diff options
author | Lennart Poettering <lennart@poettering.net> | 2003-08-26 23:47:55 +0000 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2003-08-26 23:47:55 +0000 |
commit | bb40f092719dbcdb635bae3e40c4ec1c3b88cf3b (patch) | |
tree | 013bd6613e4b1583409adff5fd04fb7d6cb6da6d /src | |
parent | 3bc3ad24a2c089b4ee80fc1765fab3d2af378d00 (diff) |
Added extract.[ch]
git-svn-id: file:///home/lennart/svn/public/syrep/trunk@3 07ea20a6-d2c5-0310-9e02-9ef735347d72
Diffstat (limited to 'src')
-rw-r--r-- | src/extract.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/extract.c b/src/extract.c new file mode 100644 index 0000000..06d95df --- /dev/null +++ b/src/extract.c @@ -0,0 +1,121 @@ +#include <sys/mman.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <sys/stat.h> +#include <stdint.h> +#include <stdio.h> + +#include "package.h" +#include "extract.h" + +#define MMAPSIZE (100*1024*1024) +#define BUFSIZE (1024*1024) + +int copy_file(const char *src, const char *dst, uint32_t l) { + int sfd = -1, dfd = -1, r = -1; + uint32_t m; + off_t o; + void *src_p, *dst_p; + void *buf = NULL; + + if ((sfd = open(src, O_RDONLY)) < 0) { + fprintf(stderr, "open(%s, O_RDONLY): %s\n", src, strerror(errno)); + goto finish; + } + + if ((dfd = open(dst, O_RDWR|O_TRUNC|O_CREAT, 0666)) < 0) { + fprintf(stderr, "open(%s, O_WRONLY): %s\n", dst, strerror(errno)); + goto finish; + } + + if (ftruncate(dfd, l) < 0) { + fprintf(stderr, "ftruncate(): %s\n", strerror(errno)); + goto finish; + } + + o = 0; + m = l < MMAPSIZE ? l : MMAPSIZE; + + while (l > 0) { + if ((src_p = mmap(NULL, m, PROT_READ, MAP_SHARED, sfd, o)) == MAP_FAILED) + break; + + if ((dst_p = mmap(NULL, m, PROT_READ|PROT_WRITE, MAP_SHARED, dfd, o)) == MAP_FAILED) { + munmap(src_p, m); + break; + } + + memcpy(dst_p, src_p, m); + + munmap(src_p, m); + munmap(dst_p, m); + + o += m; + l -= m; + m = l < MMAPSIZE ? l : MMAPSIZE; + } + + if (l > 0) { + fprintf(stderr, "mmap() failed: %s\n", strerror(errno)); + + if (!(buf = malloc(BUFSIZE))) + goto finish; + + for (;;) { + ssize_t r; + + if ((m = read(sfd, buf, BUFSIZE)) < 0) { + fprintf(stderr, "read(): %s\n", strerror(errno)); + goto finish; + } + + if (!m) + break; + + if ((r = write(dfd, buf, m)) < 0) { + fprintf(stderr, "write(): %s\n", strerror(errno)); + goto finish; + } + } + } + + + r = 0; + +finish: + + if (sfd >= 0) + close(sfd); + + if (dfd >= 0) + close(dfd); + + return r; +} + +static int cb(struct package *p, const char *name, const char *path, void *u) { + struct stat st; + uint32_t size; + + if (stat(path, &st) < 0) { + if (errno == ENOENT) + size = 0; + else { + fprintf(stderr, "stat(%s) failed: %s\n", path, strerror(errno)); + return -1; + } + } else + size = (uint32_t) st.st_size; + + if (size) + return copy_file(path, name, size); + + return 0; +} + +int extract(struct syrep_db_context *context) { + return package_foreach(context->package, cb, NULL); +} |