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.
This commit is contained in:
Timo Teras 2009-08-11 19:56:11 +03:00
parent 6b2c6c0c03
commit 8b1a53011b
1 changed files with 31 additions and 13 deletions

View File

@ -42,6 +42,8 @@ struct tar_header {
char padding[12]; /* 500-512 */ char padding[12]; /* 500-512 */
}; };
#define MAX_MD_SIZE 20
#define GET_OCTAL(s) get_octal(s, sizeof(s)) #define GET_OCTAL(s) get_octal(s, sizeof(s))
#define PUT_OCTAL(s,v) put_octal(s, sizeof(s), v) #define PUT_OCTAL(s,v) put_octal(s, sizeof(s), v)
@ -94,10 +96,10 @@ static int usage(void)
fprintf(stderr, fprintf(stderr,
"abuild-tar " VERSION "\n" "abuild-tar " VERSION "\n"
"\n" "\n"
"usage: abuild-tar [--hash [<algorithm>]] [--cut]\n" "usage: abuild-tar [--hash[=<algorithm>]] [--cut]\n"
"\n" "\n"
"options:\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" " regular entries and output tar archive on stdout\n"
" --cut Remove the end of file tar record\n" " --cut Remove the end of file tar record\n"
"\n"); "\n");
@ -173,7 +175,7 @@ static int do_it(const EVP_MD *md, int cut)
struct tar_header hdr; struct tar_header hdr;
size_t size, aligned_size; size_t size, aligned_size;
void *ptr; void *ptr;
int dohash = 0, r; int r;
struct { struct {
char id[4]; char id[4];
uint16_t nid; uint16_t nid;
@ -193,22 +195,34 @@ static int do_it(const EVP_MD *md, int cut)
if (cut && hdr.name[0] == 0) if (cut && hdr.name[0] == 0)
return 0; return 0;
ptr = NULL;
size = GET_OCTAL(hdr.size); size = GET_OCTAL(hdr.size);
aligned_size = (size + 511) & ~511; aligned_size = (size + 511) & ~511;
if (md != NULL) if (md != NULL &&
dohash = (hdr.typeflag == '0' || hdr.typeflag == '7'); (hdr.typeflag == '0' || hdr.typeflag == '2' ||
if (dohash) { hdr.typeflag == '7')) {
const unsigned char *src; const unsigned char *src;
unsigned char csdata[MAX_MD_SIZE];
int chksum, i; int chksum, i;
ptr = malloc(aligned_size); if (hdr.typeflag == '0' || hdr.typeflag == '7') {
if (full_read(STDIN_FILENO, ptr, aligned_size) != aligned_size) ptr = malloc(aligned_size);
return 1; if (full_read(STDIN_FILENO, ptr, aligned_size)
!= aligned_size)
return 1;
memcpy(&hdr.linkname[3], &mdinfo, sizeof(mdinfo)); memcpy(&hdr.linkname[3], &mdinfo, sizeof(mdinfo));
EVP_Digest(ptr, size, &hdr.linkname[3+sizeof(mdinfo)], EVP_Digest(ptr, size, csdata, NULL, md, NULL);
NULL, md, NULL); } else {
EVP_Digest(hdr.linkname, strlen(hdr.linkname),
csdata, 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 */ /* Recalculate checksum */
memset(hdr.chksum, ' ', sizeof(hdr.chksum)); 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)) if (full_write(STDOUT_FILENO, &hdr, sizeof(hdr)) != sizeof(hdr))
return 2; return 2;
if (dohash) { if (ptr != NULL) {
if (full_write(STDOUT_FILENO, ptr, aligned_size) != aligned_size) if (full_write(STDOUT_FILENO, ptr, aligned_size) != aligned_size)
return 2; return 2;
free(ptr); free(ptr);
@ -271,6 +285,10 @@ int main(int argc, char **argv)
md = EVP_get_digestbyname(digest); md = EVP_get_digestbyname(digest);
if (md == NULL) if (md == NULL)
return usage(); 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); return do_it(md, cut);