Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

SSL record.c

  Sprache: C
 

/*++
/* NAME
/* record 3
/* SUMMARY
/* simple typed record I/O
/* SYNOPSIS
/* #include <record.h>
/*
/* int rec_get(stream, buf, maxsize)
/* VSTREAM *stream;
/* VSTRING *buf;
/* ssize_t maxsize;
/*
/* int rec_get_raw(stream, buf, maxsize, flags)
/* VSTREAM *stream;
/* VSTRING *buf;
/* ssize_t maxsize;
/* int flags;
/*
/* int rec_put(stream, type, data, len)
/* VSTREAM *stream;
/* int type;
/* const char *data;
/* ssize_t len;
/* AUXILIARY FUNCTIONS
/* int rec_put_type(stream, type, offset)
/* VSTREAM *stream;
/* int type;
/* long offset;
/*
/* int rec_fprintf(stream, type, format, ...)
/* VSTREAM *stream;
/* int type;
/* const char *format;
/*
/* int rec_fputs(stream, type, str)
/* VSTREAM *stream;
/* int type;
/* const char *str;
/*
/* int REC_PUT_BUF(stream, type, buf)
/* VSTREAM *stream;
/* int type;
/* VSTRING *buf;
/*
/* int rec_vfprintf(stream, type, format, ap)
/* VSTREAM *stream;
/* int type;
/* const char *format;
/* va_list ap;
/*
/* int rec_goto(stream, where)
/* VSTREAM *stream;
/* const char *where;
/*
/* int rec_pad(stream, type, len)
/* VSTREAM *stream;
/* int type;
/* ssize_t len;
/*
/* REC_SPACE_NEED(buflen, reclen)
/* ssize_t buflen;
/* ssize_t reclen;
/*
/* REC_GET_HIDDEN_TYPE(type)
/* int type;
/* DESCRIPTION
/* This module reads and writes typed variable-length records.
/* Each record contains a 1-byte type code (0..255), a length
/* (1 or more bytes) and as much data as the length specifies.
/*
/* rec_get_raw() retrieves a record from the named record stream
/* and returns the record type. The \fImaxsize\fR argument is
/* zero, or specifies a maximal acceptable record length.
/* The result is REC_TYPE_EOF when the end of the file was reached,
/* and REC_TYPE_ERROR in case of a bad record. The result buffer is
/* null-terminated for convenience. Records may contain embedded
/* null characters. The \fIflags\fR argument specifies zero or
/* more of the following:
/* .IP REC_FLAG_FOLLOW_PTR
/* Follow PTR records, instead of exposing them to the application.
/* .IP REC_FLAG_SKIP_DTXT
/* Skip "deleted text" records, instead of exposing them to
/* the application.
/* .IP REC_FLAG_SEEK_END
/* Seek to the end-of-file upon reading a REC_TYPE_END record.
/* .PP
/* Specify REC_FLAG_NONE to request no special processing,
/* and REC_FLAG_DEFAULT for normal use.
/*
/* rec_get() is a wrapper around rec_get_raw() that always
/* enables the REC_FLAG_FOLLOW_PTR, REC_FLAG_SKIP_DTXT
/* and REC_FLAG_SEEK_END features.
/*
/* REC_GET_HIDDEN_TYPE() is an unsafe macro that returns
/* non-zero when the specified record type is "not exposed"
/* by rec_get().
/*
/* rec_put() stores the specified record and returns the record
/* type, or REC_TYPE_ERROR in case of problems.
/*
/* rec_put_type() updates the type field of the record at the
/* specified file offset.  The result is the new record type,
/* or REC_TYPE_ERROR in case of trouble.
/*
/* rec_fprintf() and rec_vfprintf() format their arguments and
/* write the result to the named stream. The result is the same
/* as with rec_put().
/*
/* rec_fputs() writes a record with as contents a copy of the
/* specified string. The result is the same as with rec_put().
/*
/* REC_PUT_BUF() is a wrapper for rec_put() that makes it
/* easier to handle VSTRING buffers. It is an unsafe macro
/* that evaluates some arguments more than once.
/*
/* rec_goto() takes the argument of a pointer record and moves
/* the file pointer to the specified location. A zero position
/* means do nothing. The result is REC_TYPE_ERROR in case of
/* failure.
/*
/* rec_pad() writes a record that occupies the larger of (the
/* specified amount) or (an implementation-defined minimum).
/*
/* REC_SPACE_NEED(buflen, reclen) converts the specified buffer
/* length into a record length. This macro modifies its second
/* argument.
/* DIAGNOSTICS
/* Panics: interface violations. Fatal errors: insufficient memory.
/* Warnings: corrupted file.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/


/* System library. */

