• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 #define LOG_TAG "backup_data"
18 
19 #include <utils/BackupHelpers.h>
20 #include <utils/ByteOrder.h>
21 
22 #include <stdio.h>
23 #include <unistd.h>
24 
25 #include <cutils/log.h>
26 
27 namespace 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 
42 const static int ROUND_UP[4] = { 0, 3, 2, 1 };
43 
44 static inline size_t
round_up(size_t n)45 round_up(size_t n)
46 {
47     return n + ROUND_UP[n % 4];
48 }
49 
50 static inline size_t
padding_extra(size_t n)51 padding_extra(size_t n)
52 {
53     return ROUND_UP[n % 4];
54 }
55 
BackupDataWriter(int fd)56 BackupDataWriter::BackupDataWriter(int fd)
57     :m_fd(fd),
58      m_status(NO_ERROR),
59      m_pos(0),
60      m_entityCount(0)
61 {
62 }
63 
~BackupDataWriter()64 BackupDataWriter::~BackupDataWriter()
65 {
66 }
67 
68 // Pad out anything they've previously written to the next 4 byte boundary.
69 status_t
write_padding_for(int n)70 BackupDataWriter::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 
88 status_t
WriteEntityHeader(const String8 & key,size_t dataSize)89 BackupDataWriter::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     String8 k;
103     if (m_keyPrefix.length() > 0) {
104         k = m_keyPrefix;
105         k += ":";
106         k += key;
107     } else {
108         k = key;
109     }
110     if (false) {
111         LOGD("Writing entity: prefix='%s' key='%s' dataSize=%d", m_keyPrefix.string(), key.string(),
112                 dataSize);
113     }
114 
115     entity_header_v1 header;
116     ssize_t keyLen;
117 
118     keyLen = k.length();
119 
120     header.type = tolel(BACKUP_HEADER_ENTITY_V1);
121     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 
131     amt = write(m_fd, k.string(), keyLen+1);
132     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 
145 status_t
WriteEntityData(const void * data,size_t size)146 BackupDataWriter::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 
164 void
SetKeyPrefix(const String8 & keyPrefix)165 BackupDataWriter::SetKeyPrefix(const String8& keyPrefix)
166 {
167     m_keyPrefix = keyPrefix;
168 }
169 
170 
BackupDataReader(int fd)171 BackupDataReader::BackupDataReader(int fd)
172     :m_fd(fd),
173      m_done(false),
174      m_status(NO_ERROR),
175      m_pos(0),
176      m_entityCount(0)
177 {
178     memset(&m_header, 0, sizeof(m_header));
179 }
180 
~BackupDataReader()181 BackupDataReader::~BackupDataReader()
182 {
183 }
184 
185 status_t
Status()186 BackupDataReader::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; \
196                 m_done = true; \
197             } else { \
198                 m_status = errno; \
199                 LOGD("CHECK_SIZE(a=%ld e=%ld) failed at line %d m_status='%s'", \
200                     long(actual), long(expected), __LINE__, strerror(m_status)); \
201             } \
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) { \
209             LOGD("SKIP_PADDING FAILED at line %d", __LINE__); \
210             m_status = err; \
211             return err; \
212         } \
213     } while(0)
214 
215 status_t
ReadNextHeader(bool * done,int * type)216 BackupDataReader::ReadNextHeader(bool* done, int* type)
217 {
218     *done = m_done;
219     if (m_status != NO_ERROR) {
220         return m_status;
221     }
222 
223     int amt;
224 
225     amt = skip_padding();
226     if (amt == EIO) {
227         *done = m_done = true;
228         return NO_ERROR;
229     }
230     else if (amt != NO_ERROR) {
231         return amt;
232     }
233     amt = read(m_fd, &m_header, sizeof(m_header));
234     *done = m_done = (amt == 0);
235     if (*done) {
236         return NO_ERROR;
237     }
238     CHECK_SIZE(amt, sizeof(m_header));
239     m_pos += sizeof(m_header);
240     if (type) {
241         *type = m_header.type;
242     }
243 
244     // validate and fix up the fields.
245     m_header.type = fromlel(m_header.type);
246     switch (m_header.type)
247     {
248         case BACKUP_HEADER_ENTITY_V1:
249         {
250             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);
257             m_entityCount++;
258 
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 
273             break;
274         }
275         default:
276             LOGD("Chunk header at %d has invalid type: 0x%08x", (int)m_pos, (int)m_header.type);
277             m_status = EINVAL;
278     }
279 
280     return m_status;
281 }
282 
283 bool
HasEntities()284 BackupDataReader::HasEntities()
285 {
286     return m_status == NO_ERROR && m_header.type == BACKUP_HEADER_ENTITY_V1;
287 }
288 
289 status_t
ReadEntityHeader(String8 * key,size_t * dataSize)290 BackupDataReader::ReadEntityHeader(String8* key, size_t* dataSize)
291 {
292     if (m_status != NO_ERROR) {
293         return m_status;
294     }
295     if (m_header.type != BACKUP_HEADER_ENTITY_V1) {
296         return EINVAL;
297     }
298     *key = m_key;
299     *dataSize = m_header.entity.dataSize;
300     return NO_ERROR;
301 }
302 
303 status_t
SkipEntityData()304 BackupDataReader::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) {
313         int pos = lseek(m_fd, m_dataEndPos, SEEK_SET);
314         if (pos == -1) {
315             return errno;
316         }
317     }
318     SKIP_PADDING();
319     return NO_ERROR;
320 }
321 
322 ssize_t
ReadEntityData(void * data,size_t size)323 BackupDataReader::ReadEntityData(void* data, size_t size)
324 {
325     if (m_status != NO_ERROR) {
326         return -1;
327     }
328     int remaining = m_dataEndPos - m_pos;
329     //LOGD("ReadEntityData size=%d m_pos=0x%x m_dataEndPos=0x%x remaining=%d\n",
330     //        size, m_pos, m_dataEndPos, remaining);
331     if (remaining <= 0) {
332         return 0;
333     }
334     if (((int)size) > remaining) {
335         size = remaining;
336     }
337     //LOGD("   reading %d bytes", size);
338     int amt = read(m_fd, data, size);
339     if (amt < 0) {
340         m_status = errno;
341         return -1;
342     }
343     if (amt == 0) {
344         m_status = EIO;
345         m_done = true;
346     }
347     m_pos += amt;
348     return amt;
349 }
350 
351 status_t
skip_padding()352 BackupDataReader::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 
368 } // namespace android
369