summaryrefslogtreecommitdiffstats
path: root/lib/libarchive/archive_write_set_format_shar.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libarchive/archive_write_set_format_shar.c')
-rw-r--r--lib/libarchive/archive_write_set_format_shar.c46
1 files changed, 32 insertions, 14 deletions
diff --git a/lib/libarchive/archive_write_set_format_shar.c b/lib/libarchive/archive_write_set_format_shar.c
index 76fa398..f063e21 100644
--- a/lib/libarchive/archive_write_set_format_shar.c
+++ b/lib/libarchive/archive_write_set_format_shar.c
@@ -38,16 +38,6 @@ __FBSDID("$FreeBSD$");
#include "archive_entry.h"
#include "archive_private.h"
-static int archive_write_shar_finish(struct archive *);
-static int archive_write_shar_header(struct archive *,
- struct archive_entry *);
-static int archive_write_shar_data_sed(struct archive *,
- const void * buff, size_t);
-static int archive_write_shar_data_uuencode(struct archive *,
- const void * buff, size_t);
-static int archive_write_shar_finish_entry(struct archive *);
-static int shar_printf(struct archive *, const char *fmt, ...);
-
struct shar {
int dump;
int end_of_line;
@@ -60,19 +50,43 @@ struct shar {
int uuavail;
char uubuffer[3];
int wrote_header;
+ char *work;
+ size_t work_len;
};
+static int archive_write_shar_finish(struct archive *);
+static int archive_write_shar_header(struct archive *,
+ struct archive_entry *);
+static int archive_write_shar_data_sed(struct archive *,
+ const void * buff, size_t);
+static int archive_write_shar_data_uuencode(struct archive *,
+ const void * buff, size_t);
+static int archive_write_shar_finish_entry(struct archive *);
+static int shar_printf(struct archive *, const char *fmt, ...);
+static void uuencode_group(struct shar *);
+
static int
shar_printf(struct archive *a, const char *fmt, ...)
{
+ struct shar *shar;
va_list ap;
- char *p;
+ int required;
int ret;
+ shar = a->format_data;
+ if (shar->work_len <= 0) {
+ shar->work_len = 1024;
+ shar->work = malloc(shar->work_len);
+ }
+
va_start(ap, fmt);
- vasprintf(&p, fmt, ap);
- ret = ((a->compression_write)(a, p, strlen(p)));
- free(p);
+ required = vsnprintf(shar->work, shar->work_len, fmt, ap);
+ if ((size_t)required >= shar->work_len) {
+ shar->work_len = required + 256;
+ realloc(shar->work, shar->work_len);
+ required = vsnprintf(shar->work, shar->work_len, fmt, ap);
+ }
+ ret = ((a->compression_write)(a, shar->work, strlen(shar->work)));
va_end(ap);
return (ret);
}
@@ -261,6 +275,7 @@ archive_write_shar_header(struct archive *a, struct archive_entry *entry)
return (ARCHIVE_OK);
}
+/* XXX TODO: This could be more efficient XXX */
static int
archive_write_shar_data_sed(struct archive *a, const void *buff, size_t length)
{
@@ -297,6 +312,7 @@ archive_write_shar_data_sed(struct archive *a, const void *buff, size_t length)
#define UUENC(c) (((c)!=0) ? ((c) & 077) + ' ': '`')
+/* XXX This could be a lot more efficient. XXX */
static void
uuencode_group(struct shar *shar)
{
@@ -443,6 +459,8 @@ archive_write_shar_finish(struct archive *a)
archive_entry_free(shar->entry);
if (shar->last_dir != NULL)
free(shar->last_dir);
+ if (shar->work != NULL)
+ free(shar->work);
free(shar);
a->format_data = NULL;
return (ARCHIVE_OK);
OpenPOWER on IntegriCloud