diff options
author | Gianluca Guida <glguida@gmail.com> | 2005-01-31 12:30:05 +0000 |
---|---|---|
committer | Gianluca Guida <glguida@gmail.com> | 2005-01-31 12:30:05 +0000 |
commit | 11a61b22dd0a0a0cc80b3c8594c85fecbb5e679a (patch) | |
tree | 82cddf3ab47f4284db20a9d7e4de84494360f55d | |
parent | ff7f04b7b3db282cba72ed16d9128a6b03816399 (diff) |
Added basic stowfs functionalities.
-rw-r--r-- | ChangeLog | 22 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | lib.c | 137 | ||||
-rw-r--r-- | lib.h | 5 | ||||
-rw-r--r-- | node.c | 2 | ||||
-rw-r--r-- | options.c | 31 | ||||
-rw-r--r-- | options.h | 4 | ||||
-rw-r--r-- | pattern.c | 131 | ||||
-rw-r--r-- | pattern.h | 53 | ||||
-rw-r--r-- | stow.c | 132 | ||||
-rw-r--r-- | stow.h | 27 |
11 files changed, 542 insertions, 4 deletions
@@ -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. @@ -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 @@ -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; +} @@ -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 @@ -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) @@ -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: @@ -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 */ @@ -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; + +} @@ -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 */ |