summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dircat.c37
-rw-r--r--dircat.h17
-rw-r--r--main.c27
3 files changed, 38 insertions, 43 deletions
diff --git a/dircat.c b/dircat.c
index bb66508..d043486 100644
--- a/dircat.c
+++ b/dircat.c
@@ -4,7 +4,8 @@
struct dircat_node
{
- struct node **dirs;
+ int num_dirs;
+ struct node *dirs[0];
};
static error_t
@@ -17,7 +18,7 @@ dircat_get_contents (void *hook, char **contents, ssize_t *contents_len)
pos = 0;
*contents = malloc (sz = 512);
- for (i=0; dcn->dirs[i]; i++)
+ for (i=0; i < dcn->num_dirs; i++)
{
char *subcon;
ssize_t sublen;
@@ -49,19 +50,20 @@ dircat_lookup (void *hook, const char *name, struct node **np)
int i;
err = ENOENT;
- for (i=0; err && dcn->dirs[i]; i++)
+ for (i=0; err && i < dcn->num_dirs; i++)
err = procfs_lookup (dcn->dirs[i], name, np);
return err;
}
static void
-dircat_release_dirs (struct node **dirs)
+dircat_release_dirs (struct node *const *dirs, int num_dirs)
{
int i;
- for (i=0; dirs[i]; i++)
- netfs_nrele (dirs[i]);
+ for (i=0; i < num_dirs; i++)
+ if (dirs[i])
+ netfs_nrele (dirs[i]);
}
static void
@@ -69,12 +71,12 @@ dircat_cleanup (void *hook)
{
struct dircat_node *dcn = hook;
- dircat_release_dirs (dcn->dirs);
+ dircat_release_dirs (dcn->dirs, dcn->num_dirs);
free (dcn);
}
struct node *
-dircat_make_node (struct node **dirs)
+dircat_make_node (struct node *const *dirs, int num_dirs)
{
static struct procfs_node_ops ops = {
.get_contents = dircat_get_contents,
@@ -85,15 +87,22 @@ dircat_make_node (struct node **dirs)
.enable_refresh_hack_and_break_readdir = 1,
};
struct dircat_node *dcn;
+ int i;
+
+ for (i=0; i < num_dirs; i++)
+ if (! dirs[i])
+ goto fail;
- dcn = malloc (sizeof *dcn);
+ dcn = malloc (sizeof *dcn + num_dirs * sizeof dcn->dirs[0]);
if (! dcn)
- {
- dircat_release_dirs (dirs);
- return NULL;
- }
+ goto fail;
- dcn->dirs = dirs;
+ dcn->num_dirs = num_dirs;
+ memcpy (dcn->dirs, dirs, num_dirs * sizeof dcn->dirs[0]);
return procfs_make_node (&ops, dcn);
+
+fail:
+ dircat_release_dirs (dirs, num_dirs);
+ return NULL;
}
diff --git a/dircat.h b/dircat.h
index cb22852..951d202 100644
--- a/dircat.h
+++ b/dircat.h
@@ -1,9 +1,10 @@
-/* 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. */
+/* 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
+ NULL pointer, the references are dropped immediately and NULL is
+ returned. The given DIRS array is duplicated and can therefore be
+ allocated on the caller's stack. Strange things will happen if some
+ elements of DIRS have entries with the same name or if one of them is
+ not a directory. */
struct node *
-dircat_make_node (struct node **dirs);
+dircat_make_node (struct node *const *dirs, int num_dirs);
diff --git a/main.c b/main.c
index 06c1da0..eaab986 100644
--- a/main.c
+++ b/main.c
@@ -118,35 +118,20 @@ struct argp argp = {
error_t
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];
+ struct node *root_dirs[] = {
+ proclist_make_node (pc),
+ rootdir_make_node (pc),
+ };
- root_dirs[0] = proclist_make_node (pc);
- if (! root_dirs[0])
- goto nomem;
-
- root_dirs[1] = rootdir_make_node (pc);
- if (! root_dirs[1])
- goto nomem;
-
- root_dirs[2] = NULL;
- *np = dircat_make_node (root_dirs);
+ *np = dircat_make_node (root_dirs, sizeof root_dirs / sizeof root_dirs[0]);
if (! *np)
- goto nomem;
+ return ENOMEM;
/* 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)