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

Line Branch Exec Source
1
/*	$OpenBSD: rec_close.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
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 * 3. Neither the name of the University nor the names of its contributors
16
 *    may be used to endorse or promote products derived from this software
17
 *    without specific prior written permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
 * SUCH DAMAGE.
30
 */
31
32
#include <sys/types.h>
33
#include <sys/uio.h>
34
#include <sys/mman.h>
35
36
#include <errno.h>
37
#include <limits.h>
38
#include <stdio.h>
39
#include <unistd.h>
40
41
#include <db.h>
42
#include "recno.h"
43
44
/*
45
 * __REC_CLOSE -- Close a recno tree.
46
 *
47
 * Parameters:
48
 *	dbp:	pointer to access method
49
 *
50
 * Returns:
51
 *	RET_ERROR, RET_SUCCESS
52
 */
53
int
54
__rec_close(DB *dbp)
55
{
56
	BTREE *t;
57
	int status;
58
59
	t = dbp->internal;
60
61
	/* Toss any page pinned across calls. */
62
	if (t->bt_pinned != NULL) {
63
		mpool_put(t->bt_mp, t->bt_pinned, 0);
64
		t->bt_pinned = NULL;
65
	}
66
67
	if (__rec_sync(dbp, 0) == RET_ERROR)
68
		return (RET_ERROR);
69
70
	/* Committed to closing. */
71
	status = RET_SUCCESS;
72
73
	if (!F_ISSET(t, R_INMEM)) {
74
		if (F_ISSET(t, R_CLOSEFP)) {
75
			if (fclose(t->bt_rfp))
76
				status = RET_ERROR;
77
		} else {
78
			if (close(t->bt_rfd))
79
				status = RET_ERROR;
80
		}
81
	}
82
83
	if (__bt_close(dbp) == RET_ERROR)
84
		status = RET_ERROR;
85
86
	return (status);
87
}
88
89
/*
90
 * __REC_SYNC -- sync the recno tree to disk.
91
 *
92
 * Parameters:
93
 *	dbp:	pointer to access method
94
 *
95
 * Returns:
96
 *	RET_SUCCESS, RET_ERROR.
97
 */
98
int
99
__rec_sync(const DB *dbp, u_int flags)
100
{
101
	struct iovec iov[2];
102
	BTREE *t;
103
	DBT data, key;
104
	off_t off;
105
	recno_t scursor, trec;
106
	int status;
107
108
	t = dbp->internal;
109
110
	/* Toss any page pinned across calls. */
111
	if (t->bt_pinned != NULL) {
112
		mpool_put(t->bt_mp, t->bt_pinned, 0);
113
		t->bt_pinned = NULL;
114
	}
115
116
	if (flags == R_RECNOSYNC)
117
		return (__bt_sync(dbp, 0));
118
119
	if (F_ISSET(t, R_RDONLY | R_INMEM) || !F_ISSET(t, R_MODIFIED))
120
		return (RET_SUCCESS);
121
122
	/* Read any remaining records into the tree. */
123
	if (!F_ISSET(t, R_EOF) && t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
124
		return (RET_ERROR);
125
126
	/* Rewind the file descriptor. */
127
	if (lseek(t->bt_rfd, 0, SEEK_SET) != 0)
128
		return (RET_ERROR);
129
130
	/* Save the cursor. */
131
	scursor = t->bt_cursor.rcursor;
132
133
	key.size = sizeof(recno_t);
134
	key.data = &trec;
135
136
	if (F_ISSET(t, R_FIXLEN)) {
137
		/*
138
		 * We assume that fixed length records are all fixed length.
139
		 * Any that aren't are either EINVAL'd or corrected by the
140
		 * record put code.
141
		 */
142
		status = (dbp->seq)(dbp, &key, &data, R_FIRST);
143
		while (status == RET_SUCCESS) {
144
			if (write(t->bt_rfd, data.data, data.size) != data.size)
145
				return (RET_ERROR);
146
			status = (dbp->seq)(dbp, &key, &data, R_NEXT);
147
		}
148
	} else {
149
		iov[1].iov_base = &t->bt_bval;
150
		iov[1].iov_len = 1;
151
152
		status = (dbp->seq)(dbp, &key, &data, R_FIRST);
153
		while (status == RET_SUCCESS) {
154
			iov[0].iov_base = data.data;
155
			iov[0].iov_len = data.size;
156
			if (writev(t->bt_rfd, iov, 2) != data.size + 1)
157
				return (RET_ERROR);
158
			status = (dbp->seq)(dbp, &key, &data, R_NEXT);
159
		}
160
	}
161
162
	/* Restore the cursor. */
163
	t->bt_cursor.rcursor = scursor;
164
165
	if (status == RET_ERROR)
166
		return (RET_ERROR);
167
	if ((off = lseek(t->bt_rfd, 0, SEEK_CUR)) == -1)
168
		return (RET_ERROR);
169
	if (ftruncate(t->bt_rfd, off))
170
		return (RET_ERROR);
171
	F_CLR(t, R_MODIFIED);
172
	return (RET_SUCCESS);
173
}