1 /**
2  * libzip data source for SDL_RWops
3 
4  * Copyright (C) 2001  Guido Draheim <guidod@gmx.de>
5  * Copyright (C) 2007, 2009  Sylvain Beucler
6 
7  * This file is part of GNU FreeDink
8 
9  * GNU FreeDink is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 3 of the
12  * License, or (at your option) any later version.
13 
14  * GNU FreeDink is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18 
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see
21  * <http://www.gnu.org/licenses/>.
22  */
23 
24 /*
25  *      (this example uses errno which might not be multithreaded everywhere)
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 #include "SDL_rwops_libzip.h"
33 #include <zip.h>
34 #include <string.h> /* strchr */
35 #include <errno.h>
36 
37 #include "log.h"
38 
39 #if 0
40 static int rwops_libzip_seek(SDL_RWops *context, int offset, int whence)
41 {
42   printf("rwops_libzip_seek(context=%p, offset=%d, whence=", context, offset);
43   switch(whence)
44     {
45     case SEEK_SET:
46       printf("SEEK_SET");
47       break;
48     case SEEK_CUR:
49       printf("SEEK_CUR");
50       break;
51     case SEEK_END:
52       printf("SEEK_END");
53       break;
54     }
55   printf(");\n");
56   return 0; /* ignored */
57 }
58 
59 static int rwops_libzip_read(SDL_RWops *context, void *ptr, int size, int maxnum)
60 {
61   printf("rwops_libzip_read(context=%p, ptr=%p, size=%d, maxnum=%d);\n", context, ptr, size, maxnum);
62   return zip_fread(context->hidden.unknown.data1, ptr, size*maxnum) / size;
63 }
64 
65 static int rwops_libzip_write(SDL_RWops *context, const void *ptr, int size, int num)
66 {
67   return -1; /* not supported */
68 }
69 
70 static int rwops_libzip_close(SDL_RWops *context)
71 {
72   printf("rwops_libzip_close(context=%p);\n", context);
73 
74   if (context == NULL)
75     return 0; /* may be SDL_RWclose is called by atexit */
76 
77   zip_fclose(context->hidden.unknown.data1);
78   /* SDL_FreeRW (context); */
79   /* TODO: zip_close(zarchive); */
80   return 0;
81 }
82 #endif
83 
84 
SDL_RWFromZIP(const char * archivename,const char * filename)85 SDL_RWops *SDL_RWFromZIP(const char* archivename, const char* filename)
86 {
87     SDL_RWops* rwops;
88     struct zip* zarchive;
89     struct zip_file* zfile;
90     int errorp = 0;
91 
92     zarchive = zip_open(archivename, ZIP_CHECKCONS, &errorp);
93     if (errorp != 0)
94       {
95 	char *errorbuf = NULL;
96 	int len = 1;
97 	errorbuf = malloc(len);
98 	len = zip_error_to_str(errorbuf, len, errorp, errno);
99 	errorbuf = realloc(errorbuf, len + 1);
100 	len = zip_error_to_str(errorbuf, len, errorp, errno);
101 	log_warn("zip_open: %s", errorbuf);
102 	free(errorbuf);
103 	return NULL;
104       }
105     zfile = zip_fopen(zarchive, filename, 0);
106     if (zfile == NULL)
107       {
108 	log_error("zip_open: %s", zip_strerror(zarchive));
109 	zip_close(zarchive);
110 	return NULL;
111       }
112 
113     /* libzip does not support seek()ing in file, so we can't use it -
114        TTF_OpenFontRW needs it to read data at the end of files.  */
115 #if 0
116     rwops = SDL_AllocRW();
117     if (rwops == NULL)
118       { errno=ENOMEM;
119 	zip_close(zarchive);
120 	return NULL;
121       }
122 
123     rwops->hidden.unknown.data1 = zfile;
124     rwops->read = rwops_libzip_read;
125     rwops->write = rwops_libzip_write;
126     rwops->seek = rwops_libzip_seek;
127     rwops->close = rwops_libzip_close;
128     return rwops;
129 #endif
130 
131     struct zip_stat zfilestat;
132     if (zip_stat(zarchive, filename, 0, &zfilestat) < 0)
133       {
134 	log_warn("zip_open: %s", zip_strerror(zarchive));
135 	zip_close(zarchive);
136 	return NULL;
137       }
138 
139     char *content = malloc(zfilestat.size);
140     zip_fread(zfile, content, zfilestat.size);
141     rwops = SDL_RWFromMem(content, zfilestat.size);
142     zip_fclose(zfile);
143     zip_close(zarchive);
144 
145     return rwops;
146 }
147