"Fossies" - the Fresh Open Source Software Archive

Member "coda-6.9.5/lib-src/rwcdb/rwcdb_file.c" (26 Jun 2007, 4110 Bytes) of package /linux/misc/old/coda-6.9.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "rwcdb_file.c" see the Fossies "Dox" file reference documentation.

    1 /* BLURB lgpl
    2                Coda File System
    3                   Release 6
    4 
    5       Copyright (c) 2003 Carnegie Mellon University
    6           Additional copyrights listed below
    7 
    8 This  code  is  distributed "AS IS" without warranty of any kind under
    9 the  terms of the  GNU  Library General Public Licence  Version 2,  as
   10 shown in the file LICENSE. The technical and financial contributors to
   11 Coda are listed in the file CREDITS.
   12 
   13             Additional copyrights
   14 */
   15 
   16 #ifdef HAVE_CONFIG_H
   17 #include <config.h>
   18 #endif
   19 
   20 #include <sys/types.h>
   21 #include <sys/stat.h>
   22 #include <fcntl.h>
   23 #define __USE_UNIX98 /* to get pread */
   24 #include <unistd.h>
   25 #include <stdio.h>
   26 #include <string.h>
   27 #include <stdlib.h>
   28 
   29 #include "rwcdb_pack.h"
   30 #include "rwcdb.h"
   31 
   32 /*=====================================================================*/
   33 /* scratch buffer */
   34 
   35 int grow_cache(struct db_file *f, u_int32_t len)
   36 {
   37     f->cache_pos = f->len;
   38     if (f->cache_len >= len)
   39     return 0;
   40 
   41     if (f->cache) free(f->cache);
   42     f->cache = (char *)malloc(len);
   43     if (!f->cache) {
   44     f->cache = NULL;
   45     return -1;
   46     }
   47     f->cache_len = len;
   48     return 0;
   49 }
   50 
   51 int cached(struct db_file *f, u_int32_t len, u_int32_t pos)
   52 {
   53     return (pos >= f->cache_pos && pos + len <= f->cache_pos + f->cache_len);
   54 }
   55 
   56 /*=====================================================================*/
   57 /* fileio */
   58 
   59 int db_file_seek(struct db_file *f, const u_int32_t pos)
   60 {
   61     if (lseek(f->fd, pos, SEEK_SET) != pos) return -1;
   62     f->pos = pos;
   63     return 0;
   64 }
   65 
   66 int db_file_mread(struct db_file *f, void **data, const u_int32_t len,
   67           const u_int32_t pos)
   68 {
   69     ssize_t n;
   70 
   71     if (pos + len > f->len)
   72     return -1;
   73 
   74     if (!cached(f, len, pos)) {
   75     if (grow_cache(f, len))
   76         return -1;
   77 
   78 #ifdef HAVE_PREAD
   79     n = pread(f->fd, f->cache, len, pos);
   80 #else
   81     if (pos != f->pos && lseek(f->fd, pos, SEEK_SET) != pos)
   82         return -1;
   83 
   84     n = read(f->fd, f->cache, len);
   85 #endif
   86     if (n >= 0)
   87         f->pos = pos + n;
   88     if (n != len) return -1;
   89 
   90     f->cache_pos = pos;
   91     f->cache_len = len;
   92     }
   93 
   94     *data = (char *)f->cache + (pos - f->cache_pos);
   95     return 0;
   96 }
   97 
   98 #define PAGESIZE (4 * 1024)
   99 
  100 int db_file_write(struct db_file *f, void *data, u_int32_t len)
  101 {
  102     ssize_t n;
  103     u_int32_t blob;
  104 
  105     if (!len) return 0;
  106 
  107     if (grow_cache(f, PAGESIZE))
  108     return -1;
  109 
  110     /* first fill the rest of the page */
  111     blob = len < (PAGESIZE - f->pending) ? len : PAGESIZE - f->pending;
  112     memcpy((char *)f->cache + f->pending, data, blob);
  113     f->pending += blob;
  114     data = (char *)data + blob;
  115     len -= blob;
  116     f->pos += blob;
  117 
  118     /* flush full pages */
  119     if (f->pending == PAGESIZE) {
  120     n = write(f->fd, f->cache, PAGESIZE);
  121     if (n == -1) return -1;
  122     f->pending = 0;
  123     }
  124 
  125     /* flush rest of the data, when it is a lot */
  126     blob = len & ~(PAGESIZE - 1);
  127     if (blob) {
  128     n = write(f->fd, data, blob);
  129     if (n == -1) return -1;
  130     data = (char *)data + blob;
  131     len -= blob;
  132     f->pos += blob;
  133     }
  134 
  135     /* start filling the next page with the leftovers */
  136     if (len) {
  137     memcpy(f->cache, data, len);
  138     f->pending += len;
  139     f->pos += len;
  140     }
  141 
  142     if (f->pos > f->len)
  143     f->len = f->pos;
  144 
  145     return 0;
  146 }
  147 
  148 int db_file_flush(struct db_file *f)
  149 {
  150     ssize_t n;
  151     if (f->pending) {
  152     n = write(f->fd, f->cache, f->pending);
  153     if (n == -1) return -1;
  154     f->pending = 0;
  155     }
  156     return 0;
  157 }
  158 
  159 int readints(struct db_file *f, u_int32_t *a, u_int32_t *b, u_int32_t pos)
  160 {
  161     void *buf;
  162 
  163     if (db_file_mread(f, &buf, 8, pos))
  164     return -1;
  165 
  166     unpackints(buf, a, b);
  167     return 0;
  168 }
  169 
  170 int db_file_open(struct db_file *f, const char *name, const int mode)
  171 {
  172     struct stat sb;
  173     u_int32_t dummy;
  174 
  175     f->pos = 0;
  176     f->eod = 2048;
  177     f->cache = NULL;
  178     f->cache_len = f->pending = 0;
  179 
  180     f->fd = open(name, mode, 0600);
  181     if (f->fd == -1) return -1;
  182 
  183     if (fstat(f->fd, &sb)) {
  184     close(f->fd);
  185     return -1;
  186     }
  187     f->ino = sb.st_ino;
  188     f->len = f->cache_pos = sb.st_size;
  189 
  190     if (f->len)
  191     (void)readints(f, &f->eod, &dummy, 0);
  192 
  193     return 0;
  194 }
  195 
  196 void db_file_close(struct db_file *f)
  197 {
  198     if (f->cache) {
  199     free(f->cache);
  200     f->cache_len = 0;
  201     }
  202 
  203     if (f->fd != -1) {
  204     close(f->fd);
  205     f->fd = -1;
  206     }
  207 }
  208