static int sysctlfs_domount(struct puffs_usermount *pu) { struct puffs_pathobj *po_root; struct puffs_node *pn_root; struct timeval tv_now; rn.myid = 2; rn.sysctl_flags = CTLTYPE_NODE; gettimeofday(&tv_now, NULL); TIMEVAL_TO_TIMESPEC(&tv_now, &fstime); pn_root = puffs_pn_new(pu, &rn); assert(pn_root != NULL); puffs_setroot(pu, pn_root); po_root = puffs_getrootpathobj(pu); po_root->po_path = &sname_root; po_root->po_len = 0; fileuid = geteuid(); filegid = getegid(); if (fileuid == 0) fileperms = 0755; else fileperms = 0555; return 0; }
int main(int argc, char *argv[]) { extern char *optarg; extern int optind; struct puffs_usermount *pu; struct puffs_pathobj *po_root; struct puffs_ops *pops; struct timespec ts; const char *typename; char *rtstr; mntoptparse_t mp; int pflags, detach, mntflags; int ch; int khashbuckets; int maxreqsize; setprogname(argv[0]); rtstr = NULL; detach = 1; mntflags = 0; khashbuckets = 256; pflags = PUFFS_KFLAG_IAONDEMAND; typename = FSNAME; maxreqsize = MAXREQMAGIC; gdtm.dtm_allowprot = VM_PROT_ALL; while ((ch = getopt(argc, argv, "bc:dfilm:n:o:p:r:st")) != -1) { switch (ch) { case 'b': /* build paths, for debugging the feature */ pflags |= PUFFS_FLAG_BUILDPATH; break; case 'c': khashbuckets = atoi(optarg); break; case 'd': dynamicfh = 1; break; case 'f': pflags |= PUFFS_KFLAG_LOOKUP_FULLPNBUF; break; case 'i': pflags &= ~PUFFS_KFLAG_IAONDEMAND; break; case 'l': straightflush = 1; break; case 'm': maxreqsize = atoi(optarg); break; case 'n': typename = optarg; break; case 'o': mp = getmntopts(optarg, puffsmopts, &mntflags, &pflags); if (mp == NULL) err(1, "getmntopts"); freemntopts(mp); break; case 'p': gdtm.dtm_allowprot = atoi(optarg); if ((gdtm.dtm_allowprot | VM_PROT_ALL) != VM_PROT_ALL) usage(); break; case 'r': rtstr = optarg; break; case 's': /* stay on top */ detach = 0; break; case 't': pflags |= PUFFS_KFLAG_WTCACHE; break; default: usage(); /*NOTREACHED*/ } } if (pflags & PUFFS_FLAG_OPDUMP) detach = 0; argc -= optind; argv += optind; if (argc != 2) usage(); PUFFSOP_INIT(pops); PUFFSOP_SET(pops, dtfs, fs, statvfs); PUFFSOP_SET(pops, dtfs, fs, unmount); PUFFSOP_SETFSNOP(pops, sync); PUFFSOP_SET(pops, dtfs, fs, fhtonode); PUFFSOP_SET(pops, dtfs, fs, nodetofh); PUFFSOP_SET(pops, dtfs, node, lookup); PUFFSOP_SET(pops, dtfs, node, access); PUFFSOP_SET(pops, puffs_genfs, node, getattr); PUFFSOP_SET(pops, dtfs, node, setattr); PUFFSOP_SET(pops, dtfs, node, create); PUFFSOP_SET(pops, dtfs, node, remove); PUFFSOP_SET(pops, dtfs, node, readdir); PUFFSOP_SET(pops, dtfs, node, poll); PUFFSOP_SET(pops, dtfs, node, mmap); PUFFSOP_SET(pops, dtfs, node, mkdir); PUFFSOP_SET(pops, dtfs, node, rmdir); PUFFSOP_SET(pops, dtfs, node, rename); PUFFSOP_SET(pops, dtfs, node, read); PUFFSOP_SET(pops, dtfs, node, write); PUFFSOP_SET(pops, dtfs, node, link); PUFFSOP_SET(pops, dtfs, node, symlink); PUFFSOP_SET(pops, dtfs, node, readlink); PUFFSOP_SET(pops, dtfs, node, mknod); PUFFSOP_SET(pops, dtfs, node, inactive); PUFFSOP_SET(pops, dtfs, node, pathconf); PUFFSOP_SET(pops, dtfs, node, reclaim); srandom(time(NULL)); /* for random generation numbers */ pu = puffs_init(pops, _PATH_PUFFS, typename, &gdtm, pflags); if (pu == NULL) err(1, "init"); gpu = pu; puffs_setfhsize(pu, sizeof(struct dtfs_fid), PUFFS_FHFLAG_NFSV2 | PUFFS_FHFLAG_NFSV3 | (dynamicfh ? PUFFS_FHFLAG_DYNAMIC : 0)); puffs_setncookiehash(pu, khashbuckets); if (signal(SIGALRM, wipe_the_sleep_out_of_my_eyes) == SIG_ERR) warn("cannot set alarm sighandler"); /* init */ if (dtfs_domount(pu, rtstr) != 0) errx(1, "dtfs_domount failed"); po_root = puffs_getrootpathobj(pu); po_root->po_path = argv[0]; po_root->po_len = strlen(argv[0]); /* often enough for testing poll */ ts.tv_sec = 1; ts.tv_nsec = 0; puffs_ml_setloopfn(pu, loopfun); puffs_ml_settimeout(pu, &ts); if (maxreqsize != MAXREQMAGIC) puffs_setmaxreqlen(pu, maxreqsize); puffs_set_errnotify(pu, puffs_kernerr_abort); if (detach) if (puffs_daemon(pu, 1, 1) == -1) err(1, "puffs_daemon"); if (puffs_mount(pu, argv[1], mntflags, puffs_getroot(pu)) == -1) err(1, "mount"); if (puffs_mainloop(pu) == -1) err(1, "mainloop"); 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; }
int main(int argc, char *argv[]) { struct puffs_usermount *pu; struct puffs_ops *pops; struct puffs_pathobj *po_root; struct puffs_node *pn_root; struct stat sb; int mntflags, pflags; int ch; int detach; setprogname(argv[0]); if (argc < 3) usage(); pflags = mntflags = 0; detach = 1; while ((ch = getopt(argc, argv, "o:s")) != -1) { switch (ch) { case 'o': getmntopts(optarg, puffsmopts, &mntflags, &pflags); break; case 's': detach = 0; break; } } pflags |= PUFFS_FLAG_BUILDPATH; argv += optind; argc -= optind; if (pflags & PUFFS_FLAG_OPDUMP) detach = 0; if (argc != 2) usage(); if (lstat(argv[0], &sb) == -1) err(1, "stat %s", argv[0]); if ((sb.st_mode & S_IFDIR) == 0) errx(1, "%s is not a directory", argv[0]); PUFFSOP_INIT(pops); puffs_null_setops(pops); if ((pu = puffs_init(pops, argv[0], "pnullfs", NULL, pflags)) == NULL) err(1, "init"); pn_root = puffs_pn_new(pu, NULL); if (pn_root == NULL) err(1, "puffs_pn_new"); puffs_setroot(pu, pn_root); puffs_setfhsize(pu, 0, PUFFS_FHFLAG_PASSTHROUGH); po_root = puffs_getrootpathobj(pu); if (po_root == NULL) err(1, "getrootpathobj"); po_root->po_path = argv[0]; po_root->po_len = strlen(argv[0]); puffs_stat2vattr(&pn_root->pn_va, &sb); if (detach) if (puffs_daemon(pu, 1, 1) == -1) err(1, "puffs_daemon"); if (puffs_mount(pu, argv[1], mntflags, pn_root) == -1) err(1, "puffs_mount"); if (puffs_mainloop(pu) == -1) err(1, "mainloop"); return 0; }