static int fsdirstat(char *path, int dev, Dir *d) { int fd; struct stat st; if(stat(path, &st) < 0 && lstat(path, &st) < 0) return -1; d->name = lastelem(path); d->uid = uidtoname(st.st_uid); d->gid = gidtoname(st.st_gid); d->muid = ""; d->qid = fsqid(&st); d->mode = (d->qid.type<<24) | (st.st_mode&0777); d->atime = st.st_atime; d->mtime = st.st_mtime; d->length = st.st_size; if(S_ISBLK(st.st_mode) && (fd = open(path, O_RDONLY)) >= 0){ d->length = disksize(fd, &st); close(fd); } // devmnt leaves 1-9 unused so that we can steal them. // it is easier for all involved if #Z shows M as the file type instead of Z. // dev is c->dev, either 1 (#Z) or 2 (#Zplan9). d->type = 'M'; d->dev = dev; return 0; }
static Chan* fsattach(char *spec) { struct stat st; Chan *c; UnixFd *ufd; int dev; dev = 1; if(spec && spec[0]){ snprint(up->genbuf, sizeof up->genbuf, "no file system #%C%s", FsChar, spec); error(up->genbuf); } if(stat("/", &st) < 0) oserror(); c = devattach(FsChar, 0); ufd = mallocz(sizeof(UnixFd), 1); ufd->path = newpath("/"); ufd->fd = -1; c->aux = ufd; c->dev = dev; c->qid = fsqid(&st); if(Trace) print("fsattach /\n"); return c; }
static int fswalk1(Chan *c, char *name) { struct stat st; char *path; UnixFd *ufd; ufd = c->aux; if(strcmp(name, "..") == 0 && strcmp(ufd->path->s, "/") == 0) return 0; path = fspath(c, name); if(stat(path, &st) < 0){ if(Trace) print("fswalk1 %s (%s)\n", path, strerror(errno)); free(path); return -1; } if(Trace) print("fswalk1 %s\n", path); free(path); c->qid = fsqid(&st); return 0; }
static Chan* fsattach(char *spec) { struct stat st; Chan *c; UnixFd *ufd; int plan9, dev; dev = 1; plan9 = 0; if(spec && spec[0]){ if(strcmp(spec, "plan9") == 0) { plan9 = 1; dev = 2; } else{ snprint(up->genbuf, sizeof up->genbuf, "no file system #%C%s", FsChar, spec); error(up->genbuf); } } if(plan9){ if(localroot == nil) error("no #Zplan9 root without -r"); if(stat(localroot, &st) < 0) oserror(); }else{ if(stat("/", &st) < 0) oserror(); } c = devattach(FsChar, spec); ufd = mallocz(sizeof(UnixFd), 1); ufd->path = newpath("/"); ufd->plan9 = plan9; ufd->fd = -1; c->aux = ufd; c->dev = dev; c->qid = fsqid(&st); if(Trace) print("fsattach /\n"); return c; }
static void fscreate(Chan *c, char *name, int mode, ulong perm) { char *path, *path0; int fd, mm; UnixFd *ufd; struct stat st; ufd = c->aux; if(Trace) print("fscreate %s %#x %#o\n", ufd->path->s, mode, perm); if(!(c->qid.type & QTDIR)) error(Enotdir); if(mode & ~(OTRUNC|ORCLOSE|3)) error(Ebadarg); if(perm & ~(DMDIR|0777)) error(Ebadarg); path0 = fspath(c, nil); path = fspath(c, name); if(waserror()){ free(path); free(path0); nexterror(); } if(stat(path0, &st) < 0) oserror(); if(perm & DMDIR){ if(mode != OREAD) error(Eperm); /* have to do the minimum 0400 so we can open it */ if(mkdir(path, (0400 | perm) & 0777) < 0) oserror(); if((fd = open(path, 0)) < 0) oserror(); fchown(fd, -1, st.st_gid); if(fstat(fd, &st) < 0){ close(fd); oserror(); } if((ufd->dir = opendir(path)) == nil) { /* arguably we should set the mode here too * but it's hard to see that this case * will ever happen */ close(fd); oserror(); } // Be like Plan 9 file servers: inherit mode bits // and group from parent. fchmod(fd, perm & st.st_mode & 0777); close(fd); ufd->diroffset = 0; ufd->nextde = nil; }else{ mm = mode & 3; if(mode & OTRUNC) mm |= O_TRUNC; if((fd = open(path, mm|O_CREAT|O_EXCL, 0666)) < 0) oserror(); // Be like Plan 9 file servers: inherit mode bits // and group from parent. fchmod(fd, perm & st.st_mode & 0777); fchown(fd, -1, st.st_gid); if(fstat(fd, &st) < 0){ close(fd); oserror(); } ufd->fd = fd; } free(path); free(path0); poperror(); ufd->path = addelem(ufd->path, name, nil); c->qid = fsqid(&st); c->offset = 0; c->flag |= COPEN; c->mode = openmode(mode); }