#include <sys_defs.h>
#include <stdlib.h>   /* 44BSD stdarg.h uses abort() */
#include <stdarg.h>
#include <unistd.h>
#include <string.h>

#ifndef NBBY
#define NBBY 8    /* XXX should be in sys_defs.h */
#endif

/* Utility library. */

#include <msg.h>
#include <mymalloc.h>
#include <vstream.h>
#include <vstring.h>
#include <stringops.h>

/* Global library. */

#include <off_cvt.h>
#include <rec_type.h>
#include <record.h>

/* rec_put_type - update record type field */

int     rec_put_type(VSTREAM *stream, int type, off_t offset)
{
    if (type < 0 || type > 255)
 msg_panic("rec_put_type: bad record type %d", type);

    if (msg_verbose > 2)
 msg_info("rec_put_type: %d at %ld", type, (long) offset);

    if (vstream_fseek(stream, offset, SEEK_SET) < 0
 || VSTREAM_PUTC(type, stream) != type) {
 msg_warn("%s: seek or write error", VSTREAM_PATH(stream));
 return (REC_TYPE_ERROR);
    } else {
 return (type);
    }
}

/* rec_put - store typed record */

int     rec_put(VSTREAM *stream, int type, const char *data, ssize_t len)
{
    ssize_t len_rest;
    int     len_byte;

    if (type < 0 || type > 255)
 msg_panic("rec_put: bad record type %d", type);

    if (msg_verbose > 2)
 msg_info("rec_put: type %c len %ld data %.10s",
   type, (long) len, data);

    /*
     * Write the record type, one byte.
     */

    if (VSTREAM_PUTC(type, stream) == VSTREAM_EOF)
 return (REC_TYPE_ERROR);

    /*
     * Write the record data length in 7-bit portions, using the 8th bit to
     * indicate that there is more. Use as many length bytes as needed.
     */

    len_rest = len;
    do {
 len_byte = len_rest & 0177;
 if (len_rest >>= 7U)
     len_byte |= 0200;
 if (VSTREAM_PUTC(len_byte, stream) == VSTREAM_EOF) {
     return (REC_TYPE_ERROR);
 }
    } while (len_rest != 0);

    /*
     * Write the record data portion. Use as many length bytes as needed.
     */

    if (len && vstream_fwrite(stream, data, len) != len)
 return (REC_TYPE_ERROR);
    return (type);
}

/* rec_get_raw - retrieve typed record */

int     rec_get_raw(VSTREAM *stream, VSTRING *buf, ssize_t maxsize, int flags)
{
    const char *myname = "rec_get";
    int     type;
    ssize_t len;
    int     len_byte;
    unsigned shift;

    /*
     * Sanity check.
     */

    if (maxsize < 0)
 msg_panic("%s: bad record size limit: %ld", myname, (long) maxsize);

    for (;;) {

 /*
  * Extract the record type.
 */

 if ((type = VSTREAM_GETC(stream)) == VSTREAM_EOF)
     return (REC_TYPE_EOF);

 /*
  * Find out the record data length. Return an error result when the
  * record data length is malformed or when it exceeds the acceptable
  * limit.
 */

 for (len = 0, shift = 0/* void */ ; shift += 7) {
     if (shift >= (int) (NBBY * sizeof(int))) {
  msg_warn("%s: too many length bits, record type %d",
    VSTREAM_PATH(stream), type);
  return (REC_TYPE_ERROR);
     }
     if ((len_byte = VSTREAM_GETC(stream)) == VSTREAM_EOF) {
  msg_warn("%s: unexpected EOF reading length, record type %d",
    VSTREAM_PATH(stream), type);
  return (REC_TYPE_ERROR);
     }
     len |= (len_byte & 0177) << shift;
     if ((len_byte & 0200) == 0)
  break;
 }
 if (len < 0 || (maxsize > 0 && len > maxsize)) {
     msg_warn("%s: illegal length %ld, record type %d",
       VSTREAM_PATH(stream), (long) len, type);
     while (len-- > 0 && VSTREAM_GETC(stream) != VSTREAM_EOF)
   /* void */ ;
     return (REC_TYPE_ERROR);
 }

 /*
  * Reserve buffer space for the result, and read the record data into
  * the buffer.
 */

 if (vstream_fread_buf(stream, buf, len) != len) {
     msg_warn("%s: unexpected EOF in data, record type %d length %ld",
       VSTREAM_PATH(stream), type, (long) len);
     return (REC_TYPE_ERROR);
 }
 VSTRING_TERMINATE(buf);
 if (msg_verbose > 2)
     msg_info("%s: type %c len %ld data %.10s", myname,
       type, (long) len, vstring_str(buf));

 /*
  * Transparency options.
 */

 if (flags == 0)
     break;
 if (type == REC_TYPE_PTR && (flags & REC_FLAG_FOLLOW_PTR) != 0
     && (type = rec_goto(stream, vstring_str(buf))) != REC_TYPE_ERROR)
     continue;
 if (type == REC_TYPE_DTXT && (flags & REC_FLAG_SKIP_DTXT) != 0)
     continue;
 if (type == REC_TYPE_END && (flags & REC_FLAG_SEEK_END) != 0
     && vstream_fseek(stream, (off_t) 0, SEEK_END) < 0) {
     msg_warn("%s: seek error after reading END record: %m",
       VSTREAM_PATH(stream));
     return (REC_TYPE_ERROR);
 }
 break;
    }
    return (type);
}

