1 #ifndef CORELIB___NCBIFILE__HPP
2 #define CORELIB___NCBIFILE__HPP
3 
4 /*  $Id: ncbifile.hpp 606787 2020-04-27 16:15:35Z lavr $
5  * ===========================================================================
6  *
7  *                            PUBLIC DOMAIN NOTICE
8  *               National Center for Biotechnology Information
9  *
10  *  This software/database is a "United States Government Work" under the
11  *  terms of the United States Copyright Act.  It was written as part of
12  *  the author's official duties as a United States Government employee and
13  *  thus cannot be copyrighted.  This software/database is freely available
14  *  to the public for use. The National Library of Medicine and the U.S.
15  *  Government have not placed any restriction on its use or reproduction.
16  *
17  *  Although all reasonable efforts have been taken to ensure the accuracy
18  *  and reliability of the software and data, the NLM and the U.S.
19  *  Government do not and cannot warrant the performance or results that
20  *  may be obtained by using this software or data. The NLM and the U.S.
21  *  Government disclaim all warranties, express or implied, including
22  *  warranties of performance, merchantability or fitness for any particular
23  *  purpose.
24  *
25  *  Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Authors: Vladimir Ivanov, Denis Vakatov
30  *
31  *
32  */
33 
34 /// @file ncbifile.hpp
35 ///
36 /// Defines classes:
37 ///   CDirEntry, CFile, CDir, CSymLink,
38 ///   CMemoryFile,
39 ///   CFileUtil,
40 ///   CFileLock,
41 ///   CFileIO,
42 ///   CFileReader, CFileWriter, CFileReaderWriter,
43 ///   CFileException.
44 ///   Defines different file finding algorithms.
45 ///
46 /// @attention
47 ///   The parts of API that returns bool usually set CNcbiError (ncbierror.hpp).
48 ///   It can be used to get an error code and get a reason why some method
49 ///   returns FALSE. PLEASE dont't rely on a regular 'errno' value.
50 ///   It is still set there for some legacy code, but please avoid.
51 
52 
53 #include <corelib/ncbi_system.hpp>
54 #include <corelib/ncbi_mask.hpp>
55 #include <corelib/ncbi_param.hpp>
56 #include <corelib/ncbisys.hpp>
57 #include <corelib/reader_writer.hpp>
58 
59 #include <sys/types.h>
60 #if defined(HAVE_SYS_STAT_H)
61 #  include <sys/stat.h>
62 #endif
63 
64 #if defined(NCBI_OS_UNIX)
65 #  include <sys/param.h>
66 #endif
67 #if defined(NCBI_OS_MSWIN)
68 #  include <stdio.h>       // for FILENAME_MAX
69 #endif
70 
71 
72 /** @addtogroup Files
73  *
74  * @{
75  */
76 
77 BEGIN_NCBI_SCOPE
78 
79 
80 // Define missing types
81 
82 // mode_t
83 #if defined(NCBI_OS_MSWIN)
84     typedef unsigned int mode_t;
85 #endif
86 
87 // FILENAME_MAX
88 #if !defined(FILENAME_MAX)
89 #  if defined(MAXNAMELEN)
90 #    define FILENAME_MAX MAXNAMELEN    /* in <sys/param.h> on some systems */
91 #  elif defined(_MAX_FNAME)
92 #    define FILENAME_MAX _MAX_FNAME    /* MS Windows */
93 #  else
94 #    define FILENAME_MAX 256
95 #  endif
96 #endif
97 
98 // PATH_MAX
99 #if !defined(PATH_MAX)
100 #  if defined(MAXPATHLEN)
101 #    define PATH_MAX MAXPATHLEN        /* in <sys/param.h> on some systems */
102 #  elif defined(_MAX_PATH)
103 #    define PATH_MAX _MAX_PATH         /* MS Windows */
104 #  else
105 #    if FILENAME_MAX > 255
106 #      define PATH_MAX FILENAME_MAX
107 #    else
108 #      define PATH_MAX 1024
109 #    endif
110 #  endif
111 #endif
112 
113 // File handle
114 #if defined(NCBI_OS_MSWIN)
115     typedef HANDLE TFileHandle;
116     const   HANDLE kInvalidHandle = INVALID_HANDLE_VALUE;
117 #else
118     typedef int TFileHandle;
119     const   int kInvalidHandle = -1;
120 #endif
121 
122 // Forward declaration of struct containing OS-specific lock storage.
123 struct SLock;
124 
125 
126 /////////////////////////////////////////////////////////////////////////////
127 ///
128 /// CFileException --
129 ///
130 /// Define exceptions generated for file operations.
131 ///
132 /// CFileException inherits its basic functionality from CCoreException
133 /// and defines additional error codes for file operations.
134 
135 class NCBI_XNCBI_EXPORT CFileException : public CCoreException
136 {
137 public:
138     /// Error types that file operations can generate.
139     enum EErrCode {
140         eMemoryMap,
141         eRelativePath,
142         eNotExists,
143         eFileSystemInfo,
144         eFileIO,
145         eTmpFile
146     };
147 
148     /// Translate from an error code value to its string representation.
149     virtual const char* GetErrCodeString(void) const override;
150 
151     // Standard exception boilerplate code.
152     NCBI_EXCEPTION_DEFAULT(CFileException, CCoreException);
153 };
154 
155 
156 // File exception with system errno-based message
157 
158 #if defined(NCBI_OS_MSWIN)
159     typedef CErrnoTemplException_Win<CFileException> CFileErrnoException_Base;
160 #else
161     typedef CErrnoTemplException<CFileException> CFileErrnoException_Base;
162 #endif
163 
164 class NCBI_XNCBI_EXPORT CFileErrnoException : public CFileErrnoException_Base
165 {
166 public:
167     /// Error types
168     enum EErrCode {
169         eFile,
170         eFileSystemInfo,
171         eFileLock,
172         eFileIO
173     };
174     /// Translate from an error code value to its string representation.
175     virtual const char* GetErrCodeString(void) const override;
176     // Standard exception boilerplate code.
177     NCBI_EXCEPTION_DEFAULT(CFileErrnoException, CFileErrnoException_Base);
178 };
179 
180 
181 /////////////////////////////////////////////////////////////////////////////
182 ///
183 /// Global settings related to the file API.
184 ///
185 ///
186 
187 class NCBI_XNCBI_EXPORT CFileAPI
188 {
189 public:
190     /// Enable or disable logging of errors from the File API classes.
191     ///
192     /// Have the same effect as FileAPILogging global parameter:
193     /// Registry file:
194     ///     [NCBI]
195     ///     FileAPILogging = true/false
196     /// Environment variable:
197     ///     NCBI_CONFIG__FILEAPILOGGING
198     ///
199     /// @param on_off_default
200     ///   Switch between logging enabled (eOn), disabled (eOff),
201     ///   or reset to the default state (currently disabled).
202     static void SetLogging(ESwitch on_off_default);
203 
204     /// Enable or disable honoring umask settings on Unix for
205     /// newly created files/directories in the File API.
206     ///
207     /// Have the same effect as FileAPIHonorUmask global parameter:
208     /// Registry file:
209     ///     [NCBI]
210     ///     FileAPIHonorUmask = true/false
211     /// Environment variable:
212     ///     NCBI_CONFIG__FILEAPIHONORUMASK
213     ///
214     /// @param on_off_default
215     ///   When set to eOn, allows read-only files to be deleted.
216     ///   Otherwise, an attempt to delete a read-only files will
217     ///   return an error (EACCES).
218     /// @note
219     ///   Unix only. On Windows umask affect only CRT function,
220     ///   the part of API that use Windows API directly just ignore umask setting.
221     static void SetHonorUmask(ESwitch on_off_default);
222 
223     /// Specify whether read-only files can be deleted via
224     /// CDirEntry::Remove() on Windows.
225     ///
226     /// Have the same effect as DeleteReadOnlyFiles global parameter:
227     /// Registry file:
228     ///     [NCBI]
229     ///     DeleteReadOnlyFiles = true/false
230     /// Environment variable:
231     ///     NCBI_CONFIG__DELETEREADONLYFILES
232     ///
233     /// @param on_off_default
234     ///   When set to eOn, allows read-only files to be deleted.
235     ///   Otherwise, an attempt to delete a read-only files will
236     ///   return an error (EACCES).
237     /// @note
238     ///   Windows only.
239     static void SetDeleteReadOnlyFiles(ESwitch on_off_default);
240 };
241 
242 
243 /////////////////////////////////////////////////////////////////////////////
244 ///
245 /// CDirEntry --
246 ///
247 /// Base class to work with files and directories.
248 ///
249 /// Models a directory entry in the file system.  Assumes that
250 /// the path argument has the following form, where any or
251 /// all components may be missing:
252 ///
253 /// <dir><base><ext>
254 ///
255 /// - dir  - file path             ("/usr/local/bin/"  or  "c:\\windows\\")
256 /// - base - file name without ext ("autoexec")
257 /// - ext  - file extension        (".bat" - whatever goes after a last dot)
258 ///
259 /// Supported filename formats:  MS DOS/Windows, UNIX.
260 
261 class NCBI_XNCBI_EXPORT CDirEntry
262 {
263 public:
264     /// Default constructor.
265     CDirEntry(void);
266 
267     /// Constructor using specified path string.
268     CDirEntry(const string& path);
269 
270     /// Copy constructor.
271     CDirEntry(const CDirEntry& other);
272 
273     /// Destructor.
274     virtual ~CDirEntry(void);
275 
276     /// Get entry path.
277     const string& GetPath(void) const;
278 
279     /// Reset path string.
280     void Reset(const string& path);
281 
282     /// Assignment operator.
283     CDirEntry& operator= (const CDirEntry& other);
284 
285 
286     //
287     // Path processing.
288     //
289 
290     /// Split a path string into its basic components.
291     ///
292     /// @param path
293     ///   Path string to be split.
294     /// @param dir
295     ///   The directory component that is returned. This will always have
296     ///   a terminating path separator (example: "/usr/local/").
297     /// @param base
298     ///   File name with both directory (if any) and extension (if any)
299     ///   parts stripped.
300     /// @param ext
301     ///   The extension component (if any), always has a leading dot
302     ///   (example: ".bat").
303     static void SplitPath(const string& path,
304                           string* dir = 0, string* base = 0, string* ext = 0);
305 
306     /// Split a path string into its basic components.
307     ///
308     /// Note that the arguments are not OS-specific.
309     /// @param path
310     ///   Path string to be split.
311     /// @param disk
312     ///   Disk name if present like "C:" (MS Windows paths only),
313     ///   otherwise empty string.
314     /// @param dir
315     ///   The directory component that is returned. This will always have
316     ///   a terminating path separator (example: "/usr/local/").
317     /// @param base
318     ///   File name with both directory (if any) and extension (if any)
319     ///   parts stripped.
320     /// @param ext
321     ///   The extension component (if any), always has a leading dot
322     ///   (example: ".bat").
323     static void SplitPathEx(const string& path,
324                             string* disk = 0, string* dir = 0,
325                             string* base = 0, string* ext = 0);
326 
327     /// What GetDir() should return if the dir entry does not contain path.
328     /// @sa GetDir
329     enum EIfEmptyPath {
330         eIfEmptyPath_Empty,    ///< Return empty string
331         eIfEmptyPath_Current   ///< Return current dir like "./"
332     };
333 
334     /// Get the directory component for this directory entry.
335     //
336     /// @param path
337     ///   Flag to control returning value for paths that don't have
338     ///   directory name.
339     /// @return
340     ///   The directory component for this directory entry, or empty string.
341     /// @sa EGetDirMode, SplitPath
342     string GetDir(EIfEmptyPath mode = eIfEmptyPath_Current) const;
343 
344     /// Get the base entry name with extension (if any).
345     string GetName(void) const;
346 
347     /// Get the base entry name without extension.
348     string GetBase(void) const;
349 
350     /// Get extension name.
351     string GetExt (void) const;
352 
353     /// Assemble a path from basic components.
354     ///
355     /// @param dir
356     ///   The directory component to make the path string. This will always
357     ///   have a terminating path separator (example: "/usr/local/").
358     /// @param base
359     ///   The base name of the file component that is used to make up the path.
360     /// @param ext
361     ///   The extension component. This will always be added with a leading dot
362     ///   (input of either "bat" or ".bat" gets added to the path as ".bat").
363     /// @return
364     ///   Path built from the components.
365     static string MakePath(const string& dir  = kEmptyStr,
366                            const string& base = kEmptyStr,
367                            const string& ext  = kEmptyStr);
368 
369     /// Get path separator symbol specific for the current platform.
370     static char GetPathSeparator(void);
371 
372     /// Check whether a character "c" is a path separator symbol
373     /// specific for the current platform.
374     static bool IsPathSeparator(const char c);
375 
376     /// Add trailing path separator, if needed.
377     static string AddTrailingPathSeparator(const string& path);
378 
379     /// Delete trailing path separator, if any.
380     static string DeleteTrailingPathSeparator(const string& path);
381 
382     /// Convert "path" on any OS to the current OS-dependent path.
383     /// Converts related paths, normalizes absolute.
384     /// @sa
385     ///   IsAbsolutePath, NormalizePath
386     static string ConvertToOSPath(const string& path);
387 
388     /// Check if a "path" is absolute for the current OS.
389     ///
390     /// Note that the "path" must be for the current OS.
391     static bool IsAbsolutePath(const string& path);
392 
393     /// Check if the "path" is absolute for any OS.
394     ///
395     /// Note that the "path" can be for any OS (MSWIN, UNIX).
396     static bool IsAbsolutePathEx(const string& path);
397 
398     /// Given a path, gets the closest parent directory which actually exists.
399     ///
400     /// @param path
401     ///   Some path to a directory entry.
402     /// @return
403     ///   The closest parent directory which actually exists.
404     /// @throws
405     ///   CFileException if no existing nearest parent directory was found.
406     /// @note
407     ///   For relative not-existent path it always returns ".".
408     ///   To avoid this, you can always use absolute path for "path":
409     ///      CDirEntry::GetNearestExistingParentDir(CDirEntry::CreateAbsolutePath(path))
410     /// @note
411     ///   On Unix, a non-empty path should always have some existing parent,
412     ///   because '/' is a common path that should always exist.
413     /// @sa
414     ///   GetDir, CreateAbsolutePath
415     static string GetNearestExistingParentDir(const string& path);
416 
417     /// Create a relative path between two points in the file
418     /// system specified by their absolute paths.
419     ///
420     /// @param path_from
421     ///   Absolute path that defines start of the relative path.
422     /// @param path_to
423     ///   Absolute path that defines endpoint of the relative path.
424     /// @return
425     ///   Relative path (empty string if the paths are the same).
426     ///   Throw CFileException on error (e.g. if any of the paths is not
427     ///   absolute, or if it is impossible to create a relative path, such
428     ///   as in case of different disks on MS-Windows).
429     static string CreateRelativePath(const string& path_from,
430                                      const string& path_to);
431 
432     /// How to interpret relative paths.
433     /// @sa CreateAbsolutePath
434     enum ERelativeToWhat {
435         /// Relative to the current working directory.
436         eRelativeToCwd,
437         /// Relative to the executable's location.  If the executable was
438         /// invoked via a symlink, search the directory containing the symlink
439         /// before the directory (if different) containing the actual binary.
440         eRelativeToExe
441     };
442 
443     /// Get an absolute path from some, possibly relative, path.
444     ///
445     /// @param path
446     ///   Path to resolve, in native syntax; returned as is if absolute.
447     /// @param rtw
448     ///   Starting point for relative path resolution -- the current directory
449     ///   by default, but looking alongside the executable is also an option.
450     /// @return
451     ///   Corresponding absolute path.  May be the original string (if already
452     ///   absolute) or the starting point indicated by rtw (if the input was
453     ///   empty or ".").
454     /// @sa ERelativeToWhat, CreateAbsolutePath
455     static string CreateAbsolutePath(const string& path,
456                                      ERelativeToWhat rtw = eRelativeToCwd);
457 
458     /// Get an absolute path from some, possibly relative, path.
459     ///
460     /// @param path
461     ///   Path to resolve, in native syntax; returned as is if absolute.
462     /// @param rtw
463     ///   Starting point for relative path resolution.  Used as a base path
464     ///   for "path" if the latter has a relative form.  Must be an absolute.
465     /// @return
466     ///   Corresponding absolute path.  May be the original string (if already
467     ///   absolute) or concatenation of rtw and path.
468     /// @sa CreateAbsolutePath
469     static string CreateAbsolutePath(const string& path, const string& rtw);
470 
471     /// Concatenate two parts of the path for the current OS.
472     ///
473     /// Note that the arguments must be OS-specific.
474     /// @param first
475     ///   First part of the path which can be either absolute or relative.
476     /// @param second
477     ///   Second part of the path must always be relative.
478     /// @return
479     ///   The concatenated path.
480     static string ConcatPath(const string& first, const string& second);
481 
482     /// Concatenate two parts of the path for any OS.
483     ///
484     /// Note that the arguments are not OS-specific.
485     /// @param first
486     ///   First part of the path which can be either absolute or relative.
487     /// @param second
488     ///   Second part of the path must always be relative.
489     /// @return
490     ///   The concatenated path.
491     static string ConcatPathEx(const string& first, const string& second);
492 
493     /// Normalize a path.
494     ///
495     /// Remove from an input "path" all redundancy, and if possible,
496     /// convert it to more simple form for the current OS.
497     /// Note that "path" must be OS-specific.
498     /// @param follow_links
499     ///   Whether to follow symlinks (shortcuts, aliases)
500     static string NormalizePath(const string& path,
501                                 EFollowLinks  follow_links = eIgnoreLinks);
502 
503 
504     //
505     // Checks & manipulations.
506     //
507 
508     /// Match a "name" against a simple filename "mask".
509     static bool MatchesMask(const string& name, const string& mask,
510                             NStr::ECase use_case = NStr::eCase);
511 
512     /// Match a "name" against a set of "masks"
513     /// Note that any name match to empty vector of masks.
514     static bool MatchesMask(const string& name, const vector<string>& masks,
515                             NStr::ECase use_case = NStr::eCase);
516 
517     /// Match a "name" against a set of "masks"
518     /// Note that any name match to empty set of masks.
519     static bool MatchesMask(const string& name, const CMask& mask,
520                             NStr::ECase use_case = NStr::eCase);
521 
522     /// Check the entry existence.
523     virtual bool Exists(void) const;
524 
525     /// Copy flags.
526     /// Note that updating modification time for directory depends on the OS.
527     /// Normally it gets updated when a new directory entry is added/removed.
528     /// On the other hand, changing contents of files in that directory
529     /// doesn't usually affect the directory modification time.
530     enum ECopyFlags {
531         /// The following flags define what to do when the
532         /// destination entry already exists:
533         /// - Overwrite the destination
534         fCF_Overwrite       = (1 << 1),
535         /// - Update older entries only (compare modification times)
536         fCF_Update          = (1 << 2) | fCF_Overwrite,
537         /// - Backup destination (renames to ".bak" by default)
538         fCF_Backup          = (1 << 3) | fCF_Overwrite,
539 
540         /// Safe copy (copy to temporary object and rename).
541         /// Be aware if used together with fCF_TopDirOnly for copying directories:
542         ///    if specified -- full copy of the source directory will be created,
543         ///        after successful copying it replaces the destination.
544         ///    if not specified -- existing destination directory will be "upgraded"
545         ///        with files from source directory, safe copying will be applied
546         ///        for every copied entry inside.
547         fCF_Safe            = (1 << 4) | fCF_Overwrite,
548 
549         /// All above flags can be applied to the top directory only
550         /// (not for every file therein), to process the directory
551         /// as a single entity for overwriting, updating or backing up.
552         fCF_TopDirOnly      = (1 << 6),
553 
554         /// If destination entry exists, it must have the same type as source.
555         fCF_EqualTypes      = (1 << 7),
556         /// Copy entries following their sym.links, not the links themselves.
557         fCF_FollowLinks     = (1 << 8),
558         fCF_Verify          = (1 << 9),   ///< Verify data after copying
559         fCF_PreserveOwner   = (1 << 10),  ///< Preserve owner/group
560         fCF_PreservePerm    = (1 << 11),  ///< Preserve permissions/attributes
561         fCF_PreserveTime    = (1 << 12),  ///< Preserve date/times
562         fCF_PreserveAll     = fCF_PreserveOwner | fCF_PreservePerm | fCF_PreserveTime,
563         fCF_Recursive       = (1 << 14),  ///< Copy recursively (for dir only)
564         /// Skip all entries for which we don't have Copy() method.
565         fCF_SkipUnsupported = (1 << 15),
566         /// Default flags.
567         fCF_Default         = fCF_Recursive | fCF_FollowLinks
568     };
569     typedef unsigned int TCopyFlags;    ///< Binary OR of "ECopyFlags"
570 
571     /// Copy the entry to a location specified by "new_path".
572     ///
573     /// The Copy() method must be overloaded in derived classes
574     /// that support copy operation.
575     /// @param new_path
576     ///   New path/name of an entry.
577     /// @param flags
578     ///   Flags specifying how to copy the entry.
579     /// @param buf_size
580     ///   Buffer size to use while copying the file contents.
581     ///   Zero value means using default buffer size. This parameter
582     ///   have advisory status and can be override, depends from OS
583     ///   and size of copied file.
584     /// @return
585     ///   TRUE if the operation was completed successfully; FALSE, otherwise.
586     /// @sa
587     ///   CFile::Copy, CDir::Copy, CLink::Copy, CopyToDir
588     virtual bool Copy(const string& new_path, TCopyFlags flags = fCF_Default,
589                       size_t buf_size = 0) const;
590 
591     /// Copy the entry to a specified directory.
592     ///
593     /// The target entry name will be "dir/entry".
594     /// @param dir
595     ///   Directory name to copy into.
596     /// @param flags
597     ///   Flags specifying how to copy the entry.
598     /// @param buf_size
599     ///   Buffer size to use while copying the file contents.
600     ///   Zero value means using default buffer size.
601     /// @return
602     ///   TRUE if the operation was completed successfully; FALSE, otherwise.
603     /// @sa
604     ///   Copy
605     bool CopyToDir(const string& dir, TCopyFlags flags = fCF_Default,
606                    size_t buf_size = 0) const;
607 
608     /// Rename flags
609     enum ERenameFlags {
610         /// Remove destination if it exists.
611         fRF_Overwrite   = (1 << 1),
612         /// Update older entries only (compare modification times).
613         fRF_Update      = (1 << 2) | fCF_Overwrite,
614         /// Backup destination if it exists before renaming.
615         fRF_Backup      = (1 << 3) | fCF_Overwrite,
616         /// If destination entry exists, it must have the same type as source.
617         fRF_EqualTypes  = (1 << 4),
618         /// Rename entries following sym.links, not the links themselves.
619         fRF_FollowLinks = (1 << 5),
620         /// Default flags
621         fRF_Default     = 0
622     };
623     typedef unsigned int TRenameFlags;   ///< Binary OR of "ERenameFlags"
624 
625     /// Rename entry.
626     ///
627     /// @param new_path
628     ///   New path/name of an entry.
629     /// @param flags
630     ///   Flags specifying how to rename the entry.
631     /// @return
632     ///   TRUE if the operation was completed successfully; FALSE, otherwise.
633     ///   NOTE that if flag fRF_Update is set, the function returns TRUE and
634     ///   just removes the current entry in case when destination entry
635     ///   exists and has its modification time newer than the current entry.
636     /// @sa
637     ///   ERenameFlags, Copy
638     bool Rename(const string& new_path, TRenameFlags flags = fRF_Default);
639 
640     /// Move the entry to a specified directory.
641     ///
642     /// The target entry name will be "dir/entry".
643     /// @param dir
644     ///   Directory name to move into.
645     /// @param flags
646     ///   Flags specifying how to move the entry.
647     /// @return
648     ///   TRUE if the operation was completed successfully; FALSE, otherwise.
649     /// @sa
650     ///   CopyToDir, Rename, Copy
651     bool MoveToDir(const string& dir, TCopyFlags flags = fRF_Default);
652 
653     /// Get backup suffix.
654     ///
655     /// @sa
656     ///   SetBackupSuffix, Backup, Rename, Copy
657     static const char* GetBackupSuffix(void);
658 
659     /// Set backup suffix.
660     ///
661     /// @sa
662     ///   GetBackupSuffix, Backup, Rename, Copy
663     static void SetBackupSuffix(const char* suffix);
664 
665     /// Backup modes
666     enum EBackupMode {
667         eBackup_Copy    = (1 << 1),     ///< Copy entry
668         eBackup_Rename  = (1 << 2),     ///< Rename entry
669         eBackup_Default = eBackup_Copy  ///< Default mode
670     };
671 
672     /// Backup an entry.
673     ///
674     /// Create a copy of the current entry with the same name and an extension
675     /// specified by SetBackupSuffix(). By default this extension is ".bak".
676     /// Backups can be automatically created in 'copy' or 'rename' operations.
677     /// If an entry with the name of the backup already exists, then it will
678     /// be deleted (if possible). The current entry name components are
679     /// changed to reflect the backed up copy.
680     /// @param suffix
681     ///   Extension to add to backup entry. If empty, GetBackupSuffix() is be used.
682     /// @param mode
683     ///   Backup mode. Specifies what to do, copy the entry or just rename it.
684     /// @param copyflags
685     ///   Flags to copy the entry. Used only if mode is eBackup_Copy,
686     /// @param copybufsize
687     ///   Buffer size to use while copying the file contents.
688     ///   Used only if 'mode' is eBackup_Copy,
689     /// @return
690     ///   TRUE if backup created successfully; FALSE otherwise.
691     /// @sa
692     ///   EBackupMode
693     bool Backup(const string& suffix      = kEmptyStr,
694                 EBackupMode   mode        = eBackup_Default,
695                 TCopyFlags    copyflags   = fCF_Default,
696                 size_t        copybufsize = 0);
697 
698 
699     /// Entries processing flags.
700     /// @note
701     ///   Different methods use different sets of flags,
702     ///   and ignore all other. Refer to method descriptions for details.
703     enum EProcessingFlags {
704 
705         /// Current entry only
706         fEntry         = (1 << 0),
707 
708         // --- directory processing flags ---------------------------
709 
710         fDir_Self      = fEntry,    ///< Top directory entry
711         fDir_Files     = (1 << 1),  ///< Non-directory entries
712         fDir_Subdirs   = (1 << 2),  ///< Subdirectory entries (non recursive)
713         fDir_Recursive = (1 << 3),  ///< Add a recursion
714 
715         /// Mask to check what should be processed in a directory
716         fDir_All = fDir_Self + fDir_Files + fDir_Subdirs,
717 
718         // --- additional flags -------------------------------------
719 
720         fIgnoreMissing   = (1 << 4),
721 
722         // --- directory processing modes ---------------------------
723         // "Enums", retained for backward compatibility.
724 
725         /// Directory entry only, no other files or subdirectories
726         eOnlyEmpty    = fDir_Self,
727         eEntryOnly    = fDir_Self,
728 
729         /// All files in the top directory only, no subdirectories
730         /// and any files in them.
731         eTopDirOnly   = fDir_Self | fDir_Files,
732 
733         /// All files and subdirectories in the top directory,
734         /// but no files in subdirectories
735         eNonRecursive = fDir_All,
736 
737         /// Process all files and subdirectories recursively.
738         eRecursive    = fDir_All | fDir_Recursive,
739 
740         /// Same as eRecursive, but do not report an error for
741         /// disappeared entries (e.g. if the same directory is being
742         /// removed in a parallel thread for example).
743         eRecursiveIgnoreMissing = eRecursive | fIgnoreMissing
744     };
745     typedef unsigned int TProcessingFlags;  ///< Binary OR of "EProcessingFlags"
746 
747     /// Flags based on TProcessingFlags
748     typedef TProcessingFlags TRemoveFlags;
749     typedef TProcessingFlags TSetModeFlags;
750 
751     /// Directory remove mode.
752     /// @deprecated  Use TRemoveFlags instead
753     NCBI_DEPRECATED typedef TRemoveFlags EDirRemoveMode;
754 
755 
756     /// Remove a directory entry.
757     ///
758     /// @flags
759     ///   Entry processing flags.
760     ///   See EProcessingFlags and CDir::Remove() for details.
761     /// @sa
762     ///   CDir::Remove, EProcessingFlags
763     virtual bool Remove(TRemoveFlags flags = eRecursive) const;
764 
765     /// Remove a directory entry.
766     ///
767     /// Same as Remove(), but removes current entry only.
768     /// Don't process entries inside directories.
769     ///
770     /// @sa Remove
771     virtual bool RemoveEntry(TRemoveFlags flags = eEntryOnly) const;
772 
773     /// Directory entry type.
774     enum EType {
775         eFile = 0,                ///< Regular file
776         eDir,                     ///< Directory
777         ePipe,                    ///< Pipe
778         eLink,                    ///< Symbolic link     (UNIX only)
779         eSymLink = eLink,         ///< Symbolic link     (UNIX only)
780         eSocket,                  ///< Socket            (UNIX only)
781         eDoor,                    ///< Door              (UNIX only)
782         eBlockSpecial,            ///< Block special     (UNIX only)
783         eCharSpecial,             ///< Character special
784         //
785         eUnknown                  ///< Unknown type
786     };
787 
788     /// Construct a directory entry object of a specified type.
789     ///
790     /// An object of specified type will be constructed in memory only,
791     /// file system will not be modified.
792     /// @param type
793     ///   Define a type of the object to create.
794     /// @return
795     ///   A pointer to newly created entry. If a class for specified type
796     ///   is not defined, generic CDirEntry will be returned. Do not forget
797     ///   to delete the returned pointer when it is no longer used.
798     /// @sa
799     ///   CFile, CDir, CSymLink
800     static CDirEntry* CreateObject(EType type, const string& path = kEmptyStr);
801 
802     /// Get a type of constructed object.
803     ///
804     /// @return
805     ///   Return one of the values in EType. Return "eUnknown" for CDirEntry.
806     /// @sa
807     ///   CreateObject, GetType
GetObjectType(void) const808     virtual EType GetObjectType(void) const { return eUnknown; };
809 
810     /// Alternate stat structure for use instead of the standard struct stat.
811     /// The alternate stat can have useful, but non-posix fields, which
812     /// are usually highly platform-dependent, and named differently
813     /// in the underlying data structures on different systems.
814     struct SStat {
815         TNcbiSys_stat orig;  ///< Original stat structure
816         // Nanoseconds for dir entry times (if available)
817         long  mtime_nsec;  ///< Nanoseconds for modification time
818         long  ctime_nsec;  ///< Nanoseconds for creation time
819         long  atime_nsec;  ///< Nanoseconds for last access time
820     };
821 
822     /// Get status information on a dir entry.
823     ///
824     /// By default have the same behavior as UNIX's lstat().
825     /// @param buffer
826     ///   Pointer to structure that stores results.
827     /// @param follow_links
828     ///   Whether to follow symlinks (shortcuts, aliases).
829     /// @return
830     ///   Return TRUE if the file-status information is obtained,
831     ///   FALSE otherwise (errno may be set).
832     bool Stat(struct SStat *buffer,
833               EFollowLinks follow_links = eIgnoreLinks) const;
834 
835     /// Get a type of a directory entry.
836     ///
837     /// @return
838     ///   Return one of the values in EType. If the directory entry does
839     ///   not exist, return "eUnknown".
840     /// @sa
841     ///   IsFile, IsDir, IsLink
842     EType GetType(EFollowLinks follow = eIgnoreLinks) const;
843 
844     /// Get a type of a directory entry by status information.
845     ///
846     /// @param st
847     ///   Status file information.
848     /// @return
849     ///   Return one of the values in EType. If the directory entry does
850     ///   not exist, return "eUnknown".
851     /// @sa
852     ///   IsFile, IsDir, IsLink
853     static EType GetType(const TNcbiSys_stat& st);
854 
855     /// Check whether a directory entry is a file.
856     /// @sa
857     ///   GetType
858     bool IsFile(EFollowLinks follow = eFollowLinks) const;
859 
860     /// Check whether a directory entry is a directory.
861     /// @sa
862     ///   GetType
863     bool IsDir(EFollowLinks follow = eFollowLinks) const;
864 
865     /// Check whether a directory entry is a symbolic link (alias).
866     /// @sa
867     ///   GetType
868     bool IsLink(void) const;
869 
870     /// Get an entry name that a link points to.
871     ///
872     /// @return
873     ///   The real entry name that the link points to. Return an empty
874     ///   string if the entry is not a link, or cannot be dereferenced.
875     ///   The dereferenced name can be another symbolic link.
876     /// @sa
877     ///   GetType, IsLink, DereferenceLink
878     string LookupLink(void) const;
879 
880     /// Dereference a link.
881     ///
882     /// If the current entry is a symbolic link, then dereference it
883     /// recursively until it is no further a link (but a file, directory,
884     /// etc, or does not exist). Replace the entry path string with
885     /// the dereferenced path.
886     /// @note
887     ///   This method dereference only last component of the path.
888     ///   To dereference all path components use DereferencePath() method.
889     /// @sa
890     ///   DereferencePath, IsLink, LookupLink, NormalizePath
891     void DereferenceLink(ENormalizePath normalize = eNormalizePath);
892 
893     /// Dereference a path.
894     ///
895     /// Very similar to DereferenceLink() method, but dereference all
896     /// path components recursively until it is no further a link
897     /// in the path (but a file, directory, etc, or does not exist).
898     /// Replace the entry path string with the dereferenced path.
899     /// @sa
900     ///   DereferenceLink, IsLink, LookupLink
901     void DereferencePath(void);
902 
903     /// Get time stamp(s) of a directory entry.
904     ///
905     /// The creation time under MS windows is an actual creation time of the
906     /// entry. Under UNIX "creation" time is the time of last entry status
907     /// change. If either OS or file system does not support some time type
908     /// (modification/last access/creation), then the corresponding CTime
909     /// gets returned "empty".
910     /// Returned times are always in CTime's time zone format (eLocal/eGMT).
911     /// NOTE that what GetTime returns may not be equal to the the time(s)
912     /// previously set by SetTime, as the behavior depends on the OS and
913     /// the file system used.
914     /// @return
915     ///   TRUE if time(s) obtained successfully, FALSE otherwise.
916     /// @sa
917     ///   GetTimeT, SetTime, Stat
918     bool GetTime(CTime* modification,
919                  CTime* last_access = 0,
920                  CTime* creation    = 0) const;
921 
922     /// Get time stamp(s) of a directory entry (time_t version).
923     ///
924     /// Use GetTime() if you need precision of more than 1 second.
925     /// Returned time(s) are always in GMT format.
926     /// @return
927     ///   TRUE if time(s) obtained successfully, FALSE otherwise.
928     /// @sa
929     ///   GetTime, SetTimeT
930     bool GetTimeT(time_t* modification,
931                   time_t* last_access = 0,
932                   time_t* creation    = 0) const;
933 
934     /// Set time stamp(s) of a directory entry.
935     ///
936     /// The process must own the file or have write permissions in order
937     /// to change the time(s). Any parameter with a value of zero will
938     /// not cause the corresponding time stamp change.
939     /// NOTE that what GetTime can later return may not be equal to the
940     /// the time(s) set by SetTime, as the behavior depends on the OS and
941     /// the file system used.
942     /// Also, on UNIX it is impossible to change creation time of an entry
943     /// (we silently ignore the "creation" time stamp on that platform).
944     /// @param modification
945     ///   Entry modification time to set.
946     /// @param last_access
947     ///   Entry last access time to set. It cannot be less than the entry
948     ///   creation time, otherwise it will be set equal to the creation time.
949     /// @param creation
950     ///   Entry creation time to set. On some platforms it cannot be changed,
951     ///   so this parameter will be quietly ignored.
952     /// @return
953     ///   TRUE if the time(s) changed successfully, FALSE otherwise.
954     /// @sa
955     ///   SetTimeT, GetTime
956     bool SetTime(const CTime* modification = 0,
957                  const CTime* last_access  = 0,
958                  const CTime* creation     = 0) const;
959 
960     /// Set time stamp(s) of a directory entry (time_t version).
961     ///
962     /// Use SetTime() if you need precision of more than 1 second.
963     /// @param modification
964     ///   Entry modification time to set.
965     /// @param creation
966     ///   Entry creation time to set. On some platforms it cannot be changed,
967     ///   so this parameter will be quietly ignored.
968     /// @param last_access
969     ///   Entry last access time to set. It cannot be less than the entry
970     ///   creation time, otherwise it will be set equal to the creation time.
971     /// @return
972     ///   TRUE if the time(s) changed successfully, FALSE otherwise.
973     /// @sa
974     ///   SetTime, GetTimeT
975     bool SetTimeT(const time_t* modification = 0,
976                   const time_t* last_access  = 0,
977                   const time_t* creation     = 0) const;
978 
979 
980     /// What IsNewer() should do if the dir entry does not exist or
981     /// is not accessible.
982     /// @sa IsNewer
983     enum EIfAbsent {
984         eIfAbsent_Throw,    ///< Throw an exception
985         eIfAbsent_Newer,    ///< Deem absent entry to be "newer"
986         eIfAbsent_NotNewer  ///< Deem absent entry to be "older"
987     };
988 
989     /// Check if the current entry is newer than a specified date/time.
990     ///
991     /// @param tm
992     ///   Time to compare with the current entry modification time.
993     /// @param if_absent
994     ///   What to do if If the entry does not exist or is not accessible.
995     /// @return
996     ///   TRUE if the entry's modification time is newer than specified time.
997     ///   Return FALSE otherwise.
998     /// @sa
999     ///   GetTime, EIfAbsent
1000     bool IsNewer(time_t    tm,
1001                  EIfAbsent if_absent /* = eIfAbsent_Throw*/) const;
1002 
1003     /// Check if the current entry is newer than a specified date/time.
1004     ///
1005     /// @param tm
1006     ///   Time to compare with the current entry modification time.
1007     /// @param if_absent
1008     ///   What to do if If the entry does not exist or is not accessible.
1009     /// @return
1010     ///   TRUE if the entry's modification time is newer than specified time.
1011     ///   Return FALSE otherwise.
1012     /// @sa
1013     ///   GetTime, EIfAbsent
1014     bool IsNewer(const CTime& tm,
1015                  EIfAbsent    if_absent /* = eIfAbsent_Throw*/) const;
1016 
1017     /// What path version of IsNewer() should do if the dir entry or specified
1018     /// path does not exist or is not accessible. Default flags (0) mean
1019     /// throwing an exceptions if one of dir entries does not exists.
1020     /// But if you don't like to have an exception here, you can change IsNewer()
1021     /// behavior specifying flags. There are three cases: there's a problem only
1022     /// with the argument (HasThis-NoPath), there's a problem only with original
1023     /// entry (NoThis-HasPath), or there are problems with both (NoThis-NoPath).
1024     /// The EIfAbsent2 lets you independently select what to do in each of those
1025     /// scenarios: throw an exception (no flags set), return true (f*_Newer),
1026     /// or return false (f*_NotNewer).
1027     /// @sa IsNewer
1028     enum EIfAbsent2 {
1029         fHasThisNoPath_Newer    = (1 << 0),
1030         fHasThisNoPath_NotNewer = (1 << 1),
1031         fNoThisHasPath_Newer    = (1 << 2),
1032         fNoThisHasPath_NotNewer = (1 << 3),
1033         fNoThisNoPath_Newer     = (1 << 4),
1034         fNoThisNoPath_NotNewer  = (1 << 5)
1035     };
1036     typedef int TIfAbsent2;   ///< Binary OR of "EIfAbsent2"
1037 
1038     /// Check if the current entry is newer than some other.
1039     ///
1040     /// @param path
1041     ///   An entry name, of which to compare the modification times.
1042     /// @return
1043     ///   TRUE if the modification time of the current entry is newer than
1044     ///   the modification time of the specified entry, or if that entry
1045     ///   doesn't exist. Return FALSE otherwise.
1046     /// @sa GetTime, EIfAbsent2
1047     bool IsNewer(const string& path,
1048                  TIfAbsent2    if_absent /* = 0 throw*/) const;
1049 
1050     /// Check if the current entry and the given entry_name are identical.
1051     ///
1052     /// Note that entries can be checked accurately only on UNIX.
1053     /// On MS Windows function can check it only by file name.
1054     /// @param entry_name
1055     ///   An entry name, of which to compare current entry.
1056     /// @return
1057     ///   TRUE if both entries exists and identical. Return FALSE otherwise.
1058     /// @param follow_links
1059     ///   Whether to follow symlinks (shortcuts, aliases)
1060     bool IsIdentical(const string& entry_name,
1061                      EFollowLinks  follow_links = eIgnoreLinks) const;
1062 
1063     /// Get an entry owner.
1064     ///
1065     /// WINDOWS:
1066     ///   Retrieve the name of the account and the name of the first
1067     ///   group, which the account belongs to. The obtained group name may
1068     ///   be an empty string, if we don't have permissions to get it.
1069     ///   Windows 2000/XP: In addition to looking up for local accounts,
1070     ///   local domain accounts, and explicitly trusted domain accounts,
1071     ///   it also can look for any account in any known domain around.
1072     /// UNIX:
1073     ///   Retrieve an entry owner:group pair.
1074     /// @param owner
1075     ///   Pointer to a string to receive an owner name.
1076     /// @param group
1077     ///   Pointer to a string to receive a group name.
1078     /// @param follow
1079     ///   Whether to follow symbolic links when getting the information.
1080     /// @param uid
1081     ///   Pointer to an unsigned int to receive numeric user id
1082     ///   (this information is purely supplemental).
1083     /// @param gid
1084     ///   Pointer to an unsigned int to receive numeric group id
1085     ///   (this information is purely supplemental).
1086     /// @note
1087     ///   Numeric uid/gid may be the fake ones on Windows (and may be 0).
1088     /// @note
1089     ///   The call will fail if neither owner nor group is provided non-NULL
1090     ///   (even though uid and/or gid may be non-NULL).
1091     /// @note
1092     ///   It is in best interest of the caller to clear all strings and
1093     ///   integers that are expected to get values out of this call prior
1094     ///   to making the actual call.
1095     /// @return
1096     ///   TRUE if successful, FALSE otherwise.
1097     /// @sa
1098     ///   SetOwner
1099     bool GetOwner(string* owner, string* group = 0,
1100                   EFollowLinks follow = eFollowLinks,
1101                   unsigned int* uid = 0, unsigned int* gid = 0) const;
1102 
1103     /// Set an entry owner and/or group.
1104     ///
1105     /// You should have administrative (super user) rights to change
1106     /// an owner or group.
1107     /// WINDOWS:
1108     ///   Only administrative privileges (Restore and Take Ownership)
1109     ///   grant rights to change ownership. Without one of the privileges,
1110     ///   an administrator cannot take ownership of any file or give ownership
1111     ///   back to the some user.
1112     /// UNIX:
1113     ///   The owner of an entry can change the group to any group of which
1114     ///   that owner is a member of. The super-user may assign the group
1115     ///   arbitrarily.
1116     /// @param owner
1117     ///   New owner name to set. Use empty string if dont want to change.
1118     /// @param group
1119     ///   New group name to set. Use empty string if dont want to change.
1120     /// @param uid
1121     ///   Pointer to an unsigned int to receive numeric user id of the
1122     ///   prospective owner (this information is purely supplemental).
1123     /// @param gid
1124     ///   Pointer to an unsigned int to receive numeric group id of the
1125     ///   prospective owner (this information is purely supplemental).
1126     /// @note
1127     ///   Numeric uid/gid can be returned even if the call was unsuccessful;
1128     ///   they may be the fake ones on Windows (and may be 0).
1129     /// @return
1130     ///   TRUE if successful, FALSE otherwise.
1131     /// @sa
1132     ///   GetOwner
1133     bool SetOwner(const string& owner, const string& group = kEmptyStr,
1134                   EFollowLinks follow = eFollowLinks,
1135                   unsigned int* uid = 0, unsigned int* gid = 0) const;
1136 
1137     //
1138     // Access permissions.
1139     //
1140 
1141     /// Directory entry access permissions.
1142     enum EMode {
1143         fExecute = 1,       ///< Execute / List(directory) permission
1144         fWrite   = 2,       ///< Write permission
1145         fRead    = 4,       ///< Read permission
1146         fDefault = 8,       ///< Special flag: ignore all other flags, use current default mode
1147 
1148         // initial defaults for directories
1149         fDefaultDirUser  = fRead | fExecute | fWrite,
1150                             ///< Default user permission for a dir.
1151         fDefaultDirGroup = fRead | fExecute,
1152                             ///< Default group permission for a dir.
1153         fDefaultDirOther = fRead | fExecute,
1154                             ///< Default other permission for a dir.
1155 
1156         // initial defaults for non-dir entries (files, etc.)
1157         fDefaultUser     = fRead | fWrite,
1158                             ///< Default user permission for a file
1159         fDefaultGroup    = fRead,
1160                             ///< Default group permission for a file
1161         fDefaultOther    = fRead
1162                             ///< Default other permission for a file
1163     };
1164     typedef unsigned int TMode;  ///< Bitwise OR of "EMode"
1165 
1166     enum ESpecialModeBits {
1167         fSticky = 1,
1168         fSetGID = 2,
1169         fSetUID = 4
1170     };
1171     typedef unsigned int TSpecialModeBits; ///< Bitwise OR of ESpecialModeBits
1172 
1173     /// Relative permissions change modes.
1174     /// Can be combined with TMode or TSpecialModeBits.
1175     /// Only one of these flags is allowed for each mode.
1176     enum EModeRelative {
1177         fModeAdd      = 16,  ///< Adds the argument permission mode to
1178                              ///< the entry's current mode.
1179         fModeRemove   = 32,  ///< Removes the argument permission mode
1180                              ///< from the entry's current mode.
1181         fModeNoChange = 64   ///< Do not change permission mode.
1182     };
1183 
1184     /// Get permission mode(s) of a directory entry.
1185     ///
1186     /// On WINDOWS: There is only the "user_mode" permission setting,
1187     /// and "group_mode" and "other_mode" settings will be ignored.
1188     /// The "user_mode" will be combined with effective permissions for
1189     /// the current process owner on specified directory entry.
1190     /// @return
1191     ///   TRUE upon successful retrieval of permission mode(s),
1192     ///   FALSE otherwise.
1193     /// @sa
1194     ///   SetMode
1195     bool GetMode(TMode*            user_mode,
1196                  TMode*            group_mode = 0,
1197                  TMode*            other_mode = 0,
1198                  TSpecialModeBits* special    = 0) const;
1199 
1200     /// Set permission mode(s) of a directory entry.
1201     ///
1202     /// Permissions are set as specified by the passed values for
1203     /// user_mode, group_mode and other_mode. This method rewrites
1204     /// each user/group/other/special permission by default.
1205     /// @note
1206     ///   Adding one of the EModeRelative flags to mode change default
1207     ///   behavior that replace modes with passed values and allow
1208     ///   for relative mode change for any of user/group/other/special.
1209     ///   It is possible to keep it as is, or add/remove some permission
1210     ///   modes specified in parameters.
1211     /// @note
1212     ///   Passing fDefault will cause the corresponding mode
1213     ///   to be taken and set from its default setting.
1214     /// @flags
1215     ///   Entry processing flags. Affect directories only,
1216     ///   see CDir::SetMode() for details. For other type entris
1217     ///   don't have any effect.
1218     /// @return
1219     ///   TRUE if permission successfully set;  FALSE, otherwise.
1220     /// @sa
1221     ///   SetDefaultMode, SetDefaultModeGlobal, GetMode, EMode,
1222     ///   EModeRelative, ESpecialModeBits, SetModeEntry, CDir::SetMode,
1223     ///   EProcessingFlags
1224     virtual bool SetMode(
1225                  TMode            user_mode, // e.g. fDefault
1226                  TMode            group_mode = fDefault,
1227                  TMode            other_mode = fDefault,
1228                  TSpecialModeBits special    = 0,
1229                  TSetModeFlags    flags      = eEntryOnly) const;
1230 
1231 
1232     /// Set permission mode(s) of a directory entry.
1233     ///
1234     /// Same as SetMode(), but process current entry only.
1235     /// Don't process entries inside directories.
1236     /// @sa SetMode
1237     virtual bool SetModeEntry(
1238                  TMode            user_mode, // e.g. fDefault
1239                  TMode            group_mode = fDefault,
1240                  TMode            other_mode = fDefault,
1241                  TSpecialModeBits special    = 0,
1242                  TSetModeFlags    flags      = eEntryOnly) const;
1243 
1244     /// Set default permission modes globally for all CDirEntry objects.
1245     ///
1246     /// The default mode is set globally for all CDirEntry objects except
1247     /// for those having their own mode set with individual
1248     /// SetDefaultMode().
1249     ///
1250     /// When "fDefault" is passed as a value of the mode parameters,
1251     /// the default mode takes places for the value as defined in EType:
1252     ///
1253     /// If user_mode is "fDefault", then the default is to take
1254     /// - "fDefaultDirUser" if this is a directory, or
1255     /// - "fDefaultUser" if this is a file.
1256     ///
1257     /// If group_mode is "fDefault", then the default is to take
1258     /// - "fDefaultDirGroup" if this is a directory, or
1259     /// - "fDefaultGroup" if this is a file.
1260     ///
1261     /// If other_mode is "fDefault", then the default is to take
1262     /// - "fDefaultDirOther" if this is a directory, or
1263     /// - "fDefaultOther" if this is a file.
1264     static void SetDefaultModeGlobal(
1265                                 EType            entry_type,
1266                                 TMode            user_mode, // e.g. fDefault
1267                                 TMode            group_mode = fDefault,
1268                                 TMode            other_mode = fDefault,
1269                                 TSpecialModeBits special    = 0);
1270 
1271     /// Set default mode(s) for this entry only.
1272     ///
1273     /// When "fDefault" is passed as a value of the parameters,
1274     /// the corresponding mode will be taken and set from the global mode
1275     /// as specified by SetDefaultModeGlobal().
1276     virtual void SetDefaultMode(EType            entry_type,
1277                                 TMode            user_mode, // e.g. fDefault
1278                                 TMode            group_mode = fDefault,
1279                                 TMode            other_mode = fDefault,
1280                                 TSpecialModeBits special    = 0);
1281 
1282     /// Check access rights.
1283     ///
1284     /// Use effective user ID (or process owner) to check the entry
1285     /// for accessibility accordingly to specified mask.
1286     /// @note
1287     ///   - If an entry is a symbolic link, that the access rights
1288     ///     will be checked for entry to which the link points.
1289     ///   - Execute bit means 'search' for directories.
1290     ///   - Success checking fExecute mode do not guarantee that
1291     ///     the file will executable at all. This function just check
1292     ///     permissions and not the file format.
1293     ///   - On some platforms, if the file is currently open for execution,
1294     ///     the function reports that it is not writable, regardless
1295     ///     of the setting of its mode.
1296     /// @note
1297     ///   This method may not work correctly
1298     ///     On MS-Windows:
1299     ///       - for network shares and mapped network drives.
1300     ///     On Unix:
1301     ///       - for entries on NFS file systems.
1302     /// @note
1303     ///   Using CheckAccess() to check if a user is authorized to e.g. open
1304     ///   a file before actually doing so creates a security hole, because
1305     ///   the user might exploit the short time interval between checking
1306     ///   and opening the file to manipulate it. Always is better to try to
1307     ///   open a file with necessary permissions and check result.
1308     /// @param access_mode
1309     ///   Checked access mode (any combination of fRead/fWrite/fExecute).
1310     /// @return
1311     ///   TRUE if specified permissions granted, FALSE otherwise
1312     ///   (also returns FALSE if the file doesn't exists or an error occurs).
1313     /// @sa
1314     ///   GetMode
1315     bool CheckAccess(TMode access_mode) const;
1316 
1317 
1318     /// Construct mode_t value from permission modes.
1319     /// Parameters must not have "fDefault" values.
1320     /// @sa ModeFromModeT
1321     static mode_t MakeModeT(TMode            user_mode,
1322                             TMode            group_mode,
1323                             TMode            other_mode,
1324                             TSpecialModeBits special);
1325 
1326     /// Convert mode_t to permission mode(s).
1327     ///
1328     /// @note
1329     ///   On WINDOWS: There is only the "user_mode" permission setting,
1330     ///   and "group_mode" and "other_mode" settings will be ignored.
1331     ///   The "user_mode" will be combined with effective permissions for
1332     ///   the current process owner on specified directory entry.
1333     /// @sa
1334     ///   GetMode, SetMode, MakeModeT
1335     static void ModeFromModeT(mode_t            mode,
1336                               TMode*            user_mode,
1337                               TMode*            group_mode = 0,
1338                               TMode*            other_mode = 0,
1339                               TSpecialModeBits* special    = 0);
1340 
1341     /// Permission mode string format.
1342     /// @sa
1343     ///   StringToMode, ModeToString
1344     enum EModeStringFormat {
1345         eModeFormat_Octal,                       ///< Octal format ("664")
1346         eModeFormat_Symbolic,                    ///< Shell symbolic format ("u=rwx,g=rwx,o=rx")
1347         eModeFormat_List,                        ///< Shell list 'ls -l' like format ("rwxrwxrwx")
1348         eModeFormat_Default = eModeFormat_Octal  ///< Default mode
1349     };
1350 
1351 
1352     /// Convert permission modes to string representation using one of predefined formats.
1353     /// Parameters must not have "fDefault" values.
1354     /// @sa StringToMode, EModeStringFormat
1355     static string ModeToString(TMode             user_mode,
1356                                TMode             group_mode,
1357                                TMode             other_mode,
1358                                TSpecialModeBits  special,
1359                                EModeStringFormat format = eModeFormat_Default);
1360 
1361     /// Convert string (in one of predefined formats, detects automatically) to permission mode(s).
1362     /// @return
1363     ///   TRUE if the operation was completed successfully; FALSE, otherwise.
1364     /// @sa
1365     ///   ModeToString, EModeStringFormat
1366     static bool StringToMode(const CTempString& mode,
1367                              TMode*            user_mode,
1368                              TMode*            group_mode = 0,
1369                              TMode*            other_mode = 0,
1370                              TSpecialModeBits* special    = 0);
1371 
1372 
1373     /// Get file/directory mode creation mask.
1374     /// @note
1375     ///   umask can be useful on Unix platform only. On Windows only
1376     ///   C Runtime library honor it, any methods that use Windows API
1377     ///   ignore its setting.
1378     /// @sa
1379     ///   SetUmask
1380     static void GetUmask(TMode*            user_mode,
1381                          TMode*            group_mode = 0,
1382                          TMode*            other_mode = 0,
1383                          TSpecialModeBits* special    = 0);
1384 
1385     /// Set file/directory mode creation mask.
1386     ///
1387     /// @note
1388     ///   fDefault value for permission mode(s) mean 0.
1389     /// @note
1390     ///   umask can be useful on Unix platform only. On Windows only
1391     ///   C Runtime library honor it, any methods that use Windows API
1392     ///   ignore its setting.
1393     /// @sa
1394     ///   GetUmask
1395     static void SetUmask(TMode             user_mode,
1396                          TMode             group_mode = fDefault,
1397                          TMode             other_mode = fDefault,
1398                          TSpecialModeBits  special    = 0);
1399 
1400     //
1401     // Temporary directory entries (and files)
1402     //
1403 
1404     /// Temporary file creation mode
1405     enum ETmpFileCreationMode {
1406         eTmpFileCreate,     ///< Create empty file for each GetTmpName* call.
1407         eTmpFileGetName     ///< Get name of the file only.
1408     };
1409 
1410     /// Get temporary file name.
1411     ///
1412     /// This class generates a temporary file name in the temporary directory
1413     /// specified by the OS. But this behavior can be changed -- just set the
1414     /// desired temporary directory using the global parameter 'TmpDir' in
1415     /// in the 'NCBI' registry section or the environment (see CParam class
1416     /// description), and it will used by default in this class.
1417     ///
1418     /// @param mode
1419     ///   Temporary file creation mode. Note, that default mode eTmpFileGetName
1420     ///   returns only the name of the temporary file, without creating it.
1421     ///   This method can be faster, but it have potential race condition,
1422     ///   when other process can leave as behind and create file with the same
1423     ///   name first. Also, please note, that if you call GetTmpName() again,
1424     ///   without creating file for previous call of this method, the same
1425     ///   file name can be returned.
1426     /// @return
1427     ///   Name of temporary file, or "kEmptyStr" if there was an error
1428     ///   getting temporary file name.
1429     /// @sa
1430     ///    GetTmpNameEx, ETmpFileCreationMode
1431     static string GetTmpName(ETmpFileCreationMode mode = eTmpFileGetName);
1432 
1433     /// Get temporary file name.
1434     ///
1435     /// @param dir
1436     ///   Directory in which temporary file is to be created;
1437     ///   default of kEmptyStr means that function try to get application
1438     ///   specific temporary directory name from global parameter (see
1439     ///   GetTmpName description), then it try to get system temporary
1440     ///   directory, and all of this fails - current directory will be used.
1441     /// @param prefix
1442     ///   Temporary file name will be prefixed by value of this parameter;
1443     ///   default of kEmptyStr means that, effectively, no prefix value will
1444     ///   be used.
1445     /// @param mode
1446     ///   Temporary file creation mode.
1447     ///   If set to "eTmpFileCreate", empty file with unique name will be
1448     ///   created. Please, do not forget to remove it yourself as soon as it
1449     ///   is no longer needed. On some platforms "eTmpFileCreate" mode is
1450     ///   equal to "eTmpFileGetName".
1451     ///   If set to "eTmpFileGetName", returns only the name of the temporary
1452     ///   file, without creating it. This method can be faster, but it have
1453     ///   potential race condition, when other process can leave as behind and
1454     ///   create file with the same name first.
1455     /// @return
1456     ///   Name of temporary file, or "kEmptyStr" if there was an error
1457     ///   getting temporary file name.
1458     /// @sa
1459     ///    GetTmpName, ETmpFileCreationMode
1460     static string GetTmpNameEx(const string&        dir    = kEmptyStr,
1461                                const string&        prefix = kEmptyStr,
1462                                ETmpFileCreationMode mode   = eTmpFileGetName);
1463 
1464 
1465     /// What type of temporary file to create.
1466     enum ETextBinary {
1467         eText,          ///< Create text file
1468         eBinary         ///< Create binary file
1469     };
1470 
1471     /// Which operations to allow on temporary file.
1472     enum EAllowRead {
1473         eAllowRead,     ///< Allow read and write
1474         eWriteOnly      ///< Allow write only
1475     };
1476 
1477     /// Create temporary file and return pointer to corresponding stream.
1478     ///
1479     /// The temporary file will be automatically deleted after the stream
1480     /// object is deleted. If the file exists before the function call, then
1481     /// after the function call it will be removed. Also any previous contents
1482     /// of the file will be overwritten.
1483     /// @param filename
1484     ///   Use this value as name of temporary file. If "kEmptyStr" is passed
1485     ///   generate a temporary file name.
1486     /// @param text_binary
1487     ///   Specifies if temporary filename should be text ("eText") or binary
1488     ///   ("eBinary").
1489     /// @param allow_read
1490     ///   If set to "eAllowRead", read and write are permitted on temporary
1491     ///   file. If set to "eWriteOnly", only write is permitted on temporary
1492     ///   file.
1493     /// @return
1494     ///   - Pointer to corresponding stream, or
1495     ///   - NULL if error encountered.
1496     /// @sa
1497     ///   CreateTmpFileEx
1498     static fstream* CreateTmpFile(const string& filename    = kEmptyStr,
1499                                   ETextBinary   text_binary = eBinary,
1500                                   EAllowRead    allow_read  = eAllowRead);
1501 
1502     /// Create temporary file and return pointer to corresponding stream.
1503     ///
1504     /// Similar to CreateTmpEx() except that you can also specify the directory
1505     /// in which to create the temporary file and the prefix string to be used
1506     /// for creating the temporary file.
1507     ///
1508     /// The temporary file will be automatically deleted after the stream
1509     /// object is deleted. If the file exists before the function call, then
1510     /// after the function call it will be removed. Also any previous contents
1511     /// of the file will be overwritten.
1512     /// @param dir
1513     ///   The directory in which the temporary file is to be created. If not
1514     ///   specified, the temporary file will be created in the current
1515     ///   directory.
1516     /// @param prefix
1517     ///   Use this value as the prefix for temporary file name. If "kEmptyStr"
1518     ///   is passed generate a temporary file name.
1519     /// @param text_binary
1520     ///   Specifies if temporary filename should be text ("eText") or binary
1521     ///   ("eBinary").
1522     /// @param allow_read
1523     ///   If set to "eAllowRead", read and write are permitted on temporary
1524     ///   file. If set to "eWriteOnly", only write is permitted on temporary
1525     ///   file.
1526     /// @return
1527     ///   - Pointer to corresponding stream, or
1528     ///   - NULL if error encountered.
1529     /// @sa
1530     ///   CreateTmpFile
1531     static fstream* CreateTmpFileEx(const string& dir         = ".",
1532                                     const string& prefix      = kEmptyStr,
1533                                     ETextBinary   text_binary = eBinary,
1534                                     EAllowRead    allow_read  = eAllowRead);
1535 
1536 protected:
1537     /// Get the default global mode.
1538     ///
1539     /// For use in derived classes like CDir and CFile.
1540     static void GetDefaultModeGlobal(EType             entry_type,
1541                                      TMode*            user_mode,
1542                                      TMode*            group_mode,
1543                                      TMode*            other_mode,
1544                                      TSpecialModeBits* special);
1545 
1546     /// Get the default mode.
1547     ///
1548     /// For use by derived classes like CDir and CFile.
1549     void GetDefaultMode(TMode*            user_mode,
1550                         TMode*            group_mode,
1551                         TMode*            other_mode,
1552                         TSpecialModeBits* special) const;
1553     mode_t GetDefaultModeT(void) const;
1554 
1555 private:
1556     string m_Path;    ///< Full path of this directory entry
1557 
1558     /// Which default mode: user, group, or other.
1559     ///
1560     /// Used as an index into an array that contains default mode values;
1561     /// so there is no "fDefault" as an enumeration value for EWho here!
1562     enum EWho {
1563         eUser = 0,    ///< User mode
1564         eGroup,       ///< Group mode
1565         eOther,       ///< Other mode
1566         eSpecial      ///< Special bits
1567     };
1568 
1569     /// Holds default mode values
1570     TMode m_DefaultMode[4/*EWho + Special bits*/];
1571 
1572     /// Holds default mode global values, per entry type
1573     static TMode m_DefaultModeGlobal[eUnknown][4/*EWho + Special bits*/];
1574 
1575     /// Backup suffix
1576     static const char* m_BackupSuffix;
1577 
1578 private:
1579     /// Convert permission mode to symbolic string representation.
1580     static string x_ModeToSymbolicString(EWho who, TMode mode, bool special_bit, char filler);
1581 };
1582 
1583 
1584 
1585 /////////////////////////////////////////////////////////////////////////////
1586 ///
1587 /// CFile --
1588 ///
1589 /// Define class to work with regular files.
1590 /// NOTE: it don't work with any special or block devices like /dev/null
1591 ///
1592 /// Models a file in a file system. Basic functionality is derived from
1593 /// CDirEntry and extended for files.
1594 
1595 class NCBI_XNCBI_EXPORT CFile : public CDirEntry
1596 {
1597     typedef CDirEntry CParent;    ///< CDirEntry is the parent class
1598 
1599 public:
1600     /// Default constructor.
1601     CFile(void);
1602 
1603     /// Constructor using specified path string.
1604     CFile(const string& file);
1605 
1606     /// Copy constructor.
1607     CFile(const CDirEntry& file);
1608 
1609     /// Destructor.
1610     virtual ~CFile(void);
1611 
1612     /// Get a type of constructed object.
GetObjectType(void) const1613     virtual EType GetObjectType(void) const { return eFile; };
1614 
1615     /// Check existence of file.
1616     /// @note
1617     ///   CDirEntry::Exists() could be faster on some platforms,
1618     ///   if you don't need to check that entry is a file.
1619     /// @sa CDirEntry::Exists
1620     virtual bool Exists(void) const;
1621 
1622     /// Get size of file.
1623     ///
1624     /// @return
1625     ///   Size of the file, if operation successful; -1, otherwise.
1626     Int8 GetLength(void) const;
1627 
1628     /// Copy a file.
1629     ///
1630     /// @param new_path
1631     ///    Target entry path/name.
1632     /// @param flags
1633     ///   Flags specified how to copy entry.
1634     /// @param buf_size
1635     ///   Size of buffer to read file.
1636     ///   Zero value means using default buffer size.
1637     /// @return
1638     ///   TRUE if operation successful; FALSE, otherwise.
1639     /// @sa
1640     ///   TCopyFlags
1641     virtual bool Copy(const string& new_path, TCopyFlags flags = fCF_Default,
1642                       size_t buf_size = 0) const;
1643 
1644     /// Compare files contents in binary form.
1645     ///
1646     /// @param file
1647     ///   File name to compare.
1648     /// @param buf_size
1649     ///   Size of buffer to read file.
1650     ///   Zero value means using default buffer size.
1651     /// @return
1652     ///   TRUE if files content is equal; FALSE otherwise.
1653     bool Compare(const string& file, size_t buf_size = 0) const;
1654 
1655     /// Mode to compare streams in text form.
1656     enum ECompareText {
1657         /// Skip end-of-line characters ('\r' and '\n')
1658         eIgnoreEol = eCompareText_IgnoreEol,
1659         ///< Skip white spaces (in terms of isspace(), including end-of-line)
1660         eIgnoreWs  = eCompareText_IgnoreWhiteSpace
1661     };
1662 
1663     /// Compare files contents in text form.
1664     ///
1665     /// @param file
1666     ///   File name to compare.
1667     /// @param mode
1668     ///   Type of white space characters to ignore
1669     /// @param buf_size
1670     ///   Size of buffer to read file.
1671     ///   Zero value means using default buffer size.
1672     /// @return
1673     ///   TRUE if files content is equal; FALSE otherwise.
1674     bool CompareTextContents(const string& file, ECompareText mode,
1675                              size_t buf_size = 0) const;
1676 };
1677 
1678 
1679 /////////////////////////////////////////////////////////////////////////////
1680 ///
1681 /// CDir --
1682 ///
1683 /// Define class to work with directories.
1684 ///
1685 
1686 class NCBI_XNCBI_EXPORT CDir : public CDirEntry
1687 {
1688     typedef CDirEntry CParent;  ///< CDirEntry is the parent class
1689 
1690 public:
1691     /// Default constructor.
1692     CDir(void);
1693 
1694     /// Constructor using specified directory name.
1695     CDir(const string& dirname);
1696 
1697     /// Copy constructor.
1698     CDir(const CDirEntry& dir);
1699 
1700     /// Destructor.
1701     virtual ~CDir(void);
1702 
1703     /// Get a type of constructed object.
GetObjectType(void) const1704     virtual EType GetObjectType(void) const { return eDir; };
1705 
1706     /// Check if directory "dirname" exists.
1707     /// @note
1708     ///   CDirEntry::Exists() could be faster on some platforms,
1709     ///   if you don't need to check that entry is a directory.
1710     virtual bool Exists(void) const;
1711 
1712     /// Get user "home" directory.
1713     static string GetHome(void);
1714 
1715     /// Get temporary directory.
1716     ///
1717     /// Return temporary directory name specified by OS via environment variables.
1718     /// @sa GetAppTmpDir
1719     static string GetTmpDir(void);
1720 
1721     /// Get temporary directory name for application.
1722     ///
1723     /// Return temporary directory name specified in the application's registry file or via environment.
1724     /// Registry file:
1725     ///     [NCBI]
1726     ///     TmpDir = ...
1727     /// Environment variable:
1728     ///     NCBI_CONFIG__NCBI__TmpDir
1729     ///
1730     /// If not specified, return GetTmpDir().
1731     /// @sa GetTmpDir
1732     static string GetAppTmpDir(void);
1733 
1734     /// Get the current working directory.
1735     static string GetCwd(void);
1736 
1737     /// Change the current working directory.
1738     static bool SetCwd(const string& dir);
1739 
1740     /// Define a list of pointers to directory entries.
1741     typedef AutoPtr<CDirEntry> TEntry;
1742     typedef list< TEntry > TEntries;
1743 
1744     /// Flags for GetEntries()
1745     /// @sa GetEntries, GetEntriesPtr
1746     enum EGetEntriesFlags {
1747         fIgnoreRecursive = (1<<1), ///< Suppress "self recursive"
1748                                    ///< elements (the directories "."
1749                                    ///< and "..").
1750         fCreateObjects   = (1<<2), ///< Create appropriate subclasses
1751                                    ///< of CDirEntry (CFile,CDir,...),
1752                                    ///< not just CDirEntry objects.
1753         fNoCase          = (1<<3), ///< Ignore upper and lower-case
1754                                    ///< differences when doing a mask
1755                                    ///< comparison. Makes the mask
1756                                    ///< case-insensitive.
1757         fIgnorePath      = (1<<4), ///< Return only names of entries,
1758                                    ///< not their full paths.
1759         fThrowOnError    = (1<<5), ///< Throws an exceptions on error,
1760                                    ///< instead of returning empty/null value.
1761 
1762         // Deprecated entries to be removed in the future
1763         eAllEntries       = 0,     ///< \deprecated Only provided for
1764                                    ///<   backward compatibility. Will be
1765                                    ///<   removed in the future. Do not use.
1766         eIgnoreRecursive  = fIgnoreRecursive
1767                                    ///< \deprecated Only provided for
1768                                    ///<   backward compatibility. Will be
1769                                    ///<   removed in the future. Do not use.
1770     };
1771     typedef int TGetEntriesFlags; ///< Binary OR of "EGetEntriesFlags"
1772 
1773 
1774     /// Get directory entries based on the specified "mask".
1775     ///
1776     /// @param mask
1777     ///   Use to select only entries that match this mask.
1778     ///   Do not use file mask if set to "kEmptyStr".
1779     /// @param flags
1780     ///   Flags defines behavior and which entries to return.
1781     /// @return
1782     ///   A list containing all directory entries.
1783     ///   Return empty list on error.
1784     /// @note
1785     ///   Use fThrowOnError to avoid getting empty list on error
1786     ///   and throwing an exception instead.
1787     TEntries GetEntries(const string&    mask  = kEmptyStr,
1788                         TGetEntriesFlags flags = 0) const;
1789 
1790     /// Get directory entries based on the specified set of "masks".
1791     ///
1792     /// @param masks
1793     ///   Use to select only entries that match this set of masks.
1794     /// @param flags
1795     ///   Flags defines behavior and which entries to return.
1796     /// @return
1797     ///   A list containing all directory entries.
1798     ///   Return empty list on error.
1799     /// @note
1800     ///   Use fThrowOnError to avoid getting empty list on error
1801     ///   and throwing an exception instead.
1802     TEntries GetEntries(const vector<string>& masks,
1803                         TGetEntriesFlags flags = 0) const;
1804 
1805     /// Get directory entries based on the specified set of "masks".
1806     ///
1807     /// @param mask
1808     ///   Use to select only entries that match this set of masks.
1809     /// @param flags
1810     ///   Flags defines behavior and which entries to return.
1811     /// @return
1812     ///   A list containing all directory entries.
1813     ///   Return empty list on error.
1814     /// @note
1815     ///   Use fThrowOnError to avoid getting empty list on error
1816     ///   and throwing an exception instead.
1817     TEntries GetEntries(const CMask&     masks,
1818                         TGetEntriesFlags flags = 0) const;
1819 
1820     /// Get directory entries based on the specified "mask".
1821     /// This methods are faster on big directories than GetEntries().
1822     ///
1823     /// @param mask
1824     ///   Use to select only entries that match this mask.
1825     ///   Do not use file mask if set to "kEmptyStr".
1826     /// @param flags
1827     ///   Flags defines behavior and which entries to return.
1828     /// @return
1829     ///   A pointer to list of directory entries.
1830     ///   NULL in the case of error.
1831     /// @note
1832     ///   Do not forget to release allocated memory using return pointer.
1833     TEntries* GetEntriesPtr(const string&    mask  = kEmptyStr,
1834                             TGetEntriesFlags flags = 0) const;
1835 
1836     /// Get directory entries based on the specified set of "masks".
1837     /// This methods are faster on big directories than GetEntries().
1838     ///
1839     /// @param mask
1840     ///   Use to select only entries that match this set of masks.
1841     /// @param flags
1842     ///   Flags defines behavior and which entries to return.
1843     /// @return
1844     ///   A pointer to list of directory entries.
1845     ///   NULL in the case of error.
1846     /// @note
1847     ///   Do not forget to release allocated memory using return pointer.
1848     TEntries* GetEntriesPtr(const vector<string>& masks,
1849                             TGetEntriesFlags flags = 0) const;
1850 
1851     /// Get directory entries based on the specified set of "masks".
1852     /// This methods are faster on big directories than GetEntries().
1853     ///
1854     /// @param mask
1855     ///   Use to select only entries that match this set of masks.
1856     /// @param flags
1857     ///   Flags defines behavior and which entries to return.
1858     /// @return
1859     ///   A pointer to list of directory entries.
1860     ///   NULL in the case of error.
1861     /// @note
1862     ///   Do not forget to release allocated memory using return pointer.
1863     TEntries* GetEntriesPtr(const CMask&     masks,
1864                             TGetEntriesFlags flags = 0) const;
1865 
1866     // OBSOLETE functions. Will be deleted soon.
1867     // Please use versions of GetEntries*() listed above.
1868 
1869     typedef TGetEntriesFlags EGetEntriesMode;
1870     /// @deprecated  Use other variant of of GetEntries() instead.
1871     NCBI_DEPRECATED
1872     TEntries GetEntries    (const string&    mask,
1873                             EGetEntriesMode  mode,
1874                             NStr::ECase      use_case) const;
1875     /// @deprecated  Use other variant of of GetEntries() instead.
1876     NCBI_DEPRECATED
1877     TEntries GetEntries    (const vector<string>& masks,
1878                             EGetEntriesMode  mode,
1879                             NStr::ECase      use_case) const;
1880     /// @deprecated  Use other variant of of GetEntries() instead.
1881     NCBI_DEPRECATED
1882     TEntries GetEntries    (const CMask&     masks,
1883                             EGetEntriesMode  mode,
1884                             NStr::ECase      use_case) const;
1885     /// @deprecated  Use other variant of of GetEntries() instead.
1886     NCBI_DEPRECATED
1887     TEntries* GetEntriesPtr(const string&    mask,
1888                             EGetEntriesMode  mode,
1889                             NStr::ECase      use_case) const;
1890     /// @deprecated  Use other variant of of GetEntries() instead.
1891     NCBI_DEPRECATED
1892     TEntries* GetEntriesPtr(const vector<string>& masks,
1893                             EGetEntriesMode  mode,
1894                             NStr::ECase      use_case) const;
1895     /// @deprecated  Use other variant of of GetEntries() instead.
1896     NCBI_DEPRECATED
1897     TEntries* GetEntriesPtr(const CMask&     masks,
1898                             EGetEntriesMode  mode,
1899                             NStr::ECase      use_case) const;
1900 
1901     /// Flags for Create()/CreatePath()
1902     /// @sa Create, CreatePath
1903     enum ECreateFlags {
1904         /// Default directory creation mode
1905         ///   - no error if directory already exists;
1906         ///   - don't change permissions if already exists;
1907         ///   - use default mode for created directory
1908         ///     see: SetDefaultMode(), SetDefaultModeGlobal(), CFileAPI::SetHonorUmask().
1909         fCreate_Default         = 0,
1910         /// Don't change permissions after creation, leave it for OS and umask control.
1911         /// This flag have a priority over CFileAPI::SetHonorUmask(), that works with fCD_Default only.
1912         fCreate_PermByUmask     = (1 << 1),
1913         /// Use same permissions as parent directory (umask ignored)
1914         fCreate_PermAsParent    = (1 << 2),
1915         /// Error, if directory already exists. All other existent entry with
1916         /// the same name (including symbolic links to directory) lead to an error by default.
1917         fCreate_ErrorIfExists   = (1 << 3),
1918         /// Allow to "update" permissions for already existent directory
1919         /// using default, umask or parent permissions as specified by previous flags.
1920         /// Note: Create() only, ignored by CreatePath().
1921         fCreate_UpdateIfExists  = (1 << 4)
1922     };
1923     typedef unsigned int TCreateFlags;    ///< Binary OR of "ECreateFlags"
1924 
1925     /// Create the directory using "dirname" passed in the constructor.
1926     ///
1927     /// Default directory creation mode:
1928     ///   - TRUE if directory already exists;
1929     ///   - don't change permissions if already exists;
1930     ///   - use default mode for created directory
1931     /// @return
1932     ///   TRUE if operation successful; FALSE, otherwise.
1933     /// @sa
1934     ///   SetDefaultMode, SetDefaultModeGlobal, CFileAPI::SetHonorUmask, CreatePath
1935     bool Create(TCreateFlags flags = fCreate_Default) const;
1936 
1937     /// Create the directory path recursively possibly more than one at a time.
1938     ///
1939     /// @return
1940     ///   TRUE if operation successful; FALSE otherwise.
1941     /// @sa Create
1942     bool CreatePath(TCreateFlags flags = fCreate_Default) const;
1943 
1944     /// Copy directory.
1945     ///
1946     /// @param new_path
1947     ///   New path/name for entry.
1948     /// @param flags
1949     ///   Flags specified how to copy directory.
1950     /// @param buf_size
1951     ///   Size of buffer to read file.
1952     ///   Zero value means using default buffer size.
1953     /// @return
1954     ///   TRUE if operation successful; FALSE, otherwise.
1955     /// @sa
1956     ///   CDirEntry::TCopyFlags, CDirEntry::Copy, CFile::Copy
1957     virtual bool Copy(const string& new_path, TCopyFlags flags = fCF_Default,
1958                       size_t buf_size = 0) const;
1959 
1960     /// Delete existing directory.
1961     ///
1962     /// @param flags
1963     ///   Directory processing flags. Some popular sets of flags
1964     ///   combined together and listed below:
1965     ///   - eOnlyEmpty
1966     ///        directory can be removed only if it is empty;
1967     ///   - eTopDirOnly
1968     ///        remove all files in the top directory only,
1969     ///        no any subdirectory or files in it;
1970     ///   - eNonRecursive
1971     ///        same as eTopDirOnly, but removes also empty
1972     ///        subdirectories in the top directory only;
1973     ///   - eRecursive
1974     ///        remove all files in directory and all its subdirectories;
1975     ///   - eRecursiveIgnoreMissing
1976     ///        same as eRecursive, but do not report an error
1977     ///        for missed entries.
1978     /// @return
1979     ///   TRUE if operation successful; FALSE otherwise.
1980     /// @sa
1981     ///   CDirEntry::Remove, EProcessingFlags
1982     virtual bool Remove(TRemoveFlags flags = eRecursive) const;
1983 
1984 
1985     /// Set permission mode(s) for a directory.
1986     ///
1987     /// Permissions are set as specified by the passed values for
1988     /// user_mode, group_mode and other_mode. This method rewrites
1989     /// each user/group/other/special permission by default.
1990     /// @note
1991     ///   Adding one of the EModeRelative flags to mode change default
1992     ///   behavior that replace modes with passed values and allow
1993     ///   for relative mode change for any of user/group/other/special.
1994     ///   It is possible to keep it as is, or add/remove some permission
1995     ///   modes specified in parameters.
1996     /// @note
1997     ///   Passing "fDefault" will cause the corresponding mode
1998     ///   to be taken and set from its default setting.
1999     /// @param flags
2000     ///   Directory processing flags. Some popular sets of flags
2001     ///   combined together and listed below:
2002     ///   - eEntryOnly
2003     ///        change modes for the directory entry itself;
2004     ///   - eTopDirOnly
2005     ///        change modes for all files in the top directory only,
2006     ///        no for any subdirectory or files in it;
2007     ///   - eNonRecursive
2008     ///        change modes for all entries in the top directory only,
2009     ///        including subdirectory entries, but do not for any files
2010     ///        in them;
2011     ///   - eRecursive
2012     ///         change modes for all files and subdirectories recursively;
2013     ///   - eRecursiveIgnoreMissing
2014     ///        same as eRecursive, but do not report an error
2015     ///        for missed entries.
2016     /// @return
2017     ///   TRUE if permissions successfully set for all entries;  FALSE, otherwise.
2018     /// @sa
2019     ///   SetMode, SetDefaultMode, SetDefaultModeGlobal,
2020     ///   EMode, EModeRelative, EProcessingFlags
2021     virtual bool SetMode(TMode            user_mode,  // e.g. fDefault
2022                          TMode            group_mode  = fDefault,
2023                          TMode            other_mode  = fDefault,
2024                          TSpecialModeBits special     = 0,
2025                          TSetModeFlags    flags       = eEntryOnly) const;
2026 };
2027 
2028 
2029 /////////////////////////////////////////////////////////////////////////////
2030 ///
2031 /// CSymLink --
2032 ///
2033 /// Define class to work with symbolic links.
2034 ///
2035 /// Models the files in a file system. Basic functionality is derived from
2036 /// CDirEntry and extended for files.
2037 
2038 class NCBI_XNCBI_EXPORT CSymLink : public CDirEntry
2039 {
2040     typedef CDirEntry CParent;    ///< CDirEntry is the parent class
2041 
2042 public:
2043     /// Default constructor.
2044     CSymLink(void);
2045 
2046     /// Constructor using specified path string.
2047     CSymLink(const string& link);
2048 
2049     /// Copy constructor.
2050     CSymLink(const CDirEntry& link);
2051 
2052     /// Destructor.
2053     virtual ~CSymLink(void);
2054 
2055     /// Get a type of constructed object.
GetObjectType(void) const2056     virtual EType GetObjectType(void) const { return eLink; };
2057 
2058     /// Check existence of link.
2059     virtual bool Exists(void) const;
2060 
2061     /// Create symbolic link.
2062     ///
2063     /// @param path
2064     ///   Path to some entry that link will be pointed to.
2065     /// @return
2066     ///   TRUE if operation successful; FALSE, otherwise.
2067     ///   Return FALSE also if link already exists.
2068     bool Create(const string& path) const;
2069 
2070     /// Copy link.
2071     ///
2072     /// @param new_path
2073     ///   Target entry path/name.
2074     /// @param flags
2075     ///   Flags specified how to copy entry.
2076     /// @param buf_size
2077     ///   Size of buffer to read file.
2078     ///   Zero value means using default buffer size.
2079     /// @return
2080     ///   TRUE if operation successful; FALSE, otherwise.
2081     /// @sa
2082     ///   CDirEntry::TCopyFlags, CDirEntry::Copy, Create
2083     virtual bool Copy(const string& new_path, TCopyFlags flags = fCF_Default,
2084                       size_t buf_size = 0) const;
2085 };
2086 
2087 
2088 
2089 /////////////////////////////////////////////////////////////////////////////
2090 ///
2091 /// CFileUtil -- Utility functions.
2092 ///
2093 /// Throws an exceptions on error.
2094 ///
2095 /// NOTE: For some combinations of platform, file system, drivers and some
2096 ///       other unknown factors, the systems calls used to get system
2097 ///       information can return incorrect information about free/total
2098 ///       disk space, be aware.
2099 
2100 class NCBI_XNCBI_EXPORT CFileUtil
2101 {
2102 public:
2103     ///   Unix:
2104     ///       The path name to any file/dir withing file system.
2105     ///   MS Windows:
2106     ///       The path name to any file/dir withing file system.
2107     ///       The root directory of the disk, or UNC name
2108     ///       (for example, \\MyServer\MyShare\, C:\).
2109     ///   The "." can be used to get disk space on current disk.
2110 
2111     //// Type of file system
2112     enum EFileSystemType {
2113         eUnknown = 0,   ///< File system type could not be determined
2114 
2115         eADFS,          ///< Acorn's Advanced Disc Filing System
2116         eAdvFS,         ///< Tru64 UNIX Advanced File System
2117         eAFFS,          ///< Amiga Fast File System
2118         eAFS,           ///< AFS File System
2119         eAUTOFS,        ///< Automount File System
2120         eBEFS,          ///< The Be (BeOS) File System (BeFS)
2121         eBFS,           ///< Boot File System
2122         eCacheFS,       ///< Cache File System
2123         eCryptFS,       ///< eCryptfs (Enterprise Cryptographic Filesystem)
2124         eCDFS,          ///< ISO 9660 CD-ROM file system (CDFS/ISO9660)
2125         eCIFS,          ///< Common Internet File System
2126         eCODA,          ///< Coda File System
2127         eCOH,           ///< Coherent (System V)
2128         eCRAMFS,        ///< Compressed ROMFS
2129         eDebugFS,       ///< Debug File System (Linux)
2130         eDEVFS,         ///< Device File System
2131         eDFS,           ///< DCE Distributed File System (DCE/DFS)
2132         eEFS,           ///< The Encrypting File System (EFS) (MSWin)
2133         eEXOFS,         ///< EXtended Object File System (EXOFS)
2134         eExt,           ///< Extended file system
2135         eExt2,          ///< Second Extended file system
2136         eExt3,          ///< Journalled form of ext2
2137         eFAT,           ///< Traditional 8.3 MSDOS-style file system
2138         eFAT32,         ///< FAT32 file system
2139         eFDFS,          ///< File Descriptor File System
2140         eFFM,           ///< File-on-File Mounting file system
2141         eFFS,           ///< Fast File System (*BSD)
2142         eFUSE,          ///< Filesystem in Userspace (FUSE)
2143         eFUSE_CTL,      ///< Fusectl (helper filesystem for FUSE)
2144         eGFS2,          ///< Global File System
2145         eGPFS,          ///< IBM General Parallel File System
2146         eHFS,           ///< Hierarchical File System
2147         eHFSPLUS,       ///< Hierarchical File System
2148         eHPFS,          ///< OS/2 High-Performance File System
2149         eHSFS,          ///< High Sierra File System
2150         eJFS,           ///< Journalling File System
2151         eJFFS,          ///< Journalling Flash File System
2152         eJFFS2,         ///< Journalling Flash File System v2
2153         eLOFS,          ///< Loopback File System
2154         eMFS,           ///< Memory File System
2155         eMinix,         ///< Minix v1
2156         eMinix2,        ///< Minix v2
2157         eMinix3,        ///< Minix v3
2158         eMSFS,          ///< Mail Slot File System
2159         eNCPFS,         ///< NetWare Core Protocol File System
2160         eNFS,           ///< Network File System (NFS)
2161         eNTFS,          ///< New Technology File System
2162         eOCFS2,         ///< Oracle Cluster File System 2
2163         eOPENPROM,      ///< /proc/openprom filesystem
2164         ePANFS,         ///< Panasas FS
2165         ePROC,          ///< /proc file system
2166         ePVFS2,         ///< Parallel Virtual File System
2167         eReiserFS,      ///< Reiser File System
2168         eRFS,           ///< Remote File Share file system (AT&T RFS)
2169         eQNX4,          ///< QNX4 file system
2170         eROMFS,         ///< ROM File System
2171         eSELINUX,       ///< Security-Enhanced Linux (SELinux)
2172         eSMBFS,         ///< Samba File System
2173         eSPECFS,        ///< SPECial File System
2174         eSquashFS,      ///< Compressed read-only filesystem (Linux)
2175         eSYSFS,         ///< (Linux)
2176         eSYSV2,         ///< System V
2177         eSYSV4,         ///< System V
2178         eTMPFS,         ///< Virtual Memory File System (TMPFS/SHMFS)
2179         eUBIFS,         ///< The Unsorted Block Image File System
2180         eUDF,           ///< Universal Disk Format
2181         eUFS,           ///< UNIX File System
2182         eUFS2,          ///< UNIX File System
2183         eUSBDEVICE,     ///< USBDevice file system
2184         eV7,            ///< UNIX V7 File System
2185         eVxFS,          ///< VERITAS File System (VxFS)
2186         eVZFS,          ///< Virtuozzo File System (VZFS)
2187         eXENIX,         ///< Xenix (SysV) file system
2188         eXFS,           ///< XFS File System
2189         eXIAFS          ///<
2190     };
2191 
2192     /// Structure to store information about file system.
2193     struct SFileSystemInfo {
2194         EFileSystemType  fs_type;       ///< Type of filesystem
2195         Uint8            total_space;   ///< Total disk space in bytes
2196         Uint8            free_space;    ///< Free disk space in bytes
2197         Uint8            used_space;    ///< Used disk space in bytes
2198         unsigned long    block_size;    ///< Allocation unit (block) size
2199         unsigned long    filename_max;  ///< Maximum filename length
2200                                         ///< (part between slashes)
2201     };
2202 
2203     /// Get file system information.
2204     ///
2205     /// Get information for the user associated with the calling thread only.
2206     /// @param path
2207     ///   String that specifies filesystem for which information
2208     ///   is to be returned.
2209     /// @param info
2210     ///   Pointer to structure which receives file system information.
2211     static void GetFileSystemInfo(const string& path, SFileSystemInfo* info);
2212 
2213     /// Get free disk space information.
2214     ///
2215     /// Get information for the user associated with the calling thread only.
2216     /// If per-user quotas are in use, then the returned values may be less
2217     /// than the actual number of free bytes available on disk.
2218     /// @param path
2219     ///   String that specifies the file system for which to return
2220     ///   the number of free bytes available on disk.
2221     /// @return
2222     ///   The amount of free space in bytes.
2223     /// @sa
2224     ///   GetFileSystemInfo, GetTotalDiskSpace, GetUsedDiskSpace
2225     static Uint8 GetFreeDiskSpace(const string& path);
2226 
2227     /// Get used disk space information.
2228     ///
2229     /// Get information for the user associated with the calling thread only.
2230     /// If per-user quotas are in use, then the returned values may be less
2231     /// than the actual number of free bytes available on disk.
2232     /// @param path
2233     ///   String that specifies the file system for which to return
2234     ///   the number of used bytes on disk.
2235     /// @return
2236     ///   The amount of used space in bytes.
2237     /// @sa
2238     ///   GetFileSystemInfo, GetTotalDiskSpace, GetFreeDiskSpace
2239     static Uint8 GetUsedDiskSpace(const string& path);
2240 
2241     /// Get total disk space information.
2242     ///
2243     /// Get information for the user associated with the calling thread only.
2244     /// If per-user quotas are in use, then the returned value may be less
2245     /// than the actual total number of bytes on the disk.
2246     /// @param path
2247     ///   String that specifies the file system for which to return
2248     ///   the total disk space in bytes.
2249     /// @return
2250     ///   The amount of total disk space in bytes.
2251     /// @sa
2252     ///   GetFileSystemInfo, GetFreeDiskSpace, GetUsedDiskSpace
2253     static Uint8 GetTotalDiskSpace(const string& path);
2254 };
2255 
2256 
2257 
2258 /////////////////////////////////////////////////////////////////////////////
2259 ///
2260 /// CFileDeleteList --
2261 ///
2262 /// Define a list of dir entries for deletion.
2263 ///
2264 /// Each object of this class maintains a list of paths that will be deleted
2265 /// from the file system when the object goes out of scope.
2266 
2267 class NCBI_XNCBI_EXPORT CFileDeleteList : public CObject
2268 {
2269 public:
2270     /// Destructor removes all dir entries on list.
2271     ~CFileDeleteList();
2272 
2273     typedef list<string> TList;
2274 
2275     /// Add a path for later deletion.
2276     /// @param path
2277     ///   String that specifies the file system entry to delete.
2278     ///   It will be stored as the absolute normalized path, so relative names
2279     ///   are safe to use.
2280     /// @note
2281     ///   Directories will be removed recursively.
2282     ///   Symbolic links -- without dir entries which they points to.
2283     void Add(const string& path);
2284 
2285     /// Get the underlying list.
2286     const TList& GetList() const;
2287     /// Set the underlying list.
2288     void SetList(TList& list);
2289 
2290 private:
2291     TList  m_Paths;  ///< List of dir entries for deletion
2292 };
2293 
2294 
2295 /////////////////////////////////////////////////////////////////////////////
2296 ///
2297 /// CFileDeleteAtExit --
2298 ///
2299 /// This class is used to mark dir entries for deletion at application exit.
2300 /// @sa CFileDeleteList
2301 
2302 class NCBI_XNCBI_EXPORT CFileDeleteAtExit
2303 {
2304 public:
2305     /// Add the name of a dir entry; it will be deleted on (normal) exit
2306     static void Add(const string& path);
2307 
2308     /// Get underlying static CFileDeleteList object
2309     static const CFileDeleteList& GetDeleteList();
2310     /// Set the underlying static CFileDeleteList object
2311     static void SetDeleteList(CFileDeleteList& list);
2312 };
2313 
2314 
2315 /////////////////////////////////////////////////////////////////////////////
2316 ///
2317 /// CTmpFile --
2318 ///
2319 /// Define class to generate temporary file name (or use specified), which
2320 /// can be automatically removed on the object destruction.
2321 ///
2322 /// This class generate temporary file name in the temporary directory
2323 /// specified by OS. But this behavior can be changed, just set desired
2324 /// temporary directory using global parameter (see CParam class description)
2325 /// in the registry or environment (section 'NCBI', name 'TmpDir') and it
2326 /// will used by default in this class.
2327 /// @note
2328 ///   The files created this way are not really temporary. If application
2329 ///   terminates abnormally, that such files can be left on the file system.
2330 ///   To avoid this you can use CFile::CreateTmpFile().
2331 /// @sa CFile::CreateTmpFile, CFile::GetTmpName, CParam
2332 
2333 class NCBI_XNCBI_EXPORT CTmpFile : public CObject
2334 {
2335 public:
2336     /// What to do with the file on object destruction.
2337     enum ERemoveMode {
2338         eRemove,    ///< Remove file
2339         eNoRemove   ///< Do not remove file
2340     };
2341 
2342     /// Default constructor.
2343     ///
2344     /// Automatically generate temporary file name.
2345     CTmpFile(ERemoveMode remove_file = eRemove);
2346 
2347     /// Constructor.
2348     ///
2349     /// Use given temporary file name.
2350     CTmpFile(const string& file_name, ERemoveMode remove_file = eRemove);
2351 
2352     /// Destructor.
2353     ~CTmpFile(void);
2354 
2355     /// What to do if stream already exists in the AsInputFile/AsOutputFile.
2356     enum EIfExists {
2357         /// You can make call of AsInputFile/AsOutputFile only once,
2358         /// on each following call throws CFileException exception.
2359         eIfExists_Throw,
2360         /// Delete previous stream and return reference to new object.
2361         /// Invalidate all previously returned references.
2362         eIfExists_Reset,
2363         /// Return reference to current stream, create new one if it
2364         /// does not exists yet.
2365         eIfExists_ReturnCurrent
2366     };
2367 
2368     /// Create I/O stream on the base of our file.
2369     CNcbiIstream& AsInputFile (EIfExists if_exists,
2370                                IOS_BASE::openmode mode = IOS_BASE::in);
2371     CNcbiOstream& AsOutputFile(EIfExists if_exists,
2372                                IOS_BASE::openmode mode = IOS_BASE::out);
2373 
2374     /// Return used file name (generated or given in the constructor).
2375     const string& GetFileName(void) const;
2376 
2377 private:
2378     string      m_FileName;            ///< Name of temporary file.
2379     ERemoveMode m_RemoveOnDestruction; ///< Remove file on destruction
2380 
2381     // Automatic pointers to store I/O streams.
2382     unique_ptr<CNcbiIstream> m_InFile;
2383     unique_ptr<CNcbiOstream> m_OutFile;
2384 
2385 private:
2386     // Prevent copying
2387     CTmpFile(const CTmpFile&);
2388     CTmpFile& operator=(const CTmpFile&);
2389 };
2390 
2391 
2392 /////////////////////////////////////////////////////////////////////////////
2393 ///
2394 /// Forward declaration of struct containing OS-specific mem.-file handle.
2395 
2396 struct SMemoryFileHandle;
2397 struct SMemoryFileAttrs;
2398 
2399 
2400 /////////////////////////////////////////////////////////////////////////////
2401 ///
2402 /// CMemoryFile_Base --
2403 ///
2404 /// Define base class for support file memory mapping.
2405 
2406 class NCBI_XNCBI_EXPORT CMemoryFile_Base
2407 {
2408 public:
2409     typedef Int8 TOffsetType; // signed for POSIX compatibility
2410 
2411     /// Which operations are permitted in memory map file.
2412     typedef enum {
2413         eMMP_Read,        ///< Data can be read
2414         eMMP_Write,       ///< Data can be written
2415         eMMP_ReadWrite    ///< Data can be read and written
2416     } EMemMapProtect;
2417 
2418     /// Whether to share changes or not.
2419     typedef enum {
2420         eMMS_Shared,      ///< Changes are shared
2421         eMMS_Private      ///< Changes are private (write do not change file)
2422     } EMemMapShare;
2423 
2424     /// Memory file open mode.
2425     enum EOpenMode {
2426         eCreate,          ///< Create new file or rewrite existent with zeros.
2427         eOpen,            ///< Open existent file, throw exception otherwise.
2428         eExtend,          ///< Extend file size with zeros if it exist,
2429                           ///< throw exception otherwise.
2430         eDefault = eOpen  ///< Default open mode
2431     };
2432 
2433     /// Constructor.
2434     ///
2435     CMemoryFile_Base(void);
2436 
2437 
2438     /// Check if memory-mapping is supported by the C++ Toolkit on this
2439     /// platform.
2440     static bool IsSupported(void);
2441 
2442 
2443     /// What type of data access pattern will be used for mapped region.
2444     ///
2445     /// Advises the VM system that the a certain region of user mapped memory
2446     /// will be accessed following a type of pattern. The VM system uses this
2447     /// information to optimize work with mapped memory.
2448     ///
2449     /// NOTE: Works on UNIX platform only.
2450     /// @sa
2451     ///   EMemoryAdvise, MemoryAdvise
2452     typedef enum {
2453         eMMA_Normal      = eMADV_Normal,
2454         eMMA_Random      = eMADV_Random,
2455         eMMA_Sequential  = eMADV_Sequential,
2456         eMMA_WillNeed    = eMADV_WillNeed,
2457         eMMA_DontNeed    = eMADV_DontNeed,
2458         eMMA_DoFork      = eMADV_DoFork,
2459         eMMA_DontFork    = eMADV_DontFork,
2460         eMMA_Mergeable   = eMADV_Mergeable,
2461         eMMA_Unmergeable = eMADV_Unmergeable
2462     } EMemMapAdvise;
2463 
2464     /// Advise on memory map usage for specified region.
2465     ///
2466     /// @param addr
2467     ///   Address of memory region whose usage is being advised.
2468     /// @param len
2469     ///   Length of memory region whose usage is being advised.
2470     /// @param advise
2471     ///   Advise on expected memory usage pattern.
2472     /// @return
2473     ///   - TRUE, if memory advise operation successful.
2474     ///   - FALSE, if memory advise operation not successful, or is not supported
2475     ///     on current platform.
2476     /// @sa
2477     ///   EMemMapAdvise, MemMapAdvise
2478     static bool MemMapAdviseAddr(void* addr, size_t len, EMemMapAdvise advise);
2479 };
2480 
2481 
2482 
2483 /////////////////////////////////////////////////////////////////////////////
2484 ///
2485 /// CMemoryFileSegment --
2486 ///
2487 /// Define auxiliary class for mapping a memory file region of the file
2488 /// into the address space of the calling process.
2489 ///
2490 /// Throws an exceptions on error.
2491 
2492 class NCBI_XNCBI_EXPORT CMemoryFileSegment : public CMemoryFile_Base
2493 {
2494 public:
2495     /// Constructor.
2496     ///
2497     /// Maps a view of the file, represented by "handle", into the address
2498     /// space of the calling process.
2499     /// @param handle
2500     ///   Handle to view of the mapped file.
2501     /// @param attr
2502     ///   Specify operations permitted on memory mapped region.
2503     /// @param offset
2504     ///   The file offset where mapping is to begin.
2505     ///   Cannot accept values less than 0.
2506     /// @param length
2507     ///   Number of bytes to map. The parameter value should be more than 0.
2508     /// @sa
2509     ///   EMemMapProtect, EMemMapShare, GetPtr, GetSize, GetOffset
2510     CMemoryFileSegment(SMemoryFileHandle& handle,
2511                        SMemoryFileAttrs&  attrs,
2512                        TOffsetType        offset,
2513                        size_t             length);
2514 
2515     /// Destructor.
2516     ///
2517     /// Unmaps a mapped area of the file.
2518     ~CMemoryFileSegment(void);
2519 
2520     /// Get pointer to beginning of data.
2521     ///
2522     /// @return
2523     ///   - Pointer to start of data, or
2524     ///   - NULL if mapped to a file of zero length, or if not mapped.
2525     void* GetPtr(void) const;
2526 
2527     /// Get offset of the mapped area from beginning of file.
2528     ///
2529     /// @return
2530     ///   Offset in bytes of mapped area from beginning of the file.
2531     ///   Always return value passed in constructor even if data
2532     ///   was not successfully mapped.
2533     TOffsetType GetOffset(void) const;
2534 
2535     /// Get length of the mapped area.
2536     ///
2537     /// @return
2538     ///   - Length in bytes of the mapped area, or
2539     ///   - 0 if not mapped.
2540     size_t GetSize(void) const;
2541 
2542     /// Get pointer to beginning of really mapped data.
2543     ///
2544     /// When the mapping object is creating and the offset is not a multiple
2545     /// of the allocation granularity, that offset and length can be adjusted
2546     /// to match it. The "length" value will be automatically increased on the
2547     /// difference between passed and real offsets.
2548     /// @return
2549     ///   - Pointer to start of data, or
2550     ///   - NULL if mapped to a file of zero length, or if not mapped.
2551     /// @sa
2552     ///    GetRealOffset, GetRealSize, GetPtr
2553     void* GetRealPtr(void) const;
2554 
2555     /// Get real offset of the mapped area from beginning of file.
2556     ///
2557     /// This real offset is adjusted to system's memory allocation granularity
2558     /// value and can be less than requested "offset" in the constructor.
2559     /// @return
2560     ///   Offset in bytes of mapped area from beginning of the file.
2561     ///   Always return adjusted value even if data was not successfully mapped.
2562     /// @sa
2563     ///    GetRealPtr, GetRealSize, GetOffset
2564     TOffsetType GetRealOffset(void) const;
2565 
2566     /// Get real length of the mapped area.
2567     ///
2568     /// Number of really mapped bytes of file. This length value can be
2569     /// increased if "offset" is not a multiple of the allocation granularity.
2570     /// @return
2571     ///   - Length in bytes of the mapped area, or
2572     ///   - 0 if not mapped.
2573     /// @sa
2574     ///    GetRealPtr, GetRealOffset, GetSize
2575     size_t GetRealSize(void) const;
2576 
2577     /// Flush by writing all modified copies of memory pages to the
2578     /// underlying file.
2579     ///
2580     /// NOTE: By default data will be flushed in the destructor.
2581     /// @return
2582     ///   - TRUE, if all data was flushed successfully.
2583     ///   - FALSE, if not mapped or if an error occurs.
2584     bool Flush(void) const;
2585 
2586     /// Unmap file view from memory.
2587     ///
2588     /// @return
2589     ///   TRUE on success; or FALSE on error.
2590     bool Unmap(void);
2591 
2592     /// Advise on mapped memory map usage.
2593     ///
2594     /// @param advise
2595     ///   Advise on expected memory usage pattern.
2596     /// @return
2597     ///   - TRUE, if memory advise operation successful.
2598     ///   - FALSE, if memory advise operation not successful, or is not supported
2599     ///     on current platform.
2600     /// @sa
2601     ///   EMemMapAdvise, MemMapAdviseAddr
2602     bool MemMapAdvise(EMemMapAdvise advise) const;
2603 
2604 private:
2605     // Check that file is mapped, throw exception otherwise.
2606     void x_Verify(void) const;
2607 
2608 private:
2609     // Values for user
2610     void*   m_DataPtr;     ///< Pointer to the beginning of the mapped area.
2611                            ///> The user seen this one.
2612     TOffsetType   m_Offset;      ///< Requested starting offset of the
2613                            ///< mapped area from beginning of file.
2614     size_t  m_Length;      ///< Requested length of the mapped area.
2615 
2616     // Internal real values
2617     void*   m_DataPtrReal; ///< Real pointer to the beginning of the mapped
2618                            ///< area which should be fried later.
2619     TOffsetType   m_OffsetReal;  ///< Corrected starting offset of the
2620                            ///< mapped area from beginning of file.
2621     size_t  m_LengthReal;  ///< Corrected length of the mapped area.
2622 
2623     // Friend classes
2624     friend class CMemoryFile;
2625 
2626 private:
2627     // Prevent copying
2628     CMemoryFileSegment(const CMemoryFileSegment&);
2629     void operator=(const CMemoryFileSegment&);
2630 };
2631 
2632 
2633 
2634 /////////////////////////////////////////////////////////////////////////////
2635 ///
2636 /// CMemoryFileMap --
2637 ///
2638 /// Define class for support a partial file memory mapping.
2639 ///
2640 /// Note, that all mapped into memory file segments have equal protect and
2641 /// share attributes, because they restricted with file open mode.
2642 /// Note, that the mapping file must exists or can be create/extended.
2643 /// If file size changes after mapping, the effect of references to portions
2644 /// of the mapped region that correspond to added or removed portions of
2645 /// the file is unspecified.
2646 ///
2647 /// Throws an exceptions on error.
2648 
2649 class NCBI_XNCBI_EXPORT CMemoryFileMap : public CMemoryFile_Base
2650 {
2651 public:
2652     /// Constructor.
2653     ///
2654     /// Initialize the memory mapping on file "file_name".
2655     /// @param filename
2656     ///   Name of file to map to memory.
2657     /// @param protect_attr
2658     ///   Specify operations permitted on memory mapped file.
2659     /// @param share_attr
2660     ///   Specify if change to memory mapped file can be shared or not.
2661     /// @param mode
2662     ///   File open mode.
2663     /// @param max_file_len
2664     ///   The size of created file if 'mode' parameter is eCreate or eExtend.
2665     ///   File will be never truncated if open mode is eExtend and real file
2666     ///   size is more that specified maximum length.
2667     /// @sa
2668     ///   EMemMapProtect, EMemMapShare, EOpenMode
2669     /// @note
2670     ///   MS Windows: If file is open in eMMP_Read mode with eMMS_Private
2671     ///   protection, that memory pages will be mapped in exclusive mode,
2672     ///   and any other process cannot access the same file for writing.
2673     CMemoryFileMap(const string&  file_name,
2674                    EMemMapProtect protect_attr = eMMP_Read,
2675                    EMemMapShare   share_attr   = eMMS_Shared,
2676                    EOpenMode      mode         = eDefault,
2677                    Uint8          max_file_len = 0);
2678 
2679     /// Destructor.
2680     ///
2681     /// Calls Unmap() and cleans up memory.
2682     ~CMemoryFileMap(void);
2683 
2684     /// Map file segment.
2685     ///
2686     /// @param offset
2687     ///   The file offset where mapping is to begin. If the offset is not
2688     ///   a multiple of the allocation granularity, that it can be decreased
2689     ///   to match it. The "length" value will be automatically increased on
2690     ///   the difference between passed and real offsets. The real offset can
2691     ///   be obtained using GetRealOffset(). Cannot accept values less than 0.
2692     /// @param length
2693     ///   Number of bytes to map. This value can be increased if "offset"
2694     ///   is not a multiple of the allocation granularity.
2695     ///   The real length of mapped region can be obtained using
2696     ///   GetRealSize() method.
2697     ///   The value 0 means that all file size will be mapped.
2698     /// @return
2699     ///   - Pointer to start of data, or
2700     ///   - NULL if mapped to a file of zero length, or if not mapped.
2701     /// @sa
2702     ///   Unmap, GetOffset, GetSize, GetRealOffset, GetRealSize
2703     /// @note
2704     ///   MS Windows: If file is open in eMMP_Read mode with eMMS_Private
2705     ///   protection, that memory pages will be mapped in exclusive mode,
2706     ///   and any other process cannot access the same file for writing.
2707     void* Map(TOffsetType offset, size_t length);
2708 
2709     /// Unmap file segment.
2710     ///
2711     /// @param ptr
2712     ///   Pointer returned by Map().
2713     /// @return
2714     ///   TRUE on success; or FALSE on error.
2715     /// @sa
2716     ///   Map
2717     bool Unmap(void* ptr);
2718 
2719     /// Unmap all mapped segment.
2720     ///
2721     /// @return
2722     ///   TRUE on success; or FALSE on error.
2723     ///   In case of error some segments can be not unmapped.
2724     bool UnmapAll(void);
2725 
2726     /// Get offset of the mapped segment from beginning of the file.
2727     ///
2728     /// @param prt
2729     ///   Pointer to mapped data returned by Map().
2730     /// @return
2731     ///   Offset in bytes of mapped segment from beginning of the file.
2732     ///   Returned value is a value of "offset" parameter passed
2733     ///   to Map() method for specified "ptr".
2734     TOffsetType GetOffset(void* ptr) const;
2735 
2736     /// Get length of the mapped segment.
2737     ///
2738     /// @param prt
2739     ///   Pointer to mapped data returned by Map().
2740     /// @return
2741     ///   Length in bytes of the mapped area.
2742     ///   Returned value is a value of "length" parameter passed
2743     ///   to Map() method for specified "ptr".
2744     size_t GetSize(void* ptr) const;
2745 
2746     /// Get length of the mapped file.
2747     ///
2748     /// @return
2749     ///   Size in bytes of the mapped file.
2750     Int8 GetFileSize(void) const;
2751 
2752     /// Flush memory mapped file segment.
2753     ///
2754     /// Flush specified mapped segment by writing all modified copies of
2755     /// memory pages to the underlying file.
2756     ///
2757     /// NOTE: By default data will be flushed in the destructor.
2758     /// @param prt
2759     ///   Pointer to mapped data returned by Map().
2760     /// @return
2761     ///   - TRUE, if all data was flushed successfully.
2762     ///   - FALSE, if an error occurs.
2763     bool Flush(void* ptr) const;
2764 
2765     /// Get pointer to memory mapped file segment by pointer to data.
2766     ///
2767     /// @param prt
2768     ///   Pointer to mapped data returned by Map().
2769     /// @return
2770     ///   Pointer to memory file mapped segment.
2771     const CMemoryFileSegment* GetMemoryFileSegment(void* ptr) const;
2772 
2773     /// Advise on mapped memory map usage.
2774     ///
2775     /// @param advise
2776     ///   Advise on expected memory usage pattern.
2777     /// @return
2778     ///   - TRUE, if memory advise operation successful.
2779     ///   - FALSE, if memory advise operation not successful, or is not supported
2780     ///     on current platform.
2781     /// @sa
2782     ///   EMemMapAdvise, MemMapAdviseAddr
2783     bool MemMapAdvise(void* ptr, EMemMapAdvise advise) const;
2784 
2785     /// Shows filename of memory mapped file
2786     ///
2787     /// @return
2788     ///   Reference to a file name of memory mapped file
GetFileName() const2789     const string& GetFileName() const noexcept
2790     {
2791         return m_FileName;
2792     }
2793 
2794 protected:
2795     /// Open file mapping for file with name m_FileName.
2796     void x_Open(void);
2797     /// Unmap mapped memory and close mapped file.
2798     void x_Close(void);
2799     /// Create new file or rewrite existent with zeros.
2800     void x_Create(Uint8 size);
2801     /// Extend file size from 'size' to 'new_size' with zero bytes.
2802     /// Note, that 'new_size' should be greater that current file size 'size'.
2803     void x_Extend(Uint8 size, Uint8 new_size);
2804 
2805     /// Get pointer to memory mapped file segment by pointer to data.
2806     CMemoryFileSegment* x_GetMemoryFileSegment(void* ptr) const;
2807 
2808 protected:
2809     string              m_FileName;  ///< File name.
2810     SMemoryFileHandle*  m_Handle;    ///< Memory file handle.
2811     SMemoryFileAttrs*   m_Attrs;     ///< Specify operations permitted on
2812                                      ///< memory mapped file and mapping mode.
2813 
2814     typedef map<void*,CMemoryFileSegment*> TSegments;
2815     TSegments           m_Segments;  ///< Map of pointers to mapped segments.
2816 
2817 private:
2818     // Prevent copying
2819     CMemoryFileMap(const CMemoryFileMap&);
2820     void operator=(const CMemoryFileMap&);
2821 };
2822 
2823 
2824 
2825 /////////////////////////////////////////////////////////////////////////////
2826 ///
2827 /// CMemoryFile --
2828 ///
2829 /// Define class to support file memory mapping.
2830 ///
2831 /// This is a simple version of the CMemoryFileMap class supporting one
2832 /// mapped segment only.
2833 ///
2834 /// Note that the file being mapped must exist or can be created/extended.
2835 /// If file size changes after mapping, the effect of references to portions
2836 /// of the mapped region that correspond to added or removed portions of
2837 /// the file is unspecified.
2838 ///
2839 /// Throws exceptions on errors.
2840 
2841 class NCBI_XNCBI_EXPORT CMemoryFile : public CMemoryFileMap
2842 {
2843 public:
2844     /// Constructor.
2845     ///
2846     /// Initialize memory mapping for file "file_name".
2847     /// @param filename
2848     ///   Name of file to map to memory.
2849     /// @param protect_attr
2850     ///   Specify operations permitted on memory mapped file.
2851     /// @param share_attr
2852     ///   Specify if change to memory mapped file can be shared or not.
2853     /// @param offset
2854     ///   The file offset where mapping is to begin.
2855     /// @param length
2856     ///   Number of bytes to map.
2857     ///   The value 0 means that all file size will be mapped.
2858     /// @param mode
2859     ///   File open mode.
2860     /// @param max_file_len
2861     ///   The size of created file if 'mode' parameter is eCreate or eExtend.
2862     ///   File will be never truncated if open mode is eExtend and real file
2863     ///   size is more that specified maximum length.
2864     /// @sa
2865     ///   EMemMapProtect, EMemMapShare, EOpenMode
2866     /// @sa
2867     ///   EMemMapProtect, EMemMapShare, Map
2868     /// @note
2869     ///   MS Windows: If file is open in eMMP_Read mode with eMMS_Private
2870     ///   protection, that memory pages will be mapped in exclusive mode,
2871     ///   and any other process cannot access the same file for writing.
2872     CMemoryFile(const string&  file_name,
2873                 EMemMapProtect protect_attr = eMMP_Read,
2874                 EMemMapShare   share_attr   = eMMS_Shared,
2875                 TOffsetType    offset       = 0,
2876                 size_t         lendth       = 0,
2877                 EOpenMode      mode         = eDefault,
2878                 Uint8          max_file_len = 0);
2879 
2880     /// Map file.
2881     ///
2882     /// @param offset
2883     ///   The file offset where mapping is to begin. If the offset is not
2884     ///   a multiple of the allocation granularity, that it can be decreased
2885     ///   to match it. The "length" value will be automatically increased on
2886     ///   the difference between passed and real offsets. The real offset can
2887     ///   be obtained using GetRealOffset(). Cannot accept values less than 0.
2888     /// @param length
2889     ///   Number of bytes to map. This value can be increased if "offset"
2890     ///   is not a multiple of the allocation granularity.
2891     ///   The real length of mapped region can be obtained using
2892     ///   GetRealSize() method.
2893     ///   The value 0 means that file will be mapped from 'offset'
2894     ///   to the end of file.
2895     /// @return
2896     ///   - Pointer to start of data, or
2897     ///   - NULL if mapped to a file of zero length, or if not mapped.
2898     /// @sa
2899     ///   Unmap, GetPtr, GetOffset, GetSize, Extend
2900     void* Map(TOffsetType offset = 0, size_t length = 0);
2901 
2902     /// Unmap file if mapped.
2903     ///
2904     /// @return
2905     ///   TRUE on success; or FALSE on error.
2906     /// @sa
2907     ///   Map, Extend
2908     bool Unmap(void);
2909 
2910     /// Extend length of the mapped region.
2911     ///
2912     /// If the sum of the current offset (from Map() method) and new size of
2913     /// the mapped region is more than current file size, that file size will
2914     /// be increased, added space filed with zeros and mapped region will
2915     /// be remapped.
2916     /// @param new_length
2917     ///   New length of the mapped region.
2918     ///   The value 0 means that file will be mapped from 'offset'
2919     ///   to the end of file.
2920     /// @return
2921     ///   New pointer to start of data.
2922     /// @sa
2923     ///   GetPtr, GetOffset, GetSize
2924     void* Extend(size_t new_lendth = 0);
2925 
2926     /// Get pointer to beginning of data.
2927     ///
2928     /// @return
2929     ///   Pointer to start of data.
2930     /// @sa
2931     ///   Map, Extend
2932     void* GetPtr(void) const;
2933 
2934     /// Get offset of the mapped area from beginning of the file.
2935     ///
2936     /// @return
2937     ///   Offset in bytes of mapped area from beginning of the file.
2938     TOffsetType GetOffset(void) const;
2939 
2940     /// Get length of the mapped region.
2941     ///
2942     /// @return
2943     ///   - Length in bytes of the mapped region, or
2944     ///   - 0 if not mapped or file is empty.
2945     size_t GetSize(void) const;
2946 
2947     /// Flush by writing all modified copies of memory pages to the
2948     /// underlying file.
2949     ///
2950     /// NOTE: By default data will be flushed in the destructor.
2951     /// @return
2952     ///   - TRUE, if all data was flushed successfully.
2953     ///   - FALSE, if an error occurs.
2954     bool Flush(void) const;
2955 
2956     /// Advise on memory map usage.
2957     ///
2958     /// @param advise
2959     ///   Advise on expected memory usage pattern.
2960     /// @return
2961     ///   - TRUE, if memory advise operation successful.
2962     ///   - FALSE, if memory advise operation not successful, or is not supported
2963     ///     on current platform.
2964     /// @sa
2965     ///   EMemMapAdvise, MemMapAdviseAddr
2966     bool MemMapAdvise(EMemMapAdvise advise) const;
2967 
2968 private:
2969     // Check that file is mapped, throw exception otherwise.
2970     void x_Verify(void) const;
2971 
2972 private:
2973     void* m_Ptr;   ///< Pointer to mapped view of file.
2974 
2975 private:
2976     // Prevent copying
2977     CMemoryFile(const CMemoryFile&);
2978     void operator=(const CMemoryFile&);
2979 };
2980 
2981 
2982 
2983 /////////////////////////////////////////////////////////////////////////////
2984 //
2985 //  Find files algorithms
2986 //
2987 
2988 /// File finding flags
2989 enum EFindFiles {
2990     fFF_File       = (1 << 0),            ///< find files
2991     fFF_Dir        = (1 << 1),            ///< find directories
2992     fFF_All        = fFF_File | fFF_Dir,  ///< find files and directories
2993                                           ///< (used automatically if fFF_File or fFF_Dir has not specified)
2994     fFF_Recursive  = (1 << 2),            ///< descend into sub-dirs
2995     fFF_Nocase     = (1 << 3),            ///< case-insensitive name search
2996     fFF_Default    = fFF_All              ///< default behavior
2997 };
2998 /// Bitwise OR of "EFindFiles"
2999 typedef int TFindFiles;
3000 
3001 
3002 /// Find files in the specified directory
3003 template<class TFindFunc>
FindFilesInDir(const CDir & dir,const vector<string> & masks,const vector<string> & masks_subdir,TFindFunc & find_func,TFindFiles flags=fFF_Default)3004 void FindFilesInDir(const CDir&            dir,
3005                     const vector<string>&  masks,
3006                     const vector<string>&  masks_subdir,
3007                     TFindFunc&             find_func,
3008                     TFindFiles             flags = fFF_Default)
3009 {
3010     TFindFiles find_type = flags & fFF_All;
3011     if ( find_type == 0 ) {
3012         flags |= fFF_All;
3013     }
3014     unique_ptr<CDir::TEntries>
3015         contents(dir.GetEntriesPtr(kEmptyStr, CDir::fIgnoreRecursive | CDir::fIgnorePath));
3016     if (contents.get() == NULL) {
3017         // error
3018         return;
3019     }
3020 
3021     NStr::ECase use_case = (flags & fFF_Nocase) ? NStr::eNocase : NStr::eCase;
3022     string path;
3023 
3024     if ( dir.GetPath().length() ) {
3025         path = CDirEntry::AddTrailingPathSeparator(dir.GetPath());
3026     }
3027     ITERATE(CDir::TEntries, it, *contents) {
3028         CDirEntry& dir_entry = **it;
3029         string name = dir_entry.GetPath();
3030         dir_entry.Reset(CDirEntry::MakePath(path, name));
3031 
3032         TFindFiles entry_type = fFF_Dir | fFF_File; // unknown
3033         if ( CDirEntry::MatchesMask(name, masks, use_case) ) {
3034             if ( find_type != (fFF_Dir | fFF_File) ) {
3035                 // need to check actual entry type
3036                 entry_type = dir_entry.IsDir()? fFF_Dir: fFF_File;
3037             }
3038             if ( (entry_type & find_type) != 0 ) {
3039                 // entry type matches
3040                 find_func(dir_entry);
3041             }
3042         }
3043         if ( (flags & fFF_Recursive) &&
3044              (entry_type & fFF_Dir) /*possible dir*/ &&
3045              CDirEntry::MatchesMask(name, masks_subdir, use_case) &&
3046              (entry_type == fFF_Dir || dir_entry.IsDir()) /*real dir*/ ) {
3047             CDir nested_dir(dir_entry.GetPath());
3048             FindFilesInDir(nested_dir, masks, masks_subdir, find_func, flags);
3049         }
3050     }
3051     return;
3052 }
3053 
3054 
3055 /// Find files in the specified directory
3056 template<class TFindFunc>
FindFilesInDir(const CDir & dir,const CMask & masks,const CMask & masks_subdir,TFindFunc & find_func,TFindFiles flags=fFF_Default)3057 void FindFilesInDir(const CDir&   dir,
3058                     const CMask&  masks,
3059                     const CMask&  masks_subdir,
3060                     TFindFunc&    find_func,
3061                     TFindFiles    flags = fFF_Default)
3062 {
3063     TFindFiles find_type = flags & fFF_All;
3064     if ( find_type == 0 ) {
3065         flags |= fFF_All;
3066     }
3067     unique_ptr<CDir::TEntries>
3068         contents(dir.GetEntriesPtr(kEmptyStr, CDir::fIgnoreRecursive |  CDir::fIgnorePath));
3069     if (contents.get() == NULL) {
3070         // error
3071         return;
3072     }
3073 
3074     NStr::ECase use_case = (flags & fFF_Nocase) ? NStr::eNocase : NStr::eCase;
3075     string path;
3076 
3077     if ( dir.GetPath().length() ) {
3078         path = CDirEntry::AddTrailingPathSeparator(dir.GetPath());
3079     }
3080     ITERATE(CDir::TEntries, it, *contents) {
3081         CDirEntry& dir_entry = **it;
3082         string name = dir_entry.GetPath();
3083         dir_entry.Reset(CDirEntry::MakePath(path, name));
3084 
3085         TFindFiles entry_type = fFF_Dir | fFF_File; // unknown
3086         if ( masks.Match(name, use_case) ) {
3087             if ( find_type != (fFF_Dir | fFF_File) ) {
3088                 // need to check actual entry type
3089                 entry_type = dir_entry.IsDir()? fFF_Dir: fFF_File;
3090             }
3091             if ( (entry_type & find_type) != 0 ) {
3092                 // entry type matches
3093                 find_func(dir_entry);
3094             }
3095         }
3096         if ( (flags & fFF_Recursive) &&
3097              (entry_type & fFF_Dir) /*possible dir*/ &&
3098              masks_subdir.Match(name, use_case) &&
3099              (entry_type == fFF_Dir || dir_entry.IsDir()) /*real dir*/ ) {
3100             CDir nested_dir(dir_entry.GetPath());
3101             FindFilesInDir(nested_dir, masks, masks_subdir, find_func, flags);
3102         }
3103     }
3104     return;
3105 }
3106 
3107 
3108 
3109 /////////////////////////////////////////////////////////////////////////////
3110 ///
3111 /// Generic algorithm for file search
3112 ///
3113 /// Algorithm scans the provided directories using iterators,
3114 /// finds files to match the masks and stores all calls functor
3115 /// object for all found entries.
3116 /// Functor call should match: void Functor(const CDirEntry& dir_entry).
3117 ///
3118 /// The difference between FindFiles<> and FileFiles2<> is that last one
3119 /// use two different masks - one for dir entries (files and/or subdirs)
3120 /// and second for subdirectories, that will be used for recursive
3121 /// search. FindFiles<> use one set of masks for all subdirectories with
3122 /// recursive search.
3123 ///
3124 
3125 template<class TPathIterator,
3126          class TFindFunc>
FindFiles(TPathIterator path_begin,TPathIterator path_end,const vector<string> & masks,TFindFunc & find_func,TFindFiles flags=fFF_Default)3127 void FindFiles(TPathIterator         path_begin,
3128                TPathIterator         path_end,
3129                const vector<string>& masks,
3130                TFindFunc&            find_func,
3131                TFindFiles            flags = fFF_Default)
3132 {
3133     vector<string> masks_empty;
3134     for (; path_begin != path_end; ++path_begin) {
3135         const string& dir_name = *path_begin;
3136         CDir dir(dir_name);
3137         FindFilesInDir(dir, masks, masks_empty, find_func, flags);
3138     }
3139     return;
3140 }
3141 
3142 
3143 template<class TPathIterator,
3144          class TFindFunc>
FindFiles2(TPathIterator path_begin,TPathIterator path_end,const vector<string> & masks,const vector<string> & masks_subdir,TFindFunc & find_func,TFindFiles flags=fFF_Default)3145 void FindFiles2(TPathIterator         path_begin,
3146                 TPathIterator         path_end,
3147                 const vector<string>& masks,
3148                 const vector<string>& masks_subdir,
3149                 TFindFunc&            find_func,
3150                 TFindFiles            flags = fFF_Default)
3151 {
3152     for (; path_begin != path_end; ++path_begin) {
3153         const string& dir_name = *path_begin;
3154         CDir dir(dir_name);
3155         FindFilesInDir(dir, masks, masks_subdir, find_func, flags);
3156     }
3157     return;
3158 }
3159 
3160 
3161 /////////////////////////////////////////////////////////////////////////////
3162 ///
3163 /// Generic algorithm for file search
3164 ///
3165 /// Algorithm scans the provided directories using iterators,
3166 /// finds files to match the masks and stores all calls functor
3167 /// object for all found entries.
3168 /// Functor call should match: void Functor(const CDirEntry& dir_entry).
3169 ///
3170 
3171 template<class TPathIterator,
3172          class TMaskIterator,
3173          class TFindFunc>
FindFiles(TPathIterator path_begin,TPathIterator path_end,TMaskIterator mask_begin,TMaskIterator mask_end,TFindFunc & find_func,TFindFiles flags=fFF_Default)3174 void FindFiles(TPathIterator path_begin,
3175                TPathIterator path_end,
3176                TMaskIterator mask_begin,
3177                TMaskIterator mask_end,
3178                TFindFunc&    find_func,
3179                TFindFiles    flags = fFF_Default)
3180 {
3181     vector<string> masks;
3182     for (; mask_begin != mask_end; ++mask_begin) {
3183         masks.push_back(*mask_begin);
3184     }
3185     FindFiles(path_begin, path_end, masks, find_func, flags);
3186     return;
3187 }
3188 
3189 
3190 /////////////////////////////////////////////////////////////////////////////
3191 ///
3192 /// Generic algorithm for file search
3193 ///
3194 /// Algorithm scans the provided directories using iterators,
3195 /// finds files to match the masks and stores all calls functor
3196 /// object for all found entries.
3197 /// Functor call should match: void Functor(const CDirEntry& dir_entry).
3198 ///
3199 
3200 template<class TPathIterator,
3201          class TFindFunc>
FindFiles(TPathIterator path_begin,TPathIterator path_end,const CMask & masks,TFindFunc & find_func,TFindFiles flags=fFF_Default)3202 void FindFiles(TPathIterator path_begin,
3203                TPathIterator path_end,
3204                const CMask&  masks,
3205                TFindFunc&    find_func,
3206                TFindFiles    flags = fFF_Default)
3207 {
3208     CMaskFileName masks_empty;
3209     for (; path_begin != path_end; ++path_begin) {
3210         const string& dir_name = *path_begin;
3211         CDir dir(dir_name);
3212         FindFilesInDir(dir, masks, masks_empty, find_func, flags);
3213     }
3214     return;
3215 }
3216 
3217 
3218 template<class TPathIterator,
3219          class TFindFunc>
FindFiles2(TPathIterator path_begin,TPathIterator path_end,const CMask & masks,const CMask & masks_subdir,TFindFunc & find_func,TFindFiles flags=fFF_Default)3220 void FindFiles2(TPathIterator path_begin,
3221                 TPathIterator path_end,
3222                 const CMask&  masks,
3223                 const CMask&  masks_subdir,
3224                 TFindFunc&    find_func,
3225                 TFindFiles    flags = fFF_Default)
3226 {
3227     for (; path_begin != path_end; ++path_begin) {
3228         const string& dir_name = *path_begin;
3229         CDir dir(dir_name);
3230         FindFilesInDir(dir, masks, masks_subdir, find_func, flags);
3231     }
3232     return;
3233 }
3234 
3235 
3236 /// Functor for generic FindFiles, adds file name to the specified container
3237 template<class TNames>
3238 class CFindFileNamesFunc
3239 {
3240 public:
CFindFileNamesFunc(TNames & names)3241     CFindFileNamesFunc(TNames& names) : m_FileNames(&names) {}
3242 
operator ()(const CDirEntry & dir_entry)3243     void operator()(const CDirEntry& dir_entry)
3244     {
3245         m_FileNames->push_back(dir_entry.GetPath());
3246     }
3247 protected:
3248     TNames*  m_FileNames;
3249 };
3250 
3251 
3252 /////////////////////////////////////////////////////////////////////////////
3253 ///
3254 /// Utility algorithm scans the provided directories using iterators
3255 /// finds files to match the masks and stores all found files in
3256 /// the container object.
3257 ///
3258 
3259 template<class TContainer, class TPathIterator>
FindFiles(TContainer & out,TPathIterator first_path,TPathIterator last_path,const vector<string> & masks,TFindFiles flags=fFF_Default)3260 void FindFiles(TContainer&           out,
3261                TPathIterator         first_path,
3262                TPathIterator         last_path,
3263                const vector<string>& masks,
3264                TFindFiles            flags = fFF_Default)
3265 {
3266     CFindFileNamesFunc<TContainer> func(out);
3267     FindFiles(first_path, last_path, masks, func, flags);
3268 }
3269 
3270 template<class TContainer, class TPathIterator>
FindFiles2(TContainer & out,TPathIterator first_path,TPathIterator last_path,const vector<string> & masks,const vector<string> & masks_subdir,TFindFiles flags=fFF_Default)3271 void FindFiles2(TContainer&           out,
3272                 TPathIterator         first_path,
3273                 TPathIterator         last_path,
3274                 const vector<string>& masks,
3275                 const vector<string>& masks_subdir,
3276                 TFindFiles            flags = fFF_Default)
3277 {
3278     CFindFileNamesFunc<TContainer> func(out);
3279     FindFiles2(first_path, last_path, masks, masks_subdir, func, flags);
3280 }
3281 
3282 
3283 /////////////////////////////////////////////////////////////////////////////
3284 ///
3285 /// Utility algorithm scans the provided directories using iterators
3286 /// finds files to match the masks and stores all found files in
3287 /// the container object.
3288 ///
3289 
3290 template<class TContainer, class TPathIterator>
FindFiles(TContainer & out,TPathIterator first_path,TPathIterator last_path,const CMask & masks,TFindFiles flags=fFF_Default)3291 void FindFiles(TContainer&    out,
3292                TPathIterator  first_path,
3293                TPathIterator  last_path,
3294                const CMask&   masks,
3295                TFindFiles     flags = fFF_Default)
3296 {
3297     CFindFileNamesFunc<TContainer> func(out);
3298     FindFiles(first_path, last_path, masks, func, flags);
3299 }
3300 
3301 template<class TContainer, class TPathIterator>
FindFiles2(TContainer & out,TPathIterator first_path,TPathIterator last_path,const CMask & masks,const CMask & masks_subdir,TFindFiles flags=fFF_Default)3302 void FindFiles2(TContainer&    out,
3303                 TPathIterator  first_path,
3304                 TPathIterator  last_path,
3305                 const CMask&   masks,
3306                 const CMask&   masks_subdir,
3307                 TFindFiles     flags = fFF_Default)
3308 {
3309     CFindFileNamesFunc<TContainer> func(out);
3310     FindFiles2(first_path, last_path, masks, masks_subdir, func, flags);
3311 }
3312 
3313 
3314 /////////////////////////////////////////////////////////////////////////////
3315 ///
3316 /// Utility algorithm scans the provided directories using iterators
3317 /// finds files to match the masks and stores all found files in
3318 /// the container object.
3319 ///
3320 
3321 template<class TContainer, class TPathIterator, class TMaskIterator>
FindFiles(TContainer & out,TPathIterator first_path,TPathIterator last_path,TMaskIterator first_mask,TMaskIterator last_mask,TFindFiles flags=fFF_Default)3322 void FindFiles(TContainer&    out,
3323                TPathIterator  first_path,
3324                TPathIterator  last_path,
3325                TMaskIterator  first_mask,
3326                TMaskIterator  last_mask,
3327                TFindFiles     flags = fFF_Default)
3328 {
3329     CFindFileNamesFunc<TContainer> func(out);
3330     FindFiles(first_path, last_path, first_mask, last_mask, func, flags);
3331 }
3332 
3333 
3334 /////////////////////////////////////////////////////////////////////////////
3335 ///
3336 /// Utility function working like glob(): takes a pattern and fills the
3337 /// result list with files/directories matching the pattern.
3338 ///
3339 
3340 void NCBI_XNCBI_EXPORT FindFiles(const string& pattern,
3341                                  list<string>& result,
3342                                  TFindFiles flags);
3343 
3344 
3345 /// Comparator for directory entries names.
3346 ///
3347 /// Compares two directory entries lexicographically, allow to sort
3348 /// elements in ascending order. Could be used with a list of entries
3349 /// obtained via CDir::GetEntries() or FindFiles().
3350 /// @param mode
3351 ///   Entries sorting mode.
3352 /// @sa
3353 ///   CDir::GetEntries, FindFiles
3354 /// @code
3355 ///     CDir::TEntries entries = CDir(dir).GetEntries("*.*");
3356 ///     entries.sort(SCompareDirEntries());
3357 /// @endcode
3358 /// @code
3359 ///     vector<string> entries;
3360 ///     FindFiles(entries, ...);
3361 ///     std::sort(entries.begin(), entries.end(), SCompareDirEntries());
3362 /// @endcode
3363 
3364 struct SCompareDirEntries
3365 {
3366     /// Sorting mode
3367     enum ESort {
3368         ePath,   ///< Sort by full path (default)
3369         eDir,    ///< Directory name
3370         eName,   ///< Full file name
3371         eBase,   ///< Base file name
3372         eExt     ///< File extension
3373     };
3374     /// You can sort by up to 3 path components.
3375     /// If first components of both paths are equal, next one
3376     /// will be used for comparison, and etc.
3377     SCompareDirEntries(ESort s1 = ePath);
3378     SCompareDirEntries(ESort s1, ESort s2);
3379     SCompareDirEntries(ESort s1, ESort s2, ESort s3);
3380 
3381     /// Comparison operators
3382     bool operator()(const CDir::TEntry& e1, const CDir::TEntry& e2);
3383     bool operator()(const string& e1, const string& e2);
3384 
3385 private:
3386     int m_Sort[3];
3387 };
3388 
3389 
3390 
3391 /////////////////////////////////////////////////////////////////////////////
3392 ///
3393 /// Base class for CFileIO, CFileReader, CFileWriter, CFileReaderWriter.
3394 ///
3395 /// Defines common types.
3396 
3397 class NCBI_XNCBI_EXPORT CFileIO_Base
3398 {
3399 public:
3400     /// File open mode.
3401     enum EOpenMode {
3402         ///< Create a new file, or truncate an existing one.
3403         eCreate,
3404         ///< Create a new file, or fail if the file already exists.
3405         eCreateNew,
3406         ///< Open an existing file, or fail if the file does not exist.
3407         eOpen,
3408         ///< Open an existing file, or create a new one.
3409         eOpenAlways,
3410         /// Open an existing file and truncate its size to 0.
3411         /// Fail if the file does not exist.
3412         eTruncate
3413     };
3414 
3415     /// Which I/O operations permitted on the file.
3416     enum EAccessMode {
3417         eRead,        ///< File can be read.
3418         eWrite,       ///< File can be written.
3419         eReadWrite    ///< File can be read and written.
3420     };
3421 
3422     /// Sharing mode for opened file.
3423     /// @note
3424     ///   If OS does not support sharing mode for files, that it will be
3425     ///   ignored.  But you can use CFileLock to lock a file or its part.
3426     /// @sa CFileLock
3427     enum EShareMode {
3428         /// Enables subsequent open operations on the file that request read
3429         /// access. Otherwise, other processes cannot open the file for reading.
3430         eShareRead,
3431         /// Enables subsequent open operations on the file that request write
3432         /// access. Otherwise, other processes cannot open the file for writing.
3433         eShareWrite,
3434         /// Combines both eShareRead and eShareWrite modes.
3435         eShare,
3436         /// Open file for exclusive access. Disables any subsequent open
3437         /// operations on the file.
3438         eExclusive
3439     };
3440 
3441     /// Which starting point to use for the moves of the file pointer.
3442     enum EPositionMoveMethod {
3443         eBegin,       ///< Absolute position from beginning of the file.
3444         eCurrent,     ///< Relative to current position.
3445         eEnd          ///< The starting point is the current EOF position.
3446     };
3447 };
3448 
3449 
3450 /////////////////////////////////////////////////////////////////////////////
3451 ///
3452 /// Class for support low level input/output for files.
3453 ///
3454 /// Throw CFileException/CFileErrnoException on error.
3455 
3456 class NCBI_XNCBI_EXPORT CFileIO : public CFileIO_Base
3457 {
3458 public:
3459     /// Default constructor
3460     CFileIO(void);
3461 
3462     /// Destruct object closing system handle if necessary
3463     ~CFileIO(void);
3464 
3465     /// Open file.
3466     void Open(const string& filename, EOpenMode open_mode,
3467               EAccessMode access_mode, EShareMode share_mode = eShare);
3468 
3469     /// Controls how temporary file is removed.
3470     enum EAutoRemove {
3471         eDoNotRemove,           ///< Do not ever remove temporary file.
3472         eRemoveInClose,         ///< Remove temporary file immediately
3473                                 ///< after closing its handle in Close().
3474         eRemoveASAP,            ///< Remove the file at the earliest
3475                                 ///< possible moment (in CreateTemporary()
3476                                 ///< on UNIX).
3477     };
3478     /// Create temporary file in the specified directory.
3479     /// The prefix argument is used to generate a unique file name.
3480     void CreateTemporary(const string& dir, const string& prefix,
3481                          EAutoRemove auto_remove = eRemoveInClose);
3482 
3483     /// Close file.
3484     void Close(void);
3485 
3486     /// Read file.
3487     ///
3488     /// @return
3489     ///   The number of bytes actually read.
3490     ///   Can be less than 'count', zero indicates end of file.
3491     size_t Read(void* buf, size_t count) const;
3492 
3493     /// Write file.
3494     ///
3495     /// Always write all 'count' bytes of data to the file.
3496     /// @return
3497     ///   The number of bytes written; equal to 'count'.
3498     size_t Write(const void* buf, size_t count) const;
3499 
3500     /// Flush file buffers.
3501     void Flush(void) const;
3502 
3503     /// Return file path and name as it was specified in the
3504     /// Open() method or created in CreateTemporary().
GetPathname(void) const3505     const string& GetPathname(void) const { return m_Pathname; }
3506 
3507     /// Return system file handle associated with the file.
GetFileHandle(void) const3508     TFileHandle GetFileHandle(void) const { return m_Handle; };
3509 
3510     /// Close previous handle if needed and use given handle for all I/O.
3511     void SetFileHandle(TFileHandle handle);
3512 
3513     /// Get file position.
3514     ///
3515     /// @return
3516     ///   Current file position.
3517     Uint8 GetFilePos(void) const;
3518 
3519     /// Set file position from beginning of the file.
3520     void SetFilePos(Uint8 position) const;
3521 
3522     /// Set file position.
3523     ///
3524     /// @param offset
3525     ///   Defines a number of bytes to move the file pointer.  A positive value
3526     ///   moves the pointer from the position indicated by 'whence' forward in
3527     ///   the file, and a negative value backspaces the file pointer towards
3528     ///   the beginning of the file.
3529     ///
3530     /// @param whence
3531     ///    Defines a pointer move origin.
3532     void SetFilePos(Int8 offset, EPositionMoveMethod whence) const;
3533 
3534     /// Get file size.
3535     ///
3536     /// @return
3537     ///   Size of the file.
3538     Uint8 GetFileSize(void) const;
3539 
3540     /// Set new size for the file.
3541     ///
3542     /// This method can be used to truncate or extend the file.
3543     /// @note
3544     ///   The file must be opened with write access rights.
3545     ///   Function repositions the offset of the file descriptor to the EOF.
3546     /// @param length
3547     ///   New file size.
3548     ///   If the file was previously longer than length, bytes past "length"
3549     ///   will no longer be accessible.  If it was shorter, the contents of
3550     ///   the file between the old EOF position and the new position are
3551     ///   not defined.  Usually it will be read in as zeros, but this depends
3552     ///   on the OS.
3553     /// @param pos
3554     ///   Defines how to set current file position after changing file size.
3555     ///   eCurrent means that file position does not change, eBegin and eEnd
3556     ///   move it to the start or the end of the file accordingly.
3557     void SetFileSize(Uint8 length, EPositionMoveMethod pos = eCurrent) const;
3558 
3559     /// Define whether the open file handle needs to be closed
3560     /// in the destructor.
SetAutoClose(bool auto_close=true)3561     void SetAutoClose(bool auto_close = true) { m_AutoClose = auto_close; }
3562 
3563     /// Define whether the temporary file created by CreateTemporary()
3564     /// must be automatically removed in Close(). This method will
3565     /// also work for regular files created with Open().
SetAutoRemove(EAutoRemove auto_remove=eRemoveInClose)3566     void SetAutoRemove(EAutoRemove auto_remove = eRemoveInClose)
3567         { m_AutoRemove = auto_remove; }
3568 
3569 protected:
3570     string       m_Pathname;    ///< File path and name.
3571     TFileHandle  m_Handle;      ///< System file handle.
3572     bool         m_AutoClose;   ///< Need to close file handle in destructor.
3573     EAutoRemove  m_AutoRemove;  ///< When (if ever) should the temporary
3574                                 ///< file be removed.
3575 
3576 private:
3577     // prevent copying
3578     CFileIO(const CFileIO&);
3579     void operator=(const CFileIO&);
3580 };
3581 
3582 
3583 
3584 /////////////////////////////////////////////////////////////////////////////
3585 ///
3586 /// File based IReader/IWriter/IReaderWriter with low level IO for speed
3587 ///
3588 /// Throw CFileException/CFileErrnoException on error.
3589 
3590 class NCBI_XNCBI_EXPORT CFileReaderWriter_Base : public CFileIO_Base
3591 {
3592 public:
3593     /// Default constructor
CFileReaderWriter_Base(void)3594     CFileReaderWriter_Base(void) {};
3595     /// Return system file handle associated with the file.
GetFileHandle(void)3596     TFileHandle GetFileHandle(void) { return m_File.GetFileHandle(); };
3597     /// Get an underlaying file I/O object
GetFileIO(void)3598     CFileIO& GetFileIO(void) { return m_File; }
3599 
3600 protected:
3601     CFileIO  m_File;
3602 private:
3603     // prevent copying
3604     CFileReaderWriter_Base(const CFileReaderWriter_Base&);
3605     void operator=(const CFileReaderWriter_Base&);
3606 };
3607 
3608 
3609 class NCBI_XNCBI_EXPORT CFileReader : public IReader,
3610                                       public CFileReaderWriter_Base
3611 {
3612 public:
3613     /// Construct CFileReader for reading from the file with name 'filename'.
3614     /// Throw CFileErrnoException on error.
3615     CFileReader(const string& filename,
3616                 EShareMode share_mode = eShareRead);
3617     CFileReader(const char* filename,
3618                 EShareMode share_mode = eShareRead);
3619 
3620     /// Construct CFileReader for reading from system handle 'handle'.
3621     /// Specified handle should have read access right.
3622     CFileReader(TFileHandle handle);
3623 
3624     /// Return a new IReader object corresponding to the given
3625     /// filename, taking "-" (but not "./-") to read from the standard input.
3626     static IReader* New(const string& filename,
3627                         EShareMode share_mode = eShareRead);
3628 
3629     /// Virtual methods from IReader
3630     virtual ERW_Result Read(void* buf, size_t count, size_t* bytes_read = 0);
3631     virtual ERW_Result PendingCount(size_t* count);
3632 
3633 private:
3634     // prevent copying
3635     CFileReader(const CFileReader&);
3636     void operator=(const CFileReader&);
3637 };
3638 
3639 
3640 class NCBI_XNCBI_EXPORT CFileWriter : public IWriter,
3641                                       public CFileReaderWriter_Base
3642 {
3643 public:
3644     /// Construct CFileWriter for writing to the file with name 'filename'.
3645     /// Throw CFileErrnoException on error.
3646     CFileWriter(const string& filename,
3647                 EOpenMode  open_mode  = eCreate,
3648                 EShareMode share_mode = eShareRead);
3649     CFileWriter(const char* filename,
3650                 EOpenMode  open_mode  = eCreate,
3651                 EShareMode share_mode = eShareRead);
3652 
3653     /// Construct CFileWriter for writing to system handle 'handle'.
3654     /// Specified handle should have read/write access rights.
3655     CFileWriter(TFileHandle handle);
3656 
3657     /// Return a new IWriter object corresponding to the given
3658     /// filename, taking "-" (but not "./-") to write to the standard output.
3659     static IWriter* New(const string& filename,
3660                         EOpenMode  open_mode  = eCreate,
3661                         EShareMode share_mode = eShareRead);
3662 
3663     /// Virtual methods from IWriter
3664     virtual ERW_Result Write(const void* buf, size_t count,
3665                              size_t* bytes_written = 0);
3666     virtual ERW_Result Flush(void);
3667 
3668 private:
3669     // prevent copying
3670     CFileWriter(const CFileWriter&);
3671     void operator=(const CFileWriter&);
3672 };
3673 
3674 
3675 class NCBI_XNCBI_EXPORT CFileReaderWriter : public IReaderWriter,
3676                                             public CFileReaderWriter_Base
3677 {
3678 public:
3679     /// Construct CFileReaderWriter for reading/writing to/from
3680     /// the file with name 'filename'.
3681     /// Throw CFileErrnoException on error.
3682     CFileReaderWriter(const string& filename,
3683                       EOpenMode  open_mode  = eOpen,
3684                       EShareMode share_mode = eShareRead);
3685     CFileReaderWriter(const char* filename,
3686                       EOpenMode  open_mode  = eOpen,
3687                       EShareMode share_mode = eShareRead);
3688 
3689     /// Construct CFileReaderWriter for writing to system handle 'handle'.
3690     /// Specified handle should have read and write access rights.
3691     CFileReaderWriter(TFileHandle handle);
3692 
3693     /// Return a new IReaderWriter object corresponding to the given
3694     /// filename.
3695     static IReaderWriter* New(const string& filename,
3696                               EOpenMode  open_mode  = eOpen,
3697                               EShareMode share_mode = eShareRead);
3698 
3699     /// Virtual methods from IReaderWriter
3700     virtual ERW_Result Read(void* buf, size_t count, size_t* bytes_read = 0);
3701     virtual ERW_Result PendingCount(size_t* count);
3702     virtual ERW_Result Write(const void* buf, size_t count,
3703                              size_t* bytes_written = 0);
3704     virtual ERW_Result Flush(void);
3705 
3706 private:
3707     // prevent copying
3708     CFileReaderWriter(const CFileReaderWriter&);
3709     void operator=(const CFileReaderWriter&);
3710 };
3711 
3712 
3713 /////////////////////////////////////////////////////////////////////////////
3714 ///
3715 /// File locking
3716 ///
3717 /// Lock a given file (by file descriptor or the file name) to read/write.
3718 ///
3719 /// Notes:
3720 ///
3721 /// 1) On majority of Unix platforms all locks are advisory, this means that
3722 ///    cooperating processes may use locks to coordinate access to a file
3723 ///    between themselves, but programs are also free to ignore locks and
3724 ///    access the file in any way they choose to.
3725 ///    MS Windows supports only mandatory locks, and operating system fully
3726 ///    enforces them.
3727 ///
3728 /// 2) After locking the file you should work with this file using ONLY
3729 ///    specified file descriptor, or if the constructor with file name was
3730 ///    used, obtain a file descriptor from CFileLock object using method
3731 ///    GetFileHandle(). Because on Unix all locks associated with a file
3732 ///    for a given process are removed when any file descriptor for that
3733 ///    file is closed by that process, even if a lock was never requested
3734 ///    for that file descriptor. On Windows you cannot open the file for
3735 ///    writing, if it already have an exclusive lock, even established
3736 ///    by the same process.
3737 ///    So, often is better to open file somewhere else and pass its file
3738 ///    descriptor to CFileLock class. In this case you have more control
3739 ///    over file. But note that lock type should match to the file open mode.
3740 ///
3741 /// 3) If you close a file that have locks, the locks will be unlocked by
3742 ///    the operating system. However, the time it takes for the operating
3743 ///    system to unlock these locks depends upon available system resources.
3744 ///    Therefore, it is recommended that your process explicitly remove all
3745 ///    locks, before closing a file. If this is not done, access to file
3746 ///    may be denied if the operating system has not yet unlocked them.
3747 ///
3748 ///  4) Locks can be inherited or not by a child process, depending from OS.
3749 ///
3750 ///  5) Locked file cannot be empty. CFileLock can work with empty files,
3751 ///     depending from OS, but it is better to avoid this for compatibility.
3752 ///
3753 /// All methods of this class except the destructor throw exceptions
3754 /// CFileErrnoException on errors.
3755 
3756 class NCBI_XNCBI_EXPORT CFileLock
3757 {
3758 public:
3759     typedef Int8 TOffsetType; // signed for POSIX compatibility
3760 
3761     /// Type of file lock.
3762     ///
3763     /// Shared lock allows all processes to read from the locked portion
3764     /// of the file, while denying to write into it.
3765     /// Exclusive lock denies other processes both read and write to
3766     /// the locked portion of the file, while allowing the locking process
3767     /// to read or write through a specified or obtained file handle.
3768     typedef enum {
3769         eShared,       ///< "read" lock.
3770         eExclusive     ///< "write" lock.
3771     } EType;
3772 
3773     /// Flags, used in constructors.
3774     ///
3775     /// Default flag in each group have priority above non-default,
3776     /// if they are used together.
3777     enum EFlags {
3778         /// Lock file using parameters specified in constructor.
3779         fLockNow        = (1 << 1),
3780         fLockLater      = (1 << 2),
3781         /// Automatically remove all obtained locks in the destructor.
3782         /// Note, that you still can unlock any segment. All remaining locks
3783         /// will be removed in the destructor.
3784         fAutoUnlock     = (1 << 3),
3785         fNoAutoUnlock   = (1 << 4),
3786         /// Default flags
3787         fDefault        = fLockNow | fAutoUnlock
3788     };
3789     typedef unsigned int TFlags;   ///< Binary OR of "EFlags"
3790 
3791 
3792     /// Construct CFileLock for locking a file with a given name 'filename'.
3793     /// File will be automatically closed in destructor and all locks removed.
3794     /// Throw CFileException if file doesn't exist, or on error.
3795     /// @sa Lock, Unlock, GetFileHandle
3796     CFileLock(const string& filename,
3797               TFlags flags  = fDefault,
3798               EType  type   = eShared,
3799               TOffsetType offset = 0,
3800               size_t length = 0);
3801     CFileLock(const char* filename,
3802               TFlags flags  = fDefault,
3803               EType  type   = eShared,
3804               TOffsetType offset = 0,
3805               size_t length = 0);
3806 
3807     /// Construct CFileLock for locking file by system file handle 'handle'.
3808     /// @note
3809     ///   The file will not be closed at CFileLock destruction.
3810     /// @sa Lock, LockSegment
3811     CFileLock(TFileHandle handle,
3812               TFlags flags  = fDefault,
3813               EType  type   = eShared,
3814               TOffsetType offset = 0,
3815               size_t length = 0);
3816 
3817     /// Destruct the CFileLock, close file and remove all locks if necessary.
3818     ~CFileLock(void);
3819 
3820     /// Lock file
3821     ///
3822     /// Lock whole file, or the part of the file.
3823     /// Previous lock will be removed. It do not remove locks,
3824     /// established on the file somewhere else.
3825     /// Throw CFileException if the lock cannot be obtained (since someone
3826     /// else has it locked already), or on error.
3827     /// @param type
3828     ///   Type of the lock, one of eShared or eExclusive.
3829     /// @param offset
3830     ///   The file offset where lock starts. Cannot accept values less than 0.
3831     /// @param length
3832     ///   Number of bytes to lock.
3833     ///   The value 0 means that whole file will be locked.
3834     /// @sa Unlock
3835     void Lock(EType type, TOffsetType offset = 0, size_t length = 0);
3836 
3837     /// Unlock file.
3838     ///
3839     /// Unlock range of the file previously locked using Lock() method.
3840     /// The file remains open. Note, that this method cannot remove locks,
3841     /// established on the file somewhere else. Only closing a file can
3842     /// unlock all locks.
3843     /// @sa Lock
3844     void Unlock(void);
3845 
3846     /// Return system file handle.
3847     ///
3848     /// If you want to read/write from/to the file, you should work with it
3849     /// using only the file descriptor, obtained using this method.
3850     /// It can be the same file descriptor as was given in the constructor.
3851     /// @return
3852     ///   File descriptor associated with the file.
GetFileHandle(void)3853     TFileHandle GetFileHandle(void) { return m_Handle; };
3854 
3855 protected:
3856     /// Auxiliary method for constructors.
3857     void x_Init(const char* filename, EType type, TOffsetType offset, size_t length);
3858 
3859 private:
3860     TFileHandle    m_Handle;      ///< System file handle.
3861     bool           m_CloseHandle; ///< Need to close file handle in destructor.
3862     TFlags         m_Flags;       ///< General flags.
3863     bool           m_IsLocked;    ///< Lock established.
3864     AutoPtr<SLock> m_Lock;        ///< Offset and length of the locked area.
3865 
3866 private:
3867     // Prevent copying
3868     CFileLock(const CFileLock&);
3869     void operator=(const CFileLock&);
3870 };
3871 
3872 
3873 /* @} */
3874 
3875 
3876 
3877 //////////////////////////////////////////////////////////////////////////////
3878 //
3879 // Inline
3880 //
3881 
3882 
3883 // CDirEntry
3884 
3885 inline
CDirEntry(void)3886 CDirEntry::CDirEntry(void)
3887 {
3888     return;
3889 }
3890 
3891 inline
GetPath(void) const3892 const string& CDirEntry::GetPath(void) const
3893 {
3894     return m_Path;
3895 }
3896 
3897 inline
GetName(void) const3898 string CDirEntry::GetName(void) const
3899 {
3900     string title, ext;
3901     SplitPath(GetPath(), 0, &title, &ext);
3902     return title + ext;
3903 }
3904 
3905 inline
GetBase(void) const3906 string CDirEntry::GetBase(void) const
3907 {
3908     string base;
3909     SplitPath(GetPath(), 0, &base);
3910     return base;
3911 }
3912 
3913 inline
GetExt(void) const3914 string CDirEntry::GetExt(void) const
3915 {
3916     string ext;
3917     SplitPath(GetPath(), 0, 0, &ext);
3918     return ext;
3919 }
3920 
3921 inline
IsFile(EFollowLinks follow) const3922 bool CDirEntry::IsFile(EFollowLinks follow) const
3923 {
3924     return GetType(follow) == eFile;
3925 }
3926 
3927 inline
IsDir(EFollowLinks follow) const3928 bool CDirEntry::IsDir(EFollowLinks follow) const
3929 {
3930     return GetType(follow) == eDir;
3931 }
3932 
3933 inline
IsLink(void) const3934 bool CDirEntry::IsLink(void) const
3935 {
3936     return GetType(eIgnoreLinks) == eLink;
3937 }
3938 
3939 #if !defined(NCBI_OS_MSWIN)
3940 // Default implementation. See Windows-specific implementation in the .cpp file
3941 inline
Exists(void) const3942 bool CDirEntry::Exists(void) const
3943 {
3944     return GetType() != eUnknown;
3945 }
3946 #endif
3947 
3948 inline
MatchesMask(const string & name,const string & mask,NStr::ECase use_case)3949 bool CDirEntry::MatchesMask(const string& name, const string& mask,
3950                             NStr::ECase use_case)
3951 {
3952     return NStr::MatchesMask(name, mask, use_case);
3953 }
3954 
3955 inline
MatchesMask(const string & name,const CMask & mask,NStr::ECase use_case)3956 bool CDirEntry::MatchesMask(const string& name, const CMask& mask,
3957                             NStr::ECase use_case)
3958 {
3959     return mask.Match(name, use_case);
3960 }
3961 
3962 inline
CopyToDir(const string & dir,TCopyFlags flags,size_t buf_size) const3963 bool CDirEntry::CopyToDir(const string& dir, TCopyFlags flags,
3964                           size_t buf_size) const
3965 {
3966     string path = MakePath(dir, GetName());
3967     return Copy(path, flags, buf_size);
3968 }
3969 
3970 inline
MoveToDir(const string & dir,TRenameFlags flags)3971 bool CDirEntry::MoveToDir(const string& dir, TRenameFlags flags)
3972 {
3973     string path = MakePath(dir, GetName());
3974     return Rename(path, flags);
3975 }
3976 
3977 inline
GetBackupSuffix(void)3978 const char* CDirEntry::GetBackupSuffix(void)
3979 {
3980     return m_BackupSuffix;
3981 }
3982 
3983 inline
SetBackupSuffix(const char * suffix)3984 void CDirEntry::SetBackupSuffix(const char* suffix)
3985 {
3986     m_BackupSuffix = const_cast<char*>(suffix);
3987 }
3988 
3989 inline
GetDefaultModeT() const3990 mode_t CDirEntry::GetDefaultModeT() const
3991 {
3992     return MakeModeT(m_DefaultMode[eUser],  m_DefaultMode[eGroup],
3993                      m_DefaultMode[eOther], m_DefaultMode[eSpecial]);
3994 }
3995 
3996 
3997 
3998 // CFile
3999 
4000 inline
CFile(void)4001 CFile::CFile(void)
4002 {
4003     SetDefaultMode(eFile, fDefault, fDefault, fDefault);
4004 }
4005 
4006 
4007 inline
CFile(const string & filename)4008 CFile::CFile(const string& filename) : CParent(filename)
4009 {
4010     SetDefaultMode(eFile, fDefault, fDefault, fDefault);
4011 }
4012 
4013 inline
CFile(const CDirEntry & file)4014 CFile::CFile(const CDirEntry& file) : CParent(file)
4015 {
4016     return;
4017 }
4018 
4019 inline
Exists(void) const4020 bool CFile::Exists(void) const
4021 {
4022     return IsFile();
4023 }
4024 
4025 
4026 // CDir
4027 
4028 inline
CDir(void)4029 CDir::CDir(void)
4030 {
4031     SetDefaultMode(eDir, fDefault, fDefault, fDefault);
4032 }
4033 
4034 inline
CDir(const string & dirname)4035 CDir::CDir(const string& dirname) : CParent(dirname)
4036 {
4037     SetDefaultMode(eDir, fDefault, fDefault, fDefault);
4038 }
4039 
4040 inline
CDir(const CDirEntry & dir)4041 CDir::CDir(const CDirEntry& dir) : CDirEntry(dir)
4042 {
4043     return;
4044 }
4045 
4046 inline
Exists(void) const4047 bool CDir::Exists(void) const
4048 {
4049     return IsDir();
4050 }
4051 
4052 inline CDir::TEntries
GetEntries(const string & mask,EGetEntriesMode mode,NStr::ECase use_case) const4053 CDir::GetEntries(const string&    mask,
4054                  EGetEntriesMode  mode,
4055                  NStr::ECase      use_case) const
4056 {
4057     if (use_case == NStr::eNocase) mode |= fNoCase;
4058     return GetEntries(mask, mode);
4059 }
4060 
4061 inline CDir::TEntries
GetEntries(const vector<string> & masks,EGetEntriesMode mode,NStr::ECase use_case) const4062 CDir::GetEntries(const vector<string>&  masks,
4063                  EGetEntriesMode        mode,
4064                  NStr::ECase            use_case) const
4065 {
4066     if (use_case == NStr::eNocase) mode |= fNoCase;
4067     return GetEntries(masks, mode);
4068 }
4069 
4070 inline CDir::TEntries
GetEntries(const CMask & masks,EGetEntriesMode mode,NStr::ECase use_case) const4071 CDir::GetEntries(const CMask&     masks,
4072                  EGetEntriesMode  mode,
4073                  NStr::ECase      use_case) const
4074 {
4075     if (use_case == NStr::eNocase) mode |= fNoCase;
4076     return GetEntries(masks, mode);
4077 }
4078 
4079 inline CDir::TEntries*
GetEntriesPtr(const string & mask,EGetEntriesMode mode,NStr::ECase use_case) const4080 CDir::GetEntriesPtr(const string&    mask,
4081                     EGetEntriesMode  mode,
4082                     NStr::ECase      use_case) const
4083 {
4084     if (use_case == NStr::eNocase) mode |= fNoCase;
4085     return GetEntriesPtr(mask, mode);
4086 }
4087 
4088 inline CDir::TEntries*
GetEntriesPtr(const vector<string> & masks,EGetEntriesMode mode,NStr::ECase use_case) const4089 CDir::GetEntriesPtr(const vector<string>&  masks,
4090                     EGetEntriesMode        mode,
4091                     NStr::ECase            use_case) const
4092 {
4093     if (use_case == NStr::eNocase) mode |= fNoCase;
4094     return GetEntriesPtr(masks, mode);
4095 }
4096 
4097 inline CDir::TEntries*
GetEntriesPtr(const CMask & masks,EGetEntriesMode mode,NStr::ECase use_case) const4098 CDir::GetEntriesPtr(const CMask&     masks,
4099                     EGetEntriesMode  mode,
4100                     NStr::ECase      use_case) const
4101 {
4102     if (use_case == NStr::eNocase) mode |= fNoCase;
4103     return GetEntriesPtr(masks, mode);
4104 }
4105 
4106 
4107 // SCompareDirEntries
4108 
4109 inline
operator ()(const CDir::TEntry & e1,const CDir::TEntry & e2)4110 bool SCompareDirEntries::operator()(const CDir::TEntry& e1, const CDir::TEntry& e2)
4111 {
4112     return operator()(e1->GetPath(), e2->GetPath());
4113 }
4114 
4115 
4116 // CSymLink
4117 
4118 inline
CSymLink(void)4119 CSymLink::CSymLink(void)
4120 {
4121     return;
4122 }
4123 
4124 inline
CSymLink(const string & link)4125 CSymLink::CSymLink(const string& link) : CParent(link)
4126 {
4127     // We dont need SetDefaultMode() here
4128     return;
4129 }
4130 
4131 inline
CSymLink(const CDirEntry & link)4132 CSymLink::CSymLink(const CDirEntry& link) : CDirEntry(link)
4133 {
4134     return;
4135 }
4136 
4137 inline
Exists(void) const4138 bool CSymLink::Exists(void) const
4139 {
4140     return IsLink();
4141 }
4142 
4143 
4144 // CFileDelete*
4145 
4146 inline
Add(const string & path)4147 void CFileDeleteList::Add(const string& path)
4148 {
4149     string p = CDirEntry::NormalizePath(CDirEntry::CreateAbsolutePath(path));
4150     m_Paths.push_back(p);
4151 }
4152 
4153 inline
GetList(void) const4154 const CFileDeleteList::TList& CFileDeleteList::GetList(void) const
4155 {
4156     return m_Paths;
4157 }
4158 
4159 inline
SetList(CFileDeleteList::TList & list)4160 void CFileDeleteList::SetList(CFileDeleteList::TList& list)
4161 {
4162     m_Paths = list;
4163 }
4164 
4165 
4166 // CMemoryFile_Base
4167 
4168 inline
MemMapAdviseAddr(void * addr,size_t len,EMemMapAdvise advise)4169 bool CMemoryFile_Base::MemMapAdviseAddr(void* addr, size_t len,
4170                                         EMemMapAdvise advise)
4171 {
4172     return MemoryAdvise(addr, len, (EMemoryAdvise)advise);
4173 }
4174 
4175 
4176 // CMemoryFileSegment
4177 
4178 inline
GetPtr(void) const4179 void* CMemoryFileSegment::GetPtr(void) const
4180 {
4181     return m_DataPtr;
4182 }
4183 
4184 inline
GetSize(void) const4185 size_t CMemoryFileSegment::GetSize(void) const
4186 {
4187     return m_Length;
4188 }
4189 
4190 
4191 inline
GetOffset(void) const4192 CMemoryFileSegment::TOffsetType CMemoryFileSegment::GetOffset(void) const
4193 {
4194     return m_Offset;
4195 }
4196 
4197 inline
GetRealPtr(void) const4198 void* CMemoryFileSegment::GetRealPtr(void) const
4199 {
4200     return m_DataPtrReal;
4201 }
4202 
4203 inline
GetRealSize(void) const4204 size_t CMemoryFileSegment::GetRealSize(void) const
4205 {
4206     return m_LengthReal;
4207 }
4208 
4209 
4210 inline
GetRealOffset(void) const4211 CMemoryFileSegment::TOffsetType CMemoryFileSegment::GetRealOffset(void) const
4212 {
4213     return m_OffsetReal;
4214 }
4215 
4216 inline
MemMapAdvise(EMemMapAdvise advise) const4217 bool CMemoryFileSegment::MemMapAdvise(EMemMapAdvise advise) const
4218 {
4219     if ( !m_DataPtr ) {
4220         return false;
4221     }
4222     return MemMapAdviseAddr(m_DataPtrReal, m_LengthReal, advise);
4223 }
4224 
4225 
4226 // CMemoryFileMap
4227 
4228 inline const CMemoryFileSegment*
GetMemoryFileSegment(void * ptr) const4229 CMemoryFileMap::GetMemoryFileSegment(void* ptr) const
4230 {
4231     return x_GetMemoryFileSegment(ptr);
4232 }
4233 
4234 inline
GetOffset(void * ptr) const4235 CMemoryFileMap::TOffsetType CMemoryFileMap::GetOffset(void* ptr) const
4236 {
4237     return GetMemoryFileSegment(ptr)->GetOffset();
4238 }
4239 
4240 inline
GetSize(void * ptr) const4241 size_t CMemoryFileMap::GetSize(void* ptr) const
4242 {
4243     return GetMemoryFileSegment(ptr)->GetSize();
4244 }
4245 
4246 inline
Flush(void * ptr) const4247 bool CMemoryFileMap::Flush(void* ptr) const
4248 {
4249     return GetMemoryFileSegment(ptr)->Flush();
4250 }
4251 
4252 inline
MemMapAdvise(void * ptr,EMemMapAdvise advise) const4253 bool CMemoryFileMap::MemMapAdvise(void* ptr, EMemMapAdvise advise) const
4254 {
4255     return GetMemoryFileSegment(ptr)->MemMapAdvise(advise);
4256 }
4257 
4258 
4259 
4260 // CMemoryFile
4261 
4262 inline
GetPtr(void) const4263 void* CMemoryFile::GetPtr(void) const
4264 {
4265     return m_Ptr;
4266 }
4267 
4268 inline
GetSize(void) const4269 size_t CMemoryFile::GetSize(void) const
4270 {
4271     // Special case: file is not mapped and its length is zero.
4272     if (!m_Ptr  &&  GetFileSize() == 0) {
4273         return 0;
4274     }
4275     x_Verify();
4276     return CMemoryFileMap::GetSize(m_Ptr);
4277 }
4278 
4279 inline
GetOffset(void) const4280 CMemoryFile::TOffsetType CMemoryFile::GetOffset(void) const
4281 {
4282     x_Verify();
4283     return CMemoryFileMap::GetOffset(m_Ptr);
4284 }
4285 
4286 inline
Flush(void) const4287 bool CMemoryFile::Flush(void) const
4288 {
4289     x_Verify();
4290     return CMemoryFileMap::Flush(m_Ptr);
4291 }
4292 
4293 inline
MemMapAdvise(EMemMapAdvise advise) const4294 bool CMemoryFile::MemMapAdvise(EMemMapAdvise advise) const
4295 {
4296     x_Verify();
4297     return CMemoryFileMap::MemMapAdvise(m_Ptr, advise);
4298 }
4299 
4300 
4301 END_NCBI_SCOPE
4302 
4303 #endif  /* CORELIB___NCBIFILE__HPP */
4304