(no commit message)
[vsys-scripts.git] / fusemount.c
1 /* Adaptation of Jeremy Stribling's version of the script to work with Vsys */
2
3 #include <assert.h>
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <sys/mount.h>
9 #include <sys/socket.h>
10 #include <sys/un.h>
11 #include "fuse.h"
12
13 void remove_string( char *data, char *string ) {
14   char *pos = strstr( data, string );
15   if( pos != NULL ) {
16     char *comma = strchr( pos, ',' );
17     if( comma == NULL ) {
18       char *endpos = pos - 1;
19       if( endpos < data ) {
20         endpos = data;
21       }
22       endpos[0] = '\0';
23     } else {
24       char tmp[200];
25       strcpy( tmp, comma+1 );
26       strcpy( pos, tmp );
27     }
28   }
29 }
30
31 int do_mount( int control_channel ) {
32   char buf[1024];
33   int n = read( control_channel, buf, 1024 );
34   assert( n != 1024 );
35   char source[200];
36   char target[200];
37   char fstype[200];
38   unsigned long mountflags;
39   char data[200];
40   
41   int r = sscanf( buf, "%s\n%s\n%s\n%ld\n%s\n", source, target, fstype, 
42                   &mountflags, data );
43
44   assert( r == 5 ); // shouldn't be an assert
45
46   int s = mount( source, target, fstype, mountflags, data );
47
48   // TODO: should probably make sure this is for a fuse filesystem type . . .
49   int fd = 0;
50   if( s != 0 && errno == EINVAL ) {
51     // replace fd with a new one
52     remove_string( data, "fd" );
53
54     char *dev;
55     fd = open_fuse_device(&dev);
56     char *end = data+strlen(data);
57     if( strlen(data) != 0 ) {
58       sprintf( end, "," );
59       end = end + 1;
60     }
61     sprintf( end, "fd=%d", fd );
62
63     s = mount( source, target, fstype, mountflags, data );
64
65   }
66
67   char outbuf[10];
68   if( s < 0 ) {
69     sprintf( outbuf, "%08x\n", errno );
70   } else {
71     sprintf( outbuf, "%08x\n", fd );
72   }
73   write( control_channel, outbuf, strlen(outbuf) );
74
75   if( fd != 0 ) {
76
77     // now we have to sendmsg it back
78     // send the fd
79     int r = send_fd(control_channel, fd);
80
81     // wait for the close
82     if( r == 0 ) {
83       int x = read(control_channel, outbuf, 1 );
84       assert( x <= 0 );
85     }
86
87     close(fd);
88
89   }
90
91 }
92
93 int do_umount( int control_channel, int num ) {
94
95   if( num > 30 ) {
96     return -1;
97   }
98     
99   char *argbuf = (char *) malloc(sizeof(char)*(1024*num+1));
100   const char *args[num+1];
101   int args_index = 0;
102
103   // read all of the arguments
104   int last_o = 0;
105   do {
106
107     int n = read( control_channel, argbuf, 1024*num+1 );
108     assert( n < 1024*num+1 ); // no assert here
109     int num_left = n;
110     while( num_left > 0 ) {
111       char arg[1024];
112       if( sscanf( argbuf, "%s\n", arg ) != 1 ) {
113         break;
114       }
115       int len = strlen(arg);
116       char *a = malloc( sizeof(char)*(strlen(arg)+1) );
117       strcpy( a, arg );
118       if( strcmp( a, "-o" ) == 0 ) {
119         last_o = 1;
120       }
121       args[args_index] = a;
122       num_left -= (len+1);
123       argbuf += (len+1);
124       args_index++;
125     }
126
127   } while( args_index < num );
128
129   args[num] = NULL;
130
131   // The last argument is the mountpoint, that's really all we care about
132   printf( "umounting %s\n", args[num-1] );
133   int r = fuse_mnt_umount("reroutemount_server", args[num-1], 0 );
134
135   // write the status (probably not necessary)
136   char outbuf[10];
137   if( r < 0 ) {
138     sprintf( outbuf, "%d\n", errno );
139   } else {
140     sprintf( outbuf, "%d\n", 0 );
141   }
142   write( control_channel, outbuf, strlen(outbuf) );
143
144 }
145
146 int main( int argc, char **argv ) {
147     int control_channel;
148     if (argc < 3) {
149         printf("This script is invoked by vsys\n");
150         exit(1);
151     }
152
153     sscanf(argv[2],"%d",&control_channel);
154     
155     // read the length
156     char buf[1024];
157     int n = read( control_channel, buf, 9 );
158     buf[n] = '\0';
159     if( n != 9 ) {
160       close(control_channel);
161       continue;
162     }
163
164     int num;
165     if( sscanf( buf, "%08x\n", &num ) != 1 ) {
166       close(control_channel);
167       continue;
168     }
169
170     if( num == 0 ) {
171       do_mount( control_channel );
172     } else {
173       do_umount( control_channel, num );
174     }
175     close(control_channel);
176
177   }
178
179   close(fd);
180   unlink(socket_name);
181
182 }