home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 July / macformat-026.iso / mac / Shareware City / Developers / berkeleydb1.73 / Berkeley_db / recno / rec_open.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-27  |  6.7 KB  |  252 lines  |  [TEXT/MPS ]

  1. /*-
  2.  * Copyright (c) 1990, 1993
  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.4 (Berkeley) 9/7/93";
  39. #endif /* LIBC_SCCS and not lint */
  40.  
  41. #if defined(macintosh) && (defined(powerc) || defined(__powerc))
  42. #include "OurMalloc.h"
  43. #endif
  44.  
  45. #include <sys/types.h>
  46. #ifndef macintosh
  47. #include <sys/mman.h>
  48. #endif
  49. #include <sys/stat.h>
  50.  
  51. #ifdef macintosh
  52. #include <sys/fcntl.h>
  53. #endif
  54.  
  55. #include <errno.h>
  56. #include <fcntl.h>
  57. #include <limits.h>
  58. #include <stddef.h>
  59. #include <stdio.h>
  60. #ifdef macintosh
  61. FILE * fdopen(int fd, char * mode);
  62. #else 
  63. #include <unistd.h>
  64. #endif
  65.  
  66. #define    __DBINTERFACE_PRIVATE
  67. #include <db.h>
  68. #include "recno.h"
  69.  
  70. DB *
  71. __rec_open(fname, flags, mode, openinfo, dflags)
  72.     const char *fname;
  73.     int flags, mode, dflags;
  74.     const RECNOINFO *openinfo;
  75. {
  76.     BTREE *t;
  77.     BTREEINFO btopeninfo;
  78.     DB *dbp;
  79.     PAGE *h;
  80.     struct stat sb;
  81.     int rfd, sverrno;
  82.  
  83.     /* Open the user's file -- if this fails, we're done. */
  84. #ifdef macintosh
  85.     if (fname != NULL && (rfd = open(fname, flags)) < 0)
  86. #else
  87.     if (fname != NULL && (rfd = open(fname, flags, mode)) < 0)
  88. #endif
  89.         return (NULL);
  90.  
  91.     /* Create a btree in memory (backed by disk). */
  92.     dbp = NULL;
  93.     if (openinfo) {
  94.         if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
  95.             goto einval;
  96.         btopeninfo.flags = 0;
  97.         btopeninfo.cachesize = openinfo->cachesize;
  98.         btopeninfo.maxkeypage = 0;
  99.         btopeninfo.minkeypage = 0;
  100.         btopeninfo.psize = openinfo->psize;
  101.         btopeninfo.compare = NULL;
  102.         btopeninfo.prefix = NULL;
  103.         btopeninfo.lorder = openinfo->lorder;
  104.         dbp = __bt_open(openinfo->bfname,
  105.             O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo, dflags);
  106.     } else
  107.         dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL, dflags);
  108.     if (dbp == NULL)
  109.         goto err;
  110.  
  111.     /*
  112.      * Some fields in the tree structure are recno specific.  Fill them
  113.      * in and make the btree structure look like a recno structure.  We
  114.      * don't change the bt_ovflsize value, it's close enough and slightly
  115.      * bigger.
  116.      */
  117.     t = dbp->internal;
  118.     if (openinfo) {
  119.         if (openinfo->flags & R_FIXEDLEN) {
  120.             SET(t, R_FIXLEN);
  121.             t->bt_reclen = openinfo->reclen;
  122.             if (t->bt_reclen == 0)
  123.                 goto einval;
  124.         }
  125.         t->bt_bval = openinfo->bval;
  126.     } else
  127.         t->bt_bval = '\n';
  128.  
  129.     SET(t, R_RECNO);
  130.     if (fname == NULL)
  131.         SET(t, R_EOF | R_INMEM);
  132.     else
  133.         t->bt_rfd = rfd;
  134.     t->bt_rcursor = 0;
  135.  
  136.     /*
  137.      * In 4.4BSD stat(2) returns true for ISSOCK on pipes.  Until
  138.      * then, this is fairly close.  Pipes are read-only.
  139.      */
  140.     if (fname != NULL) {
  141.         if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) {
  142.             switch (flags & O_ACCMODE) {
  143.             case O_RDONLY:
  144.                 SET(t, R_RDONLY);
  145.                 break;
  146.             default:
  147.                 goto einval;
  148.             }
  149. slow:        if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
  150.                 goto err;
  151.             SET(t, R_CLOSEFP);
  152.             t->bt_irec =
  153.                 ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe;
  154.         } else {
  155.             switch (flags & O_ACCMODE) {
  156.             case O_RDONLY:
  157.                 SET(t, R_RDONLY);
  158.                 break;
  159.             case O_RDWR:
  160.                 break;
  161.             default:
  162.                 goto einval;
  163.             }
  164.  
  165.             if (fstat(rfd, &sb))
  166.                 goto err;
  167.             /*
  168.              * Kluge -- we'd like to test to see if the file is too
  169.              * big to mmap.  Since, we don't know what size or type
  170.              * off_t's or size_t's are, what the largest unsigned
  171.              * integral type is, or what random insanity the local
  172.              * C compiler will perpetrate, doing the comparison in
  173.              * a portable way is flatly impossible.  Hope that mmap
  174.              * fails if the file is too large.
  175.              */
  176.             if (sb.st_size == 0)
  177.                 SET(t, R_EOF);
  178.             else {
  179.                 t->bt_msize = sb.st_size;
  180. #ifdef macintosh
  181.                 goto slow;
  182. #else
  183.                 if ((t->bt_smap = mmap(NULL, t->bt_msize,
  184.                     PROT_READ, MAP_PRIVATE, rfd,
  185.                     (off_t)0)) == (caddr_t)-1)
  186.                     goto slow;
  187.                 t->bt_cmap = t->bt_smap;
  188.                 t->bt_emap = t->bt_smap + sb.st_size;
  189.                 t->bt_irec = ISSET(t, R_FIXLEN) ?
  190.                     __rec_fmap : __rec_vmap;
  191.                 SET(t, R_MEMMAPPED);
  192. #endif
  193.             }
  194.         }
  195.     }
  196.  
  197.     /* Use the recno routines. */
  198.     dbp->close = __rec_close;
  199.     dbp->del = __rec_delete;
  200.     dbp->fd = __rec_fd;
  201.     dbp->get = __rec_get;
  202.     dbp->put = __rec_put;
  203.     dbp->seq = __rec_seq;
  204.     dbp->sync = __rec_sync;
  205.  
  206.     /* If the root page was created, reset the flags. */
  207.     if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL)
  208.         goto err;
  209.     if ((h->flags & P_TYPE) == P_BLEAF) {
  210.         h->flags = h->flags & ~P_TYPE | P_RLEAF;
  211.         mpool_put(t->bt_mp, h, MPOOL_DIRTY);
  212.     } else
  213.         mpool_put(t->bt_mp, h, 0);
  214.  
  215.     if (openinfo && openinfo->flags & R_SNAPSHOT &&
  216.         !ISSET(t, R_EOF | R_INMEM) &&
  217.         t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
  218.                 goto err;
  219.     return (dbp);
  220.  
  221. einval:    errno = EINVAL;
  222. err:    sverrno = errno;
  223.     if (dbp != NULL)
  224.         (void)__bt_close(dbp);
  225.     if (fname != NULL)
  226.         (void)close(rfd);
  227.     errno = sverrno;
  228.     return (NULL);
  229. }
  230.  
  231. int
  232. __rec_fd(dbp)
  233.     const DB *dbp;
  234. {
  235.     BTREE *t;
  236.  
  237.     t = dbp->internal;
  238.  
  239.     /* Toss any page pinned across calls. */
  240.     if (t->bt_pinned != NULL) {
  241.         mpool_put(t->bt_mp, t->bt_pinned, 0);
  242.         t->bt_pinned = NULL;
  243.     }
  244.  
  245.     /* In-memory database can't have a file descriptor. */
  246.     if (ISSET(t, R_INMEM)) {
  247.         errno = ENOENT;
  248.         return (-1);
  249.     }
  250.     return (t->bt_rfd);
  251. }
  252.