summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--applypatch/Android.mk4
-rw-r--r--applypatch/applypatch.cpp49
-rw-r--r--otafault/Android.mk58
-rw-r--r--otafault/ota_io.cpp160
-rw-r--r--otafault/ota_io.h49
-rw-r--r--otafault/test.cpp32
-rw-r--r--recovery.cpp24
-rw-r--r--roots.cpp8
-rw-r--r--roots.h6
-rw-r--r--updater/Android.mk2
-rw-r--r--updater/blockimg.cpp13
-rw-r--r--updater/install.cpp25
13 files changed, 383 insertions, 48 deletions
diff --git a/Android.mk b/Android.mk
index 602a85673..13fc04bcc 100644
--- a/Android.mk
+++ b/Android.mk
@@ -135,6 +135,7 @@ include $(LOCAL_PATH)/minui/Android.mk \
$(LOCAL_PATH)/tools/Android.mk \
$(LOCAL_PATH)/edify/Android.mk \
$(LOCAL_PATH)/uncrypt/Android.mk \
+ $(LOCAL_PATH)/otafault/Android.mk \
$(LOCAL_PATH)/updater/Android.mk \
$(LOCAL_PATH)/update_verifier/Android.mk \
$(LOCAL_PATH)/applypatch/Android.mk
diff --git a/applypatch/Android.mk b/applypatch/Android.mk
index 036b6f50d..bc2e69e62 100644
--- a/applypatch/Android.mk
+++ b/applypatch/Android.mk
@@ -21,7 +21,7 @@ LOCAL_SRC_FILES := applypatch.cpp bspatch.cpp freecache.cpp imgpatch.cpp utils.c
LOCAL_MODULE := libapplypatch
LOCAL_MODULE_TAGS := eng
LOCAL_C_INCLUDES += bootable/recovery
-LOCAL_STATIC_LIBRARIES += libbase libmtdutils libmincrypt libbz libz
+LOCAL_STATIC_LIBRARIES += libbase libotafault libmtdutils libmincrypt libbz libz
include $(BUILD_STATIC_LIBRARY)
@@ -55,7 +55,7 @@ LOCAL_CLANG := true
LOCAL_SRC_FILES := main.cpp
LOCAL_MODULE := applypatch
LOCAL_C_INCLUDES += bootable/recovery
-LOCAL_STATIC_LIBRARIES += libapplypatch libbase libmtdutils libmincrypt libbz
+LOCAL_STATIC_LIBRARIES += libapplypatch libbase libotafault libmtdutils libmincrypt libbz
LOCAL_SHARED_LIBRARIES += libz libcutils libc
include $(BUILD_EXECUTABLE)
diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp
index f9425af93..93e6b25ac 100644
--- a/applypatch/applypatch.cpp
+++ b/applypatch/applypatch.cpp
@@ -32,6 +32,7 @@
#include "mtdutils/mtdutils.h"
#include "edify/expr.h"
#include "print_sha1.h"
+#include "otafault/ota_io.h"
static int LoadPartitionContents(const char* filename, FileContents* file);
static ssize_t FileSink(const unsigned char* data, ssize_t len, void* token);
@@ -69,7 +70,7 @@ int LoadFileContents(const char* filename, FileContents* file) {
file->size = file->st.st_size;
file->data = reinterpret_cast<unsigned char*>(malloc(file->size));
- FILE* f = fopen(filename, "rb");
+ FILE* f = ota_fopen(filename, "rb");
if (f == NULL) {
printf("failed to open \"%s\": %s\n", filename, strerror(errno));
free(file->data);
@@ -77,14 +78,14 @@ int LoadFileContents(const char* filename, FileContents* file) {
return -1;
}
- size_t bytes_read = fread(file->data, 1, file->size, f);
+ size_t bytes_read = ota_fread(file->data, 1, file->size, f);
if (bytes_read != static_cast<size_t>(file->size)) {
printf("short read of \"%s\" (%zu bytes of %zd)\n", filename, bytes_read, file->size);
free(file->data);
file->data = NULL;
return -1;
}
- fclose(f);
+ ota_fclose(f);
SHA_hash(file->data, file->size, file->sha1);
return 0;
@@ -173,7 +174,7 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
}
case EMMC:
- dev = fopen(partition, "rb");
+ dev = ota_fopen(partition, "rb");
if (dev == NULL) {
printf("failed to open emmc partition \"%s\": %s\n", partition, strerror(errno));
return -1;
@@ -202,7 +203,7 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
break;
case EMMC:
- read = fread(p, 1, next, dev);
+ read = ota_fread(p, 1, next, dev);
break;
}
if (next != read) {
@@ -247,7 +248,7 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
break;
case EMMC:
- fclose(dev);
+ ota_fclose(dev);
break;
}
@@ -277,7 +278,7 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
// Save the contents of the given FileContents object under the given
// filename. Return 0 on success.
int SaveFileContents(const char* filename, const FileContents* file) {
- int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR);
+ int fd = ota_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR);
if (fd < 0) {
printf("failed to open \"%s\" for write: %s\n", filename, strerror(errno));
return -1;
@@ -287,14 +288,14 @@ int SaveFileContents(const char* filename, const FileContents* file) {
if (bytes_written != file->size) {
printf("short write of \"%s\" (%zd bytes of %zd) (%s)\n",
filename, bytes_written, file->size, strerror(errno));
- close(fd);
+ ota_close(fd);
return -1;
}
- if (fsync(fd) != 0) {
+ if (ota_fsync(fd) != 0) {
printf("fsync of \"%s\" failed: %s\n", filename, strerror(errno));
return -1;
}
- if (close(fd) != 0) {
+ if (ota_close(fd) != 0) {
printf("close of \"%s\" failed: %s\n", filename, strerror(errno));
return -1;
}
@@ -377,7 +378,7 @@ int WriteToPartition(unsigned char* data, size_t len, const char* target) {
case EMMC: {
size_t start = 0;
bool success = false;
- int fd = open(partition, O_RDWR | O_SYNC);
+ int fd = ota_open(partition, O_RDWR | O_SYNC);
if (fd < 0) {
printf("failed to open %s: %s\n", partition, strerror(errno));
return -1;
@@ -392,22 +393,22 @@ int WriteToPartition(unsigned char* data, size_t len, const char* target) {
size_t to_write = len - start;
if (to_write > 1<<20) to_write = 1<<20;
- ssize_t written = TEMP_FAILURE_RETRY(write(fd, data+start, to_write));
+ ssize_t written = TEMP_FAILURE_RETRY(ota_write(fd, data+start, to_write));
if (written == -1) {
printf("failed write writing to %s: %s\n", partition, strerror(errno));
return -1;
}
start += written;
}
- if (fsync(fd) != 0) {
+ if (ota_fsync(fd) != 0) {
printf("failed to sync to %s (%s)\n", partition, strerror(errno));
return -1;
}
- if (close(fd) != 0) {
+ if (ota_close(fd) != 0) {
printf("failed to close %s (%s)\n", partition, strerror(errno));
return -1;
}
- fd = open(partition, O_RDONLY);
+ fd = ota_open(partition, O_RDONLY);
if (fd < 0) {
printf("failed to reopen %s for verify (%s)\n", partition, strerror(errno));
return -1;
@@ -416,13 +417,13 @@ int WriteToPartition(unsigned char* data, size_t len, const char* target) {
// Drop caches so our subsequent verification read
// won't just be reading the cache.
sync();
- int dc = open("/proc/sys/vm/drop_caches", O_WRONLY);
- if (TEMP_FAILURE_RETRY(write(dc, "3\n", 2)) == -1) {
+ int dc = ota_open("/proc/sys/vm/drop_caches", O_WRONLY);
+ if (TEMP_FAILURE_RETRY(ota_write(dc, "3\n", 2)) == -1) {
printf("write to /proc/sys/vm/drop_caches failed: %s\n", strerror(errno));
} else {
printf(" caches dropped\n");
}
- close(dc);
+ ota_close(dc);
sleep(1);
// verify
@@ -442,7 +443,7 @@ int WriteToPartition(unsigned char* data, size_t len, const char* target) {
size_t so_far = 0;
while (so_far < to_read) {
ssize_t read_count =
- TEMP_FAILURE_RETRY(read(fd, buffer+so_far, to_read-so_far));
+ TEMP_FAILURE_RETRY(ota_read(fd, buffer+so_far, to_read-so_far));
if (read_count == -1) {
printf("verify read error %s at %zu: %s\n",
partition, p, strerror(errno));
@@ -474,7 +475,7 @@ int WriteToPartition(unsigned char* data, size_t len, const char* target) {
return -1;
}
- if (close(fd) != 0) {
+ if (ota_close(fd) != 0) {
printf("error closing %s (%s)\n", partition, strerror(errno));
return -1;
}
@@ -584,7 +585,7 @@ ssize_t FileSink(const unsigned char* data, ssize_t len, void* token) {
ssize_t done = 0;
ssize_t wrote;
while (done < len) {
- wrote = TEMP_FAILURE_RETRY(write(fd, data+done, len-done));
+ wrote = TEMP_FAILURE_RETRY(ota_write(fd, data+done, len-done));
if (wrote == -1) {
printf("error writing %zd bytes: %s\n", (len-done), strerror(errno));
return done;
@@ -944,7 +945,7 @@ static int GenerateTarget(FileContents* source_file,
strcpy(outname, target_filename);
strcat(outname, ".patch");
- output = open(outname, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR);
+ output = ota_open(outname, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR);
if (output < 0) {
printf("failed to open output file %s: %s\n",
outname, strerror(errno));
@@ -975,11 +976,11 @@ static int GenerateTarget(FileContents* source_file,
}
if (output >= 0) {
- if (fsync(output) != 0) {
+ if (ota_fsync(output) != 0) {
printf("failed to fsync file \"%s\" (%s)\n", outname, strerror(errno));
result = 1;
}
- if (close(output) != 0) {
+ if (ota_close(output) != 0) {
printf("failed to close file \"%s\" (%s)\n", outname, strerror(errno));
result = 1;
}
diff --git a/otafault/Android.mk b/otafault/Android.mk
new file mode 100644
index 000000000..75617a146
--- /dev/null
+++ b/otafault/Android.mk
@@ -0,0 +1,58 @@
+# Copyright 2015 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 languae governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+empty :=
+space := $(empty) $(empty)
+comma := ,
+
+ifneq ($(TARGET_INJECT_FAULTS),)
+TARGET_INJECT_FAULTS := $(subst $(comma),$(space),$(strip $(TARGET_INJECT_FAULTS)))
+endif
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := ota_io.cpp
+LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE := libotafault
+LOCAL_CLANG := true
+
+ifneq ($(TARGET_INJECT_FAULTS),)
+$(foreach ft,$(TARGET_INJECT_FAULTS),\
+ $(eval LOCAL_CFLAGS += -DTARGET_$(ft)_FAULT=$(TARGET_$(ft)_FAULT_FILE)))
+LOCAL_CFLAGS += -Wno-unused-parameter
+LOCAL_CFLAGS += -DTARGET_INJECT_FAULTS
+endif
+
+LOCAL_STATIC_LIBRARIES := libc
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := ota_io.cpp test.cpp
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE := otafault_test
+LOCAL_STATIC_LIBRARIES := libc
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_CFLAGS += -Wno-unused-parameter -Wno-writable-strings
+
+ifneq ($(TARGET_INJECT_FAULTS),)
+$(foreach ft,$(TARGET_INJECT_FAULTS),\
+ $(eval LOCAL_CFLAGS += -DTARGET_$(ft)_FAULT=$(TARGET_$(ft)_FAULT_FILE)))
+LOCAL_CFLAGS += -DTARGET_INJECT_FAULTS
+endif
+
+include $(BUILD_EXECUTABLE)
diff --git a/otafault/ota_io.cpp b/otafault/ota_io.cpp
new file mode 100644
index 000000000..02e80f9bf
--- /dev/null
+++ b/otafault/ota_io.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#if defined (TARGET_INJECT_FAULTS)
+#include <map>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "ota_io.h"
+
+#if defined (TARGET_INJECT_FAULTS)
+static std::map<int, const char*> FilenameCache;
+static std::string FaultFileName =
+#if defined (TARGET_READ_FAULT)
+ TARGET_READ_FAULT;
+#elif defined (TARGET_WRITE_FAULT)
+ TARGET_WRITE_FAULT;
+#elif defined (TARGET_FSYNC_FAULT)
+ TARGET_FSYNC_FAULT;
+#endif // defined (TARGET_READ_FAULT)
+#endif // defined (TARGET_INJECT_FAULTS)
+
+int ota_open(const char* path, int oflags) {
+#if defined (TARGET_INJECT_FAULTS)
+ // Let the caller handle errors; we do not care if open succeeds or fails
+ int fd = open(path, oflags);
+ FilenameCache[fd] = path;
+ return fd;
+#else
+ return open(path, oflags);
+#endif
+}
+
+int ota_open(const char* path, int oflags, mode_t mode) {
+#if defined (TARGET_INJECT_FAULTS)
+ int fd = open(path, oflags, mode);
+ FilenameCache[fd] = path;
+ return fd;
+#else
+ return open(path, oflags, mode);
+#endif
+}
+
+FILE* ota_fopen(const char* path, const char* mode) {
+#if defined (TARGET_INJECT_FAULTS)
+ FILE* fh = fopen(path, mode);
+ FilenameCache[(intptr_t)fh] = path;
+ return fh;
+#else
+ return fopen(path, mode);
+#endif
+}
+
+int ota_close(int fd) {
+#if defined (TARGET_INJECT_FAULTS)
+ // descriptors can be reused, so make sure not to leave them in the cahce
+ FilenameCache.erase(fd);
+#endif
+ return close(fd);
+}
+
+int ota_fclose(FILE* fh) {
+#if defined (TARGET_INJECT_FAULTS)
+ FilenameCache.erase((intptr_t)fh);
+#endif
+ return fclose(fh);
+}
+
+size_t ota_fread(void* ptr, size_t size, size_t nitems, FILE* stream) {
+#if defined (TARGET_READ_FAULT)
+ if (FilenameCache.find((intptr_t)stream) != FilenameCache.end()
+ && FilenameCache[(intptr_t)stream] == FaultFileName) {
+ FaultFileName = "";
+ errno = EIO;
+ return 0;
+ } else {
+ return fread(ptr, size, nitems, stream);
+ }
+#else
+ return fread(ptr, size, nitems, stream);
+#endif
+}
+
+ssize_t ota_read(int fd, void* buf, size_t nbyte) {
+#if defined (TARGET_READ_FAULT)
+ if (FilenameCache.find(fd) != FilenameCache.end()
+ && FilenameCache[fd] == FaultFileName) {
+ FaultFileName = "";
+ errno = EIO;
+ return -1;
+ } else {
+ return read(fd, buf, nbyte);
+ }
+#else
+ return read(fd, buf, nbyte);
+#endif
+}
+
+size_t ota_fwrite(const void* ptr, size_t size, size_t count, FILE* stream) {
+#if defined (TARGET_WRITE_FAULT)
+ if (FilenameCache.find((intptr_t)stream) != FilenameCache.end()
+ && FilenameCache[(intptr_t)stream] == FaultFileName) {
+ FaultFileName = "";
+ errno = EIO;
+ return 0;
+ } else {
+ return fwrite(ptr, size, count, stream);
+ }
+#else
+ return fwrite(ptr, size, count, stream);
+#endif
+}
+
+ssize_t ota_write(int fd, const void* buf, size_t nbyte) {
+#if defined (TARGET_WRITE_FAULT)
+ if (FilenameCache.find(fd) != FilenameCache.end()
+ && FilenameCache[fd] == FaultFileName) {
+ FaultFileName = "";
+ errno = EIO;
+ return -1;
+ } else {
+ return write(fd, buf, nbyte);
+ }
+#else
+ return write(fd, buf, nbyte);
+#endif
+}
+
+int ota_fsync(int fd) {
+#if defined (TARGET_FSYNC_FAULT)
+ if (FilenameCache.find(fd) != FilenameCache.end()
+ && FilenameCache[fd] == FaultFileName) {
+ FaultFileName = "";
+ errno = EIO;
+ return -1;
+ } else {
+ return fsync(fd);
+ }
+#else
+ return fsync(fd);
+#endif
+}
diff --git a/otafault/ota_io.h b/otafault/ota_io.h
new file mode 100644
index 000000000..641a5ae0a
--- /dev/null
+++ b/otafault/ota_io.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+/*
+ * Provide a series of proxy functions for basic file accessors.
+ * The behavior of these functions can be changed to return different
+ * errors under a variety of conditions.
+ */
+
+#ifndef _UPDATER_OTA_IO_H_
+#define _UPDATER_OTA_IO_H_
+
+#include <stdio.h>
+#include <sys/stat.h>
+
+int ota_open(const char* path, int oflags);
+
+int ota_open(const char* path, int oflags, mode_t mode);
+
+FILE* ota_fopen(const char* filename, const char* mode);
+
+int ota_close(int fd);
+
+int ota_fclose(FILE* fh);
+
+size_t ota_fread(void* ptr, size_t size, size_t nitems, FILE* stream);
+
+ssize_t ota_read(int fd, void* buf, size_t nbyte);
+
+size_t ota_fwrite(const void* ptr, size_t size, size_t count, FILE* stream);
+
+ssize_t ota_write(int fd, const void* buf, size_t nbyte);
+
+int ota_fsync(int fd);
+
+#endif
diff --git a/otafault/test.cpp b/otafault/test.cpp
new file mode 100644
index 000000000..a0f731517
--- /dev/null
+++ b/otafault/test.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 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 <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#include "ota_io.h"
+
+int main(int argc, char **argv) {
+ int fd = open("testdata/test.file", O_RDWR);
+ char buf[8];
+ char *out = "321";
+ int readv = ota_read(fd, buf, 4);
+ printf("Read returned %d\n", readv);
+ int writev = ota_write(fd, out, 4);
+ printf("Write returned %d\n", writev);
+ return 0;
+}
diff --git a/recovery.cpp b/recovery.cpp
index 17e9eb66f..ee2fb43fc 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -77,7 +77,10 @@ static const char *INTENT_FILE = "/cache/recovery/intent";
static const char *LOG_FILE = "/cache/recovery/log";
static const char *LAST_INSTALL_FILE = "/cache/recovery/last_install";
static const char *LOCALE_FILE = "/cache/recovery/last_locale";
+static const char *CONVERT_FBE_DIR = "/cache/recovery/convert_fbe";
+static const char *CONVERT_FBE_FILE = "/cache/recovery/convert_fbe/convert_fbe";
static const char *CACHE_ROOT = "/cache";
+static const char *DATA_ROOT = "/data";
static const char *SDCARD_ROOT = "/sdcard";
static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log";
static const char *TEMPORARY_INSTALL_FILE = "/tmp/last_install";
@@ -504,6 +507,7 @@ typedef struct _saved_log_file {
static bool erase_volume(const char* volume) {
bool is_cache = (strcmp(volume, CACHE_ROOT) == 0);
+ bool is_data = (strcmp(volume, DATA_ROOT) == 0);
ui->SetBackground(RecoveryUI::ERASING);
ui->SetProgressType(RecoveryUI::INDETERMINATE);
@@ -558,7 +562,25 @@ static bool erase_volume(const char* volume) {
ui->Print("Formatting %s...\n", volume);
ensure_path_unmounted(volume);
- int result = format_volume(volume);
+
+ int result;
+
+ if (is_data && reason && strcmp(reason, "convert_fbe") == 0) {
+ // Create convert_fbe breadcrumb file to signal to init
+ // to convert to file based encryption, not full disk encryption
+ mkdir(CONVERT_FBE_DIR, 0700);
+ FILE* f = fopen(CONVERT_FBE_FILE, "wb");
+ if (!f) {
+ ui->Print("Failed to convert to file encryption\n");
+ return true;
+ }
+ fclose(f);
+ result = format_volume(volume, CONVERT_FBE_DIR);
+ remove(CONVERT_FBE_FILE);
+ rmdir(CONVERT_FBE_DIR);
+ } else {
+ result = format_volume(volume);
+ }
if (is_cache) {
while (head) {
diff --git a/roots.cpp b/roots.cpp
index 12c6b5ee2..f361cb8ca 100644
--- a/roots.cpp
+++ b/roots.cpp
@@ -175,7 +175,7 @@ static int exec_cmd(const char* path, char* const argv[]) {
return WEXITSTATUS(status);
}
-int format_volume(const char* volume) {
+int format_volume(const char* volume, const char* directory) {
Volume* v = volume_for_path(volume);
if (v == NULL) {
LOGE("unknown volume \"%s\"\n", volume);
@@ -241,7 +241,7 @@ int format_volume(const char* volume) {
}
int result;
if (strcmp(v->fs_type, "ext4") == 0) {
- result = make_ext4fs(v->blk_device, length, volume, sehandle);
+ result = make_ext4fs_directory(v->blk_device, length, volume, sehandle, directory);
} else { /* Has to be f2fs because we checked earlier. */
if (v->key_loc != NULL && strcmp(v->key_loc, "footer") == 0 && length < 0) {
LOGE("format_volume: crypt footer + negative length (%zd) not supported on %s\n", length, v->fs_type);
@@ -273,6 +273,10 @@ int format_volume(const char* volume) {
return -1;
}
+int format_volume(const char* volume) {
+ return format_volume(volume, NULL);
+}
+
int setup_install_mounts() {
if (fstab == NULL) {
LOGE("can't set up install mounts: no fstab loaded\n");
diff --git a/roots.h b/roots.h
index 6e3b24355..a14b7d971 100644
--- a/roots.h
+++ b/roots.h
@@ -41,6 +41,12 @@ int ensure_path_unmounted(const char* path);
// it is mounted.
int format_volume(const char* volume);
+// Reformat the given volume (must be the mount point only, eg
+// "/cache"), no paths permitted. Attempts to unmount the volume if
+// it is mounted.
+// Copies 'directory' to root of the newly formatted volume
+int format_volume(const char* volume, const char* directory);
+
// Ensure that all and only the volumes that packages expect to find
// mounted (/tmp and /cache) are mounted. Returns 0 on success.
int setup_install_mounts();
diff --git a/updater/Android.mk b/updater/Android.mk
index dcf437474..d74dffc0c 100644
--- a/updater/Android.mk
+++ b/updater/Android.mk
@@ -45,7 +45,7 @@ LOCAL_STATIC_LIBRARIES += \
endif
LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UPDATER_LIBS) $(TARGET_RECOVERY_UPDATER_EXTRA_LIBS)
-LOCAL_STATIC_LIBRARIES += libapplypatch libbase libedify libmtdutils libminzip libz
+LOCAL_STATIC_LIBRARIES += libapplypatch libbase libotafault libedify libmtdutils libminzip libz
LOCAL_STATIC_LIBRARIES += libmincrypt libbz
LOCAL_STATIC_LIBRARIES += libcutils liblog libc
LOCAL_STATIC_LIBRARIES += libselinux
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index c6daf7db5..c898ac6f6 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -45,6 +45,7 @@
#include "install.h"
#include "mincrypt/sha.h"
#include "minzip/Hash.h"
+#include "otafault/ota_io.h"
#include "print_sha1.h"
#include "unique_fd.h"
#include "updater.h"
@@ -139,7 +140,7 @@ static bool range_overlaps(const RangeSet& r1, const RangeSet& r2) {
static int read_all(int fd, uint8_t* data, size_t size) {
size_t so_far = 0;
while (so_far < size) {
- ssize_t r = TEMP_FAILURE_RETRY(read(fd, data+so_far, size-so_far));
+ ssize_t r = TEMP_FAILURE_RETRY(ota_read(fd, data+so_far, size-so_far));
if (r == -1) {
fprintf(stderr, "read failed: %s\n", strerror(errno));
return -1;
@@ -156,7 +157,7 @@ static int read_all(int fd, std::vector<uint8_t>& buffer, size_t size) {
static int write_all(int fd, const uint8_t* data, size_t size) {
size_t written = 0;
while (written < size) {
- ssize_t w = TEMP_FAILURE_RETRY(write(fd, data+written, size-written));
+ ssize_t w = TEMP_FAILURE_RETRY(ota_write(fd, data+written, size-written));
if (w == -1) {
fprintf(stderr, "write failed: %s\n", strerror(errno));
return -1;
@@ -622,7 +623,7 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks
return -1;
}
- if (fsync(fd) == -1) {
+ if (ota_fsync(fd) == -1) {
fprintf(stderr, "fsync \"%s\" failed: %s\n", fn.c_str(), strerror(errno));
return -1;
}
@@ -642,7 +643,7 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks
return -1;
}
- if (fsync(dfd) == -1) {
+ if (ota_fsync(dfd) == -1) {
fprintf(stderr, "fsync \"%s\" failed: %s\n", dname.c_str(), strerror(errno));
return -1;
}
@@ -1467,7 +1468,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
}
if (params.canwrite) {
- if (fsync(params.fd) == -1) {
+ if (ota_fsync(params.fd) == -1) {
fprintf(stderr, "fsync failed: %s\n", strerror(errno));
goto pbiudone;
}
@@ -1492,7 +1493,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
rc = 0;
pbiudone:
- if (fsync(params.fd) == -1) {
+ if (ota_fsync(params.fd) == -1) {
fprintf(stderr, "fsync failed: %s\n", strerror(errno));
}
// params.fd will be automatically closed because of the fd_holder above.
diff --git a/updater/install.cpp b/updater/install.cpp
index b09086964..be9735595 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -48,6 +48,7 @@
#include "minzip/DirUtil.h"
#include "mtdutils/mounts.h"
#include "mtdutils/mtdutils.h"
+#include "otafault/ota_io.h"
#include "updater.h"
#include "install.h"
#include "tune2fs.h"
@@ -555,18 +556,18 @@ Value* PackageExtractFileFn(const char* name, State* state,
}
{
- int fd = TEMP_FAILURE_RETRY(open(dest_path, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC,
+ int fd = TEMP_FAILURE_RETRY(ota_open(dest_path, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC,
S_IRUSR | S_IWUSR));
if (fd == -1) {
printf("%s: can't open %s for write: %s\n", name, dest_path, strerror(errno));
goto done2;
}
success = mzExtractZipEntryToFile(za, entry, fd);
- if (fsync(fd) == -1) {
+ if (ota_fsync(fd) == -1) {
printf("fsync of \"%s\" failed: %s\n", dest_path, strerror(errno));
success = false;
}
- if (close(fd) == -1) {
+ if (ota_close(fd) == -1) {
printf("close of \"%s\" failed: %s\n", dest_path, strerror(errno));
success = false;
}
@@ -999,7 +1000,7 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
goto done;
}
- if (fread(buffer, 1, st.st_size, f) != static_cast<size_t>(st.st_size)) {
+ if (ota_fread(buffer, 1, st.st_size, f) != static_cast<size_t>(st.st_size)) {
ErrorAbort(state, "%s: failed to read %lld bytes from %s",
name, (long long)st.st_size+1, filename);
fclose(f);
@@ -1102,7 +1103,7 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
if (contents->type == VAL_STRING) {
// we're given a filename as the contents
char* filename = contents->data;
- FILE* f = fopen(filename, "rb");
+ FILE* f = ota_fopen(filename, "rb");
if (f == NULL) {
printf("%s: can't open %s: %s\n", name, filename, strerror(errno));
result = strdup("");
@@ -1112,12 +1113,12 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
success = true;
char* buffer = reinterpret_cast<char*>(malloc(BUFSIZ));
int read;
- while (success && (read = fread(buffer, 1, BUFSIZ, f)) > 0) {
+ while (success && (read = ota_fread(buffer, 1, BUFSIZ, f)) > 0) {
int wrote = mtd_write_data(ctx, buffer, read);
success = success && (wrote == read);
}
free(buffer);
- fclose(f);
+ ota_fclose(f);
} else {
// we're given a blob as the contents
ssize_t wrote = mtd_write_data(ctx, contents->data, contents->size);
@@ -1445,7 +1446,7 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) {
memset(buffer, 0, sizeof(((struct bootloader_message*)0)->command));
FILE* f = fopen(filename, "r+b");
fseek(f, offsetof(struct bootloader_message, command), SEEK_SET);
- fwrite(buffer, sizeof(((struct bootloader_message*)0)->command), 1, f);
+ ota_fwrite(buffer, sizeof(((struct bootloader_message*)0)->command), 1, f);
fclose(f);
free(filename);
@@ -1493,7 +1494,7 @@ Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
to_write = max_size;
stagestr[max_size-1] = 0;
}
- fwrite(stagestr, to_write, 1, f);
+ ota_fwrite(stagestr, to_write, 1, f);
fclose(f);
free(stagestr);
@@ -1513,7 +1514,7 @@ Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
char buffer[sizeof(((struct bootloader_message*)0)->stage)];
FILE* f = fopen(filename, "rb");
fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET);
- fread(buffer, sizeof(buffer), 1, f);
+ ota_fread(buffer, sizeof(buffer), 1, f);
fclose(f);
buffer[sizeof(buffer)-1] = '\0';
@@ -1531,13 +1532,13 @@ Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[])
size_t len;
android::base::ParseUint(len_str, &len);
- int fd = open(filename, O_WRONLY, 0644);
+ int fd = ota_open(filename, O_WRONLY, 0644);
int success = wipe_block_device(fd, len);
free(filename);
free(len_str);
- close(fd);
+ ota_close(fd);
return StringValue(strdup(success ? "t" : ""));
}