blob: d65a457f39876277fb91a61cba4e56d80bd6b3f6 [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 }
Joe Onorato5d605dc2009-06-18 18:23:43 -0700417
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700418 // 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);
Joe Onorato5d605dc2009-06-18 18:23:43 -0700423 fd = open(filename.string(), O_CREAT|O_RDWR|O_TRUNC, mode);
424 if (fd == -1) {
425 LOGW("Could not open file %s -- %s", filename.string(), strerror(errno));
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700426 return errno;
427 }
428
429 while ((amt = in->ReadEntityData(buf, RESTORE_BUF_SIZE)) > 0) {
430 err = write(fd, buf, amt);
431 if (err != amt) {
432 close(fd);
Joe Onorato5d605dc2009-06-18 18:23:43 -0700433 LOGW("Error '%s' writing '%s'", strerror(errno), filename.string());
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700434 return errno;
435 }
436 crc = crc32(crc, (Bytef*)buf, amt);
437 }
438
439 close(fd);
440
441 // Record for the snapshot
442 err = stat(filename.string(), &st);
443 if (err != 0) {
444 LOGW("Error stating file that we just created %s", filename.string());
445 return errno;
446 }
447
448 r.file = filename;
449 r.deleted = false;
450 r.s.modTime_sec = st.st_mtime;
451 r.s.modTime_nsec = 0; // workaround sim breakage
452 //r.s.modTime_nsec = st.st_mtime_nsec;
453 r.s.size = st.st_size;
454 r.s.crc32 = crc;
455
456 m_files.add(key, r);
457
458 return NO_ERROR;
459}
460
461status_t
462RestoreHelperBase::WriteSnapshot(int fd)
463{
464 return write_snapshot_file(fd, m_files);;
465}
466
Joe Onorato3ad977b2009-05-05 11:50:51 -0700467#if TEST_BACKUP_HELPERS
468
469#define SCRATCH_DIR "/data/backup_helper_test/"
470
471static int
472write_text_file(const char* path, const char* data)
473{
474 int amt;
475 int fd;
476 int len;
477
478 fd = creat(path, 0666);
479 if (fd == -1) {
480 fprintf(stderr, "creat %s failed\n", path);
481 return errno;
482 }
483
484 len = strlen(data);
485 amt = write(fd, data, len);
486 if (amt != len) {
487 fprintf(stderr, "error (%s) writing to file %s\n", strerror(errno), path);
488 return errno;
489 }
490
491 close(fd);
492
493 return 0;
494}
495
496static int
497compare_file(const char* path, const unsigned char* data, int len)
498{
499 int fd;
500 int amt;
501
502 fd = open(path, O_RDONLY);
503 if (fd == -1) {
504 fprintf(stderr, "compare_file error (%s) opening %s\n", strerror(errno), path);
505 return errno;
506 }
507
508 unsigned char* contents = (unsigned char*)malloc(len);
509 if (contents == NULL) {
510 fprintf(stderr, "malloc(%d) failed\n", len);
511 return ENOMEM;
512 }
513
514 bool sizesMatch = true;
515 amt = lseek(fd, 0, SEEK_END);
516 if (amt != len) {
517 fprintf(stderr, "compare_file file length should be %d, was %d\n", len, amt);
518 sizesMatch = false;
519 }
520 lseek(fd, 0, SEEK_SET);
521
522 int readLen = amt < len ? amt : len;
523 amt = read(fd, contents, readLen);
524 if (amt != readLen) {
525 fprintf(stderr, "compare_file read expected %d bytes but got %d\n", len, amt);
526 }
527
528 bool contentsMatch = true;
529 for (int i=0; i<readLen; i++) {
530 if (data[i] != contents[i]) {
531 if (contentsMatch) {
532 fprintf(stderr, "compare_file contents are different: (index, expected, actual)\n");
533 contentsMatch = false;
534 }
535 fprintf(stderr, " [%-2d] %02x %02x\n", i, data[i], contents[i]);
536 }
537 }
538
539 return contentsMatch && sizesMatch ? 0 : 1;
540}
541
542int
543backup_helper_test_empty()
544{
545 int err;
546 int fd;
Joe Onorato23ecae32009-06-10 17:07:15 -0700547 KeyedVector<String8,FileRec> snapshot;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700548 const char* filename = SCRATCH_DIR "backup_helper_test_empty.snap";
549
550 system("rm -r " SCRATCH_DIR);
551 mkdir(SCRATCH_DIR, 0777);
552
553 // write
554 fd = creat(filename, 0666);
555 if (fd == -1) {
556 fprintf(stderr, "error creating %s\n", filename);
557 return 1;
558 }
559
560 err = write_snapshot_file(fd, snapshot);
561
562 close(fd);
563
564 if (err != 0) {
565 fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err));
566 return err;
567 }
568
569 static const unsigned char correct_data[] = {
570 0x53, 0x6e, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00,
571 0x46, 0x69, 0x6c, 0x65, 0x10, 0x00, 0x00, 0x00
572 };
573
574 err = compare_file(filename, correct_data, sizeof(correct_data));
575 if (err != 0) {
576 return err;
577 }
578
579 // read
580 fd = open(filename, O_RDONLY);
581 if (fd == -1) {
582 fprintf(stderr, "error opening for read %s\n", filename);
583 return 1;
584 }
585
586 KeyedVector<String8,FileState> readSnapshot;
587 err = read_snapshot_file(fd, &readSnapshot);
588 if (err != 0) {
589 fprintf(stderr, "read_snapshot_file failed %d\n", err);
590 return err;
591 }
592
593 if (readSnapshot.size() != 0) {
594 fprintf(stderr, "readSnapshot should be length 0\n");
595 return 1;
596 }
597
598 return 0;
599}
600
601int
602backup_helper_test_four()
603{
604 int err;
605 int fd;
Joe Onorato23ecae32009-06-10 17:07:15 -0700606 KeyedVector<String8,FileRec> snapshot;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700607 const char* filename = SCRATCH_DIR "backup_helper_test_four.snap";
608
609 system("rm -r " SCRATCH_DIR);
610 mkdir(SCRATCH_DIR, 0777);
611
612 // write
613 fd = creat(filename, 0666);
614 if (fd == -1) {
615 fprintf(stderr, "error opening %s\n", filename);
616 return 1;
617 }
618
619 String8 filenames[4];
620 FileState states[4];
Joe Onorato23ecae32009-06-10 17:07:15 -0700621 FileRec r;
Joe Onoratoce88cb12009-06-11 11:27:16 -0700622 r.deleted = false;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700623
624 states[0].modTime_sec = 0xfedcba98;
625 states[0].modTime_nsec = 0xdeadbeef;
626 states[0].size = 0xababbcbc;
627 states[0].crc32 = 0x12345678;
628 states[0].nameLen = -12;
Joe Onorato23ecae32009-06-10 17:07:15 -0700629 r.s = states[0];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700630 filenames[0] = String8("bytes_of_padding");
Joe Onorato23ecae32009-06-10 17:07:15 -0700631 snapshot.add(filenames[0], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700632
633 states[1].modTime_sec = 0x93400031;
634 states[1].modTime_nsec = 0xdeadbeef;
635 states[1].size = 0x88557766;
636 states[1].crc32 = 0x22334422;
637 states[1].nameLen = -1;
Joe Onorato23ecae32009-06-10 17:07:15 -0700638 r.s = states[1];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700639 filenames[1] = String8("bytes_of_padding3");
Joe Onorato23ecae32009-06-10 17:07:15 -0700640 snapshot.add(filenames[1], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700641
642 states[2].modTime_sec = 0x33221144;
643 states[2].modTime_nsec = 0xdeadbeef;
644 states[2].size = 0x11223344;
645 states[2].crc32 = 0x01122334;
646 states[2].nameLen = 0;
Joe Onorato23ecae32009-06-10 17:07:15 -0700647 r.s = states[2];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700648 filenames[2] = String8("bytes_of_padding_2");
Joe Onorato23ecae32009-06-10 17:07:15 -0700649 snapshot.add(filenames[2], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700650
651 states[3].modTime_sec = 0x33221144;
652 states[3].modTime_nsec = 0xdeadbeef;
653 states[3].size = 0x11223344;
654 states[3].crc32 = 0x01122334;
655 states[3].nameLen = 0;
Joe Onorato23ecae32009-06-10 17:07:15 -0700656 r.s = states[3];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700657 filenames[3] = String8("bytes_of_padding__1");
Joe Onorato23ecae32009-06-10 17:07:15 -0700658 snapshot.add(filenames[3], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700659
660 err = write_snapshot_file(fd, snapshot);
661
662 close(fd);
663
664 if (err != 0) {
665 fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err));
666 return err;
667 }
668
669 static const unsigned char correct_data[] = {
670 // header
671 0x53, 0x6e, 0x61, 0x70, 0x04, 0x00, 0x00, 0x00,
672 0x46, 0x69, 0x6c, 0x65, 0xac, 0x00, 0x00, 0x00,
673
674 // bytes_of_padding
675 0x98, 0xba, 0xdc, 0xfe, 0xef, 0xbe, 0xad, 0xde,
676 0xbc, 0xbc, 0xab, 0xab, 0x78, 0x56, 0x34, 0x12,
677 0x10, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
678 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
679 0x64, 0x69, 0x6e, 0x67,
680
681 // bytes_of_padding3
682 0x31, 0x00, 0x40, 0x93, 0xef, 0xbe, 0xad, 0xde,
683 0x66, 0x77, 0x55, 0x88, 0x22, 0x44, 0x33, 0x22,
684 0x11, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
685 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
686 0x64, 0x69, 0x6e, 0x67, 0x33, 0xab, 0xab, 0xab,
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700687
Joe Onorato3ad977b2009-05-05 11:50:51 -0700688 // bytes of padding2
689 0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde,
690 0x44, 0x33, 0x22, 0x11, 0x34, 0x23, 0x12, 0x01,
691 0x12, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
692 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
693 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x32, 0xab, 0xab,
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700694
Joe Onorato3ad977b2009-05-05 11:50:51 -0700695 // bytes of padding3
696 0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde,
697 0x44, 0x33, 0x22, 0x11, 0x34, 0x23, 0x12, 0x01,
698 0x13, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
699 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
700 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x5f, 0x31, 0xab
701 };
702
703 err = compare_file(filename, correct_data, sizeof(correct_data));
704 if (err != 0) {
705 return err;
706 }
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700707
Joe Onorato3ad977b2009-05-05 11:50:51 -0700708 // read
709 fd = open(filename, O_RDONLY);
710 if (fd == -1) {
711 fprintf(stderr, "error opening for read %s\n", filename);
712 return 1;
713 }
714
715
716 KeyedVector<String8,FileState> readSnapshot;
717 err = read_snapshot_file(fd, &readSnapshot);
718 if (err != 0) {
719 fprintf(stderr, "read_snapshot_file failed %d\n", err);
720 return err;
721 }
722
723 if (readSnapshot.size() != 4) {
724 fprintf(stderr, "readSnapshot should be length 4 is %d\n", readSnapshot.size());
725 return 1;
726 }
727
728 bool matched = true;
729 for (size_t i=0; i<readSnapshot.size(); i++) {
730 const String8& name = readSnapshot.keyAt(i);
731 const FileState state = readSnapshot.valueAt(i);
732
733 if (name != filenames[i] || states[i].modTime_sec != state.modTime_sec
734 || states[i].modTime_nsec != state.modTime_nsec
735 || states[i].size != state.size || states[i].crc32 != states[i].crc32) {
736 fprintf(stderr, "state %d expected={%d/%d, 0x%08x, 0x%08x, %3d} '%s'\n"
737 " actual={%d/%d, 0x%08x, 0x%08x, %3d} '%s'\n", i,
738 states[i].modTime_sec, states[i].modTime_nsec, states[i].size, states[i].crc32,
739 name.length(), filenames[i].string(),
740 state.modTime_sec, state.modTime_nsec, state.size, state.crc32, state.nameLen,
741 name.string());
742 matched = false;
743 }
744 }
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700745
Joe Onorato3ad977b2009-05-05 11:50:51 -0700746 return matched ? 0 : 1;
747}
748
Joe Onorato4535e402009-05-15 09:07:06 -0400749// hexdump -v -e '" " 8/1 " 0x%02x," "\n"' data_writer.data
750const unsigned char DATA_GOLDEN_FILE[] = {
Joe Onorato2e1da322009-05-15 18:20:19 -0400751 0x44, 0x61, 0x74, 0x61, 0x0b, 0x00, 0x00, 0x00,
752 0x0c, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x5f, 0x70,
753 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00,
754 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69,
Joe Onorato5f15d152009-06-16 16:31:35 -0400755 0x6e, 0x67, 0x5f, 0x00, 0x44, 0x61, 0x74, 0x61,
756 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
Joe Onorato4535e402009-05-15 09:07:06 -0400757 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
758 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
Joe Onorato2e1da322009-05-15 18:20:19 -0400759 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
Joe Onorato5f15d152009-06-16 16:31:35 -0400760 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
Joe Onorato2e1da322009-05-15 18:20:19 -0400761 0x44, 0x61, 0x74, 0x61, 0x0d, 0x00, 0x00, 0x00,
762 0x0e, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
Joe Onorato4535e402009-05-15 09:07:06 -0400763 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
Joe Onorato2e1da322009-05-15 18:20:19 -0400764 0x5f, 0x00, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64,
765 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
Joe Onorato5f15d152009-06-16 16:31:35 -0400766 0x5f, 0x00, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61,
Joe Onorato4535e402009-05-15 09:07:06 -0400767 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
768 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
769 0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64,
Joe Onorato5f15d152009-06-16 16:31:35 -0400770 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00
771
Joe Onorato4535e402009-05-15 09:07:06 -0400772};
773const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE);
774
775static int
776test_write_header_and_entity(BackupDataWriter& writer, const char* str)
777{
778 int err;
779 String8 text(str);
780
Joe Onorato4535e402009-05-15 09:07:06 -0400781 err = writer.WriteEntityHeader(text, text.length()+1);
782 if (err != 0) {
783 fprintf(stderr, "WriteEntityHeader failed with %s\n", strerror(err));
784 return err;
785 }
786
787 err = writer.WriteEntityData(text.string(), text.length()+1);
788 if (err != 0) {
789 fprintf(stderr, "write failed for data '%s'\n", text.string());
790 return errno;
791 }
792
793 return err;
794}
795
796int
797backup_helper_test_data_writer()
798{
799 int err;
800 int fd;
801 const char* filename = SCRATCH_DIR "data_writer.data";
802
803 system("rm -r " SCRATCH_DIR);
804 mkdir(SCRATCH_DIR, 0777);
805 mkdir(SCRATCH_DIR "data", 0777);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700806
Joe Onorato4535e402009-05-15 09:07:06 -0400807 fd = creat(filename, 0666);
808 if (fd == -1) {
809 fprintf(stderr, "error creating: %s\n", strerror(errno));
810 return errno;
811 }
812
813 BackupDataWriter writer(fd);
814
815 err = 0;
816 err |= test_write_header_and_entity(writer, "no_padding_");
817 err |= test_write_header_and_entity(writer, "padded_to__3");
818 err |= test_write_header_and_entity(writer, "padded_to_2__");
819 err |= test_write_header_and_entity(writer, "padded_to1");
820
Joe Onorato4535e402009-05-15 09:07:06 -0400821 close(fd);
822
823 err = compare_file(filename, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
824 if (err != 0) {
825 return err;
826 }
827
828 return err;
829}
830
Joe Onorato2e1da322009-05-15 18:20:19 -0400831int
832test_read_header_and_entity(BackupDataReader& reader, const char* str)
833{
834 int err;
835 int bufSize = strlen(str)+1;
836 char* buf = (char*)malloc(bufSize);
837 String8 string;
838 int cookie = 0x11111111;
839 size_t actualSize;
Joe Onorato5f15d152009-06-16 16:31:35 -0400840 bool done;
841 int type;
Joe Onorato2e1da322009-05-15 18:20:19 -0400842
843 // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str);
844
Joe Onorato5f15d152009-06-16 16:31:35 -0400845 err = reader.ReadNextHeader(&done, &type);
846 if (done) {
847 fprintf(stderr, "should not be done yet\n");
848 goto finished;
849 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400850 if (err != 0) {
851 fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400852 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400853 }
Joe Onorato5f15d152009-06-16 16:31:35 -0400854 if (type != BACKUP_HEADER_ENTITY_V1) {
Joe Onorato2e1da322009-05-15 18:20:19 -0400855 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400856 fprintf(stderr, "type=0x%08x expected 0x%08x\n", type, BACKUP_HEADER_ENTITY_V1);
Joe Onorato2e1da322009-05-15 18:20:19 -0400857 }
858
859 err = reader.ReadEntityHeader(&string, &actualSize);
860 if (err != 0) {
861 fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400862 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400863 }
864 if (string != str) {
865 fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.string());
866 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400867 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400868 }
869 if ((int)actualSize != bufSize) {
870 fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize,
871 actualSize);
872 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400873 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400874 }
875
876 err = reader.ReadEntityData(buf, bufSize);
877 if (err != NO_ERROR) {
878 fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400879 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400880 }
881
882 if (0 != memcmp(buf, str, bufSize)) {
883 fprintf(stderr, "ReadEntityData expected '%s' but got something starting with "
Joe Onorato5f15d152009-06-16 16:31:35 -0400884 "%02x %02x %02x %02x '%c%c%c%c'\n", str, buf[0], buf[1], buf[2], buf[3],
885 buf[0], buf[1], buf[2], buf[3]);
Joe Onorato2e1da322009-05-15 18:20:19 -0400886 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400887 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400888 }
889
890 // The next read will confirm whether it got the right amount of data.
891
Joe Onorato5f15d152009-06-16 16:31:35 -0400892finished:
Joe Onorato2e1da322009-05-15 18:20:19 -0400893 if (err != NO_ERROR) {
894 fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err));
895 }
896 free(buf);
897 return err;
898}
899
900int
901backup_helper_test_data_reader()
902{
903 int err;
904 int fd;
905 const char* filename = SCRATCH_DIR "data_reader.data";
906
907 system("rm -r " SCRATCH_DIR);
908 mkdir(SCRATCH_DIR, 0777);
909 mkdir(SCRATCH_DIR "data", 0777);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700910
Joe Onorato2e1da322009-05-15 18:20:19 -0400911 fd = creat(filename, 0666);
912 if (fd == -1) {
913 fprintf(stderr, "error creating: %s\n", strerror(errno));
914 return errno;
915 }
916
917 err = write(fd, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
918 if (err != DATA_GOLDEN_FILE_SIZE) {
919 fprintf(stderr, "Error \"%s\" writing golden file %s\n", strerror(errno), filename);
920 return errno;
921 }
922
923 close(fd);
924
925 fd = open(filename, O_RDONLY);
926 if (fd == -1) {
927 fprintf(stderr, "Error \"%s\" opening golden file %s for read\n", strerror(errno),
928 filename);
929 return errno;
930 }
931
932 {
933 BackupDataReader reader(fd);
934
935 err = 0;
936
937 if (err == NO_ERROR) {
938 err = test_read_header_and_entity(reader, "no_padding_");
939 }
940
941 if (err == NO_ERROR) {
942 err = test_read_header_and_entity(reader, "padded_to__3");
943 }
944
945 if (err == NO_ERROR) {
946 err = test_read_header_and_entity(reader, "padded_to_2__");
947 }
948
949 if (err == NO_ERROR) {
950 err = test_read_header_and_entity(reader, "padded_to1");
951 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400952 }
953
954 close(fd);
955
956 return err;
957}
958
Joe Onorato3ad977b2009-05-05 11:50:51 -0700959static int
960get_mod_time(const char* filename, struct timeval times[2])
961{
962 int err;
963 struct stat64 st;
964 err = stat64(filename, &st);
965 if (err != 0) {
966 fprintf(stderr, "stat '%s' failed: %s\n", filename, strerror(errno));
967 return errno;
968 }
969 times[0].tv_sec = st.st_atime;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700970 times[1].tv_sec = st.st_mtime;
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700971
972 // If st_atime is a macro then struct stat64 uses struct timespec
973 // to store the access and modif time values and typically
974 // st_*time_nsec is not defined. In glibc, this is controlled by
975 // __USE_MISC.
976#ifdef __USE_MISC
977#if !defined(st_atime) || defined(st_atime_nsec)
978#error "Check if this __USE_MISC conditional is still needed."
979#endif
980 times[0].tv_usec = st.st_atim.tv_nsec / 1000;
981 times[1].tv_usec = st.st_mtim.tv_nsec / 1000;
982#else
983 times[0].tv_usec = st.st_atime_nsec / 1000;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700984 times[1].tv_usec = st.st_mtime_nsec / 1000;
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700985#endif
986
Joe Onorato3ad977b2009-05-05 11:50:51 -0700987 return 0;
988}
989
990int
991backup_helper_test_files()
992{
993 int err;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700994 int oldSnapshotFD;
Joe Onorato4535e402009-05-15 09:07:06 -0400995 int dataStreamFD;
996 int newSnapshotFD;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700997
998 system("rm -r " SCRATCH_DIR);
999 mkdir(SCRATCH_DIR, 0777);
1000 mkdir(SCRATCH_DIR "data", 0777);
1001
1002 write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
1003 write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
1004 write_text_file(SCRATCH_DIR "data/d", "d\ndd\n");
1005 write_text_file(SCRATCH_DIR "data/e", "e\nee\n");
1006 write_text_file(SCRATCH_DIR "data/f", "f\nff\n");
1007 write_text_file(SCRATCH_DIR "data/h", "h\nhh\n");
1008
1009 char const* files_before[] = {
Joe Onorato23ecae32009-06-10 17:07:15 -07001010 SCRATCH_DIR "data/b",
1011 SCRATCH_DIR "data/c",
1012 SCRATCH_DIR "data/d",
1013 SCRATCH_DIR "data/e",
1014 SCRATCH_DIR "data/f"
1015 };
1016
1017 char const* keys_before[] = {
Joe Onorato3ad977b2009-05-05 11:50:51 -07001018 "data/b",
1019 "data/c",
1020 "data/d",
1021 "data/e",
1022 "data/f"
1023 };
1024
Joe Onorato4535e402009-05-15 09:07:06 -04001025 dataStreamFD = creat(SCRATCH_DIR "1.data", 0666);
1026 if (dataStreamFD == -1) {
1027 fprintf(stderr, "error creating: %s\n", strerror(errno));
1028 return errno;
1029 }
1030
Joe Onorato3ad977b2009-05-05 11:50:51 -07001031 newSnapshotFD = creat(SCRATCH_DIR "before.snap", 0666);
1032 if (newSnapshotFD == -1) {
1033 fprintf(stderr, "error creating: %s\n", strerror(errno));
1034 return errno;
1035 }
Joe Onoratod2110db2009-05-19 13:41:21 -07001036
1037 {
1038 BackupDataWriter dataStream(dataStreamFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001039
Joe Onorato23ecae32009-06-10 17:07:15 -07001040 err = back_up_files(-1, &dataStream, newSnapshotFD, files_before, keys_before, 5);
Joe Onoratod2110db2009-05-19 13:41:21 -07001041 if (err != 0) {
1042 return err;
1043 }
Joe Onorato3ad977b2009-05-05 11:50:51 -07001044 }
1045
Joe Onorato4535e402009-05-15 09:07:06 -04001046 close(dataStreamFD);
Joe Onorato3ad977b2009-05-05 11:50:51 -07001047 close(newSnapshotFD);
1048
1049 sleep(3);
1050
1051 struct timeval d_times[2];
1052 struct timeval e_times[2];
1053
1054 err = get_mod_time(SCRATCH_DIR "data/d", d_times);
1055 err |= get_mod_time(SCRATCH_DIR "data/e", e_times);
1056 if (err != 0) {
1057 return err;
1058 }
1059
1060 write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
1061 unlink(SCRATCH_DIR "data/c");
1062 write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
1063 write_text_file(SCRATCH_DIR "data/d", "dd\ndd\n");
1064 utimes(SCRATCH_DIR "data/d", d_times);
1065 write_text_file(SCRATCH_DIR "data/e", "z\nzz\n");
1066 utimes(SCRATCH_DIR "data/e", e_times);
1067 write_text_file(SCRATCH_DIR "data/g", "g\ngg\n");
1068 unlink(SCRATCH_DIR "data/f");
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001069
Joe Onorato3ad977b2009-05-05 11:50:51 -07001070 char const* files_after[] = {
Joe Onorato23ecae32009-06-10 17:07:15 -07001071 SCRATCH_DIR "data/a", // added
1072 SCRATCH_DIR "data/b", // same
1073 SCRATCH_DIR "data/c", // different mod time
1074 SCRATCH_DIR "data/d", // different size (same mod time)
1075 SCRATCH_DIR "data/e", // different contents (same mod time, same size)
1076 SCRATCH_DIR "data/g" // added
1077 };
1078
1079 char const* keys_after[] = {
Joe Onorato3ad977b2009-05-05 11:50:51 -07001080 "data/a", // added
1081 "data/b", // same
1082 "data/c", // different mod time
1083 "data/d", // different size (same mod time)
1084 "data/e", // different contents (same mod time, same size)
1085 "data/g" // added
1086 };
1087
1088 oldSnapshotFD = open(SCRATCH_DIR "before.snap", O_RDONLY);
1089 if (oldSnapshotFD == -1) {
1090 fprintf(stderr, "error opening: %s\n", strerror(errno));
1091 return errno;
1092 }
1093
Joe Onorato4535e402009-05-15 09:07:06 -04001094 dataStreamFD = creat(SCRATCH_DIR "2.data", 0666);
1095 if (dataStreamFD == -1) {
1096 fprintf(stderr, "error creating: %s\n", strerror(errno));
1097 return errno;
1098 }
1099
Joe Onorato3ad977b2009-05-05 11:50:51 -07001100 newSnapshotFD = creat(SCRATCH_DIR "after.snap", 0666);
1101 if (newSnapshotFD == -1) {
1102 fprintf(stderr, "error creating: %s\n", strerror(errno));
1103 return errno;
1104 }
1105
Joe Onoratod2110db2009-05-19 13:41:21 -07001106 {
1107 BackupDataWriter dataStream(dataStreamFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001108
Joe Onorato23ecae32009-06-10 17:07:15 -07001109 err = back_up_files(oldSnapshotFD, &dataStream, newSnapshotFD, files_after, keys_after, 6);
Joe Onoratod2110db2009-05-19 13:41:21 -07001110 if (err != 0) {
1111 return err;
1112 }
1113}
Joe Onorato3ad977b2009-05-05 11:50:51 -07001114
1115 close(oldSnapshotFD);
Joe Onorato4535e402009-05-15 09:07:06 -04001116 close(dataStreamFD);
Joe Onorato3ad977b2009-05-05 11:50:51 -07001117 close(newSnapshotFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001118
Joe Onorato3ad977b2009-05-05 11:50:51 -07001119 return 0;
1120}
1121
Joe Onorato23ecae32009-06-10 17:07:15 -07001122int
1123backup_helper_test_null_base()
1124{
1125 int err;
1126 int oldSnapshotFD;
1127 int dataStreamFD;
1128 int newSnapshotFD;
1129
1130 system("rm -r " SCRATCH_DIR);
1131 mkdir(SCRATCH_DIR, 0777);
1132 mkdir(SCRATCH_DIR "data", 0777);
1133
1134 write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
1135
1136 char const* files[] = {
1137 SCRATCH_DIR "data/a",
1138 };
1139
1140 char const* keys[] = {
1141 "a",
1142 };
1143
1144 dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
1145 if (dataStreamFD == -1) {
1146 fprintf(stderr, "error creating: %s\n", strerror(errno));
1147 return errno;
1148 }
1149
1150 newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
1151 if (newSnapshotFD == -1) {
1152 fprintf(stderr, "error creating: %s\n", strerror(errno));
1153 return errno;
1154 }
1155
1156 {
1157 BackupDataWriter dataStream(dataStreamFD);
1158
1159 err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
1160 if (err != 0) {
1161 return err;
1162 }
1163 }
1164
1165 close(dataStreamFD);
1166 close(newSnapshotFD);
1167
1168 return 0;
1169}
1170
Joe Onoratoce88cb12009-06-11 11:27:16 -07001171int
1172backup_helper_test_missing_file()
1173{
1174 int err;
1175 int oldSnapshotFD;
1176 int dataStreamFD;
1177 int newSnapshotFD;
1178
1179 system("rm -r " SCRATCH_DIR);
1180 mkdir(SCRATCH_DIR, 0777);
1181 mkdir(SCRATCH_DIR "data", 0777);
1182
1183 write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
1184
1185 char const* files[] = {
1186 SCRATCH_DIR "data/a",
1187 SCRATCH_DIR "data/b",
1188 SCRATCH_DIR "data/c",
1189 };
1190
1191 char const* keys[] = {
1192 "a",
1193 "b",
1194 "c",
1195 };
1196
1197 dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
1198 if (dataStreamFD == -1) {
1199 fprintf(stderr, "error creating: %s\n", strerror(errno));
1200 return errno;
1201 }
1202
1203 newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
1204 if (newSnapshotFD == -1) {
1205 fprintf(stderr, "error creating: %s\n", strerror(errno));
1206 return errno;
1207 }
1208
1209 {
1210 BackupDataWriter dataStream(dataStreamFD);
1211
1212 err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
1213 if (err != 0) {
1214 return err;
1215 }
1216 }
1217
1218 close(dataStreamFD);
1219 close(newSnapshotFD);
1220
1221 return 0;
1222}
1223
Joe Onorato23ecae32009-06-10 17:07:15 -07001224
Joe Onorato3ad977b2009-05-05 11:50:51 -07001225#endif // TEST_BACKUP_HELPERS
Joe Onorato4535e402009-05-15 09:07:06 -04001226
1227}