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
41 #include <sys/types.h>
43 #include <sys/socket.h>
49 #include <lufs/proto.h>
55 #include "filesystem.h"
58 char sock_name[MAX_LEN];
60 static int usr1Handler_hit=0;
64 TRACE("usr1Handler...");
70 TRACE("got a signal: %d", sig);
72 signal(sig, sig_handler);
76 thread_launcher(void *params){
77 struct thread_info *p = (struct thread_info*)params;
78 struct file_system *fs = p->fs;
82 TRACE("thread created");
85 handle_fs(fs, sock, ppid);
87 WARN("could not instantiate filesystem (out of mem?) !");
90 if(fs->fs_ops->umount){
91 TRACE("unmounting filesystem...");
92 fs->fs_ops->umount(fs->fs_context);
94 TRACE("freeing filesystem...");
95 fs->fs_ops->free(fs->fs_context);
100 TRACE("thread exiting...");
105 #define BUF_SIZE 1024
106 #define PASSWD "/etc/passwd"
107 #define GROUP "/etc/group"
110 load_credentials(struct fs_ctl *ctl, struct file_system *fs){
111 static char buf[BUF_SIZE];
112 char srch_str[MAX_LEN + 4];
114 int res, offset, chunk, readlen;
117 TRACE("loading remote credentials for %s", ctl->cred.user);
119 if((!ctl->fs_ops->open) || (!ctl->fs_ops->read) || (!ctl->fs_ops->release)){
120 WARN("unsupported operation");
124 ctl->cred.uid = ctl->cred.gid = -1;
126 if(ctl->fs_ops->open(fs->fs_context, PASSWD, O_RDONLY) < 0){
127 TRACE("could not open %s", PASSWD);
131 sprintf(srch_str, "\n%s:", ctl->cred.user);
132 chunk = strlen(srch_str) + 64;
133 readlen = BUF_SIZE - chunk - 1;
135 memset(buf, 32, chunk);
139 res = ctl->fs_ops->read(fs->fs_context, PASSWD, offset, readlen, (buf + chunk));
141 *(buf + chunk + res) = 0;
143 if((c = strstr(buf, srch_str))){
144 TRACE("username found!");
145 if(!(c = strchr(c + strlen(srch_str), ':'))){
146 TRACE("separator not found!");
148 if(sscanf(c , ":%li:%li:", &uid, &gid) != 2){
149 TRACE("uid/gid not found!");
151 TRACE("uid: %li, gid: %li", uid, gid);
161 memcpy(buf, buf + BUF_SIZE - chunk - 1, chunk);
164 }while(res == readlen);
166 ctl->fs_ops->release(fs->fs_context, PASSWD);
169 TRACE("read failed");
174 if(ctl->fs_ops->open(fs->fs_context, GROUP, O_RDONLY) < 0){
175 TRACE("could not open %s", GROUP);
179 sprintf(srch_str, ":%li:", (long)ctl->cred.gid);
180 chunk = strlen(srch_str) + 64;
181 readlen = BUF_SIZE - chunk - 1;
183 memset(buf, 32, chunk);
187 res = ctl->fs_ops->read(fs->fs_context, GROUP, offset, readlen, (buf + chunk));
189 *(buf + chunk + res) = 0;
191 if((c = strstr(buf, srch_str))){
192 TRACE("group found!");
193 if(!(c = (char*)memrchr(buf, '\n', (c - buf)))){
194 TRACE("separator not found!");
196 *(strchr(c, ':')) = 0;
197 if(strlen(c + 1) >= MAX_LEN){
198 TRACE("groupname too long");
200 strcpy(ctl->cred.group, c + 1);
201 TRACE("group: %s", ctl->cred.group);
207 memcpy(buf, buf + BUF_SIZE - chunk - 1, chunk);
210 }while(res == readlen);
212 ctl->fs_ops->release(fs->fs_context, GROUP);
215 TRACE("read failed");
223 static struct fs_operations*
224 get_filesystem(struct fs_ctl *ctl, char *fs){
225 struct fs_operations *fops;
229 if(!(buf = (char*)malloc(strlen(fs) + 32)))
232 sprintf(buf, "liblufs-%s.so", fs);
233 TRACE("trying to load %s", buf);
235 if(!(dlhandle = dlopen(buf, RTLD_LAZY))){
242 if(!(fops = (struct fs_operations*)malloc(sizeof(struct fs_operations))))
245 memset(fops, 0, sizeof(struct fs_operations));
247 sprintf(buf, "%s_init", fs);
248 if(!(fops->init = (void*(*)(struct list_head*, struct dir_cache*, struct credentials*, void**))dlsym(dlhandle, buf))){
253 sprintf(buf, "%s_free", fs);
254 if(!(fops->free = (void(*)(void*))dlsym(dlhandle, buf))){
259 sprintf(buf, "%s_mount", fs);
260 if(!(fops->mount = (int(*)(void*))dlsym(dlhandle, buf))){
265 sprintf(buf, "%s_umount", fs);
266 if(!(fops->umount = (void(*)(void*))dlsym(dlhandle, buf)))
269 sprintf(buf, "%s_readdir", fs);
270 if(!(fops->readdir = (int(*)(void*, char*, struct directory*))dlsym(dlhandle, buf)))
273 sprintf(buf, "%s_stat", fs);
274 if(!(fops->stat = (int(*)(void*, char*, struct lufs_fattr*))dlsym(dlhandle, buf)))
277 sprintf(buf, "%s_mkdir", fs);
278 if(!(fops->mkdir = (int(*)(void*, char*, int))dlsym(dlhandle, buf)))
281 sprintf(buf, "%s_rmdir", fs);
282 if(!(fops->rmdir = (int(*)(void*, char*))dlsym(dlhandle, buf)))
285 sprintf(buf, "%s_create", fs);
286 if(!(fops->create = (int(*)(void*, char*, int))dlsym(dlhandle, buf)))
289 sprintf(buf, "%s_unlink", fs);
290 if(!(fops->unlink = (int(*)(void*, char*))dlsym(dlhandle, buf)))
293 sprintf(buf, "%s_rename", fs);
294 if(!(fops->rename = (int(*)(void*, char*, char*))dlsym(dlhandle, buf)))
297 sprintf(buf, "%s_open", fs);
298 if(!(fops->open = (int(*)(void*, char*, unsigned))dlsym(dlhandle, buf)))
301 sprintf(buf, "%s_release", fs);
302 if(!(fops->release = (int(*)(void*, char*))dlsym(dlhandle, buf)))
305 sprintf(buf, "%s_read", fs);
306 if(!(fops->read = (int(*)(void*, char*, long long, unsigned long, char*))dlsym(dlhandle, buf)))
309 sprintf(buf, "%s_write", fs);
310 if(!(fops->write = (int(*)(void*, char*, long long, unsigned long, char*))dlsym(dlhandle, buf)))
313 sprintf(buf, "%s_readlink", fs);
314 if(!(fops->readlink = (int(*)(void*, char*, char*, int))dlsym(dlhandle, buf)))
317 sprintf(buf, "%s_link", fs);
318 if(!(fops->link = (int(*)(void*, char*, char*))dlsym(dlhandle, buf)))
321 sprintf(buf, "%s_symlink", fs);
322 if(!(fops->symlink = (int(*)(void*, char*, char*))dlsym(dlhandle, buf)))
325 sprintf(buf, "%s_setattr", fs);
326 if(!(fops->setattr = (int(*)(void*, char*, struct lufs_fattr*))dlsym(dlhandle, buf)))
329 TRACE("file system loaded");
331 ctl->dlhandle = dlhandle;
345 static struct file_system*
346 new_fsinstance(struct fs_ctl *ctl){
347 struct file_system *fs;
349 if(!(fs = (struct file_system*)malloc(sizeof(struct file_system))))
352 memset(fs, 0, sizeof(struct file_system));
354 fs->fs_ops = ctl->fs_ops;
355 fs->fs_credentials = &ctl->cred;
356 fs->fs_cache = ctl->cache;
357 fs->fs_config = ctl->cfg;
359 if(!(fs->fs_context = ctl->fs_ops->init(ctl->cfg, ctl->cache, fs->fs_credentials, &ctl->global_ctx))){
360 ERROR("could not initialize file system!");
369 lu_fsctl_mount(struct fs_ctl *ctl){
371 struct file_system *fs;
376 if(!(fs = new_fsinstance(ctl)))
379 res = ctl->fs_ops->mount(fs->fs_context);
382 ctl->fs_available = fs;
384 if(load_credentials(ctl, fs) < 0)
385 TRACE("could not load credentials.");
387 TRACE("credentials loaded.");
390 WARN("fs mount failed...");
399 lu_fsctl_run(struct fs_ctl *ctl, int ssock, char *sn){
401 struct sockaddr_un addr;
403 struct thread_info *info, *info_list=NULL;
404 struct sigaction sigaction_struct;
406 if(strlen(sn) >= MAX_LEN){
407 WARN("socket name too long!");
411 strcpy(sock_name, sn);
413 #if 0 /* signal(2) will not abort accept(2) below. */
414 signal(SIGUSR1, usr1Handler);
416 memset(&sigaction_struct, 0, sizeof(sigaction_struct));
417 sigaction_struct.sa_handler = usr1Handler;
418 sigaction_struct.sa_flags = 0; /* !SA_RESTART */
419 sigaction(SIGUSR1, &sigaction_struct, NULL);
422 signal(SIGPIPE, sig_handler);
423 signal(SIGTERM, sig_handler);
424 signal(SIGINT, sig_handler);
426 while(!usr1Handler_hit){
427 len = sizeof(struct sockaddr_un);
429 if((sock = accept(ssock, (struct sockaddr*)&addr, &len)) < 0){
431 WARN("accept failed: %d(%s)", errno, strerror(errno));
434 TRACE("a client process connected.");
436 if((info = (struct thread_info*)malloc(sizeof(struct thread_info)))){
438 if(ctl->fs_available){
439 TRACE("using already mounted filesystem...");
440 info->fs = ctl->fs_available;
441 ctl->fs_available = NULL;
443 info->fs = new_fsinstance(ctl);
446 info->ppid = getpid();
447 if(!pthread_create(&info->th_id, NULL, &thread_launcher, (void*)info)){
448 info->next = info_list;
451 WARN("could not create thread!");
455 WARN("out of memory?!");
460 TRACE("joining threads...");
461 while ((info = info_list)){
462 info_list = info->next;
463 if (pthread_join(info->th_id, NULL))
464 WARN("could not join thread!");
467 if (ctl->fs_available){
468 struct file_system *fs = ctl->fs_available;
470 if(fs->fs_ops->umount){
471 TRACE("unmounting filesystem...");
472 fs->fs_ops->umount(fs->fs_context);
474 TRACE("freeing filesystem...");
475 fs->fs_ops->free(fs->fs_context);
479 TRACE("socket name: %s", sock_name);
484 lu_fsctl_create(struct list_head *conf){
486 const char *fs_name, *user_name;
488 TRACE("creating fs_ctl");
490 if(!(ctl = (struct fs_ctl*)malloc(sizeof(struct fs_ctl))))
493 memset(ctl, 0, sizeof(struct fs_ctl));
495 ctl->cache = lu_cache_create(conf);
498 if(!(fs_name = lu_opt_getchar(conf, "MOUNT", "fs"))){
499 ERROR("you need to specify a file system!");
504 if(!(ctl->fs_ops = get_filesystem(ctl, (char*)fs_name))){
505 ERROR("unsupported file system: %s", fs_name);
510 if((user_name = lu_opt_getchar(conf, "MOUNT", "username")))
511 strcpy(ctl->cred.user, user_name);
517 lu_fsctl_destroy(struct fs_ctl *ctl){
518 TRACE("destroying fs_ctl");
520 lu_cache_destroy(ctl->cache);
523 dlclose(ctl->dlhandle);
525 if(ctl->fs_available)
526 free(ctl->fs_available);