📄 btfix.cpp
字号:
/* Copyright (c) 1989 Citadel */
/* All Rights Reserved */
/* #ident "@(#)btfix.c 1.4 - 90/06/20" */
#include <blkio.h>
#include <errno.h>
/*#include <stddef.h>*/
#include <stdio.h>
/*#include <stdlib.h>*/
/*#include <string.h>*/
/* local headers */
#include "btree_.h"
#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif
/*man---------------------------------------------------------------------------
NAME
btfix - fix a corrupt btree file
SYNOPSIS
int btfix(filename, m, keysize, fldc, fldv)
const char *filename;
int m;
size_t keysize;
int fldc;
const btfield_t fldv[];
DESCRIPTION
The btfix function reconstructs a corrupt btree. The parameters
are the same as for btcreate. It may be specified that the
degree of the btree and the key size be read from the header by
passing a value of zero for m and keysize, respectively. These
parameters are provided for cases where the header is corrupt.
btfix will fail if one or more of the following is true:
[EINVAL] filename is the NULL pointer.
[EINVAL] fldc is less than 1.
[EINVAL] fldv is the NULL pointer.
[EINVAL] fldv contains an invalid field
definition.
[ENOENT] The named btree file does not exist.
[BTEEOF] Incomplete file header.
[BTEMFILE] Too many open btrees. The maximum
is defined as BTOPEN_MAX in btree.h.
SEE ALSO
btcreate.
DIAGNOSTICS
Upon successful completion, a value of 0 is returned. Otherwise,
a value of -1 is returned, and errno set to indicate the error.
NOTES
It is recommended that a backup copy of the corrupted file be
made before calling a reconstruction routine such as btfix.
btfix uses a temporary file to reconstruct the btree. If
security is important, a call should be added to set the
permissions of the temporary file (e.g., chmod in UNIX) before
data is written to it. This has not been included because such a
call is not portable.
------------------------------------------------------------------------------*/
int btfix(const char *filename, int m, size_t keysize, int fldc, const btfield_t fldv[])
{
int terrno = 0; /* tmp errno */
bthdr_t bthdr; /* btree header */
char tmpbtname[L_tmpnam + 1]; /* temporary btree file name */
btree_t *btp = NULL; /* btree */
btree_t btree; /* used for bt_blksize */
BLKFILE *bp = NULL; /* block file */
btnode_t *btnp = NULL; /* btree node */
bpos_t bn = 0; /* block number */
int k = 0; /* counter */
void *buf = NULL;
/* validate arguments */
if (filename == NULL) {
errno = EINVAL;
return -1;
}
/* open original btree file */
bp = bopen(filename, "r", sizeof(bthdr_t), (size_t)1, (size_t)0);
if (bp == NULL) {
if (errno != ENOENT) BTEPRINT;
return -1;
}
if (lockb(bp, B_RDLCK, (bpos_t)0, (bpos_t)0) == -1) { /* read lock */
terrno = errno;
bclose(bp);
errno = terrno;
return -1;
}
/* read header and set block size */
if (bgeth(bp, &bthdr) == -1) {
BTEPRINT;
if (errno == BEEOF) errno = BTEEOF;
terrno = errno;
bclose(bp);
errno = terrno;
return -1;
}
if (m == 0) {
m = bthdr.m;
}
if (keysize == 0) {
keysize = bthdr.keysize;
}
btree.bthdr.m = m; /* set block size */
btree.bthdr.keysize = keysize;
if (bsetvbuf(bp, NULL, bt_blksize(&btree), (size_t)0) == -1) {
BTEPRINT;
terrno = errno;
bclose(bp);
errno = terrno;
return -1;
}
/* create temporary btree */
tmpnam(tmpbtname);
if (btcreate(tmpbtname, m, keysize, fldc, fldv) == -1){
BTEPRINT;
terrno = errno;
bclose(bp);
errno = terrno;
return -1;
}
/*
If security is important, insert a call here
to set the permissions of file tmpbtname. In UNIX, for
example,
#include <sys/types.h>
#include <sys/stat.h>
if (chmod(tmpbtname, S_IRUSR | S_IWUSR) == -1) {
BTEPRINT;
terrno = errno;
bclose(bp);
errno = terrno;
return -1;
}
*/
btp = btopen(tmpbtname, "r+", fldc, fldv);
if (btp == NULL) {
BTEPRINT;
terrno = errno;
bclose(bp);
errno = terrno;
return -1;
}
/* create in-core btree node */
btnp = bt_ndalloc(btp);
if (btnp == NULL) {
BTEPRINT;
terrno = errno;
bclose(bp);
btclose(btp);
errno = terrno;
return -1;
}
/* create buffer for reading blocks */
buf = calloc((size_t)1, bt_blksize(&btree));
if (buf == NULL) {
BTEPRINT;
terrno = errno;
bclose(bp);
errno = terrno;
return -1;
}
/* write lock temporary btree */
if (btlock(btp, BT_WRLCK) == -1) {
terrno = errno;
bclose(bp);
free(buf);
btclose(btp);
bt_ndfree(btnp);
errno = terrno;
return -1;
}
/* main loop */
for (bn = 1; ; ++bn) {
if (bgetb(bp, bn, buf) == -1) {
if (errno == BEEOF) {
break;
}
BTEPRINT;
terrno = errno;
bclose(bp);
free(buf);
btclose(btp);
bt_ndfree(btnp);
errno = terrno;
return -1;
}
bt_fltocr(btp, btnp, buf); /* copy to in-memory node */
if ((btnp->n != 0) && bt_ndleaf(btnp)) {
for (k = 1; k <= min(btnp->n, bt_ndmax(btp)); ++k) {
if (btinsert(btp, bt_kykeyp(btp, btnp, k)) == -1) {
if (errno != BTEDUP) {
BTEPRINT;
terrno = errno;
bclose(bp);
free(buf);
btclose(btp);
bt_ndfree(btnp);
errno = terrno;
return -1;
}
}
}
}
}
/* free memory */
free(buf);
bt_ndfree(btnp);
/* close and remove original btree file */
if (bclose(bp) == -1) {
BTEPRINT;
terrno = errno;
btclose(btp);
errno = terrno;
return -1;
}
if (remove(filename) != 0) {
BTEPRINT;
terrno = errno;
btclose(btp);
errno = terrno;
return -1;
}
/* move temporary file to filename */
if (rename(tmpbtname, filename) != 0) {
BTEPRINT;
terrno = errno;
btclose(btp);
errno = terrno;
return -1;
}
/* close and remove temporary file */
if (btclose(btp) == -1) {
BTEPRINT;
return -1;
}
if (remove(tmpbtname) != 0) {
BTEPRINT;
return -1;
}
errno = 0;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -