Home | History | Annotate | Download | only in androidfw
      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_pos(0),
     63      m_entityCount(0)
     64 {
     65 }
     66 
     67 BackupDataWriter::~BackupDataWriter()
     68 {
     69 }
     70 
     71 // Pad out anything they've previously written to the next 4 byte boundary.
     72 status_t
     73 BackupDataWriter::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;
     81         if (DEBUG) ALOGI("writing %d padding bytes for %d", paddingSize, n);
     82         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 
     92 status_t
     93 BackupDataWriter::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 
    106     String8 k;
    107     if (m_keyPrefix.length() > 0) {
    108         k = m_keyPrefix;
    109         k += ":";
    110         k += key;
    111     } else {
    112         k = key;
    113     }
    114     if (DEBUG) {
    115         ALOGD("Writing header: prefix='%s' key='%s' dataSize=%d", m_keyPrefix.string(),
    116                 key.string(), dataSize);
    117     }
    118 
    119     entity_header_v1 header;
    120     ssize_t keyLen;
    121 
    122     keyLen = k.length();
    123 
    124     header.type = tolel(BACKUP_HEADER_ENTITY_V1);
    125     header.keyLen = tolel(keyLen);
    126     header.dataSize = tolel(dataSize);
    127 
    128     if (DEBUG) ALOGI("writing entity header, %d bytes", sizeof(entity_header_v1));
    129     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 
    136     if (DEBUG) ALOGI("writing entity header key, %d bytes", keyLen+1);
    137     amt = write(m_fd, k.string(), keyLen+1);
    138     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 
    151 status_t
    152 BackupDataWriter::WriteEntityData(const void* data, size_t size)
    153 {
    154     if (DEBUG) ALOGD("Writing data: size=%lu", (unsigned long) size);
    155 
    156     if (m_status != NO_ERROR) {
    157         if (DEBUG) {
    158             ALOGD("Not writing data - stream in error state %d (%s)", m_status, strerror(m_status));
    159         }
    160         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;
    169         if (DEBUG) ALOGD("write returned error %d (%s)", m_status, strerror(m_status));
    170         return m_status;
    171     }
    172     m_pos += amt;
    173     return NO_ERROR;
    174 }
    175 
    176 void
    177 BackupDataWriter::SetKeyPrefix(const String8& keyPrefix)
    178 {
    179     m_keyPrefix = keyPrefix;
    180 }
    181 
    182 
    183 BackupDataReader::BackupDataReader(int fd)
    184     :m_fd(fd),
    185      m_done(false),
    186      m_status(NO_ERROR),
    187      m_pos(0),
    188      m_entityCount(0)
    189 {
    190     memset(&m_header, 0, sizeof(m_header));
    191 }
    192 
    193 BackupDataReader::~BackupDataReader()
    194 {
    195 }
    196 
    197 status_t
    198 BackupDataReader::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; \
    208                 m_done = true; \
    209             } else { \
    210                 m_status = errno; \
    211                 ALOGD("CHECK_SIZE(a=%ld e=%ld) failed at line %d m_status='%s'", \
    212                     long(actual), long(expected), __LINE__, strerror(m_status)); \
    213             } \
    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) { \
    221             ALOGD("SKIP_PADDING FAILED at line %d", __LINE__); \
    222             m_status = err; \
    223             return err; \
    224         } \
    225     } while(0)
    226 
    227 status_t
    228 BackupDataReader::ReadNextHeader(bool* done, int* type)
    229 {
    230     *done = m_done;
    231     if (m_status != NO_ERROR) {
    232         return m_status;
    233     }
    234 
    235     int amt;
    236 
    237     amt = skip_padding();
    238     if (amt == EIO) {
    239         *done = m_done = true;
    240         return NO_ERROR;
    241     }
    242     else if (amt != NO_ERROR) {
    243         return amt;
    244     }
    245     amt = read(m_fd, &m_header, sizeof(m_header));
    246     *done = m_done = (amt == 0);
    247     if (*done) {
    248         return NO_ERROR;
    249     }
    250     CHECK_SIZE(amt, sizeof(m_header));
    251     m_pos += sizeof(m_header);
    252     if (type) {
    253         *type = m_header.type;
    254     }
    255 
    256     // validate and fix up the fields.
    257     m_header.type = fromlel(m_header.type);
    258     switch (m_header.type)
    259     {
    260         case BACKUP_HEADER_ENTITY_V1:
    261         {
    262             m_header.entity.keyLen = fromlel(m_header.entity.keyLen);
    263             if (m_header.entity.keyLen <= 0) {
    264                 ALOGD("Entity header at %d has keyLen<=0: 0x%08x\n", (int)m_pos,
    265                         (int)m_header.entity.keyLen);
    266                 m_status = EINVAL;
    267             }
    268             m_header.entity.dataSize = fromlel(m_header.entity.dataSize);
    269             m_entityCount++;
    270 
    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 
    285             break;
    286         }
    287         default:
    288             ALOGD("Chunk header at %d has invalid type: 0x%08x",
    289                     (int)(m_pos - sizeof(m_header)), (int)m_header.type);
    290             m_status = EINVAL;
    291     }
    292 
    293     return m_status;
    294 }
    295 
    296 bool
    297 BackupDataReader::HasEntities()
    298 {
    299     return m_status == NO_ERROR && m_header.type == BACKUP_HEADER_ENTITY_V1;
    300 }
    301 
    302 status_t
    303 BackupDataReader::ReadEntityHeader(String8* key, size_t* dataSize)
    304 {
    305     if (m_status != NO_ERROR) {
    306         return m_status;
    307     }
    308     if (m_header.type != BACKUP_HEADER_ENTITY_V1) {
    309         return EINVAL;
    310     }
    311     *key = m_key;
    312     *dataSize = m_header.entity.dataSize;
    313     return NO_ERROR;
    314 }
    315 
    316 status_t
    317 BackupDataReader::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) {
    326         int pos = lseek(m_fd, m_dataEndPos, SEEK_SET);
    327         if (pos == -1) {
    328             return errno;
    329         }
    330         m_pos = pos;
    331     }
    332     SKIP_PADDING();
    333     return NO_ERROR;
    334 }
    335 
    336 ssize_t
    337 BackupDataReader::ReadEntityData(void* data, size_t size)
    338 {
    339     if (m_status != NO_ERROR) {
    340         return -1;
    341     }
    342     int remaining = m_dataEndPos - m_pos;
    343     //ALOGD("ReadEntityData size=%d m_pos=0x%x m_dataEndPos=0x%x remaining=%d\n",
    344     //        size, m_pos, m_dataEndPos, remaining);
    345     if (remaining <= 0) {
    346         return 0;
    347     }
    348     if (((int)size) > remaining) {
    349         size = remaining;
    350     }
    351     //ALOGD("   reading %d bytes", size);
    352     int amt = read(m_fd, data, size);
    353     if (amt < 0) {
    354         m_status = errno;
    355         return -1;
    356     }
    357     if (amt == 0) {
    358         m_status = EIO;
    359         m_done = true;
    360     }
    361     m_pos += amt;
    362     return amt;
    363 }
    364 
    365 status_t
    366 BackupDataReader::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 
    382 } // namespace android
    383