blob: 16ff1e55e112baa391ef0584e022dc58d67923e2 [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
102 entity_header_v1 header;
103 ssize_t keyLen;
104
105 keyLen = key.length();
106
Joe Onoratod2110db2009-05-19 13:41:21 -0700107 header.type = tolel(BACKUP_HEADER_ENTITY_V1);
Joe Onorato4535e402009-05-15 09:07:06 -0400108 header.keyLen = tolel(keyLen);
109 header.dataSize = tolel(dataSize);
110
111 amt = write(m_fd, &header, sizeof(entity_header_v1));
112 if (amt != sizeof(entity_header_v1)) {
113 m_status = errno;
114 return m_status;
115 }
116 m_pos += amt;
117
118 amt = write(m_fd, key.string(), keyLen+1);
119 if (amt != keyLen+1) {
120 m_status = errno;
121 return m_status;
122 }
123 m_pos += amt;
124
125 amt = write_padding_for(keyLen+1);
126
127 m_entityCount++;
128
129 return amt;
130}
131
132status_t
133BackupDataWriter::WriteEntityData(const void* data, size_t size)
134{
135 if (m_status != NO_ERROR) {
136 return m_status;
137 }
138
139 // We don't write padding here, because they're allowed to call this several
140 // times with smaller buffers. We write it at the end of WriteEntityHeader
141 // instead.
142 ssize_t amt = write(m_fd, data, size);
143 if (amt != (ssize_t)size) {
144 m_status = errno;
145 return m_status;
146 }
147 m_pos += amt;
148 return NO_ERROR;
149}
150
Joe Onorato4535e402009-05-15 09:07:06 -0400151
Joe Onorato2e1da322009-05-15 18:20:19 -0400152
153BackupDataReader::BackupDataReader(int fd)
154 :m_fd(fd),
Joe Onorato5f15d152009-06-16 16:31:35 -0400155 m_done(false),
Joe Onorato2e1da322009-05-15 18:20:19 -0400156 m_status(NO_ERROR),
157 m_pos(0),
158 m_entityCount(0)
159{
160 memset(&m_header, 0, sizeof(m_header));
161}
162
163BackupDataReader::~BackupDataReader()
164{
165}
166
167status_t
168BackupDataReader::Status()
169{
170 return m_status;
171}
172
173#define CHECK_SIZE(actual, expected) \
174 do { \
175 if ((actual) != (expected)) { \
176 if ((actual) == 0) { \
177 m_status = EIO; \
178 } else { \
179 m_status = errno; \
180 } \
181 return m_status; \
182 } \
183 } while(0)
184#define SKIP_PADDING() \
185 do { \
186 status_t err = skip_padding(); \
187 if (err != NO_ERROR) { \
188 m_status = err; \
189 return err; \
190 } \
191 } while(0)
192
193status_t
Joe Onorato5f15d152009-06-16 16:31:35 -0400194BackupDataReader::ReadNextHeader(bool* done, int* type)
Joe Onorato2e1da322009-05-15 18:20:19 -0400195{
Joe Onorato5f15d152009-06-16 16:31:35 -0400196 *done = m_done;
Joe Onorato2e1da322009-05-15 18:20:19 -0400197 if (m_status != NO_ERROR) {
198 return m_status;
199 }
200
201 int amt;
202
Joe Onorato5f15d152009-06-16 16:31:35 -0400203 // No error checking here, in case we're at the end of the stream. Just let read() fail.
204 skip_padding();
Joe Onorato2e1da322009-05-15 18:20:19 -0400205 amt = read(m_fd, &m_header, sizeof(m_header));
Joe Onorato5f15d152009-06-16 16:31:35 -0400206 *done = m_done = (amt == 0);
Joe Onorato2e1da322009-05-15 18:20:19 -0400207 CHECK_SIZE(amt, sizeof(m_header));
208
209 // validate and fix up the fields.
210 m_header.type = fromlel(m_header.type);
211 switch (m_header.type)
212 {
Joe Onoratod2110db2009-05-19 13:41:21 -0700213 case BACKUP_HEADER_ENTITY_V1:
Joe Onorato2e1da322009-05-15 18:20:19 -0400214 m_header.entity.keyLen = fromlel(m_header.entity.keyLen);
215 if (m_header.entity.keyLen <= 0) {
216 LOGD("Entity header at %d has keyLen<=0: 0x%08x\n", (int)m_pos,
217 (int)m_header.entity.keyLen);
218 m_status = EINVAL;
219 }
220 m_header.entity.dataSize = fromlel(m_header.entity.dataSize);
Joe Onorato2e1da322009-05-15 18:20:19 -0400221 m_entityCount++;
222 break;
Joe Onorato2e1da322009-05-15 18:20:19 -0400223 default:
224 LOGD("Chunk header at %d has invalid type: 0x%08x", (int)m_pos, (int)m_header.type);
225 m_status = EINVAL;
226 }
227 m_pos += sizeof(m_header);
Joe Onoratod2110db2009-05-19 13:41:21 -0700228 if (type) {
229 *type = m_header.type;
230 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400231
232 return m_status;
233}
234
Joe Onorato2e1da322009-05-15 18:20:19 -0400235bool
236BackupDataReader::HasEntities()
237{
Joe Onoratod2110db2009-05-19 13:41:21 -0700238 return m_status == NO_ERROR && m_header.type == BACKUP_HEADER_ENTITY_V1;
Joe Onorato2e1da322009-05-15 18:20:19 -0400239}
240
241status_t
242BackupDataReader::ReadEntityHeader(String8* key, size_t* dataSize)
243{
244 if (m_status != NO_ERROR) {
245 return m_status;
246 }
Joe Onoratod2110db2009-05-19 13:41:21 -0700247 if (m_header.type != BACKUP_HEADER_ENTITY_V1) {
Joe Onorato2e1da322009-05-15 18:20:19 -0400248 return EINVAL;
249 }
Joe Onoratod2110db2009-05-19 13:41:21 -0700250 size_t size = m_header.entity.keyLen;
Joe Onorato2e1da322009-05-15 18:20:19 -0400251 char* buf = key->lockBuffer(size);
252 if (key == NULL) {
253 key->unlockBuffer();
254 m_status = ENOMEM;
255 return m_status;
256 }
257 int amt = read(m_fd, buf, size+1);
258 CHECK_SIZE(amt, (int)size+1);
259 key->unlockBuffer(size);
260 m_pos += size+1;
261 *dataSize = m_header.entity.dataSize;
262 SKIP_PADDING();
Joe Onorato5f15d152009-06-16 16:31:35 -0400263 m_dataEndPos = m_pos + *dataSize;
Joe Onorato2e1da322009-05-15 18:20:19 -0400264 return NO_ERROR;
265}
266
267status_t
Joe Onoratod2110db2009-05-19 13:41:21 -0700268BackupDataReader::SkipEntityData()
269{
270 if (m_status != NO_ERROR) {
271 return m_status;
272 }
273 if (m_header.type != BACKUP_HEADER_ENTITY_V1) {
274 return EINVAL;
275 }
276 if (m_header.entity.dataSize > 0) {
Joe Onorato5f15d152009-06-16 16:31:35 -0400277 int pos = lseek(m_fd, m_dataEndPos, SEEK_SET);
Joe Onoratod2110db2009-05-19 13:41:21 -0700278 return pos == -1 ? (int)errno : (int)NO_ERROR;
279 } else {
280 return NO_ERROR;
281 }
282}
283
284status_t
Joe Onorato2e1da322009-05-15 18:20:19 -0400285BackupDataReader::ReadEntityData(void* data, size_t size)
286{
287 if (m_status != NO_ERROR) {
288 return m_status;
289 }
Joe Onorato5f15d152009-06-16 16:31:35 -0400290 int remaining = m_dataEndPos - m_pos;
291 if (size > remaining) {
292 printf("size=%d m_pos=0x%x m_dataEndPos=0x%x remaining=%d\n",
293 size, m_pos, m_dataEndPos, remaining);
294 size = remaining;
295 }
296 if (remaining <= 0) {
297 return 0;
298 }
Joe Onorato2e1da322009-05-15 18:20:19 -0400299 int amt = read(m_fd, data, size);
300 CHECK_SIZE(amt, (int)size);
301 m_pos += size;
302 return NO_ERROR;
303}
304
305status_t
Joe Onorato2e1da322009-05-15 18:20:19 -0400306BackupDataReader::skip_padding()
307{
308 ssize_t amt;
309 ssize_t paddingSize;
310
311 paddingSize = padding_extra(m_pos);
312 if (paddingSize > 0) {
313 uint32_t padding;
314 amt = read(m_fd, &padding, paddingSize);
315 CHECK_SIZE(amt, paddingSize);
316 m_pos += amt;
317 }
318 return NO_ERROR;
319}
320
321
Joe Onorato4535e402009-05-15 09:07:06 -0400322} // namespace android