[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
multiple firmlinks
From: |
James A Morrison |
Subject: |
multiple firmlinks |
Date: |
Sat, 9 Mar 2002 17:50:52 -0500 (EST) |
Hi,
This firmlink patch should conform to the GCS, and the time mode works
nicely.
2002-03-09 James A. Morrison <ja2morri@uwaterloo.ca>
* firmlink.c: Added the functionality for multiple targets decided
on by a command line option choosing randomly, sequencially, or
based on the date/time.
Index: firmlink.c
===================================================================
RCS file: /cvsroot/hurd/hurd/trans/firmlink.c,v
retrieving revision 1.12
diff -u -r1.12 firmlink.c
--- firmlink.c 26 Feb 2001 04:16:01 -0000 1.12
+++ firmlink.c 9 Mar 2002 21:41:03 -0000
@@ -1,8 +1,9 @@
/* A translator for `firmlinks'
- Copyright (C) 1997, 1998, 1999, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.ai.mit.edu>
+ Extended by James A. Morrison <ja2morri@uwaterloo.ca>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -26,42 +27,91 @@
#include <fcntl.h>
#include <argp.h>
#include <error.h>
+#include <time.h>
#include <sys/mman.h>
#include <hurd/trivfs.h>
#include <version.h>
+#define TIME_MODE 0
+#define RANDOM_MODE 1
+#define SEQUENCE_MODE 2
+
const char *argp_program_version = STANDARD_HURD_VERSION (firmlink);
static const struct argp_option options[] =
{
+ {"randomized", 'r', NULL, 0, "Randomize selection of files, default" },
+ {"sequencial", 's', NULL, 0, "Choose files sequencially" },
+ {"format",'f',"DATE FORMAT", 0,
+ "Create files named file1/file2.DATE FORMAT"},
{ 0 }
};
-static const char args_doc[] = "TARGET";
-static const char doc[] = "A translator for firmlinks."
+static const char args_doc[] = "[file1 file2 ...]";
+static const char doc[] = "A translator for multiple firmlinks."
"\vA firmlink is sort of half-way between a symbolic link and a hard link:"
"\n"
"\nLike a symbolic link, it is `by name', and contains no actual reference to"
" the target. However, the lookup returns a node which will redirect parent"
" lookups so that attempts to find the cwd that go through the link will"
" reflect the link name, not the target name. The target referenced by the"
-" firmlink is looked up in the namespace of the translator, not the client.";
+" firmlink is looked up in the namespace of the translator, not the client."
+" A multiple firmlink can point to more than one file, and can also create"
+" files based on dates.";
/* Link parameters. */
-static char *target = 0; /* What we translate too. */
+
+struct arg_struct
+{
+ char **args;
+ char *date_format;
+ int type;
+ int flags;
+ unsigned long lastused;
+ unsigned long size;
+};
+
+struct arg_struct config;
/* Parse a single option/argument. */
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
- if (key == ARGP_KEY_ARG && state->arg_num == 0)
- target = arg;
- else if (key == ARGP_KEY_ARG || key == ARGP_KEY_NO_ARGS)
- argp_usage (state);
- else
- return ARGP_ERR_UNKNOWN;
+ struct arg_struct *arguments = state->input;
+
+ switch (key)
+ {
+ case 'r':
+ arguments->type = RANDOM_MODE;
+ arguments->flags = O_CREAT;
+ break;
+ case 's':
+ arguments->type = SEQUENCE_MODE;
+ arguments->flags = O_CREAT;
+ arguments->lastused = 0;
+ break;
+ case 'f':
+ arguments->type = TIME_MODE;
+ arguments->date_format = arg;
+ arguments->flags = 0;
+ break;
+ case ARGP_KEY_ARG:
+ arguments->args[arguments->size] = arg;
+ arguments->size++;
+ break;
+ case ARGP_KEY_END:
+ if ( arguments->type == TIME_MODE && arguments->size != 2 )
+ argp_usage (state);
+ break;
+ case ARGP_KEY_NO_ARGS:
+ argp_usage (state);
+ break;
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+
return 0;
}
@@ -74,8 +124,16 @@
mach_port_t bootstrap;
struct trivfs_control *fsys;
+ config.size = 0;
+ config.type = RANDOM_MODE;
+ config.args = (char**) malloc (argc);
+ if (! config.args)
+ error (ENOMEM, 1, "Starting up");
+
/* Parse our options... */
- argp_parse (&argp, argc, argv, 0, 0, 0);
+ argp_parse (&argp, argc, argv, 0, 0, &config);
+ if ( config.type == RANDOM_MODE )
+ srand (time (NULL) );
task_get_bootstrap_port (mach_task_self (), &bootstrap);
if (bootstrap == MACH_PORT_NULL)
@@ -102,7 +160,26 @@
{
error_t err;
file_t authed_link;
- file_t target = file_name_lookup (target_name, flags & ~O_CREAT, 0);
+ file_t target = file_name_lookup (target_name, flags & ~config.flags, 0);
+
+ /* if the file doesn't exist for TIME_MODE, create it */
+ if ( target == MACH_PORT_NULL /* did the lookup fail? */
+ && config.type == TIME_MODE /* Are we in a mode to create files? */
+ && errno == ENOENT ) /* Did we fail because the file doesn't exist */
+ {
+ file_t file;
+ char *filename;
+
+ file_t dir = file_name_split (target_name, &filename);
+ if (dir == MACH_PORT_NULL)
+ return errno;
+
+ dir_mkfile (dir, flags, 0666 & ~getumask () , &file);
+ dir_link (dir, file, filename, 0);
+
+ target = file;
+ mach_port_deallocate (mach_task_self(), dir);
+ }
if (target == MACH_PORT_NULL)
return errno;
@@ -131,6 +208,48 @@
int trivfs_allow_open = O_READ;
+/* choose a filename based on arguments->type and arguments->args.
+ The returned string is allocated within choose_filename and must
+ by the caller of choose_filename.
+
+ On error NULL is returned and errno is set appropriatly.
+*/
+char *
+choose_filename (struct arg_struct *arguments)
+{
+
+ char *target;
+ if ( arguments->type == TIME_MODE )
+ {
+ char buf[256];
+ time_t curtime;
+ struct tm loctime;
+ error_t err;
+
+ curtime = time (NULL);
+ localtime_r (&curtime, &loctime);
+ if (! strftime (buf, 256, arguments->date_format, &loctime) )
+ error (errno, errno, "formatting time");
+
+ err = asprintf (&target, "%s/%s.%s", arguments->args[0],
+ arguments->args[1], buf);
+ if ( err < 0 )
+ target = NULL;
+ }
+
+ if ( arguments->type == SEQUENCE_MODE )
+ {
+ target = strdup (arguments->args[arguments->lastused % arguments->size]);
+ if ( target )
+ arguments->lastused++;
+ }
+
+ if ( arguments->type == RANDOM_MODE )
+ {
+ target = strdup (arguments->args[rand () % arguments->size]);
+ }
+ return target;
+}
/* Return the root node of our file system: A firmlink to TARGET, unless
TARGET doesn't exist, in which case we return a symlink-like node. */
static error_t
@@ -142,7 +261,14 @@
retry_type *do_retry, char *retry_name,
mach_port_t *node, mach_msg_type_name_t *node_type)
{
- error_t err = firmlink (dotdot, target, flags, node);
+
+ error_t err;
+ char *target = choose_filename (&config);
+ if ( target == NULL )
+ return errno;
+
+ err = firmlink (dotdot, target, flags, node);
+ free(target);
if (err == ENOENT)
/* No target? Act like a link. */
@@ -166,7 +292,7 @@
void
trivfs_modify_stat (struct trivfs_protid *cred, struct stat *st)
{
- st->st_size = strlen (target);
+ st->st_size = config.size; /* strlen (target); */
st->st_blocks = 0;
st->st_mode &= ~S_IFMT;
st->st_mode |= S_IFLNK;
@@ -214,7 +340,7 @@
err = EBADF;
else
{
- off_t max = strlen (target);
+ off_t max = config.size; /* strlen (target); */
off_t start = offs >= 0 ? offs : (off_t)cred->po->hook;
if (start < 0)
return EINVAL;
@@ -226,7 +352,7 @@
err = (*data == -1) ? errno : 0;
if (!err && amount > 0)
{
- memcpy ((char *)(*data + start), target, amount);
+ memcpy ((char *)(*data + start), config.args, amount);
if (offs < 0)
cred->po->hook = (void *)(start + amount); /* Update PO offset. */
}
@@ -251,7 +377,7 @@
else if ((off_t)cred->po->hook < 0)
return EINVAL;
else
- *amount = strlen (target) - (off_t)cred->po->hook;
+ *amount = config.size - (off_t)cred->po->hook;
return 0;
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- multiple firmlinks,
James A Morrison <=