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

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

unix.superglobalmegacorp.com

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