libcrn  3.9.5
A document image processing library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CRNIO.cpp
Go to the documentation of this file.
1 /* Copyright 2006-2014 Yann LEYDIER, INSA-Lyon, CoReNum
2  *
3  * This file is part of libcrn.
4  *
5  * libcrn is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * libcrn is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with libcrn. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * file: CRNIO.cpp
19  * \author Yann LEYDIER
20  */
21 
22 #include <CRNIO/CRNIO.h>
24 
25 #include <cstdio>
26 #include <sys/stat.h>
27 #include <fstream>
28 #include <CRNException.h>
29 #include <CRNIO/CRNFileShield.h>
31 #ifdef _MSC_VER
33 # include <direct.h> // for mkdir & rmdir
34 # define access _access
35 #else
36 # include <dirent.h>
37 # include <unistd.h>
38 #endif
39 #include <string.h>
40 #include <CRNi18n.h>
41 
42 using namespace crn;
43 
48 bool& IO::IsQuiet()
49 {
50  static bool quiet = false;
51  return quiet;
52 }
53 
59 {
60  static bool verbose = false;
61  return verbose;
62 }
63 
64 
68 std::shared_ptr<Messenger>& IO::CurrentMessenger()
69 {
70  static std::shared_ptr<Messenger> messenger(std::make_shared<ConsoleMessenger>());
71  return messenger;
72 }
73 
74 /*****************************************************************************/
80 void IO::Debug(const String &msg)
81 {
82  if (!IsQuiet())
83  {
84  CurrentMessenger()->PrintDebug(msg);
85  }
86 }
87 
88 /*****************************************************************************/
94 void IO::Warning(const String &msg)
95 {
96  if (!IsQuiet())
97  {
98  CurrentMessenger()->PrintWarning(msg);
99  }
100 }
101 
102 /*****************************************************************************/
108 void IO::Verbose(const String &msg)
109 {
110  if (IsVerbose() && !IsQuiet())
111  {
112  CurrentMessenger()->PrintVerbose(msg);
113  }
114 }
115 
116 /*****************************************************************************/
122 void IO::Error(const String &msg)
123 {
124  if (!IsQuiet())
125  {
126  CurrentMessenger()->PrintError(msg);
127  }
128 }
129 
137 void IO::Mkdir(const Path &name)
138 {
139  int res = 0;
140 #if defined(_MSC_VER)
141  Path winname(name);
142  winname.ToWindows();
143  res = _mkdir(winname.CStr());
144 #else
145  Path unixname(name);
146  unixname.ToUnix();
147  res = mkdir(unixname.CStr(), S_IRWXU|S_IRWXG|S_IRGRP|S_IXGRP); // user and group can write. other can read & execute
148 #endif
149  if (res)
150  throw ExceptionIO(_("Cannot create directory: ") + StringUTF8(name));
151 }
152 
161 bool IO::Access(const Path &name, int mode)
162 {
163  Path lname(name);
164  lname.ToLocal();
165  return access(lname.CStr(), mode) == 0 ? true : false;
166 }
167 
175 void IO::Rm(const Path &name)
176 {
177  bool ok;
178  Path lname(name);
179  lname.ToLocal();
180  ok = remove(lname.CStr()) == 0;
181  if (!ok)
182  throw ExceptionIO(_("Cannot remove: ") + StringUTF8(name));
183 
184 }
185 
193 void IO::ShieldRm(const Path &name)
194 {
195  std::lock_guard<std::mutex> lock(FileShield::GetMutex(name));
196  Rm(name);
197 }
198 
205 void IO::Rmdir(const Path &name)
206 {
207  Path lname(name);
208  lname.ToLocal();
209  DIR* d=opendir(lname.CStr());
210  if(!d)
211  {
212  throw ExceptionIO(_("Cannot open directory: ") + StringUTF8(lname));
213  }
214  AtScopeExit([d](){ closedir(d); });
215  struct dirent* diren=readdir(d);
216  while(diren)
217  {
218 
219  if((!strcmp(diren->d_name,"."))||(!strcmp(diren->d_name,"..")))
220  {
221  diren=readdir(d);
222  continue;
223  }
224  char fname[1024];
225  snprintf(fname,1024,"%s/%s", lname.CStr(), diren->d_name);
226  DIR *tempdir;
227  tempdir = opendir(fname);
228  if (tempdir)
229  {
230  closedir(tempdir); tempdir = nullptr;
231  strcat(fname,"/");
232  Rmdir(fname);
233  }
234  else
235  {
236  if(remove(fname) !=0)
237  {
238  throw ExceptionIO(_("Cannot remove file: ") + StringUTF8(fname));
239  }
240  }
241  diren=readdir(d);
242  }
243  int ret;
244 #ifdef _MSC_VER
245  ret = _rmdir(lname.CStr());
246 #else
247  ret = remove(lname.CStr());
248 #endif
249  if (ret)
250  throw ExceptionIO(_("Cannot remove directory: ") + StringUTF8(name));
251 
252 }
253 
263 void IO::Copy(const Path &src, const Path &dst)
264 {
265  if (src == dst)
266  throw ExceptionInvalidArgument(_("Cannot copy a file over itself."));
267 
268  std::ifstream s;
269  std::ofstream d;
270 
271  Path locsrc(src);
272  locsrc.ToLocal();
273  Path locdst(dst);
274  locdst.ToLocal();
275  s.open(locsrc.CStr(), std::ios::binary);
276  if (!s.is_open())
277  throw ExceptionInvalidArgument(_("Cannot open source file: ") + StringUTF8(locsrc));
278  d.open(locdst.CStr(), std::ios::binary);
279  if (!d.is_open())
280  throw ExceptionInvalidArgument(_("Cannot open destination file: ") + StringUTF8(locdst));
281 
282  d << s.rdbuf();
283  d.close();
284  s.close();
285 }
286 
295 void IO::ShieldCopy(const Path &src, const Path &dst)
296 {
297  if (src == dst) // check before creating the mutex to avoid dead lock!
298  throw ExceptionInvalidArgument(_("Cannot copy a file over itself."));
299  std::lock_guard<std::mutex> locks(FileShield::GetMutex(src));
300  std::lock_guard<std::mutex> lockd(FileShield::GetMutex(dst));
301  Copy(src, dst);
302 }
303 
312 {
313  Path lname(path);
314  lname.ToLocal();
315  DIR* d = opendir(lname.CStr());
316  if(!d)
317  {
318  throw ExceptionIO(StringUTF8(_("Cannot open directory: ")) + StringUTF8(lname));
319  }
320  struct dirent* diren=readdir(d);
321  while(diren)
322  {
323 
324  if((!strcmp(diren->d_name,"."))||(!strcmp(diren->d_name,"..")))
325  {
326  diren=readdir(d);
327  continue;
328  }
329  Path fname(lname);
330  fname /= diren->d_name;
331  DIR *tempdir;
332  tempdir = opendir(fname.CStr());
333  if (tempdir)
334  {
335  closedir(tempdir); tempdir = nullptr;
336  directories.push_back(fname);
337  }
338  else
339  {
340  files.push_back(fname);
341  }
342  diren = readdir(d);
343  }
344  closedir(d);
345 
346 }
347 
static void Warning(const String &msg)
Prints warning messages. Please use CRNWarning() macro instead.
Definition: CRNIO.cpp:94
static void ShieldRm(const Path &name)
Removes a file and protects it with mutex.
Definition: CRNIO.cpp:193
static void Debug(const String &msg)
Prints debug messages. Please use CRNDebug() macro instead.
Definition: CRNIO.cpp:80
static std::shared_ptr< Messenger > & CurrentMessenger()
Delegate that will print the messages.
Definition: CRNIO.cpp:68
#define _(String)
Definition: CRNi18n.h:51
char d_name[PATH_MAX]
Definition: dirent.hh:285
#define S_IXGRP
Definition: dirent.hh:135
Definition: dirent.hh:289
static void Copy(const Path &src, const Path &dst)
Copies a file.
Definition: CRNIO.cpp:263
static void Mkdir(const Path &name)
Creates a directory.
Definition: CRNIO.cpp:137
static std::mutex & GetMutex(const Path &fname)
Gets the mutex associated to a file.
A UTF32 character string class.
Definition: CRNString.h:61
static bool & IsQuiet()
If true, Debug, Warning, Verbose and Error don't print anything.
Definition: CRNIO.cpp:48
static bool & IsVerbose()
Controls whether CRNVerbose prints something or not.
Definition: CRNIO.cpp:58
static void Verbose(const String &msg)
Prints verbose messages. Please use CRNVerbose() macro instead.
Definition: CRNIO.cpp:108
const char * CStr() const noexcept
Conversion to UTF8 cstring.
#define S_IRGRP
Definition: dirent.hh:125
A convenience class for file paths.
Definition: CRNPath.h:39
Path & ToWindows()
Converts the path to Windows format.
Definition: CRNPath.cpp:410
static void Error(const String &msg)
Prints error messages. Please use CRNError() macro instead.
Definition: CRNIO.cpp:122
static void Rmdir(const Path &name)
Recursively removes a directory.
Definition: CRNIO.cpp:205
static void ShieldCopy(const Path &src, const Path &dst)
Copies a file and protects source and destination with mutex.
Definition: CRNIO.cpp:295
Path & ToLocal()
Converts the path to the local format.
Definition: CRNPath.cpp:534
static void Rm(const Path &name)
Removes a file.
Definition: CRNIO.cpp:175
static bool Access(const Path &name, int mode)
Checks rights on a file.
Definition: CRNIO.cpp:161
A character string class.
Definition: CRNStringUTF8.h:49
Directory(const Path &path)
Constructor.
Definition: CRNIO.cpp:311
I/O error.
Definition: CRNException.h:179
#define AtScopeExit(functor)
Executes a functor at the end of the scope.
Invalid argument error (e.g.: nullptr pointer)
Definition: CRNException.h:107