1 /*-
2 * Copyright (c) 2004 Patrick Mauritz <oxygene@openbios.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27 #include "fpk.h"
28
29 /* internal functions */
30
fpk__readlfile(FILE * fpk)31 char* fpk__readlfile(FILE* fpk) {
32 unsigned char tmp;
33 unsigned int len;
34 char* result;
35
36 fread(&tmp,1,1,fpk);
37 len=tmp;
38
39 result=(char*)malloc(len);
40 fread(result,1,len,fpk);
41
42 return result;
43 }
44
fpk__readLE4(FILE * fpk)45 unsigned int fpk__readLE4(FILE* fpk) {
46 unsigned char tmp[4];
47 fread(&tmp,1,4,fpk);
48 return (tmp[3]<<24)+(tmp[2]<<16)+(tmp[1]<<8)+tmp[0];
49 }
50
fpk__clearfiles(struct fpkmeta * meta)51 void fpk__clearfiles(struct fpkmeta* meta) {
52 signed int c;
53 if (!(meta->files)) return; /* clean already */
54 for (c=0;c<meta->numfiles;c++) {
55 if (meta->files[c].name) free(meta->files[c].name);
56 if (meta->files[c].directory) free(meta->files[c].directory);
57 }
58 free(meta->files);
59 }
60
fpk__getmeta(struct fpkmeta * meta)61 void fpk__getmeta(struct fpkmeta* meta) {
62 unsigned int c;
63
64 fseek(meta->fpk,8L,SEEK_SET);
65 fread(meta->shortname,1,13,meta->fpk);
66 fread(meta->longname,1,64,meta->fpk);
67 fread(meta->author,1,36,meta->fpk);
68
69 if (meta->rootpath) free(meta->rootpath);
70 c=getc(meta->fpk);
71 (void)getc(meta->fpk);
72 meta->rootpath=(char*)malloc(c);
73 fread(meta->rootpath,1,c,meta->fpk);
74
75 return;
76 }
77
78
79 /* exported functions */
80
fpkmagic(struct fpkmeta * meta)81 int fpkmagic(struct fpkmeta* meta) {
82 char test[8];
83 rewind(meta->fpk);
84 fread(&test,1,8,meta->fpk);
85 return memcmp(test,"GPKG\0\0\0\0",8);
86 }
87
fpkgetdir(struct fpkmeta * meta)88 void fpkgetdir(struct fpkmeta* meta) {
89 unsigned int c,c2;
90
91 fseek(meta->fpk,136L,SEEK_SET);
92 c=fpk__readLE4(meta->fpk);
93
94 meta->size=0;
95
96 if (meta->files) fpk__clearfiles(meta);
97 meta->files=(struct fpkfile*)malloc(sizeof(struct fpkfile)*c);
98 meta->numfiles=c;
99
100 for (c2=0;c2<c;c2++) {
101 char v=getc(meta->fpk);
102 char *dir, *file;
103 unsigned int length;
104 if (v=='2') {
105 // finish
106 meta->files[c2].offset=-1;
107 meta->files[c2].size=-1;
108 meta->files[c2].directory=0;
109 meta->files[c2].name=0;
110 break;
111 }
112 dir=fpk__readlfile(meta->fpk);
113 file=fpk__readlfile(meta->fpk);
114 meta->files[c2].directory=dir;
115 meta->files[c2].name=file;
116 if (v=='0') {
117 length=0;
118 meta->files[c2].offset=0;
119 // directory
120 }
121 if (v=='1') {
122 length=fpk__readLE4(meta->fpk);
123 meta->files[c2].offset=ftell(meta->fpk);
124 fseek(meta->fpk,length,SEEK_CUR);
125 // file
126 }
127 meta->files[c2].size=length;
128 meta->size+=length;
129 }
130 }
131
fpkinit(struct fpkmeta * meta,const char * filename)132 signed int fpkinit(struct fpkmeta *meta, const char *filename) {
133 meta->files=0;
134 meta->rootpath=0;
135 meta->iter=-1;
136 meta->numfiles=0;
137 meta->size=0;
138
139 meta->fpk=fopen(filename,"r");
140 if (!meta->fpk) return -1;
141
142 if (fpkmagic(meta)) {
143 fclose(meta->fpk);
144 return -1;
145 }
146 fpk__getmeta(meta);
147 return 0;
148 }
149
fpkclose(struct fpkmeta * meta)150 void fpkclose(struct fpkmeta *meta) {
151 fclose(meta->fpk);
152 fpk__clearfiles(meta);
153 }
154
fpkrewind(struct fpkmeta * meta)155 void fpkrewind(struct fpkmeta *meta) {
156 meta->iter=-1;
157 }
158
fpknextfile(struct fpkmeta * meta)159 struct fpkfile* fpknextfile(struct fpkmeta *meta) {
160 while ((meta->iter<meta->numfiles) && (meta->files[++meta->iter].offset<=0)) {};
161 if (meta->iter>=meta->numfiles)
162 return NULL;
163 else
164 return &meta->files[meta->iter];
165 }
166
fpknextdir(struct fpkmeta * meta)167 struct fpkfile* fpknextdir(struct fpkmeta *meta) {
168 while ((meta->iter<meta->numfiles) && (meta->files[++meta->iter].offset!=0)) {};
169 if (meta->iter>=meta->numfiles)
170 return NULL;
171 else
172 return &meta->files[meta->iter];
173 }
174
fpkgetfile(struct fpkmeta * meta,struct fpkfile * file)175 unsigned char* fpkgetfile(struct fpkmeta *meta, struct fpkfile *file){
176 char *tmp;
177 if (file->offset<=0) return NULL; /* not a file */
178 fseek(meta->fpk,file->offset,SEEK_SET);
179 tmp=(unsigned char*)malloc(file->size);
180 fread(tmp,file->size,1,meta->fpk);
181 return tmp;
182 }
183