summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--REAMDE10
-rw-r--r--debug.h59
-rw-r--r--filter.c726
-rw-r--r--filter.c~736
-rw-r--r--filter.h348
-rw-r--r--node.c166
-rw-r--r--node.h114
-rw-r--r--options.c190
-rw-r--r--options.h44
9 files changed, 2393 insertions, 0 deletions
diff --git a/REAMDE b/REAMDE
new file mode 100644
index 000000000..a162403f8
--- /dev/null
+++ b/REAMDE
@@ -0,0 +1,10 @@
+FILTER TRANSLATOR FOR NSMUX
+
+filter is GNU/Hurd translator designed specifically to be used in
+namespace-based translator selection, that is with nsmux. When set on
+a file this translator will traverse the stack of static translators
+(which sit on the real filesystem node) and stop at the translator
+whose name matches the name provided to the filter on the command
+line. It will then read and write data using this translator, i.e. all
+translators sitting upon this translator and below the filter will be
+shunted.
diff --git a/debug.h b/debug.h
new file mode 100644
index 000000000..254226737
--- /dev/null
+++ b/debug.h
@@ -0,0 +1,59 @@
+/*----------------------------------------------------------------------------*/
+/*debug.h*/
+/*----------------------------------------------------------------------------*/
+/*Simple facilities for debugging messages*/
+/*----------------------------------------------------------------------------*/
+/*Based on the code of unionfs translator.*/
+/*----------------------------------------------------------------------------*/
+/*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc.
+ Written by Sergiu Ivanov <unlimitedscolobb@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.*/
+/*----------------------------------------------------------------------------*/
+#ifndef __DEBUG_H__
+#define __DEBUG_H__
+
+/*----------------------------------------------------------------------------*/
+#include <stdio.h>
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Macros--------------------------------------------------------------*/
+/*Print debug messages here*/
+#define DEBUG_OUTPUT "/var/log/filter.dbg"
+/*----------------------------------------------------------------------------*/
+#ifdef DEBUG
+ /*Initializes the log*/
+# define INIT_LOG() filter_dbg = fopen(DEBUG_OUTPUT, "wt")
+ /*Closes the log*/
+# define CLOSE_LOG() fclose(filter_dbg)
+ /*Prints a debug message and flushes the debug output*/
+# define LOG_MSG(fmt, args...) {fprintf(filter_dbg, fmt"\n", ##args);\
+ fflush(filter_dbg);}
+#else
+ /*Remove requests for debugging output*/
+# define INIT_LOG()
+# define CLOSE_LOG()
+# define LOG_MSG(fmt, args...)
+#endif /*DEBUG*/
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Global Variables----------------------------------------------------*/
+/*The file to write debugging info to*/
+extern FILE * filter_dbg;
+/*----------------------------------------------------------------------------*/
+#endif /*__DEBUG_H__*/
diff --git a/filter.c b/filter.c
new file mode 100644
index 000000000..09a409cb2
--- /dev/null
+++ b/filter.c
@@ -0,0 +1,726 @@
+/*----------------------------------------------------------------------------*/
+/*filter.c*/
+/*----------------------------------------------------------------------------*/
+/*The filtering translator*/
+/*----------------------------------------------------------------------------*/
+/*Based on the code of unionfs translator.*/
+/*----------------------------------------------------------------------------*/
+/*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc.
+ Written by Sergiu Ivanov <unlimitedscolobb@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.*/
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+#define _GNU_SOURCE 1
+/*----------------------------------------------------------------------------*/
+#include "filter.h"
+/*----------------------------------------------------------------------------*/
+#include <error.h>
+#include <argp.h>
+#include <argz.h>
+#include <hurd/netfs.h>
+#include <fcntl.h>
+/*----------------------------------------------------------------------------*/
+#include "debug.h"
+#include "options.h"
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Global Variables----------------------------------------------------*/
+/*The name of the server*/
+char * netfs_server_name = "filter";
+/*----------------------------------------------------------------------------*/
+/*The version of the server*/
+char * netfs_server_version = "0.0";
+/*----------------------------------------------------------------------------*/
+/*The maximal length of a chain of symbolic links*/
+int netfs_maxsymlinks = 12;
+/*----------------------------------------------------------------------------*/
+/*A port to the underlying node*/
+mach_port_t underlying_node;
+/*----------------------------------------------------------------------------*/
+/*Status information for the underlying node*/
+io_statbuf_t underlying_node_stat;
+/*----------------------------------------------------------------------------*/
+/*Mapped time used for updating node information*/
+volatile struct mapped_time_value * maptime;
+/*----------------------------------------------------------------------------*/
+/*The filesystem ID*/
+pid_t fsid;
+/*----------------------------------------------------------------------------*/
+/*The port from which we will read (TODO: and write) the data*/
+mach_port_t target;
+/*----------------------------------------------------------------------------*/
+/*The file to print debug messages to*/
+FILE * filter_dbg;
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Functions-----------------------------------------------------------*/
+/*Attempts to create a file named `name` in `dir` for `user` with mode `mode`*/
+error_t
+netfs_attempt_create_file
+ (
+ struct iouser * user,
+ struct node * dir,
+ char * name,
+ mode_t mode,
+ struct node ** node
+ )
+ {
+ LOG_MSG("netfs_attempt_create_file");
+
+ /*Unlock `dir` and say that we can do nothing else here*/
+ mutex_unlock(&dir->lock);
+ return EOPNOTSUPP;
+ }/*netfs_attempt_create_file*/
+/*----------------------------------------------------------------------------*/
+/*Return an error if the process of opening a file should not be allowed
+ to complete because of insufficient permissions*/
+error_t
+netfs_check_open_permissions
+ (
+ struct iouser * user,
+ struct node * np,
+ int flags,
+ int newnode
+ )
+ {
+ LOG_MSG("netfs_check_open_permissions");
+
+ error_t err = 0;
+
+ /*Cheks user's permissions*/
+ if(flags & O_READ)
+ err = fshelp_access(&np->nn_stat, S_IREAD, user);
+ if(!err && (flags & O_WRITE))
+ err = fshelp_access(&np->nn_stat, S_IWRITE, user);
+ if(!err && (flags & O_EXEC))
+ err = fshelp_access(&np->nn_stat, S_IEXEC, user);
+
+ /*Return the result of the check*/
+ return err;
+ }/*netfs_check_open_permissions*/
+/*----------------------------------------------------------------------------*/
+/*Attempts an utimes call for the user `cred` on node `node`*/
+error_t
+netfs_attempt_utimes
+ (
+ struct iouser * cred,
+ struct node * node,
+ struct timespec * atime,
+ struct timespec * mtime
+ )
+ {
+ LOG_MSG("netfs_attempt_utimes");
+
+ error_t err = 0;
+
+ /*See what information is to be updated*/
+ int flags = TOUCH_CTIME;
+
+ /*Check if the user is indeed the owner of the node*/
+ err = fshelp_isowner(&node->nn_stat, cred);
+
+ /*If the user is allowed to do utimes*/
+ if(!err)
+ {
+ /*If atime is to be updated*/
+ if(atime)
+ /*update the atime*/
+ node->nn_stat.st_atim = *atime;
+ else
+ /*the current time will be set as the atime*/
+ flags |= TOUCH_ATIME;
+
+ /*If mtime is to be updated*/
+ if(mtime)
+ /*update the mtime*/
+ node->nn_stat.st_mtim = *mtime;
+ else
+ /*the current time will be set as mtime*/
+ flags |= TOUCH_MTIME;
+
+ /*touch the file*/
+ fshelp_touch(&node->nn_stat, flags, maptime);
+ }
+
+ /*Return the result of operations*/
+ return err;
+ }/*netfs_attempt_utimes*/
+/*----------------------------------------------------------------------------*/
+/*Returns the valid access types for file `node` and user `cred`*/
+error_t
+netfs_report_access
+ (
+ struct iouser * cred,
+ struct node * np,
+ int * types
+ )
+ {
+ LOG_MSG("netfs_report_access");
+
+ /*No access at first*/
+ *types = 0;
+
+ /*Check the access and set the required bits*/
+ if(fshelp_access(&np->nn_stat, S_IREAD, cred) == 0)
+ *types |= O_READ;
+ if(fshelp_access(&np->nn_stat, S_IWRITE, cred) == 0)
+ *types |= O_WRITE;
+ if(fshelp_access(&np->nn_stat, S_IEXEC, cred) == 0)
+ *types |= O_EXEC;
+
+ /*Everything OK*/
+ return 0;
+ }/*netfs_report_access*/
+/*----------------------------------------------------------------------------*/
+/*Validates the stat data for the node*/
+error_t
+netfs_validate_stat
+ (
+ struct node * np,
+ struct iouser * cred
+ )
+ {
+ LOG_MSG("netfs_validate_stat");
+
+ error_t err = 0;
+
+ /*Validate the stat information about the node*/
+ err = io_stat(np->nn->port, &np->nn_stat);
+
+ /*Return the result of operations*/
+ return err;
+ }/*netfs_validate_stat*/
+/*----------------------------------------------------------------------------*/
+/*Syncs `node` completely to disk*/
+error_t
+netfs_attempt_sync
+ (
+ struct iouser * cred,
+ struct node * node,
+ int wait
+ )
+ {
+ LOG_MSG("netfs_attempt_sync");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_sync*/
+/*----------------------------------------------------------------------------*/
+/*Fetches a directory*/
+error_t
+netfs_get_dirents
+ (
+ struct iouser * cred,
+ struct node * dir,
+ int first_entry,
+ int num_entries,
+ char ** data,
+ mach_msg_type_number_t * data_len,
+ vm_size_t max_data_len,
+ int * data_entries
+ )
+ {
+ LOG_MSG("netfs_get_dirents");
+
+ /*This node is not a directory*/
+ return ENOTDIR;
+ }/*netfs_get_dirents*/
+/*----------------------------------------------------------------------------*/
+/*Looks up `name` under `dir` for `user`*/
+error_t
+netfs_attempt_lookup
+ (
+ struct iouser * user,
+ struct node * dir,
+ char * name,
+ struct node ** node
+ )
+ {
+ LOG_MSG("netfs_attempt_lookup: '%s'", name);
+
+ /*Unlock the mutexes in `dir`*/
+ mutex_unlock(&dir->lock);
+ return EOPNOTSUPP;
+ }/*netfs_attempt_lookup*/
+/*----------------------------------------------------------------------------*/
+/*Deletes `name` in `dir` for `user`*/
+error_t
+netfs_attempt_unlink
+ (
+ struct iouser * user,
+ struct node * dir,
+ char * name
+ )
+ {
+ LOG_MSG("netfs_attempt_unlink");
+
+ return 0;
+ }/*netfs_attempt_unlink*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to rename `fromdir`/`fromname` to `todir`/`toname`*/
+error_t
+netfs_attempt_rename
+ (
+ struct iouser * user,
+ struct node * fromdir,
+ char * fromname,
+ struct node * todir,
+ char * toname,
+ int excl
+ )
+ {
+ LOG_MSG("netfs_attempt_rename");
+
+ /*Operation not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_rename*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to create a new directory*/
+error_t
+netfs_attempt_mkdir
+ (
+ struct iouser * user,
+ struct node * dir,
+ char * name,
+ mode_t mode
+ )
+ {
+ LOG_MSG("netfs_attempt_mkdir");
+
+ return 0;
+ }/*netfs_attempt_mkdir*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to remove directory `name` in `dir` for `user`*/
+error_t
+netfs_attempt_rmdir
+ (
+ struct iouser * user,
+ struct node * dir,
+ char * name
+ )
+ {
+ LOG_MSG("netfs_attempt_rmdir");
+
+ return 0;
+ }/*netfs_attempt_rmdir*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to change the mode of `node` for user `cred` to `uid`:`gid`*/
+error_t
+netfs_attempt_chown
+ (
+ struct iouser * cred,
+ struct node * node,
+ uid_t uid,
+ uid_t gid
+ )
+ {
+ LOG_MSG("netfs_attempt_chown");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_chown*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to change the author of `node` to `author`*/
+error_t
+netfs_attempt_chauthor
+ (
+ struct iouser * cred,
+ struct node * node,
+ uid_t author
+ )
+ {
+ LOG_MSG("netfs_attempt_chauthor");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_chauthor*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to change the mode of `node` to `mode` for `cred`*/
+error_t
+netfs_attempt_chmod
+ (
+ struct iouser * user,
+ struct node * node,
+ mode_t mode
+ )
+ {
+ LOG_MSG("netfs_attempt_chmod");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_chmod*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to turn `node` into a symlink targetting `name`*/
+error_t
+netfs_attempt_mksymlink
+ (
+ struct iouser * cred,
+ struct node * node,
+ char * name
+ )
+ {
+ LOG_MSG("netfs_attempt_mksymlink");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_mksymlink*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to turn `node` into a device; type can be either S_IFBLK or S_IFCHR*/
+error_t
+netfs_attempt_mkdev
+ (
+ struct iouser * cred,
+ struct node * node,
+ mode_t type,
+ dev_t indexes
+ )
+ {
+ LOG_MSG("netfs_attempt_mkdev");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_mkdev*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to set the passive translator record for `file` passing `argz`*/
+error_t
+netfs_set_translator
+ (
+ struct iouser * cred,
+ struct node * node,
+ char * argz,
+ size_t arglen
+ )
+ {
+ LOG_MSG("netfs_set_translator");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_set_translator */
+/*----------------------------------------------------------------------------*/
+/*Attempts to call chflags for `node`*/
+error_t
+netfs_attempt_chflags
+ (
+ struct iouser * cred,
+ struct node * node,
+ int flags
+ )
+ {
+ LOG_MSG("netfs_attempt_chflags");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_chflags*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to set the size of file `node`*/
+error_t
+netfs_attempt_set_size
+ (
+ struct iouser * cred,
+ struct node * node,
+ loff_t size
+ )
+ {
+ LOG_MSG("netfs_attempt_set_size");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_set_size*/
+/*----------------------------------------------------------------------------*/
+/*Fetches the filesystem status information*/
+error_t
+netfs_attempt_statfs
+ (
+ struct iouser * cred,
+ struct node * node,
+ fsys_statfsbuf_t * st
+ )
+ {
+ LOG_MSG("netfs_attempt_statfs");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_statfs*/
+/*----------------------------------------------------------------------------*/
+/*Syncs the filesystem*/
+error_t
+netfs_attempt_syncfs
+ (
+ struct iouser * cred,
+ int wait
+ )
+ {
+ LOG_MSG("netfs_attempt_syncfs");
+
+ /*Everythin OK*/
+ return 0;
+ }/*netfs_attempt_syncfs*/
+/*----------------------------------------------------------------------------*/
+/*Creates a link in `dir` with `name` to `file`*/
+error_t
+netfs_attempt_link
+ (
+ struct iouser * user,
+ struct node * dir,
+ struct node * file,
+ char * name,
+ int excl
+ )
+ {
+ LOG_MSG("netfs_attempt_link");
+
+ /*Operation not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_link*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to create an anonymous file related to `dir` with `mode`*/
+error_t
+netfs_attempt_mkfile
+ (
+ struct iouser * user,
+ struct node * dir,
+ mode_t mode,
+ struct node ** node
+ )
+ {
+ LOG_MSG("netfs_attempt_mkfile");
+
+ /*Unlock the directory*/
+ mutex_unlock(&dir->lock);
+
+ /*Operation not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_mkfile*/
+/*----------------------------------------------------------------------------*/
+/*Reads the contents of symlink `node` into `buf`*/
+error_t
+netfs_attempt_readlink
+ (
+ struct iouser * user,
+ struct node * node,
+ char * buf
+ )
+ {
+ LOG_MSG("netfs_attempt_readlink");
+
+ /*Operation not supported (why?..)*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_readlink*/
+/*----------------------------------------------------------------------------*/
+/*Reads from file `node` up to `len` bytes from `offset` into `data`*/
+error_t
+netfs_attempt_read
+ (
+ struct iouser * cred,
+ struct node * np,
+ loff_t offset,
+ size_t * len,
+ void * data
+ )
+ {
+ LOG_MSG("netfs_attempt_read");
+
+ error_t err = 0;
+
+ /*Obtain a pointer to the first byte of the supplied buffer*/
+ char * buf = data;
+
+ /*Try to read the requested information from the file*/
+ err = io_read(np->nn->port, &buf, len, offset, *len);
+
+ /*If some data has been read successfully*/
+ if(!err && (buf != data))
+ {
+ /*copy the data from the buffer into which it has just been read into
+ the supplied receiver*/
+ memcpy(data, buf, *len);
+
+ /*unmap the new buffer*/
+ munmap(buf, *len);
+ }
+
+ /*Return the result of reading*/
+ return err;
+ }/*netfs_attempt_read*/
+/*----------------------------------------------------------------------------*/
+/*Writes to file `node` up to `len` bytes from offset from `data`*/
+error_t
+netfs_attempt_write
+ (
+ struct iouser * cred,
+ struct node * node,
+ loff_t offset,
+ size_t * len,
+ void * data
+ )
+ {
+ LOG_MSG("netfs_attempt_write");
+
+ return 0;
+ }/*netfs_attempt_write*/
+/*----------------------------------------------------------------------------*/
+/*Frees all storage associated with the node*/
+void
+netfs_node_norefs
+ (
+ struct node * np
+ )
+ {
+ /*Destroy the node*/
+ node_destroy(np);
+ }/*netfs_node_norefs*/
+/*----------------------------------------------------------------------------*/
+/*Implements file_get_translator_cntl as described in <hurd/fs.defs>
+ (according to diskfs_S_file_get_translator_cntl)*/
+kern_return_t
+netfs_S_file_get_translator_cntl
+ (
+ struct protid * user,
+ mach_port_t * cntl,
+ mach_msg_type_name_t * cntltype
+ )
+ {
+ /*If the information about the user is missing*/
+ if(!user)
+ return EOPNOTSUPP;
+
+ error_t err = 0;
+
+ /*Obtain the node for which we are called*/
+ node_t * np = user->po->np;
+
+ /*Lock the node*/
+ mutex_lock(&np->lock);
+
+ /*Check if the user is the owner of this node*/
+ err = fshelp_isowner(&np->nn_stat, user->user);
+
+ /*If no errors have happened*/
+ if(!err)
+ /*try to fetch the control port*/
+ err = fshelp_fetch_control(&np->transbox, cntl);
+
+ /*If no errors have occurred, but no port has been returned*/
+ if(!err && (cntl == MACH_PORT_NULL))
+ /*set the error accordingly*/
+ err = ENXIO;
+
+ /*If no errors have occurred so far*/
+ if(!err)
+ /*set the control port type*/
+ *cntltype = MACH_MSG_TYPE_MOVE_SEND;
+
+ /*Unlock the node*/
+ mutex_unlock(&np->lock);
+
+ /*Return the result of operations*/
+ return err;
+ }/*netfs_S_file_get_translator_cntl*/
+/*----------------------------------------------------------------------------*/
+int
+netfs_demuxer
+ (
+ mach_msg_header_t * ing,
+ mach_msg_header_t * outp
+ );
+/*----------------------------------------------------------------------------*/
+/*Entry point*/
+int
+main
+ (
+ int argc,
+ char ** argv
+ )
+ {
+ /*Start logging*/
+ INIT_LOG();
+ LOG_MSG(">> Starting initialization...");
+
+ /*The port on which this translator will be set upon*/
+ mach_port_t bootstrap_port;
+
+ error_t err = 0;
+
+ /*Parse the command line arguments*/
+ argp_parse(&argp_startup, argc, argv, ARGP_IN_ORDER, 0, 0);
+ LOG_MSG("Command line arguments parsed.");
+
+ /*Try to create the root node*/
+ err = node_create_root(&netfs_root_node);
+ if(err)
+ error(EXIT_FAILURE, err, "Failed to create the root node");
+ LOG_MSG("Root node created.");
+
+ /*Obtain the bootstrap port*/
+ task_get_bootstrap_port(mach_task_self(), &bootstrap_port);
+
+ /*Initialize the translator*/
+ netfs_init();
+
+ /*Obtain a port to the underlying node opened as O_NOTRANS*/
+ underlying_node = netfs_startup(bootstrap_port, O_READ | O_NOTRANS);
+ LOG_MSG("netfs initialization complete.");
+
+ /*Initialize the root node*/
+ err = node_init_root(underlying_node, netfs_root_node);
+ if(err)
+ error(EXIT_FAILURE, err, "Failed to initialize the root node");
+ LOG_MSG("Root node initialized.");
+ LOG_MSG("\tRoot node address: 0x%lX", (unsigned long)netfs_root_node);
+
+ /*Map the time for updating node information*/
+ err = maptime_map(0, 0, &maptime);
+ if(err)
+ error(EXIT_FAILURE, err, "Failed to map the time");
+ LOG_MSG("Time mapped.");
+
+ /*Obtain stat information about the underlying node*/
+ err = io_stat(underlying_node, &underlying_node_stat);
+ if(err)
+ error(EXIT_FAILURE, err,
+ "Cannot obtain stat information about the underlying node");
+ LOG_MSG("Stat information for undelying node obtained.");
+
+ /*Obtain the ID of the current process*/
+ fsid = getpid();
+
+ /*Setup the stat information for the root node*/
+ netfs_root_node->nn_stat = underlying_node_stat;
+
+ netfs_root_node->nn_stat.st_ino = FILTER_ROOT_INODE;
+ netfs_root_node->nn_stat.st_fsid = fsid;
+ netfs_root_node->nn_stat.st_mode = underlying_node_stat.st_mode;
+
+ netfs_root_node->nn_translated = netfs_root_node->nn_stat.st_mode;
+
+ netfs_root_node->nn->port = target;
+
+ /*Update the timestamps of the root node*/
+ fshelp_touch
+ (&netfs_root_node->nn_stat, TOUCH_ATIME | TOUCH_MTIME | TOUCH_CTIME,
+ maptime);
+
+ LOG_MSG(">> Initialization complete. Entering netfs server loop...");
+
+ /*Start serving clients*/
+ for(;;)
+ netfs_server_loop();
+ }/*main*/
+/*----------------------------------------------------------------------------*/
diff --git a/filter.c~ b/filter.c~
new file mode 100644
index 000000000..bd4ad6d93
--- /dev/null
+++ b/filter.c~
@@ -0,0 +1,736 @@
+/*----------------------------------------------------------------------------*/
+/*filter.c*/
+/*----------------------------------------------------------------------------*/
+/*The filtering translator*/
+/*----------------------------------------------------------------------------*/
+/*Based on the code of unionfs translator.*/
+/*----------------------------------------------------------------------------*/
+/*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc.
+ Written by Sergiu Ivanov <unlimitedscolobb@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.*/
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+#define _GNU_SOURCE 1
+/*----------------------------------------------------------------------------*/
+#include "filter.h"
+/*----------------------------------------------------------------------------*/
+#include <error.h>
+#include <argp.h>
+#include <argz.h>
+#include <hurd/netfs.h>
+#include <fcntl.h>
+/*----------------------------------------------------------------------------*/
+#include "debug.h"
+#include "options.h"
+#include "trace.h"
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Global Variables----------------------------------------------------*/
+/*The name of the server*/
+char * netfs_server_name = "filter";
+/*----------------------------------------------------------------------------*/
+/*The version of the server*/
+char * netfs_server_version = "0.0";
+/*----------------------------------------------------------------------------*/
+/*The maximal length of a chain of symbolic links*/
+int netfs_maxsymlinks = 12;
+/*----------------------------------------------------------------------------*/
+/*A port to the underlying node*/
+mach_port_t underlying_node;
+/*----------------------------------------------------------------------------*/
+/*Status information for the underlying node*/
+io_statbuf_t underlying_node_stat;
+/*----------------------------------------------------------------------------*/
+/*Mapped time used for updating node information*/
+volatile struct mapped_time_value * maptime;
+/*----------------------------------------------------------------------------*/
+/*The filesystem ID*/
+pid_t fsid;
+/*----------------------------------------------------------------------------*/
+/*The port from which we will read (TODO: and write) the data*/
+mach_port_t target;
+/*----------------------------------------------------------------------------*/
+/*The file to print debug messages to*/
+FILE * filter_dbg;
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Functions-----------------------------------------------------------*/
+/*Attempts to create a file named `name` in `dir` for `user` with mode `mode`*/
+error_t
+netfs_attempt_create_file
+ (
+ struct iouser * user,
+ struct node * dir,
+ char * name,
+ mode_t mode,
+ struct node ** node
+ )
+ {
+ LOG_MSG("netfs_attempt_create_file");
+
+ /*Unlock `dir` and say that we can do nothing else here*/
+ mutex_unlock(&dir->lock);
+ return EOPNOTSUPP;
+ }/*netfs_attempt_create_file*/
+/*----------------------------------------------------------------------------*/
+/*Return an error if the process of opening a file should not be allowed
+ to complete because of insufficient permissions*/
+error_t
+netfs_check_open_permissions
+ (
+ struct iouser * user,
+ struct node * np,
+ int flags,
+ int newnode
+ )
+ {
+ LOG_MSG("netfs_check_open_permissions");
+
+ error_t err = 0;
+
+ /*Cheks user's permissions*/
+ if(flags & O_READ)
+ err = fshelp_access(&np->nn_stat, S_IREAD, user);
+ if(!err && (flags & O_WRITE))
+ err = fshelp_access(&np->nn_stat, S_IWRITE, user);
+ if(!err && (flags & O_EXEC))
+ err = fshelp_access(&np->nn_stat, S_IEXEC, user);
+
+ /*Return the result of the check*/
+ return err;
+ }/*netfs_check_open_permissions*/
+/*----------------------------------------------------------------------------*/
+/*Attempts an utimes call for the user `cred` on node `node`*/
+error_t
+netfs_attempt_utimes
+ (
+ struct iouser * cred,
+ struct node * node,
+ struct timespec * atime,
+ struct timespec * mtime
+ )
+ {
+ LOG_MSG("netfs_attempt_utimes");
+
+ error_t err = 0;
+
+ /*See what information is to be updated*/
+ int flags = TOUCH_CTIME;
+
+ /*Check if the user is indeed the owner of the node*/
+ err = fshelp_isowner(&node->nn_stat, cred);
+
+ /*If the user is allowed to do utimes*/
+ if(!err)
+ {
+ /*If atime is to be updated*/
+ if(atime)
+ /*update the atime*/
+ node->nn_stat.st_atim = *atime;
+ else
+ /*the current time will be set as the atime*/
+ flags |= TOUCH_ATIME;
+
+ /*If mtime is to be updated*/
+ if(mtime)
+ /*update the mtime*/
+ node->nn_stat.st_mtim = *mtime;
+ else
+ /*the current time will be set as mtime*/
+ flags |= TOUCH_MTIME;
+
+ /*touch the file*/
+ fshelp_touch(&node->nn_stat, flags, maptime);
+ }
+
+ /*Return the result of operations*/
+ return err;
+ }/*netfs_attempt_utimes*/
+/*----------------------------------------------------------------------------*/
+/*Returns the valid access types for file `node` and user `cred`*/
+error_t
+netfs_report_access
+ (
+ struct iouser * cred,
+ struct node * np,
+ int * types
+ )
+ {
+ LOG_MSG("netfs_report_access");
+
+ /*No access at first*/
+ *types = 0;
+
+ /*Check the access and set the required bits*/
+ if(fshelp_access(&np->nn_stat, S_IREAD, cred) == 0)
+ *types |= O_READ;
+ if(fshelp_access(&np->nn_stat, S_IWRITE, cred) == 0)
+ *types |= O_WRITE;
+ if(fshelp_access(&np->nn_stat, S_IEXEC, cred) == 0)
+ *types |= O_EXEC;
+
+ /*Everything OK*/
+ return 0;
+ }/*netfs_report_access*/
+/*----------------------------------------------------------------------------*/
+/*Validates the stat data for the node*/
+error_t
+netfs_validate_stat
+ (
+ struct node * np,
+ struct iouser * cred
+ )
+ {
+ LOG_MSG("netfs_validate_stat");
+
+ error_t err = 0;
+
+ /*Validate the stat information about the node*/
+ err = io_stat(np->nn->port, &np->nn_stat);
+
+ /*Return the result of operations*/
+ return err;
+ }/*netfs_validate_stat*/
+/*----------------------------------------------------------------------------*/
+/*Syncs `node` completely to disk*/
+error_t
+netfs_attempt_sync
+ (
+ struct iouser * cred,
+ struct node * node,
+ int wait
+ )
+ {
+ LOG_MSG("netfs_attempt_sync");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_sync*/
+/*----------------------------------------------------------------------------*/
+/*Fetches a directory*/
+error_t
+netfs_get_dirents
+ (
+ struct iouser * cred,
+ struct node * dir,
+ int first_entry,
+ int num_entries,
+ char ** data,
+ mach_msg_type_number_t * data_len,
+ vm_size_t max_data_len,
+ int * data_entries
+ )
+ {
+ LOG_MSG("netfs_get_dirents");
+
+ /*This node is not a directory*/
+ return ENOTDIR;
+ }/*netfs_get_dirents*/
+/*----------------------------------------------------------------------------*/
+/*Looks up `name` under `dir` for `user`*/
+error_t
+netfs_attempt_lookup
+ (
+ struct iouser * user,
+ struct node * dir,
+ char * name,
+ struct node ** node
+ )
+ {
+ LOG_MSG("netfs_attempt_lookup: '%s'", name);
+
+ /*Unlock the mutexes in `dir`*/
+ mutex_unlock(&dir->lock);
+ return EOPNOTSUPP;
+ }/*netfs_attempt_lookup*/
+/*----------------------------------------------------------------------------*/
+/*Deletes `name` in `dir` for `user`*/
+error_t
+netfs_attempt_unlink
+ (
+ struct iouser * user,
+ struct node * dir,
+ char * name
+ )
+ {
+ LOG_MSG("netfs_attempt_unlink");
+
+ return 0;
+ }/*netfs_attempt_unlink*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to rename `fromdir`/`fromname` to `todir`/`toname`*/
+error_t
+netfs_attempt_rename
+ (
+ struct iouser * user,
+ struct node * fromdir,
+ char * fromname,
+ struct node * todir,
+ char * toname,
+ int excl
+ )
+ {
+ LOG_MSG("netfs_attempt_rename");
+
+ /*Operation not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_rename*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to create a new directory*/
+error_t
+netfs_attempt_mkdir
+ (
+ struct iouser * user,
+ struct node * dir,
+ char * name,
+ mode_t mode
+ )
+ {
+ LOG_MSG("netfs_attempt_mkdir");
+
+ return 0;
+ }/*netfs_attempt_mkdir*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to remove directory `name` in `dir` for `user`*/
+error_t
+netfs_attempt_rmdir
+ (
+ struct iouser * user,
+ struct node * dir,
+ char * name
+ )
+ {
+ LOG_MSG("netfs_attempt_rmdir");
+
+ return 0;
+ }/*netfs_attempt_rmdir*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to change the mode of `node` for user `cred` to `uid`:`gid`*/
+error_t
+netfs_attempt_chown
+ (
+ struct iouser * cred,
+ struct node * node,
+ uid_t uid,
+ uid_t gid
+ )
+ {
+ LOG_MSG("netfs_attempt_chown");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_chown*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to change the author of `node` to `author`*/
+error_t
+netfs_attempt_chauthor
+ (
+ struct iouser * cred,
+ struct node * node,
+ uid_t author
+ )
+ {
+ LOG_MSG("netfs_attempt_chauthor");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_chauthor*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to change the mode of `node` to `mode` for `cred`*/
+error_t
+netfs_attempt_chmod
+ (
+ struct iouser * user,
+ struct node * node,
+ mode_t mode
+ )
+ {
+ LOG_MSG("netfs_attempt_chmod");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_chmod*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to turn `node` into a symlink targetting `name`*/
+error_t
+netfs_attempt_mksymlink
+ (
+ struct iouser * cred,
+ struct node * node,
+ char * name
+ )
+ {
+ LOG_MSG("netfs_attempt_mksymlink");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_mksymlink*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to turn `node` into a device; type can be either S_IFBLK or S_IFCHR*/
+error_t
+netfs_attempt_mkdev
+ (
+ struct iouser * cred,
+ struct node * node,
+ mode_t type,
+ dev_t indexes
+ )
+ {
+ LOG_MSG("netfs_attempt_mkdev");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_mkdev*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to set the passive translator record for `file` passing `argz`*/
+error_t
+netfs_set_translator
+ (
+ struct iouser * cred,
+ struct node * node,
+ char * argz,
+ size_t arglen
+ )
+ {
+ LOG_MSG("netfs_set_translator");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_set_translator */
+/*----------------------------------------------------------------------------*/
+/*Attempts to call chflags for `node`*/
+error_t
+netfs_attempt_chflags
+ (
+ struct iouser * cred,
+ struct node * node,
+ int flags
+ )
+ {
+ LOG_MSG("netfs_attempt_chflags");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_chflags*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to set the size of file `node`*/
+error_t
+netfs_attempt_set_size
+ (
+ struct iouser * cred,
+ struct node * node,
+ loff_t size
+ )
+ {
+ LOG_MSG("netfs_attempt_set_size");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_set_size*/
+/*----------------------------------------------------------------------------*/
+/*Fetches the filesystem status information*/
+error_t
+netfs_attempt_statfs
+ (
+ struct iouser * cred,
+ struct node * node,
+ fsys_statfsbuf_t * st
+ )
+ {
+ LOG_MSG("netfs_attempt_statfs");
+
+ /*Operation is not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_statfs*/
+/*----------------------------------------------------------------------------*/
+/*Syncs the filesystem*/
+error_t
+netfs_attempt_syncfs
+ (
+ struct iouser * cred,
+ int wait
+ )
+ {
+ LOG_MSG("netfs_attempt_syncfs");
+
+ /*Everythin OK*/
+ return 0;
+ }/*netfs_attempt_syncfs*/
+/*----------------------------------------------------------------------------*/
+/*Creates a link in `dir` with `name` to `file`*/
+error_t
+netfs_attempt_link
+ (
+ struct iouser * user,
+ struct node * dir,
+ struct node * file,
+ char * name,
+ int excl
+ )
+ {
+ LOG_MSG("netfs_attempt_link");
+
+ /*Operation not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_link*/
+/*----------------------------------------------------------------------------*/
+/*Attempts to create an anonymous file related to `dir` with `mode`*/
+error_t
+netfs_attempt_mkfile
+ (
+ struct iouser * user,
+ struct node * dir,
+ mode_t mode,
+ struct node ** node
+ )
+ {
+ LOG_MSG("netfs_attempt_mkfile");
+
+ /*Unlock the directory*/
+ mutex_unlock(&dir->lock);
+
+ /*Operation not supported*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_mkfile*/
+/*----------------------------------------------------------------------------*/
+/*Reads the contents of symlink `node` into `buf`*/
+error_t
+netfs_attempt_readlink
+ (
+ struct iouser * user,
+ struct node * node,
+ char * buf
+ )
+ {
+ LOG_MSG("netfs_attempt_readlink");
+
+ /*Operation not supported (why?..)*/
+ return EOPNOTSUPP;
+ }/*netfs_attempt_readlink*/
+/*----------------------------------------------------------------------------*/
+/*Reads from file `node` up to `len` bytes from `offset` into `data`*/
+error_t
+netfs_attempt_read
+ (
+ struct iouser * cred,
+ struct node * np,
+ loff_t offset,
+ size_t * len,
+ void * data
+ )
+ {
+ LOG_MSG("netfs_attempt_read");
+
+ error_t err = 0;
+
+ /*Obtain a pointer to the first byte of the supplied buffer*/
+ char * buf = data;
+
+ /*Try to read the requested information from the file*/
+ err = io_read(np->nn->port, &buf, len, offset, *len);
+
+ /*If some data has been read successfully*/
+ if(!err && (buf != data))
+ {
+ /*copy the data from the buffer into which it has just been read into
+ the supplied receiver*/
+ memcpy(data, buf, *len);
+
+ /*unmap the new buffer*/
+ munmap(buf, *len);
+ }
+
+ /*Return the result of reading*/
+ return err;
+ }/*netfs_attempt_read*/
+/*----------------------------------------------------------------------------*/
+/*Writes to file `node` up to `len` bytes from offset from `data`*/
+error_t
+netfs_attempt_write
+ (
+ struct iouser * cred,
+ struct node * node,
+ loff_t offset,
+ size_t * len,
+ void * data
+ )
+ {
+ LOG_MSG("netfs_attempt_write");
+
+ return 0;
+ }/*netfs_attempt_write*/
+/*----------------------------------------------------------------------------*/
+/*Frees all storage associated with the node*/
+void
+netfs_node_norefs
+ (
+ struct node * np
+ )
+ {
+ /*Destroy the node*/
+ node_destroy(np);
+ }/*netfs_node_norefs*/
+/*----------------------------------------------------------------------------*/
+/*Implements file_get_translator_cntl as described in <hurd/fs.defs>
+ (according to diskfs_S_file_get_translator_cntl)*/
+kern_return_t
+netfs_S_file_get_translator_cntl
+ (
+ struct protid * user,
+ mach_port_t * cntl,
+ mach_msg_type_name_t * cntltype
+ )
+ {
+ /*If the information about the user is missing*/
+ if(!user)
+ return EOPNOTSUPP;
+
+ error_t err = 0;
+
+ /*Obtain the node for which we are called*/
+ node_t * np = user->po->np;
+
+ /*Lock the node*/
+ mutex_lock(&np->lock);
+
+ /*Check if the user is the owner of this node*/
+ err = fshelp_isowner(&np->nn_stat, user->user);
+
+ /*If no errors have happened*/
+ if(!err)
+ /*try to fetch the control port*/
+ err = fshelp_fetch_control(&np->transbox, cntl);
+
+ /*If no errors have occurred, but no port has been returned*/
+ if(!err && (cntl == MACH_PORT_NULL))
+ /*set the error accordingly*/
+ err = ENXIO;
+
+ /*If no errors have occurred so far*/
+ if(!err)
+ /*set the control port type*/
+ *cntltype = MACH_MSG_TYPE_MOVE_SEND;
+
+ /*Unlock the node*/
+ mutex_unlock(&np->lock);
+
+ /*Return the result of operations*/
+ return err;
+ }/*netfs_S_file_get_translator_cntl*/
+/*----------------------------------------------------------------------------*/
+int
+netfs_demuxer
+ (
+ mach_msg_header_t * ing,
+ mach_msg_header_t * outp
+ );
+/*----------------------------------------------------------------------------*/
+/*Entry point*/
+int
+main
+ (
+ int argc,
+ char ** argv
+ )
+ {
+ /*Start logging*/
+ INIT_LOG();
+ LOG_MSG(">> Starting initialization...");
+
+ /*The port on which this translator will be set upon*/
+ mach_port_t bootstrap_port;
+
+ error_t err = 0;
+
+ /*Parse the command line arguments*/
+ argp_parse(&argp_startup, argc, argv, ARGP_IN_ORDER, 0, 0);
+ LOG_MSG("Command line arguments parsed.");
+
+ /*Try to create the root node*/
+ err = node_create_root(&netfs_root_node);
+ if(err)
+ error(EXIT_FAILURE, err, "Failed to create the root node");
+ LOG_MSG("Root node created.");
+
+ /*Obtain the bootstrap port*/
+ task_get_bootstrap_port(mach_task_self(), &bootstrap_port);
+
+ /*Initialize the translator*/
+ netfs_init();
+
+ /*Obtain a port to the underlying node opened as O_NOTRANS*/
+ underlying_node = netfs_startup(bootstrap_port, O_READ | O_NOTRANS);
+ LOG_MSG("netfs initialization complete.");
+
+ /*Initialize the root node*/
+ err = node_init_root(underlying_node, netfs_root_node);
+ if(err)
+ error(EXIT_FAILURE, err, "Failed to initialize the root node");
+ LOG_MSG("Root node initialized.");
+ LOG_MSG("\tRoot node address: 0x%lX", (unsigned long)netfs_root_node);
+
+ /*Map the time for updating node information*/
+ err = maptime_map(0, 0, &maptime);
+ if(err)
+ error(EXIT_FAILURE, err, "Failed to map the time");
+ LOG_MSG("Time mapped.");
+
+ /*Obtain stat information about the underlying node*/
+ err = io_stat(underlying_node, &underlying_node_stat);
+ if(err)
+ error(EXIT_FAILURE, err,
+ "Cannot obtain stat information about the underlying node");
+ LOG_MSG("Stat information for undelying node obtained.");
+
+ /*Obtain the ID of the current process*/
+ fsid = getpid();
+
+ /*Setup the stat information for the root node*/
+ netfs_root_node->nn_stat = underlying_node_stat;
+
+ netfs_root_node->nn_stat.st_ino = FILTER_ROOT_INODE;
+ netfs_root_node->nn_stat.st_fsid = fsid;
+ netfs_root_node->nn_stat.st_mode = underlying_node_stat.st_mode;
+
+ netfs_root_node->nn_translated = netfs_root_node->nn_stat.st_mode;
+
+ /*Filter the translator stack under ourselves*/
+ err = trace_find(underlying_node, "/hurd/m", O_READ, &target);
+ if(err)
+ error
+ (
+ EXIT_FAILURE, err,
+ "Could not trace the translator stack on the underlying node"
+ );
+
+ netfs_root_node->nn->port = target;
+
+ /*Update the timestamps of the root node*/
+ fshelp_touch
+ (&netfs_root_node->nn_stat, TOUCH_ATIME | TOUCH_MTIME | TOUCH_CTIME,
+ maptime);
+
+ LOG_MSG(">> Initialization complete. Entering netfs server loop...");
+
+ /*Start serving clients*/
+ for(;;)
+ netfs_server_loop();
+ }/*main*/
+/*----------------------------------------------------------------------------*/
diff --git a/filter.h b/filter.h
new file mode 100644
index 000000000..6dc9a69dc
--- /dev/null
+++ b/filter.h
@@ -0,0 +1,348 @@
+/*----------------------------------------------------------------------------*/
+/*filter.h*/
+/*----------------------------------------------------------------------------*/
+/*The definitions for the filtering translator*/
+/*----------------------------------------------------------------------------*/
+/*Based on the code of unionfs translator.*/
+/*----------------------------------------------------------------------------*/
+/*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc.
+ Written by Sergiu Ivanov <unlimitedscolobb@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.*/
+/*----------------------------------------------------------------------------*/
+#ifndef __FILTER_H__
+#define __FILTER_H__
+/*----------------------------------------------------------------------------*/
+#include <stddef.h>
+#include <stdlib.h>
+#include <cthreads.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/time.h>
+#include <hurd/ihash.h>
+#include <hurd/iohelp.h>
+/*----------------------------------------------------------------------------*/
+#include "node.h"
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Macros--------------------------------------------------------------*/
+/*The inode for the root node*/
+#define FILTER_ROOT_INODE 1
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Global Variables----------------------------------------------------*/
+/*A mapped time value*/
+/*Required for a very fast access to time*/
+extern volatile struct mapped_time_value * maptime;
+/*----------------------------------------------------------------------------*/
+/*A port to the underlying node*/
+extern mach_port_t underlying_node;
+/*----------------------------------------------------------------------------*/
+/*The stat information about the underlying node*/
+extern io_statbuf_t underlying_node_stat;
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Functions-----------------------------------------------------------*/
+/*Attempts to create a file named `name` in `dir` for `user` with mode `mode`*/
+error_t
+netfs_attempt_create_file
+ (
+ struct iouser * user,
+ struct node * dir,
+ char * name,
+ mode_t mode,
+ struct node ** node
+ );
+/*----------------------------------------------------------------------------*/
+/*Returns an error if the process of opening a file should not be allowed
+ to complete because of insufficient permissions*/
+error_t
+netfs_check_open_permissions
+ (
+ struct iouser * user,
+ struct node * np,
+ int flags,
+ int newnode
+ );
+/*----------------------------------------------------------------------------*/
+/*Attempts an utimes call for the user `cred` on node `node`*/
+error_t
+netfs_attempt_utimes
+ (
+ struct iouser * cred,
+ struct node * node,
+ struct timespec * atime,
+ struct timespec * mtime
+ );
+/*----------------------------------------------------------------------------*/
+/*Returns the valid access types for file `node` and user `cred`*/
+error_t
+netfs_report_access
+ (
+ struct iouser * cred,
+ struct node * np,
+ int * types
+ );
+/*----------------------------------------------------------------------------*/
+/*Validates the stat data for the node*/
+error_t
+netfs_validate_stat
+ (
+ struct node * np,
+ struct iouser * cred
+ );
+/*----------------------------------------------------------------------------*/
+/*Syncs `node` completely to disk*/
+error_t
+netfs_attempt_sync
+ (
+ struct iouser * cred,
+ struct node * node,
+ int wait
+ );
+/*----------------------------------------------------------------------------*/
+/*Fetches a directory*/
+error_t
+netfs_get_dirents
+ (
+ struct iouser * cred,
+ struct node * dir,
+ int first_entry,
+ int num_entries,
+ char ** data,
+ mach_msg_type_number_t * data_len,
+ vm_size_t max_data_len,
+ int * data_entries
+ );
+/*----------------------------------------------------------------------------*/
+/*Looks up `name` under `dir` for `user`*/
+error_t
+netfs_attempt_lookup
+ (
+ struct iouser * user,
+ struct node * dir,
+ char * name,
+ struct node ** node
+ );
+/*----------------------------------------------------------------------------*/
+/*Deletes `name` in `dir` for `user`*/
+error_t
+netfs_attempt_unlink
+ (
+ struct iouser * user,
+ struct node * dir,
+ char * name
+ );
+/*----------------------------------------------------------------------------*/
+/*Attempts to rename `fromdir`/`fromname` to `todir`/`toname`*/
+error_t
+netfs_attempt_rename
+ (
+ struct iouser * user,
+ struct node * fromdir,
+ char * fromname,
+ struct node * todir,
+ char * toname,
+ int excl
+ );
+/*----------------------------------------------------------------------------*/
+/*Attempts to create a new directory*/
+error_t
+netfs_attempt_mkdir
+ (
+ struct iouser * user,
+ struct node * dir,
+ char * name,
+ mode_t mode
+ );
+/*----------------------------------------------------------------------------*/
+/*Attempts to remove directory `name` in `dir` for `user`*/
+error_t
+netfs_attempt_rmdir
+ (
+ struct iouser * user,
+ struct node * dir,
+ char * name
+ );
+/*----------------------------------------------------------------------------*/
+/*Attempts to change the owner of `node` for user `cred` to `uid`:`gid`*/
+error_t
+netfs_attempt_chown
+ (
+ struct iouser * cred,
+ struct node * node,
+ uid_t uid,
+ uid_t gid
+ );
+/*----------------------------------------------------------------------------*/
+/*Attempts to change the author of `node` to `author`*/
+error_t
+netfs_attempt_chauthor
+ (
+ struct iouser * cred,
+ struct node * node,
+ uid_t author
+ );
+/*----------------------------------------------------------------------------*/
+/*Attempts to change the mode of `node` to `mode` for `cred`*/
+error_t
+netfs_attempt_chmod
+ (
+ struct iouser * user,
+ struct node * node,
+ mode_t mode
+ );
+/*----------------------------------------------------------------------------*/
+/*Attempts to turn `node` into a symlink targetting `name`*/
+error_t
+netfs_attempt_mksymlink
+ (
+ struct iouser * cred,
+ struct node * node,
+ char * name
+ );
+/*----------------------------------------------------------------------------*/
+/*Attempts to turn `node` into a device; type can be either S_IFBLK or S_IFCHR*/
+error_t
+netfs_attempt_mkdev
+ (
+ struct iouser * cred,
+ struct node * node,
+ mode_t type,
+ dev_t indexes
+ );
+/*----------------------------------------------------------------------------*/
+/*Attempts to set the passive translator record for `file` passing `argz`*/
+error_t
+netfs_set_translator
+ (
+ struct iouser * cred,
+ struct node * node,
+ char * argz,
+ size_t arglen
+ );
+/*----------------------------------------------------------------------------*/
+/*Attempts to call chflags for `node`*/
+error_t
+netfs_attempt_chflags
+ (
+ struct iouser * cred,
+ struct node * node,
+ int flags
+ );
+/*----------------------------------------------------------------------------*/
+/*Attempts to set the size of file `node`*/
+error_t
+netfs_attempt_set_size
+ (
+ struct iouser * cred,
+ struct node * node,
+ loff_t size
+ );
+/*----------------------------------------------------------------------------*/
+/*Fetches the filesystem status information*/
+error_t
+netfs_attempt_statfs
+ (
+ struct iouser * cred,
+ struct node * node,
+ fsys_statfsbuf_t * st
+ );
+/*----------------------------------------------------------------------------*/
+/*Syncs the filesystem*/
+error_t
+netfs_attempt_syncfs
+ (
+ struct iouser * cred,
+ int wait
+ );
+/*----------------------------------------------------------------------------*/
+/*Creates a link in `dir` with `name` to `file`*/
+error_t
+netfs_attempt_link
+ (
+ struct iouser * user,
+ struct node * dir,
+ struct node * file,
+ char * name,
+ int excl
+ );
+/*----------------------------------------------------------------------------*/
+/*Attempts to create an anonymous file related to `dir` with `mode`*/
+error_t
+netfs_attempt_mkfile
+ (
+ struct iouser * user,
+ struct node * dir,
+ mode_t mode,
+ struct node ** node
+ );
+/*----------------------------------------------------------------------------*/
+/*Reads the contents of symlink `node` into `buf`*/
+error_t
+netfs_attempt_readlink
+ (
+ struct iouser * user,
+ struct node * node,
+ char * buf
+ );
+/*----------------------------------------------------------------------------*/
+/*Reads from file `node` up to `len` bytes from `offset` into `data`*/
+error_t
+netfs_attempt_read
+ (
+ struct iouser * cred,
+ struct node * np,
+ loff_t offset,
+ size_t * len,
+ void * data
+ );
+/*----------------------------------------------------------------------------*/
+/*Writes to file `node` up to `len` bytes from offset from `data`*/
+error_t
+netfs_attempt_write
+ (
+ struct iouser * cred,
+ struct node * node,
+ loff_t offset,
+ size_t * len,
+ void * data
+ );
+/*----------------------------------------------------------------------------*/
+/*Frees all storage associated with the node*/
+void
+netfs_node_norefs
+ (
+ struct node * np
+ );
+/*----------------------------------------------------------------------------*/
+/*Implements file_get_translator_cntl as described in <hurd/fs.defs>
+ (according to diskfs_S_file_get_translator_cntl)*/
+kern_return_t
+netfs_S_file_get_translator_cntl
+ (
+ struct protid * user,
+ mach_port_t * cntl,
+ mach_msg_type_name_t * cntltype
+ );
+/*----------------------------------------------------------------------------*/
+#endif /*__FILTER_H__*/
diff --git a/node.c b/node.c
new file mode 100644
index 000000000..33ff2777e
--- /dev/null
+++ b/node.c
@@ -0,0 +1,166 @@
+/*----------------------------------------------------------------------------*/
+/*node.c*/
+/*----------------------------------------------------------------------------*/
+/*Implementation of node management strategies*/
+/*----------------------------------------------------------------------------*/
+/*Based on the code of unionfs translator.*/
+/*----------------------------------------------------------------------------*/
+/*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc.
+ Written by Sergiu Ivanov <unlimitedscolobb@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.*/
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+#define _GNU_SOURCE 1
+/*----------------------------------------------------------------------------*/
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <stdio.h>
+/*----------------------------------------------------------------------------*/
+#include "debug.h"
+#include "node.h"
+#include "filter.h"
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Global Variables----------------------------------------------------*/
+/*The lock protecting the underlying filesystem*/
+struct mutex ulfs_lock = MUTEX_INITIALIZER;
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Functions-----------------------------------------------------------*/
+/*Derives a new node from `lnode` and adds a reference to `lnode`*/
+error_t
+node_create
+ (
+ node_t ** node /*store the result here*/
+ )
+ {
+ error_t err = 0;
+
+ /*Create a new netnode*/
+ netnode_t * netnode_new = malloc(sizeof(netnode_t));
+
+ /*If the memory could not be allocated*/
+ if(netnode_new == NULL)
+ err = ENOMEM;
+ else
+ {
+ /*create a new node from the netnode*/
+ node_t * node_new = netfs_make_node(netnode_new);
+
+ /*If the creation failed*/
+ if(node_new == NULL)
+ {
+ /*set the error code*/
+ err = ENOMEM;
+
+ /*destroy the netnode created above*/
+ free(netnode_new);
+
+ /*stop*/
+ return err;
+ }
+
+ /*store the result of creation in the second parameter*/
+ *node = node_new;
+ }
+
+ /*Return the result of operations*/
+ return err;
+ }/*node_create*/
+/*----------------------------------------------------------------------------*/
+/*Destroys the specified node and removes a light reference from the
+ associated light node*/
+void
+node_destroy
+ (
+ node_t * np
+ )
+ {
+ /*Destroy the port to the underlying filesystem allocated to the node*/
+ PORT_DEALLOC(np->nn->port);
+
+ /*Free the netnode and the node itself*/
+ free(np->nn);
+ free(np);
+ }/*node_destroy*/
+/*----------------------------------------------------------------------------*/
+/*Creates the root node and the corresponding lnode*/
+error_t
+node_create_root
+ (
+ node_t ** root_node /*store the result here*/
+ )
+ {
+ error_t err;
+
+ /*Try to create a node*/
+ node_t * node;
+ err = node_create(&node);
+ if(err)
+ return err;
+
+ /*Store the result in the parameter*/
+ *root_node = node;
+
+ /*Return the result*/
+ return err;
+ }/*node_create_root*/
+/*----------------------------------------------------------------------------*/
+/*Initializes the port to the underlying filesystem for the root node*/
+error_t
+node_init_root
+ (
+ mach_port_t underlying, /*the port to the underlying node*/
+ node_t * node /*the root node*/
+ )
+ {
+ error_t err = 0;
+
+ /*Acquire a lock for operations on the underlying filesystem*/
+ mutex_lock(&ulfs_lock);
+
+ /*Store the specified port in the node*/
+ node->nn->port = underlying;
+
+ LOG_MSG("node_init_root: Port: 0x%ld", (unsigned long)node->nn->port);
+
+ /*Stat the root node*/
+ err = io_stat(node->nn->port, &node->nn_stat);
+ if(err)
+ {
+ /*deallocate the port*/
+ PORT_DEALLOC(node->nn->port);
+
+ LOG_MSG("node_init_root: Could not stat the root node.");
+
+ /*unlock the mutex and exit*/
+ mutex_unlock(&ulfs_lock);
+ return err;
+ }
+
+ /*Release the lock for operations on the undelying filesystem*/
+ mutex_unlock(&ulfs_lock);
+
+ /*Return the result of operations*/
+ return err;
+ }/*node_init_root*/
+/*----------------------------------------------------------------------------*/
diff --git a/node.h b/node.h
new file mode 100644
index 000000000..c8c8945c7
--- /dev/null
+++ b/node.h
@@ -0,0 +1,114 @@
+/*----------------------------------------------------------------------------*/
+/*node.h*/
+/*----------------------------------------------------------------------------*/
+/*Node management. Also see lnode.h*/
+/*----------------------------------------------------------------------------*/
+/*Based on the code of unionfs translator.*/
+/*----------------------------------------------------------------------------*/
+/*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc.
+ Written by Sergiu Ivanov <unlimitedscolobb@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.*/
+/*----------------------------------------------------------------------------*/
+#ifndef __NODE_H__
+#define __NODE_H__
+
+/*----------------------------------------------------------------------------*/
+#include <error.h>
+#include <sys/stat.h>
+#include <hurd/netfs.h>
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Macros--------------------------------------------------------------*/
+/*Checks whether the give node is the root of the filterfs filesystem*/
+#define NODE_IS_ROOT(n) (((n)->nn->lnode->dir) ? (0) : (1))
+/*----------------------------------------------------------------------------*/
+/*Node flags*/
+#define FLAG_NODE_ULFS_FIXED 0x00000001 /*this node should not be updated*/
+#define FLAG_NODE_INVALIDATE 0x00000002 /*this node must be updated*/
+#define FLAG_NODE_ULFS_UPTODATE 0x00000004 /*this node has just been updated*/
+/*----------------------------------------------------------------------------*/
+/*The type of offset corresponding to the current platform*/
+#ifdef __USE_FILE_OFFSET64
+# define OFFSET_T __off64_t
+#else
+# define OFFSET_T __off_t
+#endif /*__USE_FILE_OFFSET64*/
+/*----------------------------------------------------------------------------*/
+/*The size of a chunk of a string (for a small optimization in checking
+ the property)*/
+#define STRING_CHUNK 256
+/*----------------------------------------------------------------------------*/
+/*Deallocates the specified port*/
+#define PORT_DEALLOC(p) (mach_port_deallocate(mach_task_self(), (p)))
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*The user-defined node for libnetfs*/
+struct netnode
+ {
+ /*the flags associated with this node (might be not required)*/
+ int flags;
+
+ /*a port to the underlying filesystem*/
+ file_t port;
+ };/*struct netnode*/
+/*----------------------------------------------------------------------------*/
+typedef struct netnode netnode_t;
+/*----------------------------------------------------------------------------*/
+typedef struct node node_t;
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Global Variables----------------------------------------------------*/
+/*The lock protecting the underlying filesystem*/
+extern struct mutex ulfs_lock;
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Functions-----------------------------------------------------------*/
+/*Derives a new node from `lnode` and adds a reference to `lnode`*/
+error_t
+node_create
+ (
+ node_t ** node /*store the result here*/
+ );
+/*----------------------------------------------------------------------------*/
+/*Destroys the specified node and removes a light reference from the
+ associated light node*/
+void
+node_destroy
+ (
+ node_t * np
+ );
+/*----------------------------------------------------------------------------*/
+/*Creates the root node and the corresponding lnode*/
+error_t
+node_create_root
+ (
+ node_t ** root_node /*store the result here*/
+ );
+/*----------------------------------------------------------------------------*/
+/*Initializes the port to the underlying filesystem for the root node*/
+error_t
+node_init_root
+ (
+ mach_port_t underlying, /*the port to the underlying node*/
+ node_t * node /*the root node*/
+ );
+/*----------------------------------------------------------------------------*/
+#endif /*__NODE_H__*/
diff --git a/options.c b/options.c
new file mode 100644
index 000000000..736a8589a
--- /dev/null
+++ b/options.c
@@ -0,0 +1,190 @@
+/*----------------------------------------------------------------------------*/
+/*options.h*/
+/*----------------------------------------------------------------------------*/
+/*Definitions for parsing the command line switches*/
+/*----------------------------------------------------------------------------*/
+/*Based on the code of unionfs translator.*/
+/*----------------------------------------------------------------------------*/
+/*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc.
+ Written by Sergiu Ivanov <unlimitedscolobb@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.*/
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+#define _GNU_SOURCE 1
+/*----------------------------------------------------------------------------*/
+#include <argp.h>
+#include <error.h>
+/*----------------------------------------------------------------------------*/
+#include "debug.h"
+#include "options.h"
+#include "node.h"
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Macros--------------------------------------------------------------*/
+/*Short documentation for argp*/
+#define ARGS_DOC ""
+#define DOC "Filters the translator stack of the node it is set upon."
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Forward Declarations------------------------------------------------*/
+/*Argp parser function for the common options*/
+static
+error_t
+argp_parse_common_options
+ (
+ int key,
+ char * arg,
+ struct argp_state * state
+ );
+/*----------------------------------------------------------------------------*/
+/*Argp parser function for the startup options*/
+static
+error_t
+argp_parse_startup_options
+ (
+ int key,
+ char * arg,
+ struct argp_state * state
+ );
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Global Variables----------------------------------------------------*/
+/*This variable is set to a non-zero value after the parsing of starup options
+ is finished*/
+static int parsing_startup_options_finished;
+/*----------------------------------------------------------------------------*/
+/*Argp options common to both the runtime and the startup parser*/
+static const struct argp_option argp_common_options[] =
+ {
+ {0}
+ };
+/*----------------------------------------------------------------------------*/
+/*Argp options only meaningful for startupp parsing*/
+static const struct argp_option argp_startup_options[] =
+ {
+ {0}
+ };
+/*----------------------------------------------------------------------------*/
+/*Argp parser for only the common options*/
+static const struct argp argp_parser_common_options =
+ {argp_common_options, argp_parse_common_options, 0, 0, 0};
+/*----------------------------------------------------------------------------*/
+/*Argp parser for only the startup options*/
+static const struct argp argp_parser_startup_options =
+ {argp_startup_options, argp_parse_startup_options, 0, 0, 0};
+/*----------------------------------------------------------------------------*/
+/*The list of children parsers for runtime arguments*/
+static const struct argp_child argp_children_runtime[] =
+ {
+ {&argp_parser_common_options},
+ {&netfs_std_runtime_argp},
+ {0}
+ };
+/*----------------------------------------------------------------------------*/
+/*The list of children parsers for startup arguments*/
+static const struct argp_child argp_children_startup[] =
+ {
+ {&argp_parser_startup_options},
+ {&argp_parser_common_options},
+ {&netfs_std_startup_argp},
+ {0}
+ };
+/*----------------------------------------------------------------------------*/
+/*The version of the server for argp*/
+const char * argp_program_version = "0.0";
+/*----------------------------------------------------------------------------*/
+/*The arpg parser for runtime arguments*/
+struct argp argp_runtime =
+ {0, 0, 0, 0, argp_children_runtime};
+/*----------------------------------------------------------------------------*/
+/*The argp parser for startup arguments*/
+struct argp argp_startup =
+ {0, 0, ARGS_DOC, DOC, argp_children_startup};
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Functions-----------------------------------------------------------*/
+/*Argp parser function for the common options*/
+static
+error_t
+argp_parse_common_options
+ (
+ int key,
+ char * arg,
+ struct argp_state * state
+ )
+ {
+ error_t err = 0;
+
+ /*Go through the possible options*/
+ switch(key)
+ {
+ case ARGP_KEY_END:
+ {
+ /*If parsing of startup options has not finished*/
+ if(!parsing_startup_options_finished)
+ {
+ /*set the flag that the startup options have already been parsed*/
+ parsing_startup_options_finished = 1;
+ }
+ else
+ {
+/*TODO: Take care of runtime calls modifying the property*/
+ }
+ }
+ /*If the option could not be recognized*/
+ default:
+ {
+ /*set the error code*/
+ err = ARGP_ERR_UNKNOWN;
+ }
+ }
+
+ /*Return the result*/
+ return err;
+ }/*argp_parse_common_options*/
+/*----------------------------------------------------------------------------*/
+/*Argp parser function for the startup options*/
+static
+error_t
+argp_parse_startup_options
+ (
+ int key,
+ char * arg,
+ struct argp_state * state
+ )
+ {
+ /*Do nothing in a beautiful way*/
+ error_t err = 0;
+
+ switch(key)
+ {
+ default:
+ {
+ err = ARGP_ERR_UNKNOWN;
+
+ break;
+ }
+ }
+
+ return err;
+ }/*argp_parse_startup_options*/
+/*----------------------------------------------------------------------------*/
diff --git a/options.h b/options.h
new file mode 100644
index 000000000..1db2f655f
--- /dev/null
+++ b/options.h
@@ -0,0 +1,44 @@
+/*----------------------------------------------------------------------------*/
+/*options.h*/
+/*----------------------------------------------------------------------------*/
+/*Declarations for parsing the command line switches*/
+/*----------------------------------------------------------------------------*/
+/*Based on the code of unionfs translator.*/
+/*----------------------------------------------------------------------------*/
+/*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc.
+ Written by Sergiu Ivanov <unlimitedscolobb@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.*/
+/*----------------------------------------------------------------------------*/
+#ifndef __OPTIONS_H__
+#define __OPTIONS_H__
+
+/*----------------------------------------------------------------------------*/
+/*--------Macros--------------------------------------------------------------*/
+/*Makes a long option out of option name*/
+#define OPT_LONG(o) "--"o
+/*----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*--------Global Variables----------------------------------------------------*/
+/*The argp parser for startup arguments*/
+extern struct argp argp_startup;
+/*----------------------------------------------------------------------------*/
+/*The argp parser for rutime arguments*/
+extern struct argp argp_runtime;
+/*----------------------------------------------------------------------------*/
+#endif /*__OPTIONS_H__*/