vfat.c

Go to the documentation of this file.
00001 /* vfat.c
00002  *
00003  * Miscellaneous VFAT-related functions
00004  */
00005 
00006 #include "sysincludes.h"
00007 #include "msdos.h"
00008 #include "mtools.h"
00009 #include "vfat.h"
00010 #include "file.h"
00011 #include "dirCache.h"
00012 
00013 /* #define DEBUG */
00014 
00015 const char *short_illegals=";+=[]',\"*\\<>/?:|";
00016 const char *long_illegals = "\"*\\<>/?:|\005";
00017 
00018 /* Automatically derive a new name */
00019 static void autorename(char *name,
00020                        char tilda, char dot, const char *illegals,
00021                        int limit, int bump)
00022 {
00023         int tildapos, dotpos;
00024         unsigned int seqnum=0, maxseq=0;
00025         char tmp;
00026         char *p;
00027         
00028 #ifdef DEBUG
00029         printf("In autorename for name=%s.\n", name);
00030 #endif
00031         tildapos = -1;
00032 
00033         for(p=name; *p ; p++)
00034                 if((*p < ' ' && *p != '\005') || strchr(illegals, *p)) {
00035                         *p = '_';
00036                         bump = 0;
00037                 }
00038 
00039         for(dotpos=0;
00040             name[dotpos] && dotpos < limit && name[dotpos] != dot ;
00041             dotpos++) {
00042                 if(name[dotpos] == tilda) {
00043                         tildapos = dotpos;
00044                         seqnum = 0;
00045                         maxseq = 1;
00046                 } else if (name[dotpos] >= '0' && name[dotpos] <= '9') {
00047                         seqnum = seqnum * 10 + name[dotpos] - '0';
00048                         maxseq = maxseq * 10;
00049                 } else
00050                         tildapos = -1; /* sequence number interrupted */
00051         }
00052         if(tildapos == -1) {
00053                 /* no sequence number yet */
00054                 if(dotpos > limit - 2) {
00055                         tildapos = limit - 2;
00056                         dotpos = limit;
00057                 } else {
00058                         tildapos = dotpos;
00059                         dotpos += 2;
00060                 }
00061                 seqnum = 1;
00062         } else {
00063                 if(bump)
00064                         seqnum++;
00065                 if(seqnum > 999999) {
00066                         seqnum = 1;
00067                         tildapos = dotpos - 2;
00068                         /* this matches Win95's behavior, and also guarantees
00069                          * us that the sequence numbers never get shorter */
00070                 }
00071                 if (seqnum == maxseq) {
00072                     if(dotpos >= limit)
00073                         tildapos--;
00074                     else
00075                         dotpos++;
00076                 }
00077         }
00078 
00079         tmp = name[dotpos];
00080         if((bump && seqnum == 1) || seqnum > 1 || mtools_numeric_tail)
00081                 sprintf(name+tildapos,"%c%d",tilda, seqnum);
00082         if(dot)
00083             name[dotpos]=tmp;
00084         /* replace the character if it wasn't a space */
00085 }
00086 
00087 
00088 void autorename_short(char *name, int bump)
00089 {
00090         autorename(name, '~', ' ', short_illegals, 8, bump);
00091 }
00092 
00093 void autorename_long(char *name, int bump)
00094 {
00095         autorename(name, '-', '\0', long_illegals, 255, bump);
00096 }
00097 
00098 
00099 static inline int unicode_read(struct unicode_char *in, char *out, int num)
00100 {
00101         char *end_out = out+num;
00102 
00103         while(out < end_out) {
00104                 if (in->uchar)
00105                         *out = '_';
00106                 else
00107                         *out = in->lchar;
00108                 ++out;
00109                 ++in;
00110         }
00111         return num;
00112 }
00113 
00114 
00115 void clear_vfat(struct vfat_state *v)
00116 {
00117         v->subentries = 0;
00118         v->status = 0;
00119         v->present = 0;
00120 }
00121 
00122 
00123 /* sum_shortname
00124  *
00125  * Calculate the checksum that results from the short name in *dir.
00126  *
00127  * The sum is formed by circularly right-shifting the previous sum
00128  * and adding in each character, from left to right, padding both
00129  * the name and extension to maximum length with spaces and skipping
00130  * the "." (hence always summing exactly 11 characters).
00131  * 
00132  * This exact algorithm is required in order to remain compatible
00133  * with Microsoft Windows-95 and Microsoft Windows NT 3.5.
00134  * Thanks to Jeffrey Richter of Microsoft Systems Journal for
00135  * pointing me to the correct algorithm.
00136  *
00137  * David C. Niemi (niemi@tux.org) 95.01.19
00138  */
00139 static inline unsigned char sum_shortname(char *name)
00140 {
00141         unsigned char sum;
00142         char *end = name+11;
00143 
00144         for (sum=0; name<end; ++name)
00145                 sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) 
00146                   + (*name ? *name : ' ');
00147         return(sum);
00148 }
00149 
00150 /* check_vfat
00151  *
00152  * Inspect a directory and any associated VSEs.
00153  * Return 1 if the VSEs comprise a valid long file name,
00154  * 0 if not.
00155  */
00156 static inline void check_vfat(struct vfat_state *v, struct directory *dir)
00157 {
00158         char name[12];
00159 
00160         if (! v->subentries) {
00161 #ifdef DEBUG
00162                 fprintf(stderr, "check_vfat: no VSEs.\n");
00163 #endif
00164                 return;
00165         }
00166 
00167         strncpy((char *)name, (char *)dir->name, 8);
00168         strncpy((char *)name + 8, (char *)dir->ext, 3);
00169         name[11] = '\0';
00170 
00171         if (v->sum != sum_shortname(name))
00172                 return;
00173         
00174         if( (v->status & ((1<<v->subentries) - 1)) != (1<<v->subentries) - 1)
00175                 return; /* missing entries */
00176 
00177         /* zero out byte following last entry, for good measure */
00178         v->name[VSE_NAMELEN * v->subentries] = 0;
00179         v->present = 1;
00180 }
00181 
00182 
00183 int clear_vses(Stream_t *Dir, int entrySlot, size_t last)
00184 {
00185         direntry_t entry;
00186         dirCache_t *cache;
00187         int error;
00188 
00189         entry.Dir = Dir;
00190         entry.entry = entrySlot;
00191 
00192         /*maximize(last, entry.entry + MAX_VFAT_SUBENTRIES);*/
00193         cache = allocDirCache(Dir, last);
00194         if(!cache) {
00195                 fprintf(stderr, "Out of memory error in clear_vses\n");
00196                 exit(1);
00197         }
00198         addFreeEntry(cache, entry.entry, last);
00199         for (; entry.entry < last; ++entry.entry) {
00200 #ifdef DEBUG
00201                 fprintf(stderr,"Clearing entry %d.\n", entry.entry);
00202 #endif
00203                 dir_read(&entry, &error);
00204                 if(error)
00205                     return error;
00206                 if(!entry.dir.name[0] || entry.dir.name[0] == DELMARK)
00207                         break;
00208                 entry.dir.name[0] = DELMARK;
00209                 if (entry.dir.attr == 0xf)
00210                         entry.dir.attr = '\0';
00211                 low_level_dir_write(&entry);
00212         }
00213         return 0;
00214 }
00215 
00216 int write_vfat(Stream_t *Dir, char *shortname, char *longname, int start,
00217                direntry_t *mainEntry)
00218 {
00219         struct vfat_subentry *vse;
00220         int vse_id, num_vses;
00221         char *c;
00222         direntry_t entry;
00223         dirCache_t *cache;
00224         char unixyName[13];
00225         
00226         if(longname) {
00227 #ifdef DEBUG
00228                 printf("Entering write_vfat with longname=\"%s\", start=%d.\n",
00229                        longname,start);
00230 #endif
00231                 entry.Dir = Dir;
00232                 vse = (struct vfat_subentry *) &entry.dir;
00233                 /* Fill in invariant part of vse */
00234                 vse->attribute = 0x0f;
00235                 vse->hash1 = vse->sector_l = vse->sector_u = 0;
00236                 vse->sum = sum_shortname(shortname);
00237 #ifdef DEBUG
00238                 printf("Wrote checksum=%d for shortname %s.\n", 
00239                        vse->sum,shortname);
00240 #endif
00241                 num_vses = strlen(longname)/VSE_NAMELEN + 1;
00242                 for (vse_id = num_vses; vse_id; --vse_id) {
00243                         int end = 0;
00244                         
00245                         c = longname + (vse_id - 1) * VSE_NAMELEN;
00246                         
00247                         c += unicode_write(c, vse->text1, VSE1SIZE, &end);
00248                         c += unicode_write(c, vse->text2, VSE2SIZE, &end);
00249                         c += unicode_write(c, vse->text3, VSE3SIZE, &end);
00250 
00251                         vse->id = (vse_id == num_vses) ? (vse_id | VSE_LAST) : vse_id;
00252 #ifdef DEBUG
00253                         printf("Writing longname=(%s), VSE %d (%13s) at %d, end = %d.\n",
00254                                longname, vse_id, longname + (vse_id-1) * VSE_NAMELEN,
00255                                start + num_vses - vse_id, start + num_vses);
00256 #endif
00257                         
00258                         entry.entry = start + num_vses - vse_id;
00259                         low_level_dir_write(&entry);
00260                 }
00261         } else
00262                 num_vses = 0;
00263         cache = allocDirCache(Dir, start + num_vses + 1);
00264         if(!cache) {
00265                 fprintf(stderr, "Out of memory error\n");
00266                 exit(1);
00267         }
00268         unix_name(shortname, shortname+8, 0, unixyName);
00269         addUsedEntry(cache, start, start + num_vses + 1, longname, unixyName,
00270                      &mainEntry->dir);
00271         low_level_dir_write(mainEntry);
00272         return start + num_vses;
00273 }
00274 
00275 void dir_write(direntry_t *entry)
00276 {
00277         dirCacheEntry_t *dce;
00278         dirCache_t *cache;
00279 
00280         if(entry->entry == -3) {
00281                 fprintf(stderr, "Attempt to write root directory pointer\n");
00282                 exit(1);
00283         }
00284 
00285         cache = allocDirCache(entry->Dir, entry->entry + 1);
00286         if(!cache) {
00287                 fprintf(stderr, "Out of memory error in dir_write\n");
00288                 exit(1);
00289         }
00290         dce = cache->entries[entry->entry];
00291         if(dce) {
00292                 if(entry->dir.name[0] == DELMARK) {
00293                         addFreeEntry(cache, dce->beginSlot, dce->endSlot);
00294                 } else {
00295                         dce->dir = entry->dir;
00296                 }
00297         }
00298         low_level_dir_write(entry);
00299 }
00300 
00301 
00302 /* 
00303  * The following function translates a series of vfat_subentries into
00304  * data suitable for a dircache entry
00305  */
00306 static inline void parse_vses(direntry_t *entry,                              
00307                               struct vfat_state *v)
00308 {
00309         struct vfat_subentry *vse;
00310         unsigned char id, last_flag;
00311         char *c;
00312         
00313         vse = (struct vfat_subentry *) &entry->dir;
00314         
00315         id = vse->id & VSE_MASK;
00316         last_flag = (vse->id & VSE_LAST);
00317         if (id > MAX_VFAT_SUBENTRIES) {
00318                 fprintf(stderr, "parse_vses: invalid VSE ID %d at %d.\n",
00319                         id, entry->entry);
00320                 return;
00321         }
00322         
00323 /* 950819: This code enforced finding the VSEs in order.  Well, Win95
00324  * likes to write them in *reverse* order for some bizarre reason!  So
00325  * we pretty much have to tolerate them coming in any possible order.
00326  * So skip this check, we'll do without it (What does this do, Alain?).
00327  *
00328  * 950820: Totally rearranged code to tolerate any order but to warn if
00329  * they are not in reverse order like Win95 uses.
00330  *
00331  * 950909: Tolerate any order. We recognize new chains by mismatching
00332  * checksums. In the event that the checksums match, new entries silently
00333  * overwrite old entries of the same id. This should accept all valid
00334  * entries, but may fail to reject invalid entries in some rare cases.
00335  */
00336 
00337         /* bad checksum, begin new chain */
00338         if(v->sum != vse->sum) {
00339                 clear_vfat(v);
00340                 v->sum = vse->sum;
00341         }
00342         
00343 #ifdef DEBUG
00344         if(v->status & (1 << (id-1)))
00345                 fprintf(stderr,
00346                         "parse_vses: duplicate VSE %d\n", vse->id);
00347 #endif
00348         
00349         v->status |= 1 << (id-1);
00350         if(last_flag)
00351                 v->subentries = id;
00352         
00353 #ifdef DEBUG
00354         if (id > v->subentries)
00355                 /* simple test to detect entries preceding
00356                  * the "last" entry (really the first) */
00357                 fprintf(stderr,
00358                         "parse_vses: new VSE %d sans LAST flag\n",
00359                         vse->id);
00360 #endif
00361 
00362         c = &(v->name[VSE_NAMELEN * (id-1)]);
00363         c += unicode_read(vse->text1, c, VSE1SIZE);
00364         c += unicode_read(vse->text2, c, VSE2SIZE);
00365         c += unicode_read(vse->text3, c, VSE3SIZE);
00366 #ifdef DEBUG
00367         printf("Read VSE %d at %d, subentries=%d, = (%13s).\n",
00368                id,entry->entry,v->subentries,&(v->name[VSE_NAMELEN * (id-1)]));
00369 #endif          
00370         if (last_flag)
00371                 *c = '\0';      /* Null terminate long name */
00372 }
00373 
00374 
00375 static dirCacheEntry_t *vfat_lookup_loop_common(direntry_t *direntry,
00376                                                 dirCache_t *cache,
00377                                                 int lookForFreeSpace,
00378                                                 int *io_error)
00379 {
00380         char newfile[13];
00381         int initpos = direntry->entry + 1;
00382         struct vfat_state vfat;
00383         char *longname;
00384         int error;
00385 
00386         /* not yet cached */
00387         *io_error = 0;
00388         clear_vfat(&vfat);
00389         while(1) {
00390                 ++direntry->entry;
00391                 if(!dir_read(direntry, &error)){
00392                         if(error) {
00393                             *io_error = error;
00394                             return NULL;
00395                         }
00396                         addFreeEntry(cache, initpos, direntry->entry);
00397                         return addEndEntry(cache, direntry->entry);
00398                 }
00399                 
00400                 if (direntry->dir.name[0] == '\0'){
00401                                 /* the end of the directory */
00402                         if(lookForFreeSpace)
00403                                 continue;
00404                         return addEndEntry(cache, direntry->entry);
00405                 }
00406                 if(direntry->dir.name[0] != DELMARK &&
00407                    direntry->dir.attr == 0x0f)
00408                         parse_vses(direntry, &vfat);
00409                 else
00410                         /* the main entry */
00411                         break;
00412         }
00413         
00414         /* If we get here, it's a short name FAT entry, maybe erased.
00415          * thus we should make sure that the vfat structure will be
00416          * cleared before the next loop run */
00417         
00418         /* deleted file */
00419         if (direntry->dir.name[0] == DELMARK) {
00420                 return addFreeEntry(cache, initpos, 
00421                                     direntry->entry + 1);
00422         }
00423         
00424         check_vfat(&vfat, &direntry->dir);
00425         if(!vfat.present)
00426                 vfat.subentries = 0;
00427         
00428         /* mark space between last entry and this one as free */
00429         addFreeEntry(cache, initpos, 
00430                      direntry->entry - vfat.subentries);
00431         
00432         if (direntry->dir.attr & 0x8){
00433                 strncpy(newfile, direntry->dir.name,8);
00434                 newfile[8]='\0';
00435                 strncat(newfile, direntry->dir.ext,3);
00436                 newfile[11]='\0';
00437         } else
00438                 unix_name(direntry->dir.name, 
00439                           direntry->dir.ext, 
00440                           direntry->dir.Case, 
00441                           newfile);
00442 
00443         if(vfat.present)
00444                 longname = vfat.name;
00445         else
00446                 longname = 0;
00447 
00448         return addUsedEntry(cache, direntry->entry - vfat.subentries,
00449                             direntry->entry + 1, longname, 
00450                             newfile, &direntry->dir);
00451 }
00452 
00453 static inline dirCacheEntry_t *vfat_lookup_loop_for_read(direntry_t *direntry,
00454                                                          dirCache_t *cache,
00455                                                          int *io_error)
00456 {
00457         int initpos = direntry->entry + 1;
00458         dirCacheEntry_t *dce;
00459 
00460         *io_error = 0;
00461         dce = cache->entries[initpos];
00462         if(dce) {
00463                 direntry->entry = dce->endSlot - 1;
00464                 return dce;
00465         } else {
00466                 return vfat_lookup_loop_common(direntry, cache, 0, io_error);
00467         }
00468 }
00469 
00470 
00471 typedef enum result_t {
00472         RES_NOMATCH,
00473         RES_MATCH,
00474         RES_END,
00475         RES_ERROR
00476 } result_t;
00477 
00478 
00479 /* 
00480  * 0 does not match
00481  * 1 matches
00482  * 2 end
00483  */
00484 static result_t checkNameForMatch(struct direntry_t *direntry, 
00485                                   dirCacheEntry_t *dce,
00486                                   const char *filename,
00487                                   char *longname,
00488                                   char *shortname,
00489                                   int length,
00490                                   int flags)
00491 {
00492         switch(dce->type) {
00493                 case DCET_FREE:
00494                         return RES_NOMATCH;
00495                 case DCET_END:
00496                         return RES_END;
00497                 case DCET_USED:
00498                         break;
00499                 default:
00500                         fprintf(stderr, "Unexpected entry type %d\n",
00501                                 dce->type);
00502                         return RES_ERROR;
00503         }
00504 
00505         direntry->dir = dce->dir;
00506 
00507         /* make sure the entry is of an accepted type */
00508         if((direntry->dir.attr & 0x8) && !(flags & ACCEPT_LABEL))
00509                 return RES_NOMATCH;
00510 
00511 
00512         /*---------- multiple files ----------*/
00513         if(!((flags & MATCH_ANY) ||
00514              (dce->longName && 
00515               match(dce->longName, filename, direntry->name, 0, length)) ||
00516              match(dce->shortName, filename, direntry->name, 1, length))) {
00517 
00518                 return RES_NOMATCH;
00519         }
00520 
00521         /* entry of non-requested type, has to come after name
00522          * checking because of clash handling */
00523         if(IS_DIR(direntry) && !(flags & ACCEPT_DIR)) {
00524                 if(!(flags & (ACCEPT_LABEL|MATCH_ANY|NO_MSG)))
00525                         fprintf(stderr,
00526                                 "Skipping \"%s\", is a directory\n",
00527                                 dce->shortName);
00528                 return RES_NOMATCH;
00529         }
00530 
00531         if(!(direntry->dir.attr & (ATTR_LABEL | ATTR_DIR)) && 
00532            !(flags & ACCEPT_PLAIN)) {
00533                 if(!(flags & (ACCEPT_LABEL|MATCH_ANY|NO_MSG)))
00534                         fprintf(stderr,
00535                                 "Skipping \"%s\", is not a directory\n",
00536                                 dce->shortName);
00537                 return RES_NOMATCH;
00538         }
00539 
00540         return RES_MATCH;
00541 }
00542 
00543 
00544 /*
00545  * vfat_lookup looks for filenames in directory dir.
00546  * if a name if found, it is returned in outname
00547  * if applicable, the file is opened and its stream is returned in File
00548  */
00549 
00550 int vfat_lookup(direntry_t *direntry, const char *filename, int length,
00551                 int flags, char *shortname, char *longname)
00552 {
00553         dirCacheEntry_t *dce;
00554         result_t result;
00555         dirCache_t *cache;
00556         int io_error;
00557 
00558         if(length == -1 && filename)
00559                 length = strlen(filename);
00560 
00561         if (direntry->entry == -2)
00562                 return -1;
00563 
00564         cache = allocDirCache(direntry->Dir, direntry->entry+1);
00565         if(!cache) {
00566                 fprintf(stderr, "Out of memory error in vfat_lookup [0]\n");
00567                 exit(1);
00568         }
00569 
00570         do {
00571                 dce = vfat_lookup_loop_for_read(direntry, cache, &io_error);
00572                 if(!dce) {
00573                         if (io_error)
00574                                 return -2;
00575                         fprintf(stderr, "Out of memory error in vfat_lookup\n");
00576                         exit(1);
00577                 }
00578                 result = checkNameForMatch(direntry, dce,
00579                                            filename, 
00580                                            longname, shortname,
00581                                            length, flags);
00582         } while(result == RES_NOMATCH);
00583 
00584         if(result == RES_MATCH){
00585                 if(longname){
00586                         if(dce->longName)
00587                                 strcpy(longname, dce->longName);
00588                         else
00589                                 *longname ='\0';
00590                 }
00591                 if(shortname)
00592                         strcpy(shortname, dce->shortName);
00593                 direntry->beginSlot = dce->beginSlot;
00594                 direntry->endSlot = dce->endSlot-1;
00595                 return 0; /* file found */
00596         } else {
00597                 direntry->entry = -2;
00598                 return -1; /* no file found */
00599         }
00600 }
00601 
00602 static inline dirCacheEntry_t *vfat_lookup_loop_for_insert(direntry_t *direntry,
00603                                                            int initpos,
00604                                                            dirCache_t *cache)
00605 {
00606         dirCacheEntry_t *dce;
00607         int io_error;
00608 
00609         dce = cache->entries[initpos];
00610         if(dce && dce->type != DCET_END) {
00611                 return dce;
00612         } else {
00613                 direntry->entry = initpos - 1;
00614                 dce = vfat_lookup_loop_common(direntry, cache, 1, &io_error);
00615                 if(!dce) {
00616                         if (io_error) {
00617                                 return NULL;
00618                         }
00619                         fprintf(stderr, 
00620                                 "Out of memory error in vfat_lookup_loop\n");
00621                         exit(1);
00622                 }
00623                 return cache->entries[initpos];
00624         }
00625 }
00626 
00627 static void accountFreeSlots(struct scan_state *ssp, dirCacheEntry_t *dce)
00628 {
00629         if(ssp->got_slots)
00630                 return;
00631 
00632         if(ssp->free_end != dce->beginSlot) {
00633                 ssp->free_start = dce->beginSlot;
00634         }
00635         ssp->free_end = dce->endSlot;
00636 
00637         if(ssp->free_end - ssp->free_start >= ssp->size_needed) {
00638                 ssp->got_slots = 1;
00639                 ssp->slot = ssp->free_start + ssp->size_needed - 1;
00640         }
00641 }
00642 
00643 /* lookup_for_insert replaces the old scandir function.  It directly
00644  * calls into vfat_lookup_loop, thus eliminating the overhead of the
00645  * normal vfat_lookup
00646  */
00647 int lookupForInsert(Stream_t *Dir,
00648                                         char *dosname,
00649                                         char *longname,
00650                                         struct scan_state *ssp, 
00651                                         int ignore_entry,
00652                                         int source_entry,
00653                                         int pessimisticShortRename)
00654 {
00655         direntry_t entry;
00656         int ignore_match;
00657         dirCacheEntry_t *dce;
00658         dirCache_t *cache;
00659         int pos; /* position _before_ the next answered entry */
00660         char shortName[13];
00661 
00662         ignore_match = (ignore_entry == -2 );
00663 
00664         initializeDirentry(&entry, Dir);
00665         ssp->match_free = 0;
00666 
00667         /* hash bitmap of already encountered names.  Speeds up batch appends
00668          * to huge directories, because in the best case, we only need to scan
00669          * the new entries rather than the whole directory */
00670         cache = allocDirCache(Dir, 1);
00671         if(!cache) {
00672                 fprintf(stderr, "Out of memory error in lookupForInsert\n");
00673                 exit(1);
00674         }
00675 
00676         if(!ignore_match)
00677                 unix_name(dosname, dosname + 8, 0, shortName);
00678 
00679         pos = cache->nrHashed;
00680         if(source_entry >= 0 ||
00681            (pos && isHashed(cache, longname))) {
00682                 pos = 0;
00683         } else if(pos && !ignore_match && isHashed(cache, shortName)) {
00684                 if(pessimisticShortRename) {
00685                         ssp->shortmatch = -2;
00686                         return 1;
00687                 }
00688                 pos = 0;
00689         } else if(growDirCache(cache, pos) < 0) {
00690                 fprintf(stderr, "Out of memory error in vfat_looup [0]\n");
00691                 exit(1);
00692         }
00693         do {
00694                 dce = vfat_lookup_loop_for_insert(&entry, pos, cache);
00695                 switch(dce->type) {
00696                         case DCET_FREE:
00697                                 accountFreeSlots(ssp, dce);
00698                                 break;
00699                         case DCET_USED:
00700                                 if(!(dce->dir.attr & 0x8) &&
00701                                    dce->endSlot - 1 == source_entry)
00702                                    accountFreeSlots(ssp, dce);
00703 
00704                                 /* labels never match, neither does the 
00705                                  * ignored entry */
00706                                 if( (dce->dir.attr & 0x8) ||
00707                                     (dce->endSlot - 1 == ignore_entry) )
00708                                         break;
00709 
00710                                 /* check long name */
00711                                 if((dce->longName && 
00712                                     !strcasecmp(dce->longName, longname)) ||
00713                                    (dce->shortName &&
00714                                     !strcasecmp(dce->shortName, longname))) {
00715                                         ssp->longmatch = dce->endSlot - 1;
00716                                         /* long match is a reason for
00717                                          * immediate stop */
00718                                         return 1;
00719                                 }
00720 
00721                                 /* Long name or not, always check for 
00722                                  * short name match */
00723                                 if (!ignore_match &&
00724                                     !strcasecmp(shortName, dce->shortName))
00725                                         ssp->shortmatch = dce->endSlot - 1;
00726                                 break;
00727                         case DCET_END:
00728                                 break;
00729                 }
00730                 pos = dce->endSlot;
00731         } while(dce->type != DCET_END);
00732         if (ssp->shortmatch > -1)
00733                 return 1;
00734         ssp->max_entry = dce->beginSlot;
00735         if (ssp->got_slots)
00736                 return 6;       /* Success */
00737 
00738         /* Need more room.  Can we grow the directory? */
00739         if(!isRootDir(Dir))             
00740                 return 5;       /* OK, try to grow the directory */
00741 
00742         fprintf(stderr, "No directory slots\n");
00743         return -1;
00744 }
00745 
00746 
00747 
00748 /* End vfat.c */

Generated on Fri Apr 14 22:56:56 2006 for minix by  doxygen 1.4.6