aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Kientzle <kientzle@FreeBSD.org>2004-05-17 07:35:52 +0000
committerTim Kientzle <kientzle@FreeBSD.org>2004-05-17 07:35:52 +0000
commit9d77c5f29c78660c158745fdaf2a46ce47a00364 (patch)
treed35afa22234fd34b1bafc163c14e28b855b3752d
parentef1eb2f33085d4d5cf9a6062e7a443ad51e180ca (diff)
downloadsrc-9d77c5f29c78660c158745fdaf2a46ce47a00364.tar.gz
src-9d77c5f29c78660c158745fdaf2a46ce47a00364.zip
Speed up safe_fprintf by copying to a temp buffer, then writing
blocks at a time, rather than using putc().
Notes
Notes: svn path=/head/; revision=129324
-rw-r--r--usr.bin/tar/util.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/usr.bin/tar/util.c b/usr.bin/tar/util.c
index 46bc72608074..df22404cb846 100644
--- a/usr.bin/tar/util.c
+++ b/usr.bin/tar/util.c
@@ -54,7 +54,9 @@ safe_fprintf(FILE *f, const char *fmt, ...)
int length;
va_list ap;
char *p;
+ unsigned i;
char buff_stack[256];
+ char copy_buff[256];
/* Use a stack-allocated buffer if we can, for speed and safety. */
buff_heap = NULL;
@@ -77,27 +79,44 @@ safe_fprintf(FILE *f, const char *fmt, ...)
}
}
- for (p=buff; *p != '\0'; p++) {
- unsigned char c = *p;
+ /* Write data, expanding unprintable characters. */
+ p = buff;
+ i = 0;
+ while (*p != '\0') {
+ unsigned char c = *p++;
+
if (isprint(c) && c != '\\')
- putc(c, f);
- else
+ copy_buff[i++] = c;
+ else {
+ copy_buff[i++] = '\\';
switch (c) {
- case '\a': putc('\\', f); putc('a', f); break;
- case '\b': putc('\\', f); putc('b', f); break;
- case '\f': putc('\\', f); putc('f', f); break;
- case '\n': putc('\\', f); putc('n', f); break;
+ case '\a': copy_buff[i++] = 'a'; break;
+ case '\b': copy_buff[i++] = 'b'; break;
+ case '\f': copy_buff[i++] = 'f'; break;
+ case '\n': copy_buff[i++] = 'n'; break;
#if '\r' != '\n'
/* On some platforms, \n and \r are the same. */
- case '\r': putc('\\', f); putc('r', f); break;
+ case '\r': copy_buff[i++] = 'r'; break;
#endif
- case '\t': putc('\\', f); putc('t', f); break;
- case '\v': putc('\\', f); putc('v', f); break;
- case '\\': putc('\\', f); putc('\\', f); break;
+ case '\t': copy_buff[i++] = 't'; break;
+ case '\v': copy_buff[i++] = 'v'; break;
+ case '\\': copy_buff[i++] = '\\'; break;
default:
- fprintf(f, "\\%03o", c);
+ sprintf(copy_buff + i, "%03o", c);
+ i += 3;
}
+ }
+
+ /* If our temp buffer is full, dump it and keep going. */
+ if (i > (sizeof(copy_buff) - 8)) {
+ copy_buff[i++] = '\0';
+ fprintf(f, "%s", copy_buff);
+ i = 0;
+ }
}
+ copy_buff[i++] = '\0';
+ fprintf(f, "%s", copy_buff);
+
/* If we allocated a heap-based buffer, free it now. */
if (buff_heap != NULL)
free(buff_heap);