Logo Search packages:      
Sourcecode: fatsort version File versions  Download package

sort.c

/*
      FATSort, utility for sorting FAT directory structures
      Copyright (C) 2004 Boris Leidner <fatsort(at)formenos.de>

      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.
*/

/*
      This file contains/describes functions for sorting of FAT filesystems.
*/

#include "sort.h"
#include "platform.h"

#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/param.h>
#include <iconv.h>
#include "entrylist.h"
#include "errors.h"
#include "options.h"
#include "endianness.h"
#include "clusterchain.h"
#include "signal.h"
#include "misc.h"
#include "fileio.h"
#include "platform.h"

// used to check if device is mounted
#if defined(__LINUX__)
#include <mntent.h>
#elif defined (__BSD__)
#include <sys/param.h>
#include <sys/ucred.h>
#include <sys/mount.h>
#endif

u_int32_t check_mounted(char *filename) {
/*
      check if filesystem is already mounted
*/

#if defined(__LINUX__)
      FILE *fd;
      struct mntent *mnt;
      u_int32_t ret = 0;
      char rp_filename[MAXPATHLEN], rp_mnt_fsname[MAXPATHLEN];
      
      if ((fd = setmntent("/etc/mtab", "r")) == NULL) {
            stderror();
            return -1;
      }

      // get real path
      if (realpath(filename, rp_filename) == NULL) {
            myerror("Unable to get realpath of filename!");
            return -1;
      }
      
      while ((mnt = getmntent(fd)) != NULL) {
            if (realpath(mnt->mnt_fsname, rp_mnt_fsname) != NULL) {
                  if (strcmp(rp_mnt_fsname, rp_filename) == 0) {
                        ret = 1;
                        break;
                  }
            }
      }
      
      if (endmntent(fd) != 1) {
            myerror("Closing mtab failed!");
            return -1;
      }

      return ret;

#elif defined(__BSD__)
      struct statfs *mntbuf;
      int i, mntsize;
      u_int32_t ret = 0;
      char rp_filename[MAXPATHLEN], rp_mnt_fsname[MAXPATHLEN];

      // get real path
      if (realpath(filename, rp_filename) == NULL) {
            myerror("Unable to get realpath of filename!");
            return -1;
      }

      mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);

      if (mntsize == 0) {
            stderror();
            return -1;
      }
      
      for (i = mntsize - 1; i >= 0; i--) {
            realpath(mntbuf[i].f_mntfromname, rp_mnt_fsname);
            if (strcmp(rp_mnt_fsname, rp_filename) == 0) {
                  ret = 1;
                  break;
            }
      }
      
      return ret;
#else 
      // ok, we don't know how to check this on an unknown platform
      if (!OPT_FORCE) {
            myerror("Don't know how to check if filesystem is mounted! Use option '-f' to sort nonetheless.");
            return -1;
      } else {
            return 1;
      }
#endif
}

void parseLongFilenamePart(struct sLongDirEntry *lde, char *str) {
/*
      retrieves a part of a long filename from a
      directory entry
      (thanks to M$ for this ugly hack...)
*/

      assert(lde != NULL);
      assert(str != NULL);

      iconv_t cd;
      size_t incount;
      size_t outcount;
      char *outptr = &(str[0]);
      char utf16str[28];
      char *inptr=&(utf16str[0]);
      size_t ret;

      str[0]='\0';
      
      memcpy(utf16str, (&lde->LDIR_Ord+1), 10);
      memcpy(utf16str+10, (&lde->LDIR_Ord+14), 12);
      memcpy(utf16str+22, (&lde->LDIR_Ord+28), 4);
      memset(utf16str+26, 0, 2);

      incount=26;
      outcount=MAX_PATH_LEN;

        cd = iconv_open("UTF-8", "UTF-16");

        if (cd == (iconv_t)-1) {
                myerror("iconv_open failed!");
            return;
        }

      while (incount != 0) {
                if ((ret=iconv(cd, &inptr, &incount, &outptr, &outcount)) == -1) {
                        myerror("iconv failed! %d", ret);
                  return;
                }
        }
      outptr[0]='\0';

//    we get a segfault lateron when this function is called
//    no idea yet
//    iconv_close(cd);

      return;
}

