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