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];
63 TRACE("unmounting filesystem...");
64 TRACE("socket name: %s", sock_name);
72 TRACE("got a signal: %d", sig);
74 signal(sig, sig_handler);
78 thread_launcher(void *params){
79 struct thread_info *p = (struct thread_info*)params;
80 struct file_system *fs = p->fs;
84 TRACE("thread created");
89 handle_fs(fs, sock, ppid);
91 if(fs->fs_ops->umount)
92 fs->fs_ops->umount(fs->fs_context);
93 fs->fs_ops->free(fs->fs_context);
97 WARN("could not instantiate filesystem (out of mem?) !");
101 TRACE("thread exiting...");
106 #define BUF_SIZE 1024
107 #define PASSWD "/etc/passwd"
108 #define GROUP "/etc/group"
111 load_credentials(struct fs_ctl *ctl, struct file_system *fs){
112 static char buf[BUF_SIZE];
113 char srch_str[MAX_LEN + 4];
115 int res, offset, chunk, readlen;
118 TRACE("loading remote credentials for %s", ctl->cred.user);
120 if((!ctl->fs_ops->open) || (!ctl->fs_ops->read) || (!ctl->fs_ops->release)){
121 WARN("unsupported operation");
125 ctl->cred.uid = ctl->cred.gid = -1;
127 if(ctl->fs_ops->open(fs->fs_context, PASSWD, O_RDONLY) < 0){
128 TRACE("could not open %s", PASSWD);
132 sprintf(srch_str, "\n%s:", ctl->cred.user);
133 chunk = strlen(srch_str) + 64;
134 readlen = BUF_SIZE - chunk - 1;
136 memset(buf, 32, chunk);
140 res = ctl->fs_ops->read(fs->fs_context, PASSWD, offset, readlen, (buf + chunk));
142 *(buf + chunk + res) = 0;
144 if((c = strstr(buf, srch_str))){
145 TRACE("username found!");
146 if(!(c = strchr(c + strlen(srch_str), ':'))){
147 TRACE("separator not found!");
149 if(sscanf(c , ":%li:%li:", &uid, &gid) != 2){
150 TRACE("uid/gid not found!");
152 TRACE("uid: %li, gid: %li", uid, gid);
162 memcpy(buf, buf + BUF_SIZE - chunk - 1, chunk);
165 }while(res == readlen);
167 ctl->fs_ops->release(fs->fs_context, PASSWD);
170 TRACE("read failed");
175 if(ctl->fs_ops->open(fs->fs_context, GROUP, O_RDONLY) < 0){
176 TRACE("could not open %s", GROUP);
180 sprintf(srch_str, ":%li:", (long)ctl->cred.gid);
181 chunk = strlen(srch_str) + 64;
182 readlen = BUF_SIZE - chunk - 1;
184 memset(buf, 32, chunk);
188 res = ctl->fs_ops->read(fs->fs_context, GROUP, offset, readlen, (buf + chunk));
190 *(buf + chunk + res) = 0;
192 if((c = strstr(buf, srch_str))){
193 TRACE("group found!");
194 if(!(c = (char*)memrchr(buf, '\n', (c - buf)))){
195 TRACE("separator not found!");
197 *(strchr(c, ':')) = 0;
198 if(strlen(c + 1) >= MAX_LEN){
199 TRACE("groupname too long");
201 strcpy(ctl->cred.group, c + 1);
202 TRACE("group: %s", ctl->cred.group);
208 memcpy(buf, buf + BUF_SIZE - chunk - 1, chunk);
211 }while(res == readlen);
213 ctl->fs_ops->release(fs->fs_context, GROUP);
216 TRACE("read failed");
224 static struct fs_operations*
225 get_filesystem(struct fs_ctl *ctl, char *fs){
226 struct fs_operations *fops;
230 if(!(buf = (char*)malloc(strlen(fs) + 32)))
233 sprintf(buf, "liblufs-%s.so", fs);
234 TRACE("trying to load %s", buf);
236 if(!(dlhandle = dlopen(buf, RTLD_LAZY))){
243 if(!(fops = (struct fs_operations*)malloc(sizeof(struct fs_operations))))
246 memset(fops, 0, sizeof(struct fs_operations));
248 sprintf(buf, "%s_init", fs);
249 if(!(fops->init = (void*(*)(struct list_head*, struct dir_cache*, struct credentials*, void**))dlsym(dlhandle, buf))){
254 sprintf(buf, "%s_free", fs);
255 if(!(fops->free = (void(*)(void*))dlsym(dlhandle, buf))){
260 sprintf(buf, "%s_mount", fs);
261 if(!(fops->mount = (int(*)(void*))dlsym(dlhandle, buf))){
266 sprintf(buf, "%s_umount", fs);
267 if(!(fops->umount = (void(*)(void*))dlsym(dlhandle, buf)))
270 sprintf(buf, "%s_readdir", fs);
271 if(!(fops->readdir = (int(*)(void*, char*, struct directory*))dlsym(dlhandle, buf)))
274 sprintf(buf, "%s_stat", fs);
275 if(!(fops->stat = (int(*)(void*, char*, struct lufs_fattr*))dlsym(dlhandle, buf)))
278 sprintf(buf, "%s_mkdir", fs);
279 if(!(fops->mkdir = (int(*)(void*, char*, int))dlsym(dlhandle, buf)))
282 sprintf(buf, "%s_rmdir", fs);
283 if(!(fops->rmdir = (int(*)(void*, char*))dlsym(dlhandle, buf)))
286 sprintf(buf, "%s_create", fs);
287 if(!(fops->create = (int(*)(void*, char*, int))dlsym(dlhandle, buf)))
290 sprintf(buf, "%s_unlink", fs);
291 if(!(fops->unlink = (int(*)(void*, char*))dlsym(dlhandle, buf)))
294 sprintf(buf, "%s_rename", fs);
295 if(!(fops->rename = (int(*)(void*, char*, char*))dlsym(dlhandle, buf)))
298 sprintf(buf, "%s_open", fs);
299 if(!(fops->open = (int(*)(void*, char*, unsigned))dlsym(dlhandle, buf)))
302 sprintf(buf, "%s_release", fs);
303 if(!(fops->release = (int(*)(void*, char*))dlsym(dlhandle, buf)))
306 sprintf(buf, "%s_read", fs);
307 if(!(fops->read = (int(*)(void*, char*, long long, unsigned long, char*))dlsym(dlhandle, buf)))
310 sprintf(buf, "%s_write", fs);
311 if(!(fops->write = (int(*)(void*, char*, long long, unsigned long, char*))dlsym(dlhandle, buf)))
314 sprintf(buf, "%s_readlink", fs);
315 if(!(fops->readlink = (int(*)(void*, char*, char*, int))dlsym(dlhandle, buf)))
318 sprintf(buf, "%s_link", fs);
319 if(!(fops->link = (int(*)(void*, char*, char*))dlsym(dlhandle, buf)))
322 sprintf(buf, "%s_symlink", fs);
323 if(!(fops->symlink = (int(*)(void*, char*, char*))dlsym(dlhandle, buf)))
326 sprintf(buf, "%s_setattr", fs);
327 if(!(fops->setattr = (int(*)(void*, char*, struct lufs_fattr*))dlsym(dlhandle, buf)))
330 TRACE("file system loaded");
332 ctl->dlhandle = dlhandle;
346 static struct file_system*
347 new_fsinstance(struct fs_ctl *ctl){
348 struct file_system *fs;
350 if(!(fs = (struct file_system*)malloc(sizeof(struct file_system))))
353 memset(fs, 0, sizeof(struct file_system));
355 fs->fs_ops = ctl->fs_ops;
356 fs->fs_credentials = &ctl->cred;
357 fs->fs_cache = ctl->cache;
358 fs->fs_config = ctl->cfg;
360 if(!(fs->fs_context = ctl->fs_ops->init(ctl->cfg, ctl->cache, fs->fs_credentials, &ctl->global_ctx))){
361 ERROR("could not initialize file system!");
370 lu_fsctl_mount(struct fs_ctl *ctl){
372 struct file_system *fs;
377 if(!(fs = new_fsinstance(ctl)))
380 res = ctl->fs_ops->mount(fs->fs_context);
383 ctl->fs_available = fs;
385 if(load_credentials(ctl, fs) < 0)
386 TRACE("could not load credentials.");
388 TRACE("credentials loaded.");
391 WARN("fs mount failed...");
400 lu_fsctl_run(struct fs_ctl *ctl, int ssock, char *sn){
403 struct sockaddr_un addr;
405 struct thread_info *info;
407 if(strlen(sn) >= MAX_LEN){
408 WARN("socket name too long!");
412 strcpy(sock_name, sn);
414 signal(SIGUSR1, usr1Handler);
416 signal(SIGPIPE, sig_handler);
417 signal(SIGTERM, sig_handler);
418 signal(SIGINT, sig_handler);
421 len = sizeof(struct sockaddr_un);
423 if((sock = accept(ssock, (struct sockaddr*)&addr, &len)) < 0){
425 WARN("accept failed: %d(%s)", errno, strerror(errno));
428 TRACE("a client process connected.");
430 if((info = (struct thread_info*)malloc(sizeof(struct thread_info)))){
432 if(ctl->fs_available){
433 TRACE("using already mounted filesystem...");
434 info->fs = ctl->fs_available;
435 ctl->fs_available = NULL;
437 info->fs = new_fsinstance(ctl);
440 info->ppid = getpid();
441 if(!pthread_create(&th_id, NULL, &thread_launcher, (void*)info)){
442 pthread_detach(th_id);
444 WARN("could not create thread!");
448 WARN("out of memory?!");
456 lu_fsctl_create(struct list_head *conf){
458 const char *fs_name, *user_name;
460 TRACE("creating fs_ctl");
462 if(!(ctl = (struct fs_ctl*)malloc(sizeof(struct fs_ctl))))
465 memset(ctl, 0, sizeof(struct fs_ctl));
467 ctl->cache = lu_cache_create(conf);
470 if(!(fs_name = lu_opt_getchar(conf, "MOUNT", "fs"))){
471 ERROR("you need to specify a file system!");
476 if(!(ctl->fs_ops = get_filesystem(ctl, (char*)fs_name))){
477 ERROR("unsupported file system: %s", fs_name);
482 if((user_name = lu_opt_getchar(conf, "MOUNT", "username")))
483 strcpy(ctl->cred.user, user_name);
489 lu_fsctl_destroy(struct fs_ctl *ctl){
490 TRACE("destroying fs_ctl");
492 lu_cache_destroy(ctl->cache);
495 dlclose(ctl->dlhandle);
497 if(ctl->fs_available)
498 free(ctl->fs_available);