blob: 67d07fed85cf5748974d3b351573b58533c11f7a [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;
Christopher Tate11b15772009-06-23 13:03:00 -0700305 r.s.mode = st.st_mode;
Joe Onoratoce88cb12009-06-11 11:27:16 -0700306 r.s.size = st.st_size;
307 // we compute the crc32 later down below, when we already have the file open.
Joe Onorato3ad977b2009-05-05 11:50:51 -0700308
Joe Onoratoce88cb12009-06-11 11:27:16 -0700309 if (newSnapshot.indexOfKey(key) >= 0) {
310 LOGP("back_up_files key already in use '%s'", key.string());
311 return -1;
312 }
Joe Onorato23ecae32009-06-10 17:07:15 -0700313 }
314 newSnapshot.add(key, r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700315 }
316
317 int n = 0;
318 int N = oldSnapshot.size();
319 int m = 0;
320
321 while (n<N && m<fileCount) {
322 const String8& p = oldSnapshot.keyAt(n);
323 const String8& q = newSnapshot.keyAt(m);
Joe Onoratoce88cb12009-06-11 11:27:16 -0700324 FileRec& g = newSnapshot.editValueAt(m);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700325 int cmp = p.compare(q);
Joe Onoratoce88cb12009-06-11 11:27:16 -0700326 if (g.deleted || cmp < 0) {
327 // file removed
328 LOGP("file removed: %s", p.string());
329 g.deleted = true; // They didn't mention the file, but we noticed that it's gone.
330 dataStream->WriteEntityHeader(p, -1);
331 n++;
332 }
333 else if (cmp > 0) {
Joe Onorato3ad977b2009-05-05 11:50:51 -0700334 // file added
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700335 LOGP("file added: %s", g.file.string());
336 write_update_file(dataStream, q, g.file.string());
Joe Onorato3ad977b2009-05-05 11:50:51 -0700337 m++;
338 }
Joe Onorato3ad977b2009-05-05 11:50:51 -0700339 else {
340 // both files exist, check them
Joe Onorato3ad977b2009-05-05 11:50:51 -0700341 const FileState& f = oldSnapshot.valueAt(n);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700342
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700343 int fd = open(g.file.string(), O_RDONLY);
Christopher Tate0032ce82009-06-04 17:01:06 -0700344 if (fd < 0) {
Joe Onoratod2110db2009-05-19 13:41:21 -0700345 // We can't open the file. Don't report it as a delete either. Let the
346 // server keep the old version. Maybe they'll be able to deal with it
347 // on restore.
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700348 LOGP("Unable to open file %s - skipping", g.file.string());
Joe Onoratod2110db2009-05-19 13:41:21 -0700349 } else {
Joe Onorato23ecae32009-06-10 17:07:15 -0700350 g.s.crc32 = compute_crc32(fd);
Joe Onoratod2110db2009-05-19 13:41:21 -0700351
Joe Onorato23ecae32009-06-10 17:07:15 -0700352 LOGP("%s", q.string());
Christopher Tate11b15772009-06-23 13:03:00 -0700353 LOGP(" new: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
354 f.modTime_sec, f.modTime_nsec, f.mode, f.size, f.crc32);
355 LOGP(" old: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
356 g.s.modTime_sec, g.s.modTime_nsec, g.s.mode, g.s.size, g.s.crc32);
Joe Onorato23ecae32009-06-10 17:07:15 -0700357 if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec
Christopher Tate11b15772009-06-23 13:03:00 -0700358 || f.mode != g.s.mode || f.size != g.s.size || f.crc32 != g.s.crc32) {
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700359 write_update_file(dataStream, fd, p, g.file.string());
Joe Onoratod2110db2009-05-19 13:41:21 -0700360 }
361
362 close(fd);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700363 }
364 n++;
365 m++;
366 }
367 }
368
369 // these were deleted
370 while (n<N) {
Joe Onoratod2110db2009-05-19 13:41:21 -0700371 dataStream->WriteEntityHeader(oldSnapshot.keyAt(n), -1);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700372 n++;
373 }
374
375 // these were added
376 while (m<fileCount) {
377 const String8& q = newSnapshot.keyAt(m);
Joe Onorato23ecae32009-06-10 17:07:15 -0700378 FileRec& g = newSnapshot.editValueAt(m);
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700379 write_update_file(dataStream, q, g.file.string());
Joe Onorato3ad977b2009-05-05 11:50:51 -0700380 m++;
381 }
382
383 err = write_snapshot_file(newSnapshotFD, newSnapshot);
384
385 return 0;
386}
387
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700388#define RESTORE_BUF_SIZE (8*1024)
389
390RestoreHelperBase::RestoreHelperBase()
391{
392 m_buf = malloc(RESTORE_BUF_SIZE);
393}
394
395RestoreHelperBase::~RestoreHelperBase()
396{
397 free(m_buf);
398}
399
400status_t
401RestoreHelperBase::WriteFile(const String8& filename, BackupDataReader* in)
402{
403 ssize_t err;
404 size_t dataSize;
405 String8 key;
406 int fd;
407 void* buf = m_buf;
408 ssize_t amt;
409 int mode;
410 int crc;
411 struct stat st;
412 FileRec r;
413
414 err = in->ReadEntityHeader(&key, &dataSize);
415 if (err != NO_ERROR) {
416 return err;
417 }
Joe Onorato5d605dc2009-06-18 18:23:43 -0700418
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700419 // TODO: World readable/writable for now.
420 mode = 0666;
421
422 // Write the file and compute the crc
423 crc = crc32(0L, Z_NULL, 0);
Joe Onorato5d605dc2009-06-18 18:23:43 -0700424 fd = open(filename.string(), O_CREAT|O_RDWR|O_TRUNC, mode);
425 if (fd == -1) {
426 LOGW("Could not open file %s -- %s", filename.string(), strerror(errno));
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700427 return errno;
428 }
429
430 while ((amt = in->ReadEntityData(buf, RESTORE_BUF_SIZE)) > 0) {
431 err = write(fd, buf, amt);
432 if (err != amt) {
433 close(fd);
Joe Onorato5d605dc2009-06-18 18:23:43 -0700434 LOGW("Error '%s' writing '%s'", strerror(errno), filename.string());
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700435 return errno;
436 }
437 crc = crc32(crc, (Bytef*)buf, amt);
438 }
439
440 close(fd);
441
442 // Record for the snapshot
443 err = stat(filename.string(), &st);
444 if (err != 0) {
445 LOGW("Error stating file that we just created %s", filename.string());
446 return errno;
447 }
448
449 r.file = filename;
450 r.deleted = false;
451 r.s.modTime_sec = st.st_mtime;
452 r.s.modTime_nsec = 0; // workaround sim breakage
453 //r.s.modTime_nsec = st.st_mtime_nsec;
Christopher Tate11b15772009-06-23 13:03:00 -0700454 r.s.mode = st.st_mode;
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700455 r.s.size = st.st_size;
456 r.s.crc32 = crc;
457
458 m_files.add(key, r);
459
460 return NO_ERROR;
461}
462
463status_t
464RestoreHelperBase::WriteSnapshot(int fd)
465{
466 return write_snapshot_file(fd, m_files);;
467}
468
Joe Onorato3ad977b2009-05-05 11:50:51 -0700469#if TEST_BACKUP_HELPERS
470
471#define SCRATCH_DIR "/data/backup_helper_test/"
472
473static int
474write_text_file(const char* path, const char* data)
475{
476 int amt;
477 int fd;
478 int len;
479
480 fd = creat(path, 0666);
481 if (fd == -1) {
482 fprintf(stderr, "creat %s failed\n", path);
483 return errno;
484 }
485
486 len = strlen(data);
487 amt = write(fd, data, len);
488 if (amt != len) {
489 fprintf(stderr, "error (%s) writing to file %s\n", strerror(errno), path);
490 return errno;
491 }
492
493 close(fd);
494
495 return 0;
496}
497
498static int
499compare_file(const char* path, const unsigned char* data, int len)
500{
501 int fd;
502 int amt;
503
504 fd = open(path, O_RDONLY);
505 if (fd == -1) {
506 fprintf(stderr, "compare_file error (%s) opening %s\n", strerror(errno), path);
507 return errno;
508 }
509
510 unsigned char* contents = (unsigned char*)malloc(len);
511 if (contents == NULL) {
512 fprintf(stderr, "malloc(%d) failed\n", len);
513 return ENOMEM;
514 }
515
516 bool sizesMatch = true;
517 amt = lseek(fd, 0, SEEK_END);
518 if (amt != len) {
519 fprintf(stderr, "compare_file file length should be %d, was %d\n", len, amt);
520 sizesMatch = false;
521 }
522 lseek(fd, 0, SEEK_SET);
523
524 int readLen = amt < len ? amt : len;
525 amt = read(fd, contents, readLen);
526 if (amt != readLen) {
527 fprintf(stderr, "compare_file read expected %d bytes but got %d\n", len, amt);
528 }
529
530 bool contentsMatch = true;
531 for (int i=0; i<readLen; i++) {
532 if (data[i] != contents[i]) {
533 if (contentsMatch) {
534 fprintf(stderr, "compare_file contents are different: (index, expected, actual)\n");
535 contentsMatch = false;
536 }
537 fprintf(stderr, " [%-2d] %02x %02x\n", i, data[i], contents[i]);
538 }
539 }
540
541 return contentsMatch && sizesMatch ? 0 : 1;
542}
543
544int
545backup_helper_test_empty()
546{
547 int err;
548 int fd;
Joe Onorato23ecae32009-06-10 17:07:15 -0700549 KeyedVector<String8,FileRec> snapshot;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700550 const char* filename = SCRATCH_DIR "backup_helper_test_empty.snap";
551
552 system("rm -r " SCRATCH_DIR);
553 mkdir(SCRATCH_DIR, 0777);
554
555 // write
556 fd = creat(filename, 0666);
557 if (fd == -1) {
558 fprintf(stderr, "error creating %s\n", filename);
559 return 1;
560 }
561
562 err = write_snapshot_file(fd, snapshot);
563
564 close(fd);
565
566 if (err != 0) {
567 fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err));
568 return err;
569 }
570
571 static const unsigned char correct_data[] = {
572 0x53, 0x6e, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00,
573 0x46, 0x69, 0x6c, 0x65, 0x10, 0x00, 0x00, 0x00
574 };
575
576 err = compare_file(filename, correct_data, sizeof(correct_data));
577 if (err != 0) {
578 return err;
579 }
580
581 // read
582 fd = open(filename, O_RDONLY);
583 if (fd == -1) {
584 fprintf(stderr, "error opening for read %s\n", filename);
585 return 1;
586 }
587
588 KeyedVector<String8,FileState> readSnapshot;
589 err = read_snapshot_file(fd, &readSnapshot);
590 if (err != 0) {
591 fprintf(stderr, "read_snapshot_file failed %d\n", err);
592 return err;
593 }
594
595 if (readSnapshot.size() != 0) {
596 fprintf(stderr, "readSnapshot should be length 0\n");
597 return 1;
598 }
599
600 return 0;
601}
602
603int
604backup_helper_test_four()
605{
606 int err;
607 int fd;
Joe Onorato23ecae32009-06-10 17:07:15 -0700608 KeyedVector<String8,FileRec> snapshot;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700609 const char* filename = SCRATCH_DIR "backup_helper_test_four.snap";
610
611 system("rm -r " SCRATCH_DIR);
612 mkdir(SCRATCH_DIR, 0777);
613
614 // write
615 fd = creat(filename, 0666);
616 if (fd == -1) {
617 fprintf(stderr, "error opening %s\n", filename);
618 return 1;
619 }
620
621 String8 filenames[4];
622 FileState states[4];
Joe Onorato23ecae32009-06-10 17:07:15 -0700623 FileRec r;
Joe Onoratoce88cb12009-06-11 11:27:16 -0700624 r.deleted = false;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700625
626 states[0].modTime_sec = 0xfedcba98;
627 states[0].modTime_nsec = 0xdeadbeef;
Christopher Tate11b15772009-06-23 13:03:00 -0700628 states[0].mode = 0777; // decimal 511, hex 0x000001ff
Joe Onorato3ad977b2009-05-05 11:50:51 -0700629 states[0].size = 0xababbcbc;
630 states[0].crc32 = 0x12345678;
631 states[0].nameLen = -12;
Joe Onorato23ecae32009-06-10 17:07:15 -0700632 r.s = states[0];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700633 filenames[0] = String8("bytes_of_padding");
Joe Onorato23ecae32009-06-10 17:07:15 -0700634 snapshot.add(filenames[0], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700635
636 states[1].modTime_sec = 0x93400031;
637 states[1].modTime_nsec = 0xdeadbeef;
Christopher Tate11b15772009-06-23 13:03:00 -0700638 states[1].mode = 0666; // decimal 438, hex 0x000001b6
Joe Onorato3ad977b2009-05-05 11:50:51 -0700639 states[1].size = 0x88557766;
640 states[1].crc32 = 0x22334422;
641 states[1].nameLen = -1;
Joe Onorato23ecae32009-06-10 17:07:15 -0700642 r.s = states[1];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700643 filenames[1] = String8("bytes_of_padding3");
Joe Onorato23ecae32009-06-10 17:07:15 -0700644 snapshot.add(filenames[1], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700645
646 states[2].modTime_sec = 0x33221144;
647 states[2].modTime_nsec = 0xdeadbeef;
Christopher Tate11b15772009-06-23 13:03:00 -0700648 states[2].mode = 0744; // decimal 484, hex 0x000001e4
Joe Onorato3ad977b2009-05-05 11:50:51 -0700649 states[2].size = 0x11223344;
650 states[2].crc32 = 0x01122334;
651 states[2].nameLen = 0;
Joe Onorato23ecae32009-06-10 17:07:15 -0700652 r.s = states[2];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700653 filenames[2] = String8("bytes_of_padding_2");
Joe Onorato23ecae32009-06-10 17:07:15 -0700654 snapshot.add(filenames[2], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700655
656 states[3].modTime_sec = 0x33221144;
657 states[3].modTime_nsec = 0xdeadbeef;
Christopher Tate11b15772009-06-23 13:03:00 -0700658 states[3].mode = 0755; // decimal 493, hex 0x000001ed
Joe Onorato3ad977b2009-05-05 11:50:51 -0700659 states[3].size = 0x11223344;
660 states[3].crc32 = 0x01122334;
661 states[3].nameLen = 0;
Joe Onorato23ecae32009-06-10 17:07:15 -0700662 r.s = states[3];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700663 filenames[3] = String8("bytes_of_padding__1");
Joe Onorato23ecae32009-06-10 17:07:15 -0700664 snapshot.add(filenames[3], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700665
666 err = write_snapshot_file(fd, snapshot);
667
668 close(fd);
669
670 if (err != 0) {
671 fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err));
672 return err;
673 }
674
675 static const unsigned char correct_data[] = {
676 // header
677 0x53, 0x6e, 0x61, 0x70, 0x04, 0x00, 0x00, 0x00,
Christopher Tate11b15772009-06-23 13:03:00 -0700678 0x46, 0x69, 0x6c, 0x65, 0xbc, 0x00, 0x00, 0x00,
Joe Onorato3ad977b2009-05-05 11:50:51 -0700679
680 // bytes_of_padding
681 0x98, 0xba, 0xdc, 0xfe, 0xef, 0xbe, 0xad, 0xde,
Christopher Tate11b15772009-06-23 13:03:00 -0700682 0xff, 0x01, 0x00, 0x00, 0xbc, 0xbc, 0xab, 0xab,
683 0x78, 0x56, 0x34, 0x12, 0x10, 0x00, 0x00, 0x00,
684 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6f, 0x66,
685 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
Joe Onorato3ad977b2009-05-05 11:50:51 -0700686
687 // bytes_of_padding3
688 0x31, 0x00, 0x40, 0x93, 0xef, 0xbe, 0xad, 0xde,
Christopher Tate11b15772009-06-23 13:03:00 -0700689 0xb6, 0x01, 0x00, 0x00, 0x66, 0x77, 0x55, 0x88,
690 0x22, 0x44, 0x33, 0x22, 0x11, 0x00, 0x00, 0x00,
691 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6f, 0x66,
692 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
693 0x33, 0xab, 0xab, 0xab,
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700694
Joe Onorato3ad977b2009-05-05 11:50:51 -0700695 // bytes of padding2
696 0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde,
Christopher Tate11b15772009-06-23 13:03:00 -0700697 0xe4, 0x01, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11,
698 0x34, 0x23, 0x12, 0x01, 0x12, 0x00, 0x00, 0x00,
699 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6f, 0x66,
700 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
701 0x5f, 0x32, 0xab, 0xab,
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700702
Joe Onorato3ad977b2009-05-05 11:50:51 -0700703 // bytes of padding3
704 0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde,
Christopher Tate11b15772009-06-23 13:03:00 -0700705 0xed, 0x01, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11,
706 0x34, 0x23, 0x12, 0x01, 0x13, 0x00, 0x00, 0x00,
707 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6f, 0x66,
708 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
709 0x5f, 0x5f, 0x31, 0xab
Joe Onorato3ad977b2009-05-05 11:50:51 -0700710 };
711
712 err = compare_file(filename, correct_data, sizeof(correct_data));
713 if (err != 0) {
714 return err;
715 }
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700716
Joe Onorato3ad977b2009-05-05 11:50:51 -0700717 // read
718 fd = open(filename, O_RDONLY);
719 if (fd == -1) {
720 fprintf(stderr, "error opening for read %s\n", filename);
721 return 1;
722 }
723
724
725 KeyedVector<String8,FileState> readSnapshot;
726 err = read_snapshot_file(fd, &readSnapshot);
727 if (err != 0) {
728 fprintf(stderr, "read_snapshot_file failed %d\n", err);
729 return err;
730 }
731
732 if (readSnapshot.size() != 4) {
733 fprintf(stderr, "readSnapshot should be length 4 is %d\n", readSnapshot.size());
734 return 1;
735 }
736
737 bool matched = true;
738 for (size_t i=0; i<readSnapshot.size(); i++) {
739 const String8& name = readSnapshot.keyAt(i);
740 const FileState state = readSnapshot.valueAt(i);
741
742 if (name != filenames[i] || states[i].modTime_sec != state.modTime_sec
Christopher Tate11b15772009-06-23 13:03:00 -0700743 || states[i].modTime_nsec != state.modTime_nsec || states[i].mode != state.mode
Joe Onorato3ad977b2009-05-05 11:50:51 -0700744 || states[i].size != state.size || states[i].crc32 != states[i].crc32) {
Christopher Tate11b15772009-06-23 13:03:00 -0700745 fprintf(stderr, "state %d expected={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n"
746 " actual={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n", i,
747 states[i].modTime_sec, states[i].modTime_nsec, states[i].mode, states[i].size,
748 states[i].crc32, name.length(), filenames[i].string(),
749 state.modTime_sec, state.modTime_nsec, state.mode, state.size, state.crc32,
750 state.nameLen, name.string());
Joe Onorato3ad977b2009-05-05 11:50:51 -0700751 matched = false;
752 }
753 }
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700754
Joe Onorato3ad977b2009-05-05 11:50:51 -0700755 return matched ? 0 : 1;
756}
757
Joe Onorato4535e402009-05-15 09:07:06 -0400758// hexdump -v -e '" " 8/1 " 0x%02x," "\n"' data_writer.data
759const unsigned char DATA_GOLDEN_FILE[] = {
Joe Onorato2e1da322009-05-15 18:20:19 -0400760 0x44, 0x61, 0x74, 0x61, 0x0b, 0x00, 0x00, 0x00,
761 0x0c, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x5f, 0x70,
762 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00,
763 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69,
Joe Onorato5f15d152009-06-16 16:31:35 -0400764 0x6e, 0x67, 0x5f, 0x00, 0x44, 0x61, 0x74, 0x61,
765 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
Joe Onorato4535e402009-05-15 09:07:06 -0400766 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
767 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
Joe Onorato2e1da322009-05-15 18:20:19 -0400768 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
Joe Onorato5f15d152009-06-16 16:31:35 -0400769 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
Joe Onorato2e1da322009-05-15 18:20:19 -0400770 0x44, 0x61, 0x74, 0x61, 0x0d, 0x00, 0x00, 0x00,
771 0x0e, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
Joe Onorato4535e402009-05-15 09:07:06 -0400772 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
Joe Onorato2e1da322009-05-15 18:20:19 -0400773 0x5f, 0x00, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64,
774 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
Joe Onorato5f15d152009-06-16 16:31:35 -0400775 0x5f, 0x00, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61,
Joe Onorato4535e402009-05-15 09:07:06 -0400776 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
777 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
778 0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64,
Joe Onorato5f15d152009-06-16 16:31:35 -0400779 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00
780
Joe Onorato4535e402009-05-15 09:07:06 -0400781};
782const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE);
783
784static int
785test_write_header_and_entity(BackupDataWriter& writer, const char* str)
786{
787 int err;
788 String8 text(str);
789
Joe Onorato4535e402009-05-15 09:07:06 -0400790 err = writer.WriteEntityHeader(text, text.length()+1);
791 if (err != 0) {
792 fprintf(stderr, "WriteEntityHeader failed with %s\n", strerror(err));
793 return err;
794 }
795
796 err = writer.WriteEntityData(text.string(), text.length()+1);
797 if (err != 0) {
798 fprintf(stderr, "write failed for data '%s'\n", text.string());
799 return errno;
800 }
801
802 return err;
803}
804
805int
806backup_helper_test_data_writer()
807{
808 int err;
809 int fd;
810 const char* filename = SCRATCH_DIR "data_writer.data";
811
812 system("rm -r " SCRATCH_DIR);
813 mkdir(SCRATCH_DIR, 0777);
814 mkdir(SCRATCH_DIR "data", 0777);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700815
Joe Onorato4535e402009-05-15 09:07:06 -0400816 fd = creat(filename, 0666);
817 if (fd == -1) {
818 fprintf(stderr, "error creating: %s\n", strerror(errno));
819 return errno;
820 }
821
822 BackupDataWriter writer(fd);
823
824 err = 0;
825 err |= test_write_header_and_entity(writer, "no_padding_");
826 err |= test_write_header_and_entity(writer, "padded_to__3");
827 err |= test_write_header_and_entity(writer, "padded_to_2__");
828 err |= test_write_header_and_entity(writer, "padded_to1");
829
Joe Onorato4535e402009-05-15 09:07:06 -0400830 close(fd);
831
832 err = compare_file(filename, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
833 if (err != 0) {
834 return err;
835 }
836
837 return err;
838}
839
Joe Onorato2e1da322009-05-15 18:20:19 -0400840int
841test_read_header_and_entity(BackupDataReader& reader, const char* str)
842{
843 int err;
844 int bufSize = strlen(str)+1;
845 char* buf = (char*)malloc(bufSize);
846 String8 string;
847 int cookie = 0x11111111;
848 size_t actualSize;
Joe Onorato5f15d152009-06-16 16:31:35 -0400849 bool done;
850 int type;
Christopher Tate11b15772009-06-23 13:03:00 -0700851 ssize_t nRead;
Joe Onorato2e1da322009-05-15 18:20:19 -0400852
853 // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str);
854
Joe Onorato5f15d152009-06-16 16:31:35 -0400855 err = reader.ReadNextHeader(&done, &type);
856 if (done) {
857 fprintf(stderr, "should not be done yet\n");
858 goto finished;
859 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400860 if (err != 0) {
861 fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400862 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400863 }
Joe Onorato5f15d152009-06-16 16:31:35 -0400864 if (type != BACKUP_HEADER_ENTITY_V1) {
Joe Onorato2e1da322009-05-15 18:20:19 -0400865 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400866 fprintf(stderr, "type=0x%08x expected 0x%08x\n", type, BACKUP_HEADER_ENTITY_V1);
Joe Onorato2e1da322009-05-15 18:20:19 -0400867 }
868
869 err = reader.ReadEntityHeader(&string, &actualSize);
870 if (err != 0) {
871 fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400872 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400873 }
874 if (string != str) {
875 fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.string());
876 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400877 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400878 }
879 if ((int)actualSize != bufSize) {
880 fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize,
881 actualSize);
882 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400883 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400884 }
885
Christopher Tate11b15772009-06-23 13:03:00 -0700886 nRead = reader.ReadEntityData(buf, bufSize);
887 if (nRead < 0) {
888 err = reader.Status();
Joe Onorato2e1da322009-05-15 18:20:19 -0400889 fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400890 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400891 }
892
893 if (0 != memcmp(buf, str, bufSize)) {
894 fprintf(stderr, "ReadEntityData expected '%s' but got something starting with "
Joe Onorato5f15d152009-06-16 16:31:35 -0400895 "%02x %02x %02x %02x '%c%c%c%c'\n", str, buf[0], buf[1], buf[2], buf[3],
896 buf[0], buf[1], buf[2], buf[3]);
Joe Onorato2e1da322009-05-15 18:20:19 -0400897 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400898 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400899 }
900
901 // The next read will confirm whether it got the right amount of data.
902
Joe Onorato5f15d152009-06-16 16:31:35 -0400903finished:
Joe Onorato2e1da322009-05-15 18:20:19 -0400904 if (err != NO_ERROR) {
905 fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err));
906 }
907 free(buf);
908 return err;
909}
910
911int
912backup_helper_test_data_reader()
913{
914 int err;
915 int fd;
916 const char* filename = SCRATCH_DIR "data_reader.data";
917
918 system("rm -r " SCRATCH_DIR);
919 mkdir(SCRATCH_DIR, 0777);
920 mkdir(SCRATCH_DIR "data", 0777);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700921
Joe Onorato2e1da322009-05-15 18:20:19 -0400922 fd = creat(filename, 0666);
923 if (fd == -1) {
924 fprintf(stderr, "error creating: %s\n", strerror(errno));
925 return errno;
926 }
927
928 err = write(fd, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
929 if (err != DATA_GOLDEN_FILE_SIZE) {
930 fprintf(stderr, "Error \"%s\" writing golden file %s\n", strerror(errno), filename);
931 return errno;
932 }
933
934 close(fd);
935
936 fd = open(filename, O_RDONLY);
937 if (fd == -1) {
938 fprintf(stderr, "Error \"%s\" opening golden file %s for read\n", strerror(errno),
939 filename);
940 return errno;
941 }
942
943 {
944 BackupDataReader reader(fd);
945
946 err = 0;
947
948 if (err == NO_ERROR) {
949 err = test_read_header_and_entity(reader, "no_padding_");
950 }
951
952 if (err == NO_ERROR) {
953 err = test_read_header_and_entity(reader, "padded_to__3");
954 }
955
956 if (err == NO_ERROR) {
957 err = test_read_header_and_entity(reader, "padded_to_2__");
958 }
959
960 if (err == NO_ERROR) {
961 err = test_read_header_and_entity(reader, "padded_to1");
962 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400963 }
964
965 close(fd);
966
967 return err;
968}
969
Joe Onorato3ad977b2009-05-05 11:50:51 -0700970static int
971get_mod_time(const char* filename, struct timeval times[2])
972{
973 int err;
974 struct stat64 st;
975 err = stat64(filename, &st);
976 if (err != 0) {
977 fprintf(stderr, "stat '%s' failed: %s\n", filename, strerror(errno));
978 return errno;
979 }
980 times[0].tv_sec = st.st_atime;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700981 times[1].tv_sec = st.st_mtime;
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700982
983 // If st_atime is a macro then struct stat64 uses struct timespec
984 // to store the access and modif time values and typically
985 // st_*time_nsec is not defined. In glibc, this is controlled by
986 // __USE_MISC.
987#ifdef __USE_MISC
988#if !defined(st_atime) || defined(st_atime_nsec)
989#error "Check if this __USE_MISC conditional is still needed."
990#endif
991 times[0].tv_usec = st.st_atim.tv_nsec / 1000;
992 times[1].tv_usec = st.st_mtim.tv_nsec / 1000;
993#else
994 times[0].tv_usec = st.st_atime_nsec / 1000;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700995 times[1].tv_usec = st.st_mtime_nsec / 1000;
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700996#endif
997
Joe Onorato3ad977b2009-05-05 11:50:51 -0700998 return 0;
999}
1000
1001int
1002backup_helper_test_files()
1003{
1004 int err;
Joe Onorato3ad977b2009-05-05 11:50:51 -07001005 int oldSnapshotFD;
Joe Onorato4535e402009-05-15 09:07:06 -04001006 int dataStreamFD;
1007 int newSnapshotFD;
Joe Onorato3ad977b2009-05-05 11:50:51 -07001008
1009 system("rm -r " SCRATCH_DIR);
1010 mkdir(SCRATCH_DIR, 0777);
1011 mkdir(SCRATCH_DIR "data", 0777);
1012
1013 write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
1014 write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
1015 write_text_file(SCRATCH_DIR "data/d", "d\ndd\n");
1016 write_text_file(SCRATCH_DIR "data/e", "e\nee\n");
1017 write_text_file(SCRATCH_DIR "data/f", "f\nff\n");
1018 write_text_file(SCRATCH_DIR "data/h", "h\nhh\n");
1019
1020 char const* files_before[] = {
Joe Onorato23ecae32009-06-10 17:07:15 -07001021 SCRATCH_DIR "data/b",
1022 SCRATCH_DIR "data/c",
1023 SCRATCH_DIR "data/d",
1024 SCRATCH_DIR "data/e",
1025 SCRATCH_DIR "data/f"
1026 };
1027
1028 char const* keys_before[] = {
Joe Onorato3ad977b2009-05-05 11:50:51 -07001029 "data/b",
1030 "data/c",
1031 "data/d",
1032 "data/e",
1033 "data/f"
1034 };
1035
Joe Onorato4535e402009-05-15 09:07:06 -04001036 dataStreamFD = creat(SCRATCH_DIR "1.data", 0666);
1037 if (dataStreamFD == -1) {
1038 fprintf(stderr, "error creating: %s\n", strerror(errno));
1039 return errno;
1040 }
1041
Joe Onorato3ad977b2009-05-05 11:50:51 -07001042 newSnapshotFD = creat(SCRATCH_DIR "before.snap", 0666);
1043 if (newSnapshotFD == -1) {
1044 fprintf(stderr, "error creating: %s\n", strerror(errno));
1045 return errno;
1046 }
Joe Onoratod2110db2009-05-19 13:41:21 -07001047
1048 {
1049 BackupDataWriter dataStream(dataStreamFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001050
Joe Onorato23ecae32009-06-10 17:07:15 -07001051 err = back_up_files(-1, &dataStream, newSnapshotFD, files_before, keys_before, 5);
Joe Onoratod2110db2009-05-19 13:41:21 -07001052 if (err != 0) {
1053 return err;
1054 }
Joe Onorato3ad977b2009-05-05 11:50:51 -07001055 }
1056
Joe Onorato4535e402009-05-15 09:07:06 -04001057 close(dataStreamFD);
Joe Onorato3ad977b2009-05-05 11:50:51 -07001058 close(newSnapshotFD);
1059
1060 sleep(3);
1061
1062 struct timeval d_times[2];
1063 struct timeval e_times[2];
1064
1065 err = get_mod_time(SCRATCH_DIR "data/d", d_times);
1066 err |= get_mod_time(SCRATCH_DIR "data/e", e_times);
1067 if (err != 0) {
1068 return err;
1069 }
1070
1071 write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
1072 unlink(SCRATCH_DIR "data/c");
1073 write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
1074 write_text_file(SCRATCH_DIR "data/d", "dd\ndd\n");
1075 utimes(SCRATCH_DIR "data/d", d_times);
1076 write_text_file(SCRATCH_DIR "data/e", "z\nzz\n");
1077 utimes(SCRATCH_DIR "data/e", e_times);
1078 write_text_file(SCRATCH_DIR "data/g", "g\ngg\n");
1079 unlink(SCRATCH_DIR "data/f");
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001080
Joe Onorato3ad977b2009-05-05 11:50:51 -07001081 char const* files_after[] = {
Joe Onorato23ecae32009-06-10 17:07:15 -07001082 SCRATCH_DIR "data/a", // added
1083 SCRATCH_DIR "data/b", // same
1084 SCRATCH_DIR "data/c", // different mod time
1085 SCRATCH_DIR "data/d", // different size (same mod time)
1086 SCRATCH_DIR "data/e", // different contents (same mod time, same size)
1087 SCRATCH_DIR "data/g" // added
1088 };
1089
1090 char const* keys_after[] = {
Joe Onorato3ad977b2009-05-05 11:50:51 -07001091 "data/a", // added
1092 "data/b", // same
1093 "data/c", // different mod time
1094 "data/d", // different size (same mod time)
1095 "data/e", // different contents (same mod time, same size)
1096 "data/g" // added
1097 };
1098
1099 oldSnapshotFD = open(SCRATCH_DIR "before.snap", O_RDONLY);
1100 if (oldSnapshotFD == -1) {
1101 fprintf(stderr, "error opening: %s\n", strerror(errno));
1102 return errno;
1103 }
1104
Joe Onorato4535e402009-05-15 09:07:06 -04001105 dataStreamFD = creat(SCRATCH_DIR "2.data", 0666);
1106 if (dataStreamFD == -1) {
1107 fprintf(stderr, "error creating: %s\n", strerror(errno));
1108 return errno;
1109 }
1110
Joe Onorato3ad977b2009-05-05 11:50:51 -07001111 newSnapshotFD = creat(SCRATCH_DIR "after.snap", 0666);
1112 if (newSnapshotFD == -1) {
1113 fprintf(stderr, "error creating: %s\n", strerror(errno));
1114 return errno;
1115 }
1116
Joe Onoratod2110db2009-05-19 13:41:21 -07001117 {
1118 BackupDataWriter dataStream(dataStreamFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001119
Joe Onorato23ecae32009-06-10 17:07:15 -07001120 err = back_up_files(oldSnapshotFD, &dataStream, newSnapshotFD, files_after, keys_after, 6);
Joe Onoratod2110db2009-05-19 13:41:21 -07001121 if (err != 0) {
1122 return err;
1123 }
1124}
Joe Onorato3ad977b2009-05-05 11:50:51 -07001125
1126 close(oldSnapshotFD);
Joe Onorato4535e402009-05-15 09:07:06 -04001127 close(dataStreamFD);
Joe Onorato3ad977b2009-05-05 11:50:51 -07001128 close(newSnapshotFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001129
Joe Onorato3ad977b2009-05-05 11:50:51 -07001130 return 0;
1131}
1132
Joe Onorato23ecae32009-06-10 17:07:15 -07001133int
1134backup_helper_test_null_base()
1135{
1136 int err;
1137 int oldSnapshotFD;
1138 int dataStreamFD;
1139 int newSnapshotFD;
1140
1141 system("rm -r " SCRATCH_DIR);
1142 mkdir(SCRATCH_DIR, 0777);
1143 mkdir(SCRATCH_DIR "data", 0777);
1144
1145 write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
1146
1147 char const* files[] = {
1148 SCRATCH_DIR "data/a",
1149 };
1150
1151 char const* keys[] = {
1152 "a",
1153 };
1154
1155 dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
1156 if (dataStreamFD == -1) {
1157 fprintf(stderr, "error creating: %s\n", strerror(errno));
1158 return errno;
1159 }
1160
1161 newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
1162 if (newSnapshotFD == -1) {
1163 fprintf(stderr, "error creating: %s\n", strerror(errno));
1164 return errno;
1165 }
1166
1167 {
1168 BackupDataWriter dataStream(dataStreamFD);
1169
1170 err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
1171 if (err != 0) {
1172 return err;
1173 }
1174 }
1175
1176 close(dataStreamFD);
1177 close(newSnapshotFD);
1178
1179 return 0;
1180}
1181
Joe Onoratoce88cb12009-06-11 11:27:16 -07001182int
1183backup_helper_test_missing_file()
1184{
1185 int err;
1186 int oldSnapshotFD;
1187 int dataStreamFD;
1188 int newSnapshotFD;
1189
1190 system("rm -r " SCRATCH_DIR);
1191 mkdir(SCRATCH_DIR, 0777);
1192 mkdir(SCRATCH_DIR "data", 0777);
1193
1194 write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
1195
1196 char const* files[] = {
1197 SCRATCH_DIR "data/a",
1198 SCRATCH_DIR "data/b",
1199 SCRATCH_DIR "data/c",
1200 };
1201
1202 char const* keys[] = {
1203 "a",
1204 "b",
1205 "c",
1206 };
1207
1208 dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
1209 if (dataStreamFD == -1) {
1210 fprintf(stderr, "error creating: %s\n", strerror(errno));
1211 return errno;
1212 }
1213
1214 newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
1215 if (newSnapshotFD == -1) {
1216 fprintf(stderr, "error creating: %s\n", strerror(errno));
1217 return errno;
1218 }
1219
1220 {
1221 BackupDataWriter dataStream(dataStreamFD);
1222
1223 err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
1224 if (err != 0) {
1225 return err;
1226 }
1227 }
1228
1229 close(dataStreamFD);
1230 close(newSnapshotFD);
1231
1232 return 0;
1233}
1234
Joe Onorato23ecae32009-06-10 17:07:15 -07001235
Joe Onorato3ad977b2009-05-05 11:50:51 -07001236#endif // TEST_BACKUP_HELPERS
Joe Onorato4535e402009-05-15 09:07:06 -04001237
1238}