home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / EDITOR / NVI179B / NVI179B.ZIP / db / recno / rec_open.c < prev    next >
C/C++ Source or Header  |  1997-06-01  |  7KB  |  247 lines

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