X-Git-Url: https://git.octo.it/?p=git.git;a=blobdiff_plain;f=builtin-tar-tree.c;h=39a61b629367df9dd274acf5fa310b45dd06f126;hp=5f740cf7025bc2a9b46656332c6a54e78ee737e4;hb=HEAD;hpb=4c068a983150b740c3fcf6a33f342ac923abd3f4 diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c index 5f740cf7..39a61b62 100644 --- a/builtin-tar-tree.c +++ b/builtin-tar-tree.c @@ -22,8 +22,10 @@ static unsigned long offset; static time_t archive_time; /* tries hard to write, either succeeds or dies in the attempt */ -static void reliable_write(void *buf, unsigned long size) +static void reliable_write(const void *data, unsigned long size) { + const char *buf = data; + while (size > 0) { long ret = xwrite(1, buf, size); if (ret < 0) { @@ -47,37 +49,13 @@ static void write_if_needed(void) } } -/* acquire the next record from the buffer; user must call write_if_needed() */ -static char *get_record(void) -{ - char *p = block + offset; - memset(p, 0, RECORDSIZE); - offset += RECORDSIZE; - return p; -} - -/* - * The end of tar archives is marked by 1024 nul bytes and after that - * follows the rest of the block (if any). - */ -static void write_trailer(void) -{ - get_record(); - write_if_needed(); - get_record(); - write_if_needed(); - while (offset) { - get_record(); - write_if_needed(); - } -} - /* * queues up writes, so that all our write(2) calls write exactly one * full block; pads writes to RECORDSIZE */ -static void write_blocked(void *buf, unsigned long size) +static void write_blocked(const void *data, unsigned long size) { + const char *buf = data; unsigned long tail; if (offset) { @@ -107,6 +85,21 @@ static void write_blocked(void *buf, unsigned long size) write_if_needed(); } +/* + * The end of tar archives is marked by 2*512 nul bytes and after that + * follows the rest of the block (if any). + */ +static void write_trailer(void) +{ + int tail = BLOCKSIZE - offset; + memset(block + offset, 0, tail); + reliable_write(block, BLOCKSIZE); + if (tail < 2 * RECORDSIZE) { + memset(block, 0, offset); + reliable_write(block, BLOCKSIZE); + } +} + static void strbuf_append_string(struct strbuf *sb, const char *s) { int slen = strlen(s); @@ -168,8 +161,9 @@ static int get_path_prefix(const struct strbuf *path, int maxlen) int i = path->len; if (i > maxlen) i = maxlen; - while (i > 0 && path->buf[i] != '/') + do { i--; + } while (i > 0 && path->buf[i] != '/'); return i; } @@ -239,8 +233,8 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path, /* XXX: should we provide more meaningful info here? */ sprintf(header.uid, "%07o", 0); sprintf(header.gid, "%07o", 0); - strncpy(header.uname, "git", 31); - strncpy(header.gname, "git", 31); + safe_strncpy(header.uname, "git", sizeof(header.uname)); + safe_strncpy(header.gname, "git", sizeof(header.gname)); sprintf(header.devmajor, "%07o", 0); sprintf(header.devminor, "%07o", 0); @@ -401,3 +395,28 @@ int cmd_tar_tree(int argc, const char **argv, char **envp) return remote_tar(argc, argv); return generate_tar(argc, argv, envp); } + +/* ustar header + extended global header content */ +#define HEADERSIZE (2 * RECORDSIZE) + +int cmd_get_tar_commit_id(int argc, const char **argv, char **envp) +{ + char buffer[HEADERSIZE]; + struct ustar_header *header = (struct ustar_header *)buffer; + char *content = buffer + RECORDSIZE; + ssize_t n; + + n = xread(0, buffer, HEADERSIZE); + if (n < HEADERSIZE) + die("git-get-tar-commit-id: read error"); + if (header->typeflag[0] != 'g') + return 1; + if (memcmp(content, "52 comment=", 11)) + return 1; + + n = xwrite(1, content + 11, 41); + if (n < 41) + die("git-get-tar-commit-id: write error"); + + return 0; +}