diff options
Diffstat (limited to 'hurd')
-rw-r--r-- | hurd/Versions | 7 | ||||
-rw-r--r-- | hurd/hurd.h | 6 | ||||
-rw-r--r-- | hurd/hurdlookup.c | 88 | ||||
-rw-r--r-- | hurd/report-wait.c | 122 |
4 files changed, 190 insertions, 33 deletions
diff --git a/hurd/Versions b/hurd/Versions index f3e311b2a9..5dcdc355d9 100644 --- a/hurd/Versions +++ b/hurd/Versions @@ -107,4 +107,11 @@ libc { # s* seteuids; } + GLIBC_2.1.3 { + # d* + directory_name_split; + + # h* + hurd_directory_name_split; + } } diff --git a/hurd/hurd.h b/hurd/hurd.h index 9ef6834776..e9c2db8152 100644 --- a/hurd/hurd.h +++ b/hurd/hurd.h @@ -180,6 +180,12 @@ extern int seteuids (int __n, const uid_t *__uidset); extern file_t __file_name_split (const char *file, char **name); extern file_t file_name_split (const char *file, char **name); +/* Split DIRECTORY into a parent directory and a name within the directory. + This is the same as file_name_split, but ignores trailing slashes. */ + +extern file_t __directory_name_split (const char *file, char **name); +extern file_t directory_name_split (const char *file, char **name); + /* Open a port to FILE with the given FLAGS and MODE (see <fcntl.h>). The file lookup uses the current root and working directory. Returns a port to the file if successful; otherwise sets `errno' diff --git a/hurd/hurdlookup.c b/hurd/hurdlookup.c index 0714e4aa86..7e5f9afa99 100644 --- a/hurd/hurdlookup.c +++ b/hurd/hurdlookup.c @@ -429,6 +429,81 @@ __hurd_file_name_split (error_t (*use_init_port) } weak_alias (__hurd_file_name_split, hurd_file_name_split) +/* This is the same as hurd_file_name_split, except that it ignores + trailing slashes (so *NAME is never ""). */ +error_t +__hurd_directory_name_split (error_t (*use_init_port) + (int which, error_t (*operate) (file_t)), + file_t (*get_dtable_port) (int fd), + error_t (*lookup) + (file_t dir, char *name, int flags, mode_t mode, + retry_type *do_retry, string_t retry_name, + mach_port_t *result), + const char *file_name, + file_t *dir, char **name) +{ + error_t addref (file_t crdir) + { + *dir = crdir; + return __mach_port_mod_refs (__mach_task_self (), + crdir, MACH_PORT_RIGHT_SEND, +1); + } + + const char *lastslash = strrchr (file_name, '/'); + + if (lastslash != NULL && lastslash[1] == '\0') + { + /* Trailing slash doesn't count. Look back further. */ + + /* Back up over all trailing slashes. */ + while (lastslash > file_name && *lastslash == '/') + --lastslash; + + /* Find the last one earlier in the string, before the trailing ones. */ +#if __GLIBC__ > 2 || __GLIBC_MINOR__ >= 2 + lastslash = __memrchr (file_name, '/', lastslash - file_name); +#else + /* Keep backing up, looking for a slash. */ + do + if (lastslash == file_name) + { + /* Hit the start with no slash. */ + lastslash = NULL; + break; + } + while (*lastslash-- != '/'); +#endif + } + + if (lastslash != NULL) + { + if (lastslash == file_name) + { + /* "/foobar" => crdir + "foobar". */ + *name = (char *) file_name + 1; + return (*use_init_port) (INIT_PORT_CRDIR, &addref); + } + else + { + /* "/dir1/dir2/.../file". */ + char dirname[lastslash - file_name + 1]; + memcpy (dirname, file_name, lastslash - file_name); + dirname[lastslash - file_name] = '\0'; + *name = (char *) lastslash + 1; + return + __hurd_file_name_lookup (use_init_port, get_dtable_port, lookup, + dirname, 0, 0, dir); + } + } + else + { + /* "foobar" => cwdir + "foobar". */ + *name = (char *) file_name; + return (*use_init_port) (INIT_PORT_CWDIR, &addref); + } +} +weak_alias (__hurd_directory_name_split, hurd_directory_name_split) + file_t __file_name_lookup (const char *file_name, int flags, mode_t mode) @@ -458,6 +533,19 @@ __file_name_split (const char *file_name, char **name) } weak_alias (__file_name_split, file_name_split) +file_t +__directory_name_split (const char *directory_name, char **name) +{ + error_t err; + file_t result; + + err = __hurd_directory_name_split (&_hurd_ports_use, &__getdport, 0, + directory_name, &result, name); + + return err ? (__hurd_fail (err), MACH_PORT_NULL) : result; +} +weak_alias (__directory_name_split, directory_name_split) + file_t __file_name_lookup_under (file_t startdir, diff --git a/hurd/report-wait.c b/hurd/report-wait.c index e8f4f1af4a..41fdca1619 100644 --- a/hurd/report-wait.c +++ b/hurd/report-wait.c @@ -1,5 +1,5 @@ /* Report on what a thread in our task is waiting for. - Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -26,51 +26,57 @@ #include "thread_state.h" #include "intr-msg.h" -static void -describe_number (string_t description, const char *flavor, unsigned long int i) +static char * +describe_number (string_t description, const char *flavor, long int i) { unsigned long int j; - char *p = __stpcpy (description, flavor); + char *p = flavor ? description : __stpcpy (description, flavor); + char *end; + + /* Handle sign. */ + if (i < 0) + { + i = -i; + *p++ = '-'; + } /* Allocate space for the number at the end of DESCRIPTION. */ for (j = i; j >= 10; j /= 10) p++; - p[1] = '\0'; + end = p + 1; + *end = '\0'; do { *p-- = '0' + i % 10; i /= 10; } while (i != 0); - assert (*p == '#'); + + return end; } -static void +static char * describe_port (string_t description, mach_port_t port) { int i; + if (port == MACH_PORT_NULL) + return __stpcpy (description, "(null)"); + if (port == MACH_PORT_DEAD) + return __stpcpy (description, "(dead)"); + if (port == __mach_task_self ()) - { - strcpy (description, "task-self"); - return; - } + return __stpcpy (description, "task-self"); for (i = 0; i < _hurd_nports; ++i) if (port == _hurd_ports[i].port) - { - describe_number (description, "init#", i); - return; - } + return describe_number (description, "init#", i); if (_hurd_init_dtable) { for (i = 0; i < _hurd_init_dtablesize; ++i) if (port == _hurd_init_dtable[i]) - { - describe_number (description, "fd#", i); - return; - } + return describe_number (description, "fd#", i); } else if (_hurd_dtable) { @@ -78,18 +84,12 @@ describe_port (string_t description, mach_port_t port) if (_hurd_dtable[i] == NULL) continue; else if (port == _hurd_dtable[i]->port.port) - { - describe_number (description, "fd#", i); - return; - } + return describe_number (description, "fd#", i); else if (port == _hurd_dtable[i]->ctty.port) - { - describe_number (description, "bgfd#", i); - return; - } + return describe_number (description, "bgfd#", i); } - describe_number (description, "port#", port); + return describe_number (description, "port#", port); } @@ -146,12 +146,68 @@ _S_msg_report_wait (mach_port_t msgport, thread_t thread, assert (count == MACHINE_THREAD_STATE_COUNT); if (SYSCALL_EXAMINE (&state, msgid)) { + mach_port_t send_port, rcv_port; + mach_msg_option_t option; + mach_msg_timeout_t timeout; + /* Blocked in a system call. */ - if (*msgid == -25) - /* mach_msg system call. Examine its parameters. */ - describe_port (description, MSG_EXAMINE (&state, msgid)); - else - strcpy (description, "kernel"); + if (*msgid == -25 + /* mach_msg system call. Examine its parameters. */ + && MSG_EXAMINE (&state, msgid, &send_port, &rcv_port, + &option, &timeout) == 0) + { + char *p; + if (send_port != MACH_PORT_NULL && *msgid != 0) + { + /* For the normal case of RPCs, we consider the + destination port to be the interesting thing + whether we are in fact sending or receiving at the + moment. That tells us who we are waiting for the + reply from. */ + if (send_port == ss->intr_port) + { + /* This is a Hurd interruptible RPC. + Mark it by surrounding the port description + string with [...] brackets. */ + description[0] = '['; + p = describe_port (description + 1, send_port); + *p++ = ']'; + *p = '\0'; + } + else + (void) describe_port (description, send_port); + } + else if (rcv_port != MACH_PORT_NULL) + { + /* This system call had no send port, but had a + receive port. The msgid we extracted is then just + some garbage or perhaps the msgid of the last + message this thread received, but it's not a + helpful thing to return. */ + strcpy (describe_port (description, rcv_port), ":rcv"); + *msgid = 0; + } + else if ((option & (MACH_RCV_MSG|MACH_RCV_TIMEOUT)) + == (MACH_RCV_MSG|MACH_RCV_TIMEOUT)) + { + /* A receive with no valid port can be used for a + pure timeout. Report the timeout value (counted + in milliseconds); note this is the original total + time, not the time remaining. */ + strcpy (describe_number (description, 0, timeout), "ms"); + *msgid = 0; + } + else + { + strcpy (description, "mach_msg"); + *msgid = 0; + } + } + else /* Some other system call. */ + { + (void) describe_number (description, "syscall#", *msgid); + *msgid = 0; + } } else description[0] = '\0'; |