hurdextras-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

unionfs AUTHORS BUGS CAVEAT COPYING ChangeLog M...


From: Thomas Schwinge
Subject: unionfs AUTHORS BUGS CAVEAT COPYING ChangeLog M...
Date: Sat, 08 Aug 2009 19:39:58 +0000

CVSROOT:        /cvsroot/hurdextras
Module name:    unionfs
Changes by:     Thomas Schwinge <tschwinge>     09/08/08 19:39:58

Removed files:
        .              : AUTHORS BUGS CAVEAT COPYING ChangeLog Makefile 
                         README TODO lib.c lib.h lnode.c lnode.h main.c 
                         ncache.c ncache.h netfs.c node.c node.h 
                         options.c options.h pattern.c pattern.h 
                         stow-mutations.h stow-priv.h stow.c stow.h 
                         ulfs.c ulfs.h unionfs.h update.c update.h 
                         version.h 

Log message:
        unionfs is now maintained in a Git repository: 
<http://git.savannah.gnu.org/cgit/hurd/unionfs.git/>

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/unionfs/AUTHORS?cvsroot=hurdextras&r1=1.2&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/BUGS?cvsroot=hurdextras&r1=1.2&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/CAVEAT?cvsroot=hurdextras&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/COPYING?cvsroot=hurdextras&r1=1.1.1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/ChangeLog?cvsroot=hurdextras&r1=1.20&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/Makefile?cvsroot=hurdextras&r1=1.4&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/README?cvsroot=hurdextras&r1=1.3&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/TODO?cvsroot=hurdextras&r1=1.1.1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/lib.c?cvsroot=hurdextras&r1=1.9&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/lib.h?cvsroot=hurdextras&r1=1.5&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/lnode.c?cvsroot=hurdextras&r1=1.1.1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/lnode.h?cvsroot=hurdextras&r1=1.1.1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/main.c?cvsroot=hurdextras&r1=1.3&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/ncache.c?cvsroot=hurdextras&r1=1.1.1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/ncache.h?cvsroot=hurdextras&r1=1.1.1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/netfs.c?cvsroot=hurdextras&r1=1.6&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/node.c?cvsroot=hurdextras&r1=1.10&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/node.h?cvsroot=hurdextras&r1=1.3&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/options.c?cvsroot=hurdextras&r1=1.7&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/options.h?cvsroot=hurdextras&r1=1.3&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/pattern.c?cvsroot=hurdextras&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/pattern.h?cvsroot=hurdextras&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/stow-mutations.h?cvsroot=hurdextras&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/stow-priv.h?cvsroot=hurdextras&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/stow.c?cvsroot=hurdextras&r1=1.5&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/stow.h?cvsroot=hurdextras&r1=1.2&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/ulfs.c?cvsroot=hurdextras&r1=1.5&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/ulfs.h?cvsroot=hurdextras&r1=1.4&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/unionfs.h?cvsroot=hurdextras&r1=1.1.1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/update.c?cvsroot=hurdextras&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/update.h?cvsroot=hurdextras&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/unionfs/version.h?cvsroot=hurdextras&r1=1.1.1.1&r2=0

Patches:
Index: AUTHORS
===================================================================
RCS file: AUTHORS
diff -N AUTHORS
--- AUTHORS     30 May 2005 12:53:20 -0000      1.2
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,2 +0,0 @@
-* Moritz Schulte <address@hidden>
-* Gianluca Guida <address@hidden>

Index: BUGS
===================================================================
RCS file: BUGS
diff -N BUGS
--- BUGS        8 Dec 2002 14:23:47 -0000       1.2
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -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

Index: CAVEAT
===================================================================
RCS file: CAVEAT
diff -N CAVEAT
--- CAVEAT      25 May 2005 01:56:32 -0000      1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -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.
-

Index: COPYING
===================================================================
RCS file: COPYING
diff -N COPYING
--- COPYING     7 Dec 2002 17:47:11 -0000       1.1.1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,2 +0,0 @@
-This program is licensed under the terms of the GNU General Public
-License.

