Merge change 4708 into donut
* changes: Make RestoreHelper and friends also write out the snapshot state.
This commit is contained in:
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package android.backup;
|
package android.backup;
|
||||||
|
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@@ -27,5 +29,6 @@ public interface RestoreHelper {
|
|||||||
* <code>dataSize</code> bytes from <code>data</code>.
|
* <code>dataSize</code> bytes from <code>data</code>.
|
||||||
*/
|
*/
|
||||||
public void restoreEntity(BackupDataInputStream data);
|
public void restoreEntity(BackupDataInputStream data);
|
||||||
|
public void writeSnapshot(ParcelFileDescriptor fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,69 +17,66 @@
|
|||||||
package android.backup;
|
package android.backup;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileDescriptor;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
class RestoreHelperBase {
|
class RestoreHelperBase {
|
||||||
private static final String TAG = "RestoreHelperBase";
|
private static final String TAG = "RestoreHelperBase";
|
||||||
private static final int BUF_SIZE = 8 * 1024;
|
|
||||||
|
|
||||||
|
int mPtr;
|
||||||
Context mContext;
|
Context mContext;
|
||||||
byte[] mBuf = new byte[BUF_SIZE];
|
|
||||||
boolean mExceptionLogged;
|
boolean mExceptionLogged;
|
||||||
|
|
||||||
RestoreHelperBase(Context context) {
|
RestoreHelperBase(Context context) {
|
||||||
|
mPtr = ctor();
|
||||||
mContext = context;
|
mContext = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeFile(File f, InputStream in) {
|
protected void finalize() throws Throwable {
|
||||||
boolean success = false;
|
|
||||||
FileOutputStream out = null;
|
|
||||||
try {
|
try {
|
||||||
|
dtor(mPtr);
|
||||||
|
} finally {
|
||||||
|
super.finalize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeFile(File f, InputStream in) {
|
||||||
|
if (!(in instanceof BackupDataInputStream)) {
|
||||||
|
throw new IllegalStateException("input stream must be a BackupDataInputStream");
|
||||||
|
}
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
// Create the enclosing directory.
|
// Create the enclosing directory.
|
||||||
File parent = f.getParentFile();
|
File parent = f.getParentFile();
|
||||||
parent.mkdirs();
|
parent.mkdirs();
|
||||||
|
|
||||||
// Copy the file.
|
result = writeFile_native(mPtr, f.getAbsolutePath(),
|
||||||
int sum = 0;
|
((BackupDataInputStream)in).mData.mBackupReader);
|
||||||
out = new FileOutputStream(f);
|
if (result != 0) {
|
||||||
byte[] buf = mBuf;
|
// Bail on this entity. Only log one failure per helper object.
|
||||||
int amt;
|
|
||||||
while ((amt = in.read(buf)) > 0) {
|
|
||||||
out.write(buf, 0, amt);
|
|
||||||
sum += amt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Set the permissions of the file.
|
|
||||||
|
|
||||||
// We're done
|
|
||||||
success = true;
|
|
||||||
out = null;
|
|
||||||
} catch (IOException ex) {
|
|
||||||
// Bail on this entity. Only log one exception per helper object.
|
|
||||||
if (!mExceptionLogged) {
|
if (!mExceptionLogged) {
|
||||||
Log.e(TAG, "Failed restoring file '" + f + "' for app '"
|
Log.e(TAG, "Failed restoring file '" + f + "' for app '"
|
||||||
+ mContext.getPackageName() + '\'', ex);
|
+ mContext.getPackageName() + "\' result=0x"
|
||||||
|
+ Integer.toHexString(result));
|
||||||
mExceptionLogged = true;
|
mExceptionLogged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
if (out != null) {
|
|
||||||
try {
|
|
||||||
out.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!success) {
|
|
||||||
// Something didn't work out, delete the file
|
|
||||||
f.delete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void writeSnapshot(ParcelFileDescriptor fd) {
|
||||||
|
int result = writeSnapshot_native(mPtr, fd.getFileDescriptor());
|
||||||
|
// TODO: Do something with the error.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static native int ctor();
|
||||||
|
private static native void dtor(int ptr);
|
||||||
|
private static native int writeFile_native(int ptr, String filename, int backupReader);
|
||||||
|
private static native int writeSnapshot_native(int ptr, FileDescriptor fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
package android.backup;
|
package android.backup;
|
||||||
|
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public class RestoreHelperDispatcher {
|
public class RestoreHelperDispatcher {
|
||||||
@@ -31,7 +33,7 @@ public class RestoreHelperDispatcher {
|
|||||||
mHelpers.put(keyPrefix, helper);
|
mHelpers.put(keyPrefix, helper);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispatch(BackupDataInput input) throws IOException {
|
public void dispatch(BackupDataInput input, ParcelFileDescriptor newState) throws IOException {
|
||||||
boolean alreadyComplained = false;
|
boolean alreadyComplained = false;
|
||||||
|
|
||||||
BackupDataInputStream stream = new BackupDataInputStream(input);
|
BackupDataInputStream stream = new BackupDataInputStream(input);
|
||||||
@@ -60,5 +62,17 @@ public class RestoreHelperDispatcher {
|
|||||||
}
|
}
|
||||||
input.skipEntityData(); // In case they didn't consume the data.
|
input.skipEntityData(); // In case they didn't consume the data.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mHelpers.size() > 1) {
|
||||||
|
throw new RuntimeException("RestoreHelperDispatcher won't get your your"
|
||||||
|
+ " data in the right order yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write out the state files
|
||||||
|
for (RestoreHelper helper: mHelpers.values()) {
|
||||||
|
// TODO: Write a header for the state
|
||||||
|
helper.writeSnapshot(newState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -119,7 +119,8 @@ LOCAL_SRC_FILES:= \
|
|||||||
com_android_internal_graphics_NativeUtils.cpp \
|
com_android_internal_graphics_NativeUtils.cpp \
|
||||||
android_backup_BackupDataInput.cpp \
|
android_backup_BackupDataInput.cpp \
|
||||||
android_backup_BackupDataOutput.cpp \
|
android_backup_BackupDataOutput.cpp \
|
||||||
android_backup_FileBackupHelper.cpp
|
android_backup_FileBackupHelper.cpp \
|
||||||
|
android_backup_RestoreHelperBase.cpp
|
||||||
|
|
||||||
LOCAL_C_INCLUDES += \
|
LOCAL_C_INCLUDES += \
|
||||||
$(JNI_H_INCLUDE) \
|
$(JNI_H_INCLUDE) \
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ extern int register_android_location_GpsLocationProvider(JNIEnv* env);
|
|||||||
extern int register_android_backup_BackupDataInput(JNIEnv *env);
|
extern int register_android_backup_BackupDataInput(JNIEnv *env);
|
||||||
extern int register_android_backup_BackupDataOutput(JNIEnv *env);
|
extern int register_android_backup_BackupDataOutput(JNIEnv *env);
|
||||||
extern int register_android_backup_FileBackupHelper(JNIEnv *env);
|
extern int register_android_backup_FileBackupHelper(JNIEnv *env);
|
||||||
|
extern int register_android_backup_RestoreHelperBase(JNIEnv *env);
|
||||||
|
|
||||||
static AndroidRuntime* gCurRuntime = NULL;
|
static AndroidRuntime* gCurRuntime = NULL;
|
||||||
|
|
||||||
@@ -1131,6 +1132,7 @@ static const RegJNIRec gRegJNI[] = {
|
|||||||
REG_JNI(register_android_backup_BackupDataInput),
|
REG_JNI(register_android_backup_BackupDataInput),
|
||||||
REG_JNI(register_android_backup_BackupDataOutput),
|
REG_JNI(register_android_backup_BackupDataOutput),
|
||||||
REG_JNI(register_android_backup_FileBackupHelper),
|
REG_JNI(register_android_backup_FileBackupHelper),
|
||||||
|
REG_JNI(register_android_backup_RestoreHelperBase),
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
94
core/jni/android_backup_RestoreHelperBase.cpp
Normal file
94
core/jni/android_backup_RestoreHelperBase.cpp
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* 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 "FileBackupHelper_native"
|
||||||
|
#include <utils/Log.h>
|
||||||
|
|
||||||
|
#include "JNIHelp.h"
|
||||||
|
#include <android_runtime/AndroidRuntime.h>
|
||||||
|
|
||||||
|
#include <utils/BackupHelpers.h>
|
||||||
|
|
||||||
|
namespace android
|
||||||
|
{
|
||||||
|
|
||||||
|
// java.io.FileDescriptor
|
||||||
|
static jfieldID s_descriptorField = 0;
|
||||||
|
|
||||||
|
static int
|
||||||
|
ctor(JNIEnv* env, jobject clazz)
|
||||||
|
{
|
||||||
|
return (int)new RestoreHelperBase();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dtor(JNIEnv* env, jobject clazz, jint ptr)
|
||||||
|
{
|
||||||
|
delete (RestoreHelperBase*)ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
writeFile_native(JNIEnv* env, jobject clazz, jint ptr, jstring filenameObj, int backupReaderPtr)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
|
||||||
|
BackupDataReader* reader = (BackupDataReader*)backupReaderPtr;
|
||||||
|
char const* filename;
|
||||||
|
|
||||||
|
filename = env->GetStringUTFChars(filenameObj, NULL);
|
||||||
|
|
||||||
|
err = restore->WriteFile(String8(filename), reader);
|
||||||
|
|
||||||
|
env->ReleaseStringUTFChars(filenameObj, filename);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
writeSnapshot_native(JNIEnv* env, jobject clazz, jint ptr, jobject fileDescriptor)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
|
||||||
|
int fd = env->GetIntField(fileDescriptor, s_descriptorField);
|
||||||
|
|
||||||
|
err = restore->WriteSnapshot(fd);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const JNINativeMethod g_methods[] = {
|
||||||
|
{ "ctor", "()I", (void*)ctor },
|
||||||
|
{ "dtor", "(I)V", (void*)dtor },
|
||||||
|
{ "writeFile_native", "(ILjava/lang/String;I)I", (void*)writeFile_native },
|
||||||
|
{ "writeSnapshot_native", "(ILjava/io/FileDescriptor;)I", (void*)writeSnapshot_native },
|
||||||
|
};
|
||||||
|
|
||||||
|
int register_android_backup_RestoreHelperBase(JNIEnv* env)
|
||||||
|
{
|
||||||
|
jclass clazz;
|
||||||
|
|
||||||
|
clazz = env->FindClass("java/io/FileDescriptor");
|
||||||
|
LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
|
||||||
|
s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
|
||||||
|
LOG_FATAL_IF(s_descriptorField == NULL,
|
||||||
|
"Unable to find descriptor field in java.io.FileDescriptor");
|
||||||
|
|
||||||
|
return AndroidRuntime::registerNativeMethods(env, "android/backup/RestoreHelperBase",
|
||||||
|
g_methods, NELEM(g_methods));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <utils/Errors.h>
|
#include <utils/Errors.h>
|
||||||
#include <utils/String8.h>
|
#include <utils/String8.h>
|
||||||
|
#include <utils/KeyedVector.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
@@ -32,6 +33,27 @@ typedef struct {
|
|||||||
int dataSize; // size of the data, not including the padding, -1 means delete
|
int dataSize; // size of the data, not including the padding, -1 means delete
|
||||||
} entity_header_v1;
|
} entity_header_v1;
|
||||||
|
|
||||||
|
struct SnapshotHeader {
|
||||||
|
int magic0;
|
||||||
|
int fileCount;
|
||||||
|
int magic1;
|
||||||
|
int totalSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FileState {
|
||||||
|
int modTime_sec;
|
||||||
|
int modTime_nsec;
|
||||||
|
int size;
|
||||||
|
int crc32;
|
||||||
|
int nameLen;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FileRec {
|
||||||
|
String8 file;
|
||||||
|
bool deleted;
|
||||||
|
FileState s;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the data.
|
* Writes the data.
|
||||||
@@ -99,6 +121,19 @@ private:
|
|||||||
int back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD,
|
int back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD,
|
||||||
char const* const* files, char const* const *keys, int fileCount);
|
char const* const* files, char const* const *keys, int fileCount);
|
||||||
|
|
||||||
|
class RestoreHelperBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RestoreHelperBase();
|
||||||
|
~RestoreHelperBase();
|
||||||
|
|
||||||
|
status_t WriteFile(const String8& filename, BackupDataReader* in);
|
||||||
|
status_t WriteSnapshot(int fd);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* m_buf;
|
||||||
|
KeyedVector<String8,FileRec> m_files;
|
||||||
|
};
|
||||||
|
|
||||||
#define TEST_BACKUP_HELPERS 1
|
#define TEST_BACKUP_HELPERS 1
|
||||||
|
|
||||||
|
|||||||
@@ -47,27 +47,6 @@ namespace android {
|
|||||||
#define LOGP(x...) LOGD(x)
|
#define LOGP(x...) LOGD(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct SnapshotHeader {
|
|
||||||
int magic0;
|
|
||||||
int fileCount;
|
|
||||||
int magic1;
|
|
||||||
int totalSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FileState {
|
|
||||||
int modTime_sec;
|
|
||||||
int modTime_nsec;
|
|
||||||
int size;
|
|
||||||
int crc32;
|
|
||||||
int nameLen;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FileRec {
|
|
||||||
char const* file; // this object does not own this string
|
|
||||||
bool deleted;
|
|
||||||
FileState s;
|
|
||||||
};
|
|
||||||
|
|
||||||
const static int ROUND_UP[4] = { 0, 3, 2, 1 };
|
const static int ROUND_UP[4] = { 0, 3, 2, 1 };
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
@@ -310,7 +289,8 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD
|
|||||||
for (int i=0; i<fileCount; i++) {
|
for (int i=0; i<fileCount; i++) {
|
||||||
String8 key(keys[i]);
|
String8 key(keys[i]);
|
||||||
FileRec r;
|
FileRec r;
|
||||||
char const* file = r.file = files[i];
|
char const* file = files[i];
|
||||||
|
r.file = file;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
err = stat(file, &st);
|
err = stat(file, &st);
|
||||||
@@ -351,20 +331,20 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD
|
|||||||
}
|
}
|
||||||
else if (cmp > 0) {
|
else if (cmp > 0) {
|
||||||
// file added
|
// file added
|
||||||
LOGP("file added: %s", g.file);
|
LOGP("file added: %s", g.file.string());
|
||||||
write_update_file(dataStream, q, g.file);
|
write_update_file(dataStream, q, g.file.string());
|
||||||
m++;
|
m++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// both files exist, check them
|
// both files exist, check them
|
||||||
const FileState& f = oldSnapshot.valueAt(n);
|
const FileState& f = oldSnapshot.valueAt(n);
|
||||||
|
|
||||||
int fd = open(g.file, O_RDONLY);
|
int fd = open(g.file.string(), O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
// We can't open the file. Don't report it as a delete either. Let the
|
// We can't open the file. Don't report it as a delete either. Let the
|
||||||
// server keep the old version. Maybe they'll be able to deal with it
|
// server keep the old version. Maybe they'll be able to deal with it
|
||||||
// on restore.
|
// on restore.
|
||||||
LOGP("Unable to open file %s - skipping", g.file);
|
LOGP("Unable to open file %s - skipping", g.file.string());
|
||||||
} else {
|
} else {
|
||||||
g.s.crc32 = compute_crc32(fd);
|
g.s.crc32 = compute_crc32(fd);
|
||||||
|
|
||||||
@@ -375,7 +355,7 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD
|
|||||||
g.s.modTime_sec, g.s.modTime_nsec, g.s.size, g.s.crc32);
|
g.s.modTime_sec, g.s.modTime_nsec, g.s.size, g.s.crc32);
|
||||||
if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec
|
if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec
|
||||||
|| f.size != g.s.size || f.crc32 != g.s.crc32) {
|
|| f.size != g.s.size || f.crc32 != g.s.crc32) {
|
||||||
write_update_file(dataStream, fd, p, g.file);
|
write_update_file(dataStream, fd, p, g.file.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
@@ -395,7 +375,7 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD
|
|||||||
while (m<fileCount) {
|
while (m<fileCount) {
|
||||||
const String8& q = newSnapshot.keyAt(m);
|
const String8& q = newSnapshot.keyAt(m);
|
||||||
FileRec& g = newSnapshot.editValueAt(m);
|
FileRec& g = newSnapshot.editValueAt(m);
|
||||||
write_update_file(dataStream, q, g.file);
|
write_update_file(dataStream, q, g.file.string());
|
||||||
m++;
|
m++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,6 +384,84 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define RESTORE_BUF_SIZE (8*1024)
|
||||||
|
|
||||||
|
RestoreHelperBase::RestoreHelperBase()
|
||||||
|
{
|
||||||
|
m_buf = malloc(RESTORE_BUF_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
RestoreHelperBase::~RestoreHelperBase()
|
||||||
|
{
|
||||||
|
free(m_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RestoreHelperBase::WriteFile(const String8& filename, BackupDataReader* in)
|
||||||
|
{
|
||||||
|
ssize_t err;
|
||||||
|
size_t dataSize;
|
||||||
|
String8 key;
|
||||||
|
int fd;
|
||||||
|
void* buf = m_buf;
|
||||||
|
ssize_t amt;
|
||||||
|
int mode;
|
||||||
|
int crc;
|
||||||
|
struct stat st;
|
||||||
|
FileRec r;
|
||||||
|
|
||||||
|
err = in->ReadEntityHeader(&key, &dataSize);
|
||||||
|
if (err != NO_ERROR) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: World readable/writable for now.
|
||||||
|
mode = 0666;
|
||||||
|
|
||||||
|
// Write the file and compute the crc
|
||||||
|
crc = crc32(0L, Z_NULL, 0);
|
||||||
|
fd = open(filename.string(), O_CREAT|O_RDWR, mode);
|
||||||
|
if (fd != -1) {
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((amt = in->ReadEntityData(buf, RESTORE_BUF_SIZE)) > 0) {
|
||||||
|
err = write(fd, buf, amt);
|
||||||
|
if (err != amt) {
|
||||||
|
close(fd);
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
crc = crc32(crc, (Bytef*)buf, amt);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
// Record for the snapshot
|
||||||
|
err = stat(filename.string(), &st);
|
||||||
|
if (err != 0) {
|
||||||
|
LOGW("Error stating file that we just created %s", filename.string());
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
r.file = filename;
|
||||||
|
r.deleted = false;
|
||||||
|
r.s.modTime_sec = st.st_mtime;
|
||||||
|
r.s.modTime_nsec = 0; // workaround sim breakage
|
||||||
|
//r.s.modTime_nsec = st.st_mtime_nsec;
|
||||||
|
r.s.size = st.st_size;
|
||||||
|
r.s.crc32 = crc;
|
||||||
|
|
||||||
|
m_files.add(key, r);
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RestoreHelperBase::WriteSnapshot(int fd)
|
||||||
|
{
|
||||||
|
return write_snapshot_file(fd, m_files);;
|
||||||
|
}
|
||||||
|
|
||||||
#if TEST_BACKUP_HELPERS
|
#if TEST_BACKUP_HELPERS
|
||||||
|
|
||||||
#define SCRATCH_DIR "/data/backup_helper_test/"
|
#define SCRATCH_DIR "/data/backup_helper_test/"
|
||||||
@@ -560,7 +618,6 @@ backup_helper_test_four()
|
|||||||
FileState states[4];
|
FileState states[4];
|
||||||
FileRec r;
|
FileRec r;
|
||||||
r.deleted = false;
|
r.deleted = false;
|
||||||
r.file = NULL;
|
|
||||||
|
|
||||||
states[0].modTime_sec = 0xfedcba98;
|
states[0].modTime_sec = 0xfedcba98;
|
||||||
states[0].modTime_nsec = 0xdeadbeef;
|
states[0].modTime_nsec = 0xdeadbeef;
|
||||||
|
|||||||
@@ -161,8 +161,13 @@ public class BackupTestActivity extends ListActivity
|
|||||||
new FileRestoreHelper(BackupTestActivity.this));
|
new FileRestoreHelper(BackupTestActivity.this));
|
||||||
FileInputStream dataFile = openFileInput("backup_test");
|
FileInputStream dataFile = openFileInput("backup_test");
|
||||||
BackupDataInput data = new BackupDataInput(dataFile.getFD());
|
BackupDataInput data = new BackupDataInput(dataFile.getFD());
|
||||||
dispatch.dispatch(data);
|
ParcelFileDescriptor state = ParcelFileDescriptor.open(
|
||||||
|
new File(getFilesDir(), "restore_state"),
|
||||||
|
ParcelFileDescriptor.MODE_READ_WRITE|ParcelFileDescriptor.MODE_CREATE|
|
||||||
|
ParcelFileDescriptor.MODE_TRUNCATE);
|
||||||
|
dispatch.dispatch(data, state);
|
||||||
dataFile.close();
|
dataFile.close();
|
||||||
|
state.close();
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class BackupTestAgent extends BackupAgent
|
|||||||
// dispatch.addHelper(SHARED_PREFS, new SharedPrefsRestoreHelper(this));
|
// dispatch.addHelper(SHARED_PREFS, new SharedPrefsRestoreHelper(this));
|
||||||
dispatch.addHelper(DATA_FILES, new FileRestoreHelper(this));
|
dispatch.addHelper(DATA_FILES, new FileRestoreHelper(this));
|
||||||
|
|
||||||
dispatch.dispatch(data);
|
dispatch.dispatch(data, newState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user