int main(int argc, char **argv) { int ch, mntflags; char mntpath[MAXPATHLEN]; struct vfsconf vfc; int error; /* * XXX * mount(8) calls the mount programs with an argv[0] which is * /just/ the filesystem name. So, if there is no underscore * in argv[0], we assume that we are being called from mount(8) * and that argv[0] is thus the name of the filesystem type. */ fsname = strrchr(argv[0], '_'); if (fsname) { if (strcmp(fsname, "_std") == 0) errx(EX_USAGE, "argv[0] must end in _fsname"); fsname++; } else { fsname = argv[0]; } mntflags = 0; while ((ch = getopt(argc, argv, "o:")) != -1) switch (ch) { case 'o': getmntopts(optarg, mopts, &mntflags, 0); break; case '?': default: usage(); } argc -= optind; argv += optind; if (argc != 2) usage(); error = getvfsbyname(fsname, &vfc); if (error && vfsisloadable(fsname)) { if(vfsload(fsname)) err(EX_OSERR, "vfsload(%s)", fsname); endvfsent(); error = getvfsbyname(fsname, &vfc); } if (error) errx(EX_OSERR, "%s filesystem not available", fsname); /* resolve the mountpoint with realpath(3) */ checkpath(argv[1], mntpath); if (mount(vfc.vfc_name, mntpath, mntflags, NULL)) err(EX_OSERR, NULL); exit(0); }
int fuse_kext_check_version(void) { int ret = 0; struct vfsconf vfc; ret = getvfsbyname(OSXFUSE_NAME, &vfc); if (ret) { // Kernel extension not loaded return ENOENT; } char version[32]; size_t version_len = sizeof(version); ret = sysctlbyname(OSXFUSE_SYSCTL_VERSION_NUMBER, version, &version_len, NULL, (size_t)0); if (ret) { // Kernel extension version not supported return EINVAL; } if (version_len != sizeof(OSXFUSE_VERSION) || strncmp(OSXFUSE_VERSION, version, version_len)) { // Kernel extension version not supported return EINVAL; } return ret; }
static int check_kext_status(void) { int result = -1; char version[MAXHOSTNAMELEN + 1] = { 0 }; size_t version_len = MAXHOSTNAMELEN; size_t version_len_desired = 0; struct vfsconf vfc = { 0 }; result = getvfsbyname(OSXFUSE_NAME, &vfc); if (result) { /* osxfuse is not already loaded */ return ESRCH; } /* Some version of osxfuse is already loaded. Let's check it out */ result = sysctlbyname(OSXFUSE_SYSCTL_VERSION_NUMBER, version, &version_len, (void *)NULL, (size_t)0); if (result) { return result; } /* sysctlbyname() includes the trailing '\0' in version_len */ version_len_desired = strlen(OSXFUSE_VERSION) + 1; if ((version_len != version_len_desired) || strncmp(OSXFUSE_VERSION, version, version_len)) { return EINVAL; } /* What's currently loaded is good */ return 0; }
/* * Usage: mount_hammer2 [volume] [mtpt] */ int main(int argc, char *argv[]) { struct hammer2_mount_info info; struct vfsconf vfc; char *mountpt; int error; int mount_flags; bzero(&info, sizeof(info)); mount_flags = 0; if (argc < 3) exit(1); error = getvfsbyname("hammer2", &vfc); if (error) { fprintf(stderr, "hammer2 vfs not loaded\n"); exit(1); } /* * Connect to the cluster controller. This handles both remote * mounts and device cache/master/slave mounts. * * When doing remote mounts that are allowed to run in the background * the mount program will fork, detach, print a message, and exit(0) * the originator while retrying in the background. */ info.cluster_fd = cluster_connect(argv[1]); if (info.cluster_fd < 0) { fprintf(stderr, "hammer2_mount: cluster_connect(%s) failed\n", argv[1]); exit(1); } /* * Try to mount it */ info.volume = argv[1]; info.hflags = 0; mountpt = argv[2]; error = mount(vfc.vfc_name, mountpt, mount_flags, &info); if (error) { perror("mount: "); exit(1); } /* * XXX fork a backgrounded reconnector process to handle connection * failures. XXX */ return (0); }
libzfs_handle_t * libzfs_init(void) { libzfs_handle_t *hdl; #ifdef __APPLE__ struct vfsconf vfc; struct stat sb; int loaded; /* Attempt to load zfs kext if its not already loaded. */ if (getvfsbyname("zfs", &vfc) != 0) { int pick = 0; int i; /* Find all possible zfs kext versions. */ getkextvers(kextpaths[0], &kextvers[0]); /* Pick the newest one. */ for (i = 0; i < 1; ++i) { if (kextvers[i] > kextvers[pick]) pick = i; } loaded = load_zfs_kext(kextpaths[pick]); } /* Attempt to create "/etc/zfs" its not already there. */ if (getuid() == 0 && stat("/etc/zfs", &sb)!= 0 && errno == ENOENT) { (void) mkdir("/etc/zfs", 0755); } #endif if ((hdl = calloc(sizeof (libzfs_handle_t), 1)) == NULL) { return (NULL); } if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) { free(hdl); return (NULL); } #ifndef __APPLE__ if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) { (void) close(hdl->libzfs_fd); free(hdl); return (NULL); } #endif /*!__APPLE__*/ hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "r"); zfs_prop_init(); return (hdl); }
int umountall(char **typelist) { struct vfsconf vfc; struct fstab *fs; int rval; char *cp; static int firstcall = 1; if ((fs = getfsent()) != NULL) firstcall = 0; else if (firstcall) errx(1, "fstab reading failure"); else return (0); do { /* Ignore the root. */ if (strcmp(fs->fs_file, "/") == 0) continue; /* * !!! * Historic practice: ignore unknown FSTAB_* fields. */ if (strcmp(fs->fs_type, FSTAB_RW) && strcmp(fs->fs_type, FSTAB_RO) && strcmp(fs->fs_type, FSTAB_RQ)) continue; /* If an unknown file system type, complain. */ if (getvfsbyname(fs->fs_vfstype, &vfc) == -1) { warnx("%s: unknown mount type", fs->fs_vfstype); continue; } if (checkvfsname(fs->fs_vfstype, typelist)) continue; /* * We want to unmount the file systems in the reverse order * that they were mounted. So, we save off the file name * in some allocated memory, and then call recursively. */ if ((cp = malloc((size_t)strlen(fs->fs_file) + 1)) == NULL) err(1, "malloc failed"); (void)strcpy(cp, fs->fs_file); rval = umountall(typelist); rval = umountfs(cp, typelist) || rval; free(cp); return (rval); } while ((fs = getfsent()) != NULL); return (0); }
int main(int argc, char *argv[]) { struct vfsconf vfc; int mib[4], max, x; size_t len; printf(HDRFMT, "Filesystem", "Refs", "Flags"); fputs(DASHES, stdout); if (argc > 1) { for (x = 1; x < argc; x++) if (getvfsbyname(argv[x], &vfc) == 0) printf(FMT, vfc.vfc_name, vfc.vfc_refcount, fmt_flags(vfc.vfc_flags)); else warnx("VFS %s unknown or not loaded", argv[x]); } else { mib[0] = CTL_VFS; mib[1] = VFS_GENERIC; mib[2] = VFS_MAXTYPENUM; len = sizeof(int); if (sysctl(mib, 3, &max, &len, NULL, 0) != 0) errx(1, "sysctl"); mib[2] = VFS_CONF; len = sizeof(vfc); for (x = 0; x < max; x++) { mib[3] = x; if (sysctl(mib, 4, &vfc, &len, NULL, 0) != 0) { if (errno != ENOTSUP) errx(1, "sysctl"); } else { printf(FMT, vfc.vfc_name, vfc.vfc_refcount, fmt_flags(vfc.vfc_flags)); } } } return 0; }
int main(int argc, char **argv) { int cnt, rv = 0, i; struct xvfsconf vfc, *xvfsp; size_t buflen; argc--, argv++; printf(HDRFMT, "Filesystem", "Refs", "Flags"); fputs(DASHES, stdout); if(argc) { for(; argc; argc--, argv++) { if (getvfsbyname(*argv, &vfc) == 0) { printf(FMT, vfc.vfc_name, vfc.vfc_refcount, fmt_flags(vfc.vfc_flags)); } else { warnx("VFS %s unknown or not loaded", *argv); rv++; } } } else { if (sysctlbyname("vfs.conflist", NULL, &buflen, NULL, 0) < 0) err(1, "sysctl(vfs.conflist)"); xvfsp = malloc(buflen); if (xvfsp == NULL) errx(1, "malloc failed"); if (sysctlbyname("vfs.conflist", xvfsp, &buflen, NULL, 0) < 0) err(1, "sysctl(vfs.conflist)"); cnt = buflen / sizeof(struct xvfsconf); for (i = 0; i < cnt; i++) { printf(FMT, xvfsp[i].vfc_name, xvfsp[i].vfc_refcount, fmt_flags(xvfsp[i].vfc_flags)); } free(xvfsp); } return rv; }
/* * Read the nfs stats using sysctl(3) for live kernels, or kvm_read * for dead ones. */ void readstats(struct nfsstats *stp) { if(deadkernel) { if(kvm_read(kd, (u_long)nl[N_NFSSTAT].n_value, stp, sizeof *stp) < 0) { err(1, "kvm_read"); } } else { int name[3]; size_t buflen = sizeof *stp; struct vfsconf vfc; if (getvfsbyname("nfs", &vfc) < 0) err(1, "getvfsbyname: NFS not compiled into kernel"); name[0] = CTL_VFS; name[1] = vfc.vfc_typenum; name[2] = NFS_NFSSTATS; if (sysctl(name, 3, stp, &buflen, NULL, (size_t)0) < 0) { err(1, "sysctl"); } } }
int main(void) { zfs_footprint_stats_t *footprint; size_t buflen = 8192; struct vfsconf vfc; int name[3]; int i; if (getvfsbyname("zfs", &vfc) < 0) errx(1, "ZFS not loaded into kernel"); footprint = (zfs_footprint_stats_t *) malloc(buflen); name[0] = CTL_VFS; name[1] = vfc.vfc_typenum; name[2] = ZFS_SYSCTL_FOOTPRINT; if (sysctl(name, 3, footprint, &buflen, (void *)0, (size_t)0) < 0) err(1, "sysctl"); if (footprint->version != ZFS_FOOTPRINT_VERSION) errx(1, "ZFS footprint sysctl version mismatch"); (void) initscr(); while (1) { kmem_cache_total = kmem_cache_inuse = 0; row = 0; name[0] = CTL_VFS; name[1] = vfc.vfc_typenum; name[2] = ZFS_SYSCTL_FOOTPRINT; if (sysctl(name, 3, footprint, &buflen, (void *)0, (size_t)0) < 0) err(1, "sysctl"); clear(); print_memory_info("ZFS footprint", &footprint->memory_stats); print_memory_info("ARC footprint", &footprint->arc_stats); row++; sprintf(linebuf, "%3d threads", footprint->thread_count); mvaddstr(0, 65, linebuf); sprintf(linebuf, "%9s %9s %9s %9s %9s %8s", "obj", "slab", "active", "total", "peak", "total"); mvaddstr(row++, 18, linebuf); sprintf(linebuf, " kmem_cache name"); mvaddstr(row, 0, linebuf); sprintf(linebuf, "%9s %9s %9s %9s %9s %8s", "size", "size", "objs", "objs", "objs", "mem"); mvaddstr(row++, 18, linebuf); sprintf(linebuf, "-----------------------------------------------------------------------------"); mvaddstr(row++, 0, linebuf); for (i = 0; i < footprint->caches_count; ++i) { print_cache_info(&footprint->cache_stats[i]); } sprintf(linebuf, "-----------------------------------------------------------------------------"); mvaddstr(row++, 0, linebuf); sprintf(linebuf, " kmem_cache total: %6dM %6dM", kmem_cache_inuse / ONEMEGABYTE, kmem_cache_total / ONEMEGABYTE); mvaddstr(row++, 0, linebuf); move(row, 0); // clrtobot(); refresh(); sleep(1); } endwin(); exit(0); }
libzfs_handle_t * libzfs_init(void) { libzfs_handle_t *hdl; #ifdef __APPLE__ struct vfsconf vfc; struct stat sb; int loaded; /* Attempt to load zfs kext if its not already loaded. */ if (getvfsbyname("zfs", &vfc) != 0) { int pick = 0; int i; /* Find all possible zfs kext versions. */ getkextvers(kextpaths[0], &kextvers[0]); getkextvers(kextpaths[1], &kextvers[1]); /* Pick the newest one. */ for (i = 0; i < 2; ++i) { if (kextvers[i] > kextvers[pick]) pick = i; } loaded = load_zfs_kext(kextpaths[pick]); ASSERT(loaded == 0); } /* Attempt to create "/etc/zfs" its not already there. */ if (getuid() == 0 && stat("/etc/zfs", &sb)!= 0 && errno == ENOENT) { (void) mkdir("/etc/zfs", 0755); } #endif if ((hdl = calloc(sizeof (libzfs_handle_t), 1)) == NULL) { return (NULL); } if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) { free(hdl); return (NULL); } else { /* Perform special version ceck ioctl() to unlock user-kernel * interface. This serves as protection against using userland * tools of one implementation against kernel land of another * implementation. */ zfs_cmd_t vers_zc = {0}; strncpy(vers_zc.zc_name, __STRING(MACZFS_ID), sizeof(vers_zc.zc_name)-1); vers_zc.zc_value[0] = ZFS_IOC_NUM(ZFS_IOC__LAST_USED); vers_zc.zc_value[1] = MACZFS_VERS_MAJOR; vers_zc.zc_value[2] = MACZFS_VERS_MINOR; vers_zc.zc_value[3] = MACZFS_VERS_PATCH; hdl->libzfs_log_str = NULL; if (zfs_ioctl(hdl, ZFS_IOC__VERSION_CHECK, &vers_zc) != 0) { /* kernel - user version mismatch or kernel side not ready. */ free(hdl); return (NULL); } } #ifndef __APPLE__ if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) { (void) close(hdl->libzfs_fd); free(hdl); return (NULL); } #endif /*!__APPLE__*/ hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "r"); zfs_prop_init(); return (hdl); }
int main(int argc, char **argv) { struct portal_args args; struct sockaddr_un un; char *conf; char mountpt[MAXPATHLEN]; int mntflags = 0; char tag[32]; struct vfsconf vfc; mode_t um; qelem q; int rc; int so; int error = 0; /* * Crack command line args */ int ch; while ((ch = getopt(argc, argv, "o:")) != -1) { switch (ch) { case 'o': getmntopts(optarg, mopts, &mntflags, 0); break; default: error = 1; break; } } if (optind != (argc - 2)) error = 1; if (error) usage(); /* * Get config file and mount point */ conf = argv[optind]; /* resolve the mountpoint with realpath(3) */ checkpath(argv[optind+1], mountpt); /* * Construct the listening socket */ un.sun_family = AF_UNIX; if (sizeof(_PATH_TMPPORTAL) >= sizeof(un.sun_path)) { errx(EX_SOFTWARE, "portal socket name too long"); } strcpy(un.sun_path, _PATH_TMPPORTAL); mktemp(un.sun_path); un.sun_len = strlen(un.sun_path); so = socket(AF_UNIX, SOCK_STREAM, 0); if (so < 0) { err(EX_OSERR, "socket"); } um = umask(077); unlink(un.sun_path); if (bind(so, (struct sockaddr *) &un, sizeof(un)) < 0) err(1, NULL); unlink(un.sun_path); umask(um); listen(so, 5); args.pa_socket = so; sprintf(tag, "portal:%d", getpid()); args.pa_config = tag; error = getvfsbyname("portal", &vfc); if (error && vfsisloadable("portal")) { if (vfsload("portal")) err(EX_OSERR, "vfsload(portal)"); endvfsent(); error = getvfsbyname("portal", &vfc); } if (error) errx(EX_OSERR, "portal filesystem is not available"); rc = mount(vfc.vfc_name, mountpt, mntflags, &args); if (rc < 0) err(1, NULL); /* * Everything is ready to go - now is a good time to fork */ #ifndef DEBUG daemon(0, 0); #endif /* * Start logging (and change name) */ openlog("portald", LOG_CONS|LOG_PID, LOG_DAEMON); q.q_forw = q.q_back = &q; readcf = 1; signal(SIGCHLD, sigchld); signal(SIGHUP, sighup); /* * Just loop waiting for new connections and activating them */ for (;;) { struct sockaddr_un un2; int len2 = sizeof(un2); int so2; pid_t pid; fd_set fdset; /* * Check whether we need to re-read the configuration file */ if (readcf) { #ifdef DEBUG printf ("re-reading configuration file\n"); #endif readcf = 0; conf_read(&q, conf); continue; } /* * Accept a new connection * Will get EINTR if a signal has arrived, so just * ignore that error code */ FD_ZERO(&fdset); FD_SET(so, &fdset); rc = select(so+1, &fdset, NULL, NULL, NULL); if (rc < 0) { if (errno == EINTR) continue; syslog(LOG_ERR, "select: %s", strerror(errno)); exit(EX_OSERR); } if (rc == 0) break; so2 = accept(so, (struct sockaddr *) &un2, &len2); if (so2 < 0) { /* * The unmount function does a shutdown on the socket * which will generated ECONNABORTED on the accept. */ if (errno == ECONNABORTED) break; if (errno != EINTR) { syslog(LOG_ERR, "accept: %s", strerror(errno)); exit(EX_OSERR); } continue; } /* * Now fork a new child to deal with the connection */ eagain:; switch (pid = fork()) { case -1: if (errno == EAGAIN) { sleep(1); goto eagain; } syslog(LOG_ERR, "fork: %s", strerror(errno)); break; case 0: close(so); activate(&q, so2); exit(0); default: close(so2); break; } } syslog(LOG_INFO, "%s unmounted", mountpt); exit(0); }
int main(int ac, char **av) { struct hammer_mount_info info; struct vfsconf vfc; struct hammer_volume_ondisk *od; int mount_flags = 0; int error; int ch; int init_flags = 0; int ax; int fd; int pr; int fdevs_size; char *mountpt; char *ptr; char *fdevs; bzero(&info, sizeof(info)); info.asof = 0; mount_flags = 0; info.hflags = 0; while ((ch = getopt(ac, av, "o:T:u")) != -1) { switch(ch) { case 'T': info.asof = strtoull(optarg, NULL, 0); break; case 'o': getmntopts(optarg, mopts, &mount_flags, &info.hflags); /* * Handle extended flags with parameters. */ if (info.hflags & HMNT_MASTERID) { ptr = strstr(optarg, "master="); if (ptr) { info.master_id = strtol(ptr + 7, NULL, 0); if (info.master_id == 0) { fprintf(stderr, "hammer_mount: Warning: a master id of 0 is the default, explicit\n" "settings should probably use 1-15\n"); } } ptr = strstr(optarg, "nomirror"); if (ptr) info.master_id = -1; } break; case 'u': init_flags |= MNT_UPDATE; break; default: usage(); /* not reached */ } } ac -= optind; av += optind; mount_flags |= init_flags; /* * Only the mount point need be specified in update mode. */ if (init_flags & MNT_UPDATE) { if (ac != 1) { usage(); /* not reached */ } mountpt = av[0]; if (mount(vfc.vfc_name, mountpt, mount_flags, &info)) err(1, "mountpoint %s", mountpt); exit(0); } if (ac < 2) { usage(); /* not reached */ } /* * Mount arguments: vol [vol...] mountpt */ extract_volumes(&info.volumes, &info.nvolumes, av, ac - 1); mountpt = av[ac - 1]; /* * Load the hammer module if necessary (this bit stolen from * mount_null). */ error = getvfsbyname("hammer", &vfc); if (error && vfsisloadable("hammer")) { if (vfsload("hammer") != 0) err(1, "vfsload(hammer)"); endvfsent(); error = getvfsbyname("hammer", &vfc); } if (error) errx(1, "hammer filesystem is not available"); if (mount(vfc.vfc_name, mountpt, mount_flags, &info)) { /* Build fdevs in case of error to report failed devices */ fdevs_size = ac * PATH_MAX; fdevs = malloc(fdevs_size); for (ax = 0; ax < ac - 1; ax++) { fd = open(info.volumes[ax], O_RDONLY); if (fd < 0 ) { printf ("%s: open failed\n", info.volumes[ax]); strlcat(fdevs, info.volumes[ax], fdevs_size); if (ax < ac - 2) strlcat(fdevs, " ", fdevs_size); continue; } od = malloc(HAMMER_BUFSIZE); if (od == NULL) { close (fd); perror("malloc"); continue; } bzero(od, HAMMER_BUFSIZE); pr = pread(fd, od, HAMMER_BUFSIZE, 0); if (pr != HAMMER_BUFSIZE || od->vol_signature != HAMMER_FSBUF_VOLUME) { printf("%s: Not a valid HAMMER filesystem\n", info.volumes[ax]); strlcat(fdevs, info.volumes[ax], fdevs_size); if (ax < ac - 2) strlcat(fdevs, " ", fdevs_size); } close(fd); } err(1,"mount %s on %s", fdevs, mountpt); } exit (0); }
int main(int argc, char *argv[]) { int ch; struct xvfsconf vfc; int error; unsigned int iodmin, iodmax, num_servers; size_t len; error = getvfsbyname("nfs", &vfc); if (error) { if (kldload("nfs") == -1) err(1, "kldload(nfs)"); error = getvfsbyname("nfs", &vfc); } if (error) errx(1, "NFS support is not available in the running kernel"); num_servers = 0; while ((ch = getopt(argc, argv, "n:")) != -1) switch (ch) { case 'n': num_servers = atoi(optarg); if (num_servers < 1) { warnx("nfsiod count %u; reset to %d", num_servers, 1); num_servers = 1; } if (num_servers > MAXNFSDCNT) { warnx("nfsiod count %u; reset to %d", num_servers, MAXNFSDCNT); num_servers = MAXNFSDCNT; } break; case '?': default: usage(); } argc -= optind; argv += optind; if (argc > 0) usage(); len = sizeof iodmin; error = sysctlbyname("vfs.nfs.iodmin", &iodmin, &len, NULL, 0); if (error < 0) err(1, "sysctlbyname(\"vfs.nfs.iodmin\")"); len = sizeof iodmax; error = sysctlbyname("vfs.nfs.iodmax", &iodmax, &len, NULL, 0); if (error < 0) err(1, "sysctlbyname(\"vfs.nfs.iodmax\")"); if (num_servers == 0) { /* no change */ printf("vfs.nfs.iodmin=%u\nvfs.nfs.iodmax=%u\n", iodmin, iodmax); exit(0); } /* Catch the case where we're lowering num_servers below iodmin */ if (iodmin > num_servers) { iodmin = num_servers; error = sysctlbyname("vfs.nfs.iodmin", NULL, 0, &iodmin, sizeof iodmin); if (error < 0) err(1, "sysctlbyname(\"vfs.nfs.iodmin\")"); } iodmax = num_servers; error = sysctlbyname("vfs.nfs.iodmax", NULL, 0, &iodmax, sizeof iodmax); if (error < 0) err(1, "sysctlbyname(\"vfs.nfs.iodmax\")"); exit (0); }
int main(int argc, char *argv[]) { struct iovec *iov; unsigned int iovlen; struct smb_ctx sctx, *ctx = &sctx; struct stat st; #ifdef APPLE extern void dropsuid(); extern int loadsmbvfs(); #else struct xvfsconf vfc; #endif char *next, *p, *val; int opt, error, mntflags, caseopt, fd; uid_t uid; gid_t gid; mode_t dir_mode, file_mode; char errmsg[255] = { 0 }; iov = NULL; iovlen = 0; fd = 0; uid = (uid_t)-1; gid = (gid_t)-1; caseopt = 0; file_mode = 0; dir_mode = 0; #ifdef APPLE dropsuid(); #endif if (argc == 2) { if (strcmp(argv[1], "-h") == 0) { usage(); } } if (argc < 3) usage(); #ifdef APPLE error = loadsmbvfs(); #else error = getvfsbyname(smbfs_vfsname, &vfc); if (error) { if (kldload(smbfs_vfsname) < 0) err(EX_OSERR, "kldload(%s)", smbfs_vfsname); error = getvfsbyname(smbfs_vfsname, &vfc); } #endif if (error) errx(EX_OSERR, "SMB filesystem is not available"); if (smb_lib_init() != 0) exit(1); mntflags = error = 0; caseopt = SMB_CS_NONE; if (smb_ctx_init(ctx, argc, argv, SMBL_SHARE, SMBL_SHARE, SMB_ST_DISK) != 0) exit(1); if (smb_ctx_readrc(ctx) != 0) exit(1); if (smb_rc) rc_close(smb_rc); while ((opt = getopt(argc, argv, STDPARAM_OPT"c:d:f:g:l:n:o:u:w:")) != -1) { switch (opt) { case STDPARAM_ARGS: error = smb_ctx_opt(ctx, opt, optarg); if (error) exit(1); break; case 'u': { struct passwd *pwd; pwd = isdigit(optarg[0]) ? getpwuid(atoi(optarg)) : getpwnam(optarg); if (pwd == NULL) errx(EX_NOUSER, "unknown user '%s'", optarg); uid = pwd->pw_uid; break; } case 'g': { struct group *grp; grp = isdigit(optarg[0]) ? getgrgid(atoi(optarg)) : getgrnam(optarg); if (grp == NULL) errx(EX_NOUSER, "unknown group '%s'", optarg); gid = grp->gr_gid; break; } case 'd': errno = 0; dir_mode = strtol(optarg, &next, 8); if (errno || *next != 0) errx(EX_DATAERR, "invalid value for directory mode"); break; case 'f': errno = 0; file_mode = strtol(optarg, &next, 8); if (errno || *next != 0) errx(EX_DATAERR, "invalid value for file mode"); break; case '?': usage(); /*NOTREACHED*/ case 'n': { char *inp, *nsp; nsp = inp = optarg; while ((nsp = strsep(&inp, ",;:")) != NULL) { if (strcasecmp(nsp, "LONG") == 0) { build_iovec(&iov, &iovlen, "nolong", NULL, 0); } else { errx(EX_DATAERR, "unknown suboption '%s'", nsp); } } break; }; case 'o': getmntopts(optarg, mopts, &mntflags, 0); p = strchr(optarg, '='); val = NULL; if (p != NULL) { *p = '\0'; val = p + 1; } build_iovec(&iov, &iovlen, optarg, val, (size_t)-1); break; case 'c': switch (optarg[0]) { case 'l': caseopt |= SMB_CS_LOWER; break; case 'u': caseopt |= SMB_CS_UPPER; break; default: errx(EX_DATAERR, "invalid suboption '%c' for -c", optarg[0]); } break; default: usage(); } } if (optind == argc - 2) optind++; if (optind != argc - 1) usage(); realpath(argv[optind], mount_point); if (stat(mount_point, &st) == -1) err(EX_OSERR, "could not find mount point %s", mount_point); if (!S_ISDIR(st.st_mode)) { errno = ENOTDIR; err(EX_OSERR, "can't mount on %s", mount_point); } /* if (smb_getextattr(mount_point, &einfo) == 0) errx(EX_OSERR, "can't mount on %s twice", mount_point); */ if (uid == (uid_t)-1) uid = st.st_uid; if (gid == (gid_t)-1) gid = st.st_gid; if (file_mode == 0 ) file_mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); if (dir_mode == 0) { dir_mode = file_mode; if (dir_mode & S_IRUSR) dir_mode |= S_IXUSR; if (dir_mode & S_IRGRP) dir_mode |= S_IXGRP; if (dir_mode & S_IROTH) dir_mode |= S_IXOTH; } /* * For now, let connection be private for this mount */ ctx->ct_ssn.ioc_opt |= SMBVOPT_PRIVATE; ctx->ct_ssn.ioc_owner = ctx->ct_sh.ioc_owner = 0; /* root */ ctx->ct_ssn.ioc_group = ctx->ct_sh.ioc_group = gid; opt = 0; if (dir_mode & S_IXGRP) opt |= SMBM_EXECGRP; if (dir_mode & S_IXOTH) opt |= SMBM_EXECOTH; ctx->ct_ssn.ioc_rights |= opt; ctx->ct_sh.ioc_rights |= opt; error = smb_ctx_resolve(ctx); if (error) exit(1); error = smb_ctx_lookup(ctx, SMBL_SHARE, SMBLK_CREATE); if (error) { exit(1); } fd = ctx->ct_fd; build_iovec(&iov, &iovlen, "fstype", strdup("smbfs"), -1); build_iovec(&iov, &iovlen, "fspath", mount_point, -1); build_iovec_argf(&iov, &iovlen, "fd", "%d", fd); build_iovec(&iov, &iovlen, "mountpoint", mount_point, -1); build_iovec_argf(&iov, &iovlen, "uid", "%d", uid); build_iovec_argf(&iov, &iovlen, "gid", "%d", gid); build_iovec_argf(&iov, &iovlen, "file_mode", "%d", file_mode); build_iovec_argf(&iov, &iovlen, "dir_mode", "%d", dir_mode); build_iovec_argf(&iov, &iovlen, "caseopt", "%d", caseopt); build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof errmsg); error = nmount(iov, iovlen, mntflags); smb_ctx_done(ctx); if (error) { smb_error("mount error: %s %s", error, mount_point, errmsg); exit(1); } return 0; }
int main(__unused int argc, __unused const char *argv[]) { pid_t pid = -1; int result = -1; int status; char version[MAXHOSTNAMELEN + 1] = { 0 }; size_t version_len = MAXHOSTNAMELEN; size_t version_len_desired = 0; struct vfsconf vfc = { 0 }; result = getvfsbyname(MACFUSE_FS_TYPE, &vfc); if (result) { /* MacFUSE is not already loaded */ result = -1; goto need_loading; } /* some version of MacFUSE is already loaded; let us check it out */ result = sysctlbyname(SYSCTL_MACFUSE_VERSION_NUMBER, version, &version_len, NULL, (size_t)0); if (result) { if (errno == ENOENT) { /* too old; doesn't even have the sysctl variable */ goto need_unloading; } result = -1; goto out; } /* sysctlbyname() includes the trailing '\0' in version_len */ version_len_desired = strlen(MACFUSE_VERSION) + 1; if ((version_len == version_len_desired) && !strncmp(MACFUSE_VERSION, version, version_len)) { /* what's currently loaded is good */ result = 0; goto out; } /* mismatched version; need to unload what's loaded */ need_unloading: pid = fork(); if (pid == 0) { result = execl(SYSTEM_KEXTUNLOAD, SYSTEM_KEXTUNLOAD, "-b", MACFUSE_BUNDLE_IDENTIFIER, NULL); /* We can only get here if the exec failed */ goto out; } if (pid == -1) { result = errno; goto out; } /* Success! */ if ((waitpid(pid, &status, 0) == pid) && (WIFEXITED(status))) { result = status; } else { result = -1; } if (result != 0) { /* unloading failed */ result = EBUSY; goto out; } /* unloading succeeded; now load the on-disk version */ need_loading: pid = fork(); if (pid == 0) { result = execl(SYSTEM_KEXTLOAD, SYSTEM_KEXTLOAD, MACFUSE_KEXT, NULL); /* We can only get here if the exec failed */ goto out; } if (pid == -1) { result = errno; goto out; } /* Success! */ if ((waitpid(pid, &status, 0) == pid) && (WIFEXITED(status))) { result = status; } else { result = -1; } /* now do any kext-load-time settings we need to do as root */ if (result == 0) { int admin_gid = 0; struct group *g = getgrnam(MACOSX_ADMIN_GROUP_NAME); if (!g) { goto out; } admin_gid = g->gr_gid; /* if this fails, we don't care */ (void)sysctlbyname(SYSCTL_MACFUSE_TUNABLES_ADMIN, NULL, NULL, &admin_gid, sizeof(admin_gid)); } out: _exit(result); }
libzfs_handle_t * libzfs_init(void) { libzfs_handle_t *hdl; #ifdef __APPLE__ struct vfsconf vfc; struct stat sb; int loaded; /* Attempt to load zfs kext if its not already loaded. */ if (getvfsbyname("zfs", &vfc) != 0) { int pick = 0; int i; /* Find all possible zfs kext versions. */ getkextvers(kextpaths[0], &kextvers[0]); getkextvers(kextpaths[1], &kextvers[1]); getkextvers(kextpaths[2], &kextvers[2]); /* Pick the newest one. */ for (i = 0; i < 3; ++i) { if (kextvers[i] > kextvers[pick]) pick = i; } loaded = load_zfs_kext(kextpaths[pick]); zfs_readonly_kext = (pick == 2); /* Make sure user knows they have loaded the readonly kext */ if(zfs_readonly_kext && (loaded != -1)) (void) fprintf(stderr, gettext("ZFS Readonly implemntation " "is loaded!\nTo download the full ZFS " "read/write kext with all functionality " "enabled, please go to " "http://developer.apple.com\n")); } else { zfs_readonly_kext = is_readonly_kext(vfc.vfc_typenum); } /* Attempt to create "/etc/zfs" its not already there. */ if (getuid() == 0 && stat("/etc/zfs", &sb)!= 0 && errno == ENOENT) { (void) mkdir("/etc/zfs", 0755); } #endif if ((hdl = calloc(sizeof (libzfs_handle_t), 1)) == NULL) { return (NULL); } if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) { free(hdl); return (NULL); } #ifndef __APPLE__ if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) { (void) close(hdl->libzfs_fd); free(hdl); return (NULL); } #endif /*!__APPLE__*/ hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "r"); zfs_prop_init(); /* Make sure the user knows they have loaded the Read Only kext */ return (hdl); }
/* * Nfs server daemon mostly just a user context for nfssvc() * * 1 - do file descriptor and signal cleanup * 2 - fork the nfsd(s) * 3 - create server socket(s) * 4 - register socket with rpcbind * * For connectionless protocols, just pass the socket into the kernel via. * nfssvc(). * For connection based sockets, loop doing accepts. When you get a new * socket from accept, pass the msgsock into the kernel via. nfssvc(). * The arguments are: * -r - reregister with rpcbind * -d - unregister with rpcbind * -t - support tcp nfs clients * -u - support udp nfs clients * followed by "n" which is the number of nfsds' to fork off */ int main(int argc, char **argv) { struct nfsd_args nfsdargs; struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints; struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6; struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6; struct sockaddr_in inetpeer; struct sockaddr_in6 inet6peer; fd_set ready, sockbits; fd_set v4bits, v6bits; int ch, connect_type_cnt, i, maxsock, msgsock; socklen_t len; int on = 1, unregister, reregister, sock; int tcp6sock, ip6flag, tcpflag, tcpsock; int udpflag, ecode, s, srvcnt; int bindhostc, bindanyflag, rpcbreg, rpcbregcnt; char **bindhost = NULL; pid_t pid; struct vfsconf vfc; int error; error = getvfsbyname("nfs", &vfc); if (error && vfsisloadable("nfs")) { if (vfsload("nfs")) err(1, "vfsload(nfs)"); endvfsent(); /* flush cache */ error = getvfsbyname("nfs", &vfc); } if (error) errx(1, "NFS is not available in the running kernel"); nfsdcnt = DEFNFSDCNT; unregister = reregister = tcpflag = maxsock = 0; bindanyflag = udpflag = connect_type_cnt = bindhostc = 0; #define GETOPT "ah:n:rdtu" #define USAGE "[-ardtu] [-n num_servers] [-h bindip]" while ((ch = getopt(argc, argv, GETOPT)) != -1) switch (ch) { case 'a': bindanyflag = 1; break; case 'n': nfsdcnt = atoi(optarg); if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT); nfsdcnt = DEFNFSDCNT; } break; case 'h': bindhostc++; bindhost = realloc(bindhost,sizeof(char *)*bindhostc); if (bindhost == NULL) errx(1, "Out of memory"); bindhost[bindhostc-1] = strdup(optarg); if (bindhost[bindhostc-1] == NULL) errx(1, "Out of memory"); break; case 'r': reregister = 1; break; case 'd': unregister = 1; break; case 't': tcpflag = 1; break; case 'u': udpflag = 1; break; default: case '?': usage(); }; if (!tcpflag && !udpflag) udpflag = 1; argv += optind; argc -= optind; /* * XXX * Backward compatibility, trailing number is the count of daemons. */ if (argc > 1) usage(); if (argc == 1) { nfsdcnt = atoi(argv[0]); if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT); nfsdcnt = DEFNFSDCNT; } } ip6flag = 1; s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (s == -1) { if (errno != EPROTONOSUPPORT) err(1, "socket"); ip6flag = 0; } else if (getnetconfigent("udp6") == NULL || getnetconfigent("tcp6") == NULL) { ip6flag = 0; } if (s != -1) close(s); if (bindhostc == 0 || bindanyflag) { bindhostc++; bindhost = realloc(bindhost,sizeof(char *)*bindhostc); if (bindhost == NULL) errx(1, "Out of memory"); bindhost[bindhostc-1] = strdup("*"); if (bindhost[bindhostc-1] == NULL) errx(1, "Out of memory"); } if (unregister) { unregistration(); exit (0); } if (reregister) { if (udpflag) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp); if (ecode != 0) err(1, "getaddrinfo udp: %s", gai_strerror(ecode)); nconf_udp = getnetconfigent("udp"); if (nconf_udp == NULL) err(1, "getnetconfigent udp failed"); nb_udp.buf = ai_udp->ai_addr; nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen; if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) || (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp))) err(1, "rpcb_set udp failed"); freeaddrinfo(ai_udp); } if (udpflag && ip6flag) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6); if (ecode != 0) err(1, "getaddrinfo udp6: %s", gai_strerror(ecode)); nconf_udp6 = getnetconfigent("udp6"); if (nconf_udp6 == NULL) err(1, "getnetconfigent udp6 failed"); nb_udp6.buf = ai_udp6->ai_addr; nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen; if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) || (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6))) err(1, "rpcb_set udp6 failed"); freeaddrinfo(ai_udp6); } if (tcpflag) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp); if (ecode != 0) err(1, "getaddrinfo tcp: %s", gai_strerror(ecode)); nconf_tcp = getnetconfigent("tcp"); if (nconf_tcp == NULL) err(1, "getnetconfigent tcp failed"); nb_tcp.buf = ai_tcp->ai_addr; nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen; if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp))) err(1, "rpcb_set tcp failed"); freeaddrinfo(ai_tcp); } if (tcpflag && ip6flag) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6); if (ecode != 0) err(1, "getaddrinfo tcp6: %s", gai_strerror(ecode)); nconf_tcp6 = getnetconfigent("tcp6"); if (nconf_tcp6 == NULL) err(1, "getnetconfigent tcp6 failed"); nb_tcp6.buf = ai_tcp6->ai_addr; nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen; if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) || (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6))) err(1, "rpcb_set tcp6 failed"); freeaddrinfo(ai_tcp6); } exit (0); } if (debug == 0) { daemon(0, 0); signal(SIGHUP, SIG_IGN); signal(SIGINT, SIG_IGN); /* * nfsd sits in the kernel most of the time. It needs * to ignore SIGTERM/SIGQUIT in order to stay alive as long * as possible during a shutdown, otherwise loopback * mounts will not be able to unmount. */ signal(SIGTERM, SIG_IGN); signal(SIGQUIT, SIG_IGN); } signal(SIGSYS, nonfs); signal(SIGCHLD, reapchild); openlog("nfsd", LOG_PID, LOG_DAEMON); /* If we use UDP only, we start the last server below. */ srvcnt = tcpflag ? nfsdcnt : nfsdcnt - 1; for (i = 0; i < srvcnt; i++) { switch ((pid = fork())) { case -1: syslog(LOG_ERR, "fork: %m"); nfsd_exit(1); case 0: break; default: children[i] = pid; continue; } signal(SIGUSR1, child_cleanup); setproctitle("server"); start_server(0); } signal(SIGUSR1, cleanup); FD_ZERO(&v4bits); FD_ZERO(&v6bits); FD_ZERO(&sockbits); rpcbregcnt = 0; /* Set up the socket for udp and rpcb register it. */ if (udpflag) { rpcbreg = 0; for (i = 0; i < bindhostc; i++) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; if (setbindhost(&ai_udp, bindhost[i], hints) == 0) { rpcbreg = 1; rpcbregcnt++; if ((sock = socket(ai_udp->ai_family, ai_udp->ai_socktype, ai_udp->ai_protocol)) < 0) { syslog(LOG_ERR, "can't create udp socket"); nfsd_exit(1); } if (bind(sock, ai_udp->ai_addr, ai_udp->ai_addrlen) < 0) { syslog(LOG_ERR, "can't bind udp addr %s: %m", bindhost[i]); nfsd_exit(1); } freeaddrinfo(ai_udp); nfsdargs.sock = sock; nfsdargs.name = NULL; nfsdargs.namelen = 0; if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { syslog(LOG_ERR, "can't Add UDP socket"); nfsd_exit(1); } close(sock); } } if (rpcbreg == 1) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp); if (ecode != 0) { syslog(LOG_ERR, "getaddrinfo udp: %s", gai_strerror(ecode)); nfsd_exit(1); } nconf_udp = getnetconfigent("udp"); if (nconf_udp == NULL) err(1, "getnetconfigent udp failed"); nb_udp.buf = ai_udp->ai_addr; nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen; if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) || (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp))) err(1, "rpcb_set udp failed"); freeaddrinfo(ai_udp); } } /* Set up the socket for udp6 and rpcb register it. */ if (udpflag && ip6flag) { rpcbreg = 0; for (i = 0; i < bindhostc; i++) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) { rpcbreg = 1; rpcbregcnt++; if ((sock = socket(ai_udp6->ai_family, ai_udp6->ai_socktype, ai_udp6->ai_protocol)) < 0) { syslog(LOG_ERR, "can't create udp6 socket"); nfsd_exit(1); } if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof on) < 0) { syslog(LOG_ERR, "can't set v6-only binding for " "udp6 socket: %m"); nfsd_exit(1); } if (bind(sock, ai_udp6->ai_addr, ai_udp6->ai_addrlen) < 0) { syslog(LOG_ERR, "can't bind udp6 addr %s: %m", bindhost[i]); nfsd_exit(1); } freeaddrinfo(ai_udp6); nfsdargs.sock = sock; nfsdargs.name = NULL; nfsdargs.namelen = 0; if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { syslog(LOG_ERR, "can't add UDP6 socket"); nfsd_exit(1); } close(sock); } } if (rpcbreg == 1) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6); if (ecode != 0) { syslog(LOG_ERR, "getaddrinfo udp6: %s", gai_strerror(ecode)); nfsd_exit(1); } nconf_udp6 = getnetconfigent("udp6"); if (nconf_udp6 == NULL) err(1, "getnetconfigent udp6 failed"); nb_udp6.buf = ai_udp6->ai_addr; nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen; if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) || (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6))) err(1, "rpcb_set udp6 failed"); freeaddrinfo(ai_udp6); } } /* Set up the socket for tcp and rpcb register it. */ if (tcpflag) { rpcbreg = 0; for (i = 0; i < bindhostc; i++) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) { rpcbreg = 1; rpcbregcnt++; if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { syslog(LOG_ERR, "can't create tpc socket"); nfsd_exit(1); } if (setsockopt(tcpsock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); if (bind(tcpsock, ai_tcp->ai_addr, ai_tcp->ai_addrlen) < 0) { syslog(LOG_ERR, "can't bind tcp addr %s: %m", bindhost[i]); nfsd_exit(1); } if (listen(tcpsock, 64) < 0) { syslog(LOG_ERR, "listen failed"); nfsd_exit(1); } freeaddrinfo(ai_tcp); FD_SET(tcpsock, &sockbits); FD_SET(tcpsock, &v4bits); maxsock = tcpsock; connect_type_cnt++; } } if (rpcbreg == 1) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp); if (ecode != 0) { syslog(LOG_ERR, "getaddrinfo tcp: %s", gai_strerror(ecode)); nfsd_exit(1); } nconf_tcp = getnetconfigent("tcp"); if (nconf_tcp == NULL) err(1, "getnetconfigent tcp failed"); nb_tcp.buf = ai_tcp->ai_addr; nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen; if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp))) err(1, "rpcb_set tcp failed"); freeaddrinfo(ai_tcp); } } /* Set up the socket for tcp6 and rpcb register it. */ if (tcpflag && ip6flag) { rpcbreg = 0; for (i = 0; i < bindhostc; i++) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) { rpcbreg = 1; rpcbregcnt++; if ((tcp6sock = socket(ai_tcp6->ai_family, ai_tcp6->ai_socktype, ai_tcp6->ai_protocol)) < 0) { syslog(LOG_ERR, "can't create tcp6 socket"); nfsd_exit(1); } if (setsockopt(tcp6sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); if (setsockopt(tcp6sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof on) < 0) { syslog(LOG_ERR, "can't set v6-only binding for tcp6 " "socket: %m"); nfsd_exit(1); } if (bind(tcp6sock, ai_tcp6->ai_addr, ai_tcp6->ai_addrlen) < 0) { syslog(LOG_ERR, "can't bind tcp6 addr %s: %m", bindhost[i]); nfsd_exit(1); } if (listen(tcp6sock, 64) < 0) { syslog(LOG_ERR, "listen failed"); nfsd_exit(1); } freeaddrinfo(ai_tcp6); FD_SET(tcp6sock, &sockbits); FD_SET(tcp6sock, &v6bits); if (maxsock < tcp6sock) maxsock = tcp6sock; connect_type_cnt++; } } if (rpcbreg == 1) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6); if (ecode != 0) { syslog(LOG_ERR, "getaddrinfo tcp6: %s", gai_strerror(ecode)); nfsd_exit(1); } nconf_tcp6 = getnetconfigent("tcp6"); if (nconf_tcp6 == NULL) err(1, "getnetconfigent tcp6 failed"); nb_tcp6.buf = ai_tcp6->ai_addr; nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen; if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) || (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6))) err(1, "rpcb_set tcp6 failed"); freeaddrinfo(ai_tcp6); } } if (rpcbregcnt == 0) { syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m"); nfsd_exit(1); } if (tcpflag && connect_type_cnt == 0) { syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m"); nfsd_exit(1); } setproctitle("master"); /* * We always want a master to have a clean way to to shut nfsd down * (with unregistration): if the master is killed, it unregisters and * kills all children. If we run for UDP only (and so do not have to * loop waiting waiting for accept), we instead make the parent * a "server" too. start_server will not return. */ if (!tcpflag) start_server(1); /* * Loop forever accepting connections and passing the sockets * into the kernel for the mounts. */ for (;;) { ready = sockbits; if (connect_type_cnt > 1) { if (select(maxsock + 1, &ready, NULL, NULL, NULL) < 1) { syslog(LOG_ERR, "select failed: %m"); if (errno == EINTR) continue; nfsd_exit(1); } } for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) { if (FD_ISSET(tcpsock, &ready)) { if (FD_ISSET(tcpsock, &v4bits)) { len = sizeof(inetpeer); if ((msgsock = accept(tcpsock, (struct sockaddr *)&inetpeer, &len)) < 0) { syslog(LOG_ERR, "accept failed: %m"); if (errno == ECONNABORTED || errno == EINTR) continue; nfsd_exit(1); } memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero)); if (setsockopt(msgsock, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m"); nfsdargs.sock = msgsock; nfsdargs.name = (caddr_t)&inetpeer; nfsdargs.namelen = len; nfssvc(NFSSVC_ADDSOCK, &nfsdargs); close(msgsock); } else if (FD_ISSET(tcpsock, &v6bits)) { len = sizeof(inet6peer); if ((msgsock = accept(tcpsock, (struct sockaddr *)&inet6peer, &len)) < 0) { syslog(LOG_ERR, "accept failed: %m"); if (errno == ECONNABORTED || errno == EINTR) continue; nfsd_exit(1); } if (setsockopt(msgsock, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) syslog(LOG_ERR, "setsockopt " "SO_KEEPALIVE: %m"); nfsdargs.sock = msgsock; nfsdargs.name = (caddr_t)&inet6peer; nfsdargs.namelen = len; nfssvc(NFSSVC_ADDSOCK, &nfsdargs); close(msgsock); } } } } }
int main(int argc, char *argv[]) { struct vfsconf vfc; mntoptparse_t mp; struct stat st; char *name, *srv, *p; char *port, *asrv, *aport; char mntpath[MAXPATHLEN]; char pass[NAMELEN], akey[DESKEYLEN]; int mntflags, altflags, noauth, c; getmnt_silent = 0; mntflags = 0; altflags = 0; pass[0] = '\0'; port = "564"; asrv = NULL; aport = "567"; noauth = 0; while ((c=getopt(argc, argv, "ho:")) != -1) { switch(c) { case 'o': altflags = 0; mp = getmntopts(optarg, mopts, &mntflags, &altflags); if (mp == NULL) err(EX_USAGE, "getmntopts: %s", optarg); if (altflags & ALTF_UNAME) args.uname = egetmntoptstr(mp, "uname"); if (altflags & ALTF_ANAME) args.aname = egetmntoptstr(mp, "aname"); if (altflags & ALTF_VOLUME) args.volume = egetmntoptstr(mp, "volume"); if (altflags & ALTF_PASS) { p = egetmntoptstr(mp, "pass"); strlcpy(pass, p, NAMELEN); } if (altflags & ALTF_PORT) port = egetmntoptstr(mp, "port"); if (altflags & ALTF_ASRV) asrv = egetmntoptstr(mp, "asrv"); if (altflags & ALTF_APORT) aport = egetmntoptstr(mp, "aport"); if (altflags & ALTF_NOAUTH) noauth = 1; /* flags */ if (altflags & ALTF_CHATTY9P) args.flags |= FLAG_CHATTY9P; if (altflags & ALTF_DSSTORE) args.flags &= ~FLAG_DSSTORE; if (altflags & ALTF_DOTU) args.flags |= FLAG_DOTU; freemntopts(mp); break; default: Usage: fprintf(stderr, "Usage: mount_%s [-o options] srv node\n", VFS9PNAME); exit(EX_USAGE); } } argc -= optind; argv += optind; if (argc != 2) goto Usage; srv = *argv++; name = *argv; // check path if (!realpath(name, mntpath) || stat(mntpath, &st)<0) err(EX_USAGE, "%s", mntpath); if (!S_ISDIR(st.st_mode)) { errno = ENOTDIR; err(EX_USAGE, "%s", mntpath); } if (*srv == '/') noauth++; getaddr(&args.addr, &args.addrlen, srv, port); if (!noauth) { if (asrv == NULL) asrv = srv; getaddr(&args.authaddr, &args.authaddrlen, asrv, aport); if (*pass == '\0') { if (!readpassphrase("Password: "******"USER"); if (!args.uname) args.uname = "none"; args.spec = srv; if (getvfsbyname(VFS9PNAME, &vfc) < 0) { if (load9p() < 0) err(1, NULL); if (getvfsbyname(VFS9PNAME, &vfc) < 0) errx(EX_UNAVAILABLE, "%s filesystem is not available", VFS9PNAME); } if (mount(vfc.vfc_name, mntpath, mntflags, &args) < 0) err(1, "mount %s %s", srv, mntpath); return 0; }