KiCad PCB EDA Suite
Loading...
Searching...
No Matches
lockfile.h
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
29#ifndef INCLUDE__LOCK_FILE_H_
30#define INCLUDE__LOCK_FILE_H_
31
32#include <wx/wx.h>
33#include <wx/file.h>
34#include <wx/filefn.h>
35#include <wx/log.h>
36#include <wx/filename.h>
37#include <json_common.h>
39
40#define LCK "KICAD_LOCKING"
41
43{
44public:
45 LOCKFILE( const wxString &filename, bool aRemoveOnRelease = true ) :
46 m_originalFile( filename ), m_fileCreated( false ), m_status( false ),
47 m_removeOnRelease( aRemoveOnRelease ), m_errorMsg( "" )
48 {
49 if( filename.IsEmpty() )
50 return;
51
52 wxLogTrace( LCK, "Trying to lock %s", filename );
53 wxFileName fn( filename );
54 fn.SetName( FILEEXT::LockFilePrefix + fn.GetName() );
55 fn.SetExt( fn.GetExt() + '.' + FILEEXT::LockFileExtension );
56
57 if( !fn.IsDirWritable() )
58 {
59 wxLogTrace( LCK, "File is not writable: %s", filename );
60 m_status = true;
61 m_removeOnRelease = false;
62 return;
63 }
64
65 m_lockFilename = fn.GetFullPath();
66
67 wxFile file;
68 try
69 {
70 bool lock_success = false;
71 bool rw_success = false;
72
73 {
74 wxLogNull suppressExpectedErrorMessages;
75
76 lock_success = file.Open( m_lockFilename, wxFile::write_excl );
77
78 if( !lock_success )
79 rw_success = file.Open( m_lockFilename, wxFile::read );
80 }
81
82 if( lock_success )
83 {
84 // Lock file doesn't exist, create one
85 m_fileCreated = true;
86 m_status = true;
87 m_username = wxGetUserId();
88 m_hostname = wxGetHostName();
89 nlohmann::json j;
90 j["username"] = std::string( m_username.mb_str() );
91 j["hostname"] = std::string( m_hostname.mb_str() );
92 std::string lock_info = j.dump();
93 file.Write( lock_info );
94 file.Close();
95 wxLogTrace( LCK, "Locked %s", filename );
96 }
97 else if( rw_success )
98 {
99 // Lock file already exists, read the details
100 wxString lock_info;
101 file.ReadAll( &lock_info );
102 nlohmann::json j = nlohmann::json::parse( std::string( lock_info.mb_str() ) );
103 m_username = wxString( j["username"].get<std::string>() );
104 m_hostname = wxString( j["hostname"].get<std::string>() );
105 file.Close();
106 m_errorMsg = _( "Lock file already exists" );
107 wxLogTrace( LCK, "Existing Lock for %s", filename );
108 }
109 else
110 {
111 throw std::runtime_error( "Failed to open lock file" );
112 }
113 }
114 catch( std::exception& e )
115 {
116 wxLogError( "Got an error trying to lock %s: %s", filename, e.what() );
117
118 // Delete lock file if it was created above but we threw an exception somehow
119 if( m_fileCreated )
120 {
121 wxRemoveFile( m_lockFilename );
122 m_fileCreated = false; // Reset the flag since file has been deleted manually
123 }
124
125 m_errorMsg = _( "Failed to access lock file" );
126 m_status = false;
127 }
128 }
129
130 LOCKFILE( LOCKFILE&& other ) noexcept :
131 m_originalFile( std::move( other.m_originalFile ) ),
132 m_lockFilename( std::move( other.m_lockFilename ) ),
133 m_username( std::move( other.m_username ) ),
134 m_hostname( std::move( other.m_hostname ) ),
135 m_fileCreated( other.m_fileCreated ),
136 m_status( other.m_status ),
137 m_removeOnRelease( other.m_removeOnRelease ),
138 m_errorMsg( std::move( other.m_errorMsg ) )
139 {
140 // Disable unlock in the moved-from object
141 other.m_fileCreated = false;
142 }
143
145 {
146 UnlockFile();
147 }
148
153 {
154 wxLogTrace( LCK, "Unlocking %s", m_lockFilename );
155
156 // Delete lock file only if the file was created in the constructor and if the file
157 // contains the correct user and host names.
159 {
161 wxRemoveFile( m_lockFilename );
162
163 m_fileCreated = false; // Reset the flag since file has been deleted manually
164 m_status = false;
165 m_errorMsg = wxEmptyString;
166 }
167 }
168
174 bool OverrideLock( bool aRemoveOnRelease = true )
175 {
176 wxLogTrace( LCK, "Overriding lock on %s", m_lockFilename );
177
178 if( !m_fileCreated )
179 {
180 try
181 {
182 wxFile file;
183 bool success = false;
184
185 {
186 wxLogNull suppressExpectedErrorMessages;
187 success = file.Open( m_lockFilename, wxFile::write );
188 }
189
190 if( success )
191 {
192 m_username = wxGetUserId();
193 m_hostname = wxGetHostName();
194 nlohmann::json j;
195 j["username"] = std::string( m_username.mb_str() );
196 j["hostname"] = std::string( m_hostname.mb_str() );
197 std::string lock_info = j.dump();
198 file.Write( lock_info );
199 file.Close();
200 m_fileCreated = true;
201 m_status = true;
202 m_removeOnRelease = aRemoveOnRelease;
203 m_errorMsg = wxEmptyString;
204 wxLogTrace( LCK, "Successfully overrode lock on %s", m_lockFilename );
205 return true;
206 }
207
208 return false;
209 }
210 catch( std::exception& e )
211 {
212 wxLogError( "Got exception trying to override lock on %s: %s",
213 m_lockFilename, e.what() );
214
215 return false;
216 }
217 }
218 else
219 {
220 wxLogTrace( LCK, "Upgraded lock on %s to delete on release", m_lockFilename );
221 m_removeOnRelease = aRemoveOnRelease;
222 }
223
224 return true;
225 }
226
228 {
229 return m_username == wxGetUserId() && m_hostname == wxGetHostName();
230 }
231
236 wxString GetUsername(){ return m_username; }
237
242 wxString GetHostname(){ return m_hostname; }
243
247 wxString GetErrorMsg(){ return m_errorMsg; }
248
249 bool Locked() const
250 {
251 return m_fileCreated;
252 }
253
254 bool Valid() const
255 {
256 return m_status;
257 }
258
259 explicit operator bool() const
260 {
261 return m_status;
262 }
263
264private:
267 wxString m_username;
268 wxString m_hostname;
272 wxString m_errorMsg;
273
275 {
276 wxFileName fileName( m_lockFilename );
277
278 if( !fileName.FileExists() )
279 {
280 wxLogTrace( LCK, "File does not exist: %s", m_lockFilename );
281 return false;
282 }
283
284 wxFile file;
285
286 try
287 {
288 if( file.Open( m_lockFilename, wxFile::read ) )
289 {
290 wxString lock_info;
291 file.ReadAll( &lock_info );
292 nlohmann::json j = nlohmann::json::parse( std::string( lock_info.mb_str() ) );
293
294 if( m_username == wxString( j["username"].get<std::string>() )
295 && m_hostname == wxString( j["hostname"].get<std::string>() ) )
296 {
297 wxLogTrace( LCK, "User and host match for lock %s", m_lockFilename );
298 return true;
299 }
300 }
301 }
302 catch( std::exception &e )
303 {
304 wxLogError( "Got exception trying to check user/host for lock on %s: %s",
306 e.what() );
307 }
308
309 wxLogTrace( LCK, "User and host DID NOT match for lock %s", m_lockFilename );
310 return false;
311 }
312};
313
314
315#endif // INCLUDE__LOCK_FILE_H_
bool m_removeOnRelease
Definition: lockfile.h:271
LOCKFILE(const wxString &filename, bool aRemoveOnRelease=true)
Definition: lockfile.h:45
bool m_fileCreated
Definition: lockfile.h:269
LOCKFILE(LOCKFILE &&other) noexcept
Definition: lockfile.h:130
wxString m_errorMsg
Definition: lockfile.h:272
bool m_status
Definition: lockfile.h:270
wxString m_lockFilename
Definition: lockfile.h:266
bool OverrideLock(bool aRemoveOnRelease=true)
Force the lock, overwriting the data that existed already.
Definition: lockfile.h:174
bool Valid() const
Definition: lockfile.h:254
~LOCKFILE()
Definition: lockfile.h:144
wxString m_originalFile
Definition: lockfile.h:265
wxString m_hostname
Definition: lockfile.h:268
wxString GetUsername()
Definition: lockfile.h:236
wxString GetErrorMsg()
Definition: lockfile.h:247
wxString GetHostname()
Definition: lockfile.h:242
bool checkUserAndHost()
Definition: lockfile.h:274
bool Locked() const
Definition: lockfile.h:249
wxString m_username
Definition: lockfile.h:267
bool IsLockedByMe()
Definition: lockfile.h:227
void UnlockFile()
Unlock and remove the file from the filesystem as long as we still own it.
Definition: lockfile.h:152
#define _(s)
static const std::string LockFileExtension
static const std::string LockFilePrefix
#define LCK
Definition: lockfile.h:40
Definition of file extensions used in Kicad.