#include #include #include #include #include #include #include #include #include #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); }