blob: 99687bc8f636764e09eb06f099e567dc5a6ffaea [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 -070050const static int ROUND_UP[4] = { 0, 3, 2, 1 };
51
52static inline int
53round_up(int n)
54{
55 return n + ROUND_UP[n % 4];
56}
57
58static int
59read_snapshot_file(int fd, KeyedVector<String8,FileState>* snapshot)
60{
61 int bytesRead = 0;
62 int amt;
63 SnapshotHeader header;
64
65 amt = read(fd, &header, sizeof(header));
66 if (amt != sizeof(header)) {
67 return errno;
68 }
69 bytesRead += amt;
70
71 if (header.magic0 != MAGIC0 || header.magic1 != MAGIC1) {
72 LOGW("read_snapshot_file header.magic0=0x%08x magic1=0x%08x", header.magic0, header.magic1);
73 return 1;
74 }
75
76 for (int i=0; i<header.fileCount; i++) {
77 FileState file;
78 char filenameBuf[128];
79
Joe Onorato23ecae32009-06-10 17:07:15 -070080 amt = read(fd, &file, sizeof(FileState));
81 if (amt != sizeof(FileState)) {
Joe Onorato3ad977b2009-05-05 11:50:51 -070082 LOGW("read_snapshot_file FileState truncated/error with read at %d bytes\n", bytesRead);
83 return 1;
84 }
85 bytesRead += amt;
86
87 // filename is not NULL terminated, but it is padded
88 int nameBufSize = round_up(file.nameLen);
89 char* filename = nameBufSize <= (int)sizeof(filenameBuf)
90 ? filenameBuf
91 : (char*)malloc(nameBufSize);
92 amt = read(fd, filename, nameBufSize);
93 if (amt == nameBufSize) {
94 snapshot->add(String8(filename, file.nameLen), file);
95 }
96 bytesRead += amt;
97 if (filename != filenameBuf) {
98 free(filename);
99 }
100 if (amt != nameBufSize) {
101 LOGW("read_snapshot_file filename truncated/error with read at %d bytes\n", bytesRead);
102 return 1;
103 }
104 }
105
106 if (header.totalSize != bytesRead) {
107 LOGW("read_snapshot_file length mismatch: header.totalSize=%d bytesRead=%d\n",
108 header.totalSize, bytesRead);
109 return 1;
110 }
111
112 return 0;
113}
114
115static int
Joe Onorato23ecae32009-06-10 17:07:15 -0700116write_snapshot_file(int fd, const KeyedVector<String8,FileRec>& snapshot)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700117{
Joe Onoratoce88cb12009-06-11 11:27:16 -0700118 int fileCount = 0;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700119 int bytesWritten = sizeof(SnapshotHeader);
120 // preflight size
121 const int N = snapshot.size();
122 for (int i=0; i<N; i++) {
Joe Onoratoce88cb12009-06-11 11:27:16 -0700123 const FileRec& g = snapshot.valueAt(i);
124 if (!g.deleted) {
125 const String8& name = snapshot.keyAt(i);
126 bytesWritten += sizeof(FileState) + round_up(name.length());
127 fileCount++;
128 }
Joe Onorato3ad977b2009-05-05 11:50:51 -0700129 }
130
Joe Onorato4535e402009-05-15 09:07:06 -0400131 LOGP("write_snapshot_file fd=%d\n", fd);
132
Joe Onorato3ad977b2009-05-05 11:50:51 -0700133 int amt;
Joe Onoratoce88cb12009-06-11 11:27:16 -0700134 SnapshotHeader header = { MAGIC0, fileCount, MAGIC1, bytesWritten };
Joe Onorato3ad977b2009-05-05 11:50:51 -0700135
136 amt = write(fd, &header, sizeof(header));
137 if (amt != sizeof(header)) {
138 LOGW("write_snapshot_file error writing header %s", strerror(errno));
139 return errno;
140 }
141
Joe Onoratoce88cb12009-06-11 11:27:16 -0700142 for (int i=0; i<N; i++) {
Joe Onorato23ecae32009-06-10 17:07:15 -0700143 FileRec r = snapshot.valueAt(i);
Joe Onoratoce88cb12009-06-11 11:27:16 -0700144 if (!r.deleted) {
145 const String8& name = snapshot.keyAt(i);
146 int nameLen = r.s.nameLen = name.length();
Joe Onorato3ad977b2009-05-05 11:50:51 -0700147
Joe Onoratoce88cb12009-06-11 11:27:16 -0700148 amt = write(fd, &r.s, sizeof(FileState));
149 if (amt != sizeof(FileState)) {
150 LOGW("write_snapshot_file error writing header %s", strerror(errno));
Joe Onorato3ad977b2009-05-05 11:50:51 -0700151 return 1;
152 }
Joe Onoratoce88cb12009-06-11 11:27:16 -0700153
154 // filename is not NULL terminated, but it is padded
155 amt = write(fd, name.string(), nameLen);
156 if (amt != nameLen) {
157 LOGW("write_snapshot_file error writing filename %s", strerror(errno));
158 return 1;
159 }
160 int paddingLen = ROUND_UP[nameLen % 4];
161 if (paddingLen != 0) {
162 int padding = 0xabababab;
163 amt = write(fd, &padding, paddingLen);
164 if (amt != paddingLen) {
165 LOGW("write_snapshot_file error writing %d bytes of filename padding %s",
166 paddingLen, strerror(errno));
167 return 1;
168 }
169 }
Joe Onorato3ad977b2009-05-05 11:50:51 -0700170 }
171 }
172
173 return 0;
174}
175
176static int
Joe Onoratod2110db2009-05-19 13:41:21 -0700177write_delete_file(BackupDataWriter* dataStream, const String8& key)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700178{
Joe Onorato290bb012009-05-13 18:57:29 -0400179 LOGP("write_delete_file %s\n", key.string());
Joe Onoratod2110db2009-05-19 13:41:21 -0700180 return dataStream->WriteEntityHeader(key, -1);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700181}
182
183static int
Joe Onoratod2110db2009-05-19 13:41:21 -0700184write_update_file(BackupDataWriter* dataStream, int fd, const String8& key,
Joe Onorato23ecae32009-06-10 17:07:15 -0700185 char const* realFilename)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700186{
Joe Onorato23ecae32009-06-10 17:07:15 -0700187 LOGP("write_update_file %s (%s)\n", realFilename, key.string());
Joe Onoratod2110db2009-05-19 13:41:21 -0700188
189 const int bufsize = 4*1024;
190 int err;
191 int amt;
192 int fileSize;
193 int bytesLeft;
194
195 char* buf = (char*)malloc(bufsize);
196 int crc = crc32(0L, Z_NULL, 0);
197
198
199 bytesLeft = fileSize = lseek(fd, 0, SEEK_END);
200 lseek(fd, 0, SEEK_SET);
201
202 err = dataStream->WriteEntityHeader(key, bytesLeft);
203 if (err != 0) {
204 return err;
205 }
206
207 while ((amt = read(fd, buf, bufsize)) != 0 && bytesLeft > 0) {
208 bytesLeft -= amt;
209 if (bytesLeft < 0) {
210 amt += bytesLeft; // Plus a negative is minus. Don't write more than we promised.
211 }
212 err = dataStream->WriteEntityData(buf, amt);
213 if (err != 0) {
214 return err;
215 }
216 }
217 if (bytesLeft != 0) {
218 if (bytesLeft > 0) {
219 // Pad out the space we promised in the buffer. We can't corrupt the buffer,
220 // even though the data we're sending is probably bad.
221 memset(buf, 0, bufsize);
222 while (bytesLeft > 0) {
223 amt = bytesLeft < bufsize ? bytesLeft : bufsize;
224 bytesLeft -= amt;
225 err = dataStream->WriteEntityData(buf, amt);
226 if (err != 0) {
227 return err;
228 }
229 }
230 }
231 LOGE("write_update_file size mismatch for %s. expected=%d actual=%d."
Joe Onorato23ecae32009-06-10 17:07:15 -0700232 " You aren't doing proper locking!", realFilename, fileSize, fileSize-bytesLeft);
Joe Onoratod2110db2009-05-19 13:41:21 -0700233 }
234
235 free(buf);
236
237 return NO_ERROR;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700238}
239
240static int
Joe Onorato23ecae32009-06-10 17:07:15 -0700241write_update_file(BackupDataWriter* dataStream, const String8& key, char const* realFilename)
Joe Onoratod2110db2009-05-19 13:41:21 -0700242{
243 int err;
Joe Onorato23ecae32009-06-10 17:07:15 -0700244 int fd = open(realFilename, O_RDONLY);
Joe Onoratod2110db2009-05-19 13:41:21 -0700245 if (fd == -1) {
246 return errno;
247 }
248 err = write_update_file(dataStream, fd, key, realFilename);
249 close(fd);
250 return err;
251}
252
253static int
254compute_crc32(int fd)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700255{
256 const int bufsize = 4*1024;
257 int amt;
258
Joe Onorato3ad977b2009-05-05 11:50:51 -0700259 char* buf = (char*)malloc(bufsize);
260 int crc = crc32(0L, Z_NULL, 0);
261
Joe Onoratod2110db2009-05-19 13:41:21 -0700262 lseek(fd, 0, SEEK_SET);
263
Joe Onorato3ad977b2009-05-05 11:50:51 -0700264 while ((amt = read(fd, buf, bufsize)) != 0) {
265 crc = crc32(crc, (Bytef*)buf, amt);
266 }
267
Joe Onorato3ad977b2009-05-05 11:50:51 -0700268 free(buf);
269
270 return crc;
271}
272
273int
Joe Onoratod2110db2009-05-19 13:41:21 -0700274back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD,
Joe Onorato23ecae32009-06-10 17:07:15 -0700275 char const* const* files, char const* const* keys, int fileCount)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700276{
277 int err;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700278 KeyedVector<String8,FileState> oldSnapshot;
Joe Onorato23ecae32009-06-10 17:07:15 -0700279 KeyedVector<String8,FileRec> newSnapshot;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700280
281 if (oldSnapshotFD != -1) {
282 err = read_snapshot_file(oldSnapshotFD, &oldSnapshot);
283 if (err != 0) {
284 // On an error, treat this as a full backup.
285 oldSnapshot.clear();
286 }
287 }
288
289 for (int i=0; i<fileCount; i++) {
Joe Onorato23ecae32009-06-10 17:07:15 -0700290 String8 key(keys[i]);
291 FileRec r;
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700292 char const* file = files[i];
293 r.file = file;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700294 struct stat st;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700295
Joe Onorato23ecae32009-06-10 17:07:15 -0700296 err = stat(file, &st);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700297 if (err != 0) {
Joe Onorato23ecae32009-06-10 17:07:15 -0700298 LOGW("Error stating file %s", file);
Joe Onoratoce88cb12009-06-11 11:27:16 -0700299 r.deleted = true;
300 } else {
301 r.deleted = false;
302 r.s.modTime_sec = st.st_mtime;
303 r.s.modTime_nsec = 0; // workaround sim breakage
304 //r.s.modTime_nsec = st.st_mtime_nsec;
305 r.s.size = st.st_size;
306 // we compute the crc32 later down below, when we already have the file open.
Joe Onorato3ad977b2009-05-05 11:50:51 -0700307
Joe Onoratoce88cb12009-06-11 11:27:16 -0700308 if (newSnapshot.indexOfKey(key) >= 0) {
309 LOGP("back_up_files key already in use '%s'", key.string());
310 return -1;
311 }
Joe Onorato23ecae32009-06-10 17:07:15 -0700312 }
313 newSnapshot.add(key, r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700314 }
315
316 int n = 0;
317 int N = oldSnapshot.size();
318 int m = 0;
319
320 while (n<N && m<fileCount) {
321 const String8& p = oldSnapshot.keyAt(n);
322 const String8& q = newSnapshot.keyAt(m);
Joe Onoratoce88cb12009-06-11 11:27:16 -0700323 FileRec& g = newSnapshot.editValueAt(m);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700324 int cmp = p.compare(q);
Joe Onoratoce88cb12009-06-11 11:27:16 -0700325 if (g.deleted || cmp < 0) {
326 // file removed
327 LOGP("file removed: %s", p.string());
328 g.deleted = true; // They didn't mention the file, but we noticed that it's gone.
329 dataStream->WriteEntityHeader(p, -1);
330 n++;
331 }
332 else if (cmp > 0) {
Joe Onorato3ad977b2009-05-05 11:50:51 -0700333 // file added
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700334 LOGP("file added: %s", g.file.string());
335 write_update_file(dataStream, q, g.file.string());
Joe Onorato3ad977b2009-05-05 11:50:51 -0700336 m++;
337 }
Joe Onorato3ad977b2009-05-05 11:50:51 -0700338 else {
339 // both files exist, check them
Joe Onorato3ad977b2009-05-05 11:50:51 -0700340 const FileState& f = oldSnapshot.valueAt(n);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700341
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700342 int fd = open(g.file.string(), O_RDONLY);
Christopher Tate0032ce82009-06-04 17:01:06 -0700343 if (fd < 0) {
Joe Onoratod2110db2009-05-19 13:41:21 -0700344 // We can't open the file. Don't report it as a delete either. Let the
345 // server keep the old version. Maybe they'll be able to deal with it
346 // on restore.
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700347 LOGP("Unable to open file %s - skipping", g.file.string());
Joe Onoratod2110db2009-05-19 13:41:21 -0700348 } else {
Joe Onorato23ecae32009-06-10 17:07:15 -0700349 g.s.crc32 = compute_crc32(fd);
Joe Onoratod2110db2009-05-19 13:41:21 -0700350
Joe Onorato23ecae32009-06-10 17:07:15 -0700351 LOGP("%s", q.string());
352 LOGP(" new: modTime=%d,%d size=%-3d crc32=0x%08x",
Joe Onoratod2110db2009-05-19 13:41:21 -0700353 f.modTime_sec, f.modTime_nsec, f.size, f.crc32);
Joe Onorato23ecae32009-06-10 17:07:15 -0700354 LOGP(" old: modTime=%d,%d size=%-3d crc32=0x%08x",
355 g.s.modTime_sec, g.s.modTime_nsec, g.s.size, g.s.crc32);
356 if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec
357 || f.size != g.s.size || f.crc32 != g.s.crc32) {
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700358 write_update_file(dataStream, fd, p, g.file.string());
Joe Onoratod2110db2009-05-19 13:41:21 -0700359 }
360
361 close(fd);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700362 }
363 n++;
364 m++;
365 }
366 }
367
368 // these were deleted
369 while (n<N) {
Joe Onoratod2110db2009-05-19 13:41:21 -0700370 dataStream->WriteEntityHeader(oldSnapshot.keyAt(n), -1);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700371 n++;
372 }
373
374 // these were added
375 while (m<fileCount) {
376 const String8& q = newSnapshot.keyAt(m);
Joe Onorato23ecae32009-06-10 17:07:15 -0700377 FileRec& g = newSnapshot.editValueAt(m);
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700378 write_update_file(dataStream, q, g.file.string());
Joe Onorato3ad977b2009-05-05 11:50:51 -0700379 m++;
380 }
381
382 err = write_snapshot_file(newSnapshotFD, newSnapshot);
383
384 return 0;
385}
386
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700387#define RESTORE_BUF_SIZE (8*1024)
388
389RestoreHelperBase::RestoreHelperBase()
390{
391 m_buf = malloc(RESTORE_BUF_SIZE);
392}
393
394RestoreHelperBase::~RestoreHelperBase()
395{
396 free(m_buf);
397}
398
399status_t
400RestoreHelperBase::WriteFile(const String8& filename, BackupDataReader* in)
401{
402 ssize_t err;
403 size_t dataSize;
404 String8 key;
405 int fd;
406 void* buf = m_buf;
407 ssize_t amt;
408 int mode;
409 int crc;
410 struct stat st;
411 FileRec r;
412
413 err = in->ReadEntityHeader(&key, &dataSize);
414 if (err != NO_ERROR) {
415 return err;
416 }
417
418 // TODO: World readable/writable for now.
419 mode = 0666;
420
421 // Write the file and compute the crc
422 crc = crc32(0L, Z_NULL, 0);
423 fd = open(filename.string(), O_CREAT|O_RDWR, mode);
424 if (fd != -1) {
425 return errno;
426 }
427
428 while ((amt = in->ReadEntityData(buf, RESTORE_BUF_SIZE)) > 0) {
429 err = write(fd, buf, amt);
430 if (err != amt) {
431 close(fd);
432 return errno;
433 }
434 crc = crc32(crc, (Bytef*)buf, amt);
435 }
436
437 close(fd);
438
439 // Record for the snapshot
440 err = stat(filename.string(), &st);
441 if (err != 0) {
442 LOGW("Error stating file that we just created %s", filename.string());
443 return errno;
444 }
445
446 r.file = filename;
447 r.deleted = false;
448 r.s.modTime_sec = st.st_mtime;
449 r.s.modTime_nsec = 0; // workaround sim breakage
450 //r.s.modTime_nsec = st.st_mtime_nsec;
451 r.s.size = st.st_size;
452 r.s.crc32 = crc;
453
454 m_files.add(key, r);
455
456 return NO_ERROR;
457}
458
459status_t
460RestoreHelperBase::WriteSnapshot(int fd)
461{
462 return write_snapshot_file(fd, m_files);;
463}
464
Joe Onorato3ad977b2009-05-05 11:50:51 -0700465#if TEST_BACKUP_HELPERS
466
467#define SCRATCH_DIR "/data/backup_helper_test/"
468
469static int
470write_text_file(const char* path, const char* data)
471{
472 int amt;
473 int fd;
474 int len;
475
476 fd = creat(path, 0666);
477 if (fd == -1) {
478 fprintf(stderr, "creat %s failed\n", path);
479 return errno;
480 }
481
482 len = strlen(data);
483 amt = write(fd, data, len);
484 if (amt != len) {
485 fprintf(stderr, "error (%s) writing to file %s\n", strerror(errno), path);
486 return errno;
487 }
488
489 close(fd);
490
491 return 0;
492}
493
494static int
495compare_file(const char* path, const unsigned char* data, int len)
496{
497 int fd;
498 int amt;
499
500 fd = open(path, O_RDONLY);
501 if (fd == -1) {
502 fprintf(stderr, "compare_file error (%s) opening %s\n", strerror(errno), path);
503 return errno;
504 }
505
506 unsigned char* contents = (unsigned char*)malloc(len);
507 if (contents == NULL) {
508 fprintf(stderr, "malloc(%d) failed\n", len);
509 return ENOMEM;
510 }
511
512 bool sizesMatch = true;
513 amt = lseek(fd, 0, SEEK_END);
514 if (amt != len) {
515 fprintf(stderr, "compare_file file length should be %d, was %d\n", len, amt);
516 sizesMatch = false;
517 }
518 lseek(fd, 0, SEEK_SET);
519
520 int readLen = amt < len ? amt : len;
521 amt = read(fd, contents, readLen);
522 if (amt != readLen) {
523 fprintf(stderr, "compare_file read expected %d bytes but got %d\n", len, amt);
524 }
525
526 bool contentsMatch = true;
527 for (int i=0; i<readLen; i++) {
528 if (data[i] != contents[i]) {
529 if (contentsMatch) {
530 fprintf(stderr, "compare_file contents are different: (index, expected, actual)\n");
531 contentsMatch = false;
532 }
533 fprintf(stderr, " [%-2d] %02x %02x\n", i, data[i], contents[i]);
534 }
535 }
536
537 return contentsMatch && sizesMatch ? 0 : 1;
538}
539
540int
541backup_helper_test_empty()
542{
543 int err;
544 int fd;
Joe Onorato23ecae32009-06-10 17:07:15 -0700545 KeyedVector<String8,FileRec> snapshot;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700546 const char* filename = SCRATCH_DIR "backup_helper_test_empty.snap";
547
548 system("rm -r " SCRATCH_DIR);
549 mkdir(SCRATCH_DIR, 0777);
550
551 // write
552 fd = creat(filename, 0666);
553 if (fd == -1) {
554 fprintf(stderr, "error creating %s\n", filename);
555 return 1;
556 }
557
558 err = write_snapshot_file(fd, snapshot);
559
560 close(fd);
561
562 if (err != 0) {
563 fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err));
564 return err;
565 }
566
567 static const unsigned char correct_data[] = {
568 0x53, 0x6e, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00,
569 0x46, 0x69, 0x6c, 0x65, 0x10, 0x00, 0x00, 0x00
570 };
571
572 err = compare_file(filename, correct_data, sizeof(correct_data));
573 if (err != 0) {
574 return err;
575 }
576
577 // read
578 fd = open(filename, O_RDONLY);
579 if (fd == -1) {
580 fprintf(stderr, "error opening for read %s\n", filename);
581 return 1;
582 }
583
584 KeyedVector<String8,FileState> readSnapshot;
585 err = read_snapshot_file(fd, &readSnapshot);
586 if (err != 0) {
587 fprintf(stderr, "read_snapshot_file failed %d\n", err);
588 return err;
589 }
590
591 if (readSnapshot.size() != 0) {
592 fprintf(stderr, "readSnapshot should be length 0\n");
593 return 1;
594 }
595
596 return 0;
597}
598
599int
600backup_helper_test_four()
601{
602 int err;
603 int fd;
Joe Onorato23ecae32009-06-10 17:07:15 -0700604 KeyedVector<String8,FileRec> snapshot;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700605 const char* filename = SCRATCH_DIR "backup_helper_test_four.snap";
606
607 system("rm -r " SCRATCH_DIR);
608 mkdir(SCRATCH_DIR, 0777);
609
610 // write
611 fd = creat(filename, 0666);
612 if (fd == -1) {
613 fprintf(stderr, "error opening %s\n", filename);
614 return 1;
615 }
616
617 String8 filenames[4];
618 FileState states[4];
Joe Onorato23ecae32009-06-10 17:07:15 -0700619 FileRec r;
Joe Onoratoce88cb12009-06-11 11:27:16 -0700620 r.deleted = false;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700621
622 states[0].modTime_sec = 0xfedcba98;
623 states[0].modTime_nsec = 0xdeadbeef;
624 states[0].size = 0xababbcbc;
625 states[0].crc32 = 0x12345678;
626 states[0].nameLen = -12;
Joe Onorato23ecae32009-06-10 17:07:15 -0700627 r.s = states[0];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700628 filenames[0] = String8("bytes_of_padding");
Joe Onorato23ecae32009-06-10 17:07:15 -0700629 snapshot.add(filenames[0], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700630
631 states[1].modTime_sec = 0x93400031;
632 states[1].modTime_nsec = 0xdeadbeef;
633 states[1].size = 0x88557766;
634 states[1].crc32 = 0x22334422;
635 states[1].nameLen = -1;
Joe Onorato23ecae32009-06-10 17:07:15 -0700636 r.s = states[1];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700637 filenames[1] = String8("bytes_of_padding3");
Joe Onorato23ecae32009-06-10 17:07:15 -0700638 snapshot.add(filenames[1], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700639
640 states[2].modTime_sec = 0x33221144;
641 states[2].modTime_nsec = 0xdeadbeef;
642 states[2].size = 0x11223344;
643 states[2].crc32 = 0x01122334;
644 states[2].nameLen = 0;
Joe Onorato23ecae32009-06-10 17:07:15 -0700645 r.s = states[2];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700646 filenames[2] = String8("bytes_of_padding_2");
Joe Onorato23ecae32009-06-10 17:07:15 -0700647 snapshot.add(filenames[2], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700648
649 states[3].modTime_sec = 0x33221144;
650 states[3].modTime_nsec = 0xdeadbeef;
651 states[3].size = 0x11223344;
652 states[3].crc32 = 0x01122334;
653 states[3].nameLen = 0;
Joe Onorato23ecae32009-06-10 17:07:15 -0700654 r.s = states[3];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700655 filenames[3] = String8("bytes_of_padding__1");
Joe Onorato23ecae32009-06-10 17:07:15 -0700656 snapshot.add(filenames[3], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700657
658 err = write_snapshot_file(fd, snapshot);
659
660 close(fd);
661
662 if (err != 0) {
663 fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err));
664 return err;
665 }
666
667 static const unsigned char correct_data[] = {
668 // header
669 0x53, 0x6e, 0x61, 0x70, 0x04, 0x00, 0x00, 0x00,
670 0x46, 0x69, 0x6c, 0x65, 0xac, 0x00, 0x00, 0x00,
671
672 // bytes_of_padding
673 0x98, 0xba, 0xdc, 0xfe, 0xef, 0xbe, 0xad, 0xde,
674 0xbc, 0xbc, 0xab, 0xab, 0x78, 0x56, 0x34, 0x12,
675 0x10, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
676 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
677 0x64, 0x69, 0x6e, 0x67,
678
679 // bytes_of_padding3
680 0x31, 0x00, 0x40, 0x93, 0xef, 0xbe, 0xad, 0xde,
681 0x66, 0x77, 0x55, 0x88, 0x22, 0x44, 0x33, 0x22,
682 0x11, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
683 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
684 0x64, 0x69, 0x6e, 0x67, 0x33, 0xab, 0xab, 0xab,
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700685
Joe Onorato3ad977b2009-05-05 11:50:51 -0700686 // bytes of padding2
687 0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde,
688 0x44, 0x33, 0x22, 0x11, 0x34, 0x23, 0x12, 0x01,
689 0x12, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
690 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
691 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x32, 0xab, 0xab,
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700692
Joe Onorato3ad977b2009-05-05 11:50:51 -0700693 // bytes of padding3
694 0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde,
695 0x44, 0x33, 0x22, 0x11, 0x34, 0x23, 0x12, 0x01,
696 0x13, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
697 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
698 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x5f, 0x31, 0xab
699 };
700
701 err = compare_file(filename, correct_data, sizeof(correct_data));
702 if (err != 0) {
703 return err;
704 }
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700705
Joe Onorato3ad977b2009-05-05 11:50:51 -0700706 // read
707 fd = open(filename, O_RDONLY);
708 if (fd == -1) {
709 fprintf(stderr, "error opening for read %s\n", filename);
710 return 1;
711 }
712
713
714 KeyedVector<String8,FileState> readSnapshot;
715 err = read_snapshot_file(fd, &readSnapshot);
716 if (err != 0) {
717 fprintf(stderr, "read_snapshot_file failed %d\n", err);
718 return err;
719 }
720
721 if (readSnapshot.size() != 4) {
722 fprintf(stderr, "readSnapshot should be length 4 is %d\n", readSnapshot.size());
723 return 1;
724 }
725
726 bool matched = true;
727 for (size_t i=0; i<readSnapshot.size(); i++) {
728 const String8& name = readSnapshot.keyAt(i);
729 const FileState state = readSnapshot.valueAt(i);
730
731 if (name != filenames[i] || states[i].modTime_sec != state.modTime_sec
732 || states[i].modTime_nsec != state.modTime_nsec
733 || states[i].size != state.size || states[i].crc32 != states[i].crc32) {
734 fprintf(stderr, "state %d expected={%d/%d, 0x%08x, 0x%08x, %3d} '%s'\n"
735 " actual={%d/%d, 0x%08x, 0x%08x, %3d} '%s'\n", i,
736 states[i].modTime_sec, states[i].modTime_nsec, states[i].size, states[i].crc32,
737 name.length(), filenames[i].string(),
738 state.modTime_sec, state.modTime_nsec, state.size, state.crc32, state.nameLen,
739 name.string());
740 matched = false;
741 }
742 }
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700743
Joe Onorato3ad977b2009-05-05 11:50:51 -0700744 return matched ? 0 : 1;
745}
746
Joe Onorato4535e402009-05-15 09:07:06 -0400747// hexdump -v -e '" " 8/1 " 0x%02x," "\n"' data_writer.data
748const unsigned char DATA_GOLDEN_FILE[] = {
Joe Onorato2e1da322009-05-15 18:20:19 -0400749 0x44, 0x61, 0x74, 0x61, 0x0b, 0x00, 0x00, 0x00,
750 0x0c, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x5f, 0x70,
751 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00,
752 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69,
Joe Onorato5f15d152009-06-16 16:31:35 -0400753 0x6e, 0x67, 0x5f, 0x00, 0x44, 0x61, 0x74, 0x61,
754 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
Joe Onorato4535e402009-05-15 09:07:06 -0400755 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
756 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
Joe Onorato2e1da322009-05-15 18:20:19 -0400757 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
Joe Onorato5f15d152009-06-16 16:31:35 -0400758 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
Joe Onorato2e1da322009-05-15 18:20:19 -0400759 0x44, 0x61, 0x74, 0x61, 0x0d, 0x00, 0x00, 0x00,
760 0x0e, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
Joe Onorato4535e402009-05-15 09:07:06 -0400761 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
Joe Onorato2e1da322009-05-15 18:20:19 -0400762 0x5f, 0x00, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64,
763 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
Joe Onorato5f15d152009-06-16 16:31:35 -0400764 0x5f, 0x00, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61,
Joe Onorato4535e402009-05-15 09:07:06 -0400765 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
766 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
767 0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64,
Joe Onorato5f15d152009-06-16 16:31:35 -0400768 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00
769
Joe Onorato4535e402009-05-15 09:07:06 -0400770};
771const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE);
772
773static int
774test_write_header_and_entity(BackupDataWriter& writer, const char* str)
775{
776 int err;
777 String8 text(str);
778
Joe Onorato4535e402009-05-15 09:07:06 -0400779 err = writer.WriteEntityHeader(text, text.length()+1);
780 if (err != 0) {
781 fprintf(stderr, "WriteEntityHeader failed with %s\n", strerror(err));
782 return err;
783 }
784
785 err = writer.WriteEntityData(text.string(), text.length()+1);
786 if (err != 0) {
787 fprintf(stderr, "write failed for data '%s'\n", text.string());
788 return errno;
789 }
790
791 return err;
792}
793
794int
795backup_helper_test_data_writer()
796{
797 int err;
798 int fd;
799 const char* filename = SCRATCH_DIR "data_writer.data";
800
801 system("rm -r " SCRATCH_DIR);
802 mkdir(SCRATCH_DIR, 0777);
803 mkdir(SCRATCH_DIR "data", 0777);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700804
Joe Onorato4535e402009-05-15 09:07:06 -0400805 fd = creat(filename, 0666);
806 if (fd == -1) {
807 fprintf(stderr, "error creating: %s\n", strerror(errno));
808 return errno;
809 }
810
811 BackupDataWriter writer(fd);
812
813 err = 0;
814 err |= test_write_header_and_entity(writer, "no_padding_");
815 err |= test_write_header_and_entity(writer, "padded_to__3");
816 err |= test_write_header_and_entity(writer, "padded_to_2__");
817 err |= test_write_header_and_entity(writer, "padded_to1");
818
Joe Onorato4535e402009-05-15 09:07:06 -0400819 close(fd);
820
821 err = compare_file(filename, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
822 if (err != 0) {
823 return err;
824 }
825
826 return err;
827}
828
Joe Onorato2e1da322009-05-15 18:20:19 -0400829int
830test_read_header_and_entity(BackupDataReader& reader, const char* str)
831{
832 int err;
833 int bufSize = strlen(str)+1;
834 char* buf = (char*)malloc(bufSize);
835 String8 string;
836 int cookie = 0x11111111;
837 size_t actualSize;
Joe Onorato5f15d152009-06-16 16:31:35 -0400838 bool done;
839 int type;
Joe Onorato2e1da322009-05-15 18:20:19 -0400840
841 // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str);
842
Joe Onorato5f15d152009-06-16 16:31:35 -0400843 err = reader.ReadNextHeader(&done, &type);
844 if (done) {
845 fprintf(stderr, "should not be done yet\n");
846 goto finished;
847 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400848 if (err != 0) {
849 fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400850 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400851 }
Joe Onorato5f15d152009-06-16 16:31:35 -0400852 if (type != BACKUP_HEADER_ENTITY_V1) {
Joe Onorato2e1da322009-05-15 18:20:19 -0400853 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400854 fprintf(stderr, "type=0x%08x expected 0x%08x\n", type, BACKUP_HEADER_ENTITY_V1);
Joe Onorato2e1da322009-05-15 18:20:19 -0400855 }
856
857 err = reader.ReadEntityHeader(&string, &actualSize);
858 if (err != 0) {
859 fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400860 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400861 }
862 if (string != str) {
863 fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.string());
864 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400865 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400866 }
867 if ((int)actualSize != bufSize) {
868 fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize,
869 actualSize);
870 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400871 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400872 }
873
874 err = reader.ReadEntityData(buf, bufSize);
875 if (err != NO_ERROR) {
876 fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400877 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400878 }
879
880 if (0 != memcmp(buf, str, bufSize)) {
881 fprintf(stderr, "ReadEntityData expected '%s' but got something starting with "
Joe Onorato5f15d152009-06-16 16:31:35 -0400882 "%02x %02x %02x %02x '%c%c%c%c'\n", str, buf[0], buf[1], buf[2], buf[3],
883 buf[0], buf[1], buf[2], buf[3]);
Joe Onorato2e1da322009-05-15 18:20:19 -0400884 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400885 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400886 }
887
888 // The next read will confirm whether it got the right amount of data.
889
Joe Onorato5f15d152009-06-16 16:31:35 -0400890finished:
Joe Onorato2e1da322009-05-15 18:20:19 -0400891 if (err != NO_ERROR) {
892 fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err));
893 }
894 free(buf);
895 return err;
896}
897
898int
899backup_helper_test_data_reader()
900{
901 int err;
902 int fd;
903 const char* filename = SCRATCH_DIR "data_reader.data";
904
905 system("rm -r " SCRATCH_DIR);
906 mkdir(SCRATCH_DIR, 0777);
907 mkdir(SCRATCH_DIR "data", 0777);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700908
Joe Onorato2e1da322009-05-15 18:20:19 -0400909 fd = creat(filename, 0666);
910 if (fd == -1) {
911 fprintf(stderr, "error creating: %s\n", strerror(errno));
912 return errno;
913 }
914
915 err = write(fd, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
916 if (err != DATA_GOLDEN_FILE_SIZE) {
917 fprintf(stderr, "Error \"%s\" writing golden file %s\n", strerror(errno), filename);
918 return errno;
919 }
920
921 close(fd);
922
923 fd = open(filename, O_RDONLY);
924 if (fd == -1) {
925 fprintf(stderr, "Error \"%s\" opening golden file %s for read\n", strerror(errno),
926 filename);
927 return errno;
928 }
929
930 {
931 BackupDataReader reader(fd);
932
933 err = 0;
934
935 if (err == NO_ERROR) {
936 err = test_read_header_and_entity(reader, "no_padding_");
937 }
938
939 if (err == NO_ERROR) {
940 err = test_read_header_and_entity(reader, "padded_to__3");
941 }
942
943 if (err == NO_ERROR) {
944 err = test_read_header_and_entity(reader, "padded_to_2__");
945 }
946
947 if (err == NO_ERROR) {
948 err = test_read_header_and_entity(reader, "padded_to1");
949 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400950 }
951
952 close(fd);
953
954 return err;
955}
956
Joe Onorato3ad977b2009-05-05 11:50:51 -0700957static int
958get_mod_time(const char* filename, struct timeval times[2])
959{
960 int err;
961 struct stat64 st;
962 err = stat64(filename, &st);
963 if (err != 0) {
964 fprintf(stderr, "stat '%s' failed: %s\n", filename, strerror(errno));
965 return errno;
966 }
967 times[0].tv_sec = st.st_atime;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700968 times[1].tv_sec = st.st_mtime;
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700969
970 // If st_atime is a macro then struct stat64 uses struct timespec
971 // to store the access and modif time values and typically
972 // st_*time_nsec is not defined. In glibc, this is controlled by
973 // __USE_MISC.
974#ifdef __USE_MISC
975#if !defined(st_atime) || defined(st_atime_nsec)
976#error "Check if this __USE_MISC conditional is still needed."
977#endif
978 times[0].tv_usec = st.st_atim.tv_nsec / 1000;
979 times[1].tv_usec = st.st_mtim.tv_nsec / 1000;
980#else
981 times[0].tv_usec = st.st_atime_nsec / 1000;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700982 times[1].tv_usec = st.st_mtime_nsec / 1000;
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700983#endif
984
Joe Onorato3ad977b2009-05-05 11:50:51 -0700985 return 0;
986}
987
988int
989backup_helper_test_files()
990{
991 int err;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700992 int oldSnapshotFD;
Joe Onorato4535e402009-05-15 09:07:06 -0400993 int dataStreamFD;
994 int newSnapshotFD;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700995
996 system("rm -r " SCRATCH_DIR);
997 mkdir(SCRATCH_DIR, 0777);
998 mkdir(SCRATCH_DIR "data", 0777);
999
1000 write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
1001 write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
1002 write_text_file(SCRATCH_DIR "data/d", "d\ndd\n");
1003 write_text_file(SCRATCH_DIR "data/e", "e\nee\n");
1004 write_text_file(SCRATCH_DIR "data/f", "f\nff\n");
1005 write_text_file(SCRATCH_DIR "data/h", "h\nhh\n");
1006
1007 char const* files_before[] = {
Joe Onorato23ecae32009-06-10 17:07:15 -07001008 SCRATCH_DIR "data/b",
1009 SCRATCH_DIR "data/c",
1010 SCRATCH_DIR "data/d",
1011 SCRATCH_DIR "data/e",
1012 SCRATCH_DIR "data/f"
1013 };
1014
1015 char const* keys_before[] = {
Joe Onorato3ad977b2009-05-05 11:50:51 -07001016 "data/b",
1017 "data/c",
1018 "data/d",
1019 "data/e",
1020 "data/f"
1021 };
1022
Joe Onorato4535e402009-05-15 09:07:06 -04001023 dataStreamFD = creat(SCRATCH_DIR "1.data", 0666);
1024 if (dataStreamFD == -1) {
1025 fprintf(stderr, "error creating: %s\n", strerror(errno));
1026 return errno;
1027 }
1028
Joe Onorato3ad977b2009-05-05 11:50:51 -07001029 newSnapshotFD = creat(SCRATCH_DIR "before.snap", 0666);
1030 if (newSnapshotFD == -1) {
1031 fprintf(stderr, "error creating: %s\n", strerror(errno));
1032 return errno;
1033 }
Joe Onoratod2110db2009-05-19 13:41:21 -07001034
1035 {
1036 BackupDataWriter dataStream(dataStreamFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001037
Joe Onorato23ecae32009-06-10 17:07:15 -07001038 err = back_up_files(-1, &dataStream, newSnapshotFD, files_before, keys_before, 5);
Joe Onoratod2110db2009-05-19 13:41:21 -07001039 if (err != 0) {
1040 return err;
1041 }
Joe Onorato3ad977b2009-05-05 11:50:51 -07001042 }
1043
Joe Onorato4535e402009-05-15 09:07:06 -04001044 close(dataStreamFD);
Joe Onorato3ad977b2009-05-05 11:50:51 -07001045 close(newSnapshotFD);
1046
1047 sleep(3);
1048
1049 struct timeval d_times[2];
1050 struct timeval e_times[2];
1051
1052 err = get_mod_time(SCRATCH_DIR "data/d", d_times);
1053 err |= get_mod_time(SCRATCH_DIR "data/e", e_times);
1054 if (err != 0) {
1055 return err;
1056 }
1057
1058 write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
1059 unlink(SCRATCH_DIR "data/c");
1060 write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
1061 write_text_file(SCRATCH_DIR "data/d", "dd\ndd\n");
1062 utimes(SCRATCH_DIR "data/d", d_times);
1063 write_text_file(SCRATCH_DIR "data/e", "z\nzz\n");
1064 utimes(SCRATCH_DIR "data/e", e_times);
1065 write_text_file(SCRATCH_DIR "data/g", "g\ngg\n");
1066 unlink(SCRATCH_DIR "data/f");
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001067
Joe Onorato3ad977b2009-05-05 11:50:51 -07001068 char const* files_after[] = {
Joe Onorato23ecae32009-06-10 17:07:15 -07001069 SCRATCH_DIR "data/a", // added
1070 SCRATCH_DIR "data/b", // same
1071 SCRATCH_DIR "data/c", // different mod time
1072 SCRATCH_DIR "data/d", // different size (same mod time)
1073 SCRATCH_DIR "data/e", // different contents (same mod time, same size)
1074 SCRATCH_DIR "data/g" // added
1075 };
1076
1077 char const* keys_after[] = {
Joe Onorato3ad977b2009-05-05 11:50:51 -07001078 "data/a", // added
1079 "data/b", // same
1080 "data/c", // different mod time
1081 "data/d", // different size (same mod time)
1082 "data/e", // different contents (same mod time, same size)
1083 "data/g" // added
1084 };
1085
1086 oldSnapshotFD = open(SCRATCH_DIR "before.snap", O_RDONLY);
1087 if (oldSnapshotFD == -1) {
1088 fprintf(stderr, "error opening: %s\n", strerror(errno));
1089 return errno;
1090 }
1091
Joe Onorato4535e402009-05-15 09:07:06 -04001092 dataStreamFD = creat(SCRATCH_DIR "2.data", 0666);
1093 if (dataStreamFD == -1) {
1094 fprintf(stderr, "error creating: %s\n", strerror(errno));
1095 return errno;
1096 }
1097
Joe Onorato3ad977b2009-05-05 11:50:51 -07001098 newSnapshotFD = creat(SCRATCH_DIR "after.snap", 0666);
1099 if (newSnapshotFD == -1) {
1100 fprintf(stderr, "error creating: %s\n", strerror(errno));
1101 return errno;
1102 }
1103
Joe Onoratod2110db2009-05-19 13:41:21 -07001104 {
1105 BackupDataWriter dataStream(dataStreamFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001106
Joe Onorato23ecae32009-06-10 17:07:15 -07001107 err = back_up_files(oldSnapshotFD, &dataStream, newSnapshotFD, files_after, keys_after, 6);
Joe Onoratod2110db2009-05-19 13:41:21 -07001108 if (err != 0) {
1109 return err;
1110 }
1111}
Joe Onorato3ad977b2009-05-05 11:50:51 -07001112
1113 close(oldSnapshotFD);
Joe Onorato4535e402009-05-15 09:07:06 -04001114 close(dataStreamFD);
Joe Onorato3ad977b2009-05-05 11:50:51 -07001115 close(newSnapshotFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001116
Joe Onorato3ad977b2009-05-05 11:50:51 -07001117 return 0;
1118}
1119
Joe Onorato23ecae32009-06-10 17:07:15 -07001120int
1121backup_helper_test_null_base()
1122{
1123 int err;
1124 int oldSnapshotFD;
1125 int dataStreamFD;
1126 int newSnapshotFD;
1127
1128 system("rm -r " SCRATCH_DIR);
1129 mkdir(SCRATCH_DIR, 0777);
1130 mkdir(SCRATCH_DIR "data", 0777);
1131
1132 write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
1133
1134 char const* files[] = {
1135 SCRATCH_DIR "data/a",
1136 };
1137
1138 char const* keys[] = {
1139 "a",
1140 };
1141
1142 dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
1143 if (dataStreamFD == -1) {
1144 fprintf(stderr, "error creating: %s\n", strerror(errno));
1145 return errno;
1146 }
1147
1148 newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
1149 if (newSnapshotFD == -1) {
1150 fprintf(stderr, "error creating: %s\n", strerror(errno));
1151 return errno;
1152 }
1153
1154 {
1155 BackupDataWriter dataStream(dataStreamFD);
1156
1157 err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
1158 if (err != 0) {
1159 return err;
1160 }
1161 }
1162
1163 close(dataStreamFD);
1164 close(newSnapshotFD);
1165
1166 return 0;
1167}
1168
Joe Onoratoce88cb12009-06-11 11:27:16 -07001169int
1170backup_helper_test_missing_file()
1171{
1172 int err;
1173 int oldSnapshotFD;
1174 int dataStreamFD;
1175 int newSnapshotFD;
1176
1177 system("rm -r " SCRATCH_DIR);
1178 mkdir(SCRATCH_DIR, 0777);
1179 mkdir(SCRATCH_DIR "data", 0777);
1180
1181 write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
1182
1183 char const* files[] = {
1184 SCRATCH_DIR "data/a",
1185 SCRATCH_DIR "data/b",
1186 SCRATCH_DIR "data/c",
1187 };
1188
1189 char const* keys[] = {
1190 "a",
1191 "b",
1192 "c",
1193 };
1194
1195 dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
1196 if (dataStreamFD == -1) {
1197 fprintf(stderr, "error creating: %s\n", strerror(errno));
1198 return errno;
1199 }
1200
1201 newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
1202 if (newSnapshotFD == -1) {
1203 fprintf(stderr, "error creating: %s\n", strerror(errno));
1204 return errno;
1205 }
1206
1207 {
1208 BackupDataWriter dataStream(dataStreamFD);
1209
1210 err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
1211 if (err != 0) {
1212 return err;
1213 }
1214 }
1215
1216 close(dataStreamFD);
1217 close(newSnapshotFD);
1218
1219 return 0;
1220}
1221
Joe Onorato23ecae32009-06-10 17:07:15 -07001222
Joe Onorato3ad977b2009-05-05 11:50:51 -07001223#endif // TEST_BACKUP_HELPERS
Joe Onorato4535e402009-05-15 09:07:06 -04001224
1225}