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 <nlohmann/json.hpp>
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
131 {
132 UnlockFile();
133 }
134
139 {
140 wxLogTrace( LCK, "Unlocking %s", m_lockFilename );
141
142 // Delete lock file only if the file was created in the constructor and if the file
143 // contains the correct user and host names.
145 {
147 wxRemoveFile( m_lockFilename );
148
149 m_fileCreated = false; // Reset the flag since file has been deleted manually
150 m_status = false;
151 m_errorMsg = wxEmptyString;
152 }
153 }
154
160 bool OverrideLock( bool aRemoveOnRelease = true )
161 {
162 wxLogTrace( LCK, "Overriding lock on %s", m_lockFilename );
163
164 if( !m_fileCreated )
165 {
166 try
167 {
168 wxFile file;
169 bool success = false;
170
171 {
172 wxLogNull suppressExpectedErrorMessages;
173 success = file.Open( m_lockFilename, wxFile::write );
174 }
175
176 if( success )
177 {
178 m_username = wxGetUserId();
179 m_hostname = wxGetHostName();
180 nlohmann::json j;
181 j["username"] = std::string( m_username.mb_str() );
182 j["hostname"] = std::string( m_hostname.mb_str() );
183 std::string lock_info = j.dump();
184 file.Write( lock_info );
185 file.Close();
186 m_fileCreated = true;
187 m_status = true;
188 m_removeOnRelease = aRemoveOnRelease;
189 m_errorMsg = wxEmptyString;
190 wxLogTrace( LCK, "Successfully overrode lock on %s", m_lockFilename );
191 return true;
192 }
193
194 return false;
195 }
196 catch( std::exception& e )
197 {
198 wxLogError( "Got exception trying to override lock on %s: %s",
199 m_lockFilename, e.what() );
200
201 return false;
202 }
203 }
204 else
205 {
206 wxLogTrace( LCK, "Upgraded lock on %s to delete on release", m_lockFilename );
207 m_removeOnRelease = aRemoveOnRelease;
208 }
209
210 return true;
211 }
212
214 {
215 return m_username == wxGetUserId() && m_hostname == wxGetHostName();
216 }
217
222 wxString GetUsername(){ return m_username; }
223
228 wxString GetHostname(){ return m_hostname; }
229
233 wxString GetErrorMsg(){ return m_errorMsg; }
234
235 bool Locked() const
236 {
237 return m_fileCreated;
238 }
239
240 bool Valid() const
241 {
242 return m_status;
243 }
244
245 explicit operator bool() const
246 {
247 return m_status;
248 }
249
250private:
253 wxString m_username;
254 wxString m_hostname;
258 wxString m_errorMsg;
259
261 {
262 wxFileName fileName( m_lockFilename );
263
264 if( !fileName.FileExists() )
265 {
266 wxLogTrace( LCK, "File does not exist: %s", m_lockFilename );
267 return false;
268 }
269
270 wxFile file;
271
272 try
273 {
274 if( file.Open( m_lockFilename, wxFile::read ) )
275 {
276 wxString lock_info;
277 file.ReadAll( &lock_info );
278 nlohmann::json j = nlohmann::json::parse( std::string( lock_info.mb_str() ) );
279
280 if( m_username == wxString( j["username"].get<std::string>() )
281 && m_hostname == wxString( j["hostname"].get<std::string>() ) )
282 {
283 wxLogTrace( LCK, "User and host match for lock %s", m_lockFilename );
284 return true;
285 }
286 }
287 }
288 catch( std::exception &e )
289 {
290 wxLogError( "Got exception trying to check user/host for lock on %s: %s",
292 e.what() );
293 }
294
295 wxLogTrace( LCK, "User and host DID NOT match for lock %s", m_lockFilename );
296 return false;
297 }
298};
299
300
301#endif // INCLUDE__LOCK_FILE_H_
bool m_removeOnRelease
Definition: lockfile.h:257
LOCKFILE(const wxString &filename, bool aRemoveOnRelease=true)
Definition: lockfile.h:45
bool m_fileCreated
Definition: lockfile.h:255
wxString m_errorMsg
Definition: lockfile.h:258
bool m_status
Definition: lockfile.h:256
wxString m_lockFilename
Definition: lockfile.h:252
bool OverrideLock(bool aRemoveOnRelease=true)
Force the lock, overwriting the data that existed already.
Definition: lockfile.h:160
bool Valid() const
Definition: lockfile.h:240
~LOCKFILE()
Definition: lockfile.h:130
wxString m_originalFile
Definition: lockfile.h:251
wxString m_hostname
Definition: lockfile.h:254
wxString GetUsername()
Definition: lockfile.h:222
wxString GetErrorMsg()
Definition: lockfile.h:233
wxString GetHostname()
Definition: lockfile.h:228
bool checkUserAndHost()
Definition: lockfile.h:260
bool Locked() const
Definition: lockfile.h:235
wxString m_username
Definition: lockfile.h:253
bool IsLockedByMe()
Definition: lockfile.h:213
void UnlockFile()
Unlock and remove the file from the filesystem as long as we still own it.
Definition: lockfile.h:138
#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.