2 ** Declarations needed for handling CAF (Crunched Article Files)
3 ** Written by Richard Todd (rmtodd@mailhost.ecn.uoknor.edu) 3/24/96
8 ** Format of a crunched article file:
12 typedef struct _CAFHEADER {
13 char Magic[4]; /* Magic Number "CRMT" */
14 ARTNUM Low; /* lowest article in the file */
15 ARTNUM NumSlots; /* number of articles there are room for in the TOC */
16 ARTNUM High; /* last article actually present in the file */
17 size_t Free; /* amount of space currently unused (freed by cancels/expires) */
18 off_t StartDataBlock; /* offset of first article data block. */
19 unsigned int BlockSize; /* unit of allocation for CAF files. */
20 size_t FreeZoneTabSize; /* amount of space taken up by the free zone table. */
21 size_t FreeZoneIndexSize; /* size taken up by the "index" part of the free zone table. */
22 time_t LastCleaned; /* note time of last cleaning. */
26 #define CAF_MAGIC "CRMT"
27 #define CAF_MAGIC_LEN 4
28 #define CAF_DEFAULT_BLOCKSIZE 512
31 ** then the table of free blocks. The table is FreeZoneTabSize bytes
32 ** long. First comes a "first-level" or "index" bitmap, taking up the
33 ** space from the end of the CAFHEADER to the end of the first
34 ** block, i.e. FreeZoneIndexBytes. The rest of the table is a big bitmap
35 ** listing free blocks in the 'data' portion of the CAF file.
37 ** In the "index" bitmap: LSB of bitmap byte 0 is 1 if there are any 1s
38 ** (free blocks) listed in the first block of the big bitmap, and 0 if there
39 ** are no 1s in that block. The remaining bits of the index bitmap
40 ** correspond to the remaining blocks of the big bitmap accordingly.
41 ** The idea is that from the index bitmap one can tell which part of the
42 ** main bitmap is likely to have free blocks w/o having to read the entire
45 ** As for the main bitmap, each bit is 1 if the corresponding data
46 ** block (BlockSize bytes) is free. LSB of bitmap byte 0 corresponds
47 ** to the block @ offset StartDataBlock, and all the rest follow on
50 ** Note that the main part of the bitmap is *always* FreeZoneIndexByte*8
51 ** blocks long, no matter how big the CAF file is. The table of free blocks
52 ** is almost always sparse. Also note that blocks past EOF in the CAF file
53 ** are *not* considered free. If the CAF article write routines fail to
54 ** find free space in the fre block bitmaps, they will always attempt to
55 ** extend the CAF file instead.
58 #define CAF_DEFAULT_FZSIZE (512-sizeof(CAFHEADER))
61 ** (Note: the CAFBITMAP structure isn't what's actually stored on disk
62 ** in the free bitmap region, this is just a convenient structure to
63 ** keep the bitmap size and StartBlockOffset together with the bitmap
64 ** w/o having keep passing the original CAFHEADER to every routine
65 ** that wants it. The bitmap structure contains the first (index) bitmap,
66 ** as well as pointers to structures for each block of the main bitmap that
67 ** has been read into memory.
70 typedef struct _CAFBITMAP {
72 off_t MaxDataBlock; /* can only handle offsets < this with this bitmap. */
73 size_t FreeZoneTabSize;
74 size_t FreeZoneIndexSize;
75 size_t BytesPerBMB; /* size of chunk, in bytes, that any given BMBLK can map. */
76 unsigned int BlockSize;
77 unsigned int NumBMB; /* size of Blocks array. */
78 struct _CAFBMB **Blocks;
82 typedef struct _CAFBMB {
85 int Dirty; /* 1 if this BMB has had any bits changed. */
90 ** Next in the file are the TOC (Table of Contents) entries. Each TOC
91 ** entry describes an article.
94 typedef struct _CAFTOCENT {
101 ** and then after the NumSlots TOC Entries, the actual articles, one after
102 ** another, always starting at offsets == 0 mod BlockSize
106 ** Number of slots to put in TOC by default. Can be raised if we ever get
107 ** more than 256K articles in a newsgroup (frightening thought).
110 #define CAF_DEFAULT_TOC_SIZE (256 * 1024)
113 ** Default name for CAF file in the news spool dir for a given newsgroup.
115 #define CAF_NAME "CF"
117 extern int CAFOpenArtRead(const char *cfpath, ARTNUM art, size_t *len);
118 extern int CAFOpenArtWrite(char *cfpath, ARTNUM *art, int WaitLock, size_t size);
119 extern int CAFStartWriteFd(int fd, ARTNUM *art, size_t size);
120 extern int CAFFinishWriteFd(int fd);
121 extern int CAFFinishArtWrite(int fd);
122 extern int CAFCreateCAFFile(char *cfpath, ARTNUM lowart, ARTNUM tocsize, size_t cfsize, int nolink, char *temppath);
123 extern const char *CAFErrorStr(void);
124 extern CAFTOCENT *CAFReadTOC(char *cfpath, CAFHEADER *ch);
125 extern int CAFRemoveMultArts(char *cfpath, unsigned int narts, ARTNUM *arts);
126 extern int CAFStatArticle(char *path, ARTNUM art, struct stat *st);
129 /* functions used internally by caf.c, and by the cleaner program, and cafls
130 but probably aren't useful/desirable to be used by others. */
131 extern int CAFOpenReadTOC(char *cfpath, CAFHEADER *ch, CAFTOCENT **tocpp);
132 extern int CAFReadHeader(int fd, CAFHEADER *h);
133 extern off_t CAFRoundOffsetUp(off_t offt, unsigned int bsize);
134 extern CAFBITMAP * CAFReadFreeBM(int fd, CAFHEADER *h);
135 extern void CAFDisposeBitmap(CAFBITMAP *cbm);
137 ** note! CAFIsBlockFree needs the fd, since blocks of the free bitmap may
138 ** need to be fetched from disk.
140 extern int CAFIsBlockFree(CAFBITMAP *bm, int fd, off_t block);
143 extern int caf_error; /* last error encountered by library. */
144 extern int caf_errno; /* saved value of errno here if I/O error hit by lib. */
146 #define CAF_ERR_IO 1 /* generic I/O error, check caf_errno for details */
147 #define CAF_ERR_BADFILE 2 /* corrupt file */
148 #define CAF_ERR_ARTNOTHERE 3 /* article not in the database */
149 #define CAF_ERR_CANTCREATECAF 4 /* can't create the CAF file, see errno. */
150 #define CAF_ERR_FILEBUSY 5 /* file locked by someone else. */
151 #define CAF_ERR_ARTWONTFIT 6 /* outside the range in the TOC */
152 #define CAF_ERR_ARTALREADYHERE 7 /* tried to create an article that was already here. */
153 #define CAF_ERR_BOGUSPATH 8 /* pathname not parseable. */