1 /* Crimson Fields -- a game of tactical warfare
2 Copyright (C) 2000-2007 Jens Granseuer
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 /*
20 SDL_zlib.c
21 This file provides support for reading and writing zlib-compressed
22 files (gzip) using the SDL_RWops interface of SDL.
23 */
24
25 #include "SDL_rwops.h"
26 #include "SDL_error.h"
27
28 #ifdef HAVE_LIBZ
29
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
33 #include <stdio.h>
34 #include <zlib.h>
35
36 /* Functions to read/write gzip files */
37
gzip_seek(SDL_RWops * context,int offset,int whence)38 static int gzip_seek(SDL_RWops *context, int offset, int whence) {
39 int pos;
40
41 pos = gzseek((gzFile)context->hidden.unknown.data1, offset, whence);
42 if (pos == -1) SDL_Error(SDL_EFSEEK);
43 return pos;
44 }
45
gzip_read(SDL_RWops * context,void * ptr,int size,int maxnum)46 static int gzip_read(SDL_RWops *context, void *ptr, int size, int maxnum) {
47 size_t nread;
48
49 nread = gzread((gzFile)context->hidden.unknown.data1, ptr, size * maxnum);
50 if (nread == -1) SDL_Error(SDL_EFREAD);
51 return nread;
52 }
53
gzip_write(SDL_RWops * context,const void * ptr,int size,int num)54 static int gzip_write(SDL_RWops *context, const void *ptr, int size, int num) {
55 size_t nwrote;
56
57 nwrote = gzwrite((gzFile)context->hidden.unknown.data1, ptr, size * num);
58 if (nwrote == 0) SDL_Error(SDL_EFWRITE);
59 return nwrote;
60 }
61
gzip_close(SDL_RWops * context)62 static int gzip_close(SDL_RWops *context) {
63 int rc = 0;
64
65 if (context) {
66 rc = gzclose((gzFile)context->hidden.unknown.data1);
67 SDL_FreeRW(context);
68 }
69 return rc;
70 }
71
72 /* this comes straight from the SDL sources */
73 #ifdef macintosh
74 /*
75 * translate unix-style slash-separated filename to mac-style colon-separated
76 * name; return malloced string
77 */
unix_to_mac(const char * file)78 static char *unix_to_mac(const char *file) {
79 flen = strlen(file);
80 char *path = malloc(flen + 2);
81 const char *src = file;
82 char *dst = path;
83 if(*src == '/') {
84 /* really depends on filesystem layout, hope for the best */
85 src++;
86 } else {
87 /* Check if this is a MacOS path to begin with */
88 if(*src != ':')
89 *dst++ = ':'; /* relative paths begin with ':' */
90 }
91 while(src < file + flen) {
92 const char *end = strchr(src, '/');
93 int len;
94 if(!end)
95 end = file + flen; /* last component */
96 len = end - src;
97 if(len == 0 || (len == 1 && src[0] == '.')) {
98 /* remove repeated slashes and . */
99 } else {
100 if(len == 2 && src[0] == '.' && src[1] == '.') {
101 /* replace .. with the empty string */
102 } else {
103 memcpy(dst, src, len);
104 dst += len;
105 }
106 if(end < file + flen)
107 *dst++ = ':';
108 }
109 src = end + 1;
110 }
111 *dst++ = '\0';
112 return path;
113 }
114 #endif /* macintosh */
115 #endif /* HAVE_LIBZ */
116
117 /*
118 if zlib is not available this function returns a standard file
119 structure as created by SDL_RWFromFile
120 */
SDL_RWFromGzip(const char * file,const char * mode)121 SDL_RWops *SDL_RWFromGzip(const char *file, const char *mode) {
122 SDL_RWops *rwops;
123
124 #ifdef HAVE_LIBZ
125 rwops = SDL_AllocRW();
126 if (rwops != NULL) {
127 gzFile gzfp;
128
129 # ifdef macintosh
130 char *mpath = unix_to_mac(file);
131 gzfp = gzopen(mpath, mode);
132 free(mpath);
133 # else
134 gzfp = gzopen(file, mode);
135 # endif /* macintosh */
136
137 if (gzfp != NULL) {
138 rwops->hidden.unknown.data1 = gzfp;
139 rwops->seek = gzip_seek;
140 rwops->read = gzip_read;
141 rwops->write = gzip_write;
142 rwops->close = gzip_close;
143 } else {
144 SDL_FreeRW(rwops);
145 rwops = NULL;
146 }
147 }
148
149 #else
150 rwops = SDL_RWFromFile(file, mode);
151 #endif /* HAVE_LIBZ */
152
153 return rwops;
154 }
155
156