]> git.saurik.com Git - apple/libc.git/blame - db/recno/rec_open.c
Libc-320.tar.gz
[apple/libc.git] / db / recno / rec_open.c
CommitLineData
e9ce8d39 1/*
9385eb3d 2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
e9ce8d39
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
734aad71 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
e9ce8d39 7 *
734aad71
A
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
e9ce8d39
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
734aad71
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
e9ce8d39
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
9385eb3d
A
25/*-
26 * Copyright (c) 1990, 1993, 1994
e9ce8d39
A
27 * The Regents of the University of California. All rights reserved.
28 *
29 * This code is derived from software contributed to Berkeley by
30 * Mike Olson.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 */
60
9385eb3d
A
61#if defined(LIBC_SCCS) && !defined(lint)
62static char sccsid[] = "@(#)rec_open.c 8.10 (Berkeley) 9/1/94";
63#endif /* LIBC_SCCS and not lint */
64#include <sys/cdefs.h>
e9ce8d39
A
65
66#include <sys/types.h>
9385eb3d 67#include <sys/mman.h>
e9ce8d39
A
68#include <sys/stat.h>
69
e9ce8d39
A
70#include <errno.h>
71#include <fcntl.h>
72#include <limits.h>
73#include <stddef.h>
74#include <stdio.h>
75#include <unistd.h>
76
77#include <db.h>
78#include "recno.h"
79
80DB *
81__rec_open(fname, flags, mode, openinfo, dflags)
82 const char *fname;
83 int flags, mode, dflags;
84 const RECNOINFO *openinfo;
85{
86 BTREE *t;
87 BTREEINFO btopeninfo;
88 DB *dbp;
89 PAGE *h;
90 struct stat sb;
91 int rfd, sverrno;
92
93 /* Open the user's file -- if this fails, we're done. */
94 if (fname != NULL && (rfd = open(fname, flags, mode)) < 0)
95 return (NULL);
96
97 /* Create a btree in memory (backed by disk). */
98 dbp = NULL;
99 if (openinfo) {
100 if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
101 goto einval;
102 btopeninfo.flags = 0;
103 btopeninfo.cachesize = openinfo->cachesize;
104 btopeninfo.maxkeypage = 0;
105 btopeninfo.minkeypage = 0;
106 btopeninfo.psize = openinfo->psize;
107 btopeninfo.compare = NULL;
108 btopeninfo.prefix = NULL;
109 btopeninfo.lorder = openinfo->lorder;
110 dbp = __bt_open(openinfo->bfname,
111 O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo, dflags);
112 } else
113 dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL, dflags);
114 if (dbp == NULL)
115 goto err;
116
117 /*
118 * Some fields in the tree structure are recno specific. Fill them
119 * in and make the btree structure look like a recno structure. We
120 * don't change the bt_ovflsize value, it's close enough and slightly
121 * bigger.
122 */
123 t = dbp->internal;
124 if (openinfo) {
125 if (openinfo->flags & R_FIXEDLEN) {
9385eb3d 126 F_SET(t, R_FIXLEN);
e9ce8d39
A
127 t->bt_reclen = openinfo->reclen;
128 if (t->bt_reclen == 0)
129 goto einval;
130 }
131 t->bt_bval = openinfo->bval;
132 } else
133 t->bt_bval = '\n';
134
9385eb3d 135 F_SET(t, R_RECNO);
e9ce8d39 136 if (fname == NULL)
9385eb3d 137 F_SET(t, R_EOF | R_INMEM);
e9ce8d39
A
138 else
139 t->bt_rfd = rfd;
e9ce8d39
A
140
141 if (fname != NULL) {
142 /*
143 * In 4.4BSD, stat(2) returns true for ISSOCK on pipes.
144 * Unfortunately, that's not portable, so we use lseek
145 * and check the errno values.
146 */
147 errno = 0;
148 if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) {
149 switch (flags & O_ACCMODE) {
150 case O_RDONLY:
9385eb3d 151 F_SET(t, R_RDONLY);
e9ce8d39
A
152 break;
153 default:
154 goto einval;
155 }
156slow: if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
157 goto err;
9385eb3d 158 F_SET(t, R_CLOSEFP);
e9ce8d39 159 t->bt_irec =
9385eb3d 160 F_ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe;
e9ce8d39
A
161 } else {
162 switch (flags & O_ACCMODE) {
163 case O_RDONLY:
9385eb3d 164 F_SET(t, R_RDONLY);
e9ce8d39
A
165 break;
166 case O_RDWR:
167 break;
168 default:
169 goto einval;
170 }
171
172 if (fstat(rfd, &sb))
173 goto err;
174 /*
175 * Kluge -- we'd like to test to see if the file is too
176 * big to mmap. Since, we don't know what size or type
177 * off_t's or size_t's are, what the largest unsigned
178 * integral type is, or what random insanity the local
179 * C compiler will perpetrate, doing the comparison in
180 * a portable way is flatly impossible. Hope that mmap
181 * fails if the file is too large.
182 */
183 if (sb.st_size == 0)
9385eb3d 184 F_SET(t, R_EOF);
e9ce8d39 185 else {
9385eb3d
A
186#ifdef MMAP_NOT_AVAILABLE
187 /*
188 * XXX
189 * Mmap doesn't work correctly on many current
190 * systems. In particular, it can fail subtly,
191 * with cache coherency problems. Don't use it
192 * for now.
193 */
e9ce8d39 194 t->bt_msize = sb.st_size;
9385eb3d
A
195 if ((t->bt_smap = mmap(NULL, t->bt_msize,
196 PROT_READ, MAP_PRIVATE, rfd,
197 (off_t)0)) == MAP_FAILED)
e9ce8d39
A
198 goto slow;
199 t->bt_cmap = t->bt_smap;
200 t->bt_emap = t->bt_smap + sb.st_size;
9385eb3d 201 t->bt_irec = F_ISSET(t, R_FIXLEN) ?
e9ce8d39 202 __rec_fmap : __rec_vmap;
9385eb3d
A
203 F_SET(t, R_MEMMAPPED);
204#else
205 goto slow;
206#endif
e9ce8d39
A
207 }
208 }
209 }
210
211 /* Use the recno routines. */
212 dbp->close = __rec_close;
213 dbp->del = __rec_delete;
214 dbp->fd = __rec_fd;
215 dbp->get = __rec_get;
216 dbp->put = __rec_put;
217 dbp->seq = __rec_seq;
218 dbp->sync = __rec_sync;
219
220 /* If the root page was created, reset the flags. */
221 if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL)
222 goto err;
223 if ((h->flags & P_TYPE) == P_BLEAF) {
9385eb3d
A
224 F_CLR(h, P_TYPE);
225 F_SET(h, P_RLEAF);
e9ce8d39
A
226 mpool_put(t->bt_mp, h, MPOOL_DIRTY);
227 } else
228 mpool_put(t->bt_mp, h, 0);
229
230 if (openinfo && openinfo->flags & R_SNAPSHOT &&
9385eb3d 231 !F_ISSET(t, R_EOF | R_INMEM) &&
e9ce8d39
A
232 t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
233 goto err;
234 return (dbp);
235
236einval: errno = EINVAL;
237err: sverrno = errno;
238 if (dbp != NULL)
239 (void)__bt_close(dbp);
240 if (fname != NULL)
241 (void)close(rfd);
242 errno = sverrno;
243 return (NULL);
244}
245
246int
247__rec_fd(dbp)
248 const DB *dbp;
249{
250 BTREE *t;
251
252 t = dbp->internal;
253
254 /* Toss any page pinned across calls. */
255 if (t->bt_pinned != NULL) {
256 mpool_put(t->bt_mp, t->bt_pinned, 0);
257 t->bt_pinned = NULL;
258 }
259
260 /* In-memory database can't have a file descriptor. */
9385eb3d 261 if (F_ISSET(t, R_INMEM)) {
e9ce8d39
A
262 errno = ENOENT;
263 return (-1);
264 }
265 return (t->bt_rfd);
266}