summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xdelta3/xdelta3-main.h453
-rw-r--r--xdelta3/xdelta3.c2
-rw-r--r--xdelta3/xdelta3.h2
3 files changed, 264 insertions, 193 deletions
diff --git a/xdelta3/xdelta3-main.h b/xdelta3/xdelta3-main.h
index 3cb4a5d..0c5e08d 100644
--- a/xdelta3/xdelta3-main.h
+++ b/xdelta3/xdelta3-main.h
@@ -17,38 +17,37 @@
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */ 18 */
19 19
20/* This is all the extra stuff you need for convenience to users in a command line 20/* This is all the extra stuff you need for convenience to users in a
21 * application. It contains these major components: 21 * command line application. It contains these major components:
22 * 22 *
23 * 1. VCDIFF tools 23 * 1. VCDIFF tools 2. external compression support (this is
24 * 2. external compression support (this is POSIX-specific). 24 * POSIX-specific). 3. a general read/write loop that handles all of
25 * 3. a general read/write loop that handles all of the Xdelta decode/encode/VCDIFF-print 25 * the Xdelta decode/encode/VCDIFF-print functions 4. command-line
26 * functions 26 * interpreter 5. an Xdelta application header which stores default
27 * 4. command-line interpreter 27 * filename, external compression settings 6. output/error printing
28 * 5. an Xdelta application header which stores default filename, external compression settings
29 * 6. output/error printing
30 * 7. basic file support and OS interface 28 * 7. basic file support and OS interface
31 */ 29 */
32 30
33/* TODO list: 31/* TODO list: 1. do exact gzip-like filename, stdout handling. make a
34 * 1. do exact gzip-like filename, stdout handling. make a .vcdiff extension, refuse 32 * .vcdiff extension, refuse to encode to stdout without -cf, etc.
35 * to encode to stdout without -cf, etc. 33 * 2. Allow the user to add a comment string to the app header without
36 * 2. Allow the user to add a comment string to the app header without disturbing the default 34 * disturbing the default behavior. 3. "Source file must be seekable"
37 * behavior. 35 * is not actually true for encoding, given current behavior. Allow
38 * 3. "Source file must be seekable" is not actually true for encoding, given current 36 * non-seekable sources? It would in theory let you use a fifo for
39 * behavior. Allow non-seekable sources? It would in theory let you use a fifo for 37 * the source.
40 * the source.
41 */ 38 */
42 39
43/* On error handling and printing: 40/* On error handling and printing:
44 * 41 *
45 * The xdelta library sets stream->msg to indicate what condition caused an internal 42 * The xdelta library sets stream->msg to indicate what condition
46 * failure, but many failures originate here and are printed here. The return convention 43 * caused an internal failure, but many failures originate here and
47 * is 0 for success, as throughout Xdelta code, but special attention is required here for 44 * are printed here. The return convention is 0 for success, as
48 * the operating system calls with different error handling. See the main_file_* routines. 45 * throughout Xdelta code, but special attention is required here for
49 * All errors in this file have a message printed at the time of occurance. Since some of 46 * the operating system calls with different error handling. See the
50 * these calls occur within calls to the library, the error may end up being printed again 47 * main_file_* routines. All errors in this file have a message
51 * with a more general error message. 48 * printed at the time of occurance. Since some of these calls occur
49 * within calls to the library, the error may end up being printed
50 * again with a more general error message.
52 */ 51 */
53 52
54/******************************************************************************************/ 53/******************************************************************************************/
@@ -89,8 +88,8 @@ const char* xd3_mainerror(int err_num);
89/* The number of soft-config variables. */ 88/* The number of soft-config variables. */
90#define XD3_SOFTCFG_VARCNT 7 89#define XD3_SOFTCFG_VARCNT 7
91 90
92/* this is used as in XPR(NT XD3_LIB_ERRMSG (stream, ret)) to print an error message 91/* this is used as in XPR(NT XD3_LIB_ERRMSG (stream, ret)) to print an
93 * from the library. */ 92 * error message from the library. */
94#define XD3_LIB_ERRMSG(stream, ret) "%s: %s\n", xd3_errstring (stream), xd3_mainerror (ret) 93#define XD3_LIB_ERRMSG(stream, ret) "%s: %s\n", xd3_errstring (stream), xd3_mainerror (ret)
95 94
96#include <stdio.h> /* fprintf */ 95#include <stdio.h> /* fprintf */
@@ -127,20 +126,24 @@ const char* xd3_mainerror(int err_num);
127static STARTUPINFO winStartupInfo; 126static STARTUPINFO winStartupInfo;
128#endif 127#endif
129 128
130/****************************************************************************************** 129/**********************************************************************
131 ENUMS and TYPES 130 ENUMS and TYPES
132 ******************************************************************************************/ 131 *********************************************************************/
133 132
134/* These flags (mainly pertaining to main_read() operations) are set in the 133/* These flags (mainly pertaining to main_read() operations) are set
135 * main_file->flags variable. All are related to with external decompression support. 134 * in the main_file->flags variable. All are related to with external
135 * decompression support.
136 * 136 *
137 * RD_FIRST causes the external decompression check when the input is first read. 137 * RD_FIRST causes the external decompression check when the input is
138 * first read.
138 * 139 *
139 * RD_NONEXTERNAL disables external decompression for reading a compressed input, in the 140 * RD_NONEXTERNAL disables external decompression for reading a
140 * case of Xdelta inputs. Note: Xdelta is supported as an external compression type, 141 * compressed input, in the case of Xdelta inputs. Note: Xdelta is
141 * which makes is the reason for this flag. An example to justify this is: to create a 142 * supported as an external compression type, which makes is the
142 * delta between two files that are VCDIFF-compressed. Two external Xdelta decoders are 143 * reason for this flag. An example to justify this is: to create a
143 * run to supply decompressed source and target inputs to the Xdelta encoder. */ 144 * delta between two files that are VCDIFF-compressed. Two external
145 * Xdelta decoders are run to supply decompressed source and target
146 * inputs to the Xdelta encoder. */
144typedef enum 147typedef enum
145{ 148{
146 RD_FIRST = (1 << 0), 149 RD_FIRST = (1 << 0),
@@ -155,7 +158,8 @@ typedef enum
155 XO_WRITE = 1, 158 XO_WRITE = 1,
156} main_file_modes; 159} main_file_modes;
157 160
158/* Main commands. For example, CMD_PRINTHDR is the "xdelta printhdr" command. */ 161/* Main commands. For example, CMD_PRINTHDR is the "xdelta printhdr"
162 * command. */
159typedef enum 163typedef enum
160{ 164{
161 CMD_NONE = 0, 165 CMD_NONE = 0,
@@ -184,10 +188,11 @@ typedef struct _main_extcomp main_extcomp;
184typedef struct _main_blklru main_blklru; 188typedef struct _main_blklru main_blklru;
185typedef struct _main_blklru_list main_blklru_list; 189typedef struct _main_blklru_list main_blklru_list;
186 190
187/* The main_file object supports abstract system calls like open, close, read, write, seek, 191/* The main_file object supports abstract system calls like open,
188 * stat. The program uses these to represent both seekable files and non-seekable files. 192 * close, read, write, seek, stat. The program uses these to
189 * Source files must be seekable, but the target input and any output file do not require 193 * represent both seekable files and non-seekable files. Source files
190 * seekability. 194 * must be seekable, but the target input and any output file do not
195 * require seekability.
191 */ 196 */
192struct _main_file 197struct _main_file
193{ 198{
@@ -210,8 +215,8 @@ struct _main_file
210 uint8_t *snprintf_buf; /* internal snprintf() use */ 215 uint8_t *snprintf_buf; /* internal snprintf() use */
211}; 216};
212 217
213/* Various strings and magic values used to detect and call external compression. See 218/* Various strings and magic values used to detect and call external
214 * below for examples. */ 219 * compression. See below for examples. */
215struct _main_extcomp 220struct _main_extcomp
216{ 221{
217 const char *recomp_cmdname; 222 const char *recomp_cmdname;
@@ -616,7 +621,8 @@ main_strtoxoff (const char* s, xoff_t *xo, char which)
616} 621}
617 622
618static int 623static int
619main_atou (const char* arg, usize_t *xo, usize_t low, usize_t high, char which) 624main_atou (const char* arg, usize_t *xo, usize_t low,
625 usize_t high, char which)
620{ 626{
621 xoff_t x; 627 xoff_t x;
622 int ret; 628 int ret;
@@ -641,13 +647,14 @@ main_atou (const char* arg, usize_t *xo, usize_t low, usize_t high, char which)
641 return 0; 647 return 0;
642} 648}
643 649
644/****************************************************************************************** 650/******************************************************************
645 FILE BASICS 651 FILE BASICS
646 ******************************************************************************************/ 652 ******************************************************************/
647 653
648/* With all the variation in file system-call semantics, arguments, return values and 654/* With all the variation in file system-call semantics, arguments,
649 * error-handling for the POSIX and STDIO file APIs, the insides of these functions make 655 * return values and error-handling for the POSIX and STDIO file APIs,
650 * me sick, which is why these wrappers exist. */ 656 * the insides of these functions make me sick, which is why these
657 * wrappers exist. */
651 658
652#define XOPEN_OPNAME (xfile->mode == XO_READ ? "read" : "write") 659#define XOPEN_OPNAME (xfile->mode == XO_READ ? "read" : "write")
653#define XOPEN_STDIO (xfile->mode == XO_READ ? "rb" : "wb") 660#define XOPEN_STDIO (xfile->mode == XO_READ ? "rb" : "wb")
@@ -836,10 +843,10 @@ main_file_exists (main_file *xfile)
836} 843}
837 844
838#if (XD3_POSIX || EXTERNAL_COMPRESSION) 845#if (XD3_POSIX || EXTERNAL_COMPRESSION)
839/* POSIX-generic code takes a function pointer to read() or write(). This calls the 846/* POSIX-generic code takes a function pointer to read() or write().
840 * function repeatedly until the buffer is full or EOF. The NREAD parameter is not 847 * This calls the function repeatedly until the buffer is full or EOF.
841 * set for write, NULL is passed. Return is signed, < 0 indicate errors, otherwise 848 * The NREAD parameter is not set for write, NULL is passed. Return
842 * byte count. */ 849 * is signed, < 0 indicate errors, otherwise byte count. */
843typedef int (xd3_posix_func) (int fd, uint8_t *buf, usize_t size); 850typedef int (xd3_posix_func) (int fd, uint8_t *buf, usize_t size);
844 851
845static int 852static int
@@ -871,8 +878,8 @@ xd3_posix_io (int fd, uint8_t *buf, usize_t size, xd3_posix_func *func, usize_t
871} 878}
872#endif 879#endif
873 880
874/* POSIX is unbuffered, while STDIO is buffered. main_file_read() should always be called 881/* POSIX is unbuffered, while STDIO is buffered. main_file_read()
875 * on blocks. */ 882 * should always be called on blocks. */
876static int 883static int
877main_file_read (main_file *ifile, 884main_file_read (main_file *ifile,
878 uint8_t *buf, 885 uint8_t *buf,
@@ -988,8 +995,9 @@ main_file_seek (main_file *xfile, xoff_t pos)
988 return ret; 995 return ret;
989} 996}
990 997
991/* This function simply writes the stream output buffer, if there is any, for encode, decode and recode 998/* This function simply writes the stream output buffer, if there is
992 * commands. (The VCDIFF tools use main_print_func()). */ 999 * any, for encode, decode and recode commands. (The VCDIFF tools use
1000 * main_print_func()). */
993static int 1001static int
994main_write_output (xd3_stream* stream, main_file *ofile) 1002main_write_output (xd3_stream* stream, main_file *ofile)
995{ 1003{
@@ -1004,9 +1012,79 @@ main_write_output (xd3_stream* stream, main_file *ofile)
1004 return 0; 1012 return 0;
1005} 1013}
1006 1014
1007/****************************************************************************************** 1015static int
1016main_set_secondary_flags (xd3_config *config)
1017{
1018 int ret;
1019 if (option_use_secondary)
1020 {
1021 /* The default secondary compressor is DJW, if it's compiled. */
1022 if (option_secondary == NULL)
1023 {
1024 if (SECONDARY_DJW)
1025 {
1026 config->flags |= XD3_SEC_DJW;
1027 }
1028 }
1029 else
1030 {
1031 if (strcmp (option_secondary, "fgk") == 0 && SECONDARY_FGK)
1032 {
1033 config->flags |= XD3_SEC_FGK;
1034 }
1035 else if (strncmp (option_secondary, "djw", 3) == 0 && SECONDARY_DJW)
1036 {
1037 usize_t level = 3;
1038
1039 config->flags |= XD3_SEC_DJW;
1040
1041 if (strlen (option_secondary) > 3 &&
1042 (ret = main_atou (option_secondary + 3,
1043 &level,
1044 0, 9, 'S')) != 0 &&
1045 !option_quiet)
1046 {
1047 return XD3_INVALID;
1048 }
1049
1050 /* XD3_SEC_NOXXXX flags disable secondary compression on
1051 * a per-section basis. For djw, ngroups=1 indicates
1052 * minimum work, ngroups=0 uses default settings, which
1053 * is > 1 groups by default. */
1054 if (level < 1) { config->flags |= XD3_SEC_NODATA; }
1055 if (level < 7) { config->sec_data.ngroups = 1; }
1056 else { config->sec_data.ngroups = 0; }
1057
1058 if (level < 3) { config->flags |= XD3_SEC_NOINST; }
1059 if (level < 8) { config->sec_inst.ngroups = 1; }
1060 else { config->sec_inst.ngroups = 0; }
1061
1062 if (level < 5) { config->flags |= XD3_SEC_NOADDR; }
1063 if (level < 9) { config->sec_addr.ngroups = 1; }
1064 else { config->sec_addr.ngroups = 0; }
1065 }
1066 else if (strcmp (option_secondary, "none") == 0 && SECONDARY_DJW)
1067 {
1068 /* No secondary */
1069 }
1070 else
1071 {
1072 if (!option_quiet)
1073 {
1074 XPR(NT "unrecognized secondary compressor type: %s\n",
1075 option_secondary);
1076 return XD3_INVALID;
1077 }
1078 }
1079 }
1080 }
1081
1082 return 0;
1083}
1084
1085/******************************************************************
1008 VCDIFF TOOLS 1086 VCDIFF TOOLS
1009 ******************************************************************************************/ 1087 *****************************************************************/
1010 1088
1011#if VCDIFF_TOOLS 1089#if VCDIFF_TOOLS
1012 1090
@@ -1025,9 +1103,10 @@ main_write_output (xd3_stream* stream, main_file *ofile)
1025 { return ret; } } while (0) 1103 { return ret; } } while (0)
1026 1104
1027#ifdef WIN32 1105#ifdef WIN32
1028/* According to the internet, Windows vsnprintf() differs from most Unix 1106/* According to the internet, Windows vsnprintf() differs from most
1029 * implementations regarding the terminating 0 when the boundary condition 1107 * Unix implementations regarding the terminating 0 when the boundary
1030 * is met. It doesn't matter here, we don't rely on the trailing 0. */ 1108 * condition is met. It doesn't matter here, we don't rely on the
1109 * trailing 0. */
1031#include <stdarg.h> 1110#include <stdarg.h>
1032int 1111int
1033snprintf (char *str, int n, char *fmt, ...) 1112snprintf (char *str, int n, char *fmt, ...)
@@ -1089,7 +1168,8 @@ main_print_window (xd3_stream* stream, main_file *xfile)
1089 { 1168 {
1090 size += stream->dec_current2.size; 1169 size += stream->dec_current2.size;
1091 VC(UT " %s %3u", 1170 VC(UT " %s %3u",
1092 xd3_rtype_to_string (stream->dec_current2.type, option_print_cpymode), 1171 xd3_rtype_to_string (stream->dec_current2.type,
1172 option_print_cpymode),
1093 (usize_t)stream->dec_current2.size)VE; 1173 (usize_t)stream->dec_current2.size)VE;
1094 1174
1095 if (stream->dec_current2.type >= XD3_CPY) 1175 if (stream->dec_current2.type >= XD3_CPY)
@@ -1128,11 +1208,13 @@ main_print_vcdiff_file (main_file *xfile, main_file *file, const char *type)
1128 int ret; /* Used by above macros */ 1208 int ret; /* Used by above macros */
1129 if (file->filename) 1209 if (file->filename)
1130 { 1210 {
1131 VC(UT "XDELTA filename (%s): %s\n", type, file->filename)VE; 1211 VC(UT "XDELTA filename (%s): %s\n", type,
1212 file->filename)VE;
1132 } 1213 }
1133 if (file->compressor) 1214 if (file->compressor)
1134 { 1215 {
1135 VC(UT "XDELTA ext comp (%s): %s\n", type, file->compressor->recomp_cmdname)VE; 1216 VC(UT "XDELTA ext comp (%s): %s\n", type,
1217 file->compressor->recomp_cmdname)VE;
1136 } 1218 }
1137 return 0; 1219 return 0;
1138} 1220}
@@ -1154,13 +1236,17 @@ main_print_func (xd3_stream* stream, main_file *xfile)
1154 if (stream->dec_winstart == 0) 1236 if (stream->dec_winstart == 0)
1155 { 1237 {
1156 VC(UT "VCDIFF version: 0\n")VE; 1238 VC(UT "VCDIFF version: 0\n")VE;
1157 1239 VC(UT "VCDIFF header size: %d\n",
1158 VC(UT "VCDIFF header size: %d\n", stream->dec_hdrsize)VE; 1240 stream->dec_hdrsize)VE;
1159 VC(UT "VCDIFF header indicator: ")VE; 1241 VC(UT "VCDIFF header indicator: ")VE;
1160 if ((stream->dec_hdr_ind & VCD_SECONDARY) != 0) VC(UT "VCD_SECONDARY ")VE; 1242 if ((stream->dec_hdr_ind & VCD_SECONDARY) != 0)
1161 if ((stream->dec_hdr_ind & VCD_CODETABLE) != 0) VC(UT "VCD_CODETABLE ")VE; 1243 VC(UT "VCD_SECONDARY ")VE;
1162 if ((stream->dec_hdr_ind & VCD_APPHEADER) != 0) VC(UT "VCD_APPHEADER ")VE; 1244 if ((stream->dec_hdr_ind & VCD_CODETABLE) != 0)
1163 if (stream->dec_hdr_ind == 0) VC(UT "none")VE; 1245 VC(UT "VCD_CODETABLE ")VE;
1246 if ((stream->dec_hdr_ind & VCD_APPHEADER) != 0)
1247 VC(UT "VCD_APPHEADER ")VE;
1248 if (stream->dec_hdr_ind == 0)
1249 VC(UT "none")VE;
1164 VC(UT "\n")VE; 1250 VC(UT "\n")VE;
1165 1251
1166 IF_SEC(VC(UT "VCDIFF secondary compressor: %s\n", 1252 IF_SEC(VC(UT "VCDIFF secondary compressor: %s\n",
@@ -1350,22 +1436,25 @@ main_recode_func (xd3_stream* stream, main_file *ofile)
1350} 1436}
1351#endif /* VCDIFF_TOOLS */ 1437#endif /* VCDIFF_TOOLS */
1352 1438
1353/****************************************************************************************** 1439/*******************************************************************
1354 Input decompression, output recompression 1440 Input decompression, output recompression
1355 ******************************************************************************************/ 1441 ******************************************************************/
1356 1442
1357#if EXTERNAL_COMPRESSION 1443#if EXTERNAL_COMPRESSION
1358/* This is tricky POSIX-specific code with lots of fork(), pipe(), dup(), waitpid(), and 1444/* This is tricky POSIX-specific code with lots of fork(), pipe(),
1359 * exec() business. Most of this code originated in PRCS1, which did automatic 1445 * dup(), waitpid(), and exec() business. Most of this code
1360 * package-file decompression. It works with both XD3_POSIX and XD3_STDIO file 1446 * originated in PRCS1, which did automatic package-file
1447 * decompression. It works with both XD3_POSIX and XD3_STDIO file
1361 * disciplines. 1448 * disciplines.
1362 * 1449 *
1363 * To automatically detect compressed inputs requires a child process to reconstruct the 1450 * To automatically detect compressed inputs requires a child process
1364 * input stream, which was advanced in order to detect compression, because it may not be 1451 * to reconstruct the input stream, which was advanced in order to
1365 * seekable. In other words, the main program reads part of the input stream, and if it 1452 * detect compression, because it may not be seekable. In other
1366 * detects a compressed input it then forks a pipe copier process, which copies the 1453 * words, the main program reads part of the input stream, and if it
1367 * first-read block out of the main-program's memory, then streams the remaining 1454 * detects a compressed input it then forks a pipe copier process,
1368 * compressed input into the input-decompression pipe. 1455 * which copies the first-read block out of the main-program's memory,
1456 * then streams the remaining compressed input into the
1457 * input-decompression pipe.
1369 */ 1458 */
1370 1459
1371#include <unistd.h> 1460#include <unistd.h>
@@ -1441,10 +1530,10 @@ main_external_compression_finish (void)
1441 return 0; 1530 return 0;
1442} 1531}
1443 1532
1444/* This runs as a forked process of main_input_decompress_setup() to copy input to the 1533/* This runs as a forked process of main_input_decompress_setup() to
1445 * decompression process. First, the available input is copied out of the existing 1534 * copy input to the decompression process. First, the available
1446 * buffer, then the buffer is reused to continue reading from the compressed input 1535 * input is copied out of the existing buffer, then the buffer is
1447 * file. */ 1536 * reused to continue reading from the compressed input file. */
1448static int 1537static int
1449main_pipe_copier (uint8_t *pipe_buf, 1538main_pipe_copier (uint8_t *pipe_buf,
1450 usize_t pipe_bufsize, 1539 usize_t pipe_bufsize,
@@ -1475,10 +1564,11 @@ main_pipe_copier (uint8_t *pipe_buf,
1475 return 0; 1564 return 0;
1476} 1565}
1477 1566
1478/* This function is called after we have read some amount of data from the input file and 1567/* This function is called after we have read some amount of data from
1479 * detected a compressed input. Here we start a decompression subprocess by forking 1568 * the input file and detected a compressed input. Here we start a
1480 * twice. The first process runs the decompression command, the second process copies 1569 * decompression subprocess by forking twice. The first process runs
1481 * data to the input of the first. */ 1570 * the decompression command, the second process copies data to the
1571 * input of the first. */
1482static int 1572static int
1483main_input_decompress_setup (const main_extcomp *decomp, 1573main_input_decompress_setup (const main_extcomp *decomp,
1484 main_file *ifile, 1574 main_file *ifile,
@@ -1594,17 +1684,20 @@ main_input_decompress_setup (const main_extcomp *decomp,
1594} 1684}
1595 1685
1596 1686
1597/* This routine is called when the first buffer of input data is read by the main program 1687/* This routine is called when the first buffer of input data is read
1598 * (unless input decompression is disabled by command-line option). If it recognizes the 1688 * by the main program (unless input decompression is disabled by
1599 * magic number of a known input type it invokes decompression. 1689 * command-line option). If it recognizes the magic number of a known
1690 * input type it invokes decompression.
1600 * 1691 *
1601 * Skips decompression if the decompression type or the file type is RD_NONEXTERNAL. 1692 * Skips decompression if the decompression type or the file type is
1693 * RD_NONEXTERNAL.
1602 * 1694 *
1603 * Behaves exactly like main_file_read, otherwise. 1695 * Behaves exactly like main_file_read, otherwise.
1604 * 1696 *
1605 * This function uses a separate buffer to read the first small block of input. If a 1697 * This function uses a separate buffer to read the first small block
1606 * compressed input is detected, the separate buffer is passed to the pipe copier. This 1698 * of input. If a compressed input is detected, the separate buffer
1607 * avoids using the same size buffer in both cases. */ 1699 * is passed to the pipe copier. This avoids using the same size
1700 * buffer in both cases. */
1608static int 1701static int
1609main_decompress_input_check (main_file *ifile, 1702main_decompress_input_check (main_file *ifile,
1610 uint8_t *input_buf, 1703 uint8_t *input_buf,
@@ -1626,8 +1719,8 @@ main_decompress_input_check (main_file *ifile,
1626 const main_extcomp *decomp = & extcomp_types[i]; 1719 const main_extcomp *decomp = & extcomp_types[i];
1627 1720
1628 if ((check_nread > decomp->magic_size) && 1721 if ((check_nread > decomp->magic_size) &&
1629 /* The following expr skips decompression if we are trying to read a VCDIFF 1722 /* The following expr skips decompression if we are trying
1630 * input and that is the magic number. */ 1723 * to read a VCDIFF input and that is the magic number. */
1631 !((decomp->flags & RD_NONEXTERNAL) && (ifile->flags & RD_NONEXTERNAL)) && 1724 !((decomp->flags & RD_NONEXTERNAL) && (ifile->flags & RD_NONEXTERNAL)) &&
1632 memcmp (check_buf, decomp->magic, decomp->magic_size) == 0) 1725 memcmp (check_buf, decomp->magic, decomp->magic_size) == 0)
1633 { 1726 {
@@ -1663,8 +1756,9 @@ main_decompress_input_check (main_file *ifile,
1663 return 0; 1756 return 0;
1664} 1757}
1665 1758
1666/* This is called when the source file needs to be decompressed. We fork/exec a 1759/* This is called when the source file needs to be decompressed. We
1667 * decompression command with the proper input and output to a temporary file. */ 1760 * fork/exec a decompression command with the proper input and output
1761 * to a temporary file. */
1668static int 1762static int
1669main_decompress_source (main_file *sfile, xd3_source *source) 1763main_decompress_source (main_file *sfile, xd3_source *source)
1670{ 1764{
@@ -1758,9 +1852,10 @@ main_decompress_source (main_file *sfile, xd3_source *source)
1758 return ret; 1852 return ret;
1759} 1853}
1760 1854
1761/* Initiate re-compression of the output stream. This is easier than input decompression 1855/* Initiate re-compression of the output stream. This is easier than
1762 * because we know beforehand that the stream will be compressed, whereas the input has 1856 * input decompression because we know beforehand that the stream will
1763 * already been read when we decide it should be decompressed. Thus, it only requires one 1857 * be compressed, whereas the input has already been read when we
1858 * decide it should be decompressed. Thus, it only requires one
1764 * subprocess and one pipe. */ 1859 * subprocess and one pipe. */
1765static int 1860static int
1766main_recompress_output (main_file *ofile) 1861main_recompress_output (main_file *ofile)
@@ -1803,8 +1898,8 @@ main_recompress_output (main_file *ofile)
1803 1898
1804 ext_subprocs[0] = recomp_id; 1899 ext_subprocs[0] = recomp_id;
1805 1900
1806 /* The parent closes both pipes after duplicating the output-fd for writing to the 1901 /* The parent closes both pipes after duplicating the output-fd for
1807 * compression pipe. */ 1902 * writing to the compression pipe. */
1808 output_fd = dup (pipefd[PIPE_WRITE_FD]); 1903 output_fd = dup (pipefd[PIPE_WRITE_FD]);
1809 1904
1810 if (output_fd < 0 || 1905 if (output_fd < 0 ||
@@ -1839,8 +1934,8 @@ main_recompress_output (main_file *ofile)
1839} 1934}
1840#endif /* EXTERNAL_COMPRESSION */ 1935#endif /* EXTERNAL_COMPRESSION */
1841 1936
1842/* Identify the compressor that was used based on its ident string, which is passed in the 1937/* Identify the compressor that was used based on its ident string,
1843 * application header. */ 1938 * which is passed in the application header. */
1844static const main_extcomp* 1939static const main_extcomp*
1845main_ident_compressor (const char *ident) 1940main_ident_compressor (const char *ident)
1846{ 1941{
@@ -1887,9 +1982,9 @@ main_get_compressor (const char *ident)
1887 } 1982 }
1888} 1983}
1889 1984
1890/****************************************************************************************** 1985/*********************************************************************
1891 APPLICATION HEADER 1986 APPLICATION HEADER
1892 ******************************************************************************************/ 1987 *******************************************************************/
1893 1988
1894#if XD3_ENCODER 1989#if XD3_ENCODER
1895static const char* 1990static const char*
@@ -1910,11 +2005,12 @@ main_apphead_string (const char* x)
1910static int 2005static int
1911main_set_appheader (xd3_stream *stream, main_file *input, main_file *sfile) 2006main_set_appheader (xd3_stream *stream, main_file *input, main_file *sfile)
1912{ 2007{
1913 /* The user may disable the application header. Once the appheader is set, this 2008 /* The user may disable the application header. Once the appheader
1914 * disables setting it again. */ 2009 * is set, this disables setting it again. */
1915 if (appheader_used || ! option_use_appheader) { return 0; } 2010 if (appheader_used || ! option_use_appheader) { return 0; }
1916 2011
1917 /* The user may specify the application header, otherwise format the default header. */ 2012 /* The user may specify the application header, otherwise format the
2013 default header. */
1918 if (option_appheader) 2014 if (option_appheader)
1919 { 2015 {
1920 appheader_used = option_appheader; 2016 appheader_used = option_appheader;
@@ -2010,14 +2106,15 @@ main_get_appheader_params (main_file *file, char **parsed, int output, const cha
2010} 2106}
2011 2107
2012static void 2108static void
2013main_get_appheader (xd3_stream *stream, main_file *ifile, main_file *output, main_file *sfile) 2109main_get_appheader (xd3_stream *stream, main_file *ifile,
2110 main_file *output, main_file *sfile)
2014{ 2111{
2015 uint8_t *apphead; 2112 uint8_t *apphead;
2016 usize_t appheadsz; 2113 usize_t appheadsz;
2017 int ret; 2114 int ret;
2018 2115
2019 /* The user may disable the application header. Once the appheader is set, this 2116 /* The user may disable the application header. Once the appheader
2020 * disables setting it again. */ 2117 * is set, this disables setting it again. */
2021 if (! option_use_appheader) { return; } 2118 if (! option_use_appheader) { return; }
2022 2119
2023 ret = xd3_get_appheader (stream, & apphead, & appheadsz); 2120 ret = xd3_get_appheader (stream, & apphead, & appheadsz);
@@ -2060,13 +2157,14 @@ main_get_appheader (xd3_stream *stream, main_file *ifile, main_file *output, mai
2060 return; 2157 return;
2061} 2158}
2062 2159
2063/****************************************************************************************** 2160/*********************************************************************
2064 Main I/O routines 2161 Main I/O routines
2065 ******************************************************************************************/ 2162 **********************************************************************/
2066 2163
2067/* This function acts like the above except it may also try to recognize a compressed 2164/* This function acts like the above except it may also try to
2068 * input when the first buffer of data is read. The EXTERNAL_COMPRESSION code is called 2165 * recognize a compressed input when the first buffer of data is read.
2069 * to search for magic numbers. */ 2166 * The EXTERNAL_COMPRESSION code is called to search for magic
2167 * numbers. */
2070static int 2168static int
2071main_read_primary_input (main_file *ifile, 2169main_read_primary_input (main_file *ifile,
2072 uint8_t *buf, 2170 uint8_t *buf,
@@ -2085,8 +2183,9 @@ main_read_primary_input (main_file *ifile,
2085 return main_file_read (ifile, buf, size, nread, "input read failed"); 2183 return main_file_read (ifile, buf, size, nread, "input read failed");
2086} 2184}
2087 2185
2088/* Open the main output file, sets a default file name, initiate recompression. This 2186/* Open the main output file, sets a default file name, initiate
2089 * function is expected to fprint any error messages. */ 2187 * recompression. This function is expected to fprint any error
2188 * messages. */
2090static int 2189static int
2091main_open_output (xd3_stream *stream, main_file *ofile) 2190main_open_output (xd3_stream *stream, main_file *ofile)
2092{ 2191{
@@ -2137,9 +2236,10 @@ main_open_output (xd3_stream *stream, main_file *ofile)
2137 return 0; 2236 return 0;
2138} 2237}
2139 2238
2140/* This is called at different times for encoding and decoding. The encoder calls it 2239/* This is called at different times for encoding and decoding. The
2141 * immediately, the decoder delays until the application header is received. 2240 * encoder calls it immediately, the decoder delays until the
2142 * Stream may be NULL, in which case xd3_set_source is not called. */ 2241 * application header is received. Stream may be NULL, in which case
2242 * xd3_set_source is not called. */
2143static int 2243static int
2144main_set_source (xd3_stream *stream, int cmd, main_file *sfile, xd3_source *source) 2244main_set_source (xd3_stream *stream, int cmd, main_file *sfile, xd3_source *source)
2145{ 2245{
@@ -2256,7 +2356,8 @@ main_set_source (xd3_stream *stream, int cmd, main_file *sfile, xd3_source *sour
2256 static char buf[32]; 2356 static char buf[32];
2257 2357
2258 XPR(NT "source %s winsize %s size %"Q"u\n", 2358 XPR(NT "source %s winsize %s size %"Q"u\n",
2259 sfile->filename, main_format_bcnt(option_srcwinsz, buf), source->size); 2359 sfile->filename, main_format_bcnt(option_srcwinsz, buf),
2360 source->size);
2260 } 2361 }
2261 2362
2262 if (option_verbose > 1) 2363 if (option_verbose > 1)
@@ -2315,17 +2416,18 @@ main_set_winsize (main_file *ifile) {
2315 } 2416 }
2316} 2417}
2317 2418
2318/****************************************************************************************** 2419/*******************************************************************
2319 Source routines 2420 Source routines
2320 ******************************************************************************************/ 2421 *******************************************************************/
2321 2422
2322/* This is the callback for reading a block of source. This function is blocking and it 2423/* This is the callback for reading a block of source. This function
2323 * implements a small LRU. 2424 * is blocking and it implements a small LRU.
2324 * 2425 *
2325 * Note that it is possible for main_input() to handle getblk requests in a non-blocking 2426 * Note that it is possible for main_input() to handle getblk requests
2326 * manner. If the callback is NULL then the caller of xd3_*_input() must handle the 2427 * in a non-blocking manner. If the callback is NULL then the caller
2327 * XD3_GETSRCBLK return value and fill the source in the same way. See xd3_getblk for 2428 * of xd3_*_input() must handle the XD3_GETSRCBLK return value and
2328 * details. To see an example of non-blocking getblk, see xdelta-test.h. */ 2429 * fill the source in the same way. See xd3_getblk for details. To
2430 * see an example of non-blocking getblk, see xdelta-test.h. */
2329static int 2431static int
2330main_getblk_func (xd3_stream *stream, 2432main_getblk_func (xd3_stream *stream,
2331 xd3_source *source, 2433 xd3_source *source,
@@ -2443,13 +2545,13 @@ main_getblk_func (xd3_stream *stream,
2443 return 0; 2545 return 0;
2444} 2546}
2445 2547
2446/****************************************************************************************** 2548/*********************************************************************
2447 Main routines 2549 Main routines
2448 ******************************************************************************************/ 2550 ********************************************************************/
2449 2551
2450/* This is a generic input function. It calls the xd3_encode_input or xd3_decode_input 2552/* This is a generic input function. It calls the xd3_encode_input or
2451 * functions and makes calls to the various input handling routines above, which 2553 * xd3_decode_input functions and makes calls to the various input
2452 * coordinate external decompression. 2554 * handling routines above, which coordinate external decompression.
2453 */ 2555 */
2454static int 2556static int
2455main_input (xd3_cmd cmd, 2557main_input (xd3_cmd cmd,
@@ -2474,15 +2576,13 @@ main_input (xd3_cmd cmd,
2474 int (*input_func) (xd3_stream*); 2576 int (*input_func) (xd3_stream*);
2475 int (*output_func) (xd3_stream*, main_file *); 2577 int (*output_func) (xd3_stream*, main_file *);
2476 2578
2579 memset (& stream, 0, sizeof (stream));
2477 memset (& source, 0, sizeof (source)); 2580 memset (& source, 0, sizeof (source));
2478 memset (& config, 0, sizeof (config)); 2581 memset (& config, 0, sizeof (config));
2479 2582
2480 config.alloc = main_alloc; 2583 config.alloc = main_alloc;
2481 config.freef = main_free1; 2584 config.freef = main_free1;
2482 // TODO: what about sec_xxxx.ngroups = 1? 2585
2483 config.sec_data.ngroups = 1;
2484 config.sec_addr.ngroups = 1;
2485 config.sec_inst.ngroups = 1;
2486 config.iopt_size = option_iopt_size; 2586 config.iopt_size = option_iopt_size;
2487 config.sprevsz = option_sprevsz; 2587 config.sprevsz = option_sprevsz;
2488 2588
@@ -2490,35 +2590,6 @@ main_input (xd3_cmd cmd,
2490 2590
2491 start_time = get_millisecs_now (); 2591 start_time = get_millisecs_now ();
2492 2592
2493 if (option_use_secondary)
2494 {
2495 /* The default secondary compressor is DJW, if it's compiled, being used, etc. */
2496 if (option_secondary == NULL)
2497 {
2498 if (SECONDARY_DJW) { stream_flags |= XD3_SEC_DJW; }
2499 }
2500 else
2501 {
2502 if (strcmp (option_secondary, "fgk") == 0 && SECONDARY_FGK)
2503 {
2504 stream_flags |= XD3_SEC_FGK;
2505 }
2506 else if (strcmp (option_secondary, "djw") == 0 && SECONDARY_DJW)
2507 {
2508 stream_flags |= XD3_SEC_DJW;
2509 }
2510 else if (strcmp (option_secondary, "none") == 0 && SECONDARY_DJW)
2511 {
2512 /* No secondary */
2513 }
2514 else
2515 {
2516 XPR(NT "unrecognized secondary compressor type: %s\n", option_secondary);
2517 return EXIT_FAILURE;
2518 }
2519 }
2520 }
2521
2522 if (option_use_checksum) { stream_flags |= XD3_ADLER32; } 2593 if (option_use_checksum) { stream_flags |= XD3_ADLER32; }
2523 2594
2524 /* main_input setup. */ 2595 /* main_input setup. */
@@ -2543,24 +2614,22 @@ main_input (xd3_cmd cmd,
2543 recode_stream = (xd3_stream*) main_malloc(sizeof(xd3_stream)); 2614 recode_stream = (xd3_stream*) main_malloc(sizeof(xd3_stream));
2544 2615
2545 recode_flags = (stream_flags & XD3_SEC_TYPE); 2616 recode_flags = (stream_flags & XD3_SEC_TYPE);
2546 xd3_init_config(&recode_config, recode_flags);
2547 2617
2548 recode_config.alloc = main_alloc; 2618 recode_config.alloc = main_alloc;
2549 recode_config.freef = main_free1; 2619 recode_config.freef = main_free1;
2550 2620
2551 // TODO: what about sec_xxxx.ngroups = 1? 2621 xd3_init_config(&recode_config, recode_flags);
2552 recode_config.sec_data.ngroups = 1;
2553 recode_config.sec_addr.ngroups = 1;
2554 recode_config.sec_inst.ngroups = 1;
2555 2622
2556 if ((ret = xd3_config_stream (recode_stream, &recode_config)) || 2623 if ((ret = main_set_secondary_flags (&recode_config)) ||
2624 (ret = xd3_config_stream (recode_stream, &recode_config)) ||
2557 (ret = xd3_encode_init_buffers (recode_stream))) 2625 (ret = xd3_encode_init_buffers (recode_stream)))
2558 { 2626 {
2559 XPR(NT XD3_LIB_ERRMSG (& stream, ret)); 2627
2628 XPR(NT XD3_LIB_ERRMSG (recode_stream, ret));
2560 return EXIT_FAILURE; 2629 return EXIT_FAILURE;
2561 } 2630 }
2562 2631
2563 // TODO: xd3_set_appheader (recode_stream) 2632 // TODO: main_set_appheader (recode_stream)
2564 2633
2565 ifile->flags |= RD_NONEXTERNAL; 2634 ifile->flags |= RD_NONEXTERNAL;
2566 input_func = xd3_decode_input; 2635 input_func = xd3_decode_input;
@@ -2644,9 +2713,10 @@ main_input (xd3_cmd cmd,
2644 2713
2645 if (IS_ENCODE (cmd)) 2714 if (IS_ENCODE (cmd))
2646 { 2715 {
2647 /* When encoding, open the source file, possibly decompress it. The decoder delays 2716 /* When encoding, open the source file, possibly decompress it.
2648 * this step until XD3_GOTHEADER. */ 2717 * The decoder delays this step until XD3_GOTHEADER. */
2649 if (sfile->filename != NULL && (ret = main_set_source (NULL, cmd, sfile, & source))) 2718 if (sfile->filename != NULL &&
2719 (ret = main_set_source (NULL, cmd, sfile, & source)))
2650 { 2720 {
2651 return EXIT_FAILURE; 2721 return EXIT_FAILURE;
2652 } 2722 }
@@ -2657,7 +2727,8 @@ main_input (xd3_cmd cmd,
2657 config.getblk = main_getblk_func; 2727 config.getblk = main_getblk_func;
2658 config.flags = stream_flags; 2728 config.flags = stream_flags;
2659 2729
2660 if ((ret = xd3_config_stream (& stream, & config))) 2730 if ((ret = main_set_secondary_flags (&config)) ||
2731 (ret = xd3_config_stream (& stream, & config)))
2661 { 2732 {
2662 XPR(NT XD3_LIB_ERRMSG (& stream, ret)); 2733 XPR(NT XD3_LIB_ERRMSG (& stream, ret));
2663 return EXIT_FAILURE; 2734 return EXIT_FAILURE;
@@ -2694,14 +2765,15 @@ main_input (xd3_cmd cmd,
2694 /* If we've reached EOF tell the stream to flush. */ 2765 /* If we've reached EOF tell the stream to flush. */
2695 if (nread < try_read) 2766 if (nread < try_read)
2696 { 2767 {
2697 stream_flags |= XD3_FLUSH; 2768 stream.flags |= XD3_FLUSH;
2698 xd3_set_flags (& stream, stream_flags);
2699 } 2769 }
2700 2770
2701#if XD3_ENCODER 2771#if XD3_ENCODER
2702 /* After the first main_read_primary_input completes, we know all the information 2772 /* After the first main_read_primary_input completes, we know
2703 * needed to encode the application header. */ 2773 * all the information needed to encode the application
2704 if (cmd == CMD_ENCODE && (ret = main_set_appheader (& stream, ifile, sfile))) 2774 * header. */
2775 if (cmd == CMD_ENCODE &&
2776 (ret = main_set_appheader (& stream, ifile, sfile)))
2705 { 2777 {
2706 return EXIT_FAILURE; 2778 return EXIT_FAILURE;
2707 } 2779 }
@@ -2776,7 +2848,6 @@ main_input (xd3_cmd cmd,
2776 case XD3_WINSTART: 2848 case XD3_WINSTART:
2777 { 2849 {
2778 /* e.g., set or unset XD3_SKIP_WINDOW. */ 2850 /* e.g., set or unset XD3_SKIP_WINDOW. */
2779 /* xd3_set_flags (& stream, stream_flags); */
2780 goto again; 2851 goto again;
2781 } 2852 }
2782 2853
diff --git a/xdelta3/xdelta3.c b/xdelta3/xdelta3.c
index 1487864..faf4dd7 100644
--- a/xdelta3/xdelta3.c
+++ b/xdelta3/xdelta3.c
@@ -2450,7 +2450,7 @@ xd3_config_stream(xd3_stream *stream,
2450 switch (stream->flags & XD3_SEC_TYPE) 2450 switch (stream->flags & XD3_SEC_TYPE)
2451 { 2451 {
2452 case 0: 2452 case 0:
2453 if (stream->flags & XD3_SEC_OTHER) 2453 if (stream->flags & XD3_SEC_NOALL)
2454 { 2454 {
2455 stream->msg = "XD3_SEC flags require a secondary compressor type"; 2455 stream->msg = "XD3_SEC flags require a secondary compressor type";
2456 return XD3_INTERNAL; 2456 return XD3_INTERNAL;
diff --git a/xdelta3/xdelta3.h b/xdelta3/xdelta3.h
index cd7a2a0..19f316d 100644
--- a/xdelta3/xdelta3.h
+++ b/xdelta3/xdelta3.h
@@ -341,7 +341,7 @@ typedef enum
341 XD3_SEC_NOADDR = (1 << 9), /* disable secondary compression of 341 XD3_SEC_NOADDR = (1 << 9), /* disable secondary compression of
342 the addr section. */ 342 the addr section. */
343 343
344 XD3_SEC_OTHER = (XD3_SEC_NODATA | XD3_SEC_NOINST | XD3_SEC_NOADDR), 344 XD3_SEC_NOALL = (XD3_SEC_NODATA | XD3_SEC_NOINST | XD3_SEC_NOADDR),
345 345
346 XD3_ADLER32 = (1 << 10), /* enable checksum computation in 346 XD3_ADLER32 = (1 << 10), /* enable checksum computation in
347 the encoder. */ 347 the encoder. */