void parseShortFilename(struct sShortDirEntry *sde, char *str) {
/*
      parses the short name of a file
*/

      assert(sde != NULL);
      assert(str != NULL);

      char *s;
      strncpy(str, sde->DIR_Name, 8);
      str[8]='\0';
      s=strchr(str, ' ');
      if (s!=NULL) s[0]='\0';
      if ((char)(*(sde->DIR_Name+8)) != ' ') {
            strcat(str, ".");
            strncat(str, sde->DIR_Name+8, 3);
            str[12]='\0';
      }
}

int32_t parseClusterChain(FILE *fd, struct sBootSector *bs, struct sClusterChain *chain, struct sDirEntryList *list, u_int32_t *direntries) {
/*
      parses a cluster chain and puts found directory entries to list
*/

      assert(fd != NULL);
      assert(bs != NULL);
      assert(chain != NULL);
      assert(list != NULL);
      assert(direntries != NULL);

      int32_t j, ret;
      u_int32_t maxEntries, entries=0;
      union sDirEntry de;
      struct sDirEntryList *lnde;
      struct sLongDirEntryList *llist;
      char tmp[MAX_PATH_LEN+1], dummy[MAX_PATH_LEN+1], sname[MAX_PATH_LEN+1], lname[MAX_PATH_LEN+1];

      *direntries=0;
      
      maxEntries = bs->BS_SecPerClus * SwapInt16(bs->BS_BytesPerSec) / DIR_ENTRY_SIZE;

      chain=chain->next;      // head element

      llist = NULL;
      lname[0]='\0';
      while (chain != NULL) {
            fs_seek(fd, getClusterOffset(bs, chain->cluster), SEEK_SET);
            for (j=1;j<=maxEntries;j++) {
                  entries++;
                  ret=parseEntry(fd, &de);
                  if (ret == -1) {
                        myerror("Failed to parse directory entry!");
                        return -1;
                  } else if (ret == 0) {
                        //break;
                        return 0;
                  } else if (ret == 2) {
                        parseLongFilenamePart(&de.LongDirEntry, tmp);
                        
                        // insert long dir entry in list
                        llist=insertLongDirEntryList(&de.LongDirEntry, llist);
                        if (llist == NULL) {
                              myerror("Failed to insert LongDirEntry!");
                              return -1;
                        }

                        strncpy(dummy, tmp, MAX_PATH_LEN);
                        dummy[MAX_PATH_LEN]='\0';
                        strncat(dummy, lname, MAX_PATH_LEN - strlen(dummy));
                        dummy[MAX_PATH_LEN]='\0';
                        strncpy(lname, dummy, MAX_PATH_LEN);
                        dummy[MAX_PATH_LEN]='\0';
                  } else {
                        parseShortFilename(&de.ShortDirEntry, sname);
                        if (OPT_LIST && strcmp(sname, ".") &&
                           strcmp(sname, "..") &&
                           (sname[0] != DE_FREE) &&
                          !(de.ShortDirEntry.DIR_Atrr & ATTR_VOLUME_ID)) {
                              printf("%s\n", (lname[0] != '\0') ? lname : sname);
                        }

                        lnde=newDirEntry(sname, lname, &de.ShortDirEntry, llist, entries);
                        if (lnde == NULL) {
                              myerror("Failed to create DirEntry!");
                              return -1;
                        }

                        insertDirEntryList(lnde, list);
                        (*direntries)++;
                        entries=0;
                        llist = NULL;
                        lname[0]='\0';
                  }
            }
            chain=chain->next;
      }

      return 0;
}

