[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
firmlink/filemux patch
From: |
James A Morrison |
Subject: |
firmlink/filemux patch |
Date: |
Sun, 24 Feb 2002 11:55:12 -0500 (EST) |
Hi, here is my lastest multiple firmlink translator, as a patch to
the official firmlink source. This is also available from
http://hurd.dyndns.org/tarballs/filemux-0.2.0.tar.gz
The old invocation of firmlink still works the same, but directly reading
a firmlink has changed.
2002-02-24 James A. Morrison <ja2morri@uwaterloo.ca>
* firmlink.c: Added support for multiple targets by choice of
date format, random selection, or sequencial selection
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 24 Feb 2002 16:39:54 -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,20 +27,29 @@
#include <fcntl.h>
#include <argp.h>
#include <error.h>
+#include <time.h>
#include <sys/mman.h>
#include <hurd/trivfs.h>
-#include <version.h>
+#include <version.h>
+
+#define RANDOM_MODE 1
+#define TIME_MODE 0
+#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 args_doc[] = "[file1 file2 ...]";
static const char doc[] = "A translator for firmlinks."
"\vA firmlink is sort of half-way between a symbolic link and a hard link:"
"\n"
@@ -50,18 +60,54 @@
" firmlink is looked up in the namespace of the translator, not the client.";
/* 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
+ 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 +120,12 @@
mach_port_t bootstrap;
struct trivfs_control *fsys;
+ config.size = 0;
+ config.type = RANDOM_MODE;
+ config.args = (char**)malloc(argc);
/* 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 +152,21 @@
{
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 ( config.type == TIME_MODE && errno == ENOENT ) {
+ 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 +195,40 @@
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 +240,13 @@
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 +270,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 +318,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 +330,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 +355,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] |
- firmlink/filemux patch,
James A Morrison <=