Annotation of hatari/src/file.c, revision 1.1.1.9

1.1       root        1: /*
1.1.1.6   root        2:   Hatari - file.c
1.1       root        3: 
1.1.1.5   root        4:   This file is distributed under the GNU Public License, version 2 or at
                      5:   your option any later version. Read the file gpl.txt for details.
                      6: 
1.1.1.6   root        7:   Common file access functions.
1.1       root        8: */
1.1.1.9 ! root        9: char File_rcsid[] = "Hatari $Id: file.c,v 1.24 2005/09/13 01:10:09 thothy Exp $";
1.1       root       10: 
                     11: #include <sys/types.h>
                     12: #include <sys/stat.h>
                     13: #include <fcntl.h>
1.1.1.6   root       14: #include <unistd.h>
                     15: 
                     16: #include <zlib.h>
1.1       root       17: 
                     18: #include "main.h"
1.1.1.7   root       19: #include "dialog.h"
1.1       root       20: #include "file.h"
                     21: #include "createBlankImage.h"
                     22: 
1.1.1.3   root       23: 
1.1.1.6   root       24: #if defined(__BEOS__) || (defined(__sun) && defined(__SVR4))
                     25: /* The scandir() and alphasort() functions aren't available on
                     26:  * BeOS and Solaris, so let's declare them here... */
1.1.1.3   root       27: #include <dirent.h>
                     28: 
                     29: #undef DIRSIZ
                     30: 
                     31: #define DIRSIZ(dp)                                          \
                     32:         ((sizeof(struct dirent) - sizeof(dp)->d_name) +     \
                     33:                (((dp)->d_reclen + 1 + 3) &~ 3))
                     34: 
1.1.1.6   root       35: #if defined(__sun) && defined(__SVR4)
1.1.1.7   root       36: # define dirfd(d) ((d)->dd_fd)
                     37: #elif defined(__BEOS__)
                     38: # define dirfd(d) ((d)->fd)
1.1.1.6   root       39: #endif
                     40: 
1.1       root       41: 
                     42: /*-----------------------------------------------------------------------*/
                     43: /*
1.1.1.3   root       44:   Alphabetic order comparison routine for those who want it.
1.1       root       45: */
1.1.1.3   root       46: int alphasort(const void *d1, const void *d2)
1.1       root       47: {
1.1.1.8   root       48:   return strcmp((*(struct dirent * const *)d1)->d_name, (*(struct dirent * const *)d2)->d_name);
1.1.1.3   root       49: }
1.1       root       50: 
                     51: 
1.1.1.3   root       52: /*-----------------------------------------------------------------------*/
                     53: /*
                     54:   Scan a directory for all its entries
                     55: */
