Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.sbin/sup/source Add a canonicalize option to avoid disas...



details:   https://anonhg.NetBSD.org/src/rev/d123ae48b682
branches:  trunk
changeset: 769755:d123ae48b682
user:      christos <christos%NetBSD.org@localhost>
date:      Wed Sep 21 19:34:54 2011 +0000

description:
Add a canonicalize option to avoid disaster when one converts directories
to symlinks in the tree and back. This option is expensive, it could be
made better by cacheing, but not now.

diffstat:

 usr.sbin/sup/source/sup.1       |  16 +++++++-
 usr.sbin/sup/source/supcdefs.h  |   3 +-
 usr.sbin/sup/source/supcmain.c  |   7 ++-
 usr.sbin/sup/source/supcmeat.c  |  79 +++++++++++++++++++++++++++++++++++++++-
 usr.sbin/sup/source/supcparse.c |  10 +++-
 5 files changed, 104 insertions(+), 11 deletions(-)

diffs (242 lines):

diff -r 447f94e06d11 -r d123ae48b682 usr.sbin/sup/source/sup.1
--- a/usr.sbin/sup/source/sup.1 Wed Sep 21 19:32:59 2011 +0000
+++ b/usr.sbin/sup/source/sup.1 Wed Sep 21 19:34:54 2011 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: sup.1,v 1.18 2009/11/02 00:29:04 joerg Exp $
+.\"    $NetBSD: sup.1,v 1.19 2011/09/21 19:34:54 christos Exp $
 .\"
 .\" Copyright (c) 1992 Carnegie Mellon University
 .\" All Rights Reserved.
@@ -197,6 +197,16 @@
 .B backup
 supfile option.
 .TP
+.B -C
+The
+.B -C
+flag or the
+.B canonicalize
+supfile option, canonicalize all pathnames upon reception to make sure
+local changes from directories to symlinks and vice versa have not happened
+behind sup's back, and attempt to repair them. This option is expensive.
+.TP
+.TP
 .B -d
 Files that are no longer in the collection on the
 repository will be deleted if present on the local
@@ -861,6 +871,8 @@
 that contains the same names.
 Then sup will cross the symlink and start deleting files and directories
 from the destination.
-This is not easily fixed.
+This is avoided by using the
+.B canonicalize
+option, but it is expensive.
 Don't use sup with symlink/rsymlink and the delete
 option at the same time or *be careful*!
