LCOV - code coverage report
Current view: top level - util/archive - fd_ar.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 1 1 100.0 %
Date: 2024-11-13 11:58:15 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef HEADER_fd_src_archive_fd_ar_h
       2             : #define HEADER_fd_src_archive_fd_ar_h
       3             : 
       4             : /* AR(5) is a simple archive format combining multiple files into one.
       5             :    The file format is structurally similar to TAR.
       6             : 
       7             :    This package provides a simple streaming AR reader.
       8             : 
       9             :    ### File Format
      10             : 
      11             :    Reference: https://www.freebsd.org/cgi/man.cgi?query=ar&sektion=5
      12             : 
      13             :       +------------------------+
      14             :       | Archive Magic          | 8 bytes "<arch>!\n"
      15             :       +------------------------+
      16             :       | File Header 0          | 60 bytes
      17             :       +------------------------+
      18             :       | File Content           | variable length
      19             :       |                        |
      20             :       +------------------------+
      21             :       | File Header 1          | 60 bytes (aligned to 2 bytes)
      22             :       +------------------------+
      23             :       | File Content           | variable length
      24             :       |                        |
      25             :       ..........................
      26             : 
      27             :    ### Usage
      28             : 
      29             :    The `ar(1)` tool from GNU binutils can be used to create such archive files.
      30             : 
      31             :       ar rcDS <archive_file> <file> <file> <file...>
      32             : 
      33             :    Basic usage:
      34             : 
      35             :      ... at this point, stream should be pointed at the first byte
      36             :      ... of the ar file magic
      37             : 
      38             :      fd_ar_read_init( stream );
      39             :      for(;;) {
      40             :        fd_ar_meta_t meta[1];
      41             :        if( fd_ar_read_next( stream, meta ) ) break;
      42             : 
      43             :        ... at this point, stream is pointed at first byte of contents of
      44             :        ... the next unprocessed file in the ar and there are
      45             :        ... meta->filesz bytes ni this file
      46             :        ... process next file here, advancing the stream position exactly
      47             : 
      48             :        ... meta->filesz bytes before next iteration
      49             :      }
      50             : 
      51             :    More nuanced error handling and what not is possible.  See
      52             :    descriptions below. */
      53             : 
      54             : #include "../fd_util_base.h"
      55             : 
      56             : /* See note in fd_ar.c for details on use of long for these fields. */
      57             : 
      58        1140 : #define FD_AR_META_IDENT_SZ (17UL) /* 16 + 1 for '\0' termination */
      59             : 
      60             : struct fd_ar_meta {
      61             :   long mtime;
      62             :   long uid;
      63             :   long gid;
      64             :   long mode;
      65             :   long filesz;                       /* Guaranteed to be non-negative */
      66             :   char ident[ FD_AR_META_IDENT_SZ ]; /* Guaranteed '\0' terminated */
      67             : };
      68             : 
      69             : typedef struct fd_ar_meta fd_ar_meta_t;
      70             : 
      71             : FD_PROTOTYPES_BEGIN
      72             : 
      73             : /* fd_ar_read_init starts reading an ar archive in the given stream.  On
      74             :    entry, assumes stream is positioned on the first byte of the ar
      75             :    magic.  If FD_HAS_HOSTED, stream is FILE * pointer.  Otherwise stream
      76             :    should be the equivalent for that target.
      77             : 
      78             :    Returns 0 on success and non-zero strerror compatible error code on
      79             :    failure.  If successful, the stream will be positioned on the first
      80             :    byte immediately after the ar magic.  If not, the stream state is
      81             :    undefined.
      82             : 
      83             :    Error codes include:
      84             : 
      85             :    - EINVAL: NULL stream
      86             :    - ENOENT: failed due to EOF
      87             :    - EIO:    failed due to stream i/o failure
      88             :    - EPROTO: failed due to malformed ar file (bad magic) */
      89             : 
      90             : int
      91             : fd_ar_read_init( void * stream );
      92             : 
      93             : /* fd_ar_read_next starts reading the archive file in the given stream.
      94             :    On entry, assumes stream is positioned on the first byte immediately
      95             :    after the archive magic or the first byte immediately after the just
      96             :    processed archive file content.  If FD_HAS_HOSTED, stream should
      97             :    point to an open FILE handle.  Otherwise stream should be to the
      98             :    equivalent is provided for that target.
      99             : 
     100             :    Returns 0 on success and non-zero strerror compatible error code on
     101             :    failure.  If successful, the stream will be positioned on the first
     102             :    byte of the file content to process next and meta will be populated
     103             :    with details from the archive header.
     104             : 
     105             :    If opt_meta is non-NULL, on success, *opt_meta will be populated with
     106             :    archive file metadata on return.  Of note, the size of the file
     107             :    contents is opt_meta->filesz bytes (a non-negative number).
     108             :    Otherwise, *opt_meta will be untouched.
     109             : 
     110             :    Before fd_ar_read_next is called on the get the next file, it should
     111             :    position stream just after the last byte of the file contents.  E.g.
     112             :    to skip over file contents in a hosted environment, provide opt_meta
     113             :    and do:
     114             : 
     115             :      fseek( stream, opt_meta->filesz, SEEK_CUR )
     116             : 
     117             :    If the caller did not provide opt_meta to get the filesz, the caller
     118             :    should know via other means how to position the stream after the file
     119             :    contents.
     120             : 
     121             :    Error codes include:
     122             : 
     123             :    - EINVAL: NULL stream
     124             :    - ENOENT: failed due to EOF
     125             :    - EIO:    failed due to stream i/o failure
     126             :    - EPROTO: failed due to malformed ar file (bad magic) */
     127             : 
     128             : int
     129             : fd_ar_read_next( void *         stream,
     130             :                  fd_ar_meta_t * opt_meta );
     131             : 
     132             : /* FIXME: CONSIDER AN FD_AR_READ_FINI THAT WOULD MOVE THE STREAM POINTER
     133             :    TO THE END OF THE AR FILE? */
     134             : 
     135             : FD_PROTOTYPES_END
     136             : 
     137             : #endif /* HEADER_fd_src_archive_fd_ar_h */

Generated by: LCOV version 1.14