This source file includes following definitions.
- zip_source_filep
- _zip_source_file_or_p
- read_file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 #include <sys/stat.h>
37 #include <errno.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41
42 #include "zipint.h"
43
44 struct read_file {
45 char *fname;
46 FILE *f;
47 int closep;
48 struct zip_stat st;
49
50 zip_uint64_t off;
51 zip_int64_t len;
52 zip_int64_t remain;
53 int e[2];
54 };
55
56 static zip_int64_t read_file(void *state, void *data, zip_uint64_t len,
57 enum zip_source_cmd cmd);
58
59
60
61 ZIP_EXTERN struct zip_source *
62 zip_source_filep(struct zip *za, FILE *file, zip_uint64_t start,
63 zip_int64_t len)
64 {
65 if (za == NULL)
66 return NULL;
67
68 if (file == NULL || len < -1) {
69 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
70 return NULL;
71 }
72
73 return _zip_source_file_or_p(za, NULL, file, start, len, 1, NULL);
74 }
75
76
77
78 struct zip_source *
79 _zip_source_file_or_p(struct zip *za, const char *fname, FILE *file,
80 zip_uint64_t start, zip_int64_t len, int closep,
81 const struct zip_stat *st)
82 {
83 struct read_file *f;
84 struct zip_source *zs;
85
86 if (file == NULL && fname == NULL) {
87 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
88 return NULL;
89 }
90
91 if ((f=(struct read_file *)malloc(sizeof(struct read_file))) == NULL) {
92 _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
93 return NULL;
94 }
95
96 f->fname = NULL;
97 if (fname) {
98 if ((f->fname=strdup(fname)) == NULL) {
99 _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
100 free(f);
101 return NULL;
102 }
103 }
104 f->f = file;
105 f->off = start;
106 f->len = (len ? len : -1);
107 f->closep = f->fname ? 1 : closep;
108 if (st)
109 memcpy(&f->st, st, sizeof(f->st));
110 else
111 zip_stat_init(&f->st);
112
113 if ((zs=zip_source_function(za, read_file, f)) == NULL) {
114 free(f);
115 return NULL;
116 }
117
118 return zs;
119 }
120
121
122
123 static zip_int64_t
124 read_file(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd)
125 {
126 struct read_file *z;
127 char *buf;
128 zip_uint64_t n;
129 size_t i;
130
131 z = (struct read_file *)state;
132 buf = (char *)data;
133
134 switch (cmd) {
135 case ZIP_SOURCE_OPEN:
136 if (z->fname) {
137 if ((z->f=fopen(z->fname, "rb")) == NULL) {
138 z->e[0] = ZIP_ER_OPEN;
139 z->e[1] = errno;
140 return -1;
141 }
142 }
143
144 if (z->closep && z->off > 0) {
145 if (fseeko(z->f, (off_t)z->off, SEEK_SET) < 0) {
146 z->e[0] = ZIP_ER_SEEK;
147 z->e[1] = errno;
148 return -1;
149 }
150 }
151 z->remain = z->len;
152 return 0;
153
154 case ZIP_SOURCE_READ:
155 if (z->remain != -1)
156 n = len > (zip_uint64_t)z->remain ? (zip_uint64_t)z->remain : len;
157 else
158 n = len;
159
160 if (n > SIZE_MAX)
161 n = SIZE_MAX;
162
163 if (!z->closep) {
164
165 if (fseeko(z->f, (off_t)(z->off + (zip_uint64_t)(z->len-z->remain)), SEEK_SET) < 0) {
166 z->e[0] = ZIP_ER_SEEK;
167 z->e[1] = errno;
168 return -1;
169 }
170 }
171
172 if ((i=fread(buf, 1, (size_t)n, z->f)) == 0) {
173 if (ferror(z->f)) {
174 z->e[0] = ZIP_ER_READ;
175 z->e[1] = errno;
176 return -1;
177 }
178 }
179
180 if (z->remain != -1)
181 z->remain -= i;
182
183 return (zip_int64_t)i;
184
185 case ZIP_SOURCE_CLOSE:
186 if (z->fname) {
187 fclose(z->f);
188 z->f = NULL;
189 }
190 return 0;
191
192 case ZIP_SOURCE_STAT:
193 {
194 if (len < sizeof(z->st))
195 return -1;
196
197 if (z->st.valid != 0)
198 memcpy(data, &z->st, sizeof(z->st));
199 else {
200 struct zip_stat *st;
201 struct stat fst;
202 int err;
203
204 if (z->f)
205 err = fstat(fileno(z->f), &fst);
206 else
207 err = stat(z->fname, &fst);
208
209 if (err != 0) {
210 z->e[0] = ZIP_ER_READ;
211 z->e[1] = errno;
212 return -1;
213 }
214
215 st = (struct zip_stat *)data;
216
217 zip_stat_init(st);
218 st->mtime = fst.st_mtime;
219 st->valid |= ZIP_STAT_MTIME;
220 if (z->len != -1) {
221 st->size = (zip_uint64_t)z->len;
222 st->valid |= ZIP_STAT_SIZE;
223 }
224 else if ((fst.st_mode&S_IFMT) == S_IFREG) {
225 st->size = (zip_uint64_t)fst.st_size;
226 st->valid |= ZIP_STAT_SIZE;
227 }
228 }
229 return sizeof(z->st);
230 }
231
232 case ZIP_SOURCE_ERROR:
233 if (len < sizeof(int)*2)
234 return -1;
235
236 memcpy(data, z->e, sizeof(int)*2);
237 return sizeof(int)*2;
238
239 case ZIP_SOURCE_FREE:
240 free(z->fname);
241 if (z->closep && z->f)
242 fclose(z->f);
243 free(z);
244 return 0;
245
246 default:
247 ;
248 }
249
250 return -1;
251 }