]> pd.if.org Git - zpackage/commitdiff
fix readlink bug in syncfs
authorNathan Wagner <nw@hydaspes.if.org>
Sun, 28 Oct 2018 16:25:25 +0000 (16:25 +0000)
committerNathan Wagner <nw@hydaspes.if.org>
Sat, 3 Nov 2018 12:39:53 +0000 (12:39 +0000)
zpm-syncfs.c

index ecc66c84f8bec7df14a66bd2ad21a50e8fe81431..ff80041e6750a5d43097f703c5bb76f3b733f11c 100644 (file)
@@ -334,19 +334,35 @@ static int remove_files(void *f, int ncols, char **vals, char **cols) {
 
 #define MARK fprintf(stderr, "%s %d: mark\n", __func__, __LINE__)
 
+/* file does not exist */
 #define D_NOEXIST 0x1
+/* files are different types */
 #define D_TYPE 0x2
+/* metadata is different */
 #define D_MD 0x4
+/* content or link target is different */
 #define D_HASH 0x8
+/* file to be installed is a directory */
 #define D_ISDIR  0x10
+/* path on disk is a directory */
 #define D_EISDIR 0x20
+/* usernames different */
 #define D_UID 0x40
+/* group names different */
 #define D_GID 0x80
+/* file mode is different */
 #define D_MODE 0x100
+/* mtimes are different */
 #define D_MTIME 0x200
+/* the hash of the file we are supposedly replacing is different than
+ * the the hash of the file on disk
+ */
 #define D_OHASH 0x400
+/* an error occurred trying to compare the file (other than it doesn't exist */
 #define D_ERROR 0x1000
+/* there was a stat error */
 #define D_STATERROR 0x2000
+/* there was an error calling readlink */
 #define D_RLERROR 0x4000
 
 /* 1 = file doesn't exist, 2 = file is a directory, target isn't */
@@ -388,11 +404,15 @@ static unsigned int file_compare(struct nitem *n, struct stat *st) {
                }
                if (n->hash && etype == S_IFLNK && stat_type == S_IFLNK) {
                        lsize = readlink(n->dest, link, sizeof link);
+
                        if (lsize == -1 || lsize == sizeof link) {
                                diff |= D_RLERROR;
                                diff |= D_ERROR;
-                       } else if (strcmp(n->target, link) != 0) {
-                               diff |= D_HASH;
+                       } else {
+                               link[lsize] = 0;
+                               if (strcmp(n->target, link) != 0) {
+                                       diff |= D_HASH;
+                               }
                        }
                }
                if (n->uid != st->st_uid) {
@@ -956,7 +976,20 @@ static int install_files(void *f, int ncols, char **vals, char **cols) {
                                /* accept doesn't matter, since it's
                                 * not an acceptable file */
                                /* error */
-                               return seterror(conf, "%s (hashdiff): %s", accept ? "existing file not acceptable" : "file exists", nitem.dest);
+                               if (nitem.ftype == 'l') {
+                                       char link[1024];
+                                       ssize_t lsize;
+                                       lsize = readlink(nitem.dest, link, sizeof link);
+                                       if (lsize == -1 || (size_t)lsize >= sizeof link) {
+                                               return seterror(conf, "%s (linkdiff): expecting %s -> %s, unable to read link", accept ? "existing file not acceptable" : "file exists", nitem.dest, nitem.target, link);
+                                       } else {
+                                               link[lsize] = 0;
+                                               /* links must be different */
+                                               return seterror(conf, "%s (linkdiff): expecting %s -> %s, have -> %s", accept ? "existing file not acceptable" : "file exists", nitem.dest, nitem.target, link);
+                                       }
+                               } else {
+                                       return seterror(conf, "%s (hashdiff): %s", accept ? "existing file not acceptable" : "file exists", nitem.dest);
+                               }
                        }
                        if (!mdsame && hashsame && overwrite) {
                                /* fix md */