int dtfs_node_lookup(struct puffs_usermount *pu, void *opc, struct puffs_newinfo *pni, const struct puffs_cn *pcn) { struct puffs_node *pn_dir = opc; struct dtfs_file *df = DTFS_CTOF(opc); struct dtfs_dirent *dfd; extern int straightflush; int rv; /* parent dir? */ if (PCNISDOTDOT(pcn)) { if (df->df_dotdot == NULL) return ENOENT; assert(df->df_dotdot->pn_va.va_type == VDIR); puffs_newinfo_setcookie(pni, df->df_dotdot); puffs_newinfo_setvtype(pni, df->df_dotdot->pn_va.va_type); return 0; } dfd = dtfs_dirgetbyname(df, pcn->pcn_name, pcn->pcn_namelen); if (dfd) { if ((pcn->pcn_flags & NAMEI_ISLASTCN) && (pcn->pcn_nameiop == NAMEI_DELETE)) { rv = puffs_access(VDIR, pn_dir->pn_va.va_mode, pn_dir->pn_va.va_uid, pn_dir->pn_va.va_gid, PUFFS_VWRITE, pcn->pcn_cred); if (rv) return rv; } puffs_newinfo_setcookie(pni, dfd->dfd_node); puffs_newinfo_setvtype(pni, dfd->dfd_node->pn_va.va_type); puffs_newinfo_setsize(pni, dfd->dfd_node->pn_va.va_size); puffs_newinfo_setrdev(pni, dfd->dfd_node->pn_va.va_rdev); if (straightflush) puffs_flush_pagecache_node(pu, dfd->dfd_node); return 0; } if ((pcn->pcn_flags & NAMEI_ISLASTCN) && (pcn->pcn_nameiop == NAMEI_CREATE || pcn->pcn_nameiop == NAMEI_RENAME)) { rv = puffs_access(VDIR, pn_dir->pn_va.va_mode, pn_dir->pn_va.va_uid, pn_dir->pn_va.va_gid, PUFFS_VWRITE, pcn->pcn_cred); if (rv) return rv; } return ENOENT; }
int sysctlfs_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize, struct puffs_newinfo *pni) { struct puffs_pathobj po; struct puffs_node *pn; struct sfsnode *sfs; struct sfsfid *sfid; sfid = fid; po.po_len = sfid->len; po.po_path = &sfid->path; pn = getnode(pu, &po, 0); if (pn == NULL) return EINVAL; sfs = pn->pn_data; puffs_newinfo_setcookie(pni, pn); if (ISADIR(sfs)) puffs_newinfo_setvtype(pni, VDIR); else puffs_newinfo_setvtype(pni, VREG); return 0; }
int psshfs_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize, struct puffs_newinfo *pni) { struct psshfs_ctx *pctx = puffs_getspecific(pu); struct psshfs_fid *pf = fid; struct puffs_node *pn = pf->node; struct psshfs_node *psn; int rv; if (pf->mounttime != pctx->mounttime) return EINVAL; if (pn == 0) return EINVAL; psn = pn->pn_data; if ((psn->stat & PSN_HASFH) == 0) return EINVAL; /* update node attributes */ rv = getnodeattr(pu, pn); if (rv) return EINVAL; puffs_newinfo_setcookie(pni, pn); puffs_newinfo_setvtype(pni, pn->pn_va.va_type); puffs_newinfo_setsize(pni, pn->pn_va.va_size); return 0; }
int sysctlfs_node_lookup(struct puffs_usermount *pu, void *opc, struct puffs_newinfo *pni, const struct puffs_cn *pcn) { struct puffs_cn *p2cn = __UNCONST(pcn); /* XXX: fix the interface */ struct sysctlnode sn[SFS_NODEPERDIR]; struct sysctlnode qnode; struct puffs_node *pn_dir = opc; struct puffs_node *pn_new; struct sfsnode *sfs_dir = pn_dir->pn_data, *sfs_new; SfsName *sname = PCNPATH(pcn); size_t sl, i; int nodetype; assert(ISADIR(sfs_dir)); /* * If we're looking for dotdot, we already have the entire pathname * in sname, courtesy of pathbuild, so we can skip this step. */ if (!PCNISDOTDOT(pcn)) { memset(&qnode, 0, sizeof(qnode)); sl = SFS_NODEPERDIR * sizeof(struct sysctlnode); qnode.sysctl_flags = SYSCTL_VERSION; (*sname)[PCNPLEN(pcn)] = CTL_QUERY; if (sysctl(*sname, PCNPLEN(pcn) + 1, sn, &sl, &qnode, sizeof(qnode)) == -1) return ENOENT; for (i = 0; i < sl / sizeof(struct sysctlnode); i++) if (strcmp(sn[i].sysctl_name, pcn->pcn_name) == 0) break; if (i == sl / sizeof(struct sysctlnode)) return ENOENT; (*sname)[PCNPLEN(pcn)] = sn[i].sysctl_num; p2cn->pcn_po_full.po_len++; nodetype = sn[i].sysctl_flags; } else nodetype = CTLTYPE_NODE; pn_new = getnode(pu, &p2cn->pcn_po_full, nodetype); sfs_new = pn_new->pn_data; puffs_newinfo_setcookie(pni, pn_new); if (ISADIR(sfs_new)) puffs_newinfo_setvtype(pni, VDIR); else puffs_newinfo_setvtype(pni, VREG); return 0; }
int dtfs_node_mkdir(struct puffs_usermount *pu, void *opc, struct puffs_newinfo *pni, const struct puffs_cn *pcn, const struct vattr *va) { struct puffs_node *pn_parent = opc; struct puffs_node *pn_new; pn_new = dtfs_genfile(pn_parent, pcn, VDIR); puffs_setvattr(&pn_new->pn_va, va); puffs_newinfo_setcookie(pni, pn_new); return 0; }
/* create a new node in the parent directory specified by opc */ int dtfs_node_create(struct puffs_usermount *pu, void *opc, struct puffs_newinfo *pni, const struct puffs_cn *pcn, const struct vattr *va) { struct puffs_node *pn_parent = opc; struct puffs_node *pn_new; if (!(va->va_type == VREG || va->va_type == VSOCK)) return ENODEV; pn_new = dtfs_genfile(pn_parent, pcn, va->va_type); puffs_setvattr(&pn_new->pn_va, va); puffs_newinfo_setcookie(pni, pn_new); return 0; }
/*ARGSUSED*/ int puffs_null_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize, struct puffs_newinfo *pni) { struct puffs_node *pn_res; if (fidsize != sizeof(struct fid)) return EINVAL; pn_res = puffs_pn_nodewalk(pu, fhcmp, fid); if (pn_res == NULL) return ENOENT; puffs_newinfo_setcookie(pni, pn_res); puffs_newinfo_setvtype(pni, pn_res->pn_va.va_type); puffs_newinfo_setsize(pni, (off_t)pn_res->pn_va.va_size); puffs_newinfo_setrdev(pni, pn_res->pn_va.va_rdev); return 0; }
int dtfs_node_mknod(struct puffs_usermount *pu, void *opc, struct puffs_newinfo *pni, const struct puffs_cn *pcn, const struct vattr *va) { struct puffs_node *pn_parent = opc; struct puffs_node *pn_new; if (!(va->va_type == VBLK || va->va_type == VCHR || va->va_type == VFIFO)) return EINVAL; pn_new = dtfs_genfile(pn_parent, pcn, va->va_type); puffs_setvattr(&pn_new->pn_va, va); puffs_newinfo_setcookie(pni, pn_new); return 0; }
int dtfs_node_symlink(struct puffs_usermount *pu, void *opc, struct puffs_newinfo *pni, const struct puffs_cn *pcn_src, const struct vattr *va, const char *link_target) { struct puffs_node *pn_parent = opc; struct puffs_node *pn_new; struct dtfs_file *df_new; if (va->va_type != VLNK) return ENODEV; pn_new = dtfs_genfile(pn_parent, pcn_src, VLNK); puffs_setvattr(&pn_new->pn_va, va); df_new = DTFS_PTOF(pn_new); df_new->df_linktarget = estrdup(link_target); pn_new->pn_va.va_size = strlen(df_new->df_linktarget); puffs_newinfo_setcookie(pni, pn_new); return 0; }
static int makenode(struct puffs_usermount *pu, struct puffs_newinfo *pni, const struct puffs_cn *pcn, const struct vattr *va, int regular) { struct puffs_node *pn; struct stat sb; int rv; if ((rv = processvattr(PCNPATH(pcn), va, regular)) != 0) return rv; pn = puffs_pn_new(pu, NULL); if (!pn) return ENOMEM; puffs_setvattr(&pn->pn_va, va); if (lstat(PCNPATH(pcn), &sb) == -1) return errno; puffs_stat2vattr(&pn->pn_va, &sb); puffs_newinfo_setcookie(pni, pn); return 0; }
int puffs_null_node_lookup(struct puffs_usermount *pu, puffs_cookie_t opc, struct puffs_newinfo *pni, const struct puffs_cn *pcn) { struct puffs_node *pn = opc, *pn_res; struct stat sb; int rv; assert(pn->pn_va.va_type == VDIR); /* * Note to whoever is copypasting this: you must first check * if the node is there and only then do nodewalk. Alternatively * you could make sure that you don't return unlinked/rmdir'd * nodes in some other fashion */ rv = lstat(PCNPATH(pcn), &sb); if (rv) return errno; /* XXX2: nodewalk is a bit too slow here */ pn_res = puffs_pn_nodewalk(pu, inodecmp, &sb.st_ino); if (pn_res == NULL) { pn_res = puffs_pn_new(pu, NULL); if (pn_res == NULL) return ENOMEM; puffs_stat2vattr(&pn_res->pn_va, &sb); } puffs_newinfo_setcookie(pni, pn_res); puffs_newinfo_setvtype(pni, pn_res->pn_va.va_type); puffs_newinfo_setsize(pni, (off_t)pn_res->pn_va.va_size); puffs_newinfo_setrdev(pni, pn_res->pn_va.va_rdev); return 0; }
int puffs9p_node_lookup(struct puffs_usermount *pu, void *opc, struct puffs_newinfo *pni, const struct puffs_cn *pcn) { AUTOVAR(pu); struct vattr va; struct puffs_node *pn, *pn_dir = opc; struct p9pnode *p9n_dir = pn_dir->pn_data; p9ptag_t tfid = NEXTFID(p9p); struct qid9p newqid; uint16_t nqid; p9pbuf_put_1(pb, P9PROTO_T_WALK); p9pbuf_put_2(pb, tag); p9pbuf_put_4(pb, p9n_dir->fid_base); p9pbuf_put_4(pb, tfid); p9pbuf_put_2(pb, 1); p9pbuf_put_str(pb, pcn->pcn_name); GETRESPONSE(pb); rv = proto_expect_walk_nqids(pb, &nqid); if (rv) { rv = ENOENT; goto out; } if (nqid != 1) { rv = EPROTO; goto out; } if ((rv = proto_getqid(pb, &newqid))) goto out; /* we get the parent vers in walk(?) compensate */ p9pbuf_recycleout(pb); tag = NEXTTAG(p9p); p9pbuf_put_1(pb, P9PROTO_T_STAT); p9pbuf_put_2(pb, tag); p9pbuf_put_4(pb, tfid); GETRESPONSE(pb); if ((rv = proto_expect_stat(pb, &va)) != 0) { proto_cc_clunkfid(pu, tfid, 0); rv = ENOENT; goto out; } if (newqid.qidpath != va.va_fileid) { proto_cc_clunkfid(pu, tfid, 0); rv = EPROTO; goto out; } newqid.qidvers = va.va_gen; pn = puffs_pn_nodewalk(pu, nodecmp, &newqid); if (pn == NULL) pn = newp9pnode_qid(pu, &newqid, tfid); else proto_cc_clunkfid(pu, tfid, 0); /* assert pn */ memcpy(&pn->pn_va, &va, sizeof(va)); puffs_newinfo_setcookie(pni, pn); puffs_newinfo_setvtype(pni, pn->pn_va.va_type); puffs_newinfo_setsize(pni, pn->pn_va.va_size); puffs_newinfo_setrdev(pni, pn->pn_va.va_rdev); out: RETURN(rv); }
static int nodecreate(struct puffs_usermount *pu, struct puffs_node *pn, struct puffs_newinfo *pni, const char *name, const struct vattr *vap, uint32_t dirbit) { AUTOVAR(pu); struct puffs_node *pn_new; struct p9pnode *p9n = pn->pn_data; p9pfid_t nfid = NEXTFID(p9p); struct qid9p nqid; int tries = 0; again: if (++tries > 5) { rv = EPROTO; goto out; } rv = proto_cc_dupfid(pu, p9n->fid_base, nfid); if (rv) goto out; p9pbuf_put_1(pb, P9PROTO_T_CREATE); p9pbuf_put_2(pb, tag); p9pbuf_put_4(pb, nfid); p9pbuf_put_str(pb, name); p9pbuf_put_4(pb, dirbit | (vap->va_mode & 0777)); p9pbuf_put_1(pb, 0); GETRESPONSE(pb); rv = proto_expect_qid(pb, P9PROTO_R_CREATE, &nqid); if (rv) goto out; /* * Now, little problem here: create returns an *open* fid. * So, clunk it and walk the parent directory to get a fid * which is not open for I/O yet. */ proto_cc_clunkfid(pu, nfid, 0); nfid = NEXTFID(p9p); p9pbuf_recycleout(pb); p9pbuf_put_1(pb, P9PROTO_T_WALK); p9pbuf_put_2(pb, tag); p9pbuf_put_4(pb, p9n->fid_base); p9pbuf_put_4(pb, nfid); p9pbuf_put_2(pb, 1); p9pbuf_put_str(pb, name); GETRESPONSE(pb); /* * someone removed it already? try again * note: this is kind of lose/lose */ if (p9pbuf_get_type(pb) != P9PROTO_R_WALK) goto again; pn_new = newp9pnode_va(pu, vap, nfid); qid2vattr(&pn_new->pn_va, &nqid); puffs_newinfo_setcookie(pni, pn_new); out: RETURN(rv); }