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 McCarney TemporaryFile::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 McCarney TemporaryFile& 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 McCarney void 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