[OpenAFS-devel] 'up' patch for preserving mountpoints

Todd M. Lewis Todd_Lewis@unc.edu
Mon, 18 Jun 2001 08:45:06 -0400


This is a multi-part message in MIME format.
--------------4C36B612CAAD4FA2EE8C9FED
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

The 'up' command (venus/up.c) is like a recursive copy that knows about
and copies ACLs as well as files. Unfortunately, it doesn't know about
mount points. That may account for its unusual name -- up has the side
effect of copying the files in and below its source volume(s) "up" into
its target's volume.

The attached patch adds a "-m" option to up which makes it recognize and
copy mount points rather than traversing them during its recursive copy
operation. Without the -m option, up's default (questionable) behavior
remains unchanged.
-- 
   +------------------------------------------------------------+
  / Todd_Lewis@unc.edu              http://www.unc.edu/~utoddl /
 /(919) 962-5273     Official Signature of the New Millennium /
+------------------------------------------------------------+
--------------4C36B612CAAD4FA2EE8C9FED
Content-Type: text/plain; charset=us-ascii;
 name="up.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="up.patch"

--- venus/up.c-orig	Wed May 23 13:13:59 2001
+++ venus/up.c	Mon Jun 18 08:22:55 2001
@@ -21,6 +21,7 @@
 #undef	_NONSTD_TYPES
 #endif
 #include <stdio.h>
+#include <afs/afs_args.h>
 #include <sys/param.h>
 #ifdef	AFS_SUN5_ENV
 #include <fcntl.h>
@@ -35,6 +36,9 @@
 #include <afs/vice.h>
 #undef VIRTUE
 #undef VICE
+#include <sys/ioctl.h>
+#include <netdb.h>      
+#include <afs/venus.h>
 
 /* ************************************************************* */
 
@@ -51,6 +55,7 @@
 Boolean   renameTargets = false;
 Boolean   oneLevel = false;
 Boolean   preserveDate = true;	
+Boolean   preserveMountPoints = false;
 Boolean   forceOverwrite = false;
 
 int   pageSize;
@@ -58,6 +63,9 @@
 Boolean oldAcl = false;
 char file1[MAXPATHLEN], file2[MAXPATHLEN];
 
+#define	MAXSIZE	2048
+static char space[MAXSIZE];
+
 struct OldAcl {
     int nplus;
     int nminus;
@@ -138,9 +146,13 @@
 	    preserveDate = false;
 	    break;
 	    
+	  case 'm':
+	    preserveMountPoints = true;
+	    break;
+	    
 	  default: 
 	    fprintf(stderr, "Unknown option: '%c'\n", *cp);
-	    fprintf(stderr, "usage: up [-v1frx] from to\n");
+	    fprintf(stderr, "usage: up [-v1frxm] from to\n");
 	    exit(1);
 	}
 	argc--, argv++;
@@ -151,8 +163,8 @@
         exit(1);
     }
 
-    strcpy(file1, argv[0]);
-    strcpy(file2, argv[1]);
+    strncpy(file1, argv[0], MAXPATHLEN);
+    strncpy(file2, argv[1], MAXPATHLEN);
 
 } /*ScanArgs*/
 
@@ -437,6 +449,45 @@
 	  return 1;
        }
     } /*Dealing with symlink*/
+    
+    else if ( preserveMountPoints && (code=isMountPoint( file1, &blob )) ) {
+       /*
+	* --------------------- Copy mount point  --------------------
+	*/
+
+       if ( code > 1 ) {
+          perror("checking for mount point ");
+          return 1;
+       }
+       if (verbose) {
+	  printf("Level %d: Mount point %s to %s\n", level, file1, file2);
+	  fflush(stdout);
+       }
+       
+       /* Don't ovewrite a write protected directory (unless force: -f) */
+       if (!forceOverwrite && goods2 && (s2.st_mode & 0200) == 0) {
+	  fprintf(stderr,
+		  "Target %s is write protected against its owner; not changed\n",
+		  file2);
+	  return 1;
+       }
+       
+       if (verbose) {
+	  printf("  Copy mount point %s for vol %s to %s\n", file1, blob.out, file2);
+	  fflush(stdout);
+       }
+       
+       unlink(file2);	/* Always make the new link (it was easier) */
+
+       strcat(blob.out, ".");		/* stupid convention; these end with a period */
+       code = symlink(blob.out, file2);
+       if (code == -1) {
+	  fprintf(stderr, "Could not create mount point %s for vol %s\n", file2, blob.out);
+	  perror("create mount point ");
+	  return 1;
+       }
+	
+    } /*Dealing with mount point*/
 
     else if (((s1.st_mode & S_IFMT) == S_IFDIR) && (recursive || (level == 0))) {
        /*
@@ -610,3 +661,75 @@
 
     return rcode;
 } /*Copy*/
+
+
+int isMountPoint( name, blob )
+    char *name;
+    struct ViceIoctl *blob;
+{
+    afs_int32  code;
+    char true_name[1024];		/*dirname*/
+    char parent_dir[1024];		/*Parent directory of true name*/
+    char *last_component;		/*Last component of true name*/
+
+    sprintf(true_name, "%s%s",
+            (name[0] == '/') ? "" : "./",
+            name);
+
+    /*
+     * Find rightmost slash, if any.
+     */
+    last_component = (char *) rindex(true_name, '/');
+    if (last_component) {
+        /*
+         * Found it.  Designate everything before it as the parent directory,
+         * everything after it as the final component.
+         */
+        strncpy(parent_dir, true_name, last_component - true_name);
+        parent_dir[last_component - true_name] = 0;
+        last_component++;   /*Skip the slash*/
+    }
+    else {
+        /*
+         * No slash appears in the given file name.  Set parent_dir to the current
+         * directory, and the last component as the given name.
+         */
+        strcpy(parent_dir, ".");
+        last_component = true_name;
+    }
+
+    if (strcmp(last_component, ".") == 0 || strcmp(last_component, "..") == 0) {
+        fprintf(stderr, "up: you may not use '.' or '..' as the last component\n");
+        fprintf(stderr, "up: of a name in the 'up' command.\n");
+        return 3;
+    }
+
+    blob->in = last_component;
+    blob->in_size = strlen(last_component)+1;
+    blob->out_size = MAXSIZE;
+    blob->out = space;
+    bzero(space, MAXSIZE);
+
+    code = pioctl(parent_dir, VIOC_AFS_STAT_MT_PT, blob, 0);
+
+    if (code == 0) {
+        printf("'%s' is a mount point for volume '%s'\n", name, space);
+        fflush(stdout);
+        return 1;
+    }
+    else {
+        if (errno == EINVAL) {
+            /* printf( "'%s' is not a mount point.\n", name);
+	     * fflush(stdout);
+	     */
+            return 0;
+        }
+        else {
+            fprintf( stderr, "problem examining '%s' in '%s'.\n", last_component, parent_dir );
+            return 2;
+            /* Die(errno, (ti->data ? ti->data : parent_dir));
+             */
+        }
+    }
+    return 4;
+}

--------------4C36B612CAAD4FA2EE8C9FED--