xref: /csrg-svn/lib/libc/db/recno/rec_open.c (revision 50995)
1*50995Sbostic /*-
2*50995Sbostic  * Copyright (c) 1990 The Regents of the University of California.
3*50995Sbostic  * All rights reserved.
4*50995Sbostic  *
5*50995Sbostic  * This code is derived from software contributed to Berkeley by
6*50995Sbostic  * Mike Olson.
7*50995Sbostic  *
8*50995Sbostic  * %sccs.include.redist.c%
9*50995Sbostic  */
10*50995Sbostic 
11*50995Sbostic #if defined(LIBC_SCCS) && !defined(lint)
12*50995Sbostic static char sccsid[] = "@(#)rec_open.c	5.1 (Berkeley) 09/04/91";
13*50995Sbostic #endif /* LIBC_SCCS and not lint */
14*50995Sbostic 
15*50995Sbostic #include <sys/types.h>
16*50995Sbostic #include <sys/mman.h>
17*50995Sbostic #include <sys/stat.h>
18*50995Sbostic #include <fcntl.h>
19*50995Sbostic #include <errno.h>
20*50995Sbostic #include <limits.h>
21*50995Sbostic #include <db.h>
22*50995Sbostic #include <unistd.h>
23*50995Sbostic #include <stdio.h>
24*50995Sbostic #include <stddef.h>
25*50995Sbostic #include "../btree/btree.h"
26*50995Sbostic 
27*50995Sbostic DB *
28*50995Sbostic __rec_open(fname, flags, mode, openinfo)
29*50995Sbostic 	const char *fname;
30*50995Sbostic 	int flags, mode;
31*50995Sbostic 	const RECNOINFO *openinfo;
32*50995Sbostic {
33*50995Sbostic 	BTREE *t;
34*50995Sbostic 	BTREEINFO btopeninfo;
35*50995Sbostic 	DB *dbp;
36*50995Sbostic 	PAGE *h;
37*50995Sbostic 	struct stat sb;
38*50995Sbostic 	int rfd;
39*50995Sbostic 
40*50995Sbostic 	/* Open the user's file -- if this fails, we're done. */
41*50995Sbostic 	if ((rfd = open(fname, flags, mode)) < 0)
42*50995Sbostic 		return (NULL);
43*50995Sbostic 
44*50995Sbostic 	/* Create a btree in memory (backed by disk). */
45*50995Sbostic 	if (openinfo) {
46*50995Sbostic 		btopeninfo.flags = 0;
47*50995Sbostic 		btopeninfo.cachesize = openinfo->cachesize;
48*50995Sbostic 		btopeninfo.psize = 0;
49*50995Sbostic 		btopeninfo.compare = NULL;
50*50995Sbostic 		btopeninfo.lorder = openinfo->lorder;
51*50995Sbostic 		dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo);
52*50995Sbostic 	} else
53*50995Sbostic 		dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL);
54*50995Sbostic 	if (dbp == NULL) {
55*50995Sbostic 		(void)close(rfd);
56*50995Sbostic 		return (NULL);
57*50995Sbostic 	}
58*50995Sbostic 
59*50995Sbostic 	/*
60*50995Sbostic 	 * Some fields in the tree structure are recno specific.  Fill them
61*50995Sbostic 	 * in and make the btree structure look like a recno structure.
62*50995Sbostic 	 */
63*50995Sbostic 	t = dbp->internal;
64*50995Sbostic 	if (openinfo) {
65*50995Sbostic 		if (openinfo->flags & R_FIXEDLEN)
66*50995Sbostic 			t->bt_flags |= BTF_FIXEDLEN;
67*50995Sbostic 
68*50995Sbostic 		t->bt_reclen = openinfo->reclen;
69*50995Sbostic 		if (t->bt_reclen == 0) {
70*50995Sbostic 			errno = EINVAL;
71*50995Sbostic 			goto err;
72*50995Sbostic 		}
73*50995Sbostic 
74*50995Sbostic 		t->bt_bval = openinfo->bval;
75*50995Sbostic 	} else
76*50995Sbostic 		t->bt_bval = '\n';
77*50995Sbostic 
78*50995Sbostic 	t->bt_flags = BTF_RECNO;
79*50995Sbostic 
80*50995Sbostic 	/*
81*50995Sbostic  	 * In 4.4BSD stat(2) returns true for ISSOCK on pipes.  Until then,
82*50995Sbostic 	 * this is fairly close.  Pipes are read-only.
83*50995Sbostic  	 */
84*50995Sbostic 	if (lseek(rfd, 0L, SEEK_CUR) == -1 && errno == ESPIPE) {
85*50995Sbostic 		SET(t, BTF_RDONLY);
86*50995Sbostic 		if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
87*50995Sbostic 			goto err;
88*50995Sbostic 		t->bt_irec = ISSET(t, BTF_FIXEDLEN) ? __rec_fpipe : __rec_vpipe;
89*50995Sbostic 	} else {
90*50995Sbostic 		if (fstat(rfd, &sb))
91*50995Sbostic 			goto err;
92*50995Sbostic 		if (!(flags & (O_RDWR | O_WRONLY)))
93*50995Sbostic 			SET(t, BTF_RDONLY);
94*50995Sbostic 		if ((t->bt_smap = mmap(NULL, sb.st_size, PROT_READ, MAP_FILE,
95*50995Sbostic 		    rfd, (off_t)0)) == NULL)
96*50995Sbostic 			goto err;
97*50995Sbostic 		t->bt_emap = t->bt_smap + sb.st_size;
98*50995Sbostic 		t->bt_rfd = rfd;
99*50995Sbostic 		t->bt_irec = ISSET(t, BTF_FIXEDLEN) ? __rec_fmap : __rec_vmap;
100*50995Sbostic 	}
101*50995Sbostic 
102*50995Sbostic 	/* Use the recno routines. */
103*50995Sbostic 	dbp->close = __rec_close;
104*50995Sbostic 	dbp->del = __rec_delete;
105*50995Sbostic 	dbp->get = __rec_get;
106*50995Sbostic 	dbp->put = __rec_put;
107*50995Sbostic 	dbp->seq = __rec_seq;
108*50995Sbostic 	dbp->sync = __rec_sync;
109*50995Sbostic 
110*50995Sbostic 	/* If the root page was created, reset the flags. */
111*50995Sbostic 	if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL)
112*50995Sbostic 		goto err;
113*50995Sbostic 	if ((h->flags & P_TYPE) == P_BLEAF) {
114*50995Sbostic 		h->flags = h->flags & ~P_TYPE | P_RLEAF;
115*50995Sbostic 		mpool_put(t->bt_mp, h, MPOOL_DIRTY);
116*50995Sbostic 	} else
117*50995Sbostic 		mpool_put(t->bt_mp, h, 0);
118*50995Sbostic 
119*50995Sbostic 	if (openinfo && openinfo->flags & R_SNAPSHOT &&
120*50995Sbostic 	    t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
121*50995Sbostic                 goto err;
122*50995Sbostic 	return (dbp);
123*50995Sbostic 
124*50995Sbostic err:	__bt_close(dbp);
125*50995Sbostic 	(void)close(rfd);
126*50995Sbostic 	return (NULL);
127*50995Sbostic }
128