packvfs
view src/pvfs.c @ 3:ef6c1472607f
jesus fucking christ that was easy... written a test prog "zipcat" to try out
zlib's contrib library "minizip", to list and read files out of zip archives
directly...
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 04 Nov 2013 06:46:17 +0200 |
parents | a0b3b6682d92 |
children |
line source
1 #include <string.h>
2 #include <stdarg.h>
3 #include <assert.h>
4 #include <alloca.h>
5 #include "pvfs.h"
6 #include "vnode.h"
8 int pvfs_errno;
10 int pvfs_mount(const char *mntpoint, const char *target)
11 {
12 struct vnode *srcnode, *destnode;
14 /* first locate the mount point vnode */
15 if(!(srcnode = vnode_lookup(mntpoint))) {
16 pvfs_errno = ENOENT;
17 return -1;
18 }
19 /* and make sure it's a directory */
20 if(srcnode->type != VNODE_DIR) {
21 pvfs_errno = ENOTDIR;
22 return -1;
23 }
25 /* then locate the target vnode (if it exists) */
26 if(!(destnode = vnode_lookup(target))) {
27 PVFS_DIR *dir;
28 PVFS_FILE *fp;
30 /* it's some error other than that target doesn't exist, fail... */
31 if(pvfs_errno != ENOENT) {
32 return -1;
33 }
35 /* if it doesn't exist, it might be the case we're trying
36 * to mount a package file or a real directory here. let's
37 * try them in turn...
38 */
39 if((dir = pvfs_opendir(target))) {
40 /* it's obviously a real dir as vnode_lookup failed before... */
41 assert(dir->real);
42 if(!(destnode = vnode_create_dir(target, dir))) {
43 return -1;
44 }
46 } else if((fp = pvfs_fopen(target, "rb"))) {
47 /* again, obviously real... */
48 assert(fp->real);
49 if(!(destnode = vnode_create_file(target, fp))) {
50 return -1;
51 }
53 } else {
54 /* it's neither... so let's fail */
55 pvfs_errno = ENOENT;
56 return -1;
57 }
58 }
60 /* ok so we've got the two nodes, connect them up */
61 srcnode->target = destnode;
62 return 0;
63 }
65 int pvfs_umount(const char *mntpoint)
66 {
67 struct vnode *node = vnode_lookup(mntpoint);
68 if(!node) {
69 return -1;
70 }
71 if(node->type != VNODE_DIR) {
72 pvfs_errno = ENOTDIR;
73 return -1;
74 }
75 if(!node->target) {
76 pvfs_errno = EINVAL;
77 return -1;
78 }
79 node->target = 0;
80 return 0;
81 }
83 int pvfs_chdir(const char *path)
84 {
85 return vnode_chdir(path);
86 }
88 int pvfs_mkdir(const char *path, unsigned int mode)
89 {
90 char *ppath;
91 const char *dname;
92 struct vnode *parent = 0;
94 ppath = alloca(strlen(path) + 1);
95 strcpy(ppath, path);
97 if((dname = strrchr(path, '/'))) {
98 ppath[++dname - path] = 0;
99 if(!*dname) {
100 pvfs_errno = ENOENT;
101 return -1;
102 }
103 if(!(parent = vnode_lookup(ppath))) {
104 return -1;
105 }
106 } else {
107 dname = ppath;
108 parent = vnode_getcwd();
109 }
111 return vnode_mkdir(parent, dname);
112 }
114 PVFS_FILE *pvfs_fopen(const char *fname, const char *mode)
115 {
116 FILE *fp;
117 struct vnode *node;
119 /* if we find it in the filesystem, just use it... */
120 if((fp = fopen(fname, mode))) {
121 PVFS_FILE *vfp = malloc(sizeof *vfp);
122 if(!vfp) {
123 pvfs_errno = ENOMEM;
124 return 0;
125 }
126 vfp->fp = fp;
127 vfp->real = 1;
128 return vfp;
129 }
131 /* otherwise try and locate it in the virtual hierarchy */
132 if(!(node = vnode_lookup(fname))) {
133 return 0;
134 }
135 if(node->type != VNODE_FILE) {
136 pvfs_errno = EISDIR;
137 return 0;
138 }
140 return VFILE(node);
141 }
143 int pvfs_fclose(PVFS_FILE *fp)
144 {
145 if(fp->real) {
146 /* it's real, just close it and free the struct */
147 fclose(fp->fp);
148 free(fp);
149 return 0;
150 }
152 /* TODO */
153 return -1;
154 }
156 int pvfs_fseek(PVFS_FILE *fp, long offset, int whence)
157 {
158 if(fp->real) {
159 return fseek(fp->fp, offset, whence);
160 }
162 return -1; /* TODO */
163 }
165 long pvfs_ftell(PVFS_FILE *fp)
166 {
167 if(fp->real) {
168 return ftell(fp->fp);
169 }
170 return -1; /* TODO */
171 }
173 void pvfs_rewind(PVFS_FILE *fp)
174 {
175 pvfs_fseek(fp, 0, SEEK_SET);
176 }
178 size_t pvfs_fread(void *buf, size_t size, size_t nitems, PVFS_FILE *fp)
179 {
180 if(fp->real) {
181 return fread(buf, size, nitems, fp->fp);
182 }
183 return 0; /* TODO */
184 }
186 size_t pvfs_fwrite(void *buf, size_t size, size_t nitems, PVFS_FILE *fp)
187 {
188 if(fp->real) {
189 return fwrite(buf, size, nitems, fp->fp);
190 }
191 return 0; /* TODO */
192 }
194 int pvfs_fgetc(PVFS_FILE *fp)
195 {
196 char c;
197 if(pvfs_fread(&c, 1, 1, fp) != 1) {
198 return -1;
199 }
200 return c;
201 }
203 int pvfs_fputc(int c, PVFS_FILE *fp)
204 {
205 return pvfs_fwrite(&c, 1, 1, fp) == 1 ? 0 : -1;
206 }
208 char *pvfs_fgets(char *buf, int size, PVFS_FILE *fp)
209 {
210 int i;
211 char *res = buf;
213 for(i=0; i<size - 1; i++) {
214 int c = pvfs_fgetc(fp);
215 if(!c) break;
217 *buf++ = c;
218 if(c == '\n') break;
219 }
221 *buf = 0;
222 return res;
223 }
225 int pvfs_fputs(char *buf, PVFS_FILE *fp)
226 {
227 int len = strlen(buf);
229 return pvfs_fwrite(buf, 1, len, fp) == 1 ? 0 : -1;
230 }
232 int pvfs_fscanf(PVFS_FILE *fp, const char *fmt, ...)
233 {
234 va_list ap;
235 int res;
237 va_start(ap, fmt);
238 res = pvfs_vfscanf(fp, fmt, ap);
239 va_end(ap);
240 return res;
241 }
243 int pvfs_vfscanf(PVFS_FILE *fp, const char *fmt, va_list ap)
244 {
245 return 0; /* TODO */
246 }
248 int pvfs_fprintf(PVFS_FILE *fp, const char *fmt, ...)
249 {
250 va_list ap;
251 int res;
253 va_start(ap, fmt);
254 res = pvfs_vfprintf(fp, fmt, ap);
256 va_end(ap);
257 return res;
258 }
260 int pvfs_vfprintf(PVFS_FILE *fp, const char *fmt, va_list ap)
261 {
262 return 0; /* TODO */
263 }
265 void pvfs_clearerr(PVFS_FILE *fp)
266 {
267 if(fp->real) {
268 clearerr(fp->fp);
269 return;
270 }
271 /* TODO */
272 }
274 int pvfs_feof(PVFS_FILE *fp)
275 {
276 if(fp->real) {
277 return feof(fp->fp);
278 }
279 return 0; /* TODO */
280 }
282 int pvfs_ferror(PVFS_FILE *fp)
283 {
284 if(fp->real) {
285 return ferror(fp->fp);
286 }
287 return -1; /* TODO */
288 }
290 /* POSIX stuff */
291 PVFS_DIR *pvfs_opendir(const char *dirname)
292 {
293 DIR *dir;
294 struct vnode *node;
296 if((dir = opendir(dirname))) {
297 PVFS_DIR *vdir = malloc(sizeof *vdir);
298 if(!vdir) {
299 pvfs_errno = ENOMEM;
300 return 0;
301 }
303 vdir->real = 1;
304 vdir->dir = dir;
305 return vdir;
306 }
308 if(!(node = vnode_lookup(dirname))) {
309 return 0;
310 }
311 if(node->type != VNODE_DIR) {
312 pvfs_errno = ENOTDIR;
313 return 0;
314 }
315 return VDIR(node);
316 }
318 int pvfs_closedir(PVFS_DIR *dir)
319 {
320 if(dir->real) {
321 int res = closedir(dir->dir);
322 free(dir);
323 return res;
324 }
326 /* TODO */
327 return -1;
328 }
330 struct pvfs_dirent *pvfs_readdir(PVFS_DIR *dir)
331 {
332 static struct pvfs_dirent dent;
334 if(dir->real) {
335 struct dirent *real_dent = readdir(dir->dir);
336 if(!real_dent) {
337 pvfs_errno = errno;
338 return 0;
339 }
341 strncpy(dent.d_name, real_dent->d_name, sizeof dent.d_name - 1);
342 dent.d_name[sizeof dent.d_name - 1] = 0;
344 return &dent;
345 }
346 return 0; /* TODO */
347 }
349 void pvfs_rewinddir(PVFS_DIR *dir)
350 {
351 if(dir->real) {
352 rewinddir(dir->dir);
353 return;
354 }
355 /* TODO */
356 }
358 int pvfs_stat(const char *path, struct pvfs_stat *buf)
359 {
360 return -1; /* TODO */
361 }