3 * Copyright (C) 2002 Florin Malita <mali@go.ro>
5 * This file is part of LUFS, a free userspace filesystem implementation.
6 * See http://lufs.sourceforge.net/ for updates.
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.
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.
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
34 #include <sys/types.h>
37 #include <sys/socket.h>
39 #include <sys/ioctl.h>
41 #include <sys/mount.h>
44 #include <lufs/proto.h>
49 #include "filesystem.h"
52 #define CONFIG_FILE1 "/etc/lufsd.conf"
53 #define CONFIG_FILE2 "~/.lufs/lufsd.conf"
55 const char *exec_paths[]={
56 "/usr/local/bin/lufsmnt",
63 tempsock(char *base, char *name){
64 struct sockaddr_un addr;
68 if((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0){
69 ERROR("socket error: %s", strerror(errno));
73 addr.sun_family = AF_UNIX;
77 sprintf(addr.sun_path, "%s%lu", base, rnd);
79 TRACE("trying address %s", addr.sun_path);
81 res = bind(sock, (struct sockaddr*)&addr, sizeof(addr));
82 }while((res < 0) && (errno == EADDRINUSE));
85 ERROR("bind error: %s", strerror(errno));
89 if((res = listen(sock, 10)) < 0){
90 ERROR("listen error: %s", strerror(errno));
95 strcpy(name, addr.sun_path);
100 /* From captive/src/libcaptive/sandbox/split.c/captive_sandbox_fd_closeup(): */
101 #define g_return_if_fail(cond) do { if (!(cond)) { ERROR("FAIL: " #cond ); return; } } while (0)
102 #define g_assert(cond) do { if (!(cond)) ERROR("FAIL: " #cond ); } while (0)
103 static void fd_closeup(int fd_first_to_delete,int exception)
108 struct dirent *dirent;
110 dir=opendir("/proc/self/fd/");
111 g_return_if_fail(dir!=NULL);
113 g_return_if_fail(dir_fd!=-1);
115 while (errno=0,(dirent=readdir(dir))) {
120 || !strcmp(dirent->d_name,".")
121 || !strcmp(dirent->d_name,".."))
123 dirent_fd=strtol(dirent->d_name,&endptr,10 /* base */);
124 g_assert(dirent_fd>=0 && (!endptr || !*endptr));
125 if (dirent_fd<fd_first_to_delete || dirent_fd==dir_fd || dirent_fd==exception)
128 errint=close(dirent_fd);
131 errint=close(dirent_fd);
132 g_assert(errint==-1); g_assert(errno==EBADF);
134 g_return_if_fail(errno==0); /* check for EOF */
136 errint=closedir(dir);
137 g_return_if_fail(errint==0);
139 close(dir_fd); g_assert(errno==EBADF); /* just a bit of paranoia; it should be already closed by closedir() */
141 #undef g_return_if_fail
145 main(int argc, char **argv){
146 char *service, *mountpoint, *odata;
147 struct list_head cfg;
149 char tmp[256], *nopts;
150 int ssock, pid, mpid, res;
152 INIT_LIST_HEAD(&cfg);
158 /* Close all fds as we will later fork(2) and at least usermount(8) waits
159 * for child finish by select(2) on fd left open for mount(8). We can be
160 * called as external program from mount(8). Close even STD* fds as
161 * usermount(8) uses STDERR for its pipe watching.
163 /* FIXME: 'quiet' option has no meaning now. */
166 if((argc < 5) || (strcmp(argv[3], "-o")) ){
167 ERROR("Usage: %s none <mount-point> -o [options, ...]", argv[0]);
172 TRACE("more options than expected...");
176 mountpoint = argv[2];
180 nopts = malloc(strlen(odata) + 100);
182 ERROR("out of memory!");
186 strcpy(nopts, odata);
188 if(lu_opt_parse(&cfg, "MOUNT", odata) < 0){
189 ERROR("could not parse options!");
193 if((lu_opt_loadcfg(&cfg, CONFIG_FILE1) < 0))
194 lu_opt_loadcfg(&cfg, CONFIG_FILE2);
196 if(!(ctl = lu_fsctl_create(&cfg))){
197 WARN("could not create fs_ctl!");
201 if(!lu_fsctl_mount(ctl)){
202 ERROR("could not mount filesystem!");
203 lu_fsctl_destroy(ctl);
207 if((ssock = tempsock("/tmp/lufsd", tmp)) < 0)
210 TRACE("starting filesystem master at %s", tmp);
212 chmod(tmp, S_IRWXU | S_IRWXG | S_IRWXO);
214 /* detach & launch FSCtl */
216 if((pid = fork()) < 0){
217 ERROR("fork failed!");
224 quiet = lu_opt_getchar(&cfg, "MOUNT", "quiet");
226 if((fd = open("/dev/tty", O_RDWR, 0)) < 0){
227 WARN("couldn't open tty, assuming still ok...");
230 ioctl(fd, TIOCNOTTY, 0);
237 /* FIXME: 'quiet' option has no meaning now; check fd_closeup(). */
241 TRACE("going dumb...");
242 if((stdfd = open("/dev/null", O_RDWR, 0)) < 0){
243 WARN("couldn't open /dev/null!");
252 /* launching FSCtl... */
253 lu_fsctl_run(ctl, ssock, tmp);
258 sprintf(nopts, "%s,server_socket=%s,server_pid=%d", nopts, tmp, pid);
260 /* execute lufsmnt and wait for it. */
262 if((mpid = fork()) < 0){
263 ERROR("fork failed!");
272 args[1] = mountpoint;
276 TRACE("executing %s %s %s", args[0], args[1], args[2]);
277 execvp("lufsmnt", args);
278 WARN("execvp of lufsmnt failed: %s", strerror(errno));
279 WARN("you don't seem to have lufsmnt in your path. trying regular locations...");
281 for(p = exec_paths[0]; p; p++){
282 TRACE("trying %s %s %s", p, args[1], args[2]);
286 ERROR("could not launch lufsmnt!\n");
290 if(waitpid(mpid, &res, 0) < 0){
291 ERROR("waitpid failed!");
296 if(WIFEXITED(res) && WEXITSTATUS(res) != 0){
301 TRACE("mount succeded");