summaryrefslogtreecommitdiffstats
path: root/abuild-tar.c
diff options
context:
space:
mode:
authorTimo Teras <timo.teras@iki.fi>2009-08-11 19:56:11 +0300
committerTimo Teras <timo.teras@iki.fi>2009-08-11 19:56:11 +0300
commit8b1a53011b3aa56594e785c425b318c21fba8684 (patch)
treeb554752ad322b3ac17432e580c387360c005fedd /abuild-tar.c
parent6b2c6c0c0325be3ea2a0b827106ae90b42128fa3 (diff)
downloadabuild-8b1a53011b3aa56594e785c425b318c21fba8684.tar.bz2
abuild-8b1a53011b3aa56594e785c425b318c21fba8684.tar.xz
abuild-tar: embed checksum for symlinks
and relocate the place of the symlink in tar header, as symlink use the linkname field. now it's split to devmajor, devminor and padding fields.
Diffstat (limited to 'abuild-tar.c')
-rw-r--r--abuild-tar.c44
1 files changed, 31 insertions, 13 deletions
diff --git a/abuild-tar.c b/abuild-tar.c
index 1293ddc..011fff6 100644
--- a/abuild-tar.c
+++ b/abuild-tar.c
@@ -42,6 +42,8 @@ struct tar_header {
char padding[12]; /* 500-512 */
};
+#define MAX_MD_SIZE 20
+
#define GET_OCTAL(s) get_octal(s, sizeof(s))
#define PUT_OCTAL(s,v) put_octal(s, sizeof(s), v)
@@ -94,10 +96,10 @@ static int usage(void)
fprintf(stderr,
"abuild-tar " VERSION "\n"
"\n"
-"usage: abuild-tar [--hash [<algorithm>]] [--cut]\n"
+"usage: abuild-tar [--hash[=<algorithm>]] [--cut]\n"
"\n"
"options:\n"
-" --hash [sha1|md5] Read tar archive from stdin, precalculate hash for \n"
+" --hash[=sha1|md5] Read tar archive from stdin, precalculate hash for \n"
" regular entries and output tar archive on stdout\n"
" --cut Remove the end of file tar record\n"
"\n");
@@ -173,7 +175,7 @@ static int do_it(const EVP_MD *md, int cut)
struct tar_header hdr;
size_t size, aligned_size;
void *ptr;
- int dohash = 0, r;
+ int r;
struct {
char id[4];
uint16_t nid;
@@ -193,22 +195,34 @@ static int do_it(const EVP_MD *md, int cut)
if (cut && hdr.name[0] == 0)
return 0;
+ ptr = NULL;
size = GET_OCTAL(hdr.size);
aligned_size = (size + 511) & ~511;
- if (md != NULL)
- dohash = (hdr.typeflag == '0' || hdr.typeflag == '7');
- if (dohash) {
+ if (md != NULL &&
+ (hdr.typeflag == '0' || hdr.typeflag == '2' ||
+ hdr.typeflag == '7')) {
const unsigned char *src;
+ unsigned char csdata[MAX_MD_SIZE];
int chksum, i;
- ptr = malloc(aligned_size);
- if (full_read(STDIN_FILENO, ptr, aligned_size) != aligned_size)
- return 1;
+ if (hdr.typeflag == '0' || hdr.typeflag == '7') {
+ ptr = malloc(aligned_size);
+ if (full_read(STDIN_FILENO, ptr, aligned_size)
+ != aligned_size)
+ return 1;
+
+ memcpy(&hdr.linkname[3], &mdinfo, sizeof(mdinfo));
+ EVP_Digest(ptr, size, csdata, NULL, md, NULL);
+ } else {
+ EVP_Digest(hdr.linkname, strlen(hdr.linkname),
+ csdata, NULL, md, NULL);
+ }
- memcpy(&hdr.linkname[3], &mdinfo, sizeof(mdinfo));
- EVP_Digest(ptr, size, &hdr.linkname[3+sizeof(mdinfo)],
- NULL, md, NULL);
+ /* Embed to header */
+ memcpy(&hdr.devmajor, &mdinfo, sizeof(hdr.devmajor));
+ memcpy(&hdr.devminor, &csdata[0], sizeof(hdr.devminor));
+ memcpy(&hdr.padding, &csdata[sizeof(hdr.devminor)], sizeof(hdr.padding));
/* Recalculate checksum */
memset(hdr.chksum, ' ', sizeof(hdr.chksum));
@@ -221,7 +235,7 @@ static int do_it(const EVP_MD *md, int cut)
if (full_write(STDOUT_FILENO, &hdr, sizeof(hdr)) != sizeof(hdr))
return 2;
- if (dohash) {
+ if (ptr != NULL) {
if (full_write(STDOUT_FILENO, ptr, aligned_size) != aligned_size)
return 2;
free(ptr);
@@ -271,6 +285,10 @@ int main(int argc, char **argv)
md = EVP_get_digestbyname(digest);
if (md == NULL)
return usage();
+ if (EVP_MD_size(md) > MAX_MD_SIZE) {
+ fprintf(stderr, "digest size is too large\n");
+ return -1;
+ }
}
return do_it(md, cut);