aboutsummaryrefslogtreecommitdiff
path: root/procfs/procfs_dir.c
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2014-06-15 18:25:59 +0200
committerJustus Winter <4winter@informatik.uni-hamburg.de>2014-06-15 18:25:59 +0200
commitaac4aaf42372f61c78061711916c81a9d5bcb42d (patch)
tree167fb3e426cc7757a43da2c7d04fc2baa293c5de /procfs/procfs_dir.c
parent65ebcc40e55dfb3ee776383891f8a6b15b176d27 (diff)
downloadhurd-aac4aaf42372f61c78061711916c81a9d5bcb42d.tar.gz
hurd-aac4aaf42372f61c78061711916c81a9d5bcb42d.tar.bz2
hurd-aac4aaf42372f61c78061711916c81a9d5bcb42d.zip
Prepare the procfs translator to be merged into the Hurd sources
Move the procfs translator to its own subdirectory 'procfs'. This is the last commit to this repository. Development of the procfs translator will continue in the main Hurd repository. * procfs/Makefile: Replace the standalone Makefile with the one from the Debian packaging repository.
Diffstat (limited to 'procfs/procfs_dir.c')
-rw-r--r--procfs/procfs_dir.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/procfs/procfs_dir.c b/procfs/procfs_dir.c
new file mode 100644
index 00000000..c250aa48
--- /dev/null
+++ b/procfs/procfs_dir.c
@@ -0,0 +1,134 @@
+/* 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 <stdlib.h>
+#include <string.h>
+#include "procfs.h"
+#include "procfs_dir.h"
+
+struct procfs_dir_node
+{
+ const struct procfs_dir_ops *ops;
+ void *hook;
+};
+
+static int
+entry_exists (struct procfs_dir_node *dir, const struct procfs_dir_entry *ent)
+{
+ if (ent->ops.exists)
+ return ent->ops.exists (dir->hook, ent->hook);
+ if (dir->ops->entry_ops.exists)
+ return dir->ops->entry_ops.exists (dir->hook, ent->hook);
+
+ return 1;
+}
+
+static error_t
+procfs_dir_get_contents (void *hook, char **contents, ssize_t *contents_len)
+{
+ static const char dot_dotdot[] = ".\0..";
+ struct procfs_dir_node *dir = hook;
+ const struct procfs_dir_entry *ent;
+ int pos;
+
+ /* Evaluate how much space is needed. Note that we include the hidden
+ entries, just in case their status changes between now and then. */
+ pos = sizeof dot_dotdot;
+ for (ent = dir->ops->entries; ent->name; ent++)
+ pos += strlen (ent->name) + 1;
+
+ *contents = malloc (pos);
+ if (! *contents)
+ return ENOMEM;
+
+ memcpy (*contents, dot_dotdot, sizeof dot_dotdot);
+ pos = sizeof dot_dotdot;
+ for (ent = dir->ops->entries; ent->name; ent++)
+ {
+ if (! entry_exists (dir, ent))
+ continue;
+
+ strcpy (*contents + pos, ent->name);
+ pos += strlen (ent->name) + 1;
+ }
+
+ *contents_len = pos;
+ return 0;
+}
+
+static error_t
+procfs_dir_lookup (void *hook, const char *name, struct node **np)
+{
+ struct procfs_dir_node *dir = hook;
+ const struct procfs_dir_entry *ent;
+
+ for (ent = dir->ops->entries; ent->name && strcmp (name, ent->name); ent++);
+ if (! ent->name)
+ return ENOENT;
+
+ if (ent->ops.make_node)
+ *np = ent->ops.make_node (dir->hook, ent->hook);
+ else if (dir->ops->entry_ops.make_node)
+ *np = dir->ops->entry_ops.make_node (dir->hook, ent->hook);
+ else
+ return EGRATUITOUS;
+
+ if (! *np)
+ return ENOMEM;
+
+ return 0;
+}
+
+static void
+procfs_dir_cleanup (void *hook)
+{
+ struct procfs_dir_node *dir = hook;
+
+ if (dir->ops->cleanup)
+ dir->ops->cleanup (dir->hook);
+
+ free (dir);
+}
+
+struct node *
+procfs_dir_make_node (const struct procfs_dir_ops *dir_ops, void *dir_hook)
+{
+ static const struct procfs_node_ops ops = {
+ .get_contents = procfs_dir_get_contents,
+ .lookup = procfs_dir_lookup,
+ .cleanup_contents = procfs_cleanup_contents_with_free,
+ .cleanup = procfs_dir_cleanup,
+ };
+ struct procfs_dir_node *dir;
+
+ dir = malloc (sizeof *dir);
+ if (! dir)
+ {
+ if (dir_ops->cleanup)
+ dir_ops->cleanup (dir_hook);
+
+ return NULL;
+ }
+
+ dir->ops = dir_ops;
+ dir->hook = dir_hook;
+
+ return procfs_make_node (&ops, dir);
+}
+