Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1c555097 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 4708 into donut

* changes:
  Make RestoreHelper and friends also write out the snapshot state.
parents 88247e0a da1430be
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include <utils/Errors.h>
#include <utils/String8.h>
#include <utils/KeyedVector.h>

namespace android {

@@ -32,6 +33,27 @@ typedef struct {
    int dataSize; // size of the data, not including the padding, -1 means delete
} 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.
@@ -99,6 +121,19 @@ private:
int back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD,
        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

+86 −29
Original line number Diff line number Diff line
@@ -47,27 +47,6 @@ namespace android {
#define LOGP(x...) LOGD(x)
#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 };

static inline int
@@ -310,7 +289,8 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD
    for (int i=0; i<fileCount; i++) {
        String8 key(keys[i]);
        FileRec r;
        char const* file = r.file = files[i];
        char const* file = files[i];
        r.file = file;
        struct stat st;

        err = stat(file, &st);
@@ -351,20 +331,20 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD
        }
        else if (cmp > 0) {
            // file added
            LOGP("file added: %s", g.file);
            write_update_file(dataStream, q, g.file);
            LOGP("file added: %s", g.file.string());
            write_update_file(dataStream, q, g.file.string());
            m++;
        }
        else {
            // both files exist, check them
            const FileState& f = oldSnapshot.valueAt(n);

            int fd = open(g.file, O_RDONLY);
            int fd = open(g.file.string(), O_RDONLY);
            if (fd < 0) {
                // 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
                // on restore.
                LOGP("Unable to open file %s - skipping", g.file);
                LOGP("Unable to open file %s - skipping", g.file.string());
            } else {
                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);
                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) {
                    write_update_file(dataStream, fd, p, g.file);
                    write_update_file(dataStream, fd, p, g.file.string());
                }

                close(fd);
@@ -395,7 +375,7 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD
    while (m<fileCount) {
        const String8& q = newSnapshot.keyAt(m);
        FileRec& g = newSnapshot.editValueAt(m);
        write_update_file(dataStream, q, g.file);
        write_update_file(dataStream, q, g.file.string());
        m++;
    }

@@ -404,6 +384,84 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD
    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

#define SCRATCH_DIR "/data/backup_helper_test/"
@@ -560,7 +618,6 @@ backup_helper_test_four()
    FileState states[4];
    FileRec r;
    r.deleted = false;
    r.file = NULL;

    states[0].modTime_sec = 0xfedcba98;
    states[0].modTime_nsec = 0xdeadbeef;