up-preserve-dir-mtime-20070507
[openafs.git] / src / venus / up.c
index 957ec0e..2dee7cf 100644 (file)
@@ -14,9 +14,6 @@ RCSID
     ("$Header$");
 
 /* missing type from C language */
-#define Boolean short
-#define true 1
-#define false 0
 
 #include <errno.h>
 #ifdef AFS_AIX32_ENV
@@ -59,21 +56,16 @@ RCSID
 
 #define MAXACL 400
 
-#if !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
-extern sys_nerr;
-extern char *sys_errlist[];
-#endif
-
-Boolean verbose = false;
-Boolean renameTargets = false;
-Boolean oneLevel = false;
-Boolean preserveDate = true;
-Boolean preserveMountPoints = false;
-Boolean forceOverwrite = false;
+short verbose = 0;
+short renameTargets = 0;
+short oneLevel = 0;
+short preserveDate = 1;
+short preserveMountPoints = 0;
+short forceOverwrite = 0;
 
 int pageSize;
-Boolean setacl = true;
-Boolean oldAcl = false;
+short setacl = 1;
+short oldAcl = 0;
 char file1[MAXPATHLEN], file2[MAXPATHLEN];
 
 #define        MAXSIZE 2048
@@ -86,6 +78,12 @@ struct OldAcl {
     char data[1];
 };
 
+static void ScanArgs(int argc, char *argv[]);
+static short MakeParent(char *file, afs_int32 owner);
+static int Copy(char *file1, char *file2, short recursive, int level);
+static int isMountPoint(char *name, struct ViceIoctl *blob);
+
+
 /* ************************************************************ */
 /*                                                              */
 /* main program                                                         */
