packvfs
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/pvfs.c Fri Aug 02 06:03:38 2013 +0300 1.3 @@ -0,0 +1,219 @@ 1.4 +#include <string.h> 1.5 +#include <alloca.h> 1.6 +#include <assert.h> 1.7 +#include "pvfs.h" 1.8 +#include "vnode.h" 1.9 + 1.10 +int pvfs_errno; 1.11 + 1.12 +int pvfs_mount(const char *mntpoint, const char *target) 1.13 +{ 1.14 + struct vnode *srcnode, *destnode; 1.15 + 1.16 + /* first locate the mount point vnode */ 1.17 + if(!(srcnode = vnode_lookup(mntpoint))) { 1.18 + pvfs_errno = ENOENT; 1.19 + return -1; 1.20 + } 1.21 + /* and make sure it's a directory */ 1.22 + if(srcnode->type != VNODE_DIR) { 1.23 + pvfs_errno = ENOTDIR; 1.24 + return -1; 1.25 + } 1.26 + 1.27 + /* then locate the target vnode (if it exists) */ 1.28 + if(!(destnode = vnode_lookup(target))) { 1.29 + /* it's some error other than that target doesn't exist, fail... */ 1.30 + if(pvfs_errno != ENOENT) { 1.31 + return -1; 1.32 + } 1.33 + /* if it doesn't exist, it might be the case we're trying 1.34 + * to mount a package file or a real directory here. let's 1.35 + * try them in turn... 1.36 + */ 1.37 + PVFS_DIR *dir; 1.38 + PVFS_FILE *fp; 1.39 + 1.40 + if((dir = pvfs_opendir(target))) { 1.41 + /* it's obviously a real dir as vnode_lookup failed before... */ 1.42 + assert(dir->real); 1.43 + if(!(destnode = vnode_create_dir(target, dir))) { 1.44 + return -1; 1.45 + } 1.46 + 1.47 + } else if((fp = pvfs_fopen(target, "rb"))) { 1.48 + /* again, obviously real... */ 1.49 + assert(fp->real); 1.50 + if(!(destnode = vnode_create_file(target, fp))) { 1.51 + return -1; 1.52 + } 1.53 + 1.54 + } else { 1.55 + /* it's neither... so let's fail */ 1.56 + pvfs_errno = ENOENT; 1.57 + return -1; 1.58 + } 1.59 + } 1.60 + 1.61 + /* ok so we've got the two nodes, connect them up */ 1.62 + srcnode->target = destnode; 1.63 + return 0; 1.64 +} 1.65 + 1.66 +int pvfs_umount(const char *mntpoint) 1.67 +{ 1.68 + struct vnode *node = vnode_lookup(mntpoint); 1.69 + if(!node) { 1.70 + return -1; 1.71 + } 1.72 + if(node->type != VNODE_DIR) { 1.73 + pvfs_errno = ENOTDIR; 1.74 + return -1; 1.75 + } 1.76 + if(!node->target) { 1.77 + pvfs_errno = EINVAL; 1.78 + return -1; 1.79 + } 1.80 + node->target = 0; 1.81 + return 0; 1.82 +} 1.83 + 1.84 +int pvfs_chdir(const char *path) 1.85 +{ 1.86 + return vnode_chdir(path); 1.87 +} 1.88 + 1.89 +int pvfs_mkdir(const char *path, unsigned int mode) 1.90 +{ 1.91 + char *ppath; 1.92 + const char *dname; 1.93 + struct vnode *parent = 0; 1.94 + 1.95 + ppath = alloca(strlen(path) + 1); 1.96 + strcpy(ppath, path); 1.97 + 1.98 + if((dname = strrchr(path, '/'))) { 1.99 + ppath[++dname - path] = 0; 1.100 + if(!*dname) { 1.101 + pvfs_errno = ENOENT; 1.102 + return -1; 1.103 + } 1.104 + if(!(parent = vnode_lookup(ppath))) { 1.105 + return -1; 1.106 + } 1.107 + } else { 1.108 + dname = ppath; 1.109 + parent = vnode_getcwd(); 1.110 + } 1.111 + 1.112 + return vnode_mkdir(parent, dname); 1.113 +} 1.114 + 1.115 +PVFS_FILE *pvfs_fopen(const char *fname, const char *mode) 1.116 +{ 1.117 + FILE *fp; 1.118 + struct vnode *node; 1.119 + 1.120 + /* if we find it in the filesystem, just use it... */ 1.121 + if((fp = fopen(fname, mode))) { 1.122 + PVFS_FILE *vfp = malloc(sizeof *vfp); 1.123 + if(!vfp) { 1.124 + pvfs_errno = ENOMEM; 1.125 + return 0; 1.126 + } 1.127 + vfp->fp = fp; 1.128 + vfp->real = 1; 1.129 + return vfp; 1.130 + } 1.131 + 1.132 + /* otherwise try and locate it in the virtual hierarchy */ 1.133 + if(!(node = vnode_lookup(fname))) { 1.134 + return 0; 1.135 + } 1.136 + if(node->type != VNODE_FILE) { 1.137 + pvfs_errno = EISDIR; 1.138 + return 0; 1.139 + } 1.140 + 1.141 + return VFILE(node); 1.142 +} 1.143 + 1.144 +int pvfs_fclose(PVFS_FILE *fp) 1.145 +{ 1.146 + if(fp->real) { 1.147 + /* it's real, just close it and free the struct */ 1.148 + fclose(fp->fp); 1.149 + free(fp); 1.150 + return 0; 1.151 + } 1.152 + 1.153 + /* TODO */ 1.154 + return -1; 1.155 +} 1.156 + 1.157 +int pvfs_fseek(PVFS_FILE *fp, long offset, int whence); 1.158 +long pvfs_ftell(PVFS_FILE *fp); 1.159 +void pvfs_rewind(PVFS_FILE *fp); 1.160 + 1.161 +size_t pvfs_fread(void *buf, size_t size, size_t nitems, PVFS_FILE *fp); 1.162 +size_t pvfs_write(void *buf, size_t size, size_t nitems, PVFS_FILE *fp); 1.163 + 1.164 +int pvfs_fgetc(PVFS_FILE *fp); 1.165 +int pvfs_fputc(int c, PVFS_FILE *fp); 1.166 + 1.167 +char *pvfs_fgets(char *buf, int size, PVFS_FILE *fp); 1.168 +int pvfs_fputs(char *buf, PVFS_FILE *fp); 1.169 + 1.170 +int pvfs_fscanf(PVFS_FILE *fp, const char *fmt, ...); 1.171 +int pvfs_vfscanf(PVFS_FILE *fp, const char *fmt, va_list ap); 1.172 +int pvfs_fprintf(PVFS_FILE *fp, const char *fmt, ...); 1.173 +int pvfs_vfprintf(PVFS_FILE *fp, const char *fmt, va_list ap); 1.174 + 1.175 +void pvfs_clearerr(PVFS_FILE *fp); 1.176 +int pvfs_feof(PVFS_FILE *fp); 1.177 +int pvfs_ferror(PVFS_FILE *fp); 1.178 + 1.179 +/* POSIX stuff */ 1.180 +PVFS_DIR *pvfs_opendir(const char *dirname) 1.181 +{ 1.182 + DIR *dir; 1.183 + struct vnode *node; 1.184 + 1.185 + if((dir = opendir(dirname))) { 1.186 + PVFS_DIR *vdir = malloc(sizeof *vdir); 1.187 + if(!vdir) { 1.188 + pvfs_errno = ENOMEM; 1.189 + return 0; 1.190 + } 1.191 + 1.192 + vdir->real = 1; 1.193 + vdir->dir = dir; 1.194 + return vdir; 1.195 + } 1.196 + 1.197 + if(!(node = vnode_lookup(dirname))) { 1.198 + return 0; 1.199 + } 1.200 + if(node->type != VNODE_DIR) { 1.201 + pvfs_errno = ENOTDIR; 1.202 + return 0; 1.203 + } 1.204 + return VDIR(node); 1.205 +} 1.206 + 1.207 +int pvfs_closedir(PVFS_DIR *dir) 1.208 +{ 1.209 + if(dir->real) { 1.210 + int res = closedir(dir->dir); 1.211 + free(dir); 1.212 + return res; 1.213 + } 1.214 + 1.215 + /* TODO */ 1.216 + return -1; 1.217 +} 1.218 +struct pvfs_dirent *pvfs_readdir(PVFS_DIR *dir); 1.219 +void pvfs_rewinddir(PVFS_DIR *dir); 1.220 + 1.221 +int pvfs_stat(const char *path, struct pvfs_stat *buf); 1.222 +