1 // -*- coding: utf-8 -*- 2 // Copyright (C) 2013, 2015, 2017 Laboratoire de Recherche et 3 // Développement de l'Epita (LRDE). 4 // 5 // This file is part of Spot, a model checking library. 6 // 7 // Spot is free software; you can redistribute it and/or modify it 8 // under the terms of the GNU General Public License as published by 9 // the Free Software Foundation; either version 3 of the License, or 10 // (at your option) any later version. 11 // 12 // Spot is distributed in the hope that it will be useful, but WITHOUT 13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 // License for more details. 16 // 17 // You should have received a copy of the GNU General Public License 18 // along with this program. If not, see <http://www.gnu.org/licenses/>. 19 20 #pragma once 21 22 #include <spot/misc/common.hh> 23 #include <new> 24 #include <stdexcept> 25 #include <iostream> 26 #include <list> 27 #include <spot/misc/formater.hh> 28 29 namespace spot 30 { 31 /// \ingroup misc_tools 32 /// @{ 33 34 /// \brief Temporary file name 35 /// 36 /// This class serves a dual purpose. 37 /// 38 /// 1. It carries the name of a temporary file, created with 39 /// create_tmpfile(). 40 /// 2. It represents the life of the associated file. The file is 41 /// erased as soon as the temporary_file instance is destroyed. 42 /// 43 /// Note that there are two ways to destroy temporary_file 44 /// instances. Either directly with delete, or indirectly by 45 /// calling cleanup_tmpfiles(). 46 /// You should never delete an instance that has been created 47 /// before the last call to cleanup_tmpfiles(), because that 48 /// instance has already been deleted. 49 class SPOT_API temporary_file: public printable 50 { 51 public: 52 typedef std::list<temporary_file*>::iterator cleanpos_t; 53 54 SPOT_LOCAL temporary_file(char* name, cleanpos_t cp); 55 56 temporary_file(const temporary_file& other) = delete; 57 58 virtual ~temporary_file() override; 59 name() const60 const char* name() const 61 { 62 return name_; 63 } 64 operator <<(std::ostream & os,const temporary_file * f)65 friend std::ostream& operator<<(std::ostream& os, const temporary_file* f) 66 { 67 os << f->name(); 68 return os; 69 } 70 71 virtual void print(std::ostream & os,const char *) const72 print(std::ostream& os, const char*) const final override 73 { 74 os << this; 75 } 76 77 protected: 78 char* name_; 79 cleanpos_t cleanpos_; 80 }; 81 82 /// \brief Open temporary file 83 /// 84 /// This is a specialization of temporary_file that also holds an 85 /// open file descriptor, as created by create_open_tmpfile(). 86 /// 87 /// Use the open_temporary_file::close() method if you want to close 88 /// that descriptor; do no call the POSIX close() function directly. 89 class SPOT_API open_temporary_file final: public temporary_file 90 { 91 public: 92 SPOT_LOCAL open_temporary_file(char* name, cleanpos_t cp, int fd); 93 virtual ~open_temporary_file() override; 94 95 void close(); 96 fd() const97 int fd() const 98 { 99 return fd_; 100 } 101 102 protected: 103 int fd_; 104 }; 105 106 /// \brief Create a temporary file. 107 /// 108 /// The file name will start with \a prefix, be followed by 6 109 /// randomish characters and will end in \a suffix. Usually suffix 110 /// is used to set an extension (you should include the dot). 111 /// 112 /// The temporary file is created and left empty. If you need 113 /// to fill it, consider using create_open_tmpfile() instead. 114 SPOT_API temporary_file* 115 create_tmpfile(const char* prefix, const char* suffix = nullptr); 116 117 /// \brief Create a temporary file and leave it open for writing. 118 /// 119 /// Same as create_tmpfile, be leave the file open for writing. The 120 /// open_temporary_file::fd() method returns the file descriptor. 121 SPOT_API open_temporary_file* 122 create_open_tmpfile(const char* prefix, const char* suffix = nullptr); 123 124 /// \brief Delete all temporary files. 125 /// 126 /// Delete all temporary files that have been created but haven't 127 /// been deleted so far. The verb "delete" should be understood as 128 /// both the C++ delete operator (all temporary_file and 129 /// open_temporary_file instance are destroyed) and as the file 130 /// system operation (the actual files are removed). 131 /// 132 /// Even in programs where temporary_file instance are consciously 133 /// destroyed when they are not needed, cleanup_tmpfiles() could 134 /// still be useful in signal handlers, for instance to clean all 135 /// temporary files upon SIGINT. 136 SPOT_API void 137 cleanup_tmpfiles(); 138 139 /// @} 140 } 141