Annotation of previous_trunk/src/file.c, revision 1.1

1.1     ! root        1: /*
        !             2:   Hatari - file.c
        !             3: 
        !             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: 
        !             7:   Common file access functions.
        !             8: */
        !             9: const char File_fileid[] = "Hatari file.c : " __DATE__ " " __TIME__;
        !            10: 
        !            11: #include <sys/types.h>
        !            12: #include <sys/stat.h>
        !            13: #include <sys/time.h>
        !            14: #include <fcntl.h>
        !            15: #include <unistd.h>
        !            16: #include <assert.h>
        !            17: #include <errno.h>
        !            18: #include <zlib.h>
        !            19: 
        !            20: #if defined(WIN32) && !defined(_VCWIN_)
        !            21: #include <winsock2.h>
        !            22: #endif
        !            23: 
        !            24: #include "main.h"
        !            25: #include "dialog.h"
        !            26: #include "file.h"
        !            27: #include "createBlankImage.h"
        !            28: #include "str.h"
        !            29: #include "zip.h"
        !            30: 
        !            31: #if defined(WIN32)
        !            32: #define ftello ftell
        !            33: #endif
        !            34: 
        !            35: /*-----------------------------------------------------------------------*/
        !            36: /**
        !            37:  * Remove any '/'s from end of filenames, but keeps / intact
        !            38:  */
        !            39: void File_CleanFileName(char *pszFileName)
        !            40: {
        !            41:        int len;
        !            42: 
        !            43:        len = strlen(pszFileName);
        !            44: 
        !            45:        /* Remove end slashes from filename! But / remains! Doh! */
        !            46:        while (len > 2 && pszFileName[--len] == PATHSEP)
        !            47:                pszFileName[len] = '\0';
        !            48: }
        !            49: 
        !            50: 
        !            51: /*-----------------------------------------------------------------------*/
        !            52: /**
        !            53:  * Add '/' to end of filename
        !            54:  */
        !            55: void File_AddSlashToEndFileName(char *pszFileName)
        !            56: {
        !            57:        int len;
        !            58: 
        !            59:        len = strlen(pszFileName);
        !            60: 
        !            61:        /* Check dir/filenames */
        !            62:        if (len != 0)
        !            63:        {
        !            64:                if (pszFileName[len-1] != PATHSEP)
        !            65:                {
        !            66:                        pszFileName[len] = PATHSEP; /* Must use end slash */
        !            67:                        pszFileName[len+1] = '\0';
        !            68:                }
        !            69:        }
        !            70: }
        !            71: 
        !            72: 
        !            73: /*-----------------------------------------------------------------------*/
        !            74: /**
        !            75:  * Does filename extension match? If so, return TRUE
        !            76:  */
        !            77: bool File_DoesFileExtensionMatch(const char *pszFileName, const char *pszExtension)
        !            78: {
        !            79:        if (strlen(pszFileName) < strlen(pszExtension))
        !            80:                return false;
        !            81:        /* Is matching extension? */
        !            82:        if (!strcasecmp(&pszFileName[strlen(pszFileName)-strlen(pszExtension)], pszExtension))
        !            83:                return true;
        !            84: 
        !            85:        /* No */
        !            86:        return false;
        !            87: }
        !            88: 
        !            89: 
        !            90: /*-----------------------------------------------------------------------*/
        !            91: /**
        !            92:  * Check if filename is from root
        !            93:  *
        !            94:  * Return TRUE if filename is '/', else give FALSE
        !            95:  */
        !            96: static bool File_IsRootFileName(const char *pszFileName)
        !            97: {
        !            98:        if (pszFileName[0] == '\0')     /* If NULL string return! */
        !            99:                return false;
        !           100: 
        !           101:        if (pszFileName[0] == PATHSEP)
        !           102:                return true;
        !           103: 
        !           104: #ifdef WIN32
        !           105:        if (pszFileName[1] == ':')
        !           106:                return true;
        !           107: #endif
        !           108: 
        !           109: #ifdef GEKKO
        !           110:        if (strlen(pszFileName) > 2 && pszFileName[2] == ':')   // sd:
        !           111:                return true;
        !           112:        if (strlen(pszFileName) > 3 && pszFileName[3] == ':')   // fat:
        !           113:                return true;
        !           114:        if (strlen(pszFileName) > 4 && pszFileName[4] == ':')   // fat3:
        !           115:                return true;
        !           116: #endif
        !           117: 
        !           118:        return false;
        !           119: }
        !           120: 
        !           121: 
        !           122: /*-----------------------------------------------------------------------*/
        !           123: /**
        !           124:  * Return string, to remove 'C:' part of filename
        !           125:  */
        !           126: const char *File_RemoveFileNameDrive(const char *pszFileName)
        !           127: {
        !           128:        if ( (pszFileName[0] != '\0') && (pszFileName[1] == ':') )
        !           129:                return &pszFileName[2];
        !           130:        else
        !           131:                return pszFileName;
        !           132: }
        !           133: 
        !           134: 
        !           135: /*-----------------------------------------------------------------------*/
        !           136: /**
        !           137:  * Check if filename end with a '/'
        !           138:  *
        !           139:  * Return TRUE if filename ends with '/'
        !           140:  */
        !           141: bool File_DoesFileNameEndWithSlash(char *pszFileName)
        !           142: {
        !           143:        if (pszFileName[0] == '\0')    /* If NULL string return! */
        !           144:                return false;
        !           145: 
        !           146:        /* Does string end in a '/'? */
        !           147:        if (pszFileName[strlen(pszFileName)-1] == PATHSEP)
        !           148:                return true;
        !           149: 
        !           150:        return false;
        !           151: }
        !           152: 
        !           153: 
        !           154: /*-----------------------------------------------------------------------*/
        !           155: /**
        !           156:  * Read file from disk into allocated buffer and return the buffer
        !           157:  * or NULL for error.  If pFileSize is non-NULL, read file size
        !           158:  * is set to that.
        !           159:  */
        !           160: Uint8 *File_Load(const char *pszFileName, long *pFileSize, const char * const ppszExts[])
        !           161: {
        !           162:        char *filepath = NULL;
        !           163:        Uint8 *pFile = NULL;
        !           164:        long FileSize = 0;
        !           165: 
        !           166:        /* Does the file exist? If not, see if can scan for other extensions and try these */
        !           167:        if (!File_Exists(pszFileName) && ppszExts)
        !           168:        {
        !           169:                /* Try other extensions, if succeeds, returns correct one */
        !           170:                filepath = File_FindPossibleExtFileName(pszFileName, ppszExts);
        !           171:        }
        !           172:        if (!filepath)
        !           173:                filepath = strdup(pszFileName);
        !           174: 
        !           175:        /* Is it a gzipped file? */
        !           176:        if (File_DoesFileExtensionMatch(filepath, ".gz"))
        !           177:        {
        !           178:                gzFile hGzFile;
        !           179:                /* Open and read gzipped file */
        !           180:                hGzFile = gzopen(filepath, "rb");
        !           181:                if (hGzFile != NULL)
        !           182:                {
        !           183:                        /* Find size of file: */
        !           184:                        do
        !           185:                        {
        !           186:                                /* Seek through the file until we hit the end... */
        !           187:                                gzseek(hGzFile, 1024, SEEK_CUR);
        !           188:                        }
        !           189:                        while (!gzeof(hGzFile));
        !           190:                        FileSize = gztell(hGzFile);
        !           191:                        gzrewind(hGzFile);
        !           192:                        /* Read in... */
        !           193:                        pFile = malloc(FileSize);
        !           194:                        if (pFile)
        !           195:                                FileSize = gzread(hGzFile, pFile, FileSize);
        !           196: 
        !           197:                        gzclose(hGzFile);
        !           198:                }
        !           199:        }
        !           200:        else if (File_DoesFileExtensionMatch(filepath, ".zip"))
        !           201:        {
        !           202:                /* It is a .ZIP file! -> Try to load the first file in the archive */
        !           203:                pFile = ZIP_ReadFirstFile(filepath, &FileSize, ppszExts);
        !           204:        }
        !           205:        else          /* It is a normal file */
        !           206:        {
        !           207:                FILE *hDiskFile;
        !           208:                /* Open and read normal file */
        !           209:                hDiskFile = fopen(filepath, "rb");
        !           210:                if (hDiskFile != NULL)
        !           211:                {
        !           212:                        /* Find size of file: */
        !           213:                        fseek(hDiskFile, 0, SEEK_END);
        !           214:                        FileSize = ftell(hDiskFile);
        !           215:                        fseek(hDiskFile, 0, SEEK_SET);
        !           216:                        /* Read in... */
        !           217:                        pFile = malloc(FileSize);
        !           218:                        if (pFile)
        !           219:                                FileSize = fread(pFile, 1, FileSize, hDiskFile);
        !           220: 
        !           221:                        fclose(hDiskFile);
        !           222:                }
        !           223:        }
        !           224:        free(filepath);
        !           225: 
        !           226:        /* Store size of file we read in (or 0 if failed) */
        !           227:        if (pFileSize)
        !           228:                *pFileSize = FileSize;
        !           229: 
        !           230:        return pFile;        /* Return to where read in/allocated */
        !           231: }
        !           232: 
        !           233: 
        !           234: /*-----------------------------------------------------------------------*/
        !           235: /**
        !           236:  * Save file to disk, return FALSE if errors
        !           237:  */
        !           238: bool File_Save(const char *pszFileName, const Uint8 *pAddress, size_t Size, bool bQueryOverwrite)
        !           239: {
        !           240:        bool bRet = false;
        !           241: 
        !           242:        /* Check if need to ask user if to overwrite */
        !           243:        if (bQueryOverwrite)
        !           244:        {
        !           245:                /* If file exists, ask if OK to overwrite */
        !           246:                if (!File_QueryOverwrite(pszFileName))
        !           247:                        return false;
        !           248:        }
        !           249: 
        !           250:        /* Normal file or gzipped file? */
        !           251:        if (File_DoesFileExtensionMatch(pszFileName, ".gz"))
        !           252:        {
        !           253:                gzFile hGzFile;
        !           254:                /* Create a gzipped file: */
        !           255:                hGzFile = gzopen(pszFileName, "wb");
        !           256:                if (hGzFile != NULL)
        !           257:                {
        !           258:                        /* Write data, set success flag */
        !           259:                        if (gzwrite(hGzFile, pAddress, Size) == (int)Size)
        !           260:                                bRet = true;
        !           261: 
        !           262:                        gzclose(hGzFile);
        !           263:                }
        !           264:        }
        !           265:        else
        !           266:        {
        !           267:                FILE *hDiskFile;
        !           268:                /* Create a normal file: */
        !           269:                hDiskFile = fopen(pszFileName, "wb");
        !           270:                if (hDiskFile != NULL)
        !           271:                {
        !           272:                        /* Write data, set success flag */
        !           273:                        if (fwrite(pAddress, 1, Size, hDiskFile) == Size)
        !           274:                                bRet = true;
        !           275: 
        !           276:                        fclose(hDiskFile);
        !           277:                }
        !           278:        }
        !           279: 
        !           280:        return bRet;
        !           281: }
        !           282: 
        !           283: 
        !           284: /*-----------------------------------------------------------------------*/
        !           285: /**
        !           286:  * Return size of file, -1 if error
        !           287:  */
        !           288: off_t File_Length(const char *pszFileName)
        !           289: {
        !           290:        FILE *hDiskFile;
        !           291:        off_t FileSize;
        !           292: 
        !           293:        hDiskFile = fopen(pszFileName, "rb");
        !           294:        if (hDiskFile!=NULL)
        !           295:        {
        !           296:                fseek(hDiskFile, 0, SEEK_END);
        !           297:                FileSize = ftello(hDiskFile);
        !           298:                fseek(hDiskFile, 0, SEEK_SET);
        !           299:                fclose(hDiskFile);
        !           300:                return FileSize;
        !           301:        }
        !           302: 
        !           303:        return -1;
        !           304: }
        !           305: 
        !           306: 
        !           307: /*-----------------------------------------------------------------------*/
        !           308: /**
        !           309:  * Return TRUE if file exists, is readable or writable at least and is not
        !           310:  * a directory.
        !           311:  */
        !           312: bool File_Exists(const char *filename)
        !           313: {
        !           314:        struct stat buf;
        !           315:        if (stat(filename, &buf) == 0 &&
        !           316:            (buf.st_mode & (S_IRUSR|S_IWUSR)) && !(buf.st_mode & S_IFDIR))
        !           317:        {
        !           318:                /* file points to user readable regular file */
        !           319:                return true;
        !           320:        }
        !           321:        return false;
        !           322: }
        !           323: 
        !           324: 
        !           325: /*-----------------------------------------------------------------------*/
        !           326: /**
        !           327:  * Return TRUE if directory exists.
        !           328:  */
        !           329: bool File_DirExists(const char *path)
        !           330: {
        !           331:        struct stat buf;
        !           332:     return (stat(path, &buf) == 0 && S_ISDIR(buf.st_mode));
        !           333: }
        !           334: 
        !           335: 
        !           336: /*-----------------------------------------------------------------------*/
        !           337: /**
        !           338:  * Find if file exists, and if so ask user if OK to overwrite
        !           339:  */
        !           340: bool File_QueryOverwrite(const char *pszFileName)
        !           341: {
        !           342:        const char *fmt;
        !           343:        char *szString;
        !           344:        bool ret = true;
        !           345: 
        !           346:        /* Try and find if file exists */
        !           347:        if (File_Exists(pszFileName))
        !           348:        {
        !           349:                fmt = "File '%s' exists, overwrite?";
        !           350:                /* File does exist, are we OK to overwrite? */
        !           351:                szString = malloc(strlen(pszFileName) + strlen(fmt) + 1);
        !           352:                sprintf(szString, fmt, pszFileName);
        !           353:                fprintf(stderr, "%s\n", szString);
        !           354:                ret = DlgAlert_Query(szString);
        !           355:                free(szString);
        !           356:        }
        !           357:        return ret;
        !           358: }
        !           359: 
        !           360: 
        !           361: /*-----------------------------------------------------------------------*/
        !           362: /**
        !           363:  * Try filename with various extensions and check if file exists
        !           364:  * - if so, return allocated string which caller should free,
        !           365:  *   otherwise return NULL
        !           366:  */
        !           367: char * File_FindPossibleExtFileName(const char *pszFileName, const char * const ppszExts[])
        !           368: {
        !           369:        char *szSrcDir, *szSrcName, *szSrcExt;
        !           370:        int i;
        !           371: 
        !           372:        /* Allocate temporary memory for strings: */
        !           373:        szSrcDir = malloc(3 * FILENAME_MAX);
        !           374:        if (!szSrcDir)
        !           375:        {
        !           376:                perror("File_FindPossibleExtFileName");
        !           377:                return false;
        !           378:        }
        !           379:        szSrcName = szSrcDir + FILENAME_MAX;
        !           380:        szSrcExt = szSrcName + FILENAME_MAX;
        !           381: 
        !           382:        /* Split filename into parts */
        !           383:        File_SplitPath(pszFileName, szSrcDir, szSrcName, szSrcExt);
        !           384: 
        !           385:        /* Scan possible extensions */
        !           386:        for (i = 0; ppszExts[i]; i++)
        !           387:        {
        !           388:                char *szTempFileName;
        !           389: 
        !           390:                /* Re-build with new file extension */
        !           391:                szTempFileName = File_MakePath(szSrcDir, szSrcName, ppszExts[i]);
        !           392:                if (szTempFileName)
        !           393:                {
        !           394:                        /* Does this file exist? */
        !           395:                        if (File_Exists(szTempFileName))
        !           396:                        {
        !           397:                                free(szSrcDir);
        !           398:                                /* return filename without extra strings */
        !           399:                                return szTempFileName;
        !           400:                        }
        !           401:                        free(szTempFileName);
        !           402:                }
        !           403:        }
        !           404:        free(szSrcDir);
        !           405:        return NULL;
        !           406: }
        !           407: 
        !           408: 
        !           409: /*-----------------------------------------------------------------------*/
        !           410: /**
        !           411:  * Split a complete filename into path, filename and extension.
        !           412:  * If pExt is NULL, don't split the extension from the file name!
        !           413:  * It's safe for pSrcFileName and pDir to be the same string.
        !           414:  */
        !           415: void File_SplitPath(const char *pSrcFileName, char *pDir, char *pName, char *pExt)
        !           416: {
        !           417:        char *ptr1, *ptr2;
        !           418: 
        !           419:        /* Build pathname: */
        !           420:        ptr1 = strrchr(pSrcFileName, PATHSEP);
        !           421:        if (ptr1)
        !           422:        {
        !           423:                strcpy(pName, ptr1+1);
        !           424:                memmove(pDir, pSrcFileName, ptr1-pSrcFileName);
        !           425:                pDir[ptr1-pSrcFileName] = 0;
        !           426:        }
        !           427:        else
        !           428:        {
        !           429:                strcpy(pName, pSrcFileName);
        !           430:                sprintf(pDir, ".%c", PATHSEP);
        !           431:        }
        !           432: 
        !           433:        /* Build the raw filename: */
        !           434:        if (pExt != NULL)
        !           435:        {
        !           436:                ptr2 = strrchr(pName+1, '.');
        !           437:                if (ptr2)
        !           438:                {
        !           439:                        pName[ptr2-pName] = 0;
        !           440:                        /* Copy the file extension: */
        !           441:                        strcpy(pExt, ptr2+1);
        !           442:                }
        !           443:                else
        !           444:                        pExt[0] = 0;
        !           445:        }
        !           446: }
        !           447: 
        !           448: 
        !           449: /*-----------------------------------------------------------------------*/
        !           450: /**
        !           451:  * Construct a complete filename from path, filename and extension.
        !           452:  * Return the constructed filename.
        !           453:  * pExt can also be NULL.
        !           454:  */
        !           455: char * File_MakePath(const char *pDir, const char *pName, const char *pExt)
        !           456: {
        !           457:        char *filepath;
        !           458:        int len;
        !           459: 
        !           460:        /* dir or "." + "/" + name + "." + ext + \0 */
        !           461:        len = strlen(pDir) + 2 + strlen(pName) + 1 + (pExt ? strlen(pExt) : 0) + 1;
        !           462:        filepath = malloc(len);
        !           463:        if (!filepath)
        !           464:        {
        !           465:                perror("File_MakePath");
        !           466:                return NULL;
        !           467:        }
        !           468:        if (!pDir[0])
        !           469:        {
        !           470:                filepath[0] = '.';
        !           471:                filepath[1] = '\0';
        !           472:        } else {
        !           473:                strcpy(filepath, pDir);
        !           474:        }
        !           475:        len = strlen(filepath);
        !           476:        if (filepath[len-1] != PATHSEP)
        !           477:        {
        !           478:                filepath[len++] = PATHSEP;
        !           479:        }
        !           480:        strcpy(&filepath[len], pName);
        !           481: 
        !           482:        if (pExt != NULL && pExt[0])
        !           483:        {
        !           484:                len += strlen(pName);
        !           485:                if (pExt[0] != '.')
        !           486:                        strcat(&filepath[len++], ".");
        !           487:                strcat(&filepath[len], pExt);
        !           488:        }
        !           489:        return filepath;
        !           490: }
        !           491: 
        !           492: 
        !           493: /*-----------------------------------------------------------------------*/
        !           494: /**
        !           495:  * Shrink a file name to a certain length and insert some dots if we cut
        !           496:  * something away (useful for showing file names in a dialog).
        !           497:  */
        !           498: void File_ShrinkName(char *pDestFileName, const char *pSrcFileName, int maxlen)
        !           499: {
        !           500:        int srclen = strlen(pSrcFileName);
        !           501:        if (srclen < maxlen)
        !           502:                strcpy(pDestFileName, pSrcFileName);  /* It fits! */
        !           503:        else
        !           504:        {
        !           505:                assert(maxlen > 6);
        !           506:                strncpy(pDestFileName, pSrcFileName, maxlen/2);
        !           507:                if (maxlen&1)  /* even or uneven? */
        !           508:                        pDestFileName[maxlen/2-1] = 0;
        !           509:                else
        !           510:                        pDestFileName[maxlen/2-2] = 0;
        !           511:                strcat(pDestFileName, "...");
        !           512:                strcat(pDestFileName, &pSrcFileName[strlen(pSrcFileName)-maxlen/2+1]);
        !           513:        }
        !           514: }
        !           515: 
        !           516: 
        !           517: /*-----------------------------------------------------------------------*/
        !           518: /**
        !           519:  * Open given filename in given mode and handle "stdout" & "stderr"
        !           520:  * filenames specially. Return FILE* to the opened file or NULL on error.
        !           521:  */
        !           522: FILE *File_Open(const char *path, const char *mode)
        !           523: {
        !           524:        int wr = 0, rd = 0;
        !           525:        FILE *fp;
        !           526: 
        !           527:        /* empty name signifies file that shouldn't be opened/enabled */
        !           528:        if (!*path)
        !           529:                return NULL;
        !           530: 
        !           531:        /* special "stdout" and "stderr" files can be used
        !           532:         * for files which are written or appended
        !           533:         */
        !           534:        if (strchr(mode, 'w') || strchr(mode, 'a'))
        !           535:                wr = 1;
        !           536:        if (strchr(mode, 'r'))
        !           537:                rd = 1;
        !           538:        if (strcmp(path, "stdin") == 0)
        !           539:        {
        !           540:                assert(rd && !wr);
        !           541:                return stdin;
        !           542:        }
        !           543:        if (strcmp(path, "stdout") == 0)
        !           544:        {
        !           545:                assert(wr && !rd);
        !           546:                return stdout;
        !           547:        }
        !           548:        if (strcmp(path, "stderr") == 0)
        !           549:        {
        !           550:                assert(wr && !rd);
        !           551:                return stderr;
        !           552:        }
        !           553:        /* Open a normal log file */
        !           554:        fp = fopen(path, mode);
        !           555:        if (!fp)
        !           556:         fprintf(stderr, "Can't open file '%s' (wr=%i, rd=%i):\n  %s\n",
        !           557:                 path, wr, rd, strerror(errno));
        !           558:     
        !           559:     /* printf("'%s' opened in mode '%s'\n", path, mode, fp); */
        !           560:        return fp;
        !           561: }
        !           562: 
        !           563: 
        !           564: /*-----------------------------------------------------------------------*/
        !           565: /**
        !           566:  * Close given FILE pointer and return the closed pointer
        !           567:  * as NULL for the idiom "fp = File_Close(fp);"
        !           568:  */
        !           569: FILE *File_Close(FILE *fp)
        !           570: {
        !           571:        if (fp && fp != stdin && fp != stdout && fp != stderr)
        !           572:        {
        !           573:                fclose(fp);
        !           574:        }
        !           575:        return NULL;
        !           576: }
        !           577: 
        !           578: 
        !           579: /*-----------------------------------------------------------------------*/
        !           580: /**
        !           581:  * Read data from given FILE pointer to buffer and return status
        !           582:  */
        !           583: bool File_Read(Uint8 *data, Uint32 size, Uint64 offset, FILE *fp)
        !           584: {
        !           585:     if (fseek(fp, offset, SEEK_SET))
        !           586:     {
        !           587:         fprintf(stderr, "File seek failed:\n  %s\n", strerror(errno));
        !           588:         return false;
        !           589:     }
        !           590:     if (fread(data, size, 1, fp) != 1)
        !           591:     {
        !           592:         fprintf(stderr, "Error occured while reading file.\n");
        !           593:         return false;
        !           594:     }
        !           595:     return true;
        !           596: }
        !           597: 
        !           598: 
        !           599: /*-----------------------------------------------------------------------*/
        !           600: /**
        !           601:  * Write data to given FILE pointer and return status
        !           602:  */
        !           603: bool File_Write(Uint8 *data, Uint32 size, Uint64 offset, FILE *fp)
        !           604: {
        !           605:     if (fseek(fp, offset, SEEK_SET))
        !           606:     {
        !           607:         fprintf(stderr, "File seek failed:\n  %s\n", strerror(errno));
        !           608:         return false;
        !           609:     }
        !           610:     if (fwrite(data, size, 1, fp) != 1)
        !           611:     {
        !           612:         fprintf(stderr, "Error occured while writing file.\n");
        !           613:         return false;
        !           614:     }
        !           615:     return true;
        !           616: }
        !           617: 
        !           618: 
        !           619: /*-----------------------------------------------------------------------*/
        !           620: /**
        !           621:  * Check if input is available at the specified file descriptor.
        !           622:  */
        !           623: bool File_InputAvailable(FILE *fp)
        !           624: {
        !           625: #if HAVE_SELECT
        !           626:        fd_set rfds;
        !           627:        struct timeval tv;
        !           628:        int fh;
        !           629:        int ret;
        !           630: 
        !           631:        if (!fp || (fh = fileno(fp)) == -1)
        !           632:                return false;
        !           633: 
        !           634:        /* Add the file handle to the file descriptor set */
        !           635:        FD_ZERO(&rfds);
        !           636:        FD_SET(fh, &rfds);
        !           637: 
        !           638:        /* Return immediately */
        !           639:        tv.tv_sec = 0;
        !           640:        tv.tv_usec = 0;
        !           641: 
        !           642:        /* Check if file descriptor is ready for a read */
        !           643:        ret = select(fh+1, &rfds, NULL, NULL, &tv);
        !           644: 
        !           645:        if (ret > 0)
        !           646:                return true;    /* Data available */
        !           647: #endif
        !           648: 
        !           649:        return false;
        !           650: }
        !           651: 
        !           652: 
        !           653: /*-----------------------------------------------------------------------*/
        !           654: /**
        !           655:  * Wrapper for File_MakeAbsoluteName() which special-cases stdin/out/err
        !           656:  * named files and empty file name.  The given buffer should be opened
        !           657:  * with File_Open() and closed with File_Close() if this function is used!
        !           658:  * (On Linux one can use /dev/stdout etc, this is intended for other OSes)
        !           659:  */
        !           660: void File_MakeAbsoluteSpecialName(char *path)
        !           661: {
        !           662:        if (path[0] &&
        !           663:            strcmp(path, "stdin")  != 0 &&
        !           664:            strcmp(path, "stdout") != 0 &&
        !           665:            strcmp(path, "stderr") != 0)
        !           666:                File_MakeAbsoluteName(path);
        !           667: }
        !           668: 
        !           669: /*-----------------------------------------------------------------------*/
        !           670: /**
        !           671:  * Create a clean absolute file name from a (possibly) relative file name.
        !           672:  * I.e. filter out all occurancies of "./" and "../".
        !           673:  * pFileName needs to point to a buffer of at least FILENAME_MAX bytes.
        !           674:  */
        !           675: void File_MakeAbsoluteName(char *pFileName)
        !           676: {
        !           677:        char *pTempName;
        !           678:        int inpos, outpos;
        !           679: 
        !           680:        inpos = 0;
        !           681:        pTempName = malloc(FILENAME_MAX);
        !           682:        if (!pTempName)
        !           683:        {
        !           684:                perror("File_MakeAbsoluteName - malloc");
        !           685:                return;
        !           686:        }
        !           687: 
        !           688:        /* Is it already an absolute name? */
        !           689:        if (File_IsRootFileName(pFileName))
        !           690:        {
        !           691:                outpos = 0;
        !           692:        }
        !           693:        else
        !           694:        {
        !           695:                if (!getcwd(pTempName, FILENAME_MAX))
        !           696:                {
        !           697:                        perror("File_MakeAbsoluteName - getcwd");
        !           698:                        free(pTempName);
        !           699:                        return;
        !           700:                }
        !           701:                File_AddSlashToEndFileName(pTempName);
        !           702:                outpos = strlen(pTempName);
        !           703:        }
        !           704: 
        !           705:        /* Now filter out the relative paths "./" and "../" */
        !           706:        while (pFileName[inpos] != 0 && outpos < FILENAME_MAX)
        !           707:        {
        !           708:                if (pFileName[inpos] == '.' && pFileName[inpos+1] == PATHSEP)
        !           709:                {
        !           710:                        /* Ignore "./" */
        !           711:                        inpos += 2;
        !           712:                }
        !           713:                else if (pFileName[inpos] == '.' && pFileName[inpos+1] == 0)
        !           714:                {
        !           715:                        inpos += 1;        /* Ignore "." at the end of the path string */
        !           716:                        if (outpos > 1)
        !           717:                                pTempName[outpos - 1] = 0;   /* Remove the last slash, too */
        !           718:                }
        !           719:                else if (pFileName[inpos] == '.' && pFileName[inpos+1] == '.'
        !           720:                         && (pFileName[inpos+2] == PATHSEP || pFileName[inpos+2] == 0))
        !           721:                {
        !           722:                        /* Handle "../" */
        !           723:                        char *pSlashPos;
        !           724:                        inpos += 2;
        !           725:                        pTempName[outpos - 1] = 0;
        !           726:                        pSlashPos = strrchr(pTempName, PATHSEP);
        !           727:                        if (pSlashPos)
        !           728:                        {
        !           729:                                *(pSlashPos + 1) = 0;
        !           730:                                outpos = strlen(pTempName);
        !           731:                        }
        !           732:                        else
        !           733:                        {
        !           734:                                pTempName[0] = PATHSEP;
        !           735:                                outpos = 1;
        !           736:                        }
        !           737:                        /* Were we already at the end of the string or is there more to come? */
        !           738:                        if (pFileName[inpos] == PATHSEP)
        !           739:                        {
        !           740:                                /* There was a slash after the '..', so skip slash and
        !           741:                                 * simply proceed with next part */
        !           742:                                inpos += 1;
        !           743:                        }
        !           744:                        else
        !           745:                        {
        !           746:                                /* We were at the end of the string, so let's remove the slash
        !           747:                                 * from the new string, too */
        !           748:                                if (outpos > 1)
        !           749:                                        pTempName[outpos - 1] = 0;
        !           750:                        }
        !           751:                }
        !           752:                else
        !           753:                {
        !           754:                        /* Copy until next slash or end of input string */
        !           755:                        while (pFileName[inpos] != 0 && outpos < FILENAME_MAX)
        !           756:                        {
        !           757:                                pTempName[outpos++] = pFileName[inpos++];
        !           758:                                if (pFileName[inpos - 1] == PATHSEP)
        !           759:                                        break;
        !           760:                        }
        !           761:                }
        !           762:        }
        !           763: 
        !           764:        pTempName[outpos] = 0;
        !           765: 
        !           766:        strcpy(pFileName, pTempName);          /* Copy back */
        !           767:        free(pTempName);
        !           768: }
        !           769: 
        !           770: 
        !           771: /*-----------------------------------------------------------------------*/
        !           772: /**
        !           773:  * Create a valid path name from a possibly invalid name by erasing invalid
        !           774:  * path parts at the end of the string.  If string doesn't contain any path
        !           775:  * component, it will be pointed to the root directory.  Empty string will
        !           776:  * be left as-is to prevent overwriting past allocated area.
        !           777:  */
        !           778: void File_MakeValidPathName(char *pPathName)
        !           779: {
        !           780:        struct stat dirstat;
        !           781:        char *pLastSlash;
        !           782: 
        !           783:        do
        !           784:        {
        !           785:                /* Check for a valid path */
        !           786:                if (stat(pPathName, &dirstat) == 0 && S_ISDIR(dirstat.st_mode))
        !           787:                {
        !           788:                        break;
        !           789:                }
        !           790: 
        !           791:                pLastSlash = strrchr(pPathName, PATHSEP);
        !           792:                if (pLastSlash)
        !           793:                {
        !           794:                        /* Erase the (probably invalid) part after the last slash */
        !           795:                        *pLastSlash = 0;
        !           796:                }
        !           797:                else
        !           798:                {
        !           799:                        if (pPathName[0])
        !           800:                        {
        !           801:                                /* point to root */
        !           802:                                pPathName[0] = PATHSEP;
        !           803:                                pPathName[1] = 0;
        !           804:                        }
        !           805:                        return;
        !           806:                }
        !           807:        }
        !           808:        while (pLastSlash);
        !           809: 
        !           810:        /* Make sure that path name ends with a slash */
        !           811:        File_AddSlashToEndFileName(pPathName);
        !           812: }
        !           813: 
        !           814: 
        !           815: /*-----------------------------------------------------------------------*/
        !           816: /**
        !           817:  * Remove given number of path elements from the end of the given path.
        !           818:  * Leaves '/' at the end if path still has directories. Given path
        !           819:  * may not be empty.
        !           820:  */
        !           821: void File_PathShorten(char *path, int dirs)
        !           822: {
        !           823:        int i, n = 0;
        !           824:        /* ignore last char, it may or may not be '/' */
        !           825:        i = strlen(path)-1;
        !           826:        assert(i >= 0);
        !           827:        while(i > 0 && n < dirs) {
        !           828:                if (path[--i] == PATHSEP)
        !           829:                        n++;
        !           830:        }
        !           831:        if (path[i] == PATHSEP) {
        !           832:                path[i+1] = '\0';
        !           833:        } else {
        !           834:                path[0] = PATHSEP;
        !           835:                path[1] = '\0';
        !           836:        }
        !           837: }
        !           838: 
        !           839: 
        !           840: /*-----------------------------------------------------------------------*/
        !           841: /*
        !           842:   If "/." or "/.." at end, remove that and in case of ".." remove
        !           843:   also preceding dir (go one dir up).  Leave '/' at the end of
        !           844:   the path.
        !           845: */
        !           846: void File_HandleDotDirs(char *path)
        !           847: {
        !           848:        int len = strlen(path);
        !           849:        if (len >= 2 &&
        !           850:            path[len-2] == PATHSEP &&
        !           851:            path[len-1] == '.')
        !           852:        {
        !           853:                /* keep in same dir */
        !           854:                path[len-1] = '\0';
        !           855:        }
        !           856:        else if (len >= 3 &&
        !           857:            path[len-3] == PATHSEP &&
        !           858:            path[len-2] == '.' &&
        !           859:            path[len-1] == '.')
        !           860:        {
        !           861:                /* go one dir up */
        !           862:                if (len == 3) {
        !           863:                        path[1] = 0;            /* already root */
        !           864:                } else {
        !           865:                        char *ptr;
        !           866:                        path[len-3] = 0;
        !           867:                        ptr = strrchr(path, PATHSEP);
        !           868:                        if (ptr)
        !           869:                                *(ptr+1) = 0;
        !           870:                }
        !           871:        }
        !           872: }

unix.superglobalmegacorp.com

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