http://prdownloads.sourceforge.net/lufs/lufs-0.9.6.tar.gz?download
[lufs.git] / lufsd / daemon.c
1 /*
2  * daemon.c
3  * Copyright (C) 2002 Florin Malita <mali@go.ro>
4  *
5  * This file is part of LUFS, a free userspace filesystem implementation.
6  * See http://lufs.sourceforge.net/ for updates.
7  *
8  * LUFS is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * LUFS is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <syslog.h>
26 #include <unistd.h>
27 #include <signal.h>
28 #include <fcntl.h>
29 #include <pwd.h>
30 #include <errno.h>
31 #include <time.h>
32
33 #include <sys/types.h>
34 #include <sys/wait.h>
35 #include <sys/stat.h>
36 #include <sys/socket.h>
37 #include <sys/un.h>
38 #include <sys/ioctl.h>
39 #include <sys/time.h>
40 #include <sys/mount.h>
41
42
43 #include <lufs/proto.h>
44 #include <lufs/fs.h>
45
46 #include "list.h"
47 #include "message.h"
48 #include "filesystem.h"
49 #include "fsctl.h"
50
51 #define CONFIG_FILE1    "/etc/lufsd.conf"
52 #define CONFIG_FILE2    "~/.lufs/lufsd.conf"
53
54 const char *exec_paths[]={
55     "/usr/local/bin/lufsmnt",
56     "/usr/bin/lufsmnt",
57     "/sbin/lufsmnt",
58     NULL
59 };
60
61 int
62 tempsock(char *base, char *name){
63     struct sockaddr_un addr;
64     unsigned long rnd;
65     int sock, res;
66     
67     if((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0){
68         ERROR("socket error: %s", strerror(errno));
69         return sock;
70     }
71
72     addr.sun_family = AF_UNIX;
73
74     do{
75         rnd = random();
76         sprintf(addr.sun_path, "%s%lu", base, rnd);
77
78         TRACE("trying address %s", addr.sun_path);
79
80         res = bind(sock, (struct sockaddr*)&addr, sizeof(addr));
81     }while((res < 0) && (errno == EADDRINUSE));
82
83     if(res < 0){
84         ERROR("bind error: %s", strerror(errno));
85         return res;
86     }
87     
88     if((res = listen(sock, 10)) < 0){
89         ERROR("listen error: %s", strerror(errno));
90         return res;
91     }
92     
93     if(name)
94         strcpy(name, addr.sun_path);
95
96     return sock;
97 }
98
99 int
100 main(int argc, char **argv){
101     char *service, *mountpoint, *odata;
102     struct list_head cfg;
103     struct fs_ctl *ctl;
104     char tmp[256], *nopts;
105     int ssock, pid, mpid, res;
106
107     INIT_LIST_HEAD(&cfg);
108
109     srandom(time(NULL));
110
111     if((argc < 5) || (strcmp(argv[3], "-o")) ){
112         ERROR("Usage: %s none <mount-point> -o [options, ...]", argv[0]);
113         exit(1);
114     }
115
116     if(argc > 5){
117         TRACE("more options than expected...");
118     }
119     
120     service = argv[1];
121     mountpoint = argv[2];
122     odata = argv[4];
123     
124
125     nopts = malloc(strlen(odata) + 100);
126     if(!nopts){
127         ERROR("out of memory!");
128         exit(1);
129     }
130
131     strcpy(nopts, odata);
132
133     if(lu_opt_parse(&cfg, "MOUNT", odata) < 0){
134         ERROR("could not parse options!");
135         exit(1);
136     }
137
138     if((lu_opt_loadcfg(&cfg, CONFIG_FILE1) < 0))
139         lu_opt_loadcfg(&cfg, CONFIG_FILE2);
140
141     if(!(ctl = lu_fsctl_create(&cfg))){
142         WARN("could not create fs_ctl!");
143         exit(1);
144     }
145
146     if(!lu_fsctl_mount(ctl)){
147         ERROR("could not mount filesystem!");
148         lu_fsctl_destroy(ctl);
149         exit(1);
150     }
151
152     if((ssock = tempsock("/tmp/lufsd", tmp)) < 0)
153         exit(1);
154
155     TRACE("starting filesystem master at %s", tmp);
156
157     chmod(tmp, S_IRWXU | S_IRWXG | S_IRWXO);
158
159     /* detach & launch FSCtl */
160
161     if((pid = fork()) < 0){
162         ERROR("fork failed!");
163         exit(1);
164     }else
165         if(pid == 0){
166             int fd;
167             const char *quiet;
168
169             quiet = lu_opt_getchar(&cfg, "MOUNT", "quiet");
170             
171             if((fd = open("/dev/tty", O_RDWR, 0)) < 0){
172                 WARN("couldn't open tty, assuming still ok...");
173                 fflush(stdout);
174             }else{
175                 ioctl(fd, TIOCNOTTY, 0);
176                 close(fd);
177                 setsid();
178             }
179
180             free(nopts);
181
182             if(quiet){
183                 int stdfd;
184
185                 TRACE("going dumb...");
186                 if((stdfd = open("/dev/null", O_RDWR, 0)) < 0){
187                     WARN("couldn't open /dev/null!");
188                 }else{
189                     dup2(stdfd, 0);
190                     dup2(stdfd, 1);
191                     dup2(stdfd, 2);
192                     close(stdfd);
193                 }
194             }
195
196             /* launching FSCtl... */
197             lu_fsctl_run(ctl, ssock, tmp);
198             exit(1);
199         }
200
201     
202     sprintf(nopts, "%s,server_socket=%s,server_pid=%d", nopts, tmp, pid);
203
204     /* execute lufsmnt and wait for it. */
205     
206     if((mpid = fork()) < 0){
207         ERROR("fork failed!");
208         kill(pid, SIGUSR1);
209         exit(1);
210     }else 
211         if(mpid == 0){
212             char *args[4];
213             const char *p;
214
215             args[0] = "lufsmnt";
216             args[1] = mountpoint;
217             args[2] = nopts;
218             args[3] = NULL;
219
220             TRACE("executing %s %s %s", args[0], args[1], args[2]);
221             execvp("lufsmnt", args);
222             WARN("execvp of lufsmnt failed: %s", strerror(errno));
223             WARN("you don't seem to have lufsmnt in your path. trying regular locations...");
224             
225             for(p = exec_paths[0]; p; p++){
226                 TRACE("trying %s %s %s", p, args[1], args[2]);
227                 execv(p, args);         
228             }
229
230             ERROR("could not launch lufsmnt!\n");
231             exit(1);
232         }
233
234     if(waitpid(mpid, &res, 0) < 0){
235         ERROR("waitpid failed!");
236         kill(pid, SIGUSR1);
237         exit(1);
238     }
239
240     if(WIFEXITED(res) && WEXITSTATUS(res) != 0){
241         kill(pid, SIGUSR1);
242         exit(1);
243     }
244
245     TRACE("mount succeded");
246
247     return 0;
248 }
249
250
251
252
253
254
255