summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2003-08-26 23:47:55 +0000
committerLennart Poettering <lennart@poettering.net>2003-08-26 23:47:55 +0000
commitbb40f092719dbcdb635bae3e40c4ec1c3b88cf3b (patch)
tree013bd6613e4b1583409adff5fd04fb7d6cb6da6d /src
parent3bc3ad24a2c089b4ee80fc1765fab3d2af378d00 (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.c121
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);
+}