diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/Makefile | 2 | ||||
| -rw-r--r-- | fs/fdos/Makefile | 49 | ||||
| -rw-r--r-- | fs/fdos/dev.c | 195 | ||||
| -rw-r--r-- | fs/fdos/dos.h | 177 | ||||
| -rw-r--r-- | fs/fdos/fat.c | 145 | ||||
| -rw-r--r-- | fs/fdos/fdos.c | 175 | ||||
| -rw-r--r-- | fs/fdos/fdos.h | 117 | ||||
| -rw-r--r-- | fs/fdos/fs.c | 120 | ||||
| -rw-r--r-- | fs/fdos/subdir.c | 348 | ||||
| -rw-r--r-- | fs/fdos/vfat.c | 357 | 
10 files changed, 1684 insertions, 1 deletions
| diff --git a/fs/Makefile b/fs/Makefile index 9ed0f1e5a..ad74942d0 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -22,7 +22,7 @@  #  # -SUBDIRS	:= jffs2 +SUBDIRS	:= jffs2 fdos  .depend all:  	@for dir in $(SUBDIRS) ; do \ diff --git a/fs/fdos/Makefile b/fs/fdos/Makefile new file mode 100644 index 000000000..af0fff1c8 --- /dev/null +++ b/fs/fdos/Makefile @@ -0,0 +1,49 @@ +# +# (C) Copyright 2002 +# Stäubli Faverges - <www.staubli.com> +# Pierre AUBERT  p.aubert@staubli.com +# +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB	= libfdos.a + +AOBJS	= +COBJS	= fat.o vfat.o dev.o fdos.o fs.o subdir.o  +OBJS	= $(AOBJS) $(COBJS) + +#CPPFLAGS += + +all:	$(LIB) $(AOBJS) + +$(LIB):	.depend $(OBJS) +	$(AR) crv $@ $(OBJS) + + +######################################################################### + +.depend:	Makefile $(AOBJS:.o=.S) $(COBJS:.o=.c) +		$(CC) -M $(CFLAGS) $(AOBJS:.o=.S) $(COBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/fs/fdos/dev.c b/fs/fdos/dev.c new file mode 100644 index 000000000..f38d07dbd --- /dev/null +++ b/fs/fdos/dev.c @@ -0,0 +1,195 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> + +#include "dos.h" +#include "fdos.h" + +#if (CONFIG_COMMANDS & CFG_CMD_FDOS) + +#define NB_HEADS        2 +#define NB_TRACKS       80 +#define NB_SECTORS      18 + + +static int lastwhere; + +/*----------------------------------------------------------------------------- + * dev_open --  + *----------------------------------------------------------------------------- + */ +int dev_open (void) +{ +    lastwhere = 0; +    return (0); +} + +/*----------------------------------------------------------------------------- + * dev_read -- len and where are sectors number + *----------------------------------------------------------------------------- + */ +int dev_read (void *buffer, int where, int len) +{ +    PRINTF ("dev_read (len = %d, where = %d)\n", len, where); + +    /* Si on ne desire pas lire a la position courante, il faut un seek      */ +    if (where != lastwhere) { +        if (!fdc_fdos_seek (where)) { +            PRINTF ("seek error in dev_read"); +            lastwhere = -1; +            return (-1); +        } +    } +     +    if (!fdc_fdos_read (buffer, len)) { +        PRINTF ("read error\n"); +        lastwhere = -1; +        return (-1); +    } +    lastwhere = where + len; +    return (0); +} +/*----------------------------------------------------------------------------- + * check_dev -- verify the diskette format + *----------------------------------------------------------------------------- + */ +int check_dev (BootSector_t *boot, Fs_t *fs) +{ +    unsigned int heads, sectors, tracks; +    int BootP, Infp0, InfpX, InfTm; +    int sect_per_track; + +    /* Display Boot header                                                   */ +    PRINTF ("Jump to boot code                  0x%02x 0x%02x 0x%02x\n", +            boot -> jump [0], boot -> jump [1], boot -> jump[2]); +    PRINTF ("OEM name & version                 '%*.*s'\n", +            BANNER_LG, BANNER_LG, boot -> banner ); +    PRINTF ("Bytes per sector hopefully 512     %d\n", +            __le16_to_cpu (boot -> secsiz)); +    PRINTF ("Cluster size in sectors            %d\n", +            boot -> clsiz); +    PRINTF ("Number of reserved (boot) sectors  %d\n", +            __le16_to_cpu (boot -> nrsvsect)); +    PRINTF ("Number of FAT tables hopefully 2   %d\n", +            boot -> nfat); +    PRINTF ("Number of directory slots          %d\n", +            __le16_to_cpu (boot -> dirents)); +    PRINTF ("Total sectors on disk              %d\n", +            __le16_to_cpu (boot -> psect)); +    PRINTF ("Media descriptor=first byte of FAT %d\n", +            boot -> descr); +    PRINTF ("Sectors in FAT                     %d\n", +            __le16_to_cpu (boot -> fatlen)); +    PRINTF ("Sectors/track                      %d\n", +            __le16_to_cpu (boot -> nsect)); +    PRINTF ("Heads                              %d\n", +            __le16_to_cpu (boot -> nheads)); +    PRINTF ("number of hidden sectors           %d\n", +            __le32_to_cpu (boot -> nhs)); +    PRINTF ("big total sectors                  %d\n", +            __le32_to_cpu (boot -> bigsect)); +    PRINTF ("physical drive ?                   %d\n", +            boot -> physdrive); +    PRINTF ("reserved                           %d\n", +            boot -> reserved); +    PRINTF ("dos > 4.0 diskette                 %d\n", +            boot -> dos4); +    PRINTF ("serial number                      %d\n", +            __le32_to_cpu (boot -> serial)); +    PRINTF ("disk label                         %*.*s\n", +            LABEL_LG, LABEL_LG, boot -> label); +    PRINTF ("FAT type                           %8.8s\n", +            boot -> fat_type); +    PRINTF ("reserved by 2M                     %d\n", +            boot -> res_2m); +    PRINTF ("2M checksum (not used)             %d\n", +            boot -> CheckSum); +    PRINTF ("2MF format version                 %d\n", +            boot -> fmt_2mf); +    PRINTF ("1 if write track after format      %d\n", +            boot -> wt); +    PRINTF ("data transfer rate on track 0      %d\n", +            boot -> rate_0); +    PRINTF ("data transfer rate on track<>0     %d\n", +            boot -> rate_any); +    PRINTF ("offset to boot program             %d\n", +            __le16_to_cpu (boot -> BootP)); +    PRINTF ("T1: information for track 0        %d\n", +            __le16_to_cpu (boot -> Infp0)); +    PRINTF ("T2: information for track<>0       %d\n", +            __le16_to_cpu (boot -> InfpX)); +    PRINTF ("T3: track sectors size table       %d\n", +            __le16_to_cpu (boot -> InfTm)); +    PRINTF ("Format date                        0x%04x\n", +            __le16_to_cpu (boot -> DateF)); +    PRINTF ("Format time                        0x%04x\n", +            __le16_to_cpu (boot -> TimeF)); +     + +    /* informations are extracted from boot sector                           */ +    heads = __le16_to_cpu (boot -> nheads); +    sectors = __le16_to_cpu (boot -> nsect); +    fs -> tot_sectors = __le32_to_cpu (boot -> bigsect); +    if (__le16_to_cpu (boot -> psect) != 0) { +        fs -> tot_sectors = __le16_to_cpu (boot -> psect); +    } +     +    sect_per_track = heads * sectors; +    tracks = (fs -> tot_sectors + sect_per_track - 1) / sect_per_track; +     +    BootP = __le16_to_cpu (boot -> BootP); +    Infp0 = __le16_to_cpu (boot -> Infp0); +    InfpX = __le16_to_cpu (boot -> InfpX); +    InfTm = __le16_to_cpu (boot -> InfTm); +     +    if (boot -> dos4 == EXTENDED_BOOT && +        strncmp( boot->banner,"2M", 2 ) == 0 && +        BootP < SZ_STD_SECTOR && +        Infp0 < SZ_STD_SECTOR && +        InfpX < SZ_STD_SECTOR && +        InfTm < SZ_STD_SECTOR && +        BootP >= InfTm + 2 && +        InfTm >= InfpX && +        InfpX >= Infp0 &&  +        Infp0 >= 76 ) { + +        return (-1); +    } + +    if (heads != NB_HEADS || +        tracks != NB_TRACKS || +        sectors != NB_SECTORS || +        __le16_to_cpu (boot -> secsiz) != SZ_STD_SECTOR || +        fs -> tot_sectors == 0 || +        (fs -> tot_sectors % sectors) != 0) { +        return (-1); +    } +     +    return (0); +} + + +#endif diff --git a/fs/fdos/dos.h b/fs/fdos/dos.h new file mode 100644 index 000000000..71701c9fb --- /dev/null +++ b/fs/fdos/dos.h @@ -0,0 +1,177 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _DOS_H_ +#define _DOS_H_ + +/* Definitions for Dos diskettes                                             */ + +/* General definitions                                                       */ +#define SZ_STD_SECTOR   512             /* Standard sector size              */ +#define MDIR_SIZE	32		/* Direntry size                     */ +#define FAT_BITS        12              /* Diskette use 12 bits fat          */ + +#define MAX_PATH	128		/* Max size of the MSDOS PATH        */ +#define MAX_DIR_SECS	64		/* Taille max d'un repertoire (en    */ +                                        /* secteurs)                         */ +/* Misc. definitions                                                         */ +#define DELMARK         '\xe5' +#define EXTENDED_BOOT   (0x29) +#define MEDIA_STD       (0xf0) +#define JUMP_0_1        (0xe9) +#define JUMP_0_2        (0xeb) + +/* Boot size is 256 bytes, but we need to read almost a sector, then +   assume bootsize is 512                                                    */ +#define BOOTSIZE        512 + +/* Fat definitions for 12 bits fat                                           */ +#define FAT12_MAX_NB    4086 +#define FAT12_LAST      0x0ff6 +#define FAT12_END       0x0fff + +/* file attributes                                                           */ +#define ATTR_READONLY           0x01 +#define ATTR_HIDDEN             0x02 +#define ATTR_SYSTEM             0x04 +#define ATTR_VOLUME             0x08 +#define ATTR_DIRECTORY          0x10 +#define ATTR_ARCHIVE            0x20 +#define ATTR_VSE                0x0f + +/* Name format                                                               */ +#define EXTCASE                 0x10 +#define BASECASE                0x8 + +/* Definition of the boot sector                                             */ +#define BANNER_LG               8 +#define LABEL_LG                11 + +typedef struct bootsector +{ +    unsigned char jump [3];	/* 0  Jump to boot code                      */ +    char banner [BANNER_LG];	/* 3  OEM name & version                     */ +    unsigned short secsiz;	/* 11 Bytes per sector hopefully 512         */ +    unsigned char clsiz;	/* 13 Cluster size in sectors                */ +    unsigned short nrsvsect;	/* 14 Number of reserved (boot) sectors      */ +    unsigned char nfat;		/* 16 Number of FAT tables hopefully 2       */ +    unsigned short dirents;	/* 17 Number of directory slots              */ +    unsigned short psect;	/* 19 Total sectors on disk                  */ +    unsigned char descr;	/* 21 Media descriptor=first byte of FAT     */ +    unsigned short fatlen;	/* 22 Sectors in FAT                         */ +    unsigned short nsect;	/* 24 Sectors/track                          */ +    unsigned short nheads;	/* 26 Heads                                  */ +    unsigned int nhs;	        /* 28 number of hidden sectors               */ +    unsigned int bigsect;	/* 32 big total sectors                      */ +    unsigned char physdrive;	/* 36 physical drive ?                       */ +    unsigned char reserved;	/* 37 reserved                               */ +    unsigned char dos4;		/* 38 dos > 4.0 diskette                     */ +    unsigned int serial;        /* 39 serial number                          */ +    char label [LABEL_LG];	/* 43 disk label                             */ +    char fat_type [8];		/* 54 FAT type                               */ +    unsigned char res_2m;	/* 62 reserved by 2M                         */ +    unsigned char CheckSum;	/* 63 2M checksum (not used)                 */ +    unsigned char fmt_2mf;	/* 64 2MF format version                     */ +    unsigned char wt;		/* 65 1 if write track after format          */ +    unsigned char rate_0;	/* 66 data transfer rate on track 0          */ +    unsigned char rate_any;	/* 67 data transfer rate on track<>0         */ +    unsigned short BootP;	/* 68 offset to boot program                 */ +    unsigned short Infp0;	/* 70 T1: information for track 0            */ +    unsigned short InfpX;	/* 72 T2: information for track<>0           */ +    unsigned short InfTm;	/* 74 T3: track sectors size table           */ +    unsigned short DateF;	/* 76 Format date                            */ +    unsigned short TimeF;	/* 78 Format time                            */ +    unsigned char junk [BOOTSIZE - 80];	/* 80 remaining data                 */ +} __attribute__ ((packed)) BootSector_t; + +/* Structure d'une entree de repertoire                                      */ +typedef struct directory { +    char name [8];		/* file name                                 */ +    char ext [3];		/* file extension                            */ +    unsigned char attr;		/* attribute byte                            */ +    unsigned char Case;		/* case of short filename                    */ +    unsigned char reserved [9];	/* ??                                        */ +    unsigned char time [2];	/* time stamp                                */ +    unsigned char date [2];	/* date stamp                                */ +    unsigned short start;	/* starting cluster number                   */ +    unsigned int size;	        /* size of the file                          */ +} __attribute__ ((packed))  Directory_t; + + + +#define MAX_VFAT_SUBENTRIES 20 +#define VSE_NAMELEN 13 + +#define VSE1SIZE 5 +#define VSE2SIZE 6 +#define VSE3SIZE 2 + +#define VBUFSIZE ((MAX_VFAT_SUBENTRIES * VSE_NAMELEN) + 1) + +#define MAX_VNAMELEN (255) + +#define VSE_PRESENT 0x01 +#define VSE_LAST 0x40 +#define VSE_MASK 0x1f + +/* Flag used by vfat_lookup                                                  */ +#define DO_OPEN         1 +#define ACCEPT_PLAIN    0x20 +#define ACCEPT_DIR      0x10 +#define ACCEPT_LABEL    0x08 +#define SINGLE          2 +#define MATCH_ANY       0x40 + +struct vfat_subentry { +    unsigned char id;		        /* VSE_LAST pour la fin, VSE_MASK    */ +                                        /* pour un VSE                       */ +    char text1 [VSE1SIZE * 2];          /* Caracteres encodes sur 16 bits    */ +    unsigned char attribute;	        /* 0x0f pour les VFAT                */ +    unsigned char hash1;		/* toujours 0                        */ +    unsigned char sum;		        /* Checksum du nom court             */ +    char text2 [VSE2SIZE * 2];          /* Caracteres encodes sur 16 bits    */ +    unsigned char sector_l;             /* 0 pour les VFAT                   */ +    unsigned char sector_u;		/* 0 pour les VFAT                   */ +    char text3 [VSE3SIZE * 2];          /* Caracteres encodes sur 16 bits    */ +} __attribute__ ((packed)) ; + +struct vfat_state { +    char name [VBUFSIZE]; +    int status;             /* is now a bit map of 32 bits                   */ +    int subentries; +    unsigned char sum;      /* no need to remember the sum for each          */ +                            /*   entry, it is the same anyways               */ +} __attribute__ ((packed)) ; + +/* Conversion macros                                                         */ +#define	DOS_YEAR(dir) (((dir)->date[1] >> 1) + 1980) +#define	DOS_MONTH(dir) (((((dir)->date[1]&0x1) << 3) + ((dir)->date[0] >> 5))) +#define	DOS_DAY(dir) ((dir)->date[0] & 0x1f) +#define	DOS_HOUR(dir) ((dir)->time[1] >> 3) +#define	DOS_MINUTE(dir) (((((dir)->time[1]&0x7) << 3) + ((dir)->time[0] >> 5))) +#define	DOS_SEC(dir) (((dir)->time[0] & 0x1f) * 2) + + +#endif + diff --git a/fs/fdos/fat.c b/fs/fdos/fat.c new file mode 100644 index 000000000..42df755af --- /dev/null +++ b/fs/fdos/fat.c @@ -0,0 +1,145 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> +#include <malloc.h> + +#if (CONFIG_COMMANDS & CFG_CMD_FDOS) + +#include "dos.h" +#include "fdos.h" + + +/*----------------------------------------------------------------------------- + * fat_decode --  + *----------------------------------------------------------------------------- + */ +unsigned int fat_decode (Fs_t *fs, unsigned int num) +{ +    unsigned int start = num * 3 / 2; +    unsigned char *address = fs -> fat_buf + start; +     +    if (num < 2 || start + 1 > (fs -> fat_len * SZ_STD_SECTOR)) +        return 1; +     +    if (num & 1) +        return ((address [1] & 0xff) << 4) | ((address [0] & 0xf0 ) >> 4); +    else +        return ((address [1] & 0xf) << 8) | (address [0] & 0xff ); +} +/*----------------------------------------------------------------------------- + * check_fat --  + *----------------------------------------------------------------------------- + */ +static int check_fat (Fs_t *fs) +{ +    int i, f; + +    /* Cluster verification                                                  */ +    for (i = 3 ; i < fs -> num_clus; i++){ +        f = fat_decode (fs, i); +        if (f < FAT12_LAST && f > fs -> num_clus){ +            /* Wrong cluster number detected                                 */ +            return (-1); +        } +    } +    return (0); +} +/*----------------------------------------------------------------------------- + * read_one_fat --  + *----------------------------------------------------------------------------- + */ +static int read_one_fat (BootSector_t *boot, Fs_t *fs, int nfat) +{ +    if (dev_read (fs -> fat_buf, +                  (fs -> fat_start + nfat * fs -> fat_len), +                  fs -> fat_len) < 0) { +        return (-1); +    } + +    if (fs -> fat_buf [0] || fs -> fat_buf [1] || fs -> fat_buf [2]) { +        if ((fs -> fat_buf [0] != boot -> descr && +             (fs -> fat_buf [0] != 0xf9 || boot -> descr != MEDIA_STD)) || +            fs -> fat_buf [0] < MEDIA_STD){ +            /* Unknown Media                                                 */ +            return (-1); +        } +        if (fs -> fat_buf [1] != 0xff || fs -> fat_buf [2] != 0xff){ +            /* FAT doesn't start with good values                            */ +            return (-1); +        } +    } + +    if (fs -> num_clus >= FAT12_MAX_NB) { +        /* Too much clusters                                                 */ +        return (-1); +    } + +    return check_fat (fs); +} +/*----------------------------------------------------------------------------- + * read_fat --  + *----------------------------------------------------------------------------- + */ +int read_fat (BootSector_t *boot, Fs_t *fs) +{ +    unsigned int buflen; +    int i; + +    /* Allocate Fat Buffer                                                   */ +    buflen = fs -> fat_len * SZ_STD_SECTOR; +    if (fs -> fat_buf) { +        free (fs -> fat_buf); +    } + +    if ((fs -> fat_buf = malloc (buflen)) == NULL) { +        return (-1); +    } + +    /* Try to read each Fat                                                  */ +    for (i = 0; i< fs -> nb_fat; i++){ +        if (read_one_fat (boot, fs, i) == 0) { +            /* Fat is OK                                                     */ +            fs -> num_fat = i; +            break; +        } +    } + +    if (i == fs -> nb_fat){ +        return (-1); +    } +     +    if (fs -> fat_len > (((fs -> num_clus + 2) * +                          (FAT_BITS / 4) -1 ) / 2 / +                         SZ_STD_SECTOR + 1)) { +        return (-1); +    } +    return (0); +} + + +  + +#endif diff --git a/fs/fdos/fdos.c b/fs/fdos/fdos.c new file mode 100644 index 000000000..8963f425f --- /dev/null +++ b/fs/fdos/fdos.c @@ -0,0 +1,175 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> + +#if (CONFIG_COMMANDS & CFG_CMD_FDOS) +#include <malloc.h> +#include "dos.h" +#include "fdos.h" + + +const char *month [] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +Fs_t    fs; +File_t  file; + +/*----------------------------------------------------------------------------- + * dos_open --  + *----------------------------------------------------------------------------- + */ +int dos_open(char *name) +{ +    int lg; +    int entry; +    char *fname; +     +    /* We need to suppress the " char around the name                        */ +    if (name [0] == '"') { +        name ++; +    } +    lg = strlen (name); +    if (name [lg - 1] == '"') { +        name [lg - 1] = '\0'; +    } + +    /* Open file system                                                      */ +    if (fs_init (&fs) < 0) { +        return -1; +    } + +    /* Init the file descriptor                                              */ +    file.name = name; +    file.fs = &fs; +     +    /* find the subdirectory containing the file                             */ +    if (open_subdir (&file) < 0) { +        return (-1); +    } + +    fname = basename (name); + +    /* if we try to open root directory                                      */ +    if (*fname == '\0') { +        file.file = file.subdir; +        return (0); +    } +     +    /* find the file in the subdir                                           */ +    entry = 0; +    if (vfat_lookup (&file.subdir, +                     file.fs, +                     &file.file.dir, +                     &entry, +                     0, +                     fname, +                     ACCEPT_DIR | ACCEPT_PLAIN | SINGLE | DO_OPEN, +                     0, +                     &file.file) != 0) { +        /* File not found                                                    */ +        printf ("File not found\n"); +        return (-1); +    } + +    return 0; +} + +/*----------------------------------------------------------------------------- + * dos_read --  + *----------------------------------------------------------------------------- + */ +int dos_read (ulong addr) +{ +    int read = 0, nb; + +    /* Try to boot a directory ?                                             */ +    if (file.file.dir.attr & (ATTR_DIRECTORY | ATTR_VOLUME)) { +        printf ("Unable to boot %s !!\n", file.name); +        return (-1); +    } +    while (read < file.file.FileSize) { +        PRINTF ("read_file (%ld)\n", (file.file.FileSize - read)); +        nb = read_file (&fs, +                        &file.file, +                        (char *)addr + read, +                        read, +                        (file.file.FileSize - read)); +        PRINTF ("read_file -> %d\n", nb); +        if (nb < 0) { +            printf ("read error\n"); +            return (-1); +        } +        read += nb; +    } +    return (read); +} +/*----------------------------------------------------------------------------- + * dos_dir --  + *----------------------------------------------------------------------------- + */ +int dos_dir (void) +{ +    int entry; +    Directory_t dir; +    char *name; +     +     +    if ((file.file.dir.attr & ATTR_DIRECTORY) == 0) { +        printf ("%s: not a directory !!\n", file.name); +        return (1); +    } +    entry = 0; +    if ((name = malloc (MAX_VNAMELEN + 1)) == NULL) { +        PRINTF ("Allcation error\n"); +        return (1); +    } +     +    while (vfat_lookup (&file.file, +                        file.fs, +                        &dir, +                        &entry, +                        0, +                        NULL, +                        ACCEPT_DIR | ACCEPT_PLAIN | MATCH_ANY, +                        name, +                        NULL) == 0) { +        /* Display file info                                                 */ +        printf ("%3.3s %9d %s %02d %04d %02d:%02d:%02d %s\n", +                (dir.attr & ATTR_DIRECTORY) ? "dir" : "   ", +                __le32_to_cpu (dir.size), +                month [DOS_MONTH (&dir) - 1], +                DOS_DAY (&dir), +                DOS_YEAR (&dir), +                DOS_HOUR (&dir), +                DOS_MINUTE (&dir), +                DOS_SEC (&dir), +                name); +         +    } +    free (name); +    return (0); +} + +#endif diff --git a/fs/fdos/fdos.h b/fs/fdos/fdos.h new file mode 100644 index 000000000..18076d866 --- /dev/null +++ b/fs/fdos/fdos.h @@ -0,0 +1,117 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _FDOS_H_ +#define _FDOS_H_ + + +#undef	FDOS_DEBUG + +#ifdef	FDOS_DEBUG +#define	PRINTF(fmt,args...)	printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +/* Data structure describing media                                           */ +typedef struct fs +{ +    unsigned long       tot_sectors; + +    int                 cluster_size; +    int                 num_clus; +     +    int                 fat_start; +    int                 fat_len; +    int                 nb_fat; +    int                 num_fat; +     +    int                 dir_start; +    int                 dir_len; + +    unsigned char       *fat_buf; +     +} Fs_t; + +/* Data structure describing one file system slot                            */ +typedef struct slot { +    int (*map) (struct fs *fs, +                struct slot *file, +                int where, +                int *len); +    unsigned long FileSize; + +    unsigned short int FirstAbsCluNr; +    unsigned short int PreviousAbsCluNr; +    unsigned short int PreviousRelCluNr; + +    Directory_t dir; +} Slot_t; + +typedef struct file { +    char                *name; +    int                 Case; +    Fs_t                *fs; +    Slot_t              subdir; +    Slot_t              file; +} File_t; + + +/* dev.c                                                                     */ +int dev_read (void *buffer, int where, int len); +int dev_open (void); +int check_dev (BootSector_t *boot, Fs_t *fs); + +/* fat.c                                                                     */ +unsigned int fat_decode (Fs_t *fs, unsigned int num); +int read_fat (BootSector_t *boot, Fs_t *fs); + +/* vfat.c                                                                    */ +int vfat_lookup (Slot_t *dir, +                 Fs_t *fs, +                 Directory_t *dirent, +                 int *entry, +                 int *vfat_start, +                 char *filename,  +                 int flags, +                 char *outname, +                 Slot_t *file); + +/* subdir.c                                                                  */ +char *basename (char *name); +int open_subdir (File_t *desc); +int open_file (Slot_t *file, Directory_t *dir); +int read_file (Fs_t *fs, +               Slot_t *file, +               char *buf, +               int where, +               int len); +void init_subdir (void); + +/* fs.c                                                                      */ +int fs_init (Fs_t *fs); + + +#endif + diff --git a/fs/fdos/fs.c b/fs/fdos/fs.c new file mode 100644 index 000000000..68bbde0e2 --- /dev/null +++ b/fs/fdos/fs.c @@ -0,0 +1,120 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> +#include <malloc.h> + +#if (CONFIG_COMMANDS & CFG_CMD_FDOS) + +#include "dos.h" +#include "fdos.h" + + +/*----------------------------------------------------------------------------- + * fill_fs -- Read info on file system  + *----------------------------------------------------------------------------- + */ +static int fill_fs (BootSector_t *boot, Fs_t *fs) +{ +     +    fs -> fat_start = __le16_to_cpu (boot -> nrsvsect); +    fs -> fat_len = __le16_to_cpu (boot -> fatlen); +    fs -> nb_fat = boot -> nfat; +     +    fs -> dir_start = fs -> fat_start + fs -> nb_fat * fs -> fat_len; +    fs -> dir_len = __le16_to_cpu (boot -> dirents) * MDIR_SIZE / SZ_STD_SECTOR; +    fs -> cluster_size = boot -> clsiz; +    fs -> num_clus = (fs -> tot_sectors - fs -> dir_start - fs -> dir_len) / fs -> cluster_size; + +    return (0); +} + +/*----------------------------------------------------------------------------- + * fs_init --  + *----------------------------------------------------------------------------- + */ +int fs_init (Fs_t *fs) +{ +    BootSector_t *boot; + +    /* Initialize physical device                                            */ +    if (dev_open () < 0) { +        PRINTF ("Unable to initialize the fdc\n"); +        return (-1); +    } +    init_subdir (); +     +    /* Allocate space for read the boot sector                               */ +    if ((boot = (BootSector_t *)malloc (sizeof (BootSector_t))) == NULL) { +        PRINTF ("Unable to allocate space for boot sector\n"); +        return (-1); +    } +     +    /* read boot sector                                                      */ +    if (dev_read (boot, 0, 1)){ +        PRINTF ("Error during boot sector read\n"); +        free (boot); +        return (-1); +    } + +    /* we verify it'a a DOS diskette                                         */ +    if (boot -> jump [0] !=  JUMP_0_1 && boot -> jump [0] !=  JUMP_0_2) { +        PRINTF ("Not a DOS diskette\n"); +        free (boot); +        return (-1); +    } + +    if (boot -> descr < MEDIA_STD) { +        /* We handle only recent medias (type F0)                            */ +        PRINTF ("unrecognized diskette type\n"); +        free (boot); +        return (-1); +    } + +    if (check_dev (boot, fs) < 0) { +        PRINTF ("Bad diskette\n"); +        free (boot); +        return (-1); +    } +     +    if (fill_fs (boot, fs) < 0) { +        free (boot); + +        return (-1); +    } + +    /* Read FAT                                                              */ +    if (read_fat (boot, fs) < 0) { +        free (boot); +        return (-1); +    } + +    free (boot); +    return (0); +} + + + +#endif diff --git a/fs/fdos/subdir.c b/fs/fdos/subdir.c new file mode 100644 index 000000000..5911f2e88 --- /dev/null +++ b/fs/fdos/subdir.c @@ -0,0 +1,348 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> +#include <malloc.h> + +#if (CONFIG_COMMANDS & CFG_CMD_FDOS) + +#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); +} +#endif diff --git a/fs/fdos/vfat.c b/fs/fdos/vfat.c new file mode 100644 index 000000000..f8287952e --- /dev/null +++ b/fs/fdos/vfat.c @@ -0,0 +1,357 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> + +#if (CONFIG_COMMANDS & CFG_CMD_FDOS) +#include <linux/ctype.h> + +#include "dos.h" +#include "fdos.h" + +static int dir_read (Fs_t *fs, +                     Slot_t *dir, +                     Directory_t *dirent, +                     int num, +                     struct vfat_state *v); + +static int unicode_read (char *in, char *out, int num); +static int match (const char *s, const char *p); +static unsigned char sum_shortname (char *name); +static int check_vfat (struct vfat_state *v, Directory_t *dir); +static char *conv_name (char *name, char *ext, char Case, char *ans); + + +/*----------------------------------------------------------------------------- + * clear_vfat --  + *----------------------------------------------------------------------------- + */ +static void clear_vfat (struct vfat_state *v) +{ +    v -> subentries = 0; +    v -> status = 0; +} + +/*----------------------------------------------------------------------------- + * vfat_lookup --  + *----------------------------------------------------------------------------- + */ +int vfat_lookup (Slot_t *dir, +                 Fs_t *fs, +                 Directory_t *dirent, +                 int *entry, +                 int *vfat_start, +                 char *filename,  +                 int flags, +                 char *outname, +                 Slot_t *file) +{ +    int found; +    struct vfat_state vfat; +    char newfile [VSE_NAMELEN]; +    int vfat_present = 0; + +    if (*entry == -1) { +        return -1; +    } + +    found = 0; +    clear_vfat (&vfat); +    while (1) { +        if (dir_read (fs, dir, dirent, *entry, &vfat) < 0) { +            if (vfat_start) { +                *vfat_start = *entry; +            } +            break; +        } +        (*entry)++; + +        /* Empty slot                                                        */ +        if (dirent -> name[0] == '\0'){ +            if (vfat_start == 0) { +                break; +            } +            continue; +        } + +        if (dirent -> attr == ATTR_VSE) { +            /* VSE entry, continue                                           */ +            continue; +        } +        if ( (dirent -> name [0] == DELMARK) || +             ((dirent -> attr & ATTR_DIRECTORY) != 0 && +              (flags & ACCEPT_DIR) == 0) || +             ((dirent -> attr & ATTR_VOLUME) != 0 && +              (flags & ACCEPT_LABEL) == 0) || +             (((dirent -> attr & (ATTR_DIRECTORY | ATTR_VOLUME)) == 0) && +              (flags & ACCEPT_PLAIN) == 0)) { +            clear_vfat (&vfat); +            continue; +        } + +        vfat_present = check_vfat (&vfat, dirent); +        if (vfat_start) { +            *vfat_start = *entry - 1; +            if (vfat_present) { +                *vfat_start -= vfat.subentries; +            } +        } + +        if (dirent -> attr & ATTR_VOLUME) { +            strncpy (newfile, dirent -> name, 8); +            newfile [8] = '\0'; +            strncat (newfile, dirent -> ext, 3); +            newfile [11] = '\0'; +        } +        else { +            conv_name (dirent -> name, dirent -> ext, dirent -> Case, newfile); +        } + +        if (flags & MATCH_ANY) { +            found = 1; +            break; +        } + +        if ((vfat_present && match (vfat.name, filename)) || +            (match (newfile, filename))) { +            found = 1; +            break; +        } +        clear_vfat (&vfat); +    } + +    if (found) { +        if ((flags & DO_OPEN) && file) { +            if (open_file (file, dirent) < 0) { +                return (-1); +            } +        } +        if (outname) { +            if (vfat_present) { +                strcpy (outname, vfat.name); +            } +            else { +                strcpy (outname, newfile); +            } +        } +        return (0);                    /* File found                         */ +    } else { +        *entry = -1; +        return -1;                      /* File not found                    */ +    } +} + +/*----------------------------------------------------------------------------- + * dir_read -- Read one directory entry + *----------------------------------------------------------------------------- + */ +static int dir_read (Fs_t *fs, +              Slot_t *dir, +              Directory_t *dirent, +              int num, +              struct vfat_state *v) +{ + +    /* read the directory entry                                              */ +    if (read_file (fs, +                   dir, +                   (char *)dirent, +                   num * MDIR_SIZE, +                   MDIR_SIZE) != MDIR_SIZE) { +        return (-1); +    } + +    if (v && (dirent -> attr == ATTR_VSE)) { +        struct vfat_subentry *vse; +        unsigned char id, last_flag; +        char *c; + +        vse = (struct vfat_subentry *) dirent; +        id = vse -> id & VSE_MASK; +        last_flag = (vse -> id & VSE_LAST); +        if (id > MAX_VFAT_SUBENTRIES) { +            /* Invalid VSE entry                                             */ +            return (-1); +        } + + +        /* Decode VSE                                                        */ +        if(v -> sum != vse -> sum) { +            clear_vfat (v); +            v -> sum = vse -> sum; +        } + +         +        v -> status |= 1 << (id - 1); +        if (last_flag) { +            v -> subentries = id; +        } + +        c = &(v -> name [VSE_NAMELEN * (id - 1)]); +        c += unicode_read (vse->text1, c, VSE1SIZE); +        c += unicode_read (vse->text2, c, VSE2SIZE); +        c += unicode_read (vse->text3, c, VSE3SIZE); +		 +        if (last_flag) { +            *c = '\0';	        /* Null terminate long name                  */ +        } +         +    } +    return (0); +} + +/*----------------------------------------------------------------------------- + * unicode_read --  + *----------------------------------------------------------------------------- + */ +static int unicode_read (char *in, char *out, int num) +{ +    int j; +     +    for (j = 0; j < num; ++j) { +        if (in [1]) +            *out = '_'; +        else +            *out = in [0]; +        out ++; +        in += 2; +    } +    return num; +} + +/*----------------------------------------------------------------------------- + * match --  + *----------------------------------------------------------------------------- + */ +static int match (const char *s, const char *p) +{ + +    for (; *p != '\0'; ) { +        if (toupper (*s) != toupper (*p)) { +            return (0); +        } +        p++; +        s++; +    } +     +    if (*s != '\0') { +        return (0); +    } +    else { +        return (1); +    } +} +/*----------------------------------------------------------------------------- + * sum_shortname --  + *----------------------------------------------------------------------------- + */ +static unsigned char sum_shortname (char *name) +{ +    unsigned char sum; +    int j; +     +    for (j = sum = 0; j < 11; ++j) { +        sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + +            (name [j] ? name [j] : ' '); +    } +    return (sum); +} +/*----------------------------------------------------------------------------- + * check_vfat --  + * Return 1 if long name is valid, 0 else + *----------------------------------------------------------------------------- + */ +static int check_vfat (struct vfat_state *v, Directory_t *dir) +{ +    char name[12]; +     +    if (v -> subentries == 0) { +        return 0; +    } +     +    strncpy (name, dir -> name, 8); +    strncpy (name + 8, dir -> ext, 3); +    name [11] = '\0'; +     +    if (v -> sum != sum_shortname (name)) { +        return 0; +    } +     +    if( (v -> status & ((1 << v -> subentries) - 1)) != +        (1 << v -> subentries) - 1) { +        return 0; +    } +    v->name [VSE_NAMELEN * v -> subentries] = 0; +     +    return 1; +} +/*----------------------------------------------------------------------------- + * conv_name --  + *----------------------------------------------------------------------------- + */ +static char *conv_name (char *name, char *ext, char Case, char *ans) +{ +    char tname [9], text [4]; +    int i; + +    i = 0; +    while (i < 8 && name [i] != ' ' && name [i] != '\0') { +        tname [i] = name [i]; +        i++; +    } +    tname [i] = '\0'; +     +    if (Case & BASECASE) { +        for (i = 0; i < 8 && tname [i]; i++) { +            tname [i] = tolower (tname [i]); +        } +    } + +    i = 0; +    while (i < 3 && ext [i] != ' ' && ext [i] != '\0') { +        text [i] = ext [i]; +        i++; +    } +    text [i] = '\0'; + +    if (Case & EXTCASE){ +        for (i = 0; i < 3 && text [i]; i++) { +            text [i] = tolower (text [i]); +        } +    } + +    if (*text) { +        strcpy (ans, tname); +        strcat (ans, "."); +        strcat (ans, text); +    } +    else { +        strcpy(ans, tname); +    } +    return (ans); +} + + +#endif |