1 /** 2 * Copyright © 2020 IBM Corporation 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 "temporary_file.hpp" 18 19 #include <errno.h> // for errno 20 #include <stdlib.h> // for mkstemp() 21 #include <string.h> // for strerror() 22 #include <unistd.h> // for close() 23 24 #include <stdexcept> 25 #include <string> 26 27 namespace phosphor::power::util 28 { 29 30 namespace fs = std::filesystem; 31 32 TemporaryFile::TemporaryFile() 33 { 34 // Build template path required by mkstemp() 35 std::string templatePath = fs::temp_directory_path() / 36 "phosphor-power-XXXXXX"; 37 38 // Generate unique file name, create file, and open it. The XXXXXX 39 // characters are replaced by mkstemp() to make the file name unique. 40 int fd = mkstemp(templatePath.data()); 41 if (fd == -1) 42 { 43 throw std::runtime_error{ 44 std::string{"Unable to create temporary file: "} + strerror(errno)}; 45 } 46 47 // Store path to temporary file 48 path = templatePath; 49 50 // Close file descriptor 51 if (close(fd) == -1) 52 { 53 // Save errno value; will likely change when we delete temporary file 54 int savedErrno = errno; 55 56 // Delete temporary file. The destructor won't be called because the 57 // exception below causes this constructor to exit without completing. 58 remove(); 59 60 throw std::runtime_error{ 61 std::string{"Unable to close temporary file: "} + 62 strerror(savedErrno)}; 63 } 64 } 65 66 TemporaryFile& TemporaryFile::operator=(TemporaryFile&& file) 67 { 68 // Verify not assigning object to itself (a = std::move(a)) 69 if (this != &file) 70 { 71 // Delete temporary file owned by this object 72 remove(); 73 74 // Move temporary file path from other object, transferring ownership 75 path = std::move(file.path); 76 77 // Clear path in other object; after move path is in unspecified state 78 file.path.clear(); 79 } 80 return *this; 81 } 82 83 void TemporaryFile::remove() 84 { 85 if (!path.empty()) 86 { 87 // Delete temporary file from file system 88 fs::remove(path); 89 90 // Clear path to indicate file has been deleted 91 path.clear(); 92 } 93 } 94 95 } // namespace phosphor::power::util 96