1.1.1.8   root       56: int scandir(const char *dirname, struct dirent ***namelist, int (*sdfilter)(struct dirent *), int (*dcomp)(const void *, const void *))
1.1.1.3   root       57: {
1.1.1.8   root       58:   struct dirent *d, *p, **names;
1.1.1.3   root       59:   struct stat stb;
1.1.1.8   root       60:   size_t nitems;
                     61:   size_t arraysz;
1.1.1.3   root       62:   DIR *dirp;
1.1       root       63: 
1.1.1.3   root       64:   if ((dirp = opendir(dirname)) == NULL)
                     65:     return(-1);
1.1       root       66: 
1.1.1.7   root       67:   if (fstat(dirfd(dirp), &stb) < 0)
1.1.1.3   root       68:     return(-1);
1.1       root       69: 
1.1.1.3   root       70:   /*
                     71:    * estimate the array size by taking the size of the directory file
                     72:    * and dividing it by a multiple of the minimum size entry.
                     73:    */
                     74:   arraysz = (stb.st_size / 24);
1.1       root       75: 
1.1.1.3   root       76:   names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
                     77:   if (names == NULL)
                     78:     return(-1);
1.1       root       79: 
1.1.1.3   root       80:   nitems = 0;
1.1       root       81: 
1.1.1.3   root       82:   while ((d = readdir(dirp)) != NULL) {
1.1       root       83: 
1.1.1.8   root       84:      if (sdfilter != NULL && !(*sdfilter)(d))
1.1.1.3   root       85:        continue;       /* just selected names */
1.1       root       86: 
1.1.1.3   root       87:      /*
                     88:       * Make a minimum size copy of the data
                     89:       */
1.1       root       90: 
1.1.1.3   root       91:      p = (struct dirent *)malloc(DIRSIZ(d));
                     92:      if (p == NULL)
                     93:        return(-1);
1.1       root       94: 
1.1.1.3   root       95:      p->d_ino = d->d_ino;
                     96:      p->d_reclen = d->d_reclen;
                     97:      /*p->d_namlen = d->d_namlen;*/
1.1.1.7   root       98:      memcpy(p->d_name, d->d_name, p->d_reclen + 1);
1.1       root       99: 
1.1.1.3   root      100:      /*
                    101:       * Check to make sure the array has space left and
                    102:       * realloc the maximum size.
                    103:       */
1.1       root      104: 
1.1.1.3   root      105:      if (++nitems >= arraysz) {
1.1       root      106: 
1.1.1.7   root      107:        if (fstat(dirfd(dirp), &stb) < 0)
1.1.1.3   root      108:          return(-1);     /* just might have grown */
1.1       root      109: 
1.1.1.3   root      110:        arraysz = stb.st_size / 12;
1.1       root      111: 
1.1.1.3   root      112:        names = (struct dirent **)realloc((char *)names, arraysz * sizeof(struct dirent *));
                    113:        if (names == NULL)
                    114:          return(-1);
                    115:      }
1.1       root      116: 
1.1.1.3   root      117:      names[nitems-1] = p;
                    118:    }
1.1       root      119: 
1.1.1.3   root      120:    closedir(dirp);
1.1       root      121: 
1.1.1.3   root      122:    if (nitems && dcomp != NULL)
                    123:      qsort(names, nitems, sizeof(struct dirent *), dcomp);
1.1       root      124: 
1.1.1.3   root      125:    *namelist = names;
                    126: 
1.1.1.8   root      127:    return nitems;
1.1       root      128: }
                    129: 
                    130: 
1.1.1.3   root      131: #endif /* __BEOS__ */
                    132: 
1.1       root      133: 
1.1.1.2   root      134: 
                    135: /*-----------------------------------------------------------------------*/
1.1       root      136: /*
                    137:   Remove any '/'s from end of filenames, but keeps / intact
                    138: */
                    139: void File_CleanFileName(char *pszFileName)
                    140: {
1.1.1.3   root      141:   int len;
                    142: 
                    143:   len = strlen(pszFileName);
                    144: 
                    145:   /* Security length check: */
1.1.1.6   root      146:   if (len > FILENAME_MAX)
1.1.1.3   root      147:   {
1.1.1.6   root      148:     pszFileName[FILENAME_MAX-1] = 0;
                    149:     len = FILENAME_MAX;
1.1.1.3   root      150:   }
1.1       root      151: 
1.1.1.2   root      152:   /* Remove end slash from filename! But / remains! Doh! */
1.1.1.3   root      153:   if( len>2 && pszFileName[len-1]=='/' )
                    154:     pszFileName[len-1] = 0;
1.1       root      155: }
                    156: 
1.1.1.2   root      157: 
                    158: /*-----------------------------------------------------------------------*/
1.1       root      159: /*
                    160:   Add '/' to end of filename
                    161: */
                    162: void File_AddSlashToEndFileName(char *pszFileName)
                    163: {
1.1.1.2   root      164:   /* Check dir/filenames */
1.1.1.8   root      165:   if (strlen(pszFileName)!=0)
                    166:   {
1.1       root      167:     if (pszFileName[strlen(pszFileName)-1]!='/')
1.1.1.2   root      168:       strcat(pszFileName,"/");  /* Must use end slash */
1.1       root      169:   }
                    170: }
                    171: 
1.1.1.3   root      172: 
1.1       root      173: /*-----------------------------------------------------------------------*/
                    174: /*
                    175:   Does filename extension match? If so, return TRUE
                    176: */
1.1.1.8   root      177: BOOL File_DoesFileExtensionMatch(const char *pszFileName, const char *pszExtension)
1.1       root      178: {
                    179:   if ( strlen(pszFileName) < strlen(pszExtension) )
                    180:     return(FALSE);
                    181:   /* Is matching extension? */
                    182:   if ( !strcasecmp(&pszFileName[strlen(pszFileName)-strlen(pszExtension)], pszExtension) )
                    183:     return(TRUE);
                    184: 
                    185:   /* No */
                    186:   return(FALSE);
                    187: }
                    188: 
