This is an automated email from the git hooks/post-receive script. sthibault pushed a commit to branch master in repository hurd.
commit 3a90599b4f8cabb3b86e6cb1fd3f9531ffb823a5 Author: Samuel Thibault <[email protected]> Date: Sat Jul 4 21:35:18 2015 +0000 New upstream snapshot --- configure.ac | 8 + console-client/timer.h | 2 +- console-client/xkb/kstoucs.c | 41 ++-- libdde-linux26/include/linux/device.h | 5 +- libdde-linux26/lib/src/arch/l4/pci.c | 2 +- libdiskfs/io-reauthenticate.c | 3 + libdiskfs/node-cache.c | 1 - libnetfs/io-reauthenticate.c | 3 + libps/fmt.c | 15 ++ pfinet/io-ops.c | 3 + trans/fakeroot.c | 10 +- utils/Makefile | 12 +- utils/msgids.c | 252 +++++++++++++++++++++ utils/msgids.h | 33 +++ utils/rpcscan.c | 404 ++++++++++++++++++++++++++++++++++ utils/rpctrace.c | 202 +---------------- utils/vmstat.c | 3 +- 17 files changed, 772 insertions(+), 227 deletions(-) diff --git a/configure.ac b/configure.ac index 71f3a0e..b03057b 100644 --- a/configure.ac +++ b/configure.ac @@ -292,6 +292,14 @@ PKG_CHECK_MODULES([X11], [x11 xproto], have_x11=no]) ], [have_x11=no]) ]) + +AS_IF([test "$have_x11" = "yes"], + [AC_MSG_CHECKING([whether AWK is usable]) + AS_IF([test "$AWK" != ":" && $AWK 'BEGIN { strtonum("1"); }' 2>/dev/null], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([$AWK does not provide required strtonum function])])]) + AC_SUBST([have_x11]) AC_SUBST([XKB_BASE]) AC_DEFINE_UNQUOTED([X11_PREFIX], "$X11_PREFIX") diff --git a/console-client/timer.h b/console-client/timer.h index 4204192..8a923ad 100644 --- a/console-client/timer.h +++ b/console-client/timer.h @@ -54,7 +54,7 @@ int timer_remove (struct timer_list *timer); /* Change the expiration time of the timer TIMER to EXPIRES. */ void timer_change (struct timer_list *timer, long long expires); -extern inline long long +static inline long long fetch_jiffies () { extern volatile struct mapped_time_value *timer_mapped_time; diff --git a/console-client/xkb/kstoucs.c b/console-client/xkb/kstoucs.c index 0211e9e..eb47bde 100644 --- a/console-client/xkb/kstoucs.c +++ b/console-client/xkb/kstoucs.c @@ -1,3 +1,5 @@ +#include <assert.h> + struct ksmap { int keysym; unsigned int ucs; @@ -5,6 +7,28 @@ struct ksmap { #include "kstoucs_map.c" +/* Binary search through `kstoucs_map'. */ +static unsigned int +find_ucs (int keysym, struct ksmap *first, struct ksmap *last) +{ + struct ksmap *middle = first + (last - first) / 2; + + assert (first <= last); + + if (middle->keysym == keysym) + return middle->ucs; /* base case: needle found. */ + else if (first == last) /* empty search space */ + return 0; + /* recursive cases: halve search space. */ + else if (middle->keysym < keysym) + return find_ucs (keysym, middle+1, last); + else if (middle->keysym > keysym) + /* don't remove middle from the range to compensate + for rounding down in it's calculation */ + return find_ucs (keysym, first, middle); + return 0; +} + unsigned int KeySymToUcs4 (int keysym) { @@ -23,23 +47,6 @@ unsigned int doit (int keysym) if ((keysym & 0xff000000) == 0x01000000) return (keysym & 0x00ffffff); - unsigned int - find_ucs (int keysym, struct ksmap *first, struct ksmap *last) - { - struct ksmap *middle = first + (last - first) / 2; - - if (middle->keysym == keysym) - return middle->ucs; /* base case: needle found. */ - else if (middle == first && middle == last) - return 0; /* base case: empty search space. */ - /* recursive cases: halve search space. */ - else if (middle->keysym < keysym) - return find_ucs (keysym, middle+1, last); - else if (middle->keysym > keysym) - return find_ucs (keysym, first, middle-1); - return 0; - } - #define NUM_KEYSYMS (sizeof kstoucs_map / sizeof(struct ksmap)) return find_ucs(keysym, &kstoucs_map[0], &kstoucs_map[NUM_KEYSYMS - 1]); #ifdef XKB_DEBUG diff --git a/libdde-linux26/include/linux/device.h b/libdde-linux26/include/linux/device.h index 41b4227..3dc6e94 100644 --- a/libdde-linux26/include/linux/device.h +++ b/libdde-linux26/include/linux/device.h @@ -553,7 +553,10 @@ extern const char *dev_driver_string(const struct device *dev); printk(level "%s %s: " format , dev_driver_string(dev) , \ dev_name(dev) , ## arg) #else -#define dev_printk(level, dev, format, arg...) +#include <stdio.h> +#define dev_printk(level, dev, format, arg...) \ + fprintf(stderr, level "%s %s: " format, \ + dev_driver_string(dev), dev_name(dev), ## arg) #endif #define dev_emerg(dev, format, arg...) \ diff --git a/libdde-linux26/lib/src/arch/l4/pci.c b/libdde-linux26/lib/src/arch/l4/pci.c index b50a735..6dd8e87 100644 --- a/libdde-linux26/lib/src/arch/l4/pci.c +++ b/libdde-linux26/lib/src/arch/l4/pci.c @@ -171,7 +171,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) return pcibios_enable_irq(dev); #endif WARN_UNIMPL; - return -1; + return 0; } /******************************************************************************************* diff --git a/libdiskfs/io-reauthenticate.c b/libdiskfs/io-reauthenticate.c index 649315f..985db49 100644 --- a/libdiskfs/io-reauthenticate.c +++ b/libdiskfs/io-reauthenticate.c @@ -49,8 +49,11 @@ diskfs_S_io_reauthenticate (struct protid *cred, newright = ports_get_send_right (newcred); assert (newright != MACH_PORT_NULL); + /* Release the node lock while blocking on the auth server and client. */ + pthread_mutex_unlock (&cred->po->np->lock); err = iohelp_reauth (&user, diskfs_auth_server_port, rend_port, newright, 1); + pthread_mutex_lock (&cred->po->np->lock); if (! err) { diskfs_finish_protid (newcred, user); diff --git a/libdiskfs/node-cache.c b/libdiskfs/node-cache.c index 6b70da8..a76474a 100644 --- a/libdiskfs/node-cache.c +++ b/libdiskfs/node-cache.c @@ -199,7 +199,6 @@ diskfs_node_iterate (error_t (*fun)(struct node *)) if (node_list == NULL) { pthread_rwlock_unlock (&nodecache_lock); - error (0, 0, "unable to allocate temporary node table"); return ENOMEM; } diff --git a/libnetfs/io-reauthenticate.c b/libnetfs/io-reauthenticate.c index 1d2d935..f4f50d5 100644 --- a/libnetfs/io-reauthenticate.c +++ b/libnetfs/io-reauthenticate.c @@ -37,8 +37,11 @@ netfs_S_io_reauthenticate (struct protid *user, mach_port_t rend_port) newright = ports_get_send_right (newpi); assert (newright != MACH_PORT_NULL); + /* Release the node lock while blocking on the auth server and client. */ + pthread_mutex_unlock (&user->po->np->lock); err = iohelp_reauth (&newpi->user, netfs_auth_server_port, rend_port, newright, 1); + pthread_mutex_lock (&user->po->np->lock); mach_port_deallocate (mach_task_self (), rend_port); mach_port_deallocate (mach_task_self (), newright); diff --git a/libps/fmt.c b/libps/fmt.c index 0465555..580b097 100644 --- a/libps/fmt.c +++ b/libps/fmt.c @@ -68,6 +68,8 @@ _fmt_create (char *src, int posix, struct ps_fmt_specs *fmt_specs, src = new_fmt->src; while (*src != '\0') { + char *start = src; + if (field - fields == fields_alloced) /* Time to grow FIELDS to make room for more. */ { @@ -172,6 +174,19 @@ _fmt_create (char *src, int posix, struct ps_fmt_specs *fmt_specs, /* This field spec doesn't have a name, so use its flags fields to set the global ones, and skip it. */ { + /* if we didn't use any chars, don't loop indefinitely */ + if (src == start) + { + if (err_string) + asprintf (err_string, "%s: Unknown format spec", src); + + FREE (new_fmt->src); + FREE (new_fmt); + FREE (fields); + + return EINVAL; + } + global_clr_flags = clr_flags; global_inv_flags = inv_flags; continue; diff --git a/pfinet/io-ops.c b/pfinet/io-ops.c index cc666cd..742d64f 100644 --- a/pfinet/io-ops.c +++ b/pfinet/io-ops.c @@ -379,6 +379,8 @@ S_io_reauthenticate (struct sock_user *user, auth = getauth (); newright = ports_get_send_right (newuser); assert (newright != MACH_PORT_NULL); + /* Release the global lock while blocking on the auth server and client. */ + pthread_mutex_unlock (&global_lock); do err = auth_server_authenticate (auth, rend, @@ -390,6 +392,7 @@ S_io_reauthenticate (struct sock_user *user, &gen_gids, &gengidlen, &aux_gids, &auxgidlen); while (err == EINTR); + pthread_mutex_lock (&global_lock); mach_port_deallocate (mach_task_self (), rend); mach_port_deallocate (mach_task_self (), newright); mach_port_deallocate (mach_task_self (), auth); diff --git a/trans/fakeroot.c b/trans/fakeroot.c index 63303a0..4275152 100644 --- a/trans/fakeroot.c +++ b/trans/fakeroot.c @@ -554,13 +554,11 @@ netfs_attempt_chmod (struct iouser *cred, struct node *np, mode_t mode) /* Make sure that `check_openmodes' will still always be able to reopen it. */ - real_mode = mode; nn = netfs_node_netnode (np); - if (nn->openmodes & O_READ) - real_mode |= S_IRUSR; - if (nn->openmodes & O_WRITE) - real_mode |= S_IWUSR; - if (nn->openmodes & O_EXEC) + real_mode = mode; + real_mode |= S_IRUSR; + real_mode |= S_IWUSR; + if (S_ISDIR (mode) || (nn->openmodes & O_EXEC)) real_mode |= S_IXUSR; /* We don't bother with error checking since the fake mode change should diff --git a/utils/Makefile b/utils/Makefile index 241b060..955789b 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -22,7 +22,7 @@ targets = shd ps settrans showtrans syncfs fsysopts \ storeinfo login w uptime ids loginpr sush vmstat portinfo \ devprobe vminfo addauth rmauth unsu setauth ftpcp ftpdir storecat \ storeread msgport rpctrace mount gcore fakeauth fakeroot remap \ - umount nullauth + umount nullauth rpcscan special-targets = loginpr sush uptime fakeroot remap SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \ @@ -31,7 +31,7 @@ SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \ parse.c frobauth.c frobauth-mod.c setauth.c pids.c nonsugid.c \ unsu.c ftpcp.c ftpdir.c storeread.c storecat.c msgport.c \ rpctrace.c mount.c gcore.c fakeauth.c fakeroot.sh remap.sh \ - nullauth.c match-options.c + nullauth.c match-options.c msgids.c rpcscan.c OBJS = $(filter-out %.sh,$(SRCS:.c=.o)) HURDLIBS = ps ihash store fshelp ports ftpconn shouldbeinlibc @@ -62,13 +62,15 @@ ftpcp ftpdir: ../libftpconn/libftpconn.a settrans: ../libfshelp/libfshelp.a ../libports/libports.a ps w ids settrans syncfs showtrans fsysopts storeinfo login vmstat portinfo \ devprobe vminfo addauth rmauth setauth unsu ftpcp ftpdir storeread \ - storecat msgport mount umount nullauth: \ + storecat msgport mount umount nullauth rpctrace: \ ../libshouldbeinlibc/libshouldbeinlibc.a $(filter-out $(special-targets), $(targets)): %: %.o -rpctrace: ../libports/libports.a ../libihash/libihash.a -rpctrace-CPPFLAGS = -DDATADIR=\"${datadir}\" +rpctrace: ../libports/libports.a +rpctrace rpcscan: msgids.o \ + ../libihash/libihash.a +msgids-CPPFLAGS = -DDATADIR=\"${datadir}\" fakeauth: authServer.o auth_requestUser.o interruptServer.o \ ../libports/libports.a ../libihash/libihash.a \ diff --git a/utils/msgids.c b/utils/msgids.c new file mode 100644 index 0000000..4bc08de --- /dev/null +++ b/utils/msgids.c @@ -0,0 +1,252 @@ +/* Translate message ids to symbolic names. + + Copyright (C) 1998-2015 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ + +#include <argp.h> +#include <argz.h> +#include <dirent.h> +#include <errno.h> +#include <error.h> +#include <fnmatch.h> +#include <hurd/ihash.h> +#include <mach.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "msgids.h" + +static void +msgid_ihash_cleanup (void *element, void *arg) +{ + struct msgid_info *info = element; + free (info->name); + free (info->subsystem); + free (info); +} + +static struct hurd_ihash msgid_ihash + = HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP); + +/* Parse a file of RPC names and message IDs as output by mig's -list + option: "subsystem base-id routine n request-id reply-id". Put each + request-id value into `msgid_ihash' with the routine name as its value. */ +static error_t +parse_msgid_list (const char *filename) +{ + FILE *fp; + char *buffer = NULL; + size_t bufsize = 0; + unsigned int lineno = 0; + char *name, *subsystem; + unsigned int msgid; + error_t err; + + fp = fopen (filename, "r"); + if (fp == NULL) + return errno; + + while (getline (&buffer, &bufsize, fp) > 0) + { + ++lineno; + if (buffer[0] == '#' || buffer[0] == '\0') + continue; + if (sscanf (buffer, "%ms %*u %ms %*u %u %*u\n", + &subsystem, &name, &msgid) != 3) + error (0, 0, "%s:%u: invalid format in RPC list file", + filename, lineno); + else + { + struct msgid_info *info = malloc (sizeof *info); + if (info == 0) + error (1, errno, "malloc"); + info->name = name; + info->subsystem = subsystem; + err = hurd_ihash_add (&msgid_ihash, msgid, info); + if (err) + return err; + } + } + + free (buffer); + fclose (fp); + return 0; +} + +/* Look for a name describing MSGID. We check the table directly, and + also check if this looks like the ID of a reply message whose request + ID is already in the table. */ +const struct msgid_info * +msgid_info (mach_msg_id_t msgid) +{ + const struct msgid_info *info = hurd_ihash_find (&msgid_ihash, msgid); + if (info == 0 && (msgid / 100) % 2 == 1) + { + /* This message ID is not in the table, and its number makes it + what should be an RPC reply message ID. So look up the message + ID of the corresponding RPC request and synthesize a name from + that. Then stash that name in the table so the next time the + lookup will match directly. */ + info = hurd_ihash_find (&msgid_ihash, msgid - 100); + if (info != 0) + { + struct msgid_info *reply_info = malloc (sizeof *info); + if (reply_info != 0) + { + reply_info->subsystem = strdup (info->subsystem); + reply_info->name = 0; + asprintf (&reply_info->name, "%s-reply", info->name); + hurd_ihash_add (&msgid_ihash, msgid, reply_info); + info = reply_info; + } + else + info = 0; + } + } + return info; +} + +static int +msgids_file_p (const struct dirent *eps) +{ + return fnmatch ("*.msgids", eps->d_name, 0) != FNM_NOMATCH; +} + +static void +scan_msgids_dir (char **argz, size_t *argz_len, char *dir, bool append) +{ + struct dirent **eps; + int n; + + n = scandir (dir, &eps, msgids_file_p, NULL); + if (n >= 0) + { + for (int cnt = 0; cnt < n; ++cnt) + { + char *msgids_file; + + if (asprintf (&msgids_file, "%s/%s", dir, eps[cnt]->d_name) < 0) + error (1, errno, "asprintf"); + + if (append == TRUE) + { + if (argz_add (argz, argz_len, msgids_file) != 0) + error (1, errno, "argz_add"); + } + else + { + if (argz_insert (argz, argz_len, *argz, msgids_file) != 0) + error (1, errno, "argz_insert"); + } + free (msgids_file); + } + } + + /* If the directory couldn't be scanned for whatever reason, just ignore + it. */ +} + +/* Argument parsing. */ + +static char *msgids_files_argz = NULL; +static size_t msgids_files_argz_len = 0; +static bool nostdinc = FALSE; + +#define STD_MSGIDS_DIR DATADIR "/msgids/" +#define OPT_NOSTDINC -1 + +static const struct argp_option options[] = +{ + {"nostdinc", OPT_NOSTDINC, 0, 0, + "Do not search inside the standard system directory, `" STD_MSGIDS_DIR + "', for `.msgids' files.", 0}, + {"rpc-list", 'i', "FILE", 0, + "Read FILE for assocations of message ID numbers to names.", 0}, + {0, 'I', "DIR", 0, + "Add the directory DIR to the list of directories to be searched for files " + "containing message ID numbers.", 0}, + {0} +}; + +/* Parse our options... */ +static error_t parse_opt (int key, char *arg, struct argp_state *state) +{ + switch (key) + { + case ARGP_KEY_INIT: + hurd_ihash_set_cleanup (&msgid_ihash, msgid_ihash_cleanup, 0); + break; + + case OPT_NOSTDINC: + nostdinc = TRUE; + break; + + case 'i': + if (argz_add (&msgids_files_argz, &msgids_files_argz_len, + arg) != 0) + error (1, errno, "argz_add"); + break; + + case 'I': + scan_msgids_dir (&msgids_files_argz, &msgids_files_argz_len, + arg, TRUE); + break; + + case ARGP_KEY_NO_ARGS: + return 0; + + case ARGP_KEY_ARG: + return EINVAL; + + case ARGP_KEY_END: + /* Insert the files from STD_MSGIDS_DIR at the beginning of the + list, so that their content can be overridden by subsequently + parsed files. */ + if (nostdinc == FALSE) + scan_msgids_dir (&msgids_files_argz, &msgids_files_argz_len, + STD_MSGIDS_DIR, FALSE); + + if (msgids_files_argz != NULL) + { + error_t err = 0; + char *msgids_file = NULL; + + while (! err + && (msgids_file = argz_next (msgids_files_argz, + msgids_files_argz_len, + msgids_file))) + err = parse_msgid_list (msgids_file); + + free (msgids_files_argz); + if (err) + argp_failure (state, 1, err, "%s", msgids_file); + } + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +const struct argp msgid_argp = { + .options = options, + .parser = parse_opt, + .doc = "msgid doc", +}; diff --git a/utils/msgids.h b/utils/msgids.h new file mode 100644 index 0000000..6bd2372 --- /dev/null +++ b/utils/msgids.h @@ -0,0 +1,33 @@ +/* Translate message ids to symbolic names. + + Copyright (C) 1998-2015 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef _HURD_MSGIDS_H_ +#define _HURD_MSGIDS_H_ + +/* We map message ids to procedure and subsystem names. */ +struct msgid_info +{ + char *name; + char *subsystem; +}; + +const struct msgid_info *msgid_info (mach_msg_id_t msgid); +const struct argp msgid_argp; + +#endif /* _HURD_MSGIDS_H_ */ diff --git a/utils/rpcscan.c b/utils/rpcscan.c new file mode 100644 index 0000000..2270ea8 --- /dev/null +++ b/utils/rpcscan.c @@ -0,0 +1,404 @@ +/* An RPC scanner for the Hurd. + + Copyright (C) 2015 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ + +#include <mach.h> +#include <hurd.h> +#include <hurd/ihash.h> +#include <mach/message.h> +#include <unistd.h> +#include <argp.h> +#include <error.h> +#include <string.h> +#include <version.h> +#include <sys/wait.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stddef.h> +#include <argz.h> + +#include "msgids.h" + +/* Send messages with arbitrary message ids. */ +struct Request { + mach_msg_header_t Head; +} RequestTemplate; + +struct Reply { + mach_msg_header_t Head; + mach_msg_type_t RetCodeType; + kern_return_t RetCode; + char Body[4096]; +}; + +union { + struct Request Request; + struct Reply Reply; +} Message; + +error_t +setup (mach_port_t request, mach_msg_type_name_t requestType) +{ + RequestTemplate.Head.msgh_remote_port = request; + if (! MACH_PORT_VALID (RequestTemplate.Head.msgh_local_port)) + RequestTemplate.Head.msgh_local_port = mach_reply_port (); + RequestTemplate.Head.msgh_bits = + MACH_MSGH_BITS (requestType, MACH_MSG_TYPE_MAKE_SEND_ONCE); + return 0; +} + +error_t +send (mach_msg_id_t msgid) +{ + error_t err; + Message.Request = RequestTemplate; + Message.Request.Head.msgh_id = msgid; + err = mach_msg (&Message.Request.Head, + MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, + sizeof Message.Request, + sizeof Message.Reply, + Message.Request.Head.msgh_local_port, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + if (err) + return err; + + /* XXX typecheck */ + return Message.Reply.RetCode; +} + +typedef error_t (*setup_function_t) (); +setup_function_t setup_target; +void *setup_argument; + +error_t +setup_task_target (void) +{ + error_t err; + static task_t task; + static mach_msg_type_name_t taskType = MACH_MSG_TYPE_COPY_SEND; + + if (MACH_PORT_VALID (task)) + { + task_terminate (task); + mach_port_deallocate (mach_task_self (), task); + } + + err = task_create (mach_task_self (), 0, &task); + if (err) + return err; + + return setup (task, taskType); +} + +error_t +setup_thread_target (void) +{ + error_t err; + static task_t task; + static thread_t thread; + + if (MACH_PORT_VALID (thread)) + { + thread_terminate (thread); + mach_port_deallocate (mach_task_self (), thread); + } + + if (MACH_PORT_VALID (task)) + { + task_terminate (task); + mach_port_deallocate (mach_task_self (), task); + } + + err = task_create (mach_task_self (), 0, &task); + if (err) + return err; + + err = thread_create (task, &thread); + if (err) + return err; + + return setup (thread, MACH_MSG_TYPE_COPY_SEND); +} + +error_t +setup_proc_target (void) +{ + error_t err; + static task_t task; + static process_t proc, target; + static mach_msg_type_name_t targetType = MACH_MSG_TYPE_COPY_SEND; + + if (! MACH_PORT_VALID (proc)) + proc = getproc (); + if (MACH_PORT_VALID (task)) + mach_port_deallocate (mach_task_self (), task); + if (MACH_PORT_VALID (target)) + mach_port_deallocate (mach_task_self (), target); + + err = task_create (mach_task_self (), 0, &task); + if (err) + return err; + + err = proc_task2proc (proc, task, &target); + if (err) + return err; + + return setup (target, targetType); +} + +error_t +setup_auth_target (void) +{ + static auth_t auth; + static mach_msg_type_name_t authType = MACH_MSG_TYPE_COPY_SEND; + + if (MACH_PORT_VALID (auth)) + mach_port_deallocate (mach_task_self (), auth); + + auth = getauth (); + if (! MACH_PORT_VALID (auth)) + return errno; + + return setup (auth, authType); +} + +error_t +setup_hurd_target (void) +{ + char *name = (char *) setup_argument; + mach_port_t request; + mach_msg_type_name_t requestType; + + request = file_name_lookup (name, 0, 0); + if (! MACH_PORT_VALID (request)) + return errno; + requestType = MACH_MSG_TYPE_COPY_SEND; + + return setup (request, requestType); +} + +task_t extract_target_task; +mach_port_t extract_target_port; +mach_msg_type_name_t extract_target_type; + +error_t +setup_extract_target (void) +{ + error_t err; + char *name = (char *) setup_argument; + mach_port_t request; + mach_msg_type_name_t requestType; + + err = mach_port_extract_right (extract_target_task, + extract_target_port, + extract_target_type, + &request, + &requestType); + if (err) + error (1, err, "mach_port_extract_right"); + if (err) + return err; + requestType = MACH_MSG_TYPE_COPY_SEND; + return setup (request, requestType); +} + +const char *argp_program_version = STANDARD_HURD_VERSION (rpcscan); + +char **cmd_argv; +int verbose; +int numeric; +int subsystem; + +#define OPT_TARGET_TASK -1 +#define OPT_TARGET_THREAD -2 +#define OPT_TARGET_PROC -3 +#define OPT_TARGET_AUTH -4 +#define OPT_TARGET_EXTRACT -5 + +static const struct argp_option options[] = +{ + {NULL, 0, NULL, OPTION_DOC, "Target selection", 1}, + {"task", OPT_TARGET_TASK, NULL, 0, "target a task port", 1}, + {"thread", OPT_TARGET_THREAD, NULL, 0, "target a thread port", 1}, + {"proc", OPT_TARGET_PROC, NULL, 0, "target a proc port", 1}, + {"auth", OPT_TARGET_AUTH, NULL, 0, "target an auth port", 1}, + {"extract", OPT_TARGET_EXTRACT, "PID.PORT", 0, "target port PORT of PID", 1}, + + {NULL, 0, NULL, OPTION_DOC, "Options", 2}, + {"verbose", 'v', NULL, 0, "be verbose", 2}, + {"numeric", 'n', NULL, 0, "show numeric message ids", 2}, + {"subsystem", 's', NULL, 0, "show subsystem names", 2}, + {0} +}; + +static const char args_doc[] = "[FILE]"; +static const char doc[] = "Scan a given Mach port."; + +/* Parse our options... */ +error_t +parse_opt (int key, char *arg, struct argp_state *state) +{ + error_t err; + switch (key) + { + case 'v': + verbose = 1; + break; + + case 'n': + numeric = 1; + break; + + case 's': + subsystem = 1; + break; + +#define SELECT_TARGET(target) \ + if (setup_target) \ + argp_error (state, "Multiple targets specified."); \ + setup_target = target; + + case OPT_TARGET_TASK: + SELECT_TARGET (setup_task_target); + break; + + case OPT_TARGET_THREAD: + SELECT_TARGET (setup_thread_target); + break; + + case OPT_TARGET_PROC: + SELECT_TARGET (setup_proc_target); + break; + + case OPT_TARGET_AUTH: + SELECT_TARGET (setup_auth_target); + break; + + case OPT_TARGET_EXTRACT:; + process_t proc; + pid_t pid; + char *end; + + pid = strtol (arg, &end, 10); + if (arg == end || *end != '.') + argp_error (state, "Expected format PID.PORT, got `%s'.", arg); + + arg = end + 1; + extract_target_port = strtol (arg, &end, 10); + if (arg == end || *end != '\0') + argp_error (state, "Expected format PORT, got `%s'.", arg); + + proc = getproc (); + err = proc_pid2task (proc, pid, &extract_target_task); + if (err) + argp_failure (state, 1, err, + "Could not get task of process %d", pid); + + extract_target_type = MACH_MSG_TYPE_COPY_SEND; /* XXX */ + SELECT_TARGET (setup_extract_target); + break; + + case ARGP_KEY_ARG: + SELECT_TARGET (setup_hurd_target); + setup_argument = arg; + break; +#undef SELECT_TARGET + + case ARGP_KEY_NO_ARGS: + if (setup_target == NULL) + argp_usage (state); + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +const struct argp_child children[] = + { + { .argp=&msgid_argp, }, + { 0 } + }; + +const struct argp argp = { options, parse_opt, args_doc, doc, &children }; + +void +format_msgid (char *buf, size_t len, mach_msg_id_t id) +{ + if (numeric) + numeric: + snprintf (buf, len, "%d", id); + else + { + const struct msgid_info *info; + info = msgid_info (id); + if (info == NULL) + goto numeric; + + if (subsystem) + snprintf (buf, len, "%s/%s", info->subsystem, info->name); + else + snprintf (buf, len, "%s", info->name); + } +} + +int +main (int argc, char **argv) +{ + error_t err; + mach_msg_id_t msgid; + + /* Parse our arguments. */ + argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0); + + err = setup_target (); + if (err) + /* Initial setup failed. Bail out. */ + error (1, err, "%s", + setup_target == setup_hurd_target? (char *) setup_argument: "setup"); + + for (msgid = 0; msgid < 500000; msgid++) + { + err = send (msgid); + switch (err) + { + case MACH_SEND_INVALID_DEST: + err = setup_target (); + if (err) + error (1, err, "setup"); + msgid--; /* redo */ + continue; + + case MIG_BAD_ID: + /* do nothing */ + break; + + default:; + char buf[80]; + format_msgid (buf, sizeof buf, msgid); + if (verbose) + error (0, err, "%s", buf); + else + fprintf (stdout, "%s\n", buf); + } + } + + return EXIT_SUCCESS; +} diff --git a/utils/rpctrace.c b/utils/rpctrace.c index 48daa07..d53b510 100644 --- a/utils/rpctrace.c +++ b/utils/rpctrace.c @@ -26,9 +26,7 @@ #include <mach/message.h> #include <assert.h> #include <fcntl.h> -#include <fnmatch.h> #include <sys/stat.h> -#include <dirent.h> #include <unistd.h> #include <argp.h> #include <error.h> @@ -41,24 +39,15 @@ #include <argz.h> #include <envz.h> -const char *argp_program_version = STANDARD_HURD_VERSION (rpctrace); +#include "msgids.h" -#define STD_MSGIDS_DIR DATADIR "/msgids/" +const char *argp_program_version = STANDARD_HURD_VERSION (rpctrace); static unsigned strsize = 80; -#define OPT_NOSTDINC -1 static const struct argp_option options[] = { {"output", 'o', "FILE", 0, "Send trace output to FILE instead of stderr."}, - {"nostdinc", OPT_NOSTDINC, 0, 0, - "Do not search inside the standard system directory, `" STD_MSGIDS_DIR - "', for `.msgids' files."}, - {"rpc-list", 'i', "FILE", 0, - "Read FILE for assocations of message ID numbers to names."}, - {0, 'I', "DIR", 0, - "Add the directory DIR to the list of directories to be searched for files " - "containing message ID numbers."}, {0, 's', "SIZE", 0, "Specify the maximum string size to print (the default is 80)."}, {0, 'E', "var[=value]", 0, "Set/change (var=value) or remove (var) an environment variable among the " @@ -71,23 +60,6 @@ static const struct argp_option options[] = static const char args_doc[] = "COMMAND [ARG...]"; static const char doc[] = "Trace Mach Remote Procedure Calls."; -/* The msgid_ihash table maps msgh_id values to names. */ - -struct msgid_info -{ - char *name; - char *subsystem; -}; - -static void -msgid_ihash_cleanup (void *element, void *arg) -{ - struct msgid_info *info = element; - free (info->name); - free (info->subsystem); - free (info); -} - /* This structure stores the information of the traced task. */ struct task_info { @@ -95,9 +67,6 @@ struct task_info boolean_t threads_wrapped; /* All threads of the task has been wrapped? */ }; -static struct hurd_ihash msgid_ihash - = HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP); - static struct hurd_ihash task_ihash = HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP); @@ -126,86 +95,6 @@ remove_task (task_t task) hurd_ihash_remove (&task_ihash, task); } -/* Parse a file of RPC names and message IDs as output by mig's -list - option: "subsystem base-id routine n request-id reply-id". Put each - request-id value into `msgid_ihash' with the routine name as its value. */ -static void -parse_msgid_list (const char *filename) -{ - FILE *fp; - char *buffer = NULL; - size_t bufsize = 0; - unsigned int lineno = 0; - char *name, *subsystem; - unsigned int msgid; - error_t err; - - fp = fopen (filename, "r"); - if (fp == 0) - { - error (2, errno, "%s", filename); - return; - } - - while (getline (&buffer, &bufsize, fp) > 0) - { - ++lineno; - if (buffer[0] == '#' || buffer[0] == '\0') - continue; - if (sscanf (buffer, "%ms %*u %ms %*u %u %*u\n", - &subsystem, &name, &msgid) != 3) - error (0, 0, "%s:%u: invalid format in RPC list file", - filename, lineno); - else - { - struct msgid_info *info = malloc (sizeof *info); - if (info == 0) - error (1, errno, "malloc"); - info->name = name; - info->subsystem = subsystem; - err = hurd_ihash_add (&msgid_ihash, msgid, info); - if (err) - error (1, err, "hurd_ihash_add"); - } - } - - free (buffer); - fclose (fp); -} - -/* Look for a name describing MSGID. We check the table directly, and - also check if this looks like the ID of a reply message whose request - ID is already in the table. */ -static const struct msgid_info * -msgid_info (mach_msg_id_t msgid) -{ - const struct msgid_info *info = hurd_ihash_find (&msgid_ihash, msgid); - if (info == 0 && (msgid / 100) % 2 == 1) - { - /* This message ID is not in the table, and its number makes it - what should be an RPC reply message ID. So look up the message - ID of the corresponding RPC request and synthesize a name from - that. Then stash that name in the table so the next time the - lookup will match directly. */ - info = hurd_ihash_find (&msgid_ihash, msgid - 100); - if (info != 0) - { - struct msgid_info *reply_info = malloc (sizeof *info); - if (reply_info != 0) - { - reply_info->subsystem = strdup (info->subsystem); - reply_info->name = 0; - asprintf (&reply_info->name, "%s-reply", info->name); - hurd_ihash_add (&msgid_ihash, msgid, reply_info); - info = reply_info; - } - else - info = 0; - } - } - return info; -} - static const char * msgid_name (mach_msg_id_t msgid) { @@ -1781,55 +1670,9 @@ traced_spawn (char **argv, char **envp) return pid; } - -static void -scan_msgids_dir (char **argz, size_t *argz_len, char *dir, bool append) -{ - struct dirent **eps; - int n; - - int - msgids_file_p (const struct dirent *eps) - { - if (fnmatch ("*.msgids", eps->d_name, 0) != FNM_NOMATCH) - return 1; - return 0; - } - - n = scandir (dir, &eps, msgids_file_p, NULL); - if (n >= 0) - { - for (int cnt = 0; cnt < n; ++cnt) - { - char *msgids_file; - - if (asprintf (&msgids_file, "%s/%s", dir, eps[cnt]->d_name) < 0) - error (1, errno, "asprintf"); - - if (append == TRUE) - { - if (argz_add (argz, argz_len, msgids_file) != 0) - error (1, errno, "argz_add"); - } - else - { - if (argz_insert (argz, argz_len, *argz, msgids_file) != 0) - error (1, errno, "argz_insert"); - } - free (msgids_file); - } - } - - /* If the directory couldn't be scanned for whatever reason, just ignore - it. */ -} - int main (int argc, char **argv, char **envp) { - char *msgids_files_argz = NULL; - size_t msgids_files_argz_len = 0; - bool nostdinc = FALSE; const char *outfile = 0; char **cmd_argv = 0; pthread_t thread; @@ -1847,21 +1690,6 @@ main (int argc, char **argv, char **envp) outfile = arg; break; - case OPT_NOSTDINC: - nostdinc = TRUE; - break; - - case 'i': - if (argz_add (&msgids_files_argz, &msgids_files_argz_len, - arg) != 0) - error (1, errno, "argz_add"); - break; - - case 'I': - scan_msgids_dir (&msgids_files_argz, &msgids_files_argz_len, - arg, TRUE); - break; - case 's': strsize = atoi (arg); break; @@ -1908,7 +1736,12 @@ main (int argc, char **argv, char **envp) } return 0; } - const struct argp argp = { options, parse_opt, args_doc, doc }; + const struct argp_child children[] = + { + { .argp=&msgid_argp, }, + { 0 } + }; + const struct argp argp = { options, parse_opt, args_doc, doc, &children }; /* Parse our arguments. */ argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0); @@ -1917,23 +1750,6 @@ main (int argc, char **argv, char **envp) &unknown_task); assert_perror (err); - /* Insert the files from STD_MSGIDS_DIR at the beginning of the list, so that - their content can be overridden by subsequently parsed files. */ - if (nostdinc == FALSE) - scan_msgids_dir (&msgids_files_argz, &msgids_files_argz_len, - STD_MSGIDS_DIR, FALSE); - - if (msgids_files_argz != NULL) - { - char *msgids_file = NULL; - - while ((msgids_file = argz_next (msgids_files_argz, - msgids_files_argz_len, msgids_file))) - parse_msgid_list (msgids_file); - - free (msgids_files_argz); - } - if (outfile) { ostream = fopen (outfile, "w"); @@ -1951,8 +1767,6 @@ main (int argc, char **argv, char **envp) sizeof (*notify_pi), ¬ify_pi); assert_perror (err); - hurd_ihash_set_cleanup (&msgid_ihash, msgid_ihash_cleanup, 0); - /* Spawn a single thread that will receive intercepted messages, print them, and interpose on the ports they carry. The access to the `traced_info' and ihash data structures is all single-threaded, diff --git a/utils/vmstat.c b/utils/vmstat.c index e394484..92a3672 100644 --- a/utils/vmstat.c +++ b/utils/vmstat.c @@ -242,7 +242,8 @@ vm_state_get_field (struct vm_state *state, const struct field *field) static val_t get_memobj_hit_ratio (struct vm_state *state, const struct field *field) { - return state->vmstats.hits * 100 / state->vmstats.lookups; + return (val_t) + ((float) state->vmstats.hits * 100. / (float) state->vmstats.lookups); } /* Makes sure STATE contains a default pager port and associated info, and -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-hurd/hurd.git
