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