1 // Copyright (C) 1999-2005 Open Source Telecom Corporation.
2 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
3 // Copyright (C) 2015 Cherokees of Idaho.
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free software
19 // library without restriction.  Specifically, if other files instantiate
20 // templates or use macros or inline functions from this file, or you compile
21 // this file and link it with other files to produce an executable, this
22 // file does not by itself cause the resulting executable to be covered by
23 // the GNU General Public License.  This exception does not however
24 // invalidate any other reasons why the executable file might be covered by
25 // the GNU General Public License.
26 //
27 // This exception applies only to the code released under the name GNU
28 // Common C++.  If you copy code from other releases into a copy of GNU
29 // Common C++, as the General Public License permits, the exception does
30 // not apply to the code that you add in this way.  To avoid misleading
31 // anyone as to the status of such modified files, you must delete
32 // this exception notice from them.
33 //
34 // If you write modifications of your own for GNU Common C++, it is your choice
35 // whether to permit this exception to apply to your modifications.
36 // If you do not wish that, delete this exception notice.
37 //
38 
39 /**
40  * @file file.h
41  * @short Files and dynamic loader services.
42  **/
43 
44 #ifndef COMMONCPP_FILE_H_
45 #define COMMONCPP_FILE_H_
46 
47 #ifndef COMMONCPP_CONFIG_H_
48 #include <commoncpp/config.h>
49 #endif
50 
51 #ifndef COMMONCPP_THREAD_H_
52 #include <commoncpp/thread.h>
53 #endif
54 
55 #ifndef COMMONCPP_EXCEPTION_H_
56 #include <commoncpp/exception.h>
57 #endif
58 
59 #ifndef WIN32
60 # ifdef __BORLANDC__
61 #  include <stdio.h>
62 #  include <sys/types.h>
63 # else
64 #  include <fcntl.h>
65 #  include <cstdio>
66 # endif
67 # include <dirent.h>
68 # include <sys/stat.h>
69 # include <sys/mman.h>
70 #else
71 # if __BORLANDC__ >= 0x0560
72 #  include <dirent.h>
73 #  include <sys/stat.h>
74 # else
75 #  include <direct.h>
76 # endif
77 #endif
78 
79 namespace ost {
80 
81 typedef unsigned long pos_t;
82 #ifndef _MSWINDOWS_
83 // use a define so that if the sys/types.h header already defines caddr_t
84 // as it may on BSD systems, we do not break it by redefining again.
85 #undef  caddr_t
86 #define caddr_t char *
87 typedef size_t ccxx_size_t;
88 #else
89 typedef DWORD ccxx_size_t;
90 #endif
91 
92 #ifndef PATH_MAX
93 #define PATH_MAX    256
94 #endif
95 
96 #ifndef NAME_MAX
97 #define NAME_MAX    64
98 #endif
99 
100 class __EXPORT File
101 {
102 public:
103     enum Error {
104         errSuccess = 0,
105         errNotOpened,
106         errMapFailed,
107         errInitFailed,
108         errOpenDenied,
109         errOpenFailed,
110         errOpenInUse,
111         errReadInterrupted,
112         errReadIncomplete,
113         errReadFailure,
114         errWriteInterrupted,
115         errWriteIncomplete,
116         errWriteFailure,
117         errLockFailure,
118         errExtended
119     };
120     typedef enum Error Error;
121 
122     enum Access {
123 #ifndef _MSWINDOWS_
124         accessReadOnly = O_RDONLY,
125         accessWriteOnly= O_WRONLY,
126         accessReadWrite = O_RDWR
127 #else
128         accessReadOnly = GENERIC_READ,
129         accessWriteOnly = GENERIC_WRITE,
130         accessReadWrite = GENERIC_READ | GENERIC_WRITE
131 #endif
132     };
133     typedef enum Access Access;
134 
135 protected:
136     typedef struct _fcb {
137         struct _fcb *next;
138         caddr_t address;
139         ccxx_size_t len;
140         off_t pos;
141         bool locked;
142     } fcb_t;
143 
144 public:
145 #ifdef  _MSWINDOWS_
146     enum Open {
147         openReadOnly, // = FILE_OPEN_READONLY,
148         openWriteOnly, // = FILE_OPEN_WRITEONLY,
149         openReadWrite, // = FILE_OPEN_READWRITE,
150         openAppend, // = FILE_OPEN_APPEND,
151         openTruncate // = FILE_OPEN_TRUNCATE
152     };
153 #else
154     enum Open {
155         openReadOnly = O_RDONLY,
156         openWriteOnly = O_WRONLY,
157         openReadWrite = O_RDWR,
158         openAppend = O_WRONLY | O_APPEND,
159 #ifdef  O_SYNC
160         openSync = O_RDWR | O_SYNC,
161 #else
162         openSync = O_RDWR,
163 #endif
164         openTruncate = O_RDWR | O_TRUNC
165     };
166     typedef enum Open Open;
167 
168 /* to be used in future */
169 
170 #ifndef S_IRUSR
171 #define S_IRUSR 0400
172 #define S_IWUSR 0200
173 #define S_IRGRP 0040
174 #define S_IWGRP 0020
175 #define S_IROTH 0004
176 #define S_IWOTH 0002
177 #endif
178 
179 #endif // !WIN32
180 
181 #ifndef _MSWINDOWS_
182     enum Attr {
183         attrInvalid = 0,
184         attrPrivate = S_IRUSR | S_IWUSR,
185         attrGroup = attrPrivate | S_IRGRP | S_IWGRP,
186         attrPublic = attrGroup | S_IROTH | S_IWOTH
187     };
188 #else // defined WIN32
189     enum Attr {
190         attrInvalid=0,
191         attrPrivate,
192         attrGroup,
193         attrPublic
194     };
195 #endif // !WIN32
196     typedef enum Attr Attr;
197 
198 #ifdef  _MSWINDOWS_
199     enum Complete {
200         completionImmediate, // = FILE_COMPLETION_IMMEDIATE,
201         completionDelayed, // = FILE_COMPLETION_DELAYED,
202         completionDeferred // = FILE_COMPLETION_DEFERRED
203     };
204 
205     enum Mapping {
206         mappedRead,
207         mappedWrite,
208         mappedReadWrite
209     };
210 #else
211     enum Mapping {
212         mappedRead = accessReadOnly,
213         mappedWrite = accessWriteOnly,
214         mappedReadWrite = accessReadWrite
215     };
216     enum Complete {
217         completionImmediate,
218         completionDelayed,
219         completionDeferred
220     };
221 #endif
222     typedef enum Complete Complete;
223     typedef enum Mapping Mapping;
224 
225 public:
226     static const char *getExtension(const char *path);
227     static const char *getFilename(const char *path);
228     static char *getFilename(const char *path, char *buffer, size_t size = NAME_MAX);
229     static char *getDirname(const char *path, char *buffer, size_t size = PATH_MAX);
230     static char *getRealpath(const char *path, char *buffer, size_t size = PATH_MAX);
231 };
232 
233 /**
234  * A low level portable directory class.  Used to support ccstd Directory
235  * container.  This provides a basic mechanism for allocating and
236  * accessing file entries.
237  *
238  * @author David Sugar <dyfet@ostel.com>
239  * @short low level directory access class.
240  */
241 class __EXPORT Dir : public File
242 {
243 private:
244 #ifndef _MSWINDOWS_
245     DIR *dir;
246     struct dirent *save;
247     char save_space[sizeof(struct dirent) + PATH_MAX + 1];
248     struct dirent *entry;
249 #else
250     HANDLE hDir;
251     WIN32_FIND_DATA data, fdata;
252     char *name;
253 #endif
254 
255     __DELETE_COPY(Dir);
256 
257 public:
258     Dir(const char *name = NULL);
259 
260     static bool create(const char *path, Attr attr = attrGroup);
261     static bool remove(const char *path);
262     static bool setPrefix(const char *path);
263     static bool getPrefix(char *path, size_t size = PATH_MAX);
264 
265     void open(const char *name);
266     void close(void);
267 
268     virtual ~Dir();
269 
270     const char *getName(void);
271 
272     const char *operator++() {
273         return getName();
274     }
275 
276     const char *operator++(int) {
277         return getName();
278     }
279 
280     const char *operator*();
281 
282     bool rewind(void);
283 
284     bool operator!()  const {
285 #ifndef _MSWINDOWS_
286         return !dir;
287 #else
288         return hDir == INVALID_HANDLE_VALUE;
289 #endif
290     }
291 
292     operator bool() const {
293 #ifndef _MSWINDOWS_
294         return dir;
295 #else
296         return hDir != INVALID_HANDLE_VALUE;
297 #endif
298     }
299 
300     bool isValid(void) const;
301 };
302 
303 /**
304  * A generic class to walk a hierarchical directory structure.
305  *
306  * @author David Sugar <dyfet@ostel.com>
307  * @short Directory tree walking.
308  */
309 class __EXPORT  DirTree
310 {
311 private:
312     char path[PATH_MAX + 1];
313     Dir *dir;
314     unsigned max, current, prefixpos;
315 
316     __DELETE_COPY(DirTree);
317 
318 protected:
319     /**
320      * Virtual method to filter results.  Virtual override methods
321      * should call baseclass method to assure . and .. names are
322      * stripped out.
323      *
324      * @return true if current filename is accepted.
325      * @param file path to examine
326      * @param ino info of type, date, etc.
327      */
328     virtual bool filter(const char *file, struct stat *ino);
329 
330 public:
331     /**
332      * Construct a directory tree walk starting at the specified
333      * prefix.  A maximum subdirectory depth is also specified.
334      *
335      * @param prefix to start walk.
336      * @param maxdepth subdirectory depth to examine.
337      */
338     DirTree(const char *prefix, unsigned maxdepth);
339 
340     /**
341      * Construct an un-opened directory tree of a known maximum depth
342      *
343      * @param maxdepth subdirectory subdirectory depth.
344      */
345     DirTree(unsigned maxdepth);
346 
347     virtual ~DirTree();
348 
349     /**
350      * Open a directory tree path.
351      *
352      * @param prefix directory path to open.
353      */
354     void open(const char *prefix);
355 
356     /**
357      * Close the directory path.
358      */
359     void close(void);
360 
361     /**
362      * Extract the next full pathname from the directory walk.
363      * When returning directories, a '/' is appended.  The
364      * returned string is a buffer of MAX_PATH size.
365      *
366      * @return path of next subdirectory entry or NULL.
367      */
368     char *getPath(void);
369 
370     /**
371      * This is used to step through the filter virtual for an
372      * entire subtree, and is used for cases where a derived
373      * DirTree class performs it's primary operations through
374      * filter rather than externally by calling getPath().
375      *
376      * @return number of files and directories examined.
377      * @param prefix directory path to examine.
378      */
379     unsigned perform(const char *prefix);
380 };
381 
382 /**
383  * The purpose of this class is to define a base class for low level
384  * random file access that is portable between Win32 and Posix systems.
385  * This class is a foundation both for optimized thread shared and
386  * traditional locked file access that is commonly used to build
387  * database services, rather than the standard C++ streaming file classes.
388  *
389  * @author David Sugar <dyfet@ostel.com>
390  * @short Portable random disk file access.
391  */
392 class __EXPORT RandomFile : protected Mutex, public File
393 {
394 private:
395     Error errid;
396     char *errstr;
397 
398 protected:
399 #ifndef _MSWINDOWS_
400     int fd;
401     // FIXME: WIN32 as no access member
402     Access access;
403 #else
404     HANDLE fd;
405 #endif
406     char *pathname;
407 
408     struct {
409         unsigned count : 16;
410         bool thrown : 1;
411         bool initial : 1;
412 #ifndef _MSWINDOWS_
413         bool immediate : 1;
414 #endif
415         bool temp : 1;
416     } flags;
417 
418     /**
419      * Create an unopened random access file.
420      */
421     RandomFile(const char *name = NULL);
422 
423     /**
424      * Default copy constructor.
425      */
426     RandomFile(const RandomFile &rf);
427 
428     /**
429      * Post an error event.
430      *
431      * @return error code.
432      * @param errid error code.
433      * @param errstr error message string.
434      */
435     Error error(Error errid, char *errstr = NULL);
436 
437     /**
438      * Post an extended string error message.
439      *
440      * @return errExtended.
441      * @param err error string.
442      */
error(char * err)443     inline Error error(char *err) {
444         return error(errExtended, err);
445     }
446 
447     /**
448      * Used to enable or disable throwing of exceptions on
449      * errors.
450      *
451      * @param enable true if errors will be thrown.
452      */
setError(bool enable)453     inline void setError(bool enable) {
454         flags.thrown = !enable;
455     }
456 
457 #ifndef _MSWINDOWS_
458     /**
459      * Used to set file completion modes.
460      *
461      * @return errSuccess if okay.
462      * @param mode completion mode.
463      * @todo implement in win32
464      */
465     Error setCompletion(Complete mode);
466 #endif
467 
468     /**
469      * Used to set the temporary attribute for the file.  Temporary
470      * files are automatically deleted when closed.
471      *
472      * @param enable true for marking as temporary.
473      */
setTemporary(bool enable)474     inline void setTemporary(bool enable) {
475         flags.temp = enable;
476     }
477 
478     /**
479      * This method is used to initialize a newly created file as
480      * indicated by the "initial" flag.  This method also returns
481      * the file access permissions that should be associated with
482      * the file.  This method should never be called directly, but
483      * is instead used to impliment the "Initial" method.  Typically
484      * one would use this to build an empty database shell when a
485      * previously empty database file is created.
486      *
487      * @return access, or attrInvalid if should be removed.
488      */
489     virtual Attr initialize(void);
490 
491     /**
492      * Close the file.
493      */
494     void final(void);
495 
496 public:
497     /**
498      * Destroy a random access file or it's derived class.
499      */
500     virtual ~RandomFile();
501 
502     /**
503      * This method should be called right after a RandomFile derived
504      * object has been created.  This method will invoke initialize
505      * if the object is newly created, and set file access permissions
506      * appropriately.
507      *
508      * @return true if file had to be initialized.
509      */
510     bool initial(void);
511 
512     /**
513      * Get current file capacity.
514      *
515      * @return total file size.
516      */
517     off_t getCapacity(void);
518 
519     /**
520      * This method is commonly used to close and re-open an existing
521      * database.  This may be used when the database has been unlinked
522      * and an external process provides a new one to use.
523      */
524     virtual Error restart(void);
525 
526     /**
527      * Return current error id.
528      *
529      * @return last error identifier set.
530      */
getErrorNumber(void)531     inline Error getErrorNumber(void) const {
532         return errid;
533     }
534 
535     /**
536      * Return current error string.
537      *
538      * @return last error string set.
539      */
getErrorString(void)540     inline char *getErrorString(void) const {
541         return errstr;
542     }
543 
544     operator bool() const;
545 
546     bool operator!(void) const;
547 };
548 
549 /**
550  * This class defines a database I/O file service that can be shared
551  * by multiple processes.  Each thread should access a dup of the database
552  * object, and mutex locks can be used to preserve transaction
553  * integrety if multiple threads are used.
554  *
555  * SharedFile is used when a database may be shared between multiple
556  * processes.  SharedFile automatically applies low level byte-range "file
557  * locks", and provides an interface to fetch and release byte-range locked
558  * portions of a file.
559  *
560  * @author David Sugar <dyfet@ostel.com>
561  * @short This class defines a database I/O file service that can be shared by multiple processes.
562  */
563 class __EXPORT SharedFile : public RandomFile
564 {
565 private:
566     fcb_t fcb;
567     Error open(const char *path);
568 
569 public:
570     /**
571      * Open or create a new database file.  You should also use
572      * Initial.
573      *
574      * @param path pathname of database to open.
575      */
576     SharedFile(const char *path);
577 
578     /**
579      * Create a shared file as a duplicate of an existing shared
580      * file.
581      *
582      * @param file original file.
583      */
584     SharedFile(const SharedFile &file);
585 
586     /**
587      * Close and finish a database file.
588      */
589     virtual ~SharedFile();
590 
591     /**
592      * Restart an existing database; close and re-open.
593      *
594      * @return errSuccess if successful.
595      */
restart(void)596     Error restart(void) {
597         return open(pathname);
598     }
599 
600     /**
601      * Lock and Fetch a portion of the file into physical memory.
602      * This can use state information to fetch the current record
603      * multiple times.
604      *
605      * @return errSuccess on success.
606      * @param address  address to use, or NULL if same as last I/O.
607      * @param length   length to use, or 0 if same as last I/O.
608      * @param position file position to use -1 if same as last I/O.
609      */
610     Error fetch(caddr_t address = NULL, ccxx_size_t length = 0, off_t position = -1);
611 
612     /**
613      * Update a portion of a file from physical memory.  This can use
614      * state information to commit the last read record.  The current
615      * lock is also cleared.
616      *
617      * @return errSuccess on success.
618      * @param address  address to use, or NULL if same as last I/O.
619      * @param length   length to use, or 0 if same as last I/O.
620      * @param position file position to use or -1 if same as last I/O.
621      */
622     Error update(caddr_t address = NULL, ccxx_size_t length = 0, off_t position = -1);
623 
624     /**
625      * Clear a lock held from a previous fetch operation without
626      * updating.
627      *
628      * @return errSuccess on success.
629      * @param length length to use, or 0 if same as last I/O.
630      * @param pos    file position to use or -1 if same as last I/O.
631      */
632     Error clear(ccxx_size_t length = 0, off_t pos = -1);
633 
634     /**
635      * Add new data to the end of the file.  Locks file during append.
636      *
637      * @param address address to use, or NULL if same as last I/O.
638      * @param length  length to use, or 0 if same as last I/O.
639      */
640     Error append(caddr_t address = NULL, ccxx_size_t length = 0);
641 
642     /**
643      * Fetch the current file position marker for this thread.
644      *
645      * @return file position offset.
646      */
647     off_t getPosition(void);
648 
649     bool operator++(void);
650     bool operator--(void);
651 };
652 
653 /**
654  * Create and map a disk file into memory.  This portable class works
655  * under both Posix via mmap and under the win32 API. A mapped file
656  * can be referenced directly by it's memory segment. One can map
657  * and unmap portions of a file on demand, and update
658  * changed memory pages mapped from files immediately through sync().
659  *
660  * @author David Sugar <dyfet@ostel.com>
661  * @short Map a named disk file into memory.
662  */
663 class __EXPORT MappedFile : public RandomFile
664 {
665 private:
666     fcb_t fcb;
667     int prot;
668 #ifdef  _MSWINDOWS_
669     HANDLE map;
670     char mapname[64];
671 #endif
672 
673     __DELETE_COPY(MappedFile);
674 
675 public:
676     /**
677      * Open a file for mapping.  More than one segment of a file
678      * may be mapped into seperate regions of memory.
679      *
680      * @param fname file name to access for mapping.
681      * @param mode  access mode to map file.
682      */
683     MappedFile(const char *fname, Access mode);
684 
685     /**
686      * Create if not exists, and map a file of specified size
687      * into memory.
688      *
689      * @param fname file name to access for mapping.
690      * @param mode access mode to map file.
691      * @param size of file to map.
692      */
693     MappedFile(const char *fname, Access mode, size_t size);
694 
695     /**
696      * Map a portion or all of a specified file in the specified
697      * shared memory access mode.  Valid mapping modes include
698      * mappedRead, mappedWrite, and mappedReadWrite.
699      *
700      * @param fname pathname of file to map into memory.
701      * @param offset from start of file to begin mapping in bytes.
702      * @param size of mapped area in bytes.
703      * @param mode to map file.
704      */
705     MappedFile(const char *fname, pos_t offset, size_t size, Access mode);
706 
707     /**
708      * Release a mapped section of memory associated with a file.  The
709      * mapped area is updated back to disk.
710      */
711     virtual ~MappedFile();
712 
713     // FIXME: not use library function in header ??
714     /**
715      * Synchronize the contents of the mapped portion of memory with
716      * the disk file and wait for completion.  This assures the memory
717      * mapped from the file is written back.
718      */
719     void sync(void);
720 
721     /**
722      * Synchronize a segment of memory mapped from a segment fetch.
723      *
724      * @param address memory address to update.
725      * @param len size of segment.
726      */
727     void sync(caddr_t address, size_t len);
728 
729     /**
730      * Map a portion of the memory mapped from the file back to the
731      * file and do not wait for completion.  This is useful when mapping
732      * a database file and updating a single record.
733      *
734      * @param offset offset into the mapped region of memory.
735      * @param len length of partial region (example, record length).
736      */
737     void update(size_t offset = 0, size_t len = 0);
738 
739     /**
740      * Update a mapped region back to disk as specified by address
741      * and length.
742      *
743      * @param address address of segment.
744      * @param len length of segment.
745      */
746     void update(caddr_t address, size_t len);
747 
748     /**
749      * Release (unmap) a memory segment.
750      *
751      * @param address address of memory segment to release.
752      * @param len length of memory segment to release.
753      */
754     void release(caddr_t address, size_t len);
755 
756     /**
757      * Fetch a pointer to an offset within the memory mapped portion
758      * of the disk file.  This really is used for convience of matching
759      * operations between Update and Fetch, as one could simply have
760      * accessed the base pointer where the file was mapped directly.
761      *
762      * @param offset from start of mapped memory.
763      */
764     inline caddr_t fetch(size_t offset = 0) {
765         return ((char *)(fcb.address)) + offset;
766     }
767 
768     /**
769      * Fetch and map a portion of a disk file to a logical memory
770      * block.
771      *
772      * @return pointer to memory segment.
773      * @param pos offset of file segment to map.
774      * @param len size of memory segment to map.
775      */
776     caddr_t fetch(off_t pos, size_t len);
777 
778     /**
779      * Lock the currently mapped portion of a file.
780      *
781      * @return true if pages are locked.
782      */
783     bool lock(void);
784 
785     /**
786      * Unlock a locked mapped portion of a file.
787      */
788     void unlock(void);
789 
790     /**
791      * Compute map size to aligned page boundry.
792      *
793      * @param size request.
794      * @return page aligned size.
795      */
796     size_t pageAligned(size_t size);
797 };
798 
799 
800 /**
801  * The DSO dynamic loader class is used to load object files.  On
802  * elf based systems this is typically done with dlopen.  A dummy
803  * stub class is generated for non-dl capable systems.
804  *
805  * @author David Sugar <dyfet@ostel.com>
806  * @short Dynamic class file loader.
807  */
808 class __EXPORT DSO
809 {
810 private:
811     const char *err;
812     static Mutex mutex;
813     static DSO *first;
814     static DSO *last;
815     DSO *next, *prev;
816     const char *id;
817     void *image;
818 
819     typedef ucommon::dso::addr_t addr_t;
820 
821     __DELETE_COPY(DSO);
822 
823 protected:
824     void loader(const char *filename, bool resolve);
825 
826 public:
827     /**
828      * Construct and load a DSO object file.
829      *
830      * @param filename pathname of object file to load.
831      */
DSO(const char * filename)832     DSO(const char *filename) {
833         loader(filename, true);
834     }
835 
DSO(const char * filename,bool resolve)836     DSO(const char *filename, bool resolve) {
837         loader(filename, resolve);
838     }
839 
840     /**
841      * Retrieve error indicator associated with DSO failure.  This
842      * is often used in catch handlers.
843      */
getError(void)844     inline const char *getError(void) const {
845         return err;
846     }
847 
848     /**
849      * Detach a DSO object from running memory.
850      */
851     virtual ~DSO();
852 
853     /**
854      * Lookup a symbol in the loaded file.
855      */
856     addr_t operator[](const char *sym);
857 
858     static void dynunload(void);
859 
860     /**
861      * Find a specific DSO object by filename.
862      *
863      * @param name of DSO object file (partial).
864      */
865     static DSO *getObject(const char *name);
866 
867     /**
868      * See if DSO object is valid.
869      *
870      * @return true if valid.
871      */
872     bool isValid(void);
873 
874     /**
875      * Install debug handler...
876      */
877     static void setDebug(void);
878 };
879 
880 /** @relates RandomFile */
881 bool __EXPORT isDir(const char *path);
882 /** @relates RandomFile */
883 bool __EXPORT isFile(const char *path);
884 #ifndef WIN32
885 /** @relates RandomFile */
886 bool __EXPORT isDevice(const char *path);
887 #else
888 /** @relates RandomFile */
isDevice(const char * path)889 inline bool isDevice(const char *path) {
890     return false;
891 }
892 #endif
893 /** @relates RandomFile */
894 bool __EXPORT canAccess(const char *path);
895 /** @relates RandomFile */
896 bool __EXPORT canModify(const char *path);
897 /** @relates RandomFile */
898 time_t __EXPORT lastModified(const char *path);
899 /** @relates RandomFile */
900 time_t __EXPORT lastAccessed(const char *path);
901 
902 #ifdef  COMMON_STD_EXCEPTION
903 
904 class DirException : public IOException
905 {
906 public:
DirException(const String & str)907     DirException(const String &str) : IOException(str) {};
908 };
909 
910 class __EXPORT DSOException : public IOException
911 {
912 public:
DSOException(const String & str)913     DSOException(const String &str) : IOException(str) {};
914 };
915 
916 class __EXPORT FileException : public IOException
917 {
918 public:
FileException(const String & str)919     FileException(const String &str) : IOException(str) {};
920 };
921 
922 #endif
923 
924 } // namespace ost
925 
926 #endif
927 
928