diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2010-08-01 12:43:52 +0200 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2010-08-01 12:45:12 +0200 |
commit | 2785afe572b463d578e023c6d4668aae888e09a5 (patch) | |
tree | 995dfb2f576d9c40d59d422f48127e25f1ef2cd3 /debian | |
parent | 9de2a32ced4076497e26ebfcffbd8c3ec260699b (diff) |
New upstream 20100701 snapshot.
- debian/patches/dir_acces_fix.patch: Remove patch, merged upstream.
- debian/patches/exec_fix.patch: Likewise.
- debian/patches/libdiskfs-rename.patch: Likewise.
- debian/patches/libpthread_mutex_owner.patch: Likewise.
- debian/patches/libpthread_recursive_mutex_initializer.patch: Likewise.
- debian/patches/libpthread_setcancel.patch: Likewise.
- debian/patches/pfinet-gcc-4.3-fix.patch: Likewise.
- debian/patches/procfs.patch: Likewise.
- debian/patches/libpthread_cancel_init.patch: Likewise
- debian/patches/libpthread_kill_0.patch: Likewise
- debian/patches/console_current_vcs.patch: Likewise
- debian/patches/hurd_console_startup.patch: Likewise
- debian/patches/MAKEDEV.patch: Likewise
- debian/patches/tmpfs.patch: Likewise
- debian/patches/libpthread_procfs.patch: New patch, to enable libpthread
and procfs build.
Diffstat (limited to 'debian')
-rw-r--r-- | debian/changelog | 22 | ||||
-rw-r--r-- | debian/patches/MAKEDEV.patch | 60 | ||||
-rw-r--r-- | debian/patches/console_current_vcs.patch | 61 | ||||
-rw-r--r-- | debian/patches/dir_acces_fix.patch | 15 | ||||
-rw-r--r-- | debian/patches/exec_fix.patch | 29 | ||||
-rw-r--r-- | debian/patches/ext2fs_large_stores.patch | 14 | ||||
-rw-r--r-- | debian/patches/libdiskfs-rename.patch | 27 | ||||
-rw-r--r-- | debian/patches/libpthread_cancel_init.patch | 29 | ||||
-rw-r--r-- | debian/patches/libpthread_kill_0.patch | 25 | ||||
-rw-r--r-- | debian/patches/libpthread_mutex_owner.patch | 22 | ||||
-rw-r--r-- | debian/patches/libpthread_procfs.patch | 23 | ||||
-rw-r--r-- | debian/patches/libpthread_recursive_mutex_initializer.patch | 297 | ||||
-rw-r--r-- | debian/patches/libpthread_setcancel.patch | 29 | ||||
-rw-r--r-- | debian/patches/pfinet-gcc-4.3-fix.patch | 36 | ||||
-rw-r--r-- | debian/patches/procfs.patch | 3218 | ||||
-rw-r--r-- | debian/patches/series | 14 | ||||
-rw-r--r-- | debian/patches/tmp_exec_startup.patch | 2 | ||||
-rw-r--r-- | debian/patches/tmpfs.patch | 21 |
18 files changed, 40 insertions, 3904 deletions
diff --git a/debian/changelog b/debian/changelog index 012087be..4971dfd9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,14 +1,18 @@ -hurd (20090404.1-1) UNRELEASED; urgency=low +hurd (20100701-1) UNRELEASED; urgency=low [ Samuel Thibault ] - * Cleaned upstream 20090404 snapshot. + * New upstream 20100701 snapshot. + - debian/patches/dir_acces_fix.patch: Remove patch, merged upstream. + - debian/patches/exec_fix.patch: Likewise. + - debian/patches/libdiskfs-rename.patch: Likewise. + - debian/patches/libpthread_mutex_owner.patch: Likewise. + - debian/patches/libpthread_recursive_mutex_initializer.patch: Likewise. + - debian/patches/libpthread_setcancel.patch: Likewise. + - debian/patches/pfinet-gcc-4.3-fix.patch: Likewise. + - debian/patches/procfs.patch: Likewise. + - debian/patches/libpthread_procfs.patch: New patch, to enable libpthread + and procfs build. * debian/rules: Really put debugging symbols into the hurd-dbg package. - * debian/patches/libpthread_cancel_init.patch: New patch to fix portability - of pthread.h - * debian/patches/libpthread_kill_0.patch: New patch to fix pthread_kill(th, - 0); - * debian/patches/console_current_vcs.patch: Cherry-pick patch to fix - loading the current_vcs driver. * debian/patches/hurd_console_startup.patch: Add -d current_vcs to enable /dev/cons/vcs by default. * debian/copyright: Reference /usr/share/common-licenses/GPL-2 instead of @@ -28,8 +32,6 @@ hurd (20090404.1-1) UNRELEASED; urgency=low ftpfs, hostmux, usermux, nfs, isofs.static, rpctrace, gcore, forks. Install local/runsystem.gnu in /libexec, install ext2fs.static in /boot * debian/rules: Do not ship *_pic.a, as mklibs breaks them. - * debian/patches/MAKEDEV.patch: Make MAKEDEV bash-free. - * debian/patches/tmpfs.patch: New patch to fix tmpfs crash. * debian/patches/proxy-defpager.diff: New patch to fix proxying defpager. * debian/patches/ext2fs_large_stores.patch: Apply Alioth fix #312328 from Fredrik Hammar to fix random startup crash (Closes: Bug#576519). diff --git a/debian/patches/MAKEDEV.patch b/debian/patches/MAKEDEV.patch deleted file mode 100644 index 8f130d0c..00000000 --- a/debian/patches/MAKEDEV.patch +++ /dev/null @@ -1,60 +0,0 @@ -commit 62e4f1a11b4598daa4a22fe3b868fde3c6fa818e -Author: Samuel Thibault <samuel.thibault@ens-lyon.org> -Date: Mon Jan 11 03:03:08 2010 +0100 - - Make MAKEDEV bash-free - - * sutils/MAKEDEV.sh (cmd, st, lose, mkdev): Remove function, add - (). - (mkdev): Use ${I#???} instead of ${I:3}. - ---- - MAKEDEV.sh | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/sutils/MAKEDEV.sh b/sutils/MAKEDEV.sh -index 260e93b..4277b05 100644 ---- a/sutils/MAKEDEV.sh -+++ b/sutils/MAKEDEV.sh -@@ -51,12 +51,12 @@ case "$#" in 0) - exit 1;; - esac - --function cmd { -+cmd() { - eval $ECHO "$@" - eval $EXEC "$@" - } - --function st { -+st() { - local NODE="$1" - local OWNER="$2" - local PERM="$3" -@@ -68,7 +68,7 @@ function st { - fi - } - --function lose { -+lose() { - local line - for line; do - echo 1>&2 "$0: $line" -@@ -76,7 +76,7 @@ function lose { - exit 1 - } - --function mkdev { -+mkdev() { - local I - for I; do - case $I in -@@ -120,7 +120,7 @@ function mkdev { - # ptys - [pt]ty[pqrstuvwxyzPQRS]?) - # Make one pty, both the master and slave halves. -- local id="${I:3}" -+ local id="${I#???}" - st pty$id root 666 /hurd/term ${DEVDIR}/pty$id \ - pty-master ${DEVDIR}/tty$id - st tty$id root 666 /hurd/term ${DEVDIR}/tty$id \ diff --git a/debian/patches/console_current_vcs.patch b/debian/patches/console_current_vcs.patch deleted file mode 100644 index c905677f..00000000 --- a/debian/patches/console_current_vcs.patch +++ /dev/null @@ -1,61 +0,0 @@ -commit 9291cd3fa6a76e999bc8dab25e9d5dc492403571 -Author: Samuel Thibault <samuel.thibault@ens-lyon.org> -Date: Sun Oct 25 20:55:04 2009 +0100 - - Fix current_vcs driver load - - * console-client/current-vcs.c (vcs_repeat_init): Rename function into... - (current_vcs_init): ... this. - (vcs_repeat_start): Rename function into... - (current_vcs_start): ... this. - (vcs_repeat_fini): Rename function into... - (current_vcs_fini): ... this. - ---- - console-client/current-vcs.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - ---- a/console-client/current-vcs.c -+++ b/console-client/current-vcs.c -@@ -167,7 +167,7 @@ static struct argp argp = {options, pars - - /* Initialize the current VCS driver. */ - static error_t --vcs_repeat_init (void **handle, int no_exit, int argc, char *argv[], int *next) -+current_vcs_init (void **handle, int no_exit, int argc, char *argv[], int *next) - { - error_t err; - int pos = 1; -@@ -184,7 +184,7 @@ vcs_repeat_init (void **handle, int no_e - } - - static error_t --vcs_repeat_start (void *handle) -+current_vcs_start (void *handle) - { - error_t err; - -@@ -206,7 +206,7 @@ vcs_repeat_start (void *handle) - } - - static error_t --vcs_repeat_fini (void *handle, int force) -+current_vcs_fini (void *handle, int force) - { - console_unregister_consnode (vcs_node); - console_destroy_consnode (vcs_node); -@@ -214,10 +214,10 @@ vcs_repeat_fini (void *handle, int force - } - - --struct driver_ops driver_vcs_repeat_ops = -+struct driver_ops driver_current_vcs_ops = - { -- vcs_repeat_init, -- vcs_repeat_start, -- vcs_repeat_fini -+ current_vcs_init, -+ current_vcs_start, -+ current_vcs_fini - }; - diff --git a/debian/patches/dir_acces_fix.patch b/debian/patches/dir_acces_fix.patch deleted file mode 100644 index 964b39a5..00000000 --- a/debian/patches/dir_acces_fix.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- - libfshelp/perms-access.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/libfshelp/perms-access.c -+++ b/libfshelp/perms-access.c -@@ -30,7 +30,7 @@ fshelp_access (struct stat *st, int op, - { - int gotit; - if (idvec_contains (user->uids, 0)) -- gotit = (op != S_IEXEC) || (st->st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)); -+ gotit = (op != S_IEXEC) || !S_ISREG(st->st_mode) || (st->st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)); - else if (user->uids->num == 0 && (st->st_mode & S_IUSEUNK)) - gotit = st->st_mode & (op << S_IUNKSHIFT); - else if (!fshelp_isowner (st, user)) diff --git a/debian/patches/exec_fix.patch b/debian/patches/exec_fix.patch deleted file mode 100644 index 2d53678a..00000000 --- a/debian/patches/exec_fix.patch +++ /dev/null @@ -1,29 +0,0 @@ -Fixes long-standing random hang of exec. - -2009-05-25 Samuel Thibault <samuel.thibault@ens-lyon.org> - - * exec.c (finish): Set FILE_DATA and MAP_BUFFER members of E to NULL - after freeing them. - ---- - exec/exec.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - ---- a/exec/exec.c -+++ b/exec/exec.c -@@ -1008,10 +1008,13 @@ finish (struct execdata *e, int dealloc_ - #ifdef EXECDATA_STREAM - fclose (&e->stream); - #else -- if (e->file_data != NULL) -+ if (e->file_data != NULL) { - free (e->file_data); -- else if (map_buffer (e) != NULL) -+ e->file_data = NULL; -+ } else if (map_buffer (e) != NULL) { - munmap (map_buffer (e), map_vsize (e)); -+ map_buffer (e) = NULL; -+ } - #endif - } - if (dealloc_file && e->file != MACH_PORT_NULL) diff --git a/debian/patches/ext2fs_large_stores.patch b/debian/patches/ext2fs_large_stores.patch index 7a78c4b7..0f7c6fd7 100644 --- a/debian/patches/ext2fs_large_stores.patch +++ b/debian/patches/ext2fs_large_stores.patch @@ -1907,27 +1907,17 @@ Support for >2GB volumes if (control != p->memobjcntl) { printf ("incg data request: wrong control port\n"); -@@ -67,14 +67,16 @@ _pager_seqnos_memory_object_data_request +@@ -67,9 +67,7 @@ _pager_seqnos_memory_object_data_request if (p->pager_state != NORMAL) { printf ("pager in wrong state for read\n"); - _pager_release_seqno (p, seqno); - mutex_unlock (&p->interlock); - goto allow_term_out; -+ _pager_allow_termination (p); -+ goto release_out; ++ goto allow_release_out; } err = _pager_pagemap_resize (p, offset + length); - if (err) -- goto release_out; /* Can't do much about the actual error. */ -+ { -+ _pager_allow_termination (p); -+ goto release_out; /* Can't do much about the actual error. */ -+ } - - /* If someone is paging this out right now, the disk contents are - unreliable, so we have to wait. It is too expensive (right now) to @@ -121,7 +123,8 @@ _pager_seqnos_memory_object_data_request goto error_read; diff --git a/debian/patches/libdiskfs-rename.patch b/debian/patches/libdiskfs-rename.patch deleted file mode 100644 index 2809e562..00000000 --- a/debian/patches/libdiskfs-rename.patch +++ /dev/null @@ -1,27 +0,0 @@ -Avoid a mutex deadlock by simply preventing '.' or '..' in source or target -operands. ---- - libdiskfs/dir-rename.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/libdiskfs/dir-rename.c -+++ b/libdiskfs/dir-rename.c -@@ -19,6 +19,7 @@ - - #include "priv.h" - #include "fs_S.h" -+#include <string.h> - - /* To avoid races in checkpath, and to prevent a directory from being - simultaneously renamed by two processes, we serialize all renames of -@@ -44,6 +45,10 @@ diskfs_S_dir_rename (struct protid *from - if (! tocred) - return EXDEV; - -+ if (!strcmp (fromname, ".") || !strcmp (fromname, "..") -+ || !strcmp (toname, ".") || !strcmp (toname, "..")) -+ return EINVAL; -+ - if (tocred->po->shadow_root != fromcred->po->shadow_root) - /* Same translator, but in different shadow trees. */ - return EXDEV; diff --git a/debian/patches/libpthread_cancel_init.patch b/debian/patches/libpthread_cancel_init.patch deleted file mode 100644 index 36351c15..00000000 --- a/debian/patches/libpthread_cancel_init.patch +++ /dev/null @@ -1,29 +0,0 @@ -commit d69e38ee77536912308212945cfb0b6abe93cef0 -Author: Samuel Thibault <samuel.thibault@ens-lyon.org> -Date: Tue Oct 13 20:15:08 2009 +0200 - - 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. - ---- - libpthread/sysdeps/generic/bits/cancelation.h | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/libpthread/sysdeps/generic/bits/cancelation.h -+++ b/libpthread/sysdeps/generic/bits/cancelation.h -@@ -38,9 +38,9 @@ struct __pthread_cancelation_handler **_ - = __pthread_get_cleanup_stack (); \ - struct __pthread_cancelation_handler __handler = \ - { \ -- handler: (rt), \ -- arg: (rtarg), \ -- next: *__handlers \ -+ (rt), \ -+ (rtarg), \ -+ *__handlers \ - }; \ - *__handlers = &__handler; - diff --git a/debian/patches/libpthread_kill_0.patch b/debian/patches/libpthread_kill_0.patch deleted file mode 100644 index 4aa307dc..00000000 --- a/debian/patches/libpthread_kill_0.patch +++ /dev/null @@ -1,25 +0,0 @@ -commit fb30b6bbf28d91667dcb9691dfeefffac4f99b82 -Author: Samuel Thibault <samuel.thibault@ens-lyon.org> -Date: Sun Oct 18 00:24:19 2009 +0200 - - 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. - ---- - libpthread/sysdeps/hurd/pt-kill.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/libpthread/sysdeps/hurd/pt-kill.c -+++ b/libpthread/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; diff --git a/debian/patches/libpthread_mutex_owner.patch b/debian/patches/libpthread_mutex_owner.patch deleted file mode 100644 index 466cffae..00000000 --- a/debian/patches/libpthread_mutex_owner.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- - libpthread/sysdeps/generic/pt-mutex-trylock.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/libpthread/sysdeps/generic/pt-mutex-trylock.c -+++ b/libpthread/sysdeps/generic/pt-mutex-trylock.c -@@ -34,6 +34,7 @@ __pthread_mutex_trylock (struct __pthrea - if (__pthread_spin_trylock (&mutex->__held) == 0) - /* Acquired the lock. */ - { -+#if defined(ALWAYS_TRACK_MUTEX_OWNER) - #ifndef NDEBUG - self = _pthread_self (); - if (self) -@@ -45,6 +46,7 @@ __pthread_mutex_trylock (struct __pthrea - mutex->owner = _pthread_self (); - } - #endif -+#endif - - if (mutex->attr) - switch (mutex->attr->mutex_type) diff --git a/debian/patches/libpthread_procfs.patch b/debian/patches/libpthread_procfs.patch new file mode 100644 index 00000000..5da9bfba --- /dev/null +++ b/debian/patches/libpthread_procfs.patch @@ -0,0 +1,23 @@ +diff --git a/Makefile b/Makefile +index 3194473..585d13a 100644 +--- a/Makefile ++++ b/Makefile +@@ -31,7 +31,8 @@ DIST_FILES = COPYING Makeconf config.make.in configure.in configure \ + # Hurd libraries + lib-subdirs = libshouldbeinlibc libihash libiohelp libports libthreads \ + libpager libfshelp libdiskfs libtrivfs libps \ +- libnetfs libpipe libstore libhurdbugaddr libftpconn libcons ++ libnetfs libpipe libstore libhurdbugaddr libftpconn libcons \ ++ libpthread + + # Hurd programs + prog-subdirs = auth proc exec init term \ +@@ -40,7 +41,7 @@ prog-subdirs = auth proc exec init term \ + login daemons nfsd boot console \ + hostmux usermux ftpfs trans \ + console-client utils sutils ufs-fsck ufs-utils \ +- benchmarks fstests ++ benchmarks fstests procfs + + # Other directories + other-subdirs = hurd doc config release include diff --git a/debian/patches/libpthread_recursive_mutex_initializer.patch b/debian/patches/libpthread_recursive_mutex_initializer.patch deleted file mode 100644 index 9b0f8d9c..00000000 --- a/debian/patches/libpthread_recursive_mutex_initializer.patch +++ /dev/null @@ -1,297 +0,0 @@ -Provide more mutex initializers ---- - libpthread/include/pthread/pthread.h | 2 ++ - libpthread/sysdeps/generic/bits/mutex-attr.h | 1 + - libpthread/sysdeps/generic/bits/mutex.h | 10 +++++++++- - libpthread/sysdeps/generic/pt-mutex-destroy.c | 3 ++- - libpthread/sysdeps/generic/pt-mutex-init.c | 11 ++++------- - libpthread/sysdeps/generic/pt-mutex-timedlock.c | 22 ++++++++++++++-------- - libpthread/sysdeps/generic/pt-mutex-transfer-np.c | 11 +++++++++-- - libpthread/sysdeps/generic/pt-mutex-trylock.c | 14 ++++++++++---- - libpthread/sysdeps/generic/pt-mutex-unlock.c | 16 +++++++++++----- - libpthread/sysdeps/generic/pt-mutexattr.c | 8 ++++++++ - 10 files changed, 70 insertions(+), 28 deletions(-) - ---- a/libpthread/include/pthread/pthread.h -+++ b/libpthread/include/pthread/pthread.h -@@ -313,6 +313,8 @@ extern int pthread_mutexattr_settype(pth - /* Static initializer for recursive mutexes. */ - - #ifdef __USE_GNU -+# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ -+ __PTHREAD_ERRORCHECK_MUTEX_INITIALIZER - # define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ - __PTHREAD_RECURSIVE_MUTEX_INITIALIZER - #endif ---- a/libpthread/sysdeps/generic/pt-mutex-destroy.c -+++ b/libpthread/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 ---- a/libpthread/sysdeps/generic/pt-mutex-init.c -+++ b/libpthread/sysdeps/generic/pt-mutex-init.c -@@ -35,14 +35,11 @@ _pthread_mutex_init (pthread_mutex_t *mu - /* The default attributes. */ - return 0; - -- if (attr == &__pthread_recursive_mutexattr) -- /* Non-default but known attributes. */ -- { -- mutex->attr = attr; -- return 0; -- } -+ if (! mutex->attr -+ || mutex->attr == __PTHREAD_ERRORCHECK_MUTEXATTR -+ || mutex->attr == __PTHREAD_RECURSIVE_MUTEXATTR) -+ mutex->attr = malloc (sizeof *attr); - -- mutex->attr = malloc (sizeof *attr); - if (! mutex->attr) - return ENOMEM; - ---- a/libpthread/sysdeps/generic/pt-mutex-timedlock.c -+++ b/libpthread/sysdeps/generic/pt-mutex-timedlock.c -@@ -31,6 +31,12 @@ __pthread_mutex_timedlock_internal (stru - 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 (stru - #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 (stru - 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 (stru - } - 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 (stru - } - - #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 (stru - __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; ---- a/libpthread/sysdeps/generic/pt-mutex-transfer-np.c -+++ b/libpthread/sysdeps/generic/pt-mutex-transfer-np.c -@@ -29,13 +29,20 @@ __pthread_mutex_transfer_np (struct __pt - 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 __pt - - #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; ---- a/libpthread/sysdeps/generic/pt-mutex-trylock.c -+++ b/libpthread/sysdeps/generic/pt-mutex-trylock.c -@@ -29,6 +29,12 @@ __pthread_mutex_trylock (struct __pthrea - { - 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 __pthrea - #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 __pthrea - - err = EBUSY; - -- if (mutex->attr) -+ if (attr) - { - self = _pthread_self (); -- switch (mutex->attr->mutex_type) -+ switch (attr->mutex_type) - { - case PTHREAD_MUTEX_NORMAL: - break; ---- a/libpthread/sysdeps/generic/pt-mutex-unlock.c -+++ b/libpthread/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 - #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 - 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 - - #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; ---- a/libpthread/sysdeps/generic/pt-mutexattr.c -+++ b/libpthread/sysdeps/generic/pt-mutexattr.c -@@ -28,6 +28,14 @@ const struct __pthread_mutexattr __pthre - 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, ---- a/libpthread/sysdeps/generic/bits/mutex.h -+++ b/libpthread/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. */ ---- a/libpthread/sysdeps/generic/bits/mutex-attr.h -+++ b/libpthread/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/debian/patches/libpthread_setcancel.patch b/debian/patches/libpthread_setcancel.patch deleted file mode 100644 index 601a698f..00000000 --- a/debian/patches/libpthread_setcancel.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- - libpthread/pthread/pt-setcancelstate.c | 3 ++- - libpthread/pthread/pt-setcanceltype.c | 3 ++- - 2 files changed, 4 insertions(+), 2 deletions(-) - ---- a/libpthread/pthread/pt-setcancelstate.c -+++ b/libpthread/pthread/pt-setcancelstate.c -@@ -35,7 +35,8 @@ pthread_setcancelstate (int state, int * - break; - } - -- *oldstate = p->cancel_state; -+ if (oldstate) -+ *oldstate = p->cancel_state; - p->cancel_state = state; - - return 0; ---- a/libpthread/pthread/pt-setcanceltype.c -+++ b/libpthread/pthread/pt-setcanceltype.c -@@ -35,7 +35,8 @@ pthread_setcanceltype (int type, int *ol - break; - } - -- *oldtype = p->cancel_type; -+ if (oldtype) -+ *oldtype = p->cancel_type; - p->cancel_type = type; - - return 0; diff --git a/debian/patches/pfinet-gcc-4.3-fix.patch b/debian/patches/pfinet-gcc-4.3-fix.patch deleted file mode 100644 index fbc31da9..00000000 --- a/debian/patches/pfinet-gcc-4.3-fix.patch +++ /dev/null @@ -1,36 +0,0 @@ -commit acb9f2e4bc53e0483e53549379c9c5631e452334 -Author: Samuel Thibault <samuel.thibault@ens-lyon.org> -Date: Sat Sep 26 21:29:00 2009 +0200 - - Add memory clobbers to assembly snippets - - * pfinet/linux-src/include/asm-i386/checksum.h (ip_fast_csum): - Add memory clobber to assembly snippet. - (csum_ipv6_magic): Likewise. - ---- - pfinet/linux-src/include/asm-i386/checksum.h | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/pfinet/linux-src/include/asm-i386/checksum.h -+++ b/pfinet/linux-src/include/asm-i386/checksum.h -@@ -109,7 +109,8 @@ static inline unsigned short ip_fast_csu - are modified, we must also specify them as outputs, or gcc - will assume they contain their original values. */ - : "=r" (sum), "=r" (iph), "=r" (ihl) -- : "1" (iph), "2" (ihl)); -+ : "1" (iph), "2" (ihl) -+ : "memory"); - return(sum); - } - -@@ -185,7 +186,8 @@ static __inline__ unsigned short int csu - "adcl $0, %0\n" - : "=&r" (sum) - : "r" (saddr), "r" (daddr), -- "r"(htonl((__u32) (len))), "r"(htonl(proto)), "0"(sum)); -+ "r"(htonl((__u32) (len))), "r"(htonl(proto)), "0"(sum) -+ : "memory"); - - return csum_fold(sum); - } diff --git a/debian/patches/procfs.patch b/debian/patches/procfs.patch deleted file mode 100644 index 941c5507..00000000 --- a/debian/patches/procfs.patch +++ /dev/null @@ -1,3218 +0,0 @@ -Madhusudan's experimental procfs server for Linux-like /proc ---- - Makefile | 2 - procfs/ChangeLog | 161 ++++++++++ - procfs/Makefile | 30 + - procfs/bootstrap.c | 95 ++++++ - procfs/netfs.c | 466 ++++++++++++++++++++++++++++++ - 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 +++++++++++++++++++++++++++++++++++++ - 12 files changed, 3159 insertions(+), 1 deletion(-) - ---- /dev/null -+++ b/procfs/ChangeLog -@@ -0,0 +1,161 @@ -+2008-08-30 Madhusudan.C.S <madhusudancs@gmail.com> -+ -+ * 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 <madhusudancs@gmail.com> -+ -+ * AUTHORS: File removed. -+ * COPYING: Likewise. -+ * README: Likewise. -+ -+2008-08-29 Madhusudan.C.S <madhusudancs@gmail.com> -+ -+ * 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 <madhusudancs@gmail.com> -+ -+ * 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 <madhusudancs@gmail.com> -+ -+ * README: Initial Documentation. -+ -+2008-08-18 Madhusudan.C.S <madhusudancs@gmail.com> -+ -+ * 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 <madhusudancs@gmail.com> -+ -+ * 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 <madhusudancs@gmail.com> -+ -+ * 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 <madhusudancs@gmail.com> -+ -+ * 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 <madhusudancs@gmail.com> -+ -+ * /sources/hurd/procfs: New directory added to the repository. ---- /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 ---- /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 <stddef.h> -+#include <hurd/ihash.h> -+#include <hurd/netfs.h> -+ -+#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; -+} -+ ---- /dev/null -+++ b/procfs/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 <stddef.h> -+#include <stdlib.h> -+#include <fcntl.h> -+#include <unistd.h> -+#include <dirent.h> -+#include <string.h> -+ -+#include <sys/mman.h> -+#include <sys/stat.h> -+#include <hurd/netfs.h> -+ -+#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); -+} -+ ---- /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 <stdio.h> -+#include <stdlib.h> -+#include <fcntl.h> -+#include <string.h> -+#include <errno.h> -+#include <hurd/ihash.h> -+#include <hurd/fshelp.h> -+#include <hurd/iohelp.h> -+ -+#include <hurd/netfs.h> -+ -+#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; -+} ---- /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 <stdio.h> -+#include <argp.h> -+#include <string.h> -+#include <stdlib.h> -+ -+#include <unistd.h> -+#include <error.h> -+#include <sys/stat.h> -+#include <hurd/netfs.h> -+ -+#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; -+} ---- /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 <miles@gnu.org> -+ 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 <stdlib.h> -+#include <unistd.h> -+#include <cthreads.h> -+#include <maptime.h> -+#include <hurd/ihash.h> -+#include <ps.h> -+ -+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__ */ ---- /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 <miles@gnu.org> -+ This file is part of the GNU Hurd. -+*/ -+ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <hurd/netfs.h> -+#include <hurd/ihash.h> -+#include <sys/stat.h> -+ -+#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); -+ } -+ _proc_stat_free (ps); -+ } -+ 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; -+} ---- /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 <miles@gnu.org> -+ This file is part of the GNU Hurd. -+*/ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <hurd/netfs.h> -+#include <hurd/ihash.h> -+#include <fcntl.h> -+#include <sys/stat.h> -+#include <sys/sysinfo.h> -+#include <mach/vm_statistics.h> -+#include <mach/default_pager.h> -+#include <hurd.h> -+#include <hurd/paths.h> -+#include <mach.h> -+#include <ps.h> -+#include <time.h> -+ -+#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; -+} ---- /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 ---- /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 <hurd/netfs.h> -+#include <fcntl.h> -+#include <string.h> -+#include <stdio.h> -+#include <mach/task_info.h> -+#include <sys/resource.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 = {}; -+ 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; -+} ---- a/Makefile -+++ b/Makefile -@@ -41,7 +41,7 @@ prog-subdirs = auth proc exec init term - login daemons nfsd boot console \ - hostmux usermux ftpfs trans \ - console-client utils sutils ufs-fsck ufs-utils \ -- benchmarks fstests -+ benchmarks fstests procfs - - # Other directories - other-subdirs = hurd doc config release include diff --git a/debian/patches/series b/debian/patches/series index 02c62bdc..bdc0719d 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -5,13 +5,11 @@ hurd_console_startup.patch init_try_runsystem.gnu.patch install-msgids.diff libpager_update_seqno.patch -libpthread_mutex_owner.patch libpthread_stubs.patch libpthread_tls.patch makedev.diff pfinet_dhcp.patch pflocal.patch -procfs.patch rc.patch runsystem_setup_pflocal.patch startup-usr-support.patch @@ -19,18 +17,8 @@ tmp_exec_startup.patch ttys.patch uptime_w_path_fix.patch stat_round.patch -dir_acces_fix.patch libports_stability.patch libpthread_fix.patch -libpthread_setcancel.patch extern_inline_fix.patch -exec_fix.patch -libpthread_recursive_mutex_initializer.patch -pfinet-gcc-4.3-fix.patch -MAKEDEV.patch -libdiskfs-rename.patch -libpthread_cancel_init.patch -libpthread_kill_0.patch -console_current_vcs.patch -tmpfs.patch proxy-defpager.diff +libpthread_procfs.patch diff --git a/debian/patches/tmp_exec_startup.patch b/debian/patches/tmp_exec_startup.patch index 0c77b16d..bd605718 100644 --- a/debian/patches/tmp_exec_startup.patch +++ b/debian/patches/tmp_exec_startup.patch @@ -1,4 +1,6 @@ Also try /tmp/exec as it's used for installation. + +TODO: not used by d-i. Is it used by crosshurd? --- libdiskfs/boot-start.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/debian/patches/tmpfs.patch b/debian/patches/tmpfs.patch deleted file mode 100644 index 63e4de37..00000000 --- a/debian/patches/tmpfs.patch +++ /dev/null @@ -1,21 +0,0 @@ -commit 97c5690abeaa88767acf2ffbb55552e8278052c8 -Author: Samuel Thibault <samuel.thibault@ens-lyon.org> -Date: Mon Jan 11 03:34:50 2010 +0100 - - Fix tmpfs assertion - - * tmpfs/tmpfs.h (tmpfs_dirent): Add padding field to push the - name field after its position in struct dirent. - -diff --git a/tmpfs/tmpfs.h b/tmpfs/tmpfs.h -index 3032ce3..a0e1f7a 100644 ---- a/tmpfs/tmpfs.h -+++ b/tmpfs/tmpfs.h -@@ -64,6 +64,7 @@ struct tmpfs_dirent - { - struct tmpfs_dirent *next; - struct disknode *dn; -+ uint32_t pad; - uint8_t namelen; - char name[0]; - }; |