misc/physfs/src/archiver_dir.c
branchphysfslayer
changeset 7768 13e2037ebc79
equal deleted inserted replaced
7767:d1ea9b3f543e 7768:13e2037ebc79
       
     1 /*
       
     2  * Standard directory I/O support routines for PhysicsFS.
       
     3  *
       
     4  * Please see the file LICENSE.txt in the source's root directory.
       
     5  *
       
     6  *  This file written by Ryan C. Gordon.
       
     7  */
       
     8 
       
     9 #define __PHYSICSFS_INTERNAL__
       
    10 #include "physfs_internal.h"
       
    11 
       
    12 /* There's no PHYSFS_Io interface here. Use __PHYSFS_createNativeIo(). */
       
    13 
       
    14 
       
    15 
       
    16 static char *cvtToDependent(const char *prepend, const char *path, char *buf)
       
    17 {
       
    18     BAIL_IF_MACRO(buf == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
       
    19     sprintf(buf, "%s%s", prepend ? prepend : "", path);
       
    20 
       
    21     if (__PHYSFS_platformDirSeparator != '/')
       
    22     {
       
    23         char *p;
       
    24         for (p = strchr(buf, '/'); p != NULL; p = strchr(p + 1, '/'))
       
    25             *p = __PHYSFS_platformDirSeparator;
       
    26     } /* if */
       
    27 
       
    28     return buf;
       
    29 } /* cvtToDependent */
       
    30 
       
    31 
       
    32 #define CVT_TO_DEPENDENT(buf, pre, dir) { \
       
    33     const size_t len = ((pre) ? strlen((char *) pre) : 0) + strlen(dir) + 1; \
       
    34     buf = cvtToDependent((char*)pre,dir,(char*)__PHYSFS_smallAlloc(len)); \
       
    35 }
       
    36 
       
    37 
       
    38 
       
    39 static void *DIR_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
       
    40 {
       
    41     PHYSFS_Stat st;
       
    42     const char dirsep = __PHYSFS_platformDirSeparator;
       
    43     char *retval = NULL;
       
    44     const size_t namelen = strlen(name);
       
    45     const size_t seplen = 1;
       
    46     int exists = 0;
       
    47 
       
    48     assert(io == NULL);  /* shouldn't create an Io for these. */
       
    49     BAIL_IF_MACRO(!__PHYSFS_platformStat(name, &exists, &st), ERRPASS, NULL);
       
    50     if (st.filetype != PHYSFS_FILETYPE_DIRECTORY)
       
    51         BAIL_MACRO(PHYSFS_ERR_UNSUPPORTED, NULL);
       
    52 
       
    53     retval = allocator.Malloc(namelen + seplen + 1);
       
    54     BAIL_IF_MACRO(retval == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
       
    55 
       
    56     strcpy(retval, name);
       
    57 
       
    58     /* make sure there's a dir separator at the end of the string */
       
    59     if (retval[namelen - 1] != dirsep)
       
    60     {
       
    61         retval[namelen] = dirsep;
       
    62         retval[namelen + 1] = '\0';
       
    63     } /* if */
       
    64 
       
    65     return retval;
       
    66 } /* DIR_openArchive */
       
    67 
       
    68 
       
    69 static void DIR_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
       
    70                                int omitSymLinks, PHYSFS_EnumFilesCallback cb,
       
    71                                const char *origdir, void *callbackdata)
       
    72 {
       
    73     char *d;
       
    74 
       
    75     CVT_TO_DEPENDENT(d, opaque, dname);
       
    76     if (d != NULL)
       
    77     {
       
    78         __PHYSFS_platformEnumerateFiles(d, omitSymLinks, cb,
       
    79                                         origdir, callbackdata);
       
    80         __PHYSFS_smallFree(d);
       
    81     } /* if */
       
    82 } /* DIR_enumerateFiles */
       
    83 
       
    84 
       
    85 static PHYSFS_Io *doOpen(PHYSFS_Dir *opaque, const char *name,
       
    86                          const int mode, int *fileExists)
       
    87 {
       
    88     char *f;
       
    89     PHYSFS_Io *io = NULL;
       
    90     int existtmp = 0;
       
    91 
       
    92     CVT_TO_DEPENDENT(f, opaque, name);
       
    93     BAIL_IF_MACRO(!f, ERRPASS, NULL);
       
    94 
       
    95     if (fileExists == NULL)
       
    96         fileExists = &existtmp;
       
    97 
       
    98     io = __PHYSFS_createNativeIo(f, mode);
       
    99     if (io == NULL)
       
   100     {
       
   101         const PHYSFS_ErrorCode err = PHYSFS_getLastErrorCode();
       
   102         PHYSFS_Stat statbuf;
       
   103         __PHYSFS_platformStat(f, fileExists, &statbuf);
       
   104         __PHYSFS_setError(err);
       
   105     } /* if */
       
   106     else
       
   107     {
       
   108         *fileExists = 1;
       
   109     } /* else */
       
   110 
       
   111     __PHYSFS_smallFree(f);
       
   112 
       
   113     return io;
       
   114 } /* doOpen */
       
   115 
       
   116 
       
   117 static PHYSFS_Io *DIR_openRead(PHYSFS_Dir *opaque, const char *fnm, int *exist)
       
   118 {
       
   119     return doOpen(opaque, fnm, 'r', exist);
       
   120 } /* DIR_openRead */
       
   121 
       
   122 
       
   123 static PHYSFS_Io *DIR_openWrite(PHYSFS_Dir *opaque, const char *filename)
       
   124 {
       
   125     return doOpen(opaque, filename, 'w', NULL);
       
   126 } /* DIR_openWrite */
       
   127 
       
   128 
       
   129 static PHYSFS_Io *DIR_openAppend(PHYSFS_Dir *opaque, const char *filename)
       
   130 {
       
   131     return doOpen(opaque, filename, 'a', NULL);
       
   132 } /* DIR_openAppend */
       
   133 
       
   134 
       
   135 static int DIR_remove(PHYSFS_Dir *opaque, const char *name)
       
   136 {
       
   137     int retval;
       
   138     char *f;
       
   139 
       
   140     CVT_TO_DEPENDENT(f, opaque, name);
       
   141     BAIL_IF_MACRO(!f, ERRPASS, 0);
       
   142     retval = __PHYSFS_platformDelete(f);
       
   143     __PHYSFS_smallFree(f);
       
   144     return retval;
       
   145 } /* DIR_remove */
       
   146 
       
   147 
       
   148 static int DIR_mkdir(PHYSFS_Dir *opaque, const char *name)
       
   149 {
       
   150     int retval;
       
   151     char *f;
       
   152 
       
   153     CVT_TO_DEPENDENT(f, opaque, name);
       
   154     BAIL_IF_MACRO(!f, ERRPASS, 0);
       
   155     retval = __PHYSFS_platformMkDir(f);
       
   156     __PHYSFS_smallFree(f);
       
   157     return retval;
       
   158 } /* DIR_mkdir */
       
   159 
       
   160 
       
   161 static void DIR_closeArchive(PHYSFS_Dir *opaque)
       
   162 {
       
   163     allocator.Free(opaque);
       
   164 } /* DIR_closeArchive */
       
   165 
       
   166 
       
   167 static int DIR_stat(PHYSFS_Dir *opaque, const char *name,
       
   168                     int *exists, PHYSFS_Stat *stat)
       
   169 {
       
   170     int retval = 0;
       
   171     char *d;
       
   172 
       
   173     CVT_TO_DEPENDENT(d, opaque, name);
       
   174     BAIL_IF_MACRO(!d, ERRPASS, 0);
       
   175     retval = __PHYSFS_platformStat(d, exists, stat);
       
   176     __PHYSFS_smallFree(d);
       
   177     return retval;
       
   178 } /* DIR_stat */
       
   179 
       
   180 
       
   181 const PHYSFS_Archiver __PHYSFS_Archiver_DIR =
       
   182 {
       
   183     {
       
   184         "",
       
   185         "Non-archive, direct filesystem I/O",
       
   186         "Ryan C. Gordon <icculus@icculus.org>",
       
   187         "http://icculus.org/physfs/",
       
   188     },
       
   189     DIR_openArchive,        /* openArchive() method    */
       
   190     DIR_enumerateFiles,     /* enumerateFiles() method */
       
   191     DIR_openRead,           /* openRead() method       */
       
   192     DIR_openWrite,          /* openWrite() method      */
       
   193     DIR_openAppend,         /* openAppend() method     */
       
   194     DIR_remove,             /* remove() method         */
       
   195     DIR_mkdir,              /* mkdir() method          */
       
   196     DIR_closeArchive,       /* closeArchive() method   */
       
   197     DIR_stat                /* stat() method           */
       
   198 };
       
   199 
       
   200 /* end of dir.c ... */
       
   201