#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 */
}
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) {
/* 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 */