static void setpnva(struct puffs_usermount *pu, struct puffs_node *pn, const struct vattr *vap) { struct psshfs_ctx *pctx = puffs_getspecific(pu); struct psshfs_node *psn = pn->pn_data; struct vattr modva; /* * Check if the file was modified from below us. * If so, invalidate page cache. This is the only * sensible place we can do this in. */ if (pn->pn_va.va_mtime.tv_sec != PUFFS_VNOVAL) if (pn->pn_va.va_mtime.tv_sec != vap->va_mtime.tv_sec && pn->pn_va.va_type == VREG) puffs_inval_pagecache_node(pu, pn); modva = *vap; if (pctx->domangleuid && modva.va_uid == pctx->mangleuid) modva.va_uid = pctx->myuid; if (pctx->domanglegid && modva.va_gid == pctx->manglegid) modva.va_gid = pctx->mygid; puffs_setvattr(&pn->pn_va, &modva); psn->attrread = time(NULL); }
int dtfs_node_setattr(struct puffs_usermount *pu, void *opc, const struct vattr *va, const struct puffs_cred *pcr) { struct puffs_node *pn = opc; int rv; /* check permissions */ if (va->va_flags != PUFFS_VNOVAL) return EOPNOTSUPP; if (va->va_uid != PUFFS_VNOVAL || va->va_gid != PUFFS_VNOVAL) { rv = puffs_access_chown(pn->pn_va.va_uid, pn->pn_va.va_gid, va->va_uid, va->va_gid, pcr); if (rv) return rv; } if (va->va_mode != PUFFS_VNOVAL) { rv = puffs_access_chmod(pn->pn_va.va_uid, pn->pn_va.va_gid, pn->pn_va.va_type, va->va_mode, pcr); if (rv) return rv; } if ((va->va_atime.tv_sec != PUFFS_VNOVAL && va->va_atime.tv_nsec != PUFFS_VNOVAL) || (va->va_mtime.tv_sec != PUFFS_VNOVAL && va->va_mtime.tv_nsec != PUFFS_VNOVAL)) { rv = puffs_access_times(pn->pn_va.va_uid, pn->pn_va.va_gid, pn->pn_va.va_mode, va->va_vaflags & VA_UTIMES_NULL, pcr); if (rv) return rv; } if (va->va_size != PUFFS_VNOVAL) { switch (pn->pn_va.va_type) { case VREG: dtfs_setsize(pn, va->va_size); pn->pn_va.va_bytes = va->va_size; break; case VBLK: case VCHR: case VFIFO: break; case VDIR: return EISDIR; default: return EOPNOTSUPP; } } puffs_setvattr(&pn->pn_va, va); return 0; }
/*ARGSUSED*/ int puffs_null_node_setattr(struct puffs_usermount *pu, puffs_cookie_t opc, const struct vattr *va, const struct puffs_cred *pcred) { struct puffs_node *pn = opc; int rv; rv = processvattr(PNPATH(pn), va, pn->pn_va.va_type == VREG); if (rv) return rv; puffs_setvattr(&pn->pn_va, va); 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; }
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 psshfs_handshake(struct puffs_usermount *pu, int fd) { struct psshfs_ctx *pctx = puffs_getspecific(pu); struct puffs_framebuf *pb; struct puffs_pathobj *po_root; struct puffs_node *pn_root; struct vattr va, *rva; const struct extunit *extu; char *rootpath; char *ext, *val; uint32_t count; int rv, done; pb = psbuf_makeout(); psbuf_put_1(pb, SSH_FXP_INIT); psbuf_put_4(pb, SFTP_PROTOVERSION); DO_IO(psbuf_write, pu, pb, fd, &done, rv); puffs_framebuf_recycle(pb); DO_IO(psbuf_read, pu, pb, fd, &done, rv); if (psbuf_get_type(pb) != SSH_FXP_VERSION) reterr((stderr, "invalid server response: %d", psbuf_get_type(pb)), EPROTO); pctx->protover = psbuf_get_reqid(pb); /* * Check out which extensions are available. Currently * we are only interested in the openssh statvfs extension. */ for (;;) { if (psbuf_get_str(pb, &ext, NULL) != 0) break; if (psbuf_get_str(pb, &val, NULL) != 0) break; for (extu = exttable; extu->ext; extu++) if (strcmp(ext, extu->ext) == 0 && strcmp(val, extu->val) == 0) pctx->extensions |= extu->extflag; } /* scope out our rootpath */ psbuf_recycleout(pb); psbuf_put_1(pb, SSH_FXP_REALPATH); psbuf_put_4(pb, NEXTREQ(pctx)); psbuf_put_str(pb, pctx->mountpath); DO_IO(psbuf_write, pu, pb, fd, &done, rv); puffs_framebuf_recycle(pb); DO_IO(psbuf_read, pu, pb, fd, &done, rv); if (psbuf_get_type(pb) != SSH_FXP_NAME) reterr((stderr, "invalid server realpath response for \"%s\"", pctx->mountpath), EPROTO); if (psbuf_get_4(pb, &count) == -1) reterr((stderr, "invalid realpath response: count"), EPROTO); if (psbuf_get_str(pb, &rootpath, NULL) == -1) reterr((stderr, "invalid realpath response: rootpath"), EPROTO); /* stat the rootdir so that we know it's a dir */ psbuf_recycleout(pb); psbuf_req_str(pb, SSH_FXP_LSTAT, NEXTREQ(pctx), rootpath); DO_IO(psbuf_write, pu, pb, fd, &done, rv); puffs_framebuf_recycle(pb); DO_IO(psbuf_read, pu, pb, fd, &done, rv); rv = psbuf_expect_attrs(pb, &va); if (rv) reterr((stderr, "couldn't stat rootpath"), rv); puffs_framebuf_destroy(pb); if (puffs_mode2vt(va.va_mode) != VDIR) reterr((stderr, "remote path (%s) not a directory", rootpath), ENOTDIR); pn_root = puffs_getroot(pu); rva = &pn_root->pn_va; puffs_setvattr(rva, &va); po_root = puffs_getrootpathobj(pu); if (po_root == NULL) err(1, "getrootpathobj"); po_root->po_path = rootpath; po_root->po_len = strlen(rootpath); return 0; }