1 /*
2  * afflib_i.h:
3  * The "master include file" of the AFF Library.
4  * Includes many fucntions that are not designed
5  * to be used by application programmers.
6  *
7  *
8  * Copyright (c) 2005-2006
9  *	Simson L. Garfinkel and Basis Technology, Inc.
10  *      All rights reserved.
11  *
12  * This code is derrived from software contributed by
13  * Simson L. Garfinkel
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  * 3. All advertising materials mentioning features or use of this software
24  *    must display the following acknowledgement:
25  *    This product includes software developed by Simson L. Garfinkel
26  *    and Basis Technology Corp.
27  * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
28  *    contributors to this program may be used to endorse or promote
29  *    products derived from this software without specific prior written
30  *    permission.
31  *
32  * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
33  * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
34  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
35  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36  * DISCLAIMED.  IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
37  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
40  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
41  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
42  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
43  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44  * SUCH DAMAGE.
45  */
46 
47 #ifndef AFFLIB_I_H
48 #define AFFLIB_I_H
49 
50 #ifdef KERNEL_LIBRARY
51 #ifdef __cplusplus
52 extern "C" {
53 #endif
54 void __cdecl AFDbgPrint (PCSTR Format,...);
55 #ifdef __cplusplus
56 }
57 #endif
58 #endif
59 
60 
61 /* Should we disable threading? */
62 #ifdef DISABLE_PTHREAD
63 #undef HAVE_PTHREAD
64 #endif
65 
66 /* Standard includes */
67 #ifdef HAVE_STRING_H
68 #include <string.h>
69 #endif
70 
71 #ifdef HAVE_STDLIB_H
72 #include <stdlib.h>
73 #endif
74 
75 #ifdef HAVE_ZLIB_H
76 #include <zlib.h>
77 #endif
78 
79 #ifdef HAVE_SYS_STAT_H
80 #include <sys/stat.h>
81 #endif
82 
83 #ifdef HAVE_FCNTL_H
84 #include <fcntl.h>
85 #endif
86 
87 #ifdef HAVE_ASSERT_H
88 #include <assert.h>
89 #endif
90 
91 #ifdef HAVE_ERRNO_H
92 #include <errno.h>
93 #endif
94 
95 #ifdef HAVE_DIRENT_H
96 #include <dirent.h>
97 #endif
98 
99 #ifdef HAVE_ERR_H
100 #include <err.h>
101 #endif
102 
103 #ifdef HAVE_ALLOCA_H
104 #include <alloca.h>
105 #endif
106 
107 #ifdef HAVE_LIBCRYPTO
108 #include <openssl/aes.h>
109 #include <openssl/rsa.h>		// a standard part of OpenSSL
110 #include <openssl/rand.h>
111 #include <openssl/md5.h>
112 #include <openssl/sha.h>
113 #endif
114 
115 #ifdef HAVE_PTHREAD
116 #include <pthread.h>
117 #define AF_READLOCK(af) pthread_rwlock_rdlock(&af->rwlock);
118 #define AF_WRLOCK(af) pthread_rwlock_wrlock(&af->rwlock);
119 #define AF_UNLOCK(af) pthread_rwlock_unlock(&af->rwlock);
120 #else
121 /* No threads */
122 #define AF_READLOCK(af) {}
123 #define AF_WRLOCK(af)   {}
124 #define AF_UNLOCK(af)   {}
125 #endif
126 
127 #ifdef WIN32
128 #if !defined(HAVE__MINGW_H)
129 #pragma warning(disable: 4996)  /* Don't warn on Windows about using POSIX open() instead of _open() */
130 #endif
131 #include <malloc.h>
132 #include <windows.h>
133 #include <winsock.h>			// htonl()
134 #include <direct.h>
135 #define snprintf _snprintf
136 #define strcasecmp _stricmp
137 #define mkdir(path,mode) _mkdir(path)
138 #define random() rand()
139 #define access _access
140 #define strdup _strdup
141 
142 #ifndef ENOTSUP
143 #define ENOTSUP 65536		/* made up number */
144 #endif
145 
146 #ifndef _MODE_T_
147 #define _MODE_T_
148 typedef unsigned short mode_t;
149 typedef unsigned short _mode_t;
150 #endif
151 
152 #ifndef S_ISDIR
153 #define S_ISDIR(m)(((m) & 0170000) == 0040000)
154 #endif
155 
156 #if !defined(HAVE__MINGW_H)
157 #define ftruncate(fd,size) _chsize_s(fd,size)
158 #define MAXPATHLEN 1024
159 #endif
160 
161 #if defined(HAVE__MINGW_H)
162 #ifndef ftello
163 #define ftello ftello64
164 #endif
165 
166 #ifndef fseeko
167 #define fseeko fseeko64
168 #endif
169 
170 #else
171 #define ftello _ftelli64			/* replaces ftello64 in VC2008 */
172 #define fseeko _fseeki64
173 #endif
174 
175 #endif
176 /** END OF WIN32 DEFINES **/
177 
178 #ifndef MAXPATHLEN
179 #define MAXPATHLEN 1024
180 #endif
181 
182 #ifdef HAVE_SYS_PARAM_H
183 #include <sys/param.h>
184 #endif
185 
186 #ifdef HAVE_ARPA_INET_H
187 #include <arpa/inet.h>
188 #endif
189 
190 #ifdef HAVE_UNISTD_H
191 #include <unistd.h>
192 #endif
193 
194 /* Pick an appropriate POINTER_FMT; isn't there an ANSI standard for this? */
195 #ifdef __APPLE__
196 #define POINTER_FMT "%p"
197 #endif
198 
199 #ifdef linux
200 #define POINTER_FMT "%p"
201 #endif
202 
203 #ifndef POINTER_FMT
204 #define POINTER_FMT "%x"		// guess
205 #endif
206 
207 /* Handle systems that are missing some #defines */
208 
209 #ifndef O_BINARY
210 #define O_BINARY 0			// for Windows compatability
211 #endif
212 
213 #ifndef ENOTSUP
214 #define ENOTSUP EOPNOTSUPP
215 #endif
216 
217 #ifndef O_ACCMODE
218 #define O_ACCMODE 0x0003
219 #endif
220 
221 /* If these functions do not exist, we need to create our own */
222 
223 #ifndef HAVE_ERR
224 void err(int eval, const char *fmt, ...);
225 #endif
226 
227 #ifndef HAVE_ERRX
228 void errx(int eval, const char *fmt, ...);
229 #endif
230 
231 #ifndef HAVE_WARN
232 void	warn(const char *fmt, ...);
233 #endif
234 
235 #ifndef HAVE_WARNX
236 void	warnx(const char *fmt, ...);
237 #endif
238 
239 /* access function */
240 #ifndef F_OK
241 #define F_OK            0       /* test for existence of file */
242 #endif
243 
244 #ifndef X_OK
245 #define X_OK            0x01    /* test for execute or search permission */
246 #endif
247 
248 #ifndef W_OK
249 #define W_OK            0x02    /* test for write permission */
250 #endif
251 
252 #ifndef R_OK
253 #define R_OK            0x04    /* test for read permission */
254 #endif
255 
256 
257 #if defined(WIN32) && !defined(HAVE__MINGW_H)
258 /****************************************************************
259  *** Windows emulation of opendir()/readdir()
260  *** From php
261  ****************************************************************/
262 
263 /* struct dirent - same as Unix */
264 
265 struct dirent {
266 	long  d_ino;		       /* inode (always 1 in WIN32) */
267 	off_t d_off;			/* offset to this dirent */
268 	int   d_reclen;	    /* length of d_name; was unsigned short */
269 	char  d_name[_MAX_FNAME + 1];	/* filename (null terminated) */
270 };
271 
272 
273 /* typedef DIR - not the same as Unix */
274 typedef struct {
275 	long handle;				/* _findfirst/_findnext handle */
276 	short offset;				/* offset into directory */
277 	short finished;				/* 1 if there are not more files */
278 	struct _finddata_t fileinfo;	/* from _findfirst/_findnext */
279 	char *dir;					/* the dir we are reading */
280 	struct dirent dent;			/* the dirent to return */
281 } DIR;
282 
283 /* Function prototypes */
284 
285 
286 #ifdef __cplusplus
287 extern "C" {
288 #endif
289 
290 DIR *opendir(const char *);
291 struct dirent *readdir(DIR *);
292 int readdir_r(DIR *, struct dirent *, struct dirent **);
293 int closedir(DIR *);
294 int rewinddir(DIR *);
295 
296 
297 #ifdef __cplusplus
298 }
299 #endif
300 #endif
301 
302 
303 /****************************************************************
304  *** AFFLIB internal stuff follows.
305  ****************************************************************/
306 
307 #ifdef __cplusplus
308 extern "C" {
309 #endif
310 #ifdef NEVER_DEFINED
311 }
312 #endif
313 
314 #if defined(HAVE_LIBEXPAT)
315 #define USE_AFFSIGS
316 #endif
317 
318 struct _AFFILE {
319     int     version;			// 2
320     void   *tag;			// available to callers; unused by AFFLIB
321 
322     struct af_vnode *v;			// which function table to use.
323     struct _AFFILE *parent;		// for AFF file inside an AFD
324 
325     /* For all files */
326     int     openflags;			// how it was opened
327     int     openmode;			// how we were asked to open it; more
328     int     exists;			// did file exist before open was called?
329 
330     /* From URLs */
331     char    *fname;			// Filename of file; be sure to free when done
332     char    *protocol;			// could be "file" or "s3"
333     char    *username;			// optionally specified in URL
334     char    *password;			// from URL; erase after use.
335     char    *hostname;			// from URL
336     int     port;			// from URL
337 
338     /* Extended Logging */
339     char    error_str[64];		// what went wrong
340 
341     /* Implement a stream abstraction */
342     uint64_t    image_size;		// last mappable byte of disk image
343     uint64_t    image_size_in_file;	// see if it was changed...
344     uint32_t	image_pagesize;	// the size of image data segments in this file
345     uint32_t	image_sectorsize;
346     uint64_t	pos;			// location in stream; should be signed because of comparisons
347 
348     /* Page buffer cache */
349     struct aff_pagebuf *pb;		// the current page buffer
350     struct aff_pagebuf *pbcache;	// array of pagebufs
351     int		num_pbufs;	   // number of pagebufs; default is 1
352     int		afftime;		// for updating last
353     int64_t	cur_page;		// used by vnode_raw to fake pages must be able to go negative.
354 
355     int		  debug;		// for debugging, of course
356     unsigned int  badflag_set:1;	// is badflag set?
357     unsigned char *badflag;		// bad sector flag
358 
359 
360     /****************************************************************/
361     /* Right now the instance variables for each implementation are here,
362      * which is ugly but easier for development...
363      */
364 
365     /* For AFF Segment Files; this could be moved into private storage... */
366     FILE          *aseg;
367     struct aff_toc_mem *toc;		// table of contents
368     int	           toc_count;	       // number of directory elements
369 
370     /****************************************************************/
371 
372     unsigned int write_md5:1;		// automatically write the MD5 for each page
373     unsigned int write_sha1:1;
374     unsigned int write_sha256:1;
375 
376 
377     /* These are for optimizing updates; really this should go away and we should just
378      * exmaine the TOC to find a hole, but currently we don't do that.
379      */
380     unsigned int direction_changes;     // how many times have we changed directions?
381     int          last_direction;	// should be 1 or -1
382     unsigned int random_access:1;	// are we in random access mode?
383 
384     /* additional support for writing. */
385     unsigned int compression_type;	// preferred compression type
386     int		 compression_level;	// 0 is no compression
387 
388 
389     /* w_callback:
390      * A callback that is called before and after each segment is written.
391      * Called with the arguments (i,0,0) at the beginning of the write operation.
392      * Called with the arguments (i,j,k) at the end of the write operation.
393      * i = segment number
394      * j = segment length
395      * If segment is being written with compresison, k = compressed length.
396      * If segment is written w/o compression, k = 0
397      */
398     void (*w_callback)(struct affcallback_info *acbi);
399     // called at start and end of compression.
400 
401     uint64_t	maxsize;		// maximum file size of a multi-segment files,
402                                         // or 0 if this is not a multi-segment file
403 
404     /* Performance Counters */
405     uint64_t	bytes_memcpy;		// total number of bytes memcpy'ed
406     uint64_t    pages_written;		// total number of pages written
407     uint64_t    pages_compressed;	// total number of pages compressed
408     uint64_t	pages_decompressed;
409     uint64_t    pages_read;		// total number of pages read
410     uint64_t	bytes_written;
411     uint64_t	cache_hits;
412     uint64_t	cache_misses;		// total number of pages flushed from cache
413 
414     void	*vnodeprivate;	      // private storage for the vnode
415     void	(*error_reporter)(const char *fmt, ...);
416     struct af_crypto *crypto;
417 #ifdef HAVE_PTHREAD
418     pthread_rwlock_t rwlock;		// automatically created and destroyed if pthread exists
419 #endif
420     struct af_vnode_info *vni_cache;	// vstat cache
421 };
422 
423 
424 
425 /* af_crypto:
426  * copy of AES encrypt and decrypt keys.
427  */
428 void af_crypto_allocate(AFFILE *af);
429 void af_crypto_deallocate(AFFILE *af);
430 
431 struct af_crypto {
432     uint32_t sealing_key_set:1;		// encryption key has been set
433     uint32_t auto_encrypt:1;		// encrypt segments when we write
434     uint32_t auto_decrypt:1;		// automatically decrypto when we read
435 #ifdef AES_BLOCK_SIZE
436     AES_KEY	ekey;			// encrypt key
437     AES_KEY	dkey;			// decrypt key
438 #endif
439 #ifdef HAVE_OPENSSL_EVP_H
440     EVP_PKEY	*sign_privkey;		// signing private key (to write signatures)
441     EVP_PKEY	*sign_pubkey;		// signing public key (to verify signatures)
442     X509	*sign_cert;		// signing certificate (for verifying signatures)
443     /* Sealing is kept locally and immediately turned into a dkey & ekey */
444 #endif
445 };
446 
447 
448 /* The AFF STREAM VNODE */
449 struct af_vnode {
450     int type;				// numeric vnode type
451     int flag;				// file system flag type
452     const char *name;
453     int (*identify)(const char *fname,int exists);	// returns 1 if file system is identified by implementation;
454     int (*open)(AFFILE *af);
455     int (*close)(AFFILE *af);
456     int (*vstat)(AFFILE *af,struct af_vnode_info *);	// returns info about the vnode image file
457     int (*get_seg)(AFFILE *af,const char *name,uint32_t *arg, uint8_t *data,size_t *datalen);
458     int	(*get_next_seg)(AFFILE *af,char *segname,size_t segname_len,
459 			uint32_t *arg, uint8_t *data, size_t *datalen);
460     int (*rewind_seg)(AFFILE *af);
461     int (*update_seg)(AFFILE *af,const char *name,uint32_t arg,
462 		      const uint8_t *value,uint32_t vallen);
463     int (*del_seg)(AFFILE *af,const char *name);
464     int (*read)(AFFILE *af,uint8_t *buf,uint64_t offset,size_t count);
465     int (*write)(AFFILE *af,uint8_t *buf,uint64_t offset,size_t count);
466 };
467 
468 /* VNODE Flags */
469 #define AF_VNODE_TYPE_PRIMITIVE 0x01	// single-file implementation
470 #define AF_VNODE_TYPE_COMPOUND  0x02	// multi-file implementation
471 #define AF_VNODE_TYPE_RELIABLE  0x04	// writes are reliable; no need to verify them.
472 #define AF_VNODE_MAXSIZE_MULTIPLE 0x08  // maxsize must be multiple of pagesize (for AFM and splitraw)
473 #define AF_VNODE_NO_SIGNING     0x10	// vnode does not support signing (like raw)
474 #define AF_VNODE_NO_SEALING     0x20	// vnode does not support sealing (like raw and afd)
475 
476 #define AF_SEALING_VNODE(af) (!(af->v->flag & AF_VNODE_NO_SEALING))
477 #define AF_SIGNING_VNODE(af) (!(af->v->flag & AF_VNODE_NO_SIGNING))
478 #define AF_SEALING(af) AF_SEALING_VNODE(af) && af->crypto && af->crypto->sealing_key_set
479 
480 
481 /* The header for an AFF file. All binary numbers are stored in network byte order. */
482 #define AF_HEADER "AFF10\r\n\000"
483 struct af_head {
484     char header[8];			// "AFF10\r\n\000"
485     /* segments follow */
486 };
487 
488 
489 /* The header of each segment */
490 #define AF_SEGHEAD "AFF\000"
491 struct af_segment_head {
492     char magic[4];			// "AFF\000"
493     uint32_t name_len:32;		// length of segment name
494     uint32_t data_len:32;		// length of segment data, if any
495     uint32_t flag:32;		// argument for name;
496     /* name follows, then data */
497 };
498 
499 /* The tail of each segment */
500 #define AF_SEGTAIL "ATT\000"
501 struct af_segment_tail {
502     char magic[4];			// "ATT\000"
503     uint32_t segment_len:32;      // includes head, tail, name & length
504 };
505 
506 
507 /* How 64-bit values are stored in a segment */
508 #pragma pack(1)
509 struct aff_quad {
510     uint32_t low:32;
511     uint32_t high:32;
512 };
513 #pragma pack()
514 
515 
516 /* As it is kept in memory */
517 struct aff_toc_mem {
518     char *name;			        // name of this directory entry
519     uint64_t offset;			// offset from beginning of file.
520     uint64_t segment_len;		// includes head, tail, name & length
521 };
522 
523 /* How encryption keys are stored */
524 struct affkey {
525     uint8_t version[4];
526     uint8_t affkey_aes256[32]; // AFF key encrypted with SHA-256 of passphrase
527                               // encrypted as two codebooks in a row; no need for CBC
528     uint8_t zeros_aes256[16];  // all zeros encrypted with SHA-256 of passphrase
529 };
530 #define AFFKEY_SIZE 4+32+16
531 
532 
533 void af_initialize();			// initialize the AFFLIB
534                                         // automatically called by af_open()
535 
536 /* Internal identification routines */
537 int af_identify_file_type(const char *filename,int exists); // returns type of a file; if exists=1, file must exist
538 const char *af_identify_file_name(const char *filename,int exists); // returns name of a file type;
539 int split_raw_increment_fname (char *fn); /* exposed for testing in aftest */
540 
541 AFFILE *af_open_with(const char *filename,int flags,int mode, struct af_vnode *v);
542 extern struct af_vnode *af_vnode_array[]; // array of filesystems; last is a "0"
543 
544 int	af_last_seg(AFFILE *af,char *last_segname,int last_segname_len,int64_t *pos);
545 int	af_make_badflag(AFFILE *af);	// creates a badflag and puts it
546 int	af_make_gid(AFFILE *af);	// created an AF_IMAGE_GID if it doesn't exist
547 extern  char af_error_str[64];
548 
549 
550 #define AFF_DEFAULT_PAGESIZE (1024*1024*16)
551 
552 
553 /* afflib_os.cpp:
554  * Operating-system specific code.
555  */
556 
557 /* af_figure_media:
558  * Returns information about the media in a structure.
559  * Returns 0 if successful, -1 if error.
560  */
561 
562 struct af_figure_media_buf {
563     int version;
564     int sector_size;
565     uint64_t total_sectors;
566     uint64_t max_read_blocks;		// was previously 4-bytes; must be 8!
567 };
568 int	af_figure_media(int fd,struct af_figure_media_buf *);
569 
570 /****************************************************************
571  *** Lowest-level routines for manipulating the AFF File...
572  ****************************************************************/
573 
574 /* Navigating within the AFFILE */
575 /* probe the next segment.
576  * Returns: 0 if success
577  *          -1 if error
578  *          -2 if segname_len was not large enough to hold segname
579  *         - segname - the name of the next segment.
580  *         - segsize - number of bytes the entire segment is.
581  *
582  * doesn't change af->aseg pointer if do_rewind is true, otherwise leaves stream
583  *           positioned ready to read the data
584  */
585 
586 int	af_probe_next_seg(AFFILE *af,char *segname,size_t segname_len,
587 			   uint32_t *arg,size_t *datasize, size_t *segsize,int do_rewind);
588 int	af_backspace(AFFILE *af);	// back up one segment
589 
590 
591 
592 /****************************************************************
593  *** Reading functions
594  ****************************************************************/
595 
596 
597 /* Support for data pages. This is what the stream system is built upon.
598  * Note: pagename to string translation happens inside afflib.cpp, not inside
599  * the vnode driver.
600  */
601 int	af_page_size(AFFILE *af);	// legacy (now is af_get_pagesize)
602 void	af_read_sizes(AFFILE *af);	// sets up values if we can get them.
603 int	af_set_pagesize(AFFILE *af,uint32_t pagesize); // sets the pagesize; fails with -1 if imagesize >=0
604 int	af_set_sectorsize(AFFILE *AF,int sectorsize); // fails with -1 if imagesize>=0
605 int	af_get_sectorsize(AFFILE *AF);	// returns sector size
606 int	af_has_pages(AFFILE *af);	// does the underlying system support pages?
607 int	af_get_pagesize(AFFILE *af);	// returns page size, or -1
608 int	af_get_page_raw(AFFILE *af,int64_t pagenum,uint32_t *arg,uint8_t *data,size_t *bytes);
609 int	af_get_page(AFFILE *af,int64_t pagenum,uint8_t *data,size_t *bytes);
610 #define AF_SIGFLAG_NOSIG 0x0001	// do not write signatures with af_update_segf()
611 #define AF_SIGFLAG_NOSEAL 0x0002	// do not encrypt an af_update_segf()
612 
613 /****************************************************************
614  *** Writing functions
615  ****************************************************************/
616 
617 extern  int af_cache_debug;			 // sets level of verbosity */
618 int	af_update_page(AFFILE *af,int64_t pagenum,uint8_t *data,int datalen);
619 int	af_update_segf(AFFILE *af,const char *name,
620 		       uint32_t arg,const uint8_t *value,uint32_t vallen,uint32_t sigflag);
621 
622 void	af_invalidate_vni_cache(AFFILE *af);
623 void	af_cache_writethrough(AFFILE *af,int64_t pagenum,
624 			      const uint8_t *buf,int bufflen);
625 int	af_cache_flush(AFFILE *af);		// write buffers to disk
626 struct aff_pagebuf *af_cache_alloc(AFFILE *af,int64_t pagenum);
627 
628 
629 /****************************************************************
630  ***/
631 
632 /* afflib_util.cpp
633  */
634 uint64_t   af_decode_q(uint8_t buf[8]); // return buf[8] into an unsigned quad
635 const char *af_commas(char buf[64],int64_t val);
636 int       af_hasmeta(const char *buf);	// return 1 if buf has shell metacharacters
637 int	  af_is_filestream(const char *filename); // return 1 if file:// or filename
638 void      af_parse_url(const char *url,char **protocol,char **hostname,
639 		       char **username,char **password,int *port,char **path);
640 
641 #ifndef HAVE_STRLCPY
642 size_t strlcpy(char *dest,const char *src,size_t dest_size);
643 #endif
644 
645 #ifndef HAVE_STRLCAT
646 size_t strlcat(char *dest,const char *src,size_t dest_size);
647 #endif
648 
649 
650 /****************************************************************
651  *** Table of Contents
652  ****************************************************************/
653 
654 /* Needs a rewrite for efficiency */
655 
656 /* afflib_toc.cpp:
657  * Table of contents management routines
658  * Remember: all of these routines may fail, because the whole TOC may not
659  * fit in memory...
660  *
661  * This is all experimental right now.
662  */
663 
664 int	aff_segment_overhead(const char *segname);
665 int	aff_toc_free(AFFILE *af);
666 void	aff_toc_print(AFFILE *af);
667 int	aff_toc_build(AFFILE *af);	// build by scanning the AFFILE
668 struct aff_toc_mem *aff_toc(AFFILE *af,const char *segname);
669 int	aff_toc_del(AFFILE *af,const char *segname);
670 void	aff_toc_update(AFFILE *af,const char *segname,uint64_t offset,uint64_t datalen);
671 
672 struct aff_toc_mem *aff_toc_next_seg(AFFILE *af, uint64_t offset);
673 int aff_toc_find_hole(AFFILE *af, uint64_t min_size, uint64_t *offset, uint64_t *size);
674 
675 /* lzma_glue.cpp:
676  * For the LZMA compression engine
677  */
678 int lzma_compress(uint8_t *dest,size_t *destLen, const uint8_t *data,size_t datalen,int level);
679 int lzma_uncompress(uint8_t *buf,size_t *buflen, const uint8_t *cbuf,size_t cbuf_size);
680 
681 #ifdef NEVER_DEFINED
682 {
683 #endif
684 #ifdef __cplusplus
685 }
686 #endif
687 #endif
688 
689 
690