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