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

Commit 1a9e19a7 authored by Joe Onorato's avatar Joe Onorato
Browse files

Make the file backup helper not crash if a file you requested

can't be stated.  This means you don't need to know if the files
you are backing up exist or not -- we'll figure it out for you.
parent 0ad6120d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -128,6 +128,7 @@ int backup_helper_test_empty();
int backup_helper_test_four();
int backup_helper_test_files();
int backup_helper_test_null_base();
int backup_helper_test_missing_file();
int backup_helper_test_data_writer();
int backup_helper_test_data_reader();
#endif
+108 −45
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ struct FileState {

struct FileRec {
    char const* file; // this object does not own this string
    bool deleted;
    FileState s;
};

@@ -135,18 +136,23 @@ read_snapshot_file(int fd, KeyedVector<String8,FileState>* snapshot)
static int
write_snapshot_file(int fd, const KeyedVector<String8,FileRec>& snapshot)
{
    int fileCount = 0;
    int bytesWritten = sizeof(SnapshotHeader);
    // preflight size
    const int N = snapshot.size();
    for (int i=0; i<N; i++) {
        const FileRec& g = snapshot.valueAt(i);
        if (!g.deleted) {
            const String8& name = snapshot.keyAt(i);
            bytesWritten += sizeof(FileState) + round_up(name.length());
            fileCount++;
        }
    }

    LOGP("write_snapshot_file fd=%d\n", fd);

    int amt;
    SnapshotHeader header = { MAGIC0, N, MAGIC1, bytesWritten };
    SnapshotHeader header = { MAGIC0, fileCount, MAGIC1, bytesWritten };

    amt = write(fd, &header, sizeof(header));
    if (amt != sizeof(header)) {
@@ -154,9 +160,10 @@ write_snapshot_file(int fd, const KeyedVector<String8,FileRec>& snapshot)
        return errno;
    }

    for (int i=0; i<header.fileCount; i++) {
        const String8& name = snapshot.keyAt(i);
    for (int i=0; i<N; i++) {
        FileRec r = snapshot.valueAt(i);
        if (!r.deleted) {
            const String8& name = snapshot.keyAt(i);
            int nameLen = r.s.nameLen = name.length();

            amt = write(fd, &r.s, sizeof(FileState));
@@ -182,6 +189,7 @@ write_snapshot_file(int fd, const KeyedVector<String8,FileRec>& snapshot)
                }
            }
        }
    }

    return 0;
}
@@ -308,9 +316,9 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD
        err = stat(file, &st);
        if (err != 0) {
            LOGW("Error stating file %s", file);
            continue;
        }

            r.deleted = true;
        } else {
            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;
@@ -321,6 +329,7 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD
                LOGP("back_up_files key already in use '%s'", key.string());
                return -1;
            }
        }
        newSnapshot.add(key, r);
    }

@@ -331,24 +340,24 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD
    while (n<N && m<fileCount) {
        const String8& p = oldSnapshot.keyAt(n);
        const String8& q = newSnapshot.keyAt(m);
        FileRec& g = newSnapshot.editValueAt(m);
        int cmp = p.compare(q);
        if (cmp > 0) {
            // file added
            const FileRec& g = newSnapshot.valueAt(m);
            LOGP("file added: %s", g.file);
            write_update_file(dataStream, q, g.file);
            m++;
        }
        else if (cmp < 0) {
        if (g.deleted || cmp < 0) {
            // file removed
            LOGP("file removed: %s", p.string());
            g.deleted = true; // They didn't mention the file, but we noticed that it's gone.
            dataStream->WriteEntityHeader(p, -1);
            n++;
        }
        else if (cmp > 0) {
            // file added
            LOGP("file added: %s", g.file);
            write_update_file(dataStream, q, g.file);
            m++;
        }
        else {
            // both files exist, check them
            const FileState& f = oldSnapshot.valueAt(n);
            FileRec& g = newSnapshot.editValueAt(m);

            int fd = open(g.file, O_RDONLY);
            if (fd < 0) {
@@ -550,6 +559,7 @@ backup_helper_test_four()
    String8 filenames[4];
    FileState states[4];
    FileRec r;
    r.deleted = false;
    r.file = NULL;

    states[0].modTime_sec = 0xfedcba98;
@@ -1149,6 +1159,59 @@ backup_helper_test_null_base()
    return 0;
}

int
backup_helper_test_missing_file()
{
    int err;
    int oldSnapshotFD;
    int dataStreamFD;
    int newSnapshotFD;

    system("rm -r " SCRATCH_DIR);
    mkdir(SCRATCH_DIR, 0777);
    mkdir(SCRATCH_DIR "data", 0777);

    write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");

    char const* files[] = {
        SCRATCH_DIR "data/a",
        SCRATCH_DIR "data/b",
        SCRATCH_DIR "data/c",
    };

    char const* keys[] = {
        "a",
        "b",
        "c",
    };

    dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
    if (dataStreamFD == -1) {
        fprintf(stderr, "error creating: %s\n", strerror(errno));
        return errno;
    }

    newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
    if (newSnapshotFD == -1) {
        fprintf(stderr, "error creating: %s\n", strerror(errno));
        return errno;
    }

    {
        BackupDataWriter dataStream(dataStreamFD);

        err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
        if (err != 0) {
            return err;
        }
    }

    close(dataStreamFD);
    close(newSnapshotFD);

    return 0;
}


#endif // TEST_BACKUP_HELPERS