GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libc/db/recno/rec_open.c Lines: 0 80 0.0 %
Date: 2017-11-07 Branches: 0 55 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: rec_open.c,v 1.13 2016/09/21 04:38:56 guenther Exp $	*/
2
3
/*-
4
 * Copyright (c) 1990, 1993, 1994
5
 *	The Regents of the University of California.  All rights reserved.
6
 *
7
 * This code is derived from software contributed to Berkeley by
8
 * Mike Olson.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 * 3. Neither the name of the University nor the names of its contributors
19
 *    may be used to endorse or promote products derived from this software
20
 *    without specific prior written permission.
21
 *
22
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
 * SUCH DAMAGE.
33
 */
34
35
#include <sys/types.h>
36
#include <sys/mman.h>
37
#include <sys/stat.h>
38
39
#include <errno.h>
40
#include <fcntl.h>
41
#include <limits.h>
42
#include <stddef.h>
43
#include <stdio.h>
44
#include <unistd.h>
45
46
#include <db.h>
47
#include "recno.h"
48
49
DB *
50
__rec_open(const char *fname, int flags, int mode, const RECNOINFO *openinfo,
51
    int dflags)
52
{
53
	BTREE *t;
54
	BTREEINFO btopeninfo;
55
	DB *dbp;
56
	PAGE *h;
57
	struct stat sb;
58
	int rfd, sverrno;
59
60
	/* Open the user's file -- if this fails, we're done. */
61
	if (fname != NULL && (rfd = open(fname, flags, mode)) < 0)
62
		return (NULL);
63
64
	/* Create a btree in memory (backed by disk). */
65
	dbp = NULL;
66
	if (openinfo) {
67
		if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
68
			goto einval;
69
		btopeninfo.flags = 0;
70
		btopeninfo.cachesize = openinfo->cachesize;
71
		btopeninfo.maxkeypage = 0;
72
		btopeninfo.minkeypage = 0;
73
		btopeninfo.psize = openinfo->psize;
74
		btopeninfo.compare = NULL;
75
		btopeninfo.prefix = NULL;
76
		btopeninfo.lorder = openinfo->lorder;
77
		dbp = __bt_open(openinfo->bfname,
78
		    O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo, dflags);
79
	} else
80
		dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL, dflags);
81
	if (dbp == NULL)
82
		goto err;
83
84
	/*
85
	 * Some fields in the tree structure are recno specific.  Fill them
86
	 * in and make the btree structure look like a recno structure.  We
87
	 * don't change the bt_ovflsize value, it's close enough and slightly
88
	 * bigger.
89
	 */
90
	t = dbp->internal;
91
	if (openinfo) {
92
		if (openinfo->flags & R_FIXEDLEN) {
93
			F_SET(t, R_FIXLEN);
94
			t->bt_reclen = openinfo->reclen;
95
			if (t->bt_reclen == 0)
96
				goto einval;
97
		}
98
		t->bt_bval = openinfo->bval;
99
	} else
100
		t->bt_bval = '\n';
101
102
	F_SET(t, R_RECNO);
103
	if (fname == NULL)
104
		F_SET(t, R_EOF | R_INMEM);
105
	else
106
		t->bt_rfd = rfd;
107
108
	if (fname != NULL) {
109
		/*
110
		 * In 4.4BSD, stat(2) returns true for ISSOCK on pipes.
111
		 * Unfortunately, that's not portable, so we use lseek
112
		 * and check the errno values.
113
		 */
114
		errno = 0;
115
		if (lseek(rfd, 0, SEEK_CUR) == -1 && errno == ESPIPE) {
116
			switch (flags & O_ACCMODE) {
117
			case O_RDONLY:
118
				F_SET(t, R_RDONLY);
119
				break;
120
			default:
121
				goto einval;
122
			}
123
slow:			if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
124
				goto err;
125
			F_SET(t, R_CLOSEFP);
126
			t->bt_irec =
127
			    F_ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe;
128
		} else {
129
			switch (flags & O_ACCMODE) {
130
			case O_RDONLY:
131
				F_SET(t, R_RDONLY);
132
				break;
133
			case O_RDWR:
134
				break;
135
			default:
136
				goto einval;
137
			}
138
139
			if (fstat(rfd, &sb))
140
				goto err;
141
			if (sb.st_size == 0)
142
				F_SET(t, R_EOF);
143
			else {
144
				goto slow;
145
			}
146
		}
147
	}
148
149
	/* Use the recno routines. */
150
	dbp->close = __rec_close;
151
	dbp->del = __rec_delete;
152
	dbp->fd = __rec_fd;
153
	dbp->get = __rec_get;
154
	dbp->put = __rec_put;
155
	dbp->seq = __rec_seq;
156
	dbp->sync = __rec_sync;
157
158
	/* If the root page was created, reset the flags. */
159
	if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL)
160
		goto err;
161
	if ((h->flags & P_TYPE) == P_BLEAF) {
162
		F_CLR(h, P_TYPE);
163
		F_SET(h, P_RLEAF);
164
		mpool_put(t->bt_mp, h, MPOOL_DIRTY);
165
	} else
166
		mpool_put(t->bt_mp, h, 0);
167
168
	if (openinfo && openinfo->flags & R_SNAPSHOT &&
169
	    !F_ISSET(t, R_EOF | R_INMEM) &&
170
	    t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
171
		goto err;
172
	return (dbp);
173
174
einval:	errno = EINVAL;
175
err:	sverrno = errno;
176
	if (dbp != NULL)
177
		(void)__bt_close(dbp);
178
	if (fname != NULL)
179
		(void)close(rfd);
180
	errno = sverrno;
181
	return (NULL);
182
}
183
184
int
185
__rec_fd(const DB *dbp)
186
{
187
	BTREE *t;
188
189
	t = dbp->internal;
190
191
	/* Toss any page pinned across calls. */
192
	if (t->bt_pinned != NULL) {
193
		mpool_put(t->bt_mp, t->bt_pinned, 0);
194
		t->bt_pinned = NULL;
195
	}
196
197
	/* In-memory database can't have a file descriptor. */
198
	if (F_ISSET(t, R_INMEM)) {
199
		errno = ENOENT;
200
		return (-1);
201
	}
202
	return (t->bt_rfd);
203
}