blob: bd9dc767c36034a28d142eca8141134fde7849d3 [file] [log] [blame]
Joe Onorato4535e402009-05-15 09:07:06 -04001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Joe Onorato2e1da322009-05-15 18:20:19 -040017#define LOG_TAG "backup_data"
18
Mathias Agopianb13b9bd2012-02-17 18:27:36 -080019#include <androidfw/BackupHelpers.h>
Joe Onorato4535e402009-05-15 09:07:06 -040020#include <utils/ByteOrder.h>
21
22#include <stdio.h>
Christopher Tate4a627c72011-04-01 14:43:32 -070023#include <string.h>
Joe Onorato4535e402009-05-15 09:07:06 -040024#include <unistd.h>
25
Joe Onorato2e1da322009-05-15 18:20:19 -040026#include <cutils/log.h>
27
Joe Onorato4535e402009-05-15 09:07:06 -040028namespace android {
29
Christopher Tate4a627c72011-04-01 14:43:32 -070030static const bool DEBUG = false;
31
Joe Onorato4535e402009-05-15 09:07:06 -040032/*
33 * File Format (v1):
34 *
35 * All ints are stored little-endian.
36 *
37 * - An app_header_v1 struct.
38 * - The name of the package, utf-8, null terminated, padded to 4-byte boundary.
39 * - A sequence of zero or more key/value paires (entities), each with
40 * - A entity_header_v1 struct
41 * - The key, utf-8, null terminated, padded to 4-byte boundary.
42 * - The value, padded to 4 byte boundary
43 */
44
Joe Onorato4535e402009-05-15 09:07:06 -040045const static int ROUND_UP[4] = { 0, 3, 2, 1 };
46
47static inline size_t
48round_up(size_t n)
49{
50 return n + ROUND_UP[n % 4];
51}
52
53static inline size_t
54padding_extra(size_t n)
55{
56 return ROUND_UP[n % 4];
57}
58
59BackupDataWriter::BackupDataWriter(int fd)
60 :m_fd(fd),
61 m_status(NO_ERROR),
62 m_pos(0),
63 m_entityCount(0)
64{
65}
66
67BackupDataWriter::~BackupDataWriter()
68{
69}
70
71// Pad out anything they've previously written to the next 4 byte boundary.
72status_t
73BackupDataWriter::write_padding_for(int n)
74{
75 ssize_t amt;
76 ssize_t paddingSize;
77
78 paddingSize = padding_extra(n);
79 if (paddingSize > 0) {
80 uint32_t padding = 0xbcbcbcbc;
Ashok Bhatf5df7002014-03-25 20:51:35 +000081 if (DEBUG) ALOGI("writing %zd padding bytes for %d", paddingSize, n);
Joe Onorato4535e402009-05-15 09:07:06 -040082 amt = write(m_fd, &padding, paddingSize);
83 if (amt != paddingSize) {
84 m_status = errno;
85 return m_status;
86 }
87 m_pos += amt;
88 }
89 return NO_ERROR;
90}
91
92status_t
Joe Onorato4535e402009-05-15 09:07:06 -040093BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize)
94{
95 if (m_status != NO_ERROR) {
96 return m_status;
97 }
98
99 ssize_t amt;
100
101 amt = write_padding_for(m_pos);
102 if (amt != 0) {
103 return amt;
104 }
105
Joe Onorato06290a42009-06-18 20:10:37 -0700106 String8 k;
107 if (m_keyPrefix.length() > 0) {
108 k = m_keyPrefix;
109 k += ":";
110 k += key;
111 } else {
112 k = key;
113 }
Christopher Tate4a627c72011-04-01 14:43:32 -0700114 if (DEBUG) {
Ashok Bhatf5df7002014-03-25 20:51:35 +0000115 ALOGD("Writing header: prefix='%s' key='%s' dataSize=%zu", m_keyPrefix.string(),
Steve Block5baa3a62011-12-20 16:23:08 +0000116 key.string(), dataSize);
Joe Onorato568bc322009-06-26 17:19:11 -0400117 }
Joe Onorato06290a42009-06-18 20:10:37 -0700118
Joe Onorato4535e402009-05-15 09:07:06 -0400119 entity_header_v1 header;
120 ssize_t keyLen;
121
Joe Onorato06290a42009-06-18 20:10:37 -0700122 keyLen = k.length();
Joe Onorato4535e402009-05-15 09:07:06 -0400123
Joe Onoratod2110db2009-05-19 13:41:21 -0700124 header.type = tolel(BACKUP_HEADER_ENTITY_V1);
Joe Onorato4535e402009-05-15 09:07:06 -0400125 header.keyLen = tolel(keyLen);
126 header.dataSize = tolel(dataSize);
127
Ashok Bhatf5df7002014-03-25 20:51:35 +0000128 if (DEBUG) ALOGI("writing entity header, %zu bytes", sizeof(entity_header_v1));
Joe Onorato4535e402009-05-15 09:07:06 -0400129 amt = write(m_fd, &header, sizeof(entity_header_v1));
130 if (amt != sizeof(entity_header_v1)) {
131 m_status = errno;
132 return m_status;
133 }
134 m_pos += amt;
135
Ashok Bhatf5df7002014-03-25 20:51:35 +0000136 if (DEBUG) ALOGI("writing entity header key, %zd bytes", keyLen+1);
Joe Onorato06290a42009-06-18 20:10:37 -0700137 amt = write(m_fd, k.string(), keyLen+1);
Joe Onorato4535e402009-05-15 09:07:06 -0400138 if (amt != keyLen+1) {
139 m_status = errno;
140 return m_status;
141 }
142 m_pos += amt;
143
144 amt = write_padding_for(keyLen+1);
145
146 m_entityCount++;
147
148 return amt;
149}
150
151status_t
152BackupDataWriter::WriteEntityData(const void* data, size_t size)
153{
Steve Block5baa3a62011-12-20 16:23:08 +0000154 if (DEBUG) ALOGD("Writing data: size=%lu", (unsigned long) size);
Christopher Tate4a627c72011-04-01 14:43:32 -0700155
Joe Onorato4535e402009-05-15 09:07:06 -0400156 if (m_status != NO_ERROR) {
Christopher Tate4a627c72011-04-01 14:43:32 -0700157 if (DEBUG) {
Steve Block5baa3a62011-12-20 16:23:08 +0000158 ALOGD("Not writing data - stream in error state %d (%s)", m_status, strerror(m_status));
Christopher Tate4a627c72011-04-01 14:43:32 -0700159 }
Joe Onorato4535e402009-05-15 09:07:06 -0400160 return m_status;
161 }
162
163 // We don't write padding here, because they're allowed to call this several
164 // times with smaller buffers. We write it at the end of WriteEntityHeader
165 // instead.
166 ssize_t amt = write(m_fd, data, size);
167 if (amt != (ssize_t)size) {
168 m_status = errno;
Steve Block5baa3a62011-12-20 16:23:08 +0000169 if (DEBUG) ALOGD("write returned error %d (%s)", m_status, strerror(m_status));
Joe Onorato4535e402009-05-15 09:07:06 -0400170 return m_status;
171 }
172 m_pos += amt;
173 return NO_ERROR;
174}
175
Joe Onorato06290a42009-06-18 20:10:37 -0700176void
177BackupDataWriter::SetKeyPrefix(const String8& keyPrefix)
178{
179 m_keyPrefix = keyPrefix;
180}
Joe Onorato4535e402009-05-15 09:07:06 -0400181
Joe Onorato2e1da322009-05-15 18:20:19 -0400182
183BackupDataReader::BackupDataReader(int fd)
184 :m_fd(fd),
Joe Onorato5f15d152009-06-16 16:31:35 -0400185 m_done(false),
Joe Onorato2e1da322009-05-15 18:20:19 -0400186 m_status(NO_ERROR),
187 m_pos(0),
188 m_entityCount(0)
189{
190 memset(&m_header, 0, sizeof(m_header));
191}
192
193BackupDataReader::~BackupDataReader()
194{
195}
196
197status_t
198BackupDataReader::Status()
199{
200 return m_status;
201}
202
203#define CHECK_SIZE(actual, expected) \
204 do { \
205 if ((actual) != (expected)) { \
206 if ((actual) == 0) { \
207 m_status = EIO; \
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700208 m_done = true; \
Joe Onorato2e1da322009-05-15 18:20:19 -0400209 } else { \
210 m_status = errno; \
Steve Block5baa3a62011-12-20 16:23:08 +0000211 ALOGD("CHECK_SIZE(a=%ld e=%ld) failed at line %d m_status='%s'", \
Christopher Tate4cc86e12009-09-21 19:36:51 -0700212 long(actual), long(expected), __LINE__, strerror(m_status)); \
Joe Onorato2e1da322009-05-15 18:20:19 -0400213 } \
214 return m_status; \
215 } \
216 } while(0)
217#define SKIP_PADDING() \
218 do { \
219 status_t err = skip_padding(); \
220 if (err != NO_ERROR) { \
Steve Block5baa3a62011-12-20 16:23:08 +0000221 ALOGD("SKIP_PADDING FAILED at line %d", __LINE__); \
Joe Onorato2e1da322009-05-15 18:20:19 -0400222 m_status = err; \
223 return err; \
224 } \
225 } while(0)
226
227status_t
Joe Onorato5f15d152009-06-16 16:31:35 -0400228BackupDataReader::ReadNextHeader(bool* done, int* type)
Joe Onorato2e1da322009-05-15 18:20:19 -0400229{
Joe Onorato5f15d152009-06-16 16:31:35 -0400230 *done = m_done;
Joe Onorato2e1da322009-05-15 18:20:19 -0400231 if (m_status != NO_ERROR) {
232 return m_status;
233 }
234
235 int amt;
236
Joe Onorato8d725692009-07-28 18:23:05 -0700237 amt = skip_padding();
238 if (amt == EIO) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700239 *done = m_done = true;
Joe Onorato8d725692009-07-28 18:23:05 -0700240 return NO_ERROR;
241 }
242 else if (amt != NO_ERROR) {
243 return amt;
244 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400245 amt = read(m_fd, &m_header, sizeof(m_header));
Joe Onorato5f15d152009-06-16 16:31:35 -0400246 *done = m_done = (amt == 0);
Joe Onorato8d725692009-07-28 18:23:05 -0700247 if (*done) {
248 return NO_ERROR;
249 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400250 CHECK_SIZE(amt, sizeof(m_header));
Joe Onorato5d605dc2009-06-18 18:23:43 -0700251 m_pos += sizeof(m_header);
252 if (type) {
253 *type = m_header.type;
254 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400255
256 // validate and fix up the fields.
257 m_header.type = fromlel(m_header.type);
258 switch (m_header.type)
259 {
Joe Onoratod2110db2009-05-19 13:41:21 -0700260 case BACKUP_HEADER_ENTITY_V1:
Joe Onorato5d605dc2009-06-18 18:23:43 -0700261 {
Joe Onorato2e1da322009-05-15 18:20:19 -0400262 m_header.entity.keyLen = fromlel(m_header.entity.keyLen);
263 if (m_header.entity.keyLen <= 0) {
Steve Block5baa3a62011-12-20 16:23:08 +0000264 ALOGD("Entity header at %d has keyLen<=0: 0x%08x\n", (int)m_pos,
Joe Onorato2e1da322009-05-15 18:20:19 -0400265 (int)m_header.entity.keyLen);
266 m_status = EINVAL;
267 }
268 m_header.entity.dataSize = fromlel(m_header.entity.dataSize);
Joe Onorato2e1da322009-05-15 18:20:19 -0400269 m_entityCount++;
Joe Onorato5d605dc2009-06-18 18:23:43 -0700270
271 // read the rest of the header (filename)
272 size_t size = m_header.entity.keyLen;
273 char* buf = m_key.lockBuffer(size);
274 if (buf == NULL) {
275 m_status = ENOMEM;
276 return m_status;
277 }
278 int amt = read(m_fd, buf, size+1);
279 CHECK_SIZE(amt, (int)size+1);
280 m_key.unlockBuffer(size);
281 m_pos += size+1;
282 SKIP_PADDING();
283 m_dataEndPos = m_pos + m_header.entity.dataSize;
284
Joe Onorato2e1da322009-05-15 18:20:19 -0400285 break;
Joe Onorato5d605dc2009-06-18 18:23:43 -0700286 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400287 default:
Steve Block5baa3a62011-12-20 16:23:08 +0000288 ALOGD("Chunk header at %d has invalid type: 0x%08x",
Christopher Tate28cdb9e2011-06-24 15:06:48 -0700289 (int)(m_pos - sizeof(m_header)), (int)m_header.type);
Joe Onorato2e1da322009-05-15 18:20:19 -0400290 m_status = EINVAL;
291 }
Mark Salyzyn00adb862014-03-19 11:00:06 -0700292
Joe Onorato2e1da322009-05-15 18:20:19 -0400293 return m_status;
294}
295
Joe Onorato2e1da322009-05-15 18:20:19 -0400296bool
297BackupDataReader::HasEntities()
298{
Joe Onoratod2110db2009-05-19 13:41:21 -0700299 return m_status == NO_ERROR && m_header.type == BACKUP_HEADER_ENTITY_V1;
Joe Onorato2e1da322009-05-15 18:20:19 -0400300}
301
302status_t
303BackupDataReader::ReadEntityHeader(String8* key, size_t* dataSize)
304{
305 if (m_status != NO_ERROR) {
306 return m_status;
307 }
Joe Onoratod2110db2009-05-19 13:41:21 -0700308 if (m_header.type != BACKUP_HEADER_ENTITY_V1) {
Joe Onorato2e1da322009-05-15 18:20:19 -0400309 return EINVAL;
310 }
Joe Onorato5d605dc2009-06-18 18:23:43 -0700311 *key = m_key;
Joe Onorato2e1da322009-05-15 18:20:19 -0400312 *dataSize = m_header.entity.dataSize;
Joe Onorato2e1da322009-05-15 18:20:19 -0400313 return NO_ERROR;
314}
315
316status_t
Joe Onoratod2110db2009-05-19 13:41:21 -0700317BackupDataReader::SkipEntityData()
318{
319 if (m_status != NO_ERROR) {
320 return m_status;
321 }
322 if (m_header.type != BACKUP_HEADER_ENTITY_V1) {
323 return EINVAL;
324 }
325 if (m_header.entity.dataSize > 0) {
Joe Onorato5f15d152009-06-16 16:31:35 -0400326 int pos = lseek(m_fd, m_dataEndPos, SEEK_SET);
Joe Onoratoee5bbb72009-07-13 14:44:07 -0700327 if (pos == -1) {
328 return errno;
329 }
Christopher Tate50676852012-10-04 19:10:11 -0700330 m_pos = pos;
Joe Onoratod2110db2009-05-19 13:41:21 -0700331 }
Joe Onoratoee5bbb72009-07-13 14:44:07 -0700332 SKIP_PADDING();
333 return NO_ERROR;
Joe Onoratod2110db2009-05-19 13:41:21 -0700334}
335
Joe Onoratoefd0fab2009-06-17 16:20:55 -0700336ssize_t
Joe Onorato2e1da322009-05-15 18:20:19 -0400337BackupDataReader::ReadEntityData(void* data, size_t size)
338{
339 if (m_status != NO_ERROR) {
Joe Onorato5d605dc2009-06-18 18:23:43 -0700340 return -1;
Joe Onorato2e1da322009-05-15 18:20:19 -0400341 }
Joe Onorato5f15d152009-06-16 16:31:35 -0400342 int remaining = m_dataEndPos - m_pos;
Steve Block5baa3a62011-12-20 16:23:08 +0000343 //ALOGD("ReadEntityData size=%d m_pos=0x%x m_dataEndPos=0x%x remaining=%d\n",
Joe Onoratoefd0fab2009-06-17 16:20:55 -0700344 // size, m_pos, m_dataEndPos, remaining);
Joe Onorato5f15d152009-06-16 16:31:35 -0400345 if (remaining <= 0) {
346 return 0;
347 }
Joe Onorato06290a42009-06-18 20:10:37 -0700348 if (((int)size) > remaining) {
Joe Onorato5d605dc2009-06-18 18:23:43 -0700349 size = remaining;
350 }
Steve Block5baa3a62011-12-20 16:23:08 +0000351 //ALOGD(" reading %d bytes", size);
Joe Onorato2e1da322009-05-15 18:20:19 -0400352 int amt = read(m_fd, data, size);
Joe Onorato5d605dc2009-06-18 18:23:43 -0700353 if (amt < 0) {
354 m_status = errno;
355 return -1;
356 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700357 if (amt == 0) {
358 m_status = EIO;
359 m_done = true;
360 }
Joe Onorato5d605dc2009-06-18 18:23:43 -0700361 m_pos += amt;
Joe Onoratoefd0fab2009-06-17 16:20:55 -0700362 return amt;
Joe Onorato2e1da322009-05-15 18:20:19 -0400363}
364
365status_t
Joe Onorato2e1da322009-05-15 18:20:19 -0400366BackupDataReader::skip_padding()
367{
368 ssize_t amt;
369 ssize_t paddingSize;
370
371 paddingSize = padding_extra(m_pos);
372 if (paddingSize > 0) {
373 uint32_t padding;
374 amt = read(m_fd, &padding, paddingSize);
375 CHECK_SIZE(amt, paddingSize);
376 m_pos += amt;
377 }
378 return NO_ERROR;
379}
380
381
Joe Onorato4535e402009-05-15 09:07:06 -0400382} // namespace android