summaryrefslogtreecommitdiff
path: root/libdiskfs
diff options
context:
space:
mode:
Diffstat (limited to 'libdiskfs')
-rw-r--r--libdiskfs/ChangeLog3648
-rw-r--r--libdiskfs/Makefile71
-rw-r--r--libdiskfs/boot-start.c662
-rw-r--r--libdiskfs/conch-fetch.c72
-rw-r--r--libdiskfs/conch-set.c49
-rw-r--r--libdiskfs/console.c72
-rw-r--r--libdiskfs/dead-name.c45
-rw-r--r--libdiskfs/demuxer.c42
-rw-r--r--libdiskfs/dir-chg.c75
-rw-r--r--libdiskfs/dir-clear.c70
-rw-r--r--libdiskfs/dir-init.c68
-rw-r--r--libdiskfs/dir-link.c133
-rw-r--r--libdiskfs/dir-lookup.c465
-rw-r--r--libdiskfs/dir-mkdir.c70
-rw-r--r--libdiskfs/dir-mkfile.c85
-rw-r--r--libdiskfs/dir-readdir.c61
-rw-r--r--libdiskfs/dir-rename.c229
-rw-r--r--libdiskfs/dir-renamed.c229
-rw-r--r--libdiskfs/dir-rmdir.c94
-rw-r--r--libdiskfs/dir-unlink.c98
-rw-r--r--libdiskfs/direnter.c48
-rw-r--r--libdiskfs/dirremove.c45
-rw-r--r--libdiskfs/dirrewrite.c50
-rw-r--r--libdiskfs/disk-pager.c119
-rw-r--r--libdiskfs/diskfs-pager.h70
-rw-r--r--libdiskfs/diskfs.h937
-rw-r--r--libdiskfs/extra-version.c24
-rw-r--r--libdiskfs/fhandle.h36
-rw-r--r--libdiskfs/file-access.c44
-rw-r--r--libdiskfs/file-chauthor.c42
-rw-r--r--libdiskfs/file-chflags.c40
-rw-r--r--libdiskfs/file-chg.c69
-rw-r--r--libdiskfs/file-chmod.c55
-rw-r--r--libdiskfs/file-chown.c64
-rw-r--r--libdiskfs/file-exec.c192
-rw-r--r--libdiskfs/file-get-fs-opts.c54
-rw-r--r--libdiskfs/file-get-trans.c138
-rw-r--r--libdiskfs/file-get-transcntl.c48
-rw-r--r--libdiskfs/file-getcontrol.c51
-rw-r--r--libdiskfs/file-getfh.c60
-rw-r--r--libdiskfs/file-getlinknode.c39
-rw-r--r--libdiskfs/file-inv-trans.c160
-rw-r--r--libdiskfs/file-lock-stat.c38
-rw-r--r--libdiskfs/file-lock.c38
-rw-r--r--libdiskfs/file-reparent.c65
-rw-r--r--libdiskfs/file-set-size.c55
-rw-r--r--libdiskfs/file-set-trans.c209
-rw-r--r--libdiskfs/file-statfs.c44
-rw-r--r--libdiskfs/file-sync.c42
-rw-r--r--libdiskfs/file-syncfs.c61
-rw-r--r--libdiskfs/file-utimes.c55
-rw-r--r--libdiskfs/fsmutations.h29
-rw-r--r--libdiskfs/fsys-forward.c37
-rw-r--r--libdiskfs/fsys-getfile.c104
-rw-r--r--libdiskfs/fsys-getroot.c203
-rw-r--r--libdiskfs/fsys-goaway.c54
-rw-r--r--libdiskfs/fsys-options.c116
-rw-r--r--libdiskfs/fsys-startup.c37
-rw-r--r--libdiskfs/fsys-syncfs.c75
-rw-r--r--libdiskfs/ifsock.c135
-rw-r--r--libdiskfs/init-first.c52
-rw-r--r--libdiskfs/init-init.c105
-rw-r--r--libdiskfs/init-main.c78
-rw-r--r--libdiskfs/init-startup.c205
-rw-r--r--libdiskfs/interrupt.c39
-rw-r--r--libdiskfs/io-async-icky.c33
-rw-r--r--libdiskfs/io-async.c31
-rw-r--r--libdiskfs/io-duplicate.c46
-rw-r--r--libdiskfs/io-get-conch.c44
-rw-r--r--libdiskfs/io-identity.c67
-rw-r--r--libdiskfs/io-interrupt.c29
-rw-r--r--libdiskfs/io-map-cntl.c53
-rw-r--r--libdiskfs/io-map.c73
-rw-r--r--libdiskfs/io-modes-get.c34
-rw-r--r--libdiskfs/io-modes-off.c35
-rw-r--r--libdiskfs/io-modes-on.c35
-rw-r--r--libdiskfs/io-modes-set.c36
-rw-r--r--libdiskfs/io-owner-get.c36
-rw-r--r--libdiskfs/io-owner-mod.c36
-rw-r--r--libdiskfs/io-pathconf.c79
-rw-r--r--libdiskfs/io-prenotify.c72
-rw-r--r--libdiskfs/io-read.c109
-rw-r--r--libdiskfs/io-readable.c46
-rw-r--r--libdiskfs/io-reauthenticate.c61
-rw-r--r--libdiskfs/io-rel-conch.c44
-rw-r--r--libdiskfs/io-restrict-auth.c82
-rw-r--r--libdiskfs/io-revoke.c59
-rw-r--r--libdiskfs/io-seek.c57
-rw-r--r--libdiskfs/io-select.c32
-rw-r--r--libdiskfs/io-sigio.c36
-rw-r--r--libdiskfs/io-stat.c51
-rw-r--r--libdiskfs/io-stubs.c63
-rw-r--r--libdiskfs/io-version.c42
-rw-r--r--libdiskfs/io-write.c94
-rw-r--r--libdiskfs/lithp.h31
-rw-r--r--libdiskfs/lookup.c234
-rw-r--r--libdiskfs/name-cache.c265
-rw-r--r--libdiskfs/node-create.c119
-rw-r--r--libdiskfs/node-drop.c100
-rw-r--r--libdiskfs/node-make.c50
-rw-r--r--libdiskfs/node-nput.c75
-rw-r--r--libdiskfs/node-nputl.c38
-rw-r--r--libdiskfs/node-nref.c40
-rw-r--r--libdiskfs/node-nrefl.c30
-rw-r--r--libdiskfs/node-nrele.c65
-rw-r--r--libdiskfs/node-nrelel.c39
-rw-r--r--libdiskfs/node-rdwr.c77
-rw-r--r--libdiskfs/node-times.c71
-rw-r--r--libdiskfs/node-update.c32
-rw-r--r--libdiskfs/notify-nosenders.c39
-rw-r--r--libdiskfs/notify-stubs.c71
-rw-r--r--libdiskfs/opts-append-std.c61
-rw-r--r--libdiskfs/opts-common.c51
-rw-r--r--libdiskfs/opts-get.c29
-rw-r--r--libdiskfs/opts-runtime-parse.c30
-rw-r--r--libdiskfs/opts-runtime.c23
-rw-r--r--libdiskfs/opts-set.c34
-rw-r--r--libdiskfs/opts-std-runtime.c156
-rw-r--r--libdiskfs/opts-std-startup.c162
-rw-r--r--libdiskfs/opts-version.c47
-rw-r--r--libdiskfs/ourfs_notify.defs5
-rw-r--r--libdiskfs/peropen-make.c60
-rw-r--r--libdiskfs/peropen-rele.c49
-rw-r--r--libdiskfs/ports-clean.c29
-rw-r--r--libdiskfs/ports-consts.c20
-rw-r--r--libdiskfs/ports-idle.c36
-rw-r--r--libdiskfs/ports-noports.c27
-rw-r--r--libdiskfs/ports-soft.c25
-rw-r--r--libdiskfs/priv.h143
-rw-r--r--libdiskfs/protid-make.c72
-rw-r--r--libdiskfs/protid-rele.c37
-rw-r--r--libdiskfs/rdwr-internal.c74
-rw-r--r--libdiskfs/readonly.c111
-rw-r--r--libdiskfs/remount.c47
-rw-r--r--libdiskfs/shutdown.c104
-rw-r--r--libdiskfs/sync-default.c21
-rw-r--r--libdiskfs/sync-interval.c131
-rw-r--r--libdiskfs/trans-callback.c80
-rw-r--r--libdiskfs/validate-author.c27
-rw-r--r--libdiskfs/validate-flags.c27
-rw-r--r--libdiskfs/validate-group.c27
-rw-r--r--libdiskfs/validate-mode.c27
-rw-r--r--libdiskfs/validate-owner.c27
-rw-r--r--libdiskfs/validate-rdev.c27
144 files changed, 15316 insertions, 0 deletions
diff --git a/libdiskfs/ChangeLog b/libdiskfs/ChangeLog
new file mode 100644
index 00000000..3a561231
--- /dev/null
+++ b/libdiskfs/ChangeLog
@@ -0,0 +1,3648 @@
+2000-01-25 Roland McGrath <roland@baalperazim.frob.com>
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Follow symlink despite flags if
+ MUSTBEDIR is set (i.e. there was a trailing slash).
+
+2000-01-24 Roland McGrath <roland@baalperazim.frob.com>
+
+ * rdwr-internal.c (_diskfs_rdwr_internal): Short-circuit return for
+ zero-length transfer to avoid side effects, as POSIX requires.
+
+1999-12-13 Roland McGrath <roland@baalperazim.frob.com>
+
+ Rewrite of a fix provided by Bill White <bill.white@griggsinst.com>:
+ * fhandle.h (union diskfs_fhandle): Replaces struct diskfs_fhandle.
+ Use a union element of char[28] to ensure size requirement.
+ * fsys-getfile.c (diskfs_S_fsys_getfile): Update uses for new type.
+ * file-getfh.c (diskfs_S_file_getfh): Likewise.
+
+1999-12-02 Mark Kettenis <kettenis@gnu.org>
+
+ * io-read.c (diskfs_S_io_read): Add braces to silence gcc
+ warning.
+
+1999-11-09 Roland McGrath <roland@baalperazim.frob.com>
+
+ * priv.h (_diskfs_chroot_directory): Remove const from type.
+ * init-startup.c (_diskfs_chroot_directory): Likewise.
+
+1999-11-08 Roland McGrath <roland@baalperazim.frob.com>
+
+ * disk-pager.c (fault_handler): Put more detail in assert failures.
+
+1999-10-28 Roland McGrath <roland@baalperazim.frob.com>
+
+ * node-nput.c (diskfs_nput): Call diskfs_set_node_times before
+ diskfs_lost_hardrefs. This should address the late mtime update
+ bug reported and investigated by Mark Kettenis.
+
+1999-10-23 Roland McGrath <roland@baalperazim.frob.com>
+
+ * sync-interval.c (periodic_sync): With diskfs_fsys_lock reader lock
+ held, check _diskfs_diskdirty and don't sync if not dirty.
+
+1999-10-14 Roland McGrath <roland@baalperazim.frob.com>
+
+ * opts-std-startup.c (TOGGLE): Fix `off' case.
+ Reported by Kalle Olavi Niemitalo <tosi@ees2.oulu.fi>.
+
+1999-10-13 Roland McGrath <roland@baalperazim.frob.com>
+
+ * io-pathconf.c (diskfs_S_io_pathconf): Cap diskfs_name_max to size
+ representable in struct dirent.d_namlen.
+ (diskfs_S_io_pathconf): Always return 1 for _PC_NO_TRUNC, since we
+ always constrain diskfs_name_max.
+
+ * lookup.c (diskfs_lookup): Enforce diskfs_name_max limit for CREATE
+ and RENAME, returning ENAMETOOLONG for violations.
+ * io-pathconf.c (diskfs_S_io_pathconf): _PC_NO_TRUNC controlled by
+ diskfs_name_max setting.
+
+ * diskfs.h (diskfs_name_max): Declare new variable.
+ * io-pathconf.c (diskfs_S_io_pathconf): Use it for _PC_NAME_MAX,
+ capping it to 1024.
+
+1999-10-12 Roland McGrath <roland@baalperazim.frob.com>
+
+ * opts-std-runtime.c (parse_opt: ARGP_KEY_INIT): Initialize H->noatime.
+
+1999-10-11 Roland McGrath <roland@baalperazim.frob.com>
+
+ * dir-readdir.c (diskfs_S_dir_readdir): Take new DATA_DEALLOC param.
+
+1999-10-07 Roland McGrath <roland@baalperazim.frob.com>
+
+ * lookup.c (diskfs_lookup): Rewrite code from last change, which had
+ typos (and then I just decided to change the details of the string
+ diddling).
+
+1999-10-06 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * lookup.c (diskfs_lookup): NAME is no longer const. Update
+ documentation. Strip leading and trailing slashes from NAME before
+ using it.
+ * diskfs.h (diskfs_lookup): NAME is no longer const.
+ Update documentation.
+
+1999-10-05 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * priv.h (CHANGE_NODE_FIELD): Use diskfs_check_readonly instead of
+ directly reading diskfs_readonly.
+
+1999-09-20 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * node-times.c (diskfs_set_node_times): Don't implement
+ _diskfs_noatime here.
+ * conch-fetch.c (iohelp_fetch_shared_data): Don't update
+ dn_set_atime on affected node if _diskfs_noatime.
+ * rdwr-internal.c (_diskfs_rdwr_internal): Likewise.
+
+1999-09-19 Roland McGrath <roland@baalperazim.frob.com>
+
+ * node-times.c (diskfs_set_node_times): If _diskfs_noatime is set and
+ neither NP->dn_set_mtime nor NP->dn_set_ctime is set, clear
+ NP->dn_set_atime. Short-circuit return if none of dn_set_?time set.
+ * opts-common.c (diskfs_common_options): Include "priv.h".
+ Add aliases --ro/--rw for -r/-w. Add alias --nosuid for --no-suid,
+ --noexec for --no-exec. Move --suid-ok, --exec-ok here from ...
+ * opts-std-runtime.c (std_runtime_options): ... here.
+ (struct parse_hook): New member `noatime'.
+ (set_opts): Use H->noatime to set _diskfs_noatime.
+ (parse_opt): Grok -A and OPT_ATIME to set/clear H->noatime.
+ (OPT_ATIME): New macro.
+ (OPT_SUID_OK, OPT_EXEC_OK): Moved to ...
+ * priv.h: ... here.
+ (diskfs_common_options): Add const to decl.
+ * opts-std-startup.c (parse_startup_opt): Grok OPT_SUID_OK,
+ OPT_EXEC_OK, -A, and OPT_ATIME.
+ * init-init.c (_diskfs_noatime): New variable.
+ (_diskfs_nosuid, _diskfs_noexec): Use uninitialized defns.
+ * opts-append-std.c (diskfs_append_std_options): Add --no-atime if
+ _diskfs_noatime is set.
+
+1999-09-13 Roland McGrath <roland@baalperazim.frob.com>
+
+ * Makefile, rdwr-internal.c, io-map.c, io-map-segment.c, diskfs.h:
+ Reverted changes related to io_map_segment.
+
+1999-09-09 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * io-pathconf.c: Include <unistd.h>.
+ (diskfs_S_io_pathconf): Provide real definition.
+
+1999-09-07 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * io-map-segment.c: New file. Guts from io-map.c.
+ * io-map.c (diskfs_S_io_map): Just call diskfs_S_io_map_segment.
+ * diskfs.h (diskfs_get_filemap): New parameter `index'.
+ * rdwr-internal.c (_diskfs_rdwr_internal): Pass additional
+ parameter to diskfs_get_filemap.
+ * Makefile (IOSRCS): Add io-map-segment.c.
+
+1999-07-24 Roland McGrath <roland@baalperazim.frob.com>
+
+ * dir-rmdir.c (diskfs_S_dir_rmdir): Fix bugs in last change.
+ Replace label `out' with local inline function `done'.
+ Don't try diskfs_nput (NP) when NP is null.
+
+1999-07-17 Roland McGrath <roland@baalperazim.frob.com>
+
+ * dir-link.c (diskfs_S_dir_link): Fix error checks on ports.
+ If DIRCRED (receiver port) is bad, return EOPNOTSUPP.
+ If FILECRED (argument port) is bad, return EXDEV (after EROFS check).
+
+1999-07-11 Roland McGrath <roland@baalperazim.frob.com>
+
+ * boot-start.c (diskfs_S_exec_startup_get_info): Typo in last change.
+
+1999-07-10 Roland McGrath <roland@baalperazim.frob.com>
+
+ * priv.h: Add #include <sys/mman.h> for munmap decl.
+
+1999-07-09 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * boot-start.c (diskfs_S_exec_startup_get_info): Use mmap instead
+ of vm_allocate.
+ (diskfs_S_fsys_init): Likewise.
+ * file-get-trans.c (diskfs_S_file_get_translator): Likewise.
+ * file-getfh.c (diskfs_S_file_getfh): Likewise.
+ * io-read.c (diskfs_S_io_read): Likewise.
+
+Mon Jul 5 20:03:18 1999 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * node-nputl.c (diskfs_nput_light): Fix typo in function
+ declaration. Reported by Yamashita TAKAO
+ (jargon@lares.dti.ne.jp).
+
+1999-07-03 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * file-get-trans.c (diskfs_S_file_get_translator): Use munmap
+ instead of vm_deallocate.
+ * io-read.c (diskfs_S_io_read): Likewise.
+ * protid-rele.c (diskfs_protid_rele): Likewise.
+
+1999-07-01 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * node-nref.c: New file; guts from diskfs.h.
+ * node-nput.c: Likewise.
+ * node-nrele.c: Likewise.
+ * node-nrefl.c: Likewise.
+ * node-nputl.c: Likewise.
+ * node-nrelel.c: LIkewise.
+ * diskfs.h (diskfs_nref, diskfs_nput, diskfs_nrele,
+ diskfs_nref_light, diskfs_nput_light, diskfs_nrele_light): Replace
+ inline definitions with ordinary declarations.
+ (DISKFS_EI): Removed macro.
+ * diskfs.c: Deleted file.
+ * Makefile (OTHERSRCS): Added node-nref.c, node-nput.c
+ node-nrele.c, node-nrefl.c, node-nputl.c, node-nrelel.c. Removed
+ diskfs.c.
+
+1999-06-29 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * dev-globals.c, dev-io.c, dev-open.c: Files removed.
+
+ * lookup.c (diskfs_lookup): If we get an error from
+ fshelp_checkdirmod, clear *NP as well as returning the error.
+ Use diskfs_nrele instead of diskfs_nput in case *NP and DP are
+ the same.
+
+1999-06-28 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * dir-rmdir.c (diskfs_S_dir_rmdir): Reorganized to make clearer;
+ several little buglets fixed too.
+
+1999-06-27 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * sync-default.c (diskfs_default_sync_interval): Reduce to five
+ seconds. Hardware is much different than when Unix originally
+ picked thirty, plus we manage VM differently than the Unix buffer
+ cache did, and tend to delay many more writes than Unix did.
+
+1999-06-13 Roland McGrath <roland@baalperazim.frob.com>
+
+ * file-get-trans.c (diskfs_S_file_get_translator): Fix type cast in
+ last change.
+
+ * file-get-trans.c (diskfs_S_file_get_translator): If we return an
+ error, vm_deallocate any vm_allocated memory.
+ From Mark Kettenis <kettenis@gnu.org>.
+
+1999-06-02 Roland McGrath <roland@baalperazim.frob.com>
+
+ * boot-start.c (diskfs_start_bootstrap): Pass environment collected
+ from `environ' on to init. The kernel can send more parameters
+ through this way without us knowing about them specifically.
+
+1999-05-19 Roland McGrath <roland@baalperazim.frob.com>
+
+ * console.c (diskfs_console_stdio): If there is an fd 2 that appears
+ to work, just leave it as is and dup2 it to fd 1 as well.
+
+1999-05-16 Roland McGrath <roland@baalperazim.frob.com>
+
+ * file-chown.c (diskfs_S_file_chown): Fix last change: not just
+ permission check, actually don't make the change if value is -1.
+
+1999-05-13 Roland McGrath <roland@baalperazim.frob.com>
+
+ * file-chown.c (diskfs_S_file_chown): Either arg being -1 means don't
+ change that id.
+
+Tue Apr 6 10:05:49 1999 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * dir-renamed.c (diskfs_rename_dir): Stage 1, if TNP == FNP, we
+ have to unlock TNP with diskfs_nput and not just diskfs_nrele it.
+
+Tue Mar 16 17:20:06 1999 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * lookup.c (diskfs_lookup): Reformat for prettiness.
+
+1999-02-28 Roland McGrath <roland@baalperazim.frob.com>
+
+ * io-revoke.c (diskfs_S_io_revoke): Use ports_class_iterate.
+ * readonly.c (diskfs_set_readonly): Likewise.
+
+Mon Feb 22 04:28:56 1999 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * io-revoke.c (diskfs_S_io_revoke): Protect the actual revocation
+ by blocking all other rpcs.
+
+Sat Feb 20 20:46:21 1999 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * io-revoke.c (diskfs_S_io_revoke): Release NP->lock before
+ beginning iteration.
+
+1999-02-16 Roland McGrath <roland@baalperazim.frob.com>
+
+ * io-revoke.c (diskfs_S_io_revoke): Fix typo in 1999-02-16 change.
+
+ * init-startup.c (diskfs_startup_diskfs): Fix typo 1999-02-12 change.
+
+Tue Feb 16 05:31:23 1999 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * io-revoke.c: New file.
+ * Makefile (IOSRCS): Add io-revoke.c.
+
+Sat Feb 13 04:29:29 1999 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * peropen-make.c (diskfs_make_peropen): If there is no existing
+ context, then set the shadow_root iff we are a chrooted virtual
+ root filesystem.
+
+1999-02-12 Gordon Matzigkeit <gord@trick.fig.org>
+
+ * init-startup.c (diskfs_startup_diskfs): Release the virtual
+ root's lock as soon as we've checked that it's a valid directory.
+ Ignore leading slashes in _diskfs_chroot_directory.
+
+Sun Jan 31 18:24:33 1999 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * file-utimes.c (diskfs_S_file_utimes): Implement new semantics
+ for setting to exactly present time.
+
+1999-01-27 Roland McGrath <roland@baalperazim.frob.com>
+
+ * Makefile (OTHERSRCS): Add init-main.c.
+
+1999-01-22 Roland McGrath <roland@baalperazim.frob.com>
+
+ * init-main.c: New file, defining new function diskfs_init_main.
+ * diskfs.h: Declare diskfs_init_main.
+
+ * file-set-trans.c: Remove makedev, major, minor macro definitions.
+ * dir-lookup.c: Likewise.
+
+1999-01-01 Roland McGrath <roland@baalperazim.frob.com>
+
+ * sync-interval.c (diskfs_set_sync_interval): Use ENOMEM, not EIEIO.
+
+1998-12-27 Roland McGrath <roland@baalperazim.frob.com>
+
+ Use a struct hurd_port for the cached exec server port,
+ so it is properly reference-counted and locked.
+ * boot-start.c (diskfs_exec): Variable removed.
+ (diskfs_start_bootstrap): Make it a local here.
+ Install that port in _diskfs_exec_portcell.
+ (diskfs_S_fsys_init): Use _diskfs_exec_portcell instead
+ of diskfs_exec.
+ * init-init.c (_diskfs_exec_portcell): New variable.
+ (diskfs_init_diskfs): Initialize it.
+ * priv.h: Declare it.
+ * diskfs.h (diskfs_exec, diskfs_exec_ctl): Remove decls.
+ * file-exec.c (diskfs_S_file_exec): Use _diskfs_exec_portcell instead
+ of diskfs_exec.
+
+ * init-completed.c: File removed (obsolete since 1996).
+
+ * boot-start.c (diskfs_start_bootstrap): Twiddle boot-time messages.
+
+1998-12-27 Roland McGrath <roland@baalperazim.frob.com>
+
+ * boot-start.c (_diskfs_boot_privports): Renamed from diskfs_*.
+
+ * priv.h: Declare it.
+ * console.c (diskfs_console_stdio): Change caller.
+
+ * file-statfs.c (diskfs_S_file_statfs): Remove __ from struct members.
+
+1998-12-21 Mark Kettenis <kettenis@phys.uva.nl>
+
+ * file-statfs.c (diskfs_S_file_statfs): Initialize mount options
+ in statbuf.
+
+1998-12-27 Roland McGrath <roland@baalperazim.frob.com>
+
+ * opts-std-startup.c (startup_options): Move -C above "Boot options:",
+ give it a docstring. Docstrings for --bootflags, --boot-command.
+ (_diskfs_boot_command): New variable.
+ (startup_options, parse_startup_opt): New option --boot-command,
+ consumes remaining args to set _diskfs_boot_command.
+ * priv.h: Declare _diskfs_boot_command.
+ * boot-start.c (diskfs_start_bootstrap): If diskfs_exec_server_task is
+ null, assume we are running as the boot command and have a root with
+ /servers/exec.
+ If _diskfs_boot_command is set, start that command in place of init.
+ If can't lookup initname, print error msg and loop to prompt.
+ Put a newline before "Init name" prompt.
+ After starting exec server, try to set active trans on /servers/exec.
+ (diskfs_boot_getpriv): New function: if _hurd_host_priv
+ is null, use fsys_getpriv on our bootstrap port.
+ (parent_task): New static variable, set there with fsys_getpriv call.
+ (diskfs_S_fsys_init): If diskfs_exec_server_task is null, don't do
+ anything with it; instead register parent_task as our child
+ and send an fsys_init to our parent on our bootstrap port.
+ * console.c (diskfs_console_stdio): Call diskfs_boot_privports before
+ get_privileged_ports if diskfs_boot_flags is set.
+
+1998-12-21 Roland McGrath <roland@baalperazim.frob.com>
+
+ * file-exec.c (diskfs_S_file_exec): If exec server port is stale, try
+ once to look up a new one.
+
+1998-12-06 Roland McGrath <roland@baalperazim.frob.com>
+
+ * boot-parse.c: File removed (it has been obsolete since 1995).
+
+1998-11-29 Roland McGrath <roland@baalperazim.frob.com>
+
+ * trans-callback.c (_diskfs_translator_callback1_fn): Use size_t*
+ instead of int* for ARGZ_LEN arg.
+
+1998-11-25 Mark Kettenis <kettenis@phys.uva.nl>
+
+ * boot-start.c (diskfs_S_fsys_init): Call _hurd_proc_init with new
+ args set to zero.
+
+Wed Aug 12 23:35:59 1998 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * file-chflags.c (diskfs_S_file_chflags): Only set
+ NP->dn_set_ctime if we actually set the flags.
+
+1998-10-26 Gordon Matzigkeit <gord@trick.fig.org>
+
+ * init-startup.c (diskfs_startup_diskfs): Use diskfs_nput to free
+ the old diskfs_root_node when switching to a virtual root.
+
+1998-10-20 Roland McGrath <roland@baalperazim.frob.com>
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Add braces to silence gcc
+ warning.
+ * io-identity.c (diskfs_S_io_identity): Likewise.
+ * opts-append-std.c (diskfs_append_std_options): Likewise.
+ * opts-std-runtime.c (set_opts): Likewise.
+
+1998-09-04 Roland McGrath <roland@baalperazim.frob.com>
+
+ * diskfs.h (diskfs_lookup_hard, diskfs_lookup,
+ diskfs_set_translator, diskfs_create_symlink_hook,
+ diskfs_notice_dirchange, diskfs_direnter, diskfs_direnter_hard,
+ diskfs_dirrewrite, diskfs_dirremove,
+ diskfs_create_node, diskfs_enter_lookup_cache,
+ diskfs_check_lookup_cache, dir_rename_dir, diskfs_set_options):
+ Add `const' qualifier to `char *' parameters where appropriate.
+ * opts-set.c (diskfs_set_options): Fix defn with `const'.
+ * node-create.c (diskfs_create_node): Likewise.
+ * name-cache.c (diskfs_enter_lookup_cache): Likewise.
+ (diskfs_check_lookup_cache): Likewise.
+ * dirremove.c (diskfs_dirremove): Likewise.
+ * dirrewrite.c (diskfs_dirrewrite): Likewise.
+ * lookup.c (diskfs_lookup): Likewise.
+ * direnter.c (diskfs_direnter): Likewise.
+ * dir-renamed.c (diskfs_rename_dir): Likewise.
+ * dir-chg.c (diskfs_notice_dirchange): Likewise.
+
+1998-04-04 Roland McGrath <roland@baalperazim.frob.com>
+
+ Add support for a "virtual root directory" specified at startup.
+ * priv.h (_diskfs_chroot_directory): Declare new variable.
+ * opts-std-startup.c (startup_options, parse_startup_opt): New
+ string-valued option -C/--directory/--virtual-root/--chroot sets
+ _diskfs_chroot_directory.
+ * init-startup.c (_diskfs_chroot_directory): New variable.
+ (diskfs_startup_diskfs): If that's set, look up the name and
+ warp us to that as a virtual root directory.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Initialize new peropen's
+ shadow_root_parent to null, and shadow_root to either null or,
+ if _diskfs_chroot_directory is set, to diskfs_root_node.
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Treat a shadow_root with null
+ shadow_root_parent as a "virtual root".
+
+1998-08-20 Roland McGrath <roland@baalperazim.frob.com>
+
+ * fsys-options.c (diskfs_S_fsys_get_options):
+ fshelp_return_malloced_buffer renamed to iohelp_*.
+ * file-get-fs-opts.c (diskfs_S_file_get_fs_options): Likewise.
+
+Tue Aug 11 16:17:49 1998 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * file-chflags.c (diskfs_S_file_chflags): Set NP->dn_set_ctime.
+
+ * file-utimes.c (diskfs_S_file_utimes): Add file notifications.
+
+Sun Aug 9 21:09:24 1998 Jose M. Moya <josem@gnu.org>
+
+ * diskfs.h (struct node): Add filemod_reqs member.
+ (struct modreq): Rename struct dirmod to reqmod as it is used for
+ directory and file notifications.
+ (diskfs_notice_filechange): Add prototype.
+ * dir-chg.c (diskfs_S_dir_notice_changes): Check
+ nowait_dir_changed return value for errors.
+ (diskfs_notice_dirchange): Remove requests when the notification
+ fails.
+ * file-chg.c (diskfs_S_file_notice_changes): Implement.
+ (diskfs_notice_filechange): New function.
+ * node-make.c (diskfs_make_node): Initialize filemod_reqs.
+ * node-drop.c (free_modreqs): New function.
+ (diskfs_drop_node): Free filemod_reqs.
+ * file-chauthor.c (dithkfth_TH_file_chauthor): Add file
+ notifications.
+ * file-chflags.c (diskfs_S_file_chflags): Likewise.
+ * file-chmod.c (diskfs_S_file_chmod): Likewise.
+ * file-chown.c (diskfs_S_file_chown): Likewise.
+ * file-set-size.c (diskfs_S_file_set_size): Likewise.
+ * io-prenotify.c (diskfs_S_io_prenotify): Likewise.
+ * io-write.c (diskfs_S_io_write): Likewise.
+ * node-rdwr.c (diskfs_node_rdwr): Likewise.
+
+Sat Aug 8 17:01:58 1998 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * boot-start.c (diskfs_S_fsys_init): __vm_allocate -> vm_allocate
+ and __mach_task_self -> mach_task_self. Reported by Mark Kettenis
+ (kettenis@phys.uva.nl).
+
+1998-07-25 Roland McGrath <roland@baalperazim.frob.com>
+
+ * shutdown.c (diskfs_shutdown): Sync and set the clean flag even if we
+ don't shut down. Thus a disk that was in use but hadn't been touched
+ recently needn't necessarily be checked after a system crash.
+
+1998-07-20 Roland McGrath <roland@baalperazim.frob.com>
+
+ * dir-lookup.c (diskfs_S_dir_lookup: short_circuited_callback1): Fix
+ type of arg `argz_len' to use size_t *.
+
+Tue Jul 14 16:27:00 1998 Thomas Bushnell, n/BSG <tb@mit.edu>
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Don't require the node to be
+ a directory in the null pathname case. (Thus reverting one of the
+ changes of June 15, 1994.)
+
+Mon Jun 29 18:54:23 1998 Thomas Bushnell, n/BSG <tb@mit.edu>
+
+ * lookup.c (diskfs_lookup): If NAME is empty, return an error.
+
+Tue May 12 12:08:35 1998 Thomas Bushnell, n/BSG <tb@mit.edu>
+
+ * file-get-trans.c (diskfs_S_file_get_translator) [S_ISCHR ||
+ S_ISBLK]: Free BUF after using it. Reported by Katusya Tanaka
+ (wyvern@pb3.so-net.ne.jp).
+
+Tue Sep 23 15:28:57 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * file-reparent.c (diskfs_S_file_reparent): Use diskfs_nrele
+ instead of protocol-violating up-tree lock.
+ * peropen-rele.c (diskfs_release_peropen): Likewise.
+
+1997-09-18 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * priv.h (fs_control_port): Declaration removed.
+ (_diskfs_nosuid, _diskfs_noexec): Renamed from nosuid & noexec.
+ * init-init.c: Prepend "_diskfs" to uses of NOSUID & NOEXEC.
+ * file-exec.c (diskfs_S_file_exec): Likewise.
+ * opts-std-startup.c (parse_startup_opt): Likewise.
+ * opts-std-runtime.c (set_opts): Likewise.
+ (OPT_EXEC_OK, OPT_SUID_OK): Rename definitions from ..._OPT.
+
+1997-09-16 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * opts-append-std.c (diskfs_append_std_options): Add --no-suid and
+ --no-exec options. Don't deallocate ARGZ when we get an error.
+
+Tue Sep 16 14:37:51 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * opts-append-std.c (diskfs_append_std_options): Add --no-suid and
+ --no-exec when appropriate.
+ * priv.h (nosuid, noexec): New variables.
+ * init-init.c (nosuid, noexec): New variables, initialized to zero.
+ * file-exec.c (diskfs_S_file_exec): If noexec is on, then prohibit
+ all execution with EACCES. If nosuid is on, then prohibit setuid
+ or setgid execution by silently omitting the uid substitution.
+ * opts-std-startup.c (parse_startup_opt): Implement --no-suid and
+ --no-exec.
+ * opts-common.c (diskfs_common_options): Add --no-suid and
+ --no-exec.
+ * opts-std-runtime.c (struct parse_hook): Add nosuid and noexec.
+ (parse_opt) [cases 'S', 'E', OPT_SUID_OK, OPT_EXEC_OK] Understand
+ --no-suid, --no-exec, --suid-ok, and --exec-ok.
+ (parse_opt) [case ARGP_KEY_INIT]: Initialize H->nosuid and
+ H->noexec.
+ (OPT_SUID_OK, OPT_EXEC_OK): New macros.
+ (std_runtime_options): Add --suid-ok and --exec-ok.
+ (set_opts): Set nosuid and noexec from H->nosuid and H->noexec.
+
+ * opts-common.c (diskfs_common_options): Rename --nosync to
+ --no-sync; leave --nosync as an alias.
+
+Wed Aug 20 14:03:41 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * diskfs.h: Doc fix.
+
+ * io-map.c (diskfs_S_io_map): Cope with error return from
+ diskfs_get_filemap.
+ * rdwr-internal.c (_diskfs_rdwr_internal): Likewise.
+
+ * disk-pager.c (service_paging_requests): New args for
+ ports_manage_port_operations_multithread.
+ * init-first.c (master_thread_function): Likewise.
+
+1997-08-19 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * filedev.c, machdev.c: Files removed.
+
+Thu Jul 24 12:57:26 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * name-cache.c (find_cache): Grammar doc fix.
+
+1997-07-10 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * opts-std-runtime.c (parse_opt): Turn off synchronous mode when
+ setting a sync interval.
+
+Mon Jul 7 16:25:49 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * file-exec.c: Include <fcntl.h> instead of <fcntlbits.h>.
+ Suggested by Marcus G. Daniels (marcus@cathcart.sysc.pdx.edu).
+
+Mon Jun 30 17:26:38 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_hard_readonly): New variable.
+ (diskfs_readonly): Doc change.
+ * readonly.c (diskfs_readonly): Provide initialized declaration.
+ (diskfs_check_readonly): If we cannot write the media and so we
+ switch to readonly, set diskfs_hard_readonly too.
+ (diskfs_set_readonly): If diskfs_hard_readonly is set, then
+ inhibit any attempt to clear readonly status.
+
+1997-06-23 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * peropen-make.c (diskfs_make_peropen): Initialize the
+ ROOT_PARENT, SHADOW_ROOT, and SHADOW_ROOT_PARENT fields.
+
+1997-06-09 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * io-stat.c (diskfs_S_io_stat): Use fshelp_translated rather than
+ fshelp_fetch_control.
+
+Fri Jun 6 11:42:14 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * Makefile (LCLHDRS): Add fhandle.h.
+
+Tue May 27 11:55:56 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * file-chmod.c (diskfs_S_file_chmod): Turn off S_ITRANS bits too.
+
+Mon Feb 24 17:22:05 1997 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * io-identity.c (diskfs_S_io_identity): Pass CRED's shadow root
+ inode number to fshelp_get_identity when creating a shadow root
+ fsid, not INUM.
+
+Mon Feb 24 14:40:02 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * dir-rmdir.c (diskfs_S_dir_rmdir): Check EBUSY-when-translated
+ error before ENOTDIR-when-not-dir.
+
+Sat Feb 22 00:00:32 1997 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * io-stat.c (diskfs_S_io_stat): Mark shadow roots with S_IROOT.
+ * io-identity.c (diskfs_S_io_identity): Return different fsys ids
+ for different shadow roots.
+
+ * peropen-rele.c (diskfs_release_peropen): Don't deadlock if PO's
+ shadow_root is also it's node.
+ * file-reparent.c (diskfs_S_file_reparent): Don't release a
+ reference to any old shadow_root if it was == NODE. Don't aquire
+ a new reference for NODE.
+
+Fri Feb 21 17:12:04 1997 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * dir-init.c (diskfs_init_dir): Use CRED->po as LOOKUPCRED's po,
+ so that root detection works (and doesn't crash).
+
+Thu Feb 20 00:43:38 1997 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * io-read.c (diskfs_S_io_read): Support reading from sylinks.
+ * dir-lookup.c (diskfs_S_dir_lookup): Allow symlinks to be opened
+ for O_READ.
+
+Thu Feb 13 19:27:16 1997 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * dir-rename.c (diskfs_S_dir_rename): Return EXDEV if FROMCRED and
+ TOCRED are in different shadow trees.
+
+ * file-reparent.c (diskfs_S_file_reparent): New function, from
+ dir-reparent.c.
+ * dir-reparent.c: File removed.
+ * Makefile (FSSRCS): dir-reparent.c replaced by file-reparent.c.
+
+Wed Feb 12 14:23:15 1997 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * peropen-make.c (diskfs_make_peropen): Add & use CONTEXT param.
+ Remove DOTDOT & DEPTH params.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Pass a prototype peropen
+ instead of the dotdotport and depth to diskfs_make_peropen.
+ * fsys-getfile.c (diskfs_S_fsys_getfile): Likewise.
+ * file-exec.c (diskfs_S_file_exec): Likewise.
+ * dir-reparent.c (diskfs_S_dir_reparent): Likewise.
+ * dir-mkfile.c (diskfs_S_dir_mkfile): Likewise.
+ * dir-lookup.c (diskfs_S_dir_lookup): Likewise.
+ * boot-start.c (diskfs_start_bootstrap): Likewise.
+ (diskfs_S_exec_startup_get_info): Likewise.
+ (diskfs_execboot_fsys_startup): Likewise.
+ (diskfs_S_fsys_init): Likewise.
+ * trans-callback.c (_diskfs_translator_callback2_fn): Pass COOKIE
+ directly to diskfs_make_peropen instead of unpacking each arg.
+ * priv.h (struct diskfs_trans_callback_cookie2): Type removed.
+ * dir-lookup.c (diskfs_S_dir_lookup): Use DIRCRED->po as the
+ cookie for fshelp_fetch_root instead of a local structure.
+ * diskfs.h (diskfs_lookup): Remove DEPTH & NEW_DEPTH params.
+ * dir-lookup.c (diskfs_S_dir_lookup): Get rid of DEPTH variable.
+ Get rid of depth parameters to diskfs_lookup.
+ Deal properly with EAGAIN return from diskfs_lookup.
+ Replace references to dotdotport with root_parent.
+ * dir-unlink.c (diskfs_S_dir_unlink): Don't pass depth args to
+ diskfs_lookup.
+ * dir-rmdir.c (diskfs_S_dir_rmdir): Likewise.
+ * dir-renamed.c (diskfs_rename_dir, checkpath): Likewise.
+ * dir-rename.c (diskfs_S_dir_rename): Likewise.
+ * dir-mkdir.c (diskfs_S_dir_mkdir): Likewise.
+ * dir-link.c (diskfs_S_dir_link): Likewise.
+ * dir-init.c (diskfs_init_dir): Likewise.
+ * dir-clear.c (diskfs_clear_directory): Likewise.
+ * lookup.c (diskfs_lookup): Remove DEPTH & NEW_DEPTH params.
+ Check CRED->po->shadow_root for root traversals, and get rid of assert
+ that EAGAIN isn't returned from diskfs_lookup_hard.
+ * diskfs.h (struct peropen):
+ Add shadow_root_parent & shadow_root fields.
+ Removed depth field.
+ Rename dotdotnode field to root_parent.
+ * peropen-rele.c (diskfs_release_peropen): Finalize new state.
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Remove O_EXLOCK & O_SHLOCK
+ from FLAGS mask, now that they're included in O_HURD.
+
+Thu Feb 6 02:17:35 1997 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * io-write.c (diskfs_S_io_write): Check OFF for validity and
+ return EINVAL if it's bogus.
+ * io-read.c (diskfs_S_io_read): Likewise.
+
+ * dir-mkfile.c (diskfs_S_dir_mkfile): New file's depth is one
+ greater than CRED's.
+
+ * file-getfh.c (diskfs_S_file_getfh): Implement (code from ufs).
+ * fsys-getfile.c (diskfs_S_fsys_getfile): Likewise.
+ * fhandle.h: New file.
+
+Wed Feb 5 16:06:26 1997 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * dir-reparent.c (diskfs_S_dir_reparent): Implement.
+
+ * lookup.c (diskfs_lookup): Add DEPTH & NEW_DEPTH arguments.
+ Implement new fs-root detection using them.
+ * diskfs.h (diskfs_lookup): Add DEPTH & NEW_DEPTH arguments.
+ * dir-link.c (diskfs_S_dir_link): Supply DEPTH & NEW_DEPTH
+ arguments to diskfs_lookup.
+ * dir-clear.c (diskfs_clear_directory): Likewise.
+ * dir-init.c (diskfs_init_dir): Likewise.
+ * dir-renamed.c (checkpath, diskfs_rename_dir): Likewise.
+ * dir-rename.c (diskfs_S_dir_rename): Likewise.
+ * dir-mkdir.c (diskfs_S_dir_mkdir): Likewise.
+ * dir-rmdir.c (diskfs_S_dir_rmdir): Likewise.
+ * dir-unlink.c (diskfs_S_dir_unlink): Likewise.
+ * dir-lookup.c (diskfs_S_dir_lookup): Likewise.
+ Add DEPTH variable.
+ * dir-link.c (diskfs_S_dir_link): Translate EAGAIN (meaning root's
+ parent) to EINVAL.
+ * dir-rename.c (diskfs_S_dir_rename): Likewise.
+
+ * diskfs.h (struct peropen): Add DEPTH field.
+ (diskfs_make_peropen): Add DEPTH argument.
+ * peropen-make.c (diskfs_make_peropen): Add & use DEPTH argument.
+ * boot-start.c (diskfs_start_bootstrap,
+ diskfs_S_exec_startup_get_info, diskfs_execboot_fsys_startup,
+ diskfs_S_fsys_init): Supply DEPTH argument to diskfs_make_peropen.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Likewise.
+ * file-exec.c (diskfs_S_file_exec): Likewise.
+ * dir-mkfile.c (diskfs_S_dir_mkfile): Likewise.
+ * dir-lookup.c (diskfs_S_dir_lookup): Likewise.
+ * priv.h (struct diskfs_trans_callback_cookie2): New type.
+ * trans-callback.c (_diskfs_translator_callback2_fn): Expect
+ COOKIE2 to be a pointer to a struct diskfs_trans_callback_cookie2,
+ and use that to pass args to diskfs_make_peropen.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Pass new type of cookie2 to
+ fshelp_fetch_root, as expected by _diskfs_translator_callback2.
+ * dir-lookup.c (diskfs_S_dir_lookup): Likewise.
+
+Mon Jan 20 16:18:00 1997 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * dir-reparent.c (diskfs_S_dir_reparent): New file.
+ * Makefile (FSSRCS): Add dir-reparent.c.
+
+ * disk-pager.c (preemptor): Renamed from `preempter'; type & init
+ changed as well.
+ (diskfs_start_disk_pager): `preempter' -> `preemptor'.
+ * diskfs-pager.h: Doc fix.
+
+Tue Nov 19 18:21:12 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * diskfs.h (struct node): Add author_tracks_uid field.
+ * file-chown.c (diskfs_S_file_chown): If NP->author_tracks_uid,
+ modify NP->dn_stat.st_author as well.
+ * node-create.c (diskfs_create_node): Likewise.
+
+Mon Nov 18 17:02:22 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * diskfs.h (struct node): Remove istranslated field.
+ * io-stat.c (diskfs_S_io_stat): Set S_IATRANS & S_IROOT bits in
+ st_mode field of returned buffer if appropiate.
+ * dir-lookup.c (diskfs_S_dir_lookup): Use S_IPTRANS bit in dn_stat
+ st_mode field rather than istranslated field.
+ * file-get-trans.c (diskfs_S_file_get_translator): Likewise.
+ * file-set-trans.c (diskfs_S_file_set_translator): Likewise.
+ * file-inv-trans.c (diskfs_S_file_invoke_translator): Likewise.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Likewise.
+ * node-drop.c (diskfs_drop_node): Likewise.
+ * trans-callback.c (_diskfs_translator_callback1_fn): Likewise.
+ * dir-rmdir.c (diskfs_S_dir_rmdir): Likewise.
+
+ * file-get-transcntl.c (diskfs_S_file_get_translator_cntl): Use
+ MACH_MSG_TYPE_MOVE_SEND to return *ctl, rather than COPY.
+ (diskfs_S_file_get_translator_cntl): Correctly test for errors
+ from fshelp_fetch_control.
+
+Fri Nov 15 14:06:16 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * protid-make.c (diskfs_finish_protid): Fix typo.
+
+ * file-chown.c (diskfs_S_file_chown): Look for UID, not CRED in
+ the uid set.
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Make the unauthenticated
+ port correctly.
+
+Thu Nov 14 13:07:37 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * dir-init.c (diskfs_init_dir): New vars VEC and USER; fabricate
+ LOOKUPCRED to correspond to new structure definitions.
+
+ * io-restrict-auth.c (diskfs_S_io_restrict_auth): Declare I and
+ add a missing semicolon.
+
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Eliminate PSEUDOCRED
+ entirely. Fix unrelated typo.
+
+ * file-chauthor.c (dithkfth_TH_file_chauthor): Fix first arg in
+ call to fthhelp_ithowner.
+
+Tue Nov 12 22:45:07 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * diskfs.h: Correctly close comment.
+
+Thu Nov 7 14:49:19 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * io-restrict-auth.c (diskfs_S_io_restrict_auth): If CRED has
+ root, use the requested id sets verbatim.
+
+Thu Nov 7 01:03:11 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * protid-rele.c (diskfs_protid_rele): Free CRED->user.
+
+Wed Nov 6 17:55:17 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_isuid, diskfs_groupmember, diskfs_isowner,
+ diskfs_access, diskfs_checkdirmod): Delete functions.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Replace PSEUDOCRED with
+ a real iouser and specify that in the relevant calls.
+ * io-restrict-auth.c (diskfs_S_io_restrict_auth): Reworked to use
+ idvecs.
+ * file-chmod.c (diskfs_S_file_chmod): diskfs_isuid ->
+ idvec_contains.
+ * file-chown.c (diskfs_S_file_chown): Likewise.
+ * file-getcontrol.c (diskfs_S_file_getcontrol): Likewise.
+ * file-chmod.c (diskfs_S_file_chmod): diskfs_groupmember ->
+ idvec_contains.
+ * file-chown.c (diskfs_S_file_chown): Likewise.
+ * node-create.c (diskfs_create_node): Likewise.
+ * dir-lookup.c (diskfs_S_dir_lookup): diskfs_isowner ->
+ fshelp_isowner.
+ * file-chflags.c (diskfs_S_file_chflags): Likewise.
+ * file-chmod.c (diskfs_S_file_chmod): Likewise.
+ * file-chown.c (diskfs_S_file_chown): Likewise.
+ * file-get-transcntl.c (diskfs_S_file_get_translator_cntl):
+ Likewise.
+ * file-set-trans.c (diskfs_S_file_set_translator): Likewise.
+ * file-utimes.c (diskfs_S_file_utimes): Likewise.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Likewise.
+ * lithp.h (dithkfth_ithowner): Deleted macro.
+ (fthhelp_ithowner, uther): New macros.
+ * file-chauthor.c (dithkfth_TH_file_chauthor): dthkfth_ithowner ->
+ fthhelp_ithowner.
+ * dir-lookup.c (diskfs_S_dir_lookup): diskfs_access ->
+ fshelp_access.
+ * dir-mkfile.c (diskfs_S_dir_mkfile): Likewise.
+ * file-access.c (diskfs_S_file_check_access): Likewise.
+ * file-exec.c (diskfs_S_file_exec): Likewise (in dead code).
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Likewise.
+ * ifsock.c (diskfs_S_ifsock_getsockaddr): Likewise.
+ * lookup.c (diskfs_lookup): Likewise.
+ (diskfs_lookup): diskfs_checkdirmod -> fshelp_checkdirmod.
+ * dir-lookup.c (diskfs_S_dir_lookup): New arg format for
+ fshelp_fetch_root.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Likewise.
+ * diskfs.h, protid-make.c (diskfs_create_protid): Delete args
+ `uids', `gids', `nuids', and `ngids'. Replace with new arg
+ `user'. All callers changed.
+ (diskfs_finish_protid): Likewise.
+ * file-inv-trans.c (diskfs_S_file_invoke_translator): Use
+ CRED->user instead of old fields.
+ * io-restrict-auth.c (diskfs_S_io_restrict_auth): Likewise.
+ * node-create.c (diskfs_create_node): Likewise.
+ * file-exec.c (diskfs_S_file_exec): Likewise. Use idvec_merge
+ instead of idvec_merge_ids, now that it's convenient.
+ * io-reauthenticate.c (diskfs_S_io_reauthenticate): Use new
+ iohelp_reauthenticate.
+
+Tue Nov 5 21:10:18 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * diskfs.h: Include <idvec.h>.
+ (struct protid): Delete members `uids', `gids', `nuids' and
+ `ngids'. New member `user'.
+
+Thu Oct 24 15:56:30 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * opts-std-startup.c (store_argp_children, startup_argp_children):
+ New variables.
+ (store_argp_parents, startup_argp_children): Variable removed.
+ (diskfs_store_startup_argp): Use STORE_ARGP_CHILDREN instead of
+ STORE_ARGP_PARENTS.
+ (diskfs_startup_argp): Use STARTUP_ARGP_CHILDREN instead of
+ STARTUP_ARGP_PARENTS.
+ * opts-std-runtime.c (children): New variable.
+ (parents): Variable removed.
+ (diskfs_std_runtime_argp): Use CHILDREN instead of PARENTS.
+
+Mon Oct 21 21:54:34 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * diskfs.h: Add extern inline protection.
+ * diskfs.c: New file.
+ * Makefile (OTHERSRCS): Add diskfs.c.
+
+Fri Oct 11 21:55:45 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Temporarily add O_EXLOCK and
+ O_SHLOCK to the set of retained flags, until they get added to O_HURD.
+ Turn off OPENONLY_STATE_MODES bits in the flags we pass to
+ diskfs_make_peropen, not everything *but* them!
+ * priv.h (OPENONLY_STATE_MODES): Add O_EXLOCK & O_SHLOCK.
+
+Thu Oct 10 17:22:06 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Frob lock in NEWPI->po, not PO.
+ Free NEWPI if we get an error trying to lock it.
+ <sys/file.h>: New include.
+
+Thu Oct 10 17:11:05 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Implement O_SHLOCK and
+ O_EXLOCK directly here.
+
+Thu Oct 10 10:53:28 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * peropen-rele.c (diskfs_release_peropen): Before freeing PO,
+ release any user lock it's holding.
+ <sys/file.h>: New include.
+
+Tue Oct 8 15:01:32 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * ifsock.c (diskfs_S_ifsock_getsockaddr): Write permission governs
+ access to sockets, not read permission.
+
+Mon Oct 7 14:50:04 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * dir-rmdir.c (diskfs_S_dir_rmdir): Return ENOTDIR if NP isn't a dir.
+
+Tue Sep 24 23:51:37 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * opts-version.c (_print_version): Follow version string with newline.
+
+Thu Sep 19 17:59:37 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * Makefile (HURDLIBS): Add store.
+
+Wed Sep 18 15:02:31 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * opts-version.c (_print_version): Change to use new version
+ format from the coding standards.
+
+ * opts-std-runtime.c (std_runtime_options): Change --remount to
+ --update (keep --remount as a deprecated alias).
+ <argp.h>: New include.
+ * opts-append-std.c <stdio.h>: New include.
+ * dir-lookup.c <stdio.h>: New include.
+
+Fri Sep 13 19:15:45 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * file-get-fs-opts.c (diskfs_S_file_get_fs_options): Free ARGZ if
+ diskfs_append_args returns an error.
+ * fsys-options.c (diskfs_S_fsys_get_options): Likewise.
+
+1996-09-12 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_disk_name): New declaration.
+ * readonly.c (diskfs_check_readonly): Use DISKFS_DISK_NAME
+ instead of DISKFS_DEVICE_ARG.
+ * init-startup.c (_diskfs_init_completed): Likewise.
+
+Wed Sep 11 17:25:14 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * disk-pager.c (diskfs_start_disk_pager): Renamed from
+ setup_disk_pager.
+ Add PAGER_BUCKET, IMAGE, and SIZE arguments.
+ Pass in PAGER_BUCKET to thread routine, and don't create it.
+ (diskfs_disk_pager): Renamed from disk_pager.
+ (disk_image): Variable removed.
+ (pager_bucket): Declaration removed.
+ (service_paging_requests): Get PAGER_BUCKET from argument.
+ * diskfs-pager.h (diskfs_start_disk_pager): Renamed from
+ disk_pager_setup.
+ Add PAGER_BUCKET, IMAGE, and SIZE arguments.
+ (diskfs_disk_pager): Renamed from disk_pager.
+ (disk_image, pager_bucket): Declarations removed.
+
+Mon Sep 9 10:54:58 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * fsys-options.c (diskfs_S_fsys_get_options): Initialize ARGZ &
+ ARGZ_LEN to the program name, and call diskfs_append_args instead
+ of diskfs_get_options.
+ * file-get-fs-opts.c (diskfs_S_file_get_fs_options): Likewise.
+ <argz.h>: New include.
+ * diskfs.h (diskfs_append_args): Renamed from diskfs_get_options.
+ * opts-get.c (diskfs_append_args): Likewise.
+ * opts-std-startup.c <hurd/store.h>: New include.
+ (store_argp_parents): Use diskfs_startup_argp, not
+ diskfs_std_startup_argp.
+ * Makefile (libdiskfs.so): Depend on libstore.so.
+
+ * opts-version.c <argp.h>, <stdio.h>: New includes.
+ (_print_version): Test diskfs_extra_version against 0 too.
+ * io-version.c <stdio.h>: New include.
+ (diskfs_S_io_server_version): Use snprintf instead of sprintf.
+
+Sun Sep 8 18:19:50 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * diskfs.h <argp.h>: Include removed.
+ (struct argp): New (incomplete) declaration.
+ (diskfs_get_file_device, diskfs_get_mach_device): Declarations removed.
+ (diskfs_startup_argp): Renamed from diskfs_std_startup_argp.
+ (diskfs_store_startup_argp): Renamed from
+ diskfs_std_device_startup_argp.
+ (diskfs_device_arg, diskfs_use_mach_device, diskfs_device_open,
+ diskfs_device, diskfs_device_name, diskfs_device_start,
+ diskfs_device_size, diskfs_device_block_size,
+ diskfs_log2_device_block_size, diskfs_log2_device_blocks_per_page,
+ diskfs_device_write_sync, diskfs_device_read_sync): Declarations
+ removed.
+ * opts-std-startup.c (diskfs_use_mach_device, diskfs_device_arg,
+ dev_startup_options, dev_startup_argp_parents,
+ diskfs_std_device_startup_argp): Variables removed.
+ (parse_dev_startup_opt): Function removed.
+ (diskfs_startup_argp): Renamed from diskfs_std_startup_argp.
+ * Makefile (OTHERSRCS): Remove filedev.c, machdev.c, dev-open.c,
+ dev-io.c, & dev-globals.c.
+
+Thu Sep 12 16:22:27 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * Makefile: New variable.
+ (libdiskfs.so): Delete special depedency.
+
+Thu Sep 5 11:13:54 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * io-version.c (diskfs_S_io_server_version): Only fill in
+ SERVER_NAME; ignore the rest.
+
+ * diskfs.h (diskfs_major_version, diskfs_minor_version,
+ diskfs_edit_version): Delete variables.
+ (diskfs_server_version, diskfs_extra_version): New variables.
+ * boot-start.c (diskfs_S_fsys_init): Register version from
+ diskfs_server_version; pass empty string as release.
+ * extra-version.c: New file.
+ * Makefile (OTHERSRCS): Add extra-version.c.
+ * opts-version.c: Include <version.h>.
+ (diskfs_extra_version): Delete special declaration.
+ (_print_version): Use the user's provided version number, and also
+ give it our (libdiskfs) version number.
+
+Tue Sep 3 10:48:05 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * name-cache.c (diskfs_enter_lookup_cache): Cache `.' and `..'
+ just like other nodes.
+ (diskfs_check_lookup_cache): If we get a cache hit on `..', then
+ do the inverse locking semantic, and only return success if things
+ are stable around the call.
+
+Fri Aug 30 21:57:18 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * lookup.c (cache_misses): New variable, to find out what sort of
+ thing all the cache misses are.
+ (cm_lock): New variable.
+ (diskfs_lookup): Keep track of cache misses in cache_misses.
+
+ * name-cache.c (MAXCACHE): 200 now. After experimentation, this
+ appears to be a pretty good value. Very little benefit after
+ this.
+
+Fri Aug 30 20:41:27 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * name-cache.c (struct lookup_cache): Delete member `hits'.
+ New member `stati'.
+ (diskfs_enter_lookup_cache): Don't initialize C->hits.
+ (find_cache): Set C->stati before returning.
+ (build_partial): Delete function.
+ (diskfs_check_lookup_cache): Delete calls to build_partial.
+ Register all statistics through register_neg_hit,
+ register_pos_hit, and register_miss.
+ (MAXCACHE): 2000 now.
+
+Wed Aug 28 12:20:53 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * name-cache.c (MAXCACHE): 500 for now.
+
+Mon Aug 26 15:10:55 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * name-cache.c (MAXCACHE): Increase to 50000.
+ (struct lookup_cache): New member `hits'.
+ (statistics): Name struct type `struct stats'.
+ (diskfs_enter_lookup_cache): Initialize C->hits.
+ (PARTIAL_THRESH, NPARTIALS): New macros.
+ (partial_stats): New variable.
+ (build_partial): New function.
+ (diskfs_check_lookup_cache): Call build_partial after statistics
+ frobbing.
+
+ * name-cache.c (diskfs_check_lookup_cache): Increment members of
+ statistics while still holding CACHE_LOCK.
+
+Fri Aug 16 18:23:25 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * name-cache.c (diskfs_check_lookup_cache): Keep track of negative
+ hits properly.
+ * lookup.c (diskfs_lookup): On LOOKUPs that fail to find the node,
+ enter a negative cache entry.
+
+Thu Aug 15 16:07:23 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * opts-version.c (diskfs_extra_version): New (weak) reference.
+ (_print_version): Use DISKFS_EXTRA_VERSION. Tweak edit version.
+ Fix type of EV.
+
+Thu Aug 15 16:38:41 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * io-identity.c (diskfs_S_io_identity): Don't hold lock around
+ call to fshelp_get_identity.
+
+Mon Aug 12 15:54:27 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * opts-version.c (_print_version): Print the edit version too if
+ it's non-zero.
+
+Thu Aug 8 18:18:09 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * readonly.c: Include <error.h>.
+
+Wed Aug 7 13:53:56 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * readonly.c (diskfs_check_readonly): If we get an error from
+ diskfs_hypermetadata, then switch to readonly.
+ * diskfs.h (diskfs_set_hypermetadata): Require an error code return.
+ * dev-io.c (diskfs_device_write_sync): If we get D_READ_ONLY, then
+ return EROFS to the caller instead of EIO.
+
+ * node-create.c (diskfs_create_node): New files always copy GID
+ from their parent; that's NetBSD's behavior, and it's good enough
+ for me.
+
+Thu Aug 1 17:24:08 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * file-get-transcntl.c (diskfs_S_file_get_translator_cntl): Don't
+ diskfs_nput NP; we've never created a reference. Just unlock it.
+ (And bother to lock it in the first place.)
+
+Sat Jul 27 20:05:17 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * lookup.c (diskfs_lookup): Don't nput *NP if we didn't find a file.
+
+ * init-startup.c (diskfs_S_startup_dosync): Clean up after ourselves.
+ Don't sync if DISKFS_READONLY.
+ * file-syncfs.c (diskfs_S_file_syncfs): Don't sync if DISKFS_READONLY.
+ * fsys-syncfs.c (diskfs_S_fsys_syncfs): Likewise.
+ * sync-interval.c (periodic_sync): Likewise.
+ * shutdown.c (diskfs_shutdown): Likewise.
+
+Fri Jul 26 14:52:23 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * file-exec.c (diskfs_S_file_exec): Unlock NP before we attempt to
+ do setuid/setgid (which otherwise can deadlock during port reauth).
+ Pay attention to the error code returned by fshelp_exec_reauth,
+ and don't make NEWPI if it's an error.
+ Initialize ERR.
+
+Tue Jul 23 16:05:55 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * opts-version.c (_print_version): Make return type void.
+
+Fri Jul 19 21:19:42 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * filedev.c (diskfs_get_file_device): INTS[3] contains the number
+ of runs, not the number of offsets (which is 2*NUM_RUNS).
+ Don't deallocate the device port we've fetched.
+
+ * opts-std-startup.c (startup_options, parse_startup_opt): Remove
+ the --version option, which is handled elsewhere now.
+
+Thu Jul 18 23:05:56 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * protid-make.c (diskfs_start_protid): Use noinstall version of
+ ports_create_port.
+ (diskfs_finish_protid): Install port right into port set here.
+
+Mon Jul 15 21:37:12 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_checkdirmod): diskfs_isowner returns error or
+ zero, so invert sense of tests.
+
+ * lookup.c (diskfs_lookup): If we get an error from
+ diskfs_checkdirmod, diskfs_nput the node we picked up; the caller
+ won't want it.
+
+ * dir-renamed.c (diskfs_rename_dir): When unlocking FDP, only do
+ it if we FDP != TDP. Also, only do step two (changing .. in the
+ directory being moved) if FDP != TDP.
+
+Sat Jul 13 20:05:27 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * io-reauthenticate.c (diskfs_S_io_reauthenticate): Repeat
+ diskfs_start_protid and auth_server_authenticate for as we get
+ EINTR.
+
+Sun Jul 7 21:07:53 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * boot-start.c (diskfs_S_fsys_init): Don't use unsafe MOVE_SEND in
+ call to exec_init.
+ * io-reauthenticate.c (diskfs_S_io_reauthenticate): Don't use
+ unsafe MOVE_SEND in auth_server_authenticate.
+
+Sun Jul 7 10:27:37 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * opts-version.c (_print_version): Include HURD_RELEASE in default.
+
+Sat Jul 6 16:27:01 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * opts-version.c: New file.
+ * Makefile (OTHERSRCS): Add opts-version.c.
+
+Sat Jul 6 13:32:58 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * node-drop.c (diskfs_drop_node): If this might be a special
+ symlink, then truncate it even though NP->allocsize might be
+ clear.
+
+Wed Jul 3 11:22:58 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * io-identity.c (diskfs_S_io_identity): Fetch identity using
+ fshelp_get_identity rather than creating it ourselves.
+ * diskfs.h (struct node): Remove member `identity'.
+ * node-drop.c (diskfs_drop_node): Don't deallocate NP->identity.
+ * node-make.c (diskfs_make_node): Don't initialize NP->identity.
+
+Thu Jun 27 10:07:03 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * init-startup.c (diskfs_startup_diskfs): Don't call
+ diskfs_readonly_changed here anymore.
+
+ * disk-pager.c (disk_pager_setup): Check diskfs_readonly variable
+ instead of calling diskfs_check_readonly.
+
+ * Makefile (LCLHDRS): Add diskfs-pager.h.
+
+Tue Jun 25 21:55:24 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * opts-std-runtime.c (parse_opt): Add hair to share arg parsing
+ state between two parsers that use the same parse_opt function at
+ the same time.
+
+Mon Jun 24 14:55:50 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * init-startup.c (diskfs_S_startup_dosync): Don't crash the
+ filesystem, just do a clean sync.
+ * node-drop.c (diskfs_drop_node): Call diskfs_check_readonly
+ before making mods.
+ * priv.h (_diskfs_diskdirty): New variable.
+ * diskfs.h (diskfs_check_readonly): New function.
+ * readonly.c (_diskfs_diskdirty): New var.
+ (diskfs_check_readonly): New function.
+ (diskfs_set_readonly): After clean sync, clear _diskfs_diskdirty.
+ * rdwr-internal.c (_diskfs_rdwr_internal): Use
+ diskfs_check_readonly instead of diskfs_readonly.
+ * node-create.c (diskfs_create_node): Likewise.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Likewise.
+ * file-set-trans.c (diskfs_S_file_set_translator): Likewise.
+ * disk-pager.c (disk_pager_setup): Likewise.
+ * dir-unlink.c (diskfs_S_dir_unlink): Likewise.
+ * dir-rmdir.c (diskfs_S_dir_rmdir): Likewise.
+ * dir-rename.c (diskfs_S_dir_rename): Likewise.
+ * dir-mkfile.c (diskfs_S_dir_mkfile): Likewise.
+ * dir-mkdir.c (diskfs_S_dir_mkdir): Likewise.
+ * dir-lookup.c (diskfs_S_dir_lookup): Likewise.
+ * dir-link.c (diskfs_S_dir_link): Likewise.
+ * conch-fetch.c (iohelp_fetch_shared_data): Likewise.
+ * remount.c (diskfs_remount): Likewise.
+
+ * io-reauthenticate.c (diskfs_S_io_reauthenticate): If
+ auth_server_authenticate fails, then fill with empty IDs. We
+ can't permit interruption, because this is a simpleroutine.
+
+ * file-set-trans.c (diskfs_S_file_set_translator): Validate rdev
+ change before making it.
+ * file-chflags.c (diskfs_S_file_chflags): Validate flags change
+ before making it.
+ * lithp.h (dithkfth_validate_author_change): New macro.
+ * file-chauthor.c (dithkfth_TH_file_chauthor): Validate new author
+ before changing it.
+ * node-create.c (diskfs_create_node): Validate group change before
+ making it.
+ * file-chown.c (diskfs_S_file_chown): Likewise.
+ * node-create.c (diskfs_create_node): Validate mode change before
+ making it.
+ * file-set-trans.c (diskfs_S_file_set_translator): Likewise
+ * file-chmod.c (diskfs_S_file_chmod): Likewise.
+ * node-create.c (diskfs_creade_node): Validate owner change before
+ making it.
+ * file-chown.c (diskfs_S_file_chown): Likewise.
+ * Makefile (OTHERSRCS): Add validate-mode.c, validate-group.c,
+ validate-author.c, validate-flags.c, validate-rdev.c, and
+ validate-owner.c.
+ * validate-mode.c, validate-group.c, validate-author.c,
+ validate-flags.c, validate-rdev.c, validate-owner.c: New files.
+ * diskfs.h (diskfs_validate_mode_change,
+ diskfs_validate_owner_change, diskfs_validate_group_change,
+ diskfs_validate_author_change, diskfs_validate_flags_change,
+ diskfs_validate_rdev_change): New decls.
+
+Fri Jun 21 00:18:16 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * fsys-options.c (diskfs_S_fsys_get_options): Use
+ fshelp_return_malloced_buffer to setup the return data.
+ * file-get-fs-opts.c (diskfs_S_file_get_fs_options): Likewise.
+ * opts-set.c (diskfs_set_options): Supply INPUT arg to
+ fshelp_set_options.
+
+ * opts-append-std.c (diskfs_append_std_options): Use argz_add
+ instead of rolling our own. Deal with errors.
+ <argz.h>: New include.
+
+Wed Jun 19 21:57:46 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * init-startup.c (diskfs_S_startup_dosync): Pass HANDLE to
+ ports_lookup_port. Declare ERR.
+
+ * opts-get.c (diskfs_get_options): Call diskfs_append_std_options to
+ do most of the work.
+ * opts-append-std.c: New file.
+ * opts-set.c: New file (old version renamed).
+ * opts-std-runtime.c: Renamed from opts-set.c.
+ (diskfs_set_options): Function removed.
+ (struct parse_hook): New type.
+ (set_opts, parse_opt): New functions.
+ (common_argp, parents, diskfs_std_runtime_argp): New variables.
+ * diskfs.h (diskfs_parse_runtime_options): Decl removed.
+ (diskfs_std_startup_argp): Renamed from diskfs_startup_argp, now a
+ structure decl, not a pointer decl.
+ (diskfs_std_device_startup_argp): Renamed from
+ diskfs_device_startup_argp, now a structure decl, not a pointer
+ decl.
+ (diskfs_set_options): Update decl (now takes argz & argz_len).
+ (diskfs_runtime_arg): New declaration.
+ (diskfs_std_runtime_argp, diskfs_append_std_options): New declarations.
+ * opts-runtime-parse.c, opts-runtime-unparse.c: Files removed.
+ * opts-std-startup.c (parse_dev_startup_opt): Use argp_error.
+ (diskfs_startup_arg, diskfs_device_startup_arg): Variables removed.
+ (diskfs_std_startup_argp): Renamed from startup_argp, exported.
+ (diskfs_std_device_startup_argp): Renamed from dev_startup_argp,
+ exported.
+ * fsys-options.c (diskfs_S_fsys_set_options): Don't split
+ arguments, just call diskfs_set_options with what we got.
+ * opts-runtime.c: New file.
+ * Makefile (OTHERSRCS): Add opts-std-runtime.c, opts-append-std.c,
+ opts-runtime.c. Remove opts-runtime-parse.c, opts-runtime-unparse.c
+
+Thu Jun 13 10:05:51 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * Makefile (MIGSTUBS): Add startup_notifyServer.o.
+ * init-startup.c (diskfs_S_startup_dosync): Uncomment function.
+ * demuxer.c (diskfs_demuxer): Call diskfs_startup_notify_server.
+ * init-startup.c (_diskfs_init_completed): NOTIFY doesn't need
+ deallocation.
+
+ * boot-start.c (diskfs_S_fsys_init): Build version string
+ correctly.
+
+Tue May 14 11:14:12 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * Makefile (OTHERSRCS): Remove init-completed.c.
+
+ * node-drop.c (diskfs_drop_node): Fix typo.
+
+Sat May 11 01:11:19 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * opts-std-startup.c (parse_dev_startup_opt, parse_startup_opt):
+ Use ARGP_ERR_UNKNOWN instead of EINVAL.
+ * opts-set.c (diskfs_set_options): Likewise.
+
+Fri May 10 17:15:51 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * io-identity.c: New file.
+ * Makefile (IOSRCS): Add io-identity.c.
+ * diskfs.h (diskfs_fsys_identity): New variable.
+ (struct node): New member `identity'.
+ * init-init.c (diskfs_fsys_identity): New variable.
+ (diskfs_init_diskfs): Initialize diskfs_fsys_identity.
+ * node-make.c (diskfs_make_node): Initialize NP->identity.
+ * node-drop.c (diskfs_drop_node): Free NP->identity if it's been
+ allocated.
+
+Thu May 9 11:52:52 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * protid-make.c (diskfs_make_protid): Delete function.
+ * diskfs.h (diskfs_make_protid): Delete declaration.
+
+ * init-startup.c (_diskfs_init_completed): Don't need to insert
+ right any more now that it's a poly arg.
+ Provide helpful name to init.
+
+ * fsys-options.c (diskfs_S_fsys_get_options): Accept and ignore
+ replyport parameters.
+
+ * file-sync.c (diskfs_S_file_sync): Accept and ignore new parm
+ OMITMETADATA.
+
+ * priv.h: ioserver.h -> iohelp.h.
+ * diskfs.h: Likewise.
+ * file-sync.c (diskfs_S_file_sync): s/ioserver/iohelp/g
+ * io-prenotify.c (diskfs_S_io_prenotify): Likewise.
+ * io-get-conch.c (diskfs_S_io_get_conch): Likewise.
+ * io-modes-off.c (diskfs_S_io_clear_some_openmodes): Likewise.
+ * io-modes-on.c (diskfs_S_io_set_some_openmodes): Likewise.
+ * io-modes-set.c (diskfs_S_io_set_all_openmodes): Likewise.
+ * io-read.c (diskfs_S_io_read): Likewise.
+ * io-readable.c (diskfs_S_io_readable): Likewise.
+ * io-rel-conch.c (diskfs_S_io_release_conch): Likewise.
+ * io-seek.c (diskfs_S_io_seek): Likewise.
+ * io-stat.c (diskfs_S_io_stat): Likewise.
+ * io-write.c (diskfs_S_io_write): Likewise.
+ * conch-fetch.c (iohelp_fetch_shared_data): Likewise.
+ * conch-set.c (iohelp_put_shared_data): Likewise.
+ * node-make.c (diskfs_make_node): Likewise.
+ * node-rdwr.c (diskfs_node_rdwr): Likewise.
+ * Makefile (libdiskfs.so): Likewise.
+
+ * dir-rename.c (diskfs_S_dir_rename): Understand new parm EXCL and
+ do the right thing with it.
+ * dir-link.c (diskfs_S_dir_link): Likewise.
+
+Thu May 9 12:12:41 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
+
+ * io-reauthenticate.c (diskfs_S_io_reauthenticate): Don't pass CRED
+ port in auth_server_authenticate.
+
+ * io-select.c (diskfs_S_io_select): Removed TAG arg.
+
+Thu May 9 11:42:53 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * filedev.c (diskfs_get_file_device): Deallocate most things we
+ got back from file_get_storage_info even if we didn't get an error.
+
+ * filedev.c (diskfs_get_file_device): Fix type of DATA & _DATA.
+ BLOCKSIZE -> BLOCK_SIZE. Copy name from DATA, not DEV_NAME_BUF.
+
+Mon May 6 20:12:34 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * filedev.c (diskfs_get_file_device): Enable new version.
+
+Fri May 3 15:55:44 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * filedev.c [0] (diskfs_get_file_device): Rewrite to use new interface.
+
+Tue Apr 30 14:39:06 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * init-startup.c: Include <string.h> and <hurd/startup.h>.
+ (diskfs_startup_diskfs): If not bootstrap filesystem, call
+ _diskfs_init_completed here.
+ (diskfs_S_startup_dosync): New function (commented out).
+ (_diskfs_init_completed): New function.
+ * init-completed.c: Delete file.
+ * init-init.c (diskfs_shutdown_notification_class): New variable.
+ (diskfs_init_diskfs): Initialize diskfs_shutdown_notification_class.
+ * diskfs.h (diskfs_shutdown_notification_class): New variable.
+ * boot-start.c (diskfs_S_fsys_init): diskfs_init_completed ->
+ _diskfs_init_completed.
+ * priv.h (_diskfs_init_completed): New declaration.
+ * diskfs.h (diskfs_init_completed): Delete function.
+
+Mon Apr 29 15:42:23 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * name-cache.c (struct lookup_cache): Add HDR, remove NEXT & PREV.
+ (lookup_cache): Change type to struct cacheq.
+ (mru_cache, lru_cache): Variables removed.
+ (make_mru, make_lru, init_lookup_cache): Functions removed.
+ (find_cache, diskfs_purge_lookup_cache,
+ diskfs_check_lookup_cache): Use cacheq functions.
+
+Sun Apr 28 15:22:30 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
+
+ * protid-make.c: Add obsolescence link warning.
+
+Tue Apr 23 11:05:04 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * node-drop.c (diskfs_drop_node): Don't do anything special for
+ socket naming points.
+ * Makefile (OTHERSRCS): Add dead-name.c.
+ * dead-name.c: New file.
+ * ifsock.c (diskfs_S_ifsock_getsockaddr): Request notification for
+ new SOCKADDR; count that notification as a reference.
+
+Fri Apr 12 15:56:48 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * name-cache.c (diskfs_enter_lookup_cache): Never cache . or ..
+
+Thu Apr 11 17:59:18 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * console.c: Include <hurd.h>.
+
+ * Makefile (fsys-MIGSFLAGS, fs-MIGSFLAGS, io-MIGSFLAGS,
+ ifsock-MIGSFLAGS): Reference fsmutations.h in $(srcdir).
+
+ * boot-start.c (diskfs_start_bootstrap): Print helpful message
+ before doing anything else.
+
+Wed Apr 10 16:47:21 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * name-cache.c (struct lookup_cache): Add NEXT & PREV fields.
+ Rename LEN back to NAME_LEN.
+ (lru_cache, mru_cache): New variables.
+ (first_cache, last_cache): Variables removed.
+ (make_mru, make_lru, find_cache, init_lookup_cache): New functions.
+ (diskfs_enter_lookup_cache, diskfs_purge_lookup_cache,
+ diskfs_check_lookup_cache): Rewrite to use the linked list. Deal
+ with negative entries.
+
+Tue Apr 9 12:59:02 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * lookup.c (diskfs_lookup): Deal with DS or NP being 0.
+ * name-cache.c (diskfs_check_lookup_cache): Correctly handle the
+ case where the lookup returns DIR itself.
+
+ * diskfs.h (diskfs_enter_lookup_cache, diskfs_purge_lookup_cache,
+ diskfs_check_lookup_cache): Renamed from versions without `lookup_'.
+ * name-cache.c (diskfs_enter_lookup_cache, diskfs_purge_lookup_cache,
+ diskfs_check_lookup_cache): Likewise.
+ * direnter.c (diskfs_direnter): Similarly, rename use.
+ * dirrewrite.c (diskfs_dirrewrite): Likewise.
+ * dirremove.c (diskfs_dirremove): Likewise.
+ * lookup.c (diskfs_lookup): Likewise.
+
+Sun Apr 7 15:29:02 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * name-cache.c (diskfs_check_cache): Declare I.
+ (struct lookup_cache, diskfs_enter_cache): Change NAMELEN field to LEN.
+
+Wed Apr 3 16:02:45 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * node-drop.c (diskfs_drop_node): Don't call
+ _diskfs_purge_cache_deletion.
+ * name-cache.c (_diskfs_purge_cache_deletion): Delete function.
+
+ * diskfs.h (diskfs_cached_lookup): New declaration.
+ (struct node): New member `cache_id'.
+
+Tue Apr 2 12:50:31 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * name-cache.c (diskfs_enter_cache): Don't set LC->next->prev if
+ LC->next is null.
+ (diskfs_purge_cache): If freeing node at LOOKUP_CACHE_TAIL, bump
+ LOOKUP_CACHE_TAIL back itself too.
+ (_diskfs_purge_cache_deletion): Likewise.
+
+ * lookup.c (diskfs_lookup): When doing diskfs_checkdirmod check,
+ don't return success when we should return ENOENT, just because
+ checkdirmod won. Also enter successful lookups for CREATE or
+ LOOKUP in the name cache.
+
+Fri Mar 29 13:57:37 1996 Roland McGrath <roland@charlie-brown.gnu.ai.mit.edu>
+
+ * io-map-cntl.c: Initialize shared page magic number.
+
+Mon Mar 25 09:30:31 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * name-cache.c (statistics): New variable.
+ (diskfs_check_cache): Keep statistics on cache performance.
+
+Fri Mar 22 17:51:51 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * opts-runtime-parse.c (diskfs_parse_runtime_options): Supply new
+ argument to argp_parse.
+
+Fri Mar 22 15:44:10 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * lookup.c (diskfs_lookup): Dereference NP in call to
+ diskfs_checkdirmod.
+ * direnter.c (diskfs_direnter): Don't fall off end.
+ * diskfs.h (diskfs_enter_cache, diskfs_purge_cache,
+ diskfs_check_cache): Add declarations.
+ * dir-rename.c (diskfs_S_dir_rename): Use new args for
+ diskfs_dirrewrite and diskfs_dirremove.
+ * dir-renamed.c (diskfs_rename_dir): Likewise.
+ * dir-clear.c (diskfs_clear_directory): Use new diskfs_dirremove
+ args.
+ * dir-rmdir.c (diskfs_S_dir_rmdir): Likewise.
+ * dir-unlink.c (diskfs_S_dir_unlink): Likewise.
+
+ * Makefile (OTHERSRCS): Add direnter.c, dirrewrite.c, dirremove.c,
+ and lookup.c.
+
+Wed Mar 20 14:34:22 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_lookup_hard): Remove mention of ENOTDIR and
+ EACCES errors.
+ * diskfs.h (diskfs_null_dirstat): New function.
+ * dir-lookup.c (diskfs_S_dir_lookup): Don't check cache here.
+ * dir-unlink.c (diskfs_S_dir_unlink): Don't frob cache here.
+ * dir-rmdir.c (diskfs_S_dir_rmdir): Likewise.
+ * dir-clear.c (diskfs_clear_directory): Likewise.
+ * node-create.c (diskfs_create_node): Likewise.
+ * dir-renamed.c (diskfs_rename_dir): Likewise.
+ * dir-rename.c (diskfs_S_dir_rename): Likewise.
+ * dir-link.c (diskfs_S_dir_link): Likewise.
+ * direnter.c: New file.
+ * dirrewrite.c: Likewise.
+ * dirremove.c: Likewise.
+ * lookup.c: Likewise.
+ * diskfs.h (diskfs_lookup): Renamed to be diskfs_lookup_hard.
+ (diskfs_direnter): Renamed to be diskfs_direnter_hard.
+ (diskfs_dirrewrite): Renamed to be diskfs_dirrewrite_hard.
+ (diskfs_dirremove): Renamed to be diskfs_dirremove_hard.
+ (diskfs_lookup, diskfs_direnter, diskfs_dirrewrite, diskfs_dirremove):
+
+Tue Mar 19 14:55:46 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * name-cache.c: New file.
+ * Makefile (OTHERSRCS): Add name-cache.c.
+ * dir-lookup.c (diskfs_S_dir_lookup): Check cache before normal
+ diskfs_lookup call.
+ * node-drop.c (diskfs_drop_node): Call
+ _diskfs_purge_cache_deletion before releasing node structure with
+ diskfs_node_norefs.
+ * dir-clear.c (diskfs_clear_directory): Call
+ diskfs_purge_cache_node before diskfs_dirremove.
+ * dir-rename.c (diskfs_S_dir_rename): Likewise.
+ * dir-renamed.c (diskfs_rename_dir): Likewise.
+ * dir-rmdir.c (diskfs_S_dir_rmdir): Likewise.
+ * dir-unlink.c (diskfs_S_dir_unlink): Likewise.
+ * dir-init.c (diskfs_init_dir): Doc fix.
+ * dir-rename.c (diskfs_S_dir_rename): Call diskfs_purge_cache
+ before diskfs_dirrewrite for old node.
+ * dir-renamed.c (diskfs_rename_dir): Likewise.
+ * node-create.c (diskfs_create_node): Call diskfs_enter_cache if
+ diskfs_direnter is successful.
+ * dir-link.c (diskfs_S_dir_link): Likewise.
+ * dir-rename.c (diskfs_S_dir_rename): Call diskfs_enter_cache if
+ diskfs_direnter/diskfs_dirrewrite is successful.
+ * dir-renamed.c (diskfs_rename_dir): Likewise.
+
+Fri Mar 15 23:10:57 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Don't leak a send right to
+ the anonymous handle on DNP when calling fetch_root.
+
+Tue Mar 12 14:36:10 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * file-set-trans.c (diskfs_S_file_set_translator): Deallocate ref
+ on CONTROL when we are done with it.
+
+Thu Mar 7 16:45:02 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * readonly.c (diskfs_set_readonly): Don't sleep(1) after syncing.
+
+Thu Feb 29 14:29:20 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * Makefile (OTHERSRCS): Change `opts-runtime-def.c' to
+ `opts-runtime-parse.c'. Add `opts-runtime-unparse.c'.
+
+Wed Feb 21 06:10:05 1996 Roland McGrath <roland@charlie-brown.gnu.ai.mit.edu>
+
+ * file-set-trans.c (diskfs_S_file_set_translator): Add EROFS check.
+
+Sun Feb 18 00:08:27 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * init-init.c (diskfs_init_diskfs): Use maptime_map.
+ * node-times.c (diskfs_set_node_times): Use maptime_read.
+
+Fri Feb 16 13:48:08 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * opts-runtime-def.c (diskfs_parse_runtime_options): STANDARD_ARGP
+ is const.
+
+Thu Feb 15 16:59:04 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_nput): It's not valid to touch *NP (by
+ `mutex_unlock (&np->lock);') after we have called
+ diskfs_drop_node. So don't do it in that case.
+
+Wed Feb 7 22:42:22 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_nput): Before bumping NP->references (which
+ precedes diskfs_try_dropping_softrefs), *lock*
+ diskfs_node_refcnt_lock, not mutant unlock.
+ (diskfs_nrele): Likewise.
+
+Wed Feb 7 16:22:31 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_parse_runtime_options): Make STANDARD_ARGP const.
+ (diskfs_startup_argp, diskfs_device_startup_argp): Make const.
+ * opts-common.c (diskfs_common_options): Make const.
+ * opts-std-startup.c (startup_options, dev_startup_options,
+ dev_start_argp_parents, dev_startup_argp, startup_common_argp,
+ startup_argp_parents, startup_argp, diskfs_startup_argp): Make const.
+ * opts-set.c (std_runtime_options): Make const.
+ (diskfs_set_options): Make argp structures const.
+
+Wed Feb 7 13:39:09 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Revert last change.
+
+Tue Feb 6 15:56:04 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Make the new peropen we'll
+ pass as dotdot to the fetch_root with the same flags as DIRCRED->po.
+
+Wed Jan 31 00:27:10 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * node-rdwr.c (diskfs_node_rdwr): Handle null AMTREAD.
+
+Tue Jan 30 21:20:13 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * fsys-options.c (diskfs_S_fsys_set_options): Use
+ rwlock_writer_lock instead of rwlock_reader_lock in DO_CHILDREN case.
+
+Tue Jan 30 15:03:35 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * peropen-rele.c (diskfs_release_peropen): Free dotdotport when
+ deallocating peropen.
+
+Wed Jan 24 18:14:28 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Use diskfs_create_protid instead
+ of diskfs_make_protid, and deal with an error return.
+ * dir-mkfile.c (diskfs_S_dir_mkfile): Likewise.
+ * file-exec.c (diskfs_S_file_exec): Likewise.
+ * file-inv-trans.c (diskfs_S_file_invoke_translator): Likewise.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Likewise.
+ * io-duplicate.c (diskfs_S_io_duplicate): Likewise.
+ * io-restrict-auth.c (diskfs_S_io_restrict_auth): Likewise.
+ * trans-callback.c (_diskfs_translator_callback2_fn): Likewise.
+ * boot-start.c (diskfs_start_bootstrap, diskfs_S_exec_startup_get_info,
+ diskfs_execboot_fsys_startup, diskfs_S_fsys_init): Likewise.
+ * protid-make.c (diskfs_start_protid): Return an error now, and use
+ ports_create_port instead of ports_allocate_port.
+ (diskfs_create_protid): New function.
+ (diskfs_make_protid): Call diskfs_create_protid.
+ * diskfs.h (diskfs_start_protid): Update declaration.
+ (diskfs_create_protid): New declaration.
+ * io-reauthenticate.c (diskfs_S_io_reauthenticate): Use new version of
+ diskfs_start_protid.
+ * file-getcontrol.c (diskfs_S_file_getcontrol): Use ports_create_port
+ instead of ports_allocate_port.
+ * boot-start.c (start_execserver, diskfs_start_bootstrap): Likewise.
+ * init-startup.c (diskfs_startup_diskfs): Likewise.
+ * sync-interval.c (diskfs_set_sync_interval): Likewise.
+ (periodic_sync): Pass in the MSG_ID arg to ports_begin_rpc, and
+ deal with any error returned.
+
+ * readonly.c (diskfs_set_readonly): Deal with ports_inhibit_class_rpcs
+ returning an error.
+ * remount.c (diskfs_remount): Likewise.
+ * shutdown.c (diskfs_shutdown): Likewise.
+ * sync-interval.c (diskfs_set_sync_interval): Likewise.
+
+ * dir-readdir.c: Include <fcntl.h>.
+
+Tue Jan 23 16:28:47 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * opts-std-startup.c (startup_options): Put boot options in a
+ separate group with a header.
+
+Thu Jan 18 14:05:51 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * dir-readdir.c (diskfs_S_dir_readdir): Require read permission
+ before succeeding.
+
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Deallocate ref to dotdot
+ after diskfs_make_peropen, because the latter does not eat a
+ reference.
+
+ * fsys-getroot.c (diskfs_S_fsys_getroot): In symlink case, use
+ MOVE_SEND to return the dotdot port to the user.
+
+Thu Jan 11 22:09:05 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
+
+ * diskfs-pager.h (struct disk_image_user): New type.
+ (diskfs_catch_exception, diskfs_end_catch_exception): Use it to
+ maintain a linked list of catchers instead of just one.
+
+Sat Jan 6 11:49:02 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * Makefile (installhdrs): Add diskfs-pager.h.
+ (OTHERSRCS): Add disk-pager.c.
+
+Fri Jan 5 17:06:42 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * io-write.c: Return errors regardless of *AMT--writes are all or
+ nothing.
+ * io-read.c: Return errors regardless of *DATALEN--reads are all or
+ nothing.
+
+Thu Jan 4 16:11:35 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * disk-pager.c, diskfs-pager.h: New files.
+ * exc.c: File removed.
+ * Makefile (OTHERSRCS): Remove exc.c.
+ * diskfs.h (diskfs_catch_exception, diskfs_end_catch_exception):
+ Macros removed.
+ (diskfs_register_memory_fault_area,
+ diskfs_unregister_memory_fault_area): Decls removed.
+
+ * diskfs.h: Use size_t instead of int for amounts in
+ diskfs_node_rdwr prototype.
+ * node-rdwr.c (diskfs_node_rdwr): Pass AMTREAD read/write to
+ _diskfs_rdwr_internal, instead of assuming it wrote the whole amount.
+ Update the node if anything was transferred, regardless of ERR.
+ * rdwr-internal.c (_diskfs_rdwr_internal): Rewritten using
+ pager_memcpy.
+ Fix types of args: OFFSET to off_t, make AMT read/write size_t *.
+ * priv.h: Fix args in _diskfs_rdwr_internal prototype.
+ * io-write.c: Pass AMT read/write to _diskfs_rdwr_internal, and
+ return success if any bytes were written.
+ * io-read.c: Likewise.
+
+Mon Jan 1 15:45:33 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * file-exec.c (diskfs_S_file_exec): Use fshelp_exec_reauth().
+ (setid, scan_ids): Functions deleted.
+
+Thu Dec 28 14:21:42 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * file-exec.c (diskfs_S_file_exec): Always reauth the proc port,
+ as exec does not do it, even in the secure case. Set the proc's
+ owner too.
+
+ * file-exec.c (setid): Don't touch the return params unless we succeed.
+ Add SETID parameter, and just copy old into new unless it's set.
+ Handle the NOLDGENIDS == 0 case correctly.
+ (diskfs_S_file_exec): Use the new setid() properly. Make sure that
+ {GEN,AUX}{UIDS,GIDS} are always in a state where they can be freed.
+
+Thu Dec 28 00:24:29 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * priv.h (end_using_protid_port): Don't calls ports_port_deref if
+ CRED is null.
+
+Wed Dec 27 17:32:21 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * file-exec.c (setid): New function.
+ (scan_ids): Moved out of diskfs_S_file_exec.
+ (diskfs_S_file_exec): Move duplicated code into setid(). Make the
+ bogus auth port case work correctly. Deleted old ifdefed-out code.
+ Enable setuid code.
+
+ * exc.c (diskfs_register_memory_fault_area): Register both
+ preempter1 and preempter2 in REC instead of preempter1 twice.
+
+Sat Dec 23 14:49:22 1995 Michael I. Bushnell p/BSG <mib@gnu.ai.mit.edu>
+
+ * exc.c: Entire file rewritten to use libc signal preemption
+ facility.
+
+Wed Dec 20 14:49:29 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot-start.c (diskfs_S_fsys_init): Call proc_mark_exec on
+ EXECPROCESS.
+
+Tue Dec 19 13:19:19 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * file-exec.c (diskfs_S_file_exec): Better attempt at
+ setuid/setgid execution; still not entirely right, but mostly so.
+ Will move this code to libfshelp before turning it on.
+
+Thu Dec 14 15:51:19 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_checkdirmod): Correctly return error code for
+ failure, not 1.
+
+Mon Dec 4 17:07:20 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * dir-unlink.c (diskfs_S_dir_unlink): Don't call fsys_goaway until
+ we've released our lock.
+
+Mon Dec 4 16:57:28 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * dir-unlink.c (diskfs_S_dir_unlink): Delete vestigial fetch_control.
+
+Tue Nov 21 13:54:14 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * rdwr-internal.c (_diskfs_rdwr_internal): Declare PROT volatile.
+
+ * init-first.c (master_thread_function): Declare to be `static
+ any_t'.
+
+ * fsys-options.c: Include <string.h>.
+
+ * diskfs.h (diskfs_get_options): Bother providing declaration.
+
+ * file-get-fs-opts.c: Include <string.h>.
+ (diskfs_S_file_get_fs_options): Dereference DATA_LEN in call to
+ vm_allocate.
+
+Sat Nov 18 09:01:28 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot-start.c (diskfs_S_exec_startup_get_info): Renamed from
+ diskfs_S_exec_startup, slightly different protocol. Unused exec
+ server stubs removed.
+ * Makefile (MIGSTUBS): Replaced execServer.o with exec_startupServer.o.
+
+Mon Nov 13 17:13:40 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * demuxer.c (diskfs_demuxer):
+ diskfs_exec_server --> diskfs_exec_startup_server.
+
+Mon Nov 13 16:28:27 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * file-lock-stat.c (diskfs_S_file_lock_stat): Lock around reads to
+ make sure they are mutually consistent.
+
+ * io-readable.c (diskfs_S_io_readable): Set *AMOUNT to zero if
+ filepointer is past the end of the file.
+
+Thu Nov 9 12:33:53 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * dir-link.c (diskfs_S_dir_link): Now that args are swapped,
+ deallocate port ref on FILECRED instead of DIRCRED.
+
+Sun Nov 5 10:49:26 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * Makefile (OTHERSRCS): Add opts-get.c.
+ (FSSRCS): Add file-get-fs-opts.c.
+ * file-get-fs-opts.c (diskfs_S_file_get_fs_options): New function.
+ * fsys-options.c (diskfs_S_fsys_get_options): New function.
+ * opts-get.c (diskfs_get_options): New function.
+
+ * sync-interval.c (diskfs_sync_interval): New variable.
+ (diskfs_set_sync_interval): Set DISKFS_SYNC_INTERVAL.
+
+Sat Nov 4 23:17:50 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * file-get-trans.c (diskfs_S_file_get_translator): Initialize ERROR.
+
+ * trans-callback.c (_diskfs_translator_callback2_fn):
+ UNDERLYING_TYPE should be a pointer. As should the UIDS & GIDS
+ args to diskfs_make_protid.
+
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Pass both callback args
+ to fshelp_fetch_root.
+
+ * filedev.c (diskfs_get_file_device): Give FLAGS argument to
+ file_get_storage_info.
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Fix various typos.
+ (short_circuited_callback1): Dereference ARGZ & ARGZ_LEN.
+ Include <hurd/paths.h>
+
+Wed Nov 1 15:56:45 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Add new callback arg to
+ fshelp_fetch_root call. Change short_circuited_callback1 to
+ reflect the split into two callbacks (we use the global diskfs
+ callback for the other_).
+ * trans-callback.c (_diskfs_translator_callback1_fn,
+ _diskfs_translator_callback2_fn): New functions, replacing the
+ single original.
+ (_diskfs_translator_callback1, _diskfs_translator_callback2):
+ New variables, replacing the single original.
+ * priv.h (_diskfs_translator_callback1, _diskfs_translator_callback2):
+ Declare.
+
+ * boot-start.c (diskfs_execboot_fsys_startup): Add FLAGS arg; use.
+ * fsys-startup.c (diskfs_S_fsys_startup): Ditto.
+ * init-startup.c (diskfs_startup_diskfs): Ditto.
+ * diskfs.h (diskfs_startup_diskfs, diskfs_execboot_fsys_startup):
+ Add FLAGS arg.
+
+Mon Oct 30 13:20:12 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Move code for starting
+ short-circuited translators here, from _diskfs_translator_callback_fn.
+ Inline code from node_is_translated.
+ (node_is_translated): Function removed.
+ (major, minor): New macros -- temporarily here until libc exports them.
+
+Thu Oct 26 18:41:23 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * trans-callback.c (_diskfs_translator_callback_fn): Deal with
+ short-circuited translators.
+ * dir-lookup.c (node_is_translated): New function.
+ (diskfs_S_dir_lookup): Use node_is_translated() instead of
+ np->istranslated to see whether NP has a passive translator.
+
+ * file-set-trans.c (diskfs_S_file_set_translator): Add missing else.
+ Use makedev macro instead of doing it by hand.
+ (makedev): New macro -- temporarily here until libc exports one.
+
+Thu Oct 19 12:43:47 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * fsys-options.c (diskfs_S_fsys_set_options): Only hold
+ DISKFS_FSYS_LOCK for writing while setting our own options; we
+ hold it for reading while setting our children's.
+
+ * rdwr-internal.c (_diskfs_rdwr_internal): Get rid of CRED argument.
+ * priv.h (_diskfs_rdwr_internal): Ditto.
+ * node-rdwr.c (diskfs_node_rdwr): Ditto.
+ * io-write.c (diskfs_S_io_write): Ditto.
+ * io-read.c (diskfs_S_io_read): Ditto.
+
+Wed Oct 18 15:52:53 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_get_filemap): Add prot parameter.
+ (diskfs_max_user_pager_prot): New declaration.
+ * rdwr-internal.c (_diskfs_rdwr_internal): Add argument CRED, and
+ use it to decide how to setup the mapped i/o.
+ * io-write.c (diskfs_S_io_write): Pass CRED to _diskfs_rdwr_internal.
+ * io-read.c (diskfs_S_io_read): Ditto.
+ * node-rdwr.c (diskfs_node_rdwr): Ditto.
+ * io-map.c (diskfs_S_io_map): Pass the appropiate vm protection to
+ diskfs_get_filemap. If this node isn't O_RDWR, only return the
+ appropiate memobj.
+ Include <fcntl.h>.
+ * priv.h (_diskfs_rdwr_internal): Add cred parameter.
+
+ * boot-start.c (diskfs_execboot_fsys_startup): Open exec's
+ realnode read-only for now, since we know it doesn't matter and
+ having gratuitously writable nodes around prevents us from
+ starting up or going read-only.
+ (diskfs_S_fsys_init): Don't make the cwdir/crdir right with O_WRITE.
+ * trans-callback.c (_diskfs_translator_callback_fn): Ditto for
+ other translators. The fsys_startup interface should change very
+ soon and make this irrelevant.
+
+ * readonly.c (diskfs_set_readonly): Return EBUSY if necessary.
+ Add hack to try and work around pagers-can't-wait bug.
+
+ * opts-common.c (diskfs_common_options): New variable.
+ * priv.h (diskfs_common_options): New declaration.
+ * opts-std-startup.c (startup_options): Remove options common to
+ both runtime and startup.
+ (startup_common_argp, startup_argp_parents): New variables.
+ (startup_argp): Include parents.
+ * opts-set.c (std_runtime_options): Remove options common to
+ both runtime and startup.
+ (diskfs_set_options): Use the common options.
+ * Makefile (OTHERSRCS): Add opts-common.c.
+
+ * diskfs.h (diskfs_fsys_lock): Change to a struct rwlock.
+ Include <rwlock.h>
+ * shutdown.c (diskfs_fsys_lock): Now a rwlock.
+ (diskfs_shutdown): Lock DISKFS_FSYS_LOCK for writing.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Hold DISKFS_FSYS_LOCK
+ for reading.
+ * sync-interval.c (periodic_sync): Hold DISKFS_FSYS_LOCK for
+ reading while syncing.
+ * fsys-syncfs.c (diskfs_S_fsys_syncfs): Ditto.
+ * fsys-options.c (diskfs_S_fsys_set_options): Hold DISKS_FSYS_LOCK
+ for writing.
+ Dereference PT even when a child filesystem returns an error.
+ * opts-set.c (diskfs_set_options): Don't hold DISKS_FSYS_LOCK (our
+ caller should).
+
+ * machdev.c (diskfs_get_mach_device): SIZE is in blocks.
+
+Wed Oct 18 14:00:58 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
+
+ * file-exec.c (diskfs_S_file_exec): Return EACCES for attempts to
+ execute a directory. Dike out totally bogus set[ug]id code.
+ Bother to lock NP around critical section.
+
+Tue Oct 17 14:32:41 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * init-startup.c (diskfs_startup_diskfs): Call diskfs_readonly_changed
+ if we're starting up writable.
+ * diskfs.h (diskfs_readonly_changed, diskfs_reload_global_state,
+ diskfs_node_reload, diskfs_set_readonly, diskfs_remount): New
+ declarations.
+ (diskfs_main_request_loop): Declaration removed.
+ * Makefile (OTHERSRCS): Add readonly.c, remount.c.
+ * readonly.c (diskfs_set_readonly): New function.
+ * remount.c (diskfs_remount): New function.
+
+ * opts-set.c (diskfs_set_options): Rework readonly transition &
+ remounting. Hold diskfs_fsys_lock.
+
+ * diskfs.h (diskfs_fsys_lock): Renamed from diskfs_shutdown_lock.
+ * shutdown.c (diskfs_shutdown): diskfs_shutdown_lock -->
+ diskfs_fsys_lock.
+
+Fri Oct 13 14:51:42 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_start_bootstrap): Get rid of ARGV argument.
+ (diskfs_argv): New declaration.
+ * boot-start.c (saved_argv): Variable removed.
+ (diskfs_argv): New variable. Should get set by default arg parser.
+ (diskfs_start_bootstrap): Get rid of ARGV argument.
+ (diskfs_S_fsys_init): Use DISKFS_ARGV instead of SAVED_ARGV.
+ * opts-std-startup.c (parse_startup_opt): Set DISKFS_ARGV.
+ * init-startup.c (diskfs_startup_diskfs): Call diskfs_start_bootstrap
+ if we're the bootstrap file system.
+
+ * dev-globals.c (diskfs_device, diskfs_device_name,
+ diskfs_device_start, diskfs_device_size, diskfs_device_block_size,
+ diskfs_log2_device_block_size, diskfs_log2_device_blocks_per_page):
+ New variables.
+ * dev-io.c (diskfs_device_write_sync, diskfs_device_write_sync):
+ New functions.
+ * dev-open.c (diskfs_device_open): New function, new file.
+ * diskfs.h (diskfs_device, diskfs_device_name,
+ diskfs_device_start, diskfs_device_size, diskfs_device_block_size,
+ diskfs_log2_device_block_size, diskfs_log2_device_blocks_per_page,
+ diskfs_device_write_sync, diskfs_device_write_sync,
+ diskfs_device_open, diskfs_console_stdio): New declarations.
+ * console.c (diskfs_console_stdio): New function.
+ * Makefile (OTHERSRCS): Add dev-open.c, dev-io.c, dev-globals.c,
+ console.c.
+ * opts-std-startup.c (diskfs_use_mach_device, diskfs_device_arg,
+ dev_startup_options, dev_startup_argp_parents, dev_startup_argp,
+ diskfs_device_startup_argp): New variables.
+ (parse_dev_startup_opt): New function.
+
+Thu Oct 12 16:11:22 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * boot-start.c (diskfs_execboot_fsys_startup): Fix args to dir_lookup.
+ Declare PATHBUF and RETRY.
+
+ * boot-start.c (diskfs_S_fsys_init): Put the contents of
+ diskfs_init_completed in here, freeing that routine for user-use.
+
+ * init-completed.c (diskfs_init_completed): Now empty.
+
+ * opts-set.c (std_runtime_options): Renamed from long_options,
+ convert to argp format.
+ (SHORT_OPTIONS): Removed.
+ (diskfs_set_options): Converted to use argp.
+ * diskfs.h (diskfs_parse_runtime_options,
+ diskfs_standard_startup_argp): Use argp, not options.
+ Include <argp.h> instead of <options.h>.
+ * opts-runtime-def.c (diskfs_parse_runtime_options): Use argp
+ instead of options.
+ * opts-std-startup.c (std_startup_options): Renamed from
+ std_long_options; converted to argp format.
+ (std_startup_argp): Renamed from std_startp_argp, converted argp fmt.
+ (diskfs_standard_startup_argp): Renamed from
+ diskfs_standard_startup_options.
+
+Thu Oct 12 03:25:09 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot-start.c (diskfs_execboot_fsys_startup): Use dir_lookup
+ instead of hurd_file_name_lookup to open /servers/exec.
+
+Mon Oct 9 03:42:49 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot-start.c (diskfs_execboot_fsys_startup): Pass back a port to
+ /servers/exec in *REAL.
+
+Sat Oct 7 20:51:06 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * init-completed.c (diskfs_init_completed): New function.
+ * diskfs.h (diskfs_init_completed): must --> may.
+ Add necessary includes.
+
+ * Makefile (OTHERSRCS): Add init-completed.c.
+
+Sat Oct 7 05:07:42 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * Makefile (libdiskfs.so): Depend on libpager, libioserver,
+ libfshelp, libthreads.
+
+Fri Oct 6 17:26:51 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_get_file_device, diskfs_get_mach_device): New funcs.
+ (diskfs_boot_flags): New variable.
+ (diskfs_bootflags, diskfs_bootflagarg): Variables deleted.
+
+ * boot-start.c (diskfs_S_fsys_getpriv): Add the port type parameters.
+
+ * Makefile (MIGSFLAGS): Variable deleted.
+ (fs-MIGSFLAGS, io-MIGSFLAGS, ifsock-MIGSFLAGS): New variables.
+ (fsys-MIGSFLAGS): Also import fsmutations.h.
+
+ * dir-link.c (diskfs_S_dir_link): Swap first two arguments.
+
+ * filedev.c (diskfs_get_file_device): Use new block_size return
+ value from file_get_storage_info.
+
+Thu Oct 5 15:10:34 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * Makefile (OTHERSRCS): Remove boot-parse.c; add filedev.c & machdev.c.
+ * diskfs.h (diskfs_host_priv, diskfs_master_device): Variables deleted.
+ (diskfs_parse_bootargs): Function deleted.
+ (diskfs_init_diskfs): Now returns error_t.
+ * init-init.c (diskfs_init_diskfs): Always use get_privileged_ports.
+ Now return error_t.
+ * machdev.c (diskfs_get_mach_device): Use get_privileged_ports
+ instead of diskfs_master_device.
+ * boot-start.c (diskfs_S_fsys_getpriv): Use get_privileged_ports
+ to get the privileged ports.
+ (diskfs_start_bootstrap): Use diskfs_boot_flags instead of
+ diskfs_bootflagarg.
+ (diskfs_start_bootstrap, start_execserver): Look for flags
+ directly in diskfs_boot_flags, instead of using the old
+ diskfs_bootflags.
+ * boot-start.c (diskfs_S_exec_startup): Use get_console to get the
+ console device.
+ (get_console): New function.
+ * opts-std-startup.c (OPT_BOOTFLAGS, OPT_EXEC_SERVER_TASK,
+ OPT_HOST_PRIV_PORT, OPT_DEVICE_MASTER_PORT): New defines.
+ (std_long_opts, parse_std_startup_opt): Add the
+ --device-master-port, --host-priv-port, --exec-server-task, and
+ --bootflags options.
+
+Thu Oct 5 00:46:09 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * sync-interval.c (periodic_sync_lock): Variable removed.
+ (diskfs_set_sync_interval): Use ports_inhibit_port_rpcs on `pi'
+ instead of the spin lock.
+ (periodic_sync): Don't use the lock.
+ Put ports_begin_rpc before check of periodic_sync_thread.
+
+Wed Sep 27 20:11:09 1995 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * filedev.c (diskfs_get_file_device): New file, new function.
+ * machdev.c (diskfs_get_mach_device): New file, new function.
+
+Mon Sep 18 14:21:29 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * io-pathconf.c (diskfs_S_io_pathconf): Renamed from
+ file_pathconf.c:diskfs_S_file_pathconf.
+ * Makefile (FSSRCS): Deleted file-pathconf.c.
+ (IOSRCS): Added io-pathconf.c.
+
+Sun Sep 17 18:04:10 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot-start.c (diskfs_S_exec_startup): Don't pass an argument
+ string. Set *FLAGS to EXEC_STACK_ARGS.
+
+ * file-set-size.c: Renamed from file-trunate.c.
+ (diskfs_S_file_set_size): Renamed from diskfs_s_file_truncate.
+ If SIZE exceeds the file size, extend the file.
+ * Makefile (FSSRCS): Rename file-truncate.c to file-set-size.c.
+
+Sat Sep 16 13:10:21 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * ourfs_notify.defs: New file.
+ * Makefile (DIST_FILES): Added ourfs_notify.defs.
+ (ourfs_notify_U.h ourfs_notifyUser.c, ourfs_notify.defs): Targets
+ removed.
+
+Wed Sep 13 12:36:26 1995 Michael I. Bushnell, p/BSG <mib@duality.gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_lookup): Doc fix.
+ * dir-clear.c (diskfs_clear_directory): Set the fourth arg in
+ REMOVE lookup calls in accord with change in rules for the lookup
+ call.
+
+Wed Sep 6 11:30:24 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * demuxer.c (diskfs_demuxer): Use ports_notify_server and
+ ports_interrupt_server instead of our own versions.
+ * Makefile (SRCS): Removed $(NOTIFYSRCS) and $(INTSRCS).
+ (NOTIFYSRCS, INTSRCS, notify-MIGSFLAGS): Removed.
+ (MIGSTUBS): Removed notifyServer.o and interruptServer.o.
+ * interrupt.c: File deleted.
+
+Tue Aug 29 14:22:58 1995 Michael I. Bushnell, p/BSG <mib@duality.gnu.ai.mit.edu>
+
+ * io-select.c (diskfs_S_io_select): Don't check open modes or
+ return EBADF.
+
+Fri Aug 25 15:02:19 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * Makefile (FSYSSRCS): Add fsys-forward.c.
+
+Fri Aug 25 09:44:43 1995 Michael I. Bushnell, p/BSG <mib@mole.gnu.ai.mit.edu>
+
+ * file-truncate.c (diskfs_S_file_truncate): Bother to check the
+ return value of diskfs_truncate.
+
+Wed Aug 23 14:39:07 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * Makefile (REMHDRS): Removed.
+ Rules dealing with ../lib removed.
+
+Sat Jul 29 10:34:38 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * ifsock.c (diskfs_S_ifsock_getsockaddr): Don't loop infinitely if
+ we fail to get a reasonable PF_LOCAL server.
+
+Fri Jul 28 14:59:45 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * ifsock.c (diskfs_S_ifsock_getsockaddr): Try to restart the
+ PF_LOCAL server if it dies.
+
+ * node-drop.c (diskfs_drop_node): Don't actually drop the node if
+ it is a socket naming point, unless it also has no links.
+
+Sat Jul 22 13:54:48 1995 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * file-getcontrol.c (diskfs_S_file_getcontrol): Fix typo.
+ * boot-start.c (start_execserver): Likewise.
+
+Fri Jul 21 12:37:36 1995 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * trans-callback.c (_diskfs_translator_callback_fn): Use correct
+ sense of diskfs_readonly flag.
+
+ * boot-start.c (diskfs_start_bootstrap): Free initial reference
+ created by diskfs_make_protid.
+ (diskfs_S_exec_startup): Likewise.
+ (diskfs_S_fsys_init): Likewise.
+ * dir-lookup.c (diskfs_S_dir_lookup): Likewise. (Two places.)
+ * dir-mkfile.c (diskfs_S_dir_mkfile): Likewise.
+ * file-exec.c (diskfs_S_file_exec): Likewise.
+ * file-inv-trans.c (diskfs_S_file_invoke_translator): Likewise.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Likewise.
+ * io-duplicate.c (diskfs_S_io_duplicate): Likewise.
+ * io-restrict-auth.c (diskfs_S_io_restrict_auth): Likewise.
+ * trans-callback.c (_diskfs_translator_callback_fn): Likewise.
+
+ * io-reauthenticate.c (diskfs_S_io_reauthenticate): Free initial
+ reference created by diskfs_start_protid.
+
+ * boot-start.c (diskfs_start_bootstrap): Free initial reference
+ created by ports_allocate_port.
+ (start_execserver): Likewise.
+ * file-getcontrol.c (diskfs_S_file_getcontrol): Likewise.
+ * init-startup.c (diskfs_startup_diskfs): Likewise.
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Examine the active
+ translator on NP, not on diskfs_root_node, to see if translator
+ usage is necessary.
+
+ * file-set-trans.c (diskfs_S_file_set_translator): Only validate
+ PASSIVELEN if PASSIVE is set.
+
+Tue Jul 18 16:12:20 1995 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * init-first.c (thread_timeout, server_timeout): New vars.
+ (THREAD_TIMEOUT, SERVER_TIMEOUT): Delete macros.
+ (master_thread_function): Use vars instead of macros.
+
+ * file-get-trans.c (diskfs_S_file_get_translator): Conform to new
+ memory semantic of diskfs_get_translator.
+
+Wed Jul 12 16:39:24 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
+
+ * shutdown.c (diskfs_shutdown): Call ports_resume_class_rpcs for
+ diskfs_protid_class before return EBUSY.
+
+Thu Jul 6 15:34:59 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
+
+ * Makefile (ourfs_notify_U.h ourfs_notifyUser.c): Use
+ ourfs_notify.defs instead of directly out of the include
+ directory.
+ (ourfs_notify.defs): New target.
+
+ * Makefile: Removed dependencies that are now automatically
+ generated.
+
+Mon Jun 26 15:38:07 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
+
+ * fsys-goaway.c (diskfs_S_fsys_goaway): Include "fsys_S.h" and
+ "fsys_reply_U.h". New parms REPLY and REPLY_TYPE. Send
+ fsys_goaway reply message before exit.
+ * Makefile (fsys-MIGSFLAGS): New variable.
+ * fsys-startup.c (diskfs_S_fsys_startup): New parms REPLY and
+ REPLYTYPE.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Likewise.
+ * fsys-options.c (diskfs_S_fsys_set_options): Likewise.
+ * boot-start.c (diskfs_S_fsys_getpriv): Likewise.
+ * fsys-syncfs.c (diskfs_S_fsys_syncfs): Likewise.
+ * fsys-getfile.c (diskfs_S_fsys_getfile): Include "fsys_S.h". New
+ parms REPLY and REPLYTYPE.
+
+ * sync-interval.c (periodic_sync_thread, periodic_sync_lock):
+ Declare static.
+ (control): Delete var.
+ (pi): New var.
+ (diskfs_set_sync_interval): Set PI instead of CONTROL.
+ (periodic_sync): Do sync by hand; use ports routines around it
+ properly.
+
+ * shutdown.c (diskfs_shutdown): Fix parentheses on bitwise tests.
+
+ * fsys-goaway.c (diskfs_S_fsys_goaway): If diskfs_shutdown returns
+ zero, then exit here.
+ * shutdown.c (diskfs_shutdown): Don't actually exit; return zero
+ instead.
+ * init-first.c (master_thread_function): Exit when shutdown
+ returns zero.
+
+ * file-set-trans.c (diskfs_S_file_set_translator): Ignore harmless
+ errors from fsys_goaway.
+ * shutdown.c (diskfs_shutdown): Ignore harmless errors from
+ fsys_goaway.
+ * fsys-options.c (diskfs_S_fsys_set_options/helper): Ignore
+ harmless errors from fsys_set_options.
+
+ * file-set-trans.c (diskfs_S_file_set_translator): Fix parentheses
+ on first active EXCL check.
+
+Fri Jun 23 15:43:55 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
+
+ * fsys-options.c (diskfs_S_fsys_set_options) [helper]: Unlock NP
+ around fsys call.
+ * file-syncfs.c (diskfs_S_file_syncfs) [helper]: Likewise.
+ * fsys-syncfs.c (diskfs_S_fsys_syncfs) [helper]: Likewise.
+ * shutdown.c (diskfs_shutdown) [helper]: Likewise.
+
+Thu Jun 22 14:48:46 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
+
+ * priv.h (_diskfs_translator_callback): Must be extern to force
+ inclusion of trans-callback.c.
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Correctly parethenize
+ O_NOTRANS flags test.
+
+Tue Jun 20 11:52:24 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
+
+ * node-make.c (diskfs_make_node): Fix function name
+ fshelp_init_transbox -> fshelp_transbox_init.
+
+ * file-syncfs.c: Include <hurd/fsys.h>.
+ * fsys-syncfs.c: Likewise.
+
+ * file-syncfs.c (diskfs_S_file_syncfs) [helper]: First arg to
+ fshelp_fetch_control should be &NP->transbox, not NP.
+ * fsys-options.c (diskfs_S_fsys_set_options) [helper]: Likewise.
+ * fsys-syncfs.c (diskfs_S_fsys_syncfs) [helper]: Likewise.
+ * shutdown.c (diskfs_shutdown) [helper]: Likewise.
+
+ * file-set-trans.c (diskfs_S_file_set_translator): Remove
+ assignment from if test.
+ * node-rdwr.c (diskfs_node_rdwr): Likewise.
+
+Mon Jun 19 16:32:12 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_node_iterate): New (user-provided) function.
+ * fsys-syncfs.c (diskfs_S_fsys_syncfs): Use diskfs_node_iterate
+ instead of diskfs_sync_translators.
+ * file-syncfs.c (diskfs_S_file_syncfs): Likewise.
+ * shutdown.c (diskfs_shutdown): Likewise.
+ * fsys-options.c (diskfs_S_fsys_set_options): Likewise.
+
+ * dir-rmdir.c (diskfs_S_dir_rmdir): Don't attempt anything for
+ translated directories here; just return EBUSY.
+ * dir-unlink.c (diskfs_S_dir_unlink): Don't do massively
+ complicated fsys_goaway. Instead, call it at the end (but only if
+ this was the last link) and ignore errors.
+
+ * fsys-startup.c (diskfs_S_fsys_startup): Strip out support for
+ translators; fshelp now does that itself.
+
+ * file-set-trans.c: Include <hurd/fsys.h>.
+
+ * file-set-trans.c (diskfs_S_file_set_translator): Use new
+ translator interface throughout.
+ * dir-lookup.c (diskfs_S_dir_lookup): Use new translator startup
+ interface.
+
+Fri Jun 16 17:42:44 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
+
+ * file-get-transcntl.c (diskfs_S_file_get_translator_cntl): Use
+ fshelp_fetch_control instead of old interface.
+
+Wed Jun 14 15:52:30 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
+
+ * node-drop.c (diskfs_drop_node): Call fshelp_drop_transbox
+ instead of fshelp_kill_translator; do it *after* the truncate.
+ * node-make.c (diskfs_make_node): Initialize TRANSBOX member using
+ new function. Drop initialization of TRANSLATOR member.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Use new translator
+ startup interface.
+ * Makefile (OTHERSRCS): Removed trans-start.c, trans-destroy.c,
+ and trans-sync.c. Added trans-callback.c.
+ * trans-start.c, trans-destroy,c, trans-sync.c: Deleted files.
+ * trans-callback.c: New file.
+ * priv.h (_diskfs_translator_callback): New declaration.
+ * diskfs.h (diskfs_start_translator, diskfs_destroy_translator,
+ diskfs_sync_translators):
+ Delete declarations.
+ (struct node): Replace TRANSLATOR member with new TRANSBOX member.
+ (diskfs_get_translator): Specify new calling interface.
+
+Fri Jun 9 15:48:30 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
+
+ * rdwr-internal.c (_diskfs_rdwr_internal): Cast __VM_PAGE_SIZE in
+ comparisen.
+ * io-write.c (diskfs_S_io_write): Cast DATALEN to off_t in
+ comparisons.
+ * io-read.c (diskfs_S_io_read): Cast MAKREAD to off_t in
+ comparison.
+ * io-prenotify.c (diskfs_S_io_prenotify): Cast END to off_t in
+ comparison.
+ * file-get-trans.c (diskfs_S_file_get_translator): Declare
+ variable `buflen' and various variables `len' to be unsigned.
+ * file-exec.c (diskfs_S_file_exec): Declare both variables `i' to
+ be unsigned int.
+
+ * io-async-icky.c (diskfs_S_io_get_icky_async_id): Validate CRED.
+
+ * interrupt.c (diskfs_S_interrupt_operation): Bother to implement.
+
+ * init-init.c (diskfs_init_diskfs): Pass null second argument in
+ calls to ports_create_class.
+
+ * fsys-options.c (diskfs_S_fsys_set_options): Bother validating
+ FSYS and implementing DO_CHILDREN.
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Initialize GIDS, NUIDS, and
+ NGIDS to avoid warning.
+
+ * boot-start.c: Provide unused attributes where appropriate.
+ * file-chg.c (diskfs_S_file_notice_changes): Mark parameters as
+ unused.
+ * file-getfh.c (diskfs_S_file_getfh): Likewise.
+ * file-inv-trans.c (diskfs_S_file_invoke_translator): Likewise.
+ * fsys-getfile.c (diskfs_S_fsys_getfile): Likewise.
+ * init-init.c (_diskfs_control_clean): Likewise.
+ * io-async.c (diskfs_S_io_async): Likewise.
+ * notify-stubs.c: Likewise.
+ * file-pathconf.c (diskfs_S_file_pathconf): Declare NAME to be
+ unused.
+ * io-select.c (diskfs_S_io_select): Declare ATTRIBUTE unused.
+ * io-stubs.c (diskfs_S_io_postnotify): Declare parms START and END
+ unused.
+ * io-prenotify.c (diskfs_S_io_prenotify): Declare parm START
+ unused.
+
+ * diskfs.h (diskfs_transboot_class): Delete var.
+ * init-init.c (diskfs_transboot_class): Delete var.
+ (diskfs_init_diskfs): Don't initialize it.
+
+ * dir-rename.c (diskfs_S_dir_rename): After renaming directory,
+ synchronize relevant state if DISKFS_SYNCHRONOUS.
+
+Thu Jun 8 19:01:25 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_pager_users): New function.
+ * shutdown.c (diskfs_shutdown): Rewrote to use new ports interface
+ adequately.
+
+Tue Jun 6 13:50:13 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
+
+ * init-first.c (diskfs_spawn_first_thread): Call our own
+ thread function instead of the ports one directly.
+ (master_thread_function): New function.
+
+ * notify-nosenders.c (diskfs_do_seqnos_mach_notify_no_senders):
+ Don't help support pagers here at all.
+ * demuxer.c (diskfs_demuxer): Don't call pager_demuxer.
+
+ * boot-start.c (diskfs_start_bootstrap): Use new args for
+ ports_allocate_port.
+ (start_execserver): Likewise.
+ * init-startup.c (diskfs_startup_diskfs): Likewise.
+ * protid-make.c (diskfs_start_protid): Likewise.
+ * file-getcontrol.c (diskfs_S_file_getcontrol): Likewise.
+ * sync-interval.c (diskfs_set_sync_interval): Likewise.
+
+ * boot-start.c (diskfs_S_exec_startup): Use ports_lookup_port and
+ ports_port_deref instead of ports_check_port_type and
+ ports_done_with_port.
+ (diskfs_execboot_fsys_startup): Likewise.
+ (diskfs_S_fsys_init): Likewise.
+ (diskfs_S_fsys_getpriv): Likewise.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Likewise.
+ * fsys-goaway.c (diskfs_S_fsys_goaway): Likewise
+ * fsys-startup.c (diskfs_S_fsys_startup): Likewise.
+ * fsys-syncfs.c (diskfs_S_fsys_syncfs): Likewise.
+ * notify-nosenders.c (diskfs_do_seqnos_mach_notify_no_senders):
+ Likewise.
+ * priv.h (begin_using_protid_port): Use ports_lookup_port.
+ (end_using_protid_port): Use ports_port_deref.
+
+ * trans-start.c (fshelp_transboot_port_type): Deleted var.
+ * priv.h (enum porttype): Delete.
+ * demuxer.c: Renamed from ports-demuxer.c.
+ (diskfs_demuxer): Renamed from ports_demuxer.
+ * init-init.c (diskfs_protid_class, diskfs_transboot_class,
+ diskfs_control_class, diskfs_initboot_class,
+ diskfs_execboot_class, diskfs_port_bucket): New vars.
+ (diskfs_init_diskfs): Don't call libports_initialize.
+ Initialize diskfs_protid_class, diskfs_transboot_class,
+ diskfs_control_class, diskfs_initboot_class,
+ diskfs_execboot_class, and diskfs_port_bucket.
+ * diskfs.h: (diskfs_shutdown_soft_ports): Deleted decl.
+ (ports_demuxer): Deleted decl.
+ (diskfs_demuxer): New decl.
+ (diskfs_protid_class, diskfs_transboot_class, diskfs_control_class,
+ diskfs_initboot_class,diskfs_execboot_class, diskfs_port_bucket):
+ New decls.
+ * ports-noports.c, ports-clean.c, ports-soft.c, ports-idle.c,
+ ports-consts.c, pager-consts.c, init-loop.c: Deleted files.
+ * Makefile (OTHERSRCS): Deleted ports-noports.c, ports-clean.c,
+ ports-soft.c, ports-consts, pager-consts.c, init-loop.c, and
+ ports-idle.c.
+ Replace ports-demuxer.c with demuxer.c.
+
+Mon May 22 13:52:16 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * opts-set.c (diskfs_set_options): Don't fall through to the error
+ case from the 's' one!
+ Use ARG instead of the global OPTARG.
+
+Sat May 20 01:11:05 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * file-getcontrol.c (diskfs_S_file_getcontrol): Unlock
+ _diskfs_control_lock lock instead of locking it again!
+
+Fri May 19 21:22:14 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * opts-set.c (diskfs_set_options): New function in new file.
+ * opts-runtime-def.c (diskfs_parse_runtime_options): Ditto.
+ * opts-std-startup.c (diskfs_standard_startup_options): New
+ exported variable in new file.
+ * fsys-options.c (diskfs_S_fsys_set_options): Extract the argument
+ vector and call diskfs_set_options.
+ * diskfs.h: (diskfs_standard_startup_options): Declare new variable.
+ (diskfs_set_options): Declare new function.
+ (diskfs_parse_runtime_options): Ditto.
+ Include <options.h> (currently in ../lib).
+ * Makefile (OTHERSRCS): Add opts-set.c, opts-std-startup.c, and
+ opts-runtime-def.c.
+ (OBJS): Add argz.o & options.o.
+ (REMHDRS): Add argz.h & options.h.
+
+Tue May 16 17:36:46 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * init-first.c (diskfs_spawn_first_thread): Don't start syncing here.
+ * init-startup.c (diskfs_startup_diskfs): Do it here instead.
+
+Mon May 15 15:18:25 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_set_options): Declare.
+ * fsys-options.c (diskfs_S_fsys_set_options): Extract argc & argv,
+ and call diskfs_set_options.
+ * def-set-options.c: New file (contains a default diskfs_set_options).
+
+ * Makefile (OBJS): Add argz.o (from ../lib). It shouldn't hurt to
+ have this in libdiskfs, since we need it...
+ (CPPFLAGS): Add -I../lib, to get argz.h, + $(CPPFLAGS-$(notdir $<))
+ Set the vpath for %.c to ../lib, so we get argz.c.
+ (OTHERSRCS): Add def-set-options.c.
+
+Sat May 13 03:08:35 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot-parse.c (diskfs_execserver_task): New variable.
+ (diskfs_parse_bootargs): Take a third integer arg before the
+ device name, our name for the task port of the exec server, which
+ is loaded and ready to run but suspended.
+ * boot-start.c (start_execserver): Don't create and load a task;
+ the exec server file is no longer linked into the filesystem.
+ Just set the bootstrap port of diskfs_execserver_task and resume
+ it.
+
+Fri May 12 16:22:33 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * fsys-readonly.c (diskfs_S_fsys_set_options,
+ diskfs_S_fsys_mod_readonly): Change from mod_readonly to
+ set_options. This file is now actually called fsys-options.c.
+ * Makefile (FSYSSRCS): Rename fsys-readonly.c to fsys-options.c.
+
+ * sync-interval.c (diskfs_set_sync_interval): New function (in a
+ new file) that establishes a thread to periodically sync the
+ filesystem.
+ * Makefile (OTHERSRCS): Add sync-interval.c and sync-default.c.
+ * diskfs.h: Add declarations of diskfs_set_sync_interval and
+ diskfs_default_sync_interval.
+
+ * init-first.c (diskfs_spawn_first_thread): Start background syncing.
+ * sync-default.c (diskfs_default_sync_interval): A new variable
+ that defines a default initial sync interval.
+
+Fri May 12 15:45:43 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
+
+ * io-read.c (diskfs_S_io_read): If the offset is past the end of
+ the file, then return EOF.
+
+Thu Apr 27 20:01:16 1995 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * node-drop.c (diskfs_drop_node): Deal cleanly with errors in
+ diskfs_truncate.
+
+ * diskfs.h (diskfs_nrele, diskfs_nput): We need to hold a real
+ reference around the call to diskfs_try_dropping_softrefs, because
+ that's a user-supplied routine that might itself rely on the
+ reference counting system.
+
+Thu Apr 20 18:54:26 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * node-create.c (diskfs_create_node): Return EROFS if diskfs_readonly.
+
+Tue Apr 4 20:20:40 1995 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * dir-unlink.c (diskfs_S_dir_unlink): Do fsys_goaway for
+ translated nodes being unlinked.
+ * dir-rmdir.c (diskfs_S_dir_rmdir): Likewise.
+
+Tue Apr 4 18:33:35 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
+
+ * file-exec.c (diskfs_S_file_exec): However, replacing *MAKE_SEND*
+ with COPY_SEND just doesn't work...
+
+Tue Apr 4 14:31:51 1995 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * file-exec.c (diskfs_S_file_exec): Using MOVE_SEND in call to
+ exec_exec loses, because it consumes a reference, which will be
+ consumed again by mach_msg_server if we return an error. So use
+ COPY_SEND instead, and deallocate the rights ourselves only when
+ we are to return success.
+
+Fri Mar 31 12:25:57 1995 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * file-set-trans.c (diskfs_S_file_set_translator): Only destroy
+ existing active translator if ACTIVE_FLAGS will change it. If the
+ existing active translator is provided then don't do anything.
+
+Fri Mar 17 11:36:40 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
+
+ * io-stat.c (diskfs_S_io_stat): Typo.
+
+ * diskfs.h: Back out changes to protid and associated permission
+ checking functions.
+ * file-chmod.c (diskfs_S_file_chmod): Likewise.
+ * file-chown.c (diskfs_S_file_chown): Likewise.
+ * file-getcontrol.c (diskfs_S_file_getcontrol): Likewise.
+
+ * dir-link.c (diskfs_S_dir_link): Fix typo.
+
+ * diskfs.h (_diskfs_idcheckdirmod): `diskfs_hasuid' ->
+ diskfs_idhasuid.
+ * priv.h (CHANGE_NODE_FIELD): Remove trailing space on backslashed
+ line.
+
+ * diskfs.h (_diskfs_idcheckdirmod): `cred' -> `id'.
+ (diskfs_idhasgid): Likewise.
+
+ * dir-clear.c (diskfs_clear_directory): Don't do
+ diskfs_synchronous here.
+ * dir-init.c (diskfs_init_dir): Likewise.
+ * dir-rmdir.c (diskfs_S_dir_rmdir): Repair implementation of
+ diskfs_syncronous.
+ * dir-renamed.c (diskfs_rename_dir): If we are synchronous,
+ sync the one node our parent doesn't have access to.
+ * dir-mkdir.c (diskfs_S_dir_mkdir): Implement diskfs_synchronous.
+ * dir-mkfile.c (diskfs_S_dir_mkfile): Likewise.
+ * dir-lookup.c (diskfs_S_dir_lookup): Likewise.
+ * io-read.c (diskfs_S_io_read): Likewise.
+ * fsys-syncfs.c (diskfs_S_fsys_syncfs): Likewise.
+ * node-drop.c (diskfs_drop_node): Likewise.
+ * node-rdwr.c (diskfs_node_rdwr): Likewise.
+
+Wed Mar 15 11:54:12 1995 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
+
+ * conch-fetch.c (ioserver_fetch_shared_data): Implement
+ diskfs_synchronous.
+ * dir-clear.c (diskfs_clear_directory): Likewise.
+ * dir-init.c (diskfs_init_dir): Likewise.
+ * dir-renamed.c (diskfs_rename_dir): Likewise.
+
+Wed Mar 8 16:36:04 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_synchronous): New variable.
+ * priv.h (CHANGE_NODE_FIELD): If DISKFS_SYNCHRONOUS, then sync
+ node after possibly changing it.
+ * io-seek.c: Prevent diskfs_synchronous from having its usual
+ effect here.
+ * dir-link.c (diskfs_S_dir_link): Implement diskfs_synchronous.
+ * dir-rename.c (diskfs_S_dir_rename): Likewise.
+ * dir-rmdir.c (diskfs_S_dir_rmdir): Likewise
+ * dir-unlink.c (diskfs_S_dir_unlink): Likewise.
+ * file-sync.c (diskfs_S_file_sync): Likewise.
+ * file-syncfs.c (diskfs_S_file_syncfs): Likewise.
+ * io-prenotify.c (diskfs_S_io_prenotify): Likewise.
+ * io-stat.c (diskfs_S_io_stat): Likewise.
+ * io-write.c (diskfs_S_io_write): Likewise.
+ * io-sigio.c (diskfs_S_io_sigio): Likewise.
+
+Tue Mar 7 15:21:09 1995 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * diskfs.h (struct userid): New type.
+ (struct protid): Replace UIDS, GIDS, NUIDS, and NGIDS with ID.
+ (diskfs_isuid): Replace with new function diskfs_idhasuid.
+ (diskfs_groupmember): Replace with new function diskfs_idhasgid.
+ (_diskfs_idisowner, _diskfs_idaccess, _diskfs_idcheckdirmod):
+ New functions.
+ (diskfs_isowner): Check each ID in the chain with
+ _diskfs_idisowner.
+ (diskfs_access): Check each ID in the chain with _diskfs_idaccess.
+ (diskfs_checkdirmod): Check each ID in the chain with
+ _diskfs_idcheckdirmod.
+ * file-chmod.c (diskfs_S_file_chmod): Perform the permission
+ check for each ID in the chain.
+ * file-chown.c (diskfs_S_file_chown): Likewise.
+ * file-getcontrol.c (diskfs_S_file_getcontrol): Likewise.
+
+ * boot-parse.c (diskfs_parse_bootargs): Use assert_perror instead
+ of assert where appropriate.
+ * boot-start.c (diskfs_start_bootstrap): Likewise.
+ (diskfs_S_fsys_init): Likewise.
+ * io-reauthenticate.c (diskfs_S_io_reauthenticate): Likewise.
+ * rdwr-internal.c (_diskfs_rdwr_internal): Likewise.
+
+Thu Jan 19 02:04:34 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * Makefile (ourfs_notify_U.h ourfs_notifyUser.c): Make this
+ instead of ourmsg_U.h. All references changed.
+ * dir-chg.c: Undo renaming. Includ ourfs_notify_U.h instead of
+ ourmsg_U.h.
+
+ * io-select.c: Updated to new io_select protocol.
+
+ * dir-chg.c (diskfs_S_dir_notice_changes): Call
+ nowait_msg_dir_changed instead of nowait_dir_changed.
+
+Sat Dec 10 20:03:07 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot-start.c (start_execserver): When aligning bss size for
+ vm_allocate, don't include bss start alignment fixup offset.
+
+Fri Dec 9 02:06:35 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * io-read.c (diskfs_S_io_read): Don't check for MAXREAD<0.
+
+ * io-write.c: Use mach_msg_type_number_t in place of unsigned int
+ and int.
+ * io-readable.c: Likewise.
+ * io-read.c: Likewise.
+
+Wed Nov 23 00:26:48 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * ports-demuxer.c (ports_demuxer): Call
+ diskfs_seqnos_notify_server, not seqnos_notify_server.
+
+Fri Nov 11 13:11:35 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
+
+ * io-read.c (diskfs_S_io_read): If OFF is past the end of the
+ file, don't set MAXREAD to a negative number; that will crash
+ rdwr_internal.
+
+Wed Nov 9 01:46:18 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * file-exec.c: Include <hurd/paths.h>.
+ (diskfs_S_file_exec): If diskfs_exec isn't already
+ set, try to open it here. (Later, we should also deal if
+ exec_exec returns that the previous server died.)
+
+Tue Nov 8 00:06:56 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * file-get-trans.c: Include <stdio.h> for asprintf decl.
+
+Wed Nov 2 16:16:57 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * priv.h (CHANGE_NODE_FIELD): Don't call diskfs_node_update here.
+
+Fri Oct 28 18:26:15 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot-parse.c (diskfs_parse_bootargs): Make stdout line buffered.
+ (diskfs_parse_bootargs): Use getline instead of scanf.
+ * boot-start.c (diskfs_start_bootstrap): Likewise.
+ (diskfs_S_fsys_init): Create a root port with two send right refs
+ and install it as crdir and cwdir.
+
+Tue Oct 25 14:16:50 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
+
+ * boot-start.c (diskfs_start_bootstrap): Renamed variable ARGV
+ to be EXEC_ARGV and ARGVLEN to be EXEC_ARGVLEN.
+
+Fri Oct 7 01:30:12 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot-parse.c (diskfs_parse_bootargs): Open console for reading too.
+
+ * boot-start.c (saved_argv): New static variable.
+ (diskfs_start_bootstrap): Take arg ARGV; store it in saved_argv.
+ (diskfs_S_fsys_init): Construct a portarray and call _hurd_init.
+ Or, if _hurd_ports is already allocated, call _hurd_proc_init.
+ * diskfs.h (diskfs_start_bootstrap): Update prototype.
+
+Thu Oct 6 17:47:42 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * boot-start.c (diskfs_S_fsys_init): Allocate a reference on
+ authhandle before allowing the library to consume one.
+
+Wed Oct 5 13:00:46 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * node-drop.c (diskfs_drop_node): Clear passive translator
+ if we are releasing the inode.
+
+Thu Sep 29 18:12:31 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot-parse.c (diskfs_parse_bootargs): If we have a bootstrap
+ port, talk to the CMU default pager on it, then clear it.
+
+Fri Sep 23 00:15:52 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
+
+ * diskfs.h (diskfs_lost_hardrefs): Doc fix.
+ (diskfs_try_dropping_softrefs): New declaration.
+ (diskfs_nput): Always call diskfs_lost_hardrefs if the last
+ hardref goes away; call diskfs_try_dropping_softrefs if the
+ link count has vanished too.
+ (diskfs_nrele): Likewise.
+ (diskfs_nref): Lock node during call to diskfs_new_hardrefs.
+
+Thu Sep 22 21:20:40 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
+
+ * diskfs.h (struct node): New member `istranslated'.
+ (diskfs_node_translated): Deleted function.
+ * dir-lookup.c (diskfs_S_dir_lookup): Use istranslated field
+ instead of diskfs_node_translated.
+ * file-get-trans.c (diskfs_S_file_get_translator): Likewise.
+ * file-inv-trans.c (diskfs_S_file_invoke_translator): Likewise.
+ * file-set-trans.c (diskfs_S_file_set_translator): Likewise.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Likewise.
+
+Fri Sep 16 11:53:04 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
+
+ * file-set-trans.c (diskfs_S_file_set_translator): Use new
+ lock on translator fields; don't hold it and the NP lock
+ simultaneously.
+ * trans-destroy.c (diskfs_destroy_translator): Doc fix.
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Turn off *all* flags
+ in call to getroot if we aren't the last component.
+
+Thu Sep 15 13:01:21 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
+
+ * init-init.c (diskfs_init_diskfs): Restore commented-out
+ initialization of diskfs_auth_server_port.
+
+Mon Sep 12 14:38:54 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
+
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Clear translator
+ port if we get MIG_SERVER_DIED, as with MACH_SEND_INVALID_DEST.
+
+Sun Sep 11 23:30:13 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Copy PATHBUF into RETRYNAME
+ properly when symlink target begins with a slash.
+
+Sat Sep 10 08:36:08 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * Makefile (OTHERSRCS): Add init-startup.c.
+ * init-init.c (_diskfs_dotdot_file): Variable removed.
+ (diskfs_init_diskfs): Take no args; return void.
+ Don't do fsys_startup here.
+ * init-startup.c (diskfs_startup_diskfs): New file, new function.
+ Do fsys_startup here instead.
+ * diskfs.h (diskfs_init_diskfs): Update prototype.
+ (diskfs_startup_diskfs): Declare it.
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Use error_t for ERROR.
+ Retry when fsys_getroot returns MIG_SERVER_DIED, as with
+ MACH_SEND_INVALID_DEST.
+
+Fri Sep 9 13:04:36 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
+
+ * dir-lookup.c (diskfs_S_dir_lookup) [EAGAIN]: Only copy
+ into RETRYNAME if this isn't the last component.
+
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Set *RETRY
+ and *RETRYNAME properly on normal return.
+
+ * init-init.c (diskfs_init_diskfs): Don't attempt to continue
+ if fsys_startup fails. Deallocate BOOTSTRAP after using it.
+
+Wed Sep 7 09:52:52 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
+
+ * trans-start.c (diskfs_start_translator): Don't give write
+ access to underlying node if it's not IFREG.
+
+ * dir-lookup.c (diskfs_S_dir_lookup): When returning a port
+ passed back from fsys_getroot, use MACH_MSG_TYPE_MOVE_SEND,
+ not the local default of MAKE_SEND.
+
+ * trans-start.c (diskfs_start_translator): Removed assert.
+
+Tue Sep 6 15:30:59 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
+
+ * dir-lookup.c (diskfs_S_dir_lookup): Translator startup code
+ rewritted to be more robust and use new locking protocol
+ on translink structures.
+ * trans-start.c (diskfs_start_translator): Don't pass LOCK arg
+ to diskfs_start_translator. Unlock NP around call to
+ diskfs_start_translator. Don't expect DIR to be deallocated.
+
+Thu Sep 1 12:28:03 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * trans-start.c (diskfs_start_translator): Expect right
+ on DIR and NPPORT to be consumed by fshelp_start_translator.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Allocate additional
+ send-right for DOTDOT to be consumed by diskfs_start_translator.
+ Be careful to deallocate DOTDOT when appropriate.
+ * dir-lookup.c (diskfs_S_dir_lookup): Create DIRFILE from
+ DNP, not NP. Create local reference for dirfile to use
+ in call to fsys_getroot.
+
+ * boot-start.c (diskfs_start_bootstrap): Give the
+ library values for current working and root directories.
+
+ * trans-start.c (diskfs_start_translator): Fix and enable.
+ * diskfs.h (diskfs_start_translator): Add new third arg to
+ prototype.
+ * dir-lookup.c (diskfs_S_dir_lookup): Provide third arg to
+ diskfs_start_translator.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Likewise.
+
+Wed Aug 31 12:04:51 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * file-exec.c (diskfs_S_file_exec) [reauth]: Destroy REF after
+ using it.
+
+ * file-get-trans.c (diskfs_S_file_get_translator)
+ [S_ISCHR || S_ISBLK]: Correct cast of second arg to vm_allocate.
+
+ * Makefile (FSYSSRCS): Added fsys-readonly.c and fsys-syncfs.c.
+ * fsys-readonly.c, fsys-syncfs.c: New files.
+
+Wed Aug 31 01:50:07 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * boot-parse.c (diskfs_parse_bootargs): Fix scanf format for
+ bootstrap filesystem device name.
+
+ * file-exec.c (diskfs_S_file_exec): For S_ISUID|S_ISGID, create
+ new auth handle and reauthenticate passed ports properly.
+
+Tue Aug 30 13:44:29 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * file-exec.c (diskfs_S_file_exec): Don't bother setting
+ EXEC_NEWTASK for non-readable execs; it doesn't really work
+ anyhow.
+
+ * init-init.c: Call ports_get_right with the result of
+ ports_allocate_port in call to fsys_startup.
+
+ * trans-sync.c (diskfs_sync_translators): Use fsys_syncfs
+ instead of old ugly method.
+
+ * init-init.c: Include <hurd/fsys.h>.
+
+ * boot-start.c (diskfs_start_bootstrap): Check to make sure return
+ from fsys_getroot and dir_lookup is FS_RETRY_NORMAL with empty
+ retry_name instead of old FS_RETRY_NONE.
+ * dir-lookup.c (diskfs_S_dir_lookup): Initialize return values with
+ FS_RETRY_NORMAL and empty retryname instead of old FS_RETRY_NONE.
+
+ * Makefile (FSSRCS): Remove dir-pathtrans.c; add dir-lookup.c.
+ * dir-lookup.c: Renamed from dir-pathtrans.c.
+ * dir-pathtrans.c (diskfs_S_dir_lookup): Renamed from
+ diskfs_S_dir_pathtrans.
+ * boot-start.c (diskfs_start_bootstrap): Call dir_lookup instead
+ of dir_pathtrans.
+ * ifsock.c (diskfs_S_ifsock_getsockaddr): Call file_name_lookup
+ instead of path_lookup.
+
+Mon Aug 29 12:51:42 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * io-reauthenticate.c (diskfs_S_io_reauthenticate): Use new
+ protocol for auth_server_authenticate.
+
+Fri Aug 26 12:49:09 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * file-set-trans.c (diskfs_S_file_set_translator): Rename args;
+ split flags arg into two. Interpret flags according to new
+ scheme.
+
+Thu Aug 18 12:58:44 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * boot-parse.c (diskfs_parse_bootargs): Print informative
+ bootstrap message.
+ * boot-start.c (diskfs_start_bootstrap): Likewise.
+ (start_execserver): Likewise.
+
+ * boot-start.c (diskfs_start_bootstrap): Only do `pausing'
+ hack if RB_KDB was in bootstrap args.
+ (start_execserver): Likewise.
+
+ * io-select.c (diskfs_S_io_select): Add new `porttype' arg.
+
+Thu Aug 11 13:05:40 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Set retry stuff
+ correctly if there are more components after translator
+ fsys_getroot.
+
+Sat Jul 23 02:25:54 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * Makefile (notify-MIGSFLAGS): New variable: -DSEQNOS.
+
+ * ports-demuxer.c (ports_demuxer): Prepend diskfs_ to Hurd
+ interface server functions.
+
+Fri Jul 22 10:54:23 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
+
+ * Makefile: Changed to use new scheme.
+ * boot-start.c: Include "fsys_reply_U.h" instead of "fsys_reply.h".
+ * dir-chg.c: Include "ourmsg_U.h" instead of "msg.h".
+ * fsmutations.h SERVERPREFIX): Delete macro.
+
+ * diskfs.h (struct thread_stuff, diskfs_catch_exception,
+ diskfs_end_catch_exception): Moved here from diskfs_machdep.
+ Delete inclusion of diskfs_machdep.
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Skip leading
+ slashes instead of returning an error.
+
+Tue Jul 19 22:12:29 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Fix fsys_getroot call:
+ MACH_MSG_TYPE_MOVE_SEND instead of MACH_PORT_RIGHT_MOVE_SEND.
+
+Tue Jul 19 18:37:52 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * boot-start.c (diskfs_start_bootstrap): Create root port
+ before calling fsys_getroot on exec server. Pass root port
+ as exec server's dotdot node.
+ (diskfs_execboot_fsys_startup): Deleted dotdot args.
+ * diskfs.h (diskfs_execboot_fsys_startup): Deleted dotdot args.
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans) [translator startup]:
+ Set dirfile always, not just when invoking the passive translator.
+ Pass dirfile to fsys_getroot. Clean up deallocate of dirfile.
+ * file-inv-trans.c (diskfs_S_file_invoke_translator): Comment
+ out code; this function should vanish.
+ * priv.h (_diskfs_dotdot_file): Deleted variable.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Use new arg `dotdot'
+ in place of _diskfs_dotdot_file. Pass dotdot in call to
+ fsys_getroot.
+ * trans-sync.c (diskfs_sync_translators): Pass grunge as dotdot
+ arg in call to fsys_getroot.
+ * fsys-startup.c (diskfs_S_fsys_startup): Deleted dotdot args;
+ don't pass them in calls to helper functions.
+ * init-init.c (diskfs_init_diskfs): Don't expect dotdot arg
+ from fsys_getroot; don't set _diskfs_dotdot_file.
+
+Mon Jul 18 15:24:30 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * file-inv-trans.c: New file.
+ * Makefile (FSSRCS): Added file-inv-trans.c.
+
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Dereference
+ returned_port in check for null.
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Likewise.
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): After
+ diskfs_start_translator, set var `control'.
+
+ * fsys-getroot.c (diskfs_S_fsys_getroot): After getting
+ MACH_SEND_INVALID_DEST from the translator, set error to zero
+ so that the user's open completes normally. Do other fixes
+ from Jul 7 that were made in dir-pathtrans.c for translator
+ startup.
+
+ * ports-idle.c (ports_notice_idle): New file.
+ * Makefile (OTHERSRCS): Added ports-idle.c.
+
+ * node-times.c (diskfs_set_node_times): Set old stat structure
+ times until the header file gets changed.
+
+ * ifsock.c (diskfs_S_ifsock_getsockaddr): Provide type argument
+ in call to socket_fabricate_address.
+
+Fri Jul 15 12:00:38 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Use
+ DIRCRED->po->dotdotport instead of diskfs_dotdot_file.
+
+ * diskfs.h (diskfs_read_symlink_hook): New variable.
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Don't permit symlinks
+ to be opened for reading or writing (just like other special file
+ types). Try using diskfs_read_symlink_hook before reading
+ from file data.
+
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Try using
+ diskfs_read_symlink_hook before reading from file data.
+ * file-get-trans.c (diskfs_S_file_get_translator): Likewise.
+
+Thu Jul 14 14:39:08 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * diskfs.h (diskfs_create_symlink_hook): New variable.
+ (diskfs_truncate): Doc fix.
+ * file-set-trans.c (diskfs_S_file_set_translator): Try
+ diskfs_create_symlink_hook first, before writing ourselves.
+ Return errors to user properly.
+
+ * node-times.c (diskfs_set_node_times): Use new stat structures
+ with struct timespec instead of old definitions.
+
+Wed Jul 13 14:26:37 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * shutdown.c (diskfs_shutdown): Check UNLINK bit first to avoid
+ dumping translators if we end up returning an error.
+
+ * ports-noports.c: New file.
+ * ports-soft.c: New file.
+ * diskfs.h (diskfs_shutdown_soft_ports): New declaration.
+ * Makefile (OTHERSRCS): Added ports-noports.c and ports-soft.c.
+
+ * diskfs.h (diskfs_init_diskfs): New arg `bootstrap'; add return
+ value. Call fsys_getroot if bootstrap is set.
+
+ * diskfs.h (diskfs_dotdot_file): Deleted variable.
+ (struct peropen): New member `dotdotnode'.
+ (diskfs_make_peropen): New arg DOTDOTPORT.
+ * peropen-make.c (diskfs_make_peropen): Set PO->dotdotport;
+ allocate reference if necessary.
+ * priv.h (_diskfs_dotdot_file): New variable.
+ * init-init.c (_diskfs_dotdot_file): New definition.
+ * boot-start.c (diskfs_start_bootstrap): dotdot for created
+ peropen to root should be null (we are *the* root directory in this
+ case).
+ (diskfs_S_exec_startup): Likewise.
+ * dir-mkfile.c (diskfs_S_dir_mkfile): Inherit dotdot for
+ new peropen from CRED->po.
+ * file-exec.c (diskfs_S_file_exec): Likewise.
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Inherit dotdot for
+ new peropens from DIRCRED->po.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Set dotdot
+ from _diskfs_dotdot_file.
+
+ * diskfs.h (diskfs_control_port): Deleted variable.
+ * priv.h (_diskfs_control_lock, _diskfs_ncontrol_ports): New vars.
+ (_diskfs_control_clean): New declaration.
+ * ports-clean.c (ports_cleanroutines[PT_CTL]): Use
+ _diskfs_control_clean.
+ * init-init.c (diskfs_init_diskfs): Don't create control port here.
+ (_diskfs_control_lock, _diskfs_ncontrol_ports): New declarations.
+ * file-getcontrol.c (diskfs_S_file_getcontrol): Always create
+ a new control port structure.
+
+ * io-write.c (diskfs_S_io_write): Honor O_FSYNC bit.
+ * conch-set.c (ioserver_put_shared_data): Set do_sigio if
+ user set O_FSYNC.
+ * io-stubs.c (diskfs_S_io_sigio): Removed function.
+ * io-sigio.c: New file.
+ * Makefile (IOSRCS): Added io-sigio.c
+
+ * io-write.c (diskfs_S_io_write): Eliminate pointless test for
+ !err before _diskfs_rdwr_internal; only increment filepointer if
+ there was no error.
+
+ * priv.h (_diskfs_rdwr_internal): New arg NOTIME.
+ * rdwr-internal.c (_diskfs_rdwr_internal): New arg NOTIME.
+ * io-read.c (diskfs_S_io_read): Don't set atime if O_NOATIME is on.
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Don't allow non-owner
+ to set O_NOATIME.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Likewise.
+
+ * priv.h (HONORED_STATE_MODES): Add O_NOATIME.
+ (OPENONLY_STATE_MODES): New macro.
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Use
+ OPENONLY_STATE_MODES to turn off appropriate bits.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Likewise.
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): At start, turn
+ off all the bits not in O_HURD; we ignore all those and don't
+ keep track of them in any way.
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Likewise.
+
+ * file-get-trans.c (diskfs_S_file_get_translator): Return
+ shortcircuited translators for IFCHR, IFBLK, IFIFO, and IFSOCK.
+
+ * file-set-trans.c (diskfs_S_file_set_translator): In computing
+ rdev, 377 should be *octal*, not hex.
+
+ * dir-rename.c (diskfs_S_dir_rename): Deallocate received
+ send-right for TOCRED any time we return success.
+
+ * dir-link.c (diskfs_S_dir_link): Don't assume that NP is a
+ non-directory before checking it.
+
+ * boot-start.c (diskfs_start_bootstrap): New variable
+ `initnamebuf' which is allocated and then not changed; free
+ it rather than freeing `initname'.
+
+Mon Jul 11 18:16:25 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Symlinks to pathnames
+ beginning with `/' sholud return FS_RERTY_MAGICAL (but the
+ retry name is stils the same).
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Likewise.
+
+Fri Jul 8 13:34:25 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): After getting
+ MACH_SEND_INVALID_DEST from the translator, set error to zero
+ so that the user's open completes normally.
+ (diskfs_S_dir_pathtrans): Call mach_port_mod_refs correctly.
+ (diskfs_S_dir_pathtrans): In call to fsys_getroot, turn off
+ O_NOLINK for !lastcomp, not for lastcomp.
+
+Thu Jul 7 14:46:46 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Deal correctly
+ with the sendright on the translator control port avoiding
+ races while the node is unlocked.
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): At translator
+ lookup time, if there is an active translator, release the
+ lock on DNP just like we do in the start-passive case. Also
+ after fsys_getroot, release reference and clear DNP so that
+ code at out: doesn't get it wrong.
+ (diskfs_S_dir_pathtrans): Call fshelp_translator_drop instead
+ of setting it to null ourselves.
+ * trans-destroy.c (diskfs_destroy_translator): Likewise.
+
+Wed Jul 6 14:43:55 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * ports-demuxer.c (ports_demuxer): Only call ifsock_server
+ if diskfs_shortcut_ifsock is set.
+
+Tue Jul 5 14:15:32 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * Makefile (TAGSHDRS): New variable.
+
+Thu Jun 30 11:35:43 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * fsmutations.h (IFSOCK_IMPORTS): New macro.
+
+ * ports-demuxer.c (ports_demuxer): Call ifsock_server.
+
+Wed Jun 29 17:07:17 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
+
+ * diskfs.h (struct node): New member `sockaddr'.
+ * node-make.c (diskfs_make_node): Initialize NP->sockaddr.
+ * node-drop.c (diskfs_drop_node): Deallocate NP->sockaddr
+ if it's been set.
+ * ifsock.c: New file.
+ * Makefile (IFSOCKSRCS): New variable.
+ (SRCS): Added $(IFSOCKSRCS).
+ (MIGSTUBS): Added ifsockServer.o.
+ (ifsock_S.h ifsockServer.c): New rule.
+ (ifsock_S.h): Depended on by IFSOCKSRCS generated objects.
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Detect the case
+ where the server has died by looking for MACH_SEND_INVALID_DEST
+ as a return from fsys_getroot. Rearrange lock/unlock and
+ reference counting of NP and DNP because we may need them back
+ if we have to repeat the call.
+
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Likewise.
+
+Fri Jun 24 15:52:52 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * dir-link.c (diskfs_S_dir_link): The port_info struct member
+ is `port_right', not `port'.
+
+Tue Jun 21 13:25:15 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * dir-link.c (diskfs_S_dir_link): Deallocate received send
+ right for DIRCRED anytime we return success.
+
+ * dir-chg.c (diskfs_S_dir_notice_changes): New var `np'. Return
+ ENOTDIR if call is made on a non-directory.
+
+Mon Jun 20 16:40:37 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * node-drop.c (diskfs_drop_node): Free structures holding
+ dirmod requests.
+ * node-make.c (diskfs_make_node): Initialize NP->dirmod_reqs
+ to zero.
+
+Fri Jun 17 13:16:18 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
+
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Initialize ERROR.
+
+Fri Jun 17 11:21:25 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu)
+
+ * trans-sync.c: Include <fcntl.h>.
+
+ * Makefile (boot-start.o): Depend on fsys_reply.h.
+
+Thu Jun 16 11:31:46 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
+
+ * Makefile (msg.h, msgUser.c): New rules.
+ (MIGSTUBS): Added msgUser.o.
+ (dir-chg.o): Depends on msg.h.
+ * dir-chg.c: Include "msg.h".
+
+ * diskfs.h (diskfs_start_translator): Second arg DIR is now
+ file_t. Changed locking rules.
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Call
+ diskfs_start_translator the new way; clean up lock releases.
+
+ * fshelp-dropnode.c: Deleted file.
+ * fshelp-getnode.c: Deleted file.
+ * Makefile (OTHERSRCS): Removed fshelp-dropnode.c and fshelp-getnode.c.
+
+ * boot-start.c (diskfs_start_bootstrap): Use new fsys_getroot
+ interface.
+
+ * fsys-getroot.c: Include <fcntl.h> for O_ bits. Include
+ <hurd/fsys.h> for fsys_startup prototype.
+
+ * boot-start.c (diskfs_start_bootstrap, diskfs_S_exec_startup):
+ Delete obsolete assignments to INIT_PORT_LOGINCOLL.
+
+ * diskfs.h (struct node) [dirmod_reqs]: New member.
+ (struct dirmod): New type.
+ (diskfs_dirrewrite, diskfs_dirremove, diskfs_direnter): Doc fix.
+ (diskfs_notice_dirchange): New prototype.
+ * dir-chg.c (diskfs_S_dir_notice_changes): Implement call.
+ (diskfs_notice_dirchange): New function.
+
+ * diskfs.h (diskfs_get_directs): Doc fix.
+
+ * file-access.c (diskfs_S_file_check_access): Renamed from
+ diskfs_S_file_access. Return allowable operations in *TYPE
+ rather than checking those explicitly asked for. Use O_ bits
+ instead of _OK bits. Include <fcntl.h>.
+
+Wed Jun 15 21:26:14 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Require lookup of
+ empty pathname to fail if not made on a directory.
+
+ * fsys-getroot.c (diskfs_S_fsys_getroot): Rewritten to implement
+ the new fsys_getroot interface.
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Don't implement
+ O_TRUNC here anymore.
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Use the new
+ fsys_getroot interface for translator startup.
+
+ * io-modes-set.c (diskfs_S_io_set_all_openmodes): Only let
+ the user set the user-setable bits.
+
+ * file-get-transcntl.c (diskfs_S_file_get_translator_cntl): New
+ arg CTLTYPE; set appropriately.
+
+Wed Jun 15 12:18:16 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
+
+ * file-chg.c (diskfs_S_file_notice_changes): Declare return type.
+
+ * file-access.c: New file.
+ * Makefile (FSSRCS): Added file-access.c.
+
+Tue Jun 14 14:06:36 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
+
+ * diskfs.h (diskfs_get_dirents): New declaration.
+ * dir-readdir.c (diskfs_S_dir_readdir): Implement new
+ interface using diskfs_get_directs.
+
+ * dir-chg.c, file-chg.c: New files.
+ * Makefile (FSSRCS): Added dir-chg.c and file-chg.c.
+
+Thu Jun 9 13:39:25 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Release lock on NP
+ during call to fsys_getroot; stash control port and uid info in
+ new local variables. Reacquire lock before return (because
+ common code at label OUT expects NP to be locked).
+
+Mon Jun 6 18:54:50 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): In translator
+ startup check, test O_NOTRANS in flags correctly.
+
+ * dir-renamed.c (diskfs_rename_dir): Don't call diskfs_nrele on
+ TMPNP after SPEC_DOTDOT calls; the spec says that SPEC_DOTDOT
+ with RENAME does not allocate a new reference.
+
+Sun Jun 5 05:51:11 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu)
+
+ * io-reauthenticate.c (diskfs_S_io_reauthenticate): Fix
+ initialization of {GEN,AUX}_{UIDS,GIDS}.
+
+Fri Jun 3 18:19:22 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * file-set-trans.c (diskfs_S_file_set_translator): Use
+ fshelp_set_control instead of doing it ourselves.
+
+Thu Jun 2 12:00:51 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * diskfs.h (struct node): New member `light_references'.
+ (diskfs_nref, diskfs_nput, diskfs_nrele, diskfs_make_node): Doc fix.
+ (diskfs_nref_light, diskfs_nput_light, diskfs_nrele_light):
+ New functions.
+ (diskfs_nrele, diskfs_nput): Only call diskfs_drop_node if both
+ NP->references *and* NP->light_references are zero.
+ (diskfs_new_hardrefs, diskfs_lost_hardrefs): New declarations.
+ (diskfs_nref): Call diskfs_new_hardrefs when appropriate.
+ (diskfs_nput, diskfs_nrele): Call diskfs_lost_hardrefs when
+ appropriate.
+
+ * node-make.c (diskfs_make_node): Initialize NP->light_references.
+ Doc fix.
+
+Wed Jun 1 18:24:11 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Skip over multiple
+ slashes in pathnames by incrementing NEXTNAME after setting it.
+ Also, if after we do this we discover that there is no last
+ component, then set LASTCOMP and clear NEXTNAME and CREATE
+ entirely, and set (new variable) MUSTBEDIR. Then check for
+ MUSTBEDIR after the node has been fetched. Make var TYPE
+ function-global and set it always, not just when NEWNODE is unset.
+
+Fri May 27 08:47:46 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * boot-start.c (diskfs_S_exec_exec, diskfs_S_exec_setexecdata):
+ Add missing args.
+ (diskfs_S_exec_startup): Don't point *ARGVP to EXEC_DATA local
+ storage. Instead, copy EXEC_DATA to *ARGVP if *ARGVLEN allows;
+ otherwise vm_allocate new space and copy into there.
+
+Thu May 26 15:33:57 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * diskfs.h (diskfs_nrele): Acquire lock if we are releasing
+ the last reference.
+
+ * node-drop.c (diskfs_drop_node): If we are truncating, then
+ go back to normal user state and do the truncate; the next
+ time through we will do the dealloc for real.
+ Semantics change: now this routine is responsible for
+ unlocking diskfs_node_refcnt_lock. All callers changed.
+
+Wed May 25 20:34:17 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * io-write.c (diskfs_S_io_write): Don't check for *AMT < 0; AMT is
+ an out-only parameter.
+
+Wed May 25 12:23:25 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * ports-consts.c (ports_use_multiple_threads): Deleted definition.
+ * init-first.c (diskfs_spawn_first_thread): Fork
+ ports_manage_port_operations_multithread instead of
+ ports_maange_port_operations.
+ * init-loop.c (diskfs_main_request_loop): Likewise.
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Reference node in
+ lookup of empty path case so that common code at the out: label
+ doesn't free an extra one.
+
+Mon May 23 23:13:51 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * boot-start.c (diskfs_S_fsys_init): Start exec_init after
+ proc_child.
+
+Thu May 19 12:48:53 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
+
+ * io-reauthenticate.c (diskfs_S_io_reauthenticate): Unlock
+ node after calling diskfs_finish_protid.
+
+Thu May 12 14:23:29 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
+
+ * Makefile (clean): Add fsys_reply.h and *User.c.
+
+Thu May 12 03:45:38 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * Makefile (fsys_reply.h fsys_replyUser.c): New rule.
+ (MIGSTUBS): Add fsys_replyUser.o.
+ * boot-start.c: Include fsys_reply.h.
+ (diskfs_S_fsys_init): Take new reply port args.
+ Send reply msg as soon as verified, before doing anything.
+
+Mon May 9 16:58:24 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
+
+ * diskfs.h (diskfs_init_completed): New function declaration.
+ * boot-start.c (diskfs_S_fsys_init): Don't call _hurd_proc_init.
+ Do call diskfs_init_completed.
+
+Thu May 5 13:04:43 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Behave properly
+ if nextname is null. Copy nextname to the end of the symlink
+ target rather than vice versa. Don't punt to the caller before
+ doing the append.
+ (diskfs_S_dir_pathtrans): O_NOTRANS should prevent symlink
+ interpretation.
+ (diskfs_S_dir_pathtrans): If a symlink traversal was the last
+ component, then clear CREATE (symlinks to nothing don't honor
+ O_CREAT) and clear LASTCOMP (because it isn't true any longer).
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Fix mangled check
+ for O_NOLINK.
+ (diskfs_S_dir_pathtrans): Repair furtherly mangled check for
+ O_NOLINK.
+
+ * conch-set.c (ioserver_put_shared_data): Set
+ optimal_transfer_size from the same thing we return in stat.
+
+ * io-async.c (diskfs_S_io_async): Just return EOPNOTSUPP without
+ doing anything more at all.
+
+Thu May 5 06:32:10 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * io-prenotify.c (diskfs_S_io_prenotify): Make START and END args
+ type vm_offset_t.
+
+ * io-map-cntl.c (diskfs_S_io_map_cntl): Take 3rd result arg
+ for msg type of *CTLOBJ; set it to copy-send.
+
+ * io-async.c (diskfs_S_io_async): Take 3rd result arg for msg type
+ of *IDPORT; set it to copy-send. Return 0 instead of EOPNOTSUPP;
+ should not be deallocating NOTIFY if returning an error.
+
+ * io-async-icky.c (diskfs_S_io_get_icky_async_id): Take 3rd result arg
+ for msg type of *IDPORT; set it to copy-send.
+
+ * conch-set.c (ioserver_put_shared_data): Temporarily #if 0
+ setting of optimal_transfer_size from bogus undeclared variable.
+
+ * protid-make.c: Include <string.h> to get bcopy declared.
+
+ * {file,dir,io,fsys}-*.c: Changed return type of all RPC server
+ functions to kern_return_t. error_t is not compatible with the
+ declarations in the mig-generated header files.
+
+ * Makefile: Change uses of $(headers) to $(includedir).
+
+ * file-exec.c (diskfs_S_file_exec): Fix msg type arg in exec_exec call.
+
+ * dir-pathtrans.c (diskfs_S_dir_pathtrans): Add missing close paren.
+
+ * boot-start.c (diskfs_start_bootstrap): Pass msg type arg for
+ FILE arg to exec_exec.
+ (diskfs_S_fsys_getpriv): Change return type to kern_return_t.
+ error_t is not compatible with the declarations in the
+ mig-generated header files.
+ (diskfs_S_fsys_init): Likewise.
+ (exec_stack_base, exec_stack_size): New variables.
+ (diskfs_S_exec_startup): Use those for stack values in reply.
+ (start_execserver): Pass them to mach_setup_thread to be initialized.
+
+Mon May 2 16:32:22 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
+
+ * dir-pathtrans.c: Test for O_NOLINK flag was mangled.
+
+Fri Apr 29 16:44:08 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * io-stubs.c (diskfs_S_io_readnotify): New function.
+
+ * conch-set.c (ioserver_put_shared_data): Set new fields
+ optimal_transfer_size (to sblock->fs_bsize) and
+ use_readnotify_size (to zero).
+
+ * file-exec.c (diskfs_S_file_exec): Change call to exec_exec in
+ accord with interface change in exec.defs.
+
+Mon Feb 14 11:26:26 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * boot-start.c: #include <hurd.h>.
+ (start_execserver): Call _hurd_setup_thread in place of start_thread.
diff --git a/libdiskfs/Makefile b/libdiskfs/Makefile
new file mode 100644
index 00000000..612aaea2
--- /dev/null
+++ b/libdiskfs/Makefile
@@ -0,0 +1,71 @@
+#
+# Copyright (C) 1994, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
+#
+# 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+dir := libdiskfs
+makemode := library
+
+libname = libdiskfs
+FSSRCS= dir-chg.c dir-link.c dir-lookup.c dir-mkdir.c dir-mkfile.c \
+ dir-readdir.c dir-rename.c dir-rmdir.c dir-unlink.c \
+ file-access.c file-chauthor.c file-chflags.c file-chg.c \
+ file-chmod.c file-chown.c file-exec.c file-get-fs-opts.c \
+ file-get-trans.c file-get-transcntl.c file-getcontrol.c \
+ file-getfh.c file-getlinknode.c file-inv-trans.c file-lock-stat.c \
+ file-lock.c file-set-size.c file-set-trans.c file-statfs.c \
+ file-sync.c file-syncfs.c file-utimes.c file-reparent.c
+IOSRCS= io-async-icky.c io-async.c io-duplicate.c io-get-conch.c io-revoke.c \
+ io-interrupt.c io-map-cntl.c io-map.c io-modes-get.c io-modes-off.c \
+ io-modes-on.c io-modes-set.c io-owner-mod.c io-owner-get.c \
+ io-pathconf.c io-prenotify.c io-read.c io-readable.c io-identity.c \
+ io-reauthenticate.c io-rel-conch.c io-restrict-auth.c io-seek.c \
+ io-select.c io-stat.c io-stubs.c io-write.c io-version.c io-sigio.c
+FSYSSRCS=fsys-getroot.c fsys-goaway.c fsys-startup.c fsys-getfile.c \
+ fsys-options.c fsys-syncfs.c fsys-forward.c
+IFSOCKSRCS=ifsock.c
+OTHERSRCS = conch-fetch.c conch-set.c dir-clear.c dir-init.c dir-renamed.c \
+ node-create.c node-drop.c node-make.c node-rdwr.c node-update.c \
+ node-nref.c node-nput.c node-nrele.c node-nrefl.c node-nputl.c \
+ node-nrelel.c \
+ peropen-make.c peropen-rele.c protid-make.c protid-rele.c \
+ init-init.c init-startup.c init-first.c init-main.c \
+ rdwr-internal.c boot-start.c demuxer.c node-times.c shutdown.c \
+ sync-interval.c sync-default.c \
+ opts-set.c opts-get.c opts-std-startup.c opts-std-runtime.c \
+ opts-append-std.c opts-common.c opts-runtime.c opts-version.c \
+ trans-callback.c readonly.c remount.c console.c disk-pager.c \
+ name-cache.c direnter.c dirrewrite.c dirremove.c lookup.c dead-name.c \
+ validate-mode.c validate-group.c validate-author.c validate-flags.c \
+ validate-rdev.c validate-owner.c extra-version.c
+SRCS = $(OTHERSRCS) $(FSSRCS) $(IOSRCS) $(FSYSSRCS) $(IFSOCKSRCS)
+LCLHDRS = diskfs.h priv.h lithp.h fsmutations.h diskfs-pager.h fhandle.h
+installhdrs = diskfs.h diskfs-pager.h
+DIST_FILES = ourfs_notify.defs
+
+MIGSTUBS = fsServer.o ioServer.o fsysServer.o exec_startupServer.o \
+ fsys_replyUser.o ourfs_notifyUser.o ifsockServer.o \
+ startup_notifyServer.o
+OBJS = $(sort $(SRCS:.c=.o) $(MIGSTUBS))
+
+HURDLIBS=fshelp iohelp store ports threads shouldbeinlibc
+
+fsys-MIGSFLAGS = -imacros $(srcdir)/fsmutations.h -DREPLY_PORTS
+fs-MIGSFLAGS = -imacros $(srcdir)/fsmutations.h
+io-MIGSFLAGS = -imacros $(srcdir)/fsmutations.h
+ifsock-MIGSFLAGS = -imacros $(srcdir)/fsmutations.h
+MIGCOMSFLAGS = -prefix diskfs_
+
+include ../Makeconf
diff --git a/libdiskfs/boot-start.c b/libdiskfs/boot-start.c
new file mode 100644
index 00000000..98889e6f
--- /dev/null
+++ b/libdiskfs/boot-start.c
@@ -0,0 +1,662 @@
+/*
+ Copyright (C) 1993,94,95,96,97,98,99 Free Software Foundation, Inc.
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include "priv.h"
+#include <stdio.h>
+#include <hurd.h>
+#include <hurd/fsys.h>
+#include <hurd/exec.h>
+#include <hurd/startup.h>
+#include <hurd/paths.h>
+#include <fcntl.h>
+#include <device/device.h>
+#include <sys/reboot.h>
+#include <string.h>
+#include <argz.h>
+#include <error.h>
+#include "fsys_S.h"
+#include "fsys_reply_U.h"
+
+static mach_port_t diskfs_exec_ctl;
+extern task_t diskfs_exec_server_task;
+static task_t parent_task = MACH_PORT_NULL;
+
+static struct mutex execstartlock;
+static struct condition execstarted;
+
+static char *default_init = "hurd/init";
+
+static void start_execserver ();
+
+char **diskfs_argv = 0;
+
+static mach_port_t
+get_console ()
+{
+ mach_port_t device_master, console;
+ error_t err = get_privileged_ports (0, &device_master);
+
+ if (err)
+ return MACH_PORT_NULL;
+
+ err = device_open (device_master, D_WRITE | D_READ, "console", &console);
+ if (err)
+ return MACH_PORT_NULL;
+
+ return console;
+}
+
+/* Make sure we have the privileged ports. */
+void
+_diskfs_boot_privports (void)
+{
+ assert (diskfs_boot_flags);
+ if (_hurd_host_priv == MACH_PORT_NULL)
+ {
+ /* We are the boot command run by the real bootstrap filesystem.
+ We get the privileged ports from it as init would. */
+ mach_port_t bootstrap;
+ error_t err = task_get_bootstrap_port (mach_task_self (), &bootstrap);
+ assert_perror (err);
+ err = fsys_getpriv (bootstrap, &_hurd_host_priv, &_hurd_device_master,
+ &parent_task);
+ mach_port_deallocate (mach_task_self (), bootstrap);
+ assert_perror (err);
+ }
+}
+
+/* Once diskfs_root_node is set, call this if we are a bootstrap
+ filesystem. */
+void
+diskfs_start_bootstrap ()
+{
+ mach_port_t root_pt, startup_pt, bootpt;
+ retry_type retry;
+ char pathbuf[1024];
+ string_t retry_name;
+ mach_port_t portarray[INIT_PORT_MAX];
+ mach_port_t fdarray[3]; /* XXX */
+ task_t newt;
+ error_t err;
+ char *exec_argv, *exec_env, *initname;
+ size_t exec_argvlen, exec_envlen;
+ struct port_info *bootinfo;
+ struct protid *rootpi;
+ mach_port_t diskfs_exec;
+
+ /* Create the port for current and root directory. */
+ err = diskfs_create_protid (diskfs_make_peropen (diskfs_root_node,
+ O_READ | O_EXEC, 0),
+ 0, &rootpi);
+ assert_perror (err);
+ root_pt = ports_get_right (rootpi);
+
+ /* Get us a send right to copy around. */
+ mach_port_insert_right (mach_task_self (), root_pt, root_pt,
+ MACH_MSG_TYPE_MAKE_SEND);
+
+ ports_port_deref (rootpi);
+
+ if (diskfs_exec_server_task == MACH_PORT_NULL)
+ {
+ /* We are the boot command run by the real bootstrap filesystem.
+ Our parent (the real bootstrap filesystem) provides us a root
+ directory where we look up /servers/exec like any non-bootstrap
+ filesystem would. */
+ assert (_hurd_ports);
+ assert (_hurd_ports[INIT_PORT_CRDIR].port != MACH_PORT_NULL);
+ diskfs_exec = file_name_lookup (_SERVERS_EXEC, 0, 0);
+ if (diskfs_exec == MACH_PORT_NULL)
+ error (1, errno, "%s", _SERVERS_EXEC);
+ else
+ {
+#ifndef NDEBUG
+ /* Make sure this is really a port to another server. */
+ struct port_info *pi = ports_lookup_port (diskfs_port_bucket,
+ diskfs_exec, 0);
+ assert (!pi);
+#endif
+ }
+
+ /* Here we assume the parent has already printed:
+ Hurd server bootstrap: bootfs[bootdev] exec ourfs
+ */
+ printf ("\nContinuing on new root filesystem %s:", diskfs_disk_name);
+ fflush (stdout);
+ }
+ else
+ {
+ uid_t idlist[] = {0, 0, 0};
+ file_t execnode;
+
+ printf ("Hurd server bootstrap: %s[%s]",
+ program_invocation_short_name, diskfs_disk_name);
+ fflush (stdout);
+
+ /* Get the execserver going and wait for its fsys_startup */
+ mutex_init (&execstartlock);
+ condition_init (&execstarted);
+ mutex_lock (&execstartlock);
+ start_execserver ();
+ condition_wait (&execstarted, &execstartlock);
+ mutex_unlock (&execstartlock);
+ assert (diskfs_exec_ctl != MACH_PORT_NULL);
+
+ /* Contact the exec server. */
+ err = fsys_getroot (diskfs_exec_ctl, root_pt, MACH_MSG_TYPE_COPY_SEND,
+ idlist, 3, idlist, 3, 0,
+ &retry, retry_name, &diskfs_exec);
+ assert_perror (err);
+ assert (retry == FS_RETRY_NORMAL);
+ assert (retry_name[0] == '\0');
+ assert (diskfs_exec != MACH_PORT_NULL);
+
+ /* Attempt to set the active translator for the exec server so that
+ filesystems other than the bootstrap can find it. */
+ err = dir_lookup (root_pt, _SERVERS_EXEC, O_NOTRANS, 0,
+ &retry, pathbuf, &execnode);
+ if (err)
+ {
+ error (0, err, "cannot set translator on %s", _SERVERS_EXEC);
+ mach_port_deallocate (mach_task_self (), diskfs_exec_ctl);
+ }
+ else
+ {
+ assert (retry == FS_RETRY_NORMAL);
+ assert (retry_name[0] == '\0');
+ assert (execnode != MACH_PORT_NULL);
+ err = file_set_translator (execnode, 0, FS_TRANS_SET, 0, 0, 0,
+ diskfs_exec_ctl, MACH_MSG_TYPE_MOVE_SEND);
+ mach_port_deallocate (mach_task_self (), execnode);
+ assert_perror (err);
+ }
+ diskfs_exec_ctl = MACH_PORT_NULL; /* Not used after this. */
+ }
+
+ if (_diskfs_boot_command)
+ {
+ /* We have a boot command line to run instead of init. */
+ err = argz_create (_diskfs_boot_command, &exec_argv, &exec_argvlen);
+ assert_perror (err);
+ initname = exec_argv;
+ while (*initname == '/')
+ initname++;
+ }
+ else
+ {
+ /* Choose the name of the startup server to execute. */
+ char *initnamebuf;
+ if (index (diskfs_boot_flags, 'i'))
+ {
+ size_t bufsz;
+ ssize_t len;
+ initname = default_init;
+ prompt:
+ initnamebuf = NULL;
+ printf ("\nInit name [%s]: ", initname);
+ fflush (stdout);
+ bufsz = 0;
+ switch (len = getline (&initnamebuf, &bufsz, stdin))
+ {
+ case -1:
+ perror ("getline");
+ printf ("Using default of `%s'.\n", initname);
+ case 0: /* Hmm. */
+ case 1: /* Empty line, just a newline. */
+ /* Use default. */
+ break;
+ default:
+ initnamebuf[len - 1] = '\0'; /* Remove the newline. */
+ initname = initnamebuf;
+ while (*initname == '/')
+ initname++;
+ break;
+ }
+ }
+ else
+ {
+ initname = default_init;
+ initnamebuf = NULL;
+ }
+
+ exec_argvlen = asprintf (&exec_argv, "/%s%c%s%c",
+ initname, '\0', diskfs_boot_flags, '\0');
+ if (initname != default_init)
+ free (initnamebuf);
+ initname = exec_argv + 1;
+ }
+
+ err = dir_lookup (root_pt, initname, O_READ, 0,
+ &retry, pathbuf, &startup_pt);
+ if (err)
+ {
+ printf ("\nCannot find startup program `%s': %s\n",
+ initname, strerror (err));
+ fflush (stdout);
+ free (exec_argv);
+ goto prompt;
+ }
+ assert (retry == FS_RETRY_NORMAL);
+ assert (pathbuf[0] == '\0');
+
+ err = ports_create_port (diskfs_initboot_class, diskfs_port_bucket,
+ sizeof (struct port_info), &bootinfo);
+ assert_perror (err);
+ bootpt = ports_get_right (bootinfo);
+ mach_port_insert_right (mach_task_self (), bootpt, bootpt,
+ MACH_MSG_TYPE_MAKE_SEND);
+ ports_port_deref (bootinfo);
+
+ portarray[INIT_PORT_CRDIR] = root_pt;
+ portarray[INIT_PORT_CWDIR] = root_pt;
+ portarray[INIT_PORT_AUTH] = MACH_PORT_NULL;
+ portarray[INIT_PORT_PROC] = MACH_PORT_NULL;
+ portarray[INIT_PORT_CTTYID] = MACH_PORT_NULL;
+ portarray[INIT_PORT_BOOTSTRAP] = bootpt;
+
+ fdarray[0] = fdarray[1] = fdarray[2] = get_console (); /* XXX */
+
+ err = argz_create (environ, &exec_env, &exec_envlen);
+ assert_perror (err);
+
+ err = task_create (mach_task_self (), 0, &newt);
+ assert_perror (err);
+ if (index (diskfs_boot_flags, 'd'))
+ {
+ printf ("pausing for %s...\n", exec_argv);
+ getc (stdin);
+ }
+ printf (" %s", basename (exec_argv));
+ fflush (stdout);
+ err = exec_exec (diskfs_exec, startup_pt, MACH_MSG_TYPE_COPY_SEND,
+ newt, 0, exec_argv, exec_argvlen, exec_env, exec_envlen,
+ fdarray, MACH_MSG_TYPE_COPY_SEND, 3,
+ portarray, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
+ /* Supply no intarray, since we have no info for it.
+ With none supplied, it will use the defaults. */
+ NULL, 0, 0, 0, 0, 0);
+ free (exec_argv);
+ free (exec_env);
+ mach_port_deallocate (mach_task_self (), root_pt);
+ mach_port_deallocate (mach_task_self (), startup_pt);
+ mach_port_deallocate (mach_task_self (), bootpt);
+ assert_perror (err);
+
+ /* Cache the exec server port for file_exec to use. */
+ _hurd_port_set (&_diskfs_exec_portcell, diskfs_exec);
+}
+
+/* We look like an execserver to the execserver itself; it makes this
+ call (as does any task) to get its state. We can't give it all of
+ its ports (we'll provide those with a later call to exec_init). */
+kern_return_t
+diskfs_S_exec_startup_get_info (mach_port_t port,
+ vm_address_t *user_entry,
+ vm_address_t *phdr_data,
+ vm_size_t *phdr_size,
+ vm_address_t *base_addr,
+ vm_size_t *stack_size,
+ int *flags,
+ char **argvP,
+ mach_msg_type_number_t *argvlen,
+ char **envpP __attribute__ ((unused)),
+ mach_msg_type_number_t *envplen,
+ mach_port_t **dtableP,
+ mach_msg_type_name_t *dtablepoly,
+ mach_msg_type_number_t *dtablelen,
+ mach_port_t **portarrayP,
+ mach_msg_type_name_t *portarraypoly,
+ mach_msg_type_number_t *portarraylen,
+ int **intarrayP,
+ mach_msg_type_number_t *intarraylen)
+{
+ error_t err;
+ mach_port_t *portarray, *dtable;
+ mach_port_t rootport;
+ struct ufsport *upt;
+ struct protid *rootpi;
+
+ if (!(upt = ports_lookup_port (diskfs_port_bucket, port,
+ diskfs_execboot_class)))
+ return EOPNOTSUPP;
+
+ *user_entry = 0;
+ *phdr_data = *base_addr = 0;
+ *phdr_size = *stack_size = 0;
+
+ /* We have no args for it. Tell it to look on its stack
+ for the args placed there by the boot loader. */
+ *argvlen = *envplen = 0;
+ *flags = EXEC_STACK_ARGS;
+
+ if (*portarraylen < INIT_PORT_MAX)
+ *portarrayP = mmap (0, INIT_PORT_MAX * sizeof (mach_port_t),
+ PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ portarray = *portarrayP;
+ *portarraylen = INIT_PORT_MAX;
+
+ if (*dtablelen < 3)
+ *dtableP = mmap (0, 3 * sizeof (mach_port_t), PROT_READ|PROT_WRITE,
+ MAP_ANON, 0, 0);
+ dtable = *dtableP;
+ *dtablelen = 3;
+ dtable[0] = dtable[1] = dtable[2] = get_console (); /* XXX */
+
+ *intarrayP = NULL;
+ *intarraylen = 0;
+
+ err = diskfs_create_protid (diskfs_make_peropen (diskfs_root_node,
+ O_READ | O_EXEC, 0),
+ 0, &rootpi);
+ assert_perror (err);
+ rootport = ports_get_right (rootpi);
+ ports_port_deref (rootpi);
+ portarray[INIT_PORT_CWDIR] = rootport;
+ portarray[INIT_PORT_CRDIR] = rootport;
+ portarray[INIT_PORT_AUTH] = MACH_PORT_NULL;
+ portarray[INIT_PORT_PROC] = MACH_PORT_NULL;
+ portarray[INIT_PORT_CTTYID] = MACH_PORT_NULL;
+ portarray[INIT_PORT_BOOTSTRAP] = port; /* use the same port */
+
+ *portarraypoly = MACH_MSG_TYPE_MAKE_SEND;
+
+ *dtablepoly = MACH_MSG_TYPE_COPY_SEND;
+
+ ports_port_deref (upt);
+ return 0;
+}
+
+/* Called by S_fsys_startup for execserver bootstrap. The execserver
+ is able to function without a real node, hence this fraud. */
+error_t
+diskfs_execboot_fsys_startup (mach_port_t port, int flags,
+ mach_port_t ctl,
+ mach_port_t *real,
+ mach_msg_type_name_t *realpoly)
+{
+ error_t err;
+ string_t pathbuf;
+ enum retry_type retry;
+ struct port_info *pt;
+ struct protid *rootpi;
+ mach_port_t rootport;
+
+ if (!(pt = ports_lookup_port (diskfs_port_bucket, port,
+ diskfs_execboot_class)))
+ return EOPNOTSUPP;
+
+ err = diskfs_create_protid (diskfs_make_peropen (diskfs_root_node, flags, 0),
+ 0, &rootpi);
+ assert_perror (err);
+ rootport = ports_get_right (rootpi);
+ mach_port_insert_right (mach_task_self (), rootport, rootport,
+ MACH_MSG_TYPE_MAKE_SEND);
+ ports_port_deref (rootpi);
+
+ err = dir_lookup (rootport, _SERVERS_EXEC, flags|O_NOTRANS, 0,
+ &retry, pathbuf, real);
+ assert_perror (err);
+ assert (retry == FS_RETRY_NORMAL);
+ assert (pathbuf[0] == '\0');
+ *realpoly = MACH_MSG_TYPE_MOVE_SEND;
+
+ mach_port_deallocate (mach_task_self (), rootport);
+
+ diskfs_exec_ctl = ctl;
+
+ mutex_lock (&execstartlock);
+ condition_signal (&execstarted);
+ mutex_unlock (&execstartlock);
+ ports_port_deref (pt);
+ return 0;
+}
+
+/* Called by init to get the privileged ports as described
+ in <hurd/fsys.defs>. */
+kern_return_t
+diskfs_S_fsys_getpriv (mach_port_t port,
+ mach_port_t reply, mach_msg_type_name_t reply_type,
+ mach_port_t *host_priv, mach_msg_type_name_t *hp_type,
+ mach_port_t *dev_master, mach_msg_type_name_t *dm_type,
+ mach_port_t *fstask, mach_msg_type_name_t *task_type)
+{
+ error_t err;
+ struct port_info *init_bootstrap_port =
+ ports_lookup_port (diskfs_port_bucket, port, diskfs_initboot_class);
+
+ if (!init_bootstrap_port)
+ return EOPNOTSUPP;
+
+ err = get_privileged_ports (host_priv, dev_master);
+ if (!err)
+ {
+ *fstask = mach_task_self ();
+ *hp_type = *dm_type = MACH_MSG_TYPE_MOVE_SEND;
+ *task_type = MACH_MSG_TYPE_COPY_SEND;
+ }
+
+ ports_port_deref (init_bootstrap_port);
+
+ return err;
+}
+
+/* Called by init to give us ports to the procserver and authserver as
+ described in <hurd/fsys.defs>. */
+kern_return_t
+diskfs_S_fsys_init (mach_port_t port,
+ mach_port_t reply, mach_msg_type_name_t replytype,
+ mach_port_t procserver,
+ mach_port_t authhandle)
+{
+ struct port_infe *pt;
+ static int initdone = 0;
+ mach_port_t host, startup;
+ error_t err;
+ mach_port_t root_pt;
+ struct protid *rootpi;
+
+ pt = ports_lookup_port (diskfs_port_bucket, port, diskfs_initboot_class);
+ if (!pt)
+ return EOPNOTSUPP;
+ ports_port_deref (pt);
+ if (initdone)
+ return EOPNOTSUPP;
+ initdone = 1;
+
+ /* init is single-threaded, so we must reply to its RPC before doing
+ anything which might attempt to send an RPC to init. */
+ fsys_init_reply (reply, replytype, 0);
+
+ /* Allocate our references here; _hurd_init will consume a reference
+ for the library itself. */
+ err = mach_port_mod_refs (mach_task_self (),
+ procserver, MACH_PORT_RIGHT_SEND, +1);
+ assert_perror (err);
+ err = mach_port_mod_refs (mach_task_self (),
+ authhandle, MACH_PORT_RIGHT_SEND, +1);
+ assert_perror (err);
+
+ if (diskfs_auth_server_port != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), diskfs_auth_server_port);
+ diskfs_auth_server_port = authhandle;
+
+ if (diskfs_exec_server_task != MACH_PORT_NULL)
+ {
+ process_t execprocess;
+ err = proc_task2proc (procserver, diskfs_exec_server_task, &execprocess);
+ assert_perror (err);
+
+ /* Declare that the exec server is our child. */
+ proc_child (procserver, diskfs_exec_server_task);
+ proc_mark_exec (execprocess);
+
+ /* Don't start this until now so that exec is fully authenticated
+ with proc. */
+ HURD_PORT_USE (&_diskfs_exec_portcell,
+ exec_init (port, authhandle,
+ execprocess, MACH_MSG_TYPE_COPY_SEND));
+ mach_port_deallocate (mach_task_self (), execprocess);
+
+ /* We don't need this anymore. */
+ mach_port_deallocate (mach_task_self (), diskfs_exec_server_task);
+ diskfs_exec_server_task = MACH_PORT_NULL;
+ }
+ else
+ {
+ mach_port_t bootstrap;
+ process_t parent_proc;
+
+ assert (parent_task != MACH_PORT_NULL);
+
+ /* Tell the proc server that our parent task is our child. This
+ makes the process hierarchy fail to represent the real order of
+ who created whom, but it sets the owner and authentication ids to
+ root. It doesn't really matter that the parent fs task be
+ authenticated, but the exec server needs to be authenticated to
+ complete the boot handshakes with init. The exec server gets its
+ privilege by the parent fs doing proc_child (code above) after
+ we send it fsys_init (below). */
+
+ err = proc_child (procserver, parent_task);
+ assert_perror (err);
+
+ /* Get the parent's proc server port so we can send it in the fsys_init
+ RPC just as init would. */
+ err = proc_task2proc (procserver, parent_task, &parent_proc);
+ assert_perror (err);
+
+ /* We don't need this anymore. */
+ mach_port_deallocate (mach_task_self (), parent_task);
+ parent_task = MACH_PORT_NULL;
+
+ proc_mark_exec (parent_proc);
+
+ /* Give our parent (the real bootstrap filesystem) an fsys_init
+ RPC of its own, as init would have sent it. */
+ err = task_get_bootstrap_port (mach_task_self (), &bootstrap);
+ assert_perror (err);
+ err = fsys_init (bootstrap, parent_proc, MACH_MSG_TYPE_MOVE_SEND,
+ authhandle);
+ mach_port_deallocate (mach_task_self (), bootstrap);
+ assert_perror (err);
+ }
+
+ /* Get a port to the root directory to put in the library's
+ data structures. */
+ err = diskfs_create_protid (diskfs_make_peropen (diskfs_root_node,
+ O_READ|O_EXEC, 0),
+ 0, &rootpi);
+ assert_perror (err);
+ root_pt = ports_get_right (rootpi);
+ ports_port_deref (rootpi);
+
+ /* We need two send rights, for the crdir and cwdir slots. */
+ mach_port_insert_right (mach_task_self (), root_pt, root_pt,
+ MACH_MSG_TYPE_MAKE_SEND);
+ mach_port_mod_refs (mach_task_self (), root_pt,
+ MACH_PORT_RIGHT_SEND, +1);
+
+ if (_hurd_ports)
+ {
+ /* We already have a portarray, because somebody responded to
+ exec_startup on our initial bootstrap port, even though we are
+ supposedly the bootstrap program. The losing `boot' that runs on
+ UX does this. */
+ _hurd_port_set (&_hurd_ports[INIT_PORT_PROC], procserver); /* Consume. */
+ _hurd_port_set (&_hurd_ports[INIT_PORT_AUTH], authhandle); /* Consume. */
+ _hurd_port_set (&_hurd_ports[INIT_PORT_CRDIR], root_pt); /* Consume. */
+ _hurd_port_set (&_hurd_ports[INIT_PORT_CWDIR], root_pt); /* Consume. */
+ _hurd_proc_init (diskfs_argv, NULL, 0);
+ }
+ else
+ {
+ /* We have no portarray or intarray because there was
+ no exec_startup data; _hurd_init was never called.
+ We now have the crucial ports, so create a portarray
+ and call _hurd_init. */
+ mach_port_t *portarray;
+ unsigned int i;
+ portarray = mmap (0, INIT_PORT_MAX * sizeof *portarray,
+ PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ if (MACH_PORT_NULL != (mach_port_t) 0)
+ for (i = 0; i < INIT_PORT_MAX; ++i)
+ portarray[i] = MACH_PORT_NULL;
+ portarray[INIT_PORT_PROC] = procserver;
+ portarray[INIT_PORT_AUTH] = authhandle;
+ portarray[INIT_PORT_CRDIR] = root_pt;
+ portarray[INIT_PORT_CWDIR] = root_pt;
+ _hurd_init (0, diskfs_argv, portarray, INIT_PORT_MAX, NULL, 0);
+ }
+
+ err = get_privileged_ports (&host, 0);
+ if (err)
+ return err;
+
+ proc_register_version (procserver, host, diskfs_server_name, "",
+ diskfs_server_version);
+
+ err = proc_getmsgport (procserver, 1, &startup);
+ if (!err)
+ {
+ startup_essential_task (startup, mach_task_self (), MACH_PORT_NULL,
+ diskfs_server_name, host);
+ mach_port_deallocate (mach_task_self (), startup);
+ }
+
+ mach_port_deallocate (mach_task_self (), host);
+ mach_port_deallocate (mach_task_self (), procserver);
+
+ _diskfs_init_completed ();
+
+ return MIG_NO_REPLY; /* Already replied above. */
+}
+
+/* Start the execserver running (when we are a bootstrap filesystem). */
+static void
+start_execserver (void)
+{
+ error_t err;
+ mach_port_t right;
+ extern task_t diskfs_exec_server_task; /* Set in opts-std-startup.c. */
+ struct port_info *execboot_info;
+
+ assert (diskfs_exec_server_task != MACH_PORT_NULL);
+
+ err = ports_create_port (diskfs_execboot_class, diskfs_port_bucket,
+ sizeof (struct port_info), &execboot_info);
+ assert_perror (err);
+ right = ports_get_right (execboot_info);
+ mach_port_insert_right (mach_task_self (), right,
+ right, MACH_MSG_TYPE_MAKE_SEND);
+ ports_port_deref (execboot_info);
+ task_set_special_port (diskfs_exec_server_task, TASK_BOOTSTRAP_PORT, right);
+ mach_port_deallocate (mach_task_self (), right);
+
+ if (index (diskfs_boot_flags, 'd'))
+ {
+ printf ("pausing for exec\n");
+ getc (stdin);
+ }
+ task_resume (diskfs_exec_server_task);
+
+ printf (" exec");
+ fflush (stdout);
+}
diff --git a/libdiskfs/conch-fetch.c b/libdiskfs/conch-fetch.c
new file mode 100644
index 00000000..2c5d0fd8
--- /dev/null
+++ b/libdiskfs/conch-fetch.c
@@ -0,0 +1,72 @@
+/*
+ Copyright (C) 1994, 1995, 1996, 1999 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include <hurd/iohelp.h>
+
+/* Update our copy of the relevant fields from a shared page. Callers
+ must have the share lock on the shared page as well as the inode
+ toplock. This is called by the conch management facilities of
+ libioserver as well as by us. */
+void
+iohelp_fetch_shared_data (void *arg)
+{
+ struct protid *cred = arg;
+ int mod = 0;
+
+ /* Don't allow the user to grow the file past the alloc size. */
+ if (cred->mapped->file_size > cred->po->np->allocsize)
+ cred->mapped->file_size = cred->po->np->allocsize;
+
+ /* Don't allow the user to truncate the file this way. */
+ if (cred->mapped->file_size < cred->po->np->dn_stat.st_size)
+ cred->mapped->file_size = cred->po->np->dn_stat.st_size;
+ else if (cred->po->np->dn_stat.st_size != cred->mapped->file_size)
+ {
+ /* The user can validly set the size, but block the attempt
+ if we are readonly. */
+ if (diskfs_check_readonly ())
+ cred->mapped->file_size = cred->po->np->dn_stat.st_size;
+ else
+ {
+ cred->po->np->dn_stat.st_size = cred->mapped->file_size;
+ cred->po->np->dn_set_ctime = 1;
+ mod = 1;
+ }
+ }
+
+ cred->po->filepointer = cred->mapped->xx_file_pointer;
+
+ if (!diskfs_check_readonly ())
+ {
+ if (cred->mapped->written)
+ {
+ cred->po->np->dn_set_mtime = 1;
+ mod = 1;
+ }
+ if (cred->mapped->accessed && ! _diskfs_noatime)
+ {
+ cred->po->np->dn_set_atime = 1;
+ mod = 1;
+ }
+ }
+ cred->mapped->written = 0;
+ cred->mapped->accessed = 0;
+ if (diskfs_synchronous && mod)
+ diskfs_node_update (cred->po->np, 1);
+}
+
diff --git a/libdiskfs/conch-set.c b/libdiskfs/conch-set.c
new file mode 100644
index 00000000..86d3905d
--- /dev/null
+++ b/libdiskfs/conch-set.c
@@ -0,0 +1,49 @@
+/*
+ Copyright (C) 1994, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include <hurd/iohelp.h>
+#include <fcntl.h>
+
+/* Write current values into the shared page. Callers must have the
+ share lock on the shared page, as well as the inode toplock.
+ This is called by the conch management facilities of libioserver
+ as well as by us. */
+void
+iohelp_put_shared_data (void *arg)
+{
+ struct protid *cred = arg;
+
+ cred->mapped->append_mode = (cred->po->openstat & O_APPEND);
+ cred->mapped->eof_notify = 0;
+ cred->mapped->do_sigio = (cred->po->openstat & O_FSYNC);
+ cred->mapped->use_file_size = 1;
+ cred->mapped->use_read_size = 0;
+ cred->mapped->optimal_transfer_size = cred->po->np->dn_stat.st_blksize;
+ cred->mapped->seekable = 1;
+ cred->mapped->use_prenotify_size = 1;
+ cred->mapped->use_postnotify_size = 0;
+ cred->mapped->use_readnotify_size = 0;
+ cred->mapped->prenotify_size = cred->po->np->allocsize;
+
+ cred->mapped->xx_file_pointer = cred->po->filepointer;
+ cred->mapped->rd_file_pointer = -1;
+ cred->mapped->wr_file_pointer = -1;
+ cred->mapped->file_size = cred->po->np->dn_stat.st_size;
+ cred->mapped->written = 0;
+ cred->mapped->accessed = 0;
+}
diff --git a/libdiskfs/console.c b/libdiskfs/console.c
new file mode 100644
index 00000000..a7113ace
--- /dev/null
+++ b/libdiskfs/console.c
@@ -0,0 +1,72 @@
+/* Redirect stdio to the console if possible
+
+ Copyright (C) 1995, 96, 98, 99 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <mach/mach.h>
+#include <device/device.h>
+#include <hurd.h>
+
+#include "priv.h"
+
+/* Make sure errors go somewhere reasonable. */
+void
+diskfs_console_stdio ()
+{
+ if (getpid () > 0)
+ {
+ if (write (2, "", 0) == 0)
+ /* We have a working stderr from our parent (e.g. settrans -a).
+ Just use it. */
+ dup2 (2, 1);
+ else
+ {
+ int fd = open ("/dev/console", O_RDWR);
+
+ dup2 (fd, 0);
+ dup2 (fd, 1);
+ dup2 (fd, 2);
+ if (fd > 2)
+ close (fd);
+ }
+ }
+ else
+ {
+ mach_port_t dev, cons;
+ error_t err;
+ if (diskfs_boot_flags)
+ _diskfs_boot_privports ();
+ err = get_privileged_ports (NULL, &dev);
+ assert_perror (err);
+ err = device_open (dev, D_READ|D_WRITE, "console", &cons);
+ mach_port_deallocate (mach_task_self (), dev);
+ assert_perror (err);
+ stdin = mach_open_devstream (cons, "r");
+ stdout = stderr = mach_open_devstream (cons, "w");
+ mach_port_deallocate (mach_task_self (), cons);
+ }
+}
diff --git a/libdiskfs/dead-name.c b/libdiskfs/dead-name.c
new file mode 100644
index 00000000..f5b641d2
--- /dev/null
+++ b/libdiskfs/dead-name.c
@@ -0,0 +1,45 @@
+/* Handle dead name notifications on ports
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/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. */
+
+#include "priv.h"
+
+void
+ports_dead_name (void *notify, mach_port_t dead_name)
+{
+ struct protid *pi = ports_lookup_port (diskfs_port_bucket, dead_name,
+ diskfs_protid_class);
+ struct node *np;
+
+ if (pi)
+ {
+ np = pi->po->np;
+ mutex_lock (&np->lock);
+ if (dead_name == np->sockaddr)
+ {
+ mach_port_deallocate (mach_task_self (), np->sockaddr);
+ np->sockaddr = MACH_PORT_NULL;
+ diskfs_nput (np);
+ }
+ else
+ mutex_unlock (&np->lock);
+ }
+
+ ports_interrupt_notified_rpcs (notify, dead_name, MACH_NOTIFY_DEAD_NAME);
+}
diff --git a/libdiskfs/demuxer.c b/libdiskfs/demuxer.c
new file mode 100644
index 00000000..51234cdf
--- /dev/null
+++ b/libdiskfs/demuxer.c
@@ -0,0 +1,42 @@
+/* Demultiplexer for diskfs library
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+int
+diskfs_demuxer (mach_msg_header_t *inp,
+ mach_msg_header_t *outp)
+{
+ int diskfs_fs_server (mach_msg_header_t *, mach_msg_header_t *);
+ int diskfs_io_server (mach_msg_header_t *, mach_msg_header_t *);
+ int diskfs_fsys_server (mach_msg_header_t *, mach_msg_header_t *);
+ int diskfs_exec_startup_server (mach_msg_header_t *, mach_msg_header_t *);
+ int diskfs_ifsock_server (mach_msg_header_t *, mach_msg_header_t *);
+ int diskfs_startup_notify_server (mach_msg_header_t *, mach_msg_header_t *);
+
+
+ return (diskfs_io_server (inp, outp)
+ || diskfs_fs_server (inp, outp)
+ || ports_notify_server (inp, outp)
+ || diskfs_fsys_server (inp, outp)
+ || diskfs_exec_startup_server (inp, outp)
+ || ports_interrupt_server (inp, outp)
+ || (diskfs_shortcut_ifsock ? diskfs_ifsock_server (inp, outp) : 0)
+ || diskfs_startup_notify_server (inp, outp));
+}
+
+
diff --git a/libdiskfs/dir-chg.c b/libdiskfs/dir-chg.c
new file mode 100644
index 00000000..16eb26f4
--- /dev/null
+++ b/libdiskfs/dir-chg.c
@@ -0,0 +1,75 @@
+/* Notifications of directory changes.
+ Copyright (C) 1994, 1995, 1998 Free Software Foundation, Inc.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+#include "ourfs_notify_U.h"
+
+kern_return_t
+diskfs_S_dir_notice_changes (struct protid *cred,
+ mach_port_t notify)
+{
+ error_t err;
+ struct modreq *req;
+ struct node *np;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ np = cred->po->np;
+ mutex_lock (&np->lock);
+ if (!S_ISDIR (np->dn_stat.st_mode))
+ {
+ mutex_unlock (&np->lock);
+ return ENOTDIR;
+ }
+ err = nowait_dir_changed (notify, DIR_CHANGED_NULL, "");
+ if (err)
+ {
+ mutex_unlock (&np->lock);
+ return err;
+ }
+ req = malloc (sizeof (struct modreq));
+ req->port = notify;
+ req->next = np->dirmod_reqs;
+ np->dirmod_reqs = req;
+ mutex_unlock (&np->lock);
+ return 0;
+}
+
+void
+diskfs_notice_dirchange (struct node *dp, enum dir_changed_type type,
+ const char *name)
+{
+ error_t err;
+ struct modreq **preq;
+
+ preq = &dp->dirmod_reqs;
+ while (*preq)
+ {
+ struct modreq *req = *preq;
+ err = nowait_dir_changed (req->port, type, name);
+ if (err)
+ { /* remove notify port */
+ *preq = req->next;
+ mach_port_deallocate (mach_task_self (), req->port);
+ free (req);
+ }
+ else
+ preq = &req->next;
+ }
+}
diff --git a/libdiskfs/dir-clear.c b/libdiskfs/dir-clear.c
new file mode 100644
index 00000000..7cf32358
--- /dev/null
+++ b/libdiskfs/dir-clear.c
@@ -0,0 +1,70 @@
+/*
+ Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+/* Clear the `.' and `..' entries from directory DP. Its parent is PDP,
+ and the user responsible for this is identified by CRED. Both
+ directories must be locked. */
+error_t
+diskfs_clear_directory (struct node *dp,
+ struct node *pdp,
+ struct protid *cred)
+{
+ error_t err;
+ struct dirstat *ds = alloca (diskfs_dirstat_size);
+ struct node *np;
+
+ /* Find and remove the `.' entry. */
+ err = diskfs_lookup (dp, ".", REMOVE, &np, ds, cred);
+ assert (err != ENOENT);
+ if (!err)
+ {
+ assert (np == dp);
+ err = diskfs_dirremove (dp, np, ".", ds);
+ diskfs_nrele (np);
+ }
+ else
+ diskfs_drop_dirstat (dp, ds);
+ if (err)
+ return err;
+
+ /* Decrement the link count */
+ dp->dn_stat.st_nlink--;
+ dp->dn_set_ctime = 1;
+
+ /* Find and remove the `..' entry. */
+ err = diskfs_lookup (dp, "..", REMOVE | SPEC_DOTDOT, &np, ds, cred);
+ assert (err != ENOENT);
+ if (!err)
+ {
+ assert (np == pdp);
+ err = diskfs_dirremove (dp, np, "..", ds);
+ }
+ else
+ diskfs_drop_dirstat (dp, ds);
+ if (err)
+ return err;
+
+ /* Decrement the link count on the parent */
+ pdp->dn_stat.st_nlink--;
+ pdp->dn_set_ctime = 1;
+
+ diskfs_truncate (dp, 0);
+
+ return err;
+}
diff --git a/libdiskfs/dir-init.c b/libdiskfs/dir-init.c
new file mode 100644
index 00000000..2cba3a4b
--- /dev/null
+++ b/libdiskfs/dir-init.c
@@ -0,0 +1,68 @@
+/*
+ Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+/* Locked node DP is a new directory; add whatever links are necessary
+ to give it structure; its parent is the (locked) node PDP.
+ This routine may not call diskfs_lookup on PDP. The new directory
+ must be clear within the meaning of diskfs_dirempty.
+ CRED identifies the user making the call. */
+error_t
+diskfs_init_dir (struct node *dp, struct node *pdp, struct protid *cred)
+{
+ struct dirstat *ds = alloca (diskfs_dirstat_size);
+ struct node *foo;
+ error_t err;
+
+ /* Fabricate a protid that represents root credentials. */
+ static uid_t zero = 0;
+ static struct idvec vec = {&zero, 1, 1};
+ static struct iouser user = {&vec, &vec, 0};
+ struct protid lookupcred = {{0, 0, 0, 0}, &user, cred->po, 0, 0};
+
+ /* New links */
+ if (pdp->dn_stat.st_nlink == diskfs_link_max - 1)
+ return EMLINK;
+
+ dp->dn_stat.st_nlink++; /* for `.' */
+ dp->dn_set_ctime = 1;
+ err = diskfs_lookup (dp, ".", CREATE, &foo, ds, &lookupcred);
+ assert (err == ENOENT);
+ err = diskfs_direnter (dp, ".", dp, ds, cred);
+ if (err)
+ {
+ dp->dn_stat.st_nlink--;
+ dp->dn_set_ctime = 1;
+ return err;
+ }
+
+ pdp->dn_stat.st_nlink++; /* for `..' */
+ pdp->dn_set_ctime = 1;
+ err = diskfs_lookup (dp, "..", CREATE, &foo, ds, &lookupcred);
+ assert (err == ENOENT);
+ err = diskfs_direnter (dp, "..", pdp, ds, cred);
+ if (err)
+ {
+ pdp->dn_stat.st_nlink--;
+ pdp->dn_set_ctime = 1;
+ return err;
+ }
+
+ diskfs_node_update (dp, 1);
+ return 0;
+}
diff --git a/libdiskfs/dir-link.c b/libdiskfs/dir-link.c
new file mode 100644
index 00000000..7cc88633
--- /dev/null
+++ b/libdiskfs/dir-link.c
@@ -0,0 +1,133 @@
+/* libdiskfs implementation of fs.defs: dir_link
+ Copyright (C) 1992,93,94,95,96,97,99 Free Software Foundation, Inc.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+
+/* Implement dir_link as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_dir_link (struct protid *dircred,
+ struct protid *filecred,
+ char *name,
+ int excl)
+{
+ struct node *np; /* node being linked */
+ struct node *tnp; /* node being deleted implicitly */
+ struct node *dnp; /* directory of new entry */
+ struct dirstat *ds = alloca (diskfs_dirstat_size);
+ error_t error;
+
+ if (!dircred)
+ return EOPNOTSUPP;
+
+ if (diskfs_check_readonly ())
+ return EROFS;
+
+ if (!filecred)
+ return EXDEV;
+
+ np = filecred->po->np;
+ mutex_lock (&np->lock);
+ if (S_ISDIR (np->dn_stat.st_mode))
+ {
+ mutex_unlock (&np->lock);
+ return EISDIR;
+ }
+ mutex_unlock (&np->lock);
+
+ dnp = dircred->po->np;
+ mutex_lock (&dnp->lock);
+
+ /* Lookup new location */
+ error = diskfs_lookup (dnp, name, RENAME, &tnp, ds, dircred);
+ if (!error && excl)
+ {
+ error = EEXIST;
+ diskfs_nput (tnp);
+ }
+ if (error && error != ENOENT)
+ {
+ if (error == EAGAIN)
+ error = EINVAL;
+ diskfs_drop_dirstat (dnp, ds);
+ mutex_unlock (&dnp->lock);
+ return error;
+ }
+
+ if (np == tnp)
+ {
+ diskfs_drop_dirstat (dnp, ds);
+ mutex_unlock (&dnp->lock);
+ mutex_unlock (&tnp->lock);
+ mach_port_deallocate (mach_task_self (), filecred->pi.port_right);
+ return 0;
+ }
+
+ if (tnp && S_ISDIR (tnp->dn_stat.st_mode))
+ {
+ diskfs_drop_dirstat (dnp, ds);
+ mutex_unlock (&dnp->lock);
+ mutex_unlock (&tnp->lock);
+ return EISDIR;
+ }
+
+ /* Create new entry for NP */
+
+ /* This is safe because NP is not a directory (thus not DNP) and
+ not TNP and is a leaf. */
+ mutex_lock (&np->lock);
+
+ /* Increment link count */
+ if (np->dn_stat.st_nlink == diskfs_link_max - 1)
+ {
+ diskfs_drop_dirstat (dnp, ds);
+ mutex_unlock (&np->lock);
+ mutex_unlock (&dnp->lock);
+ return EMLINK;
+ }
+ np->dn_stat.st_nlink++;
+ np->dn_set_ctime = 1;
+ diskfs_node_update (np, 1);
+
+ /* Attach it */
+ if (tnp)
+ {
+ assert (!excl);
+ error = diskfs_dirrewrite (dnp, tnp, np, name, ds);
+ if (!error)
+ {
+ /* Deallocate link on TNP */
+ tnp->dn_stat.st_nlink--;
+ tnp->dn_set_ctime = 1;
+ if (diskfs_synchronous)
+ diskfs_node_update (tnp, 1);
+ }
+ diskfs_nput (tnp);
+ }
+ else
+ error = diskfs_direnter (dnp, name, np, ds, dircred);
+
+ if (diskfs_synchronous)
+ diskfs_node_update (dnp, 1);
+
+ mutex_unlock (&dnp->lock);
+ mutex_unlock (&np->lock);
+ if (!error)
+ /* MiG won't do this for us, which it ought to. */
+ mach_port_deallocate (mach_task_self (), filecred->pi.port_right);
+ return error;
+}
diff --git a/libdiskfs/dir-lookup.c b/libdiskfs/dir-lookup.c
new file mode 100644
index 00000000..91e9ea48
--- /dev/null
+++ b/libdiskfs/dir-lookup.c
@@ -0,0 +1,465 @@
+/* libdiskfs implementation of fs.defs:dir_lookup
+ Copyright (C) 1992,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/file.h>
+#include <hurd/fsys.h>
+#include <hurd/paths.h>
+
+#include "priv.h"
+#include "fs_S.h"
+
+/* Implement dir_lookup as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_dir_lookup (struct protid *dircred,
+ char *path,
+ int flags,
+ mode_t mode,
+ enum retry_type *retry,
+ char *retryname,
+ file_t *returned_port,
+ mach_msg_type_name_t *returned_port_poly)
+{
+ struct node *dnp;
+ struct node *np;
+ int nsymlink = 0;
+ char *nextname;
+ int nextnamelen;
+ error_t error = 0;
+ char *pathbuf = 0;
+ int pathbuflen = 0;
+ int newnamelen;
+ int create, excl;
+ int lastcomp = 0;
+ int newnode = 0;
+ struct dirstat *ds = 0;
+ int mustbedir = 0;
+ int amt;
+ int type;
+ struct protid *newpi;
+
+ if (!dircred)
+ return EOPNOTSUPP;
+
+ flags &= O_HURD;
+
+ create = (flags & O_CREAT);
+ excl = (flags & O_EXCL);
+
+ /* Skip leading slashes */
+ while (path[0] == '/')
+ path++;
+
+ *returned_port_poly = MACH_MSG_TYPE_MAKE_SEND;
+ *retry = FS_RETRY_NORMAL;
+ retryname[0] = '\0';
+
+ if (path[0] == '\0')
+ {
+ /* Set things up in the state expected by the code from gotit: on. */
+ dnp = 0;
+ np = dircred->po->np;
+ mutex_lock (&np->lock);
+ diskfs_nref (np);
+ goto gotit;
+ }
+
+ dnp = dircred->po->np;
+
+ mutex_lock (&dnp->lock);
+ np = 0;
+
+ diskfs_nref (dnp); /* acquire a reference for later diskfs_nput */
+
+ do
+ {
+ assert (!lastcomp);
+
+ /* Find the name of the next pathname component */
+ nextname = index (path, '/');
+
+ 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;
+
+ /* diskfs_lookup the next pathname component */
+ if (lastcomp && create)
+ {
+ assert (!ds);
+ ds = alloca (diskfs_dirstat_size);
+ error = diskfs_lookup (dnp, path, CREATE, &np, ds, dircred);
+ }
+ else
+ error = diskfs_lookup (dnp, path, LOOKUP, &np, 0, dircred);
+
+ if (lastcomp && create && excl && (!error || error == EAGAIN))
+ error = EEXIST;
+
+ /* If we get an error we're done */
+ if (error == EAGAIN)
+ {
+ if (dnp == dircred->po->shadow_root)
+ /* We're at the root of a shadow tree. */
+ {
+ if (dircred->po->shadow_root_parent == MACH_PORT_NULL)
+ {
+ /* This is a shadow root with no parent, meaning
+ we should treat it as a virtual root disconnected
+ from its real .. directory. */
+ error = 0;
+ np = dnp;
+ diskfs_nref (np);
+ }
+ else
+ {
+ /* Punt the client up to the shadow root parent. */
+ *retry = FS_RETRY_REAUTH;
+ *returned_port = dircred->po->shadow_root_parent;
+ *returned_port_poly = MACH_MSG_TYPE_COPY_SEND;
+ if (! lastcomp)
+ strcpy (retryname, nextname);
+ error = 0;
+ goto out;
+ }
+ }
+ else if (dircred->po->root_parent != MACH_PORT_NULL)
+ /* We're at a real translator root; even if DIRCRED->po has a
+ shadow root, we can get here if its in a directory that was
+ renamed out from under it... */
+ {
+ *retry = FS_RETRY_REAUTH;
+ *returned_port = dircred->po->root_parent;
+ *returned_port_poly = MACH_MSG_TYPE_COPY_SEND;
+ if (!lastcomp)
+ strcpy (retryname, nextname);
+ error = 0;
+ goto out;
+ }
+ else
+ /* We're at a REAL root, as in there's no way up from here. */
+ {
+ error = 0;
+ np = dnp;
+ diskfs_nref (np);
+ }
+ }
+
+ /* Create the new node if necessary */
+ if (lastcomp && create)
+ {
+ if (error == ENOENT)
+ {
+ mode &= ~(S_IFMT | S_ISPARE | S_ISVTX);
+ mode |= S_IFREG;
+ error = diskfs_create_node (dnp, path, mode, &np, dircred, ds);
+ if (diskfs_synchronous)
+ {
+ diskfs_file_update (dnp, 1);
+ diskfs_file_update (np, 1);
+ }
+ newnode = 1;
+ }
+ else
+ diskfs_drop_dirstat (dnp, ds);
+ }
+
+ if (error)
+ goto out;
+
+ /* If this is translated, start the translator (if necessary)
+ and return. */
+ if ((((flags & O_NOTRANS) == 0) || !lastcomp)
+ && ((np->dn_stat.st_mode & S_IPTRANS)
+ || S_ISFIFO (np->dn_stat.st_mode)
+ || S_ISCHR (np->dn_stat.st_mode)
+ || S_ISBLK (np->dn_stat.st_mode)
+ || fshelp_translated (&np->transbox)))
+ {
+ mach_port_t dirport;
+
+ /* A callback function for short-circuited translators.
+ Symlink & ifsock are handled elsewhere. */
+ error_t short_circuited_callback1 (void *cookie1, void *cookie2,
+ uid_t *uid, gid_t *gid,
+ char **argz, size_t *argz_len)
+ {
+ struct node *node = cookie1;
+
+ switch (node->dn_stat.st_mode & S_IFMT)
+ {
+ case S_IFCHR:
+ case S_IFBLK:
+ asprintf (argz, "%s%c%d%c%d",
+ (S_ISCHR (node->dn_stat.st_mode)
+ ? _HURD_CHRDEV : _HURD_BLKDEV),
+ 0, major (node->dn_stat.st_rdev),
+ 0, minor (node->dn_stat.st_rdev));
+ *argz_len = strlen (*argz) + 1;
+ *argz_len += strlen (*argz + *argz_len) + 1;
+ *argz_len += strlen (*argz + *argz_len) + 1;
+ break;
+ case S_IFIFO:
+ asprintf (argz, "%s", _HURD_FIFO);
+ *argz_len = strlen (*argz) + 1;
+ break;
+ default:
+ return ENOENT;
+ }
+
+ *uid = node->dn_stat.st_uid;
+ *gid = node->dn_stat.st_gid;
+
+ return 0;
+ }
+
+ /* Create an unauthenticated port for DNP, and then
+ unlock it. */
+ error =
+ diskfs_create_protid (diskfs_make_peropen (dnp, 0, dircred->po),
+ iohelp_create_iouser (make_idvec (),
+ make_idvec ()),
+ &newpi);
+ if (error)
+ goto out;
+
+ dirport = ports_get_right (newpi);
+ mach_port_insert_right (mach_task_self (), dirport, dirport,
+ MACH_MSG_TYPE_MAKE_SEND);
+ ports_port_deref (newpi);
+ if (np != dnp)
+ mutex_unlock (&dnp->lock);
+
+ error = fshelp_fetch_root (&np->transbox, dircred->po,
+ dirport, dircred->user,
+ lastcomp ? flags : 0,
+ ((np->dn_stat.st_mode & S_IPTRANS)
+ ? _diskfs_translator_callback1
+ : short_circuited_callback1),
+ _diskfs_translator_callback2,
+ retry, retryname, returned_port);
+
+ /* fetch_root copies DIRPORT for success, so we always should
+ deallocate our send right. */
+ mach_port_deallocate (mach_task_self (), dirport);
+
+ if (error != ENOENT)
+ {
+ diskfs_nrele (dnp);
+ diskfs_nput (np);
+ *returned_port_poly = MACH_MSG_TYPE_MOVE_SEND;
+ if (!lastcomp && !error)
+ {
+ strcat (retryname, "/");
+ strcat (retryname, nextname);
+ }
+ return error;
+ }
+
+ /* ENOENT means there was a hiccup, and the translator
+ vanished while NP was unlocked inside fshelp_fetch_root.
+ Reacquire the locks, and continue as normal. */
+ error = 0;
+ if (np != dnp)
+ {
+ if (!strcmp (path, ".."))
+ mutex_lock (&dnp->lock);
+ else
+ {
+ mutex_unlock (&np->lock);
+ mutex_lock (&dnp->lock);
+ mutex_lock (&np->lock);
+ }
+ }
+ }
+
+ if (S_ISLNK (np->dn_stat.st_mode)
+ && (!lastcomp
+ || mustbedir /* "foo/" must see that foo points to a dir */
+ || !(flags & (O_NOLINK|O_NOTRANS))))
+ {
+ /* Handle symlink interpretation */
+
+ if (nsymlink++ > diskfs_maxsymlinks)
+ {
+ error = ELOOP;
+ goto out;
+ }
+
+ nextnamelen = nextname ? strlen (nextname) + 1 : 0;
+ newnamelen = nextnamelen + np->dn_stat.st_size + 1;
+ if (pathbuflen < newnamelen)
+ {
+ pathbuf = alloca (newnamelen);
+ pathbuflen = newnamelen;
+ }
+
+ if (diskfs_read_symlink_hook)
+ error = (*diskfs_read_symlink_hook)(np, pathbuf);
+ if (!diskfs_read_symlink_hook || error == EINVAL)
+ error = diskfs_node_rdwr (np, pathbuf,
+ 0, np->dn_stat.st_size, 0,
+ dircred, &amt);
+ if (error)
+ goto out;
+
+ if (nextname)
+ {
+ pathbuf[np->dn_stat.st_size] = '/';
+ bcopy (nextname, pathbuf + np->dn_stat.st_size + 1,
+ nextnamelen - 1);
+ }
+ pathbuf[nextnamelen + np->dn_stat.st_size] = '\0';
+
+ if (pathbuf[0] == '/')
+ {
+ /* Punt to the caller. */
+ *retry = FS_RETRY_MAGICAL;
+ *returned_port = MACH_PORT_NULL;
+ strcpy (retryname, pathbuf);
+ goto out;
+ }
+
+ path = pathbuf;
+ if (lastcomp)
+ {
+ lastcomp = 0;
+ /* Symlinks to nonexistent files aren't allowed to cause
+ creation, so clear the flag here. */
+ create = 0;
+ }
+ diskfs_nput (np);
+ np = 0;
+ }
+ else
+ {
+ /* Handle normal nodes */
+ path = nextname;
+ if (np == dnp)
+ diskfs_nrele (dnp);
+ else
+ diskfs_nput (dnp);
+ if (!lastcomp)
+ {
+ dnp = np;
+ np = 0;
+ }
+ else
+ dnp = 0;
+ }
+ } while (path && *path);
+
+ /* At this point, np is the node to return. If newnode is set, then
+ we just created this node. */
+
+ gotit:
+ type = np->dn_stat.st_mode & S_IFMT;
+
+ if (mustbedir && type != S_IFDIR)
+ {
+ error = ENOTDIR;
+ goto out;
+ }
+
+ if (!newnode)
+ /* Check permissions on existing nodes, but not new ones. */
+ {
+ if (((type == S_IFSOCK || type == S_IFBLK || type == S_IFCHR ||
+ type == S_IFIFO)
+ && (flags & (O_READ|O_WRITE|O_EXEC)))
+ || (type == S_IFLNK && (flags & (O_WRITE|O_EXEC))))
+ error = EOPNOTSUPP;
+
+ if (!error && (flags & O_READ))
+ error = fshelp_access (&np->dn_stat, S_IREAD, dircred->user);
+
+ if (!error && (flags & O_EXEC))
+ error = fshelp_access (&np->dn_stat, S_IEXEC, dircred->user);
+
+ if (!error && (flags & O_WRITE))
+ {
+ if (type == S_IFDIR)
+ error = EISDIR;
+ else if (diskfs_check_readonly ())
+ error = EROFS;
+ else
+ error = fshelp_access (&np->dn_stat, S_IWRITE, dircred->user);
+ }
+
+ if (error)
+ goto out;
+ }
+
+ if ((flags & O_NOATIME)
+ && (fshelp_isowner (&np->dn_stat, dircred->user) == EPERM))
+ flags &= ~O_NOATIME;
+
+ error =
+ diskfs_create_protid (diskfs_make_peropen (np,
+ (flags &~OPENONLY_STATE_MODES),
+ dircred->po),
+ dircred->user, &newpi);
+
+ if (! error)
+ {
+ if (flags & O_EXLOCK)
+ error = fshelp_acquire_lock (&np->userlock, &newpi->po->lock_status,
+ &np->lock, LOCK_EX);
+ else if (flags & O_SHLOCK)
+ error = fshelp_acquire_lock (&np->userlock, &newpi->po->lock_status,
+ &np->lock, LOCK_SH);
+ if (error)
+ ports_port_deref (newpi); /* Get rid of NEWPI. */
+ }
+
+ if (! error)
+ {
+ *returned_port = ports_get_right (newpi);
+ ports_port_deref (newpi);
+ }
+
+ out:
+ if (np)
+ {
+ if (dnp == np)
+ diskfs_nrele (np);
+ else
+ diskfs_nput (np);
+ }
+ if (dnp)
+ diskfs_nput (dnp);
+
+ return error;
+}
diff --git a/libdiskfs/dir-mkdir.c b/libdiskfs/dir-mkdir.c
new file mode 100644
index 00000000..1f4ff0ea
--- /dev/null
+++ b/libdiskfs/dir-mkdir.c
@@ -0,0 +1,70 @@
+/* libdiskfs implementation of fs.defs: dir_mkdir
+ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+
+/* Implement dir_mkdir as found in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_dir_mkdir (struct protid *dircred,
+ char *name,
+ mode_t mode)
+{
+ struct node *dnp;
+ struct node *np = 0;
+ struct dirstat *ds = alloca (diskfs_dirstat_size);
+ int error;
+
+ if (!dircred)
+ return EOPNOTSUPP;
+
+ dnp = dircred->po->np;
+ if (diskfs_check_readonly ())
+ return EROFS;
+
+ mutex_lock (&dnp->lock);
+
+ error = diskfs_lookup (dnp, name, CREATE, 0, ds, dircred);
+ if (error == EAGAIN)
+ error = EEXIST;
+ if (!error)
+ error = EEXIST;
+
+ if (error != ENOENT)
+ {
+ diskfs_drop_dirstat (dnp, ds);
+ mutex_unlock (&dnp->lock);
+ return error;
+ }
+
+ mode &= ~(S_ISPARE | S_IFMT);
+ mode |= S_IFDIR;
+
+ error = diskfs_create_node (dnp, name, mode, &np, dircred, ds);
+
+ if (diskfs_synchronous)
+ {
+ diskfs_file_update (dnp, 1);
+ diskfs_file_update (np, 1);
+ }
+
+ if (!error)
+ diskfs_nput (np);
+
+ mutex_unlock (&dnp->lock);
+ return error;
+}
diff --git a/libdiskfs/dir-mkfile.c b/libdiskfs/dir-mkfile.c
new file mode 100644
index 00000000..83158916
--- /dev/null
+++ b/libdiskfs/dir-mkfile.c
@@ -0,0 +1,85 @@
+/*
+ Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include "priv.h"
+#include "fs_S.h"
+#include <fcntl.h>
+
+/* Implement dir_mkfile as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_dir_mkfile (struct protid *cred,
+ int flags,
+ mode_t mode,
+ mach_port_t *newnode,
+ mach_msg_type_name_t *newnodetype)
+{
+ struct node *dnp, *np;
+ error_t err;
+ struct protid *newpi;
+
+ if (!cred)
+ return EOPNOTSUPP;
+ if (diskfs_check_readonly ())
+ return EROFS;
+ dnp = cred->po->np;
+ mutex_lock (&dnp->lock);
+ if (!S_ISDIR (dnp->dn_stat.st_mode))
+ {
+ mutex_unlock (&dnp->lock);
+ return ENOTDIR;
+ }
+ err = fshelp_access (&dnp->dn_stat, S_IWRITE, cred->user);
+ if (err)
+ {
+ mutex_unlock (&dnp->lock);
+ return err;
+ }
+
+ mode &= ~(S_IFMT | S_ISPARE | S_ISVTX);
+ mode |= S_IFREG;
+ err = diskfs_create_node (dnp, 0, mode, &np, cred, 0);
+ mutex_unlock (&dnp->lock);
+
+ if (diskfs_synchronous)
+ {
+ diskfs_file_update (dnp, 1);
+ diskfs_file_update (np, 1);
+ }
+
+ if (err)
+ return err;
+
+ flags &= (O_READ | O_WRITE | O_EXEC);
+ err = diskfs_create_protid (diskfs_make_peropen (np, flags, cred->po),
+ cred->user, &newpi);
+ if (! err)
+ {
+ *newnode = ports_get_right (newpi);
+ *newnodetype = MACH_MSG_TYPE_MAKE_SEND;
+ ports_port_deref (newpi);
+ }
+
+ diskfs_nput (np);
+
+ return err;
+}
+
+
diff --git a/libdiskfs/dir-readdir.c b/libdiskfs/dir-readdir.c
new file mode 100644
index 00000000..d1dc4490
--- /dev/null
+++ b/libdiskfs/dir-readdir.c
@@ -0,0 +1,61 @@
+/*
+ Copyright (C) 1993,94,96,99 Free Software Foundation, Inc.
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include <fcntl.h>
+#include "priv.h"
+#include "fs_S.h"
+
+kern_return_t
+diskfs_S_dir_readdir (struct protid *cred,
+ char **data,
+ u_int *datacnt,
+ boolean_t *data_dealloc,
+ int entry,
+ int nentries,
+ vm_size_t bufsiz,
+ int *amt)
+{
+ error_t err;
+ struct node *np;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ np = cred->po->np;
+ mutex_lock (&np->lock);
+
+ if ((cred->po->openstat & O_READ) == 0)
+ {
+ mutex_unlock (&np->lock);
+ return EBADF;
+ }
+
+ if ((np->dn_stat.st_mode & S_IFMT) != S_IFDIR)
+ {
+ mutex_unlock (&np->lock);
+ return ENOTDIR;
+ }
+
+ err = diskfs_get_directs (np, entry, nentries, data, datacnt, bufsiz, amt);
+ *data_dealloc = 1; /* XXX */
+ mutex_unlock (&np->lock);
+ return err;
+}
diff --git a/libdiskfs/dir-rename.c b/libdiskfs/dir-rename.c
new file mode 100644
index 00000000..6fc7e0f5
--- /dev/null
+++ b/libdiskfs/dir-rename.c
@@ -0,0 +1,229 @@
+/* libdiskfs implementation of fs.defs: dir_rename
+ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+
+/* To avoid races in checkpath, and to prevent a directory from being
+ simultaneously renamed by two processes, we serialize all renames of
+ directores with this lock */
+static struct mutex renamedirlock = MUTEX_INITIALIZER;
+
+/* Implement dir_rename as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_dir_rename (struct protid *fromcred,
+ char *fromname,
+ struct protid *tocred,
+ char *toname,
+ int excl)
+{
+ struct node *fdp, *tdp, *fnp, *tnp, *tmpnp;
+ error_t err;
+ struct dirstat *ds = alloca (diskfs_dirstat_size);
+
+ if (!fromcred)
+ return EOPNOTSUPP;
+
+ /* Verify that tocred really is a port to us. */
+ if (! tocred)
+ return EXDEV;
+
+ if (tocred->po->shadow_root != fromcred->po->shadow_root)
+ /* Same translator, but in different shadow trees. */
+ return EXDEV;
+
+ if (diskfs_check_readonly ())
+ return EROFS;
+
+ fdp = fromcred->po->np;
+ tdp = tocred->po->np;
+
+ try_again:
+ /* Acquire the source; hold a reference to it. This
+ will prevent anyone from deleting it before we create
+ the new link. */
+ mutex_lock (&fdp->lock);
+ err = diskfs_lookup (fdp, fromname, LOOKUP, &fnp, 0, fromcred);
+ mutex_unlock (&fdp->lock);
+ if (err == EAGAIN)
+ err = EINVAL;
+ if (err)
+ return err;
+
+ if (S_ISDIR (fnp->dn_stat.st_mode))
+ {
+ mutex_unlock (&fnp->lock);
+ if (!mutex_try_lock (&renamedirlock))
+ {
+ diskfs_nrele (fnp);
+ mutex_lock (&renamedirlock);
+ goto try_again;
+ }
+ err = diskfs_rename_dir (fdp, fnp, fromname, tdp, toname, fromcred,
+ tocred);
+ if (diskfs_synchronous)
+ {
+ mutex_lock (&fdp->lock);
+ diskfs_file_update (fdp, 1);
+ mutex_unlock (&fdp->lock);
+
+ mutex_lock (&fnp->lock);
+ diskfs_file_update (fnp, 1);
+ mutex_unlock (&fnp->lock);
+
+ mutex_lock (&tdp->lock);
+ diskfs_file_update (tdp, 1);
+ mutex_unlock (&tdp->lock);
+ }
+
+ diskfs_nrele (fnp);
+ mutex_unlock (&renamedirlock);
+ if (!err)
+ /* MiG won't do this for us, which it ought to. */
+ mach_port_deallocate (mach_task_self (), tocred->pi.port_right);
+ return err;
+ }
+
+ mutex_unlock (&fnp->lock);
+
+ /* We now hold no locks */
+
+ /* Link the node into the new directory. */
+ mutex_lock (&tdp->lock);
+
+ err = diskfs_lookup (tdp, toname, RENAME, &tnp, ds, tocred);
+ if (err == EAGAIN)
+ err = EINVAL;
+ else if (!err && excl)
+ {
+ err = EEXIST;
+ diskfs_nput (tnp);
+ }
+ if (err && err != ENOENT)
+ {
+ diskfs_drop_dirstat (tdp, ds);
+ diskfs_nrele (fnp);
+ mutex_unlock (&tdp->lock);
+ return err;
+ }
+
+ /* rename("foo", "link-to-foo") is guaranteed to return 0 and
+ do nothing by Posix. */
+ if (tnp == fnp)
+ {
+ diskfs_drop_dirstat (tdp, ds);
+ diskfs_nrele (fnp);
+ diskfs_nput (tnp);
+ mutex_unlock (&tdp->lock);
+ mach_port_deallocate (mach_task_self (), tocred->pi.port_right);
+ return 0;
+ }
+
+ /* rename("foo", dir) should fail. */
+ if (tnp && S_ISDIR (tnp->dn_stat.st_mode))
+ {
+ diskfs_drop_dirstat (tdp, ds);
+ diskfs_nrele (fnp);
+ mutex_unlock (&tdp->lock);
+ return EISDIR;
+ }
+
+ mutex_lock (&fnp->lock);
+
+ /* Increment the link count for the upcoming link */
+ if (fnp->dn_stat.st_nlink == diskfs_link_max - 1)
+ {
+ diskfs_drop_dirstat (tdp, ds);
+ diskfs_nput (fnp);
+ mutex_unlock (&tdp->lock);
+ return EMLINK;
+ }
+ fnp->dn_stat.st_nlink++;
+ fnp->dn_set_ctime = 1;
+ diskfs_node_update (fnp, 1);
+
+ if (tnp)
+ {
+ err = diskfs_dirrewrite (tdp, tnp, fnp, toname, ds);
+ if (!err)
+ {
+ tnp->dn_stat.st_nlink--;
+ tnp->dn_set_ctime = 1;
+ if (diskfs_synchronous)
+ diskfs_node_update (tnp, 1);
+ }
+ diskfs_nput (tnp);
+ }
+ else
+ err = diskfs_direnter (tdp, toname, fnp, ds, tocred);
+
+ if (diskfs_synchronous)
+ diskfs_node_update (tdp, 1);
+
+ mutex_unlock (&tdp->lock);
+ mutex_unlock (&fnp->lock);
+ if (err)
+ {
+ diskfs_nrele (fnp);
+ return err;
+ }
+
+ /* We now hold no locks */
+
+ /* Now we remove the source. Unfortunately, we haven't held
+ fdp locked (nor could we), so someone else might have already
+ removed it. */
+ mutex_lock (&fdp->lock);
+ err = diskfs_lookup (fdp, fromname, REMOVE, &tmpnp, ds, fromcred);
+ if (err)
+ {
+ diskfs_drop_dirstat (tdp, ds);
+ mutex_unlock (&fdp->lock);
+ diskfs_nrele (fnp);
+ return err;
+ }
+
+ if (tmpnp != fnp)
+ {
+ /* This is no longer the node being renamed, so just return. */
+ diskfs_drop_dirstat (tdp, ds);
+ diskfs_nput (tmpnp);
+ diskfs_nrele (fnp);
+ mutex_unlock (&fdp->lock);
+ mach_port_deallocate (mach_task_self (), tocred->pi.port_right);
+ return 0;
+ }
+
+ diskfs_nrele (tmpnp);
+
+ err = diskfs_dirremove (fdp, fnp, fromname, ds);
+ if (diskfs_synchronous)
+ diskfs_node_update (fdp, 1);
+
+ fnp->dn_stat.st_nlink--;
+ fnp->dn_set_ctime = 1;
+
+ if (diskfs_synchronous)
+ diskfs_node_update (fnp, 1);
+
+ diskfs_nput (fnp);
+ mutex_unlock (&fdp->lock);
+ if (!err)
+ mach_port_deallocate (mach_task_self (), tocred->pi.port_right);
+
+ return err;
+}
diff --git a/libdiskfs/dir-renamed.c b/libdiskfs/dir-renamed.c
new file mode 100644
index 00000000..3d518eb9
--- /dev/null
+++ b/libdiskfs/dir-renamed.c
@@ -0,0 +1,229 @@
+/*
+ Copyright (C) 1994, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+
+/* Check if source directory is in the path of the target directory.
+ We get target locked, source unlocked but with a reference. When
+ we return, nothing is locked, and target has lost its reference.
+ This routine assumes that no renames of directories will happen
+ while it is running; as a result, ufs_rename serializes all renames
+ of directories. */
+static error_t
+checkpath(struct node *source,
+ struct node *target,
+ struct protid *cred)
+{
+ error_t err;
+ struct node *np;
+
+ np = target;
+ for (np = target, err = 0;
+ /* nothing */;
+ /* This special lookup does a diskfs_nput on its first argument
+ when it succeeds. */
+ err = diskfs_lookup (np, "..", LOOKUP | SPEC_DOTDOT, &np, 0, cred))
+ {
+ if (err)
+ {
+ diskfs_nput (np);
+ return err;
+ }
+
+ if (np == source)
+ {
+ diskfs_nput (np);
+ return EINVAL;
+ }
+
+ if (np == diskfs_root_node)
+ {
+ diskfs_nput (np);
+ return 0;
+ }
+ }
+}
+
+/* Rename directory node FNP (whose parent is FDP, and which has name
+ FROMNAME in that directory) to have name TONAME inside directory
+ TDP. None of these nodes are locked, and none should be locked
+ upon return. This routine is serialized, so it doesn't have to be
+ reentrant. Directories will never be renamed except by this
+ routine. FROMCRED and TOCRED are the users responsible for
+ FDP/FNP and TDP respectively. */
+error_t
+diskfs_rename_dir (struct node *fdp, struct node *fnp, const char *fromname,
+ struct node *tdp, const char *toname,
+ struct protid *fromcred, struct protid *tocred)
+{
+ error_t err;
+ struct node *tnp, *tmpnp;
+ void *buf = alloca (diskfs_dirstat_size);
+ struct dirstat *ds;
+ struct dirstat *tmpds;
+
+ mutex_lock (&tdp->lock);
+ diskfs_nref (tdp); /* reference and lock will get consumed by
+ checkpath */
+ err = checkpath (fnp, tdp, tocred);
+
+ if (err)
+ return err;
+
+ /* Now, lock the parent directories. This is legal because tdp is not
+ a child of fnp (guaranteed by checkpath above). */
+ mutex_lock (&fdp->lock);
+ if (fdp != tdp)
+ mutex_lock (&tdp->lock);
+
+ /* 1: Lookup target; if it exists, make sure it's an empty directory. */
+ ds = buf;
+ err = diskfs_lookup (tdp, toname, RENAME, &tnp, ds, tocred);
+ assert (err != EAGAIN); /* <-> assert (TONAME != "..") */
+
+ if (tnp == fnp)
+ {
+ diskfs_drop_dirstat (tdp, ds);
+ diskfs_nput (tnp);
+ mutex_unlock (&tdp->lock);
+ if (fdp != tdp)
+ mutex_unlock (&fdp->lock);
+ return 0;
+ }
+
+ /* Now we can safely lock fnp */
+ mutex_lock (&fnp->lock);
+
+ if (tnp)
+ {
+ if (! S_ISDIR(tnp->dn_stat.st_mode))
+ err = ENOTDIR;
+ else if (!diskfs_dirempty (tnp, tocred))
+ err = ENOTEMPTY;
+ }
+
+ if (err && err != ENOENT)
+ goto out;
+
+ /* 2: Set our .. to point to the new parent */
+ if (fdp != tdp)
+ {
+ if (tdp->dn_stat.st_nlink == diskfs_link_max - 1)
+ {
+ err = EMLINK;
+ return EMLINK;
+ }
+ tdp->dn_stat.st_nlink++;
+ tdp->dn_set_ctime = 1;
+ if (diskfs_synchronous)
+ diskfs_node_update (tdp, 1);
+
+ tmpds = alloca (diskfs_dirstat_size);
+ err = diskfs_lookup (fnp, "..", RENAME | SPEC_DOTDOT,
+ &tmpnp, tmpds, fromcred);
+ assert (err != ENOENT);
+ assert (tmpnp == fdp);
+ if (err)
+ {
+ diskfs_drop_dirstat (fnp, tmpds);
+ goto out;
+ }
+
+ err = diskfs_dirrewrite (fnp, fdp, tdp, "..", tmpds);
+ if (diskfs_synchronous)
+ diskfs_file_update (fnp, 1);
+ if (err)
+ goto out;
+
+ fdp->dn_stat.st_nlink--;
+ fdp->dn_set_ctime = 1;
+ if (diskfs_synchronous)
+ diskfs_node_update (fdp, 1);
+ }
+
+
+ /* 3: Increment the link count on the node being moved and rewrite
+ tdp. */
+ if (fnp->dn_stat.st_nlink == diskfs_link_max - 1)
+ {
+ mutex_unlock (&fnp->lock);
+ diskfs_drop_dirstat (tdp, ds);
+ mutex_unlock (&tdp->lock);
+ if (tnp)
+ diskfs_nput (tnp);
+ return EMLINK;
+ }
+ fnp->dn_stat.st_nlink++;
+ fnp->dn_set_ctime = 1;
+ diskfs_node_update (fnp, 1);
+
+ if (tnp)
+ {
+ err = diskfs_dirrewrite (tdp, tnp, fnp, toname, ds);
+ ds = 0;
+ if (!err)
+ {
+ tnp->dn_stat.st_nlink--;
+ tnp->dn_set_ctime = 1;
+ }
+ diskfs_clear_directory (tnp, tdp, tocred);
+ if (diskfs_synchronous)
+ diskfs_file_update (tnp, 1);
+ }
+ else
+ {
+ err = diskfs_direnter (tdp, toname, fnp, ds, tocred);
+ if (diskfs_synchronous)
+ diskfs_file_update (tdp, 1);
+ }
+
+ if (err)
+ goto out;
+
+ /* 4: Remove the entry in fdp. */
+ ds = buf;
+ mutex_unlock (&fnp->lock);
+ err = diskfs_lookup (fdp, fromname, REMOVE, &tmpnp, ds, fromcred);
+ assert (tmpnp == fnp);
+ diskfs_nrele (tmpnp);
+ if (err)
+ goto out;
+
+ diskfs_dirremove (fdp, fnp, fromname, ds);
+ ds = 0;
+ fnp->dn_stat.st_nlink--;
+ fnp->dn_set_ctime = 1;
+ if (diskfs_synchronous)
+ {
+ diskfs_file_update (fdp, 1);
+ diskfs_node_update (fnp, 1);
+ }
+
+ out:
+ if (tdp)
+ mutex_unlock (&tdp->lock);
+ if (tnp)
+ diskfs_nput (tnp);
+ if (fdp && fdp != tdp)
+ mutex_unlock (&fdp->lock);
+ if (fnp)
+ mutex_unlock (&fnp->lock);
+ if (ds)
+ diskfs_drop_dirstat (tdp, ds);
+ return err;
+}
diff --git a/libdiskfs/dir-rmdir.c b/libdiskfs/dir-rmdir.c
new file mode 100644
index 00000000..a90ff07b
--- /dev/null
+++ b/libdiskfs/dir-rmdir.c
@@ -0,0 +1,94 @@
+/* libdsikfs implementation of fs.defs: dir_rmdir
+ Copyright (C) 1992,93,94,95,96,97,99 Free Software Foundation, Inc.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+#include <hurd/fsys.h>
+
+/* Implement dir_rmdir as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_dir_rmdir (struct protid *dircred,
+ char *name)
+{
+ struct node *dnp;
+ struct node *np;
+ struct dirstat *ds = alloca (diskfs_dirstat_size);
+ error_t error;
+
+ /* This routine cleans up the state we have after calling diskfs_lookup.
+ After that call, all returns are done with `return done (ERROR, NP);'. */
+ inline error_t done (error_t error, struct node *np)
+ {
+ if (np)
+ diskfs_nput (np);
+
+ if (ds)
+ diskfs_drop_dirstat (dnp, ds);
+ mutex_unlock (&dnp->lock);
+
+ return error;
+ }
+
+ if (!dircred)
+ return EOPNOTSUPP;
+
+ dnp = dircred->po->np;
+ if (diskfs_check_readonly ())
+ return EROFS;
+
+ mutex_lock (&dnp->lock);
+
+ error = diskfs_lookup (dnp, name, REMOVE, &np, ds, dircred);
+ if (error)
+ return done (error == EAGAIN ? ENOTEMPTY : error, 0);
+
+ if (dnp == np)
+ {
+ /* Attempt to rmdir(".") */
+ diskfs_nrele (np);
+ diskfs_drop_dirstat (dnp, ds);
+ mutex_unlock (&dnp->lock);
+ return EINVAL;
+ }
+
+ if ((np->dn_stat.st_mode & S_IPTRANS) || fshelp_translated (&np->transbox))
+ /* Attempt to rmdir a translated node. */
+ return done (EBUSY, np);
+
+ if (!S_ISDIR (np->dn_stat.st_mode))
+ return done (ENOTDIR, np);
+
+ if (!diskfs_dirempty (np, dircred))
+ return done (ENOTEMPTY, np);
+
+ /* Here we go! */
+ error = diskfs_dirremove (dnp, np, name, ds);
+ ds = 0;
+
+ if (!error)
+ {
+ np->dn_stat.st_nlink--;
+ np->dn_set_ctime = 1;
+ diskfs_clear_directory (np, dnp, dircred);
+ if (diskfs_synchronous)
+ diskfs_file_update (np, 1);
+ }
+ if (diskfs_synchronous)
+ diskfs_file_update (dnp, 1);
+
+ return done (error, np);
+}
diff --git a/libdiskfs/dir-unlink.c b/libdiskfs/dir-unlink.c
new file mode 100644
index 00000000..7a6ce5da
--- /dev/null
+++ b/libdiskfs/dir-unlink.c
@@ -0,0 +1,98 @@
+/* libdiskfs implementation of fs.defs: dir_unlink
+ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+#include <hurd/fsys.h>
+
+/* Implement dir_unlink as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_dir_unlink (struct protid *dircred,
+ char *name)
+{
+ struct node *dnp;
+ struct node *np;
+ struct dirstat *ds = alloca (diskfs_dirstat_size);
+ error_t error;
+ mach_port_t control = MACH_PORT_NULL;
+
+ if (!dircred)
+ return EOPNOTSUPP;
+
+ dnp = dircred->po->np;
+ if (diskfs_check_readonly ())
+ return EROFS;
+
+ mutex_lock (&dnp->lock);
+
+ error = diskfs_lookup (dnp, name, REMOVE, &np, ds, dircred);
+ if (error == EAGAIN)
+ error = EISDIR;
+ if (error)
+ {
+ diskfs_drop_dirstat (dnp, ds);
+ mutex_unlock (&dnp->lock);
+ return error;
+ }
+
+ /* This isn't the BSD behavior, but it is Posix compliant and saves
+ us on several race conditions.*/
+ if (S_ISDIR(np->dn_stat.st_mode))
+ {
+ if (np == dnp) /* gotta catch '.' */
+ diskfs_nrele (np);
+ else
+ diskfs_nput (np);
+ diskfs_drop_dirstat (dnp, ds);
+ mutex_unlock (&dnp->lock);
+ return EISDIR;
+ }
+
+ error = diskfs_dirremove (dnp, np, name, ds);
+ if (diskfs_synchronous)
+ diskfs_node_update (dnp, 1);
+ if (error)
+ {
+ diskfs_nput (np);
+ mutex_unlock (&dnp->lock);
+ return error;
+ }
+
+ np->dn_stat.st_nlink--;
+ np->dn_set_ctime = 1;
+ if (diskfs_synchronous)
+ diskfs_node_update (np, 1);
+
+ if (np->dn_stat.st_nlink == 0)
+ fshelp_fetch_control (&np->transbox, &control);
+
+ /* This check is necessary because we might get here on an error while
+ checking the mode on something which happens to be `.'. */
+ if (np == dnp)
+ diskfs_nrele (np);
+ else
+ diskfs_nput (np);
+ mutex_unlock (&dnp->lock);
+
+ if (control)
+ {
+ fsys_goaway (control, FSYS_GOAWAY_UNLINK);
+ mach_port_deallocate (mach_task_self (), control);
+ }
+
+ return error;
+}
diff --git a/libdiskfs/direnter.c b/libdiskfs/direnter.c
new file mode 100644
index 00000000..cb9b76ca
--- /dev/null
+++ b/libdiskfs/direnter.c
@@ -0,0 +1,48 @@
+/* Wrapper for diskfs_direnter_hard
+ Copyright (C) 1996, 1998 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/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. */
+
+
+#include "priv.h"
+
+/* Add NP to directory DP under the name NAME. This will only be
+ called after an unsuccessful call to diskfs_lookup of type CREATE
+ or RENAME; DP has been locked continuously since that call and DS
+ is as that call set it, NP is locked. CRED identifies the user
+ responsible for the call (to be used only to validate directory
+ growth). This function is a wrapper for diskfs_direnter_hard. */
+error_t
+diskfs_direnter (struct node *dp,
+ const char *name,
+ struct node *np,
+ struct dirstat *ds,
+ struct protid *cred)
+{
+ error_t err;
+
+ err = diskfs_direnter_hard (dp, name, np, ds, cred);
+ if (err)
+ return err;
+
+ if (dp->dirmod_reqs)
+ diskfs_notice_dirchange (dp, DIR_CHANGED_NEW, name);
+
+ diskfs_enter_lookup_cache (dp, np, name);
+ return 0;
+}
diff --git a/libdiskfs/dirremove.c b/libdiskfs/dirremove.c
new file mode 100644
index 00000000..239daa72
--- /dev/null
+++ b/libdiskfs/dirremove.c
@@ -0,0 +1,45 @@
+/* Wrapper for diskfs_dirremove_hard
+ Copyright (C) 1996, 1998 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/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. */
+
+#include "priv.h"
+
+/* This will only be called after a successful call to diskfs_lookup
+ of type REMOVE; this call should remove the name found from the
+ directory DS. DP has been locked continuously since the call to
+ diskfs_lookup and DS is as that call set it. This routine should
+ call diskfs_notice_dirchange if DP->dirmod_reqs is nonzero. This
+ function is a wrapper for diskfs_dirremove_hard. The entry being
+ removed has name NAME and refers to NP. */
+error_t
+diskfs_dirremove (struct node *dp,
+ struct node *np,
+ const char *name,
+ struct dirstat *ds)
+{
+ error_t err;
+
+ diskfs_purge_lookup_cache (dp, np);
+
+ err = diskfs_dirremove_hard (dp, ds);
+
+ if (!err && dp->dirmod_reqs)
+ diskfs_notice_dirchange (dp, DIR_CHANGED_UNLINK, name);
+ return err;
+}
diff --git a/libdiskfs/dirrewrite.c b/libdiskfs/dirrewrite.c
new file mode 100644
index 00000000..8f713960
--- /dev/null
+++ b/libdiskfs/dirrewrite.c
@@ -0,0 +1,50 @@
+/* Wrapper for diskfs_dirrewrite_hard
+ Copyright (C) 1996, 1998 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/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. */
+
+
+#include "priv.h"
+
+/* This will only be called after a successful call to diskfs_lookup
+ of type RENAME; this call should change the name found in directory
+ DP to point to node NP instead of its previous referent, OLDNP. DP
+ has been locked continuously since the call to diskfs_lookup and DS
+ is as that call set it; NP is locked. This routine should call
+ diskfs_notice_dirchange if DP->dirmod_reqs is nonzero. NAME is the
+ name of OLDNP inside DP; it is this reference which is being
+ rewritten. This function is a wrapper for diskfs_dirrewrite_hard. */
+error_t diskfs_dirrewrite (struct node *dp,
+ struct node *oldnp,
+ struct node *np,
+ const char *name,
+ struct dirstat *ds)
+{
+ error_t err;
+
+ diskfs_purge_lookup_cache (dp, oldnp);
+
+ err = diskfs_dirrewrite_hard (dp, np, ds);
+ if (err)
+ return err;
+
+ if (dp->dirmod_reqs)
+ diskfs_notice_dirchange (dp, DIR_CHANGED_RENUMBER, name);
+ diskfs_enter_lookup_cache (dp, np, name);
+ return 0;
+}
diff --git a/libdiskfs/disk-pager.c b/libdiskfs/disk-pager.c
new file mode 100644
index 00000000..b5ae53a1
--- /dev/null
+++ b/libdiskfs/disk-pager.c
@@ -0,0 +1,119 @@
+/* Map the disk image and handle faults accessing it.
+ Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
+ Written by Roland McGrath.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "diskfs-pager.h"
+#include <hurd/sigpreempt.h>
+#include <error.h>
+
+struct pager *diskfs_disk_pager;
+
+static void fault_handler (int sig, long int sigcode, struct sigcontext *scp);
+static struct hurd_signal_preemptor preemptor =
+ {
+ signals: sigmask (SIGSEGV) | sigmask (SIGBUS),
+ preemptor: NULL,
+ handler: (sighandler_t) &fault_handler,
+ };
+
+/* A top-level function for the paging thread that just services paging
+ requests. */
+static void
+service_paging_requests (any_t arg)
+{
+ struct port_bucket *pager_bucket = arg;
+ for (;;)
+ ports_manage_port_operations_multithread (pager_bucket,
+ pager_demuxer,
+ 1000 * 60 * 2,
+ 1000 * 60 * 10, 0);
+}
+
+void
+diskfs_start_disk_pager (struct user_pager_info *upi,
+ struct port_bucket *pager_bucket, int may_cache,
+ size_t size, void **image)
+{
+ error_t err;
+ mach_port_t disk_pager_port;
+
+ /* Make a thread to service paging requests. */
+ cthread_detach (cthread_fork ((cthread_fn_t) service_paging_requests,
+ (any_t)pager_bucket));
+
+ /* Create the pager. */
+ diskfs_disk_pager = pager_create (upi, pager_bucket,
+ may_cache, MEMORY_OBJECT_COPY_NONE);
+ assert (diskfs_disk_pager);
+
+ /* Get a port to the disk pager. */
+ disk_pager_port = pager_get_port (diskfs_disk_pager);
+ mach_port_insert_right (mach_task_self (), disk_pager_port, disk_pager_port,
+ MACH_MSG_TYPE_MAKE_SEND);
+
+ /* Now map the disk image. */
+ err = vm_map (mach_task_self (), (vm_address_t *)image, size,
+ 0, 1, disk_pager_port, 0, 0,
+ VM_PROT_READ | (diskfs_readonly ? 0 : VM_PROT_WRITE),
+ VM_PROT_READ | VM_PROT_WRITE,
+ VM_INHERIT_NONE);
+ if (err)
+ error (2, err, "cannot vm_map whole disk");
+
+ /* Set up the signal preemptor to catch faults on the disk image. */
+ preemptor.first = (vm_address_t) *image;
+ preemptor.last = ((vm_address_t) *image + size);
+ hurd_preempt_signals (&preemptor);
+
+ /* We have the mapping; we no longer need the send right. */
+ mach_port_deallocate (mach_task_self (), disk_pager_port);
+}
+
+static void
+fault_handler (int sig, long int sigcode, struct sigcontext *scp)
+{
+ jmp_buf *env = cthread_data (cthread_self ());
+ error_t err;
+
+#ifndef NDEBUG
+ if (!env)
+ {
+ error (0, 0,
+ "BUG: unexpected fault on disk image (%d, %#lx) in [%#lx,%#lx)"
+ " eip %#x err %#x",
+ sig, sigcode,
+ preemptor.first, preemptor.last,
+ scp->sc_eip, scp->sc_error);
+ assert (scp->sc_error == EKERN_MEMORY_ERROR);
+ err = pager_get_error (diskfs_disk_pager, sigcode);
+ assert (err);
+ assert_perror (err);
+ }
+#endif
+
+ /* Clear the record, since the faulting thread will not. */
+ cthread_set_data (cthread_self (), 0);
+
+ /* Fetch the error code from the pager. */
+ assert (scp->sc_error == EKERN_MEMORY_ERROR);
+ err = pager_get_error (diskfs_disk_pager, sigcode);
+ assert (err);
+
+ /* Make `diskfault_catch' return the error code. */
+ longjmp (*env, err);
+}
diff --git a/libdiskfs/diskfs-pager.h b/libdiskfs/diskfs-pager.h
new file mode 100644
index 00000000..4ec0b27b
--- /dev/null
+++ b/libdiskfs/diskfs-pager.h
@@ -0,0 +1,70 @@
+/* Map the disk image and handle faults accessing it.
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Written by Roland McGrath.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _HURD_DISKFS_PAGER_H
+#define _HURD_DISKFS_PAGER_H 1
+
+#include <hurd/pager.h>
+#include <hurd/ports.h>
+#include <setjmp.h>
+#include <cthreads.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdlib.h>
+
+/* Start a pager for the whole disk, and store it in DISKFS_DISK_PAGER,
+ preparing a signal preemptor so that the `diskfs_catch_exception' macro
+ below works. SIZE should be the size of the image to map, and the address
+ mapped is returned in IMAGE. INFO, PAGER_BUCKET, & MAY_CACHE are passed
+ to `pager_create'. */
+extern void diskfs_start_disk_pager (struct user_pager_info *info,
+ struct port_bucket *pager_bucket, int may_cache,
+ size_t size, void **image);
+
+extern struct pager *diskfs_disk_pager;
+
+struct disk_image_user
+ {
+ jmp_buf env;
+ struct disk_image_user *next;
+ };
+
+/* Return zero now. Return a second time with a nonzero error_t
+ if this thread faults accessing `disk_image' before calling
+ `diskfs_end_catch_exception' (below). */
+#define diskfs_catch_exception() \
+({ \
+ struct disk_image_user *diu = alloca (sizeof *diu); \
+ error_t err; \
+ diu->next = (void *) cthread_data (cthread_self ()); \
+ err = setjmp (diu->env); \
+ if (err == 0) \
+ cthread_set_data (cthread_self (), diu); \
+ err; \
+})
+
+/* No longer handle faults on `disk_image' in this thread.
+ Any unexpected fault hereafter will crash the program. */
+#define diskfs_end_catch_exception() \
+({ \
+ struct disk_image_user *diu = (void *) cthread_data (cthread_self ()); \
+ cthread_set_data (cthread_self (), diu->next); \
+})
+
+
+#endif /* hurd/diskfs-pager.h */
diff --git a/libdiskfs/diskfs.h b/libdiskfs/diskfs.h
new file mode 100644
index 00000000..e8974a11
--- /dev/null
+++ b/libdiskfs/diskfs.h
@@ -0,0 +1,937 @@
+/* Definitions for fileserver helper functions
+ Copyright (C) 1994, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _HURD_DISKFS
+#define _HURD_DISKFS
+
+#include <assert.h>
+#include <unistd.h>
+#include <rwlock.h>
+#include <hurd/ports.h>
+#include <hurd/fshelp.h>
+#include <hurd/iohelp.h>
+#include <idvec.h>
+
+/* Each user port referring to a file points to one of these
+ (with the aid of the ports library). */
+struct protid
+{
+ struct port_info pi; /* libports info block */
+
+ /* User identification */
+ struct iouser *user;
+
+ /* Object this refers to */
+ struct peropen *po;
+
+ /* Shared memory I/O information. */
+ memory_object_t shared_object;
+ struct shared_io *mapped;
+};
+
+/* One of these is created for each node opened by dir_pathtrans. */
+struct peropen
+{
+ int filepointer;
+ int lock_status;
+ int refcnt;
+ int openstat;
+
+ struct node *np;
+
+ /* The parent of the translator's root node. */
+ mach_port_t root_parent;
+
+ /* If this node is in a shadow tree, the parent of its root. */
+ mach_port_t shadow_root_parent;
+ /* If in a shadow tree, its root node in this translator. */
+ struct node *shadow_root;
+};
+
+/* A unique one of these exists for each node currently in use (and
+ possibly for some not currently in use, but with links) in the
+ filesystem. */
+struct node
+{
+ struct node *next, **prevp;
+
+ struct disknode *dn;
+
+ struct stat dn_stat;
+
+ /* Stat has been modified if one of the following four fields
+ is nonzero. Also, if one of the dn_set_?time fields is nonzero,
+ the appropriate dn_stat.st_?time field needs to be updated. */
+ int dn_set_ctime;
+ int dn_set_atime;
+ int dn_set_mtime;
+ int dn_stat_dirty;
+
+ struct mutex lock;
+
+ int references; /* hard references */
+ int light_references; /* light references */
+
+ mach_port_t sockaddr; /* address for S_IFSOCK shortcut */
+
+ int owner;
+
+ struct transbox transbox;
+
+ struct lock_box userlock;
+
+ struct conch conch;
+
+ struct modreq *dirmod_reqs;
+
+ struct modreq *filemod_reqs;
+
+ off_t allocsize;
+
+ int cache_id;
+
+ int author_tracks_uid;
+};
+
+/* Possibly lookup types for diskfs_lookup call */
+enum lookup_type
+{
+ LOOKUP,
+ CREATE,
+ REMOVE,
+ RENAME,
+};
+
+/* Pending directory and file modification request */
+struct modreq
+{
+ mach_port_t port;
+ struct modreq *next;
+};
+
+
+/* Special flag for diskfs_lookup. */
+#define SPEC_DOTDOT 0x10000000
+
+struct argp; /* opaque in this file */
+struct argp_child; /* opaque in this file */
+struct store; /* opaque in this file */
+struct store_parsed; /* opaque in this file */
+
+/* Declarations of variables the library sets. */
+
+extern mach_port_t diskfs_default_pager; /* send right */
+extern auth_t diskfs_auth_server_port; /* send right */
+
+/* The io_identity identity port for the filesystem. */
+extern mach_port_t diskfs_fsys_identity;
+
+/* The command line diskfs was started, set by the default argument parser.
+ If you don't use it, set this yourself. This is only used for bootstrap
+ file systems, to give the procserver. */
+extern char **diskfs_argv;
+
+/* When this is a bootstrap filesystem, the command line options passed from
+ the kernel. If not a bootstrap filesystem, it is 0, so it can be used to
+ distinguish between the two cases. */
+extern char *diskfs_boot_flags;
+
+/* Hold this lock while do fsys level operations. Innocuous users can just
+ hold a reader lock, and anyone who's going to do nasty things that would
+ screw anyone else should hold a writer lock. */
+extern struct rwlock diskfs_fsys_lock;
+
+extern volatile struct mapped_time_value *diskfs_mtime;
+
+/* True iff we should do every operation synchronously. It
+ is the format-specific code's responsibility to keep allocation
+ information permanently in sync if this is set; the rest will
+ be done by format independent code. */
+extern int diskfs_synchronous;
+
+extern spin_lock_t diskfs_node_refcnt_lock;
+
+extern int pager_port_type;
+
+/* Whether the filesystem is currently writable or not. */
+extern int diskfs_readonly;
+
+
+struct pager;
+
+/* Port classes we manage */
+extern struct port_class *diskfs_protid_class;
+extern struct port_class *diskfs_control_class;
+extern struct port_class *diskfs_execboot_class;
+extern struct port_class *diskfs_initboot_class;
+extern struct port_class *diskfs_shutdown_notification_class;
+
+extern struct port_bucket *diskfs_port_bucket;
+
+
+
+/* Declarations of things the user must or may define. */
+
+/* The user must define this type. This should hold information
+ between calls to diskfs_lookup and diskfs_dir{enter,rewrite,rename}
+ so that those calls work as described below. */
+struct dirstat;
+
+/* The user must define this variable; it should be the size in bytes
+ of a struct dirstat. */
+extern size_t diskfs_dirstat_size;
+
+/* The user must define this variable; it is the maximum number of
+ links to any one file. The implementation of dir_rename does not know
+ how to succeed if this is only one; on such formats you need to
+ reimplement dir_rename yourself. */
+extern int diskfs_link_max;
+
+/* The user must define this variable; it is the maximum length of
+ a single pathname component (i.e. file name within directory).
+ The filesystem code does not use this for anything, but it is
+ returned to user queries for _PC_NAME_MAX. */
+extern int diskfs_name_max;
+
+/* The user must define this variable; it is the maximum number of
+ symlinks to be traversed within a single call to dir_pathtrans.
+ If this is exceeded, dir_pathtrans will return ELOOP. */
+extern int diskfs_maxsymlinks;
+
+/* This variable is defined by diskfs; the suer should set it if
+ the filesystem media cannot be made writeable. */
+extern int diskfs_hard_readonly;
+
+/* The user must define this variable. Set this to be the node
+ of root of the filesystem. */
+extern struct node *diskfs_root_node;
+
+/* The user must define this variable. Set this to the name of the
+ filesystem server. */
+extern char *diskfs_server_name;
+
+/* The user must define this variables. Set this to be the server
+ version number. */
+extern char *diskfs_server_version;
+
+/* The user may define this variable. Set this to be any additional
+ version specification that should be printed for --version. */
+extern char *diskfs_extra_version;
+
+/* The user may define this variable. This should be nonzero iff the
+ filesystem format supports shortcutting symlink translation.
+ The library guarantees that users will not be able to read or write
+ the contents of the node directly, and the library will only do so
+ if the symlink hook functions return EINVAL or are not defined.
+ The library knows that the dn_stat.st_size field is the length of
+ the symlink, even if the hook functions are used. */
+int diskfs_shortcut_symlink;
+
+/* The user may define this variable. This should be nonzero iff the
+ filesystem format supports shortcutting chrdev translation. */
+int diskfs_shortcut_chrdev;
+
+/* The user may define this variable. This should be nonzero iff the
+ filesystem format supports shortcutting blkdev translation. */
+int diskfs_shortcut_blkdev;
+
+/* The user may define this variable. This should be nonzero iff the
+ filesystem format supports shortcutting fifo translation. */
+int diskfs_shortcut_fifo;
+
+/* The user may define this variable. This should be nonzero iff the
+ filesystem format supports shortcutting ifsock translation. */
+int diskfs_shortcut_ifsock;
+
+/* The user may define this variable, otherwise it has a default value of 30.
+ diskfs_set_sync_interval is called with this value when the first diskfs
+ thread is started up (in diskfs_spawn_first_threa). */
+extern int diskfs_default_sync_interval;
+
+/* The user must define this variable, which should be a string that somehow
+ identifies the particular disk this filesystem is interpreting. It is
+ generally only used to print messages or to distinguish instances of the
+ same filesystem type from one another. If this filesystem accesses no
+ external media, then define this to be 0. */
+extern char *diskfs_disk_name;
+
+/* The user must define this function. Set *STATFSBUF with
+ appropriate values to reflect the current state of the filesystem. */
+error_t diskfs_set_statfs (fsys_statfsbuf_t *statfsbuf);
+
+/* The user must define this function. Lookup in directory DP (which
+ is locked) the name NAME. TYPE will either be LOOKUP, CREATE,
+ RENAME, or REMOVE. CRED identifies the user making the call.
+
+ If the name is found, return zero, and (if NP is nonzero) set *NP
+ to point to the node for it, locked. If the name is not found,
+ return ENOENT, and (if NP is nonzero) set *NP to zero. If NP is
+ zero, then the node found must not be locked, even transitorily.
+ Lookups for REMOVE and RENAME (which must often check permissions
+ on the node being found) will always set NP.
+
+ If DS is nonzero then:
+ For LOOKUP: set *DS to be ignored by diskfs_drop_dirstat.
+ For CREATE: on success, set *DS to be ignored by diskfs_drop_dirstat.
+ on failure, set *DS for a future call to diskfs_direnter.
+ For RENAME: on success, set *DS for a future call to diskfs_dirrewrite.
+ on failure, set *DS for a future call to diskfs_direnter.
+ For REMOVE: on success, set *DS for a future call to diskfs_dirremove.
+ on failure, set *DS to be ignored by diskfs_drop_dirstat.
+ The caller of this function guarantees that if DS is nonzero, then
+ either the appropriate call listed above or diskfs_drop_dirstat will
+ be called with DS before the directory DP is unlocked, and guarantees
+ that no lookup calls will be made on this directory between this
+ lookup and the use (or descruction) of *DS.
+
+ If you use the library's versions of diskfs_rename_dir,
+ diskfs_clear_directory, and diskfs_init_dir, then lookups for `..'
+ might have the flag SPEC_DOTDOT or'd in. This has the following special
+ meaning:
+ For LOOKUP: DP should be unlocked and its reference dropped before
+ returning.
+ For RENAME and REMOVE: The node being found (*NP) is already held
+ locked, so don't lock it or add a reference to it.
+ (SPEC_DOTDOT will not be given with CREATE.)
+
+ Return ENOENT if NAME isn't in the directory.
+ Return EAGAIN if NAME refers to the `..' of this filesystem's root.
+ Return EIO if appropriate.
+*/
+error_t diskfs_lookup_hard (struct node *dp,
+ const char *name, enum lookup_type type,
+ struct node **np, struct dirstat *ds,
+ struct protid *cred);
+
+/* The user must define this function. Add NP to directory DP
+ under the name NAME. This will only be called after an
+ unsuccessful call to diskfs_lookup of type CREATE or RENAME; DP
+ has been locked continuously since that call and DS is as that call
+ set it, NP is locked. CRED identifies the user responsible
+ for the call (to be used only to validate directory growth). */
+error_t diskfs_direnter_hard (struct node *dp, const char *name,
+ struct node *np, struct dirstat *ds,
+ struct protid *cred);
+
+/* The user must define this function. This will only be called after
+ a successful call to diskfs_lookup of type RENAME; this call should change
+ the name found in directory DP to point to node NP instead of its previous
+ referent. DP has been locked continuously since the call to diskfs_lookup
+ and DS is as that call set it; NP is locked. */
+error_t diskfs_dirrewrite_hard (struct node *dp, struct node *np,
+ struct dirstat *ds);
+
+/* The user must define this function. This will only be called after a
+ successful call to diskfs_lookup of type REMOVE; this call should remove
+ the name found from the directory DS. DP has been locked continuously since
+ the call to diskfs_lookup and DS is as that call set it. */
+error_t diskfs_dirremove_hard (struct node *dp, struct dirstat *ds);
+
+/* The user must define this function. Initialize DS such that
+ diskfs_drop_dirstat will ignore it. */
+void diskfs_null_dirstat (struct dirstat *ds);
+
+/* The user must define this function. DS has been set by a previous
+ call to diskfs_lookup on directory DP; this function is
+ guaranteed to be called if none of
+ diskfs_dir{enter,rename,rewrite} is, and should free any state
+ retained by a struct dirstat. DP has been locked continuously since
+ the call to diskfs_lookup. */
+error_t diskfs_drop_dirstat (struct node *dp, struct dirstat *ds);
+
+/* The user must define this function. Return N directory entries
+ starting at ENTRY from locked directory node DP. Fill *DATA with
+ the entries; that pointer currently points to *DATACNT bytes. If
+ it isn't big enough, vm_allocate into *DATA. Set *DATACNT with the
+ total size used. Fill AMT with the number of entries copied.
+ Regardless, never copy more than BUFSIZ bytes. If BUFSIZ is 0,
+ then there is no limit on *DATACNT; if N is -1, then there is no limit
+ on AMT. */
+error_t diskfs_get_directs (struct node *dp, int entry, int n,
+ char **data, u_int *datacnt,
+ vm_size_t bufsiz, int *amt);
+
+/* The user must define this function. For locked node NP (for which
+ diskfs_node_translated is true) look up the name of its translator.
+ Store the name into newly malloced storage; set *NAMELEN to the
+ total length. */
+error_t diskfs_get_translator (struct node *np, char **namep, u_int *namelen);
+
+/* The user must define this function. For locked node NP, set
+ the name of the translating program to be NAME, length NAMELEN. CRED
+ identifies the user responsible for the call. */
+error_t diskfs_set_translator (struct node *np,
+ const char *name, u_int namelen,
+ struct protid *cred);
+
+/* The user must define this function. Truncate locked node NP to be SIZE
+ bytes long. (If NP is already less than or equal to SIZE bytes
+ long, do nothing.) If this is a symlink (and diskfs_shortcut_symlink
+ is set) then this should clear the symlink, even if
+ diskfs_create_symlink_hook stores the link target elsewhere. */
+error_t diskfs_truncate (struct node *np, off_t size);
+
+/* The user must define this function. Grow the disk allocated to locked node
+ NP to be at least SIZE bytes, and set NP->allocsize to the actual
+ allocated size. (If the allocated size is already SIZE bytes, do
+ nothing.) CRED identifies the user responsible for the call. */
+error_t diskfs_grow (struct node *np, off_t size, struct protid *cred);
+
+/* The user must define this function. Write to disk (synchronously
+ iff WAIT is nonzero) from format-specific buffers any non-paged
+ metadata. If CLEAN is nonzero, then after this is written the
+ filesystem will be absolutely clean, and the non-paged metadata can
+ so indicate. */
+error_t diskfs_set_hypermetadata (int wait, int clean);
+
+/* The user must define this function. Allocate a new node to be of
+ mode MODE in locked directory DP (don't actually set the mode or
+ modify the dir, that will be done by the caller); the user
+ responsible for the request can be identified with CRED. Set *NP
+ to be the newly allocated node. */
+error_t diskfs_alloc_node (struct node *dp, mode_t mode, struct node **np);
+
+/* Free node NP; the on disk copy has already been synced with
+ diskfs_node_update (where NP->dn_stat.st_mode was 0). It's
+ mode used to be MODE. */
+void diskfs_free_node (struct node *np, mode_t mode);
+
+/* Node NP has no more references; free local state, including *NP
+ if it isn't to be retained. diskfs_node_refcnt_lock is held. */
+void diskfs_node_norefs (struct node *np);
+
+/* The user must define this function. Node NP has some light
+ references, but has just lost its last hard references. Take steps
+ so that if any light references can be freed, they are. NP is locked
+ as is the pager refcount lock. This function will be called after
+ diskfs_lost_hardrefs. */
+void diskfs_try_dropping_softrefs (struct node *np);
+
+/* The user must define this funcction. Node NP has some light
+ references but has just lost its last hard reference. NP is locked. */
+void diskfs_lost_hardrefs (struct node *np);
+
+/* The user must define this function. Node NP has just acquired
+ a hard reference where it had none previously. It is thus now
+ OK again to have light references without real users. NP is
+ locked. */
+void diskfs_new_hardrefs (struct node *np);
+
+/* The user must define this function. Return non-zero if locked
+ directory DP is empty. If the user does not redefine
+ diskfs_clear_directory and diskfs_init_directory, then `empty'
+ means `possesses entries labelled . and .. only'. CRED
+ identifies the user making the call (if this user can't search
+ the directory, then this routine should fail). */
+int diskfs_dirempty (struct node *dp, struct protid *cred);
+
+/* The user may define this function. Return 0 if NP's mode can be
+ changed to MODE; otherwise return an error code. It must always be
+ possible to clear the mode; diskfs will not ask for permission
+ before doing so. */
+error_t diskfs_validate_mode_change (struct node *np, mode_t mode);
+
+/* The user may define this function. Return 0 if NP's owner can be
+ changed to UID; otherwise return an error code. */
+error_t diskfs_validate_owner_change (struct node *np, uid_t uid);
+
+/* The user may define this function. Return 0 if NP's group can be
+ changed to GID; otherwise return an error code. */
+error_t diskfs_validate_group_change (struct node *np, gid_t gid);
+
+/* The user may define this function. Return 0 if NP's author can be
+ changed to AUTHOR; otherwise return an error code. */
+error_t diskfs_validate_author_change (struct node *np, uid_t author);
+
+/* The user may define this function. Return 0 if NP's flags can be
+ changed to FLAGS; otherwise return an error code. It must always
+ be possible to clear the flags. */
+error_t diskfs_validate_flags_change (struct node *np, int flags);
+
+/* The user may define this function. Return 0 if NP's rdev can be
+ changed to RDEV; otherwise return an error code. */
+error_t diskfs_validate_rdev_change (struct node *np, dev_t rdev);
+
+/* The user must define this function. Sync the info in NP->dn_stat
+ and any associated format-specific information to disk. If WAIT is true,
+ then return only after the physicial media has been completely updated. */
+void diskfs_write_disknode (struct node *np, int wait);
+
+/* The user must define this function. Sync the file contents and all
+ associated meta data of file NP to disk (generally this will involve
+ calling diskfs_node_update for much of the metadata). If WAIT is true,
+ then return only after the physical media has been completely updated. */
+void diskfs_file_update (struct node *np, int wait);
+
+/* The user must define this function. For each active node, call
+ FUN. The node is to be locked around the call to FUN. If FUN
+ returns non-zero for any node, then immediately stop, and return
+ that value. */
+error_t diskfs_node_iterate (error_t (*fun)(struct node *));
+
+/* The user must define this function. Sync all the pagers and any
+ data belonging on disk except for the hypermetadata. If WAIT is true,
+ then return only after the physicial media has been completely updated. */
+void diskfs_sync_everything (int wait);
+
+/* Shutdown all pagers; this is done when the filesystem is exiting and is
+ irreversable. */
+void diskfs_shutdown_pager ();
+
+/* The user must define this function. Return a memory object port (send
+ right) for the file contents of NP. PROT is the maximum allowable
+ access. On errors, return MACH_PORT_NULL and set errno. */
+mach_port_t diskfs_get_filemap (struct node *np, vm_prot_t prot);
+
+/* The user must define this function. Return true if there are pager
+ ports exported that might be in use by users. If this returns false, then
+ further pager creation is also blocked. */
+int diskfs_pager_users ();
+
+/* Return the bitwise or of the maximum prot parameter (the second arg to
+ diskfs_get_filemap) for all active user pagers. */
+vm_prot_t diskfs_max_user_pager_prot ();
+
+/* The user must define this function. Return a `struct pager *' suitable
+ for use as an argument to diskfs_register_memory_fault_area that
+ refers to the pager returned by diskfs_get_filemap for node NP.
+ NP is locked. */
+struct pager *diskfs_get_filemap_pager_struct (struct node *np);
+
+/* The user may define this function. It is called when the disk has been
+ changed from read-only to read-write mode or vice-versa. READONLY is the
+ new state (which is also reflected in DISKFS_READONLY). This function is
+ also called during initial startup if the filesystem is to be writable. */
+void diskfs_readonly_changed (int readonly);
+
+/* The user must define this function. It must invalidate all cached global
+ state, and re-read it as necessary from disk, without writing anything.
+ It is always called with DISKFS_READONLY true. diskfs_node_reload is
+ subsequently called on all active nodes, so this call needn't re-read any
+ node-specific data. */
+error_t diskfs_reload_global_state ();
+
+/* The user must define this function. It must re-read all data specific to
+ NODE from disk, without writing anything. It is always called with
+ DISKFS_READONLY true. */
+error_t diskfs_node_reload (struct node *node);
+
+/* If this function is nonzero (and diskfs_shortcut_symlink is set) it
+ is called to set a symlink. If it returns EINVAL or isn't set,
+ then the normal method (writing the contents into the file data) is
+ used. If it returns any other error, it is returned to the user. */
+error_t (*diskfs_create_symlink_hook)(struct node *np, const char *target);
+
+/* If this function is nonzero (and diskfs_shortcut_symlink is set) it
+ is called to read the contents of a symlink. If it returns EINVAL or
+ isn't set, then the normal method (reading from the file data) is
+ used. If it returns any other error, it is returned to the user. */
+error_t (*diskfs_read_symlink_hook)(struct node *np, char *target);
+
+/* The library exports the following functions for general use */
+
+/* Call this after arguments have been parsed to initialize the library.
+ You must call this before calling any other diskfs functions, and after
+ parsing diskfs options. */
+error_t diskfs_init_diskfs (void);
+
+/* Call this once the filesystem is fully initialized, to advertise the new
+ filesystem control port to our parent filesystem. If BOOTSTRAP is set,
+ the diskfs will call fsys_startup on that port as appropriate and return
+ the REALNODE returned in that call; otherwise we return MACH_PORT_NULL.
+ FLAGS specifies how to open REALNODE (from the O_* set). */
+mach_port_t diskfs_startup_diskfs (mach_port_t bootstrap, int flags);
+
+/* Call this after all format-specific initialization is done (except
+ for setting diskfs_root_node); at this point the pagers should be
+ ready to go. */
+void diskfs_spawn_first_thread (void);
+
+/* Once diskfs_root_node is set, call this if we are a bootstrap
+ filesystem. If you call this, then the library will call
+ diskfs_init_completed once it has a valid proc and auth port. */
+void diskfs_start_bootstrap ();
+
+/* Node NP now has no more references; clean all state. The
+ _diskfs_node_refcnt_lock must be held, and will be released
+ upon return. NP must be locked. */
+void diskfs_drop_node (struct node *np);
+
+/* Set on disk fields from NP->dn_stat; update ctime, atime, and mtime
+ if necessary. If WAIT is true, then return only after the physical
+ media has been completely updated. */
+void diskfs_node_update (struct node *np, int wait);
+
+/* Add a hard reference to a node. If there were no hard
+ references previously, then the node cannot be locked
+ (because you must hold a hard reference to hold the lock). */
+void diskfs_nref (struct node *np);
+
+/* Unlock node NP and release a hard reference; if this is the last
+ hard reference and there are no links to the file then request
+ soft references to be dropped. */
+void diskfs_nput (struct node *np);
+
+/* Release a hard reference on NP. If NP is locked by anyone, then
+ this cannot be the last hard reference (because you must hold a
+ hard reference in order to hold the lock). If this is the last
+ hard reference and there are no links, then request soft references
+ to be dropped. */
+void diskfs_nrele (struct node *np);
+
+/* Add a light reference to a node. */
+void diskfs_nref_light (struct node *np);
+
+/* Unlock node NP and release a light reference */
+void diskfs_nput_light (struct node *np);
+
+/* Release a light reference on NP. If NP is locked by anyone, then
+ this cannot be the last reference (because you must hold a
+ hard reference in order to hold the lock). */
+void diskfs_nrele_light (struct node *np);
+
+/* Reading and writing of files. this is called by other filesystem
+ routines and handles extension of files automatically. NP is the
+ node to be read or written, and must be locked. DATA will be
+ written or filled. OFF identifies where in thi fel the I/O is to
+ take place (-1 is not allowed). AMT is the size of DATA and tells
+ how much to copy. DIR is 1 for writing and 0 for reading. CRED is
+ the user doing the access (only used to validate attempted file
+ extension). For reads, *AMTREAD is filled with the amount actually
+ read. */
+error_t
+diskfs_node_rdwr (struct node *np, char *data, off_t off,
+ size_t amt, int dir, struct protid *cred,
+ size_t *amtread);
+
+
+/* Send notifications to users who have requested them with
+ dir_notice_changes for directory DP. The type of modification and
+ affected name are TYPE and NAME respectively. This should be
+ called by diskfs_direnter, diskfs_dirremove, and diskfs_dirrewrite,
+ and anything else that changes the directory, after the change is
+ fully completed. */
+void
+diskfs_notice_dirchange (struct node *dp, enum dir_changed_type type,
+ const char *name);
+
+/* Send notifications to users who have requested them with
+ file_notice_changes for file NP. The type of modification is TYPE.
+ START and END identify the affected region of the file's data.
+ This should be called after the change is fully completed. */
+void
+diskfs_notice_filechange (struct node *np, enum file_changed_type type,
+ off_t start, off_t end);
+
+/* Create a new node structure with DS as its physical disknode.
+ The new node will have one hard reference and no light references. */
+struct node *diskfs_make_node (struct disknode *dn);
+
+
+/* The library also exports the following functions; they are not generally
+ useful unless you are redefining other functions the library provides. */
+
+/* Lookup in directory DP (which is locked) the name NAME. TYPE will
+ either be LOOKUP, CREATE, RENAME, or REMOVE. CRED identifies the
+ user making the call.
+
+ NAME will have leading and trailing slashes stripped. It is an
+ error if there are internal slashes. NAME will be modified in
+ place if there are slashes in it; it is therefore an error to
+ specify a constant NAME which contains slashes.
+
+ If the name is found, return zero, and (if NP is nonzero) set *NP
+ to point to the node for it, locked. If the name is not found,
+ return ENOENT, and (if NP is nonzero) set *NP to zero. If NP is
+ zero, then the node found must not be locked, even transitorily.
+ Lookups for REMOVE and RENAME (which must often check permissions
+ on the node being found) will always set NP.
+
+ If DS is nonzero then:
+ For LOOKUP: set *DS to be ignored by diskfs_drop_dirstat.
+ For CREATE: on success, set *DS to be ignored by diskfs_drop_dirstat.
+ on failure, set *DS for a future call to diskfs_direnter.
+ For RENAME: on success, set *DS for a future call to diskfs_dirrewrite.
+ on failure, set *DS for a future call to diskfs_direnter.
+ For REMOVE: on success, set *DS for a future call to diskfs_dirremove.
+ on failure, set *DS to be ignored by diskfs_drop_dirstat.
+ The caller of this function guarantees that if DS is nonzero, then
+ either the appropriate call listed above or diskfs_drop_dirstat will
+ be called with DS before the directory DP is unlocked, and guarantees
+ that no lookup calls will be made on this directory between this
+ lookup and the use (or descruction) of *DS.
+
+ If you use the library's versions of diskfs_rename_dir,
+ diskfs_clear_directory, and diskfs_init_dir, then lookups for `..'
+ might have the flag SPEC_DOTDOT or'd in. This has the following special
+ meaning:
+ For LOOKUP: DP should be unlocked and its reference dropped before
+ returning.
+ For RENAME and REMOVE: The node being found (*NP) is already held
+ locked, so don't lock it or add a reference to it.
+ (SPEC_DOTDOT will not be given with CREATE.)
+
+ Return ENOTDIR if DP is not a directory.
+ Return EACCES if CRED isn't allowed to search DP.
+ Return EACCES if completing the operation will require writing
+ the directory and diskfs_checkdirmod won't allow the modification.
+ Return ENOENT if NAME isn't in the directory.
+ Return EAGAIN if NAME refers to the `..' of this filesystem's root.
+ Return EIO if appropriate.
+
+ This function is a wrapper for diskfs_lookup_hard.
+*/
+error_t diskfs_lookup (struct node *dp,
+ char *name, enum lookup_type type,
+ struct node **np, struct dirstat *ds,
+ struct protid *cred);
+
+/* Add NP to directory DP under the name NAME. This will only be
+ called after an unsuccessful call to diskfs_lookup of type CREATE
+ or RENAME; DP has been locked continuously since that call and DS
+ is as that call set it, NP is locked. CRED identifies the user
+ responsible for the call (to be used only to validate directory
+ growth). This function is a wrapper for diskfs_direnter_hard. */
+error_t
+diskfs_direnter (struct node *dp, const char *name, struct node *np,
+ struct dirstat *ds, struct protid *cred);
+
+/* This will only be called after a successful call to diskfs_lookup
+ of type RENAME; this call should change the name found in directory
+ DP to point to node NP instead of its previous referent, OLDNP. DP
+ has been locked continuously since the call to diskfs_lookup and DS
+ is as that call set it; NP is locked. This routine should call
+ diskfs_notice_dirchange if DP->dirmod_reqs is nonzero. NAME is the
+ name of OLDNP inside DP; it is this reference which is being
+ rewritten. This function is a wrapper for diskfs_dirrewrite_hard. */
+error_t diskfs_dirrewrite (struct node *dp, struct node *oldnp,
+ struct node *np, const char *name,
+ struct dirstat *ds);
+
+/* This will only be called after a successful call to diskfs_lookup
+ of type REMOVE; this call should remove the name found from the
+ directory DS. DP has been locked continuously since the call to
+ diskfs_lookup and DS is as that call set it. This routine should
+ call diskfs_notice_dirchange if DP->dirmod_reqs is nonzero. This
+ function is a wrapper for diskfs_dirremove_hard. The entry being
+ removed has name NAME and refers to NP. */
+error_t diskfs_dirremove (struct node *dp, struct node *np,
+ const char *name, struct dirstat *ds);
+
+/* Return the node corresponding to CACHE_ID in *NPP. */
+error_t diskfs_cached_lookup (int cache_id, struct node **npp);
+
+/* Create a new node. Give it MODE; if that includes IFDIR, also
+ initialize `.' and `..' in the new directory. Return the node in NPP.
+ CRED identifies the user responsible for the call. If NAME is nonzero,
+ then link the new node into DIR with name NAME; DS is the result of a
+ prior diskfs_lookup for creation (and DIR has been held locked since).
+ DIR must always be provided as at least a hint for disk allocation
+ strategies. */
+error_t
+diskfs_create_node (struct node *dir, const char *name, mode_t mode,
+ struct node **newnode, struct protid *cred,
+ struct dirstat *ds);
+
+/* Create and return a protid for an existing peropen PO in CRED,
+ referring to user USER. The node PO->np must be locked. */
+error_t diskfs_create_protid (struct peropen *po, struct iouser *user,
+ struct protid **cred);
+
+/* Build and return in CRED a protid which has no user identification, for
+ peropen PO. The node PO->np must be locked. */
+error_t diskfs_start_protid (struct peropen *po, struct protid **cred);
+
+/* Finish building protid CRED started with diskfs_start_protid;
+ the user to install is USER. */
+void diskfs_finish_protid (struct protid *cred, struct iouser *user);
+
+/* Create and return a new peropen structure on node NP with open
+ flags FLAGS. The initial values for the root_parent, shadow_root, and
+ shadow_root_parent fields are copied from CONTEXT if it's non-zero,
+ otherwise zerod. */
+struct peropen *diskfs_make_peropen (struct node *np, int flags,
+ struct peropen *context);
+
+/* Called when a protid CRED has no more references. (Because references\
+ to protids are maintained by the port management library, this is
+ installed in the clean routines list.) The ports library will
+ free the structure for us. */
+void diskfs_protid_rele (void *arg);
+
+/* Decrement the reference count on a peropen structure. */
+void diskfs_release_peropen (struct peropen *po);
+
+/* Node NP has just been found in DIR with NAME. If NP is null, that
+ means that this name has been confirmed as absent in the directory. */
+void diskfs_enter_lookup_cache (struct node *dir, struct node *np,
+ const char *name);
+
+/* Purge all references in the cache to NP as a node inside
+ directory DP. */
+void diskfs_purge_lookup_cache (struct node *dp, struct node *np);
+
+/* Scan the cache looking for NAME inside DIR. If we don't know
+ anything entry at all, then return 0. If the entry is confirmed to
+ not exist, then return -1. Otherwise, return NP for the entry, with
+ a newly allocated reference. */
+struct node *diskfs_check_lookup_cache (struct node *dir, const char *name);
+
+/* Rename directory node FNP (whose parent is FDP, and which has name
+ FROMNAME in that directory) to have name TONAME inside directory
+ TDP. None of these nodes are locked, and none should be locked
+ upon return. This routine is serialized, so it doesn't have to be
+ reentrant. Directories will never be renamed except by this
+ routine. FROMCRED and TOCRED are the users responsible for
+ FDP/FNP and TDP respectively. This routine assumes the usual
+ convention where `.' and `..' are represented by ordinary links;
+ if that is not true for your format, you have to redefine this
+ function.*/
+error_t
+diskfs_rename_dir (struct node *fdp, struct node *fnp, const char *fromname,
+ struct node *tdp, const char *toname,
+ struct protid *fromcred, struct protid *tocred);
+
+/* Clear the `.' and `..' entries from directory DP. Its parent is
+ PDP, and the user responsible for this is identified by CRED. Both
+ directories must be locked. This routine assumes the usual
+ convention where `.' and `..' are represented by ordinary links; if
+ that is not true for your format, you have to redefine this
+ function. */
+error_t diskfs_clear_directory (struct node *dp, struct node *pdp,
+ struct protid *cred);
+
+/* Locked node DP is a new directory; add whatever links are necessary
+ to give it structure; its parent is the (locked) node PDP.
+ This routine may not call diskfs_lookup on PDP. The new directory
+ must be clear within the meaning of diskfs_dirempty. This routine
+ assumes the usual convention where `.' and `..' are represented by
+ ordinary links; if that is not true for your format, you have to
+ redefine this function. CRED identifies the user making the call. */
+error_t
+diskfs_init_dir (struct node *dp, struct node *pdp, struct protid *cred);
+
+/* If NP->dn_set_ctime is set, then modify NP->dn_stat.st_ctime
+ appropriately; do the analogous operation for atime and mtime as well. */
+void diskfs_set_node_times (struct node *np);
+
+/* Shutdown the filesystem; flags are as for fsys_shutdown. */
+error_t diskfs_shutdown (int flags);
+
+/* Change an active filesystem between read-only and writable modes, setting
+ the global variable DISKFS_READONLY to reflect the current mode. If an
+ error is returned, nothing will have changed. DISKFS_FSYS_LOCK should be
+ held while calling this routine. */
+error_t diskfs_set_readonly (int readonly);
+
+/* Re-read all incore data structures from disk. This will only work if
+ DISKFS_READONLY is true. DISKFS_FSYS_LOCK should be held while calling
+ this routine. */
+error_t diskfs_remount ();
+
+/* Called by S_fsys_startup for execserver bootstrap. The execserver
+ is able to function without a real node, hence this fraud. Arguments
+ are all as for fsys_startup in <hurd/fsys.defs>. */
+error_t diskfs_execboot_fsys_startup (mach_port_t port, int flags,
+ mach_port_t ctl, mach_port_t *real,
+ mach_msg_type_name_t *realpoly);
+
+/* Establish a thread to sync the filesystem every INTERVAL seconds, or
+ never, if INTERVAL is zero. If an error occurs creating the thread, it is
+ returned, otherwise 0. Subsequent calls will create a new thread and
+ (eventually) get rid of the old one; the old thread won't do any more
+ syncs, regardless. */
+error_t diskfs_set_sync_interval (int interval);
+
+/* Parse and execute the runtime options in ARGZ & ARGZ_LEN. EINVAL is
+ returned if some option is unrecognized. The default definition of this
+ routine will parse them using DISKFS_RUNTIME_ARGP, which see. */
+error_t diskfs_set_options (const char *argz, size_t argz_len);
+
+/* Append to the malloced string *ARGZ of length *ARGZ_LEN a NUL-separated
+ list of the arguments to this translator. The default definition of this
+ routine simply calls diskfs_append_std_options. */
+error_t diskfs_append_args (char **argz, unsigned *argz_len);
+
+/* If this is defined or set to an argp structure, it will be used by the
+ default diskfs_set_options to handle runtime option parsing. The default
+ definition is initialized to a pointer to DISKFS_STD_RUNTIME_ARGP. */
+extern struct argp *diskfs_runtime_argp;
+
+/* An argp for the standard diskfs runtime options. The default definition
+ of DISKFS_RUNTIME_ARGP points to this, although if the user redefines
+ that, he may chain this onto his argp as well. */
+extern const struct argp diskfs_std_runtime_argp;
+
+/* An argp structure for the standard diskfs command line arguments. The
+ user may call argp_parse on this to parse the command line, chain it onto
+ the end of his own argp structure, or ignore it completely. */
+extern const struct argp diskfs_startup_argp;
+
+/* An argp structure for the standard diskfs command line arguments plus a
+ store specification. The address of a location in which to return the
+ resulting struct store_parsed structure should be passed as the input
+ argument to argp_parse; see the declaration for STORE_ARGP in
+ <hurd/store.h> for more information. */
+extern const struct argp diskfs_store_startup_argp;
+
+/* *Appends* to ARGZ & ARGZ_LEN '\0'-separated options describing the standard
+ diskfs option state (note that unlike diskfs_get_options, ARGZ & ARGZ_LEN
+ must already have a sane value). */
+error_t diskfs_append_std_options (char **argz, unsigned *argz_len);
+
+/* Demultiplex incoming messages on ports created by libdiskfs. */
+int diskfs_demuxer (mach_msg_header_t *, mach_msg_header_t *);
+
+/* Check if the filesystem is readonly before an operation that
+ writes it. Return 1 if readonly, zero otherwise. */
+int diskfs_check_readonly (void);
+
+/* The diskfs library provides functions to demultiplex the fs, io,
+ fsys, interrupt, and notify interfaces. All the server routines
+ have the prefix `diskfs_S_'; `in' arguments of type file_t or io_t
+ appear as `struct protid *' to the stub. */
+
+
+/* All-in-one initialization function for diskfs filesystems using
+ libstore. This parses arguments using STARTUP_ARGP (defaulting to
+ diskfs_store_startup_argp if it's null; note that the ARGP_IN_ORDER
+ flag is always used); it calls diskfs_init_diskfs; it opens the
+ store with store_parsed_open, and sets diskfs_hard_readonly and
+ diskfs_readonly if the store is unwritable; it calls
+ diskfs_spawn_first_thread; finally, it returns the store and its
+ description in *STORE and *STORE_PARSED, and the bootstrap port in
+ *BOOTSTRAP. The caller should pass *BOOTSTRAP to
+ diskfs_startup_diskfs after setting diskfs_root_node.
+ (See <argp.h> and <hurd/store.h>.)
+
+ This call cannot return failure; if it encounters a fatal problem,
+ it prints a diagnostic on stderr (or the console) and exits the
+ program. */
+struct store *diskfs_init_main (struct argp *startup_argp,
+ int argc, char **argv,
+ struct store_parsed **store_parsed,
+ mach_port_t *bootstrap);
+
+/* The following are optional convenience routines and global variable, which
+ can be used by any user program that uses a mach device to hold the
+ underlying filesystem. */
+
+/* Make errors go somewhere reasonable. */
+void diskfs_console_stdio ();
+
+#endif /* hurd/diskfs.h */
diff --git a/libdiskfs/extra-version.c b/libdiskfs/extra-version.c
new file mode 100644
index 00000000..b1d78084
--- /dev/null
+++ b/libdiskfs/extra-version.c
@@ -0,0 +1,24 @@
+/* Default value for diskfs_extra_version
+ Copyright (C) 1996 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. */
+
+
+#include "priv.h"
+
+char *diskfs_extra_version = "";
diff --git a/libdiskfs/fhandle.h b/libdiskfs/fhandle.h
new file mode 100644
index 00000000..bd827d84
--- /dev/null
+++ b/libdiskfs/fhandle.h
@@ -0,0 +1,36 @@
+/* File handle type (for nfs server support)
+
+ Copyright (C) 1997,99 Free Software Foundation, Inc.
+
+ 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 the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef __FHANDLE_H__
+#define __FHANDLE_H__
+
+/* Must be exactly 28 bytes long */
+union diskfs_fhandle
+{
+ unsigned char bytes[28];
+ struct
+ {
+ int pad1;
+ int cache_id;
+ unsigned int gen;
+ } data;
+};
+
+#endif /* __FHANDLE_H__ */
diff --git a/libdiskfs/file-access.c b/libdiskfs/file-access.c
new file mode 100644
index 00000000..4a5eb17d
--- /dev/null
+++ b/libdiskfs/file-access.c
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 1994 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+#include <fcntl.h>
+
+kern_return_t
+diskfs_S_file_check_access (struct protid *cred,
+ int *type)
+{
+ struct node *np;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ np = cred->po->np;
+ mutex_lock (&np->lock);
+ *type = 0;
+ if (fshelp_access (&np->dn_stat, S_IREAD, cred->user) == 0)
+ *type |= O_READ;
+ if (fshelp_access (&np->dn_stat, S_IWRITE, cred->user) == 0)
+ *type |= O_WRITE;
+ if (fshelp_access (&np->dn_stat, S_IEXEC, cred->user) == 0)
+ *type |= O_EXEC;
+
+ mutex_unlock (&np->lock);
+
+ return 0;
+}
diff --git a/libdiskfs/file-chauthor.c b/libdiskfs/file-chauthor.c
new file mode 100644
index 00000000..6e49c53f
--- /dev/null
+++ b/libdiskfs/file-chauthor.c
@@ -0,0 +1,42 @@
+/* libdithkfth implementation of fth.defth: file_chauthor
+ Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "lithp.h"
+
+#include "priv.h"
+#include fth_TH_dot_h
+
+/* Implement file_chauthor as dethcribed in <hurd/fth.defth>. */
+kern_return_t
+dithkfth_TH_file_chauthor (struct protid *cred,
+ uid_t author)
+{
+ CHANGE_NODE_FIELD (cred,
+ ({
+ err = fthhelp_ithowner (&np->dn_thtat, cred->uther);
+ if (!err)
+ err = dithkfth_validate_author_change (np, author);
+ if (!err)
+ {
+ np->dn_thtat.tht_author = author;
+ np->dn_thet_theetime = 1;
+ if (np->filemod_reqs)
+ diskfs_notice_filechange(np, FILE_CHANGED_META,
+ 0, 0);
+ }
+ }));
+}
diff --git a/libdiskfs/file-chflags.c b/libdiskfs/file-chflags.c
new file mode 100644
index 00000000..01dc495c
--- /dev/null
+++ b/libdiskfs/file-chflags.c
@@ -0,0 +1,40 @@
+/* libdiskfs implementation of fs.defs:file_chflags
+ Copyright (C) 1992, 1993, 1994, 1996, 1998 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+
+/* Implement file_chflags as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_file_chflags (struct protid *cred,
+ int flags)
+{
+ CHANGE_NODE_FIELD (cred,
+ ({
+ err = fshelp_isowner (&np->dn_stat, cred->user);
+ if (!err)
+ err = diskfs_validate_flags_change (np, flags);
+ if (!err)
+ {
+ np->dn_stat.st_flags = flags;
+ np->dn_set_ctime = 1;
+ }
+ if (!err && np->filemod_reqs)
+ diskfs_notice_filechange(np, FILE_CHANGED_META,
+ 0, 0);
+ }));
+}
diff --git a/libdiskfs/file-chg.c b/libdiskfs/file-chg.c
new file mode 100644
index 00000000..e9535591
--- /dev/null
+++ b/libdiskfs/file-chg.c
@@ -0,0 +1,69 @@
+/*
+ Copyright (C) 1994, 1995 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+#include "ourfs_notify_U.h"
+
+kern_return_t
+diskfs_S_file_notice_changes (struct protid *cred, mach_port_t notify)
+{
+ error_t err;
+ struct modreq *req;
+ struct node *np;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ np = cred->po->np;
+ mutex_lock (&np->lock);
+ err = nowait_file_changed (notify, FILE_CHANGED_NULL, 0, 0);
+ if (err)
+ {
+ mutex_unlock (&np->lock);
+ return err;
+ }
+ req = malloc (sizeof (struct modreq));
+ req->port = notify;
+ req->next = np->filemod_reqs;
+ np->filemod_reqs = req;
+ mutex_unlock (&np->lock);
+ return 0;
+}
+
+void
+diskfs_notice_filechange (struct node *dp, enum file_changed_type type,
+ off_t start, off_t end)
+{
+ error_t err;
+ struct modreq **preq;
+
+ preq = &dp->filemod_reqs;
+ while (*preq)
+ {
+ struct modreq *req = *preq;
+ err = nowait_file_changed (req->port, type, start, end);
+ if (err)
+ { /* remove notify port */
+ *preq = req->next;
+ mach_port_deallocate (mach_task_self (), req->port);
+ free (req);
+ }
+ else
+ preq = &req->next;
+ }
+}
diff --git a/libdiskfs/file-chmod.c b/libdiskfs/file-chmod.c
new file mode 100644
index 00000000..09bbe0ea
--- /dev/null
+++ b/libdiskfs/file-chmod.c
@@ -0,0 +1,55 @@
+/* libdiskfs implementation of fs.defs: file_chmod
+ Copyright (C) 1992, 1993, 1994, 1996, 1997 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+/* Implement file_chmod as described in <hurd/fs.defs>. */
+error_t
+diskfs_S_file_chmod (struct protid *cred,
+ mode_t mode)
+{
+ mode &= ~(S_IFMT | S_ISPARE | S_ITRANS);
+
+ CHANGE_NODE_FIELD (cred,
+ ({
+ if (!(err = fshelp_isowner (&np->dn_stat, cred->user)))
+ {
+ if (!idvec_contains (cred->user->uids, 0))
+ {
+ if (!S_ISDIR (np->dn_stat.st_mode))
+ mode &= ~S_ISVTX;
+ if (!idvec_contains (cred->user->gids,
+ np->dn_stat.st_gid))
+ mode &= ~S_ISGID;
+ if (!idvec_contains (cred->user->uids,
+ np->dn_stat.st_uid))
+ mode &= ~S_ISUID;
+ }
+ mode |= (np->dn_stat.st_mode & (S_IFMT | S_ISPARE));
+ err = diskfs_validate_mode_change (np, mode);
+ if (!err)
+ {
+ np->dn_stat.st_mode = mode;
+ np->dn_set_ctime = 1;
+ if (np->filemod_reqs)
+ diskfs_notice_filechange(np,
+ FILE_CHANGED_META,
+ 0, 0);
+ }
+ }
+ }));
+}
diff --git a/libdiskfs/file-chown.c b/libdiskfs/file-chown.c
new file mode 100644
index 00000000..ecb851f2
--- /dev/null
+++ b/libdiskfs/file-chown.c
@@ -0,0 +1,64 @@
+/* libdiskfs implementetation of fs.defs: file_chown
+ Copyright (C) 1992, 1993, 1994, 1996, 1999 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+
+/* Implement file_chown as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_file_chown (struct protid *cred,
+ uid_t uid,
+ gid_t gid)
+{
+ if (uid == (uid_t) -1 && gid == (gid_t) -1) /* No change requested. */
+ return 0;
+
+ CHANGE_NODE_FIELD (cred,
+ ({
+ err = fshelp_isowner (&np->dn_stat, cred->user);
+ if (err
+ || (((uid != (uid_t) -1
+ && !idvec_contains (cred->user->uids, uid))
+ || (gid != (gid_t) -1
+ && !idvec_contains (cred->user->gids, gid)))
+ && !idvec_contains (cred->user->uids, 0)))
+ err = EPERM;
+ else
+ {
+ if (uid != (uid_t) -1)
+ err = diskfs_validate_owner_change (np, uid);
+ if (!err && gid != (gid_t) -1)
+ err = diskfs_validate_group_change (np, gid);
+ if (!err)
+ {
+ if (uid != (uid_t) -1)
+ {
+ np->dn_stat.st_uid = uid;
+ if (np->author_tracks_uid)
+ np->dn_stat.st_author = uid;
+ }
+ if (gid != (gid_t) -1)
+ np->dn_stat.st_gid = gid;
+ np->dn_set_ctime = 1;
+ if (np->filemod_reqs)
+ diskfs_notice_filechange(np,
+ FILE_CHANGED_META,
+ 0, 0);
+ }
+ }
+ }));
+}
diff --git a/libdiskfs/file-exec.c b/libdiskfs/file-exec.c
new file mode 100644
index 00000000..521f3528
--- /dev/null
+++ b/libdiskfs/file-exec.c
@@ -0,0 +1,192 @@
+/*
+ Copyright (C) 1993, 94, 95, 96, 97, 98 Free Software Foundation, Inc.
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include "priv.h"
+#include "fs_S.h"
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <hurd/exec.h>
+#include <hurd/paths.h>
+#include <string.h>
+#include <idvec.h>
+
+kern_return_t
+diskfs_S_file_exec (struct protid *cred,
+ task_t task,
+ int flags,
+ char *argv,
+ u_int argvlen,
+ char *envp,
+ u_int envplen,
+ mach_port_t *fds,
+ u_int fdslen,
+ mach_port_t *portarray,
+ u_int portarraylen,
+ int *intarray,
+ u_int intarraylen,
+ mach_port_t *deallocnames,
+ u_int deallocnameslen,
+ mach_port_t *destroynames,
+ u_int destroynameslen)
+{
+ struct node *np;
+ uid_t uid;
+ gid_t gid;
+ mode_t mode;
+ int suid, sgid;
+ struct protid *newpi;
+ error_t err = 0;
+ mach_port_t execserver;
+ int cached_exec;
+ struct hurd_userlink ulink;
+#define RETURN(code) do { err = (code); goto out; } while (0)
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ /* Get a light reference to the cached exec server port. */
+ execserver = _hurd_port_get (&_diskfs_exec_portcell, &ulink);
+ cached_exec = (execserver != MACH_PORT_NULL);
+ if (execserver == MACH_PORT_NULL)
+ {
+ /* No cached port. Look up the canonical naming point. */
+ execserver = file_name_lookup (_SERVERS_EXEC, 0, 0);
+ if (execserver == MACH_PORT_NULL)
+ return EOPNOTSUPP; /* No exec server, no exec. */
+ else
+ {
+ /* Install the newly-gotten exec server port for other
+ threads to use, then get a light reference for this call. */
+ _hurd_port_set (&_diskfs_exec_portcell, execserver);
+ execserver = _hurd_port_get (&_diskfs_exec_portcell, &ulink);
+ }
+ }
+
+ np = cred->po->np;
+
+ mutex_lock (&np->lock);
+ mode = np->dn_stat.st_mode;
+ uid = np->dn_stat.st_uid;
+ gid = np->dn_stat.st_uid;
+ mutex_unlock (&np->lock);
+
+ if (_diskfs_noexec)
+ RETURN (EACCES);
+
+ if ((cred->po->openstat & O_EXEC) == 0)
+ RETURN (EBADF);
+
+ if (!((mode & (S_IXUSR|S_IXGRP|S_IXOTH))
+ || ((mode & S_IUSEUNK) && (mode & (S_IEXEC << S_IUNKSHIFT)))))
+ RETURN (EACCES);
+
+ if ((mode & S_IFMT) == S_IFDIR)
+ RETURN (EACCES);
+
+ suid = mode & S_ISUID;
+ sgid = mode & S_ISGID;
+ if (!_diskfs_nosuid && (suid || sgid))
+ {
+ int secure = 0;
+ error_t get_file_ids (struct idvec *uids, struct idvec *gids)
+ {
+ error_t err = idvec_merge (uids, cred->user->uids);
+ if (! err)
+ err = idvec_merge (gids, cred->user->gids);
+ return err;
+ }
+ err =
+ fshelp_exec_reauth (suid, uid, sgid, gid,
+ diskfs_auth_server_port, get_file_ids,
+ portarray, portarraylen, fds, fdslen, &secure);
+ if (secure)
+ flags |= EXEC_SECURE | EXEC_NEWTASK;
+ }
+
+ /* If the user can't read the file, then we should use a new task,
+ which would be inaccessible to the user. Actually, this doesn't
+ work, because the proc server will still give out the task port
+ to the user. Too many things depend on that that it can't be
+ changed. So this vague attempt isn't even worth trying. */
+#if 0
+ if (fshelp_access (&np->dn_stat, S_IREAD, cred->user))
+ flags |= EXEC_NEWTASK;
+#endif
+
+ if (! err)
+ err = diskfs_create_protid (diskfs_make_peropen (np, O_READ, cred->po),
+ cred->user, &newpi);
+
+ if (! err)
+ {
+ do
+ {
+ err = exec_exec (execserver,
+ ports_get_right (newpi),
+ MACH_MSG_TYPE_MAKE_SEND,
+ task, flags, argv, argvlen, envp, envplen,
+ fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
+ portarray, MACH_MSG_TYPE_COPY_SEND, portarraylen,
+ intarray, intarraylen,
+ deallocnames, deallocnameslen,
+ destroynames, destroynameslen);
+ if (err == MACH_SEND_INVALID_DEST)
+ {
+ if (cached_exec)
+ {
+ /* We were using a previously looked-up exec server port.
+ Try looking up a new one before giving an error. */
+ cached_exec = 0;
+ _hurd_port_free (&_diskfs_exec_portcell, &ulink, execserver);
+
+ execserver = file_name_lookup (_SERVERS_EXEC, 0, 0);
+ if (execserver == MACH_PORT_NULL)
+ err = EOPNOTSUPP;
+ else
+ {
+ _hurd_port_set (&_diskfs_exec_portcell, execserver);
+ execserver = _hurd_port_get (&_diskfs_exec_portcell,
+ &ulink);
+ }
+ }
+ else
+ err = EOPNOTSUPP;
+ }
+ } while (err == MACH_SEND_INVALID_DEST);
+ ports_port_deref (newpi);
+ }
+
+ if (! err)
+ {
+ unsigned int i;
+
+ mach_port_deallocate (mach_task_self (), task);
+ for (i = 0; i < fdslen; i++)
+ mach_port_deallocate (mach_task_self (), fds[i]);
+ for (i = 0; i < portarraylen; i++)
+ mach_port_deallocate (mach_task_self (), portarray[i]);
+ }
+
+ out:
+ _hurd_port_free (&_diskfs_exec_portcell, &ulink, execserver);
+
+ return err;
+}
diff --git a/libdiskfs/file-get-fs-opts.c b/libdiskfs/file-get-fs-opts.c
new file mode 100644
index 00000000..9ce2eedb
--- /dev/null
+++ b/libdiskfs/file-get-fs-opts.c
@@ -0,0 +1,54 @@
+/* Get run-time file system options
+
+ Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <errno.h>
+#include <string.h>
+#include <argz.h>
+#include "priv.h"
+
+error_t
+diskfs_S_file_get_fs_options (struct protid *cred,
+ char **data, unsigned *data_len)
+{
+ error_t err;
+ char *argz = 0;
+ size_t argz_len = 0;
+
+ if (! cred)
+ return EOPNOTSUPP;
+
+ err = argz_add (&argz, &argz_len, program_invocation_name);
+ if (err)
+ return err;
+
+ rwlock_reader_lock (&diskfs_fsys_lock);
+ err = diskfs_append_args (&argz, &argz_len);
+ rwlock_reader_unlock (&diskfs_fsys_lock);
+
+ if (! err)
+ /* Move ARGZ from a malloced buffer into a vm_alloced one. */
+ err = iohelp_return_malloced_buffer (argz, argz_len, data, data_len);
+ else
+ free (argz);
+
+ return err;
+}
diff --git a/libdiskfs/file-get-trans.c b/libdiskfs/file-get-trans.c
new file mode 100644
index 00000000..118222be
--- /dev/null
+++ b/libdiskfs/file-get-trans.c
@@ -0,0 +1,138 @@
+/* libdiskfs implementation of fs.defs: file_get_translator
+ Copyright (C) 1992,93,94,95,96,98,99 Free Software Foundation, Inc.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include <hurd/paths.h>
+#include <string.h>
+#include <stdio.h>
+#include "fs_S.h"
+
+/* Implement file_get_translator as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_file_get_translator (struct protid *cred,
+ char **trans,
+ u_int *translen)
+{
+ struct node *np;
+ error_t error = 0;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ np = cred->po->np;
+
+ mutex_lock (&np->lock);
+
+ /* First look for short-circuited translators. */
+ if (S_ISLNK (np->dn_stat.st_mode))
+ {
+ unsigned int len = sizeof _HURD_SYMLINK + np->dn_stat.st_size + 1;
+ int amt;
+ assert (diskfs_shortcut_symlink);
+ if (len > *translen)
+ *trans = mmap (0, len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ bcopy (_HURD_SYMLINK, *trans, sizeof _HURD_SYMLINK);
+
+ if (diskfs_read_symlink_hook)
+ error = (*diskfs_read_symlink_hook) (np,
+ *trans + sizeof _HURD_SYMLINK);
+ if (!diskfs_read_symlink_hook || error == EINVAL)
+ {
+ error = diskfs_node_rdwr (np, *trans + sizeof _HURD_SYMLINK,
+ 0, np->dn_stat.st_size, 0, cred, &amt);
+ if (!error)
+ assert (amt == np->dn_stat.st_size);
+ }
+ if (!error)
+ {
+ (*trans)[sizeof _HURD_SYMLINK + np->dn_stat.st_size] = '\0';
+ *translen = len;
+ }
+ else if (len > *translen)
+ munmap (trans, len);
+ }
+ else if (S_ISCHR (np->dn_stat.st_mode) || S_ISBLK (np->dn_stat.st_mode))
+ {
+ char *buf;
+ unsigned int buflen;
+
+ if (S_ISCHR (np->dn_stat.st_mode))
+ assert (diskfs_shortcut_chrdev);
+ else
+ assert (diskfs_shortcut_blkdev);
+
+ buflen = asprintf (&buf, "%s%c%d%c%d",
+ (S_ISCHR (np->dn_stat.st_mode)
+ ? _HURD_CHRDEV
+ : _HURD_BLKDEV),
+ '\0', (np->dn_stat.st_rdev >> 8) & 0377,
+ '\0', (np->dn_stat.st_rdev) & 0377);
+ buflen++; /* terminating nul */
+
+ if (buflen > *translen)
+ *trans = mmap (0, buflen, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ bcopy (buf, *trans, buflen);
+ free (buf);
+ *translen = buflen;
+ error = 0;
+ }
+ else if (S_ISFIFO (np->dn_stat.st_mode))
+ {
+ unsigned int len;
+
+ len = sizeof _HURD_FIFO;
+ if (len > *translen)
+ *trans = mmap (0, len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ bcopy (_HURD_FIFO, *trans, sizeof _HURD_FIFO);
+ *translen = len;
+ error = 0;
+ }
+ else if (S_ISSOCK (np->dn_stat.st_mode))
+ {
+ unsigned int len;
+
+ len = sizeof _HURD_IFSOCK;
+ if (len > *translen)
+ *trans = mmap (0, len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ bcopy (_HURD_IFSOCK, *trans, sizeof _HURD_IFSOCK);
+ *translen = len;
+ error = 0;
+ }
+ else
+ {
+ if (! (np->dn_stat.st_mode & S_IPTRANS))
+ error = EINVAL;
+ else
+ {
+ char *string;
+ u_int len;
+ error = diskfs_get_translator (np, &string, &len);
+ if (!error)
+ {
+ if (len > *translen)
+ *trans = mmap (0, len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ bcopy (string, *trans, len);
+ *translen = len;
+ free (string);
+ }
+ }
+ }
+
+ mutex_unlock (&np->lock);
+
+ return error;
+}
diff --git a/libdiskfs/file-get-transcntl.c b/libdiskfs/file-get-transcntl.c
new file mode 100644
index 00000000..528529fb
--- /dev/null
+++ b/libdiskfs/file-get-transcntl.c
@@ -0,0 +1,48 @@
+/* libkdiskfs implementation of fs.defs: file_get_translator_cntl
+ Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+
+/* Implement file_get_translator_cntl as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_file_get_translator_cntl (struct protid *cred,
+ mach_port_t *ctl,
+ mach_msg_type_name_t *ctltype)
+{
+ struct node *np;
+ error_t error;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ np = cred->po->np;
+
+ mutex_lock (&np->lock);
+
+ error = fshelp_isowner (&np->dn_stat, cred->user);
+ if (!error)
+ error = fshelp_fetch_control (&np->transbox, ctl);
+ if (!error && *ctl == MACH_PORT_NULL)
+ error = ENXIO;
+ if (!error)
+ *ctltype = MACH_MSG_TYPE_MOVE_SEND;
+
+ mutex_unlock (&np->lock);
+
+ return error;
+}
diff --git a/libdiskfs/file-getcontrol.c b/libdiskfs/file-getcontrol.c
new file mode 100644
index 00000000..4f1ae23a
--- /dev/null
+++ b/libdiskfs/file-getcontrol.c
@@ -0,0 +1,51 @@
+/* libdiskfs implementation of fs.defs:file_getcontrol.c
+ Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+
+/* Implement file_getcontrol as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_file_getcontrol (struct protid *cred,
+ mach_port_t *control,
+ mach_msg_type_name_t *controltype)
+{
+ int error = 0;
+ struct port_info *newpi;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ if (!idvec_contains (cred->user->uids, 0))
+ error = EPERM;
+ else
+ {
+ error = ports_create_port (diskfs_control_class, diskfs_port_bucket,
+ sizeof (struct port_info), &newpi);
+ if (! error)
+ {
+ spin_lock (&_diskfs_control_lock);
+ _diskfs_ncontrol_ports++;
+ spin_unlock (&_diskfs_control_lock);
+ *control = ports_get_right (newpi);
+ *controltype = MACH_MSG_TYPE_MAKE_SEND;
+ ports_port_deref (newpi);
+ }
+ }
+
+ return error;
+}
diff --git a/libdiskfs/file-getfh.c b/libdiskfs/file-getfh.c
new file mode 100644
index 00000000..a2dbb045
--- /dev/null
+++ b/libdiskfs/file-getfh.c
@@ -0,0 +1,60 @@
+/* Return a file handle (for nfs server support)
+
+ Copyright (C) 1997, 1999 Free Software Foundation
+
+ 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 the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <string.h>
+
+#include "priv.h"
+#include "fs_S.h"
+#include "fhandle.h"
+
+/* Return an NFS file handle for CRED in FH & FN_LEN. */
+error_t
+diskfs_S_file_getfh (struct protid *cred, char **fh, unsigned *fh_len)
+{
+ struct node *node;
+ union diskfs_fhandle *f;
+
+ if (! cred)
+ return EOPNOTSUPP;
+
+ if (! idvec_contains (cred->user->uids, 0))
+ return EPERM;
+
+ assert (sizeof *f == sizeof f->bytes);
+
+ node = cred->po->np;
+
+ mutex_lock (&node->lock);
+
+ if (*fh_len < sizeof (struct diskfs_fhandle))
+ *fh = mmap (0, sizeof (struct diskfs_fhandle), PROT_READ|PROT_WRITE,
+ MAP_ANON, 0, 0);
+ *fh_len = sizeof *f;
+
+ f = (union diskfs_fhandle *) *fh;
+
+ bzero (f, sizeof *f);
+ f->data.cache_id = node->cache_id;
+ f->data.gen = node->dn_stat.st_gen;
+
+ mutex_unlock (&node->lock);
+
+ return 0;
+}
diff --git a/libdiskfs/file-getlinknode.c b/libdiskfs/file-getlinknode.c
new file mode 100644
index 00000000..4b346c96
--- /dev/null
+++ b/libdiskfs/file-getlinknode.c
@@ -0,0 +1,39 @@
+/* libdiskfs implementation of fs.defs: file_getlinknode
+ Copyright (C) 1992, 1993, 1994 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+
+/* Implement file_getlinknode as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_file_getlinknode (struct protid *cred,
+ file_t *port,
+ mach_msg_type_name_t *portpoly)
+{
+ struct node *np;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ np = cred->po->np;
+ if (np == diskfs_root_node)
+ return EBUSY;
+
+ *port = ports_get_right (cred);
+ *portpoly = MACH_MSG_TYPE_MAKE_SEND;
+ return 0;
+}
diff --git a/libdiskfs/file-inv-trans.c b/libdiskfs/file-inv-trans.c
new file mode 100644
index 00000000..d3014164
--- /dev/null
+++ b/libdiskfs/file-inv-trans.c
@@ -0,0 +1,160 @@
+/*
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+#include <fcntl.h>
+
+/* Implement fs.defs:file_invoke_translator as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_file_invoke_translator (struct protid *cred __attribute__ ((unused)),
+ int flags __attribute__ ((unused)),
+ retry_type *retry __attribute__ ((unused)),
+ char *retry_name __attribute__ ((unused)),
+ mach_port_t *retrypt __attribute__ ((unused)),
+ mach_msg_type_name_t *retrypttype
+ __attribute__ ((unused)))
+{
+#if 0
+ /* XXX */
+ static mach_port_t _diskfs_dotdot_file = MACH_PORT_NULL;
+ error_t error = 0;
+ mode_t type;
+ struct node *np;
+ struct protid *newpi;
+
+ /* This code is very similar (but subtly different) from
+ dir-pathtrans.c and fsys-getroot.c. A way should be found to
+ combine them. */
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ flags &= O_HURD;
+
+ np = cred->po->np;
+
+ mutex_lock (&np->lock);
+
+ type = np->dn_stat.st_mode & S_IFMT;
+
+ repeat_transcheck:
+ /* Ignore O_NOTRANS in the following check */
+ if ((np->dn_stat.st_mode & S_IPTRANS)
+ || np->translator.control != MACH_PORT_NULL)
+ {
+ mach_port_t control = np->translator.control;
+
+ if (control == MACH_PORT_NULL)
+ {
+ /* This use of _diskfs_dotdot_file is completely and utterly
+ bogus. XXX */
+ if (error = diskfs_start_translator (np, _diskfs_dotdot_file))
+ {
+ mutex_unlock (&np->lock);
+ return error;
+ }
+ control = np->translator.control;
+ }
+
+ mach_port_mod_refs (mach_task_self (), control, MACH_PORT_RIGHT_SEND, 1);
+ mutex_unlock (&np->lock);
+ error = fsys_getroot (control,
+ cred->user->uids->ids, cred->user->uids->num,
+ cred->user->gids->ids, cred->user->gids->num,
+ flags, retry, retry_name, retrypt);
+ if (error == MACH_SEND_INVALID_DEST)
+ {
+ mutex_lock (&np->lock);
+ if (np->translator.control == control)
+ fshelp_translator_drop (&np->translator);
+ mach_port_deallocate (mach_task_self (), control);
+ error = 0;
+ goto repeat_transcheck;
+ }
+
+ if (!error && *retrypt != MACH_PORT_NULL)
+ *retrypttype = MACH_MSG_TYPE_MOVE_SEND;
+ else
+ *retrypttype = MACH_MSG_TYPE_COPY_SEND;
+
+ return error;
+ }
+
+ /* Ignore O_NOTRANS here. */
+ if (type == S_IFLNK && !(flags & O_NOLINK))
+ {
+ /* Handle symlink interpretation */
+ char pathbuf[np->dn_stat.st_size + 1];
+ int amt;
+
+ if (diskfs_read_symlink_hook)
+ error = (*diskfs_read_symlink_hook) (np, pathbuf);
+ if (!diskfs_read_symlink_hook || error == EINVAL)
+ error = diskfs_node_rdwr (np, pathbuf, 0, np->dn_stat.st_size, 0,
+ 0, &amt);
+ pathbuf[amt] = '\0';
+
+ mutex_unlock (&np->lock);
+ if (error)
+ return error;
+
+ if (pathbuf[0] == '/')
+ {
+ *retry = FS_RETRY_MAGICAL;
+ *retrypt = MACH_PORT_NULL;
+ *retrypttype = MACH_MSG_TYPE_COPY_SEND;
+ strcpy (retry_name, pathbuf);
+ return 0;
+ }
+ else
+ {
+ *retry = FS_RETRY_REAUTH;
+ *retrypt = _diskfs_dotdot_file;
+ *retrypttype = MACH_MSG_TYPE_COPY_SEND;
+ strcpy (retry_name, pathbuf);
+ return 0;
+ }
+ }
+
+ if ((type == S_IFSOCK || type == S_IFBLK
+ || type == S_IFCHR || type == S_IFIFO)
+ && (flags & (O_READ|O_WRITE|O_EXEC)))
+ error = EOPNOTSUPP;
+
+
+ flags &= ~OPENONLY_STATE_MODES;
+
+ error = diskfs_create_protid (diskfs_make_peropen (np, flags,
+ _diskfs_dotdot_file),
+ cred->user, &newpi);
+ if (! error)
+ {
+ *retry = FS_RETRY_NONE;
+ retry_name[0] = '\0';
+ *retrypt = ports_get_right (newpi);
+ *retrypttype = MACH_MSG_TYPE_MAKE_SEND;
+ ports_port_deref (newpi);
+ }
+
+ mutex_unlock (&np->lock);
+
+ return error;
+#else
+ return EOPNOTSUPP;
+#endif
+}
diff --git a/libdiskfs/file-lock-stat.c b/libdiskfs/file-lock-stat.c
new file mode 100644
index 00000000..75341617
--- /dev/null
+++ b/libdiskfs/file-lock-stat.c
@@ -0,0 +1,38 @@
+/*
+ Copyright (C) 1994, 1995 Free Software Foundation
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include "priv.h"
+#include "fs_S.h"
+
+kern_return_t
+diskfs_S_file_lock_stat (struct protid *cred,
+ int *mystatus,
+ int *otherstatus)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+
+ mutex_lock (&cred->po->np->lock);
+ *mystatus = cred->po->lock_status;
+ *otherstatus = cred->po->np->userlock.type;
+ mutex_unlock (&cred->po->np->lock);
+ return 0;
+}
diff --git a/libdiskfs/file-lock.c b/libdiskfs/file-lock.c
new file mode 100644
index 00000000..4a348546
--- /dev/null
+++ b/libdiskfs/file-lock.c
@@ -0,0 +1,38 @@
+/*
+ Copyright (C) 1993, 1994 Free Software Foundation
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include "priv.h"
+#include "fs_S.h"
+
+kern_return_t
+diskfs_S_file_lock (struct protid *cred, int flags)
+{
+ error_t err;
+ if (!cred)
+ return EOPNOTSUPP;
+ mutex_lock (&cred->po->np->lock);
+ err = fshelp_acquire_lock (&cred->po->np->userlock, &cred->po->lock_status,
+ &cred->po->np->lock, flags);
+ mutex_unlock (&cred->po->np->lock);
+ return err;
+}
+
+
diff --git a/libdiskfs/file-reparent.c b/libdiskfs/file-reparent.c
new file mode 100644
index 00000000..d04cd798
--- /dev/null
+++ b/libdiskfs/file-reparent.c
@@ -0,0 +1,65 @@
+/* Reparent a file
+
+ Copyright (C) 1997 Free Software Foundation
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ 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 the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+
+error_t
+diskfs_S_file_reparent (struct protid *cred, mach_port_t parent,
+ mach_port_t *new, mach_msg_type_name_t *new_type)
+{
+ error_t err;
+ struct node *node;
+ struct protid *new_cred;
+
+ if (! cred)
+ return EOPNOTSUPP;
+
+ node = cred->po->np;
+
+ mutex_lock (&node->lock);
+ err = diskfs_create_protid (diskfs_make_peropen (node, cred->po->openstat,
+ cred->po),
+ cred->user, &new_cred);
+ mutex_unlock (&node->lock);
+
+ if (! err)
+ {
+ /* Remove old shadow root state. */
+ if (new_cred->po->shadow_root && new_cred->po->shadow_root != node)
+ diskfs_nrele (new_cred->po->shadow_root);
+ if (new_cred->po->shadow_root_parent)
+ mach_port_deallocate (mach_task_self (),
+ new_cred->po->shadow_root_parent);
+
+ /* And install PARENT instead. */
+ new_cred->po->shadow_root = node;
+ new_cred->po->shadow_root_parent = parent;
+
+ *new = ports_get_right (new_cred);
+ *new_type = MACH_MSG_TYPE_MAKE_SEND;
+
+ ports_port_deref (new_cred);
+ }
+
+ return err;
+}
diff --git a/libdiskfs/file-set-size.c b/libdiskfs/file-set-size.c
new file mode 100644
index 00000000..18abb469
--- /dev/null
+++ b/libdiskfs/file-set-size.c
@@ -0,0 +1,55 @@
+/* libdiskfs implementation of fs.defs: file_set_size
+ Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+#include <fcntl.h>
+
+/* Implement file_set_size as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_file_set_size (struct protid *cred,
+ off_t size)
+{
+ CHANGE_NODE_FIELD (cred,
+ ({
+ if (!(cred->po->openstat & O_WRITE))
+ err = EINVAL;
+ else if (size < np->dn_stat.st_size)
+ {
+ err = diskfs_truncate (np, size);
+ if (!err && np->filemod_reqs)
+ diskfs_notice_filechange (np,
+ FILE_CHANGED_TRUNCATE,
+ 0, size);
+ }
+ else if (size > np->dn_stat.st_size)
+ {
+ err = diskfs_grow (np, size, cred);
+ if (! err)
+ {
+ np->dn_stat.st_size = size;
+ np->dn_set_ctime = np->dn_set_mtime = 1;
+ if (np->filemod_reqs)
+ diskfs_notice_filechange (np,
+ FILE_CHANGED_EXTEND,
+ 0, size);
+ }
+ }
+ else
+ err = 0; /* Setting to same size. */
+ }));
+}
diff --git a/libdiskfs/file-set-trans.c b/libdiskfs/file-set-trans.c
new file mode 100644
index 00000000..22f42ba9
--- /dev/null
+++ b/libdiskfs/file-set-trans.c
@@ -0,0 +1,209 @@
+/* libdiskfs implementation of fs.defs: file_set_translator
+ Copyright (C) 1992, 93, 94, 95, 96, 99 Free Software Foundation, Inc.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+#include <hurd/paths.h>
+#include <hurd/fsys.h>
+
+/* Implement file_set_translator as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_file_set_translator (struct protid *cred,
+ int passive_flags,
+ int active_flags,
+ int killtrans_flags,
+ char *passive,
+ u_int passivelen,
+ fsys_t active)
+{
+ struct node *np;
+ error_t error;
+ mach_port_t control = MACH_PORT_NULL;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ if (!(passive_flags & FS_TRANS_SET) && !(active_flags & FS_TRANS_SET))
+ return 0;
+
+ if ((passive_flags & FS_TRANS_SET) && diskfs_check_readonly ())
+ return EROFS;
+
+ if (passive && passive[passivelen - 1])
+ return EINVAL;
+
+ np = cred->po->np;
+
+ mutex_lock (&np->lock);
+
+ error = fshelp_isowner (&np->dn_stat, cred->user);
+ if (error)
+ {
+ mutex_unlock (&np->lock);
+ return error;
+ }
+
+ if (active_flags & FS_TRANS_SET)
+ {
+ error = fshelp_fetch_control (&np->transbox, &control);
+ if (error)
+ {
+ mutex_unlock (&np->lock);
+ return error;
+ }
+
+ if ((control != MACH_PORT_NULL) && ((active_flags & FS_TRANS_EXCL) == 0))
+ {
+ mutex_unlock (&np->lock);
+ error = fsys_goaway (control, killtrans_flags);
+ mach_port_deallocate (mach_task_self (), control);
+ if (error && (error != MIG_SERVER_DIED)
+ && (error != MACH_SEND_INVALID_DEST))
+ return error;
+ error = 0;
+ mutex_lock (&np->lock);
+ }
+ else if (control != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), control);
+ }
+
+ /* Handle exclusive passive bit *first*. */
+ if ((passive_flags & FS_TRANS_SET)
+ && (passive_flags & FS_TRANS_EXCL)
+ && (np->dn_stat.st_mode & S_IPTRANS))
+ {
+ mutex_unlock (&np->lock);
+ return EBUSY;
+ }
+
+ if (active_flags & FS_TRANS_SET)
+ {
+ error = fshelp_set_active (&np->transbox, active,
+ active_flags & FS_TRANS_EXCL);
+ if (error)
+ {
+ mutex_unlock (&np->lock);
+ return error;
+ }
+ }
+
+ /* Set passive translator */
+ if (passive_flags & FS_TRANS_SET)
+ {
+ if (!(passive_flags & FS_TRANS_FORCE))
+ {
+ /* Handle the short-circuited translators */
+ mode_t newmode = 0;
+
+ if (diskfs_shortcut_symlink && !strcmp (passive, _HURD_SYMLINK))
+ newmode = S_IFLNK;
+ else if (diskfs_shortcut_chrdev && !(strcmp (passive, _HURD_CHRDEV)))
+ newmode = S_IFCHR;
+ else if (diskfs_shortcut_blkdev && !strcmp (passive, _HURD_BLKDEV))
+ newmode = S_IFBLK;
+ else if (diskfs_shortcut_fifo && !strcmp (passive, _HURD_FIFO))
+ newmode = S_IFIFO;
+ else if (diskfs_shortcut_ifsock && !strcmp (passive, _HURD_IFSOCK))
+ newmode = S_IFSOCK;
+
+ if (newmode)
+ {
+ if (S_ISDIR (np->dn_stat.st_mode))
+ {
+ /* We can't allow this, because if the mode of the directory
+ changes, the links will be lost. Perhaps it might be
+ allowed for empty directories, but that's too much of a
+ pain. */
+ mutex_unlock (&np->lock);
+ return EISDIR;
+ }
+ if (newmode == S_IFBLK || newmode == S_IFCHR)
+ {
+ /* Find the device number from the arguments
+ of the translator. */
+ int major, minor;
+ char *arg;
+
+ arg = passive + strlen (passive) + 1;
+ assert (arg <= passive + passivelen);
+ if (arg == passive + passivelen)
+ {
+ mutex_unlock (&np->lock);
+ return EINVAL;
+ }
+ major = strtol (arg, 0, 0);
+
+ arg = arg + strlen (arg) + 1;
+ assert (arg < passive + passivelen);
+ if (arg == passive + passivelen)
+ {
+ mutex_unlock (&np->lock);
+ return EINVAL;
+ }
+ minor = strtol (arg, 0, 0);
+
+ error = diskfs_validate_rdev_change (np,
+ makedev (major, minor));
+ if (error)
+ {
+ mutex_unlock (&np->lock);
+ return error;
+ }
+ np->dn_stat.st_rdev = makedev (major, minor);
+ }
+
+ diskfs_truncate (np, 0);
+ if (newmode == S_IFLNK)
+ {
+ char *arg = passive + strlen (passive) + 1;
+ assert (arg <= passive + passivelen);
+ if (arg == passive + passivelen)
+ {
+ mutex_unlock (&np->lock);
+ return EINVAL;
+ }
+
+ if (diskfs_create_symlink_hook)
+ error = (*diskfs_create_symlink_hook)(np, arg);
+ if (!diskfs_create_symlink_hook || error == EINVAL)
+ /* Store the argument in the file as the
+ target of the link */
+ error = diskfs_node_rdwr (np, arg, 0, strlen (arg),
+ 1, cred, 0);
+ if (error)
+ {
+ mutex_unlock (&np->lock);
+ return error;
+ }
+ }
+ newmode = (np->dn_stat.st_mode & ~S_IFMT) | newmode;
+ error = diskfs_validate_mode_change (np, newmode);
+ if (!error)
+ {
+ np->dn_stat.st_mode = newmode;
+ diskfs_node_update (np, 1);
+ }
+ mutex_unlock (&np->lock);
+ return error;
+ }
+ }
+ error = diskfs_set_translator (np, passive, passivelen, cred);
+ }
+
+ mutex_unlock (&np->lock);
+ return error;
+}
diff --git a/libdiskfs/file-statfs.c b/libdiskfs/file-statfs.c
new file mode 100644
index 00000000..ff26819f
--- /dev/null
+++ b/libdiskfs/file-statfs.c
@@ -0,0 +1,44 @@
+/* libdiskfs implementation of fs.defs: file_statfs
+ Copyright (C) 1992, 1993, 1994, 1998 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <sys/statvfs.h>
+
+#include "priv.h"
+#include "fs_S.h"
+
+/* Implement file_getcontrol as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_file_statfs (struct protid *file,
+ fsys_statfsbuf_t *statbuf)
+{
+ if (!file)
+ return EOPNOTSUPP;
+
+ statbuf->f_flag = 0;
+ if (diskfs_readonly)
+ statbuf->f_flag |= ST_RDONLY;
+ if (_diskfs_nosuid)
+ statbuf->f_flag |= ST_NOSUID;
+ if (_diskfs_noexec)
+ statbuf->f_flag |= ST_NOEXEC;
+ if (diskfs_synchronous)
+ statbuf->f_flag |= ST_SYNCHRONOUS;
+
+ diskfs_set_statfs (statbuf);
+
+ return 0;
+}
diff --git a/libdiskfs/file-sync.c b/libdiskfs/file-sync.c
new file mode 100644
index 00000000..94ffa9ac
--- /dev/null
+++ b/libdiskfs/file-sync.c
@@ -0,0 +1,42 @@
+/* libdiskfs implementation of fs.defs: file_seek
+ Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+
+/* Implement file_sync as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_file_sync (struct protid *cred,
+ int wait,
+ int omitmetadata)
+{
+ struct node *np;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ if (diskfs_synchronous)
+ wait = 1;
+
+ np = cred->po->np;
+
+ mutex_lock (&np->lock);
+ iohelp_get_conch (&np->conch);
+ mutex_unlock (&np->lock);
+ diskfs_file_update (np, wait);
+ return 0;
+}
diff --git a/libdiskfs/file-syncfs.c b/libdiskfs/file-syncfs.c
new file mode 100644
index 00000000..a3b7622e
--- /dev/null
+++ b/libdiskfs/file-syncfs.c
@@ -0,0 +1,61 @@
+/* libdiskfs implementation of fs.defs: file_syncfs
+ Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+#include <hurd/fsys.h>
+
+/* Implement file_syncfs as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_file_syncfs (struct protid *cred,
+ int wait,
+ int dochildren)
+{
+ error_t
+ helper (struct node *np)
+ {
+ error_t error;
+ mach_port_t control;
+
+ error = fshelp_fetch_control (&np->transbox, &control);
+ mutex_unlock (&np->lock);
+ if (!error && (control != MACH_PORT_NULL))
+ {
+ fsys_syncfs (control, wait, 1);
+ mach_port_deallocate (mach_task_self (), control);
+ }
+ mutex_lock (&np->lock);
+ return 0;
+ }
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ if (dochildren)
+ diskfs_node_iterate (helper);
+
+ if (diskfs_synchronous)
+ wait = 1;
+
+ if (! diskfs_readonly)
+ {
+ diskfs_sync_everything (wait);
+ diskfs_set_hypermetadata (wait, 0);
+ }
+
+ return 0;
+}
diff --git a/libdiskfs/file-utimes.c b/libdiskfs/file-utimes.c
new file mode 100644
index 00000000..b87aa18e
--- /dev/null
+++ b/libdiskfs/file-utimes.c
@@ -0,0 +1,55 @@
+/* libdiskfs implementation of fs.defs: file_utimes
+ Copyright (C) 1992, 1993, 1994, 1998, 1999 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fs_S.h"
+
+/* Implement file_utimes as described in <hurd/fs.defs>. */
+kern_return_t
+diskfs_S_file_utimes (struct protid *cred,
+ time_value_t atime,
+ time_value_t mtime)
+{
+ CHANGE_NODE_FIELD (cred,
+ ({
+ if (!(err = fshelp_isowner (&np->dn_stat, cred->user)))
+ {
+ if (atime.microseconds == -1)
+ np->dn_set_atime = 1;
+ else
+ {
+ np->dn_stat.st_atime = atime.seconds;
+ np->dn_set_atime = 0;
+ }
+
+ if (mtime.microseconds == -1)
+ np->dn_set_mtime = 1;
+ else
+ {
+ np->dn_stat.st_mtime = mtime.seconds;
+ np->dn_set_mtime = 0;
+ }
+
+ np->dn_set_ctime = 1;
+
+ if (np->filemod_reqs)
+ diskfs_notice_filechange (np,
+ FILE_CHANGED_META,
+ 0, 0);
+ }
+ }));
+}
diff --git a/libdiskfs/fsmutations.h b/libdiskfs/fsmutations.h
new file mode 100644
index 00000000..9280ee04
--- /dev/null
+++ b/libdiskfs/fsmutations.h
@@ -0,0 +1,29 @@
+/*
+ Copyright (C) 1994 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Only CPP macro definitions should go in this file. */
+
+#define FILE_INTRAN protid_t begin_using_protid_port (file_t)
+#define FILE_DESTRUCTOR end_using_protid_port (protid_t)
+
+#define IO_INTRAN protid_t begin_using_protid_port (io_t)
+#define IO_DESTRUCTOR end_using_protid_port (protid_t)
+
+#define FILE_IMPORTS import "priv.h";
+#define IO_IMPORTS import "priv.h";
+#define FSYS_IMPORTS import "priv.h";
+#define IFSOCK_IMPORTS import "priv.h";
diff --git a/libdiskfs/fsys-forward.c b/libdiskfs/fsys-forward.c
new file mode 100644
index 00000000..87441573
--- /dev/null
+++ b/libdiskfs/fsys-forward.c
@@ -0,0 +1,37 @@
+/* fsys_forward
+
+ Copyright (C) 1995 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ 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 the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fsys_S.h"
+
+/* Ask SERVER to provide fsys translation service for us. REQUESTOR is
+ the bootstrap port supplied to the original translator, and ARGV are
+ the command line arguments. If the recipient accepts the request, he
+ (or some delegate) should send fsys_startup to REQUESTOR to start the
+ filesystem up. */
+error_t
+diskfs_S_fsys_forward (mach_port_t server,
+ mach_port_t reply, mach_msg_type_name_t reply_type,
+ mach_port_t requestor, char *argz, size_t argz_len)
+{
+ return EOPNOTSUPP;
+}
diff --git a/libdiskfs/fsys-getfile.c b/libdiskfs/fsys-getfile.c
new file mode 100644
index 00000000..7d125304
--- /dev/null
+++ b/libdiskfs/fsys-getfile.c
@@ -0,0 +1,104 @@
+/* Return the file for a given handle (for nfs server support)
+
+ Copyright (C) 1997,99 Free Software Foundation, Inc.
+
+ 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 the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <fcntl.h>
+
+#include "priv.h"
+#include "fsys_S.h"
+#include "fhandle.h"
+
+/* Return in FILE & FILE_TYPE the file in FSYS corresponding to the NFS file
+ handle HANDLE & HANDLE_LEN. */
+error_t
+diskfs_S_fsys_getfile (mach_port_t fsys,
+ mach_port_t reply, mach_msg_type_name_t reply_type,
+ uid_t *uids, mach_msg_type_number_t nuids,
+ gid_t *gids, mach_msg_type_number_t ngids,
+ char *handle, mach_msg_type_number_t handle_len,
+ mach_port_t *file, mach_msg_type_name_t *file_type)
+{
+ int flags;
+ error_t err;
+ struct node *node;
+ const union diskfs_fhandle *f;
+ struct protid *new_cred;
+ struct idvec *uvec, *gvec;
+ struct iouser *user;
+ struct port_info *pt =
+ ports_lookup_port (diskfs_port_bucket, fsys, diskfs_control_class);
+
+ if (!pt)
+ return EOPNOTSUPP;
+
+ if (handle_len != sizeof *f)
+ {
+ ports_port_deref (pt);
+ return EINVAL;
+ }
+
+ f = (const union diskfs_fhandle *) handle;
+
+ err = diskfs_cached_lookup (f->data.cache_id, &node);
+ if (err)
+ {
+ ports_port_deref (pt);
+ return err;
+ }
+
+ if (node->dn_stat.st_gen != f->data.gen)
+ {
+ diskfs_nput (node);
+ ports_port_deref (pt);
+ return ESTALE;
+ }
+
+ uvec = make_idvec ();
+ gvec = make_idvec ();
+
+ idvec_set_ids (uvec, uids, nuids);
+ idvec_set_ids (gvec, gids, ngids);
+ user = iohelp_create_iouser (uvec, gvec);
+
+ flags = 0;
+ if (! fshelp_access (&node->dn_stat, S_IREAD, user))
+ flags |= O_READ;
+ if (! fshelp_access (&node->dn_stat, S_IEXEC, user))
+ flags |= O_EXEC;
+ if (! fshelp_access (&node->dn_stat, S_IWRITE, user)
+ && ! S_ISDIR (node->dn_stat.st_mode)
+ && ! diskfs_check_readonly ())
+ flags |= O_WRITE;
+
+ err = diskfs_create_protid (diskfs_make_peropen (node, flags, 0),
+ user, &new_cred);
+
+ iohelp_free_iouser (user);
+
+ diskfs_nput (node);
+ ports_port_deref (pt);
+
+ if (! err)
+ {
+ *file = ports_get_right (new_cred);
+ *file_type = MACH_MSG_TYPE_MAKE_SEND;
+ }
+
+ return err;
+}
diff --git a/libdiskfs/fsys-getroot.c b/libdiskfs/fsys-getroot.c
new file mode 100644
index 00000000..4e44395d
--- /dev/null
+++ b/libdiskfs/fsys-getroot.c
@@ -0,0 +1,203 @@
+/*
+ Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998 Free Software Foundation
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include "priv.h"
+#include "fsys_S.h"
+#include <hurd/fsys.h>
+#include <fcntl.h>
+
+/* Implement fsys_getroot as described in <hurd/fsys.defs>. */
+kern_return_t
+diskfs_S_fsys_getroot (fsys_t controlport,
+ mach_port_t reply,
+ mach_msg_type_name_t replytype,
+ mach_port_t dotdot,
+ uid_t *uids,
+ u_int nuids,
+ uid_t *gids,
+ u_int ngids,
+ int flags,
+ retry_type *retry,
+ char *retryname,
+ file_t *returned_port,
+ mach_msg_type_name_t *returned_port_poly)
+{
+ struct port_info *pt = ports_lookup_port (diskfs_port_bucket, controlport,
+ diskfs_control_class);
+ error_t error = 0;
+ mode_t type;
+ struct protid *newpi;
+ struct iouser user;
+ struct peropen peropen_context =
+ {
+ root_parent: dotdot,
+ shadow_root_parent: MACH_PORT_NULL,
+ shadow_root: _diskfs_chroot_directory ? diskfs_root_node : NULL /* XXX */
+ };
+
+ if (!pt)
+ return EOPNOTSUPP;
+
+ flags &= O_HURD;
+
+ user.uids = make_idvec ();
+ user.gids = make_idvec ();
+ idvec_set_ids (user.uids, uids, nuids);
+ idvec_set_ids (user.gids, gids, ngids);
+#define drop_idvec() idvec_free (user.gids); idvec_free (user.uids)
+
+ rwlock_reader_lock (&diskfs_fsys_lock);
+ mutex_lock (&diskfs_root_node->lock);
+
+ /* This code is similar (but not the same as) the code in
+ dir-pathtrans.c that does the same thing. Perhaps a way should
+ be found to share the logic. */
+
+ type = diskfs_root_node->dn_stat.st_mode & S_IFMT;
+
+ if (((diskfs_root_node->dn_stat.st_mode & S_IPTRANS)
+ || fshelp_translated (&diskfs_root_node->transbox))
+ && !(flags & O_NOTRANS))
+ {
+ error = fshelp_fetch_root (&diskfs_root_node->transbox,
+ &peropen_context, dotdot, &user, flags,
+ _diskfs_translator_callback1,
+ _diskfs_translator_callback2,
+ retry, retryname, returned_port);
+ if (error != ENOENT)
+ {
+ mutex_unlock (&diskfs_root_node->lock);
+ rwlock_reader_unlock (&diskfs_fsys_lock);
+ drop_idvec ();
+ if (!error)
+ *returned_port_poly = MACH_MSG_TYPE_MOVE_SEND;
+ return error;
+ }
+
+ /* ENOENT means the translator was removed in the interim. */
+ error = 0;
+ }
+
+ if (type == S_IFLNK && !(flags & (O_NOLINK | O_NOTRANS)))
+ {
+ /* Handle symlink interpretation */
+ char pathbuf[diskfs_root_node->dn_stat.st_size + 1];
+ int amt;
+
+ if (diskfs_read_symlink_hook)
+ error = (*diskfs_read_symlink_hook) (diskfs_root_node, pathbuf);
+ if (!diskfs_read_symlink_hook || error == EINVAL)
+ error = diskfs_node_rdwr (diskfs_root_node, pathbuf, 0,
+ diskfs_root_node->dn_stat.st_size, 0,
+ 0, &amt);
+ pathbuf[amt] = '\0';
+
+ mutex_unlock (&diskfs_root_node->lock);
+ rwlock_reader_unlock (&diskfs_fsys_lock);
+ if (error)
+ {
+ drop_idvec ();
+ return error;
+ }
+
+ if (pathbuf[0] == '/')
+ {
+ *retry = FS_RETRY_MAGICAL;
+ *returned_port = MACH_PORT_NULL;
+ *returned_port_poly = MACH_MSG_TYPE_COPY_SEND;
+ strcpy (retryname, pathbuf);
+ mach_port_deallocate (mach_task_self (), dotdot);
+ drop_idvec ();
+ return 0;
+ }
+ else
+ {
+ *retry = FS_RETRY_REAUTH;
+ *returned_port = dotdot;
+ *returned_port_poly = MACH_MSG_TYPE_MOVE_SEND;
+ strcpy (retryname, pathbuf);
+ drop_idvec ();
+ return 0;
+ }
+ }
+
+ if ((type == S_IFSOCK || type == S_IFBLK
+ || type == S_IFCHR || type == S_IFIFO)
+ && (flags & (O_READ|O_WRITE|O_EXEC)))
+ error = EOPNOTSUPP;
+
+ if (!error && (flags & O_READ))
+ error = fshelp_access (&diskfs_root_node->dn_stat, S_IREAD, &user);
+
+ if (!error && (flags & O_EXEC))
+ error = fshelp_access (&diskfs_root_node->dn_stat, S_IEXEC, &user);
+
+ if (!error && (flags & (O_WRITE)))
+ {
+ if (type == S_IFDIR)
+ error = EISDIR;
+ else if (diskfs_check_readonly ())
+ error = EROFS;
+ else
+ error = fshelp_access (&diskfs_root_node->dn_stat,
+ S_IWRITE, &user);
+ }
+
+ if (error)
+ {
+ mutex_unlock (&diskfs_root_node->lock);
+ rwlock_reader_unlock (&diskfs_fsys_lock);
+ drop_idvec ();
+ return error;
+ }
+
+ if ((flags & O_NOATIME)
+ && (fshelp_isowner (&diskfs_root_node->dn_stat, &user)
+ == EPERM))
+ flags &= ~O_NOATIME;
+
+ flags &= ~OPENONLY_STATE_MODES;
+
+ error =
+ diskfs_create_protid (diskfs_make_peropen (diskfs_root_node, flags,
+ &peropen_context),
+ &user, &newpi);
+
+ mach_port_deallocate (mach_task_self (), dotdot);
+
+ if (! error)
+ {
+ *retry = FS_RETRY_NORMAL;
+ *retryname = '\0';
+ *returned_port = ports_get_right (newpi);
+ *returned_port_poly = MACH_MSG_TYPE_MAKE_SEND;
+ ports_port_deref (newpi);
+ }
+
+ mutex_unlock (&diskfs_root_node->lock);
+ rwlock_reader_unlock (&diskfs_fsys_lock);
+
+ ports_port_deref (pt);
+
+ drop_idvec ();
+
+ return error;
+}
diff --git a/libdiskfs/fsys-goaway.c b/libdiskfs/fsys-goaway.c
new file mode 100644
index 00000000..611014f4
--- /dev/null
+++ b/libdiskfs/fsys-goaway.c
@@ -0,0 +1,54 @@
+/*
+ Copyright (C) 1993, 1994, 1995 Free Software Foundation
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include "priv.h"
+#include "fsys_S.h"
+#include "fsys_reply_U.h"
+
+/* Implement fsys_goaway as described in <hurd/fsys.defs>. */
+error_t
+diskfs_S_fsys_goaway (fsys_t controlport,
+ mach_port_t reply,
+ mach_msg_type_name_t reply_type,
+ int flags)
+{
+ struct port_info *pt = ports_lookup_port (diskfs_port_bucket, controlport,
+ diskfs_control_class);
+ error_t ret;
+
+ if (!pt)
+ return EOPNOTSUPP;
+
+ /* XXX FSYS_GOAWAY_NOWAIT not implemented. */
+
+ ret = diskfs_shutdown (flags);
+
+ if (ret == 0)
+ {
+ /* We are supposed to exit, but first notify the caller. */
+ fsys_goaway_reply (reply, reply_type, 0);
+ exit (0);
+ }
+
+ ports_port_deref (pt);
+ return ret;
+}
+
diff --git a/libdiskfs/fsys-options.c b/libdiskfs/fsys-options.c
new file mode 100644
index 00000000..ea5ee8c5
--- /dev/null
+++ b/libdiskfs/fsys-options.c
@@ -0,0 +1,116 @@
+/* Parse run-time options
+
+ Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <errno.h>
+#include <argz.h>
+#include <hurd/fsys.h>
+#include <string.h>
+
+#include "priv.h"
+#include "fsys_S.h"
+
+/* Implement fsys_set_options as described in <hurd/fsys.defs>. */
+kern_return_t
+diskfs_S_fsys_set_options (fsys_t fsys,
+ mach_port_t reply,
+ mach_msg_type_name_t replytype,
+ char *data, mach_msg_type_number_t len,
+ int do_children)
+{
+ error_t err = 0;
+ struct port_info *pt =
+ ports_lookup_port (diskfs_port_bucket, fsys, diskfs_control_class);
+
+ error_t
+ helper (struct node *np)
+ {
+ error_t error;
+ mach_port_t control;
+
+ error = fshelp_fetch_control (&np->transbox, &control);
+ mutex_unlock (&np->lock);
+ if (!error && (control != MACH_PORT_NULL))
+ {
+ error = fsys_set_options (control, data, len, do_children);
+ mach_port_deallocate (mach_task_self (), control);
+ }
+ else
+ error = 0;
+ mutex_lock (&np->lock);
+
+ if ((error == MIG_SERVER_DIED) || (error == MACH_SEND_INVALID_DEST))
+ error = 0;
+ return error;
+ }
+
+ if (!pt)
+ return EOPNOTSUPP;
+
+ if (do_children)
+ {
+ rwlock_writer_lock (&diskfs_fsys_lock);
+ err = diskfs_node_iterate (helper);
+ rwlock_writer_unlock (&diskfs_fsys_lock);
+ }
+
+ if (!err)
+ {
+ rwlock_writer_lock (&diskfs_fsys_lock);
+ err = diskfs_set_options (data, len);
+ rwlock_writer_unlock (&diskfs_fsys_lock);
+ }
+
+ ports_port_deref (pt);
+ return err;
+}
+
+/* Implement fsys_get_options as described in <hurd/fsys.defs>. */
+error_t
+diskfs_S_fsys_get_options (fsys_t fsys,
+ mach_port_t reply,
+ mach_msg_type_name_t replytype,
+ char **data, mach_msg_type_number_t *data_len)
+{
+ char *argz = 0;
+ size_t argz_len = 0;
+ error_t err;
+ struct port_info *port =
+ ports_lookup_port (diskfs_port_bucket, fsys, diskfs_control_class);
+
+ if (!port)
+ return EOPNOTSUPP;
+
+ err = argz_add (&argz, &argz_len, program_invocation_name);
+ if (err)
+ return err;
+
+ rwlock_reader_lock (&diskfs_fsys_lock);
+ err = diskfs_append_args (&argz, &argz_len);
+ rwlock_reader_unlock (&diskfs_fsys_lock);
+
+ if (! err)
+ /* Move ARGZ from a malloced buffer into a vm_alloced one. */
+ err = iohelp_return_malloced_buffer (argz, argz_len, data, data_len);
+ else
+ free (argz);
+
+ ports_port_deref (port);
+ return err;
+}
diff --git a/libdiskfs/fsys-startup.c b/libdiskfs/fsys-startup.c
new file mode 100644
index 00000000..baa94ca7
--- /dev/null
+++ b/libdiskfs/fsys-startup.c
@@ -0,0 +1,37 @@
+/*
+ Copyright (C) 1993, 1994, 1995 Free Software Foundation
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include "priv.h"
+#include "fsys_S.h"
+
+/* Implement fsys_startup as described in <hurd/fsys.defs>. */
+kern_return_t
+diskfs_S_fsys_startup (mach_port_t port,
+ mach_port_t reply,
+ mach_msg_type_name_t replytype,
+ int flags,
+ mach_port_t ctl,
+ mach_port_t *real,
+ mach_msg_type_name_t *realpoly)
+{
+ return diskfs_execboot_fsys_startup (port, flags, ctl, real, realpoly);
+}
+
diff --git a/libdiskfs/fsys-syncfs.c b/libdiskfs/fsys-syncfs.c
new file mode 100644
index 00000000..503eea4c
--- /dev/null
+++ b/libdiskfs/fsys-syncfs.c
@@ -0,0 +1,75 @@
+/*
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell.
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "fsys_S.h"
+#include <hurd/fsys.h>
+
+/* Implement fsys_syncfs as described in <hurd/fsys.defs>. */
+kern_return_t
+diskfs_S_fsys_syncfs (fsys_t controlport,
+ mach_port_t reply,
+ mach_msg_type_name_t replytype,
+ int wait,
+ int children)
+{
+ struct port_info *pi = ports_lookup_port (diskfs_port_bucket, controlport,
+ diskfs_control_class);
+ error_t
+ helper (struct node *np)
+ {
+ error_t error;
+ mach_port_t control;
+
+ error = fshelp_fetch_control (&np->transbox, &control);
+ mutex_unlock (&np->lock);
+ if (!error && (control != MACH_PORT_NULL))
+ {
+ fsys_syncfs (control, wait, 1);
+ mach_port_deallocate (mach_task_self (), control);
+ }
+ mutex_lock (&np->lock);
+ return 0;
+ }
+
+ if (!pi)
+ return EOPNOTSUPP;
+
+ rwlock_reader_lock (&diskfs_fsys_lock);
+
+ if (children)
+ diskfs_node_iterate (helper);
+
+ if (diskfs_synchronous)
+ wait = 1;
+
+ if (! diskfs_readonly)
+ {
+ diskfs_sync_everything (wait);
+ diskfs_set_hypermetadata (wait, 0);
+ }
+
+ rwlock_reader_unlock (&diskfs_fsys_lock);
+
+ ports_port_deref (pi);
+
+ return 0;
+}
+
diff --git a/libdiskfs/ifsock.c b/libdiskfs/ifsock.c
new file mode 100644
index 00000000..3e9b8325
--- /dev/null
+++ b/libdiskfs/ifsock.c
@@ -0,0 +1,135 @@
+/* Implement ifsock inteface
+ Copyright (C) 1994, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "ifsock_S.h"
+#include <hurd/paths.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <hurd/socket.h>
+
+static spin_lock_t pflocalserverlock = SPIN_LOCK_INITIALIZER;
+static mach_port_t pflocalserver = MACH_PORT_NULL;
+
+kern_return_t
+diskfs_S_ifsock_getsockaddr (struct protid *cred,
+ mach_port_t *address)
+{
+ error_t err;
+ struct node *np;
+ unsigned restart_tries = 0;
+
+ /* Make sure this is a socket */
+ if (!cred)
+ return EOPNOTSUPP;
+ np = cred->po->np;
+
+ retry:
+ mutex_lock (&np->lock);
+ if ((np->dn_stat.st_mode & S_IFMT) != S_IFSOCK)
+ {
+ mutex_unlock (&np->lock);
+ return EOPNOTSUPP;
+ }
+ err = fshelp_access (&np->dn_stat, S_IWRITE, cred->user);
+ if (err)
+ {
+ mutex_unlock (&np->lock);
+ return err;
+ }
+
+ if (np->sockaddr == MACH_PORT_NULL)
+ {
+ mach_port_t server;
+ mach_port_t sockaddr;
+ mach_port_t old;
+
+ mutex_unlock (&np->lock);
+
+ /* Fetch a port to the PF_LOCAL server, caching it. */
+
+ spin_lock (&pflocalserverlock);
+ if (pflocalserver == MACH_PORT_NULL)
+ {
+ /* Find out who the PF_LOCAL server is. */
+ char buf[100];
+
+ spin_unlock (&pflocalserverlock);
+
+ /* Look it up */
+ sprintf (buf, "%s/%d", _SERVERS_SOCKET, PF_LOCAL);
+ server = file_name_lookup (buf, 0, 0);
+ if (server == MACH_PORT_NULL)
+ return EIEIO;
+
+ /* Set it unless someone is already here */
+ spin_lock (&pflocalserverlock);
+ if (pflocalserver != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), server);
+ else
+ pflocalserver = server;
+ spin_unlock (&pflocalserverlock);
+
+ goto retry;
+ }
+ server = pflocalserver;
+ spin_unlock (&pflocalserverlock);
+
+ /* Create an address for the node */
+ err = socket_fabricate_address (server, AF_LOCAL, &sockaddr);
+ if ((err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED)
+ && restart_tries++ == 0)
+ /* The PF_LOCAL server died; try to restart it. */
+ {
+ spin_lock (&pflocalserverlock);
+ if (pflocalserver == server)
+ pflocalserver = MACH_PORT_NULL;
+ spin_unlock (&pflocalserverlock);
+ goto retry;
+ }
+ if (err)
+ {
+ mutex_unlock (&np->lock);
+ return EIEIO;
+ }
+
+ mutex_lock (&np->lock);
+ if (np->sockaddr != MACH_PORT_NULL)
+ /* Someone beat us */
+ mach_port_deallocate (mach_task_self (), sockaddr);
+ else
+ {
+ /* The receive right of the sockaddr holds a reference;
+ when we get a dead name on that right we drop our
+ reference. */
+ mach_port_request_notification (mach_task_self (), sockaddr,
+ MACH_NOTIFY_DEAD_NAME, 1,
+ cred->pi.port_right,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ &old);
+ if (old != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), old);
+ np->sockaddr = sockaddr;
+ diskfs_nref (np);
+ }
+ }
+
+ *address = np->sockaddr;
+ mutex_unlock (&np->lock);
+ return 0;
+}
+
diff --git a/libdiskfs/init-first.c b/libdiskfs/init-first.c
new file mode 100644
index 00000000..1a0ae3e5
--- /dev/null
+++ b/libdiskfs/init-first.c
@@ -0,0 +1,52 @@
+/*
+ Copyright (C) 1994, 1995, 1997 Free Software Foundation
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include "priv.h"
+
+static int thread_timeout = 1000 * 60 * 2; /* two minutes */
+static int server_timeout = 1000 * 60 * 10; /* ten minutes */
+
+
+static any_t
+master_thread_function (any_t foo __attribute__ ((unused)))
+{
+ error_t err;
+
+ do
+ {
+ ports_manage_port_operations_multithread (diskfs_port_bucket,
+ diskfs_demuxer,
+ thread_timeout,
+ server_timeout,
+ 0);
+ err = diskfs_shutdown (0);
+ }
+ while (err);
+
+ exit (0);
+}
+
+void
+diskfs_spawn_first_thread (void)
+{
+ cthread_detach (cthread_fork ((cthread_fn_t) master_thread_function,
+ (any_t) 0));
+}
diff --git a/libdiskfs/init-init.c b/libdiskfs/init-init.c
new file mode 100644
index 00000000..11624763
--- /dev/null
+++ b/libdiskfs/init-init.c
@@ -0,0 +1,105 @@
+/*
+ Copyright (C) 1994, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include "priv.h"
+#include <device/device.h>
+#include <hurd/fsys.h>
+#include <stdio.h>
+#include <maptime.h>
+
+mach_port_t diskfs_default_pager;
+mach_port_t diskfs_auth_server_port;
+volatile struct mapped_time_value *diskfs_mtime;
+mach_port_t diskfs_fsys_identity;
+
+int _diskfs_nosuid, _diskfs_noexec;
+int _diskfs_noatime;
+
+struct hurd_port _diskfs_exec_portcell;
+
+spin_lock_t diskfs_node_refcnt_lock = SPIN_LOCK_INITIALIZER;
+
+spin_lock_t _diskfs_control_lock = SPIN_LOCK_INITIALIZER;
+int _diskfs_ncontrol_ports = 0;
+
+struct port_class *diskfs_protid_class;
+struct port_class *diskfs_control_class;
+struct port_class *diskfs_initboot_class;
+struct port_class *diskfs_execboot_class;
+struct port_class *diskfs_shutdown_notification_class;
+
+struct port_bucket *diskfs_port_bucket;
+
+/* Call this after arguments have been parsed to initialize the
+ library. */
+error_t
+diskfs_init_diskfs (void)
+{
+ error_t err;
+
+ if (diskfs_boot_flags)
+ /* This is a boot filesystem, we have to do some things specially. */
+ {
+ mach_port_t host;
+ err = get_privileged_ports (&host, 0);
+ if (! err)
+ {
+ diskfs_default_pager = MACH_PORT_NULL;
+ err = vm_set_default_memory_manager (host, &diskfs_default_pager);
+ mach_port_deallocate (mach_task_self (), host);
+
+ if (!err)
+ err = maptime_map (1, 0, &diskfs_mtime);
+ }
+ }
+ else
+ err = maptime_map (0, 0, &diskfs_mtime);
+
+ if (err)
+ return err;
+
+ err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
+ &diskfs_fsys_identity);
+ if (err)
+ return err;
+
+ diskfs_auth_server_port = getauth ();
+
+ diskfs_protid_class = ports_create_class (diskfs_protid_rele, 0);
+ diskfs_control_class = ports_create_class (_diskfs_control_clean, 0);
+ diskfs_initboot_class = ports_create_class (0, 0);
+ diskfs_execboot_class = ports_create_class (0, 0);
+ diskfs_shutdown_notification_class = ports_create_class (0, 0);
+
+ diskfs_port_bucket = ports_create_bucket ();
+
+ _hurd_port_init (&_diskfs_exec_portcell, MACH_PORT_NULL);
+
+ return 0;
+}
+
+void
+_diskfs_control_clean (void *arg __attribute__ ((unused)))
+{
+ spin_lock (&_diskfs_control_lock);
+ _diskfs_ncontrol_ports--;
+ spin_unlock (&_diskfs_control_lock);
+}
diff --git a/libdiskfs/init-main.c b/libdiskfs/init-main.c
new file mode 100644
index 00000000..a9680dd7
--- /dev/null
+++ b/libdiskfs/init-main.c
@@ -0,0 +1,78 @@
+/* diskfs_init_main -- initialize diskfs world, parse arguments, and open store
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "diskfs.h"
+#include <argp.h>
+#include <assert.h>
+#include <error.h>
+#include <hurd/store.h>
+
+struct store *
+diskfs_init_main (struct argp *startup_argp,
+ int argc, char **argv,
+ struct store_parsed **store_parsed,
+ mach_port_t *bootstrap)
+{
+ error_t err;
+ struct store_argp_params store_params = { 0 };
+ struct store *store;
+
+ /* We must use ARGP_IN_ORDER for the parsing of --boot-command to work. */
+ err = argp_parse (startup_argp ?: &diskfs_store_startup_argp,
+ argc, argv, ARGP_IN_ORDER, NULL,
+ &store_params);
+ assert_perror (err);
+ *store_parsed = store_params.result;
+
+ err = store_parsed_name (*store_parsed, &diskfs_disk_name);
+ if (err)
+ error (2, err, "store_parsed_name");
+
+ /* This must come after the args have been parsed, as this is where the
+ host priv ports are set for booting. */
+ diskfs_console_stdio ();
+
+ if (diskfs_boot_flags)
+ /* We are the bootstrap filesystem. */
+ *bootstrap = MACH_PORT_NULL;
+ else
+ {
+ task_get_bootstrap_port (mach_task_self (), bootstrap);
+ if (bootstrap == MACH_PORT_NULL)
+ error (2, 0, "Must be started as a translator");
+ }
+
+ /* Initialize the diskfs library. Must come before any other diskfs call. */
+ err = diskfs_init_diskfs ();
+ if (err)
+ error (4, err, "init");
+
+ err = store_parsed_open (*store_parsed, diskfs_readonly ? STORE_READONLY : 0,
+ &store);
+ if (err)
+ error (3, err, "%s", diskfs_disk_name);
+
+ if (store->flags & STORE_HARD_READONLY)
+ diskfs_readonly = diskfs_hard_readonly = 1;
+
+ /* Start the first request thread, to handle RPCs and page requests. */
+ diskfs_spawn_first_thread ();
+
+ return store;
+}
diff --git a/libdiskfs/init-startup.c b/libdiskfs/init-startup.c
new file mode 100644
index 00000000..0b0b8d5f
--- /dev/null
+++ b/libdiskfs/init-startup.c
@@ -0,0 +1,205 @@
+/* diskfs_startup_diskfs -- advertise our fsys control port to our parent FS.
+ Copyright (C) 1994, 1995, 1996, 1998, 1999 Free Software Foundation
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Roland McGrath. */
+
+#include "priv.h"
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <error.h>
+#include <hurd/fsys.h>
+#include <hurd/startup.h>
+
+char *_diskfs_chroot_directory;
+
+mach_port_t
+diskfs_startup_diskfs (mach_port_t bootstrap, int flags)
+{
+ mach_port_t realnode;
+ struct port_info *newpi;
+
+ if (_diskfs_chroot_directory != NULL)
+ {
+ /* The boot options requested we change to a subdirectory
+ and treat that as the root of the filesystem. */
+ error_t err;
+ struct node *np, *old;
+ struct protid *rootpi;
+
+ /* Skip leading slashes. */
+ while (*_diskfs_chroot_directory == '/')
+ ++_diskfs_chroot_directory;
+
+ mutex_lock (&diskfs_root_node->lock);
+
+ /* Create a protid we can use in diskfs_lookup. */
+ err = diskfs_create_protid (diskfs_make_peropen (diskfs_root_node,
+ O_READ|O_EXEC, 0),
+ 0, &rootpi);
+ assert_perror (err);
+
+ /* Look up the directory name. */
+ err = diskfs_lookup (diskfs_root_node, _diskfs_chroot_directory,
+ LOOKUP, &np, NULL, rootpi);
+ mutex_unlock (&diskfs_root_node->lock);
+ ports_port_deref (rootpi);
+
+ if (err == EAGAIN)
+ error (1, 0, "`--virtual-root=%s' specifies the real root directory",
+ _diskfs_chroot_directory);
+ else if (err)
+ error (1, err, "`%s' not found", _diskfs_chroot_directory);
+
+ if (!S_ISDIR (np->dn_stat.st_mode))
+ {
+ mutex_unlock (&np->lock);
+ error (1, ENOTDIR, "%s", _diskfs_chroot_directory);
+ }
+
+ /* Install this node as the new root, forgetting about the real root
+ node. The last essential piece that makes the virtual root work
+ is in fsys-getroot.c, which sets the first peropen's shadow_root
+ if _diskfs_chroot_directory is non-null. */
+ old = diskfs_root_node;
+ diskfs_root_node = np;
+ mutex_unlock (&np->lock);
+ diskfs_nput (old);
+ }
+
+ if (bootstrap != MACH_PORT_NULL)
+ {
+ errno = ports_create_port (diskfs_control_class, diskfs_port_bucket,
+ sizeof (struct port_info), &newpi);
+ if (! errno)
+ {
+ errno = fsys_startup (bootstrap, flags, ports_get_right (newpi),
+ MACH_MSG_TYPE_MAKE_SEND, &realnode);
+ ports_port_deref (newpi);
+ }
+ if (errno)
+ {
+ perror ("Translator startup failure: fsys_startup");
+ exit (1);
+ }
+ mach_port_deallocate (mach_task_self (), bootstrap);
+ _diskfs_ncontrol_ports++;
+
+ _diskfs_init_completed ();
+ }
+ else
+ {
+ realnode = MACH_PORT_NULL;
+
+ /* We are the bootstrap filesystem; do special boot-time setup. */
+ diskfs_start_bootstrap ();
+ }
+
+ if (diskfs_default_sync_interval)
+ /* Start 'em sync'n */
+ diskfs_set_sync_interval (diskfs_default_sync_interval);
+
+ return realnode;
+}
+
+error_t
+diskfs_S_startup_dosync (mach_port_t handle)
+{
+ error_t err = 0;
+ struct port_info *pi
+ = ports_lookup_port (diskfs_port_bucket, handle,
+ diskfs_shutdown_notification_class);
+
+ if (!pi)
+ return EOPNOTSUPP;
+
+ if (! diskfs_readonly)
+ {
+ /* First start a sync so that if something goes wrong
+ we at least get this much done. */
+ diskfs_sync_everything (0);
+ diskfs_set_hypermetadata (0, 0);
+
+ rwlock_writer_lock (&diskfs_fsys_lock);
+
+ /* Permit all the current RPC's to finish, and then suspend new ones */
+ err = ports_inhibit_class_rpcs (diskfs_protid_class);
+ if (! err)
+ {
+ diskfs_sync_everything (1);
+ diskfs_set_hypermetadata (1, 1);
+ _diskfs_diskdirty = 0;
+
+ ports_resume_class_rpcs (diskfs_protid_class);
+ }
+
+ rwlock_writer_unlock (&diskfs_fsys_lock);
+ }
+
+ ports_port_deref (pi);
+
+ return err;
+}
+
+/* This is called when we have an ordinary environment, complete
+ with proc and auth ports. */
+void
+_diskfs_init_completed ()
+{
+ startup_t init;
+ process_t proc;
+ error_t err;
+ struct port_info *pi;
+ mach_port_t notify;
+ char *name;
+
+ /* Contact the startup server and register our shutdown request.
+ If we get an error, print an informational message. */
+
+ proc = getproc ();
+ assert (proc);
+
+ err = ports_create_port (diskfs_shutdown_notification_class,
+ diskfs_port_bucket, sizeof (struct port_info),
+ &pi);
+ if (err)
+ goto errout;
+
+ err = proc_getmsgport (proc, 1, &init);
+ mach_port_deallocate (mach_task_self (), proc);
+ if (err)
+ goto errout;
+
+ notify = ports_get_right (pi);
+ ports_port_deref (pi);
+ asprintf (&name,
+ "%s %s", program_invocation_short_name, diskfs_disk_name ?: "-");
+ err = startup_request_notification (init, notify,
+ MACH_MSG_TYPE_MAKE_SEND, name);
+ free (name);
+ if (err)
+ goto errout;
+
+ mach_port_deallocate (mach_task_self (), init);
+ return;
+
+ errout:
+ fprintf (stderr, "Cannot request shutdown notification: %s\n",
+ strerror (err));
+}
diff --git a/libdiskfs/interrupt.c b/libdiskfs/interrupt.c
new file mode 100644
index 00000000..ffd7fb83
--- /dev/null
+++ b/libdiskfs/interrupt.c
@@ -0,0 +1,39 @@
+/*
+ Copyright (C) 1993, 1994, 1995 Free Software Foundation
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include "priv.h"
+#include "interrupt_S.h"
+
+kern_return_t
+diskfs_S_interrupt_operation (mach_port_t handle)
+{
+ struct port_info *pi;
+
+ pi = ports_lookup_port (diskfs_port_bucket, handle, 0);
+ if (!pi)
+ return EOPNOTSUPP;
+
+ ports_interrupt_rpc (pi);
+
+ ports_port_deref (pi);
+
+ return 0;
+}
diff --git a/libdiskfs/io-async-icky.c b/libdiskfs/io-async-icky.c
new file mode 100644
index 00000000..22cb3abb
--- /dev/null
+++ b/libdiskfs/io-async-icky.c
@@ -0,0 +1,33 @@
+/*
+ Copyright (C) 1994, 1995 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+
+/* Implement io_get_icky_async_id as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_get_icky_async_id (struct protid *cred,
+ mach_port_t *idport,
+ mach_msg_type_name_t *idport_type)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+
+ *idport = MACH_PORT_NULL;
+ *idport_type = MACH_MSG_TYPE_COPY_SEND;
+ return 0;
+}
diff --git a/libdiskfs/io-async.c b/libdiskfs/io-async.c
new file mode 100644
index 00000000..e5ed6d92
--- /dev/null
+++ b/libdiskfs/io-async.c
@@ -0,0 +1,31 @@
+/*
+ Copyright (C) 1994, 1995 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+
+/* Implement io_async as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_async (struct protid *cred __attribute__ ((unused)),
+ mach_port_t notify __attribute__ ((unused)),
+ mach_port_t *idport __attribute__ ((unused)),
+ mach_msg_type_name_t *idport_type
+ __attribute__ ((unused)))
+{
+ return EOPNOTSUPP;
+}
+
diff --git a/libdiskfs/io-duplicate.c b/libdiskfs/io-duplicate.c
new file mode 100644
index 00000000..3cbf8f7b
--- /dev/null
+++ b/libdiskfs/io-duplicate.c
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+
+/* Implement io_duplicate as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_duplicate (struct protid *cred,
+ mach_port_t *port,
+ mach_msg_type_name_t *portpoly)
+{
+ error_t err;
+ struct protid *newpi;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ mutex_lock (&cred->po->np->lock);
+
+ err = diskfs_create_protid (cred->po, cred->user, &newpi);
+ if (! err)
+ {
+ *port = ports_get_right (newpi);
+ *portpoly = MACH_MSG_TYPE_MAKE_SEND;
+ ports_port_deref (newpi);
+ }
+
+ mutex_unlock (&cred->po->np->lock);
+
+ return err;
+}
diff --git a/libdiskfs/io-get-conch.c b/libdiskfs/io-get-conch.c
new file mode 100644
index 00000000..6be35f0b
--- /dev/null
+++ b/libdiskfs/io-get-conch.c
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 1994, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+
+/* Implement io_get_conch as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_get_conch (struct protid *cred)
+{
+ struct node *np;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ np = cred->po->np;
+
+ mutex_lock (&np->lock);
+
+ if (!cred->mapped)
+ {
+ mutex_unlock (&np->lock);
+ return EINVAL;
+ }
+
+ iohelp_handle_io_get_conch (&np->conch, cred, cred->mapped);
+
+ mutex_unlock (&np->lock);
+ return 0;
+}
diff --git a/libdiskfs/io-identity.c b/libdiskfs/io-identity.c
new file mode 100644
index 00000000..5717a7d2
--- /dev/null
+++ b/libdiskfs/io-identity.c
@@ -0,0 +1,67 @@
+/* libdiskfs implementation of io_identity RPC
+ Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/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. */
+
+#include "priv.h"
+#include "io_S.h"
+
+/* Implement io_identity as described in <hurd/io.defs>. */
+error_t
+diskfs_S_io_identity (struct protid *cred,
+ mach_port_t *id,
+ mach_msg_type_name_t *idtype,
+ mach_port_t *fsys,
+ mach_msg_type_name_t *fsystype,
+ int *fileno)
+{
+ struct node *np;
+ error_t err;
+ ino_t inum;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ np = cred->po->np;
+ mutex_lock (&np->lock);
+ inum = np->dn_stat.st_ino;
+ mutex_unlock (&np->lock);
+
+ err = fshelp_get_identity (diskfs_port_bucket, inum, id);
+ if (! err)
+ {
+ if (cred->po->shadow_root && cred->po->shadow_root != diskfs_root_node)
+ {
+ err = fshelp_get_identity (diskfs_port_bucket,
+ cred->po->shadow_root->dn_stat.st_ino,
+ fsys);
+ if (err)
+ mach_port_deallocate (mach_task_self (), *id);
+ }
+ else
+ *fsys = diskfs_fsys_identity;
+ }
+ if (! err)
+ {
+ *idtype = MACH_MSG_TYPE_MAKE_SEND;
+ *fsystype = MACH_MSG_TYPE_MAKE_SEND;
+ *fileno = np->dn_stat.st_ino;
+ }
+
+ return err;
+}
diff --git a/libdiskfs/io-interrupt.c b/libdiskfs/io-interrupt.c
new file mode 100644
index 00000000..2d2e4c61
--- /dev/null
+++ b/libdiskfs/io-interrupt.c
@@ -0,0 +1,29 @@
+/*
+ Copyright (C) 1994 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+
+/* Implement io_interrupt as described in <hurd/io.defs>. */
+error_t
+S_io_interrupt (struct protid *cred)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+
+ return 0;
+}
diff --git a/libdiskfs/io-map-cntl.c b/libdiskfs/io-map-cntl.c
new file mode 100644
index 00000000..b45ccffd
--- /dev/null
+++ b/libdiskfs/io-map-cntl.c
@@ -0,0 +1,53 @@
+/*
+ Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+#include <mach/default_pager.h>
+
+/* Implement io_map_cntl as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_map_cntl (struct protid *cred,
+ memory_object_t *ctlobj,
+ mach_msg_type_name_t *ctlobj_type)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+
+ assert (__vm_page_size >= sizeof (struct shared_io));
+ mutex_lock (&cred->po->np->lock);
+ if (!cred->mapped)
+ {
+ default_pager_object_create (diskfs_default_pager, &cred->shared_object,
+ __vm_page_size);
+ vm_map (mach_task_self (), (u_int *)&cred->mapped, vm_page_size, 0, 1,
+ cred->shared_object, 0, 0,
+ VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|VM_PROT_WRITE, 0);
+ cred->mapped->shared_page_magic = SHARED_PAGE_MAGIC;
+ cred->mapped->conch_status = USER_HAS_NOT_CONCH;
+ spin_lock_init (&cred->mapped->lock);
+ *ctlobj = cred->shared_object;
+ *ctlobj_type = MACH_MSG_TYPE_COPY_SEND;
+ mutex_unlock (&cred->po->np->lock);
+ return 0;
+ }
+ else
+ {
+ mutex_unlock (&cred->po->np->lock);
+ return EBUSY;
+ }
+}
diff --git a/libdiskfs/io-map.c b/libdiskfs/io-map.c
new file mode 100644
index 00000000..6268f2c5
--- /dev/null
+++ b/libdiskfs/io-map.c
@@ -0,0 +1,73 @@
+/*
+ Copyright (C) 1994, 1997 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <fcntl.h>
+
+#include "priv.h"
+#include "io_S.h"
+
+/* Implement io_map as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_map (struct protid *cred,
+ memory_object_t *rdobj,
+ mach_msg_type_name_t *rdtype,
+ memory_object_t *wrobj,
+ mach_msg_type_name_t *wrtype)
+{
+ int flags;
+ struct node *node;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ *wrobj = *rdobj = MACH_PORT_NULL;
+
+ node = cred->po->np;
+ flags = cred->po->openstat & (O_READ | O_WRITE);
+
+ mutex_lock (&node->lock);
+ switch (flags)
+ {
+ case O_READ | O_WRITE:
+ *wrobj = *rdobj = diskfs_get_filemap (node, VM_PROT_READ |VM_PROT_WRITE);
+ if (*wrobj == MACH_PORT_NULL)
+ goto error;
+ mach_port_mod_refs (mach_task_self (), *rdobj, MACH_PORT_RIGHT_SEND, 1);
+ break;
+ case O_READ:
+ *rdobj = diskfs_get_filemap (node, VM_PROT_READ);
+ if (*rdobj == MACH_PORT_NULL)
+ goto error;
+ break;
+ case O_WRITE:
+ *wrobj = diskfs_get_filemap (node, VM_PROT_WRITE);
+ if (*wrobj == MACH_PORT_NULL)
+ goto error;
+ break;
+ }
+ mutex_unlock (&node->lock);
+
+ *rdtype = MACH_MSG_TYPE_MOVE_SEND;
+ *wrtype = MACH_MSG_TYPE_MOVE_SEND;
+
+ return 0;
+
+error:
+ mutex_unlock (&node->lock);
+ return errno;
+}
+
diff --git a/libdiskfs/io-modes-get.c b/libdiskfs/io-modes-get.c
new file mode 100644
index 00000000..a959881b
--- /dev/null
+++ b/libdiskfs/io-modes-get.c
@@ -0,0 +1,34 @@
+/*
+ Copyright (C) 1994 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+
+/* Implement io_get_openmodes as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_get_openmodes (struct protid *cred,
+ int *bits)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+
+ mutex_lock (&cred->po->np->lock);
+ *bits = cred->po->openstat;
+ mutex_unlock (&cred->po->np->lock);
+ return 0;
+}
+
diff --git a/libdiskfs/io-modes-off.c b/libdiskfs/io-modes-off.c
new file mode 100644
index 00000000..25efcf22
--- /dev/null
+++ b/libdiskfs/io-modes-off.c
@@ -0,0 +1,35 @@
+/*
+ Copyright (C) 1994, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+#include <fcntl.h>
+
+/* Implement io_clear_some_openmodes as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_clear_some_openmodes (struct protid *cred,
+ int offbits)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+
+ mutex_lock (&cred->po->np->lock);
+ iohelp_get_conch (&cred->po->np->conch);
+ cred->po->openstat &= ~(offbits & HONORED_STATE_MODES);
+ mutex_unlock (&cred->po->np->lock);
+ return 0;
+}
diff --git a/libdiskfs/io-modes-on.c b/libdiskfs/io-modes-on.c
new file mode 100644
index 00000000..3b7ff40c
--- /dev/null
+++ b/libdiskfs/io-modes-on.c
@@ -0,0 +1,35 @@
+/*
+ Copyright (C) 1994, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+#include <fcntl.h>
+
+/* Implement io_set_some_openmodes as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_set_some_openmodes (struct protid *cred,
+ int newbits)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+
+ mutex_lock (&cred->po->np->lock);
+ iohelp_get_conch (&cred->po->np->conch);
+ cred->po->openstat |= (newbits & HONORED_STATE_MODES);
+ mutex_unlock (&cred->po->np->lock);
+ return 0;
+}
diff --git a/libdiskfs/io-modes-set.c b/libdiskfs/io-modes-set.c
new file mode 100644
index 00000000..2744a8f7
--- /dev/null
+++ b/libdiskfs/io-modes-set.c
@@ -0,0 +1,36 @@
+/*
+ Copyright (C) 1994, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+#include <fcntl.h>
+
+/* Implement io_set_all_openmodes as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_set_all_openmodes (struct protid *cred,
+ int newbits)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+
+ mutex_lock (&cred->po->np->lock);
+ iohelp_get_conch (&cred->po->np->conch);
+ cred->po->openstat &= ~HONORED_STATE_MODES;
+ cred->po->openstat |= (newbits & HONORED_STATE_MODES);
+ mutex_unlock (&cred->po->np->lock);
+ return 0;
+}
diff --git a/libdiskfs/io-owner-get.c b/libdiskfs/io-owner-get.c
new file mode 100644
index 00000000..057aa6e2
--- /dev/null
+++ b/libdiskfs/io-owner-get.c
@@ -0,0 +1,36 @@
+/*
+ Copyright (C) 1994 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+
+/* Implement io_get_owner as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_get_owner (struct protid *cred,
+ pid_t *owner)
+{
+ struct node *np;
+
+ if (!cred)
+ return EOPNOTSUPP;
+ np = cred->po->np;
+
+ mutex_lock (&np->lock);
+ *owner = np->owner;
+ mutex_unlock (&np->lock);
+ return 0;
+}
diff --git a/libdiskfs/io-owner-mod.c b/libdiskfs/io-owner-mod.c
new file mode 100644
index 00000000..c0977785
--- /dev/null
+++ b/libdiskfs/io-owner-mod.c
@@ -0,0 +1,36 @@
+/*
+ Copyright (C) 1994 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+
+/* Implement io_mod_owner as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_mod_owner (struct protid *cred,
+ pid_t owner)
+{
+ struct node *np;
+
+ if (!cred)
+ return EOPNOTSUPP;
+ np = cred->po->np;
+
+ mutex_lock (&np->lock);
+ np->owner = owner;
+ mutex_unlock (&np->lock);
+ return 0;
+}
diff --git a/libdiskfs/io-pathconf.c b/libdiskfs/io-pathconf.c
new file mode 100644
index 00000000..b851f9b1
--- /dev/null
+++ b/libdiskfs/io-pathconf.c
@@ -0,0 +1,79 @@
+/* libdiskfs implementation of io.defs: io_pathconf
+ Copyright (C) 1992, 1993, 1994, 1995, 1999 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <unistd.h>
+#include "priv.h"
+#include "io_S.h"
+#include <dirent.h>
+#include <limits.h>
+
+/* Implement io_pathconf as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_pathconf (struct protid *cred,
+ int name,
+ int *value)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+
+ switch (name)
+ {
+ case _PC_LINK_MAX:
+ *value = diskfs_link_max;
+ break;
+
+ case _PC_MAX_CANON:
+ case _PC_MAX_INPUT:
+ case _PC_PIPE_BUF:
+ case _PC_VDISABLE:
+ case _PC_SOCK_MAXBUF:
+ *value = -1;
+ break;
+
+ case _PC_NAME_MAX:
+ /* <hurd/hurd_types.defs> string_t constrains the upper bound.
+ The `struct dirent' format defined by libc further contrains it. */
+#define D_NAMLEN_MAX (UCHAR_MAX * sizeof (((struct dirent *) 0)->d_namlen))
+ if (diskfs_name_max > D_NAMLEN_MAX || diskfs_name_max < 0)
+ diskfs_name_max = D_NAMLEN_MAX;
+ *value = diskfs_name_max;
+ break;
+
+ case _PC_NO_TRUNC: /* enforced in diskfs_lookup */
+ *value = 1; /* diskfs_name_max >= 0; */ /* see above */
+ break;
+
+ case _PC_CHOWN_RESTRICTED:
+ case _PC_SYNC_IO:
+ case _PC_ASYNC_IO:
+ *value = 1;
+ break;
+
+ case _PC_PRIO_IO:
+ *value = 0;
+ break;
+
+ case _PC_FILESIZEBITS:
+ *value = 32;
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ return 0;
+}
diff --git a/libdiskfs/io-prenotify.c b/libdiskfs/io-prenotify.c
new file mode 100644
index 00000000..f88cb286
--- /dev/null
+++ b/libdiskfs/io-prenotify.c
@@ -0,0 +1,72 @@
+/*
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+
+/* Implement io_prenotify as described in <hurd/io.defs>.
+
+ We set the prenotify size to be the allocated size of the file;
+ then users are forced to call this routine before writing past
+ that, and we can do allocation (orreturn ENOSPC if necessary. */
+kern_return_t
+diskfs_S_io_prenotify (struct protid *cred,
+ vm_offset_t start __attribute__ ((unused)),
+ vm_offset_t end)
+{
+ struct node *np;
+ int err = 0;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ np = cred->po->np;
+
+ /* Clamp it down */
+ mutex_lock (&np->lock);
+
+ if (!cred->mapped)
+ {
+ err = EINVAL;
+ goto out;
+ }
+
+ err = iohelp_verify_user_conch (&np->conch, cred);
+ if (err)
+ goto out;
+
+ iohelp_fetch_shared_data (cred);
+
+ if ((off_t) end < np->allocsize)
+ {
+ /* The user didn't need to do this, so we'll make sure they
+ have the right shared page info. */
+ spin_lock (&cred->mapped->lock);
+ iohelp_put_shared_data (cred);
+ spin_unlock (&cred->mapped->lock);
+ goto out;
+ }
+
+ err = diskfs_grow (np, end, cred);
+ if (diskfs_synchronous)
+ diskfs_node_update (np, 1);
+ if (!err && np->filemod_reqs)
+ diskfs_notice_filechange (np, FILE_CHANGED_EXTEND, 0, end);
+ out:
+ mutex_unlock (&np->lock);
+ return err;
+}
diff --git a/libdiskfs/io-read.c b/libdiskfs/io-read.c
new file mode 100644
index 00000000..4c2adf31
--- /dev/null
+++ b/libdiskfs/io-read.c
@@ -0,0 +1,109 @@
+/*
+ Copyright (C) 1994, 1995, 1996, 1997, 1999 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+#include <fcntl.h>
+
+/* Implement io_read as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_read (struct protid *cred,
+ char **data,
+ mach_msg_type_number_t *datalen,
+ off_t offset,
+ mach_msg_type_number_t maxread)
+{
+ struct node *np;
+ int err;
+ int off = offset;
+ char *buf;
+ int ourbuf = 0;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ np = cred->po->np;
+ if (!(cred->po->openstat & O_READ))
+ return EBADF;
+
+ mutex_lock (&np->lock);
+
+ iohelp_get_conch (&np->conch);
+
+ if (off == -1)
+ off = cred->po->filepointer;
+ if (off < 0)
+ {
+ mutex_unlock (&np->lock);
+ return EINVAL;
+ }
+
+ if (off > np->dn_stat.st_size)
+ maxread = 0;
+ else if (off + (off_t) maxread > np->dn_stat.st_size)
+ maxread = np->dn_stat.st_size - off;
+
+ if (maxread > *datalen)
+ {
+ ourbuf = 1;
+ buf = mmap (0, maxread, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ *data = buf;
+ }
+ else
+ buf = *data;
+
+ *datalen = maxread;
+
+ if (maxread == 0)
+ err = 0;
+ else if (S_ISLNK (np->dn_stat.st_mode))
+ {
+ /* Read from a symlink. */
+ if (! diskfs_read_symlink_hook)
+ err = EINVAL;
+ else
+ {
+ if (off == 0 && maxread == np->dn_stat.st_size)
+ err = (*diskfs_read_symlink_hook)(np, buf);
+ else
+ {
+ char *whole_link = alloca (np->dn_stat.st_size);
+ err = (*diskfs_read_symlink_hook)(np, whole_link);
+ if (! err)
+ memcpy (buf, whole_link + off, maxread);
+ }
+ }
+ }
+ else
+ err = EINVAL; /* Use read below. */
+
+ if (err == EINVAL)
+ err = _diskfs_rdwr_internal (np, buf, off, datalen, 0,
+ cred->po->openstat & O_NOATIME);
+
+ if (diskfs_synchronous)
+ diskfs_node_update (np, 1); /* atime! */
+
+ if (offset == -1 && !err)
+ cred->po->filepointer += *datalen;
+
+ if (err && ourbuf)
+ munmap (buf, maxread);
+
+ mutex_unlock (&np->lock);
+ return err;
+}
diff --git a/libdiskfs/io-readable.c b/libdiskfs/io-readable.c
new file mode 100644
index 00000000..ccc241ef
--- /dev/null
+++ b/libdiskfs/io-readable.c
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+#include <fcntl.h>
+
+/* Implement io_readable as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_readable (struct protid *cred,
+ mach_msg_type_number_t *amount)
+{
+ struct node *np;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ if (!(cred->po->openstat & O_READ))
+ return EINVAL;
+
+ np = cred->po->np;
+
+ mutex_lock (&np->lock);
+ iohelp_get_conch (&np->conch);
+ if (np->dn_stat.st_size > cred->po->filepointer)
+ *amount = np->dn_stat.st_size - cred->po->filepointer;
+ else
+ *amount = 0;
+
+ mutex_unlock (&np->lock);
+ return 0;
+}
diff --git a/libdiskfs/io-reauthenticate.c b/libdiskfs/io-reauthenticate.c
new file mode 100644
index 00000000..3fc780d2
--- /dev/null
+++ b/libdiskfs/io-reauthenticate.c
@@ -0,0 +1,61 @@
+/*
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+
+/* Implement io_reathenticate as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_reauthenticate (struct protid *cred,
+ mach_port_t rend_port)
+{
+ struct protid *newcred;
+ error_t err;
+ mach_port_t newright;
+
+ if (cred == 0)
+ return EOPNOTSUPP;
+
+ /* This routine must carefully ignore EINTR because we
+ are a simpleroutine, so callers won't know to restart. */
+
+ mutex_lock (&cred->po->np->lock);
+ do
+ err = diskfs_start_protid (cred->po, &newcred);
+ while (err == EINTR);
+ if (err)
+ {
+ mutex_unlock (&cred->po->np->lock);
+ return err;
+ }
+
+ newright = ports_get_right (newcred);
+ err = mach_port_insert_right (mach_task_self (), newright, newright,
+ MACH_MSG_TYPE_MAKE_SEND);
+ assert_perror (err);
+
+ diskfs_finish_protid (newcred, iohelp_reauth (diskfs_auth_server_port,
+ rend_port, newright, 1));
+ mach_port_deallocate (mach_task_self (), rend_port);
+ mach_port_deallocate (mach_task_self (), newright);
+
+ mutex_unlock (&cred->po->np->lock);
+
+ ports_port_deref (newcred);
+
+ return 0;
+}
diff --git a/libdiskfs/io-rel-conch.c b/libdiskfs/io-rel-conch.c
new file mode 100644
index 00000000..c0257650
--- /dev/null
+++ b/libdiskfs/io-rel-conch.c
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 1994, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+
+/* Implement io_release_conch as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_release_conch (struct protid *cred)
+{
+ struct node *np;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ np = cred->po->np;
+ mutex_lock (&np->lock);
+ if (!cred->mapped)
+ {
+ mutex_unlock (&np->lock);
+ return EINVAL;
+ }
+
+ np = cred->po->np;
+
+ iohelp_handle_io_release_conch (&np->conch, cred);
+
+ mutex_unlock (&np->lock);
+ return 0;
+}
diff --git a/libdiskfs/io-restrict-auth.c b/libdiskfs/io-restrict-auth.c
new file mode 100644
index 00000000..0a3a5021
--- /dev/null
+++ b/libdiskfs/io-restrict-auth.c
@@ -0,0 +1,82 @@
+/*
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+
+/* Tell if the array LIST (of size N) contains a member equal to QUERY. */
+static inline int
+listmember (int *list, int query, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ if (list[i] == query)
+ return 1;
+ return 0;
+}
+
+/* Implement io_restrict_auth as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_restrict_auth (struct protid *cred,
+ mach_port_t *newport,
+ mach_msg_type_name_t *newportpoly,
+ uid_t *uids,
+ u_int nuids,
+ gid_t *gids,
+ u_int ngids)
+{
+ error_t err;
+ struct idvec *uvec, *gvec;
+ struct protid *newpi;
+ int i;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ uvec = make_idvec ();
+ gvec = make_idvec ();
+
+ if (idvec_contains (cred->user->uids, 0))
+ {
+ /* CRED has root access, and so may use any ids. */
+ idvec_set_ids (uvec, uids, nuids);
+ idvec_set_ids (gvec, gids, ngids);
+ }
+ else
+ {
+ /* Otherwise, use any of the requested ids that CRED already has. */
+ for (i = 0; i < cred->user->uids->num; i++)
+ if (listmember (uids, cred->user->uids->ids[i], nuids))
+ idvec_add (uvec, cred->user->uids->ids[i]);
+ for (i = 0; i < cred->user->gids->num; i++)
+ if (listmember (gids, cred->user->gids->ids[i], ngids))
+ idvec_add (gvec, cred->user->gids->ids[i]);
+ }
+
+ mutex_lock (&cred->po->np->lock);
+ err = diskfs_create_protid (cred->po, iohelp_create_iouser (uvec, gvec),
+ &newpi);
+ if (! err)
+ {
+ *newport = ports_get_right (newpi);
+ *newportpoly = MACH_MSG_TYPE_MAKE_SEND;
+ ports_port_deref (newpi);
+ }
+ mutex_unlock (&cred->po->np->lock);
+
+ return err;
+}
diff --git a/libdiskfs/io-revoke.c b/libdiskfs/io-revoke.c
new file mode 100644
index 00000000..d42fb6c1
--- /dev/null
+++ b/libdiskfs/io-revoke.c
@@ -0,0 +1,59 @@
+/*
+ Copyright (C) 1999 Free Software Foundation
+ Written by Thomas Bushnell, BSG.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+
+/* Implement io_revoke as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_revoke (struct protid *cred)
+{
+ error_t err;
+ struct node *np;
+
+ error_t
+ iterator_function (void *port)
+ {
+ struct protid *user = port;
+
+ if ((user != cred)
+ && (user->po->np == np))
+ ports_destroy_right (user);
+ return 0;
+ }
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ np = cred->po->np;
+
+ mutex_lock (&np->lock);
+
+ err = fshelp_isowner (&np->dn_stat, cred->user);
+
+ mutex_unlock (&np->lock);
+
+ if (err)
+ return err;
+
+ ports_inhibit_bucket_rpcs (diskfs_port_bucket);
+ ports_class_iterate (diskfs_protid_class, iterator_function);
+ ports_resume_bucket_rpcs (diskfs_port_bucket);
+
+ return 0;
+}
diff --git a/libdiskfs/io-seek.c b/libdiskfs/io-seek.c
new file mode 100644
index 00000000..33aa77d4
--- /dev/null
+++ b/libdiskfs/io-seek.c
@@ -0,0 +1,57 @@
+/*
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+#include <unistd.h>
+
+#define diskfs_readonly 0
+#define diskfs_synchronous 0
+
+/* Implement io_seek as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_seek (struct protid *cred,
+ off_t offset,
+ int whence,
+ off_t *newoffset)
+{
+
+ CHANGE_NODE_FIELD (cred,
+ ({
+ iohelp_get_conch (&np->conch);
+ switch (whence)
+ {
+ case SEEK_SET:
+ err = 0;
+ cred->po->filepointer = offset;
+ break;
+ case SEEK_CUR:
+ err = 0;
+ cred->po->filepointer += offset;
+ break;
+ case SEEK_END:
+ err = 0;
+ cred->po->filepointer = (np->dn_stat.st_size
+ + offset);
+ break;
+ default:
+ err = EINVAL;
+ break;
+ }
+ *newoffset = cred->po->filepointer;
+ }));
+}
diff --git a/libdiskfs/io-select.c b/libdiskfs/io-select.c
new file mode 100644
index 00000000..07112f7b
--- /dev/null
+++ b/libdiskfs/io-select.c
@@ -0,0 +1,32 @@
+/*
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+#include <fcntl.h>
+
+/* Implement io_select as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_select (struct protid *cred,
+ int *type)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+
+ *type &= ~SELECT_URG;
+ return 0;
+}
diff --git a/libdiskfs/io-sigio.c b/libdiskfs/io-sigio.c
new file mode 100644
index 00000000..229129bc
--- /dev/null
+++ b/libdiskfs/io-sigio.c
@@ -0,0 +1,36 @@
+/*
+ Copyright (C) 1994, 1995 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+#include <fcntl.h>
+
+/* Implement io_sigio as described in <hurd/io.defs>. We do this
+ for O_FSYNC right now, but will eventually do it for async I/O
+ too. */
+kern_return_t
+diskfs_S_io_sigio (struct protid *cred)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+
+ mutex_lock (&cred->po->np->lock);
+ if ((cred->po->openstat & O_FSYNC) || diskfs_synchronous)
+ diskfs_file_update (cred->po->np, 1);
+ mutex_unlock (&cred->po->np->lock);
+ return 0;
+}
diff --git a/libdiskfs/io-stat.c b/libdiskfs/io-stat.c
new file mode 100644
index 00000000..e51f6d93
--- /dev/null
+++ b/libdiskfs/io-stat.c
@@ -0,0 +1,51 @@
+/*
+ Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+#include <string.h>
+
+/* Implement io_stat as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_stat (struct protid *cred,
+ io_statbuf_t *statbuf)
+{
+ struct node *np;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ np = cred->po->np;
+ mutex_lock (&np->lock);
+
+ iohelp_get_conch (&np->conch);
+ if (diskfs_synchronous)
+ diskfs_node_update (np, 1);
+ else
+ diskfs_set_node_times (np);
+
+ bcopy (&np->dn_stat, statbuf, sizeof (struct stat));
+ statbuf->st_mode &= ~(S_IATRANS | S_IROOT);
+ if (fshelp_translated (&np->transbox))
+ statbuf->st_mode |= S_IATRANS;
+ if (cred->po->shadow_root == np || np == diskfs_root_node)
+ statbuf->st_mode |= S_IROOT;
+
+ mutex_unlock (&np->lock);
+
+ return 0;
+}
diff --git a/libdiskfs/io-stubs.c b/libdiskfs/io-stubs.c
new file mode 100644
index 00000000..aa1e48b2
--- /dev/null
+++ b/libdiskfs/io-stubs.c
@@ -0,0 +1,63 @@
+/*
+ Copyright (C) 1994, 1995 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+
+/* Unimplemented stubs. */
+
+/* Implement io_readsleep as described in <hurd/io.defs>
+ Semantics of ordinary files say this shouldn't happen, because
+ we never set use_read_size in the shared data. */
+kern_return_t
+diskfs_S_io_readsleep (struct protid *cred)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+
+ return 0;
+}
+
+/* Implement io_eofnotify as described in <hurd/io.defs>.
+ We don't use this feature. */
+kern_return_t
+diskfs_S_io_eofnotify (struct protid *cred)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+
+ return 0;
+}
+
+/* Implement io_postnotify as described in <hurd/io.defs>.
+ We don't use this feature. */
+kern_return_t
+diskfs_S_io_postnotify (struct protid *cred,
+ vm_offset_t start __attribute__ ((unused)),
+ vm_offset_t end __attribute__ ((unused)))
+{
+ return cred ? 0 : EOPNOTSUPP;
+}
+
+/* Implement io_readnotify as described in <hurd/io.defs>.
+ We don't use this feature. */
+kern_return_t
+diskfs_S_io_readnotify (struct protid *cred)
+{
+ return cred ? 0 : EOPNOTSUPP;
+}
+
diff --git a/libdiskfs/io-version.c b/libdiskfs/io-version.c
new file mode 100644
index 00000000..b19dd0d1
--- /dev/null
+++ b/libdiskfs/io-version.c
@@ -0,0 +1,42 @@
+/*
+ Copyright (C) 1994, 1996 Free Software Foundation
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include <stdio.h>
+
+#include "priv.h"
+#include "io_S.h"
+
+kern_return_t
+diskfs_S_io_server_version (struct protid *cred,
+ char *server_name,
+ int *major,
+ int *minor,
+ int *edit)
+{
+ if (cred)
+ {
+ snprintf (server_name, sizeof (string_t), "%s %s",
+ diskfs_server_name, diskfs_server_version);
+ return 0;
+ }
+ else
+ return EOPNOTSUPP;
+}
diff --git a/libdiskfs/io-write.c b/libdiskfs/io-write.c
new file mode 100644
index 00000000..adbfc6d5
--- /dev/null
+++ b/libdiskfs/io-write.c
@@ -0,0 +1,94 @@
+/*
+ Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include "io_S.h"
+#include <fcntl.h>
+
+/* Implement io_write as described in <hurd/io.defs>. */
+kern_return_t
+diskfs_S_io_write (struct protid *cred,
+ char *data,
+ mach_msg_type_number_t datalen,
+ off_t offset,
+ mach_msg_type_number_t *amt)
+{
+ struct node *np;
+ error_t err;
+ int off = offset;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ np = cred->po->np;
+ if (!(cred->po->openstat & O_WRITE))
+ return EBADF;
+
+ mutex_lock (&np->lock);
+
+ assert (!S_ISDIR(np->dn_stat.st_mode));
+
+ iohelp_get_conch (&np->conch);
+
+ if (off == -1)
+ {
+ if (cred->po->openstat & O_APPEND)
+ cred->po->filepointer = np->dn_stat.st_size;
+ off = cred->po->filepointer;
+ }
+ if (off < 0)
+ {
+ err = EINVAL;
+ goto out;
+ }
+
+ err = 0;
+ while (off + (off_t) datalen > np->allocsize)
+ {
+ err = diskfs_grow (np, off + datalen, cred);
+ if (diskfs_synchronous)
+ diskfs_node_update (np, 1);
+ if (err)
+ goto out;
+ if (np->filemod_reqs)
+ diskfs_notice_filechange (np, FILE_CHANGED_EXTEND, 0, off + datalen);
+ }
+
+ if (off + (off_t) datalen > np->dn_stat.st_size)
+ {
+ np->dn_stat.st_size = off + datalen;
+ np->dn_set_ctime = 1;
+ if (diskfs_synchronous)
+ diskfs_node_update (np, 1);
+ }
+
+ *amt = datalen;
+ err = _diskfs_rdwr_internal (np, data, off, amt, 1, 0);
+
+ if (!err && offset == -1)
+ cred->po->filepointer += *amt;
+
+ if (!err
+ && ((cred->po->openstat & O_FSYNC) || diskfs_synchronous))
+ diskfs_file_update (np, 1);
+
+ if (!err && np->filemod_reqs)
+ diskfs_notice_filechange (np, FILE_CHANGED_WRITE, off, off + *amt);
+ out:
+ mutex_unlock (&np->lock);
+ return err;
+}
diff --git a/libdiskfs/lithp.h b/libdiskfs/lithp.h
new file mode 100644
index 00000000..be56377d
--- /dev/null
+++ b/libdiskfs/lithp.h
@@ -0,0 +1,31 @@
+/*
+ Copyright (C) 1994, 1996 Free Software Foundation
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+/* Hmm. */
+
+#define dithkfth_TH_file_chauthor diskfs_S_file_chauthor
+#define fthhelp_ithowner fshelp_isowner
+#define dithkfth_validate_author_change diskfs_validate_author_change
+#define dn_thtat dn_stat
+#define tht_author st_author
+#define dn_thet_theetime dn_set_ctime
+#define fth_TH_dot_h "fs_S.h"
+#define uther user
diff --git a/libdiskfs/lookup.c b/libdiskfs/lookup.c
new file mode 100644
index 00000000..d81a053e
--- /dev/null
+++ b/libdiskfs/lookup.c
@@ -0,0 +1,234 @@
+/* Wrapper for diskfs_lookup_hard
+ Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/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. */
+
+#include "priv.h"
+#include <string.h>
+
+static struct
+{
+ int present;
+ int absent;
+ int errors;
+ int dot;
+ int dotdot;
+} cache_misses;
+static spin_lock_t cm_lock = SPIN_LOCK_INITIALIZER;
+
+
+/* Lookup in directory DP (which is locked) the name NAME. TYPE will
+ either be LOOKUP, CREATE, RENAME, or REMOVE. CRED identifies the
+ user making the call.
+
+ NAME will have leading and trailing slashes stripped. It is an
+ error if there are internal slashes. NAME will be modified in
+ place if there are slashes in it; it is therefore an error to
+ specify a constant NAME which contains slashes.
+
+ If the name is found, return zero, and (if NP is nonzero) set *NP
+ to point to the node for it, locked. If the name is not found,
+ return ENOENT, and (if NP is nonzero) set *NP to zero. If NP is
+ zero, then the node found must not be locked, even transitorily.
+ Lookups for REMOVE and RENAME (which must often check permissions
+ on the node being found) will always set NP.
+
+ If DS is nonzero then:
+ For LOOKUP: set *DS to be ignored by diskfs_drop_dirstat.
+ For CREATE: on success, set *DS to be ignored by diskfs_drop_dirstat.
+ on failure, set *DS for a future call to diskfs_direnter.
+ For RENAME: on success, set *DS for a future call to diskfs_dirrewrite.
+ on failure, set *DS for a future call to diskfs_direnter.
+ For REMOVE: on success, set *DS for a future call to diskfs_dirremove.
+ on failure, set *DS to be ignored by diskfs_drop_dirstat.
+ The caller of this function guarantees that if DS is nonzero, then
+ either the appropriate call listed above or diskfs_drop_dirstat will
+ be called with DS before the directory DP is unlocked, and guarantees
+ that no lookup calls will be made on this directory between this
+ lookup and the use (or descruction) of *DS.
+
+ If you use the library's versions of diskfs_rename_dir,
+ diskfs_clear_directory, and diskfs_init_dir, then lookups for `..'
+ might have the flag SPEC_DOTDOT or'd in. This has the following special
+ meaning:
+ For LOOKUP: DP should be unlocked and its reference dropped before
+ returning.
+ For RENAME and REMOVE: The node being found (*NP) is already held
+ locked, so don't lock it or add a reference to it.
+ (SPEC_DOTDOT will not be given with CREATE.)
+
+ Return ENOTDIR if DP is not a directory.
+ Return EACCES if CRED isn't allowed to search DP.
+ Return EACCES if completing the operation will require writing
+ the directory and diskfs_checkdirmod won't allow the modification.
+ Return ENOENT if NAME isn't in the directory.
+ Return EAGAIN if NAME refers to the `..' of this filesystem's root.
+ Return EIO if appropriate.
+
+ This function is a wrapper for diskfs_lookup_hard. */
+error_t
+diskfs_lookup (struct node *dp, char *name, enum lookup_type type,
+ struct node **np, struct dirstat *ds, struct protid *cred)
+{
+ error_t err;
+ struct node *cached;
+
+ if (type == REMOVE || type == RENAME)
+ assert (np);
+
+ if (!S_ISDIR (dp->dn_stat.st_mode))
+ {
+ if (ds)
+ diskfs_null_dirstat (ds);
+ return ENOTDIR;
+ }
+
+ /* Strip leading and trailing slashes. */
+ while (*name == '/')
+ name++;
+
+ if (name[0] == '\0')
+ {
+ if (ds)
+ diskfs_null_dirstat (ds);
+ return EINVAL;
+ }
+ else
+ {
+ char *p = strchr (name, '/');
+ if (p != 0)
+ {
+ *p = '\0';
+ do
+ ++p;
+ while (*p == '/');
+ if (*p != '\0')
+ {
+ if (ds)
+ diskfs_null_dirstat (ds);
+ return EINVAL;
+ }
+ }
+ }
+
+
+ err = fshelp_access (&dp->dn_stat, S_IEXEC, cred->user);
+ if (err)
+ {
+ if (ds)
+ diskfs_null_dirstat (ds);
+ return err;
+ }
+
+ if (dp == cred->po->shadow_root
+ && name[0] == '.' && name[1] == '.' && name[2] == '\0')
+ /* Ran into the root. */
+ {
+ if (ds)
+ diskfs_null_dirstat (ds);
+ return EAGAIN;
+ }
+
+ if (type == LOOKUP)
+ /* Check the cache first */
+ cached = diskfs_check_lookup_cache (dp, name);
+ else
+ cached = 0;
+
+ if (cached == (struct node *)-1)
+ /* Negative lookup cached. */
+ {
+ if (np)
+ *np = 0;
+ return ENOENT;
+ }
+ else if (cached)
+ {
+ if (np)
+ *np = cached; /* Return what we found. */
+ else
+ /* Ick, the user doesn't want the result, we have to drop our
+ reference. */
+ if (cached == dp)
+ diskfs_nrele (cached);
+ else
+ diskfs_nput (cached);
+
+ if (ds)
+ diskfs_null_dirstat (ds);
+ }
+ else
+ {
+ err = diskfs_lookup_hard (dp, name, type, np, ds, cred);
+
+ spin_lock (&cm_lock);
+ if (type == LOOKUP)
+ {
+ if (err == ENOENT)
+ cache_misses.absent++;
+ else if (err)
+ cache_misses.errors++;
+ else
+ cache_misses.present++;
+ if (name[0] == '.')
+ {
+ if (name[1] == '\0')
+ cache_misses.dot++;
+ else if (name[1] == '.' && name[2] == '\0')
+ cache_misses.dotdot++;
+ }
+ }
+ spin_unlock (&cm_lock);
+
+ if (err && err != ENOENT)
+ return err;
+
+ if (type == RENAME
+ || (type == CREATE && err == ENOENT)
+ || (type == REMOVE && err != ENOENT))
+ {
+ error_t err2;
+
+ if (diskfs_name_max > 0 && strlen (name) > diskfs_name_max)
+ err2 = ENAMETOOLONG;
+ else
+ err2 = fshelp_checkdirmod (&dp->dn_stat,
+ (err || !np) ? 0 : &(*np)->dn_stat,
+ cred->user);
+ if (err2)
+ {
+ if (np && !err)
+ {
+ if (*np == dp)
+ diskfs_nrele (*np);
+ else
+ diskfs_nput (*np);
+ *np = 0;
+ }
+ return err2;
+ }
+ }
+
+ if ((type == LOOKUP || type == CREATE) && !err && np)
+ diskfs_enter_lookup_cache (dp, *np, name);
+ else if (type == LOOKUP && err == ENOENT)
+ diskfs_enter_lookup_cache (dp, 0, name);
+ }
+
+ return err;
+}
diff --git a/libdiskfs/name-cache.c b/libdiskfs/name-cache.c
new file mode 100644
index 00000000..f31482d4
--- /dev/null
+++ b/libdiskfs/name-cache.c
@@ -0,0 +1,265 @@
+/* Directory name lookup caching
+
+ Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/BSG, & Miles Bader.
+
+ 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. */
+
+#include "priv.h"
+#include <string.h>
+#include <cacheq.h>
+
+/* Maximum number of names to cache at once */
+#define MAXCACHE 200
+
+/* Maximum length of file name we bother caching */
+#define CACHE_NAME_LEN 100
+
+/* Cache entry */
+struct lookup_cache
+{
+ struct cacheq_hdr hdr;
+
+ /* Used to indentify nodes to the fs dependent code. 0 for NODE_CACHE_ID
+ means a `negative' entry -- recording that there's definitely no node with
+ this name. */
+ int dir_cache_id, node_cache_id;
+
+ /* Name of the node NODE_CACHE_ID in the directory DIR_CACHE_ID. Entries
+ with names too long to fit in this buffer aren't cached at all. */
+ char name[CACHE_NAME_LEN];
+
+ /* Strlen of NAME. If this is zero, it's an unused entry. */
+ size_t name_len;
+
+ /* XXX */
+ int stati;
+};
+
+/* The contents of the cache in no particular order */
+static struct cacheq lookup_cache = { sizeof (struct lookup_cache) };
+
+static spin_lock_t cache_lock = SPIN_LOCK_INITIALIZER;
+
+/* Buffer to hold statistics */
+static struct stats
+{
+ long pos_hits;
+ long neg_hits;
+ long miss;
+ long fetch_errors;
+} statistics;
+
+#define PARTIAL_THRESH 100
+#define NPARTIALS MAXCACHE / PARTIAL_THRESH
+struct stats partial_stats [NPARTIALS];
+
+
+/* If there's an entry for NAME, of length NAME_LEN, in directory DIR in the
+ cache, return its entry, otherwise 0. CACHE_LOCK must be held. */
+static struct lookup_cache *
+find_cache (struct node *dir, const char *name, size_t name_len)
+{
+ struct lookup_cache *c;
+ int i;
+
+ /* Search the list. All unused entries are contiguous at the end of the
+ list, so we can stop searching when we see the first one. */
+ for (i = 0, c = lookup_cache.mru;
+ c && c->name_len;
+ c = c->hdr.next, i++)
+ if (c->name_len == name_len
+ && c->dir_cache_id == dir->cache_id
+ && c->name[0] == name[0] && strcmp (c->name, name) == 0)
+ {
+ c->stati = i / 100;
+ return c;
+ }
+
+ return 0;
+}
+
+/* Node NP has just been found in DIR with NAME. If NP is null, that
+ means that this name has been confirmed as absent in the directory. */
+void
+diskfs_enter_lookup_cache (struct node *dir, struct node *np, const char *name)
+{
+ struct lookup_cache *c;
+ size_t name_len = strlen (name);
+
+ if (name_len > CACHE_NAME_LEN - 1)
+ return;
+
+ spin_lock (&cache_lock);
+
+ if (lookup_cache.length == 0)
+ /* There should always be an lru_cache; this being zero means that the
+ cache hasn't been initialized yet. Do so. */
+ cacheq_set_length (&lookup_cache, MAXCACHE);
+
+ /* See if there's an old entry for NAME in DIR. If not, replace the least
+ recently used entry. */
+ c = find_cache (dir, name, name_len) ?: lookup_cache.lru;
+
+ /* Fill C with the new entry. */
+ c->dir_cache_id = dir->cache_id;
+ c->node_cache_id = np ? np->cache_id : 0;
+ strcpy (c->name, name);
+ c->name_len = name_len;
+
+ /* Now C becomes the MRU entry! */
+ cacheq_make_mru (&lookup_cache, c);
+
+ spin_unlock (&cache_lock);
+}
+
+/* Purge all references in the cache to NP as a node inside
+ directory DP. */
+void
+diskfs_purge_lookup_cache (struct node *dp, struct node *np)
+{
+ struct lookup_cache *c, *next;
+
+ spin_lock (&cache_lock);
+ for (c = lookup_cache.mru; c; c = next)
+ {
+ /* Save C->hdr.next, since we may move C from this position. */
+ next = c->hdr.next;
+
+ if (c->name_len
+ && c->dir_cache_id == dp->cache_id
+ && c->node_cache_id == np->cache_id)
+ {
+ c->name_len = 0;
+ cacheq_make_lru (&lookup_cache, c); /* Use C as the next free
+ entry. */
+ }
+ }
+ spin_unlock (&cache_lock);
+}
+
+/* Register a negative hit for an entry in the Nth stat class */
+void
+register_neg_hit (int n)
+{
+ int i;
+
+ statistics.neg_hits++;
+
+ for (i = 0; i < n; i++)
+ partial_stats[i].miss++;
+ for (; i < NPARTIALS; i++)
+ partial_stats[i].neg_hits++;
+}
+
+/* Register a positive hit for an entry in the Nth stat class */
+void
+register_pos_hit (int n)
+{
+ int i;
+
+ statistics.pos_hits++;
+
+ for (i = 0; i < n; i++)
+ partial_stats[i].miss++;
+ for (; i < NPARTIALS; i++)
+ partial_stats[i].pos_hits++;
+}
+
+/* Register a miss */
+void
+register_miss ()
+{
+ int i;
+
+ statistics.miss++;
+ for (i = 0; i < NPARTIALS; i++)
+ partial_stats[i].miss++;
+}
+
+
+
+/* Scan the cache looking for NAME inside DIR. If we don't know
+ anything entry at all, then return 0. If the entry is confirmed to
+ not exist, then return -1. Otherwise, return NP for the entry, with
+ a newly allocated reference. */
+struct node *
+diskfs_check_lookup_cache (struct node *dir, const char *name)
+{
+ struct lookup_cache *c;
+
+ spin_lock (&cache_lock);
+
+ c = find_cache (dir, name, strlen (name));
+ if (c)
+ {
+ int id = c->node_cache_id;
+
+ cacheq_make_mru (&lookup_cache, c); /* Record C as recently used. */
+
+ if (id == 0)
+ /* A negative cache entry. */
+ {
+ register_neg_hit (c->stati);
+ spin_unlock (&cache_lock);
+ return (struct node *)-1;
+ }
+ else if (id == dir->cache_id)
+ /* The cached node is the same as DIR. */
+ {
+ register_pos_hit (c->stati);
+ spin_unlock (&cache_lock);
+ diskfs_nref (dir);
+ return dir;
+ }
+ else
+ /* Just a normal entry in DIR; get the actual node. */
+ {
+ struct node *np;
+ error_t err;
+
+ register_pos_hit (c->stati);
+ spin_unlock (&cache_lock);
+
+ if (name[0] == '.' && name[1] == '.' && name[2] == '\0')
+ {
+ mutex_unlock (&dir->lock);
+ err = diskfs_cached_lookup (id, &np);
+ mutex_lock (&dir->lock);
+
+ /* In the window where DP was unlocked, we might
+ have lost. So check the cache again, and see
+ if it's still there; if so, then we win. */
+ c = find_cache (dir, "..", 2);
+ if (!c || c->node_cache_id != id)
+ {
+ /* Lose */
+ mutex_unlock (&np->lock);
+ return 0;
+ }
+ }
+ else
+ err = diskfs_cached_lookup (id, &np);
+ return err ? 0 : np;
+ }
+ }
+
+ register_miss ();
+ spin_unlock (&cache_lock);
+
+ return 0;
+}
diff --git a/libdiskfs/node-create.c b/libdiskfs/node-create.c
new file mode 100644
index 00000000..09dc4a5a
--- /dev/null
+++ b/libdiskfs/node-create.c
@@ -0,0 +1,119 @@
+/* Making new files
+ Copyright (C) 1992, 1993, 1994, 1996, 1998 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+/* Create a new node. Give it MODE; if that includes IFDIR, also
+ initialize `.' and `..' in the new directory. Return the node in NPP.
+ CRED identifies the user responsible for the call. If NAME is nonzero,
+ then link the new node into DIR with name NAME; DS is the result of a
+ prior diskfs_lookup for creation (and DIR has been held locked since).
+ DIR must always be provided as at least a hint for disk allocation
+ strategies. */
+error_t
+diskfs_create_node (struct node *dir,
+ const char *name,
+ mode_t mode,
+ struct node **newnode,
+ struct protid *cred,
+ struct dirstat *ds)
+{
+ struct node *np;
+ error_t err;
+ uid_t newuid;
+ gid_t newgid;
+
+ if (diskfs_check_readonly ())
+ return EROFS;
+
+ /* Make the node */
+ err = diskfs_alloc_node (dir, mode, newnode);
+ if (err)
+ {
+ if (name)
+ diskfs_drop_dirstat (dir, ds);
+ return err;
+ }
+
+ np = *newnode;
+
+ /* Initialize the on-disk fields. */
+ if (cred->user->uids->num)
+ newuid = cred->user->uids->ids[0];
+ else
+ {
+ newuid = dir->dn_stat.st_uid;
+ mode &= ~S_ISUID;
+ }
+ err = diskfs_validate_owner_change (np, newuid);
+ if (err)
+ goto change_err;
+ np->dn_stat.st_uid = newuid;
+ if (np->author_tracks_uid)
+ np->dn_stat.st_author = newuid;
+
+ newgid = dir->dn_stat.st_gid;
+ if (!idvec_contains (cred->user->gids, newgid))
+ mode &= ~S_ISGID;
+ err = diskfs_validate_group_change (np, newgid);
+ if (err)
+ goto change_err;
+ np->dn_stat.st_gid = newgid;
+
+ np->dn_stat.st_rdev = 0;
+ np->dn_stat.st_nlink = !!name;
+ err = diskfs_validate_mode_change (np, mode);
+ if (err)
+ goto change_err;
+ np->dn_stat.st_mode = mode;
+
+ np->dn_stat.st_blocks = 0;
+ np->dn_stat.st_size = 0;
+ np->dn_stat.st_flags = 0;
+ np->dn_set_atime = 1;
+ np->dn_set_mtime = 1;
+ np->dn_set_ctime = 1;
+
+ if (S_ISDIR (mode))
+ err = diskfs_init_dir (np, dir, cred);
+
+ diskfs_node_update (np, 1);
+
+ if (err)
+ {
+ change_err:
+ np->dn_stat.st_mode = 0;
+ np->dn_stat.st_nlink = 0;
+ if (name)
+ diskfs_drop_dirstat (dir, ds);
+ return err;
+ }
+
+ if (name)
+ {
+ err = diskfs_direnter (dir, name, np, ds, cred);
+ if (err)
+ {
+ if (S_ISDIR (mode))
+ diskfs_clear_directory (np, dir, cred);
+ np->dn_stat.st_nlink = 0;
+ np->dn_set_ctime = 1;
+ diskfs_nput (np);
+ }
+ }
+ return err;
+}
diff --git a/libdiskfs/node-drop.c b/libdiskfs/node-drop.c
new file mode 100644
index 00000000..f44966ba
--- /dev/null
+++ b/libdiskfs/node-drop.c
@@ -0,0 +1,100 @@
+/*
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+/* Free the list of modification requests MR */
+static void
+free_modreqs (struct modreq *mr)
+{
+ struct modreq *tmp;
+ for (; mr; mr = tmp)
+ {
+ mach_port_deallocate (mach_task_self (), mr->port);
+ tmp = mr->next;
+ free (mr);
+ }
+}
+
+
+/* Node NP now has no more references; clean all state. The
+ diskfs_node_refcnt_lock must be held, and will be released
+ upon return. NP must be locked. */
+void
+diskfs_drop_node (struct node *np)
+{
+ mode_t savemode;
+
+ if (np->dn_stat.st_nlink == 0)
+ {
+ diskfs_check_readonly ();
+ assert (!diskfs_readonly);
+
+ if (np->dn_stat.st_mode & S_IPTRANS)
+ diskfs_set_translator (np, 0, 0, 0);
+
+ if (np->allocsize != 0
+ || (diskfs_create_symlink_hook
+ && S_ISLNK (np->dn_stat.st_mode)
+ && np->dn_stat.st_size))
+ {
+ /* If the node needs to be truncated, then a complication
+ arises, because truncation might require gaining
+ new references to the node. So, we give ourselves
+ a reference back, unlock the refcnt lock. Then
+ we are in the state of a normal user, and do the truncate
+ and an nput. The next time through, this routine
+ will notice that the size is zero, and not have to
+ do anything. */
+ np->references++;
+ spin_unlock (&diskfs_node_refcnt_lock);
+ diskfs_truncate (np, 0);
+
+ /* Force allocsize to zero; if truncate consistently fails this
+ will at least prevent an infinite loop in this routine. */
+ np->allocsize = 0;
+
+ diskfs_nput (np);
+ return;
+ }
+
+ assert (np->dn_stat.st_size == 0);
+
+ savemode = np->dn_stat.st_mode;
+ np->dn_stat.st_mode = 0;
+ np->dn_stat.st_rdev = 0;
+ np->dn_set_ctime = np->dn_set_atime = 1;
+ diskfs_node_update (np, 1);
+ diskfs_free_node (np, savemode);
+ }
+ else
+ diskfs_node_update (np, diskfs_synchronous);
+
+ fshelp_drop_transbox (&np->transbox);
+
+ if (np->dirmod_reqs)
+ free_modreqs (np->dirmod_reqs);
+ if (np->filemod_reqs)
+ free_modreqs (np->filemod_reqs);
+
+ assert (!np->sockaddr);
+
+ diskfs_node_norefs (np);
+ spin_unlock (&diskfs_node_refcnt_lock);
+}
+
+
diff --git a/libdiskfs/node-make.c b/libdiskfs/node-make.c
new file mode 100644
index 00000000..ca5119a0
--- /dev/null
+++ b/libdiskfs/node-make.c
@@ -0,0 +1,50 @@
+/*
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include <fcntl.h>
+
+
+/* Create a and return new node structure with DN as its physical disknode.
+ The node will have one hard reference and no light references. */
+struct node *
+diskfs_make_node (struct disknode *dn)
+{
+ struct node *np = malloc (sizeof (struct node));
+
+ np->dn = dn;
+ np->dn_set_ctime = 0;
+ np->dn_set_atime = 0;
+ np->dn_set_mtime = 0;
+ np->dn_stat_dirty = 0;
+
+ mutex_init (&np->lock);
+ np->references = 1;
+ np->light_references = 0;
+ np->owner = 0;
+ np->sockaddr = MACH_PORT_NULL;
+
+ np->dirmod_reqs = 0;
+ np->filemod_reqs = 0;
+
+ fshelp_transbox_init (&np->transbox, &np->lock, np);
+ iohelp_initialize_conch (&np->conch, &np->lock);
+ fshelp_lock_init (&np->userlock);
+
+
+ return np;
+}
diff --git a/libdiskfs/node-nput.c b/libdiskfs/node-nput.c
new file mode 100644
index 00000000..2f4a7db4
--- /dev/null
+++ b/libdiskfs/node-nput.c
@@ -0,0 +1,75 @@
+/*
+ Copyright (C) 1999 Free Software Foundation, Inc.
+ Written by Thomas Bushnell, 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. */
+
+#include "priv.h"
+
+/* Unlock node NP and release a hard reference; if this is the last
+ hard reference and there are no links to the file then request
+ soft references to be dropped. */
+void
+diskfs_nput (struct node *np)
+{
+ int tried_drop_softrefs = 0;
+
+ loop:
+ spin_lock (&diskfs_node_refcnt_lock);
+ assert (np->references);
+ np->references--;
+ if (np->references + np->light_references == 0)
+ diskfs_drop_node (np);
+ else if (np->references == 0 && !tried_drop_softrefs)
+ {
+ spin_unlock (&diskfs_node_refcnt_lock);
+
+ /* This is our cue that something akin to "last process closes file"
+ in the POSIX.1 sense happened, so make sure any pending node time
+ updates now happen in a timely fashion. */
+ diskfs_set_node_times (np);
+
+ diskfs_lost_hardrefs (np);
+ if (!np->dn_stat.st_nlink)
+ {
+ /* There are no links. If there are soft references that
+ can be dropped, we can't let them postpone deallocation.
+ So attempt to drop them. But that's a user-supplied
+ routine, which might result in further recursive calls to
+ the ref-counting system. So we have to reacquire our
+ reference around the call to forestall disaster. */
+ spin_lock (&diskfs_node_refcnt_lock);
+ np->references++;
+ spin_unlock (&diskfs_node_refcnt_lock);
+
+ diskfs_try_dropping_softrefs (np);
+
+ /* But there's no value in looping forever in this
+ routine; only try to drop soft refs once. */
+ tried_drop_softrefs = 1;
+
+ /* Now we can drop the reference back... */
+ goto loop;
+ }
+ mutex_unlock (&np->lock);
+ }
+ else
+ {
+ spin_unlock (&diskfs_node_refcnt_lock);
+ mutex_unlock (&np->lock);
+ }
+}
diff --git a/libdiskfs/node-nputl.c b/libdiskfs/node-nputl.c
new file mode 100644
index 00000000..45b109ea
--- /dev/null
+++ b/libdiskfs/node-nputl.c
@@ -0,0 +1,38 @@
+/*
+ Copyright (C) 1999 Free Software Foundation, Inc.
+ Written by Thomas Bushnell, 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. */
+
+
+#include "priv.h"
+
+/* Unlock node NP and release a light reference */
+void
+diskfs_nput_light (struct node *np)
+{
+ spin_lock (&diskfs_node_refcnt_lock);
+ assert (np->light_references);
+ np->light_references--;
+ if (np->references + np->light_references == 0)
+ diskfs_drop_node (np);
+ else
+ {
+ spin_unlock (&diskfs_node_refcnt_lock);
+ mutex_unlock (&np->lock);
+ }
+}
diff --git a/libdiskfs/node-nref.c b/libdiskfs/node-nref.c
new file mode 100644
index 00000000..753de65f
--- /dev/null
+++ b/libdiskfs/node-nref.c
@@ -0,0 +1,40 @@
+/*
+ Copyright (C) 1999 Free Software Foundation, Inc.
+ Written by Thomas Bushnell, 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. */
+
+#include "priv.h"
+
+/* Add a hard reference to a node. If there were no hard
+ references previously, then the node cannot be locked
+ (because you must hold a hard reference to hold the lock). */
+void
+diskfs_nref (struct node *np)
+{
+ int new_hardref;
+ spin_lock (&diskfs_node_refcnt_lock);
+ np->references++;
+ new_hardref = (np->references == 1);
+ spin_unlock (&diskfs_node_refcnt_lock);
+ if (new_hardref)
+ {
+ mutex_lock (&np->lock);
+ diskfs_new_hardrefs (np);
+ mutex_unlock (&np->lock);
+ }
+}
diff --git a/libdiskfs/node-nrefl.c b/libdiskfs/node-nrefl.c
new file mode 100644
index 00000000..ce3b39dd
--- /dev/null
+++ b/libdiskfs/node-nrefl.c
@@ -0,0 +1,30 @@
+/*
+ Copyright (C) 1999 Free Software Foundation, Inc.
+ Written by Thomas Bushnell, 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. */
+
+#include "priv.h"
+
+/* Add a light reference to a node. */
+void
+diskfs_nref_light (struct node *np)
+{
+ spin_lock (&diskfs_node_refcnt_lock);
+ np->light_references++;
+ spin_unlock (&diskfs_node_refcnt_lock);
+}
diff --git a/libdiskfs/node-nrele.c b/libdiskfs/node-nrele.c
new file mode 100644
index 00000000..9dbc5d8c
--- /dev/null
+++ b/libdiskfs/node-nrele.c
@@ -0,0 +1,65 @@
+/*
+ Copyright (C) 1999 Free Software Foundation, Inc.
+ Written by Thomas Bushnell, 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. */
+
+#include "priv.h"
+
+/* Release a hard reference on NP. If NP is locked by anyone, then
+ this cannot be the last hard reference (because you must hold a
+ hard reference in order to hold the lock). If this is the last
+ hard reference and there are no links, then request soft references
+ to be dropped. */
+void
+diskfs_nrele (struct node *np)
+{
+ int tried_drop_softrefs = 0;
+
+ loop:
+ spin_lock (&diskfs_node_refcnt_lock);
+ assert (np->references);
+ np->references--;
+ if (np->references + np->light_references == 0)
+ {
+ mutex_lock (&np->lock);
+ diskfs_drop_node (np);
+ }
+ else if (np->references == 0)
+ {
+ mutex_lock (&np->lock);
+ spin_unlock (&diskfs_node_refcnt_lock);
+ diskfs_lost_hardrefs (np);
+ if (!np->dn_stat.st_nlink && !tried_drop_softrefs)
+ {
+ /* Same issue here as in nput; see that for explanation */
+ spin_lock (&diskfs_node_refcnt_lock);
+ np->references++;
+ spin_unlock (&diskfs_node_refcnt_lock);
+
+ diskfs_try_dropping_softrefs (np);
+ tried_drop_softrefs = 1;
+
+ /* Now we can drop the reference back... */
+ mutex_unlock (&np->lock);
+ goto loop;
+ }
+ mutex_unlock (&np->lock);
+ }
+ else
+ spin_unlock (&diskfs_node_refcnt_lock);
+}
diff --git a/libdiskfs/node-nrelel.c b/libdiskfs/node-nrelel.c
new file mode 100644
index 00000000..e61f6378
--- /dev/null
+++ b/libdiskfs/node-nrelel.c
@@ -0,0 +1,39 @@
+/*
+ Copyright (C) 1999 Free Software Foundation, Inc.
+ Written by Thomas Bushnell, 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. */
+
+#include "priv.h"
+
+/* Release a light reference on NP. If NP is locked by anyone, then
+ this cannot be the last reference (because you must hold a
+ hard reference in order to hold the lock). */
+void
+diskfs_nrele_light (struct node *np)
+{
+ spin_lock (&diskfs_node_refcnt_lock);
+ assert (np->light_references);
+ np->light_references--;
+ if (np->references + np->light_references == 0)
+ {
+ mutex_lock (&np->lock);
+ diskfs_drop_node (np);
+ }
+ else
+ spin_unlock (&diskfs_node_refcnt_lock);
+}
diff --git a/libdiskfs/node-rdwr.c b/libdiskfs/node-rdwr.c
new file mode 100644
index 00000000..ed94df44
--- /dev/null
+++ b/libdiskfs/node-rdwr.c
@@ -0,0 +1,77 @@
+/*
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+/* Reading and writing of files. this is called by other filesystem
+ routines and handles extension of files automatically. NP is the
+ node to be read or written, and must be locked. DATA will be
+ written or filled. OFF identifies where in thi fel the I/O is to
+ take place (-1 is not allowed). AMT is the size of DATA and tells
+ how much to copy. DIR is 1 for writing and 0 for reading. CRED is
+ the user doing the access (only used to validate attempted file
+ extension). For reads, *AMTREAD is filled with the amount actually
+ read. */
+error_t
+diskfs_node_rdwr (struct node *np,
+ char *data,
+ off_t off,
+ size_t amt,
+ int dir,
+ struct protid *cred,
+ size_t *amtread)
+{
+ error_t err;
+
+ iohelp_get_conch (&np->conch);
+
+ if (dir)
+ while (off + amt > np->allocsize)
+ {
+ err = diskfs_grow (np, off + amt, cred);
+ if (err)
+ return err;
+ if (np->filemod_reqs)
+ diskfs_notice_filechange (np, FILE_CHANGED_EXTEND, 0, off + amt);
+ }
+
+ if (off + amt > np->dn_stat.st_size)
+ {
+ if (dir)
+ {
+ np->dn_stat.st_size = off + amt;
+ np->dn_set_ctime = 1;
+ }
+ else
+ amt = np->dn_stat.st_size - off;
+ }
+
+ if (amtread)
+ *amtread = amt;
+ else
+ amtread = &amt;
+ err = _diskfs_rdwr_internal (np, data, off, amtread, dir, 0);
+ if (*amtread && diskfs_synchronous)
+ {
+ if (dir)
+ diskfs_file_update (np, 1);
+ else
+ diskfs_node_update (np, 1);
+ }
+
+ return err;
+}
diff --git a/libdiskfs/node-times.c b/libdiskfs/node-times.c
new file mode 100644
index 00000000..3931ffb0
--- /dev/null
+++ b/libdiskfs/node-times.c
@@ -0,0 +1,71 @@
+/*
+ Copyright (C) 1994,96,99 Free Software Foundation, Inc.
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include "priv.h"
+#include <maptime.h>
+
+/* If NP->dn_set_ctime is set, then modify NP->dn_stat.st_ctime
+ appropriately; do the analogous operation for atime and mtime as well. */
+void
+diskfs_set_node_times (struct node *np)
+{
+ struct timeval t;
+
+ if (!np->dn_set_mtime && !np->dn_set_atime && !np->dn_set_ctime)
+ return;
+
+ maptime_read (diskfs_mtime, &t);
+
+ if (np->dn_set_mtime)
+ {
+#ifdef notyet
+ np->dn_stat.st_mtimespec.ts_sec = t.tv_sec;
+ np->dn_stat.st_mtimespec.ts_nsec = t.tv_usec * 1000;
+#else
+ np->dn_stat.st_mtime = t.tv_sec;
+ np->dn_stat.st_mtime_usec = t.tv_usec;
+#endif
+ }
+ if (np->dn_set_atime)
+ {
+#ifdef notyet
+ np->dn_stat.st_atimespec.ts_sec = t.tv_sec;
+ np->dn_stat.st_atimespec.ts_nsec = t.tv_usec * 1000;
+#else
+ np->dn_stat.st_atime = t.tv_sec;
+ np->dn_stat.st_atime_usec = t.tv_usec;
+#endif
+ }
+ if (np->dn_set_ctime)
+ {
+#ifdef notyet
+ np->dn_stat.st_ctimespec.ts_sec = t.tv_sec;
+ np->dn_stat.st_ctimespec.ts_nsec = t.tv_usec * 1000;
+#else
+ np->dn_stat.st_ctime = t.tv_sec;
+ np->dn_stat.st_ctime_usec = t.tv_usec;
+#endif
+ }
+
+ if (np->dn_set_mtime || np->dn_set_atime || np->dn_set_ctime)
+ np->dn_stat_dirty = 1;
+ np->dn_set_mtime = np->dn_set_atime = np->dn_set_ctime = 0;
+}
diff --git a/libdiskfs/node-update.c b/libdiskfs/node-update.c
new file mode 100644
index 00000000..453dea59
--- /dev/null
+++ b/libdiskfs/node-update.c
@@ -0,0 +1,32 @@
+/*
+ Copyright (C) 1993, 1994 Free Software Foundation
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include "priv.h"
+
+/* Set on disk fields from NP->dn_stat; update ctime, atime, and mtime
+ if necessary. If WAIT is true, then return only after the physical
+ media has been completely updated. */
+void diskfs_node_update (struct node *np, int wait)
+{
+ diskfs_set_node_times (np);
+ if (np->dn_stat_dirty)
+ diskfs_write_disknode (np, wait);
+}
diff --git a/libdiskfs/notify-nosenders.c b/libdiskfs/notify-nosenders.c
new file mode 100644
index 00000000..7e6a504f
--- /dev/null
+++ b/libdiskfs/notify-nosenders.c
@@ -0,0 +1,39 @@
+/*
+ Copyright (C) 1994, 1995 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include <hurd/pager.h>
+
+/* Called by the kernel when a port has no more senders. We arrange
+ to have this sent to the port which is out of senders (NOTIFY). MSCOUNT
+ is the make-send count of the port when the notification was generated;
+ SEQNO is the sequence number of the message dequeue. */
+error_t
+diskfs_do_seqnos_mach_notify_no_senders (mach_port_t notify,
+ mach_port_seqno_t seqno __attribute__ ((unused)),
+ mach_port_mscount_t mscount)
+{
+ struct port_info *pt;
+
+ pt = ports_lookup_port (diskfs_port_bucket, notify, 0);
+
+ ports_no_senders (pt, mscount);
+
+ ports_port_deref (pt);
+
+ return 0;
+}
diff --git a/libdiskfs/notify-stubs.c b/libdiskfs/notify-stubs.c
new file mode 100644
index 00000000..a9177f81
--- /dev/null
+++ b/libdiskfs/notify-stubs.c
@@ -0,0 +1,71 @@
+/*
+ Copyright (C) 1994, 1995 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+error_t
+diskfs_do_seqnos_mach_notify_port_deleted (mach_port_t notify
+ __attribute__ ((unused)),
+ mach_port_seqno_t seqno
+ __attribute__ ((unused)),
+ mach_port_t name
+ __attribute__ ((unused)))
+{
+ return 0;
+}
+
+error_t
+diskfs_do_seqnos_mach_notify_msg_accepted (mach_port_t notify
+ __attribute__ ((unused)),
+ mach_port_seqno_t seqno
+ __attribute__ ((unused)),
+ mach_port_t name
+ __attribute__ ((unused)))
+{
+ return 0;
+}
+
+error_t
+diskfs_do_seqnos_mach_notify_port_destroyed (mach_port_t notify
+ __attribute__ ((unused)),
+ mach_port_seqno_t seqno
+ __attribute__ ((unused)),
+ mach_port_t name
+ __attribute__ ((unused)))
+{
+ return 0;
+}
+
+error_t
+diskfs_do_seqnos_mach_notify_send_once (mach_port_t notify
+ __attribute__ ((unused)),
+ mach_port_seqno_t seqno
+ __attribute__ ((unused)))
+{
+ return 0;
+}
+
+error_t
+diskfs_do_seqnos_mach_notify_dead_name (mach_port_t notify
+ __attribute__ ((unused)),
+ mach_port_seqno_t seqno
+ __attribute__ ((unused)),
+ mach_port_t name
+ __attribute__ ((unused)))
+{
+ return 0;
+}
diff --git a/libdiskfs/opts-append-std.c b/libdiskfs/opts-append-std.c
new file mode 100644
index 00000000..f6083365
--- /dev/null
+++ b/libdiskfs/opts-append-std.c
@@ -0,0 +1,61 @@
+/* Get standard diskfs run-time options
+
+ Copyright (C) 1995, 96,97,98,99 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.org>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <argz.h>
+
+#include "priv.h"
+
+error_t
+diskfs_append_std_options (char **argz, unsigned *argz_len)
+{
+ error_t err;
+ extern int diskfs_sync_interval;
+
+ if (diskfs_readonly)
+ err = argz_add (argz, argz_len, "--readonly");
+ else
+ err = argz_add (argz, argz_len, "--writable");
+
+ if (!err && _diskfs_nosuid)
+ err = argz_add (argz, argz_len, "--no-suid");
+ if (!err && _diskfs_noexec)
+ err = argz_add (argz, argz_len, "--no-exec");
+ if (!err && _diskfs_noatime)
+ err = argz_add (argz, argz_len, "--no-atime");
+
+ if (! err)
+ {
+ if (diskfs_synchronous)
+ err = argz_add (argz, argz_len, "--sync");
+ else if (diskfs_sync_interval == 0)
+ err = argz_add (argz, argz_len, "--no-sync");
+ else
+ {
+ char buf[80];
+ sprintf (buf, "--sync=%d", diskfs_sync_interval);
+ err = argz_add (argz, argz_len, buf);
+ }
+ }
+
+ return err;
+}
diff --git a/libdiskfs/opts-common.c b/libdiskfs/opts-common.c
new file mode 100644
index 00000000..05de5144
--- /dev/null
+++ b/libdiskfs/opts-common.c
@@ -0,0 +1,51 @@
+/* Options common to both startup and runtime
+
+ Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <argp.h>
+#include "priv.h"
+
+const struct argp_option diskfs_common_options[] =
+{
+ {"readonly", 'r', 0, 0, "Never write to disk or allow opens for writing"},
+ {"rdonly", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
+ {"ro", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
+ {"writable", 'w', 0, 0, "Use normal read/write behavior"},
+ {"rdwr", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
+ {"rw", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
+ {"sync", 's', "INTERVAL", OPTION_ARG_OPTIONAL,
+ "If INTERVAL is supplied, sync all data not actually written to disk"
+ " every INTERVAL seconds, otherwise operate in synchronous mode (the"
+ " default is to sync every 30 seconds)"},
+ {"no-sync", 'n', 0, 0, "Don't automatically sync data to disk"},
+ {"nosync", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
+ {"no-suid", 'S', 0, 0, "Don't permit set-uid or set-gid execution"},
+ {"nosuid", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
+ {"suid-ok", OPT_SUID_OK, 0, 0, "Enable set-uid execution"},
+ {"no-exec", 'E', 0, 0, "Don't permit any execution of files on this filesystem"},
+ {"noexec", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
+ {"exec-ok", OPT_EXEC_OK, 0, 0, "Enable execution of files"},
+ {"no-atime", 'A', 0, 0,
+ "Do not update file access times on disk for reads"},
+ {"noatime", 0, 0, OPTION_ALIAS | OPTION_HIDDEN},
+ {"atime", OPT_ATIME, 0, 0, "Do update file access times for reads normally"},
+ {0, 0}
+};
diff --git a/libdiskfs/opts-get.c b/libdiskfs/opts-get.c
new file mode 100644
index 00000000..91ec169b
--- /dev/null
+++ b/libdiskfs/opts-get.c
@@ -0,0 +1,29 @@
+/* Get run-time options
+
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+error_t
+diskfs_append_args (char **argz, unsigned *argz_len)
+{
+ return diskfs_append_std_options (argz, argz_len);
+}
diff --git a/libdiskfs/opts-runtime-parse.c b/libdiskfs/opts-runtime-parse.c
new file mode 100644
index 00000000..00ec2fc0
--- /dev/null
+++ b/libdiskfs/opts-runtime-parse.c
@@ -0,0 +1,30 @@
+/* A default diskfs_parse_runtime_options routine
+
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+error_t
+diskfs_parse_runtime_options (int argc, char **argv,
+ const struct argp *standard_argp)
+{
+ return argp_parse (standard_argp, argc, argv,
+ ARGP_NO_ERRS | ARGP_NO_HELP | ARGP_PARSE_ARGV0,
+ 0, 0);
+}
diff --git a/libdiskfs/opts-runtime.c b/libdiskfs/opts-runtime.c
new file mode 100644
index 00000000..d7264069
--- /dev/null
+++ b/libdiskfs/opts-runtime.c
@@ -0,0 +1,23 @@
+/* Default definition for diskfs_runtime_argp
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+struct argp *diskfs_runtime_argp = (struct argp *)&diskfs_std_runtime_argp;
diff --git a/libdiskfs/opts-set.c b/libdiskfs/opts-set.c
new file mode 100644
index 00000000..3cfe3f6b
--- /dev/null
+++ b/libdiskfs/opts-set.c
@@ -0,0 +1,34 @@
+/* Set run-time options
+
+ Copyright (C) 1996, 1998 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <hurd/fshelp.h>
+
+#include "priv.h"
+
+error_t
+diskfs_set_options (const char *argz, size_t argz_len)
+{
+ if (diskfs_runtime_argp)
+ return fshelp_set_options (diskfs_runtime_argp, 0, argz, argz_len, 0);
+ else
+ return EOPNOTSUPP;
+}
diff --git a/libdiskfs/opts-std-runtime.c b/libdiskfs/opts-std-runtime.c
new file mode 100644
index 00000000..c619835f
--- /dev/null
+++ b/libdiskfs/opts-std-runtime.c
@@ -0,0 +1,156 @@
+/* Parse standard run-time options
+
+ Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <argp.h>
+
+#include "priv.h"
+
+static const struct argp_option
+std_runtime_options[] =
+{
+ {"update", 'u', 0, 0, "Flush any meta-data cached in core"},
+ {"remount", 0, 0, OPTION_HIDDEN | OPTION_ALIAS}, /* deprecated */
+ {0, 0}
+};
+
+struct parse_hook
+{
+ int readonly, sync, sync_interval, remount, nosuid, noexec, noatime;
+};
+
+/* Implement the options in H, and free H. */
+static error_t
+set_opts (struct parse_hook *h)
+{
+ error_t err = 0;
+
+ /* Do things in this order: remount, change readonly, change-sync; always
+ do the remount while the disk is readonly, even if only temporarily. */
+
+ if (h->remount)
+ {
+ /* We can only remount while readonly. */
+ err = diskfs_set_readonly (1);
+ if (!err)
+ err = diskfs_remount ();
+ }
+
+ if (h->readonly != diskfs_readonly)
+ {
+ if (err)
+ diskfs_set_readonly (h->readonly); /* keep the old error. */
+ else
+ err = diskfs_set_readonly (h->readonly);
+ }
+
+ /* Change sync mode. */
+ if (h->sync)
+ {
+ diskfs_synchronous = 1;
+ diskfs_set_sync_interval (0); /* Don't waste time syncing. */
+ }
+ else
+ {
+ diskfs_synchronous = 0;
+ if (h->sync_interval >= 0)
+ diskfs_set_sync_interval (h->sync_interval);
+ }
+
+ if (h->nosuid != -1)
+ _diskfs_nosuid = h->nosuid;
+ if (h->noexec != -1)
+ _diskfs_noexec = h->noexec;
+ if (h->noatime != -1)
+ _diskfs_noatime = h->noatime;
+
+ free (h);
+
+ return err;
+}
+
+/* Parse diskfs standard runtime options. */
+static error_t
+parse_opt (int opt, char *arg, struct argp_state *state)
+{
+ struct parse_hook *h = state->hook;
+ switch (opt)
+ {
+ case 'r': h->readonly = 1; break;
+ case 'w': h->readonly = 0; break;
+ case 'u': h->remount = 1; break;
+ case 'S': h->nosuid = 1; break;
+ case 'E': h->noexec = 1; break;
+ case 'A': h->noatime = 1; break;
+ case OPT_SUID_OK: h->nosuid = 0; break;
+ case OPT_EXEC_OK: h->noexec = 0; break;
+ case OPT_ATIME: h->noatime = 0; break;
+ case 'n': h->sync_interval = 0; h->sync = 0; break;
+ case 's':
+ if (arg)
+ {
+ h->sync = 0;
+ h->sync_interval = atoi (arg);
+ }
+ else
+ h->sync = 1;
+ break;
+
+ case ARGP_KEY_INIT:
+ if (state->input)
+ state->hook = state->input; /* Share hook with parent. */
+ else
+ {
+ h = state->hook = malloc (sizeof (struct parse_hook));
+ if (! h)
+ return ENOMEM;
+ h->readonly = diskfs_readonly;
+ h->sync = diskfs_synchronous;
+ h->sync_interval = -1;
+ h->remount = 0;
+ h->nosuid = h->noexec = h->noatime = -1;
+
+ /* We know that we have one child, with which we share our hook. */
+ state->child_inputs[0] = h;
+ }
+ break;
+
+ case ARGP_KEY_ERROR:
+ if (! state->input)
+ free (h);
+ break;
+
+ case ARGP_KEY_SUCCESS:
+ if (! state->input)
+ return set_opts (h);
+ break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
+static const struct argp common_argp = { diskfs_common_options, parse_opt };
+
+static const struct argp_child children[] = { {&common_argp}, {0} };
+const struct argp diskfs_std_runtime_argp =
+{
+ std_runtime_options, parse_opt, 0, 0, children
+};
diff --git a/libdiskfs/opts-std-startup.c b/libdiskfs/opts-std-startup.c
new file mode 100644
index 00000000..9d0c1d90
--- /dev/null
+++ b/libdiskfs/opts-std-startup.c
@@ -0,0 +1,162 @@
+/* Standard startup-time command line parser
+
+ Copyright (C) 1995, 96, 97, 98, 99 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <argp.h>
+#include <hurd/store.h>
+#include "priv.h"
+
+char *diskfs_boot_flags;
+char **_diskfs_boot_command;
+
+extern char **diskfs_argv;
+
+mach_port_t diskfs_exec_server_task = MACH_PORT_NULL;
+
+/* ---------------------------------------------------------------- */
+
+#define OPT_HOST_PRIV_PORT (-1)
+#define OPT_DEVICE_MASTER_PORT (-2)
+#define OPT_EXEC_SERVER_TASK (-3)
+#define OPT_BOOTFLAGS (-4)
+#define OPT_BOOT_COMMAND (-5)
+
+static const struct argp_option
+startup_options[] =
+{
+ {"directory", 'C', "DIRECTORY", 0,
+ "Use DIRECTORY as the root of the filesystem"},
+ {"virtual-root", 0, 0, OPTION_ALIAS},
+ {"chroot", 0, 0, OPTION_ALIAS},
+
+ {0,0,0,0, "Boot options:", -2},
+ {"bootflags", OPT_BOOTFLAGS, "FLAGS", 0,
+ "Required for bootstrap filesystem, the FLAGS"
+ " argument is passed on to init"},
+ {"boot-command", OPT_BOOT_COMMAND, 0, 0,
+ "Remaining arguments form command line to run"
+ " at bootstrap instead of init"},
+ {"host-priv-port", OPT_HOST_PRIV_PORT, "PORT"},
+ {"device-master-port", OPT_DEVICE_MASTER_PORT, "PORT"},
+ {"exec-server-task", OPT_EXEC_SERVER_TASK, "PORT"},
+
+ {0}
+};
+
+static error_t
+parse_startup_opt (int opt, char *arg, struct argp_state *state)
+{
+ switch (opt)
+ {
+#define TOGGLE(var, on, off) \
+ case on: var = 1; break; \
+ case off: var = 0; break;
+ TOGGLE (diskfs_readonly, 'r', 'w');
+ TOGGLE (_diskfs_nosuid, 'S', OPT_SUID_OK);
+ TOGGLE (_diskfs_noexec, 'E', OPT_EXEC_OK);
+ TOGGLE (_diskfs_noatime, 'A', OPT_ATIME);
+#undef TOGGLE
+
+ case 's':
+ if (arg == NULL)
+ diskfs_synchronous = 1;
+ else
+ diskfs_default_sync_interval = atoi (arg);
+ break;
+ case 'n':
+ diskfs_synchronous = 0;
+ diskfs_default_sync_interval = 0;
+ break;
+
+ /* Boot options */
+ case OPT_DEVICE_MASTER_PORT:
+ _hurd_device_master = atoi (arg); break;
+ case OPT_HOST_PRIV_PORT:
+ _hurd_host_priv = atoi (arg); break;
+ case OPT_EXEC_SERVER_TASK:
+ diskfs_exec_server_task = atoi (arg); break;
+ case OPT_BOOTFLAGS:
+ diskfs_boot_flags = arg; break;
+ case 'C':
+ _diskfs_chroot_directory = arg; break;
+
+ case OPT_BOOT_COMMAND:
+ if (state->next == state->argc)
+ argp_error (state, "Command line must follow --boot-command option");
+ _diskfs_boot_command = state->argv + state->next;
+ state->next = state->argc; /* stop parsing */
+ {char **p; for (p = _diskfs_boot_command; *p; ++p) printf("BC %s\n",*p);}
+ break;
+
+ case ARGP_KEY_END:
+ diskfs_argv = state->argv; break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+
+ return 0;
+}
+
+/* Suck in the common arguments. */
+static const struct argp startup_common_argp =
+ { diskfs_common_options, parse_startup_opt };
+static const struct argp_child startup_argp_children[] =
+ { {&startup_common_argp}, {0} };
+
+/* This may be used with argp_parse to parse standard diskfs startup
+ options, possible chained onto the end of a user argp structure. */
+const struct argp
+diskfs_startup_argp =
+{
+ startup_options, parse_startup_opt, 0, 0, startup_argp_children
+};
+
+static error_t
+parse_store_startup_opt (int opt, char *arg, struct argp_state *state)
+{
+ switch (opt)
+ {
+ case ARGP_KEY_INIT:
+ /* Propagate our input to our STORE_ARGP child , which it will use to
+ return what it parses. */
+ state->child_inputs[1] = state->input; break;
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+
+ return 0;
+}
+
+static const struct argp_child store_argp_children[] =
+ { {&diskfs_startup_argp}, {&store_argp}, {0} };
+
+/* An argp structure for the standard diskfs command line arguments plus a
+ store specification. The address of a location in which to return the
+ resulting struct store_parsed structure should be passed as the input
+ argument to argp_parse; see the declaration for STORE_ARGP in
+ <hurd/store.h> for more information. */
+const struct argp
+diskfs_store_startup_argp =
+{
+ 0, parse_store_startup_opt, 0, 0, store_argp_children
+};
diff --git a/libdiskfs/opts-version.c b/libdiskfs/opts-version.c
new file mode 100644
index 00000000..c26334b2
--- /dev/null
+++ b/libdiskfs/opts-version.c
@@ -0,0 +1,47 @@
+/* Default hook for argp --version handling
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <argp.h>
+#include <version.h>
+
+#include "priv.h"
+
+static void
+_print_version (FILE *stream, struct argp_state *state)
+{
+ if (argp_program_version)
+ /* If this is non-zero, then the program's probably defined it, so let
+ that take precedence over the default. */
+ fputs (argp_program_version, stream);
+ else if (diskfs_extra_version && *diskfs_extra_version)
+ fprintf (stream, "%s (%s) %s\n",
+ diskfs_server_name, diskfs_extra_version, diskfs_server_version);
+ else
+ fprintf (stream, "%s %s\n", diskfs_server_name, diskfs_server_version);
+
+ /* And because diskfs is big and huge, put our information out too. */
+ fputs (STANDARD_HURD_VERSION (libdiskfs) "\n", stream);
+}
+
+void (*argp_program_version_hook) (FILE *stream, struct argp_state *state)
+ = _print_version;
diff --git a/libdiskfs/ourfs_notify.defs b/libdiskfs/ourfs_notify.defs
new file mode 100644
index 00000000..64127fe6
--- /dev/null
+++ b/libdiskfs/ourfs_notify.defs
@@ -0,0 +1,5 @@
+/* Private specialized presentation of fs_notify.defs for diskfs library. */
+
+#define routine simpleroutine
+#define USERPREFIX nowait_
+#include <hurd/fs_notify.defs>
diff --git a/libdiskfs/peropen-make.c b/libdiskfs/peropen-make.c
new file mode 100644
index 00000000..887658c7
--- /dev/null
+++ b/libdiskfs/peropen-make.c
@@ -0,0 +1,60 @@
+/*
+ Copyright (C) 1994, 1997, 1999 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include <sys/file.h>
+
+/* Create and return a new peropen structure on node NP with open
+ flags FLAGS. */
+struct peropen *
+diskfs_make_peropen (struct node *np, int flags, struct peropen *context)
+{
+ struct peropen *po = malloc (sizeof (struct peropen));
+
+ po->filepointer = 0;
+ po->lock_status = LOCK_UN;
+ po->refcnt = 0;
+ po->openstat = flags;
+ po->np = np;
+
+ if (context)
+ {
+ po->root_parent = context->root_parent;
+ if (po->root_parent != MACH_PORT_NULL)
+ mach_port_mod_refs (mach_task_self (), po->root_parent,
+ MACH_PORT_RIGHT_SEND, 1);
+
+ po->shadow_root = context->shadow_root;
+ if (po->shadow_root)
+ diskfs_nref (po->shadow_root);
+
+ po->shadow_root_parent = context->shadow_root_parent;
+ if (po->shadow_root_parent != MACH_PORT_NULL)
+ mach_port_mod_refs (mach_task_self (), po->shadow_root_parent,
+ MACH_PORT_RIGHT_SEND, 1);
+ }
+ else
+ {
+ po->root_parent = MACH_PORT_NULL;
+ po->shadow_root_parent = MACH_PORT_NULL;
+ po->shadow_root = _diskfs_chroot_directory ? diskfs_root_node : 0;
+ }
+
+ diskfs_nref (np);
+
+ return po;
+}
diff --git a/libdiskfs/peropen-rele.c b/libdiskfs/peropen-rele.c
new file mode 100644
index 00000000..6974e86a
--- /dev/null
+++ b/libdiskfs/peropen-rele.c
@@ -0,0 +1,49 @@
+/*
+ Copyright (C) 1994, 1996, 1997 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <sys/file.h>
+#include "priv.h"
+
+/* Decrement the reference count on a peropen structure. */
+void
+diskfs_release_peropen (struct peropen *po)
+{
+ mutex_lock (&po->np->lock);
+
+ if (--po->refcnt)
+ {
+ mutex_unlock (&po->np->lock);
+ return;
+ }
+
+ if (po->root_parent)
+ mach_port_deallocate (mach_task_self (), po->root_parent);
+
+ if (po->shadow_root && po->shadow_root != po->np)
+ diskfs_nrele (po->shadow_root);
+
+ if (po->shadow_root_parent)
+ mach_port_deallocate (mach_task_self (), po->shadow_root_parent);
+
+ if (po->lock_status != LOCK_UN)
+ fshelp_acquire_lock (&po->np->userlock, &po->lock_status,
+ &po->np->lock, LOCK_UN);
+
+ diskfs_nput (po->np);
+
+ free (po);
+}
diff --git a/libdiskfs/ports-clean.c b/libdiskfs/ports-clean.c
new file mode 100644
index 00000000..01a50dc5
--- /dev/null
+++ b/libdiskfs/ports-clean.c
@@ -0,0 +1,29 @@
+/*
+ Copyright (C) 1994 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include <hurd/pager.h>
+
+/* Indexed by port type (PT_*); called when the last reference goes
+ away on a port. */
+void (*ports_cleanroutines[])(void *)=
+{
+ [PT_PROTID] = diskfs_protid_rele,
+ [PT_PAGER] = pager_clean,
+ [PT_TRANSBOOT] = fshelp_transboot_clean,
+ [PT_CTL] = _diskfs_control_clean,
+};
diff --git a/libdiskfs/ports-consts.c b/libdiskfs/ports-consts.c
new file mode 100644
index 00000000..c2726c4c
--- /dev/null
+++ b/libdiskfs/ports-consts.c
@@ -0,0 +1,20 @@
+/*
+ Copyright (C) 1994 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* ports_wire_threads is set in init-init.c. */
+int ports_wire_cthreads = 1;
diff --git a/libdiskfs/ports-idle.c b/libdiskfs/ports-idle.c
new file mode 100644
index 00000000..9da021d5
--- /dev/null
+++ b/libdiskfs/ports-idle.c
@@ -0,0 +1,36 @@
+/*
+ Copyright (C) 1994 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+/* Called by the ports library when we have been idle for
+ ten minutes. */
+void
+ports_notice_idle (int nhard, int nsoft)
+{
+ spin_lock (&_diskfs_control_lock);
+ if (nhard > _diskfs_ncontrol_ports)
+ {
+ spin_unlock (&_diskfs_control_lock);
+ return;
+ }
+ spin_unlock (&_diskfs_control_lock);
+
+ /* XXX
+ Here should actually drop control ports and exit. */
+ return;
+}
diff --git a/libdiskfs/ports-noports.c b/libdiskfs/ports-noports.c
new file mode 100644
index 00000000..cddd8f00
--- /dev/null
+++ b/libdiskfs/ports-noports.c
@@ -0,0 +1,27 @@
+/*
+ Copyright (C) 1994 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "priv.h"
+
+/* Called by ports library when there are no ports outstanding. */
+void
+ports_no_live_ports ()
+{
+ diskfs_sync_everything (1);
+ exit (0);
+}
diff --git a/libdiskfs/ports-soft.c b/libdiskfs/ports-soft.c
new file mode 100644
index 00000000..11ff1379
--- /dev/null
+++ b/libdiskfs/ports-soft.c
@@ -0,0 +1,25 @@
+/*
+ Copyright (C) 1994 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+/* Called by ports library when there are only soft ports left. */
+void
+ports_no_hard_ports ()
+{
+ diskfs_shutdown_soft_ports ();
+}
diff --git a/libdiskfs/priv.h b/libdiskfs/priv.h
new file mode 100644
index 00000000..57d00e66
--- /dev/null
+++ b/libdiskfs/priv.h
@@ -0,0 +1,143 @@
+/* Private declarations for fileserver library
+ Copyright (C) 1994,95,96,97,98,99 Free Software Foundation, Inc.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef DISKFS_PRIV_H
+#define DISKFS_PRIV_H
+
+#include <mach.h>
+#include <hurd.h>
+#include <sys/mman.h>
+#include <hurd/ports.h>
+#include <hurd/fshelp.h>
+#include <hurd/iohelp.h>
+#include <hurd/port.h>
+#include <assert.h>
+
+#include "diskfs.h"
+
+/* These inhibit setuid or exec. */
+extern int _diskfs_nosuid, _diskfs_noexec;
+
+/* This relaxes the requirement to set `st_atime'. */
+extern int _diskfs_noatime;
+
+/* This is the -C argument value. */
+extern char *_diskfs_chroot_directory;
+
+/* If --boot-command is given, this points to the program and args. */
+extern char **_diskfs_boot_command;
+
+/* Port cell holding a cached port to the exec server. */
+extern struct hurd_port _diskfs_exec_portcell;
+
+volatile struct mapped_time_value *_diskfs_mtime;
+
+extern const struct argp_option diskfs_common_options[];
+/* Option keys for long-only options in diskfs_common_options. */
+#define OPT_SUID_OK 600 /* --suid-ok */
+#define OPT_EXEC_OK 601 /* --exec-ok */
+#define OPT_ATIME 602 /* --atime */
+
+
+/* Diskfs thinks the disk is dirty if this is set. */
+extern int _diskfs_diskdirty;
+
+/* Needed for MiG. */
+typedef struct protid *protid_t;
+
+/* Called by MiG to translate ports into struct protid *.
+ fsmutations.h arranges for this to happen for the io and
+ fs interfaces. */
+extern inline struct protid *
+begin_using_protid_port (file_t port)
+{
+ return ports_lookup_port (diskfs_port_bucket, port, diskfs_protid_class);
+}
+
+/* Called by MiG after server routines have been run; this
+ balances begin_using_protid_port, and is arranged for the io
+ and fs interfaces by fsmutations.h. */
+extern inline void
+end_using_protid_port (struct protid *cred)
+{
+ if (cred)
+ ports_port_deref (cred);
+}
+
+/* Actually read or write a file. The file size must already permit
+ the requested access. NP is the file to read/write. DATA is a buffer
+ to write from or fill on read. OFFSET is the absolute address (-1
+ not permitted here); AMT is the size of the read/write to perform;
+ DIR is set for writing and clear for reading. The inode must
+ be locked. If NOTIME is set, then don't update the access or
+ modify times on the file. */
+error_t _diskfs_rdwr_internal (struct node *np, char *data, off_t offset,
+ size_t *amt, int dir, int notime);
+
+/* Called when we have a real user environment (complete with proc
+ and auth ports). */
+void _diskfs_init_completed (void);
+
+/* Called in a bootstrap filesystem only, to get the privileged ports. */
+void _diskfs_boot_privports (void);
+
+/* Clean routine for control port. */
+void _diskfs_control_clean (void *);
+
+/* Number of outstanding PT_CTL ports. */
+extern int _diskfs_ncontrol_ports;
+
+/* Lock for _diskfs_ncontrol_ports. */
+extern spin_lock_t _diskfs_control_lock;
+
+/* Callback routines for active translator startup */
+extern fshelp_fetch_root_callback1_t _diskfs_translator_callback1;
+extern fshelp_fetch_root_callback2_t _diskfs_translator_callback2;
+
+/* This macro locks the node associated with PROTID, and then
+ evaluates the expression OPERATION; then it syncs the inode
+ (without waiting) and unlocks everything, and then returns
+ the value `err' (which can be set by OPERATION if desired). */
+#define CHANGE_NODE_FIELD(PROTID, OPERATION) \
+({ \
+ error_t err = 0; \
+ struct node *np; \
+ \
+ if (!(PROTID)) \
+ return EOPNOTSUPP; \
+ \
+ if (diskfs_check_readonly ()) \
+ return EROFS; \
+ \
+ np = (PROTID)->po->np; \
+ \
+ mutex_lock (&np->lock); \
+ (OPERATION); \
+ if (diskfs_synchronous) \
+ diskfs_node_update (np, 1); \
+ mutex_unlock (&np->lock); \
+ return err; \
+})
+
+/* Bits the user is permitted to set with io_*_openmodes */
+#define HONORED_STATE_MODES (O_APPEND|O_ASYNC|O_FSYNC|O_NONBLOCK|O_NOATIME)
+
+/* Bits that are turned off after open */
+#define OPENONLY_STATE_MODES \
+ (O_CREAT|O_EXCL|O_NOLINK|O_NOTRANS|O_NONBLOCK|O_EXLOCK|O_SHLOCK)
+
+#endif
diff --git a/libdiskfs/protid-make.c b/libdiskfs/protid-make.c
new file mode 100644
index 00000000..8f45cfd5
--- /dev/null
+++ b/libdiskfs/protid-make.c
@@ -0,0 +1,72 @@
+/*
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include <string.h>
+
+/* Build and return in CRED a protid which has no user identification, for
+ peropen PO. The node PO->np must be locked. */
+error_t
+diskfs_start_protid (struct peropen *po, struct protid **cred)
+{
+ error_t err =
+ ports_create_port_noinstall (diskfs_protid_class, diskfs_port_bucket,
+ sizeof (struct protid), cred);
+ if (! err)
+ {
+ po->refcnt++;
+ (*cred)->po = po;
+ (*cred)->shared_object = MACH_PORT_NULL;
+ (*cred)->mapped = 0;
+ }
+ return err;
+}
+
+/* Finish building protid CRED started with diskfs_start_protid;
+ the user to install is USER. */
+void
+diskfs_finish_protid (struct protid *cred, struct iouser *user)
+{
+ if (!user)
+ {
+ uid_t zero = 0;
+ /* Create one for root */
+ user = iohelp_create_iouser (make_idvec (), make_idvec ());
+ idvec_set_ids (user->uids, &zero, 1);
+ idvec_set_ids (user->gids, &zero, 1);
+ cred->user = user;
+ }
+ else
+ cred->user = iohelp_dup_iouser (user);
+
+ mach_port_move_member (mach_task_self (), cred->pi.port_right,
+ diskfs_port_bucket->portset);
+}
+
+/* Create and return a protid for an existing peropen PO in CRED for USER.
+ The node PO->np must be locked. */
+error_t
+diskfs_create_protid (struct peropen *po, struct iouser *user,
+ struct protid **cred)
+{
+ error_t err = diskfs_start_protid (po, cred);
+ if (! err)
+ diskfs_finish_protid (*cred, user);
+ return err;
+}
+
+
diff --git a/libdiskfs/protid-rele.c b/libdiskfs/protid-rele.c
new file mode 100644
index 00000000..f0646027
--- /dev/null
+++ b/libdiskfs/protid-rele.c
@@ -0,0 +1,37 @@
+/*
+ Copyright (C) 1994, 1999 Free Software Foundation
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+/* Called when a protid CRED has no more references. (Because references\
+ to protids are maintained by the port management library, this is
+ installed in the clean routines list.) The ports library will
+ free the structure for us. */
+void
+diskfs_protid_rele (void *arg)
+{
+ struct protid *cred = arg;
+
+ iohelp_free_iouser (cred->user);
+ if (cred->shared_object)
+ mach_port_deallocate (mach_task_self (), cred->shared_object);
+ if (cred->mapped)
+ munmap (cred->mapped, vm_page_size);
+ diskfs_release_peropen (cred->po);
+}
+
+
diff --git a/libdiskfs/rdwr-internal.c b/libdiskfs/rdwr-internal.c
new file mode 100644
index 00000000..18a4ae1e
--- /dev/null
+++ b/libdiskfs/rdwr-internal.c
@@ -0,0 +1,74 @@
+/*
+ Copyright (C) 1994,95,96,97,99,2000 Free Software Foundation, Inc.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include <string.h>
+#include <fcntl.h>
+#include <hurd/pager.h>
+
+/* Actually read or write a file. The file size must already permit
+ the requested access. NP is the file to read/write. DATA is a buffer
+ to write from or fill on read. OFFSET is the absolute address (-1
+ not permitted here); AMT is the size of the read/write to perform;
+ DIR is set for writing and clear for reading. The inode must
+ be locked. If NOTIME is set, then don't update the mtime or atime. */
+error_t
+_diskfs_rdwr_internal (struct node *np,
+ char *data,
+ off_t offset,
+ size_t *amt,
+ int dir,
+ int notime)
+{
+ memory_object_t memobj;
+ vm_prot_t prot = dir ? (VM_PROT_READ | VM_PROT_WRITE) : VM_PROT_READ;
+ error_t err = 0;
+
+ if (dir)
+ assert (!diskfs_readonly);
+
+ if (*amt == 0)
+ /* Zero-length writes do not update mtime or anything else, by POSIX. */
+ return 0;
+
+ if (!diskfs_check_readonly () && !notime)
+ {
+ if (dir)
+ np->dn_set_mtime = 1;
+ else if (! _diskfs_noatime)
+ np->dn_set_atime = 1;
+ }
+
+ memobj = diskfs_get_filemap (np, prot);
+
+ if (memobj == MACH_PORT_NULL)
+ return errno;
+
+ err = pager_memcpy (diskfs_get_filemap_pager_struct (np), memobj,
+ offset, data, amt, prot);
+
+ if (!diskfs_check_readonly () && !notime)
+ {
+ if (dir)
+ np->dn_set_mtime = 1;
+ else if (!_diskfs_noatime)
+ np->dn_set_atime = 1;
+ }
+
+ mach_port_deallocate (mach_task_self (), memobj);
+ return err;
+}
diff --git a/libdiskfs/readonly.c b/libdiskfs/readonly.c
new file mode 100644
index 00000000..02f583c8
--- /dev/null
+++ b/libdiskfs/readonly.c
@@ -0,0 +1,111 @@
+/* Change to/from read-only
+
+ Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <fcntl.h>
+#include <error.h>
+
+#include "priv.h"
+
+int _diskfs_diskdirty;
+int diskfs_readonly = 0;
+int diskfs_hard_readonly = 0;
+
+int
+diskfs_check_readonly ()
+{
+ error_t err;
+
+ if (diskfs_readonly)
+ return 1;
+ else
+ {
+ if (!_diskfs_diskdirty)
+ {
+ err = diskfs_set_hypermetadata (1, 0);
+ if (err)
+ {
+ error (0, 0,
+ "%s: MEDIA NOT WRITABLE; switching to READ-ONLY",
+ diskfs_disk_name ?: "-");
+ diskfs_hard_readonly = diskfs_readonly = 1;
+ return 1;
+ }
+ _diskfs_diskdirty = 1;
+ }
+ return 0;
+ }
+}
+
+/* Change an active filesystem between read-only and writable modes, setting
+ the global variable DISKFS_READONLY to reflect the current mode. If an
+ error is returned, nothing will have changed. The user should hold
+ DISKFS_FSYS_LOCK while calling this routine. */
+error_t
+diskfs_set_readonly (int readonly)
+{
+ error_t err = 0;
+
+ if (diskfs_hard_readonly)
+ return readonly ? 0 : EROFS;
+
+ if (readonly != diskfs_readonly)
+ {
+ err = ports_inhibit_class_rpcs (diskfs_protid_class);
+ if (! err)
+ {
+ if (readonly)
+ {
+ error_t peropen_writable (void *pi)
+ {
+ struct protid *const cred = pi;
+ return (cred->po->openstat & O_WRITE) ? EBUSY : 0;
+ }
+
+ /* Any writable open files? */
+ err = ports_class_iterate (diskfs_protid_class,
+ peropen_writable);
+
+ /* Any writable pagers? */
+ if (!err && (diskfs_max_user_pager_prot () & VM_PROT_WRITE))
+ err = EBUSY;
+
+ if (!err)
+ /* Sync */
+ {
+ diskfs_sync_everything (1);
+ diskfs_set_hypermetadata (1, 1);
+ _diskfs_diskdirty = 0;
+ }
+ }
+
+ if (!err)
+ {
+ diskfs_readonly = readonly;
+ diskfs_readonly_changed (readonly);
+ }
+
+ ports_resume_class_rpcs (diskfs_protid_class);
+ }
+ }
+
+ return err;
+}
diff --git a/libdiskfs/remount.c b/libdiskfs/remount.c
new file mode 100644
index 00000000..1ed622f2
--- /dev/null
+++ b/libdiskfs/remount.c
@@ -0,0 +1,47 @@
+/* Remount an active filesystem
+
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+/* Re-read all incore data structures from disk. This will only work if
+ DISKFS_READONLY is true. DISKFS_FSYS_LOCK should be held while calling
+ this routine. */
+error_t
+diskfs_remount ()
+{
+ error_t err;
+
+ if (! diskfs_check_readonly ())
+ return EBUSY;
+
+ err = ports_inhibit_class_rpcs (diskfs_protid_class);
+ if (err)
+ return err;
+
+ err = diskfs_reload_global_state ();
+ if (!err)
+ err = diskfs_node_iterate (diskfs_node_reload);
+
+ ports_resume_class_rpcs (diskfs_protid_class);
+
+ return err;
+}
diff --git a/libdiskfs/shutdown.c b/libdiskfs/shutdown.c
new file mode 100644
index 00000000..1a544f5b
--- /dev/null
+++ b/libdiskfs/shutdown.c
@@ -0,0 +1,104 @@
+/*
+ Copyright (C) 1993, 94, 95, 96, 98, 99 Free Software Foundation, Inc.
+
+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 the GNU Hurd; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Michael I. Bushnell. */
+
+#include "priv.h"
+#include <hurd/fsys.h>
+
+struct rwlock diskfs_fsys_lock = RWLOCK_INITIALIZER;
+
+/* Shutdown the filesystem; flags are as for fsys_goaway. */
+error_t
+diskfs_shutdown (int flags)
+{
+ int nports = -1;
+ int err;
+
+ error_t
+ helper (struct node *np)
+ {
+ error_t error;
+ mach_port_t control;
+
+ error = fshelp_fetch_control (&np->transbox, &control);
+ mutex_unlock (&np->lock);
+ if (!error && (control != MACH_PORT_NULL))
+ {
+ error = fsys_goaway (control, flags);
+ mach_port_deallocate (mach_task_self (), control);
+ }
+ else
+ error = 0;
+ mutex_lock (&np->lock);
+
+ if ((error == MIG_SERVER_DIED) || (error == MACH_SEND_INVALID_DEST))
+ error = 0;
+
+ return error;
+ }
+
+ if ((flags & FSYS_GOAWAY_UNLINK)
+ && S_ISDIR (diskfs_root_node->dn_stat.st_mode))
+ return EBUSY;
+
+ if (flags & FSYS_GOAWAY_RECURSE)
+ {
+ err = diskfs_node_iterate (helper);
+ if (err)
+ return err;
+ }
+
+ rwlock_writer_lock (&diskfs_fsys_lock);
+
+ /* Permit all the current RPC's to finish, and then
+ suspend new ones. */
+ err = ports_inhibit_class_rpcs (diskfs_protid_class);
+ if (err)
+ {
+ rwlock_writer_unlock (&diskfs_fsys_lock);
+ return err;
+ }
+
+ /* Write everything out and set "clean" state. Even if we don't in fact
+ shut down now, this has the nice effect that a disk that has not been
+ written for a long time will not need checking after a crash. */
+ diskfs_sync_everything (1);
+ diskfs_set_hypermetadata (1, 1);
+ _diskfs_diskdirty = 0;
+
+ /* First, see if there are outstanding user ports. */
+ nports = ports_count_class (diskfs_protid_class);
+ if (((flags & FSYS_GOAWAY_FORCE) == 0)
+ && (nports || diskfs_pager_users ()))
+ {
+ ports_enable_class (diskfs_protid_class);
+ ports_resume_class_rpcs (diskfs_protid_class);
+ rwlock_writer_unlock (&diskfs_fsys_lock);
+ return EBUSY;
+ }
+
+ if (!diskfs_readonly && (flags & FSYS_GOAWAY_NOSYNC) == 0)
+ {
+ diskfs_shutdown_pager ();
+ diskfs_set_hypermetadata (1, 1);
+ }
+
+ return 0;
+}
diff --git a/libdiskfs/sync-default.c b/libdiskfs/sync-default.c
new file mode 100644
index 00000000..4b8bdd7c
--- /dev/null
+++ b/libdiskfs/sync-default.c
@@ -0,0 +1,21 @@
+/* A variable holding the initial sync interval
+
+ Copyright (C) 1995, 1999 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+int diskfs_default_sync_interval = 5;
diff --git a/libdiskfs/sync-interval.c b/libdiskfs/sync-interval.c
new file mode 100644
index 00000000..8167fc4a
--- /dev/null
+++ b/libdiskfs/sync-interval.c
@@ -0,0 +1,131 @@
+/* Support for periodic syncing
+
+ Copyright (C) 1995, 96, 99 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <errno.h>
+#include <cthreads.h>
+#include <unistd.h>
+
+#include <hurd/fsys.h>
+
+#include "priv.h"
+
+/* A user-readable variable reflecting the last set sync interval. */
+int diskfs_sync_interval = 0;
+
+/* The thread that's doing the syncing. */
+static cthread_t periodic_sync_thread;
+
+/* This port represents the periodic sync service as if it were
+ an RPC. We can use ports_inhibit_port_rpcs on this port to guarantee
+ that the periodic_sync_thread is quiescent. */
+static struct port_info *pi;
+
+static void periodic_sync ();
+
+/* Establish a thread to sync the filesystem every INTERVAL seconds, or
+ never, if INTERVAL is zero. If an error occurs creating the thread, it is
+ returned, otherwise 0. Subsequent calls will create a new thread and
+ (eventually) get rid of the old one; the old thread won't do any more
+ syncs, regardless. */
+error_t
+diskfs_set_sync_interval (int interval)
+{
+ error_t err = 0;
+
+ if (! pi)
+ {
+ err = ports_create_port (diskfs_control_class, diskfs_port_bucket,
+ sizeof (struct port_info), &pi);
+ if (err)
+ return err;
+ }
+
+ err = ports_inhibit_port_rpcs (pi);
+ if (err)
+ return err;
+
+ /* Here we just set the new thread; any existing thread will notice when it
+ wakes up and go away silently. */
+ if (interval == 0)
+ periodic_sync_thread = 0;
+ else
+ {
+ periodic_sync_thread =
+ cthread_fork ((cthread_fn_t)periodic_sync, (any_t)interval);
+ if (periodic_sync_thread)
+ cthread_detach (periodic_sync_thread);
+ else
+ err = ENOMEM;
+ }
+
+ if (!err)
+ diskfs_sync_interval = interval;
+
+ ports_resume_port_rpcs (pi);
+
+ return err;
+}
+
+/* ---------------------------------------------------------------- */
+
+/* Sync the filesystem (pointed to by the variable CONTROL_PORT above) every
+ INTERVAL seconds, as long as it's in the thread pointed to by the global
+ variable PERIODIC_SYNC_THREAD. */
+static void
+periodic_sync (int interval)
+{
+ for (;;)
+ {
+ error_t err;
+ struct rpc_info link;
+
+ /* This acts as a lock against creation of a new sync thread
+ while we are in the process of syncing. */
+ err = ports_begin_rpc (pi, 0, &link);
+
+ if (periodic_sync_thread != cthread_self ())
+ {
+ /* We've been superseded as the sync thread. Just die silently. */
+ ports_end_rpc (pi, &link);
+ return;
+ }
+
+ if (! err)
+ {
+ if (! diskfs_readonly)
+ {
+ rwlock_reader_lock (&diskfs_fsys_lock);
+ /* Only sync if we need to, to avoid clearing the clean flag
+ when it's just been set. Any other thread doing a sync
+ will have held the lock while it did its work. */
+ if (_diskfs_diskdirty)
+ {
+ diskfs_sync_everything (0);
+ diskfs_set_hypermetadata (0, 0);
+ }
+ rwlock_reader_unlock (&diskfs_fsys_lock);
+ }
+ ports_end_rpc (pi, &link);
+ }
+
+ /* Wait until next time. */
+ sleep (interval);
+ }
+}
diff --git a/libdiskfs/trans-callback.c b/libdiskfs/trans-callback.c
new file mode 100644
index 00000000..43492d6e
--- /dev/null
+++ b/libdiskfs/trans-callback.c
@@ -0,0 +1,80 @@
+/*
+ Copyright (C) 1995, 96, 97, 98 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell.
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+#include <fcntl.h>
+
+/* Callback function needed for calls to fshelp_fetch_root. See
+ <hurd/fshelp.h> for the interface description. */
+static error_t
+_diskfs_translator_callback1_fn (void *cookie1, void *cookie2,
+ uid_t *uid, gid_t *gid,
+ char **argz, size_t *argz_len)
+{
+ error_t err;
+ struct node *np = cookie1;
+
+ if (! (np->dn_stat.st_mode & S_IPTRANS))
+ return ENOENT;
+
+ err = diskfs_get_translator (np, argz, (u_int *) argz_len);
+ if (err)
+ return err;
+
+ *uid = np->dn_stat.st_uid;
+ *gid = np->dn_stat.st_gid;
+
+ return 0;
+}
+
+/* Callback function needed for calls to fshelp_fetch_root. See
+ <hurd/fshelp.h> for the interface description. */
+static error_t
+_diskfs_translator_callback2_fn (void *cookie1, void *cookie2,
+ int flags,
+ mach_port_t *underlying,
+ mach_msg_type_name_t *underlying_type)
+{
+ struct node *np = cookie1;
+ struct protid *cred;
+ error_t err;
+ struct idvec *uids, *gids;
+
+ uids = make_idvec ();
+ gids = make_idvec ();
+ idvec_set_ids (uids, &np->dn_stat.st_uid, 1);
+ idvec_set_ids (gids, &np->dn_stat.st_gid, 1);
+
+ err =
+ diskfs_create_protid (diskfs_make_peropen (np, flags, cookie2),
+ iohelp_create_iouser (uids, gids), &cred);
+ if (! err)
+ {
+ *underlying = ports_get_right (cred);
+ *underlying_type = MACH_MSG_TYPE_MAKE_SEND;
+ ports_port_deref (cred);
+ }
+ return err;
+}
+
+fshelp_fetch_root_callback1_t _diskfs_translator_callback1 =
+ _diskfs_translator_callback1_fn;
+fshelp_fetch_root_callback2_t _diskfs_translator_callback2 =
+ _diskfs_translator_callback2_fn;
diff --git a/libdiskfs/validate-author.c b/libdiskfs/validate-author.c
new file mode 100644
index 00000000..d7dacabd
--- /dev/null
+++ b/libdiskfs/validate-author.c
@@ -0,0 +1,27 @@
+/* Default version of diskfs_validate_author_change
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/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. */
+
+#include "priv.h"
+
+error_t
+diskfs_validate_author_change (struct node *np, uid_t author)
+{
+ return 0;
+}
diff --git a/libdiskfs/validate-flags.c b/libdiskfs/validate-flags.c
new file mode 100644
index 00000000..bb54dadd
--- /dev/null
+++ b/libdiskfs/validate-flags.c
@@ -0,0 +1,27 @@
+/* Default version of diskfs_validate_flags_change
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/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. */
+
+#include "priv.h"
+
+error_t
+diskfs_validate_flags_change (struct node *np, int flags)
+{
+ return 0;
+}
diff --git a/libdiskfs/validate-group.c b/libdiskfs/validate-group.c
new file mode 100644
index 00000000..556c5aaa
--- /dev/null
+++ b/libdiskfs/validate-group.c
@@ -0,0 +1,27 @@
+/* Default version of diskfs_validate_group_change
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/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. */
+
+#include "priv.h"
+
+error_t
+diskfs_validate_group_change (struct node *np, gid_t group)
+{
+ return 0;
+}
diff --git a/libdiskfs/validate-mode.c b/libdiskfs/validate-mode.c
new file mode 100644
index 00000000..1cf150e6
--- /dev/null
+++ b/libdiskfs/validate-mode.c
@@ -0,0 +1,27 @@
+/* Default version of diskfs_validate_mode_change
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/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. */
+
+#include "priv.h"
+
+error_t
+diskfs_validate_mode_change (struct node *np, mode_t mode)
+{
+ return 0;
+}
diff --git a/libdiskfs/validate-owner.c b/libdiskfs/validate-owner.c
new file mode 100644
index 00000000..0cbe296c
--- /dev/null
+++ b/libdiskfs/validate-owner.c
@@ -0,0 +1,27 @@
+/* Default version of diskfs_validate_owner_change
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/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. */
+
+#include "priv.h"
+
+error_t
+diskfs_validate_owner_change (struct node *np, uid_t uid)
+{
+ return 0;
+}
diff --git a/libdiskfs/validate-rdev.c b/libdiskfs/validate-rdev.c
new file mode 100644
index 00000000..2d766346
--- /dev/null
+++ b/libdiskfs/validate-rdev.c
@@ -0,0 +1,27 @@
+/* Default version of diskfs_validate_rdev_change
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/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. */
+
+#include "priv.h"
+
+error_t
+diskfs_validate_rdev_change (struct node *np, dev_t rdev)
+{
+ return 0;
+}