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