int32_t parseDirEntry(FILE *fd, struct sDirEntryList *list, u_int32_t *entries) {
/*
      parses an entry of a directory structure
*/

      assert(fd != NULL);
      assert(list != NULL);
      assert(entries != NULL);

      char sname[MAX_PATH_LEN+1], lname[MAX_PATH_LEN+1], tmp[MAX_PATH_LEN+1], dummy[MAX_PATH_LEN+1];
      union sDirEntry de;
      struct sDirEntryList *lnde;
      u_int32_t count=0;

      struct sLongDirEntryList *llist = NULL;

      // read a directory entry from file
      if ((fs_read(&de, DIR_ENTRY_SIZE, 1, fd)<1)) {
            myerror("Failed to read from file!");
            return -1;
      }

      // if directory entry is empty, return
      if (de.LongDirEntry.LDIR_Ord == 0) {
            return 1;
      }

      lname[0]='\0';
      *entries=0;
      while (((de.LongDirEntry.LDIR_Attr & ATTR_LONG_NAME_MASK) == ATTR_LONG_NAME) ){

            parseLongFilenamePart(&de.LongDirEntry, tmp);

            // insert long dir entry in list
            llist=insertLongDirEntryList(&de.LongDirEntry, llist);
            if (llist == NULL) {
                  myerror("Failed to insert LongDirEntry!");
                  return -1;
            }

            count++;
            (*entries)++;
            strncpy(dummy, tmp, MAX_PATH_LEN);
            dummy[MAX_PATH_LEN]='\0';
            strncat(dummy, lname, MAX_PATH_LEN - strlen(dummy));
            dummy[MAX_PATH_LEN]='\0';
            strncpy(lname, dummy, MAX_PATH_LEN);
            dummy[MAX_PATH_LEN]='\0';
            if (fs_read(&de, DIR_ENTRY_SIZE, 1, fd)<1) {
                  myerror("Failed to read from file!");
                  return -1;
            }
      }
      
      /* short-filename directory entry appears after long-filename directory entries
         well, i should check such things in some future version */
      parseShortFilename(&de.ShortDirEntry, sname);
      (*entries)++;


      lnde = newDirEntry(sname, lname, &de.ShortDirEntry, llist, *entries);
      if (lnde == NULL) {
            myerror("Failed to create DirEntry!");
            return -1;
      }
      insertDirEntryList(lnde, list);

      if (OPT_LIST && strcmp(sname, ".") && strcmp (sname, "..") && (sname[0] != DE_FREE) && !(de.ShortDirEntry.DIR_Atrr & ATTR_VOLUME_ID)) {
            printf("%s\n", (lname[0] != '\0') ? lname : sname);
      }


      return 0;

}

int32_t writeList(FILE *fd, struct sDirEntryList *list) {
/*
      writes directory entries to file
*/

      assert(fd != NULL);
      assert(list != NULL);

      struct sLongDirEntryList *tmp;

      // no signal handling while writing (atomic action)
      start_critical_section();

      while(list->next!=NULL) {
            tmp=list->next->ldel;
            while(tmp != NULL) {
                  if (fs_write(tmp->lde, DIR_ENTRY_SIZE, 1, fd)<1) {
                        stderror();
                        return -1;
                  }
                  tmp=tmp->next;
            }
            if (fs_write(list->next->sde, DIR_ENTRY_SIZE, 1, fd)<1) {
                  stderror();
                  return -1;
            }
            list=list->next;
      }

      // end of critical section
      end_critical_section();

      return 0;
}

int32_t getClusterChain(FILE *fd, struct sBootSector *bs, u_int32_t startCluster, struct sClusterChain *chain) {
/*
      retrieves an array of all clusters in a cluster chain
      starting with startCluster
*/

      assert(fd != NULL);
      assert(bs != NULL);
      assert(chain != NULL);

      u_int32_t cluster;
      u_int32_t data,i=0;
      int32_t FATType;

      cluster=startCluster;

      FATType=getFATType(bs);

      if (FATType == FATTYPE_FAT12) {
            myerror("FAT12 is not supported!");
            return -1;
      } else if (FATType == FATTYPE_FAT16) {
            do {
                  if (i == MAX_CHAIN_LENGTH) {
                        myerror("Cluster chain is too long!");
                        return -1;
                  }
                  if (insertCluster(chain, cluster) == -1) {
                        myerror("Failed to insert cluster!");
                        return -1;
                  }
                  i++;
                  if (getFATEntry(fd, bs, cluster, &data)) {
                        myerror("Failed to get FAT entry!");
                        return -1;
                  }
                  cluster=data;
            } while (cluster < 0xfff8);   // end of cluster
      } else if (FATType == FATTYPE_FAT32){
            do {
                  if (i == MAX_CHAIN_LENGTH) {
                        myerror("Cluster chain is too long!");
                        return -1;
                  }
                  if (insertCluster(chain, cluster) == -1) {
                        myerror("Failed to insert cluster!");
                        return -1;
                  }
                  i++;
                  if (getFATEntry(fd, bs, cluster, &data)) {
                        myerror("Failed to get FAT entry");
                        return -1;
                  }
                  cluster=data;
            } while (((cluster & 0x0fffffff) != 0x0ff8fff8) &&
                   ((cluster & 0x0fffffff) < 0x0ffffff8));  // end of cluster
      } else {
            myerror("Failed to get FAT type!");
            return -1;
      }

      return i;
}

