packvfs

view src/pvfs.c @ 0:df5e9ee65a50

packvfs initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 02 Aug 2013 06:03:38 +0300
parents
children a0b3b6682d92
line source
1 #include <string.h>
2 #include <alloca.h>
3 #include <assert.h>
4 #include "pvfs.h"
5 #include "vnode.h"
7 int pvfs_errno;
9 int pvfs_mount(const char *mntpoint, const char *target)
10 {
11 struct vnode *srcnode, *destnode;
13 /* first locate the mount point vnode */
14 if(!(srcnode = vnode_lookup(mntpoint))) {
15 pvfs_errno = ENOENT;
16 return -1;
17 }
18 /* and make sure it's a directory */
19 if(srcnode->type != VNODE_DIR) {
20 pvfs_errno = ENOTDIR;
21 return -1;
22 }
24 /* then locate the target vnode (if it exists) */
25 if(!(destnode = vnode_lookup(target))) {
26 /* it's some error other than that target doesn't exist, fail... */
27 if(pvfs_errno != ENOENT) {
28 return -1;
29 }
30 /* if it doesn't exist, it might be the case we're trying
31 * to mount a package file or a real directory here. let's
32 * try them in turn...
33 */
34 PVFS_DIR *dir;
35 PVFS_FILE *fp;
37 if((dir = pvfs_opendir(target))) {
38 /* it's obviously a real dir as vnode_lookup failed before... */
39 assert(dir->real);
40 if(!(destnode = vnode_create_dir(target, dir))) {
41 return -1;
42 }
44 } else if((fp = pvfs_fopen(target, "rb"))) {
45 /* again, obviously real... */
46 assert(fp->real);
47 if(!(destnode = vnode_create_file(target, fp))) {
48 return -1;
49 }
51 } else {
52 /* it's neither... so let's fail */
53 pvfs_errno = ENOENT;
54 return -1;
55 }
56 }
58 /* ok so we've got the two nodes, connect them up */
59 srcnode->target = destnode;
60 return 0;
61 }
63 int pvfs_umount(const char *mntpoint)
64 {
65 struct vnode *node = vnode_lookup(mntpoint);
66 if(!node) {
67 return -1;
68 }
69 if(node->type != VNODE_DIR) {
70 pvfs_errno = ENOTDIR;
71 return -1;
72 }
73 if(!node->target) {
74 pvfs_errno = EINVAL;
75 return -1;
76 }
77 node->target = 0;
78 return 0;
79 }
81 int pvfs_chdir(const char *path)
82 {
83 return vnode_chdir(path);
84 }
86 int pvfs_mkdir(const char *path, unsigned int mode)
87 {
88 char *ppath;
89 const char *dname;
90 struct vnode *parent = 0;
92 ppath = alloca(strlen(path) + 1);
93 strcpy(ppath, path);
95 if((dname = strrchr(path, '/'))) {
96 ppath[++dname - path] = 0;
97 if(!*dname) {
98 pvfs_errno = ENOENT;
99 return -1;
100 }
101 if(!(parent = vnode_lookup(ppath))) {
102 return -1;
103 }
104 } else {
105 dname = ppath;
106 parent = vnode_getcwd();
107 }
109 return vnode_mkdir(parent, dname);
110 }
112 PVFS_FILE *pvfs_fopen(const char *fname, const char *mode)
113 {
114 FILE *fp;
115 struct vnode *node;
117 /* if we find it in the filesystem, just use it... */
118 if((fp = fopen(fname, mode))) {
119 PVFS_FILE *vfp = malloc(sizeof *vfp);
120 if(!vfp) {
121 pvfs_errno = ENOMEM;
122 return 0;
123 }
124 vfp->fp = fp;
125 vfp->real = 1;
126 return vfp;
127 }
129 /* otherwise try and locate it in the virtual hierarchy */
130 if(!(node = vnode_lookup(fname))) {
131 return 0;
132 }
133 if(node->type != VNODE_FILE) {
134 pvfs_errno = EISDIR;
135 return 0;
136 }
138 return VFILE(node);
139 }
141 int pvfs_fclose(PVFS_FILE *fp)
142 {
143 if(fp->real) {
144 /* it's real, just close it and free the struct */
145 fclose(fp->fp);
146 free(fp);
147 return 0;
148 }
150 /* TODO */
151 return -1;
152 }
154 int pvfs_fseek(PVFS_FILE *fp, long offset, int whence);
155 long pvfs_ftell(PVFS_FILE *fp);
156 void pvfs_rewind(PVFS_FILE *fp);
158 size_t pvfs_fread(void *buf, size_t size, size_t nitems, PVFS_FILE *fp);
159 size_t pvfs_write(void *buf, size_t size, size_t nitems, PVFS_FILE *fp);
161 int pvfs_fgetc(PVFS_FILE *fp);
162 int pvfs_fputc(int c, PVFS_FILE *fp);
164 char *pvfs_fgets(char *buf, int size, PVFS_FILE *fp);
165 int pvfs_fputs(char *buf, PVFS_FILE *fp);
167 int pvfs_fscanf(PVFS_FILE *fp, const char *fmt, ...);
168 int pvfs_vfscanf(PVFS_FILE *fp, const char *fmt, va_list ap);
169 int pvfs_fprintf(PVFS_FILE *fp, const char *fmt, ...);
170 int pvfs_vfprintf(PVFS_FILE *fp, const char *fmt, va_list ap);
172 void pvfs_clearerr(PVFS_FILE *fp);
173 int pvfs_feof(PVFS_FILE *fp);
174 int pvfs_ferror(PVFS_FILE *fp);
176 /* POSIX stuff */
177 PVFS_DIR *pvfs_opendir(const char *dirname)
178 {
179 DIR *dir;
180 struct vnode *node;
182 if((dir = opendir(dirname))) {
183 PVFS_DIR *vdir = malloc(sizeof *vdir);
184 if(!vdir) {
185 pvfs_errno = ENOMEM;
186 return 0;
187 }
189 vdir->real = 1;
190 vdir->dir = dir;
191 return vdir;
192 }
194 if(!(node = vnode_lookup(dirname))) {
195 return 0;
196 }
197 if(node->type != VNODE_DIR) {
198 pvfs_errno = ENOTDIR;
199 return 0;
200 }
201 return VDIR(node);
202 }
204 int pvfs_closedir(PVFS_DIR *dir)
205 {
206 if(dir->real) {
207 int res = closedir(dir->dir);
208 free(dir);
209 return res;
210 }
212 /* TODO */
213 return -1;
214 }
215 struct pvfs_dirent *pvfs_readdir(PVFS_DIR *dir);
216 void pvfs_rewinddir(PVFS_DIR *dir);
218 int pvfs_stat(const char *path, struct pvfs_stat *buf);