[tar] Improve performance of -c/-x/-t.
* Fixes performance of -c and -x by increasing the buffer size
from 512 bytes to 8192 bytes.
* Fixes performance of -t by using lseek instead of reading the data.
* Prevents incorrect error message when trying to remove a directory
that contains files.
* Filed related bugs US-291, US-293 and US-294.
US-295 #done
Change-Id: Id971750fa6bd6d45c27bef65b72986eb20d3db70
diff --git a/tar.c b/tar.c
index 71719b0..7f2eccc 100644
--- a/tar.c
+++ b/tar.c
@@ -16,6 +16,8 @@
#include "util.h"
#define BLKSIZ 512
+// COPY_CHUNK_SIZE must be a power of 2
+#define COPY_CHUNK_SIZE 8192
enum Type {
REG = '0',
@@ -236,10 +238,13 @@
ewrite(tarfd, b, BLKSIZ);
if (fd != -1) {
- while ((l = eread(fd, b, BLKSIZ)) > 0) {
- if (l < BLKSIZ)
- memset(b + l, 0, BLKSIZ - l);
- ewrite(tarfd, b, BLKSIZ);
+ char chunk[COPY_CHUNK_SIZE];
+ while ((l = eread(fd, chunk, COPY_CHUNK_SIZE)) > 0) {
+ // Ceiling to BLKSIZ boundary
+ int ceilsize = (l + (BLKSIZ-1)) & ~(BLKSIZ-1);
+ if (l < ceilsize)
+ memset(chunk + l, 0, ceilsize - l);
+ ewrite(tarfd, chunk, ceilsize);
}
close(fd);
}
@@ -258,7 +263,7 @@
if (!mflag && ((mtime = strtol(h->mtime, &p, 8)) < 0 || *p != '\0'))
eprintf("strtol %s: invalid number\n", h->mtime);
- if (remove(fname) < 0 && errno != ENOENT)
+ if (remove(fname) < 0 && errno != ENOENT && errno != ENOTEMPTY)
weprintf("remove %s:", fname);
tmp = estrdup(fname);
@@ -319,9 +324,17 @@
eprintf("strtol %s: invalid number\n", h->gid);
if (fd != -1) {
- for (; l > 0; l -= BLKSIZ)
- if (eread(tarfd, b, BLKSIZ) > 0)
- ewrite(fd, b, MIN(l, BLKSIZ));
+ char chunk[COPY_CHUNK_SIZE];
+ for (; l > 0; l -= COPY_CHUNK_SIZE) {
+ // Ceiling to BLKSIZ boundary
+ int ceilsize = (MIN(l, COPY_CHUNK_SIZE) + (BLKSIZ-1)) & ~(BLKSIZ-1);
+ if (eread(tarfd, chunk, ceilsize) != ceilsize) {
+ close(fd);
+ remove(fname);
+ eprintf("unexpected end of file reading %s.\n", fname);
+ }
+ ewrite(fd, chunk, ceilsize);
+ }
close(fd);
}
@@ -331,7 +344,7 @@
times[0].tv_sec = times[1].tv_sec = mtime;
times[0].tv_nsec = times[1].tv_nsec = 0;
if (!mflag && utimensat(AT_FDCWD, fname, times, AT_SYMLINK_NOFOLLOW) < 0)
- weprintf("utimensat %s:\n", fname);
+ weprintf("utimensat %s %d:\n", fname, errno);
if (h->type == SYMLINK) {
if (!getuid() && lchown(fname, uid, gid))
weprintf("lchown %s:\n", fname);
@@ -348,11 +361,11 @@
static void
skipblk(ssize_t l)
{
- char b[BLKSIZ];
-
- for (; l > 0; l -= BLKSIZ)
- if (!eread(tarfd, b, BLKSIZ))
- break;
+ // Ceiling to the next BLKSIZ boundary
+ int ceilsize = (l + (BLKSIZ-1)) & ~(BLKSIZ-1);
+ if (lseek(tarfd, ceilsize, SEEK_CUR) == -1) {
+ eprintf("unexpected end of file.\n");
+ }
}
static int