Logo Search packages:      
Sourcecode: dcc version File versions  Download package

read_rcd.c

/* Distributed Checksum Clearinghouse
 *
 * Copyright (c) 2005 by Rhyolite Software
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE
 * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 *
 * Rhyolite Software DCC 1.2.74-1.13 $Revision$
 */

#include "srvr_defs.h"

static int read_rcd_fd = -1;
static u_char read_rcd_buf[64*1024];
static off_t read_rcd_base;
static u_int read_rcd_buflen;



int
read_db(DCC_EMSG emsg, void *buf, u_int buf_len,
      int fd, off_t pos, const char *file_nm)
{
      int i;

      if (-1 == lseek(fd, pos, SEEK_SET)) {
            dcc_pemsg(EX_IOERR, emsg, "lseek(%s, 0): %s",
                    DCC_NM2PATH(file_nm), ERROR_STR());
            return -1;
      }

      i = read(fd, buf, buf_len);
      if (i >= 0)
            return i;

      if (i < 0)
            dcc_pemsg(EX_IOERR, emsg, "read(%s): %s",
                    DCC_NM2PATH(file_nm), ERROR_STR());
      return -1;
}



u_char
read_magic(DCC_EMSG emsg, DB_MAGIC *magicp,
         int fd, const char *file_nm)
{
      return (sizeof(*magicp) == read_db(emsg, magicp, sizeof(*magicp),
                                fd, 0, file_nm));
}



/* invalidate the read_rcd() read-ahead cache */
void
read_rcd_invalidate(void)
{
      read_rcd_fd = -1;
}



static int
read_rcd_sub(DCC_EMSG emsg, void *buf, u_int buflen,
           int fd, off_t pos, const char *file_nm)
{
      int i;

      if (fd == read_rcd_fd
          && pos >= read_rcd_base
          && pos+buflen <= read_rcd_base+read_rcd_buflen) {
            memcpy(buf, &read_rcd_buf[pos-read_rcd_base], buflen);
            return buflen;
      }


      i = read_db(emsg, read_rcd_buf, sizeof(read_rcd_buf),
                read_rcd_fd = fd,
                read_rcd_base = pos, file_nm);
      if (i <= 0) {
            read_rcd_fd = -1;
            return i;
      }
      read_rcd_buflen = i;
      if (buflen > read_rcd_buflen)
            buflen = read_rcd_buflen;
      memcpy(buf, &read_rcd_buf[pos-read_rcd_base], buflen);
      return buflen;
}



int                           /* -1=error 0=eof >0=record length */
read_rcd(DCC_EMSG emsg, DB_RCD *rcd,
       int fd, off_t pos, const char *file_nm)
{
      int i, hdr_len, rcd_len, num_cks;

      /* read a record, starting with its beginning */
      hdr_len = sizeof(*rcd)-sizeof(rcd->cks);
      i = read_rcd_sub(emsg, rcd, hdr_len,
                   fd, pos, file_nm);
      if (hdr_len != i) {
            if (i == 0)
                  return 0;
            if (i > 0) {
                  dcc_pemsg(EX_DATAERR, emsg,
                          "header of record at "OFF_HPAT" of %s"
                          " truncated by %d bytes",
                          lseek(fd, 0, SEEK_CUR) - i,
                          DCC_NM2PATH(file_nm), hdr_len-i);
            }
            return -1;
      }

      num_cks = DB_NUM_CKS(rcd);
      if (num_cks > DIM(rcd->cks)) {
            dcc_pemsg(EX_DATAERR, emsg,
                    "bogus checksum count %#x s at "OFF_HPAT" of %s",
                    rcd->fgs_num_cks, lseek(fd, 0, SEEK_CUR),
                    DCC_NM2PATH(file_nm));
            return -1;
      }
      rcd_len = num_cks * sizeof(rcd->cks[0]);
      if (rcd_len != 0) {
            i = read_rcd_sub(emsg, rcd->cks, rcd_len,
                         fd, pos+hdr_len, file_nm);
            if (i != rcd_len) {
                  if (i < 0)
                        return -1;
                  if (!i)
                        dcc_pemsg(EX_DATAERR, emsg,
                                "record at "OFF_HPAT" of %s"
                                " truncated after header",
                                lseek(fd, 0, SEEK_CUR),
                                DCC_NM2PATH(file_nm));
                  else
                        dcc_pemsg(EX_DATAERR, emsg,
                                "record at "OFF_HPAT" of %s"
                                " truncated by %d bytes",
                                lseek(fd, 0, SEEK_CUR),
                                DCC_NM2PATH(file_nm), rcd_len-i);
                  return 0;
            }
      }

      return hdr_len+rcd_len;
}

Generated by  Doxygen 1.6.0   Back to index