static Spfcall* npfs_open(Spfid *fid, u8 mode) { int err; Fid *f; Spqid qid; f = fid->aux; npfs_change_user(fid->user); if ((err = fidstat(f)) < 0) create_rerror(err); if (S_ISDIR(f->stat.st_mode)) { f->dir = opendir(f->path); if (!f->dir) create_rerror(errno); } else { f->fd = open(f->path, omode2uflags(mode)); if (f->fd < 0) create_rerror(errno); } err = fidstat(f); if (err < 0) create_rerror(err); f->omode = mode; ustat2qid(&f->stat, &qid); return sp_create_ropen(&qid, 0); }
static int npfs_walk(Spfid *fid, Spstr* wname, Spqid *wqid) { int n; Fid *f; struct stat st; char *path; f = fid->aux; npfs_change_user(fid->user); n = fidstat(f); if (n < 0) create_rerror(n); n = strlen(f->path); path = malloc(n + wname->len + 2); memcpy(path, f->path, n); path[n] = '/'; memcpy(path + n + 1, wname->str, wname->len); path[n + wname->len + 1] = '\0'; if (lstat(path, &st) < 0) { free(path); create_rerror(errno); return 0; } free(f->path); f->path = path; ustat2qid(&st, wqid); return 1; }
static Spfcall* ufs_stat(Spfid *fid) { int err; Fid *f; Spfcall *ret; Spwstat wstat; f = fid->aux; err = fidstat(f); if (err < 0) create_rerror(err); ustat2npwstat(f->path, &f->stat, &wstat, fid->conn->dotu, fid->conn->srv->upool); ret = sp_create_rstat(&wstat, fid->conn->dotu); free(wstat.extension); return ret; }
static Spfcall* npfs_attach(Spfid *nfid, Spfid *nafid, Spstr *uname, Spstr *aname, u32 n_uname) { int err; Spfcall* ret; Fid *fid; Spqid qid; char *user; user = NULL; ret = NULL; if (nafid != NULL) { sp_werror(Enoauth, EIO); goto done; } fid = npfs_fidalloc(); fid->omode = -1; npfs_change_user(nfid->user); fid->omode = -1; if (aname->len==0 || *aname->str!='/') fid->path = strdup("/"); else fid->path = sp_strdup(aname); nfid->aux = fid; err = fidstat(fid); if (err < 0) { create_rerror(err); goto done; } ustat2qid(&fid->stat, &qid); ret = sp_create_rattach(&qid); sp_fid_incref(nfid); done: return ret; }
static Spfcall* npfs_wstat(Spfid *fid, Spstat *stat) { int err; Fid *f; Spfcall *ret; uid_t uid; gid_t gid; char *npath, *p, *s; Spuser *user; Spgroup *group; struct utimbuf tb; ret = NULL; f = fid->aux; npfs_change_user(fid->user); err = fidstat(f); if (err < 0) { create_rerror(err); goto out; } if (fid->conn->dotu) { uid = stat->n_uid; gid = stat->n_gid; } else { uid = (uid_t) -1; gid = (gid_t) -1; } if (uid == -1 && stat->uid.len) { s = sp_strdup(&stat->uid); user = sp_uname2user(s); free(s); if (!user) { sp_werror(Eunknownuser, EIO); goto out; } uid = user->uid; } if (gid == -1 && stat->gid.len) { s = sp_strdup(&stat->gid); group = sp_gname2group(s); free(s); if (!group) { sp_werror(Eunknownuser, EIO); goto out; } gid = group->gid; } if (stat->mode != (u32)~0) { if (stat->mode&Dmdir && !S_ISDIR(f->stat.st_mode)) { sp_werror(Edirchange, EIO); goto out; } if (chmod(f->path, npstat2umode(stat, fid->conn->dotu)) < 0) { create_rerror(errno); goto out; } } if (stat->mtime != (u32)~0) { tb.actime = 0; tb.modtime = stat->mtime; if (utime(f->path, &tb) < 0) { create_rerror(errno); goto out; } } if (gid != -1) { if (chown(f->path, uid, gid) < 0) { create_rerror(errno); goto out; } } if (stat->name.len != 0) { p = strrchr(f->path, '/'); if (!p) p = f->path + strlen(f->path); npath = malloc(stat->name.len + (p - f->path) + 2); memcpy(npath, f->path, p - f->path); npath[p - f->path] = '/'; memcpy(npath + (p - f->path) + 1, stat->name.str, stat->name.len); npath[(p - f->path) + 1 + stat->name.len] = 0; if (strcmp(npath, f->path) != 0) { if (rename(f->path, npath) < 0) { create_rerror(errno); goto out; } free(f->path); f->path = npath; } } if (stat->length != ~0) { if (truncate(f->path, stat->length) < 0) { create_rerror(errno); goto out; } } ret = sp_create_rwstat(); out: return ret; }
static Spfcall* npfs_create(Spfid *fid, Spstr *name, u32 perm, u8 mode, Spstr *extension) { int n, err, omode; Fid *f; Spfcall *ret; Spqid qid; char *npath; struct stat st; ret = NULL; omode = mode; f = fid->aux; if ((err = fidstat(f)) < 0) create_rerror(err); n = strlen(f->path); npath = malloc(n + name->len + 2); memmove(npath, f->path, n); npath[n] = '/'; memmove(npath + n + 1, name->str, name->len); npath[n + name->len + 1] = '\0'; if (lstat(npath, &st)==0 || errno!=ENOENT) { sp_werror(Eexist, EEXIST); goto out; } if (perm & Dmdir) { if (mkdir(npath, perm & 0777) < 0) { create_rerror(errno); goto out; } if (lstat(npath, &f->stat) < 0) { create_rerror(errno); rmdir(npath); goto out; } f->dir = opendir(npath); if (!f->dir) { create_rerror(errno); remove(npath); goto out; } } else if (perm & (Dmnamedpipe|Dmsymlink|Dmlink|Dmdevice)) { if (npfs_create_special(fid, npath, perm, extension) < 0) goto out; if (lstat(npath, &f->stat) < 0) { create_rerror(errno); remove(npath); goto out; } } else { f->fd = open(npath, O_CREAT|omode2uflags(mode), perm & 0777); if (f->fd < 0) { create_rerror(errno); goto out; } if (lstat(npath, &f->stat) < 0) { create_rerror(errno); remove(npath); goto out; } } free(f->path); f->path = npath; f->omode = omode; npath = NULL; ustat2qid(&f->stat, &qid); ret = sp_create_rcreate(&qid, 0); out: free(npath); return ret; }