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