/* * 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 #include #include #include #include #include #include #include #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> 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 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& 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