1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
|
#ifdef OS_solaris
* This is all for Solaris 2.6.
*
* Sun defined a new API in Solaris2.6 to be used when manipulating large
* (>2Gbyte) files. This API isn't present in 2.5.x, so we can't simply
* call it -- that would mean two binaries, one for 2.5.x and the other for
* 2.6. Not pretty. So, what we do here is determine the OS on which we're
* running at runtime, and adjust the underlying Berkeley DB calls to use
* the new API if it's there.
*/
/* This must match the definition of stat64 in Solaris2.6 */
struct our_stat64 {
dev_t st_dev;
long st_pad1[3]; /* reserve for dev expansion */
u_longlong_t st_ino;
mode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
dev_t st_rdev;
long st_pad2[2];
longlong_t st_size;
timestruc_t mst_atime;
timestruc_t mst_mtime;
timestruc_t mst_ctime;
long st_blksize;
longlong_t st_blocks; /* large file support */
char st_fstype[_ST_FSTYPSZ];
long st_pad4[8]; /* expansion area */
};
#define MEGABYTE (1024 * 1024)
typedef int (*open_fn)(const char *path, int flags, ...);
typedef longlong_t (*lseek64_fn)(int fildes, longlong_t offset, int whence);
typedef longlong_t (*fstat64_fn)(int fildes, struct our_stat64 *s);
typedef void* (*mmap64_fn)(void* addr, size_t len, int prot, int flags,
int filedes, longlong_t off);
static fstat64_fn os_fstat64_fn = NULL;
static lseek64_fn os_lseek64_fn = NULL;
static mmap64_fn os_mmap64_fn = NULL;
static open_fn os_open64_fn = NULL;
static int dblayer_load_largefile_fns()
{
void *lib_handle = NULL;
void *function_found = NULL;
int ret = 0;
lib_handle = dlopen(NULL, RTLD_NOW);
if (NULL == lib_handle)
return (-1);
function_found = dlsym(lib_handle,"open64");
if (NULL == function_found)
return (-1);
os_open64_fn = (open_fn)function_found;
function_found = dlsym(lib_handle,"lseek64");
if (NULL == function_found)
return (-1);
os_lseek64_fn = (lseek64_fn)function_found;
function_found = dlsym(lib_handle,"fstat64");
if (NULL == function_found)
return (-1);
os_fstat64_fn = (fstat64_fn)function_found;
function_found = dlsym(lib_handle,"mmap64");
if (NULL == function_found)
return (-1);
os_mmap64_fn = (mmap64_fn)function_found;
return 0;
}
/* Helper function for large seeks */
static int dblayer_seek_fn_solaris(int fd,
size_t pgsize, db_pgno_t pageno, u_long relative, int whence)
{
longlong_t offset = 0;
longlong_t ret = 0;
if (NULL == os_lseek64_fn) {
return -1;
}
offset = (longlong_t)pgsize * pageno + relative;
ret = (*os_lseek64_fn)(fd,offset,whence);
return (ret == -1) ? errno : 0;
}
/* Helper function for large file mmap */
static int dblayer_map_solaris(fd, len, is_private, is_rdonly, addr)
int fd, is_private, is_rdonly;
size_t len;
void **addr;
{
void *p;
int flags, prot;
flags = is_private ? MAP_PRIVATE : MAP_SHARED;
prot = PROT_READ | (is_rdonly ? 0 : PROT_WRITE);
if ((p = (*os_mmap64_fn)(NULL,
len, prot, flags, fd, (longlong_t)0)) == (void *)MAP_FAILED)
return (errno);
*addr = p;
return (0);
}
/* Helper function for large fstat */
static int dblayer_ioinfo_solaris(const char *path,
int fd, u_int32_t *mbytesp, u_int32_t *bytesp, u_int32_t *iosizep)
{
struct our_stat64 sb;
if (NULL == os_fstat64_fn) {
return -1;
}
if ((*os_fstat64_fn)(fd, &sb) == -1)
return (errno);
/* Return the size of the file. */
if (mbytesp != NULL)
*mbytesp = (u_int32_t) (sb.st_size / (longlong_t)MEGABYTE);
if (bytesp != NULL)
*bytesp = (u_int32_t) (sb.st_size % (longlong_t)MEGABYTE);
/*
* Return the underlying filesystem blocksize, if available. Default
* to 8K on the grounds that most OS's use less than 8K as their VM
* page size.
*/
if (iosizep != NULL)
*iosizep = sb.st_blksize;
return (0);
}
#endif
#ifdef irix
* A similar mess to Solaris: a new API added in IRIX6.2 to support large
* files. We always build on 6.2 or later, so no need to do the same song
* and dance as on Solaris -- we always have the header files for the
* 64-bit API.
*/
/* Helper function for large seeks */
static int dblayer_seek_fn_irix(int fd,
size_t pgsize, db_pgno_t pageno, u_long relative, int whence)
{
off64_t offset = 0;
off64_t ret = 0;
offset = (off64_t)pgsize * pageno + relative;
ret = lseek64(fd,offset,whence);
return (ret == -1) ? errno : 0;
}
/* Helper function for large fstat */
static int dblayer_ioinfo_irix(const char *path,
int fd, u_int32_t *mbytesp, u_int32_t *bytesp, u_int32_t *iosizep)
{
struct stat64 sb;
if (fstat64(fd, &sb) == -1) {
return (errno);
}
/* Return the size of the file. */
if (mbytesp != NULL)
*mbytesp = (u_int32_t) (sb.st_size / (off64_t)MEGABYTE);
if (bytesp != NULL)
*bytesp = (u_int32_t) (sb.st_size % (off64_t)MEGABYTE);
if (iosizep != NULL)
*iosizep = sb.st_blksize;
return (0);
}
#endif /* irix */
static int dblayer_override_libdb_functions(dblayer_private *priv)
{
#if defined(OS_solaris)
int ret = 0;
ret = dblayer_load_largefile_fns();
if (0 != ret) {
Debug("Not Solaris2.6: no large file support enabled\n");
} else {
/* Means we did get the XXX64 functions, so let's use them */
db_jump_set((void*)os_open64_fn, DB_FUNC_OPEN);
db_jump_set((void*)dblayer_seek_fn_solaris, DB_FUNC_SEEK);
db_jump_set((void*)dblayer_ioinfo_solaris, DB_FUNC_IOINFO);
db_jump_set((void*)dblayer_map_solaris, DB_FUNC_MAP);
Debug("Solaris2.6: selected 64-bit file handling.\n");
}
#else
#if defined (irix)
db_jump_set((void*)dblayer_seek_fn_irix, DB_FUNC_SEEK);
db_jump_set((void*)dblayer_ioinfo_irix, DB_FUNC_IOINFO);
#endif /* irix */
#endif /* OS_solaris */
return 0;
}
|