summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremie Koenig <jk@jk.fr.eu.org>2010-08-17 17:27:54 +0000
committerJeremie Koenig <jk@jk.fr.eu.org>2010-08-30 14:14:48 +0200
commitba139824fa06a97f2a3b1cc4c6085d10a83ec2b9 (patch)
treecab204b860507636bf9a42fb5cc3368b29f9ba99
parentac75e3648e6a9c3a8cf45d5fa491abd3a3ab3613 (diff)
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.
-rw-r--r--main.c2
-rw-r--r--procfs.c15
-rw-r--r--procfs.h6
-rw-r--r--procfs_dir.c27
-rw-r--r--procfs_dir.h9
-rw-r--r--proclist.c2
6 files changed, 51 insertions, 10 deletions
diff --git a/main.c b/main.c
index bc5c865..4350eff 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 0c57686..755e051 100644
--- a/procfs.c
+++ b/procfs.c
@@ -1,6 +1,7 @@
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
+#include <mach.h>
#include <hurd/netfs.h>
#include <hurd/fshelp.h>
#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 21b0f93..3cb3223 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 62a45b1..b7fb28f 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 1ba45ad..4eb934e 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 16cef9d..e009ebd 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;