1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2009 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker *
4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker *
8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker *
10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker */
16*d57664e9SAndroid Build Coastguard Worker
17*d57664e9SAndroid Build Coastguard Worker #define LOG_TAG "file_backup_helper"
18*d57664e9SAndroid Build Coastguard Worker
19*d57664e9SAndroid Build Coastguard Worker #include <androidfw/BackupHelpers.h>
20*d57664e9SAndroid Build Coastguard Worker
21*d57664e9SAndroid Build Coastguard Worker #include <errno.h>
22*d57664e9SAndroid Build Coastguard Worker #include <fcntl.h>
23*d57664e9SAndroid Build Coastguard Worker #include <stdio.h>
24*d57664e9SAndroid Build Coastguard Worker #include <stdlib.h>
25*d57664e9SAndroid Build Coastguard Worker #include <sys/stat.h>
26*d57664e9SAndroid Build Coastguard Worker #include <sys/types.h>
27*d57664e9SAndroid Build Coastguard Worker #include <sys/time.h> // for utimes
28*d57664e9SAndroid Build Coastguard Worker #include <sys/uio.h>
29*d57664e9SAndroid Build Coastguard Worker #include <unistd.h>
30*d57664e9SAndroid Build Coastguard Worker #include <utime.h>
31*d57664e9SAndroid Build Coastguard Worker #include <zlib.h>
32*d57664e9SAndroid Build Coastguard Worker
33*d57664e9SAndroid Build Coastguard Worker #include <androidfw/PathUtils.h>
34*d57664e9SAndroid Build Coastguard Worker #include <log/log.h>
35*d57664e9SAndroid Build Coastguard Worker #include <utils/ByteOrder.h>
36*d57664e9SAndroid Build Coastguard Worker #include <utils/KeyedVector.h>
37*d57664e9SAndroid Build Coastguard Worker #include <utils/String8.h>
38*d57664e9SAndroid Build Coastguard Worker
39*d57664e9SAndroid Build Coastguard Worker #include <com_android_server_backup.h>
40*d57664e9SAndroid Build Coastguard Worker namespace backup_flags = com::android::server::backup;
41*d57664e9SAndroid Build Coastguard Worker
42*d57664e9SAndroid Build Coastguard Worker namespace android {
43*d57664e9SAndroid Build Coastguard Worker
44*d57664e9SAndroid Build Coastguard Worker #define MAGIC0 0x70616e53 // Snap
45*d57664e9SAndroid Build Coastguard Worker #define MAGIC1 0x656c6946 // File
46*d57664e9SAndroid Build Coastguard Worker
47*d57664e9SAndroid Build Coastguard Worker /*
48*d57664e9SAndroid Build Coastguard Worker * File entity data format (v1):
49*d57664e9SAndroid Build Coastguard Worker *
50*d57664e9SAndroid Build Coastguard Worker * - 4-byte version number of the metadata, little endian (0x00000001 for v1)
51*d57664e9SAndroid Build Coastguard Worker * - 12 bytes of metadata
52*d57664e9SAndroid Build Coastguard Worker * - the file data itself
53*d57664e9SAndroid Build Coastguard Worker *
54*d57664e9SAndroid Build Coastguard Worker * i.e. a 16-byte metadata header followed by the raw file data. If the
55*d57664e9SAndroid Build Coastguard Worker * restore code does not recognize the metadata version, it can still
56*d57664e9SAndroid Build Coastguard Worker * interpret the file data itself correctly.
57*d57664e9SAndroid Build Coastguard Worker *
58*d57664e9SAndroid Build Coastguard Worker * file_metadata_v1:
59*d57664e9SAndroid Build Coastguard Worker *
60*d57664e9SAndroid Build Coastguard Worker * - 4 byte version number === 0x00000001 (little endian)
61*d57664e9SAndroid Build Coastguard Worker * - 4-byte access mode (little-endian)
62*d57664e9SAndroid Build Coastguard Worker * - undefined (8 bytes)
63*d57664e9SAndroid Build Coastguard Worker */
64*d57664e9SAndroid Build Coastguard Worker
65*d57664e9SAndroid Build Coastguard Worker struct file_metadata_v1 {
66*d57664e9SAndroid Build Coastguard Worker int version;
67*d57664e9SAndroid Build Coastguard Worker int mode;
68*d57664e9SAndroid Build Coastguard Worker int undefined_1;
69*d57664e9SAndroid Build Coastguard Worker int undefined_2;
70*d57664e9SAndroid Build Coastguard Worker };
71*d57664e9SAndroid Build Coastguard Worker
72*d57664e9SAndroid Build Coastguard Worker const static int CURRENT_METADATA_VERSION = 1;
73*d57664e9SAndroid Build Coastguard Worker
74*d57664e9SAndroid Build Coastguard Worker static const bool kIsDebug = false;
75*d57664e9SAndroid Build Coastguard Worker #if TEST_BACKUP_HELPERS
76*d57664e9SAndroid Build Coastguard Worker #define LOGP(f, x...) if (kIsDebug) printf(f "\n", x)
77*d57664e9SAndroid Build Coastguard Worker #else
78*d57664e9SAndroid Build Coastguard Worker #define LOGP(x...) if (kIsDebug) ALOGD(x)
79*d57664e9SAndroid Build Coastguard Worker #endif
80*d57664e9SAndroid Build Coastguard Worker
81*d57664e9SAndroid Build Coastguard Worker const static int ROUND_UP[4] = { 0, 3, 2, 1 };
82*d57664e9SAndroid Build Coastguard Worker
83*d57664e9SAndroid Build Coastguard Worker static inline int
round_up(int n)84*d57664e9SAndroid Build Coastguard Worker round_up(int n)
85*d57664e9SAndroid Build Coastguard Worker {
86*d57664e9SAndroid Build Coastguard Worker return n + ROUND_UP[n % 4];
87*d57664e9SAndroid Build Coastguard Worker }
88*d57664e9SAndroid Build Coastguard Worker
89*d57664e9SAndroid Build Coastguard Worker static int
read_snapshot_file(int fd,KeyedVector<String8,FileState> * snapshot)90*d57664e9SAndroid Build Coastguard Worker read_snapshot_file(int fd, KeyedVector<String8,FileState>* snapshot)
91*d57664e9SAndroid Build Coastguard Worker {
92*d57664e9SAndroid Build Coastguard Worker int bytesRead = 0;
93*d57664e9SAndroid Build Coastguard Worker int amt;
94*d57664e9SAndroid Build Coastguard Worker SnapshotHeader header;
95*d57664e9SAndroid Build Coastguard Worker
96*d57664e9SAndroid Build Coastguard Worker amt = read(fd, &header, sizeof(header));
97*d57664e9SAndroid Build Coastguard Worker if (amt != sizeof(header)) {
98*d57664e9SAndroid Build Coastguard Worker return errno;
99*d57664e9SAndroid Build Coastguard Worker }
100*d57664e9SAndroid Build Coastguard Worker bytesRead += amt;
101*d57664e9SAndroid Build Coastguard Worker
102*d57664e9SAndroid Build Coastguard Worker if (header.magic0 != MAGIC0 || header.magic1 != MAGIC1) {
103*d57664e9SAndroid Build Coastguard Worker ALOGW("read_snapshot_file header.magic0=0x%08x magic1=0x%08x", header.magic0, header.magic1);
104*d57664e9SAndroid Build Coastguard Worker return 1;
105*d57664e9SAndroid Build Coastguard Worker }
106*d57664e9SAndroid Build Coastguard Worker
107*d57664e9SAndroid Build Coastguard Worker for (int i=0; i<header.fileCount; i++) {
108*d57664e9SAndroid Build Coastguard Worker FileState file;
109*d57664e9SAndroid Build Coastguard Worker char filenameBuf[128];
110*d57664e9SAndroid Build Coastguard Worker
111*d57664e9SAndroid Build Coastguard Worker amt = read(fd, &file, sizeof(FileState));
112*d57664e9SAndroid Build Coastguard Worker if (amt != sizeof(FileState)) {
113*d57664e9SAndroid Build Coastguard Worker ALOGW("read_snapshot_file FileState truncated/error with read at %d bytes\n", bytesRead);
114*d57664e9SAndroid Build Coastguard Worker return 1;
115*d57664e9SAndroid Build Coastguard Worker }
116*d57664e9SAndroid Build Coastguard Worker bytesRead += amt;
117*d57664e9SAndroid Build Coastguard Worker
118*d57664e9SAndroid Build Coastguard Worker // filename is not NULL terminated, but it is padded
119*d57664e9SAndroid Build Coastguard Worker int nameBufSize = round_up(file.nameLen);
120*d57664e9SAndroid Build Coastguard Worker char* filename = nameBufSize <= (int)sizeof(filenameBuf)
121*d57664e9SAndroid Build Coastguard Worker ? filenameBuf
122*d57664e9SAndroid Build Coastguard Worker : (char*)malloc(nameBufSize);
123*d57664e9SAndroid Build Coastguard Worker amt = read(fd, filename, nameBufSize);
124*d57664e9SAndroid Build Coastguard Worker if (amt == nameBufSize) {
125*d57664e9SAndroid Build Coastguard Worker snapshot->add(String8(filename, file.nameLen), file);
126*d57664e9SAndroid Build Coastguard Worker }
127*d57664e9SAndroid Build Coastguard Worker bytesRead += amt;
128*d57664e9SAndroid Build Coastguard Worker if (filename != filenameBuf) {
129*d57664e9SAndroid Build Coastguard Worker free(filename);
130*d57664e9SAndroid Build Coastguard Worker }
131*d57664e9SAndroid Build Coastguard Worker if (amt != nameBufSize) {
132*d57664e9SAndroid Build Coastguard Worker ALOGW("read_snapshot_file filename truncated/error with read at %d bytes\n", bytesRead);
133*d57664e9SAndroid Build Coastguard Worker return 1;
134*d57664e9SAndroid Build Coastguard Worker }
135*d57664e9SAndroid Build Coastguard Worker }
136*d57664e9SAndroid Build Coastguard Worker
137*d57664e9SAndroid Build Coastguard Worker if (header.totalSize != bytesRead) {
138*d57664e9SAndroid Build Coastguard Worker ALOGW("read_snapshot_file length mismatch: header.totalSize=%d bytesRead=%d\n",
139*d57664e9SAndroid Build Coastguard Worker header.totalSize, bytesRead);
140*d57664e9SAndroid Build Coastguard Worker return 1;
141*d57664e9SAndroid Build Coastguard Worker }
142*d57664e9SAndroid Build Coastguard Worker
143*d57664e9SAndroid Build Coastguard Worker return 0;
144*d57664e9SAndroid Build Coastguard Worker }
145*d57664e9SAndroid Build Coastguard Worker
146*d57664e9SAndroid Build Coastguard Worker static int
write_snapshot_file(int fd,const KeyedVector<String8,FileRec> & snapshot)147*d57664e9SAndroid Build Coastguard Worker write_snapshot_file(int fd, const KeyedVector<String8,FileRec>& snapshot)
148*d57664e9SAndroid Build Coastguard Worker {
149*d57664e9SAndroid Build Coastguard Worker int fileCount = 0;
150*d57664e9SAndroid Build Coastguard Worker int bytesWritten = sizeof(SnapshotHeader);
151*d57664e9SAndroid Build Coastguard Worker // preflight size
152*d57664e9SAndroid Build Coastguard Worker const int N = snapshot.size();
153*d57664e9SAndroid Build Coastguard Worker for (int i=0; i<N; i++) {
154*d57664e9SAndroid Build Coastguard Worker const FileRec& g = snapshot.valueAt(i);
155*d57664e9SAndroid Build Coastguard Worker if (!g.deleted) {
156*d57664e9SAndroid Build Coastguard Worker const String8& name = snapshot.keyAt(i);
157*d57664e9SAndroid Build Coastguard Worker bytesWritten += sizeof(FileState) + round_up(name.length());
158*d57664e9SAndroid Build Coastguard Worker fileCount++;
159*d57664e9SAndroid Build Coastguard Worker }
160*d57664e9SAndroid Build Coastguard Worker }
161*d57664e9SAndroid Build Coastguard Worker
162*d57664e9SAndroid Build Coastguard Worker LOGP("write_snapshot_file fd=%d\n", fd);
163*d57664e9SAndroid Build Coastguard Worker
164*d57664e9SAndroid Build Coastguard Worker int amt;
165*d57664e9SAndroid Build Coastguard Worker SnapshotHeader header = { MAGIC0, fileCount, MAGIC1, bytesWritten };
166*d57664e9SAndroid Build Coastguard Worker
167*d57664e9SAndroid Build Coastguard Worker amt = write(fd, &header, sizeof(header));
168*d57664e9SAndroid Build Coastguard Worker if (amt != sizeof(header)) {
169*d57664e9SAndroid Build Coastguard Worker ALOGW("write_snapshot_file error writing header %s", strerror(errno));
170*d57664e9SAndroid Build Coastguard Worker return errno;
171*d57664e9SAndroid Build Coastguard Worker }
172*d57664e9SAndroid Build Coastguard Worker
173*d57664e9SAndroid Build Coastguard Worker for (int i=0; i<N; i++) {
174*d57664e9SAndroid Build Coastguard Worker FileRec r = snapshot.valueAt(i);
175*d57664e9SAndroid Build Coastguard Worker if (!r.deleted) {
176*d57664e9SAndroid Build Coastguard Worker const String8& name = snapshot.keyAt(i);
177*d57664e9SAndroid Build Coastguard Worker int nameLen = r.s.nameLen = name.length();
178*d57664e9SAndroid Build Coastguard Worker
179*d57664e9SAndroid Build Coastguard Worker amt = write(fd, &r.s, sizeof(FileState));
180*d57664e9SAndroid Build Coastguard Worker if (amt != sizeof(FileState)) {
181*d57664e9SAndroid Build Coastguard Worker ALOGW("write_snapshot_file error writing header %s", strerror(errno));
182*d57664e9SAndroid Build Coastguard Worker return 1;
183*d57664e9SAndroid Build Coastguard Worker }
184*d57664e9SAndroid Build Coastguard Worker
185*d57664e9SAndroid Build Coastguard Worker // filename is not NULL terminated, but it is padded
186*d57664e9SAndroid Build Coastguard Worker amt = write(fd, name.c_str(), nameLen);
187*d57664e9SAndroid Build Coastguard Worker if (amt != nameLen) {
188*d57664e9SAndroid Build Coastguard Worker ALOGW("write_snapshot_file error writing filename %s", strerror(errno));
189*d57664e9SAndroid Build Coastguard Worker return 1;
190*d57664e9SAndroid Build Coastguard Worker }
191*d57664e9SAndroid Build Coastguard Worker int paddingLen = ROUND_UP[nameLen % 4];
192*d57664e9SAndroid Build Coastguard Worker if (paddingLen != 0) {
193*d57664e9SAndroid Build Coastguard Worker int padding = 0xabababab;
194*d57664e9SAndroid Build Coastguard Worker amt = write(fd, &padding, paddingLen);
195*d57664e9SAndroid Build Coastguard Worker if (amt != paddingLen) {
196*d57664e9SAndroid Build Coastguard Worker ALOGW("write_snapshot_file error writing %d bytes of filename padding %s",
197*d57664e9SAndroid Build Coastguard Worker paddingLen, strerror(errno));
198*d57664e9SAndroid Build Coastguard Worker return 1;
199*d57664e9SAndroid Build Coastguard Worker }
200*d57664e9SAndroid Build Coastguard Worker }
201*d57664e9SAndroid Build Coastguard Worker }
202*d57664e9SAndroid Build Coastguard Worker }
203*d57664e9SAndroid Build Coastguard Worker
204*d57664e9SAndroid Build Coastguard Worker return 0;
205*d57664e9SAndroid Build Coastguard Worker }
206*d57664e9SAndroid Build Coastguard Worker
207*d57664e9SAndroid Build Coastguard Worker static int
write_delete_file(BackupDataWriter * dataStream,const String8 & key)208*d57664e9SAndroid Build Coastguard Worker write_delete_file(BackupDataWriter* dataStream, const String8& key)
209*d57664e9SAndroid Build Coastguard Worker {
210*d57664e9SAndroid Build Coastguard Worker LOGP("write_delete_file %s\n", key.c_str());
211*d57664e9SAndroid Build Coastguard Worker return dataStream->WriteEntityHeader(key, -1);
212*d57664e9SAndroid Build Coastguard Worker }
213*d57664e9SAndroid Build Coastguard Worker
214*d57664e9SAndroid Build Coastguard Worker static int
write_update_file(BackupDataWriter * dataStream,int fd,int mode,const String8 & key,char const * realFilename)215*d57664e9SAndroid Build Coastguard Worker write_update_file(BackupDataWriter* dataStream, int fd, int mode, const String8& key,
216*d57664e9SAndroid Build Coastguard Worker char const* realFilename)
217*d57664e9SAndroid Build Coastguard Worker {
218*d57664e9SAndroid Build Coastguard Worker LOGP("write_update_file %s (%s) : mode 0%o\n", realFilename, key.c_str(), mode);
219*d57664e9SAndroid Build Coastguard Worker
220*d57664e9SAndroid Build Coastguard Worker const int bufsize = backup_flags::enable_max_size_writes_to_pipes() ? (64*1024) : (4*1024);
221*d57664e9SAndroid Build Coastguard Worker int err;
222*d57664e9SAndroid Build Coastguard Worker int amt;
223*d57664e9SAndroid Build Coastguard Worker int fileSize;
224*d57664e9SAndroid Build Coastguard Worker int bytesLeft;
225*d57664e9SAndroid Build Coastguard Worker file_metadata_v1 metadata;
226*d57664e9SAndroid Build Coastguard Worker
227*d57664e9SAndroid Build Coastguard Worker char* buf = (char*)malloc(bufsize);
228*d57664e9SAndroid Build Coastguard Worker
229*d57664e9SAndroid Build Coastguard Worker fileSize = lseek(fd, 0, SEEK_END);
230*d57664e9SAndroid Build Coastguard Worker lseek(fd, 0, SEEK_SET);
231*d57664e9SAndroid Build Coastguard Worker
232*d57664e9SAndroid Build Coastguard Worker if (sizeof(metadata) != 16) {
233*d57664e9SAndroid Build Coastguard Worker ALOGE("ERROR: metadata block is the wrong size!");
234*d57664e9SAndroid Build Coastguard Worker }
235*d57664e9SAndroid Build Coastguard Worker
236*d57664e9SAndroid Build Coastguard Worker bytesLeft = fileSize + sizeof(metadata);
237*d57664e9SAndroid Build Coastguard Worker err = dataStream->WriteEntityHeader(key, bytesLeft);
238*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
239*d57664e9SAndroid Build Coastguard Worker free(buf);
240*d57664e9SAndroid Build Coastguard Worker return err;
241*d57664e9SAndroid Build Coastguard Worker }
242*d57664e9SAndroid Build Coastguard Worker
243*d57664e9SAndroid Build Coastguard Worker // store the file metadata first
244*d57664e9SAndroid Build Coastguard Worker metadata.version = tolel(CURRENT_METADATA_VERSION);
245*d57664e9SAndroid Build Coastguard Worker metadata.mode = tolel(mode);
246*d57664e9SAndroid Build Coastguard Worker metadata.undefined_1 = metadata.undefined_2 = 0;
247*d57664e9SAndroid Build Coastguard Worker err = dataStream->WriteEntityData(&metadata, sizeof(metadata));
248*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
249*d57664e9SAndroid Build Coastguard Worker free(buf);
250*d57664e9SAndroid Build Coastguard Worker return err;
251*d57664e9SAndroid Build Coastguard Worker }
252*d57664e9SAndroid Build Coastguard Worker bytesLeft -= sizeof(metadata); // bytesLeft should == fileSize now
253*d57664e9SAndroid Build Coastguard Worker
254*d57664e9SAndroid Build Coastguard Worker // now store the file content
255*d57664e9SAndroid Build Coastguard Worker while ((amt = read(fd, buf, bufsize)) != 0 && bytesLeft > 0) {
256*d57664e9SAndroid Build Coastguard Worker bytesLeft -= amt;
257*d57664e9SAndroid Build Coastguard Worker if (bytesLeft < 0) {
258*d57664e9SAndroid Build Coastguard Worker amt += bytesLeft; // Plus a negative is minus. Don't write more than we promised.
259*d57664e9SAndroid Build Coastguard Worker }
260*d57664e9SAndroid Build Coastguard Worker err = dataStream->WriteEntityData(buf, amt);
261*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
262*d57664e9SAndroid Build Coastguard Worker free(buf);
263*d57664e9SAndroid Build Coastguard Worker return err;
264*d57664e9SAndroid Build Coastguard Worker }
265*d57664e9SAndroid Build Coastguard Worker }
266*d57664e9SAndroid Build Coastguard Worker if (bytesLeft != 0) {
267*d57664e9SAndroid Build Coastguard Worker if (bytesLeft > 0) {
268*d57664e9SAndroid Build Coastguard Worker // Pad out the space we promised in the buffer. We can't corrupt the buffer,
269*d57664e9SAndroid Build Coastguard Worker // even though the data we're sending is probably bad.
270*d57664e9SAndroid Build Coastguard Worker memset(buf, 0, bufsize);
271*d57664e9SAndroid Build Coastguard Worker while (bytesLeft > 0) {
272*d57664e9SAndroid Build Coastguard Worker amt = bytesLeft < bufsize ? bytesLeft : bufsize;
273*d57664e9SAndroid Build Coastguard Worker bytesLeft -= amt;
274*d57664e9SAndroid Build Coastguard Worker err = dataStream->WriteEntityData(buf, amt);
275*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
276*d57664e9SAndroid Build Coastguard Worker free(buf);
277*d57664e9SAndroid Build Coastguard Worker return err;
278*d57664e9SAndroid Build Coastguard Worker }
279*d57664e9SAndroid Build Coastguard Worker }
280*d57664e9SAndroid Build Coastguard Worker }
281*d57664e9SAndroid Build Coastguard Worker ALOGE("write_update_file size mismatch for %s. expected=%d actual=%d."
282*d57664e9SAndroid Build Coastguard Worker " You aren't doing proper locking!", realFilename, fileSize, fileSize-bytesLeft);
283*d57664e9SAndroid Build Coastguard Worker }
284*d57664e9SAndroid Build Coastguard Worker
285*d57664e9SAndroid Build Coastguard Worker free(buf);
286*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
287*d57664e9SAndroid Build Coastguard Worker }
288*d57664e9SAndroid Build Coastguard Worker
289*d57664e9SAndroid Build Coastguard Worker static int
write_update_file(BackupDataWriter * dataStream,const String8 & key,char const * realFilename)290*d57664e9SAndroid Build Coastguard Worker write_update_file(BackupDataWriter* dataStream, const String8& key, char const* realFilename)
291*d57664e9SAndroid Build Coastguard Worker {
292*d57664e9SAndroid Build Coastguard Worker int err;
293*d57664e9SAndroid Build Coastguard Worker struct stat st;
294*d57664e9SAndroid Build Coastguard Worker
295*d57664e9SAndroid Build Coastguard Worker err = stat(realFilename, &st);
296*d57664e9SAndroid Build Coastguard Worker if (err < 0) {
297*d57664e9SAndroid Build Coastguard Worker return errno;
298*d57664e9SAndroid Build Coastguard Worker }
299*d57664e9SAndroid Build Coastguard Worker
300*d57664e9SAndroid Build Coastguard Worker int fd = open(realFilename, O_RDONLY);
301*d57664e9SAndroid Build Coastguard Worker if (fd == -1) {
302*d57664e9SAndroid Build Coastguard Worker return errno;
303*d57664e9SAndroid Build Coastguard Worker }
304*d57664e9SAndroid Build Coastguard Worker
305*d57664e9SAndroid Build Coastguard Worker err = write_update_file(dataStream, fd, st.st_mode, key, realFilename);
306*d57664e9SAndroid Build Coastguard Worker close(fd);
307*d57664e9SAndroid Build Coastguard Worker return err;
308*d57664e9SAndroid Build Coastguard Worker }
309*d57664e9SAndroid Build Coastguard Worker
310*d57664e9SAndroid Build Coastguard Worker static int
compute_crc32(const char * file,FileRec * out)311*d57664e9SAndroid Build Coastguard Worker compute_crc32(const char* file, FileRec* out) {
312*d57664e9SAndroid Build Coastguard Worker int fd = open(file, O_RDONLY);
313*d57664e9SAndroid Build Coastguard Worker if (fd < 0) {
314*d57664e9SAndroid Build Coastguard Worker return -1;
315*d57664e9SAndroid Build Coastguard Worker }
316*d57664e9SAndroid Build Coastguard Worker
317*d57664e9SAndroid Build Coastguard Worker const int bufsize = 4*1024;
318*d57664e9SAndroid Build Coastguard Worker int amt;
319*d57664e9SAndroid Build Coastguard Worker
320*d57664e9SAndroid Build Coastguard Worker char* buf = (char*)malloc(bufsize);
321*d57664e9SAndroid Build Coastguard Worker int crc = crc32(0L, Z_NULL, 0);
322*d57664e9SAndroid Build Coastguard Worker
323*d57664e9SAndroid Build Coastguard Worker lseek(fd, 0, SEEK_SET);
324*d57664e9SAndroid Build Coastguard Worker
325*d57664e9SAndroid Build Coastguard Worker while ((amt = read(fd, buf, bufsize)) != 0) {
326*d57664e9SAndroid Build Coastguard Worker crc = crc32(crc, (Bytef*)buf, amt);
327*d57664e9SAndroid Build Coastguard Worker }
328*d57664e9SAndroid Build Coastguard Worker
329*d57664e9SAndroid Build Coastguard Worker close(fd);
330*d57664e9SAndroid Build Coastguard Worker free(buf);
331*d57664e9SAndroid Build Coastguard Worker
332*d57664e9SAndroid Build Coastguard Worker out->s.crc32 = crc;
333*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
334*d57664e9SAndroid Build Coastguard Worker }
335*d57664e9SAndroid Build Coastguard Worker
336*d57664e9SAndroid Build Coastguard Worker int
back_up_files(int oldSnapshotFD,BackupDataWriter * dataStream,int newSnapshotFD,char const * const * files,char const * const * keys,int fileCount)337*d57664e9SAndroid Build Coastguard Worker back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD,
338*d57664e9SAndroid Build Coastguard Worker char const* const* files, char const* const* keys, int fileCount)
339*d57664e9SAndroid Build Coastguard Worker {
340*d57664e9SAndroid Build Coastguard Worker int err;
341*d57664e9SAndroid Build Coastguard Worker KeyedVector<String8,FileState> oldSnapshot;
342*d57664e9SAndroid Build Coastguard Worker KeyedVector<String8,FileRec> newSnapshot;
343*d57664e9SAndroid Build Coastguard Worker
344*d57664e9SAndroid Build Coastguard Worker if (oldSnapshotFD != -1) {
345*d57664e9SAndroid Build Coastguard Worker err = read_snapshot_file(oldSnapshotFD, &oldSnapshot);
346*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
347*d57664e9SAndroid Build Coastguard Worker // On an error, treat this as a full backup.
348*d57664e9SAndroid Build Coastguard Worker oldSnapshot.clear();
349*d57664e9SAndroid Build Coastguard Worker }
350*d57664e9SAndroid Build Coastguard Worker }
351*d57664e9SAndroid Build Coastguard Worker
352*d57664e9SAndroid Build Coastguard Worker for (int i=0; i<fileCount; i++) {
353*d57664e9SAndroid Build Coastguard Worker String8 key(keys[i]);
354*d57664e9SAndroid Build Coastguard Worker FileRec r;
355*d57664e9SAndroid Build Coastguard Worker char const* file = files[i];
356*d57664e9SAndroid Build Coastguard Worker r.file = file;
357*d57664e9SAndroid Build Coastguard Worker struct stat st;
358*d57664e9SAndroid Build Coastguard Worker
359*d57664e9SAndroid Build Coastguard Worker err = stat(file, &st);
360*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
361*d57664e9SAndroid Build Coastguard Worker // not found => treat as deleted
362*d57664e9SAndroid Build Coastguard Worker continue;
363*d57664e9SAndroid Build Coastguard Worker } else {
364*d57664e9SAndroid Build Coastguard Worker r.deleted = false;
365*d57664e9SAndroid Build Coastguard Worker r.s.modTime_sec = st.st_mtime;
366*d57664e9SAndroid Build Coastguard Worker r.s.modTime_nsec = 0; // workaround sim breakage
367*d57664e9SAndroid Build Coastguard Worker //r.s.modTime_nsec = st.st_mtime_nsec;
368*d57664e9SAndroid Build Coastguard Worker r.s.mode = st.st_mode;
369*d57664e9SAndroid Build Coastguard Worker r.s.size = st.st_size;
370*d57664e9SAndroid Build Coastguard Worker
371*d57664e9SAndroid Build Coastguard Worker if (newSnapshot.indexOfKey(key) >= 0) {
372*d57664e9SAndroid Build Coastguard Worker LOGP("back_up_files key already in use '%s'", key.c_str());
373*d57664e9SAndroid Build Coastguard Worker return -1;
374*d57664e9SAndroid Build Coastguard Worker }
375*d57664e9SAndroid Build Coastguard Worker
376*d57664e9SAndroid Build Coastguard Worker // compute the CRC
377*d57664e9SAndroid Build Coastguard Worker if (compute_crc32(file, &r) != NO_ERROR) {
378*d57664e9SAndroid Build Coastguard Worker ALOGW("Unable to open file %s", file);
379*d57664e9SAndroid Build Coastguard Worker continue;
380*d57664e9SAndroid Build Coastguard Worker }
381*d57664e9SAndroid Build Coastguard Worker }
382*d57664e9SAndroid Build Coastguard Worker newSnapshot.add(key, r);
383*d57664e9SAndroid Build Coastguard Worker }
384*d57664e9SAndroid Build Coastguard Worker
385*d57664e9SAndroid Build Coastguard Worker int n = 0;
386*d57664e9SAndroid Build Coastguard Worker int N = oldSnapshot.size();
387*d57664e9SAndroid Build Coastguard Worker int m = 0;
388*d57664e9SAndroid Build Coastguard Worker int M = newSnapshot.size();
389*d57664e9SAndroid Build Coastguard Worker
390*d57664e9SAndroid Build Coastguard Worker while (n<N && m<M) {
391*d57664e9SAndroid Build Coastguard Worker const String8& p = oldSnapshot.keyAt(n);
392*d57664e9SAndroid Build Coastguard Worker const String8& q = newSnapshot.keyAt(m);
393*d57664e9SAndroid Build Coastguard Worker FileRec& g = newSnapshot.editValueAt(m);
394*d57664e9SAndroid Build Coastguard Worker int cmp = p.compare(q);
395*d57664e9SAndroid Build Coastguard Worker if (cmp < 0) {
396*d57664e9SAndroid Build Coastguard Worker // file present in oldSnapshot, but not present in newSnapshot
397*d57664e9SAndroid Build Coastguard Worker LOGP("file removed: %s", p.c_str());
398*d57664e9SAndroid Build Coastguard Worker write_delete_file(dataStream, p);
399*d57664e9SAndroid Build Coastguard Worker n++;
400*d57664e9SAndroid Build Coastguard Worker } else if (cmp > 0) {
401*d57664e9SAndroid Build Coastguard Worker // file added
402*d57664e9SAndroid Build Coastguard Worker LOGP("file added: %s crc=0x%08x", g.file.c_str(), g.s.crc32);
403*d57664e9SAndroid Build Coastguard Worker write_update_file(dataStream, q, g.file.c_str());
404*d57664e9SAndroid Build Coastguard Worker m++;
405*d57664e9SAndroid Build Coastguard Worker } else {
406*d57664e9SAndroid Build Coastguard Worker // same file exists in both old and new; check whether to update
407*d57664e9SAndroid Build Coastguard Worker const FileState& f = oldSnapshot.valueAt(n);
408*d57664e9SAndroid Build Coastguard Worker
409*d57664e9SAndroid Build Coastguard Worker LOGP("%s", q.c_str());
410*d57664e9SAndroid Build Coastguard Worker LOGP(" old: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
411*d57664e9SAndroid Build Coastguard Worker f.modTime_sec, f.modTime_nsec, f.mode, f.size, f.crc32);
412*d57664e9SAndroid Build Coastguard Worker LOGP(" new: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
413*d57664e9SAndroid Build Coastguard Worker g.s.modTime_sec, g.s.modTime_nsec, g.s.mode, g.s.size, g.s.crc32);
414*d57664e9SAndroid Build Coastguard Worker if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec
415*d57664e9SAndroid Build Coastguard Worker || f.mode != g.s.mode || f.size != g.s.size || f.crc32 != g.s.crc32) {
416*d57664e9SAndroid Build Coastguard Worker int fd = open(g.file.c_str(), O_RDONLY);
417*d57664e9SAndroid Build Coastguard Worker if (fd < 0) {
418*d57664e9SAndroid Build Coastguard Worker ALOGE("Unable to read file for backup: %s", g.file.c_str());
419*d57664e9SAndroid Build Coastguard Worker } else {
420*d57664e9SAndroid Build Coastguard Worker write_update_file(dataStream, fd, g.s.mode, p, g.file.c_str());
421*d57664e9SAndroid Build Coastguard Worker close(fd);
422*d57664e9SAndroid Build Coastguard Worker }
423*d57664e9SAndroid Build Coastguard Worker }
424*d57664e9SAndroid Build Coastguard Worker n++;
425*d57664e9SAndroid Build Coastguard Worker m++;
426*d57664e9SAndroid Build Coastguard Worker }
427*d57664e9SAndroid Build Coastguard Worker }
428*d57664e9SAndroid Build Coastguard Worker
429*d57664e9SAndroid Build Coastguard Worker // these were deleted
430*d57664e9SAndroid Build Coastguard Worker while (n<N) {
431*d57664e9SAndroid Build Coastguard Worker write_delete_file(dataStream, oldSnapshot.keyAt(n));
432*d57664e9SAndroid Build Coastguard Worker n++;
433*d57664e9SAndroid Build Coastguard Worker }
434*d57664e9SAndroid Build Coastguard Worker
435*d57664e9SAndroid Build Coastguard Worker // these were added
436*d57664e9SAndroid Build Coastguard Worker while (m<M) {
437*d57664e9SAndroid Build Coastguard Worker const String8& q = newSnapshot.keyAt(m);
438*d57664e9SAndroid Build Coastguard Worker FileRec& g = newSnapshot.editValueAt(m);
439*d57664e9SAndroid Build Coastguard Worker write_update_file(dataStream, q, g.file.c_str());
440*d57664e9SAndroid Build Coastguard Worker m++;
441*d57664e9SAndroid Build Coastguard Worker }
442*d57664e9SAndroid Build Coastguard Worker
443*d57664e9SAndroid Build Coastguard Worker err = write_snapshot_file(newSnapshotFD, newSnapshot);
444*d57664e9SAndroid Build Coastguard Worker
445*d57664e9SAndroid Build Coastguard Worker return 0;
446*d57664e9SAndroid Build Coastguard Worker }
447*d57664e9SAndroid Build Coastguard Worker
calc_tar_checksum(char * buf,size_t buf_size)448*d57664e9SAndroid Build Coastguard Worker static void calc_tar_checksum(char* buf, size_t buf_size) {
449*d57664e9SAndroid Build Coastguard Worker // [ 148 : 8 ] checksum -- to be calculated with this field as space chars
450*d57664e9SAndroid Build Coastguard Worker memset(buf + 148, ' ', 8);
451*d57664e9SAndroid Build Coastguard Worker
452*d57664e9SAndroid Build Coastguard Worker uint16_t sum = 0;
453*d57664e9SAndroid Build Coastguard Worker for (uint8_t* p = (uint8_t*) buf; p < ((uint8_t*)buf) + 512; p++) {
454*d57664e9SAndroid Build Coastguard Worker sum += *p;
455*d57664e9SAndroid Build Coastguard Worker }
456*d57664e9SAndroid Build Coastguard Worker
457*d57664e9SAndroid Build Coastguard Worker // Now write the real checksum value:
458*d57664e9SAndroid Build Coastguard Worker // [ 148 : 8 ] checksum: 6 octal digits [leading zeroes], NUL, SPC
459*d57664e9SAndroid Build Coastguard Worker snprintf(buf + 148, buf_size - 148, "%06o", sum); // the trailing space is
460*d57664e9SAndroid Build Coastguard Worker // already in place
461*d57664e9SAndroid Build Coastguard Worker }
462*d57664e9SAndroid Build Coastguard Worker
463*d57664e9SAndroid Build Coastguard Worker // Returns number of bytes written
write_pax_header_entry(char * buf,size_t buf_size,const char * key,const char * value)464*d57664e9SAndroid Build Coastguard Worker static int write_pax_header_entry(char* buf, size_t buf_size,
465*d57664e9SAndroid Build Coastguard Worker const char* key, const char* value) {
466*d57664e9SAndroid Build Coastguard Worker // start with the size of "1 key=value\n"
467*d57664e9SAndroid Build Coastguard Worker int len = strlen(key) + strlen(value) + 4;
468*d57664e9SAndroid Build Coastguard Worker if (len > 9) len++;
469*d57664e9SAndroid Build Coastguard Worker if (len > 99) len++;
470*d57664e9SAndroid Build Coastguard Worker if (len > 999) len++;
471*d57664e9SAndroid Build Coastguard Worker // since PATH_MAX is 4096 we don't expect to have to generate any single
472*d57664e9SAndroid Build Coastguard Worker // header entry longer than 9999 characters
473*d57664e9SAndroid Build Coastguard Worker
474*d57664e9SAndroid Build Coastguard Worker return snprintf(buf, buf_size, "%d %s=%s\n", len, key, value);
475*d57664e9SAndroid Build Coastguard Worker }
476*d57664e9SAndroid Build Coastguard Worker
477*d57664e9SAndroid Build Coastguard Worker // Wire format to the backup manager service is chunked: each chunk is prefixed by
478*d57664e9SAndroid Build Coastguard Worker // a 4-byte count of its size. A chunk size of zero (four zero bytes) indicates EOD.
send_tarfile_chunk(BackupDataWriter * writer,const char * buffer,size_t size)479*d57664e9SAndroid Build Coastguard Worker void send_tarfile_chunk(BackupDataWriter* writer, const char* buffer, size_t size) {
480*d57664e9SAndroid Build Coastguard Worker uint32_t chunk_size_no = htonl(size);
481*d57664e9SAndroid Build Coastguard Worker writer->WriteEntityData(&chunk_size_no, 4);
482*d57664e9SAndroid Build Coastguard Worker if (size != 0) writer->WriteEntityData(buffer, size);
483*d57664e9SAndroid Build Coastguard Worker }
484*d57664e9SAndroid Build Coastguard Worker
write_tarfile(const String8 & packageName,const String8 & domain,const String8 & rootpath,const String8 & filepath,off64_t * outSize,BackupDataWriter * writer)485*d57664e9SAndroid Build Coastguard Worker int write_tarfile(const String8& packageName, const String8& domain,
486*d57664e9SAndroid Build Coastguard Worker const String8& rootpath, const String8& filepath, off64_t* outSize,
487*d57664e9SAndroid Build Coastguard Worker BackupDataWriter* writer)
488*d57664e9SAndroid Build Coastguard Worker {
489*d57664e9SAndroid Build Coastguard Worker // In the output stream everything is stored relative to the root
490*d57664e9SAndroid Build Coastguard Worker const char* relstart = filepath.c_str() + rootpath.length();
491*d57664e9SAndroid Build Coastguard Worker if (*relstart == '/') relstart++; // won't be true when path == rootpath
492*d57664e9SAndroid Build Coastguard Worker String8 relpath(relstart);
493*d57664e9SAndroid Build Coastguard Worker
494*d57664e9SAndroid Build Coastguard Worker // If relpath is empty, it means this is the top of one of the standard named
495*d57664e9SAndroid Build Coastguard Worker // domain directories, so we should just skip it
496*d57664e9SAndroid Build Coastguard Worker if (relpath.length() == 0) {
497*d57664e9SAndroid Build Coastguard Worker *outSize = 0;
498*d57664e9SAndroid Build Coastguard Worker return 0;
499*d57664e9SAndroid Build Coastguard Worker }
500*d57664e9SAndroid Build Coastguard Worker
501*d57664e9SAndroid Build Coastguard Worker // Too long a name for the ustar format?
502*d57664e9SAndroid Build Coastguard Worker // "apps/" + packagename + '/' + domainpath < 155 chars
503*d57664e9SAndroid Build Coastguard Worker // relpath < 100 chars
504*d57664e9SAndroid Build Coastguard Worker bool needExtended = false;
505*d57664e9SAndroid Build Coastguard Worker if ((5 + packageName.length() + 1 + domain.length() >= 155) || (relpath.length() >= 100)) {
506*d57664e9SAndroid Build Coastguard Worker needExtended = true;
507*d57664e9SAndroid Build Coastguard Worker }
508*d57664e9SAndroid Build Coastguard Worker
509*d57664e9SAndroid Build Coastguard Worker // Non-7bit-clean path also means needing pax extended format
510*d57664e9SAndroid Build Coastguard Worker if (!needExtended) {
511*d57664e9SAndroid Build Coastguard Worker for (size_t i = 0; i < filepath.length(); i++) {
512*d57664e9SAndroid Build Coastguard Worker if ((filepath[i] & 0x80) != 0) {
513*d57664e9SAndroid Build Coastguard Worker needExtended = true;
514*d57664e9SAndroid Build Coastguard Worker break;
515*d57664e9SAndroid Build Coastguard Worker }
516*d57664e9SAndroid Build Coastguard Worker }
517*d57664e9SAndroid Build Coastguard Worker }
518*d57664e9SAndroid Build Coastguard Worker
519*d57664e9SAndroid Build Coastguard Worker int err = 0;
520*d57664e9SAndroid Build Coastguard Worker struct stat64 s;
521*d57664e9SAndroid Build Coastguard Worker if (lstat64(filepath.c_str(), &s) != 0) {
522*d57664e9SAndroid Build Coastguard Worker err = errno;
523*d57664e9SAndroid Build Coastguard Worker ALOGE("Error %d (%s) from lstat64(%s)", err, strerror(err), filepath.c_str());
524*d57664e9SAndroid Build Coastguard Worker return err;
525*d57664e9SAndroid Build Coastguard Worker }
526*d57664e9SAndroid Build Coastguard Worker
527*d57664e9SAndroid Build Coastguard Worker // very large files need a pax extended size header
528*d57664e9SAndroid Build Coastguard Worker if (s.st_size > 077777777777LL) {
529*d57664e9SAndroid Build Coastguard Worker needExtended = true;
530*d57664e9SAndroid Build Coastguard Worker }
531*d57664e9SAndroid Build Coastguard Worker
532*d57664e9SAndroid Build Coastguard Worker String8 fullname; // for pax later on
533*d57664e9SAndroid Build Coastguard Worker String8 prefix;
534*d57664e9SAndroid Build Coastguard Worker
535*d57664e9SAndroid Build Coastguard Worker const int isdir = S_ISDIR(s.st_mode);
536*d57664e9SAndroid Build Coastguard Worker if (isdir) s.st_size = 0; // directories get no actual data in the tar stream
537*d57664e9SAndroid Build Coastguard Worker
538*d57664e9SAndroid Build Coastguard Worker // Report the size, including a rough tar overhead estimation: 512 bytes for the
539*d57664e9SAndroid Build Coastguard Worker // overall tar file-block header, plus 2 blocks if using the pax extended format,
540*d57664e9SAndroid Build Coastguard Worker // plus the raw content size rounded up to a multiple of 512.
541*d57664e9SAndroid Build Coastguard Worker *outSize = 512 + (needExtended ? 1024 : 0) + 512*((s.st_size + 511)/512);
542*d57664e9SAndroid Build Coastguard Worker
543*d57664e9SAndroid Build Coastguard Worker // Measure case: we've returned the size; now return without moving data
544*d57664e9SAndroid Build Coastguard Worker if (!writer) return 0;
545*d57664e9SAndroid Build Coastguard Worker
546*d57664e9SAndroid Build Coastguard Worker // !!! TODO: use mmap when possible to avoid churning the buffer cache
547*d57664e9SAndroid Build Coastguard Worker // !!! TODO: this will break with symlinks; need to use readlink(2)
548*d57664e9SAndroid Build Coastguard Worker int fd = open(filepath.c_str(), O_RDONLY);
549*d57664e9SAndroid Build Coastguard Worker if (fd < 0) {
550*d57664e9SAndroid Build Coastguard Worker err = errno;
551*d57664e9SAndroid Build Coastguard Worker ALOGE("Error %d (%s) from open(%s)", err, strerror(err), filepath.c_str());
552*d57664e9SAndroid Build Coastguard Worker return err;
553*d57664e9SAndroid Build Coastguard Worker }
554*d57664e9SAndroid Build Coastguard Worker
555*d57664e9SAndroid Build Coastguard Worker // read/write up to this much at a time.
556*d57664e9SAndroid Build Coastguard Worker const size_t BUFSIZE = backup_flags::enable_max_size_writes_to_pipes() ? (64*1024) : (32*1024);
557*d57664e9SAndroid Build Coastguard Worker
558*d57664e9SAndroid Build Coastguard Worker char* buf = (char *)calloc(1,BUFSIZE);
559*d57664e9SAndroid Build Coastguard Worker const size_t PAXHEADER_OFFSET = 512;
560*d57664e9SAndroid Build Coastguard Worker const size_t PAXHEADER_SIZE = 512;
561*d57664e9SAndroid Build Coastguard Worker const size_t PAXDATA_SIZE = BUFSIZE - (PAXHEADER_SIZE + PAXHEADER_OFFSET);
562*d57664e9SAndroid Build Coastguard Worker char* const paxHeader = buf + PAXHEADER_OFFSET; // use a different chunk of
563*d57664e9SAndroid Build Coastguard Worker // it as separate scratch
564*d57664e9SAndroid Build Coastguard Worker char* const paxData = paxHeader + PAXHEADER_SIZE;
565*d57664e9SAndroid Build Coastguard Worker
566*d57664e9SAndroid Build Coastguard Worker if (buf == NULL) {
567*d57664e9SAndroid Build Coastguard Worker ALOGE("Out of mem allocating transfer buffer");
568*d57664e9SAndroid Build Coastguard Worker err = ENOMEM;
569*d57664e9SAndroid Build Coastguard Worker goto done;
570*d57664e9SAndroid Build Coastguard Worker }
571*d57664e9SAndroid Build Coastguard Worker
572*d57664e9SAndroid Build Coastguard Worker // Magic fields for the ustar file format
573*d57664e9SAndroid Build Coastguard Worker strcat(buf + 257, "ustar");
574*d57664e9SAndroid Build Coastguard Worker strcat(buf + 263, "00");
575*d57664e9SAndroid Build Coastguard Worker
576*d57664e9SAndroid Build Coastguard Worker // [ 265 : 32 ] user name, ignored on restore
577*d57664e9SAndroid Build Coastguard Worker // [ 297 : 32 ] group name, ignored on restore
578*d57664e9SAndroid Build Coastguard Worker
579*d57664e9SAndroid Build Coastguard Worker // [ 100 : 8 ] file mode
580*d57664e9SAndroid Build Coastguard Worker snprintf(buf + 100, 8, "%06o ", s.st_mode & ~S_IFMT);
581*d57664e9SAndroid Build Coastguard Worker
582*d57664e9SAndroid Build Coastguard Worker // [ 108 : 8 ] uid -- ignored in Android format; uids are remapped at restore time
583*d57664e9SAndroid Build Coastguard Worker // [ 116 : 8 ] gid -- ignored in Android format
584*d57664e9SAndroid Build Coastguard Worker snprintf(buf + 108, 8, "0%lo", (unsigned long)s.st_uid);
585*d57664e9SAndroid Build Coastguard Worker snprintf(buf + 116, 8, "0%lo", (unsigned long)s.st_gid);
586*d57664e9SAndroid Build Coastguard Worker
587*d57664e9SAndroid Build Coastguard Worker // [ 124 : 12 ] file size in bytes
588*d57664e9SAndroid Build Coastguard Worker snprintf(buf + 124, 12, "%011llo", (isdir) ? 0LL : s.st_size);
589*d57664e9SAndroid Build Coastguard Worker
590*d57664e9SAndroid Build Coastguard Worker // [ 136 : 12 ] last mod time as a UTC time_t
591*d57664e9SAndroid Build Coastguard Worker snprintf(buf + 136, 12, "%0lo", (unsigned long)s.st_mtime);
592*d57664e9SAndroid Build Coastguard Worker
593*d57664e9SAndroid Build Coastguard Worker // [ 156 : 1 ] link/file type
594*d57664e9SAndroid Build Coastguard Worker uint8_t type;
595*d57664e9SAndroid Build Coastguard Worker if (isdir) {
596*d57664e9SAndroid Build Coastguard Worker type = '5'; // tar magic: '5' == directory
597*d57664e9SAndroid Build Coastguard Worker } else if (S_ISREG(s.st_mode)) {
598*d57664e9SAndroid Build Coastguard Worker type = '0'; // tar magic: '0' == normal file
599*d57664e9SAndroid Build Coastguard Worker } else {
600*d57664e9SAndroid Build Coastguard Worker ALOGW("Error: unknown file mode 0%o [%s]", s.st_mode, filepath.c_str());
601*d57664e9SAndroid Build Coastguard Worker goto cleanup;
602*d57664e9SAndroid Build Coastguard Worker }
603*d57664e9SAndroid Build Coastguard Worker buf[156] = type;
604*d57664e9SAndroid Build Coastguard Worker
605*d57664e9SAndroid Build Coastguard Worker // [ 157 : 100 ] name of linked file [not implemented]
606*d57664e9SAndroid Build Coastguard Worker
607*d57664e9SAndroid Build Coastguard Worker {
608*d57664e9SAndroid Build Coastguard Worker // Prefix and main relative path. Path lengths have been preflighted.
609*d57664e9SAndroid Build Coastguard Worker if (packageName.length() > 0) {
610*d57664e9SAndroid Build Coastguard Worker prefix = "apps/";
611*d57664e9SAndroid Build Coastguard Worker prefix += packageName;
612*d57664e9SAndroid Build Coastguard Worker }
613*d57664e9SAndroid Build Coastguard Worker if (domain.length() > 0) {
614*d57664e9SAndroid Build Coastguard Worker appendPath(prefix, domain);
615*d57664e9SAndroid Build Coastguard Worker }
616*d57664e9SAndroid Build Coastguard Worker
617*d57664e9SAndroid Build Coastguard Worker // pax extended means we don't put in a prefix field, and put a different
618*d57664e9SAndroid Build Coastguard Worker // string in the basic name field. We can also construct the full path name
619*d57664e9SAndroid Build Coastguard Worker // out of the substrings we've now built.
620*d57664e9SAndroid Build Coastguard Worker fullname = prefix;
621*d57664e9SAndroid Build Coastguard Worker appendPath(fullname, relpath);
622*d57664e9SAndroid Build Coastguard Worker
623*d57664e9SAndroid Build Coastguard Worker // ustar:
624*d57664e9SAndroid Build Coastguard Worker // [ 0 : 100 ]; file name/path
625*d57664e9SAndroid Build Coastguard Worker // [ 345 : 155 ] filename path prefix
626*d57664e9SAndroid Build Coastguard Worker // We only use the prefix area if fullname won't fit in the path
627*d57664e9SAndroid Build Coastguard Worker if (fullname.length() > 100) {
628*d57664e9SAndroid Build Coastguard Worker strncpy(buf, relpath.c_str(), 100);
629*d57664e9SAndroid Build Coastguard Worker strncpy(buf + 345, prefix.c_str(), 155);
630*d57664e9SAndroid Build Coastguard Worker } else {
631*d57664e9SAndroid Build Coastguard Worker strncpy(buf, fullname.c_str(), 100);
632*d57664e9SAndroid Build Coastguard Worker }
633*d57664e9SAndroid Build Coastguard Worker }
634*d57664e9SAndroid Build Coastguard Worker
635*d57664e9SAndroid Build Coastguard Worker // [ 329 : 8 ] and [ 337 : 8 ] devmajor/devminor, not used
636*d57664e9SAndroid Build Coastguard Worker
637*d57664e9SAndroid Build Coastguard Worker ALOGI(" Name: %s", fullname.c_str());
638*d57664e9SAndroid Build Coastguard Worker
639*d57664e9SAndroid Build Coastguard Worker // If we're using a pax extended header, build & write that here; lengths are
640*d57664e9SAndroid Build Coastguard Worker // already preflighted
641*d57664e9SAndroid Build Coastguard Worker if (needExtended) {
642*d57664e9SAndroid Build Coastguard Worker char sizeStr[32]; // big enough for a 64-bit unsigned value in decimal
643*d57664e9SAndroid Build Coastguard Worker
644*d57664e9SAndroid Build Coastguard Worker // construct the pax extended header data block
645*d57664e9SAndroid Build Coastguard Worker memset(paxData, 0, PAXDATA_SIZE);
646*d57664e9SAndroid Build Coastguard Worker
647*d57664e9SAndroid Build Coastguard Worker // size header -- calc len in digits by actually rendering the number
648*d57664e9SAndroid Build Coastguard Worker // to a string - brute force but simple
649*d57664e9SAndroid Build Coastguard Worker int paxLen = 0;
650*d57664e9SAndroid Build Coastguard Worker snprintf(sizeStr, sizeof(sizeStr), "%lld", (long long)s.st_size);
651*d57664e9SAndroid Build Coastguard Worker paxLen += write_pax_header_entry(paxData, PAXDATA_SIZE, "size", sizeStr);
652*d57664e9SAndroid Build Coastguard Worker
653*d57664e9SAndroid Build Coastguard Worker // fullname was generated above with the ustar paths
654*d57664e9SAndroid Build Coastguard Worker paxLen += write_pax_header_entry(paxData + paxLen, PAXDATA_SIZE - paxLen,
655*d57664e9SAndroid Build Coastguard Worker "path", fullname.c_str());
656*d57664e9SAndroid Build Coastguard Worker
657*d57664e9SAndroid Build Coastguard Worker // Now we know how big the pax data is
658*d57664e9SAndroid Build Coastguard Worker
659*d57664e9SAndroid Build Coastguard Worker // Now build the pax *header* templated on the ustar header
660*d57664e9SAndroid Build Coastguard Worker memcpy(paxHeader, buf, 512);
661*d57664e9SAndroid Build Coastguard Worker
662*d57664e9SAndroid Build Coastguard Worker String8 leaf = getPathLeaf(fullname);
663*d57664e9SAndroid Build Coastguard Worker memset(paxHeader, 0, 100); // rewrite the name area
664*d57664e9SAndroid Build Coastguard Worker snprintf(paxHeader, 100, "PaxHeader/%s", leaf.c_str());
665*d57664e9SAndroid Build Coastguard Worker memset(paxHeader + 345, 0, 155); // rewrite the prefix area
666*d57664e9SAndroid Build Coastguard Worker strncpy(paxHeader + 345, prefix.c_str(), 155);
667*d57664e9SAndroid Build Coastguard Worker
668*d57664e9SAndroid Build Coastguard Worker paxHeader[156] = 'x'; // mark it as a pax extended header
669*d57664e9SAndroid Build Coastguard Worker
670*d57664e9SAndroid Build Coastguard Worker // [ 124 : 12 ] size of pax extended header data
671*d57664e9SAndroid Build Coastguard Worker memset(paxHeader + 124, 0, 12);
672*d57664e9SAndroid Build Coastguard Worker snprintf(paxHeader + 124, 12, "%011o", (unsigned int)paxLen);
673*d57664e9SAndroid Build Coastguard Worker
674*d57664e9SAndroid Build Coastguard Worker // Checksum and write the pax block header
675*d57664e9SAndroid Build Coastguard Worker calc_tar_checksum(paxHeader, PAXHEADER_SIZE);
676*d57664e9SAndroid Build Coastguard Worker send_tarfile_chunk(writer, paxHeader, 512);
677*d57664e9SAndroid Build Coastguard Worker
678*d57664e9SAndroid Build Coastguard Worker // Now write the pax data itself
679*d57664e9SAndroid Build Coastguard Worker int paxblocks = (paxLen + 511) / 512;
680*d57664e9SAndroid Build Coastguard Worker send_tarfile_chunk(writer, paxData, 512 * paxblocks);
681*d57664e9SAndroid Build Coastguard Worker }
682*d57664e9SAndroid Build Coastguard Worker
683*d57664e9SAndroid Build Coastguard Worker // Checksum and write the 512-byte ustar file header block to the output
684*d57664e9SAndroid Build Coastguard Worker calc_tar_checksum(buf, BUFSIZE);
685*d57664e9SAndroid Build Coastguard Worker send_tarfile_chunk(writer, buf, 512);
686*d57664e9SAndroid Build Coastguard Worker
687*d57664e9SAndroid Build Coastguard Worker // Now write the file data itself, for real files. We honor tar's convention that
688*d57664e9SAndroid Build Coastguard Worker // only full 512-byte blocks are sent to write().
689*d57664e9SAndroid Build Coastguard Worker if (!isdir) {
690*d57664e9SAndroid Build Coastguard Worker off64_t toWrite = s.st_size;
691*d57664e9SAndroid Build Coastguard Worker while (toWrite > 0) {
692*d57664e9SAndroid Build Coastguard Worker size_t toRead = toWrite;
693*d57664e9SAndroid Build Coastguard Worker if (toRead > BUFSIZE) {
694*d57664e9SAndroid Build Coastguard Worker toRead = BUFSIZE;
695*d57664e9SAndroid Build Coastguard Worker }
696*d57664e9SAndroid Build Coastguard Worker ssize_t nRead = read(fd, buf, toRead);
697*d57664e9SAndroid Build Coastguard Worker if (nRead < 0) {
698*d57664e9SAndroid Build Coastguard Worker err = errno;
699*d57664e9SAndroid Build Coastguard Worker ALOGE("Unable to read file [%s], err=%d (%s)", filepath.c_str(),
700*d57664e9SAndroid Build Coastguard Worker err, strerror(err));
701*d57664e9SAndroid Build Coastguard Worker break;
702*d57664e9SAndroid Build Coastguard Worker } else if (nRead == 0) {
703*d57664e9SAndroid Build Coastguard Worker ALOGE("EOF but expect %lld more bytes in [%s]", (long long) toWrite,
704*d57664e9SAndroid Build Coastguard Worker filepath.c_str());
705*d57664e9SAndroid Build Coastguard Worker err = EIO;
706*d57664e9SAndroid Build Coastguard Worker break;
707*d57664e9SAndroid Build Coastguard Worker }
708*d57664e9SAndroid Build Coastguard Worker
709*d57664e9SAndroid Build Coastguard Worker // At EOF we might have a short block; NUL-pad that to a 512-byte multiple. This
710*d57664e9SAndroid Build Coastguard Worker // depends on the OS guarantee that for ordinary files, read() will never return
711*d57664e9SAndroid Build Coastguard Worker // less than the number of bytes requested.
712*d57664e9SAndroid Build Coastguard Worker ssize_t partial = (nRead+512) % 512;
713*d57664e9SAndroid Build Coastguard Worker if (partial > 0) {
714*d57664e9SAndroid Build Coastguard Worker ssize_t remainder = 512 - partial;
715*d57664e9SAndroid Build Coastguard Worker memset(buf + nRead, 0, remainder);
716*d57664e9SAndroid Build Coastguard Worker nRead += remainder;
717*d57664e9SAndroid Build Coastguard Worker }
718*d57664e9SAndroid Build Coastguard Worker send_tarfile_chunk(writer, buf, nRead);
719*d57664e9SAndroid Build Coastguard Worker toWrite -= nRead;
720*d57664e9SAndroid Build Coastguard Worker }
721*d57664e9SAndroid Build Coastguard Worker }
722*d57664e9SAndroid Build Coastguard Worker
723*d57664e9SAndroid Build Coastguard Worker cleanup:
724*d57664e9SAndroid Build Coastguard Worker free(buf);
725*d57664e9SAndroid Build Coastguard Worker done:
726*d57664e9SAndroid Build Coastguard Worker close(fd);
727*d57664e9SAndroid Build Coastguard Worker return err;
728*d57664e9SAndroid Build Coastguard Worker }
729*d57664e9SAndroid Build Coastguard Worker // end tarfile
730*d57664e9SAndroid Build Coastguard Worker
731*d57664e9SAndroid Build Coastguard Worker
732*d57664e9SAndroid Build Coastguard Worker
733*d57664e9SAndroid Build Coastguard Worker const size_t RESTORE_BUF_SIZE = backup_flags::enable_max_size_writes_to_pipes() ? 64*1024 : 8*1024;
734*d57664e9SAndroid Build Coastguard Worker
RestoreHelperBase()735*d57664e9SAndroid Build Coastguard Worker RestoreHelperBase::RestoreHelperBase()
736*d57664e9SAndroid Build Coastguard Worker {
737*d57664e9SAndroid Build Coastguard Worker m_buf = malloc(RESTORE_BUF_SIZE);
738*d57664e9SAndroid Build Coastguard Worker m_loggedUnknownMetadata = false;
739*d57664e9SAndroid Build Coastguard Worker }
740*d57664e9SAndroid Build Coastguard Worker
~RestoreHelperBase()741*d57664e9SAndroid Build Coastguard Worker RestoreHelperBase::~RestoreHelperBase()
742*d57664e9SAndroid Build Coastguard Worker {
743*d57664e9SAndroid Build Coastguard Worker free(m_buf);
744*d57664e9SAndroid Build Coastguard Worker }
745*d57664e9SAndroid Build Coastguard Worker
746*d57664e9SAndroid Build Coastguard Worker status_t
WriteFile(const String8 & filename,BackupDataReader * in)747*d57664e9SAndroid Build Coastguard Worker RestoreHelperBase::WriteFile(const String8& filename, BackupDataReader* in)
748*d57664e9SAndroid Build Coastguard Worker {
749*d57664e9SAndroid Build Coastguard Worker ssize_t err;
750*d57664e9SAndroid Build Coastguard Worker size_t dataSize;
751*d57664e9SAndroid Build Coastguard Worker String8 key;
752*d57664e9SAndroid Build Coastguard Worker int fd;
753*d57664e9SAndroid Build Coastguard Worker void* buf = m_buf;
754*d57664e9SAndroid Build Coastguard Worker ssize_t amt;
755*d57664e9SAndroid Build Coastguard Worker int mode;
756*d57664e9SAndroid Build Coastguard Worker int crc;
757*d57664e9SAndroid Build Coastguard Worker struct stat st;
758*d57664e9SAndroid Build Coastguard Worker FileRec r;
759*d57664e9SAndroid Build Coastguard Worker
760*d57664e9SAndroid Build Coastguard Worker err = in->ReadEntityHeader(&key, &dataSize);
761*d57664e9SAndroid Build Coastguard Worker if (err != NO_ERROR) {
762*d57664e9SAndroid Build Coastguard Worker return err;
763*d57664e9SAndroid Build Coastguard Worker }
764*d57664e9SAndroid Build Coastguard Worker
765*d57664e9SAndroid Build Coastguard Worker // Get the metadata block off the head of the file entity and use that to
766*d57664e9SAndroid Build Coastguard Worker // set up the output file
767*d57664e9SAndroid Build Coastguard Worker file_metadata_v1 metadata;
768*d57664e9SAndroid Build Coastguard Worker amt = in->ReadEntityData(&metadata, sizeof(metadata));
769*d57664e9SAndroid Build Coastguard Worker if (amt != sizeof(metadata)) {
770*d57664e9SAndroid Build Coastguard Worker ALOGW("Could not read metadata for %s -- %ld / %s", filename.c_str(),
771*d57664e9SAndroid Build Coastguard Worker (long)amt, strerror(errno));
772*d57664e9SAndroid Build Coastguard Worker return EIO;
773*d57664e9SAndroid Build Coastguard Worker }
774*d57664e9SAndroid Build Coastguard Worker metadata.version = fromlel(metadata.version);
775*d57664e9SAndroid Build Coastguard Worker metadata.mode = fromlel(metadata.mode);
776*d57664e9SAndroid Build Coastguard Worker if (metadata.version > CURRENT_METADATA_VERSION) {
777*d57664e9SAndroid Build Coastguard Worker if (!m_loggedUnknownMetadata) {
778*d57664e9SAndroid Build Coastguard Worker m_loggedUnknownMetadata = true;
779*d57664e9SAndroid Build Coastguard Worker ALOGW("Restoring file with unsupported metadata version %d (currently %d)",
780*d57664e9SAndroid Build Coastguard Worker metadata.version, CURRENT_METADATA_VERSION);
781*d57664e9SAndroid Build Coastguard Worker }
782*d57664e9SAndroid Build Coastguard Worker }
783*d57664e9SAndroid Build Coastguard Worker mode = metadata.mode;
784*d57664e9SAndroid Build Coastguard Worker
785*d57664e9SAndroid Build Coastguard Worker // Write the file and compute the crc
786*d57664e9SAndroid Build Coastguard Worker crc = crc32(0L, Z_NULL, 0);
787*d57664e9SAndroid Build Coastguard Worker fd = open(filename.c_str(), O_CREAT|O_RDWR|O_TRUNC, mode);
788*d57664e9SAndroid Build Coastguard Worker if (fd == -1) {
789*d57664e9SAndroid Build Coastguard Worker ALOGW("Could not open file %s -- %s", filename.c_str(), strerror(errno));
790*d57664e9SAndroid Build Coastguard Worker return errno;
791*d57664e9SAndroid Build Coastguard Worker }
792*d57664e9SAndroid Build Coastguard Worker
793*d57664e9SAndroid Build Coastguard Worker while ((amt = in->ReadEntityData(buf, RESTORE_BUF_SIZE)) > 0) {
794*d57664e9SAndroid Build Coastguard Worker err = write(fd, buf, amt);
795*d57664e9SAndroid Build Coastguard Worker if (err != amt) {
796*d57664e9SAndroid Build Coastguard Worker close(fd);
797*d57664e9SAndroid Build Coastguard Worker ALOGW("Error '%s' writing '%s'", strerror(errno), filename.c_str());
798*d57664e9SAndroid Build Coastguard Worker return errno;
799*d57664e9SAndroid Build Coastguard Worker }
800*d57664e9SAndroid Build Coastguard Worker crc = crc32(crc, (Bytef*)buf, amt);
801*d57664e9SAndroid Build Coastguard Worker }
802*d57664e9SAndroid Build Coastguard Worker
803*d57664e9SAndroid Build Coastguard Worker close(fd);
804*d57664e9SAndroid Build Coastguard Worker
805*d57664e9SAndroid Build Coastguard Worker // Record for the snapshot
806*d57664e9SAndroid Build Coastguard Worker err = stat(filename.c_str(), &st);
807*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
808*d57664e9SAndroid Build Coastguard Worker ALOGW("Error stating file that we just created %s", filename.c_str());
809*d57664e9SAndroid Build Coastguard Worker return errno;
810*d57664e9SAndroid Build Coastguard Worker }
811*d57664e9SAndroid Build Coastguard Worker
812*d57664e9SAndroid Build Coastguard Worker r.file = filename;
813*d57664e9SAndroid Build Coastguard Worker r.deleted = false;
814*d57664e9SAndroid Build Coastguard Worker r.s.modTime_sec = st.st_mtime;
815*d57664e9SAndroid Build Coastguard Worker r.s.modTime_nsec = 0; // workaround sim breakage
816*d57664e9SAndroid Build Coastguard Worker //r.s.modTime_nsec = st.st_mtime_nsec;
817*d57664e9SAndroid Build Coastguard Worker r.s.mode = st.st_mode;
818*d57664e9SAndroid Build Coastguard Worker r.s.size = st.st_size;
819*d57664e9SAndroid Build Coastguard Worker r.s.crc32 = crc;
820*d57664e9SAndroid Build Coastguard Worker
821*d57664e9SAndroid Build Coastguard Worker m_files.add(key, r);
822*d57664e9SAndroid Build Coastguard Worker
823*d57664e9SAndroid Build Coastguard Worker return NO_ERROR;
824*d57664e9SAndroid Build Coastguard Worker }
825*d57664e9SAndroid Build Coastguard Worker
826*d57664e9SAndroid Build Coastguard Worker status_t
WriteSnapshot(int fd)827*d57664e9SAndroid Build Coastguard Worker RestoreHelperBase::WriteSnapshot(int fd)
828*d57664e9SAndroid Build Coastguard Worker {
829*d57664e9SAndroid Build Coastguard Worker return write_snapshot_file(fd, m_files);;
830*d57664e9SAndroid Build Coastguard Worker }
831*d57664e9SAndroid Build Coastguard Worker
832*d57664e9SAndroid Build Coastguard Worker #if TEST_BACKUP_HELPERS
833*d57664e9SAndroid Build Coastguard Worker
834*d57664e9SAndroid Build Coastguard Worker #define SCRATCH_DIR "/data/backup_helper_test/"
835*d57664e9SAndroid Build Coastguard Worker
836*d57664e9SAndroid Build Coastguard Worker static int
write_text_file(const char * path,const char * data)837*d57664e9SAndroid Build Coastguard Worker write_text_file(const char* path, const char* data)
838*d57664e9SAndroid Build Coastguard Worker {
839*d57664e9SAndroid Build Coastguard Worker int amt;
840*d57664e9SAndroid Build Coastguard Worker int fd;
841*d57664e9SAndroid Build Coastguard Worker int len;
842*d57664e9SAndroid Build Coastguard Worker
843*d57664e9SAndroid Build Coastguard Worker fd = creat(path, 0666);
844*d57664e9SAndroid Build Coastguard Worker if (fd == -1) {
845*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "creat %s failed\n", path);
846*d57664e9SAndroid Build Coastguard Worker return errno;
847*d57664e9SAndroid Build Coastguard Worker }
848*d57664e9SAndroid Build Coastguard Worker
849*d57664e9SAndroid Build Coastguard Worker len = strlen(data);
850*d57664e9SAndroid Build Coastguard Worker amt = write(fd, data, len);
851*d57664e9SAndroid Build Coastguard Worker if (amt != len) {
852*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "error (%s) writing to file %s\n", strerror(errno), path);
853*d57664e9SAndroid Build Coastguard Worker return errno;
854*d57664e9SAndroid Build Coastguard Worker }
855*d57664e9SAndroid Build Coastguard Worker
856*d57664e9SAndroid Build Coastguard Worker close(fd);
857*d57664e9SAndroid Build Coastguard Worker
858*d57664e9SAndroid Build Coastguard Worker return 0;
859*d57664e9SAndroid Build Coastguard Worker }
860*d57664e9SAndroid Build Coastguard Worker
861*d57664e9SAndroid Build Coastguard Worker static int
compare_file(const char * path,const unsigned char * data,int len)862*d57664e9SAndroid Build Coastguard Worker compare_file(const char* path, const unsigned char* data, int len)
863*d57664e9SAndroid Build Coastguard Worker {
864*d57664e9SAndroid Build Coastguard Worker int fd;
865*d57664e9SAndroid Build Coastguard Worker int amt;
866*d57664e9SAndroid Build Coastguard Worker
867*d57664e9SAndroid Build Coastguard Worker fd = open(path, O_RDONLY);
868*d57664e9SAndroid Build Coastguard Worker if (fd == -1) {
869*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "compare_file error (%s) opening %s\n", strerror(errno), path);
870*d57664e9SAndroid Build Coastguard Worker return errno;
871*d57664e9SAndroid Build Coastguard Worker }
872*d57664e9SAndroid Build Coastguard Worker
873*d57664e9SAndroid Build Coastguard Worker unsigned char* contents = (unsigned char*)malloc(len);
874*d57664e9SAndroid Build Coastguard Worker if (contents == NULL) {
875*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "malloc(%d) failed\n", len);
876*d57664e9SAndroid Build Coastguard Worker return ENOMEM;
877*d57664e9SAndroid Build Coastguard Worker }
878*d57664e9SAndroid Build Coastguard Worker
879*d57664e9SAndroid Build Coastguard Worker bool sizesMatch = true;
880*d57664e9SAndroid Build Coastguard Worker amt = lseek(fd, 0, SEEK_END);
881*d57664e9SAndroid Build Coastguard Worker if (amt != len) {
882*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "compare_file file length should be %d, was %d\n", len, amt);
883*d57664e9SAndroid Build Coastguard Worker sizesMatch = false;
884*d57664e9SAndroid Build Coastguard Worker }
885*d57664e9SAndroid Build Coastguard Worker lseek(fd, 0, SEEK_SET);
886*d57664e9SAndroid Build Coastguard Worker
887*d57664e9SAndroid Build Coastguard Worker int readLen = amt < len ? amt : len;
888*d57664e9SAndroid Build Coastguard Worker amt = read(fd, contents, readLen);
889*d57664e9SAndroid Build Coastguard Worker if (amt != readLen) {
890*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "compare_file read expected %d bytes but got %d\n", len, amt);
891*d57664e9SAndroid Build Coastguard Worker }
892*d57664e9SAndroid Build Coastguard Worker
893*d57664e9SAndroid Build Coastguard Worker bool contentsMatch = true;
894*d57664e9SAndroid Build Coastguard Worker for (int i=0; i<readLen; i++) {
895*d57664e9SAndroid Build Coastguard Worker if (data[i] != contents[i]) {
896*d57664e9SAndroid Build Coastguard Worker if (contentsMatch) {
897*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "compare_file contents are different: (index, expected, actual)\n");
898*d57664e9SAndroid Build Coastguard Worker contentsMatch = false;
899*d57664e9SAndroid Build Coastguard Worker }
900*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, " [%-2d] %02x %02x\n", i, data[i], contents[i]);
901*d57664e9SAndroid Build Coastguard Worker }
902*d57664e9SAndroid Build Coastguard Worker }
903*d57664e9SAndroid Build Coastguard Worker
904*d57664e9SAndroid Build Coastguard Worker free(contents);
905*d57664e9SAndroid Build Coastguard Worker return contentsMatch && sizesMatch ? 0 : 1;
906*d57664e9SAndroid Build Coastguard Worker }
907*d57664e9SAndroid Build Coastguard Worker
908*d57664e9SAndroid Build Coastguard Worker int
backup_helper_test_empty()909*d57664e9SAndroid Build Coastguard Worker backup_helper_test_empty()
910*d57664e9SAndroid Build Coastguard Worker {
911*d57664e9SAndroid Build Coastguard Worker int err;
912*d57664e9SAndroid Build Coastguard Worker int fd;
913*d57664e9SAndroid Build Coastguard Worker KeyedVector<String8,FileRec> snapshot;
914*d57664e9SAndroid Build Coastguard Worker const char* filename = SCRATCH_DIR "backup_helper_test_empty.snap";
915*d57664e9SAndroid Build Coastguard Worker
916*d57664e9SAndroid Build Coastguard Worker system("rm -r " SCRATCH_DIR);
917*d57664e9SAndroid Build Coastguard Worker mkdir(SCRATCH_DIR, 0777);
918*d57664e9SAndroid Build Coastguard Worker
919*d57664e9SAndroid Build Coastguard Worker // write
920*d57664e9SAndroid Build Coastguard Worker fd = creat(filename, 0666);
921*d57664e9SAndroid Build Coastguard Worker if (fd == -1) {
922*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "error creating %s\n", filename);
923*d57664e9SAndroid Build Coastguard Worker return 1;
924*d57664e9SAndroid Build Coastguard Worker }
925*d57664e9SAndroid Build Coastguard Worker
926*d57664e9SAndroid Build Coastguard Worker err = write_snapshot_file(fd, snapshot);
927*d57664e9SAndroid Build Coastguard Worker
928*d57664e9SAndroid Build Coastguard Worker close(fd);
929*d57664e9SAndroid Build Coastguard Worker
930*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
931*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err));
932*d57664e9SAndroid Build Coastguard Worker return err;
933*d57664e9SAndroid Build Coastguard Worker }
934*d57664e9SAndroid Build Coastguard Worker
935*d57664e9SAndroid Build Coastguard Worker static const unsigned char correct_data[] = {
936*d57664e9SAndroid Build Coastguard Worker 0x53, 0x6e, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00,
937*d57664e9SAndroid Build Coastguard Worker 0x46, 0x69, 0x6c, 0x65, 0x10, 0x00, 0x00, 0x00
938*d57664e9SAndroid Build Coastguard Worker };
939*d57664e9SAndroid Build Coastguard Worker
940*d57664e9SAndroid Build Coastguard Worker err = compare_file(filename, correct_data, sizeof(correct_data));
941*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
942*d57664e9SAndroid Build Coastguard Worker return err;
943*d57664e9SAndroid Build Coastguard Worker }
944*d57664e9SAndroid Build Coastguard Worker
945*d57664e9SAndroid Build Coastguard Worker // read
946*d57664e9SAndroid Build Coastguard Worker fd = open(filename, O_RDONLY);
947*d57664e9SAndroid Build Coastguard Worker if (fd == -1) {
948*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "error opening for read %s\n", filename);
949*d57664e9SAndroid Build Coastguard Worker return 1;
950*d57664e9SAndroid Build Coastguard Worker }
951*d57664e9SAndroid Build Coastguard Worker
952*d57664e9SAndroid Build Coastguard Worker KeyedVector<String8,FileState> readSnapshot;
953*d57664e9SAndroid Build Coastguard Worker err = read_snapshot_file(fd, &readSnapshot);
954*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
955*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "read_snapshot_file failed %d\n", err);
956*d57664e9SAndroid Build Coastguard Worker return err;
957*d57664e9SAndroid Build Coastguard Worker }
958*d57664e9SAndroid Build Coastguard Worker
959*d57664e9SAndroid Build Coastguard Worker if (readSnapshot.size() != 0) {
960*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "readSnapshot should be length 0\n");
961*d57664e9SAndroid Build Coastguard Worker return 1;
962*d57664e9SAndroid Build Coastguard Worker }
963*d57664e9SAndroid Build Coastguard Worker
964*d57664e9SAndroid Build Coastguard Worker return 0;
965*d57664e9SAndroid Build Coastguard Worker }
966*d57664e9SAndroid Build Coastguard Worker
967*d57664e9SAndroid Build Coastguard Worker int
backup_helper_test_four()968*d57664e9SAndroid Build Coastguard Worker backup_helper_test_four()
969*d57664e9SAndroid Build Coastguard Worker {
970*d57664e9SAndroid Build Coastguard Worker int err;
971*d57664e9SAndroid Build Coastguard Worker int fd;
972*d57664e9SAndroid Build Coastguard Worker KeyedVector<String8,FileRec> snapshot;
973*d57664e9SAndroid Build Coastguard Worker const char* filename = SCRATCH_DIR "backup_helper_test_four.snap";
974*d57664e9SAndroid Build Coastguard Worker
975*d57664e9SAndroid Build Coastguard Worker system("rm -r " SCRATCH_DIR);
976*d57664e9SAndroid Build Coastguard Worker mkdir(SCRATCH_DIR, 0777);
977*d57664e9SAndroid Build Coastguard Worker
978*d57664e9SAndroid Build Coastguard Worker // write
979*d57664e9SAndroid Build Coastguard Worker fd = creat(filename, 0666);
980*d57664e9SAndroid Build Coastguard Worker if (fd == -1) {
981*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "error opening %s\n", filename);
982*d57664e9SAndroid Build Coastguard Worker return 1;
983*d57664e9SAndroid Build Coastguard Worker }
984*d57664e9SAndroid Build Coastguard Worker
985*d57664e9SAndroid Build Coastguard Worker String8 filenames[4];
986*d57664e9SAndroid Build Coastguard Worker FileState states[4];
987*d57664e9SAndroid Build Coastguard Worker FileRec r;
988*d57664e9SAndroid Build Coastguard Worker r.deleted = false;
989*d57664e9SAndroid Build Coastguard Worker
990*d57664e9SAndroid Build Coastguard Worker states[0].modTime_sec = 0xfedcba98;
991*d57664e9SAndroid Build Coastguard Worker states[0].modTime_nsec = 0xdeadbeef;
992*d57664e9SAndroid Build Coastguard Worker states[0].mode = 0777; // decimal 511, hex 0x000001ff
993*d57664e9SAndroid Build Coastguard Worker states[0].size = 0xababbcbc;
994*d57664e9SAndroid Build Coastguard Worker states[0].crc32 = 0x12345678;
995*d57664e9SAndroid Build Coastguard Worker states[0].nameLen = -12;
996*d57664e9SAndroid Build Coastguard Worker r.s = states[0];
997*d57664e9SAndroid Build Coastguard Worker filenames[0] = String8("bytes_of_padding");
998*d57664e9SAndroid Build Coastguard Worker snapshot.add(filenames[0], r);
999*d57664e9SAndroid Build Coastguard Worker
1000*d57664e9SAndroid Build Coastguard Worker states[1].modTime_sec = 0x93400031;
1001*d57664e9SAndroid Build Coastguard Worker states[1].modTime_nsec = 0xdeadbeef;
1002*d57664e9SAndroid Build Coastguard Worker states[1].mode = 0666; // decimal 438, hex 0x000001b6
1003*d57664e9SAndroid Build Coastguard Worker states[1].size = 0x88557766;
1004*d57664e9SAndroid Build Coastguard Worker states[1].crc32 = 0x22334422;
1005*d57664e9SAndroid Build Coastguard Worker states[1].nameLen = -1;
1006*d57664e9SAndroid Build Coastguard Worker r.s = states[1];
1007*d57664e9SAndroid Build Coastguard Worker filenames[1] = String8("bytes_of_padding3");
1008*d57664e9SAndroid Build Coastguard Worker snapshot.add(filenames[1], r);
1009*d57664e9SAndroid Build Coastguard Worker
1010*d57664e9SAndroid Build Coastguard Worker states[2].modTime_sec = 0x33221144;
1011*d57664e9SAndroid Build Coastguard Worker states[2].modTime_nsec = 0xdeadbeef;
1012*d57664e9SAndroid Build Coastguard Worker states[2].mode = 0744; // decimal 484, hex 0x000001e4
1013*d57664e9SAndroid Build Coastguard Worker states[2].size = 0x11223344;
1014*d57664e9SAndroid Build Coastguard Worker states[2].crc32 = 0x01122334;
1015*d57664e9SAndroid Build Coastguard Worker states[2].nameLen = 0;
1016*d57664e9SAndroid Build Coastguard Worker r.s = states[2];
1017*d57664e9SAndroid Build Coastguard Worker filenames[2] = String8("bytes_of_padding_2");
1018*d57664e9SAndroid Build Coastguard Worker snapshot.add(filenames[2], r);
1019*d57664e9SAndroid Build Coastguard Worker
1020*d57664e9SAndroid Build Coastguard Worker states[3].modTime_sec = 0x33221144;
1021*d57664e9SAndroid Build Coastguard Worker states[3].modTime_nsec = 0xdeadbeef;
1022*d57664e9SAndroid Build Coastguard Worker states[3].mode = 0755; // decimal 493, hex 0x000001ed
1023*d57664e9SAndroid Build Coastguard Worker states[3].size = 0x11223344;
1024*d57664e9SAndroid Build Coastguard Worker states[3].crc32 = 0x01122334;
1025*d57664e9SAndroid Build Coastguard Worker states[3].nameLen = 0;
1026*d57664e9SAndroid Build Coastguard Worker r.s = states[3];
1027*d57664e9SAndroid Build Coastguard Worker filenames[3] = String8("bytes_of_padding__1");
1028*d57664e9SAndroid Build Coastguard Worker snapshot.add(filenames[3], r);
1029*d57664e9SAndroid Build Coastguard Worker
1030*d57664e9SAndroid Build Coastguard Worker err = write_snapshot_file(fd, snapshot);
1031*d57664e9SAndroid Build Coastguard Worker
1032*d57664e9SAndroid Build Coastguard Worker close(fd);
1033*d57664e9SAndroid Build Coastguard Worker
1034*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
1035*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err));
1036*d57664e9SAndroid Build Coastguard Worker return err;
1037*d57664e9SAndroid Build Coastguard Worker }
1038*d57664e9SAndroid Build Coastguard Worker
1039*d57664e9SAndroid Build Coastguard Worker static const unsigned char correct_data[] = {
1040*d57664e9SAndroid Build Coastguard Worker // header
1041*d57664e9SAndroid Build Coastguard Worker 0x53, 0x6e, 0x61, 0x70, 0x04, 0x00, 0x00, 0x00,
1042*d57664e9SAndroid Build Coastguard Worker 0x46, 0x69, 0x6c, 0x65, 0xbc, 0x00, 0x00, 0x00,
1043*d57664e9SAndroid Build Coastguard Worker
1044*d57664e9SAndroid Build Coastguard Worker // bytes_of_padding
1045*d57664e9SAndroid Build Coastguard Worker 0x98, 0xba, 0xdc, 0xfe, 0xef, 0xbe, 0xad, 0xde,
1046*d57664e9SAndroid Build Coastguard Worker 0xff, 0x01, 0x00, 0x00, 0xbc, 0xbc, 0xab, 0xab,
1047*d57664e9SAndroid Build Coastguard Worker 0x78, 0x56, 0x34, 0x12, 0x10, 0x00, 0x00, 0x00,
1048*d57664e9SAndroid Build Coastguard Worker 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6f, 0x66,
1049*d57664e9SAndroid Build Coastguard Worker 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
1050*d57664e9SAndroid Build Coastguard Worker
1051*d57664e9SAndroid Build Coastguard Worker // bytes_of_padding3
1052*d57664e9SAndroid Build Coastguard Worker 0x31, 0x00, 0x40, 0x93, 0xef, 0xbe, 0xad, 0xde,
1053*d57664e9SAndroid Build Coastguard Worker 0xb6, 0x01, 0x00, 0x00, 0x66, 0x77, 0x55, 0x88,
1054*d57664e9SAndroid Build Coastguard Worker 0x22, 0x44, 0x33, 0x22, 0x11, 0x00, 0x00, 0x00,
1055*d57664e9SAndroid Build Coastguard Worker 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6f, 0x66,
1056*d57664e9SAndroid Build Coastguard Worker 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
1057*d57664e9SAndroid Build Coastguard Worker 0x33, 0xab, 0xab, 0xab,
1058*d57664e9SAndroid Build Coastguard Worker
1059*d57664e9SAndroid Build Coastguard Worker // bytes of padding2
1060*d57664e9SAndroid Build Coastguard Worker 0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde,
1061*d57664e9SAndroid Build Coastguard Worker 0xe4, 0x01, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11,
1062*d57664e9SAndroid Build Coastguard Worker 0x34, 0x23, 0x12, 0x01, 0x12, 0x00, 0x00, 0x00,
1063*d57664e9SAndroid Build Coastguard Worker 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6f, 0x66,
1064*d57664e9SAndroid Build Coastguard Worker 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
1065*d57664e9SAndroid Build Coastguard Worker 0x5f, 0x32, 0xab, 0xab,
1066*d57664e9SAndroid Build Coastguard Worker
1067*d57664e9SAndroid Build Coastguard Worker // bytes of padding3
1068*d57664e9SAndroid Build Coastguard Worker 0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde,
1069*d57664e9SAndroid Build Coastguard Worker 0xed, 0x01, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11,
1070*d57664e9SAndroid Build Coastguard Worker 0x34, 0x23, 0x12, 0x01, 0x13, 0x00, 0x00, 0x00,
1071*d57664e9SAndroid Build Coastguard Worker 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6f, 0x66,
1072*d57664e9SAndroid Build Coastguard Worker 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
1073*d57664e9SAndroid Build Coastguard Worker 0x5f, 0x5f, 0x31, 0xab
1074*d57664e9SAndroid Build Coastguard Worker };
1075*d57664e9SAndroid Build Coastguard Worker
1076*d57664e9SAndroid Build Coastguard Worker err = compare_file(filename, correct_data, sizeof(correct_data));
1077*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
1078*d57664e9SAndroid Build Coastguard Worker return err;
1079*d57664e9SAndroid Build Coastguard Worker }
1080*d57664e9SAndroid Build Coastguard Worker
1081*d57664e9SAndroid Build Coastguard Worker // read
1082*d57664e9SAndroid Build Coastguard Worker fd = open(filename, O_RDONLY);
1083*d57664e9SAndroid Build Coastguard Worker if (fd == -1) {
1084*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "error opening for read %s\n", filename);
1085*d57664e9SAndroid Build Coastguard Worker return 1;
1086*d57664e9SAndroid Build Coastguard Worker }
1087*d57664e9SAndroid Build Coastguard Worker
1088*d57664e9SAndroid Build Coastguard Worker
1089*d57664e9SAndroid Build Coastguard Worker KeyedVector<String8,FileState> readSnapshot;
1090*d57664e9SAndroid Build Coastguard Worker err = read_snapshot_file(fd, &readSnapshot);
1091*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
1092*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "read_snapshot_file failed %d\n", err);
1093*d57664e9SAndroid Build Coastguard Worker return err;
1094*d57664e9SAndroid Build Coastguard Worker }
1095*d57664e9SAndroid Build Coastguard Worker
1096*d57664e9SAndroid Build Coastguard Worker if (readSnapshot.size() != 4) {
1097*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "readSnapshot should be length 4 is %zu\n", readSnapshot.size());
1098*d57664e9SAndroid Build Coastguard Worker return 1;
1099*d57664e9SAndroid Build Coastguard Worker }
1100*d57664e9SAndroid Build Coastguard Worker
1101*d57664e9SAndroid Build Coastguard Worker bool matched = true;
1102*d57664e9SAndroid Build Coastguard Worker for (size_t i=0; i<readSnapshot.size(); i++) {
1103*d57664e9SAndroid Build Coastguard Worker const String8& name = readSnapshot.keyAt(i);
1104*d57664e9SAndroid Build Coastguard Worker const FileState state = readSnapshot.valueAt(i);
1105*d57664e9SAndroid Build Coastguard Worker
1106*d57664e9SAndroid Build Coastguard Worker if (name != filenames[i] || states[i].modTime_sec != state.modTime_sec
1107*d57664e9SAndroid Build Coastguard Worker || states[i].modTime_nsec != state.modTime_nsec || states[i].mode != state.mode
1108*d57664e9SAndroid Build Coastguard Worker || states[i].size != state.size || states[i].crc32 != states[i].crc32) {
1109*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "state %zu expected={%d/%d, %04o, 0x%08x, 0x%08x, %3zu} '%s'\n"
1110*d57664e9SAndroid Build Coastguard Worker " actual={%d/%d, %04o, 0x%08x, 0x%08x, %3d} '%s'\n", i,
1111*d57664e9SAndroid Build Coastguard Worker states[i].modTime_sec, states[i].modTime_nsec, states[i].mode, states[i].size,
1112*d57664e9SAndroid Build Coastguard Worker states[i].crc32, name.length(), filenames[i].c_str(),
1113*d57664e9SAndroid Build Coastguard Worker state.modTime_sec, state.modTime_nsec, state.mode, state.size, state.crc32,
1114*d57664e9SAndroid Build Coastguard Worker state.nameLen, name.c_str());
1115*d57664e9SAndroid Build Coastguard Worker matched = false;
1116*d57664e9SAndroid Build Coastguard Worker }
1117*d57664e9SAndroid Build Coastguard Worker }
1118*d57664e9SAndroid Build Coastguard Worker
1119*d57664e9SAndroid Build Coastguard Worker return matched ? 0 : 1;
1120*d57664e9SAndroid Build Coastguard Worker }
1121*d57664e9SAndroid Build Coastguard Worker
1122*d57664e9SAndroid Build Coastguard Worker // hexdump -v -e '" " 8/1 " 0x%02x," "\n"' data_writer.data
1123*d57664e9SAndroid Build Coastguard Worker const unsigned char DATA_GOLDEN_FILE[] = {
1124*d57664e9SAndroid Build Coastguard Worker 0x44, 0x61, 0x74, 0x61, 0x0b, 0x00, 0x00, 0x00,
1125*d57664e9SAndroid Build Coastguard Worker 0x0c, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x5f, 0x70,
1126*d57664e9SAndroid Build Coastguard Worker 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00,
1127*d57664e9SAndroid Build Coastguard Worker 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69,
1128*d57664e9SAndroid Build Coastguard Worker 0x6e, 0x67, 0x5f, 0x00, 0x44, 0x61, 0x74, 0x61,
1129*d57664e9SAndroid Build Coastguard Worker 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1130*d57664e9SAndroid Build Coastguard Worker 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
1131*d57664e9SAndroid Build Coastguard Worker 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
1132*d57664e9SAndroid Build Coastguard Worker 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
1133*d57664e9SAndroid Build Coastguard Worker 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
1134*d57664e9SAndroid Build Coastguard Worker 0x44, 0x61, 0x74, 0x61, 0x0d, 0x00, 0x00, 0x00,
1135*d57664e9SAndroid Build Coastguard Worker 0x0e, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
1136*d57664e9SAndroid Build Coastguard Worker 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
1137*d57664e9SAndroid Build Coastguard Worker 0x5f, 0x00, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64,
1138*d57664e9SAndroid Build Coastguard Worker 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
1139*d57664e9SAndroid Build Coastguard Worker 0x5f, 0x00, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61,
1140*d57664e9SAndroid Build Coastguard Worker 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1141*d57664e9SAndroid Build Coastguard Worker 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
1142*d57664e9SAndroid Build Coastguard Worker 0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64,
1143*d57664e9SAndroid Build Coastguard Worker 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00
1144*d57664e9SAndroid Build Coastguard Worker
1145*d57664e9SAndroid Build Coastguard Worker };
1146*d57664e9SAndroid Build Coastguard Worker const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE);
1147*d57664e9SAndroid Build Coastguard Worker
1148*d57664e9SAndroid Build Coastguard Worker static int
test_write_header_and_entity(BackupDataWriter & writer,const char * str)1149*d57664e9SAndroid Build Coastguard Worker test_write_header_and_entity(BackupDataWriter& writer, const char* str)
1150*d57664e9SAndroid Build Coastguard Worker {
1151*d57664e9SAndroid Build Coastguard Worker int err;
1152*d57664e9SAndroid Build Coastguard Worker String8 text(str);
1153*d57664e9SAndroid Build Coastguard Worker
1154*d57664e9SAndroid Build Coastguard Worker err = writer.WriteEntityHeader(text, text.length()+1);
1155*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
1156*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "WriteEntityHeader failed with %s\n", strerror(err));
1157*d57664e9SAndroid Build Coastguard Worker return err;
1158*d57664e9SAndroid Build Coastguard Worker }
1159*d57664e9SAndroid Build Coastguard Worker
1160*d57664e9SAndroid Build Coastguard Worker err = writer.WriteEntityData(text.c_str(), text.length()+1);
1161*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
1162*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "write failed for data '%s'\n", text.c_str());
1163*d57664e9SAndroid Build Coastguard Worker return errno;
1164*d57664e9SAndroid Build Coastguard Worker }
1165*d57664e9SAndroid Build Coastguard Worker
1166*d57664e9SAndroid Build Coastguard Worker return err;
1167*d57664e9SAndroid Build Coastguard Worker }
1168*d57664e9SAndroid Build Coastguard Worker
1169*d57664e9SAndroid Build Coastguard Worker int
backup_helper_test_data_writer()1170*d57664e9SAndroid Build Coastguard Worker backup_helper_test_data_writer()
1171*d57664e9SAndroid Build Coastguard Worker {
1172*d57664e9SAndroid Build Coastguard Worker int err;
1173*d57664e9SAndroid Build Coastguard Worker int fd;
1174*d57664e9SAndroid Build Coastguard Worker const char* filename = SCRATCH_DIR "data_writer.data";
1175*d57664e9SAndroid Build Coastguard Worker
1176*d57664e9SAndroid Build Coastguard Worker system("rm -r " SCRATCH_DIR);
1177*d57664e9SAndroid Build Coastguard Worker mkdir(SCRATCH_DIR, 0777);
1178*d57664e9SAndroid Build Coastguard Worker mkdir(SCRATCH_DIR "data", 0777);
1179*d57664e9SAndroid Build Coastguard Worker
1180*d57664e9SAndroid Build Coastguard Worker fd = creat(filename, 0666);
1181*d57664e9SAndroid Build Coastguard Worker if (fd == -1) {
1182*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "error creating: %s\n", strerror(errno));
1183*d57664e9SAndroid Build Coastguard Worker return errno;
1184*d57664e9SAndroid Build Coastguard Worker }
1185*d57664e9SAndroid Build Coastguard Worker
1186*d57664e9SAndroid Build Coastguard Worker BackupDataWriter writer(fd);
1187*d57664e9SAndroid Build Coastguard Worker
1188*d57664e9SAndroid Build Coastguard Worker err = 0;
1189*d57664e9SAndroid Build Coastguard Worker err |= test_write_header_and_entity(writer, "no_padding_");
1190*d57664e9SAndroid Build Coastguard Worker err |= test_write_header_and_entity(writer, "padded_to__3");
1191*d57664e9SAndroid Build Coastguard Worker err |= test_write_header_and_entity(writer, "padded_to_2__");
1192*d57664e9SAndroid Build Coastguard Worker err |= test_write_header_and_entity(writer, "padded_to1");
1193*d57664e9SAndroid Build Coastguard Worker
1194*d57664e9SAndroid Build Coastguard Worker close(fd);
1195*d57664e9SAndroid Build Coastguard Worker
1196*d57664e9SAndroid Build Coastguard Worker err = compare_file(filename, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
1197*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
1198*d57664e9SAndroid Build Coastguard Worker return err;
1199*d57664e9SAndroid Build Coastguard Worker }
1200*d57664e9SAndroid Build Coastguard Worker
1201*d57664e9SAndroid Build Coastguard Worker return err;
1202*d57664e9SAndroid Build Coastguard Worker }
1203*d57664e9SAndroid Build Coastguard Worker
1204*d57664e9SAndroid Build Coastguard Worker int
test_read_header_and_entity(BackupDataReader & reader,const char * str)1205*d57664e9SAndroid Build Coastguard Worker test_read_header_and_entity(BackupDataReader& reader, const char* str)
1206*d57664e9SAndroid Build Coastguard Worker {
1207*d57664e9SAndroid Build Coastguard Worker int err;
1208*d57664e9SAndroid Build Coastguard Worker size_t bufSize = strlen(str)+1;
1209*d57664e9SAndroid Build Coastguard Worker char* buf = (char*)malloc(bufSize);
1210*d57664e9SAndroid Build Coastguard Worker String8 string;
1211*d57664e9SAndroid Build Coastguard Worker size_t actualSize;
1212*d57664e9SAndroid Build Coastguard Worker bool done;
1213*d57664e9SAndroid Build Coastguard Worker int type;
1214*d57664e9SAndroid Build Coastguard Worker ssize_t nRead;
1215*d57664e9SAndroid Build Coastguard Worker
1216*d57664e9SAndroid Build Coastguard Worker // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str);
1217*d57664e9SAndroid Build Coastguard Worker
1218*d57664e9SAndroid Build Coastguard Worker err = reader.ReadNextHeader(&done, &type);
1219*d57664e9SAndroid Build Coastguard Worker if (done) {
1220*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "should not be done yet\n");
1221*d57664e9SAndroid Build Coastguard Worker goto finished;
1222*d57664e9SAndroid Build Coastguard Worker }
1223*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
1224*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err));
1225*d57664e9SAndroid Build Coastguard Worker goto finished;
1226*d57664e9SAndroid Build Coastguard Worker }
1227*d57664e9SAndroid Build Coastguard Worker if (type != BACKUP_HEADER_ENTITY_V1) {
1228*d57664e9SAndroid Build Coastguard Worker err = EINVAL;
1229*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "type=0x%08x expected 0x%08x\n", type, BACKUP_HEADER_ENTITY_V1);
1230*d57664e9SAndroid Build Coastguard Worker }
1231*d57664e9SAndroid Build Coastguard Worker
1232*d57664e9SAndroid Build Coastguard Worker err = reader.ReadEntityHeader(&string, &actualSize);
1233*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
1234*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err));
1235*d57664e9SAndroid Build Coastguard Worker goto finished;
1236*d57664e9SAndroid Build Coastguard Worker }
1237*d57664e9SAndroid Build Coastguard Worker if (string != str) {
1238*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.c_str());
1239*d57664e9SAndroid Build Coastguard Worker err = EINVAL;
1240*d57664e9SAndroid Build Coastguard Worker goto finished;
1241*d57664e9SAndroid Build Coastguard Worker }
1242*d57664e9SAndroid Build Coastguard Worker if (actualSize != bufSize) {
1243*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ReadEntityHeader expected dataSize %zu got %zu\n",
1244*d57664e9SAndroid Build Coastguard Worker bufSize, actualSize);
1245*d57664e9SAndroid Build Coastguard Worker err = EINVAL;
1246*d57664e9SAndroid Build Coastguard Worker goto finished;
1247*d57664e9SAndroid Build Coastguard Worker }
1248*d57664e9SAndroid Build Coastguard Worker
1249*d57664e9SAndroid Build Coastguard Worker nRead = reader.ReadEntityData(buf, bufSize);
1250*d57664e9SAndroid Build Coastguard Worker if (nRead < 0) {
1251*d57664e9SAndroid Build Coastguard Worker err = reader.Status();
1252*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err));
1253*d57664e9SAndroid Build Coastguard Worker goto finished;
1254*d57664e9SAndroid Build Coastguard Worker }
1255*d57664e9SAndroid Build Coastguard Worker
1256*d57664e9SAndroid Build Coastguard Worker if (0 != memcmp(buf, str, bufSize)) {
1257*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "ReadEntityData expected '%s' but got something starting with "
1258*d57664e9SAndroid Build Coastguard Worker "%02x %02x %02x %02x '%c%c%c%c'\n", str, buf[0], buf[1], buf[2], buf[3],
1259*d57664e9SAndroid Build Coastguard Worker buf[0], buf[1], buf[2], buf[3]);
1260*d57664e9SAndroid Build Coastguard Worker err = EINVAL;
1261*d57664e9SAndroid Build Coastguard Worker goto finished;
1262*d57664e9SAndroid Build Coastguard Worker }
1263*d57664e9SAndroid Build Coastguard Worker
1264*d57664e9SAndroid Build Coastguard Worker // The next read will confirm whether it got the right amount of data.
1265*d57664e9SAndroid Build Coastguard Worker
1266*d57664e9SAndroid Build Coastguard Worker finished:
1267*d57664e9SAndroid Build Coastguard Worker if (err != NO_ERROR) {
1268*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err));
1269*d57664e9SAndroid Build Coastguard Worker }
1270*d57664e9SAndroid Build Coastguard Worker free(buf);
1271*d57664e9SAndroid Build Coastguard Worker return err;
1272*d57664e9SAndroid Build Coastguard Worker }
1273*d57664e9SAndroid Build Coastguard Worker
1274*d57664e9SAndroid Build Coastguard Worker int
backup_helper_test_data_reader()1275*d57664e9SAndroid Build Coastguard Worker backup_helper_test_data_reader()
1276*d57664e9SAndroid Build Coastguard Worker {
1277*d57664e9SAndroid Build Coastguard Worker int err;
1278*d57664e9SAndroid Build Coastguard Worker int fd;
1279*d57664e9SAndroid Build Coastguard Worker const char* filename = SCRATCH_DIR "data_reader.data";
1280*d57664e9SAndroid Build Coastguard Worker
1281*d57664e9SAndroid Build Coastguard Worker system("rm -r " SCRATCH_DIR);
1282*d57664e9SAndroid Build Coastguard Worker mkdir(SCRATCH_DIR, 0777);
1283*d57664e9SAndroid Build Coastguard Worker mkdir(SCRATCH_DIR "data", 0777);
1284*d57664e9SAndroid Build Coastguard Worker
1285*d57664e9SAndroid Build Coastguard Worker fd = creat(filename, 0666);
1286*d57664e9SAndroid Build Coastguard Worker if (fd == -1) {
1287*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "error creating: %s\n", strerror(errno));
1288*d57664e9SAndroid Build Coastguard Worker return errno;
1289*d57664e9SAndroid Build Coastguard Worker }
1290*d57664e9SAndroid Build Coastguard Worker
1291*d57664e9SAndroid Build Coastguard Worker err = write(fd, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
1292*d57664e9SAndroid Build Coastguard Worker if (err != DATA_GOLDEN_FILE_SIZE) {
1293*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "Error \"%s\" writing golden file %s\n", strerror(errno), filename);
1294*d57664e9SAndroid Build Coastguard Worker return errno;
1295*d57664e9SAndroid Build Coastguard Worker }
1296*d57664e9SAndroid Build Coastguard Worker
1297*d57664e9SAndroid Build Coastguard Worker close(fd);
1298*d57664e9SAndroid Build Coastguard Worker
1299*d57664e9SAndroid Build Coastguard Worker fd = open(filename, O_RDONLY);
1300*d57664e9SAndroid Build Coastguard Worker if (fd == -1) {
1301*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "Error \"%s\" opening golden file %s for read\n", strerror(errno),
1302*d57664e9SAndroid Build Coastguard Worker filename);
1303*d57664e9SAndroid Build Coastguard Worker return errno;
1304*d57664e9SAndroid Build Coastguard Worker }
1305*d57664e9SAndroid Build Coastguard Worker
1306*d57664e9SAndroid Build Coastguard Worker {
1307*d57664e9SAndroid Build Coastguard Worker BackupDataReader reader(fd);
1308*d57664e9SAndroid Build Coastguard Worker
1309*d57664e9SAndroid Build Coastguard Worker err = 0;
1310*d57664e9SAndroid Build Coastguard Worker
1311*d57664e9SAndroid Build Coastguard Worker if (err == NO_ERROR) {
1312*d57664e9SAndroid Build Coastguard Worker err = test_read_header_and_entity(reader, "no_padding_");
1313*d57664e9SAndroid Build Coastguard Worker }
1314*d57664e9SAndroid Build Coastguard Worker
1315*d57664e9SAndroid Build Coastguard Worker if (err == NO_ERROR) {
1316*d57664e9SAndroid Build Coastguard Worker err = test_read_header_and_entity(reader, "padded_to__3");
1317*d57664e9SAndroid Build Coastguard Worker }
1318*d57664e9SAndroid Build Coastguard Worker
1319*d57664e9SAndroid Build Coastguard Worker if (err == NO_ERROR) {
1320*d57664e9SAndroid Build Coastguard Worker err = test_read_header_and_entity(reader, "padded_to_2__");
1321*d57664e9SAndroid Build Coastguard Worker }
1322*d57664e9SAndroid Build Coastguard Worker
1323*d57664e9SAndroid Build Coastguard Worker if (err == NO_ERROR) {
1324*d57664e9SAndroid Build Coastguard Worker err = test_read_header_and_entity(reader, "padded_to1");
1325*d57664e9SAndroid Build Coastguard Worker }
1326*d57664e9SAndroid Build Coastguard Worker }
1327*d57664e9SAndroid Build Coastguard Worker
1328*d57664e9SAndroid Build Coastguard Worker close(fd);
1329*d57664e9SAndroid Build Coastguard Worker
1330*d57664e9SAndroid Build Coastguard Worker return err;
1331*d57664e9SAndroid Build Coastguard Worker }
1332*d57664e9SAndroid Build Coastguard Worker
1333*d57664e9SAndroid Build Coastguard Worker static int
get_mod_time(const char * filename,struct timeval times[2])1334*d57664e9SAndroid Build Coastguard Worker get_mod_time(const char* filename, struct timeval times[2])
1335*d57664e9SAndroid Build Coastguard Worker {
1336*d57664e9SAndroid Build Coastguard Worker int err;
1337*d57664e9SAndroid Build Coastguard Worker struct stat64 st;
1338*d57664e9SAndroid Build Coastguard Worker err = stat64(filename, &st);
1339*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
1340*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "stat '%s' failed: %s\n", filename, strerror(errno));
1341*d57664e9SAndroid Build Coastguard Worker return errno;
1342*d57664e9SAndroid Build Coastguard Worker }
1343*d57664e9SAndroid Build Coastguard Worker
1344*d57664e9SAndroid Build Coastguard Worker times[0].tv_sec = st.st_atim.tv_sec;
1345*d57664e9SAndroid Build Coastguard Worker times[0].tv_usec = st.st_atim.tv_nsec / 1000;
1346*d57664e9SAndroid Build Coastguard Worker
1347*d57664e9SAndroid Build Coastguard Worker times[1].tv_sec = st.st_mtim.tv_sec;
1348*d57664e9SAndroid Build Coastguard Worker times[1].tv_usec = st.st_mtim.tv_nsec / 1000;
1349*d57664e9SAndroid Build Coastguard Worker
1350*d57664e9SAndroid Build Coastguard Worker return 0;
1351*d57664e9SAndroid Build Coastguard Worker }
1352*d57664e9SAndroid Build Coastguard Worker
1353*d57664e9SAndroid Build Coastguard Worker int
backup_helper_test_files()1354*d57664e9SAndroid Build Coastguard Worker backup_helper_test_files()
1355*d57664e9SAndroid Build Coastguard Worker {
1356*d57664e9SAndroid Build Coastguard Worker int err;
1357*d57664e9SAndroid Build Coastguard Worker int oldSnapshotFD;
1358*d57664e9SAndroid Build Coastguard Worker int dataStreamFD;
1359*d57664e9SAndroid Build Coastguard Worker int newSnapshotFD;
1360*d57664e9SAndroid Build Coastguard Worker
1361*d57664e9SAndroid Build Coastguard Worker system("rm -r " SCRATCH_DIR);
1362*d57664e9SAndroid Build Coastguard Worker mkdir(SCRATCH_DIR, 0777);
1363*d57664e9SAndroid Build Coastguard Worker mkdir(SCRATCH_DIR "data", 0777);
1364*d57664e9SAndroid Build Coastguard Worker
1365*d57664e9SAndroid Build Coastguard Worker write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
1366*d57664e9SAndroid Build Coastguard Worker write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
1367*d57664e9SAndroid Build Coastguard Worker write_text_file(SCRATCH_DIR "data/d", "d\ndd\n");
1368*d57664e9SAndroid Build Coastguard Worker write_text_file(SCRATCH_DIR "data/e", "e\nee\n");
1369*d57664e9SAndroid Build Coastguard Worker write_text_file(SCRATCH_DIR "data/f", "f\nff\n");
1370*d57664e9SAndroid Build Coastguard Worker write_text_file(SCRATCH_DIR "data/h", "h\nhh\n");
1371*d57664e9SAndroid Build Coastguard Worker
1372*d57664e9SAndroid Build Coastguard Worker char const* files_before[] = {
1373*d57664e9SAndroid Build Coastguard Worker SCRATCH_DIR "data/b",
1374*d57664e9SAndroid Build Coastguard Worker SCRATCH_DIR "data/c",
1375*d57664e9SAndroid Build Coastguard Worker SCRATCH_DIR "data/d",
1376*d57664e9SAndroid Build Coastguard Worker SCRATCH_DIR "data/e",
1377*d57664e9SAndroid Build Coastguard Worker SCRATCH_DIR "data/f"
1378*d57664e9SAndroid Build Coastguard Worker };
1379*d57664e9SAndroid Build Coastguard Worker
1380*d57664e9SAndroid Build Coastguard Worker char const* keys_before[] = {
1381*d57664e9SAndroid Build Coastguard Worker "data/b",
1382*d57664e9SAndroid Build Coastguard Worker "data/c",
1383*d57664e9SAndroid Build Coastguard Worker "data/d",
1384*d57664e9SAndroid Build Coastguard Worker "data/e",
1385*d57664e9SAndroid Build Coastguard Worker "data/f"
1386*d57664e9SAndroid Build Coastguard Worker };
1387*d57664e9SAndroid Build Coastguard Worker
1388*d57664e9SAndroid Build Coastguard Worker dataStreamFD = creat(SCRATCH_DIR "1.data", 0666);
1389*d57664e9SAndroid Build Coastguard Worker if (dataStreamFD == -1) {
1390*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "error creating: %s\n", strerror(errno));
1391*d57664e9SAndroid Build Coastguard Worker return errno;
1392*d57664e9SAndroid Build Coastguard Worker }
1393*d57664e9SAndroid Build Coastguard Worker
1394*d57664e9SAndroid Build Coastguard Worker newSnapshotFD = creat(SCRATCH_DIR "before.snap", 0666);
1395*d57664e9SAndroid Build Coastguard Worker if (newSnapshotFD == -1) {
1396*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "error creating: %s\n", strerror(errno));
1397*d57664e9SAndroid Build Coastguard Worker return errno;
1398*d57664e9SAndroid Build Coastguard Worker }
1399*d57664e9SAndroid Build Coastguard Worker
1400*d57664e9SAndroid Build Coastguard Worker {
1401*d57664e9SAndroid Build Coastguard Worker BackupDataWriter dataStream(dataStreamFD);
1402*d57664e9SAndroid Build Coastguard Worker
1403*d57664e9SAndroid Build Coastguard Worker err = back_up_files(-1, &dataStream, newSnapshotFD, files_before, keys_before, 5);
1404*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
1405*d57664e9SAndroid Build Coastguard Worker return err;
1406*d57664e9SAndroid Build Coastguard Worker }
1407*d57664e9SAndroid Build Coastguard Worker }
1408*d57664e9SAndroid Build Coastguard Worker
1409*d57664e9SAndroid Build Coastguard Worker close(dataStreamFD);
1410*d57664e9SAndroid Build Coastguard Worker close(newSnapshotFD);
1411*d57664e9SAndroid Build Coastguard Worker
1412*d57664e9SAndroid Build Coastguard Worker sleep(3);
1413*d57664e9SAndroid Build Coastguard Worker
1414*d57664e9SAndroid Build Coastguard Worker struct timeval d_times[2];
1415*d57664e9SAndroid Build Coastguard Worker struct timeval e_times[2];
1416*d57664e9SAndroid Build Coastguard Worker
1417*d57664e9SAndroid Build Coastguard Worker err = get_mod_time(SCRATCH_DIR "data/d", d_times);
1418*d57664e9SAndroid Build Coastguard Worker err |= get_mod_time(SCRATCH_DIR "data/e", e_times);
1419*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
1420*d57664e9SAndroid Build Coastguard Worker return err;
1421*d57664e9SAndroid Build Coastguard Worker }
1422*d57664e9SAndroid Build Coastguard Worker
1423*d57664e9SAndroid Build Coastguard Worker write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
1424*d57664e9SAndroid Build Coastguard Worker unlink(SCRATCH_DIR "data/c");
1425*d57664e9SAndroid Build Coastguard Worker write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
1426*d57664e9SAndroid Build Coastguard Worker write_text_file(SCRATCH_DIR "data/d", "dd\ndd\n");
1427*d57664e9SAndroid Build Coastguard Worker utimes(SCRATCH_DIR "data/d", d_times);
1428*d57664e9SAndroid Build Coastguard Worker write_text_file(SCRATCH_DIR "data/e", "z\nzz\n");
1429*d57664e9SAndroid Build Coastguard Worker utimes(SCRATCH_DIR "data/e", e_times);
1430*d57664e9SAndroid Build Coastguard Worker write_text_file(SCRATCH_DIR "data/g", "g\ngg\n");
1431*d57664e9SAndroid Build Coastguard Worker unlink(SCRATCH_DIR "data/f");
1432*d57664e9SAndroid Build Coastguard Worker
1433*d57664e9SAndroid Build Coastguard Worker char const* files_after[] = {
1434*d57664e9SAndroid Build Coastguard Worker SCRATCH_DIR "data/a", // added
1435*d57664e9SAndroid Build Coastguard Worker SCRATCH_DIR "data/b", // same
1436*d57664e9SAndroid Build Coastguard Worker SCRATCH_DIR "data/c", // different mod time
1437*d57664e9SAndroid Build Coastguard Worker SCRATCH_DIR "data/d", // different size (same mod time)
1438*d57664e9SAndroid Build Coastguard Worker SCRATCH_DIR "data/e", // different contents (same mod time, same size)
1439*d57664e9SAndroid Build Coastguard Worker SCRATCH_DIR "data/g" // added
1440*d57664e9SAndroid Build Coastguard Worker };
1441*d57664e9SAndroid Build Coastguard Worker
1442*d57664e9SAndroid Build Coastguard Worker char const* keys_after[] = {
1443*d57664e9SAndroid Build Coastguard Worker "data/a", // added
1444*d57664e9SAndroid Build Coastguard Worker "data/b", // same
1445*d57664e9SAndroid Build Coastguard Worker "data/c", // different mod time
1446*d57664e9SAndroid Build Coastguard Worker "data/d", // different size (same mod time)
1447*d57664e9SAndroid Build Coastguard Worker "data/e", // different contents (same mod time, same size)
1448*d57664e9SAndroid Build Coastguard Worker "data/g" // added
1449*d57664e9SAndroid Build Coastguard Worker };
1450*d57664e9SAndroid Build Coastguard Worker
1451*d57664e9SAndroid Build Coastguard Worker oldSnapshotFD = open(SCRATCH_DIR "before.snap", O_RDONLY);
1452*d57664e9SAndroid Build Coastguard Worker if (oldSnapshotFD == -1) {
1453*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "error opening: %s\n", strerror(errno));
1454*d57664e9SAndroid Build Coastguard Worker return errno;
1455*d57664e9SAndroid Build Coastguard Worker }
1456*d57664e9SAndroid Build Coastguard Worker
1457*d57664e9SAndroid Build Coastguard Worker dataStreamFD = creat(SCRATCH_DIR "2.data", 0666);
1458*d57664e9SAndroid Build Coastguard Worker if (dataStreamFD == -1) {
1459*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "error creating: %s\n", strerror(errno));
1460*d57664e9SAndroid Build Coastguard Worker return errno;
1461*d57664e9SAndroid Build Coastguard Worker }
1462*d57664e9SAndroid Build Coastguard Worker
1463*d57664e9SAndroid Build Coastguard Worker newSnapshotFD = creat(SCRATCH_DIR "after.snap", 0666);
1464*d57664e9SAndroid Build Coastguard Worker if (newSnapshotFD == -1) {
1465*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "error creating: %s\n", strerror(errno));
1466*d57664e9SAndroid Build Coastguard Worker return errno;
1467*d57664e9SAndroid Build Coastguard Worker }
1468*d57664e9SAndroid Build Coastguard Worker
1469*d57664e9SAndroid Build Coastguard Worker {
1470*d57664e9SAndroid Build Coastguard Worker BackupDataWriter dataStream(dataStreamFD);
1471*d57664e9SAndroid Build Coastguard Worker
1472*d57664e9SAndroid Build Coastguard Worker err = back_up_files(oldSnapshotFD, &dataStream, newSnapshotFD, files_after, keys_after, 6);
1473*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
1474*d57664e9SAndroid Build Coastguard Worker return err;
1475*d57664e9SAndroid Build Coastguard Worker }
1476*d57664e9SAndroid Build Coastguard Worker }
1477*d57664e9SAndroid Build Coastguard Worker
1478*d57664e9SAndroid Build Coastguard Worker close(oldSnapshotFD);
1479*d57664e9SAndroid Build Coastguard Worker close(dataStreamFD);
1480*d57664e9SAndroid Build Coastguard Worker close(newSnapshotFD);
1481*d57664e9SAndroid Build Coastguard Worker
1482*d57664e9SAndroid Build Coastguard Worker return 0;
1483*d57664e9SAndroid Build Coastguard Worker }
1484*d57664e9SAndroid Build Coastguard Worker
1485*d57664e9SAndroid Build Coastguard Worker int
backup_helper_test_null_base()1486*d57664e9SAndroid Build Coastguard Worker backup_helper_test_null_base()
1487*d57664e9SAndroid Build Coastguard Worker {
1488*d57664e9SAndroid Build Coastguard Worker int err;
1489*d57664e9SAndroid Build Coastguard Worker int dataStreamFD;
1490*d57664e9SAndroid Build Coastguard Worker int newSnapshotFD;
1491*d57664e9SAndroid Build Coastguard Worker
1492*d57664e9SAndroid Build Coastguard Worker system("rm -r " SCRATCH_DIR);
1493*d57664e9SAndroid Build Coastguard Worker mkdir(SCRATCH_DIR, 0777);
1494*d57664e9SAndroid Build Coastguard Worker mkdir(SCRATCH_DIR "data", 0777);
1495*d57664e9SAndroid Build Coastguard Worker
1496*d57664e9SAndroid Build Coastguard Worker write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
1497*d57664e9SAndroid Build Coastguard Worker
1498*d57664e9SAndroid Build Coastguard Worker char const* files[] = {
1499*d57664e9SAndroid Build Coastguard Worker SCRATCH_DIR "data/a",
1500*d57664e9SAndroid Build Coastguard Worker };
1501*d57664e9SAndroid Build Coastguard Worker
1502*d57664e9SAndroid Build Coastguard Worker char const* keys[] = {
1503*d57664e9SAndroid Build Coastguard Worker "a",
1504*d57664e9SAndroid Build Coastguard Worker };
1505*d57664e9SAndroid Build Coastguard Worker
1506*d57664e9SAndroid Build Coastguard Worker dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
1507*d57664e9SAndroid Build Coastguard Worker if (dataStreamFD == -1) {
1508*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "error creating: %s\n", strerror(errno));
1509*d57664e9SAndroid Build Coastguard Worker return errno;
1510*d57664e9SAndroid Build Coastguard Worker }
1511*d57664e9SAndroid Build Coastguard Worker
1512*d57664e9SAndroid Build Coastguard Worker newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
1513*d57664e9SAndroid Build Coastguard Worker if (newSnapshotFD == -1) {
1514*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "error creating: %s\n", strerror(errno));
1515*d57664e9SAndroid Build Coastguard Worker return errno;
1516*d57664e9SAndroid Build Coastguard Worker }
1517*d57664e9SAndroid Build Coastguard Worker
1518*d57664e9SAndroid Build Coastguard Worker {
1519*d57664e9SAndroid Build Coastguard Worker BackupDataWriter dataStream(dataStreamFD);
1520*d57664e9SAndroid Build Coastguard Worker
1521*d57664e9SAndroid Build Coastguard Worker err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
1522*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
1523*d57664e9SAndroid Build Coastguard Worker return err;
1524*d57664e9SAndroid Build Coastguard Worker }
1525*d57664e9SAndroid Build Coastguard Worker }
1526*d57664e9SAndroid Build Coastguard Worker
1527*d57664e9SAndroid Build Coastguard Worker close(dataStreamFD);
1528*d57664e9SAndroid Build Coastguard Worker close(newSnapshotFD);
1529*d57664e9SAndroid Build Coastguard Worker
1530*d57664e9SAndroid Build Coastguard Worker return 0;
1531*d57664e9SAndroid Build Coastguard Worker }
1532*d57664e9SAndroid Build Coastguard Worker
1533*d57664e9SAndroid Build Coastguard Worker int
backup_helper_test_missing_file()1534*d57664e9SAndroid Build Coastguard Worker backup_helper_test_missing_file()
1535*d57664e9SAndroid Build Coastguard Worker {
1536*d57664e9SAndroid Build Coastguard Worker int err;
1537*d57664e9SAndroid Build Coastguard Worker int dataStreamFD;
1538*d57664e9SAndroid Build Coastguard Worker int newSnapshotFD;
1539*d57664e9SAndroid Build Coastguard Worker
1540*d57664e9SAndroid Build Coastguard Worker system("rm -r " SCRATCH_DIR);
1541*d57664e9SAndroid Build Coastguard Worker mkdir(SCRATCH_DIR, 0777);
1542*d57664e9SAndroid Build Coastguard Worker mkdir(SCRATCH_DIR "data", 0777);
1543*d57664e9SAndroid Build Coastguard Worker
1544*d57664e9SAndroid Build Coastguard Worker write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
1545*d57664e9SAndroid Build Coastguard Worker
1546*d57664e9SAndroid Build Coastguard Worker char const* files[] = {
1547*d57664e9SAndroid Build Coastguard Worker SCRATCH_DIR "data/a",
1548*d57664e9SAndroid Build Coastguard Worker SCRATCH_DIR "data/b",
1549*d57664e9SAndroid Build Coastguard Worker SCRATCH_DIR "data/c",
1550*d57664e9SAndroid Build Coastguard Worker };
1551*d57664e9SAndroid Build Coastguard Worker
1552*d57664e9SAndroid Build Coastguard Worker char const* keys[] = {
1553*d57664e9SAndroid Build Coastguard Worker "a",
1554*d57664e9SAndroid Build Coastguard Worker "b",
1555*d57664e9SAndroid Build Coastguard Worker "c",
1556*d57664e9SAndroid Build Coastguard Worker };
1557*d57664e9SAndroid Build Coastguard Worker
1558*d57664e9SAndroid Build Coastguard Worker dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
1559*d57664e9SAndroid Build Coastguard Worker if (dataStreamFD == -1) {
1560*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "error creating: %s\n", strerror(errno));
1561*d57664e9SAndroid Build Coastguard Worker return errno;
1562*d57664e9SAndroid Build Coastguard Worker }
1563*d57664e9SAndroid Build Coastguard Worker
1564*d57664e9SAndroid Build Coastguard Worker newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
1565*d57664e9SAndroid Build Coastguard Worker if (newSnapshotFD == -1) {
1566*d57664e9SAndroid Build Coastguard Worker fprintf(stderr, "error creating: %s\n", strerror(errno));
1567*d57664e9SAndroid Build Coastguard Worker return errno;
1568*d57664e9SAndroid Build Coastguard Worker }
1569*d57664e9SAndroid Build Coastguard Worker
1570*d57664e9SAndroid Build Coastguard Worker {
1571*d57664e9SAndroid Build Coastguard Worker BackupDataWriter dataStream(dataStreamFD);
1572*d57664e9SAndroid Build Coastguard Worker
1573*d57664e9SAndroid Build Coastguard Worker err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
1574*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
1575*d57664e9SAndroid Build Coastguard Worker return err;
1576*d57664e9SAndroid Build Coastguard Worker }
1577*d57664e9SAndroid Build Coastguard Worker }
1578*d57664e9SAndroid Build Coastguard Worker
1579*d57664e9SAndroid Build Coastguard Worker close(dataStreamFD);
1580*d57664e9SAndroid Build Coastguard Worker close(newSnapshotFD);
1581*d57664e9SAndroid Build Coastguard Worker
1582*d57664e9SAndroid Build Coastguard Worker return 0;
1583*d57664e9SAndroid Build Coastguard Worker }
1584*d57664e9SAndroid Build Coastguard Worker
1585*d57664e9SAndroid Build Coastguard Worker
1586*d57664e9SAndroid Build Coastguard Worker #endif // TEST_BACKUP_HELPERS
1587*d57664e9SAndroid Build Coastguard Worker
1588*d57664e9SAndroid Build Coastguard Worker }
1589