Implement the C++ class to write the backed up file data.
This commit is contained in:
parent
b81a9a18e5
commit
62a381bd13
|
@ -38,6 +38,16 @@
|
|||
* 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
|
||||
|
||||
#if BYTE_ORDER == DEVICE_BYTE_ORDER
|
||||
|
@ -49,16 +59,6 @@
|
|||
|
||||
#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 dtohs(x) (android_swap_short(x))
|
||||
#define htodl(x) (android_swap_long(x))
|
||||
|
@ -66,4 +66,16 @@ static inline uint16_t android_swap_short(uint16_t v)
|
|||
|
||||
#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
|
||||
|
|
|
@ -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
|
||||
#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,
|
||||
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
|
||||
|
||||
#if TEST_BACKUP_HELPERS
|
||||
int backup_helper_test_empty();
|
||||
int backup_helper_test_four();
|
||||
int backup_helper_test_files();
|
||||
int backup_helper_test_data_writer();
|
||||
#endif
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // _UTILS_BACKUP_HELPERS_H
|
||||
|
|
|
@ -117,7 +117,8 @@ LOCAL_SRC_FILES:= \
|
|||
IPermissionController.cpp \
|
||||
IServiceManager.cpp \
|
||||
Unicode.cpp \
|
||||
file_backup_helper.cpp
|
||||
backup_data.cpp \
|
||||
backup_helper_file.cpp
|
||||
|
||||
ifeq ($(TARGET_SIMULATOR),true)
|
||||
LOCAL_SRC_FILES += $(hostSources)
|
||||
|
|
|
@ -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"
|
||||
|
||||
#include <utils/backup_helpers.h>
|
||||
|
@ -19,13 +35,16 @@
|
|||
|
||||
#include <cutils/log.h>
|
||||
|
||||
using namespace android;
|
||||
namespace android {
|
||||
|
||||
#define MAGIC0 0x70616e53 // Snap
|
||||
#define MAGIC1 0x656c6946 // File
|
||||
|
||||
#if TEST_BACKUP_HELPERS
|
||||
#define LOGP(x...) printf(x)
|
||||
#else
|
||||
#define LOGP(x...) LOGD(x)
|
||||
//#define LOGP(x...) printf(x)
|
||||
#endif
|
||||
|
||||
struct SnapshotHeader {
|
||||
int magic0;
|
||||
|
@ -118,6 +137,8 @@ write_snapshot_file(int fd, const KeyedVector<String8,FileState>& snapshot)
|
|||
bytesWritten += sizeof(FileState) + round_up(name.length());
|
||||
}
|
||||
|
||||
LOGP("write_snapshot_file fd=%d\n", fd);
|
||||
|
||||
int amt;
|
||||
SnapshotHeader header = { MAGIC0, N, MAGIC1, bytesWritten };
|
||||
|
||||
|
@ -248,11 +269,13 @@ back_up_files(int oldSnapshotFD, int oldDataStream, int newSnapshotFD,
|
|||
// file added
|
||||
String8 realFilename(base);
|
||||
realFilename.appendPath(q);
|
||||
LOGP("file added: %s\n", realFilename.string());
|
||||
write_update_file(realFilename, q);
|
||||
m++;
|
||||
}
|
||||
else if (cmp < 0) {
|
||||
// file removed
|
||||
LOGP("file removed: %s\n", p.string());
|
||||
write_delete_file(p);
|
||||
n++;
|
||||
}
|
||||
|
@ -573,6 +596,107 @@ backup_helper_test_four()
|
|||
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
|
||||
get_mod_time(const char* filename, struct timeval times[2])
|
||||
{
|
||||
|
@ -594,8 +718,9 @@ int
|
|||
backup_helper_test_files()
|
||||
{
|
||||
int err;
|
||||
int newSnapshotFD;
|
||||
int oldSnapshotFD;
|
||||
int dataStreamFD;
|
||||
int newSnapshotFD;
|
||||
|
||||
system("rm -r " SCRATCH_DIR);
|
||||
mkdir(SCRATCH_DIR, 0777);
|
||||
|
@ -616,17 +741,24 @@ backup_helper_test_files()
|
|||
"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);
|
||||
if (newSnapshotFD == -1) {
|
||||
fprintf(stderr, "error creating: %s\n", strerror(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) {
|
||||
return err;
|
||||
}
|
||||
|
||||
close(dataStreamFD);
|
||||
close(newSnapshotFD);
|
||||
|
||||
sleep(3);
|
||||
|
@ -665,21 +797,30 @@ backup_helper_test_files()
|
|||
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);
|
||||
if (newSnapshotFD == -1) {
|
||||
fprintf(stderr, "error creating: %s\n", strerror(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) {
|
||||
return err;
|
||||
}
|
||||
|
||||
close(oldSnapshotFD);
|
||||
close(dataStreamFD);
|
||||
close(newSnapshotFD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // TEST_BACKUP_HELPERS
|
||||
|
||||
}
|
Loading…
Reference in New Issue