int32_t writeClusterChain(FILE *fd, struct sBootSector *bs, struct sDirEntryList *list, struct sClusterChain *chain) {
/*
      writes all entries from list to the cluster chain
*/

      assert(fd != NULL);
      assert(bs != NULL);
      assert(list != NULL);
      assert(chain != NULL);

      int32_t i=0, entries=0;
      u_int32_t MaxEntries;
      struct sLongDirEntryList *tmp;
      struct sDirEntryList *p=list->next;
      char empty[DIR_ENTRY_SIZE]={0};

      chain=chain->next;      // we don't need to look at the head element

      MaxEntries = bs->BS_SecPerClus * SwapInt16(bs->BS_BytesPerSec) / DIR_ENTRY_SIZE;
      if (fs_seek(fd, getClusterOffset(bs, chain->cluster), SEEK_SET)==-1) {
            myerror("Seek error!");
            return -1;
      }

      // no signal handling while writing (atomic action)
      start_critical_section();

      while(p != NULL) {
            if (entries+p->entries <= MaxEntries) {
                  tmp=p->ldel;
                  for (i=1;i<p->entries;i++) {
                        if (fs_write(tmp->lde, DIR_ENTRY_SIZE, 1, fd)<1) {
                              stderror();
                              return -1;
                        }
                        tmp=tmp->next;
                  }
                  if (fs_write(p->sde, DIR_ENTRY_SIZE, 1, fd)<1) {
                        stderror();
                        return -1;
                  }
                  entries+=p->entries;
            } else {
                  tmp=p->ldel;
                  for (i=1;i<=MaxEntries-entries;i++) {
                        if (fs_write(tmp->lde, DIR_ENTRY_SIZE, 1, fd)<1) {
                              stderror();
                              return -1;
                        }
                        tmp=tmp->next;
                  }
                  chain=chain->next; entries=p->entries - (MaxEntries - entries);   // next cluster
                  if (fs_seek(fd, getClusterOffset(bs, chain->cluster), SEEK_SET)==-1) {
                        myerror("Seek error!");
                        return -1;
                  }
                  while(tmp!=NULL) {
                        if (fs_write(tmp->lde, DIR_ENTRY_SIZE, 1, fd)<1) {
                              stderror();
                              return -1;
                        }
                        tmp=tmp->next;
                  }
                  if (fs_write(p->sde, DIR_ENTRY_SIZE, 1, fd)<1) {
                        stderror();
                        return -1;
                  }
            }
            p=p->next;
      }
      if (entries < MaxEntries) {
            if (fs_write(empty, DIR_ENTRY_SIZE, 1, fd)<1) {
                  stderror();
                  return -1;
            }
      }

      // end of critical section
      end_critical_section();

      return 0;

}

int32_t sort_fs(char *filename) {
/*
      sort FAT file system
*/

      assert(filename != NULL);

      FILE *fd;
      u_int32_t rfd=0;

      struct sBootSector bs;

      int32_t FATType;
      int32_t ret;

      if (OPT_FORCE) {
            if ((fd=fopen(filename, (OPT_LIST) ? "rb" : "r+b")) == NULL) {
                  stderror();
                  return -1;
            }
      } else {

            // this check is only done for user convenience
            // open would fail too if device is mounted, but without specific error message
            ret=check_mounted(filename);
            switch (ret) {
                  case 0: break;  // filesystem not mounted
                  case 1:           // filesystem mounted
                        myerror("Filesystem is mounted!");
                        return -1;
                  case -1:    // unable to check
                        myerror("Could not check if filesystem is mounted!");
                        return -1;
            }

            // opens the device exclusively. This is not mandatory! e.g. mkfs.vfat ignores it!
            if ((rfd=open(filename, (OPT_LIST) ? O_RDONLY | O_EXCL : O_RDWR | O_EXCL)) == -1) {
                  stderror();
                  return -1;
            }

            // connect the file descriptor to a stream
            if ((fd=fdopen(rfd, (OPT_LIST) ? "rb" : "r+b")) == NULL) {
                  stderror();
                  return -1;
            }
      }

      // read boot sector
      if (read_bootsector(fd, &bs)) {
            myerror("Failed to read boot sector!");
            return -1;
      }

      FATType = getFATType(&bs);

      if (FATType == FATTYPE_FAT12) {
            // FAT12
            // sorry, too complicated ;)
            myerror("FAT12 is not supported!");
            return -1;
      } else if (FATType == FATTYPE_FAT16) {
            // FAT16
            // root directory has fixed size and position
            infomsg("File system: FAT16.\n\n");
            if (sort_FAT16_rootdir(fd, &bs) == -1) {
                  myerror("Failed to sort FAT16 root directory!");
                  return -1;
            }
      } else if (FATType == FATTYPE_FAT32) {
            // FAT32
            // root directory lies in cluster chain,
            // so sort it like all other directories
            infomsg("File system: FAT32.\n\n");
            if (sortClusterChain(fd, &bs, SwapInt32(bs.FATxx.FAT32.BS_RootClus), "/") == -1) {
                  myerror("Failed to sort first cluster chain!");
                  return -1;
            }
      } else {
            myerror("Failed to get FAT type!");
            return -1;
      }

      fs_close(fd);
      close(rfd);

      return 0;
}

