summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremie Koenig <jk@jk.fr.eu.org>2010-08-23 11:33:22 +0000
committerJeremie Koenig <jk@jk.fr.eu.org>2010-08-30 14:31:31 +0200
commit6e202c432e2f16dfa83a7dc21b759c03623fa394 (patch)
tree4b3a656b37a78f89ce85082c5e754d83e4c24e45
parent0f2bdacd6ad3dbcc905925dee12cb30918c33a11 (diff)
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.
-rw-r--r--dircat.c4
-rw-r--r--netfs.c8
-rw-r--r--process.c54
-rw-r--r--procfs.c13
-rw-r--r--procfs.h14
-rw-r--r--procfs_dir.c2
-rw-r--r--proclist.c2
-rw-r--r--rootdir.c30
8 files changed, 59 insertions, 68 deletions
diff --git a/dircat.c b/dircat.c
index 93bb2fe..bb66508 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 6fd82a0..e41e062 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 fa79552..624f79e 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 a5f52b5..6d15e4f 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 8336ee8..e8ef18b 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 4df4669..8ec3f7a 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 b5acb26..38368fe 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 cd8949b..364b073 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;
}