#include "u.h"#include <sys/types.h>#include <sys/stat.h>#include <dirent.h>#include <fcntl.h>#include <errno.h>#include <stdio.h> /* for remove, rename */#include <limits.h> #ifndef NAME_MAX# define NAME_MAX 256#endif#include "lib.h"#include "dat.h"#include "fns.h"#include "error.h" typedef struct Ufsinfo Ufsinfo; enum{ NUID = 256, NGID = 256, MAXPATH = 1024, MAXCOMP = 128}; struct Ufsinfo{ int mode; int fd; int uid; int gid; DIR* dir; vlong offset; QLock oq; char* path; char nextname[NAME_MAX];}; char *base = "/"; static Qid fsqid(char*, struct stat *);static char* catpath(char*, char*);static ulong fsdirread(Chan*, uchar*, int, ulong);static int fsomode(int); static char*lastelem(char *s){ char *t; if((t = strrchr(s, '/')) == nil) return s; if(t[1] == 0) return t; return t+1;} static Chan*fsattach(char *spec){ Chan *c; struct stat stbuf; static int devno; Ufsinfo *uif; if(stat(base, &stbuf) < 0) error(strerror(errno)); c = devattach('U', spec); uif = mallocz(sizeof(Ufsinfo), 1); uif->mode = stbuf.st_mode; uif->uid = stbuf.st_uid; uif->gid = stbuf.st_gid; c->aux = uif; c->dev = devno++; c->qid.type = QTDIR;/*print("fsattach %s\n", c2name(c));*/ return c;} static Chan*fsclone(Chan *c, Chan *nc){ Ufsinfo *uif; uif = mallocz(sizeof(Ufsinfo), 1); *uif = *(Ufsinfo*)c->aux; nc->aux = uif; return nc;} static intfswalk1(Chan *c, char *name){ struct stat stbuf; char *path; Ufsinfo *uif; uif = c->aux; path = catpath(uif->path, name); /*print("** fs walk '%s' -> %s\n", path, name); */ if(stat(path, &stbuf) < 0) { free(path); return 0; } uif->mode = stbuf.st_mode; uif->uid = stbuf.st_uid; uif->gid = stbuf.st_gid; c->qid = fsqid(path, &stbuf); free(path); return 1;} static Walkqid*fswalk(Chan *c, Chan *nc, char **name, int nname){ int i; Walkqid *wq; if(nc != nil) panic("fswalk: nc != nil"); wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); nc = devclone(c); fsclone(c, nc); wq->clone = nc; for(i=0; i<nname; i++){ if(fswalk1(nc, name[i]) == 0) break; wq->qid[i] = nc->qid; } if(i != nname){ cclose(nc); wq->clone = nil; } wq->nqid = i; return wq;} static intfsstat(Chan *c, uchar *buf, int n){ Dir d; struct stat stbuf; Ufsinfo *uif; if(n < BIT16SZ) error(Eshortstat); uif = c->aux; if(stat(uif->path, &stbuf) < 0) error(strerror(errno)); d.name = lastelem(uif->path); d.uid = "unknown"; d.gid = "unknown"; d.muid = "unknown"; d.qid = c->qid; d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777); d.atime = stbuf.st_atime; d.mtime = stbuf.st_mtime; d.length = stbuf.st_size; d.type = 'U'; d.dev = c->dev; return convD2M(&d, buf, n);} static Chan*fsopen(Chan *c, int mode){ char *path; int m, isdir; Ufsinfo *uif; /*print("fsopen %s\n", c2name(c));*/ m = mode & (OTRUNC|3); switch(m) { case 0: break; case 1: case 1|16: break; case 2: case 0|16: case 2|16: break; case 3: break; default: error(Ebadarg); } isdir = c->qid.type & QTDIR; if(isdir && mode != OREAD) error(Eperm); m = fsomode(m & 3); c->mode = openmode(mode); uif = c->aux; path = uif->path; if(isdir) { uif->dir = opendir(path); if(uif->dir == 0) error(strerror(errno)); } else { if(mode & OTRUNC) m |= O_TRUNC; uif->fd = open(path, m, 0666); if(uif->fd < 0) error(strerror(errno)); } uif->offset = 0; c->offset = 0; c->flag |= COPEN; return c;} static Chan*fscreate(Chan *c, char *name, int mode, ulong perm){ int fd, m; char *path; struct stat stbuf; Ufsinfo *uif; m = fsomode(mode&3); uif = c->aux; path = catpath(uif->path, name); if(perm & DMDIR) { if(m) error(Eperm); if(mkdir(path, perm & 0777) < 0) error(strerror(errno)); fd = open(path, 0); if(fd >= 0) { chmod(path, perm & 0777); chown(path, uif->uid, uif->uid); } close(fd); uif->dir = opendir(path); if(uif->dir == 0) error(strerror(errno)); } else { fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0666); if(fd >= 0) { if(m != 1) { close(fd); fd = open(path, m); } chmod(path, perm & 0777); chown(path, uif->uid, uif->gid); } if(fd < 0) error(strerror(errno)); uif->fd = fd; } if(stat(path, &stbuf) < 0) error(strerror(errno)); c->qid = fsqid(path, &stbuf); free(path); c->offset = 0; c->flag |= COPEN; c->mode = openmode(mode); return c;} static voidfsclose(Chan *c){ Ufsinfo *uif; uif = c->aux; if(c->flag & COPEN) { if(c->qid.type & QTDIR) closedir(uif->dir); else close(uif->fd); } free(uif);} static longfsread(Chan *c, void *va, long n, vlong offset){ int fd, r; Ufsinfo *uif; /*print("fsread %s\n", c2name(c));*/ if(c->qid.type & QTDIR) return fsdirread(c, va, n, offset); uif = c->aux; qlock(&uif->oq); if(waserror()) { qunlock(&uif->oq); nexterror(); } fd = uif->fd; if(uif->offset != offset) { r = lseek(fd, offset, 0); if(r < 0) error(strerror(errno)); uif->offset = offset; } n = read(fd, va, n); if(n < 0) error(strerror(errno)); uif->offset += n; qunlock(&uif->oq); poperror(); return n;} static longfswrite(Chan *c, void *va, long n, vlong offset){ int fd, r; Ufsinfo *uif; uif = c->aux; qlock(&uif->oq); if(waserror()) { qunlock(&uif->oq); nexterror(); } fd = uif->fd; if(uif->offset != offset) { r = lseek(fd, offset, 0); if(r < 0) error(strerror(errno)); uif->offset = offset; } n = write(fd, va, n); if(n < 0) error(strerror(errno)); uif->offset += n; qunlock(&uif->oq); poperror(); return n;} static voidfsremove(Chan *c){ int n; char *path; Ufsinfo *uif; uif = c->aux; path = uif->path; if(c->qid.type & QTDIR) n = rmdir(path); else n = remove(path); if(n < 0) error(strerror(errno));} intfswstat(Chan *c, uchar *buf, int n){ Dir d; struct stat stbuf; char *old, new[MAXPATH]; char strs[MAXPATH*3], *p; Ufsinfo *uif; if(convM2D(buf, n, &d, strs) != n) error(Ebadstat); uif = c->aux; if(stat(uif->path, &stbuf) < 0) error(strerror(errno)); if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) { if(chmod(uif->path, d.mode&0777) < 0) error(strerror(errno)); uif->mode &= ~0777; uif->mode |= d.mode&0777; } if(d.name[0] && strcmp(d.name, lastelem(uif->path)) != 0) { old = uif->path; strcpy(new, old); p = strrchr(new, '/'); strcpy(p+1, d.name); if(rename(old, new) < 0) error(strerror(errno)); } /* p = name2pass(gid, d.gid); if(p == 0) error(Eunknown); if(p->id != stbuf.st_gid) { if(chown(old, stbuf.st_uid, p->id) < 0) error(strerror(errno)); uif->gid = p->id; }*/ return n;} static Qidfsqid(char *p, struct stat *st){ Qid q; int dev; ulong h; static int nqdev; static uchar *qdev; if(qdev == 0) qdev = mallocz(65536U, 1); q.type = 0; if((st->st_mode&S_IFMT) == S_IFDIR) q.type = QTDIR; dev = st->st_dev & 0xFFFFUL; if(qdev[dev] == 0) qdev[dev] = ++nqdev; h = 0; while(*p != '\0') h += *p++ * 13; q.path = (vlong)qdev[dev]<<32; q.path |= h; q.vers = st->st_mtime; return q;} static char*catpath(char *base, char *ext){ char *path; int n, m; n = strlen(base); m = strlen(ext); path = malloc(n+m+2); memmove(path, base, n); if(n > 0 && path[n-1] != '/') path[n++] = '/'; memmove(path+n, ext, m+1); return path;} static intisdots(char *name){ if(name[0] != '.') return 0; if(name[1] == '\0') return 1; if(name[1] != '.') return 0; if(name[2] == '\0') return 1; return 0;Lines 1–500 of 621. Load more
#include "u.h" #include <sys/types.h> #include <sys/stat.h> #include <dirent.h> #include <fcntl.h> #include <errno.h> #include <stdio.h> /* for remove, rename */ #include <limits.h> #ifndef NAME_MAX # define NAME_MAX 256 #endif #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" typedef struct Ufsinfo Ufsinfo; enum { NUID = 256, NGID = 256, MAXPATH = 1024, MAXCOMP = 128 }; struct Ufsinfo { int mode; int fd; int uid; int gid; DIR* dir; vlong offset; QLock oq; char* path; char nextname[NAME_MAX]; }; char *base = "/"; static Qid fsqid(char*, struct stat *); static char* catpath(char*, char*); static ulong fsdirread(Chan*, uchar*, int, ulong); static int fsomode(int); static char* lastelem(char *s) { char *t; if((t = strrchr(s, '/')) == nil) return s; if(t[1] == 0) return t; return t+1; } static Chan* fsattach(char *spec) { Chan *c; struct stat stbuf; static int devno; Ufsinfo *uif; if(stat(base, &stbuf) < 0) error(strerror(errno)); c = devattach('U', spec); uif = mallocz(sizeof(Ufsinfo), 1); uif->mode = stbuf.st_mode; uif->uid = stbuf.st_uid; uif->gid = stbuf.st_gid; c->aux = uif; c->dev = devno++; c->qid.type = QTDIR; /*print("fsattach %s\n", c2name(c));*/ return c; } static Chan* fsclone(Chan *c, Chan *nc) { Ufsinfo *uif; uif = mallocz(sizeof(Ufsinfo), 1); *uif = *(Ufsinfo*)c->aux; nc->aux = uif; return nc; } static int fswalk1(Chan *c, char *name) { struct stat stbuf; char *path; Ufsinfo *uif; uif = c->aux; path = catpath(uif->path, name); /*print("** fs walk '%s' -> %s\n", path, name); */ if(stat(path, &stbuf) < 0) { free(path); return 0; } uif->mode = stbuf.st_mode; uif->uid = stbuf.st_uid; uif->gid = stbuf.st_gid; c->qid = fsqid(path, &stbuf); free(path); return 1; } static Walkqid* fswalk(Chan *c, Chan *nc, char **name, int nname) { int i; Walkqid *wq; if(nc != nil) panic("fswalk: nc != nil"); wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); nc = devclone(c); fsclone(c, nc); wq->clone = nc; for(i=0; i<nname; i++){ if(fswalk1(nc, name[i]) == 0) break; wq->qid[i] = nc->qid; } if(i != nname){ cclose(nc); wq->clone = nil; } wq->nqid = i; return wq; } static int fsstat(Chan *c, uchar *buf, int n) { Dir d; struct stat stbuf; Ufsinfo *uif; if(n < BIT16SZ) error(Eshortstat); uif = c->aux; if(stat(uif->path, &stbuf) < 0) error(strerror(errno)); d.name = lastelem(uif->path); d.uid = "unknown"; d.gid = "unknown"; d.muid = "unknown"; d.qid = c->qid; d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777); d.atime = stbuf.st_atime; d.mtime = stbuf.st_mtime; d.length = stbuf.st_size; d.type = 'U'; d.dev = c->dev; return convD2M(&d, buf, n); } static Chan* fsopen(Chan *c, int mode) { char *path; int m, isdir; Ufsinfo *uif; /*print("fsopen %s\n", c2name(c));*/ m = mode & (OTRUNC|3); switch(m) { case 0: break; case 1: case 1|16: break; case 2: case 0|16: case 2|16: break; case 3: break; default: error(Ebadarg); } isdir = c->qid.type & QTDIR; if(isdir && mode != OREAD) error(Eperm); m = fsomode(m & 3); c->mode = openmode(mode); uif = c->aux; path = uif->path; if(isdir) { uif->dir = opendir(path); if(uif->dir == 0) error(strerror(errno)); } else { if(mode & OTRUNC) m |= O_TRUNC; uif->fd = open(path, m, 0666); if(uif->fd < 0) error(strerror(errno)); } uif->offset = 0; c->offset = 0; c->flag |= COPEN; return c; } static Chan* fscreate(Chan *c, char *name, int mode, ulong perm) { int fd, m; char *path; struct stat stbuf; Ufsinfo *uif; m = fsomode(mode&3); uif = c->aux; path = catpath(uif->path, name); if(perm & DMDIR) { if(m) error(Eperm); if(mkdir(path, perm & 0777) < 0) error(strerror(errno)); fd = open(path, 0); if(fd >= 0) { chmod(path, perm & 0777); chown(path, uif->uid, uif->uid); } close(fd); uif->dir = opendir(path); if(uif->dir == 0) error(strerror(errno)); } else { fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0666); if(fd >= 0) { if(m != 1) { close(fd); fd = open(path, m); } chmod(path, perm & 0777); chown(path, uif->uid, uif->gid); } if(fd < 0) error(strerror(errno)); uif->fd = fd; } if(stat(path, &stbuf) < 0) error(strerror(errno)); c->qid = fsqid(path, &stbuf); free(path); c->offset = 0; c->flag |= COPEN; c->mode = openmode(mode); return c; } static void fsclose(Chan *c) { Ufsinfo *uif; uif = c->aux; if(c->flag & COPEN) { if(c->qid.type & QTDIR) closedir(uif->dir); else close(uif->fd); } free(uif); } static long fsread(Chan *c, void *va, long n, vlong offset) { int fd, r; Ufsinfo *uif; /*print("fsread %s\n", c2name(c));*/ if(c->qid.type & QTDIR) return fsdirread(c, va, n, offset); uif = c->aux; qlock(&uif->oq); if(waserror()) { qunlock(&uif->oq); nexterror(); } fd = uif->fd; if(uif->offset != offset) { r = lseek(fd, offset, 0); if(r < 0) error(strerror(errno)); uif->offset = offset; } n = read(fd, va, n); if(n < 0) error(strerror(errno)); uif->offset += n; qunlock(&uif->oq); poperror(); return n; } static long fswrite(Chan *c, void *va, long n, vlong offset) { int fd, r; Ufsinfo *uif; uif = c->aux; qlock(&uif->oq); if(waserror()) { qunlock(&uif->oq); nexterror(); } fd = uif->fd; if(uif->offset != offset) { r = lseek(fd, offset, 0); if(r < 0) error(strerror(errno)); uif->offset = offset; } n = write(fd, va, n); if(n < 0) error(strerror(errno)); uif->offset += n; qunlock(&uif->oq); poperror(); return n; } static void fsremove(Chan *c) { int n; char *path; Ufsinfo *uif; uif = c->aux; path = uif->path; if(c->qid.type & QTDIR) n = rmdir(path); else n = remove(path); if(n < 0) error(strerror(errno)); } int fswstat(Chan *c, uchar *buf, int n) { Dir d; struct stat stbuf; char *old, new[MAXPATH]; char strs[MAXPATH*3], *p; Ufsinfo *uif; if(convM2D(buf, n, &d, strs) != n) error(Ebadstat); uif = c->aux; if(stat(uif->path, &stbuf) < 0) error(strerror(errno)); if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) { if(chmod(uif->path, d.mode&0777) < 0) error(strerror(errno)); uif->mode &= ~0777; uif->mode |= d.mode&0777; } if(d.name[0] && strcmp(d.name, lastelem(uif->path)) != 0) { old = uif->path; strcpy(new, old); p = strrchr(new, '/'); strcpy(p+1, d.name); if(rename(old, new) < 0) error(strerror(errno)); } /* p = name2pass(gid, d.gid); if(p == 0) error(Eunknown); if(p->id != stbuf.st_gid) { if(chown(old, stbuf.st_uid, p->id) < 0) error(strerror(errno)); uif->gid = p->id; } */ return n; } static Qid fsqid(char *p, struct stat *st) { Qid q; int dev; ulong h; static int nqdev; static uchar *qdev; if(qdev == 0) qdev = mallocz(65536U, 1); q.type = 0; if((st->st_mode&S_IFMT) == S_IFDIR) q.type = QTDIR; dev = st->st_dev & 0xFFFFUL; if(qdev[dev] == 0) qdev[dev] = ++nqdev; h = 0; while(*p != '\0') h += *p++ * 13; q.path = (vlong)qdev[dev]<<32; q.path |= h; q.vers = st->st_mtime; return q; } static char* catpath(char *base, char *ext) { char *path; int n, m; n = strlen(base); m = strlen(ext); path = malloc(n+m+2); memmove(path, base, n); if(n > 0 && path[n-1] != '/') path[n++] = '/'; memmove(path+n, ext, m+1); return path; } static int isdots(char *name) { if(name[0] != '.') return 0; if(name[1] == '\0') return 1; if(name[1] != '.') return 0; if(name[2] == '\0') return 1; return 0;