Index: ChangeLog
===================================================================
RCS file: ChangeLog
diff -N ChangeLog
--- ChangeLog   21 Jun 2006 19:12:11 -0000      1.20
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,229 +0,0 @@
-2006-06-21  Alfred M. Szmidt  <address@hidden>
-
-       * lib.c (for_each_subdir): Revert previous change.  Reported by
-       Aanjhan Ranganathan <address@hidden>.
-
-2006-04-13  Ben Asselstine  <address@hidden>
-
-       * 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  <address@hidden>
-
-       * 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  <address@hidden>
-
-       * 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  <address@hidden>
-
-       * 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  <address@hidden>
-
-       * 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  <address@hidden>
-
-       * 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  <address@hidden>
-
-       * 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  <address@hidden>
-
-       * 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  <address@hidden>
-
-       * stow.c (stow_diradd): Handle --stow argument with missing / 
-       correctly.
-
-2005-01-31  Gianluca Guida  <address@hidden>
-
-       * 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  <address@hidden>
-
-       * Makefile: Rewrite.
-
-       * netfs.c (netfs_attempt_create_file): Unlock DIR.
-       (netfs_attempt_mkfile): Likewise.
-
-2002-12-09  Moritz Schulte  <address@hidden>
-
-       * 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  <address@hidden>
-
-       * 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.

Index: Makefile
===================================================================
RCS file: Makefile
diff -N Makefile
--- Makefile    29 May 2005 16:37:07 -0000      1.4
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,81 +0,0 @@
-# Hurd unionfs
-# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
-# Written by Jeroen Dekkers <address@hidden>.
-# 
-# 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

Index: README
===================================================================
RCS file: README
diff -N README
--- README      30 May 2005 12:53:20 -0000      1.3
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,92 +0,0 @@
-This is the unionfs translator for the GNU Hurd.
-
-The unionfs translator was originally written by Moritz Schulte 
-<address@hidden> and currently mantained by Gianluca Guida 
-<address@hidden>.
-
-
-
-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 <address@hidden>.

Index: TODO
===================================================================
RCS file: TODO
diff -N TODO
--- TODO        7 Dec 2002 17:47:11 -0000       1.1.1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -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

Index: lib.c
===================================================================
RCS file: lib.c
diff -N lib.c
--- lib.c       21 Jun 2006 19:12:11 -0000      1.9
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,280 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
-   Written by Moritz Schulte <address@hidden>.
-
-   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;
-}

Index: lib.h
===================================================================
RCS file: lib.h
diff -N lib.h
--- lib.h       29 May 2005 16:37:07 -0000      1.5
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,82 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
-   Written by Moritz Schulte <address@hidden>.
-
-   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

Index: lnode.c
===================================================================
RCS file: lnode.c
diff -N lnode.c
--- lnode.c     7 Dec 2002 17:47:11 -0000       1.1.1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,184 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2001, 2002 Free Software Foundation, Inc.
-   Written by Moritz Schulte <address@hidden>.
-
-   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;
-}

Index: lnode.h
===================================================================
RCS file: lnode.h
diff -N lnode.h
--- lnode.h     7 Dec 2002 17:47:11 -0000       1.1.1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,77 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2001, 2002 Free Software Foundation, Inc.
-   Written by Moritz Schulte <address@hidden>.
-
-   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

Index: main.c
===================================================================
RCS file: main.c
diff -N main.c
--- main.c      13 Jun 2005 00:22:11 -0000      1.3
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,134 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
-   Written by Moritz Schulte <address@hidden>.
-
-   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 ();
-}

Index: ncache.c
===================================================================
RCS file: ncache.c
diff -N ncache.c
--- ncache.c    7 Dec 2002 17:47:11 -0000       1.1.1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,151 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2001, 2002 Free Software Foundation, Inc.
-   Written by Moritz Schulte <address@hidden>.
-
-   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);
-}

Index: ncache.h
===================================================================
RCS file: ncache.h
diff -N ncache.h
--- ncache.h    7 Dec 2002 17:47:11 -0000       1.1.1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,59 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2001, 2002 Free Software Foundation, Inc.
-   Written by Moritz Schulte <address@hidden>.
-
-   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

Index: netfs.c
===================================================================
RCS file: netfs.c
diff -N netfs.c
--- netfs.c     30 Jun 2005 18:49:55 -0000      1.6
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,1170 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
-   Written by Moritz Schulte <address@hidden>.
-
-   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;
-}

Index: node.c
===================================================================
RCS file: node.c
diff -N node.c
--- node.c      31 May 2005 02:58:48 -0000      1.10
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,555 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
-   Written by Moritz Schulte <address@hidden>.
-
-   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;
-}

