diff options
Diffstat (limited to 'archive-tar.c')
-rw-r--r-- | archive-tar.c | 115 |
1 files changed, 36 insertions, 79 deletions
diff --git a/archive-tar.c b/archive-tar.c index 99db58f1cf..f9eb726116 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -13,11 +13,7 @@ static char block[BLOCKSIZE]; static unsigned long offset; -static time_t archive_time; static int tar_umask = 002; -static int verbose; -static const struct commit *commit; -static size_t base_len; /* writes out the whole block, but only if it is full */ static void write_if_needed(void) @@ -114,22 +110,24 @@ static unsigned int ustar_header_chksum(const struct ustar_header *header) return chksum; } -static int get_path_prefix(const struct strbuf *path, int maxlen) +static size_t get_path_prefix(const char *path, size_t pathlen, size_t maxlen) { - int i = path->len; + size_t i = pathlen; if (i > maxlen) i = maxlen; do { i--; - } while (i > 0 && path->buf[i] != '/'); + } while (i > 0 && path[i] != '/'); return i; } -static void write_entry(const unsigned char *sha1, struct strbuf *path, - unsigned int mode, void *buffer, unsigned long size) +static int write_tar_entry(struct archiver_args *args, + const unsigned char *sha1, const char *path, size_t pathlen, + unsigned int mode, void *buffer, unsigned long size) { struct ustar_header header; struct strbuf ext_header; + int err = 0; memset(&header, 0, sizeof(header)); strbuf_init(&ext_header, 0); @@ -143,8 +141,6 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path, mode = 0100666; sprintf(header.name, "%s.paxheader", sha1_to_hex(sha1)); } else { - if (verbose) - fprintf(stderr, "%.*s\n", (int)path->len, path->buf); if (S_ISDIR(mode) || S_ISGITLINK(mode)) { *header.typeflag = TYPEFLAG_DIR; mode = (mode | 0777) & ~tar_umask; @@ -155,24 +151,24 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path, *header.typeflag = TYPEFLAG_REG; mode = (mode | ((mode & 0100) ? 0777 : 0666)) & ~tar_umask; } else { - error("unsupported file mode: 0%o (SHA1: %s)", - mode, sha1_to_hex(sha1)); - return; + return error("unsupported file mode: 0%o (SHA1: %s)", + mode, sha1_to_hex(sha1)); } - if (path->len > sizeof(header.name)) { - int plen = get_path_prefix(path, sizeof(header.prefix)); - int rest = path->len - plen - 1; + if (pathlen > sizeof(header.name)) { + size_t plen = get_path_prefix(path, pathlen, + sizeof(header.prefix)); + size_t rest = pathlen - plen - 1; if (plen > 0 && rest <= sizeof(header.name)) { - memcpy(header.prefix, path->buf, plen); - memcpy(header.name, path->buf + plen + 1, rest); + memcpy(header.prefix, path, plen); + memcpy(header.name, path + plen + 1, rest); } else { sprintf(header.name, "%s.data", sha1_to_hex(sha1)); strbuf_append_ext_header(&ext_header, "path", - path->buf, path->len); + path, pathlen); } } else - memcpy(header.name, path->buf, path->len); + memcpy(header.name, path, pathlen); } if (S_ISLNK(mode) && buffer) { @@ -187,7 +183,7 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path, sprintf(header.mode, "%07o", mode & 07777); sprintf(header.size, "%011lo", S_ISREG(mode) ? size : 0); - sprintf(header.mtime, "%011lo", archive_time); + sprintf(header.mtime, "%011lo", args->time); sprintf(header.uid, "%07o", 0); sprintf(header.gid, "%07o", 0); @@ -202,22 +198,30 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path, sprintf(header.chksum, "%07o", ustar_header_chksum(&header)); if (ext_header.len > 0) { - write_entry(sha1, NULL, 0, ext_header.buf, ext_header.len); + err = write_tar_entry(args, sha1, NULL, 0, 0, ext_header.buf, + ext_header.len); + if (err) + return err; } strbuf_release(&ext_header); write_blocked(&header, sizeof(header)); if (S_ISREG(mode) && buffer && size > 0) write_blocked(buffer, size); + return err; } -static void write_global_extended_header(const unsigned char *sha1) +static int write_global_extended_header(struct archiver_args *args) { + const unsigned char *sha1 = args->commit_sha1; struct strbuf ext_header; + int err; strbuf_init(&ext_header, 0); strbuf_append_ext_header(&ext_header, "comment", sha1_to_hex(sha1), 40); - write_entry(NULL, NULL, 0, ext_header.buf, ext_header.len); + err = write_tar_entry(args, NULL, NULL, 0, 0, ext_header.buf, + ext_header.len); strbuf_release(&ext_header); + return err; } static int git_tar_config(const char *var, const char *value, void *cb) @@ -234,64 +238,17 @@ static int git_tar_config(const char *var, const char *value, void *cb) return git_default_config(var, value, cb); } -static int write_tar_entry(const unsigned char *sha1, - const char *base, int baselen, - const char *filename, unsigned mode, int stage) -{ - static struct strbuf path = STRBUF_INIT; - void *buffer; - enum object_type type; - unsigned long size; - - strbuf_reset(&path); - strbuf_grow(&path, PATH_MAX); - strbuf_add(&path, base, baselen); - strbuf_addstr(&path, filename); - if (is_archive_path_ignored(path.buf + base_len)) - return 0; - if (S_ISDIR(mode) || S_ISGITLINK(mode)) { - strbuf_addch(&path, '/'); - buffer = NULL; - size = 0; - } else { - buffer = sha1_file_to_archive(path.buf + base_len, sha1, mode, - &type, &size, commit); - if (!buffer) - die("cannot read %s", sha1_to_hex(sha1)); - } - - write_entry(sha1, &path, mode, buffer, size); - free(buffer); - - return READ_TREE_RECURSIVE; -} - int write_tar_archive(struct archiver_args *args) { - int plen = args->base ? strlen(args->base) : 0; + int err = 0; git_config(git_tar_config, NULL); - archive_time = args->time; - verbose = args->verbose; - commit = args->commit; - base_len = args->base ? strlen(args->base) : 0; - if (args->commit_sha1) - write_global_extended_header(args->commit_sha1); - - if (args->base && plen > 0 && args->base[plen - 1] == '/') { - char *base = xstrdup(args->base); - int baselen = strlen(base); - - while (baselen > 0 && base[baselen - 1] == '/') - base[--baselen] = '\0'; - write_tar_entry(args->tree->object.sha1, "", 0, base, 040777, 0); - free(base); - } - read_tree_recursive(args->tree, args->base, plen, 0, - args->pathspec, write_tar_entry); - write_trailer(); - - return 0; + err = write_global_extended_header(args); + if (!err) + err = write_archive_entries(args, write_tar_entry); + if (!err) + write_trailer(); + return err; } |