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

1.1     ! root        1: /*
        !             2:   Hatari - zip.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:   Zipped disk support, uses zlib
        !             8: */
        !             9: const char ZIP_fileid[] = "Hatari zip.c : " __DATE__ " " __TIME__;
        !            10: 
        !            11: #include <stdio.h>
        !            12: #include <stdlib.h>
        !            13: #include <unistd.h>
        !            14: #include <dirent.h>
        !            15: #include <sys/types.h>
        !            16: #include <zlib.h>
        !            17: 
        !            18: #include "main.h"
        !            19: #include "file.h"
        !            20: #include "log.h"
        !            21: #include "str.h"
        !            22: #include "unzip.h"
        !            23: #include "zip.h"
        !            24: 
        !            25: #ifdef QNX
        !            26: #include <sys/dir.h>
        !            27: #define dirent direct
        !            28: #endif
        !            29: 
        !            30: /* #define SAVE_TO_ZIP_IMAGES */
        !            31: 
        !            32: #define ZIP_PATH_MAX  256
        !            33: 
        !            34: #define ZIP_FILE_ST   1
        !            35: #define ZIP_FILE_MSA  2
        !            36: #define ZIP_FILE_DIM  3
        !            37: 
        !            38: 
        !            39: /* Possible disk image extensions to scan for */
        !            40: static const char * const pszDiskNameExts[] =
        !            41: {
        !            42:   ".msa",
        !            43:   ".st",
        !            44:   ".dim",
        !            45:   NULL
        !            46: };
        !            47: 
        !            48: 
        !            49: /*-----------------------------------------------------------------------*/
        !            50: /**
        !            51:  * Does filename end with a .ZIP extension? If so, return true.
        !            52:  */
        !            53: bool ZIP_FileNameIsZIP(const char *pszFileName)
        !            54: {
        !            55:        return File_DoesFileExtensionMatch(pszFileName,".zip");
        !            56: }
        !            57: 
        !            58: 
        !            59: /*-----------------------------------------------------------------------*/
        !            60: /**
        !            61:  * Check if a file name contains a slash or backslash and return its position.
        !            62:  */
        !            63: static int Zip_FileNameHasSlash(const char *fn)
        !            64: {
        !            65:        int i=0;
        !            66: 
        !            67:        while (fn[i] != '\0')
        !            68:        {
        !            69:                if (fn[i] == '\\' || fn[i] == '/')
        !            70:                        return i;
        !            71:                i++;
        !            72:        }
        !            73:        return -1;
        !            74: }
        !            75: 
        !            76: 
        !            77: /*-----------------------------------------------------------------------*/
        !            78: /**
        !            79:  * Returns a list of files from a zip file. returns NULL on failure,
        !            80:  * returns a pointer to an array of strings if successful. Sets nfiles
        !            81:  * to the number of files.
        !            82:  */
        !            83: zip_dir *ZIP_GetFiles(const char *pszFileName)
        !            84: {
        !            85:        int nfiles;
        !            86:        unsigned int i;
        !            87:        unz_global_info gi;
        !            88:        int err;
        !            89:        unzFile uf;
        !            90:        char **filelist;
        !            91:        unz_file_info file_info;
        !            92:        char filename_inzip[ZIP_PATH_MAX];
        !            93:        zip_dir *zd;
        !            94: 
        !            95:        uf = unzOpen(pszFileName);
        !            96:        if (uf == NULL)
        !            97:        {
        !            98:                Log_Printf(LOG_ERROR, "ZIP_GetFiles: Cannot open %s\n", pszFileName);
        !            99:                return NULL;
        !           100:        }
        !           101: 
        !           102:        err = unzGetGlobalInfo(uf,&gi);
        !           103:        if (err != UNZ_OK)
        !           104:        {
        !           105:                Log_Printf(LOG_ERROR, "Error %d with zipfile in unzGetGlobalInfo \n",err);
        !           106:                return NULL;
        !           107:        }
        !           108: 
        !           109:        /* allocate a file list */
        !           110:        filelist = (char **)malloc(gi.number_entry*sizeof(char *));
        !           111:        if (!filelist)
        !           112:        {
        !           113:                perror("ZIP_GetFiles");
        !           114:                return NULL;
        !           115:        }
        !           116: 
        !           117:        nfiles = gi.number_entry;  /* set the number of files */
        !           118: 
        !           119:        for (i = 0; i < gi.number_entry; i++)
        !           120:        {
        !           121:                err = unzGetCurrentFileInfo(uf, &file_info, filename_inzip, ZIP_PATH_MAX, NULL, 0, NULL, 0);
        !           122:                if (err != UNZ_OK)
        !           123:                {
        !           124:                        free(filelist);
        !           125:                        return NULL;
        !           126:                }
        !           127: 
        !           128:                filelist[i] = (char *)malloc(strlen(filename_inzip) + 1);
        !           129:                if (!filelist[i])
        !           130:                {
        !           131:                        perror("ZIP_GetFiles");
        !           132:                        free(filelist);
        !           133:                        return NULL;
        !           134:                }
        !           135: 
        !           136:                strcpy(filelist[i], filename_inzip);
        !           137:                if ((i+1) < gi.number_entry)
        !           138:                {
        !           139:                        err = unzGoToNextFile(uf);
        !           140:                        if (err != UNZ_OK)
        !           141:                        {
        !           142:                                Log_Printf(LOG_ERROR, "ZIP_GetFiles: Error in ZIP-file\n");
        !           143:                                /* deallocate memory */
        !           144:                                for (; i > 0; i--)
        !           145:                                        free(filelist[i]);
        !           146:                                free(filelist);
        !           147:                                return NULL;
        !           148:                        }
        !           149:                }
        !           150:        }
        !           151: 
        !           152:        unzClose(uf);
        !           153: 
        !           154:        zd = (zip_dir *)malloc(sizeof(zip_dir));
        !           155:        if (!zd)
        !           156:        {
        !           157:                perror("ZIP_GetFiles");
        !           158:                free(filelist);
        !           159:                return NULL;
        !           160:        }
        !           161:        zd->names = filelist;
        !           162:        zd->nfiles = nfiles;
        !           163: 
        !           164:        return zd;
        !           165: }
        !           166: 
        !           167: 
        !           168: /*-----------------------------------------------------------------------*/
        !           169: /**
        !           170:  * Free the memory that has been allocated for a zip_dir.
        !           171:  */
        !           172: void ZIP_FreeZipDir(zip_dir *f_zd)
        !           173: {
        !           174:        while (f_zd->nfiles > 0)
        !           175:        {
        !           176:                f_zd->nfiles--;
        !           177:                free(f_zd->names[f_zd->nfiles]);
        !           178:                f_zd->names[f_zd->nfiles] = NULL;
        !           179:        }
        !           180:        free(f_zd->names);
        !           181:        f_zd->names = NULL;
        !           182:        free(f_zd);
        !           183: }
        !           184: 
        !           185: 
        !           186: /*-----------------------------------------------------------------------*/
        !           187: /**
        !           188:  * Free the memory that has been allocated for fentries.
        !           189:  */
        !           190: static void ZIP_FreeFentries(struct dirent **fentries, int entries)
        !           191: {
        !           192:        while (entries > 0)
        !           193:        {
        !           194:                entries--;
        !           195:                free(fentries[entries]);
        !           196:        }
        !           197:        free(fentries);
        !           198: }
        !           199: 
        !           200: 
        !           201: /*-----------------------------------------------------------------------*/
        !           202: /**
        !           203:  *   Returns a list of files from the directory (dir) in a zip file list (zip)
        !           204:  *   sets entries to the number of entries and returns a dirent structure, or
        !           205:  *   NULL on failure. NOTE: only f_name is set in the dirent structures. 
        !           206:  */
        !           207: struct dirent **ZIP_GetFilesDir(const zip_dir *zip, const char *dir, int *entries)
        !           208: {
        !           209:        int i,j;
        !           210:        zip_dir *files;
        !           211:        char *temp;
        !           212:        bool flag;
        !           213:        int slash;
        !           214:        struct dirent **fentries;
        !           215: 
        !           216:        files = (zip_dir *)malloc(sizeof(zip_dir));
        !           217:        if (!files)
        !           218:        {
        !           219:                perror("ZIP_GetFilesDir");
        !           220:                return NULL;
        !           221:        }
        !           222: 
        !           223:        files->names = (char **)malloc((zip->nfiles + 1) * sizeof(char *));
        !           224:        if (!files->names)
        !           225:        {
        !           226:                perror("ZIP_GetFilesDir");
        !           227:                free(files);
        !           228:                return NULL;
        !           229:        }
        !           230: 
        !           231:        /* add ".." directory */
        !           232:        files->nfiles = 1;
        !           233:        temp = (char *)malloc(4);
        !           234:        if (!temp)
        !           235:        {
        !           236:                ZIP_FreeZipDir(files);
        !           237:                return NULL;
        !           238:        }
        !           239:        temp[0] = temp[1] = '.';
        !           240:        temp[2] = '/';
        !           241:        temp[3] = '\0';
        !           242:        files->names[0] = temp;
        !           243: 
        !           244:        for (i = 0; i < zip->nfiles; i++)
        !           245:        {
        !           246:                if (strlen(zip->names[i]) > strlen(dir))
        !           247:                {
        !           248:                        if (strncasecmp(zip->names[i], dir, strlen(dir)) == 0)
        !           249:                        {
        !           250:                                temp = zip->names[i];
        !           251:                                temp = (char *)(temp + strlen(dir));
        !           252:                                if (temp[0] != '\0')
        !           253:                                {
        !           254:                                        if ((slash=Zip_FileNameHasSlash(temp)) > 0)
        !           255:                                        {
        !           256:                                                /* file is in a subdirectory, add this subdirectory if it doesn't exist in the list */
        !           257:                                                flag = false;
        !           258:                                                for (j = files->nfiles-1; j > 0; j--)
        !           259:                                                {
        !           260:                                                        if (strncasecmp(temp, files->names[j], slash+1) == 0)
        !           261:                                                                flag = true;
        !           262:                                                }
        !           263:                                                if (flag == false)
        !           264:                                                {
        !           265:                                                        files->names[files->nfiles] = (char *)malloc(slash+2);
        !           266:                                                        if (!files->names[files->nfiles])
        !           267:                                                        {
        !           268:                                                                perror("ZIP_GetFilesDir");
        !           269:                                                                ZIP_FreeZipDir(files);
        !           270:                                                                return NULL;
        !           271:                                                        }
        !           272:                                                        strncpy(files->names[files->nfiles], temp, slash+1);
        !           273:                                                        ((char *)files->names[files->nfiles])[slash+1] = '\0';
        !           274:                                                        files->nfiles++;
        !           275:                                                }
        !           276:                                        }
        !           277:                                        else
        !           278:                                        {
        !           279:                                                /* add a filename */
        !           280:                                                files->names[files->nfiles] = (char *)malloc(strlen(temp)+1);
        !           281:                                                if (!files->names[files->nfiles])
        !           282:                                                {
        !           283:                                                        perror("ZIP_GetFilesDir");
        !           284:                                                        ZIP_FreeZipDir(files);
        !           285:                                                        return NULL;
        !           286:                                                }
        !           287:                                                strncpy(files->names[files->nfiles], temp, strlen(temp));
        !           288:                                                ((char *)files->names[files->nfiles])[strlen(temp)] = '\0';
        !           289:                                                files->nfiles++;
        !           290:                                        }
        !           291:                                }
        !           292:                        }
        !           293:                }
        !           294:        }
        !           295: 
        !           296:        /* copy to a dirent structure */
        !           297:        *entries = files->nfiles;
        !           298:        fentries = (struct dirent **)malloc(sizeof(struct dirent *)*files->nfiles);
        !           299:        if (!fentries)
        !           300:        {
        !           301:                perror("ZIP_GetFilesDir");
        !           302:                ZIP_FreeZipDir(files);
        !           303:                return NULL;
        !           304:        }
        !           305:        for (i = 0; i < files->nfiles; i++)
        !           306:        {
        !           307:                fentries[i] = (struct dirent *)malloc(sizeof(struct dirent));
        !           308:                if (!fentries[i])
        !           309:                {
        !           310:                        perror("ZIP_GetFilesDir");
        !           311:                        ZIP_FreeFentries(fentries, i+1);
        !           312:                        return NULL;
        !           313:                }
        !           314:                strcpy(fentries[i]->d_name, files->names[i]);
        !           315:        }
        !           316: 
        !           317:        ZIP_FreeZipDir(files);
        !           318: 
        !           319:        return fentries;
        !           320: }
        !           321: 
        !           322: 
        !           323: /*-----------------------------------------------------------------------*/
        !           324: /**
        !           325:  * Check an image file in the archive, return the uncompressed length
        !           326:  */
        !           327: static long ZIP_CheckImageFile(unzFile uf, char *filename, int namelen, int *pDiskType)
        !           328: {
        !           329:        unz_file_info file_info;
        !           330: 
        !           331:        if (unzLocateFile(uf,filename, 0) != UNZ_OK)
        !           332:        {
        !           333:                Log_Printf(LOG_ERROR, "Error: File \"%s\" not found in the archive!\n", filename);
        !           334:                return -1;
        !           335:        }
        !           336: 
        !           337:        if (unzGetCurrentFileInfo(uf, &file_info, filename, namelen, NULL, 0, NULL, 0) != UNZ_OK)
        !           338:        {
        !           339:                Log_Printf(LOG_ERROR, "Error with zipfile in unzGetCurrentFileInfo\n");
        !           340:                return -1;
        !           341:        }
        !           342: 
        !           343:        Log_Printf(LOG_ERROR, "Not an .ST, .MSA or .DIM file.\n");
        !           344:        return 0;
        !           345: }
        !           346: 
        !           347: /*-----------------------------------------------------------------------*/
        !           348: /**
        !           349:  * Return the first matching file in a zip, or NULL on failure.
        !           350:  * String buffer size is ZIP_PATH_MAX
        !           351:  */
        !           352: static char *ZIP_FirstFile(const char *filename, const char * const ppsExts[])
        !           353: {
        !           354:        zip_dir *files;
        !           355:        int i, j;
        !           356:        char *name;
        !           357: 
        !           358:        files = ZIP_GetFiles(filename);
        !           359:        if (files == NULL)
        !           360:                return NULL;
        !           361: 
        !           362:        name = malloc(ZIP_PATH_MAX);
        !           363:        if (!name)
        !           364:        {
        !           365:                perror("ZIP_FirstFile");
        !           366:                return NULL;
        !           367:        }
        !           368: 
        !           369:        /* Do we have to scan for a certain extension? */
        !           370:        if (ppsExts)
        !           371:        {
        !           372:                name[0] = '\0';
        !           373:                for(i = files->nfiles-1; i >= 0; i--)
        !           374:                {
        !           375:                        for (j = 0; ppsExts[j] != NULL; j++)
        !           376:                        {
        !           377:                                if (File_DoesFileExtensionMatch(files->names[i], ppsExts[j]))
        !           378:                                {
        !           379:                                        strncpy(name, files->names[i], ZIP_PATH_MAX);
        !           380:                                        break;
        !           381:                                }
        !           382:                        }
        !           383:                }
        !           384:        }
        !           385:        else
        !           386:        {
        !           387:                /* There was no extension given -> use the very first name */
        !           388:                strncpy(name, files->names[0], ZIP_PATH_MAX);
        !           389:        }
        !           390: 
        !           391:        /* free the files */
        !           392:        ZIP_FreeZipDir(files);
        !           393: 
        !           394:        if (name[0] == '\0')
        !           395:                return NULL;
        !           396:        return name;
        !           397: }
        !           398: 
        !           399: 
        !           400: /*-----------------------------------------------------------------------*/
        !           401: /**
        !           402:  * Extract a file (filename) from a ZIP-file (uf), the number of 
        !           403:  * bytes to uncompress is size. Returns a pointer to a buffer containing
        !           404:  * the uncompressed data, or NULL.
        !           405:  */
        !           406: static void *ZIP_ExtractFile(unzFile uf, const char *filename, uLong size)
        !           407: {
        !           408:        int err = UNZ_OK;
        !           409:        char filename_inzip[ZIP_PATH_MAX];
        !           410:        void* buf;
        !           411:        uInt size_buf;
        !           412:        unz_file_info file_info;
        !           413: 
        !           414: 
        !           415:        if (unzLocateFile(uf,filename, 0) != UNZ_OK)
        !           416:        {
        !           417:                Log_Printf(LOG_ERROR, "ZIP_ExtractFile: could not find file in archive\n");
        !           418:                return NULL;
        !           419:        }
        !           420: 
        !           421:        err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
        !           422: 
        !           423:        if (err != UNZ_OK)
        !           424:        {
        !           425:                Log_Printf(LOG_ERROR, "ZIP_ExtractFile: could not get file info\n");
        !           426:                return NULL;
        !           427:        }
        !           428: 
        !           429:        size_buf = size;
        !           430:        buf = malloc(size_buf);
        !           431:        if (!buf)
        !           432:        {
        !           433:                perror("ZIP_ExtractFile");
        !           434:                return NULL;
        !           435:        }
        !           436: 
        !           437:        err = unzOpenCurrentFile(uf);
        !           438:        if (err != UNZ_OK)
        !           439:        {
        !           440:                Log_Printf(LOG_ERROR, "ZIP_ExtractFile: could not open file\n");
        !           441:                free(buf);
        !           442:                return NULL;
        !           443:        }
        !           444: 
        !           445:        do
        !           446:        {
        !           447:                err = unzReadCurrentFile(uf,buf,size_buf);
        !           448:                if (err < 0)
        !           449:                {
        !           450:                        Log_Printf(LOG_ERROR, "ZIP_ExtractFile: could not read file\n");
        !           451:                        return NULL;
        !           452:                }
        !           453:        }
        !           454:        while (err > 0);
        !           455: 
        !           456:        return buf;
        !           457: }
        !           458: 
        !           459: 
        !           460: /*-----------------------------------------------------------------------*/
        !           461: /**
        !           462:  * Load disk image from a .ZIP archive into memory, set  the number
        !           463:  * of bytes loaded into pImageSize and return the data or NULL on error.
        !           464:  */
        !           465: Uint8 *ZIP_ReadDisk(const char *pszFileName, const char *pszZipPath, long *pImageSize)
        !           466: {
        !           467:        uLong ImageSize=0;
        !           468:        unzFile uf=NULL;
        !           469:        Uint8 *buf;
        !           470:        char *path;
        !           471:        int nDiskType = -1;
        !           472:        Uint8 *pDiskBuffer = NULL;
        !           473: 
        !           474:        *pImageSize = 0;
        !           475: 
        !           476:        uf = unzOpen(pszFileName);
        !           477:        if (uf == NULL)
        !           478:        {
        !           479:                Log_Printf(LOG_ERROR, "Cannot open %s\n", pszFileName);
        !           480:                return NULL;
        !           481:        }
        !           482: 
        !           483:        if (pszZipPath == NULL || pszZipPath[0] == 0)
        !           484:        {
        !           485:                path = ZIP_FirstFile(pszFileName, pszDiskNameExts);
        !           486:                if (path == NULL)
        !           487:                {
        !           488:                        Log_Printf(LOG_ERROR, "Cannot open %s\n", pszFileName);
        !           489:                        unzClose(uf);
        !           490:                        return NULL;
        !           491:                }
        !           492:        }
        !           493:        else
        !           494:        {
        !           495:                path = malloc(ZIP_PATH_MAX);
        !           496:                if (path == NULL)
        !           497:                {
        !           498:                        perror("ZIP_ReadDisk");
        !           499:                        unzClose(uf);
        !           500:                        return NULL;
        !           501:                }
        !           502:                strncpy(path, pszZipPath, ZIP_PATH_MAX);
        !           503:                path[ZIP_PATH_MAX-1] = '\0';
        !           504:        }
        !           505: 
        !           506:        ImageSize = ZIP_CheckImageFile(uf, path, ZIP_PATH_MAX, &nDiskType);
        !           507:        if (ImageSize <= 0)
        !           508:        {
        !           509:                unzClose(uf);
        !           510:                free(path);
        !           511:                return NULL;
        !           512:        }
        !           513: 
        !           514:        /* extract to buf */
        !           515:        buf = ZIP_ExtractFile(uf, path, ImageSize);
        !           516: 
        !           517:        unzCloseCurrentFile(uf);
        !           518:        unzClose(uf);
        !           519:        free(path);
        !           520:        path = NULL;
        !           521: 
        !           522:        if (buf == NULL)
        !           523:        {
        !           524:                return NULL;  /* failed extraction, return error */
        !           525:        }
        !           526: 
        !           527:        switch(nDiskType) {
        !           528:        case ZIP_FILE_MSA:
        !           529:                /* uncompress the MSA file */
        !           530: //             pDiskBuffer = MSA_UnCompress(buf, (long *)&ImageSize);
        !           531:                free(buf);
        !           532:                buf = NULL;
        !           533:                break;
        !           534:        case ZIP_FILE_DIM:
        !           535:                /* Skip DIM header */
        !           536:                ImageSize -= 32;
        !           537:                memmove(buf, buf+32, ImageSize);
        !           538:                /* ...and passthrough */
        !           539:        case ZIP_FILE_ST:
        !           540:                /* ST image => return buffer directly */
        !           541:                pDiskBuffer = buf;
        !           542:                break;
        !           543:        }
        !           544:        
        !           545:        if (pDiskBuffer)
        !           546:        {
        !           547:                *pImageSize = ImageSize;
        !           548:        }
        !           549:        return pDiskBuffer;
        !           550: }
        !           551: 
        !           552: 
        !           553: /*-----------------------------------------------------------------------*/
        !           554: /**
        !           555:  * Save .ZIP file from memory buffer. Returns true if all is OK.
        !           556:  *
        !           557:  * Not yet implemented.
        !           558:  */
        !           559: bool ZIP_WriteDisk(const char *pszFileName,unsigned char *pBuffer,int ImageSize)
        !           560: {
        !           561:        return false;
        !           562: }
        !           563: 
        !           564: 
        !           565: /*-----------------------------------------------------------------------*/
        !           566: /**
        !           567:  * Load first file from a .ZIP archive into memory, and return the number
        !           568:  * of bytes loaded.
        !           569:  */
        !           570: Uint8 *ZIP_ReadFirstFile(const char *pszFileName, long *pImageSize, const char * const ppszExts[])
        !           571: {
        !           572:        unzFile uf=NULL;
        !           573:        Uint8 *pBuffer;
        !           574:        char *pszZipPath;
        !           575:        unz_file_info file_info;
        !           576: 
        !           577:        *pImageSize = 0;
        !           578: 
        !           579:        /* Open the ZIP file */
        !           580:        uf = unzOpen(pszFileName);
        !           581:        if (uf == NULL)
        !           582:        {
        !           583:                Log_Printf(LOG_ERROR, "Cannot open '%s'\n", pszFileName);
        !           584:                return NULL;
        !           585:        }
        !           586: 
        !           587:        /* Locate the first file in the ZIP archive */
        !           588:        pszZipPath = ZIP_FirstFile(pszFileName, ppszExts);
        !           589:        if (pszZipPath == NULL)
        !           590:        {
        !           591:                Log_Printf(LOG_ERROR, "Failed to locate first file in '%s'\n", pszFileName);
        !           592:                unzClose(uf);
        !           593:                return NULL;
        !           594:        }
        !           595: 
        !           596:        if (unzLocateFile(uf, pszZipPath, 0) != UNZ_OK)
        !           597:        {
        !           598:                Log_Printf(LOG_ERROR, "Error: Can not locate '%s' in the archive!\n", pszZipPath);
        !           599:                free(pszZipPath);
        !           600:                return NULL;
        !           601:        }
        !           602: 
        !           603:        /* Get file information (file size!) */
        !           604:        if (unzGetCurrentFileInfo(uf, &file_info, pszZipPath, ZIP_PATH_MAX, NULL, 0, NULL, 0) != UNZ_OK)
        !           605:        {
        !           606:                Log_Printf(LOG_ERROR, "Error with zipfile in unzGetCurrentFileInfo.\n");
        !           607:                free(pszZipPath);
        !           608:                return NULL;
        !           609:        }
        !           610: 
        !           611:        /* Extract to buffer */
        !           612:        pBuffer = ZIP_ExtractFile(uf, pszZipPath, file_info.uncompressed_size);
        !           613: 
        !           614:        /* And close the file */
        !           615:        unzCloseCurrentFile(uf);
        !           616:        unzClose(uf);
        !           617: 
        !           618:        free(pszZipPath);
        !           619: 
        !           620:        if (pBuffer)
        !           621:                *pImageSize = file_info.uncompressed_size;
        !           622: 
        !           623:        return pBuffer;
        !           624: }

unix.superglobalmegacorp.com

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