summaryrefslogtreecommitdiff
path: root/libcons/dir-changed.c
diff options
context:
space:
mode:
authorMarcus Brinkmann <marcus@gnu.org>2002-08-22 19:24:19 +0000
committerMarcus Brinkmann <marcus@gnu.org>2002-08-22 19:24:19 +0000
commit9cc0d6d3f8a89f35ddea92e30bdc2822c4164358 (patch)
treed182cfe90532231aaff4411a9d0118e9e5a15e7e /libcons/dir-changed.c
parent4062fb2fcf938bb6a9c5d8f6404586cab11fe227 (diff)
libcons/
2002-08-22 Marcus Brinkmann <marcus@gnu.org> * demuxer.c, init-init.c, init-loop.c, opts-version.c, extra-version.c, dir-changed.c, file-changed.c, opts-std-startup.c, cons-lookup.c, cons-switch.c, vcons-remove.c, vcons-add.c, vcons-open.c, vcons-close.c, vcons-refresh.c, priv.h, mutations.h, cons.h: New files.
Diffstat (limited to 'libcons/dir-changed.c')
-rw-r--r--libcons/dir-changed.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/libcons/dir-changed.c b/libcons/dir-changed.c
new file mode 100644
index 00000000..15b466a6
--- /dev/null
+++ b/libcons/dir-changed.c
@@ -0,0 +1,130 @@
+/* dir-changed.c - Handling dir changed notifications.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Written by Marcus Brinkmann.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include <errno.h>
+#include <dirent.h>
+#include <assert.h>
+#include <mach.h>
+#include <cthreads.h>
+
+#include "cons.h"
+#include "fs_notify_S.h"
+
+
+static error_t
+add_one (cons_t cons, char *name)
+{
+ unsigned long int nr;
+ char *tail;
+
+ errno = 0;
+ nr = strtoul (name, &tail, 10);
+ if (!errno && *tail == '\0' && nr > 0)
+ {
+ vcons_t vcons;
+ return cons_lookup (cons, nr, 1, &vcons);
+ }
+ return 0;
+}
+
+static error_t
+lookup_one (cons_t cons, char *name, vcons_t *vcons)
+{
+ unsigned long int nr;
+ char *tail;
+
+ errno = 0;
+ nr = strtoul (name, &tail, 10);
+ if (!errno && *tail == '\0' && nr > 0)
+ return cons_lookup (cons, nr, 0, vcons);
+ return 0;
+}
+
+
+kern_return_t
+cons_S_dir_changed (cons_notify_t notify, natural_t tickno,
+ dir_changed_type_t change, string_t name)
+{
+ error_t err;
+ cons_t cons;
+
+ if (!notify || !notify->cons)
+ return EOPNOTSUPP;
+ cons = notify->cons;
+
+ mutex_lock (&cons->lock);
+
+ switch (change)
+ {
+ case DIR_CHANGED_NULL:
+ {
+ DIR *dir = cons->dir;
+ struct dirent *dent;
+ do
+ {
+ errno = 0;
+ dent = readdir (dir);
+ if (!dent && errno)
+ err = errno;
+ else if (dent)
+ err = add_one (cons, dent->d_name);
+ }
+ while (dent && !err);
+ if (err)
+ assert ("Unexpected error"); /* XXX */
+ }
+ break;
+ case DIR_CHANGED_NEW:
+ {
+ err = add_one (cons, name);
+ if (err)
+ assert ("Unexpected error"); /* XXX */
+ }
+ break;
+ case DIR_CHANGED_UNLINK:
+ {
+ vcons_t vcons;
+ err = lookup_one (cons, name, &vcons);
+ if (!err)
+ {
+ cons_vcons_remove (vcons);
+ if (vcons->prev)
+ vcons->prev->next = vcons->next;
+ else
+ cons->vcons_list = vcons->next;
+ if (vcons->next)
+ vcons->next->prev = vcons->prev;
+ else
+ cons->vcons_last = vcons->prev;
+
+ /* XXX Destroy the state. */
+ free (vcons);
+ }
+ }
+ break;
+ case DIR_CHANGED_RENUMBER:
+ default:
+ assert ("Unexpected dir-changed type.");
+ mutex_unlock (&cons->lock);
+ return EINVAL;
+ }
+ mutex_unlock (&cons->lock);
+ return 0;
+}