1.1.1.2   root      189: 
                    190: /*-----------------------------------------------------------------------*/
1.1       root      191: /*
                    192:   Check if filename is from root
                    193:   
                    194:   Return TRUE if filename is '/', else give FALSE
                    195: */
                    196: BOOL File_IsRootFileName(char *pszFileName)
                    197: {
                    198:   if (pszFileName[0]=='\0')     /* If NULL string return! */
                    199:     return(FALSE);
                    200: 
                    201:   if (pszFileName[0]=='/')
                    202:     return(TRUE);
                    203: 
                    204:   return(FALSE);
                    205: }
                    206: 
1.1.1.2   root      207: 
                    208: /*-----------------------------------------------------------------------*/
1.1       root      209: /*
                    210:   Return string, to remove 'C:' part of filename
                    211: */
1.1.1.8   root      212: const char *File_RemoveFileNameDrive(const char *pszFileName)
1.1       root      213: {
                    214:   if ( (pszFileName[0]!='\0') && (pszFileName[1]==':') )
                    215:     return(&pszFileName[2]);
                    216:   else
                    217:     return(pszFileName);
                    218: }
                    219: 
                    220: 
1.1.1.2   root      221: /*-----------------------------------------------------------------------*/
1.1       root      222: /*
                    223:   Check if filename end with a '/'
                    224:   
                    225:   Return TRUE if filename ends with '/'
                    226: */
                    227: BOOL File_DoesFileNameEndWithSlash(char *pszFileName)
                    228: {
                    229:   if (pszFileName[0]=='\0')    /* If NULL string return! */
                    230:     return(FALSE);
                    231: 
1.1.1.3   root      232:   /* Does string end in a '/'? */
1.1       root      233:   if (pszFileName[strlen(pszFileName)-1]=='/')
                    234:     return(TRUE);
                    235: 
                    236:   return(FALSE);
                    237: }
                    238: 
1.1.1.2   root      239: 
                    240: /*-----------------------------------------------------------------------*/
1.1       root      241: /*
                    242:   Remove any double '/'s  from end of filenames. So just the one
                    243: */
                    244: void File_RemoveFileNameTrailingSlashes(char *pszFileName)
                    245: {
                    246:   int Length;
                    247: 
                    248:   /* Do have slash at end of filename? */
                    249:   Length = strlen(pszFileName);
1.1.1.8   root      250:   if (Length>=3)
                    251:   {
                    252:     if (pszFileName[Length-1]=='/')       /* Yes, have one previous? */
                    253:     {
1.1       root      254:       if (pszFileName[Length-2]=='/')
                    255:         pszFileName[Length-1] = '\0';     /* then remove it! */
                    256:     }
                    257:   }
                    258: }
                    259: 
                    260: 
