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

1.1     ! root        1: /*
        !             2:   Hatari
        !             3: 
        !             4:   Zipped disc support, uses zlib
        !             5: */
        !             6: 
        !             7: #include <stdio.h>
        !             8: #include <stdlib.h>
        !             9: #include <string.h>
        !            10: #include <unistd.h>
        !            11: #include <dirent.h>
        !            12: 
        !            13: #include "zlib.h"
        !            14: #include "main.h"
        !            15: #include "msa.h"
        !            16: #include "floppy.h"
        !            17: #include "file.h"
        !            18: #include "errlog.h"
        !            19: #include "unzip.h"
        !            20: #include "zip.h"
        !            21: #include "memAlloc.h"
        !            22: 
        !            23: #define SAVE_TO_GZIP_IMAGES
        !            24: /* #define SAVE_TO_ZIP_IMAGES */
        !            25: 
        !            26: #define ZIP_PATH_MAX  256
        !            27: 
        !            28: #define ZIP_FILE_ST   1
        !            29: #define ZIP_FILE_MSA  2
        !            30: 
        !            31: 
        !            32: int Zip_FileNameHasSlash(char *fn)
        !            33: {
        !            34:   int i=0;
        !            35:   while( fn[i] != '\0' )
        !            36:     {
        !            37:       if( fn[i] == '\\' || fn[i] == '/') return( i );
        !            38:       i++;
        !            39:     }  
        !            40:   return( -1 );
        !            41: }
        !            42: 
        !            43: /*-----------------------------------------------------------------------*/
        !            44: /*
        !            45:     Returns a list of files from a zip file. returns NULL on failure,
        !            46:     returns a pointer to an array of strings if successful. Sets nfiles
        !            47:     to the number of files.
        !            48: */
        !            49: zip_dir *ZIP_GetFiles(char *pszFileName)
        !            50: {
        !            51:   int nfiles;
        !            52:   int i;
        !            53:   unz_global_info gi;
        !            54:   int err;
        !            55:   unzFile uf;
        !            56:   char **filelist;
        !            57:   unz_file_info file_info;
        !            58:   char filename_inzip[ZIP_PATH_MAX];
        !            59:   zip_dir *zd; 
        !            60: 
        !            61:   uf = unzOpen(pszFileName);
        !            62:   if (uf==NULL)
        !            63:     {
        !            64:       printf("Cannot open %s\n", pszFileName);
        !            65:       return(0);
        !            66:     }
        !            67: 
        !            68:   err = unzGetGlobalInfo (uf,&gi);
        !            69:   if (err!=UNZ_OK){
        !            70:     printf("error %d with zipfile in unzGetGlobalInfo \n",err);
        !            71:     return(NULL);
        !            72:   }
        !            73:   
        !            74:   /* allocate a file list */
        !            75:   filelist = (char **)Memory_Alloc(gi.number_entry*sizeof(char *));
        !            76:   nfiles = gi.number_entry;  /* set the number of files */
        !            77:   
        !            78:   for(i=0;i<gi.number_entry;i++)
        !            79:     {
        !            80:       err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip, ZIP_PATH_MAX,NULL,0,NULL,0);
        !            81:       if (err!=UNZ_OK)
        !            82:        {
        !            83:          Memory_Free(filelist);
        !            84:          return(NULL);
        !            85:        }
        !            86:       filelist[i] = (char *)Memory_Alloc(strlen(filename_inzip) + 1);
        !            87:       strcpy(filelist[i], filename_inzip);
        !            88:       if ((i+1)<gi.number_entry)
        !            89:        {
        !            90:          err = unzGoToNextFile(uf);
        !            91:          if (err!=UNZ_OK)
        !            92:            {
        !            93:              ErrLog_File("ERROR ZIP_GetFiles with zipfile\n");
        !            94:              /* deallocate memory */
        !            95:              for(;i>0;i--)Memory_Free(filelist[i]);
        !            96:              Memory_Free(filelist);
        !            97:              return(NULL);
        !            98:            }
        !            99:        }
        !           100:     }
        !           101: 
        !           102:   zd = (zip_dir *)Memory_Alloc(sizeof(zip_dir));
        !           103:   zd->names = filelist;
        !           104:   zd->nfiles = nfiles;
        !           105:   return( zd );
        !           106: }
        !           107: 
        !           108: /*-----------------------------------------------------------------------*/
        !           109: /*
        !           110:     Returns a list of files from the directory (dir) in a zip file list (zip)
        !           111:     sets entries to the number of entries and returns a dirent structure, or
        !           112:     NULL on failure. NOTE: only f_name is set in the dirent structures. 
        !           113: */
        !           114: struct dirent **ZIP_GetFilesDir(zip_dir *zip, char *dir, int *entries)
        !           115: {
        !           116:   int i,j;
        !           117:   zip_dir *files; 
        !           118:   char *temp;
        !           119:   BOOL flag;
        !           120:   int slash;
        !           121:   struct dirent **fentries;
        !           122: 
        !           123:   files = (zip_dir *)Memory_Alloc(sizeof(zip_dir));
        !           124:   files->names = (char **)Memory_Alloc(zip->nfiles * sizeof(char *));
        !           125: 
        !           126:   /* add ".." directory */
        !           127:   files->nfiles = 1;
        !           128:   temp = (char *)Memory_Alloc(4);
        !           129:   temp[0] = temp[1] = '.'; 
        !           130:   temp[2] = '/'; temp[3] = '\0';
        !           131:   files->names[0] = temp;
        !           132:   
        !           133:   for(i=0;i<zip->nfiles;i++)
        !           134:     {
        !           135:       if(strlen(zip->names[i]) > strlen(dir))
        !           136:        {
        !           137:          if(strncasecmp(zip->names[i], dir, strlen(dir)) == 0)
        !           138:            {
        !           139:              temp = zip->names[i];
        !           140:              temp = (char *)(temp + strlen(dir));
        !           141:              if( temp[0] != '\0')
        !           142:                {
        !           143:                  if( (slash=Zip_FileNameHasSlash(temp)) > 0)
        !           144:                    {
        !           145:                      /* file is in a subdirectory, add this subdirectory if it doesn't exist in the list */
        !           146:                      flag = FALSE;
        !           147:                      for(j = files->nfiles-1;j>0;j--)
        !           148:                          if(strncasecmp(temp, files->names[j], slash+1) == 0)
        !           149:                            flag=TRUE;
        !           150:                      if( flag == FALSE )
        !           151:                        {
        !           152:                          files->names[files->nfiles] = (char *)Memory_Alloc(slash+1);
        !           153:                          strncpy(files->names[files->nfiles], temp, slash+1);
        !           154:                          ((char *)files->names[files->nfiles])[slash+1] = '\0';
        !           155:                          files->nfiles++;
        !           156:                        }
        !           157:                    } 
        !           158:                  else 
        !           159:                    {
        !           160:                      /* add a filename */
        !           161:                      files->names[files->nfiles] = (char *)Memory_Alloc(strlen(temp)+1);
        !           162:                      strncpy(files->names[files->nfiles], temp, strlen(temp));
        !           163:                      ((char *)files->names[files->nfiles])[strlen(temp)] = '\0';
        !           164:                      files->nfiles++;
        !           165:                    }
        !           166:                }
        !           167:            }
        !           168:        }
        !           169:     }
        !           170: 
        !           171:   /* copy to a dirent structure */
        !           172:   *entries = files->nfiles;
        !           173:   fentries = (struct dirent **)Memory_Alloc(sizeof(struct dirent *)*files->nfiles);
        !           174:   for(i=0; i<files->nfiles; i++)
        !           175:     {
        !           176:       fentries[i] = (struct dirent *)Memory_Alloc(sizeof(struct dirent));
        !           177:       strcpy(fentries[i]->d_name, files->names[i]);
        !           178:       Memory_Free(files->names[i]);
        !           179:     }
        !           180:   Memory_Free(files);
        !           181:   return(fentries);
        !           182: }
        !           183: 
        !           184: /*-----------------------------------------------------------------------*/
        !           185: /*
        !           186:   Check an image file in the archive, return the uncompressed length
        !           187: */
        !           188: long ZIP_CheckImageFile(unzFile uf, char *filename, int *ST_or_MSA)
        !           189: {
        !           190:   unz_file_info file_info;
        !           191: 
        !           192:   if (unzLocateFile(uf,filename, 0)!=UNZ_OK)
        !           193:     {
        !           194:       fprintf(stderr, "Error: File \"%s\"not found in the archive!", filename);
        !           195:       return(-1);
        !           196:     }
        !           197: 
        !           198:   if( unzGetCurrentFileInfo(uf,&file_info,filename, ZIP_PATH_MAX,NULL,0,NULL,0) != UNZ_OK)
        !           199:     {
        !           200:       fprintf(stderr, "Error with zipfile in unzGetCurrentFileInfo \n");
        !           201:       return(-1);
        !           202:     }
        !           203:   
        !           204:   /* check for a .msa or .st extention */
        !           205:   if(File_FileNameIsMSA(filename))
        !           206:     {
        !           207:       *ST_or_MSA = ZIP_FILE_MSA;
        !           208:       return( file_info.uncompressed_size );
        !           209:     }
        !           210: 
        !           211:   if(File_FileNameIsST(filename))
        !           212:     {
        !           213:       *ST_or_MSA = ZIP_FILE_ST;
        !           214:       return( file_info.uncompressed_size );
        !           215:     }
        !           216:   
        !           217:   fprintf(stderr, "Not an .ST or .MSA file.\n");
        !           218:   return(0);
        !           219: }
        !           220: 
        !           221: /*-----------------------------------------------------------------------*/
        !           222: /*
        !           223:   Return the first .zip or .msa file in a zip, or NULL on failure
        !           224: */
        !           225: char *ZIP_FirstFile(char *filename)
        !           226: {
        !           227:   zip_dir *files;
        !           228:   int i;
        !           229:   char *name;
        !           230: 
        !           231:   if((files = ZIP_GetFiles(filename)) == NULL) return(NULL);
        !           232:   name = Memory_Alloc(ZIP_PATH_MAX);
        !           233: 
        !           234:   name[0] = '\0';
        !           235:   for(i=files->nfiles-1;i>=0;i--)
        !           236:     if(File_FileNameIsMSA(files->names[i]) || 
        !           237:        File_FileNameIsST(files->names[i]))
        !           238:       strncpy(name, files->names[i], ZIP_PATH_MAX);
        !           239:     
        !           240:   /* free the files */
        !           241:   for(i=0;i<files->nfiles;i++)
        !           242:     Memory_Free(files->names[i]);
        !           243:   Memory_Free(files);
        !           244: 
        !           245:   if(name[0] == '\0')
        !           246:     return(NULL);
        !           247:   return(name);
        !           248: }
        !           249: 
        !           250: 
        !           251: /*-----------------------------------------------------------------------*/
        !           252: /*
        !           253:   Extract a file (filename) from a ZIP-file (uf), the number of 
        !           254:   bytes to uncompress is size. Returns a pointer to a buffer containing
        !           255:   the uncompressed data, or NULL.
        !           256: */
        !           257: char *ZIP_ExtractFile(unzFile uf, char *filename, uLong size)
        !           258: {
        !           259:   int err = UNZ_OK;
        !           260:   char filename_inzip[ZIP_PATH_MAX];
        !           261:   FILE *fout=NULL;
        !           262:   void* buf;
        !           263:   uInt size_buf;
        !           264:   
        !           265:   unz_file_info file_info;
        !           266:   uLong ratio=0;
        !           267: 
        !           268: 
        !           269:   if (unzLocateFile(uf,filename, 0)!=UNZ_OK)
        !           270:     {
        !           271:       fprintf(stderr, "ERROR ZIP_ExtractFile could not find file in archive\n");
        !           272:       ErrLog_File("ERROR ZIP_ExtractFile could not find file in archive\n");
        !           273:       return NULL;
        !           274:     }
        !           275:   
        !           276:   err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
        !           277:   
        !           278:   if (err!=UNZ_OK)
        !           279:     {
        !           280:       fprintf(stderr, "ERROR ZIP_ExtractFile could not find file in archive\n");
        !           281:       ErrLog_File("ERROR ZIP_ExtractFile could not get file info\n");
        !           282:       return NULL;
        !           283:     }
        !           284:   
        !           285:   size_buf = size;
        !           286:   buf = Memory_Alloc(size_buf);
        !           287:   
        !           288:   err = unzOpenCurrentFile(uf);
        !           289:   if (err!=UNZ_OK)
        !           290:     {
        !           291:       fprintf(stderr, "ERROR ZIP_ExtractFile could not find file in archive\n");
        !           292:       ErrLog_File("ERROR ZIP_ExtractFile could not open file\n");
        !           293:       return(NULL);
        !           294:     }
        !           295:   
        !           296:   do
        !           297:     {
        !           298:       err = unzReadCurrentFile(uf,buf,size_buf);
        !           299:       if (err<0)       
        !           300:        {
        !           301:          fprintf(stderr, "ERROR ZIP_ExtractFile could not find file in archive\n");
        !           302:          ErrLog_File("ERROR ZIP_ExtractFile could not read file\n");
        !           303:          return(NULL);
        !           304:        }
        !           305:     } while (err>0);
        !           306:   
        !           307:   return buf;
        !           308: }
        !           309: 
        !           310: /*-----------------------------------------------------------------------*/
        !           311: /*
        !           312:   Load .ZIP file into memory, return number of bytes loaded
        !           313: 
        !           314: */
        !           315: int ZIP_ReadDisc(char *pszFileName, char *pszZipPath, unsigned char *pBuffer)
        !           316: {
        !           317:   uLong ImageSize=0;
        !           318:   char *temp;
        !           319:   unzFile uf=NULL;
        !           320:   char *buf;
        !           321:   int ST_or_MSA;
        !           322:   BOOL pathAllocated=FALSE;
        !           323: 
        !           324:   uf = unzOpen(pszFileName);
        !           325:   if (uf==NULL)
        !           326:     {
        !           327:       printf("Cannot open %s\n", pszFileName);
        !           328:       return(0);
        !           329:     }
        !           330:   
        !           331:   if (pszZipPath == NULL || pszZipPath[0] == 0)
        !           332:     {
        !           333:       if((pszZipPath = ZIP_FirstFile(pszFileName)) == NULL)
        !           334:        {
        !           335:          printf("Cannot open %s\n", pszFileName);
        !           336:          return(0);
        !           337:        }
        !           338:       pathAllocated=TRUE;
        !           339:     }
        !           340: 
        !           341:   if((ImageSize = ZIP_CheckImageFile(uf, pszZipPath, &ST_or_MSA)) <= 0)
        !           342:     {
        !           343:       return(0);
        !           344:     }
        !           345: 
        !           346:   if(ImageSize > DRIVE_BUFFER_BYTES)
        !           347:     {
        !           348:       ErrLog_File("ERROR ZIP_ReadDisc uncompressed .msa or .st file is larger than buffer\n");      
        !           349:       return(0);
        !           350:     }
        !           351: 
        !           352:   /* extract to buf */
        !           353:   buf=ZIP_ExtractFile(uf, pszZipPath, ImageSize);
        !           354:   unzCloseCurrentFile(uf);
        !           355:   if(buf == NULL)
        !           356:     {
        !           357:       return(0);  /* failed extraction, return error */
        !           358:     }
        !           359: 
        !           360:   if(ST_or_MSA == ZIP_FILE_ST)
        !           361:     {
        !           362:       /* copy the ST image */
        !           363:       memcpy(pBuffer, buf, (size_t)ImageSize);
        !           364:     } else {
        !           365:       /* uncompress the MSA file */
        !           366:       ImageSize = MSA_UnCompress(buf, pBuffer);      
        !           367:     }
        !           368: 
        !           369:   /* Free the buffer */
        !           370:   Memory_Free(buf);
        !           371:   if(pathAllocated == TRUE)
        !           372:     Memory_Free(pszZipPath);
        !           373: 
        !           374:   return(ImageSize);
        !           375: }
        !           376: 
        !           377: 
        !           378: /*-----------------------------------------------------------------------*/
        !           379: /*
        !           380:   Save .ZIP file from memory buffer. Returns TRUE is all OK
        !           381:   
        !           382:   Not yet implemented.
        !           383: */
        !           384: BOOL ZIP_WriteDisc(char *pszFileName,unsigned char *pBuffer,int ImageSize)
        !           385: {
        !           386:   return(FALSE);
        !           387: }
        !           388: 
        !           389: /*-----------------------------------------------------------------------*/
        !           390: /*
        !           391:   Load .GZ file into memory, return number of bytes loaded
        !           392: 
        !           393: */
        !           394: int GZIP_ReadDisc(char *pszFileName,unsigned char *pBuffer)
        !           395: {
        !           396:   /* allocate buffer to store uncompressed bytes */
        !           397:   long ImageSize=0;
        !           398:   char *buf;
        !           399:   gzFile in;
        !           400:   int err=0;
        !           401:   
        !           402:   if((in = gzopen(pszFileName, "rb")) == NULL)
        !           403:     {
        !           404:       fprintf(stderr, "Error: could not open %s\n", pszFileName);
        !           405:       return(0);
        !           406:     }
        !           407:   
        !           408:   buf = (char *)Memory_Alloc(DRIVE_BUFFER_BYTES);
        !           409:   do {
        !           410:     ImageSize += err;
        !           411:     err = gzread(in, (char *)(buf + ImageSize), 256);
        !           412:   } while(err > 0 && ImageSize < DRIVE_BUFFER_BYTES);
        !           413:   
        !           414:   if(err < 0 || ImageSize >= DRIVE_BUFFER_BYTES)
        !           415:     {
        !           416:       fprintf(stderr, "Error: could not decompress %s\n", pszFileName);
        !           417:       return(0);
        !           418:     }
        !           419: 
        !           420:   gzclose(in);
        !           421: 
        !           422:   /* is it a gzipped .ST or .MSA file? */
        !           423:   if(File_FileNameIsSTGZ(pszFileName))
        !           424:     {
        !           425:       /* copy the ST image */
        !           426:       memcpy(pBuffer, buf, (size_t)ImageSize);
        !           427:     } else {
        !           428:       /* uncompress the MSA file */
        !           429:       ImageSize = MSA_UnCompress(buf, pBuffer);      
        !           430:     }
        !           431: 
        !           432:   Memory_Free(buf);
        !           433:   return(ImageSize);
        !           434: }
        !           435: 
        !           436: /*-----------------------------------------------------------------------*/
        !           437: /*
        !           438:   Save .GZ file from memory buffer. Returns TRUE is all OK
        !           439:   
        !           440:   Not yet implemented.
        !           441: */
        !           442: BOOL GZIP_WriteDisc(char *pszFileName,unsigned char *pBuffer,int ImageSize)
        !           443: {
        !           444: #ifdef SAVE_TO_GZIP_IMAGES
        !           445:   gzFile out;
        !           446:   int size;
        !           447: 
        !           448:   /* is it a gzipped .ST or .MSA file? */
        !           449:   if(File_FileNameIsSTGZ(pszFileName))
        !           450:     {
        !           451:       if((out = gzopen(pszFileName, "wb6 ")) == NULL)
        !           452:        {
        !           453:          fprintf(stderr, "Could not write to %s\n", pszFileName);
        !           454:          return(FALSE);
        !           455:        }
        !           456: 
        !           457:       if(gzwrite(out, pBuffer, ImageSize) != ImageSize)
        !           458:        {
        !           459:          fprintf(stderr, "Could not write to %s\n", pszFileName);
        !           460:          return(FALSE);
        !           461:        }
        !           462:       fprintf(stderr,"wrote %s\n", pszFileName);
        !           463:       gzclose(out);
        !           464:     } else {
        !           465:     }
        !           466: 
        !           467:   return(TRUE);
        !           468: 
        !           469: #else
        !           470:   return(FALSE);
        !           471: #endif
        !           472: }
        !           473: 

unix.superglobalmegacorp.com

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