Subject: bin/24477: install(1) metalog: fix digest of /dev/null, and add size field
To: None <gnats-bugs@gnats.NetBSD.org>
From: None <apb@cequrux.com>
List: netbsd-bugs
Date: 02/18/2004 18:11:44
>Number: 24477
>Category: bin
>Synopsis: install(1) metalog: fix digest of /dev/null, and add size field
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bin-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Wed Feb 18 16:13:00 UTC 2004
>Closed-Date:
>Last-Modified:
>Originator: Alan Barrett
>Release: NetBSD 1.6ZK
>Organization:
Not much
>Environment:
NetBSD 1.6ZK
>Description:
When install(1) is used to install an empty file in metalog mode,
using a command like this:
install -M ${DESTDIR}/METALOG -h sha1 /dev/null ${DESTDIR}/dir/file
the relevant line in the metalog does not contain the sha1 hash of the
empty file. This happens because /dev/null is recognised as a special
case, and the code that would have calculated the hash is bypassed.
The appended patch gives install(1) knowledge of the md5, sha1 and rmd160
hashes of an empty file. It also adds a "size=" field to the metalog.
>How-To-Repeat:
>Fix:
Apply the following patch.
Index: src/usr.bin/xinstall/xinstall.c
--- xinstall.c 2 Feb 2004 23:25:36 -0000 1.86
+++ xinstall.c 10 Feb 2004 21:09:54 -0000
@@ -101,6 +101,7 @@
DIGEST_SHA1,
} digesttype = DIGEST_NONE;
char *digest;
+char *nulldigest; /* the digest of an empty file */
#define LN_ABSOLUTE 0x01
#define LN_RELATIVE 0x02
@@ -123,7 +124,7 @@
int main(int, char *[]);
void makelink(char *, char *);
void metadata_log(const char *, const char *, struct timeval *,
- const char *, const char *);
+ const char *, const char *, off_t);
int parseid(char *, id_t *);
void strip(char *);
void usage(void);
@@ -281,12 +282,16 @@
if (0) {
} else if (strcmp(digest, "none") == 0) {
digesttype = DIGEST_NONE;
+ nulldigest = NULL;
} else if (strcmp(digest, "md5") == 0) {
digesttype = DIGEST_MD5;
+ nulldigest = "d41d8cd98f00b204e9800998ecf8427e";
} else if (strcmp(digest, "rmd160") == 0) {
digesttype = DIGEST_RMD160;
+ nulldigest = "9c1185a5c5e9fc54612808977ee8f548b2258d31";
} else if (strcmp(digest, "sha1") == 0) {
digesttype = DIGEST_SHA1;
+ nulldigest = "da39a3ee5e6b4b0d3255bfef95601890afd80709";
} else {
warnx("unknown digest `%s'", digest);
usage();
@@ -489,7 +494,8 @@
default:
dres = NULL;
}
- metadata_log(to_name, "file", NULL, NULL, dres);
+ metadata_log(to_name, "file", NULL, NULL,
+ dres, to_sb.st_size);
free(dres);
mode = omode;
owner = oowner;
@@ -506,7 +512,7 @@
if (realpath(from_name, src) == NULL)
err(1, "%s: realpath", from_name);
do_symlink(src, to_name);
- metadata_log(to_name, "link", NULL, src, NULL);
+ metadata_log(to_name, "link", NULL, src, NULL, 0);
return;
}
@@ -547,7 +553,7 @@
(void)strlcat(lnk, ++s, sizeof(lnk));
do_symlink(lnk, dst);
- metadata_log(dst, "link", NULL, lnk, NULL);
+ metadata_log(dst, "link", NULL, lnk, NULL, 0);
return;
}
@@ -556,7 +562,7 @@
* try the names the user provided
*/
do_symlink(from_name, to_name);
- metadata_log(to_name, "link", NULL, from_name, NULL);
+ metadata_log(to_name, "link", NULL, from_name, NULL, 0);
}
/*
@@ -734,7 +740,9 @@
}
#endif
- metadata_log(to_name, "file", tv, NULL, digestresult);
+ metadata_log(to_name, "file", tv, NULL,
+ (devnull ? nulldigest : digestresult),
+ (devnull ? 0 : from_sb.st_size));
free(digestresult);
}
@@ -1009,17 +1017,18 @@
|| chmod(path, mode) == -1 )) {
warn("%s: chown/chmod", path);
}
- metadata_log(path, "dir", NULL, NULL, NULL);
+ metadata_log(path, "dir", NULL, NULL, NULL, 0);
}
/*
* metadata_log --
* if metafp is not NULL, output mtree(8) full path name and settings to
- * metafp, to allow permissions to be set correctly by other tools.
+ * metafp, to allow permissions to be set correctly by other tools,
+ * or to allow integrity checks to be performed.
*/
void
metadata_log(const char *path, const char *type, struct timeval *tv,
- const char *link, const char *digestresult)
+ const char *link, const char *digestresult, off_t size)
{
static const char extra[] = { ' ', '\t', '\n', '\\', '#', '\0' };
char *buf, *p;
@@ -1067,6 +1076,8 @@
fprintf(metafp, " tags=%s", tags);
if (tv != NULL && dopreserve)
fprintf(metafp, " time=%ld.%ld", tv[1].tv_sec, tv[1].tv_usec);
+ if (*type == 'f') /* type=file */
+ fprintf(metafp, " size=%lld", (long long)size);
if (digestresult && digest)
fprintf(metafp, " %s=%s", digest, digestresult);
fputc('\n', metafp);
>Release-Note:
>Audit-Trail:
>Unformatted: