misc/libphysfs/archiver_iso9660.c
changeset 12213 bb5522e88ab2
parent 8524 a65e9bcf0a03
equal deleted inserted replaced
12212:ea891871f481 12213:bb5522e88ab2
   289         int pos = 0;
   289         int pos = 0;
   290         int lastfound = -1;
   290         int lastfound = -1;
   291         for(;pos < descriptor->filenamelen; pos++)
   291         for(;pos < descriptor->filenamelen; pos++)
   292             if (descriptor->filename[pos] == ';')
   292             if (descriptor->filename[pos] == ';')
   293                 lastfound = pos;
   293                 lastfound = pos;
   294         BAIL_IF_MACRO(lastfound < 1, PHYSFS_ERR_NO_SUCH_PATH /* !!! FIXME: PHYSFS_ERR_BAD_FILENAME */, -1);
   294         BAIL_IF_MACRO(lastfound < 1, PHYSFS_ERR_NOT_FOUND /* !!! FIXME: PHYSFS_ERR_BAD_FILENAME */, -1);
   295         BAIL_IF_MACRO(lastfound == (descriptor->filenamelen -1), PHYSFS_ERR_NO_SUCH_PATH /* !!! PHYSFS_ERR_BAD_FILENAME */, -1);
   295         BAIL_IF_MACRO(lastfound == (descriptor->filenamelen -1), PHYSFS_ERR_NOT_FOUND /* !!! PHYSFS_ERR_BAD_FILENAME */, -1);
   296         strncpy(filename, descriptor->filename, lastfound);
   296         strncpy(filename, descriptor->filename, lastfound);
   297         if (filename[lastfound - 1] == '.')
   297         if (filename[lastfound - 1] == '.')
   298             filename[lastfound - 1] = '\0'; /* consume trailing ., as done in all implementations */
   298             filename[lastfound - 1] = '\0'; /* consume trailing ., as done in all implementations */
   299         else
   299         else
   300             filename[lastfound] = '\0';
   300             filename[lastfound] = '\0';
   396  * Don't use path tables, they are not necessarily faster, but more complicated
   396  * Don't use path tables, they are not necessarily faster, but more complicated
   397  * to implement as they store only directories and not files, so searching for
   397  * to implement as they store only directories and not files, so searching for
   398  * a file needs to branch to the directory extent sooner or later.
   398  * a file needs to branch to the directory extent sooner or later.
   399  */
   399  */
   400 static int iso_find_dir_entry(ISO9660Handle *handle,const char *path,
   400 static int iso_find_dir_entry(ISO9660Handle *handle,const char *path,
   401                               ISO9660FileDescriptor *descriptor, int *exists)
   401                               ISO9660FileDescriptor *descriptor)
   402 {
   402 {
   403     char *subpath = 0;
   403     char *subpath = 0;
   404     PHYSFS_uint64 readpos, end_of_dir;
   404     PHYSFS_uint64 readpos, end_of_dir;
   405     char filename[255];
   405     char filename[255];
   406     char pathcopy[256];
   406     char pathcopy[256];
   407     char *mypath;
   407     char *mypath;
   408     int version = 0;
   408     int version = 0;
   409 
   409 
   410     strcpy(pathcopy, path);
   410     strcpy(pathcopy, path);
   411     mypath = pathcopy;
   411     mypath = pathcopy;
   412     *exists = 0;
       
   413 
   412 
   414     readpos = handle->rootdirstart;
   413     readpos = handle->rootdirstart;
   415     end_of_dir = handle->rootdirstart + handle->rootdirsize;
   414     end_of_dir = handle->rootdirstart + handle->rootdirsize;
   416     iso_extractsubpath(mypath, &subpath);
   415     iso_extractsubpath(mypath, &subpath);
   417     while (1)
   416     while (1)
   440             ERRPASS, -1);
   439             ERRPASS, -1);
   441 
   440 
   442         if (strcmp(filename, mypath) == 0)
   441         if (strcmp(filename, mypath) == 0)
   443         {
   442         {
   444             if ( (subpath == 0) || (subpath[0] == 0) )
   443             if ( (subpath == 0) || (subpath[0] == 0) )
   445             {
       
   446                 *exists = 1;
       
   447                 return 0;  /* no subpaths left and we found the entry */
   444                 return 0;  /* no subpaths left and we found the entry */
   448             } /* if */
       
   449 
   445 
   450             if (descriptor->flags.directory)
   446             if (descriptor->flags.directory)
   451             {
   447             {
   452                 /* shorten the path to the subpath */
   448                 /* shorten the path to the subpath */
   453                 mypath = subpath;
   449                 mypath = subpath;
   456                 readpos = descriptor->extentpos * 2048;
   452                 readpos = descriptor->extentpos * 2048;
   457                 end_of_dir = readpos + descriptor->datalen;
   453                 end_of_dir = readpos + descriptor->datalen;
   458             } /* if */
   454             } /* if */
   459             else
   455             else
   460             {
   456             {
       
   457                 /* !!! FIXME: set PHYSFS_ERR_NOT_FOUND? */
   461                 /* we're at a file but have a remaining subpath -> no match */
   458                 /* we're at a file but have a remaining subpath -> no match */
   462                 return 0;
   459                 return 0;
   463             } /* else */
   460             } /* else */
   464         } /* if */
   461         } /* if */
   465     } /* while */
   462     } /* while */
   466 
   463 
       
   464     /* !!! FIXME: set PHYSFS_ERR_NOT_FOUND? */
   467     return 0;
   465     return 0;
   468 } /* iso_find_dir_entry */
   466 } /* iso_find_dir_entry */
   469 
   467 
   470 
   468 
   471 static int iso_read_ext_attributes(ISO9660Handle *handle, int block,
   469 static int iso_read_ext_attributes(ISO9660Handle *handle, int block,
   553 
   551 
   554     BAIL_IF_MACRO(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
   552     BAIL_IF_MACRO(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
   555 
   553 
   556     /* Skip system area to magic number in Volume descriptor */
   554     /* Skip system area to magic number in Volume descriptor */
   557     BAIL_IF_MACRO(!io->seek(io, 32769), ERRPASS, NULL);
   555     BAIL_IF_MACRO(!io->seek(io, 32769), ERRPASS, NULL);
   558     BAIL_IF_MACRO(!io->read(io, magicnumber, 5) != 5, ERRPASS, NULL);
   556     BAIL_IF_MACRO(io->read(io, magicnumber, 5) != 5, ERRPASS, NULL);
   559     if (memcmp(magicnumber, "CD001", 6) != 0)
   557     if (memcmp(magicnumber, "CD001", 6) != 0)
   560         BAIL_MACRO(PHYSFS_ERR_UNSUPPORTED, NULL);
   558         BAIL_MACRO(PHYSFS_ERR_UNSUPPORTED, NULL);
   561 
   559 
   562     handle = allocator.Malloc(sizeof(ISO9660Handle));
   560     handle = allocator.Malloc(sizeof(ISO9660Handle));
   563     GOTO_IF_MACRO(!handle, PHYSFS_ERR_OUT_OF_MEMORY, errorcleanup);
   561     GOTO_IF_MACRO(!handle, PHYSFS_ERR_OUT_OF_MEMORY, errorcleanup);
   636     } /* if */
   634     } /* if */
   637     return NULL;
   635     return NULL;
   638 } /* ISO9660_openArchive */
   636 } /* ISO9660_openArchive */
   639 
   637 
   640 
   638 
   641 static void ISO9660_closeArchive(PHYSFS_Dir *opaque)
   639 static void ISO9660_closeArchive(void *opaque)
   642 {
   640 {
   643     ISO9660Handle *handle = (ISO9660Handle*) opaque;
   641     ISO9660Handle *handle = (ISO9660Handle*) opaque;
   644     handle->io->destroy(handle->io);
   642     handle->io->destroy(handle->io);
   645     __PHYSFS_platformDestroyMutex(handle->mutex);
   643     __PHYSFS_platformDestroyMutex(handle->mutex);
   646     allocator.Free(handle->path);
   644     allocator.Free(handle->path);
   764     fhandle->io->destroy(fhandle->io);
   762     fhandle->io->destroy(fhandle->io);
   765     return -1;
   763     return -1;
   766 } /* iso_file_open_foreign */
   764 } /* iso_file_open_foreign */
   767 
   765 
   768 
   766 
   769 static PHYSFS_Io *ISO9660_openRead(PHYSFS_Dir *opaque, const char *filename,
   767 static PHYSFS_Io *ISO9660_openRead(void *opaque, const char *filename)
   770                                    int *exists)
       
   771 {
   768 {
   772     PHYSFS_Io *retval = NULL;
   769     PHYSFS_Io *retval = NULL;
   773     ISO9660Handle *handle = (ISO9660Handle*) opaque;
   770     ISO9660Handle *handle = (ISO9660Handle*) opaque;
   774     ISO9660FileHandle *fhandle;
   771     ISO9660FileHandle *fhandle;
   775     ISO9660FileDescriptor descriptor;
   772     ISO9660FileDescriptor descriptor;
   781 
   778 
   782     retval = allocator.Malloc(sizeof(PHYSFS_Io));
   779     retval = allocator.Malloc(sizeof(PHYSFS_Io));
   783     GOTO_IF_MACRO(retval == 0, PHYSFS_ERR_OUT_OF_MEMORY, errorhandling);
   780     GOTO_IF_MACRO(retval == 0, PHYSFS_ERR_OUT_OF_MEMORY, errorhandling);
   784 
   781 
   785     /* find file descriptor */
   782     /* find file descriptor */
   786     rc = iso_find_dir_entry(handle, filename, &descriptor, exists);
   783     rc = iso_find_dir_entry(handle, filename, &descriptor);
   787     GOTO_IF_MACRO(rc, ERRPASS, errorhandling);
   784     GOTO_IF_MACRO(rc, ERRPASS, errorhandling);
   788     GOTO_IF_MACRO(!*exists, PHYSFS_ERR_NO_SUCH_PATH, errorhandling);
       
   789 
   785 
   790     fhandle->startblock = descriptor.extentpos + descriptor.extattributelen;
   786     fhandle->startblock = descriptor.extentpos + descriptor.extattributelen;
   791     fhandle->filesize = descriptor.datalen;
   787     fhandle->filesize = descriptor.datalen;
   792     fhandle->currpos = 0;
   788     fhandle->currpos = 0;
   793     fhandle->isohandle = handle;
   789     fhandle->isohandle = handle;
   814 
   810 
   815 /*******************************************************************************
   811 /*******************************************************************************
   816  * Information gathering functions
   812  * Information gathering functions
   817  ******************************************************************************/
   813  ******************************************************************************/
   818 
   814 
   819 static void ISO9660_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
   815 static void ISO9660_enumerateFiles(void *opaque, const char *dname,
   820                                    int omitSymLinks,
       
   821                                    PHYSFS_EnumFilesCallback cb,
   816                                    PHYSFS_EnumFilesCallback cb,
   822                                    const char *origdir, void *callbackdata)
   817                                    const char *origdir, void *callbackdata)
   823 {
   818 {
   824     ISO9660Handle *handle = (ISO9660Handle*) opaque;
   819     ISO9660Handle *handle = (ISO9660Handle*) opaque;
   825     ISO9660FileDescriptor descriptor;
   820     ISO9660FileDescriptor descriptor;
   834         end_of_dir = readpos + handle->rootdirsize;
   829         end_of_dir = readpos + handle->rootdirsize;
   835     } /* if */
   830     } /* if */
   836     else
   831     else
   837     {
   832     {
   838         printf("pfad %s\n",dname);
   833         printf("pfad %s\n",dname);
   839         int exists = 0;
   834         BAIL_IF_MACRO(iso_find_dir_entry(handle,dname, &descriptor), ERRPASS,);
   840         BAIL_IF_MACRO(iso_find_dir_entry(handle,dname, &descriptor, &exists), ERRPASS,);
       
   841         BAIL_IF_MACRO(!exists, ERRPASS, );
       
   842         BAIL_IF_MACRO(!descriptor.flags.directory, ERRPASS,);
   835         BAIL_IF_MACRO(!descriptor.flags.directory, ERRPASS,);
   843 
   836 
   844         readpos = descriptor.extentpos * 2048;
   837         readpos = descriptor.extentpos * 2048;
   845         end_of_dir = readpos + descriptor.datalen;
   838         end_of_dir = readpos + descriptor.datalen;
   846     } /* else */
   839     } /* else */
   871         cb(callbackdata, origdir,filename);
   864         cb(callbackdata, origdir,filename);
   872     } /* while */
   865     } /* while */
   873 } /* ISO9660_enumerateFiles */
   866 } /* ISO9660_enumerateFiles */
   874 
   867 
   875 
   868 
   876 static int ISO9660_stat(PHYSFS_Dir *opaque, const char *name, int *exists,
   869 static int ISO9660_stat(void *opaque, const char *name, PHYSFS_Stat *stat)
   877                         PHYSFS_Stat *stat)
       
   878 {
   870 {
   879     ISO9660Handle *handle = (ISO9660Handle*) opaque;
   871     ISO9660Handle *handle = (ISO9660Handle*) opaque;
   880     ISO9660FileDescriptor descriptor;
   872     ISO9660FileDescriptor descriptor;
   881     ISO9660ExtAttributeRec extattr;
   873     ISO9660ExtAttributeRec extattr;
   882     BAIL_IF_MACRO(iso_find_dir_entry(handle, name, &descriptor, exists), ERRPASS, -1);
   874     BAIL_IF_MACRO(iso_find_dir_entry(handle, name, &descriptor), ERRPASS, -1);
   883     if (!*exists)
       
   884         return 0;
       
   885 
   875 
   886     stat->readonly = 1;
   876     stat->readonly = 1;
   887 
   877 
   888     /* try to get extended info */
   878     /* try to get extended info */
   889     if (descriptor.extattributelen)
   879     if (descriptor.extattributelen)
   918 
   908 
   919 /*******************************************************************************
   909 /*******************************************************************************
   920  * Not supported functions
   910  * Not supported functions
   921  ******************************************************************************/
   911  ******************************************************************************/
   922 
   912 
   923 static PHYSFS_Io *ISO9660_openWrite(PHYSFS_Dir *opaque, const char *name)
   913 static PHYSFS_Io *ISO9660_openWrite(void *opaque, const char *name)
   924 {
   914 {
   925     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
   915     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
   926 } /* ISO9660_openWrite */
   916 } /* ISO9660_openWrite */
   927 
   917 
   928 
   918 
   929 static PHYSFS_Io *ISO9660_openAppend(PHYSFS_Dir *opaque, const char *name)
   919 static PHYSFS_Io *ISO9660_openAppend(void *opaque, const char *name)
   930 {
   920 {
   931     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
   921     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
   932 } /* ISO9660_openAppend */
   922 } /* ISO9660_openAppend */
   933 
   923 
   934 
   924 
   935 static int ISO9660_remove(PHYSFS_Dir *opaque, const char *name)
   925 static int ISO9660_remove(void *opaque, const char *name)
   936 {
   926 {
   937     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
   927     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
   938 } /* ISO9660_remove */
   928 } /* ISO9660_remove */
   939 
   929 
   940 
   930 
   941 static int ISO9660_mkdir(PHYSFS_Dir *opaque, const char *name)
   931 static int ISO9660_mkdir(void *opaque, const char *name)
   942 {
   932 {
   943     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
   933     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
   944 } /* ISO9660_mkdir */
   934 } /* ISO9660_mkdir */
   945 
   935 
   946 
   936 
   947 const PHYSFS_Archiver __PHYSFS_Archiver_ISO9660 =
   937 const PHYSFS_Archiver __PHYSFS_Archiver_ISO9660 =
   948 {
   938 {
       
   939     CURRENT_PHYSFS_ARCHIVER_API_VERSION,
   949     {
   940     {
   950         "ISO",
   941         "ISO",
   951         "ISO9660 image file",
   942         "ISO9660 image file",
   952         "Christoph Nelles <evilazrael@evilazrael.de>",
   943         "Christoph Nelles <evilazrael@evilazrael.de>",
   953         "http://www.evilazrael.de/",
   944         "https://www.evilazrael.de/",
       
   945         0,  /* supportsSymlinks */
   954     },
   946     },
   955     ISO9660_openArchive,        /* openArchive() method    */
   947     ISO9660_openArchive,
   956     ISO9660_enumerateFiles,     /* enumerateFiles() method */
   948     ISO9660_enumerateFiles,
   957     ISO9660_openRead,           /* openRead() method       */
   949     ISO9660_openRead,
   958     ISO9660_openWrite,          /* openWrite() method      */
   950     ISO9660_openWrite,
   959     ISO9660_openAppend,         /* openAppend() method     */
   951     ISO9660_openAppend,
   960     ISO9660_remove,             /* remove() method         */
   952     ISO9660_remove,
   961     ISO9660_mkdir,              /* mkdir() method          */
   953     ISO9660_mkdir,
   962     ISO9660_closeArchive,       /* closeArchive() method   */
   954     ISO9660_stat,
   963     ISO9660_stat                /* stat() method           */
   955     ISO9660_closeArchive
   964 };
   956 };
   965 
   957 
   966 #endif  /* defined PHYSFS_SUPPORTS_ISO9660 */
   958 #endif  /* defined PHYSFS_SUPPORTS_ISO9660 */
   967 
   959 
   968 /* end of archiver_iso9660.c ... */
   960 /* end of archiver_iso9660.c ... */