diff -r 447f94e06d11 -r d123ae48b682 usr.sbin/sup/source/supcdefs.h
--- a/usr.sbin/sup/source/supcdefs.h    Wed Sep 21 19:32:59 2011 +0000
+++ b/usr.sbin/sup/source/supcdefs.h    Wed Sep 21 19:34:54 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: supcdefs.h,v 1.13 2002/11/30 03:10:58 lukem Exp $      */
+/*     $NetBSD: supcdefs.h,v 1.14 2011/09/21 19:34:54 christos Exp $   */
 
 /*
  * Copyright (c) 1992 Carnegie Mellon University
@@ -116,6 +116,7 @@
 #define CFURELSUF      02000
 #define CFCOMPRESS     04000
 #define CFSILENT       10000
+#define CFCANONICALIZE 20000
 
 /*************************
  ***   M A C R O S    ***
diff -r 447f94e06d11 -r d123ae48b682 usr.sbin/sup/source/supcmain.c
--- a/usr.sbin/sup/source/supcmain.c    Wed Sep 21 19:32:59 2011 +0000
+++ b/usr.sbin/sup/source/supcmain.c    Wed Sep 21 19:34:54 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: supcmain.c,v 1.31 2011/08/31 16:25:00 plunky Exp $     */
+/*     $NetBSD: supcmain.c,v 1.32 2011/09/21 19:34:54 christos Exp $   */
 
 /*
  * Copyright (c) 1992 Carnegie Mellon University
@@ -470,7 +470,7 @@
        int oflags, aflags;
        int c;
 
-#define SUPOPTIONS "abBdDeEfkKlmM:NoOPRsStuvXzZ=:"
+#define SUPOPTIONS "abBCdDeEfkKlmM:NoOPRsStuvXzZ=:"
 
        oflags = aflags = 0;
        while ((c = getopt(*argc, *argv, SUPOPTIONS)) != -1)
@@ -502,6 +502,9 @@
                        oflags &= ~CFBACKUP;
                        aflags |= CFBACKUP;
                        break;
+               case 'C':
+                       oflags |= CFCANONICALIZE;
+                       break;
                case 'd':
                        oflags |= CFDELETE;
                        aflags &= ~CFDELETE;
diff -r 447f94e06d11 -r d123ae48b682 usr.sbin/sup/source/supcmeat.c
--- a/usr.sbin/sup/source/supcmeat.c    Wed Sep 21 19:32:59 2011 +0000
+++ b/usr.sbin/sup/source/supcmeat.c    Wed Sep 21 19:34:54 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: supcmeat.c,v 1.39 2011/08/31 16:25:00 plunky Exp $     */
+/*     $NetBSD: supcmeat.c,v 1.40 2011/09/21 19:34:54 christos Exp $   */
 
 /*
  * Copyright (c) 1992 Carnegie Mellon University
@@ -140,6 +140,7 @@
 static int linkone(TREE *, void *);
 static int execone(TREE *, void *);
 static int finishone(TREE *, void *);
+static int canonicalize(const char *);
 
 
 /* The next two routines define the fsm to support multiple fileservers
@@ -493,6 +494,8 @@
                                *q = '\0';
                        if (strchr("#;:", *p))
                                continue;
+                       if (canonicalize(p) != 0)
+                               continue;
                        (void) Tinsert(&lastT, p, FALSE);
                }
                (void) fclose(f);
@@ -720,6 +723,8 @@
                        goaway("Error sending compression check to server");
                if (docompress)
                        vnotify("SUP Using compressed file transfer\n");
+               if (thisC->Cflags & CFCANONICALIZE)
+                       vnotify("SUP Filename canonicalization is on\n");
        }
        recvmore = TRUE;
        upgradeT = NULL;
@@ -942,10 +947,22 @@
        char dirpart[STRINGLENGTH], filepart[STRINGLENGTH];
        char filename[STRINGLENGTH], buf[STRINGLENGTH];
        struct timeval tbuf[2];
-       int x;
+       int x, noupdate = 0;
        char *p;
 
-       if (t->Tflags & FUPDATE) {
+       switch (canonicalize(t->Tname)) {
+       case 0: /* Ok no changes */
+               break;
+       case 1:
+               noupdate = 1;
+               break;
+       case -1:
+               notify("SUP: Can't create path for %s (%s)\n", t->Tname,
+                   strerror(errno));
+               return TRUE;
+       }
+               
+       if ((t->Tflags & FUPDATE) && !noupdate) {
                if ((t->Tflags & FNOACCT) == 0) {
                        /* convert user and group names to local ids */
                        ugconvert(t->Tuser, t->Tgroup, &t->Tuid, &t->Tgid,
@@ -1115,6 +1132,62 @@
        return (SCMOK);
 }
 
+/*
+ * We know that since "to" is a pathname coming from the server, it must
+ * not contain any symbolic links after the root, because otherwise the
+ * server would send us only the symlink above it. So we hunt for the symlink
+ * above and if found we convert the symlink to a directory, prepare the
+ * path below the symlink, and keep 
+ */
+static int
+canonicalize(const char *to)
+{
+       char absto[STRINGLENGTH], cabsto[STRINGLENGTH * 4];
+       char dir[STRINGLENGTH], file[STRINGLENGTH];
+       char *a;
+       char *c;
+       size_t len;
+       struct stat st;
+       const char *pwd = thisC->Cprefix ? thisC->Cprefix : thisC->Cbase;
+
+       if ((thisC->Cflags & CFCANONICALIZE) == 0)
+               return 0;
+
+       path(to, dir, file);
+
+       len = strlen(pwd);
+       (void)snprintf(absto, sizeof(absto), "%s/%s", pwd, dir);
+
+       len++;
+       if (realpath(absto, cabsto) == NULL)
+               return -1;
+
+       a = absto + len;
+       c = cabsto + len;
+
+       while (*a && *c && *a == *c)
+               a++, c++;
+
+       if (*a == '\0' && *c == '\0')
+               return 0;
+
+       while (*a && *a != '/')
+               a++;
+
+       *a = '\0';
+       if (lstat(absto, &st) == -1 || !S_ISLNK(st.st_mode))
+               return -1;
+
+       if (unlink(absto) == -1)
+               return -1;
+
+       strcpy(c, a);
+       if (estabd(file, cabsto) == -1) {
+               return -1;
+       }
+       return 1;
+}
+
 /* from will be 0 if reading from network */
 int 
 copyfile(char *to, char *from)
diff -r 447f94e06d11 -r d123ae48b682 usr.sbin/sup/source/supcparse.c
--- a/usr.sbin/sup/source/supcparse.c   Wed Sep 21 19:32:59 2011 +0000
+++ b/usr.sbin/sup/source/supcparse.c   Wed Sep 21 19:34:54 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: supcparse.c,v 1.14 2006/04/02 01:39:48 christos Exp $  */
+/*     $NetBSD: supcparse.c,v 1.15 2011/09/21 19:34:54 christos Exp $  */
 
 /*
  * Copyright (c) 1992 Carnegie Mellon University
@@ -69,7 +69,7 @@
        OHOST, OBASE, OHOSTBASE, OPREFIX, ORELEASE,
        ONOTIFY, OLOGIN, OPASSWORD, OCRYPT,
        OBACKUP, ODELETE, OEXECUTE, OOLD, OTIMEOUT, OKEEP, OURELSUF,
-       OCOMPRESS
+       OCOMPRESS, OCANONICALIZE
 }    OPTION;
 
 struct option {
@@ -92,7 +92,8 @@
        { "timeout", OTIMEOUT },
        { "keep", OKEEP },
        { "use-rel-suffix", OURELSUF },
-       { "compress", OCOMPRESS }
+       { "compress", OCOMPRESS },
+       { "canonicalize", OCANONICALIZE },
 };
 
 static void passdelim(char **, char);
@@ -215,6 +216,9 @@
                case OCOMPRESS:
                        c->Cflags |= CFCOMPRESS;
                        break;
+               case OCANONICALIZE:
+                       c->Cflags |= CFCANONICALIZE;
+                       break;
                case OTIMEOUT:
                        passdelim(&args, '=');
                        arg = nxtarg(&args, " \t");



Home | Main Index | Thread Index | Old Index