1.1.1.2   root      261: /*-----------------------------------------------------------------------*/
1.1       root      262: /*
1.1.1.9 ! root      263:   Read file from disk into memory, allocate memory for it if need to (pass
1.1.1.6   root      264:   Address as NULL).
1.1       root      265: */
1.1.1.8   root      266: void *File_Read(char *pszFileName, void *pAddress, long *pFileSize, const char *ppszExts[])
1.1       root      267: {
1.1.1.6   root      268:   void *pFile = NULL;
                    269:   long FileSize = 0;
1.1       root      270: 
                    271:   /* Does the file exist? If not, see if can scan for other extensions and try these */
1.1.1.6   root      272:   if (!File_Exists(pszFileName) && ppszExts)
                    273:   {
1.1       root      274:     /* Try other extensions, if suceeds correct filename is now in 'pszFileName' */
1.1.1.6   root      275:     File_FindPossibleExtFileName(pszFileName, ppszExts);
1.1       root      276:   }
                    277: 
1.1.1.6   root      278:   /* Normal file or gzipped file? */
                    279:   if (File_DoesFileExtensionMatch(pszFileName, ".gz"))
                    280:   {
                    281:     gzFile hGzFile;
                    282:     /* Open and read gzipped file */
                    283:     hGzFile = gzopen(pszFileName, "rb");
                    284:     if (hGzFile != NULL)
                    285:     {
                    286:       /* Find size of file: */
                    287:       do
                    288:       {
                    289:         /* Seek through the file until we hit the end... */
                    290:         gzseek(hGzFile, 1024, SEEK_CUR);
                    291:       }
                    292:       while (!gzeof(hGzFile));
                    293:       FileSize = gztell(hGzFile);
                    294:       gzrewind(hGzFile);
                    295:       /* Find pointer to where to load, allocate memory if pass NULL */
                    296:       if (pAddress)
                    297:         pFile = pAddress;
                    298:       else
                    299:         pFile = malloc(FileSize);
                    300:       /* Read in... */
                    301:       if (pFile)
                    302:         gzread(hGzFile, pFile, FileSize);
1.1       root      303: 
1.1.1.6   root      304:       gzclose(hGzFile);
                    305:     }
                    306:   }
                    307:   else
                    308:   {
1.1.1.9 ! root      309:     FILE *hDiskFile;
1.1.1.6   root      310:     /* Open and read normal file */
1.1.1.9 ! root      311:     hDiskFile = fopen(pszFileName, "rb");
        !           312:     if (hDiskFile != NULL)
1.1.1.6   root      313:     {
                    314:       /* Find size of file: */
1.1.1.9 ! root      315:       fseek(hDiskFile, 0, SEEK_END);
        !           316:       FileSize = ftell(hDiskFile);
        !           317:       fseek(hDiskFile, 0, SEEK_SET);
1.1.1.6   root      318:       /* Find pointer to where to load, allocate memory if pass NULL */
                    319:       if (pAddress)
                    320:         pFile = pAddress;
                    321:       else
                    322:         pFile = malloc(FileSize);
                    323:       /* Read in... */
                    324:       if (pFile)
1.1.1.9 ! root      325:         fread(pFile, 1, FileSize, hDiskFile);
1.1.1.6   root      326: 
1.1.1.9 ! root      327:       fclose(hDiskFile);
1.1.1.6   root      328:     }
1.1       root      329:   }
1.1.1.6   root      330: 
1.1.1.2   root      331:   /* Store size of file we read in (or 0 if failed) */
1.1       root      332:   if (pFileSize)
                    333:     *pFileSize = FileSize;
                    334: 
                    335:   return(pFile);        /* Return to where read in/allocated */
                    336: }
                    337: 
1.1.1.2   root      338: 
                    339: /*-----------------------------------------------------------------------*/
1.1       root      340: /*
1.1.1.9 ! root      341:   Save file to disk, return FALSE if errors
1.1       root      342: */
1.1.1.6   root      343: BOOL File_Save(char *pszFileName, void *pAddress, size_t Size, BOOL bQueryOverwrite)
1.1       root      344: {
1.1.1.6   root      345:   BOOL bRet = FALSE;
1.1       root      346: 
                    347:   /* Check if need to ask user if to overwrite */
1.1.1.6   root      348:   if (bQueryOverwrite)
                    349:   {
1.1       root      350:     /* If file exists, ask if OK to overwrite */
                    351:     if (!File_QueryOverwrite(pszFileName))
                    352:       return(FALSE);
                    353:   }
                    354: 
1.1.1.6   root      355:   /* Normal file or gzipped file? */
                    356:   if (File_DoesFileExtensionMatch(pszFileName, ".gz"))
                    357:   {
                    358:     gzFile *hGzFile;
                    359:     /* Create a gzipped file: */
                    360:     hGzFile = gzopen(pszFileName, "wb");
                    361:     if (hGzFile != NULL)
                    362:     {
                    363:       /* Write data, set success flag */
1.1.1.8   root      364:       if (gzwrite(hGzFile, pAddress, Size) == (int)Size)
1.1.1.6   root      365:         bRet = TRUE;
1.1       root      366: 
1.1.1.6   root      367:       gzclose(hGzFile);
                    368:     }
                    369:   }
                    370:   else
                    371:   {
1.1.1.9 ! root      372:     FILE *hDiskFile;
1.1.1.6   root      373:     /* Create a normal file: */
1.1.1.9 ! root      374:     hDiskFile = fopen(pszFileName, "wb");
        !           375:     if (hDiskFile != NULL)
1.1.1.6   root      376:     {
                    377:       /* Write data, set success flag */
1.1.1.9 ! root      378:       if (fwrite(pAddress, 1, Size, hDiskFile) == Size)
1.1.1.6   root      379:         bRet = TRUE;
                    380: 
1.1.1.9 ! root      381:       fclose(hDiskFile);
1.1.1.6   root      382:     }
1.1       root      383:   }
                    384: 
                    385:   return(bRet);
                    386: }
                    387: 
