diff options
Diffstat (limited to 'libdiskfs')
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; +} |