diff options
Diffstat (limited to 'unionfs')
-rw-r--r-- | unionfs/AUTHORS | 2 | ||||
-rw-r--r-- | unionfs/BUGS | 5 | ||||
-rw-r--r-- | unionfs/CAVEAT | 25 | ||||
-rw-r--r-- | unionfs/COPYING | 2 | ||||
-rw-r--r-- | unionfs/ChangeLog | 229 | ||||
-rw-r--r-- | unionfs/Makefile | 81 | ||||
-rw-r--r-- | unionfs/README | 92 | ||||
-rw-r--r-- | unionfs/TODO | 7 | ||||
-rw-r--r-- | unionfs/lib.c | 280 | ||||
-rw-r--r-- | unionfs/lib.h | 82 | ||||
-rw-r--r-- | unionfs/lnode.c | 184 | ||||
-rw-r--r-- | unionfs/lnode.h | 77 | ||||
-rw-r--r-- | unionfs/main.c | 134 | ||||
-rw-r--r-- | unionfs/ncache.c | 151 | ||||
-rw-r--r-- | unionfs/ncache.h | 59 | ||||
-rw-r--r-- | unionfs/netfs.c | 1170 | ||||
-rw-r--r-- | unionfs/node.c | 555 | ||||
-rw-r--r-- | unionfs/node.h | 135 | ||||
-rw-r--r-- | unionfs/options.c | 225 | ||||
-rw-r--r-- | unionfs/options.h | 53 | ||||
-rw-r--r-- | unionfs/pattern.c | 131 | ||||
-rw-r--r-- | unionfs/pattern.h | 53 | ||||
-rw-r--r-- | unionfs/stow-mutations.h | 27 | ||||
-rw-r--r-- | unionfs/stow-priv.h | 45 | ||||
-rw-r--r-- | unionfs/stow.c | 328 | ||||
-rw-r--r-- | unionfs/stow.h | 30 | ||||
-rw-r--r-- | unionfs/ulfs.c | 321 | ||||
-rw-r--r-- | unionfs/ulfs.h | 75 | ||||
-rw-r--r-- | unionfs/unionfs.h | 90 | ||||
-rw-r--r-- | unionfs/update.c | 97 | ||||
-rw-r--r-- | unionfs/update.h | 28 | ||||
-rw-r--r-- | unionfs/version.h | 29 |
32 files changed, 0 insertions, 4802 deletions
diff --git a/unionfs/AUTHORS b/unionfs/AUTHORS deleted file mode 100644 index 1cc95387..00000000 --- a/unionfs/AUTHORS +++ /dev/null @@ -1,2 +0,0 @@ -* Moritz Schulte <moritz@duesseldorf.ccc.de> -* Gianluca Guida <glguida@gmail.com> diff --git a/unionfs/BUGS b/unionfs/BUGS deleted file mode 100644 index 56209654..00000000 --- a/unionfs/BUGS +++ /dev/null @@ -1,5 +0,0 @@ -Known bugs: - - * unionfs hangs when looking up recursive links, which point into the - unionfs - * emacs hangs when trying to save files in unionfs diff --git a/unionfs/CAVEAT b/unionfs/CAVEAT deleted file mode 100644 index dbb88136..00000000 --- a/unionfs/CAVEAT +++ /dev/null @@ -1,25 +0,0 @@ -While using unionfs, you could experience more permission errors or -difficult or impossible file or directory deletion. This is a list of -things that can happen. - -WARNINGS: - -- If the translator is run as by an unpriviledged user, other users will fail -to create files or directory, since the translator won't be able to change -the ownership of the file. - - -PROBLEMS: - -- If there's a name conflict in underlying filesystems between directories -and files -- say that "foo" is a directory in underlying filesystem "a" while -is a file in the underlying filesystem "b" -- then unionfs will be unable to -delete this entry. This is a structural BUG (there's no clean way to solve it), -and should be fixed. - -- If there's a name conflict in underlying filesystems between directories -(or between files), and the user has not permission to delete _ALL_ the -entries -- e.g. one hidden entry is read-only -- then he will get an EPERM -even if permissions seems ok. This is a structural BUG (there's no clean way -to solve it), and should be fixed. - diff --git a/unionfs/COPYING b/unionfs/COPYING deleted file mode 100644 index 5cc9607b..00000000 --- a/unionfs/COPYING +++ /dev/null @@ -1,2 +0,0 @@ -This program is licensed under the terms of the GNU General Public -License. diff --git a/unionfs/ChangeLog b/unionfs/ChangeLog deleted file mode 100644 index d8a29618..00000000 --- a/unionfs/ChangeLog +++ /dev/null @@ -1,229 +0,0 @@ -2006-06-21 Alfred M. Szmidt <ams@gnu.org> - - * lib.c (for_each_subdir): Revert previous change. Reported by - Aanjhan Ranganathan <aanjhan@tuxmaniac.com>. - -2006-04-13 Ben Asselstine <benasselstine@gmail.com> - - * options.c (argp_parse_common_options) - (argp_parse_startup_options, parsing_startup_options_finished) - (argp_common_options, argp_startup_options) - (argp_parser_common_options, argp_parser_startup_options) - (argp_children_runtime): Make these static. - * ulfs.c (ulfs_create, ulfs_destroy, ulfs_install) - (ulfs_uninstall, ulfs_get_path): Likewise. - - * ulfs.h (ulfs_get_path): Remove declaration. - - * lib.c (for_each_subdir): Remove unused variables. - -2005-06-27 Ben Asselstine <benasselstine@gmail.com> - - * ulfs.c (ulfs_install): Rewrote to allow insertions of - filesystems based on priority. - (ulfs_register): Added new argument 'priority'. Set the priority - value in ulfs structure. - * ulfs.h (ulfs): Added 'priority' field to struct. - Updated ulfs_register declaration. - * netfs.c (netfs_append_args): Appending new priority option. - * stow.c (stow_privdata): Added 'priority' field to struct. - (stow_diradd): Added new 'priority' argument. Fill priority field - of 'mypriv'. - (_stow_scanstowentry): Changed caller to ulfs_register. - (_stow_registermatchingdirs): Likewise. - * options.c (arg_common_options): Added entries for OPT_PRIORITY - and OPT_ADD. - (arg_parse_common_options): Handle OPT_PRIORITY and OPT_ADD - case. Renamed 'ulfs_removed' to 'ulfs_mode'. New variable - 'ulfs_priority'. Changed caller to 'stow_diradd'. Changed caller - to 'ulfs_register'. - * options.h (OPT_ADD, OPT_PRIORITY, OPT_LONG_ADD) - (OPT_LONG_PRIORITY, ULFS_MODE_ADD, ULFS_MODE_REMOVE): New - declarations. - -2005-06-13 Gianluca Guida <glguida@gmail.com> - - * main.c (main): Set properly netfs_root_node permissions when - underlying node is not a file - Reported by Alfred M. Szmidt. - -2005-05-31 Gianluca Guida <glguida@gmail.com> - - * node.c (node_unlink_file): Use lookup to figure out whether a file - exists or not, or it will fail on read-only filesystems. - Reported by Ben Asselstine. - -2005-05-30 Gianluca Guida <glguida@gmail.com> - - * AUTHORS: Added myself in the list. - * README: Added sections "Introduction" and "Stowing Feature". - * options.c (argp_program_bug_address): Changed address. - - * lib.c (for_each_subdir): When call to stat() fails free "name" - and continue the loop, instead of returning error. Return 0 at the - end of the loop. - (for_each_subdir_priv): Likewise. - - * stow.c (_stow_registermatchingdirs): Don't return error when - patternlist_match returns false. Free filepath before returning - error when ulfs_register fails. - - * ulfs.c (ulfs_register): Removed bogus fprintf. - -2005-05-29 Gianluca Guida <glguida@gmail.com> - - * Makefile: Added support for building mig stubs for stow feature. - (OBJS): Added update.o - (unionfs): Added fs_notifyServer.o to final linking. - (unionfs.static): Likewise. - (fs_notifyServer.o): New rule. - (clean): Remove fs_notifyServer.c and fs_notify_S.h when cleaning. - - * netfs.c (OFFSET_T): New macro. - (_get_node_size): New function. - (netfs_validate_stat): Call _get_node_size for root node. - - * node.c (node_unlink_file): New variable "removed". Return ENOENT - if no files unlinked. - - * ulfs.c: Include "unionfs", fcntl.h and "lib.h". - (ulfs_install, ulfs_uninstall): Rewritten. - (ulfs_for_each_under_priv, ulfs_check): New function. - (ulfs_register): Check that argument is a directory. - * ulfs.h: Removed field "prevp" from struct ulfs. - (ulfs_check): New declaration. - (ulfs_iterate, ulfs_iterate_unlocked): Don't use ulfs_chain_end. - * lib.c (check_dir): New function. - * lib.h: Added declaration of check_dir. - - * stow.c: Include "update.h", cthreads.h, hurd/port.h, - "stow-priv.h" and "ncache.h". - (stow_privdata) Added "lock" to struct. Removed "remove" to - struct. - (_stow_registermatchingdirs): Removed call to - debug_msg_send. Removed call to ulfs_unregister when - privdata->remove is set. Return error on ulfs_register failure - instead of exiting the program. - (_stow_scanstowentry): Removed call to ulfs_unregister when - privdata->remove is set. Lock privdata->lock and unlock at end. - (stow_port_bucket, stow_port_class): New variables. - (_stow_notify_init, begin_using_notify_ports) - (end_using_notify_ports, stow_S_file_changed, stow_S_dir_changed) - (_stow_notify_thread, stow_init): New functions. - (stow_diradd): Allocate "mypriv" instead of using stack. Call - _stow_notify_init. - * stow.h: Include "pattern.h". Declare - stow_init. - - * stow-priv.h: New file. - * stow-mutations.h: Likewise. - * update.c: Likewise. - * update.h: Likewise. - - * options.c: Include "update.h". - (argp_parse_common_options): Check stow_diradd return. Call - root_update_schedule instead of node_init_root and ncache_reset - when parsing_startup_options_finished is set. - - * main.c: Include "stow.h". Include "update.h". - (main): Call stow_init. Call root_update_init. - -2005-05-25 Gianluca Guida <glguida@gmail.com> - - * CAVEAT: New file. - * README: Rewritten. - - * netfs.c (netfs_attempt_unlink): Use fshelp_checkdirmod - instead of fshelp_access. - (netfs_attempt_mkdir): Implemented. - (netfs_attempt_rmdir): Likewise. - (netfs_attempt_create_file_reduced): Likewise. - Fixed typo in a comment. - * node.c (node_dir_remove): New function. - (node_dir_create): Likewise. - * node.h (node_dir_create): New declaration. - (node_dir_remove): Likewise. - - * lib.c (for_each_file_priv): Removed unused variables - "name" and "filestat". - -2005-05-24 Gianluca Guida <glguida@gmail.com> - - * netfs.c (netfs_attempt_unlink): Implemented. - (netfs_attempt_create_file_reduced): New function. - (netfs_S_dir_lookup): Initialized variable "error". - Added support for file creation. - (netfs_attempt_lookup_improved): Changed instruction flow, - return on error not continue on non-error. - Check user permission to open file before returning port. - * node.c (node_create, node_update, node_lookup_file, node_ulfs_free) - (node_ulfs_init, node_entries_get, node_create_root, node_init_root): - Changed instruction flow, return on error not continue on non-error. - (node_unlink_file): New function. - * node.h (node_unlink_file): New declaration. - (node_ulfs_iterate_reverse_unlocked): New macro. - - * options.c (argp_parse_common_options): Removed debugging fprintf. - -2005-01-31 Gianluca Guida <glguida@gmail.com> - - * stow.c (stow_diradd): Handle --stow argument with missing / - correctly. - -2005-01-31 Gianluca Guida <glguida@gmail.com> - - * pattern.c: New file. - * stow.c: Likewise. - * pattern.h: Likewise. - * stow.h: Likewise. - * Makefile (OBJS): Added pattern.o and stow.o - - * node.c: Initialize variable err. - * lib.c (file_lookup): Initialize variable err. - Include <fcntl.h>. - (make_filepath, for_each_subdir, for_each_subdir_priv) - (for_each_file_priv): New function. - * lib.h (make_filepath, for_each_subdir, for_each_subdir_priv): New - declaration. - * options.c: Include "pattern.h". - Include "stow.h". - (arg_common_options): Added entries for OPT_STOW and OPT_PATTERN. - (argp_parse_common_options): Handle OPT_STOW and OPT_PATTERN case. - * options.h (OPT_PATTERN, OPT_STOW, OPT_LONG_PATTERN, OPT_LONG_STOW): - New declarations. - -2003-07-05 Jeroen Dekkers <jeroen@dekkers.cx> - - * Makefile: Rewrite. - - * netfs.c (netfs_attempt_create_file): Unlock DIR. - (netfs_attempt_mkfile): Likewise. - -2002-12-09 Moritz Schulte <moritz@duesseldorf.ccc.de> - - * lib.h: Fix pointer arg. - * lib.c (dir_entries_get): Likewise. - * lib.c (dir_entries_get): Fix typo. - (dir_entries_get): Change type of data_size to size_t. - * node.c (node_entries_get): Change type of dirent_data_size to - size_t. - -2002-12-08 Moritz Schulte <moritz@duesseldorf.ccc.de> - - * BUGS: Remove the memory-leak bug. - * lib.c: Include <sys/mman.h>. - * node.c: Include <sys/mman.h>. - (node_entries_get): munmap dirent_data as returned by - dir_entries_get. - (node_entries_get): New variable: int dirent_data_size. - * lib.c (dir_entries_get): New argument: int *dirent_data_size. - (dir_entries_get): Do not forget to munmap DATA if something goes - wrong. - * lib.h: Update dir_entries_get declaration. - - * node.c (node_create_root): call lnode_destroy, if node_create - failed, not if lnode_create failed. Reported by Richard Smith. - - Copyright 2002, 2003, 2005 Free Software Foundation, Inc. - Copying and distribution of this file, with or without modification, are - permitted provided the copyright notice and this notice are preserved. diff --git a/unionfs/Makefile b/unionfs/Makefile deleted file mode 100644 index b1800722..00000000 --- a/unionfs/Makefile +++ /dev/null @@ -1,81 +0,0 @@ -# Hurd unionfs -# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. -# Written by Jeroen Dekkers <jeroen@dekkers.cx>. -# -# 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. - -CPP = gcc -E -x c -MIGCOM = mig -cc cat - /dev/null - -CFLAGS += -Wall -g -O2 -D_FILE_OFFSET_BITS=64 -std=gnu99 \ - -DDEBUG -LDFLAGS += -lnetfs -lfshelp -liohelp -lthreads \ - -lports -lihash -lshouldbeinlibc -OBJS = main.o node.o lnode.o ulfs.o ncache.o netfs.o \ - lib.o options.o pattern.o stow.o update.o - -MIGCOMSFLAGS = -prefix stow_ -fs_notify-MIGSFLAGS = -imacros ./stow-mutations.h - - -# How to build RPC stubs - -# We always need this setting, because libc does not include the bogus names. -MIGCOMFLAGS := -subrprefix __ - -# User settable variables: -# mig-sheader-prefix prepend to foo_S.h for name of foo.defs stub header -# MIGSFLAGS flags to CPP when building server stubs and headers -# foo-MIGSFLAGS same, but only for interface `foo' -# MIGCOMSFLAGS flags to MiG when building server stubs and headers -# foo-MIGCOMSFLAGS same, but only for interface `foo' -# MIGUFLAGS flags to CPP when building user stubs and headers -# foo-MIGUFLAGS same, but only for interface `foo' -# MIGCOMUFLAGS flags to MiG when building user stubs and headers -# foo-MIGCOMUFLAGS same, but only for interface `foo' -# CPPFLAGS flags to CPP - -# Implicit rules for building server and user stubs from mig .defs files. - -# These chained rules could be (and used to be) single rules using pipes. -# But it's convenient to be able to explicitly make the intermediate -# files when you want to deal with a problem in the MiG stub generator. -$(mig-sheader-prefix)%_S.h %Server.c: %.sdefsi - $(MIGCOM) $(MIGCOMFLAGS) $(MIGCOMSFLAGS) $($*-MIGCOMSFLAGS) \ - -sheader $(mig-sheader-prefix)$*_S.h -server $*Server.c \ - -user /dev/null -header /dev/null < $< - -%.sdefsi: %.defs - $(CPP) $(CPPFLAGS) $(MIGSFLAGS) $($*-MIGSFLAGS) -DSERVERPREFIX=S_ $< -o $@ - -vpath %.defs $(prefix)/include/hurd - - - -all: unionfs - -unionfs: $(OBJS) fs_notifyServer.o - $(CC) -o $@ $(OBJS) fs_notifyServer.o $(LDFLAGS) - -unionfs.static: $(OBJS) fs_notifyServer.o - $(CC) -static -o $@ $(OBJS) fs_notifyServer.o $(LDFLAGS) - -fs_notifyServer.o: fs_notifyServer.c - -.PHONY: clean - -clean: - rm -rf *.o fs_notifyServer.c fs_notify_S.h unionfs diff --git a/unionfs/README b/unionfs/README deleted file mode 100644 index 1849f4d9..00000000 --- a/unionfs/README +++ /dev/null @@ -1,92 +0,0 @@ -This is the unionfs translator for the GNU Hurd. - -The unionfs translator was originally written by Moritz Schulte -<moritz@duesseldorf.ccc.de> and currently mantained by Gianluca Guida -<glguida@gmail.com>. - - - -Introduction. - -An unionfs is a filesystems that joins many filesystems into one, meaning -that you can see into an "unionfs" all files contained in the filesystems -that are part of the union. - -When two or more directories with the same path are found in different -filesystems, their content is joined. -When two or more files with the same path are found in different filesystems, -unionfs has to solve this conflict. See below (Internals section) for -information on what this implementation does in such case. - -Example: -To join "foo/" "bar/" and "baz/" in the directory "quux/", just do: - - settrans -capfg quux/ /hurd/unionfs foo/ bar/ baz/ - -If you want to join even quux/ contents in the union itself, add -u as a -translator argument. -You can add filesystems at run-time with the fsysopts command. - - - -Stowing feature. - -This unionfs implements stowing feature, i.e. the translator will watch a -directory, called 'stow', that contains the directories to unite. -When a directory is added or removed in the stow, it will be added to or -removed from the unionfs. - -Example: -To use "/stow" as the stow for the directory "foo/", do: - - settrans -capfg foo/ /hurd/unionfs --stow=/stow - -All directories contained in /stow/ will then be joined together in foo/; -you can delete or add directory at run-time and you will see unionfs adding -or removing files in foo/ automatically. - -Another interesting feature of stow support of unionfs is the pattern matching -option. -For example, by using: - - settrans -capfg foo/ /hurd/unionfs -m bar --stow=/stow - -You will get joined in foo/ all sub-sub-directories of /stow matching "bar", -i.e. /stow/*/bar/; pattern matching will be done too in run-time added stow -subdirectories. -Furthermore, you can specify more complex matching pattern to the option, -like -m bar\* (to get all stow's sub-sub-directories beginning with "bar") -or specify multiple -m options. - -Example: -This command - - settrans -capfg /myfaketree/bin -m bin -m sbin --stow=/stow - -will join in /myfaketree/bin all files that are in /stow/*/bin and -/stow/*/sbin. It is equivalent to: - - settrans -capfg /myfaketree/bin -m [s]bin --stow=/stow - - - -Internals. - -This `unionfs' translator is simple, but it is definitely not a joke. - -It works by keeping in memory a dynamically updated tree of nodes, each -node representing a directory in the unionfs. A node contains an array -of ports that give access to the corrisponding directory in the underlying -filesystems. - -On lookup, the first entry found is chosen. Thus, it is very important the -underlying filesystems ordering, since the first underlying filesystem will -be the first one to be searched during lookups, and it is the filesystem -where new files and directories are written into. - -At the moment, underlying filesystem ordering is set by option ordering. - -See CAVEAT for other unexpected behaviour that could happen. - - -Please send all bug reports to Gianluca Guida <glguida@gmail.com>. diff --git a/unionfs/TODO b/unionfs/TODO deleted file mode 100644 index 790221f2..00000000 --- a/unionfs/TODO +++ /dev/null @@ -1,7 +0,0 @@ -Todo list for unionfs: - - * implement filesystem notification support; - only update nodes when needed - * cache dirents (?) - * verify that the locking is correct - * increase performance diff --git a/unionfs/lib.c b/unionfs/lib.c deleted file mode 100644 index 0423c1bc..00000000 --- a/unionfs/lib.c +++ /dev/null @@ -1,280 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - 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. */ - -#define _GNU_SOURCE - -#include <hurd/netfs.h> -#include <error.h> -#include <dirent.h> -#include <errno.h> -#include <sys/mman.h> -#include <stddef.h> - -#include "lib.h" - -/* Lock, which must be held, during printing of debugging - messages. */ -struct mutex debug_msg_lock = MUTEX_INITIALIZER; - -/* Returns no error if PATH points to a directory. */ -error_t check_dir (char *path) -{ - struct stat filestat; - error_t err = 0; - - err = stat (path, &filestat); - if (err) - return err; - - if (!S_ISDIR (filestat.st_mode)) - return ENOTDIR; - - return 0; -} - -/* Fetch directory entries for DIR; store the raw data as returned by - the dir_readdir RPC in *DIRENT_DATA, the size of *DIRENT_DATA in - *DIRENT_DATA_SIZE and a list of pointers to the dirent structures - in *DIRENT_LIST. */ -error_t -dir_entries_get (file_t dir, char **dirent_data, - size_t *dirent_data_size, struct dirent ***dirent_list) -{ - error_t err; - size_t data_size; - int entries_num; - char *data; - - err = dir_readdir (dir, &data, &data_size, 0, -1, 0, &entries_num); - if (! err) - { - struct dirent **list; - - list = malloc (sizeof (struct dirent *) * (entries_num + 1)); - if (list) - { - struct dirent *dp; - int i; - - for (i = 0, dp = (struct dirent *) data; - i < entries_num; - i++, dp = (struct dirent *) ((char *) dp + dp->d_reclen)) - *(list + i) = dp; - *(list + i) = NULL; - - *dirent_data = data; - *dirent_data_size = data_size; - *dirent_list = list; - } - else - { - munmap (data, data_size); - err = ENOMEM; - } - } - return err; -} - -/* Lookup the file named NAME beneath DIR (or the cwd, if DIR is not a - valid port. Try to open with FLAGS0 first, and if that fails with - FLAGS1; MODE is the mode to user for newly created files. On - success, stat the looked up port and store it in *PORT, the - according stat information are stored in *STAT. */ -error_t -file_lookup (file_t dir, char *name, int flags0, int flags1, - int mode, file_t *port, struct stat *stat) -{ - error_t err = 0; - file_t p; - struct stat s; - - file_t do_file_lookup (file_t d, char *n, int f, int m) - { - if (port_valid (d)) - p = file_name_lookup_under (d, n, f, m); - else if (errno == EACCES) - p = file_name_lookup (n, f, m); - return p; - } - - p = do_file_lookup (dir, name, flags0, mode); - if (! port_valid (p)) - p = do_file_lookup (dir, name, flags1, mode); - - if (port_valid (p)) - { - if (stat) - { - err = io_stat (p, &s); - if (err) - port_dealloc (p); - } - } - else - err = errno; - - if (! err) - { - *port = p; - if (stat) - *stat = s; - } - return err; -} - -#include <fcntl.h> - -char * -make_filepath (char *path, char *filename) -{ - int length; - char *filepath; - - length = strlen (path) + strlen (filename) + 2; - filepath = malloc (length); - if (filepath == NULL) - return NULL; - - strncpy (filepath, path, length); - strncat (filepath, filename, strlen (filename)); - - return filepath; -} - -error_t -for_each_subdir (char *path, error_t (*func) (char *, char *)) -{ - struct dirent **dirent, **dirent_list; - char *dirent_data; - size_t dirent_data_size; - file_t dir; - error_t err; - - dir = file_name_lookup (path, O_READ, 0); - - err = dir_entries_get (dir, &dirent_data, &dirent_data_size, &dirent_list); - if (err) - return err; - - for (dirent = dirent_list; (! err) && (*dirent); dirent++) - { - char *name; - struct stat filestat; - - if ((!strcmp ((*dirent)->d_name, ".")) - || (!strcmp ((*dirent)->d_name, ".."))) - continue; - - name = make_filepath (path, (*dirent)->d_name); - - err = stat (name, &filestat); - - free (name); - - if (err) - { - fprintf (stderr, "unionfs: couldn't stat %s%s\n", - path, (*dirent)->d_name); - continue; - } - - if (!S_ISDIR(filestat.st_mode)) - continue; - - func ((*dirent)->d_name, path); - } - - return 0; -} - -error_t -for_each_subdir_priv (char *path, error_t (*func) (char *, char *, void *), - void *priv) -{ - struct dirent **dirent, **dirent_list; - char *dirent_data; - size_t dirent_data_size; - file_t dir; - error_t err; - - dir = file_name_lookup (path, O_READ, 0); - - err = dir_entries_get (dir, &dirent_data, &dirent_data_size, &dirent_list); - if (err) - return err; - - for (dirent = dirent_list; (!err) && (*dirent); dirent++) - { - char *name; - struct stat filestat; - - if ((!strcmp ((*dirent)->d_name, ".")) - || (!strcmp ((*dirent)->d_name, ".."))) - continue; - - name = make_filepath (path, (*dirent)->d_name); - - err = stat (name, &filestat); - - free (name); - - if (err) - { - fprintf (stderr, "unionfs: couldn't stat %s%s\n", - path, (*dirent)->d_name); - continue; - } - - if (!S_ISDIR(filestat.st_mode)) - continue; - - func ((*dirent)->d_name, path, priv); - } - - return 0; -} - -error_t -for_each_file_priv (char *path, error_t (*func) (char *, char *, void *), - void *priv) -{ - struct dirent **dirent, **dirent_list; - char *dirent_data; - size_t dirent_data_size; - file_t dir; - error_t err; - - dir = file_name_lookup (path, O_READ, 0); - - err = dir_entries_get (dir, &dirent_data, &dirent_data_size, &dirent_list); - if (err) - return err; - - for (dirent = dirent_list; (!err) && (*dirent); dirent++) - { - - if ((!strcmp ((*dirent)->d_name, ".")) - || (!strcmp ((*dirent)->d_name, ".."))) - continue; - - func ((*dirent)->d_name, path, priv); - } - - return err; -} diff --git a/unionfs/lib.h b/unionfs/lib.h deleted file mode 100644 index be9a2192..00000000 --- a/unionfs/lib.h +++ /dev/null @@ -1,82 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - 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. */ - -#ifndef INCLUDED_LIB_H -#define INCLUDED_LIB_H - -#include <hurd.h> -#include <dirent.h> -#include <stddef.h> - -/* Returned directory entries are aligned to blocks this many bytes - long. Must be a power of two. */ -#define DIRENT_ALIGN 4 -#define DIRENT_NAME_OFFS offsetof (struct dirent, d_name) - -/* Length is structure before the name + the name + '\0', all padded - to a four-byte alignment. */ -#define DIRENT_LEN(name_len) \ - ((DIRENT_NAME_OFFS + (name_len) + 1 + (DIRENT_ALIGN - 1)) \ - & ~(DIRENT_ALIGN - 1)) - -/* These macros remove some Mach specific code from the server - itself. */ -#define port_null MACH_PORT_NULL -#define port_dealloc(p) mach_port_deallocate (mach_task_self (), (p)) -#define port_valid(p) ((p) != port_null) - -/* Fetch directory entries for DIR; store the raw data as returned by - the dir_readdir RPC in *DIRENT_DATA, the size of *DIRENT_DATA in - *DIRENT_DATA_SIZE and a list of pointers to the dirent structures - in *DIRENT_LIST. */ -error_t dir_entries_get (file_t dir, char **dirent_data, - size_t *dirent_data_size, - struct dirent ***dirent_list); - -char *make_filepath (char *, char *); -error_t for_each_subdir (char *, error_t (*) (char *, char *)); -error_t for_each_subdir_priv (char *, error_t (*) (char *, char *, void *), - void *); - -/* Lookup the file named NAME beneath DIR (or the cwd, if DIR is not a - valid port. Try to open with FLAGS0 first, and if that fails with - FLAGS1; MODE is the mode to user for newly created files. On - success, stat the looked up port and store it in *PORT, the - according stat information are stored in *STAT. */ -error_t file_lookup (file_t dir, char *name, int flags0, int flags1, int mode, - file_t *port, struct stat *stat); - -/* Returns no error if directory. */ -error_t check_dir (char *path); - -extern struct mutex debug_msg_lock; - -/* Support for debugging messages. */ -#define debug_msg_send(fmt, args...) \ - do \ - { \ - mutex_lock (&debug_msg_lock); \ - fprintf (stderr, "%s:%i: ", __FILE__, __LINE__); \ - fprintf (stderr, fmt , ## args); \ - putc ('\n', stderr); \ - mutex_unlock (&debug_msg_lock); \ - } \ - while (0) - -#endif diff --git a/unionfs/lnode.c b/unionfs/lnode.c deleted file mode 100644 index 9b242bba..00000000 --- a/unionfs/lnode.c +++ /dev/null @@ -1,184 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - 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. */ - -/* `light node' management. See unionfs.h for an explanation of light - nodes. */ - -#define _GNU_SOURCE - -#include <hurd/netfs.h> -#include <error.h> -#include <stdlib.h> -#include <string.h> - -#include "lnode.h" -#include "lib.h" -#include "unionfs.h" - -/* Create a new light node as an entry with the name NAME and store it - in *NODE. The new node is not locked and contains a single - reference. */ -error_t -lnode_create (char *name, lnode_t **node) -{ - lnode_t *node_new = malloc (sizeof (lnode_t)); - error_t err = 0; - - debug_msg ("lnode_create for name: %s", name); - - if (! node_new) - err = ENOMEM; - else - { - char *name_cp = NULL; - - if (name) - name_cp = strdup (name); - if (name && (! name_cp)) - { - err = ENOMEM; - free (node_new); - } - else - { - node_new->name = name_cp; - node_new->name_len = name_cp ? strlen (name_cp) : 0; - node_new->flags = 0; - node_new->node = NULL; - node_new->next = NULL; - node_new->prevp = NULL; - node_new->dir = NULL; - node_new->entries = NULL; - node_new->references = 1; - mutex_init (&node_new->lock); - mutex_lock (&node_new->lock); - *node = node_new; - } - } - return err; -} - -/* Destroy a light node. */ -void -lnode_destroy (lnode_t *node) -{ - debug_msg ("lnode_destroy for name: %s", node->name); - free (node->name); - free (node); -} - -/* Install the node in the node tree; add a reference to DIR, which - must be locked. */ -void -lnode_install (lnode_t *dir, lnode_t *node) -{ - lnode_ref_add (dir); - node->next = dir->entries; - node->prevp = &dir->entries; - if (dir->entries) - dir->entries->prevp = &node->next; - dir->entries = node; - node->dir = dir; -} - -/* Uninstall the node from the node tree; remove a reference from the - lnode containing NODE. */ -void -lnode_uninstall (lnode_t *node) -{ - lnode_ref_remove (node->dir); - *node->prevp = node->next; - if (node->next) - node->next->prevp = &node->next; -} - -/* Add a reference to NODE, which must be locked. */ -void -lnode_ref_add (lnode_t *node) -{ - node->references++; -} - -/* Remove a reference to NODE, which must be locked. If that was the - last reference, destroy the node, otherwise simply unlock NODE. */ -void -lnode_ref_remove (lnode_t *node) -{ - assert (node->references); - if (! --node->references) - { - lnode_uninstall (node); - lnode_destroy (node); - } - else - mutex_unlock (&node->lock); -} - -/* Get a light node by it's name. The looked up node is locked and - got one reference added. */ -error_t -lnode_get (lnode_t *dir, char *name, - lnode_t **node) -{ - error_t err = 0; - lnode_t *n; - - for (n = dir->entries; n && strcmp (n->name, name); n = n->next); - if (n) - { - mutex_lock (&n->lock); - lnode_ref_add (n); - *node = n; - } - else - err = ENOENT; - - return err; -} - -/* Construct the full path for a given light node. */ -error_t -lnode_path_construct (lnode_t *node, - char **path) -{ - error_t err = 0; - int p_len = 1; - lnode_t *n; - char *p; - - for (n = node; n && n->dir; n = n->dir) - p_len += n->name_len + (n->dir->dir ? 1 : 0); - - p = malloc (p_len); - if (! p) - err = ENOMEM; - else - { - *(p + --p_len) = 0; - for (n = node; n && n->dir; n = n->dir) - { - p_len -= n->name_len; - strncpy (p + p_len, n->name, n->name_len); - if (n->dir->dir) - *(p + --p_len) = '/'; - } - *path = p; - } - return err; -} diff --git a/unionfs/lnode.h b/unionfs/lnode.h deleted file mode 100644 index b43b7b26..00000000 --- a/unionfs/lnode.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - 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. */ - -/* `light node' management. */ - -#ifndef INCLUDED_LNODE_H -#define INCLUDED_LNODE_H - -#include <hurd/netfs.h> -#include <error.h> - -struct lnode -{ - char *name; /* The name of this light node. */ - int name_len; /* This is used quite often and since - NAME does not change, just - calculate it once. */ - int flags; /* Associated flags. */ - int references; /* References to this light node. */ - struct node *node; /* Reference to the real node. */ - struct lnode *next, **prevp; /* Light nodes are connected in a - linked list. */ - struct lnode *dir; /* The light node this light node is - contained int. */ - struct lnode *entries; /* A reference to the list containing - the entries of this light node. */ - struct mutex lock; /* A lock. */ -}; -typedef struct lnode lnode_t; - -/* Create a new light node as an entry with the name NAME and store it - in *NODE. The new node is not locked and contains a single - reference. */ -error_t lnode_create (char *name, lnode_t **node); - -/* Destroy a light node. */ -void lnode_destroy (lnode_t *node); - -/* Install the node in the node tree; add a reference to DIR. */ -void lnode_install (lnode_t *dir, lnode_t *node); - -/* Uninstall the node from the node tree; remove a reference from the - lnode containing NODE. */ -void lnode_uninstall (lnode_t *node); - -/* Add a reference to NODE, which must be locked. */ -void lnode_ref_add (lnode_t *node); - -/* Remove a reference to NODE, which must be locked. If that was the - last reference, destroy the node, otherwise simply unlock NODE. */ -void lnode_ref_remove (lnode_t *node); - -/* Get a light node by it's name. The looked up node is locked and - got one reference added. */ -error_t lnode_get (lnode_t *dir, char *name, - lnode_t **node); - -/* Construct the full path for a given light node. */ -error_t lnode_path_construct (lnode_t *node, char **path); - -#endif diff --git a/unionfs/main.c b/unionfs/main.c deleted file mode 100644 index c33b0654..00000000 --- a/unionfs/main.c +++ /dev/null @@ -1,134 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - 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. */ - -#define _GNU_SOURCE - -#include <hurd/netfs.h> -#include <argp.h> -#include <argz.h> -#include <error.h> -#include <fcntl.h> -#include <sys/types.h> -#include <unistd.h> - -#include "version.h" -#include "unionfs.h" -#include "ncache.h" -#include "ulfs.h" -#include "lnode.h" -#include "node.h" -#include "options.h" -#include "stow.h" -#include "update.h" - -char *netfs_server_name = "unionfs"; -char *netfs_server_version = HURD_VERSION; - -/* Not really needed, since unionfs doesn't manage symlinks. */ -int netfs_maxsymlinks = 0; - -/* Flags describing certain properties of the unionfs. */ -int unionfs_flags; - -/* The filesystem id (the pid). */ -pid_t fsid; - -/* A port to the underlying node. */ -mach_port_t underlying_node; - -/* stat information for the underlying node. */ -struct stat underlying_node_stat; - -/* Mapped time, used for updating node information. */ -volatile struct mapped_time_value *maptime; - -/* Used by netfs_set_options to handle runtime option parsing. */ -struct argp *netfs_runtime_argp = &argp_runtime; - -/* Main entry point. */ -int -main (int argc, char **argv) -{ - mach_port_t bootstrap_port; - error_t err = 0; - - root_update_init (); - - err = stow_init(); - if (err) - error (EXIT_FAILURE, err, "failed to initialize stow support"); - - /* Argument parsing. */ - argp_parse (&argp_startup, argc, argv, ARGP_IN_ORDER, 0, 0); - - err = node_create_root (&netfs_root_node); - if (err) - error (EXIT_FAILURE, err, "failed to create root node"); - - /* netfs initialization. */ - task_get_bootstrap_port (mach_task_self (), &bootstrap_port); - netfs_init (); - underlying_node = netfs_startup (bootstrap_port, O_READ); - - err = node_init_root (netfs_root_node); - if (err) - error (EXIT_FAILURE, err, "failed to initialize root node"); - - /* Map the time, used for updating node information. */ - err = maptime_map (0, 0, &maptime); - if (err) - error (EXIT_FAILURE, err, "maptime_map"); - - /* More initialiazation. */ - ncache_init (ncache_size); - - /* Here we adjust the root node permissions. */ - err = io_stat (underlying_node, &underlying_node_stat); - - if (err) - error (EXIT_FAILURE, err, "io_stat"); - - fsid = getpid (); - netfs_root_node->nn_stat = underlying_node_stat; - netfs_root_node->nn_stat.st_ino = UNIONFS_ROOT_INODE; /* FIXME. */ - netfs_root_node->nn_stat.st_fsid = fsid; - netfs_root_node->nn_stat.st_mode = S_IFDIR | (underlying_node_stat.st_mode - & ~S_IFMT & ~S_ITRANS); - netfs_root_node->nn_translated = netfs_root_node->nn_stat.st_mode; - - /* If the underlying node isn't a directory, enhance the stat - information. */ - if (! S_ISDIR (underlying_node_stat.st_mode)) - { - if (underlying_node_stat.st_mode & S_IRUSR) - netfs_root_node->nn_stat.st_mode |= S_IXUSR; - if (underlying_node_stat.st_mode & S_IRGRP) - netfs_root_node->nn_stat.st_mode |= S_IXGRP; - if (underlying_node_stat.st_mode & S_IROTH) - netfs_root_node->nn_stat.st_mode |= S_IXOTH; - } - - /* Update the timestamps of the root node. */ - fshelp_touch (&netfs_root_node->nn_stat, - TOUCH_ATIME | TOUCH_MTIME | TOUCH_CTIME, maptime); - - /* Start serving clients. */ - for (;;) - netfs_server_loop (); -} diff --git a/unionfs/ncache.c b/unionfs/ncache.c deleted file mode 100644 index 4c83ac0e..00000000 --- a/unionfs/ncache.c +++ /dev/null @@ -1,151 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - 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. */ - -#define _GNU_SOURCE - -#include <hurd/netfs.h> -#include <error.h> -#include <stdlib.h> -#include <assert.h> - -#include "ncache.h" -#include "lib.h" -#include "unionfs.h" - -/* The node cache. */ -ncache_t ncache; - -/* Cache size, may be overwritten by the user. */ -int ncache_size = NCACHE_SIZE; - -/* Initialize the node cache, set the maximum number of allowed nodes - in the cache to SIZE_MAX. */ -void -ncache_init (int size_max) -{ - ncache.mru = NULL; - ncache.lru = NULL; - ncache.size_max = size_max; - ncache.size_current = 0; - mutex_init (&ncache.lock); -} - -/* Remove the given node NODE from the cache. */ -static void -ncache_node_remove (node_t *node) -{ - struct netnode *nn = node->nn; - - if (nn->ncache_next) - nn->ncache_next->nn->ncache_prev = nn->ncache_prev; - if (nn->ncache_prev) - nn->ncache_prev->nn->ncache_next = nn->ncache_next; - if (ncache.mru == node) - ncache.mru = nn->ncache_next; - if (ncache.lru == node) - ncache.lru = nn->ncache_prev; - nn->ncache_next = NULL; - nn->ncache_prev = NULL; - ncache.size_current--; -} - -void -ncache_reset (void) -{ - node_t *node; - - mutex_lock (&ncache.lock); - while ((node = ncache.mru)) - ncache_node_remove (node); - mutex_unlock (&ncache.lock); -} - -/* Lookup the node for the light node LNODE. If it does not exist - anymore in the cache, create a new node. Store the looked up node - in *NODE. */ -error_t -ncache_node_lookup (lnode_t *lnode, node_t **node) -{ - error_t err = 0; - node_t *n; - - if (lnode->node) - { - debug_msg ("ncache_node_lookup for lnode: %s (found in cache)", - lnode->name); - n = lnode->node; - netfs_nref (n); - } - else - { - debug_msg ("ncache_node_lookup for lnode: %s (newly created)", - lnode->name); - err = node_create (lnode, &n); - } - - if (! err) - { - mutex_lock (&n->lock); - *node = n; - } - return err; -} - -/* Add the given node NODE to the node cache; remove - least-recently-used nodes, if needed. */ -void -ncache_node_add (node_t *node) -{ - mutex_lock (&ncache.lock); - - debug_msg ("adding node to cache: %s", node->nn->lnode->name); - - if (ncache.size_max > 0 || ncache.size_current > 0) - { - if (ncache.mru != node) - { - if (node->nn->ncache_next || node->nn->ncache_prev) - /* Node is already in the cache. */ - ncache_node_remove (node); - else - /* Add a reference from the cache. */ - netfs_nref (node); - - node->nn->ncache_next = ncache.mru; - node->nn->ncache_prev = NULL; - if (ncache.mru) - ncache.mru->nn->ncache_prev = node; - if (! ncache.lru) - ncache.lru = node; - ncache.mru = node; - ncache.size_current++; - } - } - - /* Forget the least used nodes. */ - while (ncache.size_current > ncache.size_max) - { - struct node *lru = ncache.lru; - debug_msg ("removing cached node: %s", lru->nn->lnode->name); - ncache_node_remove (lru); - netfs_nrele (lru); - } - - mutex_unlock (&ncache.lock); -} diff --git a/unionfs/ncache.h b/unionfs/ncache.h deleted file mode 100644 index 8fa7d107..00000000 --- a/unionfs/ncache.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - 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. */ - -#ifndef INCLUDED_NCACHE_H -#define INCLUDED_NCACHE_H - -#include <error.h> -#include <hurd/netfs.h> - -#include "node.h" - -typedef struct ncache -{ - node_t *mru; /* Reference to the mru end of the - cache chain. */ - node_t *lru; /* Reference to the lru end of the - cache chain. */ - int size_max; /* Maximal number of nodes to - cache. */ - int size_current; /* Current number of nodes in the - cache. */ - struct mutex lock; /* A lock. */ -} ncache_t; - -/* Cache size, may be overwritten by the user. */ -extern int ncache_size; - -/* Initialize the node cache, set the maximum number of allowed nodes - in the cache to SIZE_MAX. */ -void ncache_init (int size_max); - -/* Lookup the node for the light node LNODE. If it does not exist - anymore in the cache, create a new node. Store the looked up node - in *NODE. */ -error_t ncache_node_lookup (lnode_t *lnode, node_t **node); - -void ncache_reset (void); - -/* Add the given node NODE to the node cache; remove - least-recently-used nodes, if needed. */ -void ncache_node_add (node_t *node); - -#endif diff --git a/unionfs/netfs.c b/unionfs/netfs.c deleted file mode 100644 index 89d1bf67..00000000 --- a/unionfs/netfs.c +++ /dev/null @@ -1,1170 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - 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. */ - -#define _GNU_SOURCE - -#include <hurd/netfs.h> -#include <error.h> -#include <argz.h> -#include <stddef.h> -#include <fcntl.h> -#include <assert.h> -#include <string.h> -#include <stdio.h> -#include <hurd/paths.h> -#include <sys/mman.h> - -#include "unionfs.h" -#include "ulfs.h" -#include "node.h" -#include "lib.h" -#include "ncache.h" -#include "options.h" - -/* Return an argz string describing the current options. Fill *ARGZ - with a pointer to newly malloced storage holding the list and *LEN - to the length of that storage. */ -error_t -netfs_append_args (char **argz, size_t *argz_len) -{ - error_t err = 0; - - ulfs_iterate - { - if (! err) - if (unionfs_flags & FLAG_UNIONFS_MODE_DEBUG) - err = argz_add (argz, argz_len, - OPT_LONG (OPT_LONG_DEBUG)); - if (! err) - if (ulfs->flags & FLAG_ULFS_WRITABLE) - err = argz_add (argz, argz_len, - OPT_LONG (OPT_LONG_WRITABLE)); - if (! err) - if (ulfs->priority) - { - char *buf = NULL; - if ((err = asprintf (&buf, "%s=%s", OPT_LONG (OPT_LONG_PRIORITY), - ulfs->priority)) != -1) - { - err = argz_add (argz, argz_len, buf); - free (buf); - } - } - - if (! err) - { - if (ulfs->path) - err = argz_add (argz, argz_len, ulfs->path); - else - err = argz_add (argz, argz_len, - OPT_LONG (OPT_LONG_UNDERLYING)); - } - } - - return err; -} - -#ifndef __USE_FILE_OFFSET64 -#define OFFSET_T __off_t /* Size in bytes. */ -#else -#define OFFSET_T __off64_t /* Size in bytes. */ -#endif - -static error_t -_get_node_size (struct node *dir, OFFSET_T *off) -{ - size_t size = 0; - error_t err; - int count = 0; - node_dirent_t *dirent_start, *dirent_current; - node_dirent_t *dirent_list = NULL; - int first_entry = 2; - - int bump_size (const char *name) - { - size_t new_size = size + DIRENT_LEN (strlen (name)); - - size = new_size; - count ++; - return 1; - } - - err = node_entries_get (dir, &dirent_list); - if (err) - return err; - - for (dirent_start = dirent_list, count = 2; - dirent_start && first_entry > count; - dirent_start = dirent_start->next, count++); - - count = 0; - - /* Make space for the `.' and `..' entries. */ - if (first_entry == 0) - bump_size ("."); - if (first_entry <= 1) - bump_size (".."); - - /* See how much space we need for the result. */ - for (dirent_current = dirent_start; - dirent_current; - dirent_current = dirent_current->next) - if (! bump_size (dirent_current->dirent->d_name)) - break; - - free (dirent_list); - - *off = size; - - return 0; -} - - -/* Make sure that NP->nn_stat is filled with current information. - CRED identifies the user responsible for the operation. */ -error_t -netfs_validate_stat (struct node *np, struct iouser *cred) -{ - error_t err = 0; - - if (np != netfs_root_node) - { - if (! (np->nn->flags & FLAG_NODE_ULFS_UPTODATE)) - err = node_update (np); - if (! err) - { - int done = 0; - - node_ulfs_iterate_unlocked (np) - if ((! done) && port_valid (node_ulfs->port)) - { - err = io_stat (node_ulfs->port, &np->nn_stat); - if (! err) - np->nn_translated = np->nn_stat.st_mode; - done = 1; - } - if (! done) - err = ENOENT; /* FIXME? */ - } - } - else - { - _get_node_size (np, &np->nn_stat.st_size); - } - - return err; -} - -/* This should attempt a chmod call for the user specified by CRED on - locked node NP, to change the owner to UID and the group to GID. */ -error_t -netfs_attempt_chown (struct iouser *cred, struct node *np, - uid_t uid, uid_t gid) -{ - return EOPNOTSUPP; -} - -/* This should attempt a chauthor call for the user specified by CRED - on locked node NP, thereby changing the author to AUTHOR. */ -error_t -netfs_attempt_chauthor (struct iouser *cred, struct node *np, - uid_t author) -{ - return EOPNOTSUPP; -} - -/* This should attempt a chmod call for the user specified by CRED on - locked node NODE, to change the mode to MODE. Unlike the normal - Unix and Hurd meaning of chmod, this function is also used to - attempt to change files into other types. If such a transition is - attempted which is impossible, then return EOPNOTSUPP. */ -error_t -netfs_attempt_chmod (struct iouser *cred, struct node *np, - mode_t mode) -{ - return EOPNOTSUPP; -} - -/* Attempt to turn locked node NP (user CRED) into a symlink with - target NAME. */ -error_t -netfs_attempt_mksymlink (struct iouser *cred, struct node *np, - char *name) -{ - return EOPNOTSUPP; -} - -/* Attempt to turn NODE (user CRED) into a device. TYPE is either - S_IFBLK or S_IFCHR. NP is locked. */ -error_t -netfs_attempt_mkdev (struct iouser *cred, struct node *np, - mode_t type, dev_t indexes) -{ - return EOPNOTSUPP; -} - -/* Attempt to set the passive translator record for FILE to ARGZ (of - length ARGZLEN) for user CRED. NP is locked. */ -error_t -netfs_set_translator (struct iouser *cred, struct node *np, - char *argz, size_t argzlen) -{ - return EOPNOTSUPP; -} - -/* For locked node NODE with S_IPTRANS set in its mode, look up the - name of its translator. Store the name into newly malloced - storage, and return it in *ARGZ; set *ARGZ_LEN to the total length. */ -error_t -netfs_get_translator (struct node *node, char **argz, - size_t *argz_len) -{ - return EOPNOTSUPP; -} - -/* This should attempt a chflags call for the user specified by CRED - on locked node NP, to change the flags to FLAGS. */ -error_t -netfs_attempt_chflags (struct iouser *cred, struct node *np, - int flags) -{ - return EOPNOTSUPP; -} - -/* This should attempt a utimes call for the user specified by CRED on - locked node NP, to change the atime to ATIME and the mtime to - MTIME. If ATIME or MTIME is null, then set to the current time. */ -error_t -netfs_attempt_utimes (struct iouser *cred, struct node *np, - struct timespec *atime, struct timespec *mtime) -{ - return 0; -} - -/* This should attempt to set the size of the locked file NP (for user - CRED) to SIZE bytes long. */ -error_t -netfs_attempt_set_size (struct iouser *cred, struct node *np, - off_t size) -{ - return EOPNOTSUPP; -} - -/* This should attempt to fetch filesystem status information for the - remote filesystem, for the user CRED. NP is locked. */ -error_t -netfs_attempt_statfs (struct iouser *cred, struct node *np, - struct statfs *st) -{ - return EOPNOTSUPP; -} - -/* This should sync the locked file NP completely to disk, for the - user CRED. If WAIT is set, return only after the sync is - completely finished. */ -error_t -netfs_attempt_sync (struct iouser *cred, struct node *np, - int wait) -{ - return EOPNOTSUPP; -} - -/* This should sync the entire remote filesystem. If WAIT is set, - return only after the sync is completely finished. */ -error_t -netfs_attempt_syncfs (struct iouser *cred, int wait) -{ - return 0; -} - -/* lookup */ - -/* We don't use this functions, but it has to be defined. */ -error_t -netfs_attempt_lookup (struct iouser *user, struct node *dir, - char *name, struct node **node) -{ - return EOPNOTSUPP; -} - -/* Delete NAME in DIR (which is locked) for USER. */ -error_t -netfs_attempt_unlink (struct iouser *user, struct node *dir, - char *name) -{ - error_t err = 0; - mach_port_t p; - struct stat statbuf; - - node_update (dir); - - err = node_lookup_file (dir, name, 0, &p, &statbuf); - if (err) - return err; - - port_dealloc (p); - - err = fshelp_checkdirmod (&dir->nn_stat, &statbuf, user); - if (err) - return err; - - err = node_unlink_file (dir, name); - - return err; -} - -/* Attempt to rename the directory FROMDIR to TODIR. Note that neither - of the specific nodes are locked. */ -error_t -netfs_attempt_rename (struct iouser *user, struct node *fromdir, - char *fromname, struct node *todir, - char *toname, int excl) -{ - return EOPNOTSUPP; -} - -/* Attempt to create a new directory named NAME in DIR (which is - locked) for USER with mode MODE. */ -error_t -netfs_attempt_mkdir (struct iouser *user, struct node *dir, - char *name, mode_t mode) -{ - error_t err = 0; - mach_port_t p; - struct stat statbuf; - - node_update (dir); - - err = fshelp_checkdirmod (&dir->nn_stat, 0, user); - if (err) - goto exit; - - /* Special case for no UID processes (like login shell). */ - if ((!user->uids->ids) || (!user->uids->ids)) - { - err = EACCES; - goto exit; - } - - err = node_dir_create (dir, name, mode); - if (err) - goto exit; - - err = node_lookup_file (dir, name, 0, &p, &statbuf); - if (err) - { - node_dir_remove (dir, name); - goto exit; - } - - err = file_chown (p, user->uids->ids[0], user->gids->ids[0]); - if (err) - { - port_dealloc (p); - node_dir_remove (dir, name); - goto exit; - } - - port_dealloc (p); - - exit: - - return err; -} - -/* Attempt to remove directory named NAME in DIR (which is locked) for - USER. */ -error_t -netfs_attempt_rmdir (struct iouser *user, - struct node *dir, char *name) -{ - error_t err = 0; - mach_port_t p; - struct stat statbuf; - - node_update (dir); - - err = node_lookup_file (dir, name, 0, &p, &statbuf); - if (err) - return err; - - port_dealloc (p); - - err = fshelp_checkdirmod (&dir->nn_stat, &statbuf, user); - if (err) - return err; - - err = node_dir_remove (dir, name); - - return err; -} - -/* Create a link in DIR with name NAME to FILE for USER. Note that - neither DIR nor FILE are locked. If EXCL is set, do not delete the - target. Return EEXIST if NAME is already found in DIR. */ -error_t -netfs_attempt_link (struct iouser *user, struct node *dir, - struct node *file, char *name, int excl) -{ - return EOPNOTSUPP; -} - -/* Attempt to create an anonymous file related to DIR (which is - locked) for USER with MODE. Set *NP to the returned file upon - success. No matter what, unlock DIR. */ -error_t -netfs_attempt_mkfile (struct iouser *user, struct node *dir, - mode_t mode, struct node **np) -{ - mutex_unlock (&dir->lock); - return EOPNOTSUPP; -} - -/* (We don't use this function!) Attempt to create a file named NAME - in DIR (which is locked) for USER with MODE. Set *NP to the new - node upon return. On any error, clear *NP. *NP should be locked - on success; no matter what, unlock DIR before returning. */ -error_t -netfs_attempt_create_file (struct iouser *user, struct node *dir, - char *name, mode_t mode, struct node **np) -{ - mutex_unlock (&dir->lock); - return EOPNOTSUPP; -} - -/* We use this local interface to attempt_create file since we are - using our own netfs_S_dir_lookup. */ -error_t -netfs_attempt_create_file_reduced (struct iouser *user, struct node *dir, - char *name, mode_t mode, int flags) -{ - mach_port_t p; - error_t err; - struct stat statbuf; - - node_update (dir); - - err = fshelp_checkdirmod (&dir->nn_stat, 0, user); - if (err) - goto exit; - - /* Special case for no UID processes (like login shell). */ - if ((!user->uids->ids) || (!user->uids->ids)) - { - err = EACCES; - goto exit; - } - - mutex_unlock (&dir->lock); - err = node_lookup_file (dir, name, flags | O_CREAT, - &p, &statbuf); - mutex_lock (&dir->lock); - - if (err) - goto exit; - - err = file_chmod (p, mode); - if (err) - { - port_dealloc (p); - node_unlink_file (dir, name); - goto exit; - } - - err = file_chown (p, user->uids->ids[0], user->gids->ids[0]); - if (err) - { - port_dealloc (p); - node_unlink_file (dir, name); - goto exit; - } - - err = io_stat (p, &statbuf); - - /* Check file permissions. */ - if (! err && (flags & O_READ)) - err = fshelp_access (&statbuf, S_IREAD, user); - if (! err && (flags & O_WRITE)) - err = fshelp_access (&statbuf, S_IWRITE, user); - if (! err && (flags & O_EXEC)) - err = fshelp_access (&statbuf, S_IEXEC, user); - - if (err) - { - port_dealloc (p); - node_unlink_file (dir, name); - goto exit; - } - - port_dealloc (p); - - exit: - mutex_unlock (&dir->lock); - return err; -} - -/* Read the contents of locked node NP (a symlink), for USER, into - BUF. */ -error_t -netfs_attempt_readlink (struct iouser *user, struct node *np, - char *buf) -{ - return EOPNOTSUPP; -} - -/* libnetfs uses this functions once. */ -error_t -netfs_check_open_permissions (struct iouser *user, struct node *np, - int flags, int newnode) -{ - error_t err = 0; - - if (! err && (flags & O_READ)) - err = fshelp_access (&np->nn_stat, S_IREAD, user); - if (! err && (flags & O_WRITE)) - err = fshelp_access (&np->nn_stat, S_IWRITE, user); - if (! err && (flags & O_EXEC)) - err = fshelp_access (&np->nn_stat, S_IEXEC, user); - - return err; -} - -/* Read from the locked file NP for user CRED starting at OFFSET and - continuing for up to *LEN bytes. Put the data at DATA. Set *LEN - to the amount successfully read upon return. */ -error_t -netfs_attempt_read (struct iouser *cred, struct node *np, - off_t offset, size_t *len, void *data) -{ - *len = 0; - return 0; -} - -/* Write to the locked file NP for user CRED starting at OFSET and - continuing for up to *LEN bytes from DATA. Set *LEN to the amount - successfully written upon return. */ -error_t -netfs_attempt_write (struct iouser *cred, struct node *np, - off_t offset, size_t *len, void *data) -{ - /* Since unionfs only manages directories... */ - return EISDIR; -} - -/* Return the valid access types (bitwise OR of O_READ, O_WRITE, and - O_EXEC) in *TYPES for locked file NP and user CRED. */ -error_t -netfs_report_access (struct iouser *cred, struct node *np, - int *types) -{ - *types = 0; - if (fshelp_access (&np->nn_stat, S_IREAD, cred) == 0) - *types |= O_READ; - if (fshelp_access (&np->nn_stat, S_IWRITE, cred) == 0) - *types |= O_WRITE; - if (fshelp_access (&np->nn_stat, S_IEXEC, cred) == 0) - *types |= O_EXEC; - return 0; -} - -/* Create a new user from the specified UID and GID arrays. */ -struct iouser * -netfs_make_user (uid_t *uids, int nuids, uid_t *gids, int ngids) -{ - return NULL; -} - -/* Node NP has no more references; free all its associated storage. */ -void -netfs_node_norefs (struct node *np) -{ - node_destroy (np); -} - -error_t -netfs_attempt_lookup_improved (struct iouser *user, struct node *dir, - char *name, struct node **np, - int flags, int lastcomp, - mach_port_t *port, - mach_msg_type_name_t *port_type) -{ - mach_port_t p; - error_t err; - - mutex_lock (&dir->nn->lnode->lock); - - err = fshelp_access (&dir->nn_stat, S_IEXEC, user); - if (err) - goto exit; - - - if (! *name || ! strcmp (name, ".")) - { - - /* The same node is wanted. */ - *np = dir; - netfs_nref (*np); - - } - else if (! strcmp (name, "..")) - { - - /* We have to get the according light node first. */ - lnode_t *lnode = dir->nn->lnode; - node_t *node; - - err = ncache_node_lookup (lnode->dir, &node); - if (err) - goto exit; - - *np = node; - - } - else - { - - lnode_t *dir_lnode = dir->nn->lnode; - struct stat statbuf; - lnode_t *lnode = NULL; - - /* Lookup the node by it's name on the underlying - filesystems. */ - - err = node_update (dir); - - /* We have to unlock this node while doing lookups. */ - mutex_unlock (&dir_lnode->lock); - mutex_unlock (&dir->lock); - - err = node_lookup_file (dir, name, flags & ~(O_NOLINK|O_CREAT), - &p, &statbuf); - - mutex_lock (&dir->lock); - mutex_lock (&dir_lnode->lock); - - - if (err) - goto exit; - - if (S_ISDIR (statbuf.st_mode)) - { - node_t *node; - - /* We don't need this port directly. */ - port_dealloc (p); - - /* The found node is a directory, so we have to manage the - node. First we need the light node. */ - - err = lnode_get (dir_lnode, name, &lnode); - if (err == ENOENT) - { - /* It does not exist, we have to create it. */ - err = lnode_create (name, &lnode); - if (err) - goto exit; - - lnode_install (dir_lnode, lnode); - } - - /* Now we have a light node. */ - err = ncache_node_lookup (lnode, &node); - - /* This unlocks the node for us. */ - lnode_ref_remove (lnode); - - if (err) - goto exit; - - /* Got the node. */ - *np = node; - - } - else - { - /* The found node is not a directory. */ - mach_port_t p_restricted; - - if (! lastcomp) - { - /* We have not reached the last path component yet. */ - port_dealloc (p); - err = ENOTDIR; - goto exit; - } - - /* Check file permissions. */ - if (! err && (flags & O_READ)) - err = fshelp_access (&statbuf, S_IREAD, user); - if (! err && (flags & O_WRITE)) - err = fshelp_access (&statbuf, S_IWRITE, user); - if (! err && (flags & O_EXEC)) - err = fshelp_access (&statbuf, S_IEXEC, user); - - if (err) - { - port_dealloc (p); - goto exit; - } - - - /* A file node is successfully looked up. */ - err = io_restrict_auth (p, &p_restricted, - user->uids->ids, user->uids->num, - user->gids->ids, user->gids->num); - port_dealloc (p); - - if (err) - goto exit; - - /* Successfully restricted. */ - *port = p_restricted; - *port_type = MACH_MSG_TYPE_MOVE_SEND; - } - } - - exit: - - if (err) - *np = NULL; - else if (*np) - { - mutex_unlock (&(*np)->lock); - ncache_node_add (*np); - } - - mutex_unlock (&dir->nn->lnode->lock); - mutex_unlock (&dir->lock); - return err; -} - -/* We need our own, special implementation of netfs_S_dir_lookup, - because libnetfs does not (yet?) know about cases, in which the - servers wants to return (foreign) ports directly to the user, - instead of usual node structures. */ - -#define OPENONLY_STATE_MODES (O_CREAT|O_EXCL|O_NOLINK|O_NOTRANS|O_NONBLOCK) - -fshelp_fetch_root_callback1_t _netfs_translator_callback1; -fshelp_fetch_root_callback2_t _netfs_translator_callback2; - -error_t -netfs_S_dir_lookup (struct protid *diruser, - char *filename, - int flags, - mode_t mode, - retry_type *do_retry, - char *retry_name, - mach_port_t *retry_port, - mach_msg_type_name_t *retry_port_type) -{ - int create; /* true if O_CREAT flag set */ - int excl; /* true if O_EXCL flag set */ - int mustbedir = 0; /* true if the result must be S_IFDIR */ - int lastcomp = 0; /* true if we are at the last component */ - int newnode = 0; /* true if this node is newly created */ - int nsymlinks = 0; - struct node *dnp, *np; - char *nextname; - error_t error = 0; - struct protid *newpi; - struct iouser *user; - - if (!diruser) - return EOPNOTSUPP; - - create = (flags & O_CREAT); - excl = (flags & O_EXCL); - - /* Skip leading slashes */ - while (*filename == '/') - filename++; - - *retry_port_type = MACH_MSG_TYPE_MAKE_SEND; - *do_retry = FS_RETRY_NORMAL; - *retry_name = '\0'; - - if (*filename == '\0') - { - /* Set things up in the state expected by the code from gotit: on. */ - dnp = 0; - np = diruser->po->np; - mutex_lock (&np->lock); - netfs_nref (np); - goto gotit; - } - - dnp = diruser->po->np; - - mutex_lock (&dnp->lock); - - netfs_nref (dnp); /* acquire a reference for later netfs_nput */ - - do - { - assert (!lastcomp); - - /* Find the name of the next pathname component */ - nextname = index (filename, '/'); - - if (nextname) - { - *nextname++ = '\0'; - while (*nextname == '/') - nextname++; - if (*nextname == '\0') - { - /* These are the rules for filenames ending in /. */ - nextname = 0; - lastcomp = 1; - mustbedir = 1; - create = 0; - } - else - lastcomp = 0; - } - else - lastcomp = 1; - - np = 0; - - retry_lookup: - - if ((dnp == netfs_root_node || dnp == diruser->po->shadow_root) - && filename[0] == '.' && filename[1] == '.' && filename[2] == '\0') - if (dnp == diruser->po->shadow_root) - /* We're at the root of a shadow tree. */ - { - *do_retry = FS_RETRY_REAUTH; - *retry_port = diruser->po->shadow_root_parent; - *retry_port_type = MACH_MSG_TYPE_COPY_SEND; - if (! lastcomp) - strcpy (retry_name, nextname); - error = 0; - mutex_unlock (&dnp->lock); - goto out; - } - else if (diruser->po->root_parent != MACH_PORT_NULL) - /* We're at a real translator root; even if DIRUSER->po has a - shadow root, we can get here if its in a directory that was - renamed out from under it... */ - { - *do_retry = FS_RETRY_REAUTH; - *retry_port = diruser->po->root_parent; - *retry_port_type = MACH_MSG_TYPE_COPY_SEND; - if (!lastcomp) - strcpy (retry_name, nextname); - error = 0; - mutex_unlock (&dnp->lock); - goto out; - } - else - /* We are global root */ - { - error = 0; - np = dnp; - netfs_nref (np); - } - else - /* Attempt a lookup on the next pathname component. */ - error = netfs_attempt_lookup_improved (diruser->user, dnp, - filename, &np, - flags, lastcomp, - retry_port, retry_port_type); - - /* At this point, DNP is unlocked */ - - /* Implement O_EXCL flag here */ - if (lastcomp && create && excl && !error && np) - error = EEXIST; - - /* Create the new node if necessary */ - if (lastcomp && create && error == ENOENT) - { - mode &= ~(S_IFMT | S_ISPARE | S_ISVTX); - mode |= S_IFREG; - mutex_lock (&dnp->lock); - - error = netfs_attempt_create_file_reduced (diruser->user, dnp, - filename, mode, flags); - - /* We retry lookup in two cases: - - we created the file and we have to get a valid port; - - someone has already created the file (between our lookup - and this create) then we just got EEXIST. If we are EXCL, - that's fine; otherwise, we have to retry the lookup. */ - if ((!error) || (error == EEXIST && !excl)) - { - mutex_lock (&dnp->lock); - goto retry_lookup; - } - - newnode = 1; - } - - /* All remaining errors get returned to the user */ - if (error) - goto out; - - if (np) - { - mutex_lock (&np->lock); - error = netfs_validate_stat (np, diruser->user); - mutex_unlock (&np->lock); - if (error) - goto out; - } - - if (np - && S_ISLNK (np->nn_translated) - && (!lastcomp - || mustbedir /* "foo/" must see that foo points to a dir */ - || !(flags & (O_NOLINK|O_NOTRANS)))) - { - size_t nextnamelen, newnamelen, linklen; - char *linkbuf; - - /* Handle symlink interpretation */ - if (nsymlinks++ > netfs_maxsymlinks) - { - error = ELOOP; - goto out; - } - - linklen = np->nn_stat.st_size; - - nextnamelen = nextname ? strlen (nextname) + 1 : 0; - newnamelen = nextnamelen + linklen + 1; - linkbuf = alloca (newnamelen); - - error = netfs_attempt_readlink (diruser->user, np, linkbuf); - if (error) - goto out; - - if (nextname) - { - linkbuf[linklen] = '/'; - memcpy (linkbuf + linklen + 1, nextname, - nextnamelen - 1); - } - linkbuf[nextnamelen + linklen] = '\0'; - - if (linkbuf[0] == '/') - { - /* Punt to the caller */ - *do_retry = FS_RETRY_MAGICAL; - *retry_port = MACH_PORT_NULL; - strcpy (retry_name, linkbuf); - goto out; - } - - filename = linkbuf; - if (lastcomp) - { - lastcomp = 0; - - /* Symlinks to nonexistent files aren't allowed to cause - creation, so clear the flag here. */ - create = 0; - } - netfs_nput (np); - mutex_lock (&dnp->lock); - np = 0; - } - else - { - /* Normal nodes here for next filename component */ - filename = nextname; - netfs_nrele (dnp); - - if (lastcomp) - dnp = 0; - else - { - dnp = np; - np = 0; - } - } - } - while (filename && *filename); - - /* At this point, NP is the node to return. */ - gotit: - - if (mustbedir && ! np) - { - error = ENOTDIR; - goto out; - } - - if (np) - error = netfs_check_open_permissions (diruser->user, np, - flags, newnode); - - if (error) - goto out; - - flags &= ~OPENONLY_STATE_MODES; - - if (np) - { - error = iohelp_dup_iouser (&user, diruser->user); - if (error) - goto out; - - newpi = netfs_make_protid (netfs_make_peropen (np, flags, diruser->po), - user); - if (! newpi) - { - iohelp_free_iouser (user); - error = errno; - goto out; - } - - *retry_port = ports_get_right (newpi); - ports_port_deref (newpi); - } - - out: - if (np) - netfs_nput (np); - if (dnp) - netfs_nrele (dnp); - return error; -} - -/* Fill the array *DATA of size BUFSIZE with up to NENTRIES dirents - from DIR (which is locked) starting with entry ENTRY for user CRED. - The number of entries in the array is stored in *AMT and the number - of bytes in *DATACNT. If the supplied buffer is not large enough - to hold the data, it should be grown. */ -error_t -netfs_get_dirents (struct iouser *cred, struct node *dir, - int first_entry, int num_entries, char **data, - mach_msg_type_number_t *data_len, - vm_size_t max_data_len, int *data_entries) -{ - node_dirent_t *dirent_start, *dirent_current; - node_dirent_t *dirent_list = NULL; - size_t size = 0; - int count = 0; - char *data_p; - error_t err; - - int bump_size (const char *name) - { - if (num_entries == -1 || count < num_entries) - { - size_t new_size = size + DIRENT_LEN (strlen (name)); - - if (max_data_len > 0 && new_size > max_data_len) - return 0; - size = new_size; - count++; - return 1; - } - else - return 0; - } - - int add_dirent (const char *name, ino_t fileno, int type) - { - if (num_entries == -1 || count < num_entries) - { - struct dirent hdr; - size_t name_len = strlen (name); - size_t sz = DIRENT_LEN (name_len); - - if (sz > size) - return 0; - else - size -= sz; - - hdr.d_fileno = fileno; - hdr.d_reclen = sz; - hdr.d_type = type; - hdr.d_namlen = name_len; - - memcpy (data_p, &hdr, DIRENT_NAME_OFFS); - strcpy (data_p + DIRENT_NAME_OFFS, name); - data_p += sz; - count++; - - return 1; - } - else - return 0; - } - - err = node_entries_get (dir, &dirent_list); - - if (! err) - { - for (dirent_start = dirent_list, count = 2; - dirent_start && first_entry > count; - dirent_start = dirent_start->next, count++); - - count = 0; - - /* Make space for the `.' and `..' entries. */ - if (first_entry == 0) - bump_size ("."); - if (first_entry <= 1) - bump_size (".."); - - /* See how much space we need for the result. */ - for (dirent_current = dirent_start; - dirent_current; - dirent_current = dirent_current->next) - if (! bump_size (dirent_current->dirent->d_name)) - break; - - *data = mmap (0, size, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); - err = ((void *) *data == (void *) -1) ? errno : 0; - } - - if (! err) - { - data_p = *data; - *data_len = size; - *data_entries = count; - count = 0; - - /* Add `.' and `..' entries. */ - if (first_entry == 0) - add_dirent (".", 2, DT_DIR); - if (first_entry <= 1) - add_dirent ("..", 2, DT_DIR); - - for (dirent_current = dirent_start; - dirent_current; - dirent_current = dirent_current->next) - if (! add_dirent (dirent_current->dirent->d_name, - 2 /* FIXME */, - dirent_current->dirent->d_type)) - break; - } - - if (dirent_list) - node_entries_free (dirent_list); - - fshelp_touch (&dir->nn_stat, TOUCH_ATIME, maptime); - - return err; -} diff --git a/unionfs/node.c b/unionfs/node.c deleted file mode 100644 index cf9a8b47..00000000 --- a/unionfs/node.c +++ /dev/null @@ -1,555 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - 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. */ - -/* node management. */ - -#define _GNU_SOURCE - -#include <hurd/netfs.h> -#include <stdlib.h> -#include <error.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <stdio.h> - -#include "unionfs.h" -#include "node.h" -#include "ulfs.h" -#include "lib.h" - -/* Declarations for functions only used in this file. */ - -/* Deallocate all ports contained in NODE and free per-ulfs data - structures. */ -void node_ulfs_free (node_t *node); - -/* Create a new node, derived from a light node, add a reference to - the light node. */ -error_t -node_create (lnode_t *lnode, node_t **node) -{ - netnode_t *netnode_new = malloc (sizeof (netnode_t)); - error_t err = 0; - node_t *node_new; - - debug_msg ("node_create for lnode: %s", lnode->name); - - if (! netnode_new) - { - err = ENOMEM; - return err; - } - - node_new = netfs_make_node (netnode_new); - if (! node_new) - { - err = ENOMEM; - free (netnode_new); - return err; - } - - node_new->nn->ulfs = NULL; - - err = node_ulfs_init (node_new); - if (err) - { - node_destroy (node_new); - return err; - } - - lnode->node = node_new; - lnode_ref_add (lnode); - node_new->nn->lnode = lnode; - node_new->nn->flags = 0; - node_new->nn->ncache_next = NULL; - node_new->nn->ncache_prev = NULL; - *node = node_new; - - return err; -} - -/* Destroy a node, remove one reference from the associated light - node. */ -void -node_destroy (node_t *node) -{ - debug_msg ("node destroy: %s", node->nn->lnode->name); - assert (! (node->nn->ncache_next || node->nn->ncache_prev)); - node_ulfs_free (node); - mutex_lock (&node->nn->lnode->lock); - node->nn->lnode->node = NULL; - lnode_ref_remove (node->nn->lnode); - free (node->nn); - free (node); -} - -/* Make sure that all ports to the underlying filesystems of NODE, - which must be locked, are uptodate. */ -error_t -node_update (node_t *node) -{ - error_t err = 0; - char *path; - - node_ulfs_t *root_ulfs; - struct stat stat; - file_t port; - int i = 0; - - debug_msg ("node_update for lnode: %s", node->nn->lnode->name); - - if (node_is_root (node)) - return err; - - mutex_lock (&netfs_root_node->lock); - - err = lnode_path_construct (node->nn->lnode, &path); - if (err) - { - mutex_unlock (&netfs_root_node->lock); - return err; - } - - root_ulfs = netfs_root_node->nn->ulfs; - - node_ulfs_iterate_unlocked (node) - { - - if (node_ulfs->flags & FLAG_NODE_ULFS_FIXED) - { - i++; - continue; - } - - /* We really have to update the port. */ - if (port_valid (node_ulfs->port)) - port_dealloc (node_ulfs->port); - - err = file_lookup ((root_ulfs + i)->port, path, - O_READ | O_NOTRANS, O_NOTRANS, - 0, &port, &stat); - - if (err) - { - node_ulfs->port = MACH_PORT_NULL; - err = 0; - i++; - continue; - } - - if (stat.st_ino == underlying_node_stat.st_ino - && stat.st_fsid == underlying_node_stat.st_fsid) - /* It's OUR root node. */ - err = ELOOP; - else - { - port_dealloc (port); - err = file_lookup ((root_ulfs + i)->port, path, - O_READ, 0, 0, &port, &stat); - } - - if (err) - { - port = MACH_PORT_NULL; - err = 0; - } - node_ulfs->port = port; - - i++; - } - - free (path); - node->nn->flags |= FLAG_NODE_ULFS_UPTODATE; - - mutex_unlock (&netfs_root_node->lock); - - return err; -} - -/* Remove all directory named NAME beneath DIR on all underlying filesystems. - Fails if we cannot remove all the directories. */ -error_t -node_dir_remove (node_t *dir, char *name) -{ - error_t err = 0; - - node_ulfs_iterate_reverse_unlocked (dir) - { - if (!port_valid (node_ulfs->port)) - continue; - - err = dir_rmdir (node_ulfs->port, name); - if ((err) && (err != ENOENT)) - break; - } - - return err; -} - -/* Create a directory named NAME beneath DIR on the first (writable) underlying - filesystem. */ -error_t -node_dir_create (node_t *dir, char *name, mode_t mode) -{ - error_t err = 0; - - node_ulfs_iterate_unlocked (dir) - { - if (!port_valid (node_ulfs->port)) - continue; - - err = dir_mkdir (node_ulfs->port, name, mode); - - if ((!err) || (err == EEXIST) || (err == ENOTDIR)) - break; - } - - return err; -} - -/* Remove all files named NAME beneath DIR on the underlying filesystems - with FLAGS as openflags. */ -error_t -node_unlink_file (node_t *dir, char *name) -{ - mach_port_t p; - struct stat stat; - error_t err = 0; - int removed = 0; - - /* Using reverse iteration still have issues. Infact, we could be - deleting a file in some underlying filesystem, and keeping those - after the first occurring error. - FIXME: Check BEFORE starting deletion. */ - - node_ulfs_iterate_reverse_unlocked (dir) - { - - if (!port_valid (node_ulfs->port)) - continue; - - err = file_lookup (node_ulfs->port, name, - O_NOTRANS, O_NOTRANS, - 0, &p, &stat); - - port_dealloc (p); - - if (err == ENOENT) - { - err = 0; - continue; - } - - if (err) - break; - - err = dir_unlink (node_ulfs->port, name); - if ((err) && (err != ENOENT)) - break; - - if (!err) - removed++; - - } - - if ((!err) && (!removed)) - err = ENOENT; - - return err; -} - -/* Lookup a file named NAME beneath DIR on the underlying filesystems - with FLAGS as openflags. Return the first port successfully looked - up in *PORT and according stat information in *STAT. */ -error_t -node_lookup_file (node_t *dir, char *name, int flags, - file_t *port, struct stat *s) -{ - error_t err = ENOENT; - struct stat stat; - file_t p; - - node_ulfs_iterate_unlocked (dir) - { - - if (err != ENOENT) - break; - - if (!port_valid (node_ulfs->port)) - continue; - - err = file_lookup (node_ulfs->port, name, - flags | O_NOTRANS, O_NOTRANS, - 0, &p, &stat); - if (err) - continue; - - if (stat.st_ino == underlying_node_stat.st_ino - && stat.st_fsid == underlying_node_stat.st_fsid) - /* It's OUR root node. */ - err = ELOOP; - else - /* stat.st_mode & S_ITRANS */ - { - port_dealloc (p); - err = file_lookup (node_ulfs->port, name, - flags, 0, 0, &p, &stat); - } - } - - if (! err) - { - *s = stat; - *port = p; - } - - return err; -} - -/* Deallocate all ports contained in NODE and free per-ulfs data - structures. */ -void -node_ulfs_free (node_t *node) -{ - - node_ulfs_iterate_unlocked (node) - { - if (port_valid (node_ulfs->port) - && node_ulfs->port != underlying_node) - port_dealloc (node_ulfs->port); - } - - free (node->nn->ulfs); -} - -/* Initialize per-ulfs data structures for NODE. The ulfs_lock must - be held by the caller. */ -error_t -node_ulfs_init (node_t *node) -{ - node_ulfs_t *ulfs_new; - error_t err = 0; - - ulfs_new = malloc (ulfs_num * sizeof (node_ulfs_t)); - if (! ulfs_new) - { - err = ENOMEM; - return err; - } - - if (node->nn->ulfs) - node_ulfs_free (node); - - node->nn->ulfs = ulfs_new; - node->nn->ulfs_num = ulfs_num; - - node_ulfs_iterate_unlocked (node) - { - node_ulfs->flags = 0; - node_ulfs->port = port_null; - } - - return err; -} - -/* Read the merged directory entries from NODE, which must be - locked, into *DIRENTS. */ -error_t -node_entries_get (node_t *node, node_dirent_t **dirents) -{ - struct dirent **dirent_list, **dirent; - node_dirent_t *node_dirent_list = NULL; - size_t dirent_data_size; - char *dirent_data; - error_t err = 0; - - /* Add a dirent to the list. If an entry with the specified name - already exists, reuse that entry. Otherwise create a new - one. */ - error_t node_dirent_add (char *name, ino_t fileno, int type) - { - error_t e = 0; - node_dirent_t *node_dirent; - node_dirent_t *node_dirent_new; - struct dirent *dirent_new; - int name_len = strlen (name); - int size = DIRENT_LEN (name_len); - - - for (node_dirent = node_dirent_list; - node_dirent && strcmp (node_dirent->dirent->d_name, name); - node_dirent = node_dirent->next); - - if (node_dirent) - { - /* Reuse existing entry. */ - - node_dirent->dirent->d_fileno = fileno; - node_dirent->dirent->d_type = type; - return e; - } - - /* Create new entry. */ - - node_dirent_new = malloc (sizeof (node_dirent_t)); - if (!node_dirent_new) - { - e = ENOMEM; - return e; - } - - dirent_new = malloc (size); - if (!dirent_new) - { - free (node_dirent_new); - e = ENOMEM; - return e; - } - - /* Fill dirent. */ - dirent_new->d_fileno = fileno; - dirent_new->d_type = type; - dirent_new->d_reclen = size; - strcpy ((char *) dirent_new + DIRENT_NAME_OFFS, name); - - /* Add dirent to the list. */ - node_dirent_new->dirent = dirent_new; - node_dirent_new->next = node_dirent_list; - node_dirent_list = node_dirent_new; - - return e; - } - - node_ulfs_iterate_unlocked(node) - { - if (!port_valid (node_ulfs->port)) - continue; - - err = dir_entries_get (node_ulfs->port, &dirent_data, - &dirent_data_size, &dirent_list); - if (err) - continue; - - for (dirent = dirent_list; (! err) && *dirent; dirent++) - if (strcmp ((*dirent)->d_name, ".") - && strcmp ((*dirent)->d_name, "..")) - err = node_dirent_add ((*dirent)->d_name, - (*dirent)->d_fileno, - (*dirent)->d_type); - - free (dirent_list); - munmap (dirent_data, dirent_data_size); - } - - if (err) - node_entries_free (node_dirent_list); - else - *dirents = node_dirent_list; - - return err; -} - -/* Free DIRENTS. */ -void -node_entries_free (node_dirent_t *dirents) -{ - node_dirent_t *dirent, *dirent_next; - - for (dirent = dirents; dirent; dirent = dirent_next) - { - dirent_next = dirent->next; - free (dirent->dirent); - free (dirent); - } -} - -/* Create the root node (and it's according lnode) and store it in - *ROOT_NODE. */ -error_t -node_create_root (node_t **root_node) -{ - lnode_t *lnode; - node_t *node; - error_t err = 0; - - err = lnode_create (NULL, &lnode); - if (err) - return err; - - err = node_create (lnode, &node); - if (err) - { - lnode_destroy (lnode); - return err; - } - - mutex_unlock (&lnode->lock); - *root_node = node; - return err; -} - -/* Initialize the ports to the underlying filesystems for the root - node. */ - -error_t -node_init_root (node_t *node) -{ - error_t err; - ulfs_t *ulfs; - int i = 0; - - mutex_lock (&ulfs_lock); - - err = node_ulfs_init (node); - if (err) - { - mutex_unlock (&ulfs_lock); - return err; - } - - node_ulfs_iterate_unlocked (node) - { - - if (err) - break; - - err = ulfs_get_num (i, &ulfs); - if (err) - break; - - if (ulfs->path) - node_ulfs->port = file_name_lookup (ulfs->path, - O_READ | O_DIRECTORY, 0); - else - node_ulfs->port = underlying_node; - - if (! port_valid (node_ulfs->port)) - { - err = errno; - break; - } - - node_ulfs->flags |= FLAG_NODE_ULFS_FIXED; - i++; - } - - mutex_unlock (&ulfs_lock); - return err; -} diff --git a/unionfs/node.h b/unionfs/node.h deleted file mode 100644 index 41ae43ad..00000000 --- a/unionfs/node.h +++ /dev/null @@ -1,135 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - 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. */ - -/* node management. */ - -#ifndef INCLUDED_NODE_H -#define INCLUDED_NODE_H - -#include <error.h> -#include <sys/stat.h> -#include <hurd/netfs.h> - -typedef struct node node_t; - -#include "lnode.h" - -/* per-ulfs data for each node. */ -struct node_ulfs -{ - int flags; /* Flags associated for this - underlying filesystem. */ - file_t port; /* A port to the underlying - filesystem. */ -}; -typedef struct node_ulfs node_ulfs_t; - -/* Flags. */ - -/* The according port should not be updated. */ -#define FLAG_NODE_ULFS_FIXED 0x00000001 - -struct netnode -{ - lnode_t *lnode; /* A reference to the according light - node. */ - int flags; /* Associated flags. */ - node_ulfs_t *ulfs; /* Array holding data for each - underlying filesystem. */ - int ulfs_num; /* Number of entries in ULFS. */ - node_t *ncache_next; - node_t *ncache_prev; -}; -typedef struct netnode netnode_t; - -/* Flags. */ -#define FLAG_NODE_INVALIDATE 0x00000001 -#define FLAG_NODE_ULFS_UPTODATE 0x00000002 - -typedef struct node_dirent -{ - struct dirent *dirent; - struct node_dirent *next; -} node_dirent_t; - -/* Create a new node, derived from a light node, add a reference to - the light node. */ -error_t node_create (lnode_t *lnode, node_t **node); - -/* Destroy a node, remove one reference from the associated light - node. */ -void node_destroy (node_t *node); - -/* Make sure that all ports to the underlying filesystems of NODE, - which must be locked, are uptodate. */ -error_t node_update (node_t *node); - -/* Create a directory named NAME beneath DIR on all the (writable) underlying - filesystems. */ -error_t node_dir_create (node_t *dir, char *name, mode_t mode); - -/* Remove all directory named NAME beneath DIR on all underlying filesystems. - Fails if we cannot remove all the directories. */ -error_t node_dir_remove (node_t *dir, char *name); - -/* Remove all files named NAME beneath DIR on the underlying filesystems - with FLAGS as openflags. */ -error_t node_unlink_file (node_t *dir, char *name); - -/* Lookup a file named NAME beneath DIR on the underlying filesystems - with FLAGS as openflags. Return the first port successfully looked - up in *PORT and according stat information in *STAT. */ -error_t node_lookup_file (node_t *dir, char *name, int flags, - file_t *port, struct stat *stat); - -/* Initialize per-ulfs data structures for NODE. The ulfs_lock must - be held by the caller. */ -error_t node_ulfs_init (node_t *node); - -/* Read the merged directory entries from NODE, which must be - locked, into *DIRENTS. */ -error_t node_entries_get (node_t *node, node_dirent_t **dirents); - -/* Free DIRENTS. */ -void node_entries_free (node_dirent_t *dirents); - -/* Create the root node (and it's according lnode) and store it in - *ROOT_NODE. */ -error_t node_create_root (node_t **root_node); - -/* Initialize the ports to the underlying filesystems for the root - node. */ -error_t node_init_root (node_t *node); - -/* Return non-zero, if NODE is the root node. */ -#define node_is_root(node) (node)->nn->lnode->dir ? 0 : 1 - -/* Iterate over the per-ulfs data in NODE, which must be locked by the - caller. */ -#define node_ulfs_iterate_unlocked(node) \ - for (node_ulfs_t *node_ulfs = (node)->nn->ulfs; \ - node_ulfs < (node)->nn->ulfs + (node)->nn->ulfs_num; \ - node_ulfs++) - -#define node_ulfs_iterate_reverse_unlocked(node) \ - for (node_ulfs_t *node_ulfs = (node)->nn->ulfs + (node)->nn->ulfs_num - 1;\ - node_ulfs >= (node)->nn->ulfs; \ - node_ulfs--) - -#endif diff --git a/unionfs/options.c b/unionfs/options.c deleted file mode 100644 index ef29a020..00000000 --- a/unionfs/options.c +++ /dev/null @@ -1,225 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - 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. */ - -/* Argument parsing. */ - -#define _GNU_SOURCE - -#include <argp.h> -#include <error.h> - -#include "options.h" -#include "ulfs.h" -#include "ncache.h" -#include "unionfs.h" -#include "node.h" -#include "version.h" -#include "pattern.h" -#include "stow.h" -#include "update.h" - -/* This variable is set to a non-zero value after parsing of the - startup options. Whenever the argument parser is later called to - modify the underlying filesystems of the root node, the root node - is initialized accordingly directly by the parser. */ -static int parsing_startup_options_finished; - -/* Argp options common to the runtime and startup parser. */ -static const struct argp_option argp_common_options[] = - { - { OPT_LONG_UNDERLYING, OPT_UNDERLYING, 0, 0, - "add the underlying node to the unionfs" }, - { OPT_LONG_WRITABLE, OPT_WRITABLE, 0, 0, - "specify the following filesystem as writable" }, - { OPT_LONG_DEBUG, OPT_DEBUG, 0, OPTION_HIDDEN, - "send debugging messages to stderr" }, - { OPT_LONG_CACHE_SIZE, OPT_CACHE_SIZE, "SIZE", 0, - "specify the maximum number of nodes in the cache" }, - { 0, 0, 0, 0, "Runtime options:", 1 }, - { OPT_LONG_STOW, OPT_STOW, "STOWDIR", 0, - "stow given directory", 1}, - { OPT_LONG_PRIORITY, OPT_PRIORITY, "VALUE", 0, - "Set the priority for the following filesystem to VALUE", 1}, - { OPT_LONG_PATTERN, OPT_PATTERN, "PATTERN", 0, - "add only nodes of the underlying filesystem matching pattern", 1}, - { OPT_LONG_REMOVE, OPT_REMOVE, 0, 0, - "remove the following filesystem", 1 }, - { OPT_LONG_ADD, OPT_ADD, 0, 0, - "add the following filesystem (Default)", 1 }, - { 0 } - }; - -/* Argp options only meaningful for startup parsing. */ -static const struct argp_option argp_startup_options[] = - { - { 0 } - }; - -/* Argp parser function for the common options. */ -static error_t -argp_parse_common_options (int key, char *arg, struct argp_state *state) -{ - static int ulfs_flags = 0, ulfs_mode = 0, ulfs_modified = 0, - ulfs_match = 0, ulfs_priority = 0; - static struct patternlist ulfs_patternlist = - { - .lock = MUTEX_INITIALIZER, - .head = NULL - }; - error_t err = 0; - - switch (key) - { - case OPT_WRITABLE: /* --writable */ - ulfs_flags |= FLAG_ULFS_WRITABLE; - break; - - case OPT_PRIORITY: /* --priority */ - ulfs_priority = strtol (arg, NULL, 10); - break; - - case OPT_DEBUG: /* --debug */ - unionfs_flags |= FLAG_UNIONFS_MODE_DEBUG; - break; - - case OPT_CACHE_SIZE: /* --cache-size */ - ncache_size = strtol (arg, NULL, 10); - break; - - case OPT_ADD: /* --add */ - ulfs_mode = ULFS_MODE_ADD; - break; - - case OPT_REMOVE: /* --remove */ - ulfs_mode = ULFS_MODE_REMOVE; - break; - - case OPT_PATTERN: /* --match */ - ulfs_match = 1; - patternlist_add (&ulfs_patternlist, arg); - break; - - case OPT_STOW: /* --stow */ - err = stow_diradd (arg, ulfs_flags, &ulfs_patternlist, ulfs_priority); - if (err) - error (EXIT_FAILURE, err, "stow_diradd"); - ulfs_modified = 1; - ulfs_flags = ulfs_mode = ulfs_priority = 0; - ulfs_match = 0; - break; - - case OPT_UNDERLYING: /* --underlying */ - case ARGP_KEY_ARG: - - if (ulfs_mode == ULFS_MODE_REMOVE) - { - err = ulfs_unregister (arg); - if (err == ENOENT) - /* It is not a fatal error, when the user tries to remove - a filesystem, which is not used by unionfs. */ - err = 0; - } - else - err = ulfs_register (arg, ulfs_flags, ulfs_priority); - if (err) - error (EXIT_FAILURE, err, "ulfs_register"); - ulfs_modified = 1; - ulfs_flags = ulfs_mode = ulfs_priority = 0; - ulfs_match = 0; - break; - - case ARGP_KEY_END: - ulfs_flags = ulfs_mode = 0; - if (ulfs_modified && parsing_startup_options_finished) - { - root_update_schedule (); - } - else - { - ncache_reset (); - } - ulfs_modified = 0; - - if (! parsing_startup_options_finished) - parsing_startup_options_finished = 1; - break; - - default: - err = ARGP_ERR_UNKNOWN; - break; - } - - return err; -} - -/* Argp parser function for the startup oprtions. */ -static error_t -argp_parse_startup_options (int key, char *arg, struct argp_state *state) -{ - error_t err = 0; - - switch (key) - { - default: - err = ARGP_ERR_UNKNOWN; - break; - } - - return err; -} - -/* Argp parser for only the common options. */ -static const struct argp argp_parser_common_options = - { argp_common_options, argp_parse_common_options, 0, 0, 0 }; - -/* Argp parser for only the startup options. */ -static struct argp argp_parser_startup_options = - { argp_startup_options, argp_parse_startup_options, 0, 0, 0 }; - -/* The children parser for runtime arguments. */ -static const struct argp_child argp_children_runtime[] = - { - { &argp_parser_common_options }, - { &netfs_std_runtime_argp }, - { 0 } - }; - -/* The children parser for startup arguments. */ -const struct argp_child argp_children_startup[] = - { - { &argp_parser_startup_options }, - { &argp_parser_common_options }, - { &netfs_std_startup_argp }, - { 0 } - }; - -const char *argp_program_version = STANDARD_HURD_VERSION (unionfs); -const char *argp_program_bug_address = -"Gianluca Guida <glguida@gmail.com>"; - -#define ARGS_DOC "FILESYSTEMS ..." -#define DOC "Hurd unionfs server" - -/* The final argp parser for runtime arguments. */ -struct argp argp_runtime = - { 0, 0, 0, 0, argp_children_runtime }; - -/* The final argp parser for startup arguments. */ -struct argp argp_startup = - { 0, 0, ARGS_DOC, DOC, argp_children_startup }; diff --git a/unionfs/options.h b/unionfs/options.h deleted file mode 100644 index eb74ce61..00000000 --- a/unionfs/options.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - 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. */ - -/* Argument parsing. */ - -/* The possible short options. */ -#define OPT_UNDERLYING 'u' -#define OPT_WRITABLE 'w' -#define OPT_DEBUG 'd' -#define OPT_CACHE_SIZE 'c' -#define OPT_REMOVE 'r' -#define OPT_ADD 'a' -#define OPT_PATTERN 'm' -#define OPT_PRIORITY 'p' -#define OPT_STOW 's' - -/* The long options. */ -#define OPT_LONG_UNDERLYING "underlying" -#define OPT_LONG_WRITABLE "writable" -#define OPT_LONG_DEBUG "debug" -#define OPT_LONG_CACHE_SIZE "cache-size" -#define OPT_LONG_REMOVE "remove" -#define OPT_LONG_ADD "add" -#define OPT_LONG_PATTERN "match" -#define OPT_LONG_PRIORITY "priority" -#define OPT_LONG_STOW "stow" - -#define OPT_LONG(o) "--" o - -/* The final argp parser for runtime arguments. */ -extern struct argp argp_startup; - -/* The final argp parser for startup arguments. */ -extern struct argp argp_runtime; - -#define ULFS_MODE_ADD 0 -#define ULFS_MODE_REMOVE 1 diff --git a/unionfs/pattern.c b/unionfs/pattern.c deleted file mode 100644 index 68a07917..00000000 --- a/unionfs/pattern.c +++ /dev/null @@ -1,131 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Gianluca Guida <glguida@gmail.com>. - - 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. */ - -/* Pattern list management. */ - -#define _GNU_SOURCE - -#include <hurd/netfs.h> -#include <stdlib.h> -#include <fnmatch.h> -#include <errno.h> - -#include "pattern.h" - -/* Add a wildcard expression *PATTERN to **PATTERNLIST. */ -error_t -patternlist_add (struct patternlist *list, char *pattern) -{ - error_t err = 0; - struct pattern *listentry; - char *dup; - - if (pattern == NULL) /* BUG. */ - err = EINVAL; - - if (err) - return err; - - dup = strdup (pattern); - if (dup == NULL) - err = ENOMEM; - - if (err) - return err; - - listentry = malloc (sizeof (struct pattern)); - if (listentry == NULL) - err = ENOMEM; - - if (err) - return err; - - listentry->pattern = dup; - - mutex_lock (& (list->lock)); - if (list->head == NULL) /* List is empty. */ - { - list->head = listentry; - listentry->next = NULL; - } - else - { - listentry->next = list->head; - list->head = listentry; - } - mutex_unlock (& (list->lock)); - - return err; -} - -/* Check for match all pattern of the list *LIST, returning logical OR - of results. */ -int -patternlist_match (struct patternlist *list, char *string) -{ - struct pattern *ptr; - error_t err = ~0; /* Return false by default */ - - ptr = list->head; - - mutex_lock (&list->lock); - while (ptr != NULL) - { - err = fnmatch (ptr->pattern, string, FNM_FILE_NAME); - - if (!err) /* String matched. */ - break; - - ptr = ptr->next; - } - mutex_unlock (&list->lock); - - return err; -} - -/* Free all resource used by *PATTERNLIST. */ -void -patternlist_destroy (struct patternlist *list) -{ - struct pattern *next, *ptr = list->head; - - mutex_lock (& (list->lock)); - while (ptr != NULL) - { - next = ptr->next; - - free (ptr); - - ptr = next; - } - mutex_unlock (& (list->lock)); -} - -/* Return nonzero if *PATTERNLIST is empty. */ -int -patternlist_isempty (struct patternlist *list) -{ - int ret; - - mutex_lock (& (list->lock)); - ret = (list->head == NULL); - mutex_unlock (& (list->lock)); - - return ret; -} diff --git a/unionfs/pattern.h b/unionfs/pattern.h deleted file mode 100644 index 1bab9933..00000000 --- a/unionfs/pattern.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Gianluca Guida <glguida@gmail.com>. - - 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. */ - -/* Pattern list management. */ - -#ifndef _PATTERN_H -#define _PATTERN_H - -#include <hurd/netfs.h> /* For mutex stuff. */ - -struct pattern -{ - char *pattern; - - struct pattern *next; -}; - -struct patternlist -{ - struct mutex lock; - struct pattern *head; -}; - -/* Add a wildcard expression *PATTERN to **PATTERNLIST. */ -extern error_t patternlist_add (struct patternlist *list, char *pattern); - -/* Check for match all pattern of the list *LIST, returning logical OR - of results. */ -extern int patternlist_match (struct patternlist *list, char *string); - -/* Free all resource used by *PATTERNLIST */ -extern void patternlist_destroy (struct patternlist *list); - -/* Return nonzero if *PATTERNLIST is empty */ -extern int patternlist_isempty (struct patternlist *list); - -#endif /* _PATTERN_H */ diff --git a/unionfs/stow-mutations.h b/unionfs/stow-mutations.h deleted file mode 100644 index d36280d2..00000000 --- a/unionfs/stow-mutations.h +++ /dev/null @@ -1,27 +0,0 @@ -/* stow-mutations.h - MIG mutations unionfs. - Copyright (C) 2005 Free Software Foundation, Inc. - Written by Gianluca Guida <glguida@gmail.com>. - - This file is part of the GNU Hurd. - - The GNU Hurd 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, or (at - your option) any later version. - - The GNU Hurd 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, USA. */ - -/* Only CPP macro definitions should go in this file. */ - -#define FS_NOTIFY_INTRAN stow_notify_t begin_using_notify_port (fs_notify_t) -#define FS_NOTIFY_DESTRUCTOR end_using_notify_port (stow_notify_t) - -#define FS_NOTIFY_IMPORTS import "stow-priv.h"; - diff --git a/unionfs/stow-priv.h b/unionfs/stow-priv.h deleted file mode 100644 index 2212ac98..00000000 --- a/unionfs/stow-priv.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2005 Free Software Foundation, Inc. - Written by Gianluca Guida <glguida@gmail.com>. - - 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. */ - -#ifndef __STOW_PRIVDATA_H__ -#define __STOW_PRIVDATA_H__ - -#include <hurd/ports.h> - -struct stow_notify -{ - struct port_info pi; - - char *dir_name; - struct stow_privdata *priv; -}; -typedef struct stow_notify *stow_notify_t; - - -/* Called by MiG to translate ports into stow_notify_t. mutations.h - arranges for this to happen for the fs_notify interfaces. */ -stow_notify_t begin_using_notify_port (fs_notify_t port); - - -/* Called by MiG after server routines have been run; this balances - begin_using_notify_port, and is arranged for the fs_notify - interfaces by mutations.h. */ -void end_using_notify_port (stow_notify_t cred); - -#endif /* STOW_PRIVDATA_H */ diff --git a/unionfs/stow.c b/unionfs/stow.c deleted file mode 100644 index fa997472..00000000 --- a/unionfs/stow.c +++ /dev/null @@ -1,328 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2005 Free Software Foundation, Inc. - Written by Gianluca Guida <glguida@gmail.com>. - - 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. */ - - -/* Stow mode for unionfs. */ - -#define _GNU_SOURCE - -#include <argp.h> -#include <error.h> - -#include "ulfs.h" -#include "lib.h" -#include "pattern.h" -#include "update.h" - -struct stow_privdata -{ - struct patternlist *patternlist; - int flags; - int priority; - struct mutex lock; -}; - -static error_t -_stow_registermatchingdirs (char *arg, char *dirpath, void *priv) -{ - error_t err = 0; - char *filepath; - - struct stow_privdata *privdata = (struct stow_privdata *) priv ; - - err = patternlist_match (privdata->patternlist, arg); - if (err) - return 0; /* It doesn't match. This is not an error. */ - - filepath = make_filepath (dirpath, arg); - - err = ulfs_register (filepath, privdata->flags, privdata->priority); - - free (filepath); - - if (err) - return err; - - return 0; -} - -static error_t -_stow_scanstowentry (char *arg, char *dirpath, void *priv) -{ - char *filepath = dirpath; - error_t err; - - struct stow_privdata *privdata = (struct stow_privdata *) priv ; - - if (dirpath) - { - char *tmp; - tmp = make_filepath (dirpath, arg); - filepath = make_filepath (tmp, "/"); - free (tmp); - } - - mutex_lock (&privdata->lock); - - if (patternlist_isempty (privdata->patternlist)) - { - - err = ulfs_register (filepath, privdata->flags, privdata->priority); - if (err) - { - mutex_unlock (&privdata->lock); - return err; - } - - } - else - { - err = for_each_subdir_priv (filepath, _stow_registermatchingdirs, priv); - if (err) - { - mutex_unlock (&privdata->lock); - free (filepath); - return err; - } - } - - free (filepath); - mutex_unlock (&privdata->lock); - return err; -} - - -/* Implement server for fs_notify. */ - -#include <cthreads.h> -#include <hurd/port.h> - -#include "stow-priv.h" -#include "ncache.h" - -struct port_bucket *stow_port_bucket; -struct port_class *stow_port_class; - -static error_t -_stow_notify_init(char *dir_name, void *priv) -{ - error_t err; - file_t dir_port; - mach_port_t notify_port; - stow_notify_t stow_notify_port; - - err = ports_create_port (stow_port_class, stow_port_bucket, - sizeof (*stow_notify_port), - &stow_notify_port); - if (err) - return err; - - stow_notify_port->dir_name = dir_name; - stow_notify_port->priv = priv; - - dir_port = file_name_lookup (dir_name, 0, 0); - - if (!port_valid (dir_port)) - return ENOENT; /* ? */ - - - notify_port = ports_get_right (stow_notify_port); - - if (!port_valid (notify_port)) - { - port_dealloc (dir_port); - return EACCES; /* ? */ - } - - err = dir_notice_changes (dir_port, notify_port, - MACH_MSG_TYPE_MAKE_SEND); - if (err) - { - port_dealloc (dir_port); - port_dealloc (notify_port); - return err; - } - - return err; -} - -/* Called by MiG to translate ports into stow_notify_t. mutations.h - arranges for this to happen for the fs_notify interfaces. */ -stow_notify_t -begin_using_notify_port (fs_notify_t port) -{ - return ports_lookup_port (stow_port_bucket, port, stow_port_class); -} - -/* Called by MiG after server routines have been run; this balances - begin_using_notify_port, and is arranged for the fs_notify - interfaces by mutations.h. */ -void -end_using_notify_port (stow_notify_t cred) -{ - if (cred) - ports_port_deref (cred); -} - -/* We don't ask for file_changes, but this function has to be defined . */ -kern_return_t -stow_S_file_changed (stow_notify_t notify, natural_t tickno, - file_changed_type_t change, loff_t start, - loff_t end) -{ - return EOPNOTSUPP; -} - -/* Called when we receive a dir_changed message. */ -kern_return_t -stow_S_dir_changed (stow_notify_t notify, natural_t tickno, - dir_changed_type_t change, string_t name) -{ - error_t err; - - if (!notify || !notify->dir_name || !notify->priv) - return EOPNOTSUPP; - - switch (change) - { - case DIR_CHANGED_NULL: - break; - case DIR_CHANGED_NEW: - root_update_disable (); - - err = _stow_scanstowentry (name, notify->dir_name, notify->priv); - if (err) - debug_msg_send ("scanstowentry: %s\n", strerror (err)); - - root_update_schedule (); - root_update_enable (); - break; - - case DIR_CHANGED_UNLINK: - root_update_schedule (); - break; - - default: - debug_msg_send ("unsupported dir change notify"); - return EINVAL; - } - - return 0; -} - -/* This is the server thread waiting for dir_changed messages. */ -static void -_stow_notify_thread() -{ - int stow_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp) - { - int stow_fs_notify_server (mach_msg_header_t *inp, - mach_msg_header_t *outp); - - return (stow_fs_notify_server (inp, outp)); - } - - do - { - ports_manage_port_operations_multithread (stow_port_bucket, - stow_demuxer, - 1000 * 60 * 2, - 1000 * 60 * 10, - 0); - } - while (1); -} - - - -/* Interface to unionfs. */ - -error_t -stow_diradd (char *dir, int flags, struct patternlist *patternlist, - int priority) -{ - - error_t err; - struct stow_privdata *mypriv; - int dir_len; - - dir_len = strlen(dir); - if (dir_len == 0) - { - return EOPNOTSUPP; - } - - if (dir[dir_len - 1 ] != '/') - { - char *tmp; - - tmp = (char *) malloc (dir_len + 1); - - if (tmp == NULL) - return ENOMEM; - - strncpy (tmp, dir, dir_len); - - tmp[dir_len] = '/'; - - dir = tmp; - } - - mypriv = malloc (sizeof (struct stow_privdata)); - if (!mypriv) - { - free (dir); - return ENOMEM; - } - - mypriv->patternlist = patternlist; - mypriv->flags = flags; - mypriv->priority = priority; - mutex_init (&mypriv->lock); - - err = for_each_subdir_priv (dir, _stow_scanstowentry, (void *)mypriv); - if (err) - { - /* FIXME: rescan and delete previous inserted things. */ - return err; - } - - err = _stow_notify_init (dir, mypriv); - assert (!err); - - return err; -} - -error_t -stow_init (void) -{ - error_t err = 0; - - stow_port_bucket = ports_create_bucket (); - if (!stow_port_bucket) - return errno; - - stow_port_class = ports_create_class (NULL, NULL); - if (!stow_port_class) - return errno; - - cthread_detach (cthread_fork ( (cthread_fn_t)_stow_notify_thread, 0)); - - return err; -} diff --git a/unionfs/stow.h b/unionfs/stow.h deleted file mode 100644 index 54ff7060..00000000 --- a/unionfs/stow.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2005 Free Software Foundation, Inc. - Written by Gianluca Guida <glguida@gmail.com>. - - 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. */ - -/* Stow mode for unionfs. */ - -#ifndef _STOW_H -#define _STOW_H - -#include "pattern.h" - -error_t stow_init (void); -error_t stow_diradd (char *, int, struct patternlist *, int); - -#endif /* _STOW_H */ diff --git a/unionfs/ulfs.c b/unionfs/ulfs.c deleted file mode 100644 index 3c565a5c..00000000 --- a/unionfs/ulfs.c +++ /dev/null @@ -1,321 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - 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. */ - -/* Underlying filesystem management. */ - -#define _GNU_SOURCE - -#include <hurd/netfs.h> -#include <stdlib.h> -#include <error.h> -#include <string.h> - -#include "unionfs.h" -#include <fcntl.h> - -#include "lib.h" -#include "ulfs.h" - -/* The start of the ulfs chain. */ -ulfs_t *ulfs_chain_start; - -/* The end of the ulfs chain, we need this, to go through the chain in - reversed order. */ -ulfs_t *ulfs_chain_end; - -/* Number of registered underlying filesystems. */ -unsigned int ulfs_num; - -/* The lock protecting the ulfs data structures. */ -struct mutex ulfs_lock = MUTEX_INITIALIZER; - -/* Create a new ulfs element. */ -static error_t -ulfs_create (char *path, ulfs_t **ulfs) -{ - ulfs_t *ulfs_new = malloc (sizeof (ulfs_t)); - error_t err = 0; - - if (! ulfs_new) - err = ENOMEM; - else - { - char *path_cp = path ? strdup (path) : NULL; - - if (path && (! path_cp)) - { - err = ENOMEM; - free (ulfs_new); - } - else - { - ulfs_new->path = path_cp; - ulfs_new->flags = 0; - ulfs_new->next = NULL; - ulfs_new->prev = NULL; - *ulfs = ulfs_new; - } - } - return err; -} - -/* Destroy an ulfs element. */ -static void -ulfs_destroy (ulfs_t *ulfs) -{ - free (ulfs->path); - free (ulfs); -} - -/* Install ULFS into the linked list of registered filesystems in - * priority order. */ -static void -ulfs_install (ulfs_t *ulfs) -{ - ulfs_t *u = ulfs_chain_start; - int insert_at_end = 0; - if (ulfs_num == 0) - { - ulfs_chain_start = ulfs; - return; - } - - /* walk the chain until a filesystem has a priority that's too high. */ - while (u->priority > ulfs->priority) - { - if (u->next == NULL) - { - insert_at_end = 1; - break; - } - u = u->next; - } - - if (insert_at_end) - { - u->next = ulfs; - ulfs->prev = u; - } - else - { - if (u == ulfs_chain_start) - { - ulfs_chain_start = ulfs; - ulfs->next = u; - ulfs->prev = NULL; - u->prev = ulfs; - } - else - { - ulfs->next = u; - ulfs->prev = u->prev; - u->prev->next = ulfs; - u->prev = ulfs; - } - } - - return; -} - -/* Remove ULFS from the linked list of registered filesystems. */ -static void -ulfs_uninstall (ulfs_t *ulfs) -{ - if (ulfs == ulfs_chain_start) - ulfs_chain_start = ulfs->next; - - if (ulfs->next) - ulfs->next->prev = ulfs->prev; - - if (ulfs->prev) - ulfs->prev->next = ulfs->next; -} - -/* Get an ulfs element by it's index. */ -error_t -ulfs_get_num (int num, ulfs_t **ulfs) -{ - error_t err = EINVAL; - ulfs_t *u; - int i; - - for (u = ulfs_chain_start, i = 0; - u && i < num; - u = u->next, i++); - if (u) - { - err = 0; - *ulfs = u; - } - - return err; -} - -/* Get an ulfs element by the associated path. */ -static error_t -ulfs_get_path (char *path, ulfs_t **ulfs) -{ - error_t err = ENOENT; - ulfs_t *u; - - for (u = ulfs_chain_start; - u && (! (((! path) && path == u->path) - || (path && u->path && (! strcmp (path, u->path))))); - u = u->next); - if (u) - { - err = 0; - *ulfs = u; - } - return err; -} - -error_t -ulfs_for_each_under_priv (char *path_under, - error_t (*func) (char *, char *, void *), - void *priv) -{ - error_t err = 0; - ulfs_t *u; - size_t length; - - length = strlen (path_under); - - for (u = ulfs_chain_start; u; u = u->next) - { - if (!u->path) - continue; - - if (memcmp (u->path, path_under, length)) - continue; - - /* This ulfs is under path_under. */ - func ((char *)(u->path + length), path_under, priv); - } - - return err; -} - -/* Register a new underlying filesystem. */ -error_t -ulfs_register (char *path, int flags, int priority) -{ - ulfs_t *ulfs; - error_t err; - - if (path) - { - err = check_dir (path); - if (err) - return err; - } - - mutex_lock (&ulfs_lock); - err = ulfs_create (path, &ulfs); - if (! err) - { - ulfs->flags = flags; - ulfs->priority = priority; - ulfs_install (ulfs); - ulfs_num++; - } - mutex_unlock (&ulfs_lock); - return err; -} - -/* Check for deleted ulfs entries. */ -/* FIXME: Ugly as hell. Rewrite the whole ulfs.c */ -void -ulfs_check () -{ - ulfs_t *u; - file_t p; - - struct ulfs_destroy - { - ulfs_t *ulfs; - - struct ulfs_destroy *next; - } *ulfs_destroy_q = NULL; - - mutex_lock (&ulfs_lock); - - u = ulfs_chain_start; - while (u) - { - - if (u->path) - p = file_name_lookup (u->path, O_READ | O_DIRECTORY, 0); - else - p = underlying_node; - - if (! port_valid (p)) - { - struct ulfs_destroy *ptr; - - /* Add to destroy list. */ - ptr = malloc (sizeof (struct ulfs_destroy)); - assert (ptr); - - ptr->ulfs = u; - - ptr->next = ulfs_destroy_q; - ulfs_destroy_q = ptr; - } - - u = u->next; - } - - while (ulfs_destroy_q) - { - struct ulfs_destroy *ptr; - - ptr = ulfs_destroy_q; - ulfs_destroy_q = ptr->next; - - ulfs_uninstall (ptr->ulfs); - ulfs_destroy (ptr->ulfs); - ulfs_num--; - - free (ptr); - } - - mutex_unlock (&ulfs_lock); - -} - -/* Unregister an underlying filesystem. */ -error_t -ulfs_unregister (char *path) -{ - ulfs_t *ulfs; - error_t err; - - mutex_lock (&ulfs_lock); - err = ulfs_get_path (path, &ulfs); - if (! err) - { - ulfs_uninstall (ulfs); - ulfs_destroy (ulfs); - ulfs_num--; - } - mutex_unlock (&ulfs_lock); - - return err; -} diff --git a/unionfs/ulfs.h b/unionfs/ulfs.h deleted file mode 100644 index 532e3c74..00000000 --- a/unionfs/ulfs.h +++ /dev/null @@ -1,75 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - 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. */ - -/* Underlying filesystem management. */ - -#ifndef INCLUDED_ULFS_H -#define INCLUDED_ULFS_H - -/* The structure for each registered underlying filesystem. */ -typedef struct ulfs -{ - char *path; - int flags; - int priority; - struct ulfs *next, *prev; -} ulfs_t; - -/* Flags. */ - -/* The according ulfs is marked writable. */ -#define FLAG_ULFS_WRITABLE 0x00000001 - -/* The start of the ulfs chain. */ -extern ulfs_t *ulfs_chain_start; - -/* The end of the ulfs chain, we need this, to go through the chain in - reversed order. */ -extern ulfs_t *ulfs_chain_end; - -/* Number of registered underlying filesystems. */ -extern unsigned int ulfs_num; - -/* The lock protecting the ulfs data structures. */ -extern struct mutex ulfs_lock; - -/* Register a new underlying filesystem. */ -error_t ulfs_register (char *path, int flags, int priority); - -/* Unregister an underlying filesystem. */ -error_t ulfs_unregister (char *path); - -/* Get an ULFS element by it's index. */ -error_t ulfs_get_num (int num, ulfs_t **ulfs); - -/* Removes invalid ulfs entries. */ -void ulfs_check (void); - -#define ulfs_iterate \ - for (ulfs_t *ulfs = (mutex_lock (&ulfs_lock), \ - ulfs_chain_start); \ - ulfs || (mutex_unlock (&ulfs_lock), 0); \ - ulfs = ulfs->next) - -#define ulfs_iterate_unlocked \ - for (ulfs_t *ulfs = ulfs_chain_start; \ - ulfs; \ - ulfs = ulfs->next) - -#endif diff --git a/unionfs/unionfs.h b/unionfs/unionfs.h deleted file mode 100644 index 8f5a0873..00000000 --- a/unionfs/unionfs.h +++ /dev/null @@ -1,90 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - 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. */ - -/* This unionfs knows about two different kind of nodes: `light nodes' - (in short: lnode) and `nodes' (or: netfs nodes) as used by - libnetfs. They have different tasks and therefore this division - makes sense. - - lnodes form the filesystem tree as seen by the user; most - importantly they contain the `name' of the node. - - lnodes are small and cheap, they are not cached (nodes are). - - lnodes are usually created when a node is looked up and destroyed - when that node gets destroyed; but there are also reasons for - lnodes _not_ being destroyed. - - The distinction makes it possible to keep certain information for - the unionfs in these lnodes while netfs nodes don't have to stay in - memory. - - lnodes have to be looked up first before a node is looked up. Each - lnode contains a pointer to the netfs node, which might be NULL in - case the netfs node is not in memory anymore. */ - -/* General information and properties for the unionfs. */ - -#ifndef INCLUDED_UNIONFS_H -#define INCLUDED_UNIONFS_H - -#include <hurd/netfs.h> -#include <sys/types.h> - -#include "node.h" -#include "lib.h" - -/* Default maximum number of nodes in the cache. */ -#define NCACHE_SIZE 256 - -/* The inode for the root node. */ -#define UNIONFS_ROOT_INODE 1 - -/* Flags for UNIONFS_FLAGS. */ - -/* Print debugging messages to stderr. */ -#define FLAG_UNIONFS_MODE_DEBUG 0x00000001 -/* Use copy-on-write. */ -#define FLAG_UNIONFS_MODE_COW 0x00000002 - -/* Flags describing certain properties of the unionfs. */ -extern int unionfs_flags; - -/* The filesystem id (the pid). */ -extern pid_t fsid; - -/* Mapped time, used for updating node information. */ -extern volatile struct mapped_time_value *maptime; - -/* A port to the underlying node. */ -extern mach_port_t underlying_node; - -/* stat information for the underlying node. */ -extern struct stat underlying_node_stat; - -/* Send a debugging message, if unionfs is in debugging mode. */ -#define debug_msg(fmt, args...) \ - do \ - { \ - if (unionfs_flags & FLAG_UNIONFS_MODE_DEBUG) \ - debug_msg_send (fmt , ## args); \ - } \ - while (0) - -#endif diff --git a/unionfs/update.c b/unionfs/update.c deleted file mode 100644 index 8ec66883..00000000 --- a/unionfs/update.c +++ /dev/null @@ -1,97 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2005 Free Software Foundation, Inc. - Written by Gianluca Guida <glguida@gmail.com>. - - 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. */ - -/* Update thread: A clean way to solve locking issues of - root node update. */ - -#define _GNU_SOURCE - -#include <errno.h> -#include <string.h> -#include <cthreads.h> -#include <rwlock.h> - -#include "ncache.h" -#include "node.h" -#include "ulfs.h" - -/* Reader lock is used by threads that are going to - add/remove an ulfs; writer lock is hold by the - update thread. */ -static struct rwlock update_rwlock; -static struct condition update_wakeup; -static struct mutex update_lock; - -static void -_root_update_thread () -{ - error_t err; - - while (1) - { - if (hurd_condition_wait (&update_wakeup, &update_lock)) - mutex_unlock (&update_lock); - - rwlock_writer_lock (&update_rwlock); - - do - { - ulfs_check(); - err = node_init_root (netfs_root_node); - } - while (err == ENOENT); - - if (err) - { - fprintf (stderr, "update thread: got a %s\n", strerror (err)); - } - - ncache_reset (); - - rwlock_writer_unlock (&update_rwlock); - } -} - -void -root_update_schedule () -{ - condition_signal (&update_wakeup); -} - -void -root_update_disable () -{ - rwlock_reader_lock (&update_rwlock); -} - -void -root_update_enable () -{ - rwlock_reader_unlock (&update_rwlock); -} - -void -root_update_init() -{ - mutex_init (&update_lock); - rwlock_init (&update_rwlock); - condition_init (&update_wakeup); - - cthread_detach (cthread_fork ( (cthread_fn_t)_root_update_thread, 0)); -} diff --git a/unionfs/update.h b/unionfs/update.h deleted file mode 100644 index 6ebd6fc6..00000000 --- a/unionfs/update.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2005 Free Software Foundation, Inc. - Written by Gianluca Guida <glguida@gmail.com>. - - 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. */ - -#ifndef _UDPATE_H -#define _UPDATE_H - -void root_update_schedule (); -void root_update_disable (); -void root_update_enable (); -void root_update_init (); - -#endif /* UPDATE_H */ diff --git a/unionfs/version.h b/unionfs/version.h deleted file mode 100644 index 8969db31..00000000 --- a/unionfs/version.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Hurd version - Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. - Written by Thomas Bushnell, n/BSG. - - This file is part of the GNU Hurd. - - The GNU Hurd 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, or (at - your option) any later version. - - The GNU Hurd 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, USA. */ - -#ifndef HURD_VERSION -#define HURD_VERSION "0.3" -#endif - -/* The standard way to print versions for --version. */ -#define STANDARD_HURD_VERSION(s) \ - #s " (GNU Hurd) " HURD_VERSION -#define STANDARD_HURD_VERSION_EXTRA(s, extra) \ - #s " (GNU Hurd; " extra ") " HURD_VERSION |