diff options
author | Lennart Poettering <lennart@poettering.net> | 2003-08-30 13:10:12 +0000 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2003-08-30 13:10:12 +0000 |
commit | 2c2c89575688a5ccac7032401df5a58b87f49aad (patch) | |
tree | fe2c034620b60f0512463dca330f994b48640cb8 /src/util.c | |
parent | db3b96fc0014a5e860df1efc729b38d629662826 (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.c | 383 |
1 files changed, 271 insertions, 112 deletions
@@ -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; +} |