Hi, This firmlink patch should conform to the GCS, and the time mode works nicely.
2002-03-09 James A. Morrison <[EMAIL PROTECTED]> * 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 <[EMAIL PROTECTED]> + Extended by James A. Morrison <[EMAIL PROTECTED]> 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; } _______________________________________________ Bug-hurd mailing list [EMAIL PROTECTED] http://mail.gnu.org/mailman/listinfo/bug-hurd