From 3907bbbcfb806799a5349e46a2b804307a0e9836 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Tue, 17 Aug 2010 12:49:33 +0000 Subject: Add the list of processes as a directory * proclist.h, proclist.c: New files. * main.c: Add a proclist directory based on them. * Makefile: Include the proclist module. --- proclist.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 proclist.c (limited to 'proclist.c') diff --git a/proclist.c b/proclist.c new file mode 100644 index 00000000..4dd6ab31 --- /dev/null +++ b/proclist.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include +#include "procfs.h" +#include "procfs_file.h" +#include "procfs_dir.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; + 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); + if (err) + return EIO; + + *contents = malloc (num_pids * PID_STR_SIZE); + if (*contents) + { + *contents_len = 0; + for (i=0; i < num_pids; i++) + { + int n = sprintf (*contents + *contents_len, "%d", pids[i]); + assert (n >= 0); + *contents_len += (n + 1); + } + } + else + err = ENOMEM; + + vm_deallocate (mach_task_self (), (vm_address_t) pids, num_pids * sizeof pids[0]); + return err; +} + +static error_t +proclist_lookup (void *hook, const char *name, struct node **np) +{ + *np = procfs_file_make_node ("Ceci n'est pas un processus\n", -1, NULL); + return *np ? 0 : ENOMEM; +} + +struct node * +proclist_make_node (process_t process) +{ + static const struct procfs_node_ops ops = { + .get_contents = proclist_get_contents, + .lookup = proclist_lookup, + .cleanup_contents = free, + .cleanup = free, + }; + struct proclist_node *pl; + struct node *np; + + pl = malloc (sizeof *pl); + if (! pl) + return NULL; + + memset (pl, 0, sizeof *pl); + pl->process = process; + + np = procfs_make_node (&ops, pl); + if (! np) + free (pl); + + return np; +} + -- cgit v1.2.3 From ac75e3648e6a9c3a8cf45d5fa491abd3a3ab3613 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Tue, 17 Aug 2010 16:48:55 +0000 Subject: Fix the failure semantics of procfs_make_node * procfs.c (procfs_make_node): Invoke the cleanup callback on failure, so that callers don't have to. * procfs.h: Document the change. * procfs_dir.c (procfs_dir_make_node), procfs_file.c (procfs_file_make_node), proclist.c (proclist_make_node): Update to reflect the change. --- procfs.c | 14 +++++++++----- procfs.h | 2 ++ procfs_dir.c | 7 +------ procfs_file.c | 7 +------ proclist.c | 7 +------ 5 files changed, 14 insertions(+), 23 deletions(-) (limited to 'proclist.c') diff --git a/procfs.c b/procfs.c index 304befba..0c57686b 100644 --- a/procfs.c +++ b/procfs.c @@ -22,7 +22,7 @@ struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook) nn = malloc (sizeof *nn); if (! nn) - return NULL; + goto fail; memset (nn, 0, sizeof *nn); nn->ops = ops; @@ -30,10 +30,7 @@ struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook) np = netfs_make_node (nn); if (! np) - { - free (nn); - return NULL; - } + goto fail; np->nn = nn; memset (&np->nn_stat, 0, sizeof np->nn_stat); @@ -45,6 +42,13 @@ struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook) np->nn_stat.st_mode = S_IFREG | 0444; return np; + +fail: + if (ops->cleanup) + ops->cleanup (hook); + + free (nn); + return NULL; } error_t procfs_get_contents (struct node *np, void **data, size_t *data_len) diff --git a/procfs.h b/procfs.h index 0557b6d1..21b0f93d 100644 --- a/procfs.h +++ b/procfs.h @@ -29,6 +29,8 @@ struct procfs_node_ops void (*cleanup) (void *hook); }; +/* Create a new node and return it. Returns NULL if it fails to allocate + enough memory. In this case, ops->cleanup will be invoked. */ struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook); diff --git a/procfs_dir.c b/procfs_dir.c index 4d4faa28..62a45b1b 100644 --- a/procfs_dir.c +++ b/procfs_dir.c @@ -61,7 +61,6 @@ procfs_dir_make_node (const struct procfs_dir_entry *entries, void *dir_hook) .cleanup = free, }; struct procfs_dir_node *dn; - struct node *np; dn = malloc (sizeof *dn); if (! dn) @@ -70,10 +69,6 @@ procfs_dir_make_node (const struct procfs_dir_entry *entries, void *dir_hook) dn->entries = entries; dn->hook = dir_hook; - np = procfs_make_node (&ops, dn); - if (! np) - free (dn); - - return np; + return procfs_make_node (&ops, dn); } diff --git a/procfs_file.c b/procfs_file.c index 62419ee5..cb0488e9 100644 --- a/procfs_file.c +++ b/procfs_file.c @@ -40,7 +40,6 @@ procfs_file_make_node (void *contents, ssize_t len, void (*cleanup)(void *)) .cleanup = procfs_file_cleanup, }; struct procfs_file *f; - struct node *np; f = malloc (sizeof *f); if (! f) @@ -50,10 +49,6 @@ procfs_file_make_node (void *contents, ssize_t len, void (*cleanup)(void *)) f->len = (len >= 0) ? len : strlen (f->contents); f->cleanup = cleanup; - np = procfs_make_node (&ops, f); - if (! np) - free (f); - - return np; + return procfs_make_node (&ops, f); } diff --git a/proclist.c b/proclist.c index 4dd6ab31..16cef9d6 100644 --- a/proclist.c +++ b/proclist.c @@ -63,7 +63,6 @@ proclist_make_node (process_t process) .cleanup = free, }; struct proclist_node *pl; - struct node *np; pl = malloc (sizeof *pl); if (! pl) @@ -72,10 +71,6 @@ proclist_make_node (process_t process) memset (pl, 0, sizeof *pl); pl->process = process; - np = procfs_make_node (&ops, pl); - if (! np) - free (pl); - - return np; + return procfs_make_node (&ops, pl); } -- cgit v1.2.3 From ba139824fa06a97f2a3b1cc4c6085d10a83ec2b9 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Tue, 17 Aug 2010 17:27:54 +0000 Subject: More cleanup possibilities * procfs.c, procfs.h: Extend the signature of the cleanup_contents callback in the procfs_node_ops structure to include the hook and contents_len. (cleanup_contents_with_free, cleanup_contents_with_vm_deallocate): New functions, can be used as a cleanup_contents callback for simple cases. * procfs_dir.c, procfs_dir.h (procfs_dir_make_node): Update, add a cleanup callback, make sure the cleanup callback is invoked if there is an error. * proclist.c (proclist_make_node), main.c (main): Update to match the new interfaces. --- main.c | 2 +- procfs.c | 15 ++++++++++++++- procfs.h | 6 +++++- procfs_dir.c | 27 +++++++++++++++++++++++---- procfs_dir.h | 9 +++++++-- proclist.c | 2 +- 6 files changed, 51 insertions(+), 10 deletions(-) (limited to 'proclist.c') diff --git a/main.c b/main.c index bc5c865c..4350eff5 100644 --- a/main.c +++ b/main.c @@ -35,7 +35,7 @@ int main (int argc, char **argv) error (1, 0, "Must be started as a translator"); netfs_init (); - netfs_root_node = procfs_dir_make_node (entries, NULL); + netfs_root_node = procfs_dir_make_node (entries, NULL, NULL); netfs_startup (bootstrap, 0); for (;;) diff --git a/procfs.c b/procfs.c index 0c57686b..755e0519 100644 --- a/procfs.c +++ b/procfs.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include "procfs.h" @@ -15,6 +16,18 @@ struct netnode size_t contents_len; }; +void +procfs_cleanup_contents_with_free (void *hook, void *cont, size_t len) +{ + free (cont); +} + +void +procfs_cleanup_contents_with_vm_deallocate (void *hook, void *cont, size_t len) +{ + vm_deallocate (mach_task_self (), (vm_address_t) cont, (vm_size_t) len); +} + struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook) { struct netnode *nn; @@ -85,7 +98,7 @@ error_t procfs_lookup (struct node *np, const char *name, struct node **npp) void procfs_cleanup (struct node *np) { if (np->nn->contents && np->nn->ops->cleanup_contents) - np->nn->ops->cleanup_contents (np->nn->contents); + np->nn->ops->cleanup_contents (np->nn->hook, np->nn->contents, np->nn->contents_len); if (np->nn->ops->cleanup) np->nn->ops->cleanup (np->nn->hook); diff --git a/procfs.h b/procfs.h index 21b0f93d..3cb3223d 100644 --- a/procfs.h +++ b/procfs.h @@ -18,7 +18,7 @@ struct procfs_node_ops 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 *contents); + void (*cleanup_contents) (void *hook, void *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() @@ -29,6 +29,10 @@ struct procfs_node_ops void (*cleanup) (void *hook); }; +/* 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); + /* Create a new node and return it. Returns NULL if it fails to allocate enough memory. In this case, ops->cleanup will be invoked. */ struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook); diff --git a/procfs_dir.c b/procfs_dir.c index 62a45b1b..b7fb28fa 100644 --- a/procfs_dir.c +++ b/procfs_dir.c @@ -7,6 +7,7 @@ struct procfs_dir_node { const struct procfs_dir_entry *entries; void *hook; + void (*cleanup) (void *hook); }; static error_t @@ -51,23 +52,41 @@ procfs_dir_lookup (void *hook, const char *name, struct node **np) return 0; } +static void +procfs_dir_cleanup (void *hook) +{ + struct procfs_dir_node *dn = hook; + + if (dn->cleanup) + dn->cleanup (dn->hook); + + free (dn); +} + struct node * -procfs_dir_make_node (const struct procfs_dir_entry *entries, void *dir_hook) +procfs_dir_make_node (const struct procfs_dir_entry *entries, + void *dir_hook, void (*cleanup) (void *dir_hook)) { static const struct procfs_node_ops ops = { .get_contents = procfs_dir_get_contents, .lookup = procfs_dir_lookup, - .cleanup_contents = free, - .cleanup = free, + .cleanup_contents = procfs_cleanup_contents_with_free, + .cleanup = procfs_dir_cleanup, }; struct procfs_dir_node *dn; dn = malloc (sizeof *dn); if (! dn) - return NULL; + { + if (cleanup) + cleanup (dir_hook); + + return NULL; + } dn->entries = entries; dn->hook = dir_hook; + dn->cleanup = cleanup; return procfs_make_node (&ops, dn); } diff --git a/procfs_dir.h b/procfs_dir.h index 1ba45ad0..4eb934e0 100644 --- a/procfs_dir.h +++ b/procfs_dir.h @@ -9,7 +9,12 @@ struct procfs_dir_entry }; /* A simple directory is built from a table of entries. The table is - terminated by a null NAME pointer. */ + 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. */ struct node * -procfs_dir_make_node (const struct procfs_dir_entry *entries, void *dir_hook); +procfs_dir_make_node (const struct procfs_dir_entry *entries, + void *dir_hook, void (*cleanup) (void *dir_hook)); diff --git a/proclist.c b/proclist.c index 16cef9d6..e009ebdd 100644 --- a/proclist.c +++ b/proclist.c @@ -59,7 +59,7 @@ proclist_make_node (process_t process) static const struct procfs_node_ops ops = { .get_contents = proclist_get_contents, .lookup = proclist_lookup, - .cleanup_contents = free, + .cleanup_contents = procfs_cleanup_contents_with_free, .cleanup = free, }; struct proclist_node *pl; -- cgit v1.2.3 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. --- Makefile | 2 +- process.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ process.h | 2 ++ proclist.c | 13 ++++++++--- 4 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 process.c create mode 100644 process.h (limited to 'proclist.c') diff --git a/Makefile b/Makefile index 1fe7415b..23815d7f 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ TARGET = procfs -OBJS = procfs.o netfs.o procfs_file.o procfs_dir.o proclist.o main.o +OBJS = procfs.o netfs.o procfs_file.o procfs_dir.o process.o proclist.o main.o LIBS = -lnetfs CC = gcc 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); +} + diff --git a/process.h b/process.h new file mode 100644 index 00000000..8ca7c851 --- /dev/null +++ b/process.h @@ -0,0 +1,2 @@ +struct node * +process_make_node (process_t procserv, pid_t pid); diff --git a/proclist.c b/proclist.c index e009ebdd..148e4bc3 100644 --- a/proclist.c +++ b/proclist.c @@ -4,8 +4,7 @@ #include #include #include "procfs.h" -#include "procfs_file.h" -#include "procfs_dir.h" +#include "process.h" #define PID_STR_SIZE (3 * sizeof (pid_t) + 1) @@ -49,7 +48,15 @@ proclist_get_contents (void *hook, void **contents, size_t *contents_len) static error_t proclist_lookup (void *hook, const char *name, struct node **np) { - *np = procfs_file_make_node ("Ceci n'est pas un processus\n", -1, NULL); + struct proclist_node *pl = hook; + char *endp; + pid_t pid; + + pid = strtol (name, &endp, 10); + if (name[0] == '0' || !name[0] || *endp) + return ENOENT; + + *np = process_make_node (pl->process, pid); return *np ? 0 : ENOMEM; } -- 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 'proclist.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 56d301e212ac1964223cff8ef9c34889cb1a6e75 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Wed, 18 Aug 2010 20:44:54 +0000 Subject: Fuse the proclist into the root node * dircat.c, dircat.h: New files, merge directories. * Makefile: Add the dircat module. * main.c: Use dircat to merge the proclist into the root directory, instead of having it as a stand-alone one. * procfs.h, procfs.c: Add a "refresh hack" to have the contents of the root directory recreated on each request. * proclist.c (proclist_make_node): Enable the hack in question. --- Makefile | 3 +- dircat.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ dircat.h | 9 ++++++ main.c | 41 +++++++++++++++++++------- procfs.c | 8 +++++ procfs.h | 8 +++++ proclist.c | 1 + 7 files changed, 158 insertions(+), 11 deletions(-) create mode 100644 dircat.c create mode 100644 dircat.h (limited to 'proclist.c') diff --git a/Makefile b/Makefile index 23815d7f..97a61ed4 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ TARGET = procfs -OBJS = procfs.o netfs.o procfs_file.o procfs_dir.o process.o proclist.o main.o +OBJS = procfs.o netfs.o procfs_file.o procfs_dir.o \ + process.o proclist.o dircat.o main.o LIBS = -lnetfs CC = gcc diff --git a/dircat.c b/dircat.c new file mode 100644 index 00000000..857ba72b --- /dev/null +++ b/dircat.c @@ -0,0 +1,99 @@ +#include +#include +#include "procfs.h" + +struct dircat_node +{ + struct node **dirs; +}; + +static error_t +dircat_get_contents (void *hook, void **contents, size_t *contents_len) +{ + struct dircat_node *dcn = hook; + int i, sz, pos; + error_t err; + + pos = 0; + *contents = malloc (sz = 512); + + for (i=0; dcn->dirs[i]; i++) + { + void *subcon; + size_t sublen; + + err = procfs_get_contents (dcn->dirs[i], &subcon, &sublen); + if (err) + { + free (*contents); + *contents = NULL; + return err; + } + + while (pos + sublen > sz) + *contents = realloc (*contents, sz *= 2); + + memcpy (*contents + pos, subcon, sublen); + pos += sublen; + } + + *contents_len = pos; + return 0; +} + +static error_t +dircat_lookup (void *hook, const char *name, struct node **np) +{ + struct dircat_node *dcn = hook; + error_t err; + int i; + + err = ENOENT; + for (i=0; err && dcn->dirs[i]; i++) + err = procfs_lookup (dcn->dirs[i], name, np); + + return err; +} + +static void +dircat_release_dirs (struct node **dirs) +{ + int i; + + for (i=0; dirs[i]; i++) + netfs_nrele (dirs[i]); +} + +static void +dircat_cleanup (void *hook) +{ + struct dircat_node *dcn = hook; + + dircat_release_dirs (dcn->dirs); + free (dcn); +} + +struct node * +dircat_make_node (struct node **dirs) +{ + static struct procfs_node_ops ops = { + .get_contents = dircat_get_contents, + .cleanup_contents = procfs_cleanup_contents_with_free, + .lookup = dircat_lookup, + .cleanup = dircat_cleanup, + /* necessary so that it propagates to proclist */ + .enable_refresh_hack_and_break_readdir = 1, + }; + struct dircat_node *dcn; + + dcn = malloc (sizeof *dcn); + if (! dcn) + { + dircat_release_dirs (dirs); + return NULL; + } + + dcn->dirs = dirs; + return procfs_make_node (&ops, dcn); +} + diff --git a/dircat.h b/dircat.h new file mode 100644 index 00000000..cb228526 --- /dev/null +++ b/dircat.h @@ -0,0 +1,9 @@ +/* Append the contents of multiple directories. DIRS is a + NULL-terminated array of directory nodes. One reference is consumed + for each of them, even on ENOMEM, in which case NULL is returned. + DIRS has to be static data for now, or at list remain available and + unchanged for the duration of the created node's life. Strange + things will happen if they have entries with the same name or if one + of them is not a directory. */ +struct node * +dircat_make_node (struct node **dirs); diff --git a/main.c b/main.c index 4350eff5..e08bbdb7 100644 --- a/main.c +++ b/main.c @@ -7,25 +7,46 @@ #include "procfs_file.h" #include "procfs_dir.h" #include "proclist.h" +#include "dircat.h" -static struct node *make_file (void *dir_hook, void *ent_hook) +static struct node * +make_file (void *dir_hook, void *ent_hook) { return procfs_file_make_node (ent_hook, -1, NULL); } -static struct node *make_proclist (void *dir_hook, void *ent_hook) +error_t +root_make_node (struct node **np) { - return proclist_make_node (getproc ()); + static const struct procfs_dir_entry static_entries[] = { + { "hello", make_file, "Hello, World!\n" }, + { "goodbye", make_file, "Goodbye, cruel World!\n" }, + }; + /* We never have two root nodes alive simultaneously, so it's ok to + have this as static data. */ + static struct node *root_dirs[3]; + + 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]) + { + netfs_nrele (root_dirs[0]); + return ENOMEM; + } + + root_dirs[2] = NULL; + *np = dircat_make_node (root_dirs); + if (! *np) + return ENOMEM; + + return 0; } int main (int argc, char **argv) { - static const struct procfs_dir_entry entries[] = { - { "hello", make_file, "Hello, World!\n" }, - { "goodbye", make_file, "Goodbye, cruel World!\n" }, - { "proclist", make_proclist, }, - { } - }; mach_port_t bootstrap; argp_parse (&netfs_std_startup_argp, argc, argv, 0, 0, 0); @@ -35,7 +56,7 @@ int main (int argc, char **argv) error (1, 0, "Must be started as a translator"); netfs_init (); - netfs_root_node = procfs_dir_make_node (entries, NULL, NULL); + root_make_node (&netfs_root_node); netfs_startup (bootstrap, 0); for (;;) diff --git a/procfs.c b/procfs.c index 755e0519..573bb72f 100644 --- a/procfs.c +++ b/procfs.c @@ -66,6 +66,14 @@ fail: error_t procfs_get_contents (struct node *np, void **data, size_t *data_len) { + if (np->nn->ops->enable_refresh_hack_and_break_readdir && np->nn->contents) + { + if (np->nn->ops->cleanup_contents) + np->nn->ops->cleanup_contents (np->nn->hook, np->nn->contents, + np->nn->contents_len); + np->nn->contents = NULL; + } + if (! np->nn->contents && np->nn->ops->get_contents) { void *contents; diff --git a/procfs.h b/procfs.h index 3cb3223d..b44db6e3 100644 --- a/procfs.h +++ b/procfs.h @@ -27,6 +27,14 @@ struct procfs_node_ops /* Destroy this node. */ void (*cleanup) (void *hook); + + /* FIXME: This is needed because the root node is persistent, and we + want the list of processes to be updated. However, this means that + readdir() on the root node runs the risk of returning incoherent + results if done in multiple runs and processes are added/removed in + the meantime. The right way to fix this is probably to add a + getroot() user hook function to libnetfs. */ + int enable_refresh_hack_and_break_readdir; }; /* These helper functions can be used as procfs_node_ops.cleanup_contents. */ diff --git a/proclist.c b/proclist.c index 75b61a2e..94a7a04d 100644 --- a/proclist.c +++ b/proclist.c @@ -74,6 +74,7 @@ proclist_make_node (process_t process) .lookup = proclist_lookup, .cleanup_contents = procfs_cleanup_contents_with_free, .cleanup = free, + .enable_refresh_hack_and_break_readdir = 1, }; struct proclist_node *pl; -- 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 'proclist.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 4deaca2ce2c4ed2c5ab53f57a7747c71126a8da7 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 09:06:01 +0000 Subject: Use a global ps_context * proclist.c, proclist.h (proclist_create_node): Use a ps_context passed by the caller; errors are no longer possible, rename to proclist_make_node and change the signature accordingly. * rootdir.c, rootdir.h (rootdir_create_node): Likewise. * main.c (main): Create the ps_context here and pass it to root_make_node. (root_make_node): Pass it to proclist_make_node and rootdir_make_node. --- main.c | 35 ++++++++++++++++++++++------------- proclist.c | 15 +++------------ proclist.h | 6 ++++-- rootdir.c | 13 +++---------- rootdir.h | 6 ++++-- 5 files changed, 36 insertions(+), 39 deletions(-) (limited to 'proclist.c') diff --git a/main.c b/main.c index 4be506fb..91156485 100644 --- a/main.c +++ b/main.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "procfs.h" #include "proclist.h" #include "rootdir.h" @@ -94,38 +95,42 @@ struct argp argp = { }; error_t -root_make_node (struct node **np) +root_make_node (struct ps_context *pc, 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; - err = proclist_create_node (getproc (), &root_dirs[0]); - if (err) - return err; + root_dirs[0] = proclist_make_node (pc); + if (! root_dirs[0]) + goto nomem; - err = rootdir_create_node (&root_dirs[1]); - if (err) - { - netfs_nrele (root_dirs[0]); - return err; - } + root_dirs[1] = rootdir_make_node (pc); + if (! root_dirs[1]) + goto nomem; root_dirs[2] = NULL; *np = dircat_make_node (root_dirs); if (! *np) - return ENOMEM; + goto nomem; /* Since this one is not created through proc_lookup(), we have to affect an inode number to it. */ (*np)->nn_stat.st_ino = * (uint32_t *) "PROC"; return 0; + +nomem: + if (root_dirs[1]) + netfs_nrele (root_dirs[1]); + if (root_dirs[0]) + netfs_nrele (root_dirs[0]); + return ENOMEM; } int main (int argc, char **argv) { + struct ps_context *pc; mach_port_t bootstrap; error_t err; @@ -137,12 +142,16 @@ int main (int argc, char **argv) if (err) error (1, err, "Could not parse command line"); + err = ps_context_create (getproc (), &pc); + if (err) + error (1, err, "Could not create libps context"); + task_get_bootstrap_port (mach_task_self (), &bootstrap); if (bootstrap == MACH_PORT_NULL) error (1, 0, "Must be started as a translator"); netfs_init (); - err = root_make_node (&netfs_root_node); + err = root_make_node (pc, &netfs_root_node); if (err) error (1, err, "Could not create the root node"); diff --git a/proclist.c b/proclist.c index 56a3fdf9..35422a81 100644 --- a/proclist.c +++ b/proclist.c @@ -62,24 +62,15 @@ proclist_lookup (void *hook, const char *name, struct node **np) return process_lookup_pid (pc, pid, np); } -error_t -proclist_create_node (process_t procserv, struct node **np) +struct node * +proclist_make_node (struct ps_context *pc) { static const struct procfs_node_ops ops = { .get_contents = proclist_get_contents, .lookup = proclist_lookup, .cleanup_contents = procfs_cleanup_contents_with_free, - .cleanup = (void (*)(void *)) ps_context_free, .enable_refresh_hack_and_break_readdir = 1, }; - struct ps_context *pc; - error_t err; - - err = ps_context_create (procserv, &pc); - if (err) - return err; - - *np = procfs_make_node (&ops, pc); - return 0; + return procfs_make_node (&ops, pc); } diff --git a/proclist.h b/proclist.h index 1c7ab084..ce69dde3 100644 --- a/proclist.h +++ b/proclist.h @@ -1,2 +1,4 @@ -#include -error_t proclist_create_node (process_t procserv, struct node **np); +#include + +struct node * +proclist_make_node (struct ps_context *pc); diff --git a/rootdir.c b/rootdir.c index 865342ce..8062f0d3 100644 --- a/rootdir.c +++ b/rootdir.c @@ -357,22 +357,15 @@ static const struct procfs_dir_entry rootdir_entries[] = { {} }; -error_t -rootdir_create_node (struct node **np) +struct node +*rootdir_make_node (struct ps_context *pc) { - struct ps_context *pc; const struct procfs_dir_entry *entries; - error_t err; - - err = ps_context_create (getproc (), &pc); - if (err) - return err; entries = rootdir_entries; if (opt_fake_self < 0) entries++; - *np = procfs_dir_make_node (entries, pc, (void (*)(void *)) ps_context_free); - return 0; + return procfs_dir_make_node (entries, pc, NULL); } diff --git a/rootdir.h b/rootdir.h index a764b0fd..0caee258 100644 --- a/rootdir.h +++ b/rootdir.h @@ -1,2 +1,4 @@ -error_t -rootdir_create_node (struct node **np); +#include + +struct node * +rootdir_make_node (struct ps_context *pc); -- 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 'proclist.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 'proclist.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 b3d304167929bc199e6789fd67ffea035e7fdbf1 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 20:43:16 +0000 Subject: Refresh nodes when they're read from the start. This is necessary for top, for instance, which keeps some files open and re-reads them regularly. As an extra bonus we can drop the refresh hack. * procfs.c, procfs.h: Remove the refresh hack. (procfs_refresh): New function, invalidates the cached contents. * netfs.c (netfs_attempt_read, netfs_get_dirents): Call procfs_refresh when the read is from offset 0. * proclist.c (proclist_make_node): Remove the refresh hack. * dircat.c (dircat_make_node): Likewise. (dircat_get_contents): Use procfs_refresh to avoid keeping old data from the component nodes. --- dircat.c | 5 +++-- netfs.c | 6 ++++++ procfs.c | 19 +++++++++---------- procfs.h | 13 +++++-------- proclist.c | 1 - 5 files changed, 23 insertions(+), 21 deletions(-) (limited to 'proclist.c') diff --git a/dircat.c b/dircat.c index d043486d..d24e8345 100644 --- a/dircat.c +++ b/dircat.c @@ -23,6 +23,9 @@ dircat_get_contents (void *hook, char **contents, ssize_t *contents_len) char *subcon; ssize_t sublen; + /* Make sure we're not getting some old stuff. */ + procfs_refresh (dcn->dirs[i]); + err = procfs_get_contents (dcn->dirs[i], &subcon, &sublen); if (err) { @@ -83,8 +86,6 @@ dircat_make_node (struct node *const *dirs, int num_dirs) .cleanup_contents = procfs_cleanup_contents_with_free, .lookup = dircat_lookup, .cleanup = dircat_cleanup, - /* necessary so that it propagates to proclist */ - .enable_refresh_hack_and_break_readdir = 1, }; struct dircat_node *dcn; int i; diff --git a/netfs.c b/netfs.c index e41e0623..02a4bf54 100644 --- a/netfs.c +++ b/netfs.c @@ -57,6 +57,9 @@ error_t netfs_attempt_read (struct iouser *cred, struct node *np, ssize_t contents_len; error_t err; + if (offset == 0) + procfs_refresh (np); + err = procfs_get_contents (np, &contents, &contents_len); if (err) return err; @@ -139,6 +142,9 @@ error_t netfs_get_dirents (struct iouser *cred, struct node *dir, char *contents; ssize_t contents_len; error_t err; + + if (entry == 0) + procfs_refresh (dir); err = procfs_get_contents (dir, &contents, &contents_len); if (err) diff --git a/procfs.c b/procfs.c index 6d15e4fd..f7b28347 100644 --- a/procfs.c +++ b/procfs.c @@ -111,14 +111,6 @@ procfs_make_ino (struct node *np, const char *filename) 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) - { - if (np->nn->ops->cleanup_contents) - np->nn->ops->cleanup_contents (np->nn->hook, np->nn->contents, - np->nn->contents_len); - np->nn->contents = NULL; - } - if (! np->nn->contents && np->nn->ops->get_contents) { char *contents; @@ -141,6 +133,14 @@ error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len) return 0; } +void procfs_refresh (struct node *np) +{ + if (np->nn->contents && np->nn->ops->cleanup_contents) + np->nn->ops->cleanup_contents (np->nn->hook, np->nn->contents, np->nn->contents_len); + + np->nn->contents = NULL; +} + error_t procfs_lookup (struct node *np, const char *name, struct node **npp) { error_t err = ENOENT; @@ -172,8 +172,7 @@ error_t procfs_lookup (struct node *np, const char *name, struct node **npp) void procfs_cleanup (struct node *np) { - if (np->nn->contents && np->nn->ops->cleanup_contents) - np->nn->ops->cleanup_contents (np->nn->hook, np->nn->contents, np->nn->contents_len); + procfs_refresh (np); if (np->nn->ops->cleanup) np->nn->ops->cleanup (np->nn->hook); diff --git a/procfs.h b/procfs.h index e8ef18b3..a9665f97 100644 --- a/procfs.h +++ b/procfs.h @@ -32,14 +32,6 @@ struct procfs_node_ops /* Destroy this node. */ void (*cleanup) (void *hook); - - /* FIXME: This is needed because the root node is persistent, and we - want the list of processes to be updated. However, this means that - readdir() on the root node runs the risk of returning incoherent - results if done in multiple runs and processes are added/removed in - the meantime. The right way to fix this is probably to add a - getroot() user hook function to libnetfs. */ - int enable_refresh_hack_and_break_readdir; }; /* These helper functions can be used as procfs_node_ops.cleanup_contents. */ @@ -71,6 +63,11 @@ void procfs_node_chtype (struct node *np, mode_t type); corresponding child nodes. */ ino64_t procfs_make_ino (struct node *np, const char *filename); +/* Forget the current cached contents for the node. This is done before reads + from offset 0, to ensure that the data are recent even for utilities such as + top which keep some nodes open. */ +void procfs_refresh (struct node *np); + 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/proclist.c b/proclist.c index 38368feb..fe5d0cff 100644 --- a/proclist.c +++ b/proclist.c @@ -69,7 +69,6 @@ proclist_make_node (struct ps_context *pc) .get_contents = proclist_get_contents, .lookup = proclist_lookup, .cleanup_contents = procfs_cleanup_contents_with_free, - .enable_refresh_hack_and_break_readdir = 1, }; return procfs_make_node (&ops, pc); } -- 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 'proclist.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