150995Sbostic /*- 250995Sbostic * Copyright (c) 1990 The Regents of the University of California. 350995Sbostic * All rights reserved. 450995Sbostic * 550995Sbostic * This code is derived from software contributed to Berkeley by 650995Sbostic * Mike Olson. 750995Sbostic * 850995Sbostic * %sccs.include.redist.c% 950995Sbostic */ 1050995Sbostic 1150995Sbostic #if defined(LIBC_SCCS) && !defined(lint) 12*60269Sbostic static char sccsid[] = "@(#)rec_open.c 5.20 (Berkeley) 05/24/93"; 1350995Sbostic #endif /* LIBC_SCCS and not lint */ 1450995Sbostic 1550995Sbostic #include <sys/types.h> 1650995Sbostic #include <sys/mman.h> 1750995Sbostic #include <sys/stat.h> 1854362Sbostic 1956757Sbostic #include <errno.h> 2050995Sbostic #include <fcntl.h> 2150995Sbostic #include <limits.h> 2256757Sbostic #include <stddef.h> 2356757Sbostic #include <stdio.h> 2450995Sbostic #include <unistd.h> 2556757Sbostic 2657933Sbostic #include <db.h> 2751090Sbostic #include "recno.h" 2850995Sbostic 2950995Sbostic DB * 3050995Sbostic __rec_open(fname, flags, mode, openinfo) 3150995Sbostic const char *fname; 3250995Sbostic int flags, mode; 3350995Sbostic const RECNOINFO *openinfo; 3450995Sbostic { 3550995Sbostic BTREE *t; 3650995Sbostic BTREEINFO btopeninfo; 3750995Sbostic DB *dbp; 3850995Sbostic PAGE *h; 3950995Sbostic struct stat sb; 4058751Sbostic int rfd, sverrno; 4150995Sbostic 4250995Sbostic /* Open the user's file -- if this fails, we're done. */ 4356757Sbostic if (fname != NULL && (rfd = open(fname, flags, mode)) < 0) 4450995Sbostic return (NULL); 4550995Sbostic 4650995Sbostic /* Create a btree in memory (backed by disk). */ 4756757Sbostic dbp = NULL; 4850995Sbostic if (openinfo) { 4956757Sbostic if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT)) 5056703Sbostic goto einval; 5150995Sbostic btopeninfo.flags = 0; 5250995Sbostic btopeninfo.cachesize = openinfo->cachesize; 5358790Sralph btopeninfo.maxkeypage = 0; 5458790Sralph btopeninfo.minkeypage = 0; 5560065Sbostic btopeninfo.psize = openinfo->psize; 5650995Sbostic btopeninfo.compare = NULL; 5758790Sralph btopeninfo.prefix = NULL; 5850995Sbostic btopeninfo.lorder = openinfo->lorder; 5960055Sbostic dbp = __bt_open(openinfo->bfname, 6060055Sbostic O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo); 6150995Sbostic } else 6250995Sbostic dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL); 6351090Sbostic if (dbp == NULL) 6451090Sbostic goto err; 6550995Sbostic 6650995Sbostic /* 6750995Sbostic * Some fields in the tree structure are recno specific. Fill them 6851090Sbostic * in and make the btree structure look like a recno structure. We 6951090Sbostic * don't change the bt_ovflsize value, it's close enough and slightly 7051090Sbostic * bigger. 7150995Sbostic */ 7250995Sbostic t = dbp->internal; 7350995Sbostic if (openinfo) { 7455295Sbostic if (openinfo->flags & R_FIXEDLEN) { 7560055Sbostic SET(t, R_FIXLEN); 7655295Sbostic t->bt_reclen = openinfo->reclen; 7756703Sbostic if (t->bt_reclen == 0) 7856703Sbostic goto einval; 7950995Sbostic } 8050995Sbostic t->bt_bval = openinfo->bval; 8150995Sbostic } else 8250995Sbostic t->bt_bval = '\n'; 8350995Sbostic 8460055Sbostic SET(t, R_RECNO); 8558751Sbostic if (fname == NULL) 8660055Sbostic SET(t, R_EOF | R_INMEM); 8758751Sbostic else 8858751Sbostic t->bt_rfd = rfd; 8957007Sbostic t->bt_rcursor = 0; 9050995Sbostic 9150995Sbostic /* 9254286Sbostic * In 4.4BSD stat(2) returns true for ISSOCK on pipes. Until 9354286Sbostic * then, this is fairly close. Pipes are read-only. 9454286Sbostic */ 9558790Sralph if (fname != NULL) { 9656757Sbostic if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) { 9758790Sralph switch (flags & O_ACCMODE) { 9858751Sbostic case O_RDONLY: 9960055Sbostic SET(t, R_RDONLY); 10058751Sbostic break; 10158751Sbostic default: 10258751Sbostic goto einval; 10358751Sbostic } 10457227Sbostic slow: if ((t->bt_rfp = fdopen(rfd, "r")) == NULL) 10556757Sbostic goto err; 10660055Sbostic SET(t, R_CLOSEFP); 10756757Sbostic t->bt_irec = 10860055Sbostic ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe; 10956757Sbostic } else { 11058790Sralph switch (flags & O_ACCMODE) { 11156757Sbostic case O_RDONLY: 11260055Sbostic SET(t, R_RDONLY); 11356757Sbostic break; 11456757Sbostic case O_RDWR: 11556757Sbostic break; 11656757Sbostic default: 11756757Sbostic goto einval; 11856757Sbostic } 11958790Sralph 12058751Sbostic if (fstat(rfd, &sb)) 12158751Sbostic goto err; 12259772Sbostic /* 12359772Sbostic * Kludge -- but we don't know what size an off_t 12459772Sbostic * is or what size a size_t is, although we do 12559772Sbostic * know that the former is signed and the latter 12659772Sbostic * unsigned. 12759772Sbostic */ 12859772Sbostic if (sizeof(sb.st_size) > sizeof(size_t)) { 12959772Sbostic if (sb.st_size > (off_t)SIZE_T_MAX) { 13059772Sbostic errno = EFBIG; 13159772Sbostic goto err; 13259772Sbostic } 13359772Sbostic } else { 13459772Sbostic if ((size_t)sb.st_size > SIZE_T_MAX) { 13559772Sbostic errno = EFBIG; 13659772Sbostic goto err; 13759772Sbostic } 13856757Sbostic } 13958751Sbostic if (sb.st_size == 0) 14060055Sbostic SET(t, R_EOF); 14158751Sbostic else { 14258751Sbostic t->bt_msize = sb.st_size; 14358751Sbostic if ((t->bt_smap = 14458751Sbostic mmap(NULL, t->bt_msize, PROT_READ, 0, rfd, 14558751Sbostic (off_t)0)) == (caddr_t)-1) 14658751Sbostic goto slow; 14758751Sbostic t->bt_cmap = t->bt_smap; 14858751Sbostic t->bt_emap = t->bt_smap + sb.st_size; 14960055Sbostic t->bt_irec = ISSET(t, R_FIXLEN) ? 15058751Sbostic __rec_fmap : __rec_vmap; 15160055Sbostic SET(t, R_MEMMAPPED); 15258751Sbostic } 15356703Sbostic } 15458790Sralph } 15550995Sbostic 15650995Sbostic /* Use the recno routines. */ 15750995Sbostic dbp->close = __rec_close; 15850995Sbostic dbp->del = __rec_delete; 159*60269Sbostic dbp->fd = __rec_fd; 16050995Sbostic dbp->get = __rec_get; 16150995Sbostic dbp->put = __rec_put; 16250995Sbostic dbp->seq = __rec_seq; 16350995Sbostic dbp->sync = __rec_sync; 16450995Sbostic 16550995Sbostic /* If the root page was created, reset the flags. */ 16650995Sbostic if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL) 16750995Sbostic goto err; 16850995Sbostic if ((h->flags & P_TYPE) == P_BLEAF) { 16950995Sbostic h->flags = h->flags & ~P_TYPE | P_RLEAF; 17050995Sbostic mpool_put(t->bt_mp, h, MPOOL_DIRTY); 17150995Sbostic } else 17250995Sbostic mpool_put(t->bt_mp, h, 0); 17350995Sbostic 17450995Sbostic if (openinfo && openinfo->flags & R_SNAPSHOT && 17560055Sbostic !ISSET(t, R_EOF | R_INMEM) && 17650995Sbostic t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR) 17750995Sbostic goto err; 17850995Sbostic return (dbp); 17950995Sbostic 18056703Sbostic einval: errno = EINVAL; 18158751Sbostic err: sverrno = errno; 18258751Sbostic if (dbp != NULL) 18358751Sbostic (void)__bt_close(dbp); 18456757Sbostic if (fname != NULL) 18556757Sbostic (void)close(rfd); 18658751Sbostic errno = sverrno; 18750995Sbostic return (NULL); 18850995Sbostic } 189*60269Sbostic 190*60269Sbostic int 191*60269Sbostic __rec_fd(dbp) 192*60269Sbostic const DB *dbp; 193*60269Sbostic { 194*60269Sbostic BTREE *t; 195*60269Sbostic 196*60269Sbostic t = dbp->internal; 197*60269Sbostic 198*60269Sbostic if (ISSET(t, R_INMEM)) { 199*60269Sbostic errno = ENOENT; 200*60269Sbostic return (-1); 201*60269Sbostic } 202*60269Sbostic return (t->bt_rfd); 203*60269Sbostic } 204