Implement the C++ class to write the backed up file data.
This commit is contained in:
@ -38,6 +38,16 @@
|
|||||||
* intent is to allow us to avoid byte swapping on the device.
|
* intent is to allow us to avoid byte swapping on the device.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static inline uint32_t android_swap_long(uint32_t v)
|
||||||
|
{
|
||||||
|
return (v<<24) | ((v<<8)&0x00FF0000) | ((v>>8)&0x0000FF00) | (v>>24);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t android_swap_short(uint16_t v)
|
||||||
|
{
|
||||||
|
return (v<<8) | (v>>8);
|
||||||
|
}
|
||||||
|
|
||||||
#define DEVICE_BYTE_ORDER LITTLE_ENDIAN
|
#define DEVICE_BYTE_ORDER LITTLE_ENDIAN
|
||||||
|
|
||||||
#if BYTE_ORDER == DEVICE_BYTE_ORDER
|
#if BYTE_ORDER == DEVICE_BYTE_ORDER
|
||||||
@ -49,16 +59,6 @@
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static inline uint32_t android_swap_long(uint32_t v)
|
|
||||||
{
|
|
||||||
return (v<<24) | ((v<<8)&0x00FF0000) | ((v>>8)&0x0000FF00) | (v>>24);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint16_t android_swap_short(uint16_t v)
|
|
||||||
{
|
|
||||||
return (v<<8) | (v>>8);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define dtohl(x) (android_swap_long(x))
|
#define dtohl(x) (android_swap_long(x))
|
||||||
#define dtohs(x) (android_swap_short(x))
|
#define dtohs(x) (android_swap_short(x))
|
||||||
#define htodl(x) (android_swap_long(x))
|
#define htodl(x) (android_swap_long(x))
|
||||||
@ -66,4 +66,16 @@ static inline uint16_t android_swap_short(uint16_t v)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||||
|
#define fromlel(x) (x)
|
||||||
|
#define fromles(x) (x)
|
||||||
|
#define tolel(x) (x)
|
||||||
|
#define toles(x) (x)
|
||||||
|
#else
|
||||||
|
#define fromlel(x) (android_swap_long(x))
|
||||||
|
#define fromles(x) (android_swap_short(x))
|
||||||
|
#define tolel(x) (android_swap_long(x))
|
||||||
|
#define toles(x) (android_swap_short(x))
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // _LIBS_UTILS_BYTE_ORDER_H
|
#endif // _LIBS_UTILS_BYTE_ORDER_H
|
||||||
|
@ -1,15 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef _UTILS_BACKUP_HELPERS_H
|
#ifndef _UTILS_BACKUP_HELPERS_H
|
||||||
#define _UTILS_BACKUP_HELPERS_H
|
#define _UTILS_BACKUP_HELPERS_H
|
||||||
|
|
||||||
|
#include <utils/Errors.h>
|
||||||
|
#include <utils/String8.h>
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
int back_up_files(int oldSnapshotFD, int oldDataStream, int newSnapshotFD,
|
int back_up_files(int oldSnapshotFD, int oldDataStream, int newSnapshotFD,
|
||||||
char const* fileBase, char const* const* files, int fileCount);
|
char const* fileBase, char const* const* files, int fileCount);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the data.
|
||||||
|
*
|
||||||
|
* If an error occurs, it poisons this object and all write calls will fail
|
||||||
|
* with the error that occurred.
|
||||||
|
*/
|
||||||
|
class BackupDataWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BackupDataWriter(int fd);
|
||||||
|
// does not close fd
|
||||||
|
~BackupDataWriter();
|
||||||
|
|
||||||
|
status_t WriteAppHeader(const String8& packageName);
|
||||||
|
|
||||||
|
status_t WriteEntityHeader(const String8& key, size_t dataSize);
|
||||||
|
status_t WriteEntityData(const void* data, size_t size);
|
||||||
|
|
||||||
|
status_t WriteAppFooter();
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit BackupDataWriter();
|
||||||
|
status_t write_padding_for(int n);
|
||||||
|
|
||||||
|
int m_fd;
|
||||||
|
status_t m_status;
|
||||||
|
ssize_t m_pos;
|
||||||
|
int m_entityCount;
|
||||||
|
};
|
||||||
|
|
||||||
#define TEST_BACKUP_HELPERS 0
|
#define TEST_BACKUP_HELPERS 0
|
||||||
|
|
||||||
#if TEST_BACKUP_HELPERS
|
#if TEST_BACKUP_HELPERS
|
||||||
int backup_helper_test_empty();
|
int backup_helper_test_empty();
|
||||||
int backup_helper_test_four();
|
int backup_helper_test_four();
|
||||||
int backup_helper_test_files();
|
int backup_helper_test_files();
|
||||||
|
int backup_helper_test_data_writer();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
} // namespace android
|
||||||
|
|
||||||
#endif // _UTILS_BACKUP_HELPERS_H
|
#endif // _UTILS_BACKUP_HELPERS_H
|
||||||
|
@ -117,7 +117,8 @@ LOCAL_SRC_FILES:= \
|
|||||||
IPermissionController.cpp \
|
IPermissionController.cpp \
|
||||||
IServiceManager.cpp \
|
IServiceManager.cpp \
|
||||||
Unicode.cpp \
|
Unicode.cpp \
|
||||||
file_backup_helper.cpp
|
backup_data.cpp \
|
||||||
|
backup_helper_file.cpp
|
||||||
|
|
||||||
ifeq ($(TARGET_SIMULATOR),true)
|
ifeq ($(TARGET_SIMULATOR),true)
|
||||||
LOCAL_SRC_FILES += $(hostSources)
|
LOCAL_SRC_FILES += $(hostSources)
|
||||||
|
236
libs/utils/backup_data.cpp
Normal file
236
libs/utils/backup_data.cpp
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <utils/backup_helpers.h>
|
||||||
|
#include <utils/ByteOrder.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File Format (v1):
|
||||||
|
*
|
||||||
|
* All ints are stored little-endian.
|
||||||
|
*
|
||||||
|
* - An app_header_v1 struct.
|
||||||
|
* - The name of the package, utf-8, null terminated, padded to 4-byte boundary.
|
||||||
|
* - A sequence of zero or more key/value paires (entities), each with
|
||||||
|
* - A entity_header_v1 struct
|
||||||
|
* - The key, utf-8, null terminated, padded to 4-byte boundary.
|
||||||
|
* - The value, padded to 4 byte boundary
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define APP_MAGIC_V1 0x31707041 // App1 (little endian)
|
||||||
|
#define ENTITY_MAGIC_V1 0x61746144 // Data (little endian)
|
||||||
|
#define FOOTER_MAGIC_V1 0x746f6f46 // Foot (little endian)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int type; // == APP_MAGIC_V1
|
||||||
|
int packageLen; // length of the name of the package that follows, not including the null.
|
||||||
|
} app_header_v1;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int type; // ENTITY_MAGIC_V1
|
||||||
|
int keyLen; // length of the key name, not including the null terminator
|
||||||
|
int dataSize; // size of the data, not including the padding
|
||||||
|
} entity_header_v1;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int type; // FOOTER_MAGIC_V1
|
||||||
|
int entityCount; // the number of entities that were written
|
||||||
|
} app_footer_v1;
|
||||||
|
|
||||||
|
const static int ROUND_UP[4] = { 0, 3, 2, 1 };
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
round_up(size_t n)
|
||||||
|
{
|
||||||
|
return n + ROUND_UP[n % 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
padding_extra(size_t n)
|
||||||
|
{
|
||||||
|
return ROUND_UP[n % 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
BackupDataWriter::BackupDataWriter(int fd)
|
||||||
|
:m_fd(fd),
|
||||||
|
m_status(NO_ERROR),
|
||||||
|
m_pos(0),
|
||||||
|
m_entityCount(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BackupDataWriter::~BackupDataWriter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pad out anything they've previously written to the next 4 byte boundary.
|
||||||
|
status_t
|
||||||
|
BackupDataWriter::write_padding_for(int n)
|
||||||
|
{
|
||||||
|
ssize_t amt;
|
||||||
|
ssize_t paddingSize;
|
||||||
|
|
||||||
|
paddingSize = padding_extra(n);
|
||||||
|
if (paddingSize > 0) {
|
||||||
|
uint32_t padding = 0xbcbcbcbc;
|
||||||
|
amt = write(m_fd, &padding, paddingSize);
|
||||||
|
if (amt != paddingSize) {
|
||||||
|
m_status = errno;
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
m_pos += amt;
|
||||||
|
}
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BackupDataWriter::WriteAppHeader(const String8& packageName)
|
||||||
|
{
|
||||||
|
if (m_status != NO_ERROR) {
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t amt;
|
||||||
|
|
||||||
|
amt = write_padding_for(m_pos);
|
||||||
|
if (amt != 0) {
|
||||||
|
return amt;
|
||||||
|
}
|
||||||
|
|
||||||
|
app_header_v1 header;
|
||||||
|
ssize_t nameLen;
|
||||||
|
|
||||||
|
nameLen = packageName.length();
|
||||||
|
|
||||||
|
header.type = tolel(APP_MAGIC_V1);
|
||||||
|
header.packageLen = tolel(nameLen);
|
||||||
|
|
||||||
|
amt = write(m_fd, &header, sizeof(app_header_v1));
|
||||||
|
if (amt != sizeof(app_header_v1)) {
|
||||||
|
m_status = errno;
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
m_pos += amt;
|
||||||
|
|
||||||
|
amt = write(m_fd, packageName.string(), nameLen+1);
|
||||||
|
if (amt != nameLen+1) {
|
||||||
|
m_status = errno;
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
m_pos += amt;
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize)
|
||||||
|
{
|
||||||
|
if (m_status != NO_ERROR) {
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t amt;
|
||||||
|
|
||||||
|
amt = write_padding_for(m_pos);
|
||||||
|
if (amt != 0) {
|
||||||
|
return amt;
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_header_v1 header;
|
||||||
|
ssize_t keyLen;
|
||||||
|
|
||||||
|
keyLen = key.length();
|
||||||
|
|
||||||
|
header.type = tolel(ENTITY_MAGIC_V1);
|
||||||
|
header.keyLen = tolel(keyLen);
|
||||||
|
header.dataSize = tolel(dataSize);
|
||||||
|
|
||||||
|
amt = write(m_fd, &header, sizeof(entity_header_v1));
|
||||||
|
if (amt != sizeof(entity_header_v1)) {
|
||||||
|
m_status = errno;
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
m_pos += amt;
|
||||||
|
|
||||||
|
amt = write(m_fd, key.string(), keyLen+1);
|
||||||
|
if (amt != keyLen+1) {
|
||||||
|
m_status = errno;
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
m_pos += amt;
|
||||||
|
|
||||||
|
amt = write_padding_for(keyLen+1);
|
||||||
|
|
||||||
|
m_entityCount++;
|
||||||
|
|
||||||
|
return amt;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BackupDataWriter::WriteEntityData(const void* data, size_t size)
|
||||||
|
{
|
||||||
|
if (m_status != NO_ERROR) {
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't write padding here, because they're allowed to call this several
|
||||||
|
// times with smaller buffers. We write it at the end of WriteEntityHeader
|
||||||
|
// instead.
|
||||||
|
ssize_t amt = write(m_fd, data, size);
|
||||||
|
if (amt != (ssize_t)size) {
|
||||||
|
m_status = errno;
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
m_pos += amt;
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BackupDataWriter::WriteAppFooter()
|
||||||
|
{
|
||||||
|
if (m_status != NO_ERROR) {
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t amt;
|
||||||
|
|
||||||
|
amt = write_padding_for(m_pos);
|
||||||
|
if (amt != 0) {
|
||||||
|
return amt;
|
||||||
|
}
|
||||||
|
|
||||||
|
app_footer_v1 footer;
|
||||||
|
ssize_t nameLen;
|
||||||
|
|
||||||
|
footer.type = tolel(FOOTER_MAGIC_V1);
|
||||||
|
footer.entityCount = tolel(m_entityCount);
|
||||||
|
|
||||||
|
amt = write(m_fd, &footer, sizeof(app_footer_v1));
|
||||||
|
if (amt != sizeof(app_footer_v1)) {
|
||||||
|
m_status = errno;
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
m_pos += amt;
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace android
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
#define LOG_TAG "file_backup_helper"
|
#define LOG_TAG "file_backup_helper"
|
||||||
|
|
||||||
#include <utils/backup_helpers.h>
|
#include <utils/backup_helpers.h>
|
||||||
@ -19,13 +35,16 @@
|
|||||||
|
|
||||||
#include <cutils/log.h>
|
#include <cutils/log.h>
|
||||||
|
|
||||||
using namespace android;
|
namespace android {
|
||||||
|
|
||||||
#define MAGIC0 0x70616e53 // Snap
|
#define MAGIC0 0x70616e53 // Snap
|
||||||
#define MAGIC1 0x656c6946 // File
|
#define MAGIC1 0x656c6946 // File
|
||||||
|
|
||||||
|
#if TEST_BACKUP_HELPERS
|
||||||
|
#define LOGP(x...) printf(x)
|
||||||
|
#else
|
||||||
#define LOGP(x...) LOGD(x)
|
#define LOGP(x...) LOGD(x)
|
||||||
//#define LOGP(x...) printf(x)
|
#endif
|
||||||
|
|
||||||
struct SnapshotHeader {
|
struct SnapshotHeader {
|
||||||
int magic0;
|
int magic0;
|
||||||
@ -118,6 +137,8 @@ write_snapshot_file(int fd, const KeyedVector<String8,FileState>& snapshot)
|
|||||||
bytesWritten += sizeof(FileState) + round_up(name.length());
|
bytesWritten += sizeof(FileState) + round_up(name.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGP("write_snapshot_file fd=%d\n", fd);
|
||||||
|
|
||||||
int amt;
|
int amt;
|
||||||
SnapshotHeader header = { MAGIC0, N, MAGIC1, bytesWritten };
|
SnapshotHeader header = { MAGIC0, N, MAGIC1, bytesWritten };
|
||||||
|
|
||||||
@ -248,11 +269,13 @@ back_up_files(int oldSnapshotFD, int oldDataStream, int newSnapshotFD,
|
|||||||
// file added
|
// file added
|
||||||
String8 realFilename(base);
|
String8 realFilename(base);
|
||||||
realFilename.appendPath(q);
|
realFilename.appendPath(q);
|
||||||
|
LOGP("file added: %s\n", realFilename.string());
|
||||||
write_update_file(realFilename, q);
|
write_update_file(realFilename, q);
|
||||||
m++;
|
m++;
|
||||||
}
|
}
|
||||||
else if (cmp < 0) {
|
else if (cmp < 0) {
|
||||||
// file removed
|
// file removed
|
||||||
|
LOGP("file removed: %s\n", p.string());
|
||||||
write_delete_file(p);
|
write_delete_file(p);
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
@ -573,6 +596,107 @@ backup_helper_test_four()
|
|||||||
return matched ? 0 : 1;
|
return matched ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hexdump -v -e '" " 8/1 " 0x%02x," "\n"' data_writer.data
|
||||||
|
const unsigned char DATA_GOLDEN_FILE[] = {
|
||||||
|
0x41, 0x70, 0x70, 0x31, 0x0b, 0x00, 0x00, 0x00,
|
||||||
|
0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69,
|
||||||
|
0x6e, 0x67, 0x5f, 0x00, 0x44, 0x61, 0x74, 0x61,
|
||||||
|
0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
|
||||||
|
0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69,
|
||||||
|
0x6e, 0x67, 0x5f, 0x00, 0x6e, 0x6f, 0x5f, 0x70,
|
||||||
|
0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00,
|
||||||
|
0x41, 0x70, 0x70, 0x31, 0x0c, 0x00, 0x00, 0x00,
|
||||||
|
0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
|
||||||
|
0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
|
||||||
|
0x44, 0x61, 0x74, 0x61, 0x0c, 0x00, 0x00, 0x00,
|
||||||
|
0x0d, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
|
||||||
|
0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33,
|
||||||
|
0x00, 0xbc, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64,
|
||||||
|
0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33,
|
||||||
|
0x00, 0xbc, 0xbc, 0xbc, 0x41, 0x70, 0x70, 0x31,
|
||||||
|
0x0d, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
|
||||||
|
0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
|
||||||
|
0x5f, 0x00, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61,
|
||||||
|
0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
|
||||||
|
0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
|
||||||
|
0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc,
|
||||||
|
0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
|
||||||
|
0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc,
|
||||||
|
0x41, 0x70, 0x70, 0x31, 0x0a, 0x00, 0x00, 0x00,
|
||||||
|
0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
|
||||||
|
0x6f, 0x31, 0x00, 0xbc, 0x44, 0x61, 0x74, 0x61,
|
||||||
|
0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
|
||||||
|
0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
|
||||||
|
0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64,
|
||||||
|
0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00, 0xbc,
|
||||||
|
0x46, 0x6f, 0x6f, 0x74, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE);
|
||||||
|
|
||||||
|
static int
|
||||||
|
test_write_header_and_entity(BackupDataWriter& writer, const char* str)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
String8 text(str);
|
||||||
|
|
||||||
|
err = writer.WriteAppHeader(text);
|
||||||
|
if (err != 0) {
|
||||||
|
fprintf(stderr, "WriteAppHeader failed with %s\n", strerror(err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = writer.WriteEntityHeader(text, text.length()+1);
|
||||||
|
if (err != 0) {
|
||||||
|
fprintf(stderr, "WriteEntityHeader failed with %s\n", strerror(err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = writer.WriteEntityData(text.string(), text.length()+1);
|
||||||
|
if (err != 0) {
|
||||||
|
fprintf(stderr, "write failed for data '%s'\n", text.string());
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
backup_helper_test_data_writer()
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
int fd;
|
||||||
|
const char* filename = SCRATCH_DIR "data_writer.data";
|
||||||
|
|
||||||
|
system("rm -r " SCRATCH_DIR);
|
||||||
|
mkdir(SCRATCH_DIR, 0777);
|
||||||
|
mkdir(SCRATCH_DIR "data", 0777);
|
||||||
|
|
||||||
|
fd = creat(filename, 0666);
|
||||||
|
if (fd == -1) {
|
||||||
|
fprintf(stderr, "error creating: %s\n", strerror(errno));
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
BackupDataWriter writer(fd);
|
||||||
|
|
||||||
|
err = 0;
|
||||||
|
err |= test_write_header_and_entity(writer, "no_padding_");
|
||||||
|
err |= test_write_header_and_entity(writer, "padded_to__3");
|
||||||
|
err |= test_write_header_and_entity(writer, "padded_to_2__");
|
||||||
|
err |= test_write_header_and_entity(writer, "padded_to1");
|
||||||
|
|
||||||
|
writer.WriteAppFooter();
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
err = compare_file(filename, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
|
||||||
|
if (err != 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_mod_time(const char* filename, struct timeval times[2])
|
get_mod_time(const char* filename, struct timeval times[2])
|
||||||
{
|
{
|
||||||
@ -594,8 +718,9 @@ int
|
|||||||
backup_helper_test_files()
|
backup_helper_test_files()
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
int newSnapshotFD;
|
|
||||||
int oldSnapshotFD;
|
int oldSnapshotFD;
|
||||||
|
int dataStreamFD;
|
||||||
|
int newSnapshotFD;
|
||||||
|
|
||||||
system("rm -r " SCRATCH_DIR);
|
system("rm -r " SCRATCH_DIR);
|
||||||
mkdir(SCRATCH_DIR, 0777);
|
mkdir(SCRATCH_DIR, 0777);
|
||||||
@ -616,17 +741,24 @@ backup_helper_test_files()
|
|||||||
"data/f"
|
"data/f"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dataStreamFD = creat(SCRATCH_DIR "1.data", 0666);
|
||||||
|
if (dataStreamFD == -1) {
|
||||||
|
fprintf(stderr, "error creating: %s\n", strerror(errno));
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
newSnapshotFD = creat(SCRATCH_DIR "before.snap", 0666);
|
newSnapshotFD = creat(SCRATCH_DIR "before.snap", 0666);
|
||||||
if (newSnapshotFD == -1) {
|
if (newSnapshotFD == -1) {
|
||||||
fprintf(stderr, "error creating: %s\n", strerror(errno));
|
fprintf(stderr, "error creating: %s\n", strerror(errno));
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = back_up_files(-1, newSnapshotFD, 0, SCRATCH_DIR, files_before, 5);
|
err = back_up_files(-1, dataStreamFD, newSnapshotFD, SCRATCH_DIR, files_before, 5);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close(dataStreamFD);
|
||||||
close(newSnapshotFD);
|
close(newSnapshotFD);
|
||||||
|
|
||||||
sleep(3);
|
sleep(3);
|
||||||
@ -665,21 +797,30 @@ backup_helper_test_files()
|
|||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dataStreamFD = creat(SCRATCH_DIR "2.data", 0666);
|
||||||
|
if (dataStreamFD == -1) {
|
||||||
|
fprintf(stderr, "error creating: %s\n", strerror(errno));
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
newSnapshotFD = creat(SCRATCH_DIR "after.snap", 0666);
|
newSnapshotFD = creat(SCRATCH_DIR "after.snap", 0666);
|
||||||
if (newSnapshotFD == -1) {
|
if (newSnapshotFD == -1) {
|
||||||
fprintf(stderr, "error creating: %s\n", strerror(errno));
|
fprintf(stderr, "error creating: %s\n", strerror(errno));
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = back_up_files(oldSnapshotFD, newSnapshotFD, 0, SCRATCH_DIR, files_after, 6);
|
err = back_up_files(oldSnapshotFD, dataStreamFD, newSnapshotFD, SCRATCH_DIR, files_after, 6);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(oldSnapshotFD);
|
close(oldSnapshotFD);
|
||||||
|
close(dataStreamFD);
|
||||||
close(newSnapshotFD);
|
close(newSnapshotFD);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TEST_BACKUP_HELPERS
|
#endif // TEST_BACKUP_HELPERS
|
||||||
|
|
||||||
|
}
|
@ -3,6 +3,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
using namespace android;
|
||||||
|
|
||||||
#if TEST_BACKUP_HELPERS
|
#if TEST_BACKUP_HELPERS
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
@ -20,6 +22,7 @@ Test TESTS[] = {
|
|||||||
{ "backup_helper_test_empty", backup_helper_test_empty, 0, false },
|
{ "backup_helper_test_empty", backup_helper_test_empty, 0, false },
|
||||||
{ "backup_helper_test_four", backup_helper_test_four, 0, false },
|
{ "backup_helper_test_four", backup_helper_test_four, 0, false },
|
||||||
{ "backup_helper_test_files", backup_helper_test_files, 0, false },
|
{ "backup_helper_test_files", backup_helper_test_files, 0, false },
|
||||||
|
{ "backup_helper_test_data_writer", backup_helper_test_data_writer, 0, false },
|
||||||
{ 0, NULL, 0, false}
|
{ 0, NULL, 0, false}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user