Merge "Remove otafault"
This commit is contained in:
commit
a1e3d67bd7
16 changed files with 112 additions and 750 deletions
|
@ -53,7 +53,6 @@ cc_library_static {
|
|||
"libbz",
|
||||
"libcrypto",
|
||||
"libedify",
|
||||
"libotafault",
|
||||
"libotautil",
|
||||
"libz",
|
||||
],
|
||||
|
@ -100,7 +99,6 @@ cc_binary {
|
|||
"libapplypatch_modes",
|
||||
"libapplypatch",
|
||||
"libedify",
|
||||
"libotafault",
|
||||
"libotautil",
|
||||
"libbspatch",
|
||||
],
|
||||
|
|
|
@ -26,24 +26,25 @@
|
|||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/parseint.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "edify/expr.h"
|
||||
#include "otafault/ota_io.h"
|
||||
#include "otautil/paths.h"
|
||||
#include "otautil/print_sha1.h"
|
||||
|
||||
static int LoadPartitionContents(const std::string& filename, FileContents* file);
|
||||
static size_t FileSink(const unsigned char* data, size_t len, int fd);
|
||||
static int GenerateTarget(const FileContents& source_file, const std::unique_ptr<Value>& patch,
|
||||
const std::string& target_filename,
|
||||
const uint8_t target_sha1[SHA_DIGEST_LENGTH], const Value* bonus_data);
|
||||
|
@ -54,26 +55,13 @@ int LoadFileContents(const std::string& filename, FileContents* file) {
|
|||
return LoadPartitionContents(filename, file);
|
||||
}
|
||||
|
||||
struct stat sb;
|
||||
if (stat(filename.c_str(), &sb) == -1) {
|
||||
PLOG(ERROR) << "Failed to stat \"" << filename << "\"";
|
||||
std::string data;
|
||||
if (!android::base::ReadFileToString(filename, &data)) {
|
||||
PLOG(ERROR) << "Failed to read \"" << filename << "\"";
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> data(sb.st_size);
|
||||
unique_file f(ota_fopen(filename.c_str(), "rb"));
|
||||
if (!f) {
|
||||
PLOG(ERROR) << "Failed to open \"" << filename << "\"";
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t bytes_read = ota_fread(data.data(), 1, data.size(), f.get());
|
||||
if (bytes_read != data.size()) {
|
||||
LOG(ERROR) << "Short read of \"" << filename << "\" (" << bytes_read << " bytes of "
|
||||
<< data.size() << ")";
|
||||
return -1;
|
||||
}
|
||||
file->data = std::move(data);
|
||||
file->data = std::vector<unsigned char>(data.begin(), data.end());
|
||||
SHA1(file->data.data(), file->data.size(), file->sha1);
|
||||
return 0;
|
||||
}
|
||||
|
@ -110,8 +98,8 @@ static int LoadPartitionContents(const std::string& filename, FileContents* file
|
|||
std::sort(pairs.begin(), pairs.end());
|
||||
|
||||
const char* partition = pieces[1].c_str();
|
||||
unique_file dev(ota_fopen(partition, "rb"));
|
||||
if (!dev) {
|
||||
android::base::unique_fd dev(open(partition, O_RDONLY));
|
||||
if (dev == -1) {
|
||||
PLOG(ERROR) << "Failed to open eMMC partition \"" << partition << "\"";
|
||||
return -1;
|
||||
}
|
||||
|
@ -121,8 +109,7 @@ static int LoadPartitionContents(const std::string& filename, FileContents* file
|
|||
|
||||
// Allocate enough memory to hold the largest size.
|
||||
std::vector<unsigned char> buffer(pairs[pair_count - 1].first);
|
||||
unsigned char* buffer_ptr = buffer.data();
|
||||
size_t buffer_size = 0; // # bytes read so far
|
||||
size_t offset = 0; // # bytes read so far
|
||||
bool found = false;
|
||||
|
||||
for (const auto& pair : pairs) {
|
||||
|
@ -131,19 +118,16 @@ static int LoadPartitionContents(const std::string& filename, FileContents* file
|
|||
|
||||
// Read enough additional bytes to get us up to the next size. (Again,
|
||||
// we're trying the possibilities in order of increasing size).
|
||||
size_t next = current_size - buffer_size;
|
||||
if (next > 0) {
|
||||
size_t read = ota_fread(buffer_ptr, 1, next, dev.get());
|
||||
if (next != read) {
|
||||
LOG(ERROR) << "Short read (" << read << " bytes of " << next << ") for partition \""
|
||||
<< partition << "\"";
|
||||
if (current_size - offset > 0) {
|
||||
if (!android::base::ReadFully(dev, buffer.data() + offset, current_size - offset)) {
|
||||
PLOG(ERROR) << "Failed to read " << current_size - offset << " bytes of data at offset "
|
||||
<< offset << " for partition " << partition;
|
||||
return -1;
|
||||
}
|
||||
SHA1_Update(&sha_ctx, buffer_ptr, read);
|
||||
buffer_size += read;
|
||||
buffer_ptr += read;
|
||||
}
|
||||
|
||||
SHA1_Update(&sha_ctx, buffer.data() + offset, current_size - offset);
|
||||
offset = current_size;
|
||||
}
|
||||
// Duplicate the SHA context and finalize the duplicate so we can
|
||||
// check it against this pair's expected hash.
|
||||
SHA_CTX temp_ctx;
|
||||
|
@ -173,31 +157,31 @@ static int LoadPartitionContents(const std::string& filename, FileContents* file
|
|||
|
||||
SHA1_Final(file->sha1, &sha_ctx);
|
||||
|
||||
buffer.resize(buffer_size);
|
||||
buffer.resize(offset);
|
||||
file->data = std::move(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SaveFileContents(const std::string& filename, const FileContents* file) {
|
||||
unique_fd fd(
|
||||
ota_open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR));
|
||||
android::base::unique_fd fd(
|
||||
open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR));
|
||||
if (fd == -1) {
|
||||
PLOG(ERROR) << "Failed to open \"" << filename << "\" for write";
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t bytes_written = FileSink(file->data.data(), file->data.size(), fd);
|
||||
if (bytes_written != file->data.size()) {
|
||||
PLOG(ERROR) << "Short write of \"" << filename << "\" (" << bytes_written << " bytes of "
|
||||
<< file->data.size();
|
||||
if (!android::base::WriteFully(fd, file->data.data(), file->data.size())) {
|
||||
PLOG(ERROR) << "Failed to write " << file->data.size() << " bytes of data to " << filename;
|
||||
return -1;
|
||||
}
|
||||
if (ota_fsync(fd) != 0) {
|
||||
|
||||
if (fsync(fd) != 0) {
|
||||
PLOG(ERROR) << "Failed to fsync \"" << filename << "\"";
|
||||
return -1;
|
||||
}
|
||||
if (ota_close(fd) != 0) {
|
||||
|
||||
if (close(fd.release()) != 0) {
|
||||
PLOG(ERROR) << "Failed to close \"" << filename << "\"";
|
||||
return -1;
|
||||
}
|
||||
|
@ -215,42 +199,36 @@ static int WriteToPartition(const unsigned char* data, size_t len, const std::st
|
|||
return -1;
|
||||
}
|
||||
|
||||
const char* partition = pieces[1].c_str();
|
||||
unique_fd fd(ota_open(partition, O_RDWR));
|
||||
if (fd == -1) {
|
||||
PLOG(ERROR) << "Failed to open \"" << partition << "\"";
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t start = 0;
|
||||
bool success = false;
|
||||
for (size_t attempt = 0; attempt < 2; ++attempt) {
|
||||
std::string partition = pieces[1];
|
||||
android::base::unique_fd fd(open(partition.c_str(), O_RDWR));
|
||||
if (fd == -1) {
|
||||
PLOG(ERROR) << "Failed to open \"" << partition << "\"";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (TEMP_FAILURE_RETRY(lseek(fd, start, SEEK_SET)) == -1) {
|
||||
PLOG(ERROR) << "Failed to seek to " << start << " on \"" << partition << "\"";
|
||||
return -1;
|
||||
}
|
||||
while (start < len) {
|
||||
size_t to_write = len - start;
|
||||
if (to_write > 1 << 20) to_write = 1 << 20;
|
||||
|
||||
ssize_t written = TEMP_FAILURE_RETRY(ota_write(fd, data + start, to_write));
|
||||
if (written == -1) {
|
||||
PLOG(ERROR) << "Failed to write to \"" << partition << "\"";
|
||||
return -1;
|
||||
}
|
||||
start += written;
|
||||
if (!android::base::WriteFully(fd, data + start, len - start)) {
|
||||
PLOG(ERROR) << "Failed to write " << len - start << " bytes to \"" << partition << "\"";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ota_fsync(fd) != 0) {
|
||||
if (fsync(fd) != 0) {
|
||||
PLOG(ERROR) << "Failed to sync \"" << partition << "\"";
|
||||
return -1;
|
||||
}
|
||||
if (ota_close(fd) != 0) {
|
||||
if (close(fd.release()) != 0) {
|
||||
PLOG(ERROR) << "Failed to close \"" << partition << "\"";
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd.reset(ota_open(partition, O_RDONLY));
|
||||
fd.reset(open(partition.c_str(), O_RDONLY));
|
||||
if (fd == -1) {
|
||||
PLOG(ERROR) << "Failed to reopen \"" << partition << "\" for verification";
|
||||
return -1;
|
||||
|
@ -258,13 +236,12 @@ static int WriteToPartition(const unsigned char* data, size_t len, const std::st
|
|||
|
||||
// Drop caches so our subsequent verification read won't just be reading the cache.
|
||||
sync();
|
||||
unique_fd dc(ota_open("/proc/sys/vm/drop_caches", O_WRONLY));
|
||||
if (TEMP_FAILURE_RETRY(ota_write(dc, "3\n", 2)) == -1) {
|
||||
PLOG(ERROR) << "Failed to write to /proc/sys/vm/drop_caches";
|
||||
std::string drop_cache = "/proc/sys/vm/drop_caches";
|
||||
if (!android::base::WriteStringToFile("3\n", drop_cache)) {
|
||||
PLOG(ERROR) << "Failed to write to " << drop_cache;
|
||||
} else {
|
||||
LOG(INFO) << " caches dropped";
|
||||
}
|
||||
ota_close(dc);
|
||||
sleep(1);
|
||||
|
||||
// Verify.
|
||||
|
@ -281,21 +258,9 @@ static int WriteToPartition(const unsigned char* data, size_t len, const std::st
|
|||
to_read = sizeof(buffer);
|
||||
}
|
||||
|
||||
size_t so_far = 0;
|
||||
while (so_far < to_read) {
|
||||
ssize_t read_count = TEMP_FAILURE_RETRY(ota_read(fd, buffer + so_far, to_read - so_far));
|
||||
if (read_count == -1) {
|
||||
PLOG(ERROR) << "Failed to verify-read " << partition << " at " << p;
|
||||
return -1;
|
||||
} else if (read_count == 0) {
|
||||
LOG(ERROR) << "Verify-reading " << partition << " reached unexpected EOF at " << p;
|
||||
return -1;
|
||||
}
|
||||
if (static_cast<size_t>(read_count) < to_read) {
|
||||
LOG(INFO) << "Short verify-read " << partition << " at " << p << ": expected " << to_read
|
||||
<< " actual " << read_count;
|
||||
}
|
||||
so_far += read_count;
|
||||
if (!android::base::ReadFully(fd, buffer, to_read)) {
|
||||
PLOG(ERROR) << "Failed to verify-read " << partition << " at " << p;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(buffer, data + p, to_read) != 0) {
|
||||
|
@ -311,16 +276,10 @@ static int WriteToPartition(const unsigned char* data, size_t len, const std::st
|
|||
break;
|
||||
}
|
||||
|
||||
if (ota_close(fd) != 0) {
|
||||
if (close(fd.release()) != 0) {
|
||||
PLOG(ERROR) << "Failed to close " << partition;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd.reset(ota_open(partition, O_RDWR));
|
||||
if (fd == -1) {
|
||||
PLOG(ERROR) << "Failed to reopen " << partition << " for next attempt";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
|
@ -328,10 +287,6 @@ static int WriteToPartition(const unsigned char* data, size_t len, const std::st
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (ota_close(fd) == -1) {
|
||||
PLOG(ERROR) << "Failed to close " << partition;
|
||||
return -1;
|
||||
}
|
||||
sync();
|
||||
|
||||
return 0;
|
||||
|
@ -407,19 +362,6 @@ int ShowLicenses() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static size_t FileSink(const unsigned char* data, size_t len, int fd) {
|
||||
size_t done = 0;
|
||||
while (done < len) {
|
||||
ssize_t wrote = TEMP_FAILURE_RETRY(ota_write(fd, data + done, len - done));
|
||||
if (wrote == -1) {
|
||||
PLOG(ERROR) << "Failed to write " << len - done << " bytes";
|
||||
return done;
|
||||
}
|
||||
done += wrote;
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
int applypatch(const char* source_filename, const char* target_filename,
|
||||
const char* target_sha1_str, size_t /* target_size */,
|
||||
const std::vector<std::string>& patch_sha1s,
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
// Copyright (C) 2017 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.
|
||||
|
||||
cc_library_static {
|
||||
name: "libotafault",
|
||||
|
||||
host_supported: true,
|
||||
|
||||
srcs: [
|
||||
"config.cpp",
|
||||
"ota_io.cpp",
|
||||
],
|
||||
|
||||
static_libs: [
|
||||
"libbase",
|
||||
"liblog",
|
||||
"libziparchive",
|
||||
],
|
||||
|
||||
export_include_dirs: [
|
||||
"include",
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS",
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
"-Wthread-safety",
|
||||
"-Wthread-safety-negative",
|
||||
],
|
||||
|
||||
target: {
|
||||
darwin: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "otafault_test",
|
||||
|
||||
srcs: ["test.cpp"],
|
||||
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
],
|
||||
|
||||
static_executable: true,
|
||||
|
||||
static_libs: [
|
||||
"libotafault",
|
||||
"libziparchive",
|
||||
"libbase",
|
||||
"liblog",
|
||||
],
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* 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 "otafault/config.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <ziparchive/zip_archive.h>
|
||||
|
||||
#include "otafault/ota_io.h"
|
||||
|
||||
#define OTAIO_MAX_FNAME_SIZE 128
|
||||
|
||||
static ZipArchiveHandle archive;
|
||||
static bool is_retry = false;
|
||||
static std::map<std::string, bool> should_inject_cache;
|
||||
|
||||
static std::string get_type_path(const char* io_type) {
|
||||
return android::base::StringPrintf("%s/%s", OTAIO_BASE_DIR, io_type);
|
||||
}
|
||||
|
||||
void ota_io_init(ZipArchiveHandle za, bool retry) {
|
||||
archive = za;
|
||||
is_retry = retry;
|
||||
ota_set_fault_files();
|
||||
}
|
||||
|
||||
bool should_fault_inject(const char* io_type) {
|
||||
// archive will be NULL if we used an entry point other
|
||||
// than updater/updater.cpp:main
|
||||
if (archive == nullptr || is_retry) {
|
||||
return false;
|
||||
}
|
||||
const std::string type_path = get_type_path(io_type);
|
||||
if (should_inject_cache.find(type_path) != should_inject_cache.end()) {
|
||||
return should_inject_cache[type_path];
|
||||
}
|
||||
ZipString zip_type_path(type_path.c_str());
|
||||
ZipEntry entry;
|
||||
int status = FindEntry(archive, zip_type_path, &entry);
|
||||
should_inject_cache[type_path] = (status == 0);
|
||||
return (status == 0);
|
||||
}
|
||||
|
||||
bool should_hit_cache() {
|
||||
return should_fault_inject(OTAIO_CACHE);
|
||||
}
|
||||
|
||||
std::string fault_fname(const char* io_type) {
|
||||
std::string type_path = get_type_path(io_type);
|
||||
std::string fname;
|
||||
fname.resize(OTAIO_MAX_FNAME_SIZE);
|
||||
ZipString zip_type_path(type_path.c_str());
|
||||
ZipEntry entry;
|
||||
if (FindEntry(archive, zip_type_path, &entry) != 0) {
|
||||
return {};
|
||||
}
|
||||
ExtractToMemory(archive, &entry, reinterpret_cast<uint8_t*>(&fname[0]), OTAIO_MAX_FNAME_SIZE);
|
||||
return fname;
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Read configuration files in the OTA package to determine which files, if any, will trigger
|
||||
* errors.
|
||||
*
|
||||
* OTA packages can be modified to trigger errors by adding a top-level directory called
|
||||
* .libotafault, which may optionally contain up to three files called READ, WRITE, and FSYNC.
|
||||
* Each one of these optional files contains the name of a single file on the device disk which
|
||||
* will cause an IO error on the first call of the appropriate I/O action to that file.
|
||||
*
|
||||
* Example:
|
||||
* ota.zip
|
||||
* <normal package contents>
|
||||
* .libotafault
|
||||
* WRITE
|
||||
*
|
||||
* If the contents of the file WRITE were /system/build.prop, the first write action to
|
||||
* /system/build.prop would fail with EIO. Note that READ and FSYNC files are absent, so these
|
||||
* actions will not cause an error.
|
||||
*/
|
||||
|
||||
#ifndef _UPDATER_OTA_IO_CFG_H_
|
||||
#define _UPDATER_OTA_IO_CFG_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <ziparchive/zip_archive.h>
|
||||
|
||||
#define OTAIO_BASE_DIR ".libotafault"
|
||||
#define OTAIO_READ "READ"
|
||||
#define OTAIO_WRITE "WRITE"
|
||||
#define OTAIO_FSYNC "FSYNC"
|
||||
#define OTAIO_CACHE "CACHE"
|
||||
|
||||
/*
|
||||
* Initialize libotafault by providing a reference to the OTA package.
|
||||
*/
|
||||
void ota_io_init(ZipArchiveHandle zip, bool retry);
|
||||
|
||||
/*
|
||||
* Return true if a config file is present for the given IO type.
|
||||
*/
|
||||
bool should_fault_inject(const char* io_type);
|
||||
|
||||
/*
|
||||
* Return true if an EIO should occur on the next hit to /cache/saved.file
|
||||
* instead of the next hit to the specified file.
|
||||
*/
|
||||
bool should_hit_cache();
|
||||
|
||||
/*
|
||||
* Return the name of the file that should cause an error for the
|
||||
* given IO type.
|
||||
*/
|
||||
std::string fault_fname(const char* io_type);
|
||||
|
||||
#endif
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* 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 <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h> // mode_t
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <android-base/unique_fd.h>
|
||||
|
||||
#define OTAIO_CACHE_FNAME "/cache/saved.file"
|
||||
|
||||
void ota_set_fault_files();
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
struct OtaCloser {
|
||||
static void Close(int);
|
||||
};
|
||||
|
||||
using unique_fd = android::base::unique_fd_impl<OtaCloser>;
|
||||
|
||||
int ota_close(unique_fd& fd);
|
||||
|
||||
struct OtaFcloser {
|
||||
void operator()(FILE*) const;
|
||||
};
|
||||
|
||||
using unique_file = std::unique_ptr<FILE, OtaFcloser>;
|
||||
|
||||
int ota_fclose(unique_file& fh);
|
||||
|
||||
#endif
|
|
@ -1,212 +0,0 @@
|
|||
/*
|
||||
* 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 "otafault/ota_io.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
#include <android-base/thread_annotations.h>
|
||||
|
||||
#include "otafault/config.h"
|
||||
|
||||
static std::mutex filename_mutex;
|
||||
static std::map<intptr_t, const char*> filename_cache GUARDED_BY(filename_mutex);
|
||||
static std::string read_fault_file_name = "";
|
||||
static std::string write_fault_file_name = "";
|
||||
static std::string fsync_fault_file_name = "";
|
||||
|
||||
static bool get_hit_file(const char* cached_path, const std::string& ffn) {
|
||||
return should_hit_cache()
|
||||
? !strncmp(cached_path, OTAIO_CACHE_FNAME, strlen(cached_path))
|
||||
: !strncmp(cached_path, ffn.c_str(), strlen(cached_path));
|
||||
}
|
||||
|
||||
void ota_set_fault_files() {
|
||||
if (should_fault_inject(OTAIO_READ)) {
|
||||
read_fault_file_name = fault_fname(OTAIO_READ);
|
||||
}
|
||||
if (should_fault_inject(OTAIO_WRITE)) {
|
||||
write_fault_file_name = fault_fname(OTAIO_WRITE);
|
||||
}
|
||||
if (should_fault_inject(OTAIO_FSYNC)) {
|
||||
fsync_fault_file_name = fault_fname(OTAIO_FSYNC);
|
||||
}
|
||||
}
|
||||
|
||||
bool have_eio_error = false;
|
||||
|
||||
int ota_open(const char* path, int oflags) {
|
||||
// Let the caller handle errors; we do not care if open succeeds or fails
|
||||
int fd = open(path, oflags);
|
||||
std::lock_guard<std::mutex> lock(filename_mutex);
|
||||
filename_cache[fd] = path;
|
||||
return fd;
|
||||
}
|
||||
|
||||
int ota_open(const char* path, int oflags, mode_t mode) {
|
||||
int fd = open(path, oflags, mode);
|
||||
std::lock_guard<std::mutex> lock(filename_mutex);
|
||||
filename_cache[fd] = path;
|
||||
return fd;
|
||||
}
|
||||
|
||||
FILE* ota_fopen(const char* path, const char* mode) {
|
||||
FILE* fh = fopen(path, mode);
|
||||
std::lock_guard<std::mutex> lock(filename_mutex);
|
||||
filename_cache[(intptr_t)fh] = path;
|
||||
return fh;
|
||||
}
|
||||
|
||||
static int __ota_close(int fd) {
|
||||
// descriptors can be reused, so make sure not to leave them in the cache
|
||||
std::lock_guard<std::mutex> lock(filename_mutex);
|
||||
filename_cache.erase(fd);
|
||||
return close(fd);
|
||||
}
|
||||
|
||||
void OtaCloser::Close(int fd) {
|
||||
__ota_close(fd);
|
||||
}
|
||||
|
||||
int ota_close(unique_fd& fd) {
|
||||
return __ota_close(fd.release());
|
||||
}
|
||||
|
||||
static int __ota_fclose(FILE* fh) {
|
||||
std::lock_guard<std::mutex> lock(filename_mutex);
|
||||
filename_cache.erase(reinterpret_cast<intptr_t>(fh));
|
||||
return fclose(fh);
|
||||
}
|
||||
|
||||
void OtaFcloser::operator()(FILE* f) const {
|
||||
__ota_fclose(f);
|
||||
};
|
||||
|
||||
int ota_fclose(unique_file& fh) {
|
||||
return __ota_fclose(fh.release());
|
||||
}
|
||||
|
||||
size_t ota_fread(void* ptr, size_t size, size_t nitems, FILE* stream) {
|
||||
if (should_fault_inject(OTAIO_READ)) {
|
||||
std::lock_guard<std::mutex> lock(filename_mutex);
|
||||
auto cached = filename_cache.find((intptr_t)stream);
|
||||
const char* cached_path = cached->second;
|
||||
if (cached != filename_cache.end() &&
|
||||
get_hit_file(cached_path, read_fault_file_name)) {
|
||||
read_fault_file_name = "";
|
||||
errno = EIO;
|
||||
have_eio_error = true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
size_t status = fread(ptr, size, nitems, stream);
|
||||
// If I/O error occurs, set the retry-update flag.
|
||||
if (status != nitems && errno == EIO) {
|
||||
have_eio_error = true;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
ssize_t ota_read(int fd, void* buf, size_t nbyte) {
|
||||
if (should_fault_inject(OTAIO_READ)) {
|
||||
std::lock_guard<std::mutex> lock(filename_mutex);
|
||||
auto cached = filename_cache.find(fd);
|
||||
const char* cached_path = cached->second;
|
||||
if (cached != filename_cache.end()
|
||||
&& get_hit_file(cached_path, read_fault_file_name)) {
|
||||
read_fault_file_name = "";
|
||||
errno = EIO;
|
||||
have_eio_error = true;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ssize_t status = read(fd, buf, nbyte);
|
||||
if (status == -1 && errno == EIO) {
|
||||
have_eio_error = true;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
size_t ota_fwrite(const void* ptr, size_t size, size_t count, FILE* stream) {
|
||||
if (should_fault_inject(OTAIO_WRITE)) {
|
||||
std::lock_guard<std::mutex> lock(filename_mutex);
|
||||
auto cached = filename_cache.find((intptr_t)stream);
|
||||
const char* cached_path = cached->second;
|
||||
if (cached != filename_cache.end() &&
|
||||
get_hit_file(cached_path, write_fault_file_name)) {
|
||||
write_fault_file_name = "";
|
||||
errno = EIO;
|
||||
have_eio_error = true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
size_t status = fwrite(ptr, size, count, stream);
|
||||
if (status != count && errno == EIO) {
|
||||
have_eio_error = true;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
ssize_t ota_write(int fd, const void* buf, size_t nbyte) {
|
||||
if (should_fault_inject(OTAIO_WRITE)) {
|
||||
std::lock_guard<std::mutex> lock(filename_mutex);
|
||||
auto cached = filename_cache.find(fd);
|
||||
const char* cached_path = cached->second;
|
||||
if (cached != filename_cache.end() &&
|
||||
get_hit_file(cached_path, write_fault_file_name)) {
|
||||
write_fault_file_name = "";
|
||||
errno = EIO;
|
||||
have_eio_error = true;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ssize_t status = write(fd, buf, nbyte);
|
||||
if (status == -1 && errno == EIO) {
|
||||
have_eio_error = true;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int ota_fsync(int fd) {
|
||||
if (should_fault_inject(OTAIO_FSYNC)) {
|
||||
std::lock_guard<std::mutex> lock(filename_mutex);
|
||||
auto cached = filename_cache.find(fd);
|
||||
const char* cached_path = cached->second;
|
||||
if (cached != filename_cache.end() &&
|
||||
get_hit_file(cached_path, fsync_fault_file_name)) {
|
||||
fsync_fault_file_name = "";
|
||||
errno = EIO;
|
||||
have_eio_error = true;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int status = fsync(fd);
|
||||
if (status == -1 && errno == EIO) {
|
||||
have_eio_error = true;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* 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 <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "otafault/ota_io.h"
|
||||
|
||||
int main(int /* argc */, char** /* argv */) {
|
||||
int fd = open("testdata/test.file", O_RDWR);
|
||||
char buf[8];
|
||||
const 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);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
|
@ -49,6 +49,7 @@ enum CauseCode : int {
|
|||
kPackageExtractFileFailure,
|
||||
kPatchApplicationFailure,
|
||||
kHashTreeComputationFailure,
|
||||
kEioFailure,
|
||||
kVendorFailure = 200
|
||||
};
|
||||
|
||||
|
|
|
@ -56,7 +56,6 @@ libapplypatch_static_libs = [
|
|||
"libedify",
|
||||
"libimgdiff",
|
||||
"libimgpatch",
|
||||
"libotafault",
|
||||
"libotautil",
|
||||
"libbsdiff",
|
||||
"libbspatch",
|
||||
|
|
|
@ -272,7 +272,7 @@ TEST_F(UpdaterTest, file_getprop) {
|
|||
expect(nullptr, "file_getprop(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
|
||||
|
||||
// File doesn't exist.
|
||||
expect(nullptr, "file_getprop(\"/doesntexist\", \"key1\")", kFileGetPropFailure);
|
||||
expect(nullptr, "file_getprop(\"/doesntexist\", \"key1\")", kFreadFailure);
|
||||
|
||||
// Reject too large files (current limit = 65536).
|
||||
TemporaryFile temp_file1;
|
||||
|
|
|
@ -24,7 +24,6 @@ cc_defaults {
|
|||
"libbootloader_message",
|
||||
"libbspatch",
|
||||
"libedify",
|
||||
"libotafault",
|
||||
"libotautil",
|
||||
"libext4_utils",
|
||||
"libfec",
|
||||
|
|
|
@ -27,7 +27,6 @@ updater_common_static_libraries := \
|
|||
libbootloader_message \
|
||||
libbspatch \
|
||||
libedify \
|
||||
libotafault \
|
||||
libotautil \
|
||||
libext4_utils \
|
||||
libfec \
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
#include <ziparchive/zip_archive.h>
|
||||
|
||||
#include "edify/expr.h"
|
||||
#include "otafault/ota_io.h"
|
||||
#include "otautil/error_code.h"
|
||||
#include "otautil/paths.h"
|
||||
#include "otautil/print_sha1.h"
|
||||
|
@ -119,15 +118,14 @@ static bool ParseLastCommandFile(size_t* last_command_index) {
|
|||
}
|
||||
|
||||
static bool FsyncDir(const std::string& dirname) {
|
||||
android::base::unique_fd dfd(
|
||||
TEMP_FAILURE_RETRY(ota_open(dirname.c_str(), O_RDONLY | O_DIRECTORY)));
|
||||
android::base::unique_fd dfd(TEMP_FAILURE_RETRY(open(dirname.c_str(), O_RDONLY | O_DIRECTORY)));
|
||||
if (dfd == -1) {
|
||||
failure_type = kFileOpenFailure;
|
||||
failure_type = errno == EIO ? kEioFailure : kFileOpenFailure;
|
||||
PLOG(ERROR) << "Failed to open " << dirname;
|
||||
return false;
|
||||
}
|
||||
if (fsync(dfd) == -1) {
|
||||
failure_type = kFsyncFailure;
|
||||
failure_type = errno == EIO ? kEioFailure : kFsyncFailure;
|
||||
PLOG(ERROR) << "Failed to fsync " << dirname;
|
||||
return false;
|
||||
}
|
||||
|
@ -180,47 +178,6 @@ static bool SetPartitionUpdatedMarker(const std::string& marker) {
|
|||
return true;
|
||||
}
|
||||
|
||||
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(ota_read(fd, data+so_far, size-so_far));
|
||||
if (r == -1) {
|
||||
failure_type = kFreadFailure;
|
||||
PLOG(ERROR) << "read failed";
|
||||
return -1;
|
||||
} else if (r == 0) {
|
||||
failure_type = kFreadFailure;
|
||||
LOG(ERROR) << "read reached unexpected EOF.";
|
||||
return -1;
|
||||
}
|
||||
so_far += r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_all(int fd, std::vector<uint8_t>* buffer, size_t size) {
|
||||
return read_all(fd, buffer->data(), 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(ota_write(fd, data+written, size-written));
|
||||
if (w == -1) {
|
||||
failure_type = kFwriteFailure;
|
||||
PLOG(ERROR) << "write failed";
|
||||
return -1;
|
||||
}
|
||||
written += w;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_all(int fd, const std::vector<uint8_t>& buffer, size_t size) {
|
||||
return write_all(fd, buffer.data(), size);
|
||||
}
|
||||
|
||||
static bool discard_blocks(int fd, off64_t offset, uint64_t size) {
|
||||
// Don't discard blocks unless the update is a retry run.
|
||||
if (!is_retry) {
|
||||
|
@ -293,7 +250,9 @@ class RangeSinkWriter {
|
|||
write_now = current_range_left_;
|
||||
}
|
||||
|
||||
if (write_all(fd_, data, write_now) == -1) {
|
||||
if (!android::base::WriteFully(fd_, data, write_now)) {
|
||||
failure_type = errno == EIO ? kEioFailure : kFwriteFailure;
|
||||
PLOG(ERROR) << "Failed to write " << write_now << " bytes of data";
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -510,7 +469,9 @@ static int ReadBlocks(const RangeSet& src, std::vector<uint8_t>* buffer, int fd)
|
|||
}
|
||||
|
||||
size_t size = (range.second - range.first) * BLOCKSIZE;
|
||||
if (read_all(fd, buffer->data() + p, size) == -1) {
|
||||
if (!android::base::ReadFully(fd, buffer->data() + p, size)) {
|
||||
failure_type = errno == EIO ? kEioFailure : kFreadFailure;
|
||||
PLOG(ERROR) << "Failed to read " << size << " bytes of data";
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -533,7 +494,9 @@ static int WriteBlocks(const RangeSet& tgt, const std::vector<uint8_t>& buffer,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (write_all(fd, buffer.data() + written, size) == -1) {
|
||||
if (!android::base::WriteFully(fd, buffer.data() + written, size)) {
|
||||
failure_type = errno == EIO ? kEioFailure : kFwriteFailure;
|
||||
PLOG(ERROR) << "Failed to write " << size << " bytes of data";
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -793,15 +756,18 @@ static int LoadStash(const CommandParameters& params, const std::string& id, boo
|
|||
return -1;
|
||||
}
|
||||
|
||||
android::base::unique_fd fd(TEMP_FAILURE_RETRY(ota_open(fn.c_str(), O_RDONLY)));
|
||||
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(fn.c_str(), O_RDONLY)));
|
||||
if (fd == -1) {
|
||||
failure_type = errno == EIO ? kEioFailure : kFileOpenFailure;
|
||||
PLOG(ERROR) << "open \"" << fn << "\" failed";
|
||||
return -1;
|
||||
}
|
||||
|
||||
allocate(sb.st_size, buffer);
|
||||
|
||||
if (read_all(fd, buffer, sb.st_size) == -1) {
|
||||
if (!android::base::ReadFully(fd, buffer->data(), sb.st_size)) {
|
||||
failure_type = errno == EIO ? kEioFailure : kFreadFailure;
|
||||
PLOG(ERROR) << "Failed to read " << sb.st_size << " bytes of data";
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -855,8 +821,9 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks
|
|||
LOG(INFO) << " writing " << blocks << " blocks to " << cn;
|
||||
|
||||
android::base::unique_fd fd(
|
||||
TEMP_FAILURE_RETRY(ota_open(fn.c_str(), O_WRONLY | O_CREAT | O_TRUNC, STASH_FILE_MODE)));
|
||||
TEMP_FAILURE_RETRY(open(fn.c_str(), O_WRONLY | O_CREAT | O_TRUNC, STASH_FILE_MODE)));
|
||||
if (fd == -1) {
|
||||
failure_type = errno == EIO ? kEioFailure : kFileOpenFailure;
|
||||
PLOG(ERROR) << "failed to create \"" << fn << "\"";
|
||||
return -1;
|
||||
}
|
||||
|
@ -866,12 +833,14 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (write_all(fd, buffer, blocks * BLOCKSIZE) == -1) {
|
||||
if (!android::base::WriteFully(fd, buffer.data(), blocks * BLOCKSIZE)) {
|
||||
failure_type = errno == EIO ? kEioFailure : kFwriteFailure;
|
||||
PLOG(ERROR) << "Failed to write " << blocks * BLOCKSIZE << " bytes of data";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ota_fsync(fd) == -1) {
|
||||
failure_type = kFsyncFailure;
|
||||
if (fsync(fd) == -1) {
|
||||
failure_type = errno == EIO ? kEioFailure : kFsyncFailure;
|
||||
PLOG(ERROR) << "fsync \"" << fn << "\" failed";
|
||||
return -1;
|
||||
}
|
||||
|
@ -883,7 +852,6 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks
|
|||
|
||||
std::string dname = GetStashFileName(base, "", "");
|
||||
if (!FsyncDir(dname)) {
|
||||
failure_type = kFsyncFailure;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1313,7 +1281,9 @@ static int PerformCommandZero(CommandParameters& params) {
|
|||
}
|
||||
|
||||
for (size_t j = range.first; j < range.second; ++j) {
|
||||
if (write_all(params.fd, params.buffer, BLOCKSIZE) == -1) {
|
||||
if (!android::base::WriteFully(params.fd, params.buffer.data(), BLOCKSIZE)) {
|
||||
failure_type = errno == EIO ? kEioFailure : kFwriteFailure;
|
||||
PLOG(ERROR) << "Failed to write " << BLOCKSIZE << " bytes of data";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -1560,7 +1530,8 @@ static int PerformCommandComputeHashTree(CommandParameters& params) {
|
|||
}
|
||||
|
||||
for (size_t i = range.first; i < range.second; i++) {
|
||||
if (read_all(params.fd, buffer, BLOCKSIZE) == -1) {
|
||||
if (!android::base::ReadFully(params.fd, buffer, BLOCKSIZE)) {
|
||||
failure_type = errno == EIO ? kEioFailure : kFreadFailure;
|
||||
LOG(ERROR) << "Failed to read data in " << range.first << ":" << range.second;
|
||||
return -1;
|
||||
}
|
||||
|
@ -1676,8 +1647,9 @@ static Value* PerformBlockImageUpdate(const char* name, State* state,
|
|||
return StringValue("");
|
||||
}
|
||||
|
||||
params.fd.reset(TEMP_FAILURE_RETRY(ota_open(blockdev_filename->data.c_str(), O_RDWR)));
|
||||
params.fd.reset(TEMP_FAILURE_RETRY(open(blockdev_filename->data.c_str(), O_RDWR)));
|
||||
if (params.fd == -1) {
|
||||
failure_type = errno == EIO ? kEioFailure : kFileOpenFailure;
|
||||
PLOG(ERROR) << "open \"" << blockdev_filename->data << "\" failed";
|
||||
return StringValue("");
|
||||
}
|
||||
|
@ -1859,8 +1831,8 @@ static Value* PerformBlockImageUpdate(const char* name, State* state,
|
|||
}
|
||||
|
||||
if (params.canwrite) {
|
||||
if (ota_fsync(params.fd) == -1) {
|
||||
failure_type = kFsyncFailure;
|
||||
if (fsync(params.fd) == -1) {
|
||||
failure_type = errno == EIO ? kEioFailure : kFsyncFailure;
|
||||
PLOG(ERROR) << "fsync failed";
|
||||
goto pbiudone;
|
||||
}
|
||||
|
@ -1920,8 +1892,8 @@ pbiudone:
|
|||
LOG(INFO) << "verified partition contents; update may be resumed";
|
||||
}
|
||||
|
||||
if (ota_fsync(params.fd) == -1) {
|
||||
failure_type = kFsyncFailure;
|
||||
if (fsync(params.fd) == -1) {
|
||||
failure_type = errno == EIO ? kEioFailure : kFsyncFailure;
|
||||
PLOG(ERROR) << "fsync failed";
|
||||
}
|
||||
// params.fd will be automatically closed because it's a unique_fd.
|
||||
|
@ -2059,9 +2031,10 @@ Value* RangeSha1Fn(const char* name, State* state, const std::vector<std::unique
|
|||
return StringValue("");
|
||||
}
|
||||
|
||||
android::base::unique_fd fd(ota_open(blockdev_filename->data.c_str(), O_RDWR));
|
||||
android::base::unique_fd fd(open(blockdev_filename->data.c_str(), O_RDWR));
|
||||
if (fd == -1) {
|
||||
ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", blockdev_filename->data.c_str(),
|
||||
CauseCode cause_code = errno == EIO ? kEioFailure : kFileOpenFailure;
|
||||
ErrorAbort(state, cause_code, "open \"%s\" failed: %s", blockdev_filename->data.c_str(),
|
||||
strerror(errno));
|
||||
return StringValue("");
|
||||
}
|
||||
|
@ -2081,8 +2054,9 @@ Value* RangeSha1Fn(const char* name, State* state, const std::vector<std::unique
|
|||
}
|
||||
|
||||
for (size_t j = range.first; j < range.second; ++j) {
|
||||
if (read_all(fd, &buffer, BLOCKSIZE) == -1) {
|
||||
ErrorAbort(state, kFreadFailure, "failed to read %s: %s", blockdev_filename->data.c_str(),
|
||||
if (!android::base::ReadFully(fd, buffer.data(), BLOCKSIZE)) {
|
||||
CauseCode cause_code = errno == EIO ? kEioFailure : kFreadFailure;
|
||||
ErrorAbort(state, cause_code, "failed to read %s: %s", blockdev_filename->data.c_str(),
|
||||
strerror(errno));
|
||||
return StringValue("");
|
||||
}
|
||||
|
@ -2121,9 +2095,10 @@ Value* CheckFirstBlockFn(const char* name, State* state,
|
|||
return StringValue("");
|
||||
}
|
||||
|
||||
android::base::unique_fd fd(ota_open(arg_filename->data.c_str(), O_RDONLY));
|
||||
android::base::unique_fd fd(open(arg_filename->data.c_str(), O_RDONLY));
|
||||
if (fd == -1) {
|
||||
ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", arg_filename->data.c_str(),
|
||||
CauseCode cause_code = errno == EIO ? kEioFailure : kFileOpenFailure;
|
||||
ErrorAbort(state, cause_code, "open \"%s\" failed: %s", arg_filename->data.c_str(),
|
||||
strerror(errno));
|
||||
return StringValue("");
|
||||
}
|
||||
|
@ -2132,7 +2107,8 @@ Value* CheckFirstBlockFn(const char* name, State* state,
|
|||
std::vector<uint8_t> block0_buffer(BLOCKSIZE);
|
||||
|
||||
if (ReadBlocks(blk0, &block0_buffer, fd) == -1) {
|
||||
ErrorAbort(state, kFreadFailure, "failed to read %s: %s", arg_filename->data.c_str(),
|
||||
CauseCode cause_code = errno == EIO ? kEioFailure : kFreadFailure;
|
||||
ErrorAbort(state, cause_code, "failed to read %s: %s", arg_filename->data.c_str(),
|
||||
strerror(errno));
|
||||
return StringValue("");
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include <android-base/properties.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <applypatch/applypatch.h>
|
||||
#include <bootloader_message/bootloader_message.h>
|
||||
#include <ext4_utils/wipe.h>
|
||||
|
@ -56,7 +57,6 @@
|
|||
#include <ziparchive/zip_archive.h>
|
||||
|
||||
#include "edify/expr.h"
|
||||
#include "otafault/ota_io.h"
|
||||
#include "otautil/dirutil.h"
|
||||
#include "otautil/error_code.h"
|
||||
#include "otautil/mounts.h"
|
||||
|
@ -137,8 +137,8 @@ Value* PackageExtractFileFn(const char* name, State* state,
|
|||
return StringValue("");
|
||||
}
|
||||
|
||||
unique_fd fd(TEMP_FAILURE_RETRY(
|
||||
ota_open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)));
|
||||
android::base::unique_fd fd(TEMP_FAILURE_RETRY(
|
||||
open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)));
|
||||
if (fd == -1) {
|
||||
PLOG(ERROR) << name << ": can't open " << dest_path << " for write";
|
||||
return StringValue("");
|
||||
|
@ -152,11 +152,12 @@ Value* PackageExtractFileFn(const char* name, State* state,
|
|||
<< "\": " << ErrorCodeString(ret);
|
||||
success = false;
|
||||
}
|
||||
if (ota_fsync(fd) == -1) {
|
||||
if (fsync(fd) == -1) {
|
||||
PLOG(ERROR) << "fsync of \"" << dest_path << "\" failed";
|
||||
success = false;
|
||||
}
|
||||
if (ota_close(fd) == -1) {
|
||||
|
||||
if (close(fd.release()) != 0) {
|
||||
PLOG(ERROR) << "close of \"" << dest_path << "\" failed";
|
||||
success = false;
|
||||
}
|
||||
|
@ -614,33 +615,12 @@ Value* FileGetPropFn(const char* name, State* state,
|
|||
const std::string& filename = args[0];
|
||||
const std::string& key = args[1];
|
||||
|
||||
struct stat st;
|
||||
if (stat(filename.c_str(), &st) < 0) {
|
||||
return ErrorAbort(state, kFileGetPropFailure, "%s: failed to stat \"%s\": %s", name,
|
||||
filename.c_str(), strerror(errno));
|
||||
}
|
||||
|
||||
constexpr off_t MAX_FILE_GETPROP_SIZE = 65536;
|
||||
if (st.st_size > MAX_FILE_GETPROP_SIZE) {
|
||||
return ErrorAbort(state, kFileGetPropFailure, "%s too large for %s (max %lld)",
|
||||
filename.c_str(), name, static_cast<long long>(MAX_FILE_GETPROP_SIZE));
|
||||
}
|
||||
|
||||
std::string buffer(st.st_size, '\0');
|
||||
unique_file f(ota_fopen(filename.c_str(), "rb"));
|
||||
if (f == nullptr) {
|
||||
return ErrorAbort(state, kFileOpenFailure, "%s: failed to open %s: %s", name, filename.c_str(),
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
if (ota_fread(&buffer[0], 1, st.st_size, f.get()) != static_cast<size_t>(st.st_size)) {
|
||||
ErrorAbort(state, kFreadFailure, "%s: failed to read %zu bytes from %s", name,
|
||||
static_cast<size_t>(st.st_size), filename.c_str());
|
||||
std::string buffer;
|
||||
if (!android::base::ReadFileToString(filename, &buffer)) {
|
||||
ErrorAbort(state, kFreadFailure, "%s: failed to read %s", name, filename.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ota_fclose(f);
|
||||
|
||||
std::vector<std::string> lines = android::base::Split(buffer, "\n");
|
||||
for (size_t i = 0; i < lines.size(); i++) {
|
||||
std::string line = android::base::Trim(lines[i]);
|
||||
|
@ -913,7 +893,12 @@ Value* WipeBlockDeviceFn(const char* name, State* state, const std::vector<std::
|
|||
if (!android::base::ParseUint(len_str.c_str(), &len)) {
|
||||
return nullptr;
|
||||
}
|
||||
unique_fd fd(ota_open(filename.c_str(), O_WRONLY, 0644));
|
||||
android::base::unique_fd fd(open(filename.c_str(), O_WRONLY));
|
||||
if (fd == -1) {
|
||||
PLOG(ERROR) << "Failed to open " << filename;
|
||||
return StringValue("");
|
||||
}
|
||||
|
||||
// The wipe_block_device function in ext4_utils returns 0 on success and 1
|
||||
// for failure.
|
||||
int status = wipe_block_device(fd, len);
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include <ziparchive/zip_archive.h>
|
||||
|
||||
#include "edify/expr.h"
|
||||
#include "otafault/config.h"
|
||||
#include "otautil/dirutil.h"
|
||||
#include "otautil/error_code.h"
|
||||
#include "otautil/sysutil.h"
|
||||
|
@ -47,8 +46,6 @@
|
|||
// (Note it's "updateR-script", not the older "update-script".)
|
||||
static constexpr const char* SCRIPT_NAME = "META-INF/com/google/android/updater-script";
|
||||
|
||||
extern bool have_eio_error;
|
||||
|
||||
struct selabel_handle *sehandle;
|
||||
|
||||
static void UpdaterLogger(android::base::LogId /* id */, android::base::LogSeverity /* severity */,
|
||||
|
@ -166,15 +163,10 @@ int main(int argc, char** argv) {
|
|||
printf("unexpected argument: %s", argv[4]);
|
||||
}
|
||||
}
|
||||
ota_io_init(za, state.is_retry);
|
||||
|
||||
std::string result;
|
||||
bool status = Evaluate(&state, root, &result);
|
||||
|
||||
if (have_eio_error) {
|
||||
fprintf(cmd_pipe, "retry_update\n");
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
if (state.errmsg.empty()) {
|
||||
LOG(ERROR) << "script aborted (no error message)";
|
||||
|
@ -206,6 +198,9 @@ int main(int argc, char** argv) {
|
|||
if (state.cause_code == kPatchApplicationFailure) {
|
||||
LOG(INFO) << "Patch application failed, retry update.";
|
||||
fprintf(cmd_pipe, "retry_update\n");
|
||||
} else if (state.cause_code == kEioFailure) {
|
||||
LOG(INFO) << "Update failed due to EIO, retry update.";
|
||||
fprintf(cmd_pipe, "retry_update\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue