#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; }