Module Name: src Committed By: manu Date: Fri Aug 27 09:58:17 UTC 2010
Modified Files: src/lib/libperfuse: ops.c perfuse.c perfuse_if.h perfuse_priv.h src/usr.sbin/perfused: msg.c perfused.8 perfused.c perfused.h Log Message: - if perfused is not already started (cannot connect to /dev/fuse), FUSE filesystems will attempt to start it on their own, and will communicate using a socketpair - do not advertise NULL file handle as being valid when sending themback to the FUSE filesystem. - unmount if we cannot talk to the FUSE process anymore - set calling process gid properly - debug message cleanup To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/lib/libperfuse/ops.c \ src/lib/libperfuse/perfuse_if.h src/lib/libperfuse/perfuse_priv.h cvs rdiff -u -r1.1 -r1.2 src/lib/libperfuse/perfuse.c cvs rdiff -u -r1.1 -r1.2 src/usr.sbin/perfused/msg.c \ src/usr.sbin/perfused/perfused.h cvs rdiff -u -r1.2 -r1.3 src/usr.sbin/perfused/perfused.8 \ src/usr.sbin/perfused/perfused.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libperfuse/ops.c diff -u src/lib/libperfuse/ops.c:1.2 src/lib/libperfuse/ops.c:1.3 --- src/lib/libperfuse/ops.c:1.2 Thu Aug 26 13:29:01 2010 +++ src/lib/libperfuse/ops.c Fri Aug 27 09:58:17 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: ops.c,v 1.2 2010/08/26 13:29:01 manu Exp $ */ +/* $NetBSD: ops.c,v 1.3 2010/08/27 09:58:17 manu Exp $ */ /*- * Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved. @@ -667,7 +667,7 @@ svfsb->f_fsidx.__fsid_val[1] = 0; svfsb->f_fsid = ps->ps_fsid; svfsb->f_namemax = MAXPATHLEN; /* XXX */ - svfsb->f_owner = ps->ps_uid; + svfsb->f_owner = ps->ps_owner_uid; (void)strlcpy(svfsb->f_mntonname, ps->ps_target, _VFS_NAMELEN); @@ -1206,7 +1206,8 @@ if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_OPEN) { fh = perfuse_get_fh(opc); fsi->fh = fh; - fsi->valid |= FUSE_FATTR_FH; + if (fh != FUSE_UNKNOWN_FH) + fsi->valid |= FUSE_FATTR_FH; } if (vap->va_size != (u_quad_t)PUFFS_VNOVAL) { Index: src/lib/libperfuse/perfuse_if.h diff -u src/lib/libperfuse/perfuse_if.h:1.2 src/lib/libperfuse/perfuse_if.h:1.3 --- src/lib/libperfuse/perfuse_if.h:1.2 Thu Aug 26 13:29:01 2010 +++ src/lib/libperfuse/perfuse_if.h Fri Aug 27 09:58:17 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: perfuse_if.h,v 1.2 2010/08/26 13:29:01 manu Exp $ */ +/* $NetBSD: perfuse_if.h,v 1.3 2010/08/27 09:58:17 manu Exp $ */ /*- * Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved. @@ -29,6 +29,7 @@ #define _REFUSE_PERFUSE_H #define _PATH_FUSE "/dev/fuse" +#define _PATH_PERFUSED "/usr/sbin/perfused" #define FUSE_COMMFD_ENV "_FUSE_COMMFD" #define PERFUSE_MOUNT_MAGIC "noFuseRq" #define PERFUSE_UNKNOWN_INO 0xffffffff @@ -201,5 +202,6 @@ const char *perfuse_opname(int); void perfuse_fs_init(struct puffs_usermount *); int perfuse_mainloop(struct puffs_usermount *); +int perfuse_unmount(struct puffs_usermount *); #endif /* _REFUSE_PERFUSE_H */ Index: src/lib/libperfuse/perfuse_priv.h diff -u src/lib/libperfuse/perfuse_priv.h:1.2 src/lib/libperfuse/perfuse_priv.h:1.3 --- src/lib/libperfuse/perfuse_priv.h:1.2 Thu Aug 26 13:29:01 2010 +++ src/lib/libperfuse/perfuse_priv.h Fri Aug 27 09:58:17 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: perfuse_priv.h,v 1.2 2010/08/26 13:29:01 manu Exp $ */ +/* $NetBSD: perfuse_priv.h,v 1.3 2010/08/27 09:58:17 manu Exp $ */ /*- * Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved. @@ -41,9 +41,7 @@ void *ps_private; /* Private field for libperfuse user */ struct puffs_usermount *ps_pu; struct puffs_node *ps_root; - uid_t ps_uid; - gid_t ps_gid; - pid_t ps_pid; + uid_t ps_owner_uid; int ps_flags; #define PS_NO_ACCESS 0x0001 /* access is unimplemented; */ #define PS_NO_FSYNC 0x0002 /* fsync is unimplemented */ Index: src/lib/libperfuse/perfuse.c diff -u src/lib/libperfuse/perfuse.c:1.1 src/lib/libperfuse/perfuse.c:1.2 --- src/lib/libperfuse/perfuse.c:1.1 Wed Aug 25 07:16:00 2010 +++ src/lib/libperfuse/perfuse.c Fri Aug 27 09:58:17 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: perfuse.c,v 1.1 2010/08/25 07:16:00 manu Exp $ */ +/* $NetBSD: perfuse.c,v 1.2 2010/08/27 09:58:17 manu Exp $ */ /*- * Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved. @@ -101,16 +101,21 @@ int flags; mode_t mode; { - int s; + int sv[2]; struct sockaddr_un sun; struct sockaddr *sa; + char progname[] = _PATH_PERFUSED; + char minus_i[] = "-i"; + char fdstr[16]; + char *const argv[] = { progname, minus_i, fdstr, NULL}; + char *const envp[] = { NULL }; if (strcmp(path, _PATH_FUSE) != 0) return open(path, flags, mode); - if ((s = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1) { + if ((sv[0] = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1) { #ifdef PERFUSE_DEBUG - printf("%s:%d socket failed: %s", + printf("%s:%d socket failed: %s\n", __func__, __LINE__, strerror(errno)); #endif return -1; @@ -121,16 +126,49 @@ sun.sun_family = AF_LOCAL; (void)strcpy(sun.sun_path, path); - if (connect(s, sa, (socklen_t)sun.sun_len) == -1) { + if (connect(sv[0], sa, (socklen_t)sun.sun_len) == 0) + return sv[0]; + + + /* + * Attempt to run perfused on our own + * if it does not run yet; In that case + * we will talk using a socketpair + * instead of /dev/fuse. + */ + if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sv) != 0) { #ifdef PERFUSE_DEBUG - printf("%s:%d connect failed: %s", + printf("%s:%d: socketpair failed: %s\n", __func__, __LINE__, strerror(errno)); #endif - close(s); return -1; } - return s; + (void)sprintf(fdstr, "%d", sv[1]); + + switch(fork()) { + case -1: +#ifdef PERFUSE_DEBUG + printf("%s:%d: fork failed: %s\n", + __func__, __LINE__, strerror(errno)); +#endif + return -1; + /* NOTREACHED */ + break; + case 0: + (void)execve(argv[0], argv, envp); +#ifdef PERFUSE_DEBUG + printf("%s:%d: execve failed: %s\n", + __func__, __LINE__, strerror(errno)); +#endif + return -1; + /* NOTREACHED */ + break; + default: + break; + } + + return sv[0]; } @@ -188,7 +226,7 @@ if (write(s, &pmo, sizeof(pmo)) != sizeof(pmo)) { #ifdef PERFUSE_DEBUG - printf("%s:%d short write", __func__, __LINE__); + printf("%s:%d short write\n", __func__, __LINE__); #endif return -1; } @@ -197,7 +235,7 @@ len = pmo.pmo_source_len; if (write(s, source, len) != (ssize_t)len) { #ifdef PERFUSE_DEBUG - printf("%s:%d short write", __func__, __LINE__); + printf("%s:%d short write\n", __func__, __LINE__); #endif return -1; } @@ -207,7 +245,7 @@ len = pmo.pmo_target_len; if (write(s, target, len) != (ssize_t)len) { #ifdef PERFUSE_DEBUG - printf("%s:%d short write", __func__, __LINE__); + printf("%s:%d short write\n", __func__, __LINE__); #endif return -1; } @@ -217,7 +255,7 @@ len = pmo.pmo_filesystemtype_len; if (write(s, filesystemtype, len) != (ssize_t)len) { #ifdef PERFUSE_DEBUG - printf("%s:%d short write", __func__, __LINE__); + printf("%s:%d short write\n", __func__, __LINE__); #endif return -1; } @@ -227,7 +265,7 @@ len = pmo.pmo_data_len; if (write(s, data, len) != (ssize_t)len) { #ifdef PERFUSE_DEBUG - printf("%s:%d short write", __func__, __LINE__); + printf("%s:%d short write\n", __func__, __LINE__); #endif return -1; } @@ -262,7 +300,7 @@ struct puffs_pathobj *po_root; ps = init_state(); - ps->ps_uid = pmi->pmi_uid; + ps->ps_owner_uid = pmi->pmi_uid; if (pmi->pmi_source) ps->ps_source = strdup(pmi->pmi_source); @@ -274,7 +312,7 @@ /* * Some options are forbidden for non root users */ - if (ps->ps_uid != 0) + if (ps->ps_owner_uid != 0) ps->ps_mountflags |= MNT_NOSUID|MNT_NODEV; PUFFSOP_INIT(pops); @@ -414,3 +452,14 @@ { return PERFUSE_NODE_DATA(opc)->pnd_ino; } + +int +perfuse_unmount(pu) + struct puffs_usermount *pu; +{ + struct perfuse_state *ps; + + ps = puffs_getspecific(pu); + + return unmount(ps->ps_target, MNT_FORCE); +} Index: src/usr.sbin/perfused/msg.c diff -u src/usr.sbin/perfused/msg.c:1.1 src/usr.sbin/perfused/msg.c:1.2 --- src/usr.sbin/perfused/msg.c:1.1 Wed Aug 25 07:18:01 2010 +++ src/usr.sbin/perfused/msg.c Fri Aug 27 09:58:17 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: msg.c,v 1.1 2010/08/25 07:18:01 manu Exp $ */ +/* $NetBSD: msg.c,v 1.2 2010/08/27 09:58:17 manu Exp $ */ /*- * Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved. @@ -137,7 +137,7 @@ fih->pid = 0; if (cred != NULL) { (void)puffs_cred_getuid(cred, &fih->uid); - (void)puffs_cred_getuid(cred, &fih->uid); + (void)puffs_cred_getgid(cred, &fih->gid); } if ((pcc = puffs_cc_getcc(pu)) != NULL) (void)puffs_cc_getcaller(pcc, (pid_t *)&fih->pid, NULL); @@ -597,3 +597,31 @@ return; } +void +perfuse_fdnotify(pu, fd, what) + struct puffs_usermount *pu; + int fd; + int what; +{ + if (fd != (int)perfuse_getspecific(pu)) + DERRX(EX_SOFTWARE, "%s: unexpected notification for fd = %d", + __func__, fd); + + if ((what != PUFFS_FBIO_READ) && (what != PUFFS_FBIO_WRITE)) + DERRX(EX_SOFTWARE, "%s: unexpected notification what = 0x%x", + __func__, what); + + if (perfuse_unmount(pu) != 0) + DWARN("unmount() failed"); + + if (shutdown(fd, SHUT_RDWR) != 0) + DWARN("shutdown() failed"); + + if (perfuse_diagflags & PDF_MISC) + DPRINTF("Exit"); + + exit(0); + + /* NOTREACHED */ + return; +} Index: src/usr.sbin/perfused/perfused.h diff -u src/usr.sbin/perfused/perfused.h:1.1 src/usr.sbin/perfused/perfused.h:1.2 --- src/usr.sbin/perfused/perfused.h:1.1 Wed Aug 25 07:18:01 2010 +++ src/usr.sbin/perfused/perfused.h Fri Aug 27 09:58:17 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: perfused.h,v 1.1 2010/08/25 07:18:01 manu Exp $ */ +/* $NetBSD: perfused.h,v 1.2 2010/08/27 09:58:17 manu Exp $ */ /*- * Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved. @@ -52,6 +52,7 @@ int perfuse_cmpframe(struct puffs_usermount *, struct puffs_framebuf *, struct puffs_framebuf *, int *); void perfuse_gotframe(struct puffs_usermount *, struct puffs_framebuf *); +void perfuse_fdnotify(struct puffs_usermount *, int, int); struct fuse_out_header *perfuse_get_outhdr(perfuse_msg_t *); struct fuse_in_header *perfuse_get_inhdr(perfuse_msg_t *); Index: src/usr.sbin/perfused/perfused.8 diff -u src/usr.sbin/perfused/perfused.8:1.2 src/usr.sbin/perfused/perfused.8:1.3 --- src/usr.sbin/perfused/perfused.8:1.2 Thu Aug 26 13:29:02 2010 +++ src/usr.sbin/perfused/perfused.8 Fri Aug 27 09:58:17 2010 @@ -1,4 +1,4 @@ -.\" $NetBSD: perfused.8,v 1.2 2010/08/26 13:29:02 manu Exp $ +.\" $NetBSD: perfused.8,v 1.3 2010/08/27 09:58:17 manu Exp $ .\" .\" Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved. .\" @@ -34,6 +34,7 @@ .Op Fl f .Op Fl d Ar types .Op Fl s +.Op Fl i fd .Sh DESCRIPTION .Nm is a userland daemon mplementing the FUSE kernel level API. It creates a @@ -106,6 +107,15 @@ .El .It Fl s Enable debug output only when receiving SIGINFO. +.It Fl i Ar fd +Do not open +.Pa /dev/fuse +but use the socket available from file descriptor +.Ar fd . +This is used when +.Nm +is started from +.Xr libperfuse 3 . .El .Sh ERRORS The program logs to the syslog daemon as facility Index: src/usr.sbin/perfused/perfused.c diff -u src/usr.sbin/perfused/perfused.c:1.2 src/usr.sbin/perfused/perfused.c:1.3 --- src/usr.sbin/perfused/perfused.c:1.2 Thu Aug 26 13:29:02 2010 +++ src/usr.sbin/perfused/perfused.c Fri Aug 27 09:58:17 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: perfused.c,v 1.2 2010/08/26 13:29:02 manu Exp $ */ +/* $NetBSD: perfused.c,v 1.3 2010/08/27 09:58:17 manu Exp $ */ /*- * Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved. @@ -52,10 +52,10 @@ static int getpeerid(int, pid_t *, uid_t *, gid_t *); static int access_mount(const char *, uid_t, int); -static int accept_new_mount(int); +static void new_mount(int); static int parse_debug(char *); static void siginfo_handler(int); -static void parse_options(int, char **); +static int parse_options(int, char **); static void get_mount_info(int, struct perfuse_mount_info *); int main(int, char **); @@ -171,32 +171,17 @@ return; } -static int -accept_new_mount(s) - int s; +static void +new_mount(fd) + int fd; { struct puffs_usermount *pu; - struct sockaddr_storage ss; - socklen_t ss_len; - struct sockaddr *sa; struct perfuse_mount_info pmi; struct perfuse_callbacks pc; int ro_flag; pid_t pid; - int fd; int flags; -#ifdef PERFUSE_DEBUG - DPRINTF("waiting connexion\n"); -#endif - sa = (struct sockaddr *)(void *)&ss; - ss_len = sizeof(ss); - if ((fd = accept(s, sa, &ss_len)) == -1) - DERR(EX_OSERR, "accept failed"); - -#ifdef PERFUSE_DEBUG - DPRINTF("connexion accepted\n"); -#endif pid = (perfuse_diagflags & PDF_FOREGROUND) ? 0 : fork(); switch(pid) { @@ -206,7 +191,7 @@ case 0: break; default: - return fd; + return; /* NOTREACHED */ break; } @@ -245,7 +230,7 @@ pu = perfuse_init(&pc, &pmi); puffs_framev_init(pu, perfuse_readframe, perfuse_writeframe, - perfuse_cmpframe, perfuse_gotframe, NULL); + perfuse_cmpframe, perfuse_gotframe, perfuse_fdnotify); if (puffs_framev_addfd(pu, fd, PUFFS_FBIO_READ|PUFFS_FBIO_WRITE) == -1) DERR(EX_SOFTWARE, "puffs_framev_addfd failed"); @@ -269,7 +254,12 @@ /* * Hand over control to puffs main loop. */ - return perfuse_mainloop(pu); + (void)perfuse_mainloop(pu); + + DERRX(EX_SOFTWARE, "perfuse_mainloop exit"); + + /* NOTREACHED */ + return; } static int @@ -325,17 +315,18 @@ return; } -static void +static int parse_options(argc, argv) int argc; char **argv; { int ch; int foreground = 0; + int retval = -1; perfuse_diagflags = PDF_FOREGROUND | PDF_SYSLOG; - while ((ch = getopt(argc, argv, "d:fs")) != -1) { + while ((ch = getopt(argc, argv, "d:fsi:")) != -1) { switch (ch) { case 'd': perfuse_diagflags |= parse_debug(optarg); @@ -347,8 +338,12 @@ case 'f': foreground = 1; break; + case 'i': + retval = atoi(optarg); + foreground = 1; + break; default: - DERR(EX_USAGE, "%s [-d level] [-s] [-f]", argv[0]); + DERR(EX_USAGE, "%s [-d level] [-s] [-f] [-i fd]", argv[0]); break; } } @@ -356,7 +351,7 @@ if (!foreground) perfuse_diagflags &= ~PDF_FOREGROUND; - return; + return retval; } int @@ -366,7 +361,7 @@ { int s; - parse_options(argc, argv); + s = parse_options(argc, argv); if (perfuse_diagflags & PDF_SYSLOG) openlog("perfused", 0, LOG_DAEMON); @@ -375,10 +370,32 @@ if (daemon(0, 0) != 0) DERR(EX_OSERR, "daemon failed"); + if (s != -1) { + new_mount(s); + DERRX(EX_SOFTWARE, "new_mount exit while -i is used"); + } + s = perfuse_open_sock(); do { - (void)accept_new_mount(s); + struct sockaddr *sa; + struct sockaddr_storage ss; + socklen_t ss_len; + int fd; + +#ifdef PERFUSE_DEBUG + if (perfuse_diagflags & PDF_MISC) + DPRINTF("waiting connexion\n"); +#endif + sa = (struct sockaddr *)(void *)&ss; + ss_len = sizeof(ss); + if ((fd = accept(s, sa, &ss_len)) == -1) + DERR(EX_OSERR, "accept failed"); +#ifdef PERFUSE_DEBUG + if (perfuse_diagflags & PDF_MISC) + DPRINTF("connexion accepted\n"); +#endif + new_mount(fd); } while (1 /* CONSTCOND */); /* NOTREACHED */