1 #if HAVE_CONFIG_H 2 # include <config.h> 3 #endif 4 5 #include <lzma.h> 6 7 #define __USE_LARGEFILE 1 8 9 #include <stdbool.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <sys/types.h> 14 15 #include <pthread.h> 16 17 18 #pragma mark DEFINES 19 20 #define PIXZ_INDEX_MAGIC 0xDBAE14D62E324CA6LL 21 22 #define CHECK LZMA_CHECK_CRC32 23 #define MEMLIMIT (64ULL * 1024 * 1024 * 1024) // crazy high 24 25 #define CHUNKSIZE 4096 26 27 #ifndef DEBUG 28 #define DEBUG 0 29 #endif 30 #if DEBUG 31 #define debug(str, ...) fprintf(stderr, str "\n", ##__VA_ARGS__) 32 #else 33 #define debug(...) 34 #endif 35 36 37 #pragma mark LIBARCHIVE CHANGES 38 39 #include <archive.h> 40 #if ARCHIVE_VERSION_NUMBER >= 3000000 41 #define prevent_compression(a) archive_read_support_filter_none(a) 42 #define finish_reading(a) archive_read_free(a) 43 #else 44 #define prevent_compression(a) archive_read_support_compression_none(a) 45 #define finish_reading(a) archive_read_finish(a) 46 #endif 47 48 #pragma mark OPERATIONS 49 50 void pixz_list(bool tar); 51 void pixz_write(bool tar, uint32_t level); 52 void pixz_read(bool verify, size_t nspecs, char **specs); 53 54 55 #pragma mark UTILS 56 57 extern FILE *gInFile, *gOutFile; 58 extern lzma_stream gStream; 59 60 extern lzma_index *gIndex; 61 62 63 void die(const char *fmt, ...); 64 char *xstrdup(const char *s); 65 66 uint64_t xle64dec(const uint8_t *d); 67 void xle64enc(uint8_t *d, uint64_t n); 68 size_t num_threads(void); 69 70 extern double gBlockFraction; 71 72 73 #pragma mark INDEX 74 75 typedef struct file_index_t file_index_t; 76 struct file_index_t { 77 char *name; 78 off_t offset; 79 file_index_t *next; 80 }; 81 82 extern file_index_t *gFileIndex, *gLastFile; 83 84 bool is_multi_header(const char *name); 85 bool decode_index(void); // true on success 86 87 lzma_vli read_file_index(void); 88 void dump_file_index(FILE *out, bool verbose); 89 void free_file_index(void); 90 91 92 #pragma mark QUEUE 93 94 typedef struct queue_item_t queue_item_t; 95 struct queue_item_t { 96 int type; 97 void *data; 98 queue_item_t *next; 99 }; 100 101 typedef void (*queue_free_t)(int type, void *p); 102 103 typedef struct { 104 queue_item_t *first; 105 queue_item_t *last; 106 107 pthread_mutex_t mutex; 108 pthread_cond_t pop_cond; 109 110 queue_free_t freer; 111 } queue_t; 112 113 114 queue_t *queue_new(queue_free_t freer); 115 void queue_free(queue_t *q); 116 void queue_push(queue_t *q, int type, void *data); 117 int queue_pop(queue_t *q, void **datap); 118 119 120 #pragma mark PIPELINE 121 122 extern size_t gPipelineQSize; 123 extern size_t gPipelineProcessMax; 124 extern queue_t *gPipelineStartQ, *gPipelineSplitQ, *gPipelineMergeQ; 125 126 typedef enum { 127 PIPELINE_ITEM, 128 PIPELINE_STOP 129 } pipeline_tag_t; 130 131 typedef struct pipeline_item_t pipeline_item_t; 132 struct pipeline_item_t { 133 size_t seq; 134 pipeline_item_t *next; 135 136 void *data; 137 }; 138 139 typedef void* (*pipeline_data_create_t)(void); 140 typedef void (*pipeline_data_free_t)(void*); 141 typedef void (*pipeline_split_t)(void); 142 typedef void (*pipeline_process_t)(size_t); 143 144 void pipeline_create( 145 pipeline_data_create_t create, 146 pipeline_data_free_t destroy, 147 pipeline_split_t split, 148 pipeline_process_t process); 149 void pipeline_stop(void); 150 void pipeline_destroy(void); 151 152 void pipeline_dispatch(pipeline_item_t *item, queue_t *q); 153 void pipeline_split(pipeline_item_t *item); 154 pipeline_item_t *pipeline_merged(); 155