blob: adb3174990a4e081f3d2e5faf35c49bf13aa5951 [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 Agopian8ae23352009-06-04 13:53:57 -070019#include <utils/BackupHelpers.h>
Joe Onorato4535e402009-05-15 09:07:06 -040020#include <utils/ByteOrder.h>
21
22#include <stdio.h>
23#include <unistd.h>
24
Joe Onorato2e1da322009-05-15 18:20:19 -040025#include <cutils/log.h>
26
Joe Onorato4535e402009-05-15 09:07:06 -040027namespace android {
28
29/*
30 * File Format (v1):
31 *
32 * All ints are stored little-endian.
33 *
34 * - An app_header_v1 struct.
35 * - The name of the package, utf-8, null terminated, padded to 4-byte boundary.
36 * - A sequence of zero or more key/value paires (entities), each with
37 * - A entity_header_v1 struct
38 * - The key, utf-8, null terminated, padded to 4-byte boundary.
39 * - The value, padded to 4 byte boundary
40 */
41
Joe Onorato4535e402009-05-15 09:07:06 -040042const static int ROUND_UP[4] = { 0, 3, 2, 1 };
43
44static inline size_t
45round_up(size_t n)
46{
47 return n + ROUND_UP[n % 4];
48}
49
50static inline size_t
51padding_extra(size_t n)
52{
53 return ROUND_UP[n % 4];
54}
55
56BackupDataWriter::BackupDataWriter(int fd)
57 :m_fd(fd),
58 m_status(NO_ERROR),
59 m_pos(0),
60 m_entityCount(0)
61{
62}
63
64BackupDataWriter::~BackupDataWriter()
65{
66}
67
68// Pad out anything they've previously written to the next 4 byte boundary.
69status_t
70BackupDataWriter::write_padding_for(int n)
71{
72 ssize_t amt;
73 ssize_t paddingSize;
74
75 paddingSize = padding_extra(n);
76 if (paddingSize > 0) {
77 uint32_t padding = 0xbcbcbcbc;
78 amt = write(m_fd, &padding, paddingSize);
79 if (amt != paddingSize) {
80 m_status = errno;
81 return m_status;
82 }
83 m_pos += amt;
84 }
85 return NO_ERROR;
86}
87
88status_t
Joe Onorato4535e402009-05-15 09:07:06 -040089BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize)
90{
91 if (m_status != NO_ERROR) {
92 return m_status;
93 }
94
95 ssize_t amt;
96
97 amt = write_padding_for(m_pos);
98 if (amt != 0) {
99 return amt;
100 }
101
Joe Onorato06290a42009-06-18 20:10:37 -0700102 String8 k;
103 if (m_keyPrefix.length() > 0) {
104 k = m_keyPrefix;
105 k += ":";
106 k += key;
107 } else {
108 k = key;
109 }
Christopher Tate436344a2009-09-30 16:17:37 -0700110 if (false) {
Joe Onorato568bc322009-06-26 17:19:11 -0400111 LOGD("Writing entity: prefix='%s' key='%s' dataSize=%d", m_keyPrefix.string(), key.string(),
112 dataSize);
113 }
Joe Onorato06290a42009-06-18 20:10:37 -0700114
Joe Onorato4535e402009-05-15 09:07:06 -0400115 entity_header_v1 header;
116 ssize_t keyLen;
117
Joe Onorato06290a42009-06-18 20:10:37 -0700118 keyLen = k.length();
Joe Onorato4535e402009-05-15 09:07:06 -0400119
Joe Onoratod2110db2009-05-19 13:41:21 -0700120 header.type = tolel(BACKUP_HEADER_ENTITY_V1);
Joe Onorato4535e402009-05-15 09:07:06 -0400121 header.keyLen = tolel(keyLen);
122 header.dataSize = tolel(dataSize);
123
124 amt = write(m_fd, &header, sizeof(entity_header_v1));
125 if (amt != sizeof(entity_header_v1)) {
126 m_status = errno;
127 return m_status;
128 }
129 m_pos += amt;
130
Joe Onorato06290a42009-06-18 20:10:37 -0700131 amt = write(m_fd, k.string(), keyLen+1);
Joe Onorato4535e402009-05-15 09:07:06 -0400132 if (amt != keyLen+1) {
133 m_status = errno;
134 return m_status;
135 }
136 m_pos += amt;
137
138 amt = write_padding_for(keyLen+1);
139
140 m_entityCount++;
141
142 return amt;
143}
144
145status_t
146BackupDataWriter::WriteEntityData(const void* data, size_t size)
147{
148 if (m_status != NO_ERROR) {
149 return m_status;
150 }
151
152 // We don't write padding here, because they're allowed to call this several
153 // times with smaller buffers. We write it at the end of WriteEntityHeader
154 // instead.
155 ssize_t amt = write(m_fd, data, size);
156 if (amt != (ssize_t)size) {
157 m_status = errno;
158 return m_status;
159 }
160 m_pos += amt;
161 return NO_ERROR;
162}
163
Joe Onorato06290a42009-06-18 20:10:37 -0700164void
165BackupDataWriter::SetKeyPrefix(const String8& keyPrefix)
166{
167 m_keyPrefix = keyPrefix;
168}
Joe Onorato4535e402009-05-15 09:07:06 -0400169
Joe Onorato2e1da322009-05-15 18:20:19 -0400170
171BackupDataReader::BackupDataReader(int fd)
172 :m_fd(fd),
Joe Onorato5f15d152009-06-16 16:31:35 -0400173 m_done(false),
Joe Onorato2e1da322009-05-15 18:20:19 -0400174 m_status(NO_ERROR),
175 m_pos(0),
176 m_entityCount(0)
177{
178 memset(&m_header, 0, sizeof(m_header));
179}
180
181BackupDataReader::~BackupDataReader()
182{
183}
184
185status_t
186BackupDataReader::Status()
187{
188 return m_status;
189}
190
191#define CHECK_SIZE(actual, expected) \
192 do { \
193 if ((actual) != (expected)) { \
194 if ((actual) == 0) { \
195 m_status = EIO; \
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700196 m_done = true; \
Joe Onorato2e1da322009-05-15 18:20:19 -0400197 } else { \
198 m_status = errno; \
Christopher Tate4cc86e12009-09-21 19:36:51 -0700199 LOGD("CHECK_SIZE(a=%ld e=%ld) failed at line %d m_status='%s'", \
200 long(actual), long(expected), __LINE__, strerror(m_status)); \
Joe Onorato2e1da322009-05-15 18:20:19 -0400201 } \
202 return m_status; \
203 } \
204 } while(0)
205#define SKIP_PADDING() \
206 do { \
207 status_t err = skip_padding(); \
208 if (err != NO_ERROR) { \
Joe Onorato8d725692009-07-28 18:23:05 -0700209 LOGD("SKIP_PADDING FAILED at line %d", __LINE__); \
Joe Onorato2e1da322009-05-15 18:20:19 -0400210 m_status = err; \
211 return err; \
212 } \
213 } while(0)
214
215status_t
Joe Onorato5f15d152009-06-16 16:31:35 -0400216BackupDataReader::ReadNextHeader(bool* done, int* type)
Joe Onorato2e1da322009-05-15 18:20:19 -0400217{
Joe Onorato5f15d152009-06-16 16:31:35 -0400218 *done = m_done;
Joe Onorato2e1da322009-05-15 18:20:19 -0400219 if (m_status != NO_ERROR) {
220 return m_status;
221 }
222
223 int amt;
224
Joe Onorato8d725692009-07-28 18:23:05 -0700225 amt = skip_padding();
226 if (amt == EIO) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700227 *done = m_done = true;
Joe Onorato8d725692009-07-28 18:23:05 -0700228 return NO_ERROR;
229 }
230 else if (amt != NO_ERROR) {
231 return amt;
232 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400233 amt = read(m_fd, &m_header, sizeof(m_header));
Joe Onorato5f15d152009-06-16 16:31:35 -0400234 *done = m_done = (amt == 0);
Joe Onorato8d725692009-07-28 18:23:05 -0700235 if (*done) {
236 return NO_ERROR;
237 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400238 CHECK_SIZE(amt, sizeof(m_header));
Joe Onorato5d605dc2009-06-18 18:23:43 -0700239 m_pos += sizeof(m_header);
240 if (type) {
241 *type = m_header.type;
242 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400243
244 // validate and fix up the fields.
245 m_header.type = fromlel(m_header.type);
246 switch (m_header.type)
247 {
Joe Onoratod2110db2009-05-19 13:41:21 -0700248 case BACKUP_HEADER_ENTITY_V1:
Joe Onorato5d605dc2009-06-18 18:23:43 -0700249 {
Joe Onorato2e1da322009-05-15 18:20:19 -0400250 m_header.entity.keyLen = fromlel(m_header.entity.keyLen);
251 if (m_header.entity.keyLen <= 0) {
252 LOGD("Entity header at %d has keyLen<=0: 0x%08x\n", (int)m_pos,
253 (int)m_header.entity.keyLen);
254 m_status = EINVAL;
255 }
256 m_header.entity.dataSize = fromlel(m_header.entity.dataSize);
Joe Onorato2e1da322009-05-15 18:20:19 -0400257 m_entityCount++;
Joe Onorato5d605dc2009-06-18 18:23:43 -0700258
259 // read the rest of the header (filename)
260 size_t size = m_header.entity.keyLen;
261 char* buf = m_key.lockBuffer(size);
262 if (buf == NULL) {
263 m_status = ENOMEM;
264 return m_status;
265 }
266 int amt = read(m_fd, buf, size+1);
267 CHECK_SIZE(amt, (int)size+1);
268 m_key.unlockBuffer(size);
269 m_pos += size+1;
270 SKIP_PADDING();
271 m_dataEndPos = m_pos + m_header.entity.dataSize;
272
Joe Onorato2e1da322009-05-15 18:20:19 -0400273 break;
Joe Onorato5d605dc2009-06-18 18:23:43 -0700274 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400275 default:
276 LOGD("Chunk header at %d has invalid type: 0x%08x", (int)m_pos, (int)m_header.type);
277 m_status = EINVAL;
278 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400279
280 return m_status;
281}
282
Joe Onorato2e1da322009-05-15 18:20:19 -0400283bool
284BackupDataReader::HasEntities()
285{
Joe Onoratod2110db2009-05-19 13:41:21 -0700286 return m_status == NO_ERROR && m_header.type == BACKUP_HEADER_ENTITY_V1;
Joe Onorato2e1da322009-05-15 18:20:19 -0400287}
288
289status_t
290BackupDataReader::ReadEntityHeader(String8* key, size_t* dataSize)
291{
292 if (m_status != NO_ERROR) {
293 return m_status;
294 }
Joe Onoratod2110db2009-05-19 13:41:21 -0700295 if (m_header.type != BACKUP_HEADER_ENTITY_V1) {
Joe Onorato2e1da322009-05-15 18:20:19 -0400296 return EINVAL;
297 }
Joe Onorato5d605dc2009-06-18 18:23:43 -0700298 *key = m_key;
Joe Onorato2e1da322009-05-15 18:20:19 -0400299 *dataSize = m_header.entity.dataSize;
Joe Onorato2e1da322009-05-15 18:20:19 -0400300 return NO_ERROR;
301}
302
303status_t
Joe Onoratod2110db2009-05-19 13:41:21 -0700304BackupDataReader::SkipEntityData()
305{
306 if (m_status != NO_ERROR) {
307 return m_status;
308 }
309 if (m_header.type != BACKUP_HEADER_ENTITY_V1) {
310 return EINVAL;
311 }
312 if (m_header.entity.dataSize > 0) {
Joe Onorato5f15d152009-06-16 16:31:35 -0400313 int pos = lseek(m_fd, m_dataEndPos, SEEK_SET);
Joe Onoratoee5bbb72009-07-13 14:44:07 -0700314 if (pos == -1) {
315 return errno;
316 }
Joe Onoratod2110db2009-05-19 13:41:21 -0700317 }
Joe Onoratoee5bbb72009-07-13 14:44:07 -0700318 SKIP_PADDING();
319 return NO_ERROR;
Joe Onoratod2110db2009-05-19 13:41:21 -0700320}
321
Joe Onoratoefd0fab2009-06-17 16:20:55 -0700322ssize_t
Joe Onorato2e1da322009-05-15 18:20:19 -0400323BackupDataReader::ReadEntityData(void* data, size_t size)
324{
325 if (m_status != NO_ERROR) {
Joe Onorato5d605dc2009-06-18 18:23:43 -0700326 return -1;
Joe Onorato2e1da322009-05-15 18:20:19 -0400327 }
Joe Onorato5f15d152009-06-16 16:31:35 -0400328 int remaining = m_dataEndPos - m_pos;
Joe Onoratoefd0fab2009-06-17 16:20:55 -0700329 //LOGD("ReadEntityData size=%d m_pos=0x%x m_dataEndPos=0x%x remaining=%d\n",
330 // size, m_pos, m_dataEndPos, remaining);
Joe Onorato5f15d152009-06-16 16:31:35 -0400331 if (remaining <= 0) {
332 return 0;
333 }
Joe Onorato06290a42009-06-18 20:10:37 -0700334 if (((int)size) > remaining) {
Joe Onorato5d605dc2009-06-18 18:23:43 -0700335 size = remaining;
336 }
337 //LOGD(" reading %d bytes", size);
Joe Onorato2e1da322009-05-15 18:20:19 -0400338 int amt = read(m_fd, data, size);
Joe Onorato5d605dc2009-06-18 18:23:43 -0700339 if (amt < 0) {
340 m_status = errno;
341 return -1;
342 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700343 if (amt == 0) {
344 m_status = EIO;
345 m_done = true;
346 }
Joe Onorato5d605dc2009-06-18 18:23:43 -0700347 m_pos += amt;
Joe Onoratoefd0fab2009-06-17 16:20:55 -0700348 return amt;
Joe Onorato2e1da322009-05-15 18:20:19 -0400349}
350
351status_t
Joe Onorato2e1da322009-05-15 18:20:19 -0400352BackupDataReader::skip_padding()
353{
354 ssize_t amt;
355 ssize_t paddingSize;
356
357 paddingSize = padding_extra(m_pos);
358 if (paddingSize > 0) {
359 uint32_t padding;
360 amt = read(m_fd, &padding, paddingSize);
361 CHECK_SIZE(amt, paddingSize);
362 m_pos += amt;
363 }
364 return NO_ERROR;
365}
366
367
Joe Onorato4535e402009-05-15 09:07:06 -0400368} // namespace android