diff options
Diffstat (limited to 'lufis')
-rw-r--r-- | lufis/.cvsignore | 1 | ||||
-rw-r--r-- | lufis/COPYING | 340 | ||||
-rw-r--r-- | lufis/ChangeLog | 8 | ||||
-rw-r--r-- | lufis/Makefile | 21 | ||||
-rw-r--r-- | lufis/README | 50 | ||||
-rw-r--r-- | lufis/dircache.c | 478 | ||||
-rw-r--r-- | lufis/dircache.h | 75 | ||||
-rw-r--r-- | lufis/list.h | 171 | ||||
-rw-r--r-- | lufis/lufis.c | 800 | ||||
-rw-r--r-- | lufis/options.c | 301 |
10 files changed, 0 insertions, 2245 deletions
diff --git a/lufis/.cvsignore b/lufis/.cvsignore deleted file mode 100644 index dc5eb9e..0000000 --- a/lufis/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -lufis diff --git a/lufis/COPYING b/lufis/COPYING deleted file mode 100644 index d60c31a..0000000 --- a/lufis/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - <signature of Ty Coon>, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/lufis/ChangeLog b/lufis/ChangeLog deleted file mode 100644 index d3256b4..0000000 --- a/lufis/ChangeLog +++ /dev/null @@ -1,8 +0,0 @@ -2004-10-09 Miklos Szeredi <miklos@szeredi.hu> - - * Fix compilation with post 1.9 FUSE - -2004-03-09 Miklos Szeredi <miklos@szeredi.hu> - - * Make it possible to mount captivefs filesystem - diff --git a/lufis/Makefile b/lufis/Makefile deleted file mode 100644 index 5ff0392..0000000 --- a/lufis/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -CC = gcc - -CFLAGS := -Wall -W -g -LDLIBS := -lpthread -ldl -rdynamic - -PKGCONFIG := env PKG_CONFIG_PATH=/usr/local/lib/pkgconfig pkg-config -FUSEVER := $(shell $(PKGCONFIG) --modversion fuse 2> /dev/null) -ifeq ($(FUSEVER),) - LDLIBS += -lfuse -else - CFLAGS += $(shell $(PKGCONFIG) --cflags fuse) - LDLIBS += $(shell $(PKGCONFIG) --libs fuse) -endif - -CPPFLAGS := -D_FILE_OFFSET_BITS=64 -#CPPFLAGS += -DDEBUG - -lufis: lufis.o options.o dircache.o - -clean: - rm -f *.o lufis diff --git a/lufis/README b/lufis/README deleted file mode 100644 index 93db721..0000000 --- a/lufis/README +++ /dev/null @@ -1,50 +0,0 @@ -This is a modified LUFS daemon, which uses the FUSE kernel module. It -is binary compatible with existing LUFS filesystems, so no -recompilation is needed. - -Licence: - -GPL (see COPYING). Most of the code is copied from the LUFS source -written by Florin Malita <mali@go.ro>, thanks! - -Disclaimer: - -This is currently just a proof-of-concept implementation, not a -finished product. That said it seems perfectly stable. Comments, are -of course welcome <miklos@szeredi.hu>. - -Installation: - - - install lufs (0.9.7) - - install fuse (1.1) - - enter 'make' in this directory - -Usage, for exampe: - - ./lufis fs=sshfs,host=kempelen,username=mszeredi /mnt/lufis/ -s - -Don't forget the '-s' option, without it the filesystem may misbehave! - -For help on FUSE specific options see: - - ./lufis fs=localfs -h - -and - - ./lufis fs=localfs / -- -h - -For LUFS specific options (can only be specified in the first -argument) see the README in the LUFS distribution - - -Captivefs: - -from version 0.2 lufis supports mounting the captivefs. Command line -should be something like this: - -lufis "fs=captivefs,dir_cache_entries=0,image=/store/ntfs/ntfs.img,captive_options=--rw;--load-module=/var/lib/captive/ntoskrnl.exe;--filesystem=/var/lib/captive/ntfs.sys;--sandbox-server=/usr/sbin/captive-sandbox-server;" /mnt/ntfs -s - -It may work without the '-s' option, but this is untested. - -umounting should be done with 'umount' as root or 'fusermount -u' as -non-root. diff --git a/lufis/dircache.c b/lufis/dircache.c deleted file mode 100644 index bdd8717..0000000 --- a/lufis/dircache.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - * dircache.c - * Copyright (C) 2002 Florin Malita <mali@go.ro> - * - * This file is part of LUFS, a free userspace filesystem implementation. - * See http://lufs.sourceforge.net/ for updates. - * - * LUFS is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * LUFS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <pthread.h> - -#include <sys/stat.h> - -#include <lufs/proto.h> -#include <lufs/fs.h> - -#include "list.h" -#include "dircache.h" - -static char root_dir[]="/"; -static char current_dir[]="."; - -static unsigned long -hash(char *name){ - unsigned long res = 0; - unsigned int i; - - for(i = 0; i < strlen(name); i++) - if(name[i] != '/') - res = 0x21413 * (res + name[i]); - - return res % NBUCKETS; -} - -static void -delete_dir(struct directory *d){ - struct list_head *p, *tmp; - struct direntry *de; - - TRACE("in"); - list_for_each_safe(p, tmp, &d->d_entries){ - de = list_entry(p, struct direntry, e_list); - list_del(&de->e_list); - free(de->e_name); - if(de->e_link) - free(de->e_link); - free(de); - } - - list_del(&d->d_list); - free(d->d_name); - free(d); - - TRACE("out"); -} - -struct dir_cache* -lu_cache_create(struct list_head *cfg){ - struct dir_cache *cache; - int i; - const char *c; - - TRACE("creating dir cache..."); - - if(!(cache = malloc(sizeof(struct dir_cache)))) - return NULL; - - memset(cache, 0, sizeof(struct dir_cache)); - - for(i = 0; i < NBUCKETS; i++) - INIT_LIST_HEAD(&cache->buckets[i]); - - pthread_mutex_init(&cache->lock, NULL); - - cache->ttl = DEF_TTL; - if((c = lu_opt_getchar(cfg, "LUFSD", "DirCacheTTL")) && atoi(c)) - cache->ttl = atoi(c); - if((c = lu_opt_getchar(cfg, "MOUNT", "dir_cache_ttl")) && atoi(c)) - cache->ttl = atoi(c); - - cache->entries = DEF_NENTRIES; - if((c = lu_opt_getchar(cfg, "LUFSD", "DirCacheEntries")) && atoi(c)) - cache->entries = atoi(c); - if((c = lu_opt_getchar(cfg, "MOUNT", "dir_cache_entries")) && atoi(c)) - cache->entries = atoi(c); - - TRACE("entries: %d, ttl: %d", cache->entries, cache->ttl); - - return cache; -} - -void -lu_cache_destroy(struct dir_cache *cache){ - struct list_head *p, *tmp; - int i; - - for(i = 0; i < NBUCKETS; i++){ - list_for_each_safe(p, tmp, &cache->buckets[i]){ - delete_dir(list_entry(p, struct directory, d_list)); - } - } - - free(cache); -} - -static struct directory* -search(struct dir_cache *cache, char *dir){ - struct list_head *p, *tmp; - struct directory *d; - int hsh; - - hsh = hash(dir); - - TRACE("search %s in bucket %u, size=%u", dir, hsh, cache->lengths[hsh]); - - list_for_each_safe(p, tmp, &cache->buckets[hsh]){ - d = list_entry(p, struct directory, d_list); - - if(time(NULL) - d->d_stamp >= (unsigned long) cache->ttl){ - TRACE("%s expired...", d->d_name); - delete_dir(d); - cache->lengths[hsh]--; - TRACE("directory deleted"); - }else if(!strcmp(dir, d->d_name)){ - TRACE("%s found", dir); - d->d_stamp = time(NULL); - return d; - } - } - - TRACE("dir not found"); - return NULL; -} - -int -lu_cache_lookup(struct dir_cache *cache, char *dir, char *file, struct lufs_fattr *fattr, char *link, int buflen){ - struct directory *d; - struct direntry *de; - struct list_head *p; - int res = -1; - - TRACE("looking up %s in dir %s", file, dir); - - pthread_mutex_lock(&cache->lock); - - if(!(d = search(cache, dir))) - goto out; - - list_for_each(p, &d->d_entries){ - de = list_entry(p, struct direntry, e_list); - if(!strcmp(file, de->e_name)){ - TRACE("file found"); - - memcpy(fattr, &de->e_attr, sizeof(struct lufs_fattr)); - if(link){ - if(de->e_link){ - if(snprintf(link, buflen, "%s", de->e_link) >= buflen){ - WARN("link too long!"); - link[buflen - 1] =0; - } - }else{ - link[0] = 0; - } - } - - res = 0; - goto out; - } - } - - TRACE("file not found!"); - - out: - pthread_mutex_unlock(&cache->lock); - return res; -} - -static void -shrink(struct dir_cache *cache, int hsh){ - struct directory *dir; - - TRACE("shrinking bucket %u, len=%u", hsh, cache->lengths[hsh]); - - if(list_empty(&cache->buckets[hsh])) - return; - - dir = list_entry(cache->buckets[hsh].prev, struct directory, d_list); - - TRACE("deleting dir %s", dir->d_name); - - delete_dir(dir); - cache->lengths[hsh]--; -} - -static void -check_dir(struct directory *d){ - struct list_head *p, *tmp; - struct direntry *e; - struct lufs_fattr dummy; - int dot = 0, dotdot = 0; - - memset(&dummy, 0, sizeof(struct lufs_fattr)); - dummy.f_nlink = 1; - dummy.f_uid = dummy.f_gid = 1; - dummy.f_mode = S_IFDIR | S_IRWXU | S_IRGRP | S_IXGRP; - dummy.f_mtime = dummy.f_atime = dummy.f_ctime = time(NULL); - dummy.f_size = 512; - - do{ - list_for_each_safe(p, tmp, &d->d_entries){ - e = list_entry(p, struct direntry, e_list); - - if(!strcmp(e->e_name, ".")){ - TRACE("'.' entry found"); - list_del(&e->e_list); - list_add(&e->e_list, &d->d_entries); - dot = 1; - continue; - } - - if(!strcmp(e->e_name, "..")){ - TRACE("'..' entry found"); - list_del(&e->e_list); - if(!dot) - list_add(&e->e_list, &d->d_entries); - else - list_add(&e->e_list, d->d_entries.next); - - dotdot = 1; - } - } - - if(!dot) - lu_cache_add2dir(d, ".", NULL, &dummy); - - if(!dotdot) - lu_cache_add2dir(d, "..", NULL, &dummy); - - }while((!dot) || (!dotdot)); - -} - -void -lu_cache_add_dir(struct dir_cache *cache, struct directory *d){ - struct directory *dir; - int hsh; - - hsh = hash(d->d_name); - - TRACE("adding dir %s to bucket %i", d->d_name, hsh); - - check_dir(d); - - pthread_mutex_lock(&cache->lock); - - if((dir = search(cache, d->d_name))){ - TRACE("directory already in cache, deleting..."); - delete_dir(dir); - cache->lengths[hsh]--; - } - - d->d_stamp = time(NULL); - - list_add(&d->d_list, &cache->buckets[hsh]); - cache->lengths[hsh]++; - - while(cache->lengths[hsh] > cache->entries) - shrink(cache, hsh); - - pthread_mutex_unlock(&cache->lock); - - TRACE("out"); -} - -int lu_cache_readdir(struct dir_cache *cache, char *dir, - fuse_dirh_t h, fuse_dirfil_t filler) -{ - struct directory *d; - struct direntry *de; - struct list_head *p; - int res = -1; - - TRACE("reading directory %s", dir); - - pthread_mutex_lock(&cache->lock); - - if(!(d = search(cache, dir))) - goto out; - - list_for_each(p, &d->d_entries){ - de = list_entry(p, struct direntry, e_list); -#if FUSE_MAJOR_VERSION < 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION < 1) - filler(h, de->e_name, 0); -#else - filler(h, de->e_name, 0, 0); -#endif - } - - d->d_stamp = time(NULL); - - res = 0; - - out: - pthread_mutex_unlock(&cache->lock); - TRACE("out"); - return res; -} - -int -lu_cache_lookup_file(struct dir_cache *cache, char *file, struct lufs_fattr *fattr, char *link, int buflen){ - int res; - - char *sep, *dir; - - if(!(sep = strrchr(file, '/'))){ - WARN("separator not present!"); - return -1; - } - - *sep = 0; - - if(sep == file) - dir = root_dir; - else - dir = file; - - if(*(sep+1)) - file = sep + 1; - else - file = current_dir; - - TRACE("dir: %s, file: %s", dir, file); - - res = lu_cache_lookup(cache, dir, file, fattr, link, buflen); - *sep = '/'; - - return res; -} - -int -lu_cache_invalidate(struct dir_cache *cache, char *file){ - struct directory *d; - char *sep, *dir; - - if(!(sep = strrchr(file, '/'))){ - WARN("separator not present!"); - return -1; - } - - *sep = 0; - - if(sep == file) - dir = root_dir; - else - dir = file; - - TRACE("invalidating dir %s", dir); - - pthread_mutex_lock(&cache->lock); - - if(!(d = search(cache, dir))){ - *sep = '/'; - pthread_mutex_unlock(&cache->lock); - return -1; - } - - d->d_stamp = 0; - - pthread_mutex_unlock(&cache->lock); - *sep = '/'; - - return 0; -} - -struct directory* -lu_cache_mkdir(char *dir){ - struct directory *res; - - TRACE("create dir %s", dir); - - if(!(res = malloc(sizeof(struct directory)))){ - WARN("out of mem!"); - return NULL; - } - - memset(res, 0, sizeof(struct directory)); - - if(!(res->d_name = malloc(strlen(dir) + 1))){ - WARN("out of mem!"); - free(res); - return NULL; - } - - INIT_LIST_HEAD(&res->d_entries); - res->d_stamp = time(NULL); - strcpy(res->d_name, dir); - - return res; -} - -int -lu_cache_add2dir(struct directory *d, char *fname, char *link, struct lufs_fattr *fattr){ - struct direntry *de; - - TRACE("adding %s->%s to %s", fname, link, d->d_name); - - if(!(de = malloc(sizeof(struct direntry)))) - goto fail; - - - if(!(de->e_name = malloc(strlen(fname) + 1))) - goto fail_de; - - - if(link) - de->e_link = malloc(strlen(link) + 1); - else - de->e_link = malloc(2); - - if(!de->e_link) - goto fail_ename; - - memcpy(&de->e_attr, fattr, sizeof(struct lufs_fattr)); - strcpy(de->e_name, fname); - if(link) - strcpy(de->e_link, link); - else - strcpy(de->e_link, ""); - - list_add_tail(&de->e_list, &d->d_entries); - - return 0; - - fail_ename: - free(de->e_name); - fail_de: - free(de); - fail: - WARN("out of mem!"); - return -1; -} - -void -lu_cache_killdir(struct directory *d){ - struct list_head *p, *tmp; - struct direntry *de; - - TRACE("in"); - - list_for_each_safe(p, tmp, &d->d_entries){ - de = list_entry(p, struct direntry, e_list); - list_del(&de->e_list); - free(de->e_name); - if(de->e_link) - free(de->e_link); - free(de); - } - - free(d->d_name); - free(d); - -} diff --git a/lufis/dircache.h b/lufis/dircache.h deleted file mode 100644 index 3c33d25..0000000 --- a/lufis/dircache.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * dircache.h - * Copyright (C) 2002 Florin Malita <mali@go.ro> - * - * This file is part of LUFS, a free userspace filesystem implementation. - * See http://lufs.sourceforge.net/ for updates. - * - * LUFS is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * LUFS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _DIRCACHE_H_ -#define _DIRCACHE_H_ - -#include <fuse.h> - -#ifdef __cplusplus -extern "C" { -#endif - - -#define NBUCKETS 7 -#define DEF_NENTRIES 6 -#define DEF_TTL 20 - -struct list_head; - -struct direntry{ - char *e_name; - char *e_link; - struct list_head e_list; - struct lufs_fattr e_attr; -}; - -struct directory{ - char *d_name; - struct list_head d_entries; - struct list_head d_list; - unsigned long d_stamp; -}; - -struct dir_cache{ - int ttl; - int entries; - pthread_mutex_t lock; - struct list_head buckets[NBUCKETS]; - int lengths[NBUCKETS]; -}; - -struct dir_cache* lu_cache_create(struct list_head*); -void lu_cache_destroy(struct dir_cache*); - -int lu_cache_lookup_file(struct dir_cache*, char*, struct lufs_fattr*, char*, int); -void lu_cache_add(struct dir_cache*, char*, char*, struct lufs_fattr*, char*); -int lu_cache_readdir(struct dir_cache *cache, char *dir, - fuse_dirh_t h, fuse_dirfil_t filler); -int lu_cache_invalidate(struct dir_cache*, char*); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lufis/list.h b/lufis/list.h deleted file mode 100644 index f3cb6f5..0000000 --- a/lufis/list.h +++ /dev/null @@ -1,171 +0,0 @@ -#ifndef _LINUX_LIST_H -#define _LINUX_LIST_H - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static __inline__ void __list_add(struct list_head * nnew, - struct list_head * prev, - struct list_head * next) -{ - next->prev = nnew; - nnew->next = next; - nnew->prev = prev; - prev->next = nnew; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static __inline__ void list_add(struct list_head *nnew, struct list_head *head) -{ - __list_add(nnew, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @nnew: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static __inline__ void list_add_tail(struct list_head *nnew, struct list_head *head) -{ - __list_add(nnew, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static __inline__ void __list_del(struct list_head * prev, - struct list_head * next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is in an undefined state. - */ -static __inline__ void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static __inline__ void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static __inline__ int list_empty(struct list_head *head) -{ - return head->next == head; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static __inline__ void list_splice(struct list_head *list, struct list_head *head) -{ - struct list_head *first = list->next; - - if (first != list) { - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; - } -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); \ - pos = pos->next) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * list_for_each_prev - iterate over a list in reverse order - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev; pos != (head); \ - pos = pos->prev) - - -#endif diff --git a/lufis/lufis.c b/lufis/lufis.c deleted file mode 100644 index 5509bdf..0000000 --- a/lufis/lufis.c +++ /dev/null @@ -1,800 +0,0 @@ -#define _GNU_SOURCE - -#include <lufs/fs.h> -#include <lufs/proto.h> -#include <fuse.h> -#include "list.h" -#include "dircache.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <dlfcn.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <sys/vfs.h> - -/* statfs extension for captivefs */ -struct lufs_sbattr_ { /* struct statfs64 */ - unsigned long long sb_bytes; - unsigned long long sb_bytes_free; - unsigned long long sb_bytes_available; - unsigned long long sb_files; - unsigned long long sb_ffree; -}; - -struct fs_operations { - void *(*init)(struct list_head*, struct dir_cache*, struct credentials*, void**); - void (*free)(void*); - int (*mount)(void*); - void (*umount)(void*); - int (*readdir)(void*, char*, struct directory*); - int (*stat)(void*, char*, struct lufs_fattr*); - int (*mkdir)(void*, char*, int); - int (*rmdir)(void*, char*); - int (*create)(void*, char*, int); - int (*unlink)(void*, char*); - int (*rename)(void*, char*, char*); - int (*open)(void*, char*, unsigned); - int (*release)(void*, char*); - int (*read)(void*, char*, long long, unsigned long, char*); - int (*write)(void*, char*, long long, unsigned long, char*); - int (*readlink)(void*, char*, char*, int); - int (*link)(void*, char*, char*); - int (*symlink)(void*, char*, char*); - int (*setattr)(void*, char*, struct lufs_fattr*); - int (*statfs)(void*, struct lufs_sbattr_*); -}; - -static struct fs_operations lu_fops; -static void *lu_dlhandle; -static struct list_head lu_cfg; -static void *lu_global_ctx; -static struct credentials lu_cred; -static void *lu_context; -static struct dir_cache *lu_cache; - -#define BUF_SIZE 1024 -#define PASSWD "/etc/passwd" -#define GROUP "/etc/group" - -int lu_check_to(int rd_fd, int wr_fd, int time_out){ - fd_set rd, wr; - int res, maxfd = 0; - struct timeval tv; - - FD_ZERO(&rd); - FD_ZERO(&wr); - - if(rd_fd){ - FD_SET(rd_fd, &rd); - maxfd = rd_fd > maxfd ? rd_fd : maxfd; - } - - if(wr_fd){ - FD_SET(wr_fd, &wr); - maxfd = wr_fd > maxfd ? wr_fd : maxfd; - } - - tv.tv_sec = time_out; - tv.tv_usec = 0; - - do{ - res = select(maxfd + 1, &rd, &wr, NULL, &tv); - - }while((res < 0) && (errno == EINTR)); - - if(res > 0) - return 0; - - if(res < 0){ - WARN("select call failed: %s", strerror(errno)); - return -errno; - } - - WARN("operation timed out!"); - - return -ETIMEDOUT; -} - -int lu_atomic_read(int fd, char *buf, int len, int time_out){ - int res, offset = 0; - - do{ - if((time_out) && ((res = lu_check_to(fd, 0, time_out)) < 0)) - return res; - - do{ - res = read(fd, buf + offset, len - offset); - }while((res < 0) && (errno == EINTR)); - - if(res <= 0){ - WARN("read call failed: %s", strerror(errno)); - return (res < 0) ? -errno : (offset > 0 ? offset : -EPIPE); - } - - offset += res; - - }while(offset < len); - - return offset; -} - -int lu_atomic_write(int fd, char *buf, int len, int time_out){ - int res, offset = 0; - - do{ - if((time_out) && ((res = lu_check_to(0, fd, time_out)) < 0)) - return res; - - do{ - res = write(fd, buf + offset, len - offset); - }while((res < 0) && (errno == EINTR)); - - if(res <= 0){ - WARN("write call failed: %s", strerror(errno)); - return (res < 0) ? -errno : (offset > 0 ? offset : -EPIPE); - } - - offset += res; - - }while(offset < len); - - return offset; -} - -static int get_filesystem(const char *fs) -{ - char *buf; - void *dlhandle; - - if(!(buf = (char*)malloc(strlen(fs) + 32))) - return -1; - - sprintf(buf, "liblufs-%s.so", fs); - if(!(dlhandle = dlopen(buf, RTLD_LAZY))){ - ERROR(dlerror()); - goto fail; - } - - sprintf(buf, "%s_init", fs); - if(!(lu_fops.init = (void*(*)(struct list_head*, struct dir_cache*, struct credentials*, void**))dlsym(dlhandle, buf))){ - ERROR(dlerror()); - goto fail_fops; - } - - sprintf(buf, "%s_free", fs); - if(!(lu_fops.free = (void(*)(void*))dlsym(dlhandle, buf))){ - ERROR(dlerror()); - goto fail_fops; - } - - sprintf(buf, "%s_mount", fs); - if(!(lu_fops.mount = (int(*)(void*))dlsym(dlhandle, buf))){ - ERROR(dlerror()); - goto fail_fops; - } - - sprintf(buf, "%s_umount", fs); - if(!(lu_fops.umount = (void(*)(void*))dlsym(dlhandle, buf))) - ERROR(dlerror()); - - sprintf(buf, "%s_readdir", fs); - if(!(lu_fops.readdir = (int(*)(void*, char*, struct directory*))dlsym(dlhandle, buf))) - ERROR(dlerror()); - - sprintf(buf, "%s_stat", fs); - if(!(lu_fops.stat = (int(*)(void*, char*, struct lufs_fattr*))dlsym(dlhandle, buf))) - ERROR(dlerror()); - - sprintf(buf, "%s_mkdir", fs); - if(!(lu_fops.mkdir = (int(*)(void*, char*, int))dlsym(dlhandle, buf))) - ERROR(dlerror()); - - sprintf(buf, "%s_rmdir", fs); - if(!(lu_fops.rmdir = (int(*)(void*, char*))dlsym(dlhandle, buf))) - ERROR(dlerror()); - - sprintf(buf, "%s_create", fs); - if(!(lu_fops.create = (int(*)(void*, char*, int))dlsym(dlhandle, buf))) - ERROR(dlerror()); - - sprintf(buf, "%s_unlink", fs); - if(!(lu_fops.unlink = (int(*)(void*, char*))dlsym(dlhandle, buf))) - ERROR(dlerror()); - - sprintf(buf, "%s_rename", fs); - if(!(lu_fops.rename = (int(*)(void*, char*, char*))dlsym(dlhandle, buf))) - ERROR(dlerror()); - - sprintf(buf, "%s_open", fs); - if(!(lu_fops.open = (int(*)(void*, char*, unsigned))dlsym(dlhandle, buf))) - ERROR(dlerror()); - - sprintf(buf, "%s_release", fs); - if(!(lu_fops.release = (int(*)(void*, char*))dlsym(dlhandle, buf))) - ERROR(dlerror()); - - sprintf(buf, "%s_read", fs); - if(!(lu_fops.read = (int(*)(void*, char*, long long, unsigned long, char*))dlsym(dlhandle, buf))) - ERROR(dlerror()); - - sprintf(buf, "%s_write", fs); - if(!(lu_fops.write = (int(*)(void*, char*, long long, unsigned long, char*))dlsym(dlhandle, buf))) - ERROR(dlerror()); - - sprintf(buf, "%s_readlink", fs); - if(!(lu_fops.readlink = (int(*)(void*, char*, char*, int))dlsym(dlhandle, buf))) - ERROR(dlerror()); - - sprintf(buf, "%s_link", fs); - if(!(lu_fops.link = (int(*)(void*, char*, char*))dlsym(dlhandle, buf))) - ERROR(dlerror()); - - sprintf(buf, "%s_symlink", fs); - if(!(lu_fops.symlink = (int(*)(void*, char*, char*))dlsym(dlhandle, buf))) - ERROR(dlerror()); - - sprintf(buf, "%s_setattr", fs); - if(!(lu_fops.setattr = (int(*)(void*, char*, struct lufs_fattr*))dlsym(dlhandle, buf))) - ERROR(dlerror()); - sprintf(buf, "%s_statfs", fs); - lu_fops.statfs = (int(*)(void*, struct lufs_sbattr_*))dlsym(dlhandle, buf); - - lu_dlhandle = dlhandle; - free(buf); - return 0; - - fail_fops: - dlclose(dlhandle); - fail: - free(buf); - return -1; -} - -static int lu_getattr_native(const char *path, struct lufs_fattr *fattr) -{ - if(!lu_fops.stat) - return -ENOSYS; - - memset(fattr, 0, sizeof(struct lufs_fattr)); - if(lu_cache_lookup_file(lu_cache, (char *) path, fattr, NULL, 0) < 0) { - if(lu_fops.stat(lu_context, (char *) path, fattr) < 0) - return -ENOENT; - } - return 0; -} - -static int lu_getattr(const char *path, struct stat *stbuf) -{ - struct lufs_fattr fattr; - int res; - - res = lu_getattr_native(path, &fattr); - if(res < 0) - return res; - - stbuf->st_mode = fattr.f_mode; - stbuf->st_nlink = fattr.f_nlink; - stbuf->st_uid = fattr.f_uid; - stbuf->st_gid = fattr.f_gid; - stbuf->st_size = fattr.f_size; - stbuf->st_atime = fattr.f_atime; - stbuf->st_mtime = fattr.f_mtime; - stbuf->st_ctime = fattr.f_ctime; - stbuf->st_blksize = fattr.f_blksize; - stbuf->st_blocks = fattr.f_blocks; - - return 0; -} - -static int lu_readlink(const char *path, char *buf, size_t size) -{ - int len; - struct lufs_fattr fattr; - - if(!lu_fops.readlink) - return -ENOSYS; - - if(lu_cache_lookup_file(lu_cache, (char *) path, &fattr, buf, size) < 0 || - strcmp(buf, "") == 0) { - if((len = lu_fops.readlink(lu_context, (char *) path, buf, size)) < 0) - return -EPERM; - - /* FUSE leaves one extra char free at the end */ - buf[len] = '\0'; - } - - return 0; -} - -static int lu_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler) -{ - struct directory *dir; - - if(!lu_fops.readdir) - return -ENOSYS; - - if(lu_cache_readdir(lu_cache, (char *) path, h, filler) < 0){ - if(!(dir = lu_cache_mkdir((char *) path))) - return -1; - - if(lu_fops.readdir(lu_context, (char *) path, dir) < 0){ - lu_cache_killdir(dir); - return -1; - } - lu_cache_add_dir(lu_cache, dir); - - if(lu_cache_readdir(lu_cache, (char *) path, h, filler) < 0) { - return -EPERM; - } - } - return 0; -} - -static int lu_mknod(const char *path, mode_t mode, dev_t rdev) -{ - (void) rdev; - if(!S_ISREG(mode) || !lu_fops.create) - return -ENOSYS; - - if(lu_fops.create(lu_context, (char *) path, mode) < 0) - return -EPERM; - - lu_cache_invalidate(lu_cache, (char *) path); - return 0; -} - -static int lu_mkdir(const char *path, mode_t mode) -{ - if(!lu_fops.mkdir) - return -ENOSYS; - - if(lu_fops.mkdir(lu_context, (char *) path, mode) < 0) - return -EPERM; - - lu_cache_invalidate(lu_cache, (char *) path); - return 0; -} - -static int lu_unlink(const char *path) -{ - if(!lu_fops.unlink) - return -ENOSYS; - - if(lu_fops.unlink(lu_context, (char *) path) < 0) - return -EPERM; - - lu_cache_invalidate(lu_cache, (char *) path); - return 0; -} - -static int lu_rmdir(const char *path) -{ - if(!lu_fops.rmdir) - return -ENOSYS; - - if(lu_fops.rmdir(lu_context, (char *) path) < 0) - return -EPERM; - - lu_cache_invalidate(lu_cache, (char *) path); - return 0; -} - -static int lu_symlink(const char *from, const char *to) -{ - if(!lu_fops.symlink) - return -ENOSYS; - - if(lu_fops.symlink(lu_context, (char *) from, (char *) to) < 0) - return -EPERM; - - lu_cache_invalidate(lu_cache, (char *) to); - return 0; -} - -static int lu_rename(const char *from, const char *to) -{ - if(!lu_fops.rename) - return -ENOSYS; - - if(lu_fops.rename(lu_context, (char *) from, (char *) to) < 0) - return -EPERM; - - lu_cache_invalidate(lu_cache, (char *) from); - lu_cache_invalidate(lu_cache, (char *) to); - return 0; -} - -static int lu_link(const char *from, const char *to) -{ - if(!lu_fops.link) - return -ENOSYS; - - if(lu_fops.link(lu_context, (char *) from, (char *) to) < 0) - return -EPERM; - - lu_cache_invalidate(lu_cache, (char *) from); - lu_cache_invalidate(lu_cache, (char *) to); - return 0; -} - -static int lu_chmod(const char *path, mode_t mode) -{ - int res; - struct lufs_fattr fattr; - - if(!lu_fops.setattr) - return -ENOSYS; - - res = lu_getattr_native(path, &fattr); - if(res < 0) - return res; - - fattr.f_mode = mode; - if(lu_fops.setattr(lu_context, (char *) path, &fattr) < 0) - return -EPERM; - - lu_cache_invalidate(lu_cache, (char *) path); - return 0; -} - -static int lu_chown(const char *path, uid_t uid, gid_t gid) -{ - int res; - struct lufs_fattr fattr; - - if(!lu_fops.setattr) - return -ENOSYS; - - res = lu_getattr_native(path, &fattr); - if(res < 0) - return res; - - if(uid != (uid_t) -1) - fattr.f_uid = uid; - if(gid != (gid_t) -1) - fattr.f_gid = gid; - if(lu_fops.setattr(lu_context, (char *) path, &fattr) < 0) - return -EPERM; - - lu_cache_invalidate(lu_cache, (char *) path); - return 0; - -} - -static int lu_truncate(const char *path, off_t size) -{ - int res; - struct lufs_fattr fattr; - - if(!lu_fops.setattr) - return -ENOSYS; - - res = lu_getattr_native(path, &fattr); - if(res < 0) - return res; - - fattr.f_size = size; - if(lu_fops.setattr(lu_context, (char *) path, &fattr) < 0) - return -EPERM; - - lu_cache_invalidate(lu_cache, (char *) path); - return 0; -} - -static int lu_utime(const char *path, struct utimbuf *buf) -{ - int res; - struct lufs_fattr fattr; - - if(!lu_fops.setattr) - return -ENOSYS; - - res = lu_getattr_native(path, &fattr); - if(res < 0) - return res; - - fattr.f_atime = buf->actime; - fattr.f_mtime = buf->modtime; - if(lu_fops.setattr(lu_context, (char *) path, &fattr) < 0) - return -EPERM; - - lu_cache_invalidate(lu_cache, (char *) path); - return 0; -} - - -static int lu_open(const char *path, int flags) -{ - if(!lu_fops.open) - return -ENOSYS; - - if(lu_fops.open(lu_context, (char *) path, flags & O_ACCMODE) < 0) - return -EPERM; - - return 0; -} - -static int lu_read(const char *path, char *buf, size_t size, off_t offset) -{ - int res; - if(!lu_fops.read) - return -ENOSYS; - - if((res = lu_fops.read(lu_context, (char *) path, offset, size, buf)) < 0) - return -EPERM; - - return res; -} - -static int lu_write(const char *path, const char *buf, size_t size, - off_t offset) -{ - if(!lu_fops.write) - return -ENOSYS; - - if(lu_fops.write(lu_context, (char *) path, offset, size, (char *) buf) < 0) - return -EPERM; - - return size; -} - -static int lu_release(const char *path, int flags) -{ - (void) flags; - if(!lu_fops.release) - return -ENOSYS; - - if(lu_fops.release(lu_context, (char *) path) < 0) - return -EPERM; - - return 0; -} - -#if FUSE_MAJOR_VERSION < 2 -static int lu_statfs(struct fuse_statfs *stbuf) -#else -static int lu_statfs(const char *path, struct statfs *stbuf) -#endif -{ - struct lufs_sbattr_ sbattr; - - memset(&sbattr, 0, sizeof(sbattr)); - if(lu_fops.statfs) { - if(lu_fops.statfs(lu_context, &sbattr) < 0) - return -EPERM; - } - -#if FUSE_MAJOR_VERSION < 2 - stbuf->blocks = sbattr.sb_bytes / 512; - stbuf->blocks_free = sbattr.sb_bytes_available / 512; - stbuf->files = sbattr.sb_files; - stbuf->files_free = sbattr.sb_ffree; - stbuf->namelen = 255; -#else - (void) path; - stbuf->f_bsize = 512; - stbuf->f_blocks = sbattr.sb_bytes / 512; - stbuf->f_bfree = sbattr.sb_bytes_free / 512; - stbuf->f_bavail = sbattr.sb_bytes_available / 512; - stbuf->f_files = sbattr.sb_files; - stbuf->f_ffree = sbattr.sb_ffree; - stbuf->f_namelen = 255; -#endif - return 0; -} - -static int load_credentials(void) -{ - static char buf[BUF_SIZE]; - char srch_str[MAX_LEN + 4]; - long int uid, gid; - int res, offset, chunk, readlen; - char *c; - - TRACE("loading remote credentials for %s", lu_cred.user); - - if((!lu_fops.open) || (!lu_fops.read) || (!lu_fops.release)){ - WARN("unsupported operation"); - return -1;; - } - - lu_cred.uid = lu_cred.gid = -1; - - if(lu_fops.open(lu_context, PASSWD, O_RDONLY) < 0){ - TRACE("could not open %s", PASSWD); - return -1; - } - - sprintf(srch_str, "\n%s:", lu_cred.user); - chunk = strlen(srch_str) + 64; - readlen = BUF_SIZE - chunk - 1; - - memset(buf, 32, chunk); - offset = 0; - - do{ - res = lu_fops.read(lu_context, PASSWD, offset, readlen, (buf + chunk)); - if(res > 0){ - *(buf + chunk + res) = 0; - - if((c = strstr(buf, srch_str))){ - TRACE("username found!"); - if(!(c = strchr(c + strlen(srch_str), ':'))){ - TRACE("separator not found!"); - }else{ - if(sscanf(c , ":%li:%li:", &uid, &gid) != 2){ - TRACE("uid/gid not found!"); - }else{ - TRACE("uid: %li, gid: %li", uid, gid); - - lu_cred.uid = uid; - lu_cred.gid = gid; - - break; - } - } - } - - memcpy(buf, buf + BUF_SIZE - chunk - 1, chunk); - offset += res; - } - }while(res == readlen); - - lu_fops.release(lu_context, PASSWD); - - if(res <= 0){ - TRACE("read failed"); - return -1; - } - - - if(lu_fops.open(lu_context, GROUP, O_RDONLY) < 0){ - TRACE("could not open %s", GROUP); - return -1; - } - - sprintf(srch_str, ":%li:", (long)lu_cred.gid); - chunk = strlen(srch_str) + 64; - readlen = BUF_SIZE - chunk - 1; - - memset(buf, 32, chunk); - offset = 0; - - do{ - res = lu_fops.read(lu_context, GROUP, offset, readlen, (buf + chunk)); - if(res > 0){ - *(buf + chunk + res) = 0; - - if((c = strstr(buf, srch_str))){ - TRACE("group found!"); - if(!(c = (char*)memrchr(buf, '\n', (c - buf)))){ - TRACE("separator not found!"); - }else{ - *(strchr(c, ':')) = 0; - if(strlen(c + 1) >= MAX_LEN){ - TRACE("groupname too long"); - }else{ - strcpy(lu_cred.group, c + 1); - TRACE("group: %s", lu_cred.group); - break; - } - } - } - - memcpy(buf, buf + BUF_SIZE - chunk - 1, chunk); - offset += res; - } - }while(res == readlen); - - lu_fops.release(lu_context, GROUP); - - if(res <= 0){ - TRACE("read failed"); - return -1; - } - - return 0; -} - -static int lufis_init(int *argcp, char **argvp[]) -{ - int argc = *argcp; - char **argv = *argvp; - int res; - char *opts; - const char *fs_name; - - if(argc < 2) { - fprintf(stderr, "usage: %s opts\n", argv[0]); - return -1; - } - - INIT_LIST_HEAD(&lu_cfg); - opts = argv[1]; - if(lu_opt_parse(&lu_cfg, "MOUNT", opts) < 0){ - ERROR("could not parse options!"); - return -1; - } - - lu_opt_loadcfg(&lu_cfg, "/etc/lufsd.conf"); - - (*argcp)--; - (*argvp)++; - argv[1] = argv[0]; - - - lu_cache = lu_cache_create(&lu_cfg); - if(!lu_cache) - return -1; - - if(!(fs_name = lu_opt_getchar(&lu_cfg, "MOUNT", "fs"))){ - ERROR("you need to specify a file system!"); - return -1; - } - - res = get_filesystem(fs_name); - if(res == -1) - return -1; - - if(!(lu_context = lu_fops.init(&lu_cfg, lu_cache, &lu_cred, &lu_global_ctx))) { - ERROR("could not initialize file system!"); - return -1; - } - - res = lu_fops.mount(lu_context); - if(res) { - if(load_credentials() < 0) - TRACE("could not load credentials."); - else - TRACE("credentials loaded."); - } else { - WARN("fs mount failed..."); - } - - return 0; -} - -static void lufis_cleanup(void) -{ - if(lu_fops.umount) - lu_fops.umount(lu_context); - lu_fops.free(lu_context); -} - -static struct fuse_operations lu_oper = { - .getattr = lu_getattr, - .readlink = lu_readlink, - .getdir = lu_getdir, - .mknod = lu_mknod, - .mkdir = lu_mkdir, - .symlink = lu_symlink, - .unlink = lu_unlink, - .rmdir = lu_rmdir, - .rename = lu_rename, - .link = lu_link, - .chmod = lu_chmod, - .chown = lu_chown, - .truncate = lu_truncate, - .utime = lu_utime, - .open = lu_open, - .read = lu_read, - .write = lu_write, - .release = lu_release, - .statfs = lu_statfs, -}; - -int main(int argc, char *argv[]) -{ - int res; - - res = lufis_init(&argc, &argv); - if(res == -1) - exit(1); - - fuse_main(argc, argv, &lu_oper); - lufis_cleanup(); - - return 0; -} diff --git a/lufis/options.c b/lufis/options.c deleted file mode 100644 index b8b7b3a..0000000 --- a/lufis/options.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - * options.c - * Copyright (C) 2002 Florin Malita <mali@go.ro> - * - * This file is part of LUFS, a free userspace filesystem implementation. - * See http://lufs.sourceforge.net/ for updates. - * - * LUFS is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * LUFS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <lufs/fs.h> - -#include "list.h" - -struct option { - char *key; - char *value; - struct list_head list; -}; - -struct domain { - char *name; - struct list_head properties; - struct list_head list; -}; - - -static void -trim(char *buf){ - int b,e; - - if(!buf[0]) - return; - - for(b = 0; (buf[b] == ' ') || (buf[b] == '\t'); b++); - for(e = strlen(buf) - 1; (e >= 0) && ((buf[e] == ' ') || (buf[e] == '\t')); e--); - if(e < 0) - e = strlen(buf) - 1; - - buf[e + 1] = 0; - - if(b) - strcpy(buf, &buf[b]); - -} - -static struct domain* -find_domain(struct list_head *conf, char *name){ - struct list_head *p; - struct domain *cls; - - list_for_each(p, conf){ - cls = list_entry(p, struct domain, list); - if(!strcmp(name, cls->name)){ - TRACE("domain found"); - return cls; - } - } - - return NULL; -} - -int -lu_opt_loadcfg(struct list_head *conf, char *file){ - struct domain *class; - struct option *prop; - FILE *f; - static char buf[1024]; - char *i, *j; - char *cls, *key, *val; - - TRACE("loading config from %s", file); - - if(!(f = fopen(file, "r"))){ - WARN("could not open file for reading!"); - return -1; - } - - while(fgets(buf, 1024, f)){ - - buf[strlen(buf) - 1] = 0; - - if((i = strchr(buf, '#'))) - *i = 0; - - if((i = strchr(buf, '='))){ - if((j = strstr(buf, "::"))){ - cls = buf; - key = j + 2; - val = i + 1; - - *i = 0; - *j = 0; - - trim(cls); - trim(key); - trim(val); - - TRACE("class: #%s#", cls); - TRACE("key: #%s#", key); - TRACE("val: #%s#", val); - - if(!(class = find_domain(conf, cls))){ - TRACE("class not found, creating..."); - - if(!(class = malloc(sizeof(struct domain)))){ - WARN("out of mem!"); - break; - } - - memset(class, 0, sizeof(struct domain)); - - if(!(class->name = malloc(strlen(cls) + 1))){ - WARN("out of mem!"); - free(class); - break; - } - - strcpy(class->name, cls); - INIT_LIST_HEAD(&class->properties); - - list_add(&class->list, conf); - } - - if(!(prop = malloc(sizeof(struct option)))){ - WARN("out of mem!"); - break; - } - - if(!(prop->key = malloc(strlen(key) + 1))){ - WARN("out of mem!"); - free(prop); - break; - } - - if(!(prop->value = malloc(strlen(val) + 1))){ - WARN("out of mem!"); - free(prop->key); - free(prop); - break; - } - - strcpy(prop->key, key); - strcpy(prop->value, val); - - list_add(&prop->list, &class->properties); - } - } - - } - - - fclose(f); - - return 0; -} - - -const char* -lu_opt_getchar(struct list_head *conf, char *cls, char *key){ - struct domain *class; - struct option *prop; - struct list_head *p; - - TRACE("retrieving %s::%s", cls, key); - - if(!(class = find_domain(conf, cls))) - return NULL; - - list_for_each(p, &class->properties){ - prop = list_entry(p, struct option, list); - - if(!strcmp(key, prop->key)){ - TRACE("key found"); - return prop->value; - } - } - - TRACE("key not found"); - - return NULL; -} - -int -lu_opt_getint(struct list_head *conf, char *domain, char *key, long int *result, int base){ - char *end; - const char *val; - long int res; - - if(!(val = lu_opt_getchar(conf, domain, key))) - return -1; - - res = strtol(val, &end, base); - - if(*end) - return -1; - - *result = res; - return 0; -} - -int -lu_opt_parse(struct list_head *conf, char *domain, char *opts){ - struct domain *class; - struct option *prop; - char *p, *sep; - - if(!(class = find_domain(conf, domain))){ - TRACE("domain not found, creating..."); - - if(!(class = malloc(sizeof(struct domain)))){ - WARN("out of mem!"); - return -1; - } - - memset(class, 0, sizeof(struct domain)); - - if(!(class->name = malloc(strlen(domain) + 1))){ - WARN("out of mem!"); - free(class); - return -1; - } - - strcpy(class->name, domain); - INIT_LIST_HEAD(&class->properties); - - list_add(&class->list, conf); - } - - for(p = strtok(opts, ","); p; p = strtok(NULL, ",")){ - if(!strstr(p, "password")) - TRACE("option: %s", p); - - if(!(prop = malloc(sizeof(struct option)))){ - WARN("out of mem!"); - return -1; - } - - if((sep = strchr(p, '='))) - *sep = 0; - - if(!(prop->key = malloc(strlen(p) + 1))){ - WARN("out of mem!"); - free(prop); - return -1; - } - strcpy(prop->key, p); - - if(sep){ - TRACE("option with parameter"); - - if(!(prop->value = malloc(strlen(sep + 1) + 1))){ - WARN("out of mem!"); - free(prop->key); - free(prop); - return -1; - } - strcpy(prop->value, sep + 1); - - if(strstr(p, "password")){ - TRACE("hiding password..."); - memset(sep + 1, ' ', strlen(sep + 1)); - } - }else{ - TRACE("flag"); - - if(!(prop->value = malloc(2))){ - WARN("out of mem!"); - free(prop->key); - free(prop); - return -1; - } - strcpy(prop->value, ""); - - } - - list_add(&prop->list, &class->properties); - - } - - return 0; -} - - |