@@ -94,10 +92,8 @@ struct OldAcl {
 
 #include "AFS_component_version_number.c"
 
-main(argc, argv)
-     int argc;
-     char *argv[];
-
+int
+main(int argc, char *argv[])
 {
 #ifdef AFS_AIX32_ENV
     /*
@@ -120,16 +116,15 @@ main(argc, argv)
 
     /* now read each line of the CopyList */
     if (Copy(file1, file2, !oneLevel, 0))
-       exit(1);                /* some type of failure */
+       return(1);              /* some type of failure */
 
-    exit(0);
+    return(0);
 }
 
 
-ScanArgs(argc, argv)
-     int argc;
-     char *argv[];
-
+#define USAGE "usage: up [-v1frxm] from to\n"
+static void
+ScanArgs(int argc, char *argv[])
 {
     /* skip program name */
     argc--, argv++;
@@ -140,39 +135,39 @@ ScanArgs(argc, argv)
 
        switch (*++cp) {
        case 'v':
-           verbose = true;
+           verbose = 1;
            break;
 
        case '1':
-           oneLevel = true;
+           oneLevel = 1;
            break;
 
        case 'r':
-           renameTargets = true;
+           renameTargets = 1;
            break;
 
        case 'f':
-           forceOverwrite = true;
+           forceOverwrite = 1;
            break;
 
        case 'x':
-           preserveDate = false;
+           preserveDate = 0;
            break;
 
        case 'm':
-           preserveMountPoints = true;
+           preserveMountPoints = 1;
            break;
 
        default:
            fprintf(stderr, "Unknown option: '%c'\n", *cp);
-           fprintf(stderr, "usage: up [-v1frxm] from to\n");
+           fprintf(stderr, USAGE);
            exit(1);
        }
        argc--, argv++;
     }
 
     if (argc != 2) {
-       fprintf(stderr, "usage: up [-v1frx] from to\n");
+       fprintf(stderr, USAGE);
        exit(1);
     }
 
@@ -186,23 +181,21 @@ ScanArgs(argc, argv)
 /*
  * MakeParent
  *     Make sure the parent directory of this file exists.  Returns
- *     true if it exists, false otherwise.  Note: the owner argument
+ *     1 if it exists, 0 otherwise.  Note: the owner argument
  *     is a hack.  All directories made will have this owner.
  */
-Boolean
-MakeParent(file, owner)
-     char *file;
-     afs_int32 owner;
+static short
+MakeParent(char *file, afs_int32 owner)
 {
     char parent[MAXPATHLEN];
     char *p;
     struct stat s;
 
-    strcpy(parent, file);
+    strlcpy(parent, file, sizeof parent);
 
     p = strrchr(parent, '/');
     if (!p) {
-       strcpy(parent, ".");
+       strlcpy(parent, ".", sizeof parent);
     } else if (p > parent) {
        *p = '\0';
     } else {
@@ -211,7 +204,7 @@ MakeParent(file, owner)
 
     if (stat(parent, &s) < 0) {
        if (!MakeParent(parent, owner))
-           return (false);
+           return (0);
 
        if (verbose) {
            printf("Creating directory %s\n", parent);
@@ -221,7 +214,7 @@ MakeParent(file, owner)
        mkdir(parent, 0777);
        chown(parent, owner, -1);
     }
-    return (true);
+    return (1);
 }                              /*MakeParent */
 
 
@@ -230,12 +223,8 @@ MakeParent(file, owner)
  *     This does the bulk of the work of the program.  Handle one file,
  *     possibly copying subfiles if this is a directory
  */
-Copy(file1, file2, recursive, level)
-     char *file1;              /* input file name */
-     char *file2;              /* output file name */
-     Boolean recursive;                /* true if directory should be copied */
-     int level;                        /* level of recursion: 0, 1, ... */
-
+static int
+Copy(char *file1, char *file2, short recursive, int level)
 {
     struct stat s1, s2;                /*Stat blocks */
     struct ViceIoctl blob;
@@ -293,28 +282,22 @@ Copy(file1, file2, recursive, level)
                fflush(stdout);
            }
 
-           strcpy(tmpfile, file2);     /* Name of temporary file */
-           strcat(tmpfile, ".UPD");
+           strlcpy(tmpfile, file2, sizeof tmpfile);    /* Name of temporary file */
+           strlcat(tmpfile, ".UPD", sizeof tmpfile);
 
            /* open file1 for input */
            f1 = open(file1, O_RDONLY);
            if (f1 < 0) {
-               fprintf(stderr, "Unable to open input file %s, ", file1);
-               if (errno >= sys_nerr)
-                   fprintf(stderr, "error code = %d\n", errno);
-               else
-                   fprintf(stderr, "%s\n", sys_errlist[errno]);
+               fprintf(stderr, "Unable to open input file %s: %s\n",
+                       file1, strerror(errno));
                return 1;
            }
 
            /* open temporary output file */
            f2 = open(tmpfile, (O_WRONLY | O_CREAT | O_TRUNC), s1.st_mode);
            if (f2 < 0) {
-               fprintf(stderr, "Unable to open output file %s, ", tmpfile);
-               if (errno >= sys_nerr)
-                   fprintf(stderr, "error code = %d\n", errno);
-               else
-                   fprintf(stderr, "%s\n", sys_errlist[errno]);
+               fprintf(stderr, "Unable to open output file %s: %s\n",
+                       tmpfile, strerror(errno));
                fflush(stdout);
                close(f1);
                return 1;
@@ -348,8 +331,8 @@ Copy(file1, file2, recursive, level)
 
            /* Rename file2 to file2.old. [-r] */
            if (renameTargets && goods2) {
-               strcpy(newName, file2);
-               strcat(newName, ".old");
+               strlcpy(newName, file2, sizeof newName);
+               strlcat(newName, ".old", sizeof newName);
                if (verbose) {
                    printf("  Renaming %s to %s\n", file2, newName);
                    fflush(stdout);
@@ -528,6 +511,7 @@ Copy(file1, file2, recursive, level)
        char f1[MAXPATHLEN], f2[MAXPATHLEN];
        char *p1, *p2;
        struct dirent *d;
+       struct timeval tv[2];
 
        if (verbose) {
            printf("Level %d: Directory %s to %s\n", level, file1, file2);
@@ -542,8 +526,8 @@ Copy(file1, file2, recursive, level)
            return 1;
        }
 
-       strcpy(f1, file1);
-       strcpy(f2, file2);
+       strlcpy(f1, file1, sizeof f1);
+       strlcpy(f2, file2, sizeof f2);
        p1 = f1 + strlen(f1);
        p2 = f2 + strlen(f2);
        if (p1 == f1 || p1[-1] != '/')
@@ -560,8 +544,8 @@ Copy(file1, file2, recursive, level)
        while ((d = readdir(dir)) != NULL) {
            if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0)
                continue;
-           strcpy(p1, d->d_name);
-           strcpy(p2, d->d_name);
+           strlcpy(p1, d->d_name, sizeof f1 - (p1 - f1));
+           strlcpy(p2, d->d_name, sizeof f2 - (p2 - f2));
            code = Copy(f1, f2, recursive, level + 1);
            if (code && !rcode)
                rcode = 1;      /* remember errors */
@@ -614,7 +598,7 @@ Copy(file1, file2, recursive, level)
            rcode = 1;
        }
 
-       if (setacl == true) {
+       if (setacl == 1) {
            if (verbose) {
                printf("  Set acls for %s\n", file2);
                fflush(stdout);
@@ -635,7 +619,7 @@ Copy(file1, file2, recursive, level)
                for (i = 1; i < strlen(file1); i++)
                    if (file1[i] == '/')
                        break;
-               strcpy(aclspace, &file1[i]);
+               strlcpy(aclspace, &file1[i], sizeof aclspace);
 
                blob.in_size = 1 + strlen(aclspace);
                tfd = open(file1, O_RDONLY, 0);
@@ -647,7 +631,7 @@ Copy(file1, file2, recursive, level)
                close(tfd);
                if (code < 0) {
                    if (errno == EINVAL) {
-                       setacl = false;
+                       setacl = 0;
                         if (verbose) {
                             printf("  _VICEIOCTL(4) returns EINVAL\n");
                             fflush(stdout);
@@ -659,8 +643,8 @@ Copy(file1, file2, recursive, level)
                /* Now convert the thing. */
                oacl = (struct OldAcl *)(aclspace + 4);
                sprintf(tacl, "%d\n%d\n", oacl->nplus, oacl->nminus);
-               strcat(tacl, oacl->data);
-               strcpy(aclspace, tacl);
+               strlcat(tacl, oacl->data, sizeof tacl);
+               strlcpy(aclspace, tacl, sizeof aclspace);
            } /*Grab and convert old-style ACL */
            else {
                /* Get a new-style ACL */
@@ -672,7 +656,7 @@ Copy(file1, file2, recursive, level)
                code = pioctl(file1, _VICEIOCTL(2), &blob, 1);
                if (code < 0) {
                    if (errno == EINVAL) {
-                       setacl = false;
+                       setacl = 0;
                         if (verbose) {
                             printf("  _VICEIOCTL(2) returns EINVAL\n");
                             fflush(stdout);
@@ -687,7 +671,7 @@ Copy(file1, file2, recursive, level)
            /*
             * Now, set the new-style ACL.
             */
-           if (setacl == true) {
+           if (setacl == 1) {
                 if (verbose) {
                     printf("  Setting new style acl\n");
                     fflush(stdout);
@@ -699,7 +683,7 @@ Copy(file1, file2, recursive, level)
                code = pioctl(file2, _VICEIOCTL(1), &blob, 1);
                if (code) {
                    if (errno == EINVAL) {
-                       setacl = false;
+                       setacl = 0;
                         if (verbose) {
                             printf("  _VICEIOCTL(1) returns EINVAL\n");
                             fflush(stdout);
@@ -711,20 +695,27 @@ Copy(file1, file2, recursive, level)
                }
            }
 
-           if (setacl == false) {
+           if (setacl == 0) {
                printf("Not setting acls\n");
            }
        }
+
+        /* preserve access and modification times: ("-x" disables) */
+        if (preserveDate) {
+            tv[0].tv_sec = s1.st_atime;
+            tv[0].tv_usec = 0;
+            tv[1].tv_sec = s1.st_mtime;
+            tv[1].tv_usec = 0;
+            utimes(file2, tv);
+        }
     }
 
     return rcode;
 }                              /*Copy */
 
 
-int
-isMountPoint(name, blob)
-     char *name;
-     struct ViceIoctl *blob;
+static int
+isMountPoint(char *name, struct ViceIoctl *blob)
 {
     afs_int32 code;
     char true_name[1024];      /*dirname */
@@ -750,7 +741,7 @@ isMountPoint(name, blob)
         * 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, ".");
+       strlcpy(parent_dir, ".", sizeof parent_dir);
        last_component = true_name;
     }