blob: c1d5404eebc7bcd95b742f0869e055c299de6628 [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
Joe Onoratoce88cb12009-06-11 11:27:16 -070067 bool deleted;
Joe Onorato23ecae32009-06-10 17:07:15 -070068 FileState s;
69};
70
Joe Onorato3ad977b2009-05-05 11:50:51 -070071const static int ROUND_UP[4] = { 0, 3, 2, 1 };
72
73static inline int
74round_up(int n)
75{
76 return n + ROUND_UP[n % 4];
77}
78
79static int
80read_snapshot_file(int fd, KeyedVector<String8,FileState>* snapshot)
81{
82 int bytesRead = 0;
83 int amt;
84 SnapshotHeader header;
85
86 amt = read(fd, &header, sizeof(header));
87 if (amt != sizeof(header)) {
88 return errno;
89 }
90 bytesRead += amt;
91
92 if (header.magic0 != MAGIC0 || header.magic1 != MAGIC1) {
93 LOGW("read_snapshot_file header.magic0=0x%08x magic1=0x%08x", header.magic0, header.magic1);
94 return 1;
95 }
96
97 for (int i=0; i<header.fileCount; i++) {
98 FileState file;
99 char filenameBuf[128];
100
Joe Onorato23ecae32009-06-10 17:07:15 -0700101 amt = read(fd, &file, sizeof(FileState));
102 if (amt != sizeof(FileState)) {
Joe Onorato3ad977b2009-05-05 11:50:51 -0700103 LOGW("read_snapshot_file FileState truncated/error with read at %d bytes\n", bytesRead);
104 return 1;
105 }
106 bytesRead += amt;
107
108 // filename is not NULL terminated, but it is padded
109 int nameBufSize = round_up(file.nameLen);
110 char* filename = nameBufSize <= (int)sizeof(filenameBuf)
111 ? filenameBuf
112 : (char*)malloc(nameBufSize);
113 amt = read(fd, filename, nameBufSize);
114 if (amt == nameBufSize) {
115 snapshot->add(String8(filename, file.nameLen), file);
116 }
117 bytesRead += amt;
118 if (filename != filenameBuf) {
119 free(filename);
120 }
121 if (amt != nameBufSize) {
122 LOGW("read_snapshot_file filename truncated/error with read at %d bytes\n", bytesRead);
123 return 1;
124 }
125 }
126
127 if (header.totalSize != bytesRead) {
128 LOGW("read_snapshot_file length mismatch: header.totalSize=%d bytesRead=%d\n",
129 header.totalSize, bytesRead);
130 return 1;
131 }
132
133 return 0;
134}
135
136static int
Joe Onorato23ecae32009-06-10 17:07:15 -0700137write_snapshot_file(int fd, const KeyedVector<String8,FileRec>& snapshot)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700138{
Joe Onoratoce88cb12009-06-11 11:27:16 -0700139 int fileCount = 0;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700140 int bytesWritten = sizeof(SnapshotHeader);
141 // preflight size
142 const int N = snapshot.size();
143 for (int i=0; i<N; i++) {
Joe Onoratoce88cb12009-06-11 11:27:16 -0700144 const FileRec& g = snapshot.valueAt(i);
145 if (!g.deleted) {
146 const String8& name = snapshot.keyAt(i);
147 bytesWritten += sizeof(FileState) + round_up(name.length());
148 fileCount++;
149 }
Joe Onorato3ad977b2009-05-05 11:50:51 -0700150 }
151
Joe Onorato4535e402009-05-15 09:07:06 -0400152 LOGP("write_snapshot_file fd=%d\n", fd);
153
Joe Onorato3ad977b2009-05-05 11:50:51 -0700154 int amt;
Joe Onoratoce88cb12009-06-11 11:27:16 -0700155 SnapshotHeader header = { MAGIC0, fileCount, MAGIC1, bytesWritten };
Joe Onorato3ad977b2009-05-05 11:50:51 -0700156
157 amt = write(fd, &header, sizeof(header));
158 if (amt != sizeof(header)) {
159 LOGW("write_snapshot_file error writing header %s", strerror(errno));
160 return errno;
161 }
162
Joe Onoratoce88cb12009-06-11 11:27:16 -0700163 for (int i=0; i<N; i++) {
Joe Onorato23ecae32009-06-10 17:07:15 -0700164 FileRec r = snapshot.valueAt(i);
Joe Onoratoce88cb12009-06-11 11:27:16 -0700165 if (!r.deleted) {
166 const String8& name = snapshot.keyAt(i);
167 int nameLen = r.s.nameLen = name.length();
Joe Onorato3ad977b2009-05-05 11:50:51 -0700168
Joe Onoratoce88cb12009-06-11 11:27:16 -0700169 amt = write(fd, &r.s, sizeof(FileState));
170 if (amt != sizeof(FileState)) {
171 LOGW("write_snapshot_file error writing header %s", strerror(errno));
Joe Onorato3ad977b2009-05-05 11:50:51 -0700172 return 1;
173 }
Joe Onoratoce88cb12009-06-11 11:27:16 -0700174
175 // filename is not NULL terminated, but it is padded
176 amt = write(fd, name.string(), nameLen);
177 if (amt != nameLen) {
178 LOGW("write_snapshot_file error writing filename %s", strerror(errno));
179 return 1;
180 }
181 int paddingLen = ROUND_UP[nameLen % 4];
182 if (paddingLen != 0) {
183 int padding = 0xabababab;
184 amt = write(fd, &padding, paddingLen);
185 if (amt != paddingLen) {
186 LOGW("write_snapshot_file error writing %d bytes of filename padding %s",
187 paddingLen, strerror(errno));
188 return 1;
189 }
190 }
Joe Onorato3ad977b2009-05-05 11:50:51 -0700191 }
192 }
193
194 return 0;
195}
196
197static int
Joe Onoratod2110db2009-05-19 13:41:21 -0700198write_delete_file(BackupDataWriter* dataStream, const String8& key)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700199{
Joe Onorato290bb012009-05-13 18:57:29 -0400200 LOGP("write_delete_file %s\n", key.string());
Joe Onoratod2110db2009-05-19 13:41:21 -0700201 return dataStream->WriteEntityHeader(key, -1);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700202}
203
204static int
Joe Onoratod2110db2009-05-19 13:41:21 -0700205write_update_file(BackupDataWriter* dataStream, int fd, const String8& key,
Joe Onorato23ecae32009-06-10 17:07:15 -0700206 char const* realFilename)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700207{
Joe Onorato23ecae32009-06-10 17:07:15 -0700208 LOGP("write_update_file %s (%s)\n", realFilename, key.string());
Joe Onoratod2110db2009-05-19 13:41:21 -0700209
210 const int bufsize = 4*1024;
211 int err;
212 int amt;
213 int fileSize;
214 int bytesLeft;
215
216 char* buf = (char*)malloc(bufsize);
217 int crc = crc32(0L, Z_NULL, 0);
218
219
220 bytesLeft = fileSize = lseek(fd, 0, SEEK_END);
221 lseek(fd, 0, SEEK_SET);
222
223 err = dataStream->WriteEntityHeader(key, bytesLeft);
224 if (err != 0) {
225 return err;
226 }
227
228 while ((amt = read(fd, buf, bufsize)) != 0 && bytesLeft > 0) {
229 bytesLeft -= amt;
230 if (bytesLeft < 0) {
231 amt += bytesLeft; // Plus a negative is minus. Don't write more than we promised.
232 }
233 err = dataStream->WriteEntityData(buf, amt);
234 if (err != 0) {
235 return err;
236 }
237 }
238 if (bytesLeft != 0) {
239 if (bytesLeft > 0) {
240 // Pad out the space we promised in the buffer. We can't corrupt the buffer,
241 // even though the data we're sending is probably bad.
242 memset(buf, 0, bufsize);
243 while (bytesLeft > 0) {
244 amt = bytesLeft < bufsize ? bytesLeft : bufsize;
245 bytesLeft -= amt;
246 err = dataStream->WriteEntityData(buf, amt);
247 if (err != 0) {
248 return err;
249 }
250 }
251 }
252 LOGE("write_update_file size mismatch for %s. expected=%d actual=%d."
Joe Onorato23ecae32009-06-10 17:07:15 -0700253 " You aren't doing proper locking!", realFilename, fileSize, fileSize-bytesLeft);
Joe Onoratod2110db2009-05-19 13:41:21 -0700254 }
255
256 free(buf);
257
258 return NO_ERROR;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700259}
260
261static int
Joe Onorato23ecae32009-06-10 17:07:15 -0700262write_update_file(BackupDataWriter* dataStream, const String8& key, char const* realFilename)
Joe Onoratod2110db2009-05-19 13:41:21 -0700263{
264 int err;
Joe Onorato23ecae32009-06-10 17:07:15 -0700265 int fd = open(realFilename, O_RDONLY);
Joe Onoratod2110db2009-05-19 13:41:21 -0700266 if (fd == -1) {
267 return errno;
268 }
269 err = write_update_file(dataStream, fd, key, realFilename);
270 close(fd);
271 return err;
272}
273
274static int
275compute_crc32(int fd)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700276{
277 const int bufsize = 4*1024;
278 int amt;
279
Joe Onorato3ad977b2009-05-05 11:50:51 -0700280 char* buf = (char*)malloc(bufsize);
281 int crc = crc32(0L, Z_NULL, 0);
282
Joe Onoratod2110db2009-05-19 13:41:21 -0700283 lseek(fd, 0, SEEK_SET);
284
Joe Onorato3ad977b2009-05-05 11:50:51 -0700285 while ((amt = read(fd, buf, bufsize)) != 0) {
286 crc = crc32(crc, (Bytef*)buf, amt);
287 }
288
Joe Onorato3ad977b2009-05-05 11:50:51 -0700289 free(buf);
290
291 return crc;
292}
293
294int
Joe Onoratod2110db2009-05-19 13:41:21 -0700295back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD,
Joe Onorato23ecae32009-06-10 17:07:15 -0700296 char const* const* files, char const* const* keys, int fileCount)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700297{
298 int err;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700299 KeyedVector<String8,FileState> oldSnapshot;
Joe Onorato23ecae32009-06-10 17:07:15 -0700300 KeyedVector<String8,FileRec> newSnapshot;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700301
302 if (oldSnapshotFD != -1) {
303 err = read_snapshot_file(oldSnapshotFD, &oldSnapshot);
304 if (err != 0) {
305 // On an error, treat this as a full backup.
306 oldSnapshot.clear();
307 }
308 }
309
310 for (int i=0; i<fileCount; i++) {
Joe Onorato23ecae32009-06-10 17:07:15 -0700311 String8 key(keys[i]);
312 FileRec r;
313 char const* file = r.file = files[i];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700314 struct stat st;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700315
Joe Onorato23ecae32009-06-10 17:07:15 -0700316 err = stat(file, &st);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700317 if (err != 0) {
Joe Onorato23ecae32009-06-10 17:07:15 -0700318 LOGW("Error stating file %s", file);
Joe Onoratoce88cb12009-06-11 11:27:16 -0700319 r.deleted = true;
320 } else {
321 r.deleted = false;
322 r.s.modTime_sec = st.st_mtime;
323 r.s.modTime_nsec = 0; // workaround sim breakage
324 //r.s.modTime_nsec = st.st_mtime_nsec;
325 r.s.size = st.st_size;
326 // we compute the crc32 later down below, when we already have the file open.
Joe Onorato3ad977b2009-05-05 11:50:51 -0700327
Joe Onoratoce88cb12009-06-11 11:27:16 -0700328 if (newSnapshot.indexOfKey(key) >= 0) {
329 LOGP("back_up_files key already in use '%s'", key.string());
330 return -1;
331 }
Joe Onorato23ecae32009-06-10 17:07:15 -0700332 }
333 newSnapshot.add(key, r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700334 }
335
336 int n = 0;
337 int N = oldSnapshot.size();
338 int m = 0;
339
340 while (n<N && m<fileCount) {
341 const String8& p = oldSnapshot.keyAt(n);
342 const String8& q = newSnapshot.keyAt(m);
Joe Onoratoce88cb12009-06-11 11:27:16 -0700343 FileRec& g = newSnapshot.editValueAt(m);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700344 int cmp = p.compare(q);
Joe Onoratoce88cb12009-06-11 11:27:16 -0700345 if (g.deleted || cmp < 0) {
346 // file removed
347 LOGP("file removed: %s", p.string());
348 g.deleted = true; // They didn't mention the file, but we noticed that it's gone.
349 dataStream->WriteEntityHeader(p, -1);
350 n++;
351 }
352 else if (cmp > 0) {
Joe Onorato3ad977b2009-05-05 11:50:51 -0700353 // file added
Joe Onorato23ecae32009-06-10 17:07:15 -0700354 LOGP("file added: %s", g.file);
355 write_update_file(dataStream, q, g.file);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700356 m++;
357 }
Joe Onorato3ad977b2009-05-05 11:50:51 -0700358 else {
359 // both files exist, check them
Joe Onorato3ad977b2009-05-05 11:50:51 -0700360 const FileState& f = oldSnapshot.valueAt(n);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700361
Joe Onorato23ecae32009-06-10 17:07:15 -0700362 int fd = open(g.file, O_RDONLY);
Christopher Tate0032ce82009-06-04 17:01:06 -0700363 if (fd < 0) {
Joe Onoratod2110db2009-05-19 13:41:21 -0700364 // We can't open the file. Don't report it as a delete either. Let the
365 // server keep the old version. Maybe they'll be able to deal with it
366 // on restore.
Joe Onorato23ecae32009-06-10 17:07:15 -0700367 LOGP("Unable to open file %s - skipping", g.file);
Joe Onoratod2110db2009-05-19 13:41:21 -0700368 } else {
Joe Onorato23ecae32009-06-10 17:07:15 -0700369 g.s.crc32 = compute_crc32(fd);
Joe Onoratod2110db2009-05-19 13:41:21 -0700370
Joe Onorato23ecae32009-06-10 17:07:15 -0700371 LOGP("%s", q.string());
372 LOGP(" new: modTime=%d,%d size=%-3d crc32=0x%08x",
Joe Onoratod2110db2009-05-19 13:41:21 -0700373 f.modTime_sec, f.modTime_nsec, f.size, f.crc32);
Joe Onorato23ecae32009-06-10 17:07:15 -0700374 LOGP(" old: modTime=%d,%d size=%-3d crc32=0x%08x",
375 g.s.modTime_sec, g.s.modTime_nsec, g.s.size, g.s.crc32);
376 if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec
377 || f.size != g.s.size || f.crc32 != g.s.crc32) {
378 write_update_file(dataStream, fd, p, g.file);
Joe Onoratod2110db2009-05-19 13:41:21 -0700379 }
380
381 close(fd);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700382 }
383 n++;
384 m++;
385 }
386 }
387
388 // these were deleted
389 while (n<N) {
Joe Onoratod2110db2009-05-19 13:41:21 -0700390 dataStream->WriteEntityHeader(oldSnapshot.keyAt(n), -1);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700391 n++;
392 }
393
394 // these were added
395 while (m<fileCount) {
396 const String8& q = newSnapshot.keyAt(m);
Joe Onorato23ecae32009-06-10 17:07:15 -0700397 FileRec& g = newSnapshot.editValueAt(m);
398 write_update_file(dataStream, q, g.file);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700399 m++;
400 }
401
402 err = write_snapshot_file(newSnapshotFD, newSnapshot);
403
404 return 0;
405}
406
407#if TEST_BACKUP_HELPERS
408
409#define SCRATCH_DIR "/data/backup_helper_test/"
410
411static int
412write_text_file(const char* path, const char* data)
413{
414 int amt;
415 int fd;
416 int len;
417
418 fd = creat(path, 0666);
419 if (fd == -1) {
420 fprintf(stderr, "creat %s failed\n", path);
421 return errno;
422 }
423
424 len = strlen(data);
425 amt = write(fd, data, len);
426 if (amt != len) {
427 fprintf(stderr, "error (%s) writing to file %s\n", strerror(errno), path);
428 return errno;
429 }
430
431 close(fd);
432
433 return 0;
434}
435
436static int
437compare_file(const char* path, const unsigned char* data, int len)
438{
439 int fd;
440 int amt;
441
442 fd = open(path, O_RDONLY);
443 if (fd == -1) {
444 fprintf(stderr, "compare_file error (%s) opening %s\n", strerror(errno), path);
445 return errno;
446 }
447
448 unsigned char* contents = (unsigned char*)malloc(len);
449 if (contents == NULL) {
450 fprintf(stderr, "malloc(%d) failed\n", len);
451 return ENOMEM;
452 }
453
454 bool sizesMatch = true;
455 amt = lseek(fd, 0, SEEK_END);
456 if (amt != len) {
457 fprintf(stderr, "compare_file file length should be %d, was %d\n", len, amt);
458 sizesMatch = false;
459 }
460 lseek(fd, 0, SEEK_SET);
461
462 int readLen = amt < len ? amt : len;
463 amt = read(fd, contents, readLen);
464 if (amt != readLen) {
465 fprintf(stderr, "compare_file read expected %d bytes but got %d\n", len, amt);
466 }
467
468 bool contentsMatch = true;
469 for (int i=0; i<readLen; i++) {
470 if (data[i] != contents[i]) {
471 if (contentsMatch) {
472 fprintf(stderr, "compare_file contents are different: (index, expected, actual)\n");
473 contentsMatch = false;
474 }
475 fprintf(stderr, " [%-2d] %02x %02x\n", i, data[i], contents[i]);
476 }
477 }
478
479 return contentsMatch && sizesMatch ? 0 : 1;
480}
481
482int
483backup_helper_test_empty()
484{
485 int err;
486 int fd;
Joe Onorato23ecae32009-06-10 17:07:15 -0700487 KeyedVector<String8,FileRec> snapshot;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700488 const char* filename = SCRATCH_DIR "backup_helper_test_empty.snap";
489
490 system("rm -r " SCRATCH_DIR);
491 mkdir(SCRATCH_DIR, 0777);
492
493 // write
494 fd = creat(filename, 0666);
495 if (fd == -1) {
496 fprintf(stderr, "error creating %s\n", filename);
497 return 1;
498 }
499
500 err = write_snapshot_file(fd, snapshot);
501
502 close(fd);
503
504 if (err != 0) {
505 fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err));
506 return err;
507 }
508
509 static const unsigned char correct_data[] = {
510 0x53, 0x6e, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00,
511 0x46, 0x69, 0x6c, 0x65, 0x10, 0x00, 0x00, 0x00
512 };
513
514 err = compare_file(filename, correct_data, sizeof(correct_data));
515 if (err != 0) {
516 return err;
517 }
518
519 // read
520 fd = open(filename, O_RDONLY);
521 if (fd == -1) {
522 fprintf(stderr, "error opening for read %s\n", filename);
523 return 1;
524 }
525
526 KeyedVector<String8,FileState> readSnapshot;
527 err = read_snapshot_file(fd, &readSnapshot);
528 if (err != 0) {
529 fprintf(stderr, "read_snapshot_file failed %d\n", err);
530 return err;
531 }
532
533 if (readSnapshot.size() != 0) {
534 fprintf(stderr, "readSnapshot should be length 0\n");
535 return 1;
536 }
537
538 return 0;
539}
540
541int
542backup_helper_test_four()
543{
544 int err;
545 int fd;
Joe Onorato23ecae32009-06-10 17:07:15 -0700546 KeyedVector<String8,FileRec> snapshot;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700547 const char* filename = SCRATCH_DIR "backup_helper_test_four.snap";
548
549 system("rm -r " SCRATCH_DIR);
550 mkdir(SCRATCH_DIR, 0777);
551
552 // write
553 fd = creat(filename, 0666);
554 if (fd == -1) {
555 fprintf(stderr, "error opening %s\n", filename);
556 return 1;
557 }
558
559 String8 filenames[4];
560 FileState states[4];
Joe Onorato23ecae32009-06-10 17:07:15 -0700561 FileRec r;
Joe Onoratoce88cb12009-06-11 11:27:16 -0700562 r.deleted = false;
Joe Onorato23ecae32009-06-10 17:07:15 -0700563 r.file = NULL;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700564
565 states[0].modTime_sec = 0xfedcba98;
566 states[0].modTime_nsec = 0xdeadbeef;
567 states[0].size = 0xababbcbc;
568 states[0].crc32 = 0x12345678;
569 states[0].nameLen = -12;
Joe Onorato23ecae32009-06-10 17:07:15 -0700570 r.s = states[0];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700571 filenames[0] = String8("bytes_of_padding");
Joe Onorato23ecae32009-06-10 17:07:15 -0700572 snapshot.add(filenames[0], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700573
574 states[1].modTime_sec = 0x93400031;
575 states[1].modTime_nsec = 0xdeadbeef;
576 states[1].size = 0x88557766;
577 states[1].crc32 = 0x22334422;
578 states[1].nameLen = -1;
Joe Onorato23ecae32009-06-10 17:07:15 -0700579 r.s = states[1];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700580 filenames[1] = String8("bytes_of_padding3");
Joe Onorato23ecae32009-06-10 17:07:15 -0700581 snapshot.add(filenames[1], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700582
583 states[2].modTime_sec = 0x33221144;
584 states[2].modTime_nsec = 0xdeadbeef;
585 states[2].size = 0x11223344;
586 states[2].crc32 = 0x01122334;
587 states[2].nameLen = 0;
Joe Onorato23ecae32009-06-10 17:07:15 -0700588 r.s = states[2];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700589 filenames[2] = String8("bytes_of_padding_2");
Joe Onorato23ecae32009-06-10 17:07:15 -0700590 snapshot.add(filenames[2], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700591
592 states[3].modTime_sec = 0x33221144;
593 states[3].modTime_nsec = 0xdeadbeef;
594 states[3].size = 0x11223344;
595 states[3].crc32 = 0x01122334;
596 states[3].nameLen = 0;
Joe Onorato23ecae32009-06-10 17:07:15 -0700597 r.s = states[3];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700598 filenames[3] = String8("bytes_of_padding__1");
Joe Onorato23ecae32009-06-10 17:07:15 -0700599 snapshot.add(filenames[3], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700600
601 err = write_snapshot_file(fd, snapshot);
602
603 close(fd);
604
605 if (err != 0) {
606 fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err));
607 return err;
608 }
609
610 static const unsigned char correct_data[] = {
611 // header
612 0x53, 0x6e, 0x61, 0x70, 0x04, 0x00, 0x00, 0x00,
613 0x46, 0x69, 0x6c, 0x65, 0xac, 0x00, 0x00, 0x00,
614
615 // bytes_of_padding
616 0x98, 0xba, 0xdc, 0xfe, 0xef, 0xbe, 0xad, 0xde,
617 0xbc, 0xbc, 0xab, 0xab, 0x78, 0x56, 0x34, 0x12,
618 0x10, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
619 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
620 0x64, 0x69, 0x6e, 0x67,
621
622 // bytes_of_padding3
623 0x31, 0x00, 0x40, 0x93, 0xef, 0xbe, 0xad, 0xde,
624 0x66, 0x77, 0x55, 0x88, 0x22, 0x44, 0x33, 0x22,
625 0x11, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
626 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
627 0x64, 0x69, 0x6e, 0x67, 0x33, 0xab, 0xab, 0xab,
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700628
Joe Onorato3ad977b2009-05-05 11:50:51 -0700629 // bytes of padding2
630 0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde,
631 0x44, 0x33, 0x22, 0x11, 0x34, 0x23, 0x12, 0x01,
632 0x12, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
633 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
634 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x32, 0xab, 0xab,
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700635
Joe Onorato3ad977b2009-05-05 11:50:51 -0700636 // bytes of padding3
637 0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde,
638 0x44, 0x33, 0x22, 0x11, 0x34, 0x23, 0x12, 0x01,
639 0x13, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
640 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
641 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x5f, 0x31, 0xab
642 };
643
644 err = compare_file(filename, correct_data, sizeof(correct_data));
645 if (err != 0) {
646 return err;
647 }
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700648
Joe Onorato3ad977b2009-05-05 11:50:51 -0700649 // read
650 fd = open(filename, O_RDONLY);
651 if (fd == -1) {
652 fprintf(stderr, "error opening for read %s\n", filename);
653 return 1;
654 }
655
656
657 KeyedVector<String8,FileState> readSnapshot;
658 err = read_snapshot_file(fd, &readSnapshot);
659 if (err != 0) {
660 fprintf(stderr, "read_snapshot_file failed %d\n", err);
661 return err;
662 }
663
664 if (readSnapshot.size() != 4) {
665 fprintf(stderr, "readSnapshot should be length 4 is %d\n", readSnapshot.size());
666 return 1;
667 }
668
669 bool matched = true;
670 for (size_t i=0; i<readSnapshot.size(); i++) {
671 const String8& name = readSnapshot.keyAt(i);
672 const FileState state = readSnapshot.valueAt(i);
673
674 if (name != filenames[i] || states[i].modTime_sec != state.modTime_sec
675 || states[i].modTime_nsec != state.modTime_nsec
676 || states[i].size != state.size || states[i].crc32 != states[i].crc32) {
677 fprintf(stderr, "state %d expected={%d/%d, 0x%08x, 0x%08x, %3d} '%s'\n"
678 " actual={%d/%d, 0x%08x, 0x%08x, %3d} '%s'\n", i,
679 states[i].modTime_sec, states[i].modTime_nsec, states[i].size, states[i].crc32,
680 name.length(), filenames[i].string(),
681 state.modTime_sec, state.modTime_nsec, state.size, state.crc32, state.nameLen,
682 name.string());
683 matched = false;
684 }
685 }
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700686
Joe Onorato3ad977b2009-05-05 11:50:51 -0700687 return matched ? 0 : 1;
688}
689
Joe Onorato4535e402009-05-15 09:07:06 -0400690// hexdump -v -e '" " 8/1 " 0x%02x," "\n"' data_writer.data
691const unsigned char DATA_GOLDEN_FILE[] = {
Joe Onorato2e1da322009-05-15 18:20:19 -0400692 0x44, 0x61, 0x74, 0x61, 0x0b, 0x00, 0x00, 0x00,
693 0x0c, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x5f, 0x70,
694 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00,
695 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69,
Joe Onorato5f15d152009-06-16 16:31:35 -0400696 0x6e, 0x67, 0x5f, 0x00, 0x44, 0x61, 0x74, 0x61,
697 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
Joe Onorato4535e402009-05-15 09:07:06 -0400698 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
699 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
Joe Onorato2e1da322009-05-15 18:20:19 -0400700 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
Joe Onorato5f15d152009-06-16 16:31:35 -0400701 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
Joe Onorato2e1da322009-05-15 18:20:19 -0400702 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,
Joe Onorato5f15d152009-06-16 16:31:35 -0400707 0x5f, 0x00, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61,
Joe Onorato4535e402009-05-15 09:07:06 -0400708 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
709 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
710 0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64,
Joe Onorato5f15d152009-06-16 16:31:35 -0400711 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00
712
Joe Onorato4535e402009-05-15 09:07:06 -0400713};
714const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE);
715
716static int
717test_write_header_and_entity(BackupDataWriter& writer, const char* str)
718{
719 int err;
720 String8 text(str);
721
Joe Onorato4535e402009-05-15 09:07:06 -0400722 err = writer.WriteEntityHeader(text, text.length()+1);
723 if (err != 0) {
724 fprintf(stderr, "WriteEntityHeader failed with %s\n", strerror(err));
725 return err;
726 }
727
728 err = writer.WriteEntityData(text.string(), text.length()+1);
729 if (err != 0) {
730 fprintf(stderr, "write failed for data '%s'\n", text.string());
731 return errno;
732 }
733
734 return err;
735}
736
737int
738backup_helper_test_data_writer()
739{
740 int err;
741 int fd;
742 const char* filename = SCRATCH_DIR "data_writer.data";
743
744 system("rm -r " SCRATCH_DIR);
745 mkdir(SCRATCH_DIR, 0777);
746 mkdir(SCRATCH_DIR "data", 0777);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700747
Joe Onorato4535e402009-05-15 09:07:06 -0400748 fd = creat(filename, 0666);
749 if (fd == -1) {
750 fprintf(stderr, "error creating: %s\n", strerror(errno));
751 return errno;
752 }
753
754 BackupDataWriter writer(fd);
755
756 err = 0;
757 err |= test_write_header_and_entity(writer, "no_padding_");
758 err |= test_write_header_and_entity(writer, "padded_to__3");
759 err |= test_write_header_and_entity(writer, "padded_to_2__");
760 err |= test_write_header_and_entity(writer, "padded_to1");
761
Joe Onorato4535e402009-05-15 09:07:06 -0400762 close(fd);
763
764 err = compare_file(filename, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
765 if (err != 0) {
766 return err;
767 }
768
769 return err;
770}
771
Joe Onorato2e1da322009-05-15 18:20:19 -0400772int
773test_read_header_and_entity(BackupDataReader& reader, const char* str)
774{
775 int err;
776 int bufSize = strlen(str)+1;
777 char* buf = (char*)malloc(bufSize);
778 String8 string;
779 int cookie = 0x11111111;
780 size_t actualSize;
Joe Onorato5f15d152009-06-16 16:31:35 -0400781 bool done;
782 int type;
Joe Onorato2e1da322009-05-15 18:20:19 -0400783
784 // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str);
785
Joe Onorato5f15d152009-06-16 16:31:35 -0400786 err = reader.ReadNextHeader(&done, &type);
787 if (done) {
788 fprintf(stderr, "should not be done yet\n");
789 goto finished;
790 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400791 if (err != 0) {
792 fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400793 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400794 }
Joe Onorato5f15d152009-06-16 16:31:35 -0400795 if (type != BACKUP_HEADER_ENTITY_V1) {
Joe Onorato2e1da322009-05-15 18:20:19 -0400796 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400797 fprintf(stderr, "type=0x%08x expected 0x%08x\n", type, BACKUP_HEADER_ENTITY_V1);
Joe Onorato2e1da322009-05-15 18:20:19 -0400798 }
799
800 err = reader.ReadEntityHeader(&string, &actualSize);
801 if (err != 0) {
802 fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400803 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400804 }
805 if (string != str) {
806 fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.string());
807 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400808 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400809 }
810 if ((int)actualSize != bufSize) {
811 fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize,
812 actualSize);
813 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400814 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400815 }
816
817 err = reader.ReadEntityData(buf, bufSize);
818 if (err != NO_ERROR) {
819 fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400820 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400821 }
822
823 if (0 != memcmp(buf, str, bufSize)) {
824 fprintf(stderr, "ReadEntityData expected '%s' but got something starting with "
Joe Onorato5f15d152009-06-16 16:31:35 -0400825 "%02x %02x %02x %02x '%c%c%c%c'\n", str, buf[0], buf[1], buf[2], buf[3],
826 buf[0], buf[1], buf[2], buf[3]);
Joe Onorato2e1da322009-05-15 18:20:19 -0400827 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400828 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400829 }
830
831 // The next read will confirm whether it got the right amount of data.
832
Joe Onorato5f15d152009-06-16 16:31:35 -0400833finished:
Joe Onorato2e1da322009-05-15 18:20:19 -0400834 if (err != NO_ERROR) {
835 fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err));
836 }
837 free(buf);
838 return err;
839}
840
841int
842backup_helper_test_data_reader()
843{
844 int err;
845 int fd;
846 const char* filename = SCRATCH_DIR "data_reader.data";
847
848 system("rm -r " SCRATCH_DIR);
849 mkdir(SCRATCH_DIR, 0777);
850 mkdir(SCRATCH_DIR "data", 0777);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700851
Joe Onorato2e1da322009-05-15 18:20:19 -0400852 fd = creat(filename, 0666);
853 if (fd == -1) {
854 fprintf(stderr, "error creating: %s\n", strerror(errno));
855 return errno;
856 }
857
858 err = write(fd, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
859 if (err != DATA_GOLDEN_FILE_SIZE) {
860 fprintf(stderr, "Error \"%s\" writing golden file %s\n", strerror(errno), filename);
861 return errno;
862 }
863
864 close(fd);
865
866 fd = open(filename, O_RDONLY);
867 if (fd == -1) {
868 fprintf(stderr, "Error \"%s\" opening golden file %s for read\n", strerror(errno),
869 filename);
870 return errno;
871 }
872
873 {
874 BackupDataReader reader(fd);
875
876 err = 0;
877
878 if (err == NO_ERROR) {
879 err = test_read_header_and_entity(reader, "no_padding_");
880 }
881
882 if (err == NO_ERROR) {
883 err = test_read_header_and_entity(reader, "padded_to__3");
884 }
885
886 if (err == NO_ERROR) {
887 err = test_read_header_and_entity(reader, "padded_to_2__");
888 }
889
890 if (err == NO_ERROR) {
891 err = test_read_header_and_entity(reader, "padded_to1");
892 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400893 }
894
895 close(fd);
896
897 return err;
898}
899
Joe Onorato3ad977b2009-05-05 11:50:51 -0700900static int
901get_mod_time(const char* filename, struct timeval times[2])
902{
903 int err;
904 struct stat64 st;
905 err = stat64(filename, &st);
906 if (err != 0) {
907 fprintf(stderr, "stat '%s' failed: %s\n", filename, strerror(errno));
908 return errno;
909 }
910 times[0].tv_sec = st.st_atime;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700911 times[1].tv_sec = st.st_mtime;
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700912
913 // If st_atime is a macro then struct stat64 uses struct timespec
914 // to store the access and modif time values and typically
915 // st_*time_nsec is not defined. In glibc, this is controlled by
916 // __USE_MISC.
917#ifdef __USE_MISC
918#if !defined(st_atime) || defined(st_atime_nsec)
919#error "Check if this __USE_MISC conditional is still needed."
920#endif
921 times[0].tv_usec = st.st_atim.tv_nsec / 1000;
922 times[1].tv_usec = st.st_mtim.tv_nsec / 1000;
923#else
924 times[0].tv_usec = st.st_atime_nsec / 1000;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700925 times[1].tv_usec = st.st_mtime_nsec / 1000;
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700926#endif
927
Joe Onorato3ad977b2009-05-05 11:50:51 -0700928 return 0;
929}
930
931int
932backup_helper_test_files()
933{
934 int err;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700935 int oldSnapshotFD;
Joe Onorato4535e402009-05-15 09:07:06 -0400936 int dataStreamFD;
937 int newSnapshotFD;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700938
939 system("rm -r " SCRATCH_DIR);
940 mkdir(SCRATCH_DIR, 0777);
941 mkdir(SCRATCH_DIR "data", 0777);
942
943 write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
944 write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
945 write_text_file(SCRATCH_DIR "data/d", "d\ndd\n");
946 write_text_file(SCRATCH_DIR "data/e", "e\nee\n");
947 write_text_file(SCRATCH_DIR "data/f", "f\nff\n");
948 write_text_file(SCRATCH_DIR "data/h", "h\nhh\n");
949
950 char const* files_before[] = {
Joe Onorato23ecae32009-06-10 17:07:15 -0700951 SCRATCH_DIR "data/b",
952 SCRATCH_DIR "data/c",
953 SCRATCH_DIR "data/d",
954 SCRATCH_DIR "data/e",
955 SCRATCH_DIR "data/f"
956 };
957
958 char const* keys_before[] = {
Joe Onorato3ad977b2009-05-05 11:50:51 -0700959 "data/b",
960 "data/c",
961 "data/d",
962 "data/e",
963 "data/f"
964 };
965
Joe Onorato4535e402009-05-15 09:07:06 -0400966 dataStreamFD = creat(SCRATCH_DIR "1.data", 0666);
967 if (dataStreamFD == -1) {
968 fprintf(stderr, "error creating: %s\n", strerror(errno));
969 return errno;
970 }
971
Joe Onorato3ad977b2009-05-05 11:50:51 -0700972 newSnapshotFD = creat(SCRATCH_DIR "before.snap", 0666);
973 if (newSnapshotFD == -1) {
974 fprintf(stderr, "error creating: %s\n", strerror(errno));
975 return errno;
976 }
Joe Onoratod2110db2009-05-19 13:41:21 -0700977
978 {
979 BackupDataWriter dataStream(dataStreamFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700980
Joe Onorato23ecae32009-06-10 17:07:15 -0700981 err = back_up_files(-1, &dataStream, newSnapshotFD, files_before, keys_before, 5);
Joe Onoratod2110db2009-05-19 13:41:21 -0700982 if (err != 0) {
983 return err;
984 }
Joe Onorato3ad977b2009-05-05 11:50:51 -0700985 }
986
Joe Onorato4535e402009-05-15 09:07:06 -0400987 close(dataStreamFD);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700988 close(newSnapshotFD);
989
990 sleep(3);
991
992 struct timeval d_times[2];
993 struct timeval e_times[2];
994
995 err = get_mod_time(SCRATCH_DIR "data/d", d_times);
996 err |= get_mod_time(SCRATCH_DIR "data/e", e_times);
997 if (err != 0) {
998 return err;
999 }
1000
1001 write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
1002 unlink(SCRATCH_DIR "data/c");
1003 write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
1004 write_text_file(SCRATCH_DIR "data/d", "dd\ndd\n");
1005 utimes(SCRATCH_DIR "data/d", d_times);
1006 write_text_file(SCRATCH_DIR "data/e", "z\nzz\n");
1007 utimes(SCRATCH_DIR "data/e", e_times);
1008 write_text_file(SCRATCH_DIR "data/g", "g\ngg\n");
1009 unlink(SCRATCH_DIR "data/f");
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001010
Joe Onorato3ad977b2009-05-05 11:50:51 -07001011 char const* files_after[] = {
Joe Onorato23ecae32009-06-10 17:07:15 -07001012 SCRATCH_DIR "data/a", // added
1013 SCRATCH_DIR "data/b", // same
1014 SCRATCH_DIR "data/c", // different mod time
1015 SCRATCH_DIR "data/d", // different size (same mod time)
1016 SCRATCH_DIR "data/e", // different contents (same mod time, same size)
1017 SCRATCH_DIR "data/g" // added
1018 };
1019
1020 char const* keys_after[] = {
Joe Onorato3ad977b2009-05-05 11:50:51 -07001021 "data/a", // added
1022 "data/b", // same
1023 "data/c", // different mod time
1024 "data/d", // different size (same mod time)
1025 "data/e", // different contents (same mod time, same size)
1026 "data/g" // added
1027 };
1028
1029 oldSnapshotFD = open(SCRATCH_DIR "before.snap", O_RDONLY);
1030 if (oldSnapshotFD == -1) {
1031 fprintf(stderr, "error opening: %s\n", strerror(errno));
1032 return errno;
1033 }
1034
Joe Onorato4535e402009-05-15 09:07:06 -04001035 dataStreamFD = creat(SCRATCH_DIR "2.data", 0666);
1036 if (dataStreamFD == -1) {
1037 fprintf(stderr, "error creating: %s\n", strerror(errno));
1038 return errno;
1039 }
1040
Joe Onorato3ad977b2009-05-05 11:50:51 -07001041 newSnapshotFD = creat(SCRATCH_DIR "after.snap", 0666);
1042 if (newSnapshotFD == -1) {
1043 fprintf(stderr, "error creating: %s\n", strerror(errno));
1044 return errno;
1045 }
1046
Joe Onoratod2110db2009-05-19 13:41:21 -07001047 {
1048 BackupDataWriter dataStream(dataStreamFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001049
Joe Onorato23ecae32009-06-10 17:07:15 -07001050 err = back_up_files(oldSnapshotFD, &dataStream, newSnapshotFD, files_after, keys_after, 6);
Joe Onoratod2110db2009-05-19 13:41:21 -07001051 if (err != 0) {
1052 return err;
1053 }
1054}
Joe Onorato3ad977b2009-05-05 11:50:51 -07001055
1056 close(oldSnapshotFD);
Joe Onorato4535e402009-05-15 09:07:06 -04001057 close(dataStreamFD);
Joe Onorato3ad977b2009-05-05 11:50:51 -07001058 close(newSnapshotFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001059
Joe Onorato3ad977b2009-05-05 11:50:51 -07001060 return 0;
1061}
1062
Joe Onorato23ecae32009-06-10 17:07:15 -07001063int
1064backup_helper_test_null_base()
1065{
1066 int err;
1067 int oldSnapshotFD;
1068 int dataStreamFD;
1069 int newSnapshotFD;
1070
1071 system("rm -r " SCRATCH_DIR);
1072 mkdir(SCRATCH_DIR, 0777);
1073 mkdir(SCRATCH_DIR "data", 0777);
1074
1075 write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
1076
1077 char const* files[] = {
1078 SCRATCH_DIR "data/a",
1079 };
1080
1081 char const* keys[] = {
1082 "a",
1083 };
1084
1085 dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
1086 if (dataStreamFD == -1) {
1087 fprintf(stderr, "error creating: %s\n", strerror(errno));
1088 return errno;
1089 }
1090
1091 newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
1092 if (newSnapshotFD == -1) {
1093 fprintf(stderr, "error creating: %s\n", strerror(errno));
1094 return errno;
1095 }
1096
1097 {
1098 BackupDataWriter dataStream(dataStreamFD);
1099
1100 err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
1101 if (err != 0) {
1102 return err;
1103 }
1104 }
1105
1106 close(dataStreamFD);
1107 close(newSnapshotFD);
1108
1109 return 0;
1110}
1111
Joe Onoratoce88cb12009-06-11 11:27:16 -07001112int
1113backup_helper_test_missing_file()
1114{
1115 int err;
1116 int oldSnapshotFD;
1117 int dataStreamFD;
1118 int newSnapshotFD;
1119
1120 system("rm -r " SCRATCH_DIR);
1121 mkdir(SCRATCH_DIR, 0777);
1122 mkdir(SCRATCH_DIR "data", 0777);
1123
1124 write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
1125
1126 char const* files[] = {
1127 SCRATCH_DIR "data/a",
1128 SCRATCH_DIR "data/b",
1129 SCRATCH_DIR "data/c",
1130 };
1131
1132 char const* keys[] = {
1133 "a",
1134 "b",
1135 "c",
1136 };
1137
1138 dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
1139 if (dataStreamFD == -1) {
1140 fprintf(stderr, "error creating: %s\n", strerror(errno));
1141 return errno;
1142 }
1143
1144 newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
1145 if (newSnapshotFD == -1) {
1146 fprintf(stderr, "error creating: %s\n", strerror(errno));
1147 return errno;
1148 }
1149
1150 {
1151 BackupDataWriter dataStream(dataStreamFD);
1152
1153 err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
1154 if (err != 0) {
1155 return err;
1156 }
1157 }
1158
1159 close(dataStreamFD);
1160 close(newSnapshotFD);
1161
1162 return 0;
1163}
1164
Joe Onorato23ecae32009-06-10 17:07:15 -07001165
Joe Onorato3ad977b2009-05-05 11:50:51 -07001166#endif // TEST_BACKUP_HELPERS
Joe Onorato4535e402009-05-15 09:07:06 -04001167
1168}