Npfcall* diod_symlink(Npfid *fid, Npstr *name, Npstr *symtgt, u32 gid) { Npsrv *srv = fid->conn->srv; Fid *f = fid->aux; Npfcall *ret; char *target = NULL; Path npath = NULL; Npqid qid; struct stat sb; if ((f->flags & DIOD_FID_FLAGS_ROFS)) { np_uerror (EROFS); goto error_quiet; } if (!(npath = path_append (srv, f->path, name))) { np_uerror (ENOMEM); goto error; } if (!(target = np_strdup (symtgt))) { np_uerror (ENOMEM); goto error; } if (symlink (target, path_s (npath)) < 0 || lstat (path_s (npath), &sb) < 0) { np_uerror (errno); goto error_quiet; } diod_ustat2qid (&sb, &qid); if (!((ret = np_create_rsymlink (&qid)))) { (void)unlink (path_s (npath)); np_uerror (ENOMEM); goto error; } path_decref (srv, 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), path_s (f->path), name->len, name->str); error_quiet: if (npath) path_decref (srv, npath); if (target) free (target); return NULL; }
/* Tattach - attach a new user (fid->user) to aname. * diod_auth.c::diod_checkauth first authenticates/authorizes user */ Npfcall* diod_attach (Npfid *fid, Npfid *afid, Npstr *aname) { Npfcall* ret = NULL; Fid *f = NULL; Npqid qid; struct stat sb; int xflags; if (aname->len == 0 || *aname->str != '/') { np_uerror (EPERM); goto error; } if (!(f = diod_fidalloc (fid, aname))) { np_uerror (ENOMEM); goto error; } if (diod_conf_opt_runasuid ()) { if (fid->user->uid != diod_conf_get_runasuid ()) { np_uerror (EPERM); goto error; } } if (!diod_match_exports (path_s (f->path), fid->conn, fid->user, &xflags)) goto error; if ((xflags & XFLAGS_RO)) f->flags |= DIOD_FID_FLAGS_ROFS; if ((xflags & XFLAGS_SHAREFD)) f->flags |= DIOD_FID_FLAGS_SHAREFD; if (stat (path_s (f->path), &sb) < 0) { /* OK to follow symbolic links */ np_uerror (errno); goto error; } /* N.B. removed S_ISDIR (sb.st_mode) || return ENOTDIR check. * Allow a regular file or a blcok device to be exported. */ diod_ustat2qid (&sb, &qid); if ((ret = np_create_rattach (&qid)) == NULL) { np_uerror (ENOMEM); goto error; } return ret; error: errn (np_rerror (), "diod_attach %s@%s:%.*s", fid->user->uname, np_conn_get_client_id (fid->conn), aname->len, aname->str); diod_fiddestroy (fid); return NULL; }
Npfcall* diod_getattr(Npfid *fid, u64 request_mask) { Fid *f = fid->aux; Npfcall *ret; Npqid qid; struct stat sb; if ((f->flags & DIOD_FID_FLAGS_MOUNTPT)) { if (_statmnt (path_s (f->path), &sb) < 0) { np_uerror (errno); goto error_quiet; } } else { if (lstat (path_s (f->path), &sb) < 0) { np_uerror (errno); goto error_quiet; } } diod_ustat2qid (&sb, &qid); if (!(ret = np_create_rgetattr(request_mask, &qid, sb.st_mode, sb.st_uid, sb.st_gid, sb.st_nlink, sb.st_rdev, sb.st_size, sb.st_blksize, sb.st_blocks, sb.st_atim.tv_sec, sb.st_atim.tv_nsec, sb.st_mtim.tv_sec, sb.st_mtim.tv_nsec, sb.st_ctim.tv_sec, sb.st_ctim.tv_nsec, 0, 0, 0, 0))) { np_uerror (ENOMEM); goto error; } return ret; error: errn (np_rerror (), "diod_getattr %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), path_s (f->path)); error_quiet: return NULL; }
static IOCtx _ioctx_create_open (Npuser *user, Path path, int flags, u32 mode) { IOCtx ioctx; struct stat sb; ioctx = malloc (sizeof (*ioctx)); if (!ioctx) { np_uerror (ENOMEM); goto error; } pthread_mutex_init (&ioctx->lock, NULL); ioctx->refcount = 1; ioctx->lock_type = LOCK_UN; ioctx->dir = NULL; ioctx->open_flags = flags; ioctx->user = user; np_user_incref (user); ioctx->prev = ioctx->next = NULL; ioctx->fd = open (path->s, flags, mode); if (ioctx->fd < 0) { np_uerror (errno); goto error; } if (fstat (ioctx->fd, &sb) < 0) { np_uerror (errno); goto error; } ioctx->iounit = 0; /* if iounit=0, v9fs will use msize-P9_IOHDRSZ */ #ifndef __MACH__ if (S_ISDIR(sb.st_mode) && !(ioctx->dir = fdopendir (ioctx->fd))) { np_uerror (errno); goto error; } #endif if (S_ISDIR(sb.st_mode) && !(ioctx->dir = opendir (path->s))) { np_uerror (errno); goto error; } diod_ustat2qid (&sb, &ioctx->qid); return ioctx; error: if (ioctx) _ioctx_close_destroy (ioctx, 0); 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) { Npsrv *srv = fid->conn->srv; Fid *f = fid->aux; struct stat sb, sb2; Path npath = NULL; if ((f->flags & DIOD_FID_FLAGS_MOUNTPT)) { np_uerror (ENOENT); goto error_quiet; } if (!(npath = path_append (srv, f->path, wname))) { np_uerror (ENOMEM); goto error; } if (lstat (path_s (npath), &sb) < 0) { np_uerror (errno); goto error_quiet; } if (lstat (path_s (f->path), &sb2) < 0) { np_uerror (errno); goto error; } if (sb.st_dev != sb2.st_dev) { if (_statmnt (path_s (npath), &sb) < 0) goto error; f->flags |= DIOD_FID_FLAGS_MOUNTPT; } path_decref (srv, f->path); f->path = npath; diod_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), path_s (f->path), wname->len, wname->str); error_quiet: if (npath) path_decref (srv, npath); return 0; }
Npfcall* diod_mknod(Npfid *fid, Npstr *name, u32 mode, u32 major, u32 minor, u32 gid) { Npsrv *srv = fid->conn->srv; Npfcall *ret; Fid *f = fid->aux; Path npath = NULL; Npqid qid; struct stat sb; if ((f->flags & DIOD_FID_FLAGS_ROFS)) { np_uerror (EROFS); goto error_quiet; } if (!(npath = path_append (srv, f->path, name))) { np_uerror (ENOMEM); goto error; } if (mknod (path_s (npath), mode, makedev (major, minor)) < 0 || lstat (path_s (npath), &sb) < 0) { np_uerror (errno); goto error_quiet; } diod_ustat2qid (&sb, &qid); if (!((ret = np_create_rmknod (&qid)))) { (void)unlink (path_s (npath)); np_uerror (ENOMEM); goto error; } path_decref (srv, npath); return ret; error: errn (np_rerror (), "diod_mknod %s@%s:%s/%.*s", fid->user->uname, np_conn_get_client_id (fid->conn), path_s (f->path), name->len, name->str); error_quiet: if (npath) path_decref (srv, npath); return NULL; }
static u32 _copy_dirent_linux (Fid *f, struct dirent *dp, u8 *buf, u32 buflen) { Npqid qid; u32 ret = 0; if (dp->d_type == DT_UNKNOWN) { char path[PATH_MAX + 1]; struct stat sb; snprintf (path, sizeof(path), "%s/%s", path_s (f->path), dp->d_name); if (lstat (path, &sb) < 0) { np_uerror (errno); goto done; } diod_ustat2qid (&sb, &qid); } else { _dirent2qid (dp, &qid); } ret = np_serialize_p9dirent(&qid, dp->d_off, dp->d_type, dp->d_name, buf, buflen); done: return ret; }