blob: 4ad9b5179532a7b08d9bae10d8824e13d666e131 [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
Christopher Tatefbb92382009-06-23 17:35:11 -070044/*
45 * File entity data format (v1):
46 *
47 * - 4-byte version number of the metadata, little endian (0x00000001 for v1)
48 * - 12 bytes of metadata
49 * - the file data itself
50 *
51 * i.e. a 16-byte metadata header followed by the raw file data. If the
52 * restore code does not recognize the metadata version, it can still
53 * interpret the file data itself correctly.
54 *
55 * file_metadata_v1:
56 *
57 * - 4 byte version number === 0x00000001 (little endian)
58 * - 4-byte access mode (little-endian)
59 * - undefined (8 bytes)
60 */
61
62struct file_metadata_v1 {
63 int version;
64 int mode;
65 int undefined_1;
66 int undefined_2;
67};
68
69const static int CURRENT_METADATA_VERSION = 1;
70
Joe Onorato568bc322009-06-26 17:19:11 -040071#if 1
72#define LOGP(f, x...)
73#else
74#if TEST_BACKUP_HELPERS
Joe Onorato23ecae32009-06-10 17:07:15 -070075#define LOGP(f, x...) printf(f "\n", x)
Joe Onorato4535e402009-05-15 09:07:06 -040076#else
Joe Onorato290bb012009-05-13 18:57:29 -040077#define LOGP(x...) LOGD(x)
Joe Onorato4535e402009-05-15 09:07:06 -040078#endif
Joe Onorato568bc322009-06-26 17:19:11 -040079#endif
Joe Onorato290bb012009-05-13 18:57:29 -040080
Joe Onorato3ad977b2009-05-05 11:50:51 -070081const static int ROUND_UP[4] = { 0, 3, 2, 1 };
82
83static inline int
84round_up(int n)
85{
86 return n + ROUND_UP[n % 4];
87}
88
89static int
90read_snapshot_file(int fd, KeyedVector<String8,FileState>* snapshot)
91{
92 int bytesRead = 0;
93 int amt;
94 SnapshotHeader header;
95
96 amt = read(fd, &header, sizeof(header));
97 if (amt != sizeof(header)) {
98 return errno;
99 }
100 bytesRead += amt;
101
102 if (header.magic0 != MAGIC0 || header.magic1 != MAGIC1) {
103 LOGW("read_snapshot_file header.magic0=0x%08x magic1=0x%08x", header.magic0, header.magic1);
104 return 1;
105 }
106
107 for (int i=0; i<header.fileCount; i++) {
108 FileState file;
109 char filenameBuf[128];
110
Joe Onorato23ecae32009-06-10 17:07:15 -0700111 amt = read(fd, &file, sizeof(FileState));
112 if (amt != sizeof(FileState)) {
Joe Onorato3ad977b2009-05-05 11:50:51 -0700113 LOGW("read_snapshot_file FileState truncated/error with read at %d bytes\n", bytesRead);
114 return 1;
115 }
116 bytesRead += amt;
117
118 // filename is not NULL terminated, but it is padded
119 int nameBufSize = round_up(file.nameLen);
120 char* filename = nameBufSize <= (int)sizeof(filenameBuf)
121 ? filenameBuf
122 : (char*)malloc(nameBufSize);
123 amt = read(fd, filename, nameBufSize);
124 if (amt == nameBufSize) {
125 snapshot->add(String8(filename, file.nameLen), file);
126 }
127 bytesRead += amt;
128 if (filename != filenameBuf) {
129 free(filename);
130 }
131 if (amt != nameBufSize) {
132 LOGW("read_snapshot_file filename truncated/error with read at %d bytes\n", bytesRead);
133 return 1;
134 }
135 }
136
137 if (header.totalSize != bytesRead) {
138 LOGW("read_snapshot_file length mismatch: header.totalSize=%d bytesRead=%d\n",
139 header.totalSize, bytesRead);
140 return 1;
141 }
142
143 return 0;
144}
145
146static int
Joe Onorato23ecae32009-06-10 17:07:15 -0700147write_snapshot_file(int fd, const KeyedVector<String8,FileRec>& snapshot)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700148{
Joe Onoratoce88cb12009-06-11 11:27:16 -0700149 int fileCount = 0;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700150 int bytesWritten = sizeof(SnapshotHeader);
151 // preflight size
152 const int N = snapshot.size();
153 for (int i=0; i<N; i++) {
Joe Onoratoce88cb12009-06-11 11:27:16 -0700154 const FileRec& g = snapshot.valueAt(i);
155 if (!g.deleted) {
156 const String8& name = snapshot.keyAt(i);
157 bytesWritten += sizeof(FileState) + round_up(name.length());
158 fileCount++;
159 }
Joe Onorato3ad977b2009-05-05 11:50:51 -0700160 }
161
Joe Onorato4535e402009-05-15 09:07:06 -0400162 LOGP("write_snapshot_file fd=%d\n", fd);
163
Joe Onorato3ad977b2009-05-05 11:50:51 -0700164 int amt;
Joe Onoratoce88cb12009-06-11 11:27:16 -0700165 SnapshotHeader header = { MAGIC0, fileCount, MAGIC1, bytesWritten };
Joe Onorato3ad977b2009-05-05 11:50:51 -0700166
167 amt = write(fd, &header, sizeof(header));
168 if (amt != sizeof(header)) {
169 LOGW("write_snapshot_file error writing header %s", strerror(errno));
170 return errno;
171 }
172
Joe Onoratoce88cb12009-06-11 11:27:16 -0700173 for (int i=0; i<N; i++) {
Joe Onorato23ecae32009-06-10 17:07:15 -0700174 FileRec r = snapshot.valueAt(i);
Joe Onoratoce88cb12009-06-11 11:27:16 -0700175 if (!r.deleted) {
176 const String8& name = snapshot.keyAt(i);
177 int nameLen = r.s.nameLen = name.length();
Joe Onorato3ad977b2009-05-05 11:50:51 -0700178
Joe Onoratoce88cb12009-06-11 11:27:16 -0700179 amt = write(fd, &r.s, sizeof(FileState));
180 if (amt != sizeof(FileState)) {
181 LOGW("write_snapshot_file error writing header %s", strerror(errno));
Joe Onorato3ad977b2009-05-05 11:50:51 -0700182 return 1;
183 }
Joe Onoratoce88cb12009-06-11 11:27:16 -0700184
185 // filename is not NULL terminated, but it is padded
186 amt = write(fd, name.string(), nameLen);
187 if (amt != nameLen) {
188 LOGW("write_snapshot_file error writing filename %s", strerror(errno));
189 return 1;
190 }
191 int paddingLen = ROUND_UP[nameLen % 4];
192 if (paddingLen != 0) {
193 int padding = 0xabababab;
194 amt = write(fd, &padding, paddingLen);
195 if (amt != paddingLen) {
196 LOGW("write_snapshot_file error writing %d bytes of filename padding %s",
197 paddingLen, strerror(errno));
198 return 1;
199 }
200 }
Joe Onorato3ad977b2009-05-05 11:50:51 -0700201 }
202 }
203
204 return 0;
205}
206
207static int
Joe Onoratod2110db2009-05-19 13:41:21 -0700208write_delete_file(BackupDataWriter* dataStream, const String8& key)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700209{
Joe Onorato290bb012009-05-13 18:57:29 -0400210 LOGP("write_delete_file %s\n", key.string());
Joe Onoratod2110db2009-05-19 13:41:21 -0700211 return dataStream->WriteEntityHeader(key, -1);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700212}
213
214static int
Christopher Tatefbb92382009-06-23 17:35:11 -0700215write_update_file(BackupDataWriter* dataStream, int fd, int mode, const String8& key,
Joe Onorato23ecae32009-06-10 17:07:15 -0700216 char const* realFilename)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700217{
Christopher Tatefbb92382009-06-23 17:35:11 -0700218 LOGP("write_update_file %s (%s) : mode 0%o\n", realFilename, key.string(), mode);
Joe Onoratod2110db2009-05-19 13:41:21 -0700219
220 const int bufsize = 4*1024;
221 int err;
222 int amt;
223 int fileSize;
224 int bytesLeft;
Christopher Tatefbb92382009-06-23 17:35:11 -0700225 file_metadata_v1 metadata;
Joe Onoratod2110db2009-05-19 13:41:21 -0700226
227 char* buf = (char*)malloc(bufsize);
228 int crc = crc32(0L, Z_NULL, 0);
229
230
Christopher Tatefbb92382009-06-23 17:35:11 -0700231 fileSize = lseek(fd, 0, SEEK_END);
Joe Onoratod2110db2009-05-19 13:41:21 -0700232 lseek(fd, 0, SEEK_SET);
233
Christopher Tatefbb92382009-06-23 17:35:11 -0700234 if (sizeof(metadata) != 16) {
235 LOGE("ERROR: metadata block is the wrong size!");
236 }
237
238 bytesLeft = fileSize + sizeof(metadata);
Joe Onoratod2110db2009-05-19 13:41:21 -0700239 err = dataStream->WriteEntityHeader(key, bytesLeft);
240 if (err != 0) {
Christopher Tate63bcb792009-06-24 13:57:29 -0700241 free(buf);
Joe Onoratod2110db2009-05-19 13:41:21 -0700242 return err;
243 }
244
Christopher Tatefbb92382009-06-23 17:35:11 -0700245 // store the file metadata first
246 metadata.version = tolel(CURRENT_METADATA_VERSION);
247 metadata.mode = tolel(mode);
248 metadata.undefined_1 = metadata.undefined_2 = 0;
249 err = dataStream->WriteEntityData(&metadata, sizeof(metadata));
250 if (err != 0) {
Christopher Tate63bcb792009-06-24 13:57:29 -0700251 free(buf);
Christopher Tatefbb92382009-06-23 17:35:11 -0700252 return err;
253 }
254 bytesLeft -= sizeof(metadata); // bytesLeft should == fileSize now
255
256 // now store the file content
Joe Onoratod2110db2009-05-19 13:41:21 -0700257 while ((amt = read(fd, buf, bufsize)) != 0 && bytesLeft > 0) {
258 bytesLeft -= amt;
259 if (bytesLeft < 0) {
260 amt += bytesLeft; // Plus a negative is minus. Don't write more than we promised.
261 }
262 err = dataStream->WriteEntityData(buf, amt);
263 if (err != 0) {
Christopher Tate63bcb792009-06-24 13:57:29 -0700264 free(buf);
Joe Onoratod2110db2009-05-19 13:41:21 -0700265 return err;
266 }
267 }
268 if (bytesLeft != 0) {
269 if (bytesLeft > 0) {
270 // Pad out the space we promised in the buffer. We can't corrupt the buffer,
271 // even though the data we're sending is probably bad.
272 memset(buf, 0, bufsize);
273 while (bytesLeft > 0) {
274 amt = bytesLeft < bufsize ? bytesLeft : bufsize;
275 bytesLeft -= amt;
276 err = dataStream->WriteEntityData(buf, amt);
277 if (err != 0) {
Christopher Tate63bcb792009-06-24 13:57:29 -0700278 free(buf);
Joe Onoratod2110db2009-05-19 13:41:21 -0700279 return err;
280 }
281 }
282 }
283 LOGE("write_update_file size mismatch for %s. expected=%d actual=%d."
Joe Onorato23ecae32009-06-10 17:07:15 -0700284 " You aren't doing proper locking!", realFilename, fileSize, fileSize-bytesLeft);
Joe Onoratod2110db2009-05-19 13:41:21 -0700285 }
286
Christopher Tate63bcb792009-06-24 13:57:29 -0700287 free(buf);
Joe Onoratod2110db2009-05-19 13:41:21 -0700288 return NO_ERROR;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700289}
290
291static int
Joe Onorato23ecae32009-06-10 17:07:15 -0700292write_update_file(BackupDataWriter* dataStream, const String8& key, char const* realFilename)
Joe Onoratod2110db2009-05-19 13:41:21 -0700293{
294 int err;
Christopher Tatefbb92382009-06-23 17:35:11 -0700295 struct stat st;
296
297 err = stat(realFilename, &st);
298 if (err < 0) {
299 return errno;
300 }
301
Joe Onorato23ecae32009-06-10 17:07:15 -0700302 int fd = open(realFilename, O_RDONLY);
Joe Onoratod2110db2009-05-19 13:41:21 -0700303 if (fd == -1) {
304 return errno;
305 }
Christopher Tatefbb92382009-06-23 17:35:11 -0700306
307 err = write_update_file(dataStream, fd, st.st_mode, key, realFilename);
Joe Onoratod2110db2009-05-19 13:41:21 -0700308 close(fd);
309 return err;
310}
311
312static int
313compute_crc32(int fd)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700314{
315 const int bufsize = 4*1024;
316 int amt;
317
Joe Onorato3ad977b2009-05-05 11:50:51 -0700318 char* buf = (char*)malloc(bufsize);
319 int crc = crc32(0L, Z_NULL, 0);
320
Joe Onoratod2110db2009-05-19 13:41:21 -0700321 lseek(fd, 0, SEEK_SET);
322
Joe Onorato3ad977b2009-05-05 11:50:51 -0700323 while ((amt = read(fd, buf, bufsize)) != 0) {
324 crc = crc32(crc, (Bytef*)buf, amt);
325 }
326
Christopher Tate63bcb792009-06-24 13:57:29 -0700327 free(buf);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700328 return crc;
329}
330
331int
Joe Onoratod2110db2009-05-19 13:41:21 -0700332back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD,
Joe Onorato23ecae32009-06-10 17:07:15 -0700333 char const* const* files, char const* const* keys, int fileCount)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700334{
335 int err;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700336 KeyedVector<String8,FileState> oldSnapshot;
Joe Onorato23ecae32009-06-10 17:07:15 -0700337 KeyedVector<String8,FileRec> newSnapshot;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700338
339 if (oldSnapshotFD != -1) {
340 err = read_snapshot_file(oldSnapshotFD, &oldSnapshot);
341 if (err != 0) {
342 // On an error, treat this as a full backup.
343 oldSnapshot.clear();
344 }
345 }
346
347 for (int i=0; i<fileCount; i++) {
Joe Onorato23ecae32009-06-10 17:07:15 -0700348 String8 key(keys[i]);
349 FileRec r;
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700350 char const* file = files[i];
351 r.file = file;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700352 struct stat st;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700353
Joe Onorato23ecae32009-06-10 17:07:15 -0700354 err = stat(file, &st);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700355 if (err != 0) {
Joe Onoratoce88cb12009-06-11 11:27:16 -0700356 r.deleted = true;
357 } else {
358 r.deleted = false;
359 r.s.modTime_sec = st.st_mtime;
360 r.s.modTime_nsec = 0; // workaround sim breakage
361 //r.s.modTime_nsec = st.st_mtime_nsec;
Christopher Tate11b15772009-06-23 13:03:00 -0700362 r.s.mode = st.st_mode;
Joe Onoratoce88cb12009-06-11 11:27:16 -0700363 r.s.size = st.st_size;
364 // we compute the crc32 later down below, when we already have the file open.
Joe Onorato3ad977b2009-05-05 11:50:51 -0700365
Joe Onoratoce88cb12009-06-11 11:27:16 -0700366 if (newSnapshot.indexOfKey(key) >= 0) {
367 LOGP("back_up_files key already in use '%s'", key.string());
368 return -1;
369 }
Joe Onorato23ecae32009-06-10 17:07:15 -0700370 }
371 newSnapshot.add(key, r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700372 }
373
374 int n = 0;
375 int N = oldSnapshot.size();
376 int m = 0;
377
378 while (n<N && m<fileCount) {
379 const String8& p = oldSnapshot.keyAt(n);
380 const String8& q = newSnapshot.keyAt(m);
Joe Onoratoce88cb12009-06-11 11:27:16 -0700381 FileRec& g = newSnapshot.editValueAt(m);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700382 int cmp = p.compare(q);
Joe Onoratoce88cb12009-06-11 11:27:16 -0700383 if (g.deleted || cmp < 0) {
384 // file removed
385 LOGP("file removed: %s", p.string());
386 g.deleted = true; // They didn't mention the file, but we noticed that it's gone.
387 dataStream->WriteEntityHeader(p, -1);
388 n++;
389 }
390 else if (cmp > 0) {
Joe Onorato3ad977b2009-05-05 11:50:51 -0700391 // file added
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700392 LOGP("file added: %s", g.file.string());
393 write_update_file(dataStream, q, g.file.string());
Joe Onorato3ad977b2009-05-05 11:50:51 -0700394 m++;
395 }
Joe Onorato3ad977b2009-05-05 11:50:51 -0700396 else {
397 // both files exist, check them
Joe Onorato3ad977b2009-05-05 11:50:51 -0700398 const FileState& f = oldSnapshot.valueAt(n);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700399
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700400 int fd = open(g.file.string(), O_RDONLY);
Christopher Tate0032ce82009-06-04 17:01:06 -0700401 if (fd < 0) {
Joe Onoratod2110db2009-05-19 13:41:21 -0700402 // We can't open the file. Don't report it as a delete either. Let the
403 // server keep the old version. Maybe they'll be able to deal with it
404 // on restore.
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700405 LOGP("Unable to open file %s - skipping", g.file.string());
Joe Onoratod2110db2009-05-19 13:41:21 -0700406 } else {
Joe Onorato23ecae32009-06-10 17:07:15 -0700407 g.s.crc32 = compute_crc32(fd);
Joe Onoratod2110db2009-05-19 13:41:21 -0700408
Joe Onorato23ecae32009-06-10 17:07:15 -0700409 LOGP("%s", q.string());
Christopher Tate11b15772009-06-23 13:03:00 -0700410 LOGP(" new: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
411 f.modTime_sec, f.modTime_nsec, f.mode, f.size, f.crc32);
412 LOGP(" old: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
413 g.s.modTime_sec, g.s.modTime_nsec, g.s.mode, g.s.size, g.s.crc32);
Joe Onorato23ecae32009-06-10 17:07:15 -0700414 if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec
Christopher Tate11b15772009-06-23 13:03:00 -0700415 || f.mode != g.s.mode || f.size != g.s.size || f.crc32 != g.s.crc32) {
Christopher Tatefbb92382009-06-23 17:35:11 -0700416 write_update_file(dataStream, fd, g.s.mode, p, g.file.string());
Joe Onoratod2110db2009-05-19 13:41:21 -0700417 }
418
419 close(fd);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700420 }
421 n++;
422 m++;
423 }
424 }
425
426 // these were deleted
427 while (n<N) {
Joe Onoratod2110db2009-05-19 13:41:21 -0700428 dataStream->WriteEntityHeader(oldSnapshot.keyAt(n), -1);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700429 n++;
430 }
431
432 // these were added
433 while (m<fileCount) {
434 const String8& q = newSnapshot.keyAt(m);
Joe Onorato23ecae32009-06-10 17:07:15 -0700435 FileRec& g = newSnapshot.editValueAt(m);
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700436 write_update_file(dataStream, q, g.file.string());
Joe Onorato3ad977b2009-05-05 11:50:51 -0700437 m++;
438 }
439
440 err = write_snapshot_file(newSnapshotFD, newSnapshot);
441
442 return 0;
443}
444
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700445#define RESTORE_BUF_SIZE (8*1024)
446
447RestoreHelperBase::RestoreHelperBase()
448{
449 m_buf = malloc(RESTORE_BUF_SIZE);
Christopher Tate63bcb792009-06-24 13:57:29 -0700450 m_loggedUnknownMetadata = false;
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700451}
452
453RestoreHelperBase::~RestoreHelperBase()
454{
455 free(m_buf);
456}
457
458status_t
459RestoreHelperBase::WriteFile(const String8& filename, BackupDataReader* in)
460{
461 ssize_t err;
462 size_t dataSize;
463 String8 key;
464 int fd;
465 void* buf = m_buf;
466 ssize_t amt;
467 int mode;
468 int crc;
469 struct stat st;
470 FileRec r;
471
472 err = in->ReadEntityHeader(&key, &dataSize);
473 if (err != NO_ERROR) {
474 return err;
475 }
Joe Onorato5d605dc2009-06-18 18:23:43 -0700476
Christopher Tatefbb92382009-06-23 17:35:11 -0700477 // Get the metadata block off the head of the file entity and use that to
478 // set up the output file
479 file_metadata_v1 metadata;
480 amt = in->ReadEntityData(&metadata, sizeof(metadata));
481 if (amt != sizeof(metadata)) {
482 LOGW("Could not read metadata for %s -- %ld / %s", filename.string(),
483 (long)amt, strerror(errno));
484 return EIO;
485 }
486 metadata.version = fromlel(metadata.version);
487 metadata.mode = fromlel(metadata.mode);
488 if (metadata.version > CURRENT_METADATA_VERSION) {
Christopher Tate63bcb792009-06-24 13:57:29 -0700489 if (!m_loggedUnknownMetadata) {
490 m_loggedUnknownMetadata = true;
491 LOGW("Restoring file with unsupported metadata version %d (currently %d)",
492 metadata.version, CURRENT_METADATA_VERSION);
493 }
Christopher Tatefbb92382009-06-23 17:35:11 -0700494 }
495 mode = metadata.mode;
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700496
497 // Write the file and compute the crc
498 crc = crc32(0L, Z_NULL, 0);
Joe Onorato5d605dc2009-06-18 18:23:43 -0700499 fd = open(filename.string(), O_CREAT|O_RDWR|O_TRUNC, mode);
500 if (fd == -1) {
501 LOGW("Could not open file %s -- %s", filename.string(), strerror(errno));
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700502 return errno;
503 }
504
505 while ((amt = in->ReadEntityData(buf, RESTORE_BUF_SIZE)) > 0) {
506 err = write(fd, buf, amt);
507 if (err != amt) {
508 close(fd);
Joe Onorato5d605dc2009-06-18 18:23:43 -0700509 LOGW("Error '%s' writing '%s'", strerror(errno), filename.string());
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700510 return errno;
511 }
512 crc = crc32(crc, (Bytef*)buf, amt);
513 }
514
515 close(fd);
516
517 // Record for the snapshot
518 err = stat(filename.string(), &st);
519 if (err != 0) {
520 LOGW("Error stating file that we just created %s", filename.string());
521 return errno;
522 }
523
524 r.file = filename;
525 r.deleted = false;
526 r.s.modTime_sec = st.st_mtime;
527 r.s.modTime_nsec = 0; // workaround sim breakage
528 //r.s.modTime_nsec = st.st_mtime_nsec;
Christopher Tate11b15772009-06-23 13:03:00 -0700529 r.s.mode = st.st_mode;
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700530 r.s.size = st.st_size;
531 r.s.crc32 = crc;
532
533 m_files.add(key, r);
534
535 return NO_ERROR;
536}
537
538status_t
539RestoreHelperBase::WriteSnapshot(int fd)
540{
541 return write_snapshot_file(fd, m_files);;
542}
543
Joe Onorato3ad977b2009-05-05 11:50:51 -0700544#if TEST_BACKUP_HELPERS
545
546#define SCRATCH_DIR "/data/backup_helper_test/"
547
548static int
549write_text_file(const char* path, const char* data)
550{
551 int amt;
552 int fd;
553 int len;
554
555 fd = creat(path, 0666);
556 if (fd == -1) {
557 fprintf(stderr, "creat %s failed\n", path);
558 return errno;
559 }
560
561 len = strlen(data);
562 amt = write(fd, data, len);
563 if (amt != len) {
564 fprintf(stderr, "error (%s) writing to file %s\n", strerror(errno), path);
565 return errno;
566 }
567
568 close(fd);
569
570 return 0;
571}
572
573static int
574compare_file(const char* path, const unsigned char* data, int len)
575{
576 int fd;
577 int amt;
578
579 fd = open(path, O_RDONLY);
580 if (fd == -1) {
581 fprintf(stderr, "compare_file error (%s) opening %s\n", strerror(errno), path);
582 return errno;
583 }
584
585 unsigned char* contents = (unsigned char*)malloc(len);
586 if (contents == NULL) {
587 fprintf(stderr, "malloc(%d) failed\n", len);
588 return ENOMEM;
589 }
590
591 bool sizesMatch = true;
592 amt = lseek(fd, 0, SEEK_END);
593 if (amt != len) {
594 fprintf(stderr, "compare_file file length should be %d, was %d\n", len, amt);
595 sizesMatch = false;
596 }
597 lseek(fd, 0, SEEK_SET);
598
599 int readLen = amt < len ? amt : len;
600 amt = read(fd, contents, readLen);
601 if (amt != readLen) {
602 fprintf(stderr, "compare_file read expected %d bytes but got %d\n", len, amt);
603 }
604
605 bool contentsMatch = true;
606 for (int i=0; i<readLen; i++) {
607 if (data[i] != contents[i]) {
608 if (contentsMatch) {
609 fprintf(stderr, "compare_file contents are different: (index, expected, actual)\n");
610 contentsMatch = false;
611 }
612 fprintf(stderr, " [%-2d] %02x %02x\n", i, data[i], contents[i]);
613 }
614 }
615
Christopher Tate63bcb792009-06-24 13:57:29 -0700616 free(contents);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700617 return contentsMatch && sizesMatch ? 0 : 1;
618}
619
620int
621backup_helper_test_empty()
622{
623 int err;
624 int fd;
Joe Onorato23ecae32009-06-10 17:07:15 -0700625 KeyedVector<String8,FileRec> snapshot;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700626 const char* filename = SCRATCH_DIR "backup_helper_test_empty.snap";
627
628 system("rm -r " SCRATCH_DIR);
629 mkdir(SCRATCH_DIR, 0777);
630
631 // write
632 fd = creat(filename, 0666);
633 if (fd == -1) {
634 fprintf(stderr, "error creating %s\n", filename);
635 return 1;
636 }
637
638 err = write_snapshot_file(fd, snapshot);
639
640 close(fd);
641
642 if (err != 0) {
643 fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err));
644 return err;
645 }
646
647 static const unsigned char correct_data[] = {
648 0x53, 0x6e, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00,
649 0x46, 0x69, 0x6c, 0x65, 0x10, 0x00, 0x00, 0x00
650 };
651
652 err = compare_file(filename, correct_data, sizeof(correct_data));
653 if (err != 0) {
654 return err;
655 }
656
657 // read
658 fd = open(filename, O_RDONLY);
659 if (fd == -1) {
660 fprintf(stderr, "error opening for read %s\n", filename);
661 return 1;
662 }
663
664 KeyedVector<String8,FileState> readSnapshot;
665 err = read_snapshot_file(fd, &readSnapshot);
666 if (err != 0) {
667 fprintf(stderr, "read_snapshot_file failed %d\n", err);
668 return err;
669 }
670
671 if (readSnapshot.size() != 0) {
672 fprintf(stderr, "readSnapshot should be length 0\n");
673 return 1;
674 }
675
676 return 0;
677}
678
679int
680backup_helper_test_four()
681{
682 int err;
683 int fd;
Joe Onorato23ecae32009-06-10 17:07:15 -0700684 KeyedVector<String8,FileRec> snapshot;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700685 const char* filename = SCRATCH_DIR "backup_helper_test_four.snap";
686
687 system("rm -r " SCRATCH_DIR);
688 mkdir(SCRATCH_DIR, 0777);
689
690 // write
691 fd = creat(filename, 0666);
692 if (fd == -1) {
693 fprintf(stderr, "error opening %s\n", filename);
694 return 1;
695 }
696
697 String8 filenames[4];
698 FileState states[4];
Joe Onorato23ecae32009-06-10 17:07:15 -0700699 FileRec r;
Joe Onoratoce88cb12009-06-11 11:27:16 -0700700 r.deleted = false;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700701
702 states[0].modTime_sec = 0xfedcba98;
703 states[0].modTime_nsec = 0xdeadbeef;
Christopher Tate11b15772009-06-23 13:03:00 -0700704 states[0].mode = 0777; // decimal 511, hex 0x000001ff
Joe Onorato3ad977b2009-05-05 11:50:51 -0700705 states[0].size = 0xababbcbc;
706 states[0].crc32 = 0x12345678;
707 states[0].nameLen = -12;
Joe Onorato23ecae32009-06-10 17:07:15 -0700708 r.s = states[0];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700709 filenames[0] = String8("bytes_of_padding");
Joe Onorato23ecae32009-06-10 17:07:15 -0700710 snapshot.add(filenames[0], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700711
712 states[1].modTime_sec = 0x93400031;
713 states[1].modTime_nsec = 0xdeadbeef;
Christopher Tate11b15772009-06-23 13:03:00 -0700714 states[1].mode = 0666; // decimal 438, hex 0x000001b6
Joe Onorato3ad977b2009-05-05 11:50:51 -0700715 states[1].size = 0x88557766;
716 states[1].crc32 = 0x22334422;
717 states[1].nameLen = -1;
Joe Onorato23ecae32009-06-10 17:07:15 -0700718 r.s = states[1];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700719 filenames[1] = String8("bytes_of_padding3");
Joe Onorato23ecae32009-06-10 17:07:15 -0700720 snapshot.add(filenames[1], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700721
722 states[2].modTime_sec = 0x33221144;
723 states[2].modTime_nsec = 0xdeadbeef;
Christopher Tate11b15772009-06-23 13:03:00 -0700724 states[2].mode = 0744; // decimal 484, hex 0x000001e4
Joe Onorato3ad977b2009-05-05 11:50:51 -0700725 states[2].size = 0x11223344;
726 states[2].crc32 = 0x01122334;
727 states[2].nameLen = 0;
Joe Onorato23ecae32009-06-10 17:07:15 -0700728 r.s = states[2];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700729 filenames[2] = String8("bytes_of_padding_2");
Joe Onorato23ecae32009-06-10 17:07:15 -0700730 snapshot.add(filenames[2], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700731
732 states[3].modTime_sec = 0x33221144;
733 states[3].modTime_nsec = 0xdeadbeef;
Christopher Tate11b15772009-06-23 13:03:00 -0700734 states[3].mode = 0755; // decimal 493, hex 0x000001ed
Joe Onorato3ad977b2009-05-05 11:50:51 -0700735 states[3].size = 0x11223344;
736 states[3].crc32 = 0x01122334;
737 states[3].nameLen = 0;
Joe Onorato23ecae32009-06-10 17:07:15 -0700738 r.s = states[3];
Joe Onorato3ad977b2009-05-05 11:50:51 -0700739 filenames[3] = String8("bytes_of_padding__1");
Joe Onorato23ecae32009-06-10 17:07:15 -0700740 snapshot.add(filenames[3], r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700741
742 err = write_snapshot_file(fd, snapshot);
743
744 close(fd);
745
746 if (err != 0) {
747 fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err));
748 return err;
749 }
750
751 static const unsigned char correct_data[] = {
752 // header
753 0x53, 0x6e, 0x61, 0x70, 0x04, 0x00, 0x00, 0x00,
Christopher Tate11b15772009-06-23 13:03:00 -0700754 0x46, 0x69, 0x6c, 0x65, 0xbc, 0x00, 0x00, 0x00,
Joe Onorato3ad977b2009-05-05 11:50:51 -0700755
756 // bytes_of_padding
757 0x98, 0xba, 0xdc, 0xfe, 0xef, 0xbe, 0xad, 0xde,
Christopher Tate11b15772009-06-23 13:03:00 -0700758 0xff, 0x01, 0x00, 0x00, 0xbc, 0xbc, 0xab, 0xab,
759 0x78, 0x56, 0x34, 0x12, 0x10, 0x00, 0x00, 0x00,
760 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6f, 0x66,
761 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
Joe Onorato3ad977b2009-05-05 11:50:51 -0700762
763 // bytes_of_padding3
764 0x31, 0x00, 0x40, 0x93, 0xef, 0xbe, 0xad, 0xde,
Christopher Tate11b15772009-06-23 13:03:00 -0700765 0xb6, 0x01, 0x00, 0x00, 0x66, 0x77, 0x55, 0x88,
766 0x22, 0x44, 0x33, 0x22, 0x11, 0x00, 0x00, 0x00,
767 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6f, 0x66,
768 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
769 0x33, 0xab, 0xab, 0xab,
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700770
Joe Onorato3ad977b2009-05-05 11:50:51 -0700771 // bytes of padding2
772 0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde,
Christopher Tate11b15772009-06-23 13:03:00 -0700773 0xe4, 0x01, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11,
774 0x34, 0x23, 0x12, 0x01, 0x12, 0x00, 0x00, 0x00,
775 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6f, 0x66,
776 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
777 0x5f, 0x32, 0xab, 0xab,
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700778
Joe Onorato3ad977b2009-05-05 11:50:51 -0700779 // bytes of padding3
780 0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde,
Christopher Tate11b15772009-06-23 13:03:00 -0700781 0xed, 0x01, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11,
782 0x34, 0x23, 0x12, 0x01, 0x13, 0x00, 0x00, 0x00,
783 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6f, 0x66,
784 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
785 0x5f, 0x5f, 0x31, 0xab
Joe Onorato3ad977b2009-05-05 11:50:51 -0700786 };
787
788 err = compare_file(filename, correct_data, sizeof(correct_data));
789 if (err != 0) {
790 return err;
791 }
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700792
Joe Onorato3ad977b2009-05-05 11:50:51 -0700793 // read
794 fd = open(filename, O_RDONLY);
795 if (fd == -1) {
796 fprintf(stderr, "error opening for read %s\n", filename);
797 return 1;
798 }
799
800
801 KeyedVector<String8,FileState> readSnapshot;
802 err = read_snapshot_file(fd, &readSnapshot);
803 if (err != 0) {
804 fprintf(stderr, "read_snapshot_file failed %d\n", err);
805 return err;
806 }
807
808 if (readSnapshot.size() != 4) {
809 fprintf(stderr, "readSnapshot should be length 4 is %d\n", readSnapshot.size());
810 return 1;
811 }
812
813 bool matched = true;
814 for (size_t i=0; i<readSnapshot.size(); i++) {
815 const String8& name = readSnapshot.keyAt(i);
816 const FileState state = readSnapshot.valueAt(i);
817
818 if (name != filenames[i] || states[i].modTime_sec != state.modTime_sec
Christopher Tate11b15772009-06-23 13:03:00 -0700819 || states[i].modTime_nsec != state.modTime_nsec || states[i].mode != state.mode
Joe Onorato3ad977b2009-05-05 11:50:51 -0700820 || states[i].size != state.size || states[i].crc32 != states[i].crc32) {
Christopher Tate11b15772009-06-23 13:03:00 -0700821 fprintf(stderr, "state %d expected={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n"
822 " actual={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n", i,
823 states[i].modTime_sec, states[i].modTime_nsec, states[i].mode, states[i].size,
824 states[i].crc32, name.length(), filenames[i].string(),
825 state.modTime_sec, state.modTime_nsec, state.mode, state.size, state.crc32,
826 state.nameLen, name.string());
Joe Onorato3ad977b2009-05-05 11:50:51 -0700827 matched = false;
828 }
829 }
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700830
Joe Onorato3ad977b2009-05-05 11:50:51 -0700831 return matched ? 0 : 1;
832}
833
Joe Onorato4535e402009-05-15 09:07:06 -0400834// hexdump -v -e '" " 8/1 " 0x%02x," "\n"' data_writer.data
835const unsigned char DATA_GOLDEN_FILE[] = {
Joe Onorato2e1da322009-05-15 18:20:19 -0400836 0x44, 0x61, 0x74, 0x61, 0x0b, 0x00, 0x00, 0x00,
837 0x0c, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x5f, 0x70,
838 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00,
839 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69,
Joe Onorato5f15d152009-06-16 16:31:35 -0400840 0x6e, 0x67, 0x5f, 0x00, 0x44, 0x61, 0x74, 0x61,
841 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
Joe Onorato4535e402009-05-15 09:07:06 -0400842 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
843 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
Joe Onorato2e1da322009-05-15 18:20:19 -0400844 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
Joe Onorato5f15d152009-06-16 16:31:35 -0400845 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
Joe Onorato2e1da322009-05-15 18:20:19 -0400846 0x44, 0x61, 0x74, 0x61, 0x0d, 0x00, 0x00, 0x00,
847 0x0e, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
Joe Onorato4535e402009-05-15 09:07:06 -0400848 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
Joe Onorato2e1da322009-05-15 18:20:19 -0400849 0x5f, 0x00, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64,
850 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
Joe Onorato5f15d152009-06-16 16:31:35 -0400851 0x5f, 0x00, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61,
Joe Onorato4535e402009-05-15 09:07:06 -0400852 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
853 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
854 0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64,
Joe Onorato5f15d152009-06-16 16:31:35 -0400855 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00
856
Joe Onorato4535e402009-05-15 09:07:06 -0400857};
858const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE);
859
860static int
861test_write_header_and_entity(BackupDataWriter& writer, const char* str)
862{
863 int err;
864 String8 text(str);
865
Joe Onorato4535e402009-05-15 09:07:06 -0400866 err = writer.WriteEntityHeader(text, text.length()+1);
867 if (err != 0) {
868 fprintf(stderr, "WriteEntityHeader failed with %s\n", strerror(err));
869 return err;
870 }
871
872 err = writer.WriteEntityData(text.string(), text.length()+1);
873 if (err != 0) {
874 fprintf(stderr, "write failed for data '%s'\n", text.string());
875 return errno;
876 }
877
878 return err;
879}
880
881int
882backup_helper_test_data_writer()
883{
884 int err;
885 int fd;
886 const char* filename = SCRATCH_DIR "data_writer.data";
887
888 system("rm -r " SCRATCH_DIR);
889 mkdir(SCRATCH_DIR, 0777);
890 mkdir(SCRATCH_DIR "data", 0777);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700891
Joe Onorato4535e402009-05-15 09:07:06 -0400892 fd = creat(filename, 0666);
893 if (fd == -1) {
894 fprintf(stderr, "error creating: %s\n", strerror(errno));
895 return errno;
896 }
897
898 BackupDataWriter writer(fd);
899
900 err = 0;
901 err |= test_write_header_and_entity(writer, "no_padding_");
902 err |= test_write_header_and_entity(writer, "padded_to__3");
903 err |= test_write_header_and_entity(writer, "padded_to_2__");
904 err |= test_write_header_and_entity(writer, "padded_to1");
905
Joe Onorato4535e402009-05-15 09:07:06 -0400906 close(fd);
907
908 err = compare_file(filename, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
909 if (err != 0) {
910 return err;
911 }
912
913 return err;
914}
915
Joe Onorato2e1da322009-05-15 18:20:19 -0400916int
917test_read_header_and_entity(BackupDataReader& reader, const char* str)
918{
919 int err;
920 int bufSize = strlen(str)+1;
921 char* buf = (char*)malloc(bufSize);
922 String8 string;
923 int cookie = 0x11111111;
924 size_t actualSize;
Joe Onorato5f15d152009-06-16 16:31:35 -0400925 bool done;
926 int type;
Christopher Tate11b15772009-06-23 13:03:00 -0700927 ssize_t nRead;
Joe Onorato2e1da322009-05-15 18:20:19 -0400928
929 // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str);
930
Joe Onorato5f15d152009-06-16 16:31:35 -0400931 err = reader.ReadNextHeader(&done, &type);
932 if (done) {
933 fprintf(stderr, "should not be done yet\n");
934 goto finished;
935 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400936 if (err != 0) {
937 fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400938 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400939 }
Joe Onorato5f15d152009-06-16 16:31:35 -0400940 if (type != BACKUP_HEADER_ENTITY_V1) {
Joe Onorato2e1da322009-05-15 18:20:19 -0400941 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400942 fprintf(stderr, "type=0x%08x expected 0x%08x\n", type, BACKUP_HEADER_ENTITY_V1);
Joe Onorato2e1da322009-05-15 18:20:19 -0400943 }
944
945 err = reader.ReadEntityHeader(&string, &actualSize);
946 if (err != 0) {
947 fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400948 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400949 }
950 if (string != str) {
951 fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.string());
952 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400953 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400954 }
955 if ((int)actualSize != bufSize) {
956 fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize,
957 actualSize);
958 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400959 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400960 }
961
Christopher Tate11b15772009-06-23 13:03:00 -0700962 nRead = reader.ReadEntityData(buf, bufSize);
963 if (nRead < 0) {
964 err = reader.Status();
Joe Onorato2e1da322009-05-15 18:20:19 -0400965 fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400966 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400967 }
968
969 if (0 != memcmp(buf, str, bufSize)) {
970 fprintf(stderr, "ReadEntityData expected '%s' but got something starting with "
Joe Onorato5f15d152009-06-16 16:31:35 -0400971 "%02x %02x %02x %02x '%c%c%c%c'\n", str, buf[0], buf[1], buf[2], buf[3],
972 buf[0], buf[1], buf[2], buf[3]);
Joe Onorato2e1da322009-05-15 18:20:19 -0400973 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400974 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400975 }
976
977 // The next read will confirm whether it got the right amount of data.
978
Joe Onorato5f15d152009-06-16 16:31:35 -0400979finished:
Joe Onorato2e1da322009-05-15 18:20:19 -0400980 if (err != NO_ERROR) {
981 fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err));
982 }
Christopher Tate63bcb792009-06-24 13:57:29 -0700983 free(buf);
Joe Onorato2e1da322009-05-15 18:20:19 -0400984 return err;
985}
986
987int
988backup_helper_test_data_reader()
989{
990 int err;
991 int fd;
992 const char* filename = SCRATCH_DIR "data_reader.data";
993
994 system("rm -r " SCRATCH_DIR);
995 mkdir(SCRATCH_DIR, 0777);
996 mkdir(SCRATCH_DIR "data", 0777);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -0700997
Joe Onorato2e1da322009-05-15 18:20:19 -0400998 fd = creat(filename, 0666);
999 if (fd == -1) {
1000 fprintf(stderr, "error creating: %s\n", strerror(errno));
1001 return errno;
1002 }
1003
1004 err = write(fd, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
1005 if (err != DATA_GOLDEN_FILE_SIZE) {
1006 fprintf(stderr, "Error \"%s\" writing golden file %s\n", strerror(errno), filename);
1007 return errno;
1008 }
1009
1010 close(fd);
1011
1012 fd = open(filename, O_RDONLY);
1013 if (fd == -1) {
1014 fprintf(stderr, "Error \"%s\" opening golden file %s for read\n", strerror(errno),
1015 filename);
1016 return errno;
1017 }
1018
1019 {
1020 BackupDataReader reader(fd);
1021
1022 err = 0;
1023
1024 if (err == NO_ERROR) {
1025 err = test_read_header_and_entity(reader, "no_padding_");
1026 }
1027
1028 if (err == NO_ERROR) {
1029 err = test_read_header_and_entity(reader, "padded_to__3");
1030 }
1031
1032 if (err == NO_ERROR) {
1033 err = test_read_header_and_entity(reader, "padded_to_2__");
1034 }
1035
1036 if (err == NO_ERROR) {
1037 err = test_read_header_and_entity(reader, "padded_to1");
1038 }
Joe Onorato2e1da322009-05-15 18:20:19 -04001039 }
1040
1041 close(fd);
1042
1043 return err;
1044}
1045
Joe Onorato3ad977b2009-05-05 11:50:51 -07001046static int
1047get_mod_time(const char* filename, struct timeval times[2])
1048{
1049 int err;
1050 struct stat64 st;
1051 err = stat64(filename, &st);
1052 if (err != 0) {
1053 fprintf(stderr, "stat '%s' failed: %s\n", filename, strerror(errno));
1054 return errno;
1055 }
1056 times[0].tv_sec = st.st_atime;
Joe Onorato3ad977b2009-05-05 11:50:51 -07001057 times[1].tv_sec = st.st_mtime;
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001058
1059 // If st_atime is a macro then struct stat64 uses struct timespec
1060 // to store the access and modif time values and typically
1061 // st_*time_nsec is not defined. In glibc, this is controlled by
1062 // __USE_MISC.
1063#ifdef __USE_MISC
1064#if !defined(st_atime) || defined(st_atime_nsec)
1065#error "Check if this __USE_MISC conditional is still needed."
1066#endif
1067 times[0].tv_usec = st.st_atim.tv_nsec / 1000;
1068 times[1].tv_usec = st.st_mtim.tv_nsec / 1000;
1069#else
1070 times[0].tv_usec = st.st_atime_nsec / 1000;
Joe Onorato3ad977b2009-05-05 11:50:51 -07001071 times[1].tv_usec = st.st_mtime_nsec / 1000;
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001072#endif
1073
Joe Onorato3ad977b2009-05-05 11:50:51 -07001074 return 0;
1075}
1076
1077int
1078backup_helper_test_files()
1079{
1080 int err;
Joe Onorato3ad977b2009-05-05 11:50:51 -07001081 int oldSnapshotFD;
Joe Onorato4535e402009-05-15 09:07:06 -04001082 int dataStreamFD;
1083 int newSnapshotFD;
Joe Onorato3ad977b2009-05-05 11:50:51 -07001084
1085 system("rm -r " SCRATCH_DIR);
1086 mkdir(SCRATCH_DIR, 0777);
1087 mkdir(SCRATCH_DIR "data", 0777);
1088
1089 write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
1090 write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
1091 write_text_file(SCRATCH_DIR "data/d", "d\ndd\n");
1092 write_text_file(SCRATCH_DIR "data/e", "e\nee\n");
1093 write_text_file(SCRATCH_DIR "data/f", "f\nff\n");
1094 write_text_file(SCRATCH_DIR "data/h", "h\nhh\n");
1095
1096 char const* files_before[] = {
Joe Onorato23ecae32009-06-10 17:07:15 -07001097 SCRATCH_DIR "data/b",
1098 SCRATCH_DIR "data/c",
1099 SCRATCH_DIR "data/d",
1100 SCRATCH_DIR "data/e",
1101 SCRATCH_DIR "data/f"
1102 };
1103
1104 char const* keys_before[] = {
Joe Onorato3ad977b2009-05-05 11:50:51 -07001105 "data/b",
1106 "data/c",
1107 "data/d",
1108 "data/e",
1109 "data/f"
1110 };
1111
Joe Onorato4535e402009-05-15 09:07:06 -04001112 dataStreamFD = creat(SCRATCH_DIR "1.data", 0666);
1113 if (dataStreamFD == -1) {
1114 fprintf(stderr, "error creating: %s\n", strerror(errno));
1115 return errno;
1116 }
1117
Joe Onorato3ad977b2009-05-05 11:50:51 -07001118 newSnapshotFD = creat(SCRATCH_DIR "before.snap", 0666);
1119 if (newSnapshotFD == -1) {
1120 fprintf(stderr, "error creating: %s\n", strerror(errno));
1121 return errno;
1122 }
Joe Onoratod2110db2009-05-19 13:41:21 -07001123
1124 {
1125 BackupDataWriter dataStream(dataStreamFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001126
Joe Onorato23ecae32009-06-10 17:07:15 -07001127 err = back_up_files(-1, &dataStream, newSnapshotFD, files_before, keys_before, 5);
Joe Onoratod2110db2009-05-19 13:41:21 -07001128 if (err != 0) {
1129 return err;
1130 }
Joe Onorato3ad977b2009-05-05 11:50:51 -07001131 }
1132
Joe Onorato4535e402009-05-15 09:07:06 -04001133 close(dataStreamFD);
Joe Onorato3ad977b2009-05-05 11:50:51 -07001134 close(newSnapshotFD);
1135
1136 sleep(3);
1137
1138 struct timeval d_times[2];
1139 struct timeval e_times[2];
1140
1141 err = get_mod_time(SCRATCH_DIR "data/d", d_times);
1142 err |= get_mod_time(SCRATCH_DIR "data/e", e_times);
1143 if (err != 0) {
1144 return err;
1145 }
1146
1147 write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
1148 unlink(SCRATCH_DIR "data/c");
1149 write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
1150 write_text_file(SCRATCH_DIR "data/d", "dd\ndd\n");
1151 utimes(SCRATCH_DIR "data/d", d_times);
1152 write_text_file(SCRATCH_DIR "data/e", "z\nzz\n");
1153 utimes(SCRATCH_DIR "data/e", e_times);
1154 write_text_file(SCRATCH_DIR "data/g", "g\ngg\n");
1155 unlink(SCRATCH_DIR "data/f");
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001156
Joe Onorato3ad977b2009-05-05 11:50:51 -07001157 char const* files_after[] = {
Joe Onorato23ecae32009-06-10 17:07:15 -07001158 SCRATCH_DIR "data/a", // added
1159 SCRATCH_DIR "data/b", // same
1160 SCRATCH_DIR "data/c", // different mod time
1161 SCRATCH_DIR "data/d", // different size (same mod time)
1162 SCRATCH_DIR "data/e", // different contents (same mod time, same size)
1163 SCRATCH_DIR "data/g" // added
1164 };
1165
1166 char const* keys_after[] = {
Joe Onorato3ad977b2009-05-05 11:50:51 -07001167 "data/a", // added
1168 "data/b", // same
1169 "data/c", // different mod time
1170 "data/d", // different size (same mod time)
1171 "data/e", // different contents (same mod time, same size)
1172 "data/g" // added
1173 };
1174
1175 oldSnapshotFD = open(SCRATCH_DIR "before.snap", O_RDONLY);
1176 if (oldSnapshotFD == -1) {
1177 fprintf(stderr, "error opening: %s\n", strerror(errno));
1178 return errno;
1179 }
1180
Joe Onorato4535e402009-05-15 09:07:06 -04001181 dataStreamFD = creat(SCRATCH_DIR "2.data", 0666);
1182 if (dataStreamFD == -1) {
1183 fprintf(stderr, "error creating: %s\n", strerror(errno));
1184 return errno;
1185 }
1186
Joe Onorato3ad977b2009-05-05 11:50:51 -07001187 newSnapshotFD = creat(SCRATCH_DIR "after.snap", 0666);
1188 if (newSnapshotFD == -1) {
1189 fprintf(stderr, "error creating: %s\n", strerror(errno));
1190 return errno;
1191 }
1192
Joe Onoratod2110db2009-05-19 13:41:21 -07001193 {
1194 BackupDataWriter dataStream(dataStreamFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001195
Joe Onorato23ecae32009-06-10 17:07:15 -07001196 err = back_up_files(oldSnapshotFD, &dataStream, newSnapshotFD, files_after, keys_after, 6);
Joe Onoratod2110db2009-05-19 13:41:21 -07001197 if (err != 0) {
1198 return err;
1199 }
1200}
Joe Onorato3ad977b2009-05-05 11:50:51 -07001201
1202 close(oldSnapshotFD);
Joe Onorato4535e402009-05-15 09:07:06 -04001203 close(dataStreamFD);
Joe Onorato3ad977b2009-05-05 11:50:51 -07001204 close(newSnapshotFD);
Nicolas Cataniaf4c46b92009-05-22 13:41:38 -07001205
Joe Onorato3ad977b2009-05-05 11:50:51 -07001206 return 0;
1207}
1208
Joe Onorato23ecae32009-06-10 17:07:15 -07001209int
1210backup_helper_test_null_base()
1211{
1212 int err;
1213 int oldSnapshotFD;
1214 int dataStreamFD;
1215 int newSnapshotFD;
1216
1217 system("rm -r " SCRATCH_DIR);
1218 mkdir(SCRATCH_DIR, 0777);
1219 mkdir(SCRATCH_DIR "data", 0777);
1220
1221 write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
1222
1223 char const* files[] = {
1224 SCRATCH_DIR "data/a",
1225 };
1226
1227 char const* keys[] = {
1228 "a",
1229 };
1230
1231 dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
1232 if (dataStreamFD == -1) {
1233 fprintf(stderr, "error creating: %s\n", strerror(errno));
1234 return errno;
1235 }
1236
1237 newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
1238 if (newSnapshotFD == -1) {
1239 fprintf(stderr, "error creating: %s\n", strerror(errno));
1240 return errno;
1241 }
1242
1243 {
1244 BackupDataWriter dataStream(dataStreamFD);
1245
1246 err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
1247 if (err != 0) {
1248 return err;
1249 }
1250 }
1251
1252 close(dataStreamFD);
1253 close(newSnapshotFD);
1254
1255 return 0;
1256}
1257
Joe Onoratoce88cb12009-06-11 11:27:16 -07001258int
1259backup_helper_test_missing_file()
1260{
1261 int err;
1262 int oldSnapshotFD;
1263 int dataStreamFD;
1264 int newSnapshotFD;
1265
1266 system("rm -r " SCRATCH_DIR);
1267 mkdir(SCRATCH_DIR, 0777);
1268 mkdir(SCRATCH_DIR "data", 0777);
1269
1270 write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
1271
1272 char const* files[] = {
1273 SCRATCH_DIR "data/a",
1274 SCRATCH_DIR "data/b",
1275 SCRATCH_DIR "data/c",
1276 };
1277
1278 char const* keys[] = {
1279 "a",
1280 "b",
1281 "c",
1282 };
1283
1284 dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
1285 if (dataStreamFD == -1) {
1286 fprintf(stderr, "error creating: %s\n", strerror(errno));
1287 return errno;
1288 }
1289
1290 newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
1291 if (newSnapshotFD == -1) {
1292 fprintf(stderr, "error creating: %s\n", strerror(errno));
1293 return errno;
1294 }
1295
1296 {
1297 BackupDataWriter dataStream(dataStreamFD);
1298
1299 err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
1300 if (err != 0) {
1301 return err;
1302 }
1303 }
1304
1305 close(dataStreamFD);
1306 close(newSnapshotFD);
1307
1308 return 0;
1309}
1310
Joe Onorato23ecae32009-06-10 17:07:15 -07001311
Joe Onorato3ad977b2009-05-05 11:50:51 -07001312#endif // TEST_BACKUP_HELPERS
Joe Onorato4535e402009-05-15 09:07:06 -04001313
1314}