1bdb61e5fa
TEMP_FAILURE_RETRY expects an argument that returns -1 on temporary failure, not a boolean. Test: TreeHugger Change-Id: If8cb4a440e909c4ed7cbfdd34454670b0d5ee045 Exempt-From-Owner-Approval: Janitorial fix
131 lines
3.7 KiB
C++
131 lines
3.7 KiB
C++
/*
|
|
* Copyright (c) 2019, 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 "Util"
|
|
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
#include <android-base/logging.h>
|
|
#include <android-base/stringprintf.h>
|
|
|
|
#include <android/security/identity/ICredentialStore.h>
|
|
|
|
#include "Util.h"
|
|
|
|
namespace android {
|
|
namespace security {
|
|
namespace identity {
|
|
|
|
using ::android::base::StringPrintf;
|
|
|
|
Status halStatusToError(const Status& halStatus, int credStoreError) {
|
|
string message = StringPrintf(
|
|
"HAL failed with exception code %d (%s), service-specific error code %d, message '%s'",
|
|
halStatus.exceptionCode(), Status::exceptionToString(halStatus.exceptionCode()).c_str(),
|
|
halStatus.serviceSpecificErrorCode(), halStatus.exceptionMessage().c_str());
|
|
return Status::fromServiceSpecificError(credStoreError, message.c_str());
|
|
}
|
|
|
|
Status halStatusToGenericError(const Status& halStatus) {
|
|
return halStatusToError(halStatus, ICredentialStore::ERROR_GENERIC);
|
|
}
|
|
|
|
optional<vector<uint8_t>> fileGetContents(const string& path) {
|
|
int fd = open(path.c_str(), O_RDONLY);
|
|
if (fd == -1) {
|
|
PLOG(ERROR) << "Error opening " << path;
|
|
return {};
|
|
}
|
|
|
|
struct stat statbuf;
|
|
if (fstat(fd, &statbuf) != 0) {
|
|
PLOG(ERROR) << "Error statting " << path;
|
|
close(fd);
|
|
return {};
|
|
}
|
|
vector<uint8_t> data;
|
|
data.resize(statbuf.st_size);
|
|
|
|
uint8_t* p = data.data();
|
|
size_t remaining = data.size();
|
|
while (remaining > 0) {
|
|
ssize_t numRead = TEMP_FAILURE_RETRY(read(fd, p, remaining));
|
|
if (numRead <= 0) {
|
|
PLOG(ERROR) << "Failed reading from '" << path << "'";
|
|
close(fd);
|
|
return {};
|
|
}
|
|
p += numRead;
|
|
remaining -= numRead;
|
|
}
|
|
close(fd);
|
|
|
|
return data;
|
|
}
|
|
|
|
bool fileSetContents(const string& path, const vector<uint8_t>& data) {
|
|
char tempName[4096];
|
|
int fd;
|
|
|
|
string tempNameStr = path + ".XXXXXX";
|
|
if (tempNameStr.size() >= sizeof tempName - 1) {
|
|
LOG(ERROR) << "Path name too long";
|
|
return false;
|
|
}
|
|
strncpy(tempName, tempNameStr.c_str(), sizeof tempName);
|
|
|
|
fd = mkstemp(tempName);
|
|
if (fd == -1) {
|
|
PLOG(ERROR) << "Error creating temp file for '" << path << "'";
|
|
return false;
|
|
}
|
|
|
|
const uint8_t* p = data.data();
|
|
size_t remaining = data.size();
|
|
while (remaining > 0) {
|
|
ssize_t numWritten = TEMP_FAILURE_RETRY(write(fd, p, remaining));
|
|
if (numWritten <= 0) {
|
|
PLOG(ERROR) << "Failed writing into temp file for '" << path << "'";
|
|
close(fd);
|
|
return false;
|
|
}
|
|
p += numWritten;
|
|
remaining -= numWritten;
|
|
}
|
|
|
|
if (TEMP_FAILURE_RETRY(fsync(fd))) {
|
|
PLOG(ERROR) << "Failed fsyncing temp file for '" << path << "'";
|
|
close(fd);
|
|
return false;
|
|
}
|
|
close(fd);
|
|
|
|
if (rename(tempName, path.c_str()) != 0) {
|
|
PLOG(ERROR) << "Error renaming temp file for '" << path << "'";
|
|
close(fd);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
} // namespace identity
|
|
} // namespace security
|
|
} // namespace android
|