From 0c843940f9bd30b1f5325973947eb40b62e301f8 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Sat, 11 Jul 2009 10:40:39 +0200 Subject: Switch to the new ChangeLog style. * ChangeLog: Wipe out content, and add instructions about how to get it back. * auth/ChangeLog: Remove file. * benchmarks/ChangeLog: Likewise. * boot/ChangeLog: Likewise. * bsdfsck/ChangeLog: Likewise. * config/ChangeLog: Likewise. * console-client/ChangeLog: Likewise. * console/ChangeLog: Likewise. * daemons/ChangeLog: Likewise. * defpager/ChangeLog: Likewise. * doc/ChangeLog: Likewise. * exec/ChangeLog: Likewise. * ext2fs/ChangeLog: Likewise. * fatfs/ChangeLog: Likewise. * fstests/ChangeLog: Likewise. * ftpfs/ChangeLog: Likewise. * hostmux/ChangeLog: Likewise. * hurd/ChangeLog: Likewise. * include/ChangeLog: Likewise. * init/ChangeLog: Likewise. * isofs/ChangeLog: Likewise. * libcons/ChangeLog: Likewise. * libdirmgt/ChangeLog: Likewise. * libdiskfs/ChangeLog: Likewise. * libfshelp/ChangeLog: Likewise. * libftpconn/ChangeLog: Likewise. * libhurdbugaddr/ChangeLog: Likewise. * libihash/ChangeLog: Likewise. * libiohelp/ChangeLog: Likewise. * libnetfs/ChangeLog: Likewise. * libpager/ChangeLog: Likewise. * libpipe/ChangeLog: Likewise. * libports/ChangeLog: Likewise. * libps/ChangeLog: Likewise. * libshouldbeinlibc/ChangeLog: Likewise. * libstore/ChangeLog: Likewise. * libthreads/ChangeLog: Likewise. * libtrivfs/ChangeLog: Likewise. * login/ChangeLog: Likewise. * mach-defpager/ChangeLog: Likewise. * nfs/ChangeLog: Likewise. * nfsd/ChangeLog: Likewise. * pfinet/ChangeLog: Likewise. * pflocal/ChangeLog: Likewise. * proc/ChangeLog: Likewise. * release/ChangeLog: Likewise. * serverboot/ChangeLog: Likewise. * storeio/ChangeLog: Likewise. * sutils/ChangeLog: Likewise. * term/ChangeLog: Likewise. * tmpfs/ChangeLog: Likewise. * trans/ChangeLog: Likewise. * ufs-fsck/ChangeLog: Likewise. * ufs-utils/ChangeLog: Likewise. * ufs/ChangeLog: Likewise. * usermux/ChangeLog: Likewise. * utils/ChangeLog: Likewise. --- bsdfsck/ChangeLog | 98 --- serverboot/ChangeLog | 473 ------------ ufs-fsck/ChangeLog | 326 -------- ufs-utils/ChangeLog | 167 ----- ufs/ChangeLog | 2012 -------------------------------------------------- 5 files changed, 3076 deletions(-) delete mode 100644 bsdfsck/ChangeLog delete mode 100644 serverboot/ChangeLog delete mode 100644 ufs-fsck/ChangeLog delete mode 100644 ufs-utils/ChangeLog delete mode 100644 ufs/ChangeLog diff --git a/bsdfsck/ChangeLog b/bsdfsck/ChangeLog deleted file mode 100644 index 0a948518..00000000 --- a/bsdfsck/ChangeLog +++ /dev/null @@ -1,98 +0,0 @@ -Thu Jul 6 15:30:43 1995 Michael I Bushnell - - * Makefile (tables.o): Delete target. - (vpath tables.c): Tell where to find tables.c. - - * Makefile: Removed dependencies that are now automatically - generated. - -Thu Nov 3 17:18:35 1994 Michael I Bushnell - - * Makefile (dir): Changed to bsdfsck. - (target): Changed to bsdfsck. - -Thu Oct 6 13:19:25 1994 Michael I Bushnell - - * dir.c (dircheck): Fix from Charles Hannum: dircheck() shouldn't - be looking at d_type or d_namlen in blank entries *at all*. Not - only is it wrong, but it causes a serious problem on little-endian - machines, since after -c2 conversion, d_type will often be > 15. - -Wed Oct 5 12:53:45 1994 Michael I Bushnell - - * pass1.c (checkinode) [mode == 0]: Check that di_trans - is also clear here. - - * fsck.h (IFTODT): Provide macro here. - * inode.c: Not here. - -Tue Oct 4 22:42:54 1994 Michael I Bushnell - - * inode.c (ckinode) [dino.di_trans set]: Only call IDESC->id_func - if IDESC->id_type is ADDR (meaning call function for each block). - If it's DATA, then that means call dirscan on each data block, - something entirely different. - - * inode.c (IFTODT): Provide macro. - -Fri Sep 30 21:28:57 1994 Roland McGrath - - * Makefile (LCLHDRS): Define. - -Fri Sep 16 10:57:04 1994 Michael I Bushnell - - * fsck.h (direct): Define macro. - -Thu Sep 1 14:51:23 1994 Michael I Bushnell - - * inode.c (ckinode): Don't pay attention to fs_maxsymlinklen - if it's -1. - * pass1.c (checkinode): Likewise. - - * fsck.h (DI_MODE): Use | not & for bitwise disjunction. - -Fri Aug 26 12:35:21 1994 Michael I Bushnell - - * main.c (main): Don't call checkblock. - - * pass5.c (ffs_fragacct): Copy in function from ../ufs/subr.c. - - * inode.c (ckinode): Call IDESC->id_func for passive translator - if it's set. - -Thu Aug 25 11:07:05 1994 Michael I Bushnell - - * setup.c: Don't include . - (setup): Comment out variable LP and label fetching code. - (calcsb, getdisklabel): Comment out functions. Replace - calcsb with one returning constant zero. - - * main.c: Don't include or . - (main): Don't run checkfstab; just print an error in that case. - (docheck): Comment out this function. - (checkfilesys): Comment out special code for HOTROOT. - -Wed Aug 24 11:11:23 1994 Michael I Bushnell - - * fsck.h (NBBY): Define macro. - -Tue Aug 23 15:54:49 1994 Michael I Bushnell - - * dir.c (fileerror): Use DI_MODE instead of di_mode member. - (adjust): Likewise. - (linkup): Likewise. - * inode.c (ckinode): Likewise. - (clri): Likewise. - (pinode): Likewise. - * pass1.c (checkinode): Likewise. - * pass2.c (pass2check): Likewise. - * utilities.c (ftypeok): Likewise. - - * inode.c (allocino): Set di_model and di_modeh instead of di_mode. - * pass1.c (checkinode): Likewise. - * pass2.c (pass2): Likewise. - - * fsck.h (DIRSIZ): Replace ufs version with old BSD version. - (struct dirtemplate, struct odirtemplate): Proved old BSD types. - (DEV_BSIZE, MAXPATHLEN): Provide definitions. - (DI_MODE): New macro. diff --git a/serverboot/ChangeLog b/serverboot/ChangeLog deleted file mode 100644 index 8dc836cc..00000000 --- a/serverboot/ChangeLog +++ /dev/null @@ -1,473 +0,0 @@ -2007-06-06 Thomas Schwinge - - * default_pager.c (default_pager_object_create, default_pager_info) - (default_pager_objects, default_pager_object_pages) - (default_pager_object_set_size, default_pager_paging_file): Rename to - `S_default_pager_object_create', `S_default_pager_info', - `S_default_pager_objects', `S_default_pager_object_pages', - `S_default_pager_object_set_size' and `S_default_pager_paging_file'. - -2006-03-15 Alfred M. Szmidt - - * kalloc.c: #include . - (init_hook, malloc_hook, free_hook): New functions. - (__malloc_initialize_hook): New variable. - (malloc, free): Functions removed. - -2003-05-07 Ognyan Kulev - - * strfcns.c: #include instead of . - (strbuild): Use -style for handling variable argument - list. - * load.c: Don't #include . - -2002-07-03 Roland McGrath - - * elf-load.c (exec_load): Fix e_machine checking. - - * elf-load.c (exec_load): Fix typos in last change. - -2002-06-22 Roland McGrath - - * load.c (boot_script_exec_cmd): Twiddle decls of serverboot_bunzip2 - and serverboot_gunzip. - - * elf-load.c (exec_load) [__alpha__]: Grok Elf64_* headers and check - for EM_ALPHA. - * exec.c (set_regs) [__alpha__]: Alpha implementation snarfed from CMU - file bootstrap/alpha/exec.c in MK83a. - - * load.c (boot_script_exec_cmd): Cast int to intptr_t before char *. - -2002-06-14 Roland McGrath - - * default_pager.c: #include "default_pager_S.h" - -2002-05-29 Roland McGrath - - * bootstrap.c (main): int -> integer_t for boot_script values. - -2002-05-23 Marcus Brinkmann - - * Makefile: Fix last change properly, by relaxing the rule again - and adding our source dir before the exec dir. - -2002-05-23 Marcus Brinkmann - - * Makefile: Fix last change, constraining vpath even further. - -2002-05-20 Ognyan Kulev - - * Makefile: Move inclusion of ../Makeconf before using $(srcdir) - and constrain vpath directives to avoid using ../exec/exec.o. - -2002-05-07 Roland McGrath - - * default_pager.c (part_id): Add const to argument type. - -2002-03-23 Roland McGrath - - Excised default pager functionality from serverboot. - * Makefile (SRCS): Move def_pager_setup.c default_pager.c kalloc.c to - (EXTRA_DIST): ... here. - (OBJS): Remove *Server.o from here. - (MIGSFLAGS): Variable removed. - * bootstrap.c (main): Replace paging-file boot-script functions with a - stub that prints an error. No longer call partition_init, - default_pager_initialize, or default_pager. - (default_pager_bootstrap_port): Variable removed. - (main): Don't use it. - (default_pager_exception_port): Declaration removed. - (main): Don't use it. - * default_pager.c (default_pager_bootstrap_port): Variable removed. - (default_pager_demux_default): Don't use it. - (default_pager_initialize): Likewise. - (default_pager): Likewise. - (do_bootstrap_privileged_ports, bootstrap_compat): Functions removed. - [mips] (set_ras_address): Likewise. - - * default_pager.c (pager_truncate): New function. - (struct dpager): New member `limit'. - (pager_alloc): Initialize it. - (default_pager_object_set_size): New function. - (seqnos_memory_object_lock_completed): Rewritten, no longer a stub. - (default_pager_demux_object): Try default_pager_server too. - -2001-11-24 Roland McGrath - - * Makefile (installationdir): Use $(bootdir). - -2001-08-16 Roland McGrath - - * Makefile (OBJS): Add userland-boot.o here. - Add a vpath to find userland-boot.c in boot/ too. - * bootstrap.c (parse_script): Pass new arg to boot_script_parse_line. - * load.c: Include before "boot_script.h". - -2001-07-20 Roland McGrath - - * panic.c: Fix obsolescent #endif syntax. - * ext2_file_io.c: Likewise. - * disk_inode_ffs.h: Likewise. - * ffs_file_io.c: Likewise. - -2001-03-31 Roland McGrath - - * assert.h: Fix obsolescent #endif syntax. - * default_pager.c: Likewise. - * queue.h: Likewise. - * load.c: Likewise. - -2001-02-28 Roland McGrath - - * default_pager.c: Use instead of "file_io.h", - so mach-defpager gets its own version when it uses this source file. - (new_partition): If CHECK_LINUX_SIGNATURE arg is -3, don't print out. - -2001-01-11 Marcus Brinkmann - - * def_pager_setup.c: Include and - . - (default_pager_paging_storage): New stub. - -2000-04-03 Roland McGrath - - * panic.c: Include instead of . - (panic): Use stdarg style. - -2000-01-03 Roland McGrath - - * file_io.h: Include "../ext2fs/ext2_fs.h" instead of "ext2_fs.h". - * ext2_file_io.c (search_directory): Use `struct ext2_dir_entry_2' in - place of `struct ext2_dir_entry', so as to grok newer dir formats. - * ext2_fs.h: File removed. - * Makefile (LCLHDRS): Remove it from the list. - * ffs_compat.c (EXT2_INODES_PER_BLOCK): New macro, no longer in - ext2_fs.h. - -1999-11-18 Roland McGrath - - * default_pager.c (default_pager): Instead of suspending this thread, - just become the default_pager_default_thread thread ourselves. - - * wiring.c (wire_all_memory): Touch pages before wiring. - -1999-11-16 Roland McGrath - - * default_pager.c (default_pager_initialize): Use MACH_PORT_VALID to - check old DMM port, rather than just checking for MACH_PORT_NULL. - - * strfcns.c (index): Function removed. - - * ffs_file_io.c (ffs_open_file): Use memmove instead of ovbcopy. - * ext2_file_io.c (ext2_open_file): Likewise. - * strfcns.c (ovbcopy): Function removed. - -1999-11-08 Roland McGrath - - * bootstrap.c (main): Further spruce up prompting and error reporting - for root device and boot script. - -1999-10-28 Roland McGrath - - * load.c, bootstrap.c: Back out some debugging printfs accidentally - included in the last commit. - * bootstrap.c (main): Increase size of NEW_ROOT buffer. - This change was included in the last commit, but not logged then. - - * file_io.h: Include . - (FS_* macros): Define these to equivalent errno codes. - * def_pager_setup.c (add_paging_file): Put strerror of result code in - error messages. - * bootstrap.c (parse_script): Likewise. - * load.c (boot_script_exec_cmd): Include NAMEBUF in error messages, - and use strerror to format result code. - * panic.c (panic): Use program_invocation_name in message. - -1999-10-08 Thomas Bushnell, BSG - - * bootstrap.c: (DEFAULT_ROOT): Remove macro. - (main): If no root device was specified, then prompt as if the - user had specified -a. Don't use strcpy to move NEW_ROOT into - ROOT_NAME; that's unsafe. - -1999-10-06 Roland McGrath - - * bootstrap.c (DEFAULT_ROOT): Change to "hd0s1". - -1999-08-20 Roland McGrath - - * bootstrap.c (parse_script): Add one to the buffer size so we can - null-terminate after the end of the file. - -1999-07-20 Roland McGrath - - * ext2_file_io.c, ffs_file_io.c, minix_file_io.c: Remove fs-specific - routines *_page_{read,write}_file_direct. Moved to ... - * file_io.c (page_read_file_direct, page_write_file_direct): Don't - call fs-specific routine, these are not fs-specific. Instead, - replaced with former fs-specific routines (which were all identical). - Read and write more than a fs block when disk blocks are contiguous. - - * default_pager.c (new_partition): When reading Linux signature page, - handle pager_read_file_direct returning sub-page blocks. - -1999-06-03 Mark Kettenis - - * default_pager.c (new_partition): Declare `waste' as `int' - instead of `unsigned int'. - -1999-06-02 Roland McGrath - - * load.c (boot_script_exec_cmd): Copy environment from our `environ' - onto the new task's stack along with its arguments. - - * bootstrap.c (main): If we have a MULTIBOOT_CMDLINE environment - variable, set its value as ${kernel-command-line} for boot scripts. - -1999-05-29 Roland McGrath - - * bootstrap.c (main): Define $(serverboot) function for "serverboot - controls", control command replacing the pathname. For command "die", - terminate ourselves after running the boot script, no default pager. - -1999-05-23 Roland McGrath - - * default_pager.c (new_partition): Fix arg order in printf for - linux-2.2 signature page. - -1999-05-20 Roland McGrath - - * default_pager.c (new_partition): Fix SWAP-SPACE page handling. - -1999-05-17 Roland McGrath - - * default_pager.c (new_partition): Deallocate signature page when - rejecting it for wrong version. Fix typo in SWAPSPACE2 v1 bad block - bitmap handling. Free bitmap and partition structure if we reject the - partition signature. - Reported by Kalle Olavi Niemitalo . - - * default_pager.c (new_partition): Print out for - CHECK_LINUX_SIGNATURE<0 case. - -1999-05-15 Roland McGrath - - * default_pager.c (new_partition): Check if requested partition is - already in our list, and refuse it. - - * bootstrap.c (main): Remove vars HAD_A_PARITION, DOING_DEFAULT_PAGER. - Remove $(default-pager) boot script tag. We always stick around and - act as the default pager (this was already the case, just removed some - dead code). Don't print anything about having no swap partitions, - since that is a fine way to boot (just use swapon later). - - * default_pager.c (new_partition): Print out partition name and size - when no signature. - -1998-09-06 OKUJI Yoshinori - - * bunzip2.c: New file. - * load.c (GZIP) (BZIP2): New cpp constants. - (boot_script_exec_cmd): If GZIP is defined, gunzip engine is enabled. - If BZIP2 is defined, bunzip2 engine is enabled. - * Makefile (SRCS): Add bunzip2.c. - (UNZIP_OBJS): Add do-bunzip2.o. - (CPPFLAGS): Add -DGZIP, -DBZIP2 and -DSMALL_BZIP2. - -1998-09-03 OKUJI Yoshinori - - * gunzip.c: New file. - Copy libstore/gunzip.c and modify for use in serverboot. - * load.c (struct stuff): Add members, image_addr and image_size. - (mem_read) (mem_read_exec): New functions. - (boot_script_exec_cmd): Add gzexe feature. - * Makefile: Add unzip stuffs. - -1999-03-06 Roland McGrath - - * def_pager_setup.c (default_pager_setup): #if 0 out unused function. - - * default_pager.c (default_pager_paging_file): Pass 0 for new - LINUX_SIGNATURE arg to add_paging_file. - - * bootstrap.c (main: scrript_paging_file): Pass LINUX_SIGNATURE arg - through to add_paging_file. - -1999-02-27 Roland McGrath - - * def_pager_setup.c (add_paging_file): New arg CHECK_LINUX_SIGNATURE, - pass down to create_paging_partition. - * default_pager.c (create_paging_partition): New arg - CHECK_LINUX_SIGNATURE, pass down new_partition. - (new_partition): New arg CHECK_LINUX_SIGNATURE: if not < 0, - check first page of swap for Linux 2.0 or 2.2 signature page and obey - its bad-block map; if > 0, refuse the partition if no signature found. - * bootstrap.c (main): Add new boot script functions - `add-raw-paging-file', `add-linux-paging-file'. Make those - and `add-paging-file' all call add_paging_file with new - LINUX_SIGNATURE arg of -1, 1, and 0, respectively. - * default_pager.c (create_paging_partition): If new_partition returns - null, return and do nothing more. - -1998-07-25 Roland McGrath - - * default_pager.c (pager_read_offset): Cast NO_BLOCK twice, to real - return type of this function. - -Tue May 12 12:11:36 1998 Thomas Bushnell, n/BSG - - * bootstrap.c (parse_script): Free BUF before returning. Reported - by Katusya Tanaka (wyvern@pb3.so-net.ne.jp). - -1997-07-15 Miles Bader - - * bootstrap.c (main): Rearrange default pager initialization. - - * bootstrap.c (safe_gets): Use strchr instead of index. - : Include - - * bootstrap.c (main): Change "(bootstrap)" to "(serverboot)" in msgs. - * load.c (boot_script_exec_cmd): Likewise. - -1997-07-09 Miles Bader - - * bootstrap.c (main): Don't exit when no paging partition. - -1997-07-08 Miles Bader - - * bootstrap.c: Don't include "translate_root.h". - (main): Don't call translate_root. - Pass more than a single character to safe_gets. - (DEFAULT_ROOT): New macro. - (safe_gets): Make sure a newline exists before removing it. - Ensure that the cursor moves to the beginning of the next line. - * translate_root.c, translate_root.h: Files removed. - * Makefile (SRCS): Remove translate_root.c. - (LCLHDRS): Remove translate_root.h. - -Fri Jun 20 15:37:15 1997 Thomas Bushnell, n/BSG - - * bootstrap.c (main/script_paging_file): Instead of returning an - error use new variable `had_a_partition' to record whether we - successfully opened a partition. - (main/script_default_pager): Only start pager if HAD_A_PARTITION; - otherwise print warning message. - -Mon Jun 16 11:52:40 1997 Thomas Bushnell, n/BSG - - * Makefile (installationdir): Use `=' to set this instead of :=; - $(prefix) is not yet available and `=' postpones the evaluation - properly. Reported by Marcus G. Daniels, - marcus@cathcart.sysc.pdx.edu. - -Tue Jun 10 21:54:52 1997 Thomas Bushnell, n/BSG - - * disk_inode.h (struct icommon): Use short instead of uid_t/gid_t - in structure definition; those are now 32 bit types. - - * bootstrap.c (main): Support running from command line too; this - is useful at least for simple debugging. - -1997-06-09 Miles Bader - - * Makefile (LCLHDRS): Add mach-exec.h. - -Thu May 1 18:40:53 1997 Thomas Bushnell, n/BSG - - * bootstrap.c (cthread_stack_size): Don't set special value here; - use the default. - -Wed Apr 30 12:01:53 1997 Thomas Bushnell, n/BSG - - * default_pager.c (default_pager_default_thread): Now that this is - forked, rather than run directly by the first thread, we have to - gain kernel privileges to acquire reserved pages. - -Fri Apr 18 16:44:49 1997 Thomas Bushnell, n/BSG - - * wiring.c (__vm_allocate): New function. - -Wed Apr 16 14:18:28 1997 Thomas Bushnell, n/BSG - - * default_pager.c (debug): Turn off. - -Mon Apr 14 12:50:20 1997 Thomas Bushnell, n/BSG - - * default_pager.c: Remove debugging printfs. - -Thu Apr 10 15:10:25 1997 Thomas Bushnell, n/BSG - - * Makefile (installationdir): Set variable. - -Wed Apr 9 13:57:44 1997 Thomas Bushnell, n/BSG - - * default_pager.c (default_pager_default_thread): New function. - Delete old variable with this name, it was never used. - (default_pager): Fork default_pager_default_thread instead of - doing it here to avoid the possibility that we are on a tiny - stack. Current thread dies. - -Thu Apr 3 20:00:58 1997 Thomas Bushnell, n/BSG - - * elf-load.c (exec_load): Include instead of - . Include "mach-exec.h" instead of - . - (exec_load) [i386]: Check for i386 types directly; abandon old - MY_EI_DATA and MY_E_MACHINE. - * load.c: Include "mach-exec.h" instead of . - * exec.c: Likewise. - * mach-exec.h: New file. - -Wed Mar 19 14:45:27 1997 Thomas Bushnell, n/BSG - - * panic.c (panic): Clear possible errors on stdout before printing - panic string. - -Mon Mar 17 13:13:50 1997 Thomas Bushnell, n/BSG - - * wiring.c (wire_all_memory): Don't attempt wire if PROTECTION is - VM_PROT_NONE. - - * panic.c (panic): Be more informative about where the error is - coming from. - - * default_pager.c (create_paging_partition): Don't print - gratuitous output noise. - * load.c (boot_script_exec_cmd): Likewise. - -Wed Mar 12 10:53:00 1997 Thomas Bushnell, n/BSG - - * ext2_file_io.c (ext2_open_file): Clear FP before beginning - work. - * ffs_file_io.c (ffs_open_file): Likewise. - * minix_file_io.c (minix_open_file): Likewise. - - * bootstrap.c (printf_init, safe_gets): New functions. - * console.c: Deleted file. - * Makefile (SRCS): Omit console.c and gets.c. - - * load.c (read_symtab_from_file): Comment out body of function. - We don't want this. - - * defs.h: Comment out redefinitions of common types. - - * default_pager.c: Include instead of - . - * file_io.h: Likewise. - * kalloc.c: Likewise. - - * panic.c: Include instead of . - - * default_pager.c (pager_read_offset): Cast return of NO_BLOCK - properly. - -Mon Mar 10 17:07:50 1997 Thomas Bushnell, n/BSG - - * load.c: Find boot_script.h in ../boot. - * bootstrap.c: Likewise. - - * bootstrap.c (boot_panic): Repair syntax. - - * strfcns.c: Include instead of . - * load.c: Likewise. diff --git a/ufs-fsck/ChangeLog b/ufs-fsck/ChangeLog deleted file mode 100644 index c050a94e..00000000 --- a/ufs-fsck/ChangeLog +++ /dev/null @@ -1,326 +0,0 @@ -2003-07-29 Marcus Brinkmann - - * fsck.h (num_files): Change type to long. - -2002-06-13 Roland McGrath - - * fsck.h (struct dirinfo): Revert i_isize to using u_int. - -2002-06-08 Roland McGrath - - * dir.c, pass1.c, pass1b.c, pass2.c: Use %Ld for ino_t values. - * utilities.c: Likewise. - - * fsck.h: Use ino_t for lfdir. - * setup.c: Likewise. - - * fsck.h (struct dirinfo): Use size_t for i_isize. - -2001-09-30 Roland McGrath - - * pass5.c (pass5): A little manual CSE makes buggy gcc not to crash. - -2001-02-25 Roland McGrath - - * utilities.c: Include for decl. - -Thu May 6 10:25:27 1999 Thomas Bushnell, BSG - - * utilities.c (pextend): Free MORE before returning. - * dir.c (linkup): Don't free tempname until after we're done using - it in the call to warning. - Reported by Katsuya Tanaka (tanaka@boarderz.com). - -1999-03-25 Roland McGrath - - * setup.c (setup): Don't complain if the device is a block device. - -Wed Feb 19 23:10:39 1997 Miles Bader - - * main.c (argp_program_version): Make const. - -Thu Sep 12 16:40:10 1996 Thomas Bushnell, n/BSG - - * Makefile (HURDLIBS): New variable. - ($(target)): Delete special depedency. - - * Makefile (vpath tables.c): Put after Makeconf inclusion to catch - setting of $(top_srcdir). - -Fri Sep 6 16:44:07 1996 Thomas Bushnell, n/BSG - - * main.c (argp_program_version): Fix typo. - -Thu Sep 5 11:42:21 1996 Thomas Bushnell, n/BSG - - * main.c: Include . - (argp_program_version): Define with STANDARD_HURD_VERSION. - -Fri Aug 16 10:25:37 1996 Thomas Bushnell, n/BSG - - * dir.c (record_directory): Maximum number of block pointers to - record is NDADDR + NIADDR, not NDADDR * NIADDR. - * pass2.c: Include . - (pass2): Before copying block addresses to DINO in basic - integrity check, assert that DNP->i_numblks isn't too big. - -Mon Aug 12 11:39:12 1996 Thomas Bushnell, n/BSG - - * Makefile (dir): Now ufs-fsck. - -Tue Jul 23 19:32:09 1996 Miles Bader - - * inode.c (allocino): `struct timespec' now uses a field prefix - of `tv_'. - * utilities.c (pinode): Likewise. - -Thu Jul 18 14:55:14 1996 Michael I. Bushnell, p/BSG - - * pass2.c (pass2): If an entire directory block is null, allow - preen to patch it into a normal empty directory entry. - -Sat Jul 6 19:59:27 1996 Miles Bader - - * main.c (argp_program_version): New variable. - : New include. - -Mon Jul 1 12:55:48 1996 Michael I. Bushnell, p/BSG - - * pass2.c (pass2): Don't skip empty directories in `.' and `..' - correctness check; we don't clear them the way BSD does, so we - want `.' and `..' to get created for us. Also handle `.' before - `..' so that they get created in the usual order for empty - directories. - - * dir.c (makeentry): After successful directory expansion, write - out modified directory inode. - - * pass4.c (pass4): If a reconnect fails while we are preening, - give up. - -Mon Jun 24 10:19:39 1996 Michael I. Bushnell, p/BSG - - * utilities.c (errexit, punt): Exit with status 8 for catastrophic - failures. - -Thu May 23 14:12:21 1996 Michael I. Bushnell, p/BSG - - * pass2.c (pass2): Don't clear all node types in directories, just - clear those that are wrong. - -Tue May 14 16:49:46 1996 Miles Bader - - * pass2.c (pass2): Fix up test in preen case. - -Tue May 14 15:29:36 1996 Michael I. Bushnell, p/BSG - - * pass2.c (pass2): Handle directory entry type fields better for - Hurd. - -Sat May 11 01:07:49 1996 Miles Bader - - * main.c (parse_opt): Use ARGP_ERR_UNKNOWN instead of EINVAL. - -Thu May 9 20:12:51 1996 Michael I. Bushnell, p/BSG - - * pass1b.c (pass1b): Bother to initialize NUMBER. - -Fri May 3 00:48:39 1996 Miles Bader - - * main.c (nice_size, show_stats): New functions. - (main): Use show_stats. - -Wed May 1 13:59:06 1996 Miles Bader - - * main.c (main): Shorten summary message so that it fits on one line. - * utilities.c (no_preen): New function. - (problem, warning, pinode): Use it. - (warning): Don't flush all pending problems, just our own. - * dir.c (linkup): Consistently put quotes around filenames. - - * main.c (preen, num_files): New variables. - (main): Implement clean-bit checking in preen mode, and print - summary statistics. - (main, options): Add --force & --silent options. - * pass1.c (pass1): Increment NUM_FILES. - When clearing inode due to bad blocks, continue. - * inode.c (allocino, freeino): Frob NUM_FILES. - * fsck.h (force): New declaration. - * pass5.c (pass5): Vary clean msg depending on whether FSMODIFIED. - * setup.c (setup): Use error to print error msgs. - , : New includes. - - * utilities.c (problem, warning, pextend, pfail): New functions. - (pinode, pfix, reply): Use new problem recording stuff. - (push_problem, resolve_problem, flush_problems): New functions. - (struct problem): New type. - (problems, free_problems): New variables. - (retch, punt): New functions. - * fsck.h (problem, warning, pextend, pfail): New declarations. - (pinode): Update declaration. - * dir.c (validdir, makeentry, linkup): Use new printing functions. - * pass1.c (pass1): Likewise. - * pass1b.c (pass1b): Likewise. - * pass2.c (pass2): Likewise. - * pass3.c (pass3): Likewise. - * pass4.c (pass4): Likewise. - * pass5.c (pass5): Likewise. - * setup.c (setup): Likewise. - -Tue Apr 30 19:06:42 1996 Miles Bader - - * pass5.c (pass5): Be sure to call pwarn before pfix. - * main.c (main): Don't print large obnoxious banner if PREEN. - -Fri Apr 26 16:20:37 1996 Michael I. Bushnell, p/BSG - - * inode.c (allocino): Parenthesize test correctly. - - * fsck.h (swab_disk): Define as constant zero. - - * pass5.c (pass5): If not marked clean, but now it is, then offer - to mark it clean. - * utilities.c (reply): Set fix_denied anytime we return 0. - * fsck.h (fix_denied): New variable. - -Wed Apr 24 13:32:39 1996 Michael I. Bushnell, p/BSG - - * pass1.c (pass1): Don't print block numbers as we go anymore. - -Tue Apr 23 10:11:49 1996 Michael I. Bushnell, p/BSG - - * pass5.c (pass5): Correctly track contig summaries even though - they aren't used by the filesystem; we still need to preserve the - format. - -Mon Apr 15 12:51:41 1996 Michael I. Bushnell, p/BSG - - * Makefile (vpath tables.c): Find ufs directory in $(top_srcdir). - -Tue Apr 2 09:00:53 1996 Michael I. Bushnell, p/BSG - - * pass1.c (pass1): Print mode correctly in unknown file type case. - Recognize inode type IFSOCK too. - -Mon Mar 18 19:48:39 1996 Miles Bader - - * main.c (main): Pass new arg to argp_parse. Use argp_usage correctly. - -Thu Oct 19 17:45:12 1995 Miles Bader - - * main.c (main): Exit with a non-zero status if we fixed anything. - Use argp to parse options. - (options): Converted to argp format. - (args_doc): New variable. - (USAGE, usage, SHORT_OPTIONS): Removed. - Include instead of . - * Makefile ($(target)): Depend on libshouldbeinlibc.a. - -Fri Sep 22 16:55:03 1995 Miles Bader - - * utilities.c (pfix): New function. - (pfatal, pwarn, errexit): Print DEVICE_NAME too if in preen mode. - * fsck.h: Declare DEVICE_NAME. - * setup.c (setup): Set DEVICE_NAME. - * pass1.c, pass2.c, pass3.c, pass4.c, pass5.c (pass1, pass2, - pass3, pass4, pass5): Call pfix instead of printf. - * pass1.c (pass1): Only print progress report if not in preen mode. - * main.c (main): Only print section headers if not in preen mode. - -Wed Sep 20 09:11:59 1995 Miles Bader - - * utilities.c (pinode): Take a message & args to print as well. - * fsck.h: Change declaration of pinode. - * pass2.c (pass2): Use changed pinode. - * pass3.c (pass3): Use changed pinode. - * pass4.c (pass4): Use changed pinode. - -Tue Sep 19 15:37:02 1995 Miles Bader - - * pass1.c (pass1): Change the extent of DBWARN & IBWARN so that - they actually work. - * pass2.c (pass2): Adjust our record of link counts when we - add/change dir entries; also print error messages when we can't. - * pass4.c (pass4): If an unlinked file can't be reconnected, offer - to clear it. Once a reconnect attempt fails, don't try again. - * dir.c (linkup): Print the value of LFNAME rather than `lost+found'. - (searchdir, changeino): Fix backward compare. - (linkup): Don't fail when makeentry succeeds. - (searchdir): Make searchdir return zero if there's an error - during the search. - (linkup): Print appropiate error messages if searchdir fails. - (validdir): Get rid of extra newlines in error messages -- - everyone who calls this routine prints extra information if it - fails, which should immediately follow. - * main.c (main): Use getopt to parse command line options. - (usage): New function. - (options): New variable. - (lfname, lfmode): Variables moved here from setup.c. - (lfname): Made into a char* so that we can change it. - (lfmode): Get rid of IFDIR; it's added when necessary. - * fsck.h: Change LFNAME to char*. - * setup.c (lfname, lfmode): Variables moved to main.c. - -Sat Sep 9 12:12:59 1995 Miles Bader - - * Makefile (target): Changed to `fsck.ufs'. - (installationdir): New variable, install into $(sbindir). - -Thu Jul 6 15:33:46 1995 Michael I Bushnell - - * fsck.h (lookup_directory): New decl. - - * pass1.c (pass1): Remove assignment from if test. - * utilities.c (pinode): Likewise. - - * Makefile (tables.o): Delete rule. - (vpath tables.c): Tell where to find tables.c. - - * Makefile: Removed dependencies that are now automatically - generated. - -Thu Nov 3 17:19:03 1994 Michael I Bushnell - - * Makefile (dir): Changed to fsck. - (target): Changed to fsck. - -Wed Nov 2 14:39:13 1994 Michael I Bushnell - - * pass2.c (pass2): Use DIRECT_NAMLEN instead of d_namlen - throughout. - * dir.c (searchdir): Likewise. - (changeino): Likewise. - (makeentry): Likewise. - -Mon Oct 17 16:07:56 1994 Michael I Bushnell - - * inode.c (inode_iterate): FN takes new third arg. - Keep track of new var `offset' and pass it to FN. - * pass2.c (pass2/checkdirblock): New third arg. - Only scan DIRBLKSIZ chunks to the total size of the file. - * dir.c (searchdir/checkdirblock): Likewise. - (changeino/checkdirblock): Likewise. - (makeentry/checkdirblock): Likewise. - * pass1.c (pass1/checkblock): New third arg (ignored). - * pass1b.c (pass1b/checkblock): Likewise. - - * inode.c (inode_iterate): Compute MAXB correctly. - - * utilities.c (getinode): Multiple ino_to_fsbo by - sizeof (struct dinode). - (write_inode): Likewise. - (getinode): Inode buffer needs to be a full block, not a - fragment. - -Fri Oct 14 21:07:09 1994 Michael I Bushnell - - * utilities.c (lastifrag): New variable. - (getinode): Use lastifrag instead of buf; Only I/O new block - if lastifrag isn't what we want. - (write_inode): Likewise. - -Fri Oct 14 17:44:59 1994 Michael I Bushnell - - * setup.c (setup): Test ISCHR, not ISDIR. - Fix NCYL against NCG * CPG test. - Bother to set MAXFSBLOCK, MAXINO, and DIRECT_SYMLINK_EXTENSION. diff --git a/ufs-utils/ChangeLog b/ufs-utils/ChangeLog deleted file mode 100644 index d5a8bc8f..00000000 --- a/ufs-utils/ChangeLog +++ /dev/null @@ -1,167 +0,0 @@ -2008-12-08 Thomas Schwinge - - * Makefile (HURDLIBS): New variable. - -2006-03-15 Thomas Schwinge - - * mkfs.c (parse_opt): Move UP's functionality into UP_INT in order to - fix invalid lvalues. - -2002-06-08 Roland McGrath - - * mkfs.c (iput): Use %Ld format for ino_t values. - -2001-12-06 Roland McGrath - - * dlabel.c (fd_get_device): Only deallocate NODE if store_create fails. - Found by Michael Teichgraeber . - -2001-12-02 Roland McGrath - - * mkfs.c (fsinit): Set the root directory's owner/group to the user's. - Suggested by Michael Teichgraeber . - -2001-02-25 Roland McGrath - - * mkfs.c [!STANDALONE]: Include for decl. - * stati.c: Likewise. - -1999-11-20 Roland McGrath - - * dlabel.c (fd_get_device): Check STORE->class->id, not STORE->class. - -1998-09-04 Roland McGrath - - * mkfs.c (main): Fix return type to int, use return. - -Fri Jun 20 13:39:02 1997 Thomas Bushnell, n/BSG - - * mkfs.c (mkfs): Set SBLOCK.fs_clean. New file systems are always - clean. - -Thu Apr 10 13:54:31 1997 Thomas Bushnell, n/BSG - - * dlabel.c: Don't include . - (_IOR, _IOC, IOC_OUT, IOCPARM_MASK): New macros. - -Wed Feb 19 23:10:54 1997 Miles Bader - - * mkfs.c (argp_program_version): Make const. - -Thu Sep 5 11:44:38 1996 Thomas Bushnell, n/BSG - - * mkfs.c: Include . - (argp_program_version): Define with STANDARD_HURD_VERSION. - -Mon Aug 19 15:18:30 1996 Miles Bader - - * mkfs.c (doc): Supply a useful value. - -Tue Jul 23 19:34:58 1996 Miles Bader - - * mkfs.c (fsinit): `struct timespec' now uses a field prefix of `tv_'. - * stati.c (timespec_rep): Likewise. - -Fri Jun 21 02:12:16 1996 Miles Bader - - * dlabel.c (fd_get_device): Supply new args to store_create. - -Sat May 11 01:20:18 1996 Miles Bader - - * mkfs.c (parse_opt): Use ARGP_ERR_UNKNOWN instead of EINVAL. - -Fri May 10 15:50:38 1996 Miles Bader - - * dlabel.c (fd_get_device): Update to use libstore. - : New include. - * Makefile (mkfs.ufs): Depend on ../libstore/libstore.a. - -Tue Apr 30 10:06:21 1996 Michael I. Bushnell, p/BSG - - * Makefile (include ../Makeconf): BEFORE dependencies. - (all): Delete target. - ($(targets)): Each target depends on its associated .o. - -Wed Apr 3 16:31:13 1996 Miles Bader - - * mkfs.c (main): In `Can't get disklabel' error message, specify - which flag the user can use to supply the needed information. - (mkfs): Fiddle with info message. - -Sun Mar 31 14:34:28 1996 Miles Bader - - * stati.c (mode_rep): Prefix octal number with `0'. - -Fri Mar 29 11:56:52 1996 Miles Bader - - * stati.c (main): Print mode & {in,}direct blocks too. - (mode_rep): New function. - (timespec_rep): P shouldn't be static. - - * mkfs.c (main): Argp interface changes. - -Wed Mar 13 18:30:55 1996 Miles Bader - - * mkfs.c (options, args_doc, doc): New variables for option parsing. - (struct amark): New type. - (amarks_add, amarks_contains): New functions. - (default_disklabel): New variable. - (main): Most arguments are now options (and optional). Allow many - more parameters to be specified. Consult the disk label for some - defaults. - (most functions): Add explicit return type declarations. Fix - printf format specifications. Get rid of #ifdefs for MFS. - (started, malloc, realloc, calloc, free): Functions removed. - (mfs, membase): Variables removed. - , , , , , - : New includes - * dlabel.c: New file. - * Makefile (SRCS): Add dlabel.c. - (mkfs.ufs): New target. - -Tue Feb 27 14:52:00 1996 Miles Bader - - * clri.c: Move here from ../utils. - - [Entire directory renamed to `ufs-utils' from `newfs'] - -Sat Sep 9 12:17:11 1995 Miles Bader - - * Makefile (target): Changed to `mkfs.ufs'. - (installationdir): New variable, install into $(sbindir). - -Thu Nov 24 18:39:30 1994 Roland McGrath - - * mkfs.c: Protect all mfs code with #ifdef MFS. - -Wed Oct 12 12:59:01 1994 Michael I Bushnell - - * mkfs.c (main): MAXCONTIG should be zero because we don't - do clustering. - -Fri Sep 9 09:45:23 1994 Michael I Bushnell - - * mkfs.c: Include and . - (main): New function. Punt newfs.c for now. - * Makefile (SRCS, OBJS): Comment out uses of newfs.c. - (target): Build mkfs, not newfs. - - * newfs.c (mopts): Comment out. - (mntflags): Comment out. - (main): Omit check for `mfs'. Omit var `partition'. - (main) [case 'o']: Comment out mfs specific code. - (main): Comment out check for already-mounted partition. - (main): Comment out MFS specific open of FSI. - - * mkfs.c (fsinit): Use DI_MODE to read mode from NODE, and - set di_model and di_modeh instead of di_mode. - (mkfs): Don't set fields in *PP. - - * newfs.c: Include ufs header files with "../ufs/foo.h" instead of - . Don't include , , - or "mntopts.h". - -Thu Sep 8 15:52:05 1994 Michael I Bushnell - - * mkfs.c: Include ufs header files with "../ufs/foo.h" instead of - . Don't include . diff --git a/ufs/ChangeLog b/ufs/ChangeLog deleted file mode 100644 index 14fb86bd..00000000 --- a/ufs/ChangeLog +++ /dev/null @@ -1,2012 +0,0 @@ -2007-11-13 Thomas Schwinge - - * inode.c (read_disknode, write_node): Adapt to ``struct stat'' - changes. - -2007-08-16 Samuel Thibault - - * dir.c (diskfs_lookup_hard, diskfs_dirempty): Call - diskfs_set_node_atime instead of setting dp->dn_set_atime. - * inode.c (read_symlink_hook): Likewise. - -2006-03-15 Thomas Schwinge - - * dir.h (DIRECT_NAMELEN): Don't use ?: as a lvalue. - -2002-10-03 Roland McGrath - - * dir.h (MAXNAMLEN): #undef before defining. - -2002-07-31 Roland McGrath - - * dir.c (diskfs_direnter_hard): Fix test in last change. - -2002-06-08 Roland McGrath - - * inode.c (diskfs_cached_lookup): Use ino_t for argument. - - * dir.c (diskfs_direnter_hard): Use size_t for OLDSIZE. - Fail with EOVERFLOW when it would exceed that width. - - * alloc.c, dir.c: Use %Ld format for ino_t values. - * alloc.c (diskfs_alloc_node): Use %Ld format for blkcnt_t values. - -2002-05-08 Roland McGrath - - * main.c (diskfs_append_args): Fix argument type. - (main): Use %z format modifier for size_t arg. - * dir.c (dirscanblock): Use %z format modifier for vm_address_t arg. - (diskfs_dirempty): int -> vm_address_t - (count_dirents): int -> size_t - (diskfs_get_directs): u_int -> size_t - -2002-03-11 Roland McGrath - - * Makefile (ufs.static): Depend on - $(boot-store-types:%=../libstore/libstore_%.a). - -2001-11-21 Roland McGrath - - * inode.c (read_disknode): Just always call getpid for the fsid value. - -2001-10-01 Marcus Brinkmann - - * ufs.h (swab_long_long): Use LL, not lL, for constant. - Submitted by Maurizio Boriani . - -2001-08-09 Roland McGrath - - * inode.c (diskfs_get_translator): Fail with EFTYPE if the length - field stored on disk is unreasonable. Don't crash on ENOMEM. - Use memcpy instead of bcopy. - -2001-06-09 Mark Kettenis - - * inode.c (diskfs_set_statfs): If number of free blocks is less - than the number of reserved blocks, set the number of available - blocks to 0. - -2001-01-08 Marcus Brinkmann - - * main.c (main): Use %Ld instead %ld to print store->size. - * hyper.c (get_hypermetadata): Likewise. - * inode.c (diskfs_S_file_get_storage_info): Change type of variables - start and length from off_t to store_offset_t. - -2001-01-07 Marcus Brinkmann - - * dir.c: Make diskfs_dirstat_size const. - -2000-12-02 Roland McGrath - - * inode.c (write_node): Remove assert that dn_set_mtime et al are - clear. It is ok if they are set in parallel, because the latter - setting will be carried out eventually. - -2000-11-30 Marcus Brinkmann - - * dir.c (diskfs_lookup_hard): If name is too long, clear - DS before returning ENAMETOOLONG. - -2000-07-26 Mark Kettenis - - * Makefile (HURDLIBS): Reorder libs such that the threads lib - comes before the ports lib. This makes sure the functions in - libthreads properly override the stubs in libports with the new - dynamic linker semantics in glibc 2.2. - -2000-03-03 Roland McGrath - - * dir.c (diskfs_get_directs): Don't allocate buffer for *DATA until - after scanning for ENTRY and possibly returning EOF. - -1999-10-13 Roland McGrath - - * consts.c (diskfs_name_max): New variable. - -1999-09-13 Roland McGrath - - * dir.c, sizes.c, pager.c: Reverted changes related to io_map_segment. - -1999-09-09 Roland McGrath - - * Makefile (makemode): servers -> server. - (targets): Replaced with target; remove ufs.static. - (ufs.static-LDFLAGS): Variable removed. - (ufs.static, ufs): Remove deps. - -1999-09-08 Thomas Bushnell, BSG - - * dir.c (diskfs_get_directs): Initialize `err' to shut gcc up. - -1999-09-07 Thomas Bushnell, BSG - - * dir.c (diskfs_lookup_hard): Pass additional parameter to - diskfs_get_filemap. - (diskfs_dirempty): Likewise. - * sizes.c (diskfs_truncate): Likewise. - (block_extended): Likewise. - (diskfs_grow): Likewise. - * pager.c (diskfs_get_filemap): Accept additional parameter. - -1999-09-04 Thomas Bushnell, BSG - - * pager.c (find_address): If !ISREAD, then don't return errors for - access past NP->allocsize, and clear *ADDR and *DISKSIZE. These - can happen through harmless races against truncate. - (pager_write_page): Don't print annoying messages for writes to - unallocated disk. These can happen through harmless races against - truncate, and so we should not pester the console with them. - -1999-07-10 Roland McGrath - - * ufs.h: Add #include for munmap decl. - -1999-07-09 Thomas Bushnell, BSG - - * dir.c (diskfs_get_directs): Use mmap instead of vm_allocate. - * hyper.c (get_hypermetadata): Likewise. - * pager.c (pager_read_page): Likewise. - -1999-07-06 Thomas Bushnell, BSG - - * hyper.c (diskfs_readonly_changed): Use mprotect instead of - vm_protect. - -Mon Jul 5 20:04:58 1999 Thomas Bushnell, BSG - - * dir.c (diskfs_lookup_hard): Repair typo. Reported by Yamashita - TAKAO . - -1999-07-03 Thomas Bushnell, BSG - - * dir.c (diskfs_lookup_hard): Use munmap instead of - vm_deallocate. - (diskfs_direnter_hard): Likewise. - (diskfs_dirremove_hard): Likewise. - (diskfs_dirrewrite_hard): Likewise. - (diskfs_dirempty): Likewise. - (diskfs_drop_dirstat): Likewise. - (diskfs_get_directs): Likewise. - * sizes.c (block_extended): Likewise. - (poke_pages): Likewise. - * hyper.c (get_hypermetadata): Likewise. - (diskfs_set_hypermetadata): Likewise. - -1999-06-29 Thomas Bushnell, BSG - - * hyper.c (diskfs_readonly_changed): Adjust whether the store - should permit writes too. - -1999-05-02 Roland McGrath - - * main.c (main): Remove bogus uninitialized variable ERR. - -1999-01-23 Roland McGrath - - * main.c (main): Use diskfs_init_main. - -1998-12-27 Roland McGrath - - * inode.c (diskfs_set_statfs): Remove __ from struct members. - -1998-12-21 Mark Kettenis - - * inode.c (diskfs_set_statfs): Fill in statfs members that are - used to implement statvfs. - -1998-12-27 Roland McGrath - - * main.c (main): Pass ARGP_IN_ORDER flag to argp_parse because - diskfs options need it. - -1998-12-20 Roland McGrath - - * alloc.c (diskfs_alloc_node): Fix printf format to silence warning. - * hyper.c (get_hypermetadata): Likewise. - -1998-09-04 Roland McGrath - - * dir.c (diskfs_lookup_hard): Fix defn with `const'. - (diskfs_direnter_hard): Likewise. - (dirscanblock): Likewise. - * inode.c (diskfs_create_symlink_hook, create_symlink_hook): Likewise. - (diskfs_set_translator): Likewise. - -Wed Aug 20 14:34:24 1997 Thomas Bushnell, n/BSG - - * dir.c (diskfs_lookup_hard): Cope with error return from - diskfs_get_filemap. - * sizes.c (diskfs_grow): Likewise. - * dir.c (diskfs_dirempty): Cope (poorly) with error return from - diskfs_get_filemap. - * sizes.c (diskfs_truncate): Likewise. - (block_extended): Likewise. - - * pager.c (diskfs_get_filemap): If pager_create fails, return - error to caller. - -Mon Jun 30 17:38:57 1997 Thomas Bushnell, n/BSG - - * main.c (main): If the store cannot be made writable, then set - diskfs_hard_readonly and diskfs_readonly. - -1997-06-20 Miles Bader - - * hyper.c (diskfs_set_hypermetadata): Adjust device addresses for - possible differences between DEV_BSIZE & device block size. - * inode.c (diskfs_S_file_get_storage_info): Likewise. - * pager.c (pager_read_page, pager_write_page, pager_unlock_page): - Likewise. - * ufs.h (log2_dev_blocks_per_bsize): New declaration. - * main.c (main): Only require device-block-size to be <= DEV_BSIZE. - Get rid of device-block-size-is-power-of-2 check. - Set LOG2_DEV_BLOCKS_PER_BSIZE. - Exit with an error if the disk is too small rather than assert failing. - (log2_dev_blocks_per_bsize): New variable. - -Thu Feb 6 01:56:27 1997 Miles Bader - - (diskfs_S_file_getfh, diskfs_S_fsys_getfile): Functions removed. - -Tue Nov 19 18:28:26 1996 Miles Bader - - * inode.c (read_disknode): If SBLOCK->fs_inodefmt < FS_44INODEFMT, - set ST->st_author to st->st_uid, and NP->author_tracks_uid to true. - (diskfs_validate_author_change): New function. - -Mon Nov 18 17:10:00 1996 Miles Bader - - * inode.c (read_disknode): When setting ST->st_mode, Clear - S_ITRANS bits, and set S_IPTRANS if necessary. Don't set - NP->istranslated anymore. - (diskfs_set_translator): Frob S_IPTRANS bit in mode bits instead - of NP->istranslated. - (write_node): Don't write any bits in S_ITRANS to disk. - * alloc.c (ffs_alloc): Use S_IPTRANS in NP->dn_stat.st_mode - instead of NP->istranslated. - -Sat Nov 16 17:21:40 1996 Thomas Bushnell, n/BSG - - * inode.c (diskfs_S_fsys_getfile): Delete var `fakecred'. - diskfs_access -> fshelp_access. - * alloc.c (ffs_alloc): diskfs_isuid -> idvec_contains. - (ffs_realloccg): Likewise. - -Thu Nov 14 16:43:36 1996 Thomas Bushnell, n/BSG - - * inode.c (diskfs_S_file_getfh): diskfs_isuid -> idvec_contains. - (diskfs_S_fsys_getfile): Use idvecs and iousers. - -Thu Oct 24 16:07:17 1996 Miles Bader - - * main.c (startup_children, runtime_children): New variables. - (startup_parents, runtime_parents): Variables removed. - (startup_argp, runtime_argp): Use new *_CHILDREN variables instead of - corresponding *_PARENT ones. - -Thu Sep 19 18:02:40 1996 Miles Bader - - * Makefile (HURDLIBS): Add store. - -Wed Sep 18 15:30:00 1996 Miles Bader - - * inode.c (diskfs_S_file_get_storage_info): Narrow scope of RUN. - - * consts.c (diskfs_extra_version): New variable. - - * main.c (main): Remove CLASSES argument to store_parsed_open. - Use STORE_PARAMS variable to get result from parsing STORE_ARGP. - Don't force COMPAT_GNU on bootstrap filesystems (it's the default - anyway). - -Mon Sep 16 13:27:38 1996 Miles Bader - - * Makefile (ufs.static ufs): Add ../libstore/libstore.a. - - * hyper.c (zeroblock): Change type to `void *'. - (get_hypermetadata): Cast ZEROBLOCK when vm_{de,}allocating. - * ufs.h (zeroblock): Change type to `void *'. - * sizes.c (diskfs_truncate): Don't cast ZEROBLOCK to diskfs_node_rw. - (block_extended, diskfs_grow): Do cast it to offer_data. - - * main.c (main): Don't set DISKFS_USE_MACH_DEVICE (which is no longer). - - * inode.c (diskfs_S_file_get_storage_info): Coalesce adjacent - blocks when constructing RUNS. - Set *PORTS_TYPE, not *STORAGE_PORT_TYPE. - * inode.c (diskfs_S_file_getfh): Variable ERR removed. - - * sizes.c (indir_release): Use DISKFS_DISK_PAGER instead of DISK_PAGER. - * ufs.h (sync_disk_blocks): Likewise. - * pokeloc.c (sync_disk): Likewise. - * main.c (diskfs_reload_global_state): Likewise. - * pager.c (create_disk_pager, diskfs_shutdown_pager, - diskfs_sync_everything): Likewise. - * main.c , : New includes. - * hyper.c, pager.c, inode.c : New include. - (get_hypermetadata): Use %Zd for printfing size_t. - (diskfs_set_hypermetadata): Return EIO for incomplete writes. - Cast BUF when calling vm_deallocate. - - * dir.c (diskfs_direnter_hard): Initialize OLDSIZE to shut up gcc. - -Sat Sep 14 20:38:47 1996 Miles Bader - - * ufs.h (store, store_parsed, disk_image): New declarations. - - * pager.c (thread_function): Function removed. - (create_disk_pager): Create PAGER_BUCKET. - Use diskfs_start_disk_pager instead of disk_pager_setup. - (disk_image): New variable. - - * main.c (store, store_parsed, diskfs_disk_name): New variables. - (parse_opt): Propagate our input to the first child parser. - (diskfs_append_args): New function. - (diskfs_get_options): Function removed. - (startup_parents): Use DISKFS_STORE_STARTUP_ARGP instead of - DISKFS_STD_DEVICE_STARTUP_ARGP. - - * hyper.c (get_hypermetadata): Use DISKFS_DISK_NAME instead of - DISKFS_DEVICE_ARG. - * main.c (main): Likewise. - - * hyper.c (get_hypermetadata, diskfs_readonly_changed): Use - fields in STORE instead of DISKFS_DEVICE_* variables. - * inode.c (diskfs_S_file_get_storage_info): Likewise. - * pager.c (pager_report_extent): Likewise. - * main.c (main): Likewise. - * pager.c (pager_read_page, pager_write_page, pager_unlock_page): - Use store_{read,write} instead of diskfs_device_{read,write}_sync. - * hyper.c (diskfs_set_hypermetadata): Likewise. - * inode.c (diskfs_S_file_get_storage_info): Rewrite to use - libstore functions (still has NDADDR block limit, though). - -Thu Sep 12 16:36:19 1996 Thomas Bushnell, n/BSG - - * Makefile (HURDLIBS): New variable. - (ufs.static ufs): Depend on $(library_deps) instead of long list - of libraries. - -Fri Sep 6 16:00:42 1996 Thomas Bushnell, n/BSG - - * consts.c: Include . - (diskfs_major_version, diskfs_minor_version, diskfs_edit_version): - Deleted variables. - (diskfs_server_version): New variable. - -Thu Aug 29 16:07:07 1996 Thomas Bushnell, n/BSG - - * dir.c (diskfs_lookup_hard): When setting ds->stat to EXTEND, set - ds->idx by looking at the size of the file. (IDX itself is no - longer at the end because of the change on Aug 16 1996.) - -Wed Aug 28 12:15:15 1996 Thomas Bushnell, n/BSG - - * dir.c (dirscanblock): Size dirents correctly when mallocing it. - (diskfs_direnter_hard): Be more careful when sizing or resizing - dirents. Correctly set to -1 all the new entries we create after - realloc call. - -Fri Aug 16 18:51:31 1996 Thomas Bushnell, n/BSG - - * ufs.h (struct disknode): New member `dir_idx'. - * inode.c (diskfs_cached_lookup): Initialize DN->dir_idx. - * dir.c (diskfs_lookup_hard): After successful dirscanblock, - record index where we finished in DP->dn->dir_idx. Start searches - at that index. - -Mon Aug 12 13:43:46 1996 Thomas Bushnell, n/BSG - - * hyper.c (diskfs_set_hypermetadata): Bother to return 0 at end of - function. - -Wed Aug 7 13:00:30 1996 Thomas Bushnell, n/BSG - - * inode.c (diskfs_set_statfs): Compute st->f_blocks correctly; set - bsize to be fs_fsize, not fs_bsize. - - * hyper.c (diskfs_set_hypermetadata): Return an error as - appropriate. - - * inode.c (struct ufs_fhandle): Layout filehandle more like Unixy - NFSD. - (diskfs_S_file_getfh): Bother to clear unused parts of a - file handle so that they always compare equal. - -Tue Aug 6 12:19:38 1996 Thomas Bushnell, n/BSG - - * inode.c: Include . - (struct ufs_fhandle): New type. - (diskfs_S_fsys_getfile, diskfs_S_file_getfh): New functions. - -Tue Jul 23 15:58:28 1996 Miles Bader - - * inode.c (write_node, read_disknode): `struct timespec' now uses - a field prefix of `tv_'. - -Sat Jul 6 16:14:10 1996 Miles Bader - - * main.c (ufs_version): Variable removed. - -Sat Jul 6 12:45:36 1996 Michael I. Bushnell, p/BSG - - * inode.c (read_disknode): Don't set allocsize based on st->size - for kludged symlinks. - - * sizes.c (diskfs_truncate): Call record_poke after truncating a - kludged symlink. - -Wed Jul 3 13:27:04 1996 Michael I. Bushnell, p/BSG - - * main.c: Include . - (startup_parents, runtime_parents): Declare const. - -Tue Jun 25 14:02:02 1996 Miles Bader - - * main.c (diskfs_get_options): Include `--compat=' in options. - -Mon Jun 24 16:59:12 1996 Michael I. Bushnell, p/BSG - - * dir.c (diskfs_lookup_hard): Use diskfs_check_readonly instead of - diskfs_readonly. - (diskfs_dirempty): Likewise. - - * dir.c (diskfs_lookup_hard): Use diskfs_check_readonly instead of - diskfs_readonly. - (diskfs_dirempty): Likewise. - * inode.c (diskfs_cached_lookup): Likewise. - (read_symlink_hook): Likewise. - * sizes.c (diskfs_truncate): Call diskfs_check_readonly. - (diskfs_grow): Likewise. - * hyper.c (diskfs_set_hypermetadata): If CLEAN is not set, make - sure we clear the clean bit on disk. Always call sync_disk (with - appropriate WAIT). - (diskfs_readonly_changed): Don't do set_hypermetadata here. - (copy_sblock): Don't track clean state here. - - * pager.c (diskfs_shutdown_pager): Don't shutdown DISKPAGER ever, - just sync it instead. - -Sat Jun 22 17:45:34 1996 Miles Bader - - * main.c (diskfs_get_options): New function. - (options): Make const. - -Fri Jun 21 01:32:09 1996 Miles Bader - - * main.c (parse_opt): Handle runtime invalid selection of 4.2 mode. - Save select mode until we're done to correctly deal with external - errors at runtime. - (startup_parents, startup_argp, runtime_parents, runtime_argp): - New variables. - (main): Argp vars made global. - (argp_parents): diskfs_device_startup_argp --> - &diskfs_std_device_startup_argp. - -Sat Jun 15 13:57:27 1996 Miles Bader - - * main.c (options): New variable. - (parse_opt): New function. - (main): Parse ufs-specific options too. - : New include. - -Fri May 10 09:29:03 1996 Michael I. Bushnell, p/BSG - - * inode.c (diskfs_set_statfs): Fix one reference to old name of ST - member. - -Thu May 9 11:54:13 1996 Michael I. Bushnell, p/BSG - - * Makefile (ufs.static ufs): s/ioserver/iohelp/g - * ufs.h: ioserver.h -> iohelp.h. - - * inode.c (diskfs_set_statfs): Use and fill in new statfs - structure. - -Mon May 6 14:23:54 1996 Michael I. Bushnell, p/BSG - - * main.c (ufs_version): Upgrade to 0.0. - -Fri May 3 09:15:33 1996 Michael I. Bushnell, p/BSG - - * sizes.c (block_extended): Rewrite code that moves pages - to be more efficient, and not deadlock too, using unlocked - pagein permission feature (read "hack"). Return value - now indicates whether we expect a sync. - (diskfs_grow): If a call to block_extended returns nonzero, - then sync the file before returning. - * pager.c (diskfs_get_filemap): Initialize - UPI->allow_unlocked_pagein and UPI->unlocked_pagein_length. - (unlocked_pagein_lock): New variable. - (find_address): New parameter `isread'; all callers changed. - If ISREAD and we are in the unlocked pagein region, don't - attempt to acquire NP->dn->allocptrlock. - * ufs.h (struct user_pager_info): New members - `allow_unlocked_pagein' and `unlocked_pagein_length'. - (unlocked_pagein_lock): New variable. - -Thu May 2 10:56:10 1996 Michael I. Bushnell, p/BSG - - * sizes.c (offer_data): Offer pages at ADDR each time through the - loop, not the same page over and over. - (block_extended): When moving data, sync in-core pager both before - reading from disk and after providing data to kernel. - (diskfs_grow): Always call block_extended or offer_data before - adjusting block pointer. - -Tue Apr 30 13:38:42 1996 Michael I. Bushnell, p/BSG - - * sizes.c (diskfs_grow): In last offer_data, don't offer a block - number as an address. - -Fri Apr 26 15:35:53 1996 Michael I. Bushnell, p/BSG - - * Makefile (makemode): Now `servers'. - (targets): Renamed from `target'; now include ufs.static. - (ufs.static-LDFLAGS): Renamed from `LDFLAGS'. - (ufs.static): Depend on same things as `ufs'. - (include ../Makeconf): Must come before dependency information. - -Wed Apr 24 14:05:48 1996 Michael I. Bushnell, p/BSG - - * dir.h (DIRECT_NAMLEN) [! LITTLE_ENDIAN]: Deal correctly with the - case where it was written on a little endian machine without the - extension. - (DIRECT_NAMLEN) [LITTLE_ENDIAN]: Deal with case correctly where it - was written without the extension on a big endian machine. - * dir.c (dirscanblock): Use read/write_disk_entry when reading or - writing fields from directory entries. - (diskfs_direnter_hard): Likewise. - (diskfs_dirremove_hard): Likewise. - (diskfs_dirrewrite_hard): Likewise. - (diskfs_get_directs): Likewise. - (diskfs_dirempty): Likewise. - (count_dirents): Likewise. - -Tue Apr 23 11:28:42 1996 Michael I. Bushnell, p/BSG - - * dir.c (diskfs_dirempty): node_update -> diskfs_node_update. - - * hyper.c (swab_sblock, swab_csums): New functions. - (get_hypermetadata): If this is a swapped filesystem, set swab_disk. - Also swap csum and sblock after reading them. - (diskfs_set_hypermetadata): If swab_disk, swap the csums back before - writing them. - (copy_sblock): If swab_disk, swap the sblock before writing it. - * ufs.h (swab_disk): New variable. - (swab_short, swab_long, swab_long_long): New functions. - (read_disk_entry, write_disk_entry): New macros. - * alloc.c (ffs_realloccg): Use read/write_disk_entry when - reading/writing on-disk inode fields. - * bmap.c (fetch_indir_spec): Likewise. - * inode.c (read_disknode): Likewise. - (write_node): Likewise. - (diskfs_set_translator): Likewise. - (diskfs_get_translator): Likewise. - (diskfs_S_file_get_storage_info): Likewise. - * sizes.c (diskfs_truncate): Likewise. - (diskfs_grow): Likewise. - * pager.c (pager_unlock_page): Likewise. - * bmap.c (fetch_indir_spec): Use read/write_disk_entry when - reading/writing on-disk indirect blocks. - * sizes.c (diskfs_truncate): Likewise. - (indir_release): Likewise. - (diskfs_grow): Likewise. - * pager.c (pager_unlock_page): Likewise. - * alloc.c: Include - (ffs_blkpref): Use read_disk_entry when reading from BAP array. - (swab_cg, read_cg, release_cg): New functions. - (ffs_fragextend, ffs_alloccg, ffs_nodealloccg, ffs_blkfree, - diskfs_free_node): Use new cg access functions. - -Thu Apr 18 14:50:30 1996 Michael I. Bushnell, p/BSG - - * sizes.c (diskfs_grow): New variable `pagerpt'. - (offer_zeroes, block_extended): New functions. - (diskfs_grow): In initializing newly allocated data disk blocks with - zeroes, use less aggressive offer_zeroes instead of immediate - synchronous writes. After ffs_realloccg succeeds, use - block_extended to handle the magic. Get rid of old poke calls. - * alloc.c (ffs_realloccg): If we are allocating a new block, don't - actually free the old one here. - * sizes.c (diskfs_grow): New variable `pagerpt'. - (offer_zeroes, block_extended): New functions. - (diskfs_grow): In initializing newly allocated data disk blocks - with zeroes, use less aggressive offer_zeroes instead of immediate - synchronous writes. After ffs_realloccg succeeds, use - block_extended to handle the magic. Get rid of old poke calls. - -Tue Apr 16 15:20:07 1996 Michael I. Bushnell, p/BSG - - * dir.c (diskfs_lookup_hard): Set atime appropriately, and sync - the new atime if we are running synchronously (!). - (diskfs_dirempty): Likewise. - (diskfs_direnter_hard): Set mtime appropriately. - (diskfs_dirremove_hard): Likewise. - (diskfs_dirrewrite_hard): Likewise. - - * inode.c (diskfs_write_disknode): Only do sync if WAIT is set. - -Thu Apr 4 16:39:22 1996 Miles Bader - - * inode.c (diskfs_cached_lookup): Intialize NP->cache_id *after* - NP exists. - -Wed Apr 3 16:03:51 1996 Michael I. Bushnell, p/BSG - - * inode.c (diskfs_cached_lookup): Renamed from `iget'. All - callers changed. Initialize NP->cache_id. - -Fri Mar 29 16:52:31 1996 Michael I. Bushnell, p/BSG - - * sizes.c (diskfs_truncate): Cast DI->di_shortlink to correct type - before adding a character count to it. - -Mon Mar 25 13:08:10 1996 Michael I. Bushnell, p/BSG - - * dir.c (diskfs_null_dirstat): New function. - -Fri Mar 22 23:43:53 1996 Miles Bader - - * inode.c (read_symlink_hook): Only set NP's atime if !readonly. - -Wed Mar 20 14:36:31 1996 Michael I. Bushnell, p/BSG - - * dir.c (diskfs_lookup_hard): Don't do initial or final permission - checking here. - * dir.c (diskfs_dirrewrite_hard): Renamed from diskfs_dirrewrite. - No longer call modification tracking routines. - (diskfs_dirremove_hard): Renamed from diskfs_dirremove. No longer call - modification tracking routines. - (diskfs_direnter_hard): Renamed from diskfs_direnter. No longer call - modification tracking routines. - (diskfs_lookup_hard): Renamed from diskfs_lookup. - -Mon Mar 18 19:50:41 1996 Miles Bader - - * main.c (main): Pass new arg to argp_parse. - -Mon Mar 18 12:33:06 1996 Michael I. Bushnell, p/BSG - - * pager.c (diskfs_max_user_pager_prot) [add_pager_max_prot]: - (a == b) ? 1 : 0 ====> (a == b). - -Fri Feb 23 15:27:05 1996 Roland McGrath - - * hyper.c (get_hypermetadata): Use diskfs_device_arg in unclean msgs. - -Wed Feb 21 05:57:12 1996 Roland McGrath - - * hyper.c: Implement proper handling of the filesystem `clean bit'. - (ufs_clean): New variable. - (get_hypermetadata): Set it from the fs_clean flag. If not clean, - complain and force read-only. Complain when ignoring COMPAT_BSD42. - (diskfs_set_hypermetadata): Set the clean flag in the superblock - when CLEAN and fs was clean to start with. - (copy_sblock): Remove bogus clean flag frobnication. - -Fri Feb 16 17:05:36 1996 Miles Bader - - * main.c (main): Check error return from diskfs_init_diskfs. - -Sat Jan 6 11:50:14 1996 Roland McGrath - - * ufs.h (diskpager, diskpagerport, disk_image): Variables removed. - Include instead. - (sync_disk_blocks): Use `disk_pager' in place of `diskpager->p'. - * pager.c (diskfs_shutdown_pager, diskfs_sync_everything): Use - `disk_pager' in place of `diskpager->p'. - (create_disk_pager): Rewritten using disk_pager_setup. - * pokeloc.c (sync_disk): Use `disk_pager' in place of `diskpager->p'. - * sizes.c (indir_release): Likewise. - * main.c (diskfs_reload_global_state): Likewise. - -Thu Jan 4 19:10:11 1996 Roland McGrath - - * main.c (main): Don't map disk image here; create_disk_pager now - does it. - - * hyper.c (get_hypermetadata, copy_sblock): Don't put - diskfs_catch_exception () inside assert, bonehead! Use - assert_perror on a variable of its result. - -Mon Jan 1 16:38:14 1996 Michael I. Bushnell, p/BSG - - * pager.c (pager_unlock_page): When allocating block in direct - array, clear it synchronously just like we do when it goes in the - indirect array. - -Thu Nov 9 14:01:30 1995 Michael I. Bushnell, p/BSG - - * dir.c (struct dirstat): New member `nbytes'. - (dirscanblock): If DS->type is COMPRESS, still look - for TAKE/SHRINK possibilities. Also, if it's COMPRESS, - still look to see if the current block can be compressed - with fewer byte copies. - -Sun Nov 5 02:08:38 1995 Miles Bader - - * main.c (main): Add flags arg to diskfs_startup_diskfs call. - -Sat Nov 4 20:01:58 1995 Miles Bader - - * inode.c (diskfs_S_file_get_storage_info): Add FLAGS argument. - -Thu Oct 19 12:50:11 1995 Miles Bader - - * pager.c (diskfs_max_user_pager_prot): Return what we discovered, - instead of 1. - - * dir.c (diskfs_lookup, diskfs_dirempty): Give diskfs_get_filemap - a protection arg. - * sizes.c (diskfs_truncate, diskfs_grow): Ditto. - - * hyper.c (diskfs_readonly_changed): Give the 2nd arg to - vm_protect an appropiate type. - - * pager.c (diskfs_max_user_pager_prot): Stop iterating early if poss. - -Wed Oct 18 16:28:42 1995 Miles Bader - - * ufs.h (struct user_pager_info): Add max_prot field. - * pager.c (diskfs_get_filemap): Add PROT parameter, & use it. - (diskfs_pager_users): Split out block_caching & enable_caching. - (block_caching, enable_caching): New function. - (diskfs_max_user_pager_prot): New function. - - * main.c (main): Always include VM_PROT_WRITE in max prot. - * hyper.c (diskfs_readonly_changed): Change the protection of - DISK_IMAGE to reflect the new state. Clear SBLOCK_DIRTY if readonly. - - * inode.c (read_disknode): Bother to set the allocsize field. - - * ufs.h (struct rwlock): Structure deleted. - (rwlock_init, rwlock_reader_unlock, rwlock_reader_lock, - rwlock_writer_lock, rwlock_writer_unlock): Functions deleted. - - -Tue Oct 17 14:49:43 1995 Miles Bader - - * inode.c (diskfs_node_reload): New function. - (iget): Move allocsize setting into read_disknode. - * pager.c (flush_node_pager): New function. - * ufs.h (zeroblock, sblock, csum): Declare extern. - (flush_node_pager, flush_pokes): New declarations. - * pokeloc.c (flush_pokes): New function. - * hyper.c (diskfs_readonly_changed): New function. - (get_hypermetadata): Move compat_mode futzing & disk size - validation here from main. - (zeroblock, sblock, csum): Define (were common). - (get_hypermetadata): Only allocate SBLOCK if not already done. - Deallocate any old ZEROBLOCK and CSUM storage. - (diskfs_readonly_changed): New function. - * main.c (main): Move stuff into get_hypermetadata. - Writable init code moved to diskfs_readonly_changed. - (diskfs_reload_global_state): New function. - -Fri Oct 13 15:03:37 1995 Miles Bader - - * main.c (main): Use new handy diskfs routines and get rid of - tons of junk. Main should be almost all ufs-specific now. - (USAGE, usage, SHORT_OPTS, long_opts, parse_opt, trans_parse_arg): RIP. - (printf_lock): Initialize. - -Thu Oct 12 18:48:04 1995 Miles Bader - - * pager.c (pager_unlock_page, pager_write_page, pager_read_page): - Use diskfs_device_{read,write}_sync instead of dev_{read,write}_sync. - * hyper.c (diskfs_set_hypermetadata): Ditto. - * sizes.c (diskfs_grow): Ditto. - * pager.c (pager_report_extent): Calculate the pager size. - * ufs.h (dev_read_sync, dev_write_sync, dev_write, diskpagersize): - Decls removed. - - * Makefile (SRCS): Remove devio.c. - * ufs.h (ufs_device, ufs_device_name): Variables removed. - * inode.c (diskfs_S_file_get_storage_info): Use DISKFS_DEVICE - instead of UFS_DEVICE, and DISKFS_DEVICE_NAME instead of - UFS_DEVICE_NAME. - -Sat Oct 7 20:47:56 1995 Miles Bader - - * main.c (diskfs_init_completed): Function deleted (now in libdiskfs). - (thread_cancel): Function deleted. - -Fri Oct 6 17:30:23 1995 Miles Bader - - * inode.c (diskfs_S_file_get_storage_info): Change type of - ADDRESSES to off_t **, and add the BLOCK_SIZE parameter. - -Wed Oct 4 17:21:33 1995 Miles Bader - - * inode.c (diskfs_set_statfs): fsys_stb_bsize -> fsys_stb_iosize. - fsys_stb_fsize -> fsys_stb_bsize. - - * main.c (parse_opt): Rearrange slightly. - -Tue Sep 26 11:54:35 1995 Michael I. Bushnell, p/BSG - - * inode.c: Include . - (diskfs_S_file_get_storage_info): New function. - * main.c (main): Delete var `devname'. Use `ufs_device_name' - throughout instead. - * ufs.h (ufs_device_name): New var. - -Fri Sep 22 13:22:42 1995 Roland McGrath - - * hyper.c (get_hypermetadata): Use %Zd format for result of sizeof. - -Tue Sep 19 13:41:46 1995 Miles Bader - - * Makefile (LDFLAGS): New variable. - -Wed Sep 13 12:30:23 1995 Michael I. Bushnell, p/BSG - - * dir.c (diskfs_lookup): Don't attempt to lock NP if NPP is not - set. Don't even set NP if NPP is not set; use INUM as "lookup - succeeded flag" instead. Lookups for REMOVE and RENAME now *must* - set NPP. - -Wed Sep 6 11:01:50 1995 Miles Bader - - * pager.c (diskfs_pager_users): Ignore the disk pager when seeing - if there are any active pagers. - -Mon Aug 28 17:07:36 1995 Roland McGrath - - * Makefile (ufs): Depend on ../libshouldbeinlibc/libshouldbeinlibc.a. - -Fri Aug 25 17:14:09 1995 Michael I. Bushnell, p/BSG - - * sizes.c (diskfs_truncate): When freeing direct blocks mentioned - in a single indirect block, or single indirect blocks mentioned in - a double, only call the free routine (ffs_blkfree or - indir_release, respectively) if the block is actually allocated. - -Wed Aug 23 12:24:07 1995 Miles Bader - - * Makefile (ufs): Add explicit dependencies. - (HURDLIBS, LDFLAGS, REMHDRS): Removed. - Rules associated with ../lib removed. - -Fri Jul 21 17:48:12 1995 Michael I Bushnell - - * pager.c (diskfs_get_filemap): Drop initial reference created by - pager_create. - - * pager.c (diskfs_get_filemap): Avoid race with simultaneous - termination by looping until we win. - (pager_clear_user_data): Only clear UPI->np->dn->fileinfo if it - still points to us. - -Mon Jul 17 14:35:25 1995 Michael I Bushnell - - * pager.c (thread_function): Don't have any global timeout here; - we don't use it anyhow. - -Thu Jul 6 15:42:52 1995 Michael I Bushnell - - * Makefile: Removed dependencies that are now automatically - generated. - -Mon Jun 26 20:17:42 1995 Michael I Bushnell - - * pager.c: Include . - (diskfs_pager_users): New function. - -Thu Jun 22 11:41:04 1995 Michael I Bushnell - - * pager.c (thread_function): Move thread_function to be non-local, - of course, because it needs to live even after create_disk_pager - returns. - - * main.c (thread_cancel): New function (HACK). - - * Makefile (HURDLIBS): Add libihash. - - * main.c (main): Have main thread exit when done instead of - calling a diskfs function. - -Wed Jun 21 12:20:01 1995 Michael I Bushnell - - * ufs.h (user_pager_info): Removed members next and prevp. - * pager.c (pager_clear_user_data): Don't maintain pager linked - list. - (diskfs_get_filemap): Don't maintain pager linked list. - (pager_dropweak): New function. - (pager_traverse): Delete function. - (diskfs_shutdown_pager): Use ports_bucket_iterate instead of - pager_traverse. - (diskfs_sync_everything): Likewise. - - * pager.c (pager_bucket): New variable. - (create_disk_pager): Provide pager_bucket in call to pager_create. - (diskfs_get_filemap): Likewise. - (diskfs_file_update): Use ports reference calls directly instead - of pager wrappers. - (drop_pager_softrefs): Likewise. - (allow_pager_softrefs): Likewise. - (pager_traverse): Likewise. - (create_disk_pager): Initialize pager_bucket here and fork off - service thread for pager ports. - - * sizes.c (diskfs_truncate): Likewise. - - * dir.c (diskfs_lookup): Provide initialization for BUFLEN. - (diskfs_direnter): Move assignment out of if test. - -Tue Jun 20 11:48:06 1995 Michael I Bushnell - - * sizes.c (diskfs_grow): Provide initialization of POKE_OFF. - * alloc.c (ffs_realloccg): Remove assignment from if tests. - * sizes.c (diskfs_truncate): Likewise. - * bmap.c (fetch_indir_spec): Likewise. - -Mon Jun 19 21:17:21 1995 Michael I Bushnell - - * inode.c (diskfs_node_iterate): New function. - (write_all_disknodes): Use it. - -Wed Jun 14 16:18:55 1995 Michael I Bushnell - - * inode.c (diskfs_get_translator): Conform to new memory usage - semantic. - -Sat May 20 00:17:30 1995 Miles Bader - - * main.c (trans_parse_args): Use options_parse & - diskfs_standard_startup_options to parse our translator options. - (usage): New function. - (parse_opt): New function. - - * Makefile (CPPFLAGS): Add -I../lib, to get include lib include files, - and $(CPPFLAGS-$(notdir $<)) to get file-specific cpp options. - Add a vpath for %.c to ../lib, so we can use source files from there. - -Mon May 15 13:14:48 1995 Michael I Bushnell - - * pager.c (pager_clear_user_data): Doc fix. - -Sat May 13 05:04:11 1995 Roland McGrath - - * Makefile (OBJS): Remove exec_server_image.o. - (exec_server_image.o): Rule removed. - -Mon May 8 08:43:43 1995 Miles Bader - - * dir.c (diskfs_lookup): When looping back to try_again: because - we're looking up "..", be sure and trash the mapping we made of - the directory's pager -- otherwise the reference to the pager - never gets dropped and we can never free the node. - - * dir.c (diskfs_lookup): ds->type was being compared to LOOKING, which - value it can never have. Compare ds->stat against LOOKING instead. - - * pager.c (pager_clear_user_data): Don't die when called on the - disk pager. - - * inode.c (write_all_disknodes): Fix typo `alloc' --> `alloca'. - -Tue May 2 11:59:09 1995 Michael I Bushnell - - * pager.c (pager_clear_user_data): Acquire pagerlistlock around - modifications to UPI->next/prevp list structure. - -Fri Apr 28 19:02:05 1995 Michael I Bushnell - - * inode.c (write_all_disknodes): We have to really lock the nodes - around the calls to diskfs_set_node_times and write_node; this in - turn forces us to have real refereces. - -Thu Apr 13 16:36:57 1995 Miles Bader - - * main.c (main): Don't abort if a std file descriptor is already open. - -Tue Apr 4 20:08:25 1995 Michael I Bushnell - - * inode.c (diskfs_set_translator): When freeing passive - translator, account for blocks freed in NP->dn_stat.st_blocks. - -Fri Mar 31 13:43:27 1995 Michael I Bushnell - - * sizes.c (diskfs_truncate): Don't acquire writer lock on - NP->dn->allocptrlock until after forcing delayed copies through; - otherwise the pageins will deadlock attempting to get a reader - lock to service them. This is safe, because we only need - NP->allocsize here, and that can't change as long as we hold - NP->lock. - -Mon Mar 20 13:58:44 1995 Michael I Bushnell - - * consts.c (diskfs_synchronous): New variable. - -Fri Mar 17 14:31:04 1995 Michael I Bushnell - - * alloc.c (ffs_clusteracct): Make static. - (alloc_sync): New function. - (ffs_alloc): Call alloc_sync. - (ffs_realloccg): Likewise. - (diskfs_alloc_node): Likewise. - (ffs_blkfree): Likewise. - (diskfs_free_node): Likewise. - -Sat Jan 28 14:59:26 1995 Roland McGrath - - * Makefile (OBJS): Remove reference to libc's devstream.o. - -Fri Nov 11 11:45:38 1994 Michael I Bushnell - - * hyper.c (diskfs_set_hypermetadata): Always use dev_write_sync to - avoid device_write bug that says you can't modify the buffer until - device_write returns. Also remember to deallocate BUF. - -Thu Nov 10 13:27:09 1994 Michael I Bushnell - - * main.c (main): Issue decent prompt. - - * hyper.c (diskfs_set_hypermetadata): Copy CSUM into a - page-aligned page-sized buffer for disk write to avoid inane - kernel bug. - -Wed Nov 9 05:43:14 1994 Michael I Bushnell - - * main.c (main): Behave more reasonably if we can't open DEVNAME. - -Tue Nov 8 00:03:20 1994 Roland McGrath - - * pager.c (pager_write_page): Use %p for printing PAGER. - - * ufs.h: Declare copy_sblock. - -Wed Nov 2 16:06:10 1994 Michael I Bushnell - - * hyper.c (copy_sblock): Don't copy csum here. - (diskfs_set_hypermetadata): Write csum directly to disk here. - -Thu Oct 27 20:58:08 1994 Michael I Bushnell - - * dir.c (diskfs_lookup): diskfs_get_filemap returns a send right, - so don't create an additional one here. - (diskfs_dirempty): Likewise. - * sizes.c (diskfs_truncate): Likewise. - (diskfs_grow): Likewise. - -Tue Oct 25 12:49:41 1994 Michael I Bushnell - - * hyper.c (copy_sblock): Call record_poke for csum and superblock - after modifying them. - - * pager.c (diskfs_shutdown_pager): Call copy_sblock. - (diskfs_sync_everything): Likewise. - - * alloc.c (ffs_fragextend): Call record_poke for CG after - modifying it. Also set CSUM_DIRTY and SBLOCK_DIRTY. - (ffs_alloccg): Likewise. - (ffs_alloccgblk): Likewise. - (ffs_nodealloccg): Likewise. - (ffs_blkfree): Likewise. - (diskfs_free_node): Likewise. - -Fri Oct 7 01:32:56 1994 Roland McGrath - - * main.c (diskfs_init_completed): Don't call _hurd_proc_init. - (saved_argv): Variable removed. - (main): Don't set saved_argv. Pass ARGV to diskfs_start_bootstrap. - -Wed Oct 5 22:18:46 1994 Michael I Bushnell - - * inode.c (read_disknode): If we are the bootstrap filesystem, - then getpid changes once proc starts up. So only call getpid - once, thus not allowing st_dev values to mysteriously change. - -Wed Oct 5 12:56:53 1994 Michael I Bushnell - - * alloc.c (diskfs_alloc_node): Abort if free inode has - translator attached. - -Tue Oct 4 18:33:35 1994 Michael I Bushnell - - * pager.c (pager_unlock_page): Call diskfs_catch_exception. - -Tue Oct 4 00:16:04 1994 Michael I Bushnell - - * inode.c (diskfs_lost_hardrefs): Comment out body. - * ufs.h (node2pagelock): New variable. - * pager.c (node2pagelock): Initialize. - (diskfs_get_filemap): Don't let node hold a reference to the pager. - (pager_clear_user_data): Acquire node2pagelock and clear - the node's reference to the pager. - (diskfs_file_update): Hold node2pagelock for reference - of NP->dn->fileinfo. - (drop_pager_softrefs): Likewise. - (allow_pager_softrefs): Likewise. - (diskfs_get_filemap): Likewise. - * sizes.c (diskfs_truncate): Likewise. - - * Makefile (SRCS): Added pokeloc.c. - -Mon Oct 3 15:03:38 1994 Michael I Bushnell - - * sizes.c (diskfs_truncate): Rewritten. - - * bmap.c (fetch_indir_spec): Initialize OFFSET values to -2, - meaning that the entry is not needed. If LBN is negative, - then don't set values for the data block. - - * inode.c (write_node): Call record_poke after writing - dinode. - (create_symlink_hook): Likewise. - (diskfs_set_translator): Likewise. - * pager.c (pager_unlock_page): Likewise. - * sizes.c (diskfs_truncate): Likewise. - * pager.c (pager_unlock_page): Call record_poke after writing - indirect block. - * sizes.c (diskfs_grow): Likewise. - (diskfs_grow): Likewise. - * pager.c (diskfs_sync_everything) [sync_one]: If this is the - disk pager, call sync_disk instead. - * pokeloc.c: New file. - -Fri Sep 30 11:25:36 1994 Michael I Bushnell - - * dir.h: Delete DT_* definitions; they are now in . - * dir.c (diskfs_get_directs): Set USERP->d_type as DT_UNKNOWN. - When the bugs in the type fields are fixed (dealing with - multiple links and mode changes) then this can actually return - the value. - -Thu Sep 29 17:16:58 1994 Roland McGrath - - * main.c (main): Test getpid()>0 to decide we are a normal - translator instead of the boot fs. Fetch bootstrap port after - possibly calling diskfs_parse_bootargs, not before. - -Tue Sep 27 15:24:58 1994 Michael I Bushnell - - * sizes.c (diskfs_grow) [computation of newallocsize]: Last block - number is one less than the total number of blocks. - -Tue Sep 27 11:58:44 1994 Michael I Bushnell - - * bmap.c (fetch_indir_spec): Single indirect block pointer is - in the INDIR_SINGLE slot, not the INDIR_DOUBLE slot. - -Mon Sep 26 20:47:30 1994 Michael I Bushnell - - * Makefile (SRCS): Added bmap.c. - - * main.c (main): Don't call pager_init. - - * inode.c (diskfs_get_translator): Repair to read translator - correctly. - - * sizes.c (diskfs_grow): Compute block numbers in a more clean - (and confidently correct) fashion. - (diskfs_truncate): Set NP->allocsize from a properly rounded - value. - -Mon Sep 26 12:50:38 1994 Michael I Bushnell - - * inode.c (diskfs_lost_hardrefs): "Know" that a pager starts - with a portinfo; we don't actually have access to the pager - struct here. - -Fri Sep 23 14:21:55 1994 Michael I Bushnell - - [ Continuing yesterday's changes. ] - * ufs.h (struct dirty_indir): New type. - (struct disknode): New member `dirty'. - * inode.c (iget): Initialize DN->dirty. - * bmap.c (mark_indir_dirty): New function. - * pager.c (pager_unlock_page): Call mark_indir_dirty before - writing into indirect blocks. - (diskfs_file_update): Sync indirect blocks here. - (pager_traverse): Simplify; do FILE_DATA and diskpager. - (pager_init): Removed function. - (create_disk_pager): New function. - * sizes.c: Completely rewritten. - * main.c (main): Spawn first thread sooner so we can - map and look at the disk image. - * hyper.c (get_hypermetadata): Moved firewall asserts - here from pager_init. - -Thu Sep 22 11:28:46 1994 Michael I Bushnell - - [This long series of changes deletes the DINODE, CG, SINDIR, - and DINDIR pagers and adds a new pager type DISK.] - * ufs.h (struct disknode) Removed DINLOCK, SINLOCK, and - SININFO members. New member ALLOCPTRLOCK renamed from DATALOCK. - Removed SINLOC, DINLOC, SINLOCLEN, and DINLOCLEN. - (struct user_pager_info) [enum pager_type]: Removed types - DINODE, CG, SINDIR and DINDIR; added type DISK. - (dinpager, dinodepager, cgpager): Deleted vars. - (diskpager): New var. - (dinmaplock, sinmaplock, pagernplock): Deleted vars. - (sblock_dirty, csum_dirty, cgs, dinodes): Deleted vars. - (fsaddr): New macro. - (dino, indir_block, cg_locate): New inline functions. - (sync_disk_blocks, sync_dinode): New inline functions. - (struct iblock_spec): New type. - * pager.c (dinport, dinodeport, cgport, sinlist): Deleted vars. - (filepagerlist): Renamed from filelist. - (pagernplock): Deleted variable. - (find_address): Removed switch; support only DISK and FILE_DATA. - (pager_report_extent): Likewise. - (pager_unlock_page): Removed switch. Return without comment for - DISK; allocate indirect blocks as necessary right here for - FILE_DATA. - (sin_map, sin_remap, sin_unmap, din_map, din_unmap): Deleted - functions. - (indir_alloc, sync_dinode): Deleted functions. - (enqueue_pager, dequeue_pager): Deleted functions. - (diskfs_file_update): No longer lock pagernplock; nothing - to do with sininfo. - (drop_pager_softrefs): Likewise. - (allow_pager_softrefs): Likewise. - (diskfs_get_filemap): Put pager on filepagerlist right here - instead of through pager_enqueue. - (pager_clear_user_data): Likewise, mutatis mutandis. - * main.c (main): Call create_disk_pager and then map the - entire disk into disk_image. - * hyper.c (get_hypermetadata): Use bcopy instead of dev_read_sync. - (diskfs_set_hypermetadata): NOP out function. - (copy_sblock): New function, substance of code is from old - diskfs_set_hypermetadata. - * inode.c (iget): Don't initialize deleted disknode fields. - (diskfs_node_norefs): Don't verify that deleted disknode - fields are not set. - (read_disknode): Get dinode from DINO, not DINODES array. - (write_node): Likewise. - (create_symlink_hook): Likewise. - (read_symlink_hook): Likewise. - (diskfs_set_translator): Likewise. - (diskfs_get_translator): Likewise. - (diskfs_node_translated): Likewise. - * alloc.c (ffs_realloccg): Likewise. - (ffs_fragextend): Use cg_locate instead of cgs array. - (ffs_alloccg): Likewise. - (ffs_nodealloccg): Likewise. - (ffs_blkfree): Likewise. - (diskfs_free_node): Likewise. - * inode.c (diskfs_set_translator): Use bcopy and sync_disk_blocks - instead of dev_write_sync. - (diskfs_get_translator): Likewise, mutatis mutandis. - (read_disknode): Initialize NP->istranslated. - (diskfs_set_translator): Set/clear NP->istranslated as appropriate. - (diskfs_node_translated): Removed function. - * bmap.c: New file. - - [This improves the RWLOCK mechanism and makes it more - orthogonal. It should probably be moved into a library.] - * ufs.h (struct rwlock): Added MASTER and WAKEUP members. - (struct disknode): Removed RWLOCK_MASTER and RWLOCK_WAKEUP - fields. - (rwlock_reader_lock): Ommitted arg DN; use new MASTER and WAKEUP - members inside LOCK instead. - (rwlock_writer_lock): Likewise. - (rwlock_reader_unlock): Likewise. - (rwlock_init): Initialize new MASTER and WAKEUP fields. - * inode.c (iget): Don't deal with RWLOCK_MASTER and RWLOCK_WAKEUP. - * pager.c (find_address): Deleted arg DNP. Only pass one - arg to rwlock functions. - (pager_read_page): Deleted var DN; only pass one arg to rwlock - functions. - (pager_write_page): Likewise. - -Wed Sep 21 00:26:25 1994 Michael I Bushnell - - * pager.c (allow_pager_softrefs): Unlock PAGERNPLOCK when - we're done with it. - (sin_map): Hold PAGERNPLOCK all the way until we're done - with the sininfo pointer. - (pagernplock): No longer static. - * ufs.h (pagernplock): Declare here. - - * sizes.c (diskfs_grow): Don't call diskfs_file_update here. - This was done to prevent too much dirty data from accumulating - and then overwhelming the pager later. But that's really the - pager's responsibility. - - * ufs.h (struct disknode): New members `dinloclen' and `sinloclen'. - * inode.c (iget): Initialize DN->dinloclen and DN->sinloclen. - (diskfs_node_norefs): Verify that DN->dinloclen and DN->sinloclen - are both zero. - * pager.c (find_address) [SINDIR]: Verify that reference is - within bounds of NP->dn->dinloc. - (pager_unlock_page) [SINDIR]: Likewise. - (din_map): Set NP->dn->dinloclen. - (din_unmap): Clear NP->dn->dinloclen. - (find_address) [FILE_DATA]: Verify that reference is within - bounds of NP->dn->sinloc. - (pager_unlock_page) [FILE_DATE]: Likewise. - (sin_map): Set NP->dn->sinloclen. - (sin_remap): Reset NP->dn->sinloclen. - (sin_unmap): Clean NP->dn->sinloclen. - - * pager.c (pager_write_page): Flush stdout after printf. - (pager_unlock_page) [FILE_DATA]: Likewise. - - * sizes.c (diskfs_truncate): In all references to sinloc and - dinloc arrays, verify that references are within allocated bounds. - (diskfs_grow): Likewise. - (sindir_drop): Likewise. - - * pager.c: Create new mapping with extent NEWSIZE, not SIZE (which - was the old size of the mapping). - -Tue Sep 20 15:51:35 1994 Michael I Bushnell - - * pager.c (pager_report_extent) [SINDIR]: Remove erroneous extra - division by block size. - (sin_remap): Likewise. - -Mon Sep 19 17:34:11 1994 Michael I Bushnell - - * inode.c (create_symlink_hook): Write assert test correctly. - - * dir.c (diskfs_direnter) [EXTEND]: Reference file size only - *once*; don't rely on the behavior if diskfs_grow vis a vis - file size. - -Fri Sep 16 10:29:42 1994 Michael I Bushnell - - * dir.c (dirscanblock): Compute offset correctly for mangled - entry notice. - - * dir.c (diskfs_direnter) [EXTEND]: Reference file size only - once before calling diskfs_grow in case diskfs_grow actually - increases the size. - - * inode.c (diskfs_set_statfs): Set fsid from getpid. - (read_disknode): Likewise. - - * dir.h (struct directory_entry): Renamed from struct direct. - * dir.c: All uses of struct direct changed to use - struct directory_entry. - (diskfs_get_directs): New var `userp'. Copy from *ENTRYP into - it (set at DATAP) more cleanly. - -Mon Sep 12 11:30:48 1994 Michael I Bushnell - - * hyper.c (diskfs_set_hypermetadata): Don't frob clean and dirty - bits if we are readonly. - -Sat Sep 10 11:41:06 1994 Roland McGrath - - * main.c (main): When started up as a passive translator, - open fds 0, 1, and 2 on /dev/console for debugging messages. - Call diskfs_init_diskfs with no args; after warp_root, call - diskfs_startup_diskfs on BOOTSTRAP. Compare BOOTSTRAP to - MACH_PORT_NULL instead of zero. - -Fri Sep 9 13:02:33 1994 Michael I Bushnell - - * main.c (trans_parse_args): Fix and enable. - -Tue Sep 6 11:29:55 1994 Michael I Bushnell - - * inode.c (iget): Remove old assert test that checked for bad - inode block allocations. - -Thu Sep 1 11:39:12 1994 Michael I Bushnell - - * tables.c: Don't include "ufs.h"; include . Then - this file can be used unmodified by fsck. - -Tue Aug 30 13:36:37 1994 Michael I Bushnell - - * inode.c (diskfs_set_translator): ffs_blkfree doesn't have - a return value. - -Mon Aug 29 12:49:17 1994 Michael I Bushnell - - * inode.c (diskfs_set_translator): If NAMELEN is zero, then - make the node have no translator. - -Fri Aug 26 12:28:20 1994 Michael I Bushnell - - * inode.c (read_disknode): 4.4 fsck sometimes sets the author - field to -1 to mean "ignore old uid location"; take that to mean - "author == uid". - (diskfs_set_translator): If we are allocating a new block for - the translator, then account for it in st_blocks. - -Thu Aug 18 12:41:12 1994 Michael I Bushnell - - * Makefile (HURDLIBS): Use short version. - - * alloc.c (diskfs_alloc_node): Bother to set *NPP before - returning. - -Tue Aug 16 10:48:04 1994 Michael I Bushnell - - * Makefile (LDFLAGS): New variable. - -Fri Aug 5 15:51:09 1994 Michael I Bushnell - - * dir.c (diskfs_direnter) [EXTEND]: Crash if the entry won't - fit in the new block. - (diskfs_lookup): Return ENAMETOOLONG if the name is bigger than - MAXNAMLEN. - - * dir.c (diskfs_get_directs): Set USERD->d_reclen correctly. - -Fri Jul 22 15:12:35 1994 Michael I Bushnell - - * Makefile: Rewritten in accord with new scheme. - -Wed Jul 20 13:28:38 1994 Michael I Bushnell - - * main.c (main): Don't set diskfs_dotdot_file. - -Tue Jul 19 21:51:54 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) - - * ufs.h: Removed defns of u_quad_t, quad_t; now in . - Removed defn of struct timespec; now in . - -Tue Jul 19 12:47:31 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * main.c (main): Deleted var `diskfs_dotdot_file'. - (trans_parse_args): Don't set diskfs_dotdot_file; don't expect - dotdot from fsys_getroot. - - * Makefile (LDFLAGS): Moved to rule for `ufs' and commented out. - (ufs): Don't use variable $(link) anymore. - -Mon Jul 18 14:55:17 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * dir.c (diskfs_get_directs): Return data to user in old format. - Add new code for new format, maintaining compatibility correctly, - but comment it out until the library is ready. - - * hyper.c (diskfs_set_hypermetadata): If we presumed to - set new values of fs_maxfilesize, fs_qbmask, and fs_qfmask, - then restore the originals before writing out the superblock. - - * pager.c (diskfs_get_filemap): Test should be S_ISLNK, not - S_ISSOCK. - - * hyper.c (get_hypermetadata): Set new constants in filesystems - which don't have them yet. - (get_hypermetadata): Cast MAXSYMLINKLEN to long to avoid - converting sblock->fs_maxsymlinklen into an unsigned. - - * subr.c (scanc, skipc): New functions. - (ffs_setblock): Use assert instead of panic. - - * inode.c (read_disknode): Set old stat structure until the header - file gets changed. - -Fri Jul 15 12:07:15 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * sizes.c: Include for bzero. - * fs.h (blksize): Comment out dblksize macro. In blksize - macro, use NP->allocsize instead of IP->i_size. - - * dinode.h (INDIR_SINGLE, INDIR_DOUBLE, INDIR_TRIPLE): New macros. - - * inode.c (read_disknode, write_node): Use new stat and dinode - fields for times. - - * ufs.h: Change `nextgennumber' to be `u_long' instead of int. - Change prototypes of some alloc.c functions. - * alloc.c (ffs_alloc): Declare to return error_t. - (ffs_realloccg): Likewise. - (ffs_hashalloc, ffs_alloccg, ffs_fragextend, ffs_alloccg, - ffs_dirpref, ffs_nodealloccg, ffs_allccgblk, ffs_mapsearch, - ffs_clusteracct): Provide forward declarations. - (ffs_realloccg): Use printf instead of log. - Make BPREF volatile for setjmp safety. - (diskfs_alloc_node): Use diskfs global variable instead of TIME. - (ffs_nodealloccg): Likewise. - (ffs_blkfree): Likewise. - (diskfs_free_node): Likewise. - (ffs_blkfree, ffs_clusteracct): Declare as void. - (ffs_alloccg, ffs_nodealloccg): Declare as u_long. - - * ufs.h: Change prototypes of some subr.c functions. - * subr.c (ffs_isblock): Use assert instead of panic. - (ffs_clrblock): Likewise. - - * hyper.c: Include "dinode.h". - - * dinode.h (LINK_MAX): New macro, from BSD sys/sys/syslimits.h. - * fs.h (MAXBSIZE, MAXFRAG): New macros, from BSD sys/sys/param.h. - - * hyper.c (get_hypermetadata): Provide first arg in call to - fsbtodb. - (diskfs_set_hypermetadata): Likewise. - * inode.c (diskfs_set_translator): Likewise. - (diskfs_get_translator): Likewise. - * pager.c (find_address): Likewise. - (indir_alloc): Likewise. - * inode.c (iget): Provide first arg in call to lblkno. - * sizes.c (diskfs_truncate): Likewise. - * pager.c (find_address): Likewise. - * sizes.c (diskfs_grow): Likewise. - * inode.c (iget): Provide first arg in call to fragroundup. - * sizes.c (diskfs_trucate): Likewise. - * sizes.c (diskfs_grow): Likewise. - * inode.c (iget): Provide first arg in call to blkroundup. - * pager.c (pager_unlock_page): Likewise. - * sizes.c (diskfs_truncate): Likewise. - * sizes.c (diskfs_grow): Likewise. - * pager.c (find_address): Provide first arg in call to cgtod. - * pager.c (find_address): Provide first arg in call to cgimin. - * pager.c (find_address): Provide first arg in call to blktofrags. - * pager.c (find_address): Provide first arg in call to blkoff. - * sizes.c (diskfs_truncate): Likewise. - * sizes.c (diskfs_grow): Likewise. - * sizes.c (diskfs_truncate): Provide first arg in call to blksize. - * sizes.c (diskfs_grow): Likewise. - * sizes.c (diskfs_truncate): Provide first arg in call to numfrags. - - * ufs.h: Added temporary declarations of `u_quad_t', `quad_t', and - `struct timespec'. - - * pager.c (diskfs_get_filemap): Make sure that this is - a kind of node that can be validly read. - - * inode.c (create_symlink_hook): Renamed from symlink_hook. - (read_symlink_hook): New function. - (diskfs_read_symlink_hook): Initialize. - -Thu Jul 14 12:23:45 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * alloc.c: New from 4.4 BSD; BSD version `8.8 2/21/94'. - Remove old includes; include "ufs.h", "fs.h", "dinode.h", - and . Replace panics with asserts and comment out - uprintfs. Use prototypes throughout. Replace calls - to ffs_fserr with printf. - (alloclock): New variable. - (ffs_alloc): Variable struct inode *IP is now struct node *NP; - refer to it appropriately. Initialize FS to sblock. - Lock alloclock around actual allocation steps. Reverse order - of BNP and CRED arguments; declare CRED as a protid and use - accordingly. Permit CRED to be null. - (ffs_realloccg): Variable struct inode *IP is now struct node *NP; - refer to it accordingly. Comment out U*x buffer management code. - Lock alloclock around actual allocation steps. Initialize FS - from sblock. Declare CRED as a protid and use it accordingly. - Change BUF arg to PBN (physical block number); return new block - there. - (ffs_reallocblks): Comment out. - (diskfs_alloc_node): Renamed from ialloc. Initialize FS from - sblock. Use calling sequence from . Acquire - alloclock aroud actual allocation steps. Deleted vars - `pip', `pvp' (use dir instead). Use iget instead of VFS_VGET. - Var struct inode *IP now struct node *NP. Lock gennumberlock - around frobbing of nextgennumber. - (ffs_blkpref): Arg struct inode *ip is now struct node *np; - refer to it accordingly. Initialize FS to sblock. Lock - alloclock during actual work. Use csum instead of fs_cs macro. - (ffs_hashalloc): Arg struct inode *IP is now struct node *NP; - use it accordingly. Initialize FS from sblock. - (ffs_fragextend): Arg struct inode *IP is now struct node *NP; - use it accordingly. Initialize FS from sblock. Initialize - CGP from cgs array; don't use bread. Comment out calls to brelse - and bdwrite. Set CGP->time from diskfs global var. Use csum - instead of fs_cs macro. - (ffs_alloccg): Arg struct inode *IP is now struct node *NP. - Initialize FS from sblock. Initialize CGP from cgs array; - don't use bread. Comment out calls to brelse and bdwrite. - Set CGP->time from diskfs global var. Use csum instead of - fs_cs macro. - (ffs_nodealloccg): Arg struct inode *IP is now struct node *NP. - Initialize FS from sblock. Initialize CGP from cgs array; - don't use bread. Comment out calls to brelse and bdwrite. Use - csum instead of fs_cs macro. - (ffs_blkfree): Arg struct inode *IP is now struct node *NP. - Initialize FS from sblock. Initialize CGP from cgs array; - don't use bread. Comment out calls to brelse and bdwrite. Use - csum instead of fs_cs macro. - (diskfs_free_node): Renamed from ffs_vfree. Use calling - sequence from . Initialize FS from sblock. - Deleted vars pip,pvp (use NP instead). Initialize CGP from - cgs array; don't use bread. Comment out calls to brelse and - bdwrite. Use csum instead of fs_cs macro. - (ffs_fserr): Commented out. - (ffs_dirpref): Use csum instead of fs_cs macro. - - * ufs.h (ffs_alloc): Renamed from alloc; all callers changed. - (ffs_blkfree): New arg NP; renamed from blkfree; all callers changed. - (ffs_blkpref): Renamed from blkpref; all callers changed. - (ffs_realloocg): Rename from realloccg; all callers changed. - - * fs.h: New from 4.4 BSD; BSD version `8.7 4/19/94'. - (fs_cs): Don't use fs_csp; use global csum instead. - - * subr.c: New from 4.4 BSD; BSD version `8.2 9/21/93'. - Remove old includes. Include "ufs.h" and "fs.h". - (ffs_blkatoff, ffs_checkoverlap): Comment out. - - * tables.c: New from 4.4 BSD; BSD version `8.1 6/11/93'. - Don't include ; do include "ufs.h" and "fs.h". - - * dinode.h: New from 4.4 BSD; BSD version `8.3 1/21/94'. - Remove oldids/inum union; replace with author. - Renamed di_mode to be di_model; allocated di_modeh from spare. - Allocate di_trans from spare. - (di_inumber): Remove macro. - * inode.c (read_disknode): Fetch uid and gid from new (long) - fields in dinode unless we are the old inode format, in which - case fetch them from the old fields. - (write_node): Only set new uid and gid fields if we are not - COMPAT_BSD4. Set old fields if the superblock says to. - (symlink_hook): New function. - (diskfs_create_symlink_hook): Initialize. - * sizes.c (diskfs_truncate): Deal with truncation of short - symlink properly. - - * dir.h: New from 4.4 BSD; BSD version `8.2 1/21/94'. - Substitute our version of DIRSIZ which uses the namelen. - Comment out declarations of struct dirtemplate and struct - odirtemplate. - (DIRECT_TYPE, DIRECT_NAMLEN): New macros. - * ufs.h (direct_symlink_extension): New variable. - * hyper.c (get_hypermetadata): Set direct_symlink_extension. - * dir.c (dirscanblock): Use DIRECT_NAMLEN instead of d_namlen. - (diskfs_direnter): Likewise. - (diskfs_dirempty): Likewise. - (diskfs_get_directs): Likewise. - (diskfs_direnter): Set d_type field of new slot if - direct_symlink_extension is set. - (diskfs_dirrewrite): Likewise. - - * ufs.h (compat_mode): New variable. - * main.c (main): Set compat_mode to zero if we are the bootstrap - filesystem. - * inode.c (diskfs_set_translator): Return error if compat_mode - is set. - (write_node): Don't set GNU dinode field extensions unless - compat_mode is COMPAT_GNU. - -Mon Jul 11 18:14:26 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * dir.c (diskfs_get_directs): When copying entries into DATAP, - set the d_reclen parameter of the copy to the minimum length - (because that's all we use) rather than the size that it had - in the directory itself. - -Wed Jul 6 14:41:48 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * dir.c (dirscanblock): In main loop, initialize PREVOFF - to zero, not BLOCKADDR. Otherwise, the wrong value is - stored into DS->prevoff and then diskfs_dirremove crashes. - -Tue Jul 5 14:07:38 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * dinode.h: Include before test of BYTE_ORDER. - - * Makefile (TAGSLIBS): New variable. - -Tue Jun 21 13:45:04 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * dir.c (diskfs_direnter): Update dirents of DP, not NP. - -Mon Jun 20 16:43:48 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * dir.c (diskfs_direnter) [case SHRINK]: NEW should be set to - OLDNEEDED past DS->entry, not to the start of the next entry. - - * dir.c (diskfs_direnter) [case EXTEND]: Cast in assignment - to NEW needs proper scope. - - * inode.c (diskfs_node_norefs): Free dirents list of structure - being deallocated. Also add assert checks to make sure other - state is already clean. - -Thu Jun 16 11:38:17 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) - - * dir.c (diskfs_dirempty): Map directory contents ourselves - instead of using diskfs_node_rdwr. - (struct dirstat): New structure to cache mapping between - lookup and commit operation and avoid use of diskfs_node_rdwr. - (diskfs_lookup): Map directory ourselves. Keep mapping in - DS if DS is nonzero and we might use it in direnter, dirremove, - or dirrewrite. Deallocate mapped buffer if we return some - error (other than ENOENT), or if DS is zero, or if there is - no possible commit operation to follow. When setting DS->stat - to EXTEND, do it the new way. - (dirscanblock): Changed BLKOFF to be virtual address of mapped - block and renamed it BLKADDR. New arg IDX. Use mapped block - instead of calling diskfs_node_rdwr. Set DS according to the new - rules. - (diskfs_direnter): Interpret new dirstat format. - (diskfs_dirremove): Likewise. - (diskfs_dirrewrite): Likewise. - (diskfs_drop_dirstat): Deallocate cached mapping here. - - * dir.c (dirscanblock): When we find the node for type CREATE, - invalidate DS by setting type to LOOKUP, not LOOKING. - - * dir.c (diskfs_direnter, diskfs_dirremove, diskfs_dirrewrite): - Call diskfs_notice_dirchange when appropriate. - - * dir.c (diskfs_get_directs): Deal properly with case where - BUFSIZ==0 and where NENTRIES==-1. - -Wed Jun 15 16:40:12 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) - - * main.c (main): Check device sector size and media size - on startup. - -Tue Jun 14 14:41:17 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) - - * ufs.h (struct disknode) [dirents]: New member. - * inode.c (iget): Initialize DN->dirents. - * dir.c (diskfs_direnter, diskfs_dirremove): Keep track - of dirents member. - (dirscanblock): New var `nentries'; use it to count the - number of directory entries in this block and set it if - we end up scanning the entire block. - (count_dirents): New function. - (diskfs_get_directs): New function. - -Mon Jun 13 13:50:00 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) - - * ufs.h (sinmaplock, dinmaplock): New global vars. - * inode.c (inode_init): Initialize sinmaplock and dinmaplock. - * pager.c (find_address, pager_unlock_page): Protect use - if dinloc array with dinmaplock. - (din_map, din_unmap): Doc fix. - (find_address, pager_unlock_page): Protect use of sinloc array - with sinmaplock. - (sin_map, sin_remap, sin_unmap): Doc fix. - (pager_clear_user_data): Acquire sinmaplock and dinmaplock - instead of NP->dn->datalock and NP->dn->sinlock respectively. - - * sizes.c (diskfs_truncate, diskfs_grow): Protect use of sinloc - and sindir mapping functions with sinmaplock. - (sindir_drop): Protect use of dinloc and dindir mapping functions - with dinmaplock. - - * ufs.h (struct rwlock): New type. - (struct disknode) [dinlock, sinlock, datalock]: Use read-write lock. - Change comments so that these don't lock dinloc and sinloc anymore. - [rwlock_master, rwlock_wakeup]: New members. - (rwlock_reader_lock, rwlock_writer_lock, rwlock_reader_unlock, - rwlock_writer_unlock, rwlock_init): New functions. - * inode.c (iget): Initialize DN->rwlock_master and - DN->rwlock_wakeup. Change initialization of DN->dinlock, - DN->sinlock, and DN->datalock to use rwlock_init. - * pager.c (find_address): Lock NP->dn->dinlock, NP->dn->sinlock, - and NP->dn->datalock with rwlock_reader_lock. Change type of - parameter NPLOCK to be a read-write lock. New parm DNP. Callers - changed. - (pager_read_page, pager_write_page): Change type of NPLOCK to be - read-write lock; call rwlock_reader_unlock instead of - mutex_unlock. New variable DN. - (pager_unlock_page): Use rwlock_writer_lock to lock - NP->dn->dinlock, NP->dn->sinlock, and NP->dn->datalock. - * sizes.c (diskfs_truncate, diskfs_grow): Change locks of DATALOCK - field to use rwlock_writer_{un,}lock. - (sindir_drop): Ditto for SINLOCK field. - (dindir_drop): Ditto for DINLOCK field. - -Mon Jun 6 19:23:26 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * sizes.c (diskfs_grow): After realloccg, zero new data (which I'm - not sure is really necessary, but until I figure it out, this is - safest). Also poke old data (the latter only if the block has - moved)--otherwise the kernel won't know to page it out to the new - location. - (poke_pages): When poking, be careful not to actually change the data. - LEN should be end - start, not start - end. - -Fri Jun 3 12:37:27 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * inode.c (iget): When we find the node in the table, acquire the - mutex *after* incrementing NP->references and unlocking - diskfs_node_refcnt_lock; otherwise we can deadlock against - diskfs_nput. - -Thu Jun 2 12:16:09 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * ufs.h (sblock_dirty, csum_dirty, alloclock): New global variables. - * alloc.c (alloclock): Remove static keyword.. - * alloc.c (realloccg): Set sblock_dirty after changing sblock. - (blkpref): Likewise. - (fragextend): Likewise. - (alloccg): Likewise. - (alloccgblk): Likewise. - (ialloccg): Likewise. - (blkfree): Likewise. - (diskfs_free_node): Likewise. - * hyper.c (diskfs_set_hypermetadata): Likewise. - * alloc.c (fragextend): Set csum_dirty after changi csum. - (alloccg): Likewise. - (alloccgblk): Likewise. - (ialloccg): Likewise. - (blkfree): Likewise. - (diskfs_free_node): Likewise. - * hyper.c (diskfs_set_hypermetadata): Acquire alloclock while - writing hypermetadata. Only write csum and sblock if - csum_dirty or sblock_dirty, respectively, is set, and then - clear it after starting the write. - - * main.c (main): Likewise. - - * sizes.c (diskfs_truncate): Don't turn off caching; the new - light reference system takes care of this. - * pager.c (diskfs_get_filemap): No longer necessary to turn - on caching here, because truncate no longer turns it off. - - * inode.c (diskfs_lost_hardrefs, diskfs_new_hardrefs): New functions. - * pager.c (drop_pager_softrefs, allow_pager_softrefs): New functions. - (sin_map): Use diskfs_nref_light, not diskfs_nref. - (diskfs_get_filemap): Use diskfs_nref_light, not diskfs_nref. - (pager_clear_user_data): Use diskfs_nrele_light, not diskfs_nrele. - * ufs.h (drop_pager_softrefs, allow_pager_softrefs): New - declarations. - -Wed Jun 1 13:35:11 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * sizes.c (diskfs_truncate): After calling sin_unmap, turn - off caching on the sininfo pager so that it gets freed promptly - (there's generally no value in keeping it around because there - is no live fileinfo pager). - * pager.c (diskfs_get_filemap): Make sure we turn caching back on - here, however, if we start using the file pager. - - * pager.c (sin_map): When np->dn->sininfo is set, we have - to insert a valid send right after fetching the receive name. - - * pager.c (sin_unmap, din_unmap): New functions. - (pager_clear_user_data): Call sin_unmap and din_unmap - instead of doing it right here. - - * sizes.c (diskfs_truncate): Call sin_unmap instead of - doing it right here. - (sindir_drop): Call din_unmap instead of doing it right - here. Also, call it always, not just when wo do dindir_drop. - - * sizes.c (diskfs_grow): After alloc into sindir area, - unmap it if we don't have an active data pager. - * ufs.h (sin_unmap, din_unmap): New declarations. - - * sizes.c (diskfs_grow): In computing OSIZE in the realloc - case of lbn < NDADDR, deal correctly with the case where - np->allocsize is already an integral number of blocks. - - * sizes.c (diskfs_grow): Compute SIZE correctly. - - * alloc.c (alloc, realloccg, blkfree): When checking validity - of size arguments, also make sure the size isn't zero. - - * alloc.c (diskfs_alloc_node): Lock ALLOCLOCK before checking - sblock->fs_cstotal.cs_nifree. - -Tue May 31 18:47:42 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu) - - * ufs.h (DONT_CACHE_MEMORY_OBJECTS): Define it. - - * dir.c (diskfs_direnter: case TAKE): Assert that OLD->d_reclen >= - NEEDED, not that it is strictly >. - -Tue May 31 11:10:28 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * sizes.c (diskfs_grow): Call diskfs_node_update (but don't wait) - after successful completion to prevent old data from hanging around - too long and getting flushed all at once from the kernel. - - * sizes.c (diskfs_grow): Change SIZE to be the size of the last - block allocated. Delete variable NSIZE; use SIZE instead. - -Fri May 27 13:15:26 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) - - * sizes.c (diskfs_truncate): Set NP->dn_stat_dirty after each - modification of NP->dn_stat. - - * sizes.c (diskfs_truncate): Compute new value of NP->allocsize - correctly. - - * inode.c (iget): Set NP->allocsize to be the *actual* allocsize. - -Thu May 26 11:51:45 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * sizes.c (diskfs_truncate): In blkfree loop of blocks past - NDADDR, subtract NDADDR from idx to index correctly into - sinloc array. Start this loop with idx not less than NDADDR. - (diskfs_truncate): If olastblock == NDADDR, then we also - need to truncate blocks (one) mapped by single indirect blocks. - (diskfs_truncate): New variable `first2free'. Use in place - of older losing calculations involving lastblock. - (sindir_drop): Rename parameters to be FIRST and LAST. Change - interpretation of FIRST by one to correspond with changed call - in diskfs_truncate. - - * pager.c (sin_remap): When computing NEWSIZE, round up to - a page boundary, thus mimicing the SINDIR computation in - pager_report_extent properly. - - * pager.c (pager_unlock_page) [case SINDIR; vblkno == 0]: Read - from ....di_ib[INDIR_SINGLE] rather than invalid data before - NP->dn->dinloc. - - * alloc.c (alloc) [nospace]: Unlock alloclock. - (realloccg): Unlock alloclock before jumping to nospace. - (blkpref) [!(lbn < NDADDR)]: Unlock alloclock before returning - success. - - * sizes.c (diskfs_grow): When allocing a block past NDADDR, the - tbl arg to blkpref is the table of direct block pointers - NP->dn->sinloc, not the table of indirect block pointers - ...->di_ib. - - * sizes.c (diskfs_grow): When writing into the SINDIR area, call - sin_map instead of sin_remap if the sindir isn't already mapped. - Also set np->allocsize *before* calling sin_map, but *after* - calling sin_remap, to meet the requirements of those separate - routines. - - * sizes.c (diskfs_grow): If END isn't bigger than NP->allocsize, - then don't try and do anything. In computation of LBN and the - first use of NB, round up to block boundary correctly. Don't - attempt to realloc an old block if the size is 0 (in which case - NB is -1 and unsigned comparison rules might foul things up). - -Mon May 23 13:18:33 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * Makefile (ufs): Give -n in the proper order to rsh. - - * main.c: Include . - - * ufs.h (DONT_CACHE_MEMORY_OBJECTS): New compilation flag. - * pager.c (pager_report_attributes): Deleted function. - (MAY_CACHE): New macro; more useful form for using - DONT_CACHE_MEMORY_OBJECTS. - (sin_map, pager_init, diskfs_get_filemap): Provide new - args in calls to pager_create. - * sizes.c (MAY_CACHE): New macro; more useful form for - using DONT_CACHE_MEMORY_OBJECTS. - (diskfs_truncate): Use MAY_CACHE in calls to pager_change_attributes. - -Fri May 20 18:52:41 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) - - * sizes.c (diskfs_truncate): Force any delayed copies of the - vanishing region to be taken immediately before stopping, and - prevent any new delayed copies from being made until we are done - manipulating things. - (poke_pages): New function. - * pager.c (pager_report_attributes): New function. - -Wed May 18 15:51:40 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * alloc.c (alloc, realloccg, diskfs_alloc_node, alloccgblk, - blkfree, diskfs_free_node, mapsearch): Added helpful strings to - asserts. - (realloccg): Split up assert. - -Tue May 17 13:26:22 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * main.c (main): Delete unused variable PROC. - -Mon May 16 15:32:07 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * alloc.c (realloccg): When fragextend succeeds, bother to set - *PBN. - - * sizes.c (diskfs_grow): In fragment growth case, NSIZE should - not be the amount to hold SIZE (SIZE is the amount the file is - growing by), but rather the old size of the fragment plus the - SIZE. - - * dir.c (diskfs_direnter case COMPRESS): Rewrite loop to deal - properly with the case where from and to overlap. - -Mon May 9 16:51:44 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) - - * main.c (ufs_version): New variable. - (save_argv): New variable. - (main): Set save_argv. - (diskfs_init_completed): New function. - -Thu May 5 19:06:54 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) - - * Makefile (exec_server_image.o): Use -n when calling rsh. - -Thu May 5 07:39:38 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) - - * Makefile ($(OBJS)): Use $(includedir) instead of $(headers) in deps. -- cgit v1.2.3 From 2cddc873d21695166265d4c87c1939e5269a5108 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 23 Aug 2009 19:28:22 +0200 Subject: Fix assertion failure in pthread_mutex_trylock * sysdeps/generic/pt-mutex-trylock.c [!ALWAYS_TRACK_MUTEX_OWNER] (__pthread_mutex_trylock): Disable owner tracking. --- sysdeps/generic/pt-mutex-trylock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sysdeps/generic/pt-mutex-trylock.c b/sysdeps/generic/pt-mutex-trylock.c index 5264dc7b..3c8cd03c 100644 --- a/sysdeps/generic/pt-mutex-trylock.c +++ b/sysdeps/generic/pt-mutex-trylock.c @@ -34,6 +34,7 @@ __pthread_mutex_trylock (struct __pthread_mutex *mutex) if (__pthread_spin_trylock (&mutex->__held) == 0) /* Acquired the lock. */ { +#if defined(ALWAYS_TRACK_MUTEX_OWNER) #ifndef NDEBUG self = _pthread_self (); if (self) @@ -44,6 +45,7 @@ __pthread_mutex_trylock (struct __pthread_mutex *mutex) assert (! mutex->owner); mutex->owner = _pthread_self (); } +#endif #endif if (mutex->attr) -- cgit v1.2.3 From 9c989b58f694567e214deed700708f3ba9901270 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 23 Aug 2009 19:38:06 +0200 Subject: Fix pthread_mutex_t static initializers Fix pthread_mutex_t static initializers by not leaving references to __pthread_recursive_mutexattr. * include/pthread/pthread.h.orig (PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP): New macro. * sysdeps/generic/pt-mutex-destroy.c (_pthread_mutex_destroy): Compare mutex->attr with __PTHREAD_ERRORCHECK_MUTEXATTR and __PTHREAD_RECURSIVE_MUTEXATTR instead of __pthread_recursive_mutexattr. * sysdeps/generic/pt-mutex-init.c (_pthread_mutex_init): Likewise. * sysdeps/generic/pt-mutex-timedlock.c (__pthread_mutex_timedlock_internal): Likewise. * sysdeps/generic/pt-mutex-transfer-np.c (__pthread_mutex_transfer_np): Likewise. * sysdeps/generic/pt-mutex-trylock.c (__pthread_mutex_trylock): Likewise. * sysdeps/generic/pt-mutex-unlock.c (__pthread_mutex_unlock): Likewise. * sysdeps/generic/pt-mutexattr.c (__pthread_errorcheck_mutexattr): New const. * sysdeps/generic/bits/mutex-attr.h (__pthread_errorcheck_mutexattr): Declare const. * sysdeps/generic/bits/mutex.h (__PTHREAD_ERRORCHECK_MUTEXATTR, __PTHREAD_ERRORCHECK_MUTEX_INITIALIZER, __PTHREAD_RECURSIVE_MUTEXATTR): New macros. (__PTHREAD_RECURSIVE_MUTEX_INITIALIZER): Use __PTHREAD_RECURSIVE_MUTEXATTR macro instead of &__pthread_recursive_mutexattr. --- sysdeps/generic/bits/mutex-attr.h | 1 + sysdeps/generic/bits/mutex.h | 10 +++++++++- sysdeps/generic/pt-mutex-destroy.c | 3 ++- sysdeps/generic/pt-mutex-init.c | 13 +++++-------- sysdeps/generic/pt-mutex-timedlock.c | 22 ++++++++++++++-------- sysdeps/generic/pt-mutex-transfer-np.c | 11 +++++++++-- sysdeps/generic/pt-mutex-trylock.c | 14 ++++++++++---- sysdeps/generic/pt-mutex-unlock.c | 16 +++++++++++----- sysdeps/generic/pt-mutexattr.c | 8 ++++++++ 9 files changed, 69 insertions(+), 29 deletions(-) diff --git a/sysdeps/generic/bits/mutex-attr.h b/sysdeps/generic/bits/mutex-attr.h index 9161cdab..8514ebe8 100644 --- a/sysdeps/generic/bits/mutex-attr.h +++ b/sysdeps/generic/bits/mutex-attr.h @@ -35,6 +35,7 @@ struct __pthread_mutexattr }; /* Attributes for a recursive mutex. */ +extern const struct __pthread_mutexattr __pthread_errorcheck_mutexattr; extern const struct __pthread_mutexattr __pthread_recursive_mutexattr; #endif /* bits/mutex-attr.h */ diff --git a/sysdeps/generic/bits/mutex.h b/sysdeps/generic/bits/mutex.h index 86068cf5..c734c393 100644 --- a/sysdeps/generic/bits/mutex.h +++ b/sysdeps/generic/bits/mutex.h @@ -57,9 +57,17 @@ struct __pthread_mutex # define __PTHREAD_MUTEX_INITIALIZER \ { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0, 0 } +# define __PTHREAD_ERRORCHECK_MUTEXATTR ((struct __pthread_mutexattr *) ((unsigned long) __PTHREAD_MUTEX_ERRORCHECK + 1)) + +# define __PTHREAD_ERRORCHECK_MUTEX_INITIALIZER \ + { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, \ + __PTHREAD_ERRORCHECK_MUTEXATTR, 0, 0, 0 } + +# define __PTHREAD_RECURSIVE_MUTEXATTR ((struct __pthread_mutexattr *) ((unsigned long) __PTHREAD_MUTEX_RECURSIVE + 1)) + # define __PTHREAD_RECURSIVE_MUTEX_INITIALIZER \ { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, \ - (struct __pthread_mutexattr *) &__pthread_recursive_mutexattr, 0, 0, 0 } + __PTHREAD_RECURSIVE_MUTEXATTR, 0, 0, 0 } # endif #endif /* Not __pthread_mutex_defined. */ diff --git a/sysdeps/generic/pt-mutex-destroy.c b/sysdeps/generic/pt-mutex-destroy.c index b0ca00f7..3bbc73fe 100644 --- a/sysdeps/generic/pt-mutex-destroy.c +++ b/sysdeps/generic/pt-mutex-destroy.c @@ -26,7 +26,8 @@ int _pthread_mutex_destroy (pthread_mutex_t *mutex) { - if (mutex->attr == &__pthread_recursive_mutexattr) + if (mutex->attr == __PTHREAD_ERRORCHECK_MUTEXATTR + || mutex->attr == __PTHREAD_RECURSIVE_MUTEXATTR) /* Static attributes. */ ; else diff --git a/sysdeps/generic/pt-mutex-init.c b/sysdeps/generic/pt-mutex-init.c index a818fe3a..2f960286 100644 --- a/sysdeps/generic/pt-mutex-init.c +++ b/sysdeps/generic/pt-mutex-init.c @@ -35,14 +35,11 @@ _pthread_mutex_init (pthread_mutex_t *mutex, /* The default attributes. */ return 0; - if (attr == &__pthread_recursive_mutexattr) - /* Non-default but known attributes. */ - { - mutex->attr = attr; - return 0; - } - - mutex->attr = malloc (sizeof *attr); + if (! mutex->attr + || mutex->attr == __PTHREAD_ERRORCHECK_MUTEXATTR + || mutex->attr == __PTHREAD_RECURSIVE_MUTEXATTR) + mutex->attr = malloc (sizeof *attr); + if (! mutex->attr) return ENOMEM; diff --git a/sysdeps/generic/pt-mutex-timedlock.c b/sysdeps/generic/pt-mutex-timedlock.c index ee432192..883e50af 100644 --- a/sysdeps/generic/pt-mutex-timedlock.c +++ b/sysdeps/generic/pt-mutex-timedlock.c @@ -31,6 +31,12 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, const struct timespec *abstime) { struct __pthread *self; + const struct __pthread_mutexattr *attr = mutex->attr; + + if (attr == __PTHREAD_ERRORCHECK_MUTEXATTR) + attr = &__pthread_errorcheck_mutexattr; + if (attr == __PTHREAD_RECURSIVE_MUTEXATTR) + attr = &__pthread_recursive_mutexattr; __pthread_spin_lock (&mutex->__lock); if (__pthread_spin_trylock (&mutex->__held) == 0) @@ -50,8 +56,8 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, #endif #endif - if (mutex->attr) - switch (mutex->attr->mutex_type) + if (attr) + switch (attr->mutex_type) { case PTHREAD_MUTEX_NORMAL: break; @@ -75,7 +81,7 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, self = _pthread_self (); assert (self); - if (! mutex->attr || mutex->attr->mutex_type == PTHREAD_MUTEX_NORMAL) + if (! attr || attr->mutex_type == PTHREAD_MUTEX_NORMAL) { #if defined(ALWAYS_TRACK_MUTEX_OWNER) assert (mutex->owner != self); @@ -83,7 +89,7 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, } else { - switch (mutex->attr->mutex_type) + switch (attr->mutex_type) { case PTHREAD_MUTEX_ERRORCHECK: if (mutex->owner == self) @@ -108,7 +114,7 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, } #if !defined(ALWAYS_TRACK_MUTEX_OWNER) - if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) + if (attr && attr->mutex_type != PTHREAD_MUTEX_NORMAL) #endif assert (mutex->owner); @@ -147,14 +153,14 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, __pthread_block (self); #if !defined(ALWAYS_TRACK_MUTEX_OWNER) - if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) + if (attr && attr->mutex_type != PTHREAD_MUTEX_NORMAL) #endif { assert (mutex->owner == self); } - if (mutex->attr) - switch (mutex->attr->mutex_type) + if (attr) + switch (attr->mutex_type) { case PTHREAD_MUTEX_NORMAL: break; diff --git a/sysdeps/generic/pt-mutex-transfer-np.c b/sysdeps/generic/pt-mutex-transfer-np.c index 7796ac4f..967f1c7c 100644 --- a/sysdeps/generic/pt-mutex-transfer-np.c +++ b/sysdeps/generic/pt-mutex-transfer-np.c @@ -29,13 +29,20 @@ __pthread_mutex_transfer_np (struct __pthread_mutex *mutex, pthread_t tid) assert (mutex->owner == _pthread_self ()); struct __pthread *thread = __pthread_getid (tid); + const struct __pthread_mutexattr *attr = mutex->attr; + if (! thread) return ESRCH; if (thread == _pthread_self ()) return 0; - if (mutex->attr && mutex->attr->mutex_type == PTHREAD_MUTEX_ERRORCHECK) + if (attr == __PTHREAD_ERRORCHECK_MUTEXATTR) + attr = &__pthread_errorcheck_mutexattr; + if (attr == __PTHREAD_RECURSIVE_MUTEXATTR) + attr = &__pthread_recursive_mutexattr; + + if (attr && attr->mutex_type == PTHREAD_MUTEX_ERRORCHECK) { if (mutex->owner != _pthread_self ()) @@ -46,7 +53,7 @@ __pthread_mutex_transfer_np (struct __pthread_mutex *mutex, pthread_t tid) #ifndef NDEBUG # if !defined(ALWAYS_TRACK_MUTEX_OWNER) - if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) + if (attr && attr->mutex_type != PTHREAD_MUTEX_NORMAL) # endif { mutex->owner = thread; diff --git a/sysdeps/generic/pt-mutex-trylock.c b/sysdeps/generic/pt-mutex-trylock.c index 3c8cd03c..7a54cc9a 100644 --- a/sysdeps/generic/pt-mutex-trylock.c +++ b/sysdeps/generic/pt-mutex-trylock.c @@ -29,6 +29,12 @@ __pthread_mutex_trylock (struct __pthread_mutex *mutex) { int err; struct __pthread *self; + const struct __pthread_mutexattr *attr = mutex->attr; + + if (attr == __PTHREAD_ERRORCHECK_MUTEXATTR) + attr = &__pthread_errorcheck_mutexattr; + if (attr == __PTHREAD_RECURSIVE_MUTEXATTR) + attr = &__pthread_recursive_mutexattr; __pthread_spin_lock (&mutex->__lock); if (__pthread_spin_trylock (&mutex->__held) == 0) @@ -48,8 +54,8 @@ __pthread_mutex_trylock (struct __pthread_mutex *mutex) #endif #endif - if (mutex->attr) - switch (mutex->attr->mutex_type) + if (attr) + switch (attr->mutex_type) { case PTHREAD_MUTEX_NORMAL: break; @@ -70,10 +76,10 @@ __pthread_mutex_trylock (struct __pthread_mutex *mutex) err = EBUSY; - if (mutex->attr) + if (attr) { self = _pthread_self (); - switch (mutex->attr->mutex_type) + switch (attr->mutex_type) { case PTHREAD_MUTEX_NORMAL: break; diff --git a/sysdeps/generic/pt-mutex-unlock.c b/sysdeps/generic/pt-mutex-unlock.c index 7645fd4c..09d70f8f 100644 --- a/sysdeps/generic/pt-mutex-unlock.c +++ b/sysdeps/generic/pt-mutex-unlock.c @@ -28,10 +28,16 @@ int __pthread_mutex_unlock (pthread_mutex_t *mutex) { struct __pthread *wakeup; - + const struct __pthread_mutexattr *attr = mutex->attr; + + if (attr == __PTHREAD_ERRORCHECK_MUTEXATTR) + attr = &__pthread_errorcheck_mutexattr; + if (attr == __PTHREAD_RECURSIVE_MUTEXATTR) + attr = &__pthread_recursive_mutexattr; + __pthread_spin_lock (&mutex->__lock); - if (! mutex->attr || mutex->attr->mutex_type == PTHREAD_MUTEX_NORMAL) + if (! attr || attr->mutex_type == PTHREAD_MUTEX_NORMAL) { #if defined(ALWAYS_TRACK_MUTEX_OWNER) # ifndef NDEBUG @@ -45,7 +51,7 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) #endif } else - switch (mutex->attr->mutex_type) + switch (attr->mutex_type) { case PTHREAD_MUTEX_ERRORCHECK: case PTHREAD_MUTEX_RECURSIVE: @@ -55,7 +61,7 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) return EPERM; } - if (mutex->attr->mutex_type == PTHREAD_MUTEX_RECURSIVE) + if (attr->mutex_type == PTHREAD_MUTEX_RECURSIVE) if (--mutex->locks > 0) { __pthread_spin_unlock (&mutex->__lock); @@ -82,7 +88,7 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) #ifndef NDEBUG # if !defined (ALWAYS_TRACK_MUTEX_OWNER) - if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) + if (attr && attr->mutex_type != PTHREAD_MUTEX_NORMAL) # endif { mutex->owner = wakeup; diff --git a/sysdeps/generic/pt-mutexattr.c b/sysdeps/generic/pt-mutexattr.c index d80a7d74..5ebde6ea 100644 --- a/sysdeps/generic/pt-mutexattr.c +++ b/sysdeps/generic/pt-mutexattr.c @@ -28,6 +28,14 @@ const struct __pthread_mutexattr __pthread_default_mutexattr = mutex_type: PTHREAD_MUTEX_DEFAULT }; +const struct __pthread_mutexattr __pthread_errorcheck_mutexattr = +{ + prioceiling: 0, + protocol: PTHREAD_PRIO_NONE, + pshared: PTHREAD_PROCESS_PRIVATE, + mutex_type: PTHREAD_MUTEX_ERRORCHECK +}; + const struct __pthread_mutexattr __pthread_recursive_mutexattr = { prioceiling: 0, -- cgit v1.2.3 From 25cbe85eafc3d4155a59f4690a3b581ead14d938 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 23 Aug 2009 19:47:05 +0200 Subject: Fix pthread_setcancelstate/type crash * pthread/pt-setcancelstate.c (pthread_setcancelstate): Check whether OLDSTATE is NULL before filling it. * pthread/pt-setcanceltype.c (pthread_setcanceltype): Likewise. --- pthread/pt-setcancelstate.c | 3 ++- pthread/pt-setcanceltype.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pthread/pt-setcancelstate.c b/pthread/pt-setcancelstate.c index ded58922..e2d81833 100644 --- a/pthread/pt-setcancelstate.c +++ b/pthread/pt-setcancelstate.c @@ -35,7 +35,8 @@ pthread_setcancelstate (int state, int *oldstate) break; } - *oldstate = p->cancel_state; + if (oldstate) + *oldstate = p->cancel_state; p->cancel_state = state; return 0; diff --git a/pthread/pt-setcanceltype.c b/pthread/pt-setcanceltype.c index 9511c991..3ce4259c 100644 --- a/pthread/pt-setcanceltype.c +++ b/pthread/pt-setcanceltype.c @@ -35,7 +35,8 @@ pthread_setcanceltype (int type, int *oldtype) break; } - *oldtype = p->cancel_type; + if (oldtype) + *oldtype = p->cancel_type; p->cancel_type = type; return 0; -- cgit v1.2.3 From 97998cd4d4a3be935bfa373c50c2624bbabd7d02 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 13 Oct 2009 20:15:08 +0200 Subject: Fix pthread_cleanup_push old-gcc-style initializer sysdeps/generic/bits/cancelation.h (__pthread_cleanup_push): For better portability to various compilation flags, use standard initializer for struct __pthread_cancelation_handler __handler instead of old-gcc-style. --- sysdeps/generic/bits/cancelation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sysdeps/generic/bits/cancelation.h b/sysdeps/generic/bits/cancelation.h index f446d595..db9169a9 100644 --- a/sysdeps/generic/bits/cancelation.h +++ b/sysdeps/generic/bits/cancelation.h @@ -38,9 +38,9 @@ struct __pthread_cancelation_handler **__pthread_get_cleanup_stack (void); = __pthread_get_cleanup_stack (); \ struct __pthread_cancelation_handler __handler = \ { \ - handler: (rt), \ - arg: (rtarg), \ - next: *__handlers \ + (rt), \ + (rtarg), \ + *__handlers \ }; \ *__handlers = &__handler; -- cgit v1.2.3 From 75380300dc22bf3a8fbd89cf5a2358a9c29deaeb Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 18 Oct 2009 00:24:19 +0200 Subject: Fix pthread_kill(thread, 0) * sysdeps/hurd/pt-kill.c (pthread_kill): Return immediately after checks without calling _hurd_raise_signal if sig is 0. --- sysdeps/hurd/pt-kill.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sysdeps/hurd/pt-kill.c b/sysdeps/hurd/pt-kill.c index f970e065..d204e3f6 100644 --- a/sysdeps/hurd/pt-kill.c +++ b/sysdeps/hurd/pt-kill.c @@ -39,6 +39,9 @@ pthread_kill (pthread_t thread, int sig) ss = _hurd_thread_sigstate (pthread->kernel_thread); assert (ss); + if (!sig) + return 0; + detail.exc = 0; detail.code = sig; detail.error = 0; -- cgit v1.2.3 From 90dd2d73435a8e1bbcccf5ed99a91b2c438557f4 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Wed, 19 May 2010 08:32:16 +0200 Subject: Add pthread_yield function * pthread/pt-yield.c: New file. * Makefile (SRCS): Add pt-yield.c * Makefile.am (libpthread_a_SOURCES): Add pt-yield.c --- Makefile.am | 1 + pthread/pt-yield.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 pthread/pt-yield.c diff --git a/Makefile.am b/Makefile.am index e59c9460..e1c062c1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -133,6 +133,7 @@ libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ pt-kill.c \ pt-getcpuclockid.c \ pt-getschedparam.c pt-setschedparam.c pt-setschedprio.c \ + pt-yield.c \ sem-close.c sem-init.c sem-timedwait.c sem-wait.c \ sem-destroy.c sem-open.c sem-trywait.c sem-getvalue.c \ sem-post.c sem-unlink.c \ diff --git a/pthread/pt-yield.c b/pthread/pt-yield.c new file mode 100644 index 00000000..27848bb7 --- /dev/null +++ b/pthread/pt-yield.c @@ -0,0 +1,26 @@ +/* Yield the processor to another thread or process. + Copyright (C) 2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int pthread_yield(void) +{ + return sched_yield (); +} -- cgit v1.2.3 From ae5f861010e23248573efa3addbcd3f115c7d9d4 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 1 Aug 2010 01:06:33 +0200 Subject: move file to libpthread/ --- libpthread/pt-yield.c | 26 ++++++++++++++++++++++++++ pthread/pt-yield.c | 26 -------------------------- 2 files changed, 26 insertions(+), 26 deletions(-) create mode 100644 libpthread/pt-yield.c delete mode 100644 pthread/pt-yield.c diff --git a/libpthread/pt-yield.c b/libpthread/pt-yield.c new file mode 100644 index 00000000..27848bb7 --- /dev/null +++ b/libpthread/pt-yield.c @@ -0,0 +1,26 @@ +/* Yield the processor to another thread or process. + Copyright (C) 2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int pthread_yield(void) +{ + return sched_yield (); +} diff --git a/pthread/pt-yield.c b/pthread/pt-yield.c deleted file mode 100644 index 27848bb7..00000000 --- a/pthread/pt-yield.c +++ /dev/null @@ -1,26 +0,0 @@ -/* Yield the processor to another thread or process. - Copyright (C) 2010 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int pthread_yield(void) -{ - return sched_yield (); -} -- cgit v1.2.3 From 41ad1a2b52b6479c778a908c3dacee29c47619db Mon Sep 17 00:00:00 2001 From: "Madhusudan.C.S" Date: Thu, 14 Aug 2008 15:24:00 +0200 Subject: 2008-08-14 Madhusudan.C.S * ChangeLog: New file added to procfs * AUTHORS: New file added to procfs * COPYING: New file added to procfs * README: New file added to procfs * Makefile: New file added to procfs * bootstrap.c: New file added to procfs * netfs.c: New file added to procfs * node.c: New file added to procfs * procfs.c: New file added to procfs * procfs.h: New file added to procfs * procfs_dir.c: New file added to procfs * procfs_nonpid_files.c: New file added to procfs * procfs_pid.h: New file added to procfs * procfs_pid_files.c: New file added to procfs --- AUTHORS | 10 + bootstrap.c | 95 +++++++++ netfs.c | 466 ++++++++++++++++++++++++++++++++++++++++ node.c | 195 +++++++++++++++++ procfs.c | 149 +++++++++++++ procfs.h | 218 +++++++++++++++++++ procfs_dir.c | 575 ++++++++++++++++++++++++++++++++++++++++++++++++++ procfs_nonpid_files.c | 462 ++++++++++++++++++++++++++++++++++++++++ procfs_pid.h | 86 ++++++++ procfs_pid_files.c | 570 +++++++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 2826 insertions(+) create mode 100644 AUTHORS create mode 100644 bootstrap.c create mode 100644 netfs.c create mode 100644 node.c create mode 100644 procfs.c create mode 100644 procfs.h create mode 100644 procfs_dir.c create mode 100644 procfs_nonpid_files.c create mode 100644 procfs_pid.h create mode 100644 procfs_pid_files.c diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..622b6488 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,10 @@ +Written By +~~~~~~~~~~ + +Madhusudan.C.S + + +Mentored By +~~~~~~~~~~~ + +Olaf Buddenhagen diff --git a/bootstrap.c b/bootstrap.c new file mode 100644 index 00000000..73d31f00 --- /dev/null +++ b/bootstrap.c @@ -0,0 +1,95 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + bootstrap.c -- This file is functions for starting up + and initializers for the procfs translator + defined in procfs.h + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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 +#include +#include + +#include "procfs.h" + +struct ps_context *ps_context; + +/* This function is used to initialize the whole translator, can be + effect called as bootstrapping the translator. */ +error_t procfs_init () +{ + error_t err; + + err = ps_context_create (getproc (), &ps_context); + + return err; +} + +/* Create a new procfs filesystem. */ +error_t procfs_create (char *procfs_root, int fsid, + struct procfs **fs) +{ + error_t err; + /* This is the enclosing directory for this filesystem's + root node */ + struct procfs_dir *topmost_root_dir; + + /* And also a topmost-root node, just used for locking + TOPMOST_ROOT_DIR. */ + struct node *topmost_root; + + /* The new node for the filesystem's root. */ + struct procfs *new = malloc (sizeof (struct procfs)); + + if (! new) + return ENOMEM; + + new->fsid = fsid; + new->next_inode = 2; + + hurd_ihash_init (&new->inode_mappings, + offsetof (struct procfs_dir_entry, inode_locp)); + spin_lock_init (&new->inode_mappings_lock); + + topmost_root = netfs_make_node (0); + if (! topmost_root) + err = ENOMEM; + else + { + err = procfs_dir_create (new, topmost_root, procfs_root, + &topmost_root_dir); + if (! err) + { + /* ADDITIONAL BOOTSTRAPPING OF THE ROOT NODE */ + err = procfs_dir_null_lookup (topmost_root_dir, &new->root); + } + } + + if (err) + { + hurd_ihash_destroy (&new->inode_mappings); + free (new); + } + else + *fs = new; + + return err; +} + diff --git a/netfs.c b/netfs.c new file mode 100644 index 00000000..31ffe1b5 --- /dev/null +++ b/netfs.c @@ -0,0 +1,466 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "procfs.h" + +/* Trivial definitions. */ + +/* 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) +{ + return procfs_refresh_node (node); +} + +/* 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) +{ + return 0; +} + +/* 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) +{ + return EROFS; +} + +/* Attempt to remove directory named NAME in DIR for USER. */ +error_t netfs_attempt_rmdir (struct iouser *user, + struct node *dir, char *name) +{ + return EROFS; +} + +/* 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) +{ + return EROFS; +} + +/* 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) +{ + *node = NULL; + mutex_unlock (&dir->lock); + return EROFS; +} + +/* 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 = procfs_refresh_node (node); + if (!err && (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); + 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) +{ + error_t err = procfs_refresh_node (node); + int flags = TOUCH_CTIME; + + if (! err) + err = fshelp_isowner (&node->nn_stat, cred); + + if (! err) + { + if (atime) + node->nn_stat.st_atim = *atime; + else + flags |= TOUCH_ATIME; + + if (mtime) + node->nn_stat.st_mtim = *mtime; + else + flags |= TOUCH_MTIME; + + fshelp_touch (&node->nn_stat, flags, procfs_maptime); + } + + return err; +} + +/* 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) +{ + error_t err = procfs_refresh_node (node); + + if (! err) + { + *types = 0; + if (fshelp_access (&node->nn_stat, S_IREAD, cred) == 0) + *types |= O_READ; + if (fshelp_access (&node->nn_stat, S_IWRITE, cred) == 0) + *types |= O_WRITE; + if (fshelp_access (&node->nn_stat, S_IEXEC, cred) == 0) + *types |= O_EXEC; + } + + return err; +} + +/* The granularity with which we allocate space to return our result. */ +#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)) + + + +/* Fetch a directory */ +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 = procfs_refresh_node (dir); + struct procfs_dir_entry *dir_entry; + + if (! err) + { + if (dir->nn->dir) + { + if (! procfs_dir_refresh (dir->nn->dir, dir == dir->nn->fs->root)) + { + for (dir_entry = dir->nn->dir->ordered; first_entry > 0 && + dir_entry; first_entry--, + dir_entry = dir_entry->ordered_next); + if (! dir_entry ) + max_entries = 0; + + if (max_entries != 0) + { + size_t size = 0; + char *p; + int count = 0; + + + if (max_data_len == 0) + size = DIRENTS_CHUNK_SIZE; + else if (max_data_len > DIRENTS_CHUNK_SIZE) + size = DIRENTS_CHUNK_SIZE; + else + size = max_data_len; + + *data = mmap (0, size, PROT_READ|PROT_WRITE, + MAP_ANON, 0, 0); + + err = ((void *) *data == (void *) -1) ? errno : 0; + + if (! err) + { + p = *data; + + /* This gets all the actual entries present. */ + + while ((max_entries == -1 || count < max_entries) && dir_entry) + { + struct dirent hdr; + size_t name_len = strlen (dir_entry->name); + size_t sz = DIRENT_LEN (name_len); + int entry_type = IFTODT (dir_entry->stat.st_mode); + + if ((p - *data) + sz > size) + { + if (max_data_len > 0) + break; + else /* The Buffer Size must be increased. */ + { + vm_address_t extension = (vm_address_t)(*data + size); + err = vm_allocate (mach_task_self (), &extension, + DIRENTS_CHUNK_SIZE, 0); + + if (err) + break; + + size += DIRENTS_CHUNK_SIZE; + } + } + + hdr.d_namlen = name_len; + hdr.d_fileno = dir_entry->stat.st_ino; + hdr.d_reclen = sz; + hdr.d_type = entry_type; + + memcpy (p, &hdr, DIRENT_NAME_OFFS); + strcpy (p + DIRENT_NAME_OFFS, dir_entry->name); + + p += sz; + + count++; + dir_entry = dir_entry->ordered_next; + } + + if (err) + munmap (*data, size); + else + { + vm_address_t alloc_end = (vm_address_t)(*data + size); + vm_address_t real_end = round_page (p); + if (alloc_end > real_end) + munmap ((caddr_t) real_end, alloc_end - real_end); + *data_len = p - *data; + *data_entries = count; + } + } + } + else + { + *data_len = 0; + *data_entries = 0; + } + } + } + else + return ENOTDIR; + } + + 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 = procfs_refresh_node (dir); + + if (! err) + err = procfs_dir_lookup (dir->nn->dir, name, node); + + return err; +} + +/* Delete NAME in DIR for USER. */ +error_t netfs_attempt_unlink (struct iouser *user, struct node *dir, + char *name) +{ + return EROFS; +} + +/* 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) +{ + return EROFS; +} + +/* 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) +{ + return EROFS; +} + +/* 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) +{ + return EROFS; +} + +/* 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) +{ + return EROFS; +} + +/* 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) +{ + return EROFS; +} + +/* 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) +{ + return EROFS; +} + + +/* 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) +{ + return EROFS; +} + +/* 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) +{ + return EROFS; +} + +/* This should attempt to fetch filesystem status information for the remote + filesystem, for the user CRED. */ +error_t +netfs_attempt_statfs (struct iouser *cred, struct node *node, + struct statfs *st) +{ + bzero (st, sizeof *st); + st->f_type = PROCFILESYSTEM; + st->f_fsid = getpid (); + return 0; +} + +/* 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) +{ + 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) +{ + return EROFS; +} + +/* 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) +{ + *node = NULL; + mutex_unlock (&dir->lock); + return EROFS; +} + +/* Read the contents of NODE (a symlink), for USER, into BUF. */ +error_t netfs_attempt_readlink (struct iouser *user, struct node *node, char *buf) +{ + error_t err = procfs_refresh_node (node); + if (! err) + { + struct procfs_dir_entry *dir_entry = node->nn->dir_entry; + if (dir_entry) + bcopy (dir_entry->symlink_target, buf, node->nn_stat.st_size); + else + err = EINVAL; + } + return err; +} + +/* 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) +{ + error_t err; + err = procfs_refresh_node (node); + + if (! err) + { + if (*len > 0) + procfs_write_files_contents (node, offset, + len, data); + if (*len > 0) + if (offset >= *len) + *len = 0; + } + + return err; +} + +/* Write to the file NODE for user CRED starting at OFFSET 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) +{ + return EROFS; +} + +/* The user must define this function. Node NP is all done; free + all its associated storage. */ +void netfs_node_norefs (struct node *np) +{ + mutex_lock (&np->lock); + *np->prevp = np->next; + np->next->prevp = np->prevp; + procfs_remove_node (np); +} + diff --git a/node.c b/node.c new file mode 100644 index 00000000..f11fa7b0 --- /dev/null +++ b/node.c @@ -0,0 +1,195 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + node.c -- This file contains function defintions to handle + node creation and destruction. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "procfs.h" + +/* Return a new node in NODE, with a name NAME, and return the + new node with a single reference in NODE. */ +error_t procfs_create_node (struct procfs_dir_entry *dir_entry, + const char *fs_path, struct node **node) +{ + struct node *new; + struct netnode *nn = malloc (sizeof (struct netnode)); + error_t err; + + if (! nn) + return ENOMEM; + if (! fs_path) + fs_path = strdup (""); + nn->fs = dir_entry->dir->fs; + nn->dir_entry = dir_entry; + nn->dir = NULL; + nn->fs_path = strdup (fs_path); + + new = netfs_make_node (nn); + if (! new) + { + free (nn); + return ENOMEM; + } + + fshelp_touch (&new->nn_stat, TOUCH_ATIME|TOUCH_MTIME|TOUCH_CTIME, + procfs_maptime); + + spin_lock (&nn->fs->inode_mappings_lock); + err = hurd_ihash_add (&nn->fs->inode_mappings, dir_entry->stat.st_ino, dir_entry); + spin_unlock (&nn->fs->inode_mappings_lock); + + if (err) + { + free (nn); + free (new); + return err; + } + + dir_entry->node = new; + *node = new; + + return 0; +} + +/* Update the directory entry for NAME to reflect ST and SYMLINK_TARGET. + True is returned if successful, or false if there was a memory allocation + error. TIMESTAMP is used to record the time of this update. */ +static void +update_entry (struct procfs_dir_entry *dir_entry, const struct stat *st, + const char *symlink_target, time_t timestamp) +{ + ino_t ino; + struct procfs *fs = dir_entry->dir->fs; + + if (dir_entry->stat.st_ino) + ino = dir_entry->stat.st_ino; + else + ino = fs->next_inode++; + + dir_entry->name_timestamp = timestamp; + + if (st) + /* The ST and SYMLINK_TARGET parameters are only valid if ST isn't 0. */ + { + dir_entry->stat = *st; + dir_entry->stat_timestamp = timestamp; + + if (!dir_entry->symlink_target || !symlink_target + || strcmp (dir_entry->symlink_target, symlink_target) != 0) + { + if (dir_entry->symlink_target) + free (dir_entry->symlink_target); + dir_entry->symlink_target = symlink_target ? strdup (symlink_target) : 0; + } + } + + /* The st_ino field is always valid. */ + dir_entry->stat.st_ino = ino; + dir_entry->stat.st_fsid = fs->fsid; + dir_entry->stat.st_fstype = PROCFILESYSTEM; +} + +/* Refresh stat information for NODE */ +error_t procfs_refresh_node (struct node *node) +{ + struct netnode *nn = node->nn; + struct procfs_dir_entry *dir_entry = nn->dir_entry; + + if (! dir_entry) + /* This is a deleted node, don't attempt to do anything. */ + return 0; + else + { + error_t err = 0; + + struct timeval tv; + maptime_read (procfs_maptime, &tv); + + time_t timestamp = tv.tv_sec; + + struct procfs_dir *dir = dir_entry->dir; + + mutex_lock (&dir->node->lock); + + if (! dir_entry->self_p) + /* This is a deleted entry, just awaiting disposal; do so. */ + { +#if 0 + nn->dir_entry = 0; + free_entry (dir_entry); + return 0; +#endif + } + + else if (dir_entry->noent) + err = ENOENT; + else + { + if (*(dir_entry->name)) + { + err = procfs_dir_refresh (dir_entry->dir, + dir_entry->dir->node == dir_entry->dir->fs->root); + if (!err && dir_entry->noent) + err = ENOENT; + + if (err == ENOENT) + { + dir_entry->noent = 1; /* A negative entry. */ + dir_entry->name_timestamp = timestamp; + } + } + else + { + /* Refresh the root node with the old stat + information. */ + update_entry (dir_entry, &netfs_root_node->nn_stat, NULL, timestamp); + } + } + + node->nn_stat = dir_entry->stat; + node->nn_translated = S_ISLNK (dir_entry->stat.st_mode) ? S_IFLNK : 0; + if (!nn->dir && S_ISDIR (dir_entry->stat.st_mode)) + procfs_dir_create (nn->fs, node, nn->fs_path, &nn->dir); + + mutex_unlock (&dir->node->lock); + + return err; + } +} + +/* Remove NODE from its entry */ +error_t procfs_remove_node (struct node *node) +{ + + /* STUB */ + + return 0; +} diff --git a/procfs.c b/procfs.c new file mode 100644 index 00000000..1fd0d619 --- /dev/null +++ b/procfs.c @@ -0,0 +1,149 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs.c -- This file is the main file of the translator. + This has important definitions and initializes + the translator + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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 +#include +#include +#include + +#include +#include +#include +#include + +#include "procfs.h" + +/* Defines this Tanslator Name */ +char *netfs_server_name = PROCFS_SERVER_NAME; +char *netfs_server_version = PROCFS_SERVER_VERSION; +int netfs_maxsymlinks = 12; + +static const struct argp_child argp_children[] = + { + {&netfs_std_startup_argp, 0, NULL, 0}, + {0} + }; + + +const char *argp_program_version = "/proc pseudo-filesystem (" PROCFS_SERVER_NAME + ") " PROCFS_SERVER_VERSION "\n" +"Copyright (C) 2008 Free Software Foundation\n" +"This is free software; see the source for copying conditions. There is NO\n" +"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." +"\n"; + +static char *args_doc = "PROCFSROOT"; +static char *doc = "proc pseudo-filesystem for Hurd implemented as a translator. " +"This is still under very humble and initial stages of development.\n" +"Any Contribution or help is welcome. The code may not even compile"; + + +/* The Filesystem */ +struct procfs *procfs; + +/* The FILESYSTEM component of PROCFS_FS. */ +char *procfs_root = ""; + +volatile struct mapped_time_value *procfs_maptime; + +/* Startup options. */ +static const struct argp_option procfs_options[] = + { + { 0 } + }; + + +/* argp parser function for parsing single procfs command line options */ +static error_t +parse_procfs_opt (int key, char *arg, struct argp_state *state) +{ + switch (key) + { + case ARGP_KEY_ARG: + if (state->arg_num > 1) + argp_usage (state); + break; + + case ARGP_KEY_NO_ARGS: + argp_usage(state); + break; + + default: + return ARGP_ERR_UNKNOWN; + } +} + +/* Program entry point. */ +int +main (int argc, char **argv) +{ + error_t err; + mach_port_t bootstrap, underlying_node; + struct stat underlying_stat; + + struct argp argp = + { + procfs_options, parse_procfs_opt, + args_doc, doc, argp_children, + NULL, NULL + }; + + + /* Parse the command line arguments */ +// argp_parse (&argp, argc, argv, 0, 0, 0); + + task_get_bootstrap_port (mach_task_self (), &bootstrap); + + netfs_init (); + + if (maptime_map (0, 0, &procfs_maptime)) + { + perror (PROCFS_SERVER_NAME ": Cannot map time"); + return 1; + } + + procfs_init (); + + err = procfs_create (procfs_root, getpid (), &procfs); + if (err) + error (4, err, "%s", procfs_root); + + /* Create our root node */ + netfs_root_node = procfs->root; + + /* Start netfs activities */ + underlying_node = netfs_startup (bootstrap, 0); + if (io_stat (underlying_node, &underlying_stat)) + error (1, err, "cannot stat underling node"); + + /* Initialize stat information of the root node. */ + netfs_root_node->nn_stat = underlying_stat; + netfs_root_node->nn_stat.st_mode = + S_IFDIR | (underlying_stat.st_mode & ~S_IFMT & ~S_ITRANS); + + for (;;) + netfs_server_loop (); + return 1; +} diff --git a/procfs.h b/procfs.h new file mode 100644 index 00000000..95d4ee35 --- /dev/null +++ b/procfs.h @@ -0,0 +1,218 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs.h -- This file is the main header file of this + translator. This has important header + definitions for constants and functions + used in the translator. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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. + + A portion of the code in this file is based on ftpfs code + present in the hurd repositories copyrighted to FSF. The + Copyright notice from that file is given below. + + Copyright (C) 1997,98,2002 Free Software Foundation, Inc. + Written by Miles Bader + This file is part of the GNU Hurd. +*/ + +#ifndef __PROCFS_H__ +#define __PROCFS_H__ + +#define PROCFS_SERVER_NAME "procfs" +#define PROCFS_SERVER_VERSION "0.0.1" + +/* /proc Filesystem type. */ +#define PROCFILESYSTEM "procfs" + +#define NUMBER_OF_FILES_PER_PID 1 +#define JIFFY_ADJUST 100 +#define PAGES_TO_BYTES(pages) ((pages) * sysconf(_SC_PAGESIZE)) +#define BYTES_TO_PAGES(bytes) ((bytes) / sysconf(_SC_PAGESIZE)) + +#include +#include +#include +#include +#include +#include + +/* A single entry in a directory. */ +struct procfs_dir_entry +{ + char *name; /* Name of this entry */ + size_t hv; /* Hash value of NAME */ + + /* The active node referred to by this name (may be 0). + NETFS_NODE_REFCNT_LOCK should be held while frobbing this. */ + struct node *node; + + struct stat stat; + char *symlink_target; + time_t stat_timestamp; + + /* The directory to which this entry belongs. */ + struct procfs_dir *dir; + + /* Link to next entry in hash bucket, and address of previous entry's (or + hash table's) pointer to this entry. If the SELF_P field is 0, then + this is a deleted entry, awaiting final disposal. */ + struct procfs_dir_entry *next, **self_p; + + /* Next entry in 'directory order', or 0 if none known. */ + struct procfs_dir_entry *ordered_next, **ordered_self_p; + + /* When the presence/absence of this file was last checked. */ + time_t name_timestamp; + + hurd_ihash_locp_t inode_locp; /* Used for removing this entry */ + + int noent : 1; /* A negative lookup result. */ + int valid : 1; /* Marker for GC'ing. */ +}; + +/* A directory. */ +struct procfs_dir +{ + /* Number of entries in HTABLE. */ + size_t num_entries; + + /* The number of entries that have nodes attached. We keep an additional + reference to our node if there are any, to prevent it from going away. */ + size_t num_live_entries; + + /* Hash table of entries. */ + struct procfs_dir_entry **htable; + size_t htable_len; /* # of elements in HTABLE (not bytes). */ + + /* List of dir entries in 'directory order', in a linked list using the + ORDERED_NEXT and ORDERED_SELF_P fields in each entry. Not all entries + in HTABLE need be in this list. */ + struct procfs_dir_entry *ordered; + + /* The filesystem node that this is the directory for. */ + struct node *node; + + /* The filesystem this directory is in. */ + struct procfs *fs; + + /* The path to this directory in the filesystem. */ + const char *fs_path; + + time_t stat_timestamp; + time_t name_timestamp; + +}; + + +/* libnetfs node structure */ +struct netnode +{ + /* Name of this node */ + char *name; + + /* The path in the filesystem that corresponds + this node. */ + char *fs_path; + + /* The directory entry for this node. */ + struct procfs_dir_entry *dir_entry; + + /* The proc filesystem */ + struct procfs *fs; + + /* inode number, assigned to this netnode structure. */ + unsigned int inode_num; + + /* If this is a directory, the contents, or 0 if not fetched. */ + struct procfs_dir *dir; + + /* pointer to node structure, assigned to this node. */ + struct node *node; + + /* links to the previous and next nodes in the list */ + struct netnode *nextnode, *prevnode; + + /* link to parent netnode of this file or directory */ + struct netnode *parent; + + /* link to the first child netnode of this directory */ + struct netnode *child_first; +}; + +/* The actual procfs filesystem structure */ +struct procfs +{ + /* Root of the filesystem. */ + struct node *root; + + /* Inode numbers are assigned sequentially in order of creation. */ + ino_t next_inode; + int fsid; + + /* A hash table mapping inode numbers to directory entries. */ + struct hurd_ihash inode_mappings; + spin_lock_t inode_mappings_lock; +}; + +extern struct procfs *procfs; + +extern volatile struct mapped_time_value *procfs_maptime; + +extern struct ps_context *ps_context; + +/* Create a new procfs filesystem. */ +error_t procfs_create (char *procfs_root, int fsid, + struct procfs **fs); + +/* Initialize the procfs filesystem for use. */ +error_t procfs_init (); + +/* Refresh stat information for NODE */ +error_t procfs_refresh_node (struct node *node); + +/* Return a new node in NODE, with a name NAME, + and return the new node with a single + reference in NODE. */ +error_t procfs_create_node (struct procfs_dir_entry *dir_entry, + const char *fs_path, + struct node **node); + +/* Remove NODE from its entry */ +error_t procfs_remove_node (struct node *node); + +/* Return in DIR a new procfs directory, in the filesystem FS, + with node NODE and path PATH. */ +error_t procfs_dir_create (struct procfs *fs, struct node *node, + const char *path, struct procfs_dir **dir); + +/* Remove the specified DIR and free all its allocated + storage. */ +void procfs_dir_remove (struct procfs_dir *dir); + +/* Refresh DIR. */ +error_t procfs_dir_refresh (struct procfs_dir *dir, int isroot); + +/* Lookup NAME in DIR, returning its entry, or an error. + *NODE will contain the result node, locked, and with + an additional reference, or 0 if an error occurs. */ +error_t procfs_dir_lookup (struct procfs_dir *dir, const char *name, + struct node **node); + +#endif /* __PROCFS_H__ */ diff --git a/procfs_dir.c b/procfs_dir.c new file mode 100644 index 00000000..b9b0410e --- /dev/null +++ b/procfs_dir.c @@ -0,0 +1,575 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs_dir.c -- This file contains definitions to perform + directory operations such as creating, + removing and refreshing directories. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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. + + A portion of the code in this file is based on ftpfs code + present in the hurd repositories copyrighted to FSF. The + Copyright notice from that file is given below. + + Copyright (C) 1997,98,2002 Free Software Foundation, Inc. + Written by Miles Bader + This file is part of the GNU Hurd. +*/ + + +#include +#include +#include +#include +#include + +#include "procfs.h" + +/* Initial HASHTABLE length for the new directories to be created. */ +#define INIT_HTABLE_LEN 5 + +struct procfs_dir_entry **cur_entry; + +/* Return in DIR a new procfs directory, in the filesystem FS, + with node NODE and path PATH. */ +error_t procfs_dir_create (struct procfs *fs, struct node *node, + const char *path, struct procfs_dir **dir) +{ + struct procfs_dir *new = malloc (sizeof (struct procfs_dir)); + if (!new) + return ENOMEM; + struct procfs_dir_entry **htable = calloc (INIT_HTABLE_LEN, + sizeof (struct procfs_dir_entry *)); + if (!htable) + return ENOMEM; + + /* Hold a reference to the new dir's node. */ + spin_lock (&netfs_node_refcnt_lock); + node->references++; + spin_unlock (&netfs_node_refcnt_lock); + + new->num_entries = 0; + new->num_live_entries = 0; + new->htable_len = INIT_HTABLE_LEN; + new->htable = htable; + new->ordered = NULL; + new->fs_path = path; + new->fs = fs; + new->node = node; + new->stat_timestamp = 0; + new->name_timestamp = 0; + + *dir = new; + + return 0; +} + +/* Put the directory entry DIR_ENTRY into the hash table HTABLE. */ +static void +insert (struct procfs_dir_entry *dir_entry, + struct procfs_dir_entry **htable, size_t htable_len) +{ + struct procfs_dir_entry **new_htable = &htable[dir_entry->hv % htable_len]; + if (*new_htable) + (*new_htable)->self_p = &dir_entry->next; + dir_entry->next = *new_htable; + dir_entry->self_p = new_htable; + *new_htable = dir_entry; +} + +/* Calculate NAME's hash value. */ +static size_t +hash (const char *name) +{ + size_t hash_value = 0; + while (*name) + hash_value = ((hash_value << 5) + *name++) & 0xFFFFFF; + return hash_value; +} + +/* Extend the existing hashtable for DIR to accomodate values for new length + NEW_LEN. We retain all the previous entries. */ +static error_t +rehash (struct procfs_dir *dir, size_t new_len) +{ + int count; + size_t old_len = dir->htable_len; + struct procfs_dir_entry **old_htable = dir->htable; + struct procfs_dir_entry **new_htable = (struct procfs_dir_entry **) + malloc (new_len * sizeof (struct procfs_dir_entry *)); + + if (! new_htable) + return ENOMEM; + + bzero (new_htable, new_len * sizeof (struct procfs_dir_entry *)); + + for (count = 0; count < old_len; count++) + while (old_htable[count]) + { + struct procfs_dir_entry *dir_entry = old_htable[count]; + + /* Remove DIR_ENTRY from the old table */ + old_htable[count] = dir_entry->next; + + insert (dir_entry, new_htable, new_len); + } + + free (old_htable); + + dir->htable = new_htable; + dir->htable_len = new_len; + + return 0; +} + +/* Lookup NAME in DIR and return its entry. If there is no such entry, and + DNEW, the decision variable, is true, then a new entry is allocated and + returned, otherwise 0 is returned (if DNEW is true then 0 can be returned + if a memory allocation error occurs). */ +struct procfs_dir_entry * +lookup_entry (struct procfs_dir *dir, const char *name, int dnew) +{ + size_t hv = hash (name); + struct procfs_dir_entry *dir_entry = dir->htable[hv % dir->htable_len]; + + while (dir_entry && strcmp (name, dir_entry->name) != 0) + dir_entry = dir_entry->next; + + if (!dir_entry && dnew) + { + if (dir->num_entries > dir->htable_len) + /* Grow the hash table. */ + if (rehash (dir, (dir->htable_len + 1) * 2 - 1) != 0) + return 0; + + dir_entry = + (struct procfs_dir_entry *) malloc (sizeof (struct procfs_dir_entry)); + + if (dir_entry) + { + dir_entry->hv = hv; + dir_entry->name = strdup (name); + dir_entry->node = 0; + dir_entry->dir = dir; + dir_entry->stat_timestamp = 0; + bzero (&dir_entry->stat, sizeof dir_entry->stat); + dir_entry->symlink_target = 0; + dir_entry->noent = 0; + dir_entry->valid = 0; + dir_entry->name_timestamp = 0; + dir_entry->ordered_next = 0; + dir_entry->ordered_self_p = 0; + dir_entry->next = 0; + dir_entry->self_p = 0; + insert (dir_entry, dir->htable, dir->htable_len); + dir->num_entries++; + } + } + + return dir_entry; +} + + +/* Lookup NAME in DIR, returning its entry, or an error. + *NODE will contain the result node, locked, and with + an additional reference, or 0 if an error occurs. */ +error_t procfs_dir_lookup (struct procfs_dir *dir, const char *name, + struct node **node) +{ + struct procfs_dir_entry *dir_entry = 0; + error_t err = 0; + char *fs_path = dir->fs_path; + + struct timeval tv; + maptime_read (procfs_maptime, &tv); + + time_t timestamp = tv.tv_sec; + + if (*name == '\0' || strcmp (name, ".") == 0) + /* Current directory -- just add an additional reference to DIR's node + and return it. */ + { + netfs_nref (dir->node); + *node = dir->node; + return 0; + } + else if (strcmp (name, "..") == 0) + /* Parent directory. */ + { + if (dir->node->nn->dir_entry) + { + *node = dir->node->nn->dir_entry->dir->node; + mutex_lock (&(*node)->lock); + netfs_nref (*node); + } + else + { + err = ENOENT; /* No .. */ + *node = 0; + } + + mutex_unlock (&dir->node->lock); + + return err; + } + + err = procfs_dir_refresh (dir, dir->node == dir->fs->root); + if (!err && !dir_entry) + dir_entry = lookup_entry (dir, name, 0); + + if (! err) + { + if (dir_entry && !dir_entry->noent) + /* We've got a dir entry, get a node for it. */ + { + /* If there's already a node, add a ref so that it doesn't go + away. */ + spin_lock (&netfs_node_refcnt_lock); + if (dir_entry->node) + dir_entry->node->references++; + spin_unlock (&netfs_node_refcnt_lock); + + if (! dir_entry->node) + /* No node; make one and install it into E. */ + { + if (! fs_path) + err = EROFS; + + if (! err) + { + err = procfs_create_node (dir_entry, fs_path, &dir_entry->node); + + if (!err && dir->num_live_entries++ == 0) + /* Keep a reference to dir's node corresponding to + children. */ + { + spin_lock (&netfs_node_refcnt_lock); + dir->node->references++; + spin_unlock (&netfs_node_refcnt_lock); + } + } + } + + if (! err) + { + *node = dir_entry->node; + /* We have to unlock DIR's node before locking the child node + because the locking order is always child-parent. We know + the child node won't go away because we already hold the + additional reference to it. */ + mutex_unlock (&dir->node->lock); + mutex_lock (&dir_entry->node->lock); + } + } + else + err = ENOENT; + } + + if (err) + { + *node = 0; + mutex_unlock (&dir->node->lock); + } + +#if 0 + if (fs_path) + free (fs_path); +#endif + + return err; +} + +/* Lookup the null name in DIR, and return a node for it in NODE. Unlike + procfs_dir_lookup, this won't attempt to validate the existance of the + entry (to avoid opening a new connection if possible) -- that will happen + the first time the entry is refreshed. Also unlink ftpfs_dir_lookup, this + function doesn't expect DIR to be locked, and won't return *NODE locked. + This function is only used for bootstrapping the root node. */ +error_t +procfs_dir_null_lookup (struct procfs_dir *dir, struct node **node) +{ + struct procfs_dir_entry *dir_entry; + error_t err = 0; + + dir_entry = lookup_entry (dir, "", 1); + if (! dir_entry) + return ENOMEM; + + if (! dir_entry->noent) + /* We've got a dir entry, get a node for it. */ + { + /* If there's already a node, add a ref so that it doesn't go away. */ + spin_lock (&netfs_node_refcnt_lock); + if (dir_entry->node) + dir_entry->node->references++; + spin_unlock (&netfs_node_refcnt_lock); + + if (! dir_entry->node) + /* No node; make one and install it into DIR_ENTRY. */ + { + err = procfs_create_node (dir_entry, dir->fs_path, &dir_entry->node); + + if (!err && dir->num_live_entries++ == 0) + /* Keep a reference to dir's node corresponding to children. */ + { + spin_lock (&netfs_node_refcnt_lock); + dir->node->references++; + spin_unlock (&netfs_node_refcnt_lock); + } + } + + if (! err) + *node = dir_entry->node; + } + else + err = ENOENT; + + return err; +} + +/* Remove the specified DIR and free all its allocated + storage. */ +void procfs_dir_remove (struct procfs_dir *dir) +{ + + /* STUB */ + + return 0; +} + +/* Make all the directory entries invalid */ +static void +make_dir_invalid (struct procfs_dir *dir) +{ + int count; + size_t len = dir->htable_len; + struct procfs_dir_entry **htable = dir->htable; + struct procfs_dir_entry *dir_entry; + + for (count = 0; count < len; count++) + { + dir_entry = htable[count]; + while (dir_entry) + { + dir_entry->valid = 0; + dir_entry = dir_entry->next; + } + } +} + +/* Checks if the DIR name is in list of + Active pids. */ +int is_in_pid_list (struct procfs_dir *dir) +{ + int dir_name; + int count; + pid_t *pids = NULL; + int pidslen = 0; + error_t err; + + if (dir->node->nn) + { + dir_name = atoi (dir->node->nn->dir_entry->name); + err = proc_getallpids (getproc (), &pids, &pidslen); + + for (count = 0; count < pidslen; ++count) + if (pids[count] == dir_name) + return 1; + } + + return 0; + +} + +/* Checks if DIR is a directory that + represents a pid. */ +int check_parent (struct procfs_dir *dir) +{ + if (dir == dir->fs->root) + return 0; + else + if (is_in_pid_list (dir)) + return 1; + else + return 0; + +} + +/* Refresh DIR. */ +error_t procfs_dir_refresh (struct procfs_dir *dir, int isroot) +{ + error_t err; + int is_parent_pid; + struct node *node; + make_dir_invalid (dir); + + struct timeval tv; + maptime_read (procfs_maptime, &tv); + + time_t timestamp = tv.tv_sec; + cur_entry = &dir->ordered; + if (isroot) + err = procfs_fill_root_dir(dir, timestamp); + else + { + err = update_dir_entries (dir, timestamp); + is_parent_pid = check_parent (dir); + if (is_parent_pid) + err = procfs_create_files (dir, &node, timestamp); + } + + return err; +} + +/* Update the directory entry for NAME to reflect STAT and SYMLINK_TARGET. + This also creates a valid linked list of entries imposing ordering on + them. */ +struct procfs_dir_entry* +update_entries_list (struct procfs_dir *dir, const char *name, + const struct stat *stat, time_t timestamp, + const char *symlink_target) +{ + ino_t ino; + struct procfs_dir_entry *dir_entry = lookup_entry (dir, name, 1); + struct procfs *fs = dir->fs; + + if (! dir_entry) + return ENOMEM; + + if (dir_entry->stat.st_ino) + ino = dir_entry->stat.st_ino; + else + ino = fs->next_inode++; + + dir_entry->name_timestamp = timestamp; + + if (stat) + /* The ST and SYMLINK_TARGET parameters are only valid if ST isn't 0. */ + { + dir_entry->stat = *stat; + dir_entry->stat_timestamp = timestamp; + + if (!dir_entry->symlink_target || !symlink_target + || strcmp (dir_entry->symlink_target, symlink_target) != 0) + { + if (dir_entry->symlink_target) + free (dir_entry->symlink_target); + dir_entry->symlink_target = symlink_target ? strdup (symlink_target) : 0; + } + } + + /* The st_ino field is always valid. */ + dir_entry->stat.st_ino = ino; + dir_entry->stat.st_fsid = fs->fsid; + dir_entry->stat.st_fstype = PROCFILESYSTEM; + + dir_entry->valid = 1; + + if (! dir_entry->ordered_self_p) + /* Position DIR_ENTRY in the ordered chain following the previously seen entry. */ + { + /* The PREV_ENTRY_NEXT_P field holds a pointer to the NEXT-field of the + previous entry, or a pointer to the ORDERED field in the directory. */ + dir_entry->ordered_self_p = cur_entry; + + if (*dir_entry->ordered_self_p) + /* Update the self_p pointer of the previous successor. */ + (*dir_entry->ordered_self_p)->ordered_self_p = &dir_entry->ordered_next; + + /* DIR_ENTRY comes before the previous successor. */ + dir_entry->ordered_next = *dir_entry->ordered_self_p; + + *dir_entry->ordered_self_p = dir_entry; /* Put DIR_ENTRY there. */ + } + + /* Put the next entry after this one. */ + cur_entry = &dir_entry->ordered_next; + + return dir_entry; +} + +/* Fills DIR, the root directory with all the pids of + processes running in the system as directories. */ +error_t +procfs_fill_root_dir(struct procfs_dir *dir, time_t timestamp) +{ + error_t err; + char *data; + pid_t *pids; + int pidslen; + struct stat *stat = (struct stat *) malloc (sizeof (struct stat)); + stat->st_mode = S_IFDIR; + + int count; + char *dir_name_pid; + struct node *node; + struct procfs_dir *new_dir; + struct procfs_dir_entry *dir_entry; + + pids = NULL; + pidslen = 0; + err = proc_getallpids (getproc (), &pids, &pidslen); + + if (!err) + { + for (count = 0; count < pidslen; count++) + { + if (asprintf (&dir_name_pid, "%d", pids[count]) == -1) + return errno; + +#if 0 + node = (struct node *) malloc (sizeof (struct node)); + new_dir = (struct procfs_dir *) malloc (sizeof (struct procfs_dir )); + + if (! node || ! new_dir ) + return ENOMEM; +#endif + dir_entry = update_entries_list (dir, dir_name_pid, + stat, timestamp, NULL); + err = procfs_create_node (dir_entry, dir_name_pid, &node); + + procfs_dir_create (dir->fs, node, + dir_name_pid, &new_dir); + free(dir_name_pid); + } + } + + if ((err = procfs_create_uptime (dir, &node, timestamp)) != 0) + return err; + + if ((err = procfs_create_stat (dir, &node, timestamp)) != 0) + return err; + + if ((err = procfs_create_version (dir, &node, timestamp)) != 0) + return err; + + if ((err = procfs_create_meminfo (dir, &node, timestamp)) != 0) + return err; + + if ((err = procfs_create_loadavg (dir, &node, timestamp)) != 0) + return err; + + return 0; +} + +error_t update_dir_entries (struct procfs_dir *dir) +{ + /* STUB */ + return 0; +} diff --git a/procfs_nonpid_files.c b/procfs_nonpid_files.c new file mode 100644 index 00000000..104ae8b3 --- /dev/null +++ b/procfs_nonpid_files.c @@ -0,0 +1,462 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs_nonpid_files.c -- This file contains function definitions + to create and update the non-Per PID + files and their contents. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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. + + A portion of the code in this file is based on vmstat.c code + present in the hurd repositories copyrighted to FSF. The + Copyright notice from that file is given below. + + Copyright (C) 1997,98,2002 Free Software Foundation, Inc. + Written by Miles Bader + This file is part of the GNU Hurd. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "procfs.h" + +typedef long long val_t; +#define BADVAL ((val_t) - 1LL) + +/* default pager port (must be privileged to fetch this). */ +mach_port_t def_pager; +struct default_pager_info def_pager_info; + +error_t procfs_create_uptime (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "uptime") == -1) + return errno; + if (asprintf (&file_path, "%s", "uptime") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return err; +} + +error_t procfs_create_version(struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "version") == -1) + return errno; + if (asprintf (&file_path, "%s", "version") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return 0; +} + +error_t procfs_create_stat (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "stat") == -1) + return errno; + if (asprintf (&file_path, "%s", "stat") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return err; +} + +error_t procfs_create_meminfo (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "meminfo") == -1) + return errno; + if (asprintf (&file_path, "%s", "meminfo") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return err; +} + +error_t procfs_create_loadavg (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "loadavg") == -1) + return errno; + if (asprintf (&file_path, "%s", "loadavg") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return err; +} + +error_t get_uptime (double *uptime_secs) +{ + struct timeval boot_time, uptime, now; + error_t err; + struct proc_stat *ps; + + err = _proc_stat_create (1, ps_context, &ps); + + if (err) + return err; + + err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); + if (!err && !(ps->flags & PSTAT_TASK_BASIC)) + err = EGRATUITOUS; + + if (! err) + { + time_value_t *const tv = &proc_stat_task_basic_info (ps)->creation_time; + boot_time.tv_sec = tv->seconds; + boot_time.tv_usec = tv->microseconds; + if (gettimeofday (&now, 0) < 0) + error (0, errno, "gettimeofday"); + timersub (&now, &boot_time, &uptime); + *uptime_secs = (double)uptime.tv_sec + ((double)uptime.tv_usec / 1000000); + } + + _proc_stat_free (ps); + return err; +} + +error_t get_total_times (double *total_user_time_secs , double *total_system_time_secs ) +{ + error_t err; + pid_t *pids; + int pidslen = 0, count; + struct proc_stat *ps; + struct task_thread_times_info live_threads_times; + + *total_user_time_secs = 0; + *total_system_time_secs = 0; + + pids = NULL; + err = proc_getallpids (getproc (), &pids, &pidslen); + + if (!err) + for (count = 0; count < pidslen; count++) + { + err = _proc_stat_create (pids[count], ps_context, &ps); + if (err) + return err; + + err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); + if (!err && !(ps->flags & PSTAT_TASK_BASIC)) + err = EGRATUITOUS; + + if (! err) + { + *total_user_time_secs += + ((double) (proc_stat_task_basic_info (ps)->user_time.seconds)) + + (((double) (proc_stat_task_basic_info (ps)->user_time.microseconds)) / + (1000 * 1000)); + + *total_system_time_secs += + ((double) (proc_stat_task_basic_info (ps)->system_time.seconds)) + + (((double) (proc_stat_task_basic_info (ps)->system_time.microseconds)) / (1000 * 1000)); + + error_t err = set_field_value (ps, PSTAT_TASK); + if (! err) + { + err = get_task_thread_times (ps->task, &live_threads_times); + if (! err) + { + *total_user_time_secs += ((double) (live_threads_times.user_time.seconds)) + + (((double) (live_threads_times.user_time.microseconds)) / (1000 * 1000)); + *total_system_time_secs += ((double) (live_threads_times.system_time.seconds)) + + (((double) (live_threads_times.system_time.microseconds)) / (1000 * 1000)); + + } + } + } + _proc_stat_free (ps); + } + + return err; +} + +error_t procfs_write_nonpid_stat (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *stat_data; + error_t err; + double uptime_secs, total_user_time_secs; + double total_system_time_secs, idle_time_secs; + + err = get_uptime (&uptime_secs); + if (! err) + { + err = get_total_times (&total_user_time_secs, &total_system_time_secs); + if (! err) + { + idle_time_secs = uptime_secs - + total_system_time_secs; + + /* If the values are multiplied by 100, it iss done so to adjust + values in seconds to jiffies. */ + if (asprintf (&stat_data, "cpu %ld %ld %ld %ld %ld %ld %d %d %d\n" + "cpu0 %ld %ld %ld %ld %ld %ld %d %d %d\n" + "intr %ld %ld %ld %ld %ld %ld %d %d %d\n", + (long)(total_user_time_secs * 100), 0, + (long)(total_system_time_secs * 100), + (long) (idle_time_secs * 100), 0, 0, 0, 0, + 0, (long)(total_user_time_secs * 100), 0, + (long)(total_system_time_secs * 100), + (long)(idle_time_secs * 100), 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == -1) + return errno; + } + } + + memcpy (data, stat_data, strlen(stat_data)); + *len = strlen (data); + + free (stat_data); + return err; +} + +/* Makes sure the default pager port and associated + info exists, and returns 0 if not (after printing + an error). */ +static int +ensure_def_pager_info () +{ + error_t err; + + if (def_pager == MACH_PORT_NULL) + { + mach_port_t host; + + err = get_privileged_ports (&host, 0); + if (err == EPERM) + { + /* We are not root, so try opening the /servers file. */ + def_pager = file_name_lookup (_SERVERS_DEFPAGER, O_READ, 0); + if (def_pager == MACH_PORT_NULL) + { + error (0, errno, _SERVERS_DEFPAGER); + return 0; + } + } + if (def_pager == MACH_PORT_NULL) + { + if (err) + { + error (0, err, "get_privileged_ports"); + return 0; + } + + err = vm_set_default_memory_manager (host, &def_pager); + mach_port_deallocate (mach_task_self (), host); + + if (err) + { + error (0, err, "vm_set_default_memory_manager"); + return 0; + } + } + } + + if (!MACH_PORT_VALID (def_pager)) + { + if (def_pager == MACH_PORT_NULL) + { + error (0, 0, + "No default pager running, so no swap information available"); + def_pager = MACH_PORT_DEAD; /* so we don't try again */ + } + return 0; + } + + err = default_pager_info (def_pager, &def_pager_info); + if (err) + error (0, err, "default_pager_info"); + return (err == 0); +} + +#define SWAP_FIELD(getter, expr) \ + static val_t getter () \ + { return ensure_def_pager_info () ? (val_t) (expr) : BADVAL; } + +SWAP_FIELD (get_swap_size, def_pager_info.dpi_total_space) +SWAP_FIELD (get_swap_free, def_pager_info.dpi_free_space) +SWAP_FIELD (get_swap_page_size, def_pager_info.dpi_page_size) +SWAP_FIELD (get_swap_active, (def_pager_info.dpi_total_space + - def_pager_info.dpi_free_space)) + +error_t procfs_write_nonpid_meminfo (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *meminfo_data; + error_t err; + struct vm_statistics vmstats; + + err = vm_statistics (mach_task_self (), &vmstats); + + unsigned long mem_size = ((vmstats.free_count + + vmstats.active_count + vmstats.inactive_count + + vmstats.wire_count) * vmstats.pagesize) / 1024; + + if (! err) + if (asprintf (&meminfo_data, "MemTotal:\t%lu kB\n" + "MemFree:\t%lu kB\n" + "Buffers:\t%ld kB\n" + "Cached:\t\t%ld kB\n" + "SwapCached:\t%ld kB\n" + "Active:\t\t%lu kB\n" + "Inactive:\t%lu kB\n" + "HighTotal:\t%lu kB\n" + "HighFree:\t%lu kB\n" + "LowTotal:\t%lu kB\n" + "LowFree:\t%lu kB\n" + "SwapTotal:\t%lu kB\n" + "SwapFree:\t%lu kB\n", + mem_size, (PAGES_TO_BYTES(vmstats.free_count)) / 1024 , 0, 0, 0, + (PAGES_TO_BYTES(vmstats.active_count)) / 1024, + (PAGES_TO_BYTES(vmstats.inactive_count)) / 1024, 0, 0, 0, 0, + get_swap_size (), get_swap_free ()) == -1) + return errno; + + memcpy (data, meminfo_data, strlen(meminfo_data)); + *len = strlen (data); + + free (meminfo_data); + return err; +} + +error_t procfs_write_nonpid_loadavg (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *loadavg_data; + error_t err; + processor_set_info_t info; + natural_t *count; + struct host_load_info *load; + mach_port_t host; + + err = ps_host_load_info (&load); + if (err) + error (0, err, "ps_host_load_info"); + + if (! err) + if (asprintf (&loadavg_data, "%.2f %.2f %.2f %d/%d %d\n", + (double)load->avenrun[0] / (double)LOAD_SCALE, + (double)load->avenrun[1] / (double)LOAD_SCALE, + (double)load->avenrun[2] / (double)LOAD_SCALE, 0, 0, 0) == -1) + return errno; + + memcpy (data, loadavg_data, strlen(loadavg_data)); + *len = strlen (data); + + free (loadavg_data); + return err; +} + +error_t procfs_write_nonpid_uptime (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *uptime_data; + error_t err; + double uptime_secs, total_user_time_secs; + double total_system_time_secs, idle_time_secs; + + err = get_uptime (&uptime_secs); + if (! err) + { + err = get_total_times (&total_user_time_secs, + &total_system_time_secs); + if (! err) + { + idle_time_secs = uptime_secs - + total_system_time_secs; + + if (asprintf (&uptime_data, "%.2f %.2f \n", + uptime_secs, idle_time_secs) == -1) + return errno; + } + } + + + memcpy (data, uptime_data, strlen(uptime_data)); + *len = strlen (data); + + free (uptime_data); + return err; +} diff --git a/procfs_pid.h b/procfs_pid.h new file mode 100644 index 00000000..811cca84 --- /dev/null +++ b/procfs_pid.h @@ -0,0 +1,86 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs_pid.h -- This is the header file of which contains defintions + for structure of directory with PID as the name and + structure of each file in this directory. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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 __PROCFS_PID_H__ +#define __PROCFS_PID_H__ + +struct procfs_pid_files +{ + struct procfs_cwd *procfs_cwd; + struct procfs_environ *procfs_environ; + struct procfs_cpu *procfs_cpu; + struct procfs_root *procfs_root; + struct procfs_exe *procfs_exe; + struct procfs_stat *_procfs_stat; + struct procfs_statm *procfs_statm; +}; + +struct procfs_stat +{ + pid_t pid; + char *comm; + char *state; + pid_t ppid; + pid_t pgid; + pid_t sid; + int tty_nr; + pid_t tty_pgrp; + unsigned flags; + long unsigned minflt; + long unsigned cminflt; + long unsigned majflt; + long unsigned cmajflt; + time_t utime; + time_t stime; + time_t cutime; + time_t cstime; + long priority; + long nice; + long num_threads; + long itrealvalue; + long long unsigned starttime; + long unsigned vsize; + long rss; + long unsigned rlim; + long unsigned startcode; + long unsigned endcode; + long unsigned startstack; + long unsigned kstkesp; + long unsigned kstkeip; + long unsigned signal; + long unsigned blocked; + long unsigned sigignore; + long unsigned sigcatch; + long unsigned wchan; + long unsigned nswap; + long unsigned cnswap; + int exit_signal; + int processor; + unsigned rt_priority; + unsigned policy; + long long unsigned delayacct_blkio_ticks; +}; + +#endif diff --git a/procfs_pid_files.c b/procfs_pid_files.c new file mode 100644 index 00000000..1012510b --- /dev/null +++ b/procfs_pid_files.c @@ -0,0 +1,570 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs_pid_files.c -- This file contains definitions to perform + file operations such as creating, writing to, + reading from and removing files that holds + information for each process with PID + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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. + + A portion of the code in this file is based on ftpfs code + present in the hurd repositories copyrighted to FSF. The + Copyright notice from that file is given below. + +*/ + +#include +#include +#include +#include +#include +#include + +#include "procfs.h" +#include "procfs_pid.h" + +/* Update the files named NAME within the directory named + PID also with SYMLINK TARGET if necessary. */ +struct procfs_dir_entry* +update_pid_entries (struct procfs_dir *dir, const char *name, + time_t timestamp, + const char *symlink_target) +{ + struct procfs_dir_entry *dir_entry; + struct stat *stat = (struct stat *) malloc (sizeof (struct stat)); + stat->st_mode = S_IFREG; + + dir_entry = update_entries_list (dir, name, stat, + timestamp, symlink_target); + + return dir_entry; +} + +/* Creates files to store process information for DIR + whose names are pids and returns these files in *NODE. */ +error_t +procfs_create_files (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "stat") == -1) + return errno; + if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "stat") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + if (asprintf (&file_name, "%s", "status") == -1) + return errno; + if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "status") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + if (asprintf (&file_name, "%s", "cmdline") == -1) + return errno; + if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "cmdline") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + if (asprintf (&file_name, "%s", "statm") == -1) + return errno; + if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "statm") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + +#if 0 + nodes_list = &node_stat; + nodes_list++; + node = nodes_list; +#endif + + return err; +} + +/* Check if the PSTAT_FLAG is set in the corresponding PS + structure, if not set it and check again and return error + status accordingly. */ +error_t set_field_value (struct proc_stat *ps, int pstat_flag) +{ + error_t err; + + if (! (ps->flags & pstat_flag)) + { + err = proc_stat_set_flags (ps, pstat_flag); + if (err) + return err; + + /* This second check is done since ps.h specifies to + do so since the previous call would not have set + the required value. */ + if (! (ps->flags & pstat_flag)) + return EGRATUITOUS; + } + + return 0; +} + +/* Adjusts TIME_VAL structure having Seconds and + Microseconds into the value in jiffies. The + value of jiffy is a hack to adjust to what + procps uses. */ +time_t adjust_jiffy_time (time_value_t time_val) +{ + time_t jiffy_time = time_val.seconds * JIFFY_ADJUST; + jiffy_time += (time_val.microseconds * JIFFY_ADJUST) + / (1000 * 1000); + + return jiffy_time; +} + +/* Extract the user and system time for the live threads of + the process. This information is directly retrieved from + MACH since neither libps not proc makes this available. */ +error_t get_task_thread_times (task_t task, + struct task_thread_times_info *live_threads_times) +{ + error_t err; + size_t tkcount = TASK_THREAD_TIMES_INFO_COUNT; + + err = task_info (task, TASK_THREAD_TIMES_INFO, + (task_info_t) live_threads_times, &tkcount); + if (err == MACH_SEND_INVALID_DEST) + err = ESRCH; + + return err; +} + +/* Obtains the User Time in UTIME and System Time in STIME from + MACH directly since this is neither made available by libps + nor by proc server. */ +error_t get_live_threads_time (struct proc_stat *ps, + time_t *utime, time_t *stime) +{ + struct task_thread_times_info live_threads_times; + error_t err = set_field_value (ps, PSTAT_TASK); + + if (! err) + { + err = get_task_thread_times (ps->task, &live_threads_times); + if (! err) + { + *utime = adjust_jiffy_time ( + live_threads_times.user_time); + *stime = adjust_jiffy_time ( + live_threads_times.system_time); + } + } + + return err; +} + +/* Get the data for stat file into the structure + PROCFS_STAT. */ +error_t get_stat_data (pid_t pid, + struct procfs_stat **procfs_stat) +{ + error_t err; + struct procfs_stat *new = (struct procfs_stat *) + malloc (sizeof (struct procfs_stat)); + + struct proc_stat *ps; + time_t utime, stime; + + err = _proc_stat_create (pid, ps_context, &ps); + + new->pid = pid; + + if (! err) + { + err = set_field_value (ps, PSTAT_ARGS); + if (! err) + asprintf (&new->comm, "%s", ps->args); + } + + err = set_field_value (ps, PSTAT_STATE); + if (! err) + { + if (ps->state & PSTAT_STATE_P_STOP) + new->state = strdup ("T"); + if (ps->state & PSTAT_STATE_P_ZOMBIE) + new->state = strdup ("Z"); + if (ps->state & PSTAT_STATE_P_FG) + new->state = strdup ("+"); + if (ps->state & PSTAT_STATE_P_SESSLDR) + new->state = strdup ("s"); + if (ps->state & PSTAT_STATE_P_LOGINLDR) + new->state = strdup ("l"); + if (ps->state & PSTAT_STATE_P_FORKED) + new->state = strdup ("f"); + if (ps->state & PSTAT_STATE_P_NOMSG) + new->state = strdup ("m"); + if (ps->state & PSTAT_STATE_P_NOPARENT) + new->state = strdup ("p"); + if (ps->state & PSTAT_STATE_P_ORPHAN) + new->state = strdup ("o"); + if (ps->state & PSTAT_STATE_P_TRACE) + new->state = strdup ("x"); + if (ps->state & PSTAT_STATE_P_WAIT) + new->state = strdup ("w"); + if (ps->state & PSTAT_STATE_P_GETMSG) + new->state = strdup ("g"); + } + + err = set_field_value (ps, PSTAT_PROC_INFO); + if (! err) + { + new->ppid = ps->proc_info->ppid; + new->pgid = ps->proc_info->pgrp; + new->sid = ps->proc_info->session; + new->tty_pgrp = ps->proc_info->pgrp; + } + else + { + new->ppid = 0; + new->pgid = 0; + new->sid = 0; + new->tty_pgrp = 0; + } + + err = set_field_value (ps, PSTAT_STATE); + if (! err) + new->flags = ps->state; + else + new->flags = 0; + + err = set_field_value (ps, PSTAT_TASK_EVENTS); + if (! err) + { + new->minflt = ps->task_events_info->faults; + new->majflt = ps->task_events_info->pageins; + } + else + { + new->minflt = 0; + new->majflt = 0; + } + + /* This seems to be a bit inconsistent with setting of other + fields in this code. There are two reasons for this. + 1. The actual information required is not made available + by libps which should be directly obtained from MACH. + 2. The same code which is required to get the information + have to be reused in procfs_nonpid_files.c */ + err = get_live_threads_time (ps, &utime, &stime); + if (! err) + { + new->utime = utime; + new->stime = stime; + } + else + { + new->utime = 0; + new->stime = 0; + } + + err = set_field_value (ps, PSTAT_TASK_BASIC); + if (! err) + { + new->cutime = adjust_jiffy_time ( + ps->task_basic_info->user_time); + new->cstime = adjust_jiffy_time ( + ps->task_basic_info->system_time); + + new->priority = ps->task_basic_info->base_priority; + new->starttime = adjust_jiffy_time ( + ps->task_basic_info->creation_time); + + new->vsize = ps->task_basic_info->virtual_size; + new->rss = ps->task_basic_info->resident_size; + } + else + { + new->cutime = 0; + new->cstime = 0; + new->priority = 0; + new->starttime = 0; + new->vsize = 0; + new->rss = 0; + } + + new->nice = getpriority (0, pid); + + err = set_field_value (ps, PSTAT_NUM_THREADS); + if (! err) + new->num_threads = ps->num_threads; + else + new->num_threads = 0; + + /* Not Supported in Linux 2.6 or later. */ + new->tty_nr = 0; + new->itrealvalue = 0; + new->nswap = 0; + new->cnswap = 0; + + /* Temporarily set to 0 until correct + values are found .*/ + new->cminflt = 0; + new->cmajflt = 0; + new->rlim = 0; + new->startcode = 0; + new->endcode = 0; + new->startstack = 0; + new->kstkesp = 0; + new->kstkeip = 0; + new->signal = 0; + new->blocked = 0; + new->sigignore = 0; + new->sigcatch = 0; + new->wchan = 0; + new->exit_signal = 0; + new->processor = 0; + new->rt_priority = 0; + new->policy = 0; + new->delayacct_blkio_ticks = 0; + + *procfs_stat = new; + _proc_stat_free (ps); + + return err; +} + +/* Writes required process information to stat file + within the directory represented by pid. Return + the data in DATA and actual length to be written + in LEN. */ +error_t +procfs_write_stat_file (struct procfs_dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + error_t err; + char *stat_data; + struct procfs_stat *procfs_stat; + pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); + + err = get_stat_data (pid, &procfs_stat); + + if (asprintf (&stat_data, "%d (%s) %s %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %llu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu \n", + procfs_stat->pid, procfs_stat->comm, + procfs_stat->state, procfs_stat->ppid, + procfs_stat->pgid, procfs_stat->sid, + procfs_stat->tty_nr, procfs_stat->tty_pgrp, + procfs_stat->flags, procfs_stat->minflt, + procfs_stat->cminflt, procfs_stat->majflt, + procfs_stat->cmajflt, procfs_stat->utime, + procfs_stat->stime, procfs_stat->cutime, + procfs_stat->cstime, procfs_stat->priority, + procfs_stat->nice, procfs_stat->num_threads, + procfs_stat->itrealvalue, procfs_stat->starttime, + procfs_stat->vsize, BYTES_TO_PAGES(procfs_stat->rss), + procfs_stat->rlim, procfs_stat->startcode, + procfs_stat->endcode, procfs_stat->startstack, + procfs_stat->kstkesp, procfs_stat->kstkeip, + procfs_stat->signal, procfs_stat->blocked, + procfs_stat->sigignore, procfs_stat->sigcatch, + procfs_stat->wchan, procfs_stat->nswap, + procfs_stat->cnswap, procfs_stat->exit_signal, + procfs_stat->processor, procfs_stat->rt_priority, + procfs_stat->policy, + procfs_stat->delayacct_blkio_ticks) == -1) + return errno; + + + memcpy (data, stat_data, strlen(stat_data)); + *len = strlen (data); + + free (stat_data); + free (procfs_stat); + + return err; +} + +/* Writes required process's command line information + to cmline file within the directory represented by + pid. Return the data in DATA and actual length to + be written in LEN. */ +error_t +procfs_write_cmdline_file (struct procfs_dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *cmdline_data; + error_t err; + struct proc_stat *ps; + pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); + err = _proc_stat_create (pid, ps_context, &ps); + + err = set_field_value (ps, PSTAT_ARGS); + + if (! err) + if (asprintf (&cmdline_data, "%s \n", ps->args) == -1) + return errno; + + memcpy (data, cmdline_data, strlen(cmdline_data)); + *len = strlen (data); + + _proc_stat_free (ps); + free (cmdline_data); + return err; +} + +/* Writes required process's information that is represented by + stat and statm in a human readable format to status file + within the directory represented by pid. Return the data + in DATA and actual length to be written in LEN. */ +error_t +procfs_write_status_file (struct procfs_dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *status_data; + error_t err; + struct proc_stat *ps; + struct procfs_stat *procfs_stat; + + pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); + err = _proc_stat_create (pid, ps_context, &ps); + + err = get_stat_data (pid, &procfs_stat); + + if (! err) + if (asprintf (&status_data, "Name:\t%s\nState:\t%s\nTgid:\t%d\nPid:\t%d\n", procfs_stat->comm, procfs_stat->state, procfs_stat->pid, procfs_stat->pid) == -1) + return errno; + + memcpy (data, status_data, strlen(status_data)); + *len = strlen (data); + + _proc_stat_free (ps); + + free (status_data); + free (procfs_stat); + + return err; +} + +/* Writes required process information to statm file + within the directory represented by pid. Return + the data in DATA and actual length to be written + in LEN. */ +error_t +procfs_write_statm_file (struct procfs_dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *statm_data; + error_t err; + struct proc_stat *ps; + struct procfs_stat *procfs_stat; + + pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); + err = _proc_stat_create (pid, ps_context, &ps); + + err = get_stat_data (pid, &procfs_stat); + + if (! err) + if (asprintf (&statm_data, "%lu %ld %d %d %d %d %d\n", + BYTES_TO_PAGES(procfs_stat->vsize), + BYTES_TO_PAGES(procfs_stat->rss), + 0, 0, 0, 0, 0) == -1) + return errno; + + memcpy (data, statm_data, strlen(statm_data)); + *len = strlen (data); + + _proc_stat_free (ps); + + free (statm_data); + free (procfs_stat); + + return err; +} + +/* Writes required process information to each of files + within directory represented by pid, for files specified + by NODE. Return the data in DATA and actual length of + data in LEN. */ +error_t +procfs_write_files_contents (struct node *node, + off_t offset, size_t *len, void *data) +{ + error_t err; + + if (! strcmp (node->nn->dir_entry->name, "stat")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_write_nonpid_stat (node->nn->dir_entry, + offset, len, data); + else + err = procfs_write_stat_file (node->nn->dir_entry, + offset, len, data); + + if (! strcmp (node->nn->dir_entry->name, "cmdline")) + err = procfs_write_cmdline_file (node->nn->dir_entry, + offset, len, data); + + if (! strcmp (node->nn->dir_entry->name, "status")) + err = procfs_write_status_file (node->nn->dir_entry, + offset, len, data); + + if (! strcmp (node->nn->dir_entry->name, "statm")) + err = procfs_write_statm_file (node->nn->dir_entry, + offset, len, data); + + if (! strcmp (node->nn->dir_entry->name, "meminfo")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_write_nonpid_meminfo (node->nn->dir_entry, + offset, len, data); + else + err = ENOENT; + + if (! strcmp (node->nn->dir_entry->name, "loadavg")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_write_nonpid_loadavg (node->nn->dir_entry, + offset, len, data); + else + err = ENOENT; + + if (! strcmp (node->nn->dir_entry->name, "uptime")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_write_nonpid_uptime (node->nn->dir_entry, + offset, len, data); + else + err = ENOENT; + + return err; +} -- cgit v1.2.3 From 688a421a1aef82d2688909f106c4a70172530b81 Mon Sep 17 00:00:00 2001 From: "Madhusudan.C.S" Date: Mon, 18 Aug 2008 17:15:00 +0200 Subject: 2008-08-14 Madhusudan.C.S * procfs.h: (jiffy_t): New typedef. * procfs_pid.h: "procfs.h" is included. (struct procfs_pid_files): Changed all the occurrences of time_t to jiffy_t. * procfs_pid_files.c: Removed "procfs.h". (adjust_jiffy_time): Changed return type from time_t to jiffy_t. Changed the type of jiffy_time variable from time_t to jiffy_t. (get_live_threads_time): Changed the type of utime and stime from time_t to jiffy_t. (get_stat_data): Changed the type of utime and stime from time_t to jiffy_t. --- procfs.h | 2 ++ procfs_pid.h | 10 ++++++---- procfs_pid_files.c | 9 ++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/procfs.h b/procfs.h index 95d4ee35..fa2fb7f7 100644 --- a/procfs.h +++ b/procfs.h @@ -53,6 +53,8 @@ #include #include +typedef unsigned long long jiffy_t; + /* A single entry in a directory. */ struct procfs_dir_entry { diff --git a/procfs_pid.h b/procfs_pid.h index 811cca84..566c83ea 100644 --- a/procfs_pid.h +++ b/procfs_pid.h @@ -26,6 +26,8 @@ #ifndef __PROCFS_PID_H__ #define __PROCFS_PID_H__ +#include "procfs.h" + struct procfs_pid_files { struct procfs_cwd *procfs_cwd; @@ -52,10 +54,10 @@ struct procfs_stat long unsigned cminflt; long unsigned majflt; long unsigned cmajflt; - time_t utime; - time_t stime; - time_t cutime; - time_t cstime; + jiffy_t utime; + jiffy_t stime; + jiffy_t cutime; + jiffy_t cstime; long priority; long nice; long num_threads; diff --git a/procfs_pid_files.c b/procfs_pid_files.c index 1012510b..55cc52c1 100644 --- a/procfs_pid_files.c +++ b/procfs_pid_files.c @@ -37,7 +37,6 @@ #include #include -#include "procfs.h" #include "procfs_pid.h" /* Update the files named NAME within the directory named @@ -148,9 +147,9 @@ error_t set_field_value (struct proc_stat *ps, int pstat_flag) Microseconds into the value in jiffies. The value of jiffy is a hack to adjust to what procps uses. */ -time_t adjust_jiffy_time (time_value_t time_val) +jiffy_t adjust_jiffy_time (time_value_t time_val) { - time_t jiffy_time = time_val.seconds * JIFFY_ADJUST; + jiffy_t jiffy_time = time_val.seconds * JIFFY_ADJUST; jiffy_time += (time_val.microseconds * JIFFY_ADJUST) / (1000 * 1000); @@ -178,7 +177,7 @@ error_t get_task_thread_times (task_t task, MACH directly since this is neither made available by libps nor by proc server. */ error_t get_live_threads_time (struct proc_stat *ps, - time_t *utime, time_t *stime) + jiffy_t *utime, jiffy_t *stime) { struct task_thread_times_info live_threads_times; error_t err = set_field_value (ps, PSTAT_TASK); @@ -208,7 +207,7 @@ error_t get_stat_data (pid_t pid, malloc (sizeof (struct procfs_stat)); struct proc_stat *ps; - time_t utime, stime; + jiffy_t utime, stime; err = _proc_stat_create (pid, ps_context, &ps); -- cgit v1.2.3 From 415e86d598c4e15d69b5f558d305b735462083bc Mon Sep 17 00:00:00 2001 From: "Madhusudan.C.S" Date: Mon, 18 Aug 2008 17:27:00 +0200 Subject: 2008-08-18 Madhusudan.C.S * procfs_nonpid_files.c: (procfs_write_nonpid_version): New function. * procfs_pid_files.c: (procfs_write_files_contents): Add a check to find if the read is requested for the version file and corresponding a call to it. --- procfs_nonpid_files.c | 18 +++++++++++++++++- procfs_pid_files.c | 7 +++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/procfs_nonpid_files.c b/procfs_nonpid_files.c index 104ae8b3..ab1341ff 100644 --- a/procfs_nonpid_files.c +++ b/procfs_nonpid_files.c @@ -269,7 +269,7 @@ error_t procfs_write_nonpid_stat (struct dir_entry *dir_entry, idle_time_secs = uptime_secs - total_system_time_secs; - /* If the values are multiplied by 100, it iss done so to adjust + /* If the values are multiplied by 100, it is done so to adjust values in seconds to jiffies. */ if (asprintf (&stat_data, "cpu %ld %ld %ld %ld %ld %ld %d %d %d\n" "cpu0 %ld %ld %ld %ld %ld %ld %d %d %d\n" @@ -460,3 +460,19 @@ error_t procfs_write_nonpid_uptime (struct dir_entry *dir_entry, free (uptime_data); return err; } + +error_t procfs_write_nonpid_version (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *version_data; + error_t err = 0; + + if (asprintf (&version_data, "Linux version 2.6.18\n", NULL) == -1) + return errno; + + memcpy (data, version_data, strlen(version_data)); + *len = strlen (data); + + free (version_data); + return err; +} diff --git a/procfs_pid_files.c b/procfs_pid_files.c index 55cc52c1..3ad77340 100644 --- a/procfs_pid_files.c +++ b/procfs_pid_files.c @@ -565,5 +565,12 @@ procfs_write_files_contents (struct node *node, else err = ENOENT; + if (! strcmp (node->nn->dir_entry->name, "version")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_write_nonpid_version (node->nn->dir_entry, + offset, len, data); + else + err = ENOENT; + return err; } -- cgit v1.2.3 From ac38ed88929c70c4ede56816c053bf170c9c2efd Mon Sep 17 00:00:00 2001 From: "Madhusudan.C.S" Date: Mon, 18 Aug 2008 19:34:00 +0200 Subject: 2008-08-18 Madhusudan.C.S * procfs_nonpid_files.c: (get_uptime): Changed the parameter type from double to struct timeval. Changed the parameter name from uptime_secs to uptime. Removed uptime variable. Changed timersub to use the passed pointer instead of the local variable. Removed the calculation of uptime_secs. (get_total_times): Changed the parameters type from double to struct timeval. Changed the parameters name from total_user_time_secs to total_user_time and total_system_time_secs to total_system_time. New variables total_user_time_tmp, total_system_time_tmp and tmpval of type struct timeval. Call timerclear to clear the tmp variables. Remove calculation of times in seconds and do the same on struct timeval variables throughout using the timeradd macro. Assign values of temporary local variables to the pointers passed as parameters. (procfs_write_nonpid_stat): Replaced variables that hold time in seconds with struct timeval type variables and jiffy_t type variables. Argument to get_uptime changed from uptime_secs to uptime. Arguments to get_total_times changed from total_user_time_secs to total_user_time and total_system_time_secs to total_system_time. Replace arithematic time subtraction with timersub macro. Convert all the times in struct timeval type variables to jiffy_t type. Changed the type casting for the asprintf arguments to be compatible with jiffy_t type. (procfs_write_nonpid_uptime): Replaced variables that hold time in seconds with struct timeval type variables. Argument to get_uptime changed from uptime_secs to uptime. Arguments to get_total_times changed from total_user_time_secs to total_user_time and total_system_time_secs to total_system_time. Replace arithematic time subtraction with timersub macro. Convert all the times in struct timeval type variables to seconds. --- procfs_nonpid_files.c | 138 +++++++++++++++++++++++++++++++------------------- 1 file changed, 87 insertions(+), 51 deletions(-) diff --git a/procfs_nonpid_files.c b/procfs_nonpid_files.c index ab1341ff..9cb0c57a 100644 --- a/procfs_nonpid_files.c +++ b/procfs_nonpid_files.c @@ -166,9 +166,9 @@ error_t procfs_create_loadavg (struct procfs_dir *dir, return err; } -error_t get_uptime (double *uptime_secs) +error_t get_uptime (struct timeval *uptime) { - struct timeval boot_time, uptime, now; + struct timeval boot_time, now; error_t err; struct proc_stat *ps; @@ -188,15 +188,15 @@ error_t get_uptime (double *uptime_secs) boot_time.tv_usec = tv->microseconds; if (gettimeofday (&now, 0) < 0) error (0, errno, "gettimeofday"); - timersub (&now, &boot_time, &uptime); - *uptime_secs = (double)uptime.tv_sec + ((double)uptime.tv_usec / 1000000); + timersub (&now, &boot_time, uptime); } _proc_stat_free (ps); return err; } -error_t get_total_times (double *total_user_time_secs , double *total_system_time_secs ) +error_t get_total_times (struct timeval *total_user_time, + struct timeval *total_system_time) { error_t err; pid_t *pids; @@ -204,8 +204,12 @@ error_t get_total_times (double *total_user_time_secs , double *total_system_tim struct proc_stat *ps; struct task_thread_times_info live_threads_times; - *total_user_time_secs = 0; - *total_system_time_secs = 0; + struct timeval total_user_time_tmp; + struct timeval total_system_time_tmp; + struct timeval tmpval; + + timerclear (&total_user_time_tmp); + timerclear (&total_system_time_tmp); pids = NULL; err = proc_getallpids (getproc (), &pids, &pidslen); @@ -222,33 +226,40 @@ error_t get_total_times (double *total_user_time_secs , double *total_system_tim err = EGRATUITOUS; if (! err) - { - *total_user_time_secs += - ((double) (proc_stat_task_basic_info (ps)->user_time.seconds)) + - (((double) (proc_stat_task_basic_info (ps)->user_time.microseconds)) / - (1000 * 1000)); + { + tmpval.tv_sec = proc_stat_task_basic_info (ps)->user_time.seconds; + tmpval.tv_usec = proc_stat_task_basic_info (ps)->user_time.seconds; + timeradd (&total_user_time_tmp, &tmpval, &total_user_time_tmp); + + tmpval.tv_sec = proc_stat_task_basic_info (ps)->system_time.seconds; + tmpval.tv_usec = proc_stat_task_basic_info (ps)->system_time.seconds; + timeradd (&total_system_time_tmp, &tmpval, &total_system_time_tmp); - *total_system_time_secs += - ((double) (proc_stat_task_basic_info (ps)->system_time.seconds)) + - (((double) (proc_stat_task_basic_info (ps)->system_time.microseconds)) / (1000 * 1000)); - error_t err = set_field_value (ps, PSTAT_TASK); if (! err) { err = get_task_thread_times (ps->task, &live_threads_times); if (! err) { - *total_user_time_secs += ((double) (live_threads_times.user_time.seconds)) + - (((double) (live_threads_times.user_time.microseconds)) / (1000 * 1000)); - *total_system_time_secs += ((double) (live_threads_times.system_time.seconds)) + - (((double) (live_threads_times.system_time.microseconds)) / (1000 * 1000)); - + tmpval.tv_sec = live_threads_times.user_time.seconds; + tmpval.tv_usec = live_threads_times.user_time.microseconds; + timeradd (&total_user_time_tmp, &tmpval, &total_user_time_tmp); + + tmpval.tv_sec = live_threads_times.system_time.seconds; + tmpval.tv_usec = live_threads_times.system_time.microseconds; + timeradd (&total_system_time_tmp, &tmpval, &total_system_time_tmp); } } } _proc_stat_free (ps); } - + + total_user_time->tv_sec = total_user_time_tmp.tv_sec; + total_user_time->tv_usec = total_user_time_tmp.tv_usec; + + total_system_time->tv_sec = total_system_time_tmp.tv_sec; + total_system_time->tv_usec = total_system_time_tmp.tv_usec; + return err; } @@ -257,30 +268,45 @@ error_t procfs_write_nonpid_stat (struct dir_entry *dir_entry, { char *stat_data; error_t err; - double uptime_secs, total_user_time_secs; - double total_system_time_secs, idle_time_secs; + jiffy_t total_user_time_jiffy, total_system_time_jiffy; + jiffy_t idle_time_jiffy; + struct timeval uptime, total_user_time, total_system_time; + struct timeval idle_time; - err = get_uptime (&uptime_secs); + err = get_uptime (&uptime); + if (! err) { - err = get_total_times (&total_user_time_secs, &total_system_time_secs); + err = get_total_times (&total_user_time, &total_system_time); + if (! err) { - idle_time_secs = uptime_secs - - total_system_time_secs; - - /* If the values are multiplied by 100, it is done so to adjust - values in seconds to jiffies. */ - if (asprintf (&stat_data, "cpu %ld %ld %ld %ld %ld %ld %d %d %d\n" - "cpu0 %ld %ld %ld %ld %ld %ld %d %d %d\n" - "intr %ld %ld %ld %ld %ld %ld %d %d %d\n", - (long)(total_user_time_secs * 100), 0, - (long)(total_system_time_secs * 100), - (long) (idle_time_secs * 100), 0, 0, 0, 0, - 0, (long)(total_user_time_secs * 100), 0, - (long)(total_system_time_secs * 100), - (long)(idle_time_secs * 100), 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == -1) + timersub (&uptime, &total_system_time, + &idle_time); + + total_user_time_jiffy = 100 * ((double) total_user_time.tv_sec + + (double) total_user_time.tv_usec / (1000 * 1000)); + total_system_time_jiffy = 100 * ((double) total_system_time.tv_sec + + (double) total_system_time.tv_usec / (1000 * 1000)); + idle_time_jiffy = 100 * ((double) idle_time.tv_sec + + (double) idle_time.tv_usec / (1000 * 1000)); + + if (asprintf (&stat_data, "cpu %llu %llu %llu %llu %llu %llu %d %d %d\n" + "cpu0 %llu %llu %llu %llu %llu %llu %d %d %d\n" + "intr %llu %llu %llu %llu %llu %llu %d %d %d\n", + total_user_time_jiffy, (long long unsigned) 0, + total_system_time_jiffy, idle_time_jiffy, + (long long unsigned) 0, (long long unsigned) 0, + 0, 0, 0, + total_user_time_jiffy, (long long unsigned) 0, + total_system_time_jiffy, idle_time_jiffy, + (long long unsigned) 0, (long long unsigned) 0, + 0, 0, 0, + (long long unsigned) 0, + (long long unsigned) 0, (long long unsigned) 0, (long long unsigned) 0, + (long long unsigned) 0, + (long long unsigned) 0, (long long unsigned) 0, + (long long unsigned) 0, (long long unsigned) 0) == -1) return errno; } } @@ -434,23 +460,33 @@ error_t procfs_write_nonpid_uptime (struct dir_entry *dir_entry, { char *uptime_data; error_t err; - double uptime_secs, total_user_time_secs; - double total_system_time_secs, idle_time_secs; + double uptime_secs, idle_time_secs; + + struct timeval uptime_val; + struct timeval uptime, total_user_time, total_system_time; + struct timeval idle_time; + - err = get_uptime (&uptime_secs); + err = get_uptime (&uptime); if (! err) { - err = get_total_times (&total_user_time_secs, - &total_system_time_secs); + err = get_total_times (&total_user_time, + &total_system_time); if (! err) { - idle_time_secs = uptime_secs - - total_system_time_secs; - - if (asprintf (&uptime_data, "%.2f %.2f \n", + timersub (&uptime, &total_system_time, + &idle_time); + + uptime_secs = (double) uptime.tv_sec + + (double) uptime.tv_usec / (1000 * 1000); + + idle_time_secs = (double) idle_time.tv_sec + + (double) idle_time.tv_usec / (1000 * 1000); + + if (asprintf (&uptime_data, "%.2f %.2f\n", uptime_secs, idle_time_secs) == -1) return errno; - } + } } -- cgit v1.2.3 From b0c18505223662500cd54a0b901efcd69a761077 Mon Sep 17 00:00:00 2001 From: "Madhusudan.C.S" Date: Mon, 18 Aug 2008 20:26:00 +0200 Subject: 2008-08-18 Madhusudan.C.S * procfs_nonpid_files.c: (procfs_write_nonpid_stat): Changed to procfs_read_nonpid_stat. (procfs_write_nonpid_meminfo): Changed to procfs_read_nonpid_meminfo. (procfs_write_nonpid_loadavg): Changed to procfs_read_nonpid_loadavg. (procfs_write_nonpid_uptime): Changed to procfs_read_nonpid_uptime. (procfs_write_nonpid_version):Changed to procfs_read_nonpid_version. * procfs_pid_files.c: (procfs_write_stat_file): Changed to procfs_read_stat_file. Changed the comment correspondingly from Write to Read. (procfs_write_cmdline_file ): Changed to procfs_read_cmdline_file. Changed the comment correspondingly from Write to Read. (procfs_write_status_file): Changed to procfs_read_status_file. Changed the comment correspondingly from Write to Read. (procfs_write_statm_file): Changed to procfs_read_statm_file. Changed the comment correspondingly from Write to Read. (procfs_write_files_contents): Changed to procfs_read_files_contents. Changed the comment correspondingly from Write to Read. Changed the call to procfs_write_nonpid_stat to procfs_read_nonpid_stat. Changed the call to procfs_write_stat_file to procfs_read_stat_file. Changed the call to procfs_write_cmdline_file to procfs_read_cmdline_file. Changed the call to procfs_write_status_file to procfs_read_status_file. Changed the call to procfs_write_statm_file to procfs_read_statm_file. Changed the call to procfs_write_nonpid_meminfo to procfs_read_nonpid_meminfo. Changed the call to procfs_write_nonpid_loadavg to procfs_read_nonpid_loadavg. Changed the call to procfs_write_nonpid_uptime to procfs_read_nonpid_uptime. Changed the call to procfs_write_nonpid_version to procfs_read_nonpid_version. netfs.c: (netfs_attempt_read): Changed the call from procfs_write_files_contents to procfs_read_files_contents. --- netfs.c | 2 +- procfs_nonpid_files.c | 10 +++++----- procfs_pid_files.c | 46 +++++++++++++++++++++++----------------------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/netfs.c b/netfs.c index 31ffe1b5..7e00e4d4 100644 --- a/netfs.c +++ b/netfs.c @@ -435,7 +435,7 @@ error_t netfs_attempt_read (struct iouser *cred, struct node *node, if (! err) { if (*len > 0) - procfs_write_files_contents (node, offset, + procfs_read_files_contents (node, offset, len, data); if (*len > 0) if (offset >= *len) diff --git a/procfs_nonpid_files.c b/procfs_nonpid_files.c index 9cb0c57a..15c09190 100644 --- a/procfs_nonpid_files.c +++ b/procfs_nonpid_files.c @@ -263,7 +263,7 @@ error_t get_total_times (struct timeval *total_user_time, return err; } -error_t procfs_write_nonpid_stat (struct dir_entry *dir_entry, +error_t procfs_read_nonpid_stat (struct dir_entry *dir_entry, off_t offset, size_t *len, void *data) { char *stat_data; @@ -387,7 +387,7 @@ SWAP_FIELD (get_swap_page_size, def_pager_info.dpi_page_size) SWAP_FIELD (get_swap_active, (def_pager_info.dpi_total_space - def_pager_info.dpi_free_space)) -error_t procfs_write_nonpid_meminfo (struct dir_entry *dir_entry, +error_t procfs_read_nonpid_meminfo (struct dir_entry *dir_entry, off_t offset, size_t *len, void *data) { char *meminfo_data; @@ -427,7 +427,7 @@ error_t procfs_write_nonpid_meminfo (struct dir_entry *dir_entry, return err; } -error_t procfs_write_nonpid_loadavg (struct dir_entry *dir_entry, +error_t procfs_read_nonpid_loadavg (struct dir_entry *dir_entry, off_t offset, size_t *len, void *data) { char *loadavg_data; @@ -455,7 +455,7 @@ error_t procfs_write_nonpid_loadavg (struct dir_entry *dir_entry, return err; } -error_t procfs_write_nonpid_uptime (struct dir_entry *dir_entry, +error_t procfs_read_nonpid_uptime (struct dir_entry *dir_entry, off_t offset, size_t *len, void *data) { char *uptime_data; @@ -497,7 +497,7 @@ error_t procfs_write_nonpid_uptime (struct dir_entry *dir_entry, return err; } -error_t procfs_write_nonpid_version (struct dir_entry *dir_entry, +error_t procfs_read_nonpid_version (struct dir_entry *dir_entry, off_t offset, size_t *len, void *data) { char *version_data; diff --git a/procfs_pid_files.c b/procfs_pid_files.c index 3ad77340..ed3a3bdc 100644 --- a/procfs_pid_files.c +++ b/procfs_pid_files.c @@ -367,12 +367,12 @@ error_t get_stat_data (pid_t pid, return err; } -/* Writes required process information to stat file +/* Reads required process information from stat file within the directory represented by pid. Return the data in DATA and actual length to be written in LEN. */ error_t -procfs_write_stat_file (struct procfs_dir_entry *dir_entry, +procfs_read_stat_file (struct procfs_dir_entry *dir_entry, off_t offset, size_t *len, void *data) { error_t err; @@ -417,12 +417,12 @@ procfs_write_stat_file (struct procfs_dir_entry *dir_entry, return err; } -/* Writes required process's command line information - to cmline file within the directory represented by - pid. Return the data in DATA and actual length to - be written in LEN. */ +/* Reads required process's command line information + from cmline file within the directory represented + by pid. Return the data in DATA and actual length + to be written in LEN. */ error_t -procfs_write_cmdline_file (struct procfs_dir_entry *dir_entry, +procfs_read_cmdline_file (struct procfs_dir_entry *dir_entry, off_t offset, size_t *len, void *data) { char *cmdline_data; @@ -445,12 +445,12 @@ procfs_write_cmdline_file (struct procfs_dir_entry *dir_entry, return err; } -/* Writes required process's information that is represented by - stat and statm in a human readable format to status file +/* Reads required process's information that is represented by + stat and statm in a human readable format from status file within the directory represented by pid. Return the data in DATA and actual length to be written in LEN. */ error_t -procfs_write_status_file (struct procfs_dir_entry *dir_entry, +procfs_read_status_file (struct procfs_dir_entry *dir_entry, off_t offset, size_t *len, void *data) { char *status_data; @@ -478,12 +478,12 @@ procfs_write_status_file (struct procfs_dir_entry *dir_entry, return err; } -/* Writes required process information to statm file +/* Reads required process information from statm file within the directory represented by pid. Return the data in DATA and actual length to be written in LEN. */ error_t -procfs_write_statm_file (struct procfs_dir_entry *dir_entry, +procfs_read_statm_file (struct procfs_dir_entry *dir_entry, off_t offset, size_t *len, void *data) { char *statm_data; @@ -514,60 +514,60 @@ procfs_write_statm_file (struct procfs_dir_entry *dir_entry, return err; } -/* Writes required process information to each of files +/* Reads required process information from each of files within directory represented by pid, for files specified by NODE. Return the data in DATA and actual length of data in LEN. */ error_t -procfs_write_files_contents (struct node *node, +procfs_read_files_contents (struct node *node, off_t offset, size_t *len, void *data) { error_t err; if (! strcmp (node->nn->dir_entry->name, "stat")) if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_write_nonpid_stat (node->nn->dir_entry, + err = procfs_read_nonpid_stat (node->nn->dir_entry, offset, len, data); else - err = procfs_write_stat_file (node->nn->dir_entry, + err = procfs_read_stat_file (node->nn->dir_entry, offset, len, data); if (! strcmp (node->nn->dir_entry->name, "cmdline")) - err = procfs_write_cmdline_file (node->nn->dir_entry, + err = procfs_read_cmdline_file (node->nn->dir_entry, offset, len, data); if (! strcmp (node->nn->dir_entry->name, "status")) - err = procfs_write_status_file (node->nn->dir_entry, + err = procfs_read_status_file (node->nn->dir_entry, offset, len, data); if (! strcmp (node->nn->dir_entry->name, "statm")) - err = procfs_write_statm_file (node->nn->dir_entry, + err = procfs_read_statm_file (node->nn->dir_entry, offset, len, data); if (! strcmp (node->nn->dir_entry->name, "meminfo")) if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_write_nonpid_meminfo (node->nn->dir_entry, + err = procfs_read_nonpid_meminfo (node->nn->dir_entry, offset, len, data); else err = ENOENT; if (! strcmp (node->nn->dir_entry->name, "loadavg")) if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_write_nonpid_loadavg (node->nn->dir_entry, + err = procfs_read_nonpid_loadavg (node->nn->dir_entry, offset, len, data); else err = ENOENT; if (! strcmp (node->nn->dir_entry->name, "uptime")) if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_write_nonpid_uptime (node->nn->dir_entry, + err = procfs_read_nonpid_uptime (node->nn->dir_entry, offset, len, data); else err = ENOENT; if (! strcmp (node->nn->dir_entry->name, "version")) if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_write_nonpid_version (node->nn->dir_entry, + err = procfs_read_nonpid_version (node->nn->dir_entry, offset, len, data); else err = ENOENT; -- cgit v1.2.3 From 19953dc4ba760988f611d03dffc4b5549077d2fc Mon Sep 17 00:00:00 2001 From: "Madhusudan.C.S" Date: Sat, 30 Aug 2008 22:20:00 +0200 Subject: 2008-08-29 Madhusudan.C.S * AUTHORS: File removed. * COPYING: Likewise. * README: Likewise. --- AUTHORS | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 AUTHORS diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index 622b6488..00000000 --- a/AUTHORS +++ /dev/null @@ -1,10 +0,0 @@ -Written By -~~~~~~~~~~ - -Madhusudan.C.S - - -Mentored By -~~~~~~~~~~~ - -Olaf Buddenhagen -- cgit v1.2.3 From 391c62031b4fe6fa0a2f031d9f6dcf4dcd04e5ce Mon Sep 17 00:00:00 2001 From: "Madhusudan.C.S" Date: Sat, 30 Aug 2008 22:48:00 +0200 Subject: 2008-08-30 Madhusudan.C.S * procfs_dir.c: (procfs_dir_create): Assign newly created directory to its pointer in netnode. (procfs_dir_remove): Removed function. (free_entry): New function. (ordered_unlink): Likewise. (delete): Likewise. (sweep): Likewise. (procfs_dir_entries_remove): Likewise. (is_in_pid_list): Removed call to make_dir_invalid (). (procfs_fill_root_dir): struct stat *stat -> struct stat stat. Add Read and Execute permissions to all in stat.st_mode. Set stat.st_nlink to 1. Set stat.st_size to 0. Add struct proc_stat *ps definition. Set struct proc_stat data from _proc_stat_create () function and set stat.st_uid and stat.st_gid from the data in that structure. * procfs_pid_files.c: (update_pid_entries): Add Read permissions to all in stat->st_mode. --- procfs_dir.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++------- procfs_pid_files.c | 2 +- 2 files changed, 105 insertions(+), 16 deletions(-) diff --git a/procfs_dir.c b/procfs_dir.c index b9b0410e..f76e6a4b 100644 --- a/procfs_dir.c +++ b/procfs_dir.c @@ -77,6 +77,9 @@ error_t procfs_dir_create (struct procfs *fs, struct node *node, *dir = new; + if (fs->root != 0) + node->nn->dir = new; + return 0; } @@ -343,14 +346,50 @@ procfs_dir_null_lookup (struct procfs_dir *dir, struct node **node) return err; } -/* Remove the specified DIR and free all its allocated - storage. */ -void procfs_dir_remove (struct procfs_dir *dir) +/* Free the directory entry DIR_ENTRY and all resources it consumes. */ +void +free_entry (struct procfs_dir_entry *dir_entry) { - /* STUB */ + assert (! dir_entry->self_p); /* We should only free deleted nodes. */ + free (dir_entry->name); + if (dir_entry->symlink_target) + free (dir_entry->symlink_target); + free (dir_entry->node->nn->dir); + free (dir_entry->node->nn); + free (dir_entry->node); + free (dir_entry); +} + +/* Remove DIR_ENTRY from its position in the ordered_next chain. */ +static void +ordered_unlink (struct procfs_dir_entry *dir_entry) +{ + if (dir_entry->ordered_self_p) + *dir_entry->ordered_self_p = dir_entry->ordered_next; + if (dir_entry->ordered_next) + dir_entry->ordered_next->self_p = dir_entry->ordered_self_p; +} + +/* Delete DIR_ENTRY from its directory, freeing any resources it holds. */ +static void +delete (struct procfs_dir_entry *dir_entry, struct procfs_dir *dir) +{ + dir->num_entries--; - return 0; + /* Take out of the hash chain. */ + if (dir_entry->self_p) + *dir_entry->self_p = dir_entry->next; + if (dir_entry->next) + dir_entry->next->self_p = dir_entry->self_p; + + /* Take out of the directory ordered list. */ + ordered_unlink (dir_entry); + + /* If there's a node attached, we'll delete the entry whenever it goes + away, otherwise, just delete it now. */ + if (! dir_entry->node) + free_entry (dir_entry); } /* Make all the directory entries invalid */ @@ -373,6 +412,41 @@ make_dir_invalid (struct procfs_dir *dir) } } +/* Delete any entries in DIR which don't have their valid bit set. */ +static void +sweep (struct procfs_dir *dir) +{ + size_t len = dir->htable_len, i; + struct procfs_dir_entry **htable = dir->htable, *dir_entry; + + for (i = 0; i < len; i++) + { + dir_entry = htable[i]; + while (dir_entry) + { + if (!dir_entry->valid && !dir_entry->noent && dir->num_entries) + delete (dir_entry, dir); + dir_entry = dir_entry->next; + } + if (htable[i]) + { + free (htable[i]); + htable[i] = 0; + } + + } + +} + +/* Remove the specified DIR and free all its allocated + storage. */ +void procfs_dir_entries_remove (struct procfs_dir *dir) +{ + /* Free all entries. */ + make_dir_invalid (dir); + sweep (dir); +} + /* Checks if the DIR name is in list of Active pids. */ int is_in_pid_list (struct procfs_dir *dir) @@ -417,7 +491,6 @@ error_t procfs_dir_refresh (struct procfs_dir *dir, int isroot) error_t err; int is_parent_pid; struct node *node; - make_dir_invalid (dir); struct timeval tv; maptime_read (procfs_maptime, &tv); @@ -513,14 +586,18 @@ procfs_fill_root_dir(struct procfs_dir *dir, time_t timestamp) char *data; pid_t *pids; int pidslen; - struct stat *stat = (struct stat *) malloc (sizeof (struct stat)); - stat->st_mode = S_IFDIR; + struct stat stat; + stat.st_mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | + S_IROTH | S_IXOTH; + stat.st_nlink = 1; + stat.st_size = 0; int count; char *dir_name_pid; struct node *node; struct procfs_dir *new_dir; struct procfs_dir_entry *dir_entry; + struct proc_stat *ps; pids = NULL; pidslen = 0; @@ -540,13 +617,25 @@ procfs_fill_root_dir(struct procfs_dir *dir, time_t timestamp) if (! node || ! new_dir ) return ENOMEM; #endif - dir_entry = update_entries_list (dir, dir_name_pid, - stat, timestamp, NULL); - err = procfs_create_node (dir_entry, dir_name_pid, &node); - - procfs_dir_create (dir->fs, node, - dir_name_pid, &new_dir); - free(dir_name_pid); + err = _proc_stat_create (pids[count], ps_context, &ps); + if (! err) + { + err = set_field_value (ps, PSTAT_PROC_INFO); + if (! err) + { + stat.st_uid = proc_stat_proc_info (ps)->owner; + stat.st_gid = proc_stat_proc_info (ps)->pgrp; + + dir_entry = update_entries_list (dir, dir_name_pid, + &stat, timestamp, NULL); + err = procfs_create_node (dir_entry, dir_name_pid, &node); + + procfs_dir_create (dir->fs, node, + dir_name_pid, &new_dir); + free(dir_name_pid); + _proc_stat_free (ps); + } + } } } diff --git a/procfs_pid_files.c b/procfs_pid_files.c index ed3a3bdc..46861531 100644 --- a/procfs_pid_files.c +++ b/procfs_pid_files.c @@ -48,7 +48,7 @@ update_pid_entries (struct procfs_dir *dir, const char *name, { struct procfs_dir_entry *dir_entry; struct stat *stat = (struct stat *) malloc (sizeof (struct stat)); - stat->st_mode = S_IFREG; + stat->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; dir_entry = update_entries_list (dir, name, stat, timestamp, symlink_target); -- cgit v1.2.3 From db2336ab8d2c9e0f6ddf057918a3a19d5a31de97 Mon Sep 17 00:00:00 2001 From: "Madhusudan.C.S" Date: Tue, 2 Sep 2008 00:33:00 +0200 Subject: 2008-09-02 Madhusudan.C.S * netfs.c: (netfs_get_dirents): Add call to procfs_dir_entries_remove(). --- netfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/netfs.c b/netfs.c index 7e00e4d4..4f6fd5ce 100644 --- a/netfs.c +++ b/netfs.c @@ -278,6 +278,7 @@ netfs_get_dirents (struct iouser *cred, struct node *dir, return ENOTDIR; } + procfs_dir_entries_remove (dir->nn->dir); return err; } -- cgit v1.2.3 From 2f4aea7d25b7aeca6ee36126a375644acfab3cee Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Fri, 12 Dec 2008 01:48:00 +0100 Subject: 2008-12-12 Samuel Thibault * procfs_nonpid_files.c (procfs_read_nonpid_meminfo): Divide by 1024 value returned by get_swap_size and get_swap_free to get kilobytes. --- procfs_nonpid_files.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/procfs_nonpid_files.c b/procfs_nonpid_files.c index 15c09190..d8b3a7d1 100644 --- a/procfs_nonpid_files.c +++ b/procfs_nonpid_files.c @@ -417,7 +417,7 @@ error_t procfs_read_nonpid_meminfo (struct dir_entry *dir_entry, mem_size, (PAGES_TO_BYTES(vmstats.free_count)) / 1024 , 0, 0, 0, (PAGES_TO_BYTES(vmstats.active_count)) / 1024, (PAGES_TO_BYTES(vmstats.inactive_count)) / 1024, 0, 0, 0, 0, - get_swap_size (), get_swap_free ()) == -1) + get_swap_size () / 1024, get_swap_free () / 1024) == -1) return errno; memcpy (data, meminfo_data, strlen(meminfo_data)); -- cgit v1.2.3 From bb60526834227fddb97e14bd80fccc405932e352 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Mon, 31 May 2010 02:23:00 +0200 Subject: 2010-05-31 Samuel Thibault * procfs_nonpid_files.c (procfs_read_nonpid_meminfo): Print swap sizes using %llu. --- procfs_nonpid_files.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/procfs_nonpid_files.c b/procfs_nonpid_files.c index d8b3a7d1..2c1209ee 100644 --- a/procfs_nonpid_files.c +++ b/procfs_nonpid_files.c @@ -412,8 +412,8 @@ error_t procfs_read_nonpid_meminfo (struct dir_entry *dir_entry, "HighFree:\t%lu kB\n" "LowTotal:\t%lu kB\n" "LowFree:\t%lu kB\n" - "SwapTotal:\t%lu kB\n" - "SwapFree:\t%lu kB\n", + "SwapTotal:\t%llu kB\n" + "SwapFree:\t%llu kB\n", mem_size, (PAGES_TO_BYTES(vmstats.free_count)) / 1024 , 0, 0, 0, (PAGES_TO_BYTES(vmstats.active_count)) / 1024, (PAGES_TO_BYTES(vmstats.inactive_count)) / 1024, 0, 0, 0, 0, -- cgit v1.2.3 From c3b69fde7feae1954c7f1bd64af630bb26cc8fdc Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 1 Aug 2010 01:50:21 +0200 Subject: Move files to procfs to merge along hurd --- bootstrap.c | 95 ------- netfs.c | 467 ------------------------------ node.c | 195 ------------- procfs.c | 149 ---------- procfs.h | 220 -------------- procfs/ChangeLog | 177 ++++++++++++ procfs/Makefile | 30 ++ procfs/bootstrap.c | 95 +++++++ procfs/netfs.c | 467 ++++++++++++++++++++++++++++++ procfs/node.c | 195 +++++++++++++ procfs/procfs.c | 149 ++++++++++ procfs/procfs.h | 220 ++++++++++++++ procfs/procfs_dir.c | 664 +++++++++++++++++++++++++++++++++++++++++++ procfs/procfs_nonpid_files.c | 514 +++++++++++++++++++++++++++++++++ procfs/procfs_pid.h | 88 ++++++ procfs/procfs_pid_files.c | 576 +++++++++++++++++++++++++++++++++++++ procfs_dir.c | 664 ------------------------------------------- procfs_nonpid_files.c | 514 --------------------------------- procfs_pid.h | 88 ------ procfs_pid_files.c | 576 ------------------------------------- 20 files changed, 3175 insertions(+), 2968 deletions(-) delete mode 100644 bootstrap.c delete mode 100644 netfs.c delete mode 100644 node.c delete mode 100644 procfs.c delete mode 100644 procfs.h create mode 100644 procfs/ChangeLog create mode 100644 procfs/Makefile create mode 100644 procfs/bootstrap.c create mode 100644 procfs/netfs.c create mode 100644 procfs/node.c create mode 100644 procfs/procfs.c create mode 100644 procfs/procfs.h create mode 100644 procfs/procfs_dir.c create mode 100644 procfs/procfs_nonpid_files.c create mode 100644 procfs/procfs_pid.h create mode 100644 procfs/procfs_pid_files.c delete mode 100644 procfs_dir.c delete mode 100644 procfs_nonpid_files.c delete mode 100644 procfs_pid.h delete mode 100644 procfs_pid_files.c diff --git a/bootstrap.c b/bootstrap.c deleted file mode 100644 index 73d31f00..00000000 --- a/bootstrap.c +++ /dev/null @@ -1,95 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - bootstrap.c -- This file is functions for starting up - and initializers for the procfs translator - defined in procfs.h - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You 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 -#include -#include - -#include "procfs.h" - -struct ps_context *ps_context; - -/* This function is used to initialize the whole translator, can be - effect called as bootstrapping the translator. */ -error_t procfs_init () -{ - error_t err; - - err = ps_context_create (getproc (), &ps_context); - - return err; -} - -/* Create a new procfs filesystem. */ -error_t procfs_create (char *procfs_root, int fsid, - struct procfs **fs) -{ - error_t err; - /* This is the enclosing directory for this filesystem's - root node */ - struct procfs_dir *topmost_root_dir; - - /* And also a topmost-root node, just used for locking - TOPMOST_ROOT_DIR. */ - struct node *topmost_root; - - /* The new node for the filesystem's root. */ - struct procfs *new = malloc (sizeof (struct procfs)); - - if (! new) - return ENOMEM; - - new->fsid = fsid; - new->next_inode = 2; - - hurd_ihash_init (&new->inode_mappings, - offsetof (struct procfs_dir_entry, inode_locp)); - spin_lock_init (&new->inode_mappings_lock); - - topmost_root = netfs_make_node (0); - if (! topmost_root) - err = ENOMEM; - else - { - err = procfs_dir_create (new, topmost_root, procfs_root, - &topmost_root_dir); - if (! err) - { - /* ADDITIONAL BOOTSTRAPPING OF THE ROOT NODE */ - err = procfs_dir_null_lookup (topmost_root_dir, &new->root); - } - } - - if (err) - { - hurd_ihash_destroy (&new->inode_mappings); - free (new); - } - else - *fs = new; - - return err; -} - diff --git a/netfs.c b/netfs.c deleted file mode 100644 index 4f6fd5ce..00000000 --- a/netfs.c +++ /dev/null @@ -1,467 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You 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 -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "procfs.h" - -/* Trivial definitions. */ - -/* 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) -{ - return procfs_refresh_node (node); -} - -/* 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) -{ - return 0; -} - -/* 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) -{ - return EROFS; -} - -/* Attempt to remove directory named NAME in DIR for USER. */ -error_t netfs_attempt_rmdir (struct iouser *user, - struct node *dir, char *name) -{ - return EROFS; -} - -/* 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) -{ - return EROFS; -} - -/* 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) -{ - *node = NULL; - mutex_unlock (&dir->lock); - return EROFS; -} - -/* 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 = procfs_refresh_node (node); - if (!err && (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); - 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) -{ - error_t err = procfs_refresh_node (node); - int flags = TOUCH_CTIME; - - if (! err) - err = fshelp_isowner (&node->nn_stat, cred); - - if (! err) - { - if (atime) - node->nn_stat.st_atim = *atime; - else - flags |= TOUCH_ATIME; - - if (mtime) - node->nn_stat.st_mtim = *mtime; - else - flags |= TOUCH_MTIME; - - fshelp_touch (&node->nn_stat, flags, procfs_maptime); - } - - return err; -} - -/* 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) -{ - error_t err = procfs_refresh_node (node); - - if (! err) - { - *types = 0; - if (fshelp_access (&node->nn_stat, S_IREAD, cred) == 0) - *types |= O_READ; - if (fshelp_access (&node->nn_stat, S_IWRITE, cred) == 0) - *types |= O_WRITE; - if (fshelp_access (&node->nn_stat, S_IEXEC, cred) == 0) - *types |= O_EXEC; - } - - return err; -} - -/* The granularity with which we allocate space to return our result. */ -#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)) - - - -/* Fetch a directory */ -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 = procfs_refresh_node (dir); - struct procfs_dir_entry *dir_entry; - - if (! err) - { - if (dir->nn->dir) - { - if (! procfs_dir_refresh (dir->nn->dir, dir == dir->nn->fs->root)) - { - for (dir_entry = dir->nn->dir->ordered; first_entry > 0 && - dir_entry; first_entry--, - dir_entry = dir_entry->ordered_next); - if (! dir_entry ) - max_entries = 0; - - if (max_entries != 0) - { - size_t size = 0; - char *p; - int count = 0; - - - if (max_data_len == 0) - size = DIRENTS_CHUNK_SIZE; - else if (max_data_len > DIRENTS_CHUNK_SIZE) - size = DIRENTS_CHUNK_SIZE; - else - size = max_data_len; - - *data = mmap (0, size, PROT_READ|PROT_WRITE, - MAP_ANON, 0, 0); - - err = ((void *) *data == (void *) -1) ? errno : 0; - - if (! err) - { - p = *data; - - /* This gets all the actual entries present. */ - - while ((max_entries == -1 || count < max_entries) && dir_entry) - { - struct dirent hdr; - size_t name_len = strlen (dir_entry->name); - size_t sz = DIRENT_LEN (name_len); - int entry_type = IFTODT (dir_entry->stat.st_mode); - - if ((p - *data) + sz > size) - { - if (max_data_len > 0) - break; - else /* The Buffer Size must be increased. */ - { - vm_address_t extension = (vm_address_t)(*data + size); - err = vm_allocate (mach_task_self (), &extension, - DIRENTS_CHUNK_SIZE, 0); - - if (err) - break; - - size += DIRENTS_CHUNK_SIZE; - } - } - - hdr.d_namlen = name_len; - hdr.d_fileno = dir_entry->stat.st_ino; - hdr.d_reclen = sz; - hdr.d_type = entry_type; - - memcpy (p, &hdr, DIRENT_NAME_OFFS); - strcpy (p + DIRENT_NAME_OFFS, dir_entry->name); - - p += sz; - - count++; - dir_entry = dir_entry->ordered_next; - } - - if (err) - munmap (*data, size); - else - { - vm_address_t alloc_end = (vm_address_t)(*data + size); - vm_address_t real_end = round_page (p); - if (alloc_end > real_end) - munmap ((caddr_t) real_end, alloc_end - real_end); - *data_len = p - *data; - *data_entries = count; - } - } - } - else - { - *data_len = 0; - *data_entries = 0; - } - } - } - else - return ENOTDIR; - } - - procfs_dir_entries_remove (dir->nn->dir); - 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 = procfs_refresh_node (dir); - - if (! err) - err = procfs_dir_lookup (dir->nn->dir, name, node); - - return err; -} - -/* Delete NAME in DIR for USER. */ -error_t netfs_attempt_unlink (struct iouser *user, struct node *dir, - char *name) -{ - return EROFS; -} - -/* 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) -{ - return EROFS; -} - -/* 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) -{ - return EROFS; -} - -/* 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) -{ - return EROFS; -} - -/* 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) -{ - return EROFS; -} - -/* 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) -{ - return EROFS; -} - -/* 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) -{ - return EROFS; -} - - -/* 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) -{ - return EROFS; -} - -/* 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) -{ - return EROFS; -} - -/* This should attempt to fetch filesystem status information for the remote - filesystem, for the user CRED. */ -error_t -netfs_attempt_statfs (struct iouser *cred, struct node *node, - struct statfs *st) -{ - bzero (st, sizeof *st); - st->f_type = PROCFILESYSTEM; - st->f_fsid = getpid (); - return 0; -} - -/* 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) -{ - 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) -{ - return EROFS; -} - -/* 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) -{ - *node = NULL; - mutex_unlock (&dir->lock); - return EROFS; -} - -/* Read the contents of NODE (a symlink), for USER, into BUF. */ -error_t netfs_attempt_readlink (struct iouser *user, struct node *node, char *buf) -{ - error_t err = procfs_refresh_node (node); - if (! err) - { - struct procfs_dir_entry *dir_entry = node->nn->dir_entry; - if (dir_entry) - bcopy (dir_entry->symlink_target, buf, node->nn_stat.st_size); - else - err = EINVAL; - } - return err; -} - -/* 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) -{ - error_t err; - err = procfs_refresh_node (node); - - if (! err) - { - if (*len > 0) - procfs_read_files_contents (node, offset, - len, data); - if (*len > 0) - if (offset >= *len) - *len = 0; - } - - return err; -} - -/* Write to the file NODE for user CRED starting at OFFSET 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) -{ - return EROFS; -} - -/* The user must define this function. Node NP is all done; free - all its associated storage. */ -void netfs_node_norefs (struct node *np) -{ - mutex_lock (&np->lock); - *np->prevp = np->next; - np->next->prevp = np->prevp; - procfs_remove_node (np); -} - diff --git a/node.c b/node.c deleted file mode 100644 index f11fa7b0..00000000 --- a/node.c +++ /dev/null @@ -1,195 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - node.c -- This file contains function defintions to handle - node creation and destruction. - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You 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 -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "procfs.h" - -/* Return a new node in NODE, with a name NAME, and return the - new node with a single reference in NODE. */ -error_t procfs_create_node (struct procfs_dir_entry *dir_entry, - const char *fs_path, struct node **node) -{ - struct node *new; - struct netnode *nn = malloc (sizeof (struct netnode)); - error_t err; - - if (! nn) - return ENOMEM; - if (! fs_path) - fs_path = strdup (""); - nn->fs = dir_entry->dir->fs; - nn->dir_entry = dir_entry; - nn->dir = NULL; - nn->fs_path = strdup (fs_path); - - new = netfs_make_node (nn); - if (! new) - { - free (nn); - return ENOMEM; - } - - fshelp_touch (&new->nn_stat, TOUCH_ATIME|TOUCH_MTIME|TOUCH_CTIME, - procfs_maptime); - - spin_lock (&nn->fs->inode_mappings_lock); - err = hurd_ihash_add (&nn->fs->inode_mappings, dir_entry->stat.st_ino, dir_entry); - spin_unlock (&nn->fs->inode_mappings_lock); - - if (err) - { - free (nn); - free (new); - return err; - } - - dir_entry->node = new; - *node = new; - - return 0; -} - -/* Update the directory entry for NAME to reflect ST and SYMLINK_TARGET. - True is returned if successful, or false if there was a memory allocation - error. TIMESTAMP is used to record the time of this update. */ -static void -update_entry (struct procfs_dir_entry *dir_entry, const struct stat *st, - const char *symlink_target, time_t timestamp) -{ - ino_t ino; - struct procfs *fs = dir_entry->dir->fs; - - if (dir_entry->stat.st_ino) - ino = dir_entry->stat.st_ino; - else - ino = fs->next_inode++; - - dir_entry->name_timestamp = timestamp; - - if (st) - /* The ST and SYMLINK_TARGET parameters are only valid if ST isn't 0. */ - { - dir_entry->stat = *st; - dir_entry->stat_timestamp = timestamp; - - if (!dir_entry->symlink_target || !symlink_target - || strcmp (dir_entry->symlink_target, symlink_target) != 0) - { - if (dir_entry->symlink_target) - free (dir_entry->symlink_target); - dir_entry->symlink_target = symlink_target ? strdup (symlink_target) : 0; - } - } - - /* The st_ino field is always valid. */ - dir_entry->stat.st_ino = ino; - dir_entry->stat.st_fsid = fs->fsid; - dir_entry->stat.st_fstype = PROCFILESYSTEM; -} - -/* Refresh stat information for NODE */ -error_t procfs_refresh_node (struct node *node) -{ - struct netnode *nn = node->nn; - struct procfs_dir_entry *dir_entry = nn->dir_entry; - - if (! dir_entry) - /* This is a deleted node, don't attempt to do anything. */ - return 0; - else - { - error_t err = 0; - - struct timeval tv; - maptime_read (procfs_maptime, &tv); - - time_t timestamp = tv.tv_sec; - - struct procfs_dir *dir = dir_entry->dir; - - mutex_lock (&dir->node->lock); - - if (! dir_entry->self_p) - /* This is a deleted entry, just awaiting disposal; do so. */ - { -#if 0 - nn->dir_entry = 0; - free_entry (dir_entry); - return 0; -#endif - } - - else if (dir_entry->noent) - err = ENOENT; - else - { - if (*(dir_entry->name)) - { - err = procfs_dir_refresh (dir_entry->dir, - dir_entry->dir->node == dir_entry->dir->fs->root); - if (!err && dir_entry->noent) - err = ENOENT; - - if (err == ENOENT) - { - dir_entry->noent = 1; /* A negative entry. */ - dir_entry->name_timestamp = timestamp; - } - } - else - { - /* Refresh the root node with the old stat - information. */ - update_entry (dir_entry, &netfs_root_node->nn_stat, NULL, timestamp); - } - } - - node->nn_stat = dir_entry->stat; - node->nn_translated = S_ISLNK (dir_entry->stat.st_mode) ? S_IFLNK : 0; - if (!nn->dir && S_ISDIR (dir_entry->stat.st_mode)) - procfs_dir_create (nn->fs, node, nn->fs_path, &nn->dir); - - mutex_unlock (&dir->node->lock); - - return err; - } -} - -/* Remove NODE from its entry */ -error_t procfs_remove_node (struct node *node) -{ - - /* STUB */ - - return 0; -} diff --git a/procfs.c b/procfs.c deleted file mode 100644 index 1fd0d619..00000000 --- a/procfs.c +++ /dev/null @@ -1,149 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - procfs.c -- This file is the main file of the translator. - This has important definitions and initializes - the translator - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You 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 -#include -#include -#include - -#include -#include -#include -#include - -#include "procfs.h" - -/* Defines this Tanslator Name */ -char *netfs_server_name = PROCFS_SERVER_NAME; -char *netfs_server_version = PROCFS_SERVER_VERSION; -int netfs_maxsymlinks = 12; - -static const struct argp_child argp_children[] = - { - {&netfs_std_startup_argp, 0, NULL, 0}, - {0} - }; - - -const char *argp_program_version = "/proc pseudo-filesystem (" PROCFS_SERVER_NAME - ") " PROCFS_SERVER_VERSION "\n" -"Copyright (C) 2008 Free Software Foundation\n" -"This is free software; see the source for copying conditions. There is NO\n" -"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." -"\n"; - -static char *args_doc = "PROCFSROOT"; -static char *doc = "proc pseudo-filesystem for Hurd implemented as a translator. " -"This is still under very humble and initial stages of development.\n" -"Any Contribution or help is welcome. The code may not even compile"; - - -/* The Filesystem */ -struct procfs *procfs; - -/* The FILESYSTEM component of PROCFS_FS. */ -char *procfs_root = ""; - -volatile struct mapped_time_value *procfs_maptime; - -/* Startup options. */ -static const struct argp_option procfs_options[] = - { - { 0 } - }; - - -/* argp parser function for parsing single procfs command line options */ -static error_t -parse_procfs_opt (int key, char *arg, struct argp_state *state) -{ - switch (key) - { - case ARGP_KEY_ARG: - if (state->arg_num > 1) - argp_usage (state); - break; - - case ARGP_KEY_NO_ARGS: - argp_usage(state); - break; - - default: - return ARGP_ERR_UNKNOWN; - } -} - -/* Program entry point. */ -int -main (int argc, char **argv) -{ - error_t err; - mach_port_t bootstrap, underlying_node; - struct stat underlying_stat; - - struct argp argp = - { - procfs_options, parse_procfs_opt, - args_doc, doc, argp_children, - NULL, NULL - }; - - - /* Parse the command line arguments */ -// argp_parse (&argp, argc, argv, 0, 0, 0); - - task_get_bootstrap_port (mach_task_self (), &bootstrap); - - netfs_init (); - - if (maptime_map (0, 0, &procfs_maptime)) - { - perror (PROCFS_SERVER_NAME ": Cannot map time"); - return 1; - } - - procfs_init (); - - err = procfs_create (procfs_root, getpid (), &procfs); - if (err) - error (4, err, "%s", procfs_root); - - /* Create our root node */ - netfs_root_node = procfs->root; - - /* Start netfs activities */ - underlying_node = netfs_startup (bootstrap, 0); - if (io_stat (underlying_node, &underlying_stat)) - error (1, err, "cannot stat underling node"); - - /* Initialize stat information of the root node. */ - netfs_root_node->nn_stat = underlying_stat; - netfs_root_node->nn_stat.st_mode = - S_IFDIR | (underlying_stat.st_mode & ~S_IFMT & ~S_ITRANS); - - for (;;) - netfs_server_loop (); - return 1; -} diff --git a/procfs.h b/procfs.h deleted file mode 100644 index fa2fb7f7..00000000 --- a/procfs.h +++ /dev/null @@ -1,220 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - procfs.h -- This file is the main header file of this - translator. This has important header - definitions for constants and functions - used in the translator. - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You 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. - - A portion of the code in this file is based on ftpfs code - present in the hurd repositories copyrighted to FSF. The - Copyright notice from that file is given below. - - Copyright (C) 1997,98,2002 Free Software Foundation, Inc. - Written by Miles Bader - This file is part of the GNU Hurd. -*/ - -#ifndef __PROCFS_H__ -#define __PROCFS_H__ - -#define PROCFS_SERVER_NAME "procfs" -#define PROCFS_SERVER_VERSION "0.0.1" - -/* /proc Filesystem type. */ -#define PROCFILESYSTEM "procfs" - -#define NUMBER_OF_FILES_PER_PID 1 -#define JIFFY_ADJUST 100 -#define PAGES_TO_BYTES(pages) ((pages) * sysconf(_SC_PAGESIZE)) -#define BYTES_TO_PAGES(bytes) ((bytes) / sysconf(_SC_PAGESIZE)) - -#include -#include -#include -#include -#include -#include - -typedef unsigned long long jiffy_t; - -/* A single entry in a directory. */ -struct procfs_dir_entry -{ - char *name; /* Name of this entry */ - size_t hv; /* Hash value of NAME */ - - /* The active node referred to by this name (may be 0). - NETFS_NODE_REFCNT_LOCK should be held while frobbing this. */ - struct node *node; - - struct stat stat; - char *symlink_target; - time_t stat_timestamp; - - /* The directory to which this entry belongs. */ - struct procfs_dir *dir; - - /* Link to next entry in hash bucket, and address of previous entry's (or - hash table's) pointer to this entry. If the SELF_P field is 0, then - this is a deleted entry, awaiting final disposal. */ - struct procfs_dir_entry *next, **self_p; - - /* Next entry in 'directory order', or 0 if none known. */ - struct procfs_dir_entry *ordered_next, **ordered_self_p; - - /* When the presence/absence of this file was last checked. */ - time_t name_timestamp; - - hurd_ihash_locp_t inode_locp; /* Used for removing this entry */ - - int noent : 1; /* A negative lookup result. */ - int valid : 1; /* Marker for GC'ing. */ -}; - -/* A directory. */ -struct procfs_dir -{ - /* Number of entries in HTABLE. */ - size_t num_entries; - - /* The number of entries that have nodes attached. We keep an additional - reference to our node if there are any, to prevent it from going away. */ - size_t num_live_entries; - - /* Hash table of entries. */ - struct procfs_dir_entry **htable; - size_t htable_len; /* # of elements in HTABLE (not bytes). */ - - /* List of dir entries in 'directory order', in a linked list using the - ORDERED_NEXT and ORDERED_SELF_P fields in each entry. Not all entries - in HTABLE need be in this list. */ - struct procfs_dir_entry *ordered; - - /* The filesystem node that this is the directory for. */ - struct node *node; - - /* The filesystem this directory is in. */ - struct procfs *fs; - - /* The path to this directory in the filesystem. */ - const char *fs_path; - - time_t stat_timestamp; - time_t name_timestamp; - -}; - - -/* libnetfs node structure */ -struct netnode -{ - /* Name of this node */ - char *name; - - /* The path in the filesystem that corresponds - this node. */ - char *fs_path; - - /* The directory entry for this node. */ - struct procfs_dir_entry *dir_entry; - - /* The proc filesystem */ - struct procfs *fs; - - /* inode number, assigned to this netnode structure. */ - unsigned int inode_num; - - /* If this is a directory, the contents, or 0 if not fetched. */ - struct procfs_dir *dir; - - /* pointer to node structure, assigned to this node. */ - struct node *node; - - /* links to the previous and next nodes in the list */ - struct netnode *nextnode, *prevnode; - - /* link to parent netnode of this file or directory */ - struct netnode *parent; - - /* link to the first child netnode of this directory */ - struct netnode *child_first; -}; - -/* The actual procfs filesystem structure */ -struct procfs -{ - /* Root of the filesystem. */ - struct node *root; - - /* Inode numbers are assigned sequentially in order of creation. */ - ino_t next_inode; - int fsid; - - /* A hash table mapping inode numbers to directory entries. */ - struct hurd_ihash inode_mappings; - spin_lock_t inode_mappings_lock; -}; - -extern struct procfs *procfs; - -extern volatile struct mapped_time_value *procfs_maptime; - -extern struct ps_context *ps_context; - -/* Create a new procfs filesystem. */ -error_t procfs_create (char *procfs_root, int fsid, - struct procfs **fs); - -/* Initialize the procfs filesystem for use. */ -error_t procfs_init (); - -/* Refresh stat information for NODE */ -error_t procfs_refresh_node (struct node *node); - -/* Return a new node in NODE, with a name NAME, - and return the new node with a single - reference in NODE. */ -error_t procfs_create_node (struct procfs_dir_entry *dir_entry, - const char *fs_path, - struct node **node); - -/* Remove NODE from its entry */ -error_t procfs_remove_node (struct node *node); - -/* Return in DIR a new procfs directory, in the filesystem FS, - with node NODE and path PATH. */ -error_t procfs_dir_create (struct procfs *fs, struct node *node, - const char *path, struct procfs_dir **dir); - -/* Remove the specified DIR and free all its allocated - storage. */ -void procfs_dir_remove (struct procfs_dir *dir); - -/* Refresh DIR. */ -error_t procfs_dir_refresh (struct procfs_dir *dir, int isroot); - -/* Lookup NAME in DIR, returning its entry, or an error. - *NODE will contain the result node, locked, and with - an additional reference, or 0 if an error occurs. */ -error_t procfs_dir_lookup (struct procfs_dir *dir, const char *name, - struct node **node); - -#endif /* __PROCFS_H__ */ diff --git a/procfs/ChangeLog b/procfs/ChangeLog new file mode 100644 index 00000000..47cbeaf2 --- /dev/null +++ b/procfs/ChangeLog @@ -0,0 +1,177 @@ +2010-05-31 Samuel Thibault + + * procfs_nonpid_files.c (procfs_read_nonpid_meminfo): Print swap sizes + using %llu. + +2008-12-12 Samuel Thibault + + * procfs_nonpid_files.c (procfs_read_nonpid_meminfo): Divide by + 1024 value returned by get_swap_size and get_swap_free to get + kilobytes. + +2008-09-02 Madhusudan.C.S + + * netfs.c: (netfs_get_dirents): Add call to + procfs_dir_entries_remove(). + +2008-08-30 Madhusudan.C.S + + * procfs_dir.c: (procfs_dir_create): Assign newly created directory to + its pointer in netnode. + (procfs_dir_remove): Removed function. + (free_entry): New function. + (ordered_unlink): Likewise. + (delete): Likewise. + (sweep): Likewise. + (procfs_dir_entries_remove): Likewise. + (is_in_pid_list): Removed call to make_dir_invalid (). + (procfs_fill_root_dir): struct stat *stat -> struct stat stat. + Add Read and Execute permissions to all in stat.st_mode. + Set stat.st_nlink to 1. + Set stat.st_size to 0. + Add struct proc_stat *ps definition. + Set struct proc_stat data from _proc_stat_create () function and + set stat.st_uid and stat.st_gid from the data in that structure. + * procfs_pid_files.c: (update_pid_entries): Add Read permissions + to all in stat->st_mode. + +2008-08-29 Madhusudan.C.S + + * AUTHORS: File removed. + * COPYING: Likewise. + * README: Likewise. + +2008-08-29 Madhusudan.C.S + + * Makefile: (Copyright): 1997, 2000 -> 2008. + (CC): Removed. + (CFLAGS): Removed. + (INCLUDES): Removed. + (all): Removed. + ($(target)): Removed. + (%.o): Removed. + (HURDLIBS): -lnetfs -> netfs, -lfshelp -> fshelp, + -liohelp -> iohelp, -lthreads -> threads, -lports -> ports, + -lihash -> ihash, -lps -> ps, -lshouldbeinlibc -> shouldbeinlibc. + (include): Add include ../Makeconf + +2008-08-18 Madhusudan.C.S + + * procfs_nonpid_files.c: (procfs_write_nonpid_stat): Changed to + procfs_read_nonpid_stat. + (procfs_write_nonpid_meminfo): Changed to procfs_read_nonpid_meminfo. + (procfs_write_nonpid_loadavg): Changed to procfs_read_nonpid_loadavg. + (procfs_write_nonpid_uptime): Changed to procfs_read_nonpid_uptime. + (procfs_write_nonpid_version):Changed to procfs_read_nonpid_version. + * procfs_pid_files.c: (procfs_write_stat_file): Changed to + procfs_read_stat_file. + Changed the comment correspondingly from Write to Read. + (procfs_write_cmdline_file ): Changed to procfs_read_cmdline_file. + Changed the comment correspondingly from Write to Read. + (procfs_write_status_file): Changed to procfs_read_status_file. + Changed the comment correspondingly from Write to Read. + (procfs_write_statm_file): Changed to procfs_read_statm_file. + Changed the comment correspondingly from Write to Read. + (procfs_write_files_contents): Changed to procfs_read_files_contents. + Changed the comment correspondingly from Write to Read. + Changed the call to procfs_write_nonpid_stat to procfs_read_nonpid_stat. + Changed the call to procfs_write_stat_file to procfs_read_stat_file. + Changed the call to procfs_write_cmdline_file to + procfs_read_cmdline_file. + Changed the call to procfs_write_status_file to + procfs_read_status_file. + Changed the call to procfs_write_statm_file to + procfs_read_statm_file. + Changed the call to procfs_write_nonpid_meminfo to + procfs_read_nonpid_meminfo. + Changed the call to procfs_write_nonpid_loadavg to + procfs_read_nonpid_loadavg. + Changed the call to procfs_write_nonpid_uptime to + procfs_read_nonpid_uptime. + Changed the call to procfs_write_nonpid_version to + procfs_read_nonpid_version. + netfs.c: (netfs_attempt_read): Changed the call from + procfs_write_files_contents to procfs_read_files_contents. + +2008-08-18 Madhusudan.C.S + + * README: Initial Documentation. + +2008-08-18 Madhusudan.C.S + + * procfs_nonpid_files.c: (get_uptime): Changed the parameter type from + double to struct timeval. + Changed the parameter name from uptime_secs to uptime. + Removed uptime variable. + Changed timersub to use the passed pointer instead of the local + variable. + Removed the calculation of uptime_secs. + (get_total_times): Changed the parameters type from double to struct + timeval. + Changed the parameters name from total_user_time_secs to + total_user_time and total_system_time_secs to total_system_time. + New variables total_user_time_tmp, total_system_time_tmp and tmpval + of type struct timeval. + Call timerclear to clear the tmp variables. + Remove calculation of times in seconds and do the same on struct + timeval variables throughout using the timeradd macro. + Assign values of temporary local variables to the pointers passed + as parameters. + (procfs_write_nonpid_stat): Replaced variables that hold time in + seconds with struct timeval type variables and jiffy_t type variables. + Argument to get_uptime changed from uptime_secs to uptime. + Arguments to get_total_times changed from total_user_time_secs to + total_user_time and total_system_time_secs to total_system_time. + Replace arithematic time subtraction with timersub macro. + Convert all the times in struct timeval type variables to jiffy_t type. + Changed the type casting for the asprintf arguments to be compatible + with jiffy_t type. + (procfs_write_nonpid_uptime): Replaced variables that hold time in + seconds with struct timeval type variables. + Argument to get_uptime changed from uptime_secs to uptime. + Arguments to get_total_times changed from total_user_time_secs to + total_user_time and total_system_time_secs to total_system_time. + Replace arithematic time subtraction with timersub macro. + Convert all the times in struct timeval type variables to seconds. + +2008-08-18 Madhusudan.C.S + + * procfs_nonpid_files.c: (procfs_write_nonpid_version): New function. + * procfs_pid_files.c: (procfs_write_files_contents): Add a check + to find if the read is requested for the version file and + corresponding a call to it. + +2008-08-14 Madhusudan.C.S + + * procfs.h: (jiffy_t): New typedef. + * procfs_pid.h: "procfs.h" is included. + (struct procfs_pid_files): Changed all the occurrences of time_t to + jiffy_t. + * procfs_pid_files.c: Removed "procfs.h". + (adjust_jiffy_time): Changed return type from time_t to jiffy_t. + Changed the type of jiffy_time variable from time_t to jiffy_t. + (get_live_threads_time): Changed the type of utime and stime from + time_t to jiffy_t. + (get_stat_data): Changed the type of utime and stime from time_t to + jiffy_t. + +2008-08-14 Madhusudan.C.S + + * ChangeLog: New file. + * AUTHORS: New file. + * COPYING: New file. + * README: New file. + * Makefile: New file. + * bootstrap.c: New file. + * netfs.c: New file. + * node.c: New file. + * procfs.c: New file. + * procfs.h: New file. + * procfs_dir.c: New file. + * procfs_nonpid_files.c: New file. + * procfs_pid.h: New file. + * procfs_pid_files.c: New file. + +2008-05-13 Madhusudan.C.S + + * /sources/hurd/procfs: New directory added to the repository. diff --git a/procfs/Makefile b/procfs/Makefile new file mode 100644 index 00000000..500a2371 --- /dev/null +++ b/procfs/Makefile @@ -0,0 +1,30 @@ +# Makefile - for procfs +# +# Copyright (C) 2008 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 := procfs +makemode := server + +target = procfs + +SRCS = procfs.c bootstrap.c netfs.c procfs_dir.c node.c procfs_pid_files.c procfs_nonpid_files.c +LCLHDRS = procfs.h procfs_pid.h + +OBJS = $(SRCS:.c=.o) +HURDLIBS = netfs fshelp iohelp threads ports ihash ps shouldbeinlibc + +include ../Makeconf diff --git a/procfs/bootstrap.c b/procfs/bootstrap.c new file mode 100644 index 00000000..73d31f00 --- /dev/null +++ b/procfs/bootstrap.c @@ -0,0 +1,95 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + bootstrap.c -- This file is functions for starting up + and initializers for the procfs translator + defined in procfs.h + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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 +#include +#include + +#include "procfs.h" + +struct ps_context *ps_context; + +/* This function is used to initialize the whole translator, can be + effect called as bootstrapping the translator. */ +error_t procfs_init () +{ + error_t err; + + err = ps_context_create (getproc (), &ps_context); + + return err; +} + +/* Create a new procfs filesystem. */ +error_t procfs_create (char *procfs_root, int fsid, + struct procfs **fs) +{ + error_t err; + /* This is the enclosing directory for this filesystem's + root node */ + struct procfs_dir *topmost_root_dir; + + /* And also a topmost-root node, just used for locking + TOPMOST_ROOT_DIR. */ + struct node *topmost_root; + + /* The new node for the filesystem's root. */ + struct procfs *new = malloc (sizeof (struct procfs)); + + if (! new) + return ENOMEM; + + new->fsid = fsid; + new->next_inode = 2; + + hurd_ihash_init (&new->inode_mappings, + offsetof (struct procfs_dir_entry, inode_locp)); + spin_lock_init (&new->inode_mappings_lock); + + topmost_root = netfs_make_node (0); + if (! topmost_root) + err = ENOMEM; + else + { + err = procfs_dir_create (new, topmost_root, procfs_root, + &topmost_root_dir); + if (! err) + { + /* ADDITIONAL BOOTSTRAPPING OF THE ROOT NODE */ + err = procfs_dir_null_lookup (topmost_root_dir, &new->root); + } + } + + if (err) + { + hurd_ihash_destroy (&new->inode_mappings); + free (new); + } + else + *fs = new; + + return err; +} + diff --git a/procfs/netfs.c b/procfs/netfs.c new file mode 100644 index 00000000..4f6fd5ce --- /dev/null +++ b/procfs/netfs.c @@ -0,0 +1,467 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "procfs.h" + +/* Trivial definitions. */ + +/* 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) +{ + return procfs_refresh_node (node); +} + +/* 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) +{ + return 0; +} + +/* 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) +{ + return EROFS; +} + +/* Attempt to remove directory named NAME in DIR for USER. */ +error_t netfs_attempt_rmdir (struct iouser *user, + struct node *dir, char *name) +{ + return EROFS; +} + +/* 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) +{ + return EROFS; +} + +/* 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) +{ + *node = NULL; + mutex_unlock (&dir->lock); + return EROFS; +} + +/* 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 = procfs_refresh_node (node); + if (!err && (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); + 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) +{ + error_t err = procfs_refresh_node (node); + int flags = TOUCH_CTIME; + + if (! err) + err = fshelp_isowner (&node->nn_stat, cred); + + if (! err) + { + if (atime) + node->nn_stat.st_atim = *atime; + else + flags |= TOUCH_ATIME; + + if (mtime) + node->nn_stat.st_mtim = *mtime; + else + flags |= TOUCH_MTIME; + + fshelp_touch (&node->nn_stat, flags, procfs_maptime); + } + + return err; +} + +/* 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) +{ + error_t err = procfs_refresh_node (node); + + if (! err) + { + *types = 0; + if (fshelp_access (&node->nn_stat, S_IREAD, cred) == 0) + *types |= O_READ; + if (fshelp_access (&node->nn_stat, S_IWRITE, cred) == 0) + *types |= O_WRITE; + if (fshelp_access (&node->nn_stat, S_IEXEC, cred) == 0) + *types |= O_EXEC; + } + + return err; +} + +/* The granularity with which we allocate space to return our result. */ +#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)) + + + +/* Fetch a directory */ +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 = procfs_refresh_node (dir); + struct procfs_dir_entry *dir_entry; + + if (! err) + { + if (dir->nn->dir) + { + if (! procfs_dir_refresh (dir->nn->dir, dir == dir->nn->fs->root)) + { + for (dir_entry = dir->nn->dir->ordered; first_entry > 0 && + dir_entry; first_entry--, + dir_entry = dir_entry->ordered_next); + if (! dir_entry ) + max_entries = 0; + + if (max_entries != 0) + { + size_t size = 0; + char *p; + int count = 0; + + + if (max_data_len == 0) + size = DIRENTS_CHUNK_SIZE; + else if (max_data_len > DIRENTS_CHUNK_SIZE) + size = DIRENTS_CHUNK_SIZE; + else + size = max_data_len; + + *data = mmap (0, size, PROT_READ|PROT_WRITE, + MAP_ANON, 0, 0); + + err = ((void *) *data == (void *) -1) ? errno : 0; + + if (! err) + { + p = *data; + + /* This gets all the actual entries present. */ + + while ((max_entries == -1 || count < max_entries) && dir_entry) + { + struct dirent hdr; + size_t name_len = strlen (dir_entry->name); + size_t sz = DIRENT_LEN (name_len); + int entry_type = IFTODT (dir_entry->stat.st_mode); + + if ((p - *data) + sz > size) + { + if (max_data_len > 0) + break; + else /* The Buffer Size must be increased. */ + { + vm_address_t extension = (vm_address_t)(*data + size); + err = vm_allocate (mach_task_self (), &extension, + DIRENTS_CHUNK_SIZE, 0); + + if (err) + break; + + size += DIRENTS_CHUNK_SIZE; + } + } + + hdr.d_namlen = name_len; + hdr.d_fileno = dir_entry->stat.st_ino; + hdr.d_reclen = sz; + hdr.d_type = entry_type; + + memcpy (p, &hdr, DIRENT_NAME_OFFS); + strcpy (p + DIRENT_NAME_OFFS, dir_entry->name); + + p += sz; + + count++; + dir_entry = dir_entry->ordered_next; + } + + if (err) + munmap (*data, size); + else + { + vm_address_t alloc_end = (vm_address_t)(*data + size); + vm_address_t real_end = round_page (p); + if (alloc_end > real_end) + munmap ((caddr_t) real_end, alloc_end - real_end); + *data_len = p - *data; + *data_entries = count; + } + } + } + else + { + *data_len = 0; + *data_entries = 0; + } + } + } + else + return ENOTDIR; + } + + procfs_dir_entries_remove (dir->nn->dir); + 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 = procfs_refresh_node (dir); + + if (! err) + err = procfs_dir_lookup (dir->nn->dir, name, node); + + return err; +} + +/* Delete NAME in DIR for USER. */ +error_t netfs_attempt_unlink (struct iouser *user, struct node *dir, + char *name) +{ + return EROFS; +} + +/* 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) +{ + return EROFS; +} + +/* 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) +{ + return EROFS; +} + +/* 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) +{ + return EROFS; +} + +/* 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) +{ + return EROFS; +} + +/* 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) +{ + return EROFS; +} + +/* 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) +{ + return EROFS; +} + + +/* 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) +{ + return EROFS; +} + +/* 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) +{ + return EROFS; +} + +/* This should attempt to fetch filesystem status information for the remote + filesystem, for the user CRED. */ +error_t +netfs_attempt_statfs (struct iouser *cred, struct node *node, + struct statfs *st) +{ + bzero (st, sizeof *st); + st->f_type = PROCFILESYSTEM; + st->f_fsid = getpid (); + return 0; +} + +/* 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) +{ + 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) +{ + return EROFS; +} + +/* 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) +{ + *node = NULL; + mutex_unlock (&dir->lock); + return EROFS; +} + +/* Read the contents of NODE (a symlink), for USER, into BUF. */ +error_t netfs_attempt_readlink (struct iouser *user, struct node *node, char *buf) +{ + error_t err = procfs_refresh_node (node); + if (! err) + { + struct procfs_dir_entry *dir_entry = node->nn->dir_entry; + if (dir_entry) + bcopy (dir_entry->symlink_target, buf, node->nn_stat.st_size); + else + err = EINVAL; + } + return err; +} + +/* 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) +{ + error_t err; + err = procfs_refresh_node (node); + + if (! err) + { + if (*len > 0) + procfs_read_files_contents (node, offset, + len, data); + if (*len > 0) + if (offset >= *len) + *len = 0; + } + + return err; +} + +/* Write to the file NODE for user CRED starting at OFFSET 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) +{ + return EROFS; +} + +/* The user must define this function. Node NP is all done; free + all its associated storage. */ +void netfs_node_norefs (struct node *np) +{ + mutex_lock (&np->lock); + *np->prevp = np->next; + np->next->prevp = np->prevp; + procfs_remove_node (np); +} + diff --git a/procfs/node.c b/procfs/node.c new file mode 100644 index 00000000..f11fa7b0 --- /dev/null +++ b/procfs/node.c @@ -0,0 +1,195 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + node.c -- This file contains function defintions to handle + node creation and destruction. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "procfs.h" + +/* Return a new node in NODE, with a name NAME, and return the + new node with a single reference in NODE. */ +error_t procfs_create_node (struct procfs_dir_entry *dir_entry, + const char *fs_path, struct node **node) +{ + struct node *new; + struct netnode *nn = malloc (sizeof (struct netnode)); + error_t err; + + if (! nn) + return ENOMEM; + if (! fs_path) + fs_path = strdup (""); + nn->fs = dir_entry->dir->fs; + nn->dir_entry = dir_entry; + nn->dir = NULL; + nn->fs_path = strdup (fs_path); + + new = netfs_make_node (nn); + if (! new) + { + free (nn); + return ENOMEM; + } + + fshelp_touch (&new->nn_stat, TOUCH_ATIME|TOUCH_MTIME|TOUCH_CTIME, + procfs_maptime); + + spin_lock (&nn->fs->inode_mappings_lock); + err = hurd_ihash_add (&nn->fs->inode_mappings, dir_entry->stat.st_ino, dir_entry); + spin_unlock (&nn->fs->inode_mappings_lock); + + if (err) + { + free (nn); + free (new); + return err; + } + + dir_entry->node = new; + *node = new; + + return 0; +} + +/* Update the directory entry for NAME to reflect ST and SYMLINK_TARGET. + True is returned if successful, or false if there was a memory allocation + error. TIMESTAMP is used to record the time of this update. */ +static void +update_entry (struct procfs_dir_entry *dir_entry, const struct stat *st, + const char *symlink_target, time_t timestamp) +{ + ino_t ino; + struct procfs *fs = dir_entry->dir->fs; + + if (dir_entry->stat.st_ino) + ino = dir_entry->stat.st_ino; + else + ino = fs->next_inode++; + + dir_entry->name_timestamp = timestamp; + + if (st) + /* The ST and SYMLINK_TARGET parameters are only valid if ST isn't 0. */ + { + dir_entry->stat = *st; + dir_entry->stat_timestamp = timestamp; + + if (!dir_entry->symlink_target || !symlink_target + || strcmp (dir_entry->symlink_target, symlink_target) != 0) + { + if (dir_entry->symlink_target) + free (dir_entry->symlink_target); + dir_entry->symlink_target = symlink_target ? strdup (symlink_target) : 0; + } + } + + /* The st_ino field is always valid. */ + dir_entry->stat.st_ino = ino; + dir_entry->stat.st_fsid = fs->fsid; + dir_entry->stat.st_fstype = PROCFILESYSTEM; +} + +/* Refresh stat information for NODE */ +error_t procfs_refresh_node (struct node *node) +{ + struct netnode *nn = node->nn; + struct procfs_dir_entry *dir_entry = nn->dir_entry; + + if (! dir_entry) + /* This is a deleted node, don't attempt to do anything. */ + return 0; + else + { + error_t err = 0; + + struct timeval tv; + maptime_read (procfs_maptime, &tv); + + time_t timestamp = tv.tv_sec; + + struct procfs_dir *dir = dir_entry->dir; + + mutex_lock (&dir->node->lock); + + if (! dir_entry->self_p) + /* This is a deleted entry, just awaiting disposal; do so. */ + { +#if 0 + nn->dir_entry = 0; + free_entry (dir_entry); + return 0; +#endif + } + + else if (dir_entry->noent) + err = ENOENT; + else + { + if (*(dir_entry->name)) + { + err = procfs_dir_refresh (dir_entry->dir, + dir_entry->dir->node == dir_entry->dir->fs->root); + if (!err && dir_entry->noent) + err = ENOENT; + + if (err == ENOENT) + { + dir_entry->noent = 1; /* A negative entry. */ + dir_entry->name_timestamp = timestamp; + } + } + else + { + /* Refresh the root node with the old stat + information. */ + update_entry (dir_entry, &netfs_root_node->nn_stat, NULL, timestamp); + } + } + + node->nn_stat = dir_entry->stat; + node->nn_translated = S_ISLNK (dir_entry->stat.st_mode) ? S_IFLNK : 0; + if (!nn->dir && S_ISDIR (dir_entry->stat.st_mode)) + procfs_dir_create (nn->fs, node, nn->fs_path, &nn->dir); + + mutex_unlock (&dir->node->lock); + + return err; + } +} + +/* Remove NODE from its entry */ +error_t procfs_remove_node (struct node *node) +{ + + /* STUB */ + + return 0; +} diff --git a/procfs/procfs.c b/procfs/procfs.c new file mode 100644 index 00000000..1fd0d619 --- /dev/null +++ b/procfs/procfs.c @@ -0,0 +1,149 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs.c -- This file is the main file of the translator. + This has important definitions and initializes + the translator + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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 +#include +#include +#include + +#include +#include +#include +#include + +#include "procfs.h" + +/* Defines this Tanslator Name */ +char *netfs_server_name = PROCFS_SERVER_NAME; +char *netfs_server_version = PROCFS_SERVER_VERSION; +int netfs_maxsymlinks = 12; + +static const struct argp_child argp_children[] = + { + {&netfs_std_startup_argp, 0, NULL, 0}, + {0} + }; + + +const char *argp_program_version = "/proc pseudo-filesystem (" PROCFS_SERVER_NAME + ") " PROCFS_SERVER_VERSION "\n" +"Copyright (C) 2008 Free Software Foundation\n" +"This is free software; see the source for copying conditions. There is NO\n" +"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." +"\n"; + +static char *args_doc = "PROCFSROOT"; +static char *doc = "proc pseudo-filesystem for Hurd implemented as a translator. " +"This is still under very humble and initial stages of development.\n" +"Any Contribution or help is welcome. The code may not even compile"; + + +/* The Filesystem */ +struct procfs *procfs; + +/* The FILESYSTEM component of PROCFS_FS. */ +char *procfs_root = ""; + +volatile struct mapped_time_value *procfs_maptime; + +/* Startup options. */ +static const struct argp_option procfs_options[] = + { + { 0 } + }; + + +/* argp parser function for parsing single procfs command line options */ +static error_t +parse_procfs_opt (int key, char *arg, struct argp_state *state) +{ + switch (key) + { + case ARGP_KEY_ARG: + if (state->arg_num > 1) + argp_usage (state); + break; + + case ARGP_KEY_NO_ARGS: + argp_usage(state); + break; + + default: + return ARGP_ERR_UNKNOWN; + } +} + +/* Program entry point. */ +int +main (int argc, char **argv) +{ + error_t err; + mach_port_t bootstrap, underlying_node; + struct stat underlying_stat; + + struct argp argp = + { + procfs_options, parse_procfs_opt, + args_doc, doc, argp_children, + NULL, NULL + }; + + + /* Parse the command line arguments */ +// argp_parse (&argp, argc, argv, 0, 0, 0); + + task_get_bootstrap_port (mach_task_self (), &bootstrap); + + netfs_init (); + + if (maptime_map (0, 0, &procfs_maptime)) + { + perror (PROCFS_SERVER_NAME ": Cannot map time"); + return 1; + } + + procfs_init (); + + err = procfs_create (procfs_root, getpid (), &procfs); + if (err) + error (4, err, "%s", procfs_root); + + /* Create our root node */ + netfs_root_node = procfs->root; + + /* Start netfs activities */ + underlying_node = netfs_startup (bootstrap, 0); + if (io_stat (underlying_node, &underlying_stat)) + error (1, err, "cannot stat underling node"); + + /* Initialize stat information of the root node. */ + netfs_root_node->nn_stat = underlying_stat; + netfs_root_node->nn_stat.st_mode = + S_IFDIR | (underlying_stat.st_mode & ~S_IFMT & ~S_ITRANS); + + for (;;) + netfs_server_loop (); + return 1; +} diff --git a/procfs/procfs.h b/procfs/procfs.h new file mode 100644 index 00000000..fa2fb7f7 --- /dev/null +++ b/procfs/procfs.h @@ -0,0 +1,220 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs.h -- This file is the main header file of this + translator. This has important header + definitions for constants and functions + used in the translator. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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. + + A portion of the code in this file is based on ftpfs code + present in the hurd repositories copyrighted to FSF. The + Copyright notice from that file is given below. + + Copyright (C) 1997,98,2002 Free Software Foundation, Inc. + Written by Miles Bader + This file is part of the GNU Hurd. +*/ + +#ifndef __PROCFS_H__ +#define __PROCFS_H__ + +#define PROCFS_SERVER_NAME "procfs" +#define PROCFS_SERVER_VERSION "0.0.1" + +/* /proc Filesystem type. */ +#define PROCFILESYSTEM "procfs" + +#define NUMBER_OF_FILES_PER_PID 1 +#define JIFFY_ADJUST 100 +#define PAGES_TO_BYTES(pages) ((pages) * sysconf(_SC_PAGESIZE)) +#define BYTES_TO_PAGES(bytes) ((bytes) / sysconf(_SC_PAGESIZE)) + +#include +#include +#include +#include +#include +#include + +typedef unsigned long long jiffy_t; + +/* A single entry in a directory. */ +struct procfs_dir_entry +{ + char *name; /* Name of this entry */ + size_t hv; /* Hash value of NAME */ + + /* The active node referred to by this name (may be 0). + NETFS_NODE_REFCNT_LOCK should be held while frobbing this. */ + struct node *node; + + struct stat stat; + char *symlink_target; + time_t stat_timestamp; + + /* The directory to which this entry belongs. */ + struct procfs_dir *dir; + + /* Link to next entry in hash bucket, and address of previous entry's (or + hash table's) pointer to this entry. If the SELF_P field is 0, then + this is a deleted entry, awaiting final disposal. */ + struct procfs_dir_entry *next, **self_p; + + /* Next entry in 'directory order', or 0 if none known. */ + struct procfs_dir_entry *ordered_next, **ordered_self_p; + + /* When the presence/absence of this file was last checked. */ + time_t name_timestamp; + + hurd_ihash_locp_t inode_locp; /* Used for removing this entry */ + + int noent : 1; /* A negative lookup result. */ + int valid : 1; /* Marker for GC'ing. */ +}; + +/* A directory. */ +struct procfs_dir +{ + /* Number of entries in HTABLE. */ + size_t num_entries; + + /* The number of entries that have nodes attached. We keep an additional + reference to our node if there are any, to prevent it from going away. */ + size_t num_live_entries; + + /* Hash table of entries. */ + struct procfs_dir_entry **htable; + size_t htable_len; /* # of elements in HTABLE (not bytes). */ + + /* List of dir entries in 'directory order', in a linked list using the + ORDERED_NEXT and ORDERED_SELF_P fields in each entry. Not all entries + in HTABLE need be in this list. */ + struct procfs_dir_entry *ordered; + + /* The filesystem node that this is the directory for. */ + struct node *node; + + /* The filesystem this directory is in. */ + struct procfs *fs; + + /* The path to this directory in the filesystem. */ + const char *fs_path; + + time_t stat_timestamp; + time_t name_timestamp; + +}; + + +/* libnetfs node structure */ +struct netnode +{ + /* Name of this node */ + char *name; + + /* The path in the filesystem that corresponds + this node. */ + char *fs_path; + + /* The directory entry for this node. */ + struct procfs_dir_entry *dir_entry; + + /* The proc filesystem */ + struct procfs *fs; + + /* inode number, assigned to this netnode structure. */ + unsigned int inode_num; + + /* If this is a directory, the contents, or 0 if not fetched. */ + struct procfs_dir *dir; + + /* pointer to node structure, assigned to this node. */ + struct node *node; + + /* links to the previous and next nodes in the list */ + struct netnode *nextnode, *prevnode; + + /* link to parent netnode of this file or directory */ + struct netnode *parent; + + /* link to the first child netnode of this directory */ + struct netnode *child_first; +}; + +/* The actual procfs filesystem structure */ +struct procfs +{ + /* Root of the filesystem. */ + struct node *root; + + /* Inode numbers are assigned sequentially in order of creation. */ + ino_t next_inode; + int fsid; + + /* A hash table mapping inode numbers to directory entries. */ + struct hurd_ihash inode_mappings; + spin_lock_t inode_mappings_lock; +}; + +extern struct procfs *procfs; + +extern volatile struct mapped_time_value *procfs_maptime; + +extern struct ps_context *ps_context; + +/* Create a new procfs filesystem. */ +error_t procfs_create (char *procfs_root, int fsid, + struct procfs **fs); + +/* Initialize the procfs filesystem for use. */ +error_t procfs_init (); + +/* Refresh stat information for NODE */ +error_t procfs_refresh_node (struct node *node); + +/* Return a new node in NODE, with a name NAME, + and return the new node with a single + reference in NODE. */ +error_t procfs_create_node (struct procfs_dir_entry *dir_entry, + const char *fs_path, + struct node **node); + +/* Remove NODE from its entry */ +error_t procfs_remove_node (struct node *node); + +/* Return in DIR a new procfs directory, in the filesystem FS, + with node NODE and path PATH. */ +error_t procfs_dir_create (struct procfs *fs, struct node *node, + const char *path, struct procfs_dir **dir); + +/* Remove the specified DIR and free all its allocated + storage. */ +void procfs_dir_remove (struct procfs_dir *dir); + +/* Refresh DIR. */ +error_t procfs_dir_refresh (struct procfs_dir *dir, int isroot); + +/* Lookup NAME in DIR, returning its entry, or an error. + *NODE will contain the result node, locked, and with + an additional reference, or 0 if an error occurs. */ +error_t procfs_dir_lookup (struct procfs_dir *dir, const char *name, + struct node **node); + +#endif /* __PROCFS_H__ */ diff --git a/procfs/procfs_dir.c b/procfs/procfs_dir.c new file mode 100644 index 00000000..f76e6a4b --- /dev/null +++ b/procfs/procfs_dir.c @@ -0,0 +1,664 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs_dir.c -- This file contains definitions to perform + directory operations such as creating, + removing and refreshing directories. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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. + + A portion of the code in this file is based on ftpfs code + present in the hurd repositories copyrighted to FSF. The + Copyright notice from that file is given below. + + Copyright (C) 1997,98,2002 Free Software Foundation, Inc. + Written by Miles Bader + This file is part of the GNU Hurd. +*/ + + +#include +#include +#include +#include +#include + +#include "procfs.h" + +/* Initial HASHTABLE length for the new directories to be created. */ +#define INIT_HTABLE_LEN 5 + +struct procfs_dir_entry **cur_entry; + +/* Return in DIR a new procfs directory, in the filesystem FS, + with node NODE and path PATH. */ +error_t procfs_dir_create (struct procfs *fs, struct node *node, + const char *path, struct procfs_dir **dir) +{ + struct procfs_dir *new = malloc (sizeof (struct procfs_dir)); + if (!new) + return ENOMEM; + struct procfs_dir_entry **htable = calloc (INIT_HTABLE_LEN, + sizeof (struct procfs_dir_entry *)); + if (!htable) + return ENOMEM; + + /* Hold a reference to the new dir's node. */ + spin_lock (&netfs_node_refcnt_lock); + node->references++; + spin_unlock (&netfs_node_refcnt_lock); + + new->num_entries = 0; + new->num_live_entries = 0; + new->htable_len = INIT_HTABLE_LEN; + new->htable = htable; + new->ordered = NULL; + new->fs_path = path; + new->fs = fs; + new->node = node; + new->stat_timestamp = 0; + new->name_timestamp = 0; + + *dir = new; + + if (fs->root != 0) + node->nn->dir = new; + + return 0; +} + +/* Put the directory entry DIR_ENTRY into the hash table HTABLE. */ +static void +insert (struct procfs_dir_entry *dir_entry, + struct procfs_dir_entry **htable, size_t htable_len) +{ + struct procfs_dir_entry **new_htable = &htable[dir_entry->hv % htable_len]; + if (*new_htable) + (*new_htable)->self_p = &dir_entry->next; + dir_entry->next = *new_htable; + dir_entry->self_p = new_htable; + *new_htable = dir_entry; +} + +/* Calculate NAME's hash value. */ +static size_t +hash (const char *name) +{ + size_t hash_value = 0; + while (*name) + hash_value = ((hash_value << 5) + *name++) & 0xFFFFFF; + return hash_value; +} + +/* Extend the existing hashtable for DIR to accomodate values for new length + NEW_LEN. We retain all the previous entries. */ +static error_t +rehash (struct procfs_dir *dir, size_t new_len) +{ + int count; + size_t old_len = dir->htable_len; + struct procfs_dir_entry **old_htable = dir->htable; + struct procfs_dir_entry **new_htable = (struct procfs_dir_entry **) + malloc (new_len * sizeof (struct procfs_dir_entry *)); + + if (! new_htable) + return ENOMEM; + + bzero (new_htable, new_len * sizeof (struct procfs_dir_entry *)); + + for (count = 0; count < old_len; count++) + while (old_htable[count]) + { + struct procfs_dir_entry *dir_entry = old_htable[count]; + + /* Remove DIR_ENTRY from the old table */ + old_htable[count] = dir_entry->next; + + insert (dir_entry, new_htable, new_len); + } + + free (old_htable); + + dir->htable = new_htable; + dir->htable_len = new_len; + + return 0; +} + +/* Lookup NAME in DIR and return its entry. If there is no such entry, and + DNEW, the decision variable, is true, then a new entry is allocated and + returned, otherwise 0 is returned (if DNEW is true then 0 can be returned + if a memory allocation error occurs). */ +struct procfs_dir_entry * +lookup_entry (struct procfs_dir *dir, const char *name, int dnew) +{ + size_t hv = hash (name); + struct procfs_dir_entry *dir_entry = dir->htable[hv % dir->htable_len]; + + while (dir_entry && strcmp (name, dir_entry->name) != 0) + dir_entry = dir_entry->next; + + if (!dir_entry && dnew) + { + if (dir->num_entries > dir->htable_len) + /* Grow the hash table. */ + if (rehash (dir, (dir->htable_len + 1) * 2 - 1) != 0) + return 0; + + dir_entry = + (struct procfs_dir_entry *) malloc (sizeof (struct procfs_dir_entry)); + + if (dir_entry) + { + dir_entry->hv = hv; + dir_entry->name = strdup (name); + dir_entry->node = 0; + dir_entry->dir = dir; + dir_entry->stat_timestamp = 0; + bzero (&dir_entry->stat, sizeof dir_entry->stat); + dir_entry->symlink_target = 0; + dir_entry->noent = 0; + dir_entry->valid = 0; + dir_entry->name_timestamp = 0; + dir_entry->ordered_next = 0; + dir_entry->ordered_self_p = 0; + dir_entry->next = 0; + dir_entry->self_p = 0; + insert (dir_entry, dir->htable, dir->htable_len); + dir->num_entries++; + } + } + + return dir_entry; +} + + +/* Lookup NAME in DIR, returning its entry, or an error. + *NODE will contain the result node, locked, and with + an additional reference, or 0 if an error occurs. */ +error_t procfs_dir_lookup (struct procfs_dir *dir, const char *name, + struct node **node) +{ + struct procfs_dir_entry *dir_entry = 0; + error_t err = 0; + char *fs_path = dir->fs_path; + + struct timeval tv; + maptime_read (procfs_maptime, &tv); + + time_t timestamp = tv.tv_sec; + + if (*name == '\0' || strcmp (name, ".") == 0) + /* Current directory -- just add an additional reference to DIR's node + and return it. */ + { + netfs_nref (dir->node); + *node = dir->node; + return 0; + } + else if (strcmp (name, "..") == 0) + /* Parent directory. */ + { + if (dir->node->nn->dir_entry) + { + *node = dir->node->nn->dir_entry->dir->node; + mutex_lock (&(*node)->lock); + netfs_nref (*node); + } + else + { + err = ENOENT; /* No .. */ + *node = 0; + } + + mutex_unlock (&dir->node->lock); + + return err; + } + + err = procfs_dir_refresh (dir, dir->node == dir->fs->root); + if (!err && !dir_entry) + dir_entry = lookup_entry (dir, name, 0); + + if (! err) + { + if (dir_entry && !dir_entry->noent) + /* We've got a dir entry, get a node for it. */ + { + /* If there's already a node, add a ref so that it doesn't go + away. */ + spin_lock (&netfs_node_refcnt_lock); + if (dir_entry->node) + dir_entry->node->references++; + spin_unlock (&netfs_node_refcnt_lock); + + if (! dir_entry->node) + /* No node; make one and install it into E. */ + { + if (! fs_path) + err = EROFS; + + if (! err) + { + err = procfs_create_node (dir_entry, fs_path, &dir_entry->node); + + if (!err && dir->num_live_entries++ == 0) + /* Keep a reference to dir's node corresponding to + children. */ + { + spin_lock (&netfs_node_refcnt_lock); + dir->node->references++; + spin_unlock (&netfs_node_refcnt_lock); + } + } + } + + if (! err) + { + *node = dir_entry->node; + /* We have to unlock DIR's node before locking the child node + because the locking order is always child-parent. We know + the child node won't go away because we already hold the + additional reference to it. */ + mutex_unlock (&dir->node->lock); + mutex_lock (&dir_entry->node->lock); + } + } + else + err = ENOENT; + } + + if (err) + { + *node = 0; + mutex_unlock (&dir->node->lock); + } + +#if 0 + if (fs_path) + free (fs_path); +#endif + + return err; +} + +/* Lookup the null name in DIR, and return a node for it in NODE. Unlike + procfs_dir_lookup, this won't attempt to validate the existance of the + entry (to avoid opening a new connection if possible) -- that will happen + the first time the entry is refreshed. Also unlink ftpfs_dir_lookup, this + function doesn't expect DIR to be locked, and won't return *NODE locked. + This function is only used for bootstrapping the root node. */ +error_t +procfs_dir_null_lookup (struct procfs_dir *dir, struct node **node) +{ + struct procfs_dir_entry *dir_entry; + error_t err = 0; + + dir_entry = lookup_entry (dir, "", 1); + if (! dir_entry) + return ENOMEM; + + if (! dir_entry->noent) + /* We've got a dir entry, get a node for it. */ + { + /* If there's already a node, add a ref so that it doesn't go away. */ + spin_lock (&netfs_node_refcnt_lock); + if (dir_entry->node) + dir_entry->node->references++; + spin_unlock (&netfs_node_refcnt_lock); + + if (! dir_entry->node) + /* No node; make one and install it into DIR_ENTRY. */ + { + err = procfs_create_node (dir_entry, dir->fs_path, &dir_entry->node); + + if (!err && dir->num_live_entries++ == 0) + /* Keep a reference to dir's node corresponding to children. */ + { + spin_lock (&netfs_node_refcnt_lock); + dir->node->references++; + spin_unlock (&netfs_node_refcnt_lock); + } + } + + if (! err) + *node = dir_entry->node; + } + else + err = ENOENT; + + return err; +} + +/* Free the directory entry DIR_ENTRY and all resources it consumes. */ +void +free_entry (struct procfs_dir_entry *dir_entry) +{ + + assert (! dir_entry->self_p); /* We should only free deleted nodes. */ + free (dir_entry->name); + if (dir_entry->symlink_target) + free (dir_entry->symlink_target); + free (dir_entry->node->nn->dir); + free (dir_entry->node->nn); + free (dir_entry->node); + free (dir_entry); +} + +/* Remove DIR_ENTRY from its position in the ordered_next chain. */ +static void +ordered_unlink (struct procfs_dir_entry *dir_entry) +{ + if (dir_entry->ordered_self_p) + *dir_entry->ordered_self_p = dir_entry->ordered_next; + if (dir_entry->ordered_next) + dir_entry->ordered_next->self_p = dir_entry->ordered_self_p; +} + +/* Delete DIR_ENTRY from its directory, freeing any resources it holds. */ +static void +delete (struct procfs_dir_entry *dir_entry, struct procfs_dir *dir) +{ + dir->num_entries--; + + /* Take out of the hash chain. */ + if (dir_entry->self_p) + *dir_entry->self_p = dir_entry->next; + if (dir_entry->next) + dir_entry->next->self_p = dir_entry->self_p; + + /* Take out of the directory ordered list. */ + ordered_unlink (dir_entry); + + /* If there's a node attached, we'll delete the entry whenever it goes + away, otherwise, just delete it now. */ + if (! dir_entry->node) + free_entry (dir_entry); +} + +/* Make all the directory entries invalid */ +static void +make_dir_invalid (struct procfs_dir *dir) +{ + int count; + size_t len = dir->htable_len; + struct procfs_dir_entry **htable = dir->htable; + struct procfs_dir_entry *dir_entry; + + for (count = 0; count < len; count++) + { + dir_entry = htable[count]; + while (dir_entry) + { + dir_entry->valid = 0; + dir_entry = dir_entry->next; + } + } +} + +/* Delete any entries in DIR which don't have their valid bit set. */ +static void +sweep (struct procfs_dir *dir) +{ + size_t len = dir->htable_len, i; + struct procfs_dir_entry **htable = dir->htable, *dir_entry; + + for (i = 0; i < len; i++) + { + dir_entry = htable[i]; + while (dir_entry) + { + if (!dir_entry->valid && !dir_entry->noent && dir->num_entries) + delete (dir_entry, dir); + dir_entry = dir_entry->next; + } + if (htable[i]) + { + free (htable[i]); + htable[i] = 0; + } + + } + +} + +/* Remove the specified DIR and free all its allocated + storage. */ +void procfs_dir_entries_remove (struct procfs_dir *dir) +{ + /* Free all entries. */ + make_dir_invalid (dir); + sweep (dir); +} + +/* Checks if the DIR name is in list of + Active pids. */ +int is_in_pid_list (struct procfs_dir *dir) +{ + int dir_name; + int count; + pid_t *pids = NULL; + int pidslen = 0; + error_t err; + + if (dir->node->nn) + { + dir_name = atoi (dir->node->nn->dir_entry->name); + err = proc_getallpids (getproc (), &pids, &pidslen); + + for (count = 0; count < pidslen; ++count) + if (pids[count] == dir_name) + return 1; + } + + return 0; + +} + +/* Checks if DIR is a directory that + represents a pid. */ +int check_parent (struct procfs_dir *dir) +{ + if (dir == dir->fs->root) + return 0; + else + if (is_in_pid_list (dir)) + return 1; + else + return 0; + +} + +/* Refresh DIR. */ +error_t procfs_dir_refresh (struct procfs_dir *dir, int isroot) +{ + error_t err; + int is_parent_pid; + struct node *node; + + struct timeval tv; + maptime_read (procfs_maptime, &tv); + + time_t timestamp = tv.tv_sec; + cur_entry = &dir->ordered; + if (isroot) + err = procfs_fill_root_dir(dir, timestamp); + else + { + err = update_dir_entries (dir, timestamp); + is_parent_pid = check_parent (dir); + if (is_parent_pid) + err = procfs_create_files (dir, &node, timestamp); + } + + return err; +} + +/* Update the directory entry for NAME to reflect STAT and SYMLINK_TARGET. + This also creates a valid linked list of entries imposing ordering on + them. */ +struct procfs_dir_entry* +update_entries_list (struct procfs_dir *dir, const char *name, + const struct stat *stat, time_t timestamp, + const char *symlink_target) +{ + ino_t ino; + struct procfs_dir_entry *dir_entry = lookup_entry (dir, name, 1); + struct procfs *fs = dir->fs; + + if (! dir_entry) + return ENOMEM; + + if (dir_entry->stat.st_ino) + ino = dir_entry->stat.st_ino; + else + ino = fs->next_inode++; + + dir_entry->name_timestamp = timestamp; + + if (stat) + /* The ST and SYMLINK_TARGET parameters are only valid if ST isn't 0. */ + { + dir_entry->stat = *stat; + dir_entry->stat_timestamp = timestamp; + + if (!dir_entry->symlink_target || !symlink_target + || strcmp (dir_entry->symlink_target, symlink_target) != 0) + { + if (dir_entry->symlink_target) + free (dir_entry->symlink_target); + dir_entry->symlink_target = symlink_target ? strdup (symlink_target) : 0; + } + } + + /* The st_ino field is always valid. */ + dir_entry->stat.st_ino = ino; + dir_entry->stat.st_fsid = fs->fsid; + dir_entry->stat.st_fstype = PROCFILESYSTEM; + + dir_entry->valid = 1; + + if (! dir_entry->ordered_self_p) + /* Position DIR_ENTRY in the ordered chain following the previously seen entry. */ + { + /* The PREV_ENTRY_NEXT_P field holds a pointer to the NEXT-field of the + previous entry, or a pointer to the ORDERED field in the directory. */ + dir_entry->ordered_self_p = cur_entry; + + if (*dir_entry->ordered_self_p) + /* Update the self_p pointer of the previous successor. */ + (*dir_entry->ordered_self_p)->ordered_self_p = &dir_entry->ordered_next; + + /* DIR_ENTRY comes before the previous successor. */ + dir_entry->ordered_next = *dir_entry->ordered_self_p; + + *dir_entry->ordered_self_p = dir_entry; /* Put DIR_ENTRY there. */ + } + + /* Put the next entry after this one. */ + cur_entry = &dir_entry->ordered_next; + + return dir_entry; +} + +/* Fills DIR, the root directory with all the pids of + processes running in the system as directories. */ +error_t +procfs_fill_root_dir(struct procfs_dir *dir, time_t timestamp) +{ + error_t err; + char *data; + pid_t *pids; + int pidslen; + struct stat stat; + stat.st_mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | + S_IROTH | S_IXOTH; + stat.st_nlink = 1; + stat.st_size = 0; + + int count; + char *dir_name_pid; + struct node *node; + struct procfs_dir *new_dir; + struct procfs_dir_entry *dir_entry; + struct proc_stat *ps; + + pids = NULL; + pidslen = 0; + err = proc_getallpids (getproc (), &pids, &pidslen); + + if (!err) + { + for (count = 0; count < pidslen; count++) + { + if (asprintf (&dir_name_pid, "%d", pids[count]) == -1) + return errno; + +#if 0 + node = (struct node *) malloc (sizeof (struct node)); + new_dir = (struct procfs_dir *) malloc (sizeof (struct procfs_dir )); + + if (! node || ! new_dir ) + return ENOMEM; +#endif + err = _proc_stat_create (pids[count], ps_context, &ps); + if (! err) + { + err = set_field_value (ps, PSTAT_PROC_INFO); + if (! err) + { + stat.st_uid = proc_stat_proc_info (ps)->owner; + stat.st_gid = proc_stat_proc_info (ps)->pgrp; + + dir_entry = update_entries_list (dir, dir_name_pid, + &stat, timestamp, NULL); + err = procfs_create_node (dir_entry, dir_name_pid, &node); + + procfs_dir_create (dir->fs, node, + dir_name_pid, &new_dir); + free(dir_name_pid); + _proc_stat_free (ps); + } + } + } + } + + if ((err = procfs_create_uptime (dir, &node, timestamp)) != 0) + return err; + + if ((err = procfs_create_stat (dir, &node, timestamp)) != 0) + return err; + + if ((err = procfs_create_version (dir, &node, timestamp)) != 0) + return err; + + if ((err = procfs_create_meminfo (dir, &node, timestamp)) != 0) + return err; + + if ((err = procfs_create_loadavg (dir, &node, timestamp)) != 0) + return err; + + return 0; +} + +error_t update_dir_entries (struct procfs_dir *dir) +{ + /* STUB */ + return 0; +} diff --git a/procfs/procfs_nonpid_files.c b/procfs/procfs_nonpid_files.c new file mode 100644 index 00000000..2c1209ee --- /dev/null +++ b/procfs/procfs_nonpid_files.c @@ -0,0 +1,514 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs_nonpid_files.c -- This file contains function definitions + to create and update the non-Per PID + files and their contents. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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. + + A portion of the code in this file is based on vmstat.c code + present in the hurd repositories copyrighted to FSF. The + Copyright notice from that file is given below. + + Copyright (C) 1997,98,2002 Free Software Foundation, Inc. + Written by Miles Bader + This file is part of the GNU Hurd. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "procfs.h" + +typedef long long val_t; +#define BADVAL ((val_t) - 1LL) + +/* default pager port (must be privileged to fetch this). */ +mach_port_t def_pager; +struct default_pager_info def_pager_info; + +error_t procfs_create_uptime (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "uptime") == -1) + return errno; + if (asprintf (&file_path, "%s", "uptime") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return err; +} + +error_t procfs_create_version(struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "version") == -1) + return errno; + if (asprintf (&file_path, "%s", "version") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return 0; +} + +error_t procfs_create_stat (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "stat") == -1) + return errno; + if (asprintf (&file_path, "%s", "stat") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return err; +} + +error_t procfs_create_meminfo (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "meminfo") == -1) + return errno; + if (asprintf (&file_path, "%s", "meminfo") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return err; +} + +error_t procfs_create_loadavg (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "loadavg") == -1) + return errno; + if (asprintf (&file_path, "%s", "loadavg") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return err; +} + +error_t get_uptime (struct timeval *uptime) +{ + struct timeval boot_time, now; + error_t err; + struct proc_stat *ps; + + err = _proc_stat_create (1, ps_context, &ps); + + if (err) + return err; + + err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); + if (!err && !(ps->flags & PSTAT_TASK_BASIC)) + err = EGRATUITOUS; + + if (! err) + { + time_value_t *const tv = &proc_stat_task_basic_info (ps)->creation_time; + boot_time.tv_sec = tv->seconds; + boot_time.tv_usec = tv->microseconds; + if (gettimeofday (&now, 0) < 0) + error (0, errno, "gettimeofday"); + timersub (&now, &boot_time, uptime); + } + + _proc_stat_free (ps); + return err; +} + +error_t get_total_times (struct timeval *total_user_time, + struct timeval *total_system_time) +{ + error_t err; + pid_t *pids; + int pidslen = 0, count; + struct proc_stat *ps; + struct task_thread_times_info live_threads_times; + + struct timeval total_user_time_tmp; + struct timeval total_system_time_tmp; + struct timeval tmpval; + + timerclear (&total_user_time_tmp); + timerclear (&total_system_time_tmp); + + pids = NULL; + err = proc_getallpids (getproc (), &pids, &pidslen); + + if (!err) + for (count = 0; count < pidslen; count++) + { + err = _proc_stat_create (pids[count], ps_context, &ps); + if (err) + return err; + + err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); + if (!err && !(ps->flags & PSTAT_TASK_BASIC)) + err = EGRATUITOUS; + + if (! err) + { + tmpval.tv_sec = proc_stat_task_basic_info (ps)->user_time.seconds; + tmpval.tv_usec = proc_stat_task_basic_info (ps)->user_time.seconds; + timeradd (&total_user_time_tmp, &tmpval, &total_user_time_tmp); + + tmpval.tv_sec = proc_stat_task_basic_info (ps)->system_time.seconds; + tmpval.tv_usec = proc_stat_task_basic_info (ps)->system_time.seconds; + timeradd (&total_system_time_tmp, &tmpval, &total_system_time_tmp); + + error_t err = set_field_value (ps, PSTAT_TASK); + if (! err) + { + err = get_task_thread_times (ps->task, &live_threads_times); + if (! err) + { + tmpval.tv_sec = live_threads_times.user_time.seconds; + tmpval.tv_usec = live_threads_times.user_time.microseconds; + timeradd (&total_user_time_tmp, &tmpval, &total_user_time_tmp); + + tmpval.tv_sec = live_threads_times.system_time.seconds; + tmpval.tv_usec = live_threads_times.system_time.microseconds; + timeradd (&total_system_time_tmp, &tmpval, &total_system_time_tmp); + } + } + } + _proc_stat_free (ps); + } + + total_user_time->tv_sec = total_user_time_tmp.tv_sec; + total_user_time->tv_usec = total_user_time_tmp.tv_usec; + + total_system_time->tv_sec = total_system_time_tmp.tv_sec; + total_system_time->tv_usec = total_system_time_tmp.tv_usec; + + return err; +} + +error_t procfs_read_nonpid_stat (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *stat_data; + error_t err; + jiffy_t total_user_time_jiffy, total_system_time_jiffy; + jiffy_t idle_time_jiffy; + struct timeval uptime, total_user_time, total_system_time; + struct timeval idle_time; + + err = get_uptime (&uptime); + + if (! err) + { + err = get_total_times (&total_user_time, &total_system_time); + + if (! err) + { + timersub (&uptime, &total_system_time, + &idle_time); + + total_user_time_jiffy = 100 * ((double) total_user_time.tv_sec + + (double) total_user_time.tv_usec / (1000 * 1000)); + total_system_time_jiffy = 100 * ((double) total_system_time.tv_sec + + (double) total_system_time.tv_usec / (1000 * 1000)); + idle_time_jiffy = 100 * ((double) idle_time.tv_sec + + (double) idle_time.tv_usec / (1000 * 1000)); + + if (asprintf (&stat_data, "cpu %llu %llu %llu %llu %llu %llu %d %d %d\n" + "cpu0 %llu %llu %llu %llu %llu %llu %d %d %d\n" + "intr %llu %llu %llu %llu %llu %llu %d %d %d\n", + total_user_time_jiffy, (long long unsigned) 0, + total_system_time_jiffy, idle_time_jiffy, + (long long unsigned) 0, (long long unsigned) 0, + 0, 0, 0, + total_user_time_jiffy, (long long unsigned) 0, + total_system_time_jiffy, idle_time_jiffy, + (long long unsigned) 0, (long long unsigned) 0, + 0, 0, 0, + (long long unsigned) 0, + (long long unsigned) 0, (long long unsigned) 0, (long long unsigned) 0, + (long long unsigned) 0, + (long long unsigned) 0, (long long unsigned) 0, + (long long unsigned) 0, (long long unsigned) 0) == -1) + return errno; + } + } + + memcpy (data, stat_data, strlen(stat_data)); + *len = strlen (data); + + free (stat_data); + return err; +} + +/* Makes sure the default pager port and associated + info exists, and returns 0 if not (after printing + an error). */ +static int +ensure_def_pager_info () +{ + error_t err; + + if (def_pager == MACH_PORT_NULL) + { + mach_port_t host; + + err = get_privileged_ports (&host, 0); + if (err == EPERM) + { + /* We are not root, so try opening the /servers file. */ + def_pager = file_name_lookup (_SERVERS_DEFPAGER, O_READ, 0); + if (def_pager == MACH_PORT_NULL) + { + error (0, errno, _SERVERS_DEFPAGER); + return 0; + } + } + if (def_pager == MACH_PORT_NULL) + { + if (err) + { + error (0, err, "get_privileged_ports"); + return 0; + } + + err = vm_set_default_memory_manager (host, &def_pager); + mach_port_deallocate (mach_task_self (), host); + + if (err) + { + error (0, err, "vm_set_default_memory_manager"); + return 0; + } + } + } + + if (!MACH_PORT_VALID (def_pager)) + { + if (def_pager == MACH_PORT_NULL) + { + error (0, 0, + "No default pager running, so no swap information available"); + def_pager = MACH_PORT_DEAD; /* so we don't try again */ + } + return 0; + } + + err = default_pager_info (def_pager, &def_pager_info); + if (err) + error (0, err, "default_pager_info"); + return (err == 0); +} + +#define SWAP_FIELD(getter, expr) \ + static val_t getter () \ + { return ensure_def_pager_info () ? (val_t) (expr) : BADVAL; } + +SWAP_FIELD (get_swap_size, def_pager_info.dpi_total_space) +SWAP_FIELD (get_swap_free, def_pager_info.dpi_free_space) +SWAP_FIELD (get_swap_page_size, def_pager_info.dpi_page_size) +SWAP_FIELD (get_swap_active, (def_pager_info.dpi_total_space + - def_pager_info.dpi_free_space)) + +error_t procfs_read_nonpid_meminfo (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *meminfo_data; + error_t err; + struct vm_statistics vmstats; + + err = vm_statistics (mach_task_self (), &vmstats); + + unsigned long mem_size = ((vmstats.free_count + + vmstats.active_count + vmstats.inactive_count + + vmstats.wire_count) * vmstats.pagesize) / 1024; + + if (! err) + if (asprintf (&meminfo_data, "MemTotal:\t%lu kB\n" + "MemFree:\t%lu kB\n" + "Buffers:\t%ld kB\n" + "Cached:\t\t%ld kB\n" + "SwapCached:\t%ld kB\n" + "Active:\t\t%lu kB\n" + "Inactive:\t%lu kB\n" + "HighTotal:\t%lu kB\n" + "HighFree:\t%lu kB\n" + "LowTotal:\t%lu kB\n" + "LowFree:\t%lu kB\n" + "SwapTotal:\t%llu kB\n" + "SwapFree:\t%llu kB\n", + mem_size, (PAGES_TO_BYTES(vmstats.free_count)) / 1024 , 0, 0, 0, + (PAGES_TO_BYTES(vmstats.active_count)) / 1024, + (PAGES_TO_BYTES(vmstats.inactive_count)) / 1024, 0, 0, 0, 0, + get_swap_size () / 1024, get_swap_free () / 1024) == -1) + return errno; + + memcpy (data, meminfo_data, strlen(meminfo_data)); + *len = strlen (data); + + free (meminfo_data); + return err; +} + +error_t procfs_read_nonpid_loadavg (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *loadavg_data; + error_t err; + processor_set_info_t info; + natural_t *count; + struct host_load_info *load; + mach_port_t host; + + err = ps_host_load_info (&load); + if (err) + error (0, err, "ps_host_load_info"); + + if (! err) + if (asprintf (&loadavg_data, "%.2f %.2f %.2f %d/%d %d\n", + (double)load->avenrun[0] / (double)LOAD_SCALE, + (double)load->avenrun[1] / (double)LOAD_SCALE, + (double)load->avenrun[2] / (double)LOAD_SCALE, 0, 0, 0) == -1) + return errno; + + memcpy (data, loadavg_data, strlen(loadavg_data)); + *len = strlen (data); + + free (loadavg_data); + return err; +} + +error_t procfs_read_nonpid_uptime (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *uptime_data; + error_t err; + double uptime_secs, idle_time_secs; + + struct timeval uptime_val; + struct timeval uptime, total_user_time, total_system_time; + struct timeval idle_time; + + + err = get_uptime (&uptime); + if (! err) + { + err = get_total_times (&total_user_time, + &total_system_time); + if (! err) + { + timersub (&uptime, &total_system_time, + &idle_time); + + uptime_secs = (double) uptime.tv_sec + + (double) uptime.tv_usec / (1000 * 1000); + + idle_time_secs = (double) idle_time.tv_sec + + (double) idle_time.tv_usec / (1000 * 1000); + + if (asprintf (&uptime_data, "%.2f %.2f\n", + uptime_secs, idle_time_secs) == -1) + return errno; + } + } + + + memcpy (data, uptime_data, strlen(uptime_data)); + *len = strlen (data); + + free (uptime_data); + return err; +} + +error_t procfs_read_nonpid_version (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *version_data; + error_t err = 0; + + if (asprintf (&version_data, "Linux version 2.6.18\n", NULL) == -1) + return errno; + + memcpy (data, version_data, strlen(version_data)); + *len = strlen (data); + + free (version_data); + return err; +} diff --git a/procfs/procfs_pid.h b/procfs/procfs_pid.h new file mode 100644 index 00000000..566c83ea --- /dev/null +++ b/procfs/procfs_pid.h @@ -0,0 +1,88 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs_pid.h -- This is the header file of which contains defintions + for structure of directory with PID as the name and + structure of each file in this directory. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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 __PROCFS_PID_H__ +#define __PROCFS_PID_H__ + +#include "procfs.h" + +struct procfs_pid_files +{ + struct procfs_cwd *procfs_cwd; + struct procfs_environ *procfs_environ; + struct procfs_cpu *procfs_cpu; + struct procfs_root *procfs_root; + struct procfs_exe *procfs_exe; + struct procfs_stat *_procfs_stat; + struct procfs_statm *procfs_statm; +}; + +struct procfs_stat +{ + pid_t pid; + char *comm; + char *state; + pid_t ppid; + pid_t pgid; + pid_t sid; + int tty_nr; + pid_t tty_pgrp; + unsigned flags; + long unsigned minflt; + long unsigned cminflt; + long unsigned majflt; + long unsigned cmajflt; + jiffy_t utime; + jiffy_t stime; + jiffy_t cutime; + jiffy_t cstime; + long priority; + long nice; + long num_threads; + long itrealvalue; + long long unsigned starttime; + long unsigned vsize; + long rss; + long unsigned rlim; + long unsigned startcode; + long unsigned endcode; + long unsigned startstack; + long unsigned kstkesp; + long unsigned kstkeip; + long unsigned signal; + long unsigned blocked; + long unsigned sigignore; + long unsigned sigcatch; + long unsigned wchan; + long unsigned nswap; + long unsigned cnswap; + int exit_signal; + int processor; + unsigned rt_priority; + unsigned policy; + long long unsigned delayacct_blkio_ticks; +}; + +#endif diff --git a/procfs/procfs_pid_files.c b/procfs/procfs_pid_files.c new file mode 100644 index 00000000..46861531 --- /dev/null +++ b/procfs/procfs_pid_files.c @@ -0,0 +1,576 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs_pid_files.c -- This file contains definitions to perform + file operations such as creating, writing to, + reading from and removing files that holds + information for each process with PID + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You 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. + + A portion of the code in this file is based on ftpfs code + present in the hurd repositories copyrighted to FSF. The + Copyright notice from that file is given below. + +*/ + +#include +#include +#include +#include +#include +#include + +#include "procfs_pid.h" + +/* Update the files named NAME within the directory named + PID also with SYMLINK TARGET if necessary. */ +struct procfs_dir_entry* +update_pid_entries (struct procfs_dir *dir, const char *name, + time_t timestamp, + const char *symlink_target) +{ + struct procfs_dir_entry *dir_entry; + struct stat *stat = (struct stat *) malloc (sizeof (struct stat)); + stat->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; + + dir_entry = update_entries_list (dir, name, stat, + timestamp, symlink_target); + + return dir_entry; +} + +/* Creates files to store process information for DIR + whose names are pids and returns these files in *NODE. */ +error_t +procfs_create_files (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "stat") == -1) + return errno; + if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "stat") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + if (asprintf (&file_name, "%s", "status") == -1) + return errno; + if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "status") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + if (asprintf (&file_name, "%s", "cmdline") == -1) + return errno; + if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "cmdline") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + if (asprintf (&file_name, "%s", "statm") == -1) + return errno; + if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "statm") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + +#if 0 + nodes_list = &node_stat; + nodes_list++; + node = nodes_list; +#endif + + return err; +} + +/* Check if the PSTAT_FLAG is set in the corresponding PS + structure, if not set it and check again and return error + status accordingly. */ +error_t set_field_value (struct proc_stat *ps, int pstat_flag) +{ + error_t err; + + if (! (ps->flags & pstat_flag)) + { + err = proc_stat_set_flags (ps, pstat_flag); + if (err) + return err; + + /* This second check is done since ps.h specifies to + do so since the previous call would not have set + the required value. */ + if (! (ps->flags & pstat_flag)) + return EGRATUITOUS; + } + + return 0; +} + +/* Adjusts TIME_VAL structure having Seconds and + Microseconds into the value in jiffies. The + value of jiffy is a hack to adjust to what + procps uses. */ +jiffy_t adjust_jiffy_time (time_value_t time_val) +{ + jiffy_t jiffy_time = time_val.seconds * JIFFY_ADJUST; + jiffy_time += (time_val.microseconds * JIFFY_ADJUST) + / (1000 * 1000); + + return jiffy_time; +} + +/* Extract the user and system time for the live threads of + the process. This information is directly retrieved from + MACH since neither libps not proc makes this available. */ +error_t get_task_thread_times (task_t task, + struct task_thread_times_info *live_threads_times) +{ + error_t err; + size_t tkcount = TASK_THREAD_TIMES_INFO_COUNT; + + err = task_info (task, TASK_THREAD_TIMES_INFO, + (task_info_t) live_threads_times, &tkcount); + if (err == MACH_SEND_INVALID_DEST) + err = ESRCH; + + return err; +} + +/* Obtains the User Time in UTIME and System Time in STIME from + MACH directly since this is neither made available by libps + nor by proc server. */ +error_t get_live_threads_time (struct proc_stat *ps, + jiffy_t *utime, jiffy_t *stime) +{ + struct task_thread_times_info live_threads_times; + error_t err = set_field_value (ps, PSTAT_TASK); + + if (! err) + { + err = get_task_thread_times (ps->task, &live_threads_times); + if (! err) + { + *utime = adjust_jiffy_time ( + live_threads_times.user_time); + *stime = adjust_jiffy_time ( + live_threads_times.system_time); + } + } + + return err; +} + +/* Get the data for stat file into the structure + PROCFS_STAT. */ +error_t get_stat_data (pid_t pid, + struct procfs_stat **procfs_stat) +{ + error_t err; + struct procfs_stat *new = (struct procfs_stat *) + malloc (sizeof (struct procfs_stat)); + + struct proc_stat *ps; + jiffy_t utime, stime; + + err = _proc_stat_create (pid, ps_context, &ps); + + new->pid = pid; + + if (! err) + { + err = set_field_value (ps, PSTAT_ARGS); + if (! err) + asprintf (&new->comm, "%s", ps->args); + } + + err = set_field_value (ps, PSTAT_STATE); + if (! err) + { + if (ps->state & PSTAT_STATE_P_STOP) + new->state = strdup ("T"); + if (ps->state & PSTAT_STATE_P_ZOMBIE) + new->state = strdup ("Z"); + if (ps->state & PSTAT_STATE_P_FG) + new->state = strdup ("+"); + if (ps->state & PSTAT_STATE_P_SESSLDR) + new->state = strdup ("s"); + if (ps->state & PSTAT_STATE_P_LOGINLDR) + new->state = strdup ("l"); + if (ps->state & PSTAT_STATE_P_FORKED) + new->state = strdup ("f"); + if (ps->state & PSTAT_STATE_P_NOMSG) + new->state = strdup ("m"); + if (ps->state & PSTAT_STATE_P_NOPARENT) + new->state = strdup ("p"); + if (ps->state & PSTAT_STATE_P_ORPHAN) + new->state = strdup ("o"); + if (ps->state & PSTAT_STATE_P_TRACE) + new->state = strdup ("x"); + if (ps->state & PSTAT_STATE_P_WAIT) + new->state = strdup ("w"); + if (ps->state & PSTAT_STATE_P_GETMSG) + new->state = strdup ("g"); + } + + err = set_field_value (ps, PSTAT_PROC_INFO); + if (! err) + { + new->ppid = ps->proc_info->ppid; + new->pgid = ps->proc_info->pgrp; + new->sid = ps->proc_info->session; + new->tty_pgrp = ps->proc_info->pgrp; + } + else + { + new->ppid = 0; + new->pgid = 0; + new->sid = 0; + new->tty_pgrp = 0; + } + + err = set_field_value (ps, PSTAT_STATE); + if (! err) + new->flags = ps->state; + else + new->flags = 0; + + err = set_field_value (ps, PSTAT_TASK_EVENTS); + if (! err) + { + new->minflt = ps->task_events_info->faults; + new->majflt = ps->task_events_info->pageins; + } + else + { + new->minflt = 0; + new->majflt = 0; + } + + /* This seems to be a bit inconsistent with setting of other + fields in this code. There are two reasons for this. + 1. The actual information required is not made available + by libps which should be directly obtained from MACH. + 2. The same code which is required to get the information + have to be reused in procfs_nonpid_files.c */ + err = get_live_threads_time (ps, &utime, &stime); + if (! err) + { + new->utime = utime; + new->stime = stime; + } + else + { + new->utime = 0; + new->stime = 0; + } + + err = set_field_value (ps, PSTAT_TASK_BASIC); + if (! err) + { + new->cutime = adjust_jiffy_time ( + ps->task_basic_info->user_time); + new->cstime = adjust_jiffy_time ( + ps->task_basic_info->system_time); + + new->priority = ps->task_basic_info->base_priority; + new->starttime = adjust_jiffy_time ( + ps->task_basic_info->creation_time); + + new->vsize = ps->task_basic_info->virtual_size; + new->rss = ps->task_basic_info->resident_size; + } + else + { + new->cutime = 0; + new->cstime = 0; + new->priority = 0; + new->starttime = 0; + new->vsize = 0; + new->rss = 0; + } + + new->nice = getpriority (0, pid); + + err = set_field_value (ps, PSTAT_NUM_THREADS); + if (! err) + new->num_threads = ps->num_threads; + else + new->num_threads = 0; + + /* Not Supported in Linux 2.6 or later. */ + new->tty_nr = 0; + new->itrealvalue = 0; + new->nswap = 0; + new->cnswap = 0; + + /* Temporarily set to 0 until correct + values are found .*/ + new->cminflt = 0; + new->cmajflt = 0; + new->rlim = 0; + new->startcode = 0; + new->endcode = 0; + new->startstack = 0; + new->kstkesp = 0; + new->kstkeip = 0; + new->signal = 0; + new->blocked = 0; + new->sigignore = 0; + new->sigcatch = 0; + new->wchan = 0; + new->exit_signal = 0; + new->processor = 0; + new->rt_priority = 0; + new->policy = 0; + new->delayacct_blkio_ticks = 0; + + *procfs_stat = new; + _proc_stat_free (ps); + + return err; +} + +/* Reads required process information from stat file + within the directory represented by pid. Return + the data in DATA and actual length to be written + in LEN. */ +error_t +procfs_read_stat_file (struct procfs_dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + error_t err; + char *stat_data; + struct procfs_stat *procfs_stat; + pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); + + err = get_stat_data (pid, &procfs_stat); + + if (asprintf (&stat_data, "%d (%s) %s %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %llu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu \n", + procfs_stat->pid, procfs_stat->comm, + procfs_stat->state, procfs_stat->ppid, + procfs_stat->pgid, procfs_stat->sid, + procfs_stat->tty_nr, procfs_stat->tty_pgrp, + procfs_stat->flags, procfs_stat->minflt, + procfs_stat->cminflt, procfs_stat->majflt, + procfs_stat->cmajflt, procfs_stat->utime, + procfs_stat->stime, procfs_stat->cutime, + procfs_stat->cstime, procfs_stat->priority, + procfs_stat->nice, procfs_stat->num_threads, + procfs_stat->itrealvalue, procfs_stat->starttime, + procfs_stat->vsize, BYTES_TO_PAGES(procfs_stat->rss), + procfs_stat->rlim, procfs_stat->startcode, + procfs_stat->endcode, procfs_stat->startstack, + procfs_stat->kstkesp, procfs_stat->kstkeip, + procfs_stat->signal, procfs_stat->blocked, + procfs_stat->sigignore, procfs_stat->sigcatch, + procfs_stat->wchan, procfs_stat->nswap, + procfs_stat->cnswap, procfs_stat->exit_signal, + procfs_stat->processor, procfs_stat->rt_priority, + procfs_stat->policy, + procfs_stat->delayacct_blkio_ticks) == -1) + return errno; + + + memcpy (data, stat_data, strlen(stat_data)); + *len = strlen (data); + + free (stat_data); + free (procfs_stat); + + return err; +} + +/* Reads required process's command line information + from cmline file within the directory represented + by pid. Return the data in DATA and actual length + to be written in LEN. */ +error_t +procfs_read_cmdline_file (struct procfs_dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *cmdline_data; + error_t err; + struct proc_stat *ps; + pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); + err = _proc_stat_create (pid, ps_context, &ps); + + err = set_field_value (ps, PSTAT_ARGS); + + if (! err) + if (asprintf (&cmdline_data, "%s \n", ps->args) == -1) + return errno; + + memcpy (data, cmdline_data, strlen(cmdline_data)); + *len = strlen (data); + + _proc_stat_free (ps); + free (cmdline_data); + return err; +} + +/* Reads required process's information that is represented by + stat and statm in a human readable format from status file + within the directory represented by pid. Return the data + in DATA and actual length to be written in LEN. */ +error_t +procfs_read_status_file (struct procfs_dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *status_data; + error_t err; + struct proc_stat *ps; + struct procfs_stat *procfs_stat; + + pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); + err = _proc_stat_create (pid, ps_context, &ps); + + err = get_stat_data (pid, &procfs_stat); + + if (! err) + if (asprintf (&status_data, "Name:\t%s\nState:\t%s\nTgid:\t%d\nPid:\t%d\n", procfs_stat->comm, procfs_stat->state, procfs_stat->pid, procfs_stat->pid) == -1) + return errno; + + memcpy (data, status_data, strlen(status_data)); + *len = strlen (data); + + _proc_stat_free (ps); + + free (status_data); + free (procfs_stat); + + return err; +} + +/* Reads required process information from statm file + within the directory represented by pid. Return + the data in DATA and actual length to be written + in LEN. */ +error_t +procfs_read_statm_file (struct procfs_dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *statm_data; + error_t err; + struct proc_stat *ps; + struct procfs_stat *procfs_stat; + + pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); + err = _proc_stat_create (pid, ps_context, &ps); + + err = get_stat_data (pid, &procfs_stat); + + if (! err) + if (asprintf (&statm_data, "%lu %ld %d %d %d %d %d\n", + BYTES_TO_PAGES(procfs_stat->vsize), + BYTES_TO_PAGES(procfs_stat->rss), + 0, 0, 0, 0, 0) == -1) + return errno; + + memcpy (data, statm_data, strlen(statm_data)); + *len = strlen (data); + + _proc_stat_free (ps); + + free (statm_data); + free (procfs_stat); + + return err; +} + +/* Reads required process information from each of files + within directory represented by pid, for files specified + by NODE. Return the data in DATA and actual length of + data in LEN. */ +error_t +procfs_read_files_contents (struct node *node, + off_t offset, size_t *len, void *data) +{ + error_t err; + + if (! strcmp (node->nn->dir_entry->name, "stat")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_read_nonpid_stat (node->nn->dir_entry, + offset, len, data); + else + err = procfs_read_stat_file (node->nn->dir_entry, + offset, len, data); + + if (! strcmp (node->nn->dir_entry->name, "cmdline")) + err = procfs_read_cmdline_file (node->nn->dir_entry, + offset, len, data); + + if (! strcmp (node->nn->dir_entry->name, "status")) + err = procfs_read_status_file (node->nn->dir_entry, + offset, len, data); + + if (! strcmp (node->nn->dir_entry->name, "statm")) + err = procfs_read_statm_file (node->nn->dir_entry, + offset, len, data); + + if (! strcmp (node->nn->dir_entry->name, "meminfo")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_read_nonpid_meminfo (node->nn->dir_entry, + offset, len, data); + else + err = ENOENT; + + if (! strcmp (node->nn->dir_entry->name, "loadavg")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_read_nonpid_loadavg (node->nn->dir_entry, + offset, len, data); + else + err = ENOENT; + + if (! strcmp (node->nn->dir_entry->name, "uptime")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_read_nonpid_uptime (node->nn->dir_entry, + offset, len, data); + else + err = ENOENT; + + if (! strcmp (node->nn->dir_entry->name, "version")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_read_nonpid_version (node->nn->dir_entry, + offset, len, data); + else + err = ENOENT; + + return err; +} diff --git a/procfs_dir.c b/procfs_dir.c deleted file mode 100644 index f76e6a4b..00000000 --- a/procfs_dir.c +++ /dev/null @@ -1,664 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - procfs_dir.c -- This file contains definitions to perform - directory operations such as creating, - removing and refreshing directories. - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You 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. - - A portion of the code in this file is based on ftpfs code - present in the hurd repositories copyrighted to FSF. The - Copyright notice from that file is given below. - - Copyright (C) 1997,98,2002 Free Software Foundation, Inc. - Written by Miles Bader - This file is part of the GNU Hurd. -*/ - - -#include -#include -#include -#include -#include - -#include "procfs.h" - -/* Initial HASHTABLE length for the new directories to be created. */ -#define INIT_HTABLE_LEN 5 - -struct procfs_dir_entry **cur_entry; - -/* Return in DIR a new procfs directory, in the filesystem FS, - with node NODE and path PATH. */ -error_t procfs_dir_create (struct procfs *fs, struct node *node, - const char *path, struct procfs_dir **dir) -{ - struct procfs_dir *new = malloc (sizeof (struct procfs_dir)); - if (!new) - return ENOMEM; - struct procfs_dir_entry **htable = calloc (INIT_HTABLE_LEN, - sizeof (struct procfs_dir_entry *)); - if (!htable) - return ENOMEM; - - /* Hold a reference to the new dir's node. */ - spin_lock (&netfs_node_refcnt_lock); - node->references++; - spin_unlock (&netfs_node_refcnt_lock); - - new->num_entries = 0; - new->num_live_entries = 0; - new->htable_len = INIT_HTABLE_LEN; - new->htable = htable; - new->ordered = NULL; - new->fs_path = path; - new->fs = fs; - new->node = node; - new->stat_timestamp = 0; - new->name_timestamp = 0; - - *dir = new; - - if (fs->root != 0) - node->nn->dir = new; - - return 0; -} - -/* Put the directory entry DIR_ENTRY into the hash table HTABLE. */ -static void -insert (struct procfs_dir_entry *dir_entry, - struct procfs_dir_entry **htable, size_t htable_len) -{ - struct procfs_dir_entry **new_htable = &htable[dir_entry->hv % htable_len]; - if (*new_htable) - (*new_htable)->self_p = &dir_entry->next; - dir_entry->next = *new_htable; - dir_entry->self_p = new_htable; - *new_htable = dir_entry; -} - -/* Calculate NAME's hash value. */ -static size_t -hash (const char *name) -{ - size_t hash_value = 0; - while (*name) - hash_value = ((hash_value << 5) + *name++) & 0xFFFFFF; - return hash_value; -} - -/* Extend the existing hashtable for DIR to accomodate values for new length - NEW_LEN. We retain all the previous entries. */ -static error_t -rehash (struct procfs_dir *dir, size_t new_len) -{ - int count; - size_t old_len = dir->htable_len; - struct procfs_dir_entry **old_htable = dir->htable; - struct procfs_dir_entry **new_htable = (struct procfs_dir_entry **) - malloc (new_len * sizeof (struct procfs_dir_entry *)); - - if (! new_htable) - return ENOMEM; - - bzero (new_htable, new_len * sizeof (struct procfs_dir_entry *)); - - for (count = 0; count < old_len; count++) - while (old_htable[count]) - { - struct procfs_dir_entry *dir_entry = old_htable[count]; - - /* Remove DIR_ENTRY from the old table */ - old_htable[count] = dir_entry->next; - - insert (dir_entry, new_htable, new_len); - } - - free (old_htable); - - dir->htable = new_htable; - dir->htable_len = new_len; - - return 0; -} - -/* Lookup NAME in DIR and return its entry. If there is no such entry, and - DNEW, the decision variable, is true, then a new entry is allocated and - returned, otherwise 0 is returned (if DNEW is true then 0 can be returned - if a memory allocation error occurs). */ -struct procfs_dir_entry * -lookup_entry (struct procfs_dir *dir, const char *name, int dnew) -{ - size_t hv = hash (name); - struct procfs_dir_entry *dir_entry = dir->htable[hv % dir->htable_len]; - - while (dir_entry && strcmp (name, dir_entry->name) != 0) - dir_entry = dir_entry->next; - - if (!dir_entry && dnew) - { - if (dir->num_entries > dir->htable_len) - /* Grow the hash table. */ - if (rehash (dir, (dir->htable_len + 1) * 2 - 1) != 0) - return 0; - - dir_entry = - (struct procfs_dir_entry *) malloc (sizeof (struct procfs_dir_entry)); - - if (dir_entry) - { - dir_entry->hv = hv; - dir_entry->name = strdup (name); - dir_entry->node = 0; - dir_entry->dir = dir; - dir_entry->stat_timestamp = 0; - bzero (&dir_entry->stat, sizeof dir_entry->stat); - dir_entry->symlink_target = 0; - dir_entry->noent = 0; - dir_entry->valid = 0; - dir_entry->name_timestamp = 0; - dir_entry->ordered_next = 0; - dir_entry->ordered_self_p = 0; - dir_entry->next = 0; - dir_entry->self_p = 0; - insert (dir_entry, dir->htable, dir->htable_len); - dir->num_entries++; - } - } - - return dir_entry; -} - - -/* Lookup NAME in DIR, returning its entry, or an error. - *NODE will contain the result node, locked, and with - an additional reference, or 0 if an error occurs. */ -error_t procfs_dir_lookup (struct procfs_dir *dir, const char *name, - struct node **node) -{ - struct procfs_dir_entry *dir_entry = 0; - error_t err = 0; - char *fs_path = dir->fs_path; - - struct timeval tv; - maptime_read (procfs_maptime, &tv); - - time_t timestamp = tv.tv_sec; - - if (*name == '\0' || strcmp (name, ".") == 0) - /* Current directory -- just add an additional reference to DIR's node - and return it. */ - { - netfs_nref (dir->node); - *node = dir->node; - return 0; - } - else if (strcmp (name, "..") == 0) - /* Parent directory. */ - { - if (dir->node->nn->dir_entry) - { - *node = dir->node->nn->dir_entry->dir->node; - mutex_lock (&(*node)->lock); - netfs_nref (*node); - } - else - { - err = ENOENT; /* No .. */ - *node = 0; - } - - mutex_unlock (&dir->node->lock); - - return err; - } - - err = procfs_dir_refresh (dir, dir->node == dir->fs->root); - if (!err && !dir_entry) - dir_entry = lookup_entry (dir, name, 0); - - if (! err) - { - if (dir_entry && !dir_entry->noent) - /* We've got a dir entry, get a node for it. */ - { - /* If there's already a node, add a ref so that it doesn't go - away. */ - spin_lock (&netfs_node_refcnt_lock); - if (dir_entry->node) - dir_entry->node->references++; - spin_unlock (&netfs_node_refcnt_lock); - - if (! dir_entry->node) - /* No node; make one and install it into E. */ - { - if (! fs_path) - err = EROFS; - - if (! err) - { - err = procfs_create_node (dir_entry, fs_path, &dir_entry->node); - - if (!err && dir->num_live_entries++ == 0) - /* Keep a reference to dir's node corresponding to - children. */ - { - spin_lock (&netfs_node_refcnt_lock); - dir->node->references++; - spin_unlock (&netfs_node_refcnt_lock); - } - } - } - - if (! err) - { - *node = dir_entry->node; - /* We have to unlock DIR's node before locking the child node - because the locking order is always child-parent. We know - the child node won't go away because we already hold the - additional reference to it. */ - mutex_unlock (&dir->node->lock); - mutex_lock (&dir_entry->node->lock); - } - } - else - err = ENOENT; - } - - if (err) - { - *node = 0; - mutex_unlock (&dir->node->lock); - } - -#if 0 - if (fs_path) - free (fs_path); -#endif - - return err; -} - -/* Lookup the null name in DIR, and return a node for it in NODE. Unlike - procfs_dir_lookup, this won't attempt to validate the existance of the - entry (to avoid opening a new connection if possible) -- that will happen - the first time the entry is refreshed. Also unlink ftpfs_dir_lookup, this - function doesn't expect DIR to be locked, and won't return *NODE locked. - This function is only used for bootstrapping the root node. */ -error_t -procfs_dir_null_lookup (struct procfs_dir *dir, struct node **node) -{ - struct procfs_dir_entry *dir_entry; - error_t err = 0; - - dir_entry = lookup_entry (dir, "", 1); - if (! dir_entry) - return ENOMEM; - - if (! dir_entry->noent) - /* We've got a dir entry, get a node for it. */ - { - /* If there's already a node, add a ref so that it doesn't go away. */ - spin_lock (&netfs_node_refcnt_lock); - if (dir_entry->node) - dir_entry->node->references++; - spin_unlock (&netfs_node_refcnt_lock); - - if (! dir_entry->node) - /* No node; make one and install it into DIR_ENTRY. */ - { - err = procfs_create_node (dir_entry, dir->fs_path, &dir_entry->node); - - if (!err && dir->num_live_entries++ == 0) - /* Keep a reference to dir's node corresponding to children. */ - { - spin_lock (&netfs_node_refcnt_lock); - dir->node->references++; - spin_unlock (&netfs_node_refcnt_lock); - } - } - - if (! err) - *node = dir_entry->node; - } - else - err = ENOENT; - - return err; -} - -/* Free the directory entry DIR_ENTRY and all resources it consumes. */ -void -free_entry (struct procfs_dir_entry *dir_entry) -{ - - assert (! dir_entry->self_p); /* We should only free deleted nodes. */ - free (dir_entry->name); - if (dir_entry->symlink_target) - free (dir_entry->symlink_target); - free (dir_entry->node->nn->dir); - free (dir_entry->node->nn); - free (dir_entry->node); - free (dir_entry); -} - -/* Remove DIR_ENTRY from its position in the ordered_next chain. */ -static void -ordered_unlink (struct procfs_dir_entry *dir_entry) -{ - if (dir_entry->ordered_self_p) - *dir_entry->ordered_self_p = dir_entry->ordered_next; - if (dir_entry->ordered_next) - dir_entry->ordered_next->self_p = dir_entry->ordered_self_p; -} - -/* Delete DIR_ENTRY from its directory, freeing any resources it holds. */ -static void -delete (struct procfs_dir_entry *dir_entry, struct procfs_dir *dir) -{ - dir->num_entries--; - - /* Take out of the hash chain. */ - if (dir_entry->self_p) - *dir_entry->self_p = dir_entry->next; - if (dir_entry->next) - dir_entry->next->self_p = dir_entry->self_p; - - /* Take out of the directory ordered list. */ - ordered_unlink (dir_entry); - - /* If there's a node attached, we'll delete the entry whenever it goes - away, otherwise, just delete it now. */ - if (! dir_entry->node) - free_entry (dir_entry); -} - -/* Make all the directory entries invalid */ -static void -make_dir_invalid (struct procfs_dir *dir) -{ - int count; - size_t len = dir->htable_len; - struct procfs_dir_entry **htable = dir->htable; - struct procfs_dir_entry *dir_entry; - - for (count = 0; count < len; count++) - { - dir_entry = htable[count]; - while (dir_entry) - { - dir_entry->valid = 0; - dir_entry = dir_entry->next; - } - } -} - -/* Delete any entries in DIR which don't have their valid bit set. */ -static void -sweep (struct procfs_dir *dir) -{ - size_t len = dir->htable_len, i; - struct procfs_dir_entry **htable = dir->htable, *dir_entry; - - for (i = 0; i < len; i++) - { - dir_entry = htable[i]; - while (dir_entry) - { - if (!dir_entry->valid && !dir_entry->noent && dir->num_entries) - delete (dir_entry, dir); - dir_entry = dir_entry->next; - } - if (htable[i]) - { - free (htable[i]); - htable[i] = 0; - } - - } - -} - -/* Remove the specified DIR and free all its allocated - storage. */ -void procfs_dir_entries_remove (struct procfs_dir *dir) -{ - /* Free all entries. */ - make_dir_invalid (dir); - sweep (dir); -} - -/* Checks if the DIR name is in list of - Active pids. */ -int is_in_pid_list (struct procfs_dir *dir) -{ - int dir_name; - int count; - pid_t *pids = NULL; - int pidslen = 0; - error_t err; - - if (dir->node->nn) - { - dir_name = atoi (dir->node->nn->dir_entry->name); - err = proc_getallpids (getproc (), &pids, &pidslen); - - for (count = 0; count < pidslen; ++count) - if (pids[count] == dir_name) - return 1; - } - - return 0; - -} - -/* Checks if DIR is a directory that - represents a pid. */ -int check_parent (struct procfs_dir *dir) -{ - if (dir == dir->fs->root) - return 0; - else - if (is_in_pid_list (dir)) - return 1; - else - return 0; - -} - -/* Refresh DIR. */ -error_t procfs_dir_refresh (struct procfs_dir *dir, int isroot) -{ - error_t err; - int is_parent_pid; - struct node *node; - - struct timeval tv; - maptime_read (procfs_maptime, &tv); - - time_t timestamp = tv.tv_sec; - cur_entry = &dir->ordered; - if (isroot) - err = procfs_fill_root_dir(dir, timestamp); - else - { - err = update_dir_entries (dir, timestamp); - is_parent_pid = check_parent (dir); - if (is_parent_pid) - err = procfs_create_files (dir, &node, timestamp); - } - - return err; -} - -/* Update the directory entry for NAME to reflect STAT and SYMLINK_TARGET. - This also creates a valid linked list of entries imposing ordering on - them. */ -struct procfs_dir_entry* -update_entries_list (struct procfs_dir *dir, const char *name, - const struct stat *stat, time_t timestamp, - const char *symlink_target) -{ - ino_t ino; - struct procfs_dir_entry *dir_entry = lookup_entry (dir, name, 1); - struct procfs *fs = dir->fs; - - if (! dir_entry) - return ENOMEM; - - if (dir_entry->stat.st_ino) - ino = dir_entry->stat.st_ino; - else - ino = fs->next_inode++; - - dir_entry->name_timestamp = timestamp; - - if (stat) - /* The ST and SYMLINK_TARGET parameters are only valid if ST isn't 0. */ - { - dir_entry->stat = *stat; - dir_entry->stat_timestamp = timestamp; - - if (!dir_entry->symlink_target || !symlink_target - || strcmp (dir_entry->symlink_target, symlink_target) != 0) - { - if (dir_entry->symlink_target) - free (dir_entry->symlink_target); - dir_entry->symlink_target = symlink_target ? strdup (symlink_target) : 0; - } - } - - /* The st_ino field is always valid. */ - dir_entry->stat.st_ino = ino; - dir_entry->stat.st_fsid = fs->fsid; - dir_entry->stat.st_fstype = PROCFILESYSTEM; - - dir_entry->valid = 1; - - if (! dir_entry->ordered_self_p) - /* Position DIR_ENTRY in the ordered chain following the previously seen entry. */ - { - /* The PREV_ENTRY_NEXT_P field holds a pointer to the NEXT-field of the - previous entry, or a pointer to the ORDERED field in the directory. */ - dir_entry->ordered_self_p = cur_entry; - - if (*dir_entry->ordered_self_p) - /* Update the self_p pointer of the previous successor. */ - (*dir_entry->ordered_self_p)->ordered_self_p = &dir_entry->ordered_next; - - /* DIR_ENTRY comes before the previous successor. */ - dir_entry->ordered_next = *dir_entry->ordered_self_p; - - *dir_entry->ordered_self_p = dir_entry; /* Put DIR_ENTRY there. */ - } - - /* Put the next entry after this one. */ - cur_entry = &dir_entry->ordered_next; - - return dir_entry; -} - -/* Fills DIR, the root directory with all the pids of - processes running in the system as directories. */ -error_t -procfs_fill_root_dir(struct procfs_dir *dir, time_t timestamp) -{ - error_t err; - char *data; - pid_t *pids; - int pidslen; - struct stat stat; - stat.st_mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | - S_IROTH | S_IXOTH; - stat.st_nlink = 1; - stat.st_size = 0; - - int count; - char *dir_name_pid; - struct node *node; - struct procfs_dir *new_dir; - struct procfs_dir_entry *dir_entry; - struct proc_stat *ps; - - pids = NULL; - pidslen = 0; - err = proc_getallpids (getproc (), &pids, &pidslen); - - if (!err) - { - for (count = 0; count < pidslen; count++) - { - if (asprintf (&dir_name_pid, "%d", pids[count]) == -1) - return errno; - -#if 0 - node = (struct node *) malloc (sizeof (struct node)); - new_dir = (struct procfs_dir *) malloc (sizeof (struct procfs_dir )); - - if (! node || ! new_dir ) - return ENOMEM; -#endif - err = _proc_stat_create (pids[count], ps_context, &ps); - if (! err) - { - err = set_field_value (ps, PSTAT_PROC_INFO); - if (! err) - { - stat.st_uid = proc_stat_proc_info (ps)->owner; - stat.st_gid = proc_stat_proc_info (ps)->pgrp; - - dir_entry = update_entries_list (dir, dir_name_pid, - &stat, timestamp, NULL); - err = procfs_create_node (dir_entry, dir_name_pid, &node); - - procfs_dir_create (dir->fs, node, - dir_name_pid, &new_dir); - free(dir_name_pid); - _proc_stat_free (ps); - } - } - } - } - - if ((err = procfs_create_uptime (dir, &node, timestamp)) != 0) - return err; - - if ((err = procfs_create_stat (dir, &node, timestamp)) != 0) - return err; - - if ((err = procfs_create_version (dir, &node, timestamp)) != 0) - return err; - - if ((err = procfs_create_meminfo (dir, &node, timestamp)) != 0) - return err; - - if ((err = procfs_create_loadavg (dir, &node, timestamp)) != 0) - return err; - - return 0; -} - -error_t update_dir_entries (struct procfs_dir *dir) -{ - /* STUB */ - return 0; -} diff --git a/procfs_nonpid_files.c b/procfs_nonpid_files.c deleted file mode 100644 index 2c1209ee..00000000 --- a/procfs_nonpid_files.c +++ /dev/null @@ -1,514 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - procfs_nonpid_files.c -- This file contains function definitions - to create and update the non-Per PID - files and their contents. - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You 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. - - A portion of the code in this file is based on vmstat.c code - present in the hurd repositories copyrighted to FSF. The - Copyright notice from that file is given below. - - Copyright (C) 1997,98,2002 Free Software Foundation, Inc. - Written by Miles Bader - This file is part of the GNU Hurd. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "procfs.h" - -typedef long long val_t; -#define BADVAL ((val_t) - 1LL) - -/* default pager port (must be privileged to fetch this). */ -mach_port_t def_pager; -struct default_pager_info def_pager_info; - -error_t procfs_create_uptime (struct procfs_dir *dir, - struct node **node, - time_t timestamp) -{ - int err; - char *file_name, *file_path; - struct procfs_dir_entry *dir_entry; - - if (asprintf (&file_name, "%s", "uptime") == -1) - return errno; - if (asprintf (&file_path, "%s", "uptime") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - - return err; -} - -error_t procfs_create_version(struct procfs_dir *dir, - struct node **node, - time_t timestamp) -{ - int err; - char *file_name, *file_path; - struct procfs_dir_entry *dir_entry; - - if (asprintf (&file_name, "%s", "version") == -1) - return errno; - if (asprintf (&file_path, "%s", "version") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - - return 0; -} - -error_t procfs_create_stat (struct procfs_dir *dir, - struct node **node, - time_t timestamp) -{ - int err; - char *file_name, *file_path; - struct procfs_dir_entry *dir_entry; - - if (asprintf (&file_name, "%s", "stat") == -1) - return errno; - if (asprintf (&file_path, "%s", "stat") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - - return err; -} - -error_t procfs_create_meminfo (struct procfs_dir *dir, - struct node **node, - time_t timestamp) -{ - int err; - char *file_name, *file_path; - struct procfs_dir_entry *dir_entry; - - if (asprintf (&file_name, "%s", "meminfo") == -1) - return errno; - if (asprintf (&file_path, "%s", "meminfo") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - - return err; -} - -error_t procfs_create_loadavg (struct procfs_dir *dir, - struct node **node, - time_t timestamp) -{ - int err; - char *file_name, *file_path; - struct procfs_dir_entry *dir_entry; - - if (asprintf (&file_name, "%s", "loadavg") == -1) - return errno; - if (asprintf (&file_path, "%s", "loadavg") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - - return err; -} - -error_t get_uptime (struct timeval *uptime) -{ - struct timeval boot_time, now; - error_t err; - struct proc_stat *ps; - - err = _proc_stat_create (1, ps_context, &ps); - - if (err) - return err; - - err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); - if (!err && !(ps->flags & PSTAT_TASK_BASIC)) - err = EGRATUITOUS; - - if (! err) - { - time_value_t *const tv = &proc_stat_task_basic_info (ps)->creation_time; - boot_time.tv_sec = tv->seconds; - boot_time.tv_usec = tv->microseconds; - if (gettimeofday (&now, 0) < 0) - error (0, errno, "gettimeofday"); - timersub (&now, &boot_time, uptime); - } - - _proc_stat_free (ps); - return err; -} - -error_t get_total_times (struct timeval *total_user_time, - struct timeval *total_system_time) -{ - error_t err; - pid_t *pids; - int pidslen = 0, count; - struct proc_stat *ps; - struct task_thread_times_info live_threads_times; - - struct timeval total_user_time_tmp; - struct timeval total_system_time_tmp; - struct timeval tmpval; - - timerclear (&total_user_time_tmp); - timerclear (&total_system_time_tmp); - - pids = NULL; - err = proc_getallpids (getproc (), &pids, &pidslen); - - if (!err) - for (count = 0; count < pidslen; count++) - { - err = _proc_stat_create (pids[count], ps_context, &ps); - if (err) - return err; - - err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); - if (!err && !(ps->flags & PSTAT_TASK_BASIC)) - err = EGRATUITOUS; - - if (! err) - { - tmpval.tv_sec = proc_stat_task_basic_info (ps)->user_time.seconds; - tmpval.tv_usec = proc_stat_task_basic_info (ps)->user_time.seconds; - timeradd (&total_user_time_tmp, &tmpval, &total_user_time_tmp); - - tmpval.tv_sec = proc_stat_task_basic_info (ps)->system_time.seconds; - tmpval.tv_usec = proc_stat_task_basic_info (ps)->system_time.seconds; - timeradd (&total_system_time_tmp, &tmpval, &total_system_time_tmp); - - error_t err = set_field_value (ps, PSTAT_TASK); - if (! err) - { - err = get_task_thread_times (ps->task, &live_threads_times); - if (! err) - { - tmpval.tv_sec = live_threads_times.user_time.seconds; - tmpval.tv_usec = live_threads_times.user_time.microseconds; - timeradd (&total_user_time_tmp, &tmpval, &total_user_time_tmp); - - tmpval.tv_sec = live_threads_times.system_time.seconds; - tmpval.tv_usec = live_threads_times.system_time.microseconds; - timeradd (&total_system_time_tmp, &tmpval, &total_system_time_tmp); - } - } - } - _proc_stat_free (ps); - } - - total_user_time->tv_sec = total_user_time_tmp.tv_sec; - total_user_time->tv_usec = total_user_time_tmp.tv_usec; - - total_system_time->tv_sec = total_system_time_tmp.tv_sec; - total_system_time->tv_usec = total_system_time_tmp.tv_usec; - - return err; -} - -error_t procfs_read_nonpid_stat (struct dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - char *stat_data; - error_t err; - jiffy_t total_user_time_jiffy, total_system_time_jiffy; - jiffy_t idle_time_jiffy; - struct timeval uptime, total_user_time, total_system_time; - struct timeval idle_time; - - err = get_uptime (&uptime); - - if (! err) - { - err = get_total_times (&total_user_time, &total_system_time); - - if (! err) - { - timersub (&uptime, &total_system_time, - &idle_time); - - total_user_time_jiffy = 100 * ((double) total_user_time.tv_sec + - (double) total_user_time.tv_usec / (1000 * 1000)); - total_system_time_jiffy = 100 * ((double) total_system_time.tv_sec + - (double) total_system_time.tv_usec / (1000 * 1000)); - idle_time_jiffy = 100 * ((double) idle_time.tv_sec + - (double) idle_time.tv_usec / (1000 * 1000)); - - if (asprintf (&stat_data, "cpu %llu %llu %llu %llu %llu %llu %d %d %d\n" - "cpu0 %llu %llu %llu %llu %llu %llu %d %d %d\n" - "intr %llu %llu %llu %llu %llu %llu %d %d %d\n", - total_user_time_jiffy, (long long unsigned) 0, - total_system_time_jiffy, idle_time_jiffy, - (long long unsigned) 0, (long long unsigned) 0, - 0, 0, 0, - total_user_time_jiffy, (long long unsigned) 0, - total_system_time_jiffy, idle_time_jiffy, - (long long unsigned) 0, (long long unsigned) 0, - 0, 0, 0, - (long long unsigned) 0, - (long long unsigned) 0, (long long unsigned) 0, (long long unsigned) 0, - (long long unsigned) 0, - (long long unsigned) 0, (long long unsigned) 0, - (long long unsigned) 0, (long long unsigned) 0) == -1) - return errno; - } - } - - memcpy (data, stat_data, strlen(stat_data)); - *len = strlen (data); - - free (stat_data); - return err; -} - -/* Makes sure the default pager port and associated - info exists, and returns 0 if not (after printing - an error). */ -static int -ensure_def_pager_info () -{ - error_t err; - - if (def_pager == MACH_PORT_NULL) - { - mach_port_t host; - - err = get_privileged_ports (&host, 0); - if (err == EPERM) - { - /* We are not root, so try opening the /servers file. */ - def_pager = file_name_lookup (_SERVERS_DEFPAGER, O_READ, 0); - if (def_pager == MACH_PORT_NULL) - { - error (0, errno, _SERVERS_DEFPAGER); - return 0; - } - } - if (def_pager == MACH_PORT_NULL) - { - if (err) - { - error (0, err, "get_privileged_ports"); - return 0; - } - - err = vm_set_default_memory_manager (host, &def_pager); - mach_port_deallocate (mach_task_self (), host); - - if (err) - { - error (0, err, "vm_set_default_memory_manager"); - return 0; - } - } - } - - if (!MACH_PORT_VALID (def_pager)) - { - if (def_pager == MACH_PORT_NULL) - { - error (0, 0, - "No default pager running, so no swap information available"); - def_pager = MACH_PORT_DEAD; /* so we don't try again */ - } - return 0; - } - - err = default_pager_info (def_pager, &def_pager_info); - if (err) - error (0, err, "default_pager_info"); - return (err == 0); -} - -#define SWAP_FIELD(getter, expr) \ - static val_t getter () \ - { return ensure_def_pager_info () ? (val_t) (expr) : BADVAL; } - -SWAP_FIELD (get_swap_size, def_pager_info.dpi_total_space) -SWAP_FIELD (get_swap_free, def_pager_info.dpi_free_space) -SWAP_FIELD (get_swap_page_size, def_pager_info.dpi_page_size) -SWAP_FIELD (get_swap_active, (def_pager_info.dpi_total_space - - def_pager_info.dpi_free_space)) - -error_t procfs_read_nonpid_meminfo (struct dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - char *meminfo_data; - error_t err; - struct vm_statistics vmstats; - - err = vm_statistics (mach_task_self (), &vmstats); - - unsigned long mem_size = ((vmstats.free_count + - vmstats.active_count + vmstats.inactive_count + - vmstats.wire_count) * vmstats.pagesize) / 1024; - - if (! err) - if (asprintf (&meminfo_data, "MemTotal:\t%lu kB\n" - "MemFree:\t%lu kB\n" - "Buffers:\t%ld kB\n" - "Cached:\t\t%ld kB\n" - "SwapCached:\t%ld kB\n" - "Active:\t\t%lu kB\n" - "Inactive:\t%lu kB\n" - "HighTotal:\t%lu kB\n" - "HighFree:\t%lu kB\n" - "LowTotal:\t%lu kB\n" - "LowFree:\t%lu kB\n" - "SwapTotal:\t%llu kB\n" - "SwapFree:\t%llu kB\n", - mem_size, (PAGES_TO_BYTES(vmstats.free_count)) / 1024 , 0, 0, 0, - (PAGES_TO_BYTES(vmstats.active_count)) / 1024, - (PAGES_TO_BYTES(vmstats.inactive_count)) / 1024, 0, 0, 0, 0, - get_swap_size () / 1024, get_swap_free () / 1024) == -1) - return errno; - - memcpy (data, meminfo_data, strlen(meminfo_data)); - *len = strlen (data); - - free (meminfo_data); - return err; -} - -error_t procfs_read_nonpid_loadavg (struct dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - char *loadavg_data; - error_t err; - processor_set_info_t info; - natural_t *count; - struct host_load_info *load; - mach_port_t host; - - err = ps_host_load_info (&load); - if (err) - error (0, err, "ps_host_load_info"); - - if (! err) - if (asprintf (&loadavg_data, "%.2f %.2f %.2f %d/%d %d\n", - (double)load->avenrun[0] / (double)LOAD_SCALE, - (double)load->avenrun[1] / (double)LOAD_SCALE, - (double)load->avenrun[2] / (double)LOAD_SCALE, 0, 0, 0) == -1) - return errno; - - memcpy (data, loadavg_data, strlen(loadavg_data)); - *len = strlen (data); - - free (loadavg_data); - return err; -} - -error_t procfs_read_nonpid_uptime (struct dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - char *uptime_data; - error_t err; - double uptime_secs, idle_time_secs; - - struct timeval uptime_val; - struct timeval uptime, total_user_time, total_system_time; - struct timeval idle_time; - - - err = get_uptime (&uptime); - if (! err) - { - err = get_total_times (&total_user_time, - &total_system_time); - if (! err) - { - timersub (&uptime, &total_system_time, - &idle_time); - - uptime_secs = (double) uptime.tv_sec + - (double) uptime.tv_usec / (1000 * 1000); - - idle_time_secs = (double) idle_time.tv_sec + - (double) idle_time.tv_usec / (1000 * 1000); - - if (asprintf (&uptime_data, "%.2f %.2f\n", - uptime_secs, idle_time_secs) == -1) - return errno; - } - } - - - memcpy (data, uptime_data, strlen(uptime_data)); - *len = strlen (data); - - free (uptime_data); - return err; -} - -error_t procfs_read_nonpid_version (struct dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - char *version_data; - error_t err = 0; - - if (asprintf (&version_data, "Linux version 2.6.18\n", NULL) == -1) - return errno; - - memcpy (data, version_data, strlen(version_data)); - *len = strlen (data); - - free (version_data); - return err; -} diff --git a/procfs_pid.h b/procfs_pid.h deleted file mode 100644 index 566c83ea..00000000 --- a/procfs_pid.h +++ /dev/null @@ -1,88 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - procfs_pid.h -- This is the header file of which contains defintions - for structure of directory with PID as the name and - structure of each file in this directory. - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You 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 __PROCFS_PID_H__ -#define __PROCFS_PID_H__ - -#include "procfs.h" - -struct procfs_pid_files -{ - struct procfs_cwd *procfs_cwd; - struct procfs_environ *procfs_environ; - struct procfs_cpu *procfs_cpu; - struct procfs_root *procfs_root; - struct procfs_exe *procfs_exe; - struct procfs_stat *_procfs_stat; - struct procfs_statm *procfs_statm; -}; - -struct procfs_stat -{ - pid_t pid; - char *comm; - char *state; - pid_t ppid; - pid_t pgid; - pid_t sid; - int tty_nr; - pid_t tty_pgrp; - unsigned flags; - long unsigned minflt; - long unsigned cminflt; - long unsigned majflt; - long unsigned cmajflt; - jiffy_t utime; - jiffy_t stime; - jiffy_t cutime; - jiffy_t cstime; - long priority; - long nice; - long num_threads; - long itrealvalue; - long long unsigned starttime; - long unsigned vsize; - long rss; - long unsigned rlim; - long unsigned startcode; - long unsigned endcode; - long unsigned startstack; - long unsigned kstkesp; - long unsigned kstkeip; - long unsigned signal; - long unsigned blocked; - long unsigned sigignore; - long unsigned sigcatch; - long unsigned wchan; - long unsigned nswap; - long unsigned cnswap; - int exit_signal; - int processor; - unsigned rt_priority; - unsigned policy; - long long unsigned delayacct_blkio_ticks; -}; - -#endif diff --git a/procfs_pid_files.c b/procfs_pid_files.c deleted file mode 100644 index 46861531..00000000 --- a/procfs_pid_files.c +++ /dev/null @@ -1,576 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - procfs_pid_files.c -- This file contains definitions to perform - file operations such as creating, writing to, - reading from and removing files that holds - information for each process with PID - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You 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. - - A portion of the code in this file is based on ftpfs code - present in the hurd repositories copyrighted to FSF. The - Copyright notice from that file is given below. - -*/ - -#include -#include -#include -#include -#include -#include - -#include "procfs_pid.h" - -/* Update the files named NAME within the directory named - PID also with SYMLINK TARGET if necessary. */ -struct procfs_dir_entry* -update_pid_entries (struct procfs_dir *dir, const char *name, - time_t timestamp, - const char *symlink_target) -{ - struct procfs_dir_entry *dir_entry; - struct stat *stat = (struct stat *) malloc (sizeof (struct stat)); - stat->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; - - dir_entry = update_entries_list (dir, name, stat, - timestamp, symlink_target); - - return dir_entry; -} - -/* Creates files to store process information for DIR - whose names are pids and returns these files in *NODE. */ -error_t -procfs_create_files (struct procfs_dir *dir, - struct node **node, - time_t timestamp) -{ - int err; - char *file_name, *file_path; - struct procfs_dir_entry *dir_entry; - - if (asprintf (&file_name, "%s", "stat") == -1) - return errno; - if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "stat") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - - if (asprintf (&file_name, "%s", "status") == -1) - return errno; - if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "status") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - - if (asprintf (&file_name, "%s", "cmdline") == -1) - return errno; - if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "cmdline") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - - if (asprintf (&file_name, "%s", "statm") == -1) - return errno; - if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "statm") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - -#if 0 - nodes_list = &node_stat; - nodes_list++; - node = nodes_list; -#endif - - return err; -} - -/* Check if the PSTAT_FLAG is set in the corresponding PS - structure, if not set it and check again and return error - status accordingly. */ -error_t set_field_value (struct proc_stat *ps, int pstat_flag) -{ - error_t err; - - if (! (ps->flags & pstat_flag)) - { - err = proc_stat_set_flags (ps, pstat_flag); - if (err) - return err; - - /* This second check is done since ps.h specifies to - do so since the previous call would not have set - the required value. */ - if (! (ps->flags & pstat_flag)) - return EGRATUITOUS; - } - - return 0; -} - -/* Adjusts TIME_VAL structure having Seconds and - Microseconds into the value in jiffies. The - value of jiffy is a hack to adjust to what - procps uses. */ -jiffy_t adjust_jiffy_time (time_value_t time_val) -{ - jiffy_t jiffy_time = time_val.seconds * JIFFY_ADJUST; - jiffy_time += (time_val.microseconds * JIFFY_ADJUST) - / (1000 * 1000); - - return jiffy_time; -} - -/* Extract the user and system time for the live threads of - the process. This information is directly retrieved from - MACH since neither libps not proc makes this available. */ -error_t get_task_thread_times (task_t task, - struct task_thread_times_info *live_threads_times) -{ - error_t err; - size_t tkcount = TASK_THREAD_TIMES_INFO_COUNT; - - err = task_info (task, TASK_THREAD_TIMES_INFO, - (task_info_t) live_threads_times, &tkcount); - if (err == MACH_SEND_INVALID_DEST) - err = ESRCH; - - return err; -} - -/* Obtains the User Time in UTIME and System Time in STIME from - MACH directly since this is neither made available by libps - nor by proc server. */ -error_t get_live_threads_time (struct proc_stat *ps, - jiffy_t *utime, jiffy_t *stime) -{ - struct task_thread_times_info live_threads_times; - error_t err = set_field_value (ps, PSTAT_TASK); - - if (! err) - { - err = get_task_thread_times (ps->task, &live_threads_times); - if (! err) - { - *utime = adjust_jiffy_time ( - live_threads_times.user_time); - *stime = adjust_jiffy_time ( - live_threads_times.system_time); - } - } - - return err; -} - -/* Get the data for stat file into the structure - PROCFS_STAT. */ -error_t get_stat_data (pid_t pid, - struct procfs_stat **procfs_stat) -{ - error_t err; - struct procfs_stat *new = (struct procfs_stat *) - malloc (sizeof (struct procfs_stat)); - - struct proc_stat *ps; - jiffy_t utime, stime; - - err = _proc_stat_create (pid, ps_context, &ps); - - new->pid = pid; - - if (! err) - { - err = set_field_value (ps, PSTAT_ARGS); - if (! err) - asprintf (&new->comm, "%s", ps->args); - } - - err = set_field_value (ps, PSTAT_STATE); - if (! err) - { - if (ps->state & PSTAT_STATE_P_STOP) - new->state = strdup ("T"); - if (ps->state & PSTAT_STATE_P_ZOMBIE) - new->state = strdup ("Z"); - if (ps->state & PSTAT_STATE_P_FG) - new->state = strdup ("+"); - if (ps->state & PSTAT_STATE_P_SESSLDR) - new->state = strdup ("s"); - if (ps->state & PSTAT_STATE_P_LOGINLDR) - new->state = strdup ("l"); - if (ps->state & PSTAT_STATE_P_FORKED) - new->state = strdup ("f"); - if (ps->state & PSTAT_STATE_P_NOMSG) - new->state = strdup ("m"); - if (ps->state & PSTAT_STATE_P_NOPARENT) - new->state = strdup ("p"); - if (ps->state & PSTAT_STATE_P_ORPHAN) - new->state = strdup ("o"); - if (ps->state & PSTAT_STATE_P_TRACE) - new->state = strdup ("x"); - if (ps->state & PSTAT_STATE_P_WAIT) - new->state = strdup ("w"); - if (ps->state & PSTAT_STATE_P_GETMSG) - new->state = strdup ("g"); - } - - err = set_field_value (ps, PSTAT_PROC_INFO); - if (! err) - { - new->ppid = ps->proc_info->ppid; - new->pgid = ps->proc_info->pgrp; - new->sid = ps->proc_info->session; - new->tty_pgrp = ps->proc_info->pgrp; - } - else - { - new->ppid = 0; - new->pgid = 0; - new->sid = 0; - new->tty_pgrp = 0; - } - - err = set_field_value (ps, PSTAT_STATE); - if (! err) - new->flags = ps->state; - else - new->flags = 0; - - err = set_field_value (ps, PSTAT_TASK_EVENTS); - if (! err) - { - new->minflt = ps->task_events_info->faults; - new->majflt = ps->task_events_info->pageins; - } - else - { - new->minflt = 0; - new->majflt = 0; - } - - /* This seems to be a bit inconsistent with setting of other - fields in this code. There are two reasons for this. - 1. The actual information required is not made available - by libps which should be directly obtained from MACH. - 2. The same code which is required to get the information - have to be reused in procfs_nonpid_files.c */ - err = get_live_threads_time (ps, &utime, &stime); - if (! err) - { - new->utime = utime; - new->stime = stime; - } - else - { - new->utime = 0; - new->stime = 0; - } - - err = set_field_value (ps, PSTAT_TASK_BASIC); - if (! err) - { - new->cutime = adjust_jiffy_time ( - ps->task_basic_info->user_time); - new->cstime = adjust_jiffy_time ( - ps->task_basic_info->system_time); - - new->priority = ps->task_basic_info->base_priority; - new->starttime = adjust_jiffy_time ( - ps->task_basic_info->creation_time); - - new->vsize = ps->task_basic_info->virtual_size; - new->rss = ps->task_basic_info->resident_size; - } - else - { - new->cutime = 0; - new->cstime = 0; - new->priority = 0; - new->starttime = 0; - new->vsize = 0; - new->rss = 0; - } - - new->nice = getpriority (0, pid); - - err = set_field_value (ps, PSTAT_NUM_THREADS); - if (! err) - new->num_threads = ps->num_threads; - else - new->num_threads = 0; - - /* Not Supported in Linux 2.6 or later. */ - new->tty_nr = 0; - new->itrealvalue = 0; - new->nswap = 0; - new->cnswap = 0; - - /* Temporarily set to 0 until correct - values are found .*/ - new->cminflt = 0; - new->cmajflt = 0; - new->rlim = 0; - new->startcode = 0; - new->endcode = 0; - new->startstack = 0; - new->kstkesp = 0; - new->kstkeip = 0; - new->signal = 0; - new->blocked = 0; - new->sigignore = 0; - new->sigcatch = 0; - new->wchan = 0; - new->exit_signal = 0; - new->processor = 0; - new->rt_priority = 0; - new->policy = 0; - new->delayacct_blkio_ticks = 0; - - *procfs_stat = new; - _proc_stat_free (ps); - - return err; -} - -/* Reads required process information from stat file - within the directory represented by pid. Return - the data in DATA and actual length to be written - in LEN. */ -error_t -procfs_read_stat_file (struct procfs_dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - error_t err; - char *stat_data; - struct procfs_stat *procfs_stat; - pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); - - err = get_stat_data (pid, &procfs_stat); - - if (asprintf (&stat_data, "%d (%s) %s %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %llu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu \n", - procfs_stat->pid, procfs_stat->comm, - procfs_stat->state, procfs_stat->ppid, - procfs_stat->pgid, procfs_stat->sid, - procfs_stat->tty_nr, procfs_stat->tty_pgrp, - procfs_stat->flags, procfs_stat->minflt, - procfs_stat->cminflt, procfs_stat->majflt, - procfs_stat->cmajflt, procfs_stat->utime, - procfs_stat->stime, procfs_stat->cutime, - procfs_stat->cstime, procfs_stat->priority, - procfs_stat->nice, procfs_stat->num_threads, - procfs_stat->itrealvalue, procfs_stat->starttime, - procfs_stat->vsize, BYTES_TO_PAGES(procfs_stat->rss), - procfs_stat->rlim, procfs_stat->startcode, - procfs_stat->endcode, procfs_stat->startstack, - procfs_stat->kstkesp, procfs_stat->kstkeip, - procfs_stat->signal, procfs_stat->blocked, - procfs_stat->sigignore, procfs_stat->sigcatch, - procfs_stat->wchan, procfs_stat->nswap, - procfs_stat->cnswap, procfs_stat->exit_signal, - procfs_stat->processor, procfs_stat->rt_priority, - procfs_stat->policy, - procfs_stat->delayacct_blkio_ticks) == -1) - return errno; - - - memcpy (data, stat_data, strlen(stat_data)); - *len = strlen (data); - - free (stat_data); - free (procfs_stat); - - return err; -} - -/* Reads required process's command line information - from cmline file within the directory represented - by pid. Return the data in DATA and actual length - to be written in LEN. */ -error_t -procfs_read_cmdline_file (struct procfs_dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - char *cmdline_data; - error_t err; - struct proc_stat *ps; - pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); - err = _proc_stat_create (pid, ps_context, &ps); - - err = set_field_value (ps, PSTAT_ARGS); - - if (! err) - if (asprintf (&cmdline_data, "%s \n", ps->args) == -1) - return errno; - - memcpy (data, cmdline_data, strlen(cmdline_data)); - *len = strlen (data); - - _proc_stat_free (ps); - free (cmdline_data); - return err; -} - -/* Reads required process's information that is represented by - stat and statm in a human readable format from status file - within the directory represented by pid. Return the data - in DATA and actual length to be written in LEN. */ -error_t -procfs_read_status_file (struct procfs_dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - char *status_data; - error_t err; - struct proc_stat *ps; - struct procfs_stat *procfs_stat; - - pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); - err = _proc_stat_create (pid, ps_context, &ps); - - err = get_stat_data (pid, &procfs_stat); - - if (! err) - if (asprintf (&status_data, "Name:\t%s\nState:\t%s\nTgid:\t%d\nPid:\t%d\n", procfs_stat->comm, procfs_stat->state, procfs_stat->pid, procfs_stat->pid) == -1) - return errno; - - memcpy (data, status_data, strlen(status_data)); - *len = strlen (data); - - _proc_stat_free (ps); - - free (status_data); - free (procfs_stat); - - return err; -} - -/* Reads required process information from statm file - within the directory represented by pid. Return - the data in DATA and actual length to be written - in LEN. */ -error_t -procfs_read_statm_file (struct procfs_dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - char *statm_data; - error_t err; - struct proc_stat *ps; - struct procfs_stat *procfs_stat; - - pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); - err = _proc_stat_create (pid, ps_context, &ps); - - err = get_stat_data (pid, &procfs_stat); - - if (! err) - if (asprintf (&statm_data, "%lu %ld %d %d %d %d %d\n", - BYTES_TO_PAGES(procfs_stat->vsize), - BYTES_TO_PAGES(procfs_stat->rss), - 0, 0, 0, 0, 0) == -1) - return errno; - - memcpy (data, statm_data, strlen(statm_data)); - *len = strlen (data); - - _proc_stat_free (ps); - - free (statm_data); - free (procfs_stat); - - return err; -} - -/* Reads required process information from each of files - within directory represented by pid, for files specified - by NODE. Return the data in DATA and actual length of - data in LEN. */ -error_t -procfs_read_files_contents (struct node *node, - off_t offset, size_t *len, void *data) -{ - error_t err; - - if (! strcmp (node->nn->dir_entry->name, "stat")) - if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_read_nonpid_stat (node->nn->dir_entry, - offset, len, data); - else - err = procfs_read_stat_file (node->nn->dir_entry, - offset, len, data); - - if (! strcmp (node->nn->dir_entry->name, "cmdline")) - err = procfs_read_cmdline_file (node->nn->dir_entry, - offset, len, data); - - if (! strcmp (node->nn->dir_entry->name, "status")) - err = procfs_read_status_file (node->nn->dir_entry, - offset, len, data); - - if (! strcmp (node->nn->dir_entry->name, "statm")) - err = procfs_read_statm_file (node->nn->dir_entry, - offset, len, data); - - if (! strcmp (node->nn->dir_entry->name, "meminfo")) - if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_read_nonpid_meminfo (node->nn->dir_entry, - offset, len, data); - else - err = ENOENT; - - if (! strcmp (node->nn->dir_entry->name, "loadavg")) - if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_read_nonpid_loadavg (node->nn->dir_entry, - offset, len, data); - else - err = ENOENT; - - if (! strcmp (node->nn->dir_entry->name, "uptime")) - if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_read_nonpid_uptime (node->nn->dir_entry, - offset, len, data); - else - err = ENOENT; - - if (! strcmp (node->nn->dir_entry->name, "version")) - if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_read_nonpid_version (node->nn->dir_entry, - offset, len, data); - else - err = ENOENT; - - return err; -} -- cgit v1.2.3