Npfcall* diod_readdir(Npfid *fid, u64 offset, u32 count, Npreq *req) { int n; Fid *f = fid->aux; Npfcall *ret = NULL; if (!(ret = np_create_rreaddir (count))) { np_uerror (ENOMEM); goto error; } n = _read_dir_linux (f, ret->u.rreaddir.data, offset, count); if (np_rerror ()) { free (ret); ret = NULL; } else np_finalize_rreaddir (ret, n); return ret; error: errn (np_rerror (), "diod_readdir %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path); if (ret) free (ret); return NULL; }
Npfcall* diod_lcreate(Npfid *fid, Npstr *name, u32 flags, u32 mode, u32 gid) { Npsrv *srv = fid->conn->srv; Fid *f = fid->aux; Npfcall *ret; Path opath = NULL; if ((f->flags & DIOD_FID_FLAGS_ROFS)) { np_uerror (EROFS); goto error_quiet; } flags = _remap_oflags (flags); if (flags & O_DIRECT) { np_uerror (EINVAL); /* O_DIRECT not allowed - see issue 110 */ goto error_quiet; } if (!(flags & O_CREAT)) /* can't happen? */ flags |= O_CREAT; if (f->ioctx != NULL) { msg ("diod_lcreate: fid is already open"); np_uerror (EINVAL); goto error; } opath = f->path; if (!(f->path = path_append (srv, opath, name))) { np_uerror (ENOMEM); goto error; } if (ioctx_open (fid, flags, mode) < 0) { if (np_rerror () == ENOMEM) goto error; goto error_quiet; } if (!((ret = np_create_rlcreate (ioctx_qid (f->ioctx), ioctx_iounit (f->ioctx))))) { (void)ioctx_close (fid, 0); (void)unlink (path_s (f->path)); np_uerror (ENOMEM); goto error; } path_decref (srv, opath); return ret; error: errn (np_rerror (), "diod_lcreate %s@%s:%s/%.*s", fid->user->uname, np_conn_get_client_id (fid->conn), opath ? path_s (opath) : path_s (f->path), name->len, name->str); error_quiet: if (opath) { if (f->path) path_decref (srv, f->path); f->path = opath; } return NULL; }
/* Twrite - write to a file. */ Npfcall* diod_write (Npfid *fid, u64 offset, u32 count, u8 *data, Npreq *req) { Fid *f = fid->aux; Npfcall *ret; ssize_t n; if (!f->ioctx) { msg ("diod_write: fid is not open"); np_uerror (EBADF); goto error; } if ((f->flags & DIOD_FID_FLAGS_ROFS)) { np_uerror (EROFS); goto error_quiet; } if ((n = ioctx_pwrite (f->ioctx, data, count, offset)) < 0) { np_uerror (errno); goto error_quiet; } if (!(ret = np_create_rwrite (n))) { np_uerror (ENOMEM); goto error; } return ret; error: errn (np_rerror (), "diod_write %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), path_s (f->path)); error_quiet: return NULL; }
/* Tread - read from a file or directory. */ Npfcall* diod_read (Npfid *fid, u64 offset, u32 count, Npreq *req) { Fid *f = fid->aux; Npfcall *ret = NULL; ssize_t n; if (!f->ioctx) { msg ("diod_read: fid is not open"); np_uerror (EBADF); goto error; } if (!(ret = np_alloc_rread (count))) { np_uerror (ENOMEM); goto error; } n = ioctx_pread (f->ioctx, ret->u.rread.data, count, offset); if (n < 0) { np_uerror (errno); goto error_quiet; } np_set_rread_count (ret, n); return ret; error: errn (np_rerror (), "diod_read %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), path_s (f->path)); error_quiet: if (ret) free (ret); return NULL; }
Npcfid* npc_auth (Npcfsys *fs, char *aname, u32 uid, AuthFun auth) { Npcfid *afid = NULL; Npfcall *tc = NULL, *rc = NULL; if (!(afid = npc_fid_alloc (fs))) goto done; if (!(tc = np_create_tauth (afid->fid, NULL, aname, uid))) { np_uerror (ENOMEM); npc_fid_free (afid); afid = NULL; goto done; } if (afid->fsys->rpc (afid->fsys, tc, &rc) < 0) { npc_fid_free (afid); afid = NULL; goto done; } if (auth && auth (afid, uid) < 0) { int saved_err = np_rerror (); (void)npc_clunk (afid); afid = NULL; np_uerror (saved_err); goto done; } done: if (tc) free(tc); if (rc) free(rc); return afid; }
Npfcall* diod_fsync (Npfid *fid) { Fid *f = fid->aux; Npfcall *ret; if ((f->flags & DIOD_FID_FLAGS_ROFS)) { np_uerror (EROFS); goto error_quiet; } if (!f->ioctx) { msg ("diod_fsync: fid is not open"); np_uerror (EBADF); goto error; } if (ioctx_fsync (f->ioctx) < 0) { np_uerror (errno); goto error_quiet; } if (!((ret = np_create_rfsync ()))) { np_uerror (ENOMEM); goto error; } return ret; error: errn (np_rerror (), "diod_fsync %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), path_s (f->path)); error_quiet: return NULL; }
Npcfsys* npc_start (int rfd, int wfd, int msize, int flags) { Npcfsys *fs; Npfcall *tc = NULL, *rc = NULL; if ((flags & NPC_MULTI_RPC)) fs = npc_create_mtfsys (rfd, wfd, msize, flags); else fs = npc_create_fsys (rfd, wfd, msize, flags); if (!fs) goto done; if (!(tc = np_create_tversion (msize, "9P2000.L"))) { np_uerror (ENOMEM); goto done; } if (fs->rpc (fs, tc, &rc) < 0) goto done; if (rc->u.rversion.msize < msize) fs->msize = rc->u.rversion.msize; if (np_strcmp (&rc->u.rversion.version, "9P2000.L") != 0) { np_uerror(EIO); goto done; } done: if (tc) free (tc); if (rc) free (rc); if (np_rerror () && fs) { npc_finish (fs); fs = NULL; } return fs; }
/* Locking note: * Implement POSIX locks in terms of BSD flock locks. * This at least gets distributed whole-file locking to work. * Strategies for distributed record locking will deadlock. */ Npfcall* diod_lock (Npfid *fid, u8 type, u32 flags, u64 start, u64 length, u32 proc_id, Npstr *client_id) { Fid *f = fid->aux; Npfcall *ret = NULL; u8 status = P9_LOCK_ERROR; if ((f->xflags & XFLAGS_RO)) { np_uerror (EROFS); goto error_quiet; } if (flags & ~P9_LOCK_FLAGS_BLOCK) { /* only one valid flag for now */ np_uerror (EINVAL); /* (which we ignore) */ goto error; } if (_fidstat(f) < 0) goto error_quiet; switch (type) { case F_UNLCK: if (flock (f->fd, LOCK_UN) >= 0) { status = P9_LOCK_SUCCESS; f->lock_type = LOCK_UN; } else status = P9_LOCK_ERROR; break; case F_RDLCK: if (flock (f->fd, LOCK_SH | LOCK_NB) >= 0) { status = P9_LOCK_SUCCESS; f->lock_type = LOCK_SH; } else if (errno == EWOULDBLOCK) { status = P9_LOCK_BLOCKED; } else status = P9_LOCK_ERROR; break; case F_WRLCK: if (flock (f->fd, LOCK_EX | LOCK_NB) >= 0) { status = P9_LOCK_SUCCESS; f->lock_type = LOCK_EX; } else if (errno == EWOULDBLOCK) { status = P9_LOCK_BLOCKED; } break; default: np_uerror (EINVAL); goto error; } if (!((ret = np_create_rlock (status)))) { np_uerror (ENOMEM); goto error; } return ret; error: errn (np_rerror (), "diod_lock %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path); error_quiet: if (ret) free (ret); return NULL; }
/* Twrite - write to a file. */ Npfcall* diod_write (Npfid *fid, u64 offset, u32 count, u8 *data, Npreq *req) { Fid *f = fid->aux; Npfcall *ret; ssize_t n; if ((f->xflags & XFLAGS_RO)) { np_uerror (EROFS); goto error_quiet; } if ((n = pwrite (f->fd, data, count, offset)) < 0) { np_uerror (errno); goto error_quiet; } if (!(ret = np_create_rwrite (n))) { np_uerror (ENOMEM); goto error; } return ret; error: errn (np_rerror (), "diod_write %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path); error_quiet: return NULL; }
/* Tread - read from a file or directory. */ Npfcall* diod_read (Npfid *fid, u64 offset, u32 count, Npreq *req) { Fid *f = fid->aux; Npfcall *ret = NULL; ssize_t n; if (!(ret = np_alloc_rread (count))) { np_uerror (ENOMEM); goto error; } if ((n = pread (f->fd, ret->u.rread.data, count, offset)) < 0) { np_uerror (errno); goto error_quiet; } np_set_rread_count (ret, n); return ret; error: errn (np_rerror (), "diod_read %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path); error_quiet: if (ret) free (ret); return NULL; }
/* This needs to be called with the usercache lock held. * I don't think it's thread safe. -jg */ static int _getgrouplist (Npsrv *srv, Npuser *u) { int i, ret = -1; gid_t *sgcpy; u->nsg = sysconf(_SC_NGROUPS_MAX); if (u->nsg < 65536) u->nsg = 65536; if (!(u->sg = malloc (u->nsg * sizeof (gid_t)))) { np_uerror (ENOMEM); np_logerr (srv, "_alloc_user: %s", u->uname); goto done; } if (getgrouplist(u->uname, u->gid, u->sg, &u->nsg) == -1) { np_logerr (srv, "_alloc_user: %s: getgrouplist", u->uname); if (np_rerror () == 0) np_uerror (EPERM); goto done; } if ((sgcpy = malloc (u->nsg * sizeof (gid_t)))) { for (i = 0; i < u->nsg; i++) sgcpy[i] = u->sg[i]; free (u->sg); u->sg = sgcpy; } ret = 0; done: return ret; }
/* Tstatfs - read file system information. */ Npfcall* diod_statfs (Npfid *fid) { Fid *f = fid->aux; struct statfs sb; Npfcall *ret; u64 fsid; if (statfs (f->path, &sb) < 0) { np_uerror (errno); goto error; } fsid = (u64)sb.f_fsid.__val[0] | ((u64)sb.f_fsid.__val[1] << 32); if (!(ret = np_create_rstatfs(sb.f_type, sb.f_bsize, sb.f_blocks, sb.f_bfree, sb.f_bavail, sb.f_files, sb.f_ffree, fsid, sb.f_namelen))) { np_uerror (ENOMEM); goto error; } return ret; error: errn (np_rerror (), "diod_statfs %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path); return NULL; }
/* Tremove - remove a file or directory. */ Npfcall* diod_remove (Npfid *fid) { Fid *f = fid->aux; Npfcall *ret; if ((f->xflags & XFLAGS_RO)) { np_uerror (EROFS); goto error_quiet; } if (remove (f->path) < 0) { np_uerror (errno); goto error_quiet; } if (!(ret = np_create_rremove ())) { np_uerror (ENOMEM); goto error; } return ret; error: errn (np_rerror (), "diod_remove %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path); error_quiet: return NULL; }
/* Returns error code > 0 on error. * Returns 0 on success: result set to NULL at EOF, o/w set to entry */ int npc_readdir_r (Npcfid *fid, struct dirent *entry, struct dirent **result) { Npqid qid; int dname_size = PATH_MAX + 1; u64 offset; u8 type; int res; if (fid->dbuf_used >= fid->dbuf_len) { fid->dbuf_len = npc_readdir (fid, fid->offset, fid->dbuf, fid->dbuf_size); if (fid->dbuf_len < 0) return np_rerror (); if (fid->dbuf_len == 0) { /* EOF */ *result = NULL; return 0; } fid->dbuf_used = 0; } res = np_deserialize_p9dirent (&qid, &offset, &type, entry->d_name, dname_size, (u8 *)fid->dbuf + fid->dbuf_used, fid->dbuf_len - fid->dbuf_used); if (res == 0) return EIO; entry->d_off = offset; entry->d_type = type; entry->d_ino = qid.path; //entry->d_reclen fid->offset = offset; fid->dbuf_used += res; *result = entry; return 0; }
Npcfid * npc_attach (Npcfsys *fs, Npcfid *afid, char *aname, uid_t uid) { Npfcall *tc = NULL, *rc = NULL; Npcfid *fid = NULL; if (!(fid = npc_fid_alloc (fs))) goto done; if (!(tc = np_create_tattach (fid->fid, afid ? afid->fid : P9_NOFID, NULL, aname, uid))) { np_uerror (ENOMEM); goto done; } if (fs->rpc (fs, tc, &rc) < 0) goto done; done: if (tc) free (tc); if (rc) free (rc); if (np_rerror () && fid) { npc_fid_free (fid); fid = NULL; } return fid; }
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_readlink(Npfid *fid) { Fid *f = fid->aux; Npfcall *ret = NULL; char target[PATH_MAX + 1]; int n; if ((n = readlink (f->path, target, sizeof(target))) < 0) { np_uerror (errno); goto error_quiet; } target[n] = '\0'; if (!(ret = np_create_rreadlink(target))) { np_uerror (ENOMEM); goto error; } return ret; error: errn (np_rerror (), "diod_readlink %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path); error_quiet: if (ret) free (ret); return NULL; }
/* Tclunk - close a file. */ Npfcall* diod_clunk (Npfid *fid) { Fid *f = fid->aux; Npfcall *ret; if (f->dir) { if (closedir(f->dir) < 0) { np_uerror (errno); goto error_quiet; } } else if (f->fd != -1) { if (close (f->fd) < 0) { np_uerror (errno); goto error_quiet; } } if (!(ret = np_create_rclunk ())) { np_uerror (ENOMEM); goto error; } return ret; error: errn (np_rerror (), "diod_clunk %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path); error_quiet: return NULL; }
Npfcall* diod_fsync (Npfid *fid) { Fid *f = fid->aux; Npfcall *ret = NULL; if ((f->xflags & XFLAGS_RO)) { np_uerror (EROFS); goto error_quiet; } if (fsync(f->dir ? dirfd (f->dir) : f->fd) < 0) { np_uerror (errno); goto error_quiet; } if (!((ret = np_create_rfsync ()))) { np_uerror (ENOMEM); goto error; } return ret; error: errn (np_rerror (), "diod_fsync %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path); error_quiet: if (ret) free (ret); return NULL; }
int main (int argc, char *argv[]) { Npcfsys *fs; Npcfid *afid, *root; uid_t uid = geteuid (); char *aname, *path; int fd = 0; /* stdin */ diod_log_init (argv[0]); if (argc != 3) usage (); aname = argv[1]; path = argv[2]; if (!(fs = npc_start (fd, fd, 65536+24, 0))) errn_exit (np_rerror (), "npc_start"); if (!(afid = npc_auth (fs, aname, uid, diod_auth)) && np_rerror () != 0) errn_exit (np_rerror (), "npc_auth"); if (!(root = npc_attach (fs, afid, aname, uid))) errn_exit (np_rerror (), "npc_attach"); if (afid && npc_clunk (afid) < 0) errn (np_rerror (), "npc_clunk afid"); if (_mkdir_p (root, path, 0755) < 0) errn_exit (np_rerror (), "mkdir"); if (npc_clunk (root) < 0) errn_exit (np_rerror (), "npc_clunk root"); npc_finish (fs); exit (0); }
Npfcall* diod_lopen (Npfid *fid, u32 flags) { Fid *f = fid->aux; Npfcall *res; if ((f->flags & DIOD_FID_FLAGS_ROFS) && ((flags & O_WRONLY) || (flags & O_RDWR))) { np_uerror (EROFS); goto error_quiet; } flags = _remap_oflags (flags); if (flags & O_DIRECT) { np_uerror (EINVAL); /* O_DIRECT not allowed - see issue 110 */ goto error_quiet; } if ((flags & O_CREAT)) /* can't happen? */ flags &= ~O_CREAT; /* clear and allow to fail with ENOENT */ if (f->ioctx != NULL) { msg ("diod_lopen: fid is already open"); np_uerror (EINVAL); goto error; } if (ioctx_open (fid, flags, 0) < 0) { if (np_rerror () == ENOMEM) goto error; goto error_quiet; } if (!(res = np_create_rlopen (ioctx_qid (f->ioctx), ioctx_iounit (f->ioctx)))) { (void)ioctx_close (fid, 0); np_uerror (ENOMEM); goto error; } return res; error: errn (np_rerror (), "diod_lopen %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), path_s (f->path)); error_quiet: 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; }
Npfcall* diod_lopen (Npfid *fid, u32 flags) { Fid *f = fid->aux; Npfcall *res = NULL; Npqid qid; u32 iounit = 0; /* client will use msize-P9_IOHDRSZ */ if ((f->xflags & XFLAGS_RO) && ((flags & O_WRONLY) || (flags & O_RDWR))) { np_uerror (EROFS); goto error_quiet; } if ((flags & O_CREAT)) /* can't happen? */ flags &= ~O_CREAT; /* clear and allow to fail with ENOENT */ if (_fidstat (f) < 0) goto error_quiet; if (S_ISDIR (f->stat.st_mode)) { f->dir = opendir (f->path); if (!f->dir) { np_uerror (errno); goto error_quiet; } } else { f->fd = open (f->path, flags); if (f->fd < 0) { np_uerror (errno); goto error_quiet; } } if (_fidstat (f) < 0) goto error; /* can't happen? */ _ustat2qid (&f->stat, &qid); //iounit = f->stat.st_blksize; if (!(res = np_create_rlopen (&qid, iounit))) { np_uerror (ENOMEM); goto error; } return res; error: errn (np_rerror (), "diod_lopen %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path); error_quiet: if (f->dir) { (void)closedir (f->dir); f->dir = NULL; } if (f->fd != -1) { (void)close (f->fd); f->fd = -1; } if (res) free (res); return NULL; }
int main (int argc, char *argv[]) { Npcfsys *fs; Npcfid *afid, *root, *fid; char *aname; const int fd = 0; /* stdin */ uid_t uid; gid_t gid, ngid; diod_log_init (argv[0]); if (argc != 2) usage (); aname = argv[1]; if (geteuid () != 0) /* the server actually must be running as root */ msg_exit ("must run as root"); pick_user (&uid, &gid, &ngid); if (!(fs = npc_start (fd, 8192+24, 0))) errn_exit (np_rerror (), "npc_start"); if (!(afid = npc_auth (fs, aname, uid, diod_auth)) && np_rerror () != 0) errn_exit (np_rerror (), "npc_auth"); if (!(root = npc_attach (fs, afid, aname, uid))) errn_exit (np_rerror (), "npc_attach"); if (afid && npc_clunk (afid) < 0) errn_exit (np_rerror (), "npc_clunk afid"); /* should succeed */ if (!(fid = npc_create_bypath (root, "foo", 0644, O_RDONLY, gid))) errn_exit (np_rerror (), "npc_create_bypath as %d:%d with gid %d", uid, gid, gid); if (npc_clunk (fid) < 0) errn_exit (np_rerror (), "npc_clunk"); msg ("create foo with good gid succeeded"); /* should fail */ if ((fid = npc_create_bypath (root, "foo2", 0644, O_RDONLY, ngid))) msg_exit ("npc_create_bypath as %d:%d with gid %d succeeded: FAIL", uid, gid, ngid); msg ("create foo2 with bad gid failed"); if (npc_clunk (root) < 0) errn_exit (np_rerror (), "npc_clunk root"); npc_finish (fs); diod_log_fini (); exit (0); }
static int lsdir (int i, int count, Npcfid *root, int lopt, char *path) { Npcfid *dir = NULL; struct dirent d, *dp; if (!(dir = npc_opendir (root, path))) { if (np_rerror () == ENOTDIR) { if (lopt) lsfile_l (root, path); else printf ("%s\n", path); return 0; } errn (np_rerror (), "%s", path); goto error; } if (count > 1) printf ("%s:\n", path); do { if ((npc_readdir_r (dir, &d, &dp)) > 0) { errn (np_rerror (), "npc_readdir: %s", path); goto error; } if (dp) { if (lopt) lsfile_l (dir, dp->d_name); else printf ("%s\n", dp->d_name); } } while (dp != NULL); if (npc_clunk (dir) < 0) { errn (np_rerror (), "npc_clunk: %s", path); goto error; } if (count > 1 && i < count - 1) printf ("\n"); return 0; error: if (dir) (void)npc_clunk (dir); return -1; }
/* Locking note: * Implement POSIX locks in terms of BSD flock locks. * This at least gets distributed whole-file locking to work. * Strategies for distributed record locking will deadlock. */ Npfcall* diod_lock (Npfid *fid, u8 type, u32 flags, u64 start, u64 length, u32 proc_id, Npstr *client_id) { Fid *f = fid->aux; Npfcall *ret; u8 status = P9_LOCK_ERROR; if ((f->flags & DIOD_FID_FLAGS_ROFS)) { np_uerror (EROFS); goto error_quiet; } if (flags & ~P9_LOCK_FLAGS_BLOCK) { /* only one valid flag for now */ np_uerror (EINVAL); /* (which we ignore) */ goto error; } if (!f->ioctx) { msg ("diod_lock: fid is not open"); np_uerror (EBADF); goto error; } switch (type) { case P9_LOCK_TYPE_UNLCK: if (ioctx_flock (f->ioctx, LOCK_UN) == 0) status = P9_LOCK_SUCCESS; break; case P9_LOCK_TYPE_RDLCK: if (ioctx_flock (f->ioctx, LOCK_SH | LOCK_NB) == 0) status = P9_LOCK_SUCCESS; else if (errno == EWOULDBLOCK) status = P9_LOCK_BLOCKED; break; case P9_LOCK_TYPE_WRLCK: if (ioctx_flock (f->ioctx, LOCK_EX | LOCK_NB) == 0) status = P9_LOCK_SUCCESS; else if (errno == EWOULDBLOCK) status = P9_LOCK_BLOCKED; break; default: np_uerror (EINVAL); goto error; } if (!((ret = np_create_rlock (status)))) { np_uerror (ENOMEM); goto error; } return ret; error: errn (np_rerror (), "diod_lock %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), path_s (f->path)); error_quiet: return NULL; }
int main (int argc, char *argv[]) { Npcfsys *fs; Npcfid *afid, *root; char *aname; int fd = 0; /* stdin */ uid_t uid = geteuid (); diod_log_init (argv[0]); if (argc != 2) usage (); aname = argv[1]; if (!(fs = npc_start (fd, 8192+24, 0))) errn_exit (np_rerror (), "npc_start"); if (!(afid = npc_auth (fs, aname, uid, diod_auth)) && np_rerror () != 0) errn_exit (np_rerror (), "npc_auth"); if (!(root = npc_attach (fs, afid, aname, uid))) errn_exit (np_rerror (), "npc_attach"); if (afid && npc_clunk (afid) < 0) errn_exit (np_rerror (), "npc_clunk afid"); _flush_series (fs, root); if (npc_clunk (root) < 0) errn_exit (np_rerror (), "npc_clunk root"); npc_finish (fs); diod_log_fini (); exit (0); }
static void lsfile_l (Npcfid *dir, char *name) { Npcfid *fid = NULL; struct stat sb; struct passwd *pw; struct group *gr; char uid[16], gid[16]; char *mtime; if (!(fid = npc_walk (dir, name))) { errn (np_rerror (), "npc_walk %s\n", name); goto error; } if (npc_fstat (fid, &sb) < 0) { errn (np_rerror (), "npc_fstat %s\n", name); goto error; } if (npc_clunk (fid) < 0) { errn (np_rerror (), "npc_clunk %s\n", name); goto error; } if (!(pw = getpwuid (sb.st_uid))) snprintf (uid, sizeof (uid), "%d", sb.st_uid); if (!(gr = getgrgid (sb.st_gid))) snprintf (gid, sizeof (gid), "%d", sb.st_gid); mtime = ctime( &sb.st_mtime); printf ("%10s %4lu %s %s %12lu %.*s %s\n", mode2str (sb.st_mode), sb.st_nlink, pw ? pw->pw_name : uid, gr ? gr->gr_name : gid, sb.st_size, (int)strlen (mtime) - 13, mtime + 4, name); return; error: if (fid) (void)npc_clunk (fid); }
void diod_sock_startfd (Npsrv *srv, int fdin, int fdout, char *client_id) { Npconn *conn; Nptrans *trans; trans = np_fdtrans_create (fdin, fdout); if (!trans) { errn (np_rerror (), "error creating transport for %s", client_id); (void)close (fdin); if (fdin != fdout) (void)close (fdout); return; } conn = np_conn_create (srv, trans, client_id); if (!conn) { errn (np_rerror (), "error creating connection for %s", client_id); /* trans is destroyed in np_conn_create on failure */ return; } }
static void _diod_mount (Opt o, int rfd, int wfd, char *spec, char *dir, int vopt, int fopt, int nopt) { char *options, *options9p, *aname, *uname; uid_t uid; int msize; Npcfsys *fs; Npcfid *afid, *root; unsigned long mountflags = 0; options = opt_csv (o); _getflags (o, &mountflags); options9p = opt_csv (o); /* after mountflags removed from opt list */ if (!(uname = opt_find (o, "uname"))) msg_exit ("uname is not set"); /* can't happen */ uid = _uname2uid (uname); aname = opt_find (o, "aname"); /* can be null */ if (!opt_scanf (o, "msize=%d", &msize) || msize < P9_IOHDRSZ) msg_exit ("msize must be set to integer >= %d", P9_IOHDRSZ); if (vopt) msg ("pre-authenticating connection to server"); if (!(fs = npc_start (rfd, wfd, msize, 0))) errn_exit (np_rerror (), "version"); if (!(afid = npc_auth (fs, aname, uid, diod_auth)) && np_rerror () != 0) errn_exit (np_rerror (), "auth"); if (!(root = npc_attach (fs, afid, aname, uid))) { errn (np_rerror (), "attach"); if (afid) (void)npc_clunk (afid); exit (1); } if (afid && npc_clunk (afid) < 0) errn_exit (np_rerror (), "clunk afid"); if (npc_clunk (root) < 0) errn_exit (np_rerror (), "clunk root"); if (vopt) msg ("mount -t 9p %s %s -o%s", spec, dir, options); if (!fopt) { /* kernel wants non-blocking */ if (fcntl (rfd, F_SETFL, O_NONBLOCK) < 0) err_exit ("setting O_NONBLOCK flag on rfd=%d", rfd); if (fcntl (wfd, F_SETFL, O_NONBLOCK) < 0) err_exit ("setting O_NONBLOCK flag on wfd=%d", wfd); _mount (spec, dir, mountflags, options9p); } npc_finish (fs); /* closes fd */ if (!nopt) { if (!_update_mtab (options, spec, dir)) msg_exit ("failed to update /etc/mtab"); } free (options); free (options9p); }