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