int32_t sortClusterChain(FILE *fd, struct sBootSector *bs, u_int32_t cluster, char *path) {
/*
      sorts directory entries in a cluster
*/

      assert(fd != NULL);
      assert(bs != NULL);
      assert(path != NULL);

      u_int32_t clen, value, c, direntries;
      struct sClusterChain *ClusterChain=newClusterChain();
      char newpath[MAX_PATH_LEN+1]={0};

      struct sDirEntryList *list = newDirEntryList();
      struct sDirEntryList *p;

      if ((clen=getClusterChain(fd, bs, cluster, ClusterChain)) == -1 ) {
            myerror("Failed to get cluster chain!");
            return -1;
      }

      // DEBUG
/*    struct sClusterChain *ch=&ClusterChain;
      while(ch != NULL) {
            printf("%u-", ch->cluster);
            ch=ch->next;
      }
*/
      if (!OPT_LIST) {
            // DEBUG
//          printf("%s %s\n", OPT_DIRECTORY, path);
            if (parseClusterChain(fd, bs, ClusterChain, list, &direntries) == -1) {
                  myerror("Failed to parse cluster chain!");
                  return -1;
            }
            
            if (OPT_RANDOM) randomizeDirEntryList(list, direntries);

            if ((strlen(OPT_DIRECTORY) == 0) ||
                (strncmp(OPT_DIRECTORY, path, strlen(OPT_DIRECTORY)) == 0)) {
                  infomsg("Sorting directory %s\n", path);
                  if (writeClusterChain(fd, bs, list, ClusterChain) == -1) {
                        myerror("Failed to write cluster chain!");
                        return -1;
                  }
                  if ((strlen(OPT_DIRECTORY) > 0) &&
                      !OPT_RECURSIVE) {
                        freeClusterChain(ClusterChain);
                        return 0;
                  }
            }
      } else {
            printf("%s\n", path);
            if (parseClusterChain(fd, bs, ClusterChain, list, &direntries) == -1) {
                  myerror("Failed to parse cluster chain!");
                  return -1;
            }
            
            printf("\n");
      }

      freeClusterChain(ClusterChain);

      // sort sub directories
      p=list->next;
      while (p != NULL) {
            if ((p->sde->DIR_Atrr & ATTR_DIRECTORY) &&
                  (p->sde->DIR_Name[0] != DE_FREE) &&
                  !(p->sde->DIR_Atrr & ATTR_VOLUME_ID) &&
                  (strcmp(p->sname, ".")) && strcmp(p->sname, "..")) {

                  c=(SwapInt16(p->sde->DIR_FstClusHI) * 65536 + SwapInt16(p->sde->DIR_FstClusLO));
                  if (getFATEntry(fd, bs, c, &value) == -1) {
                        myerror("Failed to get FAT entry!");
                        return -1;
                  }

                  strncpy(newpath, path, MAX_PATH_LEN - strlen(newpath));
                  newpath[MAX_PATH_LEN]='\0';
                  if ((p->lname != NULL) && (p->lname[0] != '\0')) {
                        strncat(newpath, p->lname, MAX_PATH_LEN - strlen(newpath));
                        newpath[MAX_PATH_LEN]='\0';
                        strncat(newpath, "/", MAX_PATH_LEN - strlen(newpath));
                        newpath[MAX_PATH_LEN]='\0';
                  } else {
                        strncat(newpath, p->sname, MAX_PATH_LEN - strlen(newpath));
                        newpath[MAX_PATH_LEN]='\0';
                        strncat(newpath, "/", MAX_PATH_LEN - strlen(newpath));
                        newpath[MAX_PATH_LEN]='\0';
                  }

                  if (sortClusterChain(fd, bs, c, newpath) == -1) {
                        myerror("Failed to sort cluster chain!");
                        return -1;
                  }

            }
            p=p->next;
      }

      return 0;
}

