summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGianluca Guida <glguida@gmail.com>2005-01-31 12:30:05 +0000
committerGianluca Guida <glguida@gmail.com>2005-01-31 12:30:05 +0000
commit11a61b22dd0a0a0cc80b3c8594c85fecbb5e679a (patch)
tree82cddf3ab47f4284db20a9d7e4de84494360f55d
parentff7f04b7b3db282cba72ed16d9128a6b03816399 (diff)
Added basic stowfs functionalities.
-rw-r--r--ChangeLog22
-rw-r--r--Makefile2
-rw-r--r--lib.c137
-rw-r--r--lib.h5
-rw-r--r--node.c2
-rw-r--r--options.c31
-rw-r--r--options.h4
-rw-r--r--pattern.c131
-rw-r--r--pattern.h53
-rw-r--r--stow.c132
-rw-r--r--stow.h27
11 files changed, 542 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index a939e74..e19585a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2005-01-31 Gianluca Guida <glguida@gmail.com>
+
+ * pattern.c: New file.
+ * stow.c: Likewise.
+ * pattern.h: Likewise.
+ * stow.h: Likewise.
+ * Makefile (OBJS): Added pattern.o and stow.o
+
+ * node.c: Initialize variable err.
+ * lib.c (file_lookup): Initialize variable err.
+ Include <fcntl.h>.
+ (make_filepath, for_each_subdir, for_each_subdir_priv)
+ (for_each_file_priv): New function.
+ * lib.h (make_filepath, for_each_subdir, for_each_subdir_priv): New
+ declaration.
+ * options.c: Include "pattern.h".
+ Include "stow.h".
+ (arg_common_options): Added entries for OPT_STOW and OPT_PATTERN.
+ (argp_parse_common_options): Handle OPT_STOW and OPT_PATTERN case.
+ * options.h (OPT_PATTERN, OPT_STOW, OPT_LONG_PATTERN, OPT_LONG_STOW):
+ New declarations.
+
2003-07-05 Jeroen Dekkers <jeroen@dekkers.cx>
* Makefile: Rewrite.
diff --git a/Makefile b/Makefile
index 017863c..cdf157c 100644
--- a/Makefile
+++ b/Makefile
@@ -22,7 +22,7 @@ CFLAGS += -Wall -g -O2 -D_FILE_OFFSET_BITS=64 -std=gnu99 \
LDFLAGS += -lnetfs -lfshelp -liohelp -lthreads \
-lports -lihash -lshouldbeinlibc
OBJS = main.o node.o lnode.o ulfs.o ncache.o netfs.o \
- lib.o options.o
+ lib.o options.o pattern.o stow.o
all: unionfs
diff --git a/lib.c b/lib.c
index 86d8ce5..c15bcae 100644
--- a/lib.c
+++ b/lib.c
@@ -84,7 +84,7 @@ error_t
file_lookup (file_t dir, char *name, int flags0, int flags1,
int mode, file_t *port, struct stat *stat)
{
- error_t err;
+ error_t err = 0;
file_t p;
struct stat s;
@@ -121,3 +121,138 @@ file_lookup (file_t dir, char *name, int flags0, int flags1,
}
return err;
}
+
+#include <fcntl.h>
+
+char *
+make_filepath (char *path, char *filename)
+{
+ int length;
+ char *filepath;
+
+ length = strlen (path) + strlen (filename) + 2;
+ filepath = malloc (length);
+ if (filepath == NULL)
+ return NULL;
+
+ strncpy (filepath, path, length);
+ strncat (filepath, filename, strlen (filename));
+
+ return filepath;
+}
+
+error_t
+for_each_subdir (char *path, error_t (*func) (char *, char *))
+{
+ struct dirent **dirent, **dirent_list;
+ char *dirent_data;
+ size_t dirent_data_size;
+ file_t dir;
+ error_t err;
+
+ dir = file_name_lookup (path, O_READ, 0);
+
+ err = dir_entries_get (dir, &dirent_data, &dirent_data_size, &dirent_list);
+ if (err)
+ return err;
+
+ for (dirent = dirent_list; (! err) && (*dirent); dirent++)
+ {
+ char *name;
+ struct stat filestat;
+
+ if ((!strcmp ((*dirent)->d_name, "."))
+ || (!strcmp ((*dirent)->d_name, "..")))
+ continue;
+
+ name = make_filepath (path, (*dirent)->d_name);
+
+ err = stat (name, &filestat);
+
+ if (err)
+ return err;
+
+ free (name);
+
+ if (!S_ISDIR(filestat.st_mode))
+ continue;
+
+ err = func ((*dirent)->d_name, path);
+ }
+
+ return err;
+}
+
+error_t
+for_each_subdir_priv (char *path, error_t (*func) (char *, char *, void *),
+ void *priv)
+{
+ struct dirent **dirent, **dirent_list;
+ char *dirent_data;
+ size_t dirent_data_size;
+ file_t dir;
+ error_t err;
+
+ dir = file_name_lookup (path, O_READ, 0);
+
+ err = dir_entries_get (dir, &dirent_data, &dirent_data_size, &dirent_list);
+ if (err)
+ return err;
+
+ for (dirent = dirent_list; (!err) && (*dirent); dirent++)
+ {
+ char *name;
+ struct stat filestat;
+
+ if ((!strcmp ((*dirent)->d_name, "."))
+ || (!strcmp ((*dirent)->d_name, "..")))
+ continue;
+
+ name = make_filepath (path, (*dirent)->d_name);
+
+ err = stat (name, &filestat);
+
+ if (err)
+ return err;
+
+ free (name);
+
+ if (!S_ISDIR(filestat.st_mode))
+ continue;
+
+ func ((*dirent)->d_name, path, priv);
+ }
+
+ return err;
+}
+
+error_t
+for_each_file_priv (char *path, error_t (*func) (char *, char *, void *),
+ void *priv)
+{
+ struct dirent **dirent, **dirent_list;
+ char *dirent_data;
+ size_t dirent_data_size;
+ file_t dir;
+ error_t err;
+
+ dir = file_name_lookup (path, O_READ, 0);
+
+ err = dir_entries_get (dir, &dirent_data, &dirent_data_size, &dirent_list);
+ if (err)
+ return err;
+
+ for (dirent = dirent_list; (!err) && (*dirent); dirent++)
+ {
+ char *name;
+ struct stat filestat;
+
+ if ((!strcmp ((*dirent)->d_name, "."))
+ || (!strcmp ((*dirent)->d_name, "..")))
+ continue;
+
+ func ((*dirent)->d_name, path, priv);
+ }
+
+ return err;
+}
diff --git a/lib.h b/lib.h
index 7699bd8..37dae3f 100644
--- a/lib.h
+++ b/lib.h
@@ -49,6 +49,11 @@ error_t dir_entries_get (file_t dir, char **dirent_data,
size_t *dirent_data_size,
struct dirent ***dirent_list);
+char *make_filepath (char *, char *);
+error_t for_each_subdir (char *, error_t (*) (char *, char *));
+error_t for_each_subdir_priv (char *, error_t (*) (char *, char *, void *),
+ void *);
+
/* Lookup the file named NAME beneath DIR (or the cwd, if DIR is not a
valid port. Try to open with FLAGS0 first, and if that fails with
FLAGS1; MODE is the mode to user for newly created files. On
diff --git a/node.c b/node.c
index 177243e..5ea698a 100644
--- a/node.c
+++ b/node.c
@@ -360,7 +360,7 @@ node_create_root (node_t **root_node)
{
lnode_t *lnode;
node_t *node;
- error_t err;
+ error_t err = 0;
err = lnode_create (NULL, &lnode);
if (! err)
diff --git a/options.c b/options.c
index 225d649..28a68bf 100644
--- a/options.c
+++ b/options.c
@@ -30,6 +30,8 @@
#include "unionfs.h"
#include "node.h"
#include "version.h"
+#include "pattern.h"
+#include "stow.h"
/* This variable is set to a non-zero value after parsing of the
startup options. Whenever the argument parser is later called to
@@ -49,6 +51,10 @@ const struct argp_option argp_common_options[] =
{ OPT_LONG_CACHE_SIZE, OPT_CACHE_SIZE, "SIZE", 0,
"specify the maximum number of nodes in the cache" },
{ 0, 0, 0, 0, "Runtime options:", 1 },
+ { OPT_LONG_STOW, OPT_STOW, "STOWDIR", 0,
+ "stow given directory", 1},
+ { OPT_LONG_PATTERN, OPT_PATTERN, "PATTERN", 0,
+ "add only nodes of the underlying filesystem matching pattern", 1},
{ OPT_LONG_REMOVE, OPT_REMOVE, 0, 0,
"remove the following filesystem", 1 },
{ 0 }
@@ -64,7 +70,13 @@ const struct argp_option argp_startup_options[] =
error_t
argp_parse_common_options (int key, char *arg, struct argp_state *state)
{
- static int ulfs_flags = 0, ulfs_remove = 0, ulfs_modified = 0;
+ static int ulfs_flags = 0, ulfs_remove = 0, ulfs_modified = 0,
+ ulfs_match = 0;
+ static struct patternlist ulfs_patternlist =
+ {
+ .lock = MUTEX_INITIALIZER,
+ .head = NULL
+ };
error_t err = 0;
switch (key)
@@ -85,8 +97,24 @@ argp_parse_common_options (int key, char *arg, struct argp_state *state)
ulfs_remove = 1;
break;
+ case OPT_PATTERN: /* --match */
+ ulfs_match = 1;
+ patternlist_add (&ulfs_patternlist, arg);
+ break;
+
+ case OPT_STOW: /* --stow */
+ stow_diradd (arg, ulfs_flags, &ulfs_patternlist, ulfs_remove);
+
+ ulfs_modified = 1;
+ ulfs_flags = ulfs_remove = 0;
+ ulfs_match = 0;
+ break;
+
case OPT_UNDERLYING: /* --underlying */
case ARGP_KEY_ARG:
+
+ fprintf (stderr, "adding %s\n", arg);
+
if (ulfs_remove)
{
err = ulfs_unregister (arg);
@@ -101,6 +129,7 @@ argp_parse_common_options (int key, char *arg, struct argp_state *state)
error (EXIT_FAILURE, err, "ulfs_register");
ulfs_modified = 1;
ulfs_flags = ulfs_remove = 0;
+ ulfs_match = 0;
break;
case ARGP_KEY_END:
diff --git a/options.h b/options.h
index 2e86828..5ad2404 100644
--- a/options.h
+++ b/options.h
@@ -25,6 +25,8 @@
#define OPT_DEBUG 'd'
#define OPT_CACHE_SIZE 'c'
#define OPT_REMOVE 'r'
+#define OPT_PATTERN 'm'
+#define OPT_STOW 's'
/* The long options. */
#define OPT_LONG_UNDERLYING "underlying"
@@ -32,6 +34,8 @@
#define OPT_LONG_DEBUG "debug"
#define OPT_LONG_CACHE_SIZE "cache-size"
#define OPT_LONG_REMOVE "remove"
+#define OPT_LONG_PATTERN "match"
+#define OPT_LONG_STOW "stow"
#define OPT_LONG(o) "--" o
diff --git a/pattern.c b/pattern.c
new file mode 100644
index 0000000..68a0791
--- /dev/null
+++ b/pattern.c
@@ -0,0 +1,131 @@
+/* Hurd unionfs
+ Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
+ Written by Gianluca Guida <glguida@gmail.com>.
+
+ This program 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 of the
+ License, or * (at your option) any later version.
+
+ This program 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-1307
+ USA. */
+
+/* Pattern list management. */
+
+#define _GNU_SOURCE
+
+#include <hurd/netfs.h>
+#include <stdlib.h>
+#include <fnmatch.h>
+#include <errno.h>
+
+#include "pattern.h"
+
+/* Add a wildcard expression *PATTERN to **PATTERNLIST. */
+error_t
+patternlist_add (struct patternlist *list, char *pattern)
+{
+ error_t err = 0;
+ struct pattern *listentry;
+ char *dup;
+
+ if (pattern == NULL) /* BUG. */
+ err = EINVAL;
+
+ if (err)
+ return err;
+
+ dup = strdup (pattern);
+ if (dup == NULL)
+ err = ENOMEM;
+
+ if (err)
+ return err;
+
+ listentry = malloc (sizeof (struct pattern));
+ if (listentry == NULL)
+ err = ENOMEM;
+
+ if (err)
+ return err;
+
+ listentry->pattern = dup;
+
+ mutex_lock (& (list->lock));
+ if (list->head == NULL) /* List is empty. */
+ {
+ list->head = listentry;
+ listentry->next = NULL;
+ }
+ else
+ {
+ listentry->next = list->head;
+ list->head = listentry;
+ }
+ mutex_unlock (& (list->lock));
+
+ return err;
+}
+
+/* Check for match all pattern of the list *LIST, returning logical OR
+ of results. */
+int
+patternlist_match (struct patternlist *list, char *string)
+{
+ struct pattern *ptr;
+ error_t err = ~0; /* Return false by default */
+
+ ptr = list->head;
+
+ mutex_lock (&list->lock);
+ while (ptr != NULL)
+ {
+ err = fnmatch (ptr->pattern, string, FNM_FILE_NAME);
+
+ if (!err) /* String matched. */
+ break;
+
+ ptr = ptr->next;
+ }
+ mutex_unlock (&list->lock);
+
+ return err;
+}
+
+/* Free all resource used by *PATTERNLIST. */
+void
+patternlist_destroy (struct patternlist *list)
+{
+ struct pattern *next, *ptr = list->head;
+
+ mutex_lock (& (list->lock));
+ while (ptr != NULL)
+ {
+ next = ptr->next;
+
+ free (ptr);
+
+ ptr = next;
+ }
+ mutex_unlock (& (list->lock));
+}
+
+/* Return nonzero if *PATTERNLIST is empty. */
+int
+patternlist_isempty (struct patternlist *list)
+{
+ int ret;
+
+ mutex_lock (& (list->lock));
+ ret = (list->head == NULL);
+ mutex_unlock (& (list->lock));
+
+ return ret;
+}
diff --git a/pattern.h b/pattern.h
new file mode 100644
index 0000000..1bab993
--- /dev/null
+++ b/pattern.h
@@ -0,0 +1,53 @@
+/* Hurd unionfs
+ Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
+ Written by Gianluca Guida <glguida@gmail.com>.
+
+ This program 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 of the
+ License, or * (at your option) any later version.
+
+ This program 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-1307
+ USA. */
+
+/* Pattern list management. */
+
+#ifndef _PATTERN_H
+#define _PATTERN_H
+
+#include <hurd/netfs.h> /* For mutex stuff. */
+
+struct pattern
+{
+ char *pattern;
+
+ struct pattern *next;
+};
+
+struct patternlist
+{
+ struct mutex lock;
+ struct pattern *head;
+};
+
+/* Add a wildcard expression *PATTERN to **PATTERNLIST. */
+extern error_t patternlist_add (struct patternlist *list, char *pattern);
+
+/* Check for match all pattern of the list *LIST, returning logical OR
+ of results. */
+extern int patternlist_match (struct patternlist *list, char *string);
+
+/* Free all resource used by *PATTERNLIST */
+extern void patternlist_destroy (struct patternlist *list);
+
+/* Return nonzero if *PATTERNLIST is empty */
+extern int patternlist_isempty (struct patternlist *list);
+
+#endif /* _PATTERN_H */
diff --git a/stow.c b/stow.c
new file mode 100644
index 0000000..9089444
--- /dev/null
+++ b/stow.c
@@ -0,0 +1,132 @@
+/* Hurd unionfs
+ Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
+ Written by Gianluca Guida <glguida@gmail.com>.
+
+ This program 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 of the
+ License, or * (at your option) any later version.
+
+ This program 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-1307
+ USA. */
+
+/* Stow mode for unionfs. */
+
+#define _GNU_SOURCE
+
+#include <argp.h>
+#include <error.h>
+
+#include "ulfs.h"
+#include "lib.h"
+#include "pattern.h"
+
+struct stow_privdata
+{
+ struct patternlist *patternlist;
+ int flags;
+ int remove;
+};
+
+static error_t
+_stow_registermatchingdirs (char *arg, char *dirpath, void *priv)
+{
+ error_t err=0;
+ char *filepath;
+
+ struct stow_privdata *privdata = (struct stow_privdata *) priv ;
+
+ err = patternlist_match (privdata->patternlist, arg);
+
+ if (err)
+ return err;
+
+ filepath = make_filepath (dirpath, arg);
+
+ debug_msg_send ("adding %s\n", filepath);
+
+
+ if (privdata->remove)
+ {
+ err = ulfs_unregister (filepath);
+ if (err == ENOENT)
+ /* It is not a fatal error, when the user tries to remove
+ a filesystem, which is not used by unionfs. */
+ err = 0;
+ }
+ else
+ err = ulfs_register (filepath, privdata->flags);
+ if (err)
+ error (EXIT_FAILURE, err, "ulfs_register");
+
+ free (filepath);
+
+ return 0;
+
+}
+
+static error_t
+_stow_scanstowentry (char *arg, char *dirpath, void *priv)
+{
+ char *filepath = dirpath;
+ error_t err;
+
+ struct stow_privdata *privdata = (struct stow_privdata *) priv ;
+
+ if (dirpath)
+ {
+ char *tmp;
+ tmp = make_filepath (dirpath, arg);
+ filepath = make_filepath (tmp, "/");
+ free (tmp);
+ }
+
+ if (patternlist_isempty (privdata->patternlist))
+ {
+ if (privdata->remove)
+ {
+ err = ulfs_unregister (filepath);
+ if (err == ENOENT)
+ /* It is not a fatal error, when the user tries to remove
+ a filesystem, which is not used by unionfs. */
+ err = 0;
+ }
+ else
+ err = ulfs_register (filepath, privdata->flags);
+ if (err)
+ error (EXIT_FAILURE, err, "ulfs_register");
+ }
+ else
+ {
+ err = for_each_subdir_priv (filepath, _stow_registermatchingdirs, priv);
+ }
+
+ free (filepath);
+
+ return err;
+}
+
+error_t
+stow_diradd (char *dir, int flags, struct patternlist *patternlist, int remove)
+{
+
+ error_t err;
+ struct stow_privdata mypriv =
+ {
+ .patternlist = patternlist,
+ .flags = flags,
+ .remove = remove
+ };
+
+ err = for_each_subdir_priv (dir, _stow_scanstowentry, (void *)&mypriv);
+
+ return err;
+
+}
diff --git a/stow.h b/stow.h
new file mode 100644
index 0000000..7643f66
--- /dev/null
+++ b/stow.h
@@ -0,0 +1,27 @@
+/* Hurd unionfs
+ Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
+ Written by Gianluca Guida <glguida@gmail.com>.
+
+ This program 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 of the
+ License, or * (at your option) any later version.
+
+ This program 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-1307
+ USA. */
+
+/* Stow mode for unionfs. */
+
+#ifndef _STOW_H
+#define _STOW_H
+
+error_t stow_diradd (char *, int, struct patternlist *, int);
+
+#endif /* _STOW_H */