// MMap.h -- mmap() system call wrapper class
// 11/4/97
// 11/29/97 modified for private mappings of /dev/zero
#ifndef __MMAP_H
#define __MMAP_H
#pragma interface "MMap.h"
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
/*
MMap -- wrapper class for the system call mmap()
This wrapper class provides a simple interface to the system call mmap().
The object contains:
int fd -- the file descriptor of the file to be mapped
const char *fileName -- the name of the file to be mapped
size_t length -- the length of the mapped region in bytes
off_t offset -- the offset of the mapped region in the file
int prot -- the protection mode of the mapping
int flags -- the flags of the mapping
void *paddr -- the address of the mapped region in the main memory
*/
class MMap {
protected:
int fd; // file descriptor
char *fileName; // file name
size_t length; // length of the mapped region in bytes
off_t offset; // offset of the mapped region in the file
int prot; // protection mode of mmap
int flags; // mmap flags
void *paddr; // mapped addr in main memory
public:
// constructors
/*
MMap(fd) -- constructor by a file descriptor
parameters:
int FD -- the file descriptor
int p -- the protection mode
*/
MMap(int FD = -1, int p = PROT_READ | PROT_WRITE):
fd(FD),
fileName(0),
prot(p),
flags(MAP_SHARED),
paddr(0) {}
/*
MMap(MMap &) -- constructor by another MMap object
parameter:
MMap &m -- the MMap object, whose mapping is not inherited
*/
MMap(MMap &m):
fd(m.fd),
fileName(0),
prot(m.prot),
flags(m.flags),
paddr(0) {}
/*
MMap(file) -- general constructor by a file name
parameters:
const char *file -- the file name for mapping
int p -- the protection mode
*/
MMap(const char *file, int p = PROT_READ | PROT_WRITE) : paddr(0) {
struct stat st;
static const char DevZero[] = "/dev/zero";
if (file == 0) {
fd = -1;
return;
}
if (strcmp(file, DevZero) != 0) {
if (stat(file, &st) != 0) {
fd = -1;
return;
}
if (!S_ISREG(st.st_mode)) {
fd = -1;
return;
}
if (st.st_size <= 0) {
fd = -1;
return;
}
}
if (p & PROT_WRITE) {
if ((fd = open(file, O_RDWR)) == -1) {
fd = -1;
return;
}
} else {
if ((fd = open(file, O_RDONLY)) == -1) {
fd = -1;
return;
}
}
fileName = new char[strlen(file) + 1];
strcpy(fileName, file);
prot = p;
if (strcmp(file, DevZero) != 0) {
flags = MAP_SHARED;
} else {
flags = MAP_PRIVATE;
}
}
/*
assignment operater with another MMap object
parameter:
MMap &m -- another MMap object, whose mapping is not inherited
*/
MMap &operator=(MMap &m) {
fd = m.fd;
fileName = 0;
prot = m.prot;
flags = m.flags;
paddr = 0;
return *this;
}
/*
~MMap() -- destructor
This destructor unmaps the existing mapping.
*/
~MMap() {
if (fd != -1 && paddr != 0) {
this->unmap();
if (fileName) {
close(fd);
}
}
}
/*
map -- map a region to the main memory
parameters:
off_t off -- the offset of the beginning of the region in the file
size_t len -- the length of the region in bytes
return value:
void * -- the address of the mapped region in the main memory,
0 when mapping failed
*/
void *map(off_t off, size_t len) {
if (fd == -1)
return 0;
if (paddr != 0) // already mapped
munmap(paddr, length); // unmap the previous mapping
paddr = mmap(0, len, prot, flags, fd, off);
if ((int)paddr == -1) {
paddr = 0;
return 0;
}
offset = off;
length = len;
return paddr;
}
/*
unmap -- unmap the region
parameter: none
return value:
int -- -1 when unmapping failed
*/
int unmap() {
if (fd == -1)
return -1;
if (paddr == 0)
return -1;
if (munmap(paddr, length) != 0) {
return -1;
} else {
paddr = 0;
return 0;
}
}
/*
sync -- synchronize the memory with the file
parameter:
int syncflags -- MS_SYNC for synchronous operation,
MS_ASYNC for asynchronous operation
return value:
int -- -1 when synchronization failed
*/
int sync(int syncflags = MS_SYNC) {
if (fd == -1)
return -1;
if (paddr == 0)
return -1;
if (msync(paddr, length, syncflags) != 0)
return -1;
else
return 0;
}
// accessors
// get the file descriptor
int getFd() {
return fd;
}
// get the file name
const char *getFileName() {
return fileName;
}
// get the address of the mapped region in the main memory
inline void *getAddr() {
return paddr;
}
// get the length of the mapped region
inline size_t getLength() {
return paddr ? length : -1;
}
// get the offset of the mapped region in the file
inline off_t getOffset() {
return paddr ? offset : -1;
}
};
#endif // __MMAP_H