15f51444dSShawn McCarney /** 25f51444dSShawn McCarney * Copyright © 2020 IBM Corporation 35f51444dSShawn McCarney * 45f51444dSShawn McCarney * Licensed under the Apache License, Version 2.0 (the "License"); 55f51444dSShawn McCarney * you may not use this file except in compliance with the License. 65f51444dSShawn McCarney * You may obtain a copy of the License at 75f51444dSShawn McCarney * 85f51444dSShawn McCarney * http://www.apache.org/licenses/LICENSE-2.0 95f51444dSShawn McCarney * 105f51444dSShawn McCarney * Unless required by applicable law or agreed to in writing, software 115f51444dSShawn McCarney * distributed under the License is distributed on an "AS IS" BASIS, 125f51444dSShawn McCarney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135f51444dSShawn McCarney * See the License for the specific language governing permissions and 145f51444dSShawn McCarney * limitations under the License. 155f51444dSShawn McCarney */ 165f51444dSShawn McCarney 175f51444dSShawn McCarney #include "temporary_file.hpp" 185f51444dSShawn McCarney 195f51444dSShawn McCarney #include <errno.h> // for errno 205f51444dSShawn McCarney #include <stdlib.h> // for mkstemp() 215f51444dSShawn McCarney #include <string.h> // for strerror() 225f51444dSShawn McCarney #include <unistd.h> // for close() 235f51444dSShawn McCarney 245f51444dSShawn McCarney #include <stdexcept> 255f51444dSShawn McCarney #include <string> 265f51444dSShawn McCarney 275f51444dSShawn McCarney namespace phosphor::power::util 285f51444dSShawn McCarney { 295f51444dSShawn McCarney 305f51444dSShawn McCarney namespace fs = std::filesystem; 315f51444dSShawn McCarney TemporaryFile()325f51444dSShawn McCarneyTemporaryFile::TemporaryFile() 335f51444dSShawn McCarney { 345f51444dSShawn McCarney // Build template path required by mkstemp() 35*f5402197SPatrick Williams std::string templatePath = 36*f5402197SPatrick Williams fs::temp_directory_path() / "phosphor-power-XXXXXX"; 375f51444dSShawn McCarney 385f51444dSShawn McCarney // Generate unique file name, create file, and open it. The XXXXXX 395f51444dSShawn McCarney // characters are replaced by mkstemp() to make the file name unique. 405f51444dSShawn McCarney int fd = mkstemp(templatePath.data()); 415f51444dSShawn McCarney if (fd == -1) 425f51444dSShawn McCarney { 435f51444dSShawn McCarney throw std::runtime_error{ 445f51444dSShawn McCarney std::string{"Unable to create temporary file: "} + strerror(errno)}; 455f51444dSShawn McCarney } 465f51444dSShawn McCarney 475f51444dSShawn McCarney // Store path to temporary file 485f51444dSShawn McCarney path = templatePath; 495f51444dSShawn McCarney 505f51444dSShawn McCarney // Close file descriptor 515f51444dSShawn McCarney if (close(fd) == -1) 525f51444dSShawn McCarney { 535f51444dSShawn McCarney // Save errno value; will likely change when we delete temporary file 545f51444dSShawn McCarney int savedErrno = errno; 555f51444dSShawn McCarney 565f51444dSShawn McCarney // Delete temporary file. The destructor won't be called because the 575f51444dSShawn McCarney // exception below causes this constructor to exit without completing. 585f51444dSShawn McCarney remove(); 595f51444dSShawn McCarney 605f51444dSShawn McCarney throw std::runtime_error{ 615f51444dSShawn McCarney std::string{"Unable to close temporary file: "} + 625f51444dSShawn McCarney strerror(savedErrno)}; 635f51444dSShawn McCarney } 645f51444dSShawn McCarney } 655f51444dSShawn McCarney operator =(TemporaryFile && file)665f51444dSShawn McCarneyTemporaryFile& TemporaryFile::operator=(TemporaryFile&& file) 675f51444dSShawn McCarney { 685f51444dSShawn McCarney // Verify not assigning object to itself (a = std::move(a)) 695f51444dSShawn McCarney if (this != &file) 705f51444dSShawn McCarney { 715f51444dSShawn McCarney // Delete temporary file owned by this object 725f51444dSShawn McCarney remove(); 735f51444dSShawn McCarney 745f51444dSShawn McCarney // Move temporary file path from other object, transferring ownership 755f51444dSShawn McCarney path = std::move(file.path); 765f51444dSShawn McCarney 775f51444dSShawn McCarney // Clear path in other object; after move path is in unspecified state 785f51444dSShawn McCarney file.path.clear(); 795f51444dSShawn McCarney } 805f51444dSShawn McCarney return *this; 815f51444dSShawn McCarney } 825f51444dSShawn McCarney remove()835f51444dSShawn McCarneyvoid TemporaryFile::remove() 845f51444dSShawn McCarney { 855f51444dSShawn McCarney if (!path.empty()) 865f51444dSShawn McCarney { 875f51444dSShawn McCarney // Delete temporary file from file system 885f51444dSShawn McCarney fs::remove(path); 895f51444dSShawn McCarney 905f51444dSShawn McCarney // Clear path to indicate file has been deleted 915f51444dSShawn McCarney path.clear(); 925f51444dSShawn McCarney } 935f51444dSShawn McCarney } 945f51444dSShawn McCarney 955f51444dSShawn McCarney } // namespace phosphor::power::util 96