1.1.1.2   root      388: 
                    389: /*-----------------------------------------------------------------------*/
1.1       root      390: /*
                    391:   Return size of file, -1 if error
                    392: */
1.1.1.8   root      393: int File_Length(const char *pszFileName)
1.1       root      394: {
1.1.1.9 ! root      395:   FILE *hDiskFile;
1.1       root      396:   int FileSize;
1.1.1.9 ! root      397: 
        !           398:   hDiskFile = fopen(pszFileName, "rb");
        !           399:   if (hDiskFile!=NULL)
1.1.1.8   root      400:   {
1.1.1.9 ! root      401:     fseek(hDiskFile, 0, SEEK_END);
        !           402:     FileSize = ftell(hDiskFile);
        !           403:     fseek(hDiskFile, 0, SEEK_SET);
        !           404:     fclose(hDiskFile);
1.1       root      405:     return(FileSize);
                    406:   }
                    407: 
                    408:   return(-1);
                    409: }
                    410: 
1.1.1.2   root      411: 
                    412: /*-----------------------------------------------------------------------*/
1.1       root      413: /*
                    414:   Return TRUE if file exists
                    415: */
1.1.1.8   root      416: BOOL File_Exists(const char *pszFileName)
1.1       root      417: {
1.1.1.9 ! root      418:   FILE *hDiskFile;
1.1       root      419: 
1.1.1.2   root      420:   /* Attempt to open file */
1.1.1.9 ! root      421:   hDiskFile = fopen(pszFileName, "rb");
        !           422:   if (hDiskFile!=NULL)
1.1.1.8   root      423:   {
1.1.1.9 ! root      424:     fclose(hDiskFile);
1.1       root      425:     return(TRUE);
1.1.1.2   root      426:   }
1.1       root      427:   return(FALSE);
                    428: }
                    429: 
1.1.1.2   root      430: 
                    431: /*-----------------------------------------------------------------------*/
1.1       root      432: /*
                    433:   Find if file exists, and if so ask user if OK to overwrite
                    434: */
1.1.1.8   root      435: BOOL File_QueryOverwrite(const char *pszFileName)
1.1       root      436: {
1.1.1.7   root      437:   char szString[FILENAME_MAX + 26];
1.1       root      438: 
1.1.1.2   root      439:   /* Try and find if file exists */
1.1.1.6   root      440:   if (File_Exists(pszFileName))
                    441:   {
1.1.1.2   root      442:     /* File does exist, are we OK to overwrite? */
1.1.1.7   root      443:     snprintf(szString, sizeof(szString), "File '%s' exists, overwrite?", pszFileName);
                    444:        fprintf(stderr, "%s\n", szString);
                    445:     return DlgAlert_Query(szString);
1.1       root      446:   }
                    447: 
                    448:   return(TRUE);
                    449: }
                    450: 
1.1.1.2   root      451: 
                    452: /*-----------------------------------------------------------------------*/
1.1       root      453: /*
                    454:   Try filename with various extensions and check if file exists - if so return correct name
                    455: */
1.1.1.8   root      456: BOOL File_FindPossibleExtFileName(char *pszFileName, const char *ppszExts[])
1.1       root      457: {
1.1.1.8   root      458:   char *szSrcDir, *szSrcName, *szSrcExt;
                    459:   char *szTempFileName;
                    460:   int i = 0;
                    461:   BOOL bFileExists = FALSE;
                    462: 
                    463:   /* Allocate temporary memory for strings: */
                    464:   szTempFileName = malloc(4 * FILENAME_MAX);
                    465:   if (!szTempFileName)
                    466:   {
                    467:     perror("File_FindPossibleExtFileName");
                    468:     return FALSE;
                    469:   }
                    470:   szSrcDir = szTempFileName + FILENAME_MAX;
                    471:   szSrcName = szSrcDir + FILENAME_MAX;
                    472:   szSrcExt = szSrcName + FILENAME_MAX;
1.1       root      473: 
1.1.1.3   root      474:   /* Split filename into parts */
                    475:   File_splitpath(pszFileName, szSrcDir, szSrcName, szSrcExt);
1.1       root      476: 
1.1.1.3   root      477:   /* Scan possible extensions */
1.1.1.8   root      478:   while(ppszExts[i] && !bFileExists)
                    479:   {
1.1.1.3   root      480:     /* Re-build with new file extension */
                    481:     File_makepath(szTempFileName, szSrcDir, szSrcName, ppszExts[i]);
                    482:     /* Does this file exist? */
1.1.1.8   root      483:     if (File_Exists(szTempFileName))
                    484:     {
1.1.1.3   root      485:       /* Copy name for return */
1.1.1.8   root      486:       strcpy(pszFileName, szTempFileName);
                    487:       bFileExists = TRUE;
1.1       root      488:     }
                    489: 
1.1.1.3   root      490:     /* Next one */
1.1       root      491:     i++;
                    492:   }
1.1.1.3   root      493: 
1.1.1.8   root      494:   free(szTempFileName);
                    495: 
                    496:   return bFileExists;
1.1       root      497: }
1.1.1.3   root      498: 
                    499: 
                    500: /*-----------------------------------------------------------------------*/
                    501: /*
                    502:   Split a complete filename into path, filename and extension.
                    503:   If pExt is NULL, don't split the extension from the file name!
                    504: */
