2 * @brief fstream which creates files with mkstemp.
4 * @author Gerd v. Egidy
6 * @copyright © Copyright 2010 by Intra2net AG
13 #ifndef __I2N_TMPFSTREAM_HPP__
14 #define __I2N_TMPFSTREAM_HPP__
18 #include <boost/iostreams/detail/char_traits.hpp>
19 #include <boost/config.hpp>
20 #include <boost/iostreams/stream.hpp>
21 #include <boost/iostreams/device/file_descriptor.hpp>
23 #include <userfunc.hpp>
30 namespace bio = boost::iostreams;
33 * @brief fstream or ofstream which creates files with mkstemp
35 * This class becomes an std::ostream or std::stream depending on the
37 * For the most common cases, use the provided typedefs @ref tmpofstream
38 * and @ref tmpfstream.
39 * The temporary file is created with permissions 0600. These can be changed
40 * with @ref set_file_mode.
42 * @param Device Class which implements the Device Concept of boost::iostreams
43 * and offers a function Open(filedescriptor,close_on_exit). Usually
44 * this is boost::iostreams::file_descriptor and
45 * boost::iostreams::file_descriptor_sink
46 * @param Tr Character traits type
47 * @param Alloc Allocator for the character buffers
49 template< typename Device,
51 BOOST_IOSTREAMS_CHAR_TRAITS(
52 BOOST_DEDUCED_TYPENAME bio::char_type_of<Device>::type
56 BOOST_DEDUCED_TYPENAME bio::char_type_of<Device>::type
58 class tmpfstreamTempl : public bio::stream<Device, Tr, Alloc>
61 std::string tmpfilename;
67 * @brief Constructs an unopened tmpfstreamTempl.
70 : unlinked(false), fd(-1), bio::stream<Device, Tr, Alloc>()
74 * @brief Constructs and opens the tmpfstreamTempl.
76 * @param tmpnametemplate Path of the temporary file to be opened.
77 * The last 6 characters must be XXXXXX and they
78 * will be replaced with something random.
79 * @param mode std::ios_base::open_mode to open the file with
80 * @param buffer_size The size of any buffers that need to be allocated
81 * @param buffer_size The size of the putback buffer, relevant only for fstream
83 tmpfstreamTempl(const std::string& tmpnametemplate,
84 std::ios_base::open_mode mode = std::ios_base::out,
85 int buffer_size = -1 , int pback_size = -1)
86 : unlinked(false), fd(-1), bio::stream<Device, Tr, Alloc>()
88 open(tmpnametemplate,mode,buffer_size,pback_size);
91 bool open(const std::string& tmpnametemplate,
92 std::ios_base::open_mode mode = std::ios_base::out,
93 int buffer_size = -1 , int pback_size = -1);
96 * @brief Get the filename of the temporary file.
98 * @retval returns the filename really used with the XXXXXX replaced.
100 std::string get_tmp_filename()
101 { return tmpfilename; }
103 bool set_file_mode(mode_t mode);
105 bool set_owner(const I2n::User& user, const I2n::Group& group= I2n::Group());
112 bool move(const std::string& targetpath, bool overwrite=false);
119 * @brief ofstream which creates files with mkstemp
121 typedef tmpfstreamTempl<bio::file_descriptor_sink> tmpofstream;
123 * @brief fstream which creates files with mkstemp
125 typedef tmpfstreamTempl<bio::file_descriptor> tmpfstream;
128 * @brief fstream or ofstream which first writes to a temp file and atomically
129 * replaces an old file on close.
131 * This class becomes an std::ostream or std::stream depending on the
133 * For the most common cases, use the provided typedefs @ref tmpofcopystream
134 * and @ref tmpfcopystream.
135 * The temporary file is created with permissions 0600. On @ref close the
136 * permissions of the original file will be set to 0644 by default.
138 * @param Device Class which implements the Device Concept of boost::iostreams
139 * and offers a function Open(filedescriptor,close_on_exit). Usually
140 * this is boost::iostreams::file_descriptor and
141 * boost::iostreams::file_descriptor_sink
142 * @param Tr Character traits type
143 * @param Alloc Allocator for the character buffers
145 template< typename Device,
147 BOOST_IOSTREAMS_CHAR_TRAITS(
148 BOOST_DEDUCED_TYPENAME bio::char_type_of<Device>::type
152 BOOST_DEDUCED_TYPENAME bio::char_type_of<Device>::type
154 class tmpfcopystreamTempl : public tmpfstreamTempl<Device, Tr, Alloc>
157 std::string originalfilename;
159 mode_t filemode_on_close;
160 I2n::User UserOnClose;
161 I2n::Group GroupOnClose;
164 static const std::string default_template_suffix;
165 static const bool default_full_sync=false;
166 static const int default_filemode_on_close=0644;
169 * @brief Constructs an unopened tmpfcopystreamTempl.
171 tmpfcopystreamTempl()
172 : full_sync(default_full_sync),
173 filemode_on_close(default_filemode_on_close),
174 UserOnClose(), GroupOnClose(),
175 tmpfstreamTempl<Device, Tr, Alloc>()
179 * @brief Constructs and opens the tmpfcopystreamTempl.
181 * The temporary file will be in the same directory with .tmp.XXXXXX appended.
183 * @param filename The original filename which will be replaced on close
184 * @param mode std::ios_base::open_mode to open the file with
185 * @param buffer_size The size of any buffers that need to be allocated
186 * @param buffer_size The size of the putback buffer, relevant only for fstream
188 tmpfcopystreamTempl(const std::string& filename,
189 std::ios_base::open_mode mode = std::ios_base::out,
190 int buffer_size = -1 , int pback_size = -1)
191 : full_sync(default_full_sync),
192 filemode_on_close(default_filemode_on_close),
193 UserOnClose(), GroupOnClose(),
194 originalfilename(filename),
195 tmpfstreamTempl<Device, Tr, Alloc>
196 (filename+default_template_suffix,mode,buffer_size,pback_size)
200 * @brief Constructs and opens the tmpfcopystreamTempl.
202 * filename and tmpnametemplate must be on the same filesystem.
204 * @param filename The original filename which will be replaced on close
205 * @param tmpnametemplate Path of the temporary file to be opened.
206 * The last 6 characters must be XXXXXX and they
207 * will be replaced with something random.
208 * @param mode std::ios_base::open_mode to open the file with
209 * @param buffer_size The size of any buffers that need to be allocated
210 * @param buffer_size The size of the putback buffer, relevant only for fstream
212 tmpfcopystreamTempl(const std::string& filename,
213 const std::string& tmpnametemplate,
214 std::ios_base::open_mode mode = std::ios_base::out,
215 int buffer_size = -1 , int pback_size = -1)
216 : full_sync(default_full_sync),
217 filemode_on_close(default_filemode_on_close),
218 UserOnClose(), GroupOnClose(),
219 originalfilename(filename),
220 tmpfstreamTempl<Device, Tr, Alloc>
221 (tmpnametemplate,mode,buffer_size,pback_size)
224 ~tmpfcopystreamTempl()
228 * @brief Opens the tmpfcopystreamTempl.
230 * The temporary file will be in the same directory with .tmp.XXXXXX appended.
232 * @param filename The original filename which will be replaced on close
233 * @param mode std::ios_base::open_mode to open the file with
234 * @param buffer_size The size of any buffers that need to be allocated
235 * @param buffer_size The size of the putback buffer, relevant only for fstream
236 * @retval true if successful
238 bool open(const std::string& filename,
239 std::ios_base::open_mode mode = std::ios_base::out,
240 int buffer_size = -1 , int pback_size = -1)
242 originalfilename=filename;
243 return tmpfstreamTempl<Device, Tr, Alloc>
244 ::open(filename+default_template_suffix,mode,buffer_size,pback_size);
248 * @brief Opens the tmpfcopystreamTempl.
250 * filename and tmpnametemplate must be on the same filesystem.
252 * @param filename The original filename which will be replaced on close
253 * @param tmpnametemplate Path of the temporary file to be opened.
254 * The last 6 characters must be XXXXXX and they
255 * will be replaced with something random.
256 * @param mode std::ios_base::open_mode to open the file with
257 * @param buffer_size The size of any buffers that need to be allocated
258 * @param buffer_size The size of the putback buffer, relevant only for fstream
259 * @retval true if successful
261 bool open(const std::string& filename,
262 const std::string& tmpnametemplate,
263 std::ios_base::open_mode mode = std::ios_base::out,
264 int buffer_size = -1 , int pback_size = -1)
266 originalfilename=filename;
267 return tmpfstreamTempl<Device, Tr, Alloc>
268 ::open(tmpnametemplate,mode,buffer_size,pback_size);
274 * @brief Returns the name of the original file that will be replaced on @ref close.
275 * @retval name of the original file
277 std::string get_original_filename()
278 { return originalfilename; }
281 * @brief Sets the full sync mode
282 * @param do_full_sync if true the file data and metadata will be fully synced
285 void set_full_sync(bool do_full_sync=true)
286 { full_sync=do_full_sync; }
289 * @brief Read the current status of the full sync mode
290 * @retval true if the full sync mode is active
293 { return full_sync; }
296 * @brief On @ref close the target file is assigned these permissions
298 void set_filemode_on_close(mode_t mode)
299 { filemode_on_close=mode; }
302 * @brief Read the permissions that will be set on @ref close
303 * @retval permissions that will be set on @ref close
305 mode_t get_filemode_on_close()
306 { return filemode_on_close; }
309 * @brief Change file owner (chown) that will be set on @ref close
310 * @param user the new owner
311 * @param group the new group, if left empty the main group of the user is set
313 void set_owner_on_close(const I2n::User& user, const I2n::Group& group= I2n::Group())
320 * @brief Get file owner that will be set on @ref close
321 * @retval user that will be set on @ref close, an empty @ref User() means nothing will be set
323 I2n::User get_owner_on_close()
324 { return UserOnClose; }
327 * @brief Get file owner group that will be set on @ref close
328 * @retval group that will be set on @ref close
330 I2n::Group get_group_on_close()
331 { return GroupOnClose; }
334 * @brief Delete the file.
336 * calling unlink is a safe way to abort,
337 * the original file is not overwritten then
339 * @retval true if successful
342 { return tmpfstreamTempl<Device, Tr, Alloc>::unlink(); }
347 * @brief Not allowed to be called by users.
349 bool move(const std::string& targetpath, bool overwrite=false)
350 { return tmpfstreamTempl<Device, Tr, Alloc>::move(targetpath,overwrite); }
354 * @brief ofstream which first writes to a temp file and atomically replaces an old file on close.
356 typedef tmpfcopystreamTempl<bio::file_descriptor_sink> tmpofcopystream;
358 * @brief fstream which first writes to a temp file and atomically replaces an old file on close.
360 typedef tmpfcopystreamTempl<bio::file_descriptor> tmpfcopystream;