Home | History | Annotate | Download | only in tmpfile
      1 /*
      2  * Copyright (c) 2015, Intel Corporation
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without modification,
      6  * are permitted provided that the following conditions are met:
      7  *
      8  * 1. Redistributions of source code must retain the above copyright notice, this
      9  * list of conditions and the following disclaimer.
     10  *
     11  * 2. Redistributions in binary form must reproduce the above copyright notice,
     12  * this list of conditions and the following disclaimer in the documentation and/or
     13  * other materials provided with the distribution.
     14  *
     15  * 3. Neither the name of the copyright holder nor the names of its contributors
     16  * may be used to endorse or promote products derived from this software without
     17  * specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
     23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 #pragma once
     31 
     32 #include <exception>
     33 #include <fstream>
     34 #include <string>
     35 #include <array>
     36 
     37 #include <cerrno>
     38 #include <cstring>
     39 
     40 namespace parameterFramework
     41 {
     42 namespace utility
     43 {
     44 
     45 /** Create a temporary file with the given content. */
     46 class TmpFile
     47 {
     48 public:
     49     TmpFile(std::string content) : mPath(mktmp())
     50     {
     51         std::ofstream file(mPath);
     52         file.exceptions(std::ofstream::failbit | std::ofstream::badbit);
     53         file << content;
     54         // Close explicitly to detect errors (fstream destructor does not throw)
     55         file.close();
     56     }
     57 
     58     TmpFile(TmpFile &&right) : mPath(std::move(right.mPath)) { right.mPath.clear(); }
     59 
     60     /** Forbid copy semantic as sharing the tmp file is not needed.
     61      * @{ */
     62     TmpFile(const TmpFile &right) = delete;
     63     TmpFile &operator=(const TmpFile &right) = delete;
     64     /** @} */
     65 
     66     TmpFile &operator=(TmpFile &&right)
     67     {
     68         remove();
     69         mPath = std::move(right.mPath);
     70         right.mPath.clear();
     71         return *this;
     72     }
     73 
     74     ~TmpFile() { remove(); }
     75 
     76     /** @return the path to the temporary file.
     77      *          "" if the file was moved from.
     78      */
     79     const std::string &getPath() const { return mPath; }
     80 private:
     81     /** @return a valid unique file name. */
     82     std::string mktmp();
     83 
     84     /** Throw an std::runtime_error with a message constructed from the context and std::errno.
     85      *
     86      * Call it after a c standard function failure.
     87      */
     88     static void throwErrnoError(std::string context)
     89     {
     90         auto message = context + ": (" + std::to_string(errno) + ") " + std::strerror(errno);
     91         throw std::runtime_error(message);
     92     }
     93 
     94     void remove()
     95     {
     96         if (not mPath.empty()) {
     97             if (std::remove(mPath.c_str()) != 0) {
     98                 throwErrnoError("Could not delete tmpfile");
     99             }
    100         }
    101     }
    102     std::string mPath;
    103 };
    104 
    105 } // utility
    106 } // parameterFramework
    107