The Battle for Wesnoth  1.19.5+dev
fs_commit.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2016 - 2024
3  by Iris Morelle <shadowm2006@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 /**
17  * @file
18  * Atomic filesystem commit functions.
19  */
20 
21 #pragma once
22 
23 #include "filesystem.hpp"
24 
25 namespace filesystem
26 {
27 
28 /**
29  * Wrapper class that guarantees that file commit atomicity.
30  *
31  * It is possible for a signal or exception to cause a file write to be aborted
32  * in the middle of the process, leaving potentially inconsistent contents
33  * behind which may be read by the same or another application later and result
34  * in errors or further data loss.
35  *
36  * This wrapper prevents this by providing callers with an interface to request
37  * a write stream that will be actually associated to a temporary file. Once
38  * the caller is done with the file, it should call the commit() method to
39  * complete the process so that the temporary replaces the original in an
40  * atomic step.
41  *
42  * The rationale for using an explicit commit() method instead of the class
43  * destructor is that the destructor will also be invoked during exception
44  * handling, which could still cause the destination file to end up in an
45  * inconsistent state.
46  *
47  * Note that if the destructor is invoked before commit() is, the temporary
48  * file will be left behind. This is deliberate so as to provide a way for
49  * the user to look at the resulting file and optionally try to reconcile it
50  * against the original.
51  */
53 {
54 public:
55  /**
56  * Constructor.
57  *
58  * @throws filesystem::io_exception if the operation fails in some way.
59  */
60  atomic_commit(const std::string& filename);
61 
62  atomic_commit(const atomic_commit&) = delete;
64 
66 
67  /**
68  * Returns the write stream associated with the file.
69  *
70  * Before commit() is invoked, this refers to the temporary file; afterwards,
71  * to the destination.
72  */
74  {
75  return out_;
76  }
77 
78  /**
79  * Commits the new file contents to disk atomically.
80  *
81  * @throws filesystem::io_exception if the operation fails in some way.
82  */
83  void commit();
84 
85 private:
86  std::string temp_name_;
87  std::string dest_name_;
89 #ifndef _WIN32
90  int outfd_;
91 #else
92  void* handle_; // Actually a HANDLE
93 #endif
94 };
95 
96 }
Wrapper class that guarantees that file commit atomicity.
Definition: fs_commit.hpp:53
void commit()
Commits the new file contents to disk atomically.
Definition: fs_commit.cpp:206
scoped_ostream & ostream()
Returns the write stream associated with the file.
Definition: fs_commit.hpp:73
atomic_commit(const atomic_commit &)=delete
atomic_commit & operator=(const atomic_commit &)=delete
atomic_commit(const std::string &filename)
Constructor.
Definition: fs_commit.cpp:185
Declarations for File-IO.
std::unique_ptr< std::ostream > scoped_ostream
Definition: filesystem.hpp:54
std::string filename
Filename.