Npfcall* diod_lcreate(Npfid *fid, Npstr *name, u32 flags, u32 mode, u32 gid) { Fid *f = fid->aux; Npfcall *ret = NULL; char *npath = NULL; Npqid qid; int fd = -1; struct stat sb; mode_t saved_umask; int created = 0; u32 iounit = 0; /* client will use msize-P9_IOHDRSZ */ if ((f->xflags & XFLAGS_RO)) { np_uerror (EROFS); goto error_quiet; } if (!(flags & O_CREAT)) /* can't happen? */ flags |= O_CREAT; if (!(npath = _mkpath(f->path, name))) { np_uerror (ENOMEM); goto error; } saved_umask = umask(0); if ((fd = open (npath, flags, mode)) < 0) { np_uerror (errno); goto error_quiet; } created = 1; umask(saved_umask); if (fstat (fd, &sb) < 0) { np_uerror (errno); goto error; /* shouldn't happen? */ } _ustat2qid (&sb, &qid); //iounit = sb.st_blksize; if (!((ret = np_create_rlcreate (&qid, iounit)))) { np_uerror (ENOMEM); goto error; } free (f->path); f->path = npath; f->fd = fd; return ret; error: errn (np_rerror (), "diod_lcreate %s@%s:%s/%.*s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path, name->len, name->str); error_quiet: if (fd >= 0) { (void)close (fd); } if (created && npath) (void)unlink (npath); if (npath) free (npath); if (ret) free (ret); return NULL; }
Npfcall* diod_symlink(Npfid *fid, Npstr *name, Npstr *symtgt, u32 gid) { Fid *f = fid->aux; Npfcall *ret = NULL; char *target = NULL, *npath = NULL; Npqid qid; struct stat sb; mode_t saved_umask; int created = 0; if ((f->xflags & XFLAGS_RO)) { np_uerror (EROFS); goto error_quiet; } if (!(npath = _mkpath(f->path, name))) { np_uerror (ENOMEM); goto error; } if (!(target = np_strdup (symtgt))) { np_uerror (ENOMEM); goto error; } saved_umask = umask(0); if (symlink (target, npath) < 0) { np_uerror (errno); goto error_quiet; } created = 1; umask(saved_umask); if (lstat (npath, &sb) < 0) { np_uerror (errno); goto error; /* shouldn't happen? */ } _ustat2qid (&sb, &qid); if (!((ret = np_create_rsymlink (&qid)))) { np_uerror (ENOMEM); goto error; } free (npath); free (target); return ret; error: errn (np_rerror (), "diod_symlink %s@%s:%s/%.*s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path, name->len, name->str); error_quiet: if (created && npath) (void)unlink (npath); if (npath) free (npath); if (target) free (target); if (ret) free (ret); return NULL; }
static int _mkdir (const char *path, int mode, int fatal) { int r; r = _mkpath(path, mode, fatal); if (r < 0) return r; r = mkdir(path, mode); if (r < 0 && errno != EEXIST) { if (fatal) _fatal("cannot create directory %s", path); return r; } return 0; }
/* Trename - rename a file, potentially to another directory */ Npfcall* diod_rename (Npfid *fid, Npfid *dfid, Npstr *name) { Fid *f = fid->aux; Fid *d = dfid->aux; Npfcall *ret = NULL; char *npath = NULL; int renamed = 0; if ((f->xflags & XFLAGS_RO)) { np_uerror (EROFS); goto error_quiet; } if (!(npath = _mkpath(d->path, name))) { np_uerror (ENOMEM); goto error; } if (rename (f->path, npath) < 0) { np_uerror (errno); goto error_quiet; } renamed = 1; if (!(ret = np_create_rrename ())) { np_uerror (ENOMEM); goto error; } free (f->path); f->path = npath; return ret; error: errn (np_rerror (), "diod_rename %s@%s:%s to %s/%.*s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path, d->path, name->len, name->str); error_quiet: if (renamed && npath) (void)rename (npath, f->path); if (npath) free (npath); if (ret) free (f); return NULL; }
/* Twalk - walk a file path * Called from fcall.c::np_walk () on each wname component in succession. * On error, call np_uerror () and return 0. */ int diod_walk (Npfid *fid, Npstr* wname, Npqid *wqid) { Fid *f = fid->aux; struct stat sb, sb2; char *npath = NULL; if (f->mountpt) { np_uerror (ENOENT); goto error_quiet; } if (!(npath = _mkpath (f->path, wname))) { np_uerror (ENOMEM); goto error; } if (lstat (npath, &sb) < 0) { np_uerror (errno); goto error_quiet; } if (lstat (f->path, &sb2) < 0) { np_uerror (errno); goto error; } if (sb.st_dev != sb2.st_dev) { if (_statmnt (npath, &sb) < 0) goto error; f->mountpt = 1; } free (f->path); f->path = npath; _ustat2qid (&sb, wqid); return 1; error: errn (np_rerror (), "diod_walk %s@%s:%s/%.*s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path, wname->len, wname->str); error_quiet: if (npath) free (npath); return 0; }
Npfcall* diod_link (Npfid *dfid, Npfid *fid, Npstr *name) { Fid *f = fid->aux; Npfcall *ret = NULL; Fid *df = dfid->aux; char *npath = NULL; int created = 0; if ((f->xflags & XFLAGS_RO)) { np_uerror (EROFS); goto error_quiet; } if (!(npath = _mkpath(df->path, name))) { np_uerror (ENOMEM); goto error; } if (link (f->path, npath) < 0) { np_uerror (errno); goto error_quiet; } created = 1; if (!((ret = np_create_rlink ()))) { np_uerror (ENOMEM); goto error; } free (npath); return ret; error: errn (np_rerror (), "diod_link %s@%s:%s %s/%.*s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path, df->path, name->len, name->str); error_quiet: if (created && npath) (void)unlink (npath); if (npath) free (npath); if (ret) free (ret); return NULL; }
/* Twalk - walk a file path * Called from fcall.c::np_walk () on each wname component in succession. * On error, call np_uerror () and return 0. */ int diod_walk (Npfid *fid, Npstr* wname, Npqid *wqid) { Fid *f = fid->aux; struct stat st; char *npath; if (!(npath = _mkpath (f->path, wname))) { np_uerror (ENOMEM); goto error; } if (lstat (npath, &st) < 0) { np_uerror (errno); goto error_quiet; } /* N.B. inodes would not be unique if we could cross over to another * file system. But with the code below, ls -l returns ??? for mount * point dirs, which would otherwise have a "foreign" inode number. * How does NFS make them appear as empty directories? That would be * prettier. */ if (_fidstat (f) < 0) goto error; if (st.st_dev != f->stat.st_dev) { np_uerror (EXDEV); goto error; } free (f->path); f->path = npath; _ustat2qid (&st, wqid); return 1; error: errn (np_rerror (), "diod_walk %s@%s:%s/%.*s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path, wname->len, wname->str); error_quiet: if (npath) free (npath); return 0; }
Npfcall* diod_mknod(Npfid *fid, Npstr *name, u32 mode, u32 major, u32 minor, u32 gid) { Npfcall *ret; Fid *f = fid->aux; char *npath = NULL; Npqid qid; struct stat sb; if ((f->xflags & XFLAGS_RO)) { np_uerror (EROFS); goto error_quiet; } if (!(npath = _mkpath(f->path, name))) { np_uerror (ENOMEM); goto error; } if (mknod (npath, mode, makedev (major, minor)) < 0 || lstat (npath, &sb) < 0) { np_uerror (errno); goto error_quiet; } _ustat2qid (&sb, &qid); if (!((ret = np_create_rmknod (&qid)))) { (void)unlink (npath); np_uerror (ENOMEM); goto error; } free (npath); return ret; error: errn (np_rerror (), "diod_mknod %s@%s:%s/%.*s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path, name->len, name->str); error_quiet: if (npath) free (npath); return NULL; }