From c62d5ff73ceaad21bb0784ed6098d307a625b10d Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Tue, 17 Aug 2010 20:34:58 +0000 Subject: Add real process nodes * process.c, process.h: New files, implement a process directory with cmdline and environ files. * Makefile: Add the process module. * proclist.c: Replace stub pid files with the real thing. --- process.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 process.c (limited to 'process.c') diff --git a/process.c b/process.c new file mode 100644 index 00000000..90ea511b --- /dev/null +++ b/process.c @@ -0,0 +1,79 @@ +#include +#include +#include "procfs.h" +#include "procfs_dir.h" +#include "process.h" + +struct process_node { + process_t procserv; + pid_t pid; +}; + + +/* The proc_getprocargs() and proc_getprocenv() calls have the same + prototype and we use them in the same way; namely, publish the data + they return as-is. We take advantage of this to have common code and + use a function pointer as the procfs_dir "entry hook" to choose the + call to use on a file by file basis. */ + +struct process_argz_node +{ + struct process_node pn; + error_t (*getargz) (process_t, pid_t, void **, mach_msg_type_number_t *); +}; + +static error_t +process_argz_get_contents (void *hook, void **contents, size_t *contents_len) +{ + struct process_argz_node *pz = hook; + error_t err; + + *contents_len = 0; + err = pz->getargz (pz->pn.procserv, pz->pn.pid, contents, contents_len); + if (err) + return EIO; + + return 0; +} + +static struct node * +process_argz_make_node (void *dir_hook, void *entry_hook) +{ + static const struct procfs_node_ops ops = { + .get_contents = process_argz_get_contents, + .cleanup_contents = procfs_cleanup_contents_with_vm_deallocate, + .cleanup = free, + }; + struct process_argz_node *zn; + + zn = malloc (sizeof *zn); + if (! zn) + return NULL; + + memcpy (&zn->pn, dir_hook, sizeof zn->pn); + zn->getargz = entry_hook; + + return procfs_make_node (&ops, zn); +} + + +struct node * +process_make_node (process_t procserv, pid_t pid) +{ + static const struct procfs_dir_entry entries[] = { + { "cmdline", process_argz_make_node, proc_getprocargs, }, + { "environ", process_argz_make_node, proc_getprocenv, }, + { NULL, } + }; + struct process_node *pn; + + pn = malloc (sizeof *pn); + if (! pn) + return NULL; + + pn->procserv = procserv; + pn->pid = pid; + + return procfs_dir_make_node (entries, pn, free); +} + -- cgit v1.2.3 From 2fb5b93b4cd56fd68b525371ba63b0933b61d03a Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Tue, 17 Aug 2010 22:20:32 +0000 Subject: Fetch process information and reject the non-existing ones * process.c, process.h (process_make_node): Make static, include a procinfo structure into the node information. (process_lookup_pid): New function, replaces process_make_node as the outer interface, returns an error for non-existing processes. * proclist.c (proclist_lookup): Convert to the new interface. --- process.c | 34 +++++++++++++++++++++++++++++++--- process.h | 10 ++++++++-- proclist.c | 12 +++++++++--- 3 files changed, 48 insertions(+), 8 deletions(-) (limited to 'process.c') diff --git a/process.c b/process.c index 90ea511b..612ed493 100644 --- a/process.c +++ b/process.c @@ -7,6 +7,7 @@ struct process_node { process_t procserv; pid_t pid; + struct procinfo info; }; @@ -57,8 +58,8 @@ process_argz_make_node (void *dir_hook, void *entry_hook) } -struct node * -process_make_node (process_t procserv, pid_t pid) +static struct node * +process_make_node (process_t procserv, pid_t pid, const struct procinfo *info) { static const struct procfs_dir_entry entries[] = { { "cmdline", process_argz_make_node, proc_getprocargs, }, @@ -73,7 +74,34 @@ process_make_node (process_t procserv, pid_t pid) pn->procserv = procserv; pn->pid = pid; + memcpy (&pn->info, info, sizeof pn->info); - return procfs_dir_make_node (entries, pn, free); + return procfs_dir_make_node (entries, pn, process_cleanup); } +error_t +process_lookup_pid (process_t procserv, pid_t pid, struct node **np) +{ + procinfo_t info; + size_t info_sz; + data_t tw; + size_t tw_sz; + int flags; + error_t err; + + tw_sz = info_sz = 0, flags = 0; + err = proc_getprocinfo (procserv, pid, &flags, &info, &info_sz, &tw, &tw_sz); + if (err == ESRCH) + return ENOENT; + if (err) + return EIO; + + assert (info_sz * sizeof *info >= sizeof (struct procinfo)); + *np = process_make_node (procserv, pid, (struct procinfo *) info); + vm_deallocate (mach_task_self (), (vm_address_t) info, info_sz); + + if (! *np) + return ENOMEM; + + return 0; +} diff --git a/process.h b/process.h index 8ca7c851..abdaaa3b 100644 --- a/process.h +++ b/process.h @@ -1,2 +1,8 @@ -struct node * -process_make_node (process_t procserv, pid_t pid); +#include + +/* Create a node for a directory representing information available at + the proc server PROC for the given PID. On success, returns the + newly created node in *NP. */ +error_t +process_lookup_pid (process_t proc, pid_t pid, struct node **np); + diff --git a/proclist.c b/proclist.c index 148e4bc3..75b61a2e 100644 --- a/proclist.c +++ b/proclist.c @@ -52,12 +52,18 @@ proclist_lookup (void *hook, const char *name, struct node **np) char *endp; pid_t pid; + /* Self-lookups should not end up here. */ + assert (name[0]); + + /* No leading zeros allowed */ + if (name[0] == '0' && name[1]) + return ENOENT; + pid = strtol (name, &endp, 10); - if (name[0] == '0' || !name[0] || *endp) + if (*endp) return ENOENT; - *np = process_make_node (pl->process, pid); - return *np ? 0 : ENOMEM; + return process_lookup_pid (pl->process, pid, np); } struct node * -- cgit v1.2.3 From ef370b0967024ced9296ff2028abc1b154c0a951 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Wed, 18 Aug 2010 21:06:08 +0000 Subject: Set the owner of process directories. * process.c (process_make_node): Use the owner_uid from the procinfo structure to set the owner of the created directory. --- process.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'process.c') diff --git a/process.c b/process.c index 612ed493..411f4c4a 100644 --- a/process.c +++ b/process.c @@ -67,6 +67,7 @@ process_make_node (process_t procserv, pid_t pid, const struct procinfo *info) { NULL, } }; struct process_node *pn; + struct node *np; pn = malloc (sizeof *pn); if (! pn) @@ -76,7 +77,10 @@ process_make_node (process_t procserv, pid_t pid, const struct procinfo *info) pn->pid = pid; memcpy (&pn->info, info, sizeof pn->info); - return procfs_dir_make_node (entries, pn, process_cleanup); + np = procfs_dir_make_node (entries, pn, process_cleanup); + np->nn_stat.st_uid = pn->info.owner; + + return np; } error_t -- cgit v1.2.3 From 97e598086b37583585b455d2b804b6e49d97ea85 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Thu, 19 Aug 2010 03:12:27 +0000 Subject: Add a basic [pid]/stat file * process.c: Add a basic stat file. --- process.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) (limited to 'process.c') diff --git a/process.c b/process.c index 411f4c4a..2b89ef81 100644 --- a/process.c +++ b/process.c @@ -1,3 +1,4 @@ +#include #include #include #include "procfs.h" @@ -57,6 +58,113 @@ process_argz_make_node (void *dir_hook, void *entry_hook) return procfs_make_node (&ops, zn); } +/* The other files don't need any information besides the data in struct + process_node. Furthermore, their contents don't have any nul byte. + Consequently, we use a simple "multiplexer" based on the information + below. */ + +struct process_file_node +{ + struct process_node pn; + error_t (*get_contents) (struct process_node *pn, char **contents); +}; + +static char mapstate (int hurd_state) +{ + return '?'; +} + +static error_t +process_file_gc_stat (struct process_node *pn, char **contents) +{ + char *argz; + size_t argz_len; + int len; + + argz = NULL, argz_len = 0; + proc_getprocargs(pn->procserv, pn->pid, &argz, &argz_len); + + len = asprintf (contents, + "%d (%s) %c " /* pid, command, state */ + "%d %d %d " /* ppid, pgid, session */ + "%d %d " /* controling tty stuff */ + "%u " /* flags, as defined by */ + "%lu %lu %lu %lu " /* page fault counts */ + "%lu %lu %ld %ld " /* user/sys times, in sysconf(_SC_CLK_TCK) */ + "%ld %ld " /* scheduler params (priority, nice) */ + "%ld %ld " /* number of threads, [obsolete] */ + "%llu " /* start time since boot (jiffies) */ + "%lu %ld %lu " /* virtual size, rss, rss limit */ + "%lu %lu %lu %lu %lu " /* some vm addresses (code, stack, sp, pc) */ + "%lu %lu %lu %lu " /* pending, blocked, ignored and caught sigs */ + "%lu " /* wait channel */ + "%lu %lu " /* swap usage (not maintained in Linux) */ + "%d " /* exit signal, to be sent to the parent */ + "%d " /* last processor used */ + "%u %u " /* RT priority and policy */ + "%llu " /* aggregated block I/O delay */ + "\n", + pn->pid, argz ?: "", mapstate (pn->info.state), + pn->info.ppid, pn->info.pgrp, pn->info.session, + 0, 0, + 0, + 0L, 0L, 0L, 0L, + 0L, 0L, 0L, 0L, + 0L, 0L, + 0L, 0L, + 0LL, + 0L, 0L, 0L, + 0L, 0L, 0L, 0L, 0L, + 0L, 0L, 0L, 0L, + 0L, + 0L, 0L, + 0, + 0, + 0, 0, + 0LL); + + vm_deallocate (mach_task_self (), (vm_address_t) argz, argz_len); + + if (len < 0) + return ENOMEM; + + return 0; +} + +static error_t +process_file_get_contents (void *hook, void **contents, size_t *contents_len) +{ + struct process_file_node *fn = hook; + error_t err; + + err = fn->get_contents (&fn->pn, (char **) contents); + if (err) + return err; + + *contents_len = strlen (*contents); + return 0; +} + +static struct node * +process_file_make_node (void *dir_hook, void *entry_hook) +{ + static const struct procfs_node_ops ops = { + .get_contents = process_file_get_contents, + .cleanup_contents = procfs_cleanup_contents_with_free, + .cleanup = free, + }; + struct process_file_node *fn; + + fn = malloc (sizeof *fn); + if (! fn) + return NULL; + + memcpy (&fn->pn, dir_hook, sizeof fn->pn); + fn->get_contents = entry_hook; + + return procfs_make_node (&ops, fn); +} + static struct node * process_make_node (process_t procserv, pid_t pid, const struct procinfo *info) @@ -64,6 +172,7 @@ process_make_node (process_t procserv, pid_t pid, const struct procinfo *info) static const struct procfs_dir_entry entries[] = { { "cmdline", process_argz_make_node, proc_getprocargs, }, { "environ", process_argz_make_node, proc_getprocenv, }, + { "stat", process_file_make_node, process_file_gc_stat, }, { NULL, } }; struct process_node *pn; -- cgit v1.2.3 From 1f1661d6a5b6f22acb48460b5304e29af2a0a554 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Sat, 21 Aug 2010 09:26:09 +0000 Subject: Use libps and enhance [pid]/stat * Makefile: Add libps to the $(LIBS). * proclist.c, proclist.h: Embed the proc server port in a ps_context structure. (proclist_make_node): Change to prototype to allow for the possibility of error. Rename to proclist_create_node to reflect the change and non-triviality. * process.c, process.h: Revamp. Use a full-blown procstat structure instead of just the procinfo fetched from the process server. Use the additional data to complement [pid]/stat. (process_lookup_pid): Get a ps_context structure instead of a port to the process server. * main.c (root_make_node): Convert to the new interface for proclist_create_node. --- Makefile | 2 +- main.c | 7 +- process.c | 267 ++++++++++++++++++++++++++++++++----------------------------- process.h | 8 +- procfs.c | 2 +- proclist.c | 35 ++++---- proclist.h | 2 +- 7 files changed, 164 insertions(+), 159 deletions(-) (limited to 'process.c') diff --git a/Makefile b/Makefile index 97a61ed4..48013f95 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ TARGET = procfs OBJS = procfs.o netfs.o procfs_file.o procfs_dir.o \ process.o proclist.o dircat.o main.o -LIBS = -lnetfs +LIBS = -lnetfs -lps CC = gcc CFLAGS = -Wall -g diff --git a/main.c b/main.c index 15602819..75e1cda3 100644 --- a/main.c +++ b/main.c @@ -25,16 +25,17 @@ root_make_node (struct node **np) /* We never have two root nodes alive simultaneously, so it's ok to have this as static data. */ static struct node *root_dirs[3]; + error_t err; root_dirs[0] = procfs_dir_make_node (static_entries, NULL, NULL); if (! root_dirs[0]) return ENOMEM; - root_dirs[1] = proclist_make_node (getproc ()); - if (! root_dirs[1]) + err = proclist_create_node (getproc (), &root_dirs[1]); + if (err) { netfs_nrele (root_dirs[0]); - return ENOMEM; + return err; } root_dirs[2] = NULL; diff --git a/process.c b/process.c index 2b89ef81..a1cc0f61 100644 --- a/process.c +++ b/process.c @@ -1,100 +1,75 @@ #include #include +#include #include +#include +#include +#include #include "procfs.h" #include "procfs_dir.h" #include "process.h" + +/* Implementations for the process_file_desc.get_contents callback. */ -struct process_node { - process_t procserv; - pid_t pid; - struct procinfo info; -}; - - -/* The proc_getprocargs() and proc_getprocenv() calls have the same - prototype and we use them in the same way; namely, publish the data - they return as-is. We take advantage of this to have common code and - use a function pointer as the procfs_dir "entry hook" to choose the - call to use on a file by file basis. */ - -struct process_argz_node +static char * +process_file_gc_cmdline (struct proc_stat *ps, size_t *len) { - struct process_node pn; - error_t (*getargz) (process_t, pid_t, void **, mach_msg_type_number_t *); -}; + *len = proc_stat_args_len(ps); + return proc_stat_args(ps); +} -static error_t -process_argz_get_contents (void *hook, void **contents, size_t *contents_len) +static char * +process_file_gc_environ (struct proc_stat *ps, size_t *len) { - struct process_argz_node *pz = hook; - error_t err; - - *contents_len = 0; - err = pz->getargz (pz->pn.procserv, pz->pn.pid, contents, contents_len); - if (err) - return EIO; - - return 0; + *len = proc_stat_args_len(ps); + return proc_stat_args(ps); } -static struct node * -process_argz_make_node (void *dir_hook, void *entry_hook) +static char state_char (struct proc_stat *ps) { - static const struct procfs_node_ops ops = { - .get_contents = process_argz_get_contents, - .cleanup_contents = procfs_cleanup_contents_with_vm_deallocate, - .cleanup = free, - }; - struct process_argz_node *zn; - - zn = malloc (sizeof *zn); - if (! zn) - return NULL; + int i; - memcpy (&zn->pn, dir_hook, sizeof zn->pn); - zn->getargz = entry_hook; + for (i = 0; (1 << i) & (PSTAT_STATE_P_STATES | PSTAT_STATE_T_STATES); i++) + if (proc_stat_state (ps) & (1 << i)) + return proc_stat_state_tags[i]; - return procfs_make_node (&ops, zn); + return '?'; } -/* The other files don't need any information besides the data in struct - process_node. Furthermore, their contents don't have any nul byte. - Consequently, we use a simple "multiplexer" based on the information - below. */ - -struct process_file_node +static long int sc_tv (time_value_t tv) { - struct process_node pn; - error_t (*get_contents) (struct process_node *pn, char **contents); -}; + double usecs = ((double) tv.seconds) * 1000000 + tv.microseconds; + return usecs * sysconf(_SC_CLK_TCK) / 1000000; +} -static char mapstate (int hurd_state) +static long long int jiff_tv (time_value_t tv) { - return '?'; + double usecs = ((double) tv.seconds) * 1000000 + tv.microseconds; + /* Let's say a jiffy is 1/100 of a second.. */ + return usecs * 100 / 1000000; } -static error_t -process_file_gc_stat (struct process_node *pn, char **contents) +static char * +process_file_gc_stat (struct proc_stat *ps, size_t *len) { - char *argz; - size_t argz_len; - int len; - - argz = NULL, argz_len = 0; - proc_getprocargs(pn->procserv, pn->pid, &argz, &argz_len); - - len = asprintf (contents, + struct procinfo *pi = proc_stat_proc_info (ps); + task_basic_info_t tbi = proc_stat_task_basic_info (ps); + thread_basic_info_t thbi = proc_stat_thread_basic_info (ps); + char *contents; + + /* See proc(5) for more information about the contents of each field for the + Linux procfs. */ + *len = asprintf (&contents, "%d (%s) %c " /* pid, command, state */ "%d %d %d " /* ppid, pgid, session */ "%d %d " /* controling tty stuff */ "%u " /* flags, as defined by */ "%lu %lu %lu %lu " /* page fault counts */ "%lu %lu %ld %ld " /* user/sys times, in sysconf(_SC_CLK_TCK) */ - "%ld %ld " /* scheduler params (priority, nice) */ - "%ld %ld " /* number of threads, [obsolete] */ + "%d %d " /* scheduler params (priority, nice) */ + "%d %ld " /* number of threads, [obsolete] */ "%llu " /* start time since boot (jiffies) */ - "%lu %ld %lu " /* virtual size, rss, rss limit */ + "%lu %ld %lu " /* virtual size (bytes), rss (pages), rss lim */ "%lu %lu %lu %lu %lu " /* some vm addresses (code, stack, sp, pc) */ "%lu %lu %lu %lu " /* pending, blocked, ignored and caught sigs */ "%lu " /* wait channel */ @@ -104,44 +79,71 @@ process_file_gc_stat (struct process_node *pn, char **contents) "%u %u " /* RT priority and policy */ "%llu " /* aggregated block I/O delay */ "\n", - pn->pid, argz ?: "", mapstate (pn->info.state), - pn->info.ppid, pn->info.pgrp, pn->info.session, - 0, 0, - 0, - 0L, 0L, 0L, 0L, - 0L, 0L, 0L, 0L, - 0L, 0L, - 0L, 0L, - 0LL, - 0L, 0L, 0L, + proc_stat_pid (ps), proc_stat_args (ps), state_char (ps), + pi->ppid, pi->pgrp, pi->session, + 0, 0, /* no such thing as a major:minor for ctty */ + 0, /* no such thing as CLONE_* flags on Hurd */ + 0L, 0L, 0L, 0L, /* TASK_EVENTS_INFO is unavailable on GNU Mach */ + sc_tv (thbi->user_time), sc_tv (thbi->system_time), + 0L, 0L, /* cumulative time for children */ + MACH_PRIORITY_TO_NICE(thbi->base_priority) + 20, + MACH_PRIORITY_TO_NICE(thbi->base_priority), + pi->nthreads, 0L, + jiff_tv (thbi->creation_time), /* FIXME: ... since boot */ + (long unsigned int) tbi->virtual_size, + (long unsigned int) tbi->resident_size / PAGE_SIZE, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, - 0L, + (long unsigned int) proc_stat_thread_rpc (ps), /* close enough */ 0L, 0L, 0, 0, 0, 0, 0LL); - vm_deallocate (mach_task_self (), (vm_address_t) argz, argz_len); + return len >= 0 ? contents : NULL; +} - if (len < 0) - return ENOMEM; - return 0; -} +/* Describes a file in a process directory. This is used as an "entry hook" + * for our procfs_dir entry table, passed to process_file_make_node. */ +struct process_file_desc +{ + /* The proc_stat information required to get the contents of this file. */ + ps_flags_t needs; + + /* Once we have acquired the necessary information, there can be only + memory allocation errors, hence this simplified signature. */ + char *(*get_contents) (struct proc_stat *ps, size_t *len); + + /* The cmdline and environ contents don't need any cleaning since they are + part of a proc_stat structure. */ + int no_cleanup; +}; + +/* Information associated to an actual file node. */ +struct process_file_node +{ + const struct process_file_desc *desc; + struct proc_stat *ps; +}; static error_t process_file_get_contents (void *hook, void **contents, size_t *contents_len) { - struct process_file_node *fn = hook; + struct process_file_node *file = hook; error_t err; - err = fn->get_contents (&fn->pn, (char **) contents); + err = proc_stat_set_flags (file->ps, file->desc->needs); if (err) - return err; + return EIO; + if ((proc_stat_flags (file->ps) & file->desc->needs) != file->desc->needs) + return EIO; + + *contents = file->desc->get_contents (file->ps, contents_len); + if (! *contents) + return ENOMEM; - *contents_len = strlen (*contents); return 0; } @@ -153,68 +155,75 @@ process_file_make_node (void *dir_hook, void *entry_hook) .cleanup_contents = procfs_cleanup_contents_with_free, .cleanup = free, }; - struct process_file_node *fn; + static const struct procfs_node_ops ops_no_cleanup = { + .get_contents = process_file_get_contents, + .cleanup = free, + }; + struct process_file_node *f; - fn = malloc (sizeof *fn); - if (! fn) + f = malloc (sizeof *f); + if (! f) return NULL; - memcpy (&fn->pn, dir_hook, sizeof fn->pn); - fn->get_contents = entry_hook; + f->desc = entry_hook; + f->ps = dir_hook; - return procfs_make_node (&ops, fn); + return procfs_make_node (f->desc->no_cleanup ? &ops_no_cleanup : &ops, f); } -static struct node * -process_make_node (process_t procserv, pid_t pid, const struct procinfo *info) -{ - static const struct procfs_dir_entry entries[] = { - { "cmdline", process_argz_make_node, proc_getprocargs, }, - { "environ", process_argz_make_node, proc_getprocenv, }, - { "stat", process_file_make_node, process_file_gc_stat, }, - { NULL, } - }; - struct process_node *pn; - struct node *np; - - pn = malloc (sizeof *pn); - if (! pn) - return NULL; - - pn->procserv = procserv; - pn->pid = pid; - memcpy (&pn->info, info, sizeof pn->info); - - np = procfs_dir_make_node (entries, pn, process_cleanup); - np->nn_stat.st_uid = pn->info.owner; - - return np; -} +static struct procfs_dir_entry entries[] = { + { + .name = "cmdline", + .make_node = process_file_make_node, + .hook = & (struct process_file_desc) { + .get_contents = process_file_gc_cmdline, + .needs = PSTAT_ARGS, + .no_cleanup = 1, + }, + }, + { + .name = "environ", + .make_node = process_file_make_node, + .hook = & (struct process_file_desc) { + .get_contents = process_file_gc_environ, + .needs = PSTAT_ENV, + .no_cleanup = 1, + }, + }, + { + .name = "stat", + .make_node = process_file_make_node, + .hook = & (struct process_file_desc) { + .get_contents = process_file_gc_stat, + .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO + | PSTAT_TASK | PSTAT_TASK_BASIC | PSTAT_THREAD_BASIC + | PSTAT_THREAD_WAIT, + }, + }, + {} +}; error_t -process_lookup_pid (process_t procserv, pid_t pid, struct node **np) +process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) { - procinfo_t info; - size_t info_sz; - data_t tw; - size_t tw_sz; - int flags; + struct proc_stat *ps; error_t err; - tw_sz = info_sz = 0, flags = 0; - err = proc_getprocinfo (procserv, pid, &flags, &info, &info_sz, &tw, &tw_sz); + err = _proc_stat_create (pid, pc, &ps); if (err == ESRCH) return ENOENT; if (err) return EIO; - assert (info_sz * sizeof *info >= sizeof (struct procinfo)); - *np = process_make_node (procserv, pid, (struct procinfo *) info); - vm_deallocate (mach_task_self (), (vm_address_t) info, info_sz); + err = proc_stat_set_flags (ps, PSTAT_OWNER_UID); + if (err || ! (proc_stat_flags (ps) & PSTAT_OWNER_UID)) + return EIO; + *np = procfs_dir_make_node (entries, ps, (void (*)(void *)) _proc_stat_free); if (! *np) return ENOMEM; + (*np)->nn_stat.st_uid = proc_stat_owner_uid (ps); return 0; } diff --git a/process.h b/process.h index abdaaa3b..8c2ee636 100644 --- a/process.h +++ b/process.h @@ -1,8 +1,8 @@ -#include +#include -/* Create a node for a directory representing information available at - the proc server PROC for the given PID. On success, returns the +/* Create a node for a directory representing the given PID, as published by + the proc server refrenced by the libps context PC. On success, returns the newly created node in *NP. */ error_t -process_lookup_pid (process_t proc, pid_t pid, struct node **np); +process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np); diff --git a/procfs.c b/procfs.c index 4cce46b9..0a235a76 100644 --- a/procfs.c +++ b/procfs.c @@ -87,7 +87,7 @@ procfs_make_ino (struct node *np, const char *filename) jrand48 (x); } - return jrand48 (x); + return (unsigned long) jrand48 (x); } error_t procfs_get_contents (struct node *np, void **data, size_t *data_len) diff --git a/proclist.c b/proclist.c index 94a7a04d..56a3fdf9 100644 --- a/proclist.c +++ b/proclist.c @@ -3,27 +3,23 @@ #include #include #include +#include #include "procfs.h" #include "process.h" #define PID_STR_SIZE (3 * sizeof (pid_t) + 1) -struct proclist_node -{ - process_t process; -}; - static error_t proclist_get_contents (void *hook, void **contents, size_t *contents_len) { - struct proclist_node *pl = hook; + struct ps_context *pc = hook; pidarray_t pids; mach_msg_type_number_t num_pids; error_t err; int i; num_pids = 0; - err = proc_getallpids (pl->process, &pids, &num_pids); + err = proc_getallpids (pc->server, &pids, &num_pids); if (err) return EIO; @@ -48,7 +44,7 @@ proclist_get_contents (void *hook, void **contents, size_t *contents_len) static error_t proclist_lookup (void *hook, const char *name, struct node **np) { - struct proclist_node *pl = hook; + struct ps_context *pc = hook; char *endp; pid_t pid; @@ -63,28 +59,27 @@ proclist_lookup (void *hook, const char *name, struct node **np) if (*endp) return ENOENT; - return process_lookup_pid (pl->process, pid, np); + return process_lookup_pid (pc, pid, np); } -struct node * -proclist_make_node (process_t process) +error_t +proclist_create_node (process_t procserv, struct node **np) { static const struct procfs_node_ops ops = { .get_contents = proclist_get_contents, .lookup = proclist_lookup, .cleanup_contents = procfs_cleanup_contents_with_free, - .cleanup = free, + .cleanup = (void (*)(void *)) ps_context_free, .enable_refresh_hack_and_break_readdir = 1, }; - struct proclist_node *pl; - - pl = malloc (sizeof *pl); - if (! pl) - return NULL; + struct ps_context *pc; + error_t err; - memset (pl, 0, sizeof *pl); - pl->process = process; + err = ps_context_create (procserv, &pc); + if (err) + return err; - return procfs_make_node (&ops, pl); + *np = procfs_make_node (&ops, pc); + return 0; } diff --git a/proclist.h b/proclist.h index a766d50e..1c7ab084 100644 --- a/proclist.h +++ b/proclist.h @@ -1,2 +1,2 @@ #include -struct node *proclist_make_node (process_t process); +error_t proclist_create_node (process_t procserv, struct node **np); -- cgit v1.2.3 From 75f53efdc66be8c6ffac31bd17a309f9065e273c Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Sat, 21 Aug 2010 11:21:59 +0000 Subject: Encapsulate access to node->nn_stat * procfs.c, procfs.h (procfs_node_chown, procfs_node_chmod, procfs_node_chtype): New functions, encapsulate access to some nn_stat fields. * process.c (process_lookup_pid): Use procfs_node_chown instead of direct access. --- process.c | 2 +- procfs.c | 19 +++++++++++++++++++ procfs.h | 13 +++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) (limited to 'process.c') diff --git a/process.c b/process.c index a1cc0f61..779a2e18 100644 --- a/process.c +++ b/process.c @@ -224,6 +224,6 @@ process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) if (! *np) return ENOMEM; - (*np)->nn_stat.st_uid = proc_stat_owner_uid (ps); + procfs_node_chown (*np, proc_stat_owner_uid (ps)); return 0; } diff --git a/procfs.c b/procfs.c index 0a235a76..5396ecf7 100644 --- a/procfs.c +++ b/procfs.c @@ -67,6 +67,25 @@ fail: return NULL; } +void procfs_node_chown (struct node *np, uid_t owner) +{ + np->nn_stat.st_uid = owner; +} + +void procfs_node_chmod (struct node *np, mode_t mode) +{ + np->nn_stat.st_mode = (np->nn_stat.st_mode & S_IFMT) | mode; + np->nn_translated = np->nn_stat.st_mode; +} + +void procfs_node_chtype (struct node *np, mode_t type) +{ + np->nn_stat.st_mode = (np->nn_stat.st_mode & ~S_IFMT) | type; + np->nn_translated = np->nn_stat.st_mode; + if (type == S_IFLNK) + procfs_node_chmod (np, 0777); +} + /* FIXME: possibly not the fastest hash function... */ ino64_t procfs_make_ino (struct node *np, const char *filename) diff --git a/procfs.h b/procfs.h index 4c9d828b..4ab3b567 100644 --- a/procfs.h +++ b/procfs.h @@ -48,6 +48,19 @@ void procfs_cleanup_contents_with_vm_deallocate (void *, void *, size_t); enough memory. In this case, ops->cleanup will be invoked. */ struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook); +/* Set the owner of the node NP. Must be called right after the node + has been created. */ +void procfs_node_chown (struct node *np, uid_t owner); + +/* Set the permission bits of the node NP. Must be called right after + the node has been created. */ +void procfs_node_chmod (struct node *np, mode_t mode); + +/* Set the type of the node NP. If type is S_IFLNK, appropriate + permission bits will be set as well. Must be called right after the + node has been created. */ +void procfs_node_chtype (struct node *np, mode_t type); + /* Interface for the libnetfs side. */ -- cgit v1.2.3 From 80e439d146f661c416b7f42c4180b16aae7ac2f7 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Sat, 21 Aug 2010 18:06:16 +0000 Subject: Set a restrictive mode on some sensitive files * process.c (process_file_make_node, entries): Set the environ and stat files as readable only by the owner of the process. --- process.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'process.c') diff --git a/process.c b/process.c index 779a2e18..8955cf40 100644 --- a/process.c +++ b/process.c @@ -119,6 +119,9 @@ struct process_file_desc /* The cmdline and environ contents don't need any cleaning since they are part of a proc_stat structure. */ int no_cleanup; + + /* If specified, the file mode to be set with procfs_node_chmod(). */ + mode_t mode; }; /* Information associated to an actual file node. */ @@ -160,6 +163,7 @@ process_file_make_node (void *dir_hook, void *entry_hook) .cleanup = free, }; struct process_file_node *f; + struct node *np; f = malloc (sizeof *f); if (! f) @@ -168,7 +172,15 @@ process_file_make_node (void *dir_hook, void *entry_hook) f->desc = entry_hook; f->ps = dir_hook; - return procfs_make_node (f->desc->no_cleanup ? &ops_no_cleanup : &ops, f); + np = procfs_make_node (f->desc->no_cleanup ? &ops_no_cleanup : &ops, f); + if (! np) + return NULL; + + procfs_node_chown (np, proc_stat_owner_uid (f->ps)); + if (f->desc->mode) + procfs_node_chmod (np, f->desc->mode); + + return np; } @@ -189,6 +201,7 @@ static struct procfs_dir_entry entries[] = { .get_contents = process_file_gc_environ, .needs = PSTAT_ENV, .no_cleanup = 1, + .mode = 0400, }, }, { @@ -199,6 +212,7 @@ static struct procfs_dir_entry entries[] = { .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO | PSTAT_TASK | PSTAT_TASK_BASIC | PSTAT_THREAD_BASIC | PSTAT_THREAD_WAIT, + .mode = 0400, }, }, {} -- cgit v1.2.3 From b3427143ae8dc628cb3748da7618700c6bd7ac9e Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Sun, 22 Aug 2010 20:17:54 +0000 Subject: Add --clk-tck to set the clock unit * main.c (argp_parser, main): Add and parse the --clk-tck option. * main.h: Publish opt_clk_tck. * process.c (sc_tc): Use the user-provided clock frequency. * rootdir.c (rootdir_gc_stat): Likewise. --- main.c | 40 +++++++++++++++++++++++++++++++++++++++- main.h | 2 ++ process.c | 3 ++- rootdir.c | 3 ++- 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 main.h (limited to 'process.c') diff --git a/main.c b/main.c index 15ad60f4..a59ab47f 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -7,6 +8,42 @@ #include "proclist.h" #include "rootdir.h" #include "dircat.h" +#include "main.h" + +/* Command-line options */ +int opt_clk_tck; + +static error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + char *endp; + + switch (key) + { + case 'h': + opt_clk_tck = strtol (arg, &endp, 0); + if (*endp || ! *arg || opt_clk_tck <= 0) + error (1, 0, "--clk-tck: HZ should be a positive integer"); + break; + } + + return 0; +} + +struct argp argp = { + .options = (struct argp_option []) { + { "clk-tck", 'h', "HZ", 0, + "Unit used for the values expressed in system clock ticks " + "(default: sysconf(_SC_CLK_TCK))" }, + {} + }, + .parser = argp_parser, + .doc = "A virtual filesystem emulating the Linux procfs.", + .children = (struct argp_child []) { + { &netfs_std_startup_argp, }, + {} + }, +}; error_t root_make_node (struct node **np) @@ -43,7 +80,8 @@ int main (int argc, char **argv) { mach_port_t bootstrap; - argp_parse (&netfs_std_startup_argp, argc, argv, 0, 0, 0); + opt_clk_tck = sysconf(_SC_CLK_TCK); + argp_parse (&argp, argc, argv, 0, 0, 0); task_get_bootstrap_port (mach_task_self (), &bootstrap); if (bootstrap == MACH_PORT_NULL) diff --git a/main.h b/main.h new file mode 100644 index 00000000..4b2ef9a1 --- /dev/null +++ b/main.h @@ -0,0 +1,2 @@ +/* Startup options */ +extern int opt_clk_tck; diff --git a/process.c b/process.c index 8955cf40..65f0e503 100644 --- a/process.c +++ b/process.c @@ -8,6 +8,7 @@ #include "procfs.h" #include "procfs_dir.h" #include "process.h" +#include "main.h" /* Implementations for the process_file_desc.get_contents callback. */ @@ -39,7 +40,7 @@ static char state_char (struct proc_stat *ps) static long int sc_tv (time_value_t tv) { double usecs = ((double) tv.seconds) * 1000000 + tv.microseconds; - return usecs * sysconf(_SC_CLK_TCK) / 1000000; + return usecs * opt_clk_tck / 1000000; } static long long int jiff_tv (time_value_t tv) diff --git a/rootdir.c b/rootdir.c index 50f6e071..1d9c083c 100644 --- a/rootdir.c +++ b/rootdir.c @@ -7,6 +7,7 @@ #include #include "procfs.h" #include "procfs_dir.h" +#include "main.h" /* This implements a directory node with the static files in /proc */ @@ -105,7 +106,7 @@ rootdir_gc_stat (void *hook, void **contents, size_t *contents_len) return EIO; timersub (&time, &boottime, &time); - up_ticks = sysconf(_SC_CLK_TCK) * (time.tv_sec + time.tv_usec / 1000000.); + up_ticks = opt_clk_tck * (time.tv_sec + time.tv_usec / 1000000.); *contents_len = asprintf ((char **) contents, /* Does Mach keeps track of any of this? */ -- cgit v1.2.3 From 5714e1cef2584410a7823c7ead9d2435141fb0c4 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Sun, 22 Aug 2010 20:46:54 +0000 Subject: Add --stat-mode to override the perms for [pid]/stat * main.c (argp_parser, main): Add the --stat-mode option. * process.c (process_lookup_pid): Use it. --- main.c | 14 ++++++++++++++ main.h | 1 + process.c | 5 +++++ 3 files changed, 20 insertions(+) (limited to 'process.c') diff --git a/main.c b/main.c index a59ab47f..09cffc76 100644 --- a/main.c +++ b/main.c @@ -12,6 +12,7 @@ /* Command-line options */ int opt_clk_tck; +mode_t opt_stat_mode; static error_t argp_parser (int key, char *arg, struct argp_state *state) @@ -25,6 +26,12 @@ argp_parser (int key, char *arg, struct argp_state *state) if (*endp || ! *arg || opt_clk_tck <= 0) error (1, 0, "--clk-tck: HZ should be a positive integer"); break; + + case 's': + opt_stat_mode = strtol (arg, &endp, 8); + if (*endp || ! *arg || opt_stat_mode & ~07777) + error (1, 0, "--stat-mode: MODE should be an octal mode"); + break; } return 0; @@ -35,6 +42,12 @@ struct argp argp = { { "clk-tck", 'h', "HZ", 0, "Unit used for the values expressed in system clock ticks " "(default: sysconf(_SC_CLK_TCK))" }, + { "stat-mode", 's', "MODE", 0, + "The [pid]/stat file publishes information which on Hurd is only " + "available to the process owner. " + "You can use this option to override its mode to be more permissive " + "for compatibility purposes. " + "(default: 0400)" }, {} }, .parser = argp_parser, @@ -81,6 +94,7 @@ int main (int argc, char **argv) mach_port_t bootstrap; opt_clk_tck = sysconf(_SC_CLK_TCK); + opt_stat_mode = 0400; argp_parse (&argp, argc, argv, 0, 0, 0); task_get_bootstrap_port (mach_task_self (), &bootstrap); diff --git a/main.h b/main.h index 4b2ef9a1..6669d321 100644 --- a/main.h +++ b/main.h @@ -1,2 +1,3 @@ /* Startup options */ extern int opt_clk_tck; +extern mode_t opt_stat_mode; diff --git a/process.c b/process.c index 65f0e503..f7a7a577 100644 --- a/process.c +++ b/process.c @@ -206,6 +206,7 @@ static struct procfs_dir_entry entries[] = { }, }, { + /* Beware of the hack below, which requires this to be entries[2]. */ .name = "stat", .make_node = process_file_make_node, .hook = & (struct process_file_desc) { @@ -235,6 +236,10 @@ process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) if (err || ! (proc_stat_flags (ps) & PSTAT_OWNER_UID)) return EIO; + /* FIXME: have a separate proc_desc structure for each file, so this can be + accessed in a more robust and straightforward way. */ + ((struct process_file_desc *) entries[2].hook)->mode = opt_stat_mode; + *np = procfs_dir_make_node (entries, ps, (void (*)(void *)) _proc_stat_free); if (! *np) return ENOMEM; -- cgit v1.2.3 From e873ff83afba08ff61a5e98ab90d5ee05ab5c601 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 05:44:37 +0000 Subject: Add statm to process directories * process.c: Add the statm file. --- process.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'process.c') diff --git a/process.c b/process.c index f7a7a577..4404d084 100644 --- a/process.c +++ b/process.c @@ -105,6 +105,20 @@ process_file_gc_stat (struct proc_stat *ps, size_t *len) return len >= 0 ? contents : NULL; } +static char * +process_file_gc_statm (struct proc_stat *ps, size_t *len) +{ + task_basic_info_t tbi = proc_stat_task_basic_info (ps); + char *contents; + + *len = asprintf (&contents, + "%lu %lu 0 0 0 0 0\n", + tbi->virtual_size / sysconf(_SC_PAGE_SIZE), + tbi->resident_size / sysconf(_SC_PAGE_SIZE)); + + return len >= 0 ? contents : NULL; +} + /* Describes a file in a process directory. This is used as an "entry hook" * for our procfs_dir entry table, passed to process_file_make_node. */ @@ -217,6 +231,15 @@ static struct procfs_dir_entry entries[] = { .mode = 0400, }, }, + { + .name = "statm", + .make_node = process_file_make_node, + .hook = & (struct process_file_desc) { + .get_contents = process_file_gc_statm, + .needs = PSTAT_TASK_BASIC, + .mode = 0444, + }, + }, {} }; -- cgit v1.2.3 From abd1ad000a2861b46df445888365678686e31bcb Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 07:14:45 +0000 Subject: Add a status file to process directories * process.c: Add a status file. --- process.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'process.c') diff --git a/process.c b/process.c index 4404d084..b2b098ff 100644 --- a/process.c +++ b/process.c @@ -37,6 +37,27 @@ static char state_char (struct proc_stat *ps) return '?'; } +static const char *state_string (struct proc_stat *ps) +{ + static const char *const state_strings[] = { + "T (stopped)", + "Z (zombie)", + "R (running)", + "H (halted)", + "D (disk sleep)", + "S (sleeping)", + "I (idle)", + NULL + }; + int i; + + for (i = 0; state_strings[i]; i++) + if (proc_stat_state (ps) & (1 << i)) + return state_strings[i]; + + return "? (unknown)"; +} + static long int sc_tv (time_value_t tv) { double usecs = ((double) tv.seconds) * 1000000 + tv.microseconds; @@ -119,6 +140,42 @@ process_file_gc_statm (struct proc_stat *ps, size_t *len) return len >= 0 ? contents : NULL; } +static char * +process_file_gc_status (struct proc_stat *ps, size_t *len) +{ + task_basic_info_t tbi = proc_stat_task_basic_info (ps); + char *contents; + + *len = asprintf (&contents, + "Name:\t%s\n" + "State:\t%s\n" + "Tgid:\t%u\n" + "Pid:\t%u\n" + "PPid:\t%u\n" + "Uid:\t%u\t%u\t%u\t%u\n" + "VmSize:\t%8u kB\n" + "VmPeak:\t%8u kB\n" + "VmRSS:\t%8u kB\n" + "VmHWM:\t%8u kB\n" /* ie. resident peak */ + "Threads:\t%u\n", + proc_stat_args (ps), + state_string (ps), + proc_stat_pid (ps), /* XXX will need more work for threads */ + proc_stat_pid (ps), + proc_stat_proc_info (ps)->ppid, + proc_stat_owner_uid (ps), + proc_stat_owner_uid (ps), + proc_stat_owner_uid (ps), + proc_stat_owner_uid (ps), + tbi->virtual_size / 1024, + tbi->virtual_size / 1024, + tbi->resident_size / 1024, + tbi->resident_size / 1024, + proc_stat_num_threads (ps)); + + return len >= 0 ? contents : NULL; +} + /* Describes a file in a process directory. This is used as an "entry hook" * for our procfs_dir entry table, passed to process_file_make_node. */ @@ -240,6 +297,16 @@ static struct procfs_dir_entry entries[] = { .mode = 0444, }, }, + { + .name = "status", + .make_node = process_file_make_node, + .hook = & (struct process_file_desc) { + .get_contents = process_file_gc_status, + .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO + | PSTAT_TASK_BASIC | PSTAT_OWNER_UID | PSTAT_NUM_THREADS, + .mode = 0444, + }, + }, {} }; -- cgit v1.2.3 From 0439361f817c3f610c1f5ec859bd302867472e50 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 11:02:13 +0000 Subject: Fix the handling of processes without an owner * main.c (argp_parser): New option --anonymous-owner. * main.h: Publish it. * process.c (process_lookup_pid): Use it to set the file owner uid of non-owned processes. --- main.c | 22 ++++++++++++++++++++++ main.h | 1 + process.c | 4 +++- 3 files changed, 26 insertions(+), 1 deletion(-) (limited to 'process.c') diff --git a/main.c b/main.c index 91156485..06c1da04 100644 --- a/main.c +++ b/main.c @@ -16,10 +16,12 @@ int opt_clk_tck; mode_t opt_stat_mode; pid_t opt_fake_self; pid_t opt_kernel_pid; +uid_t opt_anon_owner; static error_t argp_parser (int key, char *arg, struct argp_state *state) { + struct passwd *pw; char *endp; switch (key) @@ -58,6 +60,20 @@ argp_parser (int key, char *arg, struct argp_state *state) opt_stat_mode = 0444; opt_fake_self = 1; break; + + case 'a': + pw = getpwnam (arg); + if (pw) + { + opt_anon_owner = pw->pw_uid; + break; + } + + opt_anon_owner = strtol (arg, &endp, 0); + if (*endp || ! *arg || (signed) opt_anon_owner < 0) + error(1, 0, "--anonymous-owner: USER should be the a user name " + "or a numeric UID."); + break; } return 0; @@ -84,6 +100,11 @@ struct argp argp = { { "compatible", 'c', NULL, 0, "Try to be compatible with the Linux procps utilities. " "Currently equivalent to -h 100 -s 0444 -S 1." }, + { "anonymous-owner", 'a', "USER", 0, + "Make USER the owner of files related to processes without one. " + "Be aware that USER will be granted access to the environment and " + "other sensitive information about the processes in question. " + "(default: use uid 0)" }, {} }, .parser = argp_parser, @@ -138,6 +159,7 @@ int main (int argc, char **argv) opt_stat_mode = 0400; opt_fake_self = -1; opt_kernel_pid = 2; + opt_anon_owner = 0; err = argp_parse (&argp, argc, argv, 0, 0, 0); if (err) error (1, err, "Could not parse command line"); diff --git a/main.h b/main.h index 6ada229a..28d1b023 100644 --- a/main.h +++ b/main.h @@ -3,3 +3,4 @@ extern int opt_clk_tck; extern mode_t opt_stat_mode; extern pid_t opt_fake_self; extern pid_t opt_kernel_pid; +extern uid_t opt_anon_owner; diff --git a/process.c b/process.c index b2b098ff..7f5646ae 100644 --- a/process.c +++ b/process.c @@ -314,6 +314,7 @@ error_t process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) { struct proc_stat *ps; + int owner; error_t err; err = _proc_stat_create (pid, pc, &ps); @@ -334,6 +335,7 @@ process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) if (! *np) return ENOMEM; - procfs_node_chown (*np, proc_stat_owner_uid (ps)); + owner = proc_stat_owner_uid (ps); + procfs_node_chown (*np, owner >= 0 ? owner : opt_anon_owner); return 0; } -- cgit v1.2.3 From 0f2bdacd6ad3dbcc905925dee12cb30918c33a11 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 11:24:29 +0000 Subject: Make contents a char* to avoid typecasts all over the place * procfs.h (procfs_cleanup_contents_with_free, procfs_cleanup_contents_with_vm_deallocate, procfs_get_contents, struct procfs_ops): Change CONTENTS from a void pointer to a char one. * dircat.c, netfs.c, process.c, procfs.c, procfs_dir.c, proclist.c, rootdir.c: Update. --- dircat.c | 4 ++-- netfs.c | 10 +++++----- process.c | 2 +- procfs.c | 10 +++++----- procfs.h | 10 +++++----- procfs_dir.c | 2 +- proclist.c | 2 +- rootdir.c | 32 ++++++++++++++++---------------- 8 files changed, 36 insertions(+), 36 deletions(-) (limited to 'process.c') diff --git a/dircat.c b/dircat.c index 857ba72b..93bb2fed 100644 --- a/dircat.c +++ b/dircat.c @@ -8,7 +8,7 @@ struct dircat_node }; static error_t -dircat_get_contents (void *hook, void **contents, size_t *contents_len) +dircat_get_contents (void *hook, char **contents, size_t *contents_len) { struct dircat_node *dcn = hook; int i, sz, pos; @@ -19,7 +19,7 @@ dircat_get_contents (void *hook, void **contents, size_t *contents_len) for (i=0; dcn->dirs[i]; i++) { - void *subcon; + char *subcon; size_t sublen; err = procfs_get_contents (dcn->dirs[i], &subcon, &sublen); diff --git a/netfs.c b/netfs.c index a47861e5..6fd82a00 100644 --- a/netfs.c +++ b/netfs.c @@ -29,7 +29,7 @@ int netfs_maxsymlinks = PROCFS_MAXSYMLINKS; responsible for the operation. NP is locked. */ error_t netfs_validate_stat (struct node *np, struct iouser *cred) { - void *contents; + char *contents; size_t contents_len; error_t err; @@ -57,7 +57,7 @@ error_t netfs_attempt_read (struct iouser *cred, struct node *np, size_t contents_len; error_t err; - err = procfs_get_contents (np, (void **) &contents, &contents_len); + err = procfs_get_contents (np, &contents, &contents_len); if (err) return err; @@ -82,7 +82,7 @@ error_t netfs_attempt_readlink (struct iouser *user, struct node *np, size_t contents_len; error_t err; - err = procfs_get_contents (np, (void **) &contents, &contents_len); + err = procfs_get_contents (np, &contents, &contents_len); if (err) return err; @@ -140,7 +140,7 @@ error_t netfs_get_dirents (struct iouser *cred, struct node *dir, size_t contents_len; error_t err; - err = procfs_get_contents (dir, (void **) &contents, &contents_len); + err = procfs_get_contents (dir, &contents, &contents_len); if (err) return err; @@ -159,7 +159,7 @@ error_t netfs_get_dirents (struct iouser *cred, struct node *dir, putentries (contents, contents_len, nentries, NULL, datacnt); if (bufsize < *datacnt) { - void *n = mmap (0, *datacnt, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, 0, 0); + char *n = mmap (0, *datacnt, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, 0, 0); if (n == MAP_FAILED) return ENOMEM; diff --git a/process.c b/process.c index 7f5646ae..fa795522 100644 --- a/process.c +++ b/process.c @@ -204,7 +204,7 @@ struct process_file_node }; static error_t -process_file_get_contents (void *hook, void **contents, size_t *contents_len) +process_file_get_contents (void *hook, char **contents, size_t *contents_len) { struct process_file_node *file = hook; error_t err; diff --git a/procfs.c b/procfs.c index 5396ecf7..a5f52b50 100644 --- a/procfs.c +++ b/procfs.c @@ -12,7 +12,7 @@ struct netnode void *hook; /* (cached) contents of the node */ - void *contents; + char *contents; size_t contents_len; /* parent directory, if applicable */ @@ -20,13 +20,13 @@ struct netnode }; void -procfs_cleanup_contents_with_free (void *hook, void *cont, size_t len) +procfs_cleanup_contents_with_free (void *hook, char *cont, size_t len) { free (cont); } void -procfs_cleanup_contents_with_vm_deallocate (void *hook, void *cont, size_t len) +procfs_cleanup_contents_with_vm_deallocate (void *hook, char *cont, size_t len) { vm_deallocate (mach_task_self (), (vm_address_t) cont, (vm_size_t) len); } @@ -109,7 +109,7 @@ procfs_make_ino (struct node *np, const char *filename) return (unsigned long) jrand48 (x); } -error_t procfs_get_contents (struct node *np, void **data, size_t *data_len) +error_t procfs_get_contents (struct node *np, char **data, size_t *data_len) { if (np->nn->ops->enable_refresh_hack_and_break_readdir && np->nn->contents) { @@ -121,7 +121,7 @@ error_t procfs_get_contents (struct node *np, void **data, size_t *data_len) if (! np->nn->contents && np->nn->ops->get_contents) { - void *contents; + char *contents; size_t contents_len; error_t err; diff --git a/procfs.h b/procfs.h index 4ab3b567..8336ee85 100644 --- a/procfs.h +++ b/procfs.h @@ -17,8 +17,8 @@ struct procfs_node_ops netnode->nn_stat. For regular files and symlinks, they are what you would expect; for directories, they are an argz vector of the names of the entries. */ - error_t (*get_contents) (void *hook, void **contents, size_t *contents_len); - void (*cleanup_contents) (void *hook, void *contents, size_t contents_len); + error_t (*get_contents) (void *hook, char **contents, size_t *contents_len); + void (*cleanup_contents) (void *hook, char *contents, size_t contents_len); /* Lookup NAME in this directory, and store the result in *np. The returned node should be created by lookup() using procfs_make_node() @@ -41,8 +41,8 @@ struct procfs_node_ops }; /* These helper functions can be used as procfs_node_ops.cleanup_contents. */ -void procfs_cleanup_contents_with_free (void *, void *, size_t); -void procfs_cleanup_contents_with_vm_deallocate (void *, void *, size_t); +void procfs_cleanup_contents_with_free (void *, char *, size_t); +void procfs_cleanup_contents_with_vm_deallocate (void *, char *, size_t); /* Create a new node and return it. Returns NULL if it fails to allocate enough memory. In this case, ops->cleanup will be invoked. */ @@ -69,7 +69,7 @@ void procfs_node_chtype (struct node *np, mode_t type); corresponding child nodes. */ ino64_t procfs_make_ino (struct node *np, const char *filename); -error_t procfs_get_contents (struct node *np, void **data, size_t *data_len); +error_t procfs_get_contents (struct node *np, char **data, size_t *data_len); error_t procfs_lookup (struct node *np, const char *name, struct node **npp); void procfs_cleanup (struct node *np); diff --git a/procfs_dir.c b/procfs_dir.c index 431fea3e..4df46695 100644 --- a/procfs_dir.c +++ b/procfs_dir.c @@ -11,7 +11,7 @@ struct procfs_dir_node }; static error_t -procfs_dir_get_contents (void *hook, void **contents, size_t *contents_len) +procfs_dir_get_contents (void *hook, char **contents, size_t *contents_len) { static const char dot_dotdot[] = ".\0.."; struct procfs_dir_node *dn = hook; diff --git a/proclist.c b/proclist.c index 35422a81..b5acb26c 100644 --- a/proclist.c +++ b/proclist.c @@ -10,7 +10,7 @@ #define PID_STR_SIZE (3 * sizeof (pid_t) + 1) static error_t -proclist_get_contents (void *hook, void **contents, size_t *contents_len) +proclist_get_contents (void *hook, char **contents, size_t *contents_len) { struct ps_context *pc = hook; pidarray_t pids; diff --git a/rootdir.c b/rootdir.c index 8062f0d3..cd8949bf 100644 --- a/rootdir.c +++ b/rootdir.c @@ -44,7 +44,7 @@ get_boottime (struct ps_context *pc, struct timeval *tv) } static error_t -rootdir_gc_version (void *hook, void **contents, size_t *contents_len) +rootdir_gc_version (void *hook, char **contents, size_t *contents_len) { struct utsname uts; int r; @@ -53,7 +53,7 @@ rootdir_gc_version (void *hook, void **contents, size_t *contents_len) if (r < 0) return errno; - *contents_len = asprintf ((char **) contents, + *contents_len = asprintf (contents, "Linux version 2.6.1 (%s %s %s %s)\n", uts.sysname, uts.release, uts.version, uts.machine); @@ -63,7 +63,7 @@ rootdir_gc_version (void *hook, void **contents, size_t *contents_len) /* Uptime -- we use the start time of init to deduce it. This is probably a bit fragile, as any clock update will make the result inaccurate. */ static error_t -rootdir_gc_uptime (void *hook, void **contents, size_t *contents_len) +rootdir_gc_uptime (void *hook, char **contents, size_t *contents_len) { struct timeval time, boottime; double up_secs; @@ -85,13 +85,13 @@ rootdir_gc_uptime (void *hook, void **contents, size_t *contents_len) proc(5) specifies that it should be equal to USER_HZ times the idle value in ticks from /proc/stat. So we assume a completely idle system both here and there to make that work. */ - *contents_len = asprintf ((char **) contents, "%.2lf %.2lf\n", up_secs, up_secs); + *contents_len = asprintf (contents, "%.2lf %.2lf\n", up_secs, up_secs); return *contents_len >= 0 ? 0 : ENOMEM; } static error_t -rootdir_gc_stat (void *hook, void **contents, size_t *contents_len) +rootdir_gc_stat (void *hook, char **contents, size_t *contents_len) { struct timeval boottime, time; struct vm_statistics vmstats; @@ -113,7 +113,7 @@ rootdir_gc_stat (void *hook, void **contents, size_t *contents_len) timersub (&time, &boottime, &time); up_ticks = opt_clk_tck * (time.tv_sec + time.tv_usec / 1000000.); - *contents_len = asprintf ((char **) contents, + *contents_len = asprintf (contents, /* Does Mach keeps track of any of this? */ "cpu 0 0 0 %lu 0 0 0 0 0\n" "cpu0 0 0 0 %lu 0 0 0 0 0\n" @@ -130,7 +130,7 @@ rootdir_gc_stat (void *hook, void **contents, size_t *contents_len) } static error_t -rootdir_gc_loadavg (void *hook, void **contents, size_t *contents_len) +rootdir_gc_loadavg (void *hook, char **contents, size_t *contents_len) { host_load_info_data_t hli; mach_msg_type_number_t cnt; @@ -142,7 +142,7 @@ rootdir_gc_loadavg (void *hook, void **contents, size_t *contents_len) return err; assert (cnt == HOST_LOAD_INFO_COUNT); - *contents_len = asprintf ((char **) contents, + *contents_len = asprintf (contents, "%.2f %.2f %.2f 1/0 0\n", hli.avenrun[0] / (double) LOAD_SCALE, hli.avenrun[1] / (double) LOAD_SCALE, @@ -152,7 +152,7 @@ rootdir_gc_loadavg (void *hook, void **contents, size_t *contents_len) } static error_t -rootdir_gc_meminfo (void *hook, void **contents, size_t *contents_len) +rootdir_gc_meminfo (void *hook, char **contents, size_t *contents_len) { host_basic_info_data_t hbi; mach_msg_type_number_t cnt; @@ -169,7 +169,7 @@ rootdir_gc_meminfo (void *hook, void **contents, size_t *contents_len) return err; assert (cnt == HOST_BASIC_INFO_COUNT); - *contents_len = asprintf ((char **) contents, + *contents_len = asprintf (contents, "MemTotal: %14lu kB\n" "MemFree: %14lu kB\n" "Active: %14lu kB\n" @@ -187,7 +187,7 @@ rootdir_gc_meminfo (void *hook, void **contents, size_t *contents_len) } static error_t -rootdir_gc_vmstat (void *hook, void **contents, size_t *contents_len) +rootdir_gc_vmstat (void *hook, char **contents, size_t *contents_len) { host_basic_info_data_t hbi; mach_msg_type_number_t cnt; @@ -204,7 +204,7 @@ rootdir_gc_vmstat (void *hook, void **contents, size_t *contents_len) return err; assert (cnt == HOST_BASIC_INFO_COUNT); - *contents_len = asprintf ((char **) contents, + *contents_len = asprintf (contents, "nr_free_pages %lu\n" "nr_inactive_anon %lu\n" "nr_active_anon %lu\n" @@ -232,7 +232,7 @@ rootdir_gc_vmstat (void *hook, void **contents, size_t *contents_len) } static error_t -rootdir_gc_cmdline (void *hook, void **contents, size_t *contents_len) +rootdir_gc_cmdline (void *hook, char **contents, size_t *contents_len) { struct ps_context *pc = hook; struct proc_stat *ps; @@ -259,7 +259,7 @@ rootdir_gc_cmdline (void *hook, void **contents, size_t *contents_len) memcpy (*contents, proc_stat_args (ps), *contents_len); argz_stringify (*contents, *contents_len, ' '); - ((char *) *contents)[*contents_len - 1] = '\n'; + (*contents)[*contents_len - 1] = '\n'; out: _proc_stat_free (ps); @@ -267,9 +267,9 @@ out: } static error_t -rootdir_gc_fakeself (void *hook, void **contents, size_t *contents_len) +rootdir_gc_fakeself (void *hook, char **contents, size_t *contents_len) { - *contents_len = asprintf ((char **) contents, "%d", opt_fake_self); + *contents_len = asprintf (contents, "%d", opt_fake_self); return *contents_len >= 0 ? 0 : ENOMEM; } -- cgit v1.2.3 From 6e202c432e2f16dfa83a7dc21b759c03623fa394 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 11:33:22 +0000 Subject: Detect asprintf's ENOMEM in procfs.c rather than everywhere * procfs.h: Make CONTENTS_LEN an ssize_t rather than a size_t, and document the change. * procfs.c (procfs_get_contents): Initialize CONTENTS_LEN to a negative value, and fail with ENOMEM if it's still negative after the callback returns. (everywhere): Update to ssize_t. * dircat.c, netfs.c, process.c, procfs_dir.c, proclist.c, rootdir.c: Update to ssize_t and the new GET_CONTENTS semantics. --- dircat.c | 4 ++-- netfs.c | 8 ++++---- process.c | 54 ++++++++++++++++++++---------------------------------- procfs.c | 13 ++++++++----- procfs.h | 14 ++++++++------ procfs_dir.c | 2 +- proclist.c | 2 +- rootdir.c | 30 +++++++++++++++--------------- 8 files changed, 59 insertions(+), 68 deletions(-) (limited to 'process.c') diff --git a/dircat.c b/dircat.c index 93bb2fed..bb66508a 100644 --- a/dircat.c +++ b/dircat.c @@ -8,7 +8,7 @@ struct dircat_node }; static error_t -dircat_get_contents (void *hook, char **contents, size_t *contents_len) +dircat_get_contents (void *hook, char **contents, ssize_t *contents_len) { struct dircat_node *dcn = hook; int i, sz, pos; @@ -20,7 +20,7 @@ dircat_get_contents (void *hook, char **contents, size_t *contents_len) for (i=0; dcn->dirs[i]; i++) { char *subcon; - size_t sublen; + ssize_t sublen; err = procfs_get_contents (dcn->dirs[i], &subcon, &sublen); if (err) diff --git a/netfs.c b/netfs.c index 6fd82a00..e41e0623 100644 --- a/netfs.c +++ b/netfs.c @@ -30,7 +30,7 @@ int netfs_maxsymlinks = PROCFS_MAXSYMLINKS; error_t netfs_validate_stat (struct node *np, struct iouser *cred) { char *contents; - size_t contents_len; + ssize_t contents_len; error_t err; /* Only symlinks need to have their size filled, before a read is @@ -54,7 +54,7 @@ error_t netfs_attempt_read (struct iouser *cred, struct node *np, loff_t offset, size_t *len, void *data) { char *contents; - size_t contents_len; + ssize_t contents_len; error_t err; err = procfs_get_contents (np, &contents, &contents_len); @@ -79,7 +79,7 @@ error_t netfs_attempt_readlink (struct iouser *user, struct node *np, char *buf) { char *contents; - size_t contents_len; + ssize_t contents_len; error_t err; err = procfs_get_contents (np, &contents, &contents_len); @@ -137,7 +137,7 @@ error_t netfs_get_dirents (struct iouser *cred, struct node *dir, vm_size_t bufsize, int *amt) { char *contents; - size_t contents_len; + ssize_t contents_len; error_t err; err = procfs_get_contents (dir, &contents, &contents_len); diff --git a/process.c b/process.c index fa795522..624f79e7 100644 --- a/process.c +++ b/process.c @@ -12,18 +12,18 @@ /* Implementations for the process_file_desc.get_contents callback. */ -static char * -process_file_gc_cmdline (struct proc_stat *ps, size_t *len) +static ssize_t +process_file_gc_cmdline (struct proc_stat *ps, char **contents) { - *len = proc_stat_args_len(ps); - return proc_stat_args(ps); + *contents = proc_stat_args(ps); + return proc_stat_args_len(ps); } -static char * -process_file_gc_environ (struct proc_stat *ps, size_t *len) +static ssize_t +process_file_gc_environ (struct proc_stat *ps, char **contents) { - *len = proc_stat_args_len(ps); - return proc_stat_args(ps); + *contents = proc_stat_env(ps); + return proc_stat_env_len(ps); } static char state_char (struct proc_stat *ps) @@ -71,17 +71,16 @@ static long long int jiff_tv (time_value_t tv) return usecs * 100 / 1000000; } -static char * -process_file_gc_stat (struct proc_stat *ps, size_t *len) +static ssize_t +process_file_gc_stat (struct proc_stat *ps, char **contents) { struct procinfo *pi = proc_stat_proc_info (ps); task_basic_info_t tbi = proc_stat_task_basic_info (ps); thread_basic_info_t thbi = proc_stat_thread_basic_info (ps); - char *contents; /* See proc(5) for more information about the contents of each field for the Linux procfs. */ - *len = asprintf (&contents, + return asprintf (contents, "%d (%s) %c " /* pid, command, state */ "%d %d %d " /* ppid, pgid, session */ "%d %d " /* controling tty stuff */ @@ -122,31 +121,23 @@ process_file_gc_stat (struct proc_stat *ps, size_t *len) 0, 0, 0, 0LL); - - return len >= 0 ? contents : NULL; } -static char * -process_file_gc_statm (struct proc_stat *ps, size_t *len) +static ssize_t +process_file_gc_statm (struct proc_stat *ps, char **contents) { task_basic_info_t tbi = proc_stat_task_basic_info (ps); - char *contents; - - *len = asprintf (&contents, + return asprintf (contents, "%lu %lu 0 0 0 0 0\n", tbi->virtual_size / sysconf(_SC_PAGE_SIZE), tbi->resident_size / sysconf(_SC_PAGE_SIZE)); - - return len >= 0 ? contents : NULL; } -static char * -process_file_gc_status (struct proc_stat *ps, size_t *len) +static ssize_t +process_file_gc_status (struct proc_stat *ps, char **contents) { task_basic_info_t tbi = proc_stat_task_basic_info (ps); - char *contents; - - *len = asprintf (&contents, + return asprintf (contents, "Name:\t%s\n" "State:\t%s\n" "Tgid:\t%u\n" @@ -172,8 +163,6 @@ process_file_gc_status (struct proc_stat *ps, size_t *len) tbi->resident_size / 1024, tbi->resident_size / 1024, proc_stat_num_threads (ps)); - - return len >= 0 ? contents : NULL; } @@ -186,7 +175,7 @@ struct process_file_desc /* Once we have acquired the necessary information, there can be only memory allocation errors, hence this simplified signature. */ - char *(*get_contents) (struct proc_stat *ps, size_t *len); + ssize_t (*get_contents) (struct proc_stat *ps, char **contents); /* The cmdline and environ contents don't need any cleaning since they are part of a proc_stat structure. */ @@ -204,7 +193,7 @@ struct process_file_node }; static error_t -process_file_get_contents (void *hook, char **contents, size_t *contents_len) +process_file_get_contents (void *hook, char **contents, ssize_t *contents_len) { struct process_file_node *file = hook; error_t err; @@ -215,10 +204,7 @@ process_file_get_contents (void *hook, char **contents, size_t *contents_len) if ((proc_stat_flags (file->ps) & file->desc->needs) != file->desc->needs) return EIO; - *contents = file->desc->get_contents (file->ps, contents_len); - if (! *contents) - return ENOMEM; - + *contents_len = file->desc->get_contents (file->ps, contents); return 0; } diff --git a/procfs.c b/procfs.c index a5f52b50..6d15e4fd 100644 --- a/procfs.c +++ b/procfs.c @@ -13,20 +13,20 @@ struct netnode /* (cached) contents of the node */ char *contents; - size_t contents_len; + ssize_t contents_len; /* parent directory, if applicable */ struct node *parent; }; void -procfs_cleanup_contents_with_free (void *hook, char *cont, size_t len) +procfs_cleanup_contents_with_free (void *hook, char *cont, ssize_t len) { free (cont); } void -procfs_cleanup_contents_with_vm_deallocate (void *hook, char *cont, size_t len) +procfs_cleanup_contents_with_vm_deallocate (void *hook, char *cont, ssize_t len) { vm_deallocate (mach_task_self (), (vm_address_t) cont, (vm_size_t) len); } @@ -109,7 +109,7 @@ procfs_make_ino (struct node *np, const char *filename) return (unsigned long) jrand48 (x); } -error_t procfs_get_contents (struct node *np, char **data, size_t *data_len) +error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len) { if (np->nn->ops->enable_refresh_hack_and_break_readdir && np->nn->contents) { @@ -122,12 +122,15 @@ error_t procfs_get_contents (struct node *np, char **data, size_t *data_len) if (! np->nn->contents && np->nn->ops->get_contents) { char *contents; - size_t contents_len; + ssize_t contents_len; error_t err; + contents_len = -1; err = np->nn->ops->get_contents (np->nn->hook, &contents, &contents_len); if (err) return err; + if (contents_len < 0) + return ENOMEM; np->nn->contents = contents; np->nn->contents_len = contents_len; diff --git a/procfs.h b/procfs.h index 8336ee85..e8ef18b3 100644 --- a/procfs.h +++ b/procfs.h @@ -16,9 +16,11 @@ struct procfs_node_ops symlink or directory, as determined by the file mode in netnode->nn_stat. For regular files and symlinks, they are what you would expect; for directories, they are an argz vector of the - names of the entries. */ - error_t (*get_contents) (void *hook, char **contents, size_t *contents_len); - void (*cleanup_contents) (void *hook, char *contents, size_t contents_len); + names of the entries. If upon return, *CONTENTS_LEN is negative or + unchanged, the call is considered to have failed because of a memory + allocation error. */ + error_t (*get_contents) (void *hook, char **contents, ssize_t *contents_len); + void (*cleanup_contents) (void *hook, char *contents, ssize_t contents_len); /* Lookup NAME in this directory, and store the result in *np. The returned node should be created by lookup() using procfs_make_node() @@ -41,8 +43,8 @@ struct procfs_node_ops }; /* These helper functions can be used as procfs_node_ops.cleanup_contents. */ -void procfs_cleanup_contents_with_free (void *, char *, size_t); -void procfs_cleanup_contents_with_vm_deallocate (void *, char *, size_t); +void procfs_cleanup_contents_with_free (void *, char *, ssize_t); +void procfs_cleanup_contents_with_vm_deallocate (void *, char *, ssize_t); /* Create a new node and return it. Returns NULL if it fails to allocate enough memory. In this case, ops->cleanup will be invoked. */ @@ -69,7 +71,7 @@ void procfs_node_chtype (struct node *np, mode_t type); corresponding child nodes. */ ino64_t procfs_make_ino (struct node *np, const char *filename); -error_t procfs_get_contents (struct node *np, char **data, size_t *data_len); +error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len); error_t procfs_lookup (struct node *np, const char *name, struct node **npp); void procfs_cleanup (struct node *np); diff --git a/procfs_dir.c b/procfs_dir.c index 4df46695..8ec3f7a5 100644 --- a/procfs_dir.c +++ b/procfs_dir.c @@ -11,7 +11,7 @@ struct procfs_dir_node }; static error_t -procfs_dir_get_contents (void *hook, char **contents, size_t *contents_len) +procfs_dir_get_contents (void *hook, char **contents, ssize_t *contents_len) { static const char dot_dotdot[] = ".\0.."; struct procfs_dir_node *dn = hook; diff --git a/proclist.c b/proclist.c index b5acb26c..38368feb 100644 --- a/proclist.c +++ b/proclist.c @@ -10,7 +10,7 @@ #define PID_STR_SIZE (3 * sizeof (pid_t) + 1) static error_t -proclist_get_contents (void *hook, char **contents, size_t *contents_len) +proclist_get_contents (void *hook, char **contents, ssize_t *contents_len) { struct ps_context *pc = hook; pidarray_t pids; diff --git a/rootdir.c b/rootdir.c index cd8949bf..364b0731 100644 --- a/rootdir.c +++ b/rootdir.c @@ -44,7 +44,7 @@ get_boottime (struct ps_context *pc, struct timeval *tv) } static error_t -rootdir_gc_version (void *hook, char **contents, size_t *contents_len) +rootdir_gc_version (void *hook, char **contents, ssize_t *contents_len) { struct utsname uts; int r; @@ -57,13 +57,13 @@ rootdir_gc_version (void *hook, char **contents, size_t *contents_len) "Linux version 2.6.1 (%s %s %s %s)\n", uts.sysname, uts.release, uts.version, uts.machine); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } /* Uptime -- we use the start time of init to deduce it. This is probably a bit fragile, as any clock update will make the result inaccurate. */ static error_t -rootdir_gc_uptime (void *hook, char **contents, size_t *contents_len) +rootdir_gc_uptime (void *hook, char **contents, ssize_t *contents_len) { struct timeval time, boottime; double up_secs; @@ -87,11 +87,11 @@ rootdir_gc_uptime (void *hook, char **contents, size_t *contents_len) and there to make that work. */ *contents_len = asprintf (contents, "%.2lf %.2lf\n", up_secs, up_secs); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } static error_t -rootdir_gc_stat (void *hook, char **contents, size_t *contents_len) +rootdir_gc_stat (void *hook, char **contents, ssize_t *contents_len) { struct timeval boottime, time; struct vm_statistics vmstats; @@ -126,11 +126,11 @@ rootdir_gc_stat (void *hook, char **contents, size_t *contents_len) vmstats.pageins, vmstats.pageouts, boottime.tv_sec); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } static error_t -rootdir_gc_loadavg (void *hook, char **contents, size_t *contents_len) +rootdir_gc_loadavg (void *hook, char **contents, ssize_t *contents_len) { host_load_info_data_t hli; mach_msg_type_number_t cnt; @@ -148,11 +148,11 @@ rootdir_gc_loadavg (void *hook, char **contents, size_t *contents_len) hli.avenrun[1] / (double) LOAD_SCALE, hli.avenrun[2] / (double) LOAD_SCALE); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } static error_t -rootdir_gc_meminfo (void *hook, char **contents, size_t *contents_len) +rootdir_gc_meminfo (void *hook, char **contents, ssize_t *contents_len) { host_basic_info_data_t hbi; mach_msg_type_number_t cnt; @@ -183,11 +183,11 @@ rootdir_gc_meminfo (void *hook, char **contents, size_t *contents_len) (long unsigned) vmstats.inactive_count * PAGE_SIZE / 1024, (long unsigned) vmstats.wire_count * PAGE_SIZE / 1024); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } static error_t -rootdir_gc_vmstat (void *hook, char **contents, size_t *contents_len) +rootdir_gc_vmstat (void *hook, char **contents, ssize_t *contents_len) { host_basic_info_data_t hbi; mach_msg_type_number_t cnt; @@ -228,11 +228,11 @@ rootdir_gc_vmstat (void *hook, char **contents, size_t *contents_len) (long unsigned) vmstats.pageouts, (long unsigned) vmstats.faults); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } static error_t -rootdir_gc_cmdline (void *hook, char **contents, size_t *contents_len) +rootdir_gc_cmdline (void *hook, char **contents, ssize_t *contents_len) { struct ps_context *pc = hook; struct proc_stat *ps; @@ -267,10 +267,10 @@ out: } static error_t -rootdir_gc_fakeself (void *hook, char **contents, size_t *contents_len) +rootdir_gc_fakeself (void *hook, char **contents, ssize_t *contents_len) { *contents_len = asprintf (contents, "%d", opt_fake_self); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } -- cgit v1.2.3 From f522af65aa004fea09705c74115836c6acd1cddb Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 14:15:54 +0000 Subject: Revamp procfs_dir * procfs_dir.c, procfs_dir.h: Revamp the interface to make the more complicated use cases somewhat less hackish. * process.c: Update, specify a default make_node function. * rootdir.c: Likewise; make this optional "self" link use case somewhat less hackish. --- process.c | 16 +++++++------ procfs_dir.c | 78 ++++++++++++++++++++++++++++++++++++++---------------------- procfs_dir.h | 48 +++++++++++++++++++++++++++---------- rootdir.c | 36 +++++++++++++++------------- 4 files changed, 113 insertions(+), 65 deletions(-) (limited to 'process.c') diff --git a/process.c b/process.c index 624f79e7..61688f7e 100644 --- a/process.c +++ b/process.c @@ -209,7 +209,7 @@ process_file_get_contents (void *hook, char **contents, ssize_t *contents_len) } static struct node * -process_file_make_node (void *dir_hook, void *entry_hook) +process_file_make_node (void *dir_hook, const void *entry_hook) { static const struct procfs_node_ops ops = { .get_contents = process_file_get_contents, @@ -245,7 +245,6 @@ process_file_make_node (void *dir_hook, void *entry_hook) static struct procfs_dir_entry entries[] = { { .name = "cmdline", - .make_node = process_file_make_node, .hook = & (struct process_file_desc) { .get_contents = process_file_gc_cmdline, .needs = PSTAT_ARGS, @@ -254,7 +253,6 @@ static struct procfs_dir_entry entries[] = { }, { .name = "environ", - .make_node = process_file_make_node, .hook = & (struct process_file_desc) { .get_contents = process_file_gc_environ, .needs = PSTAT_ENV, @@ -265,7 +263,6 @@ static struct procfs_dir_entry entries[] = { { /* Beware of the hack below, which requires this to be entries[2]. */ .name = "stat", - .make_node = process_file_make_node, .hook = & (struct process_file_desc) { .get_contents = process_file_gc_stat, .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO @@ -276,7 +273,6 @@ static struct procfs_dir_entry entries[] = { }, { .name = "statm", - .make_node = process_file_make_node, .hook = & (struct process_file_desc) { .get_contents = process_file_gc_statm, .needs = PSTAT_TASK_BASIC, @@ -285,7 +281,6 @@ static struct procfs_dir_entry entries[] = { }, { .name = "status", - .make_node = process_file_make_node, .hook = & (struct process_file_desc) { .get_contents = process_file_gc_status, .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO @@ -299,6 +294,13 @@ static struct procfs_dir_entry entries[] = { error_t process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) { + static const struct procfs_dir_ops dir_ops = { + .entries = entries, + .cleanup = (void (*)(void *)) _proc_stat_free, + .entry_ops = { + .make_node = process_file_make_node, + }, + }; struct proc_stat *ps; int owner; error_t err; @@ -317,7 +319,7 @@ process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) accessed in a more robust and straightforward way. */ ((struct process_file_desc *) entries[2].hook)->mode = opt_stat_mode; - *np = procfs_dir_make_node (entries, ps, (void (*)(void *)) _proc_stat_free); + *np = procfs_dir_make_node (&dir_ops, ps); if (! *np) return ENOMEM; diff --git a/procfs_dir.c b/procfs_dir.c index 8ec3f7a5..dfe30a26 100644 --- a/procfs_dir.c +++ b/procfs_dir.c @@ -5,49 +5,71 @@ struct procfs_dir_node { - const struct procfs_dir_entry *entries; + const struct procfs_dir_ops *ops; void *hook; - void (*cleanup) (void *hook); }; +static int +entry_exists (struct procfs_dir_node *dir, const struct procfs_dir_entry *ent) +{ + if (ent->ops.exists) + return ent->ops.exists (dir->hook, ent->hook); + if (dir->ops->entry_ops.exists) + return dir->ops->entry_ops.exists (dir->hook, ent->hook); + + return 1; +} + static error_t procfs_dir_get_contents (void *hook, char **contents, ssize_t *contents_len) { static const char dot_dotdot[] = ".\0.."; - struct procfs_dir_node *dn = hook; + struct procfs_dir_node *dir = hook; const struct procfs_dir_entry *ent; - char *pos; + int pos; - *contents_len = sizeof dot_dotdot; - for (ent = dn->entries; ent->name; ent++) - *contents_len += strlen (ent->name) + 1; + /* Evaluate how much space is needed. Note that we include the hidden + entries, just in case their status changes between now and then. */ + pos = sizeof dot_dotdot; + for (ent = dir->ops->entries; ent->name; ent++) + pos += strlen (ent->name) + 1; - *contents = malloc (*contents_len); + *contents = malloc (pos); if (! *contents) return ENOMEM; memcpy (*contents, dot_dotdot, sizeof dot_dotdot); - pos = *contents + sizeof dot_dotdot; - for (ent = dn->entries; ent->name; ent++) + pos = sizeof dot_dotdot; + for (ent = dir->ops->entries; ent->name; ent++) { - strcpy (pos, ent->name); + if (! entry_exists (dir, ent)) + continue; + + strcpy (*contents + pos, ent->name); pos += strlen (ent->name) + 1; } + *contents_len = pos; return 0; } static error_t procfs_dir_lookup (void *hook, const char *name, struct node **np) { - struct procfs_dir_node *dn = hook; + struct procfs_dir_node *dir = hook; const struct procfs_dir_entry *ent; - for (ent = dn->entries; ent->name && strcmp (name, ent->name); ent++); + for (ent = dir->ops->entries; ent->name && strcmp (name, ent->name); ent++); if (! ent->name) return ENOENT; - *np = ent->make_node (dn->hook, ent->hook); + if (ent->ops.make_node) + *np = ent->ops.make_node (dir->hook, ent->hook); + else if (dir->ops->entry_ops.make_node) + *np = dir->ops->entry_ops.make_node (dir->hook, ent->hook); + else + return EGRATUITOUS; + if (! *np) return ENOMEM; @@ -57,17 +79,16 @@ procfs_dir_lookup (void *hook, const char *name, struct node **np) static void procfs_dir_cleanup (void *hook) { - struct procfs_dir_node *dn = hook; + struct procfs_dir_node *dir = hook; - if (dn->cleanup) - dn->cleanup (dn->hook); + if (dir->ops->cleanup) + dir->ops->cleanup (dir->hook); - free (dn); + free (dir); } struct node * -procfs_dir_make_node (const struct procfs_dir_entry *entries, - void *dir_hook, void (*cleanup) (void *dir_hook)) +procfs_dir_make_node (const struct procfs_dir_ops *dir_ops, void *dir_hook) { static const struct procfs_node_ops ops = { .get_contents = procfs_dir_get_contents, @@ -75,21 +96,20 @@ procfs_dir_make_node (const struct procfs_dir_entry *entries, .cleanup_contents = procfs_cleanup_contents_with_free, .cleanup = procfs_dir_cleanup, }; - struct procfs_dir_node *dn; + struct procfs_dir_node *dir; - dn = malloc (sizeof *dn); - if (! dn) + dir = malloc (sizeof *dir); + if (! dir) { - if (cleanup) - cleanup (dir_hook); + if (dir_ops->cleanup) + dir_ops->cleanup (dir_hook); return NULL; } - dn->entries = entries; - dn->hook = dir_hook; - dn->cleanup = cleanup; + dir->ops = dir_ops; + dir->hook = dir_hook; - return procfs_make_node (&ops, dn); + return procfs_make_node (&ops, dir); } diff --git a/procfs_dir.h b/procfs_dir.h index 4eb934e0..12e99d2a 100644 --- a/procfs_dir.h +++ b/procfs_dir.h @@ -1,20 +1,44 @@ +/* This module provides an abstraction layer for implementing simple + directories with (mostly) static contents. The user defines the + contents of the directory by providing a table of entries and various + optional callback functions. */ -/* Each entry associates a name with a callback function for creating new - nodes corresponding to that entry. */ +/* These operations define how a given entry will behave. Either can be + omitted, both from the entry-specific operations and from the + directory-wide defaults. */ +struct procfs_dir_entry_ops +{ + /* Called when this entry is looked up to create a corresponding node. */ + struct node *(*make_node)(void *dir_hook, const void *entry_hook); + /* If this is provided and returns 0, this entry will be hidden. */ + int (*exists)(void *dir_hook, const void *entry_hook); +}; + +/* Describes an individual directory entry, associating a NAME with + * arbitrary HOOK data and node-specific OPS. */ struct procfs_dir_entry { const char *name; - struct node *(*make_node)(void *dir_hook, void *entry_hook); - void *hook; + const void *hook; + struct procfs_dir_entry_ops ops; +}; + +/* Describes a complete directory. ENTRIES is a table terminated by a + null NAME field. ENTRY_OPS provides default operations for the + entries which don't specify them. The optional CLEANUP function + should release all the resources associated with the directory hook. */ +struct procfs_dir_ops +{ + const struct procfs_dir_entry *entries; + void (*cleanup)(void *dir_hook); + struct procfs_dir_entry_ops entry_ops; }; -/* A simple directory is built from a table of entries. The table is - terminated by a null NAME pointer. The DIR_HOOK is passed the - MAKE_NODE callback function of looked up procfs_dir_entries, and to - the provided CLEANUP function when the directory is destroyed. - Returns the new directory node. If not enough memory can be - allocated, CLEANUP is invoked immediately and NULL is returned. */ +/* Create and return a new node for the directory described in OPS. + The DIR_HOOK is passed the MAKE_NODE callback function of looked up + entries, as well as to the CLEANUP callback when the node is + destroyed. If not enough memory can be allocated, OPS->CLEANUP is + invoked immediately and NULL is returned. */ struct node * -procfs_dir_make_node (const struct procfs_dir_entry *entries, - void *dir_hook, void (*cleanup) (void *dir_hook)); +procfs_dir_make_node (const struct procfs_dir_ops *ops, void *dir_hook); diff --git a/rootdir.c b/rootdir.c index 364b0731..dcee9a54 100644 --- a/rootdir.c +++ b/rootdir.c @@ -266,6 +266,12 @@ out: return err; } +static int +rootdir_fakeself_exists () +{ + return opt_fake_self >= 0; +} + static error_t rootdir_gc_fakeself (void *hook, char **contents, ssize_t *contents_len) { @@ -275,13 +281,13 @@ rootdir_gc_fakeself (void *hook, char **contents, ssize_t *contents_len) static struct node * -rootdir_file_make_node (void *dir_hook, void *entry_hook) +rootdir_file_make_node (void *dir_hook, const void *entry_hook) { return procfs_make_node (entry_hook, dir_hook); } static struct node * -rootdir_symlink_make_node (void *dir_hook, void *entry_hook) +rootdir_symlink_make_node (void *dir_hook, const void *entry_hook) { struct node *np = procfs_make_node (entry_hook, dir_hook); if (np) @@ -292,15 +298,17 @@ rootdir_symlink_make_node (void *dir_hook, void *entry_hook) static const struct procfs_dir_entry rootdir_entries[] = { { .name = "self", - .make_node = rootdir_symlink_make_node, .hook = & (struct procfs_node_ops) { .get_contents = rootdir_gc_fakeself, .cleanup_contents = procfs_cleanup_contents_with_free, }, + .ops = { + .make_node = rootdir_symlink_make_node, + .exists = rootdir_fakeself_exists, + } }, { .name = "version", - .make_node = rootdir_file_make_node, .hook = & (struct procfs_node_ops) { .get_contents = rootdir_gc_version, .cleanup_contents = procfs_cleanup_contents_with_free, @@ -308,7 +316,6 @@ static const struct procfs_dir_entry rootdir_entries[] = { }, { .name = "uptime", - .make_node = rootdir_file_make_node, .hook = & (struct procfs_node_ops) { .get_contents = rootdir_gc_uptime, .cleanup_contents = procfs_cleanup_contents_with_free, @@ -316,7 +323,6 @@ static const struct procfs_dir_entry rootdir_entries[] = { }, { .name = "stat", - .make_node = rootdir_file_make_node, .hook = & (struct procfs_node_ops) { .get_contents = rootdir_gc_stat, .cleanup_contents = procfs_cleanup_contents_with_free, @@ -324,7 +330,6 @@ static const struct procfs_dir_entry rootdir_entries[] = { }, { .name = "loadavg", - .make_node = rootdir_file_make_node, .hook = & (struct procfs_node_ops) { .get_contents = rootdir_gc_loadavg, .cleanup_contents = procfs_cleanup_contents_with_free, @@ -332,7 +337,6 @@ static const struct procfs_dir_entry rootdir_entries[] = { }, { .name = "meminfo", - .make_node = rootdir_file_make_node, .hook = & (struct procfs_node_ops) { .get_contents = rootdir_gc_meminfo, .cleanup_contents = procfs_cleanup_contents_with_free, @@ -340,7 +344,6 @@ static const struct procfs_dir_entry rootdir_entries[] = { }, { .name = "vmstat", - .make_node = rootdir_file_make_node, .hook = & (struct procfs_node_ops) { .get_contents = rootdir_gc_vmstat, .cleanup_contents = procfs_cleanup_contents_with_free, @@ -348,7 +351,6 @@ static const struct procfs_dir_entry rootdir_entries[] = { }, { .name = "cmdline", - .make_node = rootdir_file_make_node, .hook = & (struct procfs_node_ops) { .get_contents = rootdir_gc_cmdline, .cleanup_contents = procfs_cleanup_contents_with_free, @@ -360,12 +362,12 @@ static const struct procfs_dir_entry rootdir_entries[] = { struct node *rootdir_make_node (struct ps_context *pc) { - const struct procfs_dir_entry *entries; - - entries = rootdir_entries; - if (opt_fake_self < 0) - entries++; - - return procfs_dir_make_node (entries, pc, NULL); + static const struct procfs_dir_ops ops = { + .entries = rootdir_entries, + .entry_ops = { + .make_node = rootdir_file_make_node, + }, + }; + return procfs_dir_make_node (&ops, pc); } -- cgit v1.2.3 From 7550343b09a94dc1c659ad74dc75b3b77e7ab0bc Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 16:46:04 +0000 Subject: Cleanup pass on process.c * process.c: Reorder some of the code. Improve comments. Jiffies and clock tick are the same thing, right? Replace the stat mode and cleanup hacks by more straightforward solutions. --- process.c | 122 ++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 79 insertions(+), 43 deletions(-) (limited to 'process.c') diff --git a/process.c b/process.c index 61688f7e..1f9d5781 100644 --- a/process.c +++ b/process.c @@ -9,22 +9,20 @@ #include "procfs_dir.h" #include "process.h" #include "main.h" - -/* Implementations for the process_file_desc.get_contents callback. */ -static ssize_t -process_file_gc_cmdline (struct proc_stat *ps, char **contents) -{ - *contents = proc_stat_args(ps); - return proc_stat_args_len(ps); -} +/* This module implements the process directories and the files they + contain. A libps proc_stat structure is created for each process + node, and is used by the individual file content generators as a + source of information. Each possible file (cmdline, environ, ...) is + decribed in a process_file_desc structure, which specifies which bits + of information (ie. libps flags) it needs, and what function should + be used to generate the file's contents. -static ssize_t -process_file_gc_environ (struct proc_stat *ps, char **contents) -{ - *contents = proc_stat_env(ps); - return proc_stat_env_len(ps); -} + The content generators are defined first, followed by glue logic and + entry table. */ + + +/* Helper functions */ static char state_char (struct proc_stat *ps) { @@ -58,17 +56,26 @@ static const char *state_string (struct proc_stat *ps) return "? (unknown)"; } -static long int sc_tv (time_value_t tv) +static long long int timeval_jiffies (time_value_t tv) { - double usecs = ((double) tv.seconds) * 1000000 + tv.microseconds; - return usecs * opt_clk_tck / 1000000; + double secs = tv.seconds + tv.microseconds / 1000000.; + return secs * opt_clk_tck; } -static long long int jiff_tv (time_value_t tv) +/* Actual content generators */ + +static ssize_t +process_file_gc_cmdline (struct proc_stat *ps, char **contents) { - double usecs = ((double) tv.seconds) * 1000000 + tv.microseconds; - /* Let's say a jiffy is 1/100 of a second.. */ - return usecs * 100 / 1000000; + *contents = proc_stat_args(ps); + return proc_stat_args_len(ps); +} + +static ssize_t +process_file_gc_environ (struct proc_stat *ps, char **contents) +{ + *contents = proc_stat_env(ps); + return proc_stat_env_len(ps); } static ssize_t @@ -105,17 +112,18 @@ process_file_gc_stat (struct proc_stat *ps, char **contents) 0, 0, /* no such thing as a major:minor for ctty */ 0, /* no such thing as CLONE_* flags on Hurd */ 0L, 0L, 0L, 0L, /* TASK_EVENTS_INFO is unavailable on GNU Mach */ - sc_tv (thbi->user_time), sc_tv (thbi->system_time), + (long unsigned) timeval_jiffies (thbi->user_time), + (long unsigned) timeval_jiffies (thbi->system_time), 0L, 0L, /* cumulative time for children */ MACH_PRIORITY_TO_NICE(thbi->base_priority) + 20, MACH_PRIORITY_TO_NICE(thbi->base_priority), pi->nthreads, 0L, - jiff_tv (thbi->creation_time), /* FIXME: ... since boot */ - (long unsigned int) tbi->virtual_size, - (long unsigned int) tbi->resident_size / PAGE_SIZE, 0L, + timeval_jiffies (thbi->creation_time), /* FIXME: ... since boot */ + (long unsigned) tbi->virtual_size, + (long unsigned) tbi->resident_size / PAGE_SIZE, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, - (long unsigned int) proc_stat_thread_rpc (ps), /* close enough */ + (long unsigned) proc_stat_thread_rpc (ps), /* close enough */ 0L, 0L, 0, 0, @@ -127,6 +135,7 @@ static ssize_t process_file_gc_statm (struct proc_stat *ps, char **contents) { task_basic_info_t tbi = proc_stat_task_basic_info (ps); + return asprintf (contents, "%lu %lu 0 0 0 0 0\n", tbi->virtual_size / sysconf(_SC_PAGE_SIZE), @@ -137,6 +146,7 @@ static ssize_t process_file_gc_status (struct proc_stat *ps, char **contents) { task_basic_info_t tbi = proc_stat_task_basic_info (ps); + return asprintf (contents, "Name:\t%s\n" "State:\t%s\n" @@ -165,59 +175,70 @@ process_file_gc_status (struct proc_stat *ps, char **contents) proc_stat_num_threads (ps)); } + +/* Implementation of the file nodes. */ -/* Describes a file in a process directory. This is used as an "entry hook" - * for our procfs_dir entry table, passed to process_file_make_node. */ +/* Describes a file in the process directories. This structure is + filled in as an "entry hook" in our procfs_dir entry table and is + passed to the process_file_make_node function defined below. */ struct process_file_desc { /* The proc_stat information required to get the contents of this file. */ ps_flags_t needs; - /* Once we have acquired the necessary information, there can be only - memory allocation errors, hence this simplified signature. */ + /* Content generator to use for this file. Once we have acquired the + necessary information, there can be only memory allocation errors, + hence this simplified signature. */ ssize_t (*get_contents) (struct proc_stat *ps, char **contents); - /* The cmdline and environ contents don't need any cleaning since they are - part of a proc_stat structure. */ + /* The cmdline and environ contents don't need any cleaning since they + point directly into the proc_stat structure. */ int no_cleanup; /* If specified, the file mode to be set with procfs_node_chmod(). */ mode_t mode; }; -/* Information associated to an actual file node. */ struct process_file_node { const struct process_file_desc *desc; struct proc_stat *ps; }; +/* FIXME: lock the parent! */ static error_t process_file_get_contents (void *hook, char **contents, ssize_t *contents_len) { struct process_file_node *file = hook; error_t err; + /* Fetch the required information. */ err = proc_stat_set_flags (file->ps, file->desc->needs); if (err) return EIO; if ((proc_stat_flags (file->ps) & file->desc->needs) != file->desc->needs) return EIO; + /* Call the actual content generator (see the definitions below). */ *contents_len = file->desc->get_contents (file->ps, contents); return 0; } +static void +process_file_cleanup_contents (void *hook, char *contents, ssize_t len) +{ + struct process_file_node *file = hook; + + if (! file->desc->no_cleanup) + free (contents); +} + static struct node * process_file_make_node (void *dir_hook, const void *entry_hook) { static const struct procfs_node_ops ops = { .get_contents = process_file_get_contents, - .cleanup_contents = procfs_cleanup_contents_with_free, - .cleanup = free, - }; - static const struct procfs_node_ops ops_no_cleanup = { - .get_contents = process_file_get_contents, + .cleanup_contents = process_file_cleanup_contents, .cleanup = free, }; struct process_file_node *f; @@ -230,7 +251,7 @@ process_file_make_node (void *dir_hook, const void *entry_hook) f->desc = entry_hook; f->ps = dir_hook; - np = procfs_make_node (f->desc->no_cleanup ? &ops_no_cleanup : &ops, f); + np = procfs_make_node (&ops, f); if (! np) return NULL; @@ -241,6 +262,18 @@ process_file_make_node (void *dir_hook, const void *entry_hook) return np; } +/* Stat needs its own constructor in oreder to set its mode according to + the --stat-mode command-line option. */ +static struct node * +process_stat_make_node (void *dir_hook, const void *entry_hook) +{ + struct node *np = process_file_make_node (dir_hook, entry_hook); + if (np) procfs_node_chmod (np, opt_stat_mode); + return np; +} + + +/* Implementation of the process directory per se. */ static struct procfs_dir_entry entries[] = { { @@ -261,22 +294,22 @@ static struct procfs_dir_entry entries[] = { }, }, { - /* Beware of the hack below, which requires this to be entries[2]. */ .name = "stat", .hook = & (struct process_file_desc) { .get_contents = process_file_gc_stat, .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO | PSTAT_TASK | PSTAT_TASK_BASIC | PSTAT_THREAD_BASIC | PSTAT_THREAD_WAIT, - .mode = 0400, }, + .ops = { + .make_node = process_stat_make_node, + } }, { .name = "statm", .hook = & (struct process_file_desc) { .get_contents = process_file_gc_statm, .needs = PSTAT_TASK_BASIC, - .mode = 0444, }, }, { @@ -285,7 +318,6 @@ static struct procfs_dir_entry entries[] = { .get_contents = process_file_gc_status, .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO | PSTAT_TASK_BASIC | PSTAT_OWNER_UID | PSTAT_NUM_THREADS, - .mode = 0444, }, }, {} @@ -319,6 +351,10 @@ process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) accessed in a more robust and straightforward way. */ ((struct process_file_desc *) entries[2].hook)->mode = opt_stat_mode; + /* FIXME: have a separate proc_desc structure for each file, so this can be + accessed in a more robust and straightforward way. */ + ((struct process_file_desc *) entries[2].hook)->mode = opt_stat_mode; + *np = procfs_dir_make_node (&dir_ops, ps); if (! *np) return ENOMEM; -- cgit v1.2.3 From 7b027a34676880bded1a05a5c47bfa85a6e79092 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 20:21:52 +0000 Subject: Make sure the clock never runs backwards. * process.c, rootdir.c: When converting timeval structures into seconds or jiffies, make sure that floating point rounding errors don't make the clock the result jump backwards on second boundaries. --- process.c | 4 ++-- rootdir.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'process.c') diff --git a/process.c b/process.c index 1f9d5781..68e7bc1d 100644 --- a/process.c +++ b/process.c @@ -58,8 +58,8 @@ static const char *state_string (struct proc_stat *ps) static long long int timeval_jiffies (time_value_t tv) { - double secs = tv.seconds + tv.microseconds / 1000000.; - return secs * opt_clk_tck; + double secs = tv.seconds * 1000000. + tv.microseconds; + return secs * opt_clk_tck / 1000000.; } /* Actual content generators */ diff --git a/rootdir.c b/rootdir.c index 728008e5..c6ddd87c 100644 --- a/rootdir.c +++ b/rootdir.c @@ -140,8 +140,8 @@ rootdir_gc_uptime (void *hook, char **contents, ssize_t *contents_len) return err; timersub (&time, &boottime, &time); - up_secs = time.tv_sec + time.tv_usec / 1000000.; - idle_secs = idletime.tv_sec + idletime.tv_usec / 1000000.; + up_secs = (time.tv_sec * 1000000. + time.tv_usec) / 1000000.; + idle_secs = (idletime.tv_sec * 1000000. + idletime.tv_usec) / 1000000.; /* The second field is the total idle time. As far as I know we don't keep track of it. However, procps uses it to compute "USER_HZ", and @@ -178,8 +178,8 @@ rootdir_gc_stat (void *hook, char **contents, ssize_t *contents_len) return EIO; timersub (&time, &boottime, &time); - up_ticks = opt_clk_tck * (time.tv_sec + time.tv_usec / 1000000.); - idle_ticks = opt_clk_tck * (idletime.tv_sec + idletime.tv_usec / 1000000.); + up_ticks = opt_clk_tck * (time.tv_sec * 1000000. + time.tv_usec) / 1000000.; + idle_ticks = opt_clk_tck * (idletime.tv_sec * 1000000. + idletime.tv_usec) / 1000000.; *contents_len = asprintf (contents, "cpu %lu 0 0 %lu 0 0 0 0 0\n" -- cgit v1.2.3 From ca8277c6f507e54a043b84a8df9c55ac39a83c6e Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Wed, 25 Aug 2010 05:46:49 +0000 Subject: Fix leak in error case * process.c (process_lookup_pid): Fix leak in error case. --- process.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'process.c') diff --git a/process.c b/process.c index 68e7bc1d..47e34708 100644 --- a/process.c +++ b/process.c @@ -345,7 +345,10 @@ process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) err = proc_stat_set_flags (ps, PSTAT_OWNER_UID); if (err || ! (proc_stat_flags (ps) & PSTAT_OWNER_UID)) - return EIO; + { + _proc_stat_free (ps); + return EIO; + } /* FIXME: have a separate proc_desc structure for each file, so this can be accessed in a more robust and straightforward way. */ -- cgit v1.2.3 From 5c7310fd853620627b57c72ddcc3b212f29f6056 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Thu, 26 Aug 2010 23:03:40 +0000 Subject: Add copyright notices * dircat.c, dircat.h, main.c, main.h, netfs.c, process.c, process.h, procfs.c, procfs.h, procfs_dir.c, procfs_dir.h, proclist.c, proclist.h, rootdir.c, rootdir.h: Add copyright notices. --- dircat.c | 19 +++++++++++++++++++ dircat.h | 19 +++++++++++++++++++ main.c | 19 +++++++++++++++++++ main.h | 19 +++++++++++++++++++ netfs.c | 19 +++++++++++++++++++ process.c | 19 +++++++++++++++++++ process.h | 19 +++++++++++++++++++ procfs.c | 19 +++++++++++++++++++ procfs.h | 19 +++++++++++++++++++ procfs_dir.c | 19 +++++++++++++++++++ procfs_dir.h | 19 +++++++++++++++++++ proclist.c | 19 +++++++++++++++++++ proclist.h | 19 +++++++++++++++++++ rootdir.c | 19 +++++++++++++++++++ rootdir.h | 19 +++++++++++++++++++ 15 files changed, 285 insertions(+) (limited to 'process.c') diff --git a/dircat.c b/dircat.c index d24e8345..5a60899a 100644 --- a/dircat.c +++ b/dircat.c @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, concatenation of two directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include "procfs.h" diff --git a/dircat.h b/dircat.h index 951d2021..4177b384 100644 --- a/dircat.h +++ b/dircat.h @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, concatenation of two directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + /* Append the contents of NUM_DIRS directories. DIRS is an array of directory nodes. One reference is consumed for each of them. If a memory allocation error occurs, or if one of the directories is a diff --git a/main.c b/main.c index eaab9867..94fc227d 100644 --- a/main.c +++ b/main.c @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, main program. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include diff --git a/main.h b/main.h index 28d1b023..4e28b7eb 100644 --- a/main.h +++ b/main.h @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, command-line options set by main.c. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + /* Startup options */ extern int opt_clk_tck; extern mode_t opt_stat_mode; diff --git a/netfs.c b/netfs.c index 02a4bf54..24a6603f 100644 --- a/netfs.c +++ b/netfs.c @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, interface with libnetfs. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include diff --git a/process.c b/process.c index 47e34708..6652a4e9 100644 --- a/process.c +++ b/process.c @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, implementation of process directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include diff --git a/process.h b/process.h index 8c2ee636..b230a281 100644 --- a/process.h +++ b/process.h @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, implementation of process directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include /* Create a node for a directory representing the given PID, as published by diff --git a/procfs.c b/procfs.c index f7b28347..ee52de7a 100644 --- a/procfs.c +++ b/procfs.c @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, basic infrastructure. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include diff --git a/procfs.h b/procfs.h index a9665f97..64782ec4 100644 --- a/procfs.h +++ b/procfs.h @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, basic infrastructure. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include diff --git a/procfs_dir.c b/procfs_dir.c index dfe30a26..c250aa48 100644 --- a/procfs_dir.c +++ b/procfs_dir.c @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, infrastructure for directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include "procfs.h" diff --git a/procfs_dir.h b/procfs_dir.h index 12e99d2a..94c5b019 100644 --- a/procfs_dir.h +++ b/procfs_dir.h @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, infrastructure for directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + /* This module provides an abstraction layer for implementing simple directories with (mostly) static contents. The user defines the contents of the directory by providing a table of entries and various diff --git a/proclist.c b/proclist.c index fe5d0cff..58b942dc 100644 --- a/proclist.c +++ b/proclist.c @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, list of processes as a directory. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include diff --git a/proclist.h b/proclist.h index ce69dde3..bfe95b3d 100644 --- a/proclist.h +++ b/proclist.h @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, list of processes as a directory. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include struct node * diff --git a/rootdir.c b/rootdir.c index 2a2ab5a5..da068cf4 100644 --- a/rootdir.c +++ b/rootdir.c @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, permanent files of the root directory. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include diff --git a/rootdir.h b/rootdir.h index 0caee258..6980da8f 100644 --- a/rootdir.h +++ b/rootdir.h @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, permanent files of the root directory. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include struct node * -- cgit v1.2.3 From d9fc76bd4e8c9a459fad7152135b738496318415 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 27 Dec 2011 17:31:20 +0100 Subject: Do not use msgport information * process.c (process_lookup_pid): Set PSTAT_NO_MSGPORT flag. * rootdir.c (get_boottime, get_idletime, rootdir_gc_cmdline): Set PSTAT_NO_MSGPORT flag. --- process.c | 2 ++ rootdir.c | 6 ++++++ 2 files changed, 8 insertions(+) (limited to 'process.c') diff --git a/process.c b/process.c index 6652a4e9..e812a1f1 100644 --- a/process.c +++ b/process.c @@ -362,6 +362,8 @@ process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) if (err) return EIO; + proc_stat_set_flags (ps, PSTAT_NO_MSGPORT); + err = proc_stat_set_flags (ps, PSTAT_OWNER_UID); if (err || ! (proc_stat_flags (ps) & PSTAT_OWNER_UID)) { diff --git a/rootdir.c b/rootdir.c index 1fa71b03..018de617 100644 --- a/rootdir.c +++ b/rootdir.c @@ -52,6 +52,8 @@ get_boottime (struct ps_context *pc, struct timeval *tv) if (err) return err; + proc_stat_set_flags (ps, PSTAT_NO_MSGPORT); + err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); if (err || !(proc_stat_flags (ps) & PSTAT_TASK_BASIC)) err = EIO; @@ -82,6 +84,8 @@ get_idletime (struct ps_context *pc, struct timeval *tv) pst = NULL, tbi = NULL; + proc_stat_set_flags (ps, PSTAT_NO_MSGPORT); + err = proc_stat_set_flags (ps, PSTAT_NUM_THREADS); if (err || !(proc_stat_flags (ps) & PSTAT_NUM_THREADS)) { @@ -360,6 +364,8 @@ rootdir_gc_cmdline (void *hook, char **contents, ssize_t *contents_len) if (err) return EIO; + proc_stat_set_flags (ps, PSTAT_NO_MSGPORT); + err = proc_stat_set_flags (ps, PSTAT_ARGS); if (err || ! (proc_stat_flags (ps) & PSTAT_ARGS)) { -- cgit v1.2.3 From f8471a5a6b20693d3c7afc0645de62c842b82bd3 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 27 Dec 2011 18:13:00 +0100 Subject: Revert "Do not use msgport information" This reverts commit d9fc76bd4e8c9a459fad7152135b738496318415, as it breaks /proc/pid/stat --- process.c | 2 -- rootdir.c | 6 ------ 2 files changed, 8 deletions(-) (limited to 'process.c') diff --git a/process.c b/process.c index e812a1f1..6652a4e9 100644 --- a/process.c +++ b/process.c @@ -362,8 +362,6 @@ process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) if (err) return EIO; - proc_stat_set_flags (ps, PSTAT_NO_MSGPORT); - err = proc_stat_set_flags (ps, PSTAT_OWNER_UID); if (err || ! (proc_stat_flags (ps) & PSTAT_OWNER_UID)) { diff --git a/rootdir.c b/rootdir.c index 018de617..1fa71b03 100644 --- a/rootdir.c +++ b/rootdir.c @@ -52,8 +52,6 @@ get_boottime (struct ps_context *pc, struct timeval *tv) if (err) return err; - proc_stat_set_flags (ps, PSTAT_NO_MSGPORT); - err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); if (err || !(proc_stat_flags (ps) & PSTAT_TASK_BASIC)) err = EIO; @@ -84,8 +82,6 @@ get_idletime (struct ps_context *pc, struct timeval *tv) pst = NULL, tbi = NULL; - proc_stat_set_flags (ps, PSTAT_NO_MSGPORT); - err = proc_stat_set_flags (ps, PSTAT_NUM_THREADS); if (err || !(proc_stat_flags (ps) & PSTAT_NUM_THREADS)) { @@ -364,8 +360,6 @@ rootdir_gc_cmdline (void *hook, char **contents, ssize_t *contents_len) if (err) return EIO; - proc_stat_set_flags (ps, PSTAT_NO_MSGPORT); - err = proc_stat_set_flags (ps, PSTAT_ARGS); if (err || ! (proc_stat_flags (ps) & PSTAT_ARGS)) { -- cgit v1.2.3 From 4d9dc03bbc42fdfdac0dc72f2bfac1f37f70e8b7 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Sat, 14 Jan 2012 14:47:58 +0100 Subject: PID stat/status: show only the file name of processes The Linux /proc fs shows only the file name of processes in the `stat' and `status' files of every process directory, so adapt also procfs to show process file names. Add a new `args_filename` function, much similar to GNU's `basename' but returning the original string also when the resulting file name is an empty string. * process.c (args_filename): New function. (process_file_gc_stat): Wrap the `proc_stat_args' result with `args_filename'. (process_file_gc_status): Likewise. --- process.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'process.c') diff --git a/process.c b/process.c index 6652a4e9..17a38ea8 100644 --- a/process.c +++ b/process.c @@ -81,6 +81,12 @@ static long long int timeval_jiffies (time_value_t tv) return secs * opt_clk_tck / 1000000.; } +static const char *args_filename (const char *name) +{ + char *sp = strrchr (name, '/'); + return sp != NULL && *(sp + 1) != '\0' ? sp + 1 : name; +} + /* Actual content generators */ static ssize_t @@ -126,7 +132,7 @@ process_file_gc_stat (struct proc_stat *ps, char **contents) "%u %u " /* RT priority and policy */ "%llu " /* aggregated block I/O delay */ "\n", - proc_stat_pid (ps), proc_stat_args (ps), state_char (ps), + proc_stat_pid (ps), args_filename (proc_stat_args (ps)), state_char (ps), pi->ppid, pi->pgrp, pi->session, 0, 0, /* no such thing as a major:minor for ctty */ 0, /* no such thing as CLONE_* flags on Hurd */ @@ -178,7 +184,7 @@ process_file_gc_status (struct proc_stat *ps, char **contents) "VmRSS:\t%8u kB\n" "VmHWM:\t%8u kB\n" /* ie. resident peak */ "Threads:\t%u\n", - proc_stat_args (ps), + args_filename (proc_stat_args (ps)), state_string (ps), proc_stat_pid (ps), /* XXX will need more work for threads */ proc_stat_pid (ps), -- cgit v1.2.3