blob: 4c3e37dd1cad7cfaf8d0b7603ab437f72d5fc54e [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[] = {
692 0x41, 0x70, 0x70, 0x31, 0x0b, 0x00, 0x00, 0x00,
Joe Onorato2e1da322009-05-15 18:20:19 -0400693 0xdd, 0xcc, 0xbb, 0xaa, 0x6e, 0x6f, 0x5f, 0x70,
Joe Onorato4535e402009-05-15 09:07:06 -0400694 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00,
Joe Onorato2e1da322009-05-15 18:20:19 -0400695 0x44, 0x61, 0x74, 0x61, 0x0b, 0x00, 0x00, 0x00,
696 0x0c, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x5f, 0x70,
697 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00,
698 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69,
699 0x6e, 0x67, 0x5f, 0x00, 0x41, 0x70, 0x70, 0x31,
700 0x0c, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa,
Joe Onorato4535e402009-05-15 09:07:06 -0400701 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
702 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
703 0x44, 0x61, 0x74, 0x61, 0x0c, 0x00, 0x00, 0x00,
704 0x0d, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
705 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33,
706 0x00, 0xbc, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64,
707 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33,
708 0x00, 0xbc, 0xbc, 0xbc, 0x41, 0x70, 0x70, 0x31,
Joe Onorato2e1da322009-05-15 18:20:19 -0400709 0x0d, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa,
710 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
711 0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc,
712 0x44, 0x61, 0x74, 0x61, 0x0d, 0x00, 0x00, 0x00,
713 0x0e, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
Joe Onorato4535e402009-05-15 09:07:06 -0400714 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
Joe Onorato2e1da322009-05-15 18:20:19 -0400715 0x5f, 0x00, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64,
716 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
717 0x5f, 0x00, 0xbc, 0xbc, 0x41, 0x70, 0x70, 0x31,
718 0x0a, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa,
Joe Onorato4535e402009-05-15 09:07:06 -0400719 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
720 0x6f, 0x31, 0x00, 0xbc, 0x44, 0x61, 0x74, 0x61,
721 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
722 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
723 0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64,
724 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00, 0xbc,
725 0x46, 0x6f, 0x6f, 0x74, 0x04, 0x00, 0x00, 0x00,
Joe Onorato2e1da322009-05-15 18:20:19 -0400726 0x99, 0x99, 0x77, 0x77
Joe Onorato4535e402009-05-15 09:07:06 -0400727};
728const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE);
729
730static int
731test_write_header_and_entity(BackupDataWriter& writer, const char* str)
732{
733 int err;
734 String8 text(str);
735
Joe Onorato2e1da322009-05-15 18:20:19 -0400736 err = writer.WriteAppHeader(text, 0xaabbccdd);
Joe Onorato4535e402009-05-15 09:07:06 -0400737 if (err != 0) {
738 fprintf(stderr, "WriteAppHeader failed with %s\n", strerror(err));
739 return err;
740 }
741
742 err = writer.WriteEntityHeader(text, text.length()+1);
743 if (err != 0) {
744 fprintf(stderr, "WriteEntityHeader failed with %s\n", strerror(err));
745 return err;
746 }
747
748 err = writer.WriteEntityData(text.string(), text.length()+1);
749 if (err != 0) {
750 fprintf(stderr, "write failed for data '%s'\n", text.string());
751 return errno;
752 }
753
754 return err;
755}
756
757int
758backup_helper_test_data_writer()
759{
760 int err;
761 int fd;
762 const char* filename = SCRATCH_DIR "data_writer.data";
763
764 system("rm -r " SCRATCH_DIR);
765 mkdir(SCRATCH_DIR, 0777);
766 mkdir(SCRATCH_DIR "data", 0777);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700767
Joe Onorato4535e402009-05-15 09:07:06 -0400768 fd = creat(filename, 0666);
769 if (fd == -1) {
770 fprintf(stderr, "error creating: %s\n", strerror(errno));
771 return errno;
772 }
773
774 BackupDataWriter writer(fd);
775
776 err = 0;
777 err |= test_write_header_and_entity(writer, "no_padding_");
778 err |= test_write_header_and_entity(writer, "padded_to__3");
779 err |= test_write_header_and_entity(writer, "padded_to_2__");
780 err |= test_write_header_and_entity(writer, "padded_to1");
781
Joe Onorato2e1da322009-05-15 18:20:19 -0400782 writer.WriteAppFooter(0x77779999);
Joe Onorato4535e402009-05-15 09:07:06 -0400783
784 close(fd);
785
786 err = compare_file(filename, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
787 if (err != 0) {
788 return err;
789 }
790
791 return err;
792}
793
Joe Onorato2e1da322009-05-15 18:20:19 -0400794int
795test_read_header_and_entity(BackupDataReader& reader, const char* str)
796{
797 int err;
798 int bufSize = strlen(str)+1;
799 char* buf = (char*)malloc(bufSize);
800 String8 string;
801 int cookie = 0x11111111;
802 size_t actualSize;
803
804 // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str);
805
806 err = reader.ReadNextHeader();
807 if (err != 0) {
808 fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err));
809 goto done;
810 }
811
812 err = reader.ReadAppHeader(&string, &cookie);
813 if (err != 0) {
814 fprintf(stderr, "ReadAppHeader failed with %s\n", strerror(err));
815 goto done;
816 }
817 if (string != str) {
818 fprintf(stderr, "ReadAppHeader expected packageName '%s' got '%s'\n", str, string.string());
819 err = EINVAL;
820 goto done;
821 }
822 if (cookie != (int)0xaabbccdd) {
823 fprintf(stderr, "ReadAppHeader expected cookie 0x%08x got 0x%08x\n", 0xaabbccdd, cookie);
824 err = EINVAL;
825 goto done;
826 }
827
828 err = reader.ReadNextHeader();
829 if (err != 0) {
830 fprintf(stderr, "ReadNextHeader (for entity header) failed with %s\n", strerror(err));
831 goto done;
832 }
833
834 err = reader.ReadEntityHeader(&string, &actualSize);
835 if (err != 0) {
836 fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err));
837 goto done;
838 }
839 if (string != str) {
840 fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.string());
841 err = EINVAL;
842 goto done;
843 }
844 if ((int)actualSize != bufSize) {
845 fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize,
846 actualSize);
847 err = EINVAL;
848 goto done;
849 }
850
851 err = reader.ReadEntityData(buf, bufSize);
852 if (err != NO_ERROR) {
853 fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err));
854 goto done;
855 }
856
857 if (0 != memcmp(buf, str, bufSize)) {
858 fprintf(stderr, "ReadEntityData expected '%s' but got something starting with "
859 "%02x %02x %02x %02x\n", str, buf[0], buf[1], buf[2], buf[3]);
860 err = EINVAL;
861 goto done;
862 }
863
864 // The next read will confirm whether it got the right amount of data.
865
866done:
867 if (err != NO_ERROR) {
868 fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err));
869 }
870 free(buf);
871 return err;
872}
873
874int
875backup_helper_test_data_reader()
876{
877 int err;
878 int fd;
879 const char* filename = SCRATCH_DIR "data_reader.data";
880
881 system("rm -r " SCRATCH_DIR);
882 mkdir(SCRATCH_DIR, 0777);
883 mkdir(SCRATCH_DIR "data", 0777);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700884
Joe Onorato2e1da322009-05-15 18:20:19 -0400885 fd = creat(filename, 0666);
886 if (fd == -1) {
887 fprintf(stderr, "error creating: %s\n", strerror(errno));
888 return errno;
889 }
890
891 err = write(fd, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
892 if (err != DATA_GOLDEN_FILE_SIZE) {
893 fprintf(stderr, "Error \"%s\" writing golden file %s\n", strerror(errno), filename);
894 return errno;
895 }
896
897 close(fd);
898
899 fd = open(filename, O_RDONLY);
900 if (fd == -1) {
901 fprintf(stderr, "Error \"%s\" opening golden file %s for read\n", strerror(errno),
902 filename);
903 return errno;
904 }
905
906 {
907 BackupDataReader reader(fd);
908
909 err = 0;
910
911 if (err == NO_ERROR) {
912 err = test_read_header_and_entity(reader, "no_padding_");
913 }
914
915 if (err == NO_ERROR) {
916 err = test_read_header_and_entity(reader, "padded_to__3");
917 }
918
919 if (err == NO_ERROR) {
920 err = test_read_header_and_entity(reader, "padded_to_2__");
921 }
922
923 if (err == NO_ERROR) {
924 err = test_read_header_and_entity(reader, "padded_to1");
925 }
926
927 if (err == NO_ERROR) {
928 err = reader.ReadNextHeader();
929 if (err != 0) {
930 fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err));
931 }
932
933 if (err == NO_ERROR) {
934 int cookie;
935 err |= reader.ReadAppFooter(&cookie);
936 if (cookie != 0x77779999) {
937 fprintf(stderr, "app footer cookie expected=0x%08x actual=0x%08x\n",
938 0x77779999, cookie);
939 err = EINVAL;
940 }
941 }
942 }
943 }
944
945 close(fd);
946
947 return err;
948}
949
Joe Onorato3ad977b2009-05-05 11:50:51 -0700950static int
951get_mod_time(const char* filename, struct timeval times[2])
952{
953 int err;
954 struct stat64 st;
955 err = stat64(filename, &st);
956 if (err != 0) {
957 fprintf(stderr, "stat '%s' failed: %s\n", filename, strerror(errno));
958 return errno;
959 }
960 times[0].tv_sec = st.st_atime;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700961 times[1].tv_sec = st.st_mtime;
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700962
963 // If st_atime is a macro then struct stat64 uses struct timespec
964 // to store the access and modif time values and typically
965 // st_*time_nsec is not defined. In glibc, this is controlled by
966 // __USE_MISC.
967#ifdef __USE_MISC
968#if !defined(st_atime) || defined(st_atime_nsec)
969#error "Check if this __USE_MISC conditional is still needed."
970#endif
971 times[0].tv_usec = st.st_atim.tv_nsec / 1000;
972 times[1].tv_usec = st.st_mtim.tv_nsec / 1000;
973#else
974 times[0].tv_usec = st.st_atime_nsec / 1000;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700975 times[1].tv_usec = st.st_mtime_nsec / 1000;
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700976#endif
977
Joe Onorato3ad977b2009-05-05 11:50:51 -0700978 return 0;
979}
980
981int
982backup_helper_test_files()
983{
984 int err;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700985 int oldSnapshotFD;
Joe Onorato4535e402009-05-15 09:07:06 -0400986 int dataStreamFD;
987 int newSnapshotFD;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700988
989 system("rm -r " SCRATCH_DIR);
990 mkdir(SCRATCH_DIR, 0777);
991 mkdir(SCRATCH_DIR "data", 0777);
992
993 write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
994 write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
995 write_text_file(SCRATCH_DIR "data/d", "d\ndd\n");
996 write_text_file(SCRATCH_DIR "data/e", "e\nee\n");
997 write_text_file(SCRATCH_DIR "data/f", "f\nff\n");
998 write_text_file(SCRATCH_DIR "data/h", "h\nhh\n");
999
1000 char const* files_before[] = {
Joe Onorato23ecae32009-06-10 17:07:15 -07001001 SCRATCH_DIR "data/b",
1002 SCRATCH_DIR "data/c",
1003 SCRATCH_DIR "data/d",
1004 SCRATCH_DIR "data/e",
1005 SCRATCH_DIR "data/f"
1006 };
1007
1008 char const* keys_before[] = {
Joe Onorato3ad977b2009-05-05 11:50:51 -07001009 "data/b",
1010 "data/c",
1011 "data/d",
1012 "data/e",
1013 "data/f"
1014 };
1015
Joe Onorato4535e402009-05-15 09:07:06 -04001016 dataStreamFD = creat(SCRATCH_DIR "1.data", 0666);
1017 if (dataStreamFD == -1) {
1018 fprintf(stderr, "error creating: %s\n", strerror(errno));
1019 return errno;
1020 }
1021
Joe Onorato3ad977b2009-05-05 11:50:51 -07001022 newSnapshotFD = creat(SCRATCH_DIR "before.snap", 0666);
1023 if (newSnapshotFD == -1) {
1024 fprintf(stderr, "error creating: %s\n", strerror(errno));
1025 return errno;
1026 }
Joe Onoratod2110db2009-05-19 13:41:21 -07001027
1028 {
1029 BackupDataWriter dataStream(dataStreamFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001030
Joe Onorato23ecae32009-06-10 17:07:15 -07001031 err = back_up_files(-1, &dataStream, newSnapshotFD, files_before, keys_before, 5);
Joe Onoratod2110db2009-05-19 13:41:21 -07001032 if (err != 0) {
1033 return err;
1034 }
Joe Onorato3ad977b2009-05-05 11:50:51 -07001035 }
1036
Joe Onorato4535e402009-05-15 09:07:06 -04001037 close(dataStreamFD);
Joe Onorato3ad977b2009-05-05 11:50:51 -07001038 close(newSnapshotFD);
1039
1040 sleep(3);
1041
1042 struct timeval d_times[2];
1043 struct timeval e_times[2];
1044
1045 err = get_mod_time(SCRATCH_DIR "data/d", d_times);
1046 err |= get_mod_time(SCRATCH_DIR "data/e", e_times);
1047 if (err != 0) {
1048 return err;
1049 }
1050
1051 write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
1052 unlink(SCRATCH_DIR "data/c");
1053 write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
1054 write_text_file(SCRATCH_DIR "data/d", "dd\ndd\n");
1055 utimes(SCRATCH_DIR "data/d", d_times);
1056 write_text_file(SCRATCH_DIR "data/e", "z\nzz\n");
1057 utimes(SCRATCH_DIR "data/e", e_times);
1058 write_text_file(SCRATCH_DIR "data/g", "g\ngg\n");
1059 unlink(SCRATCH_DIR "data/f");
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001060
Joe Onorato3ad977b2009-05-05 11:50:51 -07001061 char const* files_after[] = {
Joe Onorato23ecae32009-06-10 17:07:15 -07001062 SCRATCH_DIR "data/a", // added
1063 SCRATCH_DIR "data/b", // same
1064 SCRATCH_DIR "data/c", // different mod time
1065 SCRATCH_DIR "data/d", // different size (same mod time)
1066 SCRATCH_DIR "data/e", // different contents (same mod time, same size)
1067 SCRATCH_DIR "data/g" // added
1068 };
1069
1070 char const* keys_after[] = {
Joe Onorato3ad977b2009-05-05 11:50:51 -07001071 "data/a", // added
1072 "data/b", // same
1073 "data/c", // different mod time
1074 "data/d", // different size (same mod time)
1075 "data/e", // different contents (same mod time, same size)
1076 "data/g" // added
1077 };
1078
1079 oldSnapshotFD = open(SCRATCH_DIR "before.snap", O_RDONLY);
1080 if (oldSnapshotFD == -1) {
1081 fprintf(stderr, "error opening: %s\n", strerror(errno));
1082 return errno;
1083 }
1084
Joe Onorato4535e402009-05-15 09:07:06 -04001085 dataStreamFD = creat(SCRATCH_DIR "2.data", 0666);
1086 if (dataStreamFD == -1) {
1087 fprintf(stderr, "error creating: %s\n", strerror(errno));
1088 return errno;
1089 }
1090
Joe Onorato3ad977b2009-05-05 11:50:51 -07001091 newSnapshotFD = creat(SCRATCH_DIR "after.snap", 0666);
1092 if (newSnapshotFD == -1) {
1093 fprintf(stderr, "error creating: %s\n", strerror(errno));
1094 return errno;
1095 }
1096
Joe Onoratod2110db2009-05-19 13:41:21 -07001097 {
1098 BackupDataWriter dataStream(dataStreamFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001099
Joe Onorato23ecae32009-06-10 17:07:15 -07001100 err = back_up_files(oldSnapshotFD, &dataStream, newSnapshotFD, files_after, keys_after, 6);
Joe Onoratod2110db2009-05-19 13:41:21 -07001101 if (err != 0) {
1102 return err;
1103 }
1104}
Joe Onorato3ad977b2009-05-05 11:50:51 -07001105
1106 close(oldSnapshotFD);
Joe Onorato4535e402009-05-15 09:07:06 -04001107 close(dataStreamFD);
Joe Onorato3ad977b2009-05-05 11:50:51 -07001108 close(newSnapshotFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001109
Joe Onorato3ad977b2009-05-05 11:50:51 -07001110 return 0;
1111}
1112
Joe Onorato23ecae32009-06-10 17:07:15 -07001113int
1114backup_helper_test_null_base()
1115{
1116 int err;
1117 int oldSnapshotFD;
1118 int dataStreamFD;
1119 int newSnapshotFD;
1120
1121 system("rm -r " SCRATCH_DIR);
1122 mkdir(SCRATCH_DIR, 0777);
1123 mkdir(SCRATCH_DIR "data", 0777);
1124
1125 write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
1126
1127 char const* files[] = {
1128 SCRATCH_DIR "data/a",
1129 };
1130
1131 char const* keys[] = {
1132 "a",
1133 };
1134
1135 dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
1136 if (dataStreamFD == -1) {
1137 fprintf(stderr, "error creating: %s\n", strerror(errno));
1138 return errno;
1139 }
1140
1141 newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
1142 if (newSnapshotFD == -1) {
1143 fprintf(stderr, "error creating: %s\n", strerror(errno));
1144 return errno;
1145 }
1146
1147 {
1148 BackupDataWriter dataStream(dataStreamFD);
1149
1150 err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
1151 if (err != 0) {
1152 return err;
1153 }
1154 }
1155
1156 close(dataStreamFD);
1157 close(newSnapshotFD);
1158
1159 return 0;
1160}
1161
Joe Onoratoce88cb12009-06-11 11:27:16 -07001162int
1163backup_helper_test_missing_file()
1164{
1165 int err;
1166 int oldSnapshotFD;
1167 int dataStreamFD;
1168 int newSnapshotFD;
1169
1170 system("rm -r " SCRATCH_DIR);
1171 mkdir(SCRATCH_DIR, 0777);
1172 mkdir(SCRATCH_DIR "data", 0777);
1173
1174 write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
1175
1176 char const* files[] = {
1177 SCRATCH_DIR "data/a",
1178 SCRATCH_DIR "data/b",
1179 SCRATCH_DIR "data/c",
1180 };
1181
1182 char const* keys[] = {
1183 "a",
1184 "b",
1185 "c",
1186 };
1187
1188 dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
1189 if (dataStreamFD == -1) {
1190 fprintf(stderr, "error creating: %s\n", strerror(errno));
1191 return errno;
1192 }
1193
1194 newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
1195 if (newSnapshotFD == -1) {
1196 fprintf(stderr, "error creating: %s\n", strerror(errno));
1197 return errno;
1198 }
1199
1200 {
1201 BackupDataWriter dataStream(dataStreamFD);
1202
1203 err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
1204 if (err != 0) {
1205 return err;
1206 }
1207 }
1208
1209 close(dataStreamFD);
1210 close(newSnapshotFD);
1211
1212 return 0;
1213}
1214
Joe Onorato23ecae32009-06-10 17:07:15 -07001215
Joe Onorato3ad977b2009-05-05 11:50:51 -07001216#endif // TEST_BACKUP_HELPERS
Joe Onorato4535e402009-05-15 09:07:06 -04001217
1218}