diff options
258 files changed, 27 insertions, 69605 deletions
diff --git a/README.CVS b/README.CVS deleted file mode 100644 index 92a2392d..00000000 --- a/README.CVS +++ /dev/null @@ -1,29 +0,0 @@ --*- Text -*- -GNU Hurd CVS version. - - -This is the Hurd. Welcome. - -For installation instructions, you might try your luck with the files -README, INSTALL, and INSTALL-cross. However, they have not been -updated for a long time. - -For now, this file documents the version requirements for the CVS -version of the Hurd. Other combinations might work, but the stated -minimum requirements are best tested by the developers. - -GNU MiG at least 1.3 -GNU Mach at least 1.3 -GNU C library CVS from 2004-03-09 or later -GNU C compiler at least 3.3.2 - -Optionally, a Sun RPC implementation is needed to build the NFS -translator and daemon: - -GNU C library at most 2.13 -TI-RPC (currently fails to build on GNU, see - <http://lists.debian.org/debian-hurd/2010/12/msg00007.html>.) - -Obviously, you also need somewhat recent versions of binutils, make, -bash and some other tools. No hard requirements are currently known -for these, though. diff --git a/boot-proxy-exc/ChangeLog b/boot-proxy-exc/ChangeLog deleted file mode 100644 index 39dc9f7a..00000000 --- a/boot-proxy-exc/ChangeLog +++ /dev/null @@ -1,998 +0,0 @@ -2009-04-19 Zheng Da <zhengda1936@gmail.com> - - * boot.c (init_kernel_task): Create a pseudo kernel task. - (main): Create the port bucket, initialize the kernel task and fork a - thread after the arguments of boot are parsed. - -2009-04-19 Zheng Da <zhengda1936@gmail.com> - - * boot.c (thread_portclass): Removed variable. - (is_user): Added variable. - (options): Add option 'u'. - (parse_opt): Handle option 'u'. - (logfile): Added variabled. - (main): Handle the cases differently when the user is root. - (do_bootstrap_privileged_ports): Likewise. - (bootstrap_compat): Likewise. - (do_mach_notify_no_senders): Likewise. - (ds_device_open): If the user is root, open the kernel device - directly. - - * userland-boot.c (boot_script_task_create): Create the pseudo task - port if it's the normal user. - (boot_script_free_task): Deallocate the task port if it's root. - -2009-04-05 Zheng Da <zhengda1936@gmail.com> - - * Makefile (SRCS): Add list.c, mach_proxy.c. - (COMMON-OBJS): Add ourmach_hostServer.o, ourmachServer.o, - ourmach_portServer.o, excServer.o. - (OBJS): Add mach_host_impl.o, mach_impl.o, mach_port_impl.o, - exc_impl.o, list.o, mach_proxy.o. - (LCLHDRS): Add util.h. - (HURDLIBS): Add ports. - - * boot.c: Include hurd/ports.h, util.h, mach_proxy.h. - (port_bucket): New variable. - (task_portclass): Likewise. - (thread_portclass): Likewise. - (privileged_host_port): Removed variable. - (master_device_port): Likewise. - (pseudo_privileged_host_port): New variable. - (request_server): Call mach_host_server() and mach_server(). - (mach_proxy_demuxer): New function. - (mach_proxy_thread): Likewise. - (options): Add option -p. - (pager_file): New variable. - (parse_opt): Handle option -p. - (init_kernel_task): New function. - (main): Create port bucket, port class, new thread; - get default memory manager; get the pseudo privileged host port; - set 'host-port' with the pseudo privileged host port. - (do_bootstrap_privileged_ports): Return the pseudo privileged host port. - (bootstrap_compat): Use the pseudo privileged host port. - (ds_device_open): Return D_NO_SUCH_DEVICE if the device isn't specified. - (do_mach_notify_no_senders): Call ports_do_mach_notify_no_senders(); - check the pseudo privileged host port. - - * boot_script.c (add_arg): Convert 'cmd->args' to 'void *' pointer first. - (sym_enter): Convert 'symtab' to 'void *' pointer first. - (boot_script_parse_line): Convert 'cmds' to to 'void *' pointer first; - Convert 'cmd->exec_funcs' to to 'void *' pointer first. - - * exc_impl.c: New file. Implement the server-side RPCs of exc. - - * list.c: New file. Implement a double linked list. - - * list.h: New file. Define a double linked list. - - * mach_host_impl.c: New file. Implement the server-side RPCs of mach_host. - - * mach_impl.c: New file. Implement the server-side RPCs of mach. - - * mach_port_impl.c: New file. Implement the server-side RPCs of mach_port. - - * mach_proxy.c: New file. - - * mach_proxy.h: New file. - - * ourmach.defs: New file. A modified mach/mach.defs. - - * ourmach_host.defs: New file. A modified mach/mach_host.defs. - - * ourmach_port.defs: New file. A modified mach/mach_port.defs. - - * userland-boot.c: Include mach_proxy.h and util.h. - (boot_script_task_create): Create a pseudo task port. - (boot_script_free_task): Don't deallocate the task port. - - * util.h: New file. - -2008-09-21 Zheng Da <zhengda1936@gmail.com> - - * boot.c (options): Change the long option and the description of - its argument. - -2008-08-28 Zheng Da <zhengda1936@gmail.com> - - * boot.c: Add '-m' option. - (dev_map): New structure. - (dev_map_head): New variable. - (add_dev_map): New function. - (lookup_dev): New function. - (parse_opt): Handle the '-m' option. - (ds_device_open): Open the device from the device file. - -2006-03-15 Thomas Schwinge <tschwinge@gnu.org> - - * boot.c (boot_script_exec_cmd): Fix invalid lvalues. - -2003-01-04 Roland McGrath <roland@frob.com> - - * boot_script.c (boot_script_parse_line): Copy the file name into - malloc'd storage. - (add_arg): New arg TEXTLEN. Store malloc'd copy of TEXT. - (boot_script_parse_line): Update callers. - -2002-06-13 Roland McGrath <roland@frob.com> - - * boot.c (ds_device_write): int -> size_t in store_write call. - (ds_device_write_inband): Likewise. - -2002-06-08 Roland McGrath <roland@frob.com> - - * boot.c (S_io_identity): Use ino_t for FILENO. - -2002-05-31 Roland McGrath <roland@frob.com> - - * boot.c: Don't include "exec_S.h". - - * boot.c (boot_script_exec_cmd): Fix typos: - {I386,ALPHA}_THREAD_STATE -> {i386,ALPHA}_THREAD_STATE_COUNT - -2002-05-28 Roland McGrath <roland@frob.com> - - * boot_script.c (boot_script_set_variable): Values int -> integer_t. - (boot_script_define_function): Likewise. - (boot_script_parse_line): Likewise. - (struct sym, struct arg): Likewise. - (boot_script_exec): Likewise. - (builtin_symbols): Likewise. - * boot.c (main): Likewise. - * boot_script.h: Update decls. - - * boot.c (boot_script_exec_cmd) - [I386_THREAD_STATE]: Conditionalize i386 thread setup code on this. - [ALPHA_THREAD_STATE]: Add Alpha thread setup code. - (set_mach_stack_args): Obsolete function removed. - - * boot.c (load_image): u_int -> vm_address_t - (ds_xxx_device_get_status, ds_xxx_device_set_status): u_int -> size_t - (S_io_restrict_auth, S_io_reauthenticate): Likewise. - (ds_device_write, ds_device_read_inband): Likewise. - (ds_device_get_status): Likewise. - (ds_device_set_status): Likewise. - (boot_script_exec_cmd): Likewise. - (ds_device_read, ds_device_write_inband): Likewise. - (ds_xxx_device_set_filter): Likewise. - (ds_device_set_filter): Likewise. - -2002-05-13 Marcus Brinkmann <marcus@gnu.org> - - * boot.c: Include <version.h> - (argp_program_version): New variable. - -2002-03-23 James A. Morrison <ja2morri@uwaterloo.ca> - - * boot.c (main): Use error, not perror and exit. - -2001-10-07 Neal H Walfield <neal@cs.uml.edu> - - * boot.c (main): Set the boot script variables based on - the KERNEL_COMMAND_LINE value. - -2001-08-23 Roland McGrath <roland@frob.com> - - * boot.c (kernel_command_line): New variable. - (options): Add --kernel-command-line/-K. - (parse_opt): Parse it, set kernel_command_line. - (main): If unset, default it to "argv[0] bootstrap_args bootdevice". - Set ${kernel-command-line} boot script variable to kernel_command_line. - -2001-08-17 Neal H Walfield <neal@cs.uml.edu> - - * userland-boot.c (boot_script_task_create): Suspend the newly - created task as the protocol requires. - (boot_script_insert_right): Fix the error message. - -2001-08-17 Roland McGrath <roland@frob.com> - - * userland-boot.c (boot_script_insert_right): Take new result - parameter for send right name in target task. - (boot_script_insert_task_port): New function. - - * boot_script.h: Update those two decls. - (VAL_TASK): New macro. - * boot_script.c (VAL_SYM, VAL_FUNC): Increase these constants. - (builtin_symbols): Use VAL_TASK for "task-create". - (boot_script_exec): Update caller of boot_script_insert_right. - Treat VAL_TASK like VAL_PORT, but call boot_script_insert_task_port. - - * boot_script.h: size_t -> unsigned int - * boot_script.c: Don't #include <string.h>. - -2001-08-16 Roland McGrath <roland@frob.com> - - * userland-boot.c (boot_script_insert_right): New function. - * boot_script.h: Declare it. - * boot_script.c (boot_script_exec): Use that instead of - mach_port_insert_right. - - * boot_script.h: Protect from multiple inclusion. - (safe_gets): Remove decl. - - * boot_script.h (boot_script_exec_cmd): Change TASK arg type to task_t. - * userland-boot.c: Likewise. - - * boot_script.h (struct cmd): Change `task' member type to `task_t'. - (boot_script_task_create, boot_script_task_resume, - boot_script_prompt_task_resume, boot_script_free_task): Declare new - functions that callers must define. - * userland-boot.c: Define those. - * boot_script.c (create_task, resume_task, prompt_resume_task): Use - those instead of direct Mach calls. - (free_cmd): Likewise. - (read_file): Function removed. - (builtin_symbols): Remove the "read-file" element. - - * boot_script.h (boot_script_malloc, boot_script_free): Declare new - functions that callers must define. - * boot_script.c: All uses of malloc/free changed to use those instead. - * userland-boot.c: New file. Defines them using malloc/free. - * Makefile (SRCS, OBJS): Add it. - * boot.c (boot_script_malloc, boot_script_free): Old cruft functions - removed. - - * boot_script.c (boot_script_parse_line): Take new first argument HOOK. - Store it in CMD->hook. - (main): Update caller. - (boot_script_exec): Pass CMD->hook as 1st arg to boot_script_exec_cmd. - (boot_script_exec_cmd): Take new first argument HOOK. - * boot.c (boot_script_exec_cmd): Likewise. - * boot_script.h (struct cmd): New member `void *hook'. - Update decls for HOOK arguments added. - -2001-02-25 Roland McGrath <roland@frob.com> - - * Makefile (ourdevice.defs): Loosen up regexp since some whitespace in - the file changed. - -2000-12-21 Marcus Brinkmann <marcus@gnu.org> - - * boot.c (main): If malloc or realloc fails, print diagnostic - message and exit. - (queue_read): Change return type from void to kern_return_t. - If malloc fails, return D_NO_MEMORY, otherwise D_SUCCESS (to simplify - code flow, malloc before acquiring the queuelock). - (ds_device_read): New variable err (local to the block in which it is - used). If queue_read fails, pass through error. - (ds_device_read_inband): Likewise. - (S_io_read): Likewise. - Reported by Igor Khavkine <i_khavki@alcor.concordia.ca>. - -2000-03-17 Roland McGrath <roland@baalperazim.frob.com> - - * boot.c (S_io_reauthenticate): Check mach_port_insert_right result - with assert_perror. - -2000-03-17 Thomas Bushnell, BSG <tb@mit.edu> - - * boot.c (S_io_reauthenticate): Don't use MACH_MSG_TYPE_MAKE_SEND - in Hurd RPC. - -2000-02-28 Roland McGrath <roland@baalperazim.frob.com> - - * boot.c (ds_device_get_status): Accept *STATUSLEN greater than needed. - -1999-09-13 Roland McGrath <roland@baalperazim.frob.com> - - * boot.c: Reverted changes related to io_map_segment. - -1999-09-07 Thomas Bushnell, BSG <tb@mit.edu> - - * boot.c (S_io_map_segment): New function. - -1999-07-11 Roland McGrath <roland@baalperazim.frob.com> - - * boot.c (ds_device_read, S_io_read): Fix sloppy bugs in last change. - -1999-07-06 Thomas Bushnell, BSG <tb@mit.edu> - - * boot.c (load_image): Use mmap instead of vm_allocate, when - allocating in mach_task_self (). - (boot_script_exec_cmd): Likewise. - (set_mach_stack_args): Likewise. - (read_reply): Likewise. - (S_io_read): Likewise. - -1999-07-10 Roland McGrath <roland@baalperazim.frob.com> - - * boot.c: Add #include <sys/mman.h> for munmap decl. - -Mon Jul 5 20:04:06 1999 Thomas Bushnell, BSG <tb@mit.edu> - - * boot.c (load_image): Fix typo in cast. Reported by Yamashita - TAKAO <jargon@lares.dti.ne.jp>. - -1999-07-03 Thomas Bushnell, BSG <tb@mit.edu> - - * boot.c (load_image): Use munmap instead of vm_deallocate when - it's from our own task. - (boot_script_read_file): Likewise. - (boot_script_exec_cmd): Likewise. - (set_mach_stack_args): Likewise. - (ds_device_read_inband): Likewise. - -1999-03-20 Roland McGrath <roland@baalperazim.frob.com> - - * boot.c (S_term_get_peername): New function. - -1999-03-14 Roland McGrath <roland@baalperazim.frob.com> - - * boot.c: Fix typo in last change. - -1999-03-10 Roland McGrath <roland@baalperazim.frob.com> - - * boot.c (main): Only use real device name if root_store is for an - enforced single run starting at the beginning of the device. - -1999-03-09 Roland McGrath <roland@baalperazim.frob.com> - - * boot.c (main): Add newline to error msg. - Patch by Marcus Brinkmann <Marcus.Brinkmann@ruhr-uni-bochum.de>. - -1999-02-16 Roland McGrath <roland@baalperazim.frob.com> - - * boot.c (S_io_revoke): Add reply, replyPoly args. - -Tue Feb 16 05:06:12 1999 Thomas Bushnell, BSG <tb@mit.edu> - - * boot.c (S_io_revoke): New (unsupported) routine. - -1998-12-26 Roland McGrath <roland@baalperazim.frob.com> - - * boot.c (isig): New variable. - (init_termstate): If it's set, set ISIG flag in c_lflag. - (options): New option -I/--isig. - (parse_opt): Make -I set `isig'. - (boot_script_exec_cmd): Print out args as well as file name. - -1998-09-04 Roland McGrath <roland@baalperazim.frob.com> - - * boot_script.c: Include <string.h> instead of declaring memset here. - Include <stdlib.h> instead of declaring malloc, free here. - -1997-07-08 Miles Bader <miles@gnu.ai.mit.edu> - - * boot_script.c (prompt_resume_task): Pass more than a single - character buffer to safe_gets. - -Mon Jul 7 16:25:49 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> - - * boot.c: Include <fcntl.h> instead of <fcntlbits.h>. Suggested - by Marcus G. Daniels (marcus@cathcart.sysc.pdx.edu). - -1997-06-20 Miles Bader <miles@gnu.ai.mit.edu> - - * boot.c (bootscript): Made global. - (parse_opt): New function. - (options, doc, args_doc): New variables. - (bootscript_args): Now an array. - (ds_device_open, ds_device_close, ds_device_write, - ds_device_write_inband, ds_device_read, ds_device_read_inband, - ds_device_get_status, ds_device_set_status, ds_device_map, - ds_xxx_device_set_filter, ds_xxx_device_get_status, - ds_xxx_device_set_status, ds_device_set_filter): - Handle "pseudo-root" device. - (pseudo_root, root_store): New variables. - (main): Use argp to parse args, and implement the pseudo-root device. - Include <argp.h> & <hurd/store.h> - * Makefile (HURDLIBS): Include libstore & libshouldbeinlibc. - -Thu Apr 10 11:53:57 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> - - * boot.c: Don't include varargs.h. - (set_mach_stack_args): Use stdarg instead of vararg. - -Mon Mar 17 13:12:45 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> - - * boot_script.c (boot_script_parse_line): Don't print gratuitous - output noise. - -Thu Sep 12 16:28:47 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> - - * Makefile (HURDLIBS): New variable. - (boot): Delete special depedencies. - -Tue Aug 13 16:57:22 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * Makefile (device.defs): Rule removed. - (ourdevice.defs): Fix rule to work with Makeconf-generated device.defs. - -Tue Aug 13 15:09:45 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> - - * Makefile (ourdevice.defs): Depend on local device.defs. - (device.defs): New rule. - -Mon Aug 12 11:11:08 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> - - * Makefile (ourdevice.defs): Find device.defs under - install_includedir now. - - * Makefile (all): No longer build uxboot by default. - -Thu Aug 1 14:38:38 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> - - * boot_script.h (safe_gets): Declare second parm as type `int'. - * boot.c (safe_gets): Likewise. - -Sun Jul 7 21:10:08 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * boot.c (S_io_reauthenticate): Don't use unsafe MOVE_SEND in - auth_server_authenticate. - -Fri May 10 16:11:49 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * boot.c (S_io_identity): Typo. - -Fri May 10 09:18:53 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * boot.c (S_io_identity): New function. - -Thu May 9 18:57:34 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * boot.c (S_io_select): No longer has TAG parm. - - * boot.c (S_io_reauthenticate): Use new interface. - -Sun Apr 28 22:50:38 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * boot.c (main): Use select instead of SIGIO. - -Mon Apr 15 12:57:29 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * Makefile (uxboot): Permit errors because people might not have - the a.out-mach3 target installed, and that's OK for many users. - - * Makefile (uxboot.0): Find frank1.ld in #(srcdir). - - * boot_script.h (safe_gets): Add decl. - * boot_script.c: Include <stdio.h>. - -Wed Apr 3 18:54:22 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * ux.c (printf): Add %d. - -Wed Mar 27 11:30:29 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * boot.c [notanymore] (S_tioctl_tiocgeta, S_tioctl_tiocseta, - S_tioctl_tiocsetaf, term_modes, term_ccs, term_speeds): - Functions & variables removed. - * Makefile (COMMON-OBJS): Remove tcattr.o. - (SRCS): Remove tcattr.c. - -Thu Mar 14 10:10:20 1996 Roland McGrath <roland@charlie-brown.gnu.ai.mit.edu> - - * Makefile (boot): Depend on libthreads.so, nothing wrong with shared - libs. - (uxboot.0, uxboot.1): Use automatic vars in cmds instead of gratuitous - redundancy. - (LDFLAGS-uxboot.0): Remove useless indirection through variable. - -Wed Feb 14 16:50:05 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * boot.c [!UX] - (orig_tty_state): New variable. - (init_termstate, restore_termstate): New hurd versions of these funcs. - * ux.c (init_termstate, restore_termstate, term_sgb, localbits): - Moved here from boot.c - -Tue Feb 13 18:49:26 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * boot.c (load_image, boot_script_read_file, main): Use O_RDONLY, - not 0 (kind of ironic, this...). - (load_image): Give the filename with the error message (and a newline). - - * ux.h (O_RDONLY, O_WRONLY, O_RDWR): New macros. - - * ux.c, ux.h: New files. - * boot.c: Move all the ux-specific grot into ux.c & ux.h. - If UX is defined, include "ux.h", else define hurdish stuff. - (main): Use get_privileged_ports instead of task_by_pid. - (load_image, boot_script_read_file, main, do_mach_notify_no_senders, - do_mach_notify_dead_name): Use host_exit instead of uxexit. - (boot_script_read_file): Use host_stat instead of uxstat. - (init_termstate, S_tioctl_tiocseta): Use sg_flags fld in struct sgttyb. - - * Makefile (all): Depend on `boot' and `uxboot'. - (COMMON-OBJS, UX-OBJS): New macros. - (OBJS): Inherit most names from $(COMMON-OBJS). - (LCLHDRS): Add ux.h. - (LDFLAGS): Use target-specific value. - (uxboot.0-LDFLAGS): New macro (with contents from old LDFLAGS). - (uxboot.o, uxboot.0): New targets. - (uxboot): Target renamed from boot.a. - -Sun Dec 10 18:05:14 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * boot.c (read_reply): Don't call clear_should_read(), just do - things ourselves. - (should_read_lock): Variable deleted. - (service_sigio): Function deleted. - (main): Use read_reply to service SIGIO again, not service_sigio. - - * boot.c (service_sigio): New function, replacing set_should_read. - Calls read_reply() itself too. - (unlock_readlock): New function. - (ds_device_read, ds_device_read_inband, S_io_read): Call - unlock_readlock instead of directly unlocking READLOCK. - (request_server, main): Don't call read_reply() anymore. - - * boot.c (should_read): New variable. - (main): SIGIO uses set_should_read instead of read_reply. - Call read_reply() after sigpause() returns. - (read_reply): Call clear_should_read(), and don't do anything if - SHOULD_READ wasn't set. - (set_should_read): New function. - (clear_should_read): New function. - (request_server): Call read_reply() before returning. - -Sat Dec 9 19:01:10 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * boot.c (S_io_read, ds_device_read_inband, ds_device_read): Don't - block SIGIO. - (main): Don't trap SIGMSG & SIGEMSG. - -Mon Dec 4 23:54:18 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * boot.c (main): Request no-senders notification on - pseudo_master_device_port. - Deallocate our send right to it when we no longer need it. - (do_mach_notify_no_senders): Exit only when both pseudo_console and - pseudo_master_device_port have no senders. - (ds_device_read_inband): Unlock readlock properly. - -Thu Nov 30 15:58:47 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * boot.c (readlock): New variable. - (read_reply): Check FIONREAD before dequeueing QR so that we don't - abandon requests. Lock READLOCK around FIONREAD/read pair. - (ds_device_read): Lock READLOCK around FIONREAD/read pair. - (ds_device_read_inband): Likewise. - (S_io_read): Likewise. - -Nov 22 16:25:01 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * boot.c (request_server): Don't call exec_server. - (S_exec_*): Functions removed. - (boot_script_task_port): Variable removed. - (boot_script_task_*, boot_script_port_*): Functions removed. - -Tue Nov 14 12:07:24 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * Makefile (OBJS): Remove execServer.o. - -Thu Sep 28 14:47:46 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * boot_script.c (read_file): Pass CMD->path for file name. - (CHECK_CMDLINE_LEN): Update ARGV pointers after reallocating the line - buffer. - -Wed Sep 27 14:01:03 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * boot.c (struct uxstat): New type. - (uxfstat): Renamed from fstat; use struct uxstat * for arg. - (boot_script_read_file): Use those. - Return the memory object port, not zero. - - * boot.c (fstat): New syscall function. - - * boot_script.c (read_file): New function. - (builtin_symbols): Add $(read-file) builtin. - * boot_script.h (boot_script_read_file): Declare it. - * boot.c (close): New syscall function. - (defpager): New variable. - (main): Set it up. - (boot_script_read_file): New function. - (useropen_dir): New variable. - (useropen): New function. - (load_image): Call it instead of open. - (main): Grok -D arg to set useropen_dir. - -Sat Sep 23 00:53:51 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * syscall.S: Restore entry SP before return. - - * boot.c (main): Use static const for constant strings. - On boot script error, write script line with error msg. - - * boot_script.c (boot_script_parse_line): Ignore line beginning - with #. - - * boot.c (S_io_pathconf): New function. - - * Makefile (LDFLAGS): Add -static. - -Fri Sep 22 14:14:23 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * mach-crt0.c (__data_start): New variable. - -Tue Aug 29 10:41:29 1995 Michael I. Bushnell, p/BSG <mib@duality.gnu.ai.mit.edu> - - * boot.c (mig_dealloc_reply_port): Remove __ from call to - mach_port_mod_refs. - (main): Look for -d in bootstrap_args, not (nonexistent) - boot_args. Remove `const' keyword from decl of MSG. - - * boot.c (sigblock, sigsetmask): New functions. - (sigmask): New macro. - (ds_device_read): Block SIGIO around critical section. - (ds_device_read_inband): Likewise. - (S_io_read): Likewise. - -Mon Aug 28 17:16:48 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * boot_script.h, boot_script.c: Updated by Shantanu Goel, to - accept action keywords only inside $(...) and only variable values - inside ${...}. - * boot.c: Updated for changes in boot_script.h protocol by - Shantanu Goel. - (main): Use boot_script_set_variable instead of magic variables. - Under -d, pause between parsing bootscript and executing it. - -Wed Aug 23 16:08:04 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - New script-driven boot mechanism, mostly implemented by Shantanu Goel. - * Makefile (SRCS): Add boot_script.c. - (OBJS): Add boot_script.o. - (LCLHDRS): New variable. - (HURDLIBS): Variable removed. - (boot): Depend on ../libthreads/libthreads.a. - * boot_script.c, boot_script.h: New files. - * boot.c (boot_like_kernel, boot_like_cmudef, boot_like_hurd): - Variables removed. - (main): Don't interpret switches. Instead of servers, take - command line argument of boot script file name. Read the file and - use boot_script functions to parse and execute its directives. - (boot_script_*): New variables and functions for boot_script callbacks. - -Sun Jul 30 23:50:53 1995 Michael I. Bushnell, p/BSG <mib@geech.gnu.ai.mit.edu> - - * Makefile: DISTFILES -> DIST_FILES. - -Sat Jul 8 11:37:32 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * boot.c (free_reply_ports, free_reply_ports_lock): New variables. - (__mig_get_reply_port, __mig_put_reply_port, __mig_dealloc_reply_port, - mig_get_reply_port, mig_put_reply_port, mig_dealloc_reply_port): - Provide better versions of these routines that won't leak reply ports. - -Fri Jul 7 15:55:18 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * mach-crt0.c: New file, from mach4-i386/libmach/standalone. - * boot.c (mach_init_routine): New variable, wanted by mach-crt0.o. - (__mig_get_reply_port, __mig_dealloc_reply_port, __mig_put_reply_port): - New functions, to avoid using hurdish versions. - * Makefile (OBJS): Add mach-crt0.o. - (SRCS): Add mach-crt0.c. - (LDFLAGS): Add -nostartfiles (as we now use mach-crt0.o). - -Thu Jul 6 15:30:18 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> - - * Makefile (boot.1, boot.a): Use $(LD) and $(OBJCOPY) instead of - explicit names. - - * boot.c: Include <mach/mig_support.h>. - (S_io_reauthenticate): Cast first arg to mig_deallocate. - (load_image): Cast second arg to read. - * tcattr.c: Undo last change; add private decl of ioctl. - - * boot.c (bootdevice): Initialize to hard-coded `sd0a' instead of - DEFAULT_BOOTDEVICE. - - * Makefile (all): Depend on boot.a too. - - * Makefile: Removed dependencies that are now automatically - generated. - -Wed May 31 10:02:11 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * Makefile (DISTFILES): New variable; include frank1.ld and - frankemul.ld. - (CPPFLAGS): Variable removed. - (LDFLAGS): Append -T frank1.ld. - (boot.1, boot.a): New targets. - - * syscall.S: Omit .globl decl for errno; it caused some as - complaint. - -Mon May 22 11:48:58 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> - - * sigvec.S: Remove copyright notice. - -Wed May 17 13:10:27 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * boot.c (load_image): Make sure we actually allocate enough - memory to read into, including the offset into the buffer at which - the segment is read. - - * sigvec.S (sigreturn, _sigreturn, sigvec): Remove the explicit - underscore prefixes from these names, now that we're using elf. - Instead we use the various macros from <i386/asm.h>. Also, return - errors correctly. [Also added a copyright notice] - -Sat May 13 03:37:24 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * boot.c (load_image): Fixed alignment calculation in ELF segment - loading. - - * syscall.S: Include i386/asm.h and use ENTRY and EXT macros, - instead of explicit _s. - -Fri May 12 18:36:39 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * boot.c (load_image): Grok ELF executables as well as a.out. - (main): Load multiple servers. Suspend all but the first. - The first gets an extra arg, its name for the task port of the - second. - -Wed Apr 12 09:18:50 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * Makefile: Don't try and install boot in /usr/local/bin. - -Wed Apr 5 17:25:19 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * boot.c: Don't include <errno.h>. Define `errno' variable. - * Makefile (SRCS): Add syscall.S. - (OBJS): Add syscall.o. - * syscall.S: Check for errors. - -Thu Jan 19 01:21:24 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * boot.c (S_io_select): Updated to new io_select protocol. - -Fri Dec 9 01:23:22 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * boot.c: Use mach_msg_type_number_t in place of unsigned int and - int. - -Fri Nov 11 14:05:43 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu> - - * boot.c (main): Always set `f' flag (signifying "fake" because we - aren't a real native bootstrap). - -Thu Nov 3 17:26:37 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> - - * Makefile (boot.o): Depend on bootstrap_S.h. - -Fri Oct 28 17:08:12 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * boot.c (main): Create the thread before setting it up. - (bootstrap_compat): Make a send right for psuedo_master_device_port. - (main): Explicitly clear NEWTASK's bootstrap port for boot_like_kernel. - (main): Format strings for port names for boot_like_kernel. - -Fri Oct 28 15:26:48 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu> - - * boot.c (boot_like_kernel, boot_like_cmudef, boot_like_hurd): New - global vars. - (set_mach_stack_args): New function. - (main): If the -k flag is given, set BOOT_LIKE_KERNEL. - If the -p flag is given, set BOOT_LIKE_CMUDEF. If neither is - given, set BOOT_LIKE_HURD. - Only set a bootstrap port if BOOT_LIKE_CMUDEF or BOOT_LIKE_HURD. - If BOOT_LIKE_KERNEL or BOOT_LIKE_CMUDEF, set up the stack the - Mach way using set_mach_stack_args. - (request_server): Declare and call bootstrap_server. - (do_bootstrap_priveleged_ports, bootstrap_compat): New functions. - * Makefile (OBJS): Require bootstrapServer.o. - * bootstrap.defs: New file. - -Tue Aug 30 11:41:33 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> - - * boot.c (S_io_reauthenticate): Use new authentication protocol. - -Mon Aug 22 13:43:32 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> - - * boot.c: Include <cthreads.h>. - (main): Run msg_thread fork; don't call - mach_msg_server_timeout here. Use sigpause instead of getpid. - (msg_thread): New function. - (queuelock): New variable. - (queue_read): Acquire queuelock. - (read_reply): Acquire queuelock. - * Makefile (HURDLIBS): New var to get threads. - -Thu Aug 18 18:04:36 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> - - * boot.c (restore_termstate): New function. - (do_mach_notify_no_senders): Call restore_termstate before exiting. - - * boot.c (main): New var `usagemsg'; print it if args are wrong. - Allow flags and disk device to be given on command line. - New var `bootfile'. - (bootdevice, bootstrap_args): New vars. - (load_image): Exit nicely if the startup file can't be found. - (S_exec_startup): Use `bootdevice' instead of hardcoded name. - Use `bootstrap_args' instead of hardcoded "-x". - (main): Only do `pausing' hack if -d was provided. - - * Makefile (CPPFLAGS): Define DEFAULT_BOOTDEVICE. - - * Makefile (/usr/local/bin/boot): Depend on boot. - - * boot.c (S_termctty_open_terminal): New "function". - (S_io_select): Added `rettype' arg. - -Sat Jul 23 02:58:05 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * Makefile (io-MIGSFLAGS): Renamed from ioMIGSFLAGS. - -Fri Jul 22 15:10:45 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> - - * boot.c (request_server): Remove S_ from io_server and - term_server. - -Thu Jul 21 19:00:36 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> - - * Makefile: Rewritten to use new scheme. - * boot.c: Include io_reply_U.h and device_reply_U.h instead - of io_repl.h and device_reply.h. - -Wed Jul 20 13:19:45 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> - - * boot.c: Comment out bits relating to tioctl interface. - * Makefile: Likewise. - -Tue Jul 19 12:41:46 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * Makefile (boot): Don't use variable $(link) anymore. - -Tue Jul 5 14:19:36 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * Makefile (SRCS): New variable. - -Sun Jul 3 17:20:07 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) - - * tcattr.c: New file. - * boot.c (S_tioctl_tiocgeta): Call tcgetattr. - (S_tioctl_tiocseta): Call tcsetattr. - * Makefile (OBJS): Add tcattr.o. - (DIST_FILES): Add tcattr.c. - -Fri Jul 1 11:16:27 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * boot.c (init_termstate): Enter raw mode here. - -Fri Jun 24 14:27:56 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * boot.c (S_term_open_ctty): Renamed from term_become_ctty. - Deleted SIGPT arg. Add msg type arg for NEWTTY. - -Fri Jun 17 13:46:07 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) - - * boot.c (request_server): Remove S_ prefix from exec_server - and notify_server. - -Fri Jun 17 00:12:16 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu) - - * Makefile (boot.o): Depend on term_S.h. - -Tue Jun 14 01:28:10 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu) - - * boot.c (request_server): Add S_ prefix to demuxer functions. - -Wed Jun 8 18:02:19 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu) - - * boot.c (S_tioctl_tiocseta): Turn off ECHO. - (S_io_select): Implement. - -Tue Jun 7 04:33:42 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu) - - * Makefile (tioctlServer.o): Depend on ../hurd/ioctl_types.h. - -Mon Jun 6 20:33:39 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu) - - * boot.c (authserver): New variable. - (S_io_reauthenticate): Do auth_server_authenticate and throw away - the returned info. - (S_exec_init): Set authserver to the passed port. - -Sat Jun 4 02:32:03 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu) - - * boot.c: Include term_S.h and tioctl_S.h. - (S_term_getctty): New function. - (S_term_*): Stub functions. - (request_server): Use S_term_server. - - * Makefile (termServer.c term_S.h): New rule. - (OBJS): Add termServer.o. - - * boot.c (S_exec_setexecdata, S_exec_exec): Fix prototypes. - -Tue May 17 18:44:29 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * boot.c (ds_device_write): DATA arg is char *; don't dereference - it in call to write. - -Mon May 16 14:34:15 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * boot.c (fsname): New variable. - (main): Set fsname to argv[1]. - (S_exec_startup): Include fsname in child's argv[0]. - - * boot.c (init_termstate): Add forward declaration. - (struct sigvec): Make SV_HANDLER member void (*)(). - (sigvec): Add declaration to avoid warning. - -Tue May 10 18:14:39 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) - - * boot.c (tioctl_tiocseta, tioctl_tiocsetw, tioctl_tiocsetf, - tioctl_tiocgeta, init_termstate): New functions. - (term_modes, term_ccs, term_speeds, term_sgb, localbits): Nev - vars. - Also added new bits from ioctl.h. - (main): Call init_termstate. - (request_server): Call tioctl_server. - * Makefile (tioctlServer.c tioctl_S.h): New targets. - (OBJS): Include tioctlServer.o. - (boot.o): Depend on tioctl_S.h - -Fri May 6 13:56:58 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) - - * boot.c (main): Restore braindamage of yesterday relating to - signals; that is, restore declaration of VEC and calls to sigvec. - * Makefile (DIST_FILES): Add sigvec.S. - -Thu May 5 13:16:42 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) - - * Makefile (device_replyUser.c): Mention that this build - device_reply.h as well. - (boot.o): Add dependency on device_reply.h and io_repl.h. - - * boot.c: Include <stdlib.h> for malloc and free prototypes. - Include <string.h> for bcopy and bzero prototypes. - Include <stdio.h> for sprintf prototype. - Include "device_reply.h" for its prototypes. - Include "io_reply.h" for its prototypes. - Declare return type for all the server functions that were lacking - such. - (sigpause): Declare type of MASK. - (ioctl): Declare third arg to be generic pointer, not char *. - (request_server): Declare MiG functions we call. - (load_image): Delete unused variable STACKADDR. - (main): Comment out declaration of VEC. - Comment out calls to sigvec. - Cast STARTPC in call to __mach_setup_thread. - Delete unused variable TIMEOUT. - (read_reply): Cast BUF correctly in call to ds_device_read_reply. - (S_exec_startup): Delete unused variable DTABLE. - (ds_device_write): Double cast arg to write to avoid warning. - (S_io_read): Order args to vm_allocate properly; cast DATA arg. - Check *datalen properly for unsigned type. - - * boot.c: Renamed _exit to uxexit to avoid library name clash. - (do_mach_notify_dead_name, do_mach_notify_no_senders): - Call uxexit instead of _exit. - - * boot.c (S_io_async, S_io_get_icky_async_id, S_io_map_cntl): - Expect new type arg for returned port. - (S_io_prenotify, S_io_postnotify): START and END args are now - vm_offset_t. - - * boot.c: Change error_t to kern_return_t because error_t - is now unsigned and conflicts with MiG's use of kern_return_t. - - * Makefile (io_S.h, ioServer.c): Punt mungio hack; use - -DREPLY_PORTS. - * boot.c: Changed all io server stubs to expect reply ports. - - * mungio: removed file. - * Makefile (DIST_FILES): Removed mungio. - - * boot.c (load_image): Only read from the image file the actual - amount being read, not that amount rounded to the nearest page. - Otherwise, the first bit of the BSS will not be zero, but will be - whatever is in the front of the symbol section of the a.out. - -Thu May 5 07:43:06 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) - - * Makefile: Change uses of $(headers) to $(includedir). - -Mon May 2 16:47:49 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) - - * boot.c (S_io_readable): Implement io_readable fully. - -Fri Apr 1 17:55:38 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) - - * Makefile (OBJS): Remove boot_machdep.o. diff --git a/boot-proxy-exc/Makefile b/boot-proxy-exc/Makefile deleted file mode 100644 index 33c475fb..00000000 --- a/boot-proxy-exc/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (C) 1993,94,95,96,97,2001 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. - -dir := boot -makemode := utility - -SRCS = mach-crt0.c boot.c ux.c sigvec.S syscall.S \ - boot_script.c userland-boot.c list.c mach_proxy.c -COMMON-OBJS = notifyServer.o ourdeviceServer.o \ - ioServer.o io_replyUser.o device_replyUser.o \ - termServer.o bootstrapServer.o boot_script.o userland-boot.o \ - ourmach_hostServer.o ourmachServer.o ourmach_portServer.o excServer.o -OBJS = boot.o mach_host_impl.o mach_impl.o mach_port_impl.o \ - exc_impl.o list.o mach_proxy.o $(COMMON-OBJS) -UX-OBJS = mach-crt0.o uxboot.o sigvec.o syscall.o ux.o $(COMMON-OBJS) -LCLHDRS = boot_script.h ux.h util.h -target = boot -io-MIGSFLAGS=-DREPLY_PORTS -DIST_FILES=frank1.ld frankemul.ld -HURDLIBS=store shouldbeinlibc threads ports - -include ../Makeconf - -#install: /usr/local/bin/uxboot -# -#/usr/local/bin/uxboot: uxboot -# cp $< $@ - -all: boot # uxboot - -ourdevice.defs: device.defs - $(CPP) $(CPPFLAGS) -x c $< | sed -e '/out[ ]*device[ ]*:[ ]*device_t/s/device_t/mach_port_send_t/' > $@ - -uxboot.o: boot.c - $(COMPILE.c) -DUX $< -o $@ - -uxboot.0: $(UX-OBJS) ../libthreads/libthreads.a - $(LINK.o) -o $@ -static -nostartfiles -Wl,-T -Wl,$(srcdir)/frank1.ld $^ -uxboot.1: frankemul.ld uxboot.0 - $(LD) -o $@ -T $^ -uxboot: uxboot.1 - -$(OBJCOPY) -S --remove-section=.comment -O a.out-mach3 $< $@ diff --git a/boot-proxy-exc/backup/ourmach.defs b/boot-proxy-exc/backup/ourmach.defs deleted file mode 100644 index 67d8475e..00000000 --- a/boot-proxy-exc/backup/ourmach.defs +++ /dev/null @@ -1,770 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University. - * Copyright (c) 1993,1994 The University of Utah and - * the Computer Systems Laboratory (CSL). - * All rights reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF - * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY - * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF - * THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * Matchmaker definitions file for Mach kernel interface. - */ - -#ifdef MACH_KERNEL -simport <kern/compat_xxx_defs.h>; /* for obsolete routines */ -#endif /* MACH_KERNEL */ - -subsystem -#if KERNEL_USER - KernelUser -#endif /* KERNEL_USER */ -#if KERNEL_SERVER - KernelServer -#endif /* KERNEL_SERVER */ - mach 2000; - -serverprefix S_; - -#ifdef KERNEL_USER -userprefix r_; -#endif /* KERNEL_USER */ - -#include <mach/std_types.defs> -#include <mach/mach_types.defs> - -skip; /* old port_allocate */ -skip; /* old port_deallocate */ -skip; /* old port_enable */ -skip; /* old port_disable */ -skip; /* old port_select */ -skip; /* old port_set_backlog */ -skip; /* old port_status */ - -/* - * Create a new task with an empty set of IPC rights, - * and having an address space constructed from the - * target task (or empty, if inherit_memory is FALSE). - */ -routine task_create( - target_task : task_t; - inherit_memory : boolean_t; - out child_task : mach_port_send_t); - -/* - * Destroy the target task, causing all of its threads - * to be destroyed, all of its IPC rights to be deallocated, - * and all of its address space to be deallocated. - */ -routine task_terminate( - target_task : task_t); - -/* - * Get user-level handler entry points for all - * emulated system calls. - */ -routine task_get_emulation_vector( - task : task_t; - out vector_start : int; - out emulation_vector: emulation_vector_t); - -/* - * Establish user-level handlers for the specified - * system calls. Non-emulated system calls are specified - * with emulation_vector[i] == EML_ROUTINE_NULL. - */ -routine task_set_emulation_vector( - task : task_t; - vector_start : int; - emulation_vector: emulation_vector_t); - -/* - * Returns the set of threads belonging to the target task. - */ -routine task_threads( - target_task : task_t; - out thread_list : thread_array_t = - array[] of mach_port_send_t, - dealloc); - -/* - * Returns information about the target task. - */ -routine task_info( - target_task : task_t; - flavor : int; - out task_info_out : task_info_t, CountInOut); - - -skip; /* old task_status */ -skip; /* old task_set_notify */ -skip; /* old thread_create */ - -/* - * Destroy the target thread. - */ -routine thread_terminate( - target_thread : thread_t); - -/* - * Return the selected state information for the target - * thread. If the thread is currently executing, the results - * may be stale. [Flavor THREAD_STATE_FLAVOR_LIST provides a - * list of valid flavors for the target thread.] - */ -routine thread_get_state( - target_thread : thread_t; - flavor : int; - out old_state : thread_state_t, CountInOut); - -/* - * Set the selected state information for the target thread. - * If the thread is currently executing, the state change - * may be ill-defined. - */ -routine thread_set_state( - target_thread : thread_t; - flavor : int; - new_state : thread_state_t); - -/* - * Returns information about the target thread. - */ -routine thread_info( - target_thread : thread_t; - flavor : int; - out thread_info_out : thread_info_t, CountInOut); - -skip; /* old thread_mutate */ - -/* - * Allocate zero-filled memory in the address space - * of the target task, either at the specified address, - * or wherever space can be found (if anywhere is TRUE), - * of the specified size. The address at which the - * allocation actually took place is returned. - */ -#ifdef EMULATOR -skip; /* the emulator redefines vm_allocate using vm_map */ -#else /* EMULATOR */ -routine vm_allocate( - target_task : vm_task_t; - inout address : vm_address_t; - size : vm_size_t; - anywhere : boolean_t); -#endif /* EMULATOR */ - -skip; /* old vm_allocate_with_pager */ - -/* - * Deallocate the specified range from the virtual - * address space of the target task. - */ -routine vm_deallocate( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t); - -/* - * Set the current or maximum protection attribute - * for the specified range of the virtual address - * space of the target task. The current protection - * limits the memory access rights of threads within - * the task; the maximum protection limits the accesses - * that may be given in the current protection. - * Protections are specified as a set of {read, write, execute} - * *permissions*. - */ -routine vm_protect( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - set_maximum : boolean_t; - new_protection : vm_prot_t); - -/* - * Set the inheritance attribute for the specified range - * of the virtual address space of the target task. - * The inheritance value is one of {none, copy, share}, and - * specifies how the child address space should acquire - * this memory at the time of a task_create call. - */ -routine vm_inherit( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - new_inheritance : vm_inherit_t); - -/* - * Returns the contents of the specified range of the - * virtual address space of the target task. [The - * range must be aligned on a virtual page boundary, - * and must be a multiple of pages in extent. The - * protection on the specified range must permit reading.] - */ -routine vm_read( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - out data : pointer_t, dealloc); - -/* - * Writes the contents of the specified range of the - * virtual address space of the target task. [The - * range must be aligned on a virtual page boundary, - * and must be a multiple of pages in extent. The - * protection on the specified range must permit writing.] - */ -routine vm_write( - target_task : vm_task_t; - address : vm_address_t; - data : pointer_t); - -/* - * Copy the contents of the source range of the virtual - * address space of the target task to the destination - * range in that same address space. [Both of the - * ranges must be aligned on a virtual page boundary, - * and must be multiples of pages in extent. The - * protection on the source range must permit reading, - * and the protection on the destination range must - * permit writing.] - */ -routine vm_copy( - target_task : vm_task_t; - source_address : vm_address_t; - size : vm_size_t; - dest_address : vm_address_t); - -/* - * Returns information about the contents of the virtual - * address space of the target task at the specified - * address. The returned protection, inheritance, sharing - * and memory object values apply to the entire range described - * by the address range returned; the memory object offset - * corresponds to the beginning of the address range. - * [If the specified address is not allocated, the next - * highest address range is described. If no addresses beyond - * the one specified are allocated, the call returns KERN_NO_SPACE.] - */ -routine vm_region( - target_task : vm_task_t; - inout address : vm_address_t; - out size : vm_size_t; - out protection : vm_prot_t; - out max_protection : vm_prot_t; - out inheritance : vm_inherit_t; - out is_shared : boolean_t; - /* avoid out-translation of the argument */ - out object_name : memory_object_name_t = - MACH_MSG_TYPE_COPY_SEND - ctype: mach_port_t; - out offset : vm_offset_t); - -/* - * Return virtual memory statistics for the host - * on which the target task resides. [Note that the - * statistics are not specific to the target task.] - */ -routine vm_statistics( - target_task : vm_task_t; - out vm_stats : vm_statistics_data_t); - -skip; /* old task_by_u*x_pid */ -skip; /* old vm_pageable */ - -/* - * Stash a handful of ports for the target task; child - * tasks inherit this stash at task_create time. - */ -routine mach_ports_register( - target_task : task_t; - init_port_set : mach_port_array_t = - ^array[] of mach_port_t); - -/* - * Retrieve the stashed ports for the target task. - */ -routine mach_ports_lookup( - target_task : task_t; - out init_port_set : mach_port_array_t = - ^array[] of mach_port_t); - -skip; /* old u*x_pid */ -skip; /* old netipc_listen */ -skip; /* old netipc_ignore */ - -/* - * Provide the data contents of a range of the given memory - * object, with the access restriction specified. [Only - * whole virtual pages of data can be accepted; partial pages - * will be discarded. Data should be provided on request, but - * may be provided in advance as desired. When data already - * held by this kernel is provided again, the new data is ignored. - * The access restriction is the subset of {read, write, execute} - * which are prohibited. The kernel may not provide any data (or - * protection) consistency among pages with different virtual page - * alignments within the same object.] - */ -simpleroutine memory_object_data_provided( - memory_control : memory_object_control_t; - offset : vm_offset_t; - data : pointer_t; - lock_value : vm_prot_t); - -/* - * Indicate that a range of the given temporary memory object does - * not exist, and that the backing memory object should be used - * instead (or zero-fill memory be used, if no backing object exists). - * [This call is intended for use only by the default memory manager. - * It should not be used to indicate a real error -- - * memory_object_data_error should be used for that purpose.] - */ -simpleroutine memory_object_data_unavailable( - memory_control : memory_object_control_t; - offset : vm_offset_t; - size : vm_size_t); - -/* - * Retrieves the attributes currently associated with - * a memory object. - */ -routine memory_object_get_attributes( - memory_control : memory_object_control_t; - out object_ready : boolean_t; - out may_cache : boolean_t; - out copy_strategy : memory_object_copy_strategy_t); - -/* - * Sets the default memory manager, the port to which - * newly-created temporary memory objects are delivered. - * [See (memory_object_default)memory_object_create.] - * The old memory manager port is returned. - */ -routine vm_set_default_memory_manager( - host_priv : host_priv_t; - inout default_manager : mach_port_copy_send_t); - -skip; /* old pager_flush_request */ - -/* - * Control use of the data associated with the given - * memory object. For each page in the given range, - * perform the following operations, in order: - * 1) restrict access to the page (disallow - * forms specified by "prot"); - * 2) write back modifications (if "should_return" - * is RETURN_DIRTY and the page is dirty, or - * "should_return" is RETURN_ALL and the page - * is either dirty or precious); and, - * 3) flush the cached copy (if "should_flush" - * is asserted). - * The set of pages is defined by a starting offset - * ("offset") and size ("size"). Only pages with the - * same page alignment as the starting offset are - * considered. - * - * A single acknowledgement is sent (to the "reply_to" - * port) when these actions are complete. - * - * There are two versions of this routine because IPC distinguishes - * between booleans and integers (a 2-valued integer is NOT a - * boolean). The new routine is backwards compatible at the C - * language interface. - */ -simpleroutine xxx_memory_object_lock_request( - memory_control : memory_object_control_t; - offset : vm_offset_t; - size : vm_size_t; - should_clean : boolean_t; - should_flush : boolean_t; - lock_value : vm_prot_t; - reply_to : mach_port_t = - MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); - - -simpleroutine memory_object_lock_request( - memory_control : memory_object_control_t; - offset : vm_offset_t; - size : vm_size_t; - should_return : memory_object_return_t; - should_flush : boolean_t; - lock_value : vm_prot_t; - reply_to : mach_port_t = - MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); - -/* obsolete */ -routine xxx_task_get_emulation_vector( - task : task_t; - out vector_start : int; - out emulation_vector: xxx_emulation_vector_t, IsLong); - -/* obsolete */ -routine xxx_task_set_emulation_vector( - task : task_t; - vector_start : int; - emulation_vector: xxx_emulation_vector_t, IsLong); - -/* - * Returns information about the host on which the - * target object resides. [This object may be - * a task, thread, or memory_object_control port.] - */ -routine xxx_host_info( - target_task : mach_port_t; - out info : machine_info_data_t); - -/* - * Returns information about a particular processor on - * the host on which the target task resides. - */ -routine xxx_slot_info( - target_task : task_t; - slot : int; - out info : machine_slot_data_t); - -/* - * Performs control operations (currently only - * turning off or on) on a particular processor on - * the host on which the target task resides. - */ -routine xxx_cpu_control( - target_task : task_t; - cpu : int; - running : boolean_t); - -skip; /* old thread_statistics */ -skip; /* old task_statistics */ -skip; /* old netport_init */ -skip; /* old netport_enter */ -skip; /* old netport_remove */ -skip; /* old thread_set_priority */ - -/* - * Increment the suspend count for the target task. - * No threads within a task may run when the suspend - * count for that task is non-zero. - */ -routine task_suspend( - target_task : task_t); - -/* - * Decrement the suspend count for the target task, - * if the count is currently non-zero. If the resulting - * suspend count is zero, then threads within the task - * that also have non-zero suspend counts may execute. - */ -routine task_resume( - target_task : task_t); - -/* - * Returns the current value of the selected special port - * associated with the target task. - */ -routine task_get_special_port( - task : task_t; - which_port : int; - out special_port : mach_port_send_t); - -/* - * Set one of the special ports associated with the - * target task. - */ -routine task_set_special_port( - task : task_t; - which_port : int; - special_port : mach_port_t); - -/* obsolete */ -routine xxx_task_info( - target_task : task_t; - flavor : int; - out task_info_out : task_info_t, IsLong); - - -/* - * Create a new thread within the target task, returning - * the port representing that new thread. The - * initial execution state of the thread is undefined. - */ -routine thread_create( - parent_task : task_t; - out child_thread : mach_port_send_t); - -/* - * Increment the suspend count for the target thread. - * Once this call has completed, the thread will not - * execute any further user or meta- instructions. - * Once suspended, a thread may not execute again until - * its suspend count is zero, and the suspend count - * for its task is also zero. - */ -routine thread_suspend( - target_thread : thread_t); - -/* - * Decrement the suspend count for the target thread, - * if that count is not already zero. - */ -routine thread_resume( - target_thread : thread_t); - -/* - * Cause any user or meta- instructions currently being - * executed by the target thread to be aborted. [Meta- - * instructions consist of the basic traps for IPC - * (e.g., msg_send, msg_receive) and self-identification - * (e.g., task_self, thread_self, thread_reply). Calls - * described by MiG interfaces are not meta-instructions - * themselves.] - */ -routine thread_abort( - target_thread : thread_t); - -/* obsolete */ -routine xxx_thread_get_state( - target_thread : thread_t; - flavor : int; - out old_state : thread_state_t, IsLong); - -/* obsolete */ -routine xxx_thread_set_state( - target_thread : thread_t; - flavor : int; - new_state : thread_state_t, IsLong); - -/* - * Returns the current value of the selected special port - * associated with the target thread. - */ -routine thread_get_special_port( - thread : thread_t; - which_port : int; - out special_port : mach_port_t); - -/* - * Set one of the special ports associated with the - * target thread. - */ -routine thread_set_special_port( - thread : thread_t; - which_port : int; - special_port : mach_port_t); - -/* obsolete */ -routine xxx_thread_info( - target_thread : thread_t; - flavor : int; - out thread_info_out : thread_info_t, IsLong); - -/* - * Establish a user-level handler for the specified - * system call. - */ -routine task_set_emulation( - target_port : task_t; - routine_entry_pt: vm_address_t; - routine_number : int); - -/* - * Establish restart pc for interrupted atomic sequences. - * This reuses the message number for the old task_get_io_port. - * See task_info.h for description of flavors. - * - */ -routine task_ras_control( - target_task : task_t; - basepc : vm_address_t; - boundspc : vm_address_t; - flavor : int); - - - -skip; /* old host_ipc_statistics */ -skip; /* old port_names */ -skip; /* old port_type */ -skip; /* old port_rename */ -skip; /* old port_allocate */ -skip; /* old port_deallocate */ -skip; /* old port_set_backlog */ -skip; /* old port_status */ -skip; /* old port_set_allocate */ -skip; /* old port_set_deallocate */ -skip; /* old port_set_add */ -skip; /* old port_set_remove */ -skip; /* old port_set_status */ -skip; /* old port_insert_send */ -skip; /* old port_extract_send */ -skip; /* old port_insert_receive */ -skip; /* old port_extract_receive */ - -/* - * Map a user-defined memory object into the virtual address - * space of the target task. If desired (anywhere is TRUE), - * the kernel will find a suitable address range of the - * specified size; else, the specific address will be allocated. - * - * The beginning address of the range will be aligned on a virtual - * page boundary, be at or beyond the address specified, and - * meet the mask requirements (bits turned on in the mask must not - * be turned on in the result); the size of the range, in bytes, - * will be rounded up to an integral number of virtual pages. - * - * The memory in the resulting range will be associated with the - * specified memory object, with the beginning of the memory range - * referring to the specified offset into the memory object. - * - * The mapping will take the current and maximum protections and - * the inheritance attributes specified; see the vm_protect and - * vm_inherit calls for a description of these attributes. - * - * If desired (copy is TRUE), the memory range will be filled - * with a copy of the data from the memory object; this copy will - * be private to this mapping in this target task. Otherwise, - * the memory in this mapping will be shared with other mappings - * of the same memory object at the same offset (in this task or - * in other tasks). [The Mach kernel only enforces shared memory - * consistency among mappings on one host with similar page alignments. - * The user-defined memory manager for this object is responsible - * for further consistency.] - */ -#ifdef EMULATOR -routine htg_vm_map( - target_task : vm_task_t; - ureplyport reply_port : mach_port_make_send_once_t; - inout address : vm_address_t; - size : vm_size_t; - mask : vm_address_t; - anywhere : boolean_t; - memory_object : memory_object_t; - offset : vm_offset_t; - copy : boolean_t; - cur_protection : vm_prot_t; - max_protection : vm_prot_t; - inheritance : vm_inherit_t); -#else /* EMULATOR */ -routine vm_map( - target_task : vm_task_t; - inout address : vm_address_t; - size : vm_size_t; - mask : vm_address_t; - anywhere : boolean_t; - memory_object : memory_object_t; - offset : vm_offset_t; - copy : boolean_t; - cur_protection : vm_prot_t; - max_protection : vm_prot_t; - inheritance : vm_inherit_t); -#endif /* EMULATOR */ - -/* - * Indicate that a range of the specified memory object cannot - * be provided at this time. [Threads waiting for memory pages - * specified by this call will experience a memory exception. - * Only threads waiting at the time of the call are affected.] - */ -simpleroutine memory_object_data_error( - memory_control : memory_object_control_t; - offset : vm_offset_t; - size : vm_size_t; - error_value : kern_return_t); - -/* - * Make decisions regarding the use of the specified - * memory object. - */ -simpleroutine memory_object_set_attributes( - memory_control : memory_object_control_t; - object_ready : boolean_t; - may_cache : boolean_t; - copy_strategy : memory_object_copy_strategy_t); - -/* - */ -simpleroutine memory_object_destroy( - memory_control : memory_object_control_t; - reason : kern_return_t); - -/* - * Provide the data contents of a range of the given memory - * object, with the access restriction specified, optional - * precious attribute, and reply message. [Only - * whole virtual pages of data can be accepted; partial pages - * will be discarded. Data should be provided on request, but - * may be provided in advance as desired. When data already - * held by this kernel is provided again, the new data is ignored. - * The access restriction is the subset of {read, write, execute} - * which are prohibited. The kernel may not provide any data (or - * protection) consistency among pages with different virtual page - * alignments within the same object. The precious value controls - * how the kernel treats the data. If it is FALSE, the kernel treats - * its copy as a temporary and may throw it away if it hasn't been - * changed. If the precious value is TRUE, the kernel treats its - * copy as a data repository and promises to return it to the manager; - * the manager may tell the kernel to throw it away instead by flushing - * and not cleaning the data -- see memory_object_lock_request. The - * reply_to port is for a compeletion message; it will be - * memory_object_supply_completed.] - */ - -simpleroutine memory_object_data_supply( - memory_control : memory_object_control_t; - offset : vm_offset_t; - data : pointer_t, Dealloc[]; - lock_value : vm_prot_t; - precious : boolean_t; - reply_to : mach_port_t = - MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); - -simpleroutine memory_object_ready( - memory_control : memory_object_control_t; - may_cache : boolean_t; - copy_strategy : memory_object_copy_strategy_t); - -simpleroutine memory_object_change_attributes( - memory_control : memory_object_control_t; - may_cache : boolean_t; - copy_strategy : memory_object_copy_strategy_t; - reply_to : mach_port_t = - MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); - -skip; /* old host_callout_statistics_reset */ -skip; /* old port_set_select */ -skip; /* old port_set_backup */ - -/* - * Set/Get special properties of memory associated - * to some virtual address range, such as cachability, - * migrability, replicability. Machine-dependent. - */ -routine vm_machine_attribute( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - attribute : vm_machine_attribute_t; - inout value : vm_machine_attribute_val_t); - -skip; /* old host_fpa_counters_reset */ - -/* - * There is no more room in this interface for additional calls. - */ diff --git a/boot-proxy-exc/backup/ourmach_host.defs b/boot-proxy-exc/backup/ourmach_host.defs deleted file mode 100644 index 0e7e367e..00000000 --- a/boot-proxy-exc/backup/ourmach_host.defs +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University. - * Copyright (c) 1993,1994 The University of Utah and - * the Computer Systems Laboratory (CSL). - * All rights reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF - * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY - * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF - * THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: mach/mach_host.defs - * - * Abstract: - * Mach host operations support. Includes processor allocation and - * control. - */ - -#ifdef MACH_KERNEL -simport <kern/compat_xxx_defs.h>; /* for obsolete routines */ -#endif - -subsystem -#if KERNEL_SERVER - KernelServer -#endif - mach_host 2600; - -serverprefix S_; - -/* - * Basic types - */ - -#include <mach/std_types.defs> -#include <mach/mach_types.defs> - -/* - * Get list of processors on this host. - */ - -routine host_processors( - host_priv : host_priv_t; - out processor_list : processor_array_t); - -/* obsolete */ -routine yyy_host_info( - host : host_t; - flavor : int; - out host_info_out : host_info_t, IsLong); - - -/* obsolete */ -routine yyy_processor_info( - processor : processor_t; - flavor : int; - out host : host_t; - out processor_info_out: processor_info_t, IsLong); - -/* - * Start processor. - */ - -routine processor_start( - processor : processor_t); - -/* - * Exit processor -- may not be restartable. - */ - -routine processor_exit( - processor : processor_t); - -/* obsolete */ -routine yyy_processor_control( - processor : processor_t; - processor_cmd : processor_info_t, IsLong); - -/* - * Get default processor set for host. - */ -routine processor_set_default( - host : host_t; - out default_set : processor_set_name_t); - -/* - * Get rights to default processor set for host. - * Replaced by host_processor_set_priv. - */ -routine xxx_processor_set_default_priv( - host : host_priv_t; - out default_set : processor_set_t); - -/* - * Create new processor set. Returns real port for manipulations, - * and name port for obtaining information. - */ -routine processor_set_create( - host : host_t; - out new_set : processor_set_t; - out new_name : processor_set_name_t); - -/* - * Destroy processor set. - */ -routine processor_set_destroy( - set : processor_set_t); - -/* obsolete */ -routine yyy_processor_set_info( - set_name : processor_set_name_t; - flavor : int; - out host : host_t; - out info_out : processor_set_info_t, IsLong); - -/* - * Assign processor to processor set. - */ -routine processor_assign( - processor : processor_t; - new_set : processor_set_t; - wait : boolean_t); - -/* - * Get current assignment for processor. - */ - -routine processor_get_assignment( - processor : processor_t; - out assigned_set : processor_set_name_t); - -/* - * Assign thread to processor set. - */ -routine thread_assign( - thread : thread_t; - new_set : processor_set_t); - -/* - * Assign thread to default set. - */ -routine thread_assign_default( - thread : thread_t); - -/* - * Get current assignment for thread. - */ -routine thread_get_assignment( - thread : thread_t; - out assigned_set : processor_set_name_t); - -/* - * Assign task to processor set. - */ -routine task_assign( - task : task_t; - new_set : processor_set_t; - assign_threads : boolean_t); -/* - * Assign task to default set. - */ -routine task_assign_default( - task : task_t; - assign_threads : boolean_t); - -/* - * Get current assignment for task. - */ -routine task_get_assignment( - task : task_t; - out assigned_set : processor_set_name_t); - -/* - * Get string describing current kernel version. - */ -routine host_kernel_version( - host : host_t; - out kernel_version : kernel_version_t); - -/* - * Set priority for thread. - */ -routine thread_priority( - thread : thread_t; - priority : int; - set_max : boolean_t); - -/* - * Set max priority for thread. - */ -routine thread_max_priority( - thread : thread_t; - processor_set : processor_set_t; - max_priority : int); - -/* - * Set task priority. - */ -routine task_priority( - task : task_t; - priority : int; - change_threads : boolean_t); - -/* - * Set max priority for processor_set. - */ -routine processor_set_max_priority( - processor_set : processor_set_t; - max_priority : int; - change_threads : boolean_t); - -/* - * Set policy for thread - */ -routine thread_policy( - thread : thread_t; - policy : int; - data : int); - -/* - * Enable policy for processor set - */ -routine processor_set_policy_enable( - processor_set : processor_set_t; - policy : int); - -/* - * Disable policy for processor set - */ -routine processor_set_policy_disable( - processor_set : processor_set_t; - policy : int; - change_threads : boolean_t); -/* - * List all tasks in processor set. - */ -routine processor_set_tasks( - processor_set : processor_set_t; - out task_list : task_array_t); - -/* - * List all threads in processor set. - */ -routine processor_set_threads( - processor_set : processor_set_t; - out thread_list : thread_array_t); - -/* - * List all processor sets on host. - */ -routine host_processor_sets( - host : host_t; - out processor_sets : processor_set_name_array_t); - -/* - * Get control port for a processor set. - */ -routine host_processor_set_priv( - host_priv : host_priv_t; - set_name : processor_set_name_t; - out set : mach_port_send_t); - -routine thread_depress_abort( - thread : thread_t); - -/* - * Set the time on this host. - * Only available to privileged users. - */ -routine host_set_time( - host_priv : host_priv_t; - new_time : time_value_t); - -/* - * Arrange for the time on this host to be gradually changed - * by an adjustment value, and return the old value. - * Only available to privileged users. - */ -routine host_adjust_time( - host_priv : host_priv_t; - in new_adjustment : time_value_t; - out old_adjustment : time_value_t); - -/* - * Get the time on this host. - * Available to all. - */ -routine host_get_time( - host : host_t; - out current_time : time_value_t); - -/* - * Reboot this host. - * Only available to privileged users. - */ -routine host_reboot( - host_priv : host_priv_t; - options : int); - -/* - * Specify that the range of the virtual address space - * of the target task must not cause page faults for - * the indicated accesses. - * - * [ To unwire the pages, specify VM_PROT_NONE. ] - */ -routine vm_wire( - host_priv : host_priv_t; - task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - access : vm_prot_t); - -/* - * Specify that the target thread must always be able - * to run and to allocate memory. - */ -routine thread_wire( - host_priv : host_priv_t; - thread : thread_t; - wired : boolean_t); - -/* - * Return information about this host. - */ - -routine host_info( - host : host_t; - flavor : int; - out host_info_out : host_info_t, CountInOut); - - -/* - * Return information about this processor. - */ -routine processor_info( - processor : processor_t; - flavor : int; - out host : host_t; - out processor_info_out: processor_info_t, CountInOut); - -/* - * Get information about processor set. - */ -routine processor_set_info( - set_name : processor_set_name_t; - flavor : int; - out host : host_t; - out info_out : processor_set_info_t, CountInOut); - -/* - * Do something machine-dependent to processor. - */ -routine processor_control( - processor : processor_t; - processor_cmd : processor_info_t); - -/* - * Get boot configuration information from kernel. - */ -routine host_get_boot_info( - host_priv : host_priv_t; - out boot_info : kernel_boot_info_t); diff --git a/boot-proxy-exc/backup/ourmach_port.defs b/boot-proxy-exc/backup/ourmach_port.defs deleted file mode 100644 index 4f131bb2..00000000 --- a/boot-proxy-exc/backup/ourmach_port.defs +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University. - * Copyright (c) 1993,1994 The University of Utah and - * the Computer Systems Laboratory (CSL). - * All rights reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF - * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY - * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF - * THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: mach/mach_port.defs - * Author: Rich Draves - * - * Copyright (c) 1989 Richard P. Draves, Jr. - * - * Exported kernel calls. - */ - -subsystem -#if KERNEL_SERVER - KernelServer -#endif - mach_port 3200; - -#include <mach/std_types.defs> -#include <mach/mach_types.defs> - -/* - * Returns the set of port and port set names - * to which the target task has access, along with - * the type (set or port) for each name. - */ - -routine mach_port_names( - task : ipc_space_t; - out names : mach_port_name_array_t = - ^array[] of mach_port_name_t - ctype: mach_port_array_t, - dealloc; - out types : mach_port_type_array_t = - ^array[] of mach_port_type_t, - dealloc); - -/* - * Returns the type (set or port) for the port name - * within the target task. Also indicates whether - * there is a dead-name request for the name. - */ - -routine mach_port_type( - task : ipc_space_t; - name : mach_port_name_t; - out ptype : mach_port_type_t); - -/* - * Changes the name by which a port (or port set) is known to - * the target task. The new name can't be in use. The - * old name becomes available for recycling. - */ - -routine mach_port_rename( - task : ipc_space_t; - old_name : mach_port_name_t; - new_name : mach_port_name_t); - -/* - * Allocates the specified kind of object, with the given name. - * The right must be one of - * MACH_PORT_RIGHT_RECEIVE - * MACH_PORT_RIGHT_PORT_SET - * MACH_PORT_RIGHT_DEAD_NAME - * New port sets are empty. New ports don't have any - * send/send-once rights or queued messages. The make-send - * count is zero and their queue limit is MACH_PORT_QLIMIT_DEFAULT. - * New sets, ports, and dead names have one user reference. - */ - -routine mach_port_allocate_name( - task : ipc_space_t; - right : mach_port_right_t; - name : mach_port_name_t); - -/* - * Allocates the specified kind of object. - * The right must be one of - * MACH_PORT_RIGHT_RECEIVE - * MACH_PORT_RIGHT_PORT_SET - * MACH_PORT_RIGHT_DEAD_NAME - * Like port_allocate_name, but the kernel picks a name. - * It can use any name not associated with a right. - */ - -routine mach_port_allocate( - task : ipc_space_t; - right : mach_port_right_t; - out name : mach_port_name_t); - -/* - * Destroys all rights associated with the name and makes it - * available for recycling immediately. The name can be a - * port (possibly with multiple user refs), a port set, or - * a dead name (again, with multiple user refs). - */ - -routine mach_port_destroy( - task : ipc_space_t; - name : mach_port_name_t); - -/* - * Releases one send/send-once/dead-name user ref. - * Just like mach_port_mod_refs -1, but deduces the - * correct type of right. This allows a user task - * to release a ref for a port without worrying - * about whether the port has died or not. - */ - -routine mach_port_deallocate( - task : ipc_space_t; - name : mach_port_name_t); - -/* - * A port set always has one user ref. - * A send-once right always has one user ref. - * A dead name always has one or more user refs. - * A send right always has one or more user refs. - * A receive right always has one user ref. - * The right must be one of - * MACH_PORT_RIGHT_RECEIVE - * MACH_PORT_RIGHT_PORT_SET - * MACH_PORT_RIGHT_DEAD_NAME - * MACH_PORT_RIGHT_SEND - * MACH_PORT_RIGHT_SEND_ONCE - */ - -routine mach_port_get_refs( - task : ipc_space_t; - name : mach_port_name_t; - right : mach_port_right_t; - out refs : mach_port_urefs_t); - -/* - * The delta is a signed change to the task's - * user ref count for the right. Only dead names - * and send rights can have a positive delta. - * The resulting user ref count can't be negative. - * If it is zero, the right is deallocated. - * If the name isn't a composite right, it becomes - * available for recycling. The right must be one of - * MACH_PORT_RIGHT_RECEIVE - * MACH_PORT_RIGHT_PORT_SET - * MACH_PORT_RIGHT_DEAD_NAME - * MACH_PORT_RIGHT_SEND - * MACH_PORT_RIGHT_SEND_ONCE - */ - -routine mach_port_mod_refs( - task : ipc_space_t; - name : mach_port_name_t; - right : mach_port_right_t; - delta : mach_port_delta_t); - -/* - * Temporary compatibility call. - */ - -routine old_mach_port_get_receive_status( - task : ipc_space_t; - name : mach_port_name_t; - out status : old_mach_port_status_t); - -/* - * Only valid for receive rights. - * Sets the queue-limit for the port. - * The limit must be - * 1 <= qlimit <= MACH_PORT_QLIMIT_MAX - */ - -routine mach_port_set_qlimit( - task : ipc_space_t; - name : mach_port_name_t; - qlimit : mach_port_msgcount_t); - -/* - * Only valid for receive rights. - * Sets the make-send count for the port. - */ - -routine mach_port_set_mscount( - task : ipc_space_t; - name : mach_port_name_t; - mscount : mach_port_mscount_t); - -/* - * Only valid for port sets. Returns a list of - * the members. - */ - -routine mach_port_get_set_status( - task : ipc_space_t; - name : mach_port_name_t; - out members : mach_port_name_array_t = - ^array[] of mach_port_name_t - ctype: mach_port_array_t, - dealloc); - -/* - * Puts the member port (the task must have receive rights) - * into the after port set. (Or removes it from any port set - * if after is MACH_PORT_NULL.) If the port is already in - * a set, does an atomic move. - */ - -routine mach_port_move_member( - task : ipc_space_t; - member : mach_port_name_t; - after : mach_port_name_t); - -/* - * Requests a notification from the kernel. The request - * must supply the send-once right which is used for - * the notification. If a send-once right was previously - * registered, it is returned. The msg_id must be one of - * MACH_NOTIFY_PORT_DESTROYED (receive rights) - * MACH_NOTIFY_DEAD_NAME (send/receive/send-once rights) - * MACH_NOTIFY_NO_SENDERS (receive rights) - * - * The sync value specifies whether a notification should - * get sent immediately, if appropriate. The exact meaning - * depends on the notification: - * MACH_NOTIFY_PORT_DESTROYED: must be zero. - * MACH_NOTIFY_DEAD_NAME: if non-zero, then name can be dead, - * and the notification gets sent immediately. - * If zero, then name can't be dead. - * MACH_NOTIFY_NO_SENDERS: the notification gets sent - * immediately if the current mscount is greater - * than or equal to the sync value and there are no - * extant send rights. - */ - -routine mach_port_request_notification( - task : ipc_space_t; - name : mach_port_name_t; - id : mach_msg_id_t; - sync : mach_port_mscount_t; - notify : mach_port_send_once_t; - out previous : mach_port_send_once_t); - -/* - * Inserts the specified rights into the target task, - * using the specified name. If inserting send/receive - * rights and the task already has send/receive rights - * for the port, then the names must agree. In any case, - * the task gains a user ref for the port. - */ - -routine mach_port_insert_right( - task : ipc_space_t; - name : mach_port_name_t; - poly : mach_port_poly_t); - -/* - * Returns the specified right for the named port - * in the target task, extracting that right from - * the target task. The target task loses a user - * ref and the name may be available for recycling. - * msgt_name must be one of - * MACH_MSG_TYPE_MOVE_RECEIVE - * MACH_MSG_TYPE_COPY_SEND - * MACH_MSG_TYPE_MAKE_SEND - * MACH_MSG_TYPE_MOVE_SEND - * MACH_MSG_TYPE_MAKE_SEND_ONCE - * MACH_MSG_TYPE_MOVE_SEND_ONCE - */ - -routine mach_port_extract_right( - task : ipc_space_t; - name : mach_port_name_t; - msgt_name : mach_msg_type_name_t; - out poly : mach_port_poly_t); - -/* - * The task must have receive rights for the named port. - * Returns a status structure (see mach/port.h). - */ - -routine mach_port_get_receive_status( - task : ipc_space_t; - name : mach_port_name_t; - out status : mach_port_status_t); - -/* - * Only valid for receive rights. - * Sets the sequence number for the port. - */ - -routine mach_port_set_seqno( - task : ipc_space_t; - name : mach_port_name_t; - seqno : mach_port_seqno_t); - -#ifdef MIGRATING_THREADS -/* - * Only valid for receive rights. - * Set the user-mode entry info for RPCs coming through this port. - * Do this BEFORE attaching an ActPool to this port, - * unless you can be sure no RPCs will be coming through it yet. - */ - -routine mach_port_set_rpcinfo( - task : ipc_space_t; - name : mach_port_name_t; - rpc_info : thread_info_t); /* XXX */ - -/* - * Only valid for receive rights. - * Create a new activation for migrating RPC, and attach it to the port's ActPool. - * Create an ActPool for the port if it doesn't already have one. - * Supply a stack and receive memory buffer. - */ - -routine mach_port_create_act( - task : task_t; - name : mach_port_name_t; - user_stack : vm_offset_t; - user_rbuf : vm_offset_t; - user_rbuf_size : vm_size_t; - out new_act : thread_t); - -#endif /* MIGRATING_THREADS */ - diff --git a/boot-proxy-exc/boot.c b/boot-proxy-exc/boot.c deleted file mode 100644 index 83b69c08..00000000 --- a/boot-proxy-exc/boot.c +++ /dev/null @@ -1,2150 +0,0 @@ -/* Load a task using the single server, and then run it - as if we were the kernel. - Copyright (C) 1993,94,95,96,97,98,99,2000,01,02,2006 - 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 <mach.h> -#include <mach/notify.h> -#include <device/device.h> -#include <a.out.h> -#include <mach/message.h> -#include <mach/mig_errors.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <cthreads.h> -#include <fcntl.h> -#include <elf.h> -#include <mach/mig_support.h> -#include <mach/default_pager.h> -#include <argp.h> -#include <hurd/store.h> -#include <hurd/ports.h> -#include <sys/mman.h> -#include <version.h> - -#include "notify_S.h" -#include "ourdevice_S.h" -#include "io_S.h" -#include "device_reply_U.h" -#include "io_reply_U.h" -#include "term_S.h" -#include "bootstrap_S.h" -/* #include "tioctl_S.h" */ -#include "util.h" -#include "boot_script.h" -#include "mach_proxy.h" - -#include <hurd/auth.h> - -#ifdef UX -#undef STORE /* We can't use libstore when under UX. */ -#else -#define STORE -#endif - -#ifdef UX - -#include "ux.h" - -#else /* !UX */ - -#include <unistd.h> -#include <fcntl.h> -#include <signal.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <termios.h> -#include <error.h> -#include <hurd.h> -#include <assert.h> - -static struct termios orig_tty_state; -static int isig; -static char *kernel_command_line; - -struct port_bucket *port_bucket; -struct port_class *task_portclass; -struct port_class *exc_portclass; -struct port_class *priv_host_portclass; -struct port_class *other_portclass; - -void destroy_priv_host (void *pi); - -static void -init_termstate () -{ - struct termios tty_state; - - if (tcgetattr (0, &tty_state) < 0) - error (10, errno, "tcgetattr"); - - orig_tty_state = tty_state; - cfmakeraw (&tty_state); - if (isig) - tty_state.c_lflag |= ISIG; - - if (tcsetattr (0, 0, &tty_state) < 0) - error (11, errno, "tcsetattr"); -} - -static void -restore_termstate () -{ - tcsetattr (0, 0, &orig_tty_state); -} - -#define host_fstat fstat -typedef struct stat host_stat_t; -#define host_exit exit - -#endif /* UX */ - -mach_port_t privileged_host_port, master_device_port, defpager; -mach_port_t pseudo_master_device_port; -mach_port_t receive_set; -mach_port_t pseudo_console, pseudo_root; -auth_t authserver; - -struct port_info *pseudo_priv_host_pi; - -struct store *root_store; - -spin_lock_t queuelock = SPIN_LOCK_INITIALIZER; -spin_lock_t readlock = SPIN_LOCK_INITIALIZER; - -mach_port_t php_child_name, psmdp_child_name, taskname; - -task_t child_task; -mach_port_t bootport; - -int console_mscount; - -vm_address_t fs_stack_base; -vm_size_t fs_stack_size; - -void init_termstate (); -void restore_termstate (); - -char *fsname; - -char bootstrap_args[100] = "-"; -char *bootdevice = 0; -char *bootscript = 0; - -boolean_t is_user = 0; - - -void safe_gets (char *buf, int buf_len) -{ - fgets (buf, buf_len, stdin); -} - -char *useropen_dir; - -int -useropen (const char *name, int flags, int mode) -{ - if (useropen_dir) - { - static int dlen; - if (!dlen) dlen = strlen (useropen_dir); - { - int len = strlen (name); - char try[dlen + 1 + len + 1]; - int fd; - memcpy (try, useropen_dir, dlen); - try[dlen] = '/'; - memcpy (&try[dlen + 1], name, len + 1); - fd = open (try, flags, mode); - if (fd >= 0) - return fd; - } - } - return open (name, flags, mode); -} - -int -request_server (mach_msg_header_t *inp, - mach_msg_header_t *outp) -{ - extern int io_server (mach_msg_header_t *, mach_msg_header_t *); - extern int device_server (mach_msg_header_t *, mach_msg_header_t *); - extern int notify_server (mach_msg_header_t *, mach_msg_header_t *); - extern int term_server (mach_msg_header_t *, mach_msg_header_t *); -/* extern int tioctl_server (mach_msg_header_t *, mach_msg_header_t *); */ - extern int bootstrap_server (mach_msg_header_t *, mach_msg_header_t *); - extern boolean_t mach_host_server (mach_msg_header_t *InHeadP, - mach_msg_header_t *OutHeadP); - extern boolean_t mach_server (mach_msg_header_t *InHeadP, - mach_msg_header_t *OutHeadP); - extern void bootstrap_compat (); - -#if 0 - if (inp->msgh_local_port == bootport && boot_like_cmudef) - { - if (inp->msgh_id == 999999) - { - bootstrap_compat (inp, outp); - return 1; - } - else - return bootstrap_server (inp, outp); - } - else -#endif - return (io_server (inp, outp) - || device_server (inp, outp) - || notify_server (inp, outp) - || term_server (inp, outp) - /* || tioctl_server (inp, outp) */); -} - -int -mach_proxy_demuxer (mach_msg_header_t *inp, - mach_msg_header_t *outp) -{ - extern boolean_t mach_server - (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); - extern boolean_t mach_host_server - (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); - extern boolean_t mach_port_server - (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); - extern boolean_t exc_server - (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); - extern int notify_server (mach_msg_header_t *, mach_msg_header_t *); - return (mach_server (inp, outp) - || mach_host_server (inp, outp) - || mach_port_server (inp, outp) - || notify_server (inp, outp) - || exc_server (inp, outp)); -} - -void -mach_proxy_thread () -{ - ports_manage_port_operations_multithread (port_bucket, - mach_proxy_demuxer, - 30 * 1000, 0, 0); -} - -vm_address_t -load_image (task_t t, - char *file) -{ - int fd; - union - { - struct exec a; - Elf32_Ehdr e; - } hdr; - char msg[] = ": cannot open bootstrap file\n"; - - fd = useropen (file, O_RDONLY, 0); - - if (fd == -1) - { - write (2, file, strlen (file)); - write (2, msg, sizeof msg - 1); - task_terminate (t); - host_exit (1); - } - - read (fd, &hdr, sizeof hdr); - if (*(Elf32_Word *) hdr.e.e_ident == *(Elf32_Word *) "\177ELF") - { - Elf32_Phdr phdrs[hdr.e.e_phnum], *ph; - lseek (fd, hdr.e.e_phoff, SEEK_SET); - read (fd, phdrs, sizeof phdrs); - for (ph = phdrs; ph < &phdrs[sizeof phdrs/sizeof phdrs[0]]; ++ph) - if (ph->p_type == PT_LOAD) - { - vm_address_t buf; - vm_size_t offs = ph->p_offset & (ph->p_align - 1); - vm_size_t bufsz = round_page (ph->p_filesz + offs); - - buf = (vm_address_t) mmap (0, bufsz, - PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); - - lseek (fd, ph->p_offset, SEEK_SET); - read (fd, (void *)(buf + offs), ph->p_filesz); - - ph->p_memsz = ((ph->p_vaddr + ph->p_memsz + ph->p_align - 1) - & ~(ph->p_align - 1)); - ph->p_vaddr &= ~(ph->p_align - 1); - ph->p_memsz -= ph->p_vaddr; - - vm_allocate (t, (vm_address_t*)&ph->p_vaddr, ph->p_memsz, 0); - vm_write (t, ph->p_vaddr, buf, bufsz); - munmap ((caddr_t) buf, bufsz); - vm_protect (t, ph->p_vaddr, ph->p_memsz, 0, - ((ph->p_flags & PF_R) ? VM_PROT_READ : 0) | - ((ph->p_flags & PF_W) ? VM_PROT_WRITE : 0) | - ((ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0)); - } - return hdr.e.e_entry; - } - else - { - /* a.out */ - int magic = N_MAGIC (hdr.a); - int headercruft; - vm_address_t base = 0x10000; - int rndamount, amount; - vm_address_t bsspagestart, bssstart; - char *buf; - - headercruft = sizeof (struct exec) * (magic == ZMAGIC); - - amount = headercruft + hdr.a.a_text + hdr.a.a_data; - rndamount = round_page (amount); - buf = mmap (0, rndamount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); - lseek (fd, sizeof hdr.a - headercruft, SEEK_SET); - read (fd, buf, amount); - vm_allocate (t, &base, rndamount, 0); - vm_write (t, base, (vm_address_t) buf, rndamount); - if (magic != OMAGIC) - vm_protect (t, base, trunc_page (headercruft + hdr.a.a_text), - 0, VM_PROT_READ | VM_PROT_EXECUTE); - munmap ((caddr_t) buf, rndamount); - - bssstart = base + hdr.a.a_text + hdr.a.a_data + headercruft; - bsspagestart = round_page (bssstart); - vm_allocate (t, &bsspagestart, - hdr.a.a_bss - (bsspagestart - bssstart), 0); - - return hdr.a.a_entry; - } -} - - -void read_reply (); -void msg_thread (); - -/* Callbacks for boot_script.c; see boot_script.h. */ - -mach_port_t -boot_script_read_file (const char *filename) -{ - static const char msg[] = ": cannot open\n"; - int fd = useropen (filename, O_RDONLY, 0); - host_stat_t st; - error_t err; - mach_port_t memobj; - vm_address_t region; - - write (2, filename, strlen (filename)); - if (fd < 0) - { - write (2, msg, sizeof msg - 1); - host_exit (1); - } - else - write (2, msg + sizeof msg - 2, 1); - - host_fstat (fd, &st); - - err = default_pager_object_create (defpager, &memobj, - round_page (st.st_size)); - if (err) - { - static const char msg[] = "cannot create default-pager object\n"; - write (2, msg, sizeof msg - 1); - host_exit (1); - } - - region = 0; - vm_map (mach_task_self (), ®ion, round_page (st.st_size), - 0, 1, memobj, 0, 0, VM_PROT_ALL, VM_PROT_ALL, VM_INHERIT_NONE); - read (fd, (char *) region, st.st_size); - munmap ((caddr_t) region, round_page (st.st_size)); - - close (fd); - return memobj; -} - -int -boot_script_exec_cmd (void *hook, - mach_port_t task, char *path, int argc, - char **argv, char *strings, int stringlen) -{ - char *args, *p; - int arg_len, i; - size_t reg_size; - void *arg_pos; - vm_offset_t stack_start, stack_end; - vm_address_t startpc, str_start; - thread_t thread; - - write (2, path, strlen (path)); - for (i = 1; i < argc; ++i) - { - write (2, " ", 1); - write (2, argv[i], strlen (argv[i])); - } - write (2, "\r\n", 2); - - startpc = load_image (task, path); - arg_len = stringlen + (argc + 2) * sizeof (char *) + sizeof (integer_t); - arg_len += 5 * sizeof (int); - stack_end = VM_MAX_ADDRESS; - stack_start = VM_MAX_ADDRESS - 16 * 1024 * 1024; - vm_allocate (task, &stack_start, stack_end - stack_start, FALSE); - arg_pos = (void *) ((stack_end - arg_len) & ~(sizeof (natural_t) - 1)); - args = mmap (0, stack_end - trunc_page ((vm_offset_t) arg_pos), - PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); - str_start = ((vm_address_t) arg_pos - + (argc + 2) * sizeof (char *) + sizeof (integer_t)); - p = args + ((vm_address_t) arg_pos & (vm_page_size - 1)); - *(int *) p = argc; - p = (void *) p + sizeof (int); - for (i = 0; i < argc; i++) - { - *(char **) p = argv[i] - strings + (char *) str_start; - p = (void *) p + sizeof (char *); - } - *(char **) p = 0; - p = (void *) p + sizeof (char *); - *(char **) p = 0; - p = (void *) p + sizeof (char *); - memcpy (p, strings, stringlen); - bzero (args, (vm_offset_t) arg_pos & (vm_page_size - 1)); - vm_write (task, trunc_page ((vm_offset_t) arg_pos), (vm_address_t) args, - stack_end - trunc_page ((vm_offset_t) arg_pos)); - munmap ((caddr_t) args, - stack_end - trunc_page ((vm_offset_t) arg_pos)); - - thread_create (task, &thread); -#ifdef i386_THREAD_STATE_COUNT - { - struct i386_thread_state regs; - reg_size = i386_THREAD_STATE_COUNT; - thread_get_state (thread, i386_THREAD_STATE, - (thread_state_t) ®s, ®_size); - regs.eip = (int) startpc; - regs.uesp = (int) arg_pos; - thread_set_state (thread, i386_THREAD_STATE, - (thread_state_t) ®s, reg_size); - } -#elif defined(ALPHA_THREAD_STATE_COUNT) - { - struct alpha_thread_state regs; - reg_size = ALPHA_THREAD_STATE_COUNT; - thread_get_state (thread, ALPHA_THREAD_STATE, - (thread_state_t) ®s, ®_size); - regs.r30 = (natural_t) arg_pos; - regs.pc = (natural_t) startpc; - thread_set_state (thread, ALPHA_THREAD_STATE, - (thread_state_t) ®s, reg_size); - } -#else -# error needs to be ported -#endif - - thread_resume (thread); - mach_port_deallocate (mach_task_self (), thread); - return 0; -} - -const char *argp_program_version = STANDARD_HURD_VERSION (boot); - -static struct argp_option options[] = -{ - { "boot-root", 'D', "DIR", 0, - "Root of a directory tree in which to find files specified in BOOT-SCRIPT" }, - { "single-user", 's', 0, 0, - "Boot in single user mode" }, - { "kernel-command-line", 'c', "COMMAND LINE", 0, - "Simulated multiboot command line to supply" }, - { "pause" , 'd', 0, 0, - "Pause for user confirmation at various times during booting" }, - { "isig", 'I', 0, 0, - "Do not disable terminal signals, so you can suspend and interrupt boot."}, - { "device-map", 'm', "DEBICENAME=DEVICEFILE", 0, - "Map the device in subhurd to the device in the main Hurd."}, - { "defpager", 'p', "PAGER TRANSLATOR", 0, - "Specify the default pager for subhurd."}, - { "user", 'u', 0, 0, "For normal user."}, - { 0 } -}; -static char args_doc[] = "BOOT-SCRIPT"; -static char doc[] = "Boot a second hurd"; - -struct dev_map -{ - char *name; - mach_port_t port; - struct dev_map *next; -}; - -static struct dev_map *dev_map_head; - -static struct dev_map *add_dev_map (char *dev_name, char *dev_file) -{ - struct dev_map *map = (struct dev_map *) malloc (sizeof (*map)); - - assert (map); - map->name = dev_name; - map->port = file_name_lookup (dev_file, 0, 0); - if (map->port == MACH_PORT_NULL) - error (1, errno, "file_name_lookup: %s", dev_file); - map->next = dev_map_head; - dev_map_head = map; - return map; -} - -static struct dev_map *lookup_dev (char *dev_name) -{ - struct dev_map *map; - - for (map = dev_map_head; map; map = map->next) - { - if (strcmp (map->name, dev_name) == 0) - return map; - } - return NULL; -} - -char *pager_file; - -static error_t -parse_opt (int key, char *arg, struct argp_state *state) -{ - char *dev_file; - - switch (key) - { - size_t len; - - case 'c': kernel_command_line = arg; break; - - case 'D': useropen_dir = arg; break; - - case 'I': isig = 1; break; - - case 's': case 'd': - len = strlen (bootstrap_args); - if (len >= sizeof bootstrap_args - 1) - argp_error (state, "Too many bootstrap args"); - bootstrap_args[len++] = key; - bootstrap_args[len] = '\0'; - break; - - case 'm': - dev_file = strchr (arg, '='); - if (dev_file == NULL) - return ARGP_ERR_UNKNOWN; - *dev_file = 0; - add_dev_map (arg, dev_file+1); - break; - - case 'p': - pager_file = arg; - break; - - case 'u': - is_user = 1; - break; - - case ARGP_KEY_ARG: - if (state->arg_num == 0) - bootscript = arg; - else - return ARGP_ERR_UNKNOWN; - break; - - case ARGP_KEY_INIT: - state->child_inputs[0] = state->input; break; - - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - -static void -sigint (int signo) -{ - int kill_task (struct task_info *task_pi) - { - task_terminate (task_pi->task_port); - return 0; - } - - info ("receives an INT"); - foreach_task (kill_task); - exit (0); -} - -void -init_signal () -{ - struct sigaction sa; - sa.sa_handler = sigint; - sa.sa_flags = 0; /* No SA_RESTART! */ - sigemptyset(&sa.sa_mask); - if (sigaction (SIGINT, &sa, NULL)) - error (2, errno, "cannot set SIGHUP handler"); -} - -void -init_kernel_task () -{ - error_t err; - task_t pseudo_task; - task_t pseudo_kernel_task; - process_t real_kernel_task_proc; - process_t proc; - extern int create_pseudo_task (task_t real_task, task_t *ret_pseudo_task); - - err = task_create (mach_task_self (), 0, &pseudo_kernel_task); - if (err) - error (4, err, "cannot create the pseudo kernel task."); - - err = proc_task2proc (getproc (), pseudo_kernel_task, &proc); - if (err) - error (4, err, "cannot get the proc port for the pseudo kernel task."); - - err = task_set_bootstrap_port (pseudo_kernel_task, proc); - if (err) - error (4, err, "cannot set the pseudo kernel task's bootstrap port"); - - err = proc_pid2proc (getproc (), 2, &real_kernel_task_proc); - if (err) - error (4, err, "cannot get the kernel task's proc port"); - - vm_address_t kargv, kenvp; - err = proc_get_arg_locations (real_kernel_task_proc, &kargv, &kenvp); - if (err) - error (4, err, "cannot get the kernel task's argument"); - proc_set_arg_locations (proc, kargv, kenvp); - create_pseudo_task (pseudo_kernel_task, &pseudo_task); - // TODO the pseudo kernel task has to been destroyed after subhurd exits. -} - -FILE *logfile; - -int -main (int argc, char **argv, char **envp) -{ - error_t err; - mach_port_t foo; - char *buf = 0; - int i, len; - char *root_store_name; - const struct argp_child kids[] = { { &store_argp }, { 0 }}; - struct argp argp = { options, parse_opt, args_doc, doc, kids }; - struct store_argp_params store_argp_params = { 0 }; - mach_port_t subhurd_privileged_host_port = MACH_PORT_NULL; - - LOG_START (); - - argp_parse (&argp, argc, argv, 0, 0, &store_argp_params); - err = store_parsed_name (store_argp_params.result, &root_store_name); - if (err) - error (2, err, "store_parsed_name"); - - err = store_parsed_open (store_argp_params.result, 0, &root_store); - if (err) - error (4, err, "%s", root_store_name); - - init_signal (); - if (!is_user) - { - get_privileged_ports (&privileged_host_port, &master_device_port); - defpager = MACH_PORT_NULL; - err = vm_set_default_memory_manager (privileged_host_port, &defpager); - if (err) - error (4, err, "vm_set_default_memory_manager"); - subhurd_privileged_host_port = privileged_host_port; - } - else - { - port_bucket = ports_create_bucket (); - task_portclass = ports_create_class (clean_pseudo_task, 0); - priv_host_portclass = ports_create_class (destroy_priv_host, 0); - exc_portclass = ports_create_class (0, 0); - other_portclass = ports_create_class (0, 0); - init_kernel_task (); - cthread_detach (cthread_fork ((cthread_fn_t) mach_proxy_thread, - (any_t) 0)); - { - mach_port_t priv_host; - get_privileged_ports (&priv_host, NULL); - defpager = MACH_PORT_NULL; - err = vm_set_default_memory_manager (priv_host, &defpager); - if (err) - error (4, err, "vm_set_default_memory_manager"); - mach_port_deallocate (mach_task_self (), priv_host); - } -// if (pager_file == NULL) -// error (4, 0, "The default pager must be specified for subhurd."); -// defpager = file_name_lookup (pager_file, O_EXEC, 0); -// if (defpager == MACH_PORT_NULL) -// error (4, errno, "file_name_look: %s", pager_file); - - /* Initialize the pseudo privileged host port. */ - err = ports_create_port (priv_host_portclass, port_bucket, - sizeof (struct port_info), - &pseudo_priv_host_pi); - if (err) - error (4, err, "fail to create the pseudo privileged host port"); - subhurd_privileged_host_port = ports_get_send_right (pseudo_priv_host_pi); - ports_port_deref (pseudo_priv_host_pi); - } - - strcat (bootstrap_args, "f"); - - mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_PORT_SET, - &receive_set); - - if (root_store->class == &store_device_class && root_store->name - && (root_store->flags & STORE_ENFORCED) - && root_store->num_runs == 1 && root_store->runs[0].start == 0) - /* Let known device nodes pass through directly. */ - bootdevice = root_store->name; - else - /* Pass a magic value that we can use to do I/O to ROOT_STORE. */ - { - bootdevice = "pseudo-root"; - mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, - &pseudo_root); - mach_port_move_member (mach_task_self (), pseudo_root, receive_set); - } - - /* Initialize the pseudo master device port. */ - mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, - &pseudo_master_device_port); - mach_port_insert_right (mach_task_self (), - pseudo_master_device_port, - pseudo_master_device_port, - MACH_MSG_TYPE_MAKE_SEND); - mach_port_move_member (mach_task_self (), pseudo_master_device_port, - receive_set); - mach_port_request_notification (mach_task_self (), pseudo_master_device_port, - MACH_NOTIFY_NO_SENDERS, 1, - pseudo_master_device_port, - MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo); - if (foo != MACH_PORT_NULL) - mach_port_deallocate (mach_task_self (), foo); - - /* Initialize the pseudo console port. */ - mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, - &pseudo_console); - mach_port_move_member (mach_task_self (), pseudo_console, receive_set); - mach_port_request_notification (mach_task_self (), pseudo_console, - MACH_NOTIFY_NO_SENDERS, 1, pseudo_console, - MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo); - if (foo != MACH_PORT_NULL) - mach_port_deallocate (mach_task_self (), foo); - - if (kernel_command_line == 0) - asprintf (&kernel_command_line, "%s %s root=%s", - argv[0], bootstrap_args, bootdevice); - - /* Initialize boot script variables. */ - if (boot_script_set_variable ("host-port", VAL_PORT, - (int) subhurd_privileged_host_port) - || boot_script_set_variable ("device-port", VAL_PORT, - (integer_t) pseudo_master_device_port) - || boot_script_set_variable ("kernel-command-line", VAL_STR, - (integer_t) kernel_command_line) - || boot_script_set_variable ("root-device", - VAL_STR, (integer_t) bootdevice) - || boot_script_set_variable ("boot-args", - VAL_STR, (integer_t) bootstrap_args)) - { - static const char msg[] = "error setting variable"; - - write (2, msg, strlen (msg)); - host_exit (1); - } - - /* Turn each `FOO=BAR' word in the command line into a boot script - variable ${FOO} with value BAR. */ - { - int len = strlen (kernel_command_line) + 1; - char *s = memcpy (alloca (len), kernel_command_line, len); - char *word; - - while ((word = strsep (&s, " \t")) != 0) - { - char *eq = strchr (word, '='); - if (eq == 0) - continue; - *eq++ = '\0'; - err = boot_script_set_variable (word, VAL_STR, (integer_t) eq); - if (err) - { - char *msg; - asprintf (&msg, "cannot set boot-script variable %s: %s\n", - word, boot_script_error_string (err)); - assert (msg); - write (2, msg, strlen (msg)); - free (msg); - host_exit (1); - } - } - } - - /* Parse the boot script. */ - { - char *p, *line; - static const char filemsg[] = "Can't open boot script\n"; - static const char memmsg[] = "Not enough memory\n"; - int amt, fd, err; - - fd = open (bootscript, O_RDONLY, 0); - if (fd < 0) - { - write (2, filemsg, sizeof (filemsg)); - host_exit (1); - } - p = buf = malloc (500); - if (!buf) - { - write (2, memmsg, sizeof (memmsg)); - host_exit (1); - } - len = 500; - amt = 0; - while (1) - { - i = read (fd, p, len - (p - buf)); - if (i <= 0) - break; - p += i; - amt += i; - if (p == buf + len) - { - char *newbuf; - - len += 500; - newbuf = realloc (buf, len); - if (!newbuf) - { - write (2, memmsg, sizeof (memmsg)); - host_exit (1); - } - p = newbuf + (p - buf); - buf = newbuf; - } - } - line = p = buf; - while (1) - { - while (p < buf + amt && *p != '\n') - p++; - *p = '\0'; - err = boot_script_parse_line (0, line); - if (err) - { - char *str; - int i; - - str = boot_script_error_string (err); - i = strlen (str); - write (2, str, i); - write (2, " in `", 5); - write (2, line, strlen (line)); - write (2, "'\n", 2); - host_exit (1); - } - if (p == buf + amt) - break; - line = ++p; - } - } - - if (index (bootstrap_args, 'd')) - { - static const char msg[] = "Pausing. . ."; - char c; - write (2, msg, sizeof (msg) - 1); - read (0, &c, 1); - } - - init_termstate (); - - /* The boot script has now been parsed into internal data structures. - Now execute its directives. */ - { - int err; - - err = boot_script_exec (); - if (err) - { - char *str = boot_script_error_string (err); - int i = strlen (str); - - write (2, str, i); - host_exit (1); - } - free (buf); - } - - mach_port_deallocate (mach_task_self (), pseudo_master_device_port); - if (is_user) - mach_port_deallocate (mach_task_self (), subhurd_privileged_host_port); - - cthread_detach (cthread_fork ((cthread_fn_t) msg_thread, (any_t) 0)); - - for (;;) - { - fd_set rmask; - FD_ZERO (&rmask); - FD_SET (0, &rmask); - if (select (1, &rmask, 0, 0, 0) == 1) - read_reply (); - else /* We hosed */ - error (5, errno, "select"); - } - - LOG_END (); -/* mach_msg_server (request_server, __vm_page_size * 2, receive_set); */ -} - -void -msg_thread() -{ - while (1) - mach_msg_server (request_server, 0, receive_set); -} - - -enum read_type -{ - DEV_READ, - DEV_READI, - IO_READ, -}; -struct qr -{ - enum read_type type; - mach_port_t reply_port; - mach_msg_type_name_t reply_type; - int amount; - struct qr *next; -}; -struct qr *qrhead, *qrtail; - -/* Queue a read for later reply. */ -kern_return_t -queue_read (enum read_type type, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - int amount) -{ - struct qr *qr; - - qr = malloc (sizeof (struct qr)); - if (!qr) - return D_NO_MEMORY; - - spin_lock (&queuelock); - - qr->type = type; - qr->reply_port = reply_port; - qr->reply_type = reply_type; - qr->amount = amount; - qr->next = 0; - if (qrtail) - qrtail->next = qr; - else - qrhead = qrtail = qr; - - spin_unlock (&queuelock); - return D_SUCCESS; -} - -/* TRUE if there's data available on stdin, which should be used to satisfy - console read requests. */ -static int should_read = 0; - -/* Reply to a queued read. */ -void -read_reply () -{ - int avail; - struct qr *qr; - char * buf; - int amtread; - - /* By forcing SHOULD_READ to true before trying the lock, we ensure that - either we get the lock ourselves or that whoever currently holds the - lock will service this read when he unlocks it. */ - should_read = 1; - if (! spin_try_lock (&readlock)) - return; - - /* Since we're commited to servicing the read, no one else need do so. */ - should_read = 0; - - ioctl (0, FIONREAD, &avail); - if (!avail) - { - spin_unlock (&readlock); - return; - } - - spin_lock (&queuelock); - - if (!qrhead) - { - spin_unlock (&queuelock); - spin_unlock (&readlock); - return; - } - - qr = qrhead; - qrhead = qr->next; - if (qr == qrtail) - qrtail = 0; - - spin_unlock (&queuelock); - - if (qr->type == DEV_READ) - buf = mmap (0, qr->amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); - else - buf = alloca (qr->amount); - amtread = read (0, buf, qr->amount); - - spin_unlock (&readlock); - - switch (qr->type) - { - case DEV_READ: - if (amtread >= 0) - ds_device_read_reply (qr->reply_port, qr->reply_type, 0, - (io_buf_ptr_t) buf, amtread); - else - ds_device_read_reply (qr->reply_port, qr->reply_type, errno, 0, 0); - break; - - case DEV_READI: - if (amtread >= 0) - ds_device_read_reply_inband (qr->reply_port, qr->reply_type, 0, - buf, amtread); - else - ds_device_read_reply_inband (qr->reply_port, qr->reply_type, errno, - 0, 0); - break; - - case IO_READ: - if (amtread >= 0) - io_read_reply (qr->reply_port, qr->reply_type, 0, - buf, amtread); - else - io_read_reply (qr->reply_port, qr->reply_type, errno, 0, 0); - break; - } - - free (qr); -} - -/* Unlock READLOCK, and also service any new read requests that it was - blocking. */ -static void -unlock_readlock () -{ - spin_unlock (&readlock); - while (should_read) - read_reply (); -} - -/* - * Handle bootstrap requests. - */ -/* These two functions from .../mk/bootstrap/default_pager.c. */ - -kern_return_t -do_bootstrap_privileged_ports(bootstrap, hostp, devicep) - mach_port_t bootstrap; - mach_port_t *hostp, *devicep; -{ - if (is_user) - /* I cannot use ports_get_right() here, - * because the port will be copied to the client. */ - *hostp = pseudo_priv_host_pi->port_right; - else - *hostp = privileged_host_port; - *devicep = pseudo_master_device_port; - return KERN_SUCCESS; -} - -void -bootstrap_compat(in, out) - mach_msg_header_t *in, *out; -{ - mig_reply_header_t *reply = (mig_reply_header_t *) out; - mach_msg_return_t mr; - - struct imsg { - mach_msg_header_t hdr; - mach_msg_type_t port_desc_1; - mach_port_t port_1; - mach_msg_type_t port_desc_2; - mach_port_t port_2; - } imsg; - - /* - * Send back the host and device ports. - */ - - imsg.hdr.msgh_bits = MACH_MSGH_BITS_COMPLEX | - MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(in->msgh_bits), 0); - /* msgh_size doesn't need to be initialized */ - imsg.hdr.msgh_remote_port = in->msgh_remote_port; - imsg.hdr.msgh_local_port = MACH_PORT_NULL; - /* msgh_seqno doesn't need to be initialized */ - imsg.hdr.msgh_id = in->msgh_id + 100; /* this is a reply msg */ - - imsg.port_desc_1.msgt_name = MACH_MSG_TYPE_COPY_SEND; - imsg.port_desc_1.msgt_size = (sizeof(mach_port_t) * 8); - imsg.port_desc_1.msgt_number = 1; - imsg.port_desc_1.msgt_inline = TRUE; - imsg.port_desc_1.msgt_longform = FALSE; - imsg.port_desc_1.msgt_deallocate = FALSE; - imsg.port_desc_1.msgt_unused = 0; - - if (is_user) - imsg.port_1 = pseudo_priv_host_pi->port_right; - else - imsg.port_1 = privileged_host_port; - - imsg.port_desc_2 = imsg.port_desc_1; - - imsg.port_desc_2.msgt_name = MACH_MSG_TYPE_MAKE_SEND; - imsg.port_2 = pseudo_master_device_port; - - /* - * Send the reply message. - * (mach_msg_server can not do this, because the reply - * is not in standard format.) - */ - - mr = mach_msg(&imsg.hdr, MACH_SEND_MSG, - sizeof imsg, 0, MACH_PORT_NULL, - MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - if (mr != MACH_MSG_SUCCESS) - (void) mach_port_deallocate(mach_task_self (), - imsg.hdr.msgh_remote_port); - - /* - * Tell mach_msg_server to do nothing. - */ - - reply->RetCode = MIG_NO_REPLY; -} - -/* Implementation of device interface */ - -kern_return_t -ds_device_open (mach_port_t master_port, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - dev_mode_t mode, - dev_name_t name, - mach_port_t *device, - mach_msg_type_name_t *devicetype) -{ - struct dev_map *map; - - if (master_port != pseudo_master_device_port) - return D_INVALID_OPERATION; - - debug ("open %s", name); - if (!strcmp (name, "console")) - { -#if 0 - mach_port_insert_right (mach_task_self (), pseudo_console, - pseudo_console, MACH_MSG_TYPE_MAKE_SEND); - console_send_rights++; -#endif - console_mscount++; - *device = pseudo_console; - *devicetype = MACH_MSG_TYPE_MAKE_SEND; - return 0; - } - else if (strcmp (name, "pseudo-root") == 0) - /* Magic root device. */ - { - *device = pseudo_root; - *devicetype = MACH_MSG_TYPE_MAKE_SEND; - return 0; - } - - map = lookup_dev (name); - if (map) - { - error_t err; - *devicetype = MACH_MSG_TYPE_MOVE_SEND; - err = device_open (map->port, mode, "", device); - return err; - } - - if (is_user) - return D_NO_SUCH_DEVICE; - else - { - *devicetype = MACH_MSG_TYPE_MOVE_SEND; - return device_open (master_device_port, mode, name, device); - } -} - -kern_return_t -ds_device_close (device_t device) -{ - if (device != pseudo_console && device != pseudo_root) - return D_NO_SUCH_DEVICE; - return 0; -} - -kern_return_t -ds_device_write (device_t device, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - dev_mode_t mode, - recnum_t recnum, - io_buf_ptr_t data, - size_t datalen, - int *bytes_written) -{ - if (device == pseudo_console) - { -#if 0 - if (console_send_rights) - { - mach_port_mod_refs (mach_task_self (), pseudo_console, - MACH_PORT_TYPE_SEND, -console_send_rights); - console_send_rights = 0; - } -#endif - - *bytes_written = write (1, data, datalen); - - return (*bytes_written == -1 ? D_IO_ERROR : D_SUCCESS); - } - else if (device == pseudo_root) - { - size_t wrote; - if (store_write (root_store, recnum, data, datalen, &wrote) != 0) - return D_IO_ERROR; - *bytes_written = wrote; - return D_SUCCESS; - } - else - return D_NO_SUCH_DEVICE; -} - -kern_return_t -ds_device_write_inband (device_t device, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - dev_mode_t mode, - recnum_t recnum, - io_buf_ptr_inband_t data, - size_t datalen, - int *bytes_written) -{ - if (device == pseudo_console) - { -#if 0 - if (console_send_rights) - { - mach_port_mod_refs (mach_task_self (), pseudo_console, - MACH_PORT_TYPE_SEND, -console_send_rights); - console_send_rights = 0; - } -#endif - - *bytes_written = write (1, data, datalen); - - return (*bytes_written == -1 ? D_IO_ERROR : D_SUCCESS); - } - else if (device == pseudo_root) - { - size_t wrote; - if (store_write (root_store, recnum, data, datalen, &wrote) != 0) - return D_IO_ERROR; - *bytes_written = wrote; - return D_SUCCESS; - } - else - return D_NO_SUCH_DEVICE; -} - -kern_return_t -ds_device_read (device_t device, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - dev_mode_t mode, - recnum_t recnum, - int bytes_wanted, - io_buf_ptr_t *data, - size_t *datalen) -{ - if (device == pseudo_console) - { - int avail; - -#if 0 - if (console_send_rights) - { - mach_port_mod_refs (mach_task_self (), pseudo_console, - MACH_PORT_TYPE_SEND, -console_send_rights); - console_send_rights = 0; - } -#endif - - spin_lock (&readlock); - ioctl (0, FIONREAD, &avail); - if (avail) - { - *data = mmap (0, bytes_wanted, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); - *datalen = read (0, *data, bytes_wanted); - unlock_readlock (); - return (*datalen == -1 ? D_IO_ERROR : D_SUCCESS); - } - else - { - kern_return_t err; - - unlock_readlock (); - err = queue_read (DEV_READ, reply_port, reply_type, bytes_wanted); - if (err) - return err; - return MIG_NO_REPLY; - } - } - else if (device == pseudo_root) - { - *datalen = 0; - return - (store_read (root_store, recnum, bytes_wanted, (void **)data, datalen) == 0 - ? D_SUCCESS - : D_IO_ERROR); - } - else - return D_NO_SUCH_DEVICE; -} - -kern_return_t -ds_device_read_inband (device_t device, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - dev_mode_t mode, - recnum_t recnum, - int bytes_wanted, - io_buf_ptr_inband_t data, - size_t *datalen) -{ - if (device == pseudo_console) - { - int avail; - -#if 0 - if (console_send_rights) - { - mach_port_mod_refs (mach_task_self (), pseudo_console, - MACH_PORT_TYPE_SEND, -console_send_rights); - console_send_rights = 0; - } -#endif - - spin_lock (&readlock); - ioctl (0, FIONREAD, &avail); - if (avail) - { - *datalen = read (0, data, bytes_wanted); - unlock_readlock (); - return (*datalen == -1 ? D_IO_ERROR : D_SUCCESS); - } - else - { - kern_return_t err; - - unlock_readlock (); - err = queue_read (DEV_READI, reply_port, reply_type, bytes_wanted); - if (err) - return err; - return MIG_NO_REPLY; - } - } - else if (device == pseudo_root) - { - error_t err; - void *returned = data; - - *datalen = bytes_wanted; - err = - store_read (root_store, recnum, bytes_wanted, (void **)&returned, datalen); - - if (! err) - { - if (returned != data) - { - bcopy (returned, (void *)data, *datalen); - munmap ((caddr_t) returned, *datalen); - } - return D_SUCCESS; - } - else - return D_IO_ERROR; - } - else - return D_NO_SUCH_DEVICE; -} - -kern_return_t -ds_xxx_device_set_status (device_t device, - dev_flavor_t flavor, - dev_status_t status, - size_t statu_cnt) -{ - if (device != pseudo_console) - return D_NO_SUCH_DEVICE; - return D_INVALID_OPERATION; -} - -kern_return_t -ds_xxx_device_get_status (device_t device, - dev_flavor_t flavor, - dev_status_t status, - size_t *statuscnt) -{ - if (device != pseudo_console && device != pseudo_root) - return D_NO_SUCH_DEVICE; - return D_INVALID_OPERATION; -} - -kern_return_t -ds_xxx_device_set_filter (device_t device, - mach_port_t rec, - int pri, - filter_array_t filt, - size_t len) -{ - if (device != pseudo_console && device != pseudo_root) - return D_NO_SUCH_DEVICE; - return D_INVALID_OPERATION; -} - -kern_return_t -ds_device_map (device_t device, - vm_prot_t prot, - vm_offset_t offset, - vm_size_t size, - memory_object_t *pager, - int unmap) -{ - if (device != pseudo_console && device != pseudo_root) - return D_NO_SUCH_DEVICE; - return D_INVALID_OPERATION; -} - -kern_return_t -ds_device_set_status (device_t device, - dev_flavor_t flavor, - dev_status_t status, - size_t statuslen) -{ - if (device != pseudo_console && device != pseudo_root) - return D_NO_SUCH_DEVICE; - return D_INVALID_OPERATION; -} - -kern_return_t -ds_device_get_status (device_t device, - dev_flavor_t flavor, - dev_status_t status, - size_t *statuslen) -{ - if (device == pseudo_console) - return D_INVALID_OPERATION; - else if (device == pseudo_root) - if (flavor == DEV_GET_SIZE) - if (*statuslen < DEV_GET_SIZE_COUNT) - return D_INVALID_SIZE; - else - { - status[DEV_GET_SIZE_DEVICE_SIZE] = root_store->size; - status[DEV_GET_SIZE_RECORD_SIZE] = root_store->block_size; - *statuslen = DEV_GET_SIZE_COUNT; - return D_SUCCESS; - } - else - return D_INVALID_OPERATION; - else - return D_NO_SUCH_DEVICE; -} - -kern_return_t -ds_device_set_filter (device_t device, - mach_port_t receive_port, - int priority, - filter_array_t filter, - size_t filterlen) -{ - if (device != pseudo_console && device != pseudo_root) - return D_NO_SUCH_DEVICE; - return D_INVALID_OPERATION; -} - - -/* Implementation of notify interface */ -kern_return_t -do_mach_notify_port_deleted (mach_port_t notify, - mach_port_t name) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_msg_accepted (mach_port_t notify, - mach_port_t name) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_port_destroyed (mach_port_t notify, - mach_port_t port) -{ - return EOPNOTSUPP; -} - -boolean_t pseudo_priv_host_destroyed = FALSE; - -void -destroy_priv_host (void *pi) -{ - pseudo_priv_host_destroyed = TRUE; - info ("pseudo privileged host port is destroyed"); -} - -kern_return_t -do_mach_notify_no_senders (mach_port_t notify, - mach_port_mscount_t mscount) -{ - static int no_console; - mach_port_t foo; - error_t err = EOPNOTSUPP; - - if (notify == pseudo_master_device_port) - { - info ("pseudo master device port has no senders"); - /* for the root */ - if (no_console && !is_user) - goto bye; - /* for the normal user */ - if (no_console && is_user && pseudo_priv_host_destroyed) - goto bye; - pseudo_master_device_port = MACH_PORT_NULL; - return 0; - } - if (pseudo_priv_host_pi->port_right == notify && is_user) - { - if (no_console && pseudo_master_device_port == MACH_PORT_NULL) - goto bye; - pseudo_priv_host_destroyed = TRUE; - return 0; - } - if (notify == pseudo_console) - { - info ("pseudo console has no senders"); - if ( - /* for the root */ - (mscount == console_mscount && - pseudo_master_device_port == MACH_PORT_NULL && - !is_user) || - /* for the normal user */ - (mscount == console_mscount && - pseudo_master_device_port == MACH_PORT_NULL && - pseudo_priv_host_destroyed && - is_user)) - { - bye: - restore_termstate (); - write (2, "bye\n", 4); - host_exit (0); - } - else - { - no_console = (mscount == console_mscount); - info ("no console: %d", no_console); - - mach_port_request_notification (mach_task_self (), pseudo_console, - MACH_NOTIFY_NO_SENDERS, - console_mscount == mscount - ? mscount + 1 - : console_mscount, - pseudo_console, - MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo); - if (foo != MACH_PORT_NULL) - mach_port_deallocate (mach_task_self (), foo); - } - } - - err = ports_do_mach_notify_no_senders (notify, mscount); - - return err; -} - -kern_return_t -do_mach_notify_send_once (mach_port_t notify) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_dead_name (mach_port_t notify, - mach_port_t name) -{ -#if 0 - if (name == child_task && notify == bootport) - host_exit (0); -#endif - return EOPNOTSUPP; -} - - -/* Implementation of the Hurd I/O interface, which - we support for the console port only. */ - -kern_return_t -S_io_write (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - char *data, - mach_msg_type_number_t datalen, - off_t offset, - mach_msg_type_number_t *amtwritten) -{ - if (object != pseudo_console) - return EOPNOTSUPP; - -#if 0 - if (console_send_rights) - { - mach_port_mod_refs (mach_task_self (), pseudo_console, - MACH_PORT_TYPE_SEND, -console_send_rights); - console_send_rights = 0; - } -#endif - - *amtwritten = write (1, data, datalen); - return *amtwritten == -1 ? errno : 0; -} - -kern_return_t -S_io_read (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - char **data, - mach_msg_type_number_t *datalen, - off_t offset, - mach_msg_type_number_t amount) -{ - mach_msg_type_number_t avail; - - if (object != pseudo_console) - return EOPNOTSUPP; - -#if 0 - if (console_send_rights) - { - mach_port_mod_refs (mach_task_self (), pseudo_console, - MACH_PORT_TYPE_SEND, -console_send_rights); - console_send_rights = 0; - } -#endif - - spin_lock (&readlock); - ioctl (0, FIONREAD, &avail); - if (avail) - { - if (amount > *datalen) - *data = mmap (0, amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); - *datalen = read (0, *data, amount); - unlock_readlock (); - return *datalen == -1 ? errno : 0; - } - else - { - kern_return_t err; - unlock_readlock (); - err = queue_read (IO_READ, reply_port, reply_type, amount); - if (err) - return err; - return MIG_NO_REPLY; - } -} - -kern_return_t -S_io_seek (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - off_t offset, - int whence, - off_t *newp) -{ - return object == pseudo_console ? ESPIPE : EOPNOTSUPP; -} - -kern_return_t -S_io_readable (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - mach_msg_type_number_t *amt) -{ - if (object != pseudo_console) - return EOPNOTSUPP; - ioctl (0, FIONREAD, amt); - return 0; -} - -kern_return_t -S_io_set_all_openmodes (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - int bits) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_get_openmodes (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - int *modes) -{ - *modes = O_READ | O_WRITE; - return object == pseudo_console ? 0 : EOPNOTSUPP; -} - -kern_return_t -S_io_set_some_openmodes (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - int bits) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_clear_some_openmodes (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - int bits) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_async (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - mach_port_t notify, - mach_port_t *id, - mach_msg_type_name_t *idtype) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_mod_owner (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - pid_t owner) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_get_owner (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - pid_t *owner) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_get_icky_async_id (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - mach_port_t *id, - mach_msg_type_name_t *idtype) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_select (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - int *type) -{ - fd_set r, w, x; - int n; - - if (object != pseudo_console) - return EOPNOTSUPP; - - FD_ZERO (&r); - FD_ZERO (&w); - FD_ZERO (&x); - FD_SET (0, &r); - FD_SET (0, &w); - FD_SET (0, &x); - - n = select (1, - (*type & SELECT_READ) ? &r : 0, - (*type & SELECT_WRITE) ? &w : 0, - (*type & SELECT_URG) ? &x : 0, - 0); - if (n < 0) - return errno; - - if (! FD_ISSET (0, &r)) - *type &= ~SELECT_READ; - if (! FD_ISSET (0, &w)) - *type &= ~SELECT_WRITE; - if (! FD_ISSET (0, &x)) - *type &= ~SELECT_URG; - - return 0; -} - -kern_return_t -S_io_stat (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - struct stat *st) -{ - if (object != pseudo_console) - return EOPNOTSUPP; - - bzero (st, sizeof (struct stat)); - st->st_blksize = 1024; - return 0; -} - -kern_return_t -S_io_reauthenticate (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - mach_port_t rend) -{ - uid_t *gu, *au; - gid_t *gg, *ag; - size_t gulen = 0, aulen = 0, gglen = 0, aglen = 0; - error_t err; - - err = mach_port_insert_right (mach_task_self (), object, object, - MACH_MSG_TYPE_MAKE_SEND); - assert_perror (err); - - if (! auth_server_authenticate (authserver, - rend, MACH_MSG_TYPE_COPY_SEND, - object, MACH_MSG_TYPE_COPY_SEND, - &gu, &gulen, - &au, &aulen, - &gg, &gglen, - &ag, &aglen)) - { - mig_deallocate ((vm_address_t) gu, gulen * sizeof *gu); - mig_deallocate ((vm_address_t) au, aulen * sizeof *gu); - mig_deallocate ((vm_address_t) gg, gglen * sizeof *gu); - mig_deallocate ((vm_address_t) au, aulen * sizeof *gu); - } - mach_port_deallocate (mach_task_self (), rend); - mach_port_deallocate (mach_task_self (), object); - - return 0; -} - -kern_return_t -S_io_restrict_auth (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - mach_port_t *newobject, - mach_msg_type_name_t *newobjtype, - uid_t *uids, - size_t nuids, - uid_t *gids, - size_t ngids) -{ - if (object != pseudo_console) - return EOPNOTSUPP; - *newobject = pseudo_console; - *newobjtype = MACH_MSG_TYPE_MAKE_SEND; - console_mscount++; - return 0; -} - -kern_return_t -S_io_duplicate (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - mach_port_t *newobj, - mach_msg_type_name_t *newobjtype) -{ - if (object != pseudo_console) - return EOPNOTSUPP; - *newobj = pseudo_console; - *newobjtype = MACH_MSG_TYPE_MAKE_SEND; - console_mscount++; - return 0; -} - -kern_return_t -S_io_server_version (mach_port_t object, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - char *name, - int *maj, - int *min, - int *edit) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_map (mach_port_t obj, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - mach_port_t *rd, - mach_msg_type_name_t *rdtype, - mach_port_t *wr, - mach_msg_type_name_t *wrtype) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_map_cntl (mach_port_t obj, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - mach_port_t *mem, - mach_msg_type_name_t *memtype) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_get_conch (mach_port_t obj, - mach_port_t reply_port, - mach_msg_type_name_t reply_type) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_release_conch (mach_port_t obj, - mach_port_t reply_port, - mach_msg_type_name_t reply_type) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_eofnotify (mach_port_t obj, - mach_port_t reply_port, - mach_msg_type_name_t reply_type) - -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_prenotify (mach_port_t obj, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - vm_offset_t start, - vm_offset_t end) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_postnotify (mach_port_t obj, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - vm_offset_t start, - vm_offset_t end) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_readsleep (mach_port_t obj, - mach_port_t reply_port, - mach_msg_type_name_t reply_type) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_readnotify (mach_port_t obj, - mach_port_t reply_port, - mach_msg_type_name_t reply_type) -{ - return EOPNOTSUPP; -} - - -kern_return_t -S_io_sigio (mach_port_t obj, - mach_port_t reply_port, - mach_msg_type_name_t reply_type) -{ - return EOPNOTSUPP; -} - - -kern_return_t -S_io_pathconf (mach_port_t obj, - mach_port_t reply_port, - mach_msg_type_name_t reply_type, - int name, int *value) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_identity (mach_port_t obj, - mach_port_t reply, - mach_msg_type_name_t replytype, - mach_port_t *id, - mach_msg_type_name_t *idtype, - mach_port_t *fsid, - mach_msg_type_name_t *fsidtype, - ino_t *fileno) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_io_revoke (mach_port_t obj, - mach_port_t reply, mach_msg_type_name_t replyPoly) -{ - return EOPNOTSUPP; -} - - - -/* Implementation of the Hurd terminal driver interface, which we only - support on the console device. */ - -kern_return_t -S_termctty_open_terminal (mach_port_t object, - int flags, - mach_port_t *result, - mach_msg_type_name_t *restype) -{ - return EOPNOTSUPP; -} - -kern_return_t -S_term_getctty (mach_port_t object, - mach_port_t *cttyid, mach_msg_type_name_t *cttyPoly) -{ - static mach_port_t id = MACH_PORT_NULL; - - if (object != pseudo_console) - return EOPNOTSUPP; - - if (id == MACH_PORT_NULL) - mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_DEAD_NAME, &id); - - *cttyid = id; - *cttyPoly = MACH_MSG_TYPE_COPY_SEND; - return 0; -} - - -kern_return_t S_term_open_ctty -( - io_t terminal, - pid_t pid, - pid_t pgrp, - mach_port_t *newtty, - mach_msg_type_name_t *newttytype -) -{ return EOPNOTSUPP; } - -kern_return_t S_term_set_nodename -( - io_t terminal, - string_t name -) -{ return EOPNOTSUPP; } - -kern_return_t S_term_get_nodename -( - io_t terminal, - string_t name -) -{ return EOPNOTSUPP; } - -kern_return_t S_term_get_peername -( - io_t terminal, - string_t name -) -{ return EOPNOTSUPP; } - -kern_return_t S_term_set_filenode -( - io_t terminal, - file_t filenode -) -{ return EOPNOTSUPP; } - -kern_return_t S_term_get_bottom_type -( - io_t terminal, - int *ttype -) -{ return EOPNOTSUPP; } - -kern_return_t S_term_on_machdev -( - io_t terminal, - mach_port_t machdev -) -{ return EOPNOTSUPP; } - -kern_return_t S_term_on_hurddev -( - io_t terminal, - io_t hurddev -) -{ return EOPNOTSUPP; } - -kern_return_t S_term_on_pty -( - io_t terminal, - io_t *ptymaster -) -{ return EOPNOTSUPP; } diff --git a/boot-proxy-exc/boot_script.c b/boot-proxy-exc/boot_script.c deleted file mode 100644 index f95cc5c4..00000000 --- a/boot-proxy-exc/boot_script.c +++ /dev/null @@ -1,791 +0,0 @@ -/* Boot script parser for Mach. */ - -/* Written by Shantanu Goel (goel@cs.columbia.edu). */ - -#include <mach/mach_types.h> -#if !KERNEL || OSKIT_MACH -#include <string.h> -#endif -#include "boot_script.h" - - -/* This structure describes a symbol. */ -struct sym -{ - /* Symbol name. */ - const char *name; - - /* Type of value returned by function. */ - int type; - - /* Symbol value. */ - integer_t val; - - /* For function symbols; type of value returned by function. */ - int ret_type; - - /* For function symbols; if set, execute function at the time - of command execution, not during parsing. A function with - this field set must also have `no_arg' set. Also, the function's - `val' argument will always be NULL. */ - int run_on_exec; -}; - -/* Additional values symbols can take. - These are only used internally. */ -#define VAL_SYM 10 /* symbol table entry */ -#define VAL_FUNC 11 /* function pointer */ - -/* This structure describes an argument. */ -struct arg -{ - /* Argument text copied verbatim. 0 if none. */ - char *text; - - /* Type of value assigned. 0 if none. */ - int type; - - /* Argument value. */ - integer_t val; -}; - -/* List of commands. */ -static struct cmd **cmds = 0; - -/* Amount allocated for `cmds'. */ -static int cmds_alloc = 0; - -/* Next available slot in `cmds'. */ -static int cmds_index = 0; - -/* Symbol table. */ -static struct sym **symtab = 0; - -/* Amount allocated for `symtab'. */ -static int symtab_alloc = 0; - -/* Next available slot in `symtab'. */ -static int symtab_index = 0; - -/* Create a task and suspend it. */ -static int -create_task (struct cmd *cmd, int *val) -{ - int err = boot_script_task_create (cmd); - *val = (int) cmd->task; - return err; -} - -/* Resume a task. */ -static int -resume_task (struct cmd *cmd, int *val) -{ - return boot_script_task_resume (cmd); -} - -/* Resume a task when the user hits return. */ -static int -prompt_resume_task (struct cmd *cmd, int *val) -{ - return boot_script_prompt_task_resume (cmd); -} - -/* List of builtin symbols. */ -static struct sym builtin_symbols[] = -{ - { "task-create", VAL_FUNC, (integer_t) create_task, VAL_TASK, 0 }, - { "task-resume", VAL_FUNC, (integer_t) resume_task, VAL_NONE, 1 }, - { "prompt-task-resume", - VAL_FUNC, (integer_t) prompt_resume_task, VAL_NONE, 1 }, -}; -#define NUM_BUILTIN (sizeof (builtin_symbols) / sizeof (builtin_symbols[0])) - -/* Free CMD and all storage associated with it. - If ABORTING is set, terminate the task associated with CMD, - otherwise just deallocate the send right. */ -static void -free_cmd (struct cmd *cmd, int aborting) -{ - if (cmd->task) - boot_script_free_task (cmd->task, aborting); - if (cmd->args) - { - int i; - for (i = 0; i < cmd->args_index; i++) - boot_script_free (cmd->args[i], sizeof *cmd->args[i]); - boot_script_free (cmd->args, sizeof cmd->args[0] * cmd->args_alloc); - } - if (cmd->exec_funcs) - boot_script_free (cmd->exec_funcs, - sizeof cmd->exec_funcs[0] * cmd->exec_funcs_alloc); - boot_script_free (cmd, sizeof *cmd); -} - -/* Free all storage allocated by the parser. - If ABORTING is set, terminate all tasks. */ -static void -cleanup (int aborting) -{ - int i; - - for (i = 0; i < cmds_index; i++) - free_cmd (cmds[i], aborting); - boot_script_free (cmds, sizeof cmds[0] * cmds_alloc); - cmds = 0; - cmds_index = cmds_alloc = 0; - - for (i = 0; i < symtab_index; i++) - boot_script_free (symtab[i], sizeof *symtab[i]); - boot_script_free (symtab, sizeof symtab[0] * symtab_alloc); - symtab = 0; - symtab_index = symtab_alloc = 0; -} - -/* Add PTR to the list of pointers PTR_LIST, which - currently has ALLOC amount of space allocated to it, and - whose next available slot is INDEX. If more space - needs to to allocated, INCR is the amount by which - to increase it. Return 0 on success, non-zero otherwise. */ -static int -add_list (void *ptr, void ***ptr_list, int *alloc, int *index, int incr) -{ - if (*index == *alloc) - { - void **p; - - *alloc += incr; - p = boot_script_malloc (*alloc * sizeof (void *)); - if (! p) - { - *alloc -= incr; - return 1; - } - if (*ptr_list) - { - memcpy (p, *ptr_list, *index * sizeof (void *)); - boot_script_free (*ptr_list, (*alloc - incr) * sizeof (void *)); - } - *ptr_list = p; - } - *(*ptr_list + *index) = ptr; - *index += 1; - return 0; -} - -/* Create an argument with TEXT, value type TYPE, and value VAL. - Add the argument to the argument list of CMD. */ -static struct arg * -add_arg (struct cmd *cmd, const char *text, int textlen, int type, int val) -{ - struct arg *arg; - - arg = boot_script_malloc (sizeof (struct arg) + textlen); - if (arg) - { - arg->text = text == 0 ? 0 : memcpy (arg + 1, text, textlen); - arg->type = type; - arg->val = val; - if (add_list (arg, (void ***) (void *)&cmd->args, - &cmd->args_alloc, &cmd->args_index, 5)) - { - boot_script_free (arg, sizeof *arg); - return 0; - } - } - return arg; -} - -/* Search for the symbol NAME in the symbol table. */ -static struct sym * -sym_lookup (const char *name) -{ - int i; - - for (i = 0; i < symtab_index; i++) - if (! strcmp (name, symtab[i]->name)) - return symtab[i]; - return 0; -} - -/* Create an entry for symbol NAME in the symbol table. */ -static struct sym * -sym_enter (const char *name) -{ - struct sym *sym; - - sym = boot_script_malloc (sizeof (struct sym)); - if (sym) - { - memset (sym, 0, sizeof (struct sym)); - sym->name = name; - if (add_list (sym, (void ***) (void *)&symtab, &symtab_alloc, &symtab_index, 20)) - { - boot_script_free (sym, sizeof *sym); - return 0; - } - } - return sym; -} - -/* Parse the command line CMDLINE. */ -int -boot_script_parse_line (void *hook, char *cmdline) -{ - char *p, *q; - int error; - struct cmd *cmd; - struct arg *arg; - - /* Extract command name. Ignore line if it lacks a command. */ - for (p = cmdline; *p == ' ' || *p == '\t'; p++) - ; - if (*p == '#') - /* Ignore comment line. */ - return 0; - -#if 0 - if (*p && *p != ' ' && *p != '\t' && *p != '\n') - { - printf ("(bootstrap): %s\n", cmdline); - } -#endif - - for (q = p; *q && *q != ' ' && *q != '\t' && *q != '\n'; q++) - ; - if (p == q) - return 0; - - *q++ = '\0'; - - /* Allocate a command structure. */ - cmd = boot_script_malloc (sizeof (struct cmd) + (q - p)); - if (! cmd) - return BOOT_SCRIPT_NOMEM; - memset (cmd, 0, sizeof (struct cmd)); - cmd->hook = hook; - cmd->path = memcpy (cmd + 1, p, q - p); - p = q; - - for (arg = 0;;) - { - if (! arg) - { - /* Skip whitespace. */ - while (*p == ' ' || *p == '\t') - p++; - - /* End of command line. */ - if (! *p || *p == '\n') - { - /* Add command to list. */ - if (add_list (cmd, (void ***) (void *) &cmds, - &cmds_alloc, &cmds_index, 10)) - { - error = BOOT_SCRIPT_NOMEM; - goto bad; - } - return 0; - } - } - - /* Look for a symbol. */ - if (arg || (*p == '$' && (*(p + 1) == '{' || *(p + 1) == '('))) - { - char end_char = (*(p + 1) == '{') ? '}' : ')'; - struct sym *sym = 0; - - for (p += 2;;) - { - char c; - int i, type; - integer_t val; - struct sym *s; - - /* Parse symbol name. */ - for (q = p; *q && *q != '\n' && *q != end_char && *q != '='; q++) - ; - if (p == q || ! *q || *q == '\n' - || (end_char == '}' && *q != '}')) - { - error = BOOT_SCRIPT_SYNTAX_ERROR; - goto bad; - } - c = *q; - *q = '\0'; - - /* See if this is a builtin symbol. */ - for (i = 0; i < NUM_BUILTIN; i++) - if (! strcmp (p, builtin_symbols[i].name)) - break; - - if (i < NUM_BUILTIN) - s = &builtin_symbols[i]; - else - { - /* Look up symbol in symbol table. - If no entry exists, create one. */ - s = sym_lookup (p); - if (! s) - { - s = sym_enter (p); - if (! s) - { - error = BOOT_SCRIPT_NOMEM; - goto bad; - } - } - } - - /* Only values are allowed in ${...} constructs. */ - if (end_char == '}' && s->type == VAL_FUNC) - return BOOT_SCRIPT_INVALID_SYM; - - /* Check that assignment is valid. */ - if (c == '=' && s->type == VAL_FUNC) - { - error = BOOT_SCRIPT_INVALID_ASG; - goto bad; - } - - /* For function symbols, execute the function. */ - if (s->type == VAL_FUNC) - { - if (! s->run_on_exec) - { - (error - = ((*((int (*) (struct cmd *, integer_t *)) s->val)) - (cmd, &val))); - if (error) - goto bad; - type = s->ret_type; - } - else - { - if (add_list (s, (void ***) (void *) &cmd->exec_funcs, - &cmd->exec_funcs_alloc, - &cmd->exec_funcs_index, 5)) - { - error = BOOT_SCRIPT_NOMEM; - goto bad; - } - type = VAL_NONE; - goto out; - } - } - else if (s->type == VAL_NONE) - { - type = VAL_SYM; - val = (integer_t) s; - } - else - { - type = s->type; - val = s->val; - } - - if (sym) - { - sym->type = type; - sym->val = val; - } - else if (arg) - { - arg->type = type; - arg->val = val; - } - - out: - p = q + 1; - if (c == end_char) - { - /* Create an argument if necessary. - We create an argument if the symbol appears - in the expression by itself. - - NOTE: This is temporary till the boot filesystem - servers support arguments. When that happens, - symbol values will only be printed if they're - associated with an argument. */ - if (! arg && end_char == '}') - { - if (! add_arg (cmd, 0, 0, type, val)) - { - error = BOOT_SCRIPT_NOMEM; - goto bad; - } - } - arg = 0; - break; - } - if (s->type != VAL_FUNC) - sym = s; - } - } - else - { - char c; - - /* Command argument; just copy the text. */ - for (q = p;; q++) - { - if (! *q || *q == ' ' || *q == '\t' || *q == '\n') - break; - if (*q == '$' && *(q + 1) == '{') - break; - } - c = *q; - *q = '\0'; - - /* Add argument to list. */ - arg = add_arg (cmd, p, q + 1 - p, VAL_NONE, 0); - if (! arg) - { - error = BOOT_SCRIPT_NOMEM; - goto bad; - } - if (c == '$') - p = q; - else - { - if (c) - p = q + 1; - else - p = q; - arg = 0; - } - } - } - - - bad: - free_cmd (cmd, 1); - cleanup (1); - return error; -} - -/* Ensure that the command line buffer can accommodate LEN bytes of space. */ -#define CHECK_CMDLINE_LEN(len) \ -{ \ - if (cmdline_alloc - cmdline_index < len) \ - { \ - char *ptr; \ - int alloc, i; \ - alloc = cmdline_alloc + len - (cmdline_alloc - cmdline_index) + 100; \ - ptr = boot_script_malloc (alloc); \ - if (! ptr) \ - { \ - error = BOOT_SCRIPT_NOMEM; \ - goto done; \ - } \ - memcpy (ptr, cmdline, cmdline_index); \ - for (i = 0; i < argc; ++i) \ - argv[i] = ptr + (argv[i] - cmdline); \ - boot_script_free (cmdline, cmdline_alloc); \ - cmdline = ptr; \ - cmdline_alloc = alloc; \ - } \ -} - -/* Execute commands previously parsed. */ -int -boot_script_exec () -{ - int cmd_index; - - for (cmd_index = 0; cmd_index < cmds_index; cmd_index++) - { - char **argv, *cmdline; - int i, argc, cmdline_alloc; - int cmdline_index, error, arg_index; - struct cmd *cmd = cmds[cmd_index]; - - /* Skip command if it doesn't have an associated task. */ - if (cmd->task == 0) - continue; - - /* Allocate a command line and copy command name. */ - cmdline_index = strlen (cmd->path) + 1; - cmdline_alloc = cmdline_index + 100; - cmdline = boot_script_malloc (cmdline_alloc); - if (! cmdline) - { - cleanup (1); - return BOOT_SCRIPT_NOMEM; - } - memcpy (cmdline, cmd->path, cmdline_index); - - /* Allocate argument vector. */ - argv = boot_script_malloc (sizeof (char *) * (cmd->args_index + 2)); - if (! argv) - { - boot_script_free (cmdline, cmdline_alloc); - cleanup (1); - return BOOT_SCRIPT_NOMEM; - } - argv[0] = cmdline; - argc = 1; - - /* Build arguments. */ - for (arg_index = 0; arg_index < cmd->args_index; arg_index++) - { - struct arg *arg = cmd->args[arg_index]; - - /* Copy argument text. */ - if (arg->text) - { - int len = strlen (arg->text); - - if (arg->type == VAL_NONE) - len++; - CHECK_CMDLINE_LEN (len); - memcpy (cmdline + cmdline_index, arg->text, len); - argv[argc++] = &cmdline[cmdline_index]; - cmdline_index += len; - } - - /* Add value of any symbol associated with this argument. */ - if (arg->type != VAL_NONE) - { - char *p, buf[50]; - int len; - mach_port_t name; - - if (arg->type == VAL_SYM) - { - struct sym *sym = (struct sym *) arg->val; - - /* Resolve symbol value. */ - while (sym->type == VAL_SYM) - sym = (struct sym *) sym->val; - if (sym->type == VAL_NONE) - { - error = BOOT_SCRIPT_UNDEF_SYM; - goto done; - } - arg->type = sym->type; - arg->val = sym->val; - } - - /* Print argument value. */ - switch (arg->type) - { - case VAL_STR: - p = (char *) arg->val; - len = strlen (p); - break; - - case VAL_TASK: - case VAL_PORT: - if (arg->type == VAL_TASK) - /* Insert send right to task port. */ - error = boot_script_insert_task_port - (cmd, (task_t) arg->val, &name); - else - /* Insert send right. */ - error = boot_script_insert_right (cmd, - (mach_port_t) arg->val, - &name); - if (error) - goto done; - - i = name; - p = buf + sizeof (buf); - len = 0; - do - { - *--p = i % 10 + '0'; - len++; - } - while (i /= 10); - break; - - default: - error = BOOT_SCRIPT_BAD_TYPE; - goto done; - } - len++; - CHECK_CMDLINE_LEN (len); - memcpy (cmdline + cmdline_index, p, len - 1); - *(cmdline + cmdline_index + len - 1) = '\0'; - if (! arg->text) - argv[argc++] = &cmdline[cmdline_index]; - cmdline_index += len; - } - } - - /* Terminate argument vector. */ - argv[argc] = 0; - - /* Execute the command. */ - if (boot_script_exec_cmd (cmd->hook, cmd->task, cmd->path, - argc, argv, cmdline, cmdline_index)) - { - error = BOOT_SCRIPT_EXEC_ERROR; - goto done; - } - - error = 0; - - done: - boot_script_free (cmdline, cmdline_alloc); - boot_script_free (argv, sizeof (char *) * (cmd->args_index + 2)); - if (error) - { - cleanup (1); - return error; - } - } - - for (cmd_index = 0; cmd_index < cmds_index; cmd_index++) - { - int i; - struct cmd *cmd = cmds[cmd_index]; - - /* Execute functions that want to be run on exec. */ - for (i = 0; i < cmd->exec_funcs_index; i++) - { - struct sym *sym = cmd->exec_funcs[i]; - int error = ((*((int (*) (struct cmd *, integer_t *)) sym->val)) - (cmd, 0)); - if (error) - { - cleanup (1); - return error; - } - } - } - - cleanup (0); - return 0; -} - -/* Create an entry for the variable NAME with TYPE and value VAL, - in the symbol table. */ -int -boot_script_set_variable (const char *name, int type, integer_t val) -{ - struct sym *sym = sym_enter (name); - - if (sym) - { - sym->type = type; - sym->val = val; - } - return sym ? 0 : 1; -} - - -/* Define the function NAME, which will return type RET_TYPE. */ -int -boot_script_define_function (const char *name, int ret_type, - int (*func) (const struct cmd *cmd, - integer_t *val)) -{ - struct sym *sym = sym_enter (name); - - if (sym) - { - sym->type = VAL_FUNC; - sym->val = (integer_t) func; - sym->ret_type = ret_type; - sym->run_on_exec = ret_type == VAL_NONE; - } - return sym ? 0 : 1; -} - - -/* Return a string describing ERR. */ -char * -boot_script_error_string (int err) -{ - switch (err) - { - case BOOT_SCRIPT_NOMEM: - return "no memory"; - - case BOOT_SCRIPT_SYNTAX_ERROR: - return "syntax error"; - - case BOOT_SCRIPT_INVALID_ASG: - return "invalid variable in assignment"; - - case BOOT_SCRIPT_MACH_ERROR: - return "mach error"; - - case BOOT_SCRIPT_UNDEF_SYM: - return "undefined symbol"; - - case BOOT_SCRIPT_EXEC_ERROR: - return "exec error"; - - case BOOT_SCRIPT_INVALID_SYM: - return "invalid variable in expression"; - - case BOOT_SCRIPT_BAD_TYPE: - return "invalid value type"; - } - return 0; -} - -#ifdef BOOT_SCRIPT_TEST -#include <stdio.h> - -int -boot_script_exec_cmd (void *hook, - mach_port_t task, char *path, int argc, - char **argv, char *strings, int stringlen) -{ - int i; - - printf ("port = %d: ", (int) task); - for (i = 0; i < argc; i++) - printf ("%s ", argv[i]); - printf ("\n"); - return 0; -} - -void -main (int argc, char **argv) -{ - char buf[500], *p; - int len; - FILE *fp; - mach_port_t host_port, device_port; - - if (argc < 2) - { - fprintf (stderr, "Usage: %s <script>\n", argv[0]); - exit (1); - } - fp = fopen (argv[1], "r"); - if (! fp) - { - fprintf (stderr, "Can't open %s\n", argv[1]); - exit (1); - } - host_port = 1; - device_port = 2; - boot_script_set_variable ("host-port", VAL_PORT, (int) host_port); - boot_script_set_variable ("device-port", VAL_PORT, (int) device_port); - boot_script_set_variable ("root-device", VAL_STR, (int) "hd0a"); - boot_script_set_variable ("boot-args", VAL_STR, (int) "-ad"); - p = buf; - len = sizeof (buf); - while (fgets (p, len, fp)) - { - int i, err; - - i = strlen (p) + 1; - err = boot_script_parse_line (0, p); - if (err) - { - fprintf (stderr, "error %s\n", boot_script_error_string (err)); - exit (1); - } - p += i; - len -= i; - } - boot_script_exec (); - exit (0); -} -#endif /* BOOT_SCRIPT_TEST */ diff --git a/boot-proxy-exc/boot_script.h b/boot-proxy-exc/boot_script.h deleted file mode 100644 index 62458693..00000000 --- a/boot-proxy-exc/boot_script.h +++ /dev/null @@ -1,116 +0,0 @@ -/* Definitions for boot script parser for Mach. */ - -#ifndef _boot_script_h -#define _boot_script_h - -/* Written by Shantanu Goel (goel@cs.columbia.edu). */ - -/* Error codes returned by boot_script_parse_line() - and boot_script_exec_cmd(). */ -#define BOOT_SCRIPT_NOMEM 1 -#define BOOT_SCRIPT_SYNTAX_ERROR 2 -#define BOOT_SCRIPT_INVALID_ASG 3 -#define BOOT_SCRIPT_MACH_ERROR 4 -#define BOOT_SCRIPT_UNDEF_SYM 5 -#define BOOT_SCRIPT_EXEC_ERROR 6 -#define BOOT_SCRIPT_INVALID_SYM 7 -#define BOOT_SCRIPT_BAD_TYPE 8 - -/* Legal values for argument `type' to function - boot_script_set_variable and boot_script_define_function. */ -#define VAL_NONE 0 /* none -- function runs at exec time */ -#define VAL_STR 1 /* string */ -#define VAL_PORT 2 /* port */ -#define VAL_TASK 3 /* task port */ - -/* This structure describes a command. */ -struct cmd -{ - /* Cookie passed in to boot_script_parse_line. */ - void *hook; - - /* Path of executable. */ - char *path; - - /* Task port. */ - task_t task; - - /* Argument list. */ - struct arg **args; - - /* Amount allocated for `args'. */ - int args_alloc; - - /* Next available slot in `args'. */ - int args_index; - - /* List of functions that want to be run on command execution. */ - struct sym **exec_funcs; - - /* Amount allocated for `exec_funcs'. */ - int exec_funcs_alloc; - - /* Next available slot in `exec_funcs'. */ - int exec_funcs_index; -}; - - -/* The user must define these functions, we work like malloc and free. */ -void *boot_script_malloc (unsigned int); -void boot_script_free (void *, unsigned int); - -/* The user must define this function. Load the image of the - executable specified by PATH in TASK. Create a thread - in TASK and point it at the executable's entry point. Initialize - TASK's stack with argument vector ARGV of length ARGC whose - strings are STRINGS. STRINGS has length STRINGLEN. - Return 0 for success, non-zero otherwise. */ -int boot_script_exec_cmd (void *hook, - task_t task, char *path, int argc, - char **argv, char *strings, int stringlen); - -/* The user must define this function. Load the contents of FILE - into a fresh anonymous memory object and return the memory object port. */ -mach_port_t boot_script_read_file (const char *file); - -/* The user must define this functions to perform the corresponding - Mach task manipulations. */ -int boot_script_task_create (struct cmd *); /* task_create + task_suspend */ -int boot_script_task_resume (struct cmd *); -int boot_script_prompt_task_resume (struct cmd *); -int boot_script_insert_right (struct cmd *, mach_port_t, mach_port_t *namep); -int boot_script_insert_task_port (struct cmd *, task_t, mach_port_t *namep); - -/* The user must define this function to clean up the `task_t' - returned by boot_script_task_create. */ -void boot_script_free_task (task_t task, int aborting); - - -/* Parse the command line LINE. This causes the command line to be - converted into an internal format. Returns 0 for success, non-zero - otherwise. - - NOTE: The parser writes into the line so it must not be a string constant. - It is also the responsibility of the caller not to deallocate the line - across calls to the parser. */ -int boot_script_parse_line (void *hook, char *cmdline); - -/* Execute the command lines prevously parsed. - Returns 0 for success, non-zero otherwise. */ -int boot_script_exec (void); - -/* Create an entry in the symbol table for variable NAME, - whose type is TYPE and value is VAL. Returns 0 on success, - non-zero otherwise. */ -int boot_script_set_variable (const char *name, int type, integer_t val); - -/* Define the function NAME, which will return type RET_TYPE. */ -int boot_script_define_function (const char *name, int ret_type, - int (*func) (const struct cmd *cmd, - integer_t *val)); - -/* Returns a string describing the error ERR. */ -char *boot_script_error_string (int err); - - -#endif /* _boot_script_h */ diff --git a/boot-proxy-exc/exc_impl.c b/boot-proxy-exc/exc_impl.c deleted file mode 100644 index 1c6900bb..00000000 --- a/boot-proxy-exc/exc_impl.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - Copyright (C) 2009 Free Software Foundation, Inc. - Written by Zheng Da. - - 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. */ - -/* This file implements the server-side RPC functions of mach_host. */ - -#include <mach.h> -#include <hurd.h> -#include <assert.h> - -#include "util.h" -#include "mach_proxy.h" - -kern_return_t -catch_exception_raise (mach_port_t exception_port, mach_port_t thread, - mach_port_t task, integer_t exception, - integer_t code, integer_t subcode) -{ - error_t err; - struct task_info *fault_task_pi = NULL; - debug (""); - - int match_task (struct task_info *task_pi) - { - if (task_pi->task_port == task) - { - fault_task_pi = task_pi; - ports_port_ref (fault_task_pi); - return 1; - } - return 0; - } - foreach_task (match_task); - - if (fault_task_pi == NULL) - { - fault_task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (fault_task_pi) - info ("find the task: %d from libports", task); - } - - if (fault_task_pi == NULL) - { - info ("cannot find the task: %d", task); - return EINVAL; - } - - err = catch_exception_raise (fault_task_pi->user_exc_port, - thread, fault_task_pi->task.port_right, - exception, code, subcode); - ports_port_deref (fault_task_pi); - return err; -} diff --git a/boot-proxy-exc/frank1.ld b/boot-proxy-exc/frank1.ld deleted file mode 100644 index 9de827ae..00000000 --- a/boot-proxy-exc/frank1.ld +++ /dev/null @@ -1,94 +0,0 @@ -OUTPUT_FORMAT("elf32-i386", "elf32-i386", - "elf32-i386") -OUTPUT_ARCH(i386) -ENTRY(_start) - SEARCH_DIR(/usr/local/i386-gnuelf/lib); -/* Do we need any of these for elf? - __DYNAMIC = 0; */ -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - . = 0x10020; - .text : - { - *(.text) - *(.interp) - *(.hash) - *(.dynsym) - *(.dynstr) - *(.rel.text) - *(.rela.text) - *(.rel.data) - *(.rela.data) - *(.rel.rodata) - *(.rela.rodata) - *(.rel.got) - *(.rela.got) - *(.rel.ctors) - *(.rela.ctors) - *(.rel.dtors) - *(.rela.dtors) - *(.rel.init) - *(.rela.init) - *(.rel.fini) - *(.rela.fini) - *(.rel.bss) - *(.rela.bss) - *(.rel.plt) - *(.rela.plt) - *(.init) - *(.plt) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - *(.fini) - *(.rodata) - *(.rodata1) - _etext = .; - PROVIDE (etext = .); - . = ALIGN(0x1000); - } =0x9090 - . = ALIGN(0x1000); - .data : - { - *(.data) - CONSTRUCTORS - - *(.data1) - *(.ctors) - *(.dtors) - *(.got.plt) *(.got) - *(.dynamic) - /* We want the small data sections together, so single-instruction offsets - can access them all, and initialized data all before uninitialized, so - we can shorten the on-disk segment size. */ - *(.sdata) - _edata = .; - PROVIDE (edata = .); - . = ALIGN(0x10); -} - __bss_start = .; - .bss : - { - *(.sbss) *(.scommon) - *(.dynbss) - *(.bss) - *(COMMON) - _end = ALIGN(4) ; - PROVIDE (end = ALIGN(4)); - } - /* These are needed for ELF backends which have not yet been - converted to the new style linker. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - /* DWARF debug sections. - Symbols in the .debug DWARF section are relative to the beginning of the - section so we begin .debug at 0. It's not clear yet what needs to happen - for the others. */ - .debug 0 : { *(.debug) } - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - .debug_sfnames 0 : { *(.debug_sfnames) } - .line 0 : { *(.line) } - /* These must appear regardless of . */ -} diff --git a/boot-proxy-exc/frankemul.ld b/boot-proxy-exc/frankemul.ld deleted file mode 100644 index 413953ef..00000000 --- a/boot-proxy-exc/frankemul.ld +++ /dev/null @@ -1,107 +0,0 @@ -OUTPUT_FORMAT("elf32-i386", "elf32-i386", - "elf32-i386") -OUTPUT_ARCH(i386) -ENTRY(_start) - SEARCH_DIR(/usr/local/i386-gnuelf/lib); -/* Do we need any of these for elf? - __DYNAMIC = 0; */ -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - . = 0x10020; - .text : - { - *(.text) - *(.interp) - *(.hash) - *(.dynsym) - *(.dynstr) - *(.rel.text) - *(.rela.text) - *(.rel.data) - *(.rela.data) - *(.rel.rodata) - *(.rela.rodata) - *(.rel.got) - *(.rela.got) - *(.rel.ctors) - *(.rela.ctors) - *(.rel.dtors) - *(.rela.dtors) - *(.rel.init) - *(.rela.init) - *(.rel.fini) - *(.rela.fini) - *(.rel.bss) - *(.rela.bss) - *(.rel.plt) - *(.rela.plt) - *(.init) - *(.plt) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - *(.fini) - *(.rodata) - *(.rodata1) -*(_hurd_ioctl_handler_lists) -*(_hurd_pgrp_changed_hook) -*(_hurd_fork_locks) -*(_hurd_subinit) -*(__libc_atexit) -*(_hurd_fd_subinit) -*(_hurd_preinit_hook) -*(_hurd_fork_child_hook) -*(_hurd_fork_parent_hook) -*(_hurd_fork_prepare_hook) -*(_hurd_reauth_hook) -*(_hurd_proc_subinit) -*(__libc_subinit) - _etext = .; - PROVIDE (etext = .); - . = ALIGN(0x1000); - } =0x9090 - . = ALIGN(0x1000); - .data : - { - *(.data) - CONSTRUCTORS - - *(.data1) - *(.ctors) - *(.dtors) - *(.got.plt) *(.got) - *(.dynamic) - /* We want the small data sections together, so single-instruction offsets - can access them all, and initialized data all before uninitialized, so - we can shorten the on-disk segment size. */ - *(.sdata) - _edata = .; - PROVIDE (edata = .); - . = ALIGN(0x10); -} - __bss_start = .; - .bss : - { - *(.sbss) *(.scommon) - *(.dynbss) - *(.bss) - *(COMMON) - _end = ALIGN(4) ; - PROVIDE (end = ALIGN(4)); - } - /* These are needed for ELF backends which have not yet been - converted to the new style linker. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - /* DWARF debug sections. - Symbols in the .debug DWARF section are relative to the beginning of the - section so we begin .debug at 0. It's not clear yet what needs to happen - for the others. */ - .debug 0 : { *(.debug) } - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - .debug_sfnames 0 : { *(.debug_sfnames) } - .line 0 : { *(.line) } - /* These must appear regardless of . */ -} diff --git a/boot-proxy-exc/list.c b/boot-proxy-exc/list.c deleted file mode 100644 index db555f35..00000000 --- a/boot-proxy-exc/list.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - Copyright (C) 2009 Free Software Foundation, Inc. - Written by Zheng Da. - - 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. */ - -/* This file implements a double linked list. */ - -#include "list.h" - -void entry_init (struct list *entry) -{ - entry->next = entry; - entry->prev = entry; -} - -void add_entry_head (struct list *head, struct list *entry) -{ - entry->next = head->next; - head->next->prev = entry; - head->next = entry; - entry->prev = head; -} - -void add_entry_end (struct list *head, struct list *entry) -{ - entry->next = head; - entry->prev = head->prev; - head->prev->next = entry; - head->prev = entry; -} - -void remove_entry (struct list *entry) -{ - entry->next->prev = entry->prev; - entry->prev->next = entry->next; -} - diff --git a/boot-proxy-exc/list.h b/boot-proxy-exc/list.h deleted file mode 100644 index f3f7585f..00000000 --- a/boot-proxy-exc/list.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - Copyright (C) 2009 Free Software Foundation, Inc. - Written by Zheng Da. - - 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 __LIST_H__ -#define __LIST_H__ - -#include <stddef.h> - -struct list -{ - struct list *next, *prev; -}; - -void entry_init (struct list *entry); -void add_entry_head (struct list *head, struct list *entry); -void add_entry_end (struct list *head, struct list *entry); -void remove_entry (struct list *entry); - -#define LIST_HEADER(head) struct list head = {&head, &head} -#define EMPTY_LIST(head) ((head)->next == (head)) -#define LIST_ENTRY(entry, type, field) ((type *) (((char *) entry) - offsetof (type, field))) - -#endif diff --git a/boot-proxy-exc/mach-crt0.c b/boot-proxy-exc/mach-crt0.c deleted file mode 100644 index 0469424e..00000000 --- a/boot-proxy-exc/mach-crt0.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * Redistribution and use in source and binary forms are permitted - * provided that: (1) source distributions retain this entire copyright - * notice and comment, and (2) distributions including binaries display - * the following acknowledgement: ``This product includes software - * developed by the University of California, Berkeley and its contributors'' - * in the documentation or other materials provided with the distribution - * and in all advertising materials mentioning features or use of this - * software. Neither the name of the University nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifndef lint -static char sccsid[] = "@(#)crt0.c 5.2 (Berkeley) 5/14/90"; -#endif /* not lint */ - -/* - * C start up routine. - * Robert Henry, UCB, 20 Oct 81 - * - * We make the following (true) assumptions: - * 1) when the kernel calls start, it does a jump to location 2, - * and thus avoids the register save mask. We are NOT called - * with a calls! see sys1.c:setregs(). - * 2) The only register variable that we can trust is sp, - * which points to the base of the kernel calling frame. - * Do NOT believe the documentation in exec(2) regarding the - * values of fp and ap. - * 3) We can allocate as many register variables as we want, - * and don't have to save them for anybody. - * 4) Because of the ways that asm's work, we can't have - * any automatic variables allocated on the stack, because - * we must catch the value of sp before any automatics are - * allocated. - */ - -#include <mach/machine/asm.h> - -int __data_start = 0; -char **environ = (char **)0; -#ifdef paranoid -static int fd; -#endif paranoid - -int (*mach_init_routine)(); -int (*_cthread_init_routine)(); -int (*_cthread_exit_routine)(); -int (*_monstartup_routine)(); -int (*_StrongBox_init_routine)(); -int errno = 0; -int exit(); - -extern int main(); - -extern unsigned char etext; -int _start() -{ - __label__ eprol; - struct kframe { - int kargc; - char *kargv[1]; /* size depends on kargc */ - char kargstr[1]; /* size varies */ - char kenvstr[1]; /* size varies */ - }; - /* - * ALL REGISTER VARIABLES!!! - */ - register struct kframe *kfp; /* r10 */ - register char **targv; - register char **argv; - -#ifdef lint - kfp = 0; - initcode = initcode = 0; -#else not lint -#define Entry_sp() \ -({ int _spl__, _tmp1__; \ - asm volatile("leal 4(%%ebp), %0" : "=r" (_spl__) : "r" (_tmp1__)); \ - _spl__; }) - - kfp = (struct kframe *)Entry_sp(); -#endif not lint - for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) - /* void */ ; - if (targv >= (char **)(*argv)) - --targv; - environ = targv; - if (mach_init_routine) - (void) mach_init_routine(); - - eprol: -#ifdef paranoid - /* - * The standard I/O library assumes that file descriptors 0, 1, and 2 - * are open. If one of these descriptors is closed prior to the start - * of the process, I/O gets very confused. To avoid this problem, we - * insure that the first three file descriptors are open before calling - * main(). Normally this is undefined, as it adds two unnecessary - * system calls. - */ - do { - fd = open("/dev/null", 2); - } while (fd >= 0 && fd < 3); - close(fd); -#endif paranoid - - - if (_cthread_init_routine) { - int new_sp; - new_sp = (*_cthread_init_routine)(); - if (new_sp) { - asm volatile("movl %0, %%esp" : : "g" (new_sp) ); - } - } - if (_StrongBox_init_routine) (*_StrongBox_init_routine)(); - - if (_monstartup_routine) { - _monstartup_routine(&&eprol, &etext); - } - - (* (_cthread_exit_routine ? _cthread_exit_routine : exit)) - (main(kfp->kargc, argv, targv)); -} diff --git a/boot-proxy-exc/mach_host_impl.c b/boot-proxy-exc/mach_host_impl.c deleted file mode 100644 index c5fc8967..00000000 --- a/boot-proxy-exc/mach_host_impl.c +++ /dev/null @@ -1,544 +0,0 @@ -/* - Copyright (C) 2009 Free Software Foundation, Inc. - Written by Zheng Da. - - 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. */ - -/* This file implements the server-side RPC functions of mach_host. */ - -#include <stdio.h> -#include <assert.h> - -#include <mach.h> -#include <hurd.h> -#include <hurd/ports.h> - -#include "util.h" -#include "list.h" -#include "mach_proxy.h" - -extern mach_port_t privileged_host_port; - -/* Set task priority. */ -kern_return_t -S_task_priority (mach_port_t task, int priority, boolean_t change_threads) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - err = task_priority (task_pi->task_port, priority, change_threads); - debug ("%s", strerror (err)); - ports_port_deref (task_pi); - return err; -} - -/* Routine processor_set_tasks */ -kern_return_t -S_processor_set_tasks (mach_port_t processor_set, task_array_t *task_list, - mach_msg_type_number_t *task_listCnt) -{ - error_t err = 0; - mach_port_t *subhurd_tasks = NULL; - int size = 0; - /* no pseudo task port is created for the kernel task. */ - int num = 0; - int tot_nbtasks = ports_count_class (task_portclass) + num; - - size = tot_nbtasks * sizeof (mach_port_t); - err = vm_allocate (mach_task_self (), - (vm_address_t *) (void *) &subhurd_tasks, - size, 1); - if (err) - goto out; - - int get_pseudo_task_port (struct task_info *task_pi) - { - assert (num < tot_nbtasks); - subhurd_tasks[num++] = ports_get_right (task_pi); - return 0; - } - - foreach_task (get_pseudo_task_port); - assert (num == tot_nbtasks); - debug ("get %d tasks", tot_nbtasks); - *task_list = subhurd_tasks; - *task_listCnt = tot_nbtasks; - -out: - /* I enable the class here, - * so no pseudo task port can be created when I count the number of tasks. */ - ports_enable_class (task_portclass); - /* The array will be deallocated after it is sent, - * but the task ports in it don't need to, - * because I only call ports_get_right() - * and the reference count isn't increased. */ - return err; -} - -/* Get control port for a processor set. */ -kern_return_t -S_host_processor_set_priv (mach_port_t host_priv, mach_port_t set_name, - mach_port_t *set, mach_msg_type_name_t *setPoly) -{ - extern struct port_class *other_portclass; - struct port_info *pi; - kern_return_t ret = 0; - - // TODO create a port for each processor set - // I should create the port for the processor set only once. - ret = ports_create_port (other_portclass, port_bucket, - sizeof (*pi), &pi); - debug ("%s", strerror (ret)); - if (ret) - return ret; - *set = ports_get_right (pi); - *setPoly = MACH_MSG_TYPE_MAKE_SEND; - ports_port_deref (pi); - return ret; -} - -/* Routine host_reboot */ -kern_return_t -S_host_reboot (mach_port_t host_priv, int options) -{ - debug (""); - assert (0); - // TODO - return EOPNOTSUPP; -} - -/* Routine vm_wire */ -kern_return_t -S_vm_wire (mach_port_t host_priv, mach_port_t task, - vm_address_t address, vm_size_t size, vm_prot_t access) -{ - debug (""); - assert (0); - // TODO - return EOPNOTSUPP; -} - -/* Routine thread_wire */ -kern_return_t -S_thread_wire (mach_port_t host_priv, mach_port_t thread, boolean_t wired) -{ - debug (""); - assert (0); - // TODO - return EOPNOTSUPP; -} - -//////////the request to the host isn't forwarded by the proxy////////// - -/* Routine host_processor_sets */ -kern_return_t -S_host_processor_sets (mach_port_t host, - processor_set_name_array_t *processor_sets, - mach_msg_type_number_t *processor_setsCnt) -{ - debug (""); - assert (0); - // the request to the host isn't forwarded. - return EOPNOTSUPP; -} - -/* Routine host_get_time */ -kern_return_t -S_host_get_time (mach_port_t host, time_value_t *current_time) -{ - debug (""); - assert (0); - // the request to the host isn't forwarded. - return EOPNOTSUPP; -} - -/* Routine host_info */ -kern_return_t -S_host_info (mach_port_t host, int flavor, host_info_t host_info_out, - mach_msg_type_number_t *host_info_outCnt) -{ - debug (""); - assert (0); - // the request to the host isn't forwarded. - return EOPNOTSUPP; -} - -/* Get string describing current kernel version. */ -kern_return_t -S_host_kernel_version (mach_port_t host, kernel_version_t kernel_version) -{ - debug (""); - assert (0); - // the proxy doesn't forward the request to the host port. - return EOPNOTSUPP; -} - -///////////////////the RPCs not used by Hurd////////////////////// - -/* Get list of processors on this host. */ -kern_return_t -S_host_processors (mach_port_t host_priv, - processor_array_t *processor_list, - mach_msg_type_number_t *processor_listCnt) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Start processor. */ -kern_return_t -S_processor_start (mach_port_t processor) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Exit processor -- may not be restartable. */ -kern_return_t -S_processor_exit (mach_port_t processor) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Get default processor set for host. */ -kern_return_t -S_processor_set_default (mach_port_t host, mach_port_t *default_set) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* - * Create new processor set. Returns real port for manipulations, - * and name port for obtaining information. - */ -kern_return_t -S_processor_set_create (mach_port_t host, mach_port_t *new_set, - mach_port_t *new_name) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Destroy processor set. */ -kern_return_t -S_processor_set_destroy (mach_port_t set) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Assign processor to processor set. */ -kern_return_t -S_processor_assign (mach_port_t processor, mach_port_t new_set, boolean_t wait) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Get current assignment for thread. */ -kern_return_t -S_processor_get_assignment (mach_port_t processor, mach_port_t *assigned_set) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Assign task to processor set. */ -kern_return_t -S_task_assign (mach_port_t task, mach_port_t new_set, boolean_t assign_threads) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Assign task to default set. */ -kern_return_t -S_task_assign_default (mach_port_t task, boolean_t assign_threads) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Get current assignment for task. */ -kern_return_t -S_task_get_assignment (mach_port_t task, mach_port_t *assigned_set) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Set max priority for processor_set. */ -kern_return_t -S_processor_set_max_priority (mach_port_t processor_set, int max_priority, - boolean_t change_threads) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Routine processor_set_policy_enable */ -kern_return_t -S_processor_set_policy_enable (mach_port_t processor_set, int policy) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Routine processor_set_policy_disable */ -kern_return_t -S_processor_set_policy_disable (mach_port_t processor_set, int policy, - boolean_t change_threads) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Routine processor_set_threads */ -kern_return_t -S_processor_set_threads (mach_port_t processor_set, - thread_array_t *thread_list, - mach_msg_type_number_t *thread_listCnt) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Routine host_set_time */ -kern_return_t -S_host_set_time (mach_port_t host_priv, time_value_t new_time) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Routine host_adjust_time */ -kern_return_t -S_host_adjust_time (mach_port_t host_priv, time_value_t new_adjustment, - time_value_t *old_adjustment) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Routine processor_info */ -kern_return_t -S_processor_info (mach_port_t processor, int flavor, mach_port_t *host, - processor_info_t processor_info_out, - mach_msg_type_number_t *processor_info_outCnt) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Routine processor_set_info */ -kern_return_t -S_processor_set_info (mach_port_t set_name, int flavor, mach_port_t *host, - processor_set_info_t info_out, - mach_msg_type_number_t *info_outCnt) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Routine processor_control */ -kern_return_t -S_processor_control (mach_port_t processor, processor_info_t processor_cmd, - mach_msg_type_number_t processor_cmdCnt) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -/* Routine host_get_boot_info */ -kern_return_t -S_host_get_boot_info (mach_port_t host_priv, kernel_boot_info_t boot_info) -{ - debug (""); - assert (0); - // Hurd currently doesn't use it. - return EOPNOTSUPP; -} - -///////////////////it's not a proxy for thread requests/////////////////// - -/* Assign thread to processor set. */ -kern_return_t -S_thread_assign (mach_port_t thread, mach_port_t new_set) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Assign thread to default set. */ -kern_return_t -S_thread_assign_default (mach_port_t thread) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Get current assignment for thread. */ -kern_return_t -S_thread_get_assignment (mach_port_t thread, mach_port_t *assigned_set) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Set priority for thread. */ -kern_return_t S_thread_priority (mach_port_t thread, int priority, - boolean_t set_max) -{ - debug (""); - assert (0); - return thread_priority (thread, priority, set_max); -} - -/* Set max priority for thread. */ -kern_return_t S_thread_max_priority (mach_port_t thread, - mach_port_t processor_set, - int max_priority) -{ - debug (""); - assert (0); - return thread_max_priority (thread, processor_set, max_priority); -} - -/* Routine thread_depress_abort */ -kern_return_t S_thread_depress_abort (mach_port_t thread) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Set policy for thread */ -kern_return_t S_thread_policy (mach_port_t thread, int policy, int data) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -////////////////////don't support obsolete requests/////////////////////// - -/* Routine yyy_host_info */ -/* obsolete */ -kern_return_t -S_yyy_host_info (mach_port_t host, int flavor, host_info_t host_info_out, - mach_msg_type_number_t *host_info_outCnt) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine yyy_processor_info */ -/* obsolete */ -kern_return_t -S_yyy_processor_info (mach_port_t processor, int flavor, mach_port_t *host, - processor_info_t processor_info_out, - mach_msg_type_number_t *processor_info_outCnt) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine yyy_processor_control */ -/* obsolete */ -kern_return_t -S_yyy_processor_control (mach_port_t processor, - processor_info_t processor_cmd, - mach_msg_type_number_t processor_cmdCnt) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* - * Get rights to default processor set for host. - * Replaced by host_processor_set_priv. - */ -kern_return_t -S_xxx_processor_set_default_priv (mach_port_t host, mach_port_t *default_set) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine yyy_processor_set_info */ -/* obsolete */ -kern_return_t -S_yyy_processor_set_info (mach_port_t set_name, int flavor, - mach_port_t *host, processor_set_info_t info_out, - mach_msg_type_number_t *info_outCnt) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} diff --git a/boot-proxy-exc/mach_impl.c b/boot-proxy-exc/mach_impl.c deleted file mode 100644 index abead5a9..00000000 --- a/boot-proxy-exc/mach_impl.c +++ /dev/null @@ -1,909 +0,0 @@ -/* - Copyright (C) 2009 Free Software Foundation, Inc. - Written by Zheng Da. - - 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. */ - -/* This file implements the server-side RPC functions of mach_host. */ - -#include <string.h> -#include <mach.h> -#include <hurd.h> -#include <assert.h> - -#include "util.h" -#include "mach_proxy.h" -#include "list.h" - -/* Routine task_create */ -kern_return_t -S_task_create (mach_port_t target_task, boolean_t inherit_memory, - mach_port_t *child_task, mach_msg_type_name_t *child_taskPoly) -{ - struct task_info *target_task_pi; - task_t real_child_task; - task_t pseudo_child_task; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - err = task_create (target_task_pi->task_port, - inherit_memory, &real_child_task); - debug ("get a request from task %d: %s", - target_task_pi->task_port, strerror (err)); - ports_port_deref (target_task_pi); - if (err) - return err; - - err = create_pseudo_task (real_child_task, &pseudo_child_task); - if (err) - { - task_terminate (real_child_task); - return err; - } - - *child_task = pseudo_child_task; - *child_taskPoly = MACH_MSG_TYPE_COPY_SEND; - - debug ("new task: %d", real_child_task); - return err; -} - -/* Routine task_terminate */ -kern_return_t -S_task_terminate (mach_port_t target_task) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - err = task_terminate (target_task_pi->task_port); - debug ("get request from task %d: %s", - target_task_pi->task_port, strerror (err)); - ports_destroy_right (target_task_pi); - ports_port_deref (target_task_pi); - return err; -} - -/* Routine task_info */ -kern_return_t -S_task_info (mach_port_t target_task, int flavor, - task_info_t task_info_out, - mach_msg_type_number_t *task_info_outCnt) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - - err = task_info (target_task_pi->task_port, flavor, - task_info_out, task_info_outCnt); - debug ("%s", strerror (err)); - ports_port_deref (target_task_pi); - return err; -} - -/* Routine vm_allocate */ -kern_return_t -S_vm_allocate (mach_port_t target_task, vm_address_t *address, - vm_size_t size, boolean_t anywhere) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - - /* This should be enough. */ - err = vm_allocate (target_task_pi->task_port, address, size, anywhere); - debug ("request is from task %d, address: %d, size: %d, anywhere: %d, %s", - target_task_pi->task_port, *address, size, anywhere, strerror (err)); - ports_port_deref (target_task_pi); - return err; -} - -/* Routine vm_deallocate */ -kern_return_t -S_vm_deallocate (mach_port_t target_task, - vm_address_t address, vm_size_t size) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - err = vm_deallocate (target_task_pi->task_port, address, size); - debug ("get a request from task %d: %s", - target_task_pi->task_port, strerror (err)); - ports_port_deref (target_task_pi); - return err; -} - -/* Routine vm_protect */ -kern_return_t -S_vm_protect (mach_port_t target_task, vm_address_t address, - vm_size_t size, boolean_t set_maximum, - vm_prot_t new_protection) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - err = vm_protect (target_task_pi->task_port, address, - size, set_maximum, new_protection); - debug ("request is from task %d: %s", - target_task_pi->task_port, strerror (err)); - ports_port_deref (target_task_pi); - return err; -} - -/* Routine vm_inherit */ -kern_return_t -S_vm_inherit (mach_port_t target_task, vm_address_t address, - vm_size_t size, vm_inherit_t new_inheritance) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - err = vm_inherit (target_task_pi->task_port, address, - size, new_inheritance); - debug ("%s", strerror (err)); - ports_port_deref (target_task_pi); - return err; -} - -/* Routine vm_read */ -kern_return_t -S_vm_read (mach_port_t target_task, vm_address_t address, - vm_size_t size, vm_offset_t *data, - mach_msg_type_number_t *dataCnt) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - - err = vm_read (target_task_pi->task_port, address, size, data, dataCnt); - debug ("get a request from task %d: %s", - target_task_pi->task_port, strerror (err)); - ports_port_deref (target_task_pi); - /* The deallocation bit is set.*/ - return err; -} - -/* Routine vm_write */ -kern_return_t -S_vm_write (mach_port_t target_task, vm_address_t address, - vm_offset_t data, mach_msg_type_number_t dataCnt) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - err = vm_write (target_task_pi->task_port, address, data, dataCnt); - debug ("get a request from task %d: %s", - target_task_pi->task_port, strerror (err)); - ports_port_deref (target_task_pi); - /* the proxy get the mapped pages from the client, - * deallocate it here. */ - vm_deallocate (mach_task_self (), data, dataCnt); - return err; -} - -/* Routine vm_copy */ -kern_return_t -S_vm_copy (mach_port_t target_task, vm_address_t source_address, - vm_size_t size, vm_address_t dest_address) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - - err = vm_copy (target_task_pi->task_port, source_address, - size, dest_address); - debug ("%s", strerror (err)); - ports_port_deref (target_task_pi); - return err; -} - -/* Routine vm_region */ -kern_return_t -S_vm_region (mach_port_t target_task, vm_address_t *address, - vm_size_t *size, vm_prot_t *protection, - vm_prot_t *max_protection, vm_inherit_t *inheritance, - boolean_t *is_shared, mach_port_t *object_name, - vm_offset_t *offset) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - - err = vm_region (target_task_pi->task_port, address, size, protection, - max_protection, inheritance, is_shared, object_name, offset); - debug ("get a request from task %d: %s, object: %d", - target_task_pi->task_port, strerror (err), *object_name); - ports_port_deref (target_task_pi); - return err; -} - -/* Routine vm_statistics */ -kern_return_t -S_vm_statistics (mach_port_t target_task, vm_statistics_data_t *vm_stats) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - - err = vm_statistics (target_task_pi->task_port, vm_stats); - debug ("request is from task %d: %s", - target_task_pi->task_port, strerror (err)); - ports_port_deref (target_task_pi); - return err; -} - -/* Routine mach_ports_register */ -kern_return_t -S_mach_ports_register (mach_port_t target_task, - mach_port_array_t init_port_set, - mach_msg_type_number_t init_port_setCnt) -{ - debug (""); - assert (0); - // not used by Hurd - return EOPNOTSUPP; -} - -/* Routine mach_ports_lookup */ -kern_return_t -S_mach_ports_lookup (mach_port_t target_task, - mach_port_array_t *init_port_set, - mach_msg_type_number_t *init_port_setCnt) -{ - debug (""); - assert (0); - // not used by Hurd - return EOPNOTSUPP; -} - -/* Routine vm_set_default_memory_manager */ -kern_return_t -S_vm_set_default_memory_manager (mach_port_t host_priv, - mach_port_t *default_manager) -{ - extern mach_port_t defpager; - debug (""); - *default_manager = defpager; - return 0; -} - - -/* Routine xxx_task_info */ -kern_return_t -S_xxx_task_info (mach_port_t target_task, int flavor, - task_info_t task_info_out, - mach_msg_type_number_t *task_info_outCnt) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine xxx_host_info */ -kern_return_t -S_xxx_host_info (mach_port_t target_task, machine_info_data_t *info) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine xxx_slot_info */ -kern_return_t -S_xxx_slot_info (mach_port_t target_task, int slot, machine_slot_data_t *info) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine xxx_cpu_control */ -kern_return_t -S_xxx_cpu_control (mach_port_t target_task, int cpu, boolean_t running) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine task_suspend */ -kern_return_t -S_task_suspend (mach_port_t target_task) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - err = task_suspend (target_task_pi->task_port); - debug ("get request from task %d: %s", - target_task_pi->task_port, strerror (err)); - ports_port_deref (target_task_pi); - return err; -} - -/* Routine task_resume */ -kern_return_t -S_task_resume (mach_port_t target_task) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - - err = task_resume (target_task_pi->task_port); - debug ("get request from task %d: %s", - target_task_pi->task_port, strerror (err)); - ports_port_deref (target_task_pi); - return err; -} - -/* Routine task_get_special_port */ -kern_return_t -S_task_get_special_port (mach_port_t target_task, int which_port, - mach_port_t *special_port, - mach_msg_type_name_t *special_portPoly) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - - err = task_get_special_port (target_task_pi->task_port, - which_port, special_port); - debug ("request is from task %d (%d, %d): %s\n", - target_task_pi->task_port, which_port, *special_port, strerror (err)); - ports_port_deref (target_task_pi); - if (err) - return err; - *special_portPoly = MACH_MSG_TYPE_MOVE_SEND; - return err; -} - -/* Routine task_set_special_port */ -kern_return_t -S_task_set_special_port (mach_port_t target_task, int which_port, - mach_port_t special_port) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - - if (which_port == TASK_EXCEPTION_PORT) - { - struct port_info *new_exc_pi; - struct port_info *old_exc_pi; - mach_port_t old_user_exc_port; - mach_port_t new_exc_port; - - err = ports_create_port (exc_portclass, port_bucket, - sizeof (new_exc_pi), &new_exc_pi); - if (err) - { - ports_port_deref (target_task_pi); - return err; - } - new_exc_port = ports_get_send_right (new_exc_pi); - - mutex_lock (&target_task_pi->lock); - old_exc_pi = target_task_pi->exc_pi; - old_user_exc_port = target_task_pi->user_exc_port; - err = task_set_special_port (target_task_pi->task_port, - which_port, new_exc_port); - target_task_pi->user_exc_port = special_port; - target_task_pi->exc_pi = new_exc_pi; - mutex_unlock (&target_task_pi->lock); - - ports_port_deref (new_exc_pi); - if (old_user_exc_port) - mach_port_deallocate (mach_task_self (), old_user_exc_port); - if (old_exc_pi) - ports_destroy_right (old_exc_pi); - debug ("get request from task %d (%d, %d): %s", - target_task_pi->task_port, which_port, - special_port, strerror (err)); - } - else - { - err = task_set_special_port (target_task_pi->task_port, - which_port, special_port); - debug ("get request from task %d (%d, %d): %s", - target_task_pi->task_port, which_port, - special_port, strerror (err)); - mach_port_deallocate (mach_task_self (), special_port); - } - ports_port_deref (target_task_pi); - return err; -} - -/* Routine task_ras_control */ -kern_return_t -S_task_ras_control (mach_port_t target_task, vm_address_t basepc, - vm_address_t boundspc, int flavor) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - err = task_ras_control (target_task_pi->task_port, basepc, boundspc, flavor); - debug ("%s", strerror (err)); - ports_port_deref (target_task_pi); - return err; -} - -/* Routine vm_map */ -kern_return_t -S_vm_map (mach_port_t target_task, vm_address_t *address, vm_size_t size, - vm_address_t mask, boolean_t anywhere, mach_port_t memory_object, - vm_offset_t offset, boolean_t copy, vm_prot_t cur_protection, - vm_prot_t max_protection, vm_inherit_t inheritance) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - err = vm_map (target_task_pi->task_port, address, size, mask, - anywhere, memory_object, offset, copy, - cur_protection, max_protection, inheritance); - debug ("request is from task %d, anywhere: %d: %s", - target_task_pi->task_port, anywhere, strerror (err)); - ports_port_deref (target_task_pi); - mach_port_deallocate (mach_task_self (), memory_object); - return err; -} - -/* Routine vm_machine_attribute */ -kern_return_t -S_vm_machine_attribute (mach_port_t target_task, vm_address_t address, - vm_size_t size, vm_machine_attribute_t attribute, - vm_machine_attribute_val_t *value) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - err = vm_machine_attribute (target_task_pi->task_port, address, - size, attribute, value); - debug ("%s", strerror (err)); - ports_port_deref (target_task_pi); - return err; -} - -/* Routine task_threads */ -kern_return_t -S_task_threads (mach_port_t target_task, thread_array_t *thread_list, - mach_msg_type_number_t *thread_listCnt) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - target_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - - // TODO: use move send - err = task_threads (target_task_pi->task_port, - thread_list, thread_listCnt); - debug ("get a request from task %d: %s", - target_task_pi->task_port, strerror (err)); -// info ("task_threads: %s, number of threads: %d", -// strerror (err), *thread_listCnt); - ports_port_deref (target_task_pi); - return err; -} - -/* Routine thread_create */ -kern_return_t -S_thread_create (mach_port_t parent_task, mach_port_t *child_thread, - mach_msg_type_name_t *child_threadPoly) -{ - struct task_info *target_task_pi; - error_t err; - - target_task_pi = ports_lookup_port (port_bucket, - parent_task, task_portclass); - if (target_task_pi == NULL) - return EOPNOTSUPP; - err = thread_create (target_task_pi->task_port, child_thread); - debug ("get a request from task %d: thread port: %d: %s", - target_task_pi->task_port, *child_thread, strerror (err)); - ports_port_deref (target_task_pi); - *child_threadPoly = MACH_MSG_TYPE_MOVE_SEND; - return err; -} - -////////////////////it doesn't forward thread request//////////////// - -/* Routine thread_suspend */ -kern_return_t -S_thread_suspend (mach_port_t target_thread) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine thread_resume */ -kern_return_t -S_thread_resume (mach_port_t target_thread) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine thread_abort */ -kern_return_t -S_thread_abort (mach_port_t target_thread) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine xxx_thread_get_state */ -kern_return_t -S_xxx_thread_get_state (mach_port_t target_thread, int flavor, - thread_state_t old_state, - mach_msg_type_number_t *old_stateCnt) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine xxx_thread_set_state */ -kern_return_t -S_xxx_thread_set_state (mach_port_t target_thread, int flavor, - thread_state_t new_state, - mach_msg_type_number_t new_stateCnt) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine xxx_thread_info */ -kern_return_t -S_xxx_thread_info (mach_port_t target_thread, int flavor, - thread_info_t thread_info_out, - mach_msg_type_number_t *thread_info_outCnt) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine thread_get_special_port */ -kern_return_t -S_thread_get_special_port (mach_port_t thread, int which_port, - mach_port_t *special_port) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine thread_set_special_port */ -kern_return_t -S_thread_set_special_port (mach_port_t thread, int which_port, - mach_port_t special_port) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine thread_terminate */ -kern_return_t -S_thread_terminate (mach_port_t target_thread) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine thread_get_state */ -kern_return_t -S_thread_get_state (mach_port_t target_thread, int flavor, - thread_state_t old_state, - mach_msg_type_number_t *old_stateCnt) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine thread_set_state */ -kern_return_t -S_thread_set_state (mach_port_t target_thread, int flavor, - thread_state_t new_state, - mach_msg_type_number_t new_stateCnt) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine thread_info */ -kern_return_t -S_thread_info (mach_port_t target_thread, int flavor, - thread_info_t thread_info_out, - mach_msg_type_number_t *thread_info_outCnt) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/////////////////////RPC related to memory object//////////////////// -//////////////////they are not needed to be forwarded//////////////// - -/* SimpleRoutine memory_object_data_provided */ -kern_return_t -S_memory_object_data_provided (mach_port_t memory_control, - vm_offset_t offset, vm_offset_t data, - mach_msg_type_number_t dataCnt, - vm_prot_t lock_value) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* SimpleRoutine memory_object_data_unavailable */ -kern_return_t -S_memory_object_data_unavailable (mach_port_t memory_control, - vm_offset_t offset, vm_size_t size) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine memory_object_get_attributes */ -kern_return_t -S_memory_object_get_attributes (mach_port_t memory_control, - boolean_t *object_ready, boolean_t *may_cache, - memory_object_copy_strategy_t *copy_strategy) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* SimpleRoutine xxx_memory_object_lock_request */ -kern_return_t -S_xxx_memory_object_lock_request (mach_port_t memory_control, - vm_offset_t offset, vm_size_t size, - boolean_t should_clean, - boolean_t should_flush, - vm_prot_t lock_value, - mach_port_t reply_to, - mach_msg_type_name_t reply_toPoly) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* SimpleRoutine memory_object_lock_request */ -kern_return_t -S_memory_object_lock_request ( mach_port_t memory_control, - vm_offset_t offset, vm_size_t size, - memory_object_return_t should_return, - boolean_t should_flush, - vm_prot_t lock_value, mach_port_t reply_to, - mach_msg_type_name_t reply_toPoly) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* SimpleRoutine memory_object_data_error */ -kern_return_t -S_memory_object_data_error (mach_port_t memory_control, - vm_offset_t offset, vm_size_t size, - kern_return_t error_value) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* SimpleRoutine memory_object_set_attributes */ -kern_return_t -S_memory_object_set_attributes (mach_port_t memory_control, - boolean_t object_ready, boolean_t may_cache, - memory_object_copy_strategy_t copy_strategy) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* SimpleRoutine memory_object_destroy */ -kern_return_t -S_memory_object_destroy (mach_port_t memory_control, kern_return_t reason) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* SimpleRoutine memory_object_data_supply */ -kern_return_t -S_memory_object_data_supply (mach_port_t memory_control, - vm_offset_t offset, vm_offset_t data, - mach_msg_type_number_t dataCnt, - vm_prot_t lock_value, boolean_t precious, - mach_port_t reply_to, - mach_msg_type_name_t reply_toPoly) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* SimpleRoutine memory_object_ready */ -kern_return_t -S_memory_object_ready (mach_port_t memory_control, boolean_t may_cache, - memory_object_copy_strategy_t copy_strategy) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* SimpleRoutine memory_object_change_attributes */ -kern_return_t -S_memory_object_change_attributes (mach_port_t memory_control, - boolean_t may_cache, - memory_object_copy_strategy_t copy_strategy, - mach_port_t reply_to, - mach_msg_type_name_t reply_toPoly) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -///////////////////////RPCs related to emulation///////////////////// -//////////////////////subhurd doesn't support it.//////////////////// - -/* Routine task_get_emulation_vector */ -kern_return_t -S_task_get_emulation_vector (mach_port_t task, int *vector_start, - emulation_vector_t *emulation_vector, - mach_msg_type_number_t *emulation_vectorCnt) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine task_set_emulation_vector */ -kern_return_t -S_task_set_emulation_vector (mach_port_t task, int vector_start, - emulation_vector_t emulation_vector, - mach_msg_type_number_t emulation_vectorCnt) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine xxx_task_get_emulation_vector */ -kern_return_t -S_xxx_task_get_emulation_vector (mach_port_t task, int *vector_start, - emulation_vector_t emulation_vector, - mach_msg_type_number_t *emulation_vectorCnt) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine xxx_task_set_emulation_vector */ -kern_return_t -S_xxx_task_set_emulation_vector (mach_port_t task, int vector_start, - emulation_vector_t emulation_vector, - mach_msg_type_number_t emulation_vectorCnt) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} - -/* Routine task_set_emulation */ -kern_return_t -S_task_set_emulation (mach_port_t target_port, - vm_address_t routine_entry_pt, int routine_number) -{ - debug (""); - assert (0); - return EOPNOTSUPP; -} diff --git a/boot-proxy-exc/mach_port_impl.c b/boot-proxy-exc/mach_port_impl.c deleted file mode 100644 index b421280b..00000000 --- a/boot-proxy-exc/mach_port_impl.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - Copyright (C) 2009 Free Software Foundation, Inc. - Written by Zheng Da. - - 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. */ - -/* This file implements the server-side RPC functions of mach_host. */ - -#include <mach.h> -#include <hurd.h> -#include <string.h> -#include <assert.h> - -#include "util.h" -#include "mach_proxy.h" - -kern_return_t -S_mach_port_names (mach_port_t task, mach_port_array_t *names, - mach_msg_type_number_t *namesCnt, - mach_port_type_array_t *types, - mach_msg_type_number_t *typesCnt) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - err = mach_port_names (task_pi->task_port, - names, namesCnt, types, typesCnt); - debug ("%s", strerror (err)); - /* The deallocation bit is set, - * so 'names' and 'types' will be deallocated after the reply is sent. */ - ports_port_deref (task_pi); - return err; -} - -/* Routine mach_port_type */ -kern_return_t -S_mach_port_type (mach_port_t task, mach_port_t name, mach_port_type_t *ptype) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - err = mach_port_type (task_pi->task_port, name, ptype); - debug ("%s", strerror (err)); - ports_port_deref (task_pi); - return err; -} - -/* Routine mach_port_rename */ -kern_return_t -S_mach_port_rename (mach_port_t task, - mach_port_t old_name, mach_port_t new_name) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - /* old_name and new_name are just names, - * so I don't need to deallocate them. - * It should be the same for other RPCs that only deal with port names */ - err = mach_port_rename (task_pi->task_port, old_name, new_name); - debug ("%s", strerror (err)); - ports_port_deref (task_pi); - return err; -} - -/* Routine mach_port_allocate_name */ -kern_return_t -S_mach_port_allocate_name (mach_port_t task, - mach_port_right_t right, mach_port_t name) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - err = mach_port_allocate_name (task_pi->task_port, right, name); - debug ("%s", strerror (err)); - ports_port_deref (task_pi); - return err; -} - -/* Routine mach_port_allocate */ -kern_return_t -S_mach_port_allocate (mach_port_t task, - mach_port_right_t right, mach_port_t *name) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - err = mach_port_allocate (task_pi->task_port, right, name); - debug ("get a request from task %d: %s", task_pi->task_port, strerror (err)); - ports_port_deref (task_pi); - return err; -} - -/* Routine mach_port_destroy */ -kern_return_t -S_mach_port_destroy (mach_port_t task, mach_port_t name) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - err = mach_port_destroy (task_pi->task_port, name); - debug ("get a request from port %d: %s", - task_pi->task_port, strerror (err)); - ports_port_deref (task_pi); - return err; -} - -/* Routine mach_port_deallocate */ -kern_return_t -S_mach_port_deallocate (mach_port_t task, mach_port_t name) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - err = mach_port_deallocate (task_pi->task_port, name); - debug ("get a request from task %d, name: %d, %s", - task_pi->task_port, name, strerror (err)); - ports_port_deref (task_pi); - return err; -} - -/* Routine mach_port_get_refs */ -kern_return_t -S_mach_port_get_refs (mach_port_t task, mach_port_t name, - mach_port_right_t right, mach_port_urefs_t *refs) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - err = mach_port_get_refs (task_pi->task_port, name, right, refs); - debug ("%s", strerror (err)); - ports_port_deref (task_pi); - return err; -} - -/* Routine mach_port_mod_refs */ -kern_return_t -S_mach_port_mod_refs (mach_port_t task, mach_port_t name, - mach_port_right_t right, mach_port_delta_t delta) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - err = mach_port_mod_refs (task_pi->task_port, name, right, delta); - debug ("get a request from task %d: port: %d, right: %d, delta: %d, %s", - task_pi->task_port, name, right, delta, strerror (err)); - ports_port_deref (task_pi); - return err; -} - -/* Routine old_mach_port_get_receive_status */ -kern_return_t -S_old_mach_port_get_receive_status (mach_port_t task, mach_port_t name, - old_mach_port_status_t *status) -{ - debug ("%s", strerror (EOPNOTSUPP)); - assert (0); - /* Hurd currently doesn't use it. */ - return EOPNOTSUPP; -} - -/* Routine mach_port_set_qlimit */ -kern_return_t -S_mach_port_set_qlimit (mach_port_t task, mach_port_t name, - mach_port_msgcount_t qlimit) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - err = mach_port_set_qlimit (task_pi->task_port, name, qlimit); - debug ("%s", strerror (err)); - ports_port_deref (task_pi); - return err; -} - -/* Routine mach_port_set_mscount */ -kern_return_t -S_mach_port_set_mscount (mach_port_t task, mach_port_t name, - mach_port_mscount_t mscount) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - err = mach_port_set_mscount (task_pi->task_port, name, mscount); - debug ("%s", strerror (err)); - ports_port_deref (task_pi); - return err; -} - -/* Routine mach_port_get_set_status */ -kern_return_t -S_mach_port_get_set_status (mach_port_t task, mach_port_t name, - mach_port_array_t *members, - mach_msg_type_number_t *membersCnt) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - err = mach_port_get_set_status (task_pi->task_port, - name, members, membersCnt); - debug ("%s", strerror (err)); - ports_port_deref (task_pi); - /* The deallocation bit is set, - * so 'members' will be deallocated after the reply is sent. */ - return err; -} - -/* Routine mach_port_move_member */ -kern_return_t -S_mach_port_move_member (mach_port_t task, mach_port_t member, - mach_port_t after) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - err = mach_port_move_member (task_pi->task_port, member, after); - debug ("%s", strerror (err)); - ports_port_deref (task_pi); - return err; -} - -/* Routine mach_port_request_notification */ -kern_return_t -S_mach_port_request_notification (mach_port_t task, mach_port_t name, - mach_msg_id_t id, mach_port_mscount_t sync, - mach_port_t notify, mach_port_t *previous, - mach_msg_type_name_t *previousPoly) -{ - struct task_info *task_pi; - mach_msg_type_name_t notify_type = MACH_MSG_TYPE_MOVE_SEND_ONCE; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - /* notify is send-once right from the client. */ - err = mach_port_request_notification (task_pi->task_port, name, id, sync, - notify, notify_type, previous); - debug ("get a request from task %d, port: %d, id: %d, notify: %d, notify_type: %d, old port: %d, %s", - task_pi->task_port, name, id, notify, notify_type, *previous, strerror (err)); - ports_port_deref (task_pi); - if (err) - return err; - *previousPoly = MACH_MSG_TYPE_MOVE_SEND_ONCE; - - return 0; -} - -/* Routine mach_port_insert_right */ -kern_return_t -S_mach_port_insert_right (mach_port_t task, mach_port_t name, - mach_port_t poly, mach_msg_type_name_t polyPoly) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - /* polyPoly can only be three possible values: MACH_MSG_TYPE_PORT_SEND, - * MACH_MSG_TYPE_PORT_SEND_ONCE and MACH_MSG_TYPE_PORT_RECEIVE, - * so port will be deallocated when mach_port_insert_right is called. */ - err = mach_port_insert_right (task_pi->task_port, name, poly, polyPoly); - debug ("get a request from task %d: %s", task_pi->task_port, strerror (err)); - ports_port_deref (task_pi); - return err; -} - -/* Routine mach_port_extract_right */ -kern_return_t -S_mach_port_extract_right (mach_port_t task, mach_port_t name, - mach_msg_type_name_t msgt_name, mach_port_t *poly, - mach_msg_type_name_t *polyPoly) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - err = mach_port_extract_right (task_pi->task_port, name, msgt_name, - poly, polyPoly); - debug ("%s", strerror (err)); - ports_port_deref (task_pi); - /* *polyPoly can only be MACH_MSG_TYPE_PORT_SEND, MACH_MSG_TYPE_PORT_RECEIVE, - * or MACH_MSG_TYPE_PORT_SEND_ONCE, so the port extracted from 'task' - * will be moved to the client. */ - return err; -} - -/* Routine mach_port_get_receive_status */ -kern_return_t -S_mach_port_get_receive_status (mach_port_t task, mach_port_t name, - mach_port_status_t *status) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - err = mach_port_get_receive_status (task_pi->task_port, name, status); - debug ("%s", strerror (err)); - ports_port_deref (task_pi); - return err; -} - -/* Routine mach_port_set_seqno */ -kern_return_t -S_mach_port_set_seqno (mach_port_t task, mach_port_t name, - mach_port_seqno_t seqno) -{ - struct task_info *task_pi; - error_t err; - - task_pi = ports_lookup_port (port_bucket, task, task_portclass); - if (task_pi == NULL) - return EOPNOTSUPP; - err = mach_port_set_seqno (task_pi->task_port, name, seqno); - debug ("%s", strerror (err)); - ports_port_deref (task_pi); - return err; -} diff --git a/boot-proxy-exc/mach_proxy.c b/boot-proxy-exc/mach_proxy.c deleted file mode 100644 index cc599353..00000000 --- a/boot-proxy-exc/mach_proxy.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - Copyright (C) 2009 Free Software Foundation, Inc. - Written by Zheng Da. - - 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 "util.h" -#include "mach_proxy.h" - -static LIST_HEADER (tasks_head); - -static struct mutex tasks_lock = MUTEX_INITIALIZER; - -int create_pseudo_task (task_t real_task, task_t *ret_pseudo_task) -{ - /* the first task is the kernel task. */ - struct task_info *task_pi; - task_t pseudo_task; - error_t err; - - err = ports_create_port (task_portclass, port_bucket, - sizeof (struct task_info), &task_pi); - if (err) - return err; - - task_pi->task_port = real_task; - task_pi->exc_pi = NULL; - task_pi->user_exc_port = 0; - mutex_init (&task_pi->lock); - entry_init (&task_pi->list); - mutex_lock (&tasks_lock); - add_entry_end (&tasks_head, &task_pi->list); - mutex_unlock (&tasks_lock); - - pseudo_task = ports_get_right (task_pi); - mach_port_insert_right (mach_task_self (), pseudo_task, pseudo_task, - MACH_MSG_TYPE_MAKE_SEND); - ports_port_deref (task_pi); - - if (ret_pseudo_task) - *ret_pseudo_task = pseudo_task; - - err = task_set_kernel_port (real_task, pseudo_task); - if (err) - { - debug ("fail to set the kernel port: %s", strerror (err)); - ports_destroy_right (task_pi); - } - - return err; -} - -void clean_pseudo_task (void *pi) -{ - struct task_info *task = pi; - - debug ("remove a pseudo task from the list"); - mutex_lock (&tasks_lock); - remove_entry (&task->list); - mutex_unlock (&tasks_lock); - - if (task->exc_pi) - ports_destroy_right (task->exc_pi); - if (task->user_exc_port) - mach_port_deallocate (mach_task_self (), task->user_exc_port); -} - -void foreach_task (task_callback_t callback) -{ - struct list *entry = &tasks_head; - mutex_lock (&tasks_lock); - for (entry = tasks_head.next; entry != &tasks_head; entry = entry->next) - { -// mutex_unlock (&tasks_lock); - struct task_info *task_pi = LIST_ENTRY (entry, struct task_info, list); - if (callback (task_pi)) - break; -// mutex_lock (&tasks_lock); - } - mutex_unlock (&tasks_lock); -} diff --git a/boot-proxy-exc/mach_proxy.h b/boot-proxy-exc/mach_proxy.h deleted file mode 100644 index 15f9c397..00000000 --- a/boot-proxy-exc/mach_proxy.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright (C) 2009 Free Software Foundation, Inc. - Written by Zheng Da. - - 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 PROXY_H -#define PROXY_H - -#include <mach.h> -#include <hurd.h> -#include <hurd/ports.h> - -#include "list.h" - -struct task_info -{ - struct port_info task; - task_t task_port; - struct port_info *exc_pi; - volatile mach_port_t user_exc_port; - struct mutex lock; - /* The linked list is used to keep the order of tasks */ - struct list list; -}; - -struct thread_info -{ - struct port_info thread; - thread_t thread_port; -}; - -typedef int (*task_callback_t) (struct task_info *); - -extern struct port_bucket *port_bucket; -extern struct port_class *task_portclass; -extern struct port_class *exc_portclass; -extern struct port_class *thread_portclass; - -int create_pseudo_task (task_t real_task, task_t *ret_pseudo_task); -void clean_pseudo_task (void *pi); -void foreach_task (task_callback_t callback); - -#define UNTESTED - -#endif diff --git a/boot-proxy-exc/ourmach.defs b/boot-proxy-exc/ourmach.defs deleted file mode 100644 index a257d954..00000000 --- a/boot-proxy-exc/ourmach.defs +++ /dev/null @@ -1,772 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University. - * Copyright (c) 1993,1994 The University of Utah and - * the Computer Systems Laboratory (CSL). - * All rights reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF - * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY - * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF - * THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * Matchmaker definitions file for Mach kernel interface. - */ - -#ifdef MACH_KERNEL -simport <kern/compat_xxx_defs.h>; /* for obsolete routines */ -#endif /* MACH_KERNEL */ - -subsystem -#if KERNEL_USER - KernelUser -#endif /* KERNEL_USER */ -#if KERNEL_SERVER - KernelServer -#endif /* KERNEL_SERVER */ - mach 2000; - -serverprefix S_; - -#ifdef KERNEL_USER -userprefix r_; -#endif /* KERNEL_USER */ - -#include <mach/std_types.defs> -#include <mach/mach_types.defs> - -skip; /* old port_allocate */ -skip; /* old port_deallocate */ -skip; /* old port_enable */ -skip; /* old port_disable */ -skip; /* old port_select */ -skip; /* old port_set_backlog */ -skip; /* old port_status */ - -/* - * Create a new task with an empty set of IPC rights, - * and having an address space constructed from the - * target task (or empty, if inherit_memory is FALSE). - */ -routine task_create( - target_task : task_t; - inherit_memory : boolean_t; - out child_task : mach_port_send_t); - -/* - * Destroy the target task, causing all of its threads - * to be destroyed, all of its IPC rights to be deallocated, - * and all of its address space to be deallocated. - */ -routine task_terminate( - target_task : task_t); - -/* - * Get user-level handler entry points for all - * emulated system calls. - */ -routine task_get_emulation_vector( - task : task_t; - out vector_start : int; - out emulation_vector: emulation_vector_t); - -/* - * Establish user-level handlers for the specified - * system calls. Non-emulated system calls are specified - * with emulation_vector[i] == EML_ROUTINE_NULL. - */ -routine task_set_emulation_vector( - task : task_t; - vector_start : int; - emulation_vector: emulation_vector_t); - - -/* - * Returns the set of threads belonging to the target task. - */ -routine task_threads( - target_task : task_t; - out thread_list : thread_array_t); -/* out thread_list : thread_send_array_t = - array[] of mach_port_send_t - ctype: thread_array_t);*/ - -/* - * Returns information about the target task. - */ -routine task_info( - target_task : task_t; - flavor : int; - out task_info_out : task_info_t, CountInOut); - - -skip; /* old task_status */ -skip; /* old task_set_notify */ -skip; /* old thread_create */ - -/* - * Destroy the target thread. - */ -routine thread_terminate( - target_thread : thread_t); - -/* - * Return the selected state information for the target - * thread. If the thread is currently executing, the results - * may be stale. [Flavor THREAD_STATE_FLAVOR_LIST provides a - * list of valid flavors for the target thread.] - */ -routine thread_get_state( - target_thread : thread_t; - flavor : int; - out old_state : thread_state_t, CountInOut); - -/* - * Set the selected state information for the target thread. - * If the thread is currently executing, the state change - * may be ill-defined. - */ -routine thread_set_state( - target_thread : thread_t; - flavor : int; - new_state : thread_state_t); - -/* - * Returns information about the target thread. - */ -routine thread_info( - target_thread : thread_t; - flavor : int; - out thread_info_out : thread_info_t, CountInOut); - -skip; /* old thread_mutate */ - -/* - * Allocate zero-filled memory in the address space - * of the target task, either at the specified address, - * or wherever space can be found (if anywhere is TRUE), - * of the specified size. The address at which the - * allocation actually took place is returned. - */ -#ifdef EMULATOR -skip; /* the emulator redefines vm_allocate using vm_map */ -#else /* EMULATOR */ -routine vm_allocate( - target_task : vm_task_t; - inout address : vm_address_t; - size : vm_size_t; - anywhere : boolean_t); -#endif /* EMULATOR */ - -skip; /* old vm_allocate_with_pager */ - -/* - * Deallocate the specified range from the virtual - * address space of the target task. - */ -routine vm_deallocate( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t); - -/* - * Set the current or maximum protection attribute - * for the specified range of the virtual address - * space of the target task. The current protection - * limits the memory access rights of threads within - * the task; the maximum protection limits the accesses - * that may be given in the current protection. - * Protections are specified as a set of {read, write, execute} - * *permissions*. - */ -routine vm_protect( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - set_maximum : boolean_t; - new_protection : vm_prot_t); - -/* - * Set the inheritance attribute for the specified range - * of the virtual address space of the target task. - * The inheritance value is one of {none, copy, share}, and - * specifies how the child address space should acquire - * this memory at the time of a task_create call. - */ -routine vm_inherit( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - new_inheritance : vm_inherit_t); - -/* - * Returns the contents of the specified range of the - * virtual address space of the target task. [The - * range must be aligned on a virtual page boundary, - * and must be a multiple of pages in extent. The - * protection on the specified range must permit reading.] - */ -routine vm_read( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - out data : pointer_t, dealloc); - -/* - * Writes the contents of the specified range of the - * virtual address space of the target task. [The - * range must be aligned on a virtual page boundary, - * and must be a multiple of pages in extent. The - * protection on the specified range must permit writing.] - */ -routine vm_write( - target_task : vm_task_t; - address : vm_address_t; - data : pointer_t); - -/* - * Copy the contents of the source range of the virtual - * address space of the target task to the destination - * range in that same address space. [Both of the - * ranges must be aligned on a virtual page boundary, - * and must be multiples of pages in extent. The - * protection on the source range must permit reading, - * and the protection on the destination range must - * permit writing.] - */ -routine vm_copy( - target_task : vm_task_t; - source_address : vm_address_t; - size : vm_size_t; - dest_address : vm_address_t); - -/* - * Returns information about the contents of the virtual - * address space of the target task at the specified - * address. The returned protection, inheritance, sharing - * and memory object values apply to the entire range described - * by the address range returned; the memory object offset - * corresponds to the beginning of the address range. - * [If the specified address is not allocated, the next - * highest address range is described. If no addresses beyond - * the one specified are allocated, the call returns KERN_NO_SPACE.] - */ -routine vm_region( - target_task : vm_task_t; - inout address : vm_address_t; - out size : vm_size_t; - out protection : vm_prot_t; - out max_protection : vm_prot_t; - out inheritance : vm_inherit_t; - out is_shared : boolean_t; - /* avoid out-translation of the argument */ - out object_name : memory_object_name_t = - MACH_MSG_TYPE_COPY_SEND - ctype: mach_port_t; - out offset : vm_offset_t); - -/* - * Return virtual memory statistics for the host - * on which the target task resides. [Note that the - * statistics are not specific to the target task.] - */ -routine vm_statistics( - target_task : vm_task_t; - out vm_stats : vm_statistics_data_t); - -skip; /* old task_by_u*x_pid */ -skip; /* old vm_pageable */ - -/* - * Stash a handful of ports for the target task; child - * tasks inherit this stash at task_create time. - */ -routine mach_ports_register( - target_task : task_t; - init_port_set : mach_port_array_t = - ^array[] of mach_port_t); - -/* - * Retrieve the stashed ports for the target task. - */ -routine mach_ports_lookup( - target_task : task_t; - out init_port_set : mach_port_array_t = - ^array[] of mach_port_t); - -skip; /* old u*x_pid */ -skip; /* old netipc_listen */ -skip; /* old netipc_ignore */ - -/* - * Provide the data contents of a range of the given memory - * object, with the access restriction specified. [Only - * whole virtual pages of data can be accepted; partial pages - * will be discarded. Data should be provided on request, but - * may be provided in advance as desired. When data already - * held by this kernel is provided again, the new data is ignored. - * The access restriction is the subset of {read, write, execute} - * which are prohibited. The kernel may not provide any data (or - * protection) consistency among pages with different virtual page - * alignments within the same object.] - */ -simpleroutine memory_object_data_provided( - memory_control : memory_object_control_t; - offset : vm_offset_t; - data : pointer_t; - lock_value : vm_prot_t); - -/* - * Indicate that a range of the given temporary memory object does - * not exist, and that the backing memory object should be used - * instead (or zero-fill memory be used, if no backing object exists). - * [This call is intended for use only by the default memory manager. - * It should not be used to indicate a real error -- - * memory_object_data_error should be used for that purpose.] - */ -simpleroutine memory_object_data_unavailable( - memory_control : memory_object_control_t; - offset : vm_offset_t; - size : vm_size_t); - -/* - * Retrieves the attributes currently associated with - * a memory object. - */ -routine memory_object_get_attributes( - memory_control : memory_object_control_t; - out object_ready : boolean_t; - out may_cache : boolean_t; - out copy_strategy : memory_object_copy_strategy_t); - -/* - * Sets the default memory manager, the port to which - * newly-created temporary memory objects are delivered. - * [See (memory_object_default)memory_object_create.] - * The old memory manager port is returned. - */ -routine vm_set_default_memory_manager( - host_priv : host_priv_t; - inout default_manager : mach_port_copy_send_t); - -skip; /* old pager_flush_request */ - -/* - * Control use of the data associated with the given - * memory object. For each page in the given range, - * perform the following operations, in order: - * 1) restrict access to the page (disallow - * forms specified by "prot"); - * 2) write back modifications (if "should_return" - * is RETURN_DIRTY and the page is dirty, or - * "should_return" is RETURN_ALL and the page - * is either dirty or precious); and, - * 3) flush the cached copy (if "should_flush" - * is asserted). - * The set of pages is defined by a starting offset - * ("offset") and size ("size"). Only pages with the - * same page alignment as the starting offset are - * considered. - * - * A single acknowledgement is sent (to the "reply_to" - * port) when these actions are complete. - * - * There are two versions of this routine because IPC distinguishes - * between booleans and integers (a 2-valued integer is NOT a - * boolean). The new routine is backwards compatible at the C - * language interface. - */ -simpleroutine xxx_memory_object_lock_request( - memory_control : memory_object_control_t; - offset : vm_offset_t; - size : vm_size_t; - should_clean : boolean_t; - should_flush : boolean_t; - lock_value : vm_prot_t; - reply_to : mach_port_t = - MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); - - -simpleroutine memory_object_lock_request( - memory_control : memory_object_control_t; - offset : vm_offset_t; - size : vm_size_t; - should_return : memory_object_return_t; - should_flush : boolean_t; - lock_value : vm_prot_t; - reply_to : mach_port_t = - MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); - -/* obsolete */ -routine xxx_task_get_emulation_vector( - task : task_t; - out vector_start : int; - out emulation_vector: xxx_emulation_vector_t, IsLong); - -/* obsolete */ -routine xxx_task_set_emulation_vector( - task : task_t; - vector_start : int; - emulation_vector: xxx_emulation_vector_t, IsLong); - -/* - * Returns information about the host on which the - * target object resides. [This object may be - * a task, thread, or memory_object_control port.] - */ -routine xxx_host_info( - target_task : mach_port_t; - out info : machine_info_data_t); - -/* - * Returns information about a particular processor on - * the host on which the target task resides. - */ -routine xxx_slot_info( - target_task : task_t; - slot : int; - out info : machine_slot_data_t); - -/* - * Performs control operations (currently only - * turning off or on) on a particular processor on - * the host on which the target task resides. - */ -routine xxx_cpu_control( - target_task : task_t; - cpu : int; - running : boolean_t); - -skip; /* old thread_statistics */ -skip; /* old task_statistics */ -skip; /* old netport_init */ -skip; /* old netport_enter */ -skip; /* old netport_remove */ -skip; /* old thread_set_priority */ - -/* - * Increment the suspend count for the target task. - * No threads within a task may run when the suspend - * count for that task is non-zero. - */ -routine task_suspend( - target_task : task_t); - -/* - * Decrement the suspend count for the target task, - * if the count is currently non-zero. If the resulting - * suspend count is zero, then threads within the task - * that also have non-zero suspend counts may execute. - */ -routine task_resume( - target_task : task_t); - -/* - * Returns the current value of the selected special port - * associated with the target task. - */ -routine task_get_special_port( - task : task_t; - which_port : int; - out special_port : mach_port_send_t); - -/* - * Set one of the special ports associated with the - * target task. - */ -routine task_set_special_port( - task : task_t; - which_port : int; - special_port : mach_port_t); - -/* obsolete */ -routine xxx_task_info( - target_task : task_t; - flavor : int; - out task_info_out : task_info_t, IsLong); - - -/* - * Create a new thread within the target task, returning - * the port representing that new thread. The - * initial execution state of the thread is undefined. - */ -routine thread_create( - parent_task : task_t; - out child_thread : mach_port_send_t); - -/* - * Increment the suspend count for the target thread. - * Once this call has completed, the thread will not - * execute any further user or meta- instructions. - * Once suspended, a thread may not execute again until - * its suspend count is zero, and the suspend count - * for its task is also zero. - */ -routine thread_suspend( - target_thread : thread_t); - -/* - * Decrement the suspend count for the target thread, - * if that count is not already zero. - */ -routine thread_resume( - target_thread : thread_t); - -/* - * Cause any user or meta- instructions currently being - * executed by the target thread to be aborted. [Meta- - * instructions consist of the basic traps for IPC - * (e.g., msg_send, msg_receive) and self-identification - * (e.g., task_self, thread_self, thread_reply). Calls - * described by MiG interfaces are not meta-instructions - * themselves.] - */ -routine thread_abort( - target_thread : thread_t); - -/* obsolete */ -routine xxx_thread_get_state( - target_thread : thread_t; - flavor : int; - out old_state : thread_state_t, IsLong); - -/* obsolete */ -routine xxx_thread_set_state( - target_thread : thread_t; - flavor : int; - new_state : thread_state_t, IsLong); - -/* - * Returns the current value of the selected special port - * associated with the target thread. - */ -routine thread_get_special_port( - thread : thread_t; - which_port : int; - out special_port : mach_port_t); - -/* - * Set one of the special ports associated with the - * target thread. - */ -routine thread_set_special_port( - thread : thread_t; - which_port : int; - special_port : mach_port_t); - -/* obsolete */ -routine xxx_thread_info( - target_thread : thread_t; - flavor : int; - out thread_info_out : thread_info_t, IsLong); - -/* - * Establish a user-level handler for the specified - * system call. - */ -routine task_set_emulation( - target_port : task_t; - routine_entry_pt: vm_address_t; - routine_number : int); - -/* - * Establish restart pc for interrupted atomic sequences. - * This reuses the message number for the old task_get_io_port. - * See task_info.h for description of flavors. - * - */ -routine task_ras_control( - target_task : task_t; - basepc : vm_address_t; - boundspc : vm_address_t; - flavor : int); - - - -skip; /* old host_ipc_statistics */ -skip; /* old port_names */ -skip; /* old port_type */ -skip; /* old port_rename */ -skip; /* old port_allocate */ -skip; /* old port_deallocate */ -skip; /* old port_set_backlog */ -skip; /* old port_status */ -skip; /* old port_set_allocate */ -skip; /* old port_set_deallocate */ -skip; /* old port_set_add */ -skip; /* old port_set_remove */ -skip; /* old port_set_status */ -skip; /* old port_insert_send */ -skip; /* old port_extract_send */ -skip; /* old port_insert_receive */ -skip; /* old port_extract_receive */ - -/* - * Map a user-defined memory object into the virtual address - * space of the target task. If desired (anywhere is TRUE), - * the kernel will find a suitable address range of the - * specified size; else, the specific address will be allocated. - * - * The beginning address of the range will be aligned on a virtual - * page boundary, be at or beyond the address specified, and - * meet the mask requirements (bits turned on in the mask must not - * be turned on in the result); the size of the range, in bytes, - * will be rounded up to an integral number of virtual pages. - * - * The memory in the resulting range will be associated with the - * specified memory object, with the beginning of the memory range - * referring to the specified offset into the memory object. - * - * The mapping will take the current and maximum protections and - * the inheritance attributes specified; see the vm_protect and - * vm_inherit calls for a description of these attributes. - * - * If desired (copy is TRUE), the memory range will be filled - * with a copy of the data from the memory object; this copy will - * be private to this mapping in this target task. Otherwise, - * the memory in this mapping will be shared with other mappings - * of the same memory object at the same offset (in this task or - * in other tasks). [The Mach kernel only enforces shared memory - * consistency among mappings on one host with similar page alignments. - * The user-defined memory manager for this object is responsible - * for further consistency.] - */ -#ifdef EMULATOR -routine htg_vm_map( - target_task : vm_task_t; - ureplyport reply_port : mach_port_make_send_once_t; - inout address : vm_address_t; - size : vm_size_t; - mask : vm_address_t; - anywhere : boolean_t; - memory_object : memory_object_t; - offset : vm_offset_t; - copy : boolean_t; - cur_protection : vm_prot_t; - max_protection : vm_prot_t; - inheritance : vm_inherit_t); -#else /* EMULATOR */ -routine vm_map( - target_task : vm_task_t; - inout address : vm_address_t; - size : vm_size_t; - mask : vm_address_t; - anywhere : boolean_t; - memory_object : memory_object_t; - offset : vm_offset_t; - copy : boolean_t; - cur_protection : vm_prot_t; - max_protection : vm_prot_t; - inheritance : vm_inherit_t); -#endif /* EMULATOR */ - -/* - * Indicate that a range of the specified memory object cannot - * be provided at this time. [Threads waiting for memory pages - * specified by this call will experience a memory exception. - * Only threads waiting at the time of the call are affected.] - */ -simpleroutine memory_object_data_error( - memory_control : memory_object_control_t; - offset : vm_offset_t; - size : vm_size_t; - error_value : kern_return_t); - -/* - * Make decisions regarding the use of the specified - * memory object. - */ -simpleroutine memory_object_set_attributes( - memory_control : memory_object_control_t; - object_ready : boolean_t; - may_cache : boolean_t; - copy_strategy : memory_object_copy_strategy_t); - -/* - */ -simpleroutine memory_object_destroy( - memory_control : memory_object_control_t; - reason : kern_return_t); - -/* - * Provide the data contents of a range of the given memory - * object, with the access restriction specified, optional - * precious attribute, and reply message. [Only - * whole virtual pages of data can be accepted; partial pages - * will be discarded. Data should be provided on request, but - * may be provided in advance as desired. When data already - * held by this kernel is provided again, the new data is ignored. - * The access restriction is the subset of {read, write, execute} - * which are prohibited. The kernel may not provide any data (or - * protection) consistency among pages with different virtual page - * alignments within the same object. The precious value controls - * how the kernel treats the data. If it is FALSE, the kernel treats - * its copy as a temporary and may throw it away if it hasn't been - * changed. If the precious value is TRUE, the kernel treats its - * copy as a data repository and promises to return it to the manager; - * the manager may tell the kernel to throw it away instead by flushing - * and not cleaning the data -- see memory_object_lock_request. The - * reply_to port is for a compeletion message; it will be - * memory_object_supply_completed.] - */ - -simpleroutine memory_object_data_supply( - memory_control : memory_object_control_t; - offset : vm_offset_t; - data : pointer_t, Dealloc[]; - lock_value : vm_prot_t; - precious : boolean_t; - reply_to : mach_port_t = - MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); - -simpleroutine memory_object_ready( - memory_control : memory_object_control_t; - may_cache : boolean_t; - copy_strategy : memory_object_copy_strategy_t); - -simpleroutine memory_object_change_attributes( - memory_control : memory_object_control_t; - may_cache : boolean_t; - copy_strategy : memory_object_copy_strategy_t; - reply_to : mach_port_t = - MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); - -skip; /* old host_callout_statistics_reset */ -skip; /* old port_set_select */ -skip; /* old port_set_backup */ - -/* - * Set/Get special properties of memory associated - * to some virtual address range, such as cachability, - * migrability, replicability. Machine-dependent. - */ -routine vm_machine_attribute( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - attribute : vm_machine_attribute_t; - inout value : vm_machine_attribute_val_t); - -skip; /* old host_fpa_counters_reset */ - -/* - * There is no more room in this interface for additional calls. - */ diff --git a/boot-proxy-exc/ourmach_host.defs b/boot-proxy-exc/ourmach_host.defs deleted file mode 100644 index c8576ddb..00000000 --- a/boot-proxy-exc/ourmach_host.defs +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University. - * Copyright (c) 1993,1994 The University of Utah and - * the Computer Systems Laboratory (CSL). - * All rights reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF - * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY - * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF - * THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: mach/mach_host.defs - * - * Abstract: - * Mach host operations support. Includes processor allocation and - * control. - */ - -#ifdef MACH_KERNEL -simport <kern/compat_xxx_defs.h>; /* for obsolete routines */ -#endif - -subsystem -#if KERNEL_SERVER - KernelServer -#endif - mach_host 2600; - -serverprefix S_; - -/* - * Basic types - */ - -#include <mach/std_types.defs> -#include <mach/mach_types.defs> - -/* - * Get list of processors on this host. - */ - -routine host_processors( - host_priv : host_priv_t; - out processor_list : processor_array_t); - -/* obsolete */ -routine yyy_host_info( - host : host_t; - flavor : int; - out host_info_out : host_info_t, IsLong); - - -/* obsolete */ -routine yyy_processor_info( - processor : processor_t; - flavor : int; - out host : host_t; - out processor_info_out: processor_info_t, IsLong); - -/* - * Start processor. - */ - -routine processor_start( - processor : processor_t); - -/* - * Exit processor -- may not be restartable. - */ - -routine processor_exit( - processor : processor_t); - -/* obsolete */ -routine yyy_processor_control( - processor : processor_t; - processor_cmd : processor_info_t, IsLong); - -/* - * Get default processor set for host. - */ -routine processor_set_default( - host : host_t; - out default_set : processor_set_name_t); - -/* - * Get rights to default processor set for host. - * Replaced by host_processor_set_priv. - */ -routine xxx_processor_set_default_priv( - host : host_priv_t; - out default_set : processor_set_t); - -/* - * Create new processor set. Returns real port for manipulations, - * and name port for obtaining information. - */ -routine processor_set_create( - host : host_t; - out new_set : processor_set_t; - out new_name : processor_set_name_t); - -/* - * Destroy processor set. - */ -routine processor_set_destroy( - set : processor_set_t); - -/* obsolete */ -routine yyy_processor_set_info( - set_name : processor_set_name_t; - flavor : int; - out host : host_t; - out info_out : processor_set_info_t, IsLong); - -/* - * Assign processor to processor set. - */ -routine processor_assign( - processor : processor_t; - new_set : processor_set_t; - wait : boolean_t); - -/* - * Get current assignment for processor. - */ - -routine processor_get_assignment( - processor : processor_t; - out assigned_set : processor_set_name_t); - -/* - * Assign thread to processor set. - */ -routine thread_assign( - thread : thread_t; - new_set : processor_set_t); - -/* - * Assign thread to default set. - */ -routine thread_assign_default( - thread : thread_t); - -/* - * Get current assignment for thread. - */ -routine thread_get_assignment( - thread : thread_t; - out assigned_set : processor_set_name_t); - -/* - * Assign task to processor set. - */ -routine task_assign( - task : task_t; - new_set : processor_set_t; - assign_threads : boolean_t); -/* - * Assign task to default set. - */ -routine task_assign_default( - task : task_t; - assign_threads : boolean_t); - -/* - * Get current assignment for task. - */ -routine task_get_assignment( - task : task_t; - out assigned_set : processor_set_name_t); - -/* - * Get string describing current kernel version. - */ -routine host_kernel_version( - host : host_t; - out kernel_version : kernel_version_t); - -/* - * Set priority for thread. - */ -routine thread_priority( - thread : thread_t; - priority : int; - set_max : boolean_t); - -/* - * Set max priority for thread. - */ -routine thread_max_priority( - thread : thread_t; - processor_set : processor_set_t; - max_priority : int); - -/* - * Set task priority. - */ -routine task_priority( - task : task_t; - priority : int; - change_threads : boolean_t); - -/* - * Set max priority for processor_set. - */ -routine processor_set_max_priority( - processor_set : processor_set_t; - max_priority : int; - change_threads : boolean_t); - -/* - * Set policy for thread - */ -routine thread_policy( - thread : thread_t; - policy : int; - data : int); - -/* - * Enable policy for processor set - */ -routine processor_set_policy_enable( - processor_set : processor_set_t; - policy : int); - -/* - * Disable policy for processor set - */ -routine processor_set_policy_disable( - processor_set : processor_set_t; - policy : int; - change_threads : boolean_t); -/* - * List all tasks in processor set. - */ -routine processor_set_tasks( - processor_set : processor_set_t; - out task_list : task_array_t, dealloc); - -/* - * List all threads in processor set. - */ -routine processor_set_threads( - processor_set : processor_set_t; - out thread_list : thread_array_t); - -/* - * List all processor sets on host. - */ -routine host_processor_sets( - host : host_t; - out processor_sets : processor_set_name_array_t); - -/* - * Get control port for a processor set. - */ -routine host_processor_set_priv( - host_priv : host_priv_t; - set_name : processor_set_name_t; - out set : mach_port_send_t); - -routine thread_depress_abort( - thread : thread_t); - -/* - * Set the time on this host. - * Only available to privileged users. - */ -routine host_set_time( - host_priv : host_priv_t; - new_time : time_value_t); - -/* - * Arrange for the time on this host to be gradually changed - * by an adjustment value, and return the old value. - * Only available to privileged users. - */ -routine host_adjust_time( - host_priv : host_priv_t; - in new_adjustment : time_value_t; - out old_adjustment : time_value_t); - -/* - * Get the time on this host. - * Available to all. - */ -routine host_get_time( - host : host_t; - out current_time : time_value_t); - -/* - * Reboot this host. - * Only available to privileged users. - */ -routine host_reboot( - host_priv : host_priv_t; - options : int); - -/* - * Specify that the range of the virtual address space - * of the target task must not cause page faults for - * the indicated accesses. - * - * [ To unwire the pages, specify VM_PROT_NONE. ] - */ -routine vm_wire( - host_priv : host_priv_t; - task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - access : vm_prot_t); - -/* - * Specify that the target thread must always be able - * to run and to allocate memory. - */ -routine thread_wire( - host_priv : host_priv_t; - thread : thread_t; - wired : boolean_t); - -/* - * Return information about this host. - */ - -routine host_info( - host : host_t; - flavor : int; - out host_info_out : host_info_t, CountInOut); - - -/* - * Return information about this processor. - */ -routine processor_info( - processor : processor_t; - flavor : int; - out host : host_t; - out processor_info_out: processor_info_t, CountInOut); - -/* - * Get information about processor set. - */ -routine processor_set_info( - set_name : processor_set_name_t; - flavor : int; - out host : host_t; - out info_out : processor_set_info_t, CountInOut); - -/* - * Do something machine-dependent to processor. - */ -routine processor_control( - processor : processor_t; - processor_cmd : processor_info_t); - -/* - * Get boot configuration information from kernel. - */ -routine host_get_boot_info( - host_priv : host_priv_t; - out boot_info : kernel_boot_info_t); diff --git a/boot-proxy-exc/ourmach_port.defs b/boot-proxy-exc/ourmach_port.defs deleted file mode 100644 index 4f131bb2..00000000 --- a/boot-proxy-exc/ourmach_port.defs +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University. - * Copyright (c) 1993,1994 The University of Utah and - * the Computer Systems Laboratory (CSL). - * All rights reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF - * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY - * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF - * THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: mach/mach_port.defs - * Author: Rich Draves - * - * Copyright (c) 1989 Richard P. Draves, Jr. - * - * Exported kernel calls. - */ - -subsystem -#if KERNEL_SERVER - KernelServer -#endif - mach_port 3200; - -#include <mach/std_types.defs> -#include <mach/mach_types.defs> - -/* - * Returns the set of port and port set names - * to which the target task has access, along with - * the type (set or port) for each name. - */ - -routine mach_port_names( - task : ipc_space_t; - out names : mach_port_name_array_t = - ^array[] of mach_port_name_t - ctype: mach_port_array_t, - dealloc; - out types : mach_port_type_array_t = - ^array[] of mach_port_type_t, - dealloc); - -/* - * Returns the type (set or port) for the port name - * within the target task. Also indicates whether - * there is a dead-name request for the name. - */ - -routine mach_port_type( - task : ipc_space_t; - name : mach_port_name_t; - out ptype : mach_port_type_t); - -/* - * Changes the name by which a port (or port set) is known to - * the target task. The new name can't be in use. The - * old name becomes available for recycling. - */ - -routine mach_port_rename( - task : ipc_space_t; - old_name : mach_port_name_t; - new_name : mach_port_name_t); - -/* - * Allocates the specified kind of object, with the given name. - * The right must be one of - * MACH_PORT_RIGHT_RECEIVE - * MACH_PORT_RIGHT_PORT_SET - * MACH_PORT_RIGHT_DEAD_NAME - * New port sets are empty. New ports don't have any - * send/send-once rights or queued messages. The make-send - * count is zero and their queue limit is MACH_PORT_QLIMIT_DEFAULT. - * New sets, ports, and dead names have one user reference. - */ - -routine mach_port_allocate_name( - task : ipc_space_t; - right : mach_port_right_t; - name : mach_port_name_t); - -/* - * Allocates the specified kind of object. - * The right must be one of - * MACH_PORT_RIGHT_RECEIVE - * MACH_PORT_RIGHT_PORT_SET - * MACH_PORT_RIGHT_DEAD_NAME - * Like port_allocate_name, but the kernel picks a name. - * It can use any name not associated with a right. - */ - -routine mach_port_allocate( - task : ipc_space_t; - right : mach_port_right_t; - out name : mach_port_name_t); - -/* - * Destroys all rights associated with the name and makes it - * available for recycling immediately. The name can be a - * port (possibly with multiple user refs), a port set, or - * a dead name (again, with multiple user refs). - */ - -routine mach_port_destroy( - task : ipc_space_t; - name : mach_port_name_t); - -/* - * Releases one send/send-once/dead-name user ref. - * Just like mach_port_mod_refs -1, but deduces the - * correct type of right. This allows a user task - * to release a ref for a port without worrying - * about whether the port has died or not. - */ - -routine mach_port_deallocate( - task : ipc_space_t; - name : mach_port_name_t); - -/* - * A port set always has one user ref. - * A send-once right always has one user ref. - * A dead name always has one or more user refs. - * A send right always has one or more user refs. - * A receive right always has one user ref. - * The right must be one of - * MACH_PORT_RIGHT_RECEIVE - * MACH_PORT_RIGHT_PORT_SET - * MACH_PORT_RIGHT_DEAD_NAME - * MACH_PORT_RIGHT_SEND - * MACH_PORT_RIGHT_SEND_ONCE - */ - -routine mach_port_get_refs( - task : ipc_space_t; - name : mach_port_name_t; - right : mach_port_right_t; - out refs : mach_port_urefs_t); - -/* - * The delta is a signed change to the task's - * user ref count for the right. Only dead names - * and send rights can have a positive delta. - * The resulting user ref count can't be negative. - * If it is zero, the right is deallocated. - * If the name isn't a composite right, it becomes - * available for recycling. The right must be one of - * MACH_PORT_RIGHT_RECEIVE - * MACH_PORT_RIGHT_PORT_SET - * MACH_PORT_RIGHT_DEAD_NAME - * MACH_PORT_RIGHT_SEND - * MACH_PORT_RIGHT_SEND_ONCE - */ - -routine mach_port_mod_refs( - task : ipc_space_t; - name : mach_port_name_t; - right : mach_port_right_t; - delta : mach_port_delta_t); - -/* - * Temporary compatibility call. - */ - -routine old_mach_port_get_receive_status( - task : ipc_space_t; - name : mach_port_name_t; - out status : old_mach_port_status_t); - -/* - * Only valid for receive rights. - * Sets the queue-limit for the port. - * The limit must be - * 1 <= qlimit <= MACH_PORT_QLIMIT_MAX - */ - -routine mach_port_set_qlimit( - task : ipc_space_t; - name : mach_port_name_t; - qlimit : mach_port_msgcount_t); - -/* - * Only valid for receive rights. - * Sets the make-send count for the port. - */ - -routine mach_port_set_mscount( - task : ipc_space_t; - name : mach_port_name_t; - mscount : mach_port_mscount_t); - -/* - * Only valid for port sets. Returns a list of - * the members. - */ - -routine mach_port_get_set_status( - task : ipc_space_t; - name : mach_port_name_t; - out members : mach_port_name_array_t = - ^array[] of mach_port_name_t - ctype: mach_port_array_t, - dealloc); - -/* - * Puts the member port (the task must have receive rights) - * into the after port set. (Or removes it from any port set - * if after is MACH_PORT_NULL.) If the port is already in - * a set, does an atomic move. - */ - -routine mach_port_move_member( - task : ipc_space_t; - member : mach_port_name_t; - after : mach_port_name_t); - -/* - * Requests a notification from the kernel. The request - * must supply the send-once right which is used for - * the notification. If a send-once right was previously - * registered, it is returned. The msg_id must be one of - * MACH_NOTIFY_PORT_DESTROYED (receive rights) - * MACH_NOTIFY_DEAD_NAME (send/receive/send-once rights) - * MACH_NOTIFY_NO_SENDERS (receive rights) - * - * The sync value specifies whether a notification should - * get sent immediately, if appropriate. The exact meaning - * depends on the notification: - * MACH_NOTIFY_PORT_DESTROYED: must be zero. - * MACH_NOTIFY_DEAD_NAME: if non-zero, then name can be dead, - * and the notification gets sent immediately. - * If zero, then name can't be dead. - * MACH_NOTIFY_NO_SENDERS: the notification gets sent - * immediately if the current mscount is greater - * than or equal to the sync value and there are no - * extant send rights. - */ - -routine mach_port_request_notification( - task : ipc_space_t; - name : mach_port_name_t; - id : mach_msg_id_t; - sync : mach_port_mscount_t; - notify : mach_port_send_once_t; - out previous : mach_port_send_once_t); - -/* - * Inserts the specified rights into the target task, - * using the specified name. If inserting send/receive - * rights and the task already has send/receive rights - * for the port, then the names must agree. In any case, - * the task gains a user ref for the port. - */ - -routine mach_port_insert_right( - task : ipc_space_t; - name : mach_port_name_t; - poly : mach_port_poly_t); - -/* - * Returns the specified right for the named port - * in the target task, extracting that right from - * the target task. The target task loses a user - * ref and the name may be available for recycling. - * msgt_name must be one of - * MACH_MSG_TYPE_MOVE_RECEIVE - * MACH_MSG_TYPE_COPY_SEND - * MACH_MSG_TYPE_MAKE_SEND - * MACH_MSG_TYPE_MOVE_SEND - * MACH_MSG_TYPE_MAKE_SEND_ONCE - * MACH_MSG_TYPE_MOVE_SEND_ONCE - */ - -routine mach_port_extract_right( - task : ipc_space_t; - name : mach_port_name_t; - msgt_name : mach_msg_type_name_t; - out poly : mach_port_poly_t); - -/* - * The task must have receive rights for the named port. - * Returns a status structure (see mach/port.h). - */ - -routine mach_port_get_receive_status( - task : ipc_space_t; - name : mach_port_name_t; - out status : mach_port_status_t); - -/* - * Only valid for receive rights. - * Sets the sequence number for the port. - */ - -routine mach_port_set_seqno( - task : ipc_space_t; - name : mach_port_name_t; - seqno : mach_port_seqno_t); - -#ifdef MIGRATING_THREADS -/* - * Only valid for receive rights. - * Set the user-mode entry info for RPCs coming through this port. - * Do this BEFORE attaching an ActPool to this port, - * unless you can be sure no RPCs will be coming through it yet. - */ - -routine mach_port_set_rpcinfo( - task : ipc_space_t; - name : mach_port_name_t; - rpc_info : thread_info_t); /* XXX */ - -/* - * Only valid for receive rights. - * Create a new activation for migrating RPC, and attach it to the port's ActPool. - * Create an ActPool for the port if it doesn't already have one. - * Supply a stack and receive memory buffer. - */ - -routine mach_port_create_act( - task : task_t; - name : mach_port_name_t; - user_stack : vm_offset_t; - user_rbuf : vm_offset_t; - user_rbuf_size : vm_size_t; - out new_act : thread_t); - -#endif /* MIGRATING_THREADS */ - diff --git a/boot-proxy-exc/sigvec.S b/boot-proxy-exc/sigvec.S deleted file mode 100644 index cc7bb94e..00000000 --- a/boot-proxy-exc/sigvec.S +++ /dev/null @@ -1,23 +0,0 @@ -#include <i386/asm.h> - -.text -ENTRY(sigreturn) - movl $0x67,%eax - lcall $0x7,$0x0 - jb error - ret -ENTRY(_sigreturn) - addl $0xc,%esp - call EXT(sigreturn) - ret -ENTRY(sigvec) - movl $0x6c,%eax - movl $EXT(_sigreturn),%edx - orl $0x80000000,%edx - lcall $0x7,$0x0 - jb error - ret -error: - movl %eax,EXT(errno) - movl $-1,%eax - ret diff --git a/boot-proxy-exc/syscall.S b/boot-proxy-exc/syscall.S deleted file mode 100644 index a04ab28d..00000000 --- a/boot-proxy-exc/syscall.S +++ /dev/null @@ -1,35 +0,0 @@ -/* Temporary.... - Copyright (C) 1993, 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. */ - -#include <i386/asm.h> - -/* .globl EXT(errno)*/ -.text -ENTRY(syscall) - pop %ecx - pop %eax - push %ecx - lcall $7, $0 - push %ecx /* Restore stack position. */ - jb error - ret -error: - movl %eax,EXT(errno) - movl $-1,%eax - ret diff --git a/boot-proxy-exc/userland-boot.c b/boot-proxy-exc/userland-boot.c deleted file mode 100644 index 20c818ff..00000000 --- a/boot-proxy-exc/userland-boot.c +++ /dev/null @@ -1,122 +0,0 @@ -/* boot_script.c support functions for running in a Mach user task. - Copyright (C) 2001 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 <mach.h> -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <error.h> -#include "boot_script.h" -#include "mach_proxy.h" -#include "util.h" - -extern boolean_t is_user; - -void * -boot_script_malloc (unsigned int size) -{ - return malloc (size); -} - -void -boot_script_free (void *ptr, unsigned int size) -{ - free (ptr); -} - -int -boot_script_task_create (struct cmd *cmd) -{ - error_t err = task_create (mach_task_self (), 0, &cmd->task); - if (err) - { - error (0, err, "%s: task_create", cmd->path); - return BOOT_SCRIPT_MACH_ERROR; - } - debug ("creating task: %s, task port: %d", cmd->path, cmd->task); - if (is_user) - { - task_t pseudo_task = 0; - create_pseudo_task (cmd->task, &pseudo_task); - /* now it is the pseudo task port. */ - cmd->task = pseudo_task; - } - err = task_suspend (cmd->task); - if (err) - { - error (0, err, "%s: task_suspend", cmd->path); - return BOOT_SCRIPT_MACH_ERROR; - } - return 0; -} - -int -boot_script_task_resume (struct cmd *cmd) -{ - debug ("resume task %s: %d", cmd->path, cmd->task); - error_t err = task_resume (cmd->task); - if (err) - { - error (0, err, "%s: task_resume", cmd->path); - return BOOT_SCRIPT_MACH_ERROR; - } - return 0; -} - -int -boot_script_prompt_task_resume (struct cmd *cmd) -{ - char xx[5]; - - printf ("Hit return to resume %s...", cmd->path); - fgets (xx, sizeof xx, stdin); - - return boot_script_task_resume (cmd); -} - -void -boot_script_free_task (task_t task, int aborting) -{ - if (aborting) - task_terminate (task); - else if (!is_user) - mach_port_deallocate (mach_task_self (), task); - /* For the normal user, the task port will still be used, - * so we cannot deallocate the task port here.*/ -} - -int -boot_script_insert_right (struct cmd *cmd, mach_port_t port, mach_port_t *name) -{ - error_t err = mach_port_insert_right (cmd->task, - port, port, MACH_MSG_TYPE_COPY_SEND); - if (err) - { - error (0, err, "%s: mach_port_insert_right", cmd->path); - return BOOT_SCRIPT_MACH_ERROR; - } - *name = port; - return 0; -} - -int -boot_script_insert_task_port (struct cmd *cmd, task_t task, mach_port_t *name) -{ - return boot_script_insert_right (cmd, task, name); -} diff --git a/boot-proxy-exc/util.h b/boot-proxy-exc/util.h deleted file mode 100644 index e82a8626..00000000 --- a/boot-proxy-exc/util.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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 UTIL_H -#define UTIL_H - -#include <stdio.h> -#include <string.h> - -#include <sys/types.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <netinet/ip.h> -#include <syslog.h> - -#include <mach.h> -#include <hurd.h> - -#define DEBUG 0 -#define INFO 1 -#define LOGLEVEL DEBUG - -extern FILE *logfile; - -#define LOG_START() do \ -{ \ - logfile = fopen("boot.log", "a"); \ - assert (logfile != NULL); \ -} while (0) - -#define LOG_END() fclose (logfile) - -#define output(format, ...) do \ -{ \ - char buf[1024]; \ - snprintf (buf, 1024, "boot: %s: %s\r\n", __func__, format); \ - fprintf (stderr , buf, ## __VA_ARGS__); \ - fflush (stderr); \ -} while (0) - -#if DEBUG >= LOGLEVEL -#define debug(format, ...) do \ -{ \ - char buf[1024]; \ - snprintf (buf, 1024, "boot: %s: %s\r\n", __func__, format); \ - fprintf (logfile , buf, ## __VA_ARGS__); \ - fflush (logfile); \ -} while (0) -#else -#define debug(format, ...) do {} while (0) -#endif - -#if INFO >= LOGLEVEL -#define info output -#else -#define info(format, ...) do {} while (0) -#endif - -#if ERROR >= LOGLEVEL -#define logerror(format, ...) do \ -{ \ - char buf[1024]; \ - snprintf (buf, 1024, "boot ERROR: %s: %s\r\n", __func__, format); \ - fprintf (stderr , buf, ## __VA_ARGS__); \ - fflush (stderr); \ -} while (0) -#else -#define logerror(format, ...) do {} while (0) -#endif - -#define print_port_type(port) do \ -{ \ - mach_port_type_t ptype; \ - error_t err = mach_port_type (mach_task_self (), port, &ptype); \ - if (err) \ - debug ("mach_port_type: %s", strerror (err)); \ - else if (ptype & MACH_PORT_TYPE_SEND) \ - debug ("port %d has send right", port); \ - else if (ptype & MACH_PORT_TYPE_RECEIVE) \ - debug ("port %d has receive right", port); \ - else if (ptype & MACH_PORT_TYPE_SEND_ONCE) \ - debug ("port %d has send once right", port); \ - else if (ptype & MACH_PORT_TYPE_PORT_SET) \ - debug ("port %d is port set", port); \ - else if (ptype & MACH_PORT_TYPE_DEAD_NAME) \ - debug ("port %d is a dead name", port); \ - else \ - debug ("the type of port %d is %d", port, ptype); \ - mach_port_urefs_t refs; \ - err = mach_port_get_refs (mach_task_self (), port, \ - MACH_PORT_RIGHT_SEND, &refs); \ - if (!err) \ - debug ("port send right references: %d", refs); \ -} while (0) - -#endif diff --git a/boot-proxy-exc/ux.c b/boot-proxy-exc/ux.c deleted file mode 100644 index b532f19e..00000000 --- a/boot-proxy-exc/ux.c +++ /dev/null @@ -1,303 +0,0 @@ -/* Hacks to make boot work under UX - - Copyright (C) 1993, 1994, 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 the GNU Hurd; see the file COPYING. If not, write to - the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include <mach.h> -#include <sys/types.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <cthreads.h> - -#include "ux.h" - -#if 0 -static int (* const _sc)(int, ...) = &syscall; -int _sc_print = 1; - -#define syscall(num, args...) \ - ({ int _rv, _num = (num), _pr = _sc_print; \ - _sc_print = 0; \ - if (_pr) printf ("syscall (%d) start\r\n", _num); \ - _rv = (*_sc) (_num , ##args); \ - if (_pr) printf ("syscall (%d) end\r\n", _num); \ - _sc_print = _pr; \ - _rv; \ - }) -#endif - -extern void __mach_init (); -void (*mach_init_routine)() = __mach_init; - -/* These will prevent the Hurd-ish versions from being used */ - -struct free_reply_port -{ - mach_port_t port; - struct free_reply_port *next; -}; -static struct free_reply_port *free_reply_ports = NULL; -static spin_lock_t free_reply_ports_lock = SPIN_LOCK_INITIALIZER; - -mach_port_t __mig_get_reply_port () -{ - spin_lock (&free_reply_ports_lock); - if (free_reply_ports == NULL) - { - spin_unlock (&free_reply_ports_lock); - return __mach_reply_port (); - } - else - { - struct free_reply_port *frp = free_reply_ports; - mach_port_t reply_port = frp->port; - free_reply_ports = free_reply_ports->next; - spin_unlock (&free_reply_ports_lock); - free (frp); - return reply_port; - } -} -mach_port_t mig_get_reply_port () -{ - return __mig_get_reply_port (); -} -void __mig_put_reply_port (mach_port_t port) -{ - struct free_reply_port *frp = malloc (sizeof (struct free_reply_port)); - frp->port = port; - spin_lock (&free_reply_ports_lock); - frp->next = free_reply_ports; - free_reply_ports = frp; - spin_unlock (&free_reply_ports_lock); -} -void mig_put_reply_port (mach_port_t port) -{ - __mig_put_reply_port (port); -} -void __mig_dealloc_reply_port (mach_port_t port) -{ - mach_port_mod_refs (__mach_task_self (), port, - MACH_PORT_RIGHT_RECEIVE, -1); -} -void mig_dealloc_reply_port (mach_port_t port) -{ - __mig_dealloc_reply_port (port); -} -void __mig_init (void *stack) {} -void mig_init (void *stack) {} - -int -task_by_pid (int pid) -{ - return syscall (-33, pid); -} - -int -write (int fd, - const void *buf, - int buflen) -{ - return syscall (4, fd, buf, buflen); -} - -int -read (int fd, - void *buf, - int buflen) -{ - return syscall (3, fd, buf, buflen); -} - -int -open (const char *name, - int flags, - int mode) -{ - return syscall (5, name, flags, mode); -} - -int -uxfstat (int fd, struct uxstat *buf) -{ - return syscall (62, fd, buf); -} - -int -close (int fd) -{ - return syscall (6, fd); -} - -int -lseek (int fd, - int off, - int whence) -{ - return syscall (19, fd, off, whence); -} - -int -uxexit (int code) -{ - return syscall (1, code); -} - -int -getpid () -{ - return syscall (20); -} - -int -ioctl (int fd, int code, void *buf) -{ - return syscall (54, fd, code, buf); -} - -int -sigblock (int mask) -{ - return syscall (109, mask); -} - -int -sigsetmask (int mask) -{ - return syscall (110, mask); -} - -int -sigpause (int mask) -{ - return syscall (111, mask); -} - - -#if 0 -void -sigreturn () -{ - asm volatile ("movl $0x67,%eax\n" - "lcall $0x7, $0x0\n" - "ret"); -} - -void -_sigreturn () -{ - asm volatile ("addl $0xc, %%esp\n" - "call %0\n" - "ret"::"m" (sigreturn)); -} - -int -sigvec (int sig, struct sigvec *vec, struct sigvec *ovec) -{ - asm volatile ("movl $0x6c,%%eax\n" - "movl %0, %%edx\n" - "orl $0x80000000, %%edx\n" - "lcall $0x7,$0x0\n" - "ret"::"g" (_sigreturn)); -} -#else -int sigvec (); -#endif - -void get_privileged_ports (mach_port_t *host_port, mach_port_t *device_port) -{ - *host_port = task_by_pid (-1); - *device_port = task_by_pid (-2); -} - -/* A *really* stupid printf that only understands %s & %d. */ -int -printf (const char *fmt, ...) -{ - va_list ap; - const char *p = fmt, *q = p; - - void flush (const char *new) - { - if (p > q) - write (1, q, p - q); - q = p = new; - } - - va_start (ap, fmt); - while (*p) - if (*p == '%' && p[1] == 's') - { - char *str = va_arg (ap, char *); - flush (p + 2); - write (1, str, strlen (str)); - } - else if (*p == '%' && p[1] == 'd') - { - int i = va_arg (ap, int); - char rbuf[20], *e = rbuf + sizeof (rbuf), *b = e; - - if (i == 0) - *--b = '0'; - else - while (i) - { - *--b = i % 10 + '0'; - i /= 10; - } - - flush (p + 2); - write (1, b, e - b); - } - else - p++; - va_end (ap); - - flush (0); - - return 0; -} - -static struct sgttyb term_sgb; -static int localbits; - -void -init_termstate () -{ - struct sgttyb sgb; - int bits; - ioctl (0, TIOCGETP, &term_sgb); - ioctl (0, TIOCLGET, &localbits); - /* Enter raw made. Rather than try and interpret these bits, - we just do what emacs does in .../emacs/src/sysdep.c for - an old style terminal driver. */ - bits = localbits | LDECCTQ | LLITOUT | LPASS8 | LNOFLSH; - ioctl (0, TIOCLSET, &bits); - sgb = term_sgb; - sgb.sg_flags &= ~ECHO; - sgb.sg_flags |= RAW | ANYP; - ioctl (0, TIOCSETN, &sgb); -} - -void -restore_termstate () -{ - ioctl (0, TIOCLSET, &localbits); - ioctl (0, TIOCSETN, &term_sgb); -} diff --git a/boot-proxy-exc/ux.h b/boot-proxy-exc/ux.h deleted file mode 100644 index d3787c54..00000000 --- a/boot-proxy-exc/ux.h +++ /dev/null @@ -1,114 +0,0 @@ -/* Hacks to make boot work under UX - - Copyright (C) 1993, 1994, 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 the GNU Hurd; see the file COPYING. If not, write to - the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#define sigmask(m) (1 << ((m)-1)) - -#define IOCPARM_MASK 0x7f -#define IOC_OUT 0x40000000 -#define IOC_IN 0x80000000 -#define _IOR(x,y,t) (IOC_OUT|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y) -#define _IOW(x,y,t) (IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y) -#define FIONREAD _IOR('f', 127, int) -#define FIOASYNC _IOW('f', 125, int) -#define TIOCGETP _IOR('t', 8, struct sgttyb) -#define TIOCLGET _IOR('t', 124, int) -#define TIOCLSET _IOW('t', 125, int) -#define TIOCSETN _IOW('t', 10, struct sgttyb) -#define LDECCTQ 0x4000 -#define LLITOUT 0x0020 -#define LPASS8 0x0800 -#define LNOFLSH 0x8000 -#define RAW 0x0020 -#define ANYP 0x00c0 -#define ECHO 8 - - -struct sgttyb -{ - char unused[4]; - short sg_flags; -}; - -#define SIGIO 23 - -struct sigvec -{ - void (*sv_handler)(); - int sv_mask; - int sv_flags; -}; - -struct uxstat - { - short int st_dev; /* Device containing the file. */ - __ino_t st_ino; /* File serial number. */ - unsigned short int st_mode; /* File mode. */ - __nlink_t st_nlink; /* Link count. */ - unsigned short int st_uid; /* User ID of the file's owner. */ - unsigned short int st_gid; /* Group ID of the file's group.*/ - short int st_rdev; /* Device number, if device. */ - __off_t st_size; /* Size of file, in bytes. */ - __time_t st_atime; /* Time of last access. */ - unsigned long int st_atime_usec; - __time_t st_mtime; /* Time of last modification. */ - unsigned long int st_mtime_usec; - __time_t st_ctime; /* Time of last status change. */ - unsigned long int st_ctime_usec; - unsigned long int st_blksize; /* Optimal block size for I/O. */ - unsigned long int st_blocks; /* Number of 512-byte blocks allocated. */ - long int st_spare[2]; - }; - -void get_privileged_ports (mach_port_t *host_port, mach_port_t *device_port); - -/* We can't include <unistd.h> for this, because that will fight witho - our definitions of syscalls below. */ -int syscall (int, ...); - -int open (const char *name, int flags, int mode); -int write (int fd, const void *buf, int len); -int read (int fd, void *buf, int len); -int uxfstat (int fd, struct uxstat *buf); -int close (int fd); -int lseek (int fd, int off, int whence); -int uxexit (int code); -int getpid (); -int ioctl (int fd, int code, void *buf); -int sigblock (int mask); -int sigsetmask (int mask); -int sigpause (int mask); -int sigvec (int sig, struct sigvec *vec, struct sigvec *ovec); - -#undef O_RDONLY -#undef O_WRONLY -#undef O_RDWR -#define O_RDONLY 0 -#define O_WRONLY 1 -#define O_RDWR 2 - -#define host_exit(c) uxexit(c) - -typedef struct uxstat host_stat_t; -#define host_fstat(fd, st) uxfstat (fd, st) - -void init_stdio (); - -#undef errno -int errno; diff --git a/bsdfsck/Makefile b/bsdfsck/Makefile deleted file mode 100644 index b5dcfbf2..00000000 --- a/bsdfsck/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -# -# 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. - -dir := bsdfsck -makemode := utility - -SRCS = dir.c inode.c main.c pass1.c pass1b.c pass2.c pass3.c pass4.c \ - pass5.c setup.c utilities.c # preen.c -OBJS = dir.o inode.o main.o pass1.o pass1b.o pass2.o pass3.o pass4.o \ - pass5.o setup.o utilities.o tables.o # preen.o -LCLHDRS = fsck.h -target = bsdfsck - -vpath tables.c ../ufs - -include ../Makeconf - diff --git a/bsdfsck/dir.c b/bsdfsck/dir.c deleted file mode 100644 index e63473ae..00000000 --- a/bsdfsck/dir.c +++ /dev/null @@ -1,690 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)dir.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: dir.c,v 1.5 1994/11/04 21:54:56 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/dir.h" -#include "../ufs/fs.h" -#include <stdlib.h> -#include <string.h> -#include "fsck.h" - -char *lfname = "lost+found"; -int lfmode = 01777; -struct dirtemplate emptydir = { 0, DIRBLKSIZ }; -struct dirtemplate dirhead = { - 0, 12, DT_DIR, 1, ".", - 0, DIRBLKSIZ - 12, DT_DIR, 2, ".." -}; -struct odirtemplate odirhead = { - 0, 12, 1, ".", - 0, DIRBLKSIZ - 12, 2, ".." -}; - -struct direct *fsck_readdir(); -struct bufarea *getdirblk(); - -/* - * Propagate connected state through the tree. - */ -propagate() -{ - register struct inoinfo **inpp, *inp; - struct inoinfo **inpend; - long change; - - inpend = &inpsort[inplast]; - do { - change = 0; - for (inpp = inpsort; inpp < inpend; inpp++) { - inp = *inpp; - if (inp->i_parent == 0) - continue; - if (statemap[inp->i_parent] == DFOUND && - statemap[inp->i_number] == DSTATE) { - statemap[inp->i_number] = DFOUND; - change++; - } - } - } while (change > 0); -} - -/* - * Scan each entry in a directory block. - */ -dirscan(idesc) - register struct inodesc *idesc; -{ - register struct direct *dp; - register struct bufarea *bp; - int dsize, n; - long blksiz; - char dbuf[DIRBLKSIZ]; - - if (idesc->id_type != DATA) - errexit("wrong type to dirscan %d\n", idesc->id_type); - if (idesc->id_entryno == 0 && - (idesc->id_filesize & (DIRBLKSIZ - 1)) != 0) - idesc->id_filesize = roundup(idesc->id_filesize, DIRBLKSIZ); - blksiz = idesc->id_numfrags * sblock.fs_fsize; - if (chkrange(idesc->id_blkno, idesc->id_numfrags)) { - idesc->id_filesize -= blksiz; - return (SKIP); - } - idesc->id_loc = 0; - for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) { - dsize = dp->d_reclen; - bcopy((char *)dp, dbuf, (size_t)dsize); -# if (BYTE_ORDER == LITTLE_ENDIAN) - if (!newinofmt) { - struct direct *tdp = (struct direct *)dbuf; - u_char tmp; - - tmp = tdp->d_namlen; - tdp->d_namlen = tdp->d_type; - tdp->d_type = tmp; - } -# endif - idesc->id_dirp = (struct direct *)dbuf; - if ((n = (*idesc->id_func)(idesc)) & ALTERED) { -# if (BYTE_ORDER == LITTLE_ENDIAN) - if (!newinofmt && !doinglevel2) { - struct direct *tdp; - u_char tmp; - - tdp = (struct direct *)dbuf; - tmp = tdp->d_namlen; - tdp->d_namlen = tdp->d_type; - tdp->d_type = tmp; - } -# endif - bp = getdirblk(idesc->id_blkno, blksiz); - bcopy(dbuf, bp->b_un.b_buf + idesc->id_loc - dsize, - (size_t)dsize); - dirty(bp); - sbdirty(); - } - if (n & STOP) - return (n); - } - return (idesc->id_filesize > 0 ? KEEPON : STOP); -} - -/* - * get next entry in a directory. - */ -struct direct * -fsck_readdir(idesc) - register struct inodesc *idesc; -{ - register struct direct *dp, *ndp; - register struct bufarea *bp; - long size, blksiz, fix, dploc; - - blksiz = idesc->id_numfrags * sblock.fs_fsize; - bp = getdirblk(idesc->id_blkno, blksiz); - if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 && - idesc->id_loc < blksiz) { - dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc); - if (dircheck(idesc, dp)) - goto dpok; - fix = dofix(idesc, "DIRECTORY CORRUPTED"); - bp = getdirblk(idesc->id_blkno, blksiz); - dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc); - dp->d_reclen = DIRBLKSIZ; - dp->d_ino = 0; - dp->d_type = 0; - dp->d_namlen = 0; - dp->d_name[0] = '\0'; - if (fix) - dirty(bp); - idesc->id_loc += DIRBLKSIZ; - idesc->id_filesize -= DIRBLKSIZ; - return (dp); - } -dpok: - if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz) - return NULL; - dploc = idesc->id_loc; - dp = (struct direct *)(bp->b_un.b_buf + dploc); - idesc->id_loc += dp->d_reclen; - idesc->id_filesize -= dp->d_reclen; - if ((idesc->id_loc % DIRBLKSIZ) == 0) - return (dp); - ndp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc); - if (idesc->id_loc < blksiz && idesc->id_filesize > 0 && - dircheck(idesc, ndp) == 0) { - size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ); - idesc->id_loc += size; - idesc->id_filesize -= size; - fix = dofix(idesc, "DIRECTORY CORRUPTED"); - bp = getdirblk(idesc->id_blkno, blksiz); - dp = (struct direct *)(bp->b_un.b_buf + dploc); - dp->d_reclen += size; - if (fix) - dirty(bp); - } - return (dp); -} - -/* - * Verify that a directory entry is valid. - * This is a superset of the checks made in the kernel. - */ -dircheck(idesc, dp) - struct inodesc *idesc; - register struct direct *dp; -{ - register int size; - register char *cp; - u_char namlen, type; - int spaceleft; - spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ); - - if (dp->d_ino >= maxino || - dp->d_reclen == 0 || - dp->d_reclen > spaceleft || - (dp->d_reclen & 0x3) != 0) - return (0); - if (dp->d_ino == 0) - return (1); - size = DIRSIZ(!newinofmt, dp); -# if (BYTE_ORDER == LITTLE_ENDIAN) - if (!newinofmt) { - type = dp->d_namlen; - namlen = dp->d_type; - } else { - namlen = dp->d_namlen; - type = dp->d_type; - } -# else - namlen = dp->d_namlen; - type = dp->d_type; -# endif - if (dp->d_reclen < size || - idesc->id_filesize < size || - namlen > MAXNAMLEN || - type > 15) - return (0); - for (cp = dp->d_name, size = 0; size < namlen; size++) - if (*cp == '\0' || (*cp++ == '/')) - return (0); - if (*cp != '\0') - return (0); - return (1); -} - -direrror(ino, errmesg) - ino_t ino; - char *errmesg; -{ - - fileerror(ino, ino, errmesg); -} - -fileerror(cwd, ino, errmesg) - ino_t cwd, ino; - char *errmesg; -{ - register struct dinode *dp; - char pathbuf[MAXPATHLEN + 1]; - - pwarn("%s ", errmesg); - pinode(ino); - printf("\n"); - getpathname(pathbuf, cwd, ino); - if (ino < ROOTINO || ino > maxino) { - pfatal("NAME=%s\n", pathbuf); - return; - } - dp = ginode(ino); - if (ftypeok(dp)) - pfatal("%s=%s\n", - (DI_MODE(dp) & IFMT) == IFDIR ? "DIR" : "FILE", pathbuf); - else - pfatal("NAME=%s\n", pathbuf); -} - -adjust(idesc, lcnt) - register struct inodesc *idesc; - short lcnt; -{ - register struct dinode *dp; - - dp = ginode(idesc->id_number); - if (dp->di_nlink == lcnt) { - if (linkup(idesc->id_number, (ino_t)0) == 0) - clri(idesc, "UNREF", 0); - } else { - pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname : - ((DI_MODE(dp) & IFMT) == IFDIR ? "DIR" : "FILE")); - pinode(idesc->id_number); - printf(" COUNT %d SHOULD BE %d", - dp->di_nlink, dp->di_nlink - lcnt); - if (preen) { - if (lcnt < 0) { - printf("\n"); - pfatal("LINK COUNT INCREASING"); - } - printf(" (ADJUSTED)\n"); - } - if (preen || reply("ADJUST") == 1) { - dp->di_nlink -= lcnt; - inodirty(); - } - } -} - -mkentry(idesc) - struct inodesc *idesc; -{ - register struct direct *dirp = idesc->id_dirp; - struct direct newent; - int newlen, oldlen; - - newent.d_namlen = strlen(idesc->id_name); - newlen = DIRSIZ(0, &newent); - if (dirp->d_ino != 0) - oldlen = DIRSIZ(0, dirp); - else - oldlen = 0; - if (dirp->d_reclen - oldlen < newlen) - return (KEEPON); - newent.d_reclen = dirp->d_reclen - oldlen; - dirp->d_reclen = oldlen; - dirp = (struct direct *)(((char *)dirp) + oldlen); - dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */ - if (newinofmt) { - dirp->d_type = typemap[idesc->id_parent]; - dirp->d_namlen = newent.d_namlen; - } else { -# if (BYTE_ORDER == LITTLE_ENDIAN) - dirp->d_type = newent.d_namlen; - dirp->d_namlen = 0; -# else - dirp->d_type = 0; - dirp->d_namlen = newent.d_namlen; -# endif - } - dirp->d_reclen = newent.d_reclen; - bcopy(idesc->id_name, dirp->d_name, (size_t)newent.d_namlen + 1); - return (ALTERED|STOP); -} - -chgino(idesc) - struct inodesc *idesc; -{ - register struct direct *dirp = idesc->id_dirp; - - if (bcmp(dirp->d_name, idesc->id_name, (int)dirp->d_namlen + 1)) - return (KEEPON); - dirp->d_ino = idesc->id_parent; - if (newinofmt) - dirp->d_type = typemap[idesc->id_parent]; - else - dirp->d_type = 0; - return (ALTERED|STOP); -} - -linkup(orphan, parentdir) - ino_t orphan; - ino_t parentdir; -{ - register struct dinode *dp; - int lostdir; - ino_t oldlfdir; - struct inodesc idesc; - char tempname[BUFSIZ]; - extern int pass4check(); - - bzero((char *)&idesc, sizeof(struct inodesc)); - dp = ginode(orphan); - lostdir = (DI_MODE(dp) & IFMT) == IFDIR; - pwarn("UNREF %s ", lostdir ? "DIR" : "FILE"); - pinode(orphan); - if (preen && dp->di_size == 0) - return (0); - if (preen) - printf(" (RECONNECTED)\n"); - else - if (reply("RECONNECT") == 0) - return (0); - if (lfdir == 0) { - dp = ginode(ROOTINO); - idesc.id_name = lfname; - idesc.id_type = DATA; - idesc.id_func = findino; - idesc.id_number = ROOTINO; - if ((ckinode(dp, &idesc) & FOUND) != 0) { - lfdir = idesc.id_parent; - } else { - pwarn("NO lost+found DIRECTORY"); - if (preen || reply("CREATE")) { - lfdir = allocdir(ROOTINO, (ino_t)0, lfmode); - if (lfdir != 0) { - if (makeentry(ROOTINO, lfdir, lfname) != 0) { - if (preen) - printf(" (CREATED)\n"); - } else { - freedir(lfdir, ROOTINO); - lfdir = 0; - if (preen) - printf("\n"); - } - } - } - } - if (lfdir == 0) { - pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY"); - printf("\n\n"); - return (0); - } - } - dp = ginode(lfdir); - if ((DI_MODE(dp) & IFMT) != IFDIR) { - pfatal("lost+found IS NOT A DIRECTORY"); - if (reply("REALLOCATE") == 0) - return (0); - oldlfdir = lfdir; - if ((lfdir = allocdir(ROOTINO, (ino_t)0, lfmode)) == 0) { - pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n"); - return (0); - } - if ((changeino(ROOTINO, lfname, lfdir) & ALTERED) == 0) { - pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n"); - return (0); - } - inodirty(); - idesc.id_type = ADDR; - idesc.id_func = pass4check; - idesc.id_number = oldlfdir; - adjust(&idesc, lncntp[oldlfdir] + 1); - lncntp[oldlfdir] = 0; - dp = ginode(lfdir); - } - if (statemap[lfdir] != DFOUND) { - pfatal("SORRY. NO lost+found DIRECTORY\n\n"); - return (0); - } - (void)lftempname(tempname, orphan); - if (makeentry(lfdir, orphan, tempname) == 0) { - pfatal("SORRY. NO SPACE IN lost+found DIRECTORY"); - printf("\n\n"); - return (0); - } - lncntp[orphan]--; - if (lostdir) { - if ((changeino(orphan, "..", lfdir) & ALTERED) == 0 && - parentdir != (ino_t)-1) - (void)makeentry(orphan, lfdir, ".."); - dp = ginode(lfdir); - dp->di_nlink++; - inodirty(); - lncntp[lfdir]++; - pwarn("DIR I=%lu CONNECTED. ", orphan); - if (parentdir != (ino_t)-1) - printf("PARENT WAS I=%lu\n", parentdir); - if (preen == 0) - printf("\n"); - } - return (1); -} - -/* - * fix an entry in a directory. - */ -changeino(dir, name, newnum) - ino_t dir; - char *name; - ino_t newnum; -{ - struct inodesc idesc; - - bzero((char *)&idesc, sizeof(struct inodesc)); - idesc.id_type = DATA; - idesc.id_func = chgino; - idesc.id_number = dir; - idesc.id_fix = DONTKNOW; - idesc.id_name = name; - idesc.id_parent = newnum; /* new value for name */ - return (ckinode(ginode(dir), &idesc)); -} - -/* - * make an entry in a directory - */ -makeentry(parent, ino, name) - ino_t parent, ino; - char *name; -{ - struct dinode *dp; - struct inodesc idesc; - char pathbuf[MAXPATHLEN + 1]; - - if (parent < ROOTINO || parent >= maxino || - ino < ROOTINO || ino >= maxino) - return (0); - bzero((char *)&idesc, sizeof(struct inodesc)); - idesc.id_type = DATA; - idesc.id_func = mkentry; - idesc.id_number = parent; - idesc.id_parent = ino; /* this is the inode to enter */ - idesc.id_fix = DONTKNOW; - idesc.id_name = name; - dp = ginode(parent); - if (dp->di_size % DIRBLKSIZ) { - dp->di_size = roundup(dp->di_size, DIRBLKSIZ); - inodirty(); - } - if ((ckinode(dp, &idesc) & ALTERED) != 0) - return (1); - getpathname(pathbuf, parent, parent); - dp = ginode(parent); - if (expanddir(dp, pathbuf) == 0) - return (0); - return (ckinode(dp, &idesc) & ALTERED); -} - -/* - * Attempt to expand the size of a directory - */ -expanddir(dp, name) - register struct dinode *dp; - char *name; -{ - daddr_t lastbn, newblk; - register struct bufarea *bp; - char *cp, firstblk[DIRBLKSIZ]; - - lastbn = lblkno(&sblock, dp->di_size); - if (lastbn >= NDADDR - 1 || dp->di_db[lastbn] == 0 || dp->di_size == 0) - return (0); - if ((newblk = allocblk(sblock.fs_frag)) == 0) - return (0); - dp->di_db[lastbn + 1] = dp->di_db[lastbn]; - dp->di_db[lastbn] = newblk; - dp->di_size += sblock.fs_bsize; - dp->di_blocks += btodb(sblock.fs_bsize); - bp = getdirblk(dp->di_db[lastbn + 1], - (long)dblksize(&sblock, dp, lastbn + 1)); - if (bp->b_errs) - goto bad; - bcopy(bp->b_un.b_buf, firstblk, DIRBLKSIZ); - bp = getdirblk(newblk, sblock.fs_bsize); - if (bp->b_errs) - goto bad; - bcopy(firstblk, bp->b_un.b_buf, DIRBLKSIZ); - for (cp = &bp->b_un.b_buf[DIRBLKSIZ]; - cp < &bp->b_un.b_buf[sblock.fs_bsize]; - cp += DIRBLKSIZ) - bcopy((char *)&emptydir, cp, sizeof emptydir); - dirty(bp); - bp = getdirblk(dp->di_db[lastbn + 1], - (long)dblksize(&sblock, dp, lastbn + 1)); - if (bp->b_errs) - goto bad; - bcopy((char *)&emptydir, bp->b_un.b_buf, sizeof emptydir); - pwarn("NO SPACE LEFT IN %s", name); - if (preen) - printf(" (EXPANDED)\n"); - else if (reply("EXPAND") == 0) - goto bad; - dirty(bp); - inodirty(); - return (1); -bad: - dp->di_db[lastbn] = dp->di_db[lastbn + 1]; - dp->di_db[lastbn + 1] = 0; - dp->di_size -= sblock.fs_bsize; - dp->di_blocks -= btodb(sblock.fs_bsize); - freeblk(newblk, sblock.fs_frag); - return (0); -} - -/* - * allocate a new directory - */ -allocdir(parent, request, mode) - ino_t parent, request; - int mode; -{ - ino_t ino; - char *cp; - struct dinode *dp; - register struct bufarea *bp; - struct dirtemplate *dirp; - - ino = allocino(request, IFDIR|mode); - if (newinofmt) - dirp = &dirhead; - else - dirp = (struct dirtemplate *)&odirhead; - dirp->dot_ino = ino; - dirp->dotdot_ino = parent; - dp = ginode(ino); - bp = getdirblk(dp->di_db[0], sblock.fs_fsize); - if (bp->b_errs) { - freeino(ino); - return (0); - } - bcopy((char *)dirp, bp->b_un.b_buf, sizeof(struct dirtemplate)); - for (cp = &bp->b_un.b_buf[DIRBLKSIZ]; - cp < &bp->b_un.b_buf[sblock.fs_fsize]; - cp += DIRBLKSIZ) - bcopy((char *)&emptydir, cp, sizeof emptydir); - dirty(bp); - dp->di_nlink = 2; - inodirty(); - if (ino == ROOTINO) { - lncntp[ino] = dp->di_nlink; - cacheino(dp, ino); - return(ino); - } - if (statemap[parent] != DSTATE && statemap[parent] != DFOUND) { - freeino(ino); - return (0); - } - cacheino(dp, ino); - statemap[ino] = statemap[parent]; - if (statemap[ino] == DSTATE) { - lncntp[ino] = dp->di_nlink; - lncntp[parent]++; - } - dp = ginode(parent); - dp->di_nlink++; - inodirty(); - return (ino); -} - -/* - * free a directory inode - */ -freedir(ino, parent) - ino_t ino, parent; -{ - struct dinode *dp; - - if (ino != parent) { - dp = ginode(parent); - dp->di_nlink--; - inodirty(); - } - freeino(ino); -} - -/* - * generate a temporary name for the lost+found directory. - */ -lftempname(bufp, ino) - char *bufp; - ino_t ino; -{ - register ino_t in; - register char *cp; - int namlen; - - cp = bufp + 2; - for (in = maxino; in > 0; in /= 10) - cp++; - *--cp = 0; - namlen = cp - bufp; - in = ino; - while (cp > bufp) { - *--cp = (in % 10) + '0'; - in /= 10; - } - *cp = '#'; - return (namlen); -} - -/* - * Get a directory block. - * Insure that it is held until another is requested. - */ -struct bufarea * -getdirblk(blkno, size) - daddr_t blkno; - long size; -{ - - if (pdirbp != 0) - pdirbp->b_flags &= ~B_INUSE; - pdirbp = getdatablk(blkno, size); - return (pdirbp); -} diff --git a/bsdfsck/fsck.h b/bsdfsck/fsck.h deleted file mode 100644 index 04bb7698..00000000 --- a/bsdfsck/fsck.h +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)fsck.h 8.1 (Berkeley) 6/5/93 - * $Id: fsck.h,v 1.10 1994/10/05 17:09:06 mib Exp $ - */ - -/* Begin GNU Hurd */ - -/* GNU ufs doesn't define struct direct, but fsck needs it. */ -#define direct directory_entry - -/* For GNU Hurd: the ufs DIRSIZ macro is different than the BSD - 4.4 version that fsck expects. So we provide here the BSD version. */ -#undef DIRSIZ -#if (BYTE_ORDER == LITTLE_ENDIAN) -#define DIRSIZ(oldfmt, dp) \ - ((oldfmt) ? \ - ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_type+1 + 3) &~ 3)) : \ - ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))) -#else -#define DIRSIZ(oldfmt, dp) \ - ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) -#endif - -/* GNU ufs has no need of struct dirtemplate; so provide the - BSD version here. */ -/* - * Template for manipulating directories. - * Should use struct direct's, but the name field - * is MAXNAMLEN - 1, and this just won't do. - */ -struct dirtemplate { - u_long dot_ino; - short dot_reclen; - u_char dot_type; - u_char dot_namlen; - char dot_name[4]; /* must be multiple of 4 */ - u_long dotdot_ino; - short dotdot_reclen; - u_char dotdot_type; - u_char dotdot_namlen; - char dotdot_name[4]; /* ditto */ -}; -/* - * This is the old format of directories, sanz type element. - */ -struct odirtemplate { - u_long dot_ino; - short dot_reclen; - u_short dot_namlen; - char dot_name[4]; /* must be multiple of 4 */ - u_long dotdot_ino; - short dotdot_reclen; - u_short dotdot_namlen; - char dotdot_name[4]; /* ditto */ -}; - -/* These shouldn't be used by anyone, but fsck seems to need it */ -#define DEV_BSIZE 512 -#define MAXPATHLEN 1024 - -/* Provide mode from struct dinode * */ -#define DI_MODE(dp) (((dp)->di_modeh << 16) | (dp)->di_model) - -#define NBBY 8 - -#define MAXPHYS (64 * 1024) - -/* The fsck code in setup.c sets the fs_csp table which ufs doesn't want. - So here is the fs_cs macro from ufs for use when that table is real. */ -#undef fs_cs -#define fs_cs(fs, indx) \ - fs_csp[(indx) >> (fs)->fs_csshift][(indx) & ~(fs)->fs_csmask] - -#define dblksize(fs, dip, lbn) \ - (((lbn) >= NDADDR || (dip)->di_size >= ((lbn) + 1) << (fs)->fs_bshift) \ - ? (fs)->fs_bsize \ - : (fragroundup(fs, blkoff(fs, (dip)->di_size)))) - -/* Don't include dirent.h lest we get confused, but we still want this. */ -#define IFTODT(mode) (((mode) & 0170000) >> 12) -#define DT_DIR IFTODT (IFDIR) - -/* missing macros */ - -/* Convert bytes to disk blocks */ -#define btodb(bytes) ((bytes) / DEV_BSIZE) - - - -/* End GNU Hurd additions */ - - -#define MAXDUP 10 /* limit on dup blks (per inode) */ -#define MAXBAD 10 /* limit on bad blks (per inode) */ -#define MAXBUFSPACE 40*1024 /* maximum space to allocate to buffers */ -#define INOBUFSIZE 56*1024 /* size of buffer to read inodes in pass1 */ - -#ifndef BUFSIZ -#define BUFSIZ 1024 -#endif - -#define USTATE 01 /* inode not allocated */ -#define FSTATE 02 /* inode is file */ -#define DSTATE 03 /* inode is directory */ -#define DFOUND 04 /* directory found during descent */ -#define DCLEAR 05 /* directory is to be cleared */ -#define FCLEAR 06 /* file is to be cleared */ - -/* - * buffer cache structure. - */ -struct bufarea { - struct bufarea *b_next; /* free list queue */ - struct bufarea *b_prev; /* free list queue */ - daddr_t b_bno; - int b_size; - int b_errs; - int b_flags; - union { - char *b_buf; /* buffer space */ - daddr_t *b_indir; /* indirect block */ - struct fs *b_fs; /* super block */ - struct cg *b_cg; /* cylinder group */ - struct dinode *b_dinode; /* inode block */ - } b_un; - char b_dirty; -}; - -#define B_INUSE 1 - -#define MINBUFS 5 /* minimum number of buffers required */ -struct bufarea bufhead; /* head of list of other blks in filesys */ -struct bufarea sblk; /* file system superblock */ -struct bufarea cgblk; /* cylinder group blocks */ -struct bufarea *pdirbp; /* current directory contents */ -struct bufarea *pbp; /* current inode block */ -struct bufarea *getdatablk(); - -#define dirty(bp) (bp)->b_dirty = 1 -#define initbarea(bp) \ - (bp)->b_dirty = 0; \ - (bp)->b_bno = (daddr_t)-1; \ - (bp)->b_flags = 0; - -#define sbdirty() sblk.b_dirty = 1 -#define cgdirty() cgblk.b_dirty = 1 -#define sblock (*sblk.b_un.b_fs) -#define cgrp (*cgblk.b_un.b_cg) - -enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE}; - -struct inodesc { - enum fixstate id_fix; /* policy on fixing errors */ - int (*id_func)(); /* function to be applied to blocks of inode */ - ino_t id_number; /* inode number described */ - ino_t id_parent; /* for DATA nodes, their parent */ - daddr_t id_blkno; /* current block number being examined */ - int id_numfrags; /* number of frags contained in block */ - quad_t id_filesize; /* for DATA nodes, the size of the directory */ - int id_loc; /* for DATA nodes, current location in dir */ - int id_entryno; /* for DATA nodes, current entry number */ - struct direct *id_dirp; /* for DATA nodes, ptr to current entry */ - char *id_name; /* for DATA nodes, name to find or enter */ - char id_type; /* type of descriptor, DATA or ADDR */ -}; -/* file types */ -#define DATA 1 -#define ADDR 2 - -/* - * Linked list of duplicate blocks. - * - * The list is composed of two parts. The first part of the - * list (from duplist through the node pointed to by muldup) - * contains a single copy of each duplicate block that has been - * found. The second part of the list (from muldup to the end) - * contains duplicate blocks that have been found more than once. - * To check if a block has been found as a duplicate it is only - * necessary to search from duplist through muldup. To find the - * total number of times that a block has been found as a duplicate - * the entire list must be searched for occurrences of the block - * in question. The following diagram shows a sample list where - * w (found twice), x (found once), y (found three times), and z - * (found once) are duplicate block numbers: - * - * w -> y -> x -> z -> y -> w -> y - * ^ ^ - * | | - * duplist muldup - */ -struct dups { - struct dups *next; - daddr_t dup; -}; -struct dups *duplist; /* head of dup list */ -struct dups *muldup; /* end of unique duplicate dup block numbers */ - -/* - * Linked list of inodes with zero link counts. - */ -struct zlncnt { - struct zlncnt *next; - ino_t zlncnt; -}; -struct zlncnt *zlnhead; /* head of zero link count list */ - -/* - * Inode cache data structures. - */ -struct inoinfo { - struct inoinfo *i_nexthash; /* next entry in hash chain */ - ino_t i_number; /* inode number of this entry */ - ino_t i_parent; /* inode number of parent */ - ino_t i_dotdot; /* inode number of `..' */ - size_t i_isize; /* size of inode */ - u_int i_numblks; /* size of block array in bytes */ - daddr_t i_blks[1]; /* actually longer */ -} **inphead, **inpsort; -long numdirs, listmax, inplast; - -char *cdevname; /* name of device being checked */ -long dev_bsize; /* computed value of DEV_BSIZE */ -long secsize; /* actual disk sector size */ -char nflag; /* assume a no response */ -char yflag; /* assume a yes response */ -int bflag; /* location of alternate super block */ -int debug; /* output debugging info */ -int cvtlevel; /* convert to newer file system format */ -int doinglevel1; /* converting to new cylinder group format */ -int doinglevel2; /* converting to new inode format */ -int newinofmt; /* filesystem has new inode format */ -char preen; /* just fix normal inconsistencies */ -char hotroot; /* checking root device */ -char havesb; /* superblock has been read */ -int fsmodified; /* 1 => write done to file system */ -int fsreadfd; /* file descriptor for reading file system */ -int fswritefd; /* file descriptor for writing file system */ - -daddr_t maxfsblock; /* number of blocks in the file system */ -char *blockmap; /* ptr to primary blk allocation map */ -ino_t maxino; /* number of inodes in file system */ -ino_t lastino; /* last inode in use */ -char *statemap; /* ptr to inode state table */ -char *typemap; /* ptr to inode type table */ -short *lncntp; /* ptr to link count table */ - -ino_t lfdir; /* lost & found directory inode number */ -char *lfname; /* lost & found directory name */ -int lfmode; /* lost & found directory creation mode */ - -daddr_t n_blks; /* number of blocks in use */ -daddr_t n_files; /* number of files in use */ - -#define clearinode(dp) (*(dp) = zino) -struct dinode zino; - -#define setbmap(blkno) setbit(blockmap, blkno) -#define testbmap(blkno) isset(blockmap, blkno) -#define clrbmap(blkno) clrbit(blockmap, blkno) - -#define STOP 0x01 -#define SKIP 0x02 -#define KEEPON 0x04 -#define ALTERED 0x08 -#define FOUND 0x10 - -time_t time(); -struct dinode *ginode(); -struct inoinfo *getinoinfo(); -void getblk(); -ino_t allocino(); -int findino(); diff --git a/bsdfsck/inode.c b/bsdfsck/inode.c deleted file mode 100644 index 7b48aef6..00000000 --- a/bsdfsck/inode.c +++ /dev/null @@ -1,562 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)inode.c 8.4 (Berkeley) 4/18/94";*/ -static char *rcsid = "$Id: inode.c,v 1.6 1994/10/05 17:05:30 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/dir.h" -#include "../ufs/fs.h" -#ifndef SMALL -#include <pwd.h> -#endif -#include <stdlib.h> -#include <string.h> -#include "fsck.h" - -static ino_t startinum; - -ckinode(dp, idesc) - struct dinode *dp; - register struct inodesc *idesc; -{ - register daddr_t *ap; - long ret, n, ndb, offset; - struct dinode dino; - quad_t remsize, sizepb; - mode_t mode; - - if (idesc->id_fix != IGNORE) - idesc->id_fix = DONTKNOW; - idesc->id_entryno = 0; - idesc->id_filesize = dp->di_size; - mode = DI_MODE(dp) & IFMT; - if (mode == IFBLK || mode == IFCHR - || (mode == IFLNK && sblock.fs_maxsymlinklen != -1 && - (dp->di_size < sblock.fs_maxsymlinklen - || (sblock.fs_maxsymlinklen == 0 && dp->di_blocks == 0)))) - return (KEEPON); - dino = *dp; - ndb = howmany(dino.di_size, sblock.fs_bsize); - for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) { - if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0) - idesc->id_numfrags = - numfrags(&sblock, fragroundup(&sblock, offset)); - else - idesc->id_numfrags = sblock.fs_frag; - if (*ap == 0) - continue; - idesc->id_blkno = *ap; - if (idesc->id_type == ADDR) - ret = (*idesc->id_func)(idesc); - else - ret = dirscan(idesc); - if (ret & STOP) - return (ret); - } - idesc->id_numfrags = sblock.fs_frag; - remsize = dino.di_size - sblock.fs_bsize * NDADDR; - sizepb = sblock.fs_bsize; - for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) { - if (*ap) { - idesc->id_blkno = *ap; - ret = iblock(idesc, n, remsize); - if (ret & STOP) - return (ret); - } - sizepb *= NINDIR(&sblock); - remsize -= sizepb; - } - /* GNU Hurd extension. */ - if (dino.di_trans && idesc->id_type == ADDR) - { - idesc->id_blkno = dino.di_trans; - idesc->id_numfrags = sblock.fs_frag; - return (*idesc->id_func)(idesc); - } - return (KEEPON); -} - -iblock(idesc, ilevel, isize) - struct inodesc *idesc; - long ilevel; - quad_t isize; -{ - register daddr_t *ap; - register daddr_t *aplim; - register struct bufarea *bp; - int i, n, (*func)(), nif; - quad_t sizepb; - char buf[BUFSIZ]; - extern int dirscan(), pass1check(); - - if (idesc->id_type == ADDR) { - func = idesc->id_func; - if (((n = (*func)(idesc)) & KEEPON) == 0) - return (n); - } else - func = dirscan; - if (chkrange(idesc->id_blkno, idesc->id_numfrags)) - return (SKIP); - bp = getdatablk(idesc->id_blkno, sblock.fs_bsize); - ilevel--; - for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++) - sizepb *= NINDIR(&sblock); - nif = howmany(isize , sizepb); - if (nif > NINDIR(&sblock)) - nif = NINDIR(&sblock); - if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) { - aplim = &bp->b_un.b_indir[NINDIR(&sblock)]; - for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) { - if (*ap == 0) - continue; - (void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu", - idesc->id_number); - if (dofix(idesc, buf)) { - *ap = 0; - dirty(bp); - } - } - flush(fswritefd, bp); - } - aplim = &bp->b_un.b_indir[nif]; - for (ap = bp->b_un.b_indir; ap < aplim; ap++) { - if (*ap) { - idesc->id_blkno = *ap; - if (ilevel == 0) - n = (*func)(idesc); - else - n = iblock(idesc, ilevel, isize); - if (n & STOP) { - bp->b_flags &= ~B_INUSE; - return (n); - } - } - isize -= sizepb; - } - bp->b_flags &= ~B_INUSE; - return (KEEPON); -} - -/* - * Check that a block in a legal block number. - * Return 0 if in range, 1 if out of range. - */ -chkrange(blk, cnt) - daddr_t blk; - int cnt; -{ - register int c; - - if ((unsigned)(blk + cnt) > maxfsblock) - return (1); - c = dtog(&sblock, blk); - if (blk < cgdmin(&sblock, c)) { - if ((blk + cnt) > cgsblock(&sblock, c)) { - if (debug) { - printf("blk %ld < cgdmin %ld;", - blk, cgdmin(&sblock, c)); - printf(" blk + cnt %ld > cgsbase %ld\n", - blk + cnt, cgsblock(&sblock, c)); - } - return (1); - } - } else { - if ((blk + cnt) > cgbase(&sblock, c+1)) { - if (debug) { - printf("blk %ld >= cgdmin %ld;", - blk, cgdmin(&sblock, c)); - printf(" blk + cnt %ld > sblock.fs_fpg %ld\n", - blk+cnt, sblock.fs_fpg); - } - return (1); - } - } - return (0); -} - -/* - * General purpose interface for reading inodes. - */ -struct dinode * -ginode(inumber) - ino_t inumber; -{ - daddr_t iblk; - - if (inumber < ROOTINO || inumber > maxino) - errexit("bad inode number %d to ginode\n", inumber); - if (startinum == 0 || - inumber < startinum || inumber >= startinum + INOPB(&sblock)) { - iblk = ino_to_fsba(&sblock, inumber); - if (pbp != 0) - pbp->b_flags &= ~B_INUSE; - pbp = getdatablk(iblk, sblock.fs_bsize); - startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock); - } - return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]); -} - -/* - * Special purpose version of ginode used to optimize first pass - * over all the inodes in numerical order. - */ -ino_t nextino, lastinum; -long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; -struct dinode *inodebuf; - -struct dinode * -getnextinode(inumber) - ino_t inumber; -{ - long size; - daddr_t dblk; - static struct dinode *dp; - - if (inumber != nextino++ || inumber > maxino) - errexit("bad inode number %d to nextinode\n", inumber); - if (inumber >= lastinum) { - readcnt++; - dblk = fsbtodb(&sblock, ino_to_fsba(&sblock, lastinum)); - if (readcnt % readpercg == 0) { - size = partialsize; - lastinum += partialcnt; - } else { - size = inobufsize; - lastinum += fullcnt; - } - (void)bread(fsreadfd, (char *)inodebuf, dblk, size); /* ??? */ - dp = inodebuf; - } - return (dp++); -} - -resetinodebuf() -{ - - startinum = 0; - nextino = 0; - lastinum = 0; - readcnt = 0; - inobufsize = blkroundup(&sblock, INOBUFSIZE); - fullcnt = inobufsize / sizeof(struct dinode); - readpercg = sblock.fs_ipg / fullcnt; - partialcnt = sblock.fs_ipg % fullcnt; - partialsize = partialcnt * sizeof(struct dinode); - if (partialcnt != 0) { - readpercg++; - } else { - partialcnt = fullcnt; - partialsize = inobufsize; - } - if (inodebuf == NULL && - (inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL) - errexit("Cannot allocate space for inode buffer\n"); - while (nextino < ROOTINO) - (void)getnextinode(nextino); -} - -freeinodebuf() -{ - - if (inodebuf != NULL) - free((char *)inodebuf); - inodebuf = NULL; -} - -/* - * Routines to maintain information about directory inodes. - * This is built during the first pass and used during the - * second and third passes. - * - * Enter inodes into the cache. - */ -cacheino(dp, inumber) - register struct dinode *dp; - ino_t inumber; -{ - register struct inoinfo *inp; - struct inoinfo **inpp; - unsigned int blks; - - blks = howmany(dp->di_size, sblock.fs_bsize); - if (blks > NDADDR) - blks = NDADDR + NIADDR; - inp = (struct inoinfo *) - malloc(sizeof(*inp) + (blks - 1) * sizeof(daddr_t)); - if (inp == NULL) - return; - inpp = &inphead[inumber % numdirs]; - inp->i_nexthash = *inpp; - *inpp = inp; - inp->i_parent = (ino_t)0; - inp->i_dotdot = (ino_t)0; - inp->i_number = inumber; - inp->i_isize = dp->di_size; - inp->i_numblks = blks * sizeof(daddr_t); - bcopy((char *)&dp->di_db[0], (char *)&inp->i_blks[0], - (size_t)inp->i_numblks); - if (inplast == listmax) { - listmax += 100; - inpsort = (struct inoinfo **)realloc((char *)inpsort, - (unsigned)listmax * sizeof(struct inoinfo *)); - if (inpsort == NULL) - errexit("cannot increase directory list"); - } - inpsort[inplast++] = inp; -} - -/* - * Look up an inode cache structure. - */ -struct inoinfo * -getinoinfo(inumber) - ino_t inumber; -{ - register struct inoinfo *inp; - - for (inp = inphead[inumber % numdirs]; inp; inp = inp->i_nexthash) { - if (inp->i_number != inumber) - continue; - return (inp); - } - errexit("cannot find inode %d\n", inumber); - return ((struct inoinfo *)0); -} - -/* - * Clean up all the inode cache structure. - */ -inocleanup() -{ - register struct inoinfo **inpp; - - if (inphead == NULL) - return; - for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) - free((char *)(*inpp)); - free((char *)inphead); - free((char *)inpsort); - inphead = inpsort = NULL; -} - -inodirty() -{ - - dirty(pbp); -} - -clri(idesc, type, flag) - register struct inodesc *idesc; - char *type; - int flag; -{ - register struct dinode *dp; - - dp = ginode(idesc->id_number); - if (flag == 1) { - pwarn("%s %s", type, - (DI_MODE(dp) & IFMT) == IFDIR ? "DIR" : "FILE"); - pinode(idesc->id_number); - } - if (preen || reply("CLEAR") == 1) { - if (preen) - printf(" (CLEARED)\n"); - n_files--; - (void)ckinode(dp, idesc); - clearinode(dp); - statemap[idesc->id_number] = USTATE; - inodirty(); - } -} - -findname(idesc) - struct inodesc *idesc; -{ - register struct direct *dirp = idesc->id_dirp; - - if (dirp->d_ino != idesc->id_parent) - return (KEEPON); - bcopy(dirp->d_name, idesc->id_name, (size_t)dirp->d_namlen + 1); - return (STOP|FOUND); -} - -findino(idesc) - struct inodesc *idesc; -{ - register struct direct *dirp = idesc->id_dirp; - - if (dirp->d_ino == 0) - return (KEEPON); - if (strcmp(dirp->d_name, idesc->id_name) == 0 && - dirp->d_ino >= ROOTINO && dirp->d_ino <= maxino) { - idesc->id_parent = dirp->d_ino; - return (STOP|FOUND); - } - return (KEEPON); -} - -pinode(ino) - ino_t ino; -{ - register struct dinode *dp; - register char *p; - struct passwd *pw; - char *ctime(); - - printf(" I=%lu ", ino); - if (ino < ROOTINO || ino > maxino) - return; - dp = ginode(ino); - printf(" OWNER="); -#ifndef SMALL - if ((pw = getpwuid((int)dp->di_uid)) != 0) - printf("%s ", pw->pw_name); - else -#endif - printf("%u ", (unsigned)dp->di_uid); - printf("MODE=%o\n", DI_MODE(dp)); - if (preen) - printf("%s: ", cdevname); - printf("SIZE=%qu ", dp->di_size); - p = ctime(&dp->di_mtime.ts_sec); - printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]); -} - -blkerror(ino, type, blk) - ino_t ino; - char *type; - daddr_t blk; -{ - - pfatal("%ld %s I=%lu", blk, type, ino); - printf("\n"); - switch (statemap[ino]) { - - case FSTATE: - statemap[ino] = FCLEAR; - return; - - case DSTATE: - statemap[ino] = DCLEAR; - return; - - case FCLEAR: - case DCLEAR: - return; - - default: - errexit("BAD STATE %d TO BLKERR", statemap[ino]); - /* NOTREACHED */ - } -} - -/* - * allocate an unused inode - */ -ino_t -allocino(request, type) - ino_t request; - int type; -{ - register ino_t ino; - register struct dinode *dp; - - if (request == 0) - request = ROOTINO; - else if (statemap[request] != USTATE) - return (0); - for (ino = request; ino < maxino; ino++) - if (statemap[ino] == USTATE) - break; - if (ino == maxino) - return (0); - switch (type & IFMT) { - case IFDIR: - statemap[ino] = DSTATE; - break; - case IFREG: - case IFLNK: - statemap[ino] = FSTATE; - break; - default: - return (0); - } - dp = ginode(ino); - dp->di_db[0] = allocblk((long)1); - if (dp->di_db[0] == 0) { - statemap[ino] = USTATE; - return (0); - } -#if 0 - dp->di_mode = type; -#else - dp->di_modeh = (type & 0xffff0000) >> 16; - dp->di_model = (type & 0x0000ffff); -#endif - (void)time(&dp->di_atime.ts_sec); - dp->di_mtime = dp->di_ctime = dp->di_atime; - dp->di_size = sblock.fs_fsize; - dp->di_blocks = btodb(sblock.fs_fsize); - n_files++; - inodirty(); - if (newinofmt) - typemap[ino] = IFTODT(type); - return (ino); -} - -/* - * deallocate an inode - */ -freeino(ino) - ino_t ino; -{ - struct inodesc idesc; - extern int pass4check(); - struct dinode *dp; - - bzero((char *)&idesc, sizeof(struct inodesc)); - idesc.id_type = ADDR; - idesc.id_func = pass4check; - idesc.id_number = ino; - dp = ginode(ino); - (void)ckinode(dp, &idesc); - clearinode(dp); - inodirty(); - statemap[ino] = USTATE; - n_files--; -} diff --git a/bsdfsck/main.c b/bsdfsck/main.c deleted file mode 100644 index adf84f74..00000000 --- a/bsdfsck/main.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char copyright[] = -"@(#) Copyright (c) 1980, 1986, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)main.c 8.2 (Berkeley) 1/23/94";*/ -static char *rcsid = "$Id: main.c,v 1.4 1994/08/26 18:06:30 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -/*#include <sys/mount.h> */ -#include "../ufs/dinode.h" -#include "../ufs/fs.h" -/* #include <fstab.h> */ -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <stdio.h> -#include "fsck.h" - -void catch(), catchquit(), voidquit(); -int returntosingle; - -/* GNU Hurd patch */ -#define blockcheck(a) (a) - -main(argc, argv) - int argc; - char *argv[]; -{ - int ch; - int ret, maxrun = 0; - extern int docheck(), checkfilesys(); - extern char *optarg; -/* extern char *blockcheck(); */ - extern int optind; - - sync(); - while ((ch = getopt(argc, argv, "dpnNyYb:c:l:m:")) != EOF) { - switch (ch) { - case 'p': - preen++; - break; - - case 'b': - bflag = argtoi('b', "number", optarg, 10); - printf("Alternate super block location: %d\n", bflag); - break; - - case 'c': - cvtlevel = argtoi('c', "conversion level", optarg, 10); - break; - - case 'd': - debug++; - break; - - case 'l': - maxrun = argtoi('l', "number", optarg, 10); - break; - - case 'm': - lfmode = argtoi('m', "mode", optarg, 8); - if (lfmode &~ 07777) - errexit("bad mode to -m: %o\n", lfmode); - printf("** lost+found creation mode %o\n", lfmode); - break; - - case 'n': - case 'N': - nflag++; - yflag = 0; - break; - - case 'y': - case 'Y': - yflag++; - nflag = 0; - break; - - default: - errexit("%c option?\n", ch); - } - } - argc -= optind; - argv += optind; - if (signal(SIGINT, SIG_IGN) != SIG_IGN) - (void)signal(SIGINT, catch); - if (preen) - (void)signal(SIGQUIT, catchquit); - if (argc) { - while (argc-- > 0) - (void)checkfilesys(blockcheck(*argv++), 0, 0L, 0); - exit(0); - } - fprintf (stderr, "You must explicitly name the filesystem to check\n"); - exit (1); -#if 0 - ret = checkfstab(preen, maxrun, docheck, checkfilesys); - if (returntosingle) - exit(2); - exit(ret); -#endif -} - -argtoi(flag, req, str, base) - int flag; - char *req, *str; - int base; -{ - char *cp; - int ret; - - ret = (int)strtol(str, &cp, base); - if (cp == str || *cp) - errexit("-%c flag requires a %s\n", flag, req); - return (ret); -} - -#if 0 -/* - * Determine whether a filesystem should be checked. - */ -docheck(fsp) - register struct fstab *fsp; -{ - - if (strcmp(fsp->fs_vfstype, "ufs") || - (strcmp(fsp->fs_type, FSTAB_RW) && - strcmp(fsp->fs_type, FSTAB_RO)) || - fsp->fs_passno == 0) - return (0); - return (1); -} -#endif - -/* - * Check the specified filesystem. - */ -/* ARGSUSED */ -checkfilesys(filesys, mntpt, auxdata, child) - char *filesys, *mntpt; - long auxdata; -{ - daddr_t n_ffree, n_bfree; - struct dups *dp; - struct zlncnt *zlnp; - int cylno; - - if (preen && child) - (void)signal(SIGQUIT, voidquit); - cdevname = filesys; - if (debug && preen) - pwarn("starting\n"); - if (setup(filesys) == 0) { - if (preen) - pfatal("CAN'T CHECK FILE SYSTEM."); - return (0); - } - /* - * 1: scan inodes tallying blocks used - */ - if (preen == 0) { - printf("** Last Mounted on %s\n", sblock.fs_fsmnt); -#if 0 - if (hotroot) - printf("** Root file system\n"); -#endif - printf("** Phase 1 - Check Blocks and Sizes\n"); - } - pass1(); - - /* - * 1b: locate first references to duplicates, if any - */ - if (duplist) { - if (preen) - pfatal("INTERNAL ERROR: dups with -p"); - printf("** Phase 1b - Rescan For More DUPS\n"); - pass1b(); - } - - /* - * 2: traverse directories from root to mark all connected directories - */ - if (preen == 0) - printf("** Phase 2 - Check Pathnames\n"); - pass2(); - - /* - * 3: scan inodes looking for disconnected directories - */ - if (preen == 0) - printf("** Phase 3 - Check Connectivity\n"); - pass3(); - - /* - * 4: scan inodes looking for disconnected files; check reference counts - */ - if (preen == 0) - printf("** Phase 4 - Check Reference Counts\n"); - pass4(); - - /* - * 5: check and repair resource counts in cylinder groups - */ - if (preen == 0) - printf("** Phase 5 - Check Cyl groups\n"); - pass5(); - - /* - * print out summary statistics - */ - n_ffree = sblock.fs_cstotal.cs_nffree; - n_bfree = sblock.fs_cstotal.cs_nbfree; - pwarn("%ld files, %ld used, %ld free ", - n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree); - printf("(%ld frags, %ld blocks, %d.%d%% fragmentation)\n", - n_ffree, n_bfree, (n_ffree * 100) / sblock.fs_dsize, - ((n_ffree * 1000 + sblock.fs_dsize / 2) / sblock.fs_dsize) % 10); - if (debug && - (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree)) - printf("%ld files missing\n", n_files); - if (debug) { - n_blks += sblock.fs_ncg * - (cgdmin(&sblock, 0) - cgsblock(&sblock, 0)); - n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0); - n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize); - if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree)) - printf("%ld blocks missing\n", n_blks); - if (duplist != NULL) { - printf("The following duplicate blocks remain:"); - for (dp = duplist; dp; dp = dp->next) - printf(" %ld,", dp->dup); - printf("\n"); - } - if (zlnhead != NULL) { - printf("The following zero link count inodes remain:"); - for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) - printf(" %lu,", zlnp->zlncnt); - printf("\n"); - } - } - zlnhead = (struct zlncnt *)0; - duplist = (struct dups *)0; - muldup = (struct dups *)0; - inocleanup(); - if (fsmodified) { - (void)time(&sblock.fs_time); - sbdirty(); - } - if (cvtlevel && sblk.b_dirty) { - /* - * Write out the duplicate super blocks - */ - for (cylno = 0; cylno < sblock.fs_ncg; cylno++) - bwrite(fswritefd, (char *)&sblock, - fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE); - } - ckfini(); - free(blockmap); - free(statemap); - free((char *)lncntp); - if (!fsmodified) - return (0); - if (!preen) - printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); -#if 0 - if (hotroot) { - struct statfs stfs_buf; - /* - * We modified the root. Do a mount update on - * it, unless it is read-write, so we can continue. - */ - if (statfs("/", &stfs_buf) == 0) { - long flags = stfs_buf.f_flags; - struct ufs_args args; - int ret; - - if (flags & MNT_RDONLY) { - args.fspec = 0; - args.export.ex_flags = 0; - args.export.ex_root = 0; - flags |= MNT_UPDATE | MNT_RELOAD; - ret = mount(MOUNT_UFS, "/", flags, &args); - if (ret == 0) - return(0); - } - } - if (!preen) - printf("\n***** REBOOT NOW *****\n"); - sync(); - return (4); - } -#endif - return (0); -} diff --git a/bsdfsck/pass1.c b/bsdfsck/pass1.c deleted file mode 100644 index 46b0e109..00000000 --- a/bsdfsck/pass1.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)pass1.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: pass1.c,v 1.4 1994/10/05 16:53:12 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/dir.h" -#include "../ufs/fs.h" -#include <stdlib.h> -#include <string.h> -#include "fsck.h" - -static daddr_t badblk; -static daddr_t dupblk; -int pass1check(); -struct dinode *getnextinode(); - -pass1() -{ - ino_t inumber; - int c, i, cgd; - struct inodesc idesc; - - /* - * Set file system reserved blocks in used block map. - */ - for (c = 0; c < sblock.fs_ncg; c++) { - cgd = cgdmin(&sblock, c); - if (c == 0) { - i = cgbase(&sblock, c); - cgd += howmany(sblock.fs_cssize, sblock.fs_fsize); - } else - i = cgsblock(&sblock, c); - for (; i < cgd; i++) - setbmap(i); - } - /* - * Find all allocated blocks. - */ - bzero((char *)&idesc, sizeof(struct inodesc)); - idesc.id_type = ADDR; - idesc.id_func = pass1check; - inumber = 0; - n_files = n_blks = 0; - resetinodebuf(); - for (c = 0; c < sblock.fs_ncg; c++) { - for (i = 0; i < sblock.fs_ipg; i++, inumber++) { - if (inumber < ROOTINO) - continue; - checkinode(inumber, &idesc); - } - } - freeinodebuf(); -} - -checkinode(inumber, idesc) - ino_t inumber; - register struct inodesc *idesc; -{ - register struct dinode *dp; - struct zlncnt *zlnp; - int ndb, j; - mode_t mode; - char *symbuf; - - dp = getnextinode(inumber); - mode = DI_MODE(dp) & IFMT; - if (mode == 0) { - /* Check for DI_TRANS here is a GNU Hurd addition. */ - if (bcmp((char *)dp->di_db, (char *)zino.di_db, - NDADDR * sizeof(daddr_t)) || - bcmp((char *)dp->di_ib, (char *)zino.di_ib, - NIADDR * sizeof(daddr_t)) || - DI_MODE(dp) || dp->di_size || dp->di_trans) { - pfatal("PARTIALLY ALLOCATED INODE I=%lu", inumber); - if (reply("CLEAR") == 1) { - dp = ginode(inumber); - clearinode(dp); - inodirty(); - } - } - statemap[inumber] = USTATE; - return; - } - lastino = inumber; - if (/* dp->di_size < 0 || */ - dp->di_size + sblock.fs_bsize - 1 < dp->di_size) { - if (debug) - printf("bad size %qu:", dp->di_size); - goto unknown; - } - if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) { - dp = ginode(inumber); - dp->di_size = sblock.fs_fsize; -#if 0 - dp->di_mode = IFREG|0600; -#else - dp->di_modeh = 0; - dp->di_model = IFREG|0600; -#endif - inodirty(); - } - ndb = howmany(dp->di_size, sblock.fs_bsize); - if (ndb < 0) { - if (debug) - printf("bad size %qu ndb %d:", - dp->di_size, ndb); - goto unknown; - } - if (mode == IFBLK || mode == IFCHR) - ndb++; - if (mode == IFLNK) { - /* - * Note that the old fastlink format always had di_blocks set - * to 0. Other than that we no longer use the `spare' field - * (which is now the extended uid) for sanity checking, the - * new format is the same as the old. We simply ignore the - * conversion altogether. - mycroft, 19MAY1994 - */ - if (doinglevel2 && - dp->di_size > 0 && dp->di_size < MAXSYMLINKLEN && - dp->di_blocks != 0) { - symbuf = alloca(secsize); - if (bread(fsreadfd, symbuf, - fsbtodb(&sblock, dp->di_db[0]), - (long)secsize) != 0) - errexit("cannot read symlink"); - if (debug) { - symbuf[dp->di_size] = 0; - printf("convert symlink %d(%s) of size %d\n", - inumber, symbuf, (long)dp->di_size); - } - dp = ginode(inumber); - bcopy(symbuf, (caddr_t)dp->di_shortlink, - (long)dp->di_size); - dp->di_blocks = 0; - inodirty(); - } - /* - * Fake ndb value so direct/indirect block checks below - * will detect any garbage after symlink string. - */ - if (sblock.fs_maxsymlinklen != -1 && - (dp->di_size < sblock.fs_maxsymlinklen || - (sblock.fs_maxsymlinklen == 0 && dp->di_blocks == 0))) { - ndb = howmany(dp->di_size, sizeof(daddr_t)); - if (ndb > NDADDR) { - j = ndb - NDADDR; - for (ndb = 1; j > 1; j--) - ndb *= NINDIR(&sblock); - ndb += NDADDR; - } - } - } - for (j = ndb; j < NDADDR; j++) - if (dp->di_db[j] != 0) { - if (debug) - printf("bad direct addr: %ld\n", dp->di_db[j]); - goto unknown; - } - for (j = 0, ndb -= NDADDR; ndb > 0; j++) - ndb /= NINDIR(&sblock); - for (; j < NIADDR; j++) - if (dp->di_ib[j] != 0) { - if (debug) - printf("bad indirect addr: %ld\n", - dp->di_ib[j]); - goto unknown; - } - if (ftypeok(dp) == 0) - goto unknown; - n_files++; - lncntp[inumber] = dp->di_nlink; - if (dp->di_nlink <= 0) { - zlnp = (struct zlncnt *)malloc(sizeof *zlnp); - if (zlnp == NULL) { - pfatal("LINK COUNT TABLE OVERFLOW"); - if (reply("CONTINUE") == 0) - errexit(""); - } else { - zlnp->zlncnt = inumber; - zlnp->next = zlnhead; - zlnhead = zlnp; - } - } - if (mode == IFDIR) { - if (dp->di_size == 0) - statemap[inumber] = DCLEAR; - else - statemap[inumber] = DSTATE; - cacheino(dp, inumber); - } else - statemap[inumber] = FSTATE; - typemap[inumber] = IFTODT(mode); - if (doinglevel2 && - (dp->di_ouid != (u_short)-1 || dp->di_ogid != (u_short)-1)) { - dp = ginode(inumber); - dp->di_uid = dp->di_ouid; - dp->di_ouid = -1; - dp->di_gid = dp->di_ogid; - dp->di_ogid = -1; - inodirty(); - } - badblk = dupblk = 0; - idesc->id_number = inumber; - (void)ckinode(dp, idesc); - idesc->id_entryno *= btodb(sblock.fs_fsize); - if (dp->di_blocks != idesc->id_entryno) { - pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)", - inumber, dp->di_blocks, idesc->id_entryno); - if (preen) - printf(" (CORRECTED)\n"); - else if (reply("CORRECT") == 0) - return; - dp = ginode(inumber); - dp->di_blocks = idesc->id_entryno; - inodirty(); - } - return; -unknown: - pfatal("UNKNOWN FILE TYPE I=%lu", inumber); - statemap[inumber] = FCLEAR; - if (reply("CLEAR") == 1) { - statemap[inumber] = USTATE; - dp = ginode(inumber); - clearinode(dp); - inodirty(); - } -} - -pass1check(idesc) - register struct inodesc *idesc; -{ - int res = KEEPON; - int anyout, nfrags; - daddr_t blkno = idesc->id_blkno; - register struct dups *dlp; - struct dups *new; - - if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) { - blkerror(idesc->id_number, "BAD", blkno); - if (badblk++ >= MAXBAD) { - pwarn("EXCESSIVE BAD BLKS I=%lu", - idesc->id_number); - if (preen) - printf(" (SKIPPING)\n"); - else if (reply("CONTINUE") == 0) - errexit(""); - return (STOP); - } - } - for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { - if (anyout && chkrange(blkno, 1)) { - res = SKIP; - } else if (!testbmap(blkno)) { - n_blks++; - setbmap(blkno); - } else { - blkerror(idesc->id_number, "DUP", blkno); - if (dupblk++ >= MAXDUP) { - pwarn("EXCESSIVE DUP BLKS I=%lu", - idesc->id_number); - if (preen) - printf(" (SKIPPING)\n"); - else if (reply("CONTINUE") == 0) - errexit(""); - return (STOP); - } - new = (struct dups *)malloc(sizeof(struct dups)); - if (new == NULL) { - pfatal("DUP TABLE OVERFLOW."); - if (reply("CONTINUE") == 0) - errexit(""); - return (STOP); - } - new->dup = blkno; - if (muldup == 0) { - duplist = muldup = new; - new->next = 0; - } else { - new->next = muldup->next; - muldup->next = new; - } - for (dlp = duplist; dlp != muldup; dlp = dlp->next) - if (dlp->dup == blkno) - break; - if (dlp == muldup && dlp->dup != blkno) - muldup = new; - } - /* - * count the number of blocks found in id_entryno - */ - idesc->id_entryno++; - } - return (res); -} diff --git a/bsdfsck/pass1b.c b/bsdfsck/pass1b.c deleted file mode 100644 index f5aadc06..00000000 --- a/bsdfsck/pass1b.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)pass1b.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: pass1b.c,v 1.2 1994/08/23 20:01:24 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/fs.h" -#include <string.h> -#include "fsck.h" - -int pass1bcheck(); -static struct dups *duphead; - -pass1b() -{ - register int c, i; - register struct dinode *dp; - struct inodesc idesc; - ino_t inumber; - - bzero((char *)&idesc, sizeof(struct inodesc)); - idesc.id_type = ADDR; - idesc.id_func = pass1bcheck; - duphead = duplist; - inumber = 0; - for (c = 0; c < sblock.fs_ncg; c++) { - for (i = 0; i < sblock.fs_ipg; i++, inumber++) { - if (inumber < ROOTINO) - continue; - dp = ginode(inumber); - if (dp == NULL) - continue; - idesc.id_number = inumber; - if (statemap[inumber] != USTATE && - (ckinode(dp, &idesc) & STOP)) - return; - } - } -} - -pass1bcheck(idesc) - register struct inodesc *idesc; -{ - register struct dups *dlp; - int nfrags, res = KEEPON; - daddr_t blkno = idesc->id_blkno; - - for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { - if (chkrange(blkno, 1)) - res = SKIP; - for (dlp = duphead; dlp; dlp = dlp->next) { - if (dlp->dup == blkno) { - blkerror(idesc->id_number, "DUP", blkno); - dlp->dup = duphead->dup; - duphead->dup = blkno; - duphead = duphead->next; - } - if (dlp == muldup) - break; - } - if (muldup == 0 || duphead == muldup->next) - return (STOP); - } - return (res); -} diff --git a/bsdfsck/pass2.c b/bsdfsck/pass2.c deleted file mode 100644 index 184106c1..00000000 --- a/bsdfsck/pass2.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)pass2.c 8.2 (Berkeley) 2/27/94";*/ -static char *rcsid = "$Id: pass2.c,v 1.3 1994/08/24 15:11:56 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/dir.h" -#include "../ufs/fs.h" -#include <stdlib.h> -#include <string.h> -#include "fsck.h" - -#define MINDIRSIZE (sizeof (struct dirtemplate)) - -int pass2check(), blksort(); - -pass2() -{ - register struct dinode *dp; - register struct inoinfo **inpp, *inp; - struct inoinfo **inpend; - struct inodesc curino; - struct dinode dino; - char pathbuf[MAXPATHLEN + 1]; - - switch (statemap[ROOTINO]) { - - case USTATE: - pfatal("ROOT INODE UNALLOCATED"); - if (reply("ALLOCATE") == 0) - errexit(""); - if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) - errexit("CANNOT ALLOCATE ROOT INODE\n"); - break; - - case DCLEAR: - pfatal("DUPS/BAD IN ROOT INODE"); - if (reply("REALLOCATE")) { - freeino(ROOTINO); - if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) - errexit("CANNOT ALLOCATE ROOT INODE\n"); - break; - } - if (reply("CONTINUE") == 0) - errexit(""); - break; - - case FSTATE: - case FCLEAR: - pfatal("ROOT INODE NOT DIRECTORY"); - if (reply("REALLOCATE")) { - freeino(ROOTINO); - if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) - errexit("CANNOT ALLOCATE ROOT INODE\n"); - break; - } - if (reply("FIX") == 0) - errexit(""); - dp = ginode(ROOTINO); -#if 0 - dp->di_mode &= ~IFMT; - dp->di_mode |= IFDIR; -#else - dp->di_model &= ~IFMT; - dp->di_model |= IFDIR; -#endif - inodirty(); - break; - - case DSTATE: - break; - - default: - errexit("BAD STATE %d FOR ROOT INODE", statemap[ROOTINO]); - } - statemap[ROOTINO] = DFOUND; - /* - * Sort the directory list into disk block order. - */ - qsort((char *)inpsort, (size_t)inplast, sizeof *inpsort, blksort); - /* - * Check the integrity of each directory. - */ - bzero((char *)&curino, sizeof(struct inodesc)); - curino.id_type = DATA; - curino.id_func = pass2check; - dp = &dino; - inpend = &inpsort[inplast]; - for (inpp = inpsort; inpp < inpend; inpp++) { - inp = *inpp; - if (inp->i_isize == 0) - continue; - if (inp->i_isize < MINDIRSIZE) { - direrror(inp->i_number, "DIRECTORY TOO SHORT"); - inp->i_isize = roundup(MINDIRSIZE, DIRBLKSIZ); - if (reply("FIX") == 1) { - dp = ginode(inp->i_number); - dp->di_size = inp->i_isize; - inodirty(); - dp = &dino; - } - } else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) { - getpathname(pathbuf, inp->i_number, inp->i_number); - pwarn("DIRECTORY %s: LENGTH %d NOT MULTIPLE OF %d", - pathbuf, inp->i_isize, DIRBLKSIZ); - if (preen) - printf(" (ADJUSTED)\n"); - inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ); - if (preen || reply("ADJUST") == 1) { - dp = ginode(inp->i_number); - dp->di_size = roundup(inp->i_isize, DIRBLKSIZ); - inodirty(); - dp = &dino; - } - } - bzero((char *)&dino, sizeof(struct dinode)); -#if 0 - dino.di_mode = IFDIR; -#else - dino.di_modeh = 0; - dino.di_model = IFDIR; -#endif - dp->di_size = inp->i_isize; - bcopy((char *)&inp->i_blks[0], (char *)&dp->di_db[0], - (size_t)inp->i_numblks); - curino.id_number = inp->i_number; - curino.id_parent = inp->i_parent; - (void)ckinode(dp, &curino); - } - /* - * Now that the parents of all directories have been found, - * make another pass to verify the value of `..' - */ - for (inpp = inpsort; inpp < inpend; inpp++) { - inp = *inpp; - if (inp->i_parent == 0 || inp->i_isize == 0) - continue; - if (statemap[inp->i_parent] == DFOUND && - statemap[inp->i_number] == DSTATE) - statemap[inp->i_number] = DFOUND; - if (inp->i_dotdot == inp->i_parent || - inp->i_dotdot == (ino_t)-1) - continue; - if (inp->i_dotdot == 0) { - inp->i_dotdot = inp->i_parent; - fileerror(inp->i_parent, inp->i_number, "MISSING '..'"); - if (reply("FIX") == 0) - continue; - (void)makeentry(inp->i_number, inp->i_parent, ".."); - lncntp[inp->i_parent]--; - continue; - } - fileerror(inp->i_parent, inp->i_number, - "BAD INODE NUMBER FOR '..'"); - if (reply("FIX") == 0) - continue; - lncntp[inp->i_dotdot]++; - lncntp[inp->i_parent]--; - inp->i_dotdot = inp->i_parent; - (void)changeino(inp->i_number, "..", inp->i_parent); - } - /* - * Mark all the directories that can be found from the root. - */ - propagate(); -} - -pass2check(idesc) - struct inodesc *idesc; -{ - register struct direct *dirp = idesc->id_dirp; - register struct inoinfo *inp; - int n, entrysize, ret = 0; - struct dinode *dp; - char *errmsg; - struct direct proto; - char namebuf[MAXPATHLEN + 1]; - char pathbuf[MAXPATHLEN + 1]; - - /* - * If converting, set directory entry type. - */ - if (doinglevel2 && dirp->d_ino > 0 && dirp->d_ino < maxino) { - dirp->d_type = typemap[dirp->d_ino]; - ret |= ALTERED; - } - /* - * check for "." - */ - if (idesc->id_entryno != 0) - goto chk1; - if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) { - if (dirp->d_ino != idesc->id_number) { - direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'"); - dirp->d_ino = idesc->id_number; - if (reply("FIX") == 1) - ret |= ALTERED; - } - if (newinofmt && dirp->d_type != DT_DIR) { - direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'"); - dirp->d_type = DT_DIR; - if (reply("FIX") == 1) - ret |= ALTERED; - } - goto chk1; - } - direrror(idesc->id_number, "MISSING '.'"); - proto.d_ino = idesc->id_number; - if (newinofmt) - proto.d_type = DT_DIR; - else - proto.d_type = 0; - proto.d_namlen = 1; - (void)strcpy(proto.d_name, "."); - entrysize = DIRSIZ(0, &proto); - if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) { - pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n", - dirp->d_name); - } else if (dirp->d_reclen < entrysize) { - pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n"); - } else if (dirp->d_reclen < 2 * entrysize) { - proto.d_reclen = dirp->d_reclen; - bcopy((char *)&proto, (char *)dirp, (size_t)entrysize); - if (reply("FIX") == 1) - ret |= ALTERED; - } else { - n = dirp->d_reclen - entrysize; - proto.d_reclen = entrysize; - bcopy((char *)&proto, (char *)dirp, (size_t)entrysize); - idesc->id_entryno++; - lncntp[dirp->d_ino]--; - dirp = (struct direct *)((char *)(dirp) + entrysize); - bzero((char *)dirp, (size_t)n); - dirp->d_reclen = n; - if (reply("FIX") == 1) - ret |= ALTERED; - } -chk1: - if (idesc->id_entryno > 1) - goto chk2; - inp = getinoinfo(idesc->id_number); - proto.d_ino = inp->i_parent; - if (newinofmt) - proto.d_type = DT_DIR; - else - proto.d_type = 0; - proto.d_namlen = 2; - (void)strcpy(proto.d_name, ".."); - entrysize = DIRSIZ(0, &proto); - if (idesc->id_entryno == 0) { - n = DIRSIZ(0, dirp); - if (dirp->d_reclen < n + entrysize) - goto chk2; - proto.d_reclen = dirp->d_reclen - n; - dirp->d_reclen = n; - idesc->id_entryno++; - lncntp[dirp->d_ino]--; - dirp = (struct direct *)((char *)(dirp) + n); - bzero((char *)dirp, (size_t)proto.d_reclen); - dirp->d_reclen = proto.d_reclen; - } - if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) { - inp->i_dotdot = dirp->d_ino; - if (newinofmt && dirp->d_type != DT_DIR) { - direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'"); - dirp->d_type = DT_DIR; - if (reply("FIX") == 1) - ret |= ALTERED; - } - goto chk2; - } - if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) { - fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); - pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n", - dirp->d_name); - inp->i_dotdot = (ino_t)-1; - } else if (dirp->d_reclen < entrysize) { - fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); - pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n"); - inp->i_dotdot = (ino_t)-1; - } else if (inp->i_parent != 0) { - /* - * We know the parent, so fix now. - */ - inp->i_dotdot = inp->i_parent; - fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); - proto.d_reclen = dirp->d_reclen; - bcopy((char *)&proto, (char *)dirp, (size_t)entrysize); - if (reply("FIX") == 1) - ret |= ALTERED; - } - idesc->id_entryno++; - if (dirp->d_ino != 0) - lncntp[dirp->d_ino]--; - return (ret|KEEPON); -chk2: - if (dirp->d_ino == 0) - return (ret|KEEPON); - if (dirp->d_namlen <= 2 && - dirp->d_name[0] == '.' && - idesc->id_entryno >= 2) { - if (dirp->d_namlen == 1) { - direrror(idesc->id_number, "EXTRA '.' ENTRY"); - dirp->d_ino = 0; - if (reply("FIX") == 1) - ret |= ALTERED; - return (KEEPON | ret); - } - if (dirp->d_name[1] == '.') { - direrror(idesc->id_number, "EXTRA '..' ENTRY"); - dirp->d_ino = 0; - if (reply("FIX") == 1) - ret |= ALTERED; - return (KEEPON | ret); - } - } - idesc->id_entryno++; - n = 0; - if (dirp->d_ino > maxino) { - fileerror(idesc->id_number, dirp->d_ino, "I OUT OF RANGE"); - n = reply("REMOVE"); - } else { -again: - switch (statemap[dirp->d_ino]) { - case USTATE: - if (idesc->id_entryno <= 2) - break; - fileerror(idesc->id_number, dirp->d_ino, "UNALLOCATED"); - n = reply("REMOVE"); - break; - - case DCLEAR: - case FCLEAR: - if (idesc->id_entryno <= 2) - break; - if (statemap[dirp->d_ino] == FCLEAR) - errmsg = "DUP/BAD"; - else if (!preen) - errmsg = "ZERO LENGTH DIRECTORY"; - else { - n = 1; - break; - } - fileerror(idesc->id_number, dirp->d_ino, errmsg); - if ((n = reply("REMOVE")) == 1) - break; - dp = ginode(dirp->d_ino); - statemap[dirp->d_ino] = - (DI_MODE(dp) & IFMT) == IFDIR ? DSTATE : FSTATE; - lncntp[dirp->d_ino] = dp->di_nlink; - goto again; - - case DSTATE: - if (statemap[idesc->id_number] == DFOUND) - statemap[dirp->d_ino] = DFOUND; - /* fall through */ - - case DFOUND: - inp = getinoinfo(dirp->d_ino); - if (inp->i_parent != 0 && idesc->id_entryno > 2) { - getpathname(pathbuf, idesc->id_number, - idesc->id_number); - getpathname(namebuf, dirp->d_ino, dirp->d_ino); - pwarn("%s %s %s\n", pathbuf, - "IS AN EXTRANEOUS HARD LINK TO DIRECTORY", - namebuf); - if (preen) - printf(" (IGNORED)\n"); - else if ((n = reply("REMOVE")) == 1) - break; - } - if (idesc->id_entryno > 2) - inp->i_parent = idesc->id_number; - /* fall through */ - - case FSTATE: - if (newinofmt && dirp->d_type != typemap[dirp->d_ino]) { - fileerror(idesc->id_number, dirp->d_ino, - "BAD TYPE VALUE"); - dirp->d_type = typemap[dirp->d_ino]; - if (reply("FIX") == 1) - ret |= ALTERED; - } - lncntp[dirp->d_ino]--; - break; - - default: - errexit("BAD STATE %d FOR INODE I=%d", - statemap[dirp->d_ino], dirp->d_ino); - } - } - if (n == 0) - return (ret|KEEPON); - dirp->d_ino = 0; - return (ret|KEEPON|ALTERED); -} - -/* - * Routine to sort disk blocks. - */ -blksort(inpp1, inpp2) - struct inoinfo **inpp1, **inpp2; -{ - - return ((*inpp1)->i_blks[0] - (*inpp2)->i_blks[0]); -} diff --git a/bsdfsck/pass3.c b/bsdfsck/pass3.c deleted file mode 100644 index 78fb6a96..00000000 --- a/bsdfsck/pass3.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)pass3.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: pass3.c,v 1.2 1994/08/23 20:02:13 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/fs.h" -#include "fsck.h" - -pass3() -{ - register struct inoinfo **inpp, *inp; - ino_t orphan; - int loopcnt; - - for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) { - inp = *inpp; - if (inp->i_number == ROOTINO || - !(inp->i_parent == 0 || statemap[inp->i_number] == DSTATE)) - continue; - if (statemap[inp->i_number] == DCLEAR) - continue; - for (loopcnt = 0; ; loopcnt++) { - orphan = inp->i_number; - if (inp->i_parent == 0 || - statemap[inp->i_parent] != DSTATE || - loopcnt > numdirs) - break; - inp = getinoinfo(inp->i_parent); - } - (void)linkup(orphan, inp->i_dotdot); - inp->i_parent = inp->i_dotdot = lfdir; - lncntp[lfdir]--; - statemap[orphan] = DFOUND; - propagate(); - } -} diff --git a/bsdfsck/pass4.c b/bsdfsck/pass4.c deleted file mode 100644 index 449c96ab..00000000 --- a/bsdfsck/pass4.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)pass4.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: pass4.c,v 1.2 1994/08/23 20:02:28 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/fs.h" -#include <stdlib.h> -#include <string.h> -#include "fsck.h" - -int pass4check(); - -pass4() -{ - register ino_t inumber; - register struct zlncnt *zlnp; - struct dinode *dp; - struct inodesc idesc; - int n; - - bzero((char *)&idesc, sizeof(struct inodesc)); - idesc.id_type = ADDR; - idesc.id_func = pass4check; - for (inumber = ROOTINO; inumber <= lastino; inumber++) { - idesc.id_number = inumber; - switch (statemap[inumber]) { - - case FSTATE: - case DFOUND: - n = lncntp[inumber]; - if (n) - adjust(&idesc, (short)n); - else { - for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) - if (zlnp->zlncnt == inumber) { - zlnp->zlncnt = zlnhead->zlncnt; - zlnp = zlnhead; - zlnhead = zlnhead->next; - free((char *)zlnp); - clri(&idesc, "UNREF", 1); - break; - } - } - break; - - case DSTATE: - clri(&idesc, "UNREF", 1); - break; - - case DCLEAR: - dp = ginode(inumber); - if (dp->di_size == 0) { - clri(&idesc, "ZERO LENGTH", 1); - break; - } - /* fall through */ - case FCLEAR: - clri(&idesc, "BAD/DUP", 1); - break; - - case USTATE: - break; - - default: - errexit("BAD STATE %d FOR INODE I=%d", - statemap[inumber], inumber); - } - } -} - -pass4check(idesc) - register struct inodesc *idesc; -{ - register struct dups *dlp; - int nfrags, res = KEEPON; - daddr_t blkno = idesc->id_blkno; - - for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { - if (chkrange(blkno, 1)) { - res = SKIP; - } else if (testbmap(blkno)) { - for (dlp = duplist; dlp; dlp = dlp->next) { - if (dlp->dup != blkno) - continue; - dlp->dup = duplist->dup; - dlp = duplist; - duplist = duplist->next; - free((char *)dlp); - break; - } - if (dlp == 0) { - clrbmap(blkno); - n_blks--; - } - } - } - return (res); -} diff --git a/bsdfsck/pass5.c b/bsdfsck/pass5.c deleted file mode 100644 index 11877f9d..00000000 --- a/bsdfsck/pass5.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)pass5.c 8.2 (Berkeley) 2/2/94";*/ -static char *rcsid = "$Id: pass5.c,v 1.3 1994/08/26 18:03:07 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/fs.h" -#include <string.h> -#include "fsck.h" - -/* From ../ufs/subr.c: */ - -/* - * Update the frsum fields to reflect addition or deletion - * of some frags. - */ -void -ffs_fragacct(fs, fragmap, fraglist, cnt) - struct fs *fs; - int fragmap; - long fraglist[]; - int cnt; -{ - int inblk; - register int field, subfield; - register int siz, pos; - - inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; - fragmap <<= 1; - for (siz = 1; siz < fs->fs_frag; siz++) { - if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) - continue; - field = around[siz]; - subfield = inside[siz]; - for (pos = siz; pos <= fs->fs_frag; pos++) { - if ((fragmap & field) == subfield) { - fraglist[siz] += cnt; - pos += siz; - field <<= siz; - subfield <<= siz; - } - field <<= 1; - subfield <<= 1; - } - } -} - - -pass5() -{ - int c, blk, frags, basesize, sumsize, mapsize, savednrpos; - register struct fs *fs = &sblock; - register struct cg *cg = &cgrp; - daddr_t dbase, dmax; - register daddr_t d; - register long i, j; - struct csum *cs; - struct csum cstotal; - struct inodesc idesc[3]; - char buf[MAXBSIZE]; - register struct cg *newcg = (struct cg *)buf; - struct ocg *ocg = (struct ocg *)buf; - - bzero((char *)newcg, (size_t)fs->fs_cgsize); - newcg->cg_niblk = fs->fs_ipg; - if (cvtlevel > 3) { - if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) { - if (preen) - pwarn("DELETING CLUSTERING MAPS\n"); - if (preen || reply("DELETE CLUSTERING MAPS")) { - fs->fs_contigsumsize = 0; - doinglevel1 = 1; - sbdirty(); - } - } - if (fs->fs_maxcontig > 1) { - char *doit = 0; - - if (fs->fs_contigsumsize < 1) { - doit = "CREAT"; - } else if (fs->fs_contigsumsize < fs->fs_maxcontig && - fs->fs_contigsumsize < FS_MAXCONTIG) { - doit = "EXPAND"; - } - if (doit) { - i = fs->fs_contigsumsize; - fs->fs_contigsumsize = - MIN(fs->fs_maxcontig, FS_MAXCONTIG); - if (CGSIZE(fs) > fs->fs_bsize) { - pwarn("CANNOT %s CLUSTER MAPS\n", doit); - fs->fs_contigsumsize = i; - } else if (preen || - reply("CREATE CLUSTER MAPS")) { - if (preen) - pwarn("%sING CLUSTER MAPS\n", - doit); - fs->fs_cgsize = - fragroundup(fs, CGSIZE(fs)); - doinglevel1 = 1; - sbdirty(); - } - } - } - } - switch ((int)fs->fs_postblformat) { - - case FS_42POSTBLFMT: - basesize = (char *)(&ocg->cg_btot[0]) - (char *)(&ocg->cg_link); - sumsize = &ocg->cg_iused[0] - (char *)(&ocg->cg_btot[0]); - mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] - - (u_char *)&ocg->cg_iused[0]; - ocg->cg_magic = CG_MAGIC; - savednrpos = fs->fs_nrpos; - fs->fs_nrpos = 8; - break; - - case FS_DYNAMICPOSTBLFMT: - newcg->cg_btotoff = - &newcg->cg_space[0] - (u_char *)(&newcg->cg_link); - newcg->cg_boff = - newcg->cg_btotoff + fs->fs_cpg * sizeof(long); - newcg->cg_iusedoff = newcg->cg_boff + - fs->fs_cpg * fs->fs_nrpos * sizeof(short); - newcg->cg_freeoff = - newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY); - if (fs->fs_contigsumsize <= 0) { - newcg->cg_nextfreeoff = newcg->cg_freeoff + - howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY); - } else { - newcg->cg_clustersumoff = newcg->cg_freeoff + - howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY) - - sizeof(long); - newcg->cg_clustersumoff = - roundup(newcg->cg_clustersumoff, sizeof(long)); - newcg->cg_clusteroff = newcg->cg_clustersumoff + - (fs->fs_contigsumsize + 1) * sizeof(long); - newcg->cg_nextfreeoff = newcg->cg_clusteroff + - howmany(fs->fs_cpg * fs->fs_spc / NSPB(fs), NBBY); - } - newcg->cg_magic = CG_MAGIC; - basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_link); - sumsize = newcg->cg_iusedoff - newcg->cg_btotoff; - mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff; - break; - - default: - errexit("UNKNOWN ROTATIONAL TABLE FORMAT %d\n", - fs->fs_postblformat); - } - bzero((char *)&idesc[0], sizeof idesc); - for (i = 0; i < 3; i++) { - idesc[i].id_type = ADDR; - if (doinglevel2) - idesc[i].id_fix = FIX; - } - bzero((char *)&cstotal, sizeof(struct csum)); - j = blknum(fs, fs->fs_size + fs->fs_frag - 1); - for (i = fs->fs_size; i < j; i++) - setbmap(i); - for (c = 0; c < fs->fs_ncg; c++) { - getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize); - if (!cg_chkmagic(cg)) - pfatal("CG %d: BAD MAGIC NUMBER\n", c); - dbase = cgbase(fs, c); - dmax = dbase + fs->fs_fpg; - if (dmax > fs->fs_size) - dmax = fs->fs_size; - newcg->cg_time = cg->cg_time; - newcg->cg_cgx = c; - if (c == fs->fs_ncg - 1) - newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg; - else - newcg->cg_ncyl = fs->fs_cpg; - newcg->cg_ndblk = dmax - dbase; - if (fs->fs_contigsumsize > 0) - newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag; - newcg->cg_cs.cs_ndir = 0; - newcg->cg_cs.cs_nffree = 0; - newcg->cg_cs.cs_nbfree = 0; - newcg->cg_cs.cs_nifree = fs->fs_ipg; - if (cg->cg_rotor < newcg->cg_ndblk) - newcg->cg_rotor = cg->cg_rotor; - else - newcg->cg_rotor = 0; - if (cg->cg_frotor < newcg->cg_ndblk) - newcg->cg_frotor = cg->cg_frotor; - else - newcg->cg_frotor = 0; - if (cg->cg_irotor < newcg->cg_niblk) - newcg->cg_irotor = cg->cg_irotor; - else - newcg->cg_irotor = 0; - bzero((char *)&newcg->cg_frsum[0], sizeof newcg->cg_frsum); - bzero((char *)&cg_blktot(newcg)[0], - (size_t)(sumsize + mapsize)); - if (fs->fs_postblformat == FS_42POSTBLFMT) - ocg->cg_magic = CG_MAGIC; - j = fs->fs_ipg * c; - for (i = 0; i < fs->fs_ipg; j++, i++) { - switch (statemap[j]) { - - case USTATE: - break; - - case DSTATE: - case DCLEAR: - case DFOUND: - newcg->cg_cs.cs_ndir++; - /* fall through */ - - case FSTATE: - case FCLEAR: - newcg->cg_cs.cs_nifree--; - setbit(cg_inosused(newcg), i); - break; - - default: - if (j < ROOTINO) - break; - errexit("BAD STATE %d FOR INODE I=%d", - statemap[j], j); - } - } - if (c == 0) - for (i = 0; i < ROOTINO; i++) { - setbit(cg_inosused(newcg), i); - newcg->cg_cs.cs_nifree--; - } - for (i = 0, d = dbase; - d < dmax; - d += fs->fs_frag, i += fs->fs_frag) { - frags = 0; - for (j = 0; j < fs->fs_frag; j++) { - if (testbmap(d + j)) - continue; - setbit(cg_blksfree(newcg), i + j); - frags++; - } - if (frags == fs->fs_frag) { - newcg->cg_cs.cs_nbfree++; - j = cbtocylno(fs, i); - cg_blktot(newcg)[j]++; - cg_blks(fs, newcg, j)[cbtorpos(fs, i)]++; - if (fs->fs_contigsumsize > 0) - setbit(cg_clustersfree(newcg), - i / fs->fs_frag); - } else if (frags > 0) { - newcg->cg_cs.cs_nffree += frags; - blk = blkmap(fs, cg_blksfree(newcg), i); - ffs_fragacct(fs, blk, newcg->cg_frsum, 1); - } - } - if (fs->fs_contigsumsize > 0) { - long *sump = cg_clustersum(newcg); - u_char *mapp = cg_clustersfree(newcg); - int map = *mapp++; - int bit = 1; - int run = 0; - - for (i = 0; i < newcg->cg_nclusterblks; i++) { - if ((map & bit) != 0) { - run++; - } else if (run != 0) { - if (run > fs->fs_contigsumsize) - run = fs->fs_contigsumsize; - sump[run]++; - run = 0; - } - if ((i & (NBBY - 1)) != (NBBY - 1)) { - bit <<= 1; - } else { - map = *mapp++; - bit = 1; - } - } - if (run != 0) { - if (run > fs->fs_contigsumsize) - run = fs->fs_contigsumsize; - sump[run]++; - } - } - cstotal.cs_nffree += newcg->cg_cs.cs_nffree; - cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree; - cstotal.cs_nifree += newcg->cg_cs.cs_nifree; - cstotal.cs_ndir += newcg->cg_cs.cs_ndir; - cs = &fs->fs_cs(fs, c); - if (bcmp((char *)&newcg->cg_cs, (char *)cs, sizeof *cs) != 0 && - dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) { - bcopy((char *)&newcg->cg_cs, (char *)cs, sizeof *cs); - sbdirty(); - } - if (doinglevel1) { - bcopy((char *)newcg, (char *)cg, (size_t)fs->fs_cgsize); - cgdirty(); - continue; - } - if (bcmp(cg_inosused(newcg), - cg_inosused(cg), mapsize) != 0 && - dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) { - bcopy(cg_inosused(newcg), cg_inosused(cg), - (size_t)mapsize); - cgdirty(); - } - if ((bcmp((char *)newcg, (char *)cg, basesize) != 0 || - bcmp((char *)&cg_blktot(newcg)[0], - (char *)&cg_blktot(cg)[0], sumsize) != 0) && - dofix(&idesc[2], "SUMMARY INFORMATION BAD")) { - bcopy((char *)newcg, (char *)cg, (size_t)basesize); - bcopy((char *)&cg_blktot(newcg)[0], - (char *)&cg_blktot(cg)[0], (size_t)sumsize); - cgdirty(); - } - } - if (fs->fs_postblformat == FS_42POSTBLFMT) - fs->fs_nrpos = savednrpos; - if (bcmp((char *)&cstotal, (char *)&fs->fs_cstotal, sizeof *cs) != 0 - && dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) { - bcopy((char *)&cstotal, (char *)&fs->fs_cstotal, sizeof *cs); - fs->fs_ronly = 0; - fs->fs_fmod = 0; - sbdirty(); - } -} diff --git a/bsdfsck/preen.c b/bsdfsck/preen.c deleted file mode 100644 index 5650f900..00000000 --- a/bsdfsck/preen.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)preen.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: preen.c,v 1.1 1994/08/23 19:29:25 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <fstab.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> - -char *rawname(), *unrawname(), *blockcheck(); - -struct part { - struct part *next; /* forward link of partitions on disk */ - char *name; /* device name */ - char *fsname; /* mounted filesystem name */ - long auxdata; /* auxiliary data for application */ -} *badlist, **badnext = &badlist; - -struct disk { - char *name; /* disk base name */ - struct disk *next; /* forward link for list of disks */ - struct part *part; /* head of list of partitions on disk */ - int pid; /* If != 0, pid of proc working on */ -} *disks; - -int nrun, ndisks; -char hotroot; - -checkfstab(preen, maxrun, docheck, chkit) - int preen, maxrun; - int (*docheck)(), (*chkit)(); -{ - register struct fstab *fsp; - register struct disk *dk, *nextdisk; - register struct part *pt; - int ret, pid, retcode, passno, sumstatus, status; - long auxdata; - char *name; - - sumstatus = 0; - for (passno = 1; passno <= 2; passno++) { - if (setfsent() == 0) { - fprintf(stderr, "Can't open checklist file: %s\n", - _PATH_FSTAB); - return (8); - } - while ((fsp = getfsent()) != 0) { - if ((auxdata = (*docheck)(fsp)) == 0) - continue; - if (preen == 0 || passno == 1 && fsp->fs_passno == 1) { - if (name = blockcheck(fsp->fs_spec)) { - if (sumstatus = (*chkit)(name, - fsp->fs_file, auxdata, 0)) - return (sumstatus); - } else if (preen) - return (8); - } else if (passno == 2 && fsp->fs_passno > 1) { - if ((name = blockcheck(fsp->fs_spec)) == NULL) { - fprintf(stderr, "BAD DISK NAME %s\n", - fsp->fs_spec); - sumstatus |= 8; - continue; - } - addpart(name, fsp->fs_file, auxdata); - } - } - if (preen == 0) - return (0); - } - if (preen) { - if (maxrun == 0) - maxrun = ndisks; - if (maxrun > ndisks) - maxrun = ndisks; - nextdisk = disks; - for (passno = 0; passno < maxrun; ++passno) { - while (ret = startdisk(nextdisk, chkit) && nrun > 0) - sleep(10); - if (ret) - return (ret); - nextdisk = nextdisk->next; - } - while ((pid = wait(&status)) != -1) { - for (dk = disks; dk; dk = dk->next) - if (dk->pid == pid) - break; - if (dk == 0) { - printf("Unknown pid %d\n", pid); - continue; - } - if (WIFEXITED(status)) - retcode = WEXITSTATUS(status); - else - retcode = 0; - if (WIFSIGNALED(status)) { - printf("%s (%s): EXITED WITH SIGNAL %d\n", - dk->part->name, dk->part->fsname, - WTERMSIG(status)); - retcode = 8; - } - if (retcode != 0) { - sumstatus |= retcode; - *badnext = dk->part; - badnext = &dk->part->next; - dk->part = dk->part->next; - *badnext = NULL; - } else - dk->part = dk->part->next; - dk->pid = 0; - nrun--; - if (dk->part == NULL) - ndisks--; - - if (nextdisk == NULL) { - if (dk->part) { - while (ret = startdisk(dk, chkit) && - nrun > 0) - sleep(10); - if (ret) - return (ret); - } - } else if (nrun < maxrun && nrun < ndisks) { - for ( ;; ) { - if ((nextdisk = nextdisk->next) == NULL) - nextdisk = disks; - if (nextdisk->part != NULL && - nextdisk->pid == 0) - break; - } - while (ret = startdisk(nextdisk, chkit) && - nrun > 0) - sleep(10); - if (ret) - return (ret); - } - } - } - if (sumstatus) { - if (badlist == 0) - return (sumstatus); - fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", - badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:"); - for (pt = badlist; pt; pt = pt->next) - fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname, - pt->next ? ", " : "\n"); - return (sumstatus); - } - (void)endfsent(); - return (0); -} - -struct disk * -finddisk(name) - char *name; -{ - register struct disk *dk, **dkp; - register char *p; - size_t len; - - for (p = name + strlen(name) - 1; p >= name; --p) - if (isdigit(*p)) { - len = p - name + 1; - break; - } - if (p < name) - len = strlen(name); - - for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) { - if (strncmp(dk->name, name, len) == 0 && - dk->name[len] == 0) - return (dk); - } - if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) { - fprintf(stderr, "out of memory"); - exit (8); - } - dk = *dkp; - if ((dk->name = malloc(len + 1)) == NULL) { - fprintf(stderr, "out of memory"); - exit (8); - } - (void)strncpy(dk->name, name, len); - dk->name[len] = '\0'; - dk->part = NULL; - dk->next = NULL; - dk->pid = 0; - ndisks++; - return (dk); -} - -addpart(name, fsname, auxdata) - char *name, *fsname; - long auxdata; -{ - struct disk *dk = finddisk(name); - register struct part *pt, **ppt = &dk->part; - - for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next) - if (strcmp(pt->name, name) == 0) { - printf("%s in fstab more than once!\n", name); - return; - } - if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) { - fprintf(stderr, "out of memory"); - exit (8); - } - pt = *ppt; - if ((pt->name = malloc(strlen(name) + 1)) == NULL) { - fprintf(stderr, "out of memory"); - exit (8); - } - (void)strcpy(pt->name, name); - if ((pt->fsname = malloc(strlen(fsname) + 1)) == NULL) { - fprintf(stderr, "out of memory"); - exit (8); - } - (void)strcpy(pt->fsname, fsname); - pt->next = NULL; - pt->auxdata = auxdata; -} - -startdisk(dk, checkit) - register struct disk *dk; - int (*checkit)(); -{ - register struct part *pt = dk->part; - - dk->pid = fork(); - if (dk->pid < 0) { - perror("fork"); - return (8); - } - if (dk->pid == 0) - exit((*checkit)(pt->name, pt->fsname, pt->auxdata, 1)); - nrun++; - return (0); -} - -char * -blockcheck(name) - char *name; -{ - struct stat stslash, stblock, stchar; - char *raw; - int retried = 0; - - hotroot = 0; - if (stat("/", &stslash) < 0) { - perror("/"); - printf("Can't stat root\n"); - return (0); - } -retry: - if (stat(name, &stblock) < 0) { - perror(name); - printf("Can't stat %s\n", name); - return (0); - } - if ((stblock.st_mode & S_IFMT) == S_IFBLK) { - if (stslash.st_dev == stblock.st_rdev) - hotroot++; - raw = rawname(name); - if (stat(raw, &stchar) < 0) { - perror(raw); - printf("Can't stat %s\n", raw); - return (name); - } - if ((stchar.st_mode & S_IFMT) == S_IFCHR) { - return (raw); - } else { - printf("%s is not a character device\n", raw); - return (name); - } - } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) { - name = unrawname(name); - retried++; - goto retry; - } - printf("Can't make sense out of name %s\n", name); - return (0); -} - -char * -unrawname(name) - char *name; -{ - char *dp; - struct stat stb; - - if ((dp = rindex(name, '/')) == 0) - return (name); - if (stat(name, &stb) < 0) - return (name); - if ((stb.st_mode & S_IFMT) != S_IFCHR) - return (name); - if (dp[1] != 'r') - return (name); - (void)strcpy(&dp[1], &dp[2]); - return (name); -} - -char * -rawname(name) - char *name; -{ - static char rawbuf[32]; - char *dp; - - if ((dp = rindex(name, '/')) == 0) - return (0); - *dp = 0; - (void)strcpy(rawbuf, name); - *dp = '/'; - (void)strcat(rawbuf, "/r"); - (void)strcat(rawbuf, &dp[1]); - return (rawbuf); -} diff --git a/bsdfsck/setup.c b/bsdfsck/setup.c deleted file mode 100644 index f65ade47..00000000 --- a/bsdfsck/setup.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)setup.c 8.2 (Berkeley) 2/21/94";*/ -static char *rcsid = "$Id: setup.c,v 1.3 1994/08/25 15:22:35 mib Exp $"; -#endif /* not lint */ - -#define DKTYPENAMES -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/fs.h" -#include <sys/stat.h> -#include <sys/ioctl.h> -/* #include <sys/disklabel.h> */ -#include <sys/file.h> -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include "fsck.h" - -struct bufarea asblk; -#define altsblock (*asblk.b_un.b_fs) -#define POWEROF2(num) (((num) & ((num) - 1)) == 0) - -struct disklabel *getdisklabel(); - -setup(dev) - char *dev; -{ - long cg, size, asked, i, j; - long bmapsize; -/* struct disklabel *lp; */ - off_t sizepb; - struct stat statb; - struct fs proto; - - havesb = 0; - fswritefd = -1; - if (stat(dev, &statb) < 0) { - printf("Can't stat %s: %s\n", dev, strerror(errno)); - return (0); - } - if ((statb.st_mode & S_IFMT) != S_IFCHR) { - pfatal("%s is not a character device", dev); - if (reply("CONTINUE") == 0) - return (0); - } - if ((fsreadfd = open(dev, O_RDONLY)) < 0) { - printf("Can't open %s: %s\n", dev, strerror(errno)); - return (0); - } - if (preen == 0) - printf("** %s", dev); - if (nflag || (fswritefd = open(dev, O_WRONLY)) < 0) { - fswritefd = -1; - if (preen) - pfatal("NO WRITE ACCESS"); - printf(" (NO WRITE)"); - } - if (preen == 0) - printf("\n"); - fsmodified = 0; - lfdir = 0; - initbarea(&sblk); - initbarea(&asblk); - sblk.b_un.b_buf = malloc(SBSIZE); - asblk.b_un.b_buf = malloc(SBSIZE); - if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL) - errexit("cannot allocate space for superblock\n"); -#if 0 - if (lp = getdisklabel((char *)NULL, fsreadfd)) - dev_bsize = secsize = lp->d_secsize; - else -#endif - dev_bsize = secsize = DEV_BSIZE; - /* - * Read in the superblock, looking for alternates if necessary - */ - if (readsb(1) == 0) { - if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0) - return(0); - if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0) - return (0); - for (cg = 0; cg < proto.fs_ncg; cg++) { - bflag = fsbtodb(&proto, cgsblock(&proto, cg)); - if (readsb(0) != 0) - break; - } - if (cg >= proto.fs_ncg) { - printf("%s %s\n%s %s\n%s %s\n", - "SEARCH FOR ALTERNATE SUPER-BLOCK", - "FAILED. YOU MUST USE THE", - "-b OPTION TO FSCK TO SPECIFY THE", - "LOCATION OF AN ALTERNATE", - "SUPER-BLOCK TO SUPPLY NEEDED", - "INFORMATION; SEE fsck(8)."); - return(0); - } - pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag); - } - maxfsblock = sblock.fs_size; - maxino = sblock.fs_ncg * sblock.fs_ipg; - /* - * Check and potentially fix certain fields in the super block. - */ - if (sblock.fs_optim != FS_OPTTIME && sblock.fs_optim != FS_OPTSPACE) { - pfatal("UNDEFINED OPTIMIZATION IN SUPERBLOCK"); - if (reply("SET TO DEFAULT") == 1) { - sblock.fs_optim = FS_OPTTIME; - sbdirty(); - } - } - if ((sblock.fs_minfree < 0 || sblock.fs_minfree > 99)) { - pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK", - sblock.fs_minfree); - if (reply("SET TO DEFAULT") == 1) { - sblock.fs_minfree = 10; - sbdirty(); - } - } - if (sblock.fs_interleave < 1 || - sblock.fs_interleave > sblock.fs_nsect) { - pwarn("IMPOSSIBLE INTERLEAVE=%d IN SUPERBLOCK", - sblock.fs_interleave); - sblock.fs_interleave = 1; - if (preen) - printf(" (FIXED)\n"); - if (preen || reply("SET TO DEFAULT") == 1) { - sbdirty(); - dirty(&asblk); - } - } - if (sblock.fs_npsect < sblock.fs_nsect || - sblock.fs_npsect > sblock.fs_nsect*2) { - pwarn("IMPOSSIBLE NPSECT=%d IN SUPERBLOCK", - sblock.fs_npsect); - sblock.fs_npsect = sblock.fs_nsect; - if (preen) - printf(" (FIXED)\n"); - if (preen || reply("SET TO DEFAULT") == 1) { - sbdirty(); - dirty(&asblk); - } - } - if (sblock.fs_inodefmt >= FS_44INODEFMT) { - newinofmt = 1; - } else { - sblock.fs_qbmask = ~sblock.fs_bmask; - sblock.fs_qfmask = ~sblock.fs_fmask; - newinofmt = 0; - } - /* - * Convert to new inode format. - */ - if (cvtlevel >= 2 && sblock.fs_inodefmt < FS_44INODEFMT) { - if (preen) - pwarn("CONVERTING TO NEW INODE FORMAT\n"); - else if (!reply("CONVERT TO NEW INODE FORMAT")) - return(0); - doinglevel2++; - sblock.fs_inodefmt = FS_44INODEFMT; - sizepb = sblock.fs_bsize; - sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1; - for (i = 0; i < NIADDR; i++) { - sizepb *= NINDIR(&sblock); - sblock.fs_maxfilesize += sizepb; - } - sblock.fs_maxsymlinklen = MAXSYMLINKLEN; - sblock.fs_qbmask = ~sblock.fs_bmask; - sblock.fs_qfmask = ~sblock.fs_fmask; - sbdirty(); - dirty(&asblk); - } - /* - * Convert to new cylinder group format. - */ - if (cvtlevel >= 1 && sblock.fs_postblformat == FS_42POSTBLFMT) { - if (preen) - pwarn("CONVERTING TO NEW CYLINDER GROUP FORMAT\n"); - else if (!reply("CONVERT TO NEW CYLINDER GROUP FORMAT")) - return(0); - doinglevel1++; - sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT; - sblock.fs_nrpos = 8; - sblock.fs_postbloff = - (char *)(&sblock.fs_opostbl[0][0]) - - (char *)(&sblock.fs_link); - sblock.fs_rotbloff = &sblock.fs_space[0] - - (u_char *)(&sblock.fs_link); - sblock.fs_cgsize = - fragroundup(&sblock, CGSIZE(&sblock)); - sbdirty(); - dirty(&asblk); - } - if (asblk.b_dirty && !bflag) { - bcopy((char *)&sblock, (char *)&altsblock, - (size_t)sblock.fs_sbsize); - flush(fswritefd, &asblk); - } - /* - * read in the summary info. - */ - asked = 0; - for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { - size = sblock.fs_cssize - i < sblock.fs_bsize ? - sblock.fs_cssize - i : sblock.fs_bsize; - sblock.fs_csp[j] = (struct csum *)calloc(1, (unsigned)size); - if (bread(fsreadfd, (char *)sblock.fs_csp[j], - fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), - size) != 0 && !asked) { - pfatal("BAD SUMMARY INFORMATION"); - if (reply("CONTINUE") == 0) - errexit(""); - asked++; - } - } - /* - * allocate and initialize the necessary maps - */ - bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(short)); - blockmap = calloc((unsigned)bmapsize, sizeof (char)); - if (blockmap == NULL) { - printf("cannot alloc %u bytes for blockmap\n", - (unsigned)bmapsize); - goto badsb; - } - statemap = calloc((unsigned)(maxino + 1), sizeof(char)); - if (statemap == NULL) { - printf("cannot alloc %u bytes for statemap\n", - (unsigned)(maxino + 1)); - goto badsb; - } - typemap = calloc((unsigned)(maxino + 1), sizeof(char)); - if (typemap == NULL) { - printf("cannot alloc %u bytes for typemap\n", - (unsigned)(maxino + 1)); - goto badsb; - } - lncntp = (short *)calloc((unsigned)(maxino + 1), sizeof(short)); - if (lncntp == NULL) { - printf("cannot alloc %u bytes for lncntp\n", - (unsigned)(maxino + 1) * sizeof(short)); - goto badsb; - } - numdirs = sblock.fs_cstotal.cs_ndir; - inplast = 0; - listmax = numdirs + 10; - inpsort = (struct inoinfo **)calloc((unsigned)listmax, - sizeof(struct inoinfo *)); - inphead = (struct inoinfo **)calloc((unsigned)numdirs, - sizeof(struct inoinfo *)); - if (inpsort == NULL || inphead == NULL) { - printf("cannot alloc %u bytes for inphead\n", - (unsigned)numdirs * sizeof(struct inoinfo *)); - goto badsb; - } - bufinit(); - return (1); - -badsb: - ckfini(); - return (0); -} - -/* - * Read in the super block and its summary info. - */ -readsb(listerr) - int listerr; -{ - daddr_t super = bflag ? bflag : SBOFF / dev_bsize; - - if (bread(fsreadfd, (char *)&sblock, super, (long)SBSIZE) != 0) - return (0); - sblk.b_bno = super; - sblk.b_size = SBSIZE; - /* - * run a few consistency checks of the super block - */ - if (sblock.fs_magic != FS_MAGIC) - { badsb(listerr, "MAGIC NUMBER WRONG"); return (0); } - if (sblock.fs_ncg < 1) - { badsb(listerr, "NCG OUT OF RANGE"); return (0); } - if (sblock.fs_cpg < 1) - { badsb(listerr, "CPG OUT OF RANGE"); return (0); } - if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl || - (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl) - { badsb(listerr, "NCYL LESS THAN NCG*CPG"); return (0); } - if (sblock.fs_sbsize > SBSIZE) - { badsb(listerr, "SIZE PREPOSTEROUSLY LARGE"); return (0); } - /* - * Compute block size that the filesystem is based on, - * according to fsbtodb, and adjust superblock block number - * so we can tell if this is an alternate later. - */ - super *= dev_bsize; - dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); - sblk.b_bno = super / dev_bsize; - if (bflag) { - havesb = 1; - return (1); - } - /* - * Set all possible fields that could differ, then do check - * of whole super block against an alternate super block. - * When an alternate super-block is specified this check is skipped. - */ - getblk(&asblk, cgsblock(&sblock, sblock.fs_ncg - 1), sblock.fs_sbsize); - if (asblk.b_errs) - return (0); - altsblock.fs_link = sblock.fs_link; - altsblock.fs_rlink = sblock.fs_rlink; - altsblock.fs_time = sblock.fs_time; - altsblock.fs_cstotal = sblock.fs_cstotal; - altsblock.fs_cgrotor = sblock.fs_cgrotor; - altsblock.fs_fmod = sblock.fs_fmod; - altsblock.fs_clean = sblock.fs_clean; - altsblock.fs_ronly = sblock.fs_ronly; - altsblock.fs_flags = sblock.fs_flags; - altsblock.fs_maxcontig = sblock.fs_maxcontig; - altsblock.fs_minfree = sblock.fs_minfree; - altsblock.fs_optim = sblock.fs_optim; - altsblock.fs_rotdelay = sblock.fs_rotdelay; - altsblock.fs_maxbpg = sblock.fs_maxbpg; - bcopy((char *)sblock.fs_csp, (char *)altsblock.fs_csp, - sizeof sblock.fs_csp); - bcopy((char *)sblock.fs_fsmnt, (char *)altsblock.fs_fsmnt, - sizeof sblock.fs_fsmnt); - bcopy((char *)sblock.fs_sparecon, (char *)altsblock.fs_sparecon, - sizeof sblock.fs_sparecon); - /* - * The following should not have to be copied. - */ - altsblock.fs_fsbtodb = sblock.fs_fsbtodb; - altsblock.fs_interleave = sblock.fs_interleave; - altsblock.fs_npsect = sblock.fs_npsect; - altsblock.fs_nrpos = sblock.fs_nrpos; - altsblock.fs_qbmask = sblock.fs_qbmask; - altsblock.fs_qfmask = sblock.fs_qfmask; - altsblock.fs_state = sblock.fs_state; - altsblock.fs_maxfilesize = sblock.fs_maxfilesize; - if (bcmp((char *)&sblock, (char *)&altsblock, (int)sblock.fs_sbsize)) { - badsb(listerr, - "VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE"); - return (0); - } - havesb = 1; - return (1); -} - -badsb(listerr, s) - int listerr; - char *s; -{ - - if (!listerr) - return; - if (preen) - printf("%s: ", cdevname); - pfatal("BAD SUPER BLOCK: %s\n", s); -} - -/* XXX */ -calcsb (dev, devfd, fs) - char *dev; - int devfd; - struct fs *fs; -{ - return 0; -} - -#if 0 -/* - * Calculate a prototype superblock based on information in the disk label. - * When done the cgsblock macro can be calculated and the fs_ncg field - * can be used. Do NOT attempt to use other macros without verifying that - * their needed information is available! - */ -calcsb(dev, devfd, fs) - char *dev; - int devfd; - register struct fs *fs; -{ - register struct disklabel *lp; - register struct partition *pp; - register char *cp; - int i; - - cp = index(dev, '\0') - 1; - if (cp == (char *)-1 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp)) { - pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev); - return (0); - } - lp = getdisklabel(dev, devfd); - if (isdigit(*cp)) - pp = &lp->d_partitions[0]; - else - pp = &lp->d_partitions[*cp - 'a']; - if (pp->p_fstype != FS_BSDFFS) { - pfatal("%s: NOT LABELED AS A BSD FILE SYSTEM (%s)\n", - dev, pp->p_fstype < FSMAXTYPES ? - fstypenames[pp->p_fstype] : "unknown"); - return (0); - } - bzero((char *)fs, sizeof(struct fs)); - fs->fs_fsize = pp->p_fsize; - fs->fs_frag = pp->p_frag; - fs->fs_cpg = pp->p_cpg; - fs->fs_size = pp->p_size; - fs->fs_ntrak = lp->d_ntracks; - fs->fs_nsect = lp->d_nsectors; - fs->fs_spc = lp->d_secpercyl; - fs->fs_nspf = fs->fs_fsize / lp->d_secsize; - fs->fs_sblkno = roundup( - howmany(lp->d_bbsize + lp->d_sbsize, fs->fs_fsize), - fs->fs_frag); - fs->fs_cgmask = 0xffffffff; - for (i = fs->fs_ntrak; i > 1; i >>= 1) - fs->fs_cgmask <<= 1; - if (!POWEROF2(fs->fs_ntrak)) - fs->fs_cgmask <<= 1; - fs->fs_cgoffset = roundup( - howmany(fs->fs_nsect, NSPF(fs)), fs->fs_frag); - fs->fs_fpg = (fs->fs_cpg * fs->fs_spc) / NSPF(fs); - fs->fs_ncg = howmany(fs->fs_size / fs->fs_spc, fs->fs_cpg); - for (fs->fs_fsbtodb = 0, i = NSPF(fs); i > 1; i >>= 1) - fs->fs_fsbtodb++; - dev_bsize = lp->d_secsize; - return (1); -} - -struct disklabel * -getdisklabel(s, fd) - char *s; - int fd; -{ - static struct disklabel lab; - - if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) { - if (s == NULL) - return ((struct disklabel *)NULL); - pwarn("ioctl (GCINFO): %s\n", strerror(errno)); - errexit("%s: can't read disk label\n", s); - } - return (&lab); -} -#endif diff --git a/bsdfsck/utilities.c b/bsdfsck/utilities.c deleted file mode 100644 index 1c281b1b..00000000 --- a/bsdfsck/utilities.c +++ /dev/null @@ -1,567 +0,0 @@ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)utilities.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: utilities.c,v 1.2 1994/08/23 20:18:15 mib Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/time.h> -#include "../ufs/dinode.h" -#include "../ufs/dir.h" -#include "../ufs/fs.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include "fsck.h" - -long diskreads, totalreads; /* Disk cache statistics */ - -ftypeok(dp) - struct dinode *dp; -{ - switch (DI_MODE(dp) & IFMT) { - - case IFDIR: - case IFREG: - case IFBLK: - case IFCHR: - case IFLNK: - case IFSOCK: - case IFIFO: - return (1); - - default: - if (debug) - printf("bad file type 0%o\n", DI_MODE(dp)); - return (0); - } -} - -reply(question) - char *question; -{ - int persevere; - char c; - - if (preen) - pfatal("INTERNAL ERROR: GOT TO reply()"); - persevere = !strcmp(question, "CONTINUE"); - printf("\n"); - if (!persevere && (nflag || fswritefd < 0)) { - printf("%s? no\n\n", question); - return (0); - } - if (yflag || (persevere && nflag)) { - printf("%s? yes\n\n", question); - return (1); - } - do { - printf("%s? [yn] ", question); - (void) fflush(stdout); - c = getc(stdin); - while (c != '\n' && getc(stdin) != '\n') - if (feof(stdin)) - return (0); - } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); - printf("\n"); - if (c == 'y' || c == 'Y') - return (1); - return (0); -} - -/* - * Malloc buffers and set up cache. - */ -bufinit() -{ - register struct bufarea *bp; - long bufcnt, i; - char *bufp; - - pbp = pdirbp = (struct bufarea *)0; - bufp = malloc((unsigned int)sblock.fs_bsize); - if (bufp == 0) - errexit("cannot allocate buffer pool\n"); - cgblk.b_un.b_buf = bufp; - initbarea(&cgblk); - bufhead.b_next = bufhead.b_prev = &bufhead; - bufcnt = MAXBUFSPACE / sblock.fs_bsize; - if (bufcnt < MINBUFS) - bufcnt = MINBUFS; - for (i = 0; i < bufcnt; i++) { - bp = (struct bufarea *)malloc(sizeof(struct bufarea)); - bufp = malloc((unsigned int)sblock.fs_bsize); - if (bp == NULL || bufp == NULL) { - if (i >= MINBUFS) - break; - errexit("cannot allocate buffer pool\n"); - } - bp->b_un.b_buf = bufp; - bp->b_prev = &bufhead; - bp->b_next = bufhead.b_next; - bufhead.b_next->b_prev = bp; - bufhead.b_next = bp; - initbarea(bp); - } - bufhead.b_size = i; /* save number of buffers */ -} - -/* - * Manage a cache of directory blocks. - */ -struct bufarea * -getdatablk(blkno, size) - daddr_t blkno; - long size; -{ - register struct bufarea *bp; - - for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next) - if (bp->b_bno == fsbtodb(&sblock, blkno)) - goto foundit; - for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev) - if ((bp->b_flags & B_INUSE) == 0) - break; - if (bp == &bufhead) - errexit("deadlocked buffer pool\n"); - getblk(bp, blkno, size); - /* fall through */ -foundit: - totalreads++; - bp->b_prev->b_next = bp->b_next; - bp->b_next->b_prev = bp->b_prev; - bp->b_prev = &bufhead; - bp->b_next = bufhead.b_next; - bufhead.b_next->b_prev = bp; - bufhead.b_next = bp; - bp->b_flags |= B_INUSE; - return (bp); -} - -void -getblk(bp, blk, size) - register struct bufarea *bp; - daddr_t blk; - long size; -{ - daddr_t dblk; - - dblk = fsbtodb(&sblock, blk); - if (bp->b_bno != dblk) { - flush(fswritefd, bp); - diskreads++; - bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size); - bp->b_bno = dblk; - bp->b_size = size; - } -} - -flush(fd, bp) - int fd; - register struct bufarea *bp; -{ - register int i, j; - - if (!bp->b_dirty) - return; - if (bp->b_errs != 0) - pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n", - (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ", - bp->b_bno); - bp->b_dirty = 0; - bp->b_errs = 0; - bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); - if (bp != &sblk) - return; - for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { - bwrite(fswritefd, (char *)sblock.fs_csp[j], - fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), - sblock.fs_cssize - i < sblock.fs_bsize ? - sblock.fs_cssize - i : sblock.fs_bsize); - } -} - -rwerror(mesg, blk) - char *mesg; - daddr_t blk; -{ - - if (preen == 0) - printf("\n"); - pfatal("CANNOT %s: BLK %ld", mesg, blk); - if (reply("CONTINUE") == 0) - errexit("Program terminated\n"); -} - -ckfini() -{ - register struct bufarea *bp, *nbp; - int cnt = 0; - - if (fswritefd < 0) { - (void)close(fsreadfd); - return; - } - flush(fswritefd, &sblk); - if (havesb && sblk.b_bno != SBOFF / dev_bsize && - !preen && reply("UPDATE STANDARD SUPERBLOCK")) { - sblk.b_bno = SBOFF / dev_bsize; - sbdirty(); - flush(fswritefd, &sblk); - } - flush(fswritefd, &cgblk); - free(cgblk.b_un.b_buf); - for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) { - cnt++; - flush(fswritefd, bp); - nbp = bp->b_prev; - free(bp->b_un.b_buf); - free((char *)bp); - } - if (bufhead.b_size != cnt) - errexit("Panic: lost %d buffers\n", bufhead.b_size - cnt); - pbp = pdirbp = (struct bufarea *)0; - if (debug) - printf("cache missed %ld of %ld (%d%%)\n", diskreads, - totalreads, (int)(diskreads * 100 / totalreads)); - (void)close(fsreadfd); - (void)close(fswritefd); -} - -bread(fd, buf, blk, size) - int fd; - char *buf; - daddr_t blk; - long size; -{ - char *cp; - int i, errs; - off_t offset; - - offset = blk; - offset *= dev_bsize; - if (lseek(fd, offset, 0) < 0) - rwerror("SEEK", blk); - else if (read(fd, buf, (int)size) == size) - return (0); - rwerror("READ", blk); - if (lseek(fd, offset, 0) < 0) - rwerror("SEEK", blk); - errs = 0; - bzero(buf, (size_t)size); - printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:"); - for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) { - if (read(fd, cp, (int)secsize) != secsize) { - (void)lseek(fd, offset + i + secsize, 0); - if (secsize != dev_bsize && dev_bsize != 1) - printf(" %ld (%ld),", - (blk * dev_bsize + i) / secsize, - blk + i / dev_bsize); - else - printf(" %ld,", blk + i / dev_bsize); - errs++; - } - } - printf("\n"); - return (errs); -} - -bwrite(fd, buf, blk, size) - int fd; - char *buf; - daddr_t blk; - long size; -{ - int i; - char *cp; - off_t offset; - - if (fd < 0) - return; - offset = blk; - offset *= dev_bsize; - if (lseek(fd, offset, 0) < 0) - rwerror("SEEK", blk); - else if (write(fd, buf, (int)size) == size) { - fsmodified = 1; - return; - } - rwerror("WRITE", blk); - if (lseek(fd, offset, 0) < 0) - rwerror("SEEK", blk); - printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:"); - for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize) - if (write(fd, cp, (int)dev_bsize) != dev_bsize) { - (void)lseek(fd, offset + i + dev_bsize, 0); - printf(" %ld,", blk + i / dev_bsize); - } - printf("\n"); - return; -} - -/* - * allocate a data block with the specified number of fragments - */ -allocblk(frags) - long frags; -{ - register int i, j, k; - - if (frags <= 0 || frags > sblock.fs_frag) - return (0); - for (i = 0; i < maxfsblock - sblock.fs_frag; i += sblock.fs_frag) { - for (j = 0; j <= sblock.fs_frag - frags; j++) { - if (testbmap(i + j)) - continue; - for (k = 1; k < frags; k++) - if (testbmap(i + j + k)) - break; - if (k < frags) { - j += k; - continue; - } - for (k = 0; k < frags; k++) - setbmap(i + j + k); - n_blks += frags; - return (i + j); - } - } - return (0); -} - -/* - * Free a previously allocated block - */ -freeblk(blkno, frags) - daddr_t blkno; - long frags; -{ - struct inodesc idesc; - - idesc.id_blkno = blkno; - idesc.id_numfrags = frags; - (void)pass4check(&idesc); -} - -/* - * Find a pathname - */ -getpathname(namebuf, curdir, ino) - char *namebuf; - ino_t curdir, ino; -{ - int len; - register char *cp; - struct inodesc idesc; - static int busy = 0; - extern int findname(); - - if (curdir == ino && ino == ROOTINO) { - (void)strcpy(namebuf, "/"); - return; - } - if (busy || - (statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) { - (void)strcpy(namebuf, "?"); - return; - } - busy = 1; - bzero((char *)&idesc, sizeof(struct inodesc)); - idesc.id_type = DATA; - idesc.id_fix = IGNORE; - cp = &namebuf[MAXPATHLEN - 1]; - *cp = '\0'; - if (curdir != ino) { - idesc.id_parent = curdir; - goto namelookup; - } - while (ino != ROOTINO) { - idesc.id_number = ino; - idesc.id_func = findino; - idesc.id_name = ".."; - if ((ckinode(ginode(ino), &idesc) & FOUND) == 0) - break; - namelookup: - idesc.id_number = idesc.id_parent; - idesc.id_parent = ino; - idesc.id_func = findname; - idesc.id_name = namebuf; - if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0) - break; - len = strlen(namebuf); - cp -= len; - bcopy(namebuf, cp, (size_t)len); - *--cp = '/'; - if (cp < &namebuf[MAXNAMLEN]) - break; - ino = idesc.id_number; - } - busy = 0; - if (ino != ROOTINO) - *--cp = '?'; - bcopy(cp, namebuf, (size_t)(&namebuf[MAXPATHLEN] - cp)); -} - -void -catch() -{ - if (!doinglevel2) - ckfini(); - exit(12); -} - -/* - * When preening, allow a single quit to signal - * a special exit after filesystem checks complete - * so that reboot sequence may be interrupted. - */ -void -catchquit() -{ - extern returntosingle; - - printf("returning to single-user after filesystem check\n"); - returntosingle = 1; - (void)signal(SIGQUIT, SIG_DFL); -} - -/* - * Ignore a single quit signal; wait and flush just in case. - * Used by child processes in preen. - */ -void -voidquit() -{ - - sleep(1); - (void)signal(SIGQUIT, SIG_IGN); - (void)signal(SIGQUIT, SIG_DFL); -} - -/* - * determine whether an inode should be fixed. - */ -dofix(idesc, msg) - register struct inodesc *idesc; - char *msg; -{ - - switch (idesc->id_fix) { - - case DONTKNOW: - if (idesc->id_type == DATA) - direrror(idesc->id_number, msg); - else - pwarn(msg); - if (preen) { - printf(" (SALVAGED)\n"); - idesc->id_fix = FIX; - return (ALTERED); - } - if (reply("SALVAGE") == 0) { - idesc->id_fix = NOFIX; - return (0); - } - idesc->id_fix = FIX; - return (ALTERED); - - case FIX: - return (ALTERED); - - case NOFIX: - case IGNORE: - return (0); - - default: - errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix); - } - /* NOTREACHED */ -} - -/* VARARGS1 */ -errexit(s1, s2, s3, s4) - char *s1; -{ - printf(s1, s2, s3, s4); - exit(8); -} - -/* - * An unexpected inconsistency occurred. - * Die if preening, otherwise just print message and continue. - */ -/* VARARGS1 */ -pfatal(s, a1, a2, a3) - char *s; -{ - - if (preen) { - printf("%s: ", cdevname); - printf(s, a1, a2, a3); - printf("\n"); - printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", - cdevname); - exit(8); - } - printf(s, a1, a2, a3); -} - -/* - * Pwarn just prints a message when not preening, - * or a warning (preceded by filename) when preening. - */ -/* VARARGS1 */ -pwarn(s, a1, a2, a3, a4, a5, a6) - char *s; -{ - - if (preen) - printf("%s: ", cdevname); - printf(s, a1, a2, a3, a4, a5, a6); -} - -#ifndef lint -/* - * Stub for routines from kernel. - */ -panic(s) - char *s; -{ - - pfatal("INTERNAL INCONSISTENCY:"); - errexit(s); -} -#endif diff --git a/configure.in b/configure.in deleted file mode 100644 index 68ec159a..00000000 --- a/configure.in +++ /dev/null @@ -1,279 +0,0 @@ -dnl Process this file with autoconf to produce a configure script. -AC_REVISION([$Id: configure.in,v 1.38 2008/11/17 11:34:18 tschwinge Exp $]) -AC_PREREQ(2.54) dnl Minimum Autoconf version required. -AC_INIT([GNU Hurd], [0.3], [bug-hurd@gnu.org]) -AC_CONFIG_SRCDIR([hurd/hurd_types.h]) dnl File to look for in srcdir. - -AC_PREFIX_DEFAULT() dnl Default to empty prefix, not /usr/local. - -AC_CANONICAL_HOST -case "$host_os" in -gnu*) ;; -none) AC_MSG_ERROR([ -*** You must specify a host of $host_cpu-gnu or $host_cpu-$host_vendor-gnu -*** to configure; you will need to use the same host specification -*** to configure other packages for the GNU/Hurd system.]) ;; -*) AC_MSG_ERROR([this is the gnu os, host cannot be $host_os -*** Host configuration must be \`MACHINE-gnu' or \`MACHINE-VENDOR-gnu'. -*** To cross-compile, you must specify both --host and --build; -*** for example \`--build=$host --host=$host_cpu-gnu'. -*** Run $0 --help for more information.]) ;; -esac - -case "$host_cpu" in -alpha*) - asm_syntax=alpha - ;; -arm*) - asm_syntax=arm - ;; -m68k | m680?0) - asm_syntax=m68k - ;; -mips*) - asm_syntax=mips - ;; -i?86) - asm_syntax=i386 - ;; -powerpc*) - asm_syntax=ppc - ;; -sparc64* | ultrasparc*) - asm_syntax=sparc64 - ;; -sparc*) - asm_syntax=sparc - ;; -*) - asm_syntax="$host_cpu" - ;; -esac -AC_SUBST(asm_syntax) - -test -r "$srcdir/libthreads/$asm_syntax/cthreads.h" || { - AC_MSG_WARN([unsupported CPU type $host_cpu]) -} - -AC_ARG_ENABLE(profile, -[ --disable-profile do not build profiled libraries and programs]) -AC_SUBST(enable_profile) - -define([default_static],['ext2fs,ufs'])dnl -AC_ARG_ENABLE(static-progs, -[ --enable-static-progs=PROGRAMS... - build statically-linked PROGRAM.static versions - of (only) the listed programs ]dnl -changequote(',')[default_static]changequote([,])) -case "$enable_static_progs" in -'no') enable_static_progs= ;; # we got --disable-static -'') enable_static_progs=default_static ;; -esac -# Convert comma/space-separated list into space-separated list. -enable_static_progs=`echo "$enable_static_progs" | sed 's/[[, ]][[, ]]*/ /g'` -AC_SUBST(enable_static_progs) - -[# Don't needlessly overwrite files that whose contents haven't changed. This -# helps for avoinding unneccessary recompilation cycles when keeping -# cross-compilation toolchains up-to-date. Thus, unconditionally use the -# supplied `install-sh', as the GNU Coreutils one doesn't provide this -# functionality yet (TODO: change that). TODO: $ac_abs_top_builddir et al. are -# not yet available here, that's why we use `readlink' (but only if available). -INSTALL="$SHELL $(readlink -f "$ac_install_sh")"\ -C || unset INSTALL] -AC_PROG_INSTALL -AC_PROG_AWK - -AC_PROG_CC -# Require GCC. -if test x$GCC != xyes; then - AC_MSG_ERROR([this code uses GNU C extensions, you must compile with GCC]) -fi - -AC_CHECK_TOOL(LD, ld) -AC_CHECK_TOOL(OBJCOPY, objcopy) -AC_CHECK_TOOL(AR, ar) -AC_CHECK_TOOL(RANLIB, ranlib) -AC_CHECK_TOOL(MIG, mig) -# Require MiG. -if test x${MIG} = x; then - AC_MSG_ERROR([ -*** You need GNU MiG to compile the GNU Hurd, please see -*** http://www.gnu.org/software/hurd/mig.html for further details, or -*** download it directly from the main GNU server (ftp.gnu.org) or any -*** GNU mirror.]) -fi - -dnl Let these propagate from the environment. -AC_SUBST(CFLAGS) AC_SUBST(CPPFLAGS) AC_SUBST(LDFLAGS) - -# See if there's a separate libcrypt (many systems put crypt there). -AC_CHECK_LIB(crypt, crypt, LIBCRYPT=-lcrypt) -AC_SUBST(LIBCRYPT) - -hurd_MIG_RETCODE - -# See if --version-script is available. -AC_CACHE_CHECK(for ld --version-script, hurd_cv_ld_version_script_option, [dnl -cat > conftest.c <<\EOF -void foobar() {} -EOF -cat > conftest.map <<\EOF -VERS_1 { - global: sym; -}; - -VERS_2 { - global: sym; -} VERS_1; -EOF - -if AC_TRY_COMMAND([eval $ac_compile 1>&AS_MESSAGE_LOG_FD()]) && - AC_TRY_COMMAND([${CC-cc} $CFLAGS -shared -o conftest.so conftest.o - -nostartfiles -nostdlib - -Wl,--version-script,conftest.map - 1>&AS_MESSAGE_LOG_FD()]); then - hurd_cv_ld_version_script_option=yes -else - hurd_cv_ld_version_script_option=no -fi -rm -f conftest*]) - -# See if libc was built with --enable-libio. -AC_CACHE_CHECK([for libio], - hurd_cv_libio, - AC_TRY_COMPILE([#include <stdio.h> -#ifndef _STDIO_USES_IOSTREAM -# error No libio found. -#endif],, - hurd_cv_libio=yes, - hurd_cv_libio=no)) - -# The versions of the symbols in libthreads have to match those in -# libc.so. Since the symbols in a libc that includes libio will be -# versioned differently from the ones in a libc that uses stdio, this -# isn't easy to accomplish. Instead we leave things unversioned if -# libio isn't found. -if test $hurd_cv_libio = yes; then - VERSIONING=$hurd_cv_ld_version_script_option -else - VERSIONING=no -fi -AC_SUBST(VERSIONING) - -# Check if libc contains getgrouplist and/or uselocale. -AC_CHECK_FUNCS(getgrouplist uselocale) - - -# From glibc HEAD, 2007-11-07. -AC_CACHE_CHECK(for -fgnu89-inline, libc_cv_gnu89_inline, [dnl -cat > conftest.c <<EOF -int foo; -#ifdef __GNUC_GNU_INLINE__ -main () { return 0;} -#else -#error -#endif -EOF -if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -S -std=gnu99 -fgnu89-inline - -o conftest.s conftest.c 1>&AS_MESSAGE_LOG_FD]) -then - libc_cv_gnu89_inline=yes -else - libc_cv_gnu89_inline=no -fi -rm -f conftest*]) -if test $libc_cv_gnu89_inline = yes; then - libc_cv_gnu89_inline=-fgnu89-inline -else - libc_cv_gnu89_inline= -fi -AC_SUBST(libc_cv_gnu89_inline) - - -# Insist on libparted unless the user declines explicitely -AC_ARG_WITH([parted], - [AS_HELP_STRING([--without-parted], [disable user-space partition stores])], - [], - [with_parted=yes]) - -PARTED_LIBS= -AC_DEFUN([PARTED_FAIL], [ - AC_MSG_FAILURE([Please install required libraries or use --without-parted.]) -]) -AS_IF([test "x$with_parted" != xno], [ - AC_CHECK_HEADER([parted/parted.h], - [AC_DEFINE(HAVE_PARTED_PARTED_H)], - [PARTED_FAIL]) - AC_CHECK_LIB([parted], [ped_device_read], [], [PARTED_FAIL]) - AC_CHECK_LIB([uuid], [uuid_generate], [], [PARTED_FAIL]) - AC_CHECK_LIB([dl], [dlopen], [], [PARTED_FAIL]) - PARTED_LIBS="-lparted -luuid -ldl" -]) -AC_SUBST([PARTED_LIBS]) - -AC_ARG_ENABLE(boot-store-types, -[ --enable-boot-store-types=TYPES... - list of store types included in statically - linked filesystems used for booting])dnl -if test -z "$enable_boot_store_types"; then - boot_store_types='device remap gunzip bunzip2' - test -z "$PARTED_LIBS" || boot_store_types="$boot_store_types part" -elif test "x$enable_boot_store_types" = xno; then - AC_MSG_WARN([you probably wanted --disable-static-progs]) -else - boot_store_types="$enable_boot_store_types" -fi -AC_SUBST(boot_store_types)dnl -AC_MSG_CHECKING(boot store types) -AC_MSG_RESULT($boot_store_types) - -AC_ARG_ENABLE(pcap, AS_HELP_STRING([--disable-pcap], [Disable pcap]), - [install_pcap=$enableval pcap_fail=yes], [install_pcap=yes pcap_fail=no]) - -if test "$install_pcap" = "yes"; then - AC_CHECK_LIB(pcap, pcap_compile, LIBPCAP=-lpcap, LIBPCAP=no) - AC_SUBST(LIBPCAP) - if test "$LIBPCAP" = "no"; then - if test "$pcap_fail" = "yes"; then - AC_MSG_ERROR([libpcap must be install in order to use eth-filter]) - else - LIBPCAP="" - fi - fi -fi - -AC_CHECK_LIB(pciaccess, pci_system_init, LIBPCIACCESS=-lpciaccess, LIBPCIACCESS=no) -AC_SUBST(LIBPCIACCESS) -if test "$LIBPCIACCESS" = "no"; then - AC_MSG_ERROR([libpciaccess must be install in order to use libddekit]) -fi - -# Check for ncursesw, which is needed for the console-curses client. -hurd_LIB_NCURSESW - -# Check for Sun RPC headers and library. -AC_CHECK_HEADER([rpc/types.h], [HAVE_SUN_RPC=yes], [HAVE_SUN_RPC=no]) -AC_SEARCH_LIBS([clnt_create], [], [:], [HAVE_SUN_RPC=no]) -AC_SUBST([HAVE_SUN_RPC]) - -if test -f ./$ac_unique_file; then - # Configuring in source directory; don't create any Makefiles. - makefiles= -else - # We are configuring in a separate build tree. - # Create a Makefile in the top-level build directory and - # one for each subdirectory Makefile in the source. - makefiles="Makeconf:build.mkcf.in \ - `cd $srcdir; for file in Makefile */Makefile; do \ - echo ${file}:build.mk.in; done`" -fi - -AC_CONFIG_FILES([config.make ${makefiles}]) -AC_OUTPUT - -dnl Local Variables: -dnl comment-start: "dnl " -dnl comment-end: "" -dnl comment-start-skip: "\\bdnl\\b\\s *" -dnl compile-command: "autoconf" -dnl End: diff --git a/dde_e100/Makeconf.local b/dde_e100/Makeconf.local index fb8e6ae6..130c8cc7 100644 --- a/dde_e100/Makeconf.local +++ b/dde_e100/Makeconf.local @@ -4,10 +4,10 @@ SYSTEM = x86-l4v2 BUILDDIR ?= .. -libmachdev_path := $(BUILDDIR)/libmachdev/libmachdev.a -libddekit_path := $(BUILDDIR)/libddekit/libddekit.a -libslab_path := $(BUILDDIR)/libhurd-slab/libhurd-slab.a -libbpf_path := $(BUILDDIR)/libbpf/libbpf.a +libmachdev_path := -L$(BUILDDIR)/libmachdev -lmachdev +libddekit_path := -L$(BUILDDIR)/libddekit -lddekit +libslab_path := -L$(BUILDDIR)/libhurd-slab -lhurd-slab +libbpf_path := -L$(BUILDDIR)/libbpf -lbpf DDEKITLIBDIR = $(PKGDIR)/../libddekit/ DDEKITINCDIR = $(PKGDIR)/../libddekit/include diff --git a/dde_e100/Makefile b/dde_e100/Makefile index f8ce6063..1f3c4c03 100644 --- a/dde_e100/Makefile +++ b/dde_e100/Makefile @@ -7,7 +7,7 @@ TARGET = dde_e100 SRC_C = main.c e100.c -LIBS += $(libmachdev_path) -ldde_linux26.o -ldde_linux26_net $(libddekit_path) -lfshelp -ltrivfs -lpciaccess -lpthread -lshouldbeinlibc -lports $(libslab_path) $(libbpf_path) +LIBS += $(libmachdev_path) -ldde_linux26.o -ldde_linux26_net $(libddekit_path) -lfshelp -ltrivfs -lpciaccess -lz -lpthread -lshouldbeinlibc -lports $(libslab_path) $(libbpf_path) CFLAGS += -g -I$(PKGDIR)/include -I$(BUILDDIR)/include # DDE configuration diff --git a/dde_e1000/Makeconf.local b/dde_e1000/Makeconf.local index fb8e6ae6..130c8cc7 100644 --- a/dde_e1000/Makeconf.local +++ b/dde_e1000/Makeconf.local @@ -4,10 +4,10 @@ SYSTEM = x86-l4v2 BUILDDIR ?= .. -libmachdev_path := $(BUILDDIR)/libmachdev/libmachdev.a -libddekit_path := $(BUILDDIR)/libddekit/libddekit.a -libslab_path := $(BUILDDIR)/libhurd-slab/libhurd-slab.a -libbpf_path := $(BUILDDIR)/libbpf/libbpf.a +libmachdev_path := -L$(BUILDDIR)/libmachdev -lmachdev +libddekit_path := -L$(BUILDDIR)/libddekit -lddekit +libslab_path := -L$(BUILDDIR)/libhurd-slab -lhurd-slab +libbpf_path := -L$(BUILDDIR)/libbpf -lbpf DDEKITLIBDIR = $(PKGDIR)/../libddekit/ DDEKITINCDIR = $(PKGDIR)/../libddekit/include diff --git a/dde_e1000/Makefile b/dde_e1000/Makefile index 2062d0b5..e0a1524b 100644 --- a/dde_e1000/Makefile +++ b/dde_e1000/Makefile @@ -7,7 +7,7 @@ TARGET = dde_e1000 SRC_C = main.c e1000_ethtool.c e1000_hw.c e1000_main.c e1000_param.c -LIBS += $(libmachdev_path) -ldde_linux26.o -ldde_linux26_net $(libddekit_path) -lfshelp -ltrivfs -lpciaccess -lpthread -lshouldbeinlibc -lports $(libslab_path) $(libbpf_path) +LIBS += $(libmachdev_path) -ldde_linux26.o -ldde_linux26_net $(libddekit_path) -lfshelp -ltrivfs -lpciaccess -lz -lpthread -lshouldbeinlibc -lports $(libslab_path) $(libbpf_path) CFLAGS += -g -I$(PKGDIR)/include -I$(BUILDDIR)/include # DDE configuration diff --git a/dde_ne2k_pci/Makeconf.local b/dde_ne2k_pci/Makeconf.local index fb8e6ae6..130c8cc7 100644 --- a/dde_ne2k_pci/Makeconf.local +++ b/dde_ne2k_pci/Makeconf.local @@ -4,10 +4,10 @@ SYSTEM = x86-l4v2 BUILDDIR ?= .. -libmachdev_path := $(BUILDDIR)/libmachdev/libmachdev.a -libddekit_path := $(BUILDDIR)/libddekit/libddekit.a -libslab_path := $(BUILDDIR)/libhurd-slab/libhurd-slab.a -libbpf_path := $(BUILDDIR)/libbpf/libbpf.a +libmachdev_path := -L$(BUILDDIR)/libmachdev -lmachdev +libddekit_path := -L$(BUILDDIR)/libddekit -lddekit +libslab_path := -L$(BUILDDIR)/libhurd-slab -lhurd-slab +libbpf_path := -L$(BUILDDIR)/libbpf -lbpf DDEKITLIBDIR = $(PKGDIR)/../libddekit/ DDEKITINCDIR = $(PKGDIR)/../libddekit/include diff --git a/dde_ne2k_pci/Makefile b/dde_ne2k_pci/Makefile index 29396856..932d5ad0 100644 --- a/dde_ne2k_pci/Makefile +++ b/dde_ne2k_pci/Makefile @@ -9,7 +9,7 @@ TARGET = dde_ne2k_pci SRC_C = main.c ne2k-pci.c 8390.c -LIBS += $(libmachdev_path) -ldde_linux26.o -ldde_linux26_net $(libddekit_path) -lfshelp -ltrivfs -lpciaccess -lpthread -lshouldbeinlibc -lports $(libslab_path) $(libbpf_path) +LIBS += $(libmachdev_path) -ldde_linux26.o -ldde_linux26_net $(libddekit_path) -lfshelp -ltrivfs -lpciaccess -lz -lpthread -lshouldbeinlibc -lports $(libslab_path) $(libbpf_path) CFLAGS += -g -I$(PKGDIR)/include -I$(BUILDDIR)/include # DDE configuration diff --git a/dde_pcnet32/Makeconf.local b/dde_pcnet32/Makeconf.local index fb8e6ae6..130c8cc7 100644 --- a/dde_pcnet32/Makeconf.local +++ b/dde_pcnet32/Makeconf.local @@ -4,10 +4,10 @@ SYSTEM = x86-l4v2 BUILDDIR ?= .. -libmachdev_path := $(BUILDDIR)/libmachdev/libmachdev.a -libddekit_path := $(BUILDDIR)/libddekit/libddekit.a -libslab_path := $(BUILDDIR)/libhurd-slab/libhurd-slab.a -libbpf_path := $(BUILDDIR)/libbpf/libbpf.a +libmachdev_path := -L$(BUILDDIR)/libmachdev -lmachdev +libddekit_path := -L$(BUILDDIR)/libddekit -lddekit +libslab_path := -L$(BUILDDIR)/libhurd-slab -lhurd-slab +libbpf_path := -L$(BUILDDIR)/libbpf -lbpf DDEKITLIBDIR = $(PKGDIR)/../libddekit/ DDEKITINCDIR = $(PKGDIR)/../libddekit/include diff --git a/dde_pcnet32/Makefile b/dde_pcnet32/Makefile index 1bf47c4c..e228a619 100644 --- a/dde_pcnet32/Makefile +++ b/dde_pcnet32/Makefile @@ -7,7 +7,7 @@ TARGET = dde_pcnet32 SRC_C = main.c pcnet32.c -LIBS += $(libmachdev_path) -ldde_linux26.o -ldde_linux26_net $(libddekit_path) -lfshelp -ltrivfs -lpciaccess -lpthread -lshouldbeinlibc -lports $(libslab_path) $(libbpf_path) +LIBS += $(libmachdev_path) -ldde_linux26.o -ldde_linux26_net $(libddekit_path) -lfshelp -ltrivfs -lpciaccess -lz -lpthread -lshouldbeinlibc -lports $(libslab_path) $(libbpf_path) CFLAGS += -g -I$(PKGDIR)/include -I$(BUILDDIR)/include # DDE configuration diff --git a/dde_rtl8139/Makeconf.local b/dde_rtl8139/Makeconf.local index fb8e6ae6..130c8cc7 100644 --- a/dde_rtl8139/Makeconf.local +++ b/dde_rtl8139/Makeconf.local @@ -4,10 +4,10 @@ SYSTEM = x86-l4v2 BUILDDIR ?= .. -libmachdev_path := $(BUILDDIR)/libmachdev/libmachdev.a -libddekit_path := $(BUILDDIR)/libddekit/libddekit.a -libslab_path := $(BUILDDIR)/libhurd-slab/libhurd-slab.a -libbpf_path := $(BUILDDIR)/libbpf/libbpf.a +libmachdev_path := -L$(BUILDDIR)/libmachdev -lmachdev +libddekit_path := -L$(BUILDDIR)/libddekit -lddekit +libslab_path := -L$(BUILDDIR)/libhurd-slab -lhurd-slab +libbpf_path := -L$(BUILDDIR)/libbpf -lbpf DDEKITLIBDIR = $(PKGDIR)/../libddekit/ DDEKITINCDIR = $(PKGDIR)/../libddekit/include diff --git a/dde_rtl8139/Makefile b/dde_rtl8139/Makefile index 95b6fa0a..91a7df93 100644 --- a/dde_rtl8139/Makefile +++ b/dde_rtl8139/Makefile @@ -9,7 +9,7 @@ TARGET = dde_rtl8139 SRC_C = main.c 8139cp.c -LIBS += $(libmachdev_path) -ldde_linux26.o -ldde_linux26_net $(libddekit_path) -lfshelp -ltrivfs -lpciaccess -lpthread -lshouldbeinlibc -lports $(libslab_path) $(libbpf_path) +LIBS += $(libmachdev_path) -ldde_linux26.o -ldde_linux26_net $(libddekit_path) -lfshelp -ltrivfs -lpciaccess -lz -lpthread -lshouldbeinlibc -lports $(libslab_path) $(libbpf_path) CFLAGS += -g -I$(PKGDIR)/include -I$(BUILDDIR)/include # DDE configuration diff --git a/eth-filter.multi-thread/ChangeLog b/eth-filter.multi-thread/ChangeLog deleted file mode 100644 index cd920067..00000000 --- a/eth-filter.multi-thread/ChangeLog +++ /dev/null @@ -1,105 +0,0 @@ -2008-08-22 Zheng Da <zhengda1936@gmail.com> - - * README: Update. - - * filter.c (proxy_info): Removed. - (proxy_pfinetpi_ht): Removed. - (proxy_devicepi_ht): Removed. - (create_proxy): Removed. - (destroy_proxy): Removed. - (proxy_device): New structure. - (proxy_user): New structure. - (proxy): New structure. - (create_proxy_user): New function. - (create_proxy_device): New function. - (clean_proxy_user): New function. - (clean_proxy_device): New function. - (ethernet_demuxer): Get the data from proxy object instead of from - proxy_info. - (do_mach_notify_dead_name): Likewise. - (ds_device_write): Likewise. - (ds_device_write_inband): Likewise. - (ds_device_read): Likewise. - (ds_device_read_inband): Likewise. - (ds_device_map): Likewise. - (ds_device_set_status): Likewise. - (ds_device_get_status): Likewise. - (ds_device_set_filter): Likewise. Create the proxy_device object. - (do_mach_notify_no_senders): Use ports_do_mach_notify_no_senders(). - (ds_device_open): Create proxy_user and proxy objects. - (main): Add the cleaning routine when creating the port class. - -2008-08-20 Zheng Da <zhengda1936@gmail.com> - - * README: Update. - - * filter.c (options): Update. - -2008-08-20 Zheng Da <zhengda1936@gmail.com> - - * filter.c (destroy_proxy): Test p_deliverport_hashloc before removing - it from proxy_deliverport_ht, and reverse the order of calling - ports_destroy_right and ports_port_deref. - (ds_device_open): Test device_file and replace "eth" with the variable - name. - -2008-08-20 Zheng Da <zhengda1936@gmail.com> - - * filter.c (device_file): Change the name of a variable. - (ds_device_open): Use device_file directly. - -2008-08-19 Zheng Da <zhengda1936@gmail.com> - - * filter.c (ds_device_open): Generate the device file name, and use it - to open the device. - -2008-08-18 Zheng Da <zhengda1936@gmail.com> - - * README: New file. - - -2008-08-17 Zheng Da <zhengda1936@gmail.com> - - * filter.c (device_name): Remove its default value. - (options): Remove the option '-M'. - (create_proxy): Get the port directly from port_right field in port_info. - (ds_device_open): Remove the code of checking the device name, - and open the device from the device file. - (parse_opt): Remove the code of handling the option '-M'. - (main): Remove the code of getting the master device port. - - -2008-08-14 Zheng Da <zhengda1936@gmail.com> - - * filter.c (pfinet_portclass, device_portclass, other_portclass): - New variables. - (create_proxy): Use pfinet_portclass and device_portclass to create the - port. - (destroy_proxy): Dereference the port before destroying it. - (trivfs_goaway): Test the number of ports in pfinet_portclass and destroy - the master_device. - (main): Create pfinet_portclass, device_portclass, other_portclass. - (print_msg): Deleted. - (deliver_msg): Remove debuging print. - - * ChangeLog: New file. - - -2008-08-13 Zheng Da <zhengda1936@gmail.com> - - * bpf_impl.c: New file. - - * Makefile: New file. - - * queue.c: New file. - - * util.h: New file. - - * bpf_impl.h: New file. - - * filter.c: New file. - - * pcap_filter.c: New file. - - * queue.h: New file. - diff --git a/eth-filter.multi-thread/Makefile b/eth-filter.multi-thread/Makefile deleted file mode 100644 index c9abe3fd..00000000 --- a/eth-filter.multi-thread/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 2008 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. - -dir := eth-filter -makemode := server - -SRCS = bpf_impl.c filter.c queue.c pcap_filter.c msg_queue.c -LCLHDRS = bpf_impl.h queue.h util.h filter.h msg_queue.h -DIST_FILES = ourdevice.defs notify.defs device_reply.defs -HURDLIBS = threads ports trivfs fshelp ihash shouldbeinlibc -target = eth-filter -MIGSTUBS = ourdeviceServer.o notifyServer.o device_replyUser.o -OBJS = $(SRCS:.c=.o) $(MIGSTUBS) - -include ../Makeconf - -CFLAGS += -I../pfinet/linux-src/include -I../pfinet/glue-include -LDFLAGS += -lpcap - -ourdevice.defs: device.defs - $(CPP) $(CPPFLAGS) -x c $< | sed -e '/out[ ]*device[ ]*:[ ]*device_t/s/device_t/mach_port_send_t/' > $@ diff --git a/eth-filter.multi-thread/README b/eth-filter.multi-thread/README deleted file mode 100644 index 2ef16eda..00000000 --- a/eth-filter.multi-thread/README +++ /dev/null @@ -1,39 +0,0 @@ -[Introduce] - -eth-filter is a filter translator that runs on the network device. The goal of eth-filter is to allow the user to setup the policy to control the traffic to the network. For example, it can block the invalid packet or the packet with the wrong destination address. It can work with eth-multiplexer to control and reduce the traffic between eth-multiplexer and pfinet, and can also work alone, running directly on the real network device. - - -[Usage] - -Usage: eth-filter [OPTION...] -Hurd filter translator. - - -i, --interface=DEVICE Network interface to use - -s, --send-filter=string The filter rule which applies to the outgoing - packet - -r, --receive-filter=string The filter rule which applies to the ingoing - packet - -S, --send-ip-range=IP range A range of IP to create the send filter - -R, --receive-ip-range=IP range - A range of IP to create the receive filter - -?, --help Give this help list - --usage Give a short usage message - -V, --version Print program version - -Mandatory or optional arguments to long options are also mandatory or optional -for any corresponding short options. - - -The '-i' option specifies the network interface the translator sits on. eth-filter can only connect to one network interface and the '-i' option should be only used once. DEVICE is a device file created by devnode translator. -The '-s' and '-r' options give the user a full control to specify the filter rules which applies to the outgoing packet and the incoming packet, respectively. The expression of the rule is the same as the one in TCPDUMP. -The '-S' and '-R' options specify a range of IP that the user wants to filter. They are used to create the sending filter and the receiving filter, respectively. The generated rule is "arp or (ip and src net addr/prefixlen)" or "arp or (ip and dst net addr/prefixlen)". If prefixlen is 32, it can be omitted. -NOTE: '-s' and '-S' cannot be used together. One will replace the other if they are both used. So are '-r' and '-R' options. -An example: settrans -acfg /servers/feth0 /hurd/eth-filter -i /dev/eth0 -S 192.168.8.0/24 -R 192.168.8.0/24 - -[Internal] - -eth-filter works as a proxy, forwarding the packet between the user program and the network interface. In order to forward packets, eth-filter runs as a client to the network device. It opens the device and writes the packet to the network device as pfinet does. It calls device_set_filter() to set the filter rule and give its own port to the device so it can receive packets from the device. The rule passed to the network device is from the user program that connects to eth-filter. -eth-filter works as a RPC server to communicate with the user program and implements the server side functions in device.defs. It gets the packet in the server side function ds_device_write and gets the port to deliver packets to the user program in ds_device_set_filter. -Three structures are used for one pair of the user program and the device: proxy_user, proxy_device, proxy. When the ds_device_open() is called, a proxy_user and proxy objectis created. A proxy_device object is created when the ds_device_set_filter() is called. The proxy_user and proxy_device extend port_info structure. When a packet is received from the user program or from the device, we have to retrieve the proxy object to get the corresponding information. This process is very similar as pflocal. When a user program exits, we need to destroy its proxy_user object and proxy object, and meanwhile, the proxy_device object related to the proxy object is also destroyed. -Two filters exist in eth-filter, one for outgoing packets and the other for incoming packets. These are BPF filters, which are ported from GNU Mach. These BPF filters only decide whether the packet should be forwarded, and they cannot decide the destination of the packet. The BPF instructions are generated by libpcap from the filter rules given by '-s' and '-r' or '-S' and '-R' options. - diff --git a/eth-filter.multi-thread/bpf_impl.c b/eth-filter.multi-thread/bpf_impl.c deleted file mode 100644 index e9202a5f..00000000 --- a/eth-filter.multi-thread/bpf_impl.c +++ /dev/null @@ -1,872 +0,0 @@ - /* - * Mach Operating System - * Copyright (c) 1993-1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * Author: David B. Golub, Carnegie Mellon University - * Date: 3/98 - * - * Network IO. - * - * Packet filter code taken from vaxif/enet.c written - * CMU and Stanford. - */ - -/* the code copied from device/net_io.c in Mach */ - -#include <arpa/inet.h> -#include <string.h> - -#include <mach.h> -#include <hurd.h> - -#include "bpf_impl.h" -#include "queue.h" -#include "util.h" - -queue_head_t rcv_port_list; /* input filter list */ -queue_head_t snd_port_list; /* output filter list */ - -/* - * Execute the filter program starting at pc on the packet p - * wirelen is the length of the original packet - * buflen is the amount of data present - * - * @p: packet data. - * @wirelen: data_count (in bytes) - * @hlen: header len (in bytes) - */ - -int -mach_bpf_do_filter(net_rcv_port_t infp, char *p, unsigned int wirelen, - char *header, unsigned int hlen, net_hash_entry_t **hash_headpp, - net_hash_entry_t *entpp) -{ - register bpf_insn_t pc, pc_end; - register unsigned int buflen; - - register unsigned long A, X; - register int k; - unsigned int mem[BPF_MEMWORDS]; - - /* Generic pointer to either HEADER or P according to the specified offset. */ - char *data = NULL; - - pc = ((bpf_insn_t) infp->filter) + 1; - /* filter[0].code is (NETF_BPF | flags) */ - pc_end = (bpf_insn_t)infp->filter_end; - buflen = NET_RCV_MAX; - *entpp = 0; /* default */ - - A = 0; - X = 0; - for (; pc < pc_end; ++pc) { - switch (pc->code) { - - default: - abort(); - case BPF_RET|BPF_K: - if (infp->rcv_port == MACH_PORT_NULL && - *entpp == 0) { - return 0; - } - return ((u_int)pc->k <= wirelen) ? - pc->k : wirelen; - - case BPF_RET|BPF_A: - if (infp->rcv_port == MACH_PORT_NULL && - *entpp == 0) { - return 0; - } - return ((u_int)A <= wirelen) ? - A : wirelen; - - case BPF_RET|BPF_MATCH_IMM: - if (mach_bpf_match ((net_hash_header_t)infp, pc->jt, mem, - hash_headpp, entpp)) { - return ((u_int)pc->k <= wirelen) ? - pc->k : wirelen; - } - return 0; - - case BPF_LD|BPF_W|BPF_ABS: - k = pc->k; - -load_word: - if ((u_int)k + sizeof(long) <= hlen) - data = header; - else if ((u_int)k + sizeof(long) <= buflen) { - k -= hlen; - data = p; - } else - return 0; - -#ifdef BPF_ALIGN - if (((int)(data + k) & 3) != 0) - A = EXTRACT_LONG(&data[k]); - else -#endif - A = ntohl(*(long *)(data + k)); - continue; - - case BPF_LD|BPF_H|BPF_ABS: - k = pc->k; - -load_half: - if ((u_int)k + sizeof(short) <= hlen) - data = header; - else if ((u_int)k + sizeof(short) <= buflen) { - k -= hlen; - data = p; - } else - return 0; - - A = EXTRACT_SHORT(&data[k]); - continue; - - case BPF_LD|BPF_B|BPF_ABS: - k = pc->k; - -load_byte: - if ((u_int)k < hlen) - data = header; - else if ((u_int)k < buflen) { - data = p; - k -= hlen; - } else - return 0; - - A = data[k]; - continue; - - case BPF_LD|BPF_W|BPF_LEN: - A = wirelen; - continue; - - case BPF_LDX|BPF_W|BPF_LEN: - X = wirelen; - continue; - - case BPF_LD|BPF_W|BPF_IND: - k = X + pc->k; - goto load_word; - - case BPF_LD|BPF_H|BPF_IND: - k = X + pc->k; - goto load_half; - - case BPF_LD|BPF_B|BPF_IND: - k = X + pc->k; - goto load_byte; - - case BPF_LDX|BPF_MSH|BPF_B: - k = pc->k; - if (k < hlen) - data = header; - else if (k < buflen) { - data = p; - k -= hlen; - } else - return 0; - - X = (data[k] & 0xf) << 2; - continue; - - case BPF_LD|BPF_IMM: - A = pc->k; - continue; - - case BPF_LDX|BPF_IMM: - X = pc->k; - continue; - - case BPF_LD|BPF_MEM: - A = mem[pc->k]; - continue; - - case BPF_LDX|BPF_MEM: - X = mem[pc->k]; - continue; - - case BPF_ST: - mem[pc->k] = A; - continue; - - case BPF_STX: - mem[pc->k] = X; - continue; - - case BPF_JMP|BPF_JA: - pc += pc->k; - continue; - - case BPF_JMP|BPF_JGT|BPF_K: - pc += (A > pc->k) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JGE|BPF_K: - pc += (A >= pc->k) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JEQ|BPF_K: - pc += (A == pc->k) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JSET|BPF_K: - pc += (A & pc->k) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JGT|BPF_X: - pc += (A > X) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JGE|BPF_X: - pc += (A >= X) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JEQ|BPF_X: - pc += (A == X) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JSET|BPF_X: - pc += (A & X) ? pc->jt : pc->jf; - continue; - - case BPF_ALU|BPF_ADD|BPF_X: - A += X; - continue; - - case BPF_ALU|BPF_SUB|BPF_X: - A -= X; - continue; - - case BPF_ALU|BPF_MUL|BPF_X: - A *= X; - continue; - - case BPF_ALU|BPF_DIV|BPF_X: - if (X == 0) - return 0; - A /= X; - continue; - - case BPF_ALU|BPF_AND|BPF_X: - A &= X; - continue; - - case BPF_ALU|BPF_OR|BPF_X: - A |= X; - continue; - - case BPF_ALU|BPF_LSH|BPF_X: - A <<= X; - continue; - - case BPF_ALU|BPF_RSH|BPF_X: - A >>= X; - continue; - - case BPF_ALU|BPF_ADD|BPF_K: - A += pc->k; - continue; - - case BPF_ALU|BPF_SUB|BPF_K: - A -= pc->k; - continue; - - case BPF_ALU|BPF_MUL|BPF_K: - A *= pc->k; - continue; - - case BPF_ALU|BPF_DIV|BPF_K: - A /= pc->k; - continue; - - case BPF_ALU|BPF_AND|BPF_K: - A &= pc->k; - continue; - - case BPF_ALU|BPF_OR|BPF_K: - A |= pc->k; - continue; - - case BPF_ALU|BPF_LSH|BPF_K: - A <<= pc->k; - continue; - - case BPF_ALU|BPF_RSH|BPF_K: - A >>= pc->k; - continue; - - case BPF_ALU|BPF_NEG: - A = -A; - continue; - - case BPF_MISC|BPF_TAX: - X = A; - continue; - - case BPF_MISC|BPF_TXA: - A = X; - continue; - } - } - - return 0; -} - -/* - * Return 1 if the 'f' is a valid filter program without a MATCH - * instruction. Return 2 if it is a valid filter program with a MATCH - * instruction. Otherwise, return 0. - * The constraints are that each jump be forward and to a valid - * code. The code must terminate with either an accept or reject. - * 'valid' is an array for use by the routine (it must be at least - * 'len' bytes long). - * - * The kernel needs to be able to verify an application's filter code. - * Otherwise, a bogus program could easily crash the system. - */ -int -mach_bpf_validate(bpf_insn_t f, int bytes, bpf_insn_t *match) -{ - register int i, j, len; - register bpf_insn_t p; - - len = BPF_BYTES2LEN(bytes); - - /* - * f[0].code is already checked to be (NETF_BPF | flags). - * So skip f[0]. - */ - - for (i = 1; i < len; ++i) { - /* - * Check that that jumps are forward, and within - * the code block. - */ - p = &f[i]; - if (BPF_CLASS(p->code) == BPF_JMP) { - register int from = i + 1; - - if (BPF_OP(p->code) == BPF_JA) { - if (from + p->k >= len) - return 0; - } - else if (from + p->jt >= len || from + p->jf >= len) - return 0; - } - /* - * Check that memory operations use valid addresses. - */ - if ((BPF_CLASS(p->code) == BPF_ST || - (BPF_CLASS(p->code) == BPF_LD && - (p->code & 0xe0) == BPF_MEM)) && - (p->k >= BPF_MEMWORDS || p->k < 0)) { - return 0; - } - /* - * Check for constant division by 0. - */ - if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) { - return 0; - } - /* - * Check for match instruction. - * Only one match instruction per filter is allowed. - */ - if (p->code == (BPF_RET|BPF_MATCH_IMM)) { - if (*match != 0 || - p->jt == 0 || - p->jt > N_NET_HASH_KEYS) - return 0; - i += p->jt; /* skip keys */ - if (i + 1 > len) - return 0; - - for (j = 1; j <= p->jt; j++) { - if (p[j].code != (BPF_MISC|BPF_KEY)) - return 0; - } - - *match = p; - } - } - if (BPF_CLASS(f[len - 1].code) == BPF_RET) - return ((*match == 0) ? 1 : 2); - else - return 0; -} - -int -mach_bpf_eq (bpf_insn_t f1, bpf_insn_t f2, int bytes) -{ - register int count; - - count = BPF_BYTES2LEN(bytes); - for (; count--; f1++, f2++) { - if (!BPF_INSN_EQ(f1, f2)) { - if ( f1->code == (BPF_MISC|BPF_KEY) && - f2->code == (BPF_MISC|BPF_KEY) ) - continue; - return FALSE; - } - }; - return TRUE; -} - -unsigned int -mach_bpf_hash (int n, unsigned int *keys) -{ - register unsigned int hval = 0; - - while (n--) { - hval += *keys++; - } - return (hval % NET_HASH_SIZE); -} - - -int -mach_bpf_match (net_hash_header_t hash, int n_keys, unsigned int *keys, - net_hash_entry_t **hash_headpp, net_hash_entry_t *entpp) -{ - register net_hash_entry_t head, entp; - register int i; - - if (n_keys != hash->n_keys) - return FALSE; - - *hash_headpp = &hash->table[mach_bpf_hash(n_keys, keys)]; - head = **hash_headpp; - - if (head == 0) - return FALSE; - - HASH_ITERATE (head, entp) - { - for (i = 0; i < n_keys; i++) { - if (keys[i] != entp->keys[i]) - break; - } - if (i == n_keys) { - *entpp = entp; - return TRUE; - } - } - HASH_ITERATE_END (head, entp) - return FALSE; -} - -/* - * Removes a hash entry (ENTP) from its queue (HEAD). - * If the reference count of filter (HP) becomes zero and not USED, - * HP is removed from the corresponding port lists and is freed. - */ - -int -hash_ent_remove (net_hash_header_t hp, int used, - net_hash_entry_t *head, net_hash_entry_t entp, queue_entry_t *dead_p) -{ - hp->ref_count--; - - if (*head == entp) { - if (queue_empty((queue_t) entp)) { - *head = 0; - ENQUEUE_DEAD(*dead_p, entp, chain); - if (hp->ref_count == 0 && !used) { - if (((net_rcv_port_t)hp)->filter[0] & NETF_IN) - queue_remove(&rcv_port_list, - (net_rcv_port_t)hp, - net_rcv_port_t, chain); - if (((net_rcv_port_t)hp)->filter[0] & NETF_OUT) - queue_remove(&snd_port_list, - (net_rcv_port_t)hp, - net_rcv_port_t, chain); - hp->n_keys = 0; - return TRUE; - } - return FALSE; - } else { - *head = (net_hash_entry_t)queue_next((queue_t) entp); - } - } - - remqueue((queue_t)*head, (queue_entry_t)entp); - ENQUEUE_DEAD(*dead_p, entp, chain); - return FALSE; -} - -/* - * net_free_dead_infp (dead_infp) - * queue_entry_t dead_infp; list of dead net_rcv_port_t. - * - * Deallocates dead net_rcv_port_t. - * No locks should be held when called. - */ -void -net_free_dead_infp (queue_entry_t dead_infp) -{ - register net_rcv_port_t infp, nextfp; - - for (infp = (net_rcv_port_t) dead_infp; infp != 0; infp = nextfp) { - nextfp = (net_rcv_port_t) queue_next(&infp->chain); - mach_port_deallocate(mach_task_self(), infp->rcv_port); - free(infp); - debug ("a dead infp is freed\n"); - } -} - -/* - * net_free_dead_entp (dead_entp) - * queue_entry_t dead_entp; list of dead net_hash_entry_t. - * - * Deallocates dead net_hash_entry_t. - * No locks should be held when called. - */ -void -net_free_dead_entp (queue_entry_t dead_entp) -{ - register net_hash_entry_t entp, nextentp; - - for (entp = (net_hash_entry_t)dead_entp; entp != 0; entp = nextentp) { - nextentp = (net_hash_entry_t) queue_next(&entp->chain); - - mach_port_deallocate(mach_task_self(), entp->rcv_port); - free(entp); - debug ("a dead entp is freed\n"); - } -} - -/* - * Set a filter for a network interface. - * - * We are given a naked send right for the rcv_port. - * If we are successful, we must consume that right. - */ -error_t -net_set_filter (mach_port_t rcv_port, int priority, - filter_t *filter, unsigned int filter_count) -{ - int filter_bytes; - bpf_insn_t match; - register net_rcv_port_t infp, my_infp; - net_rcv_port_t nextfp; - net_hash_header_t hhp; - register net_hash_entry_t entp, hash_entp=NULL; - net_hash_entry_t *head, nextentp; - queue_entry_t dead_infp, dead_entp; - int i; - int ret, is_new_infp; - io_return_t rval; - boolean_t in, out; - - /* Check the filter syntax. */ - - debug ("filter_count: %d, filter[0]: %d\n", filter_count, filter[0]); - - filter_bytes = CSPF_BYTES (filter_count); - match = (bpf_insn_t) 0; - - if (filter_count == 0) { - return (D_INVALID_OPERATION); - } else if (!((filter[0] & NETF_IN) || (filter[0] & NETF_OUT))) { - return (D_INVALID_OPERATION); /* NETF_IN or NETF_OUT required */ - } else if ((filter[0] & NETF_TYPE_MASK) == NETF_BPF) { - ret = mach_bpf_validate((bpf_insn_t)filter, filter_bytes, &match); - if (!ret) - return (D_INVALID_OPERATION); - } else { - return (D_INVALID_OPERATION); - } - debug ("net_set_filter: check over\n"); - - rval = D_SUCCESS; /* default return value */ - dead_infp = dead_entp = 0; - - if (match == (bpf_insn_t) 0) { - /* - * If there is no match instruction, we allocate - * a normal packet filter structure. - */ - my_infp = (net_rcv_port_t) calloc(1, sizeof(struct net_rcv_port)); - my_infp->rcv_port = rcv_port; - is_new_infp = TRUE; - } else { - /* - * If there is a match instruction, we assume there will be - * multiple sessions with a common substructure and allocate - * a hash table to deal with them. - */ - my_infp = 0; - hash_entp = (net_hash_entry_t) calloc(1, sizeof(struct net_hash_entry)); - is_new_infp = FALSE; - } - - /* - * Look for an existing filter on the same reply port. - * Look for filters with dead ports (for GC). - * Look for a filter with the same code except KEY insns. - */ - void check_filter_list(queue_head_t *if_port_list) - { - FILTER_ITERATE(if_port_list, infp, nextfp, &infp->chain) { - if (infp->rcv_port == MACH_PORT_NULL) { - if (match != 0 - && infp->priority == priority - && my_infp == 0 - && (infp->filter_end - infp->filter) == filter_count - && mach_bpf_eq((bpf_insn_t)infp->filter, - (bpf_insn_t)filter, filter_bytes)) { - my_infp = infp; - } - - for (i = 0; i < NET_HASH_SIZE; i++) { - head = &((net_hash_header_t) infp)->table[i]; - if (*head == 0) - continue; - - /* - * Check each hash entry to make sure the - * destination port is still valid. Remove - * any invalid entries. - */ - entp = *head; - do { - nextentp = (net_hash_entry_t) entp->he_next; - - /* checked without - ip_lock(entp->rcv_port) */ - if (entp->rcv_port == rcv_port) { - ret = hash_ent_remove ((net_hash_header_t)infp, - (my_infp == infp), - head, - entp, - &dead_entp); - if (ret) - goto hash_loop_end; - } - - entp = nextentp; - /* While test checks head since hash_ent_remove - * might modify it. - */ - } while (*head != 0 && entp != *head); - } - -hash_loop_end: - ; - } else if (infp->rcv_port == rcv_port) { - /* Remove the old filter from lists */ - if (infp->filter[0] & NETF_IN) - queue_remove(&rcv_port_list, infp, - net_rcv_port_t, chain); - if (infp->filter[0] & NETF_OUT) - queue_remove(&snd_port_list, infp, - net_rcv_port_t, chain); - - ENQUEUE_DEAD(dead_infp, infp, chain); - } - } - FILTER_ITERATE_END - } - - in = (filter[0] & NETF_IN) != 0; - out = (filter[0] & NETF_OUT) != 0; - - if (in) - check_filter_list(&rcv_port_list); - if (out) - check_filter_list(&snd_port_list); - - if (my_infp == 0) { - /* Allocate a dummy infp */ - for (i = 0; i < N_NET_HASH; i++) { - if (filter_hash_header[i].n_keys == 0) - break; - } - if (i == N_NET_HASH) { - - mach_port_deallocate(mach_task_self() , rcv_port); - if (match != 0) - free(hash_entp); - - rval = D_NO_MEMORY; - goto clean_and_return; - } - - hhp = &filter_hash_header[i]; - hhp->n_keys = match->jt; - - hhp->ref_count = 0; - for (i = 0; i < NET_HASH_SIZE; i++) - hhp->table[i] = 0; - - my_infp = (net_rcv_port_t)hhp; - my_infp->rcv_port = MACH_PORT_NULL; /* indication of dummy */ - is_new_infp = TRUE; - } - - if (is_new_infp) { - my_infp->priority = priority; - my_infp->rcv_count = 0; - - /* Copy filter program. */ - memcpy (my_infp->filter, filter, filter_bytes); - my_infp->filter_end = - (filter_t *)((char *)my_infp->filter + filter_bytes); - - /* Insert my_infp according to priority */ - if (in) { - queue_iterate(&rcv_port_list, infp, net_rcv_port_t, chain) - if (priority > infp->priority) - break; - - queue_enter(&rcv_port_list, my_infp, net_rcv_port_t, chain); - } - - if (out) { - queue_iterate(&snd_port_list, infp, net_rcv_port_t, chain) - if (priority > infp->priority) - break; - - queue_enter(&snd_port_list, my_infp, net_rcv_port_t, chain); - } - } - - if (match != 0) { - /* Insert to hash list */ - net_hash_entry_t *p; - - hash_entp->rcv_port = rcv_port; - for (i = 0; i < match->jt; i++) /* match->jt is n_keys */ - hash_entp->keys[i] = match[i+1].k; - p = &((net_hash_header_t)my_infp)-> - table[mach_bpf_hash(match->jt, hash_entp->keys)]; - - /* Not checking for the same key values */ - if (*p == 0) { - queue_init ((queue_t) hash_entp); - *p = hash_entp; - } else { - enqueue_tail((queue_t)*p, (queue_entry_t)hash_entp); - } - - ((net_hash_header_t)my_infp)->ref_count++; - } - -clean_and_return: - /* No locks are held at this point. */ - - if (dead_infp != 0) - net_free_dead_infp(dead_infp); - if (dead_entp != 0) - net_free_dead_entp(dead_entp); - - return (rval); -} - -/* Remove the filter in if_port_list whose port for delivering is dead_port. */ -void -remove_dead_filter (queue_head_t *if_port_list, mach_port_t dead_port) -{ - net_rcv_port_t infp; - net_rcv_port_t nextfp; - net_hash_entry_t *head, nextentp; - queue_entry_t dead_infp, dead_entp; - net_hash_entry_t entp = NULL; - int i, ret; - - dead_infp = dead_entp = 0; - FILTER_ITERATE (if_port_list, infp, nextfp, &infp->chain) { - if (infp->rcv_port == MACH_PORT_NULL) { - for (i = 0; i < NET_HASH_SIZE; i++) { - head = &((net_hash_header_t) infp)->table[i]; - if (*head == 0) - continue; - - /* - * Check each hash entry to make sure the - * destination port is still valid. Remove - * any invalid entries. - */ - entp = *head; - do { - nextentp = (net_hash_entry_t) entp->he_next; - - /* checked without - ip_lock(entp->rcv_port) */ - if (entp->rcv_port == dead_port) { - ret = hash_ent_remove ((net_hash_header_t) infp, - 0, - head, - entp, - &dead_entp); - if (ret) - goto hash_loop_end; - } - - entp = nextentp; - /* While test checks head since hash_ent_remove - * might modify it. - */ - } while (*head != 0 && entp != *head); - } - -hash_loop_end: - ; - } else if (infp->rcv_port == dead_port) { - /* Remove the old filter from lists */ - if (infp->filter[0] & NETF_IN) - queue_remove(&rcv_port_list, infp, - net_rcv_port_t, chain); - if (infp->filter[0] & NETF_OUT) - queue_remove(&snd_port_list, infp, - net_rcv_port_t, chain); - - ENQUEUE_DEAD(dead_infp, infp, chain); - } - } - FILTER_ITERATE_END - - if (dead_infp != 0) - net_free_dead_infp(dead_infp); - if (dead_entp != 0) - net_free_dead_entp(dead_entp); -} - -/* Remove all filters whose port for delivering is dead_port. */ -void -remove_dead_filter_from_all (mach_port_t dead_port) -{ - remove_dead_filter (&snd_port_list, dead_port); - remove_dead_filter (&rcv_port_list, dead_port); -} - -void -bpf_init() -{ - queue_init (&rcv_port_list); - queue_init (&snd_port_list); -} diff --git a/eth-filter.multi-thread/bpf_impl.h b/eth-filter.multi-thread/bpf_impl.h deleted file mode 100644 index de61df12..00000000 --- a/eth-filter.multi-thread/bpf_impl.h +++ /dev/null @@ -1,158 +0,0 @@ - /* - * Mach Operating System - * Copyright (c) 1993-1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * Author: David B. Golub, Carnegie Mellon University - * Date: 3/98 - * - * Network IO. - * - * Packet filter code taken from vaxif/enet.c written - * CMU and Stanford. - */ - -/* the code copied from device/net_io.c in Mach */ - -#ifndef BPF_IMPL_H -#define BPF_IMPL_H - -#include <mach.h> -#include <hurd.h> -#include <device/bpf.h> - -#include "queue.h" - -typedef unsigned short filter_t; -typedef filter_t *filter_array_t; - -#define NET_MAX_FILTER 128 /* was 64, bpf programs are big */ - -#define NET_HASH_SIZE 256 -#define N_NET_HASH 4 -#define N_NET_HASH_KEYS 4 - -#ifndef BPF_ALIGN -#define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p)) -#define EXTRACT_LONG(p) (ntohl(*(u_long *)p)) -#else -#define EXTRACT_SHORT(p)\ - ((u_short)\ - ((u_short)*((u_char *)p+0)<<8|\ - (u_short)*((u_char *)p+1)<<0)) -#define EXTRACT_LONG(p)\ - ((u_long)*((u_char *)p+0)<<24|\ - (u_long)*((u_char *)p+1)<<16|\ - (u_long)*((u_char *)p+2)<<8|\ - (u_long)*((u_char *)p+3)<<0) -#endif - -#define HASH_ITERATE(head, elt) (elt) = (net_hash_entry_t) (head); do { -#define HASH_ITERATE_END(head, elt) \ - (elt) = (net_hash_entry_t) queue_next((queue_entry_t) (elt)); \ -} while ((elt) != (head)); - -#define FILTER_ITERATE(if_port_list, fp, nextfp, chain) \ - for ((fp) = (net_rcv_port_t) queue_first(if_port_list); \ - !queue_end(if_port_list, (queue_entry_t)(fp)); \ - (fp) = (nextfp)) { \ - (nextfp) = (net_rcv_port_t) queue_next(chain); -#define FILTER_ITERATE_END } - -/* entry_p must be net_rcv_port_t or net_hash_entry_t */ -#define ENQUEUE_DEAD(dead, entry_p, chain) { \ - queue_next(&(entry_p)->chain) = (queue_entry_t) (dead); \ - (dead) = (queue_entry_t)(entry_p); \ -} - -#define CSPF_BYTES(n) ((n) * sizeof (filter_t)) - -/* - * Receive port for net, with packet filter. - * This data structure by itself represents a packet - * filter for a single session. - */ -struct net_rcv_port { - queue_chain_t chain; - mach_port_t rcv_port; /* port to send packet to */ - int rcv_count; /* number of packets received */ - int priority; /* priority for filter */ - filter_t *filter_end; /* pointer to end of filter */ - filter_t filter[NET_MAX_FILTER]; - /* filter operations */ -}; -typedef struct net_rcv_port *net_rcv_port_t; - -/* - * A single hash entry. - */ -struct net_hash_entry { - queue_chain_t chain; /* list of entries with same hval */ -#define he_next chain.next -#define he_prev chain.prev - mach_port_t rcv_port; /* destination port */ - unsigned int keys[N_NET_HASH_KEYS]; -}; -typedef struct net_hash_entry *net_hash_entry_t; - -/* - * This structure represents a packet filter with multiple sessions. - * - * For example, all application level TCP sessions might be - * represented by one of these structures. It looks like a - * net_rcv_port struct so that both types can live on the - * same packet filter queues. - */ -struct net_hash_header { - struct net_rcv_port rcv; - int n_keys; /* zero if not used */ - int ref_count; /* reference count */ - net_hash_entry_t table[NET_HASH_SIZE]; -} filter_hash_header[N_NET_HASH]; - -typedef struct net_hash_header *net_hash_header_t; - -int mach_bpf_do_filter(net_rcv_port_t infp, char *p, unsigned int wirelen, - char *header, unsigned int hlen, net_hash_entry_t **hash_headpp, - net_hash_entry_t *entpp); -int mach_bpf_validate(bpf_insn_t f, int bytes, bpf_insn_t *match); -int mach_bpf_eq (bpf_insn_t f1, bpf_insn_t f2, int bytes); -unsigned int mach_bpf_hash (int n, unsigned int *keys); -int mach_bpf_match (net_hash_header_t hash, int n_keys, unsigned int *keys, - net_hash_entry_t **hash_headpp, net_hash_entry_t *entpp); - -error_t net_set_filter(mach_port_t rcv_port, int priority, - filter_t *filter, unsigned int filter_count); -int hash_ent_remove (net_hash_header_t hp, int used, net_hash_entry_t *head, - net_hash_entry_t entp, queue_entry_t *dead_p); -void net_free_dead_infp (queue_entry_t dead_infp); -void net_free_dead_entp (queue_entry_t dead_entp); -void remove_dead_filter (queue_head_t *if_port_list, mach_port_t dead_port); -void remove_dead_filter_from_all (mach_port_t dead_port); -void bpf_init(); - -extern queue_head_t rcv_port_list; /* input filter list */ -extern queue_head_t snd_port_list; /* output filter list */ - -#endif /* _DEVICE_BPF_H_ */ diff --git a/eth-filter.multi-thread/filter.c b/eth-filter.multi-thread/filter.c deleted file mode 100644 index 36fe2fa0..00000000 --- a/eth-filter.multi-thread/filter.c +++ /dev/null @@ -1,878 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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. */ - -/* - * This program is a filter translator which sits on the top of the network - * interface. - * It provides two filters: for outgoing packets and for incoming packets. - * Only one pfinet server are allowed to run on the top of the translator. - */ - -#include <argp.h> -#include <errno.h> -#include <error.h> -#include <stddef.h> -#include <unistd.h> - -#include <hurd.h> -#include <mach.h> -#include <cthreads.h> -#include <device/device.h> -#include <hurd/trivfs.h> -#include <hurd/ports.h> -#include <hurd/ihash.h> - -#include "ourdevice_S.h" -#include "notify_S.h" -#include "device_reply_U.h" -#include "bpf_impl.h" -#include "util.h" -#include "filter.h" -#include "msg_queue.h" - -#ifdef DEBUG - -FILE *logfile; - -#endif - -static struct hurd_ihash proxy_deliverport_ht -= HURD_IHASH_INITIALIZER (offsetof (struct proxy, p_deliverport_hashloc)); - -/* The name of the network interface that the filter translator sits on. */ -static char *device_file; -const char *argp_program_version = "eth-filter 0.1"; -const char *argp_program_bug_address = "<bug-hurd@gnu.org>"; -static const char doc[] = "Hurd filter translator."; -static const struct argp_option options[] = -{ - {"interface", 'i', "DEVICE", 0, - "Network interface to use", 2}, - {"send-filter", 's', "string", 0, - "The filter rule which applies to the outgoing packet", 4}, - {"receive-filter", 'r', "string", 0, - "The filter rule which applies to the ingoing packet", 5}, - {"send-ip-range", 'S', "IP range", 0, - "A range of IP to create the send filter", 6}, - {"receive-ip-range", 'R', "IP range", 0, - "A range of IP to create the receive filter", 7}, - {0} -}; - -/* A filter allows every packet to be sent and be received. */ -static struct bpf_insn default_snd_filter[] = -{ - {NETF_OUT|NETF_BPF, 0, 0, 0}, - {6, 0, 0, 1500} -}; -static struct bpf_insn default_rcv_filter[] = -{ - {NETF_IN|NETF_BPF, 0, 0, 0}, - {6, 0, 0, 1500} -}; -static struct bpf_insn *snd_filter = NULL; -static int snd_filter_length; -static struct bpf_insn *rcv_filter = NULL; -static int rcv_filter_length; - -static cthread_t send_thread; -static int send_thread_running = 1; - -/* Port bucket we service requests on. */ -struct port_bucket *port_bucket; - -struct port_class *user_portclass; -struct port_class *device_portclass; -struct port_class *other_portclass; - -/* Trivfs hooks. */ -int trivfs_fstype = FSTYPE_MISC; -int trivfs_fsid = 0; -int trivfs_support_read = 0; -int trivfs_support_write = 0; -int trivfs_support_exec = 0; -int trivfs_allow_open = 0; - -struct port_class *trivfs_protid_portclasses[1]; -struct port_class *trivfs_cntl_portclasses[1]; -int trivfs_protid_nportclasses = 1; -int trivfs_cntl_nportclasses = 1; - -/* For getting the notification of ports from the kernel. */ -struct port_info *notify_pi; - -/* Write the data from the client to the device. */ -int -filter_device_write (struct filter_msg *msg) -{ - error_t err = 0; - int ret_count = 0; - int has_filter = 0; - net_hash_entry_t entp, *hash_headp; - net_rcv_port_t infp, nextfp; - int bytes_written; - struct filter_write_msg *write_msg = (struct filter_write_msg *) msg; - - /* The packet can be sent as long as it passes one filter, - * even thought there is usually only one filter in the list. */ - FILTER_ITERATE (&snd_port_list, infp, nextfp, &infp->chain) - { - has_filter = 1; - ret_count = mach_bpf_do_filter (infp, - write_msg->data + sizeof (struct ethhdr), - write_msg->datalen - sizeof (struct ethhdr), - write_msg->data, sizeof (struct ethhdr), - &hash_headp, &entp); - if (ret_count) - break; - } - FILTER_ITERATE_END - - if (ret_count || !has_filter) - err = device_write (msg->proxy->device_port, write_msg->mode, - write_msg->recnum, write_msg->data, - write_msg->datalen, &bytes_written); - ds_device_write_reply (write_msg->reply_port, write_msg->reply_type, - err, bytes_written); - return 0; -} - -/* Deliver the data from the device to the client. */ -int -filter_deliver (struct filter_msg *msg) -{ - deliver_msg (((struct filter_deliver_msg *)msg)->net_msg, - &rcv_port_list, msg->proxy->deliver_port); - return 0; -} - -error_t -create_proxy_user (struct proxy *proxy, mach_port_t *port) -{ - error_t err; - struct proxy_user *user; - - err = ports_create_port (user_portclass, port_bucket, sizeof (*user), &user); - if (err) - return err; - user->proxy = proxy; - - *port = ports_get_right (user); - ports_port_deref (user); - return 0; -} - -error_t -create_proxy_device (struct proxy *proxy, mach_port_t *port) -{ - error_t err; - struct proxy_device *device; - - err = ports_create_port (device_portclass, port_bucket, sizeof (*device), &device); - if (err) - return err; - device->proxy = proxy; - proxy->device = device; - - *port = ports_get_right (device); - ports_port_deref (device); - return 0; -} - -void -clean_proxy_user (void *p) -{ - struct proxy_user *user = p; - struct proxy *proxy = user->proxy; - - if (proxy->p_deliverport_hashloc) - hurd_ihash_locp_remove (&proxy_deliverport_ht, proxy->p_deliverport_hashloc); - - if (proxy->deliver_port != MACH_PORT_NULL) - mach_port_deallocate (mach_task_self (), proxy->deliver_port); - if (proxy->device_port != MACH_PORT_NULL) - mach_port_deallocate (mach_task_self (), proxy->device_port); - - if (proxy->device) - ports_destroy_right (proxy->device); - - free (proxy); -} - -void -clean_proxy_device (void *p) -{ - struct proxy_device *device = p; - if (device->proxy) - device->proxy->device = NULL; -} - -static int -filter_demuxer (mach_msg_header_t *inp, - mach_msg_header_t *outp) -{ - extern int device_server (mach_msg_header_t *, mach_msg_header_t *); - extern int notify_server (mach_msg_header_t *, mach_msg_header_t *); - extern int ethernet_demuxer (mach_msg_header_t *, mach_msg_header_t *); - return device_server (inp, outp) || notify_server (inp, outp) - || ethernet_demuxer (inp, outp) || trivfs_demuxer (inp, outp); -} - -int -ethernet_demuxer (mach_msg_header_t *inp, - mach_msg_header_t *outp) -{ - struct net_rcv_msg *msg = (struct net_rcv_msg *) inp; - struct proxy_device *device; - struct proxy *proxy; - - if (inp->msgh_id != NET_RCV_MSG_ID) - return 0; - - device = ports_lookup_port (port_bucket, inp->msgh_local_port, - device_portclass); - if (device == NULL) - return 0; - - proxy = device->proxy; - ports_port_deref (device); - - if (proxy && proxy->deliver_port != MACH_PORT_NULL) - queue_deliver (msg, proxy); -// deliver_msg (msg, &rcv_port_list, proxy->deliver_port); - - return 1; -} - -/* Implementation of notify interface */ -kern_return_t -do_mach_notify_port_deleted (mach_port_t notify, - mach_port_t name) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_msg_accepted (mach_port_t notify, - mach_port_t name) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_port_destroyed (mach_port_t notify, - mach_port_t port) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_no_senders (mach_port_t notify, - mach_port_mscount_t mscount) -{ - debug ("do_mach_notify_no_senders is called\n"); - return ports_do_mach_notify_no_senders (notify, mscount); -} - -kern_return_t -do_mach_notify_send_once (mach_port_t notify) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_dead_name (mach_port_t notify, - mach_port_t name) -{ - struct proxy *proxy; - - debug ("do_mach_notify_dead_name is called\n"); - mach_port_deallocate (mach_task_self (), name); - proxy = hurd_ihash_find (&proxy_deliverport_ht, name); - if (proxy) - { - proxy->deliver_port = MACH_PORT_NULL; - return 0; - } - return EINVAL; -} - -/* Implementation of device interface */ -kern_return_t -ds_xxx_device_set_status (device_t device, dev_flavor_t flavor, - dev_status_t status, size_t statu_cnt) -{ - return D_INVALID_OPERATION; -} - -kern_return_t -ds_xxx_device_get_status (device_t device, dev_flavor_t flavor, - dev_status_t status, size_t *statuscnt) -{ - return D_INVALID_OPERATION; -} - -kern_return_t -ds_xxx_device_set_filter (device_t device, mach_port_t rec, - int pri, filter_array_t filt, size_t len) -{ - return D_INVALID_OPERATION; -} - -kern_return_t -ds_device_open (mach_port_t master_port, mach_port_t reply_port, - mach_msg_type_name_t reply_portPoly, - dev_mode_t mode, dev_name_t name, mach_port_t *device, - mach_msg_type_name_t *devicetype) -{ - kern_return_t err; - mach_port_t master_device; - mach_port_t user_port; - struct proxy *proxy; - - if (device_file == NULL) - return D_NO_SUCH_DEVICE; - - master_device = file_name_lookup (device_file, 0, 0); - if (master_device == MACH_PORT_NULL) - return errno; - - proxy = (struct proxy *)calloc (1, sizeof (*proxy)); - if (proxy == NULL) - { - mach_port_deallocate (mach_task_self (), master_device); - return D_NO_MEMORY; - } - - err = device_open (master_device, mode, name, &proxy->device_port); - mach_port_deallocate (mach_task_self (), master_device); - if (err != KERN_SUCCESS) - { - free (proxy); - return err; - } - - err = create_proxy_user (proxy, &user_port); - if (err) - { - mach_port_deallocate (mach_task_self (), master_device); - free (proxy); - return err; - } - - *device = user_port; - *devicetype = MACH_MSG_TYPE_MAKE_SEND; - - return 0; -} - -kern_return_t -ds_device_close (device_t device) -{ - return 0; -} - -kern_return_t -ds_device_write (device_t device, mach_port_t reply_port, - mach_msg_type_name_t reply_type, dev_mode_t mode, - recnum_t recnum, io_buf_ptr_t data, size_t datalen, - int *bytes_written) -{ - kern_return_t err = 0; - struct proxy_user *user; - struct proxy *proxy; - int ret_count = 0; - int has_filter = 0; - net_hash_entry_t entp, *hash_headp; - net_rcv_port_t infp, nextfp; - - user = ports_lookup_port (port_bucket, device, user_portclass); - if (user == NULL) - return D_INVALID_OPERATION; - proxy = user->proxy; - - /* The packet can be sent as long as it passes one filter, - * even thought there is usually only one filter in the list. */ - FILTER_ITERATE (&snd_port_list, infp, nextfp, &infp->chain) - { - has_filter = 1; - ret_count = mach_bpf_do_filter (infp, - data + sizeof (struct ethhdr), - datalen - sizeof (struct ethhdr), - data, sizeof (struct ethhdr), - &hash_headp, &entp); - if (ret_count) - break; - } - FILTER_ITERATE_END - - if (ret_count || !has_filter) - err = device_write (proxy->device_port, mode, recnum, data, - datalen, bytes_written); - ports_port_deref (user); - return err; -} - -kern_return_t -ds_device_write_inband (device_t device, mach_port_t reply_port, - mach_msg_type_name_t reply_type, dev_mode_t mode, - recnum_t recnum, io_buf_ptr_inband_t data, - size_t datalen, int *bytes_written) -{ - kern_return_t ret; - struct proxy_user *user; - struct proxy *proxy; - - user = ports_lookup_port (port_bucket, device, user_portclass); - if (user == NULL) - return D_INVALID_OPERATION; - proxy = user->proxy; - ports_port_deref (user); - - ret = device_write_inband (proxy->device_port, mode, recnum, data, - datalen, bytes_written); - return ret; -} - -kern_return_t -ds_device_read (device_t device, mach_port_t reply_port, - mach_msg_type_name_t reply_type, dev_mode_t mode, - recnum_t recnum, int bytes_wanted, - io_buf_ptr_t *data, size_t *datalen) -{ - kern_return_t ret; - struct proxy_user *user; - struct proxy *proxy; - - user = ports_lookup_port (port_bucket, device, user_portclass); - if (user == NULL) - return D_INVALID_OPERATION; - proxy = user->proxy; - ports_port_deref (user); - - ret = device_read (proxy->device_port, mode, recnum, - bytes_wanted, data, datalen); - return ret; -} - -kern_return_t -ds_device_read_inband (device_t device, mach_port_t reply_port, - mach_msg_type_name_t reply_type, dev_mode_t mode, - recnum_t recnum, int bytes_wanted, - io_buf_ptr_inband_t data, size_t *datalen) -{ - kern_return_t ret; - struct proxy_user *user; - struct proxy *proxy; - - user = ports_lookup_port (port_bucket, device, user_portclass); - if (user == NULL) - return D_INVALID_OPERATION; - proxy = user->proxy; - ports_port_deref (user); - - ret = device_read_inband (proxy->device_port, mode, recnum, - bytes_wanted, data, datalen); - return ret; -} - -kern_return_t -ds_device_map (device_t device, vm_prot_t prot, vm_offset_t offset, - vm_size_t size, memory_object_t *pager, int unmap) -{ - kern_return_t ret; - struct proxy_user *user; - struct proxy *proxy; - - user = ports_lookup_port (port_bucket, device, user_portclass); - if (user == NULL) - return D_INVALID_OPERATION; - proxy = user->proxy; - ports_port_deref (user); - - ret = device_map (proxy->device_port, prot, offset, - size, pager, unmap); - return ret; -} - -kern_return_t -ds_device_set_status (device_t device, dev_flavor_t flavor, - dev_status_t status, size_t statuslen) -{ - kern_return_t ret; - struct proxy_user *user; - struct proxy *proxy; - - user = ports_lookup_port (port_bucket, device, user_portclass); - if (user == NULL) - return D_INVALID_OPERATION; - proxy = user->proxy; - ports_port_deref (user); - - ret = device_set_status (proxy->device_port, flavor, - status, statuslen); - return ret; -} - -kern_return_t -ds_device_get_status (device_t device, dev_flavor_t flavor, - dev_status_t status, size_t *statuslen) -{ - kern_return_t ret; - struct proxy_user *user; - struct proxy *proxy; - - user = ports_lookup_port (port_bucket, device, user_portclass); - if (user == NULL) - return D_INVALID_OPERATION; - proxy = user->proxy; - ports_port_deref (user); - - ret = device_get_status (proxy->device_port, flavor, status, statuslen); - return ret; -} - -kern_return_t -ds_device_set_filter (device_t device, mach_port_t receive_port, - int priority, filter_array_t filter, size_t filterlen) -{ - mach_port_t tmp; - kern_return_t err; - mach_port_t device_receive_port; - struct proxy_user *user; - struct proxy *proxy; - - user = ports_lookup_port (port_bucket, device, user_portclass); - if (user == NULL) - return D_INVALID_OPERATION; - proxy = user->proxy; - ports_port_deref (user); - - if (proxy->device == NULL) - { - error_t err; - err = create_proxy_device (proxy, &device_receive_port); - if (err) - return err; - } - else - device_receive_port = ports_get_right (proxy->device); - - /* Set the filter from pfinet into the interface, - * but the packet will be delivered to the translator, - * so the translator has the chance to filter some packets. */ - err = device_set_filter (proxy->device_port, - device_receive_port, - MACH_MSG_TYPE_MAKE_SEND, priority, - filter, filterlen); - if (err) - return err; - - proxy->deliver_port = receive_port; - hurd_ihash_add (&proxy_deliverport_ht, receive_port, proxy); - - err = mach_port_request_notification (mach_task_self (), receive_port, - MACH_NOTIFY_DEAD_NAME, 0, - ports_get_right (notify_pi), - MACH_MSG_TYPE_MAKE_SEND_ONCE, &tmp); - if (tmp != MACH_PORT_NULL) - mach_port_deallocate (mach_task_self (), tmp); - - return err; -} - -void -trivfs_modify_stat (struct trivfs_protid *cred, io_statbuf_t *stat) -{ -} - -error_t -trivfs_goaway (struct trivfs_control *fsys, int flags) -{ - int count; - - /* Stop new requests. */ - ports_inhibit_class_rpcs (trivfs_cntl_portclasses[0]); - ports_inhibit_class_rpcs (trivfs_protid_portclasses[0]); - - count = ports_count_class (user_portclass); - debug ("the number of ports alive: %d\n", count); - - if (count && !(flags & FSYS_GOAWAY_FORCE)) - { - /* We won't go away, so start things going again... */ - ports_enable_class (trivfs_protid_portclasses[0]); - ports_resume_class_rpcs (trivfs_cntl_portclasses[0]); - ports_resume_class_rpcs (trivfs_protid_portclasses[0]); - return EBUSY; - } - - queue_flush (); - send_thread_running = 0; -// cthread_join (send_thread); - -#ifdef DEBUG - fclose (logfile); -#endif - debug ("the translator is gone away\n"); - exit (0); -} - -/* Convert the network address input by the user into - * a form that is accepted by libpcap. */ -int -correct_net_addr (char *orig, char *result, int result_len) -{ - char *ptr; - int netmask_len; - int remain_bits; - int remain_bytes; - char netmask; - char addr[4]; - char buf[INET_ADDRSTRLEN]; - int i; - - ptr = strstr (orig, "/"); - if (ptr == NULL) - { - strncpy (result, orig, result_len); - return 0; - } - - *ptr = 0; - ptr++; - netmask_len = atoi (ptr); - if (inet_pton (AF_INET, orig, addr) < 0) - { - perror ("inet_pton"); - return -1; - } - remain_bits = netmask_len % 8; - netmask = ~0; - netmask >>= 8 - remain_bits; - netmask <<= 8 - remain_bits; - remain_bytes = netmask_len / 8; - addr[remain_bytes] &= netmask; - for (i=remain_bytes+1 ; i < 4 ; i++) - addr[i] = 0; - - snprintf (result, result_len, "%s/%s", - inet_ntop (AF_INET, addr, buf, INET_ADDRSTRLEN), ptr); - return 0; -} - -static error_t -parse_opt (int opt, char *arg, struct argp_state *state) -{ - struct bpf_insn *trans_filter_program (char *str, int send, - int *filter_len); - char buf[1024]; - char addr[INET_ADDRSTRLEN+4]; - - switch (opt) - { - case 'i': - device_file = arg; - break; - case 's': - if (snd_filter) - free (snd_filter); - snd_filter = trans_filter_program (arg, 1, &snd_filter_length); - break; - case 'r': - if (rcv_filter) - free (rcv_filter); - rcv_filter = trans_filter_program (arg, 0, &rcv_filter_length); - break; - case 'S': - if (correct_net_addr (arg, addr, INET_ADDRSTRLEN+4) < 0) - return 0; - snprintf (buf, sizeof (buf), "arp or (ip and src net %s)", addr); - if (snd_filter) - free (snd_filter); - snd_filter = trans_filter_program (buf, 1, &snd_filter_length); - break; - case 'R': - if (correct_net_addr (arg, addr, INET_ADDRSTRLEN+4) < 0) - return 0; - snprintf (buf, sizeof (buf), "arp or (ip and dst net %s)", addr); - if (rcv_filter) - free (rcv_filter); - rcv_filter = trans_filter_program (buf, 0, &rcv_filter_length); - break; - case ARGP_KEY_ERROR: - case ARGP_KEY_SUCCESS: - case ARGP_KEY_INIT: - break; - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - -void *send_thread_func (void *arg) -{ - struct filter_msg *msg; - - while (send_thread_running) - { - msg = dequeue_msg (); - if (msg == NULL) - { -// queue_empty_wait (); - continue; - } - msg->forward (msg); - msg->destroy (msg); - free (msg); - } - return NULL; -} - -int -main (int argc, char *argv[]) -{ - error_t err; - mach_port_t bootstrap; - struct trivfs_control *fsys; - const struct argp argp = { options, parse_opt, 0, doc }; - -#ifdef DEBUG - logfile = fopen ("/root/filter.log", "a+"); - if (logfile == NULL) - error (1, errno, "fopen"); -#endif - - port_bucket = ports_create_bucket (); - user_portclass = ports_create_class (clean_proxy_user, 0); - device_portclass = ports_create_class (clean_proxy_device, 0); - other_portclass = ports_create_class (0, 0); - trivfs_cntl_portclasses[0] = ports_create_class (trivfs_clean_cntl, 0); - trivfs_protid_portclasses[0] = ports_create_class (trivfs_clean_protid, 0); - - argp_parse (&argp, argc, argv, 0, 0, 0); - - /* Prepare the filter. */ - if (snd_filter == NULL) - { - snd_filter = default_snd_filter; - snd_filter_length = sizeof (default_snd_filter) / sizeof (short); - } - if (rcv_filter == NULL) - { - rcv_filter = default_rcv_filter; - rcv_filter_length = sizeof (default_rcv_filter) / sizeof (short); - } - - task_get_bootstrap_port (mach_task_self (), &bootstrap); - if (bootstrap == MACH_PORT_NULL) - error (1, 0, "must be started as a translator"); - - err = ports_create_port (other_portclass, port_bucket, - sizeof (struct port_info), ¬ify_pi); - if (err) - error (1, err, "ports_create_port for notification"); - - /* Reply to our parent. */ - err = trivfs_startup (bootstrap, 0, - trivfs_cntl_portclasses[0], port_bucket, - trivfs_protid_portclasses[0], port_bucket, &fsys); - mach_port_deallocate (mach_task_self (), bootstrap); - if (err) - error (1, err, "Contacting parent"); - - /* Initialize the bpf, and set the filter for outgoing packets. - * MACH_PORT_DEAD is used because we don't need a receiving port. */ - bpf_init (); - err = net_set_filter (MACH_PORT_DEAD, 0, (filter_t *) snd_filter, - snd_filter_length); - if (err) - error (1, err, "set the sending filter"); - /* Set the filter translator's own rule. */ - err = net_set_filter (MACH_PORT_DEAD, 0, (filter_t *) rcv_filter, - rcv_filter_length); - if (err) - error (1, err, "set the receiving filter"); - - cthread_init (); - send_thread = cthread_fork (send_thread_func, NULL); - /* TODO if the main thread exits, - * does the created thread exit if cthread_detach is called */ - cthread_detach (send_thread); - - /* Launch. */ - do - { - ports_manage_port_operations_one_thread (port_bucket, - filter_demuxer, 0); - } while (trivfs_goaway (fsys, 0)); - return 0; -} - -int -deliver_msg (struct net_rcv_msg *msg, queue_head_t *port_list, - mach_port_t dest) -{ - static int count = 0; - mach_msg_return_t err; - net_rcv_port_t infp, nextfp; - - msg->msg_hdr.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0); - msg->msg_hdr.msgh_local_port = MACH_PORT_NULL; - msg->msg_hdr.msgh_kind = MACH_MSGH_KIND_NORMAL; - - /* Deliver the packet to the right pfinet, - * actually there should be only one filter in the list. */ - FILTER_ITERATE (port_list, infp, nextfp, &infp->chain) - { - net_hash_entry_t entp, *hash_headp; - int ret_count; - - entp = (net_hash_entry_t) 0; - ret_count = mach_bpf_do_filter (infp, - msg->packet + sizeof (struct packet_header), - msg->net_rcv_msg_packet_count, - msg->header, - sizeof (struct ethhdr), - &hash_headp, &entp); - - if (ret_count) - { - msg->msg_hdr.msgh_remote_port = dest; - debug ("before delivering the packet to port %d, count: %d\n", - dest, ++count); - err = mach_msg ((mach_msg_header_t *)msg, - MACH_SEND_MSG|MACH_SEND_TIMEOUT, - msg->msg_hdr.msgh_size, 0, MACH_PORT_NULL, - /*MACH_MSG_TIMEOUT_NONE*/500, MACH_PORT_NULL); - if (err != MACH_MSG_SUCCESS) - { - mach_port_deallocate(mach_task_self (), - ((mach_msg_header_t *)msg)->msgh_remote_port); - error (0, err, "mach_msg"); - return -1; - } - debug ("after delivering the packet\n"); - } - } - FILTER_ITERATE_END - - return 0; -} diff --git a/eth-filter.multi-thread/filter.h b/eth-filter.multi-thread/filter.h deleted file mode 100644 index e1c4c8bf..00000000 --- a/eth-filter.multi-thread/filter.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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 FILTER_H -#define FILTER_H - -#include <hurd.h> -#include <mach.h> -#include <hurd/ports.h> - -#include "bpf_impl.h" - -struct filter_msg; - -struct proxy_user -{ - struct port_info pi; - struct proxy *proxy; -}; - -struct proxy_device -{ - struct port_info pi; - struct proxy *proxy; -}; - -struct proxy -{ - struct proxy_device *device; - mach_port_t deliver_port; - hurd_ihash_locp_t p_deliverport_hashloc; - mach_port_t device_port; -}; - -int deliver_msg (struct net_rcv_msg *msg, queue_head_t *port_list, - mach_port_t dest); -int filter_device_write (struct filter_msg *msg); -int filter_deliver (struct filter_msg *msg); - -#endif diff --git a/eth-filter.multi-thread/msg_queue.c b/eth-filter.multi-thread/msg_queue.c deleted file mode 100644 index c9e62e02..00000000 --- a/eth-filter.multi-thread/msg_queue.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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 <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -#include "msg_queue.h" -#include "filter.h" -#include "util.h" - -static struct filter_msg *queue_head; -static struct filter_msg *queue_tail; -static int queue_len = 0; - -static struct mutex queuelock = MUTEX_INITIALIZER; -static struct mutex condition_mutex = MUTEX_INITIALIZER; -static struct condition condition_cond = CONDITION_INITIALIZER; - -void -queue_msg (struct filter_msg *msg) -{ - msg->next = NULL; - // TODO what kind of lock do I need? - mutex_lock (&queuelock); - if (queue_head == NULL) - { - assert (queue_tail == NULL); - assert (queue_len == 0); - /* When the queue is empty. */ - queue_head = msg; - queue_tail = msg; - } - else - { - queue_tail->next = msg; - queue_tail = msg; - } - queue_len++; - debug ("queue a message, queue length: %d.\n", queue_len); - mutex_unlock (&queuelock); -// queue_wakeup (); -} - -struct filter_msg * -dequeue_msg () -{ - struct filter_msg *msg; - - mutex_lock (&queuelock); - if (queue_head == NULL) - { - assert (queue_tail == NULL); - assert (queue_len == 0); - msg = NULL; - } - else - { - msg = queue_head; - queue_head = msg->next; - if (queue_head == NULL) - queue_tail = NULL; - queue_len--; - } - debug ("dequeue a message, the queue length: %d.\n", queue_len); - mutex_unlock (&queuelock); - - return msg; -} - -/* It can be called when the translator exits. */ -void -queue_flush () -{ - struct filter_msg *msg; - struct filter_msg *tmp; - - mutex_lock (&queuelock); - msg = queue_head; - queue_head = queue_tail = NULL; - queue_len = 0; - mutex_unlock (&queuelock); - - while (msg) - { - tmp = msg; - msg = msg->next; - if (tmp->destroy) - tmp->destroy (tmp); - free (tmp); - } -} - -void -filter_write_destroy (struct filter_msg *msg) -{ - struct filter_write_msg *write_msg = (struct filter_write_msg *) msg; - - free (write_msg->data); -} - -void filter_deliver_destroy (struct filter_msg *msg) -{ - struct filter_deliver_msg *deliver_msg = (struct filter_deliver_msg *) msg; - - free (deliver_msg->net_msg); -} - -kern_return_t -queue_write (char *data, size_t datalen, mach_port_t reply_port, - mach_msg_type_name_t reply_type, dev_mode_t mode, - recnum_t recnum, struct proxy *proxy) -{ - /* Make a copy of the data */ - char *new_data; - struct filter_msg *msg; - struct filter_write_msg *write_msg; - - if (queue_len >= MAX_QUEUE) - return D_NO_MEMORY; - - new_data = (char *) malloc (datalen); - if (new_data == NULL) - return D_NO_MEMORY; - - memcpy (new_data, data, datalen); - - write_msg = (struct filter_write_msg *) malloc (sizeof (*write_msg)); - if (write_msg == NULL) - { - free (new_data); - return D_NO_MEMORY; - } - msg = (struct filter_msg *) write_msg; - - msg->proxy = proxy; - msg->forward = filter_device_write; - msg->destroy = filter_write_destroy; - - write_msg->data = new_data; - write_msg->datalen = datalen; - write_msg->reply_port = reply_port; - write_msg->reply_type = reply_type; - write_msg->mode = mode; - write_msg->recnum = recnum; - - queue_msg (msg); - return D_SUCCESS; -} - -int -queue_deliver (struct net_rcv_msg *msg, struct proxy *proxy) -{ - struct net_rcv_msg *msg_copy; - struct filter_deliver_msg *deliver_msg; - - if (queue_len >= MAX_QUEUE) - return D_NO_MEMORY; - - /* Make a copy of the data */ - msg_copy = (struct net_rcv_msg *) malloc (sizeof (*msg_copy)); - if (msg_copy == NULL) - return D_NO_MEMORY; - - deliver_msg = (struct filter_deliver_msg *) malloc (sizeof (*deliver_msg)); - if (deliver_msg == NULL) - { - free (msg_copy); - return D_NO_MEMORY; - } - - *msg_copy = *msg; - - deliver_msg->msg.proxy = proxy; - deliver_msg->msg.forward = filter_deliver; - deliver_msg->msg.destroy = filter_deliver_destroy; - - deliver_msg->net_msg = msg_copy; - - queue_msg ((struct filter_msg *)deliver_msg); - return D_SUCCESS; -} - -void -queue_empty_wait () -{ - mutex_lock (&condition_mutex); -// debug ("queue length is %d\n", queue_len); - while (queue_head == NULL) - { - debug ("thread waits for a signal.\n"); - condition_wait (&condition_cond, &condition_mutex); - } - mutex_unlock (&condition_mutex); -} - -void -queue_wakeup () -{ - if (queue_head) - { - debug ("wake up a thread.\n"); - condition_signal (&condition_cond); - } -} - diff --git a/eth-filter.multi-thread/msg_queue.h b/eth-filter.multi-thread/msg_queue.h deleted file mode 100644 index bc7800fb..00000000 --- a/eth-filter.multi-thread/msg_queue.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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 MSG_QUEUE_H -#define MSG_QUEUE_H - -#include <hurd.h> -#include <mach.h> - -#define MAX_QUEUE 1000 - -struct proxy; - -struct filter_msg -{ - struct proxy *proxy; - struct filter_msg *next; - - int (*forward) (struct filter_msg *); - void (*destroy) (struct filter_msg *); -}; - -struct filter_write_msg -{ - struct filter_msg msg; - - char *data; - size_t datalen; - dev_mode_t mode; - recnum_t recnum; - mach_port_t reply_port; - mach_msg_type_name_t reply_type; -}; - -struct filter_deliver_msg -{ - struct filter_msg msg; - - struct net_rcv_msg *net_msg; -}; - -void queue_msg (struct filter_msg *msg); -struct filter_msg * dequeue_msg (); -void queue_flush (); -kern_return_t queue_write (char *data, size_t datalen, mach_port_t reply_port, - mach_msg_type_name_t reply_type, dev_mode_t mode, - recnum_t recnum, struct proxy *proxy); -int queue_deliver (struct net_rcv_msg *msg, struct proxy *proxy); -void queue_wakeup (); -void queue_empty_wait (); - -#endif diff --git a/eth-filter.multi-thread/pcap_filter.c b/eth-filter.multi-thread/pcap_filter.c deleted file mode 100644 index 67ee9bb8..00000000 --- a/eth-filter.multi-thread/pcap_filter.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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. */ - -/* - * This file translates a string into a bpf program. - * The BPF structures are defined in both of bpf.h and pcap-bpf.h - * Hopefully, there is no conflict between them. - * This file uses the BPF definition in pcap-bpf.h. - */ - -#include <pcap.h> -#include <stdlib.h> -#include <string.h> - -#include "util.h" - -#define NETF_IN 0x1 -#define NETF_OUT 0x2 -#define NETF_NBPA 10 -#define NETF_BPF (1 << NETF_NBPA) - -/* This function translates the bpf program - * from the string into the instructions. */ -struct bpf_insn *trans_filter_program (char *str, int send, int *filter_len) -{ - struct bpf_program program; - struct bpf_insn *insn; - pcap_t *pcap; - int err; - - debug ("Compiling the bpf program: %s.\n", str); - pcap = pcap_open_dead (DLT_EN10MB, 1500); - if (pcap == NULL) - return NULL; - err = pcap_compile (pcap, &program, str, 1, 0); - if (err < 0) - { - debug ("pcap_compile: %s\n", pcap_geterr (pcap)); - pcap_close (pcap); - return NULL; - } - - debug ("Finish compiling the bpf program, get %d bpf instructions.\n", - program.bf_len); - insn = (struct bpf_insn *) malloc ((program.bf_len + 1) * sizeof (*insn)); - /* Clear the first instruction. */ - memset (insn, 0, sizeof (*insn)); - if (send) - insn->code = NETF_OUT | NETF_BPF; - else - insn->code = NETF_IN | NETF_BPF; - memcpy (insn + 1, program.bf_insns, program.bf_len * sizeof (*insn)); - *filter_len = ((program.bf_len + 1) * sizeof (*insn)) / sizeof (short); - debug ("%d bpf instructions, the length of filters is %d words\n", - program.bf_len, *filter_len); - pcap_freecode (&program); - pcap_close (pcap); - - return insn; -} diff --git a/eth-filter.multi-thread/queue.c b/eth-filter.multi-thread/queue.c deleted file mode 100644 index a43a21b0..00000000 --- a/eth-filter.multi-thread/queue.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * Routines to implement queue package. - */ - -#include "queue.h" - - - -/* - * Insert element at head of queue. - */ -void enqueue_head( - register queue_t que, - register queue_entry_t elt) -{ - elt->next = que->next; - elt->prev = que; - elt->next->prev = elt; - que->next = elt; -} - -/* - * Insert element at tail of queue. - */ -void enqueue_tail( - register queue_t que, - register queue_entry_t elt) -{ - elt->next = que; - elt->prev = que->prev; - elt->prev->next = elt; - que->prev = elt; -} - -/* - * Remove and return element at head of queue. - */ -queue_entry_t dequeue_head( - register queue_t que) -{ - register queue_entry_t elt; - - if (que->next == que) - return((queue_entry_t)0); - - elt = que->next; - elt->next->prev = que; - que->next = elt->next; - return(elt); -} - -/* - * Remove and return element at tail of queue. - */ -queue_entry_t dequeue_tail( - register queue_t que) -{ - register queue_entry_t elt; - - if (que->prev == que) - return((queue_entry_t)0); - - elt = que->prev; - elt->prev->next = que; - que->prev = elt->prev; - return(elt); -} - -/* - * Remove arbitrary element from queue. - * Does not check whether element is on queue - the world - * will go haywire if it isn't. - */ - -/*ARGSUSED*/ -void remqueue( - queue_t que, - register queue_entry_t elt) -{ - elt->next->prev = elt->prev; - elt->prev->next = elt->next; -} - -/* - * Routines to directly imitate the VAX hardware queue - * package. - */ -void insque( - register struct queue_entry *entry, - register struct queue_entry *pred) -{ - entry->next = pred->next; - entry->prev = pred; - (pred->next)->prev = entry; - pred->next = entry; -} - -struct queue_entry -*remque( - register struct queue_entry *elt) -{ - (elt->next)->prev = elt->prev; - (elt->prev)->next = elt->next; - return(elt); -} - diff --git a/eth-filter.multi-thread/queue.h b/eth-filter.multi-thread/queue.h deleted file mode 100644 index f067f557..00000000 --- a/eth-filter.multi-thread/queue.h +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon rights - * to redistribute these changes. - */ -/* - * File: queue.h - * Author: Avadis Tevanian, Jr. - * Date: 1985 - * - * Type definitions for generic queues. - * - */ - -#ifndef _KERN_QUEUE_H_ -#define _KERN_QUEUE_H_ - -/* - * Queue of abstract objects. Queue is maintained - * within that object. - * - * Supports fast removal from within the queue. - * - * How to declare a queue of elements of type "foo_t": - * In the "*foo_t" type, you must have a field of - * type "queue_chain_t" to hold together this queue. - * There may be more than one chain through a - * "foo_t", for use by different queues. - * - * Declare the queue as a "queue_t" type. - * - * Elements of the queue (of type "foo_t", that is) - * are referred to by reference, and cast to type - * "queue_entry_t" within this module. - */ - -/* - * A generic doubly-linked list (queue). - */ - -struct queue_entry { - struct queue_entry *next; /* next element */ - struct queue_entry *prev; /* previous element */ -}; - -typedef struct queue_entry *queue_t; -typedef struct queue_entry queue_head_t; -typedef struct queue_entry queue_chain_t; -typedef struct queue_entry *queue_entry_t; - -/* - * enqueue puts "elt" on the "queue". - * dequeue returns the first element in the "queue". - * remqueue removes the specified "elt" from the specified "queue". - */ - -#define enqueue(queue,elt) enqueue_tail(queue, elt) -#define dequeue(queue) dequeue_head(queue) - -void enqueue_head(queue_t, queue_entry_t); -void enqueue_tail(queue_t, queue_entry_t); -queue_entry_t dequeue_head(queue_t); -queue_entry_t dequeue_tail(queue_t); -void remqueue(queue_t, queue_entry_t); - -/* - * Macro: queue_init - * Function: - * Initialize the given queue. - * Header: - * void queue_init(q) - * queue_t q; *MODIFIED* - */ -#define queue_init(q) ((q)->next = (q)->prev = q) - -/* - * Macro: queue_first - * Function: - * Returns the first entry in the queue, - * Header: - * queue_entry_t queue_first(q) - * queue_t q; *IN* - */ -#define queue_first(q) ((q)->next) - -/* - * Macro: queue_next - * Function: - * Returns the entry after an item in the queue. - * Header: - * queue_entry_t queue_next(qc) - * queue_t qc; - */ -#define queue_next(qc) ((qc)->next) - -/* - * Macro: queue_last - * Function: - * Returns the last entry in the queue. - * Header: - * queue_entry_t queue_last(q) - * queue_t q; *IN* - */ -#define queue_last(q) ((q)->prev) - -/* - * Macro: queue_prev - * Function: - * Returns the entry before an item in the queue. - * Header: - * queue_entry_t queue_prev(qc) - * queue_t qc; - */ -#define queue_prev(qc) ((qc)->prev) - -/* - * Macro: queue_end - * Function: - * Tests whether a new entry is really the end of - * the queue. - * Header: - * boolean_t queue_end(q, qe) - * queue_t q; - * queue_entry_t qe; - */ -#define queue_end(q, qe) ((q) == (qe)) - -/* - * Macro: queue_empty - * Function: - * Tests whether a queue is empty. - * Header: - * boolean_t queue_empty(q) - * queue_t q; - */ -#define queue_empty(q) queue_end((q), queue_first(q)) - - -/*----------------------------------------------------------------*/ -/* - * Macros that operate on generic structures. The queue - * chain may be at any location within the structure, and there - * may be more than one chain. - */ - -/* - * Macro: queue_enter - * Function: - * Insert a new element at the tail of the queue. - * Header: - * void queue_enter(q, elt, type, field) - * queue_t q; - * <type> elt; - * <type> is what's in our queue - * <field> is the chain field in (*<type>) - */ -#define queue_enter(head, elt, type, field) \ -{ \ - register queue_entry_t prev; \ - \ - prev = (head)->prev; \ - if ((head) == prev) { \ - (head)->next = (queue_entry_t) (elt); \ - } \ - else { \ - ((type)prev)->field.next = (queue_entry_t)(elt);\ - } \ - (elt)->field.prev = prev; \ - (elt)->field.next = head; \ - (head)->prev = (queue_entry_t) elt; \ -} - -/* - * Macro: queue_enter_first - * Function: - * Insert a new element at the head of the queue. - * Header: - * void queue_enter_first(q, elt, type, field) - * queue_t q; - * <type> elt; - * <type> is what's in our queue - * <field> is the chain field in (*<type>) - */ -#define queue_enter_first(head, elt, type, field) \ -{ \ - register queue_entry_t next; \ - \ - next = (head)->next; \ - if ((head) == next) { \ - (head)->prev = (queue_entry_t) (elt); \ - } \ - else { \ - ((type)next)->field.prev = (queue_entry_t)(elt);\ - } \ - (elt)->field.next = next; \ - (elt)->field.prev = head; \ - (head)->next = (queue_entry_t) elt; \ -} - -/* - * Macro: queue_field [internal use only] - * Function: - * Find the queue_chain_t (or queue_t) for the - * given element (thing) in the given queue (head) - */ -#define queue_field(head, thing, type, field) \ - (((head) == (thing)) ? (head) : &((type)(thing))->field) - -/* - * Macro: queue_remove - * Function: - * Remove an arbitrary item from the queue. - * Header: - * void queue_remove(q, qe, type, field) - * arguments as in queue_enter - */ -#define queue_remove(head, elt, type, field) \ -{ \ - register queue_entry_t next, prev; \ - \ - next = (elt)->field.next; \ - prev = (elt)->field.prev; \ - \ - if ((head) == next) \ - (head)->prev = prev; \ - else \ - ((type)next)->field.prev = prev; \ - \ - if ((head) == prev) \ - (head)->next = next; \ - else \ - ((type)prev)->field.next = next; \ -} - -/* - * Macro: queue_remove_first - * Function: - * Remove and return the entry at the head of - * the queue. - * Header: - * queue_remove_first(head, entry, type, field) - * entry is returned by reference - */ -#define queue_remove_first(head, entry, type, field) \ -{ \ - register queue_entry_t next; \ - \ - (entry) = (type) ((head)->next); \ - next = (entry)->field.next; \ - \ - if ((head) == next) \ - (head)->prev = (head); \ - else \ - ((type)(next))->field.prev = (head); \ - (head)->next = next; \ -} - -/* - * Macro: queue_remove_last - * Function: - * Remove and return the entry at the tail of - * the queue. - * Header: - * queue_remove_last(head, entry, type, field) - * entry is returned by reference - */ -#define queue_remove_last(head, entry, type, field) \ -{ \ - register queue_entry_t prev; \ - \ - (entry) = (type) ((head)->prev); \ - prev = (entry)->field.prev; \ - \ - if ((head) == prev) \ - (head)->next = (head); \ - else \ - ((type)(prev))->field.next = (head); \ - (head)->prev = prev; \ -} - -/* - * Macro: queue_assign - */ -#define queue_assign(to, from, type, field) \ -{ \ - ((type)((from)->prev))->field.next = (to); \ - ((type)((from)->next))->field.prev = (to); \ - *to = *from; \ -} - -/* - * Macro: queue_iterate - * Function: - * iterate over each item in the queue. - * Generates a 'for' loop, setting elt to - * each item in turn (by reference). - * Header: - * queue_iterate(q, elt, type, field) - * queue_t q; - * <type> elt; - * <type> is what's in our queue - * <field> is the chain field in (*<type>) - */ -#define queue_iterate(head, elt, type, field) \ - for ((elt) = (type) queue_first(head); \ - !queue_end((head), (queue_entry_t)(elt)); \ - (elt) = (type) queue_next(&(elt)->field)) - -#endif /* _KERN_QUEUE_H_ */ diff --git a/eth-filter.multi-thread/util.h b/eth-filter.multi-thread/util.h deleted file mode 100644 index fa7189eb..00000000 --- a/eth-filter.multi-thread/util.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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 UTIL_H -#define UTIL_H - -#include <stdio.h> - -#include <linux/if_ether.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <netinet/ip.h> - -#define DEBUG - -#ifdef DEBUG - -#define debug(format, ...) do \ -{ \ - extern FILE *logfile; \ - char buf[1024]; \ - snprintf (buf, 1024, "filter: %s", format); \ - fprintf (stderr , buf, ## __VA_ARGS__); \ - fflush (logfile); \ -} while (0) - -#else - -#define debug(format, ...) do {} while (0) - -#endif - -static inline void -print_pack (char *packet, int len) -{ -#ifdef DEBUG - struct ethhdr *ethh = (struct ethhdr *) packet; - struct iphdr *iph = (struct iphdr *)(ethh + 1); - char src_str[INET_ADDRSTRLEN]; - char dst_str[INET_ADDRSTRLEN]; - if (ntohs (ethh->h_proto) == ETH_P_IP - && len >= sizeof (struct ethhdr) + sizeof (struct iphdr)) - { - debug ("pack: get a IP packet from %s to %s\n", - inet_ntop (AF_INET, &iph->saddr, src_str, INET_ADDRSTRLEN), - inet_ntop (AF_INET, &iph->daddr, dst_str, INET_ADDRSTRLEN)); - } - else - { - debug ("pack: get a non-IP packet: %x\n", ntohs (ethh->h_proto)); - } -#endif -} - -#endif diff --git a/eth-filter/ChangeLog b/eth-filter/ChangeLog deleted file mode 100644 index 1b3eb8ac..00000000 --- a/eth-filter/ChangeLog +++ /dev/null @@ -1,127 +0,0 @@ -2009-04-18 Zheng Da <zhengda1936@gmail.com> - - * filter.c (trivfs_allow_open): Change its value. - (ds_device_open): Change the mode for file_name_lookup(). - -2009-01-02 Zheng Da <zhengda1936@gmail.com> - - * filter.c (ds_device_write): Deallocate the out-of-line data. - -2008-10-03 Zheng Da <zhengda1936@gmail.com> - - * Makefile: Remove the include paths from pfinet. - - * util.h: Remove the line of including linux/if_ether.h - (ETH_ALEN): New macro. - (ethhdr): New structure. - -2008-09-26 Zheng Da <zhengda1936@gmail.com> - - * filter.c (ethernet_demuxer): Save and restore the message header. - (deliver_msg): Use the non-block send. - -2008-08-22 Zheng Da <zhengda1936@gmail.com> - - * README: Update. - - * filter.c (proxy_info): Removed. - (proxy_pfinetpi_ht): Removed. - (proxy_devicepi_ht): Removed. - (create_proxy): Removed. - (destroy_proxy): Removed. - (proxy_device): New structure. - (proxy_user): New structure. - (proxy): New structure. - (create_proxy_user): New function. - (create_proxy_device): New function. - (clean_proxy_user): New function. - (clean_proxy_device): New function. - (ethernet_demuxer): Get the data from proxy object instead of from - proxy_info. - (do_mach_notify_dead_name): Likewise. - (ds_device_write): Likewise. - (ds_device_write_inband): Likewise. - (ds_device_read): Likewise. - (ds_device_read_inband): Likewise. - (ds_device_map): Likewise. - (ds_device_set_status): Likewise. - (ds_device_get_status): Likewise. - (ds_device_set_filter): Likewise. Create the proxy_device object. - (do_mach_notify_no_senders): Use ports_do_mach_notify_no_senders(). - (ds_device_open): Create proxy_user and proxy objects. - (main): Add the cleaning routine when creating the port class. - -2008-08-20 Zheng Da <zhengda1936@gmail.com> - - * README: Update. - - * filter.c (options): Update. - -2008-08-20 Zheng Da <zhengda1936@gmail.com> - - * filter.c (destroy_proxy): Test p_deliverport_hashloc before removing - it from proxy_deliverport_ht, and reverse the order of calling - ports_destroy_right and ports_port_deref. - (ds_device_open): Test device_file and replace "eth" with the variable - name. - -2008-08-20 Zheng Da <zhengda1936@gmail.com> - - * filter.c (device_file): Change the name of a variable. - (ds_device_open): Use device_file directly. - -2008-08-19 Zheng Da <zhengda1936@gmail.com> - - * filter.c (ds_device_open): Generate the device file name, and use it - to open the device. - -2008-08-18 Zheng Da <zhengda1936@gmail.com> - - * README: New file. - - -2008-08-17 Zheng Da <zhengda1936@gmail.com> - - * filter.c (device_name): Remove its default value. - (options): Remove the option '-M'. - (create_proxy): Get the port directly from port_right field in port_info. - (ds_device_open): Remove the code of checking the device name, - and open the device from the device file. - (parse_opt): Remove the code of handling the option '-M'. - (main): Remove the code of getting the master device port. - - -2008-08-14 Zheng Da <zhengda1936@gmail.com> - - * filter.c (pfinet_portclass, device_portclass, other_portclass): - New variables. - (create_proxy): Use pfinet_portclass and device_portclass to create the - port. - (destroy_proxy): Dereference the port before destroying it. - (trivfs_goaway): Test the number of ports in pfinet_portclass and destroy - the master_device. - (main): Create pfinet_portclass, device_portclass, other_portclass. - (print_msg): Deleted. - (deliver_msg): Remove debuging print. - - * ChangeLog: New file. - - -2008-08-13 Zheng Da <zhengda1936@gmail.com> - - * bpf_impl.c: New file. - - * Makefile: New file. - - * queue.c: New file. - - * util.h: New file. - - * bpf_impl.h: New file. - - * filter.c: New file. - - * pcap_filter.c: New file. - - * queue.h: New file. - diff --git a/eth-filter/Makefile b/eth-filter/Makefile deleted file mode 100644 index b425c520..00000000 --- a/eth-filter/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 2008 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. - -dir := eth-filter -makemode := server - -SRCS = bpf_impl.c filter.c queue.c pcap_filter.c -LCLHDRS = bpf_impl.h queue.h util.h -DIST_FILES = ourdevice.defs notify.defs -HURDLIBS = threads ports trivfs fshelp ihash shouldbeinlibc -target = eth-filter -MIGSTUBS = ourdeviceServer.o notifyServer.o -OBJS = $(SRCS:.c=.o) $(MIGSTUBS) - -include ../Makeconf - -#CFLAGS += -I../pfinet/linux-src/include -I../pfinet/glue-include -LDFLAGS += -lpcap - -ourdevice.defs: device.defs - $(CPP) $(CPPFLAGS) -x c $< | sed -e '/out[ ]*device[ ]*:[ ]*device_t/s/device_t/mach_port_send_t/' > $@ diff --git a/eth-filter/README b/eth-filter/README deleted file mode 100644 index 2ef16eda..00000000 --- a/eth-filter/README +++ /dev/null @@ -1,39 +0,0 @@ -[Introduce] - -eth-filter is a filter translator that runs on the network device. The goal of eth-filter is to allow the user to setup the policy to control the traffic to the network. For example, it can block the invalid packet or the packet with the wrong destination address. It can work with eth-multiplexer to control and reduce the traffic between eth-multiplexer and pfinet, and can also work alone, running directly on the real network device. - - -[Usage] - -Usage: eth-filter [OPTION...] -Hurd filter translator. - - -i, --interface=DEVICE Network interface to use - -s, --send-filter=string The filter rule which applies to the outgoing - packet - -r, --receive-filter=string The filter rule which applies to the ingoing - packet - -S, --send-ip-range=IP range A range of IP to create the send filter - -R, --receive-ip-range=IP range - A range of IP to create the receive filter - -?, --help Give this help list - --usage Give a short usage message - -V, --version Print program version - -Mandatory or optional arguments to long options are also mandatory or optional -for any corresponding short options. - - -The '-i' option specifies the network interface the translator sits on. eth-filter can only connect to one network interface and the '-i' option should be only used once. DEVICE is a device file created by devnode translator. -The '-s' and '-r' options give the user a full control to specify the filter rules which applies to the outgoing packet and the incoming packet, respectively. The expression of the rule is the same as the one in TCPDUMP. -The '-S' and '-R' options specify a range of IP that the user wants to filter. They are used to create the sending filter and the receiving filter, respectively. The generated rule is "arp or (ip and src net addr/prefixlen)" or "arp or (ip and dst net addr/prefixlen)". If prefixlen is 32, it can be omitted. -NOTE: '-s' and '-S' cannot be used together. One will replace the other if they are both used. So are '-r' and '-R' options. -An example: settrans -acfg /servers/feth0 /hurd/eth-filter -i /dev/eth0 -S 192.168.8.0/24 -R 192.168.8.0/24 - -[Internal] - -eth-filter works as a proxy, forwarding the packet between the user program and the network interface. In order to forward packets, eth-filter runs as a client to the network device. It opens the device and writes the packet to the network device as pfinet does. It calls device_set_filter() to set the filter rule and give its own port to the device so it can receive packets from the device. The rule passed to the network device is from the user program that connects to eth-filter. -eth-filter works as a RPC server to communicate with the user program and implements the server side functions in device.defs. It gets the packet in the server side function ds_device_write and gets the port to deliver packets to the user program in ds_device_set_filter. -Three structures are used for one pair of the user program and the device: proxy_user, proxy_device, proxy. When the ds_device_open() is called, a proxy_user and proxy objectis created. A proxy_device object is created when the ds_device_set_filter() is called. The proxy_user and proxy_device extend port_info structure. When a packet is received from the user program or from the device, we have to retrieve the proxy object to get the corresponding information. This process is very similar as pflocal. When a user program exits, we need to destroy its proxy_user object and proxy object, and meanwhile, the proxy_device object related to the proxy object is also destroyed. -Two filters exist in eth-filter, one for outgoing packets and the other for incoming packets. These are BPF filters, which are ported from GNU Mach. These BPF filters only decide whether the packet should be forwarded, and they cannot decide the destination of the packet. The BPF instructions are generated by libpcap from the filter rules given by '-s' and '-r' or '-S' and '-R' options. - diff --git a/eth-filter/bpf_impl.c b/eth-filter/bpf_impl.c deleted file mode 100644 index e9202a5f..00000000 --- a/eth-filter/bpf_impl.c +++ /dev/null @@ -1,872 +0,0 @@ - /* - * Mach Operating System - * Copyright (c) 1993-1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * Author: David B. Golub, Carnegie Mellon University - * Date: 3/98 - * - * Network IO. - * - * Packet filter code taken from vaxif/enet.c written - * CMU and Stanford. - */ - -/* the code copied from device/net_io.c in Mach */ - -#include <arpa/inet.h> -#include <string.h> - -#include <mach.h> -#include <hurd.h> - -#include "bpf_impl.h" -#include "queue.h" -#include "util.h" - -queue_head_t rcv_port_list; /* input filter list */ -queue_head_t snd_port_list; /* output filter list */ - -/* - * Execute the filter program starting at pc on the packet p - * wirelen is the length of the original packet - * buflen is the amount of data present - * - * @p: packet data. - * @wirelen: data_count (in bytes) - * @hlen: header len (in bytes) - */ - -int -mach_bpf_do_filter(net_rcv_port_t infp, char *p, unsigned int wirelen, - char *header, unsigned int hlen, net_hash_entry_t **hash_headpp, - net_hash_entry_t *entpp) -{ - register bpf_insn_t pc, pc_end; - register unsigned int buflen; - - register unsigned long A, X; - register int k; - unsigned int mem[BPF_MEMWORDS]; - - /* Generic pointer to either HEADER or P according to the specified offset. */ - char *data = NULL; - - pc = ((bpf_insn_t) infp->filter) + 1; - /* filter[0].code is (NETF_BPF | flags) */ - pc_end = (bpf_insn_t)infp->filter_end; - buflen = NET_RCV_MAX; - *entpp = 0; /* default */ - - A = 0; - X = 0; - for (; pc < pc_end; ++pc) { - switch (pc->code) { - - default: - abort(); - case BPF_RET|BPF_K: - if (infp->rcv_port == MACH_PORT_NULL && - *entpp == 0) { - return 0; - } - return ((u_int)pc->k <= wirelen) ? - pc->k : wirelen; - - case BPF_RET|BPF_A: - if (infp->rcv_port == MACH_PORT_NULL && - *entpp == 0) { - return 0; - } - return ((u_int)A <= wirelen) ? - A : wirelen; - - case BPF_RET|BPF_MATCH_IMM: - if (mach_bpf_match ((net_hash_header_t)infp, pc->jt, mem, - hash_headpp, entpp)) { - return ((u_int)pc->k <= wirelen) ? - pc->k : wirelen; - } - return 0; - - case BPF_LD|BPF_W|BPF_ABS: - k = pc->k; - -load_word: - if ((u_int)k + sizeof(long) <= hlen) - data = header; - else if ((u_int)k + sizeof(long) <= buflen) { - k -= hlen; - data = p; - } else - return 0; - -#ifdef BPF_ALIGN - if (((int)(data + k) & 3) != 0) - A = EXTRACT_LONG(&data[k]); - else -#endif - A = ntohl(*(long *)(data + k)); - continue; - - case BPF_LD|BPF_H|BPF_ABS: - k = pc->k; - -load_half: - if ((u_int)k + sizeof(short) <= hlen) - data = header; - else if ((u_int)k + sizeof(short) <= buflen) { - k -= hlen; - data = p; - } else - return 0; - - A = EXTRACT_SHORT(&data[k]); - continue; - - case BPF_LD|BPF_B|BPF_ABS: - k = pc->k; - -load_byte: - if ((u_int)k < hlen) - data = header; - else if ((u_int)k < buflen) { - data = p; - k -= hlen; - } else - return 0; - - A = data[k]; - continue; - - case BPF_LD|BPF_W|BPF_LEN: - A = wirelen; - continue; - - case BPF_LDX|BPF_W|BPF_LEN: - X = wirelen; - continue; - - case BPF_LD|BPF_W|BPF_IND: - k = X + pc->k; - goto load_word; - - case BPF_LD|BPF_H|BPF_IND: - k = X + pc->k; - goto load_half; - - case BPF_LD|BPF_B|BPF_IND: - k = X + pc->k; - goto load_byte; - - case BPF_LDX|BPF_MSH|BPF_B: - k = pc->k; - if (k < hlen) - data = header; - else if (k < buflen) { - data = p; - k -= hlen; - } else - return 0; - - X = (data[k] & 0xf) << 2; - continue; - - case BPF_LD|BPF_IMM: - A = pc->k; - continue; - - case BPF_LDX|BPF_IMM: - X = pc->k; - continue; - - case BPF_LD|BPF_MEM: - A = mem[pc->k]; - continue; - - case BPF_LDX|BPF_MEM: - X = mem[pc->k]; - continue; - - case BPF_ST: - mem[pc->k] = A; - continue; - - case BPF_STX: - mem[pc->k] = X; - continue; - - case BPF_JMP|BPF_JA: - pc += pc->k; - continue; - - case BPF_JMP|BPF_JGT|BPF_K: - pc += (A > pc->k) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JGE|BPF_K: - pc += (A >= pc->k) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JEQ|BPF_K: - pc += (A == pc->k) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JSET|BPF_K: - pc += (A & pc->k) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JGT|BPF_X: - pc += (A > X) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JGE|BPF_X: - pc += (A >= X) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JEQ|BPF_X: - pc += (A == X) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JSET|BPF_X: - pc += (A & X) ? pc->jt : pc->jf; - continue; - - case BPF_ALU|BPF_ADD|BPF_X: - A += X; - continue; - - case BPF_ALU|BPF_SUB|BPF_X: - A -= X; - continue; - - case BPF_ALU|BPF_MUL|BPF_X: - A *= X; - continue; - - case BPF_ALU|BPF_DIV|BPF_X: - if (X == 0) - return 0; - A /= X; - continue; - - case BPF_ALU|BPF_AND|BPF_X: - A &= X; - continue; - - case BPF_ALU|BPF_OR|BPF_X: - A |= X; - continue; - - case BPF_ALU|BPF_LSH|BPF_X: - A <<= X; - continue; - - case BPF_ALU|BPF_RSH|BPF_X: - A >>= X; - continue; - - case BPF_ALU|BPF_ADD|BPF_K: - A += pc->k; - continue; - - case BPF_ALU|BPF_SUB|BPF_K: - A -= pc->k; - continue; - - case BPF_ALU|BPF_MUL|BPF_K: - A *= pc->k; - continue; - - case BPF_ALU|BPF_DIV|BPF_K: - A /= pc->k; - continue; - - case BPF_ALU|BPF_AND|BPF_K: - A &= pc->k; - continue; - - case BPF_ALU|BPF_OR|BPF_K: - A |= pc->k; - continue; - - case BPF_ALU|BPF_LSH|BPF_K: - A <<= pc->k; - continue; - - case BPF_ALU|BPF_RSH|BPF_K: - A >>= pc->k; - continue; - - case BPF_ALU|BPF_NEG: - A = -A; - continue; - - case BPF_MISC|BPF_TAX: - X = A; - continue; - - case BPF_MISC|BPF_TXA: - A = X; - continue; - } - } - - return 0; -} - -/* - * Return 1 if the 'f' is a valid filter program without a MATCH - * instruction. Return 2 if it is a valid filter program with a MATCH - * instruction. Otherwise, return 0. - * The constraints are that each jump be forward and to a valid - * code. The code must terminate with either an accept or reject. - * 'valid' is an array for use by the routine (it must be at least - * 'len' bytes long). - * - * The kernel needs to be able to verify an application's filter code. - * Otherwise, a bogus program could easily crash the system. - */ -int -mach_bpf_validate(bpf_insn_t f, int bytes, bpf_insn_t *match) -{ - register int i, j, len; - register bpf_insn_t p; - - len = BPF_BYTES2LEN(bytes); - - /* - * f[0].code is already checked to be (NETF_BPF | flags). - * So skip f[0]. - */ - - for (i = 1; i < len; ++i) { - /* - * Check that that jumps are forward, and within - * the code block. - */ - p = &f[i]; - if (BPF_CLASS(p->code) == BPF_JMP) { - register int from = i + 1; - - if (BPF_OP(p->code) == BPF_JA) { - if (from + p->k >= len) - return 0; - } - else if (from + p->jt >= len || from + p->jf >= len) - return 0; - } - /* - * Check that memory operations use valid addresses. - */ - if ((BPF_CLASS(p->code) == BPF_ST || - (BPF_CLASS(p->code) == BPF_LD && - (p->code & 0xe0) == BPF_MEM)) && - (p->k >= BPF_MEMWORDS || p->k < 0)) { - return 0; - } - /* - * Check for constant division by 0. - */ - if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) { - return 0; - } - /* - * Check for match instruction. - * Only one match instruction per filter is allowed. - */ - if (p->code == (BPF_RET|BPF_MATCH_IMM)) { - if (*match != 0 || - p->jt == 0 || - p->jt > N_NET_HASH_KEYS) - return 0; - i += p->jt; /* skip keys */ - if (i + 1 > len) - return 0; - - for (j = 1; j <= p->jt; j++) { - if (p[j].code != (BPF_MISC|BPF_KEY)) - return 0; - } - - *match = p; - } - } - if (BPF_CLASS(f[len - 1].code) == BPF_RET) - return ((*match == 0) ? 1 : 2); - else - return 0; -} - -int -mach_bpf_eq (bpf_insn_t f1, bpf_insn_t f2, int bytes) -{ - register int count; - - count = BPF_BYTES2LEN(bytes); - for (; count--; f1++, f2++) { - if (!BPF_INSN_EQ(f1, f2)) { - if ( f1->code == (BPF_MISC|BPF_KEY) && - f2->code == (BPF_MISC|BPF_KEY) ) - continue; - return FALSE; - } - }; - return TRUE; -} - -unsigned int -mach_bpf_hash (int n, unsigned int *keys) -{ - register unsigned int hval = 0; - - while (n--) { - hval += *keys++; - } - return (hval % NET_HASH_SIZE); -} - - -int -mach_bpf_match (net_hash_header_t hash, int n_keys, unsigned int *keys, - net_hash_entry_t **hash_headpp, net_hash_entry_t *entpp) -{ - register net_hash_entry_t head, entp; - register int i; - - if (n_keys != hash->n_keys) - return FALSE; - - *hash_headpp = &hash->table[mach_bpf_hash(n_keys, keys)]; - head = **hash_headpp; - - if (head == 0) - return FALSE; - - HASH_ITERATE (head, entp) - { - for (i = 0; i < n_keys; i++) { - if (keys[i] != entp->keys[i]) - break; - } - if (i == n_keys) { - *entpp = entp; - return TRUE; - } - } - HASH_ITERATE_END (head, entp) - return FALSE; -} - -/* - * Removes a hash entry (ENTP) from its queue (HEAD). - * If the reference count of filter (HP) becomes zero and not USED, - * HP is removed from the corresponding port lists and is freed. - */ - -int -hash_ent_remove (net_hash_header_t hp, int used, - net_hash_entry_t *head, net_hash_entry_t entp, queue_entry_t *dead_p) -{ - hp->ref_count--; - - if (*head == entp) { - if (queue_empty((queue_t) entp)) { - *head = 0; - ENQUEUE_DEAD(*dead_p, entp, chain); - if (hp->ref_count == 0 && !used) { - if (((net_rcv_port_t)hp)->filter[0] & NETF_IN) - queue_remove(&rcv_port_list, - (net_rcv_port_t)hp, - net_rcv_port_t, chain); - if (((net_rcv_port_t)hp)->filter[0] & NETF_OUT) - queue_remove(&snd_port_list, - (net_rcv_port_t)hp, - net_rcv_port_t, chain); - hp->n_keys = 0; - return TRUE; - } - return FALSE; - } else { - *head = (net_hash_entry_t)queue_next((queue_t) entp); - } - } - - remqueue((queue_t)*head, (queue_entry_t)entp); - ENQUEUE_DEAD(*dead_p, entp, chain); - return FALSE; -} - -/* - * net_free_dead_infp (dead_infp) - * queue_entry_t dead_infp; list of dead net_rcv_port_t. - * - * Deallocates dead net_rcv_port_t. - * No locks should be held when called. - */ -void -net_free_dead_infp (queue_entry_t dead_infp) -{ - register net_rcv_port_t infp, nextfp; - - for (infp = (net_rcv_port_t) dead_infp; infp != 0; infp = nextfp) { - nextfp = (net_rcv_port_t) queue_next(&infp->chain); - mach_port_deallocate(mach_task_self(), infp->rcv_port); - free(infp); - debug ("a dead infp is freed\n"); - } -} - -/* - * net_free_dead_entp (dead_entp) - * queue_entry_t dead_entp; list of dead net_hash_entry_t. - * - * Deallocates dead net_hash_entry_t. - * No locks should be held when called. - */ -void -net_free_dead_entp (queue_entry_t dead_entp) -{ - register net_hash_entry_t entp, nextentp; - - for (entp = (net_hash_entry_t)dead_entp; entp != 0; entp = nextentp) { - nextentp = (net_hash_entry_t) queue_next(&entp->chain); - - mach_port_deallocate(mach_task_self(), entp->rcv_port); - free(entp); - debug ("a dead entp is freed\n"); - } -} - -/* - * Set a filter for a network interface. - * - * We are given a naked send right for the rcv_port. - * If we are successful, we must consume that right. - */ -error_t -net_set_filter (mach_port_t rcv_port, int priority, - filter_t *filter, unsigned int filter_count) -{ - int filter_bytes; - bpf_insn_t match; - register net_rcv_port_t infp, my_infp; - net_rcv_port_t nextfp; - net_hash_header_t hhp; - register net_hash_entry_t entp, hash_entp=NULL; - net_hash_entry_t *head, nextentp; - queue_entry_t dead_infp, dead_entp; - int i; - int ret, is_new_infp; - io_return_t rval; - boolean_t in, out; - - /* Check the filter syntax. */ - - debug ("filter_count: %d, filter[0]: %d\n", filter_count, filter[0]); - - filter_bytes = CSPF_BYTES (filter_count); - match = (bpf_insn_t) 0; - - if (filter_count == 0) { - return (D_INVALID_OPERATION); - } else if (!((filter[0] & NETF_IN) || (filter[0] & NETF_OUT))) { - return (D_INVALID_OPERATION); /* NETF_IN or NETF_OUT required */ - } else if ((filter[0] & NETF_TYPE_MASK) == NETF_BPF) { - ret = mach_bpf_validate((bpf_insn_t)filter, filter_bytes, &match); - if (!ret) - return (D_INVALID_OPERATION); - } else { - return (D_INVALID_OPERATION); - } - debug ("net_set_filter: check over\n"); - - rval = D_SUCCESS; /* default return value */ - dead_infp = dead_entp = 0; - - if (match == (bpf_insn_t) 0) { - /* - * If there is no match instruction, we allocate - * a normal packet filter structure. - */ - my_infp = (net_rcv_port_t) calloc(1, sizeof(struct net_rcv_port)); - my_infp->rcv_port = rcv_port; - is_new_infp = TRUE; - } else { - /* - * If there is a match instruction, we assume there will be - * multiple sessions with a common substructure and allocate - * a hash table to deal with them. - */ - my_infp = 0; - hash_entp = (net_hash_entry_t) calloc(1, sizeof(struct net_hash_entry)); - is_new_infp = FALSE; - } - - /* - * Look for an existing filter on the same reply port. - * Look for filters with dead ports (for GC). - * Look for a filter with the same code except KEY insns. - */ - void check_filter_list(queue_head_t *if_port_list) - { - FILTER_ITERATE(if_port_list, infp, nextfp, &infp->chain) { - if (infp->rcv_port == MACH_PORT_NULL) { - if (match != 0 - && infp->priority == priority - && my_infp == 0 - && (infp->filter_end - infp->filter) == filter_count - && mach_bpf_eq((bpf_insn_t)infp->filter, - (bpf_insn_t)filter, filter_bytes)) { - my_infp = infp; - } - - for (i = 0; i < NET_HASH_SIZE; i++) { - head = &((net_hash_header_t) infp)->table[i]; - if (*head == 0) - continue; - - /* - * Check each hash entry to make sure the - * destination port is still valid. Remove - * any invalid entries. - */ - entp = *head; - do { - nextentp = (net_hash_entry_t) entp->he_next; - - /* checked without - ip_lock(entp->rcv_port) */ - if (entp->rcv_port == rcv_port) { - ret = hash_ent_remove ((net_hash_header_t)infp, - (my_infp == infp), - head, - entp, - &dead_entp); - if (ret) - goto hash_loop_end; - } - - entp = nextentp; - /* While test checks head since hash_ent_remove - * might modify it. - */ - } while (*head != 0 && entp != *head); - } - -hash_loop_end: - ; - } else if (infp->rcv_port == rcv_port) { - /* Remove the old filter from lists */ - if (infp->filter[0] & NETF_IN) - queue_remove(&rcv_port_list, infp, - net_rcv_port_t, chain); - if (infp->filter[0] & NETF_OUT) - queue_remove(&snd_port_list, infp, - net_rcv_port_t, chain); - - ENQUEUE_DEAD(dead_infp, infp, chain); - } - } - FILTER_ITERATE_END - } - - in = (filter[0] & NETF_IN) != 0; - out = (filter[0] & NETF_OUT) != 0; - - if (in) - check_filter_list(&rcv_port_list); - if (out) - check_filter_list(&snd_port_list); - - if (my_infp == 0) { - /* Allocate a dummy infp */ - for (i = 0; i < N_NET_HASH; i++) { - if (filter_hash_header[i].n_keys == 0) - break; - } - if (i == N_NET_HASH) { - - mach_port_deallocate(mach_task_self() , rcv_port); - if (match != 0) - free(hash_entp); - - rval = D_NO_MEMORY; - goto clean_and_return; - } - - hhp = &filter_hash_header[i]; - hhp->n_keys = match->jt; - - hhp->ref_count = 0; - for (i = 0; i < NET_HASH_SIZE; i++) - hhp->table[i] = 0; - - my_infp = (net_rcv_port_t)hhp; - my_infp->rcv_port = MACH_PORT_NULL; /* indication of dummy */ - is_new_infp = TRUE; - } - - if (is_new_infp) { - my_infp->priority = priority; - my_infp->rcv_count = 0; - - /* Copy filter program. */ - memcpy (my_infp->filter, filter, filter_bytes); - my_infp->filter_end = - (filter_t *)((char *)my_infp->filter + filter_bytes); - - /* Insert my_infp according to priority */ - if (in) { - queue_iterate(&rcv_port_list, infp, net_rcv_port_t, chain) - if (priority > infp->priority) - break; - - queue_enter(&rcv_port_list, my_infp, net_rcv_port_t, chain); - } - - if (out) { - queue_iterate(&snd_port_list, infp, net_rcv_port_t, chain) - if (priority > infp->priority) - break; - - queue_enter(&snd_port_list, my_infp, net_rcv_port_t, chain); - } - } - - if (match != 0) { - /* Insert to hash list */ - net_hash_entry_t *p; - - hash_entp->rcv_port = rcv_port; - for (i = 0; i < match->jt; i++) /* match->jt is n_keys */ - hash_entp->keys[i] = match[i+1].k; - p = &((net_hash_header_t)my_infp)-> - table[mach_bpf_hash(match->jt, hash_entp->keys)]; - - /* Not checking for the same key values */ - if (*p == 0) { - queue_init ((queue_t) hash_entp); - *p = hash_entp; - } else { - enqueue_tail((queue_t)*p, (queue_entry_t)hash_entp); - } - - ((net_hash_header_t)my_infp)->ref_count++; - } - -clean_and_return: - /* No locks are held at this point. */ - - if (dead_infp != 0) - net_free_dead_infp(dead_infp); - if (dead_entp != 0) - net_free_dead_entp(dead_entp); - - return (rval); -} - -/* Remove the filter in if_port_list whose port for delivering is dead_port. */ -void -remove_dead_filter (queue_head_t *if_port_list, mach_port_t dead_port) -{ - net_rcv_port_t infp; - net_rcv_port_t nextfp; - net_hash_entry_t *head, nextentp; - queue_entry_t dead_infp, dead_entp; - net_hash_entry_t entp = NULL; - int i, ret; - - dead_infp = dead_entp = 0; - FILTER_ITERATE (if_port_list, infp, nextfp, &infp->chain) { - if (infp->rcv_port == MACH_PORT_NULL) { - for (i = 0; i < NET_HASH_SIZE; i++) { - head = &((net_hash_header_t) infp)->table[i]; - if (*head == 0) - continue; - - /* - * Check each hash entry to make sure the - * destination port is still valid. Remove - * any invalid entries. - */ - entp = *head; - do { - nextentp = (net_hash_entry_t) entp->he_next; - - /* checked without - ip_lock(entp->rcv_port) */ - if (entp->rcv_port == dead_port) { - ret = hash_ent_remove ((net_hash_header_t) infp, - 0, - head, - entp, - &dead_entp); - if (ret) - goto hash_loop_end; - } - - entp = nextentp; - /* While test checks head since hash_ent_remove - * might modify it. - */ - } while (*head != 0 && entp != *head); - } - -hash_loop_end: - ; - } else if (infp->rcv_port == dead_port) { - /* Remove the old filter from lists */ - if (infp->filter[0] & NETF_IN) - queue_remove(&rcv_port_list, infp, - net_rcv_port_t, chain); - if (infp->filter[0] & NETF_OUT) - queue_remove(&snd_port_list, infp, - net_rcv_port_t, chain); - - ENQUEUE_DEAD(dead_infp, infp, chain); - } - } - FILTER_ITERATE_END - - if (dead_infp != 0) - net_free_dead_infp(dead_infp); - if (dead_entp != 0) - net_free_dead_entp(dead_entp); -} - -/* Remove all filters whose port for delivering is dead_port. */ -void -remove_dead_filter_from_all (mach_port_t dead_port) -{ - remove_dead_filter (&snd_port_list, dead_port); - remove_dead_filter (&rcv_port_list, dead_port); -} - -void -bpf_init() -{ - queue_init (&rcv_port_list); - queue_init (&snd_port_list); -} diff --git a/eth-filter/bpf_impl.h b/eth-filter/bpf_impl.h deleted file mode 100644 index de61df12..00000000 --- a/eth-filter/bpf_impl.h +++ /dev/null @@ -1,158 +0,0 @@ - /* - * Mach Operating System - * Copyright (c) 1993-1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * Author: David B. Golub, Carnegie Mellon University - * Date: 3/98 - * - * Network IO. - * - * Packet filter code taken from vaxif/enet.c written - * CMU and Stanford. - */ - -/* the code copied from device/net_io.c in Mach */ - -#ifndef BPF_IMPL_H -#define BPF_IMPL_H - -#include <mach.h> -#include <hurd.h> -#include <device/bpf.h> - -#include "queue.h" - -typedef unsigned short filter_t; -typedef filter_t *filter_array_t; - -#define NET_MAX_FILTER 128 /* was 64, bpf programs are big */ - -#define NET_HASH_SIZE 256 -#define N_NET_HASH 4 -#define N_NET_HASH_KEYS 4 - -#ifndef BPF_ALIGN -#define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p)) -#define EXTRACT_LONG(p) (ntohl(*(u_long *)p)) -#else -#define EXTRACT_SHORT(p)\ - ((u_short)\ - ((u_short)*((u_char *)p+0)<<8|\ - (u_short)*((u_char *)p+1)<<0)) -#define EXTRACT_LONG(p)\ - ((u_long)*((u_char *)p+0)<<24|\ - (u_long)*((u_char *)p+1)<<16|\ - (u_long)*((u_char *)p+2)<<8|\ - (u_long)*((u_char *)p+3)<<0) -#endif - -#define HASH_ITERATE(head, elt) (elt) = (net_hash_entry_t) (head); do { -#define HASH_ITERATE_END(head, elt) \ - (elt) = (net_hash_entry_t) queue_next((queue_entry_t) (elt)); \ -} while ((elt) != (head)); - -#define FILTER_ITERATE(if_port_list, fp, nextfp, chain) \ - for ((fp) = (net_rcv_port_t) queue_first(if_port_list); \ - !queue_end(if_port_list, (queue_entry_t)(fp)); \ - (fp) = (nextfp)) { \ - (nextfp) = (net_rcv_port_t) queue_next(chain); -#define FILTER_ITERATE_END } - -/* entry_p must be net_rcv_port_t or net_hash_entry_t */ -#define ENQUEUE_DEAD(dead, entry_p, chain) { \ - queue_next(&(entry_p)->chain) = (queue_entry_t) (dead); \ - (dead) = (queue_entry_t)(entry_p); \ -} - -#define CSPF_BYTES(n) ((n) * sizeof (filter_t)) - -/* - * Receive port for net, with packet filter. - * This data structure by itself represents a packet - * filter for a single session. - */ -struct net_rcv_port { - queue_chain_t chain; - mach_port_t rcv_port; /* port to send packet to */ - int rcv_count; /* number of packets received */ - int priority; /* priority for filter */ - filter_t *filter_end; /* pointer to end of filter */ - filter_t filter[NET_MAX_FILTER]; - /* filter operations */ -}; -typedef struct net_rcv_port *net_rcv_port_t; - -/* - * A single hash entry. - */ -struct net_hash_entry { - queue_chain_t chain; /* list of entries with same hval */ -#define he_next chain.next -#define he_prev chain.prev - mach_port_t rcv_port; /* destination port */ - unsigned int keys[N_NET_HASH_KEYS]; -}; -typedef struct net_hash_entry *net_hash_entry_t; - -/* - * This structure represents a packet filter with multiple sessions. - * - * For example, all application level TCP sessions might be - * represented by one of these structures. It looks like a - * net_rcv_port struct so that both types can live on the - * same packet filter queues. - */ -struct net_hash_header { - struct net_rcv_port rcv; - int n_keys; /* zero if not used */ - int ref_count; /* reference count */ - net_hash_entry_t table[NET_HASH_SIZE]; -} filter_hash_header[N_NET_HASH]; - -typedef struct net_hash_header *net_hash_header_t; - -int mach_bpf_do_filter(net_rcv_port_t infp, char *p, unsigned int wirelen, - char *header, unsigned int hlen, net_hash_entry_t **hash_headpp, - net_hash_entry_t *entpp); -int mach_bpf_validate(bpf_insn_t f, int bytes, bpf_insn_t *match); -int mach_bpf_eq (bpf_insn_t f1, bpf_insn_t f2, int bytes); -unsigned int mach_bpf_hash (int n, unsigned int *keys); -int mach_bpf_match (net_hash_header_t hash, int n_keys, unsigned int *keys, - net_hash_entry_t **hash_headpp, net_hash_entry_t *entpp); - -error_t net_set_filter(mach_port_t rcv_port, int priority, - filter_t *filter, unsigned int filter_count); -int hash_ent_remove (net_hash_header_t hp, int used, net_hash_entry_t *head, - net_hash_entry_t entp, queue_entry_t *dead_p); -void net_free_dead_infp (queue_entry_t dead_infp); -void net_free_dead_entp (queue_entry_t dead_entp); -void remove_dead_filter (queue_head_t *if_port_list, mach_port_t dead_port); -void remove_dead_filter_from_all (mach_port_t dead_port); -void bpf_init(); - -extern queue_head_t rcv_port_list; /* input filter list */ -extern queue_head_t snd_port_list; /* output filter list */ - -#endif /* _DEVICE_BPF_H_ */ diff --git a/eth-filter/filter.c b/eth-filter/filter.c deleted file mode 100644 index 75a389d2..00000000 --- a/eth-filter/filter.c +++ /dev/null @@ -1,827 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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. */ - -/* - * This program is a filter translator which sits on the top of the network - * interface. - * It provides two filters: for outgoing packets and for incoming packets. - * Only one pfinet server are allowed to run on the top of the translator. - */ - -#include <argp.h> -#include <errno.h> -#include <error.h> -#include <stddef.h> - -#include <fcntl.h> -#include <hurd.h> -#include <mach.h> -#include <device/device.h> -#include <hurd/trivfs.h> -#include <hurd/ports.h> -#include <hurd/ihash.h> - -#include "ourdevice_S.h" -#include "notify_S.h" -#include "bpf_impl.h" -#include "util.h" - -struct proxy_user -{ - struct port_info pi; - struct proxy *proxy; -}; - -struct proxy_device -{ - struct port_info pi; - struct proxy *proxy; -}; - -struct proxy -{ - struct proxy_device *device; - mach_port_t deliver_port; - hurd_ihash_locp_t p_deliverport_hashloc; - mach_port_t device_port; -}; - -int deliver_msg (struct net_rcv_msg *msg, queue_head_t *port_list, - mach_port_t dest); - -static struct hurd_ihash proxy_deliverport_ht -= HURD_IHASH_INITIALIZER (offsetof (struct proxy, p_deliverport_hashloc)); - -/* The name of the network interface that the filter translator sits on. */ -static char *device_file; -const char *argp_program_version = "eth-filter 0.1"; -const char *argp_program_bug_address = "<bug-hurd@gnu.org>"; -static const char doc[] = "Hurd filter translator."; -static const struct argp_option options[] = -{ - {"interface", 'i', "DEVICE", 0, - "Network interface to use", 2}, - {"send-filter", 's', "string", 0, - "The filter rule which applies to the outgoing packet", 4}, - {"receive-filter", 'r', "string", 0, - "The filter rule which applies to the ingoing packet", 5}, - {"send-ip-range", 'S', "IP range", 0, - "A range of IP to create the send filter", 6}, - {"receive-ip-range", 'R', "IP range", 0, - "A range of IP to create the receive filter", 7}, - {0} -}; - -/* A filter allows every packet to be sent and be received. */ -static struct bpf_insn default_snd_filter[] = -{ - {NETF_OUT|NETF_BPF, 0, 0, 0}, - {6, 0, 0, 1500} -}; -static struct bpf_insn default_rcv_filter[] = -{ - {NETF_IN|NETF_BPF, 0, 0, 0}, - {6, 0, 0, 1500} -}; -static struct bpf_insn *snd_filter = NULL; -static int snd_filter_length; -static struct bpf_insn *rcv_filter = NULL; -static int rcv_filter_length; - -/* Port bucket we service requests on. */ -struct port_bucket *port_bucket; - -struct port_class *user_portclass; -struct port_class *device_portclass; -struct port_class *other_portclass; - -/* Trivfs hooks. */ -int trivfs_fstype = FSTYPE_MISC; -int trivfs_fsid = 0; -int trivfs_support_read = 0; -int trivfs_support_write = 0; -int trivfs_support_exec = 0; -int trivfs_allow_open = O_READ | O_WRITE; - -struct port_class *trivfs_protid_portclasses[1]; -struct port_class *trivfs_cntl_portclasses[1]; -int trivfs_protid_nportclasses = 1; -int trivfs_cntl_nportclasses = 1; - -/* For getting the notification of ports from the kernel. */ -struct port_info *notify_pi; - -error_t -create_proxy_user (struct proxy *proxy, mach_port_t *port) -{ - error_t err; - struct proxy_user *user; - - err = ports_create_port (user_portclass, port_bucket, sizeof (*user), &user); - if (err) - return err; - user->proxy = proxy; - - *port = ports_get_right (user); - ports_port_deref (user); - return 0; -} - -error_t -create_proxy_device (struct proxy *proxy, mach_port_t *port) -{ - error_t err; - struct proxy_device *device; - - err = ports_create_port (device_portclass, port_bucket, sizeof (*device), &device); - if (err) - return err; - device->proxy = proxy; - proxy->device = device; - - *port = ports_get_right (device); - ports_port_deref (device); - return 0; -} - -void -clean_proxy_user (void *p) -{ - struct proxy_user *user = p; - struct proxy *proxy = user->proxy; - - if (proxy->p_deliverport_hashloc) - hurd_ihash_locp_remove (&proxy_deliverport_ht, proxy->p_deliverport_hashloc); - - if (proxy->deliver_port != MACH_PORT_NULL) - mach_port_deallocate (mach_task_self (), proxy->deliver_port); - if (proxy->device_port != MACH_PORT_NULL) - mach_port_deallocate (mach_task_self (), proxy->device_port); - - if (proxy->device) - ports_destroy_right (proxy->device); - - free (proxy); -} - -void -clean_proxy_device (void *p) -{ - struct proxy_device *device = p; - if (device->proxy) - device->proxy->device = NULL; -} - -static int -filter_demuxer (mach_msg_header_t *inp, - mach_msg_header_t *outp) -{ - extern int device_server (mach_msg_header_t *, mach_msg_header_t *); - extern int notify_server (mach_msg_header_t *, mach_msg_header_t *); - extern int ethernet_demuxer (mach_msg_header_t *, mach_msg_header_t *); - return device_server (inp, outp) || notify_server (inp, outp) - || ethernet_demuxer (inp, outp) || trivfs_demuxer (inp, outp); -} - -int -ethernet_demuxer (mach_msg_header_t *inp, - mach_msg_header_t *outp) -{ - struct net_rcv_msg *msg = (struct net_rcv_msg *) inp; - struct proxy_device *device; - struct proxy *proxy; - mach_msg_header_t header; - - if (inp->msgh_id != NET_RCV_MSG_ID) - return 0; - - device = ports_lookup_port (port_bucket, inp->msgh_local_port, device_portclass); - if (device == NULL) - return 0; - proxy = device->proxy; - ports_port_deref (device); - - if (proxy && proxy->deliver_port != MACH_PORT_NULL) - { - header = msg->msg_hdr; - deliver_msg (msg, &rcv_port_list, proxy->deliver_port); - msg->msg_hdr = header; - } - - return 1; -} - -/* Implementation of notify interface */ -kern_return_t -do_mach_notify_port_deleted (mach_port_t notify, - mach_port_t name) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_msg_accepted (mach_port_t notify, - mach_port_t name) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_port_destroyed (mach_port_t notify, - mach_port_t port) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_no_senders (mach_port_t notify, - mach_port_mscount_t mscount) -{ - debug ("do_mach_notify_no_senders is called\n"); - return ports_do_mach_notify_no_senders (notify, mscount); -} - -kern_return_t -do_mach_notify_send_once (mach_port_t notify) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_dead_name (mach_port_t notify, - mach_port_t name) -{ - struct proxy *proxy; - - debug ("do_mach_notify_dead_name is called\n"); - mach_port_deallocate (mach_task_self (), name); - proxy = hurd_ihash_find (&proxy_deliverport_ht, name); - if (proxy) - { - proxy->deliver_port = MACH_PORT_NULL; - return 0; - } - return EINVAL; -} - -/* Implementation of device interface */ -kern_return_t -ds_xxx_device_set_status (device_t device, dev_flavor_t flavor, - dev_status_t status, size_t statu_cnt) -{ - return D_INVALID_OPERATION; -} - -kern_return_t -ds_xxx_device_get_status (device_t device, dev_flavor_t flavor, - dev_status_t status, size_t *statuscnt) -{ - return D_INVALID_OPERATION; -} - -kern_return_t -ds_xxx_device_set_filter (device_t device, mach_port_t rec, - int pri, filter_array_t filt, size_t len) -{ - return D_INVALID_OPERATION; -} - -kern_return_t -ds_device_open (mach_port_t master_port, mach_port_t reply_port, - mach_msg_type_name_t reply_portPoly, - dev_mode_t mode, dev_name_t name, mach_port_t *device, - mach_msg_type_name_t *devicetype) -{ - kern_return_t err; - mach_port_t master_device; - mach_port_t user_port; - int file_mode = 0; - struct proxy *proxy; - - if (device_file == NULL) - return D_NO_SUCH_DEVICE; - - if (mode | D_WRITE) - file_mode |= O_WRITE; - if (mode | D_READ) - file_mode |= O_READ; - master_device = file_name_lookup (device_file, file_mode, 0); - if (master_device == MACH_PORT_NULL) - return errno; - - proxy = (struct proxy *)calloc (1, sizeof (*proxy)); - if (proxy == NULL) - { - mach_port_deallocate (mach_task_self (), master_device); - return D_NO_MEMORY; - } - - err = device_open (master_device, mode, name, &proxy->device_port); - mach_port_deallocate (mach_task_self (), master_device); - if (err != KERN_SUCCESS) - { - free (proxy); - return err; - } - - err = create_proxy_user (proxy, &user_port); - if (err) - { - mach_port_deallocate (mach_task_self (), master_device); - free (proxy); - return err; - } - - *device = user_port; - *devicetype = MACH_MSG_TYPE_MAKE_SEND; - - return 0; -} - -kern_return_t -ds_device_close (device_t device) -{ - return 0; -} - -kern_return_t -ds_device_write (device_t device, mach_port_t reply_port, - mach_msg_type_name_t reply_type, dev_mode_t mode, - recnum_t recnum, io_buf_ptr_t data, size_t datalen, - int *bytes_written) -{ - int ret_count = 0; - int has_filter = 0; - net_hash_entry_t entp, *hash_headp; - net_rcv_port_t infp, nextfp; - struct proxy_user *user; - struct proxy *proxy; - - user = ports_lookup_port (port_bucket, device, user_portclass); - if (user == NULL) - { - vm_deallocate (mach_task_self (), data, datalen); - return D_INVALID_OPERATION; - } - proxy = user->proxy; - ports_port_deref (user); - - /* The packet can be sent as long as it passes one filter, - * even thought there is usually only one filter in the list. */ - FILTER_ITERATE (&snd_port_list, infp, nextfp, &infp->chain) - { - has_filter = 1; - ret_count = mach_bpf_do_filter (infp, - data + sizeof (struct ethhdr), - datalen - sizeof (struct ethhdr), - data, sizeof (struct ethhdr), - &hash_headp, &entp); - if (ret_count) - break; - } - FILTER_ITERATE_END - - error_t err; - if (ret_count || !has_filter) - { - print_pack (data, datalen); - debug ("before writing a packet from the device.\n"); - err = device_write (proxy->device_port, mode , recnum , - data, datalen, bytes_written); - debug ("after writing a packet from the device.\n"); - } - else - { - *bytes_written = datalen; - err = 0; - } - vm_deallocate (mach_task_self (), data, datalen); - return err; -} - -kern_return_t -ds_device_write_inband (device_t device, mach_port_t reply_port, - mach_msg_type_name_t reply_type, dev_mode_t mode, - recnum_t recnum, io_buf_ptr_inband_t data, - size_t datalen, int *bytes_written) -{ - kern_return_t ret; - struct proxy_user *user; - struct proxy *proxy; - - user = ports_lookup_port (port_bucket, device, user_portclass); - if (user == NULL) - return D_INVALID_OPERATION; - proxy = user->proxy; - ports_port_deref (user); - - ret = device_write_inband (proxy->device_port, mode, recnum, data, - datalen, bytes_written); - return ret; -} - -kern_return_t -ds_device_read (device_t device, mach_port_t reply_port, - mach_msg_type_name_t reply_type, dev_mode_t mode, - recnum_t recnum, int bytes_wanted, - io_buf_ptr_t *data, size_t *datalen) -{ - kern_return_t ret; - struct proxy_user *user; - struct proxy *proxy; - - user = ports_lookup_port (port_bucket, device, user_portclass); - if (user == NULL) - return D_INVALID_OPERATION; - proxy = user->proxy; - ports_port_deref (user); - - ret = device_read (proxy->device_port, mode, recnum, - bytes_wanted, data, datalen); - return ret; -} - -kern_return_t -ds_device_read_inband (device_t device, mach_port_t reply_port, - mach_msg_type_name_t reply_type, dev_mode_t mode, - recnum_t recnum, int bytes_wanted, - io_buf_ptr_inband_t data, size_t *datalen) -{ - kern_return_t ret; - struct proxy_user *user; - struct proxy *proxy; - - user = ports_lookup_port (port_bucket, device, user_portclass); - if (user == NULL) - return D_INVALID_OPERATION; - proxy = user->proxy; - ports_port_deref (user); - - ret = device_read_inband (proxy->device_port, mode, recnum, - bytes_wanted, data, datalen); - return ret; -} - -kern_return_t -ds_device_map (device_t device, vm_prot_t prot, vm_offset_t offset, - vm_size_t size, memory_object_t *pager, int unmap) -{ - kern_return_t ret; - struct proxy_user *user; - struct proxy *proxy; - - user = ports_lookup_port (port_bucket, device, user_portclass); - if (user == NULL) - return D_INVALID_OPERATION; - proxy = user->proxy; - ports_port_deref (user); - - ret = device_map (proxy->device_port, prot, offset, - size, pager, unmap); - return ret; -} - -kern_return_t -ds_device_set_status (device_t device, dev_flavor_t flavor, - dev_status_t status, size_t statuslen) -{ - kern_return_t ret; - struct proxy_user *user; - struct proxy *proxy; - - user = ports_lookup_port (port_bucket, device, user_portclass); - if (user == NULL) - return D_INVALID_OPERATION; - proxy = user->proxy; - ports_port_deref (user); - - ret = device_set_status (proxy->device_port, flavor, - status, statuslen); - return ret; -} - -kern_return_t -ds_device_get_status (device_t device, dev_flavor_t flavor, - dev_status_t status, size_t *statuslen) -{ - kern_return_t ret; - struct proxy_user *user; - struct proxy *proxy; - - user = ports_lookup_port (port_bucket, device, user_portclass); - if (user == NULL) - return D_INVALID_OPERATION; - proxy = user->proxy; - ports_port_deref (user); - - ret = device_get_status (proxy->device_port, flavor, status, statuslen); - return ret; -} - -kern_return_t -ds_device_set_filter (device_t device, mach_port_t receive_port, - int priority, filter_array_t filter, size_t filterlen) -{ - mach_port_t tmp; - kern_return_t err; - mach_port_t device_receive_port; - struct proxy_user *user; - struct proxy *proxy; - - user = ports_lookup_port (port_bucket, device, user_portclass); - if (user == NULL) - return D_INVALID_OPERATION; - proxy = user->proxy; - ports_port_deref (user); - - if (proxy->device == NULL) - { - error_t err; - err = create_proxy_device (proxy, &device_receive_port); - if (err) - return err; - } - else - device_receive_port = ports_get_right (proxy->device); - - /* Set the filter from pfinet into the interface, - * but the packet will be delivered to the translator, - * so the translator has the chance to filter some packets. */ - err = device_set_filter (proxy->device_port, - device_receive_port, - MACH_MSG_TYPE_MAKE_SEND, priority, - filter, filterlen); - if (err) - return err; - - proxy->deliver_port = receive_port; - hurd_ihash_add (&proxy_deliverport_ht, receive_port, proxy); - - err = mach_port_request_notification (mach_task_self (), receive_port, - MACH_NOTIFY_DEAD_NAME, 0, - ports_get_right (notify_pi), - MACH_MSG_TYPE_MAKE_SEND_ONCE, &tmp); - if (tmp != MACH_PORT_NULL) - mach_port_deallocate (mach_task_self (), tmp); - - return err; -} - -void -trivfs_modify_stat (struct trivfs_protid *cred, io_statbuf_t *stat) -{ -} - -error_t -trivfs_goaway (struct trivfs_control *fsys, int flags) -{ - int count; - - /* Stop new requests. */ - ports_inhibit_class_rpcs (trivfs_cntl_portclasses[0]); - ports_inhibit_class_rpcs (trivfs_protid_portclasses[0]); - - count = ports_count_class (user_portclass); - debug ("the number of ports alive: %d\n", count); - - if (count && !(flags & FSYS_GOAWAY_FORCE)) - { - /* We won't go away, so start things going again... */ - ports_enable_class (trivfs_protid_portclasses[0]); - ports_resume_class_rpcs (trivfs_cntl_portclasses[0]); - ports_resume_class_rpcs (trivfs_protid_portclasses[0]); - return EBUSY; - } - - debug ("the translator is gone away\n"); - exit (0); -} - -/* Convert the network address input by the user into - * a form that is accepted by libpcap. */ -int -correct_net_addr (char *orig, char *result, int result_len) -{ - char *ptr; - int netmask_len; - int remain_bits; - int remain_bytes; - char netmask; - char addr[4]; - char buf[INET_ADDRSTRLEN]; - int i; - - ptr = strstr (orig, "/"); - if (ptr == NULL) - { - strncpy (result, orig, result_len); - return 0; - } - - *ptr = 0; - ptr++; - netmask_len = atoi (ptr); - if (inet_pton (AF_INET, orig, addr) < 0) - { - perror ("inet_pton"); - return -1; - } - remain_bits = netmask_len % 8; - netmask = ~0; - netmask >>= 8 - remain_bits; - netmask <<= 8 - remain_bits; - remain_bytes = netmask_len / 8; - addr[remain_bytes] &= netmask; - for (i=remain_bytes+1 ; i < 4 ; i++) - addr[i] = 0; - - snprintf (result, result_len, "%s/%s", - inet_ntop (AF_INET, addr, buf, INET_ADDRSTRLEN), ptr); - return 0; -} - -static error_t -parse_opt (int opt, char *arg, struct argp_state *state) -{ - struct bpf_insn *trans_filter_program (char *str, int send, - int *filter_len); - char buf[1024]; - char addr[INET_ADDRSTRLEN+4]; - - switch (opt) - { - case 'i': - device_file = arg; - break; - case 's': - if (snd_filter) - free (snd_filter); - snd_filter = trans_filter_program (arg, 1, &snd_filter_length); - break; - case 'r': - if (rcv_filter) - free (rcv_filter); - rcv_filter = trans_filter_program (arg, 0, &rcv_filter_length); - break; - case 'S': - if (correct_net_addr (arg, addr, INET_ADDRSTRLEN+4) < 0) - return 0; - snprintf (buf, sizeof (buf), "arp or (ip and src net %s)", addr); - if (snd_filter) - free (snd_filter); - snd_filter = trans_filter_program (buf, 1, &snd_filter_length); - break; - case 'R': - if (correct_net_addr (arg, addr, INET_ADDRSTRLEN+4) < 0) - return 0; - snprintf (buf, sizeof (buf), "arp or (ip and dst net %s)", addr); - if (rcv_filter) - free (rcv_filter); - rcv_filter = trans_filter_program (buf, 0, &rcv_filter_length); - break; - case ARGP_KEY_ERROR: - case ARGP_KEY_SUCCESS: - case ARGP_KEY_INIT: - break; - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - -int -main (int argc, char *argv[]) -{ - error_t err; - mach_port_t bootstrap; - struct trivfs_control *fsys; - const struct argp argp = { options, parse_opt, 0, doc }; - - port_bucket = ports_create_bucket (); - user_portclass = ports_create_class (clean_proxy_user, 0); - device_portclass = ports_create_class (clean_proxy_device, 0); - other_portclass = ports_create_class (0, 0); - trivfs_cntl_portclasses[0] = ports_create_class (trivfs_clean_cntl, 0); - trivfs_protid_portclasses[0] = ports_create_class (trivfs_clean_protid, 0); - - argp_parse (&argp, argc, argv, 0, 0, 0); - - /* Prepare the filter. */ - if (snd_filter == NULL) - { - snd_filter = default_snd_filter; - snd_filter_length = sizeof (default_snd_filter) / sizeof (short); - } - if (rcv_filter == NULL) - { - rcv_filter = default_rcv_filter; - rcv_filter_length = sizeof (default_rcv_filter) / sizeof (short); - } - - task_get_bootstrap_port (mach_task_self (), &bootstrap); - if (bootstrap == MACH_PORT_NULL) - error (1, 0, "must be started as a translator"); - - err = ports_create_port (other_portclass, port_bucket, - sizeof (struct port_info), ¬ify_pi); - if (err) - error (1, err, "ports_create_port for notification"); - - /* Reply to our parent. */ - err = trivfs_startup (bootstrap, 0, - trivfs_cntl_portclasses[0], port_bucket, - trivfs_protid_portclasses[0], port_bucket, &fsys); - mach_port_deallocate (mach_task_self (), bootstrap); - if (err) - error (1, err, "Contacting parent"); - - /* Initialize the bpf, and set the filter for outgoing packets. - * MACH_PORT_DEAD is used because we don't need a receiving port. */ - bpf_init (); - err = net_set_filter (MACH_PORT_DEAD, 0, (filter_t *) snd_filter, - snd_filter_length); - if (err) - error (1, err, "set the sending filter"); - /* Set the filter translator's own rule. */ - err = net_set_filter (MACH_PORT_DEAD, 0, (filter_t *) rcv_filter, - rcv_filter_length); - if (err) - error (1, err, "set the receiving filter"); - - /* Launch. */ - do - { - ports_manage_port_operations_one_thread (port_bucket, - filter_demuxer, 0); - } while (trivfs_goaway (fsys, 0)); - return 0; -} - -int -deliver_msg (struct net_rcv_msg *msg, queue_head_t *port_list, - mach_port_t dest) -{ - int ret_count = 0; - int has_filter = 0; - mach_msg_return_t err; - net_rcv_port_t infp, nextfp; - - msg->msg_hdr.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0); - msg->msg_hdr.msgh_local_port = MACH_PORT_NULL; - msg->msg_hdr.msgh_kind = MACH_MSGH_KIND_NORMAL; - - /* Deliver the packet to the right pfinet, - * actually there should be only one filter in the list. */ - FILTER_ITERATE (port_list, infp, nextfp, &infp->chain) - { - net_hash_entry_t entp, *hash_headp; - - entp = (net_hash_entry_t) 0; - ret_count = mach_bpf_do_filter (infp, - msg->packet + sizeof (struct packet_header), - msg->net_rcv_msg_packet_count, - msg->header, - sizeof (struct ethhdr), - &hash_headp, &entp); - - if (ret_count) - break; - } - FILTER_ITERATE_END - - if (ret_count || !has_filter) - { - msg->msg_hdr.msgh_remote_port = dest; - debug ("before delivering the message\n"); - err = mach_msg ((mach_msg_header_t *)msg, - MACH_SEND_MSG|MACH_SEND_TIMEOUT, - msg->msg_hdr.msgh_size, 0, MACH_PORT_NULL, - 0, MACH_PORT_NULL); - if (err != MACH_MSG_SUCCESS) - { - fprintf (stderr, "deliver msg: mach_msg: %s\n", - strerror (err)); - return -1; - } - debug ("after delivering the message\n"); - } - - return 0; -} diff --git a/eth-filter/pcap_filter.c b/eth-filter/pcap_filter.c deleted file mode 100644 index 67ee9bb8..00000000 --- a/eth-filter/pcap_filter.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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. */ - -/* - * This file translates a string into a bpf program. - * The BPF structures are defined in both of bpf.h and pcap-bpf.h - * Hopefully, there is no conflict between them. - * This file uses the BPF definition in pcap-bpf.h. - */ - -#include <pcap.h> -#include <stdlib.h> -#include <string.h> - -#include "util.h" - -#define NETF_IN 0x1 -#define NETF_OUT 0x2 -#define NETF_NBPA 10 -#define NETF_BPF (1 << NETF_NBPA) - -/* This function translates the bpf program - * from the string into the instructions. */ -struct bpf_insn *trans_filter_program (char *str, int send, int *filter_len) -{ - struct bpf_program program; - struct bpf_insn *insn; - pcap_t *pcap; - int err; - - debug ("Compiling the bpf program: %s.\n", str); - pcap = pcap_open_dead (DLT_EN10MB, 1500); - if (pcap == NULL) - return NULL; - err = pcap_compile (pcap, &program, str, 1, 0); - if (err < 0) - { - debug ("pcap_compile: %s\n", pcap_geterr (pcap)); - pcap_close (pcap); - return NULL; - } - - debug ("Finish compiling the bpf program, get %d bpf instructions.\n", - program.bf_len); - insn = (struct bpf_insn *) malloc ((program.bf_len + 1) * sizeof (*insn)); - /* Clear the first instruction. */ - memset (insn, 0, sizeof (*insn)); - if (send) - insn->code = NETF_OUT | NETF_BPF; - else - insn->code = NETF_IN | NETF_BPF; - memcpy (insn + 1, program.bf_insns, program.bf_len * sizeof (*insn)); - *filter_len = ((program.bf_len + 1) * sizeof (*insn)) / sizeof (short); - debug ("%d bpf instructions, the length of filters is %d words\n", - program.bf_len, *filter_len); - pcap_freecode (&program); - pcap_close (pcap); - - return insn; -} diff --git a/eth-filter/queue.c b/eth-filter/queue.c deleted file mode 100644 index a43a21b0..00000000 --- a/eth-filter/queue.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * Routines to implement queue package. - */ - -#include "queue.h" - - - -/* - * Insert element at head of queue. - */ -void enqueue_head( - register queue_t que, - register queue_entry_t elt) -{ - elt->next = que->next; - elt->prev = que; - elt->next->prev = elt; - que->next = elt; -} - -/* - * Insert element at tail of queue. - */ -void enqueue_tail( - register queue_t que, - register queue_entry_t elt) -{ - elt->next = que; - elt->prev = que->prev; - elt->prev->next = elt; - que->prev = elt; -} - -/* - * Remove and return element at head of queue. - */ -queue_entry_t dequeue_head( - register queue_t que) -{ - register queue_entry_t elt; - - if (que->next == que) - return((queue_entry_t)0); - - elt = que->next; - elt->next->prev = que; - que->next = elt->next; - return(elt); -} - -/* - * Remove and return element at tail of queue. - */ -queue_entry_t dequeue_tail( - register queue_t que) -{ - register queue_entry_t elt; - - if (que->prev == que) - return((queue_entry_t)0); - - elt = que->prev; - elt->prev->next = que; - que->prev = elt->prev; - return(elt); -} - -/* - * Remove arbitrary element from queue. - * Does not check whether element is on queue - the world - * will go haywire if it isn't. - */ - -/*ARGSUSED*/ -void remqueue( - queue_t que, - register queue_entry_t elt) -{ - elt->next->prev = elt->prev; - elt->prev->next = elt->next; -} - -/* - * Routines to directly imitate the VAX hardware queue - * package. - */ -void insque( - register struct queue_entry *entry, - register struct queue_entry *pred) -{ - entry->next = pred->next; - entry->prev = pred; - (pred->next)->prev = entry; - pred->next = entry; -} - -struct queue_entry -*remque( - register struct queue_entry *elt) -{ - (elt->next)->prev = elt->prev; - (elt->prev)->next = elt->next; - return(elt); -} - diff --git a/eth-filter/queue.h b/eth-filter/queue.h deleted file mode 100644 index f067f557..00000000 --- a/eth-filter/queue.h +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon rights - * to redistribute these changes. - */ -/* - * File: queue.h - * Author: Avadis Tevanian, Jr. - * Date: 1985 - * - * Type definitions for generic queues. - * - */ - -#ifndef _KERN_QUEUE_H_ -#define _KERN_QUEUE_H_ - -/* - * Queue of abstract objects. Queue is maintained - * within that object. - * - * Supports fast removal from within the queue. - * - * How to declare a queue of elements of type "foo_t": - * In the "*foo_t" type, you must have a field of - * type "queue_chain_t" to hold together this queue. - * There may be more than one chain through a - * "foo_t", for use by different queues. - * - * Declare the queue as a "queue_t" type. - * - * Elements of the queue (of type "foo_t", that is) - * are referred to by reference, and cast to type - * "queue_entry_t" within this module. - */ - -/* - * A generic doubly-linked list (queue). - */ - -struct queue_entry { - struct queue_entry *next; /* next element */ - struct queue_entry *prev; /* previous element */ -}; - -typedef struct queue_entry *queue_t; -typedef struct queue_entry queue_head_t; -typedef struct queue_entry queue_chain_t; -typedef struct queue_entry *queue_entry_t; - -/* - * enqueue puts "elt" on the "queue". - * dequeue returns the first element in the "queue". - * remqueue removes the specified "elt" from the specified "queue". - */ - -#define enqueue(queue,elt) enqueue_tail(queue, elt) -#define dequeue(queue) dequeue_head(queue) - -void enqueue_head(queue_t, queue_entry_t); -void enqueue_tail(queue_t, queue_entry_t); -queue_entry_t dequeue_head(queue_t); -queue_entry_t dequeue_tail(queue_t); -void remqueue(queue_t, queue_entry_t); - -/* - * Macro: queue_init - * Function: - * Initialize the given queue. - * Header: - * void queue_init(q) - * queue_t q; *MODIFIED* - */ -#define queue_init(q) ((q)->next = (q)->prev = q) - -/* - * Macro: queue_first - * Function: - * Returns the first entry in the queue, - * Header: - * queue_entry_t queue_first(q) - * queue_t q; *IN* - */ -#define queue_first(q) ((q)->next) - -/* - * Macro: queue_next - * Function: - * Returns the entry after an item in the queue. - * Header: - * queue_entry_t queue_next(qc) - * queue_t qc; - */ -#define queue_next(qc) ((qc)->next) - -/* - * Macro: queue_last - * Function: - * Returns the last entry in the queue. - * Header: - * queue_entry_t queue_last(q) - * queue_t q; *IN* - */ -#define queue_last(q) ((q)->prev) - -/* - * Macro: queue_prev - * Function: - * Returns the entry before an item in the queue. - * Header: - * queue_entry_t queue_prev(qc) - * queue_t qc; - */ -#define queue_prev(qc) ((qc)->prev) - -/* - * Macro: queue_end - * Function: - * Tests whether a new entry is really the end of - * the queue. - * Header: - * boolean_t queue_end(q, qe) - * queue_t q; - * queue_entry_t qe; - */ -#define queue_end(q, qe) ((q) == (qe)) - -/* - * Macro: queue_empty - * Function: - * Tests whether a queue is empty. - * Header: - * boolean_t queue_empty(q) - * queue_t q; - */ -#define queue_empty(q) queue_end((q), queue_first(q)) - - -/*----------------------------------------------------------------*/ -/* - * Macros that operate on generic structures. The queue - * chain may be at any location within the structure, and there - * may be more than one chain. - */ - -/* - * Macro: queue_enter - * Function: - * Insert a new element at the tail of the queue. - * Header: - * void queue_enter(q, elt, type, field) - * queue_t q; - * <type> elt; - * <type> is what's in our queue - * <field> is the chain field in (*<type>) - */ -#define queue_enter(head, elt, type, field) \ -{ \ - register queue_entry_t prev; \ - \ - prev = (head)->prev; \ - if ((head) == prev) { \ - (head)->next = (queue_entry_t) (elt); \ - } \ - else { \ - ((type)prev)->field.next = (queue_entry_t)(elt);\ - } \ - (elt)->field.prev = prev; \ - (elt)->field.next = head; \ - (head)->prev = (queue_entry_t) elt; \ -} - -/* - * Macro: queue_enter_first - * Function: - * Insert a new element at the head of the queue. - * Header: - * void queue_enter_first(q, elt, type, field) - * queue_t q; - * <type> elt; - * <type> is what's in our queue - * <field> is the chain field in (*<type>) - */ -#define queue_enter_first(head, elt, type, field) \ -{ \ - register queue_entry_t next; \ - \ - next = (head)->next; \ - if ((head) == next) { \ - (head)->prev = (queue_entry_t) (elt); \ - } \ - else { \ - ((type)next)->field.prev = (queue_entry_t)(elt);\ - } \ - (elt)->field.next = next; \ - (elt)->field.prev = head; \ - (head)->next = (queue_entry_t) elt; \ -} - -/* - * Macro: queue_field [internal use only] - * Function: - * Find the queue_chain_t (or queue_t) for the - * given element (thing) in the given queue (head) - */ -#define queue_field(head, thing, type, field) \ - (((head) == (thing)) ? (head) : &((type)(thing))->field) - -/* - * Macro: queue_remove - * Function: - * Remove an arbitrary item from the queue. - * Header: - * void queue_remove(q, qe, type, field) - * arguments as in queue_enter - */ -#define queue_remove(head, elt, type, field) \ -{ \ - register queue_entry_t next, prev; \ - \ - next = (elt)->field.next; \ - prev = (elt)->field.prev; \ - \ - if ((head) == next) \ - (head)->prev = prev; \ - else \ - ((type)next)->field.prev = prev; \ - \ - if ((head) == prev) \ - (head)->next = next; \ - else \ - ((type)prev)->field.next = next; \ -} - -/* - * Macro: queue_remove_first - * Function: - * Remove and return the entry at the head of - * the queue. - * Header: - * queue_remove_first(head, entry, type, field) - * entry is returned by reference - */ -#define queue_remove_first(head, entry, type, field) \ -{ \ - register queue_entry_t next; \ - \ - (entry) = (type) ((head)->next); \ - next = (entry)->field.next; \ - \ - if ((head) == next) \ - (head)->prev = (head); \ - else \ - ((type)(next))->field.prev = (head); \ - (head)->next = next; \ -} - -/* - * Macro: queue_remove_last - * Function: - * Remove and return the entry at the tail of - * the queue. - * Header: - * queue_remove_last(head, entry, type, field) - * entry is returned by reference - */ -#define queue_remove_last(head, entry, type, field) \ -{ \ - register queue_entry_t prev; \ - \ - (entry) = (type) ((head)->prev); \ - prev = (entry)->field.prev; \ - \ - if ((head) == prev) \ - (head)->next = (head); \ - else \ - ((type)(prev))->field.next = (head); \ - (head)->prev = prev; \ -} - -/* - * Macro: queue_assign - */ -#define queue_assign(to, from, type, field) \ -{ \ - ((type)((from)->prev))->field.next = (to); \ - ((type)((from)->next))->field.prev = (to); \ - *to = *from; \ -} - -/* - * Macro: queue_iterate - * Function: - * iterate over each item in the queue. - * Generates a 'for' loop, setting elt to - * each item in turn (by reference). - * Header: - * queue_iterate(q, elt, type, field) - * queue_t q; - * <type> elt; - * <type> is what's in our queue - * <field> is the chain field in (*<type>) - */ -#define queue_iterate(head, elt, type, field) \ - for ((elt) = (type) queue_first(head); \ - !queue_end((head), (queue_entry_t)(elt)); \ - (elt) = (type) queue_next(&(elt)->field)) - -#endif /* _KERN_QUEUE_H_ */ diff --git a/eth-filter/util.h b/eth-filter/util.h deleted file mode 100644 index de23710a..00000000 --- a/eth-filter/util.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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 UTIL_H -#define UTIL_H - -#include <stdio.h> - -#include <sys/types.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <netinet/ip.h> - -#ifdef DEBUG - -#define debug(format, ...) do \ -{ \ - char buf[1024]; \ - snprintf (buf, 1024, "filter: %s", format); \ - fprintf (stderr , buf, ## __VA_ARGS__); \ - fflush (stderr); \ -} while (0) - -#else - -#define debug(format, ...) do {} while (0) - -#endif - -#define ETH_ALEN 6 /* Octets in one ethernet addr */ - -struct ethhdr -{ - unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ - unsigned char h_source[ETH_ALEN]; /* source ether addr */ - unsigned short h_proto; /* packet type ID field */ -}; - -static inline void -print_pack (char *packet, int len) -{ -#ifdef DEBUG - struct ethhdr *ethh = (struct ethhdr *) packet; - struct iphdr *iph = (struct iphdr *)(ethh + 1); - char src_str[INET_ADDRSTRLEN]; - char dst_str[INET_ADDRSTRLEN]; - if (ntohs (ethh->h_proto) == ETH_P_IP - && len >= sizeof (struct ethhdr) + sizeof (struct iphdr)) - { - debug ("pack: get a IP packet from %s to %s\n", - inet_ntop (AF_INET, &iph->saddr, src_str, INET_ADDRSTRLEN), - inet_ntop (AF_INET, &iph->daddr, dst_str, INET_ADDRSTRLEN)); - } - else - { - debug ("pack: get a non-IP packet: %x\n", ntohs (ethh->h_proto)); - } -#endif -} - -#endif diff --git a/eth-multiplexer/ChangeLog b/eth-multiplexer/ChangeLog deleted file mode 100644 index 37371185..00000000 --- a/eth-multiplexer/ChangeLog +++ /dev/null @@ -1,341 +0,0 @@ -2009-04-18 Zheng Da <zhengda1936@gmail.com> - - * device_impl.c (ds_device_open): Create a virtual device if it - doesn't exist. - - * netfs_impl.c (new_node): Test if the lnode structure exists - before setting its field. - (lookup): Copy the device name and don't create the virtual device. - (netfs_validate_stat): Set the status with the one of the underlying - node if the node has no lnode structure. - (netfs_attempt_chmod): chmod isn't supported if the node has no lnode - structure. - (netfs_node_norefs): Free the name in netnode. - - * netfs_impl.h (net_node): Add a new field 'name'. - -2009-04-18 Zheng Da <zhengda1936@gmail.com> - - * device_impl.c (ds_device_open): Check the mode for opening the file. - - * multiplexer.c - (underlying_node_stat): New variable. - (main): Get the mapped time from Mach and set the time of the underlying - node of the translator. - - * netfs_impl.c (lookup): Set the new created node with the same permission - as the underlying node of the translator and its time. - (netfs_check_open_permissions): Check the open permission of a node - in the same way. - (netfs_attempt_unlink): Change the return value. - (netfs_attempt_rename): Likewise. - (netfs_attempt_mkdir): Likewise. - (netfs_attempt_rmdir): Likewise. - (netfs_attempt_chown): Likewise. - (netfs_attempt_chauthor): Likewise. - (netfs_attempt_mksymlink): Likewise. - (netfs_attempt_mkdev): Likewise. - (netfs_set_translator): Likewise. - (netfs_attempt_chflags): Likewise. - (netfs_attempt_set_size): Likewise. - (netfs_attempt_link): Likewise. - (netfs_attempt_mkfile): Likewise. - (netfs_attempt_write): Likewise. - (netfs_attempt_chmod): Write the code to support the change of the mode. - - * netfs_impl.h (multiplexer_maptime): Add the declaration. - -2009-01-03 Zheng Da <zhengda1936@gmail.com> - - * device_impl.c (ds_device_write): Deallocate the out-of-line data. - -2008-12-12 Zheng Da <zhengda1936@gmail.com> - - * multiplexer.c (main): Initialize the file status of the root node. - - * netfs_impl.c (netfs_validate_stat): Set the file status of the node - with the one in the light node. - - * vdev.h (dev_act_func): Define a new type. - (foreach_dev_do): Declare the function. - -2008-11-18 Zheng Da <zhengda1936@gmail.com> - - * netfs_impl.c (netfs_get_dirents): Use foreach_dev_do. - - * vdev.c (dev_head, dev_num): Hide in the file. - (dev_list_lock): New variable. - (get_dev_num): New function. - (lookup_dev_by_name): Use lock. - (foreach_dev_do): New function. - (remove_dead_port_from_dev): Use lock. - (broadcast_pack, broadcast_msg): Use foreach_dev_do. - - * vdev.h (dev_num): Remove declaration. - (get_dev_num): Add declaration. - -2008-11-13 Zheng Da <zhengda1936@gmail.com> - - * device_impl.c (ds_device_open): Use dev_port, dereference pi. - - * util.h (print_backtrace): New macro. - - * vdev.c (add_vdev): Set dev_port. - - * vdev.h (vether_device): Add dev_port. - -2008-11-12 Zheng Da <zhengda1936@gmail.com> - - * Makefile (SRCS): Updated. - - * demuxer.c: New file. - - * device_impl.c (ds_device_open): Use netfs_port_bucket. - - * make-protid.c: Deleted. - -2008-11-02 Zheng Da <zhengda1936@gmail.com> - - * Makefile (CFLAGS): Add a macro. - (SRCS): Add new C files. - (LCLHDRS): Add new H files. - (HURDLIBS): Change libraries. - - * demuxer.c: New file. - - * device_impl.c: New file. - - * make-protid.c: New file. - - * netfs_impl.c: New file. - - * netfs_impl.h: New file. - - * notify_impl.c: New file. - - * multiplexer.c: Remove the trivfs variables. Move the implementation of - notify interface. Move the implementation of device interface. - (multiplexer_thread): New functions. - (main): Run the libnetfs translator. - - * util.h (debug): Update. - - * vdev.c (lookup_dev_by_name): Use strncmp. - (add_vdev): Change its interface. - -2008-10-27 Zheng Da <zhengda1936@gmail.com> - - * README: Update. - - * bpf_impl.c (destroy_filters): New function. - - * multiplexer.c (nb_dev): Deleted. - (options): Remove the option '-v'. - (do_mach_notify_no_senders): Remove all port_info in the same way. - (ds_device_open): Create new devices if they don't exist, and decrease - their reference counts. - (ds_device_set_filter): Fix a bug. - (trivfs_goaway): Use has_vdev() to test. - (parse_opt): Remove the code of handling '-v'. - (main): Remove the code of creating virtual devices. - - * util.h (ETH_P_IP): New macro. - - * vdev.c (all_dev_close): Deleted. - (add_vdev): Link virtual device. - (destroy_vdev): New function. - - * vdev.h (vether_device): Changed. - - -2008-10-03 Zheng Da <zhengda1936@gmail.com> - - * Makefile (CFLAGS): Remove the include paths from pfinet. - - * util.h: Remove the line of including linux/if_ether.h. - (ETH_ALEN): New macro. - (ethhdr): New structure. - - * vdev.c (ETH_HLEN): New macro. - - * vdev.h: Remove the line of including linux/etherdevice.h and include util.h - -2008-10-03 Zheng Da <zhengda1936@gmail.com> - - * multiplexer.c (parse_opt): Don't create the virtual devices in case 'v'. - (main): Create the virtual devices. - - * README: Update. - -2008-10-03 Zheng Da <zhengda1936@gmail.com> - - * multiplexer.c (ds_device_write): Don't call device_write when ether_port is NULL. - (ds_device_get_status): Call dev_getstat when ether_port is NULL. - (main): If device_file isn't specified, don't open the underlying device. - -2008-09-26 Zheng Da <zhengda1936@gmail.com> - - * vdev.c (deliver_msg): Use non-block send. - -2008-09-21 Zheng Da <zhengda1936@gmail.com> - - * README: Update. - -2008-09-02 Zheng Da <zhengda1936@gmail.com> - - * ethernet.c (ether_filter): Use the original NPF filter. - -2008-9-01 Zheng Da <zhengda1936@gmail.com> - - * multiplexer.c (ds_device_write): Reverse the calling of functions. - (ds_device_get_status): Call device_get_status. - - * vdev.c (broadcast_pack): Change its function prototype. Broadcast to - all other interface. - (deliver_pack): Don't set the message header. - (broadcast_msg): Save the original message header and restore it. - (deliver_msg): Deallocate the port if mach_msg fails. - - * vdev.h (broadcast_pack): Change its function prototype. - -2008-8-29 Zheng Da <zhengda1936@gmail.com> - - * ethernet.c (ethernet_open): Use error instead of assert_perror. - - * multiplexer.c (ds_device_set_filter): Return the error. - -2008-8-28 Zheng Da <zhengda1936@gmail.com> - - * ethernet.c (NET_FLAGS): New macro. - -2008-8-22 Zheng Da <zhengda1936@gmail.com> - - * README: Update. - - * Makefile: Remove list.h. - - * multiplexer.c (do_mach_notify_no_senders): Get vether_device object - with ports_lookup_port(). - (ds_xxx_device_set_status): Likewise. - (ds_xxx_device_get_status): Likewise. - (ds_xxx_device_set_filter): Likewise. - (ds_device_write): Likewise. - (ds_device_write_inband): Likewise. - (ds_device_read): Likewise. - (ds_device_read_inband): Likewise. - (ds_device_map): Likewise. - (ds_device_set_status): Likewise. - (ds_device_get_status): Likewise. - (ds_device_set_filter): Likewise. - (do_mach_notify_dead_name): Deallocate the port. - (ds_device_open): Get the name directly from the vether_device object. - (ds_device_close): Return 0 immediately. - - * vdev.c (dev_head): Point to the head of the device list. - (print_eth_addr): Removed. - (lookup_dev_by_devport): Likewise. - (lookup_dev_by_name): Use the for loop to replace list_for_each_entry. - (remove_dead_port_from_dev): Likewise. - (all_dev_close): Likewise. - (broadcast_pack): Likewise. - (broadcast_msg): Likewise. - (add_vdev): Create the vether_device object with ports_create_port. - (has_vdev): Test if the device list is empty. - - * vdev.h: Don't include list.h. - (vether_device): Include the port_info object instead of its pointer. - (next): Replace dev_list. - - * list.h: Removed. - -2008-8-20 Zheng Da <zhengda1936@gmail.com> - - * README: Update. - - * multiplexer.c (options): Update. - -2008-8-20 Zheng Da <zhengda1936@gmail.com> - - * multiplexer.c (main): Test device_file before using it. - -2008-8-20 Zheng Da <zhengda1936@gmail.com> - - * multiplexer.c (device_file): Rename a variable. - (main): Use device_file directly. - -2008-8-19 Zheng Da <zhengda1936@gmail.com> - - * multiplexer.c (main): Generate the device file name, and use it - to open the device. - -2008-8-18 Zheng Da <zhengda1936@gmail.com> - - * README: New file. - - * multiplexer.c (options): Change the meaning of '-v' option. - (parse_opt): Change the way of handling '-v' option. - - * vdev.c (has_vdev): New function. - - * vdev.h (has_vdev): New declaration. - -2008-8-17 Zheng Da <zhengda1936@gmail.com> - - * ethernet.c (ethernet_open): Use a hard coded string for the device name. - - * multiplexer.c: Remove the option '-M'. - (parse_opt): Remove the code of handling '-M' option. - (main): Get the master device port from the device file. - -2008-8-14 Zheng Da <zhengda1936@gmail.com> - - * ChangeLog: New file. - - * multiplexer.c (vdev_portclass, other_portclass): - New variables. - (do_mach_notify_no_senders): Mark the device unused when there are no - senders for the device. - (do_mach_notify_dead_name): Return 0. - (ds_device_open): Mark the device used. - (ds_device_close): Remove the code of decreasing the count of the device. - (trivfs_goaway): Only test if all devices aren't used, and delete the code - of closing the device. - (parse_opt): Use vdev_portclass to create the virtual device. - (main): Create vdev_portclass and other_portclass, open the ethernet - device with other_portclass and create notify_pi with other_portclass. - - * vdev.c (all_dev_close): Change the way of testing if all devices are - closed. - - * vdev.h (vether_device): Replace count field with used. - -2008-8-13 Zheng Da <zhengda1936@gmail.com> - - * bpf_impl.c: New file. - - * bpf_impl.h: New file. - - * dev_stat.c: New file. - - * ethernet.c: New file. - - * ethernet.h: New file. - - * list.h: New file. - - * Makefile: New file. - - * multiplexer.c: New file. - - * queue.c: New file. - - * queue.h: New file. - - * test.c: New file. - - * util.h: New file. - - * vdev.c: New file. - - * vdev.h: New file. - diff --git a/eth-multiplexer/Makefile b/eth-multiplexer/Makefile deleted file mode 100644 index f321a619..00000000 --- a/eth-multiplexer/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 2008 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. - -dir := eth-multiplexer -makemode := server -target = eth-multiplexer - -#CFLAGS += -DDEBUG -SRCS = ethernet.c vdev.c multiplexer.c dev_stat.c netfs_impl.c notify_impl.c device_impl.c demuxer.c -MIGSTUBS = ourdeviceServer.o notifyServer.o -OBJS = $(SRCS:.c=.o) $(MIGSTUBS) -LCLHDRS = ethernet.h util.h vdev.h netfs_impl.h -DIST_FILES = ourdevice.defs notify.defs -HURDLIBS=ports fshelp shouldbeinlibc netfs bpf - -CFLAGS += -I$(top_srcdir)/libbpf - -include ../Makeconf - -ourdevice.defs: device.defs - $(CPP) $(CPPFLAGS) -x c $< | sed -e '/out[ ]*device[ ]*:[ ]*device_t/s/device_t/mach_port_send_t/' > $@ - diff --git a/eth-multiplexer/README b/eth-multiplexer/README deleted file mode 100644 index 0024a937..00000000 --- a/eth-multiplexer/README +++ /dev/null @@ -1,27 +0,0 @@ -[Introduction] - -eth-multiplexer is a network multiplexer. It creates virtual ethernet interface and dispatches the packet to the right user program that opens its virtual interface. It also works as a bridge to connect the real ethernet interface and the virtual ones. - - -[Usage] - -Usage: eth-multiplexer [OPTION...] -Hurd multiplexer server. - - -i, --interface=DEVICE Network interface to use - -?, --help Give this help list - --usage Give a short usage message - -V, --version Print program version - -Mandatory or optional arguments to long options are also mandatory or optional -for any corresponding short options. - - -The '-i' option specifies the network interface the translator sits on. eth-multiplexer can only connect to one network interface and the '-i' option should be only used once. DEVICE is a device file that is created by the devnode translator. - - -[Internal] - -eth-multiplexer implements the server side functions in device.defs, so other programs can access the virtual device as other devices. All information about the virtual interface is kept in the vether_device structure. -When eth-multiplexer gets a packet from a virtual interface (which happens in ds_device_write) or from the real interface (which happens in ethernet_demuxer), it sends the packet to all other interfaces. eth-multipexer has BPF filters for each client. The BPF filter decides whether to deliver the packet. The packet delivery is done by deliver_pack(). There is no filter for the real network interface in eth-multiplexer, so every packet from the virtual interface will be sent to the real interface whose filter will decide the destination of the packet. -eth-multiplexer sets the real interface into the promiscuous mode, so eth-multiplexer can receive the packet with the virtual interface's hardware address from the real interface. diff --git a/eth-multiplexer/demuxer.c b/eth-multiplexer/demuxer.c deleted file mode 100644 index 1f671b20..00000000 --- a/eth-multiplexer/demuxer.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - 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 <hurd/netfs.h> - -int -netfs_demuxer (mach_msg_header_t *inp, - mach_msg_header_t *outp) -{ - int netfs_fs_server (mach_msg_header_t *, mach_msg_header_t *); - int netfs_io_server (mach_msg_header_t *, mach_msg_header_t *); - int netfs_fsys_server (mach_msg_header_t *, mach_msg_header_t *); - int netfs_ifsock_server (mach_msg_header_t *, mach_msg_header_t *); - int device_server (mach_msg_header_t *, mach_msg_header_t *); - - return (netfs_io_server (inp, outp) - || netfs_fs_server (inp, outp) - || ports_notify_server (inp, outp) - || netfs_fsys_server (inp, outp) - || ports_interrupt_server (inp, outp) - || netfs_ifsock_server (inp, outp) - || device_server (inp, outp)); -} - diff --git a/eth-multiplexer/dev_stat.c b/eth-multiplexer/dev_stat.c deleted file mode 100644 index 43c68d6a..00000000 --- a/eth-multiplexer/dev_stat.c +++ /dev/null @@ -1,101 +0,0 @@ - /* - * Mach Operating System - * Copyright (c) 1993-1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * Author: David B. Golub, Carnegie Mellon University - * Date: 3/98 - * - * Network IO. - * - * Packet filter code taken from vaxif/enet.c written - * CMU and Stanford. - */ - -/* the code copied from device/net_io.c in Mach */ - -#include <string.h> -#include <arpa/inet.h> - -#include <mach.h> - -#include "vdev.h" - -io_return_t -dev_getstat(struct vether_device *ifp, dev_flavor_t flavor, - dev_status_t status, natural_t *count) -{ - switch (flavor) { - case NET_STATUS: - { - register struct net_status *ns = (struct net_status *)status; - - if (*count < NET_STATUS_COUNT) - return (D_INVALID_OPERATION); - - ns->min_packet_size = ifp->if_header_size; - ns->max_packet_size = ifp->if_header_size + ifp->if_mtu; - ns->header_format = ifp->if_header_format; - ns->header_size = ifp->if_header_size; - ns->address_size = ifp->if_address_size; - ns->flags = ifp->if_flags; - ns->mapped_size = 0; - - *count = NET_STATUS_COUNT; - break; - } - case NET_ADDRESS: - { - register int addr_byte_count; - register int addr_int_count; - register int i; - - addr_byte_count = ifp->if_address_size; - addr_int_count = (addr_byte_count + (sizeof(int)-1)) - / sizeof(int); - - if (*count < addr_int_count) { - return (D_INVALID_OPERATION); - } - - memcpy(status, ifp->if_address, addr_byte_count); - if (addr_byte_count < addr_int_count * sizeof(int)) - memset((char *)status + addr_byte_count, 0, - (addr_int_count * sizeof(int) - - addr_byte_count)); - - for (i = 0; i < addr_int_count; i++) { - register int word; - - word = status[i]; - status[i] = htonl(word); - } - *count = addr_int_count; - break; - } - default: - return (D_INVALID_OPERATION); - } - return (D_SUCCESS); -} diff --git a/eth-multiplexer/device.h b/eth-multiplexer/device.h deleted file mode 100644 index db0798d6..00000000 --- a/eth-multiplexer/device.h +++ /dev/null @@ -1,336 +0,0 @@ -#ifndef _device_user_ -#define _device_user_ - -/* Module device */ - -#include <mach/kern_return.h> -#include <mach/port.h> -#include <mach/message.h> - -#include <mach/std_types.h> -#include <mach/mach_types.h> -#include <device/device_types.h> -#include <device/net_status.h> - -/* Routine device_open */ -#ifdef mig_external -mig_external -#else -extern -#endif -kern_return_t device_open -#if defined(LINTLIBRARY) - (master_port, mode, name, device) - mach_port_t master_port; - dev_mode_t mode; - dev_name_t name; - mach_port_t *device; -{ return device_open(master_port, mode, name, device); } -#else -( - mach_port_t master_port, - dev_mode_t mode, - dev_name_t name, - mach_port_t *device -); -#endif - -/* Routine device_close */ -#ifdef mig_external -mig_external -#else -extern -#endif -kern_return_t device_close -#if defined(LINTLIBRARY) - (device) - mach_port_t device; -{ return device_close(device); } -#else -( - mach_port_t device -); -#endif - -/* Routine device_write */ -#ifdef mig_external -mig_external -#else -extern -#endif -kern_return_t device_write -#if defined(LINTLIBRARY) - (device, mode, recnum, data, dataCnt, bytes_written) - mach_port_t device; - dev_mode_t mode; - recnum_t recnum; - io_buf_ptr_t data; - mach_msg_type_number_t dataCnt; - int *bytes_written; -{ return device_write(device, mode, recnum, data, dataCnt, bytes_written); } -#else -( - mach_port_t device, - dev_mode_t mode, - recnum_t recnum, - io_buf_ptr_t data, - mach_msg_type_number_t dataCnt, - int *bytes_written -); -#endif - -/* Routine device_write_inband */ -#ifdef mig_external -mig_external -#else -extern -#endif -kern_return_t device_write_inband -#if defined(LINTLIBRARY) - (device, mode, recnum, data, dataCnt, bytes_written) - mach_port_t device; - dev_mode_t mode; - recnum_t recnum; - io_buf_ptr_inband_t data; - mach_msg_type_number_t dataCnt; - int *bytes_written; -{ return device_write_inband(device, mode, recnum, data, dataCnt, bytes_written); } -#else -( - mach_port_t device, - dev_mode_t mode, - recnum_t recnum, - io_buf_ptr_inband_t data, - mach_msg_type_number_t dataCnt, - int *bytes_written -); -#endif - -/* Routine device_read */ -#ifdef mig_external -mig_external -#else -extern -#endif -kern_return_t device_read -#if defined(LINTLIBRARY) - (device, mode, recnum, bytes_wanted, data, dataCnt) - mach_port_t device; - dev_mode_t mode; - recnum_t recnum; - int bytes_wanted; - io_buf_ptr_t *data; - mach_msg_type_number_t *dataCnt; -{ return device_read(device, mode, recnum, bytes_wanted, data, dataCnt); } -#else -( - mach_port_t device, - dev_mode_t mode, - recnum_t recnum, - int bytes_wanted, - io_buf_ptr_t *data, - mach_msg_type_number_t *dataCnt -); -#endif - -/* Routine device_read_inband */ -#ifdef mig_external -mig_external -#else -extern -#endif -kern_return_t device_read_inband -#if defined(LINTLIBRARY) - (device, mode, recnum, bytes_wanted, data, dataCnt) - mach_port_t device; - dev_mode_t mode; - recnum_t recnum; - int bytes_wanted; - io_buf_ptr_inband_t data; - mach_msg_type_number_t *dataCnt; -{ return device_read_inband(device, mode, recnum, bytes_wanted, data, dataCnt); } -#else -( - mach_port_t device, - dev_mode_t mode, - recnum_t recnum, - int bytes_wanted, - io_buf_ptr_inband_t data, - mach_msg_type_number_t *dataCnt -); -#endif - -/* Routine xxx_device_set_status */ -#ifdef mig_external -mig_external -#else -extern -#endif -kern_return_t xxx_device_set_status -#if defined(LINTLIBRARY) - (device, flavor, status, statusCnt) - mach_port_t device; - dev_flavor_t flavor; - dev_status_t status; - mach_msg_type_number_t statusCnt; -{ return xxx_device_set_status(device, flavor, status, statusCnt); } -#else -( - mach_port_t device, - dev_flavor_t flavor, - dev_status_t status, - mach_msg_type_number_t statusCnt -); -#endif - -/* Routine xxx_device_get_status */ -#ifdef mig_external -mig_external -#else -extern -#endif -kern_return_t xxx_device_get_status -#if defined(LINTLIBRARY) - (device, flavor, status, statusCnt) - mach_port_t device; - dev_flavor_t flavor; - dev_status_t status; - mach_msg_type_number_t *statusCnt; -{ return xxx_device_get_status(device, flavor, status, statusCnt); } -#else -( - mach_port_t device, - dev_flavor_t flavor, - dev_status_t status, - mach_msg_type_number_t *statusCnt -); -#endif - -/* Routine xxx_device_set_filter */ -#ifdef mig_external -mig_external -#else -extern -#endif -kern_return_t xxx_device_set_filter -#if defined(LINTLIBRARY) - (device, receive_port, receive_portPoly, priority, filter, filterCnt) - mach_port_t device; - mach_port_t receive_port; - mach_msg_type_name_t receive_portPoly; - int priority; - filter_array_t filter; - mach_msg_type_number_t filterCnt; -{ return xxx_device_set_filter(device, receive_port, receive_portPoly, priority, filter, filterCnt); } -#else -( - mach_port_t device, - mach_port_t receive_port, - mach_msg_type_name_t receive_portPoly, - int priority, - filter_array_t filter, - mach_msg_type_number_t filterCnt -); -#endif - -/* Routine device_map */ -#ifdef mig_external -mig_external -#else -extern -#endif -kern_return_t device_map -#if defined(LINTLIBRARY) - (device, prot, offset, size, pager, unmap) - mach_port_t device; - vm_prot_t prot; - vm_offset_t offset; - vm_size_t size; - mach_port_t *pager; - int unmap; -{ return device_map(device, prot, offset, size, pager, unmap); } -#else -( - mach_port_t device, - vm_prot_t prot, - vm_offset_t offset, - vm_size_t size, - mach_port_t *pager, - int unmap -); -#endif - -/* Routine device_set_status */ -#ifdef mig_external -mig_external -#else -extern -#endif -kern_return_t device_set_status -#if defined(LINTLIBRARY) - (device, flavor, status, statusCnt) - mach_port_t device; - dev_flavor_t flavor; - dev_status_t status; - mach_msg_type_number_t statusCnt; -{ return device_set_status(device, flavor, status, statusCnt); } -#else -( - mach_port_t device, - dev_flavor_t flavor, - dev_status_t status, - mach_msg_type_number_t statusCnt -); -#endif - -/* Routine device_get_status */ -#ifdef mig_external -mig_external -#else -extern -#endif -kern_return_t device_get_status -#if defined(LINTLIBRARY) - (device, flavor, status, statusCnt) - mach_port_t device; - dev_flavor_t flavor; - dev_status_t status; - mach_msg_type_number_t *statusCnt; -{ return device_get_status(device, flavor, status, statusCnt); } -#else -( - mach_port_t device, - dev_flavor_t flavor, - dev_status_t status, - mach_msg_type_number_t *statusCnt -); -#endif - -/* Routine device_set_filter */ -#ifdef mig_external -mig_external -#else -extern -#endif -kern_return_t device_set_filter -#if defined(LINTLIBRARY) - (device, receive_port, receive_portPoly, priority, filter, filterCnt) - mach_port_t device; - mach_port_t receive_port; - mach_msg_type_name_t receive_portPoly; - int priority; - filter_array_t filter; - mach_msg_type_number_t filterCnt; -{ return device_set_filter(device, receive_port, receive_portPoly, priority, filter, filterCnt); } -#else -( - mach_port_t device, - mach_port_t receive_port, - mach_msg_type_name_t receive_portPoly, - int priority, - filter_array_t filter, - mach_msg_type_number_t filterCnt -); -#endif - -#endif /* not defined(_device_user_) */ diff --git a/eth-multiplexer/device_impl.c b/eth-multiplexer/device_impl.c deleted file mode 100644 index 953fca70..00000000 --- a/eth-multiplexer/device_impl.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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 <mach.h> -#include <hurd.h> -#include <hurd/ports.h> -#include <hurd/netfs.h> -#include <device/device.h> - -#include "ethernet.h" -#include "vdev.h" -#include "ourdevice_S.h" -#include "notify_S.h" -#include "bpf_impl.h" -#include "netfs_impl.h" -#include "util.h" - -extern struct port_bucket *port_bucket; -extern struct port_class *vdev_portclass; -extern struct port_class *other_portclass; -extern struct port_info *notify_pi; - -/* Implementation of device interface */ -kern_return_t -ds_xxx_device_set_status (device_t device, dev_flavor_t flavor, - dev_status_t status, size_t statu_cnt) -{ - struct vether_device *vdev = ports_lookup_port (port_bucket, device, - vdev_portclass); - if (vdev == NULL) - return D_NO_SUCH_DEVICE; - ports_port_deref (vdev); - return D_INVALID_OPERATION; -} - -kern_return_t -ds_xxx_device_get_status (device_t device, dev_flavor_t flavor, - dev_status_t status, size_t *statuscnt) -{ - struct vether_device *vdev = ports_lookup_port (port_bucket, device, - vdev_portclass); - if (vdev == NULL) - return D_NO_SUCH_DEVICE; - ports_port_deref (vdev); - return D_INVALID_OPERATION; -} - -kern_return_t -ds_xxx_device_set_filter (device_t device, mach_port_t rec, - int pri, filter_array_t filt, size_t len) -{ - struct vether_device *vdev = ports_lookup_port (port_bucket, device, - vdev_portclass); - if (vdev == NULL) - return D_NO_SUCH_DEVICE; - ports_port_deref (vdev); - return D_INVALID_OPERATION; -} - -/* - * This function is currently running in the multithread environment, - * it should be protected by locks. - */ -kern_return_t -ds_device_open (mach_port_t master_port, mach_port_t reply_port, - mach_msg_type_name_t reply_portPoly, - dev_mode_t mode, dev_name_t name, mach_port_t *device, - mach_msg_type_name_t *devicetype) -{ - struct vether_device *dev; - int openstat; - int right_mode = 1; - struct protid *pi = ports_lookup_port (netfs_port_bucket, master_port, 0); - if (pi == NULL) - return D_NO_SUCH_DEVICE; - - /* If the virtual device hasn't been created yet, - * create it now. */ - if (pi->po->np->nn->ln == NULL) - { - extern struct port_bucket *port_bucket; - extern struct port_class *vdev_portclass; - extern struct stat underlying_node_stat; - static int ino_count = 0; - /* Create a new light node (virtual device). */ - struct lnode *ln = (struct lnode *) add_vdev (pi->po->np->nn->name, - sizeof (*ln), - vdev_portclass, - port_bucket); - if (ln == NULL) - { - ports_port_deref (pi); - return D_NO_MEMORY; - } - memset (&ln->st, 0, sizeof (ln->st)); - ln->st.st_ino = ++ino_count; - ln->st.st_mode = S_IFCHR | (underlying_node_stat.st_mode & ~S_IFMT); - ln->st.st_ctime = ln->st.st_mtime = ln->st.st_atime = time (NULL); - fshelp_touch (&ln->st, TOUCH_ATIME|TOUCH_MTIME|TOUCH_CTIME, - multiplexer_maptime); - pi->po->np->nn->ln = ln; - } - - dev = (struct vether_device *) pi->po->np->nn->ln; - /* check the mode */ - openstat = pi->po->openstat; - if (mode & D_READ && !(openstat & O_READ)) - right_mode = 0; - if (mode & D_WRITE && !(openstat & O_WRITE)) - right_mode = 0; - ports_port_deref (pi); - - if (dev) - { - if (!right_mode) - return EBADF; - *device = dev->dev_port; - *devicetype = MACH_MSG_TYPE_MAKE_SEND; - return 0; - } - return D_NO_SUCH_DEVICE; -} - -kern_return_t -ds_device_close (device_t device) -{ - return 0; -} - -kern_return_t -ds_device_write (device_t device, mach_port_t reply_port, - mach_msg_type_name_t reply_type, dev_mode_t mode, - recnum_t recnum, io_buf_ptr_t data, size_t datalen, - int *bytes_written) -{ - kern_return_t ret = 0; - struct vether_device *vdev = ports_lookup_port (port_bucket, device, - vdev_portclass); - if (vdev == NULL) - { - vm_deallocate (mach_task_self (), data, datalen); - return D_NO_SUCH_DEVICE; - } - /* The packet is forwarded to all virtual interfaces and - * the interface which the multiplexer connects to. */ - broadcast_pack (data, datalen, vdev); - *bytes_written = datalen; - if(ether_port != MACH_PORT_NULL) - ret = device_write (ether_port, mode , recnum , - data, datalen, bytes_written); - /* The data in device_write() is transmifered out of line, - * so the server-side function has to deallocate it. */ - vm_deallocate (mach_task_self (), data, datalen); - ports_port_deref (vdev); - return ret; -} - -kern_return_t -ds_device_write_inband (device_t device, mach_port_t reply_port, - mach_msg_type_name_t reply_type, dev_mode_t mode, - recnum_t recnum, io_buf_ptr_inband_t data, - size_t datalen, int *bytes_written) -{ - struct vether_device *vdev = ports_lookup_port (port_bucket, device, - vdev_portclass); - if (vdev == NULL) - return D_NO_SUCH_DEVICE; - ports_port_deref (vdev); - return D_INVALID_OPERATION; -} - -kern_return_t -ds_device_read (device_t device, mach_port_t reply_port, - mach_msg_type_name_t reply_type, dev_mode_t mode, - recnum_t recnum, int bytes_wanted, - io_buf_ptr_t *data, size_t *datalen) -{ - struct vether_device *vdev = ports_lookup_port (port_bucket, device, - vdev_portclass); - if (vdev == NULL) - return D_NO_SUCH_DEVICE; - ports_port_deref (vdev); - return D_INVALID_OPERATION; -} - -kern_return_t -ds_device_read_inband (device_t device, mach_port_t reply_port, - mach_msg_type_name_t reply_type, dev_mode_t mode, - recnum_t recnum, int bytes_wanted, - io_buf_ptr_inband_t data, size_t *datalen) -{ - struct vether_device *vdev = ports_lookup_port (port_bucket, device, - vdev_portclass); - if (vdev == NULL) - return D_NO_SUCH_DEVICE; - ports_port_deref (vdev); - return D_INVALID_OPERATION; -} - -kern_return_t -ds_device_map (device_t device, vm_prot_t prot, vm_offset_t offset, - vm_size_t size, memory_object_t *pager, int unmap) -{ - struct vether_device *vdev = ports_lookup_port (port_bucket, device, - vdev_portclass); - if (vdev == NULL) - return D_NO_SUCH_DEVICE; - ports_port_deref (vdev); - return D_INVALID_OPERATION; -} - -kern_return_t -ds_device_set_status (device_t device, dev_flavor_t flavor, - dev_status_t status, size_t statuslen) -{ - struct vether_device *vdev = ports_lookup_port (port_bucket, device, - vdev_portclass); - if (vdev == NULL) - return D_NO_SUCH_DEVICE; - ports_port_deref (vdev); - return D_INVALID_OPERATION; -} - -kern_return_t -ds_device_get_status (device_t device, dev_flavor_t flavor, - dev_status_t status, size_t *statuslen) -{ - extern io_return_t dev_getstat (struct vether_device *, dev_flavor_t, - dev_status_t, natural_t *); - kern_return_t ret = 0; - struct vether_device *vdev = ports_lookup_port (port_bucket, device, - vdev_portclass); - if (vdev == NULL) - return D_NO_SUCH_DEVICE; - if(ether_port != MACH_PORT_NULL) - ret = device_get_status (ether_port, flavor, status, statuslen); - else - ret = dev_getstat (vdev, flavor, status, statuslen); - ports_port_deref (vdev); - return ret; -} - -kern_return_t -ds_device_set_filter (device_t device, mach_port_t receive_port, - int priority, filter_array_t filter, size_t filterlen) -{ - mach_port_t tmp; - kern_return_t err; - struct vether_device *vdev = ports_lookup_port (port_bucket, device, - vdev_portclass); - if (vdev == NULL) - return D_NO_SUCH_DEVICE; - err = mach_port_request_notification (mach_task_self (), receive_port, - MACH_NOTIFY_DEAD_NAME, 0, - ports_get_right (notify_pi), - MACH_MSG_TYPE_MAKE_SEND_ONCE, &tmp); - if (err != KERN_SUCCESS) - goto out; - if (tmp != MACH_PORT_NULL) - mach_port_deallocate (mach_task_self (), tmp); - err = net_set_filter (&vdev->port_list, receive_port, - priority, filter, filterlen); -out: - ports_port_deref (vdev); - return err; -} diff --git a/eth-multiplexer/ethernet.c b/eth-multiplexer/ethernet.c deleted file mode 100644 index 32c5589f..00000000 --- a/eth-multiplexer/ethernet.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - Copyright (C) 1995, 1996, 1998, 1999, 2000, 2002, 2007, 2008 - Free Software Foundation, Inc. - - Written by Zheng Da - - Based on pfinet/ethernet.c, 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 <string.h> -#include <error.h> -#include <assert.h> -#include <net/if.h> -#include <sys/ioctl.h> - -#include <hurd/ports.h> -#include <device/device.h> -#include <device/net_status.h> - -#include "ethernet.h" -#include "vdev.h" -#include "util.h" - -#define ETH_HLEN 14 - -static struct port_info *readpt; - -/* Port for writing message to the real network interface. */ -mach_port_t ether_port; -/* Port for receiving messages from the interface. */ -static mach_port_t readptname; - -/* The BPF instruction allows IP and ARP packets */ -static struct bpf_insn ether_filter[] = -{ - {NETF_IN|NETF_BPF, /* Header. */ 0, 0, 0}, - {40, 0, 0, 12}, - {21, 1, 0, 2054}, - {21, 0, 1, 2048}, - {6, 0, 0, 1500}, - {6, 0, 0, 0} -}; -static int ether_filter_len = sizeof (ether_filter) / sizeof (short); - -int ethernet_demuxer (mach_msg_header_t *inp, - mach_msg_header_t *outp) -{ - struct net_rcv_msg *msg = (struct net_rcv_msg *) inp; - - if (inp->msgh_id != NET_RCV_MSG_ID) - return 0; - - broadcast_msg (msg); - /* The data from the underlying network is inside the message, - * so we don't need to deallocate the data. */ - return 1; -} - -int set_promisc (char *dev_name, mach_port_t ether_port, int is_promisc) -{ -#ifndef NET_FLAGS -#define NET_FLAGS (('n'<<16) + 4) -#endif - short flags; - int ret; - size_t count; - - debug ("set_promisc is called, is_promisc: %d\n", is_promisc); - count = sizeof (flags); - ret = device_get_status (ether_port, NET_FLAGS, (dev_status_t) &flags, - &count); - if (ret) - { - error (0, ret, "device_get_status"); - return -1; - } - if (is_promisc) - flags |= IFF_PROMISC; - else - flags &= ~IFF_PROMISC; - ret = device_set_status(ether_port, NET_FLAGS, (dev_status_t) &flags, - sizeof (flags)); - if (ret) - { - error (0, ret, "device_set_status"); - return -1; - } - return 0; -} - -int ethernet_open (char *dev_name, device_t master_device, - struct port_bucket *etherport_bucket, - struct port_class *etherreadclass) -{ - error_t err; - - assert (ether_port == MACH_PORT_NULL); - - err = ports_create_port (etherreadclass, etherport_bucket, - sizeof (struct port_info), &readpt); - if (err) - error (2, err, "ports_create_port"); - readptname = ports_get_right (readpt); - mach_port_insert_right (mach_task_self (), readptname, readptname, - MACH_MSG_TYPE_MAKE_SEND); - - mach_port_set_qlimit (mach_task_self (), readptname, MACH_PORT_QLIMIT_MAX); - - err = device_open (master_device, D_WRITE | D_READ, "eth", ðer_port); - mach_port_deallocate (mach_task_self (), master_device); - if (err) - error (2, err, "device_open: %s", dev_name); - - err = device_set_filter (ether_port, ports_get_right (readpt), - MACH_MSG_TYPE_MAKE_SEND, 0, - (unsigned short *)ether_filter, ether_filter_len); - if (err) - error (2, err, "device_set_filter: %s", dev_name); - - set_promisc (dev_name, ether_port, 1); - return 0; -} - -int ethernet_close (char *dev_name) -{ - set_promisc (dev_name, ether_port, 0); - return 0; -} - diff --git a/eth-multiplexer/ethernet.h b/eth-multiplexer/ethernet.h deleted file mode 100644 index 04b41e38..00000000 --- a/eth-multiplexer/ethernet.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copyright (C) 2008 - Free Software Foundation, Inc. - - Written by Zheng Da. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ - -#ifndef ETHERNET_H -#define ETHERNET_H - -#include <netinet/in.h> -#include <stdlib.h> - -extern mach_port_t ether_port; - -int ethernet_open (char *dev_name, device_t master_device, - struct port_bucket *etherport_bucket, - struct port_class *etherreadclass); -int ethernet_close (char *dev_name); -int ethernet_demuxer (mach_msg_header_t *inp, - mach_msg_header_t *outp); - -#endif - diff --git a/eth-multiplexer/multiplexer.c b/eth-multiplexer/multiplexer.c deleted file mode 100644 index 3ea1408c..00000000 --- a/eth-multiplexer/multiplexer.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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. */ - -/* - * The multiplexer server provides the virtual network interface. - * When it gets a packet, it forwards it to every other network interface, - * the ones that are created by itself or that it connects to. - * BPF is ported to the multiplexer to help deliver packets - * to the right pfinet. - */ - -#include <argz.h> -#include <argp.h> -#include <errno.h> -#include <error.h> -#include <stdlib.h> -#include <fcntl.h> - -#include <hurd.h> -#include <mach.h> -#include <version.h> -#include <device/device.h> -#include <hurd/ports.h> -#include <hurd/netfs.h> - -#include "ethernet.h" -#include "vdev.h" -#include "ourdevice_S.h" -#include "notify_S.h" -#include "bpf_impl.h" -#include "netfs_impl.h" -#include "util.h" - -/* The device which the multiplexer connects to */ -static char *device_file; - -const char *argp_program_version = "eth-multiplexer 0.1"; -const char *argp_program_bug_address = "<bug-hurd@gnu.org>"; -static const char doc[] = "Hurd multiplexer server."; -static const struct argp_option options[] = -{ - {"interface", 'i', "DEVICE", 0, - "Network interface to use", 2}, - {0} -}; - -/* Port bucket we service requests on. */ -struct port_bucket *port_bucket; -struct port_class *other_portclass; -struct port_class *vdev_portclass; -struct port_info *notify_pi; - -int netfs_maxsymlinks = 12; -char *netfs_server_name = "multiplexer"; -char *netfs_server_version = HURD_VERSION; -file_t root_file; -struct lnode root; -struct stat underlying_node_stat; - -static int -multiplexer_demuxer (mach_msg_header_t *inp, - mach_msg_header_t *outp) -{ - int device_server (mach_msg_header_t *, mach_msg_header_t *); - int notify_server (mach_msg_header_t *, mach_msg_header_t *); - - return (device_server (inp, outp) - || notify_server (inp, outp) - || ethernet_demuxer (inp, outp)); -} - -static any_t -multiplexer_thread (any_t arg) -{ - ports_manage_port_operations_one_thread (port_bucket, - multiplexer_demuxer, - 0); - return 0; -} - -static error_t -parse_opt (int opt, char *arg, struct argp_state *state) -{ - switch (opt) - { - case 'i': - device_file = arg; - break; - case ARGP_KEY_ERROR: - case ARGP_KEY_SUCCESS: - case ARGP_KEY_INIT: - break; - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - -int -main (int argc, char *argv[]) -{ - error_t err; - mach_port_t bootstrap; - mach_port_t master_device; - const struct argp argp = { options, parse_opt, 0, doc }; - - port_bucket = ports_create_bucket (); - other_portclass = ports_create_class (0, 0); - vdev_portclass = ports_create_class (destroy_vdev, 0); - - argp_parse (&argp, argc, argv, 0, 0, 0); - - /* Open the network interface. */ - if (device_file) - { - master_device = file_name_lookup (device_file, 0, 0); - if (master_device == MACH_PORT_NULL) - error (1, errno, "file_name_lookup"); - - ethernet_open (device_file, master_device, port_bucket, - other_portclass); - } - - /* Prepare for the notification. */ - err = ports_create_port (other_portclass, port_bucket, - sizeof (struct port_info), ¬ify_pi); - if (err) - error (1, err, "ports_create_port for notification"); - - task_get_bootstrap_port (mach_task_self (), &bootstrap); - if (bootstrap == MACH_PORT_NULL) - error (1, 0, "must be started as a translator"); - - /* Run the multiplexer server in another thread. */ - cthread_detach (cthread_fork (multiplexer_thread, 0)); - - err = maptime_map (0, 0, &multiplexer_maptime); - if (err) - error (4, err, "Cannot map time"); - - /* Initialize netfs and start the translator. */ - netfs_init (); - - root_file = netfs_startup (bootstrap, O_READ); - err = new_node (&root, &netfs_root_node); - if (err) - error (5, err, "Cannot create root node"); - - err = io_stat (root_file, &underlying_node_stat); - if (err) - error (6, err, "Cannot stat underlying node"); - - struct stat stat = underlying_node_stat; - /* If the underlying node is not a directory, increase its permissions */ - if(!S_ISDIR(stat.st_mode)) - { - if(stat.st_mode & S_IRUSR) - stat.st_mode |= S_IXUSR; - if(stat.st_mode & S_IRGRP) - stat.st_mode |= S_IXGRP; - if(stat.st_mode & S_IROTH) - stat.st_mode |= S_IXOTH; - } - - stat.st_mode &= ~(S_ITRANS | S_IFMT); - stat.st_mode |= S_IFDIR; - netfs_root_node->nn->ln->st = stat; - fshelp_touch (&netfs_root_node->nn_stat, TOUCH_ATIME|TOUCH_MTIME|TOUCH_CTIME, - multiplexer_maptime); - - netfs_server_loop (); /* Never returns. */ - return 0; -} - -error_t -netfs_append_args (char **argz, size_t *argz_len) -{ - error_t err = 0; - -#define ADD_OPT(fmt, args...) \ - do { char buf[100]; \ - if (! err) { \ - snprintf (buf, sizeof buf, fmt , ##args); \ - err = argz_add (argz, argz_len, buf); } } while (0) - if (device_file) - ADD_OPT ("--interface=%s", device_file); -#undef ADD_OPT - return err; -} diff --git a/eth-multiplexer/netfs_impl.c b/eth-multiplexer/netfs_impl.c deleted file mode 100644 index 40015a83..00000000 --- a/eth-multiplexer/netfs_impl.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - Copyright (C) 2008, 2009 Free Software Foundation, Inc. - Written by Zheng Da. - - 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 <dirent.h> -#include <stddef.h> -#include <sys/mman.h> -#include <stdlib.h> -#include <ctype.h> - -#include <hurd/netfs.h> - -#include "netfs_impl.h" -#include "vdev.h" -#include "util.h" - -#define DIRENTS_CHUNK_SIZE (8*1024) -/* Returned directory entries are aligned to blocks this many bytes long. - * Must be a power of two. */ -#define DIRENT_ALIGN 4 -#define DIRENT_NAME_OFFS offsetof (struct dirent, d_name) - -/* Length is structure before the name + the name + '\0', all - * padded to a four-byte alignment. */ -#define DIRENT_LEN(name_len) \ - ((DIRENT_NAME_OFFS + (name_len) + 1 + (DIRENT_ALIGN - 1)) \ - & ~(DIRENT_ALIGN - 1)) - -extern struct stat underlying_node_stat; - -int -is_num (char *str) -{ - for (; *str; str++) - { - if (!isdigit (*str)) - return 0; - } - return 1; -} - -/* Make a new virtual node. Always consumes the ports. */ -error_t -new_node (struct lnode *ln, struct node **np) -{ - error_t err = 0; - struct netnode *nn = calloc (1, sizeof *nn); - struct node *node; - - if (nn == 0) - return ENOMEM; - node = netfs_make_node (nn); - if (node == 0) - { - free (nn); - *np = NULL; - return ENOMEM; - } - if (ln) - ln->n = node; - nn->ln = ln; - *np = node; - return err; -} - -struct node * -lookup (char *name) -{ - struct lnode *ln = (struct lnode *) lookup_dev_by_name (name); - - char *copied_name = malloc (strlen (name) + 1); - strcpy (copied_name, name); - if (ln) - { - new_node (ln, &ln->n); - ln->n->nn->name = copied_name; - return ln->n; - } - else - { - struct node *n; - new_node (ln, &n); - n->nn->name = copied_name; - return n; - } -} - -/* Attempt to create a file named NAME in DIR for USER with MODE. Set *NODE - to the new node upon return. On any error, clear *NODE. *NODE should be - locked on success; no matter what, unlock DIR before returning. */ -error_t -netfs_attempt_create_file (struct iouser *user, struct node *dir, - char *name, mode_t mode, struct node **node) -{ - debug(""); - *node = 0; - mutex_unlock (&dir->lock); - return EOPNOTSUPP; -} - -/* Node NODE is being opened by USER, with FLAGS. NEWNODE is nonzero if we - just created this node. Return an error if we should not permit the open - to complete because of a permission restriction. */ -error_t -netfs_check_open_permissions (struct iouser *user, struct node *node, - int flags, int newnode) -{ - error_t err = 0; - - /*Cheks user's permissions*/ - if(flags & O_READ) - err = fshelp_access(&node->nn_stat, S_IREAD, user); - if(!err && (flags & O_WRITE)) - err = fshelp_access(&node->nn_stat, S_IWRITE, user); - if(!err && (flags & O_EXEC)) - err = fshelp_access(&node->nn_stat, S_IEXEC, user); - - debug("the mode of node: %o, return result: %d", - (node->nn_stat.st_mode & ~S_IFMT), err); - /*Return the result of the check*/ - return err; -} - -/* This should attempt a utimes call for the user specified by CRED on node - NODE, to change the atime to ATIME and the mtime to MTIME. */ -error_t -netfs_attempt_utimes (struct iouser *cred, struct node *node, - struct timespec *atime, struct timespec *mtime) -{ - debug(""); - return EOPNOTSUPP; -} - -/* Return the valid access types (bitwise OR of O_READ, O_WRITE, and O_EXEC) - in *TYPES for file NODE and user CRED. */ -error_t -netfs_report_access (struct iouser *cred, struct node *node, int *types) -{ - debug(""); - *types = 0; - return 0; -} - -/* Make sure that NP->nn_stat is filled with current information. CRED - identifies the user responsible for the operation. */ -error_t -netfs_validate_stat (struct node *node, struct iouser *cred) -{ - struct stat st; - - if (node->nn->ln) - st = node->nn->ln->st; - else - st = underlying_node_stat; - - debug("node: %p", node); - node->nn_translated = S_ISLNK (st.st_mode) ? S_IFLNK : 0; - node->nn_stat = st; - return 0; -} - -/* This should sync the file NODE completely to disk, for the user CRED. If - WAIT is set, return only after sync is completely finished. */ -error_t -netfs_attempt_sync (struct iouser *cred, struct node *node, int wait) -{ - debug(""); - return 0; -} - -error_t -netfs_get_dirents (struct iouser *cred, struct node *dir, - int first_entry, int max_entries, char **data, - mach_msg_type_number_t *data_len, - vm_size_t max_data_len, int *data_entries) -{ - error_t err; - int count = 0; - char *data_p; - size_t size = (max_data_len == 0 || max_data_len > DIRENTS_CHUNK_SIZE - ? DIRENTS_CHUNK_SIZE : max_data_len); - debug (""); - int - add_dirent (const char * name, ino_t ino, int type) - { - /*If the required number of dirents has not been listed yet*/ - if((max_entries == -1) || (count < max_entries)) - { - struct dirent hdr; - size_t name_len = strlen(name); - size_t sz = DIRENT_LEN(name_len); - - /*If there is no room for this dirent*/ - if ((data_p - *data) + sz > size) - { - if (max_data_len > 0) - return 1; - else - /* Try to grow our return buffer. */ - { - error_t err; - vm_address_t extension = (vm_address_t)(*data + size); - err = vm_allocate (mach_task_self (), &extension, - DIRENTS_CHUNK_SIZE, 0); - if (err) - { - munmap (*data, size); - return 1; - } - size += DIRENTS_CHUNK_SIZE; - } - } - - /*setup the dirent*/ - hdr.d_ino = ino; - hdr.d_reclen = sz; - hdr.d_type = type; - hdr.d_namlen = name_len; - memcpy(data_p, &hdr, DIRENT_NAME_OFFS); - strcpy(data_p + DIRENT_NAME_OFFS, name); - data_p += sz; - - /*count the new dirent*/ - ++count; - } - return 0; - } - int add_each_dev (struct vether_device *dev) - { - struct lnode *ln = (struct lnode *) dev; - add_dirent (ln->vdev.name, ln->st.st_ino, DT_CHR); - return 0; - } - if (dir != netfs_root_node) - return ENOTDIR; - - *data = mmap (0, size, PROT_READ | PROT_WRITE, MAP_ANON, 0, 0); - err = ((void *) *data == (void *) -1) ? errno : 0; - if (!err) - { - data_p = *data; - if (first_entry < 2 + get_dev_num ()) - { - add_dirent (".", 2, DT_DIR); - add_dirent ("..", 2, DT_DIR); - foreach_dev_do (add_each_dev); - } - - vm_address_t alloc_end = (vm_address_t)(*data + size); - vm_address_t real_end = round_page (data_p); - if (alloc_end > real_end) - munmap ((caddr_t) real_end, alloc_end - real_end); - *data_entries = count; - debug ("first_entry is %d, count is %d", first_entry, count); - *data_len = data_p - *data; - } - return err; -} - -/* Lookup NAME in DIR for USER; set *NODE to the found name upon return. If - the name was not found, then return ENOENT. On any error, clear *NODE. - (*NODE, if found, should be locked, this call should unlock DIR no matter - what.) */ -error_t netfs_attempt_lookup (struct iouser *user, struct node *dir, - char *name, struct node **node) -{ - error_t err = 0; - - debug ("dir: %p, file name: %s", dir, name); - - if (strcmp(name, ".") == 0) - { - netfs_nref(dir); - *node = dir; - return 0; - } - else if (strcmp(name, "..") == 0) - { - /*The supplied node is always root*/ - err = ENOENT; - *node = NULL; - - /*unlock the directory*/ - mutex_unlock (&dir->lock); - - /*stop here*/ - return err; - } - - *node = lookup (name); - mutex_lock (&(*node)->lock); - mutex_unlock (&dir->lock); - return 0; -} - -/* Delete NAME in DIR for USER. */ -error_t netfs_attempt_unlink (struct iouser *user, struct node *dir, - char *name) -{ - debug(""); - return EOPNOTSUPP; -} - -/* Note that in this one call, neither of the specific nodes are locked. */ -error_t netfs_attempt_rename (struct iouser *user, struct node *fromdir, - char *fromname, struct node *todir, - char *toname, int excl) -{ - debug(""); - return EOPNOTSUPP; -} - -/* Attempt to create a new directory named NAME in DIR for USER with mode - MODE. */ -error_t netfs_attempt_mkdir (struct iouser *user, struct node *dir, - char *name, mode_t mode) -{ - debug(""); - return EOPNOTSUPP; -} - -/* Attempt to remove directory named NAME in DIR for USER. */ -error_t netfs_attempt_rmdir (struct iouser *user, - struct node *dir, char *name) -{ - debug(""); - return EOPNOTSUPP; -} - -/* This should attempt a chmod call for the user specified by CRED on node - NODE, to change the owner to UID and the group to GID. */ -error_t netfs_attempt_chown (struct iouser *cred, struct node *node, - uid_t uid, uid_t gid) -{ - debug(""); - return EOPNOTSUPP; -} - -/* This should attempt a chauthor call for the user specified by CRED on node - NODE, to change the author to AUTHOR. */ -error_t netfs_attempt_chauthor (struct iouser *cred, struct node *node, - uid_t author) -{ - debug(""); - return EOPNOTSUPP; -} - -/* This should attempt a chmod call for the user specified by CRED on node - NODE, to change the mode to MODE. Unlike the normal Unix and Hurd meaning - of chmod, this function is also used to attempt to change files into other - types. If such a transition is attempted which is impossible, then return - EOPNOTSUPP. */ -error_t netfs_attempt_chmod (struct iouser *cred, struct node *node, - mode_t mode) -{ - error_t err = 0; - debug(""); - if (node->nn->ln == NULL) - return EOPNOTSUPP; - - mode &= ~S_ITRANS; - err = fshelp_isowner (&node->nn->ln->st, cred); - if (err) - return err; - mode |= node->nn->ln->st.st_mode & S_IFMT; - node->nn->ln->st.st_mode = mode; - fshelp_touch (&node->nn_stat, TOUCH_CTIME, multiplexer_maptime); - return err; -} - -/* Attempt to turn NODE (user CRED) into a symlink with target NAME. */ -error_t netfs_attempt_mksymlink (struct iouser *cred, struct node *node, - char *name) -{ - debug(""); - return EOPNOTSUPP; -} - -/* Attempt to turn NODE (user CRED) into a device. TYPE is either S_IFBLK or - S_IFCHR. */ -error_t netfs_attempt_mkdev (struct iouser *cred, struct node *node, - mode_t type, dev_t indexes) -{ - debug(""); - return EOPNOTSUPP; -} - -/* Attempt to set the passive translator record for FILE to ARGZ (of length - ARGZLEN) for user CRED. */ -error_t netfs_set_translator (struct iouser *cred, struct node *node, - char *argz, size_t argzlen) -{ - debug(""); - return EOPNOTSUPP; -} - -/* This should attempt a chflags call for the user specified by CRED on node - NODE, to change the flags to FLAGS. */ -error_t netfs_attempt_chflags (struct iouser *cred, struct node *node, - int flags) -{ - debug(""); - return EOPNOTSUPP; -} - -/* This should attempt to set the size of the file NODE (for user CRED) to - SIZE bytes long. */ -error_t netfs_attempt_set_size (struct iouser *cred, struct node *node, - off_t size) -{ - debug(""); - return EOPNOTSUPP; -} - -/*Fetches the filesystem status information*/ -error_t -netfs_attempt_statfs (struct iouser *cred, struct node *node, - struct statfs *st) -{ - debug(""); - return EOPNOTSUPP; -} - -/* This should sync the entire remote filesystem. If WAIT is set, return - only after sync is completely finished. */ -error_t netfs_attempt_syncfs (struct iouser *cred, int wait) -{ - debug(""); - return 0; -} - -/* Create a link in DIR with name NAME to FILE for USER. Note that neither - DIR nor FILE are locked. If EXCL is set, do not delete the target, but - return EEXIST if NAME is already found in DIR. */ -error_t netfs_attempt_link (struct iouser *user, struct node *dir, - struct node *file, char *name, int excl) -{ - debug(""); - return EOPNOTSUPP; -} - -/* Attempt to create an anonymous file related to DIR for USER with MODE. - Set *NODE to the returned file upon success. No matter what, unlock DIR. */ -error_t netfs_attempt_mkfile (struct iouser *user, struct node *dir, - mode_t mode, struct node **node) -{ - debug(""); - *node = 0; - mutex_unlock (&dir->lock); - return EOPNOTSUPP; -} - -/* Read the contents of NODE (a symlink), for USER, into BUF. */ -error_t netfs_attempt_readlink (struct iouser *user, struct node *node, char *buf) -{ - debug(""); - return EOPNOTSUPP; -} - -/* Read from the file NODE for user CRED starting at OFFSET and continuing for - up to *LEN bytes. Put the data at DATA. Set *LEN to the amount - successfully read upon return. */ -error_t netfs_attempt_read (struct iouser *cred, struct node *node, - off_t offset, size_t *len, void *data) -{ - debug(""); - return EOPNOTSUPP; -} - -/* Write to the file NODE for user CRED starting at OFSET and continuing for up - to *LEN bytes from DATA. Set *LEN to the amount seccessfully written upon - return. */ -error_t netfs_attempt_write (struct iouser *cred, struct node *node, - off_t offset, size_t *len, void *data) -{ - debug(""); - return EOPNOTSUPP; -} - -/* Node NP is all done; free all its associated storage. */ -void -netfs_node_norefs (struct node *node) -{ - debug("node: %p", node); - if (node->nn->ln) - node->nn->ln->n = NULL; - free (node->nn->name); - free (node->nn); - free (node); -} - diff --git a/eth-multiplexer/netfs_impl.h b/eth-multiplexer/netfs_impl.h deleted file mode 100644 index 17c66f63..00000000 --- a/eth-multiplexer/netfs_impl.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (C) 2008, 2009 Free Software Foundation, Inc. - Written by Zheng Da. - - 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 NETFS_IMPL -#define NETFS_IMPL - -#include <hurd.h> -#include <mach.h> - -#include "vdev.h" - -struct netnode -{ - struct lnode *ln; - char *name; -}; - -struct lnode -{ - struct vether_device vdev; - struct stat st; - struct node *n; -}; - -extern file_t root_file; -volatile struct mapped_time_value *multiplexer_maptime; - -error_t new_node (struct lnode *ln, struct node **np); - -#endif diff --git a/eth-multiplexer/notify_impl.c b/eth-multiplexer/notify_impl.c deleted file mode 100644 index 33725bb6..00000000 --- a/eth-multiplexer/notify_impl.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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 <hurd.h> -#include <mach.h> - -#include "vdev.h" - -/* Implementation of notify interface */ -kern_return_t -do_mach_notify_port_deleted (mach_port_t notify, - mach_port_t name) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_msg_accepted (mach_port_t notify, - mach_port_t name) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_port_destroyed (mach_port_t notify, - mach_port_t port) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_no_senders (mach_port_t notify, - mach_port_mscount_t mscount) -{ - return ports_do_mach_notify_no_senders (notify, mscount); -} - -kern_return_t -do_mach_notify_send_once (mach_port_t notify) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_dead_name (mach_port_t notify, - mach_port_t name) -{ - debug ("do_mach_notify_dead_name is called\n"); - mach_port_deallocate (mach_task_self (), name); - remove_dead_port_from_dev (name); - return 0; -} diff --git a/eth-multiplexer/test.c b/eth-multiplexer/test.c deleted file mode 100644 index bf80583f..00000000 --- a/eth-multiplexer/test.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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. */ - -#define _GNU_SOURCE - -#include <stdio.h> -#include <string.h> -#include <error.h> - -#include <hurd.h> -#include <mach.h> -#include <device/device.h> - -int -main(int argc , char *argv[]) -{ - mach_port_t device; - mach_port_t master_device; - error_t err; - - err = get_privileged_ports (0, &master_device); - if (err) - error (2, err, "cannot get device master port"); - - err = device_open (master_device, D_READ | D_WRITE, "eth0", &device); - if (err) - error (1, err, "device_open"); - printf ("the device port is %d\n", device); - - err = device_open (master_device, D_READ | D_WRITE, "eth0", &device); - if (err) - error (1, err, "device_open"); - printf ("the device port is %d\n", device); - - return 0; -} diff --git a/eth-multiplexer/util.h b/eth-multiplexer/util.h deleted file mode 100644 index c90b0f85..00000000 --- a/eth-multiplexer/util.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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 UTIL_H -#define UTIL_H - -#include <stdio.h> -#include <execinfo.h> - -#include <sys/types.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <netinet/ip.h> - -#include <mach.h> - -#ifdef DEBUG - -#define debug(format, ...) do \ -{ \ - char buf[1024]; \ - snprintf (buf, 1024, "multiplexer: %s: %s\n", __func__, format); \ - fprintf (stderr , buf, ## __VA_ARGS__); \ - fflush (stderr); \ -} while (0) - -#else - -#define debug(format, ...) do {} while (0) - -#endif - -#define print_backtrace() do \ -{ \ - size_t size; \ - void *array[30]; \ - size = backtrace (array, sizeof (array)); \ - debug ("the depth of the stack: %d", size); \ - backtrace_symbols_fd(array, size, fileno (stderr)); \ -} while (0) - -#define ETH_ALEN 6 /* Octets in one ethernet addr */ - -struct ethhdr -{ - unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ - unsigned char h_source[ETH_ALEN]; /* source ether addr */ - unsigned short h_proto; /* packet type ID field */ -}; - -static inline void -print_pack (char *packet, int len) -{ -#ifdef DEBUG -#define ETH_P_IP 0x0800 - struct ethhdr *ethh = (struct ethhdr *) packet; - struct iphdr *iph = (struct iphdr *)(ethh + 1); - char src_str[INET_ADDRSTRLEN]; - char dst_str[INET_ADDRSTRLEN]; - if (ntohs (ethh->h_proto) == ETH_P_IP - && len >= sizeof (struct ethhdr) + sizeof (struct iphdr)) - { - debug ("multiplexer: get a IP packet from %s to %s\n", - inet_ntop (AF_INET, &iph->saddr, src_str, INET_ADDRSTRLEN), - inet_ntop (AF_INET, &iph->daddr, dst_str, INET_ADDRSTRLEN)); - } - else - { - debug ("multiplexer: get a non-IP packet\n"); - } -#endif -} - -#endif diff --git a/eth-multiplexer/vdev.c b/eth-multiplexer/vdev.c deleted file mode 100644 index 29e2b4b1..00000000 --- a/eth-multiplexer/vdev.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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. */ - -/* This file implement the virtual network interface */ - -#include <string.h> -#include <stdio.h> -#include <netinet/ip.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <stdlib.h> -#include <error.h> - -#include <cthreads.h> - -#include "vdev.h" -#include "queue.h" -#include "bpf_impl.h" -#include "util.h" - -#define ETH_HLEN sizeof (struct ethhdr) - -static struct vether_device *dev_head; -static int dev_num; - -/* This lock is only used to protected the virtual device list. - * TODO every device structure should has its own lock to protect itself. */ -static struct mutex dev_list_lock = MUTEX_INITIALIZER; - -mach_msg_type_t header_type = -{ - MACH_MSG_TYPE_BYTE, - 8, - NET_HDW_HDR_MAX, - TRUE, - FALSE, - FALSE, - 0 -}; - -mach_msg_type_t packet_type = -{ - MACH_MSG_TYPE_BYTE, /* name */ - 8, /* size */ - 0, /* number */ - TRUE, /* inline */ - FALSE, /* longform */ - FALSE /* deallocate */ -}; - -int -get_dev_num () -{ - return dev_num; -} - -struct vether_device * -lookup_dev_by_name (char *name) -{ - struct vether_device *vdev; - mutex_lock (&dev_list_lock); - for (vdev = dev_head; vdev; vdev = vdev->next) - { - if (strncmp (vdev->name, name, IFNAMSIZ) == 0) - break; - } - mutex_unlock (&dev_list_lock); - return vdev; -} - -int -foreach_dev_do (int (func) (struct vether_device *)) -{ - struct vether_device *vdev; - int rval = 0; - mutex_lock (&dev_list_lock); - for (vdev = dev_head; vdev; vdev = vdev->next) - { - mutex_unlock (&dev_list_lock); - /* func() can stop the loop by returning <> 0 */ - rval = func (vdev); - mutex_lock (&dev_list_lock); - if (rval) - break; - } - mutex_unlock (&dev_list_lock); - return rval; -} - -/* Remove all filters with the dead name. */ -int -remove_dead_port_from_dev (mach_port_t dead_port) -{ - struct vether_device *vdev; - mutex_lock (&dev_list_lock); - for (vdev = dev_head; vdev; vdev = vdev->next) - { - remove_dead_filter (&vdev->port_list, - &vdev->port_list.if_rcv_port_list, dead_port); - remove_dead_filter (&vdev->port_list, - &vdev->port_list.if_snd_port_list, dead_port); - } - mutex_unlock (&dev_list_lock); - return 0; -} - -/* Add a new virtual interface to the multiplexer. */ -struct vether_device * -add_vdev (char *name, int size, - struct port_class *class, struct port_bucket *bucket) -{ - error_t err; - struct vether_device *vdev; - - if (size < sizeof (*vdev)) - size = sizeof (*vdev); - err = ports_create_port (class, bucket, size, &vdev); - if (err) - return NULL; - - vdev->dev_port = ports_get_right (vdev); - ports_port_deref (vdev); - strncpy (vdev->name, name, IFNAMSIZ); - vdev->if_header_size = ETH_HLEN; - vdev->if_mtu = ETH_MTU; - vdev->if_header_format = HDR_ETHERNET; - vdev->if_address_size = ETH_ALEN; - vdev->if_flags = 0; - vdev->if_address[0] = 0x52; - vdev->if_address[1] = 0x54; - *(int *)(vdev->if_address + 2) = random (); - - queue_init (&vdev->port_list.if_rcv_port_list); - queue_init (&vdev->port_list.if_snd_port_list); - - mutex_lock (&dev_list_lock); - vdev->next = dev_head; - dev_head = vdev; - vdev->pprev = &dev_head; - if (vdev->next) - vdev->next->pprev = &vdev->next; - dev_num++; - mutex_unlock (&dev_list_lock); - - debug ("initialize the virtual device\n"); - return vdev; -} - -void -destroy_vdev (void *port) -{ - struct vether_device *vdev = (struct vether_device *)port; - - debug ("device %s is going to be destroyed\n", vdev->name); - /* Delete it from the virtual device list */ - mutex_lock (&dev_list_lock); - *vdev->pprev = vdev->next; - if (vdev->next) - vdev->next->pprev = vdev->pprev; - dev_num--; - mutex_unlock (&dev_list_lock); - - /* TODO Delete all filters in the interface, - * there shouldn't be any filters left */ - destroy_filters (&vdev->port_list); -} - -/* Test if there are devices existing in the list */ -int -has_vdev () -{ - return dev_head != NULL; -} - -/* Broadcast the packet to all virtual interfaces - * except the one the packet is from */ -int -broadcast_pack (char *data, int datalen, struct vether_device *from_vdev) -{ - int internal_deliver_pack (struct vether_device *vdev) - { - if (from_vdev == vdev) - return 0; - return deliver_pack (data, datalen, vdev); - } - - return foreach_dev_do (internal_deliver_pack); -} - -/* Create a message, and deliver it. */ -int -deliver_pack (char *data, int datalen, struct vether_device *vdev) -{ - struct net_rcv_msg msg; - int pack_size; - struct ethhdr *header; - struct packet_header *packet; - - pack_size = datalen - sizeof (struct ethhdr); - /* remember message sizes must be rounded up */ - msg.msg_hdr.msgh_size = (((mach_msg_size_t) (sizeof(struct net_rcv_msg) - - NET_RCV_MAX + pack_size)) + 3) & ~3; - - header = (struct ethhdr *) msg.header; - packet = (struct packet_header *) msg.packet; - msg.header_type = header_type; - memcpy (header, data, sizeof (struct ethhdr)); - msg.packet_type = packet_type; - memcpy (packet + 1, data + sizeof (struct ethhdr), pack_size); - packet->type = header->h_proto; - packet->length = pack_size + sizeof (struct packet_header); - msg.packet_type.msgt_number = packet->length; - - return deliver_msg (&msg, vdev); -} - -/* Broadcast the message to all virtual interfaces. */ -int -broadcast_msg (struct net_rcv_msg *msg) -{ - int rval = 0; - mach_msg_header_t header; - - int internal_deliver_msg (struct vether_device *vdev) - { - return deliver_msg (msg, vdev); - } - - /* Save the message header because deliver_msg will change it. */ - header = msg->msg_hdr; - rval = foreach_dev_do (internal_deliver_msg); - msg->msg_hdr = header; - return rval; -} - -/* - * Deliver the message to all right pfinet servers that - * connects to the virtual network interface. - */ -int -deliver_msg(struct net_rcv_msg *msg, struct vether_device *vdev) -{ - mach_msg_return_t err; - queue_head_t *if_port_list; - net_rcv_port_t infp, nextfp; - - msg->msg_hdr.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0); - /* remember message sizes must be rounded up */ - msg->msg_hdr.msgh_local_port = MACH_PORT_NULL; - msg->msg_hdr.msgh_kind = MACH_MSGH_KIND_NORMAL; - msg->msg_hdr.msgh_id = NET_RCV_MSG_ID; - - if_port_list = &vdev->port_list.if_rcv_port_list; - FILTER_ITERATE (if_port_list, infp, nextfp, &infp->input) - { - mach_port_t dest; - net_hash_entry_t entp, *hash_headp; - int ret_count; - - entp = (net_hash_entry_t) 0; - ret_count = bpf_do_filter (infp, - msg->packet + sizeof (struct packet_header), - msg->net_rcv_msg_packet_count, msg->header, - sizeof (struct ethhdr), &hash_headp, &entp); - if (entp == (net_hash_entry_t) 0) - dest = infp->rcv_port; - else - dest = entp->rcv_port; - - if (ret_count) - { - debug ("before delivering the packet\n"); - msg->msg_hdr.msgh_remote_port = dest; - err = mach_msg ((mach_msg_header_t *)msg, - MACH_SEND_MSG|MACH_SEND_TIMEOUT, - msg->msg_hdr.msgh_size, 0, MACH_PORT_NULL, - 0, MACH_PORT_NULL); - if (err != MACH_MSG_SUCCESS) - { - mach_port_deallocate(mach_task_self (), - ((mach_msg_header_t *)msg)->msgh_remote_port); - error (0, err, "mach_msg"); - return -1; - } - debug ("after delivering the packet\n"); - } - } - FILTER_ITERATE_END - - return 0; -} - diff --git a/eth-multiplexer/vdev.h b/eth-multiplexer/vdev.h deleted file mode 100644 index c8696785..00000000 --- a/eth-multiplexer/vdev.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ - -#ifndef VDEV_H -#define VDEV_H - -#include <net/if.h> - -#include <hurd.h> -#include <mach.h> -#include <hurd/ports.h> -#include <device/net_status.h> - -#include <bpf_impl.h> - -#include "queue.h" -#include "util.h" - -#define MAX_SERVERS 10 -#define ETH_MTU 1500 - -struct vether_device -{ - /* The ports used by the socket server to send packets to the interface. */ - struct port_info dev_pi; - mach_port_t dev_port; - - char name[IFNAMSIZ]; - - short if_header_size; - short if_mtu; - short if_header_format; - short if_address_size; - short if_flags; - char if_address[ETH_ALEN]; - - struct vether_device *next; - struct vether_device **pprev; - - if_filter_list_t port_list; -}; - -typedef int (*dev_act_func) (struct vether_device *); - -int serv_connect (mach_port_t port); -int serv_disconnect (); -struct vether_device *lookup_dev_by_name (char *name); -int remove_dead_port_from_dev (mach_port_t dead_port); -struct vether_device *add_vdev (char *name, int size, - struct port_class *class, - struct port_bucket *bucket); -void destroy_vdev (void *port); -int has_vdev (); -int deliver_msg (struct net_rcv_msg *msg, struct vether_device *vdev); -int deliver_pack (char *data, int datalen, struct vether_device *vdev); -boolean_t all_dev_close (); -int broadcast_pack (char *data, int datalen, struct vether_device *from_vdev); -int broadcast_msg (struct net_rcv_msg *msg); -int get_dev_num (); -int foreach_dev_do (dev_act_func func); - -#endif diff --git a/libddekit/Makefile b/libddekit/Makefile index a11534b7..59f75095 100644 --- a/libddekit/Makefile +++ b/libddekit/Makefile @@ -37,7 +37,7 @@ LCLHDRS = $(installhdrs) \ dde.h \ config.h list.h util.h -MIGSTUBS = deviceUser.o machUser.o +MIGSTUBS = experimentalUser.o OBJS = $(sort $(SRCS:.c=.o) $(MIGSTUBS)) HURDLIBS = ports shouldbeinlibc hurd-slab diff --git a/libddekit/device.defs b/libddekit/device.defs deleted file mode 100644 index 7c39f8a5..00000000 --- a/libddekit/device.defs +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: device/device.defs - * Author: Douglas Orr - * Feb 10, 1988 - * Abstract: - * Mach device support. Mach devices are accessed through - * block and character device interfaces to the kernel. - */ - -#ifdef MACH_KERNEL -simport <kern/compat_xxx_defs.h>; /* for obsolete routines */ -#endif - -subsystem -#if KERNEL_SERVER - KernelServer -#endif - device 2800; - -#include <mach/std_types.defs> -#include <mach/mach_types.defs> -#include <device/device_types.defs> - -serverprefix ds_; - -type reply_port_t = MACH_MSG_TYPE_MAKE_SEND_ONCE | polymorphic - ctype: mach_port_t; - -routine device_open( - master_port : mach_port_t; - sreplyport reply_port : reply_port_t; - mode : dev_mode_t; - name : dev_name_t; - out device : device_t - ); - -routine device_close( - device : device_t - ); - -routine device_write( - device : device_t; - sreplyport reply_port : reply_port_t; - in mode : dev_mode_t; - in recnum : recnum_t; - in data : io_buf_ptr_t; - out bytes_written : int - ); - -routine device_write_inband( - device : device_t; - sreplyport reply_port : reply_port_t; - in mode : dev_mode_t; - in recnum : recnum_t; - in data : io_buf_ptr_inband_t; - out bytes_written : int - ); - -routine device_read( - device : device_t; - sreplyport reply_port : reply_port_t; - in mode : dev_mode_t; - in recnum : recnum_t; - in bytes_wanted : int; - out data : io_buf_ptr_t - ); - -routine device_read_inband( - device : device_t; - sreplyport reply_port : reply_port_t; - in mode : dev_mode_t; - in recnum : recnum_t; - in bytes_wanted : int; - out data : io_buf_ptr_inband_t - ); - -/* obsolete */ -routine xxx_device_set_status( - device : device_t; - in flavor : dev_flavor_t; - in status : dev_status_t, IsLong - ); - -/* obsolete */ -routine xxx_device_get_status( - device : device_t; - in flavor : dev_flavor_t; - out status : dev_status_t, IsLong - ); - -/* obsolete */ -routine xxx_device_set_filter( - device : device_t; - in receive_port : mach_port_send_t; - in priority : int; - in filter : filter_array_t, IsLong - ); - -routine device_map( - device : device_t; - in prot : vm_prot_t; - in offset : vm_offset_t; - in size : vm_size_t; - out pager : memory_object_t; - in unmap : int - ); - -routine device_set_status( - device : device_t; - in flavor : dev_flavor_t; - in status : dev_status_t - ); - -routine device_get_status( - device : device_t; - in flavor : dev_flavor_t; - out status : dev_status_t, CountInOut - ); - -routine device_set_filter( - device : device_t; - in receive_port : mach_port_send_t; - in priority : int; - in filter : filter_array_t - ); - -routine device_intr_register( - master_port : mach_port_t; - in line : int; - in id : int; - in flags : int; - in receive_port : mach_port_send_t - ); - -/* - * enable/disable the specified line. - */ -routine device_intr_enable( - master_port : mach_port_t; - line : int; - status : char); diff --git a/libddekit/interrupt.c b/libddekit/interrupt.c index fb1f6163..940363b1 100644 --- a/libddekit/interrupt.c +++ b/libddekit/interrupt.c @@ -27,7 +27,7 @@ #define BLOCK_IRQ 0 -#define MACH_INTR_NOTIFY 100 +#define MACH_INTR_NOTIFY 424242 typedef struct { diff --git a/libddekit/mach.defs b/libddekit/mach.defs deleted file mode 100644 index 2750bcd5..00000000 --- a/libddekit/mach.defs +++ /dev/null @@ -1,715 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University. - * Copyright (c) 1993,1994 The University of Utah and - * the Computer Systems Laboratory (CSL). - * All rights reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF - * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY - * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF - * THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * Matchmaker definitions file for Mach kernel interface. - */ - -subsystem -#if KERNEL_USER - KernelUser -#endif /* KERNEL_USER */ -#if KERNEL_SERVER - KernelServer -#endif /* KERNEL_SERVER */ - mach 2000; - -#ifdef KERNEL_USER -userprefix r_; -#endif /* KERNEL_USER */ - -#include <mach/std_types.defs> -#include <mach/mach_types.defs> - -skip; /* old port_allocate */ -skip; /* old port_deallocate */ -skip; /* old port_enable */ -skip; /* old port_disable */ -skip; /* old port_select */ -skip; /* old port_set_backlog */ -skip; /* old port_status */ - -/* - * Create a new task with an empty set of IPC rights, - * and having an address space constructed from the - * target task (or empty, if inherit_memory is FALSE). - */ -routine task_create( - target_task : task_t; - inherit_memory : boolean_t; - out child_task : task_t); - -/* - * Destroy the target task, causing all of its threads - * to be destroyed, all of its IPC rights to be deallocated, - * and all of its address space to be deallocated. - */ -routine task_terminate( - target_task : task_t); - -/* - * Get user-level handler entry points for all - * emulated system calls. - */ -routine task_get_emulation_vector( - task : task_t; - out vector_start : int; - out emulation_vector: emulation_vector_t); - -/* - * Establish user-level handlers for the specified - * system calls. Non-emulated system calls are specified - * with emulation_vector[i] == EML_ROUTINE_NULL. - */ -routine task_set_emulation_vector( - task : task_t; - vector_start : int; - emulation_vector: emulation_vector_t); - - -/* - * Returns the set of threads belonging to the target task. - */ -routine task_threads( - target_task : task_t; - out thread_list : thread_array_t); - -/* - * Returns information about the target task. - */ -routine task_info( - target_task : task_t; - flavor : int; - out task_info_out : task_info_t, CountInOut); - - -skip; /* old task_status */ -skip; /* old task_set_notify */ -skip; /* old thread_create */ - -/* - * Destroy the target thread. - */ -routine thread_terminate( - target_thread : thread_t); - -/* - * Return the selected state information for the target - * thread. If the thread is currently executing, the results - * may be stale. [Flavor THREAD_STATE_FLAVOR_LIST provides a - * list of valid flavors for the target thread.] - */ -routine thread_get_state( - target_thread : thread_t; - flavor : int; - out old_state : thread_state_t, CountInOut); - -/* - * Set the selected state information for the target thread. - * If the thread is currently executing, the state change - * may be ill-defined. - */ -routine thread_set_state( - target_thread : thread_t; - flavor : int; - new_state : thread_state_t); - -/* - * Returns information about the target thread. - */ -routine thread_info( - target_thread : thread_t; - flavor : int; - out thread_info_out : thread_info_t, CountInOut); - -skip; /* old thread_mutate */ - -/* - * Allocate zero-filled memory in the address space - * of the target task, either at the specified address, - * or wherever space can be found (if anywhere is TRUE), - * of the specified size. The address at which the - * allocation actually took place is returned. - */ -#ifdef EMULATOR -skip; /* the emulator redefines vm_allocate using vm_map */ -#else /* EMULATOR */ -routine vm_allocate( - target_task : vm_task_t; - inout address : vm_address_t; - size : vm_size_t; - anywhere : boolean_t); -#endif /* EMULATOR */ - -skip; /* old vm_allocate_with_pager */ - -/* - * Deallocate the specified range from the virtual - * address space of the target task. - */ -routine vm_deallocate( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t); - -/* - * Set the current or maximum protection attribute - * for the specified range of the virtual address - * space of the target task. The current protection - * limits the memory access rights of threads within - * the task; the maximum protection limits the accesses - * that may be given in the current protection. - * Protections are specified as a set of {read, write, execute} - * *permissions*. - */ -routine vm_protect( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - set_maximum : boolean_t; - new_protection : vm_prot_t); - -/* - * Set the inheritance attribute for the specified range - * of the virtual address space of the target task. - * The inheritance value is one of {none, copy, share}, and - * specifies how the child address space should acquire - * this memory at the time of a task_create call. - */ -routine vm_inherit( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - new_inheritance : vm_inherit_t); - -/* - * Returns the contents of the specified range of the - * virtual address space of the target task. [The - * range must be aligned on a virtual page boundary, - * and must be a multiple of pages in extent. The - * protection on the specified range must permit reading.] - */ -routine vm_read( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - out data : pointer_t); - -/* - * Writes the contents of the specified range of the - * virtual address space of the target task. [The - * range must be aligned on a virtual page boundary, - * and must be a multiple of pages in extent. The - * protection on the specified range must permit writing.] - */ -routine vm_write( - target_task : vm_task_t; - address : vm_address_t; - data : pointer_t); - -/* - * Copy the contents of the source range of the virtual - * address space of the target task to the destination - * range in that same address space. [Both of the - * ranges must be aligned on a virtual page boundary, - * and must be multiples of pages in extent. The - * protection on the source range must permit reading, - * and the protection on the destination range must - * permit writing.] - */ -routine vm_copy( - target_task : vm_task_t; - source_address : vm_address_t; - size : vm_size_t; - dest_address : vm_address_t); - -/* - * Returns information about the contents of the virtual - * address space of the target task at the specified - * address. The returned protection, inheritance, sharing - * and memory object values apply to the entire range described - * by the address range returned; the memory object offset - * corresponds to the beginning of the address range. - * [If the specified address is not allocated, the next - * highest address range is described. If no addresses beyond - * the one specified are allocated, the call returns KERN_NO_SPACE.] - */ -routine vm_region( - target_task : vm_task_t; - inout address : vm_address_t; - out size : vm_size_t; - out protection : vm_prot_t; - out max_protection : vm_prot_t; - out inheritance : vm_inherit_t; - out is_shared : boolean_t; - /* avoid out-translation of the argument */ - out object_name : memory_object_name_t = - MACH_MSG_TYPE_MOVE_SEND - ctype: mach_port_t; - out offset : vm_offset_t); - -/* - * Return virtual memory statistics for the host - * on which the target task resides. [Note that the - * statistics are not specific to the target task.] - */ -routine vm_statistics( - target_task : vm_task_t; - out vm_stats : vm_statistics_data_t); - -skip; /* old task_by_u*x_pid */ -skip; /* old vm_pageable */ - -/* - * Stash a handful of ports for the target task; child - * tasks inherit this stash at task_create time. - */ -routine mach_ports_register( - target_task : task_t; - init_port_set : mach_port_array_t = - ^array[] of mach_port_t); - -/* - * Retrieve the stashed ports for the target task. - */ -routine mach_ports_lookup( - target_task : task_t; - out init_port_set : mach_port_array_t = - ^array[] of mach_port_t); - -skip; /* old u*x_pid */ -skip; /* old netipc_listen */ -skip; /* old netipc_ignore */ - -/* - * Provide the data contents of a range of the given memory - * object, with the access restriction specified. [Only - * whole virtual pages of data can be accepted; partial pages - * will be discarded. Data should be provided on request, but - * may be provided in advance as desired. When data already - * held by this kernel is provided again, the new data is ignored. - * The access restriction is the subset of {read, write, execute} - * which are prohibited. The kernel may not provide any data (or - * protection) consistency among pages with different virtual page - * alignments within the same object.] - */ -simpleroutine memory_object_data_provided( - memory_control : memory_object_control_t; - offset : vm_offset_t; - data : pointer_t; - lock_value : vm_prot_t); - -/* - * Indicate that a range of the given temporary memory object does - * not exist, and that the backing memory object should be used - * instead (or zero-fill memory be used, if no backing object exists). - * [This call is intended for use only by the default memory manager. - * It should not be used to indicate a real error -- - * memory_object_data_error should be used for that purpose.] - */ -simpleroutine memory_object_data_unavailable( - memory_control : memory_object_control_t; - offset : vm_offset_t; - size : vm_size_t); - -/* - * Retrieves the attributes currently associated with - * a memory object. - */ -routine memory_object_get_attributes( - memory_control : memory_object_control_t; - out object_ready : boolean_t; - out may_cache : boolean_t; - out copy_strategy : memory_object_copy_strategy_t); - -/* - * Sets the default memory manager, the port to which - * newly-created temporary memory objects are delivered. - * [See (memory_object_default)memory_object_create.] - * The old memory manager port is returned. - */ -routine vm_set_default_memory_manager( - host_priv : host_priv_t; - inout default_manager : mach_port_make_send_t); - -skip; /* old pager_flush_request */ - -/* - * Control use of the data associated with the given - * memory object. For each page in the given range, - * perform the following operations, in order: - * 1) restrict access to the page (disallow - * forms specified by "prot"); - * 2) write back modifications (if "should_return" - * is RETURN_DIRTY and the page is dirty, or - * "should_return" is RETURN_ALL and the page - * is either dirty or precious); and, - * 3) flush the cached copy (if "should_flush" - * is asserted). - * The set of pages is defined by a starting offset - * ("offset") and size ("size"). Only pages with the - * same page alignment as the starting offset are - * considered. - * - * A single acknowledgement is sent (to the "reply_to" - * port) when these actions are complete. - * - * There are two versions of this routine because IPC distinguishes - * between booleans and integers (a 2-valued integer is NOT a - * boolean). The new routine is backwards compatible at the C - * language interface. - */ - -skip; /* old xxx_memory_object_lock_request */ - -simpleroutine memory_object_lock_request( - memory_control : memory_object_control_t; - offset : vm_offset_t; - size : vm_size_t; - should_return : memory_object_return_t; - should_flush : boolean_t; - lock_value : vm_prot_t; - reply_to : mach_port_t = - MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); - -skip; /* old xxx_task_get_emulation_vector */ -skip; /* old xxx_task_set_emulation_vector */ -skip; /* old xxx_host_info */ -skip; /* old xxx_slot_info */ -skip; /* old xxx_cpu_control */ -skip; /* old thread_statistics */ -skip; /* old task_statistics */ -skip; /* old netport_init */ -skip; /* old netport_enter */ -skip; /* old netport_remove */ -skip; /* old thread_set_priority */ - -/* - * Increment the suspend count for the target task. - * No threads within a task may run when the suspend - * count for that task is non-zero. - */ -routine task_suspend( - target_task : task_t); - -/* - * Decrement the suspend count for the target task, - * if the count is currently non-zero. If the resulting - * suspend count is zero, then threads within the task - * that also have non-zero suspend counts may execute. - */ -routine task_resume( - target_task : task_t); - -/* - * Returns the current value of the selected special port - * associated with the target task. - */ -routine task_get_special_port( - task : task_t; - which_port : int; - out special_port : mach_port_t); - -/* - * Set one of the special ports associated with the - * target task. - */ -routine task_set_special_port( - task : task_t; - which_port : int; - special_port : mach_port_t); - -skip; /* old xxx_task_info */ - - -/* - * Create a new thread within the target task, returning - * the port representing that new thread. The - * initial execution state of the thread is undefined. - */ -routine thread_create( - parent_task : task_t; - out child_thread : thread_t); - -/* - * Increment the suspend count for the target thread. - * Once this call has completed, the thread will not - * execute any further user or meta- instructions. - * Once suspended, a thread may not execute again until - * its suspend count is zero, and the suspend count - * for its task is also zero. - */ -routine thread_suspend( - target_thread : thread_t); - -/* - * Decrement the suspend count for the target thread, - * if that count is not already zero. - */ -routine thread_resume( - target_thread : thread_t); - -/* - * Cause any user or meta- instructions currently being - * executed by the target thread to be aborted. [Meta- - * instructions consist of the basic traps for IPC - * (e.g., msg_send, msg_receive) and self-identification - * (e.g., task_self, thread_self, thread_reply). Calls - * described by MiG interfaces are not meta-instructions - * themselves.] - */ -routine thread_abort( - target_thread : thread_t); - -skip; /* old xxx_thread_get_state */ -skip; /* old xxx_thread_set_state */ - -/* - * Returns the current value of the selected special port - * associated with the target thread. - */ -routine thread_get_special_port( - thread : thread_t; - which_port : int; - out special_port : mach_port_t); - -/* - * Set one of the special ports associated with the - * target thread. - */ -routine thread_set_special_port( - thread : thread_t; - which_port : int; - special_port : mach_port_t); - -skip; /* old xxx_thread_info */ - -/* - * Establish a user-level handler for the specified - * system call. - */ -routine task_set_emulation( - target_port : task_t; - routine_entry_pt: vm_address_t; - routine_number : int); - -/* - * Establish restart pc for interrupted atomic sequences. - * This reuses the message number for the old task_get_io_port. - * See task_info.h for description of flavors. - * - */ -routine task_ras_control( - target_task : task_t; - basepc : vm_address_t; - boundspc : vm_address_t; - flavor : int); - - - -skip; /* old host_ipc_statistics */ -skip; /* old port_names */ -skip; /* old port_type */ -skip; /* old port_rename */ -skip; /* old port_allocate */ -skip; /* old port_deallocate */ -skip; /* old port_set_backlog */ -skip; /* old port_status */ -skip; /* old port_set_allocate */ -skip; /* old port_set_deallocate */ -skip; /* old port_set_add */ -skip; /* old port_set_remove */ -skip; /* old port_set_status */ -skip; /* old port_insert_send */ -skip; /* old port_extract_send */ -skip; /* old port_insert_receive */ -skip; /* old port_extract_receive */ - -/* - * Map a user-defined memory object into the virtual address - * space of the target task. If desired (anywhere is TRUE), - * the kernel will find a suitable address range of the - * specified size; else, the specific address will be allocated. - * - * The beginning address of the range will be aligned on a virtual - * page boundary, be at or beyond the address specified, and - * meet the mask requirements (bits turned on in the mask must not - * be turned on in the result); the size of the range, in bytes, - * will be rounded up to an integral number of virtual pages. - * - * The memory in the resulting range will be associated with the - * specified memory object, with the beginning of the memory range - * referring to the specified offset into the memory object. - * - * The mapping will take the current and maximum protections and - * the inheritance attributes specified; see the vm_protect and - * vm_inherit calls for a description of these attributes. - * - * If desired (copy is TRUE), the memory range will be filled - * with a copy of the data from the memory object; this copy will - * be private to this mapping in this target task. Otherwise, - * the memory in this mapping will be shared with other mappings - * of the same memory object at the same offset (in this task or - * in other tasks). [The Mach kernel only enforces shared memory - * consistency among mappings on one host with similar page alignments. - * The user-defined memory manager for this object is responsible - * for further consistency.] - */ -#ifdef EMULATOR -routine htg_vm_map( - target_task : vm_task_t; - ureplyport reply_port : mach_port_make_send_once_t; - inout address : vm_address_t; - size : vm_size_t; - mask : vm_address_t; - anywhere : boolean_t; - memory_object : memory_object_t; - offset : vm_offset_t; - copy : boolean_t; - cur_protection : vm_prot_t; - max_protection : vm_prot_t; - inheritance : vm_inherit_t); -#else /* EMULATOR */ -routine vm_map( - target_task : vm_task_t; - inout address : vm_address_t; - size : vm_size_t; - mask : vm_address_t; - anywhere : boolean_t; - memory_object : memory_object_t; - offset : vm_offset_t; - copy : boolean_t; - cur_protection : vm_prot_t; - max_protection : vm_prot_t; - inheritance : vm_inherit_t); -#endif /* EMULATOR */ - -/* - * Indicate that a range of the specified memory object cannot - * be provided at this time. [Threads waiting for memory pages - * specified by this call will experience a memory exception. - * Only threads waiting at the time of the call are affected.] - */ -simpleroutine memory_object_data_error( - memory_control : memory_object_control_t; - offset : vm_offset_t; - size : vm_size_t; - error_value : kern_return_t); - -/* - * Make decisions regarding the use of the specified - * memory object. - */ -simpleroutine memory_object_set_attributes( - memory_control : memory_object_control_t; - object_ready : boolean_t; - may_cache : boolean_t; - copy_strategy : memory_object_copy_strategy_t); - -/* - */ -simpleroutine memory_object_destroy( - memory_control : memory_object_control_t; - reason : kern_return_t); - -/* - * Provide the data contents of a range of the given memory - * object, with the access restriction specified, optional - * precious attribute, and reply message. [Only - * whole virtual pages of data can be accepted; partial pages - * will be discarded. Data should be provided on request, but - * may be provided in advance as desired. When data already - * held by this kernel is provided again, the new data is ignored. - * The access restriction is the subset of {read, write, execute} - * which are prohibited. The kernel may not provide any data (or - * protection) consistency among pages with different virtual page - * alignments within the same object. The precious value controls - * how the kernel treats the data. If it is FALSE, the kernel treats - * its copy as a temporary and may throw it away if it hasn't been - * changed. If the precious value is TRUE, the kernel treats its - * copy as a data repository and promises to return it to the manager; - * the manager may tell the kernel to throw it away instead by flushing - * and not cleaning the data -- see memory_object_lock_request. The - * reply_to port is for a compeletion message; it will be - * memory_object_supply_completed.] - */ - -simpleroutine memory_object_data_supply( - memory_control : memory_object_control_t; - offset : vm_offset_t; - data : pointer_t, Dealloc[]; - lock_value : vm_prot_t; - precious : boolean_t; - reply_to : mach_port_t = - MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); - -simpleroutine memory_object_ready( - memory_control : memory_object_control_t; - may_cache : boolean_t; - copy_strategy : memory_object_copy_strategy_t); - -simpleroutine memory_object_change_attributes( - memory_control : memory_object_control_t; - may_cache : boolean_t; - copy_strategy : memory_object_copy_strategy_t; - reply_to : mach_port_t = - MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); - -skip; /* old host_callout_statistics_reset */ -skip; /* old port_set_select */ -skip; /* old port_set_backup */ - -/* - * Set/Get special properties of memory associated - * to some virtual address range, such as cachability, - * migrability, replicability. Machine-dependent. - */ -routine vm_machine_attribute( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - attribute : vm_machine_attribute_t; - inout value : vm_machine_attribute_val_t); - -skip; /* old host_fpa_counters_reset */ - -/* - * This routine is created for allocating DMA buffers. - * We are going to get a contiguous physical memory - * and its physical address in addition to the virtual address. - */ -routine vm_allocate_contiguous( - host_priv : host_priv_t; - target_task : vm_task_t; - out vaddr : vm_address_t; - out paddr : vm_address_t; - size : vm_size_t); - -/* - * There is no more room in this interface for additional calls. - */ diff --git a/libmachdev/device.defs b/libmachdev/device.defs deleted file mode 100644 index 7c39f8a5..00000000 --- a/libmachdev/device.defs +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: device/device.defs - * Author: Douglas Orr - * Feb 10, 1988 - * Abstract: - * Mach device support. Mach devices are accessed through - * block and character device interfaces to the kernel. - */ - -#ifdef MACH_KERNEL -simport <kern/compat_xxx_defs.h>; /* for obsolete routines */ -#endif - -subsystem -#if KERNEL_SERVER - KernelServer -#endif - device 2800; - -#include <mach/std_types.defs> -#include <mach/mach_types.defs> -#include <device/device_types.defs> - -serverprefix ds_; - -type reply_port_t = MACH_MSG_TYPE_MAKE_SEND_ONCE | polymorphic - ctype: mach_port_t; - -routine device_open( - master_port : mach_port_t; - sreplyport reply_port : reply_port_t; - mode : dev_mode_t; - name : dev_name_t; - out device : device_t - ); - -routine device_close( - device : device_t - ); - -routine device_write( - device : device_t; - sreplyport reply_port : reply_port_t; - in mode : dev_mode_t; - in recnum : recnum_t; - in data : io_buf_ptr_t; - out bytes_written : int - ); - -routine device_write_inband( - device : device_t; - sreplyport reply_port : reply_port_t; - in mode : dev_mode_t; - in recnum : recnum_t; - in data : io_buf_ptr_inband_t; - out bytes_written : int - ); - -routine device_read( - device : device_t; - sreplyport reply_port : reply_port_t; - in mode : dev_mode_t; - in recnum : recnum_t; - in bytes_wanted : int; - out data : io_buf_ptr_t - ); - -routine device_read_inband( - device : device_t; - sreplyport reply_port : reply_port_t; - in mode : dev_mode_t; - in recnum : recnum_t; - in bytes_wanted : int; - out data : io_buf_ptr_inband_t - ); - -/* obsolete */ -routine xxx_device_set_status( - device : device_t; - in flavor : dev_flavor_t; - in status : dev_status_t, IsLong - ); - -/* obsolete */ -routine xxx_device_get_status( - device : device_t; - in flavor : dev_flavor_t; - out status : dev_status_t, IsLong - ); - -/* obsolete */ -routine xxx_device_set_filter( - device : device_t; - in receive_port : mach_port_send_t; - in priority : int; - in filter : filter_array_t, IsLong - ); - -routine device_map( - device : device_t; - in prot : vm_prot_t; - in offset : vm_offset_t; - in size : vm_size_t; - out pager : memory_object_t; - in unmap : int - ); - -routine device_set_status( - device : device_t; - in flavor : dev_flavor_t; - in status : dev_status_t - ); - -routine device_get_status( - device : device_t; - in flavor : dev_flavor_t; - out status : dev_status_t, CountInOut - ); - -routine device_set_filter( - device : device_t; - in receive_port : mach_port_send_t; - in priority : int; - in filter : filter_array_t - ); - -routine device_intr_register( - master_port : mach_port_t; - in line : int; - in id : int; - in flags : int; - in receive_port : mach_port_send_t - ); - -/* - * enable/disable the specified line. - */ -routine device_intr_enable( - master_port : mach_port_t; - line : int; - status : char); diff --git a/libmachdev/mach.defs b/libmachdev/mach.defs deleted file mode 100644 index 2750bcd5..00000000 --- a/libmachdev/mach.defs +++ /dev/null @@ -1,715 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University. - * Copyright (c) 1993,1994 The University of Utah and - * the Computer Systems Laboratory (CSL). - * All rights reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF - * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY - * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF - * THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * Matchmaker definitions file for Mach kernel interface. - */ - -subsystem -#if KERNEL_USER - KernelUser -#endif /* KERNEL_USER */ -#if KERNEL_SERVER - KernelServer -#endif /* KERNEL_SERVER */ - mach 2000; - -#ifdef KERNEL_USER -userprefix r_; -#endif /* KERNEL_USER */ - -#include <mach/std_types.defs> -#include <mach/mach_types.defs> - -skip; /* old port_allocate */ -skip; /* old port_deallocate */ -skip; /* old port_enable */ -skip; /* old port_disable */ -skip; /* old port_select */ -skip; /* old port_set_backlog */ -skip; /* old port_status */ - -/* - * Create a new task with an empty set of IPC rights, - * and having an address space constructed from the - * target task (or empty, if inherit_memory is FALSE). - */ -routine task_create( - target_task : task_t; - inherit_memory : boolean_t; - out child_task : task_t); - -/* - * Destroy the target task, causing all of its threads - * to be destroyed, all of its IPC rights to be deallocated, - * and all of its address space to be deallocated. - */ -routine task_terminate( - target_task : task_t); - -/* - * Get user-level handler entry points for all - * emulated system calls. - */ -routine task_get_emulation_vector( - task : task_t; - out vector_start : int; - out emulation_vector: emulation_vector_t); - -/* - * Establish user-level handlers for the specified - * system calls. Non-emulated system calls are specified - * with emulation_vector[i] == EML_ROUTINE_NULL. - */ -routine task_set_emulation_vector( - task : task_t; - vector_start : int; - emulation_vector: emulation_vector_t); - - -/* - * Returns the set of threads belonging to the target task. - */ -routine task_threads( - target_task : task_t; - out thread_list : thread_array_t); - -/* - * Returns information about the target task. - */ -routine task_info( - target_task : task_t; - flavor : int; - out task_info_out : task_info_t, CountInOut); - - -skip; /* old task_status */ -skip; /* old task_set_notify */ -skip; /* old thread_create */ - -/* - * Destroy the target thread. - */ -routine thread_terminate( - target_thread : thread_t); - -/* - * Return the selected state information for the target - * thread. If the thread is currently executing, the results - * may be stale. [Flavor THREAD_STATE_FLAVOR_LIST provides a - * list of valid flavors for the target thread.] - */ -routine thread_get_state( - target_thread : thread_t; - flavor : int; - out old_state : thread_state_t, CountInOut); - -/* - * Set the selected state information for the target thread. - * If the thread is currently executing, the state change - * may be ill-defined. - */ -routine thread_set_state( - target_thread : thread_t; - flavor : int; - new_state : thread_state_t); - -/* - * Returns information about the target thread. - */ -routine thread_info( - target_thread : thread_t; - flavor : int; - out thread_info_out : thread_info_t, CountInOut); - -skip; /* old thread_mutate */ - -/* - * Allocate zero-filled memory in the address space - * of the target task, either at the specified address, - * or wherever space can be found (if anywhere is TRUE), - * of the specified size. The address at which the - * allocation actually took place is returned. - */ -#ifdef EMULATOR -skip; /* the emulator redefines vm_allocate using vm_map */ -#else /* EMULATOR */ -routine vm_allocate( - target_task : vm_task_t; - inout address : vm_address_t; - size : vm_size_t; - anywhere : boolean_t); -#endif /* EMULATOR */ - -skip; /* old vm_allocate_with_pager */ - -/* - * Deallocate the specified range from the virtual - * address space of the target task. - */ -routine vm_deallocate( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t); - -/* - * Set the current or maximum protection attribute - * for the specified range of the virtual address - * space of the target task. The current protection - * limits the memory access rights of threads within - * the task; the maximum protection limits the accesses - * that may be given in the current protection. - * Protections are specified as a set of {read, write, execute} - * *permissions*. - */ -routine vm_protect( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - set_maximum : boolean_t; - new_protection : vm_prot_t); - -/* - * Set the inheritance attribute for the specified range - * of the virtual address space of the target task. - * The inheritance value is one of {none, copy, share}, and - * specifies how the child address space should acquire - * this memory at the time of a task_create call. - */ -routine vm_inherit( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - new_inheritance : vm_inherit_t); - -/* - * Returns the contents of the specified range of the - * virtual address space of the target task. [The - * range must be aligned on a virtual page boundary, - * and must be a multiple of pages in extent. The - * protection on the specified range must permit reading.] - */ -routine vm_read( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - out data : pointer_t); - -/* - * Writes the contents of the specified range of the - * virtual address space of the target task. [The - * range must be aligned on a virtual page boundary, - * and must be a multiple of pages in extent. The - * protection on the specified range must permit writing.] - */ -routine vm_write( - target_task : vm_task_t; - address : vm_address_t; - data : pointer_t); - -/* - * Copy the contents of the source range of the virtual - * address space of the target task to the destination - * range in that same address space. [Both of the - * ranges must be aligned on a virtual page boundary, - * and must be multiples of pages in extent. The - * protection on the source range must permit reading, - * and the protection on the destination range must - * permit writing.] - */ -routine vm_copy( - target_task : vm_task_t; - source_address : vm_address_t; - size : vm_size_t; - dest_address : vm_address_t); - -/* - * Returns information about the contents of the virtual - * address space of the target task at the specified - * address. The returned protection, inheritance, sharing - * and memory object values apply to the entire range described - * by the address range returned; the memory object offset - * corresponds to the beginning of the address range. - * [If the specified address is not allocated, the next - * highest address range is described. If no addresses beyond - * the one specified are allocated, the call returns KERN_NO_SPACE.] - */ -routine vm_region( - target_task : vm_task_t; - inout address : vm_address_t; - out size : vm_size_t; - out protection : vm_prot_t; - out max_protection : vm_prot_t; - out inheritance : vm_inherit_t; - out is_shared : boolean_t; - /* avoid out-translation of the argument */ - out object_name : memory_object_name_t = - MACH_MSG_TYPE_MOVE_SEND - ctype: mach_port_t; - out offset : vm_offset_t); - -/* - * Return virtual memory statistics for the host - * on which the target task resides. [Note that the - * statistics are not specific to the target task.] - */ -routine vm_statistics( - target_task : vm_task_t; - out vm_stats : vm_statistics_data_t); - -skip; /* old task_by_u*x_pid */ -skip; /* old vm_pageable */ - -/* - * Stash a handful of ports for the target task; child - * tasks inherit this stash at task_create time. - */ -routine mach_ports_register( - target_task : task_t; - init_port_set : mach_port_array_t = - ^array[] of mach_port_t); - -/* - * Retrieve the stashed ports for the target task. - */ -routine mach_ports_lookup( - target_task : task_t; - out init_port_set : mach_port_array_t = - ^array[] of mach_port_t); - -skip; /* old u*x_pid */ -skip; /* old netipc_listen */ -skip; /* old netipc_ignore */ - -/* - * Provide the data contents of a range of the given memory - * object, with the access restriction specified. [Only - * whole virtual pages of data can be accepted; partial pages - * will be discarded. Data should be provided on request, but - * may be provided in advance as desired. When data already - * held by this kernel is provided again, the new data is ignored. - * The access restriction is the subset of {read, write, execute} - * which are prohibited. The kernel may not provide any data (or - * protection) consistency among pages with different virtual page - * alignments within the same object.] - */ -simpleroutine memory_object_data_provided( - memory_control : memory_object_control_t; - offset : vm_offset_t; - data : pointer_t; - lock_value : vm_prot_t); - -/* - * Indicate that a range of the given temporary memory object does - * not exist, and that the backing memory object should be used - * instead (or zero-fill memory be used, if no backing object exists). - * [This call is intended for use only by the default memory manager. - * It should not be used to indicate a real error -- - * memory_object_data_error should be used for that purpose.] - */ -simpleroutine memory_object_data_unavailable( - memory_control : memory_object_control_t; - offset : vm_offset_t; - size : vm_size_t); - -/* - * Retrieves the attributes currently associated with - * a memory object. - */ -routine memory_object_get_attributes( - memory_control : memory_object_control_t; - out object_ready : boolean_t; - out may_cache : boolean_t; - out copy_strategy : memory_object_copy_strategy_t); - -/* - * Sets the default memory manager, the port to which - * newly-created temporary memory objects are delivered. - * [See (memory_object_default)memory_object_create.] - * The old memory manager port is returned. - */ -routine vm_set_default_memory_manager( - host_priv : host_priv_t; - inout default_manager : mach_port_make_send_t); - -skip; /* old pager_flush_request */ - -/* - * Control use of the data associated with the given - * memory object. For each page in the given range, - * perform the following operations, in order: - * 1) restrict access to the page (disallow - * forms specified by "prot"); - * 2) write back modifications (if "should_return" - * is RETURN_DIRTY and the page is dirty, or - * "should_return" is RETURN_ALL and the page - * is either dirty or precious); and, - * 3) flush the cached copy (if "should_flush" - * is asserted). - * The set of pages is defined by a starting offset - * ("offset") and size ("size"). Only pages with the - * same page alignment as the starting offset are - * considered. - * - * A single acknowledgement is sent (to the "reply_to" - * port) when these actions are complete. - * - * There are two versions of this routine because IPC distinguishes - * between booleans and integers (a 2-valued integer is NOT a - * boolean). The new routine is backwards compatible at the C - * language interface. - */ - -skip; /* old xxx_memory_object_lock_request */ - -simpleroutine memory_object_lock_request( - memory_control : memory_object_control_t; - offset : vm_offset_t; - size : vm_size_t; - should_return : memory_object_return_t; - should_flush : boolean_t; - lock_value : vm_prot_t; - reply_to : mach_port_t = - MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); - -skip; /* old xxx_task_get_emulation_vector */ -skip; /* old xxx_task_set_emulation_vector */ -skip; /* old xxx_host_info */ -skip; /* old xxx_slot_info */ -skip; /* old xxx_cpu_control */ -skip; /* old thread_statistics */ -skip; /* old task_statistics */ -skip; /* old netport_init */ -skip; /* old netport_enter */ -skip; /* old netport_remove */ -skip; /* old thread_set_priority */ - -/* - * Increment the suspend count for the target task. - * No threads within a task may run when the suspend - * count for that task is non-zero. - */ -routine task_suspend( - target_task : task_t); - -/* - * Decrement the suspend count for the target task, - * if the count is currently non-zero. If the resulting - * suspend count is zero, then threads within the task - * that also have non-zero suspend counts may execute. - */ -routine task_resume( - target_task : task_t); - -/* - * Returns the current value of the selected special port - * associated with the target task. - */ -routine task_get_special_port( - task : task_t; - which_port : int; - out special_port : mach_port_t); - -/* - * Set one of the special ports associated with the - * target task. - */ -routine task_set_special_port( - task : task_t; - which_port : int; - special_port : mach_port_t); - -skip; /* old xxx_task_info */ - - -/* - * Create a new thread within the target task, returning - * the port representing that new thread. The - * initial execution state of the thread is undefined. - */ -routine thread_create( - parent_task : task_t; - out child_thread : thread_t); - -/* - * Increment the suspend count for the target thread. - * Once this call has completed, the thread will not - * execute any further user or meta- instructions. - * Once suspended, a thread may not execute again until - * its suspend count is zero, and the suspend count - * for its task is also zero. - */ -routine thread_suspend( - target_thread : thread_t); - -/* - * Decrement the suspend count for the target thread, - * if that count is not already zero. - */ -routine thread_resume( - target_thread : thread_t); - -/* - * Cause any user or meta- instructions currently being - * executed by the target thread to be aborted. [Meta- - * instructions consist of the basic traps for IPC - * (e.g., msg_send, msg_receive) and self-identification - * (e.g., task_self, thread_self, thread_reply). Calls - * described by MiG interfaces are not meta-instructions - * themselves.] - */ -routine thread_abort( - target_thread : thread_t); - -skip; /* old xxx_thread_get_state */ -skip; /* old xxx_thread_set_state */ - -/* - * Returns the current value of the selected special port - * associated with the target thread. - */ -routine thread_get_special_port( - thread : thread_t; - which_port : int; - out special_port : mach_port_t); - -/* - * Set one of the special ports associated with the - * target thread. - */ -routine thread_set_special_port( - thread : thread_t; - which_port : int; - special_port : mach_port_t); - -skip; /* old xxx_thread_info */ - -/* - * Establish a user-level handler for the specified - * system call. - */ -routine task_set_emulation( - target_port : task_t; - routine_entry_pt: vm_address_t; - routine_number : int); - -/* - * Establish restart pc for interrupted atomic sequences. - * This reuses the message number for the old task_get_io_port. - * See task_info.h for description of flavors. - * - */ -routine task_ras_control( - target_task : task_t; - basepc : vm_address_t; - boundspc : vm_address_t; - flavor : int); - - - -skip; /* old host_ipc_statistics */ -skip; /* old port_names */ -skip; /* old port_type */ -skip; /* old port_rename */ -skip; /* old port_allocate */ -skip; /* old port_deallocate */ -skip; /* old port_set_backlog */ -skip; /* old port_status */ -skip; /* old port_set_allocate */ -skip; /* old port_set_deallocate */ -skip; /* old port_set_add */ -skip; /* old port_set_remove */ -skip; /* old port_set_status */ -skip; /* old port_insert_send */ -skip; /* old port_extract_send */ -skip; /* old port_insert_receive */ -skip; /* old port_extract_receive */ - -/* - * Map a user-defined memory object into the virtual address - * space of the target task. If desired (anywhere is TRUE), - * the kernel will find a suitable address range of the - * specified size; else, the specific address will be allocated. - * - * The beginning address of the range will be aligned on a virtual - * page boundary, be at or beyond the address specified, and - * meet the mask requirements (bits turned on in the mask must not - * be turned on in the result); the size of the range, in bytes, - * will be rounded up to an integral number of virtual pages. - * - * The memory in the resulting range will be associated with the - * specified memory object, with the beginning of the memory range - * referring to the specified offset into the memory object. - * - * The mapping will take the current and maximum protections and - * the inheritance attributes specified; see the vm_protect and - * vm_inherit calls for a description of these attributes. - * - * If desired (copy is TRUE), the memory range will be filled - * with a copy of the data from the memory object; this copy will - * be private to this mapping in this target task. Otherwise, - * the memory in this mapping will be shared with other mappings - * of the same memory object at the same offset (in this task or - * in other tasks). [The Mach kernel only enforces shared memory - * consistency among mappings on one host with similar page alignments. - * The user-defined memory manager for this object is responsible - * for further consistency.] - */ -#ifdef EMULATOR -routine htg_vm_map( - target_task : vm_task_t; - ureplyport reply_port : mach_port_make_send_once_t; - inout address : vm_address_t; - size : vm_size_t; - mask : vm_address_t; - anywhere : boolean_t; - memory_object : memory_object_t; - offset : vm_offset_t; - copy : boolean_t; - cur_protection : vm_prot_t; - max_protection : vm_prot_t; - inheritance : vm_inherit_t); -#else /* EMULATOR */ -routine vm_map( - target_task : vm_task_t; - inout address : vm_address_t; - size : vm_size_t; - mask : vm_address_t; - anywhere : boolean_t; - memory_object : memory_object_t; - offset : vm_offset_t; - copy : boolean_t; - cur_protection : vm_prot_t; - max_protection : vm_prot_t; - inheritance : vm_inherit_t); -#endif /* EMULATOR */ - -/* - * Indicate that a range of the specified memory object cannot - * be provided at this time. [Threads waiting for memory pages - * specified by this call will experience a memory exception. - * Only threads waiting at the time of the call are affected.] - */ -simpleroutine memory_object_data_error( - memory_control : memory_object_control_t; - offset : vm_offset_t; - size : vm_size_t; - error_value : kern_return_t); - -/* - * Make decisions regarding the use of the specified - * memory object. - */ -simpleroutine memory_object_set_attributes( - memory_control : memory_object_control_t; - object_ready : boolean_t; - may_cache : boolean_t; - copy_strategy : memory_object_copy_strategy_t); - -/* - */ -simpleroutine memory_object_destroy( - memory_control : memory_object_control_t; - reason : kern_return_t); - -/* - * Provide the data contents of a range of the given memory - * object, with the access restriction specified, optional - * precious attribute, and reply message. [Only - * whole virtual pages of data can be accepted; partial pages - * will be discarded. Data should be provided on request, but - * may be provided in advance as desired. When data already - * held by this kernel is provided again, the new data is ignored. - * The access restriction is the subset of {read, write, execute} - * which are prohibited. The kernel may not provide any data (or - * protection) consistency among pages with different virtual page - * alignments within the same object. The precious value controls - * how the kernel treats the data. If it is FALSE, the kernel treats - * its copy as a temporary and may throw it away if it hasn't been - * changed. If the precious value is TRUE, the kernel treats its - * copy as a data repository and promises to return it to the manager; - * the manager may tell the kernel to throw it away instead by flushing - * and not cleaning the data -- see memory_object_lock_request. The - * reply_to port is for a compeletion message; it will be - * memory_object_supply_completed.] - */ - -simpleroutine memory_object_data_supply( - memory_control : memory_object_control_t; - offset : vm_offset_t; - data : pointer_t, Dealloc[]; - lock_value : vm_prot_t; - precious : boolean_t; - reply_to : mach_port_t = - MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); - -simpleroutine memory_object_ready( - memory_control : memory_object_control_t; - may_cache : boolean_t; - copy_strategy : memory_object_copy_strategy_t); - -simpleroutine memory_object_change_attributes( - memory_control : memory_object_control_t; - may_cache : boolean_t; - copy_strategy : memory_object_copy_strategy_t; - reply_to : mach_port_t = - MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic); - -skip; /* old host_callout_statistics_reset */ -skip; /* old port_set_select */ -skip; /* old port_set_backup */ - -/* - * Set/Get special properties of memory associated - * to some virtual address range, such as cachability, - * migrability, replicability. Machine-dependent. - */ -routine vm_machine_attribute( - target_task : vm_task_t; - address : vm_address_t; - size : vm_size_t; - attribute : vm_machine_attribute_t; - inout value : vm_machine_attribute_val_t); - -skip; /* old host_fpa_counters_reset */ - -/* - * This routine is created for allocating DMA buffers. - * We are going to get a contiguous physical memory - * and its physical address in addition to the virtual address. - */ -routine vm_allocate_contiguous( - host_priv : host_priv_t; - target_task : vm_task_t; - out vaddr : vm_address_t; - out paddr : vm_address_t; - size : vm_size_t); - -/* - * There is no more room in this interface for additional calls. - */ diff --git a/netfs-sample/README b/netfs-sample/README deleted file mode 100644 index 112cce59..00000000 --- a/netfs-sample/README +++ /dev/null @@ -1,13 +0,0 @@ -FILTERFS TRANSLATOR - -WHAT'S THIS? -filterfs is a GNU/Hurd translator that filters the contents of the directory it -is set upon according to the result of execution of a given command. - -WHAT'S IT FOR? -This translator is intended as a preparatory exercise for the namespace-based -translator selection project (see http://www.bddebian.com/~wiki/community/gsoc/), -so it does not really have a stand-alone importance :-) - -DEVELOPER -Sergiu Ivanov <unlimitedscolobb@gmail.com> diff --git a/netfs-sample/build b/netfs-sample/build deleted file mode 100755 index 2555e2ca..00000000 --- a/netfs-sample/build +++ /dev/null @@ -1 +0,0 @@ -gcc -Wall -g -lnetfs -lfshelp -liohelp -lthreads -lports -lihash -lshouldbeinlibc -o filterfs filterfs.c node.c lnode.c ncache.c options.c lib.c 2>&1 | tee errors diff --git a/netfs-sample/debug.h b/netfs-sample/debug.h deleted file mode 100644 index 606d7e79..00000000 --- a/netfs-sample/debug.h +++ /dev/null @@ -1,60 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/*debug.h*/ -/*----------------------------------------------------------------------------*/ -/*Simple facilities for debugging messages*/ -/*----------------------------------------------------------------------------*/ -/*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ -/*Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA.*/ -/*----------------------------------------------------------------------------*/ -#ifndef __DEBUG_H__ -#define __DEBUG_H__ - -/*----------------------------------------------------------------------------*/ -#include <stdio.h> -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Macros--------------------------------------------------------------*/ -/*Print debug messages here*/ -#define DEBUG_OUTPUT "/var/tmp/filterfs.dbg" -/*----------------------------------------------------------------------------*/ -#ifdef DEBUG - /*Initializes the log*/ -# define INIT_LOG() filterfs_dbg = fopen(DEBUG_OUTPUT, "wt") - /*Closes the log*/ -# define CLOSE_LOG() fclose(filterfs_dbg) - /*Prints a debug message and flushes the debug output*/ -# define LOG_MSG(fmt, args...) {fprintf(filterfs_dbg, fmt"\n", ##args);\ - fflush(filterfs_dbg);} -#else - /*Remove requests for debugging output*/ -# define INIT_LOG() -# define CLOSE_LOG() -# define LOG_MSG(fmt, args...) -#endif /*DEBUG*/ -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ -/*The file to write debugging info to*/ -extern FILE * filterfs_dbg; -/*----------------------------------------------------------------------------*/ - -#endif /*__DEBUG_H__*/ diff --git a/netfs-sample/errors b/netfs-sample/errors deleted file mode 100644 index e69de29b..00000000 --- a/netfs-sample/errors +++ /dev/null diff --git a/netfs-sample/filtered b/netfs-sample/filtered deleted file mode 100644 index e69de29b..00000000 --- a/netfs-sample/filtered +++ /dev/null diff --git a/netfs-sample/filterfs.c b/netfs-sample/filterfs.c deleted file mode 100644 index d768e18b..00000000 --- a/netfs-sample/filterfs.c +++ /dev/null @@ -1,1236 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/*filter.c*/ -/*----------------------------------------------------------------------------*/ -/*The filtering translator*/ -/*----------------------------------------------------------------------------*/ -/*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ -/*Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA.*/ -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -#define _GNU_SOURCE 1 -/*----------------------------------------------------------------------------*/ -#include "filterfs.h" -/*----------------------------------------------------------------------------*/ -#include <error.h> -#include <argp.h> -#include <argz.h> -#include <hurd/netfs.h> -#include <fcntl.h> -/*----------------------------------------------------------------------------*/ -#include "debug.h" -#include "options.h" -#include "ncache.h" -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Macros--------------------------------------------------------------*/ -/*The state modes use in open*/ -#define OPENONLY_STATE_MODES (O_CREAT | O_EXCL | O_NOLINK | O_NOTRANS \ - | O_NONBLOCK) -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ -/*The name of the server*/ -char * netfs_server_name = "filterfs"; -/*----------------------------------------------------------------------------*/ -/*The version of the server*/ -char * netfs_server_version = "0.0"; -/*----------------------------------------------------------------------------*/ -/*The maximal length of a chain of symbolic links*/ -int netfs_maxsymlinks = 12; -/*----------------------------------------------------------------------------*/ -/*A port to the underlying node*/ -mach_port_t underlying_node; -/*----------------------------------------------------------------------------*/ -/*Status information for the underlying node*/ -io_statbuf_t underlying_node_stat; -/*----------------------------------------------------------------------------*/ -/*Mapped time used for updating node information*/ -volatile struct mapped_time_value * maptime; -/*----------------------------------------------------------------------------*/ -/*The filesystem ID*/ -pid_t fsid; -/*----------------------------------------------------------------------------*/ -/*The file to print debug messages to*/ -FILE * filterfs_dbg; -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ -/*Attempts to create a file named `name` in `dir` for `user` with mode `mode`*/ -error_t -netfs_attempt_create_file -( - struct iouser * user, - struct node * dir, - char * name, - mode_t mode, - struct node ** node -) -{ - LOG_MSG("netfs_attempt_create_file"); - - /*Unlock `dir` and say that we can do nothing else here*/ - mutex_unlock(&dir->lock); - return EOPNOTSUPP; -}/*netfs_attempt_create_file*/ -/*----------------------------------------------------------------------------*/ -/*Return an error if the process of opening a file should not be allowed - to complete because of insufficient permissions*/ -error_t -netfs_check_open_permissions -( - struct iouser * user, - struct node * np, - int flags, - int newnode -) -{ - LOG_MSG("netfs_check_open_permissions: '%s'", np->nn->lnode->name); - - error_t err = 0; - - /*Cheks user's permissions*/ - if(flags & O_READ) - err = fshelp_access(&np->nn_stat, S_IREAD, user); - if(!err && (flags & O_WRITE)) - err = fshelp_access(&np->nn_stat, S_IWRITE, user); - if(!err && (flags & O_EXEC)) - err = fshelp_access(&np->nn_stat, S_IEXEC, user); - - /*Return the result of the check*/ - return err; -}/*netfs_check_open_permissions*/ -/*----------------------------------------------------------------------------*/ -/*Attempts an utimes call for the user `cred` on node `node`*/ -error_t -netfs_attempt_utimes -( - struct iouser * cred, - struct node * node, - struct timespec * atime, - struct timespec * mtime -) -{ - LOG_MSG("netfs_attempt_utimes"); - - error_t err = 0; - - /*See what information is to be updated*/ - int flags = TOUCH_CTIME; - - /*Check if the user is indeed the owner of the node*/ - err = fshelp_isowner(&node->nn_stat, cred); - - /*If the user is allowed to do utimes*/ - if(!err) - { - /*If atime is to be updated*/ - if(atime) - /*update the atime*/ - node->nn_stat.st_atim = *atime; - else - /*the current time will be set as the atime*/ - flags |= TOUCH_ATIME; - - /*If mtime is to be updated*/ - if(mtime) - /*update the mtime*/ - node->nn_stat.st_mtim = *mtime; - else - /*the current time will be set as mtime*/ - flags |= TOUCH_MTIME; - - /*touch the file*/ - fshelp_touch(&node->nn_stat, flags, maptime); - } - - /*Return the result of operations*/ - return err; -}/*netfs_attempt_utimes*/ -/*----------------------------------------------------------------------------*/ -/*Returns the valid access types for file `node` and user `cred`*/ -error_t -netfs_report_access -( - struct iouser * cred, - struct node * np, - int * types -) -{ - LOG_MSG("netfs_report_access"); - - /*No access at first*/ - *types = 0; - - /*Check the access and set the required bits*/ - if(fshelp_access(&np->nn_stat, S_IREAD, cred) == 0) - *types |= O_READ; - if(fshelp_access(&np->nn_stat, S_IWRITE, cred) == 0) - *types |= O_WRITE; - if(fshelp_access(&np->nn_stat, S_IEXEC, cred) == 0) - *types |= O_EXEC; - - /*Everything OK*/ - return 0; -}/*netfs_report_access*/ -/*----------------------------------------------------------------------------*/ -/*Validates the stat data for the node*/ -error_t -netfs_validate_stat -( - struct node * np, - struct iouser * cred -) -{ - LOG_MSG("netfs_validate_stat: '%s'", np->nn->lnode->name); - - error_t err = 0; - - /*If we are not at the root*/ - if(np != netfs_root_node) - { - /*If the node is not surely up-to-date*/ - if(!(np->nn->flags & FLAG_NODE_ULFS_UPTODATE)) - { - /*update it*/ - err = node_update(np); - } - - /*If no errors have yet occurred*/ - if(!err) - { - /*If the port to the file corresponding to `np` is valid*/ - if(np->nn->port != MACH_PORT_NULL) - { - /*We have a directory here (normally, only they maintain an open port). - Generally, our only concern is to maintain an open port in this case*/ - - /*attempt to stat this file*/ - err = io_stat(np->nn->port, &np->nn_stat); - - /*If stat information has been successfully obtained for the file*/ - if(!err) - /*duplicate the st_mode field of stat structure*/ - np->nn_translated = np->nn_stat.st_mode; - } - else - { - /*We, most probably, have something which is not a directory. Therefore - we will open the port and close it after the stat, so that additional - resources are not consumed.*/ - - /*the parent node of the current node*/ - node_t * dnp; - - /*obtain the parent node of the the current node*/ - err = ncache_node_lookup(np->nn->lnode->dir, &dnp); - - /*the lookup should never fail here*/ - assert(!err); - - /*open a port to the file we are interested in*/ - mach_port_t p = file_name_lookup_under - (dnp->nn->port, np->nn->lnode->name, 0, 0); - - /*put `dnp` back, since we don't need it any more*/ - netfs_nput(dnp); - - if(!p) - return EBADF; - - /*try to stat the node*/ - err = io_stat(p, &np->nn_stat); - - /*deallocate the port*/ - PORT_DEALLOC(p); - } - } - } - /*If we are at the root*/ - else - /*put the size of the node into the stat structure belonging to `np`*/ - node_get_size(np, (OFFSET_T *)&np->nn_stat.st_size); - - /*Return the result of operations*/ - return err; -}/*netfs_validate_stat*/ -/*----------------------------------------------------------------------------*/ -/*Syncs `node` completely to disk*/ -error_t -netfs_attempt_sync -( - struct iouser * cred, - struct node * node, - int wait -) -{ - LOG_MSG("netfs_attempt_sync"); - - /*Operation is not supported*/ - return EOPNOTSUPP; -}/*netfs_attempt_sync*/ -/*----------------------------------------------------------------------------*/ -/*Fetches a directory*/ -error_t -netfs_get_dirents -( - struct iouser * cred, - struct node * dir, - int first_entry, - int num_entries, - char ** data, - mach_msg_type_number_t * data_len, - vm_size_t max_data_len, - int * data_entries -) -{ - LOG_MSG("netfs_get_dirents: '%s'", dir->nn->lnode->name); - - error_t err; - - /*Two pointers required for processing the list of dirents*/ - node_dirent_t * dirent_start, * dirent_current; - - /*The pointer to the beginning of the list of dirents*/ - node_dirent_t * dirent_list = NULL; - - /*The size of the current dirent*/ - size_t size = 0; - - /*The number of dirents added*/ - int count = 0; - - /*The dereferenced value of parameter `data`*/ - char * data_p; - - /*Takes into account the size of the given dirent*/ - int - bump_size - ( - const char * name - ) - { - /*If the required number of entries has not been listed yet*/ - if((num_entries == -1) || (count < num_entries)) - { - /*take the current size and take into account the length of the name*/ - size_t new_size = size + DIRENT_LEN(strlen(name)); - - /*If there is a limit for the received size and it has been exceeded*/ - if((max_data_len > 0) && (new_size > max_data_len)) - /*a new dirent cannot be added*/ - return 0; - - /*memorize the new size*/ - size = new_size; - - /*increase the number of dirents added*/ - ++count; - - /*everything is OK*/ - return 1; - } - else - { - /*dirents cannot be added*/ - return 0; - } - }/*bump_size*/ - - /*Adds a dirent to the list of dirents*/ - int - add_dirent - ( - const char * name, - ino_t ino, - int type - ) - { - /*If the required number of dirents has not been listed yet*/ - if((num_entries == -1) || (count < num_entries)) - { - /*create a new dirent*/ - struct dirent hdr; - - /*obtain the length of the name*/ - size_t name_len = strlen(name); - - /*compute the full size of the dirent*/ - size_t sz = DIRENT_LEN(name_len); - - /*If there is no room for this dirent*/ - if(sz > size) - /*stop*/ - return 0; - else - /*take into account the fact that a new dirent has just been added*/ - size -= sz; - - /*setup the dirent*/ - hdr.d_ino = ino; - hdr.d_reclen = sz; - hdr.d_type = type; - hdr.d_namlen = name_len; - - /*The following two lines of code reflect the old layout of - dirents in the memory. Now libnetfs expects the layout - identical to the layout provided by dir_readdir (see dir_entries_get)*/ - - /*copy the header of the dirent into the final block of dirents*/ - memcpy(data_p, &hdr, DIRENT_NAME_OFFS); - - /*copy the name of the dirent into the block of dirents*/ - strcpy(data_p + DIRENT_NAME_OFFS, name); - - /*This line is commented for the same reason as the two specifically - commented lines above.*/ - /*move the current pointer in the block of dirents*/ - data_p += sz; - - /*count the new dirent*/ - ++count; - - /*everything was OK, so say it*/ - return 1; - } - else - /*no [new] dirents allowed*/ - return 0; - }/*add_dirent*/ - - /*List the dirents for node `dir`*/ - err = node_entries_get(dir, &dirent_list); - - /*If listing was successful*/ - if(!err) - { - /*find the entry whose number is `first_entry`*/ - for - ( - dirent_start = dirent_list, count = 2; - dirent_start && (count < first_entry); - dirent_start = dirent_start->next, ++count - ); - - /*reset number of dirents added so far*/ - count = 0; - - /*make space for entries '.' and '..', if required*/ - if(first_entry == 0) - bump_size("."); - if(first_entry <= 1) - bump_size(".."); - - /*Go through all dirents*/ - for - ( - dirent_current = dirent_start; - dirent_current; - dirent_current = dirent_current->next - ) - /*If another dirent cannot be added succesfully*/ - if(bump_size(dirent_current->dirent->d_name) == 0) - /*stop here*/ - break; - - /*allocate the required space for dirents*/ - *data = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON, 0, 0); - - /*check if any error occurred*/ - err = ((void *)*data == MAP_FAILED) ? (errno) : (0); - } - - /*If no errors have occurred so far*/ - if(!err) - { - /*obtain the pointer to the beginning of the block of dirents*/ - data_p = *data; - - /*fill the parameters with useful values*/ - *data_len = size; - *data_entries = count; - - /*reset the number of dirents added*/ - count = 0; - - /*add entries '.' and '..', if required*/ - if(first_entry == 0) - add_dirent(".", 2, DT_DIR); - if(first_entry <= 1) - add_dirent("..", 2, DT_DIR); - - /*Follow the list of dirents beginning with dirents_start*/ - for - ( - dirent_current = dirent_start; dirent_current; - dirent_current = dirent_current->next - ) - /*If the addition of the current dirent fails*/ - if - ( - add_dirent - (dirent_current->dirent->d_name, dirent_current->dirent->d_fileno, - dirent_current->dirent->d_type) == 0 - ) - /*stop adding dirents*/ - break; - } - - /*If the list of dirents has been allocated, free it*/ - if(dirent_list) - node_entries_free(dirent_list); - - /*The directory has been read right now, modify the access time*/ - fshelp_touch(&dir->nn_stat, TOUCH_ATIME, maptime); - - /*Return the result of listing the dirents*/ - return err; -}/*netfs_get_dirents*/ -/*----------------------------------------------------------------------------*/ -/*Looks up `name` under `dir` for `user`*/ -error_t -netfs_attempt_lookup -( - struct iouser * user, - struct node * dir, - char * name, - struct node ** node -) -{ - LOG_MSG("netfs_attempt_lookup: '%s'", name); - - error_t err = 0; - - /*If we are asked to fetch the current directory*/ - if(strcmp(name, ".") == 0) - { - /*add a reference to `dir` and put it into `node`*/ - netfs_nref(dir); - *node = dir; - - /*everything is OK*/ - return 0; - } - /*If we are asked to fetch the parent directory*/ - else if(strcmp(name, "..") == 0) - { - /*If the supplied node is not root*/ - if(dir->nn->lnode->dir) - { - /*The node corresponding to the parent directory must exist here*/ - assert(dir->nn->lnode->dir->node); - - /*put the parent node of `dir` into the result*/ - err = ncache_node_lookup(dir->nn->lnode->dir, node); - } - /*The supplied node is root*/ - else - { - /*this node is not included into our filesystem*/ - err = ENOENT; - *node = NULL; - } - - /*unlock the directory*/ - mutex_unlock(&dir->lock); - - /*stop here*/ - return err; - } - - /*Checks whether the given name satisfied the required property*/ - int - check_property - ( - const char * name - ) - { - /*If there is no property*/ - if(!property) - /*no filtering will be applied, any name is OK*/ - return 0; - - /*The number of occurrences of PROPERTY_PARAM in the property*/ - int param_entries_count = 0; - - /*The pointer to the current occurrence of PROPERTY_PARAM*/ - char * occurrence = strstr(property, PROPERTY_PARAM); - - /*Count the number of occurrences*/ - for(; occurrence; - occurrence = strstr(occurrence + 1, PROPERTY_PARAM), - ++param_entries_count); - - /*Compute the length of the property param*/ - size_t property_param_len = strlen(PROPERTY_PARAM); - - /*The length of the property*/ - size_t property_len = (property) ? (strlen(property)) : (0); - - /*Everything OK at first*/ - err = 0; - - /*Compute the length of the full name once*/ - size_t full_name_len = strlen(dir->nn->lnode->path) + 1 + strlen(name) + 1; - - /*Try to allocate the required space*/ - char * full_name = malloc(full_name_len); - if(!full_name) - { - err = ENOMEM; - return 0; - } - - /*Initialize `full_name` as a valid string*/ - full_name[0] = 0; - - /*Construct the full name*/ - strcpy(full_name, dir->nn->lnode->path); - strcat(full_name, "/"); - strcat(full_name, name); - - LOG_MSG("netfs_attempt_lookup: Applying filter to %s...", full_name); - - /*Compute the space required for the final filtering command*/ - size_t sz = property_len + (strlen(full_name) - property_param_len) - * param_entries_count; - - /*Try to allocate the space for the command*/ - char * cmd = malloc(sz); - if(!cmd) - { - free(full_name); - err = ENOMEM; - return 0; - } - - /*Initialize `cmd` as a valid string*/ - cmd[0] = 0; - - /*The current occurence of PROPERTY_PARAM in property*/ - char * p = strstr(property, PROPERTY_PARAM); - - /*The pointer to the current position in the property*/ - char * propp = property; - - /*While the command has not been constructed*/ - for(; p; p = strstr(propp, PROPERTY_PARAM)) - { - /*add the new part of the property to the command*/ - strncat(cmd, propp, p - propp); - - /*add the filename to the command*/ - strcat(cmd, full_name); - - /*LOG_MSG("\tcmd = '%s'", cmd);*/ - - /*advance the pointer in the property*/ - propp = p + property_param_len; - - /*LOG_MSG("\tpropp points at '%s'", propp);*/ - } - - /*Copy the rest of the property to the command*/ - strcat(cmd, propp); - - /*LOG_MSG("node_entries_get: The filtering command: '%s'.", cmd);*/ - - /*Execute the command*/ - int xcode = WEXITSTATUS(system(cmd)); - - /*Return the exit code of the command*/ - return xcode; - }/*check_property*/ - - /*If the given name does not satisfy the property*/ - if(check_property(name) != 0) - { - /*unlock the directory*/ - mutex_unlock(&dir->lock); - - /*no such file in the directory*/ - return ENOENT; - } - - /*Try to lookup the given file in the underlying directory*/ - mach_port_t p = file_name_lookup_under(dir->nn->port, name, 0, 0); - - /*If the lookup failed*/ - if(p == MACH_PORT_NULL) - { - /*unlock the directory*/ - mutex_unlock(&dir->lock); - - /*no such entry*/ - return ENOENT; - } - - /*Obtain the stat information about the file*/ - io_statbuf_t stat; - err = io_stat(p, &stat); - - /*Deallocate the obtained port*/ - PORT_DEALLOC(p); - - /*If this file is not a directory*/ - if(err || !S_ISDIR(stat.st_mode)) - { - /*do not set the port*/ - p = MACH_PORT_NULL; - } - else - { - /*lookup the port with the right to read the contents of the directory*/ - p = file_name_lookup_under(dir->nn->port, name, O_READ | O_DIRECTORY, 0); - if(p == MACH_PORT_NULL) - { - return EBADF; /*not enough rights?*/ - } - } - - /*The lnode corresponding to the entry we are supposed to fetch*/ - lnode_t * lnode; - - /*Finalizes the execution of this function*/ - void - finalize(void) - { - /*If some errors have occurred*/ - if(err) - { - /*the user should receive nothing*/ - *node = NULL; - - /*If there is some port, free it*/ - if(p != MACH_PORT_NULL) - PORT_DEALLOC(p); - } - /*If there is a node to return*/ - if(*node) - { - /*unlock the node*/ - mutex_unlock(&(*node)->lock); - - /*add the node to the cache*/ - ncache_node_add(*node); - } - - /*Unlock the mutexes in `dir`*/ - mutex_unlock(&dir->nn->lnode->lock); - mutex_unlock(&dir->lock); - }/*finalize*/ - - /*Try to find an lnode called `name` under the lnode corresponding to `dir`*/ - err = lnode_get(dir->nn->lnode, name, &lnode); - - /*If such an entry does not exist*/ - if(err == ENOENT) - { - /*create a new lnode with the supplied name*/ - err = lnode_create(name, &lnode); - if(err) - { - finalize(); - return err; - } - - /*install the new lnode into the directory*/ - lnode_install(dir->nn->lnode, lnode); - } - - /*Obtain the node corresponding to this lnode*/ - err = ncache_node_lookup(lnode, node); - - /*Remove an extra reference from the lnode*/ - lnode_ref_remove(lnode); - - /*If the lookup in the cache failed*/ - if(err) - { - /*stop*/ - finalize(); - return err; - } - - /*Store the port in the node*/ - (*node)->nn->port = p; - - /*Construct the full path to the node*/ - err = lnode_path_construct(lnode, NULL); - if(err) - { - finalize(); - return err; - } - - /*Now the node is up-to-date*/ - (*node)->nn->flags = FLAG_NODE_ULFS_UPTODATE; - - /*Return the result of performing the operations*/ - finalize(); - return err; -}/*netfs_attempt_lookup*/ -/*----------------------------------------------------------------------------*/ -/*Deletes `name` in `dir` for `user`*/ -error_t -netfs_attempt_unlink -( - struct iouser * user, - struct node * dir, - char * name -) -{ - LOG_MSG("netfs_attempt_unlink"); - - return 0; -}/*netfs_attempt_unlink*/ -/*----------------------------------------------------------------------------*/ -/*Attempts to rename `fromdir`/`fromname` to `todir`/`toname`*/ -error_t -netfs_attempt_rename -( - struct iouser * user, - struct node * fromdir, - char * fromname, - struct node * todir, - char * toname, - int excl -) -{ - LOG_MSG("netfs_attempt_rename"); - - /*Operation not supported*/ - return EOPNOTSUPP; -}/*netfs_attempt_rename*/ -/*----------------------------------------------------------------------------*/ -/*Attempts to create a new directory*/ -error_t -netfs_attempt_mkdir -( - struct iouser * user, - struct node * dir, - char * name, - mode_t mode -) -{ - LOG_MSG("netfs_attempt_mkdir"); - - return 0; -}/*netfs_attempt_mkdir*/ -/*----------------------------------------------------------------------------*/ -/*Attempts to remove directory `name` in `dir` for `user`*/ -error_t -netfs_attempt_rmdir -( - struct iouser * user, - struct node * dir, - char * name -) -{ - LOG_MSG("netfs_attempt_rmdir"); - - return 0; -}/*netfs_attempt_rmdir*/ -/*----------------------------------------------------------------------------*/ -/*Attempts to change the mode of `node` for user `cred` to `uid`:`gid`*/ -error_t -netfs_attempt_chown -( - struct iouser * cred, - struct node * node, - uid_t uid, - uid_t gid -) -{ - LOG_MSG("netfs_attempt_chown"); - - /*Operation is not supported*/ - return EOPNOTSUPP; -}/*netfs_attempt_chown*/ -/*----------------------------------------------------------------------------*/ -/*Attempts to change the author of `node` to `author`*/ -error_t -netfs_attempt_chauthor -( - struct iouser * cred, - struct node * node, - uid_t author -) -{ - LOG_MSG("netfs_attempt_chauthor"); - - /*Operation is not supported*/ - return EOPNOTSUPP; -}/*netfs_attempt_chauthor*/ -/*----------------------------------------------------------------------------*/ -/*Attempts to change the mode of `node` to `mode` for `cred`*/ -error_t -netfs_attempt_chmod -( - struct iouser * user, - struct node * node, - mode_t mode -) -{ - LOG_MSG("netfs_attempt_chmod"); - - /*Operation is not supported*/ - return EOPNOTSUPP; -}/*netfs_attempt_chmod*/ -/*----------------------------------------------------------------------------*/ -/*Attempts to turn `node` into a symlink targetting `name`*/ -error_t -netfs_attempt_mksymlink -( - struct iouser * cred, - struct node * node, - char * name -) -{ - LOG_MSG("netfs_attempt_mksymlink"); - - /*Operation is not supported*/ - return EOPNOTSUPP; -}/*netfs_attempt_mksymlink*/ -/*----------------------------------------------------------------------------*/ -/*Attempts to turn `node` into a device; type can be either S_IFBLK or S_IFCHR*/ -error_t -netfs_attempt_mkdev -( - struct iouser * cred, - struct node * node, - mode_t type, - dev_t indexes -) -{ - LOG_MSG("netfs_attempt_mkdev"); - - /*Operation is not supported*/ - return EOPNOTSUPP; -}/*netfs_attempt_mkdev*/ -/*----------------------------------------------------------------------------*/ -/*Attempts to set the passive translator record for `file` passing `argz`*/ -error_t -netfs_set_translator -( - struct iouser * cred, - struct node * node, - char * argz, - size_t arglen -) -{ - LOG_MSG("netfs_set_translator"); - - /*Operation is not supported*/ - return EOPNOTSUPP; -}/*netfs_set_translator */ -/*----------------------------------------------------------------------------*/ -/*Attempts to call chflags for `node`*/ -error_t -netfs_attempt_chflags -( - struct iouser * cred, - struct node * node, - int flags -) -{ - LOG_MSG("netfs_attempt_chflags"); - - /*Operation is not supported*/ - return EOPNOTSUPP; -}/*netfs_attempt_chflags*/ -/*----------------------------------------------------------------------------*/ -/*Attempts to set the size of file `node`*/ -error_t -netfs_attempt_set_size -( - struct iouser * cred, - struct node * node, - loff_t size -) -{ - LOG_MSG("netfs_attempt_set_size"); - - /*Operation is not supported*/ - return EOPNOTSUPP; -}/*netfs_attempt_set_size*/ -/*----------------------------------------------------------------------------*/ -/*Fetches the filesystem status information*/ -error_t -netfs_attempt_statfs -( - struct iouser * cred, - struct node * node, - fsys_statfsbuf_t * st -) -{ - LOG_MSG("netfs_attempt_statfs"); - - /*Operation is not supported*/ - return EOPNOTSUPP; -}/*netfs_attempt_statfs*/ -/*----------------------------------------------------------------------------*/ -/*Syncs the filesystem*/ -error_t -netfs_attempt_syncfs -( - struct iouser * cred, - int wait -) -{ - LOG_MSG("netfs_attempt_syncfs"); - - /*Everythin OK*/ - return 0; -}/*netfs_attempt_syncfs*/ -/*----------------------------------------------------------------------------*/ -/*Creates a link in `dir` with `name` to `file`*/ -error_t -netfs_attempt_link -( - struct iouser * user, - struct node * dir, - struct node * file, - char * name, - int excl -) -{ - LOG_MSG("netfs_attempt_link"); - - /*Operation not supported*/ - return EOPNOTSUPP; -}/*netfs_attempt_link*/ -/*----------------------------------------------------------------------------*/ -/*Attempts to create an anonymous file related to `dir` with `mode`*/ -error_t -netfs_attempt_mkfile -( - struct iouser * user, - struct node * dir, - mode_t mode, - struct node ** node -) -{ - LOG_MSG("netfs_attempt_mkfile"); - - /*Unlock the directory*/ - mutex_unlock(&dir->lock); - - /*Operation not supported*/ - return EOPNOTSUPP; -}/*netfs_attempt_mkfile*/ -/*----------------------------------------------------------------------------*/ -/*Reads the contents of symlink `node` into `buf`*/ -error_t -netfs_attempt_readlink -( - struct iouser * user, - struct node * node, - char * buf -) -{ - LOG_MSG("netfs_attempt_readlink"); - - /*Operation not supported (why?..)*/ - return EOPNOTSUPP; -}/*netfs_attempt_readlink*/ -/*----------------------------------------------------------------------------*/ -/*Reads from file `node` up to `len` bytes from `offset` into `data`*/ -error_t -netfs_attempt_read -( - struct iouser * cred, - struct node * np, - loff_t offset, - size_t * len, - void * data -) -{ - LOG_MSG("netfs_attempt_read"); - - error_t err = 0; - - /*If there is no port open for the current node*/ - if(np->nn->port == MACH_PORT_NULL) - { - /*the parent node of the current node*/ - node_t * dnp; - - /*obtain the parent node of the the current node*/ - err = ncache_node_lookup(np->nn->lnode->dir, &dnp); - - /*the lookup should never fail here*/ - assert(!err); - - /*open a port to the file we are interested in*/ - mach_port_t p = file_name_lookup_under - (dnp->nn->port, np->nn->lnode->name, O_READ, 0); - - /*put `dnp` back, since we don't need it any more*/ - netfs_nput(dnp); - - if(!p) - return EBADF; - - /*store the port in the node*/ - np->nn->port = p; - } - - /*Read the required data from the file*/ - err = io_read(np->nn->port, (char **)&data, len, offset, *len); - - /*Return the result of reading*/ - return err; -}/*netfs_attempt_read*/ -/*----------------------------------------------------------------------------*/ -/*Writes to file `node` up to `len` bytes from offset from `data`*/ -error_t -netfs_attempt_write -( - struct iouser * cred, - struct node * node, - loff_t offset, - size_t * len, - void * data -) -{ - LOG_MSG("netfs_attempt_write"); - - return 0; -}/*netfs_attempt_write*/ -/*----------------------------------------------------------------------------*/ -/*Frees all storage associated with the node*/ -void -netfs_node_norefs -( - struct node * np -) -{ - /*Destroy the node*/ - node_destroy(np); -}/*netfs_node_norefs*/ -/*----------------------------------------------------------------------------*/ -/*Entry point*/ -int -main -( - int argc, - char ** argv -) -{ - /*Start logging*/ - INIT_LOG(); - LOG_MSG(">> Starting initialization..."); - - /*The port on which this translator will be set upon*/ - mach_port_t bootstrap_port; - - error_t err = 0; - - /*Parse the command line arguments*/ - argp_parse(&argp_startup, argc, argv, ARGP_IN_ORDER, 0, 0); - LOG_MSG("Command line arguments parsed."); - - /*Try to create the root node*/ - err = node_create_root(&netfs_root_node); - if(err) - error(EXIT_FAILURE, err, "Failed to create the root node"); - LOG_MSG("Root node created."); - - /*Obtain the bootstrap port*/ - task_get_bootstrap_port(mach_task_self(), &bootstrap_port); - - /*Initialize the translator*/ - netfs_init(); - - /*Obtain a port to the underlying node*/ - underlying_node = netfs_startup(bootstrap_port, O_READ); - LOG_MSG("netfs initialization complete."); - - /*Initialize the root node*/ - err = node_init_root(netfs_root_node); - if(err) - error(EXIT_FAILURE, err, "Failed to initialize the root node"); - LOG_MSG("Root node initialized."); - LOG_MSG("\tRoot node address: 0x%lX", (unsigned long)netfs_root_node); - - /*Map the time for updating node information*/ - err = maptime_map(0, 0, &maptime); - if(err) - error(EXIT_FAILURE, err, "Failed to map the time"); - LOG_MSG("Time mapped."); - - /*Initialize the cache with the required number of nodes*/ - ncache_init(ncache_size); - LOG_MSG("Cache initialized."); - - /*Obtain stat information about the underlying node*/ - err = io_stat(underlying_node, &underlying_node_stat); - if(err) - error(EXIT_FAILURE, err, - "Cannot obtain stat information about the underlying node"); - LOG_MSG("Stat information for undelying node obtained."); - - /*Obtain the ID of the current process*/ - fsid = getpid(); - - /*Setup the stat information for the root node*/ - netfs_root_node->nn_stat = underlying_node_stat; - - netfs_root_node->nn_stat.st_ino = FILTERFS_ROOT_INODE; - netfs_root_node->nn_stat.st_fsid = fsid; - netfs_root_node->nn_stat.st_mode = S_IFDIR | (underlying_node_stat.st_mode - & ~S_IFMT & ~S_ITRANS); /*we are providing a translated directory*/ - - netfs_root_node->nn_translated = netfs_root_node->nn_stat.st_mode; - - /*If the underlying node is not a directory, enhance the permissions - of the root node of filterfs*/ - if(!S_ISDIR(underlying_node_stat.st_mode)) - { - /*can be read by owner*/ - if(underlying_node_stat.st_mode & S_IRUSR) - /*allow execution by the owner*/ - netfs_root_node->nn_stat.st_mode |= S_IXUSR; - /*can be read by group*/ - if(underlying_node_stat.st_mode & S_IRGRP) - /*allow execution by the group*/ - netfs_root_node->nn_stat.st_mode |= S_IXGRP; - /*can be read by others*/ - if(underlying_node_stat.st_mode & S_IROTH) - /*allow execution by the others*/ - netfs_root_node->nn_stat.st_mode |= S_IXOTH; - } - - /*Update the timestamps of the root node*/ - fshelp_touch - (&netfs_root_node->nn_stat, TOUCH_ATIME | TOUCH_MTIME | TOUCH_CTIME, - maptime); - - LOG_MSG(">> Initialization complete. Entering netfs server loop..."); - - /*Start serving clients*/ - for(;;) - netfs_server_loop(); -}/*main*/ -/*----------------------------------------------------------------------------*/ diff --git a/netfs-sample/filterfs.h b/netfs-sample/filterfs.h deleted file mode 100644 index 4470a7fb..00000000 --- a/netfs-sample/filterfs.h +++ /dev/null @@ -1,453 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/*filter.h*/ -/*----------------------------------------------------------------------------*/ -/*The definitions for the filtering translator*/ -/*----------------------------------------------------------------------------*/ -/*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ -/*Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA.*/ -/*----------------------------------------------------------------------------*/ -#ifndef __FILTERFS_H__ -#define __FILTERFS_H__ -/*----------------------------------------------------------------------------*/ -#include <stddef.h> -#include <stdlib.h> -#include <cthreads.h> -#include <unistd.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/statfs.h> -#include <sys/time.h> -#include <hurd/ihash.h> -#include <hurd/iohelp.h> -/*----------------------------------------------------------------------------*/ -#include "lib.h" -#include "node.h" -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Macros--------------------------------------------------------------*/ -/*The inode for the root node*/ -#define FILTERFS_ROOT_INODE 1 -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ -/*A mapped time value for filterfs*/ -/*Required for a very fast access to time*/ -extern volatile struct mapped_time_value * maptime; -/*----------------------------------------------------------------------------*/ -/*A port to the underlying node*/ -extern mach_port_t underlying_node; -/*----------------------------------------------------------------------------*/ -/*The stat information about the underlying node*/ -extern io_statbuf_t underlying_node_stat; -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Structures----------------------------------------------------------*/ -/*A single entry in a directory*/ -struct filterfs_dir_entry - { - char * name; /*name of the entry*/ - size_t hv; /*hash value of NAME*/ - - struct node * node; /*the active node referred to by this node (may be 0)*/ - /*NETFS_NDOE_REFCNT_LOCK should be hel whule frobbing this*/ - - struct stat stat; /*status information*/ - - char * symlink_target; /*the name of the node this entry might refer to*/ - - time_t stat_timestamp; /*the moment at which the status information was retreieved*/ - - /*the directory to which this entry belongs*/ - struct filterfs_dir * dir; - - /*link to the entry in hash bucket and the address of the previous entry's - (or hashtable's) pointer to this entry*/ - /*If self_p is null, then this entry is deleted and awaiting - the final disposal*/ - struct filterfs_dir_entry * next, ** self_p; - - /*the next and the previous entries in the 'directory order'; 0 if there - are none*/ - struct filterfs_dir_entry * ordered_next, ** ordered_self_p; - - /*when the presence/absence of this file was last checked*/ - time_t name_timestamp; - - /*used for removing this entry*/ - hurd_ihash_locp_t inode_locp; - - /*a field for a negative result of lookup*/ - int noent : 1; - - /*a marker for gabage collecting*/ - int valid : 1; - };/*struct filterfs_dir_entry*/ -/*----------------------------------------------------------------------------*/ -/*A directory*/ -struct filterfs_dir - { - /*the number of entries in the hash table*/ - size_t num_entries; - - /*the number of entries that have nodes attached*/ - /*We keep an additional reference to our node if there is any, - to prevent it from going away*/ - size_t num_live_entries; - - /*the hash table for entries*/ - struct filterfs_dir_entry ** htable; - size_t htable_len; /*the lenght of the hash table*/ - - /*the list of entries in 'directory order'.*/ - /*The entries are listed in a linked list using the ordered_next - and ordered_self_p fields in each entry. Not all entries in htable - need to be in this list*/ - struct filterfs_dir_entry * ordered; - - /*the filesystem node corresponding to this directory*/ - struct node * node; - - /*the filesystem this directory is in*/ - struct filterfs * fs; - - /*when the presence/absence of this file was last checked*/ - time_t name_timestamp; - - /*used for removing this entry*/ - hurd_ihash_locp_t inode_locp; - - /*Stuff for detecting bulk stats (?)*/ - /*Might be reduntant for this project*/ - - /*the timestamp of the first sample in bulk_stat_count1, rounded to - BULK_STAT_PERIOD seconds*/ - time_t buld_stat_base_stamp; - - /*the number of stats done in the period - [bulk_stat_base_stamp, bulk_stat_base_stamp + BULK_STAT_PERIOD]*/ - unsigned bulk_stat_count_first_half; - - /*the number of stats done in the period - [bulk_stat_bast_stamp + BULK_STAT_PERIOD, - bulk_stat_bast_stamp + 2 * BULK_STAT_PERIOD]*/ - unsigned bulk_stat_count_second_half; - };/*struct filterfs_dir*/ -/*----------------------------------------------------------------------------*/ -/*A particular filesystem*/ -struct filterfs - { - /*the root of the filesystem*/ - struct node * root; - - /*inode numbers*/ - /*Assigned sequentially in the order of creation*/ - ino_t next_inode; - - /*the identifier of the filesystem (?)*/ - int fsid; - - /*a hash table mapping inode numbers to directory entries*/ - struct hurd_ihash inode_mappings; - - /*the lock for the hash table*/ - spin_lock_t inode_mappings_lock; - };/*struct filterfs*/ -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ -/*Attempts to create a file named `name` in `dir` for `user` with mode `mode`*/ -error_t -netfs_attempt_create_file - ( - struct iouser * user, - struct node * dir, - char * name, - mode_t mode, - struct node ** node - ); -/*----------------------------------------------------------------------------*/ -/*Returns an error if the process of opening a file should not be allowed - to complete because of insufficient permissions*/ -error_t -netfs_check_open_permissions - ( - struct iouser * user, - struct node * np, - int flags, - int newnode - ); -/*----------------------------------------------------------------------------*/ -/*Attempts an utimes call for the user `cred` on node `node`*/ -error_t -netfs_attempt_utimes - ( - struct iouser * cred, - struct node * node, - struct timespec * atime, - struct timespec * mtime - ); -/*----------------------------------------------------------------------------*/ -/*Returns the valid access types for file `node` and user `cred`*/ -error_t -netfs_report_access - ( - struct iouser * cred, - struct node * np, - int * types - ); -/*----------------------------------------------------------------------------*/ -/*Validates the stat data for the node*/ -error_t -netfs_validate_stat - ( - struct node * np, - struct iouser * cred - ); -/*----------------------------------------------------------------------------*/ -/*Syncs `node` completely to disk*/ -error_t -netfs_attempt_sync - ( - struct iouser * cred, - struct node * node, - int wait - ); -/*----------------------------------------------------------------------------*/ -/*Fetches a directory*/ -error_t -netfs_get_dirents - ( - struct iouser * cred, - struct node * dir, - int first_entry, - int num_entries, - char ** data, - mach_msg_type_number_t * data_len, - vm_size_t max_data_len, - int * data_entries - ); -/*----------------------------------------------------------------------------*/ -/*Looks up `name` under `dir` for `user`*/ -error_t -netfs_attempt_lookup - ( - struct iouser * user, - struct node * dir, - char * name, - struct node ** node - ); -/*----------------------------------------------------------------------------*/ -/*Deletes `name` in `dir` for `user`*/ -error_t -netfs_attempt_unlink - ( - struct iouser * user, - struct node * dir, - char * name - ); -/*----------------------------------------------------------------------------*/ -/*Attempts to rename `fromdir`/`fromname` to `todir`/`toname`*/ -error_t -netfs_attempt_rename - ( - struct iouser * user, - struct node * fromdir, - char * fromname, - struct node * todir, - char * toname, - int excl - ); -/*----------------------------------------------------------------------------*/ -/*Attempts to create a new directory*/ -error_t -netfs_attempt_mkdir - ( - struct iouser * user, - struct node * dir, - char * name, - mode_t mode - ); -/*----------------------------------------------------------------------------*/ -/*Attempts to remove directory `name` in `dir` for `user`*/ -error_t -netfs_attempt_rmdir - ( - struct iouser * user, - struct node * dir, - char * name - ); -/*----------------------------------------------------------------------------*/ -/*Attempts to change the owner of `node` for user `cred` to `uid`:`gid`*/ -error_t -netfs_attempt_chown - ( - struct iouser * cred, - struct node * node, - uid_t uid, - uid_t gid - ); -/*----------------------------------------------------------------------------*/ -/*Attempts to change the author of `node` to `author`*/ -error_t -netfs_attempt_chauthor - ( - struct iouser * cred, - struct node * node, - uid_t author - ); -/*----------------------------------------------------------------------------*/ -/*Attempts to change the mode of `node` to `mode` for `cred`*/ -error_t -netfs_attempt_chmod - ( - struct iouser * user, - struct node * node, - mode_t mode - ); -/*----------------------------------------------------------------------------*/ -/*Attempts to turn `node` into a symlink targetting `name`*/ -error_t -netfs_attempt_mksymlink - ( - struct iouser * cred, - struct node * node, - char * name - ); -/*----------------------------------------------------------------------------*/ -/*Attempts to turn `node` into a device; type can be either S_IFBLK or S_IFCHR*/ -error_t -netfs_attempt_mkdev - ( - struct iouser * cred, - struct node * node, - mode_t type, - dev_t indexes - ); -/*----------------------------------------------------------------------------*/ -/*Attempts to set the passive translator record for `file` passing `argz`*/ -error_t -netfs_set_translator - ( - struct iouser * cred, - struct node * node, - char * argz, - size_t arglen - ); -/*----------------------------------------------------------------------------*/ -/*Attempts to call chflags for `node`*/ -error_t -netfs_attempt_chflags - ( - struct iouser * cred, - struct node * node, - int flags - ); -/*----------------------------------------------------------------------------*/ -/*Attempts to set the size of file `node`*/ -error_t -netfs_attempt_set_size - ( - struct iouser * cred, - struct node * node, - loff_t size - ); -/*----------------------------------------------------------------------------*/ -/*Fetches the filesystem status information*/ -error_t -netfs_attempt_statfs - ( - struct iouser * cred, - struct node * node, - fsys_statfsbuf_t * st - ); -/*----------------------------------------------------------------------------*/ -/*Syncs the filesystem*/ -error_t -netfs_attempt_syncfs - ( - struct iouser * cred, - int wait - ); -/*----------------------------------------------------------------------------*/ -/*Creates a link in `dir` with `name` to `file`*/ -error_t -netfs_attempt_link - ( - struct iouser * user, - struct node * dir, - struct node * file, - char * name, - int excl - ); -/*----------------------------------------------------------------------------*/ -/*Attempts to create an anonymous file related to `dir` with `mode`*/ -error_t -netfs_attempt_mkfile - ( - struct iouser * user, - struct node * dir, - mode_t mode, - struct node ** node - ); -/*----------------------------------------------------------------------------*/ -/*Reads the contents of symlink `node` into `buf`*/ -error_t -netfs_attempt_readlink - ( - struct iouser * user, - struct node * node, - char * buf - ); -/*----------------------------------------------------------------------------*/ -/*Reads from file `node` up to `len` bytes from `offset` into `data`*/ -error_t -netfs_attempt_read - ( - struct iouser * cred, - struct node * np, - loff_t offset, - size_t * len, - void * data - ); -/*----------------------------------------------------------------------------*/ -/*Writes to file `node` up to `len` bytes from offset from `data`*/ -error_t -netfs_attempt_write - ( - struct iouser * cred, - struct node * node, - loff_t offset, - size_t * len, - void * data - ); -/*----------------------------------------------------------------------------*/ -/*Frees all storage associated with the node*/ -void -netfs_node_norefs - ( - struct node * np - ); -/*----------------------------------------------------------------------------*/ -#endif diff --git a/netfs-sample/lib.c b/netfs-sample/lib.c deleted file mode 100644 index aa0ff0be..00000000 --- a/netfs-sample/lib.c +++ /dev/null @@ -1,193 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/*lib.h*/ -/*----------------------------------------------------------------------------*/ -/*Basic routines for filesystem manipulations*/ -/*----------------------------------------------------------------------------*/ -/*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ -/*Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA.*/ -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -#define _GNU_SOURCE 1 -/*----------------------------------------------------------------------------*/ -#include <sys/mman.h> -/*----------------------------------------------------------------------------*/ -#include "lib.h" -#include "debug.h" -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ -/*Fetches directory entries for `dir`*/ -error_t -dir_entries_get - ( - file_t dir, - char ** dirent_data, /*the list of directory entries as returned - by dir_readdir*/ - size_t * dirent_data_size, /*the size of `dirent_data`*/ - struct dirent *** dirent_list /*the array of pointers to beginnings of - dirents in dirent_data*/ - ) - { - error_t err = 0; - - /*The data (array of dirents(?)) returned by dir_readdir*/ - char * data; - - /*The size of `data`*/ - size_t data_size; - - /*The number of entries in `data`*/ - int entries_num; - - /*Try to read the contents of the specified directory*/ - err = dir_readdir(dir, &data, &data_size, 0, -1, 0, &entries_num); - if(err) - return err; - - /*Create a new list of dirents*/ - struct dirent ** list; - - /*Allocate the memory for the list of dirents and for the - finalizing element*/ - list = malloc(sizeof(struct dirent *) * (entries_num + 1)); - - /*If memory allocation has failed*/ - if(!list) - { - /*free the result of dir_readdir*/ - munmap(data, data_size); - - /*return the corresponding error*/ - return ENOMEM; - } - - /*The current directory entry*/ - struct dirent * dp; - - int i; - - /*Go through every element of the list of dirents*/ - for - ( - i = 0, dp = (struct dirent *)data; - i < entries_num; - ++i, dp = (struct dirent *)((char *)dp + dp->d_reclen)) - /*copy the current value into the list*/ - *(list + i) = dp; - - /*Nullify the last element of the list*/ - *(list + i) = NULL; - - /*Copy the required values in the parameters*/ - *dirent_data = data; - *dirent_data_size = data_size; - *dirent_list = list; - - /*Return success*/ - return err; - }/*dir_entries_get*/ -/*----------------------------------------------------------------------------*/ -/*Lookup `name` under `dir` (or cwd, if `dir` is invalid)*/ -error_t -file_lookup - ( - file_t dir, - char * name, - int flags0, /*try to open with these flags first*/ - int flags1, /*try to open with these flags, if `flags0` fail*/ - int mode, /*if the file is to be created, create it with this mode*/ - file_t * port, /*store the port to the looked up file here*/ - io_statbuf_t * stat /*store the stat information here*/ - ) - { - error_t err = 0; - - /*The port to the looked up file*/ - file_t p; - - /*The stat information about the looked up file*/ - io_statbuf_t s; - - /*Performs a lookup under 'dir' or in cwd, if `dir` is invalid*/ - file_t - do_file_lookup - ( - file_t dir, - char * name, /*lookup this file*/ - int flags, /*lookup the file with these flags*/ - int mode /*if a new file is to be created, create it with this mode*/ - ) - { - /*The result of lookup*/ - file_t p; - - /*If `dir` is a valid port*/ - if(dir != MACH_PORT_NULL) - /*try to lookup `name` under `dir`*/ - p = file_name_lookup_under(dir, name, flags, mode); - else - /*lookup `name` under current cwd*/ - p = file_name_lookup(name, flags, mode); - - /*Return the result of the lookup*/ - return p; - }/*do_file_lookup*/ - - /*Lookup `name` under the suggested `dir`*/ - p = do_file_lookup(dir, name, flags0, mode); - - /*If the lookup failed*/ - if(p == MACH_PORT_NULL) - /*try to lookup for `name` using alternative flags `flags1`*/ - p = do_file_lookup(dir, name, flags1, mode); - - /*If the port is valid*/ - if(p != MACH_PORT_NULL) - { - /*If stat information is required*/ - if(stat) - { - /*obtain stat information for `p`*/ - err = io_stat(p, &s); - if(err) - PORT_DEALLOC(p); - } - } - else - /*copy `errno` into `err`*/ - err = errno; - - /*If no errors have happened during lookup*/ - if(!err) - { - /*copy the resulting port into *`port`*/ - *port = p; - - /*fill in the receiver for stat information, if requried*/ - if(stat) - *stat = s; - } - - /*Return the result of performing operations*/ - return err; - }/*file_lookup*/ -/*----------------------------------------------------------------------------*/ diff --git a/netfs-sample/lib.h b/netfs-sample/lib.h deleted file mode 100644 index 6335efcf..00000000 --- a/netfs-sample/lib.h +++ /dev/null @@ -1,82 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/*lib.h*/ -/*----------------------------------------------------------------------------*/ -/*Declarations of basic routines for filesystem manipulations*/ -/*----------------------------------------------------------------------------*/ -/*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ -/*Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA.*/ -/*----------------------------------------------------------------------------*/ -#ifndef __LIB_H__ -#define __LIB_H__ - -/*----------------------------------------------------------------------------*/ -#define __USE_FILE_OFFSET64 -/*----------------------------------------------------------------------------*/ -#include <hurd.h> -#include <dirent.h> -#include <stddef.h> -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Macros--------------------------------------------------------------*/ -/*Alignment of directory entries*/ -#define DIRENT_ALIGN 4 -/*----------------------------------------------------------------------------*/ -/*The offset of the directory name in the directory entry structure*/ -#define DIRENT_NAME_OFFS offsetof(struct dirent, d_name) -/*----------------------------------------------------------------------------*/ -/*Computes the length of the structure before the name + the name + 0, - all padded to DIRENT_ALIGN*/ -#define DIRENT_LEN(name_len)\ - ((DIRENT_NAME_OFFS + (name_len) + 1 + DIRENT_ALIGN - 1) &\ - ~(DIRENT_ALIGN - 1)) -/*----------------------------------------------------------------------------*/ -/*Deallocate the given port for the current task*/ -#define PORT_DEALLOC(p) (mach_port_deallocate(mach_task_self(), (p))) -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ -/*Fetches directory entries for `dir`*/ -error_t -dir_entries_get - ( - file_t dir, - char ** dirent_data, /*the list of directory entries as returned - by dir_readdir*/ - size_t * dirent_data_size, /*the size of `dirent_data`*/ - struct dirent *** dirent_list /*the array of pointers to beginnings of - dirents in dirent_data*/ - ); -/*----------------------------------------------------------------------------*/ -/*Lookup `name` under `dir` (or cwd, if `dir` is invalid)*/ -error_t -file_lookup - ( - file_t dir, - char * name, - int flags0, /*try to open with these flags first*/ - int flags1, /*try to open with these flags, if `flags0` fail*/ - int mode, /*if the file is to be created, create it with this mode*/ - file_t * port, /*store the port to the looked up file here*/ - io_statbuf_t * stat /*store the stat information here*/ - ); -/*----------------------------------------------------------------------------*/ -#endif /*__LIB_H__*/ diff --git a/netfs-sample/lnode.c b/netfs-sample/lnode.c deleted file mode 100644 index 33394ed0..00000000 --- a/netfs-sample/lnode.c +++ /dev/null @@ -1,305 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/*lnode.c*/ -/*----------------------------------------------------------------------------*/ -/*Implementation of policies of management of 'light nodes'*/ -/*----------------------------------------------------------------------------*/ -/*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ -/*Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA.*/ -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -#define _GNU_SOURCE -/*----------------------------------------------------------------------------*/ -#include "lnode.h" -#include "debug.h" -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ -/*Adds a reference to the `lnode` (which must be locked)*/ -void -lnode_ref_add - ( - lnode_t * node - ) - { - /*Increment the number of references*/ - ++node->references; - }/*lnode_ref_add*/ -/*----------------------------------------------------------------------------*/ -/*Removes a reference from `node` (which must be locked). If that was the last - reference, destroy the node*/ -void -lnode_ref_remove - ( - lnode_t * node - ) - { - /*Fail if the node is not referenced by anybody*/ - assert(node->references); - - /*Decrement the number of references to `node`*/ - --node->references; - - /*If there are no references remaining*/ - if(node->references == 0) - { - /*uninstall the node from the directory it is in and destroy it*/ - lnode_uninstall(node); - lnode_destroy(node); - } - else - /*simply unlock the node*/ - mutex_unlock(&node->lock); - }/*lnode_ref_remove*/ -/*----------------------------------------------------------------------------*/ -/*Creates a new lnode with `name`; the new node is locked and contains - a single reference*/ -error_t -lnode_create - ( - char * name, - lnode_t ** node /*put the result here*/ - ) - { - /*Allocate the memory for the node*/ - lnode_t * node_new = malloc(sizeof(lnode_t)); - - /*If the memory has not been allocated*/ - if(!node_new) - { - /*stop*/ - return ENOMEM; - } - - /*The copy of the name*/ - char * name_cp = NULL; - - /*If the name exists*/ - if(name) - { - /*duplicate it*/ - name_cp = strdup(name); - - /*If the name has not been duplicated*/ - if(!name_cp) - { - /*free the node*/ - free(node_new); - - /*stop*/ - return ENOMEM; - } - } - - /*Setup the new node*/ - memset(node_new, 0, sizeof(lnode_t)); - node_new->name = name_cp; - node_new->name_len = (name_cp) ? (strlen(name_cp)) : (0); - - /*Setup one reference to this lnode*/ - node_new->references = 1; - - /*Initialize the mutex and acquire a lock on this lnode*/ - mutex_init(&node_new->lock); - mutex_lock(&node_new->lock); - - /*Store the result in the second parameter*/ - *node = node_new; - - /*Return success*/ - return 0; - }/*lnode_create*/ -/*----------------------------------------------------------------------------*/ -/*Destroys the given lnode*/ -void -lnode_destroy - ( - lnode_t * node /*destroy this*/ - ) - { - /*Destroy the name of the node*/ - free(node->name); - - /*Destroy the node itself*/ - free(node); - }/*lnode_destroy*/ -/*----------------------------------------------------------------------------*/ -/*Constructs the full path for the given lnode and stores the result both in - the parameter and inside the lnode (the same string, actually)*/ -error_t -lnode_path_construct - ( - lnode_t * node, - char ** path /*store the path here*/ - ) - { - error_t err = 0; - - /*The final path*/ - char * p; - - /*The final length of the path*/ - int p_len = 0; - - /*A temporary pointer to an lnode*/ - lnode_t * n; - - /*While the root node of the filterfs filesystem has not been reached*/ - for(n = node; n && n->dir; n = n->dir) - /*add the length of the name of `n` to `p_len` make some space for - the delimiter '/', if we are not approaching the root node*/ - /*p_len += n->name_len + ((n->dir->dir) ? (1) : (0));*/ - /*There is some path to our root node, so we will anyway have to - add a '/'*/ - p_len += n->name_len + 1; - - /*Include the space for the path to the root node of the filterfs - (n is now the root of the filesystem)*/ - p_len += strlen(n->path) + 1; - - /*Try to allocate the space for the string*/ - p = malloc(p_len * sizeof(char)); - if(!p) - err = ENOMEM; - /*If memory allocation has been successful*/ - else - { - /*put a terminal 0 at the end of the path*/ - p[--p_len] = 0; - - /*While the root node of the filterfs filesystem has not been reached*/ - for(n = node; n && n->dir; n = n->dir) - { - /*compute the position where the name of `n` is to be inserted*/ - p_len -= n->name_len; - - /*copy the name of the node into the path (omit the terminal 0)*/ - strncpy(p + p_len, n->name, n->name_len); - - /*If we are not at the root node of the filterfs filesystem, add the - separator*/ - /*if(n->dir->dir) - p[--p_len] = '/';*/ - /*we anyway have to add the separator slash*/ - p[--p_len] = '/'; - } - - /*put the path to the root node at the beginning of the first path - (n is at the root now)*/ - strncpy(p, n->path, strlen(n->path)); - - /*destroy the former path in lnode, if it exists*/ - if(node->path) - free(node->path); - - /*store the new path inside the lnode*/ - node->path = p; - - /*store the path in the parameter*/ - if(path) - *path = p; - } - - /*Return the result of operations*/ - return err; - }/*lnode_path_construct*/ -/*----------------------------------------------------------------------------*/ -/*Gets a light node by its name, locks it and increments its refcount*/ -error_t -lnode_get - ( - lnode_t * dir, /*search here*/ - char * name, /*search for this name*/ - lnode_t ** node /*put the result here*/ - ) - { - error_t err = 0; - - /*The pointer to the required lnode*/ - lnode_t * n; - - /*Find `name` among the names of entries in `dir`*/ - for(n = dir->entries; n && (strcmp(n->name, name) != 0); n = n->next); - - /*If the search has been successful*/ - if(n) - { - /*lock the node*/ - mutex_lock(&n->lock); - - /*increment the refcount of the found lnode*/ - lnode_ref_add(n); - - /*put a pointer to `n` into the parameter*/ - *node = n; - } - else - err = ENOENT; - - /*Return the result of operations*/ - return err; - }/*lnode_get*/ -/*----------------------------------------------------------------------------*/ -/*Install the lnode into the lnode tree: add a reference to `dir` (which must - be locked)*/ -void -lnode_install - ( - lnode_t * dir, /*install here*/ - lnode_t * node /*install this*/ - ) - { - /*Install `node` into the list of entries in `dir`*/ - node->next = dir->entries; - node->prevp = &dir->entries; /*this node is the first on the list*/ - if(dir->entries) - dir->entries->prevp = &node->next; /*here `prevp` gets the value - corresponding to its meaning*/ - dir->entries = node; - - /*Add a new reference to dir*/ - lnode_ref_add(dir); - - /*Setup the `dir` link in node*/ - node->dir = dir; - }/*lnode_install*/ -/*----------------------------------------------------------------------------*/ -/*Unistall the node from the node tree; remove a reference from the lnode - containing `node`*/ -void -lnode_uninstall - ( - lnode_t * node - ) - { - /*Remove a reference from the parent*/ - lnode_ref_remove(node->dir); - - /*Make the next pointer in the previous element point to the element, - which follows `node`*/ - *node->prevp = node->next; - - /*If the current node is not the last one, connect the list after removal - of the current node*/ - if(node->next) - node->next->prevp = &node->next; - }/*lnode_uninstall*/ -/*----------------------------------------------------------------------------*/ diff --git a/netfs-sample/lnode.h b/netfs-sample/lnode.h deleted file mode 100644 index 7c42c8d4..00000000 --- a/netfs-sample/lnode.h +++ /dev/null @@ -1,143 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/*lnode.h*/ -/*----------------------------------------------------------------------------*/ -/*Management of cheap 'light nodes'*/ -/*----------------------------------------------------------------------------*/ -/*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ -/*Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA.*/ -/*----------------------------------------------------------------------------*/ -#ifndef __LNODE_H__ -#define __LNODE_H__ - -/*----------------------------------------------------------------------------*/ -#include <error.h> -#include <hurd/netfs.h> -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*A candy synonym for the fundamental libnetfs node*/ -typedef struct node node_t; -/*----------------------------------------------------------------------------*/ -/*The light node*/ -struct lnode - { - /*the name of the lnode*/ - char * name; - - /*the length of the name; `name` does not change, and this value is used - quite often, therefore calculate it just once*/ - size_t name_len; - - /*the full path to the lnode*/ - char * path; - - /*the associated flags*/ - int flags; - - /*the number of references to this lnode*/ - int references; - - /*the reference to the real node*/ - node_t * node; - - /*the next lnode and the pointer to this lnode from the previous one*/ - struct lnode * next, **prevp; - - /*the lnode (directory) in which this node is contained*/ - struct lnode * dir; - - /*the beginning of the list of entries contained in this lnode (directory)*/ - struct lnode * entries; - - /*a lock*/ - struct mutex lock; - };/*struct lnode*/ -/*----------------------------------------------------------------------------*/ -typedef struct lnode lnode_t; -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ -/*Adds a reference to the `lnode` (which must be locked)*/ -void -lnode_ref_add - ( - lnode_t * node - ); -/*----------------------------------------------------------------------------*/ -/*Removes a reference from `node` (which must be locked). If that was the last - reference, destroy the node*/ -void -lnode_ref_remove - ( - lnode_t * node - ); -/*----------------------------------------------------------------------------*/ -/*Creates a new lnode with `name`; the new node is locked and contains - a single reference*/ -error_t -lnode_create - ( - char * name, - lnode_t ** node /*put the result here*/ - ); -/*----------------------------------------------------------------------------*/ -/*Destroys the given lnode*/ -void -lnode_destroy - ( - lnode_t * node /*destroy this*/ - ); -/*----------------------------------------------------------------------------*/ -/*Constructs the full path for the given lnode and stores the result both in - the parameter and inside the lnode (the same string, actually)*/ -error_t -lnode_path_construct - ( - lnode_t * node, - char ** path /*store the path here*/ - ); -/*----------------------------------------------------------------------------*/ -/*Gets a light node by its name, locks it and increments its refcount*/ -error_t -lnode_get - ( - lnode_t * dir, /*search here*/ - char * name, /*search for this name*/ - lnode_t ** node /*put the result here*/ - ); -/*----------------------------------------------------------------------------*/ -/*Install the lnode into the lnode tree: add a reference to `dir` (which must - be locked)*/ -void -lnode_install - ( - lnode_t * dir, /*install here*/ - lnode_t * node /*install this*/ - ); -/*----------------------------------------------------------------------------*/ -/*Unistall the node from the node tree; remove a reference from the lnode*/ -void -lnode_uninstall - ( - lnode_t * node - ); -/*----------------------------------------------------------------------------*/ -#endif /*__LNODE_H__*/ diff --git a/netfs-sample/ncache.c b/netfs-sample/ncache.c deleted file mode 100644 index 12462d31..00000000 --- a/netfs-sample/ncache.c +++ /dev/null @@ -1,221 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/*ncache.h*/ -/*----------------------------------------------------------------------------*/ -/*The implementation of the cache of nodes*/ -/*----------------------------------------------------------------------------*/ -/*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ -/*Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA.*/ -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -#define _GNU_SOURCE 1 -/*----------------------------------------------------------------------------*/ -#include "ncache.h" -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ -/*The global cache chain*/ -ncache_t ncache; -/*----------------------------------------------------------------------------*/ -/*Cache size (may be overwritten by the user)*/ -int ncache_size = NCACHE_SIZE; -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ -/*Initializes the node cache*/ -void -ncache_init - ( - int size_max - ) - { - /*Reset the LRU and MRU ends of the list*/ - ncache.mru = ncache.lru = NULL; - - /*Set the maximal size according to the parameter*/ - ncache.size_max = size_max; - - /*The cache is empty so far; remark that*/ - ncache.size_current = 0; - - /*Init the lock*/ - mutex_init(&ncache.lock); - }/*ncache_init*/ -/*----------------------------------------------------------------------------*/ -/*Looks up the lnode and stores the result in `node`; creates a new entry - in the cache if the lookup fails*/ -error_t -ncache_node_lookup - ( - lnode_t * lnode, /*search for this*/ - node_t ** node /*put the result here*/ - ) - { - error_t err = 0; - - /*Obtain the pointer to the node corresponding to `lnode`*/ - node_t * n = lnode->node; - - /*If a node has already been created for the given lnode*/ - if(n != NULL) - { - /*count a new reference to 'n'*/ - netfs_nref(n); - } - else - { - /*create a new node for the given lnode and store the result in `n`*/ - err = node_create(lnode, &n); - } - - /*If no errors have occurred during the previous operations*/ - if(!err) - { - /*lock the mutex in the looked up node*/ - mutex_lock(&n->lock); - - /*store the lookup result in `node`*/ - *node = n; - } - - /*Return the result of operations*/ - return err; - }/*ncache_node_lookup*/ -/*----------------------------------------------------------------------------*/ -/*Removes the given node from the cache*/ -static -void -ncache_node_remove - ( - node_t * node - ) - { - /*Obtain the pointer to the netnode (this contains the information - specific of us)*/ - struct netnode * nn = node->nn; - - /*If there exists a successor of this node in the cache chain*/ - if(nn->ncache_next) - /*remove the reference in the successor*/ - nn->ncache_next->nn->ncache_prev = nn->ncache_prev; - /*If there exists a predecessor of this node in the cache chain*/ - if(nn->ncache_prev) - /*remove the reference in the predecessor*/ - nn->ncache_prev->nn->ncache_next = nn->ncache_next; - - /*If the node was located at the MRU end of the list*/ - if(ncache.mru == node) - /*shift the MRU end to the next node*/ - ncache.mru = nn->ncache_next; - /*If the node was located at the LRU end of the list*/ - if(ncache.lru == node) - /*shift the LRU end to the previous node*/ - ncache.lru = nn->ncache_prev; - - /*Invalidate the references inside the node*/ - nn->ncache_next = nn->ncache_prev = NULL; - - /*Count the removal of a node*/ - --ncache.size_current; - }/*ncache_node_remove*/ -/*----------------------------------------------------------------------------*/ -/*Resets the node cache*/ -void -ncache_reset(void) - { - /*The node being currently deleted*/ - node_t * node; - - /*Acquire a lock on the cache*/ - mutex_lock(&ncache.lock); - - /*Remove the whole cache chain*/ - for(node = ncache.mru; node != NULL; ncache_node_remove(node), node = ncache.mru); - - /*Release the lock*/ - mutex_unlock(&ncache.lock); - }/*ncache_reset*/ -/*----------------------------------------------------------------------------*/ -/*Adds the given node to the cache*/ -void -ncache_node_add - ( - node_t * node /*the node to add*/ - ) - { - /*Acquire a lock on the cache*/ - mutex_lock(&ncache.lock); - - /*If there already are some nodes in the cache and it is enabled*/ - if((ncache.size_max > 0) || (ncache.size_current > 0)) - { - /*If the node to be added is not at the MRU end already*/ - if(ncache.mru != node) - { - /*If the node is correctly integrated in the cache*/ - if((node->nn->ncache_next != NULL) && (node->nn->ncache_prev != NULL)) - /*remove the old entry*/ - ncache_node_remove(node); - else - /*add a new reference to the node*/ - netfs_nref(node); - - /*put the node at the MRU end of the cache chain*/ - node->nn->ncache_next = ncache.mru; - node->nn->ncache_prev = NULL; - - /*setup the pointer in the old MRU end, if it exists*/ - if(ncache.mru != NULL) - ncache.mru->nn->ncache_prev = node; - - /*setup the LRU end of the cache chain, if it did not exist previously*/ - if(ncache.lru == NULL) - ncache.lru = node; - - /*shift the MRU end to the new node*/ - ncache.mru = node; - - /*count the addition*/ - ++ncache.size_current; - } - } - - /*While the size of the cache is exceeding the maximal size*/ - node_t * old_lru; - for - ( - old_lru = ncache.lru; - ncache.size_current > ncache.size_max; - old_lru = ncache.lru - ) - { - /*remove the current LRU end of the list from the cache*/ - ncache_node_remove(old_lru); - - /*release the reference to the node owned by this thread*/ - netfs_nrele(old_lru); - } - - /*Release the lock on the cache*/ - mutex_unlock(&ncache.lock); - }/*ncache_node_add*/ -/*----------------------------------------------------------------------------*/ diff --git a/netfs-sample/ncache.h b/netfs-sample/ncache.h deleted file mode 100644 index 124d514e..00000000 --- a/netfs-sample/ncache.h +++ /dev/null @@ -1,100 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/*ncache.h*/ -/*----------------------------------------------------------------------------*/ -/*The cache of nodes*/ -/*----------------------------------------------------------------------------*/ -/*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ -/*Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA.*/ -/*----------------------------------------------------------------------------*/ -#ifndef __NCACHE_H__ -#define __NCACHE_H__ - -/*----------------------------------------------------------------------------*/ -#include <error.h> -#include <hurd/netfs.h> -/*----------------------------------------------------------------------------*/ -#include "node.h" -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Macros--------------------------------------------------------------*/ -/*The default maximal cache size*/ -#define NCACHE_SIZE 256 -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*A cache chain*/ -struct ncache - { - /*the MRU end of the cache chain*/ - node_t * mru; - - /*the LRU end of the cache chain*/ - node_t * lru; - - /*the maximal number of nodes to cache*/ - int size_max; - - /*the current length of the cache chain*/ - int size_current; - - /*a lock*/ - struct mutex lock; - };/*struct ncache*/ -/*----------------------------------------------------------------------------*/ -typedef struct ncache ncache_t; -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ -/*The cache size (may be overwritten by the user)*/ -extern int cache_size; -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ -/*Initializes the node cache*/ -void -ncache_init - ( - int size_max - ); -/*----------------------------------------------------------------------------*/ -/*Looks up the lnode and stores the result in `node`; creates a new entry - in the cache if the lookup fails*/ -error_t -ncache_node_lookup - ( - lnode_t * lnode, /*search for this*/ - node_t ** node /*put the result here*/ - ); -/*----------------------------------------------------------------------------*/ -/*Resets the node cache*/ -void -ncache_reset(void); -/*----------------------------------------------------------------------------*/ -/*Adds the given node to the cache*/ -void -ncache_node_add - ( - node_t * node /*the node to add*/ - ); -/*----------------------------------------------------------------------------*/ -#endif /*__NCACHE_H__*/ diff --git a/netfs-sample/node.c b/netfs-sample/node.c deleted file mode 100644 index 602660b6..00000000 --- a/netfs-sample/node.c +++ /dev/null @@ -1,803 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/*node.c*/ -/*----------------------------------------------------------------------------*/ -/*Implementation of node management strategies*/ -/*----------------------------------------------------------------------------*/ -/*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ -/*Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA.*/ -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -#define _GNU_SOURCE 1 -/*----------------------------------------------------------------------------*/ -#include <stdlib.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <stdio.h> -/*----------------------------------------------------------------------------*/ -#include "debug.h" -#include "node.h" -#include "options.h" -#include "lib.h" -#include "filterfs.h" -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ -/*The lock protecting the underlying filesystem*/ -struct mutex ulfs_lock = MUTEX_INITIALIZER; -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ -/*Derives a new node from `lnode` and adds a reference to `lnode`*/ -error_t -node_create -( - lnode_t * lnode, - node_t ** node /*store the result here*/ -) -{ - error_t err = 0; - - /*Create a new netnode*/ - netnode_t * netnode_new = malloc(sizeof(netnode_t)); - - /*If the memory could not be allocated*/ - if(netnode_new == NULL) - err = ENOMEM; - else - { - /*create a new node from the netnode*/ - node_t * node_new = netfs_make_node(netnode_new); - - /*If the creation failed*/ - if(node_new == NULL) - { - /*set the error code*/ - err = ENOMEM; - - /*destroy the netnode created above*/ - free(netnode_new); - - /*stop*/ - return err; - } - - /*link the lnode to the new node*/ - lnode->node = node_new; - lnode_ref_add(lnode); - - /*setup the references in the newly created node*/ - node_new->nn->lnode = lnode; - node_new->nn->flags = 0; - node_new->nn->ncache_next = node_new->nn->ncache_prev = NULL; - - /*store the result of creation in the second parameter*/ - *node = node_new; - } - - /*Return the result of operations*/ - return err; -}/*node_create*/ -/*----------------------------------------------------------------------------*/ -/*Destroys the specified node and removes a light reference from the - associated light node*/ -void -node_destroy -( - node_t * np -) -{ - /*Die if the node does not belong to node cache*/ - assert(!np->nn->ncache_next || !np->nn->ncache_prev); - - /*Destroy the port to the underlying filesystem allocated to the node*/ - PORT_DEALLOC(np->nn->port); - - /*Lock the lnode corresponding to the current node*/ - mutex_lock(&np->nn->lnode->lock); - - /*Orphan the light node*/ - np->nn->lnode->node = NULL; - - /*Remove a reference from the lnode*/ - lnode_ref_remove(np->nn->lnode); - - /*Free the netnode and the node itself*/ - free(np->nn); - free(np); -}/*node_destroy*/ -/*----------------------------------------------------------------------------*/ -/*Creates the root node and the corresponding lnode*/ -error_t -node_create_root -( - node_t ** root_node /*store the result here*/ -) -{ - /*Try to create a new lnode*/ - lnode_t * lnode; - error_t err = lnode_create(NULL, &lnode); - - /*Stop, if the creation failed*/ - if(err) - return err; - - /*Try to derive the node corresponding to `lnode`*/ - node_t * node; - err = node_create(lnode, &node); - - /*If the operation failed*/ - if(err) - { - /*destroy the created lnode*/ - lnode_destroy(lnode); - - /*stop*/ - return err; - } - - /*Release the lock on the lnode*/ - mutex_unlock(&lnode->lock); - - /*Store the result in the parameter*/ - *root_node = node; - - /*Return the result*/ - return err; -}/*node_create_root*/ -/*----------------------------------------------------------------------------*/ -/*Initializes the port to the underlying filesystem for the root node*/ -error_t -node_init_root -( - node_t * node /*the root node*/ -) -{ - error_t err = 0; - - /*Acquire a lock for operations on the underlying filesystem*/ - mutex_lock(&ulfs_lock); - - /*Open the port to the directory specified in `dir`*/ - node->nn->port = file_name_lookup(dir, O_READ | O_DIRECTORY, 0); - - /*If the directory could not be opened*/ - if(node->nn->port == MACH_PORT_NULL) - { - /*set the error code accordingly*/ - err = errno; - LOG_MSG("node_init_root: Could not open the port for %s.", dir); - - /*release the lock and stop*/ - mutex_unlock(&ulfs_lock); - return err; - } - - LOG_MSG("node_init_root: Port for %s opened successfully.", dir); - LOG_MSG("\tPort: 0x%lX", (unsigned long)node->nn->port); - - /*Stat the root node*/ - err = io_stat(node->nn->port, &node->nn_stat); - if(err) - { - /*deallocate the port*/ - PORT_DEALLOC(node->nn->port); - - LOG_MSG("node_init_root: Could not stat the root node."); - - /*unlock the mutex and exit*/ - mutex_unlock(&ulfs_lock); - return err; - } - - /*Set the path to the corresponding lnode to `dir`*/ - node->nn->lnode->path = strdup(dir); - if(!node->nn->lnode->path) - { - /*deallocate the port*/ - PORT_DEALLOC(node->nn->port); - - /*unlock the mutex*/ - mutex_unlock(&ulfs_lock); - - LOG_MSG("node_init_root: Could not strdup the directory."); - return ENOMEM; - } - - /*The current position in dir*/ - char * p = dir + strlen(dir); - - /*Go through the path from end to beginning*/ - for(; p >= dir; --p) - { - /*If the current character is a '/'*/ - if(*p == '/') - { - /*If p is not the first character*/ - if(p > dir) - { - /*if this slash is escaped, skip it*/ - if(*(p - 1) == '\\') - continue; - } - - /*advance the pointer to the first character after the slash*/ - ++p; - - /*stop*/ - break; - } - } - - LOG_MSG("node_init_root: The name of root node is %s.", p); - - /*Set the name of the lnode to the last element in the path to dir*/ - node->nn->lnode->name = strdup(p); - /*If the name of the node could not be duplicated*/ - if(!node->nn->lnode->name) - { - /*free the name of the path to the node and deallocate teh port*/ - free(node->nn->lnode->path); - PORT_DEALLOC(node->nn->port); - - /*unlock the mutex*/ - mutex_unlock(&ulfs_lock); - - LOG_MSG("node_init_root: Could not strdup the name of the root node."); - return ENOMEM; - } - - /*Compute the length of the name of the root node*/ - node->nn->lnode->name_len = strlen(p); - - /*Release the lock for operations on the undelying filesystem*/ - mutex_unlock(&ulfs_lock); - - /*Return the result of operations*/ - return err; -}/*node_init_root*/ -/*----------------------------------------------------------------------------*/ -/*Frees a list of dirents*/ -void -node_entries_free -( - node_dirent_t * dirents /*free this*/ -) -{ - /*The current and the next elements*/ - node_dirent_t * dirent, * dirent_next; - - /*Go through all elements of the list*/ - for(dirent = dirents; dirent; dirent = dirent_next) - { - /*store the next element*/ - dirent_next = dirent->next; - - /*free the dirent stored in the current element of the list*/ - free(dirent->dirent); - - /*free the current element*/ - free(dirent); - } -}/*node_entries_free*/ -/*----------------------------------------------------------------------------*/ -/*Reads the directory entries from `node`, which must be locked*/ -error_t -node_entries_get -( - node_t * node, - node_dirent_t ** dirents /*store the result here*/ -) -{ - error_t err = 0; - - /*Obtain the path to the current node*/ - char * path_to_node = node->nn->lnode->path; - - /*The number of PROPERTY_PARAMs in the property*/ - int param_entries_count = 0; - - /*The length of the property*/ - size_t property_len = (property) ? (strlen(property)) : (0); - - /*The length of PROPERTY_PARAM*/ - size_t property_param_len = strlen(PROPERTY_PARAM); - - /*The full name and the filtering command*/ - char * full_name = NULL, * cmd = NULL; - - /*The lengths of the full name and the filtering command in chunks*/ - size_t full_name_size = 1, cmd_size = 1; - - /*If some property was indeed specified*/ - if(property_len != 0) - { - /*the pointer to the current occurrence of PROPERTY_PARAM*/ - char * occurrence = strstr(property, PROPERTY_PARAM); - - /*count the number of occurrences*/ - for(; occurrence; - occurrence = strstr(occurrence + 1, PROPERTY_PARAM), - ++param_entries_count); - - /*try allocate the memory for the fullname and the filtering command*/ - full_name = malloc(full_name_size * STRING_CHUNK); - if(!full_name) - return ENOMEM; - - cmd = malloc(cmd_size * STRING_CHUNK); - if(!cmd) - { - free(full_name); - return ENOMEM; - } - } - - /*Obtain the length of the path*/ - size_t pathlen = strlen(path_to_node); - - /*Checks if the given file satisfies the property. Zero value means that - the entry must be filtered out*/ - int - check_property - ( - const char * name /*the name of the file*/ - ) - { - /*If there is no property*/ - if(!property) - /*no filtering will be applied, any name is OK*/ - return 0; - - /*Everything OK at first*/ - err = 0; - - /*Compute the length of the full name once*/ - size_t full_name_len = pathlen + 1 + strlen(name) + 1; - - /*See how much space (in chunks) is required for the full name*/ - int chunks = full_name_size; - for(; full_name_len > chunks * STRING_CHUNK; ++chunks); - - /*If more memory is requied*/ - if(chunks > full_name_size) - { - /*free the old full name*/ - free(full_name); - - /*try to allocate the new memory*/ - full_name = malloc(chunks * STRING_CHUNK); - if(!full_name) - { - err = ENOMEM; - free(cmd); /*the string for the command is definitely allocated here*/ - return 0; - } - - /*store the new size*/ - full_name_size = chunks; - } - - /*Initialize `full_name` as a valid string*/ - full_name[0] = 0; - - /*Construct the full name*/ - strcpy(full_name, path_to_node); - strcat(full_name, "/"); - strcat(full_name, name); - - /*LOG_MSG("node_entries_get: Applying filter to %s...", full_name);*/ - - /*Compute the space required for the final filtering command*/ - size_t sz = property_len + (strlen(full_name) - property_param_len) - * param_entries_count; - - /*See how much space (in chunks) is required for the command*/ - for(chunks = cmd_size; sz > chunks * STRING_CHUNK; ++chunks); - - /*If more memory is requied*/ - if(chunks > cmd_size) - { - /*free the old command*/ - free(cmd); - - /*try to allocate the new memory*/ - cmd = malloc(chunks * STRING_CHUNK); - if(!cmd) - { - err = ENOMEM; - free(full_name); /*the string for the full name is - definitely allocated here*/ - return 0; - } - - /*store the new size*/ - cmd_size = chunks; - } - - /*Initialize `cmd` as a valid string*/ - cmd[0] = 0; - - /*The current occurence of PROPERTY_PARAM in property*/ - char * p = strstr(property, PROPERTY_PARAM); - - /*The pointer to the current position in the property*/ - char * propp = property; - - /*While the command has not been constructed*/ - for(; p; p = strstr(propp, PROPERTY_PARAM)) - { - /*add the new part of the property to the command*/ - strncat(cmd, propp, p - propp); - - /*add the filename to the command*/ - strcat(cmd, full_name); - - /*LOG_MSG("\tcmd = '%s'", cmd);*/ - - /*advance the pointer in the property*/ - propp = p + property_param_len; - - /*LOG_MSG("\tpropp points at '%s'", propp);*/ - } - - /*Copy the rest of the property to the command*/ - strcat(cmd, propp); - - /*LOG_MSG("node_entries_get: The filtering command: '%s'.", cmd);*/ - - /*Execute the command*/ - int xcode = WEXITSTATUS(system(cmd)); - - /*Return the exit code of the command*/ - return xcode; - }/*check_property*/ - - /*The list of dirents*/ - struct dirent ** dirent_list, **dirent; - - /*The head of the list of dirents*/ - node_dirent_t * node_dirent_list = NULL; - - /*The size of the array of pointers to dirent*/ - size_t dirent_data_size; - - /*The array of dirents*/ - char * dirent_data; - - /*Obtain the directory entries for the given node*/ - err = dir_entries_get - (node->nn->port, &dirent_data, &dirent_data_size, &dirent_list); - if(err) - { - return err; - } - - /*The new entry in the list*/ - node_dirent_t * node_dirent_new; - - /*The new dirent*/ - struct dirent * dirent_new; - - /*LOG_MSG("node_entries_get: Getting entries for %p", node);*/ - - /*The name of the current dirent*/ - char * name; - - /*The length of the current name*/ - size_t name_len; - - /*The size of the current dirent*/ - size_t size; - - /*The exit code of property*/ - int good; - - /*Go through all elements of the list of pointers to dirent*/ - for(dirent = dirent_list; *dirent; ++dirent) - { - /*obtain the name of the current dirent*/ - name = &((*dirent)->d_name[0]); - - /*If the current dirent is either '.' or '..', skip it*/ - if((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) - continue; - - /*check if the current dirent has the property*/ - good = check_property(name); - if(err) - break; - - /*If the current entry is not good, skip it*/ - if(good != 0) - continue; - - /*obtain the length of the current name*/ - name_len = strlen(name); - - /*obtain the length of the current dirent*/ - size = DIRENT_LEN(name_len); - - /*create a new list element*/ - node_dirent_new = malloc(sizeof(node_dirent_t)); - if(!node_dirent_new) - { - err = ENOMEM; - break; - } - - /*create a new dirent*/ - dirent_new = malloc(size); - if(!dirent_new) - { - free(node_dirent_new); - err = ENOMEM; - break; - } - - /*fill the dirent with information*/ - dirent_new->d_ino = (*dirent)->d_ino; - dirent_new->d_type = (*dirent)->d_type; - dirent_new->d_reclen = size; - strcpy((char *)dirent_new + DIRENT_NAME_OFFS, name); - - /*add the dirent to the list*/ - node_dirent_new->dirent = dirent_new; - node_dirent_new->next = node_dirent_list; - node_dirent_list = node_dirent_new; - } - - /*If something went wrong in the loop*/ - if(err) - /*free the list of dirents*/ - node_entries_free(node_dirent_list); - else - /*store the list of dirents in the second parameter*/ - *dirents = node_dirent_list; - - /*Free the list of pointers to dirent*/ - free(dirent_list); - - /*Free the results of listing the dirents*/ - munmap(dirent_data, dirent_data_size); - - /*Free the full name and the command (if these are present at all)*/ - if(full_name) - free(full_name); - if(cmd) - free(cmd); - - /*Return the result of operations*/ - return err; -}/*node_entries_get*/ -/*----------------------------------------------------------------------------*/ -/*Makes sure that all ports to the underlying filesystem of `node` are up to - date*/ -error_t -node_update -( - node_t * node -) -{ - error_t err = 0; - - /*The full path to this node*/ - char * path; - - /*Stat information for `node`*/ - io_statbuf_t stat; - - /*The port to the file corresponding to `node`*/ - file_t port; - - /*If the specified node is the root node or if it must not be updated*/ - if(NODE_IS_ROOT(node) || (node->nn->flags & FLAG_NODE_ULFS_FIXED)) - /*do nothing*/ - return err; /*return 0; actually*/ - - /*Gain exclusive access to the root node of the filesystem*/ - mutex_lock(&netfs_root_node->lock); - - /*Construct the full path to `node`*/ - err = lnode_path_construct(node->nn->lnode, &path); - if(err) - { - mutex_unlock(&netfs_root_node->lock); - return err; - } - - /*Deallocate `node`'s port to the underlying filesystem*/ - if(node->nn->port) - PORT_DEALLOC(node->nn->port); - - /*Try to lookup the file for `node` in its untranslated version*/ - err = file_lookup - ( - netfs_root_node->nn->port, path, O_READ | O_NOTRANS, O_NOTRANS, - 0, &port, &stat - ); - if(err) - { - node->nn->port = MACH_PORT_NULL; - err = 0; /*failure (?)*/ - return err; - } - - /*If the node looked up is actually the root node of filterfs filesystem*/ - if - ( - (stat.st_ino == underlying_node_stat.st_ino) - && (stat.st_fsid == underlying_node_stat.st_fsid) - ) - /*set `err` accordingly*/ - err = ELOOP; - else - { - /*deallocate the obtained port*/ - PORT_DEALLOC(port); - - /*obtain the translated version of the required node*/ - err = file_lookup - (netfs_root_node->nn->port, path, O_READ, 0, 0, &port, &stat); - } - - /*If there have been errors*/ - if(err) - /*reset the port*/ - port = MACH_PORT_NULL; - - /*Store the port in the node*/ - node->nn->port = port; - - /*Remove the flag about the invalidity of the current node and set the - flag that the node is up-to-date*/ - node->nn->flags &= ~FLAG_NODE_INVALIDATE; - node->nn->flags |= FLAG_NODE_ULFS_UPTODATE; - - /*Release the lock on the root node of filterfs filesystem*/ - mutex_unlock(&netfs_root_node->lock); - - /*Return the result of operations*/ - return err; -}/*node_update*/ -/*----------------------------------------------------------------------------*/ -/*Computes the size of the given directory*/ -error_t -node_get_size -( - node_t * dir, - OFFSET_T * off -) -{ - error_t err = 0; - - /*The final size*/ - size_t size = 0; - - /*The number of directory entries*/ - /*int count = 0;*/ - - /*The the node in the directory entries list from which we start counting*/ - /*node_dirent_t * dirent_start = NULL;*/ - - /*The currently analyzed dirent*/ - node_dirent_t * dirent_current = NULL; - - /*The pointer to the beginning of the list of dirents*/ - node_dirent_t * dirent_list = NULL; - - /*The first entry we have to analyze*/ - /*int first_entry = 2;*/ - - /*Takes into consideration the name of the current dirent*/ - void - bump_size - ( - const char * name - ) - { - /*Increment the current size by the size of the current dirent*/ - size += DIRENT_LEN(strlen(name)); - - /*Count the current dirent*/ - /*++count;*/ - }/*bump_size*/ - - /*Obtain the list of entries in the current directory*/ - err = node_entries_get(dir, &dirent_list); - if(err) - return err; - - /*Obtain the pointer to the dirent which has the number first_entry*/ - /*Actually, the first element of the list*/ - /*This code is included in unionfs, but it's completely useless here*/ - /*for - ( - dirent_start = dirent_list, count = 2; - dirent_start && count < first_entry; - dirent_start = dirent_start->next, ++count - );*/ - - /*Reset the count*/ - /*count = 0;*/ - - /*Make space for '.' and '..' entries*/ - /*This code is included in unionfs, but it's completely useless here*/ - /*if(first_entry == 0) - bump_size("."); - if(first_entry <= 1) - bump_size("..");*/ - - /*See how much space is required for the node*/ - for - ( - dirent_current = dirent_list/*dirent_start*/; dirent_current; - dirent_current = dirent_current->next - ) - bump_size(dirent_current->dirent->d_name); - - /*Free the list of dirents*/ - node_entries_free(dirent_list); - - /*Return the size*/ - *off = size; - return 0; -}/*node_get_size*/ -/*----------------------------------------------------------------------------*/ -/*Remove the file called `name` under `dir`*/ -error_t -node_unlink_file -( - node_t * dir, - char * name -) -{ - error_t err = 0; - - /*The port to the file which will be unlinked*/ - mach_port_t p; - - /*Stat information about the file which will be unlinked*/ - io_statbuf_t stat; - - /*If port corresponding to `dir` is invalid*/ - if(dir->nn->port == MACH_PORT_NULL) - /*stop with an error*/ - return ENOENT; /*FIXME: Is the return value indeed meaningful here?*/ - - /*Attempt to lookup the specified file*/ - err = file_lookup(dir->nn->port, name, O_NOTRANS, O_NOTRANS, 0, &p, &stat); - if(err) - return err; - - /*Deallocate the obtained port*/ - PORT_DEALLOC(p); - - /*Unlink file `name` under `dir`*/ - err = dir_unlink(dir->nn->port, name); - if(err) - return err; - - return err; -}/*node_unlink_file*/ -/*----------------------------------------------------------------------------*/ diff --git a/netfs-sample/node.h b/netfs-sample/node.h deleted file mode 100644 index dcd618d4..00000000 --- a/netfs-sample/node.h +++ /dev/null @@ -1,168 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/*node.h*/ -/*----------------------------------------------------------------------------*/ -/*Node management. Also see lnode.h*/ -/*----------------------------------------------------------------------------*/ -/*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ -/*Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA.*/ -/*----------------------------------------------------------------------------*/ -#ifndef __NODE_H__ -#define __NODE_H__ - -/*----------------------------------------------------------------------------*/ -#include <error.h> -#include <sys/stat.h> -#include <hurd/netfs.h> -/*----------------------------------------------------------------------------*/ -#include "lnode.h" -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Macros--------------------------------------------------------------*/ -/*Checks whether the give node is the root of the filterfs filesystem*/ -#define NODE_IS_ROOT(n) (((n)->nn->lnode->dir) ? (0) : (1)) -/*----------------------------------------------------------------------------*/ -/*Node flags*/ -#define FLAG_NODE_ULFS_FIXED 0x00000001 /*this node should not be updated*/ -#define FLAG_NODE_INVALIDATE 0x00000002 /*this node must be updated*/ -#define FLAG_NODE_ULFS_UPTODATE 0x00000004 /*this node has just been updated*/ -/*----------------------------------------------------------------------------*/ -/*The type of offset corresponding to the current platform*/ -#ifdef __USE_FILE_OFFSET64 -# define OFFSET_T __off64_t -#else -# define OFFSET_T __off_t -#endif /*__USE_FILE_OFFSET64*/ -/*----------------------------------------------------------------------------*/ -/*The size of a chunk of a string (for a small optimization in checking - the property)*/ -#define STRING_CHUNK 256 -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*The user-defined node for libnetfs*/ -struct netnode - { - /*the reference to the corresponding light node*/ - lnode_t * lnode; - - /*the flags associated with this node (might be not required)*/ - int flags; - - /*a port to the underlying filesystem*/ - file_t port; - - /*the neighbouring entries in the cache*/ - node_t * ncache_prev, * ncache_next; - };/*struct netnode*/ -/*----------------------------------------------------------------------------*/ -typedef struct netnode netnode_t; -/*----------------------------------------------------------------------------*/ -/*A list element containing directory entry*/ -struct node_dirent - { - /*the directory entry*/ - struct dirent * dirent; - - /*the next element*/ - struct node_dirent * next; - };/*struct node_dirent*/ -/*----------------------------------------------------------------------------*/ -typedef struct node_dirent node_dirent_t; -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ -/*The lock protecting the underlying filesystem*/ -extern struct mutex ulfs_lock; -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ -/*Derives a new node from `lnode` and adds a reference to `lnode`*/ -error_t -node_create - ( - lnode_t * lnode, - node_t ** node /*store the result here*/ - ); -/*----------------------------------------------------------------------------*/ -/*Destroys the specified node and removes a light reference from the - associated light node*/ -void -node_destroy - ( - node_t * np - ); -/*----------------------------------------------------------------------------*/ -/*Creates the root node and the corresponding lnode*/ -error_t -node_create_root - ( - node_t ** root_node /*store the result here*/ - ); -/*----------------------------------------------------------------------------*/ -/*Initializes the port to the underlying filesystem for the root node*/ -error_t -node_init_root - ( - node_t * node /*the root node*/ - ); -/*----------------------------------------------------------------------------*/ -/*Frees a list of dirents*/ -void -node_entries_free - ( - node_dirent_t * dirents /*free this*/ - ); -/*----------------------------------------------------------------------------*/ -/*Reads the directory entries from `node`, which must be locked*/ -error_t -node_entries_get - ( - node_t * node, - node_dirent_t ** dirents /*store the result here*/ - ); -/*----------------------------------------------------------------------------*/ -/*Makes sure that all ports to the underlying filesystem of `node` are up to - date*/ -error_t -node_update - ( - node_t * node - ); -/*----------------------------------------------------------------------------*/ -/*Computes the size of the given directory*/ -error_t -node_get_size - ( - node_t * dir, - OFFSET_T * off - ); -/*----------------------------------------------------------------------------*/ -/*Remove the file called `name` under `dir`*/ -error_t -node_unlink_file - ( - node_t * dir, - char * name - ); -/*----------------------------------------------------------------------------*/ -#endif /*__NODE_H__*/ diff --git a/netfs-sample/options.c b/netfs-sample/options.c deleted file mode 100644 index c39d3f2b..00000000 --- a/netfs-sample/options.c +++ /dev/null @@ -1,255 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/*options.h*/ -/*----------------------------------------------------------------------------*/ -/*Definitions for parsing the command line switches*/ -/*----------------------------------------------------------------------------*/ -/*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ -/*Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA.*/ -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -#define _GNU_SOURCE 1 -/*----------------------------------------------------------------------------*/ -#include <argp.h> -#include <error.h> -/*----------------------------------------------------------------------------*/ -#include "debug.h" -#include "options.h" -#include "ncache.h" -#include "node.h" -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Macros--------------------------------------------------------------*/ -/*Short documentation for argp*/ -#define ARGS_DOC "DIR" -#define DOC "Shows the contents of DIR filtered according to PROPERTY.\ - If DIR is not specified, ~/ is assumed." -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Forward Declarations------------------------------------------------*/ -/*Argp parser function for the common options*/ -static -error_t -argp_parse_common_options - ( - int key, - char * arg, - struct argp_state * state - ); -/*----------------------------------------------------------------------------*/ -/*Argp parser function for the startup options*/ -static -error_t -argp_parse_startup_options - ( - int key, - char * arg, - struct argp_state * state - ); -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ -/*This variable is set to a non-zero value after the parsing of starup options - is finished*/ -/*Whenever the argument parser is later called to modify the - options of filterfs the root node will be initialized accordingly directly - by the parser*/ -static int parsing_startup_options_finished; -/*----------------------------------------------------------------------------*/ -/*Argp options common to both the runtime and the startup parser*/ -static const struct argp_option argp_common_options[] = - { - {OPT_LONG_CACHE_SIZE, OPT_CACHE_SIZE, "SIZE", 0, - "The maximal number of nodes in the node cache"}, - {OPT_LONG_PROPERTY, OPT_PROPERTY, "PROPERTY", 0, - "The command which will act as a filter"} - }; -/*----------------------------------------------------------------------------*/ -/*Argp options only meaningful for startupp parsing*/ -static const struct argp_option argp_startup_options[] = - { - {0} - }; -/*----------------------------------------------------------------------------*/ -/*Argp parser for only the common options*/ -static const struct argp argp_parser_common_options = - {argp_common_options, argp_parse_common_options, 0, 0, 0}; -/*----------------------------------------------------------------------------*/ -/*Argp parser for only the startup options*/ -static const struct argp argp_parser_startup_options = - {argp_startup_options, argp_parse_startup_options, 0, 0, 0}; -/*----------------------------------------------------------------------------*/ -/*The list of children parsers for runtime arguments*/ -static const struct argp_child argp_children_runtime[] = - { - {&argp_parser_common_options}, - {&netfs_std_runtime_argp}, - {0} - }; -/*----------------------------------------------------------------------------*/ -/*The list of children parsers for startup arguments*/ -static const struct argp_child argp_children_startup[] = - { - {&argp_parser_startup_options}, - {&argp_parser_common_options}, - {&netfs_std_startup_argp}, - {0} - }; -/*----------------------------------------------------------------------------*/ -/*The version of the server for argp*/ -const char * argp_program_version = "0.0"; -/*----------------------------------------------------------------------------*/ -/*The arpg parser for runtime arguments*/ -struct argp argp_runtime = - {0, 0, 0, 0, argp_children_runtime}; -/*----------------------------------------------------------------------------*/ -/*The argp parser for startup arguments*/ -struct argp argp_startup = - {0, 0, ARGS_DOC, DOC, argp_children_startup}; -/*----------------------------------------------------------------------------*/ -/*The filtering command*/ -char * property = NULL; -/*----------------------------------------------------------------------------*/ -/*The directory to filter*/ -char * dir = NULL; -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ -/*Argp parser function for the common options*/ -static -error_t -argp_parse_common_options - ( - int key, - char * arg, - struct argp_state * state - ) - { - error_t err = 0; - - /*Go through the possible options*/ - switch(key) - { - case OPT_CACHE_SIZE: - { - /*store the new cache-size*/ - ncache_size = strtol(arg, NULL, 10); - - break; - } - case OPT_PROPERTY: - { - /*try to duplicate the filtering command*/ - property = strdup(arg); - if(!property) - error(EXIT_FAILURE, ENOMEM, "Could not strdup the property"); - - break; - } - case ARGP_KEY_ARG: /*the directory to filter*/ - { - /*try to duplicate the directory name*/ - dir = strdup(arg); - if(!dir) - error(EXIT_FAILURE, ENOMEM, "argp_parse_common_options: " - "Could not strdup the directory"); - - /*fill all trailing spaces with 0*/ - int i = strlen(dir) - 1; - /*for(i = strlen(dir) - 1; (i >= 0) && (dir[i] == ' '); dir[i--] = 0);*/ - /*the original filename may contain spaces*/ - - /*If the last non blank symbol is a '/' and it's not the only one*/ - if((dir[i] == '/') && (i != 0)) - /*put 0 instead*/ - dir[i] = 0; - - LOG_MSG("argp_parse_common_options: Filtering the directory %s.", dir); - - break; - } - case ARGP_KEY_END: - { - /*If parsing of startup options has not finished*/ - if(!parsing_startup_options_finished) - { - /*reset the cache*/ - ncache_reset(); - - /*If the directory has not been specified*/ - if(!dir) - { - /*assume the directory to be the home directory*/ - ; - - /*FIXME: The default directory is /var/tmp*/ - dir = "/var/tmp"; - } - - /*set the flag that the startup options have already been parsed*/ - parsing_startup_options_finished = 1; - } - else - { -/*TODO: Take care of runtime calls modifying the property*/ - } - } - /*If the option could not be recognized*/ - default: - { - /*set the error code*/ - err = ARGP_ERR_UNKNOWN; - } - } - - /*Return the result*/ - return err; - }/*argp_parse_common_options*/ -/*----------------------------------------------------------------------------*/ -/*Argp parser function for the startup options*/ -static -error_t -argp_parse_startup_options - ( - int key, - char * arg, - struct argp_state * state - ) - { - /*Do nothing in a beautiful way*/ - error_t err = 0; - - switch(key) - { - default: - { - err = ARGP_ERR_UNKNOWN; - - break; - } - } - - return err; - }/*argp_parse_startup_options*/ -/*----------------------------------------------------------------------------*/ diff --git a/netfs-sample/options.h b/netfs-sample/options.h deleted file mode 100644 index 0f917bb0..00000000 --- a/netfs-sample/options.h +++ /dev/null @@ -1,64 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/*options.h*/ -/*----------------------------------------------------------------------------*/ -/*Declarations for parsing the command line switches*/ -/*----------------------------------------------------------------------------*/ -/*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ -/*Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA.*/ -/*----------------------------------------------------------------------------*/ -#ifndef __OPTIONS_H__ -#define __OPTIONS_H__ - -/*----------------------------------------------------------------------------*/ -/*--------Macros--------------------------------------------------------------*/ -/*The possible short options*/ -#define OPT_CACHE_SIZE 'c' -/*the property according to which filtering will be performed*/ -#define OPT_PROPERTY 'p' -/*----------------------------------------------------------------------------*/ -/*The corresponding long options*/ -#define OPT_LONG_CACHE_SIZE "cache-size" -#define OPT_LONG_PROPERTY "property" -/*----------------------------------------------------------------------------*/ -/*Makes a long option out of option name*/ -#define OPT_LONG(o) "--"o -/*----------------------------------------------------------------------------*/ -/*The substring of the property which shall be replaced by the filename*/ -#define PROPERTY_PARAM "{}" -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ -/*The argp parser for startup arguments*/ -extern struct argp argp_startup; -/*----------------------------------------------------------------------------*/ -/*The argp parser for rutime arguments*/ -extern struct argp argp_runtime; -/*----------------------------------------------------------------------------*/ -/*The number of nodes in cache (see ncache.{c,h})*/ -extern int ncache_size; -/*----------------------------------------------------------------------------*/ -/*The filtering command*/ -extern char * property; -/*----------------------------------------------------------------------------*/ -/*The directory to filter*/ -extern char * dir; -/*----------------------------------------------------------------------------*/ -#endif /*__OPTIONS_H__*/ diff --git a/proc_proxy/ChangeLog b/proc_proxy/ChangeLog deleted file mode 100644 index c647bd15..00000000 --- a/proc_proxy/ChangeLog +++ /dev/null @@ -1,40 +0,0 @@ -2008-08-29 Zheng Da <zhengda1936@gmail.com> - - * README: Update. - -2008-08-29 Zheng Da <zhengda1936@gmail.com> - - * Makefile: Add process_ops.c - - * proc_proxy.c (master_port, args_doc, doc, options): New variables. - (reqport_find): Remove debugging print. - (comm_argv, comm_argc): New variables. - (add_comm_arg, add_comm_line, parse_opt): New functions. - (argp): New variable. - (main): Parse the options with argp. - - * proc_proxy.h (DEBUG): Removed macro. - - * process_ops.c (S_proc_getprivports): Return the master device port. - -2008-08-18 Zheng Da <zhengda1936@gmail.com> - - * README: New file. - -2008-08-17 Zheng Da <zhengda1936@gmail.com> - - * process.defs: Remove file. - - * process_ops.c: Replace the server prefix with the default one "S_". - -2008-08-17 Zheng Da <zhengda1936@gmail.com> - - * process.defs: New file. - - * Makefile: New file. - - * process_ops.c: New file. - - * proc_proxy.c: New file. - - * proc_proxy.h: New file. diff --git a/proc_proxy/Makefile b/proc_proxy/Makefile deleted file mode 100644 index 60ce1758..00000000 --- a/proc_proxy/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 2008 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. - -dir := proc_proxy -makemode := server - -SRCS = proc_proxy.c process_ops.c -LCLHDRS = proc_proxy.h -DIST_FILES = process.defs -HURDLIBS = threads ports -target = proc_proxy -MIGSTUBS = processServer.o -OBJS = $(SRCS:.c=.o) $(MIGSTUBS) - -MIGSFLAGS="-DPROCESS_INTRAN=vpstruct_t reqport_find (process_t)" \ - "-DPROCESS_DESTRUCTOR=process_drop (vpstruct_t)" \ - "-DPROCESS_IMPORTS=import \"proc_proxy.h\";" - -include ../Makeconf - -my_processUser.c: processUser.c - cat $< | sed -e '/__mig_get_reply_port *( *)/s/__mig_get_reply_port/my_get_reply_port/' > $@; diff --git a/proc_proxy/README b/proc_proxy/README deleted file mode 100644 index 83e11691..00000000 --- a/proc_proxy/README +++ /dev/null @@ -1,26 +0,0 @@ -[Introduction] - -proc_proxy is a proxy for the proc server. It intercepts the PROCESS requests that should be sent from a user to his proc server, so it provides a possibility for us to tamper the reply or even create the reply at our will. - -The current implementation of proc_proxy is able to help the pfinet translator open the virtual interface created by eth-multiplexer. - - -[Usage] - -Usage: proc_proxy [OPTION...] command line -Hurd proc proxy - - -M, --master-device=FILE Get the pseudo master device from a translator - -?, --help Give this help list - --usage Give a short usage message - -Mandatory or optional arguments to long options are also mandatory or optional for any corresponding short options. - - -[Internal] - -proc_proxy implements the server-side functions in process.defs. In the beginning, proc_proxy forks a new process, set its child's process server to itself, and run the command in the child process. Therefore, proc_proxy can get all PROCESS reqeusts from its child. - -proc_proxy works in the same way as the proc server to distinguish different processes with their ports. proc_proxy creates a port for each process. When a request comes, reqport_find() is called on the port to find the corresponding process. The port created for a new task is in server-side proc_task2proc. When a proc_task2proc request for a new task comes, a new port is created for the task and the send right of the port is returned. - -In order to help pfinet open the virtual interface created by eth-multiplexer, proc_proxy returns the port to eth-multiplexer as a master device port to pfinet. diff --git a/proc_proxy/proc_proxy.c b/proc_proxy/proc_proxy.c deleted file mode 100644 index c7878328..00000000 --- a/proc_proxy/proc_proxy.c +++ /dev/null @@ -1,276 +0,0 @@ -/* Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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 <stdio.h> -#include <argp.h> -#include <error.h> -#include <syslog.h> -#include <errno.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <stddef.h> - -#include <hurd.h> -#include <mach.h> - -#include "proc_proxy.h" - -struct port_bucket *proc_bucket; -struct port_class *proc_class; - -mach_port_t master_port; - -static struct hurd_ihash proc_ht -= HURD_IHASH_INITIALIZER (offsetof (struct vproc, p_task_hashloc)); - -static char *args_doc = "command line"; -static char *doc = "Hurd proc proxy"; -static struct argp_option options[] = -{ - {"master-device", 'M', "FILE", 0, "Get the pseudo master device from a translator"}, - { 0 } -}; - -vpstruct_t -reqport_find (mach_port_t reqport) -{ - vpstruct_t p; - p = ports_lookup_port (proc_bucket, reqport, proc_class); - return p; -} - -void -task_clean_routine (void *port) -{ - vpstruct_t proc = port; - hurd_ihash_locp_remove (&proc_ht, proc->p_task_hashloc); - mach_port_deallocate (mach_task_self (), proc->proc); - mach_port_deallocate (mach_task_self (), proc->task_id); -} - -vpstruct_t -create_task (task_t task) -{ - vpstruct_t proc; - error_t err = ports_create_port (proc_class, proc_bucket, - sizeof (*proc), &proc); - if (err) - error (3, err, "ports_create_port"); - - proc->task_id = task; - - hurd_ihash_add (&proc_ht, proc->task_id, proc); - return proc; -} - -vpstruct_t -find_task (task_t task) -{ - return hurd_ihash_find (&proc_ht, task) ? : create_task (task); -} - -int -request_server (mach_msg_header_t *inp, mach_msg_header_t *outp) -{ - extern boolean_t process_server (mach_msg_header_t *, mach_msg_header_t *); - return process_server (inp, outp); -} - -void -print_cmd (int argc, char *argv[]) -{ - int i; - for (i = 0; i < argc; i++) - { - debug ("%s ", argv[i]); - } - debug ("\n"); -} - -static char **comm_argv; -static int comm_argc; - -static int add_comm_arg (char *arg) -{ - static int comm_capacity = 0; - if (comm_capacity <= comm_argc) - { - comm_capacity += 8; - comm_argv = (char **) realloc (comm_argv, - comm_capacity * sizeof (char *)); - if (comm_argv == NULL) - error (1, errno, "realloc"); - } - - comm_argv[comm_argc] = arg; - comm_argc++; - - return 0; -} - -static void add_comm_line (char *line) -{ - char *p = line; - char *start; - - /* Skip the space */ - for (; *p != 0 && isspace (*p); p++); - start = p; - - while (1) - { - /* Find the end of an option */ - for (; *p != 0 && !isspace (*p); p++); - if (*p) - { - *p = 0; - p++; - } - add_comm_arg (start); - - /* Find the beginning of an option */ - for (; *p != 0 && isspace (*p); p++); - if (*p == 0) - break; - start = p; - } -} - -static error_t -parse_opt (int key, char *arg, struct argp_state *state) -{ - switch (key) - { - case 'M': - master_port = file_name_lookup (arg, 0, 0); - if (master_port == MACH_PORT_NULL) - error (1, errno, "file_name_lookup"); - break; - case ARGP_KEY_ARG: - add_comm_line (arg); - break; - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - -int -main (int argc, char *argv[]) -{ - error_t err; - vpstruct_t child_proc; - mach_port_t receive_port; - mach_port_t proc_port; - int pipe_fd1s[2]; - int pipe_fd2s[2]; - pid_t child_pid; - task_t child_task; - struct argp argp = - { options, parse_opt, args_doc, doc}; - - argp_parse (&argp, argc, argv, 0, 0, 0); - add_comm_arg (NULL); - - if (pipe (pipe_fd1s) < 0) - error (2, errno, "pipe"); - if (pipe (pipe_fd2s) < 0) - error (2, errno, "pipe"); - - err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_DEAD_NAME, - &proc_port); - if (err != KERN_SUCCESS) - error (2, err, "mach_port_allocate"); - - child_pid = fork (); - if (child_pid < 0) - error (2, errno, "fork"); - else if (child_pid == 0) - { - /* generate a new process group for child process, - * it's needed to set the child process group to foreground */ - setpgid (getpid (), getpid ()); - - close (pipe_fd1s[1]); - close (pipe_fd2s[0]); - - debug ("child process starts\n"); - read (pipe_fd1s[0], &proc_port, sizeof (proc_port)); - print_cmd (comm_argc, comm_argv); - write (pipe_fd2s[1], &proc_port, sizeof (proc_port)); - - setproc (proc_port); - debug ("child: current proc is %d\n", getproc ()); - if (execvp (comm_argv[0], comm_argv) < 0) - error (2, errno, "execvp"); - } - - debug ("create a child process %d\n", child_pid); - - /* Set the child process group as the foreground group. */ - tcsetpgrp (fileno (stdout), child_pid); - - close (pipe_fd1s[0]); - close (pipe_fd2s[1]); - - proc_bucket = ports_create_bucket (); - proc_class = ports_create_class (task_clean_routine, 0); - - /* Make the send right to the proc porxy in the child process. */ - child_task = pid2task (child_pid); - err = mach_port_destroy (child_task, proc_port); - if (err != KERN_SUCCESS) - error (2, err, "mach_port_destroy"); - child_proc = create_task (child_task); - receive_port = ports_get_right (child_proc); - err = mach_port_insert_right (child_task, proc_port, receive_port, - MACH_MSG_TYPE_MAKE_SEND); - if (err != KERN_SUCCESS) - error (2, err, "mach_port_insert_right"); - - /* Tell the child the send right. */ - write (pipe_fd1s[1], &proc_port, sizeof(proc_port)); - /* Synchronize. The child process should run first. */ - read (pipe_fd2s[0], &proc_port, sizeof(proc_port)); - - debug ("the proxy starts\n"); - proc_task2proc (getproc(), child_task, &child_proc->proc); - - while (1) - { - int status; - int ret; - - ports_manage_port_operations_one_thread (proc_bucket, - request_server, 500); - ret = waitpid (child_pid, &status, WNOHANG); - if (ret < 0) - error (1, errno, "waitpid"); - - /* if the child process exits */ - if (ret == 1 && WIFEXITED (status)) - break; - - } - debug ("proc proxy exits\n"); - - return 0; -} - diff --git a/proc_proxy/proc_proxy.h b/proc_proxy/proc_proxy.h deleted file mode 100644 index 17494415..00000000 --- a/proc_proxy/proc_proxy.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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 PROC_PROXY_H -#define PROC_PROXY_H - -#include <stdio.h> - -#include <hurd.h> -#include <hurd/ports.h> - -#ifdef DEBUG - -#define debug(format, ...) \ - do \ - { \ - char buf [1024]; \ - snprintf (buf, sizeof (buf), "%s: %s", __func__, format); \ - fprintf (stderr, buf, ## __VA_ARGS__); \ - } \ - while (0) - -#else - -#define debug(format, ...) do {} while (0) - -#endif - -struct vproc -{ - struct port_info p_pi; - task_t task_id; - /* The actual port to the proc server for the process. */ - process_t proc; - hurd_ihash_locp_t p_task_hashloc; -}; - -typedef struct vproc *vpstruct_t; - -static inline void -process_drop (vpstruct_t p) -{ - if (p) - ports_port_deref (p); -} - -vpstruct_t reqport_find (mach_port_t port); -vpstruct_t find_task (task_t task); -mach_port_t my_get_reply_port (void); - -#endif diff --git a/proc_proxy/process_ops.c b/proc_proxy/process_ops.c deleted file mode 100644 index ed6b2f76..00000000 --- a/proc_proxy/process_ops.c +++ /dev/null @@ -1,453 +0,0 @@ -/* Copyright (C) 2008 Free Software Foundation, Inc. - Written by Zheng Da. - - 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 <error.h> - -#include "process_S.h" - -kern_return_t -S_proc_getprivports (vpstruct_t process, mach_port_t *host_priv, - mach_port_t *device_master) -{ - extern mach_port_t master_port; - kern_return_t ret = 0; - debug ("task id: %d\n", process->task_id); - if (host_priv) - { - mach_port_t orig_device_master; - ret = proc_getprivports (process->proc, host_priv, - &orig_device_master); - if (ret) - { - error (0, ret, "proc_getprivports"); - return ret; - } - mach_port_deallocate (mach_task_self (), orig_device_master); - } - - if (device_master) - *device_master = master_port; - return ret; -} - -kern_return_t -S_proc_getallpids (vpstruct_t process, pidarray_t *pidarray, - mach_msg_type_number_t *pidarrayCnt) -{ - debug ("task id: %d\n", process->task_id); - return proc_getallpids (getproc (), pidarray, pidarrayCnt); -} - -kern_return_t -S_proc_setexecdata (vpstruct_t process, portarray_t ports, - mach_msg_type_number_t portsCnt, intarray_t ints, - mach_msg_type_number_t intsCnt) -{ - debug ("task id: %d\n", process->task_id); - return proc_setexecdata (process->proc, ports, MACH_MSG_TYPE_COPY_SEND, - portsCnt, ints, intsCnt); -} - -kern_return_t -S_proc_getexecdata (vpstruct_t process, portarray_t *ports, - mach_msg_type_name_t *portsPoly, - mach_msg_type_number_t *portsCnt, - intarray_t *ints, mach_msg_type_number_t *intsCnt) -{ - kern_return_t ret; - debug ("task id: %d\n", process->task_id); - ret = proc_getexecdata (process->proc, ports, portsCnt, ints, intsCnt); - if (ret == 0) - *portsPoly = MACH_MSG_TYPE_MOVE_SEND; - return ret; -} - -kern_return_t -S_proc_execdata_notify (vpstruct_t process, mach_port_t notify) -{ - debug ("task id: %d\n", process->task_id); - return proc_execdata_notify (process->proc, notify, MACH_MSG_TYPE_MOVE_SEND); -} - -kern_return_t -S_proc_uname (vpstruct_t process, utsname_t *uname) -{ - debug ("task id: %d\n", process->task_id); - return proc_uname (process->proc, uname); -} - -kern_return_t -S_proc_register_version (vpstruct_t process, mach_port_t credential, - string_t name, string_t release, string_t version) -{ - debug ("task id: %d\n", process->task_id); - return proc_register_version (process->proc, credential, - name, release, version); -} - -kern_return_t -S_proc_reauthenticate (vpstruct_t process, mach_port_t rendezvous2) -{ - debug ("task id: %d\n", process->task_id); - return proc_reauthenticate (process->proc, rendezvous2, - MACH_MSG_TYPE_MOVE_SEND); -} - -kern_return_t -S_proc_child (vpstruct_t process, mach_port_t child) -{ - debug ("task id: %d, child task: %d\n", process->task_id, child); - return proc_child (process->proc, child); -} - -kern_return_t -S_proc_setmsgport (vpstruct_t process, mach_port_t reply_port, - mach_msg_type_name_t reply_portPoly, mach_port_t newmsgport, - mach_port_t *oldmsgport, mach_msg_type_name_t *oldmsgportPoly) -{ - kern_return_t ret=0; - debug ("task id: %d\n", process->task_id); - ret = proc_setmsgport (process->proc, newmsgport, oldmsgport); - if (ret == 0){ - *oldmsgportPoly = MACH_MSG_TYPE_MOVE_SEND; - } - return ret; -} - -kern_return_t -S_proc_getmsgport (vpstruct_t process, mach_port_t reply_port, - mach_msg_type_name_t reply_portPoly, pid_t pid, - mach_port_t *msgport) -{ - debug ("task id: %d\n", process->task_id); - return proc_getmsgport (getproc(), pid, msgport); -} - -kern_return_t -S_proc_reassign (vpstruct_t process, mach_port_t newtask) -{ - debug ("task id: %d\n", process->task_id); - return proc_reassign (process->proc, newtask); -} - -kern_return_t -S_proc_setowner (vpstruct_t process, uid_t owner, int clear) -{ - debug ("task id: %d\n", process->task_id); - return proc_setowner (process->proc, owner, clear); -} - -kern_return_t -S_proc_getpids (vpstruct_t process, pid_t *pid, - pid_t *ppid, int *orphaned) -{ - debug ("task id: %d\n", process->task_id); - return proc_getpids (process->proc, pid, ppid, orphaned); -} - -kern_return_t -S_proc_set_arg_locations (vpstruct_t process, vm_address_t argv, - vm_address_t envp) -{ - kern_return_t ret; - debug ("task id: %d\n", process->task_id); - ret = proc_set_arg_locations(process->proc , argv , envp); - if (ret) - error (4, ret, "proc_set_arg_locations"); - return ret; -} - -kern_return_t -S_proc_get_arg_locations (vpstruct_t process, vm_address_t *argv, - vm_address_t *envp) -{ - debug ("task id: %d\n", process->task_id); - return proc_get_arg_locations (process->proc, argv, envp); -} - -kern_return_t -S_proc_wait (vpstruct_t process, mach_port_t reply_port, - mach_msg_type_name_t reply_portPoly, pid_t pid, int options, - int *status, int *sigcode, rusage_t *rusage, pid_t *pid_status) -{ - debug ("task id: %d\n", process->task_id); - return proc_wait (process->proc, pid, options, status, sigcode, - rusage, pid_status); -} - -kern_return_t -S_proc_dostop (vpstruct_t process, mach_port_t contthread) -{ - kern_return_t ret; - - debug ("task id: %d\n", process->task_id); - ret = proc_dostop(process->proc, contthread); - if (ret) - error (4, ret, "proc_dostop"); - return ret; -} - -kern_return_t -S_proc_handle_exceptions (vpstruct_t process, mach_port_t msgport, - mach_port_t forwardport, int flavor, - thread_state_t new_state, - mach_msg_type_number_t new_stateCnt) -{ - debug ("task id: %d\n", process->task_id); - return proc_handle_exceptions (process->proc, msgport, forwardport, - MACH_MSG_TYPE_MOVE_SEND, flavor, - new_state, new_stateCnt); -} - -kern_return_t -S_proc_mark_stop (vpstruct_t process, int signo, int sigcode) -{ - debug ("task id: %d\n", process->task_id); - return proc_mark_stop (process->proc, signo, sigcode); -} - -kern_return_t -S_proc_mark_cont (vpstruct_t process) -{ - debug ("task id: %d\n", process->task_id); - return proc_mark_cont (process->proc); -} - -kern_return_t -S_proc_mark_exit (vpstruct_t process, int status, int sigcode) -{ - debug ("task id: %d\n", process->task_id); - return proc_mark_exit (process->proc, status, sigcode); -} - -kern_return_t -S_proc_mark_traced (vpstruct_t process) -{ - debug ("task id: %d\n", process->task_id); - return proc_mark_traced (process->proc); -} - -kern_return_t -S_proc_mark_exec (vpstruct_t process) -{ - debug ("task id: %d\n", process->task_id); - return proc_mark_exec (process->proc); -} - -kern_return_t -S_proc_mod_stopchild (vpstruct_t process, int doit) -{ - debug ("task id: %d\n", process->task_id); - return proc_mod_stopchild (process->proc , doit); -} - -kern_return_t -S_proc_pid2task (vpstruct_t process, pid_t pid, mach_port_t *task) -{ - kern_return_t ret; - ret = proc_pid2task (getproc (), pid, task); - debug ("pid: %d, task: %d\n", pid, *task); - return ret; -} - -kern_return_t -S_proc_task2pid (vpstruct_t process, mach_port_t task, pid_t *pid) -{ - debug ("task id: %d\n", task); - return proc_task2pid (getproc (), task, pid); -} - -kern_return_t -S_proc_task2proc (vpstruct_t callerp, mach_port_t task, - mach_port_t *proc) -{ - kern_return_t err; - process_t actual_proc; - - debug ("task id: %d\n", task); - vpstruct_t process = find_task (task); - *proc = ports_get_right (process); - - /* Get the actuall port to the proc server. */ - err = proc_task2proc (getproc (), task, &actual_proc); - if (err) - error (3, err, "proc_task2proc"); - process->proc = actual_proc; - - /* TODO Do I always need to deallocate task? */ - mach_port_deallocate (mach_task_self (), task); - return 0; -} - -kern_return_t -S_proc_proc2task (vpstruct_t process, mach_port_t *task) -{ - debug ("task id: %d\n", process->task_id); - *task = process->task_id; - return 0; -} - -kern_return_t -S_proc_pid2proc (vpstruct_t process, pid_t pid, mach_port_t *proc) -{ - debug ("pid id: %d\n", pid); - return proc_pid2proc (getproc (), pid, proc); -} - -kern_return_t -S_proc_getprocinfo (vpstruct_t process, pid_t which, int *flags, - procinfo_t *procinfo, mach_msg_type_number_t *procinfoCnt, - data_t *threadwaits, mach_msg_type_number_t *threadwaitsCnt) -{ - debug ("pid id: %d\n", which); - return proc_getprocinfo (getproc (), which, flags, procinfo, - procinfoCnt, threadwaits, threadwaitsCnt); -} - -kern_return_t -S_proc_getprocargs (vpstruct_t process, pid_t which, - data_t *procargs, mach_msg_type_number_t *procargsCnt) -{ - debug ("pid id: %d\n", which); - return proc_getprocargs (getproc (), which, procargs, procargsCnt); -} - -kern_return_t -S_proc_getprocenv (vpstruct_t process, pid_t which, - data_t *procenv, mach_msg_type_number_t *procenvCnt) -{ - debug ("pid id: %d\n", which); - return proc_getprocenv (getproc (), which, procenv, procenvCnt); -} - -kern_return_t -S_proc_make_login_coll (vpstruct_t process) -{ - debug ("task id: %d\n", process->task_id); - return proc_make_login_coll (process->proc); -} - -kern_return_t -S_proc_getloginid (vpstruct_t process, pid_t pid, pid_t *login_id) -{ - debug ("pid id: %d\n", pid); - return proc_getloginid (getproc (), pid, login_id); -} - -kern_return_t -S_proc_getloginpids (vpstruct_t process, pid_t id, - pidarray_t *pids, mach_msg_type_number_t *pidsCnt) -{ - debug ("pid id: %d\n", id); - return proc_getloginpids (getproc (), id, pids, pidsCnt); -} - -kern_return_t -S_proc_setlogin (vpstruct_t process, string_t logname) -{ - debug ("task id: %d\n", process->task_id); - return proc_setlogin (process->proc, logname); -} - -kern_return_t -S_proc_getlogin (vpstruct_t process, string_t logname) -{ - debug ("task id: %d\n", process->task_id); - return proc_getlogin (process->proc, logname); -} - -kern_return_t -S_proc_setsid (vpstruct_t process) -{ - debug ("task id: %d\n", process->task_id); - return proc_setsid (process->proc); -} - -kern_return_t -S_proc_getsid (vpstruct_t process, pid_t pid, pid_t *sid) -{ - debug ("pid id: %d\n", pid); - return proc_getsid (getproc (), pid, sid); -} - -kern_return_t -S_proc_getsessionpgids (vpstruct_t process, pid_t sid, - pidarray_t *pgidset, mach_msg_type_number_t *pgidsetCnt) -{ - debug ("pid id: %d\n", sid); - return proc_getsessionpgids (getproc (), sid, pgidset, pgidsetCnt); -} - -kern_return_t -S_proc_getsessionpids (vpstruct_t process, pid_t sid, - pidarray_t *pidset, mach_msg_type_number_t *pidsetCnt) -{ - debug ("pid id: %d\n", sid); - return proc_getsessionpids (getproc (), sid, pidset, pidsetCnt); -} - -kern_return_t -S_proc_getsidport (vpstruct_t process, mach_port_t *sessport, - mach_msg_type_name_t *sessportPoly) -{ - kern_return_t ret; - debug ("task id: %d\n", process->task_id); - ret = proc_getsidport (process->proc, sessport); - if (ret == 0) - *sessportPoly = MACH_MSG_TYPE_MOVE_SEND; - return ret; -} - -kern_return_t -S_proc_setpgrp (vpstruct_t process, pid_t pid, pid_t pgrp) -{ - debug ("pid id: %d\n", pid); - return proc_setpgrp (getproc (), pid, pgrp); -} - -kern_return_t -S_proc_getpgrp (vpstruct_t process, pid_t pid, pid_t *pgrp) -{ - kern_return_t ret; - debug ("pid id: %d\n", pid); - ret = proc_getpgrp(getproc(), pid, pgrp); - if (ret) - error (0, ret, "proc_proxy: proc_getpgrp"); - return ret; -} - -kern_return_t -S_proc_getpgrppids (vpstruct_t process, pid_t pgrp, - pidarray_t *pidset, mach_msg_type_number_t *pidsetCnt) -{ - debug ("pgrp id: %d\n", pgrp); - return proc_getpgrppids (getproc (), pgrp, pidset, pidsetCnt); -} - -kern_return_t -S_proc_get_tty (vpstruct_t calling_process, pid_t target_process, - mach_port_t *tty, mach_msg_type_name_t *ttyPoly) -{ - kern_return_t ret; - debug (""); - ret = proc_get_tty (getproc (), target_process, tty); - if (ret == 0) - *ttyPoly = MACH_MSG_TYPE_MOVE_SEND; - return ret; -} diff --git a/proc_proxy/test.c b/proc_proxy/test.c deleted file mode 100644 index fa3591c0..00000000 --- a/proc_proxy/test.c +++ /dev/null @@ -1,7 +0,0 @@ -#include <stdio.h> - -int main (int argc, char *argv[]) -{ - printf ("hello world: %s\n", argv[1]); - return 0; -} diff --git a/ufs-fsck/Makefile b/ufs-fsck/Makefile deleted file mode 100644 index a484428e..00000000 --- a/ufs-fsck/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -# -# Copyright (C) 1994, 1995, 1996 Free Software Foundation -# 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. - -dir := ufs-fsck -makemode := utility - -SRCS = dir.c main.c pass1.c pass1b.c pass2.c pass3.c pass4.c \ - pass5.c setup.c utilities.c inode.c -OBJS = $(subst .c,.o,$(SRCS)) tables.o -LCLHDRS = fsck.h -target = fsck.ufs -installationdir = $(sbindir) -HURDLIBS=shouldbeinlibc - -include ../Makeconf - -vpath tables.c $(top_srcdir)/ufs - diff --git a/ufs-fsck/dir.c b/ufs-fsck/dir.c deleted file mode 100644 index 85757b16..00000000 --- a/ufs-fsck/dir.c +++ /dev/null @@ -1,567 +0,0 @@ -/* Directory management subroutines - Copyright (C) 1994,96,99,2002 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 "fsck.h" - -/* This routine is used in pass 1 to initialize DIRARRAY and DIRSORTED. - Copy information from DP (for number NUMBER) into a newly allocated - dirinfo structure and add it to the arrays. */ -void -record_directory (struct dinode *dp, ino_t number) -{ - u_int blks; - struct dirinfo *dnp; - - blks = howmany (dp->di_size, sblock->fs_bsize); - if (blks > NDADDR) - blks = NDADDR + NIADDR; - blks *= sizeof (daddr_t); - dnp = malloc (sizeof (struct dirinfo) + blks); - - dnp->i_number = number; - dnp->i_parent = dnp->i_dotdot = 0; - dnp->i_isize = dp->di_size; - dnp->i_numblks = blks; - bcopy (dp->di_db, dnp->i_blks, blks); - - if (dirarrayused == dirarraysize) - { - if (dirarraysize == 0) - { - dirarraysize = 100; - dirarray = malloc (dirarraysize * sizeof (struct dirinfo *)); - dirsorted = malloc (dirarraysize * sizeof (struct dirinfo *)); - } - else - { - dirarraysize *= 2; - dirarray = realloc (dirarray, - dirarraysize * sizeof (struct dirinfo *)); - dirsorted = realloc (dirsorted, - dirarraysize * sizeof (struct dirinfo *)); - } - } - dirarray[dirarrayused] = dnp; - dirsorted[dirarrayused] = dnp; - dirarrayused++; -} - -/* Return the cached dirinfo structure for directory INO. */ -struct dirinfo * -lookup_directory (ino_t ino) -{ - int i; - - for (i = 0; i < dirarrayused; i++) - if (dirarray[i]->i_number == ino) - return dirarray[i]; - - errexit ("Cannot find cached directory I=%Ld\n", ino); -} - -/* Check to see if DIR is really a readable directory; if it - isn't, then bail with an appropriate message and return 0; - else return 1. MSG identifies the action contemplated */ -static int -validdir (ino_t dir, char *action) -{ - switch (inodestate[dir]) - { - case DIRECTORY: - case DIRECTORY|DIR_REF: - return 1; - - case UNALLOC: - warning (1, "CANNOT %s I=%Ld; NOT ALLOCATED", action, dir); - return 0; - - case BADDIR: - warning (1, "CANNOT %s I=%Ld; BAD BLOCKS", action, dir); - return 0; - - case REG: - warning (1, "CANNOT %s I=%Ld; NOT DIRECTORY", action, dir); - return 0; - - default: - errexit ("ILLEGAL STATE"); - } -} - -/* Search directory DIR for name NAME. If NAME is found, then - set *INO to the inode of the entry; otherwise clear INO. Returns 1 if all - was normal, or 0 if there was some error doing the search. */ -int -searchdir (ino_t dir, char *name, ino_t *ino) -{ - struct dinode dino; - int len; - - /* Scan through one directory block and see if it - contains NAME. */ - void - check1block (void *buf) - { - struct directory_entry *dp; - - for (dp = buf; (void *)dp - buf < DIRBLKSIZ; - dp = (struct directory_entry *) ((void *)dp + dp->d_reclen)) - { - if (dp->d_reclen == 0 - || dp->d_reclen + (void *)dp - buf > DIRBLKSIZ) - return; - - if (dp->d_ino == 0 || dp->d_ino > maxino) - continue; - - if (DIRECT_NAMLEN (dp) == len && strcmp (dp->d_name, name) == 0) - { - *ino = dp->d_ino; - return; - } - } - } - - /* Read part of a directory and look to see if it contains - NAME. Return 1 if we should keep looking at more - blocks. */ - int - checkdirblock (daddr_t bno, int nfrags, off_t offset) - { - void *buf = alloca (nfrags * sblock->fs_fsize); - void *bufp; - - readblock (fsbtodb (sblock, bno), buf, nfrags * sblock->fs_fsize); - for (bufp = buf; - bufp - buf < nfrags * sblock->fs_fsize - && offset + (bufp - buf) + DIRBLKSIZ <= dino.di_size; - bufp += DIRBLKSIZ) - { - check1block (bufp); - if (*ino) - return 0; - } - return 1; - } - - *ino = 0; - - if (!validdir (dir, "READ")) - return 0; - - getinode (dir, &dino); - - len = strlen (name); - datablocks_iterate (&dino, checkdirblock); - - return 1; -} - -/* Change the existing entry in DIR for name NAME to be - inode INO. Return 1 if the entry was found and - replaced, else return 0. */ -int -changeino (ino_t dir, char *name, ino_t ino) -{ - struct dinode dino; - int len; - int madechange; - - /* Scan through a directory block looking for NAME; - if we find it then change the inode pointer to point - at INO and return 1; if we don't find it then return 0. */ - int - check1block (void *buf) - { - struct directory_entry *dp; - - for (dp = buf; (void *)dp - buf < DIRBLKSIZ; - dp = (struct directory_entry *) ((void *)dp + dp->d_reclen)) - { - if (dp->d_reclen == 0 - || dp->d_reclen + (void *)dp - buf > DIRBLKSIZ) - return 0; - - if (dp->d_ino == 0 || dp->d_ino > maxino) - continue; - - if (DIRECT_NAMLEN (dp) == len && strcmp (dp->d_name, name) == 0) - { - dp->d_ino = ino; - madechange = 1; - return 1; - } - } - return 0; - } - - /* Read part of a directory and look to see if it - contains NAME. Return 1 if we should keep looking - at more blocks. */ - int - checkdirblock (daddr_t bno, int nfrags, off_t offset) - { - void *buf = alloca (nfrags * sblock->fs_fsize); - void *bufp; - - readblock (fsbtodb (sblock, bno), buf, nfrags * sblock->fs_fsize); - for (bufp = buf; - bufp - buf < nfrags * sblock->fs_fsize - && offset + (bufp - buf) + DIRBLKSIZ <= dino.di_size; - bufp += DIRBLKSIZ) - { - if (check1block (bufp)) - { - writeblock (fsbtodb (sblock, bno), buf, - nfrags * sblock->fs_fsize); - return 0; - } - } - return 1; - } - - if (!validdir (dir, "REWRITE")) - return 0; - - getinode (dir, &dino); - len = strlen (name); - madechange = 0; - datablocks_iterate (&dino, checkdirblock); - return madechange; -} - -/* Attempt to expand the size of a directory. Return - 1 if we succeeded. */ -static int -expanddir (struct dinode *dp) -{ - daddr_t lastbn, newblk; - char *cp, buf[sblock->fs_bsize]; - - lastbn = lblkno (sblock, dp->di_size); - if (blkoff (sblock, dp->di_size) && lastbn >= NDADDR - 1) - return 0; - else if (!blkoff (sblock, dp->di_size) && lastbn >= NDADDR) - return 0; - else if (blkoff (sblock, dp->di_size) && !dp->di_db[lastbn]) - return 0; - else if (!blkoff (sblock, dp->di_size) && dp->di_db[lastbn]) - return 0; - - newblk = allocblk (sblock->fs_frag); - if (!newblk) - return 0; - - if (blkoff (sblock, dp->di_size)) - dp->di_db[lastbn + 1] = dp->di_db[lastbn]; - dp->di_db[lastbn] = newblk; - dp->di_size += sblock->fs_bsize; - dp->di_blocks += sblock->fs_bsize / DEV_BSIZE; - - for (cp = buf; cp < buf + sblock->fs_bsize; cp += DIRBLKSIZ) - { - struct directory_entry *dir = (struct directory_entry *) cp; - dir->d_ino = 0; - dir->d_reclen = DIRBLKSIZ; - } - - writeblock (fsbtodb (sblock, newblk), buf, sblock->fs_bsize); - return 1; -} - -/* Add a new link into directory DIR with name NAME and target - INO. Return 1 if we succeeded and 0 if we failed. It is - an error to call this routine if NAME is already present - in DIR. */ -int -makeentry (ino_t dir, ino_t ino, char *name) -{ - int len; - struct dinode dino; - int needed; - int madeentry; - - /* Read a directory block and see if it contains room for the - new entry. If so, add it and return 1; otherwise return 0. */ - int - check1block (void *buf) - { - struct directory_entry *dp; - - for (dp = buf; (void *)dp - buf < DIRBLKSIZ; - dp = (struct directory_entry *) ((void *)dp + dp->d_reclen)) - { - if (dp->d_reclen == 0 - || dp->d_reclen + (void *)dp - buf > DIRBLKSIZ) - return 0; - if (dp->d_ino - && dp->d_reclen - DIRSIZ (DIRECT_NAMLEN (dp)) >= needed) - { - struct directory_entry *newdp; - newdp = (struct directory_entry *) - ((void *)dp + DIRSIZ (DIRECT_NAMLEN (dp))); - - newdp->d_reclen = dp->d_reclen - DIRSIZ (DIRECT_NAMLEN (dp)); - DIRECT_NAMLEN (newdp) = len; - newdp->d_ino = ino; - if (direct_symlink_extension) - newdp->d_type = typemap[ino]; - bcopy (name, newdp->d_name, len + 1); - - dp->d_reclen -= newdp->d_reclen; - madeentry = 1; - return 1; - } - else if (!dp->d_ino && dp->d_reclen >= needed) - { - DIRECT_NAMLEN (dp) = len; - dp->d_ino = ino; - if (direct_symlink_extension) - dp->d_type = typemap[ino]; - bcopy (name, dp->d_name, len + 1); - madeentry = 1; - return 1; - } - } - return 0; - } - - /* Read part of a directory and look to see if it - contains NAME. Return 1 if we should keep looking - at more blocks. */ - int - checkdirblock (daddr_t bno, int nfrags, off_t offset) - { - void *buf = alloca (nfrags * sblock->fs_fsize); - void *bufp; - - readblock (fsbtodb (sblock, bno), buf, nfrags * sblock->fs_fsize); - for (bufp = buf; - bufp - buf < nfrags * sblock->fs_fsize - && offset + (bufp - buf) + DIRBLKSIZ <= dino.di_size; - bufp += DIRBLKSIZ) - { - if (check1block (bufp)) - { - writeblock (fsbtodb (sblock, bno), buf, - nfrags * sblock->fs_fsize); - return 0; - } - } - return 1; - } - - if (!validdir (dir, "MODIFY")) - return 0; - - getinode (dir, &dino); - len = strlen (name); - needed = DIRSIZ (len); - madeentry = 0; - datablocks_iterate (&dino, checkdirblock); - if (!madeentry) - { - /* Attempt to expand the directory. */ - problem (0, "NO SPACE LEFT IN DIR INO=%Ld", dir); - if (preen || reply ("EXPAND")) - { - if (expanddir (&dino)) - { - write_inode (ino, &dino); - datablocks_iterate (&dino, checkdirblock); - pfix ("EXPANDED"); - } - else - { - pfail (0); - warning (1, "CANNOT EXPAND DIRECTORY"); - } - } - } - return madeentry; -} - -/* Create a directory node whose parent is to be PARENT, whose inode - is REQUEST, and whose mode is to be MODE. If REQUEST is zero, then - allocate any inode. Initialze the contents of the - directory. Return the inode of the new directory. */ -ino_t -allocdir (ino_t parent, ino_t request, mode_t mode) -{ - ino_t ino; - - mode |= IFDIR; - - ino = allocino (request, mode); - if (!ino) - return 0; - if (!makeentry (ino, ino, ".")) - goto bad; - if (!makeentry (ino, parent, "..")) - goto bad; - - linkfound[ino]++; - linkfound[parent]++; - return ino; - - bad: - freeino (ino); - return 0; -} - -/* Link node INO into lost+found. If PARENT is positive then INO is - a directory, and PARENT is the number of `..' as found in INO. - If PARENT is zero then INO is a directory without any .. entry. - If the node could be linked, return 1; else return 0. */ -int -linkup (ino_t ino, ino_t parent) -{ - int search_failed; - struct dinode lfdino; - char *tempname; - ino_t foo; - - if (lfdir == 0) - { - if (!searchdir (ROOTINO, lfname, &lfdir)) - { - warning (1, "FAILURE SEARCHING FOR `%s'", lfname); - return 0; - } - if (lfdir == 0) - { - problem (0, "NO `%s' DIRECTORY", lfname); - if (preen || reply ("CREATE")) - { - lfdir = allocdir (ROOTINO, 0, lfmode); - if (lfdir != 0) - { - if (! makeentry (ROOTINO, lfdir, lfname)) - { - freeino (lfdir); - linkfound[ROOTINO]--; - lfdir = 0; - } - } - } - if (lfdir) - pfix ("CREATED"); - else - { - pfail (0); - warning (1, "SORRY, CANNOT CREATE `%s' DIRECTORY", lfname); - return 0; - } - } - } - - getinode (lfdir, &lfdino); - if ((lfdino.di_model & IFMT) != IFDIR) - { - ino_t oldlfdir; - - problem (1, "`%s' IS NOT A DIRECTORY", lfname); - if (! reply ("REALLOCATE")) - return 0; - - oldlfdir = lfdir; - - lfdir = allocdir (ROOTINO, 0, lfmode); - if (!lfdir) - { - warning (1, "SORRY, CANNOT CREATE `%s' DIRECTORY", lfname); - return 0; - } - if (!changeino (ROOTINO, lfname, lfdir)) - { - warning (1, "SORRY, CANNOT CREATE `%s' DIRECTORY", lfname); - return 0; - } - - /* One less link to the old one */ - linkfound[oldlfdir]--; - - getinode (lfdir, &lfdino); - } - - if (inodestate[lfdir] != DIRECTORY && inodestate[lfdir] != (DIRECTORY|DIR_REF)) - { - warning (1, "SORRY. `%s' DIRECTORY NOT ALLOCATED", lfname); - return 0; - } - - asprintf (&tempname, "#%Ld", ino); - search_failed = !searchdir (lfdir, tempname, &foo); - while (foo) - { - char *newname; - asprintf (&newname, "%sa", tempname); - free (tempname); - tempname = newname; - search_failed = !searchdir (lfdir, tempname, &foo); - } - if (search_failed) - { - warning (1, "FAILURE SEARCHING FOR `%s' IN `%s'", tempname, lfname); - free (tempname); - return 0; - } - if (!makeentry (lfdir, ino, tempname)) - { - free (tempname); - warning (1, "SORRY, NO SPACE IN `%s' DIRECTORY", lfname); - return 0; - } - free (tempname); - linkfound[ino]++; - - if (parent != -1) - { - /* Reset `..' in ino */ - if (parent) - { - if (!changeino (ino, "..", lfdir)) - { - warning (1, "CANNOT ADJUST `..' LINK I=%Ld", ino); - return 0; - } - /* Forget about link to old parent */ - linkfound[parent]--; - } - else if (!makeentry (ino, lfdir, "..")) - { - warning (1, "CANNOT CREAT `..' LINK I=%Ld", ino); - return 0; - } - - /* Account for link to lost+found; update inode directly - here to avoid confusing warning later. */ - linkfound[lfdir]++; - linkcount[lfdir]++; - lfdino.di_nlink++; - write_inode (lfdir, &lfdino); - - if (parent) - warning (0, "DIR I=%Ld CONNECTED; PARENT WAS I=%Ld", ino, parent); - else - warning (0, "DIR I=%Ld CONNECTED", ino); - } - return 1; -} diff --git a/ufs-fsck/fsck.h b/ufs-fsck/fsck.h deleted file mode 100644 index 4a5dabf5..00000000 --- a/ufs-fsck/fsck.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - Copyright (C) 1994,95,96,2002 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 <sys/types.h> -#include <sys/time.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <dirent.h> - -#define swab_disk 0 - -#include "../ufs/fs.h" -#include "../ufs/dinode.h" -#include "../ufs/dir.h" - -/* Type of an inode */ -#define UNALLOC 0 -#define REG 1 -#define DIRECTORY 2 -#define BADDIR 3 - -/* Added to directories in pass 2 */ -#define DIR_REF 4 /* dir has been found in connectivity search */ - -/* State of each inode (set by pass 1) */ -char *inodestate; - -/* Number of links claimed by each inode (set by pass 1) */ -nlink_t *linkcount; - -/* Number of links found to each inode (set by pass 2) */ -nlink_t *linkfound; - -/* DT_foo type of each inode (set by pass 1) */ -char *typemap; - -/* Map of blocks allocated */ -char *blockmap; - -/* A string identifying what we're trying to check. */ -extern char *device_name; - - -/* Command line flags */ -int nowrite; /* all questions fail */ -int noquery; /* all questions succeed */ - - -enum contret -{ - RET_STOP, - RET_GOOD, - RET_BAD, -}; - - -/* One of these structures is set up for each directory by - pass 1 and used by passes 2 and 3. */ -struct dirinfo -{ - struct inoinfo *i_nexthash; /* next entry in hash chain */ - ino_t i_number; /* inode entry of this dir */ - ino_t i_parent; /* inode entry of parent */ - ino_t i_dotdot; /* inode number of `..' */ - ino_t i_dot; /* inode number of `.' */ - u_int i_isize; /* size of inode */ - u_int i_numblks; /* size of block array in bytes */ - daddr_t i_blks[0]; /* array of inode block addresses */ -}; - -/* Array of all the dirinfo structures in inode number order */ -struct dirinfo **dirarray; - -/* Array of all thi dirinfo structures sorted by their first - block address */ -struct dirinfo **dirsorted; - -int dirarrayused; /* number of directories */ -int dirarraysize; /* alloced size of dirarray/dirsorted */ - -struct dups { - struct dups *next; - daddr_t dup; -}; -struct dups *duplist; /* head of dup list */ -struct dups *muldup; /* end of unique duplicate dup block numbers */ - - -extern struct fs *sblock; - -extern daddr_t maxfsblock; -extern int maxino; -extern int direct_symlink_extension; - -extern int newinofmt; - -/* Terse automatic mode for noninteractive use; punts on severe problems. */ -extern int preen; - -extern int readfd, writefd; - -extern int fix_denied; - -extern int fsmodified; - -extern ino_t lfdir; - -/* Total number of files found on the partition. */ -extern long num_files; - -extern mode_t lfmode; -extern char *lfname; - -#define NBBY 8 -#define howmany(x,y) (((x)+((y)-1))/(y)) -#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) -#define isclr(a, i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) -#define isset(a, i) ((a)[(i)/NBBY] & (1<<((i)%NBBY))) -#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY)) -#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<(i)%NBBY)) -#define DEV_BSIZE 512 - -#define setbmap(blkno) setbit (blockmap, blkno) -#define testbmap(blkno) isset (blockmap, blkno) -#define clrbmap(blkno) clrbit (blockmap, blkno) - -#define DI_MODE(dp) (((dp)->di_modeh << 16) | (dp)->di_model) - - - -int setup (char *); -void pass1 (), pass1b (), pass2 (), pass3 (), pass4 (), pass5 (); - -void readblock (daddr_t, void *, size_t); -void writeblock (daddr_t, void *, size_t); - -void getinode (ino_t, struct dinode *); -void write_inode (ino_t, struct dinode *); -void clear_inode (ino_t, struct dinode *); - -daddr_t allocblk (int); -int check_range (daddr_t, int); - -ino_t allocino (ino_t, mode_t); -void freeino (ino_t); -ino_t allocdir (ino_t, ino_t, mode_t); - -int makeentry (ino_t, ino_t, char *); -int changeino (ino_t, char *, ino_t); - -int linkup (ino_t, ino_t); - -void datablocks_iterate (struct dinode *, int (*)(daddr_t, int, off_t)); -void allblock_iterate (struct dinode *, int (*)(daddr_t, int, off_t)); - -void record_directory (struct dinode *, ino_t); -struct dirinfo *lookup_directory (ino_t); - -void errexit (char *, ...) __attribute__ ((format (printf, 1, 2), noreturn)); -void warning (int, char *, ...) __attribute__ ((format (printf, 2, 3))); -void problem (int, char *, ...) __attribute__ ((format (printf, 2, 3))); -void pinode (int, ino_t, char *fmt, ...) __attribute__ ((format (printf, 3, 4))); -void pextend (char *, ...) __attribute__ ((format (printf, 1, 2))); -void pfix (char *fix), pfail (char *reason); -int reply (char *); diff --git a/ufs-fsck/inode.c b/ufs-fsck/inode.c deleted file mode 100644 index df4b880e..00000000 --- a/ufs-fsck/inode.c +++ /dev/null @@ -1,203 +0,0 @@ -/* Inode allocation, deallocation, etc. - Copyright (C) 1994, 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 "fsck.h" - -static void -inode_iterate (struct dinode *dp, - int (*fn) (daddr_t, int, off_t), - int doaddrblocks) -{ - mode_t mode = dp->di_model & IFMT; - int nb, maxb; - off_t totaloffset = 0; - - /* Call FN for iblock IBLOCK of level LEVEL and recurse down - the indirect block pointers. */ - int - scaniblock (daddr_t iblock, int level) - { - int cont; - daddr_t ptrs[NINDIR(sblock)]; - int i; - - if (doaddrblocks) - { - cont = (*fn)(iblock, sblock->fs_frag, totaloffset); - if (cont == RET_STOP) - return RET_STOP; - else if (cont == RET_BAD) - return RET_GOOD; - } - - readblock (fsbtodb (sblock, iblock), ptrs, sblock->fs_bsize); - for (i = 0; i < NINDIR (sblock); i++) - { - if (!ptrs[i]) - continue; - - if (level == 0) - { - cont = (*fn)(ptrs[i], sblock->fs_frag, totaloffset); - totaloffset += sblock->fs_bsize; - } - else - cont = scaniblock (ptrs[i], level - 1); - if (cont == RET_STOP) - return RET_STOP; - } - return RET_GOOD; - } - - if (mode == IFBLK || mode == IFCHR - || (mode == IFLNK && sblock->fs_maxsymlinklen != -1 - && (dp->di_size < sblock->fs_maxsymlinklen - || (sblock->fs_maxsymlinklen == 0 && dp->di_blocks == 0)))) - return; - - maxb = lblkno (sblock, dp->di_size - 1); - totaloffset = 0; - for (nb = 0; nb < NDADDR; nb++) - { - int offset; - int nfrags; - - if (nb == maxb && (offset = blkoff (sblock, dp->di_size))) - nfrags = numfrags (sblock, fragroundup (sblock, offset)); - else - nfrags = sblock->fs_frag; - - if (dp->di_db[nb] - && (*fn)(dp->di_db[nb], nfrags, totaloffset) != RET_GOOD) - return; - totaloffset += nfrags * sizeof (sblock->fs_fsize); - } - - for (nb = 0; nb < NIADDR; nb++) - if (dp->di_ib[nb] && scaniblock (dp->di_ib[nb], nb) != RET_GOOD) - return; - - if (doaddrblocks && dp->di_trans) - (*fn)(dp->di_trans, sblock->fs_frag, totaloffset); -} - -void -datablocks_iterate (struct dinode *dp, - int (*fn) (daddr_t, int, off_t)) -{ - inode_iterate (dp, fn, 0); -} - -void -allblock_iterate (struct dinode *dp, - int (*fn) (daddr_t, int, off_t)) -{ - inode_iterate (dp, fn, 1); -} - -/* Allocate an inode. If INUM is nonzero, then allocate that - node specifically, otherwise allocate any available inode. - MODE is the mode of the new file. Return the allocated - inode number (or 0 if the allocation failed). */ -ino_t -allocino (ino_t request, mode_t mode) -{ - ino_t ino; - struct dinode dino; - struct timeval tv; - - if (request) - { - if (inodestate[request] != UNALLOC) - return 0; - ino = request; - } - else - { - for (ino = ROOTINO; ino < maxino; ino++) - if (inodestate[ino] == UNALLOC) - break; - if (ino == maxino) - return 0; - } - - if ((mode & IFMT) == IFDIR) - inodestate[ino] = DIRECTORY | DIR_REF; - else - inodestate[ino] = REG; - - getinode (ino, &dino); - dino.di_modeh = (mode & 0xffff0000) >> 16; - dino.di_model = (mode & 0x0000ffff); - gettimeofday (&tv, 0); - dino.di_atime.tv_sec = tv.tv_sec; - dino.di_atime.tv_nsec = tv.tv_usec * 1000; - dino.di_mtime = dino.di_ctime = dino.di_atime; - dino.di_size = 0; - dino.di_blocks = 0; - num_files++; - write_inode (ino, &dino); - typemap[ino] = IFTODT (mode); - return ino; -} - -/* Deallocate inode INUM. */ -void -freeino (ino_t inum) -{ - struct dinode dino; - - int - clearblock (daddr_t bno, int nfrags, off_t offset) - { - int i; - - for (i = 0; i < nfrags; i++) - { - if (check_range (bno + i, 1)) - return RET_BAD; - if (testbmap (bno + i)) - { - struct dups *dlp; - for (dlp = duplist; dlp; dlp = dlp->next) - { - if (dlp->dup != bno + i) - continue; - dlp->dup = duplist->dup; - dlp = duplist; - duplist = duplist->next; - free (dlp); - break; - } - if (dlp == 0) - clrbmap (bno + i); - } - } - return RET_GOOD; - } - - getinode (inum, &dino); - allblock_iterate (&dino, clearblock); - - clear_inode (inum, &dino); - inodestate[inum] = UNALLOC; - - num_files--; -} diff --git a/ufs-fsck/main.c b/ufs-fsck/main.c deleted file mode 100644 index 34c32a67..00000000 --- a/ufs-fsck/main.c +++ /dev/null @@ -1,170 +0,0 @@ -/* Main program for GNU fsck - Copyright (C) 1994, 1996, 1997 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 <errno.h> -#include <argp.h> -#include <hurd.h> -#include <version.h> - -#include "fsck.h" - -const char *argp_program_version = STANDARD_HURD_VERSION (fsck.ufs); - -char *lfname = "lost+found"; -mode_t lfmode = 0755; - -/* Terse automatic mode for noninteractive use; punts on severe problems. */ -int preen = 0; - -/* Total number of files found on the partition. */ -long num_files = 0; - -static struct argp_option options[] = -{ - {"preen", 'p', 0, 0, "Terse automatic mode", 1}, - {"yes", 'y', 0, 0, "Automatically answer yes to all questions"}, - {"no", 'n', 0, 0, "Automatically answer no to all questions"}, - {"lost+found", 'l', "NAME", 0, "The name of the lost+found directory in /"}, - {"lf-mode", 'm', "MODE", 0, "The mode of the lost+found directory in /"}, - {0, 0, 0, 0, "In --preen mode, the following also apply:", 2}, - {"force", 'f', 0, 0, "Check even if clean"}, - {"silent", 's', 0, 0, "Only print diagostic messages"}, - {0, 0} -}; -char *args_doc = "DEVICE"; - -/* Returns a malloced buffer containing a nice printable size for FRAGS. */ -static char * -nice_size (long frags) -{ - char *rep; - char *units = "KMGT", *u = units; - float num = ((float)frags * sblock->fs_fsize) / 1024; - - while (num > 1024) - { - num /= 1024; - u++; - } - - asprintf (&rep, num >= 1000 ? "%.0f%c" : "%.3g%c", num, *u); - - return rep; -} - -/* Print summary statistics. */ -static void -show_stats () -{ - long num_ffree = sblock->fs_cstotal.cs_nffree; - long num_bfree = sblock->fs_cstotal.cs_nbfree; - long tot_ffree = num_ffree + sblock->fs_frag * num_bfree; - char *urep = nice_size (sblock->fs_dsize - tot_ffree); - char *frep = nice_size (tot_ffree); - warning (0, "%ld files, %s used, %s free (%ld.%ld%% fragmentation)", - num_files, urep, frep, - (num_ffree * 100) / sblock->fs_dsize, - (((num_ffree * 1000 + sblock->fs_dsize / 2) / sblock->fs_dsize) - % 10)); - free (urep); - free (frep); -} - -int -main (int argc, char **argv) -{ - int silent = 0, force = 0; - char *device = 0; - error_t parse_opt (int key, char *arg, struct argp_state *state) - { - switch (key) - { - case 'p': preen = 1; break; - case 'y': noquery = 1; break; - case 'n': nowrite = 1; break; - case 'l': lfname = arg; break; - case 'm': lfmode = strtol (arg, 0, 8); break; - case 'f': force = 1; break; - case 's': silent = 1; break; - case ARGP_KEY_ARG: - if (!device) - { - device = arg; - break; - } - /* Fall through */ - case ARGP_KEY_NO_ARGS: - argp_usage (state); - default: - return ARGP_ERR_UNKNOWN; - } - return 0; - } - struct argp argp = {options, parse_opt, args_doc}; - - preen = nowrite = noquery = 0; - argp_parse (&argp, argc, argv, 0, 0, 0); - - if (!setup (device)) - exit (1); - - if (preen && sblock->fs_clean && !force) - { - if (! silent) - warning (0, "FILESYSTEM CLEAN"); - } - else - { - if (!preen) - printf ("** Phase 1 -- Check Blocks and Sizes\n"); - pass1 (); - - if (duplist) - { - if (!preen) - printf ("** Phase 1b -- Rescan for More Duplicates\n"); - pass1b (); - } - - if (!preen) - printf ("** Phase 2 -- Check Pathnames\n"); - pass2 (); - - if (!preen) - printf ("** Phase 3 -- Check Connectivity\n"); - pass3 (); - - if (!preen) - printf ("** Phase 4 -- Check Reference Counts\n"); - pass4 (); - - if (!preen) - printf ("** Phase 5 -- Check Cyl Groups\n"); - pass5 (); - - if (! silent) - show_stats (sblock); - } - - if (fsmodified && !preen) - printf ("\n***** FILE SYSTEM WAS MODIFIED *****\n"); - - exit (fsmodified ? 2 : 0); -} diff --git a/ufs-fsck/pass1.c b/ufs-fsck/pass1.c deleted file mode 100644 index bd41cc62..00000000 --- a/ufs-fsck/pass1.c +++ /dev/null @@ -1,437 +0,0 @@ -/* Pass one of GNU fsck -- count blocks and verify inodes - Copyright (C) 1994,95,96,2002 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 "fsck.h" - -static struct dinode zino; - -/* Find all the blocks in use by files and filesystem reserved blocks. - Set them in the global block map. For each file, if a block is found - allocated twice, then record the block and inode in DUPLIST. - Initialize INODESTATE, LINKCOUNT, and TYPEMAP. */ -void -pass1 () -{ - ino_t number; - ino_t i; - int cg; - struct dinode dino; - struct dinode *dp = &dino; - mode_t mode, type; - int ndb; - int holdallblocks; - int lbn; - int nblocks; - int blkerror; - int nblkrngerrors; - int nblkduperrors; - - /* This function is called for each block of DP. Check to see - if the block number is valid. If so, set the entry in the - block map. If the block map entry is already set, then keep - track of this block and see if the user wants to clear the - node. Increment NBLOCKS by the number of data blocks held. - Set BLKERROR if this block is invalid. - Return RET_GOOD, RET_BAD, RET_STOP if the block is good, - bad, or if we should entirely stop checking blocks in this - inode. */ - int - checkblock (daddr_t bno, int nfrags, off_t offset) - { -#define MAXBAD 10 - int outofrange; - struct dups *dlp, *new; - int wasbad = 0; - - /* Check to see if this block is in range */ - outofrange = check_range (bno, nfrags); - if (outofrange) - { - blkerror = 1; - wasbad = 1; - if (nblkrngerrors == 0) - warning (0, "I=%Ld HAS BAD BLOCKS", number); - if (nblkrngerrors++ > MAXBAD) - { - problem (0, "EXCESSIVE BAD BLKS I=%Ld", number); - if (preen || reply ("SKIP")) - { - pfail ("SKIPPING"); - return RET_STOP; - } - } - } - - for (; nfrags > 0; bno++, nfrags--) - { - if (outofrange && check_range (bno, 1)) - warning (0, "BAD BLOCK %lu", bno); - else - { - if (!testbmap (bno)) - setbmap (bno); - else - { - blkerror = 1; - if (nblkduperrors == 0) - warning (0, "I=%Ld HAS DUPLICATE BLOCKS", number); - warning (0, "DUPLICATE BLOCK %ld", bno); - wasbad = 1; - if (nblkduperrors++ > MAXBAD) - { - problem (0, "EXCESSIVE DUP BLKS I=%Ld", number); - if (preen || reply ("SKIP")) - { - pfail ("SKIPPING"); - return RET_STOP; - } - } - new = malloc (sizeof (struct dups)); - new->dup = bno; - if (muldup == 0) - { - duplist = muldup = new; - new->next = 0; - } - else - { - new->next = muldup->next; - muldup->next = new; - } - for (dlp = duplist; dlp != muldup; dlp = dlp->next) - if (dlp->dup == bno) - break; - if (dlp == muldup && dlp->dup != bno) - muldup = new; - } - } - nblocks += sblock->fs_fsize / DEV_BSIZE; - } - return wasbad ? RET_BAD : RET_GOOD; - } - - - /* Account for blocks used by meta data */ - for (cg = 0; cg < sblock->fs_ncg; cg++) - { - daddr_t firstdata, firstcgblock, bno; - - /* Each cylinder group past the first reserves data - from its cylinder group copy to (but not including) - the first datablock. - - The first, however, reserves from the very front of the - cylinder group (thus including the boot block), and it also - reserves the data blocks holding the csum information. */ - firstdata = cgdmin (sblock, cg); - if (cg == 0) - { - firstcgblock = cgbase (sblock, cg); - firstdata += howmany (sblock->fs_cssize, sblock->fs_fsize); - } - else - firstcgblock = cgsblock (sblock, cg); - - /* Mark the blocks set */ - for (bno = firstcgblock; bno < firstdata; bno++) - setbmap (bno); - } - - /* Loop through each inode, doing initial checks */ - for (number = 0, cg = 0; cg < sblock->fs_ncg; cg++) - for (i = 0; i < sblock->fs_ipg; i++, number++) - { - /* These record whether we've already complained about extra - direct/indirect blocks. */ - int dbwarn = 0, ibwarn = 0; - -/* if (!preen && !(number % 10000)) - printf ("I=%Ld\n", number); */ - - if (number < ROOTINO) - continue; - - getinode (number, dp); - mode = DI_MODE (dp); - type = mode & IFMT; - - /* If the node is not allocated, then make sure it's - properly clear */ - if (type == 0) - { - if (bcmp (dp->di_db, zino.di_db, NDADDR * sizeof (daddr_t)) - || bcmp (dp->di_ib, zino.di_ib, NIADDR * sizeof (daddr_t)) - || dp->di_trans - || DI_MODE (dp) - || dp->di_size) - { - problem (0, "PARTIALLY ALLOCATED INODE I=%Ld", number); - if (preen || reply ("CLEAR")) - { - clear_inode (number, dp); - pfix ("CLEARED"); - } - } - inodestate[number] = UNALLOC; - } - else - { - /* Node is allocated. */ - - /* Check to see if we think the node should be cleared */ - - /* Verify size for basic validity */ - holdallblocks = 0; - - if (dp->di_size + sblock->fs_bsize - 1 < dp->di_size) - { - problem (1, "OVERFLOW IN FILE SIZE I=%Ld (SIZE == %lld)", number, - dp->di_size); - if (reply ("CLEAR")) - { - clear_inode (number, dp); - inodestate[number] = UNALLOC; - continue; - } - inodestate[number] = UNALLOC; - warning (0, "WILL TREAT ANY BLOCKS HELD BY I=%Ld AS ALLOCATED", - number); - holdallblocks = 1; - } - - /* Decode type and set NDB - also set inodestate correctly. */ - inodestate[number] = REG; - switch (type) - { - case IFBLK: - case IFCHR: - ndb = 1; - break; - - case IFIFO: - case IFSOCK: - ndb = 0; - break; - - case IFLNK: - if (sblock->fs_maxsymlinklen != -1) - { - /* Check to see if this is a fastlink. The - old fast link format has fs_maxsymlinklen - of zero and di_blocks zero; the new format has - fs_maxsymlinklen set and we ignore di_blocks. - So check for either. */ - if ((sblock->fs_maxsymlinklen - && dp->di_size < sblock->fs_maxsymlinklen) - || (!sblock->fs_maxsymlinklen && !dp->di_blocks)) - { - /* Fake NDB value so that we will check - all the block pointers past the symlink */ - ndb = howmany (dp->di_size, sizeof (daddr_t)); - if (ndb > NDADDR) - { - int j = ndb - NDADDR; - for (ndb = 1; j > 1; i--) - ndb *= NINDIR (sblock); - ndb += NDADDR; - } - } - else - ndb = howmany (dp->di_size, sblock->fs_bsize); - } - else - ndb = howmany (dp->di_size, sblock->fs_bsize); - break; - - case IFDIR: - inodestate[number] = DIRECTORY; - /* Fall through */ - case IFREG: - ndb = howmany (dp->di_size, sblock->fs_bsize); - break; - - default: - problem (1, "UNKNOWN FILE TYPE I=%Ld (MODE=%ol)", number, mode); - if (reply ("CLEAR")) - { - clear_inode (number, dp); - inodestate[number] = UNALLOC; - continue; - } - inodestate[number] = UNALLOC; - holdallblocks = 1; - warning (0, "WILL TREAT ANY BLOCKS HELD BY I=%Ld " - "AS ALLOCATED", number); - ndb = 0; - } - - if (ndb < 0) - { - problem (1, "BAD FILE SIZE I= %Ld (SIZE == %lld)", number, - dp->di_size); - if (reply ("CLEAR")) - { - clear_inode (number, dp); - inodestate[number] = UNALLOC; - continue; - } - inodestate[number] = UNALLOC; - warning (0, "WILL TREAT ANY BLOCKS HELD BY I=%Ld AS ALLOCATED", - number); - holdallblocks = 1; - } - - /* Make sure that direct and indirect block pointers - past the file size are zero. If the size is bogus, then - don't bother (they should all be zero, but the user has - requested that they be treated as allocated). */ - if (!holdallblocks) - { - if (dp->di_size - && (type == IFBLK || type == IFCHR - || type == IFSOCK || type == IFIFO)) - { - problem (1, "SPECIAL NODE I=%Ld (MODE=%ol) HAS SIZE %lld", - number, mode, dp->di_size); - if (reply ("TRUNCATE")) - { - dp->di_size = 0; - write_inode (number, dp); - } - } - - /* If we haven't set NDB speciall above, then it is set from - the file size correctly by the size check. */ - - /* Check all the direct and indirect blocks that are past the - amount necessary to be zero. */ - for (lbn = ndb; lbn < NDADDR; lbn++) - { - if (dp->di_db[lbn]) - { - if (!dbwarn) - { - dbwarn = 1; - problem (0, "INODE I=%Ld HAS EXTRA DIRECT BLOCKS", - number); - if (preen || reply ("DEALLOCATE")) - { - dp->di_db[lbn] = 0; - dbwarn = 2; - pfix ("DEALLOCATED"); - } - } - else if (dbwarn == 2) - dp->di_db[lbn] = 0; - } - if (dbwarn == 2) - write_inode (number, dp); - } - - for (lbn = 0, ndb -= NDADDR; ndb > 0; lbn++) - ndb /= NINDIR (sblock); - for (; lbn < NIADDR; lbn++) - { - if (dp->di_ib[lbn]) - { - if (ibwarn) - { - ibwarn = 1; - problem (0, "INODE I=%Ld HAS EXTRA INDIRECT BLOCKS", - number); - if (preen || reply ("DEALLOCATE")) - { - dp->di_ib[lbn] = 0; - ibwarn = 2; - pfix ("DEALLOCATED"); - } - } - else if (ibwarn == 2) - dp->di_ib[lbn] = 0; - } - if (ibwarn == 2) - write_inode (number, dp); - } - } - - /* If this node is really allocated (as opposed to something - that we should clear but the user won't) then set LINKCOUNT - and TYPEMAP entries. */ - if (inodestate[number] != UNALLOC) - { - linkcount[number] = dp->di_nlink; - typemap[number] = IFTODT (mode); - } - - /* Iterate over the blocks of the file, - calling CHECKBLOCK for each file. */ - nblocks = 0; - blkerror = 0; - nblkduperrors = 0; - nblkrngerrors = 0; - allblock_iterate (dp, checkblock); - - if (blkerror) - { - if (preen) - warning (1, "DUPLICATE or BAD BLOCKS"); - else - { - problem (0, "I=%Ld has ", number); - if (nblkduperrors) - { - pextend ("%d DUPLICATE BLOCKS", nblkduperrors); - if (nblkrngerrors) - pextend (" and "); - } - if (nblkrngerrors) - pextend ("%d BAD BLOCKS", nblkrngerrors); - if (reply ("CLEAR")) - { - clear_inode (number, dp); - inodestate[number] = UNALLOC; - continue; - } - else if (inodestate[number] == DIRECTORY) - inodestate[number] = BADDIR; - } - } - else if (dp->di_blocks != nblocks) - { - problem (0, "INCORRECT BLOCK COUNT I=%Ld (%ld should be %d)", - number, dp->di_blocks, nblocks); - if (preen || reply ("CORRECT")) - { - dp->di_blocks = nblocks; - write_inode (number, dp); - pfix ("CORRECTED"); - } - } - - num_files++; - - if (type == IFDIR) - record_directory (dp, number); - } - } -} diff --git a/ufs-fsck/pass1b.c b/ufs-fsck/pass1b.c deleted file mode 100644 index 4da86974..00000000 --- a/ufs-fsck/pass1b.c +++ /dev/null @@ -1,90 +0,0 @@ -/* Pass 1b of fsck -- scan inodes for references to duplicate blocks - Copyright (C) 1994,96,2002 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 "fsck.h" - -void -pass1b () -{ - struct dinode dino; - struct dinode *dp = &dino; - int cg, i; - ino_t number = 0; - int dupblk; - struct dups *duphead = duplist; - - /* Check each block of file DP; if the block is in the dup block - list then add it to the dup block list under this file. - Return RET_GOOD or RET_BAD if the block is - good or bad, respectively. */ - int - checkblock (daddr_t bno, int nfrags, off_t offset) - { - struct dups *dlp; - int hadbad = 0; - - for (; nfrags > 0; bno++, nfrags--) - { - if (check_range (bno, 1)) - return RET_BAD; - for (dlp = duphead; dlp; dlp = dlp->next) - { - if (dlp->dup == bno) - { - dupblk++; - warning (0, "DUPLICATE BLOCK %ld\n", bno); - dlp->dup = duphead->dup; - duphead->dup = bno; - duphead = duphead->next; - hadbad = 1; - } - if (dlp == muldup) - break; - } - } - return hadbad ? RET_BAD : RET_GOOD; - } - - /* Call CHECKBLOCK for each block of each node, to see if it holds - a block already found to be a duplicate. */ - for (cg = 0; cg < sblock->fs_ncg; cg++) - for (i = 0; i < sblock->fs_ipg; i++, number++) - { - if (number < ROOTINO) - continue; - if (inodestate[number] != UNALLOC) - { - getinode (number, dp); - dupblk = 0; - allblock_iterate (dp, checkblock); - if (dupblk) - { - problem (1, "I=%Ld HAS %d DUPLICATE BLOCKS", number, dupblk); - if (reply ("CLEAR")) - { - clear_inode (number, dp); - inodestate[number] = UNALLOC; - } - else if (inodestate[number] == DIRECTORY) - inodestate[number] = BADDIR; - } - } - } -} diff --git a/ufs-fsck/pass2.c b/ufs-fsck/pass2.c deleted file mode 100644 index d95929ef..00000000 --- a/ufs-fsck/pass2.c +++ /dev/null @@ -1,400 +0,0 @@ -/* Pass 2 of GNU fsck -- examine all directories for validity - Copyright (C) 1994,96,2002 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 "fsck.h" -#include <assert.h> - -/* Verify root inode's allocation and check all directories for - viability. Set DIRSORTED array fully and check to make sure - each directory has a correct . and .. in it. */ -void -pass2 () -{ - int nd; - struct dirinfo *dnp; - struct dinode dino; - - /* Return negative, zero, or positive according to the - ordering of the first data block of **DNP1 and **DNP2. */ - int - sortfunc (const void *ptr1, const void *ptr2) - { - struct dirinfo * const *dnp1 = ptr1; - struct dirinfo * const *dnp2 = ptr2; - return ((*dnp1)->i_blks[0] - (*dnp2)->i_blks[0]); - } - - /* Called for each DIRBLKSIZ chunk of the directory. - BUF is the data of the directory block. Return - 1 if this block has been modified and should be written - to disk; otherwise return 0. */ - int - check1block (void *buf) - { - struct directory_entry *dp; - int mod = 0; - u_char namlen; - char type; - int i; - - for (dp = buf; (void *)dp - buf < DIRBLKSIZ; - dp = (struct directory_entry *) ((void *)dp + dp->d_reclen)) - { - /* Check RECLEN for basic validity */ - if (dp->d_reclen == 0 - || dp->d_reclen + (void *)dp - buf > DIRBLKSIZ) - { - /* Perhaps the entire dir block is zero. UFS does that - when extending directories. So allow preening - to safely patch up all-null dir blocks. */ - if (dp == buf) - { - char *bp; - for (bp = (char *)buf; bp < (char *)buf + DIRBLKSIZ; bp++) - if (*bp) - goto reclen_problem; - - problem (0, "NULL BLOCK IN DIRECTORY"); - if (preen || reply ("PATCH")) - { - /* Mark this entry free, and return. */ - dp->d_ino = 0; - dp->d_reclen = DIRBLKSIZ; - pfix ("PATCHED"); - return 1; - } - else - return mod; - } - - reclen_problem: - problem (1, "BAD RECLEN IN DIRECTORY"); - if (reply ("SALVAGE")) - { - /* Skip over everything else in this dirblock; - mark this entry free. */ - dp->d_ino = 0; - dp->d_reclen = DIRBLKSIZ - ((void *)dp - buf); - return 1; - } - else - /* But give up regardless */ - return mod; - } - - /* Check INO */ - if (dp->d_ino > maxino) - { - problem (1, "BAD INODE NUMBER IN DIRECTORY"); - if (reply ("SALVAGE")) - { - /* Mark this entry clear */ - dp->d_ino = 0; - mod = 1; - } - } - - if (!dp->d_ino) - continue; - - /* Check INO */ - if (inodestate[dp->d_ino] == UNALLOC) - { - pinode (0, dnp->i_number, "REF TO UNALLOCATED NODE IN"); - if (preen || reply ("REMOVE")) - { - dp->d_ino = 0; - mod = 1; - pfix ("REMOVED"); - continue; - } - } - - /* Check NAMLEN */ - namlen = DIRECT_NAMLEN (dp); - if (namlen > MAXNAMLEN) - { - problem (1, "BAD NAMLEN IN DIRECTORY"); - if (reply ("SALVAGE")) - { - /* Mark this entry clear */ - dp->d_ino = 0; - mod = 1; - } - } - else - { - /* Check for illegal characters */ - for (i = 0; i < DIRECT_NAMLEN (dp); i++) - if (dp->d_name[i] == '\0' || dp->d_name[i] == '/') - { - problem (1, "ILLEGAL CHARACTER IN FILE NAME"); - if (reply ("SALVAGE")) - { - /* Mark this entry clear */ - dp->d_ino = 0; - mod = 1; - break; - } - } - if (dp->d_name[DIRECT_NAMLEN (dp)]) - { - problem (1, "DIRECTORY NAME NOT TERMINATED"); - if (reply ("SALVAGE")) - { - /* Mark this entry clear */ - dp->d_ino = 0; - mod = 1; - } - } - } - - if (!dp->d_ino) - continue; - - /* Check TYPE */ - type = DIRECT_TYPE (dp); - if (type != DT_UNKNOWN && type != typemap[dp->d_ino]) - { - problem (0, "INCORRECT NODE TYPE IN DIRECTORY"); - if (preen || reply ("CLEAR")) - { - pfix ("CLEARED"); - dp->d_type = 0; - mod = 1; - } - } - - /* Here we should check for duplicate directory entries; - that's too much trouble right now. */ - - /* Account for the inode in the linkfound map */ - if (inodestate[dp->d_ino] != UNALLOC) - linkfound[dp->d_ino]++; - - if (inodestate[dp->d_ino] == DIRECTORY - || inodestate[dp->d_ino] == BADDIR) - { - if (DIRECT_NAMLEN (dp) == 1 && dp->d_name[0] == '.') - dnp->i_dot = dp->d_ino; - else if (DIRECT_NAMLEN (dp) == 2 - && dp->d_name[0] == '.' && dp->d_name[1] == '.') - dnp->i_dotdot = dp->d_ino; - else - { - struct dirinfo *targetdir; - targetdir = lookup_directory (dp->d_ino); - if (targetdir->i_parent) - { - problem (0, "EXTRANEOUS LINK `%s' TO DIR I=%ld", - dp->d_name, dp->d_ino); - pextend (" FOUND IN DIR I=%Ld", dnp->i_number); - if (preen || reply ("REMOVE")) - { - dp->d_ino = 0; - mod = 1; - pfix ("REMOVED"); - } - } - else - targetdir->i_parent = dnp->i_number; - } - } - } - return mod; - } - - /* Called for each filesystem block of the directory. Load BNO - into core and then call CHECK1BLOCK for each DIRBLKSIZ chunk. - OFFSET is the offset this block occupies ithe file. - Always return 1. */ - int - checkdirblock (daddr_t bno, int nfrags, off_t offset) - { - void *buf = alloca (nfrags * sblock->fs_fsize); - void *bufp; - int rewrite; - - readblock (fsbtodb (sblock, bno), buf, nfrags * sblock->fs_fsize); - rewrite = 0; - for (bufp = buf; - bufp - buf < nfrags * sblock->fs_fsize - && offset + (bufp - buf) + DIRBLKSIZ <= dnp->i_isize; - bufp += DIRBLKSIZ) - { - if (check1block (bufp)) - rewrite = 1; - } - if (rewrite) - writeblock (fsbtodb (sblock, bno), buf, nfrags * sblock->fs_fsize); - return 1; - } - - switch (inodestate [ROOTINO]) - { - default: - errexit ("BAD STATE %d FOR ROOT INODE", (int) (inodestate[ROOTINO])); - - case DIRECTORY: - break; - - case UNALLOC: - problem (1, "ROOT INODE UNALLOCATED"); - if (!reply ("ALLOCATE")) - errexit ("ABORTING"); - if (allocdir (ROOTINO, ROOTINO, 0755) != ROOTINO) - errexit ("CANNOT ALLOCATE ROOT INODE"); - break; - - case REG: - problem (1, "ROOT INODE NOT DIRECTORY"); - if (reply ("REALLOCATE")) - freeino (ROOTINO); - if (allocdir (ROOTINO, ROOTINO, 0755) != ROOTINO) - errexit ("CANNOT ALLOCATE ROOT INODE"); - break; - - case BADDIR: - problem (1, "DUPLICATE or BAD BLOCKS IN ROOT INODE"); - if (reply ("REALLOCATE")) - { - freeino (ROOTINO); - if (allocdir (ROOTINO, ROOTINO, 0755) != ROOTINO) - errexit ("CANNOT ALLOCATE ROOT INODE"); - } - if (reply ("CONTINUE") == 0) - errexit ("ABORTING"); - break; - } - - /* Sort inpsort */ - qsort (dirsorted, dirarrayused, sizeof (struct dirinfo *), sortfunc); - - /* Check basic integrity of each directory */ - for (nd = 0; nd < dirarrayused; nd++) - { - dnp = dirsorted[nd]; - - if (dnp->i_isize == 0) - continue; - if (dnp->i_isize % DIRBLKSIZ) - { - problem (0, "DIRECTORY INO=%Ld: LENGTH %d NOT MULTIPLE OF %d", - dnp->i_number, dnp->i_isize, DIRBLKSIZ); - if (preen || reply ("ADJUST")) - { - getinode (dnp->i_number, &dino); - dino.di_size = roundup (dnp->i_isize, DIRBLKSIZ); - write_inode (dnp->i_number, &dino); - pfix ("ADJUSTED"); - } - } - bzero (&dino, sizeof (struct dinode)); - dino.di_size = dnp->i_isize; - assert (dnp->i_numblks <= (NDADDR + NIADDR) * sizeof (daddr_t)); - bcopy (dnp->i_blks, dino.di_db, dnp->i_numblks); - - datablocks_iterate (&dino, checkdirblock); - } - - - /* At this point for each directory: - If this directory is an entry in another directory, then i_parent is - set to that node's number. - If this directory has a `..' entry, then i_dotdot is set to that link. - Check to see that `..' is set correctly. */ - for (nd = 0; nd < dirarrayused; nd++) - { - dnp = dirsorted[nd]; - - /* Root is considered to be its own parent even though it isn't - listed. */ - if (dnp->i_number == ROOTINO && !dnp->i_parent) - dnp->i_parent = ROOTINO; - - /* Check `.' to make sure it exists and is correct */ - if (dnp->i_dot == 0) - { - dnp->i_dot = dnp->i_number; - pinode (0, dnp->i_number, "MISSING `.' IN"); - if ((preen || reply ("FIX")) - && makeentry (dnp->i_number, dnp->i_number, ".")) - { - linkfound[dnp->i_number]++; - pfix ("FIXED"); - } - else - pfail (0); - } - else if (dnp->i_dot != dnp->i_number) - { - pinode (0, dnp->i_number, "BAD INODE NUMBER FOR `.' IN"); - if (preen || reply ("FIX")) - { - ino_t old_dot = dnp->i_dot; - dnp->i_dot = dnp->i_number; - if (changeino (dnp->i_number, ".", dnp->i_number)) - { - linkfound[dnp->i_number]++; - if (inodestate[old_dot] != UNALLOC) - linkfound[old_dot]--; - pfix ("FIXED"); - } - else - pfail (0); - } - } - - /* Check `..' to make sure it exists and is correct */ - if (dnp->i_parent && dnp->i_dotdot == 0) - { - dnp->i_dotdot = dnp->i_parent; - pinode (0, dnp->i_number, "MISSING `..' IN"); - if ((preen || reply ("FIX")) - && makeentry (dnp->i_number, dnp->i_parent, "..")) - { - linkfound[dnp->i_parent]++; - pfix ("FIXED"); - } - else - pfail (0); - } - else if (dnp->i_parent && dnp->i_dotdot != dnp->i_parent) - { - pinode (0, dnp->i_number, "BAD INODE NUMBER FOR `..' IN"); - if (preen || reply ("FIX")) - { - ino_t parent = dnp->i_parent, old_dotdot = dnp->i_dotdot; - dnp->i_dotdot = parent; - if (changeino (dnp->i_number, "..", parent)) - /* Adjust what the parent's link count should be; the actual - count will be corrected in an later pass. */ - { - linkfound[parent]++; - if (inodestate[old_dotdot] != UNALLOC) - linkfound[old_dotdot]--; - pfix ("FIXED"); - } - else - pfail (0); - } - } - } -} diff --git a/ufs-fsck/pass3.c b/ufs-fsck/pass3.c deleted file mode 100644 index fd5ad1b0..00000000 --- a/ufs-fsck/pass3.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Pass 3 of GNU fsck -- Look for disconnected directories - Copyright (C) 1994, 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 "fsck.h" - -void -pass3 () -{ - struct dirinfo *dnp; - int nd; - int change; - - /* Mark all the directories that can be found from the root. */ - - inodestate[ROOTINO] |= DIR_REF; - - do - { - change = 0; - for (nd = 0; nd < dirarrayused; nd++) - { - dnp = dirsorted[nd]; - if (dnp->i_parent - && inodestate[dnp->i_parent] == (DIRECTORY | DIR_REF) - && inodestate[dnp->i_number] == DIRECTORY) - { - inodestate[dnp->i_number] |= DIR_REF; - change = 1; - } - } - } - while (change); - - /* Check for orphaned directories */ - for (nd = 0; nd < dirarrayused; nd++) - { - dnp = dirsorted[nd]; - - if (dnp->i_parent == 0) - { - if (inodestate[dnp->i_number] & DIR_REF) - errexit ("ORPHANED DIR MARKED WITH CONNECT"); - pinode (0, dnp->i_number, "UNREF"); - if ((preen || reply ("RECONNECT")) - && linkup (dnp->i_number, dnp->i_dotdot)) - { - dnp->i_parent = dnp->i_dotdot = lfdir; - pfix ("RECONNECTED"); - } - else - pfail (0); - } - } -} diff --git a/ufs-fsck/pass4.c b/ufs-fsck/pass4.c deleted file mode 100644 index f8fe9814..00000000 --- a/ufs-fsck/pass4.c +++ /dev/null @@ -1,94 +0,0 @@ -/* Pass 4 of GNU fsck -- Check reference counts - Copyright (C) 1994, 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 "fsck.h" - -void -pass4() -{ - ino_t number; - /* True if any reconnect attempt failed, in which case we don't try again. */ - int reconn_failed = 0; - - for (number = ROOTINO; number < maxino; number++) - { - if (linkfound[number] && inodestate[number] != UNALLOC) - { - if (linkcount[number] != linkfound[number]) - { - pinode (0, number, - "LINK COUNT %d SHOULD BE %d IN", - linkcount[number], linkfound[number]); - if (preen || reply ("ADJUST")) - { - struct dinode dino; - getinode (number, &dino); - dino.di_nlink = linkfound[number]; - write_inode (number, &dino); - pfix ("ADJUSTED"); - } - } - } - else if (linkfound[number] && inodestate[number] == UNALLOC) - { - /* This can't happen because we never count links to unallocated - nodes. */ - errexit ("LINK RECORDED FOR UNALLOCATED NODE"); - } - else if (!linkfound[number] && inodestate[number] != UNALLOC) - { - /* No links to allocated node. If the size is zero, then - we want to clear it; if the size is positive, then we - want to reattach in. */ - struct dinode dino; - - pinode (0, number, "UNREF"); - - getinode (number, &dino); - if (dino.di_size && !reconn_failed) - { - /* This can't happen for dirctories because pass 3 should - already have reset them up. */ - if ((DI_MODE (&dino) & IFMT) == IFDIR) - errexit ("NO LINKS TO NONZERO DIRECTORY"); - - if (preen || reply ("RECONNECT")) - reconn_failed = !linkup (number, -1); - if (! reconn_failed) - pfix ("RECONNECTED"); - if (preen && reconn_failed) - pfail ("RECONNECT FAILED"); - } - if (dino.di_size == 0 || reconn_failed) - { - if (reconn_failed && !preen) - /* If preening, the previous call to problem is still active - (more likely the failure was too severe, and exited). */ - problem (0, "RECONNECT FAILED"); - if (preen || reply ("CLEAR")) - { - inodestate[number] = UNALLOC; - clear_inode (number, &dino); - pfix ("CLEARED"); - } - } - } - } -} diff --git a/ufs-fsck/pass5.c b/ufs-fsck/pass5.c deleted file mode 100644 index cb426a7d..00000000 --- a/ufs-fsck/pass5.c +++ /dev/null @@ -1,450 +0,0 @@ -/* Pass 5 of GNU fsck -- check allocation maps and summaries - Copyright (C) 1994,96,2001 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 "fsck.h" - -/* From ../ufs/subr.c: */ - -/* - * Update the frsum fields to reflect addition or deletion - * of some frags. - */ -static void -ffs_fragacct(fs, fragmap, fraglist, cnt) - struct fs *fs; - int fragmap; - long fraglist[]; - int cnt; -{ - int inblk; - register int field, subfield; - register int siz, pos; - - inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; - fragmap <<= 1; - for (siz = 1; siz < fs->fs_frag; siz++) { - if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) - continue; - field = around[siz]; - subfield = inside[siz]; - for (pos = siz; pos <= fs->fs_frag; pos++) { - if ((fragmap & field) == subfield) { - fraglist[siz] += cnt; - pos += siz; - field <<= siz; - subfield <<= siz; - } - field <<= 1; - subfield <<= 1; - } - } -} - -void -pass5 () -{ - struct cg *newcg, *cg; - struct ocg *newocg; - int savednrpos = 0; - struct csum cstotal; - int i, j; - int c; - daddr_t d; - struct csum *sbcsums; - - int basesize; /* size of cg not counting flexibly sized */ - int sumsize; /* size of block totals and pos tbl */ - int mapsize; /* size of inode map + block map */ - - int writesb; - int writecg; - int writecsum; - - writesb = 0; - writecsum = 0; - - cg = alloca (sblock->fs_cgsize); - - newcg = alloca (sblock->fs_cgsize); - newocg = (struct ocg *)newcg; - - sbcsums = alloca (fragroundup (sblock, sblock->fs_cssize)); - - readblock (fsbtodb (sblock, sblock->fs_csaddr), sbcsums, - fragroundup (sblock, sblock->fs_cssize)); - - /* Construct a CG structure; initialize everything that's the same - in each cylinder group. */ - bzero (newcg, sblock->fs_cgsize); - newcg->cg_niblk = sblock->fs_ipg; - switch (sblock->fs_postblformat) - { - case FS_42POSTBLFMT: - /* Initialize size information */ - basesize = (char *)(&newocg->cg_btot[0]) - (char *)(&newocg->cg_link); - sumsize = &newocg->cg_iused[0] - (char *)(&newocg->cg_btot[0]); - mapsize = (&newocg->cg_free[howmany(sblock->fs_fpg, NBBY)] - - (u_char *)&newocg->cg_iused[0]); - savednrpos = sblock->fs_nrpos; - sblock->fs_nrpos = 8; - break; - - case FS_DYNAMICPOSTBLFMT: - /* Set fields unique to new cg structure */ - newcg->cg_btotoff = &newcg->cg_space[0] - (u_char *)(&newcg->cg_link); - newcg->cg_boff = newcg->cg_btotoff + sblock->fs_cpg * sizeof (long); - newcg->cg_iusedoff = newcg->cg_boff + (sblock->fs_cpg - * sblock->fs_nrpos - * sizeof (short)); - newcg->cg_freeoff = newcg->cg_iusedoff + howmany (sblock->fs_ipg, NBBY); - - if (sblock->fs_contigsumsize <= 0) - { - newcg->cg_nextfreeoff = - (newcg->cg_freeoff - + howmany (sblock->fs_cpg * sblock->fs_spc / NSPF (sblock), - NBBY)); - } - else - { - newcg->cg_clustersumoff = - (newcg->cg_freeoff - + howmany (sblock->fs_cpg * sblock->fs_spc / NSPF (sblock), NBBY) - - sizeof (long)); - newcg->cg_clustersumoff = - roundup (newcg->cg_clustersumoff, sizeof (long)); - newcg->cg_clusteroff = - (newcg->cg_clustersumoff - + (sblock->fs_contigsumsize + 1) * sizeof (long)); - newcg->cg_nextfreeoff = - (newcg->cg_clusteroff - + howmany (sblock->fs_cpg * sblock->fs_spc / NSPB (sblock), - NBBY)); - } - - newcg->cg_magic = CG_MAGIC; - - /* Set map sizes */ - basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_link); - sumsize = newcg->cg_iusedoff - newcg->cg_btotoff; - mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff; - break; - - default: - errexit ("UNKNOWN POSTBL FORMAT"); - } - - bzero (&cstotal, sizeof (struct csum)); - - /* Mark fragments past the end of the filesystem as used. */ - j = blknum (sblock, sblock->fs_size + sblock->fs_frag - 1); - for (i = sblock->fs_size; i < j; i++) - setbmap (i); - - /* Now walk through the cylinder groups, checking each one. */ - for (c = 0; c < sblock->fs_ncg; c++) - { - int dbase, dmax; - - /* Read the cylinder group structure */ - readblock (fsbtodb (sblock, cgtod (sblock, c)), cg, sblock->fs_cgsize); - writecg = 0; - - if (!cg_chkmagic (cg)) - warning (1, "CG %d: BAD MAGIC NUMBER", c); - - /* Compute first and last data block addresses in this group */ - dbase = cgbase (sblock, c); - dmax = dbase + sblock->fs_fpg; - if (dmax > sblock->fs_size) - dmax = sblock->fs_size; - - /* Initialize newcg fully; values from cg for those - we can't check. */ - newcg->cg_time = cg->cg_time; - newcg->cg_cgx = c; - if (c == sblock->fs_ncg - 1) - newcg->cg_ncyl = sblock->fs_ncyl % sblock->fs_cpg; - else - newcg->cg_ncyl = sblock->fs_cpg; - newcg->cg_ndblk = dmax - dbase; - if (sblock->fs_contigsumsize > 0) - newcg->cg_nclusterblks = newcg->cg_ndblk / sblock->fs_frag; - newcg->cg_cs.cs_ndir = 0; - newcg->cg_cs.cs_nffree = 0; - newcg->cg_cs.cs_nbfree = 0; - newcg->cg_cs.cs_nifree = sblock->fs_ipg; - - /* Check these for basic viability; if they are wrong - then clear them. */ - newcg->cg_rotor = cg->cg_rotor; - newcg->cg_frotor = cg->cg_frotor; - newcg->cg_irotor = cg->cg_irotor; - if (newcg->cg_rotor > newcg->cg_ndblk) - { - problem (0, "ILLEGAL ROTOR VALUE IN CG %d", c); - if (preen || reply ("FIX")) - { - newcg->cg_rotor = 0; - cg->cg_rotor = 0; - writecg = 1; - pfix ("FIXED"); - } - } - if (newcg->cg_frotor > newcg->cg_ndblk) - { - problem (0, "ILLEGAL FROTOR VALUE IN CG %d", c); - if (preen || reply ("FIX")) - { - newcg->cg_frotor = 0; - cg->cg_frotor = 0; - writecg = 1; - pfix ("FIXED"); - } - } - if (newcg->cg_irotor > newcg->cg_niblk) - { - problem (0, "ILLEGAL IROTOR VALUE IN CG %d", c); - if (preen || reply ("FIX")) - { - newcg->cg_irotor = 0; - cg->cg_irotor = 0; - writecg = 1; - pfix ("FIXED"); - } - } - - /* Zero the block maps and summary areas */ - bzero (&newcg->cg_frsum[0], sizeof newcg->cg_frsum); - bzero (&cg_blktot (newcg)[0], sumsize + mapsize); - if (sblock->fs_postblformat == FS_42POSTBLFMT) - newocg->cg_magic = CG_MAGIC; - - /* Walk through each inode, accounting for it in - the inode map and in newcg->cg_cs. */ - /* In this loop, J is the inode number, and I is the - inode number relative to this CG. */ - j = sblock->fs_ipg * c; - for (i = 0; i < sblock->fs_ipg; j++, i++) - switch (inodestate[j]) - { - case DIRECTORY: - case DIRECTORY | DIR_REF: - case BADDIR: - newcg->cg_cs.cs_ndir++; - /* Fall through... */ - case REG: - newcg->cg_cs.cs_nifree--; - setbit (cg_inosused (newcg), i); - /* Fall through... */ - case UNALLOC: - break; - - default: - errexit ("UNKNOWN STATE I=%d", j); - } - /* Account for inodes 0 and 1 */ - if (c == 0) - for (i = 0; i < ROOTINO; i++) - { - setbit (cg_inosused (newcg), i); - newcg->cg_cs.cs_nifree--; - } - - /* Walk through each data block, accounting for it in - the block map and in newcg->cg_cs. */ - /* In this look, D is the block number and I is the - block number relative to this CG. */ - for (i = 0, d = dbase; - d < dmax; - d += sblock->fs_frag, i += sblock->fs_frag) - { - int frags = 0; - - /* Set each free frag of this block in the block map; - count how many frags were free. */ - for (j = 0; j < sblock->fs_frag; j++) - { - if (testbmap (d + j)) - continue; - setbit (cg_blksfree (newcg), i + j); - frags++; - } - - /* If all the frags were free, then count this as - a free block too. */ - if (frags == sblock->fs_frag) - { - newcg->cg_cs.cs_nbfree++; - j = cbtocylno (sblock, i); - cg_blktot(newcg)[j]++; - cg_blks(sblock, newcg, j)[cbtorpos(sblock, i)]++; - if (sblock->fs_contigsumsize > 0) - setbit (cg_clustersfree (newcg), i / sblock->fs_frag); - } - else if (frags) - { - /* Partial; account for the frags. */ - int blk; - newcg->cg_cs.cs_nffree += frags; - blk = blkmap (sblock, cg_blksfree (newcg), i); - ffs_fragacct (sblock, blk, newcg->cg_frsum, 1); - } - } - - if (sblock->fs_contigsumsize > 0) - { - long *sump = cg_clustersum (newcg); - u_char *mapp = cg_clustersfree (newcg); - int map = *mapp++; - int bit = 1; - int run = 0; - - for (i = 0; i < newcg->cg_nclusterblks; i++) - { - if ((map & bit) != 0) - run++; - else if (run) - { - if (run > sblock->fs_contigsumsize) - run = sblock->fs_contigsumsize; - sump[run]++; - run = 0; - } - - if ((i & (NBBY - 1)) != (NBBY - 1)) - bit <<= 1; - else - { - map = *mapp++; - bit = 1; - } - } - if (run != 0) - { - if (run > sblock->fs_contigsumsize) - run = sblock->fs_contigsumsize; - sump[run]++; - } - } - - /* Add this cylinder group's totals into the superblock's - totals. */ - cstotal.cs_nffree += newcg->cg_cs.cs_nffree; - cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree; - cstotal.cs_nifree += newcg->cg_cs.cs_nifree; - cstotal.cs_ndir += newcg->cg_cs.cs_ndir; - - /* Check counts in superblock */ - if (bcmp (&newcg->cg_cs, &sbcsums[c], sizeof (struct csum))) - { - problem (0, "FREE BLK COUNTS FOR CG %d WRONG IN SUPERBLOCK", c); - if (preen || reply ("FIX")) - { - bcopy (&newcg->cg_cs, &sbcsums[c], sizeof (struct csum)); - writecsum = 1; - pfix ("FIXED"); - } - } - - /* Check inode and block maps */ - if (bcmp (cg_inosused (newcg), cg_inosused (cg), mapsize)) - { - problem (0, "BLKS OR INOS MISSING IN CG %d BIT MAPS", c); - if (preen || reply ("FIX")) - { - bcopy (cg_inosused (newcg), cg_inosused (cg), mapsize); - writecg = 1; - pfix ("FIXED"); - } - } - - if (bcmp (&cg_blktot(newcg)[0], &cg_blktot(cg)[0], sumsize)) - { - problem (0, "SUMMARY INFORMATION FOR CG %d BAD", c); - if (preen || reply ("FIX")) - { - bcopy (&cg_blktot(newcg)[0], &cg_blktot(cg)[0], sumsize); - writecg = 1; - pfix ("FIXED"); - } - } - - if (bcmp (newcg, cg, basesize)) - { - problem (0, "CYLINDER GROUP %d BAD", c); - if (preen || reply ("FIX")) - { - bcopy (newcg, cg, basesize); - writecg = 1; - pfix ("FIXED"); - } - } - - if (writecg) - writeblock (fsbtodb (sblock, cgtod (sblock, c)), - cg, sblock->fs_cgsize); - } - - /* Restore nrpos */ - if (sblock->fs_postblformat == FS_42POSTBLFMT) - sblock->fs_nrpos = savednrpos; - - if (bcmp (&cstotal, &sblock->fs_cstotal, sizeof (struct csum))) - { - problem (0, "TOTAL FREE BLK COUNTS WRONG IN SUPERBLOCK"); - if (preen || reply ("FIX")) - { - bcopy (&cstotal, &sblock->fs_cstotal, sizeof (struct csum)); - sblock->fs_ronly = 0; - sblock->fs_fmod = 0; - writesb = 1; - pfix ("FIXED"); - } - } - - if (sblock->fs_clean == 0 && !fix_denied) - { - problem (0, fsmodified ? "FILESYSTEM MODIFIED" : "FILESYSTEM UNCLEAN"); - if (preen || reply ("MARK CLEAN")) - { - sblock->fs_clean = 1; - writesb = 1; - pfix ("MARKED CLEAN"); - } - } - - if (writesb) - writeblock (SBLOCK, sblock, SBSIZE); - - if (writecsum) - { - const int cssize = fragroundup (sblock, sblock->fs_cssize); - struct csum *test; - - writeblock (fsbtodb (sblock, sblock->fs_csaddr), sbcsums, - fragroundup (sblock, sblock->fs_cssize)); - - test = alloca (cssize); - readblock (fsbtodb (sblock, sblock->fs_csaddr), test, cssize); - if (bcmp (test, sbcsums, cssize)) - warning (0, "CSUM WRITE INCONSISTENT"); - } -} diff --git a/ufs-fsck/setup.c b/ufs-fsck/setup.c deleted file mode 100644 index 9433bd68..00000000 --- a/ufs-fsck/setup.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - Copyright (C) 1994,96,99,2002 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 "fsck.h" -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <error.h> - -static char sblockbuf[SBSIZE]; -struct fs *sblock = (struct fs *)sblockbuf; - -/* A string identifying what we're trying to check. */ -char *device_name = 0; - -daddr_t maxfsblock; -int maxino; -int direct_symlink_extension; - -int newinofmt; - -int readfd, writefd; - -int fix_denied = 0; - -int fsmodified = 0; - -ino_t lfdir; - -/* Get ready to run on device with pathname DEV. */ -int -setup (char *dev) -{ - struct stat st; - int changedsb; - size_t bmapsize; - - device_name = dev; - - if (stat (dev, &st) == -1) - { - error (0, errno, "%s", dev); - return 0; - } - if (!S_ISCHR (st.st_mode) && !S_ISBLK (st.st_mode)) - { - problem (1, "%s is not a character or block device", dev); - if (! reply ("CONTINUE")) - return 0; - } - if (preen == 0) - printf ("** %s", dev); - if (!nowrite) - readfd = open (dev, O_RDWR); - if (nowrite || readfd == -1) - { - readfd = open (dev, O_RDONLY); - if (readfd == -1) - { - error (0, errno, "%s", dev); - return 0; - } - writefd = -1; - nowrite = 1; - if (preen) - warning (1, "NO WRITE ACCESS"); - printf (" (NO WRITE)"); - } - else - writefd = readfd; - - if (preen == 0) - printf ("\n"); - - lfdir = 0; - - /* We don't do the alternate superblock stuff here (yet). */ - readblock (SBLOCK, sblock, SBSIZE); - changedsb = 0; - - if (sblock->fs_magic != FS_MAGIC) - { - warning (1, "BAD MAGIC NUMBER"); - return 0; - } - if (sblock->fs_ncg < 1) - { - warning (1, "NCG OUT OF RANGE"); - return 0; - } - if (sblock->fs_cpg < 1) - { - warning (1, "CPG OUT OF RANGE"); - return 0; - } - if (sblock->fs_ncg * sblock->fs_cpg < sblock->fs_ncyl - || (sblock->fs_ncg - 1) * sblock->fs_cpg >= sblock->fs_ncyl) - { - warning (1, "NCYL INCONSISTENT WITH NCG AND CPG"); - return 0; - } - if (sblock->fs_sbsize > SBSIZE) - { - warning (1, "SBLOCK SIZE PREPONTEROUSLY LARGE"); - return 0; - } - if (sblock->fs_optim != FS_OPTTIME && sblock->fs_optim != FS_OPTSPACE) - { - problem (1, "UNDEFINED OPTIMIZATION IN SUPERBLOCK"); - if (reply ("SET TO DEFAULT")) - { - sblock->fs_optim = FS_OPTTIME; - changedsb = 1; - } - } - if (sblock->fs_minfree < 0 || sblock->fs_minfree > 99) - { - problem (0, "IMPOSSIBLE MINFREE=%ld IN SUPERBLOCK", sblock->fs_minfree); - if (preen || reply ("SET TO DEFAULT")) - { - sblock->fs_minfree = 10; - changedsb = 1; - pfix ("SET TO DEFAULT"); - } - } - if (sblock->fs_interleave < 1 - || sblock->fs_interleave > sblock->fs_nsect) - { - problem (0, "IMPOSSIBLE INTERLEAVE=%ld IN SUPERBLOCK", - sblock->fs_interleave); - if (preen || reply ("SET TO DEFAULT")) - { - sblock->fs_interleave = 1; - changedsb = 1; - pfix ("SET TO DEFAULT"); - } - } - if (sblock->fs_npsect < sblock->fs_nsect - || sblock->fs_npsect > sblock->fs_nsect * 2) - { - problem (0, "IMPOSSIBLE NPSECT=%ld IN SUPERBLOCK", sblock->fs_npsect); - if (preen || reply ("SET TO DEFAULT")) - { - sblock->fs_npsect = sblock->fs_nsect; - changedsb = 1; - pfix ("SET TO DEFAULT"); - } - } - if (sblock->fs_inodefmt >= FS_44INODEFMT) - newinofmt = 1; - else - { - sblock->fs_qbmask = ~sblock->fs_bmask; - sblock->fs_qfmask = ~sblock->fs_fmask; - newinofmt = 0; - } - - if (changedsb) - writeblock (SBLOCK, sblock, SBSIZE); - - /* Constants */ - maxfsblock = sblock->fs_size; - maxino = sblock->fs_ncg * sblock->fs_ipg; - direct_symlink_extension = sblock->fs_maxsymlinklen > 0; - - /* Allocate and initialize maps */ - bmapsize = roundup (howmany (maxfsblock, NBBY), sizeof (short)); - blockmap = calloc (bmapsize, sizeof (char)); - inodestate = calloc (maxino + 1, sizeof (char)); - typemap = calloc (maxino + 1, sizeof (char)); - linkcount = calloc (maxino + 1, sizeof (nlink_t)); - linkfound = calloc (maxino + 1, sizeof (nlink_t)); - return 1; -} diff --git a/ufs-fsck/utilities.c b/ufs-fsck/utilities.c deleted file mode 100644 index 14705f84..00000000 --- a/ufs-fsck/utilities.c +++ /dev/null @@ -1,455 +0,0 @@ -/* Miscellaneous functions for fsck - Copyright (C) 1994,95,96,99,2001,02 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 "fsck.h" -#include <fcntl.h> -#include <sys/file.h> -#include <unistd.h> -#include <stdarg.h> -#include <pwd.h> -#include <error.h> -#include <time.h> - -static void retch (char *reason); - -/* Read disk block ADDR into BUF of SIZE bytes. */ -void -readblock (daddr_t addr, void *buf, size_t size) -{ - if (lseek (readfd, addr * DEV_BSIZE, L_SET) == -1) - errexit ("CANNOT SEEK TO BLOCK %ld", addr); - if (read (readfd, buf, size) != size) - errexit ("CANNOT READ BLOCK %ld", addr); -} - -/* Write disk block BLKNO from BUF of SIZE bytes. */ -void -writeblock (daddr_t addr, void *buf, size_t size) -{ - if (lseek (writefd, addr * DEV_BSIZE, L_SET) == -1) - errexit ("CANNOT SEEK TO BLOCK %ld", addr); - if (write (writefd, buf, size) != size) - errexit ("CANNOT WRITE BLOCK %ld", addr); - fsmodified = 1; -} - -/* Last filesystem fragment that we read an inode from */ -static char *lastifrag; -static daddr_t lastifragaddr; - -/* Read inode number INO into DINODE. */ -void -getinode (ino_t ino, struct dinode *di) -{ - daddr_t iblk; - - if (!lastifrag) - lastifrag = malloc (sblock->fs_bsize); - - iblk = ino_to_fsba (sblock, ino); - if (iblk != lastifragaddr) - readblock (fsbtodb (sblock, iblk), lastifrag, sblock->fs_bsize); - lastifragaddr = iblk; - bcopy (lastifrag + ino_to_fsbo (sblock, ino) * sizeof (struct dinode), - di, sizeof (struct dinode)); -} - -/* Write inode number INO from DINODE. */ -void -write_inode (ino_t ino, struct dinode *di) -{ - daddr_t iblk; - - iblk = ino_to_fsba (sblock, ino); - if (iblk != lastifragaddr) - readblock (fsbtodb (sblock, iblk), lastifrag, sblock->fs_bsize); - lastifragaddr = iblk; - bcopy (di, lastifrag + ino_to_fsbo (sblock, ino) * sizeof (struct dinode), - sizeof (struct dinode)); - writeblock (fsbtodb (sblock, iblk), lastifrag, sblock->fs_bsize); -} - -/* Clear inode number INO and zero DI. */ -void -clear_inode (ino_t ino, struct dinode *di) -{ - bzero (di, sizeof (struct dinode)); - write_inode (ino, di); -} - -/* Allocate and return a block and account for it in all the block - maps locally. Don't trust or change the disk block maps. - The block should be NFRAGS fragments long. */ -daddr_t -allocblk (int nfrags) -{ - daddr_t i; - int j, k; - - if (nfrags <= 0 || nfrags > sblock->fs_frag) - return 0; - - /* Examine each block of the filesystem. */ - for (i = 0; i < maxfsblock - sblock->fs_frag; i += sblock->fs_frag) - { - /* For each piece of the block big enough to hold this frag... */ - for (j = 0; j <= sblock->fs_frag - nfrags; j++) - { - /* For each frag of this piece... */ - for (k = 0; k < nfrags; k++) - if (testbmap (i + j + k)) - break; - - /* If one of the frags was allocated... */ - if (k < nfrags) - { - /* Skip at least that far (short cut) */ - j += k; - continue; - } - - /* It's free (at address i + j) */ - - /* Mark the frags allocated in our map */ - for (k = 0; k < nfrags; k++) - setbmap (i + j + k); - - return (i + j); - } - } - return 0; -} - -/* Check if a block starting at BLK and extending for CNT - fragments is out of range; if it is, then return 1; otherwise return 0. */ -int -check_range (daddr_t blk, int cnt) -{ - int c; - - if ((unsigned)(blk + cnt) > maxfsblock) - return 1; - - c = dtog (sblock, blk); - if (blk < cgdmin (sblock, c)) - { - if (blk + cnt > cgsblock (sblock, c)) - return 1; - } - else - { - if (blk + cnt > cgbase (sblock, c + 1)) - return 1; - } - - return 0; -} - -struct problem { - char *desc; - struct problem *prev; -}; - -/* A queue of problems found by fsck that are waiting resolution. The front - of the list is the most recent problem found (and presumably since - previous problems haven't been resolved yet, they depend on this one being - solved for their resolution). */ -static struct problem *problems = 0; - -static struct problem *free_problems = 0; - -static void -push_problem (char *fmt, va_list args) -{ - struct problem *prob = free_problems; - - if (! prob) - prob = malloc (sizeof (struct problem)); - else - problems = prob->prev; - if (! prob) - retch ("malloc failed"); - - if (vasprintf (&prob->desc, fmt, args) < 0) - retch ("vasprintf failed"); - - prob->prev = problems; - problems = prob; -} - -/* Print the most recent problem, and perhaps how it was resolved. */ -static void -resolve_problem (char *fix) -{ - struct problem *prob = problems; - - if (! prob) - retch ("no more problems"); - - problems = prob->prev; - prob->prev = free_problems; - - if (preen && device_name) - printf ("%s: %s", device_name, prob->desc); - else - printf ("%s", prob->desc); - if (fix) - printf (" (%s)\n", fix); - else - putchar ('\n'); - free (prob->desc); -} - -/* Retire all problems as if they failed. We print them in chronological - order rather than lifo order, as this is a bit clearer, and we can do it - when we know they're all going to fail. */ -static void -flush_problems () -{ - struct problem *fail (struct problem *prob) - { - struct problem *last = prob->prev ? fail (prob->prev) : prob; - if (preen && device_name) - printf ("%s: %s\n", device_name, prob->desc); - else - puts (prob->desc); - free (prob->desc); - return last; - } - if (problems) - { - fail (problems)->prev = free_problems; - free_problems = problems; - } -} - -/* Like printf, but exit after printing. */ -void -errexit (char *fmt, ...) -{ - va_list args; - - flush_problems (); - - if (preen && device_name) - printf ("%s: ", device_name); - - va_start (args, fmt); - vprintf (fmt, args); - va_end (args); - putchar ('\n'); - - exit (8); -} - -static void -retch (char *reason) -{ - flush_problems (); - error (99, 0, "(internal error) %s!", reason); -} - -/* Prints all unresolved problems and exits, printing MSG as well. */ -static void -punt (char *msg) -{ - problem (0, "%s", msg); - flush_problems (); - exit (8); -} - -/* If SEVERE is true, and we're in preen mode, then things are too hair to - fix automatically, so tell the user to do it himself and punt. */ -static void -no_preen (int severe) -{ - if (severe && preen) - punt ("PLEASE RUN fsck MANUALLY"); -} - -/* Store away the given message about a problem found. A call to problem must - be matched later with a call to pfix, pfail, or reply; to print more - in the same message, intervening calls to pextend can be used. If SEVERE is - true, and we're in preen mode, then the program is terminated. */ -void -problem (int severe, char *fmt, ...) -{ - va_list args; - - va_start (args, fmt); - push_problem (fmt, args); - va_end (args); - - no_preen (severe); -} - -/* Following a call to problem (with perhaps intervening calls to - pmore), appends the given message to that message. */ -void -pextend (char *fmt, ...) -{ - va_list args; - char *more, *concat; - struct problem *prob = problems; - - if (! prob) - retch ("No pending problem to add to"); - - va_start (args, fmt); - if (vasprintf (&more, fmt, args) < 0) - retch ("vasprintf failed"); - va_end (args); - - concat = realloc (prob->desc, strlen (prob->desc) + 1 + strlen (more) + 1); - if (! concat) - retch ("realloc failed"); - - strcpy (concat + strlen (concat), more); - prob->desc = concat; - free (more); -} - -/* Like problem, but as if immediately followed by pfail. */ -void -warning (int severe, char *fmt, ...) -{ - va_list args; - - va_start (args, fmt); - push_problem (fmt, args); - va_end (args); - - no_preen (severe); - - resolve_problem (0); -} - -/* Like problem, but appends a helpful description of the given inode number to - the message. */ -void -pinode (int severe, ino_t ino, char *fmt, ...) -{ - if (fmt) - { - va_list args; - va_start (args, fmt); - push_problem (fmt, args); - va_end (args); - } - - if (ino < ROOTINO || ino > maxino) - pextend (" (BOGUS INODE) I=%Ld", ino); - else - { - char *p; - struct dinode dino; - struct passwd *pw; - - getinode (ino, &dino); - - pextend (" %s I=%Ld", (DI_MODE (&dino) & IFMT) == IFDIR ? "DIR" : "FILE", - ino); - - pw = getpwuid (dino.di_uid); - if (pw) - pextend (" O=%s", pw->pw_name); - else - pextend (" O=%lu", dino.di_uid); - - pextend (" M=0%o", DI_MODE (&dino)); - pextend (" SZ=%llu", dino.di_size); - p = ctime (&dino.di_mtime.tv_sec); - pextend (" MT=%12.12s %4.4s", &p[4], &p[20]); - } - - no_preen (severe); -} - -/* Print a successful resolution to a pending problem. Must follow a call to - problem or pextend. */ -void -pfix (char *fix) -{ - if (preen) - resolve_problem (fix ?: "FIXED"); -} - -/* Print an unsuccessful resolution to a pending problem. Must follow a call - to problem or pextend. */ -void -pfail (char *failure) -{ - if (preen) - resolve_problem (failure); -} - -/* Ask the user a question; return 1 if the user says yes, and 0 - if the user says no. This call must follow a call to problem or pextend, - which it completes. */ -int -reply (char *question) -{ - int persevere; - char c; - - if (preen) - retch ("Got to reply() in preen mode"); - - /* Emit the problem to which the question pertains. */ - resolve_problem (0); - - persevere = !strcmp (question, "CONTINUE"); - - if (!persevere && (nowrite || writefd < 0)) - { - fix_denied = 1; - printf ("%s? no\n\n", question); - return 0; - } - else if (noquery || (persevere && nowrite)) - { - printf ("%s? yes\n\n", question); - return 1; - } - else - { - do - { - printf ("%s? [yn] ", question); - fflush (stdout); - c = getchar (); - while (c != '\n' && getchar () != '\n') - if (feof (stdin)) - { - fix_denied = 1; - return 0; - } - } - while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); - putchar ('\n'); - if (c == 'y' || c == 'Y') - return 1; - else - { - fix_denied = 1; - return 0; - } - } -} diff --git a/ufs-utils/Makefile b/ufs-utils/Makefile deleted file mode 100644 index df22440e..00000000 --- a/ufs-utils/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright (C) 1994, 1996, 2008 Free Software Foundation -# 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. - -dir := ufs-utils -makemode := utilities - -targets = mkfs.ufs clri.ufs stati.ufs -target-suffix = .ufs -SRCS = mkfs.c clri.c stati.c dlabel.c -installationdir = $(sbindir) - -OBJS = $(SRCS:.c=.o) -HURDLIBS = store shouldbeinlibc - -include ../Makeconf - -mkfs.ufs: mkfs.o dlabel.o ../libstore/libstore.a ../libshouldbeinlibc/libshouldbeinlibc.a - -$(targets): %.ufs: %.o - - diff --git a/ufs-utils/clri.c b/ufs-utils/clri.c deleted file mode 100644 index 1ad348a1..00000000 --- a/ufs-utils/clri.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Rich $alz of BBN Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char copyright[] = -"@(#) Copyright (c) 1990, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; - -static char copyright[] __attribute__ ((unused)); -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)clri.c 8.2 (Berkeley) 9/23/93"; -static char sccsid[] __attribute__ ((unused)); -#endif /* not lint */ - -/* Modified by Michael I. Bushnell for GNU Hurd. */ - -#include <sys/param.h> -#include <sys/time.h> - -#include "../ufs/dinode.h" -#include "../ufs/fs.h" - - - -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <unistd.h> - -#define MAXPHYS (64 * 1024) -#define DEV_BSIZE 512 - - -int -main(argc, argv) - int argc; - char *argv[]; -{ - register struct fs *sbp; - register struct dinode *ip; - register int fd; - struct dinode ibuf[MAXBSIZE / sizeof (struct dinode)]; - long generation, bsize; - off_t offset; - int inonum; - char *fs, sblock[SBSIZE]; - - if (argc < 3) { - (void)fprintf(stderr, "usage: clri filesystem inode ...\n"); - exit(1); - } - - fs = *++argv; - - /* get the superblock. */ - if ((fd = open(fs, O_RDWR, 0)) < 0) - { - perror (fs); - exit (1); - } - if (lseek(fd, (off_t)(SBLOCK * DEV_BSIZE), SEEK_SET) < 0) - { - perror (fs); - exit (1); - } - if (read(fd, sblock, sizeof(sblock)) != sizeof(sblock)) { - (void)fprintf(stderr, - "clri: %s: can't read the superblock.\n", fs); - exit(1); - } - - sbp = (struct fs *)sblock; - if (sbp->fs_magic != FS_MAGIC) { - (void)fprintf(stderr, - "clri: %s: superblock magic number 0x%lux, not 0x%x.\n", - fs, sbp->fs_magic, FS_MAGIC); - exit(1); - } - bsize = sbp->fs_bsize; - - /* remaining arguments are inode numbers. */ - while (*++argv) { - /* get the inode number. */ - if ((inonum = atoi(*argv)) <= 0) { - (void)fprintf(stderr, - "clri: %s is not a valid inode number.\n", *argv); - exit(1); - } - (void)printf("clearing %d\n", inonum); - - /* read in the appropriate block. */ - offset = ino_to_fsba(sbp, inonum); /* inode to fs blk */ - offset = fsbtodb(sbp, offset); /* fs blk disk blk */ - offset *= DEV_BSIZE; /* disk blk to bytes */ - - /* seek and read the block */ - if (lseek(fd, offset, SEEK_SET) < 0) - { - perror (fs); - exit (1); - } - if (read(fd, ibuf, bsize) != bsize) - { - perror (fs); - exit (1); - } - - /* get the inode within the block. */ - ip = &ibuf[ino_to_fsbo(sbp, inonum)]; - - /* clear the inode, and bump the generation count. */ - generation = ip->di_gen + 1; - memset(ip, 0, sizeof(*ip)); - ip->di_gen = generation; - - /* backup and write the block */ - if (lseek(fd, (off_t)-bsize, SEEK_CUR) < 0) - { - perror (fs); - exit (1); - } - if (write(fd, ibuf, bsize) != bsize) - { - perror (fs); - exit (1); - } - (void)fsync(fd); - } - (void)close(fd); - exit(0); -} diff --git a/ufs-utils/dlabel.c b/ufs-utils/dlabel.c deleted file mode 100644 index 355cb3f6..00000000 --- a/ufs-utils/dlabel.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Get the disklabel from a device node - - Copyright (C) 1996,99,2001 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.org> - - 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 <hurd.h> -#include <mach.h> -#include <string.h> -#include <device/device.h> -#include <device/disk_status.h> -#include <hurd/store.h> - -/* XXX Ick. */ -#define IOCPARM_MASK 0x1fff/* parameter length, at most 13 bits */ -#define IOC_OUT 0x40000000/* copy out parameters */ -#define _IOC(inout,group,num,len) \ - (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num)) -#define _IOR(g,n,t) _IOC(IOC_OUT,(g), (n), sizeof(t)) - -static error_t -fd_get_device (int fd, device_t *device) -{ - error_t err; - struct store *store; - file_t node = getdport (fd); - - if (node == MACH_PORT_NULL) - return errno; - - err = store_create (node, 0, 0, &store); /* consumes NODE on success */ - if (! err) - { - if (store->class->id != STORAGE_DEVICE - /* In addition to requiring a device, we also want the *whole* - device -- one contiguous run starting at 0. */ - || store->num_runs != 1 - || store->runs[0].start != 0) - err = ENODEV; - else if (store->port == MACH_PORT_NULL) - /* Usually getting a null port back means we didn't have sufficient - privileges. */ - err = EPERM; - else - { - *device = store->port; - store->port = MACH_PORT_NULL; /* Steal the port from STORE! */ - } - store_free (store); - } - else - mach_port_deallocate (mach_task_self (), node); - - return err; -} - -error_t -fd_get_disklabel (int fd, struct disklabel *label) -{ - device_t device; - error_t err = fd_get_device (fd, &device); - - if (! err) - { - mach_msg_type_number_t label_len = sizeof *label / sizeof (integer_t); - - err = device_get_status (device, DIOCGDINFO, - (dev_status_t)label, &label_len); - if (!err && label_len != sizeof *label / sizeof (integer_t)) - err = ERANGE; - - mach_port_deallocate (mach_task_self (), device); - } - - return err; -} diff --git a/ufs-utils/mkfs.c b/ufs-utils/mkfs.c deleted file mode 100644 index aef3ea92..00000000 --- a/ufs-utils/mkfs.c +++ /dev/null @@ -1,1406 +0,0 @@ -/* - * Copyright (c) 1980, 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)mkfs.c 8.3 (Berkeley) 2/3/94";*/ -static char *rcsid = "$Id: mkfs.c,v 1.22 2006/03/14 23:27:50 tschwinge Exp $"; -#endif /* not lint */ - -#include <unistd.h> -#include <stddef.h> -#include <stdlib.h> -#include <argp.h> -#include <assert.h> -#include <error.h> -#include <string.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/wait.h> -#include <sys/resource.h> -#include "../ufs/dinode.h" -#include "../ufs/dir.h" -#include "../ufs/fs.h" -/* #include <sys/disklabel.h> */ -#include <sys/stat.h> -#include <fcntl.h> -#include <dirent.h> -#include <version.h> - -#include <device/device_types.h> -#include <device/disk_status.h> - -#include <hurd.h> - -/* Begin misc additions for GNU Hurd */ - -/* For GNU Hurd: the ufs DIRSIZ macro is different than the BSD - 4.4 version that mkfs expects. So we provide here the BSD version. */ -#undef DIRSIZ -#if (BYTE_ORDER == LITTLE_ENDIAN) -#define DIRSIZ(oldfmt, dp) \ - ((oldfmt) ? \ - ((sizeof (struct directory_entry) - (MAXNAMLEN+1)) + (((dp)->d_type+1 + 3) &~ 3)) : \ - ((sizeof (struct directory_entry) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))) -#else -#define DIRSIZ(oldfmt, dp) \ - ((sizeof (struct directory_entry) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) -#endif - -#define MAXPHYS (64 * 1024) - -/* Provide mode from struct dinode * */ -#define DI_MODE(dp) (((dp)->di_modeh << 16) | (dp)->di_model) - -#define DEV_BSIZE 512 - -#define btodb(bytes) ((bytes) / DEV_BSIZE) - -/* End additions for GNU Hurd */ - -#ifndef STANDALONE -#include <a.out.h> -#include <stdio.h> -#include <time.h> -#endif - -/* - * make file system for cylinder-group style file systems - */ - -extern error_t fd_get_disklabel (int fd, struct disklabel *lab); -static void mkfs (), initcg (), fsinit (), setblock (); -static void iput (), rdfs (), clrblock (), wtfs (); -static int makedir (), isblock (); - -/* - * We limit the size of the inode map to be no more than a - * third of the cylinder group space, since we must leave at - * least an equal amount of space for the block map. - * - * N.B.: MAXIPG must be a multiple of INOPB(fs). - */ -#define MAXIPG(fs) roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs)) - -#define UMASK 0755 -#define MAXINOPB (MAXBSIZE / sizeof(struct dinode)) -#define POWEROF2(num) (((num) & ((num) - 1)) == 0) - -/* - * variables set up by front end. - */ -#define extern -extern int Nflag; /* run mkfs without writing file system */ -extern int Oflag; /* format as an 4.3BSD file system */ -extern int fssize; /* file system size */ -extern int ntracks; /* # tracks/cylinder */ -extern int nsectors; /* # sectors/track */ -extern int nphyssectors; /* # sectors/track including spares */ -extern int secpercyl; /* sectors per cylinder */ -extern int sectorsize; /* bytes/sector */ -extern int rpm; /* revolutions/minute of drive */ -extern int interleave; /* hardware sector interleave */ -extern int trackskew; /* sector 0 skew, per track */ -extern int headswitch; /* head switch time, usec */ -extern int trackseek; /* track-to-track seek, usec */ -extern int fsize; /* fragment size */ -extern int bsize; /* block size */ -extern int cpg; /* cylinders/cylinder group */ -extern int cpgflg; /* cylinders/cylinder group flag was given */ -extern int minfree; /* free space threshold */ -extern int opt; /* optimization preference (space or time) */ -extern int density; /* number of bytes per inode */ -extern int maxcontig; /* max contiguous blocks to allocate */ -extern int rotdelay; /* rotational delay between blocks */ -extern int maxbpg; /* maximum blocks per file in a cyl group */ -extern int nrpos; /* # of distinguished rotational positions */ -extern int bbsize; /* boot block size */ -extern int sbsize; /* superblock size */ -#undef extern - -union { - struct fs fs; - char pad[SBSIZE]; -} fsun; -#define sblock fsun.fs -struct csum *fscs; - -union { - struct cg cg; - char pad[MAXBSIZE]; -} cgun; -#define acg cgun.cg - -struct dinode zino[MAXBSIZE / sizeof(struct dinode)]; - -int fsi, fso; -daddr_t alloc(); - -const char *argp_program_version = STANDARD_HURD_VERSION (mkfs.ufs); - -#define _STRINGIFY(arg) #arg -#define STRINGIFY(arg) _STRINGIFY (arg) - -static const struct argp_option options[] = { - {0,0,0,0,0, 1}, - {"just-print", 'N', 0, 0, - "Just print the file system parameters that would be used"}, - {"old-format", 'O', 0, 0, "Create a 4.3BSD format filesystem"}, - {"max-contig", 'a', "BLOCKS", 0, - "The maximum number of contiguous blocks that will be laid out before" - " forcing a rotational delay; the default is no limit"}, - {"block-size", 'b', "BYTES", 0, "The block size of the file system"}, - {"group-cylinders", 'c', "N", 0, - "The number of cylinders per cylinder group; the default 16"}, - {"rot-delay", 'd', "MSEC", 0, - "The expected time to service a transfer completion interrupt and" - " initiate a new transfer on the same disk; the default is 0"}, - {"max-bpg", 'e', "BLOCKS", 0, - "Maximum number of blocks any single file can allocate out of a cylinder" - " group before it is forced to begin allocating blocks from another" - " cylinder group; the default is about one quarter of the total blocks" - " in a cylinder group"}, - {"frag-size", 'f', "BYTES", 0, "The fragment size"}, - {"inode-density", 'i', "BYTES", 0, - "The density of inodes in the file system, in bytes of data space per" - " inode; the default is one inode per 4 filesystem frags"}, - {"minfree", 'm', "PERCENT", 0, - "The percentage of space reserved from normal users; the default is " - STRINGIFY (MINFREE) "%"}, - {"rot-positions", 'n', "N", 0, - "The number of distinct rotational positions; the default is 8"}, - {"optimization", 'o', "METH", 0, "``space'' or ``time''"}, - {"size", 's', "SECTORS", 0, "The size of the file system"}, - - {0,0,0,0, - "The following options override the standard sizes for the disk" - " geometry; their default values are taken from the disk label:", 2}, - - {"sector-size", 'S', "BYTES", 0, "The size of a sector (usually 512)"}, - {"skew", 'k', "SECTORS", 0, "Sector 0 skew, per track"}, - {"interleave", 'l', "LOG-PHYS-RATIO", 0, "Hardware sector interleave"}, - {"rpm", 'r', "RPM", 0, "The speed of the disk in revolutions per minute"}, - {"tracks", 't', "N", 0, "The number of tracks/cylinder"}, - {"sectors", 'u', "N", 0, - "The number of sectors per track (does not include sectors reserved for" - " bad block replacement"}, - {"spare-sectors", 'p', "N", 0, - "Spare sectors (for bad sector replacement) at the end of each track"}, - {"cyl-spare-sectors", 'x', "N", 0, - "Spare sectors (for bad sector replacement) at the end of the last track" - " in each cylinder"}, - {0, 0} -}; -static char *args_doc = "DEVICE"; -static char *doc = "Write a ufs filesystem image onto DEVICE."; - -struct amark { void *addr; struct amark *next; }; - -static void -amarks_add (struct amark **amarks, void *addr) - { - struct amark *up = malloc (sizeof (struct amark)); - assert (up != 0); - up->addr = addr; - up->next = *amarks; - *amarks = up; - } -static int -amarks_contains (struct amark *amarks, void *addr) - { - while (amarks) - if (amarks->addr == addr) - return 1; - else - amarks = amarks->next; - return 0; - } - -static const struct disklabel default_disklabel = { - d_rpm: 3600, - d_interleave: 1, - d_secsize: DEV_BSIZE, - d_sparespertrack: 0, - d_sparespercyl: 0, - d_trackskew: 0, - d_cylskew: 0, - d_headswitch: 0, - d_trkseek: 0, -}; - -char *device = 0; - -#define deverr(code, err, fmt, args...) \ - error (code, err, "%s: " fmt, device , ##args) - -int -main (int argc, char **argv) -{ - int fdo, fdi; - struct amark *uparams = 0; - error_t label_err = 0; - struct disklabel label_buf, *label = 0; - int nspares = 0, ncspares = 0; - - /* Parse our options... */ - error_t parse_opt (int key, char *arg, struct argp_state *state) - { - switch (key) - { - case 'N': Nflag = 1; break; - case 'O': Oflag = 1; break; - -/* Mark &VAR as being a uparam, and set VAR. */ -#define UP_INT(var) { amarks_add (&uparams, &var); var = atoi (arg); } - - case 'a': UP_INT (maxcontig); break; - case 'b': UP_INT (bsize); break; - case 'c': UP_INT (cpg); cpgflg = 1; break; - case 'd': UP_INT (rotdelay); break; - case 'e': UP_INT (maxbpg); break; - case 'f': UP_INT (fsize); break; - case 'i': UP_INT (density); break; - case 'm': UP_INT (minfree); break; - case 'n': UP_INT (nrpos); break; - case 's': UP_INT (fssize); break; - case 'S': UP_INT (sectorsize); break; - case 'k': UP_INT (trackskew); break; - case 'l': UP_INT (interleave); break; - case 'r': UP_INT (rpm); break; - case 't': UP_INT (ntracks); break; - case 'u': UP_INT (nsectors); break; - case 'p': UP_INT (nspares); break; - case 'x': UP_INT (ncspares); break; - - case 'o': - amarks_add (&uparams, &opt); - if (strcmp (arg, "time") == 0) - opt = FS_OPTTIME; - else if (strcmp (arg, "space") == 0) - opt = FS_OPTSPACE; - else - argp_error (state, "%s: Invalid value for --optimization", arg); - break; - - case ARGP_KEY_ARG: - if (state->arg_num > 0) - return ARGP_ERR_UNKNOWN; - device = arg; - break; - - default: - return ARGP_ERR_UNKNOWN; - } - return 0; - } - const struct argp argp = { options, parse_opt, args_doc, doc }; - - /* Tries to get the disklabel for DEVICE; if it can't, then if PARAM_NAME - is 0, returns 0, otherwise an error is printed (using PARAM_NAME) and - the program exits. */ - struct disklabel *dl (char *param_name) - { - if (! label) - { - if (! label_err) - { - label_err = fd_get_disklabel (fdi, &label_buf); - if (! label_err) - label = &label_buf; - } - if (label_err && param_name) - error (9, label_err, - "%s: Can't get disklabel; please specify --%s", - device, param_name); - } - return label; - } - /* Tries to get the integer field at offset OFFS from the disklabel for - DEVICE; if it can't, then if PARAM_NAME is 0, returns the corresponding - value from DEFAULT_DISKLABEL, otherwise an error is printed and the - program exits. */ - int dl_int (char *param_name, size_t offs) - { - struct disklabel *l = dl (param_name); - return *(int *)((char *)(l ?: &default_disklabel) + offs); - } - /* A version of dl_int that takes the field name instead of an offset. */ -#define DL_INT(param_name, field) \ - dl_int (param_name, offsetof (struct disklabel, field)) - - /* Like dl_int, but adjust for any difference in sector size between the - disklabel and SECTORSIZE. */ - int dl_secs (char *param_name, size_t offs) - { - int val = dl_int (param_name, offs); - int dl_ss = DL_INT (0, d_secsize); - if (sectorsize < dl_ss) - deverr (10, 0, - "%d: Sector size is less than device sector size (%d)", - sectorsize, dl_ss); - else if (sectorsize > dl_ss) - if (sectorsize % dl_ss != 0) - deverr (11, 0, - "%d: Sector size not a multiple of device sector size (%d)", - sectorsize, dl_ss); - else - val /= sectorsize / dl_ss; - return val; - } - /* A version of dl_secs that takes the field name instead of an offset. */ -#define DL_SECS(param_name, field) \ - dl_secs (param_name, offsetof (struct disklabel, field)) - - /* Parse our arguments. */ - argp_parse (&argp, argc, argv, 0, 0, 0); - - fdi = open (device, O_RDONLY); - if (fdi == -1) - error (2, errno, "%s", device); - fdo = open (device, O_WRONLY); - if (fdo == -1) - error (3, errno, "%s", device); - - /* If VAR hasn't been set by the user, set it to DEF_VAL. */ -#define DEFAULT(var, def_val) \ - (amarks_contains (uparams, &var) ? 0 : (((var) = (def_val)), 0)) - - DEFAULT (sectorsize, DEV_BSIZE); - DEFAULT (fssize, - ({ struct stat st; - if (fstat (fdi, &st) == -1) - deverr (4, errno, "Cannot get size"); - st.st_size / sectorsize; })); - DEFAULT (ntracks, DL_INT ("tracks", d_ntracks)); - DEFAULT (nsectors, DL_SECS ("sectors", d_nsectors)); - DEFAULT (nspares, DL_SECS (0, d_sparespertrack)); - DEFAULT (ncspares, DL_SECS (0, d_sparespercyl)); - - if (nspares >= nsectors) - deverr (5, 0, "%d: Too many spare sectors per track", nspares); - if (ncspares >= nsectors) - deverr (5, 0, "%d: Too many spare sectors per cylinder", ncspares); - nphyssectors = nsectors + nspares; - - secpercyl = nsectors * ntracks; - - DEFAULT (rpm, DL_INT (0, d_rpm)); - DEFAULT (interleave, DL_INT (0, d_interleave)); - DEFAULT (trackskew, DL_SECS (0, d_trackskew)); - DEFAULT (headswitch, DL_INT (0, d_headswitch)); - DEFAULT (trackseek, DL_INT (0, d_trkseek)); - - DEFAULT (fsize, 1024); - DEFAULT (bsize, 8192); - - DEFAULT (cpg, 16); - DEFAULT (minfree, MINFREE); - DEFAULT (opt, DEFAULTOPT); - DEFAULT (density, 4 * fsize); -/* maxcontig = MAX (1, MIN (MAXPHYS, MAXBSIZE) / bsize - 1); */ - DEFAULT (maxcontig, 0); - DEFAULT (rotdelay, 4); -#define MAXBLKPG(bsize) ((bsize) / sizeof(daddr_t)) - DEFAULT (maxbpg, MAXBLKPG (bsize)); - DEFAULT (nrpos, 8); - - bbsize = BBSIZE; - sbsize = SBSIZE; - - mkfs (0, device, fdi, fdo); - - return 0; -} - -void -mkfs(pp, fsys, fi, fo) - struct partition *pp; - char *fsys; - int fi, fo; -{ - register long i, mincpc, mincpg, inospercg; - long cylno, rpos, blk, j, warn = 0; - long used, mincpgcnt, bpcg; - long mapcramped, inodecramped; - long postblsize, rotblsize, totalsbsize; - time_t utime; - quad_t sizepb; - -#ifndef STANDALONE - time(&utime); -#endif - fsi = fi; - fso = fo; - if (Oflag) { - sblock.fs_inodefmt = FS_42INODEFMT; - sblock.fs_maxsymlinklen = 0; - } else { - sblock.fs_inodefmt = FS_44INODEFMT; - sblock.fs_maxsymlinklen = MAXSYMLINKLEN; - } - /* - * Validate the given file system size. - * Verify that its last block can actually be accessed. - */ - if (fssize <= 0) - deverr (13, 0, "preposterous size %d", fssize); - wtfs(fssize - 1, sectorsize, (char *)&sblock); - /* - * collect and verify the sector and track info - */ - sblock.fs_nsect = nsectors; - sblock.fs_ntrak = ntracks; - if (sblock.fs_ntrak <= 0) - deverr (14, 0, "preposterous ntrak %ld", sblock.fs_ntrak); - if (sblock.fs_nsect <= 0) - deverr (15, 0, "preposterous nsect %ld", sblock.fs_nsect); - /* - * collect and verify the block and fragment sizes - */ - sblock.fs_bsize = bsize; - sblock.fs_fsize = fsize; - if (!POWEROF2(sblock.fs_bsize)) - deverr (16, 0, - "block size must be a power of 2, not %ld", - sblock.fs_bsize); - if (!POWEROF2(sblock.fs_fsize)) - deverr (17, 0, - "fragment size must be a power of 2, not %ld", - sblock.fs_fsize); - if (sblock.fs_fsize < sectorsize) - deverr (18, 0, - "fragment size %ld is too small, minimum is %d", - sblock.fs_fsize, sectorsize); - if (sblock.fs_bsize < MINBSIZE) - deverr (19, 0, - "block size %ld is too small, minimum is %d", - sblock.fs_bsize, MINBSIZE); - if (sblock.fs_bsize < sblock.fs_fsize) - deverr (20, 0, - "block size (%ld) cannot be smaller than fragment size (%ld)", - sblock.fs_bsize, sblock.fs_fsize); - sblock.fs_bmask = ~(sblock.fs_bsize - 1); - sblock.fs_fmask = ~(sblock.fs_fsize - 1); - sblock.fs_qbmask = ~sblock.fs_bmask; - sblock.fs_qfmask = ~sblock.fs_fmask; - for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1) - sblock.fs_bshift++; - for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1) - sblock.fs_fshift++; - sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize); - for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1) - sblock.fs_fragshift++; - if (sblock.fs_frag > MAXFRAG) - deverr (21, 0, - "fragment size %ld is too small, minimum with block size %ld is %ld", - sblock.fs_fsize, sblock.fs_bsize, - sblock.fs_bsize / MAXFRAG); - sblock.fs_nrpos = nrpos; - sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t); - sblock.fs_inopb = sblock.fs_bsize / sizeof(struct dinode); - sblock.fs_nspf = sblock.fs_fsize / sectorsize; - for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1) - sblock.fs_fsbtodb++; - sblock.fs_sblkno = - roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag); - sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno + - roundup(howmany(sbsize, sblock.fs_fsize), sblock.fs_frag)); - sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; - sblock.fs_cgoffset = roundup( - howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag); - for (sblock.fs_cgmask = 0xffffffff, i = sblock.fs_ntrak; i > 1; i >>= 1) - sblock.fs_cgmask <<= 1; - if (!POWEROF2(sblock.fs_ntrak)) - sblock.fs_cgmask <<= 1; - sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1; - for (sizepb = sblock.fs_bsize, i = 0; i < NIADDR; i++) { - sizepb *= NINDIR(&sblock); - sblock.fs_maxfilesize += sizepb; - } - /* - * Validate specified/determined secpercyl - * and calculate minimum cylinders per group. - */ - sblock.fs_spc = secpercyl; - for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc; - sblock.fs_cpc > 1 && (i & 1) == 0; - sblock.fs_cpc >>= 1, i >>= 1) - /* void */; - mincpc = sblock.fs_cpc; - bpcg = sblock.fs_spc * sectorsize; - inospercg = roundup(bpcg / sizeof(struct dinode), INOPB(&sblock)); - if (inospercg > MAXIPG(&sblock)) - inospercg = MAXIPG(&sblock); - used = (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock); - mincpgcnt = howmany(sblock.fs_cgoffset * (~sblock.fs_cgmask) + used, - sblock.fs_spc); - mincpg = roundup(mincpgcnt, mincpc); - /* - * Ensure that cylinder group with mincpg has enough space - * for block maps. - */ - sblock.fs_cpg = mincpg; - sblock.fs_ipg = inospercg; - if (maxcontig > 1) - sblock.fs_contigsumsize = MIN(maxcontig, FS_MAXCONTIG); - mapcramped = 0; - while (CGSIZE(&sblock) > sblock.fs_bsize) { - mapcramped = 1; - if (sblock.fs_bsize < MAXBSIZE) { - sblock.fs_bsize <<= 1; - if ((i & 1) == 0) { - i >>= 1; - } else { - sblock.fs_cpc <<= 1; - mincpc <<= 1; - mincpg = roundup(mincpgcnt, mincpc); - sblock.fs_cpg = mincpg; - } - sblock.fs_frag <<= 1; - sblock.fs_fragshift += 1; - if (sblock.fs_frag <= MAXFRAG) - continue; - } - if (sblock.fs_fsize == sblock.fs_bsize) - deverr (22, 0, - "There is no block size that can support this disk"); - sblock.fs_frag >>= 1; - sblock.fs_fragshift -= 1; - sblock.fs_fsize <<= 1; - sblock.fs_nspf <<= 1; - } - /* - * Ensure that cylinder group with mincpg has enough space for inodes. - */ - inodecramped = 0; - used *= sectorsize; - inospercg = roundup((mincpg * bpcg - used) / density, INOPB(&sblock)); - sblock.fs_ipg = inospercg; - while (inospercg > MAXIPG(&sblock)) { - inodecramped = 1; - if (mincpc == 1 || sblock.fs_frag == 1 || - sblock.fs_bsize == MINBSIZE) - break; - deverr (0, 0, - "With a block size of %ld %s %ld", sblock.fs_bsize, - "minimum bytes per inode is", - (mincpg * bpcg - used) / MAXIPG(&sblock) + 1); - sblock.fs_bsize >>= 1; - sblock.fs_frag >>= 1; - sblock.fs_fragshift -= 1; - mincpc >>= 1; - sblock.fs_cpg = roundup(mincpgcnt, mincpc); - if (CGSIZE(&sblock) > sblock.fs_bsize) { - sblock.fs_bsize <<= 1; - break; - } - mincpg = sblock.fs_cpg; - inospercg = - roundup((mincpg * bpcg - used) / density, INOPB(&sblock)); - sblock.fs_ipg = inospercg; - } - if (inodecramped) { - if (inospercg > MAXIPG(&sblock)) - deverr (0, 0, "Minimum bytes per inode is %ld", - (mincpg * bpcg - used) / MAXIPG(&sblock) + 1); - else if (!mapcramped) - deverr (0, 0, - "With %d bytes per inode," - " minimum cylinders per group is %ld", - density, mincpg); - } - if (mapcramped) - deverr (0, 0, - "With %ld sectors per cylinder," - " minimum cylinders per group is %ld", - sblock.fs_spc, mincpg); - if (inodecramped || mapcramped) - if (sblock.fs_bsize != bsize) - { - deverr (0, 0, - "This requires the block size to be changed from %d to %ld", - bsize, sblock.fs_bsize); - deverr (23, 0, - "and the fragment size to be changed from %d to %ld", - fsize, sblock.fs_fsize); - } - else - exit(23); - /* - * Calculate the number of cylinders per group - */ - sblock.fs_cpg = cpg; - if (sblock.fs_cpg % mincpc != 0) { - deverr (0, 0, - "%s groups must have a multiple of %ld cylinders", - cpgflg ? "Cylinder" : "Warning: cylinder", mincpc); - sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc); - if (!cpgflg) - cpg = sblock.fs_cpg; - } - /* - * Must ensure there is enough space for inodes. - */ - sblock.fs_ipg = roundup((sblock.fs_cpg * bpcg - used) / density, - INOPB(&sblock)); - while (sblock.fs_ipg > MAXIPG(&sblock)) { - inodecramped = 1; - sblock.fs_cpg -= mincpc; - sblock.fs_ipg = roundup((sblock.fs_cpg * bpcg - used) / density, - INOPB(&sblock)); - } - /* - * Must ensure there is enough space to hold block map. - */ - while (CGSIZE(&sblock) > sblock.fs_bsize) { - mapcramped = 1; - sblock.fs_cpg -= mincpc; - sblock.fs_ipg = roundup((sblock.fs_cpg * bpcg - used) / density, - INOPB(&sblock)); - } - sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); - if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) - deverr (24, 0, "panic (fs_cpg * fs_spc) %% NSPF != 0"); - if (sblock.fs_cpg < mincpg) - deverr (25, 0, - "cylinder groups must have at least %ld cylinders", mincpg); - else if (sblock.fs_cpg != cpg) - { - if (cpgflg && !mapcramped && !inodecramped) - exit(26); - deverr (0, 0, - "%s%s cylinders per group to %ld", - (cpgflg ? "" : "Warning: "), - ((mapcramped && inodecramped) - ? "Block size and bytes per inode restrict" - : mapcramped ? "Block size restricts" - : "Bytes per inode restrict"), - sblock.fs_cpg); - if (cpgflg) - exit(27); - } - sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock)); - /* - * Now have size for file system and nsect and ntrak. - * Determine number of cylinders and blocks in the file system. - */ - sblock.fs_size = fssize = dbtofsb(&sblock, fssize); - sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc; - if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) { - sblock.fs_ncyl++; - warn = 1; - } - if (sblock.fs_ncyl < 1) - deverr (28, 0, "file systems must have at least one cylinder"); - /* - * Determine feasability/values of rotational layout tables. - * - * The size of the rotational layout tables is limited by the - * size of the superblock, SBSIZE. The amount of space available - * for tables is calculated as (SBSIZE - sizeof (struct fs)). - * The size of these tables is inversely proportional to the block - * size of the file system. The size increases if sectors per track - * are not powers of two, because more cylinders must be described - * by the tables before the rotational pattern repeats (fs_cpc). - */ - sblock.fs_interleave = interleave; - sblock.fs_trackskew = trackskew; - sblock.fs_npsect = nphyssectors; - sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT; - sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs)); - if (sblock.fs_ntrak == 1) { - sblock.fs_cpc = 0; - goto next; - } - postblsize = sblock.fs_nrpos * sblock.fs_cpc * sizeof(short); - rotblsize = sblock.fs_cpc * sblock.fs_spc / NSPB(&sblock); - totalsbsize = sizeof(struct fs) + rotblsize; - if (sblock.fs_nrpos == 8 && sblock.fs_cpc <= 16) { - /* use old static table space */ - sblock.fs_postbloff = (char *)(&sblock.fs_opostbl[0][0]) - - (char *)(&sblock.fs_link); - sblock.fs_rotbloff = &sblock.fs_space[0] - - (u_char *)(&sblock.fs_link); - } else { - /* use dynamic table space */ - sblock.fs_postbloff = &sblock.fs_space[0] - - (u_char *)(&sblock.fs_link); - sblock.fs_rotbloff = sblock.fs_postbloff + postblsize; - totalsbsize += postblsize; - } - if (totalsbsize > SBSIZE || - sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) - { - deverr (0, 0, - "Warning: insufficient space in super block for " - "rotational layout tables with nsect %ld and ntrak %ld", - sblock.fs_nsect, sblock.fs_ntrak); - deverr (0, 0, "File system performance may be impaired"); - sblock.fs_cpc = 0; - goto next; - } - sblock.fs_sbsize = fragroundup(&sblock, totalsbsize); - /* - * calculate the available blocks for each rotational position - */ - for (cylno = 0; cylno < sblock.fs_cpc; cylno++) - for (rpos = 0; rpos < sblock.fs_nrpos; rpos++) - fs_postbl(&sblock, cylno)[rpos] = -1; - for (i = (rotblsize - 1) * sblock.fs_frag; - i >= 0; i -= sblock.fs_frag) { - cylno = cbtocylno(&sblock, i); - rpos = cbtorpos(&sblock, i); - blk = fragstoblks(&sblock, i); - if (fs_postbl(&sblock, cylno)[rpos] == -1) - fs_rotbl(&sblock)[blk] = 0; - else - fs_rotbl(&sblock)[blk] = - fs_postbl(&sblock, cylno)[rpos] - blk; - fs_postbl(&sblock, cylno)[rpos] = blk; - } -next: - /* - * Compute/validate number of cylinder groups. - */ - sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; - if (sblock.fs_ncyl % sblock.fs_cpg) - sblock.fs_ncg++; - sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock); - i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1); - if (cgdmin(&sblock, i) - cgbase(&sblock, i) >= sblock.fs_fpg) - { - deverr (0, 0, - "Inode blocks/cyl group (%ld) >= data blocks (%ld)", - cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag, - sblock.fs_fpg / sblock.fs_frag); - deverr (29, 0, - "number of cylinders per cylinder group (%ld)" - " must be increased", sblock.fs_cpg); - } - j = sblock.fs_ncg - 1; - if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg && - cgdmin(&sblock, j) - cgbase(&sblock, j) > i) { - if (j == 0) - deverr (30, 0, - "Filesystem must have at least %ld sectors", - NSPF(&sblock) - * (cgdmin(&sblock, 0) + 3 * sblock.fs_frag)); - deverr (0, 0, - "Warning: inode blocks/cyl group (%ld) >=" - " data blocks (%ld) in last cylinder group.", - ((cgdmin(&sblock, j) - cgbase(&sblock, j)) - / sblock.fs_frag), - i / sblock.fs_frag); - deverr (0, 0, - "This implies %ld sector(s) cannot be allocated", - i * NSPF(&sblock)); - sblock.fs_ncg--; - sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg; - sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc / - NSPF(&sblock); - warn = 0; - } - if (warn) - deverr (0, 0, - "Warning: %ld sector(s) in last cylinder unallocated", - sblock.fs_spc - - (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1) - * sblock.fs_spc)); - /* - * fill in remaining fields of the super block - */ - sblock.fs_csaddr = cgdmin(&sblock, 0); - sblock.fs_cssize = - fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); - i = sblock.fs_bsize / sizeof(struct csum); - sblock.fs_csmask = ~(i - 1); - for (sblock.fs_csshift = 0; i > 1; i >>= 1) - sblock.fs_csshift++; - fscs = (struct csum *)calloc(1, sblock.fs_cssize); - sblock.fs_magic = FS_MAGIC; - sblock.fs_rotdelay = rotdelay; - sblock.fs_minfree = minfree; - sblock.fs_maxcontig = maxcontig; - sblock.fs_headswitch = headswitch; - sblock.fs_trkseek = trackseek; - sblock.fs_maxbpg = maxbpg; - sblock.fs_rps = rpm / 60; - sblock.fs_optim = opt; - sblock.fs_cgrotor = 0; - sblock.fs_cstotal.cs_ndir = 0; - sblock.fs_cstotal.cs_nbfree = 0; - sblock.fs_cstotal.cs_nifree = 0; - sblock.fs_cstotal.cs_nffree = 0; - sblock.fs_fmod = 0; - sblock.fs_ronly = 0; - sblock.fs_clean = 1; - - /* - * Dump out summary information about file system. - */ - printf("%s:\n\t%ld sectors in %ld %s of %ld tracks, %ld sectors\n", - fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl, - "cylinders", sblock.fs_ntrak, sblock.fs_nsect); -#define B2MBFACTOR (1 / (1024.0 * 1024.0)) - printf("\t%.1fMB in %ld cyl groups (%ld c/g, %.2fMB/g, %ld i/g)\n", - (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, - sblock.fs_ncg, sblock.fs_cpg, - (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, - sblock.fs_ipg); -#undef B2MBFACTOR - - /* - * Now build the cylinders group blocks and - * then print out indices of cylinder groups. - */ - printf("\tsuperblock backups at:"); - for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { - initcg(cylno, utime); - if (cylno % 8 == 0) - printf("\n\t"); - printf(" %ld,", fsbtodb(&sblock, cgsblock(&sblock, cylno))); - } - printf("\n"); - if (Nflag) - exit(0); - /* - * Now construct the initial file system, - * then write out the super-block. - */ - fsinit(utime); - sblock.fs_time = utime; - wtfs((int)SBOFF / sectorsize, sbsize, (char *)&sblock); - for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) - wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), - sblock.fs_cssize - i < sblock.fs_bsize ? - sblock.fs_cssize - i : sblock.fs_bsize, - ((char *)fscs) + i); - /* - * Write out the duplicate super blocks - */ - for (cylno = 0; cylno < sblock.fs_ncg; cylno++) - wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), - sbsize, (char *)&sblock); -#if 0 /* Not in Hurd (yet) */ - /* - * Update information about this partion in pack - * label, to that it may be updated on disk. - */ - pp->p_fstype = FS_BSDFFS; - pp->p_fsize = sblock.fs_fsize; - pp->p_frag = sblock.fs_frag; - pp->p_cpg = sblock.fs_cpg; -#endif -} - -/* - * Initialize a cylinder group. - */ -void -initcg(cylno, utime) - int cylno; - time_t utime; -{ - long i; - daddr_t cbase, d, dlower, dupper, dmax, blkno; - register struct csum *cs; - - /* - * Determine block bounds for cylinder group. - * Allow space for super block summary information in first - * cylinder group. - */ - cbase = cgbase(&sblock, cylno); - dmax = cbase + sblock.fs_fpg; - if (dmax > sblock.fs_size) - dmax = sblock.fs_size; - dlower = cgsblock(&sblock, cylno) - cbase; - dupper = cgdmin(&sblock, cylno) - cbase; - if (cylno == 0) - dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); - cs = fscs + cylno; - bzero(&acg, sblock.fs_cgsize); - acg.cg_time = utime; - acg.cg_magic = CG_MAGIC; - acg.cg_cgx = cylno; - if (cylno == sblock.fs_ncg - 1) - acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; - else - acg.cg_ncyl = sblock.fs_cpg; - acg.cg_niblk = sblock.fs_ipg; - acg.cg_ndblk = dmax - cbase; - if (sblock.fs_contigsumsize > 0) - acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag; - acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_link); - acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(long); - acg.cg_iusedoff = acg.cg_boff + - sblock.fs_cpg * sblock.fs_nrpos * sizeof(short); - acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY); - if (sblock.fs_contigsumsize <= 0) { - acg.cg_nextfreeoff = acg.cg_freeoff + - howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY); - } else { - acg.cg_clustersumoff = acg.cg_freeoff + howmany - (sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY) - - sizeof(long); - acg.cg_clustersumoff = - roundup(acg.cg_clustersumoff, sizeof(long)); - acg.cg_clusteroff = acg.cg_clustersumoff + - (sblock.fs_contigsumsize + 1) * sizeof(long); - acg.cg_nextfreeoff = acg.cg_clusteroff + howmany - (sblock.fs_cpg * sblock.fs_spc / NSPB(&sblock), NBBY); - } - if (acg.cg_nextfreeoff - (long)(&acg.cg_link) > sblock.fs_cgsize) - deverr (37, 0, "Panic: cylinder group too big"); - acg.cg_cs.cs_nifree += sblock.fs_ipg; - if (cylno == 0) - for (i = 0; i < ROOTINO; i++) { - setbit(cg_inosused(&acg), i); - acg.cg_cs.cs_nifree--; - } - for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) - wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), - sblock.fs_bsize, (char *)zino); - if (cylno > 0) { - /* - * In cylno 0, beginning space is reserved - * for boot and super blocks. - */ - for (d = 0; d < dlower; d += sblock.fs_frag) { - blkno = d / sblock.fs_frag; - setblock(&sblock, cg_blksfree(&acg), blkno); - if (sblock.fs_contigsumsize > 0) - setbit(cg_clustersfree(&acg), blkno); - acg.cg_cs.cs_nbfree++; - cg_blktot(&acg)[cbtocylno(&sblock, d)]++; - cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) - [cbtorpos(&sblock, d)]++; - } - sblock.fs_dsize += dlower; - } - sblock.fs_dsize += acg.cg_ndblk - dupper; - i = dupper % sblock.fs_frag; - if (i) { - acg.cg_frsum[sblock.fs_frag - i]++; - for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { - setbit(cg_blksfree(&acg), dupper); - acg.cg_cs.cs_nffree++; - } - } - for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) { - blkno = d / sblock.fs_frag; - setblock(&sblock, cg_blksfree(&acg), blkno); - if (sblock.fs_contigsumsize > 0) - setbit(cg_clustersfree(&acg), blkno); - acg.cg_cs.cs_nbfree++; - cg_blktot(&acg)[cbtocylno(&sblock, d)]++; - cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) - [cbtorpos(&sblock, d)]++; - d += sblock.fs_frag; - } - if (d < dmax - cbase) { - acg.cg_frsum[dmax - cbase - d]++; - for (; d < dmax - cbase; d++) { - setbit(cg_blksfree(&acg), d); - acg.cg_cs.cs_nffree++; - } - } - if (sblock.fs_contigsumsize > 0) { - long *sump = cg_clustersum(&acg); - u_char *mapp = cg_clustersfree(&acg); - int map = *mapp++; - int bit = 1; - int run = 0; - - for (i = 0; i < acg.cg_nclusterblks; i++) { - if ((map & bit) != 0) { - run++; - } else if (run != 0) { - if (run > sblock.fs_contigsumsize) - run = sblock.fs_contigsumsize; - sump[run]++; - run = 0; - } - if ((i & (NBBY - 1)) != (NBBY - 1)) { - bit <<= 1; - } else { - map = *mapp++; - bit = 1; - } - } - if (run != 0) { - if (run > sblock.fs_contigsumsize) - run = sblock.fs_contigsumsize; - sump[run]++; - } - } - sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; - sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; - sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; - sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; - *cs = acg.cg_cs; - wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), - sblock.fs_bsize, (char *)&acg); -} - -/* - * initialize the file system - */ -struct dinode node; - -#ifdef LOSTDIR -#define PREDEFDIR 3 -#else -#define PREDEFDIR 2 -#endif - -struct directory_entry root_dir[] = { - { ROOTINO, sizeof(struct directory_entry), DT_DIR, 1, "." }, - { ROOTINO, sizeof(struct directory_entry), DT_DIR, 2, ".." }, -#ifdef LOSTDIR - { LOSTFOUNDINO, sizeof(struct directory_entry), DT_DIR, 10, "lost+found" }, -#endif -}; -struct odirectory_entry { - u_long d_ino; - u_short d_reclen; - u_short d_namlen; - u_char d_name[MAXNAMLEN + 1]; -} oroot_dir[] = { - { ROOTINO, sizeof(struct directory_entry), 1, "." }, - { ROOTINO, sizeof(struct directory_entry), 2, ".." }, -#ifdef LOSTDIR - { LOSTFOUNDINO, sizeof(struct directory_entry), 10, "lost+found" }, -#endif -}; -#ifdef LOSTDIR -struct directory_entry lost_found_dir[] = { - { LOSTFOUNDINO, sizeof(struct directory_entry), DT_DIR, 1, "." }, - { ROOTINO, sizeof(struct directory_entry), DT_DIR, 2, ".." }, - { 0, DIRBLKSIZ, 0, 0, 0 }, -}; -struct odirectory_entry olost_found_dir[] = { - { LOSTFOUNDINO, sizeof(struct directory_entry), 1, "." }, - { ROOTINO, sizeof(struct directory_entry), 2, ".." }, - { 0, DIRBLKSIZ, 0, 0 }, -}; -#endif -char buf[MAXBSIZE]; - -void -fsinit(utime) - time_t utime; -{ - /* - * initialize the node - */ - node.di_atime.tv_sec = utime; - node.di_mtime.tv_sec = utime; - node.di_ctime.tv_sec = utime; -#ifdef LOSTDIR - /* - * create the lost+found directory - */ - if (Oflag) { - (void)makedir((struct directory_entry *)olost_found_dir, 2); - for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) - bcopy(&olost_found_dir[2], &buf[i], - DIRSIZ(0, &olost_found_dir[2])); - } else { - (void)makedir(lost_found_dir, 2); - for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) - bcopy(&lost_found_dir[2], &buf[i], - DIRSIZ(0, &lost_found_dir[2])); - } - node.di_model = ifdir | UMASK; - node.di_modeh = 0; - node.di_nlink = 2; - node.di_size = sblock.fs_bsize; - node.di_db[0] = alloc(node.di_size, DI_MODE (&node)); - node.di_blocks = btodb(fragroundup(&sblock, node.di_size)); - wtfs(fsbtodb(&sblock, node.di_db[0]), node.di_size, buf); - iput(&node, LOSTFOUNDINO); -#endif - /* - * create the root directory - */ - node.di_model = IFDIR | UMASK; - node.di_modeh = 0; - node.di_nlink = PREDEFDIR; - - /* Set the uid/gid to non-root if run by a non-root user. This - is what mke2fs does in e2fsprogs-1.18 (actually it uses the - real IDs iff geteuid()!=0, but that is just wrong). */ - node.di_uid = geteuid(); - if (node.di_uid != 0) - node.di_gid = getegid(); - - if (Oflag) - node.di_size = makedir((struct directory_entry *)oroot_dir, PREDEFDIR); - else - node.di_size = makedir(root_dir, PREDEFDIR); - node.di_db[0] = alloc(sblock.fs_fsize, DI_MODE (&node)); - node.di_blocks = btodb(fragroundup(&sblock, node.di_size)); - wtfs(fsbtodb(&sblock, node.di_db[0]), sblock.fs_fsize, buf); - iput(&node, ROOTINO); -} - -/* - * construct a set of directory entries in "buf". - * return size of directory. - */ -int -makedir(protodir, entries) - register struct directory_entry *protodir; - int entries; -{ - char *cp; - int i, spcleft; - - spcleft = DIRBLKSIZ; - for (cp = buf, i = 0; i < entries - 1; i++) { - protodir[i].d_reclen = DIRSIZ(0, &protodir[i]); - bcopy(&protodir[i], cp, protodir[i].d_reclen); - cp += protodir[i].d_reclen; - spcleft -= protodir[i].d_reclen; - } - protodir[i].d_reclen = spcleft; - bcopy(&protodir[i], cp, DIRSIZ(0, &protodir[i])); - return (DIRBLKSIZ); -} - -/* - * allocate a block or frag - */ -daddr_t -alloc(size, mode) - int size; - int mode; -{ - int i, frag; - daddr_t d, blkno; - - rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, - (char *)&acg); - if (acg.cg_magic != CG_MAGIC) { - deverr (0, 0, "cg 0: bad magic number"); - return (0); - } - if (acg.cg_cs.cs_nbfree == 0) { - deverr (0, 0, "first cylinder group ran out of space"); - return (0); - } - for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) - if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag)) - goto goth; - deverr (0, 0, "internal error: can't find block in cyl 0"); - return (0); -goth: - blkno = fragstoblks(&sblock, d); - clrblock(&sblock, cg_blksfree(&acg), blkno); - if (sblock.fs_contigsumsize > 0) - clrbit(cg_clustersfree(&acg), blkno); - acg.cg_cs.cs_nbfree--; - sblock.fs_cstotal.cs_nbfree--; - fscs[0].cs_nbfree--; - if (mode & IFDIR) { - acg.cg_cs.cs_ndir++; - sblock.fs_cstotal.cs_ndir++; - fscs[0].cs_ndir++; - } - cg_blktot(&acg)[cbtocylno(&sblock, d)]--; - cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--; - if (size != sblock.fs_bsize) { - frag = howmany(size, sblock.fs_fsize); - fscs[0].cs_nffree += sblock.fs_frag - frag; - sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; - acg.cg_cs.cs_nffree += sblock.fs_frag - frag; - acg.cg_frsum[sblock.fs_frag - frag]++; - for (i = frag; i < sblock.fs_frag; i++) - setbit(cg_blksfree(&acg), d + i); - } - wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, - (char *)&acg); - return (d); -} - -/* - * Allocate an inode on the disk - */ -void -iput(ip, ino) - register struct dinode *ip; - register ino_t ino; -{ - struct dinode buf[MAXINOPB]; - daddr_t d; - int c; - - c = ino_to_cg(&sblock, ino); - rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, - (char *)&acg); - if (acg.cg_magic != CG_MAGIC) - deverr (31, 0, "cg 0: bad magic number"); - acg.cg_cs.cs_nifree--; - setbit(cg_inosused(&acg), ino); - wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, - (char *)&acg); - sblock.fs_cstotal.cs_nifree--; - fscs[0].cs_nifree--; - if (ino >= sblock.fs_ipg * sblock.fs_ncg) - deverr (32, 0, "fsinit: inode value out of range (%Ld)", ino); - d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino)); - rdfs(d, sblock.fs_bsize, buf); - buf[ino_to_fsbo(&sblock, ino)] = *ip; - wtfs(d, sblock.fs_bsize, buf); -} - -/* - * read a block from the file system - */ -void -rdfs(bno, size, bf) - daddr_t bno; - int size; - char *bf; -{ - int n; - if (lseek(fsi, (off_t)bno * sectorsize, 0) < 0) - deverr (33, errno, "rdfs: %ld: seek error", bno); - n = read(fsi, bf, size); - if (n != size) - deverr (34, errno, "rdfs: %ld: read error", bno); -} - -/* - * write a block to the file system - */ -void -wtfs(bno, size, bf) - daddr_t bno; - int size; - char *bf; -{ - int n; - if (Nflag) - return; - if (lseek(fso, (off_t)bno * sectorsize, SEEK_SET) < 0) - deverr (35, errno, "wtfs: %ld: seek error", bno); - n = write(fso, bf, size); - if (n != size) - deverr (36, errno, "wtfs: %ld: write error", bno); -} - -/* - * check if a block is available - */ -int -isblock(fs, cp, h) - struct fs *fs; - unsigned char *cp; - int h; -{ - unsigned char mask; - - switch (fs->fs_frag) { - case 8: - return (cp[h] == 0xff); - case 4: - mask = 0x0f << ((h & 0x1) << 2); - return ((cp[h >> 1] & mask) == mask); - case 2: - mask = 0x03 << ((h & 0x3) << 1); - return ((cp[h >> 2] & mask) == mask); - case 1: - mask = 0x01 << (h & 0x7); - return ((cp[h >> 3] & mask) == mask); - default: - deverr (0, 0, "isblock bad fs_frag %ld", fs->fs_frag); - return (0); - } -} - -/* - * take a block out of the map - */ -void -clrblock(fs, cp, h) - struct fs *fs; - unsigned char *cp; - int h; -{ - switch ((fs)->fs_frag) { - case 8: - cp[h] = 0; - return; - case 4: - cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); - return; - case 2: - cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); - return; - case 1: - cp[h >> 3] &= ~(0x01 << (h & 0x7)); - return; - default: - deverr (0, 0, "clrblock bad fs_frag %ld", fs->fs_frag); - return; - } -} - -/* - * put a block into the map - */ -void -setblock(fs, cp, h) - struct fs *fs; - unsigned char *cp; - int h; -{ - switch (fs->fs_frag) { - case 8: - cp[h] = 0xff; - return; - case 4: - cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); - return; - case 2: - cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); - return; - case 1: - cp[h >> 3] |= (0x01 << (h & 0x7)); - return; - default: - deverr (0, 0, "setblock bad fs_frag %ld", fs->fs_frag); - return; - } -} diff --git a/ufs-utils/newfs.c b/ufs-utils/newfs.c deleted file mode 100644 index efc7dbea..00000000 --- a/ufs-utils/newfs.c +++ /dev/null @@ -1,705 +0,0 @@ -/* - * Copyright (c) 1983, 1989, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char copyright[] = -"@(#) Copyright (c) 1983, 1989, 1993, 1994\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -/*static char sccsid[] = "from: @(#)newfs.c 8.8 (Berkeley) 4/18/94";*/ -static char *rcsid = "$Id: newfs.c,v 1.2 1994/09/09 14:11:41 mib Exp $"; -#endif /* not lint */ - -/* - * newfs: friendly front end to mkfs - */ -#include <sys/param.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -/* #include <sys/disklabel.h> */ -#include <sys/file.h> -/* #include <sys/mount.h> */ - -#include "../ufs/dir.h" -#include "../ufs/fs.h" - -#include <ctype.h> -#include <errno.h> -#include <paths.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> -#include <unistd.h> - -#if __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif - -/* #include "mntopts.h" */ - -/* GNU Hurd additions */ -#define MAXPATHLEN 2048 - -/* End GNU Hurd additions */ - - -#if 0 -struct mntopt mopts[] = { - MOPT_STDOPTS, - MOPT_ASYNC, - { NULL }, -}; -#endif - -#if __STDC__ -void fatal(const char *fmt, ...); -#else -void fatal(); -#endif - -#define COMPAT /* allow non-labeled disks */ - -/* - * The following two constants set the default block and fragment sizes. - * Both constants must be a power of 2 and meet the following constraints: - * MINBSIZE <= DESBLKSIZE <= MAXBSIZE - * sectorsize <= DESFRAGSIZE <= DESBLKSIZE - * DESBLKSIZE / DESFRAGSIZE <= 8 - */ -#define DFL_FRAGSIZE 1024 -#define DFL_BLKSIZE 8192 - -/* - * Cylinder groups may have up to many cylinders. The actual - * number used depends upon how much information can be stored - * on a single cylinder. The default is to use 16 cylinders - * per group. - */ -#define DESCPG 16 /* desired fs_cpg */ - -/* - * ROTDELAY gives the minimum number of milliseconds to initiate - * another disk transfer on the same cylinder. It is used in - * determining the rotationally optimal layout for disk blocks - * within a file; the default of fs_rotdelay is 4ms. - */ -#define ROTDELAY 4 - -/* - * MAXBLKPG determines the maximum number of data blocks which are - * placed in a single cylinder group. The default is one indirect - * block worth of data blocks. - */ -#define MAXBLKPG(bsize) ((bsize) / sizeof(daddr_t)) - -/* - * Each file system has a number of inodes statically allocated. - * We allocate one inode slot per NFPI fragments, expecting this - * to be far more than we will ever need. - */ -#define NFPI 4 - -/* - * For each cylinder we keep track of the availability of blocks at different - * rotational positions, so that we can lay out the data to be picked - * up with minimum rotational latency. NRPOS is the default number of - * rotational positions that we distinguish. With NRPOS of 8 the resolution - * of our summary information is 2ms for a typical 3600 rpm drive. - */ -#define NRPOS 8 /* number distinct rotational positions */ - - -int mfs; /* run as the memory based filesystem */ -int Nflag; /* run without writing file system */ -int Oflag; /* format as an 4.3BSD file system */ -int fssize; /* file system size */ -int ntracks; /* # tracks/cylinder */ -int nsectors; /* # sectors/track */ -int nphyssectors; /* # sectors/track including spares */ -int secpercyl; /* sectors per cylinder */ -int trackspares = -1; /* spare sectors per track */ -int cylspares = -1; /* spare sectors per cylinder */ -int sectorsize; /* bytes/sector */ -#ifdef tahoe -int realsectorsize; /* bytes/sector in hardware */ -#endif -int rpm; /* revolutions/minute of drive */ -int interleave; /* hardware sector interleave */ -int trackskew = -1; /* sector 0 skew, per track */ -int headswitch; /* head switch time, usec */ -int trackseek; /* track-to-track seek, usec */ -int fsize = 0; /* fragment size */ -int bsize = 0; /* block size */ -int cpg = DESCPG; /* cylinders/cylinder group */ -int cpgflg; /* cylinders/cylinder group flag was given */ -int minfree = MINFREE; /* free space threshold */ -int opt = DEFAULTOPT; /* optimization preference (space or time) */ -int density; /* number of bytes per inode */ -int maxcontig = 0; /* max contiguous blocks to allocate */ -int rotdelay = ROTDELAY; /* rotational delay between blocks */ -int maxbpg; /* maximum blocks per file in a cyl group */ -int nrpos = NRPOS; /* # of distinguished rotational positions */ -int bbsize = BBSIZE; /* boot block size */ -int sbsize = SBSIZE; /* superblock size */ -/* int mntflags = MNT_ASYNC;*/ /* flags to be passed to mount */ -u_long memleft; /* virtual memory available */ -caddr_t membase; /* start address of memory based filesystem */ -#ifdef COMPAT -char *disktype; -int unlabeled; -#endif - -char device[MAXPATHLEN]; -char *progname; - -int -main(argc, argv) - int argc; - char *argv[]; -{ - extern char *optarg; - extern int optind; - register int ch; - register struct partition *pp; - register struct disklabel *lp; - struct disklabel *getdisklabel(); -/* struct partition oldpartition; */ - struct stat st; - struct statfs *mp; - int fsi, fso, len, n; - char *cp, *s1, *s2, *special, *opstring, buf[BUFSIZ]; - - if (progname = rindex(*argv, '/')) - ++progname; - else - progname = *argv; - -#if 0 - if (strstr(progname, "mfs")) { - mfs = 1; - Nflag++; - } -#endif - - opstring = mfs ? - "NT:a:b:c:d:e:f:i:m:o:s:" : - "NOS:T:a:b:c:d:e:f:i:k:l:m:n:o:p:r:s:t:u:x:"; - while ((ch = getopt(argc, argv, opstring)) != EOF) - switch (ch) { - case 'N': - Nflag = 1; - break; - case 'O': - Oflag = 1; - break; - case 'S': - if ((sectorsize = atoi(optarg)) <= 0) - fatal("%s: bad sector size", optarg); - break; -#ifdef COMPAT - case 'T': - disktype = optarg; - break; -#endif - case 'a': - if ((maxcontig = atoi(optarg)) <= 0) - fatal("%s: bad maximum contiguous blocks\n", - optarg); - break; - case 'b': - if ((bsize = atoi(optarg)) < MINBSIZE) - fatal("%s: bad block size", optarg); - break; - case 'c': - if ((cpg = atoi(optarg)) <= 0) - fatal("%s: bad cylinders/group", optarg); - cpgflg++; - break; - case 'd': - if ((rotdelay = atoi(optarg)) < 0) - fatal("%s: bad rotational delay\n", optarg); - break; - case 'e': - if ((maxbpg = atoi(optarg)) <= 0) - fatal("%s: bad blocks per file in a cylinder group\n", - optarg); - break; - case 'f': - if ((fsize = atoi(optarg)) <= 0) - fatal("%s: bad fragment size", optarg); - break; - case 'i': - if ((density = atoi(optarg)) <= 0) - fatal("%s: bad bytes per inode\n", optarg); - break; - case 'k': - if ((trackskew = atoi(optarg)) < 0) - fatal("%s: bad track skew", optarg); - break; - case 'l': - if ((interleave = atoi(optarg)) <= 0) - fatal("%s: bad interleave", optarg); - break; - case 'm': - if ((minfree = atoi(optarg)) < 0 || minfree > 99) - fatal("%s: bad free space %%\n", optarg); - break; - case 'n': - if ((nrpos = atoi(optarg)) <= 0) - fatal("%s: bad rotational layout count\n", - optarg); - break; - case 'o': -#if 0 - if (mfs) - getmntopts(optarg, mopts, &mntflags); - else -#endif - { - if (strcmp(optarg, "space") == 0) - opt = FS_OPTSPACE; - else if (strcmp(optarg, "time") == 0) - opt = FS_OPTTIME; - else - fatal("%s: unknown optimization preference: use `space' or `time'."); - } - break; - case 'p': - if ((trackspares = atoi(optarg)) < 0) - fatal("%s: bad spare sectors per track", - optarg); - break; - case 'r': - if ((rpm = atoi(optarg)) <= 0) - fatal("%s: bad revolutions/minute\n", optarg); - break; - case 's': - if ((fssize = atoi(optarg)) <= 0) - fatal("%s: bad file system size", optarg); - break; - case 't': - if ((ntracks = atoi(optarg)) <= 0) - fatal("%s: bad total tracks", optarg); - break; - case 'u': - if ((nsectors = atoi(optarg)) <= 0) - fatal("%s: bad sectors/track", optarg); - break; - case 'x': - if ((cylspares = atoi(optarg)) < 0) - fatal("%s: bad spare sectors per cylinder", - optarg); - break; - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - - if (argc != 2 && (mfs || argc != 1)) - usage(); - - special = argv[0]; - cp = rindex(special, '/'); - if (cp == 0) { - /* - * No path prefix; try /dev/r%s then /dev/%s. - */ - (void)sprintf(device, "%sr%s", _PATH_DEV, special); - if (stat(device, &st) == -1) - (void)sprintf(device, "%s%s", _PATH_DEV, special); - special = device; - } - if (Nflag) { - fso = -1; - } else { - fso = open(special, O_WRONLY); - if (fso < 0) - fatal("%s: %s", special, strerror(errno)); - -#if 0 - /* Bail if target special is mounted */ - n = getmntinfo(&mp, MNT_NOWAIT); - if (n == 0) - fatal("%s: getmntinfo: %s", special, strerror(errno)); - - len = sizeof(_PATH_DEV) - 1; - s1 = special; - if (strncmp(_PATH_DEV, s1, len) == 0) - s1 += len; - - while (--n >= 0) { - s2 = mp->f_mntfromname; - if (strncmp(_PATH_DEV, s2, len) == 0) { - s2 += len - 1; - *s2 = 'r'; - } - if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) - fatal("%s is mounted on %s", - special, mp->f_mntonname); - ++mp; - } -#endif - } -#if 0 - if (mfs && disktype != NULL) { - lp = (struct disklabel *)getdiskbyname(disktype); - if (lp == NULL) - fatal("%s: unknown disk type", disktype); - pp = &lp->d_partitions[1]; - } else { - fsi = open(special, O_RDONLY); - if (fsi < 0) - fatal("%s: %s", special, strerror(errno)); - if (fstat(fsi, &st) < 0) - fatal("%s: %s", special, strerror(errno)); - if ((st.st_mode & S_IFMT) != S_IFCHR && !mfs) - printf("%s: %s: not a character-special device\n", - progname, special); - cp = index(argv[0], '\0') - 1; - if (cp == 0 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp)) - fatal("%s: can't figure out file system partition", - argv[0]); -#ifdef COMPAT - if (!mfs && disktype == NULL) - disktype = argv[1]; -#endif - lp = getdisklabel(special, fsi); - if (isdigit(*cp)) - pp = &lp->d_partitions[0]; - else - pp = &lp->d_partitions[*cp - 'a']; - if (pp->p_size == 0) - fatal("%s: `%c' partition is unavailable", - argv[0], *cp); - if (pp->p_fstype == FS_BOOT) - fatal("%s: `%c' partition overlaps boot program", - argv[0], *cp); - } -#endif - /* GNU Hurd specific here */ - fsi = open (special, O_RDONLY); - if (fsi < 0) - fatal("%s: %s", special, strerror(errno)); - if (fstat(fsi, &st) < 0) - fatal("%s: %s", special, strerror(errno)); - fssize = st.st_size; - /* End GNU Hurd specific */ - - if (fssize == 0) - fssize = pp->p_size; - if (fssize > pp->p_size && !mfs) - fatal("%s: maximum file system size on the `%c' partition is %d", - argv[0], *cp, pp->p_size); - if (rpm == 0) { - rpm = lp->d_rpm; - if (rpm <= 0) - rpm = 3600; - } - if (ntracks == 0) { - ntracks = lp->d_ntracks; - if (ntracks <= 0) - fatal("%s: no default #tracks", argv[0]); - } - if (nsectors == 0) { - nsectors = lp->d_nsectors; - if (nsectors <= 0) - fatal("%s: no default #sectors/track", argv[0]); - } - if (sectorsize == 0) { - sectorsize = lp->d_secsize; - if (sectorsize <= 0) - fatal("%s: no default sector size", argv[0]); - } - if (trackskew == -1) { - trackskew = lp->d_trackskew; - if (trackskew < 0) - trackskew = 0; - } - if (interleave == 0) { - interleave = lp->d_interleave; - if (interleave <= 0) - interleave = 1; - } - if (fsize == 0) { - fsize = pp->p_fsize; - if (fsize <= 0) - fsize = MAX(DFL_FRAGSIZE, lp->d_secsize); - } - if (bsize == 0) { - bsize = pp->p_frag * pp->p_fsize; - if (bsize <= 0) - bsize = MIN(DFL_BLKSIZE, 8 * fsize); - } - /* - * Maxcontig sets the default for the maximum number of blocks - * that may be allocated sequentially. With filesystem clustering - * it is possible to allocate contiguous blocks up to the maximum - * transfer size permitted by the controller or buffering. - */ - if (maxcontig == 0) - maxcontig = MAX(1, MIN(MAXPHYS, MAXBSIZE) / bsize - 1); - if (density == 0) - density = NFPI * fsize; - if (minfree < MINFREE && opt != FS_OPTSPACE) { - fprintf(stderr, "Warning: changing optimization to space "); - fprintf(stderr, "because minfree is less than %d%%\n", MINFREE); - opt = FS_OPTSPACE; - } - if (trackspares == -1) { - trackspares = lp->d_sparespertrack; - if (trackspares < 0) - trackspares = 0; - } - nphyssectors = nsectors + trackspares; - if (cylspares == -1) { - cylspares = lp->d_sparespercyl; - if (cylspares < 0) - cylspares = 0; - } - secpercyl = nsectors * ntracks - cylspares; - if (secpercyl != lp->d_secpercyl) - fprintf(stderr, "%s (%d) %s (%lu)\n", - "Warning: calculated sectors per cylinder", secpercyl, - "disagrees with disk label", lp->d_secpercyl); - if (maxbpg == 0) - maxbpg = MAXBLKPG(bsize); - headswitch = lp->d_headswitch; - trackseek = lp->d_trkseek; -#ifdef notdef /* label may be 0 if faked up by kernel */ - bbsize = lp->d_bbsize; - sbsize = lp->d_sbsize; -#endif - oldpartition = *pp; -#ifdef tahoe - realsectorsize = sectorsize; - if (sectorsize != DEV_BSIZE) { /* XXX */ - int secperblk = DEV_BSIZE / sectorsize; - - sectorsize = DEV_BSIZE; - nsectors /= secperblk; - nphyssectors /= secperblk; - secpercyl /= secperblk; - fssize /= secperblk; - pp->p_size /= secperblk; - } -#endif - mkfs(pp, special, fsi, fso); -#ifdef tahoe - if (realsectorsize != DEV_BSIZE) - pp->p_size *= DEV_BSIZE / realsectorsize; -#endif - if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition))) - rewritelabel(special, fso, lp); - if (!Nflag) - close(fso); - close(fsi); -#ifdef MFS - if (mfs) { - struct mfs_args args; - - sprintf(buf, "mfs:%d", getpid()); - args.fspec = buf; - args.export.ex_root = -2; - if (mntflags & MNT_RDONLY) - args.export.ex_flags = MNT_EXRDONLY; - else - args.export.ex_flags = 0; - args.base = membase; - args.size = fssize * sectorsize; - if (mount(MOUNT_MFS, argv[1], mntflags, &args) < 0) - fatal("%s: %s", argv[1], strerror(errno)); - } -#endif - exit(0); -} - -#ifdef COMPAT -char lmsg[] = "%s: can't read disk label; disk type must be specified"; -#else -char lmsg[] = "%s: can't read disk label"; -#endif - -struct disklabel * -getdisklabel(s, fd) - char *s; - int fd; -{ - static struct disklabel lab; - - if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) { -#ifdef COMPAT - if (disktype) { - struct disklabel *lp, *getdiskbyname(); - - unlabeled++; - lp = getdiskbyname(disktype); - if (lp == NULL) - fatal("%s: unknown disk type", disktype); - return (lp); - } -#endif - warn("ioctl (GDINFO)"); - fatal(lmsg, s); - } - return (&lab); -} - -rewritelabel(s, fd, lp) - char *s; - int fd; - register struct disklabel *lp; -{ -#ifdef COMPAT - if (unlabeled) - return; -#endif - lp->d_checksum = 0; - lp->d_checksum = dkcksum(lp); - if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) { - warn("ioctl (WDINFO)"); - fatal("%s: can't rewrite disk label", s); - } -#if vax - if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { - register i; - int cfd; - daddr_t alt; - char specname[64]; - char blk[1024]; - char *cp; - - /* - * Make name for 'c' partition. - */ - strcpy(specname, s); - cp = specname + strlen(specname) - 1; - if (!isdigit(*cp)) - *cp = 'c'; - cfd = open(specname, O_WRONLY); - if (cfd < 0) - fatal("%s: %s", specname, strerror(errno)); - bzero(blk, sizeof(blk)); - *(struct disklabel *)(blk + LABELOFFSET) = *lp; - alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; - for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { - if (lseek(cfd, (off_t)(alt + i) * lp->d_secsize, - L_SET) == -1) - fatal("lseek to badsector area: %s", - strerror(errno)); - if (write(cfd, blk, lp->d_secsize) < lp->d_secsize) - warn("alternate label %d write", i/2); - } - close(cfd); - } -#endif -} - -/*VARARGS*/ -void -#if __STDC__ -fatal(const char *fmt, ...) -#else -fatal(fmt, va_alist) - char *fmt; - va_dcl -#endif -{ - va_list ap; - -#if __STDC__ - va_start(ap, fmt); -#else - va_start(ap); -#endif - if (fcntl(STDERR_FILENO, F_GETFL) < 0) { - openlog(progname, LOG_CONS, LOG_DAEMON); - vsyslog(LOG_ERR, fmt, ap); - closelog(); - } else { - vwarnx(fmt, ap); - } - va_end(ap); - exit(1); - /*NOTREACHED*/ -} - -usage() -{ - if (mfs) { - fprintf(stderr, - "usage: %s [ -fsoptions ] special-device mount-point\n", - progname); - } else - fprintf(stderr, - "usage: %s [ -fsoptions ] special-device%s\n", - progname, -#ifdef COMPAT - " [device-type]"); -#else - ""); -#endif - fprintf(stderr, "where fsoptions are:\n"); - fprintf(stderr, - "\t-N do not create file system, just print out parameters\n"); - fprintf(stderr, "\t-O create a 4.3BSD format filesystem\n"); - fprintf(stderr, "\t-S sector size\n"); -#ifdef COMPAT - fprintf(stderr, "\t-T disktype\n"); -#endif - fprintf(stderr, "\t-a maximum contiguous blocks\n"); - fprintf(stderr, "\t-b block size\n"); - fprintf(stderr, "\t-c cylinders/group\n"); - fprintf(stderr, "\t-d rotational delay between contiguous blocks\n"); - fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n"); - fprintf(stderr, "\t-f frag size\n"); - fprintf(stderr, "\t-i number of bytes per inode\n"); - fprintf(stderr, "\t-k sector 0 skew, per track\n"); - fprintf(stderr, "\t-l hardware sector interleave\n"); - fprintf(stderr, "\t-m minimum free space %%\n"); - fprintf(stderr, "\t-n number of distinguished rotational positions\n"); - fprintf(stderr, "\t-o optimization preference (`space' or `time')\n"); - fprintf(stderr, "\t-p spare sectors per track\n"); - fprintf(stderr, "\t-s file system size (sectors)\n"); - fprintf(stderr, "\t-r revolutions/minute\n"); - fprintf(stderr, "\t-t tracks/cylinder\n"); - fprintf(stderr, "\t-u sectors/track\n"); - fprintf(stderr, "\t-x spare sectors per cylinder\n"); - exit(1); -} diff --git a/ufs-utils/stati.c b/ufs-utils/stati.c deleted file mode 100644 index ba545bf2..00000000 --- a/ufs-utils/stati.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Rich $alz of BBN Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char copyright[] = -"@(#) Copyright (c) 1990, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; - -static char copyright[] __attribute__ ((unused)); -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)clri.c 8.2 (Berkeley) 9/23/93"; -static char sccsid[] __attribute__ ((unused)); -#endif /* not lint */ - -/* Modified by Michael I. Bushnell for GNU Hurd. */ - -#include <sys/param.h> -#include <sys/time.h> -#include <sys/stat.h> - -#include "../ufs/dinode.h" -#include "../ufs/fs.h" - -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <time.h> -#include <unistd.h> -#include <pwd.h> -#include <grp.h> - -#define MAXPHYS (64 * 1024) -#define DEV_BSIZE 512 - -/* Returns a nice representation of a file mode in a static buffer. */ -static char * -mode_rep (unsigned short mode) -{ - static char buf[30]; - char *p = buf; - - void add_perms (int shift, unsigned sid_mask) - { - unsigned short smode = mode << shift; - *p++ = (smode & S_IREAD) ? 'r' : '-'; - *p++ = (smode & S_IWRITE) ? 'w' : '-'; - *p++ = (smode & S_IEXEC) ? ((mode & sid_mask) ? 's' : 'x') : '-'; - } - - switch (mode & S_IFMT) - { - case S_IFREG: *p++ = '-'; break; - case S_IFDIR: *p++ = 'd'; break; - case S_IFCHR: *p++ = 'c'; break; - case S_IFBLK: *p++ = 'b'; break; - case S_IFLNK: *p++ = 'l'; break; - case S_IFSOCK:*p++ = 'p'; break; - case S_IFIFO: *p++ = 'f'; break; - default: *p++ = '?'; - } - - add_perms (0, S_ISUID); - add_perms (3, S_ISGID); - add_perms (6, 0); - - snprintf (p, buf + sizeof buf - p, " [0%0o]", mode); - - return buf; -} - -/* Returns a nice representation of a struct timespec in a static buffer. */ -static char * -timespec_rep (struct timespec *ts) -{ - static char buf[200]; - char *p = buf; - if (ts->tv_sec || ts->tv_nsec) - { - time_t time = ts->tv_sec; - strcpy (buf, ctime (&time)); - p += strlen (buf); - if (p[-1] == '\n') - p--; - *p++ = ' '; - } - snprintf (p, buf + sizeof buf - p, "[%ld, %ld]", ts->tv_sec, ts->tv_nsec); - return buf; -} - -/* Returns a nice representation of a uid in a static buffer. */ -static char * -uid_rep (uid_t uid) -{ - static char buf[200]; - struct passwd *pw = getpwuid (uid); - if (pw) - snprintf (buf, sizeof buf, "%d(%s)", uid, pw->pw_name); - else - snprintf (buf, sizeof buf, "%d", uid); - return buf; -} - -/* Returns a nice representation of a gid in a static buffer. */ -static char * -gid_rep (gid_t gid) -{ - static char buf[200]; - struct group *gr = getgrgid (gid); - if (gr) - snprintf (buf, sizeof buf, "%d(%s)", gid, gr->gr_name); - else - snprintf (buf, sizeof buf, "%d", gid); - return buf; -} - -int -main(argc, argv) - int argc; - char *argv[]; -{ - register struct fs *sbp; - register struct dinode *ip; - register int fd; - struct dinode ibuf[MAXBSIZE / sizeof (struct dinode)]; - long bsize; - off_t offset; - int inonum; - char *fs, sblock[SBSIZE]; - - if (argc < 3) { - (void)fprintf(stderr, "usage: stati filesystem inode ...\n"); - exit(1); - } - - fs = *++argv; - - /* get the superblock. */ - if ((fd = open(fs, O_RDWR, 0)) < 0) - { - perror (fs); - exit (1); - } - if (lseek(fd, (off_t)(SBLOCK * DEV_BSIZE), SEEK_SET) < 0) - { - perror (fs); - exit (1); - } - if (read(fd, sblock, sizeof(sblock)) != sizeof(sblock)) { - (void)fprintf(stderr, - "stati: %s: can't read the superblock.\n", fs); - exit(1); - } - - sbp = (struct fs *)sblock; - if (sbp->fs_magic != FS_MAGIC) { - (void)fprintf(stderr, - "stati: %s: superblock magic number 0x%lux, not 0x%x.\n", - fs, sbp->fs_magic, FS_MAGIC); - exit(1); - } - bsize = sbp->fs_bsize; - - /* remaining arguments are inode numbers. */ - while (*++argv) { - int i; - - /* get the inode number. */ - if ((inonum = atoi(*argv)) <= 0) { - (void)fprintf(stderr, - "stati: %s is not a valid inode number.\n", *argv); - exit(1); - } - - /* read in the appropriate block. */ - offset = ino_to_fsba(sbp, inonum); /* inode to fs blk */ - offset = fsbtodb(sbp, offset); /* fs blk disk blk */ - offset *= DEV_BSIZE; /* disk blk to bytes */ - - /* seek and read the block */ - if (lseek(fd, offset, SEEK_SET) < 0) - { - perror (fs); - exit (1); - } - if (read(fd, ibuf, bsize) != bsize) - { - perror (fs); - exit (1); - } - - /* get the inode within the block. */ - ip = &ibuf[ino_to_fsbo(sbp, inonum)]; - - if (argc > 3) - printf ("inode: %d\n", inonum); - - printf ("mode: %s\n", mode_rep (ip->di_model)); - printf ("nlink: %d\n", ip->di_nlink); - printf ("size: %qd\n", ip->di_size); - printf ("atime: %s\n", timespec_rep (&ip->di_atime)); - printf ("mtime: %s\n", timespec_rep (&ip->di_mtime)); - printf ("ctime: %s\n", timespec_rep (&ip->di_ctime)); - printf ("flags: %#lx\n", ip->di_flags); - printf ("blocks: %ld\n", ip->di_blocks); - printf ("gener: %ld\n", ip->di_gen); - printf ("uid: %s\n", uid_rep (ip->di_uid)); - printf ("gid: %s\n", gid_rep (ip->di_gid)); - printf ("dblks: "); - for (i = 0; i < NDADDR; i++) - printf ("%s%ld", (i == 0 ? "" : ", "), ip->di_db[i]); - putchar ('\n'); - printf ("iblks: "); - for (i = 0; i < NIADDR; i++) - printf ("%s%ld", (i == 0 ? "" : ", "), ip->di_ib[i]); - putchar ('\n'); - printf ("trans: %ld\n", ip->di_trans); - - if (argv[1]) - putchar ('\n'); - } - (void)close(fd); - exit(0); -} diff --git a/ufs/Makefile b/ufs/Makefile deleted file mode 100644 index 02cf38ba..00000000 --- a/ufs/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# Makefile for ufs -# -# Copyright (C) 1994,95,96,99,2000,02 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 := ufs -makemode := server - -target = ufs -SRCS = alloc.c consts.c dir.c hyper.c inode.c main.c pager.c \ - sizes.c subr.c tables.c bmap.c pokeloc.c -LCLHDRS = ufs.h fs.h dinode.h dir.h - -OBJS = $(SRCS:.c=.o) -HURDLIBS = diskfs iohelp fshelp store pager threads ports ihash shouldbeinlibc - -include ../Makeconf - -ufs.static: $(boot-store-types:%=../libstore/libstore_%.a) diff --git a/ufs/alloc.c b/ufs/alloc.c deleted file mode 100644 index d8f92255..00000000 --- a/ufs/alloc.c +++ /dev/null @@ -1,1703 +0,0 @@ -/* Disk allocation routines - Copyright (C) 1993,94,95,96,98,2002 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. */ - -/* Modified from UCB by Michael I. Bushnell. */ -/* - * Copyright (c) 1982, 1986, 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ffs_alloc.c 8.8 (Berkeley) 2/21/94 - */ - -#include "ufs.h" -#include <stdio.h> -#include <string.h> - - -/* These don't work *at all* here; don't even try setting them. */ -#undef DIAGNOSTIC -#undef QUOTA - -extern u_long nextgennumber; - -spin_lock_t alloclock = SPIN_LOCK_INITIALIZER; - -/* Forward declarations */ -static u_long ffs_hashalloc (struct node *, int, long, int, - u_long (*)(struct node *, int, daddr_t, int)); -static u_long ffs_alloccg (struct node *, int, daddr_t, int); -static daddr_t ffs_fragextend (struct node *, int, long, int, int); -static ino_t ffs_dirpref (struct fs *); -static u_long ffs_nodealloccg (struct node *, int, daddr_t, int); -static daddr_t ffs_alloccgblk (struct fs *, struct cg *, daddr_t); -static daddr_t ffs_mapsearch (struct fs *, struct cg *, daddr_t, int); -static void ffs_clusteracct (struct fs *, struct cg *, daddr_t, int); - -/* Sync all allocation information and nod eNP if diskfs_synchronous. */ -inline void -alloc_sync (struct node *np) -{ - if (diskfs_synchronous) - { - if (np) - diskfs_node_update (np, 1); - copy_sblock (); - diskfs_set_hypermetadata (1, 0); - sync_disk (1); - } -} - -/* Byteswap everything in CGP. */ -void -swab_cg (struct cg *cg) -{ - int i, j; - - if (swab_long (cg->cg_magic) == CG_MAGIC - || cg->cg_magic == CG_MAGIC) - { - cg->cg_magic = swab_long (cg->cg_magic); - cg->cg_time = swab_long (cg->cg_time); - cg->cg_cgx = swab_long (cg->cg_cgx); - cg->cg_ncyl = swab_short (cg->cg_ncyl); - cg->cg_niblk = swab_short (cg->cg_niblk); - cg->cg_cs.cs_ndir = swab_long (cg->cg_cs.cs_ndir); - cg->cg_cs.cs_nbfree = swab_long (cg->cg_cs.cs_nbfree); - cg->cg_cs.cs_nifree = swab_long (cg->cg_cs.cs_nifree); - cg->cg_cs.cs_nffree = swab_long (cg->cg_cs.cs_nffree); - cg->cg_rotor = swab_long (cg->cg_rotor); - cg->cg_irotor = swab_long (cg->cg_irotor); - for (i = 0; i < MAXFRAG; i++) - cg->cg_frsum[i] = swab_long (cg->cg_frsum[i]); - cg->cg_btotoff = swab_long (cg->cg_btotoff); - cg->cg_boff = swab_long (cg->cg_boff); - cg->cg_iusedoff = swab_long (cg->cg_iusedoff); - cg->cg_freeoff = swab_long (cg->cg_freeoff); - cg->cg_nextfreeoff = swab_long (cg->cg_nextfreeoff); - cg->cg_clustersumoff = swab_long (cg->cg_clustersumoff); - cg->cg_clusteroff = swab_long (cg->cg_clusteroff); - cg->cg_nclusterblks = swab_long (cg->cg_nclusterblks); - - /* blktot map */ - for (i = 0; i < cg->cg_ncyl; i++) - cg_blktot(cg)[i] = swab_long (cg_blktot(cg)[i]); - - /* blks map */ - for (i = 0; i < cg->cg_ncyl; i++) - for (j = 0; j < sblock->fs_nrpos; j++) - cg_blks(sblock, cg, i)[j] = swab_short (cg_blks (sblock, cg, i)[j]); - - for (i = 0; i < sblock->fs_contigsumsize; i++) - cg_clustersum(cg)[i] = swab_long (cg_clustersum(cg)[i]); - - /* inosused, blksfree, and cg_clustersfree are char arrays */ - } - else - { - /* Old format cylinder group... */ - struct ocg *ocg = (struct ocg *) cg; - - if (swab_long (ocg->cg_magic) != CG_MAGIC - && ocg->cg_magic != CG_MAGIC) - return; - - ocg->cg_time = swab_long (ocg->cg_time); - ocg->cg_cgx = swab_long (ocg->cg_cgx); - ocg->cg_ncyl = swab_short (ocg->cg_ncyl); - ocg->cg_niblk = swab_short (ocg->cg_niblk); - ocg->cg_ndblk = swab_long (ocg->cg_ndblk); - ocg->cg_cs.cs_ndir = swab_long (ocg->cg_cs.cs_ndir); - ocg->cg_cs.cs_nbfree = swab_long (ocg->cg_cs.cs_nbfree); - ocg->cg_cs.cs_nifree = swab_long (ocg->cg_cs.cs_nifree); - ocg->cg_cs.cs_nffree = swab_long (ocg->cg_cs.cs_nffree); - ocg->cg_rotor = swab_long (ocg->cg_rotor); - ocg->cg_frotor = swab_long (ocg->cg_frotor); - ocg->cg_irotor = swab_long (ocg->cg_irotor); - for (i = 0; i < 8; i++) - ocg->cg_frsum[i] = swab_long (ocg->cg_frsum[i]); - for (i = 0; i < 32; i++) - ocg->cg_btot[i] = swab_long (ocg->cg_btot[i]); - for (i = 0; i < 32; i++) - for (j = 0; j < 8; j++) - ocg->cg_b[i][j] = swab_short (ocg->cg_b[i][j]); - ocg->cg_magic = swab_long (ocg->cg_magic); - } -} - - -/* Read cylinder group indexed CG. Set *CGPP to point at it. - Return 1 if caller should call release_cgp when we're done with it; - otherwise zero. */ -int -read_cg (int cg, struct cg **cgpp) -{ - struct cg *diskcg = cg_locate (cg); - - if (swab_disk) - { - *cgpp = malloc (sblock->fs_cgsize); - bcopy (diskcg, *cgpp, sblock->fs_cgsize); - swab_cg (*cgpp); - return 1; - } - else - { - *cgpp = diskcg; - return 0; - } -} - -/* Caller of read_cg is done with cg; write it back to disk (swapping it - along the way) and free the memory allocated in read_cg. */ -void -release_cg (struct cg *cgp) -{ - int cgx = cgp->cg_cgx; - swab_cg (cgp); - bcopy (cgp, cg_locate (cgx), sblock->fs_cgsize); - free (cgp); -} - - -/* - * Allocate a block in the file system. - * - * The size of the requested block is given, which must be some - * multiple of fs_fsize and <= fs_bsize. - * A preference may be optionally specified. If a preference is given - * the following hierarchy is used to allocate a block: - * 1) allocate the requested block. - * 2) allocate a rotationally optimal block in the same cylinder. - * 3) allocate a block in the same cylinder group. - * 4) quadradically rehash into other cylinder groups, until an - * available block is located. - * If no block preference is given the following hierarchy is used - * to allocate a block: - * 1) allocate a block in the cylinder group that contains the - * inode for the file. - * 2) quadradically rehash into other cylinder groups, until an - * available block is located. - */ -error_t -ffs_alloc(register struct node *np, - daddr_t lbn, - daddr_t bpref, - int size, - daddr_t *bnp, - struct protid *cred) -{ - register struct fs *fs; - daddr_t bno; - int cg; - - *bnp = 0; - fs = sblock; -#ifdef DIAGNOSTIC - if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0) { - printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n", - ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt); - panic("ffs_alloc: bad size"); - } - assert (cred); -#endif /* DIAGNOSTIC */ - spin_lock (&alloclock); - if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0) - goto nospace; - if (cred && !idvec_contains (cred->user->uids, 0) - && freespace(fs, fs->fs_minfree) <= 0) - goto nospace; -#ifdef QUOTA - if (error = chkdq(ip, (long)btodb(size), cred, 0)) - return (error); -#endif - if (bpref >= fs->fs_size) - bpref = 0; - if (bpref == 0) - cg = ino_to_cg(fs, np->dn->number); - else - cg = dtog(fs, bpref); - bno = (daddr_t)ffs_hashalloc(np, cg, (long)bpref, size, - (u_long (*)())ffs_alloccg); - if (bno > 0) { - spin_unlock (&alloclock); - np->dn_stat.st_blocks += btodb(size); - np->dn_set_ctime = 1; - np->dn_set_mtime = 1; - *bnp = bno; - alloc_sync (np); - return (0); - } -#ifdef QUOTA - /* - * Restore user's disk quota because allocation failed. - */ - (void) chkdq(ip, (long)-btodb(size), cred, FORCE); -#endif -nospace: - spin_unlock (&alloclock); - printf ("file system full"); -/* ffs_fserr(fs, cred->cr_uid, "file system full"); */ -/* uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); */ - return (ENOSPC); -} - -/* - * Reallocate a fragment to a bigger size - * - * The number and size of the old block is given, and a preference - * and new size is also specified. The allocator attempts to extend - * the original block. Failing that, the regular block allocator is - * invoked to get an appropriate block. - */ -error_t -ffs_realloccg(register struct node *np, - daddr_t lbprev, - volatile daddr_t bpref, - int osize, - int nsize, - daddr_t *pbn, - struct protid *cred) -{ - register struct fs *fs; - int cg, error; - volatile int request; - daddr_t bprev, bno; - - *pbn = 0; - fs = sblock; -#ifdef DIAGNOSTIC - if ((u_int)osize > fs->fs_bsize || fragoff(fs, osize) != 0 || - (u_int)nsize > fs->fs_bsize || fragoff(fs, nsize) != 0) { - printf( - "dev = 0x%x, bsize = %d, osize = %d, nsize = %d, fs = %s\n", - ip->i_dev, fs->fs_bsize, osize, nsize, fs->fs_fsmnt); - panic("ffs_realloccg: bad size"); - } - if (cred == NOCRED) - panic("ffs_realloccg: missing credential\n"); -#endif /* DIAGNOSTIC */ - - spin_lock (&alloclock); - - if (!idvec_contains (cred->user->uids, 0) - && freespace(fs, fs->fs_minfree) <= 0) - goto nospace; - error = diskfs_catch_exception (); - if (error) - return error; - bprev = read_disk_entry ((dino (np->dn->number))->di_db[lbprev]); - diskfs_end_catch_exception (); - assert ("old block not allocated" && bprev); - -#if 0 /* Not needed in GNU Hurd ufs */ - /* - * Allocate the extra space in the buffer. - */ - if (error = bread(ITOV(ip), lbprev, osize, NOCRED, &bp)) { - brelse(bp); - return (error); - } -#ifdef QUOTA - if (error = chkdq(ip, (long)btodb(nsize - osize), cred, 0)) { - brelse(bp); - return (error); - } -#endif -#endif /* 0 */ - - /* - * Check for extension in the existing location. - */ - cg = dtog(fs, bprev); - bno = ffs_fragextend(np, cg, (long)bprev, osize, nsize); - if (bno) { - assert (bno == bprev); - spin_unlock (&alloclock); - np->dn_stat.st_blocks += btodb(nsize - osize); - np->dn_set_ctime = 1; - np->dn_set_mtime = 1; - *pbn = bno; -#if 0 /* Not done this way in GNU Hurd ufs. */ - allocbuf(bp, nsize); - bp->b_flags |= B_DONE; - bzero((char *)bp->b_data + osize, (u_int)nsize - osize); - *bpp = bp; -#endif - alloc_sync (np); - return (0); - } - /* - * Allocate a new disk location. - */ - if (bpref >= fs->fs_size) - bpref = 0; - switch ((int)fs->fs_optim) { - case FS_OPTSPACE: - /* - * Allocate an exact sized fragment. Although this makes - * best use of space, we will waste time relocating it if - * the file continues to grow. If the fragmentation is - * less than half of the minimum free reserve, we choose - * to begin optimizing for time. - */ - request = nsize; - if (fs->fs_minfree < 5 || - fs->fs_cstotal.cs_nffree > - fs->fs_dsize * fs->fs_minfree / (2 * 100)) - break; - printf ("%s: optimization changed from SPACE to TIME\n", - fs->fs_fsmnt); - fs->fs_optim = FS_OPTTIME; - break; - case FS_OPTTIME: - /* - * At this point we have discovered a file that is trying to - * grow a small fragment to a larger fragment. To save time, - * we allocate a full sized block, then free the unused portion. - * If the file continues to grow, the `ffs_fragextend' call - * above will be able to grow it in place without further - * copying. If aberrant programs cause disk fragmentation to - * grow within 2% of the free reserve, we choose to begin - * optimizing for space. - */ - request = fs->fs_bsize; - if (fs->fs_cstotal.cs_nffree < - fs->fs_dsize * (fs->fs_minfree - 2) / 100) - break; - printf ("%s: optimization changed from TIME to SPACE\n", - fs->fs_fsmnt); - fs->fs_optim = FS_OPTSPACE; - break; - default: - assert (0); - /* NOTREACHED */ - } - bno = (daddr_t)ffs_hashalloc(np, cg, (long)bpref, request, - (u_long (*)())ffs_alloccg); - if (bno > 0) { -#if 0 /* Not necessary in GNU Hurd ufs */ - bp->b_blkno = fsbtodb(fs, bno); - (void) vnode_pager_uncache(ITOV(ip)); -#endif -/* Commented out here for Hurd; we don't want to free this until we've - saved the old contents. Callers are responsible for freeing the - block when they are done with it. */ -/* ffs_blkfree(np, bprev, (long)osize); */ - if (nsize < request) - ffs_blkfree(np, bno + numfrags(fs, nsize), - (long)(request - nsize)); - spin_unlock (&alloclock); - np->dn_stat.st_blocks += btodb(nsize - osize); - np->dn_set_mtime = 1; - np->dn_set_ctime = 1; - *pbn = bno; -#if 0 /* Not done this way in GNU Hurd ufs */ - allocbuf(bp, nsize); - bp->b_flags |= B_DONE; - bzero((char *)bp->b_data + osize, (u_int)nsize - osize); - *bpp = bp; -#endif /* 0 */ - alloc_sync (np); - return (0); - } -#ifdef QUOTA - /* - * Restore user's disk quota because allocation failed. - */ - (void) chkdq(ip, (long)-btodb(nsize - osize), cred, FORCE); -#endif -#if 0 /* Not necesarry in GNU Hurd ufs */ - brelse(bp); -#endif -nospace: - /* - * no space available - */ - spin_unlock (&alloclock); - printf ("file system full"); -/* ffs_fserr(fs, cred->cr_uid, "file system full"); */ -/* uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); */ - return (ENOSPC); -} - -#if 0 /* Not used (yet?) in GNU Hurd ufs */ -/* - * Reallocate a sequence of blocks into a contiguous sequence of blocks. - * - * The vnode and an array of buffer pointers for a range of sequential - * logical blocks to be made contiguous is given. The allocator attempts - * to find a range of sequential blocks starting as close as possible to - * an fs_rotdelay offset from the end of the allocation for the logical - * block immediately preceding the current range. If successful, the - * physical block numbers in the buffer pointers and in the inode are - * changed to reflect the new allocation. If unsuccessful, the allocation - * is left unchanged. The success in doing the reallocation is returned. - * Note that the error return is not reflected back to the user. Rather - * the previous block allocation will be used. - */ -#include <sys/sysctl.h> -int doasyncfree = 1; -struct ctldebug debug14 = { "doasyncfree", &doasyncfree }; -int -ffs_reallocblks(ap) - struct vop_reallocblks_args /* { - struct vnode *a_vp; - struct cluster_save *a_buflist; - } */ *ap; -{ - struct fs *fs; - struct inode *ip; - struct vnode *vp; - struct buf *sbp, *ebp; - daddr_t *bap, *sbap, *ebap; - struct cluster_save *buflist; - daddr_t start_lbn, end_lbn, soff, eoff, newblk, blkno; - struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp; - int i, len, start_lvl, end_lvl, pref, ssize; - - vp = ap->a_vp; - ip = VTOI(vp); - fs = ip->i_fs; - if (fs->fs_contigsumsize <= 0) - return (ENOSPC); - buflist = ap->a_buflist; - len = buflist->bs_nchildren; - start_lbn = buflist->bs_children[0]->b_lblkno; - end_lbn = start_lbn + len - 1; -#ifdef DIAGNOSTIC - for (i = 1; i < len; i++) - if (buflist->bs_children[i]->b_lblkno != start_lbn + i) - panic("ffs_reallocblks: non-cluster"); -#endif - /* - * If the latest allocation is in a new cylinder group, assume that - * the filesystem has decided to move and do not force it back to - * the previous cylinder group. - */ - if (dtog(fs, dbtofsb(fs, buflist->bs_children[0]->b_blkno)) != - dtog(fs, dbtofsb(fs, buflist->bs_children[len - 1]->b_blkno))) - return (ENOSPC); - if (ufs_getlbns(vp, start_lbn, start_ap, &start_lvl) || - ufs_getlbns(vp, end_lbn, end_ap, &end_lvl)) - return (ENOSPC); - /* - * Get the starting offset and block map for the first block. - */ - if (start_lvl == 0) { - sbap = &ip->i_db[0]; - soff = start_lbn; - } else { - idp = &start_ap[start_lvl - 1]; - if (bread(vp, idp->in_lbn, (int)fs->fs_bsize, NOCRED, &sbp)) { - brelse(sbp); - return (ENOSPC); - } - sbap = (daddr_t *)sbp->b_data; - soff = idp->in_off; - } - /* - * Find the preferred location for the cluster. - */ - pref = ffs_blkpref(ip, start_lbn, soff, sbap); - /* - * If the block range spans two block maps, get the second map. - */ - if (end_lvl == 0 || (idp = &end_ap[end_lvl - 1])->in_off + 1 >= len) { - ssize = len; - } else { -#ifdef DIAGNOSTIC - if (start_ap[start_lvl-1].in_lbn == idp->in_lbn) - panic("ffs_reallocblk: start == end"); -#endif - ssize = len - (idp->in_off + 1); - if (bread(vp, idp->in_lbn, (int)fs->fs_bsize, NOCRED, &ebp)) - goto fail; - ebap = (daddr_t *)ebp->b_data; - } - /* - * Search the block map looking for an allocation of the desired size. - */ - if ((newblk = (daddr_t)ffs_hashalloc(ip, dtog(fs, pref), (long)pref, - len, (u_long (*)())ffs_clusteralloc)) == 0) - goto fail; - /* - * We have found a new contiguous block. - * - * First we have to replace the old block pointers with the new - * block pointers in the inode and indirect blocks associated - * with the file. - */ - blkno = newblk; - for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->fs_frag) { - if (i == ssize) - bap = ebap; -#ifdef DIAGNOSTIC - if (buflist->bs_children[i]->b_blkno != fsbtodb(fs, *bap)) - panic("ffs_reallocblks: alloc mismatch"); -#endif - *bap++ = blkno; - } - /* - * Next we must write out the modified inode and indirect blocks. - * For strict correctness, the writes should be synchronous since - * the old block values may have been written to disk. In practise - * they are almost never written, but if we are concerned about - * strict correctness, the `doasyncfree' flag should be set to zero. - * - * The test on `doasyncfree' should be changed to test a flag - * that shows whether the associated buffers and inodes have - * been written. The flag should be set when the cluster is - * started and cleared whenever the buffer or inode is flushed. - * We can then check below to see if it is set, and do the - * synchronous write only when it has been cleared. - */ - if (sbap != &ip->i_db[0]) { - if (doasyncfree) - bdwrite(sbp); - else - bwrite(sbp); - } else { - ip->i_flag |= IN_CHANGE | IN_UPDATE; - if (!doasyncfree) - VOP_UPDATE(vp, &time, &time, MNT_WAIT); - } - if (ssize < len) - if (doasyncfree) - bdwrite(ebp); - else - bwrite(ebp); - /* - * Last, free the old blocks and assign the new blocks to the buffers. - */ - for (blkno = newblk, i = 0; i < len; i++, blkno += fs->fs_frag) { - ffs_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno), - fs->fs_bsize); - buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno); - } - return (0); - -fail: - if (ssize < len) - brelse(ebp); - if (sbap != &ip->i_db[0]) - brelse(sbp); - return (ENOSPC); -} -#endif /* 0 */ - -/* - * Allocate an inode in the file system. - * - * If allocating a directory, use ffs_dirpref to select the inode. - * If allocating in a directory, the following hierarchy is followed: - * 1) allocate the preferred inode. - * 2) allocate an inode in the same cylinder group. - * 3) quadradically rehash into other cylinder groups, until an - * available inode is located. - * If no inode preference is given the following hierarchy is used - * to allocate an inode: - * 1) allocate an inode in cylinder group 0. - * 2) quadradically rehash into other cylinder groups, until an - * available inode is located. - */ -/* This is now the diskfs_alloc_node callback from the diskfs library - (described in <hurd/diskfs.h>). It used to be ffs_valloc in BSD. */ -error_t -diskfs_alloc_node (struct node *dir, - mode_t mode, - struct node **npp) -{ - register struct fs *fs; - struct node *np; - ino_t ino, ipref; - int cg, error; - int sex; - - fs = sblock; - - - spin_lock (&alloclock); - - if (fs->fs_cstotal.cs_nifree == 0) - { - spin_unlock (&alloclock); - goto noinodes; - } - - if (S_ISDIR (mode)) - ipref = ffs_dirpref(fs); - else - ipref = dir->dn->number; - - if (ipref >= fs->fs_ncg * fs->fs_ipg) - ipref = 0; - cg = ino_to_cg(fs, ipref); - ino = (ino_t)ffs_hashalloc(dir, cg, (long)ipref, - mode, ffs_nodealloccg); - spin_unlock (&alloclock); - if (ino == 0) - goto noinodes; - error = diskfs_cached_lookup (ino, &np); - assert ("duplicate allocation" && !np->dn_stat.st_mode); - assert (! (np->dn_stat.st_mode & S_IPTRANS)); - if (np->dn_stat.st_blocks) { - printf("free inode %Ld had %Ld blocks\n", - ino, np->dn_stat.st_blocks); - np->dn_stat.st_blocks = 0; - np->dn_set_ctime = 1; - } - np->dn_stat.st_flags = 0; - /* - * Set up a new generation number for this inode. - */ - spin_lock (&gennumberlock); - sex = diskfs_mtime->seconds; - if (++nextgennumber < (u_long)sex) - nextgennumber = sex; - np->dn_stat.st_gen = nextgennumber; - spin_unlock (&gennumberlock); - - *npp = np; - alloc_sync (np); - return (0); -noinodes: - printf ("out of inodes"); -/* ffs_fserr(fs, ap->a_cred->cr_uid, "out of inodes"); */ -/* uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt);*/ - return (ENOSPC); -} - -/* - * Find a cylinder to place a directory. - * - * The policy implemented by this algorithm is to select from - * among those cylinder groups with above the average number of - * free inodes, the one with the smallest number of directories. - */ -static ino_t -ffs_dirpref(register struct fs *fs) -{ - int cg, minndir, mincg, avgifree; - - avgifree = fs->fs_cstotal.cs_nifree / fs->fs_ncg; - minndir = fs->fs_ipg; - mincg = 0; - for (cg = 0; cg < fs->fs_ncg; cg++) - if (csum[cg].cs_ndir < minndir && - csum[cg].cs_nifree >= avgifree) { - mincg = cg; - minndir = csum[cg].cs_ndir; - } - return ((ino_t)(fs->fs_ipg * mincg)); -} - -/* - * Select the desired position for the next block in a file. The file is - * logically divided into sections. The first section is composed of the - * direct blocks. Each additional section contains fs_maxbpg blocks. - * - * If no blocks have been allocated in the first section, the policy is to - * request a block in the same cylinder group as the inode that describes - * the file. If no blocks have been allocated in any other section, the - * policy is to place the section in a cylinder group with a greater than - * average number of free blocks. An appropriate cylinder group is found - * by using a rotor that sweeps the cylinder groups. When a new group of - * blocks is needed, the sweep begins in the cylinder group following the - * cylinder group from which the previous allocation was made. The sweep - * continues until a cylinder group with greater than the average number - * of free blocks is found. If the allocation is for the first block in an - * indirect block, the information on the previous allocation is unavailable; - * here a best guess is made based upon the logical block number being - * allocated. - * - * If a section is already partially allocated, the policy is to - * contiguously allocate fs_maxcontig blocks. The end of one of these - * contiguous blocks and the beginning of the next is physically separated - * so that the disk head will be in transit between them for at least - * fs_rotdelay milliseconds. This is to allow time for the processor to - * schedule another I/O transfer. - */ -daddr_t -ffs_blkpref(struct node *np, - daddr_t lbn, - int indx, - daddr_t *bap) -{ - register struct fs *fs; - register int cg; - int avgbfree, startcg; - daddr_t nextblk; - - fs = sblock; - spin_lock (&alloclock); - if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) { - if (lbn < NDADDR) { - cg = ino_to_cg(fs, np->dn->number); - spin_unlock (&alloclock); - return (fs->fs_fpg * cg + fs->fs_frag); - } - /* - * Find a cylinder with greater than average number of - * unused data blocks. - */ - if (indx == 0 || bap[indx - 1] == 0) - startcg = - (ino_to_cg(fs, np->dn->number) - + lbn / fs->fs_maxbpg); - else - startcg = dtog(fs, - read_disk_entry (bap[indx - 1])) + 1; - startcg %= fs->fs_ncg; - avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg; - for (cg = startcg; cg < fs->fs_ncg; cg++) - if (csum[cg].cs_nbfree >= avgbfree) { - fs->fs_cgrotor = cg; - spin_unlock (&alloclock); - return (fs->fs_fpg * cg + fs->fs_frag); - } - for (cg = 0; cg <= startcg; cg++) - if (csum[cg].cs_nbfree >= avgbfree) { - fs->fs_cgrotor = cg; - spin_unlock (&alloclock); - return (fs->fs_fpg * cg + fs->fs_frag); - } - spin_unlock (&alloclock); - return 0; - } - spin_unlock (&alloclock); - /* - * One or more previous blocks have been laid out. If less - * than fs_maxcontig previous blocks are contiguous, the - * next block is requested contiguously, otherwise it is - * requested rotationally delayed by fs_rotdelay milliseconds. - */ - nextblk = read_disk_entry (bap[indx - 1]) + fs->fs_frag; - if (indx < fs->fs_maxcontig - || (read_disk_entry (bap[indx - fs->fs_maxcontig]) + - blkstofrags(fs, fs->fs_maxcontig) != nextblk)) - { - return (nextblk); - } - if (fs->fs_rotdelay != 0) - /* - * Here we convert ms of delay to frags as: - * (frags) = (ms) * (rev/sec) * (sect/rev) / - * ((sect/frag) * (ms/sec)) - * then round up to the next block. - */ - nextblk += roundup(fs->fs_rotdelay * fs->fs_rps * fs->fs_nsect / - (NSPF(fs) * 1000), fs->fs_frag); - return (nextblk); -} - -/* - * Implement the cylinder overflow algorithm. - * - * The policy implemented by this algorithm is: - * 1) allocate the block in its requested cylinder group. - * 2) quadradically rehash on the cylinder group number. - * 3) brute force search for a free block. - */ -/*VARARGS5*/ -static u_long -ffs_hashalloc(struct node *np, - int cg, - long pref, - int size, /* size for data blocks, mode for inodes */ - u_long (*allocator)()) -{ - register struct fs *fs; - long result; - int i, icg = cg; - - fs = sblock; - /* - * 1: preferred cylinder group - */ - result = (*allocator)(np, cg, pref, size); - if (result) - return (result); - /* - * 2: quadratic rehash - */ - for (i = 1; i < fs->fs_ncg; i *= 2) { - cg += i; - if (cg >= fs->fs_ncg) - cg -= fs->fs_ncg; - result = (*allocator)(np, cg, 0, size); - if (result) - return (result); - } - /* - * 3: brute force search - * Note that we start at i == 2, since 0 was checked initially, - * and 1 is always checked in the quadratic rehash. - */ - cg = (icg + 2) % fs->fs_ncg; - for (i = 2; i < fs->fs_ncg; i++) { - result = (*allocator)(np, cg, 0, size); - if (result) - return (result); - cg++; - if (cg == fs->fs_ncg) - cg = 0; - } - return 0; -} - -/* - * Determine whether a fragment can be extended. - * - * Check to see if the necessary fragments are available, and - * if they are, allocate them. - */ -static daddr_t -ffs_fragextend(struct node *np, - int cg, - long bprev, - int osize, - int nsize) -{ - register struct fs *fs; - struct cg *cgp; - long bno; - int frags, bbase; - int i; - int releasecg; - - fs = sblock; - if (csum[cg].cs_nffree < numfrags(fs, nsize - osize)) - return 0; - frags = numfrags(fs, nsize); - bbase = fragnum(fs, bprev); - if (bbase > fragnum(fs, (bprev + frags - 1))) { - /* cannot extend across a block boundary */ - return 0; - } -#if 0 /* Wrong for GNU Hurd ufs */ - error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), - (int)fs->fs_cgsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (NULL); - } - cgp = (struct cg *)bp->b_data; -#else - releasecg = read_cg (cg, &cgp); -#endif - if (!cg_chkmagic(cgp)) { -/* brelse(bp); */ - if (releasecg) - release_cg (cgp); - return 0; - } - cgp->cg_time = diskfs_mtime->seconds; - bno = dtogd(fs, bprev); - for (i = numfrags(fs, osize); i < frags; i++) - if (isclr(cg_blksfree(cgp), bno + i)) { -/* brelse(bp); */ - if (releasecg) - release_cg (cgp); - return 0; - } - /* - * the current fragment can be extended - * deduct the count on fragment being extended into - * increase the count on the remaining fragment (if any) - * allocate the extended piece - */ - for (i = frags; i < fs->fs_frag - bbase; i++) - if (isclr(cg_blksfree(cgp), bno + i)) - break; - cgp->cg_frsum[i - numfrags(fs, osize)]--; - if (i != frags) - cgp->cg_frsum[i - frags]++; - for (i = numfrags(fs, osize); i < frags; i++) { - clrbit(cg_blksfree(cgp), bno + i); - cgp->cg_cs.cs_nffree--; - fs->fs_cstotal.cs_nffree--; - csum[cg].cs_nffree--; - } - if (releasecg) - release_cg (cgp); - record_poke (cgp, sblock->fs_cgsize); - csum_dirty = 1; - sblock_dirty = 1; - fs->fs_fmod = 1; -/* bdwrite(bp); */ - return (bprev); -} - -/* - * Determine whether a block can be allocated. - * - * Check to see if a block of the appropriate size is available, - * and if it is, allocate it. - */ -static u_long -ffs_alloccg(struct node *np, - int cg, - daddr_t bpref, - int size) -{ - register struct fs *fs; - struct cg *cgp; - register int i; - int bno, frags, allocsiz; - int releasecg; - - fs = sblock; - if (csum[cg].cs_nbfree == 0 && size == fs->fs_bsize) - return 0; -#if 0 /* Not this way in GNU Hurd ufs */ - error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), - (int)fs->fs_cgsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (NULL); - } - cgp = (struct cg *)bp->b_data; -#else - releasecg = read_cg (cg, &cgp); -#endif - if (!cg_chkmagic(cgp) || - (cgp->cg_cs.cs_nbfree == 0 && size == fs->fs_bsize)) { -/* brelse(bp); */ - if (releasecg) - release_cg (cgp); - return 0; - } - cgp->cg_time = diskfs_mtime->seconds; - if (size == fs->fs_bsize) { - bno = ffs_alloccgblk(fs, cgp, bpref); -/* bdwrite(bp); */ - if (releasecg) - release_cg (cgp); - return (bno); - } - /* - * check to see if any fragments are already available - * allocsiz is the size which will be allocated, hacking - * it down to a smaller size if necessary - */ - frags = numfrags(fs, size); - for (allocsiz = frags; allocsiz < fs->fs_frag; allocsiz++) - if (cgp->cg_frsum[allocsiz] != 0) - break; - if (allocsiz == fs->fs_frag) { - /* - * no fragments were available, so a block will be - * allocated, and hacked up - */ - if (cgp->cg_cs.cs_nbfree == 0) { -/* brelse(bp); */ - if (releasecg) - release_cg (cgp); - return 0; - } - bno = ffs_alloccgblk(fs, cgp, bpref); - bpref = dtogd(fs, bno); - for (i = frags; i < fs->fs_frag; i++) - setbit(cg_blksfree(cgp), bpref + i); - i = fs->fs_frag - frags; - cgp->cg_cs.cs_nffree += i; - fs->fs_cstotal.cs_nffree += i; - csum[cg].cs_nffree += i; - fs->fs_fmod = 1; - cgp->cg_frsum[i]++; - - if (releasecg) - release_cg (cgp); - record_poke (cgp, sblock->fs_cgsize); - csum_dirty = 1; - sblock_dirty = 1; -/* bdwrite(bp); */ - return (bno); - } - bno = ffs_mapsearch(fs, cgp, bpref, allocsiz); - if (bno < 0) { -/* brelse(bp); */ - if (releasecg) - release_cg (cgp); - return 0; - } - for (i = 0; i < frags; i++) - clrbit(cg_blksfree(cgp), bno + i); - cgp->cg_cs.cs_nffree -= frags; - fs->fs_cstotal.cs_nffree -= frags; - csum[cg].cs_nffree -= frags; - fs->fs_fmod = 1; - cgp->cg_frsum[allocsiz]--; - if (frags != allocsiz) - cgp->cg_frsum[allocsiz - frags]++; - if (releasecg) - release_cg (cgp); - record_poke (cgp, sblock->fs_cgsize); - csum_dirty = 1; - sblock_dirty = 1; -/* bdwrite(bp); */ - return (cg * fs->fs_fpg + bno); -} - -/* - * Allocate a block in a cylinder group. - * - * This algorithm implements the following policy: - * 1) allocate the requested block. - * 2) allocate a rotationally optimal block in the same cylinder. - * 3) allocate the next available block on the block rotor for the - * specified cylinder group. - * Note that this routine only allocates fs_bsize blocks; these - * blocks may be fragmented by the routine that allocates them. - */ -static daddr_t -ffs_alloccgblk(register struct fs *fs, - register struct cg *cgp, - daddr_t bpref) -{ - daddr_t bno, blkno; - int cylno, pos, delta; - short *cylbp; - register int i; - - if (bpref == 0 || dtog(fs, bpref) != cgp->cg_cgx) { - bpref = cgp->cg_rotor; - goto norot; - } - bpref = blknum(fs, bpref); - bpref = dtogd(fs, bpref); - /* - * if the requested block is available, use it - */ - if (ffs_isblock(fs, cg_blksfree(cgp), fragstoblks(fs, bpref))) { - bno = bpref; - goto gotit; - } - /* - * check for a block available on the same cylinder - */ - cylno = cbtocylno(fs, bpref); - if (cg_blktot(cgp)[cylno] == 0) - goto norot; - if (fs->fs_cpc == 0) { - /* - * Block layout information is not available. - * Leaving bpref unchanged means we take the - * next available free block following the one - * we just allocated. Hopefully this will at - * least hit a track cache on drives of unknown - * geometry (e.g. SCSI). - */ - goto norot; - } - /* - * check the summary information to see if a block is - * available in the requested cylinder starting at the - * requested rotational position and proceeding around. - */ - cylbp = cg_blks(fs, cgp, cylno); - pos = cbtorpos(fs, bpref); - for (i = pos; i < fs->fs_nrpos; i++) - if (cylbp[i] > 0) - break; - if (i == fs->fs_nrpos) - for (i = 0; i < pos; i++) - if (cylbp[i] > 0) - break; - if (cylbp[i] > 0) { - /* - * found a rotational position, now find the actual - * block. A panic if none is actually there. - */ - pos = cylno % fs->fs_cpc; - bno = (cylno - pos) * fs->fs_spc / NSPB(fs); - assert (fs_postbl(fs, pos)[i] != -1); - for (i = fs_postbl(fs, pos)[i];; ) { - if (ffs_isblock(fs, cg_blksfree(cgp), bno + i)) { - bno = blkstofrags(fs, (bno + i)); - goto gotit; - } - delta = fs_rotbl(fs)[i]; - if (delta <= 0 || - delta + i > fragstoblks(fs, fs->fs_fpg)) - break; - i += delta; - } - printf("pos = %d, i = %d, fs = %s\n", pos, i, fs->fs_fsmnt); - assert (0); - } -norot: - /* - * no blocks in the requested cylinder, so take next - * available one in this cylinder group. - */ - bno = ffs_mapsearch(fs, cgp, bpref, (int)fs->fs_frag); - if (bno < 0) - return 0; - cgp->cg_rotor = bno; -gotit: - blkno = fragstoblks(fs, bno); - ffs_clrblock(fs, cg_blksfree(cgp), (long)blkno); - ffs_clusteracct(fs, cgp, blkno, -1); - cgp->cg_cs.cs_nbfree--; - fs->fs_cstotal.cs_nbfree--; - csum[cgp->cg_cgx].cs_nbfree--; - cylno = cbtocylno(fs, bno); - cg_blks(fs, cgp, cylno)[cbtorpos(fs, bno)]--; - cg_blktot(cgp)[cylno]--; - fs->fs_fmod = 1; - record_poke (cgp, sblock->fs_cgsize); - csum_dirty = 1; - sblock_dirty = 1; - return (cgp->cg_cgx * fs->fs_fpg + bno); -} - -#if 0 /* Not needed in GNU Hurd ufs (yet?) */ -/* - * Determine whether a cluster can be allocated. - * - * We do not currently check for optimal rotational layout if there - * are multiple choices in the same cylinder group. Instead we just - * take the first one that we find following bpref. - */ -static daddr_t -ffs_clusteralloc(ip, cg, bpref, len) - struct inode *ip; - int cg; - daddr_t bpref; - int len; -{ - register struct fs *fs; - register struct cg *cgp; - struct buf *bp; - int i, run, bno, bit, map; - u_char *mapp; - - fs = ip->i_fs; - if (fs->fs_cs(fs, cg).cs_nbfree < len) - return (NULL); - if (bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, - NOCRED, &bp)) - goto fail; - cgp = (struct cg *)bp->b_data; - if (!cg_chkmagic(cgp)) - goto fail; - /* - * Check to see if a cluster of the needed size (or bigger) is - * available in this cylinder group. - */ - for (i = len; i <= fs->fs_contigsumsize; i++) - if (cg_clustersum(cgp)[i] > 0) - break; - if (i > fs->fs_contigsumsize) - goto fail; - /* - * Search the cluster map to find a big enough cluster. - * We take the first one that we find, even if it is larger - * than we need as we prefer to get one close to the previous - * block allocation. We do not search before the current - * preference point as we do not want to allocate a block - * that is allocated before the previous one (as we will - * then have to wait for another pass of the elevator - * algorithm before it will be read). We prefer to fail and - * be recalled to try an allocation in the next cylinder group. - */ - if (dtog(fs, bpref) != cg) - bpref = 0; - else - bpref = fragstoblks(fs, dtogd(fs, blknum(fs, bpref))); - mapp = &cg_clustersfree(cgp)[bpref / NBBY]; - map = *mapp++; - bit = 1 << (bpref % NBBY); - for (run = 0, i = bpref; i < cgp->cg_nclusterblks; i++) { - if ((map & bit) == 0) { - run = 0; - } else { - run++; - if (run == len) - break; - } - if ((i & (NBBY - 1)) != (NBBY - 1)) { - bit <<= 1; - } else { - map = *mapp++; - bit = 1; - } - } - if (i == cgp->cg_nclusterblks) - goto fail; - /* - * Allocate the cluster that we have found. - */ - bno = cg * fs->fs_fpg + blkstofrags(fs, i - run + 1); - len = blkstofrags(fs, len); - for (i = 0; i < len; i += fs->fs_frag) - if (ffs_alloccgblk(fs, cgp, bno + i) != bno + i) - panic("ffs_clusteralloc: lost block"); - brelse(bp); - return (bno); - -fail: - brelse(bp); - return (0); -} -#endif - -/* - * Determine whether an inode can be allocated. - * - * Check to see if an inode is available, and if it is, - * allocate it using the following policy: - * 1) allocate the requested inode. - * 2) allocate the next available inode after the requested - * inode in the specified cylinder group. - */ -static u_long -ffs_nodealloccg(struct node *np, - int cg, - daddr_t ipref, - int mode) -{ - register struct fs *fs; - struct cg *cgp; - int start, len, loc, map, i; - int releasecg; - - fs = sblock; - if (csum[cg].cs_nifree == 0) - return 0; -#if 0 /* Not this way in GNU Hurd ufs */ - error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), - (int)fs->fs_cgsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (NULL); - } - cgp = (struct cg *)bp->b_data; -#else - releasecg = read_cg (cg, &cgp); -#endif - if (!cg_chkmagic(cgp) || cgp->cg_cs.cs_nifree == 0) { -/* brelse(bp); */ - if (releasecg) - release_cg (cgp); - return 0; - } - cgp->cg_time = diskfs_mtime->seconds; - if (ipref) { - ipref %= fs->fs_ipg; - if (isclr(cg_inosused(cgp), ipref)) - goto gotit; - } - start = cgp->cg_irotor / NBBY; - len = howmany(fs->fs_ipg - cgp->cg_irotor, NBBY); - loc = skpc(0xff, len, &cg_inosused(cgp)[start]); - if (loc == 0) { - len = start + 1; - start = 0; - loc = skpc(0xff, len, &cg_inosused(cgp)[0]); - assert (loc != 0); - } - i = start + len - loc; - map = cg_inosused(cgp)[i]; - ipref = i * NBBY; - for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) { - if ((map & i) == 0) { - cgp->cg_irotor = ipref; - goto gotit; - } - } - assert (0); - /* NOTREACHED */ -gotit: - setbit(cg_inosused(cgp), ipref); - cgp->cg_cs.cs_nifree--; - fs->fs_cstotal.cs_nifree--; - csum[cg].cs_nifree--; - fs->fs_fmod = 1; - if ((mode & IFMT) == IFDIR) { - cgp->cg_cs.cs_ndir++; - fs->fs_cstotal.cs_ndir++; - csum[cg].cs_ndir++; - } - if (releasecg) - release_cg (cgp); - record_poke (cgp, sblock->fs_cgsize); - csum_dirty = 1; - sblock_dirty = 1; -/* bdwrite(bp); */ - return (cg * fs->fs_ipg + ipref); -} - -/* - * Free a block or fragment. - * - * The specified block or fragment is placed back in the - * free map. If a fragment is deallocated, a possible - * block reassembly is checked. - */ -void -ffs_blkfree(register struct node *np, - daddr_t bno, - long size) -{ - register struct fs *fs; - struct cg *cgp; - daddr_t blkno; - int i, cg, blk, frags, bbase; - int releasecg; - - fs = sblock; - assert ((u_int)size <= fs->fs_bsize && !fragoff (fs, size)); - cg = dtog(fs, bno); - if ((u_int)bno >= fs->fs_size) { - printf("bad block %ld, ino %Ld\n", bno, np->dn->number); -/* ffs_fserr(fs, ip->i_uid, "bad block"); */ - return; - } -#if 0 /* Not this way in GNU Hurd ufs */ - error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), - (int)fs->fs_cgsize, NOCRED, &bp); - if (error) { - brelse(bp); - return; - } - cgp = (struct cg *)bp->b_data; -#else - releasecg = read_cg (cg, &cgp); -#endif - if (!cg_chkmagic(cgp)) { -/* brelse(bp); */ - if (releasecg) - release_cg (cgp); - return; - } - cgp->cg_time = diskfs_mtime->seconds; - bno = dtogd(fs, bno); - if (size == fs->fs_bsize) { - blkno = fragstoblks(fs, bno); - assert (!ffs_isblock(fs, cg_blksfree (cgp), blkno)); - ffs_setblock(fs, cg_blksfree(cgp), blkno); - ffs_clusteracct(fs, cgp, blkno, 1); - cgp->cg_cs.cs_nbfree++; - fs->fs_cstotal.cs_nbfree++; - csum[cg].cs_nbfree++; - i = cbtocylno(fs, bno); - cg_blks(fs, cgp, i)[cbtorpos(fs, bno)]++; - cg_blktot(cgp)[i]++; - } else { - bbase = bno - fragnum(fs, bno); - /* - * decrement the counts associated with the old frags - */ - blk = blkmap(fs, cg_blksfree(cgp), bbase); - ffs_fragacct(fs, blk, cgp->cg_frsum, -1); - /* - * deallocate the fragment - */ - frags = numfrags(fs, size); - for (i = 0; i < frags; i++) { - assert (!isset (cg_blksfree(cgp), bno + i)); - setbit(cg_blksfree(cgp), bno + i); - } - cgp->cg_cs.cs_nffree += i; - fs->fs_cstotal.cs_nffree += i; - csum[cg].cs_nffree += i; - /* - * add back in counts associated with the new frags - */ - blk = blkmap(fs, cg_blksfree(cgp), bbase); - ffs_fragacct(fs, blk, cgp->cg_frsum, 1); - /* - * if a complete block has been reassembled, account for it - */ - blkno = fragstoblks(fs, bbase); - if (ffs_isblock(fs, cg_blksfree(cgp), blkno)) { - cgp->cg_cs.cs_nffree -= fs->fs_frag; - fs->fs_cstotal.cs_nffree -= fs->fs_frag; - csum[cg].cs_nffree -= fs->fs_frag; - ffs_clusteracct(fs, cgp, blkno, 1); - cgp->cg_cs.cs_nbfree++; - fs->fs_cstotal.cs_nbfree++; - csum[cg].cs_nbfree++; - i = cbtocylno(fs, bbase); - cg_blks(fs, cgp, i)[cbtorpos(fs, bbase)]++; - cg_blktot(cgp)[i]++; - } - } - if (releasecg) - release_cg (cgp); - record_poke (cgp, sblock->fs_cgsize); - csum_dirty = 1; - sblock_dirty = 1; - fs->fs_fmod = 1; - alloc_sync (np); -/* bdwrite(bp); */ -} - -/* - * Free an inode. - * - * The specified inode is placed back in the free map. - */ -/* Implement diskfs call back diskfs_free_node (described in - <hurd/diskfs.h>. This was called ffs_vfree in BSD. */ -void -diskfs_free_node (struct node *np, mode_t mode) -{ - register struct fs *fs; - struct cg *cgp; - ino_t ino = np->dn->number; - int cg; - int releasecg; - - fs = sblock; - assert (ino < fs->fs_ipg * fs->fs_ncg); - cg = ino_to_cg(fs, ino); -#if 0 /* Not this way in GNU Hurd ufs */ - error = bread(pip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), - (int)fs->fs_cgsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (0); - } - cgp = (struct cg *)bp->b_data; -#else - releasecg = read_cg (cg, &cgp); -#endif - if (!cg_chkmagic(cgp)) { -/* brelse(bp); */ - if (releasecg) - release_cg (cgp); - return; - } - cgp->cg_time = diskfs_mtime->seconds; - ino %= fs->fs_ipg; - if (isclr(cg_inosused(cgp), ino)) { -/* printf("dev = 0x%x, ino = %Ld, fs = %s\n", - pip->i_dev, ino, fs->fs_fsmnt); */ - assert (diskfs_readonly); - } - clrbit(cg_inosused(cgp), ino); - if (ino < cgp->cg_irotor) - cgp->cg_irotor = ino; - cgp->cg_cs.cs_nifree++; - fs->fs_cstotal.cs_nifree++; - csum[cg].cs_nifree++; - if ((mode & IFMT) == IFDIR) { - cgp->cg_cs.cs_ndir--; - fs->fs_cstotal.cs_ndir--; - csum[cg].cs_ndir--; - } - if (releasecg) - release_cg (cgp); - record_poke (cgp, sblock->fs_cgsize); - csum_dirty = 1; - sblock_dirty = 1; - fs->fs_fmod = 1; - alloc_sync (np); -/* bdwrite(bp); */ -} - -/* - * Find a block of the specified size in the specified cylinder group. - * - * It is a panic if a request is made to find a block if none are - * available. - */ -static daddr_t -ffs_mapsearch(register struct fs *fs, - register struct cg *cgp, - daddr_t bpref, - int allocsiz) -{ - daddr_t bno; - int start, len, loc, i; - int blk, field, subfield, pos; - - /* - * find the fragment by searching through the free block - * map for an appropriate bit pattern - */ - if (bpref) - start = dtogd(fs, bpref) / NBBY; - else - start = cgp->cg_frotor / NBBY; - len = howmany(fs->fs_fpg, NBBY) - start; - loc = scanc((u_int)len, (u_char *)&cg_blksfree(cgp)[start], - (u_char *)fragtbl[fs->fs_frag], - (u_char)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); - if (loc == 0) { - len = start + 1; - start = 0; - loc = scanc((u_int)len, (u_char *)&cg_blksfree(cgp)[0], - (u_char *)fragtbl[fs->fs_frag], - (u_char)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); - assert (loc); - - } - bno = (start + len - loc) * NBBY; - cgp->cg_frotor = bno; - /* - * found the byte in the map - * sift through the bits to find the selected frag - */ - for (i = bno + NBBY; bno < i; bno += fs->fs_frag) { - blk = blkmap(fs, cg_blksfree(cgp), bno); - blk <<= 1; - field = around[allocsiz]; - subfield = inside[allocsiz]; - for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) { - if ((blk & field) == subfield) - return (bno + pos); - field <<= 1; - subfield <<= 1; - } - } - assert (0); - return (-1); -} - -/* - * Update the cluster map because of an allocation or free. - * - * Cnt == 1 means free; cnt == -1 means allocating. - */ -static void -ffs_clusteracct(struct fs *fs, - struct cg *cgp, - daddr_t blkno, - int cnt) -{ - long *sump; - u_char *freemapp, *mapp; - int i, start, end, forw, back, map, bit; - - if (fs->fs_contigsumsize <= 0) - return; - freemapp = cg_clustersfree(cgp); - sump = cg_clustersum(cgp); - /* - * Allocate or clear the actual block. - */ - if (cnt > 0) - setbit(freemapp, blkno); - else - clrbit(freemapp, blkno); - /* - * Find the size of the cluster going forward. - */ - start = blkno + 1; - end = start + fs->fs_contigsumsize; - if (end >= cgp->cg_nclusterblks) - end = cgp->cg_nclusterblks; - mapp = &freemapp[start / NBBY]; - map = *mapp++; - bit = 1 << (start % NBBY); - for (i = start; i < end; i++) { - if ((map & bit) == 0) - break; - if ((i & (NBBY - 1)) != (NBBY - 1)) { - bit <<= 1; - } else { - map = *mapp++; - bit = 1; - } - } - forw = i - start; - /* - * Find the size of the cluster going backward. - */ - start = blkno - 1; - end = start - fs->fs_contigsumsize; - if (end < 0) - end = -1; - mapp = &freemapp[start / NBBY]; - map = *mapp--; - bit = 1 << (start % NBBY); - for (i = start; i > end; i--) { - if ((map & bit) == 0) - break; - if ((i & (NBBY - 1)) != 0) { - bit >>= 1; - } else { - map = *mapp--; - bit = 1 << (NBBY - 1); - } - } - back = start - i; - /* - * Account for old cluster and the possibly new forward and - * back clusters. - */ - i = back + forw + 1; - if (i > fs->fs_contigsumsize) - i = fs->fs_contigsumsize; - sump[i] += cnt; - if (back > 0) - sump[back] -= cnt; - if (forw > 0) - sump[forw] -= cnt; -} - -#if 0 -/* - * Fserr prints the name of a file system with an error diagnostic. - * - * The form of the error message is: - * fs: error message - */ -static void -ffs_fserr(fs, uid, cp) - struct fs *fs; - u_int uid; - char *cp; -{ - - log(LOG_ERR, "uid %d on %s: %s\n", uid, fs->fs_fsmnt, cp); -} -#endif diff --git a/ufs/bmap.c b/ufs/bmap.c deleted file mode 100644 index 1a138f39..00000000 --- a/ufs/bmap.c +++ /dev/null @@ -1,120 +0,0 @@ -/* Interpretation of indirect block structure - 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 "ufs.h" - -/* For logical block number LBN of file NP, look it the block address, - giving the "path" of indirect blocks to the file, starting - with the least indirect. Fill *INDIRS with information for - the block. */ -error_t -fetch_indir_spec (struct node *np, volatile daddr_t lbn, - struct iblock_spec *indirs) -{ - struct dinode *di = dino (np->dn->number); - error_t err; - daddr_t *siblock; - - err = diskfs_catch_exception (); - if (err) - return err; - - indirs[0].offset = -2; - indirs[1].offset = -2; - indirs[2].offset = -2; - indirs[3].offset = -2; - - if (lbn < NDADDR) - { - if (lbn >= 0) - { - indirs[0].bno = read_disk_entry (di->di_db[lbn]); - indirs[0].offset = -1; - } - - diskfs_end_catch_exception (); - return 0; - } - - lbn -= NDADDR; - - indirs[0].offset = lbn % NINDIR (sblock); - - if (lbn / NINDIR (sblock)) - { - /* We will use the double indirect block */ - int ibn; - daddr_t *diblock; - - ibn = lbn / NINDIR (sblock) - 1; - - indirs[1].offset = ibn % NINDIR (sblock); - - /* We don't support triple indirect blocks, but this - is where we'd do it. */ - assert (!(ibn / NINDIR (sblock))); - - indirs[2].offset = -1; - indirs[2].bno = read_disk_entry (di->di_ib[INDIR_DOUBLE]); - - if (indirs[2].bno) - { - diblock = indir_block (indirs[2].bno); - indirs[1].bno = read_disk_entry (diblock[indirs[1].offset]); - } - else - indirs[1].bno = 0; - } - else - { - indirs[1].offset = -1; - indirs[1].bno = read_disk_entry (di->di_ib[INDIR_SINGLE]); - } - - if (indirs[1].bno) - { - siblock = indir_block (indirs[1].bno); - indirs[0].bno = read_disk_entry (siblock[indirs[0].offset]); - } - else - indirs[0].bno = 0; - - diskfs_end_catch_exception (); - return 0; -} - - -/* Mark indirect block BNO as dirty on node NP's list. NP must - be locked. */ -void -mark_indir_dirty (struct node *np, daddr_t bno) -{ - struct dirty_indir *d; - - for (d = np->dn->dirty; d; d = d->next) - if (d->bno == bno) - return; - - d = malloc (sizeof (struct dirty_indir)); - d->bno = bno; - d->next = np->dn->dirty; - np->dn->dirty = d; -} - diff --git a/ufs/consts.c b/ufs/consts.c deleted file mode 100644 index 69221233..00000000 --- a/ufs/consts.c +++ /dev/null @@ -1,33 +0,0 @@ -/* Various constants wanted by the diskfs library - 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 "ufs.h" -#include "dir.h" -#include <version.h> - -int diskfs_link_max = LINK_MAX; -int diskfs_name_max = MAXNAMLEN; -int diskfs_maxsymlinks = 8; -int diskfs_shortcut_symlink = 1; -int diskfs_shortcut_chrdev = 1; -int diskfs_shortcut_blkdev = 1; -int diskfs_shortcut_fifo = 1; -int diskfs_shortcut_ifsock = 1; -char *diskfs_server_name = "ufs"; -char *diskfs_server_version = HURD_VERSION; -char *diskfs_extra_version = "GNU Hurd"; -int diskfs_synchronous = 0; diff --git a/ufs/dinode.h b/ufs/dinode.h deleted file mode 100644 index 00be0d94..00000000 --- a/ufs/dinode.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - 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. */ - -/* - * Copyright (c) 1982, 1989, 1993 - * The Regents of the University of California. All rights reserved. - * (c) UNIX System Laboratories, Inc. - * All or some portions of this file are derived from material licensed - * to the University of California by American Telephone and Telegraph - * Co. or Unix System Laboratories, Inc. and are reproduced herein with - * the permission of UNIX System Laboratories, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)dinode.h 8.3 (Berkeley) 1/21/94 - */ - -/* - * The root inode is the root of the file system. Inode 0 can't be used for - * normal purposes and historically bad blocks were linked to inode 1, thus - * the root inode is 2. (Inode 1 is no longer used for this purpose, however - * numerous dump tapes make this assumption, so we are stuck with it). - */ -#define ROOTINO ((ino_t)2) - -/* - * A dinode contains all the meta-data associated with a UFS file. - * This structure defines the on-disk format of a dinode. - */ - -#define NDADDR 12 /* Direct addresses in inode. */ -#define NIADDR 3 /* Indirect addresses in inode. */ - -/* Maximum value of di_nlink field. */ -#define LINK_MAX 32767 - -/* Indexes into di_ib */ -#define INDIR_SINGLE 0 -#define INDIR_DOUBLE 1 -#define INDIR_TRIPLE 2 /* NOT SUPPORTED */ - -struct dinode { - u_short di_model; /* 0: IFMT and permissions. */ - short di_nlink; /* 2: File link count. */ - union - { - u_long diu_author; /* 4: File author */ - u_short diu_oldids[2]; /* Old format uid and gid */ - } di_u; - u_quad_t di_size; /* 8: File byte count. */ - struct timespec di_atime; /* 16: Last access time. */ - struct timespec di_mtime; /* 24: Last modified time. */ - struct timespec di_ctime; /* 32: Last inode change time. */ - daddr_t di_db[NDADDR]; /* 40: Direct disk blocks. */ - daddr_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */ - u_long di_flags; /* 100: Status flags (chflags). */ - long di_blocks; /* 104: Blocks actually held. */ - long di_gen; /* 108: Generation number. */ - u_long di_uid; /* 112: File owner. */ - u_long di_gid; /* 116: File group. */ - u_short di_modeh; /* 120: Mode high bits */ - u_short di_spare; /* 122: unused */ - long di_trans; /* 124: filesystem translator */ -}; - -#define di_author di_u.diu_author /* GNU extension */ -#define di_ouid di_u.diu_oldids[0] -#define di_ogid di_u.diu_oldids[1] - -/* - * The di_db fields may be overlaid with other information for - * file types that do not have associated disk storage. Block - * and character devices overlay the first data block with their - * dev_t value. Short symbolic links place their path in the - * di_db area. - */ -#define di_rdev di_db[0] -#define di_shortlink di_db -#define MAXSYMLINKLEN ((NDADDR + NIADDR) * sizeof(daddr_t)) - -/* File modes. */ -#define IEXEC 0000100 /* Executable. */ -#define IWRITE 0000200 /* Writeable. */ -#define IREAD 0000400 /* Readable. */ -#define ISVTX 0001000 /* Sticky bit. */ -#define ISGID 0002000 /* Set-gid. */ -#define ISUID 0004000 /* Set-uid. */ - -/* File types. */ -#define IFMT 0170000 /* Mask of file type. */ -#define IFIFO 0010000 /* Named pipe (fifo). */ -#define IFCHR 0020000 /* Character device. */ -#define IFDIR 0040000 /* Directory file. */ -#define IFBLK 0060000 /* Block device. */ -#define IFREG 0100000 /* Regular file. */ -#define IFLNK 0120000 /* Symbolic link. */ -#define IFSOCK 0140000 /* UNIX domain socket. */ diff --git a/ufs/dir.c b/ufs/dir.c deleted file mode 100644 index 3c5f152a..00000000 --- a/ufs/dir.c +++ /dev/null @@ -1,988 +0,0 @@ -/* Directory management routines - - Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2007 - 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 "ufs.h" -#include "dir.h" - -#include <string.h> -#include <stdio.h> -#include <dirent.h> - -#undef d_ino - -enum slot_status -{ - /* This means we haven't yet found room for a new entry. */ - LOOKING, - - /* This means that the specified entry is free and should be used. */ - TAKE, - - /* This means that the specified entry has enough room at the end - to hold the new entry. */ - SHRINK, - - /* This means that there is enough space in the block, but not in - any one single entry, so they all have to be shifted to make - room. */ - COMPRESS, - - /* This means that the directory will have to be grown to hold the - entry. */ - EXTEND, - - /* For removal and rename, this means that this is the location - of the entry found. */ - HERE_TIS, -}; - -struct dirstat -{ - /* Type of followp operation expected */ - enum lookup_type type; - - /* One of the statuses above */ - enum slot_status stat; - - /* Mapped address and length of directory */ - vm_address_t mapbuf; - vm_size_t mapextent; - - /* Index of this directory block. */ - int idx; - - /* For stat COMPRESS, this is the address (inside mapbuf) - of the first direct in the directory block to be compressed. */ - /* For stat HERE_TIS, SHRINK, and TAKE, this is the entry referenced. */ - struct directory_entry *entry; - - /* For stat HERE_TIS, type REMOVE, this is the address of the immediately - previous direct in this directory block, or zero if this is the first. */ - struct directory_entry *preventry; - - /* For stat COMPRESS, this is the number of bytes needed to be copied - in order to undertake the compression. */ - size_t nbytes; -}; - -const size_t diskfs_dirstat_size = sizeof (struct dirstat); - -/* Initialize DS such that diskfs_drop_dirstat will ignore it. */ -void -diskfs_null_dirstat (struct dirstat *ds) -{ - ds->type = LOOKUP; -} - -static error_t -dirscanblock (vm_address_t blockoff, struct node *dp, int idx, - const char *name, int namelen, enum lookup_type type, - struct dirstat *ds, ino_t *inum); - -/* Implement the diskfs_lookup from the diskfs library. See - <hurd/diskfs.h> for the interface specification. */ -error_t -diskfs_lookup_hard (struct node *dp, const char *name, enum lookup_type type, - struct node **npp, struct dirstat *ds, struct protid *cred) -{ - error_t err; - ino_t inum; - int namelen; - int spec_dotdot; - struct node *np = 0; - int retry_dotdot = 0; - memory_object_t memobj; - vm_prot_t prot = - (type == LOOKUP) ? VM_PROT_READ : (VM_PROT_READ | VM_PROT_WRITE); - vm_address_t buf = 0; - vm_size_t buflen = 0; - int blockaddr; - int idx, lastidx; - int looped; - - if ((type == REMOVE) || (type == RENAME)) - assert (npp); - - if (npp) - *npp = 0; - - spec_dotdot = type & SPEC_DOTDOT; - type &= ~SPEC_DOTDOT; - - namelen = strlen (name); - - if (namelen > MAXNAMLEN) - { - if (ds) - diskfs_null_dirstat (ds); - return ENAMETOOLONG; - } - - try_again: - if (ds) - { - ds->type = LOOKUP; - ds->mapbuf = 0; - ds->mapextent = 0; - } - if (buf) - { - munmap ((caddr_t) buf, buflen); - buf = 0; - } - if (ds && (type == CREATE || type == RENAME)) - ds->stat = LOOKING; - - /* Map in the directory contents. */ - memobj = diskfs_get_filemap (dp, prot); - - if (memobj == MACH_PORT_NULL) - return errno; - - buf = 0; - /* We allow extra space in case we have to do an EXTEND. */ - buflen = round_page (dp->dn_stat.st_size + DIRBLKSIZ); - err = vm_map (mach_task_self (), - &buf, buflen, 0, 1, memobj, 0, 0, prot, prot, 0); - mach_port_deallocate (mach_task_self (), memobj); - - inum = 0; - - diskfs_set_node_atime (dp); - - /* Start the lookup at DP->dn->dir_idx. */ - idx = dp->dn->dir_idx; - if (idx * DIRBLKSIZ > dp->dn_stat.st_size) - idx = 0; /* just in case */ - blockaddr = buf + idx * DIRBLKSIZ; - looped = (idx == 0); - lastidx = idx; - if (lastidx == 0) - lastidx = dp->dn_stat.st_size / DIRBLKSIZ; - - while (!looped || idx < lastidx) - { - err = dirscanblock (blockaddr, dp, idx, name, namelen, type, ds, &inum); - if (!err) - { - dp->dn->dir_idx = idx; - break; - } - if (err != ENOENT) - { - munmap ((caddr_t) buf, buflen); - return err; - } - - blockaddr += DIRBLKSIZ; - idx++; - if (blockaddr - buf >= dp->dn_stat.st_size && !looped) - { - /* We've gotten to the end; start back at the beginning */ - looped = 1; - blockaddr = buf; - idx = 0; - } - } - - diskfs_set_node_atime (dp); - if (diskfs_synchronous) - diskfs_node_update (dp, 1); - - /* If err is set here, it's ENOENT, and we don't want to - think about that as an error yet. */ - err = 0; - - if (inum && npp) - { - if (namelen != 2 || name[0] != '.' || name[1] != '.') - { - if (inum == dp->dn->number) - { - np = dp; - diskfs_nref (np); - } - else - { - err = diskfs_cached_lookup (inum, &np); - if (err) - goto out; - } - } - - /* We are looking up .. */ - /* Check to see if this is the root of the filesystem. */ - else if (dp->dn->number == 2) - { - err = EAGAIN; - goto out; - } - - /* We can't just do diskfs_cached_lookup, because we would then deadlock. - So we do this. Ick. */ - else if (retry_dotdot) - { - /* Check to see that we got the same answer as last time. */ - if (inum != retry_dotdot) - { - /* Drop what we *thought* was .. (but isn't any more) and - try *again*. */ - diskfs_nput (np); - mutex_unlock (&dp->lock); - err = diskfs_cached_lookup (inum, &np); - mutex_lock (&dp->lock); - if (err) - goto out; - retry_dotdot = inum; - goto try_again; - } - /* Otherwise, we got it fine and np is already set properly. */ - } - else if (!spec_dotdot) - { - /* Lock them in the proper order, and then - repeat the directory scan to see if this is still - right. */ - mutex_unlock (&dp->lock); - err = diskfs_cached_lookup (inum, &np); - mutex_lock (&dp->lock); - if (err) - goto out; - retry_dotdot = inum; - goto try_again; - } - - /* Here below are the spec dotdot cases. */ - else if (type == RENAME || type == REMOVE) - np = ifind (inum); - - else if (type == LOOKUP) - { - diskfs_nput (dp); - err = diskfs_cached_lookup (inum, &np); - if (err) - goto out; - } - else - assert (0); - } - - if ((type == CREATE || type == RENAME) && !inum && ds && ds->stat == LOOKING) - { - /* We didn't find any room, so mark ds to extend the dir */ - ds->type = CREATE; - ds->stat = EXTEND; - ds->idx = dp->dn_stat.st_size / DIRBLKSIZ; - } - - /* Return to the user; if we can't, release the reference - (and lock) we acquired above. */ - out: - /* Deallocate or save the mapping. */ - if ((err && err != ENOENT) - || !ds - || ds->type == LOOKUP) - { - munmap ((caddr_t) buf, buflen); - if (ds) - ds->type = LOOKUP; /* set to be ignored by drop_dirstat */ - } - else - { - ds->mapbuf = buf; - ds->mapextent = buflen; - } - - if (np) - { - assert (npp); - if (err) - { - if (!spec_dotdot) - { - /* Normal case */ - if (np == dp) - diskfs_nrele (np); - else - diskfs_nput (np); - } - else if (type == RENAME || type == REMOVE) - /* We just did ifind to get np; that allocates - no new references, so we don't have anything to do */ - ; - else if (type == LOOKUP) - /* We did diskfs_cached_lookup */ - diskfs_nput (np); - } - else - *npp = np; - } - - return err ? : inum ? 0 : ENOENT; -} - -/* Scan block at address BLKADDR (of node DP; block index IDX), for - name NAME of length NAMELEN. Args TYPE, DS are as for - diskfs_lookup. If found, set *INUM to the inode number, else - return ENOENT. */ -static error_t -dirscanblock (vm_address_t blockaddr, struct node *dp, int idx, - const char *name, int namelen, enum lookup_type type, - struct dirstat *ds, ino_t *inum) -{ - int nfree = 0; - int needed = 0; - vm_address_t currentoff, prevoff; - struct directory_entry *entry = 0; - int nentries = 0; - size_t nbytes = 0; - int looking = 0; - int countcopies = 0; - int consider_compress = 0; - - if (ds && (ds->stat == LOOKING - || ds->stat == COMPRESS)) - { - looking = 1; - countcopies = 1; - needed = DIRSIZ (namelen); - } - - for (currentoff = blockaddr, prevoff = 0; - currentoff < blockaddr + DIRBLKSIZ; - prevoff = currentoff, currentoff += read_disk_entry (entry->d_reclen)) - { - entry = (struct directory_entry *)currentoff; - - if (!entry->d_reclen - || read_disk_entry (entry->d_reclen) % 4 - || DIRECT_NAMLEN (entry) > MAXNAMLEN - || (currentoff + read_disk_entry (entry->d_reclen) - > blockaddr + DIRBLKSIZ) - || entry->d_name[DIRECT_NAMLEN (entry)] - || DIRSIZ (DIRECT_NAMLEN (entry)) > read_disk_entry (entry->d_reclen) - || memchr (entry->d_name, '\0', DIRECT_NAMLEN (entry))) - { - fprintf (stderr, "Bad directory entry: inode: %Ld offset: %zd\n", - dp->dn->number, currentoff - blockaddr + idx * DIRBLKSIZ); - return ENOENT; - } - - if (looking || countcopies) - { - int thisfree; - - /* Count how much free space this entry has in it. */ - if (entry->d_ino == 0) - thisfree = read_disk_entry (entry->d_reclen); - else - thisfree = (read_disk_entry (entry->d_reclen) - - DIRSIZ (DIRECT_NAMLEN (entry))); - - /* If this isn't at the front of the block, then it will - have to be copied if we do a compression; count the - number of bytes there too. */ - if (countcopies && currentoff != blockaddr) - nbytes += DIRSIZ (DIRECT_NAMLEN (entry)); - - if (ds->stat == COMPRESS && nbytes > ds->nbytes) - /* The previously found compress is better than - this one, so don't bother counting any more. */ - countcopies = 0; - - if (thisfree >= needed) - { - ds->type = CREATE; - ds->stat = read_disk_entry (entry->d_ino) == 0 ? TAKE : SHRINK; - ds->entry = entry; - ds->idx = idx; - looking = countcopies = 0; - } - else - { - nfree += thisfree; - if (nfree >= needed) - consider_compress = 1; - } - } - - if (entry->d_ino) - nentries++; - - if (DIRECT_NAMLEN (entry) == namelen - && entry->d_name[0] == name[0] - && entry->d_ino - && !bcmp (entry->d_name, name, namelen)) - break; - } - - if (consider_compress - && (ds->type == LOOKING - || (ds->type == COMPRESS && ds->nbytes > nbytes))) - { - ds->type = CREATE; - ds->stat = COMPRESS; - ds->entry = (struct directory_entry *) blockaddr; - ds->idx = idx; - ds->nbytes = nbytes; - } - - if (currentoff >= blockaddr + DIRBLKSIZ) - { - int i; - /* The name is not in this block. */ - - /* Because we scanned the entire block, we should write - down how many entries there were. */ - if (!dp->dn->dirents) - { - dp->dn->dirents = malloc ((dp->dn_stat.st_size / DIRBLKSIZ) - * sizeof (int)); - for (i = 0; i < dp->dn_stat.st_size/DIRBLKSIZ; i++) - dp->dn->dirents[i] = -1; - } - /* Make sure the count is correct if there is one now. */ - assert (dp->dn->dirents[idx] == -1 - || dp->dn->dirents[idx] == nentries); - dp->dn->dirents[idx] = nentries; - - return ENOENT; - } - - /* We have found the required name. */ - - if (ds && type == CREATE) - ds->type = LOOKUP; /* it's invalid now */ - else if (ds && (type == REMOVE || type == RENAME)) - { - ds->type = type; - ds->stat = HERE_TIS; - ds->entry = entry; - ds->idx = idx; - ds->preventry = (struct directory_entry *) prevoff; - } - - *inum = read_disk_entry (entry->d_ino); - return 0; -} - -/* Following a lookup call for CREATE, this adds a node to a directory. - DP is the directory to be modified; NAME is the name to be entered; - NP is the node being linked in; DS is the cached information returned - by lookup; CRED describes the user making the call. This call may - only be made if the directory has been held locked continuously since - the preceding lookup call, and only if that call returned ENOENT. */ -error_t -diskfs_direnter_hard(struct node *dp, - const char *name, - struct node *np, - struct dirstat *ds, - struct protid *cred) -{ - struct directory_entry *new; - int namelen = strlen (name); - int needed = DIRSIZ (namelen); - int oldneeded; - vm_address_t fromoff, tooff; - int totfreed; - error_t err; - size_t oldsize = 0; - - assert (ds->type == CREATE); - - dp->dn_set_mtime = 1; - - switch (ds->stat) - { - case TAKE: - /* We are supposed to consume this slot. */ - assert (ds->entry->d_ino == 0 - && read_disk_entry (ds->entry->d_reclen) >= needed); - - write_disk_entry (ds->entry->d_ino, np->dn->number); - DIRECT_NAMLEN (ds->entry) = namelen; - if (direct_symlink_extension) - ds->entry->d_type = IFTODT (np->dn_stat.st_mode); - bcopy (name, ds->entry->d_name, namelen + 1); - - break; - - case SHRINK: - /* We are supposed to take the extra space at the end - of this slot. */ - oldneeded = DIRSIZ (DIRECT_NAMLEN (ds->entry)); - assert (read_disk_entry (ds->entry->d_reclen) - oldneeded >= needed); - - new = (struct directory_entry *) ((vm_address_t) ds->entry + oldneeded); - - write_disk_entry (new->d_ino, np->dn->number); - write_disk_entry (new->d_reclen, - read_disk_entry (ds->entry->d_reclen) - oldneeded); - DIRECT_NAMLEN (new) = namelen; - if (direct_symlink_extension) - new->d_type = IFTODT (np->dn_stat.st_mode); - bcopy (name, new->d_name, namelen + 1); - - write_disk_entry (ds->entry->d_reclen, oldneeded); - - break; - - case COMPRESS: - /* We are supposed to move all the entries to the - front of the block, giving each the minimum - necessary room. This should free up enough space - for the new entry. */ - fromoff = tooff = (vm_address_t) ds->entry; - - while (fromoff < (vm_address_t) ds->entry + DIRBLKSIZ) - { - struct directory_entry *from = (struct directory_entry *)fromoff; - struct directory_entry *to = (struct directory_entry *) tooff; - int fromreclen = read_disk_entry (from->d_reclen); - - if (from->d_ino != 0) - { - assert (fromoff >= tooff); - - bcopy (from, to, fromreclen); - write_disk_entry (to->d_reclen, DIRSIZ (DIRECT_NAMLEN (to))); - - tooff += read_disk_entry (to->d_reclen); - } - fromoff += fromreclen; - } - - totfreed = (vm_address_t) ds->entry + DIRBLKSIZ - tooff; - assert (totfreed >= needed); - - new = (struct directory_entry *) tooff; - write_disk_entry (new->d_ino, np->dn->number); - write_disk_entry (new->d_reclen, totfreed); - DIRECT_NAMLEN (new) = namelen; - if (direct_symlink_extension) - new->d_type = IFTODT (np->dn_stat.st_mode); - bcopy (name, new->d_name, namelen + 1); - break; - - case EXTEND: - /* Extend the file. */ - assert (needed <= DIRBLKSIZ); - - oldsize = dp->dn_stat.st_size; - if ((off_t)(oldsize + DIRBLKSIZ) != dp->dn_stat.st_size + DIRBLKSIZ) - { - /* We can't possibly map the whole directory in. */ - munmap ((caddr_t) ds->mapbuf, ds->mapextent); - return EOVERFLOW; - } - while (oldsize + DIRBLKSIZ > dp->allocsize) - { - err = diskfs_grow (dp, oldsize + DIRBLKSIZ, cred); - if (err) - { - munmap ((caddr_t) ds->mapbuf, ds->mapextent); - return err; - } - } - - new = (struct directory_entry *) (ds->mapbuf + oldsize); - - dp->dn_stat.st_size = oldsize + DIRBLKSIZ; - dp->dn_set_ctime = 1; - - write_disk_entry (new->d_ino, np->dn->number); - write_disk_entry (new->d_reclen, DIRBLKSIZ); - DIRECT_NAMLEN (new) = namelen; - if (direct_symlink_extension) - new->d_type = IFTODT (np->dn_stat.st_mode); - bcopy (name, new->d_name, namelen + 1); - break; - - default: - assert (0); - } - - dp->dn_set_mtime = 1; - - munmap ((caddr_t) ds->mapbuf, ds->mapextent); - - if (ds->stat != EXTEND) - { - /* If we are keeping count of this block, then keep the count up - to date. */ - if (dp->dn->dirents && dp->dn->dirents[ds->idx] != -1) - dp->dn->dirents[ds->idx]++; - } - else - { - int i; - /* It's cheap, so start a count here even if we aren't counting - anything at all. */ - if (dp->dn->dirents) - { - dp->dn->dirents = realloc (dp->dn->dirents, - (dp->dn_stat.st_size / DIRBLKSIZ - * sizeof (int))); - for (i = oldsize / DIRBLKSIZ; - i < dp->dn_stat.st_size / DIRBLKSIZ; - i++) - dp->dn->dirents[i] = -1; - - dp->dn->dirents[ds->idx] = 1; - } - else - { - dp->dn->dirents = malloc (dp->dn_stat.st_size / DIRBLKSIZ - * sizeof (int)); - for (i = 0; i < dp->dn_stat.st_size / DIRBLKSIZ; i++) - dp->dn->dirents[i] = -1; - dp->dn->dirents[ds->idx] = 1; - } - } - - diskfs_file_update (dp, 1); - - return 0; -} - -/* Following a lookup call for REMOVE, this removes the link from the - directory. DP is the directory being changed and DS is the cached - information returned from lookup. This call is only valid if the - directory has been locked continuously since the call to lookup, and - only if that call succeeded. */ -error_t -diskfs_dirremove_hard(struct node *dp, - struct dirstat *ds) -{ - assert (ds->type == REMOVE); - assert (ds->stat == HERE_TIS); - - dp->dn_set_mtime = 1; - - if (ds->preventry == 0) - ds->entry->d_ino = 0; - else - { - assert ((vm_address_t) ds->entry - (vm_address_t) ds->preventry - == read_disk_entry (ds->preventry->d_reclen)); - write_disk_entry (ds->preventry->d_reclen, - (read_disk_entry (ds->preventry->d_reclen) - + read_disk_entry (ds->entry->d_reclen))); - } - - dp->dn_set_mtime = 1; - - munmap ((caddr_t) ds->mapbuf, ds->mapextent); - - /* If we are keeping count of this block, then keep the count up - to date. */ - if (dp->dn->dirents && dp->dn->dirents[ds->idx] != -1) - dp->dn->dirents[ds->idx]--; - - diskfs_file_update (dp, 1); - - return 0; -} - - -/* Following a lookup call for RENAME, this changes the inode number - on a directory entry. DP is the directory being changed; NP is - the new node being linked in; DP is the cached information returned - by lookup. This call is only valid if the directory has been locked - continuously since the call to lookup, and only if that call - succeeded. */ -error_t -diskfs_dirrewrite_hard(struct node *dp, - struct node *np, - struct dirstat *ds) -{ - assert (ds->type == RENAME); - assert (ds->stat == HERE_TIS); - - dp->dn_set_mtime = 1; - write_disk_entry (ds->entry->d_ino, np->dn->number); - if (direct_symlink_extension) - ds->entry->d_type = IFTODT (np->dn_stat.st_mode); - dp->dn_set_mtime = 1; - - munmap ((caddr_t) ds->mapbuf, ds->mapextent); - - diskfs_file_update (dp, 1); - - return 0; -} - -/* Tell if DP is an empty directory (has only "." and ".." entries). */ -/* This routine must be called from inside a catch_exception (). */ -int -diskfs_dirempty(struct node *dp, - struct protid *cred) -{ - struct directory_entry *entry; - vm_address_t buf, curoff; - memory_object_t memobj; - error_t err; - - memobj = diskfs_get_filemap (dp, VM_PROT_READ); - - if (memobj == MACH_PORT_NULL) - /* XXX should reflect error properly */ - return 0; - - buf = 0; - - err = vm_map (mach_task_self (), &buf, dp->dn_stat.st_size, 0, - 1, memobj, 0, 0, VM_PROT_READ, VM_PROT_READ, 0); - mach_port_deallocate (mach_task_self (), memobj); - assert (!err); - - diskfs_set_node_atime (dp); - - for (curoff = buf; - curoff < buf + dp->dn_stat.st_size; - curoff += read_disk_entry (entry->d_reclen)) - { - entry = (struct directory_entry *) curoff; - - if (entry->d_ino != 0 - && (DIRECT_NAMLEN (entry) > 2 - || entry->d_name[0] != '.' - || (entry->d_name[1] != '.' - && entry->d_name[1] != '\0'))) - { - munmap ((caddr_t) buf, dp->dn_stat.st_size); - diskfs_set_node_atime (dp); - if (diskfs_synchronous) - diskfs_node_update (dp, 1); - return 0; - } - } - diskfs_set_node_atime (dp); - if (diskfs_synchronous) - diskfs_node_update (dp, 1); - munmap ((caddr_t) buf, dp->dn_stat.st_size); - return 1; -} - -/* Make DS an invalid dirstat. */ -error_t -diskfs_drop_dirstat (struct node *dp, struct dirstat *ds) -{ - if (ds->type != LOOKUP) - { - assert (ds->mapbuf); - munmap ((caddr_t) ds->mapbuf, ds->mapextent); - ds->type = LOOKUP; - } - return 0; -} - - -/* Count the entries in directory block NB for directory DP and - write the answer down in its dirents array. As a side affect - fill BUF with the block. */ -static error_t -count_dirents (struct node *dp, int nb, char *buf) -{ - size_t amt; - char *offinblk; - struct directory_entry *entry; - int count = 0; - error_t err; - - assert (dp->dn->dirents); - assert ((nb + 1) * DIRBLKSIZ <= dp->dn_stat.st_size); - - err = diskfs_node_rdwr (dp, buf, nb * DIRBLKSIZ, DIRBLKSIZ, 0, 0, &amt); - if (err) - return err; - assert (amt == DIRBLKSIZ); - - for (offinblk = buf; - offinblk < buf + DIRBLKSIZ; - offinblk += read_disk_entry (entry->d_reclen)) - { - entry = (struct directory_entry *) offinblk; - if (entry->d_ino) - count++; - } - - assert (dp->dn->dirents[nb] == -1 || dp->dn->dirents[nb] == count); - dp->dn->dirents[nb] = count; - return 0; -} - -/* Implement the disikfs_get_directs callback as described in - <hurd/diskfs.h>. */ -error_t -diskfs_get_directs (struct node *dp, - int entry, - int nentries, - char **data, - size_t *datacnt, - vm_size_t bufsiz, - int *amt) -{ - int blkno; - int nblks; - int curentry; - char buf[DIRBLKSIZ]; - char *bufp; - int bufvalid; - error_t err; - int i; - char *datap; - struct directory_entry *entryp; - int allocsize; - size_t checklen; - struct dirent *userp; - - nblks = dp->dn_stat.st_size/DIRBLKSIZ; - - if (!dp->dn->dirents) - { - dp->dn->dirents = malloc (nblks * sizeof (int)); - for (i = 0; i < nblks; i++) - dp->dn->dirents[i] = -1; - } - - /* Scan through the entries to find ENTRY. If we encounter - a -1 in the process then stop to fill it. When we run - off the end, ENTRY is too big. */ - curentry = 0; - bufvalid = 0; - for (blkno = 0; blkno < nblks; blkno++) - { - if (dp->dn->dirents[blkno] == -1) - { - err = count_dirents (dp, blkno, buf); - if (err) - return err; - bufvalid = 1; - } - - if (curentry + dp->dn->dirents[blkno] > entry) - /* ENTRY starts in this block. */ - break; - - curentry += dp->dn->dirents[blkno]; - - bufvalid = 0; - } - - if (blkno == nblks) - { - /* We reached the end of the directory without seeing ENTRY. - This is treated as an EOF condition, meaning we return - success with empty results. */ - *datacnt = 0; - *amt = 0; - return 0; - } - - /* Allocate enough space to hold the maximum we might return */ - if (!bufsiz || bufsiz > dp->dn_stat.st_size) - allocsize = round_page (dp->dn_stat.st_size); - else - allocsize = round_page (bufsiz); - - if (allocsize > *datacnt) - *data = mmap (0, allocsize, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); - - /* Set bufp appropriately */ - bufp = buf; - if (curentry != entry) - { - /* Look through the block to find out where to start, - setting bufp appropriately. */ - if (!bufvalid) - { - err = diskfs_node_rdwr (dp, buf, blkno * DIRBLKSIZ, DIRBLKSIZ, - 0, 0, &checklen); - if (err) - return err; - assert (checklen == DIRBLKSIZ); - bufvalid = 1; - } - for (i = 0, bufp = buf; - i < entry - curentry && bufp - buf < DIRBLKSIZ; - (bufp - += read_disk_entry (((struct directory_entry *)bufp)->d_reclen)), - i++) - ; - /* Make sure we didn't run off the end. */ - assert (bufp - buf < DIRBLKSIZ); - } - - i = 0; - datap = *data; - - /* Copy the entries, one at a time. */ - while (((nentries == -1) || (i < nentries)) - && (!bufsiz || (datap - *data < bufsiz) ) - && blkno < nblks) - { - if (!bufvalid) - { - err = diskfs_node_rdwr (dp, buf, blkno * DIRBLKSIZ, DIRBLKSIZ, - 0, 0, &checklen); - if (err) - return err; - assert (checklen == DIRBLKSIZ); - bufvalid = 1; - bufp = buf; - } - - entryp = (struct directory_entry *)bufp; - - if (entryp->d_ino) - { - userp = (struct dirent *) datap; - - userp->d_fileno = read_disk_entry (entryp->d_ino); - userp->d_reclen = DIRSIZ (DIRECT_NAMLEN (entryp)); - userp->d_namlen = DIRECT_NAMLEN (entryp); - bcopy (entryp->d_name, userp->d_name, DIRECT_NAMLEN (entryp) + 1); - userp->d_type = DT_UNKNOWN; /* until fixed */ - i++; - datap += DIRSIZ (DIRECT_NAMLEN (entryp)); - } - - bufp += read_disk_entry (entryp->d_reclen); - if (bufp - buf == DIRBLKSIZ) - { - blkno++; - bufvalid = 0; - } - } - - /* We've copied all we can. If we allocated our own array - but didn't fill all of it, then free whatever memory we didn't use. */ - if (allocsize > *datacnt) - { - if (round_page (datap - *data) < allocsize) - munmap (*data + round_page (datap - *data), - allocsize - round_page (datap - *data)); - } - - /* Set variables for return */ - *datacnt = datap - *data; - *amt = i; - return 0; -} diff --git a/ufs/dir.h b/ufs/dir.h deleted file mode 100644 index 5730ef44..00000000 --- a/ufs/dir.h +++ /dev/null @@ -1,163 +0,0 @@ -/* Modified from BSD by Michael I. Bushnell for GNU Hurd ufs server. */ -/* - * Copyright (c) 1982, 1986, 1989, 1993 - * The Regents of the University of California. All rights reserved. - * (c) UNIX System Laboratories, Inc. - * All or some portions of this file are derived from material licensed - * to the University of California by American Telephone and Telegraph - * Co. or Unix System Laboratories, Inc. and are reproduced herein with - * the permission of UNIX System Laboratories, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)dir.h 8.2 (Berkeley) 1/21/94 - */ - -#ifndef _DIR_H_ -#define _DIR_H_ - -#include <endian.h> - -/* - * A directory consists of some number of blocks of DIRBLKSIZ - * bytes, where DIRBLKSIZ is chosen such that it can be transferred - * to disk in a single atomic operation (e.g. 512 bytes on most machines). - * - * Each DIRBLKSIZ byte block contains some number of directory entry - * structures, which are of variable length. Each directory entry has - * a struct direct at the front of it, containing its inode number, - * the length of the entry, and the length of the name contained in - * the entry. These are followed by the name padded to a 4 byte boundary - * with null bytes. All names are guaranteed null terminated. - * The maximum length of a name in a directory is MAXNAMLEN. - * - * The macro DIRSIZ(fmt, dp) gives the amount of space required to represent - * a directory entry. Free space in a directory is represented by - * entries which have dp->d_reclen > DIRSIZ(fmt, dp). All DIRBLKSIZ bytes - * in a directory block are claimed by the directory entries. This - * usually results in the last entry in a directory having a large - * dp->d_reclen. When entries are deleted from a directory, the - * space is returned to the previous entry in the same directory - * block by increasing its dp->d_reclen. If the first entry of - * a directory block is free, then its dp->d_ino is set to 0. - * Entries other than the first in a directory do not normally have - * dp->d_ino set to 0. - */ -#define DIRBLKSIZ DEV_BSIZE -#undef MAXNAMLEN -#define MAXNAMLEN 255 - -/* Don't call this struct DIRECT because the library defines that - (sometimes) in a possible different way. */ - -struct directory_entry { - u_long d_ino; /* inode number of entry */ - u_short d_reclen; /* length of this record */ - u_char d_type; /* file type, see below */ - u_char d_namlen; /* length of string in d_name */ - char d_name[MAXNAMLEN + 1]; /* name with length <= MAXNAMLEN */ -}; - -/* Return the type from a struct directory_entry, paying attention to whether - this filesystem supports the type extension */ -#define DIRECT_TYPE(dp) (direct_symlink_extension ? (dp)->d_type : DT_UNKNOWN) - -/* Return the namlen from a struct direct, paying attention to whether - this filesystem supports the type extension */ -#if (BYTE_ORDER == LITTLE_ENDIAN) -#define DIRECT_NAMLEN(dp) (*(direct_symlink_extension || swab_disk \ - ? &(dp)->d_namlen \ - : &(dp)->d_type)) -#else -#define DIRECT_NAMLEN(dp) (*(!direct_symlink_extension && swab_disk \ - ? &(dp)->d_type \ - : &(dp)->d_namlen)) -#endif - -/* - * The DIRSIZ macro gives the minimum record length which will hold - * the directory entry. This requires the amount of space in struct direct - * without the d_name field, plus enough space for the name with a terminating - * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. - */ -/* In BSD this macro takes a struct direct. Modified by MIB here to - take the namelen (as computed by strlen). */ -#define DIRSIZ(namelen) \ - ((sizeof (struct directory_entry) - (MAXNAMLEN+1)) + (((namelen)+1 + 3) &~ 3)) - -#if 0 /* This is the BSD definition */ -#if (BYTE_ORDER == LITTLE_ENDIAN) -#define DIRSIZ(oldfmt, dp) \ - ((oldfmt) ? \ - ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_type+1 + 3) &~ 3)) : \ - ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))) -#else -#define DIRSIZ(oldfmt, dp) \ - ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) -#endif -#endif /* 0 */ - -#define OLDDIRFMT 1 -#define NEWDIRFMT 0 - -#if 0 /* Not used in GNU */ -/* - * Template for manipulating directories. - * Should use struct direct's, but the name field - * is MAXNAMLEN - 1, and this just won't do. - */ -struct dirtemplate { - u_long dot_ino; - short dot_reclen; - u_char dot_type; - u_char dot_namlen; - char dot_name[4]; /* must be multiple of 4 */ - u_long dotdot_ino; - short dotdot_reclen; - u_char dotdot_type; - u_char dotdot_namlen; - char dotdot_name[4]; /* ditto */ -}; - -/* - * This is the old format of directories, sanz type element. - */ -struct odirtemplate { - u_long dot_ino; - short dot_reclen; - u_short dot_namlen; - char dot_name[4]; /* must be multiple of 4 */ - u_long dotdot_ino; - short dotdot_reclen; - u_short dotdot_namlen; - char dotdot_name[4]; /* ditto */ -}; -#endif /* 0 */ - -#endif /* !_DIR_H_ */ diff --git a/ufs/fs.h b/ufs/fs.h deleted file mode 100644 index a2a3cc9b..00000000 --- a/ufs/fs.h +++ /dev/null @@ -1,509 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)fs.h 8.7 (Berkeley) 4/19/94 - */ - -/* - * Each disk drive contains some number of file systems. - * A file system consists of a number of cylinder groups. - * Each cylinder group has inodes and data. - * - * A file system is described by its super-block, which in turn - * describes the cylinder groups. The super-block is critical - * data and is replicated in each cylinder group to protect against - * catastrophic loss. This is done at `newfs' time and the critical - * super-block data does not change, so the copies need not be - * referenced further unless disaster strikes. - * - * For file system fs, the offsets of the various blocks of interest - * are given in the super block as: - * [fs->fs_sblkno] Super-block - * [fs->fs_cblkno] Cylinder group block - * [fs->fs_iblkno] Inode blocks - * [fs->fs_dblkno] Data blocks - * The beginning of cylinder group cg in fs, is given by - * the ``cgbase(fs, cg)'' macro. - * - * The first boot and super blocks are given in absolute disk addresses. - * The byte-offset forms are preferred, as they don't imply a sector size. - */ -#define BBSIZE 8192 -#define SBSIZE 8192 -#define BBOFF ((off_t)(0)) -#define SBOFF ((off_t)(BBOFF + BBSIZE)) -#define BBLOCK ((daddr_t)(0)) -#define SBLOCK ((daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE)) - -/* - * Addresses stored in inodes are capable of addressing fragments - * of `blocks'. File system blocks of at most size MAXBSIZE can - * be optionally broken into 2, 4, or 8 pieces, each of which is - * addressible; these pieces may be DEV_BSIZE, or some multiple of - * a DEV_BSIZE unit. - * - * Large files consist of exclusively large data blocks. To avoid - * undue wasted disk space, the last data block of a small file may be - * allocated as only as many fragments of a large block as are - * necessary. The file system format retains only a single pointer - * to such a fragment, which is a piece of a single large block that - * has been divided. The size of such a fragment is determinable from - * information in the inode, using the ``blksize(fs, ip, lbn)'' macro. - * - * The file system records space availability at the fragment level; - * to determine block availability, aligned fragments are examined. - */ - -/* - * The file system is made out of blocks of at most MAXBSIZE units, with - * smaller units (fragments) only in the last direct block. MAXBSIZE - * primarily determines the size of buffers in the buffer pool. It may be - * made larger without any effect on existing file systems; however making - * it smaller make make some file systems unmountable. - */ -#define MAXBSIZE MAXPHYS -#define MAXFRAG 8 - -/* - * MINBSIZE is the smallest allowable block size. - * In order to insure that it is possible to create files of size - * 2^32 with only two levels of indirection, MINBSIZE is set to 4096. - * MINBSIZE must be big enough to hold a cylinder group block, - * thus changes to (struct cg) must keep its size within MINBSIZE. - * Note that super blocks are always of size SBSIZE, - * and that both SBSIZE and MAXBSIZE must be >= MINBSIZE. - */ -#define MINBSIZE 4096 - -/* - * The path name on which the file system is mounted is maintained - * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in - * the super block for this name. - * The limit on the amount of summary information per file system - * is defined by MAXCSBUFS. It is currently parameterized for a - * maximum of two million cylinders. - */ -#define MAXMNTLEN 512 -#define MAXCSBUFS 32 - -/* - * A summary of contiguous blocks of various sizes is maintained - * in each cylinder group. Normally this is set by the initial - * value of fs_maxcontig. To conserve space, a maximum summary size - * is set by FS_MAXCONTIG. - */ -#define FS_MAXCONTIG 16 - -/* - * MINFREE gives the minimum acceptable percentage of file system - * blocks which may be free. If the freelist drops below this level - * only the superuser may continue to allocate blocks. This may - * be set to 0 if no reserve of free blocks is deemed necessary, - * however throughput drops by fifty percent if the file system - * is run at between 95% and 100% full; thus the minimum default - * value of fs_minfree is 5%. However, to get good clustering - * performance, 10% is a better choice. hence we use 10% as our - * default value. With 10% free space, fragmentation is not a - * problem, so we choose to optimize for time. - */ -#define MINFREE 5 -#define DEFAULTOPT FS_OPTTIME - -/* - * Per cylinder group information; summarized in blocks allocated - * from first cylinder group data blocks. These blocks have to be - * read in from fs_csaddr (size fs_cssize) in addition to the - * super block. - * - * N.B. sizeof(struct csum) must be a power of two in order for - * the ``fs_cs'' macro to work (see below). - */ -struct csum { - long cs_ndir; /* number of directories */ - long cs_nbfree; /* number of free blocks */ - long cs_nifree; /* number of free inodes */ - long cs_nffree; /* number of free frags */ -}; - -/* - * Super block for a file system. - */ -struct fs { - struct fs *fs_link; /* linked list of file systems */ - struct fs *fs_rlink; /* used for incore super blocks */ - daddr_t fs_sblkno; /* addr of super-block in filesys */ - daddr_t fs_cblkno; /* offset of cyl-block in filesys */ - daddr_t fs_iblkno; /* offset of inode-blocks in filesys */ - daddr_t fs_dblkno; /* offset of first data after cg */ - long fs_cgoffset; /* cylinder group offset in cylinder */ - long fs_cgmask; /* used to calc mod fs_ntrak */ - time_t fs_time; /* last time written */ - long fs_size; /* number of blocks in fs */ - long fs_dsize; /* number of data blocks in fs */ - long fs_ncg; /* number of cylinder groups */ - long fs_bsize; /* size of basic blocks in fs */ - long fs_fsize; /* size of frag blocks in fs */ - long fs_frag; /* number of frags in a block in fs */ -/* these are configuration parameters */ - long fs_minfree; /* minimum percentage of free blocks */ - long fs_rotdelay; /* num of ms for optimal next block */ - long fs_rps; /* disk revolutions per second */ -/* these fields can be computed from the others */ - long fs_bmask; /* ``blkoff'' calc of blk offsets */ - long fs_fmask; /* ``fragoff'' calc of frag offsets */ - long fs_bshift; /* ``lblkno'' calc of logical blkno */ - long fs_fshift; /* ``numfrags'' calc number of frags */ -/* these are configuration parameters */ - long fs_maxcontig; /* max number of contiguous blks */ - long fs_maxbpg; /* max number of blks per cyl group */ -/* these fields can be computed from the others */ - long fs_fragshift; /* block to frag shift */ - long fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ - long fs_sbsize; /* actual size of super block */ - long fs_csmask; /* csum block offset */ - long fs_csshift; /* csum block number */ - long fs_nindir; /* value of NINDIR */ - long fs_inopb; /* value of INOPB */ - long fs_nspf; /* value of NSPF */ -/* yet another configuration parameter */ - long fs_optim; /* optimization preference, see below */ -/* these fields are derived from the hardware */ - long fs_npsect; /* # sectors/track including spares */ - long fs_interleave; /* hardware sector interleave */ - long fs_trackskew; /* sector 0 skew, per track */ - long fs_headswitch; /* head switch time, usec */ - long fs_trkseek; /* track-to-track seek, usec */ -/* sizes determined by number of cylinder groups and their sizes */ - daddr_t fs_csaddr; /* blk addr of cyl grp summary area */ - long fs_cssize; /* size of cyl grp summary area */ - long fs_cgsize; /* cylinder group size */ -/* these fields are derived from the hardware */ - long fs_ntrak; /* tracks per cylinder */ - long fs_nsect; /* sectors per track */ - long fs_spc; /* sectors per cylinder */ -/* this comes from the disk driver partitioning */ - long fs_ncyl; /* cylinders in file system */ -/* these fields can be computed from the others */ - long fs_cpg; /* cylinders per group */ - long fs_ipg; /* inodes per group */ - long fs_fpg; /* blocks per group * fs_frag */ -/* this data must be re-computed after crashes */ - struct csum fs_cstotal; /* cylinder summary information */ -/* these fields are cleared at mount time */ - char fs_fmod; /* super block modified flag */ - char fs_clean; /* file system is clean flag */ - char fs_ronly; /* mounted read-only flag */ - char fs_flags; /* currently unused flag */ - char fs_fsmnt[MAXMNTLEN]; /* name mounted on */ -/* these fields retain the current block allocation info */ - long fs_cgrotor; /* last cg searched */ - struct csum *fs_csp[MAXCSBUFS];/* list of fs_cs info buffers */ - long fs_cpc; /* cyl per cycle in postbl */ - short fs_opostbl[16][8]; /* old rotation block list head */ - long fs_sparecon[50]; /* reserved for future constants */ - long fs_contigsumsize; /* size of cluster summary array */ - long fs_maxsymlinklen; /* max length of an internal symlink */ - long fs_inodefmt; /* format of on-disk inodes */ - u_quad_t fs_maxfilesize; /* maximum representable file size */ - quad_t fs_qbmask; /* ~fs_bmask - for use with quad size */ - quad_t fs_qfmask; /* ~fs_fmask - for use with quad size */ - long fs_state; /* validate fs_clean field */ - long fs_postblformat; /* format of positional layout tables */ - long fs_nrpos; /* number of rotational positions */ - long fs_postbloff; /* (short) rotation block list head */ - long fs_rotbloff; /* (u_char) blocks for each rotation */ - long fs_magic; /* magic number */ - u_char fs_space[1]; /* list of blocks for each rotation */ -/* actually longer */ -}; -/* - * Filesystem idetification - */ -#define FS_MAGIC 0x011954 /* the fast filesystem magic number */ -#define FS_OKAY 0x7c269d38 /* superblock checksum */ -#define FS_42INODEFMT -1 /* 4.2BSD inode format */ -#define FS_44INODEFMT 2 /* 4.4BSD inode format */ -/* - * Preference for optimization. - */ -#define FS_OPTTIME 0 /* minimize allocation time */ -#define FS_OPTSPACE 1 /* minimize disk fragmentation */ - -/* - * Rotational layout table format types - */ -#define FS_42POSTBLFMT -1 /* 4.2BSD rotational table format */ -#define FS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */ -/* - * Macros for access to superblock array structures - */ -#define fs_postbl(fs, cylno) \ - (((fs)->fs_postblformat == FS_42POSTBLFMT) \ - ? ((fs)->fs_opostbl[cylno]) \ - : ((short *)((char *)(fs) + (fs)->fs_postbloff) + (cylno) * (fs)->fs_nrpos)) -#define fs_rotbl(fs) \ - (((fs)->fs_postblformat == FS_42POSTBLFMT) \ - ? ((fs)->fs_space) \ - : ((u_char *)((char *)(fs) + (fs)->fs_rotbloff))) - -/* - * The size of a cylinder group is calculated by CGSIZE. The maximum size - * is limited by the fact that cylinder groups are at most one block. - * Its size is derived from the size of the maps maintained in the - * cylinder group and the (struct cg) size. - */ -#define CGSIZE(fs) \ - /* base cg */ (sizeof(struct cg) + sizeof(long) + \ - /* blktot size */ (fs)->fs_cpg * sizeof(long) + \ - /* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(short) + \ - /* inode map */ howmany((fs)->fs_ipg, NBBY) + \ - /* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY) +\ - /* if present */ ((fs)->fs_contigsumsize <= 0 ? 0 : \ - /* cluster sum */ (fs)->fs_contigsumsize * sizeof(long) + \ - /* cluster map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPB(fs), NBBY))) - -#if 0 /* Wrong for GNU Hurd ufs; we don't use fs_csp at all. */ -/* - * Convert cylinder group to base address of its global summary info. - * - * N.B. This macro assumes that sizeof(struct csum) is a power of two. - */ -#define fs_cs(fs, indx) \ - fs_csp[(indx) >> (fs)->fs_csshift][(indx) & ~(fs)->fs_csmask] -#else -/* Global variable csum is declared in ufs.h; use it instead - of fs_cs stuff. */ -#define fs_cs(fs, indx) this will generate a syntax error. -#endif - -/* - * Cylinder group block for a file system. - */ -#define CG_MAGIC 0x090255 -struct cg { - struct cg *cg_link; /* linked list of cyl groups */ - long cg_magic; /* magic number */ - time_t cg_time; /* time last written */ - long cg_cgx; /* we are the cgx'th cylinder group */ - short cg_ncyl; /* number of cyl's this cg */ - short cg_niblk; /* number of inode blocks this cg */ - long cg_ndblk; /* number of data blocks this cg */ - struct csum cg_cs; /* cylinder summary information */ - long cg_rotor; /* position of last used block */ - long cg_frotor; /* position of last used frag */ - long cg_irotor; /* position of last used inode */ - long cg_frsum[MAXFRAG]; /* counts of available frags */ - long cg_btotoff; /* (long) block totals per cylinder */ - long cg_boff; /* (short) free block positions */ - long cg_iusedoff; /* (char) used inode map */ - long cg_freeoff; /* (u_char) free block map */ - long cg_nextfreeoff; /* (u_char) next available space */ - long cg_clustersumoff; /* (long) counts of avail clusters */ - long cg_clusteroff; /* (char) free cluster map */ - long cg_nclusterblks; /* number of clusters this cg */ - long cg_sparecon[13]; /* reserved for future use */ - u_char cg_space[1]; /* space for cylinder group maps */ -/* actually longer */ -}; -/* - * Macros for access to cylinder group array structures - */ -#define cg_blktot(cgp) \ - (((cgp)->cg_magic != CG_MAGIC) \ - ? (((struct ocg *)(cgp))->cg_btot) \ - : ((long *)((char *)(cgp) + (cgp)->cg_btotoff))) -#define cg_blks(fs, cgp, cylno) \ - (((cgp)->cg_magic != CG_MAGIC) \ - ? (((struct ocg *)(cgp))->cg_b[cylno]) \ - : ((short *)((char *)(cgp) + (cgp)->cg_boff) + (cylno) * (fs)->fs_nrpos)) -#define cg_inosused(cgp) \ - (((cgp)->cg_magic != CG_MAGIC) \ - ? (((struct ocg *)(cgp))->cg_iused) \ - : ((char *)((char *)(cgp) + (cgp)->cg_iusedoff))) -#define cg_blksfree(cgp) \ - (((cgp)->cg_magic != CG_MAGIC) \ - ? (((struct ocg *)(cgp))->cg_free) \ - : ((u_char *)((char *)(cgp) + (cgp)->cg_freeoff))) -#define cg_chkmagic(cgp) \ - ((cgp)->cg_magic == CG_MAGIC || ((struct ocg *)(cgp))->cg_magic == CG_MAGIC) -#define cg_clustersfree(cgp) \ - ((u_char *)((char *)(cgp) + (cgp)->cg_clusteroff)) -#define cg_clustersum(cgp) \ - ((long *)((char *)(cgp) + (cgp)->cg_clustersumoff)) - -/* - * The following structure is defined - * for compatibility with old file systems. - */ -struct ocg { - struct ocg *cg_link; /* linked list of cyl groups */ - struct ocg *cg_rlink; /* used for incore cyl groups */ - time_t cg_time; /* time last written */ - long cg_cgx; /* we are the cgx'th cylinder group */ - short cg_ncyl; /* number of cyl's this cg */ - short cg_niblk; /* number of inode blocks this cg */ - long cg_ndblk; /* number of data blocks this cg */ - struct csum cg_cs; /* cylinder summary information */ - long cg_rotor; /* position of last used block */ - long cg_frotor; /* position of last used frag */ - long cg_irotor; /* position of last used inode */ - long cg_frsum[8]; /* counts of available frags */ - long cg_btot[32]; /* block totals per cylinder */ - short cg_b[32][8]; /* positions of free blocks */ - char cg_iused[256]; /* used inode map */ - long cg_magic; /* magic number */ - u_char cg_free[1]; /* free block map */ -/* actually longer */ -}; - -/* - * Turn file system block numbers into disk block addresses. - * This maps file system blocks to device size blocks. - */ -#define fsbtodb(fs, b) ((b) << (fs)->fs_fsbtodb) -#define dbtofsb(fs, b) ((b) >> (fs)->fs_fsbtodb) - -/* - * Cylinder group macros to locate things in cylinder groups. - * They calc file system addresses of cylinder group data structures. - */ -#define cgbase(fs, c) ((daddr_t)((fs)->fs_fpg * (c))) -#define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */ -#define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */ -#define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */ -#define cgtod(fs, c) (cgstart(fs, c) + (fs)->fs_cblkno) /* cg block */ -#define cgstart(fs, c) \ - (cgbase(fs, c) + (fs)->fs_cgoffset * ((c) & ~((fs)->fs_cgmask))) - -/* - * Macros for handling inode numbers: - * inode number to file system block offset. - * inode number to cylinder group number. - * inode number to file system block address. - */ -#define ino_to_cg(fs, x) ((x) / (fs)->fs_ipg) -#define ino_to_fsba(fs, x) \ - ((daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \ - (blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs)))))) -#define ino_to_fsbo(fs, x) ((x) % INOPB(fs)) - -/* - * Give cylinder group number for a file system block. - * Give cylinder group block number for a file system block. - */ -#define dtog(fs, d) ((d) / (fs)->fs_fpg) -#define dtogd(fs, d) ((d) % (fs)->fs_fpg) - -/* - * Extract the bits for a block from a map. - * Compute the cylinder and rotational position of a cyl block addr. - */ -#define blkmap(fs, map, loc) \ - (((map)[(loc) / NBBY] >> ((loc) % NBBY)) & (0xff >> (NBBY - (fs)->fs_frag))) -#define cbtocylno(fs, bno) \ - ((bno) * NSPF(fs) / (fs)->fs_spc) -#define cbtorpos(fs, bno) \ - (((bno) * NSPF(fs) % (fs)->fs_spc / (fs)->fs_nsect * (fs)->fs_trackskew + \ - (bno) * NSPF(fs) % (fs)->fs_spc % (fs)->fs_nsect * (fs)->fs_interleave) % \ - (fs)->fs_nsect * (fs)->fs_nrpos / (fs)->fs_npsect) - -/* - * The following macros optimize certain frequently calculated - * quantities by using shifts and masks in place of divisions - * modulos and multiplications. - */ -#define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \ - ((loc) & (fs)->fs_qbmask) -#define fragoff(fs, loc) /* calculates (loc % fs->fs_fsize) */ \ - ((loc) & (fs)->fs_qfmask) -#define lblktosize(fs, blk) /* calculates (blk * fs->fs_bsize) */ \ - ((blk) << (fs)->fs_bshift) -#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \ - ((loc) >> (fs)->fs_bshift) -#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \ - ((loc) >> (fs)->fs_fshift) -#define blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \ - (((size) + (fs)->fs_qbmask) & (fs)->fs_bmask) -#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \ - (((size) + (fs)->fs_qfmask) & (fs)->fs_fmask) -#define fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \ - ((frags) >> (fs)->fs_fragshift) -#define blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \ - ((blks) << (fs)->fs_fragshift) -#define fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \ - ((fsb) & ((fs)->fs_frag - 1)) -#define blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \ - ((fsb) &~ ((fs)->fs_frag - 1)) - -/* - * Determine the number of available frags given a - * percentage to hold in reserve - */ -#define freespace(fs, percentreserved) \ - (blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \ - (fs)->fs_cstotal.cs_nffree - ((fs)->fs_dsize * (percentreserved) / 100)) - -/* - * Determining the size of a file block in the file system. - */ -/* Changed from BSD to use allocsize instead of i_size. */ -#define blksize(fs, np, lbn) \ - (((lbn) >= NDADDR || (np)->allocsize >= ((lbn) + 1) << (fs)->fs_bshift) \ - ? (fs)->fs_bsize \ - : (fragroundup(fs, blkoff(fs, (np)->allocsize)))) - -#if 0 /* Don't use this */ -#define dblksize(fs, dip, lbn) \ - (((lbn) >= NDADDR || (dip)->di_size >= ((lbn) + 1) << (fs)->fs_bshift) \ - ? (fs)->fs_bsize \ - : (fragroundup(fs, blkoff(fs, (dip)->di_size)))) -#endif - -/* - * Number of disk sectors per block; assumes DEV_BSIZE byte sector size. - */ -#define NSPB(fs) ((fs)->fs_nspf << (fs)->fs_fragshift) -#define NSPF(fs) ((fs)->fs_nspf) - -/* - * INOPB is the number of inodes in a secondary storage block. - */ -#define INOPB(fs) ((fs)->fs_inopb) -#define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift) - -/* - * NINDIR is the number of indirects in a file system block. - */ -#define NINDIR(fs) ((fs)->fs_nindir) - -extern int inside[], around[]; -extern u_char *fragtbl[]; diff --git a/ufs/hyper.c b/ufs/hyper.c deleted file mode 100644 index ece327a2..00000000 --- a/ufs/hyper.c +++ /dev/null @@ -1,414 +0,0 @@ -/* Fetching and storing the hypermetadata (superblock and cg summary info). - 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 "ufs.h" -#include <string.h> -#include <stdio.h> -#include <error.h> -#include <hurd/store.h> - -static int ufs_clean; /* fs clean before we started writing? */ - -static int oldformat; - -void *zeroblock; - -struct fs *sblock; -struct csum *csum; - -void -swab_sblock (struct fs *sblock) -{ - int i, j; - - sblock->fs_sblkno = swab_long (sblock->fs_sblkno); - sblock->fs_cblkno = swab_long (sblock->fs_cblkno); - sblock->fs_iblkno = swab_long (sblock->fs_iblkno); - sblock->fs_dblkno = swab_long (sblock->fs_dblkno); - sblock->fs_cgoffset = swab_long (sblock->fs_cgoffset); - sblock->fs_cgmask = swab_long (sblock->fs_cgmask); - sblock->fs_time = swab_long (sblock->fs_time); - sblock->fs_size = swab_long (sblock->fs_size); - sblock->fs_dsize = swab_long (sblock->fs_dsize); - sblock->fs_ncg = swab_long (sblock->fs_ncg); - sblock->fs_bsize = swab_long (sblock->fs_bsize); - sblock->fs_fsize = swab_long (sblock->fs_fsize); - sblock->fs_frag = swab_long (sblock->fs_frag); - sblock->fs_minfree = swab_long (sblock->fs_minfree); - sblock->fs_rotdelay = swab_long (sblock->fs_rotdelay); - sblock->fs_rps = swab_long (sblock->fs_rps); - sblock->fs_bmask = swab_long (sblock->fs_bmask); - sblock->fs_fmask = swab_long (sblock->fs_fmask); - sblock->fs_bshift = swab_long (sblock->fs_bshift); - sblock->fs_fshift = swab_long (sblock->fs_fshift); - sblock->fs_maxcontig = swab_long (sblock->fs_maxcontig); - sblock->fs_maxbpg = swab_long (sblock->fs_maxbpg); - sblock->fs_fragshift = swab_long (sblock->fs_fragshift); - sblock->fs_fsbtodb = swab_long (sblock->fs_fsbtodb); - sblock->fs_sbsize = swab_long (sblock->fs_sbsize); - sblock->fs_csmask = swab_long (sblock->fs_csmask); - sblock->fs_csshift = swab_long (sblock->fs_csshift); - sblock->fs_nindir = swab_long (sblock->fs_nindir); - sblock->fs_inopb = swab_long (sblock->fs_inopb); - sblock->fs_nspf = swab_long (sblock->fs_nspf); - sblock->fs_optim = swab_long (sblock->fs_optim); - sblock->fs_npsect = swab_long (sblock->fs_npsect); - sblock->fs_interleave = swab_long (sblock->fs_interleave); - sblock->fs_trackskew = swab_long (sblock->fs_trackskew); - sblock->fs_headswitch = swab_long (sblock->fs_headswitch); - sblock->fs_trkseek = swab_long (sblock->fs_trkseek); - sblock->fs_csaddr = swab_long (sblock->fs_csaddr); - sblock->fs_cssize = swab_long (sblock->fs_cssize); - sblock->fs_cgsize = swab_long (sblock->fs_cgsize); - sblock->fs_ntrak = swab_long (sblock->fs_ntrak); - sblock->fs_nsect = swab_long (sblock->fs_nsect); - sblock->fs_spc = swab_long (sblock->fs_spc); - sblock->fs_ncyl = swab_long (sblock->fs_ncyl); - sblock->fs_cpg = swab_long (sblock->fs_cpg); - sblock->fs_ipg = swab_long (sblock->fs_ipg); - sblock->fs_fpg = swab_long (sblock->fs_fpg); - sblock->fs_cstotal.cs_ndir = swab_long (sblock->fs_cstotal.cs_ndir); - sblock->fs_cstotal.cs_nbfree = swab_long (sblock->fs_cstotal.cs_nbfree); - sblock->fs_cstotal.cs_nifree = swab_long (sblock->fs_cstotal.cs_nifree); - sblock->fs_cstotal.cs_nffree = swab_long (sblock->fs_cstotal.cs_nffree); - /* fs_fmod, fs_clean, fs_ronly, fs_flags, fs_fsmnt are all char */ - sblock->fs_cgrotor = swab_long (sblock->fs_cgrotor); - sblock->fs_cpc = swab_long (sblock->fs_cpc); - sblock->fs_contigsumsize = swab_long (sblock->fs_contigsumsize); - sblock->fs_maxsymlinklen = swab_long (sblock->fs_maxsymlinklen); - sblock->fs_inodefmt = swab_long (sblock->fs_inodefmt); - sblock->fs_maxfilesize = swab_long_long (sblock->fs_maxfilesize); - sblock->fs_qbmask = swab_long_long (sblock->fs_qbmask); - sblock->fs_state = swab_long (sblock->fs_state); - sblock->fs_postblformat = swab_long (sblock->fs_postblformat); - sblock->fs_nrpos = swab_long (sblock->fs_nrpos); - sblock->fs_postbloff = swab_long (sblock->fs_postbloff); - sblock->fs_rotbloff = swab_long (sblock->fs_rotbloff); - sblock->fs_magic = swab_long (sblock->fs_magic); - - /* Tables */ - if (sblock->fs_postblformat == FS_42POSTBLFMT) - for (i = 0; i < 16; i++) - for (j = 0; j < 8; j++) - sblock->fs_opostbl[i][j] = swab_short (sblock->fs_opostbl[i][j]); - else - for (i = 0; i < sblock->fs_cpc; i++) - for (j = 0; j < sblock->fs_nrpos; j++) - fs_postbl(sblock, j)[i] - = swab_short (fs_postbl (sblock, j)[i]); - - /* The rot table is all chars */ -} - -void -swab_csums (struct csum *csum) -{ - int i; - - for (i = 0; i < sblock->fs_ncg; i++) - { - csum[i].cs_ndir = swab_long (csum[i].cs_ndir); - csum[i].cs_nbfree = swab_long (csum[i].cs_nbfree); - csum[i].cs_nifree = swab_long (csum[i].cs_nifree); - csum[i].cs_nffree = swab_long (csum[i].cs_nffree); - } -} - -void -get_hypermetadata (void) -{ - error_t err; - - if (!sblock) - sblock = malloc (SBSIZE); - - /* Free previous values. */ - if (zeroblock) - munmap ((caddr_t) zeroblock, sblock->fs_bsize); - if (csum) - free (csum); - - err = diskfs_catch_exception (); - assert_perror (err); - bcopy (disk_image + SBOFF, sblock, SBSIZE); - diskfs_end_catch_exception (); - - if ((swab_long (sblock->fs_magic)) == FS_MAGIC) - { - swab_disk = 1; - swab_sblock (sblock); - } - else - swab_disk = 0; - - if (sblock->fs_magic != FS_MAGIC) - { - fprintf (stderr, "Bad magic number %#lx (should be %#x)\n", - sblock->fs_magic, FS_MAGIC); - exit (1); - } - if (sblock->fs_bsize > 8192) - { - fprintf (stderr, "Block size %ld is too big (max is 8192 bytes)\n", - sblock->fs_bsize); - exit (1); - } - if (sblock->fs_bsize < sizeof (struct fs)) - { - fprintf (stderr, "Block size %ld is too small (min is %Zd bytes)\n", - sblock->fs_bsize, sizeof (struct fs)); - exit (1); - } - - if (sblock->fs_maxsymlinklen > (long)MAXSYMLINKLEN) - { - fprintf (stderr, "Max shortcut symlinklen %ld is too big (max is %ld)\n", - sblock->fs_maxsymlinklen, (long)MAXSYMLINKLEN); - exit (1); - } - - assert ((__vm_page_size % DEV_BSIZE) == 0); - assert ((sblock->fs_bsize % DEV_BSIZE) == 0); - assert (__vm_page_size <= sblock->fs_bsize); - - /* Examine the clean bit and force read-only if unclean. */ - ufs_clean = sblock->fs_clean; - if (! ufs_clean) - { - error (0, 0, - "%s: warning: FILESYSTEM NOT UNMOUNTED CLEANLY; PLEASE fsck", - diskfs_disk_name); - if (! diskfs_readonly) - { - diskfs_readonly = 1; - error (0, 0, - "%s: MOUNTED READ-ONLY; MUST USE `fsysopts --writable'", - diskfs_disk_name); - } - } - - /* If this is an old filesystem, then we have some more - work to do; some crucial constants might not be set; we - are therefore forced to set them here. */ - - if (sblock->fs_npsect < sblock->fs_nsect) - sblock->fs_npsect = sblock->fs_nsect; - - if (sblock->fs_interleave < 1) - sblock->fs_interleave = 1; - - if (sblock->fs_postblformat == FS_42POSTBLFMT) - sblock->fs_nrpos = 8; - - if (sblock->fs_inodefmt < FS_44INODEFMT) - { - quad_t sizepb = sblock->fs_bsize; - int i; - - oldformat = 1; - sblock->fs_maxfilesize = sblock->fs_bsize * NDADDR - 1; - for (i = 0; i < NIADDR; i++) - { - sizepb *= NINDIR (sblock); - sblock->fs_maxfilesize += sizepb; - } - sblock->fs_qbmask = ~sblock->fs_bmask; - sblock->fs_qfmask = ~sblock->fs_fmask; - } - - /* Find out if we support the 4.4 symlink/dirtype extension */ - if (sblock->fs_maxsymlinklen > 0) - direct_symlink_extension = 1; - else - direct_symlink_extension = 0; - - csum = malloc (fsaddr (sblock, howmany (sblock->fs_cssize, - sblock->fs_fsize))); - - assert (!diskfs_catch_exception ()); - bcopy (disk_image + fsaddr (sblock, sblock->fs_csaddr), - csum, - fsaddr (sblock, howmany (sblock->fs_cssize, sblock->fs_fsize))); - diskfs_end_catch_exception (); - - if (swab_disk) - swab_csums (csum); - - if (store->size < sblock->fs_size * sblock->fs_fsize) - { - fprintf (stderr, - "Disk size (%Ld) less than necessary " - "(superblock says we need %ld)\n", - store->size, sblock->fs_size * sblock->fs_fsize); - exit (1); - } - - zeroblock = mmap (0, sblock->fs_bsize, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); - - /* If the filesystem has new features in it, don't pay attention to - the user's request not to use them. */ - if ((sblock->fs_inodefmt == FS_44INODEFMT - || direct_symlink_extension) - && compat_mode == COMPAT_BSD42) - { - compat_mode = COMPAT_BSD44; - error (0, 0, - "4.2 compat mode requested on 4.4 fs--switched to 4.4 mode"); - } -} - -/* Write the csum data. This isn't backed by a pager because it is - taken from ordinary data blocks and might not be an even number - of pages; in that case writing it through the pager would nuke whatever - pages came after it on the disk and were backed by file pagers. */ -error_t -diskfs_set_hypermetadata (int wait, int clean) -{ - error_t err; - - spin_lock (&alloclock); - - if (csum_dirty) - { - /* Copy into a page-aligned buffer to avoid bugs in kernel device - code. */ - void *buf = 0; - size_t read = 0; - size_t bufsize = round_page (fragroundup (sblock, sblock->fs_cssize)); - - err = store_read (store, - fsbtodb (sblock, sblock->fs_csaddr) - << log2_dev_blocks_per_dev_bsize, - bufsize, &buf, &read); - if (err) - return err; - else if (read != bufsize) - err = EIO; - else - { - size_t wrote; - bcopy (csum, buf, sblock->fs_cssize); - if (swab_disk) - swab_csums ((struct csum *)buf); - err = store_write (store, - fsbtodb (sblock, sblock->fs_csaddr) - << log2_dev_blocks_per_dev_bsize, - buf, bufsize, &wrote); - if (!err && wrote != bufsize) - err = EIO; - } - - munmap (buf, read); - - if (err) - { - spin_unlock (&alloclock); - return err; - } - - csum_dirty = 0; - } - - if (clean && ufs_clean && !sblock->fs_clean) - { - /* The filesystem is clean, so set the clean flag. */ - sblock->fs_clean = 1; - sblock_dirty = 1; - } - else if (!clean && sblock->fs_clean) - { - /* Clear the clean flag */ - sblock->fs_clean = 0; - sblock_dirty = 1; - wait = 1; /* must be synchronous */ - } - - spin_unlock (&alloclock); - - /* Update the superblock if necessary (clean bit was just set). */ - copy_sblock (); - - sync_disk (wait); - return 0; -} - -/* Copy the sblock into the disk */ -void -copy_sblock () -{ - error_t err; - - err = diskfs_catch_exception (); - assert_perror (err); - - spin_lock (&alloclock); - - if (sblock_dirty) - { - assert (! diskfs_readonly); - - if (sblock->fs_postblformat == FS_42POSTBLFMT - || oldformat - || swab_disk) - { - char sblockcopy[SBSIZE]; - struct fs *sbcopy = (struct fs *)sblockcopy; - bcopy (sblock, sblockcopy, SBSIZE); - if (sblock->fs_postblformat == FS_42POSTBLFMT) - sbcopy->fs_nrpos = -1; - if (oldformat) - { - sbcopy->fs_maxfilesize = -1; - sbcopy->fs_qbmask = -1; - sbcopy->fs_qfmask = -1; - } - if (swab_disk) - swab_sblock (sbcopy); - bcopy (sbcopy, disk_image + SBOFF, SBSIZE); - } - else - bcopy (sblock, disk_image + SBOFF, SBSIZE); - record_poke (disk_image + SBOFF, SBSIZE); - sblock_dirty = 0; - } - - spin_unlock (&alloclock); - - diskfs_end_catch_exception (); -} - -void -diskfs_readonly_changed (int readonly) -{ - (*(readonly ? store_set_flags : store_clear_flags)) (store, STORE_READONLY); - - mprotect (disk_image, store->size, PROT_READ | (readonly ? 0 : PROT_WRITE)); - - if (readonly) - { - /* We know we are sync'd now. The superblock is marked as dirty - because we cleared the clean flag immediately after sync'ing. - But now we want to leave it marked clean and not touch it further. */ - sblock_dirty = 0; - return; - } - - strcpy (sblock->fs_fsmnt, "Hurd /"); /* XXX */ - - if (!sblock->fs_clean) - error (0, 0, "WARNING: UNCLEANED FILESYSTEM NOW WRITABLE"); -} diff --git a/ufs/inode.c b/ufs/inode.c deleted file mode 100644 index 77a45edb..00000000 --- a/ufs/inode.c +++ /dev/null @@ -1,703 +0,0 @@ -/* Inode management routines - - Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2007 - 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 "ufs.h" -#include <string.h> -#include <unistd.h> -#include <stdio.h> -#include <netinet/in.h> -#include <fcntl.h> -#include <hurd/store.h> - -#define INOHSZ 512 -#if ((INOHSZ&(INOHSZ-1)) == 0) -#define INOHASH(ino) ((ino)&(INOHSZ-1)) -#else -#define INOHASH(ino) (((unsigned)(ino))%INOHSZ) -#endif - -static struct node *nodehash[INOHSZ]; -static error_t read_disknode (struct node *np); - -spin_lock_t gennumberlock = SPIN_LOCK_INITIALIZER; - -/* Initialize the inode hash table. */ -void -inode_init () -{ - int n; - for (n = 0; n < INOHSZ; n++) - nodehash[n] = 0; -} - -/* Fetch inode INUM, set *NPP to the node structure; - gain one user reference and lock the node. */ -error_t -diskfs_cached_lookup (ino_t inum, struct node **npp) -{ - struct disknode *dn; - struct node *np; - error_t err; - - spin_lock (&diskfs_node_refcnt_lock); - for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext) - { - if (np->dn->number != inum) - continue; - - np->references++; - spin_unlock (&diskfs_node_refcnt_lock); - mutex_lock (&np->lock); - *npp = np; - return 0; - } - - dn = malloc (sizeof (struct disknode)); - - dn->number = inum; - dn->dirents = 0; - dn->dir_idx = 0; - - rwlock_init (&dn->allocptrlock); - dn->dirty = 0; - dn->fileinfo = 0; - - np = diskfs_make_node (dn); - np->cache_id = inum; - - mutex_lock (&np->lock); - dn->hnext = nodehash[INOHASH(inum)]; - if (dn->hnext) - dn->hnext->dn->hprevp = &dn->hnext; - dn->hprevp = &nodehash[INOHASH(inum)]; - nodehash[INOHASH(inum)] = np; - spin_unlock (&diskfs_node_refcnt_lock); - - err = read_disknode (np); - - if (!diskfs_check_readonly () && !np->dn_stat.st_gen) - { - spin_lock (&gennumberlock); - if (++nextgennumber < diskfs_mtime->seconds) - nextgennumber = diskfs_mtime->seconds; - np->dn_stat.st_gen = nextgennumber; - spin_unlock (&gennumberlock); - np->dn_set_ctime = 1; - } - - if (err) - return err; - else - { - *npp = np; - return 0; - } -} - -/* Lookup node INUM (which must have a reference already) and return it - without allocating any new references. */ -struct node * -ifind (ino_t inum) -{ - struct node *np; - - spin_lock (&diskfs_node_refcnt_lock); - for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext) - { - if (np->dn->number != inum) - continue; - - assert (np->references); - spin_unlock (&diskfs_node_refcnt_lock); - return np; - } - assert (0); -} - -/* The last reference to a node has gone away; drop - it from the hash table and clean all state in the dn structure. */ -void -diskfs_node_norefs (struct node *np) -{ - *np->dn->hprevp = np->dn->hnext; - if (np->dn->hnext) - np->dn->hnext->dn->hprevp = np->dn->hprevp; - if (np->dn->dirents) - free (np->dn->dirents); - assert (!np->dn->fileinfo); - free (np->dn); - free (np); -} - -/* The last hard reference to a node has gone away; arrange to have - all the weak references dropped that can be. */ -void -diskfs_try_dropping_softrefs (struct node *np) -{ - drop_pager_softrefs (np); -} - -/* The last hard reference to a node has gone away. */ -void -diskfs_lost_hardrefs (struct node *np) -{ -#ifdef notanymore - struct port_info *pi; - struct pager *p; - - /* Check and see if there is a pager which has only - one reference (ours). If so, then drop that reference, - breaking the cycle. The complexity in this routine - is all due to this cycle. */ - - if (np->dn->fileinfo) - { - spin_lock (&_libports_portrefcntlock); - pi = (struct port_info *) np->dn->fileinfo->p; - if (pi->refcnt == 1) - { - - /* The only way to get a new reference to the pager - in this state is to call diskfs_get_filemap; this - can't happen as long as we hold NP locked. So - we can safely unlock _libports_portrefcntlock for - the following call. */ - spin_unlock (&_libports_portrefcntlock); - - /* Right now the node is locked with no hard refs; - this is an anomalous situation. Before messing with - the reference count on the file pager, we have to - give ourselves a reference back so that we are really - allowed to hold the lock. Then we can do the - unreference. */ - p = np->dn->fileinfo->p; - np->dn->fileinfo = 0; - diskfs_nref (np); - pager_unreference (p); - - assert (np->references == 1 && np->light_references == 0); - - /* This will do the real deallocate. Whew. */ - diskfs_nput (np); - } - else - spin_unlock (&_libports_portrefcntlock); - } -#endif -} - -/* A new hard reference to a node has been created; it's now OK to - have unused weak references. */ -void -diskfs_new_hardrefs (struct node *np) -{ - allow_pager_softrefs (np); -} - -/* Read stat information out of the dinode. */ -static error_t -read_disknode (struct node *np) -{ - struct stat *st = &np->dn_stat; - struct dinode *di = dino (np->dn->number); - error_t err; - - err = diskfs_catch_exception (); - if (err) - return err; - - st->st_fstype = FSTYPE_UFS; - st->st_fsid = getpid (); /* This call is very cheap. */ - st->st_ino = np->dn->number; - st->st_gen = read_disk_entry (di->di_gen); - st->st_rdev = read_disk_entry(di->di_rdev); - st->st_mode = (((read_disk_entry (di->di_model) - | (read_disk_entry (di->di_modeh) << 16)) - & ~S_ITRANS) - | (di->di_trans ? S_IPTRANS : 0)); - st->st_nlink = read_disk_entry (di->di_nlink); - st->st_size = read_disk_entry (di->di_size); - st->st_atim.tv_sec = read_disk_entry (di->di_atime.tv_sec); - st->st_atim.tv_nsec = read_disk_entry (di->di_atime.tv_nsec); - st->st_mtim.tv_sec = read_disk_entry (di->di_mtime.tv_sec); - st->st_mtim.tv_nsec = read_disk_entry (di->di_mtime.tv_nsec); - st->st_ctim.tv_sec = read_disk_entry (di->di_ctime.tv_sec); - st->st_ctim.tv_nsec = read_disk_entry (di->di_ctime.tv_nsec); - st->st_blksize = sblock->fs_bsize; - st->st_blocks = read_disk_entry (di->di_blocks); - st->st_flags = read_disk_entry (di->di_flags); - - if (sblock->fs_inodefmt < FS_44INODEFMT) - { - st->st_uid = read_disk_entry (di->di_ouid); - st->st_gid = read_disk_entry (di->di_ogid); - st->st_author = st->st_uid; - np->author_tracks_uid = 1; - } - else - { - st->st_uid = read_disk_entry (di->di_uid); - st->st_gid = read_disk_entry (di->di_gid); - st->st_author = read_disk_entry (di->di_author); - if (st->st_author == -1) - st->st_author = st->st_uid; - } - - diskfs_end_catch_exception (); - if (!S_ISBLK (st->st_mode) && !S_ISCHR (st->st_mode)) - st->st_rdev = 0; - - if (S_ISLNK (st->st_mode) - && direct_symlink_extension - && st->st_size < sblock->fs_maxsymlinklen) - np->allocsize = 0; - else - { - if (lblkno (sblock, np->dn_stat.st_size) < NDADDR) - np->allocsize = fragroundup (sblock, st->st_size); - else - np->allocsize = blkroundup (sblock, st->st_size); - } - - return 0; -} - -error_t diskfs_node_reload (struct node *node) -{ - if (node->dn->dirents) - { - free (node->dn->dirents); - node->dn->dirents = 0; - } - flush_node_pager (node); - read_disknode (node); - return 0; -} - -/* 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) -{ - if (compat_mode == COMPAT_GNU) - return 0; - else - /* For non-hurd filesystems, the author & owner are the same. */ - return (author == np->dn_stat.st_uid) ? 0 : EINVAL; -} - -static void -write_node (struct node *np) -{ - struct stat *st = &np->dn_stat; - struct dinode *di = dino (np->dn->number); - error_t err; - - if (np->dn_stat_dirty) - { - assert (!diskfs_readonly); - - err = diskfs_catch_exception (); - if (err) - return; - - write_disk_entry (di->di_gen, st->st_gen); - - if (S_ISBLK (st->st_mode) || S_ISCHR (st->st_mode)) - write_disk_entry (di->di_rdev, st->st_rdev); - - /* We happen to know that the stat mode bits are the same - as the ufs mode bits. */ - - if (compat_mode == COMPAT_GNU) - { - mode_t mode = st->st_mode & ~S_ITRANS; - write_disk_entry (di->di_model, mode & 0xffff); - write_disk_entry (di->di_modeh, (mode >> 16) & 0xffff); - } - else - { - write_disk_entry (di->di_model, st->st_mode & 0xffff & ~S_ITRANS); - di->di_modeh = 0; - } - - if (compat_mode != COMPAT_BSD42) - { - write_disk_entry (di->di_uid, st->st_uid); - write_disk_entry (di->di_gid, st->st_gid); - } - - if (sblock->fs_inodefmt < FS_44INODEFMT) - { - write_disk_entry (di->di_ouid, st->st_uid & 0xffff); - write_disk_entry (di->di_ogid, st->st_gid & 0xffff); - } - else if (compat_mode == COMPAT_GNU) - write_disk_entry (di->di_author, st->st_author); - - write_disk_entry (di->di_nlink, st->st_nlink); - write_disk_entry (di->di_size, st->st_size); - write_disk_entry (di->di_atime.tv_sec, st->st_atim.tv_sec); - write_disk_entry (di->di_atime.tv_nsec, st->st_atim.tv_nsec); - write_disk_entry (di->di_mtime.tv_sec, st->st_mtim.tv_sec); - write_disk_entry (di->di_mtime.tv_nsec, st->st_mtim.tv_nsec); - write_disk_entry (di->di_ctime.tv_sec, st->st_ctim.tv_sec); - write_disk_entry (di->di_ctime.tv_nsec, st->st_ctim.tv_nsec); - write_disk_entry (di->di_blocks, st->st_blocks); - write_disk_entry (di->di_flags, st->st_flags); - - diskfs_end_catch_exception (); - np->dn_stat_dirty = 0; - record_poke (di, sizeof (struct dinode)); - } -} - -/* See if we should create a symlink by writing it directly into - the block pointer array. Returning EINVAL tells diskfs to do it - the usual way. */ -static error_t -create_symlink_hook (struct node *np, const char *target) -{ - int len = strlen (target); - error_t err; - struct dinode *di; - - if (!direct_symlink_extension) - return EINVAL; - - assert (compat_mode != COMPAT_BSD42); - - if (len >= sblock->fs_maxsymlinklen) - return EINVAL; - - err = diskfs_catch_exception (); - if (err) - return err; - - di = dino (np->dn->number); - bcopy (target, di->di_shortlink, len); - np->dn_stat.st_size = len; - np->dn_set_ctime = 1; - np->dn_set_mtime = 1; - record_poke (di, sizeof (struct dinode)); - - diskfs_end_catch_exception (); - return 0; -} -error_t (*diskfs_create_symlink_hook)(struct node *, const char *) - = create_symlink_hook; - -/* Check if this symlink is stored directly in the block pointer array. - Returning EINVAL tells diskfs to do it the usual way. */ -static error_t -read_symlink_hook (struct node *np, - char *buf) -{ - error_t err; - - if (!direct_symlink_extension - || np->dn_stat.st_size >= sblock->fs_maxsymlinklen) - return EINVAL; - - err = diskfs_catch_exception (); - if (err) - return err; - - bcopy ((dino (np->dn->number))->di_shortlink, buf, np->dn_stat.st_size); - - diskfs_set_node_atime (np); - - diskfs_end_catch_exception (); - return 0; -} -error_t (*diskfs_read_symlink_hook)(struct node *, char *) - = read_symlink_hook; - -error_t -diskfs_node_iterate (error_t (*fun)(struct node *)) -{ - struct node *np; - struct item {struct item *next; struct node *np;} *list = 0; - struct item *i; - error_t err; - int n; - - /* Acquire a reference on all the nodes in the hash table - and enter them into a list on the stack. */ - spin_lock (&diskfs_node_refcnt_lock); - for (n = 0; n < INOHSZ; n++) - for (np = nodehash[n]; np; np = np->dn->hnext) - { - np->references++; - i = alloca (sizeof (struct item)); - i->next = list; - i->np = np; - list = i; - } - spin_unlock (&diskfs_node_refcnt_lock); - - err = 0; - for (i = list; i; i = i->next) - { - if (!err) - { - mutex_lock (&i->np->lock); - err = (*fun)(i->np); - mutex_unlock (&i->np->lock); - } - diskfs_nrele (i->np); - } - return err; -} - -/* Write all active disknodes into the dinode pager. */ -void -write_all_disknodes () -{ - error_t - helper (struct node *np) - { - diskfs_set_node_times (np); - write_node (np); - return 0; - } - - diskfs_node_iterate (helper); -} - -void -diskfs_write_disknode (struct node *np, int wait) -{ - write_node (np); - if (wait) - sync_dinode (np->dn->number, 1); -} - -/* Implement the diskfs_set_statfs callback from the diskfs library; - see <hurd/diskfs.h> for the interface description. */ -error_t -diskfs_set_statfs (struct statfs *st) -{ - st->f_type = FSTYPE_UFS; - st->f_bsize = sblock->fs_fsize; - st->f_blocks = sblock->fs_dsize; - st->f_bfree = (sblock->fs_cstotal.cs_nbfree * sblock->fs_frag - + sblock->fs_cstotal.cs_nffree); - st->f_bavail = ((sblock->fs_dsize * (100 - sblock->fs_minfree) / 100) - - (sblock->fs_dsize - st->f_bfree)); - if (st->f_bfree < ((sblock->fs_dsize * (100 - sblock->fs_minfree) / 100))) - st->f_bavail = 0; - st->f_files = sblock->fs_ncg * sblock->fs_ipg - 2; /* not 0 or 1 */ - st->f_ffree = sblock->fs_cstotal.cs_nifree; - st->f_fsid = getpid (); - st->f_namelen = 0; - st->f_favail = st->f_ffree; - st->f_frsize = sblock->fs_fsize; - return 0; -} - -/* Implement the diskfs_set_translator callback from the diskfs - library; see <hurd/diskfs.h> for the interface description. */ -error_t -diskfs_set_translator (struct node *np, const char *name, u_int namelen, - struct protid *cred) -{ - daddr_t blkno; - error_t err; - char buf[sblock->fs_bsize]; - struct dinode *di; - - if (compat_mode != COMPAT_GNU) - return EOPNOTSUPP; - - if (namelen + sizeof (u_int) > sblock->fs_bsize) - return ENAMETOOLONG; - - err = diskfs_catch_exception (); - if (err) - return err; - - di = dino (np->dn->number); - blkno = read_disk_entry (di->di_trans); - - if (namelen && !blkno) - { - /* Allocate block for translator */ - err = ffs_alloc (np, 0, 0, sblock->fs_bsize, &blkno, cred); - if (err) - { - diskfs_end_catch_exception (); - return err; - } - write_disk_entry (di->di_trans, blkno); - record_poke (di, sizeof (struct dinode)); - np->dn_set_ctime = 1; - } - else if (!namelen && blkno) - { - /* Clear block for translator going away. */ - ffs_blkfree (np, blkno, sblock->fs_bsize); - di->di_trans = 0; - record_poke (di, sizeof (struct dinode)); - np->dn_stat.st_blocks -= btodb (sblock->fs_bsize); - np->dn_stat.st_mode &= ~S_IPTRANS; - np->dn_set_ctime = 1; - } - - if (namelen) - { - bcopy (&namelen, buf, sizeof (u_int)); - bcopy (name, buf + sizeof (u_int), namelen); - - bcopy (buf, disk_image + fsaddr (sblock, blkno), sblock->fs_bsize); - sync_disk_blocks (blkno, sblock->fs_bsize, 1); - - np->dn_stat.st_mode |= S_IPTRANS; - np->dn_set_ctime = 1; - } - - diskfs_end_catch_exception (); - return err; -} - -/* Implement the diskfs_get_translator callback from the diskfs library. - See <hurd/diskfs.h> for the interface description. */ -error_t -diskfs_get_translator (struct node *np, char **namep, u_int *namelen) -{ - error_t err; - daddr_t blkno; - u_int datalen; - const void *transloc; - - err = diskfs_catch_exception (); - if (err) - return err; - - blkno = read_disk_entry ((dino (np->dn->number))->di_trans); - assert (blkno); - transloc = disk_image + fsaddr (sblock, blkno); - - datalen = *(u_int *)transloc; - if (datalen > sblock->fs_bsize - sizeof (u_int)) - err = EFTYPE; - else - { - *namep = malloc (datalen); - if (*namep == NULL) - err = ENOMEM; - memcpy (*namep, transloc + sizeof (u_int), datalen); - } - - diskfs_end_catch_exception (); - - *namelen = datalen; - return 0; -} - -/* Called when all hard ports have gone away. */ -void -diskfs_shutdown_soft_ports () -{ - /* Should initiate termination of internally held pager ports - (the only things that should be soft) XXX */ -} - -/* Return a description of the storage of the file. */ -/* In STORAGE_DATA are the following, in network byte order: - - Inode number (4 bytes) - disk address of transator spec (4 bytes) - disk address of inode structure (4 bytes) - offset into inode block holding inode (4 bytes) */ -error_t -diskfs_S_file_get_storage_info (struct protid *cred, - mach_port_t **ports, - mach_msg_type_name_t *ports_type, - mach_msg_type_number_t *num_ports, - int **ints, mach_msg_type_number_t *num_ints, - off_t **offsets, - mach_msg_type_number_t *num_offsets, - char **data, mach_msg_type_number_t *data_len) -{ - error_t err; - struct node *np; - struct store *file_store; - struct store_run runs[NDADDR]; - size_t num_runs = 0; - - if (! cred) - return EOPNOTSUPP; - - np = cred->po->np; - mutex_lock (&np->lock); - - /* See if this file fits in the direct block pointers. If not, punt - for now. (Reading indir blocks is a pain, and I'm postponing - pain.) XXX */ - if (np->allocsize > NDADDR * sblock->fs_bsize) - { - mutex_unlock (&np->lock); - return EINVAL; - } - - err = diskfs_catch_exception (); - if (! err) - if (!direct_symlink_extension - || np->dn_stat.st_size >= sblock->fs_maxsymlinklen - || !S_ISLNK (np->dn_stat.st_mode)) - /* Copy the block pointers */ - { - int i; - struct store_run *run = runs; - struct dinode *di = dino (np->dn->number); - - for (i = 0; i < NDADDR; i++) - { - store_offset_t start = fsbtodb (sblock, read_disk_entry (di->di_db[i])); - store_offset_t length = - (((i + 1) * sblock->fs_bsize > np->allocsize) - ? np->allocsize - i * sblock->fs_bsize - : sblock->fs_bsize); - start <<= log2_dev_blocks_per_dev_bsize; - length <<= log2_dev_blocks_per_dev_bsize; - if (num_runs == 0 || run->start + run->length != start) - *run++ = (struct store_run){ start, length }; - else - run->length += length; - } - } - diskfs_end_catch_exception (); - - mutex_unlock (&np->lock); - - if (! err) - err = store_clone (store, &file_store); - if (! err) - { - err = store_remap (file_store, runs, num_runs, &file_store); - if (! err) - err = store_return (file_store, ports, num_ports, ints, num_ints, - offsets, num_offsets, data, data_len); - store_free (file_store); - } - *ports_type = MACH_MSG_TYPE_COPY_SEND; - - return err; -} diff --git a/ufs/main.c b/ufs/main.c deleted file mode 100644 index 242107f4..00000000 --- a/ufs/main.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - Copyright (C) 1994,95,96,97,98,99,2002 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 "ufs.h" -#include <stdarg.h> -#include <stdio.h> -#include <error.h> -#include <device/device.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <argz.h> -#include <argp.h> -#include <hurd/store.h> - -struct node *diskfs_root_node; - -struct store *store = 0; -struct store_parsed *store_parsed = 0; - -char *diskfs_disk_name = 0; - -/* Number of device blocks per DEV_BSIZE block. */ -unsigned log2_dev_blocks_per_dev_bsize = 0; - -/* Set diskfs_root_node to the root inode. */ -static void -warp_root (void) -{ - error_t err; - err = diskfs_cached_lookup (2, &diskfs_root_node); - assert (!err); - mutex_unlock (&diskfs_root_node->lock); -} - -/* XXX */ -struct mutex printf_lock = MUTEX_INITIALIZER; -int printf (const char *fmt, ...) -{ - va_list arg; - int done; - va_start (arg, fmt); - mutex_lock (&printf_lock); - done = vprintf (fmt, arg); - mutex_unlock (&printf_lock); - va_end (arg); - return done; -} - -int diskfs_readonly; - -/* Ufs-specific options. XXX this should be moved so it can be done at - runtime as well as startup. */ -static const struct argp_option -options[] = -{ - {"compat", 'C', "FMT", 0, - "FMT may be GNU, 4.4, or 4.2, and determines which filesystem extensions" - " are written onto the disk (default is GNU)"}, - {0} -}; - -/* Parse a ufs-specific command line option. */ -static error_t -parse_opt (int key, char *arg, struct argp_state *state) -{ - switch (key) - { - enum compat_mode mode; - - case 'C': - if (strcasecmp (arg, "gnu") == 0) - mode = COMPAT_GNU; - else if (strcmp (arg, "4.4") == 0) - mode = COMPAT_BSD44; - else if (strcmp (arg, "4.2") == 0) - { - if (sblock - && (sblock->fs_inodefmt == FS_44INODEFMT - || direct_symlink_extension)) - { - argp_failure (state, 0, 0, - "4.2 compat mode requested on 4.4 fs"); - return EINVAL; - } - mode = COMPAT_BSD42; - } - else - { - argp_error (state, "%s: Unknown compatibility mode", arg); - return EINVAL; - } - - state->hook = (void *)mode; /* Save it for the end. */ - break; - - case ARGP_KEY_INIT: - state->child_inputs[0] = state->input; - state->hook = (void *)compat_mode; break; - case ARGP_KEY_SUCCESS: - compat_mode = (enum compat_mode)state->hook; break; - - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - -/* Add our startup arguments to the standard diskfs set. */ -static const struct argp_child startup_children[] = - {{&diskfs_store_startup_argp}, {0}}; -static struct argp startup_argp = {options, parse_opt, 0, 0, startup_children}; - -/* Similarly at runtime. */ -static const struct argp_child runtime_children[] = - {{&diskfs_std_runtime_argp}, {0}}; -static struct argp runtime_argp = {options, parse_opt, 0, 0, runtime_children}; - -struct argp *diskfs_runtime_argp = (struct argp *)&runtime_argp; - -/* Override the standard diskfs routine so we can add our own output. */ -error_t -diskfs_append_args (char **argz, size_t *argz_len) -{ - error_t err; - - /* Get the standard things. */ - err = diskfs_append_std_options (argz, argz_len); - - if (!err && compat_mode != COMPAT_GNU) - err = argz_add (argz, argz_len, - ((compat_mode == COMPAT_BSD42) - ? "--compat=4.2" - : "--compat=4.4")); - - if (! err) - err = store_parsed_append_args (store_parsed, argz, argz_len); - - return err; -} - -int -main (int argc, char **argv) -{ - mach_port_t bootstrap; - - /* Initialize the diskfs library, parse arguments, and open the store. - This starts the first diskfs thread for us. */ - store = diskfs_init_main (&startup_argp, argc, argv, - &store_parsed, &bootstrap); - - if (store->block_size > DEV_BSIZE) - error (4, 0, "%s: Bad device block size %zd (should be <= %d)", - diskfs_disk_name, store->block_size, DEV_BSIZE); - if (store->size < SBSIZE + SBOFF) - error (5, 0, "%s: Disk too small (%Ld bytes)", diskfs_disk_name, - store->size); - - log2_dev_blocks_per_dev_bsize = 0; - while ((1 << log2_dev_blocks_per_dev_bsize) < DEV_BSIZE) - log2_dev_blocks_per_dev_bsize++; - log2_dev_blocks_per_dev_bsize -= store->log2_block_size; - - /* Map the entire disk. */ - create_disk_pager (); - - get_hypermetadata (); - - inode_init (); - - /* Find our root node. */ - warp_root (); - - /* Now that we are all set up to handle requests, and diskfs_root_node is - set properly, it is safe to export our fsys control port to the - outside world. */ - diskfs_startup_diskfs (bootstrap, 0); - - /* SET HOST NAME */ - - /* And this thread is done with its work. */ - cthread_exit (0); - - return 0; -} - -error_t -diskfs_reload_global_state () -{ - flush_pokes (); - pager_flush (diskfs_disk_pager, 1); - get_hypermetadata (); - return 0; -} diff --git a/ufs/pager.c b/ufs/pager.c deleted file mode 100644 index 3038932d..00000000 --- a/ufs/pager.c +++ /dev/null @@ -1,806 +0,0 @@ -/* Pager for ufs - 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 "ufs.h" -#include <strings.h> -#include <stdio.h> -#include <unistd.h> -#include <hurd/store.h> - -spin_lock_t node2pagelock = SPIN_LOCK_INITIALIZER; - -spin_lock_t unlocked_pagein_lock = SPIN_LOCK_INITIALIZER; - -#ifdef DONT_CACHE_MEMORY_OBJECTS -#define MAY_CACHE 0 -#else -#define MAY_CACHE 1 -#endif - -struct port_bucket *pager_bucket; - -/* Mapped image of the disk. */ -void *disk_image; - -/* Find the location on disk of page OFFSET in pager UPI. Return the - disk address (in disk block) in *ADDR. If *NPLOCK is set on - return, then release that mutex after I/O on the data has - completed. Set DISKSIZE to be the amount of valid data on disk. - (If this is an unallocated block, then set *ADDR to zero.) - ISREAD is non-zero iff this is for a pagein. */ -static error_t -find_address (struct user_pager_info *upi, - vm_address_t offset, - daddr_t *addr, - int *disksize, - struct rwlock **nplock, - int isread) -{ - error_t err; - struct rwlock *lock; - - assert (upi->type == DISK || upi->type == FILE_DATA); - - if (upi->type == DISK) - { - *disksize = __vm_page_size; - *addr = offset / DEV_BSIZE; - *nplock = 0; - return 0; - } - else - { - struct iblock_spec indirs[NIADDR + 1]; - struct node *np; - - np = upi->np; - - if (isread) - { - try_again: - - /* If we should allow an unlocked pagein, do so. (This - still has a slight race; there could be a pageout in progress - which is blocked on NP->np->allocptrlock itself. In that - case the pagein that should proceed unimpeded is blocked - in the pager library waiting for the pageout to complete. - I think this is sufficiently rare to put it off for the time - being.) */ - - spin_lock (&unlocked_pagein_lock); - if (offset >= upi->allow_unlocked_pagein - && (offset + vm_page_size - <= upi->allow_unlocked_pagein + upi->unlocked_pagein_length)) - { - spin_unlock (&unlocked_pagein_lock); - *nplock = 0; - goto have_lock; - } - spin_unlock (&unlocked_pagein_lock); - - /* Block on the rwlock if necessary; but when we wake up, - don't acquire it; check again from the top. - This is mutated inline from rwlock.h. */ - lock = &np->dn->allocptrlock; - mutex_lock (&lock->master); - if (lock->readers == -1 || lock->writers_waiting) - { - lock->readers_waiting++; - condition_wait (&lock->wakeup, &lock->master); - lock->readers_waiting--; - mutex_unlock (&lock->master); - goto try_again; - } - lock->readers++; - mutex_unlock (&lock->master); - *nplock = lock; - } - else - { - rwlock_reader_lock (&np->dn->allocptrlock); - *nplock = &np->dn->allocptrlock; - } - - have_lock: - - if (offset >= np->allocsize) - { - if (*nplock) - rwlock_reader_unlock (*nplock); - if (isread) - return EIO; - else - { - *addr = 0; - *disksize = 0; - return 0; - } - } - - if (offset + __vm_page_size > np->allocsize) - *disksize = np->allocsize - offset; - else - *disksize = __vm_page_size; - - err = fetch_indir_spec (np, lblkno (sblock, offset), indirs); - if (err && *nplock) - rwlock_reader_unlock (*nplock); - else - { - if (indirs[0].bno) - *addr = (fsbtodb (sblock, indirs[0].bno) - + blkoff (sblock, offset) / DEV_BSIZE); - else - *addr = 0; - } - - return err; - } -} - - -/* Implement the pager_read_page callback from the pager library. See - <hurd/pager.h> for the interface description. */ -error_t -pager_read_page (struct user_pager_info *pager, - vm_offset_t page, - vm_address_t *buf, - int *writelock) -{ - error_t err; - struct rwlock *nplock; - daddr_t addr; - int disksize; - - err = find_address (pager, page, &addr, &disksize, &nplock, 1); - if (err) - return err; - - if (addr) - { - size_t read = 0; - err = store_read (store, addr << log2_dev_blocks_per_dev_bsize, - disksize, (void **)buf, &read); - if (read != disksize) - err = EIO; - if (!err && disksize != __vm_page_size) - bzero ((void *)(*buf + disksize), __vm_page_size - disksize); - *writelock = 0; - } - else - { -#if 0 - printf ("Write-locked pagein Object %#x\tOffset %#x\n", pager, page); - fflush (stdout); -#endif - *buf = (vm_address_t) mmap (0, vm_page_size, PROT_READ|PROT_WRITE, - MAP_ANON, 0, 0); - *writelock = 1; - } - - if (nplock) - rwlock_reader_unlock (nplock); - - return err; -} - -/* Implement the pager_write_page callback from the pager library. See - <hurd/pager.h> for the interface description. */ -error_t -pager_write_page (struct user_pager_info *pager, - vm_offset_t page, - vm_address_t buf) -{ - daddr_t addr; - int disksize; - struct rwlock *nplock; - error_t err; - - err = find_address (pager, page, &addr, &disksize, &nplock, 0); - if (err) - return err; - - if (addr) - { - size_t wrote; - err = store_write (store, addr << log2_dev_blocks_per_dev_bsize, - (void *)buf, disksize, &wrote); - if (wrote != disksize) - err = EIO; - } - else - err = 0; - - if (nplock) - rwlock_reader_unlock (nplock); - - return err; -} - -/* Implement the pager_unlock_page callback from the pager library. See - <hurd/pager.h> for the interface description. */ -error_t -pager_unlock_page (struct user_pager_info *pager, - vm_offset_t address) -{ - struct node *np; - error_t err; - struct iblock_spec indirs[NIADDR + 1]; - daddr_t bno; - struct disknode *dn; - struct dinode *di; - - /* Zero an sblock->fs_bsize piece of disk starting at BNO, - synchronously. We do this on newly allocated indirect - blocks before setting the pointer to them to ensure that an - indirect block absolutely never points to garbage. */ - void zero_disk_block (int bno) - { - bzero (indir_block (bno), sblock->fs_bsize); - sync_disk_blocks (bno, sblock->fs_bsize, 1); - }; - - /* Problem--where to get cred values for allocation here? */ - -#if 0 - printf ("Unlock page request, Object %#x\tOffset %#x...", pager, address); - fflush (stdout); -#endif - - if (pager->type == DISK) - return 0; - - np = pager->np; - dn = np->dn; - di = dino (dn->number); - - rwlock_writer_lock (&dn->allocptrlock); - - /* If this is the last block, we don't let it get unlocked. */ - if (address + __vm_page_size - > blkroundup (sblock, np->allocsize) - sblock->fs_bsize) - { - printf ("attempt to unlock at last block denied\n"); - fflush (stdout); - rwlock_writer_unlock (&dn->allocptrlock); - return EIO; - } - - err = fetch_indir_spec (np, lblkno (sblock, address), indirs); - if (err) - { - rwlock_writer_unlock (&dn->allocptrlock); - return EIO; - } - - err = diskfs_catch_exception (); - if (err) - { - rwlock_writer_unlock (&dn->allocptrlock); - return EIO; - } - - /* See if we need a triple indirect block; fail if we do. */ - assert (indirs[0].offset == -1 - || indirs[1].offset == -1 - || indirs[2].offset == -1); - - /* Check to see if this block is allocated. */ - if (indirs[0].bno == 0) - { - size_t wrote; - - if (indirs[0].offset == -1) - { - err = ffs_alloc (np, lblkno (sblock, address), - ffs_blkpref (np, lblkno (sblock, address), - lblkno (sblock, address), di->di_db), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - - assert (lblkno (sblock, address) < NDADDR); - err = store_write (store, - fsbtodb (sblock, bno) - << log2_dev_blocks_per_dev_bsize, - zeroblock, sblock->fs_bsize, &wrote); - if (!err && wrote != sblock->fs_bsize) - err = EIO; - if (err) - goto out; - - indirs[0].bno = bno; - write_disk_entry (di->di_db[lblkno (sblock, address)], bno); - record_poke (di, sizeof (struct dinode)); - } - else - { - daddr_t *siblock; - - /* We need to set siblock to the single indirect block - array; see if the single indirect block is allocated. */ - if (indirs[1].bno == 0) - { - if (indirs[1].offset == -1) - { - err = ffs_alloc (np, lblkno (sblock, address), - ffs_blkpref (np, lblkno (sblock, address), - INDIR_SINGLE, di->di_ib), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - zero_disk_block (bno); - indirs[1].bno = bno; - write_disk_entry (di->di_ib[INDIR_SINGLE], bno); - record_poke (di, sizeof (struct dinode)); - } - else - { - daddr_t *diblock; - - /* We need to set diblock to the double indirect - block array; see if the double indirect block is - allocated. */ - if (indirs[2].bno == 0) - { - /* This assert because triple indirection is - not supported. */ - assert (indirs[2].offset == -1); - - err = ffs_alloc (np, lblkno (sblock, address), - ffs_blkpref (np, lblkno (sblock, - address), - INDIR_DOUBLE, di->di_ib), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - zero_disk_block (bno); - indirs[2].bno = bno; - write_disk_entry (di->di_ib[INDIR_DOUBLE], bno); - record_poke (di, sizeof (struct dinode)); - } - - diblock = indir_block (indirs[2].bno); - mark_indir_dirty (np, indirs[2].bno); - - /* Now we can allocate the single indirect block */ - - err = ffs_alloc (np, lblkno (sblock, address), - ffs_blkpref (np, lblkno (sblock, address), - indirs[1].offset, diblock), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - zero_disk_block (bno); - indirs[1].bno = bno; - write_disk_entry (diblock[indirs[1].offset], bno); - record_poke (diblock, sblock->fs_bsize); - } - } - - siblock = indir_block (indirs[1].bno); - mark_indir_dirty (np, indirs[1].bno); - - /* Now we can allocate the data block. */ - - err = ffs_alloc (np, lblkno (sblock, address), - ffs_blkpref (np, lblkno (sblock, address), - indirs[0].offset, siblock), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - - err = store_write (store, - fsbtodb (sblock, bno) - << log2_dev_blocks_per_dev_bsize, - zeroblock, sblock->fs_bsize, &wrote); - if (!err && wrote != sblock->fs_bsize) - err = EIO; - if (err) - goto out; - - indirs[0].bno = bno; - write_disk_entry (siblock[indirs[0].offset], bno); - record_poke (siblock, sblock->fs_bsize); - } - } - - out: - diskfs_end_catch_exception (); - rwlock_writer_unlock (&dn->allocptrlock); - return err; -} - -/* Implement the pager_report_extent callback from the pager library. See - <hurd/pager.h> for the interface description. */ -inline error_t -pager_report_extent (struct user_pager_info *pager, - vm_address_t *offset, - vm_size_t *size) -{ - assert (pager->type == DISK || pager->type == FILE_DATA); - - *offset = 0; - - if (pager->type == DISK) - *size = store->size; - else - *size = pager->np->allocsize; - - return 0; -} - -/* Implement the pager_clear_user_data callback from the pager library. - See <hurd/pager.h> for the interface description. */ -void -pager_clear_user_data (struct user_pager_info *upi) -{ - /* XXX Do the right thing for the disk pager here too. */ - if (upi->type == FILE_DATA) - { - spin_lock (&node2pagelock); - if (upi->np->dn->fileinfo == upi) - upi->np->dn->fileinfo = 0; - spin_unlock (&node2pagelock); - diskfs_nrele_light (upi->np); - } - free (upi); -} - -void -pager_dropweak (struct user_pager_info *upi __attribute__ ((unused))) -{ -} - - - -/* Create the DISK pager. */ -void -create_disk_pager (void) -{ - struct user_pager_info *upi = malloc (sizeof (struct user_pager_info)); - - upi->type = DISK; - upi->np = 0; - pager_bucket = ports_create_bucket (); - diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, store->size, - &disk_image); - upi->p = diskfs_disk_pager; -} - -/* This syncs a single file (NP) to disk. Wait for all I/O to complete - if WAIT is set. NP->lock must be held. */ -void -diskfs_file_update (struct node *np, - int wait) -{ - struct dirty_indir *d, *tmp; - struct user_pager_info *upi; - - spin_lock (&node2pagelock); - upi = np->dn->fileinfo; - if (upi) - ports_port_ref (upi->p); - spin_unlock (&node2pagelock); - - if (upi) - { - pager_sync (upi->p, wait); - ports_port_deref (upi->p); - } - - for (d = np->dn->dirty; d; d = tmp) - { - sync_disk_blocks (d->bno, sblock->fs_bsize, wait); - tmp = d->next; - free (d); - } - np->dn->dirty = 0; - - diskfs_node_update (np, wait); -} - -/* Invalidate any pager data associated with NODE. */ -void -flush_node_pager (struct node *node) -{ - struct user_pager_info *upi; - struct disknode *dn = node->dn; - struct dirty_indir *dirty = dn->dirty; - - spin_lock (&node2pagelock); - upi = dn->fileinfo; - if (upi) - ports_port_ref (upi->p); - spin_unlock (&node2pagelock); - - if (upi) - { - pager_flush (upi->p, 1); - ports_port_deref (upi->p); - } - - dn->dirty = 0; - - while (dirty) - { - struct dirty_indir *next = dirty->next; - free (dirty); - dirty = next; - } -} - -/* Call this to create a FILE_DATA pager and return a send right. - NP must be locked. PROT is the max protection desired. */ -mach_port_t -diskfs_get_filemap (struct node *np, vm_prot_t prot) -{ - struct user_pager_info *upi; - mach_port_t right; - - assert (S_ISDIR (np->dn_stat.st_mode) - || S_ISREG (np->dn_stat.st_mode) - || (S_ISLNK (np->dn_stat.st_mode) - && (!direct_symlink_extension - || np->dn_stat.st_size >= sblock->fs_maxsymlinklen))); - - spin_lock (&node2pagelock); - do - if (!np->dn->fileinfo) - { - upi = malloc (sizeof (struct user_pager_info)); - upi->type = FILE_DATA; - upi->np = np; - upi->max_prot = prot; - upi->allow_unlocked_pagein = 0; - upi->unlocked_pagein_length = 0; - diskfs_nref_light (np); - upi->p = pager_create (upi, pager_bucket, - MAY_CACHE, MEMORY_OBJECT_COPY_DELAY); - if (upi->p == 0) - { - diskfs_nrele_light (np); - free (upi); - spin_unlock (&node2pagelock); - return MACH_PORT_NULL; - } - np->dn->fileinfo = upi; - right = pager_get_port (np->dn->fileinfo->p); - ports_port_deref (np->dn->fileinfo->p); - } - else - { - np->dn->fileinfo->max_prot |= prot; - - /* Because NP->dn->fileinfo->p is not a real reference, - this might be nearly deallocated. If that's so, then - the port right will be null. In that case, clear here - and loop. The deallocation will complete separately. */ - right = pager_get_port (np->dn->fileinfo->p); - if (right == MACH_PORT_NULL) - np->dn->fileinfo = 0; - } - while (right == MACH_PORT_NULL); - - spin_unlock (&node2pagelock); - - mach_port_insert_right (mach_task_self (), right, right, - MACH_MSG_TYPE_MAKE_SEND); - - return right; -} - -/* Call this when we should turn off caching so that unused memory object - ports get freed. */ -void -drop_pager_softrefs (struct node *np) -{ - struct user_pager_info *upi; - - spin_lock (&node2pagelock); - upi = np->dn->fileinfo; - if (upi) - ports_port_ref (upi->p); - spin_unlock (&node2pagelock); - - if (MAY_CACHE && upi) - pager_change_attributes (upi->p, 0, MEMORY_OBJECT_COPY_DELAY, 0); - if (upi) - ports_port_deref (upi->p); -} - -/* Call this when we should turn on caching because it's no longer - important for unused memory object ports to get freed. */ -void -allow_pager_softrefs (struct node *np) -{ - struct user_pager_info *upi; - - spin_lock (&node2pagelock); - upi = np->dn->fileinfo; - if (upi) - ports_port_ref (upi->p); - spin_unlock (&node2pagelock); - - if (MAY_CACHE && upi) - pager_change_attributes (upi->p, 1, MEMORY_OBJECT_COPY_DELAY, 0); - if (upi) - ports_port_deref (upi->p); -} - -static void -block_caching () -{ - error_t block_cache (void *arg) - { - struct pager *p = arg; - - pager_change_attributes (p, 0, MEMORY_OBJECT_COPY_DELAY, 1); - return 0; - } - - /* Loop through the pagers and turn off caching one by one, - synchronously. That should cause termination of each pager. */ - ports_bucket_iterate (pager_bucket, block_cache); -} - -static void -enable_caching () -{ - error_t enable_cache (void *arg) - { - struct pager *p = arg; - struct user_pager_info *upi = pager_get_upi (p); - - pager_change_attributes (p, 1, MEMORY_OBJECT_COPY_DELAY, 0); - - /* It's possible that we didn't have caching on before, because - the user here is the only reference to the underlying node - (actually, that's quite likely inside this particular - routine), and if that node has no links. So dinkle the node - ref counting scheme here, which will cause caching to be - turned off, if that's really necessary. */ - if (upi->type == FILE_DATA) - { - diskfs_nref (upi->np); - diskfs_nrele (upi->np); - } - - return 0; - } - - ports_bucket_iterate (pager_bucket, enable_cache); -} - -/* Tell diskfs if there are pagers exported, and if none, then - prevent any new ones from showing up. */ -int -diskfs_pager_users () -{ - int npagers = ports_count_bucket (pager_bucket); - - if (npagers <= 1) - return 0; - - if (MAY_CACHE) - { - block_caching (); - - /* Give it a second; the kernel doesn't actually shutdown - immediately. XXX */ - sleep (1); - - npagers = ports_count_bucket (pager_bucket); - if (npagers <= 1) - return 0; - - /* Darn, there are actual honest users. Turn caching back on, - and return failure. */ - enable_caching (); - } - - ports_enable_bucket (pager_bucket); - - return 1; -} - -/* 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 () -{ - vm_prot_t max_prot = 0; - int npagers = ports_count_bucket (pager_bucket); - - if (npagers > 1) - /* More than just the disk pager. */ - { - error_t add_pager_max_prot (void *v_p) - { - struct pager *p = v_p; - struct user_pager_info *upi = pager_get_upi (p); - if (upi->type == FILE_DATA) - max_prot |= upi->max_prot; - /* Stop iterating if MAX_PROT is as filled as it's going to get. */ - return max_prot == (VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); - } - - block_caching (); /* Make any silly pagers go away. */ - - /* Give it a second; the kernel doesn't actually shutdown - immediately. XXX */ - sleep (1); - - ports_bucket_iterate (pager_bucket, add_pager_max_prot); - - enable_caching (); - } - - ports_enable_bucket (pager_bucket); - - return max_prot; -} - -/* Call this to find out the struct pager * corresponding to the - FILE_DATA pager of inode IP. This should be used *only* as a subsequent - argument to register_memory_fault_area, and will be deleted when - the kernel interface is fixed. NP must be locked. */ -struct pager * -diskfs_get_filemap_pager_struct (struct node *np) -{ - /* This is safe because fileinfo can't be cleared; there must be - an active mapping for this to be called. */ - return np->dn->fileinfo->p; -} - -/* Shutdown all the pagers. */ -void -diskfs_shutdown_pager () -{ - error_t shutdown_one (void *arg) - { - struct pager *p = arg; - /* Don't ever shut down the disk pager. */ - if (p != diskfs_disk_pager) - pager_shutdown (p); - return 0; - } - - copy_sblock (); - write_all_disknodes (); - ports_bucket_iterate (pager_bucket, shutdown_one); - sync_disk (1); -} - -/* Sync all the pagers. */ -void -diskfs_sync_everything (int wait) -{ - error_t sync_one (void *arg) - { - struct pager *p = arg; - /* Make sure the disk pager is done last. */ - if (p != diskfs_disk_pager) - pager_sync (p, wait); - return 0; - } - - copy_sblock (); - write_all_disknodes (); - ports_bucket_iterate (pager_bucket, sync_one); - sync_disk (wait); -} diff --git a/ufs/pokeloc.c b/ufs/pokeloc.c deleted file mode 100644 index 267aa106..00000000 --- a/ufs/pokeloc.c +++ /dev/null @@ -1,85 +0,0 @@ -/* Remember where we've written the disk to speed up sync - Copyright (C) 1994, 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 "ufs.h" - -struct pokeloc -{ - vm_offset_t offset; - vm_size_t length; - struct pokeloc *next; -}; - -struct pokeloc *pokelist; -spin_lock_t pokelistlock = SPIN_LOCK_INITIALIZER; - -/* Remember that data here on the disk has been modified. */ -void -record_poke (void *loc, vm_size_t length) -{ - struct pokeloc *pl = malloc (sizeof (struct pokeloc)); - vm_offset_t offset; - - offset = loc - disk_image; - pl->offset = trunc_page (offset); - pl->length = round_page (offset + length) - pl->offset; - - spin_lock (&pokelistlock); - pl->next = pokelist; - pokelist = pl; - spin_unlock (&pokelistlock); -} - -/* Get rid of any outstanding pokes. */ -void -flush_pokes () -{ - struct pokeloc *pl; - - spin_lock (&pokelistlock); - pl = pokelist; - pokelist = 0; - spin_unlock (&pokelistlock); - - while (pl) - { - struct pokeloc *next = pl->next; - free (pl); - pl = next; - } -} - -/* Sync all the modified pieces of disk */ -void -sync_disk (int wait) -{ - struct pokeloc *pl, *tmp; - - spin_lock (&pokelistlock); - for (pl = pokelist; pl; pl = tmp) - { - pager_sync_some (diskfs_disk_pager, pl->offset, pl->length, wait); - tmp = pl->next; - free (pl); - } - pokelist = 0; - spin_unlock (&pokelistlock); -} - diff --git a/ufs/sizes.c b/ufs/sizes.c deleted file mode 100644 index 58cbfc98..00000000 --- a/ufs/sizes.c +++ /dev/null @@ -1,719 +0,0 @@ -/* File growth and truncation - Copyright (C) 1993, 1994, 1995, 1996, 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. */ - -/* Written by Michael I. Bushnell. */ - -#include "ufs.h" -#include <string.h> - -#ifdef DONT_CACHE_MEMORY_OBJECTS -#define MAY_CACHE 0 -#else -#define MAY_CACHE 1 -#endif - -static int indir_release (struct node *np, daddr_t bno, int level); -static void poke_pages (memory_object_t, vm_offset_t, vm_offset_t); - -/* Implement the diskfs_truncate callback; sse <hurd/diskfs.h> for the - interface description. */ -error_t -diskfs_truncate (struct node *np, - off_t length) -{ - int offset; - struct dinode *di = dino (np->dn->number); - volatile int blocksfreed = 0; - error_t err; - int i; - struct iblock_spec indirs[NIADDR + 1]; - volatile daddr_t lbn; - struct user_pager_info *upi; - - if (length >= np->dn_stat.st_size) - return 0; - - diskfs_check_readonly (); - assert (!diskfs_readonly); - - /* First check to see if this is a kludged symlink; if so - this is special. */ - if (direct_symlink_extension && S_ISLNK (np->dn_stat.st_mode) - && np->dn_stat.st_size < sblock->fs_maxsymlinklen) - { - error_t err; - - err = diskfs_catch_exception (); - if (err) - return err; - bzero ((char *)di->di_shortlink + length, np->dn_stat.st_size - length); - record_poke (di, sizeof (struct dinode)); - diskfs_end_catch_exception (); - np->dn_stat.st_size = length; - np->dn_set_ctime = np->dn_set_mtime = 1; - diskfs_node_update (np, 1); - return 0; - } - - /* If the file is not being trucated to a block boundary, - the zero the partial bit in the new last block. */ - offset = blkoff (sblock, length); - if (offset) - { - int bsize; /* size of new last block */ - int savesize = np->allocsize; - - np->allocsize = length; /* temporary */ - bsize = blksize (sblock, np, lblkno (sblock, length)); - np->allocsize = savesize; - diskfs_node_rdwr (np, zeroblock, length, bsize - offset, 1, 0, 0); - diskfs_file_update (np, 1); - } - - /* Now flush all the data past the new size from the kernel. - Also force any delayed copies of this data to take place - immediately. (We are implicitly changing the data to zeros - and doing it without the kernel's immediate knowledge; - accordingl we must help out the kernel thusly.) */ - spin_lock (&node2pagelock); - upi = np->dn->fileinfo; - if (upi) - ports_port_ref (upi->p); - spin_unlock (&node2pagelock); - - if (upi) - { - mach_port_t obj; - - pager_change_attributes (upi->p, MAY_CACHE, - MEMORY_OBJECT_COPY_NONE, 1); - obj = diskfs_get_filemap (np, VM_PROT_READ | VM_PROT_WRITE); - if (obj != MACH_PORT_NULL) - { - /* XXX should cope with errors from diskfs_get_filemap */ - poke_pages (obj, round_page (length), round_page (np->allocsize)); - mach_port_deallocate (mach_task_self (), obj); - pager_flush_some (upi->p, round_page (length), - np->allocsize - length, 1); - } - ports_port_deref (upi->p); - } - - rwlock_writer_lock (&np->dn->allocptrlock); - - /* Update the size on disk; fsck will finish freeing blocks if necessary - should we crash. */ - np->dn_stat.st_size = length; - np->dn_set_mtime = 1; - np->dn_set_ctime = 1; - diskfs_node_update (np, 1); - - /* Find out the location information for the last block to - be retained */ - lbn = lblkno (sblock, length - 1); - err = fetch_indir_spec (np, lbn, indirs); - /* err XXX */ - - /* We don't support triple indirs */ - assert (indirs[3].offset == -2); - - err = diskfs_catch_exception (); - /* err XXX */ - - /* BSD carefully finds out how far to clear; it's vastly simpler - to just clear everything after the new last block. */ - - /* Free direct blocks */ - if (indirs[0].offset < 0) - { - /* ...mapped from the inode. */ - for (i = lbn + 1; i < NDADDR; i++) - if (di->di_db[i]) - { - long bsize = blksize (sblock, np, i); - ffs_blkfree (np, read_disk_entry (di->di_db[i]), bsize); - di->di_db[i] = 0; - blocksfreed += btodb (bsize); - } - } - else - { - /* ... or mapped from sindir */ - if (indirs[1].bno) - { - daddr_t *sindir = indir_block (indirs[1].bno); - for (i = indirs[0].offset + 1; i < NINDIR (sblock); i++) - if (sindir[i]) - { - ffs_blkfree (np, read_disk_entry (sindir[i]), - sblock->fs_bsize); - sindir[i] = 0; - blocksfreed += btodb (sblock->fs_bsize); - } - record_poke (sindir, sblock->fs_bsize); - } - } - - /* Free single indirect blocks */ - if (indirs[1].offset < 0) - { - /* ...mapped from the inode */ - if (di->di_ib[INDIR_SINGLE] && indirs[1].offset == -2) - { - blocksfreed += indir_release (np, - read_disk_entry (di->di_ib - [INDIR_SINGLE]), - INDIR_SINGLE); - di->di_ib[INDIR_SINGLE] = 0; - } - } - else - { - /* ...or mapped from dindir */ - if (indirs[2].bno) - { - daddr_t *dindir = indir_block (indirs[2].bno); - for (i = indirs[1].offset + 1; i < NINDIR (sblock); i++) - if (dindir[i]) - { - blocksfreed += indir_release (np, - read_disk_entry (dindir[i]), - INDIR_SINGLE); - dindir[i] = 0; - } - record_poke (dindir, sblock->fs_bsize); - } - } - - /* Free double indirect block */ - assert (indirs[2].offset < 0); /* which must be mapped from the inode */ - if (indirs[2].offset == -2) - { - if (di->di_ib[INDIR_DOUBLE]) - { - blocksfreed += indir_release (np, - read_disk_entry (di->di_ib - [INDIR_DOUBLE]), - INDIR_DOUBLE); - di->di_ib[INDIR_DOUBLE] = 0; - } - } - - /* Finally, check to see if the new last direct block is - changing size; if so release any frags necessary. */ - if (lbn >= 0 && lbn < NDADDR && di->di_db[lbn]) - { - long oldspace, newspace; - daddr_t bn; - - bn = read_disk_entry (di->di_db[lbn]); - oldspace = blksize (sblock, np, lbn); - np->allocsize = fragroundup (sblock, length); - newspace = blksize (sblock, np, lbn); - - assert (newspace); - - if (oldspace - newspace) - { - bn += numfrags (sblock, newspace); - ffs_blkfree (np, bn, oldspace - newspace); - blocksfreed += btodb (oldspace - newspace); - } - } - else - { - if (lbn > NDADDR) - np->allocsize = blkroundup (sblock, length); - else - np->allocsize = fragroundup (sblock, length); - } - - record_poke (di, sizeof (struct dinode)); - - np->dn_stat.st_blocks -= blocksfreed; - np->dn_set_ctime = 1; - diskfs_node_update (np, 1); - - rwlock_writer_unlock (&np->dn->allocptrlock); - - /* At this point the last block (as defined by np->allocsize) - might not be allocated. We need to allocate it to maintain - the rule that the last block of a file is always allocated. */ - - if (np->allocsize && indirs[0].bno == 0) - { - /* The strategy is to reduce LBN until we get one that's allocated; - then reduce allocsize accordingly, then call diskfs_grow. */ - - do - err = fetch_indir_spec (np, --lbn, indirs); - /* err XXX */ - while (indirs[0].bno == 0 && lbn >= 0); - - assert ((lbn + 1) * sblock->fs_bsize < np->allocsize); - np->allocsize = (lbn + 1) * sblock->fs_bsize; - - diskfs_grow (np, length, 0); - } - - diskfs_end_catch_exception (); - - /* Now we can permit delayed copies again. */ - spin_lock (&node2pagelock); - upi = np->dn->fileinfo; - if (upi) - ports_port_ref (upi->p); - spin_unlock (&node2pagelock); - if (upi) - { - pager_change_attributes (upi->p, MAY_CACHE, - MEMORY_OBJECT_COPY_DELAY, 0); - ports_port_deref (upi->p); - } - - return err; -} - -/* Free indirect block BNO of level LEVEL; recursing if necessary - to free other indirect blocks. Return the number of disk - blocks freed. */ -static int -indir_release (struct node *np, daddr_t bno, int level) -{ - int count = 0; - daddr_t *addrs; - int i; - struct dirty_indir *d, *prev, *next; - - assert (bno); - - addrs = indir_block (bno); - for (i = 0; i < NINDIR (sblock); i++) - if (addrs[i]) - { - if (level == INDIR_SINGLE) - { - ffs_blkfree (np, read_disk_entry (addrs[i]), sblock->fs_bsize); - count += btodb (sblock->fs_bsize); - } - else - count += indir_release (np, read_disk_entry (addrs[i]), level - 1); - } - - /* Subtlety: this block is no longer necessary; the information - the kernel has cached corresponding to ADDRS is now unimportant. - Consider that if this block is allocated to a file, it will then - be double cached and the kernel might decide to write out - the disk_image version of the block. So we have to flush - the block from the kernel's memory, making sure we do it - synchronously--and BEFORE we attach it to the free list - with ffs_blkfree. */ - pager_flush_some (diskfs_disk_pager, fsaddr (sblock, bno), sblock->fs_bsize, 1); - - /* We should also take this block off the inode's list of - dirty indirect blocks if it's there. */ - prev = 0; - d = np->dn->dirty; - while (d) - { - next = d->next; - if (d->bno == bno) - { - if (prev) - prev->next = next; - else - np->dn->dirty = next; - free (d); - } - else - { - prev = d; - next = d->next; - } - d = next; - } - - /* Free designated block */ - ffs_blkfree (np, bno, sblock->fs_bsize); - count += btodb (sblock->fs_bsize); - - return count; -} - - -/* Offer data at BUF from START of LEN bytes of file NP. */ -void -offer_data (struct node *np, - off_t start, - size_t len, - vm_address_t buf) -{ - vm_address_t addr; - - len = round_page (len); - - assert (start % vm_page_size == 0); - - assert (np->dn->fileinfo); - for (addr = start; addr < start + len; addr += vm_page_size) - pager_offer_page (np->dn->fileinfo->p, 1, 0, addr, buf + (addr - start)); -} - -/* Logical block LBN of node NP has been extended with ffs_realloccg. - It used to be allocated at OLD_PBN and is now at NEW_PBN. The old - size was OLD_SIZE; it is now NEW_SIZE bytes long. Arrange for the data - on disk to be kept consistent, and free the old block if it has moved. - Return one iff we've actually moved data around on disk. */ -int -block_extended (struct node *np, - daddr_t lbn, - daddr_t old_pbn, - daddr_t new_pbn, - size_t old_size, - size_t new_size) -{ - /* Make sure that any pages of this block which just became allocated - don't get paged in from disk. */ - if (round_page (old_size) < round_page (new_size)) - offer_data (np, lbn * sblock->fs_bsize + round_page (old_size), - round_page (new_size) - round_page (old_size), - (vm_address_t)zeroblock); - - if (old_pbn != new_pbn) - { - memory_object_t mapobj; - error_t err; - vm_address_t mapaddr; - volatile int *pokeaddr; - - /* Map in this part of the file */ - mapobj = diskfs_get_filemap (np, VM_PROT_WRITE | VM_PROT_READ); - - /* XXX Should cope with errors from diskfs_get_filemap and back - out the operation here. */ - assert (mapobj); - - err = vm_map (mach_task_self (), &mapaddr, round_page (old_size), 0, 1, - mapobj, lbn * sblock->fs_bsize, 0, - VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|VM_PROT_WRITE, 0); - assert_perror (err); - - /* Allow these pageins to occur even though we're holding the lock */ - spin_lock (&unlocked_pagein_lock); - np->dn->fileinfo->allow_unlocked_pagein = lbn * sblock->fs_bsize; - np->dn->fileinfo->unlocked_pagein_length = round_page (old_size); - spin_unlock (&unlocked_pagein_lock); - - /* Make sure all waiting pageins see this change. */ - mutex_lock (&np->dn->allocptrlock.master); - condition_broadcast (&np->dn->allocptrlock.wakeup); - mutex_unlock (&np->dn->allocptrlock.master); - - /* Force the pages in core and make sure they are dirty */ - for (pokeaddr = (int *)mapaddr; - pokeaddr < (int *) (mapaddr + round_page (old_size)); - pokeaddr += vm_page_size / sizeof (*pokeaddr)) - *pokeaddr = *pokeaddr; - - /* Turn off the special pagein permission */ - spin_lock (&unlocked_pagein_lock); - np->dn->fileinfo->allow_unlocked_pagein = 0; - np->dn->fileinfo->unlocked_pagein_length = 0; - spin_unlock (&unlocked_pagein_lock); - - /* Undo mapping */ - mach_port_deallocate (mach_task_self (), mapobj); - munmap ((caddr_t) mapaddr, round_page (old_size)); - - /* Now it's OK to free the old block */ - ffs_blkfree (np, old_pbn, old_size); - - /* Tell caller that we've moved data */ - return 1; - } - else - return 0; -} - - -/* Implement the diskfs_grow callback; see <hurd/diskfs.h> for the - interface description. */ -error_t -diskfs_grow (struct node *np, - off_t end, - struct protid *cred) -{ - daddr_t lbn, olbn; - int size, osize; - error_t err; - struct dinode *di = dino (np->dn->number); - mach_port_t pagerpt; - int need_sync = 0; - - /* Zero an sblock->fs_bsize piece of disk starting at BNO, - synchronously. We do this on newly allocated indirect - blocks before setting the pointer to them to ensure that an - indirect block absolutely never points to garbage. */ - void zero_disk_block (int bno) - { - bzero (indir_block (bno), sblock->fs_bsize); - sync_disk_blocks (bno, sblock->fs_bsize, 1); - }; - - /* Check to see if we don't actually have to do anything */ - if (end <= np->allocsize) - return 0; - - diskfs_check_readonly (); - assert (!diskfs_readonly); - - /* This reference will ensure that NP->dn->fileinfo stays allocated. */ - pagerpt = diskfs_get_filemap (np, VM_PROT_WRITE|VM_PROT_READ); - - if (pagerpt == MACH_PORT_NULL) - return errno; - - /* The new last block of the file. */ - lbn = lblkno (sblock, end - 1); - - /* This is the size of that block if it is in the NDADDR array. */ - size = fragroundup (sblock, blkoff (sblock, end)); - if (size == 0) - size = sblock->fs_bsize; - - rwlock_writer_lock (&np->dn->allocptrlock); - - /* The old last block of the file. */ - olbn = lblkno (sblock, np->allocsize - 1); - - /* This is the size of that block if it is in the NDADDR array. */ - osize = fragroundup (sblock, blkoff (sblock, np->allocsize)); - if (osize == 0) - osize = sblock->fs_bsize; - - /* If this end point is a new block and the file currently - has a fragment, then expand the fragment to a full block. */ - if (np->allocsize && olbn < NDADDR && olbn < lbn) - { - if (osize < sblock->fs_bsize) - { - daddr_t old_pbn, bno; - err = ffs_realloccg (np, olbn, - ffs_blkpref (np, lbn, lbn, di->di_db), - osize, sblock->fs_bsize, &bno, cred); - if (err) - goto out; - - old_pbn = read_disk_entry (di->di_db[olbn]); - - need_sync = block_extended (np, olbn, old_pbn, bno, - osize, sblock->fs_bsize); - - write_disk_entry (di->di_db[olbn], bno); - record_poke (di, sizeof (struct dinode)); - np->dn_set_ctime = 1; - } - } - - if (lbn < NDADDR) - { - daddr_t bno, old_pbn = read_disk_entry (di->di_db[lbn]); - - if (old_pbn != 0) - { - /* The last block is already allocated. Therefore we - must be expanding the fragment. Make sure that's really - what we're up to. */ - assert (size > osize); - assert (lbn == olbn); - - err = ffs_realloccg (np, lbn, - ffs_blkpref (np, lbn, lbn, di->di_db), - osize, size, &bno, cred); - if (err) - goto out; - - need_sync = block_extended (np, lbn, old_pbn, bno, osize, size); - - write_disk_entry (di->di_db[lbn], bno); - record_poke (di, sizeof (struct dinode)); - np->dn_set_ctime = 1; - } - else - { - /* Allocate a new last block. */ - err = ffs_alloc (np, lbn, - ffs_blkpref (np, lbn, lbn, di->di_db), - size, &bno, cred); - if (err) - goto out; - - - offer_data (np, lbn * sblock->fs_bsize, size, - (vm_address_t)zeroblock); - write_disk_entry (di->di_db[lbn], bno); - record_poke (di, sizeof (struct dinode)); - np->dn_set_ctime = 1; - } - } - else - { - struct iblock_spec indirs[NIADDR + 1]; - daddr_t *siblock; - daddr_t bno; - - /* Count the number of levels of indirection. */ - err = fetch_indir_spec (np, lbn, indirs); - if (err) - goto out; - - /* Make sure we didn't miss the NDADDR case - above somehow. */ - assert (indirs[0].offset != -1); - - /* See if we need a triple indirect block; fail if so. */ - assert (indirs[1].offset == -1 || indirs[2].offset == -1); - - /* Check to see if this block is allocated. If it is - that's an error. */ - assert (indirs[0].bno == 0); - - /* We need to set SIBLOCK to the single indirect block - array; see if the single indirect block is allocated. */ - if (indirs[1].bno == 0) - { - /* Allocate it. */ - if (indirs[1].offset == -1) - { - err = ffs_alloc (np, lbn, - ffs_blkpref (np, lbn, INDIR_SINGLE, di->di_ib), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - zero_disk_block (bno); - indirs[1].bno = bno; - write_disk_entry (di->di_ib[INDIR_SINGLE], bno); - record_poke (di, sizeof (struct dinode)); - } - else - { - daddr_t *diblock; - - /* We need to set diblock to the double indirect block - array; see if the double indirect block is allocated. */ - if (indirs[2].bno == 0) - { - /* This assert because triple indirection is not - supported. */ - assert (indirs[2].offset == -1); - err = ffs_alloc (np, lbn, - ffs_blkpref (np, lbn, - INDIR_DOUBLE, di->di_ib), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - zero_disk_block (bno); - indirs[2].bno = bno; - write_disk_entry (di->di_ib[INDIR_DOUBLE], bno); - record_poke (di, sizeof (struct dinode)); - } - - diblock = indir_block (indirs[2].bno); - mark_indir_dirty (np, indirs[2].bno); - - /* Now we can allocate the single indirect block */ - err = ffs_alloc (np, lbn, - ffs_blkpref (np, lbn, - indirs[1].offset, diblock), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - zero_disk_block (bno); - indirs[1].bno = bno; - write_disk_entry (diblock[indirs[1].offset], bno); - record_poke (diblock, sblock->fs_bsize); - } - } - - siblock = indir_block (indirs[1].bno); - mark_indir_dirty (np, indirs[1].bno); - - /* Now we can allocate the data block. */ - err = ffs_alloc (np, lbn, - ffs_blkpref (np, lbn, indirs[0].offset, siblock), - sblock->fs_bsize, &bno, 0); - if (err) - goto out; - offer_data (np, lbn * sblock->fs_bsize, sblock->fs_bsize, - (vm_address_t)zeroblock); - indirs[0].bno = bno; - write_disk_entry (siblock[indirs[0].offset], bno); - record_poke (siblock, sblock->fs_bsize); - } - - out: - mach_port_deallocate (mach_task_self (), pagerpt); - if (!err) - { - int newallocsize; - if (lbn < NDADDR) - newallocsize = lbn * sblock->fs_bsize + size; - else - newallocsize = (lbn + 1) * sblock->fs_bsize; - assert (newallocsize > np->allocsize); - np->allocsize = newallocsize; - } - - rwlock_writer_unlock (&np->dn->allocptrlock); - - if (need_sync) - diskfs_file_update (np, 1); - - return err; -} - -/* Write something to each page from START to END inclusive of memory - object OBJ, but make sure the data doesns't actually change. */ -static void -poke_pages (memory_object_t obj, - vm_offset_t start, - vm_offset_t end) -{ - vm_address_t addr, poke; - vm_size_t len; - error_t err; - - while (start < end) - { - len = 8 * vm_page_size; - if (len > end - start) - len = end - start; - addr = 0; - err = vm_map (mach_task_self (), &addr, len, 0, 1, obj, start, 0, - VM_PROT_WRITE|VM_PROT_READ, VM_PROT_READ|VM_PROT_WRITE, 0); - if (!err) - { - for (poke = addr; poke < addr + len; poke += vm_page_size) - *(volatile int *)poke = *(volatile int *)poke; - munmap ((caddr_t) addr, len); - } - start += len; - } -} - diff --git a/ufs/subr.c b/ufs/subr.c deleted file mode 100644 index 2b356ddc..00000000 --- a/ufs/subr.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ffs_subr.c 8.2 (Berkeley) 9/21/93 - */ - -#include "ufs.h" - -#if 0 /* Not needed in GNU Hurd ufs. */ -/* - * Return buffer with the contents of block "offset" from the beginning of - * directory "ip". If "res" is non-zero, fill it in with a pointer to the - * remaining space in the directory. - */ -int -ffs_blkatoff(ap) - struct vop_blkatoff_args /* { - struct vnode *a_vp; - off_t a_offset; - char **a_res; - struct buf **a_bpp; - } */ *ap; -{ - struct inode *ip; - register struct fs *fs; - struct buf *bp; - daddr_t lbn; - int bsize, error; - - ip = VTOI(ap->a_vp); - fs = ip->i_fs; - lbn = lblkno(fs, ap->a_offset); - bsize = blksize(fs, ip, lbn); - - *ap->a_bpp = NULL; - if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) { - brelse(bp); - return (error); - } - if (ap->a_res) - *ap->a_res = (char *)bp->b_data + blkoff(fs, ap->a_offset); - *ap->a_bpp = bp; - return (0); -} -#endif /* 0 */ - -/* - * Update the frsum fields to reflect addition or deletion - * of some frags. - */ -void -ffs_fragacct(fs, fragmap, fraglist, cnt) - struct fs *fs; - int fragmap; - long fraglist[]; - int cnt; -{ - int inblk; - register int field, subfield; - register int siz, pos; - - inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; - fragmap <<= 1; - for (siz = 1; siz < fs->fs_frag; siz++) { - if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) - continue; - field = around[siz]; - subfield = inside[siz]; - for (pos = siz; pos <= fs->fs_frag; pos++) { - if ((fragmap & field) == subfield) { - fraglist[siz] += cnt; - pos += siz; - field <<= siz; - subfield <<= siz; - } - field <<= 1; - subfield <<= 1; - } - } -} - -#if 0 /* Not needed in GNU Hurd ufs. */ -void -ffs_checkoverlap(bp, ip) - struct buf *bp; - struct inode *ip; -{ - register struct buf *ebp, *ep; - register daddr_t start, last; - struct vnode *vp; - - ebp = &buf[nbuf]; - start = bp->b_blkno; - last = start + btodb(bp->b_bcount) - 1; - for (ep = buf; ep < ebp; ep++) { - if (ep == bp || (ep->b_flags & B_INVAL) || - ep->b_vp == NULLVP) - continue; - if (VOP_BMAP(ep->b_vp, (daddr_t)0, &vp, (daddr_t)0, NULL)) - continue; - if (vp != ip->i_devvp) - continue; - /* look for overlap */ - if (ep->b_bcount == 0 || ep->b_blkno > last || - ep->b_blkno + btodb(ep->b_bcount) <= start) - continue; - vprint("Disk overlap", vp); - (void)printf("\tstart %d, end %d overlap start %d, end %d\n", - start, last, ep->b_blkno, - ep->b_blkno + btodb(ep->b_bcount) - 1); - panic("Disk buffer overlap"); - } -} -#endif /* 0 */ - -/* - * block operations - * - * check if a block is available - */ -int -ffs_isblock(fs, cp, h) - struct fs *fs; - unsigned char *cp; - daddr_t h; -{ - unsigned char mask; - - switch ((int)fs->fs_frag) { - case 8: - return (cp[h] == 0xff); - case 4: - mask = 0x0f << ((h & 0x1) << 2); - return ((cp[h >> 1] & mask) == mask); - case 2: - mask = 0x03 << ((h & 0x3) << 1); - return ((cp[h >> 2] & mask) == mask); - case 1: - mask = 0x01 << (h & 0x7); - return ((cp[h >> 3] & mask) == mask); - default: - assert (0); - } -} - -/* - * take a block out of the map - */ -void -ffs_clrblock(fs, cp, h) - struct fs *fs; - u_char *cp; - daddr_t h; -{ - - switch ((int)fs->fs_frag) { - case 8: - cp[h] = 0; - return; - case 4: - cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); - return; - case 2: - cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); - return; - case 1: - cp[h >> 3] &= ~(0x01 << (h & 0x7)); - return; - default: - assert (0); - } -} - -/* - * put a block into the map - */ -void -ffs_setblock(fs, cp, h) - struct fs *fs; - unsigned char *cp; - daddr_t h; -{ - - switch ((int)fs->fs_frag) { - - case 8: - cp[h] = 0xff; - return; - case 4: - cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); - return; - case 2: - cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); - return; - case 1: - cp[h >> 3] |= (0x01 << (h & 0x7)); - return; - default: - assert (0); - } -} - -/* Taken from 4.4 BSD sys/libkern/skpc.c: - @(#)skpc.c 8.1 (Berkeley) 6/10/93 -*/ -int -skpc(mask0, size, cp0) - int mask0; - int size; - char *cp0; -{ - register u_char *cp, *end, mask; - - mask = mask0; - cp = (u_char *)cp0; - for (end = &cp[size]; cp < end && *cp == mask; ++cp); - return (end - cp); -} - -/* Taken from 4.4 BSD sys/libkern/scanc.c: - @(#)scanc.c 8.1 (Berkeley) 6/10/93 -*/ -int -scanc(size, cp, table, mask0) - u_int size; - register u_char *cp, table[]; - int mask0; -{ - register u_char *end; - register u_char mask; - - mask = mask0; - for (end = &cp[size]; cp < end && (table[*cp] & mask) == 0; ++cp); - return (end - cp); -} diff --git a/ufs/tables.c b/ufs/tables.c deleted file mode 100644 index d345b9e4..00000000 --- a/ufs/tables.c +++ /dev/null @@ -1,138 +0,0 @@ -/* Modified from BSD for GNU Hurd ufs server by Michael I. Bushnell. */ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ffs_tables.c 8.1 (Berkeley) 6/11/93 - */ - -#include <sys/types.h> -#include "fs.h" - -/* - * Bit patterns for identifying fragments in the block map - * used as ((map & around) == inside) - */ -int around[9] = { - 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff -}; -int inside[9] = { - 0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe -}; - -/* - * Given a block map bit pattern, the frag tables tell whether a - * particular size fragment is available. - * - * used as: - * if ((1 << (size - 1)) & fragtbl[fs->fs_frag][map] { - * at least one fragment of the indicated size is available - * } - * - * These tables are used by the scanc instruction on the VAX to - * quickly find an appropriate fragment. - */ -u_char fragtbl124[256] = { - 0x00, 0x16, 0x16, 0x2a, 0x16, 0x16, 0x26, 0x4e, - 0x16, 0x16, 0x16, 0x3e, 0x2a, 0x3e, 0x4e, 0x8a, - 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, - 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, - 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, - 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, - 0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e, - 0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa, - 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, - 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, - 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, - 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, - 0x26, 0x36, 0x36, 0x2e, 0x36, 0x36, 0x26, 0x6e, - 0x36, 0x36, 0x36, 0x3e, 0x2e, 0x3e, 0x6e, 0xae, - 0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e, - 0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce, - 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, - 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, - 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, - 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, - 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, - 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e, - 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, - 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe, - 0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e, - 0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa, - 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, - 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe, - 0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e, - 0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce, - 0x8a, 0x9e, 0x9e, 0xaa, 0x9e, 0x9e, 0xae, 0xce, - 0x9e, 0x9e, 0x9e, 0xbe, 0xaa, 0xbe, 0xce, 0x8a, -}; - -u_char fragtbl8[256] = { - 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04, - 0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08, - 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, - 0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10, - 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, - 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, - 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, - 0x04, 0x05, 0x05, 0x06, 0x08, 0x09, 0x10, 0x20, - 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, - 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, - 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, - 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11, - 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, - 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a, - 0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, - 0x08, 0x09, 0x09, 0x0a, 0x10, 0x11, 0x20, 0x40, - 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, - 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, - 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, - 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11, - 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, - 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, - 0x05, 0x05, 0x05, 0x07, 0x09, 0x09, 0x11, 0x21, - 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, - 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, - 0x02, 0x03, 0x03, 0x02, 0x06, 0x07, 0x0a, 0x12, - 0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, - 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x04, 0x0c, - 0x08, 0x09, 0x09, 0x0a, 0x09, 0x09, 0x0a, 0x0c, - 0x10, 0x11, 0x11, 0x12, 0x20, 0x21, 0x40, 0x80, -}; - -/* - * The actual fragtbl array. - */ -u_char *fragtbl[MAXFRAG + 1] = { - 0, fragtbl124, fragtbl124, 0, fragtbl124, 0, 0, 0, fragtbl8, -}; diff --git a/ufs/ufs.h b/ufs/ufs.h deleted file mode 100644 index 5d823ebc..00000000 --- a/ufs/ufs.h +++ /dev/null @@ -1,289 +0,0 @@ -/* - 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 <mach.h> -#include <hurd.h> -#include <sys/mman.h> -#include <hurd/ports.h> -#include <hurd/pager.h> -#include <hurd/fshelp.h> -#include <hurd/iohelp.h> -#include <hurd/diskfs.h> -#include <sys/mman.h> -#include <assert.h> -#include "fs.h" -#include "dinode.h" - -/* Define this if memory objects should not be cached by the kernel. - Normally, don't define it, but defining it causes a much greater rate - of paging requests, which may be helpful in catching bugs. */ - -/* #undef DONT_CACHE_MEMORY_OBJECTS */ - -struct disknode -{ - ino_t number; - - int dir_idx; - - /* For a directory, this array holds the number of directory entries in - each DIRBLKSIZE piece of the directory. */ - int *dirents; - - /* Links on hash list. */ - struct node *hnext, **hprevp; - - struct rwlock allocptrlock; - - struct dirty_indir *dirty; - - struct user_pager_info *fileinfo; -}; - -/* Identifies a particular block and where it's found - when interpreting indirect block structure. */ -struct iblock_spec -{ - /* Disk address of block */ - daddr_t bno; - - /* Offset in next block up; -1 if it's in the inode itself. */ - int offset; -}; - -/* Identifies an indirect block owned by this file which - might be dirty. */ -struct dirty_indir -{ - daddr_t bno; /* Disk address of block. */ - struct dirty_indir *next; -}; - -struct user_pager_info -{ - struct node *np; - enum pager_type - { - DISK, - FILE_DATA, - } type; - struct pager *p; - vm_prot_t max_prot; - - vm_offset_t allow_unlocked_pagein; - vm_size_t unlocked_pagein_length; -}; - -#include <hurd/diskfs-pager.h> - -/* The physical media. */ -extern struct store *store; -/* What the user specified. */ -extern struct store_parsed *store_parsed; - -/* Mapped image of the disk. */ -extern void *disk_image; - -extern void *zeroblock; - -extern struct fs *sblock; -extern struct csum *csum; -int sblock_dirty; -int csum_dirty; - -spin_lock_t node2pagelock; - -spin_lock_t alloclock; - -spin_lock_t gennumberlock; -u_long nextgennumber; - -spin_lock_t unlocked_pagein_lock; - -/* The compat_mode specifies whether or not we write - extensions onto the disk. */ -enum compat_mode -{ - COMPAT_GNU = 0, - COMPAT_BSD42 = 1, - COMPAT_BSD44 = 2, -} compat_mode; - -/* If this is set, then this filesystem has two extensions: - 1) directory entries include the type field. - 2) symlink targets might be written directly in the di_db field - of the dinode. */ -int direct_symlink_extension; - -/* If this is set, then the disk is byteswapped from native order. */ -int swab_disk; - -/* Number of device blocks per DEV_BSIZE block. */ -unsigned log2_dev_blocks_per_dev_bsize; - -/* Handy macros */ -#define DEV_BSIZE 512 -#define NBBY 8 -#define btodb(n) ((n) / DEV_BSIZE) -#define howmany(x,y) (((x)+((y)-1))/(y)) -#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) -#define isclr(a, i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) -#define isset(a, i) ((a)[(i)/NBBY] & (1<<((i)%NBBY))) -#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY)) -#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<(i)%NBBY)) -#define fsaddr(fs,n) (fsbtodb(fs,n)*DEV_BSIZE) - - -/* Functions for looking inside disk_image */ - -/* Convert an inode number to the dinode on disk. */ -extern inline struct dinode * -dino (ino_t inum) -{ - return (struct dinode *) - (disk_image - + fsaddr (sblock, ino_to_fsba (sblock, inum)) - + ino_to_fsbo (sblock, inum) * sizeof (struct dinode)); -} - -/* Convert a indirect block number to a daddr_t table. */ -extern inline daddr_t * -indir_block (daddr_t bno) -{ - return (daddr_t *) (disk_image + fsaddr (sblock, bno)); -} - -/* Convert a cg number to the cylinder group. */ -extern inline struct cg * -cg_locate (int ncg) -{ - return (struct cg *) (disk_image + fsaddr (sblock, cgtod (sblock, ncg))); -} - -/* Sync part of the disk */ -extern inline void -sync_disk_blocks (daddr_t blkno, size_t nbytes, int wait) -{ - pager_sync_some (diskfs_disk_pager, fsaddr (sblock, blkno), nbytes, wait); -} - -/* Sync an disk inode */ -extern inline void -sync_dinode (int inum, int wait) -{ - sync_disk_blocks (ino_to_fsba (sblock, inum), sblock->fs_fsize, wait); -} - - -/* Functions for byte swapping */ -extern inline short -swab_short (short arg) -{ - return (((arg & 0xff) << 8) - | ((arg & 0xff00) >> 8)); -} - -extern inline long -swab_long (long arg) -{ - return (((long) swab_short (arg & 0xffff) << 16) - | swab_short ((arg & 0xffff0000) >> 16)); -} - -extern inline long long -swab_long_long (long long arg) -{ - return (((long long) swab_long (arg & 0xffffffff) << 32) - | swab_long ((arg & 0xffffffff00000000LL) >> 32)); -} - -/* Return ENTRY, after byteswapping it if necessary */ -#define read_disk_entry(entry) \ -({ \ - typeof (entry) ret; \ - if (!swab_disk || sizeof (entry) == 1) \ - ret = (entry); \ - else if (sizeof (entry) == 2) \ - ret = swab_short (entry); \ - else if (sizeof (entry) == 4) \ - ret = swab_long (entry); \ - else \ - abort (); \ - ret; \ -}) - -/* Execute A = B, but byteswap it along the way if necessary */ -#define write_disk_entry(a,b) \ -({ \ - if (!swab_disk || sizeof (a) == 1) \ - ((a) = (b)); \ - else if (sizeof (a) == 2) \ - ((a) = (swab_short (b))); \ - else if (sizeof (a) == 4) \ - ((a) = (swab_long (b))); \ - else \ - abort (); \ -}) - - - - - -/* From alloc.c: */ -error_t ffs_alloc (struct node *, daddr_t, daddr_t, int, daddr_t *, - struct protid *); -void ffs_blkfree(struct node *, daddr_t bno, long size); -daddr_t ffs_blkpref (struct node *, daddr_t, int, daddr_t *); -error_t ffs_realloccg(struct node *, daddr_t, daddr_t, - int, int, daddr_t *, struct protid *); - -/* From bmap.c */ -error_t fetch_indir_spec (struct node *, daddr_t, struct iblock_spec *); -void mark_indir_dirty (struct node *, daddr_t); - -/* From hyper.c: */ -void get_hypermetadata (void); -void copy_sblock (void); - -/* From inode.c: */ -struct node *ifind (ino_t ino); -void inode_init (void); -void write_all_disknodes (void); - -/* From pager.c: */ -void create_disk_pager (void); -void din_map (struct node *); -void sin_map (struct node *); -void sin_remap (struct node *, int); -void sin_unmap (struct node *); -void din_unmap (struct node *); -void drop_pager_softrefs (struct node *); -void allow_pager_softrefs (struct node *); -void flush_node_pager (struct node *); - -/* From subr.c: */ -void ffs_fragacct (struct fs *, int, long [], int); -int ffs_isblock(struct fs *, u_char *, daddr_t); -void ffs_clrblock(struct fs *, u_char *, daddr_t); -void ffs_setblock (struct fs *, u_char *, daddr_t); -int skpc (int, int, char *); -int scanc (u_int, u_char *, u_char [], int); - -/* From pokeloc.c: */ -void record_poke (void *, vm_size_t); -void sync_disk (int); -void flush_pokes (); diff --git a/unionfs/AUTHORS b/unionfs/AUTHORS deleted file mode 100644 index 1cc95387..00000000 --- a/unionfs/AUTHORS +++ /dev/null @@ -1,2 +0,0 @@ -* Moritz Schulte <moritz@duesseldorf.ccc.de> -* Gianluca Guida <glguida@gmail.com> diff --git a/unionfs/BUGS b/unionfs/BUGS deleted file mode 100644 index 56209654..00000000 --- a/unionfs/BUGS +++ /dev/null @@ -1,5 +0,0 @@ -Known bugs: - - * unionfs hangs when looking up recursive links, which point into the - unionfs - * emacs hangs when trying to save files in unionfs diff --git a/unionfs/CAVEAT b/unionfs/CAVEAT deleted file mode 100644 index dbb88136..00000000 --- a/unionfs/CAVEAT +++ /dev/null @@ -1,25 +0,0 @@ -While using unionfs, you could experience more permission errors or -difficult or impossible file or directory deletion. This is a list of -things that can happen. - -WARNINGS: - -- If the translator is run as by an unpriviledged user, other users will fail -to create files or directory, since the translator won't be able to change -the ownership of the file. - - -PROBLEMS: - -- If there's a name conflict in underlying filesystems between directories -and files -- say that "foo" is a directory in underlying filesystem "a" while -is a file in the underlying filesystem "b" -- then unionfs will be unable to -delete this entry. This is a structural BUG (there's no clean way to solve it), -and should be fixed. - -- If there's a name conflict in underlying filesystems between directories -(or between files), and the user has not permission to delete _ALL_ the -entries -- e.g. one hidden entry is read-only -- then he will get an EPERM -even if permissions seems ok. This is a structural BUG (there's no clean way -to solve it), and should be fixed. - diff --git a/unionfs/COPYING b/unionfs/COPYING deleted file mode 100644 index 5cc9607b..00000000 --- a/unionfs/COPYING +++ /dev/null @@ -1,2 +0,0 @@ -This program is licensed under the terms of the GNU General Public -License. diff --git a/unionfs/ChangeLog b/unionfs/ChangeLog deleted file mode 100644 index d8a29618..00000000 --- a/unionfs/ChangeLog +++ /dev/null @@ -1,229 +0,0 @@ -2006-06-21 Alfred M. Szmidt <ams@gnu.org> - - * lib.c (for_each_subdir): Revert previous change. Reported by - Aanjhan Ranganathan <aanjhan@tuxmaniac.com>. - -2006-04-13 Ben Asselstine <benasselstine@gmail.com> - - * options.c (argp_parse_common_options) - (argp_parse_startup_options, parsing_startup_options_finished) - (argp_common_options, argp_startup_options) - (argp_parser_common_options, argp_parser_startup_options) - (argp_children_runtime): Make these static. - * ulfs.c (ulfs_create, ulfs_destroy, ulfs_install) - (ulfs_uninstall, ulfs_get_path): Likewise. - - * ulfs.h (ulfs_get_path): Remove declaration. - - * lib.c (for_each_subdir): Remove unused variables. - -2005-06-27 Ben Asselstine <benasselstine@gmail.com> - - * ulfs.c (ulfs_install): Rewrote to allow insertions of - filesystems based on priority. - (ulfs_register): Added new argument 'priority'. Set the priority - value in ulfs structure. - * ulfs.h (ulfs): Added 'priority' field to struct. - Updated ulfs_register declaration. - * netfs.c (netfs_append_args): Appending new priority option. - * stow.c (stow_privdata): Added 'priority' field to struct. - (stow_diradd): Added new 'priority' argument. Fill priority field - of 'mypriv'. - (_stow_scanstowentry): Changed caller to ulfs_register. - (_stow_registermatchingdirs): Likewise. - * options.c (arg_common_options): Added entries for OPT_PRIORITY - and OPT_ADD. - (arg_parse_common_options): Handle OPT_PRIORITY and OPT_ADD - case. Renamed 'ulfs_removed' to 'ulfs_mode'. New variable - 'ulfs_priority'. Changed caller to 'stow_diradd'. Changed caller - to 'ulfs_register'. - * options.h (OPT_ADD, OPT_PRIORITY, OPT_LONG_ADD) - (OPT_LONG_PRIORITY, ULFS_MODE_ADD, ULFS_MODE_REMOVE): New - declarations. - -2005-06-13 Gianluca Guida <glguida@gmail.com> - - * main.c (main): Set properly netfs_root_node permissions when - underlying node is not a file - Reported by Alfred M. Szmidt. - -2005-05-31 Gianluca Guida <glguida@gmail.com> - - * node.c (node_unlink_file): Use lookup to figure out whether a file - exists or not, or it will fail on read-only filesystems. - Reported by Ben Asselstine. - -2005-05-30 Gianluca Guida <glguida@gmail.com> - - * AUTHORS: Added myself in the list. - * README: Added sections "Introduction" and "Stowing Feature". - * options.c (argp_program_bug_address): Changed address. - - * lib.c (for_each_subdir): When call to stat() fails free "name" - and continue the loop, instead of returning error. Return 0 at the - end of the loop. - (for_each_subdir_priv): Likewise. - - * stow.c (_stow_registermatchingdirs): Don't return error when - patternlist_match returns false. Free filepath before returning - error when ulfs_register fails. - - * ulfs.c (ulfs_register): Removed bogus fprintf. - -2005-05-29 Gianluca Guida <glguida@gmail.com> - - * Makefile: Added support for building mig stubs for stow feature. - (OBJS): Added update.o - (unionfs): Added fs_notifyServer.o to final linking. - (unionfs.static): Likewise. - (fs_notifyServer.o): New rule. - (clean): Remove fs_notifyServer.c and fs_notify_S.h when cleaning. - - * netfs.c (OFFSET_T): New macro. - (_get_node_size): New function. - (netfs_validate_stat): Call _get_node_size for root node. - - * node.c (node_unlink_file): New variable "removed". Return ENOENT - if no files unlinked. - - * ulfs.c: Include "unionfs", fcntl.h and "lib.h". - (ulfs_install, ulfs_uninstall): Rewritten. - (ulfs_for_each_under_priv, ulfs_check): New function. - (ulfs_register): Check that argument is a directory. - * ulfs.h: Removed field "prevp" from struct ulfs. - (ulfs_check): New declaration. - (ulfs_iterate, ulfs_iterate_unlocked): Don't use ulfs_chain_end. - * lib.c (check_dir): New function. - * lib.h: Added declaration of check_dir. - - * stow.c: Include "update.h", cthreads.h, hurd/port.h, - "stow-priv.h" and "ncache.h". - (stow_privdata) Added "lock" to struct. Removed "remove" to - struct. - (_stow_registermatchingdirs): Removed call to - debug_msg_send. Removed call to ulfs_unregister when - privdata->remove is set. Return error on ulfs_register failure - instead of exiting the program. - (_stow_scanstowentry): Removed call to ulfs_unregister when - privdata->remove is set. Lock privdata->lock and unlock at end. - (stow_port_bucket, stow_port_class): New variables. - (_stow_notify_init, begin_using_notify_ports) - (end_using_notify_ports, stow_S_file_changed, stow_S_dir_changed) - (_stow_notify_thread, stow_init): New functions. - (stow_diradd): Allocate "mypriv" instead of using stack. Call - _stow_notify_init. - * stow.h: Include "pattern.h". Declare - stow_init. - - * stow-priv.h: New file. - * stow-mutations.h: Likewise. - * update.c: Likewise. - * update.h: Likewise. - - * options.c: Include "update.h". - (argp_parse_common_options): Check stow_diradd return. Call - root_update_schedule instead of node_init_root and ncache_reset - when parsing_startup_options_finished is set. - - * main.c: Include "stow.h". Include "update.h". - (main): Call stow_init. Call root_update_init. - -2005-05-25 Gianluca Guida <glguida@gmail.com> - - * CAVEAT: New file. - * README: Rewritten. - - * netfs.c (netfs_attempt_unlink): Use fshelp_checkdirmod - instead of fshelp_access. - (netfs_attempt_mkdir): Implemented. - (netfs_attempt_rmdir): Likewise. - (netfs_attempt_create_file_reduced): Likewise. - Fixed typo in a comment. - * node.c (node_dir_remove): New function. - (node_dir_create): Likewise. - * node.h (node_dir_create): New declaration. - (node_dir_remove): Likewise. - - * lib.c (for_each_file_priv): Removed unused variables - "name" and "filestat". - -2005-05-24 Gianluca Guida <glguida@gmail.com> - - * netfs.c (netfs_attempt_unlink): Implemented. - (netfs_attempt_create_file_reduced): New function. - (netfs_S_dir_lookup): Initialized variable "error". - Added support for file creation. - (netfs_attempt_lookup_improved): Changed instruction flow, - return on error not continue on non-error. - Check user permission to open file before returning port. - * node.c (node_create, node_update, node_lookup_file, node_ulfs_free) - (node_ulfs_init, node_entries_get, node_create_root, node_init_root): - Changed instruction flow, return on error not continue on non-error. - (node_unlink_file): New function. - * node.h (node_unlink_file): New declaration. - (node_ulfs_iterate_reverse_unlocked): New macro. - - * options.c (argp_parse_common_options): Removed debugging fprintf. - -2005-01-31 Gianluca Guida <glguida@gmail.com> - - * stow.c (stow_diradd): Handle --stow argument with missing / - correctly. - -2005-01-31 Gianluca Guida <glguida@gmail.com> - - * pattern.c: New file. - * stow.c: Likewise. - * pattern.h: Likewise. - * stow.h: Likewise. - * Makefile (OBJS): Added pattern.o and stow.o - - * node.c: Initialize variable err. - * lib.c (file_lookup): Initialize variable err. - Include <fcntl.h>. - (make_filepath, for_each_subdir, for_each_subdir_priv) - (for_each_file_priv): New function. - * lib.h (make_filepath, for_each_subdir, for_each_subdir_priv): New - declaration. - * options.c: Include "pattern.h". - Include "stow.h". - (arg_common_options): Added entries for OPT_STOW and OPT_PATTERN. - (argp_parse_common_options): Handle OPT_STOW and OPT_PATTERN case. - * options.h (OPT_PATTERN, OPT_STOW, OPT_LONG_PATTERN, OPT_LONG_STOW): - New declarations. - -2003-07-05 Jeroen Dekkers <jeroen@dekkers.cx> - - * Makefile: Rewrite. - - * netfs.c (netfs_attempt_create_file): Unlock DIR. - (netfs_attempt_mkfile): Likewise. - -2002-12-09 Moritz Schulte <moritz@duesseldorf.ccc.de> - - * lib.h: Fix pointer arg. - * lib.c (dir_entries_get): Likewise. - * lib.c (dir_entries_get): Fix typo. - (dir_entries_get): Change type of data_size to size_t. - * node.c (node_entries_get): Change type of dirent_data_size to - size_t. - -2002-12-08 Moritz Schulte <moritz@duesseldorf.ccc.de> - - * BUGS: Remove the memory-leak bug. - * lib.c: Include <sys/mman.h>. - * node.c: Include <sys/mman.h>. - (node_entries_get): munmap dirent_data as returned by - dir_entries_get. - (node_entries_get): New variable: int dirent_data_size. - * lib.c (dir_entries_get): New argument: int *dirent_data_size. - (dir_entries_get): Do not forget to munmap DATA if something goes - wrong. - * lib.h: Update dir_entries_get declaration. - - * node.c (node_create_root): call lnode_destroy, if node_create - failed, not if lnode_create failed. Reported by Richard Smith. - - Copyright 2002, 2003, 2005 Free Software Foundation, Inc. - Copying and distribution of this file, with or without modification, are - permitted provided the copyright notice and this notice are preserved. diff --git a/unionfs/Makefile b/unionfs/Makefile deleted file mode 100644 index b1800722..00000000 --- a/unionfs/Makefile +++ /dev/null @@ -1,81 +0,0 @@ -# Hurd unionfs -# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. -# Written by Jeroen Dekkers <jeroen@dekkers.cx>. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or * -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA. - -CPP = gcc -E -x c -MIGCOM = mig -cc cat - /dev/null - -CFLAGS += -Wall -g -O2 -D_FILE_OFFSET_BITS=64 -std=gnu99 \ - -DDEBUG -LDFLAGS += -lnetfs -lfshelp -liohelp -lthreads \ - -lports -lihash -lshouldbeinlibc -OBJS = main.o node.o lnode.o ulfs.o ncache.o netfs.o \ - lib.o options.o pattern.o stow.o update.o - -MIGCOMSFLAGS = -prefix stow_ -fs_notify-MIGSFLAGS = -imacros ./stow-mutations.h - - -# How to build RPC stubs - -# We always need this setting, because libc does not include the bogus names. -MIGCOMFLAGS := -subrprefix __ - -# User settable variables: -# mig-sheader-prefix prepend to foo_S.h for name of foo.defs stub header -# MIGSFLAGS flags to CPP when building server stubs and headers -# foo-MIGSFLAGS same, but only for interface `foo' -# MIGCOMSFLAGS flags to MiG when building server stubs and headers -# foo-MIGCOMSFLAGS same, but only for interface `foo' -# MIGUFLAGS flags to CPP when building user stubs and headers -# foo-MIGUFLAGS same, but only for interface `foo' -# MIGCOMUFLAGS flags to MiG when building user stubs and headers -# foo-MIGCOMUFLAGS same, but only for interface `foo' -# CPPFLAGS flags to CPP - -# Implicit rules for building server and user stubs from mig .defs files. - -# These chained rules could be (and used to be) single rules using pipes. -# But it's convenient to be able to explicitly make the intermediate -# files when you want to deal with a problem in the MiG stub generator. -$(mig-sheader-prefix)%_S.h %Server.c: %.sdefsi - $(MIGCOM) $(MIGCOMFLAGS) $(MIGCOMSFLAGS) $($*-MIGCOMSFLAGS) \ - -sheader $(mig-sheader-prefix)$*_S.h -server $*Server.c \ - -user /dev/null -header /dev/null < $< - -%.sdefsi: %.defs - $(CPP) $(CPPFLAGS) $(MIGSFLAGS) $($*-MIGSFLAGS) -DSERVERPREFIX=S_ $< -o $@ - -vpath %.defs $(prefix)/include/hurd - - - -all: unionfs - -unionfs: $(OBJS) fs_notifyServer.o - $(CC) -o $@ $(OBJS) fs_notifyServer.o $(LDFLAGS) - -unionfs.static: $(OBJS) fs_notifyServer.o - $(CC) -static -o $@ $(OBJS) fs_notifyServer.o $(LDFLAGS) - -fs_notifyServer.o: fs_notifyServer.c - -.PHONY: clean - -clean: - rm -rf *.o fs_notifyServer.c fs_notify_S.h unionfs diff --git a/unionfs/README b/unionfs/README deleted file mode 100644 index 1849f4d9..00000000 --- a/unionfs/README +++ /dev/null @@ -1,92 +0,0 @@ -This is the unionfs translator for the GNU Hurd. - -The unionfs translator was originally written by Moritz Schulte -<moritz@duesseldorf.ccc.de> and currently mantained by Gianluca Guida -<glguida@gmail.com>. - - - -Introduction. - -An unionfs is a filesystems that joins many filesystems into one, meaning -that you can see into an "unionfs" all files contained in the filesystems -that are part of the union. - -When two or more directories with the same path are found in different -filesystems, their content is joined. -When two or more files with the same path are found in different filesystems, -unionfs has to solve this conflict. See below (Internals section) for -information on what this implementation does in such case. - -Example: -To join "foo/" "bar/" and "baz/" in the directory "quux/", just do: - - settrans -capfg quux/ /hurd/unionfs foo/ bar/ baz/ - -If you want to join even quux/ contents in the union itself, add -u as a -translator argument. -You can add filesystems at run-time with the fsysopts command. - - - -Stowing feature. - -This unionfs implements stowing feature, i.e. the translator will watch a -directory, called 'stow', that contains the directories to unite. -When a directory is added or removed in the stow, it will be added to or -removed from the unionfs. - -Example: -To use "/stow" as the stow for the directory "foo/", do: - - settrans -capfg foo/ /hurd/unionfs --stow=/stow - -All directories contained in /stow/ will then be joined together in foo/; -you can delete or add directory at run-time and you will see unionfs adding -or removing files in foo/ automatically. - -Another interesting feature of stow support of unionfs is the pattern matching -option. -For example, by using: - - settrans -capfg foo/ /hurd/unionfs -m bar --stow=/stow - -You will get joined in foo/ all sub-sub-directories of /stow matching "bar", -i.e. /stow/*/bar/; pattern matching will be done too in run-time added stow -subdirectories. -Furthermore, you can specify more complex matching pattern to the option, -like -m bar\* (to get all stow's sub-sub-directories beginning with "bar") -or specify multiple -m options. - -Example: -This command - - settrans -capfg /myfaketree/bin -m bin -m sbin --stow=/stow - -will join in /myfaketree/bin all files that are in /stow/*/bin and -/stow/*/sbin. It is equivalent to: - - settrans -capfg /myfaketree/bin -m [s]bin --stow=/stow - - - -Internals. - -This `unionfs' translator is simple, but it is definitely not a joke. - -It works by keeping in memory a dynamically updated tree of nodes, each -node representing a directory in the unionfs. A node contains an array -of ports that give access to the corrisponding directory in the underlying -filesystems. - -On lookup, the first entry found is chosen. Thus, it is very important the -underlying filesystems ordering, since the first underlying filesystem will -be the first one to be searched during lookups, and it is the filesystem -where new files and directories are written into. - -At the moment, underlying filesystem ordering is set by option ordering. - -See CAVEAT for other unexpected behaviour that could happen. - - -Please send all bug reports to Gianluca Guida <glguida@gmail.com>. diff --git a/unionfs/TODO b/unionfs/TODO deleted file mode 100644 index 790221f2..00000000 --- a/unionfs/TODO +++ /dev/null @@ -1,7 +0,0 @@ -Todo list for unionfs: - - * implement filesystem notification support; - only update nodes when needed - * cache dirents (?) - * verify that the locking is correct - * increase performance diff --git a/unionfs/lib.c b/unionfs/lib.c deleted file mode 100644 index 0423c1bc..00000000 --- a/unionfs/lib.c +++ /dev/null @@ -1,280 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -#define _GNU_SOURCE - -#include <hurd/netfs.h> -#include <error.h> -#include <dirent.h> -#include <errno.h> -#include <sys/mman.h> -#include <stddef.h> - -#include "lib.h" - -/* Lock, which must be held, during printing of debugging - messages. */ -struct mutex debug_msg_lock = MUTEX_INITIALIZER; - -/* Returns no error if PATH points to a directory. */ -error_t check_dir (char *path) -{ - struct stat filestat; - error_t err = 0; - - err = stat (path, &filestat); - if (err) - return err; - - if (!S_ISDIR (filestat.st_mode)) - return ENOTDIR; - - return 0; -} - -/* Fetch directory entries for DIR; store the raw data as returned by - the dir_readdir RPC in *DIRENT_DATA, the size of *DIRENT_DATA in - *DIRENT_DATA_SIZE and a list of pointers to the dirent structures - in *DIRENT_LIST. */ -error_t -dir_entries_get (file_t dir, char **dirent_data, - size_t *dirent_data_size, struct dirent ***dirent_list) -{ - error_t err; - size_t data_size; - int entries_num; - char *data; - - err = dir_readdir (dir, &data, &data_size, 0, -1, 0, &entries_num); - if (! err) - { - struct dirent **list; - - list = malloc (sizeof (struct dirent *) * (entries_num + 1)); - if (list) - { - struct dirent *dp; - int i; - - for (i = 0, dp = (struct dirent *) data; - i < entries_num; - i++, dp = (struct dirent *) ((char *) dp + dp->d_reclen)) - *(list + i) = dp; - *(list + i) = NULL; - - *dirent_data = data; - *dirent_data_size = data_size; - *dirent_list = list; - } - else - { - munmap (data, data_size); - err = ENOMEM; - } - } - return err; -} - -/* Lookup the file named NAME beneath DIR (or the cwd, if DIR is not a - valid port. Try to open with FLAGS0 first, and if that fails with - FLAGS1; MODE is the mode to user for newly created files. On - success, stat the looked up port and store it in *PORT, the - according stat information are stored in *STAT. */ -error_t -file_lookup (file_t dir, char *name, int flags0, int flags1, - int mode, file_t *port, struct stat *stat) -{ - error_t err = 0; - file_t p; - struct stat s; - - file_t do_file_lookup (file_t d, char *n, int f, int m) - { - if (port_valid (d)) - p = file_name_lookup_under (d, n, f, m); - else if (errno == EACCES) - p = file_name_lookup (n, f, m); - return p; - } - - p = do_file_lookup (dir, name, flags0, mode); - if (! port_valid (p)) - p = do_file_lookup (dir, name, flags1, mode); - - if (port_valid (p)) - { - if (stat) - { - err = io_stat (p, &s); - if (err) - port_dealloc (p); - } - } - else - err = errno; - - if (! err) - { - *port = p; - if (stat) - *stat = s; - } - return err; -} - -#include <fcntl.h> - -char * -make_filepath (char *path, char *filename) -{ - int length; - char *filepath; - - length = strlen (path) + strlen (filename) + 2; - filepath = malloc (length); - if (filepath == NULL) - return NULL; - - strncpy (filepath, path, length); - strncat (filepath, filename, strlen (filename)); - - return filepath; -} - -error_t -for_each_subdir (char *path, error_t (*func) (char *, char *)) -{ - struct dirent **dirent, **dirent_list; - char *dirent_data; - size_t dirent_data_size; - file_t dir; - error_t err; - - dir = file_name_lookup (path, O_READ, 0); - - err = dir_entries_get (dir, &dirent_data, &dirent_data_size, &dirent_list); - if (err) - return err; - - for (dirent = dirent_list; (! err) && (*dirent); dirent++) - { - char *name; - struct stat filestat; - - if ((!strcmp ((*dirent)->d_name, ".")) - || (!strcmp ((*dirent)->d_name, ".."))) - continue; - - name = make_filepath (path, (*dirent)->d_name); - - err = stat (name, &filestat); - - free (name); - - if (err) - { - fprintf (stderr, "unionfs: couldn't stat %s%s\n", - path, (*dirent)->d_name); - continue; - } - - if (!S_ISDIR(filestat.st_mode)) - continue; - - func ((*dirent)->d_name, path); - } - - return 0; -} - -error_t -for_each_subdir_priv (char *path, error_t (*func) (char *, char *, void *), - void *priv) -{ - struct dirent **dirent, **dirent_list; - char *dirent_data; - size_t dirent_data_size; - file_t dir; - error_t err; - - dir = file_name_lookup (path, O_READ, 0); - - err = dir_entries_get (dir, &dirent_data, &dirent_data_size, &dirent_list); - if (err) - return err; - - for (dirent = dirent_list; (!err) && (*dirent); dirent++) - { - char *name; - struct stat filestat; - - if ((!strcmp ((*dirent)->d_name, ".")) - || (!strcmp ((*dirent)->d_name, ".."))) - continue; - - name = make_filepath (path, (*dirent)->d_name); - - err = stat (name, &filestat); - - free (name); - - if (err) - { - fprintf (stderr, "unionfs: couldn't stat %s%s\n", - path, (*dirent)->d_name); - continue; - } - - if (!S_ISDIR(filestat.st_mode)) - continue; - - func ((*dirent)->d_name, path, priv); - } - - return 0; -} - -error_t -for_each_file_priv (char *path, error_t (*func) (char *, char *, void *), - void *priv) -{ - struct dirent **dirent, **dirent_list; - char *dirent_data; - size_t dirent_data_size; - file_t dir; - error_t err; - - dir = file_name_lookup (path, O_READ, 0); - - err = dir_entries_get (dir, &dirent_data, &dirent_data_size, &dirent_list); - if (err) - return err; - - for (dirent = dirent_list; (!err) && (*dirent); dirent++) - { - - if ((!strcmp ((*dirent)->d_name, ".")) - || (!strcmp ((*dirent)->d_name, ".."))) - continue; - - func ((*dirent)->d_name, path, priv); - } - - return err; -} diff --git a/unionfs/lib.h b/unionfs/lib.h deleted file mode 100644 index be9a2192..00000000 --- a/unionfs/lib.h +++ /dev/null @@ -1,82 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -#ifndef INCLUDED_LIB_H -#define INCLUDED_LIB_H - -#include <hurd.h> -#include <dirent.h> -#include <stddef.h> - -/* Returned directory entries are aligned to blocks this many bytes - long. Must be a power of two. */ -#define DIRENT_ALIGN 4 -#define DIRENT_NAME_OFFS offsetof (struct dirent, d_name) - -/* Length is structure before the name + the name + '\0', all padded - to a four-byte alignment. */ -#define DIRENT_LEN(name_len) \ - ((DIRENT_NAME_OFFS + (name_len) + 1 + (DIRENT_ALIGN - 1)) \ - & ~(DIRENT_ALIGN - 1)) - -/* These macros remove some Mach specific code from the server - itself. */ -#define port_null MACH_PORT_NULL -#define port_dealloc(p) mach_port_deallocate (mach_task_self (), (p)) -#define port_valid(p) ((p) != port_null) - -/* Fetch directory entries for DIR; store the raw data as returned by - the dir_readdir RPC in *DIRENT_DATA, the size of *DIRENT_DATA in - *DIRENT_DATA_SIZE and a list of pointers to the dirent structures - in *DIRENT_LIST. */ -error_t dir_entries_get (file_t dir, char **dirent_data, - size_t *dirent_data_size, - struct dirent ***dirent_list); - -char *make_filepath (char *, char *); -error_t for_each_subdir (char *, error_t (*) (char *, char *)); -error_t for_each_subdir_priv (char *, error_t (*) (char *, char *, void *), - void *); - -/* Lookup the file named NAME beneath DIR (or the cwd, if DIR is not a - valid port. Try to open with FLAGS0 first, and if that fails with - FLAGS1; MODE is the mode to user for newly created files. On - success, stat the looked up port and store it in *PORT, the - according stat information are stored in *STAT. */ -error_t file_lookup (file_t dir, char *name, int flags0, int flags1, int mode, - file_t *port, struct stat *stat); - -/* Returns no error if directory. */ -error_t check_dir (char *path); - -extern struct mutex debug_msg_lock; - -/* Support for debugging messages. */ -#define debug_msg_send(fmt, args...) \ - do \ - { \ - mutex_lock (&debug_msg_lock); \ - fprintf (stderr, "%s:%i: ", __FILE__, __LINE__); \ - fprintf (stderr, fmt , ## args); \ - putc ('\n', stderr); \ - mutex_unlock (&debug_msg_lock); \ - } \ - while (0) - -#endif diff --git a/unionfs/lnode.c b/unionfs/lnode.c deleted file mode 100644 index 9b242bba..00000000 --- a/unionfs/lnode.c +++ /dev/null @@ -1,184 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -/* `light node' management. See unionfs.h for an explanation of light - nodes. */ - -#define _GNU_SOURCE - -#include <hurd/netfs.h> -#include <error.h> -#include <stdlib.h> -#include <string.h> - -#include "lnode.h" -#include "lib.h" -#include "unionfs.h" - -/* Create a new light node as an entry with the name NAME and store it - in *NODE. The new node is not locked and contains a single - reference. */ -error_t -lnode_create (char *name, lnode_t **node) -{ - lnode_t *node_new = malloc (sizeof (lnode_t)); - error_t err = 0; - - debug_msg ("lnode_create for name: %s", name); - - if (! node_new) - err = ENOMEM; - else - { - char *name_cp = NULL; - - if (name) - name_cp = strdup (name); - if (name && (! name_cp)) - { - err = ENOMEM; - free (node_new); - } - else - { - node_new->name = name_cp; - node_new->name_len = name_cp ? strlen (name_cp) : 0; - node_new->flags = 0; - node_new->node = NULL; - node_new->next = NULL; - node_new->prevp = NULL; - node_new->dir = NULL; - node_new->entries = NULL; - node_new->references = 1; - mutex_init (&node_new->lock); - mutex_lock (&node_new->lock); - *node = node_new; - } - } - return err; -} - -/* Destroy a light node. */ -void -lnode_destroy (lnode_t *node) -{ - debug_msg ("lnode_destroy for name: %s", node->name); - free (node->name); - free (node); -} - -/* Install the node in the node tree; add a reference to DIR, which - must be locked. */ -void -lnode_install (lnode_t *dir, lnode_t *node) -{ - lnode_ref_add (dir); - node->next = dir->entries; - node->prevp = &dir->entries; - if (dir->entries) - dir->entries->prevp = &node->next; - dir->entries = node; - node->dir = dir; -} - -/* Uninstall the node from the node tree; remove a reference from the - lnode containing NODE. */ -void -lnode_uninstall (lnode_t *node) -{ - lnode_ref_remove (node->dir); - *node->prevp = node->next; - if (node->next) - node->next->prevp = &node->next; -} - -/* Add a reference to NODE, which must be locked. */ -void -lnode_ref_add (lnode_t *node) -{ - node->references++; -} - -/* Remove a reference to NODE, which must be locked. If that was the - last reference, destroy the node, otherwise simply unlock NODE. */ -void -lnode_ref_remove (lnode_t *node) -{ - assert (node->references); - if (! --node->references) - { - lnode_uninstall (node); - lnode_destroy (node); - } - else - mutex_unlock (&node->lock); -} - -/* Get a light node by it's name. The looked up node is locked and - got one reference added. */ -error_t -lnode_get (lnode_t *dir, char *name, - lnode_t **node) -{ - error_t err = 0; - lnode_t *n; - - for (n = dir->entries; n && strcmp (n->name, name); n = n->next); - if (n) - { - mutex_lock (&n->lock); - lnode_ref_add (n); - *node = n; - } - else - err = ENOENT; - - return err; -} - -/* Construct the full path for a given light node. */ -error_t -lnode_path_construct (lnode_t *node, - char **path) -{ - error_t err = 0; - int p_len = 1; - lnode_t *n; - char *p; - - for (n = node; n && n->dir; n = n->dir) - p_len += n->name_len + (n->dir->dir ? 1 : 0); - - p = malloc (p_len); - if (! p) - err = ENOMEM; - else - { - *(p + --p_len) = 0; - for (n = node; n && n->dir; n = n->dir) - { - p_len -= n->name_len; - strncpy (p + p_len, n->name, n->name_len); - if (n->dir->dir) - *(p + --p_len) = '/'; - } - *path = p; - } - return err; -} diff --git a/unionfs/lnode.h b/unionfs/lnode.h deleted file mode 100644 index b43b7b26..00000000 --- a/unionfs/lnode.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -/* `light node' management. */ - -#ifndef INCLUDED_LNODE_H -#define INCLUDED_LNODE_H - -#include <hurd/netfs.h> -#include <error.h> - -struct lnode -{ - char *name; /* The name of this light node. */ - int name_len; /* This is used quite often and since - NAME does not change, just - calculate it once. */ - int flags; /* Associated flags. */ - int references; /* References to this light node. */ - struct node *node; /* Reference to the real node. */ - struct lnode *next, **prevp; /* Light nodes are connected in a - linked list. */ - struct lnode *dir; /* The light node this light node is - contained int. */ - struct lnode *entries; /* A reference to the list containing - the entries of this light node. */ - struct mutex lock; /* A lock. */ -}; -typedef struct lnode lnode_t; - -/* Create a new light node as an entry with the name NAME and store it - in *NODE. The new node is not locked and contains a single - reference. */ -error_t lnode_create (char *name, lnode_t **node); - -/* Destroy a light node. */ -void lnode_destroy (lnode_t *node); - -/* Install the node in the node tree; add a reference to DIR. */ -void lnode_install (lnode_t *dir, lnode_t *node); - -/* Uninstall the node from the node tree; remove a reference from the - lnode containing NODE. */ -void lnode_uninstall (lnode_t *node); - -/* Add a reference to NODE, which must be locked. */ -void lnode_ref_add (lnode_t *node); - -/* Remove a reference to NODE, which must be locked. If that was the - last reference, destroy the node, otherwise simply unlock NODE. */ -void lnode_ref_remove (lnode_t *node); - -/* Get a light node by it's name. The looked up node is locked and - got one reference added. */ -error_t lnode_get (lnode_t *dir, char *name, - lnode_t **node); - -/* Construct the full path for a given light node. */ -error_t lnode_path_construct (lnode_t *node, char **path); - -#endif diff --git a/unionfs/main.c b/unionfs/main.c deleted file mode 100644 index c33b0654..00000000 --- a/unionfs/main.c +++ /dev/null @@ -1,134 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -#define _GNU_SOURCE - -#include <hurd/netfs.h> -#include <argp.h> -#include <argz.h> -#include <error.h> -#include <fcntl.h> -#include <sys/types.h> -#include <unistd.h> - -#include "version.h" -#include "unionfs.h" -#include "ncache.h" -#include "ulfs.h" -#include "lnode.h" -#include "node.h" -#include "options.h" -#include "stow.h" -#include "update.h" - -char *netfs_server_name = "unionfs"; -char *netfs_server_version = HURD_VERSION; - -/* Not really needed, since unionfs doesn't manage symlinks. */ -int netfs_maxsymlinks = 0; - -/* Flags describing certain properties of the unionfs. */ -int unionfs_flags; - -/* The filesystem id (the pid). */ -pid_t fsid; - -/* A port to the underlying node. */ -mach_port_t underlying_node; - -/* stat information for the underlying node. */ -struct stat underlying_node_stat; - -/* Mapped time, used for updating node information. */ -volatile struct mapped_time_value *maptime; - -/* Used by netfs_set_options to handle runtime option parsing. */ -struct argp *netfs_runtime_argp = &argp_runtime; - -/* Main entry point. */ -int -main (int argc, char **argv) -{ - mach_port_t bootstrap_port; - error_t err = 0; - - root_update_init (); - - err = stow_init(); - if (err) - error (EXIT_FAILURE, err, "failed to initialize stow support"); - - /* Argument parsing. */ - argp_parse (&argp_startup, argc, argv, ARGP_IN_ORDER, 0, 0); - - err = node_create_root (&netfs_root_node); - if (err) - error (EXIT_FAILURE, err, "failed to create root node"); - - /* netfs initialization. */ - task_get_bootstrap_port (mach_task_self (), &bootstrap_port); - netfs_init (); - underlying_node = netfs_startup (bootstrap_port, O_READ); - - err = node_init_root (netfs_root_node); - if (err) - error (EXIT_FAILURE, err, "failed to initialize root node"); - - /* Map the time, used for updating node information. */ - err = maptime_map (0, 0, &maptime); - if (err) - error (EXIT_FAILURE, err, "maptime_map"); - - /* More initialiazation. */ - ncache_init (ncache_size); - - /* Here we adjust the root node permissions. */ - err = io_stat (underlying_node, &underlying_node_stat); - - if (err) - error (EXIT_FAILURE, err, "io_stat"); - - fsid = getpid (); - netfs_root_node->nn_stat = underlying_node_stat; - netfs_root_node->nn_stat.st_ino = UNIONFS_ROOT_INODE; /* FIXME. */ - netfs_root_node->nn_stat.st_fsid = fsid; - netfs_root_node->nn_stat.st_mode = S_IFDIR | (underlying_node_stat.st_mode - & ~S_IFMT & ~S_ITRANS); - netfs_root_node->nn_translated = netfs_root_node->nn_stat.st_mode; - - /* If the underlying node isn't a directory, enhance the stat - information. */ - if (! S_ISDIR (underlying_node_stat.st_mode)) - { - if (underlying_node_stat.st_mode & S_IRUSR) - netfs_root_node->nn_stat.st_mode |= S_IXUSR; - if (underlying_node_stat.st_mode & S_IRGRP) - netfs_root_node->nn_stat.st_mode |= S_IXGRP; - if (underlying_node_stat.st_mode & S_IROTH) - netfs_root_node->nn_stat.st_mode |= S_IXOTH; - } - - /* Update the timestamps of the root node. */ - fshelp_touch (&netfs_root_node->nn_stat, - TOUCH_ATIME | TOUCH_MTIME | TOUCH_CTIME, maptime); - - /* Start serving clients. */ - for (;;) - netfs_server_loop (); -} diff --git a/unionfs/ncache.c b/unionfs/ncache.c deleted file mode 100644 index 4c83ac0e..00000000 --- a/unionfs/ncache.c +++ /dev/null @@ -1,151 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -#define _GNU_SOURCE - -#include <hurd/netfs.h> -#include <error.h> -#include <stdlib.h> -#include <assert.h> - -#include "ncache.h" -#include "lib.h" -#include "unionfs.h" - -/* The node cache. */ -ncache_t ncache; - -/* Cache size, may be overwritten by the user. */ -int ncache_size = NCACHE_SIZE; - -/* Initialize the node cache, set the maximum number of allowed nodes - in the cache to SIZE_MAX. */ -void -ncache_init (int size_max) -{ - ncache.mru = NULL; - ncache.lru = NULL; - ncache.size_max = size_max; - ncache.size_current = 0; - mutex_init (&ncache.lock); -} - -/* Remove the given node NODE from the cache. */ -static void -ncache_node_remove (node_t *node) -{ - struct netnode *nn = node->nn; - - if (nn->ncache_next) - nn->ncache_next->nn->ncache_prev = nn->ncache_prev; - if (nn->ncache_prev) - nn->ncache_prev->nn->ncache_next = nn->ncache_next; - if (ncache.mru == node) - ncache.mru = nn->ncache_next; - if (ncache.lru == node) - ncache.lru = nn->ncache_prev; - nn->ncache_next = NULL; - nn->ncache_prev = NULL; - ncache.size_current--; -} - -void -ncache_reset (void) -{ - node_t *node; - - mutex_lock (&ncache.lock); - while ((node = ncache.mru)) - ncache_node_remove (node); - mutex_unlock (&ncache.lock); -} - -/* Lookup the node for the light node LNODE. If it does not exist - anymore in the cache, create a new node. Store the looked up node - in *NODE. */ -error_t -ncache_node_lookup (lnode_t *lnode, node_t **node) -{ - error_t err = 0; - node_t *n; - - if (lnode->node) - { - debug_msg ("ncache_node_lookup for lnode: %s (found in cache)", - lnode->name); - n = lnode->node; - netfs_nref (n); - } - else - { - debug_msg ("ncache_node_lookup for lnode: %s (newly created)", - lnode->name); - err = node_create (lnode, &n); - } - - if (! err) - { - mutex_lock (&n->lock); - *node = n; - } - return err; -} - -/* Add the given node NODE to the node cache; remove - least-recently-used nodes, if needed. */ -void -ncache_node_add (node_t *node) -{ - mutex_lock (&ncache.lock); - - debug_msg ("adding node to cache: %s", node->nn->lnode->name); - - if (ncache.size_max > 0 || ncache.size_current > 0) - { - if (ncache.mru != node) - { - if (node->nn->ncache_next || node->nn->ncache_prev) - /* Node is already in the cache. */ - ncache_node_remove (node); - else - /* Add a reference from the cache. */ - netfs_nref (node); - - node->nn->ncache_next = ncache.mru; - node->nn->ncache_prev = NULL; - if (ncache.mru) - ncache.mru->nn->ncache_prev = node; - if (! ncache.lru) - ncache.lru = node; - ncache.mru = node; - ncache.size_current++; - } - } - - /* Forget the least used nodes. */ - while (ncache.size_current > ncache.size_max) - { - struct node *lru = ncache.lru; - debug_msg ("removing cached node: %s", lru->nn->lnode->name); - ncache_node_remove (lru); - netfs_nrele (lru); - } - - mutex_unlock (&ncache.lock); -} diff --git a/unionfs/ncache.h b/unionfs/ncache.h deleted file mode 100644 index 8fa7d107..00000000 --- a/unionfs/ncache.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -#ifndef INCLUDED_NCACHE_H -#define INCLUDED_NCACHE_H - -#include <error.h> -#include <hurd/netfs.h> - -#include "node.h" - -typedef struct ncache -{ - node_t *mru; /* Reference to the mru end of the - cache chain. */ - node_t *lru; /* Reference to the lru end of the - cache chain. */ - int size_max; /* Maximal number of nodes to - cache. */ - int size_current; /* Current number of nodes in the - cache. */ - struct mutex lock; /* A lock. */ -} ncache_t; - -/* Cache size, may be overwritten by the user. */ -extern int ncache_size; - -/* Initialize the node cache, set the maximum number of allowed nodes - in the cache to SIZE_MAX. */ -void ncache_init (int size_max); - -/* Lookup the node for the light node LNODE. If it does not exist - anymore in the cache, create a new node. Store the looked up node - in *NODE. */ -error_t ncache_node_lookup (lnode_t *lnode, node_t **node); - -void ncache_reset (void); - -/* Add the given node NODE to the node cache; remove - least-recently-used nodes, if needed. */ -void ncache_node_add (node_t *node); - -#endif diff --git a/unionfs/netfs.c b/unionfs/netfs.c deleted file mode 100644 index 89d1bf67..00000000 --- a/unionfs/netfs.c +++ /dev/null @@ -1,1170 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -#define _GNU_SOURCE - -#include <hurd/netfs.h> -#include <error.h> -#include <argz.h> -#include <stddef.h> -#include <fcntl.h> -#include <assert.h> -#include <string.h> -#include <stdio.h> -#include <hurd/paths.h> -#include <sys/mman.h> - -#include "unionfs.h" -#include "ulfs.h" -#include "node.h" -#include "lib.h" -#include "ncache.h" -#include "options.h" - -/* Return an argz string describing the current options. Fill *ARGZ - with a pointer to newly malloced storage holding the list and *LEN - to the length of that storage. */ -error_t -netfs_append_args (char **argz, size_t *argz_len) -{ - error_t err = 0; - - ulfs_iterate - { - if (! err) - if (unionfs_flags & FLAG_UNIONFS_MODE_DEBUG) - err = argz_add (argz, argz_len, - OPT_LONG (OPT_LONG_DEBUG)); - if (! err) - if (ulfs->flags & FLAG_ULFS_WRITABLE) - err = argz_add (argz, argz_len, - OPT_LONG (OPT_LONG_WRITABLE)); - if (! err) - if (ulfs->priority) - { - char *buf = NULL; - if ((err = asprintf (&buf, "%s=%s", OPT_LONG (OPT_LONG_PRIORITY), - ulfs->priority)) != -1) - { - err = argz_add (argz, argz_len, buf); - free (buf); - } - } - - if (! err) - { - if (ulfs->path) - err = argz_add (argz, argz_len, ulfs->path); - else - err = argz_add (argz, argz_len, - OPT_LONG (OPT_LONG_UNDERLYING)); - } - } - - return err; -} - -#ifndef __USE_FILE_OFFSET64 -#define OFFSET_T __off_t /* Size in bytes. */ -#else -#define OFFSET_T __off64_t /* Size in bytes. */ -#endif - -static error_t -_get_node_size (struct node *dir, OFFSET_T *off) -{ - size_t size = 0; - error_t err; - int count = 0; - node_dirent_t *dirent_start, *dirent_current; - node_dirent_t *dirent_list = NULL; - int first_entry = 2; - - int bump_size (const char *name) - { - size_t new_size = size + DIRENT_LEN (strlen (name)); - - size = new_size; - count ++; - return 1; - } - - err = node_entries_get (dir, &dirent_list); - if (err) - return err; - - for (dirent_start = dirent_list, count = 2; - dirent_start && first_entry > count; - dirent_start = dirent_start->next, count++); - - count = 0; - - /* Make space for the `.' and `..' entries. */ - if (first_entry == 0) - bump_size ("."); - if (first_entry <= 1) - bump_size (".."); - - /* See how much space we need for the result. */ - for (dirent_current = dirent_start; - dirent_current; - dirent_current = dirent_current->next) - if (! bump_size (dirent_current->dirent->d_name)) - break; - - free (dirent_list); - - *off = size; - - return 0; -} - - -/* Make sure that NP->nn_stat is filled with current information. - CRED identifies the user responsible for the operation. */ -error_t -netfs_validate_stat (struct node *np, struct iouser *cred) -{ - error_t err = 0; - - if (np != netfs_root_node) - { - if (! (np->nn->flags & FLAG_NODE_ULFS_UPTODATE)) - err = node_update (np); - if (! err) - { - int done = 0; - - node_ulfs_iterate_unlocked (np) - if ((! done) && port_valid (node_ulfs->port)) - { - err = io_stat (node_ulfs->port, &np->nn_stat); - if (! err) - np->nn_translated = np->nn_stat.st_mode; - done = 1; - } - if (! done) - err = ENOENT; /* FIXME? */ - } - } - else - { - _get_node_size (np, &np->nn_stat.st_size); - } - - return err; -} - -/* This should attempt a chmod call for the user specified by CRED on - locked node NP, to change the owner to UID and the group to GID. */ -error_t -netfs_attempt_chown (struct iouser *cred, struct node *np, - uid_t uid, uid_t gid) -{ - return EOPNOTSUPP; -} - -/* This should attempt a chauthor call for the user specified by CRED - on locked node NP, thereby changing the author to AUTHOR. */ -error_t -netfs_attempt_chauthor (struct iouser *cred, struct node *np, - uid_t author) -{ - return EOPNOTSUPP; -} - -/* This should attempt a chmod call for the user specified by CRED on - locked node NODE, to change the mode to MODE. Unlike the normal - Unix and Hurd meaning of chmod, this function is also used to - attempt to change files into other types. If such a transition is - attempted which is impossible, then return EOPNOTSUPP. */ -error_t -netfs_attempt_chmod (struct iouser *cred, struct node *np, - mode_t mode) -{ - return EOPNOTSUPP; -} - -/* Attempt to turn locked node NP (user CRED) into a symlink with - target NAME. */ -error_t -netfs_attempt_mksymlink (struct iouser *cred, struct node *np, - char *name) -{ - return EOPNOTSUPP; -} - -/* Attempt to turn NODE (user CRED) into a device. TYPE is either - S_IFBLK or S_IFCHR. NP is locked. */ -error_t -netfs_attempt_mkdev (struct iouser *cred, struct node *np, - mode_t type, dev_t indexes) -{ - return EOPNOTSUPP; -} - -/* Attempt to set the passive translator record for FILE to ARGZ (of - length ARGZLEN) for user CRED. NP is locked. */ -error_t -netfs_set_translator (struct iouser *cred, struct node *np, - char *argz, size_t argzlen) -{ - return EOPNOTSUPP; -} - -/* For locked node NODE with S_IPTRANS set in its mode, look up the - name of its translator. Store the name into newly malloced - storage, and return it in *ARGZ; set *ARGZ_LEN to the total length. */ -error_t -netfs_get_translator (struct node *node, char **argz, - size_t *argz_len) -{ - return EOPNOTSUPP; -} - -/* This should attempt a chflags call for the user specified by CRED - on locked node NP, to change the flags to FLAGS. */ -error_t -netfs_attempt_chflags (struct iouser *cred, struct node *np, - int flags) -{ - return EOPNOTSUPP; -} - -/* This should attempt a utimes call for the user specified by CRED on - locked node NP, to change the atime to ATIME and the mtime to - MTIME. If ATIME or MTIME is null, then set to the current time. */ -error_t -netfs_attempt_utimes (struct iouser *cred, struct node *np, - struct timespec *atime, struct timespec *mtime) -{ - return 0; -} - -/* This should attempt to set the size of the locked file NP (for user - CRED) to SIZE bytes long. */ -error_t -netfs_attempt_set_size (struct iouser *cred, struct node *np, - off_t size) -{ - return EOPNOTSUPP; -} - -/* This should attempt to fetch filesystem status information for the - remote filesystem, for the user CRED. NP is locked. */ -error_t -netfs_attempt_statfs (struct iouser *cred, struct node *np, - struct statfs *st) -{ - return EOPNOTSUPP; -} - -/* This should sync the locked file NP completely to disk, for the - user CRED. If WAIT is set, return only after the sync is - completely finished. */ -error_t -netfs_attempt_sync (struct iouser *cred, struct node *np, - int wait) -{ - return EOPNOTSUPP; -} - -/* This should sync the entire remote filesystem. If WAIT is set, - return only after the sync is completely finished. */ -error_t -netfs_attempt_syncfs (struct iouser *cred, int wait) -{ - return 0; -} - -/* lookup */ - -/* We don't use this functions, but it has to be defined. */ -error_t -netfs_attempt_lookup (struct iouser *user, struct node *dir, - char *name, struct node **node) -{ - return EOPNOTSUPP; -} - -/* Delete NAME in DIR (which is locked) for USER. */ -error_t -netfs_attempt_unlink (struct iouser *user, struct node *dir, - char *name) -{ - error_t err = 0; - mach_port_t p; - struct stat statbuf; - - node_update (dir); - - err = node_lookup_file (dir, name, 0, &p, &statbuf); - if (err) - return err; - - port_dealloc (p); - - err = fshelp_checkdirmod (&dir->nn_stat, &statbuf, user); - if (err) - return err; - - err = node_unlink_file (dir, name); - - return err; -} - -/* Attempt to rename the directory FROMDIR to TODIR. Note that neither - of the specific nodes are locked. */ -error_t -netfs_attempt_rename (struct iouser *user, struct node *fromdir, - char *fromname, struct node *todir, - char *toname, int excl) -{ - return EOPNOTSUPP; -} - -/* Attempt to create a new directory named NAME in DIR (which is - locked) for USER with mode MODE. */ -error_t -netfs_attempt_mkdir (struct iouser *user, struct node *dir, - char *name, mode_t mode) -{ - error_t err = 0; - mach_port_t p; - struct stat statbuf; - - node_update (dir); - - err = fshelp_checkdirmod (&dir->nn_stat, 0, user); - if (err) - goto exit; - - /* Special case for no UID processes (like login shell). */ - if ((!user->uids->ids) || (!user->uids->ids)) - { - err = EACCES; - goto exit; - } - - err = node_dir_create (dir, name, mode); - if (err) - goto exit; - - err = node_lookup_file (dir, name, 0, &p, &statbuf); - if (err) - { - node_dir_remove (dir, name); - goto exit; - } - - err = file_chown (p, user->uids->ids[0], user->gids->ids[0]); - if (err) - { - port_dealloc (p); - node_dir_remove (dir, name); - goto exit; - } - - port_dealloc (p); - - exit: - - return err; -} - -/* Attempt to remove directory named NAME in DIR (which is locked) for - USER. */ -error_t -netfs_attempt_rmdir (struct iouser *user, - struct node *dir, char *name) -{ - error_t err = 0; - mach_port_t p; - struct stat statbuf; - - node_update (dir); - - err = node_lookup_file (dir, name, 0, &p, &statbuf); - if (err) - return err; - - port_dealloc (p); - - err = fshelp_checkdirmod (&dir->nn_stat, &statbuf, user); - if (err) - return err; - - err = node_dir_remove (dir, name); - - return err; -} - -/* Create a link in DIR with name NAME to FILE for USER. Note that - neither DIR nor FILE are locked. If EXCL is set, do not delete the - target. Return EEXIST if NAME is already found in DIR. */ -error_t -netfs_attempt_link (struct iouser *user, struct node *dir, - struct node *file, char *name, int excl) -{ - return EOPNOTSUPP; -} - -/* Attempt to create an anonymous file related to DIR (which is - locked) for USER with MODE. Set *NP to the returned file upon - success. No matter what, unlock DIR. */ -error_t -netfs_attempt_mkfile (struct iouser *user, struct node *dir, - mode_t mode, struct node **np) -{ - mutex_unlock (&dir->lock); - return EOPNOTSUPP; -} - -/* (We don't use this function!) Attempt to create a file named NAME - in DIR (which is locked) for USER with MODE. Set *NP to the new - node upon return. On any error, clear *NP. *NP should be locked - on success; no matter what, unlock DIR before returning. */ -error_t -netfs_attempt_create_file (struct iouser *user, struct node *dir, - char *name, mode_t mode, struct node **np) -{ - mutex_unlock (&dir->lock); - return EOPNOTSUPP; -} - -/* We use this local interface to attempt_create file since we are - using our own netfs_S_dir_lookup. */ -error_t -netfs_attempt_create_file_reduced (struct iouser *user, struct node *dir, - char *name, mode_t mode, int flags) -{ - mach_port_t p; - error_t err; - struct stat statbuf; - - node_update (dir); - - err = fshelp_checkdirmod (&dir->nn_stat, 0, user); - if (err) - goto exit; - - /* Special case for no UID processes (like login shell). */ - if ((!user->uids->ids) || (!user->uids->ids)) - { - err = EACCES; - goto exit; - } - - mutex_unlock (&dir->lock); - err = node_lookup_file (dir, name, flags | O_CREAT, - &p, &statbuf); - mutex_lock (&dir->lock); - - if (err) - goto exit; - - err = file_chmod (p, mode); - if (err) - { - port_dealloc (p); - node_unlink_file (dir, name); - goto exit; - } - - err = file_chown (p, user->uids->ids[0], user->gids->ids[0]); - if (err) - { - port_dealloc (p); - node_unlink_file (dir, name); - goto exit; - } - - err = io_stat (p, &statbuf); - - /* Check file permissions. */ - if (! err && (flags & O_READ)) - err = fshelp_access (&statbuf, S_IREAD, user); - if (! err && (flags & O_WRITE)) - err = fshelp_access (&statbuf, S_IWRITE, user); - if (! err && (flags & O_EXEC)) - err = fshelp_access (&statbuf, S_IEXEC, user); - - if (err) - { - port_dealloc (p); - node_unlink_file (dir, name); - goto exit; - } - - port_dealloc (p); - - exit: - mutex_unlock (&dir->lock); - return err; -} - -/* Read the contents of locked node NP (a symlink), for USER, into - BUF. */ -error_t -netfs_attempt_readlink (struct iouser *user, struct node *np, - char *buf) -{ - return EOPNOTSUPP; -} - -/* libnetfs uses this functions once. */ -error_t -netfs_check_open_permissions (struct iouser *user, struct node *np, - int flags, int newnode) -{ - error_t err = 0; - - if (! err && (flags & O_READ)) - err = fshelp_access (&np->nn_stat, S_IREAD, user); - if (! err && (flags & O_WRITE)) - err = fshelp_access (&np->nn_stat, S_IWRITE, user); - if (! err && (flags & O_EXEC)) - err = fshelp_access (&np->nn_stat, S_IEXEC, user); - - return err; -} - -/* Read from the locked file NP for user CRED starting at OFFSET and - continuing for up to *LEN bytes. Put the data at DATA. Set *LEN - to the amount successfully read upon return. */ -error_t -netfs_attempt_read (struct iouser *cred, struct node *np, - off_t offset, size_t *len, void *data) -{ - *len = 0; - return 0; -} - -/* Write to the locked file NP for user CRED starting at OFSET and - continuing for up to *LEN bytes from DATA. Set *LEN to the amount - successfully written upon return. */ -error_t -netfs_attempt_write (struct iouser *cred, struct node *np, - off_t offset, size_t *len, void *data) -{ - /* Since unionfs only manages directories... */ - return EISDIR; -} - -/* Return the valid access types (bitwise OR of O_READ, O_WRITE, and - O_EXEC) in *TYPES for locked file NP and user CRED. */ -error_t -netfs_report_access (struct iouser *cred, struct node *np, - int *types) -{ - *types = 0; - if (fshelp_access (&np->nn_stat, S_IREAD, cred) == 0) - *types |= O_READ; - if (fshelp_access (&np->nn_stat, S_IWRITE, cred) == 0) - *types |= O_WRITE; - if (fshelp_access (&np->nn_stat, S_IEXEC, cred) == 0) - *types |= O_EXEC; - return 0; -} - -/* Create a new user from the specified UID and GID arrays. */ -struct iouser * -netfs_make_user (uid_t *uids, int nuids, uid_t *gids, int ngids) -{ - return NULL; -} - -/* Node NP has no more references; free all its associated storage. */ -void -netfs_node_norefs (struct node *np) -{ - node_destroy (np); -} - -error_t -netfs_attempt_lookup_improved (struct iouser *user, struct node *dir, - char *name, struct node **np, - int flags, int lastcomp, - mach_port_t *port, - mach_msg_type_name_t *port_type) -{ - mach_port_t p; - error_t err; - - mutex_lock (&dir->nn->lnode->lock); - - err = fshelp_access (&dir->nn_stat, S_IEXEC, user); - if (err) - goto exit; - - - if (! *name || ! strcmp (name, ".")) - { - - /* The same node is wanted. */ - *np = dir; - netfs_nref (*np); - - } - else if (! strcmp (name, "..")) - { - - /* We have to get the according light node first. */ - lnode_t *lnode = dir->nn->lnode; - node_t *node; - - err = ncache_node_lookup (lnode->dir, &node); - if (err) - goto exit; - - *np = node; - - } - else - { - - lnode_t *dir_lnode = dir->nn->lnode; - struct stat statbuf; - lnode_t *lnode = NULL; - - /* Lookup the node by it's name on the underlying - filesystems. */ - - err = node_update (dir); - - /* We have to unlock this node while doing lookups. */ - mutex_unlock (&dir_lnode->lock); - mutex_unlock (&dir->lock); - - err = node_lookup_file (dir, name, flags & ~(O_NOLINK|O_CREAT), - &p, &statbuf); - - mutex_lock (&dir->lock); - mutex_lock (&dir_lnode->lock); - - - if (err) - goto exit; - - if (S_ISDIR (statbuf.st_mode)) - { - node_t *node; - - /* We don't need this port directly. */ - port_dealloc (p); - - /* The found node is a directory, so we have to manage the - node. First we need the light node. */ - - err = lnode_get (dir_lnode, name, &lnode); - if (err == ENOENT) - { - /* It does not exist, we have to create it. */ - err = lnode_create (name, &lnode); - if (err) - goto exit; - - lnode_install (dir_lnode, lnode); - } - - /* Now we have a light node. */ - err = ncache_node_lookup (lnode, &node); - - /* This unlocks the node for us. */ - lnode_ref_remove (lnode); - - if (err) - goto exit; - - /* Got the node. */ - *np = node; - - } - else - { - /* The found node is not a directory. */ - mach_port_t p_restricted; - - if (! lastcomp) - { - /* We have not reached the last path component yet. */ - port_dealloc (p); - err = ENOTDIR; - goto exit; - } - - /* Check file permissions. */ - if (! err && (flags & O_READ)) - err = fshelp_access (&statbuf, S_IREAD, user); - if (! err && (flags & O_WRITE)) - err = fshelp_access (&statbuf, S_IWRITE, user); - if (! err && (flags & O_EXEC)) - err = fshelp_access (&statbuf, S_IEXEC, user); - - if (err) - { - port_dealloc (p); - goto exit; - } - - - /* A file node is successfully looked up. */ - err = io_restrict_auth (p, &p_restricted, - user->uids->ids, user->uids->num, - user->gids->ids, user->gids->num); - port_dealloc (p); - - if (err) - goto exit; - - /* Successfully restricted. */ - *port = p_restricted; - *port_type = MACH_MSG_TYPE_MOVE_SEND; - } - } - - exit: - - if (err) - *np = NULL; - else if (*np) - { - mutex_unlock (&(*np)->lock); - ncache_node_add (*np); - } - - mutex_unlock (&dir->nn->lnode->lock); - mutex_unlock (&dir->lock); - return err; -} - -/* We need our own, special implementation of netfs_S_dir_lookup, - because libnetfs does not (yet?) know about cases, in which the - servers wants to return (foreign) ports directly to the user, - instead of usual node structures. */ - -#define OPENONLY_STATE_MODES (O_CREAT|O_EXCL|O_NOLINK|O_NOTRANS|O_NONBLOCK) - -fshelp_fetch_root_callback1_t _netfs_translator_callback1; -fshelp_fetch_root_callback2_t _netfs_translator_callback2; - -error_t -netfs_S_dir_lookup (struct protid *diruser, - char *filename, - int flags, - mode_t mode, - retry_type *do_retry, - char *retry_name, - mach_port_t *retry_port, - mach_msg_type_name_t *retry_port_type) -{ - int create; /* true if O_CREAT flag set */ - int excl; /* true if O_EXCL flag set */ - int mustbedir = 0; /* true if the result must be S_IFDIR */ - int lastcomp = 0; /* true if we are at the last component */ - int newnode = 0; /* true if this node is newly created */ - int nsymlinks = 0; - struct node *dnp, *np; - char *nextname; - error_t error = 0; - struct protid *newpi; - struct iouser *user; - - if (!diruser) - return EOPNOTSUPP; - - create = (flags & O_CREAT); - excl = (flags & O_EXCL); - - /* Skip leading slashes */ - while (*filename == '/') - filename++; - - *retry_port_type = MACH_MSG_TYPE_MAKE_SEND; - *do_retry = FS_RETRY_NORMAL; - *retry_name = '\0'; - - if (*filename == '\0') - { - /* Set things up in the state expected by the code from gotit: on. */ - dnp = 0; - np = diruser->po->np; - mutex_lock (&np->lock); - netfs_nref (np); - goto gotit; - } - - dnp = diruser->po->np; - - mutex_lock (&dnp->lock); - - netfs_nref (dnp); /* acquire a reference for later netfs_nput */ - - do - { - assert (!lastcomp); - - /* Find the name of the next pathname component */ - nextname = index (filename, '/'); - - if (nextname) - { - *nextname++ = '\0'; - while (*nextname == '/') - nextname++; - if (*nextname == '\0') - { - /* These are the rules for filenames ending in /. */ - nextname = 0; - lastcomp = 1; - mustbedir = 1; - create = 0; - } - else - lastcomp = 0; - } - else - lastcomp = 1; - - np = 0; - - retry_lookup: - - if ((dnp == netfs_root_node || dnp == diruser->po->shadow_root) - && filename[0] == '.' && filename[1] == '.' && filename[2] == '\0') - if (dnp == diruser->po->shadow_root) - /* We're at the root of a shadow tree. */ - { - *do_retry = FS_RETRY_REAUTH; - *retry_port = diruser->po->shadow_root_parent; - *retry_port_type = MACH_MSG_TYPE_COPY_SEND; - if (! lastcomp) - strcpy (retry_name, nextname); - error = 0; - mutex_unlock (&dnp->lock); - goto out; - } - else if (diruser->po->root_parent != MACH_PORT_NULL) - /* We're at a real translator root; even if DIRUSER->po has a - shadow root, we can get here if its in a directory that was - renamed out from under it... */ - { - *do_retry = FS_RETRY_REAUTH; - *retry_port = diruser->po->root_parent; - *retry_port_type = MACH_MSG_TYPE_COPY_SEND; - if (!lastcomp) - strcpy (retry_name, nextname); - error = 0; - mutex_unlock (&dnp->lock); - goto out; - } - else - /* We are global root */ - { - error = 0; - np = dnp; - netfs_nref (np); - } - else - /* Attempt a lookup on the next pathname component. */ - error = netfs_attempt_lookup_improved (diruser->user, dnp, - filename, &np, - flags, lastcomp, - retry_port, retry_port_type); - - /* At this point, DNP is unlocked */ - - /* Implement O_EXCL flag here */ - if (lastcomp && create && excl && !error && np) - error = EEXIST; - - /* Create the new node if necessary */ - if (lastcomp && create && error == ENOENT) - { - mode &= ~(S_IFMT | S_ISPARE | S_ISVTX); - mode |= S_IFREG; - mutex_lock (&dnp->lock); - - error = netfs_attempt_create_file_reduced (diruser->user, dnp, - filename, mode, flags); - - /* We retry lookup in two cases: - - we created the file and we have to get a valid port; - - someone has already created the file (between our lookup - and this create) then we just got EEXIST. If we are EXCL, - that's fine; otherwise, we have to retry the lookup. */ - if ((!error) || (error == EEXIST && !excl)) - { - mutex_lock (&dnp->lock); - goto retry_lookup; - } - - newnode = 1; - } - - /* All remaining errors get returned to the user */ - if (error) - goto out; - - if (np) - { - mutex_lock (&np->lock); - error = netfs_validate_stat (np, diruser->user); - mutex_unlock (&np->lock); - if (error) - goto out; - } - - if (np - && S_ISLNK (np->nn_translated) - && (!lastcomp - || mustbedir /* "foo/" must see that foo points to a dir */ - || !(flags & (O_NOLINK|O_NOTRANS)))) - { - size_t nextnamelen, newnamelen, linklen; - char *linkbuf; - - /* Handle symlink interpretation */ - if (nsymlinks++ > netfs_maxsymlinks) - { - error = ELOOP; - goto out; - } - - linklen = np->nn_stat.st_size; - - nextnamelen = nextname ? strlen (nextname) + 1 : 0; - newnamelen = nextnamelen + linklen + 1; - linkbuf = alloca (newnamelen); - - error = netfs_attempt_readlink (diruser->user, np, linkbuf); - if (error) - goto out; - - if (nextname) - { - linkbuf[linklen] = '/'; - memcpy (linkbuf + linklen + 1, nextname, - nextnamelen - 1); - } - linkbuf[nextnamelen + linklen] = '\0'; - - if (linkbuf[0] == '/') - { - /* Punt to the caller */ - *do_retry = FS_RETRY_MAGICAL; - *retry_port = MACH_PORT_NULL; - strcpy (retry_name, linkbuf); - goto out; - } - - filename = linkbuf; - if (lastcomp) - { - lastcomp = 0; - - /* Symlinks to nonexistent files aren't allowed to cause - creation, so clear the flag here. */ - create = 0; - } - netfs_nput (np); - mutex_lock (&dnp->lock); - np = 0; - } - else - { - /* Normal nodes here for next filename component */ - filename = nextname; - netfs_nrele (dnp); - - if (lastcomp) - dnp = 0; - else - { - dnp = np; - np = 0; - } - } - } - while (filename && *filename); - - /* At this point, NP is the node to return. */ - gotit: - - if (mustbedir && ! np) - { - error = ENOTDIR; - goto out; - } - - if (np) - error = netfs_check_open_permissions (diruser->user, np, - flags, newnode); - - if (error) - goto out; - - flags &= ~OPENONLY_STATE_MODES; - - if (np) - { - error = iohelp_dup_iouser (&user, diruser->user); - if (error) - goto out; - - newpi = netfs_make_protid (netfs_make_peropen (np, flags, diruser->po), - user); - if (! newpi) - { - iohelp_free_iouser (user); - error = errno; - goto out; - } - - *retry_port = ports_get_right (newpi); - ports_port_deref (newpi); - } - - out: - if (np) - netfs_nput (np); - if (dnp) - netfs_nrele (dnp); - return error; -} - -/* Fill the array *DATA of size BUFSIZE with up to NENTRIES dirents - from DIR (which is locked) starting with entry ENTRY for user CRED. - The number of entries in the array is stored in *AMT and the number - of bytes in *DATACNT. If the supplied buffer is not large enough - to hold the data, it should be grown. */ -error_t -netfs_get_dirents (struct iouser *cred, struct node *dir, - int first_entry, int num_entries, char **data, - mach_msg_type_number_t *data_len, - vm_size_t max_data_len, int *data_entries) -{ - node_dirent_t *dirent_start, *dirent_current; - node_dirent_t *dirent_list = NULL; - size_t size = 0; - int count = 0; - char *data_p; - error_t err; - - int bump_size (const char *name) - { - if (num_entries == -1 || count < num_entries) - { - size_t new_size = size + DIRENT_LEN (strlen (name)); - - if (max_data_len > 0 && new_size > max_data_len) - return 0; - size = new_size; - count++; - return 1; - } - else - return 0; - } - - int add_dirent (const char *name, ino_t fileno, int type) - { - if (num_entries == -1 || count < num_entries) - { - struct dirent hdr; - size_t name_len = strlen (name); - size_t sz = DIRENT_LEN (name_len); - - if (sz > size) - return 0; - else - size -= sz; - - hdr.d_fileno = fileno; - hdr.d_reclen = sz; - hdr.d_type = type; - hdr.d_namlen = name_len; - - memcpy (data_p, &hdr, DIRENT_NAME_OFFS); - strcpy (data_p + DIRENT_NAME_OFFS, name); - data_p += sz; - count++; - - return 1; - } - else - return 0; - } - - err = node_entries_get (dir, &dirent_list); - - if (! err) - { - for (dirent_start = dirent_list, count = 2; - dirent_start && first_entry > count; - dirent_start = dirent_start->next, count++); - - count = 0; - - /* Make space for the `.' and `..' entries. */ - if (first_entry == 0) - bump_size ("."); - if (first_entry <= 1) - bump_size (".."); - - /* See how much space we need for the result. */ - for (dirent_current = dirent_start; - dirent_current; - dirent_current = dirent_current->next) - if (! bump_size (dirent_current->dirent->d_name)) - break; - - *data = mmap (0, size, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); - err = ((void *) *data == (void *) -1) ? errno : 0; - } - - if (! err) - { - data_p = *data; - *data_len = size; - *data_entries = count; - count = 0; - - /* Add `.' and `..' entries. */ - if (first_entry == 0) - add_dirent (".", 2, DT_DIR); - if (first_entry <= 1) - add_dirent ("..", 2, DT_DIR); - - for (dirent_current = dirent_start; - dirent_current; - dirent_current = dirent_current->next) - if (! add_dirent (dirent_current->dirent->d_name, - 2 /* FIXME */, - dirent_current->dirent->d_type)) - break; - } - - if (dirent_list) - node_entries_free (dirent_list); - - fshelp_touch (&dir->nn_stat, TOUCH_ATIME, maptime); - - return err; -} diff --git a/unionfs/node.c b/unionfs/node.c deleted file mode 100644 index cf9a8b47..00000000 --- a/unionfs/node.c +++ /dev/null @@ -1,555 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -/* node management. */ - -#define _GNU_SOURCE - -#include <hurd/netfs.h> -#include <stdlib.h> -#include <error.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <stdio.h> - -#include "unionfs.h" -#include "node.h" -#include "ulfs.h" -#include "lib.h" - -/* Declarations for functions only used in this file. */ - -/* Deallocate all ports contained in NODE and free per-ulfs data - structures. */ -void node_ulfs_free (node_t *node); - -/* Create a new node, derived from a light node, add a reference to - the light node. */ -error_t -node_create (lnode_t *lnode, node_t **node) -{ - netnode_t *netnode_new = malloc (sizeof (netnode_t)); - error_t err = 0; - node_t *node_new; - - debug_msg ("node_create for lnode: %s", lnode->name); - - if (! netnode_new) - { - err = ENOMEM; - return err; - } - - node_new = netfs_make_node (netnode_new); - if (! node_new) - { - err = ENOMEM; - free (netnode_new); - return err; - } - - node_new->nn->ulfs = NULL; - - err = node_ulfs_init (node_new); - if (err) - { - node_destroy (node_new); - return err; - } - - lnode->node = node_new; - lnode_ref_add (lnode); - node_new->nn->lnode = lnode; - node_new->nn->flags = 0; - node_new->nn->ncache_next = NULL; - node_new->nn->ncache_prev = NULL; - *node = node_new; - - return err; -} - -/* Destroy a node, remove one reference from the associated light - node. */ -void -node_destroy (node_t *node) -{ - debug_msg ("node destroy: %s", node->nn->lnode->name); - assert (! (node->nn->ncache_next || node->nn->ncache_prev)); - node_ulfs_free (node); - mutex_lock (&node->nn->lnode->lock); - node->nn->lnode->node = NULL; - lnode_ref_remove (node->nn->lnode); - free (node->nn); - free (node); -} - -/* Make sure that all ports to the underlying filesystems of NODE, - which must be locked, are uptodate. */ -error_t -node_update (node_t *node) -{ - error_t err = 0; - char *path; - - node_ulfs_t *root_ulfs; - struct stat stat; - file_t port; - int i = 0; - - debug_msg ("node_update for lnode: %s", node->nn->lnode->name); - - if (node_is_root (node)) - return err; - - mutex_lock (&netfs_root_node->lock); - - err = lnode_path_construct (node->nn->lnode, &path); - if (err) - { - mutex_unlock (&netfs_root_node->lock); - return err; - } - - root_ulfs = netfs_root_node->nn->ulfs; - - node_ulfs_iterate_unlocked (node) - { - - if (node_ulfs->flags & FLAG_NODE_ULFS_FIXED) - { - i++; - continue; - } - - /* We really have to update the port. */ - if (port_valid (node_ulfs->port)) - port_dealloc (node_ulfs->port); - - err = file_lookup ((root_ulfs + i)->port, path, - O_READ | O_NOTRANS, O_NOTRANS, - 0, &port, &stat); - - if (err) - { - node_ulfs->port = MACH_PORT_NULL; - err = 0; - i++; - continue; - } - - if (stat.st_ino == underlying_node_stat.st_ino - && stat.st_fsid == underlying_node_stat.st_fsid) - /* It's OUR root node. */ - err = ELOOP; - else - { - port_dealloc (port); - err = file_lookup ((root_ulfs + i)->port, path, - O_READ, 0, 0, &port, &stat); - } - - if (err) - { - port = MACH_PORT_NULL; - err = 0; - } - node_ulfs->port = port; - - i++; - } - - free (path); - node->nn->flags |= FLAG_NODE_ULFS_UPTODATE; - - mutex_unlock (&netfs_root_node->lock); - - return err; -} - -/* Remove all directory named NAME beneath DIR on all underlying filesystems. - Fails if we cannot remove all the directories. */ -error_t -node_dir_remove (node_t *dir, char *name) -{ - error_t err = 0; - - node_ulfs_iterate_reverse_unlocked (dir) - { - if (!port_valid (node_ulfs->port)) - continue; - - err = dir_rmdir (node_ulfs->port, name); - if ((err) && (err != ENOENT)) - break; - } - - return err; -} - -/* Create a directory named NAME beneath DIR on the first (writable) underlying - filesystem. */ -error_t -node_dir_create (node_t *dir, char *name, mode_t mode) -{ - error_t err = 0; - - node_ulfs_iterate_unlocked (dir) - { - if (!port_valid (node_ulfs->port)) - continue; - - err = dir_mkdir (node_ulfs->port, name, mode); - - if ((!err) || (err == EEXIST) || (err == ENOTDIR)) - break; - } - - return err; -} - -/* Remove all files named NAME beneath DIR on the underlying filesystems - with FLAGS as openflags. */ -error_t -node_unlink_file (node_t *dir, char *name) -{ - mach_port_t p; - struct stat stat; - error_t err = 0; - int removed = 0; - - /* Using reverse iteration still have issues. Infact, we could be - deleting a file in some underlying filesystem, and keeping those - after the first occurring error. - FIXME: Check BEFORE starting deletion. */ - - node_ulfs_iterate_reverse_unlocked (dir) - { - - if (!port_valid (node_ulfs->port)) - continue; - - err = file_lookup (node_ulfs->port, name, - O_NOTRANS, O_NOTRANS, - 0, &p, &stat); - - port_dealloc (p); - - if (err == ENOENT) - { - err = 0; - continue; - } - - if (err) - break; - - err = dir_unlink (node_ulfs->port, name); - if ((err) && (err != ENOENT)) - break; - - if (!err) - removed++; - - } - - if ((!err) && (!removed)) - err = ENOENT; - - return err; -} - -/* Lookup a file named NAME beneath DIR on the underlying filesystems - with FLAGS as openflags. Return the first port successfully looked - up in *PORT and according stat information in *STAT. */ -error_t -node_lookup_file (node_t *dir, char *name, int flags, - file_t *port, struct stat *s) -{ - error_t err = ENOENT; - struct stat stat; - file_t p; - - node_ulfs_iterate_unlocked (dir) - { - - if (err != ENOENT) - break; - - if (!port_valid (node_ulfs->port)) - continue; - - err = file_lookup (node_ulfs->port, name, - flags | O_NOTRANS, O_NOTRANS, - 0, &p, &stat); - if (err) - continue; - - if (stat.st_ino == underlying_node_stat.st_ino - && stat.st_fsid == underlying_node_stat.st_fsid) - /* It's OUR root node. */ - err = ELOOP; - else - /* stat.st_mode & S_ITRANS */ - { - port_dealloc (p); - err = file_lookup (node_ulfs->port, name, - flags, 0, 0, &p, &stat); - } - } - - if (! err) - { - *s = stat; - *port = p; - } - - return err; -} - -/* Deallocate all ports contained in NODE and free per-ulfs data - structures. */ -void -node_ulfs_free (node_t *node) -{ - - node_ulfs_iterate_unlocked (node) - { - if (port_valid (node_ulfs->port) - && node_ulfs->port != underlying_node) - port_dealloc (node_ulfs->port); - } - - free (node->nn->ulfs); -} - -/* Initialize per-ulfs data structures for NODE. The ulfs_lock must - be held by the caller. */ -error_t -node_ulfs_init (node_t *node) -{ - node_ulfs_t *ulfs_new; - error_t err = 0; - - ulfs_new = malloc (ulfs_num * sizeof (node_ulfs_t)); - if (! ulfs_new) - { - err = ENOMEM; - return err; - } - - if (node->nn->ulfs) - node_ulfs_free (node); - - node->nn->ulfs = ulfs_new; - node->nn->ulfs_num = ulfs_num; - - node_ulfs_iterate_unlocked (node) - { - node_ulfs->flags = 0; - node_ulfs->port = port_null; - } - - return err; -} - -/* Read the merged directory entries from NODE, which must be - locked, into *DIRENTS. */ -error_t -node_entries_get (node_t *node, node_dirent_t **dirents) -{ - struct dirent **dirent_list, **dirent; - node_dirent_t *node_dirent_list = NULL; - size_t dirent_data_size; - char *dirent_data; - error_t err = 0; - - /* Add a dirent to the list. If an entry with the specified name - already exists, reuse that entry. Otherwise create a new - one. */ - error_t node_dirent_add (char *name, ino_t fileno, int type) - { - error_t e = 0; - node_dirent_t *node_dirent; - node_dirent_t *node_dirent_new; - struct dirent *dirent_new; - int name_len = strlen (name); - int size = DIRENT_LEN (name_len); - - - for (node_dirent = node_dirent_list; - node_dirent && strcmp (node_dirent->dirent->d_name, name); - node_dirent = node_dirent->next); - - if (node_dirent) - { - /* Reuse existing entry. */ - - node_dirent->dirent->d_fileno = fileno; - node_dirent->dirent->d_type = type; - return e; - } - - /* Create new entry. */ - - node_dirent_new = malloc (sizeof (node_dirent_t)); - if (!node_dirent_new) - { - e = ENOMEM; - return e; - } - - dirent_new = malloc (size); - if (!dirent_new) - { - free (node_dirent_new); - e = ENOMEM; - return e; - } - - /* Fill dirent. */ - dirent_new->d_fileno = fileno; - dirent_new->d_type = type; - dirent_new->d_reclen = size; - strcpy ((char *) dirent_new + DIRENT_NAME_OFFS, name); - - /* Add dirent to the list. */ - node_dirent_new->dirent = dirent_new; - node_dirent_new->next = node_dirent_list; - node_dirent_list = node_dirent_new; - - return e; - } - - node_ulfs_iterate_unlocked(node) - { - if (!port_valid (node_ulfs->port)) - continue; - - err = dir_entries_get (node_ulfs->port, &dirent_data, - &dirent_data_size, &dirent_list); - if (err) - continue; - - for (dirent = dirent_list; (! err) && *dirent; dirent++) - if (strcmp ((*dirent)->d_name, ".") - && strcmp ((*dirent)->d_name, "..")) - err = node_dirent_add ((*dirent)->d_name, - (*dirent)->d_fileno, - (*dirent)->d_type); - - free (dirent_list); - munmap (dirent_data, dirent_data_size); - } - - if (err) - node_entries_free (node_dirent_list); - else - *dirents = node_dirent_list; - - return err; -} - -/* Free DIRENTS. */ -void -node_entries_free (node_dirent_t *dirents) -{ - node_dirent_t *dirent, *dirent_next; - - for (dirent = dirents; dirent; dirent = dirent_next) - { - dirent_next = dirent->next; - free (dirent->dirent); - free (dirent); - } -} - -/* Create the root node (and it's according lnode) and store it in - *ROOT_NODE. */ -error_t -node_create_root (node_t **root_node) -{ - lnode_t *lnode; - node_t *node; - error_t err = 0; - - err = lnode_create (NULL, &lnode); - if (err) - return err; - - err = node_create (lnode, &node); - if (err) - { - lnode_destroy (lnode); - return err; - } - - mutex_unlock (&lnode->lock); - *root_node = node; - return err; -} - -/* Initialize the ports to the underlying filesystems for the root - node. */ - -error_t -node_init_root (node_t *node) -{ - error_t err; - ulfs_t *ulfs; - int i = 0; - - mutex_lock (&ulfs_lock); - - err = node_ulfs_init (node); - if (err) - { - mutex_unlock (&ulfs_lock); - return err; - } - - node_ulfs_iterate_unlocked (node) - { - - if (err) - break; - - err = ulfs_get_num (i, &ulfs); - if (err) - break; - - if (ulfs->path) - node_ulfs->port = file_name_lookup (ulfs->path, - O_READ | O_DIRECTORY, 0); - else - node_ulfs->port = underlying_node; - - if (! port_valid (node_ulfs->port)) - { - err = errno; - break; - } - - node_ulfs->flags |= FLAG_NODE_ULFS_FIXED; - i++; - } - - mutex_unlock (&ulfs_lock); - return err; -} diff --git a/unionfs/node.h b/unionfs/node.h deleted file mode 100644 index 41ae43ad..00000000 --- a/unionfs/node.h +++ /dev/null @@ -1,135 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -/* node management. */ - -#ifndef INCLUDED_NODE_H -#define INCLUDED_NODE_H - -#include <error.h> -#include <sys/stat.h> -#include <hurd/netfs.h> - -typedef struct node node_t; - -#include "lnode.h" - -/* per-ulfs data for each node. */ -struct node_ulfs -{ - int flags; /* Flags associated for this - underlying filesystem. */ - file_t port; /* A port to the underlying - filesystem. */ -}; -typedef struct node_ulfs node_ulfs_t; - -/* Flags. */ - -/* The according port should not be updated. */ -#define FLAG_NODE_ULFS_FIXED 0x00000001 - -struct netnode -{ - lnode_t *lnode; /* A reference to the according light - node. */ - int flags; /* Associated flags. */ - node_ulfs_t *ulfs; /* Array holding data for each - underlying filesystem. */ - int ulfs_num; /* Number of entries in ULFS. */ - node_t *ncache_next; - node_t *ncache_prev; -}; -typedef struct netnode netnode_t; - -/* Flags. */ -#define FLAG_NODE_INVALIDATE 0x00000001 -#define FLAG_NODE_ULFS_UPTODATE 0x00000002 - -typedef struct node_dirent -{ - struct dirent *dirent; - struct node_dirent *next; -} node_dirent_t; - -/* Create a new node, derived from a light node, add a reference to - the light node. */ -error_t node_create (lnode_t *lnode, node_t **node); - -/* Destroy a node, remove one reference from the associated light - node. */ -void node_destroy (node_t *node); - -/* Make sure that all ports to the underlying filesystems of NODE, - which must be locked, are uptodate. */ -error_t node_update (node_t *node); - -/* Create a directory named NAME beneath DIR on all the (writable) underlying - filesystems. */ -error_t node_dir_create (node_t *dir, char *name, mode_t mode); - -/* Remove all directory named NAME beneath DIR on all underlying filesystems. - Fails if we cannot remove all the directories. */ -error_t node_dir_remove (node_t *dir, char *name); - -/* Remove all files named NAME beneath DIR on the underlying filesystems - with FLAGS as openflags. */ -error_t node_unlink_file (node_t *dir, char *name); - -/* Lookup a file named NAME beneath DIR on the underlying filesystems - with FLAGS as openflags. Return the first port successfully looked - up in *PORT and according stat information in *STAT. */ -error_t node_lookup_file (node_t *dir, char *name, int flags, - file_t *port, struct stat *stat); - -/* Initialize per-ulfs data structures for NODE. The ulfs_lock must - be held by the caller. */ -error_t node_ulfs_init (node_t *node); - -/* Read the merged directory entries from NODE, which must be - locked, into *DIRENTS. */ -error_t node_entries_get (node_t *node, node_dirent_t **dirents); - -/* Free DIRENTS. */ -void node_entries_free (node_dirent_t *dirents); - -/* Create the root node (and it's according lnode) and store it in - *ROOT_NODE. */ -error_t node_create_root (node_t **root_node); - -/* Initialize the ports to the underlying filesystems for the root - node. */ -error_t node_init_root (node_t *node); - -/* Return non-zero, if NODE is the root node. */ -#define node_is_root(node) (node)->nn->lnode->dir ? 0 : 1 - -/* Iterate over the per-ulfs data in NODE, which must be locked by the - caller. */ -#define node_ulfs_iterate_unlocked(node) \ - for (node_ulfs_t *node_ulfs = (node)->nn->ulfs; \ - node_ulfs < (node)->nn->ulfs + (node)->nn->ulfs_num; \ - node_ulfs++) - -#define node_ulfs_iterate_reverse_unlocked(node) \ - for (node_ulfs_t *node_ulfs = (node)->nn->ulfs + (node)->nn->ulfs_num - 1;\ - node_ulfs >= (node)->nn->ulfs; \ - node_ulfs--) - -#endif diff --git a/unionfs/options.c b/unionfs/options.c deleted file mode 100644 index ef29a020..00000000 --- a/unionfs/options.c +++ /dev/null @@ -1,225 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -/* Argument parsing. */ - -#define _GNU_SOURCE - -#include <argp.h> -#include <error.h> - -#include "options.h" -#include "ulfs.h" -#include "ncache.h" -#include "unionfs.h" -#include "node.h" -#include "version.h" -#include "pattern.h" -#include "stow.h" -#include "update.h" - -/* This variable is set to a non-zero value after parsing of the - startup options. Whenever the argument parser is later called to - modify the underlying filesystems of the root node, the root node - is initialized accordingly directly by the parser. */ -static int parsing_startup_options_finished; - -/* Argp options common to the runtime and startup parser. */ -static const struct argp_option argp_common_options[] = - { - { OPT_LONG_UNDERLYING, OPT_UNDERLYING, 0, 0, - "add the underlying node to the unionfs" }, - { OPT_LONG_WRITABLE, OPT_WRITABLE, 0, 0, - "specify the following filesystem as writable" }, - { OPT_LONG_DEBUG, OPT_DEBUG, 0, OPTION_HIDDEN, - "send debugging messages to stderr" }, - { OPT_LONG_CACHE_SIZE, OPT_CACHE_SIZE, "SIZE", 0, - "specify the maximum number of nodes in the cache" }, - { 0, 0, 0, 0, "Runtime options:", 1 }, - { OPT_LONG_STOW, OPT_STOW, "STOWDIR", 0, - "stow given directory", 1}, - { OPT_LONG_PRIORITY, OPT_PRIORITY, "VALUE", 0, - "Set the priority for the following filesystem to VALUE", 1}, - { OPT_LONG_PATTERN, OPT_PATTERN, "PATTERN", 0, - "add only nodes of the underlying filesystem matching pattern", 1}, - { OPT_LONG_REMOVE, OPT_REMOVE, 0, 0, - "remove the following filesystem", 1 }, - { OPT_LONG_ADD, OPT_ADD, 0, 0, - "add the following filesystem (Default)", 1 }, - { 0 } - }; - -/* Argp options only meaningful for startup parsing. */ -static const struct argp_option argp_startup_options[] = - { - { 0 } - }; - -/* Argp parser function for the common options. */ -static error_t -argp_parse_common_options (int key, char *arg, struct argp_state *state) -{ - static int ulfs_flags = 0, ulfs_mode = 0, ulfs_modified = 0, - ulfs_match = 0, ulfs_priority = 0; - static struct patternlist ulfs_patternlist = - { - .lock = MUTEX_INITIALIZER, - .head = NULL - }; - error_t err = 0; - - switch (key) - { - case OPT_WRITABLE: /* --writable */ - ulfs_flags |= FLAG_ULFS_WRITABLE; - break; - - case OPT_PRIORITY: /* --priority */ - ulfs_priority = strtol (arg, NULL, 10); - break; - - case OPT_DEBUG: /* --debug */ - unionfs_flags |= FLAG_UNIONFS_MODE_DEBUG; - break; - - case OPT_CACHE_SIZE: /* --cache-size */ - ncache_size = strtol (arg, NULL, 10); - break; - - case OPT_ADD: /* --add */ - ulfs_mode = ULFS_MODE_ADD; - break; - - case OPT_REMOVE: /* --remove */ - ulfs_mode = ULFS_MODE_REMOVE; - break; - - case OPT_PATTERN: /* --match */ - ulfs_match = 1; - patternlist_add (&ulfs_patternlist, arg); - break; - - case OPT_STOW: /* --stow */ - err = stow_diradd (arg, ulfs_flags, &ulfs_patternlist, ulfs_priority); - if (err) - error (EXIT_FAILURE, err, "stow_diradd"); - ulfs_modified = 1; - ulfs_flags = ulfs_mode = ulfs_priority = 0; - ulfs_match = 0; - break; - - case OPT_UNDERLYING: /* --underlying */ - case ARGP_KEY_ARG: - - if (ulfs_mode == ULFS_MODE_REMOVE) - { - err = ulfs_unregister (arg); - if (err == ENOENT) - /* It is not a fatal error, when the user tries to remove - a filesystem, which is not used by unionfs. */ - err = 0; - } - else - err = ulfs_register (arg, ulfs_flags, ulfs_priority); - if (err) - error (EXIT_FAILURE, err, "ulfs_register"); - ulfs_modified = 1; - ulfs_flags = ulfs_mode = ulfs_priority = 0; - ulfs_match = 0; - break; - - case ARGP_KEY_END: - ulfs_flags = ulfs_mode = 0; - if (ulfs_modified && parsing_startup_options_finished) - { - root_update_schedule (); - } - else - { - ncache_reset (); - } - ulfs_modified = 0; - - if (! parsing_startup_options_finished) - parsing_startup_options_finished = 1; - break; - - default: - err = ARGP_ERR_UNKNOWN; - break; - } - - return err; -} - -/* Argp parser function for the startup oprtions. */ -static error_t -argp_parse_startup_options (int key, char *arg, struct argp_state *state) -{ - error_t err = 0; - - switch (key) - { - default: - err = ARGP_ERR_UNKNOWN; - break; - } - - return err; -} - -/* Argp parser for only the common options. */ -static const struct argp argp_parser_common_options = - { argp_common_options, argp_parse_common_options, 0, 0, 0 }; - -/* Argp parser for only the startup options. */ -static struct argp argp_parser_startup_options = - { argp_startup_options, argp_parse_startup_options, 0, 0, 0 }; - -/* The children parser for runtime arguments. */ -static const struct argp_child argp_children_runtime[] = - { - { &argp_parser_common_options }, - { &netfs_std_runtime_argp }, - { 0 } - }; - -/* The children parser for startup arguments. */ -const struct argp_child argp_children_startup[] = - { - { &argp_parser_startup_options }, - { &argp_parser_common_options }, - { &netfs_std_startup_argp }, - { 0 } - }; - -const char *argp_program_version = STANDARD_HURD_VERSION (unionfs); -const char *argp_program_bug_address = -"Gianluca Guida <glguida@gmail.com>"; - -#define ARGS_DOC "FILESYSTEMS ..." -#define DOC "Hurd unionfs server" - -/* The final argp parser for runtime arguments. */ -struct argp argp_runtime = - { 0, 0, 0, 0, argp_children_runtime }; - -/* The final argp parser for startup arguments. */ -struct argp argp_startup = - { 0, 0, ARGS_DOC, DOC, argp_children_startup }; diff --git a/unionfs/options.h b/unionfs/options.h deleted file mode 100644 index eb74ce61..00000000 --- a/unionfs/options.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -/* Argument parsing. */ - -/* The possible short options. */ -#define OPT_UNDERLYING 'u' -#define OPT_WRITABLE 'w' -#define OPT_DEBUG 'd' -#define OPT_CACHE_SIZE 'c' -#define OPT_REMOVE 'r' -#define OPT_ADD 'a' -#define OPT_PATTERN 'm' -#define OPT_PRIORITY 'p' -#define OPT_STOW 's' - -/* The long options. */ -#define OPT_LONG_UNDERLYING "underlying" -#define OPT_LONG_WRITABLE "writable" -#define OPT_LONG_DEBUG "debug" -#define OPT_LONG_CACHE_SIZE "cache-size" -#define OPT_LONG_REMOVE "remove" -#define OPT_LONG_ADD "add" -#define OPT_LONG_PATTERN "match" -#define OPT_LONG_PRIORITY "priority" -#define OPT_LONG_STOW "stow" - -#define OPT_LONG(o) "--" o - -/* The final argp parser for runtime arguments. */ -extern struct argp argp_startup; - -/* The final argp parser for startup arguments. */ -extern struct argp argp_runtime; - -#define ULFS_MODE_ADD 0 -#define ULFS_MODE_REMOVE 1 diff --git a/unionfs/pattern.c b/unionfs/pattern.c deleted file mode 100644 index 68a07917..00000000 --- a/unionfs/pattern.c +++ /dev/null @@ -1,131 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Gianluca Guida <glguida@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -/* Pattern list management. */ - -#define _GNU_SOURCE - -#include <hurd/netfs.h> -#include <stdlib.h> -#include <fnmatch.h> -#include <errno.h> - -#include "pattern.h" - -/* Add a wildcard expression *PATTERN to **PATTERNLIST. */ -error_t -patternlist_add (struct patternlist *list, char *pattern) -{ - error_t err = 0; - struct pattern *listentry; - char *dup; - - if (pattern == NULL) /* BUG. */ - err = EINVAL; - - if (err) - return err; - - dup = strdup (pattern); - if (dup == NULL) - err = ENOMEM; - - if (err) - return err; - - listentry = malloc (sizeof (struct pattern)); - if (listentry == NULL) - err = ENOMEM; - - if (err) - return err; - - listentry->pattern = dup; - - mutex_lock (& (list->lock)); - if (list->head == NULL) /* List is empty. */ - { - list->head = listentry; - listentry->next = NULL; - } - else - { - listentry->next = list->head; - list->head = listentry; - } - mutex_unlock (& (list->lock)); - - return err; -} - -/* Check for match all pattern of the list *LIST, returning logical OR - of results. */ -int -patternlist_match (struct patternlist *list, char *string) -{ - struct pattern *ptr; - error_t err = ~0; /* Return false by default */ - - ptr = list->head; - - mutex_lock (&list->lock); - while (ptr != NULL) - { - err = fnmatch (ptr->pattern, string, FNM_FILE_NAME); - - if (!err) /* String matched. */ - break; - - ptr = ptr->next; - } - mutex_unlock (&list->lock); - - return err; -} - -/* Free all resource used by *PATTERNLIST. */ -void -patternlist_destroy (struct patternlist *list) -{ - struct pattern *next, *ptr = list->head; - - mutex_lock (& (list->lock)); - while (ptr != NULL) - { - next = ptr->next; - - free (ptr); - - ptr = next; - } - mutex_unlock (& (list->lock)); -} - -/* Return nonzero if *PATTERNLIST is empty. */ -int -patternlist_isempty (struct patternlist *list) -{ - int ret; - - mutex_lock (& (list->lock)); - ret = (list->head == NULL); - mutex_unlock (& (list->lock)); - - return ret; -} diff --git a/unionfs/pattern.h b/unionfs/pattern.h deleted file mode 100644 index 1bab9933..00000000 --- a/unionfs/pattern.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Gianluca Guida <glguida@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -/* Pattern list management. */ - -#ifndef _PATTERN_H -#define _PATTERN_H - -#include <hurd/netfs.h> /* For mutex stuff. */ - -struct pattern -{ - char *pattern; - - struct pattern *next; -}; - -struct patternlist -{ - struct mutex lock; - struct pattern *head; -}; - -/* Add a wildcard expression *PATTERN to **PATTERNLIST. */ -extern error_t patternlist_add (struct patternlist *list, char *pattern); - -/* Check for match all pattern of the list *LIST, returning logical OR - of results. */ -extern int patternlist_match (struct patternlist *list, char *string); - -/* Free all resource used by *PATTERNLIST */ -extern void patternlist_destroy (struct patternlist *list); - -/* Return nonzero if *PATTERNLIST is empty */ -extern int patternlist_isempty (struct patternlist *list); - -#endif /* _PATTERN_H */ diff --git a/unionfs/stow-mutations.h b/unionfs/stow-mutations.h deleted file mode 100644 index d36280d2..00000000 --- a/unionfs/stow-mutations.h +++ /dev/null @@ -1,27 +0,0 @@ -/* stow-mutations.h - MIG mutations unionfs. - Copyright (C) 2005 Free Software Foundation, Inc. - Written by Gianluca Guida <glguida@gmail.com>. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ - -/* Only CPP macro definitions should go in this file. */ - -#define FS_NOTIFY_INTRAN stow_notify_t begin_using_notify_port (fs_notify_t) -#define FS_NOTIFY_DESTRUCTOR end_using_notify_port (stow_notify_t) - -#define FS_NOTIFY_IMPORTS import "stow-priv.h"; - diff --git a/unionfs/stow-priv.h b/unionfs/stow-priv.h deleted file mode 100644 index 2212ac98..00000000 --- a/unionfs/stow-priv.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2005 Free Software Foundation, Inc. - Written by Gianluca Guida <glguida@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -#ifndef __STOW_PRIVDATA_H__ -#define __STOW_PRIVDATA_H__ - -#include <hurd/ports.h> - -struct stow_notify -{ - struct port_info pi; - - char *dir_name; - struct stow_privdata *priv; -}; -typedef struct stow_notify *stow_notify_t; - - -/* Called by MiG to translate ports into stow_notify_t. mutations.h - arranges for this to happen for the fs_notify interfaces. */ -stow_notify_t begin_using_notify_port (fs_notify_t port); - - -/* Called by MiG after server routines have been run; this balances - begin_using_notify_port, and is arranged for the fs_notify - interfaces by mutations.h. */ -void end_using_notify_port (stow_notify_t cred); - -#endif /* STOW_PRIVDATA_H */ diff --git a/unionfs/stow.c b/unionfs/stow.c deleted file mode 100644 index fa997472..00000000 --- a/unionfs/stow.c +++ /dev/null @@ -1,328 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2005 Free Software Foundation, Inc. - Written by Gianluca Guida <glguida@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - - -/* Stow mode for unionfs. */ - -#define _GNU_SOURCE - -#include <argp.h> -#include <error.h> - -#include "ulfs.h" -#include "lib.h" -#include "pattern.h" -#include "update.h" - -struct stow_privdata -{ - struct patternlist *patternlist; - int flags; - int priority; - struct mutex lock; -}; - -static error_t -_stow_registermatchingdirs (char *arg, char *dirpath, void *priv) -{ - error_t err = 0; - char *filepath; - - struct stow_privdata *privdata = (struct stow_privdata *) priv ; - - err = patternlist_match (privdata->patternlist, arg); - if (err) - return 0; /* It doesn't match. This is not an error. */ - - filepath = make_filepath (dirpath, arg); - - err = ulfs_register (filepath, privdata->flags, privdata->priority); - - free (filepath); - - if (err) - return err; - - return 0; -} - -static error_t -_stow_scanstowentry (char *arg, char *dirpath, void *priv) -{ - char *filepath = dirpath; - error_t err; - - struct stow_privdata *privdata = (struct stow_privdata *) priv ; - - if (dirpath) - { - char *tmp; - tmp = make_filepath (dirpath, arg); - filepath = make_filepath (tmp, "/"); - free (tmp); - } - - mutex_lock (&privdata->lock); - - if (patternlist_isempty (privdata->patternlist)) - { - - err = ulfs_register (filepath, privdata->flags, privdata->priority); - if (err) - { - mutex_unlock (&privdata->lock); - return err; - } - - } - else - { - err = for_each_subdir_priv (filepath, _stow_registermatchingdirs, priv); - if (err) - { - mutex_unlock (&privdata->lock); - free (filepath); - return err; - } - } - - free (filepath); - mutex_unlock (&privdata->lock); - return err; -} - - -/* Implement server for fs_notify. */ - -#include <cthreads.h> -#include <hurd/port.h> - -#include "stow-priv.h" -#include "ncache.h" - -struct port_bucket *stow_port_bucket; -struct port_class *stow_port_class; - -static error_t -_stow_notify_init(char *dir_name, void *priv) -{ - error_t err; - file_t dir_port; - mach_port_t notify_port; - stow_notify_t stow_notify_port; - - err = ports_create_port (stow_port_class, stow_port_bucket, - sizeof (*stow_notify_port), - &stow_notify_port); - if (err) - return err; - - stow_notify_port->dir_name = dir_name; - stow_notify_port->priv = priv; - - dir_port = file_name_lookup (dir_name, 0, 0); - - if (!port_valid (dir_port)) - return ENOENT; /* ? */ - - - notify_port = ports_get_right (stow_notify_port); - - if (!port_valid (notify_port)) - { - port_dealloc (dir_port); - return EACCES; /* ? */ - } - - err = dir_notice_changes (dir_port, notify_port, - MACH_MSG_TYPE_MAKE_SEND); - if (err) - { - port_dealloc (dir_port); - port_dealloc (notify_port); - return err; - } - - return err; -} - -/* Called by MiG to translate ports into stow_notify_t. mutations.h - arranges for this to happen for the fs_notify interfaces. */ -stow_notify_t -begin_using_notify_port (fs_notify_t port) -{ - return ports_lookup_port (stow_port_bucket, port, stow_port_class); -} - -/* Called by MiG after server routines have been run; this balances - begin_using_notify_port, and is arranged for the fs_notify - interfaces by mutations.h. */ -void -end_using_notify_port (stow_notify_t cred) -{ - if (cred) - ports_port_deref (cred); -} - -/* We don't ask for file_changes, but this function has to be defined . */ -kern_return_t -stow_S_file_changed (stow_notify_t notify, natural_t tickno, - file_changed_type_t change, loff_t start, - loff_t end) -{ - return EOPNOTSUPP; -} - -/* Called when we receive a dir_changed message. */ -kern_return_t -stow_S_dir_changed (stow_notify_t notify, natural_t tickno, - dir_changed_type_t change, string_t name) -{ - error_t err; - - if (!notify || !notify->dir_name || !notify->priv) - return EOPNOTSUPP; - - switch (change) - { - case DIR_CHANGED_NULL: - break; - case DIR_CHANGED_NEW: - root_update_disable (); - - err = _stow_scanstowentry (name, notify->dir_name, notify->priv); - if (err) - debug_msg_send ("scanstowentry: %s\n", strerror (err)); - - root_update_schedule (); - root_update_enable (); - break; - - case DIR_CHANGED_UNLINK: - root_update_schedule (); - break; - - default: - debug_msg_send ("unsupported dir change notify"); - return EINVAL; - } - - return 0; -} - -/* This is the server thread waiting for dir_changed messages. */ -static void -_stow_notify_thread() -{ - int stow_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp) - { - int stow_fs_notify_server (mach_msg_header_t *inp, - mach_msg_header_t *outp); - - return (stow_fs_notify_server (inp, outp)); - } - - do - { - ports_manage_port_operations_multithread (stow_port_bucket, - stow_demuxer, - 1000 * 60 * 2, - 1000 * 60 * 10, - 0); - } - while (1); -} - - - -/* Interface to unionfs. */ - -error_t -stow_diradd (char *dir, int flags, struct patternlist *patternlist, - int priority) -{ - - error_t err; - struct stow_privdata *mypriv; - int dir_len; - - dir_len = strlen(dir); - if (dir_len == 0) - { - return EOPNOTSUPP; - } - - if (dir[dir_len - 1 ] != '/') - { - char *tmp; - - tmp = (char *) malloc (dir_len + 1); - - if (tmp == NULL) - return ENOMEM; - - strncpy (tmp, dir, dir_len); - - tmp[dir_len] = '/'; - - dir = tmp; - } - - mypriv = malloc (sizeof (struct stow_privdata)); - if (!mypriv) - { - free (dir); - return ENOMEM; - } - - mypriv->patternlist = patternlist; - mypriv->flags = flags; - mypriv->priority = priority; - mutex_init (&mypriv->lock); - - err = for_each_subdir_priv (dir, _stow_scanstowentry, (void *)mypriv); - if (err) - { - /* FIXME: rescan and delete previous inserted things. */ - return err; - } - - err = _stow_notify_init (dir, mypriv); - assert (!err); - - return err; -} - -error_t -stow_init (void) -{ - error_t err = 0; - - stow_port_bucket = ports_create_bucket (); - if (!stow_port_bucket) - return errno; - - stow_port_class = ports_create_class (NULL, NULL); - if (!stow_port_class) - return errno; - - cthread_detach (cthread_fork ( (cthread_fn_t)_stow_notify_thread, 0)); - - return err; -} diff --git a/unionfs/stow.h b/unionfs/stow.h deleted file mode 100644 index 54ff7060..00000000 --- a/unionfs/stow.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2005 Free Software Foundation, Inc. - Written by Gianluca Guida <glguida@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -/* Stow mode for unionfs. */ - -#ifndef _STOW_H -#define _STOW_H - -#include "pattern.h" - -error_t stow_init (void); -error_t stow_diradd (char *, int, struct patternlist *, int); - -#endif /* _STOW_H */ diff --git a/unionfs/ulfs.c b/unionfs/ulfs.c deleted file mode 100644 index 3c565a5c..00000000 --- a/unionfs/ulfs.c +++ /dev/null @@ -1,321 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -/* Underlying filesystem management. */ - -#define _GNU_SOURCE - -#include <hurd/netfs.h> -#include <stdlib.h> -#include <error.h> -#include <string.h> - -#include "unionfs.h" -#include <fcntl.h> - -#include "lib.h" -#include "ulfs.h" - -/* The start of the ulfs chain. */ -ulfs_t *ulfs_chain_start; - -/* The end of the ulfs chain, we need this, to go through the chain in - reversed order. */ -ulfs_t *ulfs_chain_end; - -/* Number of registered underlying filesystems. */ -unsigned int ulfs_num; - -/* The lock protecting the ulfs data structures. */ -struct mutex ulfs_lock = MUTEX_INITIALIZER; - -/* Create a new ulfs element. */ -static error_t -ulfs_create (char *path, ulfs_t **ulfs) -{ - ulfs_t *ulfs_new = malloc (sizeof (ulfs_t)); - error_t err = 0; - - if (! ulfs_new) - err = ENOMEM; - else - { - char *path_cp = path ? strdup (path) : NULL; - - if (path && (! path_cp)) - { - err = ENOMEM; - free (ulfs_new); - } - else - { - ulfs_new->path = path_cp; - ulfs_new->flags = 0; - ulfs_new->next = NULL; - ulfs_new->prev = NULL; - *ulfs = ulfs_new; - } - } - return err; -} - -/* Destroy an ulfs element. */ -static void -ulfs_destroy (ulfs_t *ulfs) -{ - free (ulfs->path); - free (ulfs); -} - -/* Install ULFS into the linked list of registered filesystems in - * priority order. */ -static void -ulfs_install (ulfs_t *ulfs) -{ - ulfs_t *u = ulfs_chain_start; - int insert_at_end = 0; - if (ulfs_num == 0) - { - ulfs_chain_start = ulfs; - return; - } - - /* walk the chain until a filesystem has a priority that's too high. */ - while (u->priority > ulfs->priority) - { - if (u->next == NULL) - { - insert_at_end = 1; - break; - } - u = u->next; - } - - if (insert_at_end) - { - u->next = ulfs; - ulfs->prev = u; - } - else - { - if (u == ulfs_chain_start) - { - ulfs_chain_start = ulfs; - ulfs->next = u; - ulfs->prev = NULL; - u->prev = ulfs; - } - else - { - ulfs->next = u; - ulfs->prev = u->prev; - u->prev->next = ulfs; - u->prev = ulfs; - } - } - - return; -} - -/* Remove ULFS from the linked list of registered filesystems. */ -static void -ulfs_uninstall (ulfs_t *ulfs) -{ - if (ulfs == ulfs_chain_start) - ulfs_chain_start = ulfs->next; - - if (ulfs->next) - ulfs->next->prev = ulfs->prev; - - if (ulfs->prev) - ulfs->prev->next = ulfs->next; -} - -/* Get an ulfs element by it's index. */ -error_t -ulfs_get_num (int num, ulfs_t **ulfs) -{ - error_t err = EINVAL; - ulfs_t *u; - int i; - - for (u = ulfs_chain_start, i = 0; - u && i < num; - u = u->next, i++); - if (u) - { - err = 0; - *ulfs = u; - } - - return err; -} - -/* Get an ulfs element by the associated path. */ -static error_t -ulfs_get_path (char *path, ulfs_t **ulfs) -{ - error_t err = ENOENT; - ulfs_t *u; - - for (u = ulfs_chain_start; - u && (! (((! path) && path == u->path) - || (path && u->path && (! strcmp (path, u->path))))); - u = u->next); - if (u) - { - err = 0; - *ulfs = u; - } - return err; -} - -error_t -ulfs_for_each_under_priv (char *path_under, - error_t (*func) (char *, char *, void *), - void *priv) -{ - error_t err = 0; - ulfs_t *u; - size_t length; - - length = strlen (path_under); - - for (u = ulfs_chain_start; u; u = u->next) - { - if (!u->path) - continue; - - if (memcmp (u->path, path_under, length)) - continue; - - /* This ulfs is under path_under. */ - func ((char *)(u->path + length), path_under, priv); - } - - return err; -} - -/* Register a new underlying filesystem. */ -error_t -ulfs_register (char *path, int flags, int priority) -{ - ulfs_t *ulfs; - error_t err; - - if (path) - { - err = check_dir (path); - if (err) - return err; - } - - mutex_lock (&ulfs_lock); - err = ulfs_create (path, &ulfs); - if (! err) - { - ulfs->flags = flags; - ulfs->priority = priority; - ulfs_install (ulfs); - ulfs_num++; - } - mutex_unlock (&ulfs_lock); - return err; -} - -/* Check for deleted ulfs entries. */ -/* FIXME: Ugly as hell. Rewrite the whole ulfs.c */ -void -ulfs_check () -{ - ulfs_t *u; - file_t p; - - struct ulfs_destroy - { - ulfs_t *ulfs; - - struct ulfs_destroy *next; - } *ulfs_destroy_q = NULL; - - mutex_lock (&ulfs_lock); - - u = ulfs_chain_start; - while (u) - { - - if (u->path) - p = file_name_lookup (u->path, O_READ | O_DIRECTORY, 0); - else - p = underlying_node; - - if (! port_valid (p)) - { - struct ulfs_destroy *ptr; - - /* Add to destroy list. */ - ptr = malloc (sizeof (struct ulfs_destroy)); - assert (ptr); - - ptr->ulfs = u; - - ptr->next = ulfs_destroy_q; - ulfs_destroy_q = ptr; - } - - u = u->next; - } - - while (ulfs_destroy_q) - { - struct ulfs_destroy *ptr; - - ptr = ulfs_destroy_q; - ulfs_destroy_q = ptr->next; - - ulfs_uninstall (ptr->ulfs); - ulfs_destroy (ptr->ulfs); - ulfs_num--; - - free (ptr); - } - - mutex_unlock (&ulfs_lock); - -} - -/* Unregister an underlying filesystem. */ -error_t -ulfs_unregister (char *path) -{ - ulfs_t *ulfs; - error_t err; - - mutex_lock (&ulfs_lock); - err = ulfs_get_path (path, &ulfs); - if (! err) - { - ulfs_uninstall (ulfs); - ulfs_destroy (ulfs); - ulfs_num--; - } - mutex_unlock (&ulfs_lock); - - return err; -} diff --git a/unionfs/ulfs.h b/unionfs/ulfs.h deleted file mode 100644 index 532e3c74..00000000 --- a/unionfs/ulfs.h +++ /dev/null @@ -1,75 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -/* Underlying filesystem management. */ - -#ifndef INCLUDED_ULFS_H -#define INCLUDED_ULFS_H - -/* The structure for each registered underlying filesystem. */ -typedef struct ulfs -{ - char *path; - int flags; - int priority; - struct ulfs *next, *prev; -} ulfs_t; - -/* Flags. */ - -/* The according ulfs is marked writable. */ -#define FLAG_ULFS_WRITABLE 0x00000001 - -/* The start of the ulfs chain. */ -extern ulfs_t *ulfs_chain_start; - -/* The end of the ulfs chain, we need this, to go through the chain in - reversed order. */ -extern ulfs_t *ulfs_chain_end; - -/* Number of registered underlying filesystems. */ -extern unsigned int ulfs_num; - -/* The lock protecting the ulfs data structures. */ -extern struct mutex ulfs_lock; - -/* Register a new underlying filesystem. */ -error_t ulfs_register (char *path, int flags, int priority); - -/* Unregister an underlying filesystem. */ -error_t ulfs_unregister (char *path); - -/* Get an ULFS element by it's index. */ -error_t ulfs_get_num (int num, ulfs_t **ulfs); - -/* Removes invalid ulfs entries. */ -void ulfs_check (void); - -#define ulfs_iterate \ - for (ulfs_t *ulfs = (mutex_lock (&ulfs_lock), \ - ulfs_chain_start); \ - ulfs || (mutex_unlock (&ulfs_lock), 0); \ - ulfs = ulfs->next) - -#define ulfs_iterate_unlocked \ - for (ulfs_t *ulfs = ulfs_chain_start; \ - ulfs; \ - ulfs = ulfs->next) - -#endif diff --git a/unionfs/unionfs.h b/unionfs/unionfs.h deleted file mode 100644 index 8f5a0873..00000000 --- a/unionfs/unionfs.h +++ /dev/null @@ -1,90 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2001, 2002 Free Software Foundation, Inc. - Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -/* This unionfs knows about two different kind of nodes: `light nodes' - (in short: lnode) and `nodes' (or: netfs nodes) as used by - libnetfs. They have different tasks and therefore this division - makes sense. - - lnodes form the filesystem tree as seen by the user; most - importantly they contain the `name' of the node. - - lnodes are small and cheap, they are not cached (nodes are). - - lnodes are usually created when a node is looked up and destroyed - when that node gets destroyed; but there are also reasons for - lnodes _not_ being destroyed. - - The distinction makes it possible to keep certain information for - the unionfs in these lnodes while netfs nodes don't have to stay in - memory. - - lnodes have to be looked up first before a node is looked up. Each - lnode contains a pointer to the netfs node, which might be NULL in - case the netfs node is not in memory anymore. */ - -/* General information and properties for the unionfs. */ - -#ifndef INCLUDED_UNIONFS_H -#define INCLUDED_UNIONFS_H - -#include <hurd/netfs.h> -#include <sys/types.h> - -#include "node.h" -#include "lib.h" - -/* Default maximum number of nodes in the cache. */ -#define NCACHE_SIZE 256 - -/* The inode for the root node. */ -#define UNIONFS_ROOT_INODE 1 - -/* Flags for UNIONFS_FLAGS. */ - -/* Print debugging messages to stderr. */ -#define FLAG_UNIONFS_MODE_DEBUG 0x00000001 -/* Use copy-on-write. */ -#define FLAG_UNIONFS_MODE_COW 0x00000002 - -/* Flags describing certain properties of the unionfs. */ -extern int unionfs_flags; - -/* The filesystem id (the pid). */ -extern pid_t fsid; - -/* Mapped time, used for updating node information. */ -extern volatile struct mapped_time_value *maptime; - -/* A port to the underlying node. */ -extern mach_port_t underlying_node; - -/* stat information for the underlying node. */ -extern struct stat underlying_node_stat; - -/* Send a debugging message, if unionfs is in debugging mode. */ -#define debug_msg(fmt, args...) \ - do \ - { \ - if (unionfs_flags & FLAG_UNIONFS_MODE_DEBUG) \ - debug_msg_send (fmt , ## args); \ - } \ - while (0) - -#endif diff --git a/unionfs/update.c b/unionfs/update.c deleted file mode 100644 index 8ec66883..00000000 --- a/unionfs/update.c +++ /dev/null @@ -1,97 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2005 Free Software Foundation, Inc. - Written by Gianluca Guida <glguida@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -/* Update thread: A clean way to solve locking issues of - root node update. */ - -#define _GNU_SOURCE - -#include <errno.h> -#include <string.h> -#include <cthreads.h> -#include <rwlock.h> - -#include "ncache.h" -#include "node.h" -#include "ulfs.h" - -/* Reader lock is used by threads that are going to - add/remove an ulfs; writer lock is hold by the - update thread. */ -static struct rwlock update_rwlock; -static struct condition update_wakeup; -static struct mutex update_lock; - -static void -_root_update_thread () -{ - error_t err; - - while (1) - { - if (hurd_condition_wait (&update_wakeup, &update_lock)) - mutex_unlock (&update_lock); - - rwlock_writer_lock (&update_rwlock); - - do - { - ulfs_check(); - err = node_init_root (netfs_root_node); - } - while (err == ENOENT); - - if (err) - { - fprintf (stderr, "update thread: got a %s\n", strerror (err)); - } - - ncache_reset (); - - rwlock_writer_unlock (&update_rwlock); - } -} - -void -root_update_schedule () -{ - condition_signal (&update_wakeup); -} - -void -root_update_disable () -{ - rwlock_reader_lock (&update_rwlock); -} - -void -root_update_enable () -{ - rwlock_reader_unlock (&update_rwlock); -} - -void -root_update_init() -{ - mutex_init (&update_lock); - rwlock_init (&update_rwlock); - condition_init (&update_wakeup); - - cthread_detach (cthread_fork ( (cthread_fn_t)_root_update_thread, 0)); -} diff --git a/unionfs/update.h b/unionfs/update.h deleted file mode 100644 index 6ebd6fc6..00000000 --- a/unionfs/update.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Hurd unionfs - Copyright (C) 2005 Free Software Foundation, Inc. - Written by Gianluca Guida <glguida@gmail.com>. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or * (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -#ifndef _UDPATE_H -#define _UPDATE_H - -void root_update_schedule (); -void root_update_disable (); -void root_update_enable (); -void root_update_init (); - -#endif /* UPDATE_H */ diff --git a/unionfs/version.h b/unionfs/version.h deleted file mode 100644 index 8969db31..00000000 --- a/unionfs/version.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Hurd version - Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. - Written by Thomas Bushnell, n/BSG. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ - -#ifndef HURD_VERSION -#define HURD_VERSION "0.3" -#endif - -/* The standard way to print versions for --version. */ -#define STANDARD_HURD_VERSION(s) \ - #s " (GNU Hurd) " HURD_VERSION -#define STANDARD_HURD_VERSION_EXTRA(s, extra) \ - #s " (GNU Hurd; " extra ") " HURD_VERSION diff --git a/windhoek/MAINTAINER b/windhoek/MAINTAINER deleted file mode 100644 index b94bec5c..00000000 --- a/windhoek/MAINTAINER +++ /dev/null @@ -1 +0,0 @@ -mailaddr doebel@os.inf.tu-dresden.de diff --git a/windhoek/Makeconf.local b/windhoek/Makeconf.local deleted file mode 100644 index d6594dc7..00000000 --- a/windhoek/Makeconf.local +++ /dev/null @@ -1,10 +0,0 @@ -SYSTEMS = x86-l4v2 -ARCH = x86 -SYSTEM = x86-l4v2 - -DDEKITLIBDIR = /root/hurd/libddekit/ -DDEKITINCDIR = /root/hurd/libddekit/include -DDE26LIBDIR = /root/hurd/libdde_linux26/lib/src -OBJ_BASE = /root/hurd/libdde_linux26/build - -L4LIBDIR = . diff --git a/windhoek/Makefile b/windhoek/Makefile deleted file mode 100644 index 91646bba..00000000 --- a/windhoek/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -PKGDIR ?= ../libdde_linux26 -L4DIR ?= $(PKGDIR) - -SYSTEMS = x86-l4v2 - -DEFAULT_RELOC = 0x00a00000 - -include Makeconf.local -#-include $(PKGDIR_OBJ)/../dde/Makeconf - -TARGET = windhoek - -IDE_SRC = ide.c ide-disk.c ide-generic.c ide-io.c ide-park.c \ - ide-iops.c ide-lib.c ide-pm.c ide-pnp.c ide-probe.c ide-taskfile.c \ - setup-pci.c ide-pci-generic.c ide-pio-blacklist.c ide-sysfs.c \ - ide-dma.c ide-gd.c -IDEFILES = $(addprefix ide/, $(IDE_SRC)) - -CDROM_SRC = #cdrom.c -CDROMFILES = $(addprefix cdrom/, $(CDROM_SRC)) - -PARTITION_SRC = check.c -PARTITIONFILES = $(addprefix partitions/, $(PARTITION_SRC)) - -SRC_C = main.c genhd.c -SRC_C += $(IDEFILES) \ - $(CDROMFILES) \ - $(PARTITIONFILES) - -LIBS += --whole-archive --no-whole-archive ../libmachdev/libmachdev.a \ - -ldde_linux26.o -ldde_linux26_block ../libddekit/libddekit.a \ - -lfshelp -ltrivfs -lpciaccess -lthreads -lshouldbeinlibc \ - -lports -lhurd-slab - -LDFLAGS += -Wl,-u,__l4ddekit_initcall_noop_init -Wl,-u,__l4ddekit_initcall_as_init -Wl,-u,__l4ddekit_initcall_deadline_init - -# DDE configuration -include $(L4DIR)/Makeconf - -include $(L4DIR)/mk/prog.mk diff --git a/windhoek/TODO b/windhoek/TODO deleted file mode 100644 index 61506fe3..00000000 --- a/windhoek/TODO +++ /dev/null @@ -1,8 +0,0 @@ -* implement notifications (and tickets) -* test and fix scatter-gather I/O -* support multiple dataspaces per client - * clients can add dataspaces to an open connection - * SG I/O should be possible across all dataspaces - of a connection -* replace IDE by libATA -* add USB Storage diff --git a/windhoek/cdrom/cdrom.c b/windhoek/cdrom/cdrom.c deleted file mode 100644 index cceace61..00000000 --- a/windhoek/cdrom/cdrom.c +++ /dev/null @@ -1,3676 +0,0 @@ -/* linux/drivers/cdrom/cdrom.c - Copyright (c) 1996, 1997 David A. van Leeuwen. - Copyright (c) 1997, 1998 Erik Andersen <andersee@debian.org> - Copyright (c) 1998, 1999 Jens Axboe <axboe@image.dk> - - May be copied or modified under the terms of the GNU General Public - License. See linux/COPYING for more information. - - Uniform CD-ROM driver for Linux. - See Documentation/cdrom/cdrom-standard.tex for usage information. - - The routines in the file provide a uniform interface between the - software that uses CD-ROMs and the various low-level drivers that - actually talk to the hardware. Suggestions are welcome. - Patches that work are more welcome though. ;-) - - To Do List: - ---------------------------------- - - -- Modify sysctl/proc interface. I plan on having one directory per - drive, with entries for outputing general drive information, and sysctl - based tunable parameters such as whether the tray should auto-close for - that drive. Suggestions (or patches) for this welcome! - - - Revision History - ---------------------------------- - 1.00 Date Unknown -- David van Leeuwen <david@tm.tno.nl> - -- Initial version by David A. van Leeuwen. I don't have a detailed - changelog for the 1.x series, David? - -2.00 Dec 2, 1997 -- Erik Andersen <andersee@debian.org> - -- New maintainer! As David A. van Leeuwen has been too busy to activly - maintain and improve this driver, I am now carrying on the torch. If - you have a problem with this driver, please feel free to contact me. - - -- Added (rudimentary) sysctl interface. I realize this is really weak - right now, and is _very_ badly implemented. It will be improved... - - -- Modified CDROM_DISC_STATUS so that it is now incorporated into - the Uniform CD-ROM driver via the cdrom_count_tracks function. - The cdrom_count_tracks function helps resolve some of the false - assumptions of the CDROM_DISC_STATUS ioctl, and is also used to check - for the correct media type when mounting or playing audio from a CD. - - -- Remove the calls to verify_area and only use the copy_from_user and - copy_to_user stuff, since these calls now provide their own memory - checking with the 2.1.x kernels. - - -- Major update to return codes so that errors from low-level drivers - are passed on through (thanks to Gerd Knorr for pointing out this - problem). - - -- Made it so if a function isn't implemented in a low-level driver, - ENOSYS is now returned instead of EINVAL. - - -- Simplified some complex logic so that the source code is easier to read. - - -- Other stuff I probably forgot to mention (lots of changes). - -2.01 to 2.11 Dec 1997-Jan 1998 - -- TO-DO! Write changelogs for 2.01 to 2.12. - -2.12 Jan 24, 1998 -- Erik Andersen <andersee@debian.org> - -- Fixed a bug in the IOCTL_IN and IOCTL_OUT macros. It turns out that - copy_*_user does not return EFAULT on error, but instead returns the number - of bytes not copied. I was returning whatever non-zero stuff came back from - the copy_*_user functions directly, which would result in strange errors. - -2.13 July 17, 1998 -- Erik Andersen <andersee@debian.org> - -- Fixed a bug in CDROM_SELECT_SPEED where you couldn't lower the speed - of the drive. Thanks to Tobias Ringstr|m <tori@prosolvia.se> for pointing - this out and providing a simple fix. - -- Fixed the procfs-unload-module bug with the fill_inode procfs callback. - thanks to Andrea Arcangeli - -- Fixed it so that the /proc entry now also shows up when cdrom is - compiled into the kernel. Before it only worked when loaded as a module. - - 2.14 August 17, 1998 -- Erik Andersen <andersee@debian.org> - -- Fixed a bug in cdrom_media_changed and handling of reporting that - the media had changed for devices that _don't_ implement media_changed. - Thanks to Grant R. Guenther <grant@torque.net> for spotting this bug. - -- Made a few things more pedanticly correct. - -2.50 Oct 19, 1998 - Jens Axboe <axboe@image.dk> - -- New maintainers! Erik was too busy to continue the work on the driver, - so now Chris Zwilling <chris@cloudnet.com> and Jens Axboe <axboe@image.dk> - will do their best to follow in his footsteps - - 2.51 Dec 20, 1998 - Jens Axboe <axboe@image.dk> - -- Check if drive is capable of doing what we ask before blindly changing - cdi->options in various ioctl. - -- Added version to proc entry. - - 2.52 Jan 16, 1999 - Jens Axboe <axboe@image.dk> - -- Fixed an error in open_for_data where we would sometimes not return - the correct error value. Thanks Huba Gaspar <huba@softcell.hu>. - -- Fixed module usage count - usage was based on /proc/sys/dev - instead of /proc/sys/dev/cdrom. This could lead to an oops when other - modules had entries in dev. Feb 02 - real bug was in sysctl.c where - dev would be removed even though it was used. cdrom.c just illuminated - that bug. - - 2.53 Feb 22, 1999 - Jens Axboe <axboe@image.dk> - -- Fixup of several ioctl calls, in particular CDROM_SET_OPTIONS has - been "rewritten" because capabilities and options aren't in sync. They - should be... - -- Added CDROM_LOCKDOOR ioctl. Locks the door and keeps it that way. - -- Added CDROM_RESET ioctl. - -- Added CDROM_DEBUG ioctl. Enable debug messages on-the-fly. - -- Added CDROM_GET_CAPABILITY ioctl. This relieves userspace programs - from parsing /proc/sys/dev/cdrom/info. - - 2.54 Mar 15, 1999 - Jens Axboe <axboe@image.dk> - -- Check capability mask from low level driver when counting tracks as - per suggestion from Corey J. Scotts <cstotts@blue.weeg.uiowa.edu>. - - 2.55 Apr 25, 1999 - Jens Axboe <axboe@image.dk> - -- autoclose was mistakenly checked against CDC_OPEN_TRAY instead of - CDC_CLOSE_TRAY. - -- proc info didn't mask against capabilities mask. - - 3.00 Aug 5, 1999 - Jens Axboe <axboe@image.dk> - -- Unified audio ioctl handling across CD-ROM drivers. A lot of the - code was duplicated before. Drives that support the generic packet - interface are now being fed packets from here instead. - -- First attempt at adding support for MMC2 commands - for DVD and - CD-R(W) drives. Only the DVD parts are in now - the interface used is - the same as for the audio ioctls. - -- ioctl cleanups. if a drive couldn't play audio, it didn't get - a change to perform device specific ioctls as well. - -- Defined CDROM_CAN(CDC_XXX) for checking the capabilities. - -- Put in sysctl files for autoclose, autoeject, check_media, debug, - and lock. - -- /proc/sys/dev/cdrom/info has been updated to also contain info about - CD-Rx and DVD capabilities. - -- Now default to checking media type. - -- CDROM_SEND_PACKET ioctl added. The infrastructure was in place for - doing this anyway, with the generic_packet addition. - - 3.01 Aug 6, 1999 - Jens Axboe <axboe@image.dk> - -- Fix up the sysctl handling so that the option flags get set - correctly. - -- Fix up ioctl handling so the device specific ones actually get - called :). - - 3.02 Aug 8, 1999 - Jens Axboe <axboe@image.dk> - -- Fixed volume control on SCSI drives (or others with longer audio - page). - -- Fixed a couple of DVD minors. Thanks to Andrew T. Veliath - <andrewtv@usa.net> for telling me and for having defined the various - DVD structures and ioctls in the first place! He designed the original - DVD patches for ide-cd and while I rearranged and unified them, the - interface is still the same. - - 3.03 Sep 1, 1999 - Jens Axboe <axboe@image.dk> - -- Moved the rest of the audio ioctls from the CD-ROM drivers here. Only - CDROMREADTOCENTRY and CDROMREADTOCHDR are left. - -- Moved the CDROMREADxxx ioctls in here. - -- Defined the cdrom_get_last_written and cdrom_get_next_block as ioctls - and exported functions. - -- Erik Andersen <andersen@xmission.com> modified all SCMD_ commands - to now read GPCMD_ for the new generic packet interface. All low level - drivers are updated as well. - -- Various other cleanups. - - 3.04 Sep 12, 1999 - Jens Axboe <axboe@image.dk> - -- Fixed a couple of possible memory leaks (if an operation failed and - we didn't free the buffer before returning the error). - -- Integrated Uniform CD Changer handling from Richard Sharman - <rsharman@pobox.com>. - -- Defined CD_DVD and CD_CHANGER log levels. - -- Fixed the CDROMREADxxx ioctls. - -- CDROMPLAYTRKIND uses the GPCMD_PLAY_AUDIO_MSF command - too few - drives supported it. We lose the index part, however. - -- Small modifications to accommodate opens of /dev/hdc1, required - for ide-cd to handle multisession discs. - -- Export cdrom_mode_sense and cdrom_mode_select. - -- init_cdrom_command() for setting up a cgc command. - - 3.05 Oct 24, 1999 - Jens Axboe <axboe@image.dk> - -- Changed the interface for CDROM_SEND_PACKET. Before it was virtually - impossible to send the drive data in a sensible way. - -- Lowered stack usage in mmc_ioctl(), dvd_read_disckey(), and - dvd_read_manufact. - -- Added setup of write mode for packet writing. - -- Fixed CDDA ripping with cdda2wav - accept much larger requests of - number of frames and split the reads in blocks of 8. - - 3.06 Dec 13, 1999 - Jens Axboe <axboe@image.dk> - -- Added support for changing the region of DVD drives. - -- Added sense data to generic command. - - 3.07 Feb 2, 2000 - Jens Axboe <axboe@suse.de> - -- Do same "read header length" trick in cdrom_get_disc_info() as - we do in cdrom_get_track_info() -- some drive don't obey specs and - fail if they can't supply the full Mt Fuji size table. - -- Deleted stuff related to setting up write modes. It has a different - home now. - -- Clear header length in mode_select unconditionally. - -- Removed the register_disk() that was added, not needed here. - - 3.08 May 1, 2000 - Jens Axboe <axboe@suse.de> - -- Fix direction flag in setup_send_key and setup_report_key. This - gave some SCSI adapters problems. - -- Always return -EROFS for write opens - -- Convert to module_init/module_exit style init and remove some - of the #ifdef MODULE stuff - -- Fix several dvd errors - DVD_LU_SEND_ASF should pass agid, - DVD_HOST_SEND_RPC_STATE did not set buffer size in cdb, and - dvd_do_auth passed uninitialized data to drive because init_cdrom_command - did not clear a 0 sized buffer. - - 3.09 May 12, 2000 - Jens Axboe <axboe@suse.de> - -- Fix Video-CD on SCSI drives that don't support READ_CD command. In - that case switch block size and issue plain READ_10 again, then switch - back. - - 3.10 Jun 10, 2000 - Jens Axboe <axboe@suse.de> - -- Fix volume control on CD's - old SCSI-II drives now use their own - code, as doing MODE6 stuff in here is really not my intention. - -- Use READ_DISC_INFO for more reliable end-of-disc. - - 3.11 Jun 12, 2000 - Jens Axboe <axboe@suse.de> - -- Fix bug in getting rpc phase 2 region info. - -- Reinstate "correct" CDROMPLAYTRKIND - - 3.12 Oct 18, 2000 - Jens Axboe <axboe@suse.de> - -- Use quiet bit on packet commands not known to work - - 3.20 Dec 17, 2003 - Jens Axboe <axboe@suse.de> - -- Various fixes and lots of cleanups not listed :-) - -- Locking fixes - -- Mt Rainier support - -- DVD-RAM write open fixes - - Nov 5 2001, Aug 8 2002. Modified by Andy Polyakov - <appro@fy.chalmers.se> to support MMC-3 compliant DVD+RW units. - - Modified by Nigel Kukard <nkukard@lbsd.net> - support DVD+RW - 2.4.x patch by Andy Polyakov <appro@fy.chalmers.se> - --------------------------------------------------------------------------*/ - -#define REVISION "Revision: 3.20" -#define VERSION "Id: cdrom.c 3.20 2003/12/17" - -/* I use an error-log mask to give fine grain control over the type of - messages dumped to the system logs. The available masks include: */ -#define CD_NOTHING 0x0 -#define CD_WARNING 0x1 -#define CD_REG_UNREG 0x2 -#define CD_DO_IOCTL 0x4 -#define CD_OPEN 0x8 -#define CD_CLOSE 0x10 -#define CD_COUNT_TRACKS 0x20 -#define CD_CHANGER 0x40 -#define CD_DVD 0x80 - -/* Define this to remove _all_ the debugging messages */ -/* #define ERRLOGMASK CD_NOTHING */ -#define ERRLOGMASK CD_WARNING -/* #define ERRLOGMASK (CD_WARNING|CD_OPEN|CD_COUNT_TRACKS|CD_CLOSE) */ -/* #define ERRLOGMASK (CD_WARNING|CD_REG_UNREG|CD_DO_IOCTL|CD_OPEN|CD_CLOSE|CD_COUNT_TRACKS) */ - -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/buffer_head.h> -#include <linux/major.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/cdrom.h> -#include <linux/sysctl.h> -#include <linux/proc_fs.h> -#include <linux/blkpg.h> -#include <linux/init.h> -#include <linux/fcntl.h> -#include <linux/blkdev.h> -#include <linux/times.h> - -#include <asm/uaccess.h> - -/* used to tell the module to turn on full debugging messages */ -static int debug; -/* used to keep tray locked at all times */ -static int keeplocked; -/* default compatibility mode */ -static int autoclose=1; -static int autoeject; -static int lockdoor = 1; -/* will we ever get to use this... sigh. */ -static int check_media_type; -/* automatically restart mrw format */ -static int mrw_format_restart = 1; -module_param(debug, bool, 0); -module_param(autoclose, bool, 0); -module_param(autoeject, bool, 0); -module_param(lockdoor, bool, 0); -module_param(check_media_type, bool, 0); -module_param(mrw_format_restart, bool, 0); - -static DEFINE_MUTEX(cdrom_mutex); - -static const char *mrw_format_status[] = { - "not mrw", - "bgformat inactive", - "bgformat active", - "mrw complete", -}; - -static const char *mrw_address_space[] = { "DMA", "GAA" }; - -#if (ERRLOGMASK!=CD_NOTHING) -#define cdinfo(type, fmt, args...) \ - if ((ERRLOGMASK & type) || debug==1 ) \ - printk(KERN_INFO "cdrom: " fmt, ## args) -#else -#define cdinfo(type, fmt, args...) -#endif - -/* These are used to simplify getting data in from and back to user land */ -#define IOCTL_IN(arg, type, in) \ - if (copy_from_user(&(in), (type __user *) (arg), sizeof (in))) \ - return -EFAULT; - -#define IOCTL_OUT(arg, type, out) \ - if (copy_to_user((type __user *) (arg), &(out), sizeof (out))) \ - return -EFAULT; - -/* The (cdo->capability & ~cdi->mask & CDC_XXX) construct was used in - a lot of places. This macro makes the code more clear. */ -#define CDROM_CAN(type) (cdi->ops->capability & ~cdi->mask & (type)) - -/* used in the audio ioctls */ -#define CHECKAUDIO if ((ret=check_for_audio_disc(cdi, cdo))) return ret - -/* - * Another popular OS uses 7 seconds as the hard timeout for default - * commands, so it is a good choice for us as well. - */ -#define CDROM_DEF_TIMEOUT (7 * HZ) - -/* Not-exported routines. */ -static int open_for_data(struct cdrom_device_info * cdi); -static int check_for_audio_disc(struct cdrom_device_info * cdi, - struct cdrom_device_ops * cdo); -static void sanitize_format(union cdrom_addr *addr, - u_char * curr, u_char requested); -static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, - unsigned long arg); - -int cdrom_get_last_written(struct cdrom_device_info *, long *); -static int cdrom_get_next_writable(struct cdrom_device_info *, long *); -static void cdrom_count_tracks(struct cdrom_device_info *, tracktype*); - -static int cdrom_mrw_exit(struct cdrom_device_info *cdi); - -static int cdrom_get_disc_info(struct cdrom_device_info *cdi, disc_information *di); - -static void cdrom_sysctl_register(void); - -static LIST_HEAD(cdrom_list); - -static int cdrom_dummy_generic_packet(struct cdrom_device_info *cdi, - struct packet_command *cgc) -{ - if (cgc->sense) { - cgc->sense->sense_key = 0x05; - cgc->sense->asc = 0x20; - cgc->sense->ascq = 0x00; - } - - cgc->stat = -EIO; - return -EIO; -} - -/* This macro makes sure we don't have to check on cdrom_device_ops - * existence in the run-time routines below. Change_capability is a - * hack to have the capability flags defined const, while we can still - * change it here without gcc complaining at every line. - */ -#define ENSURE(call, bits) if (cdo->call == NULL) *change_capability &= ~(bits) - -int register_cdrom(struct cdrom_device_info *cdi) -{ - static char banner_printed; - struct cdrom_device_ops *cdo = cdi->ops; - int *change_capability = (int *)&cdo->capability; /* hack */ - - cdinfo(CD_OPEN, "entering register_cdrom\n"); - - if (cdo->open == NULL || cdo->release == NULL) - return -EINVAL; - if (!banner_printed) { - printk(KERN_INFO "Uniform CD-ROM driver " REVISION "\n"); - banner_printed = 1; - cdrom_sysctl_register(); - } - - ENSURE(drive_status, CDC_DRIVE_STATUS ); - ENSURE(media_changed, CDC_MEDIA_CHANGED); - ENSURE(tray_move, CDC_CLOSE_TRAY | CDC_OPEN_TRAY); - ENSURE(lock_door, CDC_LOCK); - ENSURE(select_speed, CDC_SELECT_SPEED); - ENSURE(get_last_session, CDC_MULTI_SESSION); - ENSURE(get_mcn, CDC_MCN); - ENSURE(reset, CDC_RESET); - ENSURE(generic_packet, CDC_GENERIC_PACKET); - cdi->mc_flags = 0; - cdo->n_minors = 0; - cdi->options = CDO_USE_FFLAGS; - - if (autoclose==1 && CDROM_CAN(CDC_CLOSE_TRAY)) - cdi->options |= (int) CDO_AUTO_CLOSE; - if (autoeject==1 && CDROM_CAN(CDC_OPEN_TRAY)) - cdi->options |= (int) CDO_AUTO_EJECT; - if (lockdoor==1) - cdi->options |= (int) CDO_LOCK; - if (check_media_type==1) - cdi->options |= (int) CDO_CHECK_TYPE; - - if (CDROM_CAN(CDC_MRW_W)) - cdi->exit = cdrom_mrw_exit; - - if (cdi->disk) - cdi->cdda_method = CDDA_BPC_FULL; - else - cdi->cdda_method = CDDA_OLD; - - if (!cdo->generic_packet) - cdo->generic_packet = cdrom_dummy_generic_packet; - - cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name); - mutex_lock(&cdrom_mutex); - list_add(&cdi->list, &cdrom_list); - mutex_unlock(&cdrom_mutex); - return 0; -} -#undef ENSURE - -void unregister_cdrom(struct cdrom_device_info *cdi) -{ - cdinfo(CD_OPEN, "entering unregister_cdrom\n"); - - mutex_lock(&cdrom_mutex); - list_del(&cdi->list); - mutex_unlock(&cdrom_mutex); - - if (cdi->exit) - cdi->exit(cdi); - - cdi->ops->n_minors--; - cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name); -} - -int cdrom_get_media_event(struct cdrom_device_info *cdi, - struct media_event_desc *med) -{ - struct packet_command cgc; - unsigned char buffer[8]; - struct event_header *eh = (struct event_header *) buffer; - - init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ); - cgc.cmd[0] = GPCMD_GET_EVENT_STATUS_NOTIFICATION; - cgc.cmd[1] = 1; /* IMMED */ - cgc.cmd[4] = 1 << 4; /* media event */ - cgc.cmd[8] = sizeof(buffer); - cgc.quiet = 1; - - if (cdi->ops->generic_packet(cdi, &cgc)) - return 1; - - if (be16_to_cpu(eh->data_len) < sizeof(*med)) - return 1; - - if (eh->nea || eh->notification_class != 0x4) - return 1; - - memcpy(med, &buffer[sizeof(*eh)], sizeof(*med)); - return 0; -} - -/* - * the first prototypes used 0x2c as the page code for the mrw mode page, - * subsequently this was changed to 0x03. probe the one used by this drive - */ -static int cdrom_mrw_probe_pc(struct cdrom_device_info *cdi) -{ - struct packet_command cgc; - char buffer[16]; - - init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ); - - cgc.timeout = HZ; - cgc.quiet = 1; - - if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC, 0)) { - cdi->mrw_mode_page = MRW_MODE_PC; - return 0; - } else if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC_PRE1, 0)) { - cdi->mrw_mode_page = MRW_MODE_PC_PRE1; - return 0; - } - - return 1; -} - -static int cdrom_is_mrw(struct cdrom_device_info *cdi, int *write) -{ - struct packet_command cgc; - struct mrw_feature_desc *mfd; - unsigned char buffer[16]; - int ret; - - *write = 0; - - init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ); - - cgc.cmd[0] = GPCMD_GET_CONFIGURATION; - cgc.cmd[3] = CDF_MRW; - cgc.cmd[8] = sizeof(buffer); - cgc.quiet = 1; - - if ((ret = cdi->ops->generic_packet(cdi, &cgc))) - return ret; - - mfd = (struct mrw_feature_desc *)&buffer[sizeof(struct feature_header)]; - if (be16_to_cpu(mfd->feature_code) != CDF_MRW) - return 1; - *write = mfd->write; - - if ((ret = cdrom_mrw_probe_pc(cdi))) { - *write = 0; - return ret; - } - - return 0; -} - -static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont) -{ - struct packet_command cgc; - unsigned char buffer[12]; - int ret; - - printk(KERN_INFO "cdrom: %sstarting format\n", cont ? "Re" : ""); - - /* - * FmtData bit set (bit 4), format type is 1 - */ - init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_WRITE); - cgc.cmd[0] = GPCMD_FORMAT_UNIT; - cgc.cmd[1] = (1 << 4) | 1; - - cgc.timeout = 5 * 60 * HZ; - - /* - * 4 byte format list header, 8 byte format list descriptor - */ - buffer[1] = 1 << 1; - buffer[3] = 8; - - /* - * nr_blocks field - */ - buffer[4] = 0xff; - buffer[5] = 0xff; - buffer[6] = 0xff; - buffer[7] = 0xff; - - buffer[8] = 0x24 << 2; - buffer[11] = cont; - - ret = cdi->ops->generic_packet(cdi, &cgc); - if (ret) - printk(KERN_INFO "cdrom: bgformat failed\n"); - - return ret; -} - -static int cdrom_mrw_bgformat_susp(struct cdrom_device_info *cdi, int immed) -{ - struct packet_command cgc; - - init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); - cgc.cmd[0] = GPCMD_CLOSE_TRACK; - - /* - * Session = 1, Track = 0 - */ - cgc.cmd[1] = !!immed; - cgc.cmd[2] = 1 << 1; - - cgc.timeout = 5 * 60 * HZ; - - return cdi->ops->generic_packet(cdi, &cgc); -} - -static int cdrom_flush_cache(struct cdrom_device_info *cdi) -{ - struct packet_command cgc; - - init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); - cgc.cmd[0] = GPCMD_FLUSH_CACHE; - - cgc.timeout = 5 * 60 * HZ; - - return cdi->ops->generic_packet(cdi, &cgc); -} - -static int cdrom_mrw_exit(struct cdrom_device_info *cdi) -{ - disc_information di; - int ret; - - ret = cdrom_get_disc_info(cdi, &di); - if (ret < 0 || ret < (int)offsetof(typeof(di),disc_type)) - return 1; - - ret = 0; - if (di.mrw_status == CDM_MRW_BGFORMAT_ACTIVE) { - printk(KERN_INFO "cdrom: issuing MRW back ground " - "format suspend\n"); - ret = cdrom_mrw_bgformat_susp(cdi, 0); - } - - if (!ret && cdi->media_written) - ret = cdrom_flush_cache(cdi); - - return ret; -} - -static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space) -{ - struct packet_command cgc; - struct mode_page_header *mph; - char buffer[16]; - int ret, offset, size; - - init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ); - - cgc.buffer = buffer; - cgc.buflen = sizeof(buffer); - - if ((ret = cdrom_mode_sense(cdi, &cgc, cdi->mrw_mode_page, 0))) - return ret; - - mph = (struct mode_page_header *) buffer; - offset = be16_to_cpu(mph->desc_length); - size = be16_to_cpu(mph->mode_data_length) + 2; - - buffer[offset + 3] = space; - cgc.buflen = size; - - if ((ret = cdrom_mode_select(cdi, &cgc))) - return ret; - - printk(KERN_INFO "cdrom: %s: mrw address space %s selected\n", cdi->name, mrw_address_space[space]); - return 0; -} - -static int cdrom_get_random_writable(struct cdrom_device_info *cdi, - struct rwrt_feature_desc *rfd) -{ - struct packet_command cgc; - char buffer[24]; - int ret; - - init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ); - - cgc.cmd[0] = GPCMD_GET_CONFIGURATION; /* often 0x46 */ - cgc.cmd[3] = CDF_RWRT; /* often 0x0020 */ - cgc.cmd[8] = sizeof(buffer); /* often 0x18 */ - cgc.quiet = 1; - - if ((ret = cdi->ops->generic_packet(cdi, &cgc))) - return ret; - - memcpy(rfd, &buffer[sizeof(struct feature_header)], sizeof (*rfd)); - return 0; -} - -static int cdrom_has_defect_mgt(struct cdrom_device_info *cdi) -{ - struct packet_command cgc; - char buffer[16]; - __be16 *feature_code; - int ret; - - init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ); - - cgc.cmd[0] = GPCMD_GET_CONFIGURATION; - cgc.cmd[3] = CDF_HWDM; - cgc.cmd[8] = sizeof(buffer); - cgc.quiet = 1; - - if ((ret = cdi->ops->generic_packet(cdi, &cgc))) - return ret; - - feature_code = (__be16 *) &buffer[sizeof(struct feature_header)]; - if (be16_to_cpu(*feature_code) == CDF_HWDM) - return 0; - - return 1; -} - - -static int cdrom_is_random_writable(struct cdrom_device_info *cdi, int *write) -{ - struct rwrt_feature_desc rfd; - int ret; - - *write = 0; - - if ((ret = cdrom_get_random_writable(cdi, &rfd))) - return ret; - - if (CDF_RWRT == be16_to_cpu(rfd.feature_code)) - *write = 1; - - return 0; -} - -static int cdrom_media_erasable(struct cdrom_device_info *cdi) -{ - disc_information di; - int ret; - - ret = cdrom_get_disc_info(cdi, &di); - if (ret < 0 || ret < offsetof(typeof(di), n_first_track)) - return -1; - - return di.erasable; -} - -/* - * FIXME: check RO bit - */ -static int cdrom_dvdram_open_write(struct cdrom_device_info *cdi) -{ - int ret = cdrom_media_erasable(cdi); - - /* - * allow writable open if media info read worked and media is - * erasable, _or_ if it fails since not all drives support it - */ - if (!ret) - return 1; - - return 0; -} - -static int cdrom_mrw_open_write(struct cdrom_device_info *cdi) -{ - disc_information di; - int ret; - - /* - * always reset to DMA lba space on open - */ - if (cdrom_mrw_set_lba_space(cdi, MRW_LBA_DMA)) { - printk(KERN_ERR "cdrom: failed setting lba address space\n"); - return 1; - } - - ret = cdrom_get_disc_info(cdi, &di); - if (ret < 0 || ret < offsetof(typeof(di),disc_type)) - return 1; - - if (!di.erasable) - return 1; - - /* - * mrw_status - * 0 - not MRW formatted - * 1 - MRW bgformat started, but not running or complete - * 2 - MRW bgformat in progress - * 3 - MRW formatting complete - */ - ret = 0; - printk(KERN_INFO "cdrom open: mrw_status '%s'\n", - mrw_format_status[di.mrw_status]); - if (!di.mrw_status) - ret = 1; - else if (di.mrw_status == CDM_MRW_BGFORMAT_INACTIVE && - mrw_format_restart) - ret = cdrom_mrw_bgformat(cdi, 1); - - return ret; -} - -static int mo_open_write(struct cdrom_device_info *cdi) -{ - struct packet_command cgc; - char buffer[255]; - int ret; - - init_cdrom_command(&cgc, &buffer, 4, CGC_DATA_READ); - cgc.quiet = 1; - - /* - * obtain write protect information as per - * drivers/scsi/sd.c:sd_read_write_protect_flag - */ - - ret = cdrom_mode_sense(cdi, &cgc, GPMODE_ALL_PAGES, 0); - if (ret) - ret = cdrom_mode_sense(cdi, &cgc, GPMODE_VENDOR_PAGE, 0); - if (ret) { - cgc.buflen = 255; - ret = cdrom_mode_sense(cdi, &cgc, GPMODE_ALL_PAGES, 0); - } - - /* drive gave us no info, let the user go ahead */ - if (ret) - return 0; - - return buffer[3] & 0x80; -} - -static int cdrom_ram_open_write(struct cdrom_device_info *cdi) -{ - struct rwrt_feature_desc rfd; - int ret; - - if ((ret = cdrom_has_defect_mgt(cdi))) - return ret; - - if ((ret = cdrom_get_random_writable(cdi, &rfd))) - return ret; - else if (CDF_RWRT == be16_to_cpu(rfd.feature_code)) - ret = !rfd.curr; - - cdinfo(CD_OPEN, "can open for random write\n"); - return ret; -} - -static void cdrom_mmc3_profile(struct cdrom_device_info *cdi) -{ - struct packet_command cgc; - char buffer[32]; - int ret, mmc3_profile; - - init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ); - - cgc.cmd[0] = GPCMD_GET_CONFIGURATION; - cgc.cmd[1] = 0; - cgc.cmd[2] = cgc.cmd[3] = 0; /* Starting Feature Number */ - cgc.cmd[8] = sizeof(buffer); /* Allocation Length */ - cgc.quiet = 1; - - if ((ret = cdi->ops->generic_packet(cdi, &cgc))) - mmc3_profile = 0xffff; - else - mmc3_profile = (buffer[6] << 8) | buffer[7]; - - cdi->mmc3_profile = mmc3_profile; -} - -static int cdrom_is_dvd_rw(struct cdrom_device_info *cdi) -{ - switch (cdi->mmc3_profile) { - case 0x12: /* DVD-RAM */ - case 0x1A: /* DVD+RW */ - return 0; - default: - return 1; - } -} - -/* - * returns 0 for ok to open write, non-0 to disallow - */ -static int cdrom_open_write(struct cdrom_device_info *cdi) -{ - int mrw, mrw_write, ram_write; - int ret = 1; - - mrw = 0; - if (!cdrom_is_mrw(cdi, &mrw_write)) - mrw = 1; - - if (CDROM_CAN(CDC_MO_DRIVE)) - ram_write = 1; - else - (void) cdrom_is_random_writable(cdi, &ram_write); - - if (mrw) - cdi->mask &= ~CDC_MRW; - else - cdi->mask |= CDC_MRW; - - if (mrw_write) - cdi->mask &= ~CDC_MRW_W; - else - cdi->mask |= CDC_MRW_W; - - if (ram_write) - cdi->mask &= ~CDC_RAM; - else - cdi->mask |= CDC_RAM; - - if (CDROM_CAN(CDC_MRW_W)) - ret = cdrom_mrw_open_write(cdi); - else if (CDROM_CAN(CDC_DVD_RAM)) - ret = cdrom_dvdram_open_write(cdi); - else if (CDROM_CAN(CDC_RAM) && - !CDROM_CAN(CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_MRW|CDC_MO_DRIVE)) - ret = cdrom_ram_open_write(cdi); - else if (CDROM_CAN(CDC_MO_DRIVE)) - ret = mo_open_write(cdi); - else if (!cdrom_is_dvd_rw(cdi)) - ret = 0; - - return ret; -} - -static void cdrom_dvd_rw_close_write(struct cdrom_device_info *cdi) -{ - struct packet_command cgc; - - if (cdi->mmc3_profile != 0x1a) { - cdinfo(CD_CLOSE, "%s: No DVD+RW\n", cdi->name); - return; - } - - if (!cdi->media_written) { - cdinfo(CD_CLOSE, "%s: DVD+RW media clean\n", cdi->name); - return; - } - - printk(KERN_INFO "cdrom: %s: dirty DVD+RW media, \"finalizing\"\n", - cdi->name); - - init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); - cgc.cmd[0] = GPCMD_FLUSH_CACHE; - cgc.timeout = 30*HZ; - cdi->ops->generic_packet(cdi, &cgc); - - init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); - cgc.cmd[0] = GPCMD_CLOSE_TRACK; - cgc.timeout = 3000*HZ; - cgc.quiet = 1; - cdi->ops->generic_packet(cdi, &cgc); - - init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); - cgc.cmd[0] = GPCMD_CLOSE_TRACK; - cgc.cmd[2] = 2; /* Close session */ - cgc.quiet = 1; - cgc.timeout = 3000*HZ; - cdi->ops->generic_packet(cdi, &cgc); - - cdi->media_written = 0; -} - -static int cdrom_close_write(struct cdrom_device_info *cdi) -{ -#if 0 - return cdrom_flush_cache(cdi); -#else - return 0; -#endif -} - -/* We use the open-option O_NONBLOCK to indicate that the - * purpose of opening is only for subsequent ioctl() calls; no device - * integrity checks are performed. - * - * We hope that all cd-player programs will adopt this convention. It - * is in their own interest: device control becomes a lot easier - * this way. - */ -int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, fmode_t mode) -{ - int ret; - - cdinfo(CD_OPEN, "entering cdrom_open\n"); - - /* if this was a O_NONBLOCK open and we should honor the flags, - * do a quick open without drive/disc integrity checks. */ - cdi->use_count++; - if ((mode & FMODE_NDELAY) && (cdi->options & CDO_USE_FFLAGS)) { - ret = cdi->ops->open(cdi, 1); - } else { - ret = open_for_data(cdi); - if (ret) - goto err; - cdrom_mmc3_profile(cdi); - if (mode & FMODE_WRITE) { - ret = -EROFS; - if (cdrom_open_write(cdi)) - goto err_release; - if (!CDROM_CAN(CDC_RAM)) - goto err_release; - ret = 0; - cdi->media_written = 0; - } - } - - if (ret) - goto err; - - cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n", - cdi->name, cdi->use_count); - /* Do this on open. Don't wait for mount, because they might - not be mounting, but opening with O_NONBLOCK */ - check_disk_change(bdev); - return 0; -err_release: - if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) { - cdi->ops->lock_door(cdi, 0); - cdinfo(CD_OPEN, "door unlocked.\n"); - } - cdi->ops->release(cdi); -err: - cdi->use_count--; - return ret; -} - -static -int open_for_data(struct cdrom_device_info * cdi) -{ - int ret; - struct cdrom_device_ops *cdo = cdi->ops; - tracktype tracks; - cdinfo(CD_OPEN, "entering open_for_data\n"); - /* Check if the driver can report drive status. If it can, we - can do clever things. If it can't, well, we at least tried! */ - if (cdo->drive_status != NULL) { - ret = cdo->drive_status(cdi, CDSL_CURRENT); - cdinfo(CD_OPEN, "drive_status=%d\n", ret); - if (ret == CDS_TRAY_OPEN) { - cdinfo(CD_OPEN, "the tray is open...\n"); - /* can/may i close it? */ - if (CDROM_CAN(CDC_CLOSE_TRAY) && - cdi->options & CDO_AUTO_CLOSE) { - cdinfo(CD_OPEN, "trying to close the tray.\n"); - ret=cdo->tray_move(cdi,0); - if (ret) { - cdinfo(CD_OPEN, "bummer. tried to close the tray but failed.\n"); - /* Ignore the error from the low - level driver. We don't care why it - couldn't close the tray. We only care - that there is no disc in the drive, - since that is the _REAL_ problem here.*/ - ret=-ENOMEDIUM; - goto clean_up_and_return; - } - } else { - cdinfo(CD_OPEN, "bummer. this drive can't close the tray.\n"); - ret=-ENOMEDIUM; - goto clean_up_and_return; - } - /* Ok, the door should be closed now.. Check again */ - ret = cdo->drive_status(cdi, CDSL_CURRENT); - if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) { - cdinfo(CD_OPEN, "bummer. the tray is still not closed.\n"); - cdinfo(CD_OPEN, "tray might not contain a medium.\n"); - ret=-ENOMEDIUM; - goto clean_up_and_return; - } - cdinfo(CD_OPEN, "the tray is now closed.\n"); - } - /* the door should be closed now, check for the disc */ - ret = cdo->drive_status(cdi, CDSL_CURRENT); - if (ret!=CDS_DISC_OK) { - ret = -ENOMEDIUM; - goto clean_up_and_return; - } - } - cdrom_count_tracks(cdi, &tracks); - if (tracks.error == CDS_NO_DISC) { - cdinfo(CD_OPEN, "bummer. no disc.\n"); - ret=-ENOMEDIUM; - goto clean_up_and_return; - } - /* CD-Players which don't use O_NONBLOCK, workman - * for example, need bit CDO_CHECK_TYPE cleared! */ - if (tracks.data==0) { - if (cdi->options & CDO_CHECK_TYPE) { - /* give people a warning shot, now that CDO_CHECK_TYPE - is the default case! */ - cdinfo(CD_OPEN, "bummer. wrong media type.\n"); - cdinfo(CD_WARNING, "pid %d must open device O_NONBLOCK!\n", - (unsigned int)task_pid_nr(current)); - ret=-EMEDIUMTYPE; - goto clean_up_and_return; - } - else { - cdinfo(CD_OPEN, "wrong media type, but CDO_CHECK_TYPE not set.\n"); - } - } - - cdinfo(CD_OPEN, "all seems well, opening the device.\n"); - - /* all seems well, we can open the device */ - ret = cdo->open(cdi, 0); /* open for data */ - cdinfo(CD_OPEN, "opening the device gave me %d.\n", ret); - /* After all this careful checking, we shouldn't have problems - opening the device, but we don't want the device locked if - this somehow fails... */ - if (ret) { - cdinfo(CD_OPEN, "open device failed.\n"); - goto clean_up_and_return; - } - if (CDROM_CAN(CDC_LOCK) && (cdi->options & CDO_LOCK)) { - cdo->lock_door(cdi, 1); - cdinfo(CD_OPEN, "door locked.\n"); - } - cdinfo(CD_OPEN, "device opened successfully.\n"); - return ret; - - /* Something failed. Try to unlock the drive, because some drivers - (notably ide-cd) lock the drive after every command. This produced - a nasty bug where after mount failed, the drive would remain locked! - This ensures that the drive gets unlocked after a mount fails. This - is a goto to avoid bloating the driver with redundant code. */ -clean_up_and_return: - cdinfo(CD_OPEN, "open failed.\n"); - if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) { - cdo->lock_door(cdi, 0); - cdinfo(CD_OPEN, "door unlocked.\n"); - } - return ret; -} - -/* This code is similar to that in open_for_data. The routine is called - whenever an audio play operation is requested. -*/ -static int check_for_audio_disc(struct cdrom_device_info * cdi, - struct cdrom_device_ops * cdo) -{ - int ret; - tracktype tracks; - cdinfo(CD_OPEN, "entering check_for_audio_disc\n"); - if (!(cdi->options & CDO_CHECK_TYPE)) - return 0; - if (cdo->drive_status != NULL) { - ret = cdo->drive_status(cdi, CDSL_CURRENT); - cdinfo(CD_OPEN, "drive_status=%d\n", ret); - if (ret == CDS_TRAY_OPEN) { - cdinfo(CD_OPEN, "the tray is open...\n"); - /* can/may i close it? */ - if (CDROM_CAN(CDC_CLOSE_TRAY) && - cdi->options & CDO_AUTO_CLOSE) { - cdinfo(CD_OPEN, "trying to close the tray.\n"); - ret=cdo->tray_move(cdi,0); - if (ret) { - cdinfo(CD_OPEN, "bummer. tried to close tray but failed.\n"); - /* Ignore the error from the low - level driver. We don't care why it - couldn't close the tray. We only care - that there is no disc in the drive, - since that is the _REAL_ problem here.*/ - return -ENOMEDIUM; - } - } else { - cdinfo(CD_OPEN, "bummer. this driver can't close the tray.\n"); - return -ENOMEDIUM; - } - /* Ok, the door should be closed now.. Check again */ - ret = cdo->drive_status(cdi, CDSL_CURRENT); - if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) { - cdinfo(CD_OPEN, "bummer. the tray is still not closed.\n"); - return -ENOMEDIUM; - } - if (ret!=CDS_DISC_OK) { - cdinfo(CD_OPEN, "bummer. disc isn't ready.\n"); - return -EIO; - } - cdinfo(CD_OPEN, "the tray is now closed.\n"); - } - } - cdrom_count_tracks(cdi, &tracks); - if (tracks.error) - return(tracks.error); - - if (tracks.audio==0) - return -EMEDIUMTYPE; - - return 0; -} - -void cdrom_release(struct cdrom_device_info *cdi, fmode_t mode) -{ - struct cdrom_device_ops *cdo = cdi->ops; - int opened_for_data; - - cdinfo(CD_CLOSE, "entering cdrom_release\n"); - - if (cdi->use_count > 0) - cdi->use_count--; - - if (cdi->use_count == 0) { - cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name); - cdrom_dvd_rw_close_write(cdi); - - if ((cdo->capability & CDC_LOCK) && !keeplocked) { - cdinfo(CD_CLOSE, "Unlocking door!\n"); - cdo->lock_door(cdi, 0); - } - } - - opened_for_data = !(cdi->options & CDO_USE_FFLAGS) || - !(mode & FMODE_NDELAY); - - /* - * flush cache on last write release - */ - if (CDROM_CAN(CDC_RAM) && !cdi->use_count && cdi->for_data) - cdrom_close_write(cdi); - - cdo->release(cdi); - if (cdi->use_count == 0) { /* last process that closes dev*/ - if (opened_for_data && - cdi->options & CDO_AUTO_EJECT && CDROM_CAN(CDC_OPEN_TRAY)) - cdo->tray_move(cdi, 1); - } -} - -static int cdrom_read_mech_status(struct cdrom_device_info *cdi, - struct cdrom_changer_info *buf) -{ - struct packet_command cgc; - struct cdrom_device_ops *cdo = cdi->ops; - int length; - - /* - * Sanyo changer isn't spec compliant (doesn't use regular change - * LOAD_UNLOAD command, and it doesn't implement the mech status - * command below - */ - if (cdi->sanyo_slot) { - buf->hdr.nslots = 3; - buf->hdr.curslot = cdi->sanyo_slot == 3 ? 0 : cdi->sanyo_slot; - for (length = 0; length < 3; length++) { - buf->slots[length].disc_present = 1; - buf->slots[length].change = 0; - } - return 0; - } - - length = sizeof(struct cdrom_mechstat_header) + - cdi->capacity * sizeof(struct cdrom_slot); - - init_cdrom_command(&cgc, buf, length, CGC_DATA_READ); - cgc.cmd[0] = GPCMD_MECHANISM_STATUS; - cgc.cmd[8] = (length >> 8) & 0xff; - cgc.cmd[9] = length & 0xff; - return cdo->generic_packet(cdi, &cgc); -} - -static int cdrom_slot_status(struct cdrom_device_info *cdi, int slot) -{ - struct cdrom_changer_info *info; - int ret; - - cdinfo(CD_CHANGER, "entering cdrom_slot_status()\n"); - if (cdi->sanyo_slot) - return CDS_NO_INFO; - - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - if ((ret = cdrom_read_mech_status(cdi, info))) - goto out_free; - - if (info->slots[slot].disc_present) - ret = CDS_DISC_OK; - else - ret = CDS_NO_DISC; - -out_free: - kfree(info); - return ret; -} - -/* Return the number of slots for an ATAPI/SCSI cdrom, - * return 1 if not a changer. - */ -int cdrom_number_of_slots(struct cdrom_device_info *cdi) -{ - int status; - int nslots = 1; - struct cdrom_changer_info *info; - - cdinfo(CD_CHANGER, "entering cdrom_number_of_slots()\n"); - /* cdrom_read_mech_status requires a valid value for capacity: */ - cdi->capacity = 0; - - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - if ((status = cdrom_read_mech_status(cdi, info)) == 0) - nslots = info->hdr.nslots; - - kfree(info); - return nslots; -} - - -/* If SLOT < 0, unload the current slot. Otherwise, try to load SLOT. */ -static int cdrom_load_unload(struct cdrom_device_info *cdi, int slot) -{ - struct packet_command cgc; - - cdinfo(CD_CHANGER, "entering cdrom_load_unload()\n"); - if (cdi->sanyo_slot && slot < 0) - return 0; - - init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); - cgc.cmd[0] = GPCMD_LOAD_UNLOAD; - cgc.cmd[4] = 2 + (slot >= 0); - cgc.cmd[8] = slot; - cgc.timeout = 60 * HZ; - - /* The Sanyo 3 CD changer uses byte 7 of the - GPCMD_TEST_UNIT_READY to command to switch CDs instead of - using the GPCMD_LOAD_UNLOAD opcode. */ - if (cdi->sanyo_slot && -1 < slot) { - cgc.cmd[0] = GPCMD_TEST_UNIT_READY; - cgc.cmd[7] = slot; - cgc.cmd[4] = cgc.cmd[8] = 0; - cdi->sanyo_slot = slot ? slot : 3; - } - - return cdi->ops->generic_packet(cdi, &cgc); -} - -static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot) -{ - struct cdrom_changer_info *info; - int curslot; - int ret; - - cdinfo(CD_CHANGER, "entering cdrom_select_disc()\n"); - if (!CDROM_CAN(CDC_SELECT_DISC)) - return -EDRIVE_CANT_DO_THIS; - - (void) cdi->ops->media_changed(cdi, slot); - - if (slot == CDSL_NONE) { - /* set media changed bits, on both queues */ - cdi->mc_flags = 0x3; - return cdrom_load_unload(cdi, -1); - } - - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - if ((ret = cdrom_read_mech_status(cdi, info))) { - kfree(info); - return ret; - } - - curslot = info->hdr.curslot; - kfree(info); - - if (cdi->use_count > 1 || keeplocked) { - if (slot == CDSL_CURRENT) { - return curslot; - } else { - return -EBUSY; - } - } - - /* Specifying CDSL_CURRENT will attempt to load the currnet slot, - which is useful if it had been previously unloaded. - Whether it can or not, it returns the current slot. - Similarly, if slot happens to be the current one, we still - try and load it. */ - if (slot == CDSL_CURRENT) - slot = curslot; - - /* set media changed bits on both queues */ - cdi->mc_flags = 0x3; - if ((ret = cdrom_load_unload(cdi, slot))) - return ret; - - return slot; -} - -/* We want to make media_changed accessible to the user through an - * ioctl. The main problem now is that we must double-buffer the - * low-level implementation, to assure that the VFS and the user both - * see a medium change once. - */ - -static -int media_changed(struct cdrom_device_info *cdi, int queue) -{ - unsigned int mask = (1 << (queue & 1)); - int ret = !!(cdi->mc_flags & mask); - - if (!CDROM_CAN(CDC_MEDIA_CHANGED)) - return ret; - /* changed since last call? */ - if (cdi->ops->media_changed(cdi, CDSL_CURRENT)) { - cdi->mc_flags = 0x3; /* set bit on both queues */ - ret |= 1; - cdi->media_written = 0; - } - cdi->mc_flags &= ~mask; /* clear bit */ - return ret; -} - -int cdrom_media_changed(struct cdrom_device_info *cdi) -{ - /* This talks to the VFS, which doesn't like errors - just 1 or 0. - * Returning "0" is always safe (media hasn't been changed). Do that - * if the low-level cdrom driver dosn't support media changed. */ - if (cdi == NULL || cdi->ops->media_changed == NULL) - return 0; - if (!CDROM_CAN(CDC_MEDIA_CHANGED)) - return 0; - return media_changed(cdi, 0); -} - -/* badly broken, I know. Is due for a fixup anytime. */ -static void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype* tracks) -{ - struct cdrom_tochdr header; - struct cdrom_tocentry entry; - int ret, i; - tracks->data=0; - tracks->audio=0; - tracks->cdi=0; - tracks->xa=0; - tracks->error=0; - cdinfo(CD_COUNT_TRACKS, "entering cdrom_count_tracks\n"); - /* Grab the TOC header so we can see how many tracks there are */ - if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header))) { - if (ret == -ENOMEDIUM) - tracks->error = CDS_NO_DISC; - else - tracks->error = CDS_NO_INFO; - return; - } - /* check what type of tracks are on this disc */ - entry.cdte_format = CDROM_MSF; - for (i = header.cdth_trk0; i <= header.cdth_trk1; i++) { - entry.cdte_track = i; - if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry)) { - tracks->error=CDS_NO_INFO; - return; - } - if (entry.cdte_ctrl & CDROM_DATA_TRACK) { - if (entry.cdte_format == 0x10) - tracks->cdi++; - else if (entry.cdte_format == 0x20) - tracks->xa++; - else - tracks->data++; - } else - tracks->audio++; - cdinfo(CD_COUNT_TRACKS, "track %d: format=%d, ctrl=%d\n", - i, entry.cdte_format, entry.cdte_ctrl); - } - cdinfo(CD_COUNT_TRACKS, "disc has %d tracks: %d=audio %d=data %d=Cd-I %d=XA\n", - header.cdth_trk1, tracks->audio, tracks->data, - tracks->cdi, tracks->xa); -} - -/* Requests to the low-level drivers will /always/ be done in the - following format convention: - - CDROM_LBA: all data-related requests. - CDROM_MSF: all audio-related requests. - - However, a low-level implementation is allowed to refuse this - request, and return information in its own favorite format. - - It doesn't make sense /at all/ to ask for a play_audio in LBA - format, or ask for multi-session info in MSF format. However, for - backward compatibility these format requests will be satisfied, but - the requests to the low-level drivers will be sanitized in the more - meaningful format indicated above. - */ - -static -void sanitize_format(union cdrom_addr *addr, - u_char * curr, u_char requested) -{ - if (*curr == requested) - return; /* nothing to be done! */ - if (requested == CDROM_LBA) { - addr->lba = (int) addr->msf.frame + - 75 * (addr->msf.second - 2 + 60 * addr->msf.minute); - } else { /* CDROM_MSF */ - int lba = addr->lba; - addr->msf.frame = lba % 75; - lba /= 75; - lba += 2; - addr->msf.second = lba % 60; - addr->msf.minute = lba / 60; - } - *curr = requested; -} - -void init_cdrom_command(struct packet_command *cgc, void *buf, int len, - int type) -{ - memset(cgc, 0, sizeof(struct packet_command)); - if (buf) - memset(buf, 0, len); - cgc->buffer = (char *) buf; - cgc->buflen = len; - cgc->data_direction = type; - cgc->timeout = CDROM_DEF_TIMEOUT; -} - -/* DVD handling */ - -#define copy_key(dest,src) memcpy((dest), (src), sizeof(dvd_key)) -#define copy_chal(dest,src) memcpy((dest), (src), sizeof(dvd_challenge)) - -static void setup_report_key(struct packet_command *cgc, unsigned agid, unsigned type) -{ - cgc->cmd[0] = GPCMD_REPORT_KEY; - cgc->cmd[10] = type | (agid << 6); - switch (type) { - case 0: case 8: case 5: { - cgc->buflen = 8; - break; - } - case 1: { - cgc->buflen = 16; - break; - } - case 2: case 4: { - cgc->buflen = 12; - break; - } - } - cgc->cmd[9] = cgc->buflen; - cgc->data_direction = CGC_DATA_READ; -} - -static void setup_send_key(struct packet_command *cgc, unsigned agid, unsigned type) -{ - cgc->cmd[0] = GPCMD_SEND_KEY; - cgc->cmd[10] = type | (agid << 6); - switch (type) { - case 1: { - cgc->buflen = 16; - break; - } - case 3: { - cgc->buflen = 12; - break; - } - case 6: { - cgc->buflen = 8; - break; - } - } - cgc->cmd[9] = cgc->buflen; - cgc->data_direction = CGC_DATA_WRITE; -} - -static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) -{ - int ret; - u_char buf[20]; - struct packet_command cgc; - struct cdrom_device_ops *cdo = cdi->ops; - rpc_state_t rpc_state; - - memset(buf, 0, sizeof(buf)); - init_cdrom_command(&cgc, buf, 0, CGC_DATA_READ); - - switch (ai->type) { - /* LU data send */ - case DVD_LU_SEND_AGID: - cdinfo(CD_DVD, "entering DVD_LU_SEND_AGID\n"); - cgc.quiet = 1; - setup_report_key(&cgc, ai->lsa.agid, 0); - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - ai->lsa.agid = buf[7] >> 6; - /* Returning data, let host change state */ - break; - - case DVD_LU_SEND_KEY1: - cdinfo(CD_DVD, "entering DVD_LU_SEND_KEY1\n"); - setup_report_key(&cgc, ai->lsk.agid, 2); - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - copy_key(ai->lsk.key, &buf[4]); - /* Returning data, let host change state */ - break; - - case DVD_LU_SEND_CHALLENGE: - cdinfo(CD_DVD, "entering DVD_LU_SEND_CHALLENGE\n"); - setup_report_key(&cgc, ai->lsc.agid, 1); - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - copy_chal(ai->lsc.chal, &buf[4]); - /* Returning data, let host change state */ - break; - - /* Post-auth key */ - case DVD_LU_SEND_TITLE_KEY: - cdinfo(CD_DVD, "entering DVD_LU_SEND_TITLE_KEY\n"); - cgc.quiet = 1; - setup_report_key(&cgc, ai->lstk.agid, 4); - cgc.cmd[5] = ai->lstk.lba; - cgc.cmd[4] = ai->lstk.lba >> 8; - cgc.cmd[3] = ai->lstk.lba >> 16; - cgc.cmd[2] = ai->lstk.lba >> 24; - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - ai->lstk.cpm = (buf[4] >> 7) & 1; - ai->lstk.cp_sec = (buf[4] >> 6) & 1; - ai->lstk.cgms = (buf[4] >> 4) & 3; - copy_key(ai->lstk.title_key, &buf[5]); - /* Returning data, let host change state */ - break; - - case DVD_LU_SEND_ASF: - cdinfo(CD_DVD, "entering DVD_LU_SEND_ASF\n"); - setup_report_key(&cgc, ai->lsasf.agid, 5); - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - ai->lsasf.asf = buf[7] & 1; - break; - - /* LU data receive (LU changes state) */ - case DVD_HOST_SEND_CHALLENGE: - cdinfo(CD_DVD, "entering DVD_HOST_SEND_CHALLENGE\n"); - setup_send_key(&cgc, ai->hsc.agid, 1); - buf[1] = 0xe; - copy_chal(&buf[4], ai->hsc.chal); - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - ai->type = DVD_LU_SEND_KEY1; - break; - - case DVD_HOST_SEND_KEY2: - cdinfo(CD_DVD, "entering DVD_HOST_SEND_KEY2\n"); - setup_send_key(&cgc, ai->hsk.agid, 3); - buf[1] = 0xa; - copy_key(&buf[4], ai->hsk.key); - - if ((ret = cdo->generic_packet(cdi, &cgc))) { - ai->type = DVD_AUTH_FAILURE; - return ret; - } - ai->type = DVD_AUTH_ESTABLISHED; - break; - - /* Misc */ - case DVD_INVALIDATE_AGID: - cgc.quiet = 1; - cdinfo(CD_DVD, "entering DVD_INVALIDATE_AGID\n"); - setup_report_key(&cgc, ai->lsa.agid, 0x3f); - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - break; - - /* Get region settings */ - case DVD_LU_SEND_RPC_STATE: - cdinfo(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n"); - setup_report_key(&cgc, 0, 8); - memset(&rpc_state, 0, sizeof(rpc_state_t)); - cgc.buffer = (char *) &rpc_state; - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - ai->lrpcs.type = rpc_state.type_code; - ai->lrpcs.vra = rpc_state.vra; - ai->lrpcs.ucca = rpc_state.ucca; - ai->lrpcs.region_mask = rpc_state.region_mask; - ai->lrpcs.rpc_scheme = rpc_state.rpc_scheme; - break; - - /* Set region settings */ - case DVD_HOST_SEND_RPC_STATE: - cdinfo(CD_DVD, "entering DVD_HOST_SEND_RPC_STATE\n"); - setup_send_key(&cgc, 0, 6); - buf[1] = 6; - buf[4] = ai->hrpcs.pdrc; - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - break; - - default: - cdinfo(CD_WARNING, "Invalid DVD key ioctl (%d)\n", ai->type); - return -ENOTTY; - } - - return 0; -} - -static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s, - struct packet_command *cgc) -{ - unsigned char buf[21], *base; - struct dvd_layer *layer; - struct cdrom_device_ops *cdo = cdi->ops; - int ret, layer_num = s->physical.layer_num; - - if (layer_num >= DVD_LAYERS) - return -EINVAL; - - init_cdrom_command(cgc, buf, sizeof(buf), CGC_DATA_READ); - cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE; - cgc->cmd[6] = layer_num; - cgc->cmd[7] = s->type; - cgc->cmd[9] = cgc->buflen & 0xff; - - /* - * refrain from reporting errors on non-existing layers (mainly) - */ - cgc->quiet = 1; - - ret = cdo->generic_packet(cdi, cgc); - if (ret) - return ret; - - base = &buf[4]; - layer = &s->physical.layer[layer_num]; - - /* - * place the data... really ugly, but at least we won't have to - * worry about endianess in userspace. - */ - memset(layer, 0, sizeof(*layer)); - layer->book_version = base[0] & 0xf; - layer->book_type = base[0] >> 4; - layer->min_rate = base[1] & 0xf; - layer->disc_size = base[1] >> 4; - layer->layer_type = base[2] & 0xf; - layer->track_path = (base[2] >> 4) & 1; - layer->nlayers = (base[2] >> 5) & 3; - layer->track_density = base[3] & 0xf; - layer->linear_density = base[3] >> 4; - layer->start_sector = base[5] << 16 | base[6] << 8 | base[7]; - layer->end_sector = base[9] << 16 | base[10] << 8 | base[11]; - layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15]; - layer->bca = base[16] >> 7; - - return 0; -} - -static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s, - struct packet_command *cgc) -{ - int ret; - u_char buf[8]; - struct cdrom_device_ops *cdo = cdi->ops; - - init_cdrom_command(cgc, buf, sizeof(buf), CGC_DATA_READ); - cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE; - cgc->cmd[6] = s->copyright.layer_num; - cgc->cmd[7] = s->type; - cgc->cmd[8] = cgc->buflen >> 8; - cgc->cmd[9] = cgc->buflen & 0xff; - - ret = cdo->generic_packet(cdi, cgc); - if (ret) - return ret; - - s->copyright.cpst = buf[4]; - s->copyright.rmi = buf[5]; - - return 0; -} - -static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s, - struct packet_command *cgc) -{ - int ret, size; - u_char *buf; - struct cdrom_device_ops *cdo = cdi->ops; - - size = sizeof(s->disckey.value) + 4; - - buf = kmalloc(size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - init_cdrom_command(cgc, buf, size, CGC_DATA_READ); - cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE; - cgc->cmd[7] = s->type; - cgc->cmd[8] = size >> 8; - cgc->cmd[9] = size & 0xff; - cgc->cmd[10] = s->disckey.agid << 6; - - ret = cdo->generic_packet(cdi, cgc); - if (!ret) - memcpy(s->disckey.value, &buf[4], sizeof(s->disckey.value)); - - kfree(buf); - return ret; -} - -static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s, - struct packet_command *cgc) -{ - int ret, size = 4 + 188; - u_char *buf; - struct cdrom_device_ops *cdo = cdi->ops; - - buf = kmalloc(size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - init_cdrom_command(cgc, buf, size, CGC_DATA_READ); - cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE; - cgc->cmd[7] = s->type; - cgc->cmd[9] = cgc->buflen & 0xff; - - ret = cdo->generic_packet(cdi, cgc); - if (ret) - goto out; - - s->bca.len = buf[0] << 8 | buf[1]; - if (s->bca.len < 12 || s->bca.len > 188) { - cdinfo(CD_WARNING, "Received invalid BCA length (%d)\n", s->bca.len); - ret = -EIO; - goto out; - } - memcpy(s->bca.value, &buf[4], s->bca.len); - ret = 0; -out: - kfree(buf); - return ret; -} - -static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s, - struct packet_command *cgc) -{ - int ret = 0, size; - u_char *buf; - struct cdrom_device_ops *cdo = cdi->ops; - - size = sizeof(s->manufact.value) + 4; - - buf = kmalloc(size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - init_cdrom_command(cgc, buf, size, CGC_DATA_READ); - cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE; - cgc->cmd[7] = s->type; - cgc->cmd[8] = size >> 8; - cgc->cmd[9] = size & 0xff; - - ret = cdo->generic_packet(cdi, cgc); - if (ret) - goto out; - - s->manufact.len = buf[0] << 8 | buf[1]; - if (s->manufact.len < 0 || s->manufact.len > 2048) { - cdinfo(CD_WARNING, "Received invalid manufacture info length" - " (%d)\n", s->manufact.len); - ret = -EIO; - } else { - memcpy(s->manufact.value, &buf[4], s->manufact.len); - } - -out: - kfree(buf); - return ret; -} - -static int dvd_read_struct(struct cdrom_device_info *cdi, dvd_struct *s, - struct packet_command *cgc) -{ - switch (s->type) { - case DVD_STRUCT_PHYSICAL: - return dvd_read_physical(cdi, s, cgc); - - case DVD_STRUCT_COPYRIGHT: - return dvd_read_copyright(cdi, s, cgc); - - case DVD_STRUCT_DISCKEY: - return dvd_read_disckey(cdi, s, cgc); - - case DVD_STRUCT_BCA: - return dvd_read_bca(cdi, s, cgc); - - case DVD_STRUCT_MANUFACT: - return dvd_read_manufact(cdi, s, cgc); - - default: - cdinfo(CD_WARNING, ": Invalid DVD structure read requested (%d)\n", - s->type); - return -EINVAL; - } -} - -int cdrom_mode_sense(struct cdrom_device_info *cdi, - struct packet_command *cgc, - int page_code, int page_control) -{ - struct cdrom_device_ops *cdo = cdi->ops; - - memset(cgc->cmd, 0, sizeof(cgc->cmd)); - - cgc->cmd[0] = GPCMD_MODE_SENSE_10; - cgc->cmd[2] = page_code | (page_control << 6); - cgc->cmd[7] = cgc->buflen >> 8; - cgc->cmd[8] = cgc->buflen & 0xff; - cgc->data_direction = CGC_DATA_READ; - return cdo->generic_packet(cdi, cgc); -} - -int cdrom_mode_select(struct cdrom_device_info *cdi, - struct packet_command *cgc) -{ - struct cdrom_device_ops *cdo = cdi->ops; - - memset(cgc->cmd, 0, sizeof(cgc->cmd)); - memset(cgc->buffer, 0, 2); - cgc->cmd[0] = GPCMD_MODE_SELECT_10; - cgc->cmd[1] = 0x10; /* PF */ - cgc->cmd[7] = cgc->buflen >> 8; - cgc->cmd[8] = cgc->buflen & 0xff; - cgc->data_direction = CGC_DATA_WRITE; - return cdo->generic_packet(cdi, cgc); -} - -static int cdrom_read_subchannel(struct cdrom_device_info *cdi, - struct cdrom_subchnl *subchnl, int mcn) -{ - struct cdrom_device_ops *cdo = cdi->ops; - struct packet_command cgc; - char buffer[32]; - int ret; - - init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ); - cgc.cmd[0] = GPCMD_READ_SUBCHANNEL; - cgc.cmd[1] = 2; /* MSF addressing */ - cgc.cmd[2] = 0x40; /* request subQ data */ - cgc.cmd[3] = mcn ? 2 : 1; - cgc.cmd[8] = 16; - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - subchnl->cdsc_audiostatus = cgc.buffer[1]; - subchnl->cdsc_format = CDROM_MSF; - subchnl->cdsc_ctrl = cgc.buffer[5] & 0xf; - subchnl->cdsc_trk = cgc.buffer[6]; - subchnl->cdsc_ind = cgc.buffer[7]; - - subchnl->cdsc_reladdr.msf.minute = cgc.buffer[13]; - subchnl->cdsc_reladdr.msf.second = cgc.buffer[14]; - subchnl->cdsc_reladdr.msf.frame = cgc.buffer[15]; - subchnl->cdsc_absaddr.msf.minute = cgc.buffer[9]; - subchnl->cdsc_absaddr.msf.second = cgc.buffer[10]; - subchnl->cdsc_absaddr.msf.frame = cgc.buffer[11]; - - return 0; -} - -/* - * Specific READ_10 interface - */ -static int cdrom_read_cd(struct cdrom_device_info *cdi, - struct packet_command *cgc, int lba, - int blocksize, int nblocks) -{ - struct cdrom_device_ops *cdo = cdi->ops; - - memset(&cgc->cmd, 0, sizeof(cgc->cmd)); - cgc->cmd[0] = GPCMD_READ_10; - cgc->cmd[2] = (lba >> 24) & 0xff; - cgc->cmd[3] = (lba >> 16) & 0xff; - cgc->cmd[4] = (lba >> 8) & 0xff; - cgc->cmd[5] = lba & 0xff; - cgc->cmd[6] = (nblocks >> 16) & 0xff; - cgc->cmd[7] = (nblocks >> 8) & 0xff; - cgc->cmd[8] = nblocks & 0xff; - cgc->buflen = blocksize * nblocks; - return cdo->generic_packet(cdi, cgc); -} - -/* very generic interface for reading the various types of blocks */ -static int cdrom_read_block(struct cdrom_device_info *cdi, - struct packet_command *cgc, - int lba, int nblocks, int format, int blksize) -{ - struct cdrom_device_ops *cdo = cdi->ops; - - memset(&cgc->cmd, 0, sizeof(cgc->cmd)); - cgc->cmd[0] = GPCMD_READ_CD; - /* expected sector size - cdda,mode1,etc. */ - cgc->cmd[1] = format << 2; - /* starting address */ - cgc->cmd[2] = (lba >> 24) & 0xff; - cgc->cmd[3] = (lba >> 16) & 0xff; - cgc->cmd[4] = (lba >> 8) & 0xff; - cgc->cmd[5] = lba & 0xff; - /* number of blocks */ - cgc->cmd[6] = (nblocks >> 16) & 0xff; - cgc->cmd[7] = (nblocks >> 8) & 0xff; - cgc->cmd[8] = nblocks & 0xff; - cgc->buflen = blksize * nblocks; - - /* set the header info returned */ - switch (blksize) { - case CD_FRAMESIZE_RAW0 : cgc->cmd[9] = 0x58; break; - case CD_FRAMESIZE_RAW1 : cgc->cmd[9] = 0x78; break; - case CD_FRAMESIZE_RAW : cgc->cmd[9] = 0xf8; break; - default : cgc->cmd[9] = 0x10; - } - - return cdo->generic_packet(cdi, cgc); -} - -static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf, - int lba, int nframes) -{ - struct packet_command cgc; - int ret = 0; - int nr; - - cdi->last_sense = 0; - - memset(&cgc, 0, sizeof(cgc)); - - /* - * start with will ra.nframes size, back down if alloc fails - */ - nr = nframes; - do { - cgc.buffer = kmalloc(CD_FRAMESIZE_RAW * nr, GFP_KERNEL); - if (cgc.buffer) - break; - - nr >>= 1; - } while (nr); - - if (!nr) - return -ENOMEM; - - if (!access_ok(VERIFY_WRITE, ubuf, nframes * CD_FRAMESIZE_RAW)) { - ret = -EFAULT; - goto out; - } - - cgc.data_direction = CGC_DATA_READ; - while (nframes > 0) { - if (nr > nframes) - nr = nframes; - - ret = cdrom_read_block(cdi, &cgc, lba, nr, 1, CD_FRAMESIZE_RAW); - if (ret) - break; - if (__copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) { - ret = -EFAULT; - break; - } - ubuf += CD_FRAMESIZE_RAW * nr; - nframes -= nr; - lba += nr; - } -out: - kfree(cgc.buffer); - return ret; -} - -static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, - int lba, int nframes) -{ - struct request_queue *q = cdi->disk->queue; - struct request *rq; - struct bio *bio; - unsigned int len; - int nr, ret = 0; - - if (!q) - return -ENXIO; - - cdi->last_sense = 0; - - while (nframes) { - nr = nframes; - if (cdi->cdda_method == CDDA_BPC_SINGLE) - nr = 1; - if (nr * CD_FRAMESIZE_RAW > (q->max_sectors << 9)) - nr = (q->max_sectors << 9) / CD_FRAMESIZE_RAW; - - len = nr * CD_FRAMESIZE_RAW; - - rq = blk_get_request(q, READ, GFP_KERNEL); - if (!rq) { - ret = -ENOMEM; - break; - } - - ret = blk_rq_map_user(q, rq, NULL, ubuf, len, GFP_KERNEL); - if (ret) { - blk_put_request(rq); - break; - } - - rq->cmd[0] = GPCMD_READ_CD; - rq->cmd[1] = 1 << 2; - rq->cmd[2] = (lba >> 24) & 0xff; - rq->cmd[3] = (lba >> 16) & 0xff; - rq->cmd[4] = (lba >> 8) & 0xff; - rq->cmd[5] = lba & 0xff; - rq->cmd[6] = (nr >> 16) & 0xff; - rq->cmd[7] = (nr >> 8) & 0xff; - rq->cmd[8] = nr & 0xff; - rq->cmd[9] = 0xf8; - - rq->cmd_len = 12; - rq->cmd_type = REQ_TYPE_BLOCK_PC; - rq->timeout = 60 * HZ; - bio = rq->bio; - - if (blk_execute_rq(q, cdi->disk, rq, 0)) { - struct request_sense *s = rq->sense; - ret = -EIO; - cdi->last_sense = s->sense_key; - } - - if (blk_rq_unmap_user(bio)) - ret = -EFAULT; - blk_put_request(rq); - - if (ret) - break; - - nframes -= nr; - lba += nr; - ubuf += len; - } - - return ret; -} - -static int cdrom_read_cdda(struct cdrom_device_info *cdi, __u8 __user *ubuf, - int lba, int nframes) -{ - int ret; - - if (cdi->cdda_method == CDDA_OLD) - return cdrom_read_cdda_old(cdi, ubuf, lba, nframes); - -retry: - /* - * for anything else than success and io error, we need to retry - */ - ret = cdrom_read_cdda_bpc(cdi, ubuf, lba, nframes); - if (!ret || ret != -EIO) - return ret; - - /* - * I've seen drives get sense 4/8/3 udma crc errors on multi - * frame dma, so drop to single frame dma if we need to - */ - if (cdi->cdda_method == CDDA_BPC_FULL && nframes > 1) { - printk("cdrom: dropping to single frame dma\n"); - cdi->cdda_method = CDDA_BPC_SINGLE; - goto retry; - } - - /* - * so we have an io error of some sort with multi frame dma. if the - * condition wasn't a hardware error - * problems, not for any error - */ - if (cdi->last_sense != 0x04 && cdi->last_sense != 0x0b) - return ret; - - printk("cdrom: dropping to old style cdda (sense=%x)\n", cdi->last_sense); - cdi->cdda_method = CDDA_OLD; - return cdrom_read_cdda_old(cdi, ubuf, lba, nframes); -} - -static int cdrom_ioctl_multisession(struct cdrom_device_info *cdi, - void __user *argp) -{ - struct cdrom_multisession ms_info; - u8 requested_format; - int ret; - - cdinfo(CD_DO_IOCTL, "entering CDROMMULTISESSION\n"); - - if (!(cdi->ops->capability & CDC_MULTI_SESSION)) - return -ENOSYS; - - if (copy_from_user(&ms_info, argp, sizeof(ms_info))) - return -EFAULT; - - requested_format = ms_info.addr_format; - if (requested_format != CDROM_MSF && requested_format != CDROM_LBA) - return -EINVAL; - ms_info.addr_format = CDROM_LBA; - - ret = cdi->ops->get_last_session(cdi, &ms_info); - if (ret) - return ret; - - sanitize_format(&ms_info.addr, &ms_info.addr_format, requested_format); - - if (copy_to_user(argp, &ms_info, sizeof(ms_info))) - return -EFAULT; - - cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION successful\n"); - return 0; -} - -static int cdrom_ioctl_eject(struct cdrom_device_info *cdi) -{ - cdinfo(CD_DO_IOCTL, "entering CDROMEJECT\n"); - - if (!CDROM_CAN(CDC_OPEN_TRAY)) - return -ENOSYS; - if (cdi->use_count != 1 || keeplocked) - return -EBUSY; - if (CDROM_CAN(CDC_LOCK)) { - int ret = cdi->ops->lock_door(cdi, 0); - if (ret) - return ret; - } - - return cdi->ops->tray_move(cdi, 1); -} - -static int cdrom_ioctl_closetray(struct cdrom_device_info *cdi) -{ - cdinfo(CD_DO_IOCTL, "entering CDROMCLOSETRAY\n"); - - if (!CDROM_CAN(CDC_CLOSE_TRAY)) - return -ENOSYS; - return cdi->ops->tray_move(cdi, 0); -} - -static int cdrom_ioctl_eject_sw(struct cdrom_device_info *cdi, - unsigned long arg) -{ - cdinfo(CD_DO_IOCTL, "entering CDROMEJECT_SW\n"); - - if (!CDROM_CAN(CDC_OPEN_TRAY)) - return -ENOSYS; - if (keeplocked) - return -EBUSY; - - cdi->options &= ~(CDO_AUTO_CLOSE | CDO_AUTO_EJECT); - if (arg) - cdi->options |= CDO_AUTO_CLOSE | CDO_AUTO_EJECT; - return 0; -} - -static int cdrom_ioctl_media_changed(struct cdrom_device_info *cdi, - unsigned long arg) -{ - struct cdrom_changer_info *info; - int ret; - - cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n"); - - if (!CDROM_CAN(CDC_MEDIA_CHANGED)) - return -ENOSYS; - - /* cannot select disc or select current disc */ - if (!CDROM_CAN(CDC_SELECT_DISC) || arg == CDSL_CURRENT) - return media_changed(cdi, 1); - - if ((unsigned int)arg >= cdi->capacity) - return -EINVAL; - - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - ret = cdrom_read_mech_status(cdi, info); - if (!ret) - ret = info->slots[arg].change; - kfree(info); - return ret; -} - -static int cdrom_ioctl_set_options(struct cdrom_device_info *cdi, - unsigned long arg) -{ - cdinfo(CD_DO_IOCTL, "entering CDROM_SET_OPTIONS\n"); - - /* - * Options need to be in sync with capability. - * Too late for that, so we have to check each one separately. - */ - switch (arg) { - case CDO_USE_FFLAGS: - case CDO_CHECK_TYPE: - break; - case CDO_LOCK: - if (!CDROM_CAN(CDC_LOCK)) - return -ENOSYS; - break; - case 0: - return cdi->options; - /* default is basically CDO_[AUTO_CLOSE|AUTO_EJECT] */ - default: - if (!CDROM_CAN(arg)) - return -ENOSYS; - } - cdi->options |= (int) arg; - return cdi->options; -} - -static int cdrom_ioctl_clear_options(struct cdrom_device_info *cdi, - unsigned long arg) -{ - cdinfo(CD_DO_IOCTL, "entering CDROM_CLEAR_OPTIONS\n"); - - cdi->options &= ~(int) arg; - return cdi->options; -} - -static int cdrom_ioctl_select_speed(struct cdrom_device_info *cdi, - unsigned long arg) -{ - cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_SPEED\n"); - - if (!CDROM_CAN(CDC_SELECT_SPEED)) - return -ENOSYS; - return cdi->ops->select_speed(cdi, arg); -} - -static int cdrom_ioctl_select_disc(struct cdrom_device_info *cdi, - unsigned long arg) -{ - cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_DISC\n"); - - if (!CDROM_CAN(CDC_SELECT_DISC)) - return -ENOSYS; - - if (arg != CDSL_CURRENT && arg != CDSL_NONE) { - if ((int)arg >= cdi->capacity) - return -EINVAL; - } - - /* - * ->select_disc is a hook to allow a driver-specific way of - * seleting disc. However, since there is no equivalent hook for - * cdrom_slot_status this may not actually be useful... - */ - if (cdi->ops->select_disc) - return cdi->ops->select_disc(cdi, arg); - - cdinfo(CD_CHANGER, "Using generic cdrom_select_disc()\n"); - return cdrom_select_disc(cdi, arg); -} - -static int cdrom_ioctl_reset(struct cdrom_device_info *cdi, - struct block_device *bdev) -{ - cdinfo(CD_DO_IOCTL, "entering CDROM_RESET\n"); - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (!CDROM_CAN(CDC_RESET)) - return -ENOSYS; - invalidate_bdev(bdev); - return cdi->ops->reset(cdi); -} - -static int cdrom_ioctl_lock_door(struct cdrom_device_info *cdi, - unsigned long arg) -{ - cdinfo(CD_DO_IOCTL, "%socking door.\n", arg ? "L" : "Unl"); - - if (!CDROM_CAN(CDC_LOCK)) - return -EDRIVE_CANT_DO_THIS; - - keeplocked = arg ? 1 : 0; - - /* - * Don't unlock the door on multiple opens by default, but allow - * root to do so. - */ - if (cdi->use_count != 1 && !arg && !capable(CAP_SYS_ADMIN)) - return -EBUSY; - return cdi->ops->lock_door(cdi, arg); -} - -static int cdrom_ioctl_debug(struct cdrom_device_info *cdi, - unsigned long arg) -{ - cdinfo(CD_DO_IOCTL, "%sabling debug.\n", arg ? "En" : "Dis"); - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - debug = arg ? 1 : 0; - return debug; -} - -static int cdrom_ioctl_get_capability(struct cdrom_device_info *cdi) -{ - cdinfo(CD_DO_IOCTL, "entering CDROM_GET_CAPABILITY\n"); - return (cdi->ops->capability & ~cdi->mask); -} - -/* - * The following function is implemented, although very few audio - * discs give Universal Product Code information, which should just be - * the Medium Catalog Number on the box. Note, that the way the code - * is written on the CD is /not/ uniform across all discs! - */ -static int cdrom_ioctl_get_mcn(struct cdrom_device_info *cdi, - void __user *argp) -{ - struct cdrom_mcn mcn; - int ret; - - cdinfo(CD_DO_IOCTL, "entering CDROM_GET_MCN\n"); - - if (!(cdi->ops->capability & CDC_MCN)) - return -ENOSYS; - ret = cdi->ops->get_mcn(cdi, &mcn); - if (ret) - return ret; - - if (copy_to_user(argp, &mcn, sizeof(mcn))) - return -EFAULT; - cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN successful\n"); - return 0; -} - -static int cdrom_ioctl_drive_status(struct cdrom_device_info *cdi, - unsigned long arg) -{ - cdinfo(CD_DO_IOCTL, "entering CDROM_DRIVE_STATUS\n"); - - if (!(cdi->ops->capability & CDC_DRIVE_STATUS)) - return -ENOSYS; - if (!CDROM_CAN(CDC_SELECT_DISC) || - (arg == CDSL_CURRENT || arg == CDSL_NONE)) - return cdi->ops->drive_status(cdi, CDSL_CURRENT); - if (((int)arg >= cdi->capacity)) - return -EINVAL; - return cdrom_slot_status(cdi, arg); -} - -/* - * Ok, this is where problems start. The current interface for the - * CDROM_DISC_STATUS ioctl is flawed. It makes the false assumption that - * CDs are all CDS_DATA_1 or all CDS_AUDIO, etc. Unfortunatly, while this - * is often the case, it is also very common for CDs to have some tracks - * with data, and some tracks with audio. Just because I feel like it, - * I declare the following to be the best way to cope. If the CD has ANY - * data tracks on it, it will be returned as a data CD. If it has any XA - * tracks, I will return it as that. Now I could simplify this interface - * by combining these returns with the above, but this more clearly - * demonstrates the problem with the current interface. Too bad this - * wasn't designed to use bitmasks... -Erik - * - * Well, now we have the option CDS_MIXED: a mixed-type CD. - * User level programmers might feel the ioctl is not very useful. - * ---david - */ -static int cdrom_ioctl_disc_status(struct cdrom_device_info *cdi) -{ - tracktype tracks; - - cdinfo(CD_DO_IOCTL, "entering CDROM_DISC_STATUS\n"); - - cdrom_count_tracks(cdi, &tracks); - if (tracks.error) - return tracks.error; - - /* Policy mode on */ - if (tracks.audio > 0) { - if (!tracks.data && !tracks.cdi && !tracks.xa) - return CDS_AUDIO; - else - return CDS_MIXED; - } - - if (tracks.cdi > 0) - return CDS_XA_2_2; - if (tracks.xa > 0) - return CDS_XA_2_1; - if (tracks.data > 0) - return CDS_DATA_1; - /* Policy mode off */ - - cdinfo(CD_WARNING,"This disc doesn't have any tracks I recognize!\n"); - return CDS_NO_INFO; -} - -static int cdrom_ioctl_changer_nslots(struct cdrom_device_info *cdi) -{ - cdinfo(CD_DO_IOCTL, "entering CDROM_CHANGER_NSLOTS\n"); - return cdi->capacity; -} - -static int cdrom_ioctl_get_subchnl(struct cdrom_device_info *cdi, - void __user *argp) -{ - struct cdrom_subchnl q; - u8 requested, back; - int ret; - - /* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/ - - if (copy_from_user(&q, argp, sizeof(q))) - return -EFAULT; - - requested = q.cdsc_format; - if (requested != CDROM_MSF && requested != CDROM_LBA) - return -EINVAL; - q.cdsc_format = CDROM_MSF; - - ret = cdi->ops->audio_ioctl(cdi, CDROMSUBCHNL, &q); - if (ret) - return ret; - - back = q.cdsc_format; /* local copy */ - sanitize_format(&q.cdsc_absaddr, &back, requested); - sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested); - - if (copy_to_user(argp, &q, sizeof(q))) - return -EFAULT; - /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ - return 0; -} - -static int cdrom_ioctl_read_tochdr(struct cdrom_device_info *cdi, - void __user *argp) -{ - struct cdrom_tochdr header; - int ret; - - /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */ - - if (copy_from_user(&header, argp, sizeof(header))) - return -EFAULT; - - ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header); - if (ret) - return ret; - - if (copy_to_user(argp, &header, sizeof(header))) - return -EFAULT; - /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */ - return 0; -} - -static int cdrom_ioctl_read_tocentry(struct cdrom_device_info *cdi, - void __user *argp) -{ - struct cdrom_tocentry entry; - u8 requested_format; - int ret; - - /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */ - - if (copy_from_user(&entry, argp, sizeof(entry))) - return -EFAULT; - - requested_format = entry.cdte_format; - if (requested_format != CDROM_MSF && requested_format != CDROM_LBA) - return -EINVAL; - /* make interface to low-level uniform */ - entry.cdte_format = CDROM_MSF; - ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry); - if (ret) - return ret; - sanitize_format(&entry.cdte_addr, &entry.cdte_format, requested_format); - - if (copy_to_user(argp, &entry, sizeof(entry))) - return -EFAULT; - /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */ - return 0; -} - -static int cdrom_ioctl_play_msf(struct cdrom_device_info *cdi, - void __user *argp) -{ - struct cdrom_msf msf; - - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); - - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - if (copy_from_user(&msf, argp, sizeof(msf))) - return -EFAULT; - return cdi->ops->audio_ioctl(cdi, CDROMPLAYMSF, &msf); -} - -static int cdrom_ioctl_play_trkind(struct cdrom_device_info *cdi, - void __user *argp) -{ - struct cdrom_ti ti; - int ret; - - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n"); - - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - if (copy_from_user(&ti, argp, sizeof(ti))) - return -EFAULT; - - ret = check_for_audio_disc(cdi, cdi->ops); - if (ret) - return ret; - return cdi->ops->audio_ioctl(cdi, CDROMPLAYTRKIND, &ti); -} -static int cdrom_ioctl_volctrl(struct cdrom_device_info *cdi, - void __user *argp) -{ - struct cdrom_volctrl volume; - - cdinfo(CD_DO_IOCTL, "entering CDROMVOLCTRL\n"); - - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - if (copy_from_user(&volume, argp, sizeof(volume))) - return -EFAULT; - return cdi->ops->audio_ioctl(cdi, CDROMVOLCTRL, &volume); -} - -static int cdrom_ioctl_volread(struct cdrom_device_info *cdi, - void __user *argp) -{ - struct cdrom_volctrl volume; - int ret; - - cdinfo(CD_DO_IOCTL, "entering CDROMVOLREAD\n"); - - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - - ret = cdi->ops->audio_ioctl(cdi, CDROMVOLREAD, &volume); - if (ret) - return ret; - - if (copy_to_user(argp, &volume, sizeof(volume))) - return -EFAULT; - return 0; -} - -static int cdrom_ioctl_audioctl(struct cdrom_device_info *cdi, - unsigned int cmd) -{ - int ret; - - cdinfo(CD_DO_IOCTL, "doing audio ioctl (start/stop/pause/resume)\n"); - - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; - ret = check_for_audio_disc(cdi, cdi->ops); - if (ret) - return ret; - return cdi->ops->audio_ioctl(cdi, cmd, NULL); -} - -/* - * Just about every imaginable ioctl is supported in the Uniform layer - * these days. - * ATAPI / SCSI specific code now mainly resides in mmc_ioctl(). - */ -int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev, - fmode_t mode, unsigned int cmd, unsigned long arg) -{ - void __user *argp = (void __user *)arg; - int ret; - struct gendisk *disk = bdev->bd_disk; - - /* - * Try the generic SCSI command ioctl's first. - */ - ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp); - if (ret != -ENOTTY) - return ret; - - switch (cmd) { - case CDROMMULTISESSION: - return cdrom_ioctl_multisession(cdi, argp); - case CDROMEJECT: - return cdrom_ioctl_eject(cdi); - case CDROMCLOSETRAY: - return cdrom_ioctl_closetray(cdi); - case CDROMEJECT_SW: - return cdrom_ioctl_eject_sw(cdi, arg); - case CDROM_MEDIA_CHANGED: - return cdrom_ioctl_media_changed(cdi, arg); - case CDROM_SET_OPTIONS: - return cdrom_ioctl_set_options(cdi, arg); - case CDROM_CLEAR_OPTIONS: - return cdrom_ioctl_clear_options(cdi, arg); - case CDROM_SELECT_SPEED: - return cdrom_ioctl_select_speed(cdi, arg); - case CDROM_SELECT_DISC: - return cdrom_ioctl_select_disc(cdi, arg); - case CDROMRESET: - return cdrom_ioctl_reset(cdi, bdev); - case CDROM_LOCKDOOR: - return cdrom_ioctl_lock_door(cdi, arg); - case CDROM_DEBUG: - return cdrom_ioctl_debug(cdi, arg); - case CDROM_GET_CAPABILITY: - return cdrom_ioctl_get_capability(cdi); - case CDROM_GET_MCN: - return cdrom_ioctl_get_mcn(cdi, argp); - case CDROM_DRIVE_STATUS: - return cdrom_ioctl_drive_status(cdi, arg); - case CDROM_DISC_STATUS: - return cdrom_ioctl_disc_status(cdi); - case CDROM_CHANGER_NSLOTS: - return cdrom_ioctl_changer_nslots(cdi); - } - - /* - * Use the ioctls that are implemented through the generic_packet() - * interface. this may look at bit funny, but if -ENOTTY is - * returned that particular ioctl is not implemented and we - * let it go through the device specific ones. - */ - if (CDROM_CAN(CDC_GENERIC_PACKET)) { - ret = mmc_ioctl(cdi, cmd, arg); - if (ret != -ENOTTY) - return ret; - } - - /* - * Note: most of the cdinfo() calls are commented out here, - * because they fill up the sys log when CD players poll - * the drive. - */ - switch (cmd) { - case CDROMSUBCHNL: - return cdrom_ioctl_get_subchnl(cdi, argp); - case CDROMREADTOCHDR: - return cdrom_ioctl_read_tochdr(cdi, argp); - case CDROMREADTOCENTRY: - return cdrom_ioctl_read_tocentry(cdi, argp); - case CDROMPLAYMSF: - return cdrom_ioctl_play_msf(cdi, argp); - case CDROMPLAYTRKIND: - return cdrom_ioctl_play_trkind(cdi, argp); - case CDROMVOLCTRL: - return cdrom_ioctl_volctrl(cdi, argp); - case CDROMVOLREAD: - return cdrom_ioctl_volread(cdi, argp); - case CDROMSTART: - case CDROMSTOP: - case CDROMPAUSE: - case CDROMRESUME: - return cdrom_ioctl_audioctl(cdi, cmd); - } - - return -ENOSYS; -} - -/* - * Required when we need to use READ_10 to issue other than 2048 block - * reads - */ -static int cdrom_switch_blocksize(struct cdrom_device_info *cdi, int size) -{ - struct cdrom_device_ops *cdo = cdi->ops; - struct packet_command cgc; - struct modesel_head mh; - - memset(&mh, 0, sizeof(mh)); - mh.block_desc_length = 0x08; - mh.block_length_med = (size >> 8) & 0xff; - mh.block_length_lo = size & 0xff; - - memset(&cgc, 0, sizeof(cgc)); - cgc.cmd[0] = 0x15; - cgc.cmd[1] = 1 << 4; - cgc.cmd[4] = 12; - cgc.buflen = sizeof(mh); - cgc.buffer = (char *) &mh; - cgc.data_direction = CGC_DATA_WRITE; - mh.block_desc_length = 0x08; - mh.block_length_med = (size >> 8) & 0xff; - mh.block_length_lo = size & 0xff; - - return cdo->generic_packet(cdi, &cgc); -} - -static noinline int mmc_ioctl_cdrom_read_data(struct cdrom_device_info *cdi, - void __user *arg, - struct packet_command *cgc, - int cmd) -{ - struct request_sense sense; - struct cdrom_msf msf; - int blocksize = 0, format = 0, lba; - int ret; - - switch (cmd) { - case CDROMREADRAW: - blocksize = CD_FRAMESIZE_RAW; - break; - case CDROMREADMODE1: - blocksize = CD_FRAMESIZE; - format = 2; - break; - case CDROMREADMODE2: - blocksize = CD_FRAMESIZE_RAW0; - break; - } - IOCTL_IN(arg, struct cdrom_msf, msf); - lba = msf_to_lba(msf.cdmsf_min0, msf.cdmsf_sec0, msf.cdmsf_frame0); - /* FIXME: we need upper bound checking, too!! */ - if (lba < 0) - return -EINVAL; - - cgc->buffer = kmalloc(blocksize, GFP_KERNEL); - if (cgc->buffer == NULL) - return -ENOMEM; - - memset(&sense, 0, sizeof(sense)); - cgc->sense = &sense; - cgc->data_direction = CGC_DATA_READ; - ret = cdrom_read_block(cdi, cgc, lba, 1, format, blocksize); - if (ret && sense.sense_key == 0x05 && - sense.asc == 0x20 && - sense.ascq == 0x00) { - /* - * SCSI-II devices are not required to support - * READ_CD, so let's try switching block size - */ - /* FIXME: switch back again... */ - ret = cdrom_switch_blocksize(cdi, blocksize); - if (ret) - goto out; - cgc->sense = NULL; - ret = cdrom_read_cd(cdi, cgc, lba, blocksize, 1); - ret |= cdrom_switch_blocksize(cdi, blocksize); - } - if (!ret && copy_to_user(arg, cgc->buffer, blocksize)) - ret = -EFAULT; -out: - kfree(cgc->buffer); - return ret; -} - -static noinline int mmc_ioctl_cdrom_read_audio(struct cdrom_device_info *cdi, - void __user *arg) -{ - struct cdrom_read_audio ra; - int lba; - - IOCTL_IN(arg, struct cdrom_read_audio, ra); - - if (ra.addr_format == CDROM_MSF) - lba = msf_to_lba(ra.addr.msf.minute, - ra.addr.msf.second, - ra.addr.msf.frame); - else if (ra.addr_format == CDROM_LBA) - lba = ra.addr.lba; - else - return -EINVAL; - - /* FIXME: we need upper bound checking, too!! */ - if (lba < 0 || ra.nframes <= 0 || ra.nframes > CD_FRAMES) - return -EINVAL; - - return cdrom_read_cdda(cdi, ra.buf, lba, ra.nframes); -} - -static noinline int mmc_ioctl_cdrom_subchannel(struct cdrom_device_info *cdi, - void __user *arg) -{ - int ret; - struct cdrom_subchnl q; - u_char requested, back; - IOCTL_IN(arg, struct cdrom_subchnl, q); - requested = q.cdsc_format; - if (!((requested == CDROM_MSF) || - (requested == CDROM_LBA))) - return -EINVAL; - q.cdsc_format = CDROM_MSF; - ret = cdrom_read_subchannel(cdi, &q, 0); - if (ret) - return ret; - back = q.cdsc_format; /* local copy */ - sanitize_format(&q.cdsc_absaddr, &back, requested); - sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested); - IOCTL_OUT(arg, struct cdrom_subchnl, q); - /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ - return 0; -} - -static noinline int mmc_ioctl_cdrom_play_msf(struct cdrom_device_info *cdi, - void __user *arg, - struct packet_command *cgc) -{ - struct cdrom_device_ops *cdo = cdi->ops; - struct cdrom_msf msf; - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); - IOCTL_IN(arg, struct cdrom_msf, msf); - cgc->cmd[0] = GPCMD_PLAY_AUDIO_MSF; - cgc->cmd[3] = msf.cdmsf_min0; - cgc->cmd[4] = msf.cdmsf_sec0; - cgc->cmd[5] = msf.cdmsf_frame0; - cgc->cmd[6] = msf.cdmsf_min1; - cgc->cmd[7] = msf.cdmsf_sec1; - cgc->cmd[8] = msf.cdmsf_frame1; - cgc->data_direction = CGC_DATA_NONE; - return cdo->generic_packet(cdi, cgc); -} - -static noinline int mmc_ioctl_cdrom_play_blk(struct cdrom_device_info *cdi, - void __user *arg, - struct packet_command *cgc) -{ - struct cdrom_device_ops *cdo = cdi->ops; - struct cdrom_blk blk; - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYBLK\n"); - IOCTL_IN(arg, struct cdrom_blk, blk); - cgc->cmd[0] = GPCMD_PLAY_AUDIO_10; - cgc->cmd[2] = (blk.from >> 24) & 0xff; - cgc->cmd[3] = (blk.from >> 16) & 0xff; - cgc->cmd[4] = (blk.from >> 8) & 0xff; - cgc->cmd[5] = blk.from & 0xff; - cgc->cmd[7] = (blk.len >> 8) & 0xff; - cgc->cmd[8] = blk.len & 0xff; - cgc->data_direction = CGC_DATA_NONE; - return cdo->generic_packet(cdi, cgc); -} - -static noinline int mmc_ioctl_cdrom_volume(struct cdrom_device_info *cdi, - void __user *arg, - struct packet_command *cgc, - unsigned int cmd) -{ - struct cdrom_volctrl volctrl; - unsigned char buffer[32]; - char mask[sizeof(buffer)]; - unsigned short offset; - int ret; - - cdinfo(CD_DO_IOCTL, "entering CDROMVOLUME\n"); - - IOCTL_IN(arg, struct cdrom_volctrl, volctrl); - - cgc->buffer = buffer; - cgc->buflen = 24; - ret = cdrom_mode_sense(cdi, cgc, GPMODE_AUDIO_CTL_PAGE, 0); - if (ret) - return ret; - - /* originally the code depended on buffer[1] to determine - how much data is available for transfer. buffer[1] is - unfortunately ambigious and the only reliable way seem - to be to simply skip over the block descriptor... */ - offset = 8 + be16_to_cpu(*(__be16 *)(buffer + 6)); - - if (offset + 16 > sizeof(buffer)) - return -E2BIG; - - if (offset + 16 > cgc->buflen) { - cgc->buflen = offset + 16; - ret = cdrom_mode_sense(cdi, cgc, - GPMODE_AUDIO_CTL_PAGE, 0); - if (ret) - return ret; - } - - /* sanity check */ - if ((buffer[offset] & 0x3f) != GPMODE_AUDIO_CTL_PAGE || - buffer[offset + 1] < 14) - return -EINVAL; - - /* now we have the current volume settings. if it was only - a CDROMVOLREAD, return these values */ - if (cmd == CDROMVOLREAD) { - volctrl.channel0 = buffer[offset+9]; - volctrl.channel1 = buffer[offset+11]; - volctrl.channel2 = buffer[offset+13]; - volctrl.channel3 = buffer[offset+15]; - IOCTL_OUT(arg, struct cdrom_volctrl, volctrl); - return 0; - } - - /* get the volume mask */ - cgc->buffer = mask; - ret = cdrom_mode_sense(cdi, cgc, GPMODE_AUDIO_CTL_PAGE, 1); - if (ret) - return ret; - - buffer[offset + 9] = volctrl.channel0 & mask[offset + 9]; - buffer[offset + 11] = volctrl.channel1 & mask[offset + 11]; - buffer[offset + 13] = volctrl.channel2 & mask[offset + 13]; - buffer[offset + 15] = volctrl.channel3 & mask[offset + 15]; - - /* set volume */ - cgc->buffer = buffer + offset - 8; - memset(cgc->buffer, 0, 8); - return cdrom_mode_select(cdi, cgc); -} - -static noinline int mmc_ioctl_cdrom_start_stop(struct cdrom_device_info *cdi, - struct packet_command *cgc, - int cmd) -{ - struct cdrom_device_ops *cdo = cdi->ops; - cdinfo(CD_DO_IOCTL, "entering CDROMSTART/CDROMSTOP\n"); - cgc->cmd[0] = GPCMD_START_STOP_UNIT; - cgc->cmd[1] = 1; - cgc->cmd[4] = (cmd == CDROMSTART) ? 1 : 0; - cgc->data_direction = CGC_DATA_NONE; - return cdo->generic_packet(cdi, cgc); -} - -static noinline int mmc_ioctl_cdrom_pause_resume(struct cdrom_device_info *cdi, - struct packet_command *cgc, - int cmd) -{ - struct cdrom_device_ops *cdo = cdi->ops; - cdinfo(CD_DO_IOCTL, "entering CDROMPAUSE/CDROMRESUME\n"); - cgc->cmd[0] = GPCMD_PAUSE_RESUME; - cgc->cmd[8] = (cmd == CDROMRESUME) ? 1 : 0; - cgc->data_direction = CGC_DATA_NONE; - return cdo->generic_packet(cdi, cgc); -} - -static noinline int mmc_ioctl_dvd_read_struct(struct cdrom_device_info *cdi, - void __user *arg, - struct packet_command *cgc) -{ - int ret; - dvd_struct *s; - int size = sizeof(dvd_struct); - - if (!CDROM_CAN(CDC_DVD)) - return -ENOSYS; - - s = kmalloc(size, GFP_KERNEL); - if (!s) - return -ENOMEM; - - cdinfo(CD_DO_IOCTL, "entering DVD_READ_STRUCT\n"); - if (copy_from_user(s, arg, size)) { - kfree(s); - return -EFAULT; - } - - ret = dvd_read_struct(cdi, s, cgc); - if (ret) - goto out; - - if (copy_to_user(arg, s, size)) - ret = -EFAULT; -out: - kfree(s); - return ret; -} - -static noinline int mmc_ioctl_dvd_auth(struct cdrom_device_info *cdi, - void __user *arg) -{ - int ret; - dvd_authinfo ai; - if (!CDROM_CAN(CDC_DVD)) - return -ENOSYS; - cdinfo(CD_DO_IOCTL, "entering DVD_AUTH\n"); - IOCTL_IN(arg, dvd_authinfo, ai); - ret = dvd_do_auth(cdi, &ai); - if (ret) - return ret; - IOCTL_OUT(arg, dvd_authinfo, ai); - return 0; -} - -static noinline int mmc_ioctl_cdrom_next_writable(struct cdrom_device_info *cdi, - void __user *arg) -{ - int ret; - long next = 0; - cdinfo(CD_DO_IOCTL, "entering CDROM_NEXT_WRITABLE\n"); - ret = cdrom_get_next_writable(cdi, &next); - if (ret) - return ret; - IOCTL_OUT(arg, long, next); - return 0; -} - -static noinline int mmc_ioctl_cdrom_last_written(struct cdrom_device_info *cdi, - void __user *arg) -{ - int ret; - long last = 0; - cdinfo(CD_DO_IOCTL, "entering CDROM_LAST_WRITTEN\n"); - ret = cdrom_get_last_written(cdi, &last); - if (ret) - return ret; - IOCTL_OUT(arg, long, last); - return 0; -} - -static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, - unsigned long arg) -{ - struct packet_command cgc; - void __user *userptr = (void __user *)arg; - - memset(&cgc, 0, sizeof(cgc)); - - /* build a unified command and queue it through - cdo->generic_packet() */ - switch (cmd) { - case CDROMREADRAW: - case CDROMREADMODE1: - case CDROMREADMODE2: - return mmc_ioctl_cdrom_read_data(cdi, userptr, &cgc, cmd); - case CDROMREADAUDIO: - return mmc_ioctl_cdrom_read_audio(cdi, userptr); - case CDROMSUBCHNL: - return mmc_ioctl_cdrom_subchannel(cdi, userptr); - case CDROMPLAYMSF: - return mmc_ioctl_cdrom_play_msf(cdi, userptr, &cgc); - case CDROMPLAYBLK: - return mmc_ioctl_cdrom_play_blk(cdi, userptr, &cgc); - case CDROMVOLCTRL: - case CDROMVOLREAD: - return mmc_ioctl_cdrom_volume(cdi, userptr, &cgc, cmd); - case CDROMSTART: - case CDROMSTOP: - return mmc_ioctl_cdrom_start_stop(cdi, &cgc, cmd); - case CDROMPAUSE: - case CDROMRESUME: - return mmc_ioctl_cdrom_pause_resume(cdi, &cgc, cmd); - case DVD_READ_STRUCT: - return mmc_ioctl_dvd_read_struct(cdi, userptr, &cgc); - case DVD_AUTH: - return mmc_ioctl_dvd_auth(cdi, userptr); - case CDROM_NEXT_WRITABLE: - return mmc_ioctl_cdrom_next_writable(cdi, userptr); - case CDROM_LAST_WRITTEN: - return mmc_ioctl_cdrom_last_written(cdi, userptr); - } - - return -ENOTTY; -} - -static int cdrom_get_track_info(struct cdrom_device_info *cdi, __u16 track, __u8 type, - track_information *ti) -{ - struct cdrom_device_ops *cdo = cdi->ops; - struct packet_command cgc; - int ret, buflen; - - init_cdrom_command(&cgc, ti, 8, CGC_DATA_READ); - cgc.cmd[0] = GPCMD_READ_TRACK_RZONE_INFO; - cgc.cmd[1] = type & 3; - cgc.cmd[4] = (track & 0xff00) >> 8; - cgc.cmd[5] = track & 0xff; - cgc.cmd[8] = 8; - cgc.quiet = 1; - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - buflen = be16_to_cpu(ti->track_information_length) + - sizeof(ti->track_information_length); - - if (buflen > sizeof(track_information)) - buflen = sizeof(track_information); - - cgc.cmd[8] = cgc.buflen = buflen; - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - /* return actual fill size */ - return buflen; -} - -/* requires CD R/RW */ -static int cdrom_get_disc_info(struct cdrom_device_info *cdi, disc_information *di) -{ - struct cdrom_device_ops *cdo = cdi->ops; - struct packet_command cgc; - int ret, buflen; - - /* set up command and get the disc info */ - init_cdrom_command(&cgc, di, sizeof(*di), CGC_DATA_READ); - cgc.cmd[0] = GPCMD_READ_DISC_INFO; - cgc.cmd[8] = cgc.buflen = 2; - cgc.quiet = 1; - - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - /* not all drives have the same disc_info length, so requeue - * packet with the length the drive tells us it can supply - */ - buflen = be16_to_cpu(di->disc_information_length) + - sizeof(di->disc_information_length); - - if (buflen > sizeof(disc_information)) - buflen = sizeof(disc_information); - - cgc.cmd[8] = cgc.buflen = buflen; - if ((ret = cdo->generic_packet(cdi, &cgc))) - return ret; - - /* return actual fill size */ - return buflen; -} - -/* return the last written block on the CD-R media. this is for the udf - file system. */ -int cdrom_get_last_written(struct cdrom_device_info *cdi, long *last_written) -{ - struct cdrom_tocentry toc; - disc_information di; - track_information ti; - __u32 last_track; - int ret = -1, ti_size; - - if (!CDROM_CAN(CDC_GENERIC_PACKET)) - goto use_toc; - - ret = cdrom_get_disc_info(cdi, &di); - if (ret < (int)(offsetof(typeof(di), last_track_lsb) - + sizeof(di.last_track_lsb))) - goto use_toc; - - /* if unit didn't return msb, it's zeroed by cdrom_get_disc_info */ - last_track = (di.last_track_msb << 8) | di.last_track_lsb; - ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti); - if (ti_size < (int)offsetof(typeof(ti), track_start)) - goto use_toc; - - /* if this track is blank, try the previous. */ - if (ti.blank) { - if (last_track==1) - goto use_toc; - last_track--; - ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti); - } - - if (ti_size < (int)(offsetof(typeof(ti), track_size) - + sizeof(ti.track_size))) - goto use_toc; - - /* if last recorded field is valid, return it. */ - if (ti.lra_v && ti_size >= (int)(offsetof(typeof(ti), last_rec_address) - + sizeof(ti.last_rec_address))) { - *last_written = be32_to_cpu(ti.last_rec_address); - } else { - /* make it up instead */ - *last_written = be32_to_cpu(ti.track_start) + - be32_to_cpu(ti.track_size); - if (ti.free_blocks) - *last_written -= (be32_to_cpu(ti.free_blocks) + 7); - } - return 0; - - /* this is where we end up if the drive either can't do a - GPCMD_READ_DISC_INFO or GPCMD_READ_TRACK_RZONE_INFO or if - it doesn't give enough information or fails. then we return - the toc contents. */ -use_toc: - toc.cdte_format = CDROM_MSF; - toc.cdte_track = CDROM_LEADOUT; - if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &toc))) - return ret; - sanitize_format(&toc.cdte_addr, &toc.cdte_format, CDROM_LBA); - *last_written = toc.cdte_addr.lba; - return 0; -} - -/* return the next writable block. also for udf file system. */ -static int cdrom_get_next_writable(struct cdrom_device_info *cdi, long *next_writable) -{ - disc_information di; - track_information ti; - __u16 last_track; - int ret, ti_size; - - if (!CDROM_CAN(CDC_GENERIC_PACKET)) - goto use_last_written; - - ret = cdrom_get_disc_info(cdi, &di); - if (ret < 0 || ret < offsetof(typeof(di), last_track_lsb) - + sizeof(di.last_track_lsb)) - goto use_last_written; - - /* if unit didn't return msb, it's zeroed by cdrom_get_disc_info */ - last_track = (di.last_track_msb << 8) | di.last_track_lsb; - ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti); - if (ti_size < 0 || ti_size < offsetof(typeof(ti), track_start)) - goto use_last_written; - - /* if this track is blank, try the previous. */ - if (ti.blank) { - if (last_track == 1) - goto use_last_written; - last_track--; - ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti); - if (ti_size < 0) - goto use_last_written; - } - - /* if next recordable address field is valid, use it. */ - if (ti.nwa_v && ti_size >= offsetof(typeof(ti), next_writable) - + sizeof(ti.next_writable)) { - *next_writable = be32_to_cpu(ti.next_writable); - return 0; - } - -use_last_written: - if ((ret = cdrom_get_last_written(cdi, next_writable))) { - *next_writable = 0; - return ret; - } else { - *next_writable += 7; - return 0; - } -} - -EXPORT_SYMBOL(cdrom_get_last_written); -EXPORT_SYMBOL(register_cdrom); -EXPORT_SYMBOL(unregister_cdrom); -EXPORT_SYMBOL(cdrom_open); -EXPORT_SYMBOL(cdrom_release); -EXPORT_SYMBOL(cdrom_ioctl); -EXPORT_SYMBOL(cdrom_media_changed); -EXPORT_SYMBOL(cdrom_number_of_slots); -EXPORT_SYMBOL(cdrom_mode_select); -EXPORT_SYMBOL(cdrom_mode_sense); -EXPORT_SYMBOL(init_cdrom_command); -EXPORT_SYMBOL(cdrom_get_media_event); - -#ifdef CONFIG_SYSCTL - -#define CDROM_STR_SIZE 1000 - -static struct cdrom_sysctl_settings { - char info[CDROM_STR_SIZE]; /* general info */ - int autoclose; /* close tray upon mount, etc */ - int autoeject; /* eject on umount */ - int debug; /* turn on debugging messages */ - int lock; /* lock the door on device open */ - int check; /* check media type */ -} cdrom_sysctl_settings; - -enum cdrom_print_option { - CTL_NAME, - CTL_SPEED, - CTL_SLOTS, - CTL_CAPABILITY -}; - -static int cdrom_print_info(const char *header, int val, char *info, - int *pos, enum cdrom_print_option option) -{ - const int max_size = sizeof(cdrom_sysctl_settings.info); - struct cdrom_device_info *cdi; - int ret; - - ret = scnprintf(info + *pos, max_size - *pos, header); - if (!ret) - return 1; - - *pos += ret; - - list_for_each_entry(cdi, &cdrom_list, list) { - switch (option) { - case CTL_NAME: - ret = scnprintf(info + *pos, max_size - *pos, - "\t%s", cdi->name); - break; - case CTL_SPEED: - ret = scnprintf(info + *pos, max_size - *pos, - "\t%d", cdi->speed); - break; - case CTL_SLOTS: - ret = scnprintf(info + *pos, max_size - *pos, - "\t%d", cdi->capacity); - break; - case CTL_CAPABILITY: - ret = scnprintf(info + *pos, max_size - *pos, - "\t%d", CDROM_CAN(val) != 0); - break; - default: - printk(KERN_INFO "cdrom: invalid option%d\n", option); - return 1; - } - if (!ret) - return 1; - *pos += ret; - } - - return 0; -} - -static int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp, - void __user *buffer, size_t *lenp, loff_t *ppos) -{ - int pos; - char *info = cdrom_sysctl_settings.info; - const int max_size = sizeof(cdrom_sysctl_settings.info); - - if (!*lenp || (*ppos && !write)) { - *lenp = 0; - return 0; - } - - mutex_lock(&cdrom_mutex); - - pos = sprintf(info, "CD-ROM information, " VERSION "\n"); - - if (cdrom_print_info("\ndrive name:\t", 0, info, &pos, CTL_NAME)) - goto done; - if (cdrom_print_info("\ndrive speed:\t", 0, info, &pos, CTL_SPEED)) - goto done; - if (cdrom_print_info("\ndrive # of slots:", 0, info, &pos, CTL_SLOTS)) - goto done; - if (cdrom_print_info("\nCan close tray:\t", - CDC_CLOSE_TRAY, info, &pos, CTL_CAPABILITY)) - goto done; - if (cdrom_print_info("\nCan open tray:\t", - CDC_OPEN_TRAY, info, &pos, CTL_CAPABILITY)) - goto done; - if (cdrom_print_info("\nCan lock tray:\t", - CDC_LOCK, info, &pos, CTL_CAPABILITY)) - goto done; - if (cdrom_print_info("\nCan change speed:", - CDC_SELECT_SPEED, info, &pos, CTL_CAPABILITY)) - goto done; - if (cdrom_print_info("\nCan select disk:", - CDC_SELECT_DISC, info, &pos, CTL_CAPABILITY)) - goto done; - if (cdrom_print_info("\nCan read multisession:", - CDC_MULTI_SESSION, info, &pos, CTL_CAPABILITY)) - goto done; - if (cdrom_print_info("\nCan read MCN:\t", - CDC_MCN, info, &pos, CTL_CAPABILITY)) - goto done; - if (cdrom_print_info("\nReports media changed:", - CDC_MEDIA_CHANGED, info, &pos, CTL_CAPABILITY)) - goto done; - if (cdrom_print_info("\nCan play audio:\t", - CDC_PLAY_AUDIO, info, &pos, CTL_CAPABILITY)) - goto done; - if (cdrom_print_info("\nCan write CD-R:\t", - CDC_CD_R, info, &pos, CTL_CAPABILITY)) - goto done; - if (cdrom_print_info("\nCan write CD-RW:", - CDC_CD_RW, info, &pos, CTL_CAPABILITY)) - goto done; - if (cdrom_print_info("\nCan read DVD:\t", - CDC_DVD, info, &pos, CTL_CAPABILITY)) - goto done; - if (cdrom_print_info("\nCan write DVD-R:", - CDC_DVD_R, info, &pos, CTL_CAPABILITY)) - goto done; - if (cdrom_print_info("\nCan write DVD-RAM:", - CDC_DVD_RAM, info, &pos, CTL_CAPABILITY)) - goto done; - if (cdrom_print_info("\nCan read MRW:\t", - CDC_MRW, info, &pos, CTL_CAPABILITY)) - goto done; - if (cdrom_print_info("\nCan write MRW:\t", - CDC_MRW_W, info, &pos, CTL_CAPABILITY)) - goto done; - if (cdrom_print_info("\nCan write RAM:\t", - CDC_RAM, info, &pos, CTL_CAPABILITY)) - goto done; - if (!scnprintf(info + pos, max_size - pos, "\n\n")) - goto done; -doit: - mutex_unlock(&cdrom_mutex); - return proc_dostring(ctl, write, filp, buffer, lenp, ppos); -done: - printk(KERN_INFO "cdrom: info buffer too small\n"); - goto doit; -} - -/* Unfortunately, per device settings are not implemented through - procfs/sysctl yet. When they are, this will naturally disappear. For now - just update all drives. Later this will become the template on which - new registered drives will be based. */ -static void cdrom_update_settings(void) -{ - struct cdrom_device_info *cdi; - - mutex_lock(&cdrom_mutex); - list_for_each_entry(cdi, &cdrom_list, list) { - if (autoclose && CDROM_CAN(CDC_CLOSE_TRAY)) - cdi->options |= CDO_AUTO_CLOSE; - else if (!autoclose) - cdi->options &= ~CDO_AUTO_CLOSE; - if (autoeject && CDROM_CAN(CDC_OPEN_TRAY)) - cdi->options |= CDO_AUTO_EJECT; - else if (!autoeject) - cdi->options &= ~CDO_AUTO_EJECT; - if (lockdoor && CDROM_CAN(CDC_LOCK)) - cdi->options |= CDO_LOCK; - else if (!lockdoor) - cdi->options &= ~CDO_LOCK; - if (check_media_type) - cdi->options |= CDO_CHECK_TYPE; - else - cdi->options &= ~CDO_CHECK_TYPE; - } - mutex_unlock(&cdrom_mutex); -} - -static int cdrom_sysctl_handler(ctl_table *ctl, int write, struct file * filp, - void __user *buffer, size_t *lenp, loff_t *ppos) -{ - int ret; - - ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); - - if (write) { - - /* we only care for 1 or 0. */ - autoclose = !!cdrom_sysctl_settings.autoclose; - autoeject = !!cdrom_sysctl_settings.autoeject; - debug = !!cdrom_sysctl_settings.debug; - lockdoor = !!cdrom_sysctl_settings.lock; - check_media_type = !!cdrom_sysctl_settings.check; - - /* update the option flags according to the changes. we - don't have per device options through sysctl yet, - but we will have and then this will disappear. */ - cdrom_update_settings(); - } - - return ret; -} - -/* Place files in /proc/sys/dev/cdrom */ -static ctl_table cdrom_table[] = { - { - .procname = "info", - .data = &cdrom_sysctl_settings.info, - .maxlen = CDROM_STR_SIZE, - .mode = 0444, - .proc_handler = &cdrom_sysctl_info, - }, - { - .procname = "autoclose", - .data = &cdrom_sysctl_settings.autoclose, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &cdrom_sysctl_handler, - }, - { - .procname = "autoeject", - .data = &cdrom_sysctl_settings.autoeject, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &cdrom_sysctl_handler, - }, - { - .procname = "debug", - .data = &cdrom_sysctl_settings.debug, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &cdrom_sysctl_handler, - }, - { - .procname = "lock", - .data = &cdrom_sysctl_settings.lock, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &cdrom_sysctl_handler, - }, - { - .procname = "check_media", - .data = &cdrom_sysctl_settings.check, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &cdrom_sysctl_handler - }, - { .ctl_name = 0 } -}; - -static ctl_table cdrom_cdrom_table[] = { - { - .ctl_name = DEV_CDROM, - .procname = "cdrom", - .maxlen = 0, - .mode = 0555, - .child = cdrom_table, - }, - { .ctl_name = 0 } -}; - -/* Make sure that /proc/sys/dev is there */ -static ctl_table cdrom_root_table[] = { - { - .ctl_name = CTL_DEV, - .procname = "dev", - .maxlen = 0, - .mode = 0555, - .child = cdrom_cdrom_table, - }, - { .ctl_name = 0 } -}; -static struct ctl_table_header *cdrom_sysctl_header; - -static void cdrom_sysctl_register(void) -{ - static int initialized; - - if (initialized == 1) - return; - - cdrom_sysctl_header = register_sysctl_table(cdrom_root_table); - - /* set the defaults */ - cdrom_sysctl_settings.autoclose = autoclose; - cdrom_sysctl_settings.autoeject = autoeject; - cdrom_sysctl_settings.debug = debug; - cdrom_sysctl_settings.lock = lockdoor; - cdrom_sysctl_settings.check = check_media_type; - - initialized = 1; -} - -static void cdrom_sysctl_unregister(void) -{ - if (cdrom_sysctl_header) - unregister_sysctl_table(cdrom_sysctl_header); -} - -#else /* CONFIG_SYSCTL */ - -static void cdrom_sysctl_register(void) -{ -} - -static void cdrom_sysctl_unregister(void) -{ -} - -#endif /* CONFIG_SYSCTL */ - -static int __init cdrom_init(void) -{ - cdrom_sysctl_register(); - - return 0; -} - -static void __exit cdrom_exit(void) -{ - printk(KERN_INFO "Uniform CD-ROM driver unloaded\n"); - cdrom_sysctl_unregister(); -} - -module_init(cdrom_init); -module_exit(cdrom_exit); -MODULE_LICENSE("GPL"); diff --git a/windhoek/default.ld b/windhoek/default.ld deleted file mode 100644 index f8e4e28d..00000000 --- a/windhoek/default.ld +++ /dev/null @@ -1,213 +0,0 @@ -/* Script for -z combreloc: combine and sort reloc sections */ -OUTPUT_FORMAT("elf32-i386", "elf32-i386", - "elf32-i386") -OUTPUT_ARCH(i386) -ENTRY(_start) -SEARCH_DIR("/usr/i486-gnu/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib"); -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - PROVIDE (__executable_start = 0x08048000); . = 0x08048000 + SIZEOF_HEADERS; - .interp : { *(.interp) } - .note.gnu.build-id : { *(.note.gnu.build-id) } - .hash : { *(.hash) } - .gnu.hash : { *(.gnu.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - .rel.dyn : - { - *(.rel.init) - *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) - *(.rel.fini) - *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) - *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) - *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) - *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) - *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) - *(.rel.ctors) - *(.rel.dtors) - *(.rel.got) - *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) - } - .rela.dyn : - { - *(.rela.init) - *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) - *(.rela.fini) - *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) - *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) - *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) - *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) - *(.rela.ctors) - *(.rela.dtors) - *(.rela.got) - *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) - } - .rel.plt : { *(.rel.plt) } - .rela.plt : { *(.rela.plt) } - .init : - { - KEEP (*(.init)) - } =0x90909090 - .plt : { *(.plt) } - .text : - { - *(.text .stub .text.* .gnu.linkonce.t.*) - KEEP (*(.text.*personality*)) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - } =0x90909090 - .fini : - { - KEEP (*(.fini)) - } =0x90909090 - PROVIDE (__etext = .); - PROVIDE (_etext = .); - PROVIDE (etext = .); - .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } - .rodata1 : { *(.rodata1) } - .eh_frame_hdr : { *(.eh_frame_hdr) } - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. */ - . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); - /* Exception handling */ - .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } - /* Thread Local Storage sections */ - .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } - .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - } - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); - } - .ctors : - { - /* gcc uses crtbegin.o to find the start of - the constructors, so we make sure it is - first. Because this is a wildcard, it - doesn't matter if the user does not - actually link against crtbegin.o; the - linker won't look for a file to match a - wildcard. The wildcard also means that it - doesn't matter which directory crtbegin.o - is in. */ - KEEP (*crtbegin.o(.ctors)) - KEEP (*crtbegin?.o(.ctors)) - /* We don't want to include the .ctor section from - the crtend.o file until after the sorted ctors. - The .ctor section from the crtend file contains the - end of ctors marker and it must be last */ - KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) - - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - - KEEP (*(.mark_beg_l4dde_ctors)) - KEEP (*(SORT(.l4dde_ctors.?))) - KEEP (*(SORT(.l4dde_ctors.??))) - KEEP (*(SORT(.l4dde_ctors.???))) - KEEP (*(SORT(.l4dde_ctors.????))) - KEEP (*(SORT(.l4dde_ctors.?????))) - KEEP (*(.l4dde_ctors)) - KEEP (*(.mark_end_l4dde_ctors)) - } - .dtors : - { - KEEP (*crtbegin.o(.dtors)) - KEEP (*crtbegin?.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - } - .jcr : { KEEP (*(.jcr)) } - .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } - .dynamic : { *(.dynamic) } - .got : { *(.got) } - . = DATA_SEGMENT_RELRO_END (12, .); - .got.plt : { *(.got.plt) } - .data : - { - *(.data .data.* .gnu.linkonce.d.*) - KEEP (*(.gnu.linkonce.d.*personality*)) - SORT(CONSTRUCTORS) - } - .data1 : { *(.data1) } - _edata = .; PROVIDE (edata = .); - __bss_start = .; - .bss : - { - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(COMMON) - /* Align here to ensure that the .bss section occupies space up to - _end. Align after .bss to ensure correct alignment even if the - .bss section disappears because there are no input sections. - FIXME: Why do we need it? When there is no .bss section, we don't - pad the .data section. */ - . = ALIGN(. != 0 ? 32 / 8 : 1); - } - . = ALIGN(32 / 8); - . = ALIGN(32 / 8); - _end = .; PROVIDE (end = .); - . = DATA_SEGMENT_END (.); - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - /* DWARF 3 */ - .debug_pubtypes 0 : { *(.debug_pubtypes) } - .debug_ranges 0 : { *(.debug_ranges) } - .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } - /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) } -} - diff --git a/windhoek/genhd.c b/windhoek/genhd.c deleted file mode 100644 index 30cf03de..00000000 --- a/windhoek/genhd.c +++ /dev/null @@ -1,133 +0,0 @@ -/** - * \file windhoek/server/src/genhd.c - * \brief Windhoek genhd replacement - * - * \date 2008-01-29 - * \author Bjoern Doebel <doebel@tudos.org> - * - * (c) 2008 Technische Universitaet Dresden - * This file is part of DROPS, which is distributed under the terms of the - * GNU General Public License 2. Please see the COPYING file for details. - */ - -#include <linux/genhd.h> -#include <linux/hdreg.h> -#include <linux/ide.h> - -#define MAX_GENDISKS 10 -#define DEBUG_MSG(msg, ...) printk("%s: \033[34m"msg"\033[0m\n", __FUNCTION__, ##__VA_ARGS__) - -/* - * Array for storing all known block devices - */ -struct gendisk *known_disks[MAX_GENDISKS]; - -static void print_gendisk(struct gendisk *gendisk) -{ - struct block_device *bdev = bdget_disk(gendisk, 0); - struct hd_geometry geom; - - DEBUG_MSG("disk: %p (maj %x, min %x, max_min %x)", gendisk, - gendisk->major, gendisk->first_minor, gendisk->minors); - DEBUG_MSG("\tdisk name '%s'", gendisk->disk_name); -// DEBUG_MSG("\tpartitions @ %p, fops @ %p", gendisk->part, gendisk->fops); - DEBUG_MSG("\trq @ %p, privdata @ %p", gendisk->queue, gendisk->private_data); - DEBUG_MSG("\tcapacity %d, flags %x, dev %p", get_capacity(gendisk), gendisk->flags, - gendisk->driverfs_dev); -} - - -void add_disk(struct gendisk *disk) -{ - int i, err; - dev_t devt; - struct block_device *bdev; - - /* minors == 0 indicates to use ext devt from part0 and should - * be accompanied with EXT_DEVT flag. Make sure all - * parameters make sense. - */ - WARN_ON(disk->minors && !(disk->major || disk->first_minor)); - WARN_ON(!disk->minors && !(disk->flags & GENHD_FL_EXT_DEVT)); - - for (i = 0; i < MAX_GENDISKS; ++i) { - if (known_disks[i] == NULL) - break; - } - - print_gendisk(disk); - known_disks[i] = disk; - - disk->flags |= GENHD_FL_UP; - - err = blk_alloc_devt(&disk->part0, &devt); - if (err) { - WARN_ON(1); - return; - } - disk_to_dev(disk)->devt = devt; - - /* ->major and ->first_minor aren't supposed to be - * dereferenced from here on, but set them just in case. - */ - disk->major = MAJOR(devt); - disk->first_minor = MINOR(devt); - -// blk_register_region(disk_devt(disk), disk->minors, NULL, -// exact_match, exact_lock, disk); - blk_register_queue(disk); - - bdev = bdget_disk(disk, 0); - BUG_ON(!bdev); - - bdev->bd_invalidated = 0; - err = blkdev_get(bdev, FMODE_READ); - BUG_ON(err); - //blkdev_put(bdev); -} - - -struct gendisk *get_gendisk(dev_t dev, int *part) -{ - int i; - - // XXX: no partitions - *part = 0; - - for (i = 0; i < MAX_GENDISKS; ++i) { - if (!known_disks[i]) - continue; - - if (MKDEV(known_disks[i]->major, known_disks[i]->first_minor) == dev) - return known_disks[i]; - } - - return NULL; -} - - -struct gendisk* find_disk_by_name(const char* name) -{ - struct gendisk *ret = NULL; - int i; - - for (i = 0; i < MAX_GENDISKS; ++i) { - if (!known_disks[i]) - continue; - - if (!strcmp(known_disks[i]->disk_name, name)) { - ret = known_disks[i]; - break; - } - } - - return ret; -} - - -void gendisk_init() -{ - int i; - for (i = 0; i < MAX_GENDISKS; ++i) - known_disks[i] = NULL; -} diff --git a/windhoek/ide/ide-cd.h b/windhoek/ide/ide-cd.h deleted file mode 100644 index c878bfcf..00000000 --- a/windhoek/ide/ide-cd.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 1996-98 Erik Andersen - * Copyright (C) 1998-2000 Jens Axboe - */ -#ifndef _IDE_CD_H -#define _IDE_CD_H - -#include <linux/cdrom.h> -#include <asm/byteorder.h> - -#define IDECD_DEBUG_LOG 0 - -#if IDECD_DEBUG_LOG -#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args) -#else -#define ide_debug_log(lvl, fmt, args...) do {} while (0) -#endif - -#define ATAPI_WAIT_WRITE_BUSY (10 * HZ) - -/************************************************************************/ - -#define SECTOR_BITS 9 -#ifndef SECTOR_SIZE -#define SECTOR_SIZE (1 << SECTOR_BITS) -#endif -#define SECTORS_PER_FRAME (CD_FRAMESIZE >> SECTOR_BITS) -#define SECTOR_BUFFER_SIZE (CD_FRAMESIZE * 32) - -/* Capabilities Page size including 8 bytes of Mode Page Header */ -#define ATAPI_CAPABILITIES_PAGE_SIZE (8 + 20) -#define ATAPI_CAPABILITIES_PAGE_PAD_SIZE 4 - -/* Structure of a MSF cdrom address. */ -struct atapi_msf { - u8 reserved; - u8 minute; - u8 second; - u8 frame; -}; - -/* Space to hold the disk TOC. */ -#define MAX_TRACKS 99 -struct atapi_toc_header { - unsigned short toc_length; - u8 first_track; - u8 last_track; -}; - -struct atapi_toc_entry { - u8 reserved1; -#if defined(__BIG_ENDIAN_BITFIELD) - u8 adr : 4; - u8 control : 4; -#elif defined(__LITTLE_ENDIAN_BITFIELD) - u8 control : 4; - u8 adr : 4; -#else -#error "Please fix <asm/byteorder.h>" -#endif - u8 track; - u8 reserved2; - union { - unsigned lba; - struct atapi_msf msf; - } addr; -}; - -struct atapi_toc { - int last_session_lba; - int xa_flag; - unsigned long capacity; - struct atapi_toc_header hdr; - struct atapi_toc_entry ent[MAX_TRACKS+1]; - /* One extra for the leadout. */ -}; - -/* Extra per-device info for cdrom drives. */ -struct cdrom_info { - ide_drive_t *drive; - struct ide_driver *driver; - struct gendisk *disk; - struct device dev; - - /* Buffer for table of contents. NULL if we haven't allocated - a TOC buffer for this device yet. */ - - struct atapi_toc *toc; - - /* The result of the last successful request sense command - on this device. */ - struct request_sense sense_data; - - struct request request_sense_request; - - u8 max_speed; /* Max speed of the drive. */ - u8 current_speed; /* Current speed of the drive. */ - - /* Per-device info needed by cdrom.c generic driver. */ - struct cdrom_device_info devinfo; - - unsigned long write_timeout; -}; - -/* ide-cd_verbose.c */ -void ide_cd_log_error(const char *, struct request *, struct request_sense *); - -/* ide-cd.c functions used by ide-cd_ioctl.c */ -int ide_cd_queue_pc(ide_drive_t *, const unsigned char *, int, void *, - unsigned *, struct request_sense *, int, unsigned int); -int ide_cd_read_toc(ide_drive_t *, struct request_sense *); -int ide_cdrom_get_capabilities(ide_drive_t *, u8 *); -void ide_cdrom_update_speed(ide_drive_t *, u8 *); -int cdrom_check_status(ide_drive_t *, struct request_sense *); - -/* ide-cd_ioctl.c */ -int ide_cdrom_open_real(struct cdrom_device_info *, int); -void ide_cdrom_release_real(struct cdrom_device_info *); -int ide_cdrom_drive_status(struct cdrom_device_info *, int); -int ide_cdrom_check_media_change_real(struct cdrom_device_info *, int); -int ide_cdrom_tray_move(struct cdrom_device_info *, int); -int ide_cdrom_lock_door(struct cdrom_device_info *, int); -int ide_cdrom_select_speed(struct cdrom_device_info *, int); -int ide_cdrom_get_last_session(struct cdrom_device_info *, - struct cdrom_multisession *); -int ide_cdrom_get_mcn(struct cdrom_device_info *, struct cdrom_mcn *); -int ide_cdrom_reset(struct cdrom_device_info *cdi); -int ide_cdrom_audio_ioctl(struct cdrom_device_info *, unsigned int, void *); -int ide_cdrom_packet(struct cdrom_device_info *, struct packet_command *); - -#endif /* _IDE_CD_H */ diff --git a/windhoek/ide/ide-disk.c b/windhoek/ide/ide-disk.c deleted file mode 100644 index 24654e93..00000000 --- a/windhoek/ide/ide-disk.c +++ /dev/null @@ -1,750 +0,0 @@ -/* - * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) - * Copyright (C) 1998-2002 Linux ATA Development - * Andre Hedrick <andre@linux-ide.org> - * Copyright (C) 2003 Red Hat - * Copyright (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz - */ - -/* - * Mostly written by Mark Lord <mlord@pobox.com> - * and Gadi Oxman <gadio@netvision.net.il> - * and Andre Hedrick <andre@linux-ide.org> - * - * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c. - */ - -#include <linux/types.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/major.h> -#include <linux/errno.h> -#include <linux/genhd.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/mutex.h> -#include <linux/leds.h> -#include <linux/ide.h> -#include <linux/hdreg.h> - -#include <asm/byteorder.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/div64.h> - -#include "ide-disk.h" - -static const u8 ide_rw_cmds[] = { - ATA_CMD_READ_MULTI, - ATA_CMD_WRITE_MULTI, - ATA_CMD_READ_MULTI_EXT, - ATA_CMD_WRITE_MULTI_EXT, - ATA_CMD_PIO_READ, - ATA_CMD_PIO_WRITE, - ATA_CMD_PIO_READ_EXT, - ATA_CMD_PIO_WRITE_EXT, - ATA_CMD_READ, - ATA_CMD_WRITE, - ATA_CMD_READ_EXT, - ATA_CMD_WRITE_EXT, -}; - -static const u8 ide_data_phases[] = { - TASKFILE_MULTI_IN, - TASKFILE_MULTI_OUT, - TASKFILE_IN, - TASKFILE_OUT, - TASKFILE_IN_DMA, - TASKFILE_OUT_DMA, -}; - -static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma) -{ - u8 index, lba48, write; - - lba48 = (task->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0; - write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0; - - if (dma) - index = 8; - else - index = drive->mult_count ? 0 : 4; - - task->tf.command = ide_rw_cmds[index + lba48 + write]; - - if (dma) - index = 8; /* fixup index */ - - task->data_phase = ide_data_phases[index / 2 + write]; -} - -/* - * __ide_do_rw_disk() issues READ and WRITE commands to a disk, - * using LBA if supported, or CHS otherwise, to address sectors. - */ -static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, - sector_t block) -{ - ide_hwif_t *hwif = drive->hwif; - u16 nsectors = (u16)rq->nr_sectors; - u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48); - u8 dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); - ide_task_t task; - struct ide_taskfile *tf = &task.tf; - ide_startstop_t rc; - - if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) { - if (block + rq->nr_sectors > 1ULL << 28) - dma = 0; - else - lba48 = 0; - } - - if (!dma) { - ide_init_sg_cmd(drive, rq); - ide_map_sg(drive, rq); - } - - memset(&task, 0, sizeof(task)); - task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - - if (drive->dev_flags & IDE_DFLAG_LBA) { - if (lba48) { - pr_debug("%s: LBA=0x%012llx\n", drive->name, - (unsigned long long)block); - - tf->hob_nsect = (nsectors >> 8) & 0xff; - tf->hob_lbal = (u8)(block >> 24); - if (sizeof(block) != 4) { - tf->hob_lbam = (u8)((u64)block >> 32); - tf->hob_lbah = (u8)((u64)block >> 40); - } - - tf->nsect = nsectors & 0xff; - tf->lbal = (u8) block; - tf->lbam = (u8)(block >> 8); - tf->lbah = (u8)(block >> 16); - - task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB); - } else { - tf->nsect = nsectors & 0xff; - tf->lbal = block; - tf->lbam = block >>= 8; - tf->lbah = block >>= 8; - tf->device = (block >> 8) & 0xf; - } - - tf->device |= ATA_LBA; - } else { - unsigned int sect, head, cyl, track; - - track = (int)block / drive->sect; - sect = (int)block % drive->sect + 1; - head = track % drive->head; - cyl = track / drive->head; - - pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect); - - tf->nsect = nsectors & 0xff; - tf->lbal = sect; - tf->lbam = cyl; - tf->lbah = cyl >> 8; - tf->device = head; - } - - if (rq_data_dir(rq)) - task.tf_flags |= IDE_TFLAG_WRITE; - - ide_tf_set_cmd(drive, &task, dma); - if (!dma) - hwif->data_phase = task.data_phase; - task.rq = rq; - - rc = do_rw_taskfile(drive, &task); - - if (rc == ide_stopped && dma) { - /* fallback to PIO */ - task.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK; - ide_tf_set_cmd(drive, &task, 0); - hwif->data_phase = task.data_phase; - ide_init_sg_cmd(drive, rq); - rc = do_rw_taskfile(drive, &task); - } - - return rc; -} - -/* - * 268435455 == 137439 MB or 28bit limit - * 320173056 == 163929 MB or 48bit addressing - * 1073741822 == 549756 MB or 48bit addressing fake drive - */ - -static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq, - sector_t block) -{ - ide_hwif_t *hwif = drive->hwif; - - BUG_ON(drive->dev_flags & IDE_DFLAG_BLOCKED); - - if (!blk_fs_request(rq)) { - blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command"); - ide_end_request(drive, 0, 0); - return ide_stopped; - } - - ledtrig_ide_activity(); - - pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n", - drive->name, rq_data_dir(rq) == READ ? "read" : "writ", - (unsigned long long)block, rq->nr_sectors, - (unsigned long)rq->buffer); - - if (hwif->rw_disk) - hwif->rw_disk(drive, rq); - - return __ide_do_rw_disk(drive, rq, block); -} - -/* - * Queries for true maximum capacity of the drive. - * Returns maximum LBA address (> 0) of the drive, 0 if failed. - */ -static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48) -{ - ide_task_t args; - struct ide_taskfile *tf = &args.tf; - u64 addr = 0; - - /* Create IDE/ATA command request structure */ - memset(&args, 0, sizeof(ide_task_t)); - if (lba48) - tf->command = ATA_CMD_READ_NATIVE_MAX_EXT; - else - tf->command = ATA_CMD_READ_NATIVE_MAX; - tf->device = ATA_LBA; - args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - if (lba48) - args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB); - /* submit command request */ - ide_no_data_taskfile(drive, &args); - - /* if OK, compute maximum address value */ - if ((tf->status & 0x01) == 0) - addr = ide_get_lba_addr(tf, lba48) + 1; - - return addr; -} - -/* - * Sets maximum virtual LBA address of the drive. - * Returns new maximum virtual LBA address (> 0) or 0 on failure. - */ -static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48) -{ - ide_task_t args; - struct ide_taskfile *tf = &args.tf; - u64 addr_set = 0; - - addr_req--; - /* Create IDE/ATA command request structure */ - memset(&args, 0, sizeof(ide_task_t)); - tf->lbal = (addr_req >> 0) & 0xff; - tf->lbam = (addr_req >>= 8) & 0xff; - tf->lbah = (addr_req >>= 8) & 0xff; - if (lba48) { - tf->hob_lbal = (addr_req >>= 8) & 0xff; - tf->hob_lbam = (addr_req >>= 8) & 0xff; - tf->hob_lbah = (addr_req >>= 8) & 0xff; - tf->command = ATA_CMD_SET_MAX_EXT; - } else { - tf->device = (addr_req >>= 8) & 0x0f; - tf->command = ATA_CMD_SET_MAX; - } - tf->device |= ATA_LBA; - args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - if (lba48) - args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB); - /* submit command request */ - ide_no_data_taskfile(drive, &args); - /* if OK, compute maximum address value */ - if ((tf->status & 0x01) == 0) - addr_set = ide_get_lba_addr(tf, lba48) + 1; - - return addr_set; -} - -static unsigned long long sectors_to_MB(unsigned long long n) -{ - n <<= 9; /* make it bytes */ - do_div(n, 1000000); /* make it MB */ - return n; -} - -/* - * Some disks report total number of sectors instead of - * maximum sector address. We list them here. - */ -static const struct drive_list_entry hpa_list[] = { - { "ST340823A", NULL }, - { "ST320413A", NULL }, - { "ST310211A", NULL }, - { NULL, NULL } -}; - -static void idedisk_check_hpa(ide_drive_t *drive) -{ - unsigned long long capacity, set_max; - int lba48 = ata_id_lba48_enabled(drive->id); - - capacity = drive->capacity64; - - set_max = idedisk_read_native_max_address(drive, lba48); - - if (ide_in_drive_list(drive->id, hpa_list)) { - /* - * Since we are inclusive wrt to firmware revisions do this - * extra check and apply the workaround only when needed. - */ - if (set_max == capacity + 1) - set_max--; - } - - if (set_max <= capacity) - return; - - printk(KERN_INFO "%s: Host Protected Area detected.\n" - "\tcurrent capacity is %llu sectors (%llu MB)\n" - "\tnative capacity is %llu sectors (%llu MB)\n", - drive->name, - capacity, sectors_to_MB(capacity), - set_max, sectors_to_MB(set_max)); - - set_max = idedisk_set_max_address(drive, set_max, lba48); - - if (set_max) { - drive->capacity64 = set_max; - printk(KERN_INFO "%s: Host Protected Area disabled.\n", - drive->name); - } -} - -static int ide_disk_get_capacity(ide_drive_t *drive) -{ - u16 *id = drive->id; - int lba; - - if (ata_id_lba48_enabled(id)) { - /* drive speaks 48-bit LBA */ - lba = 1; - drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2); - } else if (ata_id_has_lba(id) && ata_id_is_lba_capacity_ok(id)) { - /* drive speaks 28-bit LBA */ - lba = 1; - drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY); - } else { - /* drive speaks boring old 28-bit CHS */ - lba = 0; - drive->capacity64 = drive->cyl * drive->head * drive->sect; - } - - if (lba) { - drive->dev_flags |= IDE_DFLAG_LBA; - - /* - * If this device supports the Host Protected Area feature set, - * then we may need to change our opinion about its capacity. - */ - if (ata_id_hpa_enabled(id)) - idedisk_check_hpa(drive); - } - - /* limit drive capacity to 137GB if LBA48 cannot be used */ - if ((drive->dev_flags & IDE_DFLAG_LBA48) == 0 && - drive->capacity64 > 1ULL << 28) { - printk(KERN_WARNING "%s: cannot use LBA48 - full capacity " - "%llu sectors (%llu MB)\n", - drive->name, (unsigned long long)drive->capacity64, - sectors_to_MB(drive->capacity64)); - drive->capacity64 = 1ULL << 28; - } - - if ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && - (drive->dev_flags & IDE_DFLAG_LBA48)) { - if (drive->capacity64 > 1ULL << 28) { - printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode" - " will be used for accessing sectors " - "> %u\n", drive->name, 1 << 28); - } else - drive->dev_flags &= ~IDE_DFLAG_LBA48; - } - - return 0; -} - -static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) -{ - ide_drive_t *drive = q->queuedata; - ide_task_t *task = kmalloc(sizeof(*task), GFP_ATOMIC); - - /* FIXME: map struct ide_taskfile on rq->cmd[] */ - BUG_ON(task == NULL); - - memset(task, 0, sizeof(*task)); - if (ata_id_flush_ext_enabled(drive->id) && - (drive->capacity64 >= (1UL << 28))) - task->tf.command = ATA_CMD_FLUSH_EXT; - else - task->tf.command = ATA_CMD_FLUSH; - task->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE | - IDE_TFLAG_DYN; - task->data_phase = TASKFILE_NO_DATA; - - rq->cmd_type = REQ_TYPE_ATA_TASKFILE; - rq->cmd_flags |= REQ_SOFTBARRIER; - rq->special = task; -} - -ide_devset_get(multcount, mult_count); - -/* - * This is tightly woven into the driver->do_special can not touch. - * DON'T do it again until a total personality rewrite is committed. - */ -static int set_multcount(ide_drive_t *drive, int arg) -{ - struct request *rq; - int error; - - if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff)) - return -EINVAL; - - if (drive->special.b.set_multmode) - return -EBUSY; - - rq = blk_get_request(drive->queue, READ, __GFP_WAIT); - rq->cmd_type = REQ_TYPE_ATA_TASKFILE; - - drive->mult_req = arg; - drive->special.b.set_multmode = 1; - error = blk_execute_rq(drive->queue, NULL, rq, 0); - blk_put_request(rq); - - return (drive->mult_count == arg) ? 0 : -EIO; -} - -ide_devset_get_flag(nowerr, IDE_DFLAG_NOWERR); - -static int set_nowerr(ide_drive_t *drive, int arg) -{ - if (arg < 0 || arg > 1) - return -EINVAL; - - if (arg) - drive->dev_flags |= IDE_DFLAG_NOWERR; - else - drive->dev_flags &= ~IDE_DFLAG_NOWERR; - - drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT; - - return 0; -} - -static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect) -{ - ide_task_t task; - - memset(&task, 0, sizeof(task)); - task.tf.feature = feature; - task.tf.nsect = nsect; - task.tf.command = ATA_CMD_SET_FEATURES; - task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - - return ide_no_data_taskfile(drive, &task); -} - -static void update_ordered(ide_drive_t *drive) -{ - u16 *id = drive->id; - unsigned ordered = QUEUE_ORDERED_NONE; - prepare_flush_fn *prep_fn = NULL; - - if (drive->dev_flags & IDE_DFLAG_WCACHE) { - unsigned long long capacity; - int barrier; - /* - * We must avoid issuing commands a drive does not - * understand or we may crash it. We check flush cache - * is supported. We also check we have the LBA48 flush - * cache if the drive capacity is too large. By this - * time we have trimmed the drive capacity if LBA48 is - * not available so we don't need to recheck that. - */ - capacity = ide_gd_capacity(drive); - barrier = ata_id_flush_enabled(id) && - (drive->dev_flags & IDE_DFLAG_NOFLUSH) == 0 && - ((drive->dev_flags & IDE_DFLAG_LBA48) == 0 || - capacity <= (1ULL << 28) || - ata_id_flush_ext_enabled(id)); - - printk(KERN_INFO "%s: cache flushes %ssupported\n", - drive->name, barrier ? "" : "not "); - - if (barrier) { - ordered = QUEUE_ORDERED_DRAIN_FLUSH; - prep_fn = idedisk_prepare_flush; - } - } else - ordered = QUEUE_ORDERED_DRAIN; - - blk_queue_ordered(drive->queue, ordered, prep_fn); -} - -ide_devset_get_flag(wcache, IDE_DFLAG_WCACHE); - -static int set_wcache(ide_drive_t *drive, int arg) -{ - int err = 1; - - if (arg < 0 || arg > 1) - return -EINVAL; - - if (ata_id_flush_enabled(drive->id)) { - err = ide_do_setfeature(drive, - arg ? SETFEATURES_WC_ON : SETFEATURES_WC_OFF, 0); - if (err == 0) { - if (arg) - drive->dev_flags |= IDE_DFLAG_WCACHE; - else - drive->dev_flags &= ~IDE_DFLAG_WCACHE; - } - } - - update_ordered(drive); - - return err; -} - -static int do_idedisk_flushcache(ide_drive_t *drive) -{ - ide_task_t args; - - memset(&args, 0, sizeof(ide_task_t)); - if (ata_id_flush_ext_enabled(drive->id)) - args.tf.command = ATA_CMD_FLUSH_EXT; - else - args.tf.command = ATA_CMD_FLUSH; - args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - return ide_no_data_taskfile(drive, &args); -} - -ide_devset_get(acoustic, acoustic); - -static int set_acoustic(ide_drive_t *drive, int arg) -{ - if (arg < 0 || arg > 254) - return -EINVAL; - - ide_do_setfeature(drive, - arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF, arg); - - drive->acoustic = arg; - - return 0; -} - -ide_devset_get_flag(addressing, IDE_DFLAG_LBA48); - -/* - * drive->addressing: - * 0: 28-bit - * 1: 48-bit - * 2: 48-bit capable doing 28-bit - */ -static int set_addressing(ide_drive_t *drive, int arg) -{ - if (arg < 0 || arg > 2) - return -EINVAL; - - if (arg && ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48) || - ata_id_lba48_enabled(drive->id) == 0)) - return -EIO; - - if (arg == 2) - arg = 0; - - if (arg) - drive->dev_flags |= IDE_DFLAG_LBA48; - else - drive->dev_flags &= ~IDE_DFLAG_LBA48; - - return 0; -} - -ide_ext_devset_rw(acoustic, acoustic); -ide_ext_devset_rw(address, addressing); -ide_ext_devset_rw(multcount, multcount); -ide_ext_devset_rw(wcache, wcache); - -ide_ext_devset_rw_sync(nowerr, nowerr); - -static int ide_disk_check(ide_drive_t *drive, const char *s) -{ - return 1; -} - -static void ide_disk_setup(ide_drive_t *drive) -{ - struct ide_disk_obj *idkp = drive->driver_data; - struct request_queue *q = drive->queue; - ide_hwif_t *hwif = drive->hwif; - u16 *id = drive->id; - char *m = (char *)&id[ATA_ID_PROD]; - unsigned long long capacity; - - ide_proc_register_driver(drive, idkp->driver); - - if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) - return; - - if (drive->dev_flags & IDE_DFLAG_REMOVABLE) { - /* - * Removable disks (eg. SYQUEST); ignore 'WD' drives - */ - if (m[0] != 'W' || m[1] != 'D') - drive->dev_flags |= IDE_DFLAG_DOORLOCKING; - } - - (void)set_addressing(drive, 1); - - if (drive->dev_flags & IDE_DFLAG_LBA48) { - int max_s = 2048; - - if (max_s > hwif->rqsize) - max_s = hwif->rqsize; - - blk_queue_max_sectors(q, max_s); - } - - printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, - q->max_sectors / 2); - - if (ata_id_is_ssd(id)) - queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); - - /* calculate drive capacity, and select LBA if possible */ - ide_disk_get_capacity(drive); - - /* - * if possible, give fdisk access to more of the drive, - * by correcting bios_cyls: - */ - capacity = ide_gd_capacity(drive); - - if ((drive->dev_flags & IDE_DFLAG_FORCED_GEOM) == 0) { - if (ata_id_lba48_enabled(drive->id)) { - /* compatibility */ - drive->bios_sect = 63; - drive->bios_head = 255; - } - - if (drive->bios_sect && drive->bios_head) { - unsigned int cap0 = capacity; /* truncate to 32 bits */ - unsigned int cylsz, cyl; - - if (cap0 != capacity) - drive->bios_cyl = 65535; - else { - cylsz = drive->bios_sect * drive->bios_head; - cyl = cap0 / cylsz; - if (cyl > 65535) - cyl = 65535; - if (cyl > drive->bios_cyl) - drive->bios_cyl = cyl; - } - } - } - printk(KERN_INFO "%s: %llu sectors (%llu MB)", - drive->name, capacity, sectors_to_MB(capacity)); - - /* Only print cache size when it was specified */ - if (id[ATA_ID_BUF_SIZE]) - printk(KERN_CONT " w/%dKiB Cache", id[ATA_ID_BUF_SIZE] / 2); - - printk(KERN_CONT ", CHS=%d/%d/%d\n", - drive->bios_cyl, drive->bios_head, drive->bios_sect); - - /* write cache enabled? */ - if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id)) - drive->dev_flags |= IDE_DFLAG_WCACHE; - - set_wcache(drive, 1); - - if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 && - (drive->head == 0 || drive->head > 16)) { - printk(KERN_ERR "%s: invalid geometry: %d physical heads?\n", - drive->name, drive->head); - drive->dev_flags &= ~IDE_DFLAG_ATTACH; - } else - drive->dev_flags |= IDE_DFLAG_ATTACH; -} - -static void ide_disk_flush(ide_drive_t *drive) -{ - if (ata_id_flush_enabled(drive->id) == 0 || - (drive->dev_flags & IDE_DFLAG_WCACHE) == 0) - return; - - if (do_idedisk_flushcache(drive)) - printk(KERN_INFO "%s: wcache flush failed!\n", drive->name); -} - -static int ide_disk_init_media(ide_drive_t *drive, struct gendisk *disk) -{ - return 0; -} - -static int ide_disk_set_doorlock(ide_drive_t *drive, struct gendisk *disk, - int on) -{ - ide_task_t task; - int ret; - - if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) == 0) - return 0; - - memset(&task, 0, sizeof(task)); - task.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK; - task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - - ret = ide_no_data_taskfile(drive, &task); - - if (ret) - drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING; - - return ret; -} - -#ifdef DDE_LINUX -int ide_disk_ioctl(ide_drive_t *drive, struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) -{ - return 0; -} -#endif - -const struct ide_disk_ops ide_ata_disk_ops = { - .check = ide_disk_check, - .get_capacity = ide_disk_get_capacity, - .setup = ide_disk_setup, - .flush = ide_disk_flush, - .init_media = ide_disk_init_media, - .set_doorlock = ide_disk_set_doorlock, - .do_request = ide_do_rw_disk, - .end_request = ide_end_request, - .ioctl = ide_disk_ioctl, -}; diff --git a/windhoek/ide/ide-disk.h b/windhoek/ide/ide-disk.h deleted file mode 100644 index 326a12ff..00000000 --- a/windhoek/ide/ide-disk.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __IDE_DISK_H -#define __IDE_DISK_H - -#include "ide-gd.h" -#include "local.h" - -#ifdef CONFIG_IDE_GD_ATA -/* ide-disk.c */ -extern const struct ide_disk_ops ide_ata_disk_ops; -ide_decl_devset(address); -ide_decl_devset(multcount); -ide_decl_devset(nowerr); -ide_decl_devset(wcache); -ide_decl_devset(acoustic); - -/* ide-disk_ioctl.c */ -int ide_disk_ioctl(ide_drive_t *, struct block_device *, fmode_t, unsigned int, - unsigned long); - -#ifdef CONFIG_IDE_PROC_FS -/* ide-disk_proc.c */ -extern ide_proc_entry_t ide_disk_proc[]; -extern const struct ide_proc_devset ide_disk_settings[]; -#endif -#else -#define ide_disk_proc NULL -#define ide_disk_settings NULL -#endif - -#endif /* __IDE_DISK_H */ diff --git a/windhoek/ide/ide-dma.c b/windhoek/ide/ide-dma.c deleted file mode 100644 index 059c90bb..00000000 --- a/windhoek/ide/ide-dma.c +++ /dev/null @@ -1,507 +0,0 @@ -/* - * IDE DMA support (including IDE PCI BM-DMA). - * - * Copyright (C) 1995-1998 Mark Lord - * Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org> - * Copyright (C) 2004, 2007 Bartlomiej Zolnierkiewicz - * - * May be copied or modified under the terms of the GNU General Public License - * - * DMA is supported for all IDE devices (disk drives, cdroms, tapes, floppies). - */ - -/* - * Special Thanks to Mark for his Six years of work. - */ - -/* - * Thanks to "Christopher J. Reimer" <reimer@doe.carleton.ca> for - * fixing the problem with the BIOS on some Acer motherboards. - * - * Thanks to "Benoit Poulot-Cazajous" <poulot@chorus.fr> for testing - * "TX" chipset compatibility and for providing patches for the "TX" chipset. - * - * Thanks to Christian Brunner <chb@muc.de> for taking a good first crack - * at generic DMA -- his patches were referred to when preparing this code. - * - * Most importantly, thanks to Robert Bringman <rob@mars.trion.com> - * for supplying a Promise UDMA board & WD UDMA drive for this work! - */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/ide.h> -#include <linux/scatterlist.h> -#include <linux/dma-mapping.h> - -static const struct drive_list_entry drive_whitelist[] = { - { "Micropolis 2112A" , NULL }, - { "CONNER CTMA 4000" , NULL }, - { "CONNER CTT8000-A" , NULL }, - { "ST34342A" , NULL }, - { NULL , NULL } -}; - -static const struct drive_list_entry drive_blacklist[] = { - { "WDC AC11000H" , NULL }, - { "WDC AC22100H" , NULL }, - { "WDC AC32500H" , NULL }, - { "WDC AC33100H" , NULL }, - { "WDC AC31600H" , NULL }, - { "WDC AC32100H" , "24.09P07" }, - { "WDC AC23200L" , "21.10N21" }, - { "Compaq CRD-8241B" , NULL }, - { "CRD-8400B" , NULL }, - { "CRD-8480B", NULL }, - { "CRD-8482B", NULL }, - { "CRD-84" , NULL }, - { "SanDisk SDP3B" , NULL }, - { "SanDisk SDP3B-64" , NULL }, - { "SANYO CD-ROM CRD" , NULL }, - { "HITACHI CDR-8" , NULL }, - { "HITACHI CDR-8335" , NULL }, - { "HITACHI CDR-8435" , NULL }, - { "Toshiba CD-ROM XM-6202B" , NULL }, - { "TOSHIBA CD-ROM XM-1702BC", NULL }, - { "CD-532E-A" , NULL }, - { "E-IDE CD-ROM CR-840", NULL }, - { "CD-ROM Drive/F5A", NULL }, - { "WPI CDD-820", NULL }, - { "SAMSUNG CD-ROM SC-148C", NULL }, - { "SAMSUNG CD-ROM SC", NULL }, - { "ATAPI CD-ROM DRIVE 40X MAXIMUM", NULL }, - { "_NEC DV5800A", NULL }, - { "SAMSUNG CD-ROM SN-124", "N001" }, - { "Seagate STT20000A", NULL }, - { "CD-ROM CDR_U200", "1.09" }, - { NULL , NULL } - -}; - -/** - * ide_dma_intr - IDE DMA interrupt handler - * @drive: the drive the interrupt is for - * - * Handle an interrupt completing a read/write DMA transfer on an - * IDE device - */ - -ide_startstop_t ide_dma_intr(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - u8 stat = 0, dma_stat = 0; - - dma_stat = hwif->dma_ops->dma_end(drive); - stat = hwif->tp_ops->read_status(hwif); - - if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | ATA_DRQ)) { - if (!dma_stat) { - struct request *rq = hwif->rq; - - task_end_request(drive, rq, stat); - return ide_stopped; - } - printk(KERN_ERR "%s: %s: bad DMA status (0x%02x)\n", - drive->name, __func__, dma_stat); - } - return ide_error(drive, "dma_intr", stat); -} -EXPORT_SYMBOL_GPL(ide_dma_intr); - -int ide_dma_good_drive(ide_drive_t *drive) -{ - return ide_in_drive_list(drive->id, drive_whitelist); -} - -/** - * ide_build_sglist - map IDE scatter gather for DMA I/O - * @drive: the drive to build the DMA table for - * @rq: the request holding the sg list - * - * Perform the DMA mapping magic necessary to access the source or - * target buffers of a request via DMA. The lower layers of the - * kernel provide the necessary cache management so that we can - * operate in a portable fashion. - */ - -int ide_build_sglist(ide_drive_t *drive, struct request *rq) -{ - ide_hwif_t *hwif = drive->hwif; - struct scatterlist *sg = hwif->sg_table; - int i; - - ide_map_sg(drive, rq); - - if (rq_data_dir(rq) == READ) - hwif->sg_dma_direction = DMA_FROM_DEVICE; - else - hwif->sg_dma_direction = DMA_TO_DEVICE; - - i = dma_map_sg(hwif->dev, sg, hwif->sg_nents, hwif->sg_dma_direction); - if (i) { - hwif->orig_sg_nents = hwif->sg_nents; - hwif->sg_nents = i; - } - - return i; -} -EXPORT_SYMBOL_GPL(ide_build_sglist); - -/** - * ide_destroy_dmatable - clean up DMA mapping - * @drive: The drive to unmap - * - * Teardown mappings after DMA has completed. This must be called - * after the completion of each use of ide_build_dmatable and before - * the next use of ide_build_dmatable. Failure to do so will cause - * an oops as only one mapping can be live for each target at a given - * time. - */ - -void ide_destroy_dmatable(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - - dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->orig_sg_nents, - hwif->sg_dma_direction); -} -EXPORT_SYMBOL_GPL(ide_destroy_dmatable); - -/** - * ide_dma_off_quietly - Generic DMA kill - * @drive: drive to control - * - * Turn off the current DMA on this IDE controller. - */ - -void ide_dma_off_quietly(ide_drive_t *drive) -{ - drive->dev_flags &= ~IDE_DFLAG_USING_DMA; - ide_toggle_bounce(drive, 0); - - drive->hwif->dma_ops->dma_host_set(drive, 0); -} -EXPORT_SYMBOL(ide_dma_off_quietly); - -/** - * ide_dma_off - disable DMA on a device - * @drive: drive to disable DMA on - * - * Disable IDE DMA for a device on this IDE controller. - * Inform the user that DMA has been disabled. - */ - -void ide_dma_off(ide_drive_t *drive) -{ - printk(KERN_INFO "%s: DMA disabled\n", drive->name); - ide_dma_off_quietly(drive); -} -EXPORT_SYMBOL(ide_dma_off); - -/** - * ide_dma_on - Enable DMA on a device - * @drive: drive to enable DMA on - * - * Enable IDE DMA for a device on this IDE controller. - */ - -void ide_dma_on(ide_drive_t *drive) -{ - drive->dev_flags |= IDE_DFLAG_USING_DMA; - ide_toggle_bounce(drive, 1); - - drive->hwif->dma_ops->dma_host_set(drive, 1); -} - -int __ide_dma_bad_drive(ide_drive_t *drive) -{ - u16 *id = drive->id; - - int blacklist = ide_in_drive_list(id, drive_blacklist); - if (blacklist) { - printk(KERN_WARNING "%s: Disabling (U)DMA for %s (blacklisted)\n", - drive->name, (char *)&id[ATA_ID_PROD]); - return blacklist; - } - return 0; -} -EXPORT_SYMBOL(__ide_dma_bad_drive); - -static const u8 xfer_mode_bases[] = { - XFER_UDMA_0, - XFER_MW_DMA_0, - XFER_SW_DMA_0, -}; - -static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode) -{ - u16 *id = drive->id; - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - unsigned int mask = 0; - - switch (base) { - case XFER_UDMA_0: - if ((id[ATA_ID_FIELD_VALID] & 4) == 0) - break; - - if (port_ops && port_ops->udma_filter) - mask = port_ops->udma_filter(drive); - else - mask = hwif->ultra_mask; - mask &= id[ATA_ID_UDMA_MODES]; - - /* - * avoid false cable warning from eighty_ninty_three() - */ - if (req_mode > XFER_UDMA_2) { - if ((mask & 0x78) && (eighty_ninty_three(drive) == 0)) - mask &= 0x07; - } - break; - case XFER_MW_DMA_0: - if ((id[ATA_ID_FIELD_VALID] & 2) == 0) - break; - if (port_ops && port_ops->mdma_filter) - mask = port_ops->mdma_filter(drive); - else - mask = hwif->mwdma_mask; - mask &= id[ATA_ID_MWDMA_MODES]; - break; - case XFER_SW_DMA_0: - if (id[ATA_ID_FIELD_VALID] & 2) { - mask = id[ATA_ID_SWDMA_MODES] & hwif->swdma_mask; - } else if (id[ATA_ID_OLD_DMA_MODES] >> 8) { - u8 mode = id[ATA_ID_OLD_DMA_MODES] >> 8; - - /* - * if the mode is valid convert it to the mask - * (the maximum allowed mode is XFER_SW_DMA_2) - */ - if (mode <= 2) - mask = ((2 << mode) - 1) & hwif->swdma_mask; - } - break; - default: - BUG(); - break; - } - - return mask; -} - -/** - * ide_find_dma_mode - compute DMA speed - * @drive: IDE device - * @req_mode: requested mode - * - * Checks the drive/host capabilities and finds the speed to use for - * the DMA transfer. The speed is then limited by the requested mode. - * - * Returns 0 if the drive/host combination is incapable of DMA transfers - * or if the requested mode is not a DMA mode. - */ - -u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode) -{ - ide_hwif_t *hwif = drive->hwif; - unsigned int mask; - int x, i; - u8 mode = 0; - - if (drive->media != ide_disk) { - if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA) - return 0; - } - - for (i = 0; i < ARRAY_SIZE(xfer_mode_bases); i++) { - if (req_mode < xfer_mode_bases[i]) - continue; - mask = ide_get_mode_mask(drive, xfer_mode_bases[i], req_mode); - x = fls(mask) - 1; - if (x >= 0) { - mode = xfer_mode_bases[i] + x; - break; - } - } - - if (hwif->chipset == ide_acorn && mode == 0) { - /* - * is this correct? - */ - if (ide_dma_good_drive(drive) && - drive->id[ATA_ID_EIDE_DMA_TIME] < 150) - mode = XFER_MW_DMA_1; - } - - mode = min(mode, req_mode); - - printk(KERN_INFO "%s: %s mode selected\n", drive->name, - mode ? ide_xfer_verbose(mode) : "no DMA"); - - return mode; -} -EXPORT_SYMBOL_GPL(ide_find_dma_mode); - -static int ide_tune_dma(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - u8 speed; - - if (ata_id_has_dma(drive->id) == 0 || - (drive->dev_flags & IDE_DFLAG_NODMA)) - return 0; - - /* consult the list of known "bad" drives */ - if (__ide_dma_bad_drive(drive)) - return 0; - - if (ide_id_dma_bug(drive)) - return 0; - - if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA) - return config_drive_for_dma(drive); - - speed = ide_max_dma_mode(drive); - - if (!speed) - return 0; - - if (ide_set_dma_mode(drive, speed)) - return 0; - - return 1; -} - -static int ide_dma_check(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - - if (ide_tune_dma(drive)) - return 0; - - /* TODO: always do PIO fallback */ - if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA) - return -1; - - ide_set_max_pio(drive); - - return -1; -} - -int ide_id_dma_bug(ide_drive_t *drive) -{ - u16 *id = drive->id; - - if (id[ATA_ID_FIELD_VALID] & 4) { - if ((id[ATA_ID_UDMA_MODES] >> 8) && - (id[ATA_ID_MWDMA_MODES] >> 8)) - goto err_out; - } else if (id[ATA_ID_FIELD_VALID] & 2) { - if ((id[ATA_ID_MWDMA_MODES] >> 8) && - (id[ATA_ID_SWDMA_MODES] >> 8)) - goto err_out; - } - return 0; -err_out: - printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name); - return 1; -} - -int ide_set_dma(ide_drive_t *drive) -{ - int rc; - - /* - * Force DMAing for the beginning of the check. - * Some chipsets appear to do interesting - * things, if not checked and cleared. - * PARANOIA!!! - */ - ide_dma_off_quietly(drive); - - rc = ide_dma_check(drive); - if (rc) - return rc; - - ide_dma_on(drive); - - return 0; -} - -void ide_check_dma_crc(ide_drive_t *drive) -{ - u8 mode; - - ide_dma_off_quietly(drive); - drive->crc_count = 0; - mode = drive->current_speed; - /* - * Don't try non Ultra-DMA modes without iCRC's. Force the - * device to PIO and make the user enable SWDMA/MWDMA modes. - */ - if (mode > XFER_UDMA_0 && mode <= XFER_UDMA_7) - mode--; - else - mode = XFER_PIO_4; - ide_set_xfer_rate(drive, mode); - if (drive->current_speed >= XFER_SW_DMA_0) - ide_dma_on(drive); -} - -void ide_dma_lost_irq(ide_drive_t *drive) -{ - printk(KERN_ERR "%s: DMA interrupt recovery\n", drive->name); -} -EXPORT_SYMBOL_GPL(ide_dma_lost_irq); - -void ide_dma_timeout(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - - printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name); - - if (hwif->dma_ops->dma_test_irq(drive)) - return; - - ide_dump_status(drive, "DMA timeout", hwif->tp_ops->read_status(hwif)); - - hwif->dma_ops->dma_end(drive); -} -EXPORT_SYMBOL_GPL(ide_dma_timeout); - -void ide_release_dma_engine(ide_hwif_t *hwif) -{ - if (hwif->dmatable_cpu) { - int prd_size = hwif->prd_max_nents * hwif->prd_ent_size; - - dma_free_coherent(hwif->dev, prd_size, - hwif->dmatable_cpu, hwif->dmatable_dma); - hwif->dmatable_cpu = NULL; - } -} -EXPORT_SYMBOL_GPL(ide_release_dma_engine); - -int ide_allocate_dma_engine(ide_hwif_t *hwif) -{ - int prd_size; - - if (hwif->prd_max_nents == 0) - hwif->prd_max_nents = PRD_ENTRIES; - if (hwif->prd_ent_size == 0) - hwif->prd_ent_size = PRD_BYTES; - - prd_size = hwif->prd_max_nents * hwif->prd_ent_size; - - hwif->dmatable_cpu = dma_alloc_coherent(hwif->dev, prd_size, - &hwif->dmatable_dma, - GFP_ATOMIC); - if (hwif->dmatable_cpu == NULL) { - printk(KERN_ERR "%s: unable to allocate PRD table\n", - hwif->name); - return -ENOMEM; - } - - return 0; -} -EXPORT_SYMBOL_GPL(ide_allocate_dma_engine); diff --git a/windhoek/ide/ide-floppy.h b/windhoek/ide/ide-floppy.h deleted file mode 100644 index 6dd2beb4..00000000 --- a/windhoek/ide/ide-floppy.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef __IDE_FLOPPY_H -#define __IDE_FLOPPY_H - -#include "ide-gd.h" - -#ifdef CONFIG_IDE_GD_ATAPI -/* - * Pages of the SELECT SENSE / MODE SENSE packet commands. - * See SFF-8070i spec. - */ -#define IDEFLOPPY_CAPABILITIES_PAGE 0x1b -#define IDEFLOPPY_FLEXIBLE_DISK_PAGE 0x05 - -/* IOCTLs used in low-level formatting. */ -#define IDEFLOPPY_IOCTL_FORMAT_SUPPORTED 0x4600 -#define IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY 0x4601 -#define IDEFLOPPY_IOCTL_FORMAT_START 0x4602 -#define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603 - -/* ide-floppy.c */ -extern const struct ide_disk_ops ide_atapi_disk_ops; -void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *, u8); -void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *); - -/* ide-floppy_ioctl.c */ -int ide_floppy_ioctl(ide_drive_t *, struct block_device *, fmode_t, - unsigned int, unsigned long); - -#ifdef CONFIG_IDE_PROC_FS -/* ide-floppy_proc.c */ -extern ide_proc_entry_t ide_floppy_proc[]; -extern const struct ide_proc_devset ide_floppy_settings[]; -#endif -#else -#define ide_floppy_proc NULL -#define ide_floppy_settings NULL -#endif - -#endif /*__IDE_FLOPPY_H */ diff --git a/windhoek/ide/ide-gd.c b/windhoek/ide/ide-gd.c deleted file mode 100644 index 275ed3bf..00000000 --- a/windhoek/ide/ide-gd.c +++ /dev/null @@ -1,409 +0,0 @@ -#include <linux/module.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/genhd.h> -#include <linux/mutex.h> -#include <linux/ide.h> -#include <linux/hdreg.h> - -#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) -#define IDE_DISK_MINORS (1 << PARTN_BITS) -#else -#define IDE_DISK_MINORS 0 -#endif - -#include "ide-disk.h" -#include "ide-floppy.h" -#include "local.h" - -#define IDE_GD_VERSION "1.18" - -/* module parameters */ -static unsigned long debug_mask; -module_param(debug_mask, ulong, 0644); - -static DEFINE_MUTEX(ide_disk_ref_mutex); - -static void ide_disk_release(struct device *); - -static struct ide_disk_obj *ide_disk_get(struct gendisk *disk) -{ - struct ide_disk_obj *idkp = NULL; - - mutex_lock(&ide_disk_ref_mutex); - idkp = ide_drv_g(disk, ide_disk_obj); - if (idkp) { - if (ide_device_get(idkp->drive)) - idkp = NULL; - else - get_device(&idkp->dev); - } - mutex_unlock(&ide_disk_ref_mutex); - return idkp; -} - -static void ide_disk_put(struct ide_disk_obj *idkp) -{ - ide_drive_t *drive = idkp->drive; - - mutex_lock(&ide_disk_ref_mutex); - put_device(&idkp->dev); - ide_device_put(drive); - mutex_unlock(&ide_disk_ref_mutex); -} - -sector_t ide_gd_capacity(ide_drive_t *drive) -{ - return drive->capacity64; -} - -static int ide_gd_probe(ide_drive_t *); - -static void ide_gd_remove(ide_drive_t *drive) -{ - struct ide_disk_obj *idkp = drive->driver_data; - struct gendisk *g = idkp->disk; - - ide_proc_unregister_driver(drive, idkp->driver); - device_del(&idkp->dev); - del_gendisk(g); - drive->disk_ops->flush(drive); - - mutex_lock(&ide_disk_ref_mutex); - put_device(&idkp->dev); - mutex_unlock(&ide_disk_ref_mutex); -} - -static void ide_disk_release(struct device *dev) -{ - struct ide_disk_obj *idkp = to_ide_drv(dev, ide_disk_obj); - ide_drive_t *drive = idkp->drive; - struct gendisk *g = idkp->disk; - - drive->disk_ops = NULL; - drive->driver_data = NULL; - g->private_data = NULL; - put_disk(g); - kfree(idkp); -} - -/* - * On HPA drives the capacity needs to be - * reinitilized on resume otherwise the disk - * can not be used and a hard reset is required - */ -static void ide_gd_resume(ide_drive_t *drive) -{ - if (ata_id_hpa_enabled(drive->id)) - (void)drive->disk_ops->get_capacity(drive); -} - -static void ide_gd_shutdown(ide_drive_t *drive) -{ -#ifdef CONFIG_ALPHA - /* On Alpha, halt(8) doesn't actually turn the machine off, - it puts you into the sort of firmware monitor. Typically, - it's used to boot another kernel image, so it's not much - different from reboot(8). Therefore, we don't need to - spin down the disk in this case, especially since Alpha - firmware doesn't handle disks in standby mode properly. - On the other hand, it's reasonably safe to turn the power - off when the shutdown process reaches the firmware prompt, - as the firmware initialization takes rather long time - - at least 10 seconds, which should be sufficient for - the disk to expire its write cache. */ - if (system_state != SYSTEM_POWER_OFF) { -#else - if (system_state == SYSTEM_RESTART) { -#endif - drive->disk_ops->flush(drive); - return; - } - - printk(KERN_INFO "Shutdown: %s\n", drive->name); - - drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND); -} - -#ifdef CONFIG_IDE_PROC_FS -static ide_proc_entry_t *ide_disk_proc_entries(ide_drive_t *drive) -{ - return (drive->media == ide_disk) ? ide_disk_proc : ide_floppy_proc; -} - -static const struct ide_proc_devset *ide_disk_proc_devsets(ide_drive_t *drive) -{ - return (drive->media == ide_disk) ? ide_disk_settings - : ide_floppy_settings; -} -#endif - -static ide_startstop_t ide_gd_do_request(ide_drive_t *drive, - struct request *rq, sector_t sector) -{ - return drive->disk_ops->do_request(drive, rq, sector); -} - -static int ide_gd_end_request(ide_drive_t *drive, int uptodate, int nrsecs) -{ - return drive->disk_ops->end_request(drive, uptodate, nrsecs); -} - -static struct ide_driver ide_gd_driver = { - .gen_driver = { - .owner = THIS_MODULE, - .name = "ide-gd", - .bus = &ide_bus_type, - }, - .probe = ide_gd_probe, - .remove = ide_gd_remove, - .resume = ide_gd_resume, - .shutdown = ide_gd_shutdown, - .version = IDE_GD_VERSION, - .do_request = ide_gd_do_request, - .end_request = ide_gd_end_request, -#ifdef CONFIG_IDE_PROC_FS - .proc_entries = ide_disk_proc_entries, - .proc_devsets = ide_disk_proc_devsets, -#endif -}; - -static int ide_gd_open(struct block_device *bdev, fmode_t mode) -{ - struct gendisk *disk = bdev->bd_disk; - struct ide_disk_obj *idkp; - ide_drive_t *drive; - int ret = 0; - - idkp = ide_disk_get(disk); - if (idkp == NULL) - return -ENXIO; - - drive = idkp->drive; - - ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); - - idkp->openers++; - - if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) { - drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS; - /* Just in case */ - - ret = drive->disk_ops->init_media(drive, disk); - - /* - * Allow O_NDELAY to open a drive without a disk, or with an - * unreadable disk, so that we can get the format capacity - * of the drive or begin the format - Sam - */ - if (ret && (mode & FMODE_NDELAY) == 0) { - ret = -EIO; - goto out_put_idkp; - } - - if ((drive->dev_flags & IDE_DFLAG_WP) && (mode & FMODE_WRITE)) { - ret = -EROFS; - goto out_put_idkp; - } - - /* - * Ignore the return code from door_lock, - * since the open() has already succeeded, - * and the door_lock is irrelevant at this point. - */ - drive->disk_ops->set_doorlock(drive, disk, 1); - drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED; - check_disk_change(bdev); - } else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) { - ret = -EBUSY; - goto out_put_idkp; - } - return 0; - -out_put_idkp: - idkp->openers--; - ide_disk_put(idkp); - return ret; -} - -static int ide_gd_release(struct gendisk *disk, fmode_t mode) -{ - struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); - ide_drive_t *drive = idkp->drive; - - ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); - - if (idkp->openers == 1) - drive->disk_ops->flush(drive); - - if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) { - drive->disk_ops->set_doorlock(drive, disk, 0); - drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS; - } - - idkp->openers--; - - ide_disk_put(idkp); - - return 0; -} - -static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj); - ide_drive_t *drive = idkp->drive; - - geo->heads = drive->bios_head; - geo->sectors = drive->bios_sect; - geo->cylinders = (u16)drive->bios_cyl; /* truncate */ - return 0; -} - -static int ide_gd_media_changed(struct gendisk *disk) -{ - struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); - ide_drive_t *drive = idkp->drive; - int ret; - - /* do not scan partitions twice if this is a removable device */ - if (drive->dev_flags & IDE_DFLAG_ATTACH) { - drive->dev_flags &= ~IDE_DFLAG_ATTACH; - return 0; - } - - ret = !!(drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED); - drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED; - - return ret; -} - -static int ide_gd_revalidate_disk(struct gendisk *disk) -{ - struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); - ide_drive_t *drive = idkp->drive; - - if (ide_gd_media_changed(disk)) - drive->disk_ops->get_capacity(drive); - - set_capacity(disk, ide_gd_capacity(drive)); - return 0; -} - -static int ide_gd_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) -{ - struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj); - ide_drive_t *drive = idkp->drive; - - return drive->disk_ops->ioctl(drive, bdev, mode, cmd, arg); -} - -static struct block_device_operations ide_gd_ops = { - .owner = THIS_MODULE, - .open = ide_gd_open, - .release = ide_gd_release, - .locked_ioctl = ide_gd_ioctl, - .getgeo = ide_gd_getgeo, - .media_changed = ide_gd_media_changed, - .revalidate_disk = ide_gd_revalidate_disk -}; - -static int ide_gd_probe(ide_drive_t *drive) -{ - const struct ide_disk_ops *disk_ops = NULL; - struct ide_disk_obj *idkp; - struct gendisk *g; - - /* strstr("foo", "") is non-NULL */ - if (!strstr("ide-gd", drive->driver_req)) - goto failed; - -#ifdef CONFIG_IDE_GD_ATA - if (drive->media == ide_disk) - disk_ops = &ide_ata_disk_ops; -#endif -#ifdef CONFIG_IDE_GD_ATAPI - if (drive->media == ide_floppy) - disk_ops = &ide_atapi_disk_ops; -#endif - if (disk_ops == NULL) - goto failed; - - if (disk_ops->check(drive, DRV_NAME) == 0) { - printk(KERN_ERR PFX "%s: not supported by this driver\n", - drive->name); - goto failed; - } - - idkp = kzalloc(sizeof(*idkp), GFP_KERNEL); - if (!idkp) { - printk(KERN_ERR PFX "%s: can't allocate a disk structure\n", - drive->name); - goto failed; - } - - g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif)); - if (!g) - goto out_free_idkp; - - ide_init_disk(g, drive); - - idkp->dev.parent = &drive->gendev; - idkp->dev.release = ide_disk_release; - dev_set_name(&idkp->dev, dev_name(&drive->gendev)); - - if (device_register(&idkp->dev)) - goto out_free_disk; - - idkp->drive = drive; - idkp->driver = &ide_gd_driver; - idkp->disk = g; - - g->private_data = &idkp->driver; - - drive->driver_data = idkp; - drive->debug_mask = debug_mask; - drive->disk_ops = disk_ops; - - disk_ops->setup(drive); - - set_capacity(g, ide_gd_capacity(drive)); - - g->minors = IDE_DISK_MINORS; - g->driverfs_dev = &drive->gendev; - g->flags |= GENHD_FL_EXT_DEVT; - if (drive->dev_flags & IDE_DFLAG_REMOVABLE) - g->flags = GENHD_FL_REMOVABLE; - g->fops = &ide_gd_ops; - add_disk(g); - return 0; - -out_free_disk: - put_disk(g); -out_free_idkp: - kfree(idkp); -failed: - return -ENODEV; -} - -static int __init ide_gd_init(void) -{ - printk(KERN_INFO DRV_NAME " driver " IDE_GD_VERSION "\n"); - return driver_register(&ide_gd_driver.gen_driver); -} - -static void __exit ide_gd_exit(void) -{ - driver_unregister(&ide_gd_driver.gen_driver); -} - -MODULE_ALIAS("ide:*m-disk*"); -MODULE_ALIAS("ide-disk"); -MODULE_ALIAS("ide:*m-floppy*"); -MODULE_ALIAS("ide-floppy"); -module_init(ide_gd_init); -module_exit(ide_gd_exit); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("generic ATA/ATAPI disk driver"); diff --git a/windhoek/ide/ide-gd.h b/windhoek/ide/ide-gd.h deleted file mode 100644 index b604bdd3..00000000 --- a/windhoek/ide/ide-gd.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __IDE_GD_H -#define __IDE_GD_H - -#define DRV_NAME "ide-gd" -#define PFX DRV_NAME ": " - -/* define to see debug info */ -#define IDE_GD_DEBUG_LOG 0 - -#if IDE_GD_DEBUG_LOG -#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args) -#else -#define ide_debug_log(lvl, fmt, args...) do {} while (0) -#endif - -struct ide_disk_obj { - ide_drive_t *drive; - struct ide_driver *driver; - struct gendisk *disk; - struct device dev; - unsigned int openers; /* protected by BKL for now */ - - /* Last failed packet command */ - struct ide_atapi_pc *failed_pc; - /* used for blk_{fs,pc}_request() requests */ - struct ide_atapi_pc queued_pc; - - /* Last error information */ - u8 sense_key, asc, ascq; - - int progress_indication; - - /* Device information */ - /* Current format */ - int blocks, block_size, bs_factor; - /* Last format capacity descriptor */ - u8 cap_desc[8]; - /* Copy of the flexible disk page */ - u8 flexible_disk_page[32]; -}; - -sector_t ide_gd_capacity(ide_drive_t *); - -#endif /* __IDE_GD_H */ diff --git a/windhoek/ide/ide-generic.c b/windhoek/ide/ide-generic.c deleted file mode 100644 index 7c9cae02..00000000 --- a/windhoek/ide/ide-generic.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * generic/default IDE host driver - * - * Copyright (C) 2004, 2008 Bartlomiej Zolnierkiewicz - * This code was split off from ide.c. See it for original copyrights. - * - * May be copied or modified under the terms of the GNU General Public License. - */ - -/* - * For special cases new interfaces may be added using sysfs, i.e. - * - * echo -n "0x168:0x36e:10" > /sys/class/ide_generic/add - * - * will add an interface using I/O ports 0x168-0x16f/0x36e and IRQ 10. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/ide.h> -#include <linux/pci_ids.h> - -/* FIXME: convert m32r to use ide_platform host driver */ -#ifdef CONFIG_M32R -#include <asm/m32r.h> -#endif - -#include "local.h" - -#define DRV_NAME "ide_generic" - -static int probe_mask = 0x3f; -module_param(probe_mask, int, 0); -MODULE_PARM_DESC(probe_mask, "probe mask for legacy ISA IDE ports"); - -static ssize_t store_add(struct class *cls, const char *buf, size_t n) -{ - unsigned int base, ctl; - int irq, rc; - hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; - - if (sscanf(buf, "%x:%x:%d", &base, &ctl, &irq) != 3) - return -EINVAL; - - memset(&hw, 0, sizeof(hw)); - ide_std_init_ports(&hw, base, ctl); - hw.irq = irq; - hw.chipset = ide_generic; - - rc = ide_host_add(NULL, hws, NULL); - if (rc) - return rc; - - return n; -}; - -static struct class_attribute ide_generic_class_attrs[] = { - __ATTR(add, S_IWUSR, NULL, store_add), - __ATTR_NULL -}; - -static void ide_generic_class_release(struct class *cls) -{ - kfree(cls); -} - -static int __init ide_generic_sysfs_init(void) -{ - struct class *cls; - int rc; - - cls = kzalloc(sizeof(*cls), GFP_KERNEL); - if (!cls) - return -ENOMEM; - - cls->name = DRV_NAME; - cls->owner = THIS_MODULE; - cls->class_release = ide_generic_class_release; - cls->class_attrs = ide_generic_class_attrs; - - rc = class_register(cls); - if (rc) { - kfree(cls); - return rc; - } - - return 0; -} - -#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2) \ - || defined(CONFIG_PLAT_OPSPUT) -static const u16 legacy_bases[] = { 0x1f0 }; -static const int legacy_irqs[] = { PLD_IRQ_CFIREQ }; -#elif defined(CONFIG_PLAT_MAPPI3) -static const u16 legacy_bases[] = { 0x1f0, 0x170 }; -static const int legacy_irqs[] = { PLD_IRQ_CFIREQ, PLD_IRQ_IDEIREQ }; -#elif defined(CONFIG_ALPHA) -static const u16 legacy_bases[] = { 0x1f0, 0x170, 0x1e8, 0x168 }; -static const int legacy_irqs[] = { 14, 15, 11, 10 }; -#else -static const u16 legacy_bases[] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 }; -static const int legacy_irqs[] = { 14, 15, 11, 10, 8, 12 }; -#endif - -static void ide_generic_check_pci_legacy_iobases(int *primary, int *secondary) -{ - struct pci_dev *p = NULL; - u16 val; - - for_each_pci_dev(p) { - - if (pci_resource_start(p, 0) == 0x1f0) - *primary = 1; - if (pci_resource_start(p, 2) == 0x170) - *secondary = 1; - - /* Cyrix CS55{1,2}0 pre SFF MWDMA ATA on the bridge */ - if (p->vendor == PCI_VENDOR_ID_CYRIX && - (p->device == PCI_DEVICE_ID_CYRIX_5510 || - p->device == PCI_DEVICE_ID_CYRIX_5520)) - *primary = *secondary = 1; - - /* Intel MPIIX - PIO ATA on non PCI side of bridge */ - if (p->vendor == PCI_VENDOR_ID_INTEL && - p->device == PCI_DEVICE_ID_INTEL_82371MX) { - - pci_read_config_word(p, 0x6C, &val); - if (val & 0x8000) { - /* ATA port enabled */ - if (val & 0x4000) - *secondary = 1; - else - *primary = 1; - } - } - } -} - -static int __init ide_generic_init(void) -{ - hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; - unsigned long io_addr; - int i, rc = 0, primary = 0, secondary = 0; - - ide_generic_check_pci_legacy_iobases(&primary, &secondary); - - if (!probe_mask) { - printk(KERN_INFO DRV_NAME ": please use \"probe_mask=0x3f\" " - "module parameter for probing all legacy ISA IDE ports\n"); - - if (primary == 0) - probe_mask |= 0x1; - - if (secondary == 0) - probe_mask |= 0x2; - } else - printk(KERN_INFO DRV_NAME ": enforcing probing of I/O ports " - "upon user request\n"); - - i = 1; - io_addr = legacy_bases[i]; - - if ((probe_mask & (1 << i)) && io_addr) { - if (!request_region(io_addr, 8, DRV_NAME)) { - printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX " - "not free.\n", - DRV_NAME, io_addr, io_addr + 7); - goto out; - } - - if (!request_region(io_addr + 0x206, 1, DRV_NAME)) { - printk(KERN_ERR "%s: I/O resource 0x%lX " - "not free.\n", - DRV_NAME, io_addr + 0x206); - release_region(io_addr, 8); - goto out; - } - - memset(&hw, 0, sizeof(hw)); - ide_std_init_ports(&hw, io_addr, io_addr + 0x206); -#ifdef CONFIG_IA64 - hw.irq = isa_irq_to_vector(legacy_irqs[i]); -#else - hw.irq = legacy_irqs[i]; -#endif - hw.chipset = ide_generic; - - rc = ide_host_add(NULL, hws, NULL); - if (rc) { - release_region(io_addr + 0x206, 1); - release_region(io_addr, 8); - } - } - -out: - if (ide_generic_sysfs_init()) - printk(KERN_ERR DRV_NAME ": failed to create ide_generic " - "class\n"); - - return rc; -} - -module_init(ide_generic_init); - -MODULE_LICENSE("GPL"); diff --git a/windhoek/ide/ide-io.c b/windhoek/ide/ide-io.c deleted file mode 100644 index 0d4b4ddf..00000000 --- a/windhoek/ide/ide-io.c +++ /dev/null @@ -1,1230 +0,0 @@ -/* - * IDE I/O functions - * - * Basic PIO and command management functionality. - * - * This code was split off from ide.c. See ide.c for history and original - * copyrights. - * - * 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. - * - * For the avoidance of doubt the "preferred form" of this code is one which - * is in an open non patent encumbered format. Where cryptographic key signing - * forms part of the process of creating an executable the information - * including keys needed to generate an equivalently functional executable - * are deemed to be part of the source code. - */ - - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/major.h> -#include <linux/errno.h> -#include <linux/genhd.h> -#include <linux/blkpg.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/ide.h> -#include <linux/hdreg.h> -#include <linux/completion.h> -#include <linux/reboot.h> -#include <linux/cdrom.h> -#include <linux/seq_file.h> -#include <linux/device.h> -#include <linux/kmod.h> -#include <linux/scatterlist.h> -#include <linux/bitops.h> - -#include <asm/byteorder.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/io.h> - -#include <ddekit/timer.h> - -static int __ide_end_request(ide_drive_t *drive, struct request *rq, - int uptodate, unsigned int nr_bytes, int dequeue) -{ - int ret = 1; - int error = 0; - - if (uptodate <= 0) - error = uptodate ? uptodate : -EIO; - - /* - * if failfast is set on a request, override number of sectors and - * complete the whole request right now - */ - if (blk_noretry_request(rq) && error) - nr_bytes = rq->hard_nr_sectors << 9; - - if (!blk_fs_request(rq) && error && !rq->errors) - rq->errors = -EIO; - - /* - * decide whether to reenable DMA -- 3 is a random magic for now, - * if we DMA timeout more than 3 times, just stay in PIO - */ - if ((drive->dev_flags & IDE_DFLAG_DMA_PIO_RETRY) && - drive->retry_pio <= 3) { - drive->dev_flags &= ~IDE_DFLAG_DMA_PIO_RETRY; - ide_dma_on(drive); - } - - if (!blk_end_request(rq, error, nr_bytes)) - ret = 0; - - if (ret == 0 && dequeue) - drive->hwif->rq = NULL; - - return ret; -} - -/** - * ide_end_request - complete an IDE I/O - * @drive: IDE device for the I/O - * @uptodate: - * @nr_sectors: number of sectors completed - * - * This is our end_request wrapper function. We complete the I/O - * update random number input and dequeue the request, which if - * it was tagged may be out of order. - */ - -int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) -{ - unsigned int nr_bytes = nr_sectors << 9; - struct request *rq = drive->hwif->rq; - - if (!nr_bytes) { - if (blk_pc_request(rq)) - nr_bytes = rq->data_len; - else - nr_bytes = rq->hard_cur_sectors << 9; - } - - return __ide_end_request(drive, rq, uptodate, nr_bytes, 1); -} -EXPORT_SYMBOL(ide_end_request); - -/** - * ide_end_dequeued_request - complete an IDE I/O - * @drive: IDE device for the I/O - * @uptodate: - * @nr_sectors: number of sectors completed - * - * Complete an I/O that is no longer on the request queue. This - * typically occurs when we pull the request and issue a REQUEST_SENSE. - * We must still finish the old request but we must not tamper with the - * queue in the meantime. - * - * NOTE: This path does not handle barrier, but barrier is not supported - * on ide-cd anyway. - */ - -int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq, - int uptodate, int nr_sectors) -{ - BUG_ON(!blk_rq_started(rq)); - - return __ide_end_request(drive, rq, uptodate, nr_sectors << 9, 0); -} -EXPORT_SYMBOL_GPL(ide_end_dequeued_request); - -/** - * ide_end_drive_cmd - end an explicit drive command - * @drive: command - * @stat: status bits - * @err: error bits - * - * Clean up after success/failure of an explicit drive command. - * These get thrown onto the queue so they are synchronized with - * real I/O operations on the drive. - * - * In LBA48 mode we have to read the register set twice to get - * all the extra information out. - */ - -void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) -{ - ide_hwif_t *hwif = drive->hwif; - struct request *rq = hwif->rq; - - if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { - ide_task_t *task = (ide_task_t *)rq->special; - - if (task) { - struct ide_taskfile *tf = &task->tf; - - tf->error = err; - tf->status = stat; - - drive->hwif->tp_ops->tf_read(drive, task); - - if (task->tf_flags & IDE_TFLAG_DYN) - kfree(task); - } - } else if (blk_pm_request(rq)) { - struct request_pm_state *pm = rq->data; - - ide_complete_power_step(drive, rq); - if (pm->pm_step == IDE_PM_COMPLETED) - ide_complete_pm_request(drive, rq); - return; - } - - hwif->rq = NULL; - - rq->errors = err; - - if (unlikely(blk_end_request(rq, (rq->errors ? -EIO : 0), - blk_rq_bytes(rq)))) - BUG(); -} -EXPORT_SYMBOL(ide_end_drive_cmd); - -static void ide_kill_rq(ide_drive_t *drive, struct request *rq) -{ - if (rq->rq_disk) { - struct ide_driver *drv; - - drv = *(struct ide_driver **)rq->rq_disk->private_data; - drv->end_request(drive, 0, 0); - } else - ide_end_request(drive, 0, 0); -} - -static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) -{ - ide_hwif_t *hwif = drive->hwif; - - if ((stat & ATA_BUSY) || - ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) { - /* other bits are useless when BUSY */ - rq->errors |= ERROR_RESET; - } else if (stat & ATA_ERR) { - /* err has different meaning on cdrom and tape */ - if (err == ATA_ABORTED) { - if ((drive->dev_flags & IDE_DFLAG_LBA) && - /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */ - hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS) - return ide_stopped; - } else if ((err & BAD_CRC) == BAD_CRC) { - /* UDMA crc error, just retry the operation */ - drive->crc_count++; - } else if (err & (ATA_BBK | ATA_UNC)) { - /* retries won't help these */ - rq->errors = ERROR_MAX; - } else if (err & ATA_TRK0NF) { - /* help it find track zero */ - rq->errors |= ERROR_RECAL; - } - } - - if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ && - (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) { - int nsect = drive->mult_count ? drive->mult_count : 1; - - ide_pad_transfer(drive, READ, nsect * SECTOR_SIZE); - } - - if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) { - ide_kill_rq(drive, rq); - return ide_stopped; - } - - if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) - rq->errors |= ERROR_RESET; - - if ((rq->errors & ERROR_RESET) == ERROR_RESET) { - ++rq->errors; - return ide_do_reset(drive); - } - - if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) - drive->special.b.recalibrate = 1; - - ++rq->errors; - - return ide_stopped; -} - -static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) -{ - ide_hwif_t *hwif = drive->hwif; - - if ((stat & ATA_BUSY) || - ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) { - /* other bits are useless when BUSY */ - rq->errors |= ERROR_RESET; - } else { - /* add decoding error stuff */ - } - - if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) - /* force an abort */ - hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE); - - if (rq->errors >= ERROR_MAX) { - ide_kill_rq(drive, rq); - } else { - if ((rq->errors & ERROR_RESET) == ERROR_RESET) { - ++rq->errors; - return ide_do_reset(drive); - } - ++rq->errors; - } - - return ide_stopped; -} - -static ide_startstop_t -__ide_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) -{ - if (drive->media == ide_disk) - return ide_ata_error(drive, rq, stat, err); - return ide_atapi_error(drive, rq, stat, err); -} - -/** - * ide_error - handle an error on the IDE - * @drive: drive the error occurred on - * @msg: message to report - * @stat: status bits - * - * ide_error() takes action based on the error returned by the drive. - * For normal I/O that may well include retries. We deal with - * both new-style (taskfile) and old style command handling here. - * In the case of taskfile command handling there is work left to - * do - */ - -ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat) -{ - struct request *rq; - u8 err; - - err = ide_dump_status(drive, msg, stat); - - rq = drive->hwif->rq; - if (rq == NULL) - return ide_stopped; - - /* retry only "normal" I/O: */ - if (!blk_fs_request(rq)) { - rq->errors = 1; - ide_end_drive_cmd(drive, stat, err); - return ide_stopped; - } - - return __ide_error(drive, rq, stat, err); -} -EXPORT_SYMBOL_GPL(ide_error); - -static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) -{ - tf->nsect = drive->sect; - tf->lbal = drive->sect; - tf->lbam = drive->cyl; - tf->lbah = drive->cyl >> 8; - tf->device = (drive->head - 1) | drive->select; - tf->command = ATA_CMD_INIT_DEV_PARAMS; -} - -static void ide_tf_set_restore_cmd(ide_drive_t *drive, struct ide_taskfile *tf) -{ - tf->nsect = drive->sect; - tf->command = ATA_CMD_RESTORE; -} - -static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf) -{ - tf->nsect = drive->mult_req; - tf->command = ATA_CMD_SET_MULTI; -} - -static ide_startstop_t ide_disk_special(ide_drive_t *drive) -{ - special_t *s = &drive->special; - ide_task_t args; - - memset(&args, 0, sizeof(ide_task_t)); - args.data_phase = TASKFILE_NO_DATA; - - if (s->b.set_geometry) { - s->b.set_geometry = 0; - ide_tf_set_specify_cmd(drive, &args.tf); - } else if (s->b.recalibrate) { - s->b.recalibrate = 0; - ide_tf_set_restore_cmd(drive, &args.tf); - } else if (s->b.set_multmode) { - s->b.set_multmode = 0; - ide_tf_set_setmult_cmd(drive, &args.tf); - } else if (s->all) { - int special = s->all; - s->all = 0; - printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special); - return ide_stopped; - } - - args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE | - IDE_TFLAG_CUSTOM_HANDLER; - - do_rw_taskfile(drive, &args); - - return ide_started; -} - -/** - * do_special - issue some special commands - * @drive: drive the command is for - * - * do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS, - * ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive. - * - * It used to do much more, but has been scaled back. - */ - -static ide_startstop_t do_special (ide_drive_t *drive) -{ - special_t *s = &drive->special; - -#ifdef DEBUG - printk("%s: do_special: 0x%02x\n", drive->name, s->all); -#endif - if (drive->media == ide_disk) - return ide_disk_special(drive); - - s->all = 0; - drive->mult_req = 0; - return ide_stopped; -} - -void ide_map_sg(ide_drive_t *drive, struct request *rq) -{ - ide_hwif_t *hwif = drive->hwif; - struct scatterlist *sg = hwif->sg_table; - - if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { - sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE); - hwif->sg_nents = 1; - } else if (!rq->bio) { - sg_init_one(sg, rq->data, rq->data_len); - hwif->sg_nents = 1; - } else { - hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); - } -} - -EXPORT_SYMBOL_GPL(ide_map_sg); - -void ide_init_sg_cmd(ide_drive_t *drive, struct request *rq) -{ - ide_hwif_t *hwif = drive->hwif; - - hwif->nsect = hwif->nleft = rq->nr_sectors; - hwif->cursg_ofs = 0; - hwif->cursg = NULL; -} - -EXPORT_SYMBOL_GPL(ide_init_sg_cmd); - -/** - * execute_drive_command - issue special drive command - * @drive: the drive to issue the command on - * @rq: the request structure holding the command - * - * execute_drive_cmd() issues a special drive command, usually - * initiated by ioctl() from the external hdparm program. The - * command can be a drive command, drive task or taskfile - * operation. Weirdly you can call it with NULL to wait for - * all commands to finish. Don't do this as that is due to change - */ - -static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, - struct request *rq) -{ - ide_hwif_t *hwif = drive->hwif; - ide_task_t *task = rq->special; - - if (task) { - hwif->data_phase = task->data_phase; - - switch (hwif->data_phase) { - case TASKFILE_MULTI_OUT: - case TASKFILE_OUT: - case TASKFILE_MULTI_IN: - case TASKFILE_IN: - ide_init_sg_cmd(drive, rq); - ide_map_sg(drive, rq); - default: - break; - } - - return do_rw_taskfile(drive, task); - } - - /* - * NULL is actually a valid way of waiting for - * all current requests to be flushed from the queue. - */ -#ifdef DEBUG - printk("%s: DRIVE_CMD (null)\n", drive->name); -#endif - ide_end_drive_cmd(drive, hwif->tp_ops->read_status(hwif), - ide_read_error(drive)); - - return ide_stopped; -} - -int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting, - int arg) -{ - struct request_queue *q = drive->queue; - struct request *rq; - int ret = 0; - - if (!(setting->flags & DS_SYNC)) - return setting->set(drive, arg); - - rq = blk_get_request(q, READ, __GFP_WAIT); - rq->cmd_type = REQ_TYPE_SPECIAL; - rq->cmd_len = 5; - rq->cmd[0] = REQ_DEVSET_EXEC; - *(int *)&rq->cmd[1] = arg; - rq->special = setting->set; - - if (blk_execute_rq(q, NULL, rq, 0)) - ret = rq->errors; - blk_put_request(rq); - - return ret; -} -EXPORT_SYMBOL_GPL(ide_devset_execute); - -static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) -{ - u8 cmd = rq->cmd[0]; - - if (cmd == REQ_PARK_HEADS || cmd == REQ_UNPARK_HEADS) { - ide_task_t task; - struct ide_taskfile *tf = &task.tf; - - memset(&task, 0, sizeof(task)); - if (cmd == REQ_PARK_HEADS) { - drive->sleep = *(unsigned long *)rq->special; - drive->dev_flags |= IDE_DFLAG_SLEEPING; - tf->command = ATA_CMD_IDLEIMMEDIATE; - tf->feature = 0x44; - tf->lbal = 0x4c; - tf->lbam = 0x4e; - tf->lbah = 0x55; - task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER; - } else /* cmd == REQ_UNPARK_HEADS */ - tf->command = ATA_CMD_CHK_POWER; - - task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - task.rq = rq; - drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA; - return do_rw_taskfile(drive, &task); - } - - switch (cmd) { - case REQ_DEVSET_EXEC: - { - int err, (*setfunc)(ide_drive_t *, int) = rq->special; - - err = setfunc(drive, *(int *)&rq->cmd[1]); - if (err) - rq->errors = err; - else - err = 1; - ide_end_request(drive, err, 0); - return ide_stopped; - } - case REQ_DRIVE_RESET: - return ide_do_reset(drive); - default: - blk_dump_rq_flags(rq, "ide_special_rq - bad request"); - ide_end_request(drive, 0, 0); - return ide_stopped; - } -} - -/** - * start_request - start of I/O and command issuing for IDE - * - * start_request() initiates handling of a new I/O request. It - * accepts commands and I/O (read/write) requests. - * - * FIXME: this function needs a rename - */ - -static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) -{ - ide_startstop_t startstop; - - BUG_ON(!blk_rq_started(rq)); - -#ifdef DEBUG - printk("%s: start_request: current=0x%08lx\n", - drive->hwif->name, (unsigned long) rq); -#endif - - /* bail early if we've exceeded max_failures */ - if (drive->max_failures && (drive->failures > drive->max_failures)) { - rq->cmd_flags |= REQ_FAILED; - goto kill_rq; - } - - if (blk_pm_request(rq)) - ide_check_pm_state(drive, rq); - - SELECT_DRIVE(drive); - if (ide_wait_stat(&startstop, drive, drive->ready_stat, - ATA_BUSY | ATA_DRQ, WAIT_READY)) { - printk(KERN_ERR "%s: drive not ready for command\n", drive->name); - return startstop; - } - if (!drive->special.all) { - struct ide_driver *drv; - - /* - * We reset the drive so we need to issue a SETFEATURES. - * Do it _after_ do_special() restored device parameters. - */ - if (drive->current_speed == 0xff) - ide_config_drive_speed(drive, drive->desired_speed); - - if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) - return execute_drive_cmd(drive, rq); - else if (blk_pm_request(rq)) { - struct request_pm_state *pm = rq->data; -#ifdef DEBUG_PM - printk("%s: start_power_step(step: %d)\n", - drive->name, pm->pm_step); -#endif - startstop = ide_start_power_step(drive, rq); - if (startstop == ide_stopped && - pm->pm_step == IDE_PM_COMPLETED) - ide_complete_pm_request(drive, rq); - return startstop; - } else if (!rq->rq_disk && blk_special_request(rq)) - /* - * TODO: Once all ULDs have been modified to - * check for specific op codes rather than - * blindly accepting any special request, the - * check for ->rq_disk above may be replaced - * by a more suitable mechanism or even - * dropped entirely. - */ - return ide_special_rq(drive, rq); - - drv = *(struct ide_driver **)rq->rq_disk->private_data; - - return drv->do_request(drive, rq, rq->sector); - } - return do_special(drive); -kill_rq: - ide_kill_rq(drive, rq); - return ide_stopped; -} - -/** - * ide_stall_queue - pause an IDE device - * @drive: drive to stall - * @timeout: time to stall for (jiffies) - * - * ide_stall_queue() can be used by a drive to give excess bandwidth back - * to the port by sleeping for timeout jiffies. - */ - -void ide_stall_queue (ide_drive_t *drive, unsigned long timeout) -{ - if (timeout > WAIT_WORSTCASE) - timeout = WAIT_WORSTCASE; - drive->sleep = timeout + jiffies; - drive->dev_flags |= IDE_DFLAG_SLEEPING; -} -EXPORT_SYMBOL(ide_stall_queue); - -static inline int ide_lock_port(ide_hwif_t *hwif) -{ - if (hwif->busy) - return 1; - - hwif->busy = 1; - - return 0; -} - -static inline void ide_unlock_port(ide_hwif_t *hwif) -{ - hwif->busy = 0; -} - -static inline int ide_lock_host(struct ide_host *host, ide_hwif_t *hwif) -{ - int rc = 0; - - if (host->host_flags & IDE_HFLAG_SERIALIZE) { - rc = test_and_set_bit_lock(IDE_HOST_BUSY, &host->host_busy); - if (rc == 0) { - /* for atari only */ - ide_get_lock(ide_intr, hwif); - } - } - return rc; -} - -static inline void ide_unlock_host(struct ide_host *host) -{ - if (host->host_flags & IDE_HFLAG_SERIALIZE) { - /* for atari only */ - ide_release_lock(); - clear_bit_unlock(IDE_HOST_BUSY, &host->host_busy); - } -} - -/* - * Issue a new request to a device. - */ -void do_ide_request(struct request_queue *q) -{ - ide_drive_t *drive = q->queuedata; - ide_hwif_t *hwif = drive->hwif; - struct ide_host *host = hwif->host; - struct request *rq = NULL; - ide_startstop_t startstop; - - /* - * drive is doing pre-flush, ordered write, post-flush sequence. even - * though that is 3 requests, it must be seen as a single transaction. - * we must not preempt this drive until that is complete - */ - if (blk_queue_flushing(q)) - /* - * small race where queue could get replugged during - * the 3-request flush cycle, just yank the plug since - * we want it to finish asap - */ - blk_remove_plug(q); - - spin_unlock_irq(q->queue_lock); - - if (ide_lock_host(host, hwif)) - goto plug_device_2; - - spin_lock_irq(&hwif->lock); - - if (!ide_lock_port(hwif)) { - ide_hwif_t *prev_port; -repeat: - prev_port = hwif->host->cur_port; - hwif->rq = NULL; - - if (drive->dev_flags & IDE_DFLAG_SLEEPING) { - if (time_before(drive->sleep, jiffies)) { - ide_unlock_port(hwif); - goto plug_device; - } - } - - if ((hwif->host->host_flags & IDE_HFLAG_SERIALIZE) && - hwif != prev_port) { - /* - * set nIEN for previous port, drives in the - * quirk_list may not like intr setups/cleanups - */ - if (prev_port && prev_port->cur_dev->quirk_list == 0) - prev_port->tp_ops->set_irq(prev_port, 0); - - hwif->host->cur_port = hwif; - } - hwif->cur_dev = drive; - drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); - - spin_unlock_irq(&hwif->lock); - spin_lock_irq(q->queue_lock); - /* - * we know that the queue isn't empty, but this can happen - * if the q->prep_rq_fn() decides to kill a request - */ - rq = elv_next_request(drive->queue); - spin_unlock_irq(q->queue_lock); - spin_lock_irq(&hwif->lock); - - if (!rq) { - ide_unlock_port(hwif); - goto out; - } - - /* - * Sanity: don't accept a request that isn't a PM request - * if we are currently power managed. This is very important as - * blk_stop_queue() doesn't prevent the elv_next_request() - * above to return us whatever is in the queue. Since we call - * ide_do_request() ourselves, we end up taking requests while - * the queue is blocked... - * - * We let requests forced at head of queue with ide-preempt - * though. I hope that doesn't happen too much, hopefully not - * unless the subdriver triggers such a thing in its own PM - * state machine. - */ - if ((drive->dev_flags & IDE_DFLAG_BLOCKED) && - blk_pm_request(rq) == 0 && - (rq->cmd_flags & REQ_PREEMPT) == 0) { - /* there should be no pending command at this point */ - ide_unlock_port(hwif); - goto plug_device; - } - - hwif->rq = rq; - - spin_unlock_irq(&hwif->lock); - startstop = start_request(drive, rq); - spin_lock_irq(&hwif->lock); - - if (startstop == ide_stopped) - goto repeat; - } else - goto plug_device; -out: - spin_unlock_irq(&hwif->lock); - if (rq == NULL) - ide_unlock_host(host); - spin_lock_irq(q->queue_lock); - return; - -plug_device: - spin_unlock_irq(&hwif->lock); - ide_unlock_host(host); -plug_device_2: - spin_lock_irq(q->queue_lock); - - if (!elv_queue_empty(q)) - blk_plug_device(q); -} - -/* - * un-busy the port etc, and clear any pending DMA status. we want to - * retry the current request in pio mode instead of risking tossing it - * all away - */ -static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) -{ - ide_hwif_t *hwif = drive->hwif; - struct request *rq; - ide_startstop_t ret = ide_stopped; - - /* - * end current dma transaction - */ - - if (error < 0) { - printk(KERN_WARNING "%s: DMA timeout error\n", drive->name); - (void)hwif->dma_ops->dma_end(drive); - ret = ide_error(drive, "dma timeout error", - hwif->tp_ops->read_status(hwif)); - } else { - printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name); - hwif->dma_ops->dma_timeout(drive); - } - - /* - * disable dma for now, but remember that we did so because of - * a timeout -- we'll reenable after we finish this next request - * (or rather the first chunk of it) in pio. - */ - drive->dev_flags |= IDE_DFLAG_DMA_PIO_RETRY; - drive->retry_pio++; - ide_dma_off_quietly(drive); - - /* - * un-busy drive etc and make sure request is sane - */ - - rq = hwif->rq; - if (!rq) - goto out; - - hwif->rq = NULL; - - rq->errors = 0; - - if (!rq->bio) - goto out; - - rq->sector = rq->bio->bi_sector; - rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9; - rq->hard_cur_sectors = rq->current_nr_sectors; - rq->buffer = bio_data(rq->bio); -out: - return ret; -} - -static void ide_plug_device(ide_drive_t *drive) -{ - struct request_queue *q = drive->queue; - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - if (!elv_queue_empty(q)) - blk_plug_device(q); - spin_unlock_irqrestore(q->queue_lock, flags); -} - -/** - * ide_timer_expiry - handle lack of an IDE interrupt - * @data: timer callback magic (hwif) - * - * An IDE command has timed out before the expected drive return - * occurred. At this point we attempt to clean up the current - * mess. If the current handler includes an expiry handler then - * we invoke the expiry handler, and providing it is happy the - * work is done. If that fails we apply generic recovery rules - * invoking the handler and checking the drive DMA status. We - * have an excessively incestuous relationship with the DMA - * logic that wants cleaning up. - */ - -void ide_timer_expiry (unsigned long data) -{ - ide_hwif_t *hwif = (ide_hwif_t *)data; - ide_drive_t *uninitialized_var(drive); - ide_handler_t *handler; - unsigned long flags; - int wait = -1; - int plug_device = 0; - - spin_lock_irqsave(&hwif->lock, flags); - - handler = hwif->handler; - - if (handler == NULL || hwif->req_gen != hwif->req_gen_timer) { - /* - * Either a marginal timeout occurred - * (got the interrupt just as timer expired), - * or we were "sleeping" to give other devices a chance. - * Either way, we don't really want to complain about anything. - */ - } else { - ide_expiry_t *expiry = hwif->expiry; - ide_startstop_t startstop = ide_stopped; - - drive = hwif->cur_dev; - - if (expiry) { - wait = expiry(drive); - if (wait > 0) { /* continue */ - /* reset timer */ - hwif->timer.expires = jiffies + wait; - hwif->req_gen_timer = hwif->req_gen; - add_timer(&hwif->timer); - spin_unlock_irqrestore(&hwif->lock, flags); - return; - } - } - hwif->handler = NULL; - /* - * We need to simulate a real interrupt when invoking - * the handler() function, which means we need to - * globally mask the specific IRQ: - */ - spin_unlock(&hwif->lock); - /* disable_irq_nosync ?? */ - disable_irq(hwif->irq); - /* local CPU only, as if we were handling an interrupt */ - local_irq_disable(); - if (hwif->polling) { - startstop = handler(drive); - } else if (drive_is_ready(drive)) { - if (drive->waiting_for_dma) - hwif->dma_ops->dma_lost_irq(drive); - (void)ide_ack_intr(hwif); - printk(KERN_WARNING "%s: lost interrupt\n", - drive->name); - startstop = handler(drive); - } else { - if (drive->waiting_for_dma) - startstop = ide_dma_timeout_retry(drive, wait); - else - startstop = ide_error(drive, "irq timeout", - hwif->tp_ops->read_status(hwif)); - } - spin_lock_irq(&hwif->lock); - enable_irq(hwif->irq); - if (startstop == ide_stopped) { - ide_unlock_port(hwif); - plug_device = 1; - } - } - spin_unlock_irqrestore(&hwif->lock, flags); - - if (plug_device) { - ide_unlock_host(hwif->host); - ide_plug_device(drive); - } -} - -/** - * unexpected_intr - handle an unexpected IDE interrupt - * @irq: interrupt line - * @hwif: port being processed - * - * There's nothing really useful we can do with an unexpected interrupt, - * other than reading the status register (to clear it), and logging it. - * There should be no way that an irq can happen before we're ready for it, - * so we needn't worry much about losing an "important" interrupt here. - * - * On laptops (and "green" PCs), an unexpected interrupt occurs whenever - * the drive enters "idle", "standby", or "sleep" mode, so if the status - * looks "good", we just ignore the interrupt completely. - * - * This routine assumes __cli() is in effect when called. - * - * If an unexpected interrupt happens on irq15 while we are handling irq14 - * and if the two interfaces are "serialized" (CMD640), then it looks like - * we could screw up by interfering with a new request being set up for - * irq15. - * - * In reality, this is a non-issue. The new command is not sent unless - * the drive is ready to accept one, in which case we know the drive is - * not trying to interrupt us. And ide_set_handler() is always invoked - * before completing the issuance of any new drive command, so we will not - * be accidentally invoked as a result of any valid command completion - * interrupt. - */ - -static void unexpected_intr(int irq, ide_hwif_t *hwif) -{ - u8 stat = hwif->tp_ops->read_status(hwif); - - if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) { - /* Try to not flood the console with msgs */ - static unsigned long last_msgtime, count; - ++count; - - if (time_after(jiffies, last_msgtime + HZ)) { - last_msgtime = jiffies; - printk(KERN_ERR "%s: unexpected interrupt, " - "status=0x%02x, count=%ld\n", - hwif->name, stat, count); - } - } -} - -/** - * ide_intr - default IDE interrupt handler - * @irq: interrupt number - * @dev_id: hwif - * @regs: unused weirdness from the kernel irq layer - * - * This is the default IRQ handler for the IDE layer. You should - * not need to override it. If you do be aware it is subtle in - * places - * - * hwif is the interface in the group currently performing - * a command. hwif->cur_dev is the drive and hwif->handler is - * the IRQ handler to call. As we issue a command the handlers - * step through multiple states, reassigning the handler to the - * next step in the process. Unlike a smart SCSI controller IDE - * expects the main processor to sequence the various transfer - * stages. We also manage a poll timer to catch up with most - * timeout situations. There are still a few where the handlers - * don't ever decide to give up. - * - * The handler eventually returns ide_stopped to indicate the - * request completed. At this point we issue the next request - * on the port and the process begins again. - */ - -irqreturn_t ide_intr (int irq, void *dev_id) -{ - ide_hwif_t *hwif = (ide_hwif_t *)dev_id; - ide_drive_t *uninitialized_var(drive); - ide_handler_t *handler; - unsigned long flags; - ide_startstop_t startstop; - irqreturn_t irq_ret = IRQ_NONE; - int plug_device = 0; - - if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) { - if (hwif != hwif->host->cur_port) - goto out_early; - } - - spin_lock_irqsave(&hwif->lock, flags); - - if (!ide_ack_intr(hwif)) - goto out; - - handler = hwif->handler; - - if (handler == NULL || hwif->polling) { - /* - * Not expecting an interrupt from this drive. - * That means this could be: - * (1) an interrupt from another PCI device - * sharing the same PCI INT# as us. - * or (2) a drive just entered sleep or standby mode, - * and is interrupting to let us know. - * or (3) a spurious interrupt of unknown origin. - * - * For PCI, we cannot tell the difference, - * so in that case we just ignore it and hope it goes away. - * - * FIXME: unexpected_intr should be hwif-> then we can - * remove all the ifdef PCI crap - */ -#ifdef CONFIG_BLK_DEV_IDEPCI - if (hwif->chipset != ide_pci) -#endif /* CONFIG_BLK_DEV_IDEPCI */ - { - /* - * Probably not a shared PCI interrupt, - * so we can safely try to do something about it: - */ - unexpected_intr(irq, hwif); -#ifdef CONFIG_BLK_DEV_IDEPCI - } else { - /* - * Whack the status register, just in case - * we have a leftover pending IRQ. - */ - (void)hwif->tp_ops->read_status(hwif); -#endif /* CONFIG_BLK_DEV_IDEPCI */ - } - goto out; - } - - drive = hwif->cur_dev; - - if (!drive_is_ready(drive)) - /* - * This happens regularly when we share a PCI IRQ with - * another device. Unfortunately, it can also happen - * with some buggy drives that trigger the IRQ before - * their status register is up to date. Hopefully we have - * enough advance overhead that the latter isn't a problem. - */ - goto out; - - hwif->handler = NULL; - hwif->req_gen++; - del_timer(&hwif->timer); - spin_unlock(&hwif->lock); - - if (hwif->port_ops && hwif->port_ops->clear_irq) - hwif->port_ops->clear_irq(drive); - - if (drive->dev_flags & IDE_DFLAG_UNMASK) - local_irq_enable_in_hardirq(); - - /* service this interrupt, may set handler for next interrupt */ - startstop = handler(drive); - - spin_lock_irq(&hwif->lock); - /* - * Note that handler() may have set things up for another - * interrupt to occur soon, but it cannot happen until - * we exit from this routine, because it will be the - * same irq as is currently being serviced here, and Linux - * won't allow another of the same (on any CPU) until we return. - */ - if (startstop == ide_stopped) { - BUG_ON(hwif->handler); - ide_unlock_port(hwif); - plug_device = 1; - } - irq_ret = IRQ_HANDLED; -out: - spin_unlock_irqrestore(&hwif->lock, flags); -out_early: - if (plug_device) { - ide_unlock_host(hwif->host); - ide_plug_device(drive); - } - - return irq_ret; -} -EXPORT_SYMBOL_GPL(ide_intr); - -/** - * ide_do_drive_cmd - issue IDE special command - * @drive: device to issue command - * @rq: request to issue - * - * This function issues a special IDE device request - * onto the request queue. - * - * the rq is queued at the head of the request queue, displacing - * the currently-being-processed request and this function - * returns immediately without waiting for the new rq to be - * completed. This is VERY DANGEROUS, and is intended for - * careful use by the ATAPI tape/cdrom driver code. - */ - -void ide_do_drive_cmd(ide_drive_t *drive, struct request *rq) -{ - struct request_queue *q = drive->queue; - unsigned long flags; - - drive->hwif->rq = NULL; - - spin_lock_irqsave(q->queue_lock, flags); - __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); - spin_unlock_irqrestore(q->queue_lock, flags); -} -EXPORT_SYMBOL(ide_do_drive_cmd); - -void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma) -{ - ide_hwif_t *hwif = drive->hwif; - ide_task_t task; - - memset(&task, 0, sizeof(task)); - task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM | - IDE_TFLAG_OUT_FEATURE | tf_flags; - task.tf.feature = dma; /* Use PIO/DMA */ - task.tf.lbam = bcount & 0xff; - task.tf.lbah = (bcount >> 8) & 0xff; - - ide_tf_dump(drive->name, &task.tf); - hwif->tp_ops->set_irq(hwif, 1); - SELECT_MASK(drive, 0); - hwif->tp_ops->tf_load(drive, &task); -} - -EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load); - -void ide_pad_transfer(ide_drive_t *drive, int write, int len) -{ - ide_hwif_t *hwif = drive->hwif; - u8 buf[4] = { 0 }; - - while (len > 0) { - if (write) - hwif->tp_ops->output_data(drive, NULL, buf, min(4, len)); - else - hwif->tp_ops->input_data(drive, NULL, buf, min(4, len)); - len -= 4; - } -} -EXPORT_SYMBOL_GPL(ide_pad_transfer); diff --git a/windhoek/ide/ide-iops.c b/windhoek/ide/ide-iops.c deleted file mode 100644 index 21dbe568..00000000 --- a/windhoek/ide/ide-iops.c +++ /dev/null @@ -1,1217 +0,0 @@ -/* - * Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org> - * Copyright (C) 2003 Red Hat - * - */ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/major.h> -#include <linux/errno.h> -#include <linux/genhd.h> -#include <linux/blkpg.h> -#include <linux/slab.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/ide.h> -#include <linux/bitops.h> -#include <linux/nmi.h> - -#include <asm/byteorder.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/io.h> - -#include "local.h" - -#include <ddekit/timer.h> - -/* - * Conventional PIO operations for ATA devices - */ - -static u8 ide_inb (unsigned long port) -{ - return (u8) inb(port); -} - -static void ide_outb (u8 val, unsigned long port) -{ - outb(val, port); -} - -/* - * MMIO operations, typically used for SATA controllers - */ - -static u8 ide_mm_inb (unsigned long port) -{ - return (u8) readb((void __iomem *) port); -} - -static void ide_mm_outb (u8 value, unsigned long port) -{ - writeb(value, (void __iomem *) port); -} - -void SELECT_DRIVE (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - ide_task_t task; - - if (port_ops && port_ops->selectproc) - port_ops->selectproc(drive); - - memset(&task, 0, sizeof(task)); - task.tf_flags = IDE_TFLAG_OUT_DEVICE; - - drive->hwif->tp_ops->tf_load(drive, &task); -} - -void SELECT_MASK(ide_drive_t *drive, int mask) -{ - const struct ide_port_ops *port_ops = drive->hwif->port_ops; - - if (port_ops && port_ops->maskproc) - port_ops->maskproc(drive, mask); -} - -void ide_exec_command(ide_hwif_t *hwif, u8 cmd) -{ - if (hwif->host_flags & IDE_HFLAG_MMIO) - writeb(cmd, (void __iomem *)hwif->io_ports.command_addr); - else - outb(cmd, hwif->io_ports.command_addr); -} -EXPORT_SYMBOL_GPL(ide_exec_command); - -u8 ide_read_status(ide_hwif_t *hwif) -{ - if (hwif->host_flags & IDE_HFLAG_MMIO) - return readb((void __iomem *)hwif->io_ports.status_addr); - else - return inb(hwif->io_ports.status_addr); -} -EXPORT_SYMBOL_GPL(ide_read_status); - -u8 ide_read_altstatus(ide_hwif_t *hwif) -{ - if (hwif->host_flags & IDE_HFLAG_MMIO) - return readb((void __iomem *)hwif->io_ports.ctl_addr); - else - return inb(hwif->io_ports.ctl_addr); -} -EXPORT_SYMBOL_GPL(ide_read_altstatus); - -void ide_set_irq(ide_hwif_t *hwif, int on) -{ - u8 ctl = ATA_DEVCTL_OBS; - - if (on == 4) { /* hack for SRST */ - ctl |= 4; - on &= ~4; - } - - ctl |= on ? 0 : 2; - - if (hwif->host_flags & IDE_HFLAG_MMIO) - writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr); - else - outb(ctl, hwif->io_ports.ctl_addr); -} -EXPORT_SYMBOL_GPL(ide_set_irq); - -void ide_tf_load(ide_drive_t *drive, ide_task_t *task) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - struct ide_taskfile *tf = &task->tf; - void (*tf_outb)(u8 addr, unsigned long port); - u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; - u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; - - if (mmio) - tf_outb = ide_mm_outb; - else - tf_outb = ide_outb; - - if (task->tf_flags & IDE_TFLAG_FLAGGED) - HIHI = 0xFF; - - if (task->tf_flags & IDE_TFLAG_OUT_DATA) { - u16 data = (tf->hob_data << 8) | tf->data; - - if (mmio) - writew(data, (void __iomem *)io_ports->data_addr); - else - outw(data, io_ports->data_addr); - } - - if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) - tf_outb(tf->hob_feature, io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) - tf_outb(tf->hob_nsect, io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) - tf_outb(tf->hob_lbal, io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) - tf_outb(tf->hob_lbam, io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) - tf_outb(tf->hob_lbah, io_ports->lbah_addr); - - if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) - tf_outb(tf->feature, io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_OUT_NSECT) - tf_outb(tf->nsect, io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_OUT_LBAL) - tf_outb(tf->lbal, io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_OUT_LBAM) - tf_outb(tf->lbam, io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_OUT_LBAH) - tf_outb(tf->lbah, io_ports->lbah_addr); - - if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) - tf_outb((tf->device & HIHI) | drive->select, - io_ports->device_addr); -} -EXPORT_SYMBOL_GPL(ide_tf_load); - -void ide_tf_read(ide_drive_t *drive, ide_task_t *task) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - struct ide_taskfile *tf = &task->tf; - void (*tf_outb)(u8 addr, unsigned long port); - u8 (*tf_inb)(unsigned long port); - u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; - - if (mmio) { - tf_outb = ide_mm_outb; - tf_inb = ide_mm_inb; - } else { - tf_outb = ide_outb; - tf_inb = ide_inb; - } - - if (task->tf_flags & IDE_TFLAG_IN_DATA) { - u16 data; - - if (mmio) - data = readw((void __iomem *)io_ports->data_addr); - else - data = inw(io_ports->data_addr); - - tf->data = data & 0xff; - tf->hob_data = (data >> 8) & 0xff; - } - - /* be sure we're looking at the low order bits */ - tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); - - if (task->tf_flags & IDE_TFLAG_IN_FEATURE) - tf->feature = tf_inb(io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_IN_NSECT) - tf->nsect = tf_inb(io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAL) - tf->lbal = tf_inb(io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAM) - tf->lbam = tf_inb(io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAH) - tf->lbah = tf_inb(io_ports->lbah_addr); - if (task->tf_flags & IDE_TFLAG_IN_DEVICE) - tf->device = tf_inb(io_ports->device_addr); - - if (task->tf_flags & IDE_TFLAG_LBA48) { - tf_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); - - if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) - tf->hob_feature = tf_inb(io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) - tf->hob_nsect = tf_inb(io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) - tf->hob_lbal = tf_inb(io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) - tf->hob_lbam = tf_inb(io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) - tf->hob_lbah = tf_inb(io_ports->lbah_addr); - } -} -EXPORT_SYMBOL_GPL(ide_tf_read); - -/* - * Some localbus EIDE interfaces require a special access sequence - * when using 32-bit I/O instructions to transfer data. We call this - * the "vlb_sync" sequence, which consists of three successive reads - * of the sector count register location, with interrupts disabled - * to ensure that the reads all happen together. - */ -static void ata_vlb_sync(unsigned long port) -{ - (void)inb(port); - (void)inb(port); - (void)inb(port); -} - -/* - * This is used for most PIO data transfers *from* the IDE interface - * - * These routines will round up any request for an odd number of bytes, - * so if an odd len is specified, be sure that there's at least one - * extra byte allocated for the buffer. - */ -void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf, - unsigned int len) -{ - DEBUG_MSG("drive %p, rq %p, buf %p, len %d", drive, rq, buf, len); - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - unsigned long data_addr = io_ports->data_addr; - u8 io_32bit = drive->io_32bit; - u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; - - len++; - - DEBUG_MSG("io32bit: %d", io_32bit); - - if (io_32bit) { - unsigned long uninitialized_var(flags); - - if ((io_32bit & 2) && !mmio) { - local_irq_save(flags); - ata_vlb_sync(io_ports->nsect_addr); - } - - if (mmio) - __ide_mm_insl((void __iomem *)data_addr, buf, len / 4); - else - insl(data_addr, buf, len / 4); - - if ((io_32bit & 2) && !mmio) - local_irq_restore(flags); - - if ((len & 3) >= 2) { - if (mmio) - __ide_mm_insw((void __iomem *)data_addr, - (u8 *)buf + (len & ~3), 1); - else - insw(data_addr, (u8 *)buf + (len & ~3), 1); - } - } else { - if (mmio) - __ide_mm_insw((void __iomem *)data_addr, buf, len / 2); - else - insw(data_addr, buf, len / 2); - } -} -EXPORT_SYMBOL_GPL(ide_input_data); - -/* - * This is used for most PIO data transfers *to* the IDE interface - */ -void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf, - unsigned int len) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - unsigned long data_addr = io_ports->data_addr; - u8 io_32bit = drive->io_32bit; - u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; - - len++; - - if (io_32bit) { - unsigned long uninitialized_var(flags); - - if ((io_32bit & 2) && !mmio) { - local_irq_save(flags); - ata_vlb_sync(io_ports->nsect_addr); - } - - if (mmio) - __ide_mm_outsl((void __iomem *)data_addr, buf, len / 4); - else - outsl(data_addr, buf, len / 4); - - if ((io_32bit & 2) && !mmio) - local_irq_restore(flags); - - if ((len & 3) >= 2) { - if (mmio) - __ide_mm_outsw((void __iomem *)data_addr, - (u8 *)buf + (len & ~3), 1); - else - outsw(data_addr, (u8 *)buf + (len & ~3), 1); - } - } else { - if (mmio) - __ide_mm_outsw((void __iomem *)data_addr, buf, len / 2); - else - outsw(data_addr, buf, len / 2); - } -} -EXPORT_SYMBOL_GPL(ide_output_data); - -u8 ide_read_error(ide_drive_t *drive) -{ - ide_task_t task; - - memset(&task, 0, sizeof(task)); - task.tf_flags = IDE_TFLAG_IN_FEATURE; - - drive->hwif->tp_ops->tf_read(drive, &task); - - return task.tf.error; -} -EXPORT_SYMBOL_GPL(ide_read_error); - -void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason) -{ - ide_task_t task; - - memset(&task, 0, sizeof(task)); - task.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM | - IDE_TFLAG_IN_NSECT; - - drive->hwif->tp_ops->tf_read(drive, &task); - - *bcount = (task.tf.lbah << 8) | task.tf.lbam; - *ireason = task.tf.nsect & 3; -} -EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason); - -const struct ide_tp_ops default_tp_ops = { - .exec_command = ide_exec_command, - .read_status = ide_read_status, - .read_altstatus = ide_read_altstatus, - - .set_irq = ide_set_irq, - - .tf_load = ide_tf_load, - .tf_read = ide_tf_read, - - .input_data = ide_input_data, - .output_data = ide_output_data, -}; - -void ide_fix_driveid(u16 *id) -{ -#ifndef __LITTLE_ENDIAN -# ifdef __BIG_ENDIAN - int i; - - for (i = 0; i < 256; i++) - id[i] = __le16_to_cpu(id[i]); -# else -# error "Please fix <asm/byteorder.h>" -# endif -#endif -} - -/* - * ide_fixstring() cleans up and (optionally) byte-swaps a text string, - * removing leading/trailing blanks and compressing internal blanks. - * It is primarily used to tidy up the model name/number fields as - * returned by the ATA_CMD_ID_ATA[PI] commands. - */ - -void ide_fixstring (u8 *s, const int bytecount, const int byteswap) -{ - u8 *p, *end = &s[bytecount & ~1]; /* bytecount must be even */ - - if (byteswap) { - /* convert from big-endian to host byte order */ - for (p = s ; p != end ; p += 2) - be16_to_cpus((u16 *) p); - } - - /* strip leading blanks */ - p = s; - while (s != end && *s == ' ') - ++s; - /* compress internal blanks and strip trailing blanks */ - while (s != end && *s) { - if (*s++ != ' ' || (s != end && *s && *s != ' ')) - *p++ = *(s-1); - } - /* wipe out trailing garbage */ - while (p != end) - *p++ = '\0'; -} - -EXPORT_SYMBOL(ide_fixstring); - -/* - * Needed for PCI irq sharing - */ -int drive_is_ready (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - u8 stat = 0; - - if (drive->waiting_for_dma) - return hwif->dma_ops->dma_test_irq(drive); - - /* - * We do a passive status test under shared PCI interrupts on - * cards that truly share the ATA side interrupt, but may also share - * an interrupt with another pci card/device. We make no assumptions - * about possible isa-pnp and pci-pnp issues yet. - */ - if (hwif->io_ports.ctl_addr && - (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) - stat = hwif->tp_ops->read_altstatus(hwif); - else - /* Note: this may clear a pending IRQ!! */ - stat = hwif->tp_ops->read_status(hwif); - - if (stat & ATA_BUSY) - /* drive busy: definitely not interrupting */ - return 0; - - /* drive ready: *might* be interrupting */ - return 1; -} - -EXPORT_SYMBOL(drive_is_ready); - -/* - * This routine busy-waits for the drive status to be not "busy". - * It then checks the status for all of the "good" bits and none - * of the "bad" bits, and if all is okay it returns 0. All other - * cases return error -- caller may then invoke ide_error(). - * - * This routine should get fixed to not hog the cpu during extra long waits.. - * That could be done by busy-waiting for the first jiffy or two, and then - * setting a timer to wake up at half second intervals thereafter, - * until timeout is achieved, before timing out. - */ -static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout, u8 *rstat) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; - unsigned long flags; - int i; - u8 stat; - - udelay(1); /* spec allows drive 400ns to assert "BUSY" */ - stat = tp_ops->read_status(hwif); - - if (stat & ATA_BUSY) { - local_save_flags(flags); - local_irq_enable_in_hardirq(); - timeout += jiffies; - while ((stat = tp_ops->read_status(hwif)) & ATA_BUSY) { - if (time_after(jiffies, timeout)) { - /* - * One last read after the timeout in case - * heavy interrupt load made us not make any - * progress during the timeout.. - */ - stat = tp_ops->read_status(hwif); - if ((stat & ATA_BUSY) == 0) - break; - - local_irq_restore(flags); - *rstat = stat; - return -EBUSY; - } - } - local_irq_restore(flags); - } - /* - * Allow status to settle, then read it again. - * A few rare drives vastly violate the 400ns spec here, - * so we'll wait up to 10usec for a "good" status - * rather than expensively fail things immediately. - * This fix courtesy of Matthew Faupel & Niccolo Rigacci. - */ - for (i = 0; i < 10; i++) { - udelay(1); - stat = tp_ops->read_status(hwif); - - if (OK_STAT(stat, good, bad)) { - *rstat = stat; - return 0; - } - } - *rstat = stat; - return -EFAULT; -} - -/* - * In case of error returns error value after doing "*startstop = ide_error()". - * The caller should return the updated value of "startstop" in this case, - * "startstop" is unchanged when the function returns 0. - */ -int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout) -{ - int err; - u8 stat; - - /* bail early if we've exceeded max_failures */ - if (drive->max_failures && (drive->failures > drive->max_failures)) { - *startstop = ide_stopped; - return 1; - } - - err = __ide_wait_stat(drive, good, bad, timeout, &stat); - - if (err) { - char *s = (err == -EBUSY) ? "status timeout" : "status error"; - *startstop = ide_error(drive, s, stat); - } - - return err; -} - -EXPORT_SYMBOL(ide_wait_stat); - -/** - * ide_in_drive_list - look for drive in black/white list - * @id: drive identifier - * @table: list to inspect - * - * Look for a drive in the blacklist and the whitelist tables - * Returns 1 if the drive is found in the table. - */ - -int ide_in_drive_list(u16 *id, const struct drive_list_entry *table) -{ - for ( ; table->id_model; table++) - if ((!strcmp(table->id_model, (char *)&id[ATA_ID_PROD])) && - (!table->id_firmware || - strstr((char *)&id[ATA_ID_FW_REV], table->id_firmware))) - return 1; - return 0; -} - -EXPORT_SYMBOL_GPL(ide_in_drive_list); - -/* - * Early UDMA66 devices don't set bit14 to 1, only bit13 is valid. - * We list them here and depend on the device side cable detection for them. - * - * Some optical devices with the buggy firmwares have the same problem. - */ -static const struct drive_list_entry ivb_list[] = { - { "QUANTUM FIREBALLlct10 05" , "A03.0900" }, - { "TSSTcorp CDDVDW SH-S202J" , "SB00" }, - { "TSSTcorp CDDVDW SH-S202J" , "SB01" }, - { "TSSTcorp CDDVDW SH-S202N" , "SB00" }, - { "TSSTcorp CDDVDW SH-S202N" , "SB01" }, - { "TSSTcorp CDDVDW SH-S202H" , "SB00" }, - { "TSSTcorp CDDVDW SH-S202H" , "SB01" }, - { "SAMSUNG SP0822N" , "WA100-10" }, - { NULL , NULL } -}; - -/* - * All hosts that use the 80c ribbon must use! - * The name is derived from upper byte of word 93 and the 80c ribbon. - */ -u8 eighty_ninty_three (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - u16 *id = drive->id; - int ivb = ide_in_drive_list(id, ivb_list); - - if (hwif->cbl == ATA_CBL_PATA40_SHORT) - return 1; - - if (ivb) - printk(KERN_DEBUG "%s: skipping word 93 validity check\n", - drive->name); - - if (ata_id_is_sata(id) && !ivb) - return 1; - - if (hwif->cbl != ATA_CBL_PATA80 && !ivb) - goto no_80w; - - /* - * FIXME: - * - change master/slave IDENTIFY order - * - force bit13 (80c cable present) check also for !ivb devices - * (unless the slave device is pre-ATA3) - */ - if ((id[ATA_ID_HW_CONFIG] & 0x4000) || - (ivb && (id[ATA_ID_HW_CONFIG] & 0x2000))) - return 1; - -no_80w: - if (drive->dev_flags & IDE_DFLAG_UDMA33_WARNED) - return 0; - - printk(KERN_WARNING "%s: %s side 80-wire cable detection failed, " - "limiting max speed to UDMA33\n", - drive->name, - hwif->cbl == ATA_CBL_PATA80 ? "drive" : "host"); - - drive->dev_flags |= IDE_DFLAG_UDMA33_WARNED; - - return 0; -} - -int ide_driveid_update(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; - u16 *id; - unsigned long flags; - u8 stat; - - /* - * Re-read drive->id for possible DMA mode - * change (copied from ide-probe.c) - */ - - SELECT_MASK(drive, 1); - tp_ops->set_irq(hwif, 0); - msleep(50); - tp_ops->exec_command(hwif, ATA_CMD_ID_ATA); - - if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 1)) { - SELECT_MASK(drive, 0); - return 0; - } - - msleep(50); /* wait for IRQ and ATA_DRQ */ - stat = tp_ops->read_status(hwif); - - if (!OK_STAT(stat, ATA_DRQ, BAD_R_STAT)) { - SELECT_MASK(drive, 0); - printk("%s: CHECK for good STATUS\n", drive->name); - return 0; - } - local_irq_save(flags); - SELECT_MASK(drive, 0); - id = kmalloc(SECTOR_SIZE, GFP_ATOMIC); - if (!id) { - local_irq_restore(flags); - return 0; - } - tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); - (void)tp_ops->read_status(hwif); /* clear drive IRQ */ - local_irq_enable(); - local_irq_restore(flags); - ide_fix_driveid(id); - - drive->id[ATA_ID_UDMA_MODES] = id[ATA_ID_UDMA_MODES]; - drive->id[ATA_ID_MWDMA_MODES] = id[ATA_ID_MWDMA_MODES]; - drive->id[ATA_ID_SWDMA_MODES] = id[ATA_ID_SWDMA_MODES]; - /* anything more ? */ - - kfree(id); - - if ((drive->dev_flags & IDE_DFLAG_USING_DMA) && ide_id_dma_bug(drive)) - ide_dma_off(drive); - - return 1; -} - -int ide_config_drive_speed(ide_drive_t *drive, u8 speed) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; - u16 *id = drive->id, i; - int error = 0; - u8 stat; - ide_task_t task; - -#ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_ops) /* check if host supports DMA */ - hwif->dma_ops->dma_host_set(drive, 0); -#endif - - /* Skip setting PIO flow-control modes on pre-EIDE drives */ - if ((speed & 0xf8) == XFER_PIO_0 && ata_id_has_iordy(drive->id) == 0) - goto skip; - - /* - * Don't use ide_wait_cmd here - it will - * attempt to set_geometry and recalibrate, - * but for some reason these don't work at - * this point (lost interrupt). - */ - /* - * Select the drive, and issue the SETFEATURES command - */ - disable_irq_nosync(hwif->irq); - - /* - * FIXME: we race against the running IRQ here if - * this is called from non IRQ context. If we use - * disable_irq() we hang on the error path. Work - * is needed. - */ - - udelay(1); - SELECT_DRIVE(drive); - SELECT_MASK(drive, 1); - udelay(1); - tp_ops->set_irq(hwif, 0); - - memset(&task, 0, sizeof(task)); - task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT; - task.tf.feature = SETFEATURES_XFER; - task.tf.nsect = speed; - - tp_ops->tf_load(drive, &task); - - tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES); - - if (drive->quirk_list == 2) - tp_ops->set_irq(hwif, 1); - - error = __ide_wait_stat(drive, drive->ready_stat, - ATA_BUSY | ATA_DRQ | ATA_ERR, - WAIT_CMD, &stat); - - SELECT_MASK(drive, 0); - - enable_irq(hwif->irq); - - if (error) { - (void) ide_dump_status(drive, "set_drive_speed_status", stat); - return error; - } - - id[ATA_ID_UDMA_MODES] &= ~0xFF00; - id[ATA_ID_MWDMA_MODES] &= ~0x0F00; - id[ATA_ID_SWDMA_MODES] &= ~0x0F00; - - skip: -#ifdef CONFIG_BLK_DEV_IDEDMA - if (speed >= XFER_SW_DMA_0 && (drive->dev_flags & IDE_DFLAG_USING_DMA)) - hwif->dma_ops->dma_host_set(drive, 1); - else if (hwif->dma_ops) /* check if host supports DMA */ - ide_dma_off_quietly(drive); -#endif - - if (speed >= XFER_UDMA_0) { - i = 1 << (speed - XFER_UDMA_0); - id[ATA_ID_UDMA_MODES] |= (i << 8 | i); - } else if (speed >= XFER_MW_DMA_0) { - i = 1 << (speed - XFER_MW_DMA_0); - id[ATA_ID_MWDMA_MODES] |= (i << 8 | i); - } else if (speed >= XFER_SW_DMA_0) { - i = 1 << (speed - XFER_SW_DMA_0); - id[ATA_ID_SWDMA_MODES] |= (i << 8 | i); - } - - if (!drive->init_speed) - drive->init_speed = speed; - drive->current_speed = speed; - return error; -} - -/* - * This should get invoked any time we exit the driver to - * wait for an interrupt response from a drive. handler() points - * at the appropriate code to handle the next interrupt, and a - * timer is started to prevent us from waiting forever in case - * something goes wrong (see the ide_timer_expiry() handler later on). - * - * See also ide_execute_command - */ -static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, - unsigned int timeout, ide_expiry_t *expiry) -{ - ide_hwif_t *hwif = drive->hwif; - - BUG_ON(hwif->handler); - hwif->handler = handler; - hwif->expiry = expiry; - hwif->timer.expires = jiffies + timeout; - hwif->req_gen_timer = hwif->req_gen; - add_timer(&hwif->timer); -} - -void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, - unsigned int timeout, ide_expiry_t *expiry) -{ - ide_hwif_t *hwif = drive->hwif; - unsigned long flags; - - spin_lock_irqsave(&hwif->lock, flags); - __ide_set_handler(drive, handler, timeout, expiry); - spin_unlock_irqrestore(&hwif->lock, flags); -} - -EXPORT_SYMBOL(ide_set_handler); - -/** - * ide_execute_command - execute an IDE command - * @drive: IDE drive to issue the command against - * @command: command byte to write - * @handler: handler for next phase - * @timeout: timeout for command - * @expiry: handler to run on timeout - * - * Helper function to issue an IDE command. This handles the - * atomicity requirements, command timing and ensures that the - * handler and IRQ setup do not race. All IDE command kick off - * should go via this function or do equivalent locking. - */ - -void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler, - unsigned timeout, ide_expiry_t *expiry) -{ - ide_hwif_t *hwif = drive->hwif; - unsigned long flags; - - spin_lock_irqsave(&hwif->lock, flags); - __ide_set_handler(drive, handler, timeout, expiry); - hwif->tp_ops->exec_command(hwif, cmd); - /* - * Drive takes 400nS to respond, we must avoid the IRQ being - * serviced before that. - * - * FIXME: we could skip this delay with care on non shared devices - */ - ndelay(400); - spin_unlock_irqrestore(&hwif->lock, flags); -} -EXPORT_SYMBOL(ide_execute_command); - -void ide_execute_pkt_cmd(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - unsigned long flags; - - spin_lock_irqsave(&hwif->lock, flags); - hwif->tp_ops->exec_command(hwif, ATA_CMD_PACKET); - ndelay(400); - spin_unlock_irqrestore(&hwif->lock, flags); -} -EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd); - -static inline void ide_complete_drive_reset(ide_drive_t *drive, int err) -{ - struct request *rq = drive->hwif->rq; - - if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) - ide_end_request(drive, err ? err : 1, 0); -} - -/* needed below */ -static ide_startstop_t do_reset1 (ide_drive_t *, int); - -/* - * atapi_reset_pollfunc() gets invoked to poll the interface for completion every 50ms - * during an atapi drive reset operation. If the drive has not yet responded, - * and we have not yet hit our maximum waiting time, then the timer is restarted - * for another 50ms. - */ -static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - u8 stat; - - SELECT_DRIVE(drive); - udelay (10); - stat = hwif->tp_ops->read_status(hwif); - - if (OK_STAT(stat, 0, ATA_BUSY)) - printk("%s: ATAPI reset complete\n", drive->name); - else { - if (time_before(jiffies, hwif->poll_timeout)) { - ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); - /* continue polling */ - return ide_started; - } - /* end of polling */ - hwif->polling = 0; - printk("%s: ATAPI reset timed-out, status=0x%02x\n", - drive->name, stat); - /* do it the old fashioned way */ - return do_reset1(drive, 1); - } - /* done polling */ - hwif->polling = 0; - ide_complete_drive_reset(drive, 0); - return ide_stopped; -} - -static void ide_reset_report_error(ide_hwif_t *hwif, u8 err) -{ - static const char *err_master_vals[] = - { NULL, "passed", "formatter device error", - "sector buffer error", "ECC circuitry error", - "controlling MPU error" }; - - u8 err_master = err & 0x7f; - - printk(KERN_ERR "%s: reset: master: ", hwif->name); - if (err_master && err_master < 6) - printk(KERN_CONT "%s", err_master_vals[err_master]); - else - printk(KERN_CONT "error (0x%02x?)", err); - if (err & 0x80) - printk(KERN_CONT "; slave: failed"); - printk(KERN_CONT "\n"); -} - -/* - * reset_pollfunc() gets invoked to poll the interface for completion every 50ms - * during an ide reset operation. If the drives have not yet responded, - * and we have not yet hit our maximum waiting time, then the timer is restarted - * for another 50ms. - */ -static ide_startstop_t reset_pollfunc (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - u8 tmp; - int err = 0; - - if (port_ops && port_ops->reset_poll) { - err = port_ops->reset_poll(drive); - if (err) { - printk(KERN_ERR "%s: host reset_poll failure for %s.\n", - hwif->name, drive->name); - goto out; - } - } - - tmp = hwif->tp_ops->read_status(hwif); - - if (!OK_STAT(tmp, 0, ATA_BUSY)) { - if (time_before(jiffies, hwif->poll_timeout)) { - ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); - /* continue polling */ - return ide_started; - } - printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp); - drive->failures++; - err = -EIO; - } else { - tmp = ide_read_error(drive); - - if (tmp == 1) { - printk(KERN_INFO "%s: reset: success\n", hwif->name); - drive->failures = 0; - } else { - ide_reset_report_error(hwif, tmp); - drive->failures++; - err = -EIO; - } - } -out: - hwif->polling = 0; /* done polling */ - ide_complete_drive_reset(drive, err); - return ide_stopped; -} - -static void ide_disk_pre_reset(ide_drive_t *drive) -{ - int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1; - - drive->special.all = 0; - drive->special.b.set_geometry = legacy; - drive->special.b.recalibrate = legacy; - - drive->mult_count = 0; - drive->dev_flags &= ~IDE_DFLAG_PARKED; - - if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 && - (drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) - drive->mult_req = 0; - - if (drive->mult_req != drive->mult_count) - drive->special.b.set_multmode = 1; -} - -static void pre_reset(ide_drive_t *drive) -{ - const struct ide_port_ops *port_ops = drive->hwif->port_ops; - - if (drive->media == ide_disk) - ide_disk_pre_reset(drive); - else - drive->dev_flags |= IDE_DFLAG_POST_RESET; - - if (drive->dev_flags & IDE_DFLAG_USING_DMA) { - if (drive->crc_count) - ide_check_dma_crc(drive); - else - ide_dma_off(drive); - } - - if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0) { - if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) { - drive->dev_flags &= ~IDE_DFLAG_UNMASK; - drive->io_32bit = 0; - } - return; - } - - if (port_ops && port_ops->pre_reset) - port_ops->pre_reset(drive); - - if (drive->current_speed != 0xff) - drive->desired_speed = drive->current_speed; - drive->current_speed = 0xff; -} - -/* - * do_reset1() attempts to recover a confused drive by resetting it. - * Unfortunately, resetting a disk drive actually resets all devices on - * the same interface, so it can really be thought of as resetting the - * interface rather than resetting the drive. - * - * ATAPI devices have their own reset mechanism which allows them to be - * individually reset without clobbering other devices on the same interface. - * - * Unfortunately, the IDE interface does not generate an interrupt to let - * us know when the reset operation has finished, so we must poll for this. - * Equally poor, though, is the fact that this may a very long time to complete, - * (up to 30 seconds worstcase). So, instead of busy-waiting here for it, - * we set a timer to poll at 50ms intervals. - */ -static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; - const struct ide_port_ops *port_ops; - ide_drive_t *tdrive; - unsigned long flags, timeout; - int i; - DEFINE_WAIT(wait); - - spin_lock_irqsave(&hwif->lock, flags); - - /* We must not reset with running handlers */ - BUG_ON(hwif->handler != NULL); - - /* For an ATAPI device, first try an ATAPI SRST. */ - if (drive->media != ide_disk && !do_not_try_atapi) { - pre_reset(drive); - SELECT_DRIVE(drive); - udelay (20); - tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); - ndelay(400); - hwif->poll_timeout = jiffies + WAIT_WORSTCASE; - hwif->polling = 1; - __ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); - spin_unlock_irqrestore(&hwif->lock, flags); - return ide_started; - } - - /* We must not disturb devices in the IDE_DFLAG_PARKED state. */ - do { - unsigned long now; - - prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE); - timeout = jiffies; - ide_port_for_each_dev(i, tdrive, hwif) { - if (tdrive->dev_flags & IDE_DFLAG_PRESENT && - tdrive->dev_flags & IDE_DFLAG_PARKED && - time_after(tdrive->sleep, timeout)) - timeout = tdrive->sleep; - } - - now = jiffies; - if (time_before_eq(timeout, now)) - break; - - spin_unlock_irqrestore(&hwif->lock, flags); - timeout = schedule_timeout_uninterruptible(timeout - now); - spin_lock_irqsave(&hwif->lock, flags); - } while (timeout); - finish_wait(&ide_park_wq, &wait); - - /* - * First, reset any device state data we were maintaining - * for any of the drives on this interface. - */ - ide_port_for_each_dev(i, tdrive, hwif) - pre_reset(tdrive); - - if (io_ports->ctl_addr == 0) { - spin_unlock_irqrestore(&hwif->lock, flags); - ide_complete_drive_reset(drive, -ENXIO); - return ide_stopped; - } - - /* - * Note that we also set nIEN while resetting the device, - * to mask unwanted interrupts from the interface during the reset. - * However, due to the design of PC hardware, this will cause an - * immediate interrupt due to the edge transition it produces. - * This single interrupt gives us a "fast poll" for drives that - * recover from reset very quickly, saving us the first 50ms wait time. - * - * TODO: add ->softreset method and stop abusing ->set_irq - */ - /* set SRST and nIEN */ - tp_ops->set_irq(hwif, 4); - /* more than enough time */ - udelay(10); - /* clear SRST, leave nIEN (unless device is on the quirk list) */ - tp_ops->set_irq(hwif, drive->quirk_list == 2); - /* more than enough time */ - udelay(10); - hwif->poll_timeout = jiffies + WAIT_WORSTCASE; - hwif->polling = 1; - __ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); - - /* - * Some weird controller like resetting themselves to a strange - * state when the disks are reset this way. At least, the Winbond - * 553 documentation says that - */ - port_ops = hwif->port_ops; - if (port_ops && port_ops->resetproc) - port_ops->resetproc(drive); - - spin_unlock_irqrestore(&hwif->lock, flags); - return ide_started; -} - -/* - * ide_do_reset() is the entry point to the drive/interface reset code. - */ - -ide_startstop_t ide_do_reset (ide_drive_t *drive) -{ - return do_reset1(drive, 0); -} - -EXPORT_SYMBOL(ide_do_reset); - -/* - * ide_wait_not_busy() waits for the currently selected device on the hwif - * to report a non-busy status, see comments in ide_probe_port(). - */ -int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout) -{ - u8 stat = 0; - - while(timeout--) { - /* - * Turn this into a schedule() sleep once I'm sure - * about locking issues (2.5 work ?). - */ - mdelay(1); - stat = hwif->tp_ops->read_status(hwif); - if ((stat & ATA_BUSY) == 0) - return 0; - /* - * Assume a value of 0xff means nothing is connected to - * the interface and it doesn't implement the pull-down - * resistor on D7. - */ - if (stat == 0xff) - return -ENODEV; - touch_softlockup_watchdog(); - touch_nmi_watchdog(); - } - return -EBUSY; -} diff --git a/windhoek/ide/ide-lib.c b/windhoek/ide/ide-lib.c deleted file mode 100644 index 09526a0d..00000000 --- a/windhoek/ide/ide-lib.c +++ /dev/null @@ -1,423 +0,0 @@ -#include <linux/types.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/interrupt.h> -#include <linux/ide.h> -#include <linux/bitops.h> - -static const char *udma_str[] = - { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44", - "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" }; -static const char *mwdma_str[] = - { "MWDMA0", "MWDMA1", "MWDMA2" }; -static const char *swdma_str[] = - { "SWDMA0", "SWDMA1", "SWDMA2" }; -static const char *pio_str[] = - { "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" }; - -/** - * ide_xfer_verbose - return IDE mode names - * @mode: transfer mode - * - * Returns a constant string giving the name of the mode - * requested. - */ - -const char *ide_xfer_verbose(u8 mode) -{ - const char *s; - u8 i = mode & 0xf; - - if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7) - s = udma_str[i]; - else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2) - s = mwdma_str[i]; - else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2) - s = swdma_str[i]; - else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5) - s = pio_str[i & 0x7]; - else if (mode == XFER_PIO_SLOW) - s = "PIO SLOW"; - else - s = "XFER ERROR"; - - return s; -} -EXPORT_SYMBOL(ide_xfer_verbose); - -/** - * ide_rate_filter - filter transfer mode - * @drive: IDE device - * @speed: desired speed - * - * Given the available transfer modes this function returns - * the best available speed at or below the speed requested. - * - * TODO: check device PIO capabilities - */ - -static u8 ide_rate_filter(ide_drive_t *drive, u8 speed) -{ - ide_hwif_t *hwif = drive->hwif; - u8 mode = ide_find_dma_mode(drive, speed); - - if (mode == 0) { - if (hwif->pio_mask) - mode = fls(hwif->pio_mask) - 1 + XFER_PIO_0; - else - mode = XFER_PIO_4; - } - -/* printk("%s: mode 0x%02x, speed 0x%02x\n", __func__, mode, speed); */ - - return min(speed, mode); -} - -/** - * ide_get_best_pio_mode - get PIO mode from drive - * @drive: drive to consider - * @mode_wanted: preferred mode - * @max_mode: highest allowed mode - * - * This routine returns the recommended PIO settings for a given drive, - * based on the drive->id information and the ide_pio_blacklist[]. - * - * Drive PIO mode is auto-selected if 255 is passed as mode_wanted. - * This is used by most chipset support modules when "auto-tuning". - */ - -u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode) -{ - u16 *id = drive->id; - int pio_mode = -1, overridden = 0; - - if (mode_wanted != 255) - return min_t(u8, mode_wanted, max_mode); - - if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0) - pio_mode = ide_scan_pio_blacklist((char *)&id[ATA_ID_PROD]); - - if (pio_mode != -1) { - printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name); - } else { - pio_mode = id[ATA_ID_OLD_PIO_MODES] >> 8; - if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ - pio_mode = 2; - overridden = 1; - } - - if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */ - if (ata_id_has_iordy(id)) { - if (id[ATA_ID_PIO_MODES] & 7) { - overridden = 0; - if (id[ATA_ID_PIO_MODES] & 4) - pio_mode = 5; - else if (id[ATA_ID_PIO_MODES] & 2) - pio_mode = 4; - else - pio_mode = 3; - } - } - } - - if (overridden) - printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n", - drive->name); - } - - if (pio_mode > max_mode) - pio_mode = max_mode; - - return pio_mode; -} -EXPORT_SYMBOL_GPL(ide_get_best_pio_mode); - -/* req_pio == "255" for auto-tune */ -void ide_set_pio(ide_drive_t *drive, u8 req_pio) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - u8 host_pio, pio; - - if (port_ops == NULL || port_ops->set_pio_mode == NULL || - (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) - return; - - BUG_ON(hwif->pio_mask == 0x00); - - host_pio = fls(hwif->pio_mask) - 1; - - pio = ide_get_best_pio_mode(drive, req_pio, host_pio); - - /* - * TODO: - * - report device max PIO mode - * - check req_pio != 255 against device max PIO mode - */ - printk(KERN_DEBUG "%s: host max PIO%d wanted PIO%d%s selected PIO%d\n", - drive->name, host_pio, req_pio, - req_pio == 255 ? "(auto-tune)" : "", pio); - - (void)ide_set_pio_mode(drive, XFER_PIO_0 + pio); -} -EXPORT_SYMBOL_GPL(ide_set_pio); - -/** - * ide_toggle_bounce - handle bounce buffering - * @drive: drive to update - * @on: on/off boolean - * - * Enable or disable bounce buffering for the device. Drives move - * between PIO and DMA and that changes the rules we need. - */ - -void ide_toggle_bounce(ide_drive_t *drive, int on) -{ - u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */ - - if (!PCI_DMA_BUS_IS_PHYS) { - addr = BLK_BOUNCE_ANY; - } else if (on && drive->media == ide_disk) { - struct device *dev = drive->hwif->dev; - - if (dev && dev->dma_mask) - addr = *dev->dma_mask; - } - - if (drive->queue) - blk_queue_bounce_limit(drive->queue, addr); -} - -int ide_set_pio_mode(ide_drive_t *drive, const u8 mode) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - - if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE) - return 0; - - if (port_ops == NULL || port_ops->set_pio_mode == NULL) - return -1; - - /* - * TODO: temporary hack for some legacy host drivers that didn't - * set transfer mode on the device in ->set_pio_mode method... - */ - if (port_ops->set_dma_mode == NULL) { - port_ops->set_pio_mode(drive, mode - XFER_PIO_0); - return 0; - } - - if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) { - if (ide_config_drive_speed(drive, mode)) - return -1; - port_ops->set_pio_mode(drive, mode - XFER_PIO_0); - return 0; - } else { - port_ops->set_pio_mode(drive, mode - XFER_PIO_0); - return ide_config_drive_speed(drive, mode); - } -} - -int ide_set_dma_mode(ide_drive_t *drive, const u8 mode) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - - if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE) - return 0; - - if (port_ops == NULL || port_ops->set_dma_mode == NULL) - return -1; - - if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) { - if (ide_config_drive_speed(drive, mode)) - return -1; - port_ops->set_dma_mode(drive, mode); - return 0; - } else { - port_ops->set_dma_mode(drive, mode); - return ide_config_drive_speed(drive, mode); - } -} -EXPORT_SYMBOL_GPL(ide_set_dma_mode); - -/** - * ide_set_xfer_rate - set transfer rate - * @drive: drive to set - * @rate: speed to attempt to set - * - * General helper for setting the speed of an IDE device. This - * function knows about user enforced limits from the configuration - * which ->set_pio_mode/->set_dma_mode does not. - */ - -int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - - if (port_ops == NULL || port_ops->set_dma_mode == NULL || - (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) - return -1; - - rate = ide_rate_filter(drive, rate); - - BUG_ON(rate < XFER_PIO_0); - - if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5) - return ide_set_pio_mode(drive, rate); - - return ide_set_dma_mode(drive, rate); -} - -static void ide_dump_opcode(ide_drive_t *drive) -{ - struct request *rq = drive->hwif->rq; - ide_task_t *task = NULL; - - if (!rq) - return; - - if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) - task = rq->special; - - printk(KERN_ERR "ide: failed opcode was: "); - if (task == NULL) - printk(KERN_CONT "unknown\n"); - else - printk(KERN_CONT "0x%02x\n", task->tf.command); -} - -u64 ide_get_lba_addr(struct ide_taskfile *tf, int lba48) -{ - u32 high, low; - - if (lba48) - high = (tf->hob_lbah << 16) | (tf->hob_lbam << 8) | - tf->hob_lbal; - else - high = tf->device & 0xf; - low = (tf->lbah << 16) | (tf->lbam << 8) | tf->lbal; - - return ((u64)high << 24) | low; -} -EXPORT_SYMBOL_GPL(ide_get_lba_addr); - -static void ide_dump_sector(ide_drive_t *drive) -{ - ide_task_t task; - struct ide_taskfile *tf = &task.tf; - u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48); - - memset(&task, 0, sizeof(task)); - if (lba48) - task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_HOB_LBA | - IDE_TFLAG_LBA48; - else - task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE; - - drive->hwif->tp_ops->tf_read(drive, &task); - - if (lba48 || (tf->device & ATA_LBA)) - printk(KERN_CONT ", LBAsect=%llu", - (unsigned long long)ide_get_lba_addr(tf, lba48)); - else - printk(KERN_CONT ", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam, - tf->device & 0xf, tf->lbal); -} - -static void ide_dump_ata_error(ide_drive_t *drive, u8 err) -{ - printk(KERN_ERR "{ "); - if (err & ATA_ABORTED) - printk(KERN_CONT "DriveStatusError "); - if (err & ATA_ICRC) - printk(KERN_CONT "%s", - (err & ATA_ABORTED) ? "BadCRC " : "BadSector "); - if (err & ATA_UNC) - printk(KERN_CONT "UncorrectableError "); - if (err & ATA_IDNF) - printk(KERN_CONT "SectorIdNotFound "); - if (err & ATA_TRK0NF) - printk(KERN_CONT "TrackZeroNotFound "); - if (err & ATA_AMNF) - printk(KERN_CONT "AddrMarkNotFound "); - printk(KERN_CONT "}"); - if ((err & (ATA_BBK | ATA_ABORTED)) == ATA_BBK || - (err & (ATA_UNC | ATA_IDNF | ATA_AMNF))) { - struct request *rq = drive->hwif->rq; - - ide_dump_sector(drive); - - if (rq) - printk(KERN_CONT ", sector=%llu", - (unsigned long long)rq->sector); - } - printk(KERN_CONT "\n"); -} - -static void ide_dump_atapi_error(ide_drive_t *drive, u8 err) -{ - printk(KERN_ERR "{ "); - if (err & ATAPI_ILI) - printk(KERN_CONT "IllegalLengthIndication "); - if (err & ATAPI_EOM) - printk(KERN_CONT "EndOfMedia "); - if (err & ATA_ABORTED) - printk(KERN_CONT "AbortedCommand "); - if (err & ATA_MCR) - printk(KERN_CONT "MediaChangeRequested "); - if (err & ATAPI_LFS) - printk(KERN_CONT "LastFailedSense=0x%02x ", - (err & ATAPI_LFS) >> 4); - printk(KERN_CONT "}\n"); -} - -/** - * ide_dump_status - translate ATA/ATAPI error - * @drive: drive that status applies to - * @msg: text message to print - * @stat: status byte to decode - * - * Error reporting, in human readable form (luxurious, but a memory hog). - * Combines the drive name, message and status byte to provide a - * user understandable explanation of the device error. - */ - -u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat) -{ - u8 err = 0; - - printk(KERN_ERR "%s: %s: status=0x%02x { ", drive->name, msg, stat); - if (stat & ATA_BUSY) - printk(KERN_CONT "Busy "); - else { - if (stat & ATA_DRDY) - printk(KERN_CONT "DriveReady "); - if (stat & ATA_DF) - printk(KERN_CONT "DeviceFault "); - if (stat & ATA_DSC) - printk(KERN_CONT "SeekComplete "); - if (stat & ATA_DRQ) - printk(KERN_CONT "DataRequest "); - if (stat & ATA_CORR) - printk(KERN_CONT "CorrectedError "); - if (stat & ATA_IDX) - printk(KERN_CONT "Index "); - if (stat & ATA_ERR) - printk(KERN_CONT "Error "); - } - printk(KERN_CONT "}\n"); - if ((stat & (ATA_BUSY | ATA_ERR)) == ATA_ERR) { - err = ide_read_error(drive); - printk(KERN_ERR "%s: %s: error=0x%02x ", drive->name, msg, err); - if (drive->media == ide_disk) - ide_dump_ata_error(drive, err); - else - ide_dump_atapi_error(drive, err); - } - ide_dump_opcode(drive); - return err; -} -EXPORT_SYMBOL(ide_dump_status); diff --git a/windhoek/ide/ide-park.c b/windhoek/ide/ide-park.c deleted file mode 100644 index c5ccf79e..00000000 --- a/windhoek/ide/ide-park.c +++ /dev/null @@ -1,126 +0,0 @@ -#include <linux/kernel.h> -#include <linux/ide.h> -#include <linux/jiffies.h> -#include <linux/blkdev.h> - -#include <ddekit/timer.h> - -DECLARE_WAIT_QUEUE_HEAD(ide_park_wq); - -static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) -{ - ide_hwif_t *hwif = drive->hwif; - struct request_queue *q = drive->queue; - struct request *rq; - int rc; - - timeout += jiffies; - spin_lock_irq(&hwif->lock); - if (drive->dev_flags & IDE_DFLAG_PARKED) { - int reset_timer = time_before(timeout, drive->sleep); - int start_queue = 0; - - drive->sleep = timeout; - wake_up_all(&ide_park_wq); - if (reset_timer && del_timer(&hwif->timer)) - start_queue = 1; - spin_unlock_irq(&hwif->lock); - - if (start_queue) { - spin_lock_irq(q->queue_lock); - blk_start_queueing(q); - spin_unlock_irq(q->queue_lock); - } - return; - } - spin_unlock_irq(&hwif->lock); - - rq = blk_get_request(q, READ, __GFP_WAIT); - rq->cmd[0] = REQ_PARK_HEADS; - rq->cmd_len = 1; - rq->cmd_type = REQ_TYPE_SPECIAL; - rq->special = &timeout; - rc = blk_execute_rq(q, NULL, rq, 1); - blk_put_request(rq); - if (rc) - goto out; - - /* - * Make sure that *some* command is sent to the drive after the - * timeout has expired, so power management will be reenabled. - */ - rq = blk_get_request(q, READ, GFP_NOWAIT); - if (unlikely(!rq)) - goto out; - - rq->cmd[0] = REQ_UNPARK_HEADS; - rq->cmd_len = 1; - rq->cmd_type = REQ_TYPE_SPECIAL; - elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 1); - -out: - return; -} - -ssize_t ide_park_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - ide_hwif_t *hwif = drive->hwif; - unsigned long now; - unsigned int msecs; - - if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD) - return -EOPNOTSUPP; - - spin_lock_irq(&hwif->lock); - now = jiffies; - if (drive->dev_flags & IDE_DFLAG_PARKED && - time_after(drive->sleep, now)) - msecs = jiffies_to_msecs(drive->sleep - now); - else - msecs = 0; - spin_unlock_irq(&hwif->lock); - - return snprintf(buf, 20, "%u\n", msecs); -} - -ssize_t ide_park_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t len) -{ -#define MAX_PARK_TIMEOUT 30000 - ide_drive_t *drive = to_ide_device(dev); - long int input; - int rc; - - rc = strict_strtol(buf, 10, &input); - if (rc || input < -2) - return -EINVAL; - if (input > MAX_PARK_TIMEOUT) { - input = MAX_PARK_TIMEOUT; - rc = -EOVERFLOW; - } - - mutex_lock(&ide_setting_mtx); - if (input >= 0) { - if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD) - rc = -EOPNOTSUPP; - else if (input || drive->dev_flags & IDE_DFLAG_PARKED) - issue_park_cmd(drive, msecs_to_jiffies(input)); - } else { - if (drive->media == ide_disk) - switch (input) { - case -1: - drive->dev_flags &= ~IDE_DFLAG_NO_UNLOAD; - break; - case -2: - drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; - break; - } - else - rc = -EOPNOTSUPP; - } - mutex_unlock(&ide_setting_mtx); - - return rc ? rc : len; -} diff --git a/windhoek/ide/ide-pci-generic.c b/windhoek/ide/ide-pci-generic.c deleted file mode 100644 index f47b9326..00000000 --- a/windhoek/ide/ide-pci-generic.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> - * Portions (C) Copyright 2002 Red Hat 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. - * - * For the avoidance of doubt the "preferred form" of this code is one which - * is in an open non patent encumbered format. Where cryptographic key signing - * forms part of the process of creating an executable the information - * including keys needed to generate an equivalently functional executable - * are deemed to be part of the source code. - */ - -#include <linux/types.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/ide.h> -#include <linux/init.h> - -#define DRV_NAME "ide_pci_generic" - -#include "local.h" - -static int ide_generic_all; /* Set to claim all devices */ - -module_param_named(all_generic_ide, ide_generic_all, bool, 0444); -MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers."); - -#define IDE_HFLAGS_UMC (IDE_HFLAG_NO_DMA | IDE_HFLAG_FORCE_LEGACY_IRQS) - -#define DECLARE_GENERIC_PCI_DEV(extra_flags) \ - { \ - .name = DRV_NAME, \ - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | \ - extra_flags, \ - .swdma_mask = ATA_SWDMA2, \ - .mwdma_mask = ATA_MWDMA2, \ - .udma_mask = ATA_UDMA6, \ - } - -static const struct ide_port_info generic_chipsets[] __devinitdata = { - /* 0: Unknown */ - DECLARE_GENERIC_PCI_DEV(0), - - { /* 1: NS87410 */ - .name = DRV_NAME, - .enablebits = { {0x43, 0x08, 0x08}, {0x47, 0x08, 0x08} }, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, - .swdma_mask = ATA_SWDMA2, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA6, - }, - - /* 2: SAMURAI / HT6565 / HINT_IDE */ - DECLARE_GENERIC_PCI_DEV(0), - /* 3: UM8673F / UM8886A / UM8886BF */ - DECLARE_GENERIC_PCI_DEV(IDE_HFLAGS_UMC), - /* 4: VIA_IDE / OPTI621V / Piccolo010{2,3,5} */ - DECLARE_GENERIC_PCI_DEV(IDE_HFLAG_NO_AUTODMA), - - { /* 5: VIA8237SATA */ - .name = DRV_NAME, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | - IDE_HFLAG_OFF_BOARD, - .swdma_mask = ATA_SWDMA2, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA6, - }, - - { /* 6: Revolution */ - .name = DRV_NAME, - .host_flags = IDE_HFLAG_CLEAR_SIMPLEX | - IDE_HFLAG_TRUST_BIOS_FOR_DMA | - IDE_HFLAG_OFF_BOARD, - .swdma_mask = ATA_SWDMA2, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA6, - } -}; - -/** - * generic_init_one - called when a PIIX is found - * @dev: the generic device - * @id: the matching pci id - * - * Called when the PCI registration layer (or the IDE initialization) - * finds a device matching our IDE device tables. - */ - -static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - const struct ide_port_info *d = &generic_chipsets[id->driver_data]; - int ret = -ENODEV; - - /* Don't use the generic entry unless instructed to do so */ - if (id->driver_data == 0 && ide_generic_all == 0) - goto out; - - switch (dev->vendor) { - case PCI_VENDOR_ID_UMC: - if (dev->device == PCI_DEVICE_ID_UMC_UM8886A && - !(PCI_FUNC(dev->devfn) & 1)) - goto out; /* UM8886A/BF pair */ - break; - case PCI_VENDOR_ID_OPTI: - if (dev->device == PCI_DEVICE_ID_OPTI_82C558 && - !(PCI_FUNC(dev->devfn) & 1)) - goto out; - break; - case PCI_VENDOR_ID_JMICRON: - if (dev->device != PCI_DEVICE_ID_JMICRON_JMB368 && - PCI_FUNC(dev->devfn) != 1) - goto out; - break; - case PCI_VENDOR_ID_NS: - if (dev->device == PCI_DEVICE_ID_NS_87410 && - (dev->class >> 8) != PCI_CLASS_STORAGE_IDE) - goto out; - break; - } - - if (dev->vendor != PCI_VENDOR_ID_JMICRON) { - u16 command; - pci_read_config_word(dev, PCI_COMMAND, &command); - if (!(command & PCI_COMMAND_IO)) { - printk(KERN_INFO "%s %s: skipping disabled " - "controller\n", d->name, pci_name(dev)); - goto out; - } - } - ret = ide_pci_init_one(dev, d, NULL); -out: - return ret; -} - -static const struct pci_device_id generic_pci_tbl[] = { - { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_87410), 1 }, - { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE), 2 }, - { PCI_VDEVICE(HOLTEK, PCI_DEVICE_ID_HOLTEK_6565), 2 }, - { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8673F), 3 }, - { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886A), 3 }, - { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886BF), 3 }, - { PCI_VDEVICE(HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), 2 }, - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C561), 4 }, - { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C558), 4 }, -#ifdef CONFIG_BLK_DEV_IDE_SATA - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8237_SATA), 5 }, -#endif - { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO), 4 }, - { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), 4 }, - { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), 4 }, - { PCI_VDEVICE(NETCELL, PCI_DEVICE_ID_REVOLUTION), 6 }, - /* - * Must come last. If you add entries adjust - * this table and generic_chipsets[] appropriately. - */ - { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, generic_pci_tbl); - -static struct pci_driver generic_pci_driver = { - .name = "PCI_IDE", - .id_table = generic_pci_tbl, - .probe = generic_init_one, - .remove = ide_pci_remove, - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init generic_ide_init(void) -{ - return ide_pci_register_driver(&generic_pci_driver); -} - -static void __exit generic_ide_exit(void) -{ - pci_unregister_driver(&generic_pci_driver); -} - -module_init(generic_ide_init); -module_exit(generic_ide_exit); - -MODULE_AUTHOR("Andre Hedrick"); -MODULE_DESCRIPTION("PCI driver module for generic PCI IDE"); -MODULE_LICENSE("GPL"); diff --git a/windhoek/ide/ide-pio-blacklist.c b/windhoek/ide/ide-pio-blacklist.c deleted file mode 100644 index a8c2c8f8..00000000 --- a/windhoek/ide/ide-pio-blacklist.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * PIO blacklist. Some drives incorrectly report their maximal PIO mode, - * at least in respect to CMD640. Here we keep info on some known drives. - * - * Changes to the ide_pio_blacklist[] should be made with EXTREME CAUTION - * to avoid breaking the fragile cmd640.c support. - */ - -#include <linux/string.h> - -static struct ide_pio_info { - const char *name; - int pio; -} ide_pio_blacklist [] = { - { "Conner Peripherals 540MB - CFS540A", 3 }, - - { "WDC AC2700", 3 }, - { "WDC AC2540", 3 }, - { "WDC AC2420", 3 }, - { "WDC AC2340", 3 }, - { "WDC AC2250", 0 }, - { "WDC AC2200", 0 }, - { "WDC AC21200", 4 }, - { "WDC AC2120", 0 }, - { "WDC AC2850", 3 }, - { "WDC AC1270", 3 }, - { "WDC AC1170", 1 }, - { "WDC AC1210", 1 }, - { "WDC AC280", 0 }, - { "WDC AC31000", 3 }, - { "WDC AC31200", 3 }, - - { "Maxtor 7131 AT", 1 }, - { "Maxtor 7171 AT", 1 }, - { "Maxtor 7213 AT", 1 }, - { "Maxtor 7245 AT", 1 }, - { "Maxtor 7345 AT", 1 }, - { "Maxtor 7546 AT", 3 }, - { "Maxtor 7540 AV", 3 }, - - { "SAMSUNG SHD-3121A", 1 }, - { "SAMSUNG SHD-3122A", 1 }, - { "SAMSUNG SHD-3172A", 1 }, - - { "ST5660A", 3 }, - { "ST3660A", 3 }, - { "ST3630A", 3 }, - { "ST3655A", 3 }, - { "ST3391A", 3 }, - { "ST3390A", 1 }, - { "ST3600A", 1 }, - { "ST3290A", 0 }, - { "ST3144A", 0 }, - { "ST3491A", 1 }, /* reports 3, should be 1 or 2 (depending on drive) - according to Seagate's FIND-ATA program */ - - { "QUANTUM ELS127A", 0 }, - { "QUANTUM ELS170A", 0 }, - { "QUANTUM LPS240A", 0 }, - { "QUANTUM LPS210A", 3 }, - { "QUANTUM LPS270A", 3 }, - { "QUANTUM LPS365A", 3 }, - { "QUANTUM LPS540A", 3 }, - { "QUANTUM LIGHTNING 540A", 3 }, - { "QUANTUM LIGHTNING 730A", 3 }, - - { "QUANTUM FIREBALL_540", 3 }, /* Older Quantum Fireballs don't work */ - { "QUANTUM FIREBALL_640", 3 }, - { "QUANTUM FIREBALL_1080", 3 }, - { "QUANTUM FIREBALL_1280", 3 }, - { NULL, 0 } -}; - -/** - * ide_scan_pio_blacklist - check for a blacklisted drive - * @model: Drive model string - * - * This routine searches the ide_pio_blacklist for an entry - * matching the start/whole of the supplied model name. - * - * Returns -1 if no match found. - * Otherwise returns the recommended PIO mode from ide_pio_blacklist[]. - */ - -int ide_scan_pio_blacklist(char *model) -{ - struct ide_pio_info *p; - - for (p = ide_pio_blacklist; p->name != NULL; p++) { - if (strncmp(p->name, model, strlen(p->name)) == 0) - return p->pio; - } - return -1; -} diff --git a/windhoek/ide/ide-pm.c b/windhoek/ide/ide-pm.c deleted file mode 100644 index 60538d9c..00000000 --- a/windhoek/ide/ide-pm.c +++ /dev/null @@ -1,239 +0,0 @@ -#include <linux/kernel.h> -#include <linux/ide.h> -#include <linux/hdreg.h> - -int generic_ide_suspend(struct device *dev, pm_message_t mesg) -{ - ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive); - ide_hwif_t *hwif = drive->hwif; - struct request *rq; - struct request_pm_state rqpm; - ide_task_t args; - int ret; - - /* call ACPI _GTM only once */ - if ((drive->dn & 1) == 0 || pair == NULL) - ide_acpi_get_timing(hwif); - - memset(&rqpm, 0, sizeof(rqpm)); - memset(&args, 0, sizeof(args)); - rq = blk_get_request(drive->queue, READ, __GFP_WAIT); - rq->cmd_type = REQ_TYPE_PM_SUSPEND; - rq->special = &args; - rq->data = &rqpm; - rqpm.pm_step = IDE_PM_START_SUSPEND; - if (mesg.event == PM_EVENT_PRETHAW) - mesg.event = PM_EVENT_FREEZE; - rqpm.pm_state = mesg.event; - - ret = blk_execute_rq(drive->queue, NULL, rq, 0); - blk_put_request(rq); - - /* call ACPI _PS3 only after both devices are suspended */ - if (ret == 0 && ((drive->dn & 1) || pair == NULL)) - ide_acpi_set_state(hwif, 0); - - return ret; -} - -int generic_ide_resume(struct device *dev) -{ - ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive); - ide_hwif_t *hwif = drive->hwif; - struct request *rq; - struct request_pm_state rqpm; - ide_task_t args; - int err; - - /* call ACPI _PS0 / _STM only once */ - if ((drive->dn & 1) == 0 || pair == NULL) { - ide_acpi_set_state(hwif, 1); - ide_acpi_push_timing(hwif); - } - - ide_acpi_exec_tfs(drive); - - memset(&rqpm, 0, sizeof(rqpm)); - memset(&args, 0, sizeof(args)); - rq = blk_get_request(drive->queue, READ, __GFP_WAIT); - rq->cmd_type = REQ_TYPE_PM_RESUME; - rq->cmd_flags |= REQ_PREEMPT; - rq->special = &args; - rq->data = &rqpm; - rqpm.pm_step = IDE_PM_START_RESUME; - rqpm.pm_state = PM_EVENT_ON; - - err = blk_execute_rq(drive->queue, NULL, rq, 1); - blk_put_request(rq); - - if (err == 0 && dev->driver) { - struct ide_driver *drv = to_ide_driver(dev->driver); - - if (drv->resume) - drv->resume(drive); - } - - return err; -} - -void ide_complete_power_step(ide_drive_t *drive, struct request *rq) -{ - struct request_pm_state *pm = rq->data; - -#ifdef DEBUG_PM - printk(KERN_INFO "%s: complete_power_step(step: %d)\n", - drive->name, pm->pm_step); -#endif - if (drive->media != ide_disk) - return; - - switch (pm->pm_step) { - case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */ - if (pm->pm_state == PM_EVENT_FREEZE) - pm->pm_step = IDE_PM_COMPLETED; - else - pm->pm_step = IDE_PM_STANDBY; - break; - case IDE_PM_STANDBY: /* Suspend step 2 (standby) */ - pm->pm_step = IDE_PM_COMPLETED; - break; - case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */ - pm->pm_step = IDE_PM_IDLE; - break; - case IDE_PM_IDLE: /* Resume step 2 (idle)*/ - pm->pm_step = IDE_PM_RESTORE_DMA; - break; - } -} - -ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) -{ - struct request_pm_state *pm = rq->data; - ide_task_t *args = rq->special; - - memset(args, 0, sizeof(*args)); - - switch (pm->pm_step) { - case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */ - if (drive->media != ide_disk) - break; - /* Not supported? Switch to next step now. */ - if (ata_id_flush_enabled(drive->id) == 0 || - (drive->dev_flags & IDE_DFLAG_WCACHE) == 0) { - ide_complete_power_step(drive, rq); - return ide_stopped; - } - if (ata_id_flush_ext_enabled(drive->id)) - args->tf.command = ATA_CMD_FLUSH_EXT; - else - args->tf.command = ATA_CMD_FLUSH; - goto out_do_tf; - case IDE_PM_STANDBY: /* Suspend step 2 (standby) */ - args->tf.command = ATA_CMD_STANDBYNOW1; - goto out_do_tf; - case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */ - ide_set_max_pio(drive); - /* - * skip IDE_PM_IDLE for ATAPI devices - */ - if (drive->media != ide_disk) - pm->pm_step = IDE_PM_RESTORE_DMA; - else - ide_complete_power_step(drive, rq); - return ide_stopped; - case IDE_PM_IDLE: /* Resume step 2 (idle) */ - args->tf.command = ATA_CMD_IDLEIMMEDIATE; - goto out_do_tf; - case IDE_PM_RESTORE_DMA: /* Resume step 3 (restore DMA) */ - /* - * Right now, all we do is call ide_set_dma(drive), - * we could be smarter and check for current xfer_speed - * in struct drive etc... - */ - if (drive->hwif->dma_ops == NULL) - break; - /* - * TODO: respect IDE_DFLAG_USING_DMA - */ - ide_set_dma(drive); - break; - } - - pm->pm_step = IDE_PM_COMPLETED; - return ide_stopped; - -out_do_tf: - args->tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - args->data_phase = TASKFILE_NO_DATA; - return do_rw_taskfile(drive, args); -} - -/** - * ide_complete_pm_request - end the current Power Management request - * @drive: target drive - * @rq: request - * - * This function cleans up the current PM request and stops the queue - * if necessary. - */ -void ide_complete_pm_request(ide_drive_t *drive, struct request *rq) -{ - struct request_queue *q = drive->queue; - unsigned long flags; - -#ifdef DEBUG_PM - printk("%s: completing PM request, %s\n", drive->name, - blk_pm_suspend_request(rq) ? "suspend" : "resume"); -#endif - spin_lock_irqsave(q->queue_lock, flags); - if (blk_pm_suspend_request(rq)) - blk_stop_queue(q); - else - drive->dev_flags &= ~IDE_DFLAG_BLOCKED; - spin_unlock_irqrestore(q->queue_lock, flags); - - drive->hwif->rq = NULL; - - if (blk_end_request(rq, 0, 0)) - BUG(); -} - -void ide_check_pm_state(ide_drive_t *drive, struct request *rq) -{ - struct request_pm_state *pm = rq->data; - - if (blk_pm_suspend_request(rq) && - pm->pm_step == IDE_PM_START_SUSPEND) - /* Mark drive blocked when starting the suspend sequence. */ - drive->dev_flags |= IDE_DFLAG_BLOCKED; - else if (blk_pm_resume_request(rq) && - pm->pm_step == IDE_PM_START_RESUME) { - /* - * The first thing we do on wakeup is to wait for BSY bit to - * go away (with a looong timeout) as a drive on this hwif may - * just be POSTing itself. - * We do that before even selecting as the "other" device on - * the bus may be broken enough to walk on our toes at this - * point. - */ - ide_hwif_t *hwif = drive->hwif; - struct request_queue *q = drive->queue; - unsigned long flags; - int rc; -#ifdef DEBUG_PM - printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name); -#endif - rc = ide_wait_not_busy(hwif, 35000); - if (rc) - printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name); - SELECT_DRIVE(drive); - hwif->tp_ops->set_irq(hwif, 1); - rc = ide_wait_not_busy(hwif, 100000); - if (rc) - printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); - - spin_lock_irqsave(q->queue_lock, flags); - blk_start_queue(q); - spin_unlock_irqrestore(q->queue_lock, flags); - } -} diff --git a/windhoek/ide/ide-pnp.c b/windhoek/ide/ide-pnp.c deleted file mode 100644 index bac9b392..00000000 --- a/windhoek/ide/ide-pnp.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * This file provides autodetection for ISA PnP IDE interfaces. - * It was tested with "ESS ES1868 Plug and Play AudioDrive" IDE interface. - * - * Copyright (C) 2000 Andrey Panin <pazke@donpac.ru> - * - * 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. - * - * You should have received a copy of the GNU General Public License - * (for example /usr/src/linux/COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/init.h> -#include <linux/pnp.h> -#include <linux/ide.h> - -#define DRV_NAME "ide-pnp" - -/* Add your devices here :)) */ -static struct pnp_device_id idepnp_devices[] = { - /* Generic ESDI/IDE/ATA compatible hard disk controller */ - {.id = "PNP0600", .driver_data = 0}, - {.id = ""} -}; - -static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) -{ - struct ide_host *host; - unsigned long base, ctl; - int rc; - hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; - - printk(KERN_INFO DRV_NAME ": generic PnP IDE interface\n"); - - if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && pnp_irq_valid(dev, 0))) - return -1; - - base = pnp_port_start(dev, 0); - ctl = pnp_port_start(dev, 1); - - if (!request_region(base, 8, DRV_NAME)) { - printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", - DRV_NAME, base, base + 7); - return -EBUSY; - } - - if (!request_region(ctl, 1, DRV_NAME)) { - printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", - DRV_NAME, ctl); - release_region(base, 8); - return -EBUSY; - } - - memset(&hw, 0, sizeof(hw)); - ide_std_init_ports(&hw, base, ctl); - hw.irq = pnp_irq(dev, 0); - hw.chipset = ide_generic; - - rc = ide_host_add(NULL, hws, &host); - if (rc) - goto out; - - pnp_set_drvdata(dev, host); - - return 0; -out: - release_region(ctl, 1); - release_region(base, 8); - - return rc; -} - -static void idepnp_remove(struct pnp_dev *dev) -{ - struct ide_host *host = pnp_get_drvdata(dev); - - ide_host_remove(host); - - release_region(pnp_port_start(dev, 1), 1); - release_region(pnp_port_start(dev, 0), 8); -} - -static struct pnp_driver idepnp_driver = { - .name = "ide", - .id_table = idepnp_devices, - .probe = idepnp_probe, - .remove = idepnp_remove, -}; - -static int __init pnpide_init(void) -{ - return pnp_register_driver(&idepnp_driver); -} - -static void __exit pnpide_exit(void) -{ - pnp_unregister_driver(&idepnp_driver); -} - -module_init(pnpide_init); -module_exit(pnpide_exit); - -MODULE_LICENSE("GPL"); diff --git a/windhoek/ide/ide-probe.c b/windhoek/ide/ide-probe.c deleted file mode 100644 index bcb299d2..00000000 --- a/windhoek/ide/ide-probe.c +++ /dev/null @@ -1,1741 +0,0 @@ -/* - * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) - * Copyright (C) 2005, 2007 Bartlomiej Zolnierkiewicz - */ - -/* - * Mostly written by Mark Lord <mlord@pobox.com> - * and Gadi Oxman <gadio@netvision.net.il> - * and Andre Hedrick <andre@linux-ide.org> - * - * See linux/MAINTAINERS for address of current maintainer. - * - * This is the IDE probe module, as evolved from hd.c and ide.c. - * - * -- increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot - * by Andrea Arcangeli - */ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/major.h> -#include <linux/errno.h> -#include <linux/genhd.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/ide.h> -#include <linux/spinlock.h> -#include <linux/kmod.h> -#include <linux/pci.h> -#include <linux/scatterlist.h> - -#include <asm/byteorder.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/io.h> - -#include "local.h" - -#include <ddekit/timer.h> - -/** - * generic_id - add a generic drive id - * @drive: drive to make an ID block for - * - * Add a fake id field to the drive we are passed. This allows - * use to skip a ton of NULL checks (which people always miss) - * and make drive properties unconditional outside of this file - */ - -static void generic_id(ide_drive_t *drive) -{ - u16 *id = drive->id; - - id[ATA_ID_CUR_CYLS] = id[ATA_ID_CYLS] = drive->cyl; - id[ATA_ID_CUR_HEADS] = id[ATA_ID_HEADS] = drive->head; - id[ATA_ID_CUR_SECTORS] = id[ATA_ID_SECTORS] = drive->sect; -} - -static void ide_disk_init_chs(ide_drive_t *drive) -{ - u16 *id = drive->id; - - /* Extract geometry if we did not already have one for the drive */ - if (!drive->cyl || !drive->head || !drive->sect) { - drive->cyl = drive->bios_cyl = id[ATA_ID_CYLS]; - drive->head = drive->bios_head = id[ATA_ID_HEADS]; - drive->sect = drive->bios_sect = id[ATA_ID_SECTORS]; - } - - /* Handle logical geometry translation by the drive */ - if (ata_id_current_chs_valid(id)) { - drive->cyl = id[ATA_ID_CUR_CYLS]; - drive->head = id[ATA_ID_CUR_HEADS]; - drive->sect = id[ATA_ID_CUR_SECTORS]; - } - - /* Use physical geometry if what we have still makes no sense */ - if (drive->head > 16 && id[ATA_ID_HEADS] && id[ATA_ID_HEADS] <= 16) { - drive->cyl = id[ATA_ID_CYLS]; - drive->head = id[ATA_ID_HEADS]; - drive->sect = id[ATA_ID_SECTORS]; - } -} - -static void ide_disk_init_mult_count(ide_drive_t *drive) -{ - u16 *id = drive->id; - u8 max_multsect = id[ATA_ID_MAX_MULTSECT] & 0xff; - - if (max_multsect) { - if ((max_multsect / 2) > 1) - id[ATA_ID_MULTSECT] = max_multsect | 0x100; - else - id[ATA_ID_MULTSECT] &= ~0x1ff; - - drive->mult_req = id[ATA_ID_MULTSECT] & 0xff; - - if (drive->mult_req) - drive->special.b.set_multmode = 1; - } -} - -static void ide_classify_ata_dev(ide_drive_t *drive) -{ - u16 *id = drive->id; - char *m = (char *)&id[ATA_ID_PROD]; - int is_cfa = ata_id_is_cfa(id); - - /* CF devices are *not* removable in Linux definition of the term */ - if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7))) - drive->dev_flags |= IDE_DFLAG_REMOVABLE; - - drive->media = ide_disk; - - if (!ata_id_has_unload(drive->id)) - drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; - - printk(KERN_INFO "%s: %s, %s DISK drive\n", drive->name, m, - is_cfa ? "CFA" : "ATA"); -} - -static void ide_classify_atapi_dev(ide_drive_t *drive) -{ - u16 *id = drive->id; - char *m = (char *)&id[ATA_ID_PROD]; - u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f; - - printk(KERN_INFO "%s: %s, ATAPI ", drive->name, m); - switch (type) { - case ide_floppy: - if (!strstr(m, "CD-ROM")) { - if (!strstr(m, "oppy") && - !strstr(m, "poyp") && - !strstr(m, "ZIP")) - printk(KERN_CONT "cdrom or floppy?, assuming "); - if (drive->media != ide_cdrom) { - printk(KERN_CONT "FLOPPY"); - drive->dev_flags |= IDE_DFLAG_REMOVABLE; - break; - } - } - /* Early cdrom models used zero */ - type = ide_cdrom; - case ide_cdrom: - drive->dev_flags |= IDE_DFLAG_REMOVABLE; -#ifdef CONFIG_PPC - /* kludge for Apple PowerBook internal zip */ - if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) { - printk(KERN_CONT "FLOPPY"); - type = ide_floppy; - break; - } -#endif - printk(KERN_CONT "CD/DVD-ROM"); - break; - case ide_tape: - printk(KERN_CONT "TAPE"); - break; - case ide_optical: - printk(KERN_CONT "OPTICAL"); - drive->dev_flags |= IDE_DFLAG_REMOVABLE; - break; - default: - printk(KERN_CONT "UNKNOWN (type %d)", type); - break; - } - - printk(KERN_CONT " drive\n"); - drive->media = type; - /* an ATAPI device ignores DRDY */ - drive->ready_stat = 0; - if (ata_id_cdb_intr(id)) - drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT; - drive->dev_flags |= IDE_DFLAG_DOORLOCKING; - /* we don't do head unloading on ATAPI devices */ - drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; -} - -/** - * do_identify - identify a drive - * @drive: drive to identify - * @cmd: command used - * - * Called when we have issued a drive identify command to - * read and parse the results. This function is run with - * interrupts disabled. - */ - -static void do_identify(ide_drive_t *drive, u8 cmd) -{ - ide_hwif_t *hwif = drive->hwif; - u16 *id = drive->id; - char *m = (char *)&id[ATA_ID_PROD]; - unsigned long flags; - int bswap = 1; - - /* local CPU only; some systems need this */ - local_irq_save(flags); - /* read 512 bytes of id info */ - hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); - local_irq_restore(flags); - - drive->dev_flags |= IDE_DFLAG_ID_READ; -#ifdef DEBUG - printk(KERN_INFO "%s: dumping identify data\n", drive->name); - ide_dump_identify((u8 *)id); -#endif - ide_fix_driveid(id); - - /* - * ATA_CMD_ID_ATA returns little-endian info, - * ATA_CMD_ID_ATAPI *usually* returns little-endian info. - */ - if (cmd == ATA_CMD_ID_ATAPI) { - if ((m[0] == 'N' && m[1] == 'E') || /* NEC */ - (m[0] == 'F' && m[1] == 'X') || /* Mitsumi */ - (m[0] == 'P' && m[1] == 'i')) /* Pioneer */ - /* Vertos drives may still be weird */ - bswap ^= 1; - } - - ide_fixstring(m, ATA_ID_PROD_LEN, bswap); - ide_fixstring((char *)&id[ATA_ID_FW_REV], ATA_ID_FW_REV_LEN, bswap); - ide_fixstring((char *)&id[ATA_ID_SERNO], ATA_ID_SERNO_LEN, bswap); - - /* we depend on this a lot! */ - m[ATA_ID_PROD_LEN - 1] = '\0'; - - if (strstr(m, "E X A B Y T E N E S T")) - goto err_misc; - - drive->dev_flags |= IDE_DFLAG_PRESENT; - drive->dev_flags &= ~IDE_DFLAG_DEAD; - - /* - * Check for an ATAPI device - */ - if (cmd == ATA_CMD_ID_ATAPI) - ide_classify_atapi_dev(drive); - else - /* - * Not an ATAPI device: looks like a "regular" hard disk - */ - ide_classify_ata_dev(drive); - return; -err_misc: - kfree(id); - drive->dev_flags &= ~IDE_DFLAG_PRESENT; -} - -/** - * actual_try_to_identify - send ata/atapi identify - * @drive: drive to identify - * @cmd: command to use - * - * try_to_identify() sends an ATA(PI) IDENTIFY request to a drive - * and waits for a response. It also monitors irqs while this is - * happening, in hope of automatically determining which one is - * being used by the interface. - * - * Returns: 0 device was identified - * 1 device timed-out (no response to identify request) - * 2 device aborted the command (refused to identify itself) - */ - -static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; - int use_altstatus = 0, rc; - unsigned long timeout; - u8 s = 0, a = 0; - - /* take a deep breath */ - msleep(50); - - if (io_ports->ctl_addr && - (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) { - a = tp_ops->read_altstatus(hwif); - s = tp_ops->read_status(hwif); - if ((a ^ s) & ~ATA_IDX) - /* ancient Seagate drives, broken interfaces */ - printk(KERN_INFO "%s: probing with STATUS(0x%02x) " - "instead of ALTSTATUS(0x%02x)\n", - drive->name, s, a); - else - /* use non-intrusive polling */ - use_altstatus = 1; - } - - /* set features register for atapi - * identify command to be sure of reply - */ - if (cmd == ATA_CMD_ID_ATAPI) { - ide_task_t task; - - memset(&task, 0, sizeof(task)); - /* disable DMA & overlap */ - task.tf_flags = IDE_TFLAG_OUT_FEATURE; - - tp_ops->tf_load(drive, &task); - } - - /* ask drive for ID */ - tp_ops->exec_command(hwif, cmd); - - timeout = ((cmd == ATA_CMD_ID_ATA) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; - - if (ide_busy_sleep(hwif, timeout, use_altstatus)) - return 1; - - /* wait for IRQ and ATA_DRQ */ - msleep(50); - s = tp_ops->read_status(hwif); - - if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) { - /* drive returned ID */ - do_identify(drive, cmd); - /* drive responded with ID */ - rc = 0; - /* clear drive IRQ */ - (void)tp_ops->read_status(hwif); - } else { - /* drive refused ID */ - rc = 2; - } - return rc; -} - -/** - * try_to_identify - try to identify a drive - * @drive: drive to probe - * @cmd: command to use - * - * Issue the identify command and then do IRQ probing to - * complete the identification when needed by finding the - * IRQ the drive is attached to - */ - -static int try_to_identify (ide_drive_t *drive, u8 cmd) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; - int retval; - int autoprobe = 0; - unsigned long cookie = 0; - - /* - * Disable device irq unless we need to - * probe for it. Otherwise we'll get spurious - * interrupts during the identify-phase that - * the irq handler isn't expecting. - */ - if (hwif->io_ports.ctl_addr) { - if (!hwif->irq) { - autoprobe = 1; - cookie = probe_irq_on(); - } - tp_ops->set_irq(hwif, autoprobe); - } - - retval = actual_try_to_identify(drive, cmd); - - if (autoprobe) { - int irq; - - tp_ops->set_irq(hwif, 0); - /* clear drive IRQ */ - (void)tp_ops->read_status(hwif); - udelay(5); - irq = probe_irq_off(cookie); - if (!hwif->irq) { - if (irq > 0) { - hwif->irq = irq; - } else { - /* Mmmm.. multiple IRQs.. - * don't know which was ours - */ - printk(KERN_ERR "%s: IRQ probe failed (0x%lx)\n", - drive->name, cookie); - } - } - } - return retval; -} - -int ide_busy_sleep(ide_hwif_t *hwif, unsigned long timeout, int altstatus) -{ - u8 stat; - - timeout += jiffies; - - do { - msleep(50); /* give drive a breather */ - stat = altstatus ? hwif->tp_ops->read_altstatus(hwif) - : hwif->tp_ops->read_status(hwif); - if ((stat & ATA_BUSY) == 0) - return 0; - } while (time_before(jiffies, timeout)); - - return 1; /* drive timed-out */ -} - -static u8 ide_read_device(ide_drive_t *drive) -{ - ide_task_t task; - - memset(&task, 0, sizeof(task)); - task.tf_flags = IDE_TFLAG_IN_DEVICE; - - drive->hwif->tp_ops->tf_read(drive, &task); - - return task.tf.device; -} - -/** - * do_probe - probe an IDE device - * @drive: drive to probe - * @cmd: command to use - * - * do_probe() has the difficult job of finding a drive if it exists, - * without getting hung up if it doesn't exist, without trampling on - * ethernet cards, and without leaving any IRQs dangling to haunt us later. - * - * If a drive is "known" to exist (from CMOS or kernel parameters), - * but does not respond right away, the probe will "hang in there" - * for the maximum wait time (about 30 seconds), otherwise it will - * exit much more quickly. - * - * Returns: 0 device was identified - * 1 device timed-out (no response to identify request) - * 2 device aborted the command (refused to identify itself) - * 3 bad status from device (possible for ATAPI drives) - * 4 probe was not attempted because failure was obvious - */ - -static int do_probe (ide_drive_t *drive, u8 cmd) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; - int rc; - u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat; - - /* avoid waiting for inappropriate probes */ - if (present && drive->media != ide_disk && cmd == ATA_CMD_ID_ATA) - return 4; - -#ifdef DEBUG - printk(KERN_INFO "probing for %s: present=%d, media=%d, probetype=%s\n", - drive->name, present, drive->media, - (cmd == ATA_CMD_ID_ATA) ? "ATA" : "ATAPI"); -#endif - - /* needed for some systems - * (e.g. crw9624 as drive0 with disk as slave) - */ - msleep(50); - SELECT_DRIVE(drive); - msleep(50); - - if (ide_read_device(drive) != drive->select && present == 0) { - if (drive->dn & 1) { - /* exit with drive0 selected */ - SELECT_DRIVE(hwif->devices[0]); - /* allow ATA_BUSY to assert & clear */ - msleep(50); - } - /* no i/f present: mmm.. this should be a 4 -ml */ - return 3; - } - - stat = tp_ops->read_status(hwif); - - if (OK_STAT(stat, ATA_DRDY, ATA_BUSY) || - present || cmd == ATA_CMD_ID_ATAPI) { - /* send cmd and wait */ - if ((rc = try_to_identify(drive, cmd))) { - /* failed: try again */ - rc = try_to_identify(drive,cmd); - } - - stat = tp_ops->read_status(hwif); - - if (stat == (ATA_BUSY | ATA_DRDY)) - return 4; - - if (rc == 1 && cmd == ATA_CMD_ID_ATAPI) { - printk(KERN_ERR "%s: no response (status = 0x%02x), " - "resetting drive\n", drive->name, stat); - msleep(50); - SELECT_DRIVE(drive); - msleep(50); - tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); - (void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0); - rc = try_to_identify(drive, cmd); - } - - /* ensure drive IRQ is clear */ - stat = tp_ops->read_status(hwif); - - if (rc == 1) - printk(KERN_ERR "%s: no response (status = 0x%02x)\n", - drive->name, stat); - } else { - /* not present or maybe ATAPI */ - rc = 3; - } - if (drive->dn & 1) { - /* exit with drive0 selected */ - SELECT_DRIVE(hwif->devices[0]); - msleep(50); - /* ensure drive irq is clear */ - (void)tp_ops->read_status(hwif); - } - return rc; -} - -/* - * - */ -static void enable_nest (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; - u8 stat; - - printk(KERN_INFO "%s: enabling %s -- ", - hwif->name, (char *)&drive->id[ATA_ID_PROD]); - - SELECT_DRIVE(drive); - msleep(50); - tp_ops->exec_command(hwif, ATA_EXABYTE_ENABLE_NEST); - - if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 0)) { - printk(KERN_CONT "failed (timeout)\n"); - return; - } - - msleep(50); - - stat = tp_ops->read_status(hwif); - - if (!OK_STAT(stat, 0, BAD_STAT)) - printk(KERN_CONT "failed (status = 0x%02x)\n", stat); - else - printk(KERN_CONT "success\n"); -} - -/** - * probe_for_drives - upper level drive probe - * @drive: drive to probe for - * - * probe_for_drive() tests for existence of a given drive using do_probe() - * and presents things to the user as needed. - * - * Returns: 0 no device was found - * 1 device was found - * (note: IDE_DFLAG_PRESENT might still be not set) - */ - -static u8 probe_for_drive(ide_drive_t *drive) -{ - char *m; - - /* - * In order to keep things simple we have an id - * block for all drives at all times. If the device - * is pre ATA or refuses ATA/ATAPI identify we - * will add faked data to this. - * - * Also note that 0 everywhere means "can't do X" - */ - - drive->dev_flags &= ~IDE_DFLAG_ID_READ; - - drive->id = kzalloc(SECTOR_SIZE, GFP_KERNEL); - if (drive->id == NULL) { - printk(KERN_ERR "ide: out of memory for id data.\n"); - return 0; - } - - m = (char *)&drive->id[ATA_ID_PROD]; - strcpy(m, "UNKNOWN"); - - /* skip probing? */ - if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0) { -retry: - /* if !(success||timed-out) */ - if (do_probe(drive, ATA_CMD_ID_ATA) >= 2) - /* look for ATAPI device */ - (void)do_probe(drive, ATA_CMD_ID_ATAPI); - - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - /* drive not found */ - return 0; - - if (strstr(m, "E X A B Y T E N E S T")) { - enable_nest(drive); - goto retry; - } - - /* identification failed? */ - if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) { - if (drive->media == ide_disk) { - printk(KERN_INFO "%s: non-IDE drive, CHS=%d/%d/%d\n", - drive->name, drive->cyl, - drive->head, drive->sect); - } else if (drive->media == ide_cdrom) { - printk(KERN_INFO "%s: ATAPI cdrom (?)\n", drive->name); - } else { - /* nuke it */ - printk(KERN_WARNING "%s: Unknown device on bus refused identification. Ignoring.\n", drive->name); - drive->dev_flags &= ~IDE_DFLAG_PRESENT; - } - } - /* drive was found */ - } - - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - return 0; - - /* The drive wasn't being helpful. Add generic info only */ - if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) { - generic_id(drive); - return 1; - } - - if (drive->media == ide_disk) { - ide_disk_init_chs(drive); - ide_disk_init_mult_count(drive); - } - - return !!(drive->dev_flags & IDE_DFLAG_PRESENT); -} - -static void hwif_release_dev(struct device *dev) -{ - ide_hwif_t *hwif = container_of(dev, ide_hwif_t, gendev); - - complete(&hwif->gendev_rel_comp); -} - -static int ide_register_port(ide_hwif_t *hwif) -{ - int ret; - - /* register with global device tree */ - dev_set_name(&hwif->gendev, hwif->name); - hwif->gendev.driver_data = hwif; - if (hwif->gendev.parent == NULL) - hwif->gendev.parent = hwif->dev; - hwif->gendev.release = hwif_release_dev; - - ret = device_register(&hwif->gendev); - if (ret < 0) { - printk(KERN_WARNING "IDE: %s: device_register error: %d\n", - __func__, ret); - goto out; - } - - hwif->portdev = device_create(ide_port_class, &hwif->gendev, - MKDEV(0, 0), hwif, hwif->name); - if (IS_ERR(hwif->portdev)) { - ret = PTR_ERR(hwif->portdev); - device_unregister(&hwif->gendev); - } -out: - return ret; -} - -/** - * ide_port_wait_ready - wait for port to become ready - * @hwif: IDE port - * - * This is needed on some PPCs and a bunch of BIOS-less embedded - * platforms. Typical cases are: - * - * - The firmware hard reset the disk before booting the kernel, - * the drive is still doing it's poweron-reset sequence, that - * can take up to 30 seconds. - * - * - The firmware does nothing (or no firmware), the device is - * still in POST state (same as above actually). - * - * - Some CD/DVD/Writer combo drives tend to drive the bus during - * their reset sequence even when they are non-selected slave - * devices, thus preventing discovery of the main HD. - * - * Doing this wait-for-non-busy should not harm any existing - * configuration and fix some issues like the above. - * - * BenH. - * - * Returns 0 on success, error code (< 0) otherwise. - */ - -static int ide_port_wait_ready(ide_hwif_t *hwif) -{ - ide_drive_t *drive; - int i, rc; - - printk(KERN_DEBUG "Probing IDE interface %s...\n", hwif->name); - - /* Let HW settle down a bit from whatever init state we - * come from */ - mdelay(2); - - /* Wait for BSY bit to go away, spec timeout is 30 seconds, - * I know of at least one disk who takes 31 seconds, I use 35 - * here to be safe - */ - rc = ide_wait_not_busy(hwif, 35000); - if (rc) - return rc; - - /* Now make sure both master & slave are ready */ - ide_port_for_each_dev(i, drive, hwif) { - /* Ignore disks that we will not probe for later. */ - if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0 || - (drive->dev_flags & IDE_DFLAG_PRESENT)) { - SELECT_DRIVE(drive); - hwif->tp_ops->set_irq(hwif, 1); - mdelay(2); - rc = ide_wait_not_busy(hwif, 35000); - if (rc) - goto out; - } else - printk(KERN_DEBUG "%s: ide_wait_not_busy() skipped\n", - drive->name); - } -out: - /* Exit function with master reselected (let's be sane) */ - if (i) - SELECT_DRIVE(hwif->devices[0]); - - return rc; -} - -/** - * ide_undecoded_slave - look for bad CF adapters - * @dev1: slave device - * - * Analyse the drives on the interface and attempt to decide if we - * have the same drive viewed twice. This occurs with crap CF adapters - * and PCMCIA sometimes. - */ - -void ide_undecoded_slave(ide_drive_t *dev1) -{ - ide_drive_t *dev0 = dev1->hwif->devices[0]; - - if ((dev1->dn & 1) == 0 || (dev0->dev_flags & IDE_DFLAG_PRESENT) == 0) - return; - - /* If the models don't match they are not the same product */ - if (strcmp((char *)&dev0->id[ATA_ID_PROD], - (char *)&dev1->id[ATA_ID_PROD])) - return; - - /* Serial numbers do not match */ - if (strncmp((char *)&dev0->id[ATA_ID_SERNO], - (char *)&dev1->id[ATA_ID_SERNO], ATA_ID_SERNO_LEN)) - return; - - /* No serial number, thankfully very rare for CF */ - if (*(char *)&dev0->id[ATA_ID_SERNO] == 0) - return; - - /* Appears to be an IDE flash adapter with decode bugs */ - printk(KERN_WARNING "ide-probe: ignoring undecoded slave\n"); - - dev1->dev_flags &= ~IDE_DFLAG_PRESENT; -} - -EXPORT_SYMBOL_GPL(ide_undecoded_slave); - -static int ide_probe_port(ide_hwif_t *hwif) -{ - ide_drive_t *drive; - unsigned long flags; - unsigned int irqd; - int i, rc = -ENODEV; - - BUG_ON(hwif->present); - - if ((hwif->devices[0]->dev_flags & IDE_DFLAG_NOPROBE) && - (hwif->devices[1]->dev_flags & IDE_DFLAG_NOPROBE)) - return -EACCES; - - /* - * We must always disable IRQ, as probe_for_drive will assert IRQ, but - * we'll install our IRQ driver much later... - */ - irqd = hwif->irq; - if (irqd) - disable_irq(hwif->irq); - - local_save_flags(flags); - local_irq_enable_in_hardirq(); - - if (ide_port_wait_ready(hwif) == -EBUSY) - printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name); - - /* - * Second drive should only exist if first drive was found, - * but a lot of cdrom drives are configured as single slaves. - */ - ide_port_for_each_dev(i, drive, hwif) { - (void) probe_for_drive(drive); - if (drive->dev_flags & IDE_DFLAG_PRESENT) - rc = 0; - } - - local_irq_restore(flags); - - /* - * Use cached IRQ number. It might be (and is...) changed by probe - * code above - */ - if (irqd) - enable_irq(irqd); - - return rc; -} - -static void ide_port_tune_devices(ide_hwif_t *hwif) -{ - const struct ide_port_ops *port_ops = hwif->port_ops; - ide_drive_t *drive; - int i; - - ide_port_for_each_dev(i, drive, hwif) { - if (drive->dev_flags & IDE_DFLAG_PRESENT) { - if (port_ops && port_ops->quirkproc) - port_ops->quirkproc(drive); - } - } - - ide_port_for_each_dev(i, drive, hwif) { - if (drive->dev_flags & IDE_DFLAG_PRESENT) { - ide_set_max_pio(drive); - - drive->dev_flags |= IDE_DFLAG_NICE1; - - if (hwif->dma_ops) - ide_set_dma(drive); - } - } - - ide_port_for_each_dev(i, drive, hwif) { - if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT) - drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT; - else - drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT; - } -} - -/* - * init request queue - */ -static int ide_init_queue(ide_drive_t *drive) -{ - struct request_queue *q; - ide_hwif_t *hwif = drive->hwif; - int max_sectors = 256; - int max_sg_entries = PRD_ENTRIES; - - /* - * Our default set up assumes the normal IDE case, - * that is 64K segmenting, standard PRD setup - * and LBA28. Some drivers then impose their own - * limits and LBA48 we could raise it but as yet - * do not. - */ - - q = blk_init_queue_node(do_ide_request, NULL, hwif_to_node(hwif)); - if (!q) - return 1; - - q->queuedata = drive; - blk_queue_segment_boundary(q, 0xffff); - - if (hwif->rqsize < max_sectors) - max_sectors = hwif->rqsize; - blk_queue_max_sectors(q, max_sectors); - -#ifdef CONFIG_PCI - /* When we have an IOMMU, we may have a problem where pci_map_sg() - * creates segments that don't completely match our boundary - * requirements and thus need to be broken up again. Because it - * doesn't align properly either, we may actually have to break up - * to more segments than what was we got in the first place, a max - * worst case is twice as many. - * This will be fixed once we teach pci_map_sg() about our boundary - * requirements, hopefully soon. *FIXME* - */ - if (!PCI_DMA_BUS_IS_PHYS) - max_sg_entries >>= 1; -#endif /* CONFIG_PCI */ - - blk_queue_max_hw_segments(q, max_sg_entries); - blk_queue_max_phys_segments(q, max_sg_entries); - - /* assign drive queue */ - drive->queue = q; - - /* needs drive->queue to be set */ - ide_toggle_bounce(drive, 1); - - return 0; -} - -static DEFINE_MUTEX(ide_cfg_mtx); - -/* - * For any present drive: - * - allocate the block device queue - */ -static int ide_port_setup_devices(ide_hwif_t *hwif) -{ - ide_drive_t *drive; - int i, j = 0; - - mutex_lock(&ide_cfg_mtx); - ide_port_for_each_dev(i, drive, hwif) { - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - continue; - - if (ide_init_queue(drive)) { - printk(KERN_ERR "ide: failed to init %s\n", - drive->name); - kfree(drive->id); - drive->id = NULL; - drive->dev_flags &= ~IDE_DFLAG_PRESENT; - continue; - } - - j++; - } - mutex_unlock(&ide_cfg_mtx); - - return j; -} - -/* - * This routine sets up the IRQ for an IDE interface. - */ -static int init_irq (ide_hwif_t *hwif) -{ - struct ide_io_ports *io_ports = &hwif->io_ports; - irq_handler_t irq_handler; - int sa = 0; - - mutex_lock(&ide_cfg_mtx); - spin_lock_init(&hwif->lock); - - init_timer(&hwif->timer); - hwif->timer.function = &ide_timer_expiry; - hwif->timer.data = (unsigned long)hwif; - - irq_handler = hwif->host->irq_handler; - if (irq_handler == NULL) - irq_handler = ide_intr; - -#if defined(__mc68000__) - sa = IRQF_SHARED; -#endif /* __mc68000__ */ - - if (hwif->chipset == ide_pci) - sa = IRQF_SHARED; - - if (io_ports->ctl_addr) - hwif->tp_ops->set_irq(hwif, 1); - - if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif)) - goto out_up; - - if (!hwif->rqsize) { - if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) || - (hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA)) - hwif->rqsize = 256; - else - hwif->rqsize = 65536; - } - -#if !defined(__mc68000__) - printk(KERN_INFO "%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name, - io_ports->data_addr, io_ports->status_addr, - io_ports->ctl_addr, hwif->irq); -#else - printk(KERN_INFO "%s at 0x%08lx on irq %d", hwif->name, - io_ports->data_addr, hwif->irq); -#endif /* __mc68000__ */ - if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) - printk(KERN_CONT " (serialized)"); - printk(KERN_CONT "\n"); - - mutex_unlock(&ide_cfg_mtx); - return 0; -out_up: - mutex_unlock(&ide_cfg_mtx); - return 1; -} - -static int ata_lock(dev_t dev, void *data) -{ - /* FIXME: we want to pin hwif down */ - return 0; -} - -static struct kobject *ata_probe(dev_t dev, int *part, void *data) -{ - ide_hwif_t *hwif = data; - int unit = *part >> PARTN_BITS; - ide_drive_t *drive = hwif->devices[unit]; - - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - return NULL; - - if (drive->media == ide_disk) - request_module("ide-disk"); - if (drive->media == ide_cdrom || drive->media == ide_optical) - request_module("ide-cd"); - if (drive->media == ide_tape) - request_module("ide-tape"); - if (drive->media == ide_floppy) - request_module("ide-floppy"); - - return NULL; -} - -static struct kobject *exact_match(dev_t dev, int *part, void *data) -{ - struct gendisk *p = data; - *part &= (1 << PARTN_BITS) - 1; - return &disk_to_dev(p)->kobj; -} - -static int exact_lock(dev_t dev, void *data) -{ - struct gendisk *p = data; - - if (!get_disk(p)) - return -1; - return 0; -} - -void ide_register_region(struct gendisk *disk) -{ - blk_register_region(MKDEV(disk->major, disk->first_minor), - disk->minors, NULL, exact_match, exact_lock, disk); -} - -EXPORT_SYMBOL_GPL(ide_register_region); - -void ide_unregister_region(struct gendisk *disk) -{ - blk_unregister_region(MKDEV(disk->major, disk->first_minor), - disk->minors); -} - -EXPORT_SYMBOL_GPL(ide_unregister_region); - -void ide_init_disk(struct gendisk *disk, ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - unsigned int unit = drive->dn & 1; - - disk->major = hwif->major; - disk->first_minor = unit << PARTN_BITS; - sprintf(disk->disk_name, "hd%c", 'a' + hwif->index * MAX_DRIVES + unit); - DEBUG_MSG("disk has a name: %s", disk->disk_name); - disk->queue = drive->queue; -} - -EXPORT_SYMBOL_GPL(ide_init_disk); - -static void drive_release_dev (struct device *dev) -{ - ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); - ide_hwif_t *hwif = drive->hwif; - - ide_proc_unregister_device(drive); - - spin_lock_irq(&hwif->lock); - kfree(drive->id); - drive->id = NULL; - drive->dev_flags &= ~IDE_DFLAG_PRESENT; - /* Messed up locking ... */ - spin_unlock_irq(&hwif->lock); - blk_cleanup_queue(drive->queue); - spin_lock_irq(&hwif->lock); - drive->queue = NULL; - spin_unlock_irq(&hwif->lock); - - complete(&drive->gendev_rel_comp); -} - -static int hwif_init(ide_hwif_t *hwif) -{ - int old_irq; - - if (!hwif->irq) { - hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); - if (!hwif->irq) { - printk(KERN_ERR "%s: disabled, no IRQ\n", hwif->name); - return 0; - } - } - - if (register_blkdev(hwif->major, hwif->name)) - return 0; - - if (!hwif->sg_max_nents) - hwif->sg_max_nents = PRD_ENTRIES; - - hwif->sg_table = kmalloc(sizeof(struct scatterlist)*hwif->sg_max_nents, - GFP_KERNEL); - if (!hwif->sg_table) { - printk(KERN_ERR "%s: unable to allocate SG table.\n", hwif->name); - goto out; - } - - sg_init_table(hwif->sg_table, hwif->sg_max_nents); - - if (init_irq(hwif) == 0) - goto done; - - old_irq = hwif->irq; - /* - * It failed to initialise. Find the default IRQ for - * this port and try that. - */ - hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); - if (!hwif->irq) { - printk(KERN_ERR "%s: disabled, unable to get IRQ %d\n", - hwif->name, old_irq); - goto out; - } - if (init_irq(hwif)) { - printk(KERN_ERR "%s: probed IRQ %d and default IRQ %d failed\n", - hwif->name, old_irq, hwif->irq); - goto out; - } - printk(KERN_WARNING "%s: probed IRQ %d failed, using default\n", - hwif->name, hwif->irq); - -done: - blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS, - THIS_MODULE, ata_probe, ata_lock, hwif); - return 1; - -out: - unregister_blkdev(hwif->major, hwif->name); - return 0; -} - -static void hwif_register_devices(ide_hwif_t *hwif) -{ - ide_drive_t *drive; - unsigned int i; - - ide_port_for_each_dev(i, drive, hwif) { - struct device *dev = &drive->gendev; - int ret; - - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - continue; - - dev_set_name(dev, "%u.%u", hwif->index, i); - dev->parent = &hwif->gendev; - dev->bus = &ide_bus_type; - dev->driver_data = drive; - dev->release = drive_release_dev; - - ret = device_register(dev); - if (ret < 0) - printk(KERN_WARNING "IDE: %s: device_register error: " - "%d\n", __func__, ret); - } -} - -static void ide_port_init_devices(ide_hwif_t *hwif) -{ - const struct ide_port_ops *port_ops = hwif->port_ops; - ide_drive_t *drive; - int i; - - ide_port_for_each_dev(i, drive, hwif) { - drive->dn = i + hwif->channel * 2; - - if (hwif->host_flags & IDE_HFLAG_IO_32BIT) - drive->io_32bit = 1; - if (hwif->host_flags & IDE_HFLAG_UNMASK_IRQS) - drive->dev_flags |= IDE_DFLAG_UNMASK; - if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS) - drive->dev_flags |= IDE_DFLAG_NO_UNMASK; - - if (port_ops && port_ops->init_dev) - port_ops->init_dev(drive); - } -} - -static void ide_init_port(ide_hwif_t *hwif, unsigned int port, - const struct ide_port_info *d) -{ - hwif->channel = port; - - if (d->chipset) - hwif->chipset = d->chipset; - - if (d->init_iops) - d->init_iops(hwif); - - if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || - (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) - hwif->irq = port ? 15 : 14; - - /* ->host_flags may be set by ->init_iops (or even earlier...) */ - hwif->host_flags |= d->host_flags; - hwif->pio_mask = d->pio_mask; - - if (d->tp_ops) - hwif->tp_ops = d->tp_ops; - - /* ->set_pio_mode for DTC2278 is currently limited to port 0 */ - if (hwif->chipset != ide_dtc2278 || hwif->channel == 0) - hwif->port_ops = d->port_ops; - - hwif->swdma_mask = d->swdma_mask; - hwif->mwdma_mask = d->mwdma_mask; - hwif->ultra_mask = d->udma_mask; - - if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) { - int rc; - - hwif->dma_ops = d->dma_ops; - - if (d->init_dma) - rc = d->init_dma(hwif, d); - else - rc = ide_hwif_setup_dma(hwif, d); - - if (rc < 0) { - printk(KERN_INFO "%s: DMA disabled\n", hwif->name); - - hwif->dma_ops = NULL; - hwif->dma_base = 0; - hwif->swdma_mask = 0; - hwif->mwdma_mask = 0; - hwif->ultra_mask = 0; - } - } - - if ((d->host_flags & IDE_HFLAG_SERIALIZE) || - ((d->host_flags & IDE_HFLAG_SERIALIZE_DMA) && hwif->dma_base)) - hwif->host->host_flags |= IDE_HFLAG_SERIALIZE; - - if (d->max_sectors) - hwif->rqsize = d->max_sectors; - - /* call chipset specific routine for each enabled port */ - if (d->init_hwif) - d->init_hwif(hwif); -} - -static void ide_port_cable_detect(ide_hwif_t *hwif) -{ - const struct ide_port_ops *port_ops = hwif->port_ops; - - if (port_ops && port_ops->cable_detect && (hwif->ultra_mask & 0x78)) { - if (hwif->cbl != ATA_CBL_PATA40_SHORT) - hwif->cbl = port_ops->cable_detect(hwif); - } -} - -static const u8 ide_hwif_to_major[] = - { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, - IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR }; - -static void ide_port_init_devices_data(ide_hwif_t *hwif) -{ - ide_drive_t *drive; - int i; - - ide_port_for_each_dev(i, drive, hwif) { - u8 j = (hwif->index * MAX_DRIVES) + i; - - memset(drive, 0, sizeof(*drive)); - - drive->media = ide_disk; - drive->select = (i << 4) | ATA_DEVICE_OBS; - drive->hwif = hwif; - drive->ready_stat = ATA_DRDY; - drive->bad_wstat = BAD_W_STAT; - drive->special.b.recalibrate = 1; - drive->special.b.set_geometry = 1; - drive->name[0] = 'h'; - drive->name[1] = 'd'; - drive->name[2] = 'a' + j; - drive->max_failures = IDE_DEFAULT_MAX_FAILURES; - - INIT_LIST_HEAD(&drive->list); - init_completion(&drive->gendev_rel_comp); - } -} - -static void ide_init_port_data(ide_hwif_t *hwif, unsigned int index) -{ - /* fill in any non-zero initial values */ - hwif->index = index; - hwif->major = ide_hwif_to_major[index]; - - hwif->name[0] = 'i'; - hwif->name[1] = 'd'; - hwif->name[2] = 'e'; - hwif->name[3] = '0' + index; - - init_completion(&hwif->gendev_rel_comp); - - hwif->tp_ops = &default_tp_ops; - - ide_port_init_devices_data(hwif); -} - -static void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw) -{ - memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports)); - hwif->irq = hw->irq; - hwif->chipset = hw->chipset; - hwif->dev = hw->dev; - hwif->gendev.parent = hw->parent ? hw->parent : hw->dev; - hwif->ack_intr = hw->ack_intr; - hwif->config_data = hw->config; -} - -static unsigned int ide_indexes; - -/** - * ide_find_port_slot - find free port slot - * @d: IDE port info - * - * Return the new port slot index or -ENOENT if we are out of free slots. - */ - -static int ide_find_port_slot(const struct ide_port_info *d) -{ - int idx = -ENOENT; - u8 bootable = (d && (d->host_flags & IDE_HFLAG_NON_BOOTABLE)) ? 0 : 1; - u8 i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;; - - /* - * Claim an unassigned slot. - * - * Give preference to claiming other slots before claiming ide0/ide1, - * just in case there's another interface yet-to-be-scanned - * which uses ports 0x1f0/0x170 (the ide0/ide1 defaults). - * - * Unless there is a bootable card that does not use the standard - * ports 0x1f0/0x170 (the ide0/ide1 defaults). - */ - mutex_lock(&ide_cfg_mtx); - if (bootable) { - if ((ide_indexes | i) != (1 << MAX_HWIFS) - 1) - idx = ffz(ide_indexes | i); - } else { - if ((ide_indexes | 3) != (1 << MAX_HWIFS) - 1) - idx = ffz(ide_indexes | 3); - else if ((ide_indexes & 3) != 3) - idx = ffz(ide_indexes); - } - if (idx >= 0) - ide_indexes |= (1 << idx); - mutex_unlock(&ide_cfg_mtx); - - return idx; -} - -static void ide_free_port_slot(int idx) -{ - mutex_lock(&ide_cfg_mtx); - ide_indexes &= ~(1 << idx); - mutex_unlock(&ide_cfg_mtx); -} - -static void ide_port_free_devices(ide_hwif_t *hwif) -{ - ide_drive_t *drive; - int i; - - ide_port_for_each_dev(i, drive, hwif) - kfree(drive); -} - -static int ide_port_alloc_devices(ide_hwif_t *hwif, int node) -{ - int i; - - for (i = 0; i < MAX_DRIVES; i++) { - ide_drive_t *drive; - - drive = kzalloc_node(sizeof(*drive), GFP_KERNEL, node); - if (drive == NULL) - goto out_nomem; - - hwif->devices[i] = drive; - } - return 0; - -out_nomem: - ide_port_free_devices(hwif); - return -ENOMEM; -} - -struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws) -{ - struct ide_host *host; - struct device *dev = hws[0] ? hws[0]->dev : NULL; - int node = dev ? dev_to_node(dev) : -1; - int i; - - host = kzalloc_node(sizeof(*host), GFP_KERNEL, node); - if (host == NULL) - return NULL; - - for (i = 0; i < MAX_HOST_PORTS; i++) { - ide_hwif_t *hwif; - int idx; - - if (hws[i] == NULL) - continue; - - hwif = kzalloc_node(sizeof(*hwif), GFP_KERNEL, node); - if (hwif == NULL) - continue; - - if (ide_port_alloc_devices(hwif, node) < 0) { - kfree(hwif); - continue; - } - - idx = ide_find_port_slot(d); - if (idx < 0) { - printk(KERN_ERR "%s: no free slot for interface\n", - d ? d->name : "ide"); - kfree(hwif); - continue; - } - - ide_init_port_data(hwif, idx); - - hwif->host = host; - - host->ports[i] = hwif; - host->n_ports++; - } - - if (host->n_ports == 0) { - kfree(host); - return NULL; - } - - host->dev[0] = dev; - - if (d) { - host->init_chipset = d->init_chipset; - host->host_flags = d->host_flags; - } - - return host; -} -EXPORT_SYMBOL_GPL(ide_host_alloc); - -static void ide_port_free(ide_hwif_t *hwif) -{ - ide_port_free_devices(hwif); - ide_free_port_slot(hwif->index); - kfree(hwif); -} - -static void ide_disable_port(ide_hwif_t *hwif) -{ - struct ide_host *host = hwif->host; - int i; - - printk(KERN_INFO "%s: disabling port\n", hwif->name); - - for (i = 0; i < MAX_HOST_PORTS; i++) { - if (host->ports[i] == hwif) { - host->ports[i] = NULL; - host->n_ports--; - } - } - - ide_port_free(hwif); -} - -int ide_host_register(struct ide_host *host, const struct ide_port_info *d, - hw_regs_t **hws) -{ - ide_hwif_t *hwif, *mate = NULL; - int i, j = 0; - - ide_host_for_each_port(i, hwif, host) { - if (hwif == NULL) { - mate = NULL; - continue; - } - - ide_init_port_hw(hwif, hws[i]); - ide_port_apply_params(hwif); - - if (d == NULL) { - mate = NULL; - } else { - if ((i & 1) && mate) { - hwif->mate = mate; - mate->mate = hwif; - } - - mate = (i & 1) ? NULL : hwif; - - ide_init_port(hwif, i & 1, d); - ide_port_cable_detect(hwif); - } - - ide_port_init_devices(hwif); - } - - ide_host_for_each_port(i, hwif, host) { - if (hwif == NULL) - continue; - - if (ide_probe_port(hwif) == 0) - hwif->present = 1; - - if (hwif->chipset != ide_4drives || !hwif->mate || - !hwif->mate->present) { - if (ide_register_port(hwif)) { - ide_disable_port(hwif); - continue; - } - } - - if (hwif->present) - ide_port_tune_devices(hwif); - } - - ide_host_for_each_port(i, hwif, host) { - if (hwif == NULL) - continue; - - if (hwif_init(hwif) == 0) { - printk(KERN_INFO "%s: failed to initialize IDE " - "interface\n", hwif->name); - device_unregister(&hwif->gendev); - ide_disable_port(hwif); - continue; - } - - if (hwif->present) - if (ide_port_setup_devices(hwif) == 0) { - hwif->present = 0; - continue; - } - - j++; - - ide_acpi_init(hwif); - - if (hwif->present) - ide_acpi_port_init_devices(hwif); - } - - ide_host_for_each_port(i, hwif, host) { - if (hwif == NULL) - continue; - - if (hwif->present) - hwif_register_devices(hwif); - } - - ide_host_for_each_port(i, hwif, host) { - if (hwif == NULL) - continue; - - ide_sysfs_register_port(hwif); - ide_proc_register_port(hwif); - - if (hwif->present) - ide_proc_port_register_devices(hwif); - } - - return j ? 0 : -1; -} -EXPORT_SYMBOL_GPL(ide_host_register); - -int ide_host_add(const struct ide_port_info *d, hw_regs_t **hws, - struct ide_host **hostp) -{ - struct ide_host *host; - int rc; - - host = ide_host_alloc(d, hws); - if (host == NULL) - return -ENOMEM; - - rc = ide_host_register(host, d, hws); - if (rc) { - ide_host_free(host); - return rc; - } - - if (hostp) - *hostp = host; - - return 0; -} -EXPORT_SYMBOL_GPL(ide_host_add); - -static void __ide_port_unregister_devices(ide_hwif_t *hwif) -{ - ide_drive_t *drive; - int i; - - ide_port_for_each_dev(i, drive, hwif) { - if (drive->dev_flags & IDE_DFLAG_PRESENT) { - device_unregister(&drive->gendev); - wait_for_completion(&drive->gendev_rel_comp); - } - } -} - -void ide_port_unregister_devices(ide_hwif_t *hwif) -{ - mutex_lock(&ide_cfg_mtx); - __ide_port_unregister_devices(hwif); - hwif->present = 0; - ide_port_init_devices_data(hwif); - mutex_unlock(&ide_cfg_mtx); -} -EXPORT_SYMBOL_GPL(ide_port_unregister_devices); - -/** - * ide_unregister - free an IDE interface - * @hwif: IDE interface - * - * Perform the final unregister of an IDE interface. - * - * Locking: - * The caller must not hold the IDE locks. - * - * It is up to the caller to be sure there is no pending I/O here, - * and that the interface will not be reopened (present/vanishing - * locking isn't yet done BTW). - */ - -static void ide_unregister(ide_hwif_t *hwif) -{ - BUG_ON(in_interrupt()); - BUG_ON(irqs_disabled()); - - mutex_lock(&ide_cfg_mtx); - - if (hwif->present) { - __ide_port_unregister_devices(hwif); - hwif->present = 0; - } - - ide_proc_unregister_port(hwif); - - free_irq(hwif->irq, hwif); - - device_unregister(hwif->portdev); - device_unregister(&hwif->gendev); - wait_for_completion(&hwif->gendev_rel_comp); - - /* - * Remove us from the kernel's knowledge - */ - blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<<PARTN_BITS); - kfree(hwif->sg_table); - unregister_blkdev(hwif->major, hwif->name); - - ide_release_dma_engine(hwif); - - mutex_unlock(&ide_cfg_mtx); -} - -void ide_host_free(struct ide_host *host) -{ - ide_hwif_t *hwif; - int i; - - ide_host_for_each_port(i, hwif, host) { - if (hwif) - ide_port_free(hwif); - } - - kfree(host); -} -EXPORT_SYMBOL_GPL(ide_host_free); - -void ide_host_remove(struct ide_host *host) -{ - ide_hwif_t *hwif; - int i; - - ide_host_for_each_port(i, hwif, host) { - if (hwif) - ide_unregister(hwif); - } - - ide_host_free(host); -} -EXPORT_SYMBOL_GPL(ide_host_remove); - -void ide_port_scan(ide_hwif_t *hwif) -{ - ide_port_apply_params(hwif); - ide_port_cable_detect(hwif); - ide_port_init_devices(hwif); - - if (ide_probe_port(hwif) < 0) - return; - - hwif->present = 1; - - ide_port_tune_devices(hwif); - ide_port_setup_devices(hwif); - ide_acpi_port_init_devices(hwif); - hwif_register_devices(hwif); - ide_proc_port_register_devices(hwif); -} -EXPORT_SYMBOL_GPL(ide_port_scan); diff --git a/windhoek/ide/ide-proc.c b/windhoek/ide/ide-proc.c deleted file mode 100644 index a7b9287e..00000000 --- a/windhoek/ide/ide-proc.c +++ /dev/null @@ -1,701 +0,0 @@ -/* - * Copyright (C) 1997-1998 Mark Lord - * Copyright (C) 2003 Red Hat - * - * Some code was moved here from ide.c, see it for original copyrights. - */ - -/* - * This is the /proc/ide/ filesystem implementation. - * - * Drive/Driver settings can be retrieved by reading the drive's - * "settings" files. e.g. "cat /proc/ide0/hda/settings" - * To write a new value "val" into a specific setting "name", use: - * echo "name:val" >/proc/ide/ide0/hda/settings - */ - -#include <linux/module.h> - -#include <asm/uaccess.h> -#include <linux/errno.h> -#include <linux/proc_fs.h> -#include <linux/stat.h> -#include <linux/mm.h> -#include <linux/pci.h> -#include <linux/ctype.h> -#include <linux/ide.h> -#include <linux/seq_file.h> - -#include <asm/io.h> - -static struct proc_dir_entry *proc_ide_root; - -static int proc_ide_read_imodel - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_hwif_t *hwif = (ide_hwif_t *) data; - int len; - const char *name; - - switch (hwif->chipset) { - case ide_generic: name = "generic"; break; - case ide_pci: name = "pci"; break; - case ide_cmd640: name = "cmd640"; break; - case ide_dtc2278: name = "dtc2278"; break; - case ide_ali14xx: name = "ali14xx"; break; - case ide_qd65xx: name = "qd65xx"; break; - case ide_umc8672: name = "umc8672"; break; - case ide_ht6560b: name = "ht6560b"; break; - case ide_4drives: name = "4drives"; break; - case ide_pmac: name = "mac-io"; break; - case ide_au1xxx: name = "au1xxx"; break; - case ide_palm3710: name = "palm3710"; break; - case ide_acorn: name = "acorn"; break; - default: name = "(unknown)"; break; - } - len = sprintf(page, "%s\n", name); - PROC_IDE_READ_RETURN(page, start, off, count, eof, len); -} - -static int proc_ide_read_mate - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_hwif_t *hwif = (ide_hwif_t *) data; - int len; - - if (hwif && hwif->mate) - len = sprintf(page, "%s\n", hwif->mate->name); - else - len = sprintf(page, "(none)\n"); - PROC_IDE_READ_RETURN(page, start, off, count, eof, len); -} - -static int proc_ide_read_channel - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_hwif_t *hwif = (ide_hwif_t *) data; - int len; - - page[0] = hwif->channel ? '1' : '0'; - page[1] = '\n'; - len = 2; - PROC_IDE_READ_RETURN(page, start, off, count, eof, len); -} - -static int proc_ide_read_identify - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *)data; - int len = 0, i = 0; - int err = 0; - - len = sprintf(page, "\n"); - - if (drive) { - __le16 *val = (__le16 *)page; - - err = taskfile_lib_get_identify(drive, page); - if (!err) { - char *out = (char *)page + SECTOR_SIZE; - - page = out; - do { - out += sprintf(out, "%04x%c", - le16_to_cpup(val), (++i & 7) ? ' ' : '\n'); - val += 1; - } while (i < SECTOR_SIZE / 2); - len = out - page; - } - } - PROC_IDE_READ_RETURN(page, start, off, count, eof, len); -} - -/** - * ide_find_setting - find a specific setting - * @st: setting table pointer - * @name: setting name - * - * Scan's the setting table for a matching entry and returns - * this or NULL if no entry is found. The caller must hold the - * setting semaphore - */ - -static -const struct ide_proc_devset *ide_find_setting(const struct ide_proc_devset *st, - char *name) -{ - while (st->name) { - if (strcmp(st->name, name) == 0) - break; - st++; - } - return st->name ? st : NULL; -} - -/** - * ide_read_setting - read an IDE setting - * @drive: drive to read from - * @setting: drive setting - * - * Read a drive setting and return the value. The caller - * must hold the ide_setting_mtx when making this call. - * - * BUGS: the data return and error are the same return value - * so an error -EINVAL and true return of the same value cannot - * be told apart - */ - -static int ide_read_setting(ide_drive_t *drive, - const struct ide_proc_devset *setting) -{ - const struct ide_devset *ds = setting->setting; - int val = -EINVAL; - - if (ds->get) - val = ds->get(drive); - - return val; -} - -/** - * ide_write_setting - read an IDE setting - * @drive: drive to read from - * @setting: drive setting - * @val: value - * - * Write a drive setting if it is possible. The caller - * must hold the ide_setting_mtx when making this call. - * - * BUGS: the data return and error are the same return value - * so an error -EINVAL and true return of the same value cannot - * be told apart - * - * FIXME: This should be changed to enqueue a special request - * to the driver to change settings, and then wait on a sema for completion. - * The current scheme of polling is kludgy, though safe enough. - */ - -static int ide_write_setting(ide_drive_t *drive, - const struct ide_proc_devset *setting, int val) -{ - const struct ide_devset *ds = setting->setting; - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (!ds->set) - return -EPERM; - if ((ds->flags & DS_SYNC) - && (val < setting->min || val > setting->max)) - return -EINVAL; - return ide_devset_execute(drive, ds, val); -} - -ide_devset_get(xfer_rate, current_speed); - -static int set_xfer_rate (ide_drive_t *drive, int arg) -{ - ide_task_t task; - int err; - - if (arg < XFER_PIO_0 || arg > XFER_UDMA_6) - return -EINVAL; - - memset(&task, 0, sizeof(task)); - task.tf.command = ATA_CMD_SET_FEATURES; - task.tf.feature = SETFEATURES_XFER; - task.tf.nsect = (u8)arg; - task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT | - IDE_TFLAG_IN_NSECT; - - err = ide_no_data_taskfile(drive, &task); - - if (!err) { - ide_set_xfer_rate(drive, (u8) arg); - ide_driveid_update(drive); - } - return err; -} - -ide_devset_rw(current_speed, xfer_rate); -ide_devset_rw_field(init_speed, init_speed); -ide_devset_rw_flag(nice1, IDE_DFLAG_NICE1); -ide_devset_rw_field(number, dn); - -static const struct ide_proc_devset ide_generic_settings[] = { - IDE_PROC_DEVSET(current_speed, 0, 70), - IDE_PROC_DEVSET(init_speed, 0, 70), - IDE_PROC_DEVSET(io_32bit, 0, 1 + (SUPPORT_VLB_SYNC << 1)), - IDE_PROC_DEVSET(keepsettings, 0, 1), - IDE_PROC_DEVSET(nice1, 0, 1), - IDE_PROC_DEVSET(number, 0, 3), - IDE_PROC_DEVSET(pio_mode, 0, 255), - IDE_PROC_DEVSET(unmaskirq, 0, 1), - IDE_PROC_DEVSET(using_dma, 0, 1), - { NULL }, -}; - -static void proc_ide_settings_warn(void) -{ - static int warned; - - if (warned) - return; - - printk(KERN_WARNING "Warning: /proc/ide/hd?/settings interface is " - "obsolete, and will be removed soon!\n"); - warned = 1; -} - -static int proc_ide_read_settings - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - const struct ide_proc_devset *setting, *g, *d; - const struct ide_devset *ds; - ide_drive_t *drive = (ide_drive_t *) data; - char *out = page; - int len, rc, mul_factor, div_factor; - - proc_ide_settings_warn(); - - mutex_lock(&ide_setting_mtx); - g = ide_generic_settings; - d = drive->settings; - out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n"); - out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n"); - while (g->name || (d && d->name)) { - /* read settings in the alphabetical order */ - if (g->name && d && d->name) { - if (strcmp(d->name, g->name) < 0) - setting = d++; - else - setting = g++; - } else if (d && d->name) { - setting = d++; - } else - setting = g++; - mul_factor = setting->mulf ? setting->mulf(drive) : 1; - div_factor = setting->divf ? setting->divf(drive) : 1; - out += sprintf(out, "%-24s", setting->name); - rc = ide_read_setting(drive, setting); - if (rc >= 0) - out += sprintf(out, "%-16d", rc * mul_factor / div_factor); - else - out += sprintf(out, "%-16s", "write-only"); - out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor); - ds = setting->setting; - if (ds->get) - out += sprintf(out, "r"); - if (ds->set) - out += sprintf(out, "w"); - out += sprintf(out, "\n"); - } - len = out - page; - mutex_unlock(&ide_setting_mtx); - PROC_IDE_READ_RETURN(page, start, off, count, eof, len); -} - -#define MAX_LEN 30 - -static int proc_ide_write_settings(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - char name[MAX_LEN + 1]; - int for_real = 0, mul_factor, div_factor; - unsigned long n; - - const struct ide_proc_devset *setting; - char *buf, *s; - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - proc_ide_settings_warn(); - - if (count >= PAGE_SIZE) - return -EINVAL; - - s = buf = (char *)__get_free_page(GFP_USER); - if (!buf) - return -ENOMEM; - - if (copy_from_user(buf, buffer, count)) { - free_page((unsigned long)buf); - return -EFAULT; - } - - buf[count] = '\0'; - - /* - * Skip over leading whitespace - */ - while (count && isspace(*s)) { - --count; - ++s; - } - /* - * Do one full pass to verify all parameters, - * then do another to actually write the new settings. - */ - do { - char *p = s; - n = count; - while (n > 0) { - unsigned val; - char *q = p; - - while (n > 0 && *p != ':') { - --n; - p++; - } - if (*p != ':') - goto parse_error; - if (p - q > MAX_LEN) - goto parse_error; - memcpy(name, q, p - q); - name[p - q] = 0; - - if (n > 0) { - --n; - p++; - } else - goto parse_error; - - val = simple_strtoul(p, &q, 10); - n -= q - p; - p = q; - if (n > 0 && !isspace(*p)) - goto parse_error; - while (n > 0 && isspace(*p)) { - --n; - ++p; - } - - mutex_lock(&ide_setting_mtx); - /* generic settings first, then driver specific ones */ - setting = ide_find_setting(ide_generic_settings, name); - if (!setting) { - if (drive->settings) - setting = ide_find_setting(drive->settings, name); - if (!setting) { - mutex_unlock(&ide_setting_mtx); - goto parse_error; - } - } - if (for_real) { - mul_factor = setting->mulf ? setting->mulf(drive) : 1; - div_factor = setting->divf ? setting->divf(drive) : 1; - ide_write_setting(drive, setting, val * div_factor / mul_factor); - } - mutex_unlock(&ide_setting_mtx); - } - } while (!for_real++); - free_page((unsigned long)buf); - return count; -parse_error: - free_page((unsigned long)buf); - printk("proc_ide_write_settings(): parse error\n"); - return -EINVAL; -} - -int proc_ide_read_capacity - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = sprintf(page, "%llu\n", (long long)0x7fffffff); - PROC_IDE_READ_RETURN(page, start, off, count, eof, len); -} - -EXPORT_SYMBOL_GPL(proc_ide_read_capacity); - -int proc_ide_read_geometry - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - char *out = page; - int len; - - out += sprintf(out, "physical %d/%d/%d\n", - drive->cyl, drive->head, drive->sect); - out += sprintf(out, "logical %d/%d/%d\n", - drive->bios_cyl, drive->bios_head, drive->bios_sect); - - len = out - page; - PROC_IDE_READ_RETURN(page, start, off, count, eof, len); -} - -EXPORT_SYMBOL(proc_ide_read_geometry); - -static int proc_ide_read_dmodel - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - char *m = (char *)&drive->id[ATA_ID_PROD]; - int len; - - len = sprintf(page, "%.40s\n", m[0] ? m : "(none)"); - PROC_IDE_READ_RETURN(page, start, off, count, eof, len); -} - -static int proc_ide_read_driver - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *)data; - struct device *dev = &drive->gendev; - struct ide_driver *ide_drv; - int len; - - if (dev->driver) { - ide_drv = to_ide_driver(dev->driver); - len = sprintf(page, "%s version %s\n", - dev->driver->name, ide_drv->version); - } else - len = sprintf(page, "ide-default version 0.9.newide\n"); - PROC_IDE_READ_RETURN(page, start, off, count, eof, len); -} - -static int ide_replace_subdriver(ide_drive_t *drive, const char *driver) -{ - struct device *dev = &drive->gendev; - int ret = 1; - int err; - - device_release_driver(dev); - /* FIXME: device can still be in use by previous driver */ - strlcpy(drive->driver_req, driver, sizeof(drive->driver_req)); - err = device_attach(dev); - if (err < 0) - printk(KERN_WARNING "IDE: %s: device_attach error: %d\n", - __func__, err); - drive->driver_req[0] = 0; - if (dev->driver == NULL) { - err = device_attach(dev); - if (err < 0) - printk(KERN_WARNING - "IDE: %s: device_attach(2) error: %d\n", - __func__, err); - } - if (dev->driver && !strcmp(dev->driver->name, driver)) - ret = 0; - - return ret; -} - -static int proc_ide_write_driver - (struct file *file, const char __user *buffer, unsigned long count, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - char name[32]; - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (count > 31) - count = 31; - if (copy_from_user(name, buffer, count)) - return -EFAULT; - name[count] = '\0'; - if (ide_replace_subdriver(drive, name)) - return -EINVAL; - return count; -} - -static int proc_ide_read_media - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - const char *media; - int len; - - switch (drive->media) { - case ide_disk: media = "disk\n"; break; - case ide_cdrom: media = "cdrom\n"; break; - case ide_tape: media = "tape\n"; break; - case ide_floppy: media = "floppy\n"; break; - case ide_optical: media = "optical\n"; break; - default: media = "UNKNOWN\n"; break; - } - strcpy(page, media); - len = strlen(media); - PROC_IDE_READ_RETURN(page, start, off, count, eof, len); -} - -static ide_proc_entry_t generic_drive_entries[] = { - { "driver", S_IFREG|S_IRUGO, proc_ide_read_driver, - proc_ide_write_driver }, - { "identify", S_IFREG|S_IRUSR, proc_ide_read_identify, NULL }, - { "media", S_IFREG|S_IRUGO, proc_ide_read_media, NULL }, - { "model", S_IFREG|S_IRUGO, proc_ide_read_dmodel, NULL }, - { "settings", S_IFREG|S_IRUSR|S_IWUSR, proc_ide_read_settings, - proc_ide_write_settings }, - { NULL, 0, NULL, NULL } -}; - -static void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data) -{ - struct proc_dir_entry *ent; - - if (!dir || !p) - return; - while (p->name != NULL) { - ent = create_proc_entry(p->name, p->mode, dir); - if (!ent) return; - ent->data = data; - ent->read_proc = p->read_proc; - ent->write_proc = p->write_proc; - p++; - } -} - -static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p) -{ - if (!dir || !p) - return; - while (p->name != NULL) { - remove_proc_entry(p->name, dir); - p++; - } -} - -void ide_proc_register_driver(ide_drive_t *drive, struct ide_driver *driver) -{ - mutex_lock(&ide_setting_mtx); - drive->settings = driver->proc_devsets(drive); - mutex_unlock(&ide_setting_mtx); - - ide_add_proc_entries(drive->proc, driver->proc_entries(drive), drive); -} - -EXPORT_SYMBOL(ide_proc_register_driver); - -/** - * ide_proc_unregister_driver - remove driver specific data - * @drive: drive - * @driver: driver - * - * Clean up the driver specific /proc files and IDE settings - * for a given drive. - * - * Takes ide_setting_mtx. - */ - -void ide_proc_unregister_driver(ide_drive_t *drive, struct ide_driver *driver) -{ - ide_remove_proc_entries(drive->proc, driver->proc_entries(drive)); - - mutex_lock(&ide_setting_mtx); - /* - * ide_setting_mtx protects both the settings list and the use - * of settings (we cannot take a setting out that is being used). - */ - drive->settings = NULL; - mutex_unlock(&ide_setting_mtx); -} -EXPORT_SYMBOL(ide_proc_unregister_driver); - -void ide_proc_port_register_devices(ide_hwif_t *hwif) -{ - struct proc_dir_entry *ent; - struct proc_dir_entry *parent = hwif->proc; - ide_drive_t *drive; - char name[64]; - int i; - - ide_port_for_each_dev(i, drive, hwif) { - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0 || drive->proc) - continue; - - drive->proc = proc_mkdir(drive->name, parent); - if (drive->proc) - ide_add_proc_entries(drive->proc, generic_drive_entries, drive); - sprintf(name, "ide%d/%s", (drive->name[2]-'a')/2, drive->name); - ent = proc_symlink(drive->name, proc_ide_root, name); - if (!ent) return; - } -} - -void ide_proc_unregister_device(ide_drive_t *drive) -{ - if (drive->proc) { - ide_remove_proc_entries(drive->proc, generic_drive_entries); - remove_proc_entry(drive->name, proc_ide_root); - remove_proc_entry(drive->name, drive->hwif->proc); - drive->proc = NULL; - } -} - -static ide_proc_entry_t hwif_entries[] = { - { "channel", S_IFREG|S_IRUGO, proc_ide_read_channel, NULL }, - { "mate", S_IFREG|S_IRUGO, proc_ide_read_mate, NULL }, - { "model", S_IFREG|S_IRUGO, proc_ide_read_imodel, NULL }, - { NULL, 0, NULL, NULL } -}; - -void ide_proc_register_port(ide_hwif_t *hwif) -{ - if (!hwif->proc) { - hwif->proc = proc_mkdir(hwif->name, proc_ide_root); - - if (!hwif->proc) - return; - - ide_add_proc_entries(hwif->proc, hwif_entries, hwif); - } -} - -void ide_proc_unregister_port(ide_hwif_t *hwif) -{ - if (hwif->proc) { - ide_remove_proc_entries(hwif->proc, hwif_entries); - remove_proc_entry(hwif->name, proc_ide_root); - hwif->proc = NULL; - } -} - -static int proc_print_driver(struct device_driver *drv, void *data) -{ - struct ide_driver *ide_drv = to_ide_driver(drv); - struct seq_file *s = data; - - seq_printf(s, "%s version %s\n", drv->name, ide_drv->version); - - return 0; -} - -static int ide_drivers_show(struct seq_file *s, void *p) -{ - int err; - - err = bus_for_each_drv(&ide_bus_type, NULL, s, proc_print_driver); - if (err < 0) - printk(KERN_WARNING "IDE: %s: bus_for_each_drv error: %d\n", - __func__, err); - return 0; -} - -static int ide_drivers_open(struct inode *inode, struct file *file) -{ - return single_open(file, &ide_drivers_show, NULL); -} - -static const struct file_operations ide_drivers_operations = { - .owner = THIS_MODULE, - .open = ide_drivers_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -void proc_ide_create(void) -{ - proc_ide_root = proc_mkdir("ide", NULL); - - if (!proc_ide_root) - return; - - proc_create("drivers", 0, proc_ide_root, &ide_drivers_operations); -} - -void proc_ide_destroy(void) -{ - remove_proc_entry("drivers", proc_ide_root); - remove_proc_entry("ide", NULL); -} diff --git a/windhoek/ide/ide-sysfs.c b/windhoek/ide/ide-sysfs.c deleted file mode 100644 index 883ffaca..00000000 --- a/windhoek/ide/ide-sysfs.c +++ /dev/null @@ -1,125 +0,0 @@ -#include <linux/kernel.h> -#include <linux/ide.h> - -char *ide_media_string(ide_drive_t *drive) -{ - switch (drive->media) { - case ide_disk: - return "disk"; - case ide_cdrom: - return "cdrom"; - case ide_tape: - return "tape"; - case ide_floppy: - return "floppy"; - case ide_optical: - return "optical"; - default: - return "UNKNOWN"; - } -} - -static ssize_t media_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", ide_media_string(drive)); -} - -static ssize_t drivename_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", drive->name); -} - -static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "ide:m-%s\n", ide_media_string(drive)); -} - -static ssize_t model_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]); -} - -static ssize_t firmware_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]); -} - -static ssize_t serial_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]); -} - -struct device_attribute ide_dev_attrs[] = { - __ATTR_RO(media), - __ATTR_RO(drivename), - __ATTR_RO(modalias), - __ATTR_RO(model), - __ATTR_RO(firmware), - __ATTR(serial, 0400, serial_show, NULL), - __ATTR(unload_heads, 0644, ide_park_show, ide_park_store), - __ATTR_NULL -}; - -static ssize_t store_delete_devices(struct device *portdev, - struct device_attribute *attr, - const char *buf, size_t n) -{ - ide_hwif_t *hwif = dev_get_drvdata(portdev); - - if (strncmp(buf, "1", n)) - return -EINVAL; - - ide_port_unregister_devices(hwif); - - return n; -}; - -static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices); - -static ssize_t store_scan(struct device *portdev, - struct device_attribute *attr, - const char *buf, size_t n) -{ - ide_hwif_t *hwif = dev_get_drvdata(portdev); - - if (strncmp(buf, "1", n)) - return -EINVAL; - - ide_port_unregister_devices(hwif); - ide_port_scan(hwif); - - return n; -}; - -static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan); - -static struct device_attribute *ide_port_attrs[] = { - &dev_attr_delete_devices, - &dev_attr_scan, - NULL -}; - -int ide_sysfs_register_port(ide_hwif_t *hwif) -{ - int i, uninitialized_var(rc); - - for (i = 0; ide_port_attrs[i]; i++) { - rc = device_create_file(hwif->portdev, ide_port_attrs[i]); - if (rc) - break; - } - - return rc; -} diff --git a/windhoek/ide/ide-taskfile.c b/windhoek/ide/ide-taskfile.c deleted file mode 100644 index a499923a..00000000 --- a/windhoek/ide/ide-taskfile.c +++ /dev/null @@ -1,695 +0,0 @@ -/* - * Copyright (C) 2000-2002 Michael Cornwell <cornwell@acm.org> - * Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org> - * Copyright (C) 2001-2002 Klaus Smolin - * IBM Storage Technology Division - * Copyright (C) 2003-2004, 2007 Bartlomiej Zolnierkiewicz - * - * The big the bad and the ugly. - */ - -#include <linux/types.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/hdreg.h> -#include <linux/ide.h> -#include <linux/scatterlist.h> - -#include <asm/uaccess.h> -#include <asm/io.h> - -#include "local.h" - -void ide_tf_dump(const char *s, struct ide_taskfile *tf) -{ -#ifdef DEBUG - printk("%s: tf: feat 0x%02x nsect 0x%02x lbal 0x%02x " - "lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n", - s, tf->feature, tf->nsect, tf->lbal, - tf->lbam, tf->lbah, tf->device, tf->command); - printk("%s: hob: nsect 0x%02x lbal 0x%02x " - "lbam 0x%02x lbah 0x%02x\n", - s, tf->hob_nsect, tf->hob_lbal, - tf->hob_lbam, tf->hob_lbah); -#endif -} - -int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf) -{ - ide_task_t args; - - memset(&args, 0, sizeof(ide_task_t)); - args.tf.nsect = 0x01; - if (drive->media == ide_disk) - args.tf.command = ATA_CMD_ID_ATA; - else - args.tf.command = ATA_CMD_ID_ATAPI; - args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - args.data_phase = TASKFILE_IN; - return ide_raw_taskfile(drive, &args, buf, 1); -} - -static ide_startstop_t task_no_data_intr(ide_drive_t *); -static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *); -static ide_startstop_t task_in_intr(ide_drive_t *); - -ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_taskfile *tf = &task->tf; - ide_handler_t *handler = NULL; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; - const struct ide_dma_ops *dma_ops = hwif->dma_ops; - - if (task->data_phase == TASKFILE_MULTI_IN || - task->data_phase == TASKFILE_MULTI_OUT) { - if (!drive->mult_count) { - printk(KERN_ERR "%s: multimode not set!\n", - drive->name); - return ide_stopped; - } - } - - if (task->tf_flags & IDE_TFLAG_FLAGGED) - task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS; - - memcpy(&hwif->task, task, sizeof(*task)); - - if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) { - ide_tf_dump(drive->name, tf); - tp_ops->set_irq(hwif, 1); - SELECT_MASK(drive, 0); - tp_ops->tf_load(drive, task); - } - - switch (task->data_phase) { - case TASKFILE_MULTI_OUT: - case TASKFILE_OUT: - tp_ops->exec_command(hwif, tf->command); - ndelay(400); /* FIXME */ - return pre_task_out_intr(drive, task->rq); - case TASKFILE_MULTI_IN: - case TASKFILE_IN: - handler = task_in_intr; - /* fall-through */ - case TASKFILE_NO_DATA: - if (handler == NULL) - handler = task_no_data_intr; - ide_execute_command(drive, tf->command, handler, - WAIT_WORSTCASE, NULL); - return ide_started; - default: - if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0 || - dma_ops->dma_setup(drive)) - return ide_stopped; - dma_ops->dma_exec_cmd(drive, tf->command); - dma_ops->dma_start(drive); - return ide_started; - } -} -EXPORT_SYMBOL_GPL(do_rw_taskfile); - -/* - * Handler for commands without a data phase - */ -static ide_startstop_t task_no_data_intr(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - ide_task_t *task = &hwif->task; - struct ide_taskfile *tf = &task->tf; - int custom = (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) ? 1 : 0; - int retries = (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) ? 5 : 1; - u8 stat; - - local_irq_enable_in_hardirq(); - - while (1) { - stat = hwif->tp_ops->read_status(hwif); - if ((stat & ATA_BUSY) == 0 || retries-- == 0) - break; - udelay(10); - }; - - if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) { - if (custom && tf->command == ATA_CMD_SET_MULTI) { - drive->mult_req = drive->mult_count = 0; - drive->special.b.recalibrate = 1; - (void)ide_dump_status(drive, __func__, stat); - return ide_stopped; - } else if (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) { - if ((stat & (ATA_ERR | ATA_DRQ)) == 0) { - ide_set_handler(drive, &task_no_data_intr, - WAIT_WORSTCASE, NULL); - return ide_started; - } - } - return ide_error(drive, "task_no_data_intr", stat); - /* calls ide_end_drive_cmd */ - } - - if (!custom) - ide_end_drive_cmd(drive, stat, ide_read_error(drive)); - else if (tf->command == ATA_CMD_IDLEIMMEDIATE) { - hwif->tp_ops->tf_read(drive, task); - if (tf->lbal != 0xc4) { - printk(KERN_ERR "%s: head unload failed!\n", - drive->name); - ide_tf_dump(drive->name, tf); - } else - drive->dev_flags |= IDE_DFLAG_PARKED; - ide_end_drive_cmd(drive, stat, ide_read_error(drive)); - } else if (tf->command == ATA_CMD_SET_MULTI) - drive->mult_count = drive->mult_req; - - return ide_stopped; -} - -static u8 wait_drive_not_busy(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - int retries; - u8 stat; - - /* - * Last sector was transfered, wait until device is ready. This can - * take up to 6 ms on some ATAPI devices, so we will wait max 10 ms. - */ - for (retries = 0; retries < 1000; retries++) { - stat = hwif->tp_ops->read_status(hwif); - - if (stat & ATA_BUSY) - udelay(10); - else - break; - } - - if (stat & ATA_BUSY) - printk(KERN_ERR "%s: drive still BUSY!\n", drive->name); - - return stat; -} - -static void ide_pio_sector(ide_drive_t *drive, struct request *rq, - unsigned int write) -{ - DEBUG_MSG("========= ide_pio start ========="); - ide_hwif_t *hwif = drive->hwif; - struct scatterlist *sg = hwif->sg_table; - struct scatterlist *cursg = hwif->cursg; - struct page *page; -#ifdef CONFIG_HIGHMEM - unsigned long flags; -#endif - unsigned int offset; - u8 *buf; - - cursg = hwif->cursg; - DEBUG_MSG("sg = %p, cursg %p", sg, cursg); - if (!cursg) { - cursg = sg; - hwif->cursg = sg; - } - - page = sg_page(cursg); - offset = cursg->offset + hwif->cursg_ofs * SECTOR_SIZE; - DEBUG_MSG("page %p, offset %lx", page, offset); - - /* get the current page and offset */ - page = nth_page(page, (offset >> PAGE_SHIFT)); - offset %= PAGE_SIZE; - DEBUG_MSG("== transform ==> page %p, offset %lx", page, offset); - DEBUG_MSG(" virt %p", page_address(page)); - - -#ifdef CONFIG_HIGHMEM - local_irq_save(flags); -#endif - buf = kmap_atomic(page, KM_BIO_SRC_IRQ) + offset; - DEBUG_MSG("kmap_atomic(%p) = %p", page, buf); - - hwif->nleft--; - hwif->cursg_ofs++; - - if ((hwif->cursg_ofs * SECTOR_SIZE) == cursg->length) { - hwif->cursg = sg_next(hwif->cursg); - hwif->cursg_ofs = 0; - } - - /* do the actual data transfer */ - if (write) - hwif->tp_ops->output_data(drive, rq, buf, SECTOR_SIZE); - else - hwif->tp_ops->input_data(drive, rq, buf, SECTOR_SIZE); - - kunmap_atomic(buf, KM_BIO_SRC_IRQ); -#ifdef CONFIG_HIGHMEM - local_irq_restore(flags); -#endif -} - -static void ide_pio_multi(ide_drive_t *drive, struct request *rq, - unsigned int write) -{ - unsigned int nsect; - - nsect = min_t(unsigned int, drive->hwif->nleft, drive->mult_count); - DEBUG_MSG("io on %d sectors (%d, %d)", nsect, drive->hwif->nleft, drive->mult_count); - while (nsect--) - ide_pio_sector(drive, rq, write); -} - -static void ide_pio_datablock(ide_drive_t *drive, struct request *rq, - unsigned int write) -{ - u8 saved_io_32bit = drive->io_32bit; - - if (rq->bio) /* fs request */ - rq->errors = 0; - - if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { - ide_task_t *task = rq->special; - - if (task->tf_flags & IDE_TFLAG_IO_16BIT) - drive->io_32bit = 0; - } - - touch_softlockup_watchdog(); - - DEBUG_MSG("data_phase : %s", drive->hwif->data_phase == TASKFILE_MULTI_IN ? "TASKFILE_MULTI_IN" : - drive->hwif->data_phase == TASKFILE_MULTI_OUT ? "TASKFILE_MULTI_OUT" : - "unknown"); - switch (drive->hwif->data_phase) { - case TASKFILE_MULTI_IN: - case TASKFILE_MULTI_OUT: - ide_pio_multi(drive, rq, write); - break; - default: - ide_pio_sector(drive, rq, write); - break; - } - - drive->io_32bit = saved_io_32bit; -} - -static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, - const char *s, u8 stat) -{ - if (rq->bio) { - ide_hwif_t *hwif = drive->hwif; - int sectors = hwif->nsect - hwif->nleft; - - switch (hwif->data_phase) { - case TASKFILE_IN: - if (hwif->nleft) - break; - /* fall through */ - case TASKFILE_OUT: - sectors--; - break; - case TASKFILE_MULTI_IN: - if (hwif->nleft) - break; - /* fall through */ - case TASKFILE_MULTI_OUT: - sectors -= drive->mult_count; - default: - break; - } - - if (sectors > 0) { - struct ide_driver *drv; - - drv = *(struct ide_driver **)rq->rq_disk->private_data; - drv->end_request(drive, 1, sectors); - } - } - return ide_error(drive, s, stat); -} - -void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) -{ - if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { - u8 err = ide_read_error(drive); - - ide_end_drive_cmd(drive, stat, err); - return; - } - - if (rq->rq_disk) { - struct ide_driver *drv; - - drv = *(struct ide_driver **)rq->rq_disk->private_data;; - drv->end_request(drive, 1, rq->nr_sectors); - } else - ide_end_request(drive, 1, rq->nr_sectors); -} - -/* - * We got an interrupt on a task_in case, but no errors and no DRQ. - * - * It might be a spurious irq (shared irq), but it might be a - * command that had no output. - */ -static ide_startstop_t task_in_unexpected(ide_drive_t *drive, struct request *rq, u8 stat) -{ - /* Command all done? */ - if (OK_STAT(stat, ATA_DRDY, ATA_BUSY)) { - task_end_request(drive, rq, stat); - return ide_stopped; - } - - /* Assume it was a spurious irq */ - ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL); - return ide_started; -} - -/* - * Handler for command with PIO data-in phase (Read/Read Multiple). - */ -static ide_startstop_t task_in_intr(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - struct request *rq = hwif->rq; - u8 stat = hwif->tp_ops->read_status(hwif); - - /* Error? */ - if (stat & ATA_ERR) - return task_error(drive, rq, __func__, stat); - - /* Didn't want any data? Odd. */ - if ((stat & ATA_DRQ) == 0) - return task_in_unexpected(drive, rq, stat); - - ide_pio_datablock(drive, rq, 0); - - /* Are we done? Check status and finish transfer. */ - if (!hwif->nleft) { - stat = wait_drive_not_busy(drive); - if (!OK_STAT(stat, 0, BAD_STAT)) - return task_error(drive, rq, __func__, stat); - task_end_request(drive, rq, stat); - return ide_stopped; - } - - /* Still data left to transfer. */ - ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL); - - return ide_started; -} - -/* - * Handler for command with PIO data-out phase (Write/Write Multiple). - */ -static ide_startstop_t task_out_intr (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - struct request *rq = hwif->rq; - u8 stat = hwif->tp_ops->read_status(hwif); - - if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat)) - return task_error(drive, rq, __func__, stat); - - /* Deal with unexpected ATA data phase. */ - if (((stat & ATA_DRQ) == 0) ^ !hwif->nleft) - return task_error(drive, rq, __func__, stat); - - if (!hwif->nleft) { - task_end_request(drive, rq, stat); - return ide_stopped; - } - - /* Still data left to transfer. */ - ide_pio_datablock(drive, rq, 1); - ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL); - - return ide_started; -} - -static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, struct request *rq) -{ - ide_startstop_t startstop; - - if (ide_wait_stat(&startstop, drive, ATA_DRQ, - drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n", - drive->name, drive->hwif->data_phase ? "MULT" : "", - (drive->dev_flags & IDE_DFLAG_LBA48) ? "_EXT" : ""); - return startstop; - } - - if ((drive->dev_flags & IDE_DFLAG_UNMASK) == 0) - local_irq_disable(); - - ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL); - ide_pio_datablock(drive, rq, 1); - - return ide_started; -} - -int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *task, u8 *buf, u16 nsect) -{ - struct request *rq; - int error; - - rq = blk_get_request(drive->queue, READ, __GFP_WAIT); - rq->cmd_type = REQ_TYPE_ATA_TASKFILE; - rq->buffer = buf; - - /* - * (ks) We transfer currently only whole sectors. - * This is suffient for now. But, it would be great, - * if we would find a solution to transfer any size. - * To support special commands like READ LONG. - */ - rq->hard_nr_sectors = rq->nr_sectors = nsect; - rq->hard_cur_sectors = rq->current_nr_sectors = nsect; - - if (task->tf_flags & IDE_TFLAG_WRITE) - rq->cmd_flags |= REQ_RW; - - rq->special = task; - task->rq = rq; - - error = blk_execute_rq(drive->queue, NULL, rq, 0); - blk_put_request(rq); - - return error; -} - -EXPORT_SYMBOL(ide_raw_taskfile); - -int ide_no_data_taskfile(ide_drive_t *drive, ide_task_t *task) -{ - task->data_phase = TASKFILE_NO_DATA; - - return ide_raw_taskfile(drive, task, NULL, 0); -} -EXPORT_SYMBOL_GPL(ide_no_data_taskfile); - -#ifdef CONFIG_IDE_TASK_IOCTL -int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) -{ - ide_task_request_t *req_task; - ide_task_t args; - u8 *outbuf = NULL; - u8 *inbuf = NULL; - u8 *data_buf = NULL; - int err = 0; - int tasksize = sizeof(struct ide_task_request_s); - unsigned int taskin = 0; - unsigned int taskout = 0; - u16 nsect = 0; - char __user *buf = (char __user *)arg; - -// printk("IDE Taskfile ...\n"); - - req_task = kzalloc(tasksize, GFP_KERNEL); - if (req_task == NULL) return -ENOMEM; - if (copy_from_user(req_task, buf, tasksize)) { - kfree(req_task); - return -EFAULT; - } - - taskout = req_task->out_size; - taskin = req_task->in_size; - - if (taskin > 65536 || taskout > 65536) { - err = -EINVAL; - goto abort; - } - - if (taskout) { - int outtotal = tasksize; - outbuf = kzalloc(taskout, GFP_KERNEL); - if (outbuf == NULL) { - err = -ENOMEM; - goto abort; - } - if (copy_from_user(outbuf, buf + outtotal, taskout)) { - err = -EFAULT; - goto abort; - } - } - - if (taskin) { - int intotal = tasksize + taskout; - inbuf = kzalloc(taskin, GFP_KERNEL); - if (inbuf == NULL) { - err = -ENOMEM; - goto abort; - } - if (copy_from_user(inbuf, buf + intotal, taskin)) { - err = -EFAULT; - goto abort; - } - } - - memset(&args, 0, sizeof(ide_task_t)); - - memcpy(&args.tf_array[0], req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE - 2); - memcpy(&args.tf_array[6], req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE); - - args.data_phase = req_task->data_phase; - - args.tf_flags = IDE_TFLAG_IO_16BIT | IDE_TFLAG_DEVICE | - IDE_TFLAG_IN_TF; - if (drive->dev_flags & IDE_DFLAG_LBA48) - args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_IN_HOB); - - if (req_task->out_flags.all) { - args.tf_flags |= IDE_TFLAG_FLAGGED; - - if (req_task->out_flags.b.data) - args.tf_flags |= IDE_TFLAG_OUT_DATA; - - if (req_task->out_flags.b.nsector_hob) - args.tf_flags |= IDE_TFLAG_OUT_HOB_NSECT; - if (req_task->out_flags.b.sector_hob) - args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAL; - if (req_task->out_flags.b.lcyl_hob) - args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAM; - if (req_task->out_flags.b.hcyl_hob) - args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAH; - - if (req_task->out_flags.b.error_feature) - args.tf_flags |= IDE_TFLAG_OUT_FEATURE; - if (req_task->out_flags.b.nsector) - args.tf_flags |= IDE_TFLAG_OUT_NSECT; - if (req_task->out_flags.b.sector) - args.tf_flags |= IDE_TFLAG_OUT_LBAL; - if (req_task->out_flags.b.lcyl) - args.tf_flags |= IDE_TFLAG_OUT_LBAM; - if (req_task->out_flags.b.hcyl) - args.tf_flags |= IDE_TFLAG_OUT_LBAH; - } else { - args.tf_flags |= IDE_TFLAG_OUT_TF; - if (args.tf_flags & IDE_TFLAG_LBA48) - args.tf_flags |= IDE_TFLAG_OUT_HOB; - } - - if (req_task->in_flags.b.data) - args.tf_flags |= IDE_TFLAG_IN_DATA; - - switch(req_task->data_phase) { - case TASKFILE_MULTI_OUT: - if (!drive->mult_count) { - /* (hs): give up if multcount is not set */ - printk(KERN_ERR "%s: %s Multimode Write " \ - "multcount is not set\n", - drive->name, __func__); - err = -EPERM; - goto abort; - } - /* fall through */ - case TASKFILE_OUT: - /* fall through */ - case TASKFILE_OUT_DMAQ: - case TASKFILE_OUT_DMA: - nsect = taskout / SECTOR_SIZE; - data_buf = outbuf; - break; - case TASKFILE_MULTI_IN: - if (!drive->mult_count) { - /* (hs): give up if multcount is not set */ - printk(KERN_ERR "%s: %s Multimode Read failure " \ - "multcount is not set\n", - drive->name, __func__); - err = -EPERM; - goto abort; - } - /* fall through */ - case TASKFILE_IN: - /* fall through */ - case TASKFILE_IN_DMAQ: - case TASKFILE_IN_DMA: - nsect = taskin / SECTOR_SIZE; - data_buf = inbuf; - break; - case TASKFILE_NO_DATA: - break; - default: - err = -EFAULT; - goto abort; - } - - if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA) - nsect = 0; - else if (!nsect) { - nsect = (args.tf.hob_nsect << 8) | args.tf.nsect; - - if (!nsect) { - printk(KERN_ERR "%s: in/out command without data\n", - drive->name); - err = -EFAULT; - goto abort; - } - } - - if (req_task->req_cmd == IDE_DRIVE_TASK_RAW_WRITE) - args.tf_flags |= IDE_TFLAG_WRITE; - - err = ide_raw_taskfile(drive, &args, data_buf, nsect); - - memcpy(req_task->hob_ports, &args.tf_array[0], HDIO_DRIVE_HOB_HDR_SIZE - 2); - memcpy(req_task->io_ports, &args.tf_array[6], HDIO_DRIVE_TASK_HDR_SIZE); - - if ((args.tf_flags & IDE_TFLAG_FLAGGED_SET_IN_FLAGS) && - req_task->in_flags.all == 0) { - req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS; - if (drive->dev_flags & IDE_DFLAG_LBA48) - req_task->in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8); - } - - if (copy_to_user(buf, req_task, tasksize)) { - err = -EFAULT; - goto abort; - } - if (taskout) { - int outtotal = tasksize; - if (copy_to_user(buf + outtotal, outbuf, taskout)) { - err = -EFAULT; - goto abort; - } - } - if (taskin) { - int intotal = tasksize + taskout; - if (copy_to_user(buf + intotal, inbuf, taskin)) { - err = -EFAULT; - goto abort; - } - } -abort: - kfree(req_task); - kfree(outbuf); - kfree(inbuf); - -// printk("IDE Taskfile ioctl ended. rc = %i\n", err); - - return err; -} -#endif diff --git a/windhoek/ide/ide.c b/windhoek/ide/ide.c deleted file mode 100644 index 15eb62ed..00000000 --- a/windhoek/ide/ide.c +++ /dev/null @@ -1,554 +0,0 @@ -/* - * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) - * Copyright (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz - */ - -/* - * Mostly written by Mark Lord <mlord@pobox.com> - * and Gadi Oxman <gadio@netvision.net.il> - * and Andre Hedrick <andre@linux-ide.org> - * - * See linux/MAINTAINERS for address of current maintainer. - * - * This is the multiple IDE interface driver, as evolved from hd.c. - * It supports up to MAX_HWIFS IDE interfaces, on one or more IRQs - * (usually 14 & 15). - * There can be up to two drives per interface, as per the ATA-2 spec. - * - * ... - * - * From hd.c: - * | - * | It traverses the request-list, using interrupts to jump between functions. - * | As nearly all functions can be called within interrupts, we may not sleep. - * | Special care is recommended. Have Fun! - * | - * | modified by Drew Eckhardt to check nr of hd's from the CMOS. - * | - * | Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug - * | in the early extended-partition checks and added DM partitions. - * | - * | Early work on error handling by Mika Liljeberg (liljeber@cs.Helsinki.FI). - * | - * | IRQ-unmask, drive-id, multiple-mode, support for ">16 heads", - * | and general streamlining by Mark Lord (mlord@pobox.com). - * - * October, 1994 -- Complete line-by-line overhaul for linux 1.1.x, by: - * - * Mark Lord (mlord@pobox.com) (IDE Perf.Pkg) - * Delman Lee (delman@ieee.org) ("Mr. atdisk2") - * Scott Snyder (snyder@fnald0.fnal.gov) (ATAPI IDE cd-rom) - * - * This was a rewrite of just about everything from hd.c, though some original - * code is still sprinkled about. Think of it as a major evolution, with - * inspiration from lots of linux users, esp. hamish@zot.apana.org.au - */ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/interrupt.h> -#include <linux/major.h> -#include <linux/errno.h> -#include <linux/genhd.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/ide.h> -#include <linux/hdreg.h> -#include <linux/completion.h> -#include <linux/device.h> - -struct class *ide_port_class; - -/* - * Locks for IDE setting functionality - */ - -DEFINE_MUTEX(ide_setting_mtx); - -ide_devset_get(io_32bit, io_32bit); - -static int set_io_32bit(ide_drive_t *drive, int arg) -{ - if (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT) - return -EPERM; - - if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) - return -EINVAL; - - drive->io_32bit = arg; - - return 0; -} - -ide_devset_get_flag(ksettings, IDE_DFLAG_KEEP_SETTINGS); - -static int set_ksettings(ide_drive_t *drive, int arg) -{ - if (arg < 0 || arg > 1) - return -EINVAL; - - if (arg) - drive->dev_flags |= IDE_DFLAG_KEEP_SETTINGS; - else - drive->dev_flags &= ~IDE_DFLAG_KEEP_SETTINGS; - - return 0; -} - -ide_devset_get_flag(using_dma, IDE_DFLAG_USING_DMA); - -static int set_using_dma(ide_drive_t *drive, int arg) -{ -#ifdef CONFIG_BLK_DEV_IDEDMA - int err = -EPERM; - - if (arg < 0 || arg > 1) - return -EINVAL; - - if (ata_id_has_dma(drive->id) == 0) - goto out; - - if (drive->hwif->dma_ops == NULL) - goto out; - - err = 0; - - if (arg) { - if (ide_set_dma(drive)) - err = -EIO; - } else - ide_dma_off(drive); - -out: - return err; -#else - if (arg < 0 || arg > 1) - return -EINVAL; - - return -EPERM; -#endif -} - -/* - * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away - */ -static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio) -{ - switch (req_pio) { - case 202: - case 201: - case 200: - case 102: - case 101: - case 100: - return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0; - case 9: - case 8: - return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0; - case 7: - case 6: - return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0; - default: - return 0; - } -} - -static int set_pio_mode(ide_drive_t *drive, int arg) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - - if (arg < 0 || arg > 255) - return -EINVAL; - - if (port_ops == NULL || port_ops->set_pio_mode == NULL || - (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) - return -ENOSYS; - - if (set_pio_mode_abuse(drive->hwif, arg)) { - if (arg == 8 || arg == 9) { - unsigned long flags; - - /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */ - spin_lock_irqsave(&hwif->lock, flags); - port_ops->set_pio_mode(drive, arg); - spin_unlock_irqrestore(&hwif->lock, flags); - } else - port_ops->set_pio_mode(drive, arg); - } else { - int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); - - ide_set_pio(drive, arg); - - if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) { - if (keep_dma) - ide_dma_on(drive); - } - } - - return 0; -} - -ide_devset_get_flag(unmaskirq, IDE_DFLAG_UNMASK); - -static int set_unmaskirq(ide_drive_t *drive, int arg) -{ - if (drive->dev_flags & IDE_DFLAG_NO_UNMASK) - return -EPERM; - - if (arg < 0 || arg > 1) - return -EINVAL; - - if (arg) - drive->dev_flags |= IDE_DFLAG_UNMASK; - else - drive->dev_flags &= ~IDE_DFLAG_UNMASK; - - return 0; -} - -ide_ext_devset_rw_sync(io_32bit, io_32bit); -ide_ext_devset_rw_sync(keepsettings, ksettings); -ide_ext_devset_rw_sync(unmaskirq, unmaskirq); -ide_ext_devset_rw_sync(using_dma, using_dma); -__IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode); - -/** - * ide_device_get - get an additional reference to a ide_drive_t - * @drive: device to get a reference to - * - * Gets a reference to the ide_drive_t and increments the use count of the - * underlying LLDD module. - */ -int ide_device_get(ide_drive_t *drive) -{ - struct device *host_dev; - struct module *module; - - if (!get_device(&drive->gendev)) - return -ENXIO; - - host_dev = drive->hwif->host->dev[0]; - module = host_dev ? host_dev->driver->owner : NULL; - - if (module && !try_module_get(module)) { - put_device(&drive->gendev); - return -ENXIO; - } - - return 0; -} -EXPORT_SYMBOL_GPL(ide_device_get); - -/** - * ide_device_put - release a reference to a ide_drive_t - * @drive: device to release a reference on - * - * Release a reference to the ide_drive_t and decrements the use count of - * the underlying LLDD module. - */ -void ide_device_put(ide_drive_t *drive) -{ -#ifdef CONFIG_MODULE_UNLOAD - struct device *host_dev = drive->hwif->host->dev[0]; - struct module *module = host_dev ? host_dev->driver->owner : NULL; - - if (module) - module_put(module); -#endif - put_device(&drive->gendev); -} -EXPORT_SYMBOL_GPL(ide_device_put); - -static int ide_bus_match(struct device *dev, struct device_driver *drv) -{ - return 1; -} - -static int ide_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - ide_drive_t *drive = to_ide_device(dev); - - add_uevent_var(env, "MEDIA=%s", ide_media_string(drive)); - add_uevent_var(env, "DRIVENAME=%s", drive->name); - add_uevent_var(env, "MODALIAS=ide:m-%s", ide_media_string(drive)); - return 0; -} - -static int generic_ide_probe(struct device *dev) -{ - ide_drive_t *drive = to_ide_device(dev); - struct ide_driver *drv = to_ide_driver(dev->driver); - - return drv->probe ? drv->probe(drive) : -ENODEV; -} - -static int generic_ide_remove(struct device *dev) -{ - ide_drive_t *drive = to_ide_device(dev); - struct ide_driver *drv = to_ide_driver(dev->driver); - - if (drv->remove) - drv->remove(drive); - - return 0; -} - -static void generic_ide_shutdown(struct device *dev) -{ - ide_drive_t *drive = to_ide_device(dev); - struct ide_driver *drv = to_ide_driver(dev->driver); - - if (dev->driver && drv->shutdown) - drv->shutdown(drive); -} - -struct bus_type ide_bus_type = { - .name = "ide", - .match = ide_bus_match, - .uevent = ide_uevent, - .probe = generic_ide_probe, - .remove = generic_ide_remove, - .shutdown = generic_ide_shutdown, - .dev_attrs = ide_dev_attrs, -#ifndef DDE_LINUX - .suspend = generic_ide_suspend, - .resume = generic_ide_resume, -#endif -}; - -EXPORT_SYMBOL_GPL(ide_bus_type); - -int ide_vlb_clk; -EXPORT_SYMBOL_GPL(ide_vlb_clk); - -module_param_named(vlb_clock, ide_vlb_clk, int, 0); -MODULE_PARM_DESC(vlb_clock, "VLB clock frequency (in MHz)"); - -int ide_pci_clk; -EXPORT_SYMBOL_GPL(ide_pci_clk); - -module_param_named(pci_clock, ide_pci_clk, int, 0); -MODULE_PARM_DESC(pci_clock, "PCI bus clock frequency (in MHz)"); - -static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp) -{ - int a, b, i, j = 1; - unsigned int *dev_param_mask = (unsigned int *)kp->arg; - - /* controller . device (0 or 1) [ : 1 (set) | 0 (clear) ] */ - if (sscanf(s, "%d.%d:%d", &a, &b, &j) != 3 && - sscanf(s, "%d.%d", &a, &b) != 2) - return -EINVAL; - - i = a * MAX_DRIVES + b; - - if (i >= MAX_HWIFS * MAX_DRIVES || j < 0 || j > 1) - return -EINVAL; - - if (j) - *dev_param_mask |= (1 << i); - else - *dev_param_mask &= ~(1 << i); - - return 0; -} - -static unsigned int ide_nodma; - -module_param_call(nodma, ide_set_dev_param_mask, NULL, &ide_nodma, 0); -MODULE_PARM_DESC(nodma, "disallow DMA for a device"); - -static unsigned int ide_noflush; - -module_param_call(noflush, ide_set_dev_param_mask, NULL, &ide_noflush, 0); -MODULE_PARM_DESC(noflush, "disable flush requests for a device"); - -static unsigned int ide_noprobe; - -module_param_call(noprobe, ide_set_dev_param_mask, NULL, &ide_noprobe, 0); -MODULE_PARM_DESC(noprobe, "skip probing for a device"); - -static unsigned int ide_nowerr; - -module_param_call(nowerr, ide_set_dev_param_mask, NULL, &ide_nowerr, 0); -MODULE_PARM_DESC(nowerr, "ignore the ATA_DF bit for a device"); - -static unsigned int ide_cdroms; - -module_param_call(cdrom, ide_set_dev_param_mask, NULL, &ide_cdroms, 0); -MODULE_PARM_DESC(cdrom, "force device as a CD-ROM"); - -struct chs_geom { - unsigned int cyl; - u8 head; - u8 sect; -}; - -static unsigned int ide_disks; -static struct chs_geom ide_disks_chs[MAX_HWIFS * MAX_DRIVES]; - -static int ide_set_disk_chs(const char *str, struct kernel_param *kp) -{ - int a, b, c = 0, h = 0, s = 0, i, j = 1; - - /* controller . device (0 or 1) : Cylinders , Heads , Sectors */ - /* controller . device (0 or 1) : 1 (use CHS) | 0 (ignore CHS) */ - if (sscanf(str, "%d.%d:%d,%d,%d", &a, &b, &c, &h, &s) != 5 && - sscanf(str, "%d.%d:%d", &a, &b, &j) != 3) - return -EINVAL; - - i = a * MAX_DRIVES + b; - - if (i >= MAX_HWIFS * MAX_DRIVES || j < 0 || j > 1) - return -EINVAL; - - if (c > INT_MAX || h > 255 || s > 255) - return -EINVAL; - - if (j) - ide_disks |= (1 << i); - else - ide_disks &= ~(1 << i); - - ide_disks_chs[i].cyl = c; - ide_disks_chs[i].head = h; - ide_disks_chs[i].sect = s; - - return 0; -} - -module_param_call(chs, ide_set_disk_chs, NULL, NULL, 0); -MODULE_PARM_DESC(chs, "force device as a disk (using CHS)"); - -static void ide_dev_apply_params(ide_drive_t *drive, u8 unit) -{ - int i = drive->hwif->index * MAX_DRIVES + unit; - - if (ide_nodma & (1 << i)) { - printk(KERN_INFO "ide: disallowing DMA for %s\n", drive->name); - drive->dev_flags |= IDE_DFLAG_NODMA; - } - if (ide_noflush & (1 << i)) { - printk(KERN_INFO "ide: disabling flush requests for %s\n", - drive->name); - drive->dev_flags |= IDE_DFLAG_NOFLUSH; - } - if (ide_noprobe & (1 << i)) { - printk(KERN_INFO "ide: skipping probe for %s\n", drive->name); - drive->dev_flags |= IDE_DFLAG_NOPROBE; - } - if (ide_nowerr & (1 << i)) { - printk(KERN_INFO "ide: ignoring the ATA_DF bit for %s\n", - drive->name); - drive->bad_wstat = BAD_R_STAT; - } - if (ide_cdroms & (1 << i)) { - printk(KERN_INFO "ide: forcing %s as a CD-ROM\n", drive->name); - drive->dev_flags |= IDE_DFLAG_PRESENT; - drive->media = ide_cdrom; - /* an ATAPI device ignores DRDY */ - drive->ready_stat = 0; - } - if (ide_disks & (1 << i)) { - drive->cyl = drive->bios_cyl = ide_disks_chs[i].cyl; - drive->head = drive->bios_head = ide_disks_chs[i].head; - drive->sect = drive->bios_sect = ide_disks_chs[i].sect; - - printk(KERN_INFO "ide: forcing %s as a disk (%d/%d/%d)\n", - drive->name, - drive->cyl, drive->head, drive->sect); - - drive->dev_flags |= IDE_DFLAG_FORCED_GEOM | IDE_DFLAG_PRESENT; - drive->media = ide_disk; - drive->ready_stat = ATA_DRDY; - } -} - -static unsigned int ide_ignore_cable; - -static int ide_set_ignore_cable(const char *s, struct kernel_param *kp) -{ - int i, j = 1; - - /* controller (ignore) */ - /* controller : 1 (ignore) | 0 (use) */ - if (sscanf(s, "%d:%d", &i, &j) != 2 && sscanf(s, "%d", &i) != 1) - return -EINVAL; - - if (i >= MAX_HWIFS || j < 0 || j > 1) - return -EINVAL; - - if (j) - ide_ignore_cable |= (1 << i); - else - ide_ignore_cable &= ~(1 << i); - - return 0; -} - -module_param_call(ignore_cable, ide_set_ignore_cable, NULL, NULL, 0); -MODULE_PARM_DESC(ignore_cable, "ignore cable detection"); - -void ide_port_apply_params(ide_hwif_t *hwif) -{ - ide_drive_t *drive; - int i; - - if (ide_ignore_cable & (1 << hwif->index)) { - printk(KERN_INFO "ide: ignoring cable detection for %s\n", - hwif->name); - hwif->cbl = ATA_CBL_PATA40_SHORT; - } - - ide_port_for_each_dev(i, drive, hwif) - ide_dev_apply_params(drive, i); -} - -/* - * This is gets invoked once during initialization, to set *everything* up - */ -static int __init ide_init(void) -{ - int ret; - - printk(KERN_INFO "Uniform Multi-Platform E-IDE driver\n"); - - ret = bus_register(&ide_bus_type); - if (ret < 0) { - printk(KERN_WARNING "IDE: bus_register error: %d\n", ret); - return ret; - } - - ide_port_class = class_create(THIS_MODULE, "ide_port"); - if (IS_ERR(ide_port_class)) { - ret = PTR_ERR(ide_port_class); - goto out_port_class; - } - - proc_ide_create(); - - return 0; - -out_port_class: - bus_unregister(&ide_bus_type); - - return ret; -} - -static void __exit ide_exit(void) -{ - proc_ide_destroy(); - - class_destroy(ide_port_class); - - bus_unregister(&ide_bus_type); -} - -module_init(ide_init); -module_exit(ide_exit); - -MODULE_LICENSE("GPL"); diff --git a/windhoek/ide/local.h b/windhoek/ide/local.h deleted file mode 100644 index c2d0952a..00000000 --- a/windhoek/ide/local.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef LOCAL_H -#define LOCAL_H - -#define DEBUG_MSG(msg, ...) {} - -// printk("%s: \033[31m"msg"\033[0m\n", __FUNCTION__, ##__VA_ARGS__) - -#define CONFIG_IDE_GD 1 -#define CONFIG_IDE_GD_ATA 1 - -#endif diff --git a/windhoek/ide/piix.c b/windhoek/ide/piix.c deleted file mode 100644 index f1e2e4ef..00000000 --- a/windhoek/ide/piix.c +++ /dev/null @@ -1,482 +0,0 @@ -/* - * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer - * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> - * Copyright (C) 2003 Red Hat - * Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com> - * - * May be copied or modified under the terms of the GNU General Public License - * - * Documentation: - * - * Publically available from Intel web site. Errata documentation - * is also publically available. As an aide to anyone hacking on this - * driver the list of errata that are relevant is below.going back to - * PIIX4. Older device documentation is now a bit tricky to find. - * - * Errata of note: - * - * Unfixable - * PIIX4 errata #9 - Only on ultra obscure hw - * ICH3 errata #13 - Not observed to affect real hw - * by Intel - * - * Things we must deal with - * PIIX4 errata #10 - BM IDE hang with non UDMA - * (must stop/start dma to recover) - * 440MX errata #15 - As PIIX4 errata #10 - * PIIX4 errata #15 - Must not read control registers - * during a PIO transfer - * 440MX errata #13 - As PIIX4 errata #15 - * ICH2 errata #21 - DMA mode 0 doesn't work right - * ICH0/1 errata #55 - As ICH2 errata #21 - * ICH2 spec c #9 - Extra operations needed to handle - * drive hotswap [NOT YET SUPPORTED] - * ICH2 spec c #20 - IDE PRD must not cross a 64K boundary - * and must be dword aligned - * ICH2 spec c #24 - UDMA mode 4,5 t85/86 should be 6ns not 3.3 - * - * Should have been BIOS fixed: - * 450NX: errata #19 - DMA hangs on old 450NX - * 450NX: errata #20 - DMA hangs on old 450NX - * 450NX: errata #25 - Corruption with DMA on old 450NX - * ICH3 errata #15 - IDE deadlock under high load - * (BIOS must set dev 31 fn 0 bit 23) - * ICH3 errata #18 - Don't use native mode - */ - -#include <linux/types.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/ide.h> -#include <linux/init.h> - -#include <asm/io.h> - -#define DRV_NAME "piix" - -static int no_piix_dma; - -/** - * piix_set_pio_mode - set host controller for PIO mode - * @drive: drive - * @pio: PIO mode number - * - * Set the interface PIO mode based upon the settings done by AMI BIOS. - */ - -static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = to_pci_dev(hwif->dev); - int is_slave = drive->dn & 1; - int master_port = hwif->channel ? 0x42 : 0x40; - int slave_port = 0x44; - unsigned long flags; - u16 master_data; - u8 slave_data; - static DEFINE_SPINLOCK(tune_lock); - int control = 0; - - /* ISP RTC */ - static const u8 timings[][2]= { - { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; - - /* - * Master vs slave is synchronized above us but the slave register is - * shared by the two hwifs so the corner case of two slave timeouts in - * parallel must be locked. - */ - spin_lock_irqsave(&tune_lock, flags); - pci_read_config_word(dev, master_port, &master_data); - - if (pio > 1) - control |= 1; /* Programmable timing on */ - if (drive->media == ide_disk) - control |= 4; /* Prefetch, post write */ - if (pio > 2) - control |= 2; /* IORDY */ - if (is_slave) { - master_data |= 0x4000; - master_data &= ~0x0070; - if (pio > 1) { - /* Set PPE, IE and TIME */ - master_data |= control << 4; - } - pci_read_config_byte(dev, slave_port, &slave_data); - slave_data &= hwif->channel ? 0x0f : 0xf0; - slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << - (hwif->channel ? 4 : 0); - } else { - master_data &= ~0x3307; - if (pio > 1) { - /* enable PPE, IE and TIME */ - master_data |= control; - } - master_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8); - } - pci_write_config_word(dev, master_port, master_data); - if (is_slave) - pci_write_config_byte(dev, slave_port, slave_data); - spin_unlock_irqrestore(&tune_lock, flags); -} - -/** - * piix_set_dma_mode - set host controller for DMA mode - * @drive: drive - * @speed: DMA mode - * - * Set a PIIX host controller to the desired DMA mode. This involves - * programming the right timing data into the PCI configuration space. - */ - -static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 maslave = hwif->channel ? 0x42 : 0x40; - int a_speed = 3 << (drive->dn * 4); - int u_flag = 1 << drive->dn; - int v_flag = 0x01 << drive->dn; - int w_flag = 0x10 << drive->dn; - int u_speed = 0; - int sitre; - u16 reg4042, reg4a; - u8 reg48, reg54, reg55; - - pci_read_config_word(dev, maslave, ®4042); - sitre = (reg4042 & 0x4000) ? 1 : 0; - pci_read_config_byte(dev, 0x48, ®48); - pci_read_config_word(dev, 0x4a, ®4a); - pci_read_config_byte(dev, 0x54, ®54); - pci_read_config_byte(dev, 0x55, ®55); - - if (speed >= XFER_UDMA_0) { - u8 udma = speed - XFER_UDMA_0; - - u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4); - - if (!(reg48 & u_flag)) - pci_write_config_byte(dev, 0x48, reg48 | u_flag); - if (speed == XFER_UDMA_5) { - pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag); - } else { - pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); - } - if ((reg4a & a_speed) != u_speed) - pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed); - if (speed > XFER_UDMA_2) { - if (!(reg54 & v_flag)) - pci_write_config_byte(dev, 0x54, reg54 | v_flag); - } else - pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); - } else { - const u8 mwdma_to_pio[] = { 0, 3, 4 }; - u8 pio; - - if (reg48 & u_flag) - pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); - if (reg4a & a_speed) - pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - if (reg54 & v_flag) - pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); - if (reg55 & w_flag) - pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); - - if (speed >= XFER_MW_DMA_0) - pio = mwdma_to_pio[speed - XFER_MW_DMA_0]; - else - pio = 2; /* only SWDMA2 is allowed */ - - piix_set_pio_mode(drive, pio); - } -} - -/** - * init_chipset_ich - set up the ICH chipset - * @dev: PCI device to set up - * - * Initialize the PCI device as required. For the ICH this turns - * out to be nice and simple. - */ - -static unsigned int init_chipset_ich(struct pci_dev *dev) -{ - u32 extra = 0; - - pci_read_config_dword(dev, 0x54, &extra); - pci_write_config_dword(dev, 0x54, extra | 0x400); - - return 0; -} - -/** - * ich_clear_irq - clear BMDMA status - * @drive: IDE drive - * - * ICHx contollers set DMA INTR no matter DMA or PIO. - * BMDMA status might need to be cleared even for - * PIO interrupts to prevent spurious/lost IRQ. - */ -static void ich_clear_irq(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - u8 dma_stat; - - /* - * ide_dma_end() needs BMDMA status for error checking. - * So, skip clearing BMDMA status here and leave it - * to ide_dma_end() if this is DMA interrupt. - */ - if (drive->waiting_for_dma || hwif->dma_base == 0) - return; - - /* clear the INTR & ERROR bits */ - dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); - /* Should we force the bit as well ? */ - outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS); -} - -struct ich_laptop { - u16 device; - u16 subvendor; - u16 subdevice; -}; - -/* - * List of laptops that use short cables rather than 80 wire - */ - -static const struct ich_laptop ich_laptop[] = { - /* devid, subvendor, subdev */ - { 0x27DF, 0x1025, 0x0102 }, /* ICH7 on Acer 5602aWLMi */ - { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */ - { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */ - { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ - { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */ - { 0x27DF, 0x1071, 0xD221 }, /* ICH7 on Hercules EC-900 */ - { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */ - { 0x24CA, 0x1025, 0x003d }, /* ICH4 on ACER TM290 */ - { 0x266F, 0x1025, 0x0066 }, /* ICH6 on ACER Aspire 1694WLMi */ - { 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */ - /* end marker */ - { 0, } -}; - -static u8 piix_cable_detect(ide_hwif_t *hwif) -{ - struct pci_dev *pdev = to_pci_dev(hwif->dev); - const struct ich_laptop *lap = &ich_laptop[0]; - u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30; - - /* check for specials */ - while (lap->device) { - if (lap->device == pdev->device && - lap->subvendor == pdev->subsystem_vendor && - lap->subdevice == pdev->subsystem_device) { - return ATA_CBL_PATA40_SHORT; - } - lap++; - } - - pci_read_config_byte(pdev, 0x54, ®54h); - - return (reg54h & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40; -} - -/** - * init_hwif_piix - fill in the hwif for the PIIX - * @hwif: IDE interface - * - * Set up the ide_hwif_t for the PIIX interface according to the - * capabilities of the hardware. - */ - -static void __devinit init_hwif_piix(ide_hwif_t *hwif) -{ - if (!hwif->dma_base) - return; - - if (no_piix_dma) - hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0; -} - -static const struct ide_port_ops piix_port_ops = { - .set_pio_mode = piix_set_pio_mode, - .set_dma_mode = piix_set_dma_mode, - .cable_detect = piix_cable_detect, -}; - -static const struct ide_port_ops ich_port_ops = { - .set_pio_mode = piix_set_pio_mode, - .set_dma_mode = piix_set_dma_mode, - .clear_irq = ich_clear_irq, - .cable_detect = piix_cable_detect, -}; - -#ifndef CONFIG_IA64 - #define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS -#else - #define IDE_HFLAGS_PIIX 0 -#endif - -#define DECLARE_PIIX_DEV(udma) \ - { \ - .name = DRV_NAME, \ - .init_hwif = init_hwif_piix, \ - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \ - .port_ops = &piix_port_ops, \ - .host_flags = IDE_HFLAGS_PIIX, \ - .pio_mask = ATA_PIO4, \ - .swdma_mask = ATA_SWDMA2_ONLY, \ - .mwdma_mask = ATA_MWDMA12_ONLY, \ - .udma_mask = udma, \ - } - -#define DECLARE_ICH_DEV(udma) \ - { \ - .name = DRV_NAME, \ - .init_chipset = init_chipset_ich, \ - .init_hwif = init_hwif_piix, \ - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \ - .port_ops = &ich_port_ops, \ - .host_flags = IDE_HFLAGS_PIIX, \ - .pio_mask = ATA_PIO4, \ - .swdma_mask = ATA_SWDMA2_ONLY, \ - .mwdma_mask = ATA_MWDMA12_ONLY, \ - .udma_mask = udma, \ - } - -static const struct ide_port_info piix_pci_info[] __devinitdata = { - /* 0: MPIIX */ - { /* - * MPIIX actually has only a single IDE channel mapped to - * the primary or secondary ports depending on the value - * of the bit 14 of the IDETIM register at offset 0x6c - */ - .name = DRV_NAME, - .enablebits = {{0x6d,0xc0,0x80}, {0x6d,0xc0,0xc0}}, - .host_flags = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_NO_DMA | - IDE_HFLAGS_PIIX, - .pio_mask = ATA_PIO4, - /* This is a painful system best to let it self tune for now */ - }, - /* 1: PIIXa/PIIXb/PIIX3 */ - DECLARE_PIIX_DEV(0x00), /* no udma */ - /* 2: PIIX4 */ - DECLARE_PIIX_DEV(ATA_UDMA2), - /* 3: ICH0 */ - DECLARE_ICH_DEV(ATA_UDMA2), - /* 4: ICH */ - DECLARE_ICH_DEV(ATA_UDMA4), - /* 5: PIIX4 */ - DECLARE_PIIX_DEV(ATA_UDMA4), - /* 6: ICH[2-7]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */ - DECLARE_ICH_DEV(ATA_UDMA5), -}; - -/** - * piix_init_one - called when a PIIX is found - * @dev: the piix device - * @id: the matching pci id - * - * Called when the PCI registration layer (or the IDE initialization) - * finds a device matching our IDE device tables. - */ - -static int __devinit piix_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - return ide_pci_init_one(dev, &piix_pci_info[id->driver_data], NULL); -} - -/** - * piix_check_450nx - Check for problem 450NX setup - * - * Check for the present of 450NX errata #19 and errata #25. If - * they are found, disable use of DMA IDE - */ - -static void __devinit piix_check_450nx(void) -{ - struct pci_dev *pdev = NULL; - u16 cfg; - while((pdev=pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev))!=NULL) - { - /* Look for 450NX PXB. Check for problem configurations - A PCI quirk checks bit 6 already */ - pci_read_config_word(pdev, 0x41, &cfg); - /* Only on the original revision: IDE DMA can hang */ - if (pdev->revision == 0x00) - no_piix_dma = 1; - /* On all revisions below 5 PXB bus lock must be disabled for IDE */ - else if (cfg & (1<<14) && pdev->revision < 5) - no_piix_dma = 2; - } - if(no_piix_dma) - printk(KERN_WARNING DRV_NAME ": 450NX errata present, disabling IDE DMA.\n"); - if(no_piix_dma == 2) - printk(KERN_WARNING DRV_NAME ": A BIOS update may resolve this.\n"); -} - -static const struct pci_device_id piix_pci_tbl[] = { - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_0), 1 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_1), 1 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371MX), 0 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371SB_1), 1 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371AB), 2 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AB_1), 3 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82443MX_1), 2 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AA_1), 4 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82372FB_1), 5 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82451NX), 2 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_9), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_8), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_10), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_11), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_11), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_11), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801E_11), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_10), 6 }, -#ifdef CONFIG_BLK_DEV_IDE_SATA - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_1), 6 }, -#endif - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18), 6 }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6), 6 }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, piix_pci_tbl); - -static struct pci_driver piix_pci_driver = { - .name = "PIIX_IDE", - .id_table = piix_pci_tbl, - .probe = piix_init_one, - .remove = ide_pci_remove, - .suspend = ide_pci_suspend, - .resume = ide_pci_resume, -}; - -static int __init piix_ide_init(void) -{ - piix_check_450nx(); - return ide_pci_register_driver(&piix_pci_driver); -} - -static void __exit piix_ide_exit(void) -{ - pci_unregister_driver(&piix_pci_driver); -} - -module_init(piix_ide_init); -module_exit(piix_ide_exit); - -MODULE_AUTHOR("Andre Hedrick, Andrzej Krzysztofowicz"); -MODULE_DESCRIPTION("PCI driver module for Intel PIIX IDE"); -MODULE_LICENSE("GPL"); diff --git a/windhoek/ide/setup-pci.c b/windhoek/ide/setup-pci.c deleted file mode 100644 index e85d1ed2..00000000 --- a/windhoek/ide/setup-pci.c +++ /dev/null @@ -1,694 +0,0 @@ -/* - * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> - * Copyright (C) 1995-1998 Mark Lord - * Copyright (C) 2007 Bartlomiej Zolnierkiewicz - * - * May be copied or modified under the terms of the GNU General Public License - */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/ide.h> -#include <linux/dma-mapping.h> - -#include <asm/io.h> - -/** - * ide_setup_pci_baseregs - place a PCI IDE controller native - * @dev: PCI device of interface to switch native - * @name: Name of interface - * - * We attempt to place the PCI interface into PCI native mode. If - * we succeed the BARs are ok and the controller is in PCI mode. - * Returns 0 on success or an errno code. - * - * FIXME: if we program the interface and then fail to set the BARS - * we don't switch it back to legacy mode. Do we actually care ?? - */ - -static int ide_setup_pci_baseregs(struct pci_dev *dev, const char *name) -{ - u8 progif = 0; - - /* - * Place both IDE interfaces into PCI "native" mode: - */ - if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || - (progif & 5) != 5) { - if ((progif & 0xa) != 0xa) { - printk(KERN_INFO "%s %s: device not capable of full " - "native PCI mode\n", name, pci_name(dev)); - return -EOPNOTSUPP; - } - printk(KERN_INFO "%s %s: placing both ports into native PCI " - "mode\n", name, pci_name(dev)); - (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5); - if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || - (progif & 5) != 5) { - printk(KERN_ERR "%s %s: rewrite of PROGIF failed, " - "wanted 0x%04x, got 0x%04x\n", - name, pci_name(dev), progif | 5, progif); - return -EOPNOTSUPP; - } - } - return 0; -} - -#ifdef CONFIG_BLK_DEV_IDEDMA_PCI -static int ide_pci_clear_simplex(unsigned long dma_base, const char *name) -{ - u8 dma_stat = inb(dma_base + 2); - - outb(dma_stat & 0x60, dma_base + 2); - dma_stat = inb(dma_base + 2); - - return (dma_stat & 0x80) ? 1 : 0; -} - -/** - * ide_pci_dma_base - setup BMIBA - * @hwif: IDE interface - * @d: IDE port info - * - * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space. - */ - -unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned long dma_base = 0; - - if (hwif->host_flags & IDE_HFLAG_MMIO) - return hwif->dma_base; - - if (hwif->mate && hwif->mate->dma_base) { - dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8); - } else { - u8 baridx = (d->host_flags & IDE_HFLAG_CS5520) ? 2 : 4; - - dma_base = pci_resource_start(dev, baridx); - - if (dma_base == 0) { - printk(KERN_ERR "%s %s: DMA base is invalid\n", - d->name, pci_name(dev)); - return 0; - } - } - - if (hwif->channel) - dma_base += 8; - - return dma_base; -} -EXPORT_SYMBOL_GPL(ide_pci_dma_base); - -int ide_pci_check_simplex(ide_hwif_t *hwif, const struct ide_port_info *d) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 dma_stat; - - if (d->host_flags & (IDE_HFLAG_MMIO | IDE_HFLAG_CS5520)) - goto out; - - if (d->host_flags & IDE_HFLAG_CLEAR_SIMPLEX) { - if (ide_pci_clear_simplex(hwif->dma_base, d->name)) - printk(KERN_INFO "%s %s: simplex device: DMA forced\n", - d->name, pci_name(dev)); - goto out; - } - - /* - * If the device claims "simplex" DMA, this means that only one of - * the two interfaces can be trusted with DMA at any point in time - * (so we should enable DMA only on one of the two interfaces). - * - * FIXME: At this point we haven't probed the drives so we can't make - * the appropriate decision. Really we should defer this problem until - * we tune the drive then try to grab DMA ownership if we want to be - * the DMA end. This has to be become dynamic to handle hot-plug. - */ - dma_stat = hwif->dma_ops->dma_sff_read_status(hwif); - if ((dma_stat & 0x80) && hwif->mate && hwif->mate->dma_base) { - printk(KERN_INFO "%s %s: simplex device: DMA disabled\n", - d->name, pci_name(dev)); - return -1; - } -out: - return 0; -} -EXPORT_SYMBOL_GPL(ide_pci_check_simplex); - -/* - * Set up BM-DMA capability (PnP BIOS should have done this) - */ -int ide_pci_set_master(struct pci_dev *dev, const char *name) -{ - u16 pcicmd; - - pci_read_config_word(dev, PCI_COMMAND, &pcicmd); - - if ((pcicmd & PCI_COMMAND_MASTER) == 0) { - pci_set_master(dev); - - if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || - (pcicmd & PCI_COMMAND_MASTER) == 0) { - printk(KERN_ERR "%s %s: error updating PCICMD\n", - name, pci_name(dev)); - return -EIO; - } - } - - return 0; -} -EXPORT_SYMBOL_GPL(ide_pci_set_master); -#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ - -void ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d) -{ - printk(KERN_INFO "%s %s: IDE controller (0x%04x:0x%04x rev 0x%02x)\n", - d->name, pci_name(dev), - dev->vendor, dev->device, dev->revision); -} -EXPORT_SYMBOL_GPL(ide_setup_pci_noise); - - -/** - * ide_pci_enable - do PCI enables - * @dev: PCI device - * @d: IDE port info - * - * Enable the IDE PCI device. We attempt to enable the device in full - * but if that fails then we only need IO space. The PCI code should - * have setup the proper resources for us already for controllers in - * legacy mode. - * - * Returns zero on success or an error code - */ - -static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d) -{ - int ret, bars; - - if (pci_enable_device(dev)) { - ret = pci_enable_device_io(dev); - if (ret < 0) { - printk(KERN_WARNING "%s %s: couldn't enable device\n", - d->name, pci_name(dev)); - goto out; - } - printk(KERN_WARNING "%s %s: BIOS configuration fixed\n", - d->name, pci_name(dev)); - } - - /* - * assume all devices can do 32-bit DMA for now, we can add - * a DMA mask field to the struct ide_port_info if we need it - * (or let lower level driver set the DMA mask) - */ - ret = pci_set_dma_mask(dev, DMA_32BIT_MASK); - if (ret < 0) { - printk(KERN_ERR "%s %s: can't set DMA mask\n", - d->name, pci_name(dev)); - goto out; - } - - if (d->host_flags & IDE_HFLAG_SINGLE) - bars = (1 << 2) - 1; - else - bars = (1 << 4) - 1; - - if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) { - if (d->host_flags & IDE_HFLAG_CS5520) - bars |= (1 << 2); - else - bars |= (1 << 4); - } - - ret = pci_request_selected_regions(dev, bars, d->name); - if (ret < 0) - printk(KERN_ERR "%s %s: can't reserve resources\n", - d->name, pci_name(dev)); -out: - return ret; -} - -/** - * ide_pci_configure - configure an unconfigured device - * @dev: PCI device - * @d: IDE port info - * - * Enable and configure the PCI device we have been passed. - * Returns zero on success or an error code. - */ - -static int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d) -{ - u16 pcicmd = 0; - /* - * PnP BIOS was *supposed* to have setup this device, but we - * can do it ourselves, so long as the BIOS has assigned an IRQ - * (or possibly the device is using a "legacy header" for IRQs). - * Maybe the user deliberately *disabled* the device, - * but we'll eventually ignore it again if no drives respond. - */ - if (ide_setup_pci_baseregs(dev, d->name) || - pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) { - printk(KERN_INFO "%s %s: device disabled (BIOS)\n", - d->name, pci_name(dev)); - return -ENODEV; - } - if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) { - printk(KERN_ERR "%s %s: error accessing PCI regs\n", - d->name, pci_name(dev)); - return -EIO; - } - if (!(pcicmd & PCI_COMMAND_IO)) { - printk(KERN_ERR "%s %s: unable to enable IDE controller\n", - d->name, pci_name(dev)); - return -ENXIO; - } - return 0; -} - -/** - * ide_pci_check_iomem - check a register is I/O - * @dev: PCI device - * @d: IDE port info - * @bar: BAR number - * - * Checks if a BAR is configured and points to MMIO space. If so, - * return an error code. Otherwise return 0 - */ - -static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *d, - int bar) -{ - ulong flags = pci_resource_flags(dev, bar); - - /* Unconfigured ? */ - if (!flags || pci_resource_len(dev, bar) == 0) - return 0; - - /* I/O space */ - if (flags & IORESOURCE_IO) - return 0; - - /* Bad */ - return -EINVAL; -} - -/** - * ide_hw_configure - configure a hw_regs_t instance - * @dev: PCI device holding interface - * @d: IDE port info - * @port: port number - * @irq: PCI IRQ - * @hw: hw_regs_t instance corresponding to this port - * - * Perform the initial set up for the hardware interface structure. This - * is done per interface port rather than per PCI device. There may be - * more than one port per device. - * - * Returns zero on success or an error code. - */ - -static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d, - unsigned int port, int irq, hw_regs_t *hw) -{ - unsigned long ctl = 0, base = 0; - - if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) { - if (ide_pci_check_iomem(dev, d, 2 * port) || - ide_pci_check_iomem(dev, d, 2 * port + 1)) { - printk(KERN_ERR "%s %s: I/O baseregs (BIOS) are " - "reported as MEM for port %d!\n", - d->name, pci_name(dev), port); - return -EINVAL; - } - - ctl = pci_resource_start(dev, 2*port+1); - base = pci_resource_start(dev, 2*port); - } else { - /* Use default values */ - ctl = port ? 0x374 : 0x3f4; - base = port ? 0x170 : 0x1f0; - } - - if (!base || !ctl) { - printk(KERN_ERR "%s %s: bad PCI BARs for port %d, skipping\n", - d->name, pci_name(dev), port); - return -EINVAL; - } - - memset(hw, 0, sizeof(*hw)); - hw->irq = irq; - hw->dev = &dev->dev; - hw->chipset = d->chipset ? d->chipset : ide_pci; - ide_std_init_ports(hw, base, ctl | 2); - - return 0; -} - -#ifdef CONFIG_BLK_DEV_IDEDMA_PCI -/** - * ide_hwif_setup_dma - configure DMA interface - * @hwif: IDE interface - * @d: IDE port info - * - * Set up the DMA base for the interface. Enable the master bits as - * necessary and attempt to bring the device DMA into a ready to use - * state - */ - -int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - - if ((d->host_flags & IDE_HFLAG_NO_AUTODMA) == 0 || - ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && - (dev->class & 0x80))) { - unsigned long base = ide_pci_dma_base(hwif, d); - - if (base == 0) - return -1; - - hwif->dma_base = base; - - if (hwif->dma_ops == NULL) - hwif->dma_ops = &sff_dma_ops; - - if (ide_pci_check_simplex(hwif, d) < 0) - return -1; - - if (ide_pci_set_master(dev, d->name) < 0) - return -1; - - if (hwif->host_flags & IDE_HFLAG_MMIO) - printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name); - else - printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n", - hwif->name, base, base + 7); - - hwif->extra_base = base + (hwif->channel ? 8 : 16); - - if (ide_allocate_dma_engine(hwif)) - return -1; - } - - return 0; -} -#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ - -/** - * ide_setup_pci_controller - set up IDE PCI - * @dev: PCI device - * @d: IDE port info - * @noisy: verbose flag - * - * Set up the PCI and controller side of the IDE interface. This brings - * up the PCI side of the device, checks that the device is enabled - * and enables it if need be - */ - -static int ide_setup_pci_controller(struct pci_dev *dev, - const struct ide_port_info *d, int noisy) -{ - int ret; - u16 pcicmd; - - if (noisy) - ide_setup_pci_noise(dev, d); - - ret = ide_pci_enable(dev, d); - if (ret < 0) - goto out; - - ret = pci_read_config_word(dev, PCI_COMMAND, &pcicmd); - if (ret < 0) { - printk(KERN_ERR "%s %s: error accessing PCI regs\n", - d->name, pci_name(dev)); - goto out; - } - if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */ - ret = ide_pci_configure(dev, d); - if (ret < 0) - goto out; - printk(KERN_INFO "%s %s: device enabled (Linux)\n", - d->name, pci_name(dev)); - } - -out: - return ret; -} - -/** - * ide_pci_setup_ports - configure ports/devices on PCI IDE - * @dev: PCI device - * @d: IDE port info - * @pciirq: IRQ line - * @hw: hw_regs_t instances corresponding to this PCI IDE device - * @hws: hw_regs_t pointers table to update - * - * Scan the interfaces attached to this device and do any - * necessary per port setup. Attach the devices and ask the - * generic DMA layer to do its work for us. - * - * Normally called automaticall from do_ide_pci_setup_device, - * but is also used directly as a helper function by some controllers - * where the chipset setup is not the default PCI IDE one. - */ - -void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, - int pciirq, hw_regs_t *hw, hw_regs_t **hws) -{ - int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port; - u8 tmp; - - /* - * Set up the IDE ports - */ - - for (port = 0; port < channels; ++port) { - const struct ide_pci_enablebit *e = &d->enablebits[port]; - - if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || - (tmp & e->mask) != e->val)) { - printk(KERN_INFO "%s %s: IDE port disabled\n", - d->name, pci_name(dev)); - continue; /* port not enabled */ - } - - if (ide_hw_configure(dev, d, port, pciirq, hw + port)) - continue; - - *(hws + port) = hw + port; - } -} -EXPORT_SYMBOL_GPL(ide_pci_setup_ports); - -/* - * ide_setup_pci_device() looks at the primary/secondary interfaces - * on a PCI IDE device and, if they are enabled, prepares the IDE driver - * for use with them. This generic code works for most PCI chipsets. - * - * One thing that is not standardized is the location of the - * primary/secondary interface "enable/disable" bits. For chipsets that - * we "know" about, this information is in the struct ide_port_info; - * for all other chipsets, we just assume both interfaces are enabled. - */ -static int do_ide_setup_pci_device(struct pci_dev *dev, - const struct ide_port_info *d, - u8 noisy) -{ - int pciirq, ret; - - /* - * Can we trust the reported IRQ? - */ - pciirq = dev->irq; - - /* - * This allows offboard ide-pci cards the enable a BIOS, - * verify interrupt settings of split-mirror pci-config - * space, place chipset into init-mode, and/or preserve - * an interrupt if the card is not native ide support. - */ - ret = d->init_chipset ? d->init_chipset(dev) : 0; - if (ret < 0) - goto out; - - if (ide_pci_is_in_compatibility_mode(dev)) { - if (noisy) - printk(KERN_INFO "%s %s: not 100%% native mode: will " - "probe irqs later\n", d->name, pci_name(dev)); - pciirq = ret; - } else if (!pciirq && noisy) { - printk(KERN_WARNING "%s %s: bad irq (%d): will probe later\n", - d->name, pci_name(dev), pciirq); - } else if (noisy) { - printk(KERN_INFO "%s %s: 100%% native mode on irq %d\n", - d->name, pci_name(dev), pciirq); - } - - ret = pciirq; -out: - return ret; -} - -int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d, - void *priv) -{ - struct ide_host *host; - hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL }; - int ret; - - ret = ide_setup_pci_controller(dev, d, 1); - if (ret < 0) - goto out; - - ide_pci_setup_ports(dev, d, 0, &hw[0], &hws[0]); - - host = ide_host_alloc(d, hws); - if (host == NULL) { - ret = -ENOMEM; - goto out; - } - - host->dev[0] = &dev->dev; - - host->host_priv = priv; - - pci_set_drvdata(dev, host); - - ret = do_ide_setup_pci_device(dev, d, 1); - if (ret < 0) - goto out; - - /* fixup IRQ */ - hw[1].irq = hw[0].irq = ret; - - ret = ide_host_register(host, d, hws); - if (ret) - ide_host_free(host); -out: - return ret; -} -EXPORT_SYMBOL_GPL(ide_pci_init_one); - -int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, - const struct ide_port_info *d, void *priv) -{ - struct pci_dev *pdev[] = { dev1, dev2 }; - struct ide_host *host; - int ret, i; - hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL }; - - for (i = 0; i < 2; i++) { - ret = ide_setup_pci_controller(pdev[i], d, !i); - if (ret < 0) - goto out; - - ide_pci_setup_ports(pdev[i], d, 0, &hw[i*2], &hws[i*2]); - } - - host = ide_host_alloc(d, hws); - if (host == NULL) { - ret = -ENOMEM; - goto out; - } - - host->dev[0] = &dev1->dev; - host->dev[1] = &dev2->dev; - - host->host_priv = priv; - - pci_set_drvdata(pdev[0], host); - pci_set_drvdata(pdev[1], host); - - for (i = 0; i < 2; i++) { - ret = do_ide_setup_pci_device(pdev[i], d, !i); - - /* - * FIXME: Mom, mom, they stole me the helper function to undo - * do_ide_setup_pci_device() on the first device! - */ - if (ret < 0) - goto out; - - /* fixup IRQ */ - hw[i*2 + 1].irq = hw[i*2].irq = ret; - } - - ret = ide_host_register(host, d, hws); - if (ret) - ide_host_free(host); -out: - return ret; -} -EXPORT_SYMBOL_GPL(ide_pci_init_two); - -void ide_pci_remove(struct pci_dev *dev) -{ - struct ide_host *host = pci_get_drvdata(dev); - struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL; - int bars; - - if (host->host_flags & IDE_HFLAG_SINGLE) - bars = (1 << 2) - 1; - else - bars = (1 << 4) - 1; - - if ((host->host_flags & IDE_HFLAG_NO_DMA) == 0) { - if (host->host_flags & IDE_HFLAG_CS5520) - bars |= (1 << 2); - else - bars |= (1 << 4); - } - - ide_host_remove(host); - - if (dev2) - pci_release_selected_regions(dev2, bars); - pci_release_selected_regions(dev, bars); - - if (dev2) - pci_disable_device(dev2); - pci_disable_device(dev); -} -EXPORT_SYMBOL_GPL(ide_pci_remove); - -#ifdef CONFIG_PM -int ide_pci_suspend(struct pci_dev *dev, pm_message_t state) -{ - pci_save_state(dev); - pci_disable_device(dev); - pci_set_power_state(dev, pci_choose_state(dev, state)); - - return 0; -} -EXPORT_SYMBOL_GPL(ide_pci_suspend); - -int ide_pci_resume(struct pci_dev *dev) -{ - struct ide_host *host = pci_get_drvdata(dev); - int rc; - - pci_set_power_state(dev, PCI_D0); - - rc = pci_enable_device(dev); - if (rc) - return rc; - - pci_restore_state(dev); - pci_set_master(dev); - - if (host->init_chipset) - host->init_chipset(dev); - - return 0; -} -EXPORT_SYMBOL_GPL(ide_pci_resume); -#endif diff --git a/windhoek/include/Makefile b/windhoek/include/Makefile deleted file mode 100644 index 8d31023f..00000000 --- a/windhoek/include/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -PKGDIR ?= .. -L4DIR ?= $(PKGDIR)/../.. - -# All haeder files found in this directory tree will be automatically -# installed in a way that they can be included with -# #include <l4/pkgname/yourfile.h> later. -# No need to list them in this Makefile. - -include $(L4DIR)/mk/include.mk diff --git a/windhoek/include/types.h b/windhoek/include/types.h deleted file mode 100644 index c8aaeb00..00000000 --- a/windhoek/include/types.h +++ /dev/null @@ -1,135 +0,0 @@ -/** - * \file windhoek/include/types.h - * \brief Windhoek data types - * - * \date 2008-02-15 - * \author Bjoern Doebel <doebel@tudos.org> - * - * (c) 2008 Technische Universitaet Dresden - * This file is part of DROPS, which is distributed under the terms of the - * GNU General Public License 2. Please see the COPYING file for details. - */ - -#ifndef WINDHOEK_DATA_TYPES_H -#define WINDHOEK_DATA_TYPES_H - -#include <l4/dm_generic/types.h> -#include <l4/log/l4log.h> -#include <l4/util/macros.h> - -#define MAX_NAME_LEN 16 - -/** Windhoek BIO types */ -enum -{ - BIO_READ, - BIO_WRITE -}; - -/* - * Windhoek manages connections using dataspaces. Every connection is - * represented by a server-side handle that the client needs to use whenever - * it calls Windhoek. Using this handle, the server manages client state - * containing exactly one control dataspace (CTRL) and an arbitrary number of - * data dataspaces (DATA). - * - * CTRL layout: - * - * +----------------------------------------------------------+ - * | HEAD | - * | * device description (struct windhoek_device) | - * +----------------------------------------------------------+ - * | REQUEST DESCRIPTORS | - * | * array of request descriptors | - * | (struct windhoek_bio) | - * | | - * | ... | - * +----------------------------------------------------------+ - * - * - * - * DATA layout: - * - * DATA spaces contain arbitrary block data and are managed by - * the client. For requests, the client allocates an appropriate region inside - * a DATA space and hands over this dataspace's ID and an offset along with - * the request struct to the server. - */ - - -/* - * Handle to a block device. Retrieved during open() call. - */ -typedef l4_int32_t blockdev_handle_t; - - -/** Information about a Windhoek block device - */ -typedef struct -{ - unsigned int start_sector; /* First sector on disk belonging - to this dev */ - unsigned int block_size; /* sector size */ - unsigned int cylinders; - unsigned int heads; - unsigned int sectors; /* Number of sectors per cylinder */ - unsigned int capacity; /* total no of sectors */ - unsigned long flags; /* flags */ - char name[MAX_NAME_LEN]; /* device name */ - blockdev_handle_t handle; /* device handle */ -} windhoek_device; - - -/** Dump block device info - */ -L4_INLINE void dump_windhoek_device(windhoek_device *dev); -L4_INLINE void dump_windhoek_device(windhoek_device *dev) -{ - LOG("Windhoek device '%s', @ %p", dev->name, dev); - LOG("\tsectors %d, startsect %x", dev->sectors, dev->start_sector); - LOG("\tblock size %d, heads %d, cyl %d", dev->block_size, - dev->heads, dev->cylinders); - LOG("\tflags %lx, handle %x", dev->flags, dev->handle); -} - - -/** Just like BDDF, a BIO consists of one or more chunks inside a dataspace - */ -typedef struct -{ - l4dm_dataspace_t ds; /**< dataspace ID */ - unsigned int offset; /**< offset in DS */ - unsigned int size; /**< chunk size */ -} ds_list_element; - - -L4_INLINE void dump_ds_element(ds_list_element *d); -L4_INLINE void dump_ds_element(ds_list_element *d) -{ - LOG("ds id %04x, offset %x, size %x", d->ds.id, d->offset, d->size); -} - - -/** BIO struct used for transmitting requests - */ -typedef struct -{ - unsigned int uid; /**< unique identifier - managed by clients */ - unsigned int type; /**< bio type */ - blockdev_handle_t handle; /**< handle to block device */ - unsigned int start_sector; /**< start sector of request */ - unsigned short sg_count; /**< number of SG elements */ - /* XXX: Must be last element! */ - ds_list_element sg_data[0]; /**< SG data */ -} windhoek_bio; - - -L4_INLINE void dump_windhoek_bio(windhoek_bio *bio); -L4_INLINE void dump_windhoek_bio(windhoek_bio *bio) -{ - LOG("bio type %s", bio->type == BIO_READ ? "read" : "write"); - LOG("handle %x, start sect %x, sg_count %x", bio->handle, - bio->start_sector, bio->sg_count); -} - -#endif diff --git a/windhoek/main.c b/windhoek/main.c deleted file mode 100644 index c4e88666..00000000 --- a/windhoek/main.c +++ /dev/null @@ -1,77 +0,0 @@ -/** - * \file windhoek/server/src/main.c - * \brief Windhoek main function - * - * \date 2008-01-29 - * \author Bjoern Doebel <doebel@tudos.org> - * - * (c) 2008 Technische Universitaet Dresden - * This file is part of DROPS, which is distributed under the terms of the - * GNU General Public License 2. Please see the COPYING file for details. - */ -#include <asm/current.h> - -#include <linux/kernel.h> -#include <linux/completion.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/wait.h> -#include <linux/sched.h> -#include <linux/workqueue.h> -#include <linux/interrupt.h> -#include <linux/fs.h> -#include <linux/genhd.h> -#include <linux/bio.h> -#include <linux/hdreg.h> -#include <linux/list.h> -#include <linux/buffer_head.h> - -#include <dde.h> -#include <ddekit/initcall.h> -#include <ddekit/assert.h> -#include <dde26.h> - -extern int bdev_cache_init(void); -extern int ide_generic_init(void); -extern int ide_cdrom_init(void); -extern int genhd_device_init(void); - -int using_std = 1; - -int main(int argc, const char **argv) -{ - extern void ds_server(void); - int err; - - l4dde26_init(); - l4dde26_process_init(); - l4dde26_init_timers(); - l4dde26_softirq_init(); - printk("DDE base system initialized.\n"); - err = bdev_cache_init(); - printk("Initialized blockdev caches. (%x)\n", err); - - gendisk_init(); - l4dde26_do_initcalls(); - - /* no generic driver, we use a dedicated one - * XXX: make this a fallback if no other driver is found */ -#if 0 - err = ide_generic_init(); - printk("Initialized generic IDE driver. (%x)\n", err); -#endif - - printk("+----------------------------------------+\n"); - printk("| Windhoek block server |\n"); - printk("| ready to rumble.... |\n"); - printk("+----------------------------------------+\n"); - - register_block (); - mach_device_init(); - trivfs_init(); - - cthread_detach (cthread_fork (ds_server, NULL)); - trivfs_server(); - - return 0; -} diff --git a/windhoek/partitions/Kconfig b/windhoek/partitions/Kconfig deleted file mode 100644 index cb5f0a3f..00000000 --- a/windhoek/partitions/Kconfig +++ /dev/null @@ -1,251 +0,0 @@ -# -# Partition configuration -# -config PARTITION_ADVANCED - bool "Advanced partition selection" - help - Say Y here if you would like to use hard disks under Linux which - were partitioned under an operating system running on a different - architecture than your Linux system. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about foreign partitioning schemes. - - If unsure, say N. - -config ACORN_PARTITION - bool "Acorn partition support" if PARTITION_ADVANCED - default y if ARCH_ACORN - help - Support hard disks partitioned under Acorn operating systems. - -config ACORN_PARTITION_CUMANA - bool "Cumana partition support" if PARTITION_ADVANCED - default y if ARCH_ACORN - depends on ACORN_PARTITION - help - Say Y here if you would like to use hard disks under Linux which - were partitioned using the Cumana interface on Acorn machines. - -config ACORN_PARTITION_EESOX - bool "EESOX partition support" if PARTITION_ADVANCED - default y if ARCH_ACORN - depends on ACORN_PARTITION - -config ACORN_PARTITION_ICS - bool "ICS partition support" if PARTITION_ADVANCED - default y if ARCH_ACORN - depends on ACORN_PARTITION - help - Say Y here if you would like to use hard disks under Linux which - were partitioned using the ICS interface on Acorn machines. - -config ACORN_PARTITION_ADFS - bool "Native filecore partition support" if PARTITION_ADVANCED - default y if ARCH_ACORN - depends on ACORN_PARTITION - help - The Acorn Disc Filing System is the standard file system of the - RiscOS operating system which runs on Acorn's ARM-based Risc PC - systems and the Acorn Archimedes range of machines. If you say - `Y' here, Linux will support disk partitions created under ADFS. - -config ACORN_PARTITION_POWERTEC - bool "PowerTec partition support" if PARTITION_ADVANCED - default y if ARCH_ACORN - depends on ACORN_PARTITION - help - Support reading partition tables created on Acorn machines using - the PowerTec SCSI drive. - -config ACORN_PARTITION_RISCIX - bool "RISCiX partition support" if PARTITION_ADVANCED - default y if ARCH_ACORN - depends on ACORN_PARTITION - help - Once upon a time, there was a native Unix port for the Acorn series - of machines called RISCiX. If you say 'Y' here, Linux will be able - to read disks partitioned under RISCiX. - -config OSF_PARTITION - bool "Alpha OSF partition support" if PARTITION_ADVANCED - default y if ALPHA - help - Say Y here if you would like to use hard disks under Linux which - were partitioned on an Alpha machine. - -config AMIGA_PARTITION - bool "Amiga partition table support" if PARTITION_ADVANCED - default y if (AMIGA || AFFS_FS=y) - help - Say Y here if you would like to use hard disks under Linux which - were partitioned under AmigaOS. - -config ATARI_PARTITION - bool "Atari partition table support" if PARTITION_ADVANCED - default y if ATARI - help - Say Y here if you would like to use hard disks under Linux which - were partitioned under the Atari OS. - -config IBM_PARTITION - bool "IBM disk label and partition support" - depends on PARTITION_ADVANCED && S390 - help - Say Y here if you would like to be able to read the hard disk - partition table format used by IBM DASD disks operating under CMS. - Otherwise, say N. - -config MAC_PARTITION - bool "Macintosh partition map support" if PARTITION_ADVANCED - default y if (MAC || PPC_PMAC) - help - Say Y here if you would like to use hard disks under Linux which - were partitioned on a Macintosh. - -config MSDOS_PARTITION - bool "PC BIOS (MSDOS partition tables) support" if PARTITION_ADVANCED - default y - help - Say Y here. - -config BSD_DISKLABEL - bool "BSD disklabel (FreeBSD partition tables) support" - depends on PARTITION_ADVANCED && MSDOS_PARTITION - help - FreeBSD uses its own hard disk partition scheme on your PC. It - requires only one entry in the primary partition table of your disk - and manages it similarly to DOS extended partitions, putting in its - first sector a new partition table in BSD disklabel format. Saying Y - here allows you to read these disklabels and further mount FreeBSD - partitions from within Linux if you have also said Y to "UFS - file system support", above. If you don't know what all this is - about, say N. - -config MINIX_SUBPARTITION - bool "Minix subpartition support" - depends on PARTITION_ADVANCED && MSDOS_PARTITION - help - Minix 2.0.0/2.0.2 subpartition table support for Linux. - Say Y here if you want to mount and use Minix 2.0.0/2.0.2 - subpartitions. - -config SOLARIS_X86_PARTITION - bool "Solaris (x86) partition table support" - depends on PARTITION_ADVANCED && MSDOS_PARTITION - help - Like most systems, Solaris x86 uses its own hard disk partition - table format, incompatible with all others. Saying Y here allows you - to read these partition tables and further mount Solaris x86 - partitions from within Linux if you have also said Y to "UFS - file system support", above. - -config UNIXWARE_DISKLABEL - bool "Unixware slices support" - depends on PARTITION_ADVANCED && MSDOS_PARTITION - ---help--- - Like some systems, UnixWare uses its own slice table inside a - partition (VTOC - Virtual Table of Contents). Its format is - incompatible with all other OSes. Saying Y here allows you to read - VTOC and further mount UnixWare partitions read-only from within - Linux if you have also said Y to "UFS file system support" or - "System V and Coherent file system support", above. - - This is mainly used to carry data from a UnixWare box to your - Linux box via a removable medium like magneto-optical, ZIP or - removable IDE drives. Note, however, that a good portable way to - transport files and directories between unixes (and even other - operating systems) is given by the tar program ("man tar" or - preferably "info tar"). - - If you don't know what all this is about, say N. - -config LDM_PARTITION - bool "Windows Logical Disk Manager (Dynamic Disk) support" - depends on PARTITION_ADVANCED - ---help--- - Say Y here if you would like to use hard disks under Linux which - were partitioned using Windows 2000's/XP's or Vista's Logical Disk - Manager. They are also known as "Dynamic Disks". - - Note this driver only supports Dynamic Disks with a protective MBR - label, i.e. DOS partition table. It does not support GPT labelled - Dynamic Disks yet as can be created with Vista. - - Windows 2000 introduced the concept of Dynamic Disks to get around - the limitations of the PC's partitioning scheme. The Logical Disk - Manager allows the user to repartition a disk and create spanned, - mirrored, striped or RAID volumes, all without the need for - rebooting. - - Normal partitions are now called Basic Disks under Windows 2000, XP, - and Vista. - - For a fuller description read <file:Documentation/ldm.txt>. - - If unsure, say N. - -config LDM_DEBUG - bool "Windows LDM extra logging" - depends on LDM_PARTITION - help - Say Y here if you would like LDM to log verbosely. This could be - helpful if the driver doesn't work as expected and you'd like to - report a bug. - - If unsure, say N. - -config SGI_PARTITION - bool "SGI partition support" if PARTITION_ADVANCED - default y if DEFAULT_SGI_PARTITION - help - Say Y here if you would like to be able to read the hard disk - partition table format used by SGI machines. - -config ULTRIX_PARTITION - bool "Ultrix partition table support" if PARTITION_ADVANCED - default y if MACH_DECSTATION - help - Say Y here if you would like to be able to read the hard disk - partition table format used by DEC (now Compaq) Ultrix machines. - Otherwise, say N. - -config SUN_PARTITION - bool "Sun partition tables support" if PARTITION_ADVANCED - default y if (SPARC || SUN3 || SUN3X) - ---help--- - Like most systems, SunOS uses its own hard disk partition table - format, incompatible with all others. Saying Y here allows you to - read these partition tables and further mount SunOS partitions from - within Linux if you have also said Y to "UFS file system support", - above. This is mainly used to carry data from a SPARC under SunOS to - your Linux box via a removable medium like magneto-optical or ZIP - drives; note however that a good portable way to transport files and - directories between unixes (and even other operating systems) is - given by the tar program ("man tar" or preferably "info tar"). If - you don't know what all this is about, say N. - -config KARMA_PARTITION - bool "Karma Partition support" - depends on PARTITION_ADVANCED - help - Say Y here if you would like to mount the Rio Karma MP3 player, as it - uses a proprietary partition table. - -config EFI_PARTITION - bool "EFI GUID Partition support" - depends on PARTITION_ADVANCED - select CRC32 - help - Say Y here if you would like to use hard disks under Linux which - were partitioned using EFI GPT. - -config SYSV68_PARTITION - bool "SYSV68 partition table support" if PARTITION_ADVANCED - default y if VME - help - Say Y here if you would like to be able to read the hard disk - partition table format used by Motorola Delta machines (using - sysv68). - Otherwise, say N. diff --git a/windhoek/partitions/Makefile b/windhoek/partitions/Makefile deleted file mode 100644 index 03af8eac..00000000 --- a/windhoek/partitions/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# -# Makefile for the linux kernel. -# - -obj-$(CONFIG_BLOCK) := check.o - -obj-$(CONFIG_ACORN_PARTITION) += acorn.o -obj-$(CONFIG_AMIGA_PARTITION) += amiga.o -obj-$(CONFIG_ATARI_PARTITION) += atari.o -obj-$(CONFIG_MAC_PARTITION) += mac.o -obj-$(CONFIG_LDM_PARTITION) += ldm.o -obj-$(CONFIG_MSDOS_PARTITION) += msdos.o -obj-$(CONFIG_OSF_PARTITION) += osf.o -obj-$(CONFIG_SGI_PARTITION) += sgi.o -obj-$(CONFIG_SUN_PARTITION) += sun.o -obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o -obj-$(CONFIG_IBM_PARTITION) += ibm.o -obj-$(CONFIG_EFI_PARTITION) += efi.o -obj-$(CONFIG_KARMA_PARTITION) += karma.o -obj-$(CONFIG_SYSV68_PARTITION) += sysv68.o diff --git a/windhoek/partitions/acorn.c b/windhoek/partitions/acorn.c deleted file mode 100644 index a97b477a..00000000 --- a/windhoek/partitions/acorn.c +++ /dev/null @@ -1,555 +0,0 @@ -/* - * linux/fs/partitions/acorn.c - * - * Copyright (c) 1996-2000 Russell King. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Scan ADFS partitions on hard disk drives. Unfortunately, there - * isn't a standard for partitioning drives on Acorn machines, so - * every single manufacturer of SCSI and IDE cards created their own - * method. - */ -#include <linux/buffer_head.h> -#include <linux/adfs_fs.h> - -#include "check.h" -#include "acorn.h" - -/* - * Partition types. (Oh for reusability) - */ -#define PARTITION_RISCIX_MFM 1 -#define PARTITION_RISCIX_SCSI 2 -#define PARTITION_LINUX 9 - -#if defined(CONFIG_ACORN_PARTITION_CUMANA) || \ - defined(CONFIG_ACORN_PARTITION_ADFS) -static struct adfs_discrecord * -adfs_partition(struct parsed_partitions *state, char *name, char *data, - unsigned long first_sector, int slot) -{ - struct adfs_discrecord *dr; - unsigned int nr_sects; - - if (adfs_checkbblk(data)) - return NULL; - - dr = (struct adfs_discrecord *)(data + 0x1c0); - - if (dr->disc_size == 0 && dr->disc_size_high == 0) - return NULL; - - nr_sects = (le32_to_cpu(dr->disc_size_high) << 23) | - (le32_to_cpu(dr->disc_size) >> 9); - - if (name) - printk(" [%s]", name); - put_partition(state, slot, first_sector, nr_sects); - return dr; -} -#endif - -#ifdef CONFIG_ACORN_PARTITION_RISCIX - -struct riscix_part { - __le32 start; - __le32 length; - __le32 one; - char name[16]; -}; - -struct riscix_record { - __le32 magic; -#define RISCIX_MAGIC cpu_to_le32(0x4a657320) - __le32 date; - struct riscix_part part[8]; -}; - -#if defined(CONFIG_ACORN_PARTITION_CUMANA) || \ - defined(CONFIG_ACORN_PARTITION_ADFS) -static int -riscix_partition(struct parsed_partitions *state, struct block_device *bdev, - unsigned long first_sect, int slot, unsigned long nr_sects) -{ - Sector sect; - struct riscix_record *rr; - - rr = (struct riscix_record *)read_dev_sector(bdev, first_sect, §); - if (!rr) - return -1; - - printk(" [RISCiX]"); - - - if (rr->magic == RISCIX_MAGIC) { - unsigned long size = nr_sects > 2 ? 2 : nr_sects; - int part; - - printk(" <"); - - put_partition(state, slot++, first_sect, size); - for (part = 0; part < 8; part++) { - if (rr->part[part].one && - memcmp(rr->part[part].name, "All\0", 4)) { - put_partition(state, slot++, - le32_to_cpu(rr->part[part].start), - le32_to_cpu(rr->part[part].length)); - printk("(%s)", rr->part[part].name); - } - } - - printk(" >\n"); - } else { - put_partition(state, slot++, first_sect, nr_sects); - } - - put_dev_sector(sect); - return slot; -} -#endif -#endif - -#define LINUX_NATIVE_MAGIC 0xdeafa1de -#define LINUX_SWAP_MAGIC 0xdeafab1e - -struct linux_part { - __le32 magic; - __le32 start_sect; - __le32 nr_sects; -}; - -#if defined(CONFIG_ACORN_PARTITION_CUMANA) || \ - defined(CONFIG_ACORN_PARTITION_ADFS) -static int -linux_partition(struct parsed_partitions *state, struct block_device *bdev, - unsigned long first_sect, int slot, unsigned long nr_sects) -{ - Sector sect; - struct linux_part *linuxp; - unsigned long size = nr_sects > 2 ? 2 : nr_sects; - - printk(" [Linux]"); - - put_partition(state, slot++, first_sect, size); - - linuxp = (struct linux_part *)read_dev_sector(bdev, first_sect, §); - if (!linuxp) - return -1; - - printk(" <"); - while (linuxp->magic == cpu_to_le32(LINUX_NATIVE_MAGIC) || - linuxp->magic == cpu_to_le32(LINUX_SWAP_MAGIC)) { - if (slot == state->limit) - break; - put_partition(state, slot++, first_sect + - le32_to_cpu(linuxp->start_sect), - le32_to_cpu(linuxp->nr_sects)); - linuxp ++; - } - printk(" >"); - - put_dev_sector(sect); - return slot; -} -#endif - -#ifdef CONFIG_ACORN_PARTITION_CUMANA -int -adfspart_check_CUMANA(struct parsed_partitions *state, struct block_device *bdev) -{ - unsigned long first_sector = 0; - unsigned int start_blk = 0; - Sector sect; - unsigned char *data; - char *name = "CUMANA/ADFS"; - int first = 1; - int slot = 1; - - /* - * Try Cumana style partitions - sector 6 contains ADFS boot block - * with pointer to next 'drive'. - * - * There are unknowns in this code - is the 'cylinder number' of the - * next partition relative to the start of this one - I'm assuming - * it is. - * - * Also, which ID did Cumana use? - * - * This is totally unfinished, and will require more work to get it - * going. Hence it is totally untested. - */ - do { - struct adfs_discrecord *dr; - unsigned int nr_sects; - - data = read_dev_sector(bdev, start_blk * 2 + 6, §); - if (!data) - return -1; - - if (slot == state->limit) - break; - - dr = adfs_partition(state, name, data, first_sector, slot++); - if (!dr) - break; - - name = NULL; - - nr_sects = (data[0x1fd] + (data[0x1fe] << 8)) * - (dr->heads + (dr->lowsector & 0x40 ? 1 : 0)) * - dr->secspertrack; - - if (!nr_sects) - break; - - first = 0; - first_sector += nr_sects; - start_blk += nr_sects >> (BLOCK_SIZE_BITS - 9); - nr_sects = 0; /* hmm - should be partition size */ - - switch (data[0x1fc] & 15) { - case 0: /* No partition / ADFS? */ - break; - -#ifdef CONFIG_ACORN_PARTITION_RISCIX - case PARTITION_RISCIX_SCSI: - /* RISCiX - we don't know how to find the next one. */ - slot = riscix_partition(state, bdev, first_sector, - slot, nr_sects); - break; -#endif - - case PARTITION_LINUX: - slot = linux_partition(state, bdev, first_sector, - slot, nr_sects); - break; - } - put_dev_sector(sect); - if (slot == -1) - return -1; - } while (1); - put_dev_sector(sect); - return first ? 0 : 1; -} -#endif - -#ifdef CONFIG_ACORN_PARTITION_ADFS -/* - * Purpose: allocate ADFS partitions. - * - * Params : hd - pointer to gendisk structure to store partition info. - * dev - device number to access. - * - * Returns: -1 on error, 0 for no ADFS boot sector, 1 for ok. - * - * Alloc : hda = whole drive - * hda1 = ADFS partition on first drive. - * hda2 = non-ADFS partition. - */ -int -adfspart_check_ADFS(struct parsed_partitions *state, struct block_device *bdev) -{ - unsigned long start_sect, nr_sects, sectscyl, heads; - Sector sect; - unsigned char *data; - struct adfs_discrecord *dr; - unsigned char id; - int slot = 1; - - data = read_dev_sector(bdev, 6, §); - if (!data) - return -1; - - dr = adfs_partition(state, "ADFS", data, 0, slot++); - if (!dr) { - put_dev_sector(sect); - return 0; - } - - heads = dr->heads + ((dr->lowsector >> 6) & 1); - sectscyl = dr->secspertrack * heads; - start_sect = ((data[0x1fe] << 8) + data[0x1fd]) * sectscyl; - id = data[0x1fc] & 15; - put_dev_sector(sect); - - /* - * Work out start of non-adfs partition. - */ - nr_sects = (bdev->bd_inode->i_size >> 9) - start_sect; - - if (start_sect) { - switch (id) { -#ifdef CONFIG_ACORN_PARTITION_RISCIX - case PARTITION_RISCIX_SCSI: - case PARTITION_RISCIX_MFM: - slot = riscix_partition(state, bdev, start_sect, - slot, nr_sects); - break; -#endif - - case PARTITION_LINUX: - slot = linux_partition(state, bdev, start_sect, - slot, nr_sects); - break; - } - } - printk("\n"); - return 1; -} -#endif - -#ifdef CONFIG_ACORN_PARTITION_ICS - -struct ics_part { - __le32 start; - __le32 size; -}; - -static int adfspart_check_ICSLinux(struct block_device *bdev, unsigned long block) -{ - Sector sect; - unsigned char *data = read_dev_sector(bdev, block, §); - int result = 0; - - if (data) { - if (memcmp(data, "LinuxPart", 9) == 0) - result = 1; - put_dev_sector(sect); - } - - return result; -} - -/* - * Check for a valid ICS partition using the checksum. - */ -static inline int valid_ics_sector(const unsigned char *data) -{ - unsigned long sum; - int i; - - for (i = 0, sum = 0x50617274; i < 508; i++) - sum += data[i]; - - sum -= le32_to_cpu(*(__le32 *)(&data[508])); - - return sum == 0; -} - -/* - * Purpose: allocate ICS partitions. - * Params : hd - pointer to gendisk structure to store partition info. - * dev - device number to access. - * Returns: -1 on error, 0 for no ICS table, 1 for partitions ok. - * Alloc : hda = whole drive - * hda1 = ADFS partition 0 on first drive. - * hda2 = ADFS partition 1 on first drive. - * ..etc.. - */ -int -adfspart_check_ICS(struct parsed_partitions *state, struct block_device *bdev) -{ - const unsigned char *data; - const struct ics_part *p; - int slot; - Sector sect; - - /* - * Try ICS style partitions - sector 0 contains partition info. - */ - data = read_dev_sector(bdev, 0, §); - if (!data) - return -1; - - if (!valid_ics_sector(data)) { - put_dev_sector(sect); - return 0; - } - - printk(" [ICS]"); - - for (slot = 1, p = (const struct ics_part *)data; p->size; p++) { - u32 start = le32_to_cpu(p->start); - s32 size = le32_to_cpu(p->size); /* yes, it's signed. */ - - if (slot == state->limit) - break; - - /* - * Negative sizes tell the RISC OS ICS driver to ignore - * this partition - in effect it says that this does not - * contain an ADFS filesystem. - */ - if (size < 0) { - size = -size; - - /* - * Our own extension - We use the first sector - * of the partition to identify what type this - * partition is. We must not make this visible - * to the filesystem. - */ - if (size > 1 && adfspart_check_ICSLinux(bdev, start)) { - start += 1; - size -= 1; - } - } - - if (size) - put_partition(state, slot++, start, size); - } - - put_dev_sector(sect); - printk("\n"); - return 1; -} -#endif - -#ifdef CONFIG_ACORN_PARTITION_POWERTEC -struct ptec_part { - __le32 unused1; - __le32 unused2; - __le32 start; - __le32 size; - __le32 unused5; - char type[8]; -}; - -static inline int valid_ptec_sector(const unsigned char *data) -{ - unsigned char checksum = 0x2a; - int i; - - /* - * If it looks like a PC/BIOS partition, then it - * probably isn't PowerTec. - */ - if (data[510] == 0x55 && data[511] == 0xaa) - return 0; - - for (i = 0; i < 511; i++) - checksum += data[i]; - - return checksum == data[511]; -} - -/* - * Purpose: allocate ICS partitions. - * Params : hd - pointer to gendisk structure to store partition info. - * dev - device number to access. - * Returns: -1 on error, 0 for no ICS table, 1 for partitions ok. - * Alloc : hda = whole drive - * hda1 = ADFS partition 0 on first drive. - * hda2 = ADFS partition 1 on first drive. - * ..etc.. - */ -int -adfspart_check_POWERTEC(struct parsed_partitions *state, struct block_device *bdev) -{ - Sector sect; - const unsigned char *data; - const struct ptec_part *p; - int slot = 1; - int i; - - data = read_dev_sector(bdev, 0, §); - if (!data) - return -1; - - if (!valid_ptec_sector(data)) { - put_dev_sector(sect); - return 0; - } - - printk(" [POWERTEC]"); - - for (i = 0, p = (const struct ptec_part *)data; i < 12; i++, p++) { - u32 start = le32_to_cpu(p->start); - u32 size = le32_to_cpu(p->size); - - if (size) - put_partition(state, slot++, start, size); - } - - put_dev_sector(sect); - printk("\n"); - return 1; -} -#endif - -#ifdef CONFIG_ACORN_PARTITION_EESOX -struct eesox_part { - char magic[6]; - char name[10]; - __le32 start; - __le32 unused6; - __le32 unused7; - __le32 unused8; -}; - -/* - * Guess who created this format? - */ -static const char eesox_name[] = { - 'N', 'e', 'i', 'l', ' ', - 'C', 'r', 'i', 't', 'c', 'h', 'e', 'l', 'l', ' ', ' ' -}; - -/* - * EESOX SCSI partition format. - * - * This is a goddamned awful partition format. We don't seem to store - * the size of the partition in this table, only the start addresses. - * - * There are two possibilities where the size comes from: - * 1. The individual ADFS boot block entries that are placed on the disk. - * 2. The start address of the next entry. - */ -int -adfspart_check_EESOX(struct parsed_partitions *state, struct block_device *bdev) -{ - Sector sect; - const unsigned char *data; - unsigned char buffer[256]; - struct eesox_part *p; - sector_t start = 0; - int i, slot = 1; - - data = read_dev_sector(bdev, 7, §); - if (!data) - return -1; - - /* - * "Decrypt" the partition table. God knows why... - */ - for (i = 0; i < 256; i++) - buffer[i] = data[i] ^ eesox_name[i & 15]; - - put_dev_sector(sect); - - for (i = 0, p = (struct eesox_part *)buffer; i < 8; i++, p++) { - sector_t next; - - if (memcmp(p->magic, "Eesox", 6)) - break; - - next = le32_to_cpu(p->start); - if (i) - put_partition(state, slot++, start, next - start); - start = next; - } - - if (i != 0) { - sector_t size; - - size = get_capacity(bdev->bd_disk); - put_partition(state, slot++, start, size - start); - printk("\n"); - } - - return i ? 1 : 0; -} -#endif diff --git a/windhoek/partitions/acorn.h b/windhoek/partitions/acorn.h deleted file mode 100644 index 81fd50ec..00000000 --- a/windhoek/partitions/acorn.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * linux/fs/partitions/acorn.h - * - * Copyright (C) 1996-2001 Russell King. - * - * I _hate_ this partitioning mess - why can't we have one defined - * format, and everyone stick to it? - */ - -int adfspart_check_CUMANA(struct parsed_partitions *state, struct block_device *bdev); -int adfspart_check_ADFS(struct parsed_partitions *state, struct block_device *bdev); -int adfspart_check_ICS(struct parsed_partitions *state, struct block_device *bdev); -int adfspart_check_POWERTEC(struct parsed_partitions *state, struct block_device *bdev); -int adfspart_check_EESOX(struct parsed_partitions *state, struct block_device *bdev); diff --git a/windhoek/partitions/amiga.c b/windhoek/partitions/amiga.c deleted file mode 100644 index 9917a8c3..00000000 --- a/windhoek/partitions/amiga.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * fs/partitions/amiga.c - * - * Code extracted from drivers/block/genhd.c - * - * Copyright (C) 1991-1998 Linus Torvalds - * Re-organised Feb 1998 Russell King - */ - -#include <linux/types.h> -#include <linux/affs_hardblocks.h> - -#include "check.h" -#include "amiga.h" - -static __inline__ u32 -checksum_block(__be32 *m, int size) -{ - u32 sum = 0; - - while (size--) - sum += be32_to_cpu(*m++); - return sum; -} - -int -amiga_partition(struct parsed_partitions *state, struct block_device *bdev) -{ - Sector sect; - unsigned char *data; - struct RigidDiskBlock *rdb; - struct PartitionBlock *pb; - int start_sect, nr_sects, blk, part, res = 0; - int blksize = 1; /* Multiplier for disk block size */ - int slot = 1; - char b[BDEVNAME_SIZE]; - - for (blk = 0; ; blk++, put_dev_sector(sect)) { - if (blk == RDB_ALLOCATION_LIMIT) - goto rdb_done; - data = read_dev_sector(bdev, blk, §); - if (!data) { - if (warn_no_part) - printk("Dev %s: unable to read RDB block %d\n", - bdevname(bdev, b), blk); - res = -1; - goto rdb_done; - } - if (*(__be32 *)data != cpu_to_be32(IDNAME_RIGIDDISK)) - continue; - - rdb = (struct RigidDiskBlock *)data; - if (checksum_block((__be32 *)data, be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F) == 0) - break; - /* Try again with 0xdc..0xdf zeroed, Windows might have - * trashed it. - */ - *(__be32 *)(data+0xdc) = 0; - if (checksum_block((__be32 *)data, - be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)==0) { - printk("Warning: Trashed word at 0xd0 in block %d " - "ignored in checksum calculation\n",blk); - break; - } - - printk("Dev %s: RDB in block %d has bad checksum\n", - bdevname(bdev, b), blk); - } - - /* blksize is blocks per 512 byte standard block */ - blksize = be32_to_cpu( rdb->rdb_BlockBytes ) / 512; - - printk(" RDSK (%d)", blksize * 512); /* Be more informative */ - blk = be32_to_cpu(rdb->rdb_PartitionList); - put_dev_sector(sect); - for (part = 1; blk>0 && part<=16; part++, put_dev_sector(sect)) { - blk *= blksize; /* Read in terms partition table understands */ - data = read_dev_sector(bdev, blk, §); - if (!data) { - if (warn_no_part) - printk("Dev %s: unable to read partition block %d\n", - bdevname(bdev, b), blk); - res = -1; - goto rdb_done; - } - pb = (struct PartitionBlock *)data; - blk = be32_to_cpu(pb->pb_Next); - if (pb->pb_ID != cpu_to_be32(IDNAME_PARTITION)) - continue; - if (checksum_block((__be32 *)pb, be32_to_cpu(pb->pb_SummedLongs) & 0x7F) != 0 ) - continue; - - /* Tell Kernel about it */ - - nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 - - be32_to_cpu(pb->pb_Environment[9])) * - be32_to_cpu(pb->pb_Environment[3]) * - be32_to_cpu(pb->pb_Environment[5]) * - blksize; - if (!nr_sects) - continue; - start_sect = be32_to_cpu(pb->pb_Environment[9]) * - be32_to_cpu(pb->pb_Environment[3]) * - be32_to_cpu(pb->pb_Environment[5]) * - blksize; - put_partition(state,slot++,start_sect,nr_sects); - { - /* Be even more informative to aid mounting */ - char dostype[4]; - __be32 *dt = (__be32 *)dostype; - *dt = pb->pb_Environment[16]; - if (dostype[3] < ' ') - printk(" (%c%c%c^%c)", - dostype[0], dostype[1], - dostype[2], dostype[3] + '@' ); - else - printk(" (%c%c%c%c)", - dostype[0], dostype[1], - dostype[2], dostype[3]); - printk("(res %d spb %d)", - be32_to_cpu(pb->pb_Environment[6]), - be32_to_cpu(pb->pb_Environment[4])); - } - res = 1; - } - printk("\n"); - -rdb_done: - return res; -} diff --git a/windhoek/partitions/amiga.h b/windhoek/partitions/amiga.h deleted file mode 100644 index 2f3e9ce2..00000000 --- a/windhoek/partitions/amiga.h +++ /dev/null @@ -1,6 +0,0 @@ -/* - * fs/partitions/amiga.h - */ - -int amiga_partition(struct parsed_partitions *state, struct block_device *bdev); - diff --git a/windhoek/partitions/atari.c b/windhoek/partitions/atari.c deleted file mode 100644 index 1f3572d5..00000000 --- a/windhoek/partitions/atari.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * fs/partitions/atari.c - * - * Code extracted from drivers/block/genhd.c - * - * Copyright (C) 1991-1998 Linus Torvalds - * Re-organised Feb 1998 Russell King - */ - -#include <linux/ctype.h> -#include "check.h" -#include "atari.h" - -/* ++guenther: this should be settable by the user ("make config")?. - */ -#define ICD_PARTS - -/* check if a partition entry looks valid -- Atari format is assumed if at - least one of the primary entries is ok this way */ -#define VALID_PARTITION(pi,hdsiz) \ - (((pi)->flg & 1) && \ - isalnum((pi)->id[0]) && isalnum((pi)->id[1]) && isalnum((pi)->id[2]) && \ - be32_to_cpu((pi)->st) <= (hdsiz) && \ - be32_to_cpu((pi)->st) + be32_to_cpu((pi)->siz) <= (hdsiz)) - -static inline int OK_id(char *s) -{ - return memcmp (s, "GEM", 3) == 0 || memcmp (s, "BGM", 3) == 0 || - memcmp (s, "LNX", 3) == 0 || memcmp (s, "SWP", 3) == 0 || - memcmp (s, "RAW", 3) == 0 ; -} - -int atari_partition(struct parsed_partitions *state, struct block_device *bdev) -{ - Sector sect; - struct rootsector *rs; - struct partition_info *pi; - u32 extensect; - u32 hd_size; - int slot; -#ifdef ICD_PARTS - int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */ -#endif - - rs = (struct rootsector *) read_dev_sector(bdev, 0, §); - if (!rs) - return -1; - - /* Verify this is an Atari rootsector: */ - hd_size = bdev->bd_inode->i_size >> 9; - if (!VALID_PARTITION(&rs->part[0], hd_size) && - !VALID_PARTITION(&rs->part[1], hd_size) && - !VALID_PARTITION(&rs->part[2], hd_size) && - !VALID_PARTITION(&rs->part[3], hd_size)) { - /* - * if there's no valid primary partition, assume that no Atari - * format partition table (there's no reliable magic or the like - * :-() - */ - put_dev_sector(sect); - return 0; - } - - pi = &rs->part[0]; - printk (" AHDI"); - for (slot = 1; pi < &rs->part[4] && slot < state->limit; slot++, pi++) { - struct rootsector *xrs; - Sector sect2; - ulong partsect; - - if ( !(pi->flg & 1) ) - continue; - /* active partition */ - if (memcmp (pi->id, "XGM", 3) != 0) { - /* we don't care about other id's */ - put_partition (state, slot, be32_to_cpu(pi->st), - be32_to_cpu(pi->siz)); - continue; - } - /* extension partition */ -#ifdef ICD_PARTS - part_fmt = 1; -#endif - printk(" XGM<"); - partsect = extensect = be32_to_cpu(pi->st); - while (1) { - xrs = (struct rootsector *)read_dev_sector(bdev, partsect, §2); - if (!xrs) { - printk (" block %ld read failed\n", partsect); - put_dev_sector(sect); - return -1; - } - - /* ++roman: sanity check: bit 0 of flg field must be set */ - if (!(xrs->part[0].flg & 1)) { - printk( "\nFirst sub-partition in extended partition is not valid!\n" ); - put_dev_sector(sect2); - break; - } - - put_partition(state, slot, - partsect + be32_to_cpu(xrs->part[0].st), - be32_to_cpu(xrs->part[0].siz)); - - if (!(xrs->part[1].flg & 1)) { - /* end of linked partition list */ - put_dev_sector(sect2); - break; - } - if (memcmp( xrs->part[1].id, "XGM", 3 ) != 0) { - printk("\nID of extended partition is not XGM!\n"); - put_dev_sector(sect2); - break; - } - - partsect = be32_to_cpu(xrs->part[1].st) + extensect; - put_dev_sector(sect2); - if (++slot == state->limit) { - printk( "\nMaximum number of partitions reached!\n" ); - break; - } - } - printk(" >"); - } -#ifdef ICD_PARTS - if ( part_fmt!=1 ) { /* no extended partitions -> test ICD-format */ - pi = &rs->icdpart[0]; - /* sanity check: no ICD format if first partition invalid */ - if (OK_id(pi->id)) { - printk(" ICD<"); - for (; pi < &rs->icdpart[8] && slot < state->limit; slot++, pi++) { - /* accept only GEM,BGM,RAW,LNX,SWP partitions */ - if (!((pi->flg & 1) && OK_id(pi->id))) - continue; - part_fmt = 2; - put_partition (state, slot, - be32_to_cpu(pi->st), - be32_to_cpu(pi->siz)); - } - printk(" >"); - } - } -#endif - put_dev_sector(sect); - - printk ("\n"); - - return 1; -} diff --git a/windhoek/partitions/atari.h b/windhoek/partitions/atari.h deleted file mode 100644 index 63186b00..00000000 --- a/windhoek/partitions/atari.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * fs/partitions/atari.h - * Moved by Russell King from: - * - * linux/include/linux/atari_rootsec.h - * definitions for Atari Rootsector layout - * by Andreas Schwab (schwab@ls5.informatik.uni-dortmund.de) - * - * modified for ICD/Supra partitioning scheme restricted to at most 12 - * partitions - * by Guenther Kelleter (guenther@pool.informatik.rwth-aachen.de) - */ - -struct partition_info -{ - u8 flg; /* bit 0: active; bit 7: bootable */ - char id[3]; /* "GEM", "BGM", "XGM", or other */ - __be32 st; /* start of partition */ - __be32 siz; /* length of partition */ -}; - -struct rootsector -{ - char unused[0x156]; /* room for boot code */ - struct partition_info icdpart[8]; /* info for ICD-partitions 5..12 */ - char unused2[0xc]; - u32 hd_siz; /* size of disk in blocks */ - struct partition_info part[4]; - u32 bsl_st; /* start of bad sector list */ - u32 bsl_cnt; /* length of bad sector list */ - u16 checksum; /* checksum for bootable disks */ -} __attribute__((__packed__)); - -int atari_partition(struct parsed_partitions *state, struct block_device *bdev); diff --git a/windhoek/partitions/check.c b/windhoek/partitions/check.c deleted file mode 100644 index 041a2d37..00000000 --- a/windhoek/partitions/check.c +++ /dev/null @@ -1,643 +0,0 @@ -/* - * fs/partitions/check.c - * - * Code extracted from drivers/block/genhd.c - * Copyright (C) 1991-1998 Linus Torvalds - * Re-organised Feb 1998 Russell King - * - * We now have independent partition support from the - * block drivers, which allows all the partition code to - * be grouped in one location, and it to be mostly self - * contained. - * - * Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl} - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/kmod.h> -#include <linux/ctype.h> -#include <linux/genhd.h> - -#include "check.h" - -#include "acorn.h" -#include "amiga.h" -#include "atari.h" -#include "ldm.h" -#include "mac.h" -#include "msdos.h" -#include "osf.h" -#include "sgi.h" -#include "sun.h" -#include "ibm.h" -#include "ultrix.h" -#include "efi.h" -#include "karma.h" -#include "sysv68.h" - -#ifdef CONFIG_BLK_DEV_MD -extern void md_autodetect_dev(dev_t dev); -#endif - -int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/ - -#ifndef DDE_LINUX -static int (*check_part[])(struct parsed_partitions *, struct block_device *) = { - /* - * Probe partition formats with tables at disk address 0 - * that also have an ADFS boot block at 0xdc0. - */ -#ifdef CONFIG_ACORN_PARTITION_ICS - adfspart_check_ICS, -#endif -#ifdef CONFIG_ACORN_PARTITION_POWERTEC - adfspart_check_POWERTEC, -#endif -#ifdef CONFIG_ACORN_PARTITION_EESOX - adfspart_check_EESOX, -#endif - - /* - * Now move on to formats that only have partition info at - * disk address 0xdc0. Since these may also have stale - * PC/BIOS partition tables, they need to come before - * the msdos entry. - */ -#ifdef CONFIG_ACORN_PARTITION_CUMANA - adfspart_check_CUMANA, -#endif -#ifdef CONFIG_ACORN_PARTITION_ADFS - adfspart_check_ADFS, -#endif - -#ifdef CONFIG_EFI_PARTITION - efi_partition, /* this must come before msdos */ -#endif -#ifdef CONFIG_SGI_PARTITION - sgi_partition, -#endif -#ifdef CONFIG_LDM_PARTITION - ldm_partition, /* this must come before msdos */ -#endif -#ifdef CONFIG_MSDOS_PARTITION - msdos_partition, -#endif -#ifdef CONFIG_OSF_PARTITION - osf_partition, -#endif -#ifdef CONFIG_SUN_PARTITION - sun_partition, -#endif -#ifdef CONFIG_AMIGA_PARTITION - amiga_partition, -#endif -#ifdef CONFIG_ATARI_PARTITION - atari_partition, -#endif -#ifdef CONFIG_MAC_PARTITION - mac_partition, -#endif -#ifdef CONFIG_ULTRIX_PARTITION - ultrix_partition, -#endif -#ifdef CONFIG_IBM_PARTITION - ibm_partition, -#endif -#ifdef CONFIG_KARMA_PARTITION - karma_partition, -#endif -#ifdef CONFIG_SYSV68_PARTITION - sysv68_partition, -#endif - NULL -}; -#endif - -/* - * disk_name() is used by partition check code and the genhd driver. - * It formats the devicename of the indicated disk into - * the supplied buffer (of size at least 32), and returns - * a pointer to that same buffer (for convenience). - */ - -char *disk_name(struct gendisk *hd, int partno, char *buf) -{ - if (!partno) - snprintf(buf, BDEVNAME_SIZE, "%s", hd->disk_name); - else if (isdigit(hd->disk_name[strlen(hd->disk_name)-1])) - snprintf(buf, BDEVNAME_SIZE, "%sp%d", hd->disk_name, partno); - else - snprintf(buf, BDEVNAME_SIZE, "%s%d", hd->disk_name, partno); - - return buf; -} - -const char *bdevname(struct block_device *bdev, char *buf) -{ - return disk_name(bdev->bd_disk, bdev->bd_part->partno, buf); -} - -EXPORT_SYMBOL(bdevname); - -/* - * There's very little reason to use this, you should really - * have a struct block_device just about everywhere and use - * bdevname() instead. - */ -const char *__bdevname(dev_t dev, char *buffer) -{ - scnprintf(buffer, BDEVNAME_SIZE, "unknown-block(%u,%u)", - MAJOR(dev), MINOR(dev)); - return buffer; -} - -EXPORT_SYMBOL(__bdevname); - -#ifndef DDE_LINUX -static struct parsed_partitions * -check_partition(struct gendisk *hd, struct block_device *bdev) -{ - struct parsed_partitions *state; - int i, res, err; - - state = kmalloc(sizeof(struct parsed_partitions), GFP_KERNEL); - if (!state) - return NULL; - - disk_name(hd, 0, state->name); - printk(KERN_INFO " %s:", state->name); - if (isdigit(state->name[strlen(state->name)-1])) - sprintf(state->name, "p"); - - state->limit = disk_max_parts(hd); - i = res = err = 0; - while (!res && check_part[i]) { - memset(&state->parts, 0, sizeof(state->parts)); - res = check_part[i++](state, bdev); - if (res < 0) { - /* We have hit an I/O error which we don't report now. - * But record it, and let the others do their job. - */ - err = res; - res = 0; - } - - } - if (res > 0) - return state; - if (err) - /* The partition is unrecognized. So report I/O errors if there were any */ - res = err; - if (!res) - printk(" unknown partition table\n"); - else if (warn_no_part) - printk(" unable to read partition table\n"); - kfree(state); - return ERR_PTR(res); -} -#endif - -static ssize_t part_partition_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct hd_struct *p = dev_to_part(dev); - - return sprintf(buf, "%d\n", p->partno); -} - -static ssize_t part_start_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct hd_struct *p = dev_to_part(dev); - - return sprintf(buf, "%llu\n",(unsigned long long)p->start_sect); -} - -ssize_t part_size_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct hd_struct *p = dev_to_part(dev); - return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects); -} - -ssize_t part_stat_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct hd_struct *p = dev_to_part(dev); - int cpu; - - cpu = part_stat_lock(); - part_round_stats(cpu, p); - part_stat_unlock(); - return sprintf(buf, - "%8lu %8lu %8llu %8u " - "%8lu %8lu %8llu %8u " - "%8u %8u %8u" - "\n", - part_stat_read(p, ios[READ]), - part_stat_read(p, merges[READ]), - (unsigned long long)part_stat_read(p, sectors[READ]), - jiffies_to_msecs(part_stat_read(p, ticks[READ])), - part_stat_read(p, ios[WRITE]), - part_stat_read(p, merges[WRITE]), - (unsigned long long)part_stat_read(p, sectors[WRITE]), - jiffies_to_msecs(part_stat_read(p, ticks[WRITE])), - p->in_flight, - jiffies_to_msecs(part_stat_read(p, io_ticks)), - jiffies_to_msecs(part_stat_read(p, time_in_queue))); -} - -#ifdef CONFIG_FAIL_MAKE_REQUEST -ssize_t part_fail_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct hd_struct *p = dev_to_part(dev); - - return sprintf(buf, "%d\n", p->make_it_fail); -} - -ssize_t part_fail_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hd_struct *p = dev_to_part(dev); - int i; - - if (count > 0 && sscanf(buf, "%d", &i) > 0) - p->make_it_fail = (i == 0) ? 0 : 1; - - return count; -} -#endif - -static DEVICE_ATTR(partition, S_IRUGO, part_partition_show, NULL); -static DEVICE_ATTR(start, S_IRUGO, part_start_show, NULL); -static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL); -static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL); -#ifdef CONFIG_FAIL_MAKE_REQUEST -static struct device_attribute dev_attr_fail = - __ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store); -#endif - -static struct attribute *part_attrs[] = { - &dev_attr_partition.attr, - &dev_attr_start.attr, - &dev_attr_size.attr, - &dev_attr_stat.attr, -#ifdef CONFIG_FAIL_MAKE_REQUEST - &dev_attr_fail.attr, -#endif - NULL -}; - -static struct attribute_group part_attr_group = { - .attrs = part_attrs, -}; - -static struct attribute_group *part_attr_groups[] = { - &part_attr_group, - NULL -}; - -static void part_release(struct device *dev) -{ - struct hd_struct *p = dev_to_part(dev); - free_part_stats(p); - kfree(p); -} - -struct device_type part_type = { - .name = "partition", - .groups = part_attr_groups, - .release = part_release, -}; - -static void delete_partition_rcu_cb(struct rcu_head *head) -{ - struct hd_struct *part = container_of(head, struct hd_struct, rcu_head); - - part->start_sect = 0; - part->nr_sects = 0; - part_stat_set_all(part, 0); - put_device(part_to_dev(part)); -} - -void delete_partition(struct gendisk *disk, int partno) -{ - struct disk_part_tbl *ptbl = disk->part_tbl; - struct hd_struct *part; - - if (partno >= ptbl->len) - return; - - part = ptbl->part[partno]; - if (!part) - return; - - blk_free_devt(part_devt(part)); - rcu_assign_pointer(ptbl->part[partno], NULL); - rcu_assign_pointer(ptbl->last_lookup, NULL); - kobject_put(part->holder_dir); - device_del(part_to_dev(part)); - -#ifndef DDE_LINUX - call_rcu(&part->rcu_head, delete_partition_rcu_cb); -#else - delete_partition_rcu_cb(&part->rcu_head); -#endif -} - -static ssize_t whole_disk_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return 0; -} -static DEVICE_ATTR(whole_disk, S_IRUSR | S_IRGRP | S_IROTH, - whole_disk_show, NULL); - -struct hd_struct *add_partition(struct gendisk *disk, int partno, - sector_t start, sector_t len, int flags) -{ - struct hd_struct *p; - dev_t devt = MKDEV(0, 0); - struct device *ddev = disk_to_dev(disk); - struct device *pdev; - struct disk_part_tbl *ptbl; - const char *dname; - int err; - - err = disk_expand_part_tbl(disk, partno); - if (err) - return ERR_PTR(err); - ptbl = disk->part_tbl; - - if (ptbl->part[partno]) - return ERR_PTR(-EBUSY); - - p = kzalloc(sizeof(*p), GFP_KERNEL); - if (!p) - return ERR_PTR(-EBUSY); - - if (!init_part_stats(p)) { - err = -ENOMEM; - goto out_free; - } - pdev = part_to_dev(p); - - p->start_sect = start; - p->nr_sects = len; - p->partno = partno; - p->policy = get_disk_ro(disk); - - dname = dev_name(ddev); - if (isdigit(dname[strlen(dname) - 1])) - dev_set_name(pdev, "%sp%d", dname, partno); - else - dev_set_name(pdev, "%s%d", dname, partno); - - device_initialize(pdev); - pdev->class = &block_class; - pdev->type = &part_type; - pdev->parent = ddev; - - err = blk_alloc_devt(p, &devt); - if (err) - goto out_free_stats; - pdev->devt = devt; - - /* delay uevent until 'holders' subdir is created */ - pdev->uevent_suppress = 1; - err = device_add(pdev); - if (err) - goto out_put; - - err = -ENOMEM; - p->holder_dir = kobject_create_and_add("holders", &pdev->kobj); - if (!p->holder_dir) - goto out_del; - - pdev->uevent_suppress = 0; - if (flags & ADDPART_FLAG_WHOLEDISK) { - err = device_create_file(pdev, &dev_attr_whole_disk); - if (err) - goto out_del; - } - - /* everything is up and running, commence */ - INIT_RCU_HEAD(&p->rcu_head); - rcu_assign_pointer(ptbl->part[partno], p); - - /* suppress uevent if the disk supresses it */ - if (!ddev->uevent_suppress) - kobject_uevent(&pdev->kobj, KOBJ_ADD); - - return p; - -out_free_stats: - free_part_stats(p); -out_free: - kfree(p); - return ERR_PTR(err); -out_del: - kobject_put(p->holder_dir); - device_del(pdev); -out_put: - put_device(pdev); - blk_free_devt(devt); - return ERR_PTR(err); -} - -/* Not exported, helper to add_disk(). */ -void register_disk(struct gendisk *disk) -{ - struct device *ddev = disk_to_dev(disk); - struct block_device *bdev; - struct disk_part_iter piter; - struct hd_struct *part; - int err; - - ddev->parent = disk->driverfs_dev; - - dev_set_name(ddev, disk->disk_name); - - /* delay uevents, until we scanned partition table */ - ddev->uevent_suppress = 1; - - if (device_add(ddev)) - return; -#ifndef CONFIG_SYSFS_DEPRECATED - err = sysfs_create_link(block_depr, &ddev->kobj, - kobject_name(&ddev->kobj)); - if (err) { - device_del(ddev); - return; - } -#endif - disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj); - disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj); - - /* No minors to use for partitions */ - if (!disk_partitionable(disk)) - goto exit; - - /* No such device (e.g., media were just removed) */ - if (!get_capacity(disk)) - goto exit; - - bdev = bdget_disk(disk, 0); - if (!bdev) - goto exit; - - bdev->bd_invalidated = 1; - err = blkdev_get(bdev, FMODE_READ); - if (err < 0) - goto exit; - blkdev_put(bdev, FMODE_READ); - -exit: - /* announce disk after possible partitions are created */ - ddev->uevent_suppress = 0; - kobject_uevent(&ddev->kobj, KOBJ_ADD); - - /* announce possible partitions */ - disk_part_iter_init(&piter, disk, 0); - while ((part = disk_part_iter_next(&piter))) - kobject_uevent(&part_to_dev(part)->kobj, KOBJ_ADD); - disk_part_iter_exit(&piter); -} - -int rescan_partitions(struct gendisk *disk, struct block_device *bdev) -{ -#ifndef DDE_LINUX - struct disk_part_iter piter; - struct hd_struct *part; - struct parsed_partitions *state; - int p, highest, res; - - if (bdev->bd_part_count) - return -EBUSY; - res = invalidate_partition(disk, 0); - if (res) - return res; - - disk_part_iter_init(&piter, disk, DISK_PITER_INCL_EMPTY); - while ((part = disk_part_iter_next(&piter))) - delete_partition(disk, part->partno); - disk_part_iter_exit(&piter); - - if (disk->fops->revalidate_disk) - disk->fops->revalidate_disk(disk); - check_disk_size_change(disk, bdev); - bdev->bd_invalidated = 0; - if (!get_capacity(disk) || !(state = check_partition(disk, bdev))) - return 0; - if (IS_ERR(state)) /* I/O error reading the partition table */ - return -EIO; - - /* tell userspace that the media / partition table may have changed */ - kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE); - - /* Detect the highest partition number and preallocate - * disk->part_tbl. This is an optimization and not strictly - * necessary. - */ - for (p = 1, highest = 0; p < state->limit; p++) - if (state->parts[p].size) - highest = p; - - disk_expand_part_tbl(disk, highest); - - /* add partitions */ - for (p = 1; p < state->limit; p++) { - sector_t size = state->parts[p].size; - sector_t from = state->parts[p].from; - if (!size) - continue; - if (from >= get_capacity(disk)) { - printk(KERN_WARNING - "%s: p%d ignored, start %llu is behind the end of the disk\n", - disk->disk_name, p, (unsigned long long) from); - continue; - } - if (from + size > get_capacity(disk)) { - /* - * we can not ignore partitions of broken tables - * created by for example camera firmware, but we - * limit them to the end of the disk to avoid - * creating invalid block devices - */ - printk(KERN_WARNING - "%s: p%d size %llu limited to end of disk\n", - disk->disk_name, p, (unsigned long long) size); - size = get_capacity(disk) - from; - } - part = add_partition(disk, p, from, size, - state->parts[p].flags); - if (IS_ERR(part)) { - printk(KERN_ERR " %s: p%d could not be added: %ld\n", - disk->disk_name, p, -PTR_ERR(part)); - continue; - } -#ifdef CONFIG_BLK_DEV_MD - if (state->parts[p].flags & ADDPART_FLAG_RAID) - md_autodetect_dev(part_to_dev(part)->devt); -#endif - } - kfree(state); -#endif /* DDE_LINUX */ - return 0; -} - -unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p) -{ - struct address_space *mapping = bdev->bd_inode->i_mapping; - struct page *page; - - page = read_mapping_page(mapping, (pgoff_t)(n >> (PAGE_CACHE_SHIFT-9)), - NULL); - if (!IS_ERR(page)) { - if (PageError(page)) - goto fail; - p->v = page; - return (unsigned char *)page_address(page) + ((n & ((1 << (PAGE_CACHE_SHIFT - 9)) - 1)) << 9); -fail: - page_cache_release(page); - } - p->v = NULL; - return NULL; -} - -EXPORT_SYMBOL(read_dev_sector); - -void del_gendisk(struct gendisk *disk) -{ - struct disk_part_iter piter; - struct hd_struct *part; - - /* invalidate stuff */ - disk_part_iter_init(&piter, disk, - DISK_PITER_INCL_EMPTY | DISK_PITER_REVERSE); - while ((part = disk_part_iter_next(&piter))) { - invalidate_partition(disk, part->partno); - delete_partition(disk, part->partno); - } - disk_part_iter_exit(&piter); - - invalidate_partition(disk, 0); - blk_free_devt(disk_to_dev(disk)->devt); - set_capacity(disk, 0); - disk->flags &= ~GENHD_FL_UP; - unlink_gendisk(disk); - part_stat_set_all(&disk->part0, 0); - disk->part0.stamp = 0; - - kobject_put(disk->part0.holder_dir); - kobject_put(disk->slave_dir); - disk->driverfs_dev = NULL; -#ifndef CONFIG_SYSFS_DEPRECATED - sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk))); -#endif - device_del(disk_to_dev(disk)); -} diff --git a/windhoek/partitions/check.h b/windhoek/partitions/check.h deleted file mode 100644 index 98dbe1a8..00000000 --- a/windhoek/partitions/check.h +++ /dev/null @@ -1,30 +0,0 @@ -#include <linux/pagemap.h> -#include <linux/blkdev.h> - -/* - * add_gd_partition adds a partitions details to the devices partition - * description. - */ -struct parsed_partitions { - char name[BDEVNAME_SIZE]; - struct { - sector_t from; - sector_t size; - int flags; - } parts[DISK_MAX_PARTS]; - int next; - int limit; -}; - -static inline void -put_partition(struct parsed_partitions *p, int n, sector_t from, sector_t size) -{ - if (n < p->limit) { - p->parts[n].from = from; - p->parts[n].size = size; - printk(" %s%d", p->name, n); - } -} - -extern int warn_no_part; - diff --git a/windhoek/partitions/efi.c b/windhoek/partitions/efi.c deleted file mode 100644 index 038a6022..00000000 --- a/windhoek/partitions/efi.c +++ /dev/null @@ -1,631 +0,0 @@ -/************************************************************ - * EFI GUID Partition Table handling - * Per Intel EFI Specification v1.02 - * http://developer.intel.com/technology/efi/efi.htm - * efi.[ch] by Matt Domsch <Matt_Domsch@dell.com> - * Copyright 2000,2001,2002,2004 Dell 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 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * TODO: - * - * Changelog: - * Mon Nov 09 2004 Matt Domsch <Matt_Domsch@dell.com> - * - test for valid PMBR and valid PGPT before ever reading - * AGPT, allow override with 'gpt' kernel command line option. - * - check for first/last_usable_lba outside of size of disk - * - * Tue Mar 26 2002 Matt Domsch <Matt_Domsch@dell.com> - * - Ported to 2.5.7-pre1 and 2.5.7-dj2 - * - Applied patch to avoid fault in alternate header handling - * - cleaned up find_valid_gpt - * - On-disk structure and copy in memory is *always* LE now - - * swab fields as needed - * - remove print_gpt_header() - * - only use first max_p partition entries, to keep the kernel minor number - * and partition numbers tied. - * - * Mon Feb 04 2002 Matt Domsch <Matt_Domsch@dell.com> - * - Removed __PRIPTR_PREFIX - not being used - * - * Mon Jan 14 2002 Matt Domsch <Matt_Domsch@dell.com> - * - Ported to 2.5.2-pre11 + library crc32 patch Linus applied - * - * Thu Dec 6 2001 Matt Domsch <Matt_Domsch@dell.com> - * - Added compare_gpts(). - * - moved le_efi_guid_to_cpus() back into this file. GPT is the only - * thing that keeps EFI GUIDs on disk. - * - Changed gpt structure names and members to be simpler and more Linux-like. - * - * Wed Oct 17 2001 Matt Domsch <Matt_Domsch@dell.com> - * - Removed CONFIG_DEVFS_VOLUMES_UUID code entirely per Martin Wilck - * - * Wed Oct 10 2001 Matt Domsch <Matt_Domsch@dell.com> - * - Changed function comments to DocBook style per Andreas Dilger suggestion. - * - * Mon Oct 08 2001 Matt Domsch <Matt_Domsch@dell.com> - * - Change read_lba() to use the page cache per Al Viro's work. - * - print u64s properly on all architectures - * - fixed debug_printk(), now Dprintk() - * - * Mon Oct 01 2001 Matt Domsch <Matt_Domsch@dell.com> - * - Style cleanups - * - made most functions static - * - Endianness addition - * - remove test for second alternate header, as it's not per spec, - * and is unnecessary. There's now a method to read/write the last - * sector of an odd-sized disk from user space. No tools have ever - * been released which used this code, so it's effectively dead. - * - Per Asit Mallick of Intel, added a test for a valid PMBR. - * - Added kernel command line option 'gpt' to override valid PMBR test. - * - * Wed Jun 6 2001 Martin Wilck <Martin.Wilck@Fujitsu-Siemens.com> - * - added devfs volume UUID support (/dev/volumes/uuids) for - * mounting file systems by the partition GUID. - * - * Tue Dec 5 2000 Matt Domsch <Matt_Domsch@dell.com> - * - Moved crc32() to linux/lib, added efi_crc32(). - * - * Thu Nov 30 2000 Matt Domsch <Matt_Domsch@dell.com> - * - Replaced Intel's CRC32 function with an equivalent - * non-license-restricted version. - * - * Wed Oct 25 2000 Matt Domsch <Matt_Domsch@dell.com> - * - Fixed the last_lba() call to return the proper last block - * - * Thu Oct 12 2000 Matt Domsch <Matt_Domsch@dell.com> - * - Thanks to Andries Brouwer for his debugging assistance. - * - Code works, detects all the partitions. - * - ************************************************************/ -#include <linux/crc32.h> -#include "check.h" -#include "efi.h" - -/* This allows a kernel command line option 'gpt' to override - * the test for invalid PMBR. Not __initdata because reloading - * the partition tables happens after init too. - */ -static int force_gpt; -static int __init -force_gpt_fn(char *str) -{ - force_gpt = 1; - return 1; -} -__setup("gpt", force_gpt_fn); - - -/** - * efi_crc32() - EFI version of crc32 function - * @buf: buffer to calculate crc32 of - * @len - length of buf - * - * Description: Returns EFI-style CRC32 value for @buf - * - * This function uses the little endian Ethernet polynomial - * but seeds the function with ~0, and xor's with ~0 at the end. - * Note, the EFI Specification, v1.02, has a reference to - * Dr. Dobbs Journal, May 1994 (actually it's in May 1992). - */ -static inline u32 -efi_crc32(const void *buf, unsigned long len) -{ - return (crc32(~0L, buf, len) ^ ~0L); -} - -/** - * last_lba(): return number of last logical block of device - * @bdev: block device - * - * Description: Returns last LBA value on success, 0 on error. - * This is stored (by sd and ide-geometry) in - * the part[0] entry for this disk, and is the number of - * physical sectors available on the disk. - */ -static u64 -last_lba(struct block_device *bdev) -{ - if (!bdev || !bdev->bd_inode) - return 0; - return (bdev->bd_inode->i_size >> 9) - 1ULL; -} - -static inline int -pmbr_part_valid(struct partition *part) -{ - if (part->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT && - le32_to_cpu(part->start_sect) == 1UL) - return 1; - return 0; -} - -/** - * is_pmbr_valid(): test Protective MBR for validity - * @mbr: pointer to a legacy mbr structure - * - * Description: Returns 1 if PMBR is valid, 0 otherwise. - * Validity depends on two things: - * 1) MSDOS signature is in the last two bytes of the MBR - * 2) One partition of type 0xEE is found - */ -static int -is_pmbr_valid(legacy_mbr *mbr) -{ - int i; - if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE) - return 0; - for (i = 0; i < 4; i++) - if (pmbr_part_valid(&mbr->partition_record[i])) - return 1; - return 0; -} - -/** - * read_lba(): Read bytes from disk, starting at given LBA - * @bdev - * @lba - * @buffer - * @size_t - * - * Description: Reads @count bytes from @bdev into @buffer. - * Returns number of bytes read on success, 0 on error. - */ -static size_t -read_lba(struct block_device *bdev, u64 lba, u8 * buffer, size_t count) -{ - size_t totalreadcount = 0; - - if (!bdev || !buffer || lba > last_lba(bdev)) - return 0; - - while (count) { - int copied = 512; - Sector sect; - unsigned char *data = read_dev_sector(bdev, lba++, §); - if (!data) - break; - if (copied > count) - copied = count; - memcpy(buffer, data, copied); - put_dev_sector(sect); - buffer += copied; - totalreadcount +=copied; - count -= copied; - } - return totalreadcount; -} - -/** - * alloc_read_gpt_entries(): reads partition entries from disk - * @bdev - * @gpt - GPT header - * - * Description: Returns ptes on success, NULL on error. - * Allocates space for PTEs based on information found in @gpt. - * Notes: remember to free pte when you're done! - */ -static gpt_entry * -alloc_read_gpt_entries(struct block_device *bdev, gpt_header *gpt) -{ - size_t count; - gpt_entry *pte; - if (!bdev || !gpt) - return NULL; - - count = le32_to_cpu(gpt->num_partition_entries) * - le32_to_cpu(gpt->sizeof_partition_entry); - if (!count) - return NULL; - pte = kzalloc(count, GFP_KERNEL); - if (!pte) - return NULL; - - if (read_lba(bdev, le64_to_cpu(gpt->partition_entry_lba), - (u8 *) pte, - count) < count) { - kfree(pte); - pte=NULL; - return NULL; - } - return pte; -} - -/** - * alloc_read_gpt_header(): Allocates GPT header, reads into it from disk - * @bdev - * @lba is the Logical Block Address of the partition table - * - * Description: returns GPT header on success, NULL on error. Allocates - * and fills a GPT header starting at @ from @bdev. - * Note: remember to free gpt when finished with it. - */ -static gpt_header * -alloc_read_gpt_header(struct block_device *bdev, u64 lba) -{ - gpt_header *gpt; - if (!bdev) - return NULL; - - gpt = kzalloc(sizeof (gpt_header), GFP_KERNEL); - if (!gpt) - return NULL; - - if (read_lba(bdev, lba, (u8 *) gpt, - sizeof (gpt_header)) < sizeof (gpt_header)) { - kfree(gpt); - gpt=NULL; - return NULL; - } - - return gpt; -} - -/** - * is_gpt_valid() - tests one GPT header and PTEs for validity - * @bdev - * @lba is the logical block address of the GPT header to test - * @gpt is a GPT header ptr, filled on return. - * @ptes is a PTEs ptr, filled on return. - * - * Description: returns 1 if valid, 0 on error. - * If valid, returns pointers to newly allocated GPT header and PTEs. - */ -static int -is_gpt_valid(struct block_device *bdev, u64 lba, - gpt_header **gpt, gpt_entry **ptes) -{ - u32 crc, origcrc; - u64 lastlba; - - if (!bdev || !gpt || !ptes) - return 0; - if (!(*gpt = alloc_read_gpt_header(bdev, lba))) - return 0; - - /* Check the GUID Partition Table signature */ - if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) { - pr_debug("GUID Partition Table Header signature is wrong:" - "%lld != %lld\n", - (unsigned long long)le64_to_cpu((*gpt)->signature), - (unsigned long long)GPT_HEADER_SIGNATURE); - goto fail; - } - - /* Check the GUID Partition Table CRC */ - origcrc = le32_to_cpu((*gpt)->header_crc32); - (*gpt)->header_crc32 = 0; - crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size)); - - if (crc != origcrc) { - pr_debug("GUID Partition Table Header CRC is wrong: %x != %x\n", - crc, origcrc); - goto fail; - } - (*gpt)->header_crc32 = cpu_to_le32(origcrc); - - /* Check that the my_lba entry points to the LBA that contains - * the GUID Partition Table */ - if (le64_to_cpu((*gpt)->my_lba) != lba) { - pr_debug("GPT my_lba incorrect: %lld != %lld\n", - (unsigned long long)le64_to_cpu((*gpt)->my_lba), - (unsigned long long)lba); - goto fail; - } - - /* Check the first_usable_lba and last_usable_lba are - * within the disk. - */ - lastlba = last_lba(bdev); - if (le64_to_cpu((*gpt)->first_usable_lba) > lastlba) { - pr_debug("GPT: first_usable_lba incorrect: %lld > %lld\n", - (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba), - (unsigned long long)lastlba); - goto fail; - } - if (le64_to_cpu((*gpt)->last_usable_lba) > lastlba) { - pr_debug("GPT: last_usable_lba incorrect: %lld > %lld\n", - (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba), - (unsigned long long)lastlba); - goto fail; - } - - if (!(*ptes = alloc_read_gpt_entries(bdev, *gpt))) - goto fail; - - /* Check the GUID Partition Entry Array CRC */ - crc = efi_crc32((const unsigned char *) (*ptes), - le32_to_cpu((*gpt)->num_partition_entries) * - le32_to_cpu((*gpt)->sizeof_partition_entry)); - - if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) { - pr_debug("GUID Partitition Entry Array CRC check failed.\n"); - goto fail_ptes; - } - - /* We're done, all's well */ - return 1; - - fail_ptes: - kfree(*ptes); - *ptes = NULL; - fail: - kfree(*gpt); - *gpt = NULL; - return 0; -} - -/** - * is_pte_valid() - tests one PTE for validity - * @pte is the pte to check - * @lastlba is last lba of the disk - * - * Description: returns 1 if valid, 0 on error. - */ -static inline int -is_pte_valid(const gpt_entry *pte, const u64 lastlba) -{ - if ((!efi_guidcmp(pte->partition_type_guid, NULL_GUID)) || - le64_to_cpu(pte->starting_lba) > lastlba || - le64_to_cpu(pte->ending_lba) > lastlba) - return 0; - return 1; -} - -/** - * compare_gpts() - Search disk for valid GPT headers and PTEs - * @pgpt is the primary GPT header - * @agpt is the alternate GPT header - * @lastlba is the last LBA number - * Description: Returns nothing. Sanity checks pgpt and agpt fields - * and prints warnings on discrepancies. - * - */ -static void -compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba) -{ - int error_found = 0; - if (!pgpt || !agpt) - return; - if (le64_to_cpu(pgpt->my_lba) != le64_to_cpu(agpt->alternate_lba)) { - printk(KERN_WARNING - "GPT:Primary header LBA != Alt. header alternate_lba\n"); - printk(KERN_WARNING "GPT:%lld != %lld\n", - (unsigned long long)le64_to_cpu(pgpt->my_lba), - (unsigned long long)le64_to_cpu(agpt->alternate_lba)); - error_found++; - } - if (le64_to_cpu(pgpt->alternate_lba) != le64_to_cpu(agpt->my_lba)) { - printk(KERN_WARNING - "GPT:Primary header alternate_lba != Alt. header my_lba\n"); - printk(KERN_WARNING "GPT:%lld != %lld\n", - (unsigned long long)le64_to_cpu(pgpt->alternate_lba), - (unsigned long long)le64_to_cpu(agpt->my_lba)); - error_found++; - } - if (le64_to_cpu(pgpt->first_usable_lba) != - le64_to_cpu(agpt->first_usable_lba)) { - printk(KERN_WARNING "GPT:first_usable_lbas don't match.\n"); - printk(KERN_WARNING "GPT:%lld != %lld\n", - (unsigned long long)le64_to_cpu(pgpt->first_usable_lba), - (unsigned long long)le64_to_cpu(agpt->first_usable_lba)); - error_found++; - } - if (le64_to_cpu(pgpt->last_usable_lba) != - le64_to_cpu(agpt->last_usable_lba)) { - printk(KERN_WARNING "GPT:last_usable_lbas don't match.\n"); - printk(KERN_WARNING "GPT:%lld != %lld\n", - (unsigned long long)le64_to_cpu(pgpt->last_usable_lba), - (unsigned long long)le64_to_cpu(agpt->last_usable_lba)); - error_found++; - } - if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) { - printk(KERN_WARNING "GPT:disk_guids don't match.\n"); - error_found++; - } - if (le32_to_cpu(pgpt->num_partition_entries) != - le32_to_cpu(agpt->num_partition_entries)) { - printk(KERN_WARNING "GPT:num_partition_entries don't match: " - "0x%x != 0x%x\n", - le32_to_cpu(pgpt->num_partition_entries), - le32_to_cpu(agpt->num_partition_entries)); - error_found++; - } - if (le32_to_cpu(pgpt->sizeof_partition_entry) != - le32_to_cpu(agpt->sizeof_partition_entry)) { - printk(KERN_WARNING - "GPT:sizeof_partition_entry values don't match: " - "0x%x != 0x%x\n", - le32_to_cpu(pgpt->sizeof_partition_entry), - le32_to_cpu(agpt->sizeof_partition_entry)); - error_found++; - } - if (le32_to_cpu(pgpt->partition_entry_array_crc32) != - le32_to_cpu(agpt->partition_entry_array_crc32)) { - printk(KERN_WARNING - "GPT:partition_entry_array_crc32 values don't match: " - "0x%x != 0x%x\n", - le32_to_cpu(pgpt->partition_entry_array_crc32), - le32_to_cpu(agpt->partition_entry_array_crc32)); - error_found++; - } - if (le64_to_cpu(pgpt->alternate_lba) != lastlba) { - printk(KERN_WARNING - "GPT:Primary header thinks Alt. header is not at the end of the disk.\n"); - printk(KERN_WARNING "GPT:%lld != %lld\n", - (unsigned long long)le64_to_cpu(pgpt->alternate_lba), - (unsigned long long)lastlba); - error_found++; - } - - if (le64_to_cpu(agpt->my_lba) != lastlba) { - printk(KERN_WARNING - "GPT:Alternate GPT header not at the end of the disk.\n"); - printk(KERN_WARNING "GPT:%lld != %lld\n", - (unsigned long long)le64_to_cpu(agpt->my_lba), - (unsigned long long)lastlba); - error_found++; - } - - if (error_found) - printk(KERN_WARNING - "GPT: Use GNU Parted to correct GPT errors.\n"); - return; -} - -/** - * find_valid_gpt() - Search disk for valid GPT headers and PTEs - * @bdev - * @gpt is a GPT header ptr, filled on return. - * @ptes is a PTEs ptr, filled on return. - * Description: Returns 1 if valid, 0 on error. - * If valid, returns pointers to newly allocated GPT header and PTEs. - * Validity depends on PMBR being valid (or being overridden by the - * 'gpt' kernel command line option) and finding either the Primary - * GPT header and PTEs valid, or the Alternate GPT header and PTEs - * valid. If the Primary GPT header is not valid, the Alternate GPT header - * is not checked unless the 'gpt' kernel command line option is passed. - * This protects against devices which misreport their size, and forces - * the user to decide to use the Alternate GPT. - */ -static int -find_valid_gpt(struct block_device *bdev, gpt_header **gpt, gpt_entry **ptes) -{ - int good_pgpt = 0, good_agpt = 0, good_pmbr = 0; - gpt_header *pgpt = NULL, *agpt = NULL; - gpt_entry *pptes = NULL, *aptes = NULL; - legacy_mbr *legacymbr; - u64 lastlba; - if (!bdev || !gpt || !ptes) - return 0; - - lastlba = last_lba(bdev); - if (!force_gpt) { - /* This will be added to the EFI Spec. per Intel after v1.02. */ - legacymbr = kzalloc(sizeof (*legacymbr), GFP_KERNEL); - if (legacymbr) { - read_lba(bdev, 0, (u8 *) legacymbr, - sizeof (*legacymbr)); - good_pmbr = is_pmbr_valid(legacymbr); - kfree(legacymbr); - } - if (!good_pmbr) - goto fail; - } - - good_pgpt = is_gpt_valid(bdev, GPT_PRIMARY_PARTITION_TABLE_LBA, - &pgpt, &pptes); - if (good_pgpt) - good_agpt = is_gpt_valid(bdev, - le64_to_cpu(pgpt->alternate_lba), - &agpt, &aptes); - if (!good_agpt && force_gpt) - good_agpt = is_gpt_valid(bdev, lastlba, - &agpt, &aptes); - - /* The obviously unsuccessful case */ - if (!good_pgpt && !good_agpt) - goto fail; - - compare_gpts(pgpt, agpt, lastlba); - - /* The good cases */ - if (good_pgpt) { - *gpt = pgpt; - *ptes = pptes; - kfree(agpt); - kfree(aptes); - if (!good_agpt) { - printk(KERN_WARNING - "Alternate GPT is invalid, " - "using primary GPT.\n"); - } - return 1; - } - else if (good_agpt) { - *gpt = agpt; - *ptes = aptes; - kfree(pgpt); - kfree(pptes); - printk(KERN_WARNING - "Primary GPT is invalid, using alternate GPT.\n"); - return 1; - } - - fail: - kfree(pgpt); - kfree(agpt); - kfree(pptes); - kfree(aptes); - *gpt = NULL; - *ptes = NULL; - return 0; -} - -/** - * efi_partition(struct parsed_partitions *state, struct block_device *bdev) - * @state - * @bdev - * - * Description: called from check.c, if the disk contains GPT - * partitions, sets up partition entries in the kernel. - * - * If the first block on the disk is a legacy MBR, - * it will get handled by msdos_partition(). - * If it's a Protective MBR, we'll handle it here. - * - * We do not create a Linux partition for GPT, but - * only for the actual data partitions. - * Returns: - * -1 if unable to read the partition table - * 0 if this isn't our partition table - * 1 if successful - * - */ -int -efi_partition(struct parsed_partitions *state, struct block_device *bdev) -{ - gpt_header *gpt = NULL; - gpt_entry *ptes = NULL; - u32 i; - - if (!find_valid_gpt(bdev, &gpt, &ptes) || !gpt || !ptes) { - kfree(gpt); - kfree(ptes); - return 0; - } - - pr_debug("GUID Partition Table is valid! Yea!\n"); - - for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { - if (!is_pte_valid(&ptes[i], last_lba(bdev))) - continue; - - put_partition(state, i+1, le64_to_cpu(ptes[i].starting_lba), - (le64_to_cpu(ptes[i].ending_lba) - - le64_to_cpu(ptes[i].starting_lba) + - 1ULL)); - - /* If this is a RAID volume, tell md */ - if (!efi_guidcmp(ptes[i].partition_type_guid, - PARTITION_LINUX_RAID_GUID)) - state->parts[i+1].flags = 1; - } - kfree(ptes); - kfree(gpt); - printk("\n"); - return 1; -} diff --git a/windhoek/partitions/efi.h b/windhoek/partitions/efi.h deleted file mode 100644 index 2cc89d04..00000000 --- a/windhoek/partitions/efi.h +++ /dev/null @@ -1,130 +0,0 @@ -/************************************************************ - * EFI GUID Partition Table - * Per Intel EFI Specification v1.02 - * http://developer.intel.com/technology/efi/efi.htm - * - * By Matt Domsch <Matt_Domsch@dell.com> Fri Sep 22 22:15:56 CDT 2000 - * Copyright 2000,2001 Dell 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 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - ************************************************************/ - -#ifndef FS_PART_EFI_H_INCLUDED -#define FS_PART_EFI_H_INCLUDED - -#include <linux/types.h> -#include <linux/fs.h> -#include <linux/genhd.h> -#include <linux/kernel.h> -#include <linux/major.h> -#include <linux/string.h> -#include <linux/efi.h> - -#define MSDOS_MBR_SIGNATURE 0xaa55 -#define EFI_PMBR_OSTYPE_EFI 0xEF -#define EFI_PMBR_OSTYPE_EFI_GPT 0xEE - -#define GPT_BLOCK_SIZE 512 -#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL -#define GPT_HEADER_REVISION_V1 0x00010000 -#define GPT_PRIMARY_PARTITION_TABLE_LBA 1 - -#define PARTITION_SYSTEM_GUID \ - EFI_GUID( 0xC12A7328, 0xF81F, 0x11d2, \ - 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B) -#define LEGACY_MBR_PARTITION_GUID \ - EFI_GUID( 0x024DEE41, 0x33E7, 0x11d3, \ - 0x9D, 0x69, 0x00, 0x08, 0xC7, 0x81, 0xF3, 0x9F) -#define PARTITION_MSFT_RESERVED_GUID \ - EFI_GUID( 0xE3C9E316, 0x0B5C, 0x4DB8, \ - 0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE) -#define PARTITION_BASIC_DATA_GUID \ - EFI_GUID( 0xEBD0A0A2, 0xB9E5, 0x4433, \ - 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7) -#define PARTITION_LINUX_RAID_GUID \ - EFI_GUID( 0xa19d880f, 0x05fc, 0x4d3b, \ - 0xa0, 0x06, 0x74, 0x3f, 0x0f, 0x84, 0x91, 0x1e) -#define PARTITION_LINUX_SWAP_GUID \ - EFI_GUID( 0x0657fd6d, 0xa4ab, 0x43c4, \ - 0x84, 0xe5, 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f) -#define PARTITION_LINUX_LVM_GUID \ - EFI_GUID( 0xe6d6d379, 0xf507, 0x44c2, \ - 0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28) - -typedef struct _gpt_header { - __le64 signature; - __le32 revision; - __le32 header_size; - __le32 header_crc32; - __le32 reserved1; - __le64 my_lba; - __le64 alternate_lba; - __le64 first_usable_lba; - __le64 last_usable_lba; - efi_guid_t disk_guid; - __le64 partition_entry_lba; - __le32 num_partition_entries; - __le32 sizeof_partition_entry; - __le32 partition_entry_array_crc32; - u8 reserved2[GPT_BLOCK_SIZE - 92]; -} __attribute__ ((packed)) gpt_header; - -typedef struct _gpt_entry_attributes { - u64 required_to_function:1; - u64 reserved:47; - u64 type_guid_specific:16; -} __attribute__ ((packed)) gpt_entry_attributes; - -typedef struct _gpt_entry { - efi_guid_t partition_type_guid; - efi_guid_t unique_partition_guid; - __le64 starting_lba; - __le64 ending_lba; - gpt_entry_attributes attributes; - efi_char16_t partition_name[72 / sizeof (efi_char16_t)]; -} __attribute__ ((packed)) gpt_entry; - -typedef struct _legacy_mbr { - u8 boot_code[440]; - __le32 unique_mbr_signature; - __le16 unknown; - struct partition partition_record[4]; - __le16 signature; -} __attribute__ ((packed)) legacy_mbr; - -/* Functions */ -extern int efi_partition(struct parsed_partitions *state, struct block_device *bdev); - -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * -------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/windhoek/partitions/ibm.c b/windhoek/partitions/ibm.c deleted file mode 100644 index 1e064c4a..00000000 --- a/windhoek/partitions/ibm.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * File...........: linux/fs/partitions/ibm.c - * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> - * Volker Sameske <sameske@de.ibm.com> - * Bugreports.to..: <Linux390@de.ibm.com> - * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 - */ - -#include <linux/buffer_head.h> -#include <linux/hdreg.h> -#include <linux/slab.h> -#include <asm/dasd.h> -#include <asm/ebcdic.h> -#include <asm/uaccess.h> -#include <asm/vtoc.h> - -#include "check.h" -#include "ibm.h" - -/* - * compute the block number from a - * cyl-cyl-head-head structure - */ -static inline int -cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) { - return ptr->cc * geo->heads * geo->sectors + - ptr->hh * geo->sectors; -} - -/* - * compute the block number from a - * cyl-cyl-head-head-block structure - */ -static inline int -cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) { - return ptr->cc * geo->heads * geo->sectors + - ptr->hh * geo->sectors + - ptr->b; -} - -/* - */ -int -ibm_partition(struct parsed_partitions *state, struct block_device *bdev) -{ - int blocksize, offset, size,res; - loff_t i_size; - dasd_information2_t *info; - struct hd_geometry *geo; - char type[5] = {0,}; - char name[7] = {0,}; - union label_t { - struct vtoc_volume_label vol; - struct vtoc_cms_label cms; - } *label; - unsigned char *data; - Sector sect; - - res = 0; - blocksize = bdev_hardsect_size(bdev); - if (blocksize <= 0) - goto out_exit; - i_size = i_size_read(bdev->bd_inode); - if (i_size == 0) - goto out_exit; - - info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL); - if (info == NULL) - goto out_exit; - geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL); - if (geo == NULL) - goto out_nogeo; - label = kmalloc(sizeof(union label_t), GFP_KERNEL); - if (label == NULL) - goto out_nolab; - - if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0 || - ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0) - goto out_freeall; - - /* - * Get volume label, extract name and type. - */ - data = read_dev_sector(bdev, info->label_block*(blocksize/512), §); - if (data == NULL) - goto out_readerr; - - strncpy (type, data, 4); - if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) - strncpy(name, data + 8, 6); - else - strncpy(name, data + 4, 6); - memcpy(label, data, sizeof(union label_t)); - put_dev_sector(sect); - - EBCASC(type, 4); - EBCASC(name, 6); - - res = 1; - - /* - * Three different formats: LDL, CDL and unformated disk - * - * identified by info->format - * - * unformated disks we do not have to care about - */ - if (info->format == DASD_FORMAT_LDL) { - if (strncmp(type, "CMS1", 4) == 0) { - /* - * VM style CMS1 labeled disk - */ - if (label->cms.disk_offset != 0) { - printk("CMS1/%8s(MDSK):", name); - /* disk is reserved minidisk */ - blocksize = label->cms.block_size; - offset = label->cms.disk_offset; - size = (label->cms.block_count - 1) - * (blocksize >> 9); - } else { - printk("CMS1/%8s:", name); - offset = (info->label_block + 1); - size = i_size >> 9; - } - } else { - /* - * Old style LNX1 or unlabeled disk - */ - if (strncmp(type, "LNX1", 4) == 0) - printk ("LNX1/%8s:", name); - else - printk("(nonl)"); - offset = (info->label_block + 1); - size = i_size >> 9; - } - put_partition(state, 1, offset*(blocksize >> 9), - size-offset*(blocksize >> 9)); - } else if (info->format == DASD_FORMAT_CDL) { - /* - * New style CDL formatted disk - */ - unsigned int blk; - int counter; - - /* - * check if VOL1 label is available - * if not, something is wrong, skipping partition detection - */ - if (strncmp(type, "VOL1", 4) == 0) { - printk("VOL1/%8s:", name); - /* - * get block number and read then go through format1 - * labels - */ - blk = cchhb2blk(&label->vol.vtoc, geo) + 1; - counter = 0; - data = read_dev_sector(bdev, blk * (blocksize/512), - §); - while (data != NULL) { - struct vtoc_format1_label f1; - - memcpy(&f1, data, - sizeof(struct vtoc_format1_label)); - put_dev_sector(sect); - - /* skip FMT4 / FMT5 / FMT7 labels */ - if (f1.DS1FMTID == _ascebc['4'] - || f1.DS1FMTID == _ascebc['5'] - || f1.DS1FMTID == _ascebc['7']) { - blk++; - data = read_dev_sector(bdev, blk * - (blocksize/512), - §); - continue; - } - - /* only FMT1 valid at this point */ - if (f1.DS1FMTID != _ascebc['1']) - break; - - /* OK, we got valid partition data */ - offset = cchh2blk(&f1.DS1EXT1.llimit, geo); - size = cchh2blk(&f1.DS1EXT1.ulimit, geo) - - offset + geo->sectors; - if (counter >= state->limit) - break; - put_partition(state, counter + 1, - offset * (blocksize >> 9), - size * (blocksize >> 9)); - counter++; - blk++; - data = read_dev_sector(bdev, - blk * (blocksize/512), - §); - } - - if (!data) - /* Are we not supposed to report this ? */ - goto out_readerr; - } else - printk(KERN_WARNING "Warning, expected Label VOL1 not " - "found, treating as CDL formated Disk"); - - } - - printk("\n"); - goto out_freeall; - - -out_readerr: - res = -1; -out_freeall: - kfree(label); -out_nolab: - kfree(geo); -out_nogeo: - kfree(info); -out_exit: - return res; -} diff --git a/windhoek/partitions/ibm.h b/windhoek/partitions/ibm.h deleted file mode 100644 index 31f85a6a..00000000 --- a/windhoek/partitions/ibm.h +++ /dev/null @@ -1 +0,0 @@ -int ibm_partition(struct parsed_partitions *, struct block_device *); diff --git a/windhoek/partitions/karma.c b/windhoek/partitions/karma.c deleted file mode 100644 index 176d89bc..00000000 --- a/windhoek/partitions/karma.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * fs/partitions/karma.c - * Rio Karma partition info. - * - * Copyright (C) 2006 Bob Copeland (me@bobcopeland.com) - * based on osf.c - */ - -#include "check.h" -#include "karma.h" - -int karma_partition(struct parsed_partitions *state, struct block_device *bdev) -{ - int i; - int slot = 1; - Sector sect; - unsigned char *data; - struct disklabel { - u8 d_reserved[270]; - struct d_partition { - __le32 p_res; - u8 p_fstype; - u8 p_res2[3]; - __le32 p_offset; - __le32 p_size; - } d_partitions[2]; - u8 d_blank[208]; - __le16 d_magic; - } __attribute__((packed)) *label; - struct d_partition *p; - - data = read_dev_sector(bdev, 0, §); - if (!data) - return -1; - - label = (struct disklabel *)data; - if (le16_to_cpu(label->d_magic) != KARMA_LABEL_MAGIC) { - put_dev_sector(sect); - return 0; - } - - p = label->d_partitions; - for (i = 0 ; i < 2; i++, p++) { - if (slot == state->limit) - break; - - if (p->p_fstype == 0x4d && le32_to_cpu(p->p_size)) { - put_partition(state, slot, le32_to_cpu(p->p_offset), - le32_to_cpu(p->p_size)); - } - slot++; - } - printk("\n"); - put_dev_sector(sect); - return 1; -} - diff --git a/windhoek/partitions/karma.h b/windhoek/partitions/karma.h deleted file mode 100644 index ecf7d3f2..00000000 --- a/windhoek/partitions/karma.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * fs/partitions/karma.h - */ - -#define KARMA_LABEL_MAGIC 0xAB56 - -int karma_partition(struct parsed_partitions *state, struct block_device *bdev); - diff --git a/windhoek/partitions/ldm.c b/windhoek/partitions/ldm.c deleted file mode 100644 index 8652fb99..00000000 --- a/windhoek/partitions/ldm.c +++ /dev/null @@ -1,1551 +0,0 @@ -/** - * ldm - Support for Windows Logical Disk Manager (Dynamic Disks) - * - * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org> - * Copyright (c) 2001-2007 Anton Altaparmakov - * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com> - * - * Documentation is available at http://www.linux-ntfs.org/content/view/19/37/ - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program (in the main directory of the source in the file COPYING); if - * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - */ - -#include <linux/slab.h> -#include <linux/pagemap.h> -#include <linux/stringify.h> -#include "ldm.h" -#include "check.h" -#include "msdos.h" - -/** - * ldm_debug/info/error/crit - Output an error message - * @f: A printf format string containing the message - * @...: Variables to substitute into @f - * - * ldm_debug() writes a DEBUG level message to the syslog but only if the - * driver was compiled with debug enabled. Otherwise, the call turns into a NOP. - */ -#ifndef CONFIG_LDM_DEBUG -#define ldm_debug(...) do {} while (0) -#else -#define ldm_debug(f, a...) _ldm_printk (KERN_DEBUG, __func__, f, ##a) -#endif - -#define ldm_crit(f, a...) _ldm_printk (KERN_CRIT, __func__, f, ##a) -#define ldm_error(f, a...) _ldm_printk (KERN_ERR, __func__, f, ##a) -#define ldm_info(f, a...) _ldm_printk (KERN_INFO, __func__, f, ##a) - -__attribute__ ((format (printf, 3, 4))) -static void _ldm_printk (const char *level, const char *function, - const char *fmt, ...) -{ - static char buf[128]; - va_list args; - - va_start (args, fmt); - vsnprintf (buf, sizeof (buf), fmt, args); - va_end (args); - - printk ("%s%s(): %s\n", level, function, buf); -} - -/** - * ldm_parse_hexbyte - Convert a ASCII hex number to a byte - * @src: Pointer to at least 2 characters to convert. - * - * Convert a two character ASCII hex string to a number. - * - * Return: 0-255 Success, the byte was parsed correctly - * -1 Error, an invalid character was supplied - */ -static int ldm_parse_hexbyte (const u8 *src) -{ - unsigned int x; /* For correct wrapping */ - int h; - - /* high part */ - if ((x = src[0] - '0') <= '9'-'0') h = x; - else if ((x = src[0] - 'a') <= 'f'-'a') h = x+10; - else if ((x = src[0] - 'A') <= 'F'-'A') h = x+10; - else return -1; - h <<= 4; - - /* low part */ - if ((x = src[1] - '0') <= '9'-'0') return h | x; - if ((x = src[1] - 'a') <= 'f'-'a') return h | (x+10); - if ((x = src[1] - 'A') <= 'F'-'A') return h | (x+10); - return -1; -} - -/** - * ldm_parse_guid - Convert GUID from ASCII to binary - * @src: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba - * @dest: Memory block to hold binary GUID (16 bytes) - * - * N.B. The GUID need not be NULL terminated. - * - * Return: 'true' @dest contains binary GUID - * 'false' @dest contents are undefined - */ -static bool ldm_parse_guid (const u8 *src, u8 *dest) -{ - static const int size[] = { 4, 2, 2, 2, 6 }; - int i, j, v; - - if (src[8] != '-' || src[13] != '-' || - src[18] != '-' || src[23] != '-') - return false; - - for (j = 0; j < 5; j++, src++) - for (i = 0; i < size[j]; i++, src+=2, *dest++ = v) - if ((v = ldm_parse_hexbyte (src)) < 0) - return false; - - return true; -} - -/** - * ldm_parse_privhead - Read the LDM Database PRIVHEAD structure - * @data: Raw database PRIVHEAD structure loaded from the device - * @ph: In-memory privhead structure in which to return parsed information - * - * This parses the LDM database PRIVHEAD structure supplied in @data and - * sets up the in-memory privhead structure @ph with the obtained information. - * - * Return: 'true' @ph contains the PRIVHEAD data - * 'false' @ph contents are undefined - */ -static bool ldm_parse_privhead(const u8 *data, struct privhead *ph) -{ - bool is_vista = false; - - BUG_ON(!data || !ph); - if (MAGIC_PRIVHEAD != get_unaligned_be64(data)) { - ldm_error("Cannot find PRIVHEAD structure. LDM database is" - " corrupt. Aborting."); - return false; - } - ph->ver_major = get_unaligned_be16(data + 0x000C); - ph->ver_minor = get_unaligned_be16(data + 0x000E); - ph->logical_disk_start = get_unaligned_be64(data + 0x011B); - ph->logical_disk_size = get_unaligned_be64(data + 0x0123); - ph->config_start = get_unaligned_be64(data + 0x012B); - ph->config_size = get_unaligned_be64(data + 0x0133); - /* Version 2.11 is Win2k/XP and version 2.12 is Vista. */ - if (ph->ver_major == 2 && ph->ver_minor == 12) - is_vista = true; - if (!is_vista && (ph->ver_major != 2 || ph->ver_minor != 11)) { - ldm_error("Expected PRIVHEAD version 2.11 or 2.12, got %d.%d." - " Aborting.", ph->ver_major, ph->ver_minor); - return false; - } - ldm_debug("PRIVHEAD version %d.%d (Windows %s).", ph->ver_major, - ph->ver_minor, is_vista ? "Vista" : "2000/XP"); - if (ph->config_size != LDM_DB_SIZE) { /* 1 MiB in sectors. */ - /* Warn the user and continue, carefully. */ - ldm_info("Database is normally %u bytes, it claims to " - "be %llu bytes.", LDM_DB_SIZE, - (unsigned long long)ph->config_size); - } - if ((ph->logical_disk_size == 0) || (ph->logical_disk_start + - ph->logical_disk_size > ph->config_start)) { - ldm_error("PRIVHEAD disk size doesn't match real disk size"); - return false; - } - if (!ldm_parse_guid(data + 0x0030, ph->disk_id)) { - ldm_error("PRIVHEAD contains an invalid GUID."); - return false; - } - ldm_debug("Parsed PRIVHEAD successfully."); - return true; -} - -/** - * ldm_parse_tocblock - Read the LDM Database TOCBLOCK structure - * @data: Raw database TOCBLOCK structure loaded from the device - * @toc: In-memory toc structure in which to return parsed information - * - * This parses the LDM Database TOCBLOCK (table of contents) structure supplied - * in @data and sets up the in-memory tocblock structure @toc with the obtained - * information. - * - * N.B. The *_start and *_size values returned in @toc are not range-checked. - * - * Return: 'true' @toc contains the TOCBLOCK data - * 'false' @toc contents are undefined - */ -static bool ldm_parse_tocblock (const u8 *data, struct tocblock *toc) -{ - BUG_ON (!data || !toc); - - if (MAGIC_TOCBLOCK != get_unaligned_be64(data)) { - ldm_crit ("Cannot find TOCBLOCK, database may be corrupt."); - return false; - } - strncpy (toc->bitmap1_name, data + 0x24, sizeof (toc->bitmap1_name)); - toc->bitmap1_name[sizeof (toc->bitmap1_name) - 1] = 0; - toc->bitmap1_start = get_unaligned_be64(data + 0x2E); - toc->bitmap1_size = get_unaligned_be64(data + 0x36); - - if (strncmp (toc->bitmap1_name, TOC_BITMAP1, - sizeof (toc->bitmap1_name)) != 0) { - ldm_crit ("TOCBLOCK's first bitmap is '%s', should be '%s'.", - TOC_BITMAP1, toc->bitmap1_name); - return false; - } - strncpy (toc->bitmap2_name, data + 0x46, sizeof (toc->bitmap2_name)); - toc->bitmap2_name[sizeof (toc->bitmap2_name) - 1] = 0; - toc->bitmap2_start = get_unaligned_be64(data + 0x50); - toc->bitmap2_size = get_unaligned_be64(data + 0x58); - if (strncmp (toc->bitmap2_name, TOC_BITMAP2, - sizeof (toc->bitmap2_name)) != 0) { - ldm_crit ("TOCBLOCK's second bitmap is '%s', should be '%s'.", - TOC_BITMAP2, toc->bitmap2_name); - return false; - } - ldm_debug ("Parsed TOCBLOCK successfully."); - return true; -} - -/** - * ldm_parse_vmdb - Read the LDM Database VMDB structure - * @data: Raw database VMDB structure loaded from the device - * @vm: In-memory vmdb structure in which to return parsed information - * - * This parses the LDM Database VMDB structure supplied in @data and sets up - * the in-memory vmdb structure @vm with the obtained information. - * - * N.B. The *_start, *_size and *_seq values will be range-checked later. - * - * Return: 'true' @vm contains VMDB info - * 'false' @vm contents are undefined - */ -static bool ldm_parse_vmdb (const u8 *data, struct vmdb *vm) -{ - BUG_ON (!data || !vm); - - if (MAGIC_VMDB != get_unaligned_be32(data)) { - ldm_crit ("Cannot find the VMDB, database may be corrupt."); - return false; - } - - vm->ver_major = get_unaligned_be16(data + 0x12); - vm->ver_minor = get_unaligned_be16(data + 0x14); - if ((vm->ver_major != 4) || (vm->ver_minor != 10)) { - ldm_error ("Expected VMDB version %d.%d, got %d.%d. " - "Aborting.", 4, 10, vm->ver_major, vm->ver_minor); - return false; - } - - vm->vblk_size = get_unaligned_be32(data + 0x08); - vm->vblk_offset = get_unaligned_be32(data + 0x0C); - vm->last_vblk_seq = get_unaligned_be32(data + 0x04); - - ldm_debug ("Parsed VMDB successfully."); - return true; -} - -/** - * ldm_compare_privheads - Compare two privhead objects - * @ph1: First privhead - * @ph2: Second privhead - * - * This compares the two privhead structures @ph1 and @ph2. - * - * Return: 'true' Identical - * 'false' Different - */ -static bool ldm_compare_privheads (const struct privhead *ph1, - const struct privhead *ph2) -{ - BUG_ON (!ph1 || !ph2); - - return ((ph1->ver_major == ph2->ver_major) && - (ph1->ver_minor == ph2->ver_minor) && - (ph1->logical_disk_start == ph2->logical_disk_start) && - (ph1->logical_disk_size == ph2->logical_disk_size) && - (ph1->config_start == ph2->config_start) && - (ph1->config_size == ph2->config_size) && - !memcmp (ph1->disk_id, ph2->disk_id, GUID_SIZE)); -} - -/** - * ldm_compare_tocblocks - Compare two tocblock objects - * @toc1: First toc - * @toc2: Second toc - * - * This compares the two tocblock structures @toc1 and @toc2. - * - * Return: 'true' Identical - * 'false' Different - */ -static bool ldm_compare_tocblocks (const struct tocblock *toc1, - const struct tocblock *toc2) -{ - BUG_ON (!toc1 || !toc2); - - return ((toc1->bitmap1_start == toc2->bitmap1_start) && - (toc1->bitmap1_size == toc2->bitmap1_size) && - (toc1->bitmap2_start == toc2->bitmap2_start) && - (toc1->bitmap2_size == toc2->bitmap2_size) && - !strncmp (toc1->bitmap1_name, toc2->bitmap1_name, - sizeof (toc1->bitmap1_name)) && - !strncmp (toc1->bitmap2_name, toc2->bitmap2_name, - sizeof (toc1->bitmap2_name))); -} - -/** - * ldm_validate_privheads - Compare the primary privhead with its backups - * @bdev: Device holding the LDM Database - * @ph1: Memory struct to fill with ph contents - * - * Read and compare all three privheads from disk. - * - * The privheads on disk show the size and location of the main disk area and - * the configuration area (the database). The values are range-checked against - * @hd, which contains the real size of the disk. - * - * Return: 'true' Success - * 'false' Error - */ -static bool ldm_validate_privheads (struct block_device *bdev, - struct privhead *ph1) -{ - static const int off[3] = { OFF_PRIV1, OFF_PRIV2, OFF_PRIV3 }; - struct privhead *ph[3] = { ph1 }; - Sector sect; - u8 *data; - bool result = false; - long num_sects; - int i; - - BUG_ON (!bdev || !ph1); - - ph[1] = kmalloc (sizeof (*ph[1]), GFP_KERNEL); - ph[2] = kmalloc (sizeof (*ph[2]), GFP_KERNEL); - if (!ph[1] || !ph[2]) { - ldm_crit ("Out of memory."); - goto out; - } - - /* off[1 & 2] are relative to ph[0]->config_start */ - ph[0]->config_start = 0; - - /* Read and parse privheads */ - for (i = 0; i < 3; i++) { - data = read_dev_sector (bdev, - ph[0]->config_start + off[i], §); - if (!data) { - ldm_crit ("Disk read failed."); - goto out; - } - result = ldm_parse_privhead (data, ph[i]); - put_dev_sector (sect); - if (!result) { - ldm_error ("Cannot find PRIVHEAD %d.", i+1); /* Log again */ - if (i < 2) - goto out; /* Already logged */ - else - break; /* FIXME ignore for now, 3rd PH can fail on odd-sized disks */ - } - } - - num_sects = bdev->bd_inode->i_size >> 9; - - if ((ph[0]->config_start > num_sects) || - ((ph[0]->config_start + ph[0]->config_size) > num_sects)) { - ldm_crit ("Database extends beyond the end of the disk."); - goto out; - } - - if ((ph[0]->logical_disk_start > ph[0]->config_start) || - ((ph[0]->logical_disk_start + ph[0]->logical_disk_size) - > ph[0]->config_start)) { - ldm_crit ("Disk and database overlap."); - goto out; - } - - if (!ldm_compare_privheads (ph[0], ph[1])) { - ldm_crit ("Primary and backup PRIVHEADs don't match."); - goto out; - } - /* FIXME ignore this for now - if (!ldm_compare_privheads (ph[0], ph[2])) { - ldm_crit ("Primary and backup PRIVHEADs don't match."); - goto out; - }*/ - ldm_debug ("Validated PRIVHEADs successfully."); - result = true; -out: - kfree (ph[1]); - kfree (ph[2]); - return result; -} - -/** - * ldm_validate_tocblocks - Validate the table of contents and its backups - * @bdev: Device holding the LDM Database - * @base: Offset, into @bdev, of the database - * @ldb: Cache of the database structures - * - * Find and compare the four tables of contents of the LDM Database stored on - * @bdev and return the parsed information into @toc1. - * - * The offsets and sizes of the configs are range-checked against a privhead. - * - * Return: 'true' @toc1 contains validated TOCBLOCK info - * 'false' @toc1 contents are undefined - */ -static bool ldm_validate_tocblocks(struct block_device *bdev, - unsigned long base, struct ldmdb *ldb) -{ - static const int off[4] = { OFF_TOCB1, OFF_TOCB2, OFF_TOCB3, OFF_TOCB4}; - struct tocblock *tb[4]; - struct privhead *ph; - Sector sect; - u8 *data; - int i, nr_tbs; - bool result = false; - - BUG_ON(!bdev || !ldb); - ph = &ldb->ph; - tb[0] = &ldb->toc; - tb[1] = kmalloc(sizeof(*tb[1]) * 3, GFP_KERNEL); - if (!tb[1]) { - ldm_crit("Out of memory."); - goto err; - } - tb[2] = (struct tocblock*)((u8*)tb[1] + sizeof(*tb[1])); - tb[3] = (struct tocblock*)((u8*)tb[2] + sizeof(*tb[2])); - /* - * Try to read and parse all four TOCBLOCKs. - * - * Windows Vista LDM v2.12 does not always have all four TOCBLOCKs so - * skip any that fail as long as we get at least one valid TOCBLOCK. - */ - for (nr_tbs = i = 0; i < 4; i++) { - data = read_dev_sector(bdev, base + off[i], §); - if (!data) { - ldm_error("Disk read failed for TOCBLOCK %d.", i); - continue; - } - if (ldm_parse_tocblock(data, tb[nr_tbs])) - nr_tbs++; - put_dev_sector(sect); - } - if (!nr_tbs) { - ldm_crit("Failed to find a valid TOCBLOCK."); - goto err; - } - /* Range check the TOCBLOCK against a privhead. */ - if (((tb[0]->bitmap1_start + tb[0]->bitmap1_size) > ph->config_size) || - ((tb[0]->bitmap2_start + tb[0]->bitmap2_size) > - ph->config_size)) { - ldm_crit("The bitmaps are out of range. Giving up."); - goto err; - } - /* Compare all loaded TOCBLOCKs. */ - for (i = 1; i < nr_tbs; i++) { - if (!ldm_compare_tocblocks(tb[0], tb[i])) { - ldm_crit("TOCBLOCKs 0 and %d do not match.", i); - goto err; - } - } - ldm_debug("Validated %d TOCBLOCKs successfully.", nr_tbs); - result = true; -err: - kfree(tb[1]); - return result; -} - -/** - * ldm_validate_vmdb - Read the VMDB and validate it - * @bdev: Device holding the LDM Database - * @base: Offset, into @bdev, of the database - * @ldb: Cache of the database structures - * - * Find the vmdb of the LDM Database stored on @bdev and return the parsed - * information in @ldb. - * - * Return: 'true' @ldb contains validated VBDB info - * 'false' @ldb contents are undefined - */ -static bool ldm_validate_vmdb (struct block_device *bdev, unsigned long base, - struct ldmdb *ldb) -{ - Sector sect; - u8 *data; - bool result = false; - struct vmdb *vm; - struct tocblock *toc; - - BUG_ON (!bdev || !ldb); - - vm = &ldb->vm; - toc = &ldb->toc; - - data = read_dev_sector (bdev, base + OFF_VMDB, §); - if (!data) { - ldm_crit ("Disk read failed."); - return false; - } - - if (!ldm_parse_vmdb (data, vm)) - goto out; /* Already logged */ - - /* Are there uncommitted transactions? */ - if (get_unaligned_be16(data + 0x10) != 0x01) { - ldm_crit ("Database is not in a consistent state. Aborting."); - goto out; - } - - if (vm->vblk_offset != 512) - ldm_info ("VBLKs start at offset 0x%04x.", vm->vblk_offset); - - /* - * The last_vblkd_seq can be before the end of the vmdb, just make sure - * it is not out of bounds. - */ - if ((vm->vblk_size * vm->last_vblk_seq) > (toc->bitmap1_size << 9)) { - ldm_crit ("VMDB exceeds allowed size specified by TOCBLOCK. " - "Database is corrupt. Aborting."); - goto out; - } - - result = true; -out: - put_dev_sector (sect); - return result; -} - - -/** - * ldm_validate_partition_table - Determine whether bdev might be a dynamic disk - * @bdev: Device holding the LDM Database - * - * This function provides a weak test to decide whether the device is a dynamic - * disk or not. It looks for an MS-DOS-style partition table containing at - * least one partition of type 0x42 (formerly SFS, now used by Windows for - * dynamic disks). - * - * N.B. The only possible error can come from the read_dev_sector and that is - * only likely to happen if the underlying device is strange. If that IS - * the case we should return zero to let someone else try. - * - * Return: 'true' @bdev is a dynamic disk - * 'false' @bdev is not a dynamic disk, or an error occurred - */ -static bool ldm_validate_partition_table (struct block_device *bdev) -{ - Sector sect; - u8 *data; - struct partition *p; - int i; - bool result = false; - - BUG_ON (!bdev); - - data = read_dev_sector (bdev, 0, §); - if (!data) { - ldm_crit ("Disk read failed."); - return false; - } - - if (*(__le16*) (data + 0x01FE) != cpu_to_le16 (MSDOS_LABEL_MAGIC)) - goto out; - - p = (struct partition*)(data + 0x01BE); - for (i = 0; i < 4; i++, p++) - if (SYS_IND (p) == LDM_PARTITION) { - result = true; - break; - } - - if (result) - ldm_debug ("Found W2K dynamic disk partition type."); - -out: - put_dev_sector (sect); - return result; -} - -/** - * ldm_get_disk_objid - Search a linked list of vblk's for a given Disk Id - * @ldb: Cache of the database structures - * - * The LDM Database contains a list of all partitions on all dynamic disks. - * The primary PRIVHEAD, at the beginning of the physical disk, tells us - * the GUID of this disk. This function searches for the GUID in a linked - * list of vblk's. - * - * Return: Pointer, A matching vblk was found - * NULL, No match, or an error - */ -static struct vblk * ldm_get_disk_objid (const struct ldmdb *ldb) -{ - struct list_head *item; - - BUG_ON (!ldb); - - list_for_each (item, &ldb->v_disk) { - struct vblk *v = list_entry (item, struct vblk, list); - if (!memcmp (v->vblk.disk.disk_id, ldb->ph.disk_id, GUID_SIZE)) - return v; - } - - return NULL; -} - -/** - * ldm_create_data_partitions - Create data partitions for this device - * @pp: List of the partitions parsed so far - * @ldb: Cache of the database structures - * - * The database contains ALL the partitions for ALL disk groups, so we need to - * filter out this specific disk. Using the disk's object id, we can find all - * the partitions in the database that belong to this disk. - * - * Add each partition in our database, to the parsed_partitions structure. - * - * N.B. This function creates the partitions in the order it finds partition - * objects in the linked list. - * - * Return: 'true' Partition created - * 'false' Error, probably a range checking problem - */ -static bool ldm_create_data_partitions (struct parsed_partitions *pp, - const struct ldmdb *ldb) -{ - struct list_head *item; - struct vblk *vb; - struct vblk *disk; - struct vblk_part *part; - int part_num = 1; - - BUG_ON (!pp || !ldb); - - disk = ldm_get_disk_objid (ldb); - if (!disk) { - ldm_crit ("Can't find the ID of this disk in the database."); - return false; - } - - printk (" [LDM]"); - - /* Create the data partitions */ - list_for_each (item, &ldb->v_part) { - vb = list_entry (item, struct vblk, list); - part = &vb->vblk.part; - - if (part->disk_id != disk->obj_id) - continue; - - put_partition (pp, part_num, ldb->ph.logical_disk_start + - part->start, part->size); - part_num++; - } - - printk ("\n"); - return true; -} - - -/** - * ldm_relative - Calculate the next relative offset - * @buffer: Block of data being worked on - * @buflen: Size of the block of data - * @base: Size of the previous fixed width fields - * @offset: Cumulative size of the previous variable-width fields - * - * Because many of the VBLK fields are variable-width, it's necessary - * to calculate each offset based on the previous one and the length - * of the field it pointed to. - * - * Return: -1 Error, the calculated offset exceeded the size of the buffer - * n OK, a range-checked offset into buffer - */ -static int ldm_relative(const u8 *buffer, int buflen, int base, int offset) -{ - - base += offset; - if (!buffer || offset < 0 || base > buflen) { - if (!buffer) - ldm_error("!buffer"); - if (offset < 0) - ldm_error("offset (%d) < 0", offset); - if (base > buflen) - ldm_error("base (%d) > buflen (%d)", base, buflen); - return -1; - } - if (base + buffer[base] >= buflen) { - ldm_error("base (%d) + buffer[base] (%d) >= buflen (%d)", base, - buffer[base], buflen); - return -1; - } - return buffer[base] + offset + 1; -} - -/** - * ldm_get_vnum - Convert a variable-width, big endian number, into cpu order - * @block: Pointer to the variable-width number to convert - * - * Large numbers in the LDM Database are often stored in a packed format. Each - * number is prefixed by a one byte width marker. All numbers in the database - * are stored in big-endian byte order. This function reads one of these - * numbers and returns the result - * - * N.B. This function DOES NOT perform any range checking, though the most - * it will read is eight bytes. - * - * Return: n A number - * 0 Zero, or an error occurred - */ -static u64 ldm_get_vnum (const u8 *block) -{ - u64 tmp = 0; - u8 length; - - BUG_ON (!block); - - length = *block++; - - if (length && length <= 8) - while (length--) - tmp = (tmp << 8) | *block++; - else - ldm_error ("Illegal length %d.", length); - - return tmp; -} - -/** - * ldm_get_vstr - Read a length-prefixed string into a buffer - * @block: Pointer to the length marker - * @buffer: Location to copy string to - * @buflen: Size of the output buffer - * - * Many of the strings in the LDM Database are not NULL terminated. Instead - * they are prefixed by a one byte length marker. This function copies one of - * these strings into a buffer. - * - * N.B. This function DOES NOT perform any range checking on the input. - * If the buffer is too small, the output will be truncated. - * - * Return: 0, Error and @buffer contents are undefined - * n, String length in characters (excluding NULL) - * buflen-1, String was truncated. - */ -static int ldm_get_vstr (const u8 *block, u8 *buffer, int buflen) -{ - int length; - - BUG_ON (!block || !buffer); - - length = block[0]; - if (length >= buflen) { - ldm_error ("Truncating string %d -> %d.", length, buflen); - length = buflen - 1; - } - memcpy (buffer, block + 1, length); - buffer[length] = 0; - return length; -} - - -/** - * ldm_parse_cmp3 - Read a raw VBLK Component object into a vblk structure - * @buffer: Block of data being worked on - * @buflen: Size of the block of data - * @vb: In-memory vblk in which to return information - * - * Read a raw VBLK Component object (version 3) into a vblk structure. - * - * Return: 'true' @vb contains a Component VBLK - * 'false' @vb contents are not defined - */ -static bool ldm_parse_cmp3 (const u8 *buffer, int buflen, struct vblk *vb) -{ - int r_objid, r_name, r_vstate, r_child, r_parent, r_stripe, r_cols, len; - struct vblk_comp *comp; - - BUG_ON (!buffer || !vb); - - r_objid = ldm_relative (buffer, buflen, 0x18, 0); - r_name = ldm_relative (buffer, buflen, 0x18, r_objid); - r_vstate = ldm_relative (buffer, buflen, 0x18, r_name); - r_child = ldm_relative (buffer, buflen, 0x1D, r_vstate); - r_parent = ldm_relative (buffer, buflen, 0x2D, r_child); - - if (buffer[0x12] & VBLK_FLAG_COMP_STRIPE) { - r_stripe = ldm_relative (buffer, buflen, 0x2E, r_parent); - r_cols = ldm_relative (buffer, buflen, 0x2E, r_stripe); - len = r_cols; - } else { - r_stripe = 0; - r_cols = 0; - len = r_parent; - } - if (len < 0) - return false; - - len += VBLK_SIZE_CMP3; - if (len != get_unaligned_be32(buffer + 0x14)) - return false; - - comp = &vb->vblk.comp; - ldm_get_vstr (buffer + 0x18 + r_name, comp->state, - sizeof (comp->state)); - comp->type = buffer[0x18 + r_vstate]; - comp->children = ldm_get_vnum (buffer + 0x1D + r_vstate); - comp->parent_id = ldm_get_vnum (buffer + 0x2D + r_child); - comp->chunksize = r_stripe ? ldm_get_vnum (buffer+r_parent+0x2E) : 0; - - return true; -} - -/** - * ldm_parse_dgr3 - Read a raw VBLK Disk Group object into a vblk structure - * @buffer: Block of data being worked on - * @buflen: Size of the block of data - * @vb: In-memory vblk in which to return information - * - * Read a raw VBLK Disk Group object (version 3) into a vblk structure. - * - * Return: 'true' @vb contains a Disk Group VBLK - * 'false' @vb contents are not defined - */ -static int ldm_parse_dgr3 (const u8 *buffer, int buflen, struct vblk *vb) -{ - int r_objid, r_name, r_diskid, r_id1, r_id2, len; - struct vblk_dgrp *dgrp; - - BUG_ON (!buffer || !vb); - - r_objid = ldm_relative (buffer, buflen, 0x18, 0); - r_name = ldm_relative (buffer, buflen, 0x18, r_objid); - r_diskid = ldm_relative (buffer, buflen, 0x18, r_name); - - if (buffer[0x12] & VBLK_FLAG_DGR3_IDS) { - r_id1 = ldm_relative (buffer, buflen, 0x24, r_diskid); - r_id2 = ldm_relative (buffer, buflen, 0x24, r_id1); - len = r_id2; - } else { - r_id1 = 0; - r_id2 = 0; - len = r_diskid; - } - if (len < 0) - return false; - - len += VBLK_SIZE_DGR3; - if (len != get_unaligned_be32(buffer + 0x14)) - return false; - - dgrp = &vb->vblk.dgrp; - ldm_get_vstr (buffer + 0x18 + r_name, dgrp->disk_id, - sizeof (dgrp->disk_id)); - return true; -} - -/** - * ldm_parse_dgr4 - Read a raw VBLK Disk Group object into a vblk structure - * @buffer: Block of data being worked on - * @buflen: Size of the block of data - * @vb: In-memory vblk in which to return information - * - * Read a raw VBLK Disk Group object (version 4) into a vblk structure. - * - * Return: 'true' @vb contains a Disk Group VBLK - * 'false' @vb contents are not defined - */ -static bool ldm_parse_dgr4 (const u8 *buffer, int buflen, struct vblk *vb) -{ - char buf[64]; - int r_objid, r_name, r_id1, r_id2, len; - struct vblk_dgrp *dgrp; - - BUG_ON (!buffer || !vb); - - r_objid = ldm_relative (buffer, buflen, 0x18, 0); - r_name = ldm_relative (buffer, buflen, 0x18, r_objid); - - if (buffer[0x12] & VBLK_FLAG_DGR4_IDS) { - r_id1 = ldm_relative (buffer, buflen, 0x44, r_name); - r_id2 = ldm_relative (buffer, buflen, 0x44, r_id1); - len = r_id2; - } else { - r_id1 = 0; - r_id2 = 0; - len = r_name; - } - if (len < 0) - return false; - - len += VBLK_SIZE_DGR4; - if (len != get_unaligned_be32(buffer + 0x14)) - return false; - - dgrp = &vb->vblk.dgrp; - - ldm_get_vstr (buffer + 0x18 + r_objid, buf, sizeof (buf)); - return true; -} - -/** - * ldm_parse_dsk3 - Read a raw VBLK Disk object into a vblk structure - * @buffer: Block of data being worked on - * @buflen: Size of the block of data - * @vb: In-memory vblk in which to return information - * - * Read a raw VBLK Disk object (version 3) into a vblk structure. - * - * Return: 'true' @vb contains a Disk VBLK - * 'false' @vb contents are not defined - */ -static bool ldm_parse_dsk3 (const u8 *buffer, int buflen, struct vblk *vb) -{ - int r_objid, r_name, r_diskid, r_altname, len; - struct vblk_disk *disk; - - BUG_ON (!buffer || !vb); - - r_objid = ldm_relative (buffer, buflen, 0x18, 0); - r_name = ldm_relative (buffer, buflen, 0x18, r_objid); - r_diskid = ldm_relative (buffer, buflen, 0x18, r_name); - r_altname = ldm_relative (buffer, buflen, 0x18, r_diskid); - len = r_altname; - if (len < 0) - return false; - - len += VBLK_SIZE_DSK3; - if (len != get_unaligned_be32(buffer + 0x14)) - return false; - - disk = &vb->vblk.disk; - ldm_get_vstr (buffer + 0x18 + r_diskid, disk->alt_name, - sizeof (disk->alt_name)); - if (!ldm_parse_guid (buffer + 0x19 + r_name, disk->disk_id)) - return false; - - return true; -} - -/** - * ldm_parse_dsk4 - Read a raw VBLK Disk object into a vblk structure - * @buffer: Block of data being worked on - * @buflen: Size of the block of data - * @vb: In-memory vblk in which to return information - * - * Read a raw VBLK Disk object (version 4) into a vblk structure. - * - * Return: 'true' @vb contains a Disk VBLK - * 'false' @vb contents are not defined - */ -static bool ldm_parse_dsk4 (const u8 *buffer, int buflen, struct vblk *vb) -{ - int r_objid, r_name, len; - struct vblk_disk *disk; - - BUG_ON (!buffer || !vb); - - r_objid = ldm_relative (buffer, buflen, 0x18, 0); - r_name = ldm_relative (buffer, buflen, 0x18, r_objid); - len = r_name; - if (len < 0) - return false; - - len += VBLK_SIZE_DSK4; - if (len != get_unaligned_be32(buffer + 0x14)) - return false; - - disk = &vb->vblk.disk; - memcpy (disk->disk_id, buffer + 0x18 + r_name, GUID_SIZE); - return true; -} - -/** - * ldm_parse_prt3 - Read a raw VBLK Partition object into a vblk structure - * @buffer: Block of data being worked on - * @buflen: Size of the block of data - * @vb: In-memory vblk in which to return information - * - * Read a raw VBLK Partition object (version 3) into a vblk structure. - * - * Return: 'true' @vb contains a Partition VBLK - * 'false' @vb contents are not defined - */ -static bool ldm_parse_prt3(const u8 *buffer, int buflen, struct vblk *vb) -{ - int r_objid, r_name, r_size, r_parent, r_diskid, r_index, len; - struct vblk_part *part; - - BUG_ON(!buffer || !vb); - r_objid = ldm_relative(buffer, buflen, 0x18, 0); - if (r_objid < 0) { - ldm_error("r_objid %d < 0", r_objid); - return false; - } - r_name = ldm_relative(buffer, buflen, 0x18, r_objid); - if (r_name < 0) { - ldm_error("r_name %d < 0", r_name); - return false; - } - r_size = ldm_relative(buffer, buflen, 0x34, r_name); - if (r_size < 0) { - ldm_error("r_size %d < 0", r_size); - return false; - } - r_parent = ldm_relative(buffer, buflen, 0x34, r_size); - if (r_parent < 0) { - ldm_error("r_parent %d < 0", r_parent); - return false; - } - r_diskid = ldm_relative(buffer, buflen, 0x34, r_parent); - if (r_diskid < 0) { - ldm_error("r_diskid %d < 0", r_diskid); - return false; - } - if (buffer[0x12] & VBLK_FLAG_PART_INDEX) { - r_index = ldm_relative(buffer, buflen, 0x34, r_diskid); - if (r_index < 0) { - ldm_error("r_index %d < 0", r_index); - return false; - } - len = r_index; - } else { - r_index = 0; - len = r_diskid; - } - if (len < 0) { - ldm_error("len %d < 0", len); - return false; - } - len += VBLK_SIZE_PRT3; - if (len > get_unaligned_be32(buffer + 0x14)) { - ldm_error("len %d > BE32(buffer + 0x14) %d", len, - get_unaligned_be32(buffer + 0x14)); - return false; - } - part = &vb->vblk.part; - part->start = get_unaligned_be64(buffer + 0x24 + r_name); - part->volume_offset = get_unaligned_be64(buffer + 0x2C + r_name); - part->size = ldm_get_vnum(buffer + 0x34 + r_name); - part->parent_id = ldm_get_vnum(buffer + 0x34 + r_size); - part->disk_id = ldm_get_vnum(buffer + 0x34 + r_parent); - if (vb->flags & VBLK_FLAG_PART_INDEX) - part->partnum = buffer[0x35 + r_diskid]; - else - part->partnum = 0; - return true; -} - -/** - * ldm_parse_vol5 - Read a raw VBLK Volume object into a vblk structure - * @buffer: Block of data being worked on - * @buflen: Size of the block of data - * @vb: In-memory vblk in which to return information - * - * Read a raw VBLK Volume object (version 5) into a vblk structure. - * - * Return: 'true' @vb contains a Volume VBLK - * 'false' @vb contents are not defined - */ -static bool ldm_parse_vol5(const u8 *buffer, int buflen, struct vblk *vb) -{ - int r_objid, r_name, r_vtype, r_disable_drive_letter, r_child, r_size; - int r_id1, r_id2, r_size2, r_drive, len; - struct vblk_volu *volu; - - BUG_ON(!buffer || !vb); - r_objid = ldm_relative(buffer, buflen, 0x18, 0); - if (r_objid < 0) { - ldm_error("r_objid %d < 0", r_objid); - return false; - } - r_name = ldm_relative(buffer, buflen, 0x18, r_objid); - if (r_name < 0) { - ldm_error("r_name %d < 0", r_name); - return false; - } - r_vtype = ldm_relative(buffer, buflen, 0x18, r_name); - if (r_vtype < 0) { - ldm_error("r_vtype %d < 0", r_vtype); - return false; - } - r_disable_drive_letter = ldm_relative(buffer, buflen, 0x18, r_vtype); - if (r_disable_drive_letter < 0) { - ldm_error("r_disable_drive_letter %d < 0", - r_disable_drive_letter); - return false; - } - r_child = ldm_relative(buffer, buflen, 0x2D, r_disable_drive_letter); - if (r_child < 0) { - ldm_error("r_child %d < 0", r_child); - return false; - } - r_size = ldm_relative(buffer, buflen, 0x3D, r_child); - if (r_size < 0) { - ldm_error("r_size %d < 0", r_size); - return false; - } - if (buffer[0x12] & VBLK_FLAG_VOLU_ID1) { - r_id1 = ldm_relative(buffer, buflen, 0x52, r_size); - if (r_id1 < 0) { - ldm_error("r_id1 %d < 0", r_id1); - return false; - } - } else - r_id1 = r_size; - if (buffer[0x12] & VBLK_FLAG_VOLU_ID2) { - r_id2 = ldm_relative(buffer, buflen, 0x52, r_id1); - if (r_id2 < 0) { - ldm_error("r_id2 %d < 0", r_id2); - return false; - } - } else - r_id2 = r_id1; - if (buffer[0x12] & VBLK_FLAG_VOLU_SIZE) { - r_size2 = ldm_relative(buffer, buflen, 0x52, r_id2); - if (r_size2 < 0) { - ldm_error("r_size2 %d < 0", r_size2); - return false; - } - } else - r_size2 = r_id2; - if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE) { - r_drive = ldm_relative(buffer, buflen, 0x52, r_size2); - if (r_drive < 0) { - ldm_error("r_drive %d < 0", r_drive); - return false; - } - } else - r_drive = r_size2; - len = r_drive; - if (len < 0) { - ldm_error("len %d < 0", len); - return false; - } - len += VBLK_SIZE_VOL5; - if (len > get_unaligned_be32(buffer + 0x14)) { - ldm_error("len %d > BE32(buffer + 0x14) %d", len, - get_unaligned_be32(buffer + 0x14)); - return false; - } - volu = &vb->vblk.volu; - ldm_get_vstr(buffer + 0x18 + r_name, volu->volume_type, - sizeof(volu->volume_type)); - memcpy(volu->volume_state, buffer + 0x18 + r_disable_drive_letter, - sizeof(volu->volume_state)); - volu->size = ldm_get_vnum(buffer + 0x3D + r_child); - volu->partition_type = buffer[0x41 + r_size]; - memcpy(volu->guid, buffer + 0x42 + r_size, sizeof(volu->guid)); - if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE) { - ldm_get_vstr(buffer + 0x52 + r_size, volu->drive_hint, - sizeof(volu->drive_hint)); - } - return true; -} - -/** - * ldm_parse_vblk - Read a raw VBLK object into a vblk structure - * @buf: Block of data being worked on - * @len: Size of the block of data - * @vb: In-memory vblk in which to return information - * - * Read a raw VBLK object into a vblk structure. This function just reads the - * information common to all VBLK types, then delegates the rest of the work to - * helper functions: ldm_parse_*. - * - * Return: 'true' @vb contains a VBLK - * 'false' @vb contents are not defined - */ -static bool ldm_parse_vblk (const u8 *buf, int len, struct vblk *vb) -{ - bool result = false; - int r_objid; - - BUG_ON (!buf || !vb); - - r_objid = ldm_relative (buf, len, 0x18, 0); - if (r_objid < 0) { - ldm_error ("VBLK header is corrupt."); - return false; - } - - vb->flags = buf[0x12]; - vb->type = buf[0x13]; - vb->obj_id = ldm_get_vnum (buf + 0x18); - ldm_get_vstr (buf+0x18+r_objid, vb->name, sizeof (vb->name)); - - switch (vb->type) { - case VBLK_CMP3: result = ldm_parse_cmp3 (buf, len, vb); break; - case VBLK_DSK3: result = ldm_parse_dsk3 (buf, len, vb); break; - case VBLK_DSK4: result = ldm_parse_dsk4 (buf, len, vb); break; - case VBLK_DGR3: result = ldm_parse_dgr3 (buf, len, vb); break; - case VBLK_DGR4: result = ldm_parse_dgr4 (buf, len, vb); break; - case VBLK_PRT3: result = ldm_parse_prt3 (buf, len, vb); break; - case VBLK_VOL5: result = ldm_parse_vol5 (buf, len, vb); break; - } - - if (result) - ldm_debug ("Parsed VBLK 0x%llx (type: 0x%02x) ok.", - (unsigned long long) vb->obj_id, vb->type); - else - ldm_error ("Failed to parse VBLK 0x%llx (type: 0x%02x).", - (unsigned long long) vb->obj_id, vb->type); - - return result; -} - - -/** - * ldm_ldmdb_add - Adds a raw VBLK entry to the ldmdb database - * @data: Raw VBLK to add to the database - * @len: Size of the raw VBLK - * @ldb: Cache of the database structures - * - * The VBLKs are sorted into categories. Partitions are also sorted by offset. - * - * N.B. This function does not check the validity of the VBLKs. - * - * Return: 'true' The VBLK was added - * 'false' An error occurred - */ -static bool ldm_ldmdb_add (u8 *data, int len, struct ldmdb *ldb) -{ - struct vblk *vb; - struct list_head *item; - - BUG_ON (!data || !ldb); - - vb = kmalloc (sizeof (*vb), GFP_KERNEL); - if (!vb) { - ldm_crit ("Out of memory."); - return false; - } - - if (!ldm_parse_vblk (data, len, vb)) { - kfree(vb); - return false; /* Already logged */ - } - - /* Put vblk into the correct list. */ - switch (vb->type) { - case VBLK_DGR3: - case VBLK_DGR4: - list_add (&vb->list, &ldb->v_dgrp); - break; - case VBLK_DSK3: - case VBLK_DSK4: - list_add (&vb->list, &ldb->v_disk); - break; - case VBLK_VOL5: - list_add (&vb->list, &ldb->v_volu); - break; - case VBLK_CMP3: - list_add (&vb->list, &ldb->v_comp); - break; - case VBLK_PRT3: - /* Sort by the partition's start sector. */ - list_for_each (item, &ldb->v_part) { - struct vblk *v = list_entry (item, struct vblk, list); - if ((v->vblk.part.disk_id == vb->vblk.part.disk_id) && - (v->vblk.part.start > vb->vblk.part.start)) { - list_add_tail (&vb->list, &v->list); - return true; - } - } - list_add_tail (&vb->list, &ldb->v_part); - break; - } - return true; -} - -/** - * ldm_frag_add - Add a VBLK fragment to a list - * @data: Raw fragment to be added to the list - * @size: Size of the raw fragment - * @frags: Linked list of VBLK fragments - * - * Fragmented VBLKs may not be consecutive in the database, so they are placed - * in a list so they can be pieced together later. - * - * Return: 'true' Success, the VBLK was added to the list - * 'false' Error, a problem occurred - */ -static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags) -{ - struct frag *f; - struct list_head *item; - int rec, num, group; - - BUG_ON (!data || !frags); - - group = get_unaligned_be32(data + 0x08); - rec = get_unaligned_be16(data + 0x0C); - num = get_unaligned_be16(data + 0x0E); - if ((num < 1) || (num > 4)) { - ldm_error ("A VBLK claims to have %d parts.", num); - return false; - } - - list_for_each (item, frags) { - f = list_entry (item, struct frag, list); - if (f->group == group) - goto found; - } - - f = kmalloc (sizeof (*f) + size*num, GFP_KERNEL); - if (!f) { - ldm_crit ("Out of memory."); - return false; - } - - f->group = group; - f->num = num; - f->rec = rec; - f->map = 0xFF << num; - - list_add_tail (&f->list, frags); -found: - if (f->map & (1 << rec)) { - ldm_error ("Duplicate VBLK, part %d.", rec); - f->map &= 0x7F; /* Mark the group as broken */ - return false; - } - - f->map |= (1 << rec); - - if (num > 0) { - data += VBLK_SIZE_HEAD; - size -= VBLK_SIZE_HEAD; - } - memcpy (f->data+rec*(size-VBLK_SIZE_HEAD)+VBLK_SIZE_HEAD, data, size); - - return true; -} - -/** - * ldm_frag_free - Free a linked list of VBLK fragments - * @list: Linked list of fragments - * - * Free a linked list of VBLK fragments - * - * Return: none - */ -static void ldm_frag_free (struct list_head *list) -{ - struct list_head *item, *tmp; - - BUG_ON (!list); - - list_for_each_safe (item, tmp, list) - kfree (list_entry (item, struct frag, list)); -} - -/** - * ldm_frag_commit - Validate fragmented VBLKs and add them to the database - * @frags: Linked list of VBLK fragments - * @ldb: Cache of the database structures - * - * Now that all the fragmented VBLKs have been collected, they must be added to - * the database for later use. - * - * Return: 'true' All the fragments we added successfully - * 'false' One or more of the fragments we invalid - */ -static bool ldm_frag_commit (struct list_head *frags, struct ldmdb *ldb) -{ - struct frag *f; - struct list_head *item; - - BUG_ON (!frags || !ldb); - - list_for_each (item, frags) { - f = list_entry (item, struct frag, list); - - if (f->map != 0xFF) { - ldm_error ("VBLK group %d is incomplete (0x%02x).", - f->group, f->map); - return false; - } - - if (!ldm_ldmdb_add (f->data, f->num*ldb->vm.vblk_size, ldb)) - return false; /* Already logged */ - } - return true; -} - -/** - * ldm_get_vblks - Read the on-disk database of VBLKs into memory - * @bdev: Device holding the LDM Database - * @base: Offset, into @bdev, of the database - * @ldb: Cache of the database structures - * - * To use the information from the VBLKs, they need to be read from the disk, - * unpacked and validated. We cache them in @ldb according to their type. - * - * Return: 'true' All the VBLKs were read successfully - * 'false' An error occurred - */ -static bool ldm_get_vblks (struct block_device *bdev, unsigned long base, - struct ldmdb *ldb) -{ - int size, perbuf, skip, finish, s, v, recs; - u8 *data = NULL; - Sector sect; - bool result = false; - LIST_HEAD (frags); - - BUG_ON (!bdev || !ldb); - - size = ldb->vm.vblk_size; - perbuf = 512 / size; - skip = ldb->vm.vblk_offset >> 9; /* Bytes to sectors */ - finish = (size * ldb->vm.last_vblk_seq) >> 9; - - for (s = skip; s < finish; s++) { /* For each sector */ - data = read_dev_sector (bdev, base + OFF_VMDB + s, §); - if (!data) { - ldm_crit ("Disk read failed."); - goto out; - } - - for (v = 0; v < perbuf; v++, data+=size) { /* For each vblk */ - if (MAGIC_VBLK != get_unaligned_be32(data)) { - ldm_error ("Expected to find a VBLK."); - goto out; - } - - recs = get_unaligned_be16(data + 0x0E); /* Number of records */ - if (recs == 1) { - if (!ldm_ldmdb_add (data, size, ldb)) - goto out; /* Already logged */ - } else if (recs > 1) { - if (!ldm_frag_add (data, size, &frags)) - goto out; /* Already logged */ - } - /* else Record is not in use, ignore it. */ - } - put_dev_sector (sect); - data = NULL; - } - - result = ldm_frag_commit (&frags, ldb); /* Failures, already logged */ -out: - if (data) - put_dev_sector (sect); - ldm_frag_free (&frags); - - return result; -} - -/** - * ldm_free_vblks - Free a linked list of vblk's - * @lh: Head of a linked list of struct vblk - * - * Free a list of vblk's and free the memory used to maintain the list. - * - * Return: none - */ -static void ldm_free_vblks (struct list_head *lh) -{ - struct list_head *item, *tmp; - - BUG_ON (!lh); - - list_for_each_safe (item, tmp, lh) - kfree (list_entry (item, struct vblk, list)); -} - - -/** - * ldm_partition - Find out whether a device is a dynamic disk and handle it - * @pp: List of the partitions parsed so far - * @bdev: Device holding the LDM Database - * - * This determines whether the device @bdev is a dynamic disk and if so creates - * the partitions necessary in the gendisk structure pointed to by @hd. - * - * We create a dummy device 1, which contains the LDM database, and then create - * each partition described by the LDM database in sequence as devices 2+. For - * example, if the device is hda, we would have: hda1: LDM database, hda2, hda3, - * and so on: the actual data containing partitions. - * - * Return: 1 Success, @bdev is a dynamic disk and we handled it - * 0 Success, @bdev is not a dynamic disk - * -1 An error occurred before enough information had been read - * Or @bdev is a dynamic disk, but it may be corrupted - */ -int ldm_partition (struct parsed_partitions *pp, struct block_device *bdev) -{ - struct ldmdb *ldb; - unsigned long base; - int result = -1; - - BUG_ON (!pp || !bdev); - - /* Look for signs of a Dynamic Disk */ - if (!ldm_validate_partition_table (bdev)) - return 0; - - ldb = kmalloc (sizeof (*ldb), GFP_KERNEL); - if (!ldb) { - ldm_crit ("Out of memory."); - goto out; - } - - /* Parse and check privheads. */ - if (!ldm_validate_privheads (bdev, &ldb->ph)) - goto out; /* Already logged */ - - /* All further references are relative to base (database start). */ - base = ldb->ph.config_start; - - /* Parse and check tocs and vmdb. */ - if (!ldm_validate_tocblocks (bdev, base, ldb) || - !ldm_validate_vmdb (bdev, base, ldb)) - goto out; /* Already logged */ - - /* Initialize vblk lists in ldmdb struct */ - INIT_LIST_HEAD (&ldb->v_dgrp); - INIT_LIST_HEAD (&ldb->v_disk); - INIT_LIST_HEAD (&ldb->v_volu); - INIT_LIST_HEAD (&ldb->v_comp); - INIT_LIST_HEAD (&ldb->v_part); - - if (!ldm_get_vblks (bdev, base, ldb)) { - ldm_crit ("Failed to read the VBLKs from the database."); - goto cleanup; - } - - /* Finally, create the data partition devices. */ - if (ldm_create_data_partitions (pp, ldb)) { - ldm_debug ("Parsed LDM database successfully."); - result = 1; - } - /* else Already logged */ - -cleanup: - ldm_free_vblks (&ldb->v_dgrp); - ldm_free_vblks (&ldb->v_disk); - ldm_free_vblks (&ldb->v_volu); - ldm_free_vblks (&ldb->v_comp); - ldm_free_vblks (&ldb->v_part); -out: - kfree (ldb); - return result; -} diff --git a/windhoek/partitions/ldm.h b/windhoek/partitions/ldm.h deleted file mode 100644 index 30e08e80..00000000 --- a/windhoek/partitions/ldm.h +++ /dev/null @@ -1,215 +0,0 @@ -/** - * ldm - Part of the Linux-NTFS project. - * - * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org> - * Copyright (c) 2001-2007 Anton Altaparmakov - * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com> - * - * Documentation is available at http://www.linux-ntfs.org/content/view/19/37/ - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (in the main directory of the Linux-NTFS source - * in the file COPYING); if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _FS_PT_LDM_H_ -#define _FS_PT_LDM_H_ - -#include <linux/types.h> -#include <linux/list.h> -#include <linux/genhd.h> -#include <linux/fs.h> -#include <asm/unaligned.h> -#include <asm/byteorder.h> - -struct parsed_partitions; - -/* Magic numbers in CPU format. */ -#define MAGIC_VMDB 0x564D4442 /* VMDB */ -#define MAGIC_VBLK 0x56424C4B /* VBLK */ -#define MAGIC_PRIVHEAD 0x5052495648454144ULL /* PRIVHEAD */ -#define MAGIC_TOCBLOCK 0x544F43424C4F434BULL /* TOCBLOCK */ - -/* The defined vblk types. */ -#define VBLK_VOL5 0x51 /* Volume, version 5 */ -#define VBLK_CMP3 0x32 /* Component, version 3 */ -#define VBLK_PRT3 0x33 /* Partition, version 3 */ -#define VBLK_DSK3 0x34 /* Disk, version 3 */ -#define VBLK_DSK4 0x44 /* Disk, version 4 */ -#define VBLK_DGR3 0x35 /* Disk Group, version 3 */ -#define VBLK_DGR4 0x45 /* Disk Group, version 4 */ - -/* vblk flags indicating extra information will be present */ -#define VBLK_FLAG_COMP_STRIPE 0x10 -#define VBLK_FLAG_PART_INDEX 0x08 -#define VBLK_FLAG_DGR3_IDS 0x08 -#define VBLK_FLAG_DGR4_IDS 0x08 -#define VBLK_FLAG_VOLU_ID1 0x08 -#define VBLK_FLAG_VOLU_ID2 0x20 -#define VBLK_FLAG_VOLU_SIZE 0x80 -#define VBLK_FLAG_VOLU_DRIVE 0x02 - -/* size of a vblk's static parts */ -#define VBLK_SIZE_HEAD 16 -#define VBLK_SIZE_CMP3 22 /* Name and version */ -#define VBLK_SIZE_DGR3 12 -#define VBLK_SIZE_DGR4 44 -#define VBLK_SIZE_DSK3 12 -#define VBLK_SIZE_DSK4 45 -#define VBLK_SIZE_PRT3 28 -#define VBLK_SIZE_VOL5 58 - -/* component types */ -#define COMP_STRIPE 0x01 /* Stripe-set */ -#define COMP_BASIC 0x02 /* Basic disk */ -#define COMP_RAID 0x03 /* Raid-set */ - -/* Other constants. */ -#define LDM_DB_SIZE 2048 /* Size in sectors (= 1MiB). */ - -#define OFF_PRIV1 6 /* Offset of the first privhead - relative to the start of the - device in sectors */ - -/* Offsets to structures within the LDM Database in sectors. */ -#define OFF_PRIV2 1856 /* Backup private headers. */ -#define OFF_PRIV3 2047 - -#define OFF_TOCB1 1 /* Tables of contents. */ -#define OFF_TOCB2 2 -#define OFF_TOCB3 2045 -#define OFF_TOCB4 2046 - -#define OFF_VMDB 17 /* List of partitions. */ - -#define LDM_PARTITION 0x42 /* Formerly SFS (Landis). */ - -#define TOC_BITMAP1 "config" /* Names of the two defined */ -#define TOC_BITMAP2 "log" /* bitmaps in the TOCBLOCK. */ - -/* Borrowed from msdos.c */ -#define SYS_IND(p) (get_unaligned(&(p)->sys_ind)) - -struct frag { /* VBLK Fragment handling */ - struct list_head list; - u32 group; - u8 num; /* Total number of records */ - u8 rec; /* This is record number n */ - u8 map; /* Which portions are in use */ - u8 data[0]; -}; - -/* In memory LDM database structures. */ - -#define GUID_SIZE 16 - -struct privhead { /* Offsets and sizes are in sectors. */ - u16 ver_major; - u16 ver_minor; - u64 logical_disk_start; - u64 logical_disk_size; - u64 config_start; - u64 config_size; - u8 disk_id[GUID_SIZE]; -}; - -struct tocblock { /* We have exactly two bitmaps. */ - u8 bitmap1_name[16]; - u64 bitmap1_start; - u64 bitmap1_size; - u8 bitmap2_name[16]; - u64 bitmap2_start; - u64 bitmap2_size; -}; - -struct vmdb { /* VMDB: The database header */ - u16 ver_major; - u16 ver_minor; - u32 vblk_size; - u32 vblk_offset; - u32 last_vblk_seq; -}; - -struct vblk_comp { /* VBLK Component */ - u8 state[16]; - u64 parent_id; - u8 type; - u8 children; - u16 chunksize; -}; - -struct vblk_dgrp { /* VBLK Disk Group */ - u8 disk_id[64]; -}; - -struct vblk_disk { /* VBLK Disk */ - u8 disk_id[GUID_SIZE]; - u8 alt_name[128]; -}; - -struct vblk_part { /* VBLK Partition */ - u64 start; - u64 size; /* start, size and vol_off in sectors */ - u64 volume_offset; - u64 parent_id; - u64 disk_id; - u8 partnum; -}; - -struct vblk_volu { /* VBLK Volume */ - u8 volume_type[16]; - u8 volume_state[16]; - u8 guid[16]; - u8 drive_hint[4]; - u64 size; - u8 partition_type; -}; - -struct vblk_head { /* VBLK standard header */ - u32 group; - u16 rec; - u16 nrec; -}; - -struct vblk { /* Generalised VBLK */ - u8 name[64]; - u64 obj_id; - u32 sequence; - u8 flags; - u8 type; - union { - struct vblk_comp comp; - struct vblk_dgrp dgrp; - struct vblk_disk disk; - struct vblk_part part; - struct vblk_volu volu; - } vblk; - struct list_head list; -}; - -struct ldmdb { /* Cache of the database */ - struct privhead ph; - struct tocblock toc; - struct vmdb vm; - struct list_head v_dgrp; - struct list_head v_disk; - struct list_head v_volu; - struct list_head v_comp; - struct list_head v_part; -}; - -int ldm_partition (struct parsed_partitions *state, struct block_device *bdev); - -#endif /* _FS_PT_LDM_H_ */ - diff --git a/windhoek/partitions/mac.c b/windhoek/partitions/mac.c deleted file mode 100644 index d4a0fad3..00000000 --- a/windhoek/partitions/mac.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * fs/partitions/mac.c - * - * Code extracted from drivers/block/genhd.c - * Copyright (C) 1991-1998 Linus Torvalds - * Re-organised Feb 1998 Russell King - */ - -#include <linux/ctype.h> -#include "check.h" -#include "mac.h" - -#ifdef CONFIG_PPC_PMAC -#include <asm/machdep.h> -extern void note_bootable_part(dev_t dev, int part, int goodness); -#endif - -/* - * Code to understand MacOS partition tables. - */ - -static inline void mac_fix_string(char *stg, int len) -{ - int i; - - for (i = len - 1; i >= 0 && stg[i] == ' '; i--) - stg[i] = 0; -} - -int mac_partition(struct parsed_partitions *state, struct block_device *bdev) -{ - int slot = 1; - Sector sect; - unsigned char *data; - int blk, blocks_in_map; - unsigned secsize; -#ifdef CONFIG_PPC_PMAC - int found_root = 0; - int found_root_goodness = 0; -#endif - struct mac_partition *part; - struct mac_driver_desc *md; - - /* Get 0th block and look at the first partition map entry. */ - md = (struct mac_driver_desc *) read_dev_sector(bdev, 0, §); - if (!md) - return -1; - if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) { - put_dev_sector(sect); - return 0; - } - secsize = be16_to_cpu(md->block_size); - put_dev_sector(sect); - data = read_dev_sector(bdev, secsize/512, §); - if (!data) - return -1; - part = (struct mac_partition *) (data + secsize%512); - if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) { - put_dev_sector(sect); - return 0; /* not a MacOS disk */ - } - printk(" [mac]"); - blocks_in_map = be32_to_cpu(part->map_count); - for (blk = 1; blk <= blocks_in_map; ++blk) { - int pos = blk * secsize; - put_dev_sector(sect); - data = read_dev_sector(bdev, pos/512, §); - if (!data) - return -1; - part = (struct mac_partition *) (data + pos%512); - if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) - break; - put_partition(state, slot, - be32_to_cpu(part->start_block) * (secsize/512), - be32_to_cpu(part->block_count) * (secsize/512)); - - if (!strnicmp(part->type, "Linux_RAID", 10)) - state->parts[slot].flags = 1; -#ifdef CONFIG_PPC_PMAC - /* - * If this is the first bootable partition, tell the - * setup code, in case it wants to make this the root. - */ - if (machine_is(powermac)) { - int goodness = 0; - - mac_fix_string(part->processor, 16); - mac_fix_string(part->name, 32); - mac_fix_string(part->type, 32); - - if ((be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE) - && strcasecmp(part->processor, "powerpc") == 0) - goodness++; - - if (strcasecmp(part->type, "Apple_UNIX_SVR2") == 0 - || (strnicmp(part->type, "Linux", 5) == 0 - && strcasecmp(part->type, "Linux_swap") != 0)) { - int i, l; - - goodness++; - l = strlen(part->name); - if (strcmp(part->name, "/") == 0) - goodness++; - for (i = 0; i <= l - 4; ++i) { - if (strnicmp(part->name + i, "root", - 4) == 0) { - goodness += 2; - break; - } - } - if (strnicmp(part->name, "swap", 4) == 0) - goodness--; - } - - if (goodness > found_root_goodness) { - found_root = blk; - found_root_goodness = goodness; - } - } -#endif /* CONFIG_PPC_PMAC */ - - ++slot; - } -#ifdef CONFIG_PPC_PMAC - if (found_root_goodness) - note_bootable_part(bdev->bd_dev, found_root, found_root_goodness); -#endif - - put_dev_sector(sect); - printk("\n"); - return 1; -} diff --git a/windhoek/partitions/mac.h b/windhoek/partitions/mac.h deleted file mode 100644 index bbf26e13..00000000 --- a/windhoek/partitions/mac.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * fs/partitions/mac.h - */ - -#define MAC_PARTITION_MAGIC 0x504d - -/* type field value for A/UX or other Unix partitions */ -#define APPLE_AUX_TYPE "Apple_UNIX_SVR2" - -struct mac_partition { - __be16 signature; /* expected to be MAC_PARTITION_MAGIC */ - __be16 res1; - __be32 map_count; /* # blocks in partition map */ - __be32 start_block; /* absolute starting block # of partition */ - __be32 block_count; /* number of blocks in partition */ - char name[32]; /* partition name */ - char type[32]; /* string type description */ - __be32 data_start; /* rel block # of first data block */ - __be32 data_count; /* number of data blocks */ - __be32 status; /* partition status bits */ - __be32 boot_start; - __be32 boot_size; - __be32 boot_load; - __be32 boot_load2; - __be32 boot_entry; - __be32 boot_entry2; - __be32 boot_cksum; - char processor[16]; /* identifies ISA of boot */ - /* there is more stuff after this that we don't need */ -}; - -#define MAC_STATUS_BOOTABLE 8 /* partition is bootable */ - -#define MAC_DRIVER_MAGIC 0x4552 - -/* Driver descriptor structure, in block 0 */ -struct mac_driver_desc { - __be16 signature; /* expected to be MAC_DRIVER_MAGIC */ - __be16 block_size; - __be32 block_count; - /* ... more stuff */ -}; - -int mac_partition(struct parsed_partitions *state, struct block_device *bdev); diff --git a/windhoek/partitions/msdos.c b/windhoek/partitions/msdos.c deleted file mode 100644 index 79651188..00000000 --- a/windhoek/partitions/msdos.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - * fs/partitions/msdos.c - * - * Code extracted from drivers/block/genhd.c - * Copyright (C) 1991-1998 Linus Torvalds - * - * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug - * in the early extended-partition checks and added DM partitions - * - * Support for DiskManager v6.0x added by Mark Lord, - * with information provided by OnTrack. This now works for linux fdisk - * and LILO, as well as loadlin and bootln. Note that disks other than - * /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1). - * - * More flexible handling of extended partitions - aeb, 950831 - * - * Check partition table on IDE disks for common CHS translations - * - * Re-organised Feb 1998 Russell King - */ -#include <linux/msdos_fs.h> - -#include "check.h" -#include "msdos.h" -#include "efi.h" - -/* - * Many architectures don't like unaligned accesses, while - * the nr_sects and start_sect partition table entries are - * at a 2 (mod 4) address. - */ -#include <asm/unaligned.h> - -#define SYS_IND(p) (get_unaligned(&p->sys_ind)) -#define NR_SECTS(p) ({ __le32 __a = get_unaligned(&p->nr_sects); \ - le32_to_cpu(__a); \ - }) - -#define START_SECT(p) ({ __le32 __a = get_unaligned(&p->start_sect); \ - le32_to_cpu(__a); \ - }) - -static inline int is_extended_partition(struct partition *p) -{ - return (SYS_IND(p) == DOS_EXTENDED_PARTITION || - SYS_IND(p) == WIN98_EXTENDED_PARTITION || - SYS_IND(p) == LINUX_EXTENDED_PARTITION); -} - -#define MSDOS_LABEL_MAGIC1 0x55 -#define MSDOS_LABEL_MAGIC2 0xAA - -static inline int -msdos_magic_present(unsigned char *p) -{ - return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2); -} - -/* Value is EBCDIC 'IBMA' */ -#define AIX_LABEL_MAGIC1 0xC9 -#define AIX_LABEL_MAGIC2 0xC2 -#define AIX_LABEL_MAGIC3 0xD4 -#define AIX_LABEL_MAGIC4 0xC1 -static int aix_magic_present(unsigned char *p, struct block_device *bdev) -{ - struct partition *pt = (struct partition *) (p + 0x1be); - Sector sect; - unsigned char *d; - int slot, ret = 0; - - if (!(p[0] == AIX_LABEL_MAGIC1 && - p[1] == AIX_LABEL_MAGIC2 && - p[2] == AIX_LABEL_MAGIC3 && - p[3] == AIX_LABEL_MAGIC4)) - return 0; - /* Assume the partition table is valid if Linux partitions exists */ - for (slot = 1; slot <= 4; slot++, pt++) { - if (pt->sys_ind == LINUX_SWAP_PARTITION || - pt->sys_ind == LINUX_RAID_PARTITION || - pt->sys_ind == LINUX_DATA_PARTITION || - pt->sys_ind == LINUX_LVM_PARTITION || - is_extended_partition(pt)) - return 0; - } - d = read_dev_sector(bdev, 7, §); - if (d) { - if (d[0] == '_' && d[1] == 'L' && d[2] == 'V' && d[3] == 'M') - ret = 1; - put_dev_sector(sect); - }; - return ret; -} - -/* - * Create devices for each logical partition in an extended partition. - * The logical partitions form a linked list, with each entry being - * a partition table with two entries. The first entry - * is the real data partition (with a start relative to the partition - * table start). The second is a pointer to the next logical partition - * (with a start relative to the entire extended partition). - * We do not create a Linux partition for the partition tables, but - * only for the actual data partitions. - */ - -static void -parse_extended(struct parsed_partitions *state, struct block_device *bdev, - u32 first_sector, u32 first_size) -{ - struct partition *p; - Sector sect; - unsigned char *data; - u32 this_sector, this_size; - int sector_size = bdev_hardsect_size(bdev) / 512; - int loopct = 0; /* number of links followed - without finding a data partition */ - int i; - - this_sector = first_sector; - this_size = first_size; - - while (1) { - if (++loopct > 100) - return; - if (state->next == state->limit) - return; - data = read_dev_sector(bdev, this_sector, §); - if (!data) - return; - - if (!msdos_magic_present(data + 510)) - goto done; - - p = (struct partition *) (data + 0x1be); - - /* - * Usually, the first entry is the real data partition, - * the 2nd entry is the next extended partition, or empty, - * and the 3rd and 4th entries are unused. - * However, DRDOS sometimes has the extended partition as - * the first entry (when the data partition is empty), - * and OS/2 seems to use all four entries. - */ - - /* - * First process the data partition(s) - */ - for (i=0; i<4; i++, p++) { - u32 offs, size, next; - if (!NR_SECTS(p) || is_extended_partition(p)) - continue; - - /* Check the 3rd and 4th entries - - these sometimes contain random garbage */ - offs = START_SECT(p)*sector_size; - size = NR_SECTS(p)*sector_size; - next = this_sector + offs; - if (i >= 2) { - if (offs + size > this_size) - continue; - if (next < first_sector) - continue; - if (next + size > first_sector + first_size) - continue; - } - - put_partition(state, state->next, next, size); - if (SYS_IND(p) == LINUX_RAID_PARTITION) - state->parts[state->next].flags = ADDPART_FLAG_RAID; - loopct = 0; - if (++state->next == state->limit) - goto done; - } - /* - * Next, process the (first) extended partition, if present. - * (So far, there seems to be no reason to make - * parse_extended() recursive and allow a tree - * of extended partitions.) - * It should be a link to the next logical partition. - */ - p -= 4; - for (i=0; i<4; i++, p++) - if (NR_SECTS(p) && is_extended_partition(p)) - break; - if (i == 4) - goto done; /* nothing left to do */ - - this_sector = first_sector + START_SECT(p) * sector_size; - this_size = NR_SECTS(p) * sector_size; - put_dev_sector(sect); - } -done: - put_dev_sector(sect); -} - -/* james@bpgc.com: Solaris has a nasty indicator: 0x82 which also - indicates linux swap. Be careful before believing this is Solaris. */ - -static void -parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev, - u32 offset, u32 size, int origin) -{ -#ifdef CONFIG_SOLARIS_X86_PARTITION - Sector sect; - struct solaris_x86_vtoc *v; - int i; - short max_nparts; - - v = (struct solaris_x86_vtoc *)read_dev_sector(bdev, offset+1, §); - if (!v) - return; - if (le32_to_cpu(v->v_sanity) != SOLARIS_X86_VTOC_SANE) { - put_dev_sector(sect); - return; - } - printk(" %s%d: <solaris:", state->name, origin); - if (le32_to_cpu(v->v_version) != 1) { - printk(" cannot handle version %d vtoc>\n", - le32_to_cpu(v->v_version)); - put_dev_sector(sect); - return; - } - /* Ensure we can handle previous case of VTOC with 8 entries gracefully */ - max_nparts = le16_to_cpu (v->v_nparts) > 8 ? SOLARIS_X86_NUMSLICE : 8; - for (i=0; i<max_nparts && state->next<state->limit; i++) { - struct solaris_x86_slice *s = &v->v_slice[i]; - if (s->s_size == 0) - continue; - printk(" [s%d]", i); - /* solaris partitions are relative to current MS-DOS - * one; must add the offset of the current partition */ - put_partition(state, state->next++, - le32_to_cpu(s->s_start)+offset, - le32_to_cpu(s->s_size)); - } - put_dev_sector(sect); - printk(" >\n"); -#endif -} - -#if defined(CONFIG_BSD_DISKLABEL) -/* - * Create devices for BSD partitions listed in a disklabel, under a - * dos-like partition. See parse_extended() for more information. - */ -static void -parse_bsd(struct parsed_partitions *state, struct block_device *bdev, - u32 offset, u32 size, int origin, char *flavour, - int max_partitions) -{ - Sector sect; - struct bsd_disklabel *l; - struct bsd_partition *p; - - l = (struct bsd_disklabel *)read_dev_sector(bdev, offset+1, §); - if (!l) - return; - if (le32_to_cpu(l->d_magic) != BSD_DISKMAGIC) { - put_dev_sector(sect); - return; - } - printk(" %s%d: <%s:", state->name, origin, flavour); - - if (le16_to_cpu(l->d_npartitions) < max_partitions) - max_partitions = le16_to_cpu(l->d_npartitions); - for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) { - u32 bsd_start, bsd_size; - - if (state->next == state->limit) - break; - if (p->p_fstype == BSD_FS_UNUSED) - continue; - bsd_start = le32_to_cpu(p->p_offset); - bsd_size = le32_to_cpu(p->p_size); - if (offset == bsd_start && size == bsd_size) - /* full parent partition, we have it already */ - continue; - if (offset > bsd_start || offset+size < bsd_start+bsd_size) { - printk("bad subpartition - ignored\n"); - continue; - } - put_partition(state, state->next++, bsd_start, bsd_size); - } - put_dev_sector(sect); - if (le16_to_cpu(l->d_npartitions) > max_partitions) - printk(" (ignored %d more)", - le16_to_cpu(l->d_npartitions) - max_partitions); - printk(" >\n"); -} -#endif - -static void -parse_freebsd(struct parsed_partitions *state, struct block_device *bdev, - u32 offset, u32 size, int origin) -{ -#ifdef CONFIG_BSD_DISKLABEL - parse_bsd(state, bdev, offset, size, origin, - "bsd", BSD_MAXPARTITIONS); -#endif -} - -static void -parse_netbsd(struct parsed_partitions *state, struct block_device *bdev, - u32 offset, u32 size, int origin) -{ -#ifdef CONFIG_BSD_DISKLABEL - parse_bsd(state, bdev, offset, size, origin, - "netbsd", BSD_MAXPARTITIONS); -#endif -} - -static void -parse_openbsd(struct parsed_partitions *state, struct block_device *bdev, - u32 offset, u32 size, int origin) -{ -#ifdef CONFIG_BSD_DISKLABEL - parse_bsd(state, bdev, offset, size, origin, - "openbsd", OPENBSD_MAXPARTITIONS); -#endif -} - -/* - * Create devices for Unixware partitions listed in a disklabel, under a - * dos-like partition. See parse_extended() for more information. - */ -static void -parse_unixware(struct parsed_partitions *state, struct block_device *bdev, - u32 offset, u32 size, int origin) -{ -#ifdef CONFIG_UNIXWARE_DISKLABEL - Sector sect; - struct unixware_disklabel *l; - struct unixware_slice *p; - - l = (struct unixware_disklabel *)read_dev_sector(bdev, offset+29, §); - if (!l) - return; - if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC || - le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) { - put_dev_sector(sect); - return; - } - printk(" %s%d: <unixware:", state->name, origin); - p = &l->vtoc.v_slice[1]; - /* I omit the 0th slice as it is the same as whole disk. */ - while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) { - if (state->next == state->limit) - break; - - if (p->s_label != UNIXWARE_FS_UNUSED) - put_partition(state, state->next++, - START_SECT(p), NR_SECTS(p)); - p++; - } - put_dev_sector(sect); - printk(" >\n"); -#endif -} - -/* - * Minix 2.0.0/2.0.2 subpartition support. - * Anand Krishnamurthy <anandk@wiproge.med.ge.com> - * Rajeev V. Pillai <rajeevvp@yahoo.com> - */ -static void -parse_minix(struct parsed_partitions *state, struct block_device *bdev, - u32 offset, u32 size, int origin) -{ -#ifdef CONFIG_MINIX_SUBPARTITION - Sector sect; - unsigned char *data; - struct partition *p; - int i; - - data = read_dev_sector(bdev, offset, §); - if (!data) - return; - - p = (struct partition *)(data + 0x1be); - - /* The first sector of a Minix partition can have either - * a secondary MBR describing its subpartitions, or - * the normal boot sector. */ - if (msdos_magic_present (data + 510) && - SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */ - - printk(" %s%d: <minix:", state->name, origin); - for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) { - if (state->next == state->limit) - break; - /* add each partition in use */ - if (SYS_IND(p) == MINIX_PARTITION) - put_partition(state, state->next++, - START_SECT(p), NR_SECTS(p)); - } - printk(" >\n"); - } - put_dev_sector(sect); -#endif /* CONFIG_MINIX_SUBPARTITION */ -} - -static struct { - unsigned char id; - void (*parse)(struct parsed_partitions *, struct block_device *, - u32, u32, int); -} subtypes[] = { - {FREEBSD_PARTITION, parse_freebsd}, - {NETBSD_PARTITION, parse_netbsd}, - {OPENBSD_PARTITION, parse_openbsd}, - {MINIX_PARTITION, parse_minix}, - {UNIXWARE_PARTITION, parse_unixware}, - {SOLARIS_X86_PARTITION, parse_solaris_x86}, - {NEW_SOLARIS_X86_PARTITION, parse_solaris_x86}, - {0, NULL}, -}; - -int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) -{ - int sector_size = bdev_hardsect_size(bdev) / 512; - Sector sect; - unsigned char *data; - struct partition *p; - struct fat_boot_sector *fb; - int slot; - - data = read_dev_sector(bdev, 0, §); - if (!data) - return -1; - if (!msdos_magic_present(data + 510)) { - put_dev_sector(sect); - return 0; - } - - if (aix_magic_present(data, bdev)) { - put_dev_sector(sect); - printk( " [AIX]"); - return 0; - } - - /* - * Now that the 55aa signature is present, this is probably - * either the boot sector of a FAT filesystem or a DOS-type - * partition table. Reject this in case the boot indicator - * is not 0 or 0x80. - */ - p = (struct partition *) (data + 0x1be); - for (slot = 1; slot <= 4; slot++, p++) { - if (p->boot_ind != 0 && p->boot_ind != 0x80) { - /* - * Even without a valid boot inidicator value - * its still possible this is valid FAT filesystem - * without a partition table. - */ - fb = (struct fat_boot_sector *) data; - if (slot == 1 && fb->reserved && fb->fats - && fat_valid_media(fb->media)) { - printk("\n"); - put_dev_sector(sect); - return 1; - } else { - put_dev_sector(sect); - return 0; - } - } - } - -#ifdef CONFIG_EFI_PARTITION - p = (struct partition *) (data + 0x1be); - for (slot = 1 ; slot <= 4 ; slot++, p++) { - /* If this is an EFI GPT disk, msdos should ignore it. */ - if (SYS_IND(p) == EFI_PMBR_OSTYPE_EFI_GPT) { - put_dev_sector(sect); - return 0; - } - } -#endif - p = (struct partition *) (data + 0x1be); - - /* - * Look for partitions in two passes: - * First find the primary and DOS-type extended partitions. - * On the second pass look inside *BSD, Unixware and Solaris partitions. - */ - - state->next = 5; - for (slot = 1 ; slot <= 4 ; slot++, p++) { - u32 start = START_SECT(p)*sector_size; - u32 size = NR_SECTS(p)*sector_size; - if (!size) - continue; - if (is_extended_partition(p)) { - /* prevent someone doing mkfs or mkswap on an - extended partition, but leave room for LILO */ - put_partition(state, slot, start, size == 1 ? 1 : 2); - printk(" <"); - parse_extended(state, bdev, start, size); - printk(" >"); - continue; - } - put_partition(state, slot, start, size); - if (SYS_IND(p) == LINUX_RAID_PARTITION) - state->parts[slot].flags = 1; - if (SYS_IND(p) == DM6_PARTITION) - printk("[DM]"); - if (SYS_IND(p) == EZD_PARTITION) - printk("[EZD]"); - } - - printk("\n"); - - /* second pass - output for each on a separate line */ - p = (struct partition *) (0x1be + data); - for (slot = 1 ; slot <= 4 ; slot++, p++) { - unsigned char id = SYS_IND(p); - int n; - - if (!NR_SECTS(p)) - continue; - - for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++) - ; - - if (!subtypes[n].parse) - continue; - subtypes[n].parse(state, bdev, START_SECT(p)*sector_size, - NR_SECTS(p)*sector_size, slot); - } - put_dev_sector(sect); - return 1; -} diff --git a/windhoek/partitions/msdos.h b/windhoek/partitions/msdos.h deleted file mode 100644 index 01e5e0b6..00000000 --- a/windhoek/partitions/msdos.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * fs/partitions/msdos.h - */ - -#define MSDOS_LABEL_MAGIC 0xAA55 - -int msdos_partition(struct parsed_partitions *state, struct block_device *bdev); - diff --git a/windhoek/partitions/osf.c b/windhoek/partitions/osf.c deleted file mode 100644 index c05c17bc..00000000 --- a/windhoek/partitions/osf.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * fs/partitions/osf.c - * - * Code extracted from drivers/block/genhd.c - * - * Copyright (C) 1991-1998 Linus Torvalds - * Re-organised Feb 1998 Russell King - */ - -#include "check.h" -#include "osf.h" - -int osf_partition(struct parsed_partitions *state, struct block_device *bdev) -{ - int i; - int slot = 1; - Sector sect; - unsigned char *data; - struct disklabel { - __le32 d_magic; - __le16 d_type,d_subtype; - u8 d_typename[16]; - u8 d_packname[16]; - __le32 d_secsize; - __le32 d_nsectors; - __le32 d_ntracks; - __le32 d_ncylinders; - __le32 d_secpercyl; - __le32 d_secprtunit; - __le16 d_sparespertrack; - __le16 d_sparespercyl; - __le32 d_acylinders; - __le16 d_rpm, d_interleave, d_trackskew, d_cylskew; - __le32 d_headswitch, d_trkseek, d_flags; - __le32 d_drivedata[5]; - __le32 d_spare[5]; - __le32 d_magic2; - __le16 d_checksum; - __le16 d_npartitions; - __le32 d_bbsize, d_sbsize; - struct d_partition { - __le32 p_size; - __le32 p_offset; - __le32 p_fsize; - u8 p_fstype; - u8 p_frag; - __le16 p_cpg; - } d_partitions[8]; - } * label; - struct d_partition * partition; - - data = read_dev_sector(bdev, 0, §); - if (!data) - return -1; - - label = (struct disklabel *) (data+64); - partition = label->d_partitions; - if (le32_to_cpu(label->d_magic) != DISKLABELMAGIC) { - put_dev_sector(sect); - return 0; - } - if (le32_to_cpu(label->d_magic2) != DISKLABELMAGIC) { - put_dev_sector(sect); - return 0; - } - for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) { - if (slot == state->limit) - break; - if (le32_to_cpu(partition->p_size)) - put_partition(state, slot, - le32_to_cpu(partition->p_offset), - le32_to_cpu(partition->p_size)); - slot++; - } - printk("\n"); - put_dev_sector(sect); - return 1; -} diff --git a/windhoek/partitions/osf.h b/windhoek/partitions/osf.h deleted file mode 100644 index 427b8eab..00000000 --- a/windhoek/partitions/osf.h +++ /dev/null @@ -1,7 +0,0 @@ -/* - * fs/partitions/osf.h - */ - -#define DISKLABELMAGIC (0x82564557UL) - -int osf_partition(struct parsed_partitions *state, struct block_device *bdev); diff --git a/windhoek/partitions/sgi.c b/windhoek/partitions/sgi.c deleted file mode 100644 index ed5ac83f..00000000 --- a/windhoek/partitions/sgi.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * fs/partitions/sgi.c - * - * Code extracted from drivers/block/genhd.c - */ - -#include "check.h" -#include "sgi.h" - -struct sgi_disklabel { - __be32 magic_mushroom; /* Big fat spliff... */ - __be16 root_part_num; /* Root partition number */ - __be16 swap_part_num; /* Swap partition number */ - s8 boot_file[16]; /* Name of boot file for ARCS */ - u8 _unused0[48]; /* Device parameter useless crapola.. */ - struct sgi_volume { - s8 name[8]; /* Name of volume */ - __be32 block_num; /* Logical block number */ - __be32 num_bytes; /* How big, in bytes */ - } volume[15]; - struct sgi_partition { - __be32 num_blocks; /* Size in logical blocks */ - __be32 first_block; /* First logical block */ - __be32 type; /* Type of this partition */ - } partitions[16]; - __be32 csum; /* Disk label checksum */ - __be32 _unused1; /* Padding */ -}; - -int sgi_partition(struct parsed_partitions *state, struct block_device *bdev) -{ - int i, csum; - __be32 magic; - int slot = 1; - unsigned int start, blocks; - __be32 *ui, cs; - Sector sect; - struct sgi_disklabel *label; - struct sgi_partition *p; - char b[BDEVNAME_SIZE]; - - label = (struct sgi_disklabel *) read_dev_sector(bdev, 0, §); - if (!label) - return -1; - p = &label->partitions[0]; - magic = label->magic_mushroom; - if(be32_to_cpu(magic) != SGI_LABEL_MAGIC) { - /*printk("Dev %s SGI disklabel: bad magic %08x\n", - bdevname(bdev, b), be32_to_cpu(magic));*/ - put_dev_sector(sect); - return 0; - } - ui = ((__be32 *) (label + 1)) - 1; - for(csum = 0; ui >= ((__be32 *) label);) { - cs = *ui--; - csum += be32_to_cpu(cs); - } - if(csum) { - printk(KERN_WARNING "Dev %s SGI disklabel: csum bad, label corrupted\n", - bdevname(bdev, b)); - put_dev_sector(sect); - return 0; - } - /* All SGI disk labels have 16 partitions, disks under Linux only - * have 15 minor's. Luckily there are always a few zero length - * partitions which we don't care about so we never overflow the - * current_minor. - */ - for(i = 0; i < 16; i++, p++) { - blocks = be32_to_cpu(p->num_blocks); - start = be32_to_cpu(p->first_block); - if (blocks) { - put_partition(state, slot, start, blocks); - if (be32_to_cpu(p->type) == LINUX_RAID_PARTITION) - state->parts[slot].flags = ADDPART_FLAG_RAID; - } - slot++; - } - printk("\n"); - put_dev_sector(sect); - return 1; -} diff --git a/windhoek/partitions/sgi.h b/windhoek/partitions/sgi.h deleted file mode 100644 index 5d5595c0..00000000 --- a/windhoek/partitions/sgi.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * fs/partitions/sgi.h - */ - -extern int sgi_partition(struct parsed_partitions *state, struct block_device *bdev); - -#define SGI_LABEL_MAGIC 0x0be5a941 - diff --git a/windhoek/partitions/sun.c b/windhoek/partitions/sun.c deleted file mode 100644 index c95e6a62..00000000 --- a/windhoek/partitions/sun.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * fs/partitions/sun.c - * - * Code extracted from drivers/block/genhd.c - * - * Copyright (C) 1991-1998 Linus Torvalds - * Re-organised Feb 1998 Russell King - */ - -#include "check.h" -#include "sun.h" - -int sun_partition(struct parsed_partitions *state, struct block_device *bdev) -{ - int i; - __be16 csum; - int slot = 1; - __be16 *ush; - Sector sect; - struct sun_disklabel { - unsigned char info[128]; /* Informative text string */ - struct sun_vtoc { - __be32 version; /* Layout version */ - char volume[8]; /* Volume name */ - __be16 nparts; /* Number of partitions */ - struct sun_info { /* Partition hdrs, sec 2 */ - __be16 id; - __be16 flags; - } infos[8]; - __be16 padding; /* Alignment padding */ - __be32 bootinfo[3]; /* Info needed by mboot */ - __be32 sanity; /* To verify vtoc sanity */ - __be32 reserved[10]; /* Free space */ - __be32 timestamp[8]; /* Partition timestamp */ - } vtoc; - __be32 write_reinstruct; /* sectors to skip, writes */ - __be32 read_reinstruct; /* sectors to skip, reads */ - unsigned char spare[148]; /* Padding */ - __be16 rspeed; /* Disk rotational speed */ - __be16 pcylcount; /* Physical cylinder count */ - __be16 sparecyl; /* extra sects per cylinder */ - __be16 obs1; /* gap1 */ - __be16 obs2; /* gap2 */ - __be16 ilfact; /* Interleave factor */ - __be16 ncyl; /* Data cylinder count */ - __be16 nacyl; /* Alt. cylinder count */ - __be16 ntrks; /* Tracks per cylinder */ - __be16 nsect; /* Sectors per track */ - __be16 obs3; /* bhead - Label head offset */ - __be16 obs4; /* ppart - Physical Partition */ - struct sun_partition { - __be32 start_cylinder; - __be32 num_sectors; - } partitions[8]; - __be16 magic; /* Magic number */ - __be16 csum; /* Label xor'd checksum */ - } * label; - struct sun_partition *p; - unsigned long spc; - char b[BDEVNAME_SIZE]; - int use_vtoc; - int nparts; - - label = (struct sun_disklabel *)read_dev_sector(bdev, 0, §); - if (!label) - return -1; - - p = label->partitions; - if (be16_to_cpu(label->magic) != SUN_LABEL_MAGIC) { -/* printk(KERN_INFO "Dev %s Sun disklabel: bad magic %04x\n", - bdevname(bdev, b), be16_to_cpu(label->magic)); */ - put_dev_sector(sect); - return 0; - } - /* Look at the checksum */ - ush = ((__be16 *) (label+1)) - 1; - for (csum = 0; ush >= ((__be16 *) label);) - csum ^= *ush--; - if (csum) { - printk("Dev %s Sun disklabel: Csum bad, label corrupted\n", - bdevname(bdev, b)); - put_dev_sector(sect); - return 0; - } - - /* Check to see if we can use the VTOC table */ - use_vtoc = ((be32_to_cpu(label->vtoc.sanity) == SUN_VTOC_SANITY) && - (be32_to_cpu(label->vtoc.version) == 1) && - (be16_to_cpu(label->vtoc.nparts) <= 8)); - - /* Use 8 partition entries if not specified in validated VTOC */ - nparts = (use_vtoc) ? be16_to_cpu(label->vtoc.nparts) : 8; - - /* - * So that old Linux-Sun partitions continue to work, - * alow the VTOC to be used under the additional condition ... - */ - use_vtoc = use_vtoc || !(label->vtoc.sanity || - label->vtoc.version || label->vtoc.nparts); - spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect); - for (i = 0; i < nparts; i++, p++) { - unsigned long st_sector; - unsigned int num_sectors; - - st_sector = be32_to_cpu(p->start_cylinder) * spc; - num_sectors = be32_to_cpu(p->num_sectors); - if (num_sectors) { - put_partition(state, slot, st_sector, num_sectors); - state->parts[slot].flags = 0; - if (use_vtoc) { - if (be16_to_cpu(label->vtoc.infos[i].id) == LINUX_RAID_PARTITION) - state->parts[slot].flags |= ADDPART_FLAG_RAID; - else if (be16_to_cpu(label->vtoc.infos[i].id) == SUN_WHOLE_DISK) - state->parts[slot].flags |= ADDPART_FLAG_WHOLEDISK; - } - } - slot++; - } - printk("\n"); - put_dev_sector(sect); - return 1; -} diff --git a/windhoek/partitions/sun.h b/windhoek/partitions/sun.h deleted file mode 100644 index 7f864d1f..00000000 --- a/windhoek/partitions/sun.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * fs/partitions/sun.h - */ - -#define SUN_LABEL_MAGIC 0xDABE -#define SUN_VTOC_SANITY 0x600DDEEE - -int sun_partition(struct parsed_partitions *state, struct block_device *bdev); diff --git a/windhoek/partitions/sysv68.c b/windhoek/partitions/sysv68.c deleted file mode 100644 index 4eba27b7..00000000 --- a/windhoek/partitions/sysv68.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * fs/partitions/sysv68.c - * - * Copyright (C) 2007 Philippe De Muyter <phdm@macqel.be> - */ - -#include "check.h" -#include "sysv68.h" - -/* - * Volume ID structure: on first 256-bytes sector of disk - */ - -struct volumeid { - u8 vid_unused[248]; - u8 vid_mac[8]; /* ASCII string "MOTOROLA" */ -}; - -/* - * config block: second 256-bytes sector on disk - */ - -struct dkconfig { - u8 ios_unused0[128]; - __be32 ios_slcblk; /* Slice table block number */ - __be16 ios_slccnt; /* Number of entries in slice table */ - u8 ios_unused1[122]; -}; - -/* - * combined volumeid and dkconfig block - */ - -struct dkblk0 { - struct volumeid dk_vid; - struct dkconfig dk_ios; -}; - -/* - * Slice Table Structure - */ - -struct slice { - __be32 nblocks; /* slice size (in blocks) */ - __be32 blkoff; /* block offset of slice */ -}; - - -int sysv68_partition(struct parsed_partitions *state, struct block_device *bdev) -{ - int i, slices; - int slot = 1; - Sector sect; - unsigned char *data; - struct dkblk0 *b; - struct slice *slice; - - data = read_dev_sector(bdev, 0, §); - if (!data) - return -1; - - b = (struct dkblk0 *)data; - if (memcmp(b->dk_vid.vid_mac, "MOTOROLA", sizeof(b->dk_vid.vid_mac))) { - put_dev_sector(sect); - return 0; - } - slices = be16_to_cpu(b->dk_ios.ios_slccnt); - i = be32_to_cpu(b->dk_ios.ios_slcblk); - put_dev_sector(sect); - - data = read_dev_sector(bdev, i, §); - if (!data) - return -1; - - slices -= 1; /* last slice is the whole disk */ - printk("sysV68: %s(s%u)", state->name, slices); - slice = (struct slice *)data; - for (i = 0; i < slices; i++, slice++) { - if (slot == state->limit) - break; - if (be32_to_cpu(slice->nblocks)) { - put_partition(state, slot, - be32_to_cpu(slice->blkoff), - be32_to_cpu(slice->nblocks)); - printk("(s%u)", i); - } - slot++; - } - printk("\n"); - put_dev_sector(sect); - return 1; -} diff --git a/windhoek/partitions/sysv68.h b/windhoek/partitions/sysv68.h deleted file mode 100644 index fa733f68..00000000 --- a/windhoek/partitions/sysv68.h +++ /dev/null @@ -1 +0,0 @@ -extern int sysv68_partition(struct parsed_partitions *state, struct block_device *bdev); diff --git a/windhoek/partitions/ultrix.c b/windhoek/partitions/ultrix.c deleted file mode 100644 index ec852c11..00000000 --- a/windhoek/partitions/ultrix.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * fs/partitions/ultrix.c - * - * Code extracted from drivers/block/genhd.c - * - * Re-organised Jul 1999 Russell King - */ - -#include "check.h" -#include "ultrix.h" - -int ultrix_partition(struct parsed_partitions *state, struct block_device *bdev) -{ - int i; - Sector sect; - unsigned char *data; - struct ultrix_disklabel { - s32 pt_magic; /* magic no. indicating part. info exits */ - s32 pt_valid; /* set by driver if pt is current */ - struct pt_info { - s32 pi_nblocks; /* no. of sectors */ - u32 pi_blkoff; /* block offset for start */ - } pt_part[8]; - } *label; - -#define PT_MAGIC 0x032957 /* Partition magic number */ -#define PT_VALID 1 /* Indicates if struct is valid */ - - data = read_dev_sector(bdev, (16384 - sizeof(*label))/512, §); - if (!data) - return -1; - - label = (struct ultrix_disklabel *)(data + 512 - sizeof(*label)); - - if (label->pt_magic == PT_MAGIC && label->pt_valid == PT_VALID) { - for (i=0; i<8; i++) - if (label->pt_part[i].pi_nblocks) - put_partition(state, i+1, - label->pt_part[i].pi_blkoff, - label->pt_part[i].pi_nblocks); - put_dev_sector(sect); - printk ("\n"); - return 1; - } else { - put_dev_sector(sect); - return 0; - } -} diff --git a/windhoek/partitions/ultrix.h b/windhoek/partitions/ultrix.h deleted file mode 100644 index a74bf8e2..00000000 --- a/windhoek/partitions/ultrix.h +++ /dev/null @@ -1,5 +0,0 @@ -/* - * fs/partitions/ultrix.h - */ - -int ultrix_partition(struct parsed_partitions *state, struct block_device *bdev); |