From: Sergey Poznyakoff Date: Sat, 26 Nov 2005 19:31:02 +0000 (+0000) Subject: (xheader_format_name): Fix memory leak. X-Git-Url: https://git.brokenzipper.com/gitweb?a=commitdiff_plain;h=9590e781c0ed2ea8a792327fc17d6bb122a92b04;p=chaz%2Ftar (xheader_format_name): Fix memory leak. --- diff --git a/src/xheader.c b/src/xheader.c index 8f727a9..d880bd5 100644 --- a/src/xheader.c +++ b/src/xheader.c @@ -235,6 +235,7 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n) size_t len = strlen (fmt); char *q; const char *p; + char *dirp = NULL; char *dir = NULL; char *base = NULL; char pidbuf[UINTMAX_STRSIZE_BOUND]; @@ -253,8 +254,9 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n) case 'd': if (st) { - dir = safer_name_suffix (dir_name (st->orig_file_name), - false, absolute_names_option); + if (!dirp) + dirp = dir_name (st->orig_file_name); + dir = safer_name_suffix (dirp, false, absolute_names_option); len += strlen (dir) - 2; } break; @@ -328,6 +330,8 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n) *q++ = *p++; } + free (dirp); + /* Do not allow it to end in a slash */ while (q > buf && ISSLASH (q[-1])) q--; @@ -370,6 +374,17 @@ xheader_write (char type, char *name, struct xheader *xhdr) size_t size; char *p; + if (multi_volume_option) + { + /* Estimate the total size of the extended header and, in case + if XHDTYPE, the ustar header following it, and make sure that + these fit into the current volume */ + size_t hblocks = 1 + (extended_header.size + BLOCKSIZE - 1) / BLOCKSIZE; + if (type == XHDTYPE) + hblocks++; + multi_volume_fixup (hblocks); + } + size = xhdr->size; header = start_private_header (name, size); header->header.typeflag = type; @@ -400,6 +415,44 @@ xheader_write (char type, char *name, struct xheader *xhdr) global_header_count++; } +/* SIZE is guaranteed to be divisible by BLOCKSIZE */ +void +xheader_eof (size_t size) +{ + union block *header; + char *name; + int first_block = 1; + int nl = 0; + + size -= BLOCKSIZE; + name = xheader_ghdr_name (); + header = start_private_header (name, size); + header->header.typeflag = XGLTYPE; + free (name); + simple_finish_header (header); + if (size) + nl = 1; + while (size > 0) + { + size_t len; + + header = find_next_block (); + len = BLOCKSIZE; + if (len > size) + len = size; + memset (header->buffer, 0, len); + if (first_block) + { + first_block = 0; + sprintf (header->buffer, "%d GNU.volume.eof=", size); + } + size -= len; + set_next_block_after (header); + } + if (nl) + header->buffer[BLOCKSIZE-1] = '\n'; +} + void xheader_write_global (void) { @@ -615,6 +668,20 @@ extended_header_init (void) } } +void +xheader_save (struct xheader *xhdr) +{ + *xhdr = extended_header; + memset (&extended_header, 0, sizeof extended_header); +} + +void +xheader_restore (struct xheader *xhdr) +{ + xheader_destroy (&extended_header); + extended_header = *xhdr; +} + void xheader_store (char const *keyword, struct tar_stat_info const *st, void const *data)