Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

452 Commits   2 Branches   1 Tag
     5         kx /* gdbmopen.c - Open the dbm file and initialize data structures for use. */
     5         kx 
     5         kx /* This file is part of GDBM, the GNU data base manager.
     5         kx    Copyright (C) 1990, 1991, 1993, 2007, 2011, 2013 Free Software Foundation,
     5         kx    Inc.
     5         kx 
     5         kx    GDBM is free software; you can redistribute it and/or modify
     5         kx    it under the terms of the GNU General Public License as published by
     5         kx    the Free Software Foundation; either version 3, or (at your option)
     5         kx    any later version.
     5         kx 
     5         kx    GDBM is distributed in the hope that it will be useful,
     5         kx    but WITHOUT ANY WARRANTY; without even the implied warranty of
     5         kx    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     5         kx    GNU General Public License for more details.
     5         kx 
     5         kx    You should have received a copy of the GNU General Public License
     5         kx    along with GDBM. If not, see <http://www.gnu.org/licenses/>.   */
     5         kx 
     5         kx /* Include system configuration before all else. */
     5         kx #include "autoconf.h"
     5         kx 
     5         kx #include "gdbmdefs.h"
     5         kx 
     5         kx /* Determine our native magic number and bail if we can't. */
     5         kx #if SIZEOF_OFF_T == 4
     5         kx # define GDBM_MAGIC	GDBM_MAGIC32
     5         kx #elif SIZEOF_OFF_T == 8
     5         kx # define GDBM_MAGIC	GDBM_MAGIC64
     5         kx #else
     5         kx # error "Unsupported off_t size, contact GDBM maintainer.  What crazy system is this?!?"
     5         kx #endif
     5         kx 
     5         kx /* Initialize dbm system.  FILE is a pointer to the file name.  If the file
     5         kx    has a size of zero bytes, a file initialization procedure is performed,
     5         kx    setting up the initial structure in the file.  BLOCK_SIZE is used during
     5         kx    initialization to determine the size of various constructs.  If the value
     5         kx    is less than 512, the file system blocksize is used, otherwise the value
     5         kx    of BLOCK_SIZE is used.  BLOCK_SIZE is ignored if the file has previously
     5         kx    initialized.  If FLAGS is set to GDBM_READ the user wants to just
     5         kx    read the database and any call to dbm_store or dbm_delete will fail. Many
     5         kx    readers can access the database at the same time.  If FLAGS is set to
     5         kx    GDBM_WRITE, the user wants both read and write access to the database and
     5         kx    requires exclusive access.  If FLAGS is GDBM_WRCREAT, the user wants
     5         kx    both read and write access to the database and if the database does not
     5         kx    exist, create a new one.  If FLAGS is GDBM_NEWDB, the user want a
     5         kx    new database created, regardless of whether one existed, and wants read
     5         kx    and write access to the new database.  Any error detected will cause a 
     5         kx    return value of null and an approprate value will be in gdbm_errno.  If
     5         kx    no errors occur, a pointer to the "gdbm file descriptor" will be
     5         kx    returned. */
     5         kx    
     5         kx 
     5         kx GDBM_FILE 
     5         kx gdbm_open (const char *file, int block_size, int flags, int mode,
     5         kx      	   void (*fatal_func) (const char *))
     5         kx {
     5         kx   GDBM_FILE dbf;		/* The record to return. */
     5         kx   struct stat file_stat;	/* Space for the stat information. */
     5         kx   int         len;		/* Length of the file name. */
     5         kx   off_t       file_pos;		/* Used with seeks. */
     5         kx   int	      file_block_size;	/* Block size to use for a new file. */
     5         kx   int 	      index;		/* Used as a loop index. */
     5         kx   char        need_trunc;	/* Used with GDBM_NEWDB and locking to avoid
     5         kx 				   truncating a file from under a reader. */
     5         kx   int         rc;               /* temporary error code */ 
     5         kx   int         fbits = 0;        /* additional bits for open(2) flags */
     5         kx   
     5         kx   /* Initialize the gdbm_errno variable. */
     5         kx   gdbm_errno = GDBM_NO_ERROR;
     5         kx 
     5         kx   /* Allocate new info structure. */
     5         kx   dbf = (GDBM_FILE) malloc (sizeof (*dbf));
     5         kx   if (dbf == NULL)
     5         kx     {
     5         kx       gdbm_errno = GDBM_MALLOC_ERROR;
     5         kx       return NULL;
     5         kx     }
     5         kx 
     5         kx   /* Initialize some fields for known values.  This is done so gdbm_close
     5         kx      will work if called before allocating some structures. */
     5         kx   dbf->dir  = NULL;
     5         kx   dbf->bucket = NULL;
     5         kx   dbf->header = NULL;
     5         kx   dbf->bucket_cache = NULL;
     5         kx   dbf->cache_size = 0;
     5         kx 
     5         kx   dbf->memory_mapping = FALSE;
     5         kx   dbf->mapped_size_max = SIZE_T_MAX;
     5         kx   dbf->mapped_region = NULL;
     5         kx   dbf->mapped_size = 0;
     5         kx   dbf->mapped_pos = 0;
     5         kx   dbf->mapped_off = 0;
     5         kx   
     5         kx   /* Save name of file. */
     5         kx   len = strlen (file);
     5         kx   dbf->name = (char *) malloc (len + 1);
     5         kx   if (dbf->name == NULL)
     5         kx     {
     5         kx       free (dbf);
     5         kx       gdbm_errno = GDBM_MALLOC_ERROR;
     5         kx       return NULL;
     5         kx     }
     5         kx   strcpy (dbf->name, file);
     5         kx 
     5         kx   /* Initialize the fatal error routine. */
     5         kx   dbf->fatal_err = fatal_func;
     5         kx 
     5         kx   dbf->fast_write = TRUE;	/* Default to setting fast_write. */
     5         kx   dbf->file_locking = TRUE;	/* Default to doing file locking. */
     5         kx   dbf->central_free = FALSE;	/* Default to not using central_free. */
     5         kx   dbf->coalesce_blocks = FALSE; /* Default to not coalescing blocks. */
     5         kx   
     5         kx   /* GDBM_FAST used to determine whether or not we set fast_write. */
     5         kx   if (flags & GDBM_SYNC)
     5         kx     {
     5         kx       /* If GDBM_SYNC has been requested, don't do fast_write. */
     5         kx       dbf->fast_write = FALSE;
     5         kx     }
     5         kx   if (flags & GDBM_NOLOCK)
     5         kx     {
     5         kx       dbf->file_locking = FALSE;
     5         kx     }
     5         kx   if (flags & GDBM_CLOEXEC)
     5         kx     {
     5         kx       fbits = O_CLOEXEC;
     5         kx       dbf->cloexec = TRUE;
     5         kx     }
     5         kx   else
     5         kx     dbf->cloexec = FALSE;
     5         kx   
     5         kx   /* Open the file. */
     5         kx   need_trunc = FALSE;
     5         kx   switch (flags & GDBM_OPENMASK)
     5         kx     {
     5         kx       case GDBM_READER:
     5         kx 	dbf->desc = open (dbf->name, O_RDONLY|fbits, 0);
     5         kx 	break;
     5         kx 
     5         kx       case GDBM_WRITER:
     5         kx 	dbf->desc = open (dbf->name, O_RDWR|fbits, 0);
     5         kx 	break;
     5         kx 
     5         kx       case GDBM_NEWDB:
     5         kx 	dbf->desc = open (dbf->name, O_RDWR|O_CREAT|fbits, mode);
     5         kx 	need_trunc = TRUE;
     5         kx 	break;
     5         kx 
     5         kx       default:
     5         kx 	dbf->desc = open (dbf->name, O_RDWR|O_CREAT|fbits, mode);
     5         kx 	break;
     5         kx 
     5         kx     }
     5         kx   if (dbf->desc < 0)
     5         kx     {
     5         kx       SAVE_ERRNO (free (dbf->name);
     5         kx                   free (dbf));
     5         kx       gdbm_errno = GDBM_FILE_OPEN_ERROR;
     5         kx       return NULL;
     5         kx     }
     5         kx 
     5         kx   /* Get the status of the file. */
     5         kx   if (fstat (dbf->desc, &file_stat))
     5         kx     {
     5         kx       SAVE_ERRNO (close (dbf->desc);
     5         kx 		  free (dbf->name);
     5         kx 		  free (dbf));
     5         kx       gdbm_errno = GDBM_FILE_STAT_ERROR;
     5         kx       return NULL;
     5         kx     }
     5         kx   
     5         kx   /* Zero-length file can't be a reader... */
     5         kx   if (((flags & GDBM_OPENMASK) == GDBM_READER) && (file_stat.st_size == 0))
     5         kx     {
     5         kx       close (dbf->desc);
     5         kx       free (dbf->name);
     5         kx       free (dbf);
     5         kx       gdbm_errno = GDBM_EMPTY_DATABASE;
     5         kx       return NULL;
     5         kx     }
     5         kx 
     5         kx   /* Record the kind of user. */
     5         kx   dbf->read_write = (flags & GDBM_OPENMASK);
     5         kx 
     5         kx   /* Lock the file in the appropriate way. */
     5         kx   if (dbf->file_locking)
     5         kx     {
     5         kx       if (_gdbm_lock_file (dbf) == -1)
     5         kx 	{
     5         kx 	  close (dbf->desc);
     5         kx 	  free (dbf->name);
     5         kx 	  free (dbf);
     5         kx 	  if ((flags & GDBM_OPENMASK) == GDBM_READER)
     5         kx 	    gdbm_errno = GDBM_CANT_BE_READER;
     5         kx 	  else
     5         kx 	    gdbm_errno = GDBM_CANT_BE_WRITER;
     5         kx 	  return NULL;
     5         kx 	}
     5         kx     }
     5         kx 
     5         kx   /* If we do have a write lock and it was a GDBM_NEWDB, it is 
     5         kx      now time to truncate the file. */
     5         kx   if (need_trunc && file_stat.st_size != 0)
     5         kx     {
     5         kx       TRUNCATE (dbf);
     5         kx       fstat (dbf->desc, &file_stat);
     5         kx     }
     5         kx 
     5         kx   /* Decide if this is a new file or an old file. */
     5         kx   if (file_stat.st_size == 0)
     5         kx     {
     5         kx 
     5         kx       /* This is a new file.  Create an empty database.  */
     5         kx 
     5         kx       /* Start with the blocksize. */
     5         kx       if (block_size < 512)
     5         kx 	file_block_size = STATBLKSIZE;
     5         kx       else
     5         kx 	file_block_size = block_size;
     5         kx 
     5         kx       /* Get space for the file header. It will be written to disk, so
     5         kx          make sure there's no garbage in it. */
     5         kx       dbf->header = (gdbm_file_header *) calloc (1, file_block_size);
     5         kx       if (dbf->header == NULL)
     5         kx 	{
     5         kx 	  gdbm_close (dbf);
     5         kx 	  gdbm_errno = GDBM_MALLOC_ERROR;
     5         kx 	  return NULL;
     5         kx 	}
     5         kx 
     5         kx       /* Set the magic number and the block_size. */
     5         kx       dbf->header->header_magic = GDBM_MAGIC;
     5         kx       dbf->header->block_size = file_block_size;
     5         kx      
     5         kx       /* Create the initial hash table directory.  */
     5         kx       dbf->header->dir_size = 8 * sizeof (off_t);
     5         kx       dbf->header->dir_bits = 3;
     5         kx       while (dbf->header->dir_size < dbf->header->block_size)
     5         kx 	{
     5         kx 	  dbf->header->dir_size <<= 1;
     5         kx 	  dbf->header->dir_bits += 1;
     5         kx 	}
     5         kx 
     5         kx       /* Check for correct block_size. */
     5         kx       if (dbf->header->dir_size != dbf->header->block_size)
     5         kx 	{
     5         kx 	  gdbm_close (dbf);
     5         kx 	  gdbm_errno = GDBM_BLOCK_SIZE_ERROR;
     5         kx 	  return NULL;
     5         kx 	}
     5         kx 
     5         kx       /* Allocate the space for the directory. */
     5         kx       dbf->dir = (off_t *) malloc (dbf->header->dir_size);
     5         kx       if (dbf->dir == NULL)
     5         kx 	{
     5         kx 	  gdbm_close (dbf);
     5         kx 	  gdbm_errno = GDBM_MALLOC_ERROR;
     5         kx 	  return NULL;
     5         kx 	}
     5         kx       dbf->header->dir = dbf->header->block_size;
     5         kx 
     5         kx       /* Create the first and only hash bucket. */
     5         kx       dbf->header->bucket_elems =
     5         kx 	(dbf->header->block_size - sizeof (hash_bucket))
     5         kx 	/ sizeof (bucket_element) + 1;
     5         kx       dbf->header->bucket_size  = dbf->header->block_size;
     5         kx       dbf->bucket = (hash_bucket *) calloc (1, dbf->header->bucket_size);
     5         kx       if (dbf->bucket == NULL)
     5         kx 	{
     5         kx 	  gdbm_close (dbf);
     5         kx 	  gdbm_errno = GDBM_MALLOC_ERROR;
     5         kx 	  return NULL;
     5         kx 	}
     5         kx       _gdbm_new_bucket (dbf, dbf->bucket, 0);
     5         kx       dbf->bucket->av_count = 1;
     5         kx       dbf->bucket->bucket_avail[0].av_adr = 3*dbf->header->block_size;
     5         kx       dbf->bucket->bucket_avail[0].av_size = dbf->header->block_size;
     5         kx 
     5         kx       /* Set table entries to point to hash buckets. */
     5         kx       for (index = 0; index < GDBM_DIR_COUNT (dbf); index++)
     5         kx 	dbf->dir[index] = 2*dbf->header->block_size;
     5         kx 
     5         kx       /* Initialize the active avail block. */
     5         kx       dbf->header->avail.size
     5         kx 	= ( (dbf->header->block_size - sizeof (gdbm_file_header))
     5         kx 	 / sizeof (avail_elem)) + 1;
     5         kx       dbf->header->avail.count = 0;
     5         kx       dbf->header->avail.next_block = 0;
     5         kx       dbf->header->next_block  = 4*dbf->header->block_size;
     5         kx 
     5         kx       /* Write initial configuration to the file. */
     5         kx       /* Block 0 is the file header and active avail block. */
     5         kx       rc = _gdbm_full_write (dbf, dbf->header, dbf->header->block_size);
     5         kx       if (rc)
     5         kx 	{
     5         kx 	  SAVE_ERRNO (gdbm_close (dbf));
     5         kx 	  gdbm_errno = rc;
     5         kx 	  return NULL;
     5         kx 	}
     5         kx 
     5         kx       /* Block 1 is the initial bucket directory. */
     5         kx       rc = _gdbm_full_write (dbf, dbf->dir, dbf->header->dir_size);
     5         kx       if (rc)
     5         kx 	{
     5         kx 	  SAVE_ERRNO (gdbm_close (dbf));
     5         kx 	  gdbm_errno = rc;
     5         kx 	  return NULL;
     5         kx 	}
     5         kx 
     5         kx       /* Block 2 is the only bucket. */
     5         kx       rc = _gdbm_full_write (dbf, dbf->bucket, dbf->header->bucket_size);
     5         kx       if (rc)
     5         kx 	{
     5         kx 	  SAVE_ERRNO (gdbm_close (dbf));
     5         kx 	  gdbm_errno = rc;
     5         kx 	  return NULL;
     5         kx 	}
     5         kx 
     5         kx       /* Wait for initial configuration to be written to disk. */
     5         kx       __fsync (dbf);
     5         kx 
     5         kx       free (dbf->bucket);
     5         kx     }
     5         kx   else
     5         kx     {
     5         kx       /* This is an old database.  Read in the information from the file
     5         kx 	 header and initialize the hash directory. */
     5         kx 
     5         kx       gdbm_file_header partial_header;  /* For the first part of it. */
     5         kx 
     5         kx       /* Read the partial file header. */
     5         kx       rc = _gdbm_full_read (dbf, &partial_header, sizeof (gdbm_file_header));
     5         kx       if (rc)
     5         kx 	{
     5         kx 	  SAVE_ERRNO (gdbm_close (dbf));
     5         kx 	  gdbm_errno = rc;
     5         kx 	  return NULL;
     5         kx 	}
     5         kx 
     5         kx       /* Is the magic number good? */
     5         kx       if (partial_header.header_magic != GDBM_MAGIC
     5         kx 	  && partial_header.header_magic != GDBM_OMAGIC)
     5         kx 	{
     5         kx 	  gdbm_close (dbf);
     5         kx 	  switch (partial_header.header_magic)
     5         kx 	    {
     5         kx 	      case GDBM_OMAGIC_SWAP:
     5         kx 	      case GDBM_MAGIC32_SWAP:
     5         kx 	      case GDBM_MAGIC64_SWAP:
     5         kx 		gdbm_errno = GDBM_BYTE_SWAPPED;
     5         kx 		break;
     5         kx 	      case GDBM_MAGIC32:
     5         kx 	      case GDBM_MAGIC64:
     5         kx 		gdbm_errno = GDBM_BAD_FILE_OFFSET;
     5         kx 		break;
     5         kx 	      default:
     5         kx 		gdbm_errno = GDBM_BAD_MAGIC_NUMBER;
     5         kx 	    }
     5         kx 	  return NULL;
     5         kx 	}
     5         kx 
     5         kx       /* It is a good database, read the entire header. */
     5         kx       dbf->header = (gdbm_file_header *) malloc (partial_header.block_size);
     5         kx       if (dbf->header == NULL)
     5         kx 	{
     5         kx 	  gdbm_close (dbf);
     5         kx 	  gdbm_errno = GDBM_MALLOC_ERROR;
     5         kx 	  return NULL;
     5         kx 	}
     5         kx       memcpy (dbf->header, &partial_header, sizeof (gdbm_file_header));
     5         kx       rc = _gdbm_full_read (dbf, &dbf->header->avail.av_table[1],
     5         kx 			    dbf->header->block_size-sizeof (gdbm_file_header));
     5         kx       if (rc)
     5         kx 	{
     5         kx 	  SAVE_ERRNO (gdbm_close (dbf));
     5         kx 	  gdbm_errno = rc;
     5         kx 	  return NULL;
     5         kx 	}
     5         kx 	
     5         kx       /* Allocate space for the hash table directory.  */
     5         kx       dbf->dir = (off_t *) malloc (dbf->header->dir_size);
     5         kx       if (dbf->dir == NULL)
     5         kx 	{
     5         kx 	  gdbm_close (dbf);
     5         kx 	  gdbm_errno = GDBM_MALLOC_ERROR;
     5         kx 	  return NULL;
     5         kx 	}
     5         kx 
     5         kx       /* Read the hash table directory. */
     5         kx       file_pos = __lseek (dbf, dbf->header->dir, SEEK_SET);
     5         kx       if (file_pos != dbf->header->dir)
     5         kx 	{
     5         kx 	  SAVE_ERRNO (gdbm_close (dbf));
     5         kx 	  gdbm_errno = GDBM_FILE_SEEK_ERROR;
     5         kx 	  return NULL;
     5         kx 	}
     5         kx 
     5         kx       rc = _gdbm_full_read (dbf, dbf->dir, dbf->header->dir_size);
     5         kx       if (rc)
     5         kx 	{
     5         kx 	  SAVE_ERRNO (gdbm_close (dbf));
     5         kx 	  gdbm_errno = rc;
     5         kx 	  return NULL;
     5         kx 	}
     5         kx 
     5         kx     }
     5         kx 
     5         kx #if HAVE_MMAP
     5         kx   if (!(flags & GDBM_NOMMAP))
     5         kx     {
     5         kx       if (_gdbm_mapped_init (dbf) == 0)
     5         kx 	dbf->memory_mapping = TRUE;
     5         kx       else
     5         kx 	{
     5         kx 	  /* gdbm_errno should already be set. */
     5         kx 	  close (dbf->desc);
     5         kx 	  free (dbf->name);
     5         kx 	  free (dbf);
     5         kx 	  return NULL;
     5         kx 	}
     5         kx     }
     5         kx #endif
     5         kx 
     5         kx   /* Finish initializing dbf. */
     5         kx   dbf->last_read = -1;
     5         kx   dbf->bucket = NULL;
     5         kx   dbf->bucket_dir = 0;
     5         kx   dbf->cache_entry = NULL;
     5         kx   dbf->header_changed = FALSE;
     5         kx   dbf->directory_changed = FALSE;
     5         kx   dbf->bucket_changed = FALSE;
     5         kx   dbf->second_changed = FALSE;
     5         kx   
     5         kx   /* Everything is fine, return the pointer to the file
     5         kx      information structure.  */
     5         kx   return dbf;
     5         kx 
     5         kx }
     5         kx 
     5         kx /* Initialize the bucket cache. */
     5         kx int
     5         kx _gdbm_init_cache(GDBM_FILE dbf, size_t size)
     5         kx {
     5         kx   int index;
     5         kx 
     5         kx   if (dbf->bucket_cache == NULL)
     5         kx     {
     5         kx       dbf->bucket_cache = (cache_elem *) malloc(sizeof(cache_elem) * size);
     5         kx       if(dbf->bucket_cache == NULL)
     5         kx         {
     5         kx           gdbm_errno = GDBM_MALLOC_ERROR;
     5         kx           return -1;
     5         kx         }
     5         kx       dbf->cache_size = size;
     5         kx 
     5         kx       for(index = 0; index < size; index++)
     5         kx         {
     5         kx           (dbf->bucket_cache[index]).ca_bucket
     5         kx             = (hash_bucket *) calloc (1, dbf->header->bucket_size);
     5         kx           if ((dbf->bucket_cache[index]).ca_bucket == NULL)
     5         kx 	    {
     5         kx               gdbm_errno = GDBM_MALLOC_ERROR;
     5         kx 	      return -1;
     5         kx             }
     5         kx           (dbf->bucket_cache[index]).ca_adr = 0;
     5         kx           (dbf->bucket_cache[index]).ca_changed = FALSE;
     5         kx           (dbf->bucket_cache[index]).ca_data.hash_val = -1;
     5         kx           (dbf->bucket_cache[index]).ca_data.elem_loc = -1;
     5         kx           (dbf->bucket_cache[index]).ca_data.dptr = NULL;
     5         kx         }
     5         kx       dbf->bucket = dbf->bucket_cache[0].ca_bucket;
     5         kx       dbf->cache_entry = &dbf->bucket_cache[0];
     5         kx     }
     5         kx   return 0;
     5         kx }