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 sprintf(buf, "%s_statfs", fs);
330 /* 'statfs' is optional as it is new for lufs-0.9.6-captive. */
331 fops->statfs = (int(*)(void*, struct lufs_sbattr*))dlsym(dlhandle, buf);
333 TRACE("file system loaded");
335 ctl->dlhandle = dlhandle;
349 static struct file_system*
350 new_fsinstance(struct fs_ctl *ctl){
351 struct file_system *fs;
353 if(!(fs = (struct file_system*)malloc(sizeof(struct file_system))))
356 memset(fs, 0, sizeof(struct file_system));
358 fs->fs_ops = ctl->fs_ops;
359 fs->fs_credentials = &ctl->cred;
360 fs->fs_cache = ctl->cache;
361 fs->fs_config = ctl->cfg;
363 if(!(fs->fs_context = ctl->fs_ops->init(ctl->cfg, ctl->cache, fs->fs_credentials, &ctl->global_ctx))){
364 ERROR("could not initialize file system!");
373 lu_fsctl_mount(struct fs_ctl *ctl){
375 struct file_system *fs;
380 if(!(fs = new_fsinstance(ctl)))
383 res = ctl->fs_ops->mount(fs->fs_context);
386 ctl->fs_available = fs;
388 if(load_credentials(ctl, fs) < 0)
389 TRACE("could not load credentials.");
391 TRACE("credentials loaded.");
394 WARN("fs mount failed...");
403 lu_fsctl_run(struct fs_ctl *ctl, int ssock, char *sn){
405 struct sockaddr_un addr;
407 struct thread_info *info, *info_list=NULL;
408 struct sigaction sigaction_struct;
410 if(strlen(sn) >= MAX_LEN){
411 WARN("socket name too long!");
415 strcpy(sock_name, sn);
417 #if 0 /* signal(2) will not abort accept(2) below. */
418 signal(SIGUSR1, usr1Handler);
420 memset(&sigaction_struct, 0, sizeof(sigaction_struct));
421 sigaction_struct.sa_handler = usr1Handler;
422 sigaction_struct.sa_flags = 0; /* !SA_RESTART */
423 sigaction(SIGUSR1, &sigaction_struct, NULL);
426 signal(SIGPIPE, sig_handler);
427 signal(SIGTERM, sig_handler);
428 signal(SIGINT, sig_handler);
430 while(!usr1Handler_hit){
431 len = sizeof(struct sockaddr_un);
433 if((sock = accept(ssock, (struct sockaddr*)&addr, &len)) < 0){
435 WARN("accept failed: %d(%s)", errno, strerror(errno));
438 TRACE("a client process connected.");
440 if((info = (struct thread_info*)malloc(sizeof(struct thread_info)))){
442 if(ctl->fs_available){
443 TRACE("using already mounted filesystem...");
444 info->fs = ctl->fs_available;
445 ctl->fs_available = NULL;
447 info->fs = new_fsinstance(ctl);
450 info->ppid = getpid();
451 if(!pthread_create(&info->th_id, NULL, &thread_launcher, (void*)info)){
452 info->next = info_list;
455 WARN("could not create thread!");
459 WARN("out of memory?!");
464 TRACE("joining threads...");
465 while ((info = info_list)){
466 info_list = info->next;
467 if (pthread_join(info->th_id, NULL))
468 WARN("could not join thread!");
471 if (ctl->fs_available){
472 struct file_system *fs = ctl->fs_available;
474 if(fs->fs_ops->umount){
475 TRACE("unmounting filesystem...");
476 fs->fs_ops->umount(fs->fs_context);
478 TRACE("freeing filesystem...");
479 fs->fs_ops->free(fs->fs_context);
483 TRACE("socket name: %s", sock_name);
488 lu_fsctl_create(struct list_head *conf){
490 const char *fs_name, *user_name;
492 TRACE("creating fs_ctl");
494 if(!(ctl = (struct fs_ctl*)malloc(sizeof(struct fs_ctl))))
497 memset(ctl, 0, sizeof(struct fs_ctl));
499 ctl->cache = lu_cache_create(conf);
502 if(!(fs_name = lu_opt_getchar(conf, "MOUNT", "fs"))){
503 ERROR("you need to specify a file system!");
508 if(!(ctl->fs_ops = get_filesystem(ctl, (char*)fs_name))){
509 ERROR("unsupported file system: %s", fs_name);
514 if((user_name = lu_opt_getchar(conf, "MOUNT", "username")))
515 strcpy(ctl->cred.user, user_name);
521 lu_fsctl_destroy(struct fs_ctl *ctl){
522 TRACE("destroying fs_ctl");
524 lu_cache_destroy(ctl->cache);
527 dlclose(ctl->dlhandle);
529 if(ctl->fs_available)
530 free(ctl->fs_available);