bug-hurd
[Top][All Lists]
Advanced

[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;
 }
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]