Index: node.h
===================================================================
RCS file: node.h
diff -N node.h
--- node.h      25 May 2005 01:59:48 -0000      1.3
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,135 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2001, 2002 Free Software Foundation, Inc.
-   Written by Moritz Schulte <address@hidden>.
-
-   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

Index: options.c
===================================================================
RCS file: options.c
diff -N options.c
--- options.c   13 Apr 2006 11:06:02 -0000      1.7
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,225 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
-   Written by Moritz Schulte <address@hidden>.
-
-   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 <address@hidden>";
-
-#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 };

Index: options.h
===================================================================
RCS file: options.h
diff -N options.h
--- options.h   30 Jun 2005 18:49:55 -0000      1.3
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,53 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2001, 2002 Free Software Foundation, Inc.
-   Written by Moritz Schulte <address@hidden>.
-
-   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

Index: pattern.c
===================================================================
RCS file: pattern.c
diff -N pattern.c
--- pattern.c   31 Jan 2005 12:30:05 -0000      1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,131 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
-   Written by Gianluca Guida <address@hidden>.
-
-   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;
-}

Index: pattern.h
===================================================================
RCS file: pattern.h
diff -N pattern.h
--- pattern.h   31 Jan 2005 12:30:05 -0000      1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,53 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
-   Written by Gianluca Guida <address@hidden>.
-
-   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 */

Index: stow-mutations.h
===================================================================
RCS file: stow-mutations.h
diff -N stow-mutations.h
--- stow-mutations.h    29 May 2005 16:37:07 -0000      1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,27 +0,0 @@
-/* stow-mutations.h - MIG mutations unionfs.
-   Copyright (C) 2005 Free Software Foundation, Inc.
-   Written by Gianluca Guida <address@hidden>.
-
-   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";
-

Index: stow-priv.h
===================================================================
RCS file: stow-priv.h
diff -N stow-priv.h
--- stow-priv.h 29 May 2005 16:37:07 -0000      1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,45 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2005 Free Software Foundation, Inc.
-   Written by Gianluca Guida <address@hidden>.
-
-   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 */

Index: stow.c
===================================================================
RCS file: stow.c
diff -N stow.c
--- stow.c      30 Jun 2005 18:49:55 -0000      1.5
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,328 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2005 Free Software Foundation, Inc.
-   Written by Gianluca Guida <address@hidden>.
-
-   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;
-}

Index: stow.h
===================================================================
RCS file: stow.h
diff -N stow.h
--- stow.h      29 May 2005 16:37:07 -0000      1.2
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,30 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2005 Free Software Foundation, Inc.
-   Written by Gianluca Guida <address@hidden>.
-
-   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  */

Index: ulfs.c
===================================================================
RCS file: ulfs.c
diff -N ulfs.c
--- ulfs.c      13 Apr 2006 11:06:02 -0000      1.5
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,321 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
-   Written by Moritz Schulte <address@hidden>.
-
-   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;
-}

Index: ulfs.h
===================================================================
RCS file: ulfs.h
diff -N ulfs.h
--- ulfs.h      13 Apr 2006 11:06:02 -0000      1.4
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,75 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
-   Written by Moritz Schulte <address@hidden>.
-
-   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

Index: unionfs.h
===================================================================
RCS file: unionfs.h
diff -N unionfs.h
--- unionfs.h   7 Dec 2002 17:47:13 -0000       1.1.1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,90 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2001, 2002 Free Software Foundation, Inc.
-   Written by Moritz Schulte <address@hidden>.
-
-   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

Index: update.c
===================================================================
RCS file: update.c
diff -N update.c
--- update.c    29 May 2005 16:37:07 -0000      1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,97 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2005 Free Software Foundation, Inc.
-   Written by Gianluca Guida <address@hidden>.
-
-   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));
-}

Index: update.h
===================================================================
RCS file: update.h
diff -N update.h
--- update.h    29 May 2005 16:37:07 -0000      1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,28 +0,0 @@
-/* Hurd unionfs
-   Copyright (C) 2005 Free Software Foundation, Inc.
-   Written by Gianluca Guida <address@hidden>.
-
-   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 */

Index: version.h
===================================================================
RCS file: version.h
diff -N version.h
--- version.h   7 Dec 2002 17:47:13 -0000       1.1.1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]