1 /**
2  * zziplib data source for SDL_RWops
3 
4  * Copyright (C) 2001  Guido Draheim <guidod@gmx.de>
5  * Copyright (C) 2007, 2008, 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 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 /* Order headers appropriately:
29    http://lists.gnu.org/archive/html/bug-gnulib/2007-12/msg00152.html */
30 #include <unistd.h> /* close->rpl_close */
31 #include <zzip/zzip.h> /* also sources unistd.h */
32 #include <SDL_rwops.h> /* has a 'close' member, replaced by
33 			  'rpl_close' */
34 
35 #include "SDL_rwops_zzip.h"
36 #include <string.h> /* strchr */
37 
38 
39 /* MSVC can not take a casted variable as an lvalue ! */
40 #define SDL_RWOPS_ZZIP_DATA(_context) \
41              ((_context)->hidden.unknown.data1)
42 #define SDL_RWOPS_ZZIP_FILE(_context)  (ZZIP_FILE*) \
43              ((_context)->hidden.unknown.data1)
44 
rwops_zzip_seek(SDL_RWops * context,int offset,int whence)45 static int rwops_zzip_seek(SDL_RWops *context, int offset, int whence)
46 {
47     return zzip_seek(SDL_RWOPS_ZZIP_FILE(context), offset, whence);
48 }
49 
rwops_zzip_read(SDL_RWops * context,void * ptr,int size,int maxnum)50 static int rwops_zzip_read(SDL_RWops *context, void *ptr, int size, int maxnum)
51 {
52     return zzip_read(SDL_RWOPS_ZZIP_FILE(context), ptr, size*maxnum) / size;
53 }
54 
rwops_zzip_write(SDL_RWops * context,const void * ptr,int size,int num)55 static int rwops_zzip_write(SDL_RWops *context, const void *ptr, int size, int num)
56 {
57     return 0; /* ignored */
58 }
59 
rwops_zzip_close(SDL_RWops * context)60 static int rwops_zzip_close(SDL_RWops *context)
61 {
62     if (! context) return 0; /* may be SDL_RWclose is called by atexit */
63 
64     zzip_close (SDL_RWOPS_ZZIP_FILE(context));
65     SDL_FreeRW (context);
66     return 0;
67 }
68 
SDL_RWFromZZIP(const char * file,const char * mode)69 SDL_RWops *SDL_RWFromZZIP(const char* file, const char* mode)
70 {
71     register SDL_RWops* rwops;
72     register ZZIP_FILE* zzip_file;
73 
74     if (! strchr (mode, 'r'))
75 	return SDL_RWFromFile(file, mode);
76 
77 /*     zzip_file = zzip_fopen (file, mode); */
78     zzip_strings_t xor_fileext[] = { "", 0 };
79     zzip_file = zzip_open_ext_io(file,
80       0, ZZIP_CASELESS|ZZIP_ONLYZIP,
81       xor_fileext, 0);
82     if (! zzip_file) return 0;
83 
84     rwops = SDL_AllocRW ();
85     if (! rwops) { errno=ENOMEM; zzip_close (zzip_file); return 0; }
86 
87     SDL_RWOPS_ZZIP_DATA(rwops) = zzip_file;
88     rwops->read = rwops_zzip_read;
89     rwops->write = rwops_zzip_write;
90     rwops->seek = rwops_zzip_seek;
91     rwops->close = rwops_zzip_close;
92     return rwops;
93 }
94