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