1 /*
2  *      Copyright (c) 2001 Guido Draheim <guidod@gmx.de>
3  *      Use freely under the restrictions of the ZLIB License
4  *
5  *      (this example uses errno which might not be multithreaded everywhere)
6  */
7 
8 #include "SDL_rwops_libzip.h"
9 #include <zip.h>
10 #include <string.h> /* strchr */
11 #include <errno.h>
12 
13 #if 0
14 static int rwops_libzip_seek(SDL_RWops *context, int offset, int whence)
15 {
16   printf("rwops_libzip_seek(context=%p, offset=%d, whence=", context, offset);
17   switch(whence)
18     {
19     case SEEK_SET:
20       printf("SEEK_SET");
21       break;
22     case SEEK_CUR:
23       printf("SEEK_CUR");
24       break;
25     case SEEK_END:
26       printf("SEEK_END");
27       break;
28     }
29   printf(");\n");
30   return 0; /* ignored */
31 }
32 
33 static int rwops_libzip_read(SDL_RWops *context, void *ptr, int size, int maxnum)
34 {
35   printf("rwops_libzip_read(context=%p, ptr=%p, size=%d, maxnum=%d);\n", context, ptr, size, maxnum);
36   return zip_fread(context->hidden.unknown.data1, ptr, size*maxnum) / size;
37 }
38 
39 static int rwops_libzip_write(SDL_RWops *context, const void *ptr, int size, int num)
40 {
41   return -1; /* not supported */
42 }
43 
44 static int rwops_libzip_close(SDL_RWops *context)
45 {
46   printf("rwops_libzip_close(context=%p);\n", context);
47 
48   if (context == NULL)
49     return 0; /* may be SDL_RWclose is called by atexit */
50 
51   zip_fclose(context->hidden.unknown.data1);
52   /* SDL_FreeRW (context); */
53   /* TODO: zip_close(zarchive); */
54   return 0;
55 }
56 #endif
57 
58 
SDL_RWFromZIP(const char * archivename,const char * filename)59 SDL_RWops *SDL_RWFromZIP(const char* archivename, const char* filename)
60 {
61     SDL_RWops* rwops;
62     struct zip* zarchive;
63     struct zip_file* zfile;
64     int errorp = 0;
65 
66     zarchive = zip_open(archivename, ZIP_CHECKCONS, &errorp);
67     if (errorp != 0)
68       {
69 	char *errorbuf = NULL;
70 	int len = 1;
71 	errorbuf = malloc(len);
72 	len = zip_error_to_str(errorbuf, len, errorp, errno);
73 	errorbuf = realloc(errorbuf, len + 1);
74 	len = zip_error_to_str(errorbuf, len, errorp, errno);
75 	fprintf(stderr, "zip_open: %s\n", errorbuf);
76 	free(errorbuf);
77 	return NULL;
78       }
79     zfile = zip_fopen(zarchive, filename, 0);
80     if (zfile == NULL)
81       {
82 	fprintf(stderr, "zip_open: %s\n", zip_strerror(zarchive));
83 	zip_close(zarchive);
84 	return NULL;
85       }
86 
87     /* libzip does not support seek()ing in file, so we can't use it -
88        TTF_OpenFontRW needs it to read data at the end of files.  */
89 #if 0
90     rwops = SDL_AllocRW();
91     if (rwops == NULL)
92       { errno=ENOMEM;
93 	zip_close(zarchive);
94 	return NULL;
95       }
96 
97     rwops->hidden.unknown.data1 = zfile;
98     rwops->read = rwops_libzip_read;
99     rwops->write = rwops_libzip_write;
100     rwops->seek = rwops_libzip_seek;
101     rwops->close = rwops_libzip_close;
102     return rwops;
103 #endif
104 
105     struct zip_stat zfilestat;
106     if (zip_stat(zarchive, filename, 0, &zfilestat) < 0)
107       {
108 	fprintf(stderr, "zip_open: %s\n", zip_strerror(zarchive));
109 	zip_close(zarchive);
110 	return NULL;
111       }
112 
113     char *content = malloc(zfilestat.size);
114     zip_fread(zfile, content, zfilestat.size);
115     rwops = SDL_RWFromMem(content, zfilestat.size);
116     zip_fclose(zfile);
117     zip_close(zarchive);
118 
119     return rwops;
120 }
121