|
@@ -1,329 +0,0 @@
|
|
|
-/*
|
|
|
- * (C) Copyright 2002
|
|
|
- * Stäubli Faverges - <www.staubli.com>
|
|
|
- * Pierre AUBERT p.aubert@staubli.com
|
|
|
- *
|
|
|
- * SPDX-License-Identifier: GPL-2.0+
|
|
|
- */
|
|
|
-
|
|
|
-#include <common.h>
|
|
|
-#include <config.h>
|
|
|
-#include <malloc.h>
|
|
|
-
|
|
|
-#include "dos.h"
|
|
|
-#include "fdos.h"
|
|
|
-
|
|
|
-static int cache_sect;
|
|
|
-static unsigned char cache [SZ_STD_SECTOR];
|
|
|
-
|
|
|
-
|
|
|
-#define min(x,y) ((x)<(y)?(x):(y))
|
|
|
-
|
|
|
-static int descend (Slot_t *parent,
|
|
|
- Fs_t *fs,
|
|
|
- char *path);
|
|
|
-
|
|
|
-/*-----------------------------------------------------------------------------
|
|
|
- * init_subdir --
|
|
|
- *-----------------------------------------------------------------------------
|
|
|
- */
|
|
|
-void init_subdir (void)
|
|
|
-{
|
|
|
- cache_sect = -1;
|
|
|
-}
|
|
|
-/*-----------------------------------------------------------------------------
|
|
|
- * basename --
|
|
|
- *-----------------------------------------------------------------------------
|
|
|
- */
|
|
|
-char *basename (char *name)
|
|
|
-{
|
|
|
- register char *cptr;
|
|
|
-
|
|
|
- if (!name || !*name) {
|
|
|
- return ("");
|
|
|
- }
|
|
|
-
|
|
|
- for (cptr= name; *cptr++; );
|
|
|
- while (--cptr >= name) {
|
|
|
- if (*cptr == '/') {
|
|
|
- return (cptr + 1);
|
|
|
- }
|
|
|
- }
|
|
|
- return(name);
|
|
|
-}
|
|
|
-/*-----------------------------------------------------------------------------
|
|
|
- * root_map --
|
|
|
- *-----------------------------------------------------------------------------
|
|
|
- */
|
|
|
-static int root_map (Fs_t *fs, Slot_t *file, int where, int *len)
|
|
|
-{
|
|
|
- *len = min (*len, fs -> dir_len * SZ_STD_SECTOR - where);
|
|
|
- if (*len < 0 ) {
|
|
|
- *len = 0;
|
|
|
- return (-1);
|
|
|
- }
|
|
|
- return fs -> dir_start * SZ_STD_SECTOR + where;
|
|
|
-}
|
|
|
-/*-----------------------------------------------------------------------------
|
|
|
- * normal_map --
|
|
|
- *-----------------------------------------------------------------------------
|
|
|
- */
|
|
|
-static int normal_map (Fs_t *fs, Slot_t *file, int where, int *len)
|
|
|
-{
|
|
|
- int offset;
|
|
|
- int NrClu;
|
|
|
- unsigned short RelCluNr;
|
|
|
- unsigned short CurCluNr;
|
|
|
- unsigned short NewCluNr;
|
|
|
- unsigned short AbsCluNr;
|
|
|
- int clus_size;
|
|
|
-
|
|
|
- clus_size = fs -> cluster_size * SZ_STD_SECTOR;
|
|
|
- offset = where % clus_size;
|
|
|
-
|
|
|
- *len = min (*len, file -> FileSize - where);
|
|
|
-
|
|
|
- if (*len < 0 ) {
|
|
|
- *len = 0;
|
|
|
- return (0);
|
|
|
- }
|
|
|
-
|
|
|
- if (file -> FirstAbsCluNr < 2){
|
|
|
- *len = 0;
|
|
|
- return (0);
|
|
|
- }
|
|
|
-
|
|
|
- RelCluNr = where / clus_size;
|
|
|
-
|
|
|
- if (RelCluNr >= file -> PreviousRelCluNr){
|
|
|
- CurCluNr = file -> PreviousRelCluNr;
|
|
|
- AbsCluNr = file -> PreviousAbsCluNr;
|
|
|
- } else {
|
|
|
- CurCluNr = 0;
|
|
|
- AbsCluNr = file -> FirstAbsCluNr;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- NrClu = (offset + *len - 1) / clus_size;
|
|
|
- while (CurCluNr <= RelCluNr + NrClu) {
|
|
|
- if (CurCluNr == RelCluNr){
|
|
|
- /* we have reached the beginning of our zone. Save
|
|
|
- * coordinates */
|
|
|
- file -> PreviousRelCluNr = RelCluNr;
|
|
|
- file -> PreviousAbsCluNr = AbsCluNr;
|
|
|
- }
|
|
|
- NewCluNr = fat_decode (fs, AbsCluNr);
|
|
|
- if (NewCluNr == 1 || NewCluNr == 0) {
|
|
|
- PRINTF("Fat problem while decoding %d %x\n",
|
|
|
- AbsCluNr, NewCluNr);
|
|
|
- return (-1);
|
|
|
- }
|
|
|
- if (CurCluNr == RelCluNr + NrClu) {
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- if (CurCluNr < RelCluNr && NewCluNr == FAT12_END) {
|
|
|
- *len = 0;
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- if (CurCluNr >= RelCluNr && NewCluNr != AbsCluNr + 1)
|
|
|
- break;
|
|
|
- CurCluNr++;
|
|
|
- AbsCluNr = NewCluNr;
|
|
|
- }
|
|
|
-
|
|
|
- *len = min (*len, (1 + CurCluNr - RelCluNr) * clus_size - offset);
|
|
|
-
|
|
|
- return (((file -> PreviousAbsCluNr - 2) * fs -> cluster_size +
|
|
|
- fs -> dir_start + fs -> dir_len) *
|
|
|
- SZ_STD_SECTOR + offset);
|
|
|
-}
|
|
|
-/*-----------------------------------------------------------------------------
|
|
|
- * open_subdir -- open the subdir containing the file
|
|
|
- *-----------------------------------------------------------------------------
|
|
|
- */
|
|
|
-int open_subdir (File_t *desc)
|
|
|
-{
|
|
|
- char *pathname;
|
|
|
- char *tmp, *s, *path;
|
|
|
- char terminator;
|
|
|
-
|
|
|
- if ((pathname = (char *)malloc (MAX_PATH)) == NULL) {
|
|
|
- return (-1);
|
|
|
- }
|
|
|
-
|
|
|
- strcpy (pathname, desc -> name);
|
|
|
-
|
|
|
- /* Suppress file name */
|
|
|
- tmp = basename (pathname);
|
|
|
- *tmp = '\0';
|
|
|
-
|
|
|
- /* root directory init */
|
|
|
- desc -> subdir.FirstAbsCluNr = 0;
|
|
|
- desc -> subdir.FileSize = -1;
|
|
|
- desc -> subdir.map = root_map;
|
|
|
- desc -> subdir.dir.attr = ATTR_DIRECTORY;
|
|
|
-
|
|
|
- tmp = pathname;
|
|
|
- for (s = tmp; ; ++s) {
|
|
|
- if (*s == '/' || *s == '\0') {
|
|
|
- path = tmp;
|
|
|
- terminator = *s;
|
|
|
- *s = '\0';
|
|
|
- if (s != tmp && strcmp (path,".")) {
|
|
|
- if (descend (&desc -> subdir, desc -> fs, path) < 0) {
|
|
|
- free (pathname);
|
|
|
- return (-1);
|
|
|
- }
|
|
|
- }
|
|
|
- if (terminator == 0) {
|
|
|
- break;
|
|
|
- }
|
|
|
- tmp = s + 1;
|
|
|
- }
|
|
|
- }
|
|
|
- free (pathname);
|
|
|
- return (0);
|
|
|
-}
|
|
|
-/*-----------------------------------------------------------------------------
|
|
|
- * descend --
|
|
|
- *-----------------------------------------------------------------------------
|
|
|
- */
|
|
|
-static int descend (Slot_t *parent,
|
|
|
- Fs_t *fs,
|
|
|
- char *path)
|
|
|
-{
|
|
|
- int entry;
|
|
|
- Slot_t SubDir;
|
|
|
-
|
|
|
- if(path[0] == '\0' || strcmp (path, ".") == 0) {
|
|
|
- return (0);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- entry = 0;
|
|
|
- if (vfat_lookup (parent,
|
|
|
- fs,
|
|
|
- &(SubDir.dir),
|
|
|
- &entry,
|
|
|
- 0,
|
|
|
- path,
|
|
|
- ACCEPT_DIR | SINGLE | DO_OPEN,
|
|
|
- 0,
|
|
|
- &SubDir) == 0) {
|
|
|
- *parent = SubDir;
|
|
|
- return (0);
|
|
|
- }
|
|
|
-
|
|
|
- if (strcmp(path, "..") == 0) {
|
|
|
- parent -> FileSize = -1;
|
|
|
- parent -> FirstAbsCluNr = 0;
|
|
|
- parent -> map = root_map;
|
|
|
- return (0);
|
|
|
- }
|
|
|
- return (-1);
|
|
|
-}
|
|
|
-/*-----------------------------------------------------------------------------
|
|
|
- * open_file --
|
|
|
- *-----------------------------------------------------------------------------
|
|
|
- */
|
|
|
-int open_file (Slot_t *file, Directory_t *dir)
|
|
|
-{
|
|
|
- int first;
|
|
|
- unsigned long size;
|
|
|
-
|
|
|
- first = __le16_to_cpu (dir -> start);
|
|
|
-
|
|
|
- if(first == 0 &&
|
|
|
- (dir -> attr & ATTR_DIRECTORY) != 0) {
|
|
|
- file -> FirstAbsCluNr = 0;
|
|
|
- file -> FileSize = -1;
|
|
|
- file -> map = root_map;
|
|
|
- return (0);
|
|
|
- }
|
|
|
-
|
|
|
- if ((dir -> attr & ATTR_DIRECTORY) != 0) {
|
|
|
- size = (1UL << 31) - 1;
|
|
|
- }
|
|
|
- else {
|
|
|
- size = __le32_to_cpu (dir -> size);
|
|
|
- }
|
|
|
-
|
|
|
- file -> map = normal_map;
|
|
|
- file -> FirstAbsCluNr = first;
|
|
|
- file -> PreviousRelCluNr = 0xffff;
|
|
|
- file -> FileSize = size;
|
|
|
- return (0);
|
|
|
-}
|
|
|
-/*-----------------------------------------------------------------------------
|
|
|
- * read_file --
|
|
|
- *-----------------------------------------------------------------------------
|
|
|
- */
|
|
|
-int read_file (Fs_t *fs,
|
|
|
- Slot_t *file,
|
|
|
- char *buf,
|
|
|
- int where,
|
|
|
- int len)
|
|
|
-{
|
|
|
- int pos;
|
|
|
- int read, nb, sect, offset;
|
|
|
-
|
|
|
- pos = file -> map (fs, file, where, &len);
|
|
|
- if (pos < 0) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- if (len == 0) {
|
|
|
- return (0);
|
|
|
- }
|
|
|
-
|
|
|
- /* Compute sector number */
|
|
|
- sect = pos / SZ_STD_SECTOR;
|
|
|
- offset = pos % SZ_STD_SECTOR;
|
|
|
- read = 0;
|
|
|
-
|
|
|
- if (offset) {
|
|
|
- /* Read doesn't start at the sector beginning. We need to use our */
|
|
|
- /* cache */
|
|
|
- if (sect != cache_sect) {
|
|
|
- if (dev_read (cache, sect, 1) < 0) {
|
|
|
- return (-1);
|
|
|
- }
|
|
|
- cache_sect = sect;
|
|
|
- }
|
|
|
- nb = min (len, SZ_STD_SECTOR - offset);
|
|
|
-
|
|
|
- memcpy (buf, cache + offset, nb);
|
|
|
- read += nb;
|
|
|
- len -= nb;
|
|
|
- sect += 1;
|
|
|
- }
|
|
|
-
|
|
|
- if (len > SZ_STD_SECTOR) {
|
|
|
- nb = (len - 1) / SZ_STD_SECTOR;
|
|
|
- if (dev_read (buf + read, sect, nb) < 0) {
|
|
|
- return ((read) ? read : -1);
|
|
|
- }
|
|
|
- /* update sector position */
|
|
|
- sect += nb;
|
|
|
-
|
|
|
- /* Update byte position */
|
|
|
- nb *= SZ_STD_SECTOR;
|
|
|
- read += nb;
|
|
|
- len -= nb;
|
|
|
- }
|
|
|
-
|
|
|
- if (len) {
|
|
|
- if (sect != cache_sect) {
|
|
|
- if (dev_read (cache, sect, 1) < 0) {
|
|
|
- return ((read) ? read : -1);
|
|
|
- cache_sect = -1;
|
|
|
- }
|
|
|
- cache_sect = sect;
|
|
|
- }
|
|
|
-
|
|
|
- memcpy (buf + read, cache, len);
|
|
|
- read += len;
|
|
|
- }
|
|
|
- return (read);
|
|
|
-}
|