diff options
Diffstat (limited to 'tar/util.c')
-rw-r--r-- | tar/util.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/tar/util.c b/tar/util.c index 2a3d9a03b544..7e705c2be228 100644 --- a/tar/util.c +++ b/tar/util.c @@ -56,7 +56,7 @@ __FBSDID("$FreeBSD: src/usr.bin/tar/util.c,v 1.23 2008/12/15 06:00:25 kientzle E #include <wctype.h> #else /* If we don't have wctype, we need to hack up some version of iswprint(). */ -#define iswprint isprint +#define iswprint isprint #endif #include "bsdtar.h" @@ -66,14 +66,14 @@ static size_t bsdtar_expand_char(char *, size_t, char); static const char *strip_components(const char *path, int elements); #if defined(_WIN32) && !defined(__CYGWIN__) -#define read _read +#define read _read #endif /* TODO: Hack up a version of mbtowc for platforms with no wide * character support at all. I think the following might suffice, * but it needs careful testing. * #if !HAVE_MBTOWC - * #define mbtowc(wcp, p, n) ((*wcp = *p), 1) + * #define mbtowc(wcp, p, n) ((*wcp = *p), 1) * #endif */ @@ -115,8 +115,21 @@ safe_fprintf(FILE *f, const char *fmt, ...) va_end(ap); /* If the result was too large, allocate a buffer on the heap. */ - if (length >= fmtbuff_length) { - fmtbuff_length = length+1; + while (length < 0 || length >= fmtbuff_length) { + if (length >= fmtbuff_length) + fmtbuff_length = length+1; + else if (fmtbuff_length < 8192) + fmtbuff_length *= 2; + else { + int old_length = fmtbuff_length; + fmtbuff_length += fmtbuff_length / 4; + if (old_length > fmtbuff_length) { + length = old_length; + fmtbuff_heap[length-1] = '\0'; + break; + } + } + free(fmtbuff_heap); fmtbuff_heap = malloc(fmtbuff_length); /* Reformat the result into the heap buffer if we can. */ @@ -129,6 +142,7 @@ safe_fprintf(FILE *f, const char *fmt, ...) /* Leave fmtbuff pointing to the truncated * string in fmtbuff_stack. */ length = sizeof(fmtbuff_stack) - 1; + break; } } @@ -267,12 +281,19 @@ yes(const char *fmt, ...) * about -C with non-existent directories; such requests will only * fail if the directory must be accessed. * - * TODO: Make this handle Windows paths correctly. */ void set_chdir(struct bsdtar *bsdtar, const char *newdir) { +#if defined(_WIN32) && !defined(__CYGWIN__) + if (newdir[0] == '/' || newdir[0] == '\\' || + /* Detect this type, for example, "C:\" or "C:/" */ + (((newdir[0] >= 'a' && newdir[0] <= 'z') || + (newdir[0] >= 'A' && newdir[0] <= 'Z')) && + newdir[1] == ':' && (newdir[2] == '/' || newdir[2] == '\\'))) { +#else if (newdir[0] == '/') { +#endif /* The -C /foo -C /bar case; dump first one. */ free(bsdtar->pending_chdir); bsdtar->pending_chdir = NULL; @@ -362,10 +383,8 @@ edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry) #if HAVE_REGEX_H char *subst_name; int r; -#endif -#if HAVE_REGEX_H - r = apply_substitution(bsdtar, name, &subst_name, 0); + r = apply_substitution(bsdtar, name, &subst_name, 0, 0); if (r == -1) { lafe_warnc(0, "Invalid substitution, skipping entry"); return 1; @@ -381,7 +400,7 @@ edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry) } if (archive_entry_hardlink(entry)) { - r = apply_substitution(bsdtar, archive_entry_hardlink(entry), &subst_name, 1); + r = apply_substitution(bsdtar, archive_entry_hardlink(entry), &subst_name, 0, 1); if (r == -1) { lafe_warnc(0, "Invalid substitution, skipping entry"); return 1; @@ -392,7 +411,7 @@ edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry) } } if (archive_entry_symlink(entry) != NULL) { - r = apply_substitution(bsdtar, archive_entry_symlink(entry), &subst_name, 1); + r = apply_substitution(bsdtar, archive_entry_symlink(entry), &subst_name, 1, 0); if (r == -1) { lafe_warnc(0, "Invalid substitution, skipping entry"); return 1; @@ -507,14 +526,13 @@ const char * tar_i64toa(int64_t n0) { static char buff[24]; - int64_t n = n0 < 0 ? -n0 : n0; + uint64_t n = n0 < 0 ? -n0 : n0; char *p = buff + sizeof(buff); *--p = '\0'; do { *--p = '0' + (int)(n % 10); - n /= 10; - } while (n > 0); + } while (n /= 10); if (n0 < 0) *--p = '-'; return p; |