diff options
| author | Android (Google) Code Review <android-gerrit@google.com> | 2009-06-24 11:18:01 -0700 | 
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2009-06-24 11:18:01 -0700 | 
| commit | 0e034e5a9a71e5e196baff630dca796a0e3ed3e2 (patch) | |
| tree | 75bc0bb09e201e488bd68203b86599f8a5e65f01 | |
| parent | 6f8e592347d463044b7dd8999588840cec6e956e (diff) | |
| parent | fbb92385f2fb0ae1146bb8f3d73547d90bda6db1 (diff) | |
| download | frameworks_base-0e034e5a9a71e5e196baff630dca796a0e3ed3e2.zip frameworks_base-0e034e5a9a71e5e196baff630dca796a0e3ed3e2.tar.gz frameworks_base-0e034e5a9a71e5e196baff630dca796a0e3ed3e2.tar.bz2 | |
Merge change 5162 into donut
* changes:
  Preserve file access mode when backing up / restoring files
| -rw-r--r-- | libs/utils/BackupHelpers.cpp | 102 | 
1 files changed, 89 insertions, 13 deletions
| diff --git a/libs/utils/BackupHelpers.cpp b/libs/utils/BackupHelpers.cpp index 67d07fe..3346614 100644 --- a/libs/utils/BackupHelpers.cpp +++ b/libs/utils/BackupHelpers.cpp @@ -41,7 +41,43 @@ namespace android {  #define MAGIC0 0x70616e53 // Snap  #define MAGIC1 0x656c6946 // File -#if 1 // TEST_BACKUP_HELPERS +/* + * File entity data format (v1): + * + *   - 4-byte version number of the metadata, little endian (0x00000001 for v1) + *   - 12 bytes of metadata + *   - the file data itself + * + * i.e. a 16-byte metadata header followed by the raw file data.  If the + * restore code does not recognize the metadata version, it can still + * interpret the file data itself correctly. + * + * file_metadata_v1: + * + *   - 4 byte version number === 0x00000001 (little endian) + *   - 4-byte access mode (little-endian) + *   - undefined (8 bytes) + */ + +struct file_metadata_v1 { +    int version; +    int mode; +    int undefined_1; +    int undefined_2; +}; + +const static int CURRENT_METADATA_VERSION = 1; + +// auto-free buffer management object +class StAutoFree { +public: +    StAutoFree(void* buffer) { mBuf = buffer; } +    ~StAutoFree() { free(mBuf); } +private: +    void* mBuf; +}; + +#if 0 // TEST_BACKUP_HELPERS  #define LOGP(f, x...) printf(f "\n", x)  #else  #define LOGP(x...) LOGD(x) @@ -181,29 +217,48 @@ write_delete_file(BackupDataWriter* dataStream, const String8& key)  }  static int -write_update_file(BackupDataWriter* dataStream, int fd, const String8& key, +write_update_file(BackupDataWriter* dataStream, int fd, int mode, const String8& key,          char const* realFilename)  { -    LOGP("write_update_file %s (%s)\n", realFilename, key.string()); +    LOGP("write_update_file %s (%s) : mode 0%o\n", realFilename, key.string(), mode);      const int bufsize = 4*1024;      int err;      int amt;      int fileSize;      int bytesLeft; +    file_metadata_v1 metadata;      char* buf = (char*)malloc(bufsize); +    StAutoFree _autoFree(buf); +      int crc = crc32(0L, Z_NULL, 0); -    bytesLeft = fileSize = lseek(fd, 0, SEEK_END); +    fileSize = lseek(fd, 0, SEEK_END);      lseek(fd, 0, SEEK_SET); +    if (sizeof(metadata) != 16) { +        LOGE("ERROR: metadata block is the wrong size!"); +    } + +    bytesLeft = fileSize + sizeof(metadata);      err = dataStream->WriteEntityHeader(key, bytesLeft);      if (err != 0) {          return err;      } +    // store the file metadata first +    metadata.version = tolel(CURRENT_METADATA_VERSION); +    metadata.mode = tolel(mode); +    metadata.undefined_1 = metadata.undefined_2 = 0; +    err = dataStream->WriteEntityData(&metadata, sizeof(metadata)); +    if (err != 0) { +        return err; +    } +    bytesLeft -= sizeof(metadata); // bytesLeft should == fileSize now + +    // now store the file content      while ((amt = read(fd, buf, bufsize)) != 0 && bytesLeft > 0) {          bytesLeft -= amt;          if (bytesLeft < 0) { @@ -232,8 +287,6 @@ write_update_file(BackupDataWriter* dataStream, int fd, const String8& key,                  " You aren't doing proper locking!", realFilename, fileSize, fileSize-bytesLeft);      } -    free(buf); -      return NO_ERROR;  } @@ -241,11 +294,19 @@ static int  write_update_file(BackupDataWriter* dataStream, const String8& key, char const* realFilename)  {      int err; +    struct stat st; + +    err = stat(realFilename, &st); +    if (err < 0) { +        return errno; +    } +      int fd = open(realFilename, O_RDONLY);      if (fd == -1) {          return errno;      } -    err = write_update_file(dataStream, fd, key, realFilename); + +    err = write_update_file(dataStream, fd, st.st_mode, key, realFilename);      close(fd);      return err;  } @@ -257,6 +318,8 @@ compute_crc32(int fd)      int amt;      char* buf = (char*)malloc(bufsize); +    StAutoFree _autoFree(buf); +      int crc = crc32(0L, Z_NULL, 0);      lseek(fd, 0, SEEK_SET); @@ -265,8 +328,6 @@ compute_crc32(int fd)          crc = crc32(crc, (Bytef*)buf, amt);      } -    free(buf); -      return crc;  } @@ -356,7 +417,7 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD                          g.s.modTime_sec, g.s.modTime_nsec, g.s.mode, g.s.size, g.s.crc32);                  if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec                          || f.mode != g.s.mode || f.size != g.s.size || f.crc32 != g.s.crc32) { -                    write_update_file(dataStream, fd, p, g.file.string()); +                    write_update_file(dataStream, fd, g.s.mode, p, g.file.string());                  }                  close(fd); @@ -416,8 +477,22 @@ RestoreHelperBase::WriteFile(const String8& filename, BackupDataReader* in)          return err;      } -    // TODO: World readable/writable for now. -    mode = 0666; +    // Get the metadata block off the head of the file entity and use that to +    // set up the output file +    file_metadata_v1 metadata; +    amt = in->ReadEntityData(&metadata, sizeof(metadata)); +    if (amt != sizeof(metadata)) { +        LOGW("Could not read metadata for %s -- %ld / %s", filename.string(), +                (long)amt, strerror(errno)); +        return EIO; +    } +    metadata.version = fromlel(metadata.version); +    metadata.mode = fromlel(metadata.mode); +    if (metadata.version > CURRENT_METADATA_VERSION) { +        LOGW("Restoring file with unsupported metadata version %d (currently %d)", +                metadata.version, CURRENT_METADATA_VERSION); +    } +    mode = metadata.mode;      // Write the file and compute the crc      crc = crc32(0L, Z_NULL, 0); @@ -512,6 +587,7 @@ compare_file(const char* path, const unsigned char* data, int len)          fprintf(stderr, "malloc(%d) failed\n", len);          return ENOMEM;      } +    StAutoFree _autoFree(contents);      bool sizesMatch = true;      amt = lseek(fd, 0, SEEK_END); @@ -843,6 +919,7 @@ test_read_header_and_entity(BackupDataReader& reader, const char* str)      int err;      int bufSize = strlen(str)+1;      char* buf = (char*)malloc(bufSize); +    StAutoFree _autoFree(buf);      String8 string;      int cookie = 0x11111111;      size_t actualSize; @@ -904,7 +981,6 @@ finished:      if (err != NO_ERROR) {          fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err));      } -    free(buf);      return err;  } | 
