blob: 3346614761928a42af6b3fc52f8a82e7356a1462 [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
71// auto-free buffer management object
72class StAutoFree {
73public:
74 StAutoFree(void* buffer) { mBuf = buffer; }
75 ~StAutoFree() { free(mBuf); }
76private:
77 void* mBuf;
78};
79
80#if 0 // TEST_BACKUP_HELPERS
Joe Onorato23ecae32009-06-10 17:07:15 -070081#define LOGP(f, x...) printf(f "\n", x)
Joe Onorato4535e402009-05-15 09:07:06 -040082#else
Joe Onorato290bb012009-05-13 18:57:29 -040083#define LOGP(x...) LOGD(x)
Joe Onorato4535e402009-05-15 09:07:06 -040084#endif
Joe Onorato290bb012009-05-13 18:57:29 -040085
Joe Onorato3ad977b2009-05-05 11:50:51 -070086const static int ROUND_UP[4] = { 0, 3, 2, 1 };
87
88static inline int
89round_up(int n)
90{
91 return n + ROUND_UP[n % 4];
92}
93
94static int
95read_snapshot_file(int fd, KeyedVector<String8,FileState>* snapshot)
96{
97 int bytesRead = 0;
98 int amt;
99 SnapshotHeader header;
100
101 amt = read(fd, &header, sizeof(header));
102 if (amt != sizeof(header)) {
103 return errno;
104 }
105 bytesRead += amt;
106
107 if (header.magic0 != MAGIC0 || header.magic1 != MAGIC1) {
108 LOGW("read_snapshot_file header.magic0=0x%08x magic1=0x%08x", header.magic0, header.magic1);
109 return 1;
110 }
111
112 for (int i=0; i<header.fileCount; i++) {
113 FileState file;
114 char filenameBuf[128];
115
Joe Onorato23ecae32009-06-10 17:07:15 -0700116 amt = read(fd, &file, sizeof(FileState));
117 if (amt != sizeof(FileState)) {
Joe Onorato3ad977b2009-05-05 11:50:51 -0700118 LOGW("read_snapshot_file FileState truncated/error with read at %d bytes\n", bytesRead);
119 return 1;
120 }
121 bytesRead += amt;
122
123 // filename is not NULL terminated, but it is padded
124 int nameBufSize = round_up(file.nameLen);
125 char* filename = nameBufSize <= (int)sizeof(filenameBuf)
126 ? filenameBuf
127 : (char*)malloc(nameBufSize);
128 amt = read(fd, filename, nameBufSize);
129 if (amt == nameBufSize) {
130 snapshot->add(String8(filename, file.nameLen), file);
131 }
132 bytesRead += amt;
133 if (filename != filenameBuf) {
134 free(filename);
135 }
136 if (amt != nameBufSize) {
137 LOGW("read_snapshot_file filename truncated/error with read at %d bytes\n", bytesRead);
138 return 1;
139 }
140 }
141
142 if (header.totalSize != bytesRead) {
143 LOGW("read_snapshot_file length mismatch: header.totalSize=%d bytesRead=%d\n",
144 header.totalSize, bytesRead);
145 return 1;
146 }
147
148 return 0;
149}
150
151static int
Joe Onorato23ecae32009-06-10 17:07:15 -0700152write_snapshot_file(int fd, const KeyedVector<String8,FileRec>& snapshot)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700153{
Joe Onoratoce88cb12009-06-11 11:27:16 -0700154 int fileCount = 0;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700155 int bytesWritten = sizeof(SnapshotHeader);
156 // preflight size
157 const int N = snapshot.size();
158 for (int i=0; i<N; i++) {
Joe Onoratoce88cb12009-06-11 11:27:16 -0700159 const FileRec& g = snapshot.valueAt(i);
160 if (!g.deleted) {
161 const String8& name = snapshot.keyAt(i);
162 bytesWritten += sizeof(FileState) + round_up(name.length());
163 fileCount++;
164 }
Joe Onorato3ad977b2009-05-05 11:50:51 -0700165 }
166
Joe Onorato4535e402009-05-15 09:07:06 -0400167 LOGP("write_snapshot_file fd=%d\n", fd);
168
Joe Onorato3ad977b2009-05-05 11:50:51 -0700169 int amt;
Joe Onoratoce88cb12009-06-11 11:27:16 -0700170 SnapshotHeader header = { MAGIC0, fileCount, MAGIC1, bytesWritten };
Joe Onorato3ad977b2009-05-05 11:50:51 -0700171
172 amt = write(fd, &header, sizeof(header));
173 if (amt != sizeof(header)) {
174 LOGW("write_snapshot_file error writing header %s", strerror(errno));
175 return errno;
176 }
177
Joe Onoratoce88cb12009-06-11 11:27:16 -0700178 for (int i=0; i<N; i++) {
Joe Onorato23ecae32009-06-10 17:07:15 -0700179 FileRec r = snapshot.valueAt(i);
Joe Onoratoce88cb12009-06-11 11:27:16 -0700180 if (!r.deleted) {
181 const String8& name = snapshot.keyAt(i);
182 int nameLen = r.s.nameLen = name.length();
Joe Onorato3ad977b2009-05-05 11:50:51 -0700183
Joe Onoratoce88cb12009-06-11 11:27:16 -0700184 amt = write(fd, &r.s, sizeof(FileState));
185 if (amt != sizeof(FileState)) {
186 LOGW("write_snapshot_file error writing header %s", strerror(errno));
Joe Onorato3ad977b2009-05-05 11:50:51 -0700187 return 1;
188 }
Joe Onoratoce88cb12009-06-11 11:27:16 -0700189
190 // filename is not NULL terminated, but it is padded
191 amt = write(fd, name.string(), nameLen);
192 if (amt != nameLen) {
193 LOGW("write_snapshot_file error writing filename %s", strerror(errno));
194 return 1;
195 }
196 int paddingLen = ROUND_UP[nameLen % 4];
197 if (paddingLen != 0) {
198 int padding = 0xabababab;
199 amt = write(fd, &padding, paddingLen);
200 if (amt != paddingLen) {
201 LOGW("write_snapshot_file error writing %d bytes of filename padding %s",
202 paddingLen, strerror(errno));
203 return 1;
204 }
205 }
Joe Onorato3ad977b2009-05-05 11:50:51 -0700206 }
207 }
208
209 return 0;
210}
211
212static int
Joe Onoratod2110db2009-05-19 13:41:21 -0700213write_delete_file(BackupDataWriter* dataStream, const String8& key)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700214{
Joe Onorato290bb012009-05-13 18:57:29 -0400215 LOGP("write_delete_file %s\n", key.string());
Joe Onoratod2110db2009-05-19 13:41:21 -0700216 return dataStream->WriteEntityHeader(key, -1);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700217}
218
219static int
Christopher Tatefbb92382009-06-23 17:35:11 -0700220write_update_file(BackupDataWriter* dataStream, int fd, int mode, const String8& key,
Joe Onorato23ecae32009-06-10 17:07:15 -0700221 char const* realFilename)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700222{
Christopher Tatefbb92382009-06-23 17:35:11 -0700223 LOGP("write_update_file %s (%s) : mode 0%o\n", realFilename, key.string(), mode);
Joe Onoratod2110db2009-05-19 13:41:21 -0700224
225 const int bufsize = 4*1024;
226 int err;
227 int amt;
228 int fileSize;
229 int bytesLeft;
Christopher Tatefbb92382009-06-23 17:35:11 -0700230 file_metadata_v1 metadata;
Joe Onoratod2110db2009-05-19 13:41:21 -0700231
232 char* buf = (char*)malloc(bufsize);
Christopher Tatefbb92382009-06-23 17:35:11 -0700233 StAutoFree _autoFree(buf);
234
Joe Onoratod2110db2009-05-19 13:41:21 -0700235 int crc = crc32(0L, Z_NULL, 0);
236
237
Christopher Tatefbb92382009-06-23 17:35:11 -0700238 fileSize = lseek(fd, 0, SEEK_END);
Joe Onoratod2110db2009-05-19 13:41:21 -0700239 lseek(fd, 0, SEEK_SET);
240
Christopher Tatefbb92382009-06-23 17:35:11 -0700241 if (sizeof(metadata) != 16) {
242 LOGE("ERROR: metadata block is the wrong size!");
243 }
244
245 bytesLeft = fileSize + sizeof(metadata);
Joe Onoratod2110db2009-05-19 13:41:21 -0700246 err = dataStream->WriteEntityHeader(key, bytesLeft);
247 if (err != 0) {
248 return err;
249 }
250
Christopher Tatefbb92382009-06-23 17:35:11 -0700251 // store the file metadata first
252 metadata.version = tolel(CURRENT_METADATA_VERSION);
253 metadata.mode = tolel(mode);
254 metadata.undefined_1 = metadata.undefined_2 = 0;
255 err = dataStream->WriteEntityData(&metadata, sizeof(metadata));
256 if (err != 0) {
257 return err;
258 }
259 bytesLeft -= sizeof(metadata); // bytesLeft should == fileSize now
260
261 // now store the file content
Joe Onoratod2110db2009-05-19 13:41:21 -0700262 while ((amt = read(fd, buf, bufsize)) != 0 && bytesLeft > 0) {
263 bytesLeft -= amt;
264 if (bytesLeft < 0) {
265 amt += bytesLeft; // Plus a negative is minus. Don't write more than we promised.
266 }
267 err = dataStream->WriteEntityData(buf, amt);
268 if (err != 0) {
269 return err;
270 }
271 }
272 if (bytesLeft != 0) {
273 if (bytesLeft > 0) {
274 // Pad out the space we promised in the buffer. We can't corrupt the buffer,
275 // even though the data we're sending is probably bad.
276 memset(buf, 0, bufsize);
277 while (bytesLeft > 0) {
278 amt = bytesLeft < bufsize ? bytesLeft : bufsize;
279 bytesLeft -= amt;
280 err = dataStream->WriteEntityData(buf, amt);
281 if (err != 0) {
282 return err;
283 }
284 }
285 }
286 LOGE("write_update_file size mismatch for %s. expected=%d actual=%d."
Joe Onorato23ecae32009-06-10 17:07:15 -0700287 " You aren't doing proper locking!", realFilename, fileSize, fileSize-bytesLeft);
Joe Onoratod2110db2009-05-19 13:41:21 -0700288 }
289
Joe Onoratod2110db2009-05-19 13:41:21 -0700290 return NO_ERROR;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700291}
292
293static int
Joe Onorato23ecae32009-06-10 17:07:15 -0700294write_update_file(BackupDataWriter* dataStream, const String8& key, char const* realFilename)
Joe Onoratod2110db2009-05-19 13:41:21 -0700295{
296 int err;
Christopher Tatefbb92382009-06-23 17:35:11 -0700297 struct stat st;
298
299 err = stat(realFilename, &st);
300 if (err < 0) {
301 return errno;
302 }
303
Joe Onorato23ecae32009-06-10 17:07:15 -0700304 int fd = open(realFilename, O_RDONLY);
Joe Onoratod2110db2009-05-19 13:41:21 -0700305 if (fd == -1) {
306 return errno;
307 }
Christopher Tatefbb92382009-06-23 17:35:11 -0700308
309 err = write_update_file(dataStream, fd, st.st_mode, key, realFilename);
Joe Onoratod2110db2009-05-19 13:41:21 -0700310 close(fd);
311 return err;
312}
313
314static int
315compute_crc32(int fd)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700316{
317 const int bufsize = 4*1024;
318 int amt;
319
Joe Onorato3ad977b2009-05-05 11:50:51 -0700320 char* buf = (char*)malloc(bufsize);
Christopher Tatefbb92382009-06-23 17:35:11 -0700321 StAutoFree _autoFree(buf);
322
Joe Onorato3ad977b2009-05-05 11:50:51 -0700323 int crc = crc32(0L, Z_NULL, 0);
324
Joe Onoratod2110db2009-05-19 13:41:21 -0700325 lseek(fd, 0, SEEK_SET);
326
Joe Onorato3ad977b2009-05-05 11:50:51 -0700327 while ((amt = read(fd, buf, bufsize)) != 0) {
328 crc = crc32(crc, (Bytef*)buf, amt);
329 }
330
Joe Onorato3ad977b2009-05-05 11:50:51 -0700331 return crc;
332}
333
334int
Joe Onoratod2110db2009-05-19 13:41:21 -0700335back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD,
Joe Onorato23ecae32009-06-10 17:07:15 -0700336 char const* const* files, char const* const* keys, int fileCount)
Joe Onorato3ad977b2009-05-05 11:50:51 -0700337{
338 int err;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700339 KeyedVector<String8,FileState> oldSnapshot;
Joe Onorato23ecae32009-06-10 17:07:15 -0700340 KeyedVector<String8,FileRec> newSnapshot;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700341
342 if (oldSnapshotFD != -1) {
343 err = read_snapshot_file(oldSnapshotFD, &oldSnapshot);
344 if (err != 0) {
345 // On an error, treat this as a full backup.
346 oldSnapshot.clear();
347 }
348 }
349
350 for (int i=0; i<fileCount; i++) {
Joe Onorato23ecae32009-06-10 17:07:15 -0700351 String8 key(keys[i]);
352 FileRec r;
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700353 char const* file = files[i];
354 r.file = file;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700355 struct stat st;
Joe Onorato3ad977b2009-05-05 11:50:51 -0700356
Joe Onorato23ecae32009-06-10 17:07:15 -0700357 err = stat(file, &st);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700358 if (err != 0) {
Joe Onorato23ecae32009-06-10 17:07:15 -0700359 LOGW("Error stating file %s", file);
Joe Onoratoce88cb12009-06-11 11:27:16 -0700360 r.deleted = true;
361 } else {
362 r.deleted = false;
363 r.s.modTime_sec = st.st_mtime;
364 r.s.modTime_nsec = 0; // workaround sim breakage
365 //r.s.modTime_nsec = st.st_mtime_nsec;
Christopher Tate11b15772009-06-23 13:03:00 -0700366 r.s.mode = st.st_mode;
Joe Onoratoce88cb12009-06-11 11:27:16 -0700367 r.s.size = st.st_size;
368 // we compute the crc32 later down below, when we already have the file open.
Joe Onorato3ad977b2009-05-05 11:50:51 -0700369
Joe Onoratoce88cb12009-06-11 11:27:16 -0700370 if (newSnapshot.indexOfKey(key) >= 0) {
371 LOGP("back_up_files key already in use '%s'", key.string());
372 return -1;
373 }
Joe Onorato23ecae32009-06-10 17:07:15 -0700374 }
375 newSnapshot.add(key, r);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700376 }
377
378 int n = 0;
379 int N = oldSnapshot.size();
380 int m = 0;
381
382 while (n<N && m<fileCount) {
383 const String8& p = oldSnapshot.keyAt(n);
384 const String8& q = newSnapshot.keyAt(m);
Joe Onoratoce88cb12009-06-11 11:27:16 -0700385 FileRec& g = newSnapshot.editValueAt(m);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700386 int cmp = p.compare(q);
Joe Onoratoce88cb12009-06-11 11:27:16 -0700387 if (g.deleted || cmp < 0) {
388 // file removed
389 LOGP("file removed: %s", p.string());
390 g.deleted = true; // They didn't mention the file, but we noticed that it's gone.
391 dataStream->WriteEntityHeader(p, -1);
392 n++;
393 }
394 else if (cmp > 0) {
Joe Onorato3ad977b2009-05-05 11:50:51 -0700395 // file added
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700396 LOGP("file added: %s", g.file.string());
397 write_update_file(dataStream, q, g.file.string());
Joe Onorato3ad977b2009-05-05 11:50:51 -0700398 m++;
399 }
Joe Onorato3ad977b2009-05-05 11:50:51 -0700400 else {
401 // both files exist, check them
Joe Onorato3ad977b2009-05-05 11:50:51 -0700402 const FileState& f = oldSnapshot.valueAt(n);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700403
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700404 int fd = open(g.file.string(), O_RDONLY);
Christopher Tate0032ce82009-06-04 17:01:06 -0700405 if (fd < 0) {
Joe Onoratod2110db2009-05-19 13:41:21 -0700406 // We can't open the file. Don't report it as a delete either. Let the
407 // server keep the old version. Maybe they'll be able to deal with it
408 // on restore.
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700409 LOGP("Unable to open file %s - skipping", g.file.string());
Joe Onoratod2110db2009-05-19 13:41:21 -0700410 } else {
Joe Onorato23ecae32009-06-10 17:07:15 -0700411 g.s.crc32 = compute_crc32(fd);
Joe Onoratod2110db2009-05-19 13:41:21 -0700412
Joe Onorato23ecae32009-06-10 17:07:15 -0700413 LOGP("%s", q.string());
Christopher Tate11b15772009-06-23 13:03:00 -0700414 LOGP(" new: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
415 f.modTime_sec, f.modTime_nsec, f.mode, f.size, f.crc32);
416 LOGP(" old: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
417 g.s.modTime_sec, g.s.modTime_nsec, g.s.mode, g.s.size, g.s.crc32);
Joe Onorato23ecae32009-06-10 17:07:15 -0700418 if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec
Christopher Tate11b15772009-06-23 13:03:00 -0700419 || f.mode != g.s.mode || f.size != g.s.size || f.crc32 != g.s.crc32) {
Christopher Tatefbb92382009-06-23 17:35:11 -0700420 write_update_file(dataStream, fd, g.s.mode, p, g.file.string());
Joe Onoratod2110db2009-05-19 13:41:21 -0700421 }
422
423 close(fd);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700424 }
425 n++;
426 m++;
427 }
428 }
429
430 // these were deleted
431 while (n<N) {
Joe Onoratod2110db2009-05-19 13:41:21 -0700432 dataStream->WriteEntityHeader(oldSnapshot.keyAt(n), -1);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700433 n++;
434 }
435
436 // these were added
437 while (m<fileCount) {
438 const String8& q = newSnapshot.keyAt(m);
Joe Onorato23ecae32009-06-10 17:07:15 -0700439 FileRec& g = newSnapshot.editValueAt(m);
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700440 write_update_file(dataStream, q, g.file.string());
Joe Onorato3ad977b2009-05-05 11:50:51 -0700441 m++;
442 }
443
444 err = write_snapshot_file(newSnapshotFD, newSnapshot);
445
446 return 0;
447}
448
Joe Onoratod2d9ceb2009-06-18 13:11:18 -0700449#define RESTORE_BUF_SIZE (8*1024)
450
451RestoreHelperBase::RestoreHelperBase()
452{
453 m_buf = malloc(RESTORE_BUF_SIZE);
454}
455
456RestoreHelperBase::~RestoreHelperBase()
457{
458 free(m_buf);
459}
460
461status_t
462RestoreHelperBase::WriteFile(const String8& filename, BackupDataReader* in)
463{
464 ssize_t err;
465 size_t dataSize;
466 String8 key;
467 int fd;
468 void* buf = m_buf;
469 ssize_t amt;
470 int mode;
471 int crc;
472 struct stat st;
473 FileRec r;
474
475 err = in->ReadEntityHeader(&key, &dataSize);
476 if (err != NO_ERROR) {
477 return err;
478 }
Joe Onorato5d605dc2009-06-18 18:23:43 -0700479
Christopher Tatefbb92382009-06-23 17:35:11 -0700480 // Get the metadata block off the head of the file entity and use that to
481 // set up the output file
482 file_metadata_v1 metadata;
483 amt = in->ReadEntityData(&metadata, sizeof(metadata));
484 if (amt != sizeof(metadata)) {
485 LOGW("Could not read metadata for %s -- %ld / %s", filename.string(),
486 (long)amt, strerror(errno));
487 return EIO;
488 }
489 metadata.version = fromlel(metadata.version);
490 metadata.mode = fromlel(metadata.mode);
491 if (metadata.version > CURRENT_METADATA_VERSION) {
492 LOGW("Restoring file with unsupported metadata version %d (currently %d)",
493 metadata.version, CURRENT_METADATA_VERSION);
494 }
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 }
Christopher Tatefbb92382009-06-23 17:35:11 -0700590 StAutoFree _autoFree(contents);
Joe Onorato3ad977b2009-05-05 11:50:51 -0700591
592 bool sizesMatch = true;
593 amt = lseek(fd, 0, SEEK_END);
594 if (amt != len) {
595 fprintf(stderr, "compare_file file length should be %d, was %d\n", len, amt);
596 sizesMatch = false;
597 }
598 lseek(fd, 0, SEEK_SET);
599
600 int readLen = amt < len ? amt : len;
601 amt = read(fd, contents, readLen);
602 if (amt != readLen) {
603 fprintf(stderr, "compare_file read expected %d bytes but got %d\n", len, amt);
604 }
605
606 bool contentsMatch = true;
607 for (int i=0; i<readLen; i++) {
608 if (data[i] != contents[i]) {
609 if (contentsMatch) {
610 fprintf(stderr, "compare_file contents are different: (index, expected, actual)\n");
611 contentsMatch = false;
612 }
613 fprintf(stderr, " [%-2d] %02x %02x\n", i, data[i], contents[i]);
614 }
615 }
616
617 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);
Christopher Tatefbb92382009-06-23 17:35:11 -0700922 StAutoFree _autoFree(buf);
Joe Onorato2e1da322009-05-15 18:20:19 -0400923 String8 string;
924 int cookie = 0x11111111;
925 size_t actualSize;
Joe Onorato5f15d152009-06-16 16:31:35 -0400926 bool done;
927 int type;
Christopher Tate11b15772009-06-23 13:03:00 -0700928 ssize_t nRead;
Joe Onorato2e1da322009-05-15 18:20:19 -0400929
930 // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str);
931
Joe Onorato5f15d152009-06-16 16:31:35 -0400932 err = reader.ReadNextHeader(&done, &type);
933 if (done) {
934 fprintf(stderr, "should not be done yet\n");
935 goto finished;
936 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400937 if (err != 0) {
938 fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400939 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400940 }
Joe Onorato5f15d152009-06-16 16:31:35 -0400941 if (type != BACKUP_HEADER_ENTITY_V1) {
Joe Onorato2e1da322009-05-15 18:20:19 -0400942 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400943 fprintf(stderr, "type=0x%08x expected 0x%08x\n", type, BACKUP_HEADER_ENTITY_V1);
Joe Onorato2e1da322009-05-15 18:20:19 -0400944 }
945
946 err = reader.ReadEntityHeader(&string, &actualSize);
947 if (err != 0) {
948 fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400949 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400950 }
951 if (string != str) {
952 fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.string());
953 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400954 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400955 }
956 if ((int)actualSize != bufSize) {
957 fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize,
958 actualSize);
959 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400960 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400961 }
962
Christopher Tate11b15772009-06-23 13:03:00 -0700963 nRead = reader.ReadEntityData(buf, bufSize);
964 if (nRead < 0) {
965 err = reader.Status();
Joe Onorato2e1da322009-05-15 18:20:19 -0400966 fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err));
Joe Onorato5f15d152009-06-16 16:31:35 -0400967 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400968 }
969
970 if (0 != memcmp(buf, str, bufSize)) {
971 fprintf(stderr, "ReadEntityData expected '%s' but got something starting with "
Joe Onorato5f15d152009-06-16 16:31:35 -0400972 "%02x %02x %02x %02x '%c%c%c%c'\n", str, buf[0], buf[1], buf[2], buf[3],
973 buf[0], buf[1], buf[2], buf[3]);
Joe Onorato2e1da322009-05-15 18:20:19 -0400974 err = EINVAL;
Joe Onorato5f15d152009-06-16 16:31:35 -0400975 goto finished;
Joe Onorato2e1da322009-05-15 18:20:19 -0400976 }
977
978 // The next read will confirm whether it got the right amount of data.
979
Joe Onorato5f15d152009-06-16 16:31:35 -0400980finished:
Joe Onorato2e1da322009-05-15 18:20:19 -0400981 if (err != NO_ERROR) {
982 fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err));
983 }
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}