summaryrefslogtreecommitdiffstats
path: root/src/util.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2003-08-30 13:10:12 +0000
committerLennart Poettering <lennart@poettering.net>2003-08-30 13:10:12 +0000
commit2c2c89575688a5ccac7032401df5a58b87f49aad (patch)
treefe2c034620b60f0512463dca330f994b48640cb8 /src/util.c
parentdb3b96fc0014a5e860df1efc729b38d629662826 (diff)
package.c rewrite
git-svn-id: file:///home/lennart/svn/public/syrep/trunk@14 07ea20a6-d2c5-0310-9e02-9ef735347d72
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c383
1 files changed, 271 insertions, 112 deletions
diff --git a/src/util.c b/src/util.c
index f0d66d1..7067428 100644
--- a/src/util.c
+++ b/src/util.c
@@ -18,7 +18,7 @@
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
***/
-#define USE_SENDFILE
+//#define USE_SENDFILE
#include <stdio.h>
#include <assert.h>
@@ -115,29 +115,32 @@ void rotdash_hide(void) {
fputs(" \b", stderr);
}
-const char* get_snapshot_filename(const char *path, const char *fn) {
+const char* get_attached_filename(const char *root, const char *fn) {
static char npath[PATH_MAX];
+ snprintf(npath, sizeof(npath), "%s/.syrep", root);
+ mkdir(npath, 0777);
+ snprintf(npath, sizeof(npath), "%s/.syrep/%s", root, fn);
+ return npath;
+}
+
+const char* get_snapshot_filename(const char *root, const char *fn) {
struct stat st;
- if (stat(path, &st) < 0) {
+ if (stat(root, &st) < 0) {
if (errno == ENOENT)
- return path;
+ return root;
- fprintf(stderr, "stat(%s) failed: %s\n", path, strerror(errno));
+ fprintf(stderr, "stat(%s) failed: %s\n", root, strerror(errno));
return NULL;
}
if (S_ISREG(st.st_mode))
- return path;
+ return root;
- if (S_ISDIR(st.st_mode)) {
- snprintf(npath, sizeof(npath), "%s/.syrep", path);
- mkdir(npath, 0777);
- snprintf(npath, sizeof(npath), "%s/.syrep/%s", path, fn);
- return npath;
- }
+ if (S_ISDIR(st.st_mode))
+ return get_attached_filename(root, fn);
- fprintf(stderr, "<%s> is not a valid syrep snapshot\n", path);
+ fprintf(stderr, "<%s> is not a valid syrep snapshot\n", root);
return NULL;
}
@@ -151,149 +154,271 @@ int isdirectory(const char *path) {
}
-#define MMAPSIZE (100*1024*1024)
-#define BUFSIZE (1024*1024)
-
-int copy_fd(int sfd, int dfd, uint32_t l) {
- off_t src_o, dst_o;
- void *src_p, *dst_p;
- void *buf = NULL;
- int r = -1;
- struct stat st;
#ifdef USE_SENDFILE
- ssize_t k;
- off_t sfo;
-#endif
- if ((src_o = lseek(sfd, 0, SEEK_CUR)) == (off_t) -1) {
- fprintf(stderr, "lseek(): %s\n", strerror(errno));
- goto finish;
- }
+static int copy_fd_sendfile(int sfd, int dfd, uint32_t l) {
+ off_t sfo, o;
+ ssize_t r;
- if (fstat(sfd, &st) < 0) {
- fprintf(stderr, "fstat(): %s\n", strerror(errno));
- goto finish;
- }
+ if ((sfo = lseek(sfd, 0, SEEK_CUR)) == (off_t) -1)
+ o = 0;
+ else
+ o = sfo;
+
+ if ((r = sendfile(dfd, sfd, &o, l)) != l)
+ return -1;
- if (l == (uint32_t) -1 || l >= st.st_size - src_o)
- l = st.st_size - src_o;
+ if (sfo != (off_t) -1) {
+ sfo += r;
- if ((dst_o = lseek(dfd, 0, SEEK_CUR)) == (off_t) -1) {
- fprintf(stderr, "lseek(): %s\n", strerror(errno));
- goto finish;
+ lseek(sfd, sfo, SEEK_SET);
}
+
+ return 0;
+}
+
+#endif
- if (fstat(dfd, &st) < 0) {
- fprintf(stderr, "fstat(): %s\n", strerror(errno));
- goto finish;
+
+int filesize(int fd) {
+ struct stat st;
+
+ if (fstat(fd, &st) < 0) {
+ fprintf(stderr, "stat(): %s\n", strerror(errno));
+ return -1;
}
+
+ return st.st_size;
+}
+
+int expand_file(int fd, size_t l) {
+ size_t s;
+
+ if ((s = filesize(fd)) < 0)
+ return -1;
- if (dst_o+l > st.st_size)
- if (ftruncate(dfd, dst_o+l) < 0) {
+ if (s < l)
+ if (ftruncate(fd, l) < 0) {
fprintf(stderr, "ftruncate(): %s\n", strerror(errno));
- goto finish;
+ return -1;
}
-
-#ifdef USE_SENDFILE
+ return 0;
+}
- sfo = src_o;
- if ((k = sendfile(dfd, sfd, &sfo, l)) > 0) {
+#define MMAPSIZE (100*1024*1024)
+#define BUFSIZE (32*1024)
- l -= k;
- dst_o += k;
- src_o = sfo;
-
- if (lseek(sfd, src_o, SEEK_SET) == (off_t) -1) {
- fprintf(stderr, "lseek(): %s\n", strerror(errno));
- goto finish;
- }
- } else if (k < 0)
- fprintf(stderr, "sendfile() failed for file copy, trying mmap(): %s\n", strerror(errno));
+int copy_fd(int sfd, int dfd, size_t l) {
+ off_t sfo, dfo, msfo, mdfo;
+ void *sp, *dp;
+ size_t m, sm, dm;
+ static size_t psize = 0;
+#ifdef USE_SENDFILE
+ if (!copy_fd_sendfile(sfd, dfd, l))
+ return 0;
#endif
+ //fprintf(stderr, "copy_fd(%u)\n", l);
+
+ if (psize == 0)
+ psize = sysconf(_SC_PAGESIZE);
+
+ sp = dp = MAP_FAILED;
+
if (l > BUFSIZE) {
- uint32_t m = l < MMAPSIZE ? l : MMAPSIZE;
- while (l > 0) {
- if ((src_p = mmap(NULL, m, PROT_READ, MAP_SHARED, sfd, src_o)) == MAP_FAILED)
- break;
+ m = l < MMAPSIZE ? l : MMAPSIZE;
+
+ if ((sfo = lseek(sfd, 0, SEEK_CUR)) != (off_t) -1) {
+ size_t s;
- if ((dst_p = mmap(NULL, m, PROT_READ|PROT_WRITE, MAP_SHARED, dfd, dst_o)) == MAP_FAILED) {
- munmap(src_p, m);
- break;
+ if ((s = filesize(sfd)) < 0)
+ return -1;
+
+ if (s < sfo+l) {
+ fprintf(stderr, "File too short (%u vs. %lu %i)\n", s, sfo+l, l);
+ return -1;
}
+
+ msfo = (sfo/psize)*psize;
+ sm = m+(sfo-msfo);
+ sp = mmap(NULL, sm, PROT_READ, MAP_SHARED, sfd, msfo);
+ }
+
+ if ((dfo = lseek(dfd, 0, SEEK_CUR)) != (off_t) -1) {
+ if (expand_file(dfd, dfo+l) < 0)
+ return -1;
+
+ mdfo = (dfo/psize)*psize;
+ dm = m+(dfo-mdfo);
+ dp = mmap(NULL, dm, PROT_READ|PROT_WRITE, MAP_SHARED, dfd, mdfo);
+ }
+
+ }
+
+ if (sp == MAP_FAILED && dp == MAP_FAILED) { /* copy fd to fd */
+ void *buf = NULL;
+
+ if (!(buf = malloc(BUFSIZE))) {
+ fprintf(stderr, "malloc(): %s\n", strerror(errno));
+ return -1;
+ }
+
+ while (l > 0) {
+ ssize_t n;
- memcpy(dst_p, src_p, m);
+ m = l > BUFSIZE ? BUFSIZE : l;
- munmap(src_p, m);
- munmap(dst_p, m);
+ if ((n = loop_read(sfd, buf, m)) != m) {
+
+ if (n < 0)
+ fprintf(stderr, "read(): %s\n", strerror(errno));
+ else
+ fprintf(stderr, "Short read\n");
- if (interrupted) {
- fprintf(stderr, "Canceled.\n");
- goto finish;
+ free(buf);
+ return -1;
+ }
+
+ if ((n = loop_write(dfd, buf, m)) != m) {
+
+ if (n < 0)
+ fprintf(stderr, "write(): %s\n", strerror(errno));
+ else
+ fprintf(stderr, "Short write\n");
+
+ free(buf);
+ return -1;
+ }
+
+ l -= m;
+ }
+
+ free(buf);
+ return 0;
+ } else if (sp == MAP_FAILED) { /* copy fd to mmap */
+
+ for (;;) {
+ ssize_t n;
+
+ n = loop_read(sfd, dp+(dfo-mdfo), m);
+ munmap(dp, dm);
+
+ if (n != m) {
+
+ if (n < 0)
+ fprintf(stderr, "read(): %s\n", strerror(errno));
+ else
+ fprintf(stderr, "Short read\n");
+
+ return -1;
}
- src_o += m;
- dst_o += m;
+
l -= m;
+ dfo += m;
+
+ if (l <= 0) {
+ if (lseek(dfd, dfo, SEEK_SET) == (off_t) -1)
+ return -1;
+
+ return 0;
+ }
- m = l < MMAPSIZE ? l : MMAPSIZE;
+ mdfo = (dfo/psize)*psize;
+ dm = m+(dfo-mdfo);
+ if ((dp = mmap(NULL, dm, PROT_READ|PROT_WRITE, MAP_SHARED, dfd, mdfo)) == MAP_FAILED) {
+ fprintf(stderr, "mmap(): %s\n", strerror(errno));
+ return -1;
+ }
+
}
+
-
- if (lseek(sfd, src_o, SEEK_SET) == (off_t) -1) {
- fprintf(stderr, "lseek(): %s\n", strerror(errno));
- goto finish;
+ } else if (dp == MAP_FAILED) { /* copy mmap to fd */
+
+ for (;;) {
+ ssize_t n;
+
+ n = loop_write(dfd, sp+(sfo-msfo), m);
+ munmap(sp, sm);
+
+ if (n != m) {
+
+ if (n < 0)
+ fprintf(stderr, "write(): %s\n", strerror(errno));
+ else
+ fprintf(stderr, "Short write\n");
+
+ return -1;
+ }
+
+ l -= m;
+ sfo += m;
+
+ if (l <= 0) {
+ if (lseek(sfd, sfo, SEEK_SET) == (off_t) -1)
+ return -1;
+
+ return 0;
+ }
+
+ msfo = (sfo/psize)*psize;
+ sm = m+(sfo-msfo);
+ if ((sp = mmap(NULL, sm, PROT_READ, MAP_SHARED, sfd, msfo)) == MAP_FAILED) {
+ fprintf(stderr, "mmap(): %s\n", strerror(errno));
+ return -1;
+ }
}
- if (lseek(dfd, dst_o, SEEK_SET) == (off_t) -1) {
- fprintf(stderr, "lseek(): %s\n", strerror(errno));
- goto finish;
- }
-
- if (l > 0)
- fprintf(stderr, "mmap() failed for file copy, trying read()/write(): %s\n", strerror(errno));
- }
-
- if (l > 0) {
- if (!(buf = malloc(BUFSIZE)))
- goto finish;
+
+ } else { /* copy mmap to mmap */
for (;;) {
- ssize_t m;
- if (interrupted) {
- fprintf(stderr, "Canceled.\n");
- goto finish;
- }
+ memcpy(dp+(dfo-mdfo), sp+(sfo-msfo), m);
+
+ munmap(sp, sm);
+ munmap(dp, dm);
+
+ l -= m;
+ sfo += m;
+ dfo += m;
- if ((m = read(sfd, buf, BUFSIZE)) < 0) {
- fprintf(stderr, "read(): %s\n", strerror(errno));
- goto finish;
+ if (l <= 0) {
+
+ if (lseek(sfd, sfo, SEEK_SET) == (off_t) -1)
+ return -1;
+
+ if (lseek(dfd, dfo, SEEK_SET) == (off_t) -1)
+ return -1;
+
+ return 0;
}
- if (!m)
- break;
-
- if (write(dfd, buf, m) < 0) {
- fprintf(stderr, "write(): %s\n", strerror(errno));
- goto finish;
+ msfo = (sfo/psize)*psize;
+ sm = m+(sfo-msfo);
+ if ((sp = mmap(NULL, sm, PROT_READ, MAP_SHARED, sfd, msfo)) == MAP_FAILED) {
+ fprintf(stderr, "mmap(): %s\n", strerror(errno));
+ return -1;
+ }
+
+ mdfo = (dfo/psize)*psize;
+ dm = m+(dfo-mdfo);
+ if ((dp = mmap(NULL, dm, PROT_READ|PROT_WRITE, MAP_SHARED, dfd, mdfo)) == MAP_FAILED) {
+ fprintf(stderr, "mmap(): %s\n", strerror(errno));
+ return -1;
}
}
}
-
- r = 0;
-
-finish:
-
- return r;
}
int copy_file(const char *src, const char *dst, int c) {
int sfd = -1, dfd = -1, r = -1;
-
+ size_t size;
+
if ((sfd = open(src, O_RDONLY)) < 0) {
fprintf(stderr, "open(\"%s\", O_RDONLY): %s\n", src, strerror(errno));
goto finish;
@@ -304,7 +429,10 @@ int copy_file(const char *src, const char *dst, int c) {
goto finish;
}
- if (copy_fd(sfd, dfd, (uint32_t) -1) < 0)
+ if ((size = filesize(sfd)) < 0)
+ goto finish;
+
+ if (copy_fd(sfd, dfd, size) < 0)
goto finish;
r = 0;
@@ -570,3 +698,34 @@ finish:
return r;
}
+ssize_t loop_read(int fd, void *d, size_t l) {
+ void *p = d;
+
+ while (l > 0) {
+ ssize_t r;
+
+ if ((r = read(fd, p, l)) <= 0)
+ return p-d > 0 ? p-d : r;
+
+ p += r;
+ l -= r;
+ }
+
+ return p-d;
+}
+
+ssize_t loop_write(int fd, void *d, size_t l) {
+ void *p = d;
+
+ while (l > 0) {
+ ssize_t r;
+
+ if ((r = write(fd, p, l)) <= 0)
+ return p-d > 0 ? p-d : r;
+
+ p += r;
+ l -= r;
+ }
+
+ return p-d;
+}