/*-1* SPDX-License-Identifier: BSD-3-Clause2*3* Copyright (c) 1990, 1993, 19944* The Regents of the University of California. All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14* 3. Neither the name of the University nor the names of its contributors15* may be used to endorse or promote products derived from this software16* without specific prior written permission.17*18* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND19* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE20* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE21* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE22* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL23* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS24* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)25* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT26* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY27* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF28* SUCH DAMAGE.29*/3031#include "namespace.h"32#include <sys/types.h>33#include <sys/uio.h>34#include <sys/mman.h>3536#include <errno.h>37#include <limits.h>38#include <stdio.h>39#include <unistd.h>40#include "un-namespace.h"4142#include <db.h>43#include "recno.h"4445/*46* __REC_CLOSE -- Close a recno tree.47*48* Parameters:49* dbp: pointer to access method50*51* Returns:52* RET_ERROR, RET_SUCCESS53*/54int55__rec_close(DB *dbp)56{57BTREE *t;58int status;5960t = dbp->internal;6162/* Toss any page pinned across calls. */63if (t->bt_pinned != NULL) {64mpool_put(t->bt_mp, t->bt_pinned, 0);65t->bt_pinned = NULL;66}6768if (__rec_sync(dbp, 0) == RET_ERROR)69return (RET_ERROR);7071/* Committed to closing. */72status = RET_SUCCESS;73if (F_ISSET(t, R_MEMMAPPED) && munmap(t->bt_smap, t->bt_msize))74status = RET_ERROR;7576if (!F_ISSET(t, R_INMEM)) {77if (F_ISSET(t, R_CLOSEFP)) {78if (fclose(t->bt_rfp))79status = RET_ERROR;80} else {81if (_close(t->bt_rfd))82status = RET_ERROR;83}84}8586if (__bt_close(dbp) == RET_ERROR)87status = RET_ERROR;8889return (status);90}9192/*93* __REC_SYNC -- sync the recno tree to disk.94*95* Parameters:96* dbp: pointer to access method97*98* Returns:99* RET_SUCCESS, RET_ERROR.100*/101int102__rec_sync(const DB *dbp, u_int flags)103{104struct iovec iov[2];105BTREE *t;106DBT data, key;107off_t off;108recno_t scursor, trec;109int status;110111t = dbp->internal;112113/* Toss any page pinned across calls. */114if (t->bt_pinned != NULL) {115mpool_put(t->bt_mp, t->bt_pinned, 0);116t->bt_pinned = NULL;117}118119if (flags == R_RECNOSYNC)120return (__bt_sync(dbp, 0));121122if (F_ISSET(t, R_RDONLY | R_INMEM) || !F_ISSET(t, R_MODIFIED))123return (RET_SUCCESS);124125/* Read any remaining records into the tree. */126if (!F_ISSET(t, R_EOF) && t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)127return (RET_ERROR);128129/* Rewind the file descriptor. */130if (lseek(t->bt_rfd, (off_t)0, SEEK_SET) != 0)131return (RET_ERROR);132133/* Save the cursor. */134scursor = t->bt_cursor.rcursor;135136key.size = sizeof(recno_t);137key.data = &trec;138139if (F_ISSET(t, R_FIXLEN)) {140/*141* We assume that fixed length records are all fixed length.142* Any that aren't are either EINVAL'd or corrected by the143* record put code.144*/145status = (dbp->seq)(dbp, &key, &data, R_FIRST);146while (status == RET_SUCCESS) {147if (_write(t->bt_rfd, data.data, data.size) !=148(ssize_t)data.size)149return (RET_ERROR);150status = (dbp->seq)(dbp, &key, &data, R_NEXT);151}152} else {153iov[1].iov_base = &t->bt_bval;154iov[1].iov_len = 1;155156status = (dbp->seq)(dbp, &key, &data, R_FIRST);157while (status == RET_SUCCESS) {158iov[0].iov_base = data.data;159iov[0].iov_len = data.size;160if (_writev(t->bt_rfd, iov, 2) != (ssize_t)(data.size + 1))161return (RET_ERROR);162status = (dbp->seq)(dbp, &key, &data, R_NEXT);163}164}165166/* Restore the cursor. */167t->bt_cursor.rcursor = scursor;168169if (status == RET_ERROR)170return (RET_ERROR);171if ((off = lseek(t->bt_rfd, (off_t)0, SEEK_CUR)) == -1)172return (RET_ERROR);173if (ftruncate(t->bt_rfd, off))174return (RET_ERROR);175F_CLR(t, R_MODIFIED);176return (RET_SUCCESS);177}178179180