blob: ffe4dff9fe69bdf90fe6334d76eea101ef4f747d [file] [log] [blame]
Joe Onorato4535e402009-05-15 09:07:06 -04001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Joe Onorato3ad977b2009-05-05 11:50:51 -070017#define LOG_TAG "file_backup_helper"
18
Mathias Agopian8ae23352009-06-04 13:53:57 -070019#include <utils/BackupHelpers.h>
Joe Onorato3ad977b2009-05-05 11:50:51 -070020
21#include <utils/KeyedVector.h>
22#include <utils/ByteOrder.h>
23#include <utils/String8.h>
24
25#include <errno.h>
26#include <sys/types.h>
27#include <sys/uio.h>
28#include <sys/stat.h>
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -070029#include <sys/time.h> // for utimes
Joe Onorato3ad977b2009-05-05 11:50:51 -070030#include <stdio.h>
31#include <stdlib.h>
32#include <unistd.h>
Joe Onoratoc825d3e2009-05-06 12:55:46 -040033#include <utime.h>
Joe Onorato3ad977b2009-05-05 11:50:51 -070034#include <fcntl.h>
35#include <zlib.h>
36
37#include <cutils/log.h>
38
Joe Onorato4535e402009-05-15 09:07:06 -040039namespace android {
Joe Onorato3ad977b2009-05-05 11:50:51 -070040
41#define MAGIC0 0x70616e53 // Snap
42#define MAGIC1 0x656c6946 // File
43
Joe Onorato23ecae32009-06-10 17:07:15 -070044#if 1 // TEST_BACKUP_HELPERS
45#define LOGP(f, x...) printf(f "\n", x)
Joe Onorato4535e402009-05-15 09:07:06 -040046#else
Joe Onorato290bb012009-05-13 18:57:29 -040047#define LOGP(x...) LOGD(x)
Joe Onorato4535e402009-05-15 09:07:06 -040048#endif
Joe Onorato290bb012009-05-13 18:57:29 -040049
Joe Onorato3ad977b2009-05-05 11:50:51 -070050struct SnapshotHeader {
51 int magic0;
52 int fileCount;
53 int magic1;
54 int totalSize;
55};
56
57struct FileState {
58 int modTime_sec;
59 int modTime_nsec;
60 int size;
61 int crc32;
62 int nameLen;
63};
64
Joe Onorato23ecae32009-06-10 17:07:15 -070065struct FileRec {
66 char const* file; // this object does not own this string
67 FileState s;
68};
69
Joe Onorato3ad977b2009-05-05 11:50:51 -070070const static int ROUND_UP[4] = { 0, 3, 2, 1 };
71
72static inline int
73round_up(int n)
74{
75 return n + ROUND_UP[n % 4];
76}
77
78static int
79read_snapshot_file(int fd, KeyedVector<String8,FileState>* snapshot)
80{
81 int bytesRead = 0;
82 int amt;
83 SnapshotHeader header;
84
85 amt = read(fd, &header, sizeof(header));
86 if (amt != sizeof(header)) {
87 return errno;
88 }
89 bytesRead += amt;
90
91 if (header.magic0 != MAGIC0 || header.magic1 != MAGIC1) {
92 LOGW("read_snapshot_file header.magic0=0x%08x magic1=0x%08x", header.magic0, header.magic1);
93 return 1;
94 }
95
96 for (int i=0; i<header.fileCount; i++) {
97 FileState file;
98 char filenameBuf[128];
99
Joe Onorato23ecae32009-06-10 17:07:15 -0700100 amt = read(fd, &file, sizeof(FileState));
101 if (amt != sizeof(FileState)) {
Joe Onorato3ad977b2009-05-05 11:50:51 -0700102 LOGW("read_snapshot_file FileState truncated/error with read at %d bytes\n", bytesRead);
103 return 1;
104 }
105 bytesRead += amt;
106
107 // filename is not NULL terminated, but it is padded
108 int nameBufSize = round_up(file.nameLen);
109 char* filename = nameBufSize <= (int)sizeof(filenameBuf)
110 ? filenameBuf
111 : (char*)malloc(nameBufSize);
112 amt = read(fd, filename, nameBufSize);
113 if (amt == nameBufSize) {
114 snapshot->add(String8(filename, file.nameLen), file);
115 }
116 bytesRead += amt;
117 if (filename != filenameBuf) {
118 free(filename);
119 }
120 if (amt != nameBufSize) {
121 LOGW("read_snapshot_file filename truncated/error with read at %d bytes\n", bytesRead);
122 return 1;
123 }
124 }
125
126 if (header.totalSize != bytesRead) {
127 LOGW("read_snapshot_file length mismatch: header.totalSize=%d bytesRead=%d\n",
128 header.totalSize, bytesRead);
129 return 1;
130 }
131
132 return 0;
133}
134
135static int
Joe Onorato23ecae32009-06-10 17:07:15 -0700136write_snapshot_file(int fd, const KeyedVector<String8,FileRec>& snapshot)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700137{
138 int bytesWritten = sizeof(SnapshotHeader);
139 // preflight size
140 const int N = snapshot.size();
141 for (int i=0; i<N; i++) {
142 const String8& name = snapshot.keyAt(i);
143 bytesWritten += sizeof(FileState) + round_up(name.length());
144 }
145
Joe Onorato4535e402009-05-15 09:07:06 -0400146 LOGP("write_snapshot_file fd=%d\n", fd);
147
Joe Onorato3ad977b2009-05-05 11:50:51 -0700148 int amt;
149 SnapshotHeader header = { MAGIC0, N, MAGIC1, bytesWritten };
150
151 amt = write(fd, &header, sizeof(header));
152 if (amt != sizeof(header)) {
153 LOGW("write_snapshot_file error writing header %s", strerror(errno));
154 return errno;
155 }
156
157 for (int i=0; i<header.fileCount; i++) {
158 const String8& name = snapshot.keyAt(i);
Joe Onorato23ecae32009-06-10 17:07:15 -0700159 FileRec r = snapshot.valueAt(i);
160 int nameLen = r.s.nameLen = name.length();
Joe Onorato3ad977b2009-05-05 11:50:51 -0700161
Joe Onorato23ecae32009-06-10 17:07:15 -0700162 amt = write(fd, &r.s, sizeof(FileState));
163 if (amt != sizeof(FileState)) {
Joe Onorato3ad977b2009-05-05 11:50:51 -0700164 LOGW("write_snapshot_file error writing header %s", strerror(errno));
165 return 1;
166 }
167
168 // filename is not NULL terminated, but it is padded
169 amt = write(fd, name.string(), nameLen);
170 if (amt != nameLen) {
171 LOGW("write_snapshot_file error writing filename %s", strerror(errno));
172 return 1;
173 }
174 int paddingLen = ROUND_UP[nameLen % 4];
175 if (paddingLen != 0) {
176 int padding = 0xabababab;
177 amt = write(fd, &padding, paddingLen);
178 if (amt != paddingLen) {
179 LOGW("write_snapshot_file error writing %d bytes of filename padding %s",
180 paddingLen, strerror(errno));
181 return 1;
182 }
183 }
184 }
185
186 return 0;
187}
188
189static int
Joe Onoratod2110db2009-05-19 13:41:21 -0700190write_delete_file(BackupDataWriter* dataStream, const String8& key)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700191{
Joe Onorato290bb012009-05-13 18:57:29 -0400192 LOGP("write_delete_file %s\n", key.string());
Joe Onoratod2110db2009-05-19 13:41:21 -0700193 return dataStream->WriteEntityHeader(key, -1);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700194}
195
196static int
Joe Onoratod2110db2009-05-19 13:41:21 -0700197write_update_file(BackupDataWriter* dataStream, int fd, const String8& key,
Joe Onorato23ecae32009-06-10 17:07:15 -0700198 char const* realFilename)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700199{
Joe Onorato23ecae32009-06-10 17:07:15 -0700200 LOGP("write_update_file %s (%s)\n", realFilename, key.string());
Joe Onoratod2110db2009-05-19 13:41:21 -0700201
202 const int bufsize = 4*1024;
203 int err;
204 int amt;
205 int fileSize;
206 int bytesLeft;
207
208 char* buf = (char*)malloc(bufsize);
209 int crc = crc32(0L, Z_NULL, 0);
210
211
212 bytesLeft = fileSize = lseek(fd, 0, SEEK_END);
213 lseek(fd, 0, SEEK_SET);
214
215 err = dataStream->WriteEntityHeader(key, bytesLeft);
216 if (err != 0) {
217 return err;
218 }
219
220 while ((amt = read(fd, buf, bufsize)) != 0 && bytesLeft > 0) {
221 bytesLeft -= amt;
222 if (bytesLeft < 0) {
223 amt += bytesLeft; // Plus a negative is minus. Don't write more than we promised.
224 }
225 err = dataStream->WriteEntityData(buf, amt);
226 if (err != 0) {
227 return err;
228 }
229 }
230 if (bytesLeft != 0) {
231 if (bytesLeft > 0) {
232 // Pad out the space we promised in the buffer. We can't corrupt the buffer,
233 // even though the data we're sending is probably bad.
234 memset(buf, 0, bufsize);
235 while (bytesLeft > 0) {
236 amt = bytesLeft < bufsize ? bytesLeft : bufsize;
237 bytesLeft -= amt;
238 err = dataStream->WriteEntityData(buf, amt);
239 if (err != 0) {
240 return err;
241 }
242 }
243 }
244 LOGE("write_update_file size mismatch for %s. expected=%d actual=%d."
Joe Onorato23ecae32009-06-10 17:07:15 -0700245 " You aren't doing proper locking!", realFilename, fileSize, fileSize-bytesLeft);
Joe Onoratod2110db2009-05-19 13:41:21 -0700246 }
247
248 free(buf);
249
250 return NO_ERROR;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700251}
252
253static int
Joe Onorato23ecae32009-06-10 17:07:15 -0700254write_update_file(BackupDataWriter* dataStream, const String8& key, char const* realFilename)
Joe Onoratod2110db2009-05-19 13:41:21 -0700255{
256 int err;
Joe Onorato23ecae32009-06-10 17:07:15 -0700257 int fd = open(realFilename, O_RDONLY);
Joe Onoratod2110db2009-05-19 13:41:21 -0700258 if (fd == -1) {
259 return errno;
260 }
261 err = write_update_file(dataStream, fd, key, realFilename);
262 close(fd);
263 return err;
264}
265
266static int
267compute_crc32(int fd)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700268{
269 const int bufsize = 4*1024;
270 int amt;
271
Joe Onorato3ad977b2009-05-05 11:50:51 -0700272 char* buf = (char*)malloc(bufsize);
273 int crc = crc32(0L, Z_NULL, 0);
274
Joe Onoratod2110db2009-05-19 13:41:21 -0700275 lseek(fd, 0, SEEK_SET);
276
Joe Onorato3ad977b2009-05-05 11:50:51 -0700277 while ((amt = read(fd, buf, bufsize)) != 0) {
278 crc = crc32(crc, (Bytef*)buf, amt);
279 }
280
Joe Onorato3ad977b2009-05-05 11:50:51 -0700281 free(buf);
282
283 return crc;
284}
285
286int
Joe Onoratod2110db2009-05-19 13:41:21 -0700287back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD,
Joe Onorato23ecae32009-06-10 17:07:15 -0700288 char const* const* files, char const* const* keys, int fileCount)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700289{
290 int err;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700291 KeyedVector<String8,FileState> oldSnapshot;
Joe Onorato23ecae32009-06-10 17:07:15 -0700292 KeyedVector<String8,FileRec> newSnapshot;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700293
294 if (oldSnapshotFD != -1) {
295 err = read_snapshot_file(oldSnapshotFD, &oldSnapshot);
296 if (err != 0) {
297 // On an error, treat this as a full backup.
298 oldSnapshot.clear();
299 }
300 }
301
302 for (int i=0; i<fileCount; i++) {
Joe Onorato23ecae32009-06-10 17:07:15 -0700303 String8 key(keys[i]);
304 FileRec r;
305 char const* file = r.file = files[i];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700306 struct stat st;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700307
Joe Onorato23ecae32009-06-10 17:07:15 -0700308 err = stat(file, &st);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700309 if (err != 0) {
Joe Onorato23ecae32009-06-10 17:07:15 -0700310 LOGW("Error stating file %s", file);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700311 continue;
312 }
313
Joe Onorato23ecae32009-06-10 17:07:15 -0700314 r.s.modTime_sec = st.st_mtime;
315 r.s.modTime_nsec = 0; // workaround sim breakage
316 //r.s.modTime_nsec = st.st_mtime_nsec;
317 r.s.size = st.st_size;
Joe Onoratod2110db2009-05-19 13:41:21 -0700318 // we compute the crc32 later down below, when we already have the file open.
Joe Onorato23ecae32009-06-10 17:07:15 -0700319
320 if (newSnapshot.indexOfKey(key) >= 0) {
321 LOGP("back_up_files key already in use '%s'", key.string());
322 return -1;
323 }
324 newSnapshot.add(key, r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700325 }
326
327 int n = 0;
328 int N = oldSnapshot.size();
329 int m = 0;
330
331 while (n<N && m<fileCount) {
332 const String8& p = oldSnapshot.keyAt(n);
333 const String8& q = newSnapshot.keyAt(m);
334 int cmp = p.compare(q);
335 if (cmp > 0) {
336 // file added
Joe Onorato23ecae32009-06-10 17:07:15 -0700337 const FileRec& g = newSnapshot.valueAt(m);
338 LOGP("file added: %s", g.file);
339 write_update_file(dataStream, q, g.file);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700340 m++;
341 }
342 else if (cmp < 0) {
343 // file removed
Joe Onorato23ecae32009-06-10 17:07:15 -0700344 LOGP("file removed: %s", p.string());
Joe Onoratod2110db2009-05-19 13:41:21 -0700345 dataStream->WriteEntityHeader(p, -1);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700346 n++;
347 }
348 else {
349 // both files exist, check them
Joe Onorato3ad977b2009-05-05 11:50:51 -0700350 const FileState& f = oldSnapshot.valueAt(n);
Joe Onorato23ecae32009-06-10 17:07:15 -0700351 FileRec& g = newSnapshot.editValueAt(m);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700352
Joe Onorato23ecae32009-06-10 17:07:15 -0700353 int fd = open(g.file, O_RDONLY);
Christopher Tate0032ce82009-06-04 17:01:06 -0700354 if (fd < 0) {
Joe Onoratod2110db2009-05-19 13:41:21 -0700355 // We can't open the file. Don't report it as a delete either. Let the
356 // server keep the old version. Maybe they'll be able to deal with it
357 // on restore.
Joe Onorato23ecae32009-06-10 17:07:15 -0700358 LOGP("Unable to open file %s - skipping", g.file);
Joe Onoratod2110db2009-05-19 13:41:21 -0700359 } else {
Joe Onorato23ecae32009-06-10 17:07:15 -0700360 g.s.crc32 = compute_crc32(fd);
Joe Onoratod2110db2009-05-19 13:41:21 -0700361
Joe Onorato23ecae32009-06-10 17:07:15 -0700362 LOGP("%s", q.string());
363 LOGP(" new: modTime=%d,%d size=%-3d crc32=0x%08x",
Joe Onoratod2110db2009-05-19 13:41:21 -0700364 f.modTime_sec, f.modTime_nsec, f.size, f.crc32);
Joe Onorato23ecae32009-06-10 17:07:15 -0700365 LOGP(" old: modTime=%d,%d size=%-3d crc32=0x%08x",
366 g.s.modTime_sec, g.s.modTime_nsec, g.s.size, g.s.crc32);
367 if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec
368 || f.size != g.s.size || f.crc32 != g.s.crc32) {
369 write_update_file(dataStream, fd, p, g.file);
Joe Onoratod2110db2009-05-19 13:41:21 -0700370 }
371
372 close(fd);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700373 }
374 n++;
375 m++;
376 }
377 }
378
379 // these were deleted
380 while (n<N) {
Joe Onoratod2110db2009-05-19 13:41:21 -0700381 dataStream->WriteEntityHeader(oldSnapshot.keyAt(n), -1);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700382 n++;
383 }
384
385 // these were added
386 while (m<fileCount) {
387 const String8& q = newSnapshot.keyAt(m);
Joe Onorato23ecae32009-06-10 17:07:15 -0700388 FileRec& g = newSnapshot.editValueAt(m);
389 write_update_file(dataStream, q, g.file);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700390 m++;
391 }
392
393 err = write_snapshot_file(newSnapshotFD, newSnapshot);
394
395 return 0;
396}
397
398#if TEST_BACKUP_HELPERS
399
400#define SCRATCH_DIR "/data/backup_helper_test/"
401
402static int
403write_text_file(const char* path, const char* data)
404{
405 int amt;
406 int fd;
407 int len;
408
409 fd = creat(path, 0666);
410 if (fd == -1) {
411 fprintf(stderr, "creat %s failed\n", path);
412 return errno;
413 }
414
415 len = strlen(data);
416 amt = write(fd, data, len);
417 if (amt != len) {
418 fprintf(stderr, "error (%s) writing to file %s\n", strerror(errno), path);
419 return errno;
420 }
421
422 close(fd);
423
424 return 0;
425}
426
427static int
428compare_file(const char* path, const unsigned char* data, int len)
429{
430 int fd;
431 int amt;
432
433 fd = open(path, O_RDONLY);
434 if (fd == -1) {
435 fprintf(stderr, "compare_file error (%s) opening %s\n", strerror(errno), path);
436 return errno;
437 }
438
439 unsigned char* contents = (unsigned char*)malloc(len);
440 if (contents == NULL) {
441 fprintf(stderr, "malloc(%d) failed\n", len);
442 return ENOMEM;
443 }
444
445 bool sizesMatch = true;
446 amt = lseek(fd, 0, SEEK_END);
447 if (amt != len) {
448 fprintf(stderr, "compare_file file length should be %d, was %d\n", len, amt);
449 sizesMatch = false;
450 }
451 lseek(fd, 0, SEEK_SET);
452
453 int readLen = amt < len ? amt : len;
454 amt = read(fd, contents, readLen);
455 if (amt != readLen) {
456 fprintf(stderr, "compare_file read expected %d bytes but got %d\n", len, amt);
457 }
458
459 bool contentsMatch = true;
460 for (int i=0; i<readLen; i++) {
461 if (data[i] != contents[i]) {
462 if (contentsMatch) {
463 fprintf(stderr, "compare_file contents are different: (index, expected, actual)\n");
464 contentsMatch = false;
465 }
466 fprintf(stderr, " [%-2d] %02x %02x\n", i, data[i], contents[i]);
467 }
468 }
469
470 return contentsMatch && sizesMatch ? 0 : 1;
471}
472
473int
474backup_helper_test_empty()
475{
476 int err;
477 int fd;
Joe Onorato23ecae32009-06-10 17:07:15 -0700478 KeyedVector<String8,FileRec> snapshot;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700479 const char* filename = SCRATCH_DIR "backup_helper_test_empty.snap";
480
481 system("rm -r " SCRATCH_DIR);
482 mkdir(SCRATCH_DIR, 0777);
483
484 // write
485 fd = creat(filename, 0666);
486 if (fd == -1) {
487 fprintf(stderr, "error creating %s\n", filename);
488 return 1;
489 }
490
491 err = write_snapshot_file(fd, snapshot);
492
493 close(fd);
494
495 if (err != 0) {
496 fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err));
497 return err;
498 }
499
500 static const unsigned char correct_data[] = {
501 0x53, 0x6e, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00,
502 0x46, 0x69, 0x6c, 0x65, 0x10, 0x00, 0x00, 0x00
503 };
504
505 err = compare_file(filename, correct_data, sizeof(correct_data));
506 if (err != 0) {
507 return err;
508 }
509
510 // read
511 fd = open(filename, O_RDONLY);
512 if (fd == -1) {
513 fprintf(stderr, "error opening for read %s\n", filename);
514 return 1;
515 }
516
517 KeyedVector<String8,FileState> readSnapshot;
518 err = read_snapshot_file(fd, &readSnapshot);
519 if (err != 0) {
520 fprintf(stderr, "read_snapshot_file failed %d\n", err);
521 return err;
522 }
523
524 if (readSnapshot.size() != 0) {
525 fprintf(stderr, "readSnapshot should be length 0\n");
526 return 1;
527 }
528
529 return 0;
530}
531
532int
533backup_helper_test_four()
534{
535 int err;
536 int fd;
Joe Onorato23ecae32009-06-10 17:07:15 -0700537 KeyedVector<String8,FileRec> snapshot;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700538 const char* filename = SCRATCH_DIR "backup_helper_test_four.snap";
539
540 system("rm -r " SCRATCH_DIR);
541 mkdir(SCRATCH_DIR, 0777);
542
543 // write
544 fd = creat(filename, 0666);
545 if (fd == -1) {
546 fprintf(stderr, "error opening %s\n", filename);
547 return 1;
548 }
549
550 String8 filenames[4];
551 FileState states[4];
Joe Onorato23ecae32009-06-10 17:07:15 -0700552 FileRec r;
553 r.file = NULL;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700554
555 states[0].modTime_sec = 0xfedcba98;
556 states[0].modTime_nsec = 0xdeadbeef;
557 states[0].size = 0xababbcbc;
558 states[0].crc32 = 0x12345678;
559 states[0].nameLen = -12;
Joe Onorato23ecae32009-06-10 17:07:15 -0700560 r.s = states[0];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700561 filenames[0] = String8("bytes_of_padding");
Joe Onorato23ecae32009-06-10 17:07:15 -0700562 snapshot.add(filenames[0], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700563
564 states[1].modTime_sec = 0x93400031;
565 states[1].modTime_nsec = 0xdeadbeef;
566 states[1].size = 0x88557766;
567 states[1].crc32 = 0x22334422;
568 states[1].nameLen = -1;
Joe Onorato23ecae32009-06-10 17:07:15 -0700569 r.s = states[1];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700570 filenames[1] = String8("bytes_of_padding3");
Joe Onorato23ecae32009-06-10 17:07:15 -0700571 snapshot.add(filenames[1], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700572
573 states[2].modTime_sec = 0x33221144;
574 states[2].modTime_nsec = 0xdeadbeef;
575 states[2].size = 0x11223344;
576 states[2].crc32 = 0x01122334;
577 states[2].nameLen = 0;
Joe Onorato23ecae32009-06-10 17:07:15 -0700578 r.s = states[2];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700579 filenames[2] = String8("bytes_of_padding_2");
Joe Onorato23ecae32009-06-10 17:07:15 -0700580 snapshot.add(filenames[2], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700581
582 states[3].modTime_sec = 0x33221144;
583 states[3].modTime_nsec = 0xdeadbeef;
584 states[3].size = 0x11223344;
585 states[3].crc32 = 0x01122334;
586 states[3].nameLen = 0;
Joe Onorato23ecae32009-06-10 17:07:15 -0700587 r.s = states[3];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700588 filenames[3] = String8("bytes_of_padding__1");
Joe Onorato23ecae32009-06-10 17:07:15 -0700589 snapshot.add(filenames[3], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700590
591 err = write_snapshot_file(fd, snapshot);
592
593 close(fd);
594
595 if (err != 0) {
596 fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err));
597 return err;
598 }
599
600 static const unsigned char correct_data[] = {
601 // header
602 0x53, 0x6e, 0x61, 0x70, 0x04, 0x00, 0x00, 0x00,
603 0x46, 0x69, 0x6c, 0x65, 0xac, 0x00, 0x00, 0x00,
604
605 // bytes_of_padding
606 0x98, 0xba, 0xdc, 0xfe, 0xef, 0xbe, 0xad, 0xde,
607 0xbc, 0xbc, 0xab, 0xab, 0x78, 0x56, 0x34, 0x12,
608 0x10, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
609 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
610 0x64, 0x69, 0x6e, 0x67,
611
612 // bytes_of_padding3
613 0x31, 0x00, 0x40, 0x93, 0xef, 0xbe, 0xad, 0xde,
614 0x66, 0x77, 0x55, 0x88, 0x22, 0x44, 0x33, 0x22,
615 0x11, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
616 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
617 0x64, 0x69, 0x6e, 0x67, 0x33, 0xab, 0xab, 0xab,
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700618
Joe Onorato3ad977b2009-05-05 11:50:51 -0700619 // bytes of padding2
620 0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde,
621 0x44, 0x33, 0x22, 0x11, 0x34, 0x23, 0x12, 0x01,
622 0x12, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
623 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
624 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x32, 0xab, 0xab,
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700625
Joe Onorato3ad977b2009-05-05 11:50:51 -0700626 // bytes of padding3
627 0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde,
628 0x44, 0x33, 0x22, 0x11, 0x34, 0x23, 0x12, 0x01,
629 0x13, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
630 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
631 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x5f, 0x31, 0xab
632 };
633
634 err = compare_file(filename, correct_data, sizeof(correct_data));
635 if (err != 0) {
636 return err;
637 }
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700638
Joe Onorato3ad977b2009-05-05 11:50:51 -0700639 // read
640 fd = open(filename, O_RDONLY);
641 if (fd == -1) {
642 fprintf(stderr, "error opening for read %s\n", filename);
643 return 1;
644 }
645
646
647 KeyedVector<String8,FileState> readSnapshot;
648 err = read_snapshot_file(fd, &readSnapshot);
649 if (err != 0) {
650 fprintf(stderr, "read_snapshot_file failed %d\n", err);
651 return err;
652 }
653
654 if (readSnapshot.size() != 4) {
655 fprintf(stderr, "readSnapshot should be length 4 is %d\n", readSnapshot.size());
656 return 1;
657 }
658
659 bool matched = true;
660 for (size_t i=0; i<readSnapshot.size(); i++) {
661 const String8& name = readSnapshot.keyAt(i);
662 const FileState state = readSnapshot.valueAt(i);
663
664 if (name != filenames[i] || states[i].modTime_sec != state.modTime_sec
665 || states[i].modTime_nsec != state.modTime_nsec
666 || states[i].size != state.size || states[i].crc32 != states[i].crc32) {
667 fprintf(stderr, "state %d expected={%d/%d, 0x%08x, 0x%08x, %3d} '%s'\n"
668 " actual={%d/%d, 0x%08x, 0x%08x, %3d} '%s'\n", i,
669 states[i].modTime_sec, states[i].modTime_nsec, states[i].size, states[i].crc32,
670 name.length(), filenames[i].string(),
671 state.modTime_sec, state.modTime_nsec, state.size, state.crc32, state.nameLen,
672 name.string());
673 matched = false;
674 }
675 }
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700676
Joe Onorato3ad977b2009-05-05 11:50:51 -0700677 return matched ? 0 : 1;
678}
679
Joe Onorato4535e402009-05-15 09:07:06 -0400680// hexdump -v -e '" " 8/1 " 0x%02x," "\n"' data_writer.data
681const unsigned char DATA_GOLDEN_FILE[] = {
682 0x41, 0x70, 0x70, 0x31, 0x0b, 0x00, 0x00, 0x00,
Joe Onorato2e1da322009-05-15 18:20:19 -0400683 0xdd, 0xcc, 0xbb, 0xaa, 0x6e, 0x6f, 0x5f, 0x70,
Joe Onorato4535e402009-05-15 09:07:06 -0400684 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00,
Joe Onorato2e1da322009-05-15 18:20:19 -0400685 0x44, 0x61, 0x74, 0x61, 0x0b, 0x00, 0x00, 0x00,
686 0x0c, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x5f, 0x70,
687 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00,
688 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69,
689 0x6e, 0x67, 0x5f, 0x00, 0x41, 0x70, 0x70, 0x31,
690 0x0c, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa,
Joe Onorato4535e402009-05-15 09:07:06 -0400691 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
692 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
693 0x44, 0x61, 0x74, 0x61, 0x0c, 0x00, 0x00, 0x00,
694 0x0d, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
695 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33,
696 0x00, 0xbc, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64,
697 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33,
698 0x00, 0xbc, 0xbc, 0xbc, 0x41, 0x70, 0x70, 0x31,
Joe Onorato2e1da322009-05-15 18:20:19 -0400699 0x0d, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa,
700 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
701 0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc,
702 0x44, 0x61, 0x74, 0x61, 0x0d, 0x00, 0x00, 0x00,
703 0x0e, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
Joe Onorato4535e402009-05-15 09:07:06 -0400704 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
Joe Onorato2e1da322009-05-15 18:20:19 -0400705 0x5f, 0x00, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64,
706 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
707 0x5f, 0x00, 0xbc, 0xbc, 0x41, 0x70, 0x70, 0x31,
708 0x0a, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa,
Joe Onorato4535e402009-05-15 09:07:06 -0400709 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
710 0x6f, 0x31, 0x00, 0xbc, 0x44, 0x61, 0x74, 0x61,
711 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
712 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
713 0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64,
714 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00, 0xbc,
715 0x46, 0x6f, 0x6f, 0x74, 0x04, 0x00, 0x00, 0x00,
Joe Onorato2e1da322009-05-15 18:20:19 -0400716 0x99, 0x99, 0x77, 0x77
Joe Onorato4535e402009-05-15 09:07:06 -0400717};
718const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE);
719
720static int
721test_write_header_and_entity(BackupDataWriter& writer, const char* str)
722{
723 int err;
724 String8 text(str);
725
Joe Onorato2e1da322009-05-15 18:20:19 -0400726 err = writer.WriteAppHeader(text, 0xaabbccdd);
Joe Onorato4535e402009-05-15 09:07:06 -0400727 if (err != 0) {
728 fprintf(stderr, "WriteAppHeader failed with %s\n", strerror(err));
729 return err;
730 }
731
732 err = writer.WriteEntityHeader(text, text.length()+1);
733 if (err != 0) {
734 fprintf(stderr, "WriteEntityHeader failed with %s\n", strerror(err));
735 return err;
736 }
737
738 err = writer.WriteEntityData(text.string(), text.length()+1);
739 if (err != 0) {
740 fprintf(stderr, "write failed for data '%s'\n", text.string());
741 return errno;
742 }
743
744 return err;
745}
746
747int
748backup_helper_test_data_writer()
749{
750 int err;
751 int fd;
752 const char* filename = SCRATCH_DIR "data_writer.data";
753
754 system("rm -r " SCRATCH_DIR);
755 mkdir(SCRATCH_DIR, 0777);
756 mkdir(SCRATCH_DIR "data", 0777);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700757
Joe Onorato4535e402009-05-15 09:07:06 -0400758 fd = creat(filename, 0666);
759 if (fd == -1) {
760 fprintf(stderr, "error creating: %s\n", strerror(errno));
761 return errno;
762 }
763
764 BackupDataWriter writer(fd);
765
766 err = 0;
767 err |= test_write_header_and_entity(writer, "no_padding_");
768 err |= test_write_header_and_entity(writer, "padded_to__3");
769 err |= test_write_header_and_entity(writer, "padded_to_2__");
770 err |= test_write_header_and_entity(writer, "padded_to1");
771
Joe Onorato2e1da322009-05-15 18:20:19 -0400772 writer.WriteAppFooter(0x77779999);
Joe Onorato4535e402009-05-15 09:07:06 -0400773
774 close(fd);
775
776 err = compare_file(filename, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
777 if (err != 0) {
778 return err;
779 }
780
781 return err;
782}
783
Joe Onorato2e1da322009-05-15 18:20:19 -0400784int
785test_read_header_and_entity(BackupDataReader& reader, const char* str)
786{
787 int err;
788 int bufSize = strlen(str)+1;
789 char* buf = (char*)malloc(bufSize);
790 String8 string;
791 int cookie = 0x11111111;
792 size_t actualSize;
793
794 // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str);
795
796 err = reader.ReadNextHeader();
797 if (err != 0) {
798 fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err));
799 goto done;
800 }
801
802 err = reader.ReadAppHeader(&string, &cookie);
803 if (err != 0) {
804 fprintf(stderr, "ReadAppHeader failed with %s\n", strerror(err));
805 goto done;
806 }
807 if (string != str) {
808 fprintf(stderr, "ReadAppHeader expected packageName '%s' got '%s'\n", str, string.string());
809 err = EINVAL;
810 goto done;
811 }
812 if (cookie != (int)0xaabbccdd) {
813 fprintf(stderr, "ReadAppHeader expected cookie 0x%08x got 0x%08x\n", 0xaabbccdd, cookie);
814 err = EINVAL;
815 goto done;
816 }
817
818 err = reader.ReadNextHeader();
819 if (err != 0) {
820 fprintf(stderr, "ReadNextHeader (for entity header) failed with %s\n", strerror(err));
821 goto done;
822 }
823
824 err = reader.ReadEntityHeader(&string, &actualSize);
825 if (err != 0) {
826 fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err));
827 goto done;
828 }
829 if (string != str) {
830 fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.string());
831 err = EINVAL;
832 goto done;
833 }
834 if ((int)actualSize != bufSize) {
835 fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize,
836 actualSize);
837 err = EINVAL;
838 goto done;
839 }
840
841 err = reader.ReadEntityData(buf, bufSize);
842 if (err != NO_ERROR) {
843 fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err));
844 goto done;
845 }
846
847 if (0 != memcmp(buf, str, bufSize)) {
848 fprintf(stderr, "ReadEntityData expected '%s' but got something starting with "
849 "%02x %02x %02x %02x\n", str, buf[0], buf[1], buf[2], buf[3]);
850 err = EINVAL;
851 goto done;
852 }
853
854 // The next read will confirm whether it got the right amount of data.
855
856done:
857 if (err != NO_ERROR) {
858 fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err));
859 }
860 free(buf);
861 return err;
862}
863
864int
865backup_helper_test_data_reader()
866{
867 int err;
868 int fd;
869 const char* filename = SCRATCH_DIR "data_reader.data";
870
871 system("rm -r " SCRATCH_DIR);
872 mkdir(SCRATCH_DIR, 0777);
873 mkdir(SCRATCH_DIR "data", 0777);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700874
Joe Onorato2e1da322009-05-15 18:20:19 -0400875 fd = creat(filename, 0666);
876 if (fd == -1) {
877 fprintf(stderr, "error creating: %s\n", strerror(errno));
878 return errno;
879 }
880
881 err = write(fd, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
882 if (err != DATA_GOLDEN_FILE_SIZE) {
883 fprintf(stderr, "Error \"%s\" writing golden file %s\n", strerror(errno), filename);
884 return errno;
885 }
886
887 close(fd);
888
889 fd = open(filename, O_RDONLY);
890 if (fd == -1) {
891 fprintf(stderr, "Error \"%s\" opening golden file %s for read\n", strerror(errno),
892 filename);
893 return errno;
894 }
895
896 {
897 BackupDataReader reader(fd);
898
899 err = 0;
900
901 if (err == NO_ERROR) {
902 err = test_read_header_and_entity(reader, "no_padding_");
903 }
904
905 if (err == NO_ERROR) {
906 err = test_read_header_and_entity(reader, "padded_to__3");
907 }
908
909 if (err == NO_ERROR) {
910 err = test_read_header_and_entity(reader, "padded_to_2__");
911 }
912
913 if (err == NO_ERROR) {
914 err = test_read_header_and_entity(reader, "padded_to1");
915 }
916
917 if (err == NO_ERROR) {
918 err = reader.ReadNextHeader();
919 if (err != 0) {
920 fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err));
921 }
922
923 if (err == NO_ERROR) {
924 int cookie;
925 err |= reader.ReadAppFooter(&cookie);
926 if (cookie != 0x77779999) {
927 fprintf(stderr, "app footer cookie expected=0x%08x actual=0x%08x\n",
928 0x77779999, cookie);
929 err = EINVAL;
930 }
931 }
932 }
933 }
934
935 close(fd);
936
937 return err;
938}
939
Joe Onorato3ad977b2009-05-05 11:50:51 -0700940static int
941get_mod_time(const char* filename, struct timeval times[2])
942{
943 int err;
944 struct stat64 st;
945 err = stat64(filename, &st);
946 if (err != 0) {
947 fprintf(stderr, "stat '%s' failed: %s\n", filename, strerror(errno));
948 return errno;
949 }
950 times[0].tv_sec = st.st_atime;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700951 times[1].tv_sec = st.st_mtime;
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700952
953 // If st_atime is a macro then struct stat64 uses struct timespec
954 // to store the access and modif time values and typically
955 // st_*time_nsec is not defined. In glibc, this is controlled by
956 // __USE_MISC.
957#ifdef __USE_MISC
958#if !defined(st_atime) || defined(st_atime_nsec)
959#error "Check if this __USE_MISC conditional is still needed."
960#endif
961 times[0].tv_usec = st.st_atim.tv_nsec / 1000;
962 times[1].tv_usec = st.st_mtim.tv_nsec / 1000;
963#else
964 times[0].tv_usec = st.st_atime_nsec / 1000;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700965 times[1].tv_usec = st.st_mtime_nsec / 1000;
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700966#endif
967
Joe Onorato3ad977b2009-05-05 11:50:51 -0700968 return 0;
969}
970
971int
972backup_helper_test_files()
973{
974 int err;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700975 int oldSnapshotFD;
Joe Onorato4535e402009-05-15 09:07:06 -0400976 int dataStreamFD;
977 int newSnapshotFD;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700978
979 system("rm -r " SCRATCH_DIR);
980 mkdir(SCRATCH_DIR, 0777);
981 mkdir(SCRATCH_DIR "data", 0777);
982
983 write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
984 write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
985 write_text_file(SCRATCH_DIR "data/d", "d\ndd\n");
986 write_text_file(SCRATCH_DIR "data/e", "e\nee\n");
987 write_text_file(SCRATCH_DIR "data/f", "f\nff\n");
988 write_text_file(SCRATCH_DIR "data/h", "h\nhh\n");
989
990 char const* files_before[] = {
Joe Onorato23ecae32009-06-10 17:07:15 -0700991 SCRATCH_DIR "data/b",
992 SCRATCH_DIR "data/c",
993 SCRATCH_DIR "data/d",
994 SCRATCH_DIR "data/e",
995 SCRATCH_DIR "data/f"
996 };
997
998 char const* keys_before[] = {
Joe Onorato3ad977b2009-05-05 11:50:51 -0700999 "data/b",
1000 "data/c",
1001 "data/d",
1002 "data/e",
1003 "data/f"
1004 };
1005
Joe Onorato4535e402009-05-15 09:07:06 -04001006 dataStreamFD = creat(SCRATCH_DIR "1.data", 0666);
1007 if (dataStreamFD == -1) {
1008 fprintf(stderr, "error creating: %s\n", strerror(errno));
1009 return errno;
1010 }
1011
Joe Onorato3ad977b2009-05-05 11:50:51 -07001012 newSnapshotFD = creat(SCRATCH_DIR "before.snap", 0666);
1013 if (newSnapshotFD == -1) {
1014 fprintf(stderr, "error creating: %s\n", strerror(errno));
1015 return errno;
1016 }
Joe Onoratod2110db2009-05-19 13:41:21 -07001017
1018 {
1019 BackupDataWriter dataStream(dataStreamFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001020
Joe Onorato23ecae32009-06-10 17:07:15 -07001021 err = back_up_files(-1, &dataStream, newSnapshotFD, files_before, keys_before, 5);
Joe Onoratod2110db2009-05-19 13:41:21 -07001022 if (err != 0) {
1023 return err;
1024 }
Joe Onorato3ad977b2009-05-05 11:50:51 -07001025 }
1026
Joe Onorato4535e402009-05-15 09:07:06 -04001027 close(dataStreamFD);
Joe Onorato3ad977b2009-05-05 11:50:51 -07001028 close(newSnapshotFD);
1029
1030 sleep(3);
1031
1032 struct timeval d_times[2];
1033 struct timeval e_times[2];
1034
1035 err = get_mod_time(SCRATCH_DIR "data/d", d_times);
1036 err |= get_mod_time(SCRATCH_DIR "data/e", e_times);
1037 if (err != 0) {
1038 return err;
1039 }
1040
1041 write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
1042 unlink(SCRATCH_DIR "data/c");
1043 write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
1044 write_text_file(SCRATCH_DIR "data/d", "dd\ndd\n");
1045 utimes(SCRATCH_DIR "data/d", d_times);
1046 write_text_file(SCRATCH_DIR "data/e", "z\nzz\n");
1047 utimes(SCRATCH_DIR "data/e", e_times);
1048 write_text_file(SCRATCH_DIR "data/g", "g\ngg\n");
1049 unlink(SCRATCH_DIR "data/f");
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001050
Joe Onorato3ad977b2009-05-05 11:50:51 -07001051 char const* files_after[] = {
Joe Onorato23ecae32009-06-10 17:07:15 -07001052 SCRATCH_DIR "data/a", // added
1053 SCRATCH_DIR "data/b", // same
1054 SCRATCH_DIR "data/c", // different mod time
1055 SCRATCH_DIR "data/d", // different size (same mod time)
1056 SCRATCH_DIR "data/e", // different contents (same mod time, same size)
1057 SCRATCH_DIR "data/g" // added
1058 };
1059
1060 char const* keys_after[] = {
Joe Onorato3ad977b2009-05-05 11:50:51 -07001061 "data/a", // added
1062 "data/b", // same
1063 "data/c", // different mod time
1064 "data/d", // different size (same mod time)
1065 "data/e", // different contents (same mod time, same size)
1066 "data/g" // added
1067 };
1068
1069 oldSnapshotFD = open(SCRATCH_DIR "before.snap", O_RDONLY);
1070 if (oldSnapshotFD == -1) {
1071 fprintf(stderr, "error opening: %s\n", strerror(errno));
1072 return errno;
1073 }
1074
Joe Onorato4535e402009-05-15 09:07:06 -04001075 dataStreamFD = creat(SCRATCH_DIR "2.data", 0666);
1076 if (dataStreamFD == -1) {
1077 fprintf(stderr, "error creating: %s\n", strerror(errno));
1078 return errno;
1079 }
1080
Joe Onorato3ad977b2009-05-05 11:50:51 -07001081 newSnapshotFD = creat(SCRATCH_DIR "after.snap", 0666);
1082 if (newSnapshotFD == -1) {
1083 fprintf(stderr, "error creating: %s\n", strerror(errno));
1084 return errno;
1085 }
1086
Joe Onoratod2110db2009-05-19 13:41:21 -07001087 {
1088 BackupDataWriter dataStream(dataStreamFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001089
Joe Onorato23ecae32009-06-10 17:07:15 -07001090 err = back_up_files(oldSnapshotFD, &dataStream, newSnapshotFD, files_after, keys_after, 6);
Joe Onoratod2110db2009-05-19 13:41:21 -07001091 if (err != 0) {
1092 return err;
1093 }
1094}
Joe Onorato3ad977b2009-05-05 11:50:51 -07001095
1096 close(oldSnapshotFD);
Joe Onorato4535e402009-05-15 09:07:06 -04001097 close(dataStreamFD);
Joe Onorato3ad977b2009-05-05 11:50:51 -07001098 close(newSnapshotFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001099
Joe Onorato3ad977b2009-05-05 11:50:51 -07001100 return 0;
1101}
1102
Joe Onorato23ecae32009-06-10 17:07:15 -07001103int
1104backup_helper_test_null_base()
1105{
1106 int err;
1107 int oldSnapshotFD;
1108 int dataStreamFD;
1109 int newSnapshotFD;
1110
1111 system("rm -r " SCRATCH_DIR);
1112 mkdir(SCRATCH_DIR, 0777);
1113 mkdir(SCRATCH_DIR "data", 0777);
1114
1115 write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
1116
1117 char const* files[] = {
1118 SCRATCH_DIR "data/a",
1119 };
1120
1121 char const* keys[] = {
1122 "a",
1123 };
1124
1125 dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
1126 if (dataStreamFD == -1) {
1127 fprintf(stderr, "error creating: %s\n", strerror(errno));
1128 return errno;
1129 }
1130
1131 newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
1132 if (newSnapshotFD == -1) {
1133 fprintf(stderr, "error creating: %s\n", strerror(errno));
1134 return errno;
1135 }
1136
1137 {
1138 BackupDataWriter dataStream(dataStreamFD);
1139
1140 err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
1141 if (err != 0) {
1142 return err;
1143 }
1144 }
1145
1146 close(dataStreamFD);
1147 close(newSnapshotFD);
1148
1149 return 0;
1150}
1151
1152
Joe Onorato3ad977b2009-05-05 11:50:51 -07001153#endif // TEST_BACKUP_HELPERS
Joe Onorato4535e402009-05-15 09:07:06 -04001154
1155}