1.1.1.8   root      505: void File_splitpath(const char *pSrcFileName, char *pDir, char *pName, char *pExt)
1.1.1.3   root      506: {
                    507:   char *ptr1, *ptr2;
                    508: 
                    509:   /* Build pathname: */
                    510:   ptr1 = strrchr(pSrcFileName, '/');
                    511:   if( ptr1 )
                    512:   {
                    513:     strcpy(pDir, pSrcFileName);
                    514:     strcpy(pName, ptr1+1);
                    515:     pDir[ptr1-pSrcFileName+1] = 0;
                    516:   }
                    517:   else
                    518:   {
                    519:     strcpy(pDir, "./");
                    520:     strcpy(pName, pSrcFileName);
                    521:   }
                    522: 
                    523:   /* Build the raw filename: */
                    524:   if( pExt!=NULL )
                    525:   {
                    526:     ptr2 = strrchr(pName+1, '.');
                    527:     if( ptr2 )
                    528:     {
                    529:       pName[ptr2-pName] = 0;
                    530:       /* Copy the file extension: */
                    531:       strcpy(pExt, ptr2+1);
                    532:     }
                    533:     else
                    534:       pExt[0] = 0;
                    535:    }
                    536: }
                    537: 
                    538: 
                    539: /*-----------------------------------------------------------------------*/
                    540: /*
                    541:   Build a complete filename from path, filename and extension.
                    542:   pExt can also be NULL.
                    543: */
1.1.1.8   root      544: void File_makepath(char *pDestFileName, const char *pDir, const char *pName, const char *pExt)
1.1.1.3   root      545: {
                    546:   strcpy(pDestFileName, pDir);
                    547:   if( strlen(pDestFileName)==0 )
                    548:     strcpy(pDestFileName, "./");
                    549:   if( pDestFileName[strlen(pDestFileName)-1]!='/' )
                    550:     strcat(pDestFileName, "/");
                    551: 
                    552:   strcat(pDestFileName, pName);
                    553: 
                    554:   if( pExt!=NULL )
                    555:   {
                    556:     if( strlen(pExt)>0 && pExt[0]!='.' )
                    557:       strcat(pDestFileName, ".");
                    558:     strcat(pDestFileName, pExt);
                    559:   }
                    560: }
                    561: 
                    562: 
                    563: /*-----------------------------------------------------------------------*/
                    564: /*
                    565:   Shrink a file name to a certain length and insert some dots if we cut
                    566:   something away (usefull for showing file names in a dialog).
                    567: */
                    568: void File_ShrinkName(char *pDestFileName, char *pSrcFileName, int maxlen)
                    569: {
                    570:   int srclen = strlen(pSrcFileName);
                    571:   if( srclen<maxlen )
                    572:     strcpy(pDestFileName, pSrcFileName);  /* It fits! */
                    573:   else
                    574:   {
                    575:     strncpy(pDestFileName, pSrcFileName, maxlen/2);
                    576:     if(maxlen&1)  /* even or uneven? */
                    577:       pDestFileName[maxlen/2-1] = 0;
                    578:     else
                    579:       pDestFileName[maxlen/2-2] = 0;
                    580:     strcat(pDestFileName, "...");
                    581:     strcat(pDestFileName, &pSrcFileName[strlen(pSrcFileName)-maxlen/2+1]);
                    582:   }
                    583: }
                    584: 
