int sysctlfs_fs_nodetofh(struct puffs_usermount *pu, void *cookie, void *fid, size_t *fidsize) { struct puffs_node *pn = cookie; struct sfsfid *sfid; sfid = fid; sfid->len = PNPLEN(pn); memcpy(&sfid->path, PNPATH(pn), sfid->len * sizeof(int)); return 0; }
/* * called from nodewalk, checks for exact match */ void * puffs_path_walkcmp(struct puffs_usermount *pu, struct puffs_node *pn, void *arg) { struct puffs_pathobj *po = arg; struct puffs_pathobj po2; if (po->po_len != PNPLEN(pn)) return NULL; /* * If hashing and the hash doesn't match, we know this is * definitely not a match. Otherwise check for collisions. */ if (pu->pu_flags & PUFFS_FLAG_HASHPATH) if (pn->pn_po.po_hash != po->po_hash) return NULL; po2.po_path = PNPATH(pn); po2.po_len = PNPLEN(pn); if (pu->pu_pathcmp(pu, po, &po2, PNPLEN(pn), 0) == 0) return pn; return NULL; }
int sysctlfs_node_write(struct puffs_usermount *pu, void *opc, uint8_t *buf, off_t offset, size_t *resid, const struct puffs_cred *cred, int ioflag) { struct puffs_node *pn = opc; struct sfsnode *sfs = pn->pn_data; long long ll; int i, rv; bool b; /* * I picked the wrong day to ... um, the wrong place to return errors */ /* easy to support, but just unavailable now */ if (rflag) return EOPNOTSUPP; if (puffs_cred_isjuggernaut(cred) == 0) return EACCES; if (ISADIR(sfs)) return EISDIR; if (offset != 0) return EINVAL; if (ioflag & PUFFS_IO_APPEND) return EINVAL; switch (SYSCTL_TYPE(sfs->sysctl_flags)) { case CTLTYPE_BOOL: if (strcasestr((const char *)buf, "true")) b = true; else if (strcasestr((const char *)buf, "false")) b = false; else return EINVAL; rv = sysctl(PNPATH(pn), PNPLEN(pn), NULL, NULL, &b, sizeof(b)); break; case CTLTYPE_INT: if (sscanf((const char *)buf, "%d", &i) != 1) return EINVAL; rv = sysctl(PNPATH(pn), PNPLEN(pn), NULL, NULL, &i, sizeof(int)); break; case CTLTYPE_QUAD: if (sscanf((const char *)buf, "%lld", &ll) != 1) return EINVAL; rv = sysctl(PNPATH(pn), PNPLEN(pn), NULL, NULL, &ll, sizeof(long long)); break; case CTLTYPE_STRING: rv = sysctl(PNPATH(pn), PNPLEN(pn), NULL, NULL, buf, *resid); break; default: rv = EINVAL; break; } if (rv) return rv; *resid = 0; return 0; }
int sysctlfs_node_readdir(struct puffs_usermount *pu, void *opc, struct dirent *dent, off_t *readoff, size_t *reslen, const struct puffs_cred *pcr, int *eofflag, off_t *cookies, size_t *ncookies) { struct sysctlnode sn[SFS_NODEPERDIR]; struct sysctlnode qnode; struct puffs_node *pn_dir = opc; struct puffs_node *pn_res; struct puffs_pathobj po; struct sfsnode *sfs_dir = pn_dir->pn_data, *sfs_ent; SfsName *sname; size_t sl, i; enum vtype vt; ino_t id; *ncookies = 0; again: if (*readoff == DENT_DOT || *readoff == DENT_DOTDOT) { puffs_gendotdent(&dent, sfs_dir->myid, *readoff, reslen); (*readoff)++; PUFFS_STORE_DCOOKIE(cookies, ncookies, *readoff); goto again; } memset(&qnode, 0, sizeof(qnode)); sl = SFS_NODEPERDIR * sizeof(struct sysctlnode); qnode.sysctl_flags = SYSCTL_VERSION; sname = PNPATH(pn_dir); (*sname)[PNPLEN(pn_dir)] = CTL_QUERY; if (sysctl(*sname, PNPLEN(pn_dir) + 1, sn, &sl, &qnode, sizeof(qnode)) == -1) return ENOENT; po.po_path = sname; po.po_len = PNPLEN(pn_dir)+1; for (i = DENT_ADJ(*readoff); i < sl / sizeof(struct sysctlnode); i++) { if (SYSCTL_TYPE(sn[i].sysctl_flags) == CTLTYPE_NODE) vt = VDIR; else vt = VREG; /* * check if the node exists. if so, give it the real * inode number. otherwise just fake it. */ (*sname)[PNPLEN(pn_dir)] = sn[i].sysctl_num; pn_res = puffs_pn_nodewalk(pu, puffs_path_walkcmp, &po); if (pn_res) { sfs_ent = pn_res->pn_data; id = sfs_ent->myid; } else { id = nextid++; } if (!puffs_nextdent(&dent, sn[i].sysctl_name, id, puffs_vtype2dt(vt), reslen)) return 0; (*readoff)++; PUFFS_STORE_DCOOKIE(cookies, ncookies, *readoff); } *eofflag = 1; return 0; }