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