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