summaryrefslogtreecommitdiff
path: root/unionfs/node.c
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2012-04-08 23:09:39 +0000
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2012-04-08 23:09:39 +0000
commit5499792c357777dcfc5ee461fa64baaba1d2dde5 (patch)
tree15363c44fe541b3adcd720edf39696e9230d7feb /unionfs/node.c
parente5fca9a10c2622b85cc77e776ea56c8dbb9847e6 (diff)
parentc6db537edac054a03847b1b99f78c00703f48d6b (diff)
Merge branch 'dde' of git.debian.org:/git/pkg-hurd/hurd into dde
Diffstat (limited to 'unionfs/node.c')
-rw-r--r--unionfs/node.c555
1 files changed, 0 insertions, 555 deletions
diff --git a/unionfs/node.c b/unionfs/node.c
deleted file mode 100644
index cf9a8b47..00000000
--- a/unionfs/node.c
+++ /dev/null
@@ -1,555 +0,0 @@
-/* Hurd unionfs
- Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
- Written by Moritz Schulte <moritz@duesseldorf.ccc.de>.
-
- 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. */
-
-/* node management. */
-
-#define _GNU_SOURCE
-
-#include <hurd/netfs.h>
-#include <stdlib.h>
-#include <error.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <stdio.h>
-
-#include "unionfs.h"
-#include "node.h"
-#include "ulfs.h"
-#include "lib.h"
-
-/* Declarations for functions only used in this file. */
-
-/* Deallocate all ports contained in NODE and free per-ulfs data
- structures. */
-void node_ulfs_free (node_t *node);
-
-/* Create a new node, derived from a light node, add a reference to
- the light node. */
-error_t
-node_create (lnode_t *lnode, node_t **node)
-{
- netnode_t *netnode_new = malloc (sizeof (netnode_t));
- error_t err = 0;
- node_t *node_new;
-
- debug_msg ("node_create for lnode: %s", lnode->name);
-
- if (! netnode_new)
- {
- err = ENOMEM;
- return err;
- }
-
- node_new = netfs_make_node (netnode_new);
- if (! node_new)
- {
- err = ENOMEM;
- free (netnode_new);
- return err;
- }
-
- node_new->nn->ulfs = NULL;
-
- err = node_ulfs_init (node_new);
- if (err)
- {
- node_destroy (node_new);
- return err;
- }
-
- lnode->node = node_new;
- lnode_ref_add (lnode);
- node_new->nn->lnode = lnode;
- node_new->nn->flags = 0;
- node_new->nn->ncache_next = NULL;
- node_new->nn->ncache_prev = NULL;
- *node = node_new;
-
- return err;
-}
-
-/* Destroy a node, remove one reference from the associated light
- node. */
-void
-node_destroy (node_t *node)
-{
- debug_msg ("node destroy: %s", node->nn->lnode->name);
- assert (! (node->nn->ncache_next || node->nn->ncache_prev));
- node_ulfs_free (node);
- mutex_lock (&node->nn->lnode->lock);
- node->nn->lnode->node = NULL;
- lnode_ref_remove (node->nn->lnode);
- free (node->nn);
- free (node);
-}
-
-/* Make sure that all ports to the underlying filesystems of NODE,
- which must be locked, are uptodate. */
-error_t
-node_update (node_t *node)
-{
- error_t err = 0;
- char *path;
-
- node_ulfs_t *root_ulfs;
- struct stat stat;
- file_t port;
- int i = 0;
-
- debug_msg ("node_update for lnode: %s", node->nn->lnode->name);
-
- if (node_is_root (node))
- return err;
-
- mutex_lock (&netfs_root_node->lock);
-
- err = lnode_path_construct (node->nn->lnode, &path);
- if (err)
- {
- mutex_unlock (&netfs_root_node->lock);
- return err;
- }
-
- root_ulfs = netfs_root_node->nn->ulfs;
-
- node_ulfs_iterate_unlocked (node)
- {
-
- if (node_ulfs->flags & FLAG_NODE_ULFS_FIXED)
- {
- i++;
- continue;
- }
-
- /* We really have to update the port. */
- if (port_valid (node_ulfs->port))
- port_dealloc (node_ulfs->port);
-
- err = file_lookup ((root_ulfs + i)->port, path,
- O_READ | O_NOTRANS, O_NOTRANS,
- 0, &port, &stat);
-
- if (err)
- {
- node_ulfs->port = MACH_PORT_NULL;
- err = 0;
- i++;
- continue;
- }
-
- if (stat.st_ino == underlying_node_stat.st_ino
- && stat.st_fsid == underlying_node_stat.st_fsid)
- /* It's OUR root node. */
- err = ELOOP;
- else
- {
- port_dealloc (port);
- err = file_lookup ((root_ulfs + i)->port, path,
- O_READ, 0, 0, &port, &stat);
- }
-
- if (err)
- {
- port = MACH_PORT_NULL;
- err = 0;
- }
- node_ulfs->port = port;
-
- i++;
- }
-
- free (path);
- node->nn->flags |= FLAG_NODE_ULFS_UPTODATE;
-
- mutex_unlock (&netfs_root_node->lock);
-
- return err;
-}
-
-/* Remove all directory named NAME beneath DIR on all underlying filesystems.
- Fails if we cannot remove all the directories. */
-error_t
-node_dir_remove (node_t *dir, char *name)
-{
- error_t err = 0;
-
- node_ulfs_iterate_reverse_unlocked (dir)
- {
- if (!port_valid (node_ulfs->port))
- continue;
-
- err = dir_rmdir (node_ulfs->port, name);
- if ((err) && (err != ENOENT))
- break;
- }
-
- return err;
-}
-
-/* Create a directory named NAME beneath DIR on the first (writable) underlying
- filesystem. */
-error_t
-node_dir_create (node_t *dir, char *name, mode_t mode)
-{
- error_t err = 0;
-
- node_ulfs_iterate_unlocked (dir)
- {
- if (!port_valid (node_ulfs->port))
- continue;
-
- err = dir_mkdir (node_ulfs->port, name, mode);
-
- if ((!err) || (err == EEXIST) || (err == ENOTDIR))
- break;
- }
-
- return err;
-}
-
-/* Remove all files named NAME beneath DIR on the underlying filesystems
- with FLAGS as openflags. */
-error_t
-node_unlink_file (node_t *dir, char *name)
-{
- mach_port_t p;
- struct stat stat;
- error_t err = 0;
- int removed = 0;
-
- /* Using reverse iteration still have issues. Infact, we could be
- deleting a file in some underlying filesystem, and keeping those
- after the first occurring error.
- FIXME: Check BEFORE starting deletion. */
-
- node_ulfs_iterate_reverse_unlocked (dir)
- {
-
- if (!port_valid (node_ulfs->port))
- continue;
-
- err = file_lookup (node_ulfs->port, name,
- O_NOTRANS, O_NOTRANS,
- 0, &p, &stat);
-
- port_dealloc (p);
-
- if (err == ENOENT)
- {
- err = 0;
- continue;
- }
-
- if (err)
- break;
-
- err = dir_unlink (node_ulfs->port, name);
- if ((err) && (err != ENOENT))
- break;
-
- if (!err)
- removed++;
-
- }
-
- if ((!err) && (!removed))
- err = ENOENT;
-
- return err;
-}
-
-/* Lookup a file named NAME beneath DIR on the underlying filesystems
- with FLAGS as openflags. Return the first port successfully looked
- up in *PORT and according stat information in *STAT. */
-error_t
-node_lookup_file (node_t *dir, char *name, int flags,
- file_t *port, struct stat *s)
-{
- error_t err = ENOENT;
- struct stat stat;
- file_t p;
-
- node_ulfs_iterate_unlocked (dir)
- {
-
- if (err != ENOENT)
- break;
-
- if (!port_valid (node_ulfs->port))
- continue;
-
- err = file_lookup (node_ulfs->port, name,
- flags | O_NOTRANS, O_NOTRANS,
- 0, &p, &stat);
- if (err)
- continue;
-
- if (stat.st_ino == underlying_node_stat.st_ino
- && stat.st_fsid == underlying_node_stat.st_fsid)
- /* It's OUR root node. */
- err = ELOOP;
- else
- /* stat.st_mode & S_ITRANS */
- {
- port_dealloc (p);
- err = file_lookup (node_ulfs->port, name,
- flags, 0, 0, &p, &stat);
- }
- }
-
- if (! err)
- {
- *s = stat;
- *port = p;
- }
-
- return err;
-}
-
-/* Deallocate all ports contained in NODE and free per-ulfs data
- structures. */
-void
-node_ulfs_free (node_t *node)
-{
-
- node_ulfs_iterate_unlocked (node)
- {
- if (port_valid (node_ulfs->port)
- && node_ulfs->port != underlying_node)
- port_dealloc (node_ulfs->port);
- }
-
- free (node->nn->ulfs);
-}
-
-/* Initialize per-ulfs data structures for NODE. The ulfs_lock must
- be held by the caller. */
-error_t
-node_ulfs_init (node_t *node)
-{
- node_ulfs_t *ulfs_new;
- error_t err = 0;
-
- ulfs_new = malloc (ulfs_num * sizeof (node_ulfs_t));
- if (! ulfs_new)
- {
- err = ENOMEM;
- return err;
- }
-
- if (node->nn->ulfs)
- node_ulfs_free (node);
-
- node->nn->ulfs = ulfs_new;
- node->nn->ulfs_num = ulfs_num;
-
- node_ulfs_iterate_unlocked (node)
- {
- node_ulfs->flags = 0;
- node_ulfs->port = port_null;
- }
-
- return err;
-}
-
-/* Read the merged directory entries from NODE, which must be
- locked, into *DIRENTS. */
-error_t
-node_entries_get (node_t *node, node_dirent_t **dirents)
-{
- struct dirent **dirent_list, **dirent;
- node_dirent_t *node_dirent_list = NULL;
- size_t dirent_data_size;
- char *dirent_data;
- error_t err = 0;
-
- /* Add a dirent to the list. If an entry with the specified name
- already exists, reuse that entry. Otherwise create a new
- one. */
- error_t node_dirent_add (char *name, ino_t fileno, int type)
- {
- error_t e = 0;
- node_dirent_t *node_dirent;
- node_dirent_t *node_dirent_new;
- struct dirent *dirent_new;
- int name_len = strlen (name);
- int size = DIRENT_LEN (name_len);
-
-
- for (node_dirent = node_dirent_list;
- node_dirent && strcmp (node_dirent->dirent->d_name, name);
- node_dirent = node_dirent->next);
-
- if (node_dirent)
- {
- /* Reuse existing entry. */
-
- node_dirent->dirent->d_fileno = fileno;
- node_dirent->dirent->d_type = type;
- return e;
- }
-
- /* Create new entry. */
-
- node_dirent_new = malloc (sizeof (node_dirent_t));
- if (!node_dirent_new)
- {
- e = ENOMEM;
- return e;
- }
-
- dirent_new = malloc (size);
- if (!dirent_new)
- {
- free (node_dirent_new);
- e = ENOMEM;
- return e;
- }
-
- /* Fill dirent. */
- dirent_new->d_fileno = fileno;
- dirent_new->d_type = type;
- dirent_new->d_reclen = size;
- strcpy ((char *) dirent_new + DIRENT_NAME_OFFS, name);
-
- /* Add dirent to the list. */
- node_dirent_new->dirent = dirent_new;
- node_dirent_new->next = node_dirent_list;
- node_dirent_list = node_dirent_new;
-
- return e;
- }
-
- node_ulfs_iterate_unlocked(node)
- {
- if (!port_valid (node_ulfs->port))
- continue;
-
- err = dir_entries_get (node_ulfs->port, &dirent_data,
- &dirent_data_size, &dirent_list);
- if (err)
- continue;
-
- for (dirent = dirent_list; (! err) && *dirent; dirent++)
- if (strcmp ((*dirent)->d_name, ".")
- && strcmp ((*dirent)->d_name, ".."))
- err = node_dirent_add ((*dirent)->d_name,
- (*dirent)->d_fileno,
- (*dirent)->d_type);
-
- free (dirent_list);
- munmap (dirent_data, dirent_data_size);
- }
-
- if (err)
- node_entries_free (node_dirent_list);
- else
- *dirents = node_dirent_list;
-
- return err;
-}
-
-/* Free DIRENTS. */
-void
-node_entries_free (node_dirent_t *dirents)
-{
- node_dirent_t *dirent, *dirent_next;
-
- for (dirent = dirents; dirent; dirent = dirent_next)
- {
- dirent_next = dirent->next;
- free (dirent->dirent);
- free (dirent);
- }
-}
-
-/* Create the root node (and it's according lnode) and store it in
- *ROOT_NODE. */
-error_t
-node_create_root (node_t **root_node)
-{
- lnode_t *lnode;
- node_t *node;
- error_t err = 0;
-
- err = lnode_create (NULL, &lnode);
- if (err)
- return err;
-
- err = node_create (lnode, &node);
- if (err)
- {
- lnode_destroy (lnode);
- return err;
- }
-
- mutex_unlock (&lnode->lock);
- *root_node = node;
- return err;
-}
-
-/* Initialize the ports to the underlying filesystems for the root
- node. */
-
-error_t
-node_init_root (node_t *node)
-{
- error_t err;
- ulfs_t *ulfs;
- int i = 0;
-
- mutex_lock (&ulfs_lock);
-
- err = node_ulfs_init (node);
- if (err)
- {
- mutex_unlock (&ulfs_lock);
- return err;
- }
-
- node_ulfs_iterate_unlocked (node)
- {
-
- if (err)
- break;
-
- err = ulfs_get_num (i, &ulfs);
- if (err)
- break;
-
- if (ulfs->path)
- node_ulfs->port = file_name_lookup (ulfs->path,
- O_READ | O_DIRECTORY, 0);
- else
- node_ulfs->port = underlying_node;
-
- if (! port_valid (node_ulfs->port))
- {
- err = errno;
- break;
- }
-
- node_ulfs->flags |= FLAG_NODE_ULFS_FIXED;
- i++;
- }
-
- mutex_unlock (&ulfs_lock);
- return err;
-}