int32_t sort_FAT16_rootdir(FILE *fd, struct sBootSector *bs) {
/*
      sorts the root directory of a FAT16 file system
*/

      assert(fd != NULL);
      assert(bs != NULL);

      off_t BSOffset;
      u_int32_t FATSz, i, ret;
      u_int32_t entries,count=0, c, value;
      u_int32_t direntries=0;
      char newpath[MAX_PATH_LEN+1]={0};

      struct sDirEntryList *list = newDirEntryList();
      struct sDirEntryList *p;

      if (bs->BS_FATSz16 != 0) {
            FATSz = SwapInt16(bs->BS_FATSz16);
      } else {
            FATSz = SwapInt32(bs->FATxx.FAT32.BS_FATSz32);
      }

      BSOffset = ((off_t)SwapInt16(bs->BS_RsvdSecCnt) + bs->BS_NumFATs * FATSz)* SwapInt16(bs->BS_BytesPerSec);

      fs_seek(fd, BSOffset, SEEK_SET);

      if (OPT_LIST) {
            printf("/\n");
      }

      // read all entries and parse it to the list
      for (i=1;i<=SwapInt16(bs->BS_RootEntCnt);i++) {
            ret=parseDirEntry(fd, list, &entries);
            count+=entries;
            if (ret == 1) {
                  break;
            } else if (ret == -1) {
                  myerror("Failed to parse directory entries!");
                  return -1;
            }
            direntries++;
            // well, one entry read, but not matched
            if (entries == 0) count++;
      }

      if (!OPT_LIST) {
            if (OPT_RANDOM) randomizeDirEntryList(list, direntries);
            
            if ((strlen(OPT_DIRECTORY) == 0) ||
                (strncmp(OPT_DIRECTORY, "/", strlen(OPT_DIRECTORY)) == 0)) {
                  infomsg("Sorting directory /\n");
                  fs_seek(fd, BSOffset, SEEK_SET);
                  // write the sorted entries back to the fs
                  if (writeList(fd, list) == -1) {
                        myerror("Failed to write FAT entries!");
                        return -1;
                  }
                  if ((strlen(OPT_DIRECTORY) > 0) &&
                      !OPT_RECURSIVE) {
                        freeDirEntryList(list);
                        return 0;
                  }
            }
      } else {
            printf("\n");
      }

      // sort sub directories
      p=list->next;
      while (p != NULL) {
            if ((p->sde->DIR_Atrr & ATTR_DIRECTORY) &&
                  (p->sde->DIR_Name[0] != DE_FREE) &&
                  !(p->sde->DIR_Atrr & ATTR_VOLUME_ID) &&
                  (strcmp(p->sname, ".")) && strcmp(p->sname, "..")) {
                  c= (SwapInt16(p->sde->DIR_FstClusHI) * 65536 + SwapInt16(p->sde->DIR_FstClusLO));
                  if (getFATEntry(fd, bs, c, &value) == -1) {
                        myerror("Failed to get FAT entry!");
                        return -1;
                  }

                  strncpy(newpath, "/", MAX_PATH_LEN - strlen(newpath));
                  newpath[MAX_PATH_LEN]='\0';
                  if ((p->lname != NULL) && (p->lname[0] != '\0')) {
                        strncat(newpath, p->lname, MAX_PATH_LEN - strlen(newpath));
                        newpath[MAX_PATH_LEN]='\0';
                        strncat(newpath, "/", MAX_PATH_LEN - strlen(newpath));
                        newpath[MAX_PATH_LEN]='\0';
                  } else {
                        strncat(newpath, p->sname, MAX_PATH_LEN - strlen(newpath));
                        newpath[MAX_PATH_LEN]='\0';
                        strncat(newpath, "/", MAX_PATH_LEN - strlen(newpath));
                        newpath[MAX_PATH_LEN]='\0';
                  }

                  if (sortClusterChain(fd, bs, c, newpath) == -1) {
                        myerror("Failed to sort cluster chain!");
                        return -1;
                  }
            }
            p=p->next;
      }

      freeDirEntryList(list);

      return 0;
}

Generated by  Doxygen 1.6.0   Back to index