1.1.1.6   root      585: 
                    586: /*-----------------------------------------------------------------------*/
                    587: /*
                    588:   Create a clean absolute file name from a (possibly) relative file name.
                    589:   I.e. filter out all occurancies of "./" and "../".
                    590:   pFileName needs to point to a buffer of at least FILENAME_MAX bytes.
                    591: */
                    592: void File_MakeAbsoluteName(char *pFileName)
                    593: {
1.1.1.8   root      594:   char *pTempName;
1.1.1.6   root      595:   int inpos, outpos;
                    596: 
                    597:   inpos = 0;
1.1.1.8   root      598:   pTempName = malloc(FILENAME_MAX);
                    599:   if (!pTempName)
                    600:   {
                    601:     perror("File_MakeAbsoluteName - malloc");
                    602:        return;
                    603:   }
1.1.1.6   root      604: 
                    605:   /* Is it already an absolute name? */
                    606:   if(pFileName[0] == '/')
                    607:   {
                    608:     outpos = 0;
                    609:   }
                    610:   else
                    611:   {
1.1.1.8   root      612:     if (!getcwd(pTempName, FILENAME_MAX))
                    613:     {
                    614:       perror("File_MakeAbsoluteName - getcwd");
                    615:       free(pTempName);
                    616:          return;
                    617:     }
1.1.1.6   root      618:     File_AddSlashToEndFileName(pTempName);
                    619:     outpos = strlen(pTempName);
                    620:   }
                    621: 
                    622:   /* Now filter out the relative paths "./" and "../" */
                    623:   while (pFileName[inpos] != 0 && outpos < FILENAME_MAX)
                    624:   {
                    625:     if (pFileName[inpos] == '.' && pFileName[inpos+1] == '/')
                    626:     {
                    627:       /* Ignore "./" */
                    628:       inpos += 2;
                    629:     }
                    630:     else if (pFileName[inpos] == '.' && pFileName[inpos+1] == '.' && pFileName[inpos+2] == '/')
                    631:     {
                    632:       /* Handle "../" */
                    633:       char *pSlashPos;
                    634:       inpos += 3;
                    635:       pTempName[outpos - 1] = 0;
                    636:       pSlashPos = strrchr(pTempName, '/');
                    637:       if (pSlashPos)
                    638:       {
                    639:         *(pSlashPos + 1) = 0;
                    640:         outpos = strlen(pTempName);
                    641:       }
                    642:       else
                    643:       {
                    644:         pTempName[0] = '/';
                    645:         outpos = 1;
                    646:       }
                    647:     }
                    648:     else
                    649:     {
                    650:       /* Copy until next slash or end of input string */
                    651:       while (pFileName[inpos] != 0 && outpos < FILENAME_MAX)
                    652:       {
                    653:         pTempName[outpos++] = pFileName[inpos++];
                    654:         if (pFileName[inpos - 1] == '/')  break;
                    655:       }
                    656:     }
                    657:   }
                    658: 
                    659:   pTempName[outpos] = 0;
                    660: 
                    661:   strcpy(pFileName, pTempName);          /* Copy back */
1.1.1.8   root      662:   free(pTempName);
                    663: }
                    664: 
                    665: 
                    666: /*-----------------------------------------------------------------------*/
                    667: /*
                    668:   Create a valid path name from a possibly invalid name by erasing invalid
                    669:   path parts at the end of the string.
                    670:   pPathName needs to point to a buffer of at least FILENAME_MAX bytes.
                    671: */
                    672: void File_MakeValidPathName(char *pPathName)
                    673: {
                    674:   struct stat dirstat;
                    675:   char *pLastSlash;
                    676: 
                    677:   do
                    678:   {
                    679:     /* Check for a valid path */
                    680:     if (stat(pPathName, &dirstat) == 0 && S_ISDIR(dirstat.st_mode))
                    681:     {
                    682:       break;
                    683:     }
                    684: 
                    685:     pLastSlash = strrchr(pPathName, '/');
                    686:     if (pLastSlash)
                    687:     {
                    688:       /* Erase the (probably invalid) part after the last slash */
                    689:       *pLastSlash = 0;
                    690:     }
                    691:     else
                    692:     {
                    693:       /* Path name seems to be completely invalid -> set to root directory */
                    694:       strcpy(pPathName, "/");
                    695:     }
                    696:   }
                    697:   while (pLastSlash);
1.1.1.6   root      698: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.