Begin work on an alternate object store mechanism using the TAR format.
[cumulus.git] / tarstore.cc
1 /* LBS: An LFS-inspired filesystem backup system
2  * Copyright (C) 2006  Michael Vrable
3  *
4  * Backup data is stored in a collection of objects, which are grouped together
5  * into segments for storage purposes.  This implementation of the object store
6  * is built on top of libtar, and represents segments as TAR files and objects
7  * as files within them. */
8
9 #include <stdio.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <unistd.h>
13 #include <fcntl.h>
14 #include <time.h>
15 #include <uuid/uuid.h>
16
17 #include <string>
18
19 #include "tarstore.h"
20
21 using std::string;
22
23 Tarfile::Tarfile(const string &path, const string &segment)
24     : segment_name(segment)
25 {
26     if (tar_open(&t, (char *)path.c_str(), NULL, O_WRONLY | O_CREAT, 0600,
27                  TAR_VERBOSE | TAR_GNU) == -1)
28         throw IOException("Error opening Tarfile");
29 }
30
31 Tarfile::~Tarfile()
32 {
33     tar_append_eof(t);
34
35     if (tar_close(t) != 0)
36         throw IOException("Error closing Tarfile");
37 }
38
39 void Tarfile::write_object(int id, const char *data, size_t len)
40 {
41     memset(&t->th_buf, 0, sizeof(struct tar_header));
42
43     char buf[64];
44     sprintf(buf, "%08x", id);
45     string path = segment_name + "/" + buf;
46     printf("path: %s\n", path.c_str());
47
48     th_set_type(t, S_IFREG | 0600);
49     th_set_user(t, 0);
50     th_set_group(t, 0);
51     th_set_mode(t, 0600);
52     th_set_size(t, len);
53     th_set_mtime(t, time(NULL));
54     th_set_path(t, const_cast<char *>(path.c_str()));
55     th_finish(t);
56
57     if (th_write(t) != 0)
58         throw IOException("Error writing tar header");
59
60     th_print(t);
61
62     if (len == 0)
63         return;
64
65     size_t blocks = (len + T_BLOCKSIZE - 1) / T_BLOCKSIZE;
66     size_t padding = blocks * T_BLOCKSIZE - len;
67
68     for (size_t i = 0; i < blocks - 1; i++) {
69         if (tar_block_write(t, &data[i * T_BLOCKSIZE]) == -1)
70             throw IOException("Error writing tar block");
71     }
72
73     char block[T_BLOCKSIZE];
74     memset(block, 0, sizeof(block));
75     memcpy(block, &data[T_BLOCKSIZE * (blocks - 1)], T_BLOCKSIZE - padding);
76     if (tar_block_write(t, block) == -1)
77         throw IOException("Error writing final tar block");
78 }