// Copyright (C) 1999-2000 Open Source Telecom Corporation.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// As a special exception to the GNU General Public License, permission is
// granted for additional uses of the text contained in its release
// of Common C++.
//
// The exception is that, if you link the Common C++ library with other
// files to produce an executable, this does not by itself cause the
// resulting executable to be covered by the GNU General Public License.
// Your use of that executable is in no way restricted on account of
// linking the Common C++ library code into it.
//
// This exception does not however invalidate any other reasons why
// the executable file might be covered by the GNU General Public License.
//
// This exception applies only to the code released under the
// name Common C++. If you copy code from other releases into a copy of
// Common C++, as the General Public License permits, the exception does
// not apply to the code that you add in this way. To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
//
// If you write modifications of your own for Common C++, it is your choice
// whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice.
#ifndef __CCXX_FILE_H__
#define __CCXX_FILE_H__
#ifndef __CCXX_THREAD_H__
#include <cc++/thread.h>
#else
#ifdef __CCXX_NAMESPACE_H__
#include <cc++/macros.h>
#endif
#endif
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <iostream.h>
#include <fstream.h>
typedef unsigned long pos_t;
typedef struct _fcb
{
struct _fcb *next;
caddr_t address;
size_t len;
off_t pos;
} fcb_t;
enum
{
FILE_OPEN_READONLY = O_RDONLY,
FILE_OPEN_WRITEONLY = O_WRONLY,
FILE_OPEN_READWRITE = O_RDWR,
FILE_OPEN_APPEND = O_WRONLY | O_APPEND,
#ifdef O_SYNC
FILE_OPEN_SYNC = O_RDWR | O_SYNC,
#else
FILE_OPEN_SYNC = O_RDWR,
#endif
FILE_OPEN_TRUNCATE = O_RDWR | O_TRUNC
};
/* to be used in future */
#ifndef S_IRUSR
#define S_IRUSR 0400
#define S_IWUSR 0200
#define S_IRGRP 0040
#define S_IWGRP 0020
#define S_IROTH 0004
#define S_IWOTH 0002
#endif
typedef enum
{
FILE_ATTR_INVALID = 0,
FILE_ATTR_PRIVATE = S_IRUSR | S_IWUSR,
FILE_ATTR_GROUP = FILE_ATTR_PRIVATE | S_IRGRP | S_IWGRP,
FILE_ATTR_PUBLIC = FILE_ATTR_GROUP | S_IROTH | S_IWOTH
} fileattr_t;
typedef enum
{
FILE_SUCCESS = 0,
FILE_NOT_OPENED,
FILE_MAP_FAILED,
FILE_INIT_FAILED,
FILE_OPEN_DENIED,
FILE_OPEN_FAILED,
FILE_OPEN_INUSE,
FILE_READ_INTERRUPTED,
FILE_READ_INCOMPLETE,
FILE_READ_FAILURE,
FILE_WRITE_INTERRUPTED,
FILE_WRITE_INCOMPLETE,
FILE_WRITE_FAILURE,
FILE_EXTENDED_ERROR
} fileerror_t;
typedef enum
{
FILE_ACCESS_READONLY = O_RDONLY,
FILE_ACCESS_WRITEONLY= O_WRONLY,
FILE_ACCESS_READWRITE = O_RDWR
} fileaccess_t;
#define FILE_MAPPED_READ FILE_ACCESS_READONLY
#define FILE_MAPPED_WRITE FILE_ACCESS_WRITEONLY
#define FILE_MAPPED_RDWR FILE_ACCESS_RDWR
typedef enum
{
FILE_COMPLETION_IMMEDIATE,
FILE_COMPLETION_DELAYED,
FILE_COMPLETION_DEFERRED
} filecomplete_t;
/**
* This class provides a few alterations to the standard fstream class
* for dealing with fifo devices. In particular, a fifo is assumed to
* be created via mkfifo and is destroyed when closed. The fifo is a
* r/w streamable object. fifo streams are presumed unique to posix
* systems and are generally not portable classes.
*/
class fifostream : public fstream
{
private:
char *pathname;
public:
/**
* Create fifo "object", but do not create or open a fifo
* stream.
*/
fifostream();
/**
* Create and open a fifo stream object.
*
* @param name of fifo.
*/
fifostream(const char *fname, long access = (long)FILE_ATTR_GROUP);
/**
* close any open fifo and remove.
*/
~fifostream();
/**
* open a new fifo stream. Kill the currently open one if
* present.
*
* @param name of fifo.
*/
void open(const char *fname, long access = (long)FILE_ATTR_GROUP);
/**
* close the fifo stream and remove it.
*/
void close(void);
};
/**
* The FIFOSession produces a seperate thread which can manage a fifo
* stream session. This is somewhat similar to TTYSession and TCPSession
* in purpose.
*/
class FIFOSession : public Thread, public fstream
{
private:
char *pathname;
public:
FIFOSession(const char *session, long access = (long)FILE_ATTR_GROUP, Semaphore *start = NULL, int pri = 0, int stack = 0);
~FIFOSession();
};
/**
* A low level portable directory class. Used to support ccstd Directory
* container. This provides a basic mechanism for allocating and
* accessing file entries.
*
* @author David Sugar <dyfet@ostel.com>
* @short low level directory access class.
*/
class Dir
{
private:
DIR *dir;
public:
Dir(const char *name);
~Dir();
char *getName(void);
bool operator!()
{return !dir;};
};
/**
* The purpose of this class is to define a base class for low level
* random file access that is portable between Win32 and Posix systems.
* This class is a foundation both for optimized thread shared and
* traditional locked file access that is commonly used to build
* database services, rather than the standard C++ streaming file classes.
*
* @author David Sugar <dyfet@ostel.com>
* @short Portable random disk file access.
*/
class RandomFile : public Mutex
{
private:
fileerror_t errid;
char *errstr;
protected:
int fd;
fileaccess_t access;
char *pathname;
struct
{
unsigned count : 16;
bool thrown : 1;
bool initial : 1;
bool immediate : 1;
bool temp : 1;
} flags;
/**
* Create an unopened random access file.
*/
RandomFile();
/**
* Default copy constructor.
*/
RandomFile(const RandomFile &rf);
/**
* Post an error event.
*
* @return error code.
* @param error code.
* @param error message string.
*/
fileerror_t Error(fileerror_t errid, char *errstr = NULL);
/**
* Post an extended string error message.
*
* @return FILE_EXTENDED_ERROR.
* @param error string.
*/
inline fileerror_t Error(char *errstr)
{return Error(FILE_EXTENDED_ERROR, errstr);};
/**
* Used to enable or disable throwing of exceptions on
* errors.
*
* @param true if errors will be thrown.
*/
inline void setError(bool enable)
{flags.thrown = !enable;};
/**
* Used to set file completion modes.
*
* @return FILE_SUCCESS if okay.
* @param completion mode.
*/
fileerror_t setCompletion(filecomplete_t mode);
/**
* Used to set the temporary attribute for the file. Temporary
* files are automatically deleted when closed.
*
* @param true for marking as temporary.
*/
inline void setTemporary(bool enable)
{flags.temp = enable;};
/**
* This method is used to initialize a newly created file as
* indicated by the "initial" flag. This method also returns
* the file access permissions that should be associated with
* the file. This method should never be called directly, but
* is instead used to impliment the "Initial" method. Typically
* one would use this to build an empty database shell when a
* previously empty database file is created.
*
* @return access, or FILE_ATTR_INVALID if should be removed.
*/
virtual fileattr_t Initialize(void)
{return FILE_ATTR_PUBLIC;};
/**
* Close the file.
*/
void Final(void);
public:
/**
* Destroy a random access file or it's derived class.
*/
virtual ~RandomFile()
{Final();};
/**
* This method should be called right after a RandomFile derived
* object has been created. This method will invoke initialize
* if the object is newly created, and set file access permissions
* appropriately.
*
* @return true if file had to be initialized.
*/
bool Initial(void);
/**
* Get current file capacity.
*
* @return total file size.
*/
off_t getCapacity(void);
/**
* This method is commonly used to close and re-open an existing
* database. This may be used when the database has been unlinked
* and an external process provides a new one to use.
*/
virtual fileerror_t Restart(void)
{return FILE_OPEN_FAILED;};
/**
* Return current error id.
*
* @return last error identifier set.
*/
inline fileerror_t getErrorNumber(void)
{return errid;};
/**
* Return current error string.
*
* @return last error string set.
*/
inline char *getErrorString(void)
{return errstr;};
bool operator!(void);
};
/**
* This class defines a database I/O file service that can be shared
* by multiple threads. All threads access a global copy of the database
* object, and mutex locks can be used to preserve transaction
* integrety. pread/pwrite calls can be used for optimized I/O when
* supported.
*/
class ThreadFile : public RandomFile
{
private:
ThreadKey state;
fcb_t *first;
fcb_t *getFCB(void);
fileerror_t Open(const char *path);
public:
/**
* Open or create a new database file. You should also use
* Initial.
*
* @param pathname of database to open.
*/
ThreadFile(const char *path);
/**
* Close and finish a database file.
*/
~ThreadFile();
/**
* Restart an existing database; close and re-open.
*
* @return FILE_SUCCESS if successful.
*/
fileerror_t Restart(void)
{return Open(pathname);};
/**
* Fetch a portion of the file into physical memory. This can use
* state information to fetch the current record multiple times.
*
* @return FILE_SUCCESS on success.
* @param address to use, or NULL if same as last I/O.
* @param length to use, or 0 if same as last I/O.
* @param file position to use -1 if same as last I/O.
*/
fileerror_t Fetch(caddr_t address = NULL, size_t length = 0, off_t position = - 1);
/**
* Update a portion of a file from physical memory. This can use
* state information to commit the last read record.
*
* @return FILE_SUCCESS on success.
* @param address to use, or NULL if same as last I/O.
* @param length to use, or 0 if same as last I/O.
* @param file position to use or -1 if same as last I/O.
*/
fileerror_t Update(caddr_t address = NULL, size_t length = 0, off_t position = -1);
/**
* Add new data to the end of the file.
* @param address to use, or NULL if same as last I/O.
* @param length to use, or 0 if same as last I/O.
*/
fileerror_t Append(caddr_t address = NULL, size_t length = 0);
/**
* Fetch the current file position marker for this thread.
*
* @return file position offset.
*/
off_t getPosition(void);
bool operator++(void);
bool operator--(void);
};
/**
* This class defines a database I/O file service that can be shared
* by multiple processes. Each thread should access a dup of the database
* object, and mutex locks can be used to preserve transaction
* integrety if multiple threads are used.
*/
class SharedFile : public RandomFile
{
private:
fcb_t fcb;
fileerror_t Open(const char *path);
public:
/**
* Open or create a new database file. You should also use
* Initial.
*
* @param pathname of database to open.
* @param file access mode.
*/
SharedFile(const char *path);
/**
* Create a shared file as a duplicate of an existing shared
* file.
*
* @param original file.
*/
SharedFile(const SharedFile &file);
/**
* Close and finish a database file.
*/
~SharedFile();
/**
* Restart an existing database; close and re-open.
*
* @return FILE_SUCCESS if successful.
*/
fileerror_t Restart(void)
{return Open(pathname);};
/**
* Lock and Fetch a portion of the file into physical memory.
* This can use state information to fetch the current record
* multiple times.
*
* @return FILE_SUCCESS on success.
* @param address to use, or NULL if same as last I/O.
* @param length to use, or 0 if same as last I/O.
* @param file position to use -1 if same as last I/O.
*/
fileerror_t Fetch(caddr_t address = NULL, size_t length = 0, off_t position = - 1);
/**
* Update a portion of a file from physical memory. This can use
* state information to commit the last read record. The current
* lock is also cleared.
*
* @return FILE_SUCCESS on success.
* @param address to use, or NULL if same as last I/O.
* @param length to use, or 0 if same as last I/O.
* @param file position to use or -1 if same as last I/O.
*/
fileerror_t Update(caddr_t address = NULL, size_t length = 0, off_t position = -1);
/**
* Clear a lock held from a previous fetch operation without
* updating.
*
* @return FILE_SUCCESS on success.
* @param length to use, or 0 if same as last I/O.
* @param file position to use or -1 if same as last I/O.
*/
fileerror_t Clear(size_t length = 0, off_t pos = -1);
/**
* Add new data to the end of the file. Locks file during append.
*
* @param address to use, or NULL if same as last I/O.
* @param length to use, or 0 if same as last I/O.
*/
fileerror_t Append(caddr_t address = NULL, size_t length = 0);
/**
* Fetch the current file position marker for this thread.
*
* @return file position offset.
*/
off_t getPosition(void);
bool operator++(void);
bool operator--(void);
};
/**
* Create and map a disk file into memory. This portable class works
* under both Posix via mmap and under the win32 API. A mapped file
* can be referenced directly by it's memory segment.
*
* @author David Sugar
* @short map a named disk file into memory.
*/
class MappedFile : public RandomFile
{
private:
fcb_t fcb;
int prot;
public:
/**
* Open a file for mapping. More than one segment of a file
* may be mapped into seperate regions of memory.
*
* @param file name to access for mapping.
* @param access mode to map file.
*/
MappedFile(const char *fname, fileaccess_t mode);
/**
* Map a portion or all of a specified file in the specified
* shared memory access mode. Valid mapping modes include
* FILE_MAPPED_READ, FILE_MAPPED_WRITE, and FILE_MAPPED_RDWR.
*
* @param fname pathname of file to map into memory.
* @param offset from start of file to begin mapping in bytes.
* @param size of mapped area in bytes.
* @param mode to map file.
*/
MappedFile(const char *fname, pos_t offset, size_t size, fileaccess_t mode);
/**
* Release a mapped section of memory associated with a file. The
* mapped area is updated back to disk.
*/
virtual ~MappedFile();
/**
* Synchronize the contents of the mapped portion of memory with
* the disk file and wait for completion. This assures the memory
* mapped from the file is written back.
*/
inline void Sync(void)
{msync(fcb.address, fcb.len, MS_SYNC);};
/**
* Synchronize a segment of memory mapped from a segment fetch.
*
* @param memory address to update.
* @param size of segment.
*/
void Sync(caddr_t address, size_t len);
/**
* Map a portion of the memory mapped from the file back to the
* file and do not wait for completion. This is useful when mapping
* a database file and updating a single record.
*
* @param offset into the mapped region of memory.
* @param len of partial region (example, record length).
*/
void Update(size_t offset = 0, size_t len = 0);
/**
* Update a mapped region back to disk as specified by address
* and length.
*
* @param address of segment.
* @param length of segment.
*/
void Update(caddr_t address, size_t len);
/**
* Release (unmap) a memory segment.
*
* @param address of memory segment to release.
* @param length of memory segment to release.
*/
void Release(caddr_t address, size_t len);
/**
* Fetch a pointer to an offset within the memory mapped portion
* of the disk file. This really is used for convience of matching
* operations between Update and Fetch, as one could simply have
* accessed the base pointer where the file was mapped directly.
*
* @param offset from start of mapped memory.
*/
inline caddr_t Fetch(size_t offset = 0)
{return ((char *)(fcb.address)) + offset;};
/**
* Fetch and map a portion of a disk file to a logical memory
* block.
*
* @return pointer to memory segment.
* @param offset of file segment to map.
* @param size of memory segment to map.
*/
caddr_t Fetch(off_t pos, size_t len);
};
/**
* The Pipe uses system kernel buffering to hold data being passed either
* between two execution contexts within the same process, or between
* different processes. Unlike thread's "Buffer", Pipe uses system
* descriptors and kernel memory. Under Posix, the size of the pipe and
* associated kernel memory is always a fixed constant as defined by
* _PC_PIPE_BUF. The Common C++ "pipe" class primarily deals with "atomic"
* transfers of fixed sized objects through pipes. Pipes may pass
* data arbitrarily and can also be used through the "pipestream" class.
*
* The "Pipe" class is not meant to be a true "public" class, but as a
* builder class for deriving other classes.
*
* @author David Sugar <dyfet@ostel.com>.
* @short kernel buffering between processes and/or threads.
*/
class Pipe
{
private:
int fd[2];
int objcount;
int objsize;
protected:
/**
* Get the object size for atomic operations.
*
* @return size of atomic operations.
*/
inline int getSize(void)
{return objsize;};
/**
* Sender is often used for implementing a fork()'d message port
* between processes. By stopping the sender, the current pipe
* can then only be used for receiving, and the sender is presumed
* to be in the other half of a fork()'d process.
*
* @see #endReceiver
*/
inline void endSender(void)
{close(fd[1]);};
/**
* Receiver is often used for implementing a fork()'d message port
* between processes. By stopping the receiver, the current pipe
* can then only be used for sending, and the receiver is presumed
* to be in the other half of a fork()'d process.
*
* @see #endSender
*/
inline void endReceiver(void)
{close(fd[0]);};
/**
* Create a kernel pipe descriptor set using pipe(). On systems
* which allow the pipe kernel buffer to be defined, a size for
* aligned atomic transfers can be set, as well as the number of
* atomic objects the kernel will buffer. On Posix systems, these
* options are ignored.
*
* @param objsize of atomic objects to send.
* @param count of atomic objects to kernel buffer.
*/
Pipe(int size = 512, int count = 1);
/**
* Destroy the pipe and kernel descriptor resources.
*/
~Pipe();
/**
* Create a pipe as a duplicate of an existing pipe.
*
* @param orig pipe to duplicate.
*/
Pipe(const Pipe &orig);
Pipe &operator=(const Pipe &orig);
/* depreciated methods */
void Sender(void)
{endReceiver();};
void Receiver(void)
{endSender();};
int Read(void *buf, int len)
{return ::read(fd[0], (char *)buf, len);};
int Write(void *buf, int len)
{return ::write(fd[1], (char *)buf, len);};
public:
/**
* Used to see if the pipe has any open entities.
*/
bool operator!();
/**
* Perform an object atomic transfer of data from a pipe.
*
* @return number of bytes actually read if successful.
* @param addr pointer to store read data.
* @param len number of bytes to read.
*/
inline int Recv(void *addr)
{return ::read(fd[0], (char *)addr, objsize);};
/**
* Perform an object atomic transfer of data to a pipe.
*
* @return number of bytes written if successful.
* @param addr pointer to write data from.
* @param len number of butes to write.
*/
inline int Send(void *addr)
{return ::write(fd[1], (char *)addr, objsize);};
};
/**
* The DSO dynamic loader class is used to load object files. On
* elf based systems this is typically done with dlopen. A dummy
* stub class is generated for non-dl capable systems.
*
* @author David Sugar <dyfet@ostel.com>
* @short Dynamic class file loader.
*/
class DSO
{
private:
#ifdef HAVE_MODULES
static Mutex mutex;
static DSO *first, *last;
DSO *next, *prev;
void *image;
#endif
public:
/**
* Construct and load a DSO object file.
*
* @param pathname of object file to load.
*/
#ifdef HAVE_MODULES
DSO(char *filename);
#else
DSO(char *filename)
{throw this;};
#endif
/**
* Retrieve error indicator associated with DSO failure. This
* is often used in catch handlers.
*/
char *getError(void);
/**
* Detach a DSO object from running memory.
*/
#ifdef HAVE_MODULES
~DSO();
#endif
/**
* Lookup a symbol in the loaded file.
*/
#ifdef HAVE_MODULES
void *operator[](const char *);
#else
void *operator[](const char *)
{return NULL;};
#endif
#ifdef HAVE_MODULES
friend void dynunload(void);
#else
friend void dynunload(void)
{return;};
#endif
};
bool isDir(const char *path);
bool isFile(const char *path);
bool isDevice(const char *path);
bool canAccess(const char *path);
bool canModify(const char *path);
#ifdef __CCXX_NAMESPACE_H__
#undef __CCXX_NAMESPACE_H__
#include <cc++/namespace.h>
#endif
#endif
| Generated by: dyfet@home.sys on Fri May 12 08:41:04 200. |