Annotation of hatari/src/zip.c, revision 1.1.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.