3
3
* Licensed under the GPL
6
#define _XOPEN_SOURCE 500
12
15
#include <byteswap.h>
13
16
#include <sys/stat.h>
14
17
#include <sys/types.h>
15
18
#include <sys/param.h>
16
#include <netinet/in.h>
18
#if __BYTE_ORDER == __BIG_ENDIAN
19
# define ntohll(x) (x)
20
# define htonll(x) (x)
21
#elif __BYTE_ORDER == __LITTLE_ENDIAN
22
# define ntohll(x) bswap_64(x)
23
# define htonll(x) bswap_64(x)
25
#error "__BYTE_ORDER not defined"
28
typedef long long u64;
30
/* XXX All these fields should be word-length independent */
32
struct cow_header_common {
34
unsigned long version;
37
/* taken from ubd_user.c */
39
#define PATH_LEN_V1 256
41
struct cow_header_v1 {
42
struct cow_header_common common;
43
char backing_file[PATH_LEN_V1];
49
#define PATH_LEN_V2 MAXPATHLEN
51
struct cow_header_v2 {
52
struct cow_header_common common;
53
char backing_file[PATH_LEN_V2];
60
struct cow_header_v1 v1;
61
struct cow_header_v2 v2;
64
#define COW_MAGIC 0x4f4f4f4d /* mooo */
67
21
static inline int ubd_test_bit(int bit, unsigned long *data)
84
38
data[n] |= (1 << off);
87
static void sizes(u64 size, int sectorsize, int bitmap_offset,
88
int *bitmap_len_out, int *data_offset_out)
90
*bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
92
*data_offset_out = bitmap_offset + *bitmap_len_out;
93
*data_offset_out = (*data_offset_out + sectorsize - 1) / sectorsize;
94
*data_offset_out *= sectorsize;
97
int create_backing_file(int argc, char *argv[])
41
int create_backing_file(char *in, char *out, char *actual_backing)
101
43
int cow_fd, back_fd, in_fd, out_fd;
103
45
unsigned long *bitmap;
109
union cow_header header;
110
struct cow_header_common common;
46
unsigned long bitmap_len;
49
__u64 size, offset, i; /* i is u64 to prevent 32 bit overflow */
50
__u32 version, alignment;
112
unsigned long magic, version;
113
52
char *backing_file;
116
int sectorsize, bitmap_offset;
54
int sectorsize, bitmap_offset, perms, n;
118
56
if((cow_fd = open(in, O_RDONLY)) < 0){
119
57
perror("COW file open");
122
if((out_fd = creat(out, 0644)) < 0){
123
perror("Output file open");
127
if(read(cow_fd, &common, sizeof(common)) != sizeof(common)){
128
perror("COW common header read");
131
if(lseek64(cow_fd, 0, SEEK_SET) != 0){
132
perror("seeking back to COW file start");
136
magic = common.magic;
137
if(magic == COW_MAGIC) version = common.version;
138
else if(magic == ntohl(COW_MAGIC)) version = ntohl(common.version);
140
fprintf(stderr,"magic number (0x%x) doesn't match COW_MAGIC "
141
"(0x%x)\n", (unsigned int) magic, COW_MAGIC);
146
if(read(cow_fd, &header.v1, sizeof(header.v1)) !=
148
perror("Reading full V1 COW header");
151
backing_file = header.v1.backing_file;
152
size = header.v1.size;
153
mtime = header.v1.mtime;
154
sectorsize = header.v1.sectorsize;
155
bitmap_offset = sizeof(header.v1);
157
else if(version == 2){
158
if(read(cow_fd, &header.v2, sizeof(header.v2)) !=
160
perror("Reading full V2 COW header");
163
backing_file = header.v2.backing_file;
164
size = ntohll(header.v2.size);
165
mtime = ntohl(header.v2.mtime);
166
sectorsize = ntohl(header.v2.sectorsize);
167
bitmap_offset = sizeof(header.v2);
170
fprintf(stderr,"Unknown version %ld\n", version);
174
if(stat64(backing_file, &buf) < 0) {
61
if(read_cow_header(file_reader, &cow_fd, &version, &backing_file,
62
&mtime, &size, §orsize, &alignment,
64
fprintf(stderr, "Reading COW header failed\n");
68
if(actual_backing != NULL)
69
backing_file = actual_backing;
71
if(stat(backing_file, &buf) < 0) {
175
72
perror("Stating backing file");
178
76
if(buf.st_size != size){
179
77
fprintf(stderr,"Size mismatch (%ld vs %ld) of COW header "
180
"vs backing file\n", (long int) buf.st_size,
78
"vs backing file \"%s\"\n", (long int) size,
79
(long int) buf.st_size, backing_file);
184
82
if(buf.st_mtime != mtime) {
185
83
fprintf(stderr,"mtime mismatch (%ld vs %ld) of COW "
186
"header vs backing file\n", buf.st_mtime,
84
"header vs backing file \"%s\"\n", mtime, buf.st_mtime,
191
if((back_fd = open(backing_file, O_RDONLY)) < 0){
89
perms = (out != NULL) ? O_RDONLY : O_RDWR;
91
if((back_fd = open(backing_file, perms)) < 0){
192
92
perror("Opening backing file");
196
sizes(size, sectorsize, bitmap_offset, &bitmap_len, &data_offset);
97
if((out_fd = creat(out, 0644)) < 0){
98
perror("Output file open");
102
else out_fd = back_fd;
104
cow_sizes(version, size, sectorsize, alignment, bitmap_offset,
105
&bitmap_len, &data_offset);
198
107
bitmap = (unsigned long *) malloc(bitmap_len);
199
108
if(bitmap == NULL) {
204
if(lseek64(cow_fd, bitmap_offset, SEEK_SET) < 0){
205
perror("Seeking to COW bitmap");
209
if(read(cow_fd, bitmap, bitmap_len) != bitmap_len){
113
if(pread(cow_fd, bitmap, bitmap_len, bitmap_offset) != bitmap_len){
210
114
perror("Reading COW bitmap");
214
blocks = bitmap_len * 8;
215
block = (char *) malloc(sectorsize);
217
perror("Malloc of buffer");
118
sectors = size / sectorsize;
119
sector = malloc(sectorsize);
120
zeros = malloc(sectorsize);
121
if((sector == NULL) || (zeros == NULL)){
122
perror("Malloc of buffers");
221
for(i = 0; i < blocks; i++){
126
memset(zeros, 0, sectorsize);
128
for(i = 0; i < sectors; i++){
222
129
offset = i * sectorsize;
223
if(ubd_test_bit(i,bitmap)){
130
if(ubd_test_bit(i, bitmap)){
224
131
offset += data_offset;
227
134
else in_fd = back_fd;
228
if(lseek64(in_fd, offset, SEEK_SET) < 0){
229
perror("Seeking into data");
233
if(read(in_fd, block, sectorsize) != sectorsize){
136
/* If we're doing a destructive merge, and the backing file
137
* sector is up to date, then there's nothing to do.
139
if((out_fd == back_fd) && (in_fd == back_fd))
142
if(pread(in_fd, sector, sectorsize, offset) != sectorsize){
234
143
perror("Reading data");
238
if(write(out_fd, block, sectorsize) != sectorsize){
147
/* Sparse file creation - if the sector is all zeros and it's
148
* not the last sector (which always gets written out in order
149
* to make the file size right), maybe it doesn't need to be
153
if((i < sectors - 1) && !memcmp(sector, zeros, sectorsize)){
154
/* If we're doing a non-destructive merge, then zero
155
* sectors can just be skipped.
157
if(out_fd != back_fd)
160
/* Otherwise, we are doing a destructive merge, and
161
* we need to check the backing file for a zero
164
n = pread(back_fd, sector, sectorsize, i * sectorsize);
166
perror("Checking backing file for zeros");
170
if(!memcmp(sector, zeros, sectorsize))
173
/* The backing file sector isn't zeros, so the sector
174
* of zeros in the COW file needs to be written out.
176
memset(sector, 0, sectorsize);
179
/* The offset can't be 'offset' because that's used as an
180
* input offset, which may be offset by the COW header.
182
n = pwrite(out_fd, sector, sectorsize, i * sectorsize);
239
184
perror("Writing data");
251
int usage(char *prog) {
252
printf("%s usage:\n",prog);
253
printf("%s <COW file> <new backing file>\n", prog);
254
printf("creates a new filesystem image from the COW file and its.\n");
255
printf("backing file.\n");
256
printf("%s supports version 1 and 2 COW files.\n", prog);
197
static char *usage_string =
199
"\t%s [ -b <actual backing file> ] <COW file> <new backing file>\n"
200
"\t%s [ -b <actual backing file> ] -d <COW file>\n"
201
"Creates a new filesystem image from the COW file and its backing file.\n"
202
"Specifying -d will cause a destructive, in-place merge of the COW file into\n"
203
"its current backing file\n"
204
"Specifying -b overrides the backing_file specified in the COW file. This is\n"
205
"needed when dealing with a COW file that was created inside a chroot jail.\n"
206
"%s supports version 1 and 2 COW files.\n"
209
static int Usage(char *prog) {
210
fprintf(stderr, usage_string, prog, prog, prog, prog);
260
214
int main(int argc, char **argv)
262
if(argc == 3) create_backing_file(argc, argv);
216
char *prog = argv[0];
217
char *actual_backing_file = NULL;
226
if(!strcmp(argv[0], "-d")){
232
if(!strcmp(argv[0], "-b")){
233
actual_backing_file = argv[1];
239
if(argc != 1) Usage(prog);
240
create_backing_file(argv[0], NULL, actual_backing_file);
243
if(argc != 2) Usage(prog);
244
create_backing_file(argv[0], argv[1], actual_backing_file);