/* rec_goto - follow PTR record */

int     rec_goto(VSTREAM *stream, const char *buf)
{
    off_t   offset;
    static char *saved_path;
    static off_t saved_offset;
    static int reverse_count;

    /*
     * Crude workaround for queue file loops. VSTREAMs currently have no
     * option to attach application-specific data, so we use global state and
     * simple logic to detect if an application switches streams. We trigger
     * on reverse jumps only. There's one reverse jump for every inserted
     * header, but only one reverse jump for all appended recipients. No-one
     * is likely to insert 10000 message headers, but someone might append
     * 10000 recipients.
     */

#define REVERSE_JUMP_LIMIT 10000

    if (saved_path == 0 || strcmp(saved_path, VSTREAM_PATH(stream)) != 0) {
 if (saved_path)
     myfree(saved_path);
 saved_path = mystrdup(VSTREAM_PATH(stream));
 reverse_count = 0;
 saved_offset = 0;
    }
    while (ISSPACE(*buf))
 buf++;
    if ((offset = off_cvt_string(buf)) < 0) {
 msg_warn("%s: malformed pointer record value: %s",
   VSTREAM_PATH(stream), buf);
 return (REC_TYPE_ERROR);
    } else if (offset == 0) {
 /* Dummy record. */
 return (0);
    } else if (offset <= saved_offset && ++reverse_count > REVERSE_JUMP_LIMIT) {
 msg_warn("%s: too many reverse jump records", VSTREAM_PATH(stream));
 return (REC_TYPE_ERROR);
    } else if (vstream_fseek(stream, offset, SEEK_SET) < 0) {
 msg_warn("%s: seek error after pointer record: %m",
   VSTREAM_PATH(stream));
 return (REC_TYPE_ERROR);
    } else {
 saved_offset = offset;
 return (0);
    }
}

/* rec_vfprintf - write formatted string to record */

int     rec_vfprintf(VSTREAM *stream, int type, const char *format, va_list ap)
{
    static VSTRING *vp;

    if (vp == 0)
 vp = vstring_alloc(100);

    /*
     * Writing a formatted string involves an extra copy, because we must
     * know the record length before we can write it.
     */

    vstring_vsprintf(vp, format, ap);
    return (REC_PUT_BUF(stream, type, vp));
}

/* rec_fprintf - write formatted string to record */

int     rec_fprintf(VSTREAM *stream, int type, const char *format,...)
{
    int     result;
    va_list ap;

    va_start(ap, format);
    result = rec_vfprintf(stream, type, format, ap);
    va_end(ap);
    return (result);
}

/* rec_fputs - write string to record */

int     rec_fputs(VSTREAM *stream, int type, const char *str)
{
    return (rec_put(stream, type, str, str ? strlen(str) : 0));
}

/* rec_pad - write padding record */

int     rec_pad(VSTREAM *stream, int type, ssize_t len)
{
    int     width = len - 2;  /* type + length */

    return (rec_fprintf(stream, type, "%*s",
   width < 1 ? 1 : width, "0"));
}

Messung V0.5 in Prozent
C=73 H=95 G=84

¤ Dauer der Verarbeitung: 0.24 Sekunden  (vorverarbeitet am  2026-08-09) ¤

*© Formatika GbR, Deutschland






Versionsinformation zu Columbo

Bemerkung:

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Anfrage:

Dauer der Verarbeitung:

Sekunden

sprechenden Kalenders






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=752002