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 <androidfw/BackupHelpers.h> 20 #include <utils/ByteOrder.h> 21 22 #include <stdio.h> 23 #include <string.h> 24 #include <unistd.h> 25 26 #include <cutils/log.h> 27 28 namespace android { 29 30 static const bool DEBUG = false; 31 32 /* 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 45 const static int ROUND_UP[4] = { 0, 3, 2, 1 }; 46 47 static inline size_t 48 round_up(size_t n) 49 { 50 return n + ROUND_UP[n % 4]; 51 } 52 53 static inline size_t 54 padding_extra(size_t n) 55 { 56 return ROUND_UP[n % 4]; 57 } 58 59 BackupDataWriter::BackupDataWriter(int fd) 60 :m_fd(fd), 61 m_status(NO_ERROR), 62 m_entityCount(0) 63 { 64 m_pos = (ssize_t) lseek(fd, 0, SEEK_CUR); 65 if (DEBUG) ALOGI("BackupDataWriter(%d) @ %ld", fd, (long)m_pos); 66 } 67 68 BackupDataWriter::~BackupDataWriter() 69 { 70 } 71 72 // Pad out anything they've previously written to the next 4 byte boundary. 73 status_t 74 BackupDataWriter::write_padding_for(int n) 75 { 76 ssize_t amt; 77 ssize_t paddingSize; 78 79 paddingSize = padding_extra(n); 80 if (paddingSize > 0) { 81 uint32_t padding = 0xbcbcbcbc; 82 if (DEBUG) ALOGI("writing %zd padding bytes for %d", paddingSize, n); 83 amt = write(m_fd, &padding, paddingSize); 84 if (amt != paddingSize) { 85 m_status = errno; 86 return m_status; 87 } 88 m_pos += amt; 89 } 90 return NO_ERROR; 91 } 92 93 status_t 94 BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize) 95 { 96 if (m_status != NO_ERROR) { 97 return m_status; 98 } 99 100 ssize_t amt; 101 102 amt = write_padding_for(m_pos); 103 if (amt != 0) { 104 return amt; 105 } 106 107 String8 k; 108 if (m_keyPrefix.length() > 0) { 109 k = m_keyPrefix; 110 k += ":"; 111 k += key; 112 } else { 113 k = key; 114 } 115 if (DEBUG) { 116 ALOGD("Writing header: prefix='%s' key='%s' dataSize=%zu", m_keyPrefix.string(), 117 key.string(), dataSize); 118 } 119 120 entity_header_v1 header; 121 ssize_t keyLen; 122 123 keyLen = k.length(); 124 125 header.type = tolel(BACKUP_HEADER_ENTITY_V1); 126 header.keyLen = tolel(keyLen); 127 header.dataSize = tolel(dataSize); 128 129 if (DEBUG) ALOGI("writing entity header, %zu bytes", sizeof(entity_header_v1)); 130 amt = write(m_fd, &header, sizeof(entity_header_v1)); 131 if (amt != sizeof(entity_header_v1)) { 132 m_status = errno; 133 return m_status; 134 } 135 m_pos += amt; 136 137 if (DEBUG) ALOGI("writing entity header key, %zd bytes", keyLen+1); 138 amt = write(m_fd, k.string(), keyLen+1); 139 if (amt != keyLen+1) { 140 m_status = errno; 141 return m_status; 142 } 143 m_pos += amt; 144 145 amt = write_padding_for(keyLen+1); 146 147 m_entityCount++; 148 149 return amt; 150 } 151 152 status_t 153 BackupDataWriter::WriteEntityData(const void* data, size_t size) 154 { 155 if (DEBUG) ALOGD("Writing data: size=%lu", (unsigned long) size); 156 157 if (m_status != NO_ERROR) { 158 if (DEBUG) { 159 ALOGD("Not writing data - stream in error state %d (%s)", m_status, strerror(m_status)); 160 } 161 return m_status; 162 } 163 164 // We don't write padding here, because they're allowed to call this several 165 // times with smaller buffers. We write it at the end of WriteEntityHeader 166 // instead. 167 ssize_t amt = write(m_fd, data, size); 168 if (amt != (ssize_t)size) { 169 m_status = errno; 170 if (DEBUG) ALOGD("write returned error %d (%s)", m_status, strerror(m_status)); 171 return m_status; 172 } 173 m_pos += amt; 174 return NO_ERROR; 175 } 176 177 void 178 BackupDataWriter::SetKeyPrefix(const String8& keyPrefix) 179 { 180 m_keyPrefix = keyPrefix; 181 } 182 183 184 BackupDataReader::BackupDataReader(int fd) 185 :m_fd(fd), 186 m_done(false), 187 m_status(NO_ERROR), 188 m_entityCount(0) 189 { 190 memset(&m_header, 0, sizeof(m_header)); 191 m_pos = (ssize_t) lseek(fd, 0, SEEK_CUR); 192 if (DEBUG) ALOGI("BackupDataReader(%d) @ %ld", fd, (long)m_pos); 193 } 194 195 BackupDataReader::~BackupDataReader() 196 { 197 } 198 199 status_t 200 BackupDataReader::Status() 201 { 202 return m_status; 203 } 204 205 #define CHECK_SIZE(actual, expected) \ 206 do { \ 207 if ((actual) != (expected)) { \ 208 if ((actual) == 0) { \ 209 m_status = EIO; \ 210 m_done = true; \ 211 } else { \ 212 m_status = errno; \ 213 ALOGD("CHECK_SIZE(a=%ld e=%ld) failed at line %d m_status='%s'", \ 214 long(actual), long(expected), __LINE__, strerror(m_status)); \ 215 } \ 216 return m_status; \ 217 } \ 218 } while(0) 219 #define SKIP_PADDING() \ 220 do { \ 221 status_t err = skip_padding(); \ 222 if (err != NO_ERROR) { \ 223 ALOGD("SKIP_PADDING FAILED at line %d", __LINE__); \ 224 m_status = err; \ 225 return err; \ 226 } \ 227 } while(0) 228 229 status_t 230 BackupDataReader::ReadNextHeader(bool* done, int* type) 231 { 232 *done = m_done; 233 if (m_status != NO_ERROR) { 234 return m_status; 235 } 236 237 int amt; 238 239 amt = skip_padding(); 240 if (amt == EIO) { 241 *done = m_done = true; 242 return NO_ERROR; 243 } 244 else if (amt != NO_ERROR) { 245 return amt; 246 } 247 amt = read(m_fd, &m_header, sizeof(m_header)); 248 *done = m_done = (amt == 0); 249 if (*done) { 250 return NO_ERROR; 251 } 252 CHECK_SIZE(amt, sizeof(m_header)); 253 m_pos += sizeof(m_header); 254 if (type) { 255 *type = m_header.type; 256 } 257 258 // validate and fix up the fields. 259 m_header.type = fromlel(m_header.type); 260 switch (m_header.type) 261 { 262 case BACKUP_HEADER_ENTITY_V1: 263 { 264 m_header.entity.keyLen = fromlel(m_header.entity.keyLen); 265 if (m_header.entity.keyLen <= 0) { 266 ALOGD("Entity header at %d has keyLen<=0: 0x%08x\n", (int)m_pos, 267 (int)m_header.entity.keyLen); 268 m_status = EINVAL; 269 } 270 m_header.entity.dataSize = fromlel(m_header.entity.dataSize); 271 m_entityCount++; 272 273 // read the rest of the header (filename) 274 size_t size = m_header.entity.keyLen; 275 char* buf = m_key.lockBuffer(size); 276 if (buf == NULL) { 277 m_status = ENOMEM; 278 return m_status; 279 } 280 int amt = read(m_fd, buf, size+1); 281 CHECK_SIZE(amt, (int)size+1); 282 m_key.unlockBuffer(size); 283 m_pos += size+1; 284 SKIP_PADDING(); 285 m_dataEndPos = m_pos + m_header.entity.dataSize; 286 287 break; 288 } 289 default: 290 ALOGD("Chunk header at %d has invalid type: 0x%08x", 291 (int)(m_pos - sizeof(m_header)), (int)m_header.type); 292 m_status = EINVAL; 293 } 294 295 return m_status; 296 } 297 298 bool 299 BackupDataReader::HasEntities() 300 { 301 return m_status == NO_ERROR && m_header.type == BACKUP_HEADER_ENTITY_V1; 302 } 303 304 status_t 305 BackupDataReader::ReadEntityHeader(String8* key, size_t* dataSize) 306 { 307 if (m_status != NO_ERROR) { 308 return m_status; 309 } 310 if (m_header.type != BACKUP_HEADER_ENTITY_V1) { 311 return EINVAL; 312 } 313 *key = m_key; 314 *dataSize = m_header.entity.dataSize; 315 return NO_ERROR; 316 } 317 318 status_t 319 BackupDataReader::SkipEntityData() 320 { 321 if (m_status != NO_ERROR) { 322 return m_status; 323 } 324 if (m_header.type != BACKUP_HEADER_ENTITY_V1) { 325 return EINVAL; 326 } 327 if (m_header.entity.dataSize > 0) { 328 int pos = lseek(m_fd, m_dataEndPos, SEEK_SET); 329 if (pos == -1) { 330 return errno; 331 } 332 m_pos = pos; 333 } 334 SKIP_PADDING(); 335 return NO_ERROR; 336 } 337 338 ssize_t 339 BackupDataReader::ReadEntityData(void* data, size_t size) 340 { 341 if (m_status != NO_ERROR) { 342 return -1; 343 } 344 int remaining = m_dataEndPos - m_pos; 345 //ALOGD("ReadEntityData size=%d m_pos=0x%x m_dataEndPos=0x%x remaining=%d\n", 346 // size, m_pos, m_dataEndPos, remaining); 347 if (remaining <= 0) { 348 return 0; 349 } 350 if (((int)size) > remaining) { 351 size = remaining; 352 } 353 //ALOGD(" reading %d bytes", size); 354 int amt = read(m_fd, data, size); 355 if (amt < 0) { 356 m_status = errno; 357 return -1; 358 } 359 if (amt == 0) { 360 m_status = EIO; 361 m_done = true; 362 } 363 m_pos += amt; 364 return amt; 365 } 366 367 status_t 368 BackupDataReader::skip_padding() 369 { 370 ssize_t amt; 371 ssize_t paddingSize; 372 373 paddingSize = padding_extra(m_pos); 374 if (paddingSize > 0) { 375 uint32_t padding; 376 amt = read(m_fd, &padding, paddingSize); 377 CHECK_SIZE(amt, paddingSize); 378 m_pos += amt; 379 } 380 return NO_ERROR; 381 } 382 383 384 } // namespace android 385