1// 2// Copyright (C) 2015 The Android Open Source Project 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15// 16 17#include "tpm_manager/server/local_data_store_impl.h" 18 19#include <fcntl.h> 20 21#include <string> 22 23#include <base/files/file_path.h> 24#include <base/files/file_util.h> 25#include <base/files/important_file_writer.h> 26 27using base::FilePath; 28 29namespace tpm_manager { 30 31const char kTpmLocalDataFile[] = "/var/lib/tpm_manager/local_tpm_data"; 32const mode_t kLocalDataPermissions = 0600; 33 34bool LocalDataStoreImpl::Read(LocalData* data) { 35 CHECK(data); 36 FilePath path(kTpmLocalDataFile); 37 if (!base::PathExists(path)) { 38 data->Clear(); 39 return true; 40 } 41 int permissions = 0; 42 if (base::GetPosixFilePermissions(path, &permissions) && 43 (permissions & ~kLocalDataPermissions) != 0) { 44 base::SetPosixFilePermissions(path, kLocalDataPermissions); 45 } 46 std::string file_data; 47 if (!ReadFileToString(path, &file_data)) { 48 LOG(ERROR) << "Error reading data store file."; 49 return false; 50 } 51 if (!data->ParseFromString(file_data)) { 52 LOG(ERROR) << "Error parsing file data into protobuf."; 53 return false; 54 } 55 return true; 56} 57 58bool LocalDataStoreImpl::Write(const LocalData& data) { 59 std::string file_data; 60 if (!data.SerializeToString(&file_data)) { 61 LOG(ERROR) << "Error serializing file to string."; 62 return false; 63 } 64 FilePath path(kTpmLocalDataFile); 65 if (!base::CreateDirectory(path.DirName())) { 66 LOG(ERROR) << "Cannot create directory: " << path.DirName().value(); 67 return false; 68 } 69 if (!base::ImportantFileWriter::WriteFileAtomically(path, file_data)) { 70 LOG(ERROR) << "Failed to write file: " << path.value(); 71 return false; 72 } 73 if (!base::SetPosixFilePermissions(path, kLocalDataPermissions)) { 74 LOG(ERROR) << "Failed to set permissions for file: " << path.value(); 75 return false; 76 } 77 // Sync the parent directory. 78 std::string dir_name = path.DirName().value(); 79 int dir_fd = HANDLE_EINTR(open(dir_name.c_str(), O_RDONLY|O_DIRECTORY)); 80 if (dir_fd < 0) { 81 PLOG(WARNING) << "Could not open " << dir_name << " for syncing"; 82 return false; 83 } 84 // POSIX specifies EINTR as a possible return value of fsync(). 85 int result = HANDLE_EINTR(fsync(dir_fd)); 86 if (result < 0) { 87 PLOG(WARNING) << "Failed to sync " << dir_name; 88 close(dir_fd); 89 return false; 90 } 91 // close() may not be retried on error. 92 result = IGNORE_EINTR(close(dir_fd)); 93 if (result < 0) { 94 PLOG(WARNING) << "Failed to close after sync " << dir_name; 95 return false; 96 } 97 return true; 98} 99 100} // namespace tpm_manager 101