Adding FUSE related vsys scripts
authorSapan Bhatia <sapanb@cs.princeton.edu>
Tue, 24 Mar 2009 20:32:54 +0000 (20:32 +0000)
committerSapan Bhatia <sapanb@cs.princeton.edu>
Tue, 24 Mar 2009 20:32:54 +0000 (20:32 +0000)
Makefile
fuse.h [new file with mode: 0644]
fusemount.c [new file with mode: 0644]

index 98afcd6..7d586f6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -12,5 +12,8 @@ fdpass.o: fdpass.c
 fd_bmsocket: fd_bmsocket.c fdpass.o
        gcc fd_bmsocket.c fdpass.o -o exec/fd_bmsocket
 
+fd_fusemount: fd_fusemount.c fdpass.o
+       gcc fd_fusemount.c fdpass.o -o exec/fd_fusemount
+
 clean: 
        rm -f exec/*
diff --git a/fuse.h b/fuse.h
new file mode 100644 (file)
index 0000000..2ade06c
--- /dev/null
+++ b/fuse.h
@@ -0,0 +1,8 @@
+#define FUSE_DEV_OLD "/proc/fs/fuse/dev"
+#define FUSE_DEV_NEW "/dev/fuse"
+
+int rrm_receive_fd(int fd);
+int rrm_send_fd(int sock_fd, int fd);
+int rrm_open_fuse_device(char **devp);
+int rrm_fuse_mnt_umount(const char *progname, const char *mnt, int lazy);
+
diff --git a/fusemount.c b/fusemount.c
new file mode 100644 (file)
index 0000000..eb870eb
--- /dev/null
@@ -0,0 +1,181 @@
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include "fuse.h"
+
+void remove_string( char *data, char *string ) {
+  char *pos = strstr( data, string );
+  if( pos != NULL ) {
+    char *comma = strchr( pos, ',' );
+    if( comma == NULL ) {
+      char *endpos = pos - 1;
+      if( endpos < data ) {
+       endpos = data;
+      }
+      endpos[0] = '\0';
+    } else {
+      char tmp[200];
+      strcpy( tmp, comma+1 );
+      strcpy( pos, tmp );
+    }
+  }
+}
+
+int do_mount( int control_channel ) {
+  char buf[1024];
+  int n = read( control_channel, buf, 1024 );
+  assert( n != 1024 );
+
+  char source[200];
+  char target[200];
+  char fstype[200];
+  unsigned long mountflags;
+  char data[200];
+  
+  int r = sscanf( buf, "%s\n%s\n%s\n%ld\n%s\n", source, target, fstype, 
+                 &mountflags, data );
+
+  assert( r == 5 ); // shouldn't be an assert
+
+  int s = mount( source, target, fstype, mountflags, data );
+
+  // TODO: should probably make sure this is for a fuse filesystem type . . .
+  int fd = 0;
+  if( s != 0 && errno == EINVAL ) {
+    // replace fd with a new one
+    remove_string( data, "fd" );
+
+    char *dev;
+    fd = open_fuse_device(&dev);
+    char *end = data+strlen(data);
+    if( strlen(data) != 0 ) {
+      sprintf( end, "," );
+      end = end + 1;
+    }
+    sprintf( end, "fd=%d", fd );
+
+    s = mount( source, target, fstype, mountflags, data );
+
+  }
+
+  char outbuf[10];
+  if( s < 0 ) {
+    sprintf( outbuf, "%08x\n", errno );
+  } else {
+    sprintf( outbuf, "%08x\n", fd );
+  }
+  write( control_channel, outbuf, strlen(outbuf) );
+
+  if( fd != 0 ) {
+
+    // now we have to sendmsg it back
+    // send the fd
+    int r = send_fd(control_channel, fd);
+
+    // wait for the close
+    if( r == 0 ) {
+      int x = read(control_channel, outbuf, 1 );
+      assert( x <= 0 );
+    }
+
+    close(fd);
+
+  }
+
+}
+
+int do_umount( int control_channel, int num ) {
+
+  if( num > 30 ) {
+    return -1;
+  }
+    
+  char *argbuf = (char *) malloc(sizeof(char)*(1024*num+1));
+  const char *args[num+1];
+  int args_index = 0;
+
+  // read all of the arguments
+  int last_o = 0;
+  do {
+
+    int n = read( control_channel, argbuf, 1024*num+1 );
+    assert( n < 1024*num+1 ); // no assert here
+    int num_left = n;
+    while( num_left > 0 ) {
+      char arg[1024];
+      if( sscanf( argbuf, "%s\n", arg ) != 1 ) {
+       break;
+      }
+      int len = strlen(arg);
+      char *a = malloc( sizeof(char)*(strlen(arg)+1) );
+      strcpy( a, arg );
+      if( strcmp( a, "-o" ) == 0 ) {
+       last_o = 1;
+      }
+      args[args_index] = a;
+      num_left -= (len+1);
+      argbuf += (len+1);
+      args_index++;
+    }
+
+  } while( args_index < num );
+
+  args[num] = NULL;
+
+  // The last argument is the mountpoint, that's really all we care about
+  printf( "umounting %s\n", args[num-1] );
+  int r = fuse_mnt_umount("reroutemount_server", args[num-1], 0 );
+
+  // write the status (probably not necessary)
+  char outbuf[10];
+  if( r < 0 ) {
+    sprintf( outbuf, "%d\n", errno );
+  } else {
+    sprintf( outbuf, "%d\n", 0 );
+  }
+  write( control_channel, outbuf, strlen(outbuf) );
+
+}
+
+int main( int argc, char **argv ) {
+    int control_channel;
+    if (argc < 3) {
+        printf("This script is invoked by vsys\n");
+        exit(1);
+    }
+
+    sscanf(argv[2],"%d",&control_channel);
+    
+    // read the length
+    char buf[1024];
+    int n = read( control_channel, buf, 9 );
+    buf[n] = '\0';
+    if( n != 9 ) {
+      close(control_channel);
+      continue;
+    }
+
+    int num;
+    if( sscanf( buf, "%08x\n", &num ) != 1 ) {
+      close(control_channel);
+      continue;
+    }
+
+    if( num == 0 ) {
+      do_mount( control_channel );
+    } else {
+      do_umount( control_channel, num );
+    }
+    close(control_channel);
+
+  }
+
+  close(fd);
+  unlink(socket_name);
+
+}