home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / ixemul-45.0-src.tgz / tar.out / contrib / ixemul / db / recno / rec_open.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  7KB  |  237 lines

  1. /*    $NetBSD: rec_open.c,v 1.6 1995/02/27 13:25:05 cgd Exp $    */
  2.  
  3. /*-
  4.  * Copyright (c) 1990, 1993
  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. All advertising materials mentioning features or use of this software
  19.  *    must display the following acknowledgement:
  20.  *    This product includes software developed by the University of
  21.  *    California, Berkeley and its contributors.
  22.  * 4. Neither the name of the University nor the names of its contributors
  23.  *    may be used to endorse or promote products derived from this software
  24.  *    without specific prior written permission.
  25.  *
  26.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  27.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  30.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  35.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  36.  * SUCH DAMAGE.
  37.  */
  38.  
  39. #if defined(LIBC_SCCS) && !defined(lint)
  40. #if 0
  41. static char sccsid[] = "@(#)rec_open.c    8.6 (Berkeley) 2/22/94";
  42. #else
  43. static char rcsid[] = "$NetBSD: rec_open.c,v 1.6 1995/02/27 13:25:05 cgd Exp $";
  44. #endif
  45. #endif /* LIBC_SCCS and not lint */
  46.  
  47. #include <sys/types.h>
  48. #include <sys/mman.h>
  49. #include <sys/stat.h>
  50.  
  51. #include <errno.h>
  52. #include <fcntl.h>
  53. #include <limits.h>
  54. #include <stddef.h>
  55. #include <stdio.h>
  56. #include <unistd.h>
  57.  
  58. #include <db.h>
  59. #include "recno.h"
  60.  
  61. DB *
  62. __rec_open(fname, flags, mode, openinfo, dflags)
  63.     const char *fname;
  64.     int flags, mode, dflags;
  65.     const RECNOINFO *openinfo;
  66. {
  67.     BTREE *t;
  68.     BTREEINFO btopeninfo;
  69.     DB *dbp;
  70.     PAGE *h;
  71.     struct stat sb;
  72.     int rfd = 0, sverrno;
  73.  
  74.     /* Open the user's file -- if this fails, we're done. */
  75.     if (fname != NULL && (rfd = open(fname, flags, mode)) < 0)
  76.         return (NULL);
  77.  
  78.     /* Create a btree in memory (backed by disk). */
  79.     dbp = NULL;
  80.     if (openinfo) {
  81.         if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
  82.             goto einval;
  83.         btopeninfo.flags = 0;
  84.         btopeninfo.cachesize = openinfo->cachesize;
  85.         btopeninfo.maxkeypage = 0;
  86.         btopeninfo.minkeypage = 0;
  87.         btopeninfo.psize = openinfo->psize;
  88.         btopeninfo.compare = NULL;
  89.         btopeninfo.prefix = NULL;
  90.         btopeninfo.lorder = openinfo->lorder;
  91.         dbp = __bt_open(openinfo->bfname,
  92.             O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo, dflags);
  93.     } else
  94.         dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL, dflags);
  95.     if (dbp == NULL)
  96.         goto err;
  97.  
  98.     /*
  99.      * Some fields in the tree structure are recno specific.  Fill them
  100.      * in and make the btree structure look like a recno structure.  We
  101.      * don't change the bt_ovflsize value, it's close enough and slightly
  102.      * bigger.
  103.      */
  104.     t = dbp->internal;
  105.     if (openinfo) {
  106.         if (openinfo->flags & R_FIXEDLEN) {
  107.             SET(t, R_FIXLEN);
  108.             t->bt_reclen = openinfo->reclen;
  109.             if (t->bt_reclen == 0)
  110.                 goto einval;
  111.         }
  112.         t->bt_bval = openinfo->bval;
  113.     } else
  114.         t->bt_bval = '\n';
  115.  
  116.     SET(t, R_RECNO);
  117.     if (fname == NULL)
  118.         SET(t, R_EOF | R_INMEM);
  119.     else
  120.         t->bt_rfd = rfd;
  121.     t->bt_rcursor = 0;
  122.  
  123.     if (fname != NULL) {
  124.         /*
  125.          * In 4.4BSD, stat(2) returns true for ISSOCK on pipes.
  126.          * Unfortunately, that's not portable, so we use lseek
  127.          * and check the errno values.
  128.          */
  129.         errno = 0;
  130.         if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) {
  131.             switch (flags & O_ACCMODE) {
  132.             case O_RDONLY:
  133.                 SET(t, R_RDONLY);
  134.                 break;
  135.             default:
  136.                 goto einval;
  137.             }
  138. slow:            if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
  139.                 goto err;
  140.             SET(t, R_CLOSEFP);
  141.             t->bt_irec =
  142.                 ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe;
  143.         } else {
  144.             switch (flags & O_ACCMODE) {
  145.             case O_RDONLY:
  146.                 SET(t, R_RDONLY);
  147.                 break;
  148.             case O_RDWR:
  149.                 break;
  150.             default:
  151.                 goto einval;
  152.             }
  153.  
  154.             if (fstat(rfd, &sb))
  155.                 goto err;
  156.             /*
  157.              * Kluge -- we'd like to test to see if the file is too
  158.              * big to mmap.  Since, we don't know what size or type
  159.              * off_t's or size_t's are, what the largest unsigned
  160.              * integral type is, or what random insanity the local
  161.              * C compiler will perpetrate, doing the comparison in
  162.              * a portable way is flatly impossible.  Hope that mmap
  163.              * fails if the file is too large.
  164.              */
  165.             if (sb.st_size == 0)
  166.                 SET(t, R_EOF);
  167.             else {
  168.                 t->bt_msize = sb.st_size;
  169.                 if ((t->bt_smap = mmap(NULL, t->bt_msize,
  170.                     PROT_READ, MAP_PRIVATE, rfd,
  171.                     (off_t)0)) == (caddr_t)-1)
  172.                     goto slow;
  173.                 t->bt_cmap = t->bt_smap;
  174.                 t->bt_emap = t->bt_smap + sb.st_size;
  175.                 t->bt_irec = ISSET(t, R_FIXLEN) ?
  176.                     __rec_fmap : __rec_vmap;
  177.                 SET(t, R_MEMMAPPED);
  178.             }
  179.         }
  180.     }
  181.  
  182.     /* Use the recno routines. */
  183.     dbp->close = __rec_close;
  184.     dbp->del = __rec_delete;
  185.     dbp->fd = __rec_fd;
  186.     dbp->get = __rec_get;
  187.     dbp->put = __rec_put;
  188.     dbp->seq = __rec_seq;
  189.     dbp->sync = __rec_sync;
  190.  
  191.     /* If the root page was created, reset the flags. */
  192.     if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL)
  193.         goto err;
  194.     if ((h->flags & P_TYPE) == P_BLEAF) {
  195.         h->flags = (h->flags & ~P_TYPE) | P_RLEAF;
  196.         mpool_put(t->bt_mp, h, MPOOL_DIRTY);
  197.     } else
  198.         mpool_put(t->bt_mp, h, 0);
  199.  
  200.     if (openinfo && openinfo->flags & R_SNAPSHOT &&
  201.         !ISSET(t, R_EOF | R_INMEM) &&
  202.         t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
  203.                 goto err;
  204.     return (dbp);
  205.  
  206. einval:    errno = EINVAL;
  207. err:    sverrno = errno;
  208.     if (dbp != NULL)
  209.         (void)__bt_close(dbp);
  210.     if (fname != NULL)
  211.         (void)close(rfd);
  212.     errno = sverrno;
  213.     return (NULL);
  214. }
  215.  
  216. int
  217. __rec_fd(dbp)
  218.     const DB *dbp;
  219. {
  220.     BTREE *t;
  221.  
  222.     t = dbp->internal;
  223.  
  224.     /* Toss any page pinned across calls. */
  225.     if (t->bt_pinned != NULL) {
  226.         mpool_put(t->bt_mp, t->bt_pinned, 0);
  227.         t->bt_pinned = NULL;
  228.     }
  229.  
  230.     /* In-memory database can't have a file descriptor. */
  231.     if (ISSET(t, R_INMEM)) {
  232.         errno = ENOENT;
  233.         return (-1);
  234.     }
  235.     return (t->bt_rfd);
  236. }
  237.