Audacity  3.0.3
FileConfig.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  FileConfig.cpp
6 
7  Leland Lucius
8 
9 **********************************************************************/
10 
11 
12 
13 #include <errno.h>
14 
15 #include <wx/defs.h>
16 #include <wx/app.h>
17 #include <wx/bmpbuttn.h>
18 #include <wx/button.h>
19 #include <wx/filefn.h>
20 #include <wx/fileconf.h>
21 #include <wx/sizer.h>
22 #include <wx/wfstream.h>
23 
24 #include "FileConfig.h"
25 
26 #include <cerrno> // for ENOENT
27 
28 #if !defined(F_OK)
29 #define F_OK 0x00
30 #endif
31 #if !defined(W_OK)
32 #define W_OK 0x02
33 #endif
34 #if !defined(R_OK)
35 #define R_OK 0x04
36 #endif
37 
38 FileConfig::FileConfig(const wxString& appName,
39  const wxString& vendorName,
40  const wxString& localFilename,
41  const wxString& globalFilename,
42  long style,
43  const wxMBConv& conv)
44 : wxConfigBase(appName, vendorName, localFilename, globalFilename, style),
45  mAppName(appName),
46  mVendorName(vendorName),
47  mLocalFilename(localFilename),
48  mGlobalFilename(globalFilename),
49  mStyle(style),
50  mConv(conv),
51  mDirty(false)
52 {
53 }
54 
56 {
57  while (true)
58  {
59  mConfig = std::make_unique<wxFileConfig>
61 
62  // Prevent wxFileConfig from attempting a Flush() during object deletion. This happens
63  // because we don't use the wxFileConfig::Flush() method and so the wxFileConfig dirty
64  // flag never gets reset. During deletion, the dirty flag is checked and a Flush()
65  // performed. This can (and probably will) create bogus temporary files.
66  mConfig->DisableAutoSave();
67 
68  bool canRead = false;
69  bool canWrite = false;
70  int fd;
71 
72  fd = wxOpen(mLocalFilename, O_RDONLY, S_IREAD);
73  if (fd != -1 || errno == ENOENT)
74  {
75  canRead = true;
76  if (fd != -1)
77  {
78  wxClose(fd);
79  }
80  }
81 
82  fd = wxOpen(mLocalFilename, O_WRONLY | O_CREAT, S_IWRITE);
83  if (fd != -1)
84  {
85  canWrite = true;
86  wxClose(fd);
87  }
88 
89  if (canRead && canWrite)
90  {
91  break;
92  }
93 
94  Warn();
95  }
96 }
97 
99 {
100  wxASSERT(mDirty == false);
101 }
102 
103 void FileConfig::SetPath(const wxString& strPath)
104 {
105  mConfig->SetPath(strPath);
106 }
107 
108 const wxString& FileConfig::GetPath() const
109 {
110  return mConfig->GetPath();
111 }
112 
113 bool FileConfig::GetFirstGroup(wxString& str, long& lIndex) const
114 {
115  return mConfig->GetFirstGroup(str, lIndex);
116 }
117 
118 bool FileConfig::GetNextGroup(wxString& str, long& lIndex) const
119 {
120  return mConfig->GetNextGroup(str, lIndex);
121 }
122 
123 bool FileConfig::GetFirstEntry(wxString& str, long& lIndex) const
124 {
125  return mConfig->GetFirstEntry(str, lIndex);
126 }
127 
128 bool FileConfig::GetNextEntry(wxString& str, long& lIndex) const
129 {
130  return mConfig->GetNextEntry(str, lIndex);
131 }
132 
133 size_t FileConfig::GetNumberOfEntries(bool bRecursive) const
134 {
135  return mConfig->GetNumberOfEntries(bRecursive);
136 }
137 
138 size_t FileConfig::GetNumberOfGroups(bool bRecursive) const
139 {
140  return mConfig->GetNumberOfGroups(bRecursive);
141 }
142 
143 bool FileConfig::HasGroup(const wxString& strName) const
144 {
145  return mConfig->HasGroup(strName);
146 }
147 
148 bool FileConfig::HasEntry(const wxString& strName) const
149 {
150  return mConfig->HasEntry(strName);
151 }
152 
153 bool FileConfig::Flush(bool WXUNUSED(bCurrentOnly))
154 {
155  if (!mDirty)
156  {
157  return true;
158  }
159 
160  while (true)
161  {
162  FilePath backup = mLocalFilename + ".bkp";
163 
164  if (!wxFileExists(backup) || (wxRemove(backup) == 0))
165  {
166  if (!wxFileExists(mLocalFilename) || (wxRename(mLocalFilename, backup) == 0))
167  {
168  wxFileOutputStream stream(mLocalFilename);
169  if (stream.IsOk())
170  {
171  if (mConfig->Save(stream))
172  {
173  stream.Sync();
174  if (stream.IsOk() && stream.Close())
175  {
176  if (!wxFileExists(backup) || (wxRemove(backup) == 0))
177  {
178  mDirty = false;
179  return true;
180  }
181  }
182  }
183  }
184 
185  if (wxFileExists(backup))
186  {
187  wxRemove(mLocalFilename);
188  wxRename(backup, mLocalFilename);
189  }
190  }
191  }
192 
193  Warn();
194  }
195 
196  return false;
197 }
198 
199 bool FileConfig::RenameEntry(const wxString& oldName, const wxString& newName)
200 {
201  auto res = mConfig->RenameEntry(oldName, newName);
202  if (res)
203  {
204  mDirty = true;
205  }
206  return res;
207 }
208 
209 bool FileConfig::RenameGroup(const wxString& oldName, const wxString& newName)
210 {
211  auto res = mConfig->RenameGroup(oldName, newName);
212  if (res)
213  {
214  mDirty = true;
215  }
216  return res;
217 }
218 
219 bool FileConfig::DeleteEntry(const wxString& key, bool bDeleteGroupIfEmpty)
220 {
221  auto res = mConfig->DeleteEntry(key, bDeleteGroupIfEmpty);
222  if (res)
223  {
224  mDirty = true;
225  }
226  return res;
227 }
228 
229 bool FileConfig::DeleteGroup(const wxString& key)
230 {
231  auto res = mConfig->DeleteGroup(key);
232  if (res)
233  {
234  mDirty = true;
235  }
236  return res;
237 }
238 
240 {
241  auto res = mConfig->DeleteAll();
242  if (res)
243  {
244  mDirty = true;
245  }
246  return res;
247 }
248 
249 bool FileConfig::DoReadString(const wxString& key, wxString *pStr) const
250 {
251  return mConfig->Read(key, pStr);
252 }
253 
254 bool FileConfig::DoReadLong(const wxString& key, long *pl) const
255 {
256  return mConfig->Read(key, pl);
257 }
258 
259 #if wxUSE_BASE64
260 bool FileConfig::DoReadBinary(const wxString& key, wxMemoryBuffer* buf) const
261 {
262  return mConfig->Read(key, buf);
263 }
264 #endif // wxUSE_BASE64
265 
266 bool FileConfig::DoWriteString(const wxString& key, const wxString& szValue)
267 {
268  bool res = mConfig->Write(key, szValue);
269  if (res)
270  {
271  mDirty = true;
272  }
273  return res;
274 }
275 
276 bool FileConfig::DoWriteLong(const wxString& key, long lValue)
277 {
278  bool res = mConfig->Write(key, lValue);
279  if (res)
280  {
281  mDirty = true;
282  }
283  return res;
284 }
285 
286 #if wxUSE_BASE64
287 bool FileConfig::DoWriteBinary(const wxString& key, const wxMemoryBuffer& buf)
288 {
289  bool res = mConfig->Write(key, buf);
290  if (res)
291  {
292  mDirty = true;
293  }
294  return res;
295 }
296 #endif // wxUSE_BASE64
FileConfig::RenameGroup
virtual bool RenameGroup(const wxString &oldName, const wxString &newName) wxOVERRIDE
Definition: FileConfig.cpp:209
FileConfig::SetPath
virtual void SetPath(const wxString &strPath) wxOVERRIDE
Definition: FileConfig.cpp:103
FilePath
wxString FilePath
Definition: Identifier.h:227
FileConfig::RenameEntry
virtual bool RenameEntry(const wxString &oldName, const wxString &newName) wxOVERRIDE
Definition: FileConfig.cpp:199
FileConfig::DoReadLong
virtual bool DoReadLong(const wxString &key, long *pl) const wxOVERRIDE
Definition: FileConfig.cpp:254
FileConfig::mDirty
bool mDirty
Definition: FileConfig.h:99
FileConfig::mAppName
const wxString mAppName
Definition: FileConfig.h:84
FileConfig::mVendorName
const wxString mVendorName
Definition: FileConfig.h:85
FileConfig::DoWriteLong
virtual bool DoWriteLong(const wxString &key, long lValue) wxOVERRIDE
Definition: FileConfig.cpp:276
FileConfig::HasEntry
virtual bool HasEntry(const wxString &strName) const wxOVERRIDE
Definition: FileConfig.cpp:148
FileConfig::GetNumberOfEntries
virtual size_t GetNumberOfEntries(bool bRecursive=false) const wxOVERRIDE
Definition: FileConfig.cpp:133
FileConfig.h
FileConfig::HasGroup
virtual bool HasGroup(const wxString &strName) const wxOVERRIDE
Definition: FileConfig.cpp:143
FileConfig::DeleteEntry
virtual bool DeleteEntry(const wxString &key, bool bDeleteGroupIfEmpty=true) wxOVERRIDE
Definition: FileConfig.cpp:219
FileConfig::DoReadString
virtual bool DoReadString(const wxString &key, wxString *pStr) const wxOVERRIDE
Definition: FileConfig.cpp:249
FileConfig::GetFirstGroup
virtual bool GetFirstGroup(wxString &str, long &lIndex) const wxOVERRIDE
Definition: FileConfig.cpp:113
FileConfig::mLocalFilename
const wxString mLocalFilename
Definition: FileConfig.h:86
FileConfig::GetFirstEntry
virtual bool GetFirstEntry(wxString &str, long &lIndex) const wxOVERRIDE
Definition: FileConfig.cpp:123
FileConfig::GetNextEntry
virtual bool GetNextEntry(wxString &str, long &lIndex) const wxOVERRIDE
Definition: FileConfig.cpp:128
FileConfig::GetNextGroup
virtual bool GetNextGroup(wxString &str, long &lIndex) const wxOVERRIDE
Definition: FileConfig.cpp:118
FileConfig::mConfig
std::unique_ptr< wxFileConfig > mConfig
Definition: FileConfig.h:91
FileConfig::mStyle
const long mStyle
Definition: FileConfig.h:88
FileConfig::Init
void Init()
Definition: FileConfig.cpp:55
FileConfig::mGlobalFilename
const wxString mGlobalFilename
Definition: FileConfig.h:87
FileConfig::DeleteGroup
virtual bool DeleteGroup(const wxString &key) wxOVERRIDE
Definition: FileConfig.cpp:229
FileConfig::Flush
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:153
key
static const AudacityProject::AttachedObjects::RegisteredFactory key
Definition: CommandManager.cpp:196
FileConfig::~FileConfig
virtual ~FileConfig()
Definition: FileConfig.cpp:98
FileConfig::GetNumberOfGroups
virtual size_t GetNumberOfGroups(bool bRecursive=false) const wxOVERRIDE
Definition: FileConfig.cpp:138
FileConfig::Warn
virtual void Warn()=0
Override to notify the user of error conditions involving writability of config files.
FileConfig::DeleteAll
virtual bool DeleteAll() wxOVERRIDE
Definition: FileConfig.cpp:239
FileConfig::FileConfig
FileConfig(const wxString &appName=wxEmptyString, const wxString &vendorName=wxEmptyString, const wxString &localFilename=wxEmptyString, const wxString &globalFilename=wxEmptyString, long style=wxCONFIG_USE_LOCAL_FILE|wxCONFIG_USE_GLOBAL_FILE, const wxMBConv &conv=wxConvAuto())
Definition: FileConfig.cpp:38
FileConfig::DoWriteString
virtual bool DoWriteString(const wxString &key, const wxString &szValue) wxOVERRIDE
Definition: FileConfig.cpp:266
FileConfig::mConv
const wxMBConv & mConv
Definition: FileConfig.h:89
FileConfig::GetPath
virtual const wxString & GetPath() const wxOVERRIDE
Definition: FileConfig.cpp:108