summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xdelta3/Makefile2
-rw-r--r--xdelta3/xdelta3-decode.h4
-rw-r--r--xdelta3/xdelta3-main.h296
-rw-r--r--xdelta3/xdelta3.c8
-rw-r--r--xdelta3/xdelta3.h7
5 files changed, 174 insertions, 143 deletions
diff --git a/xdelta3/Makefile b/xdelta3/Makefile
index 6826253..5024b4f 100644
--- a/xdelta3/Makefile
+++ b/xdelta3/Makefile
@@ -170,7 +170,7 @@ xdelta3-32: $(SOURCES)
170xdelta3-debug2: $(SOURCES) 170xdelta3-debug2: $(SOURCES)
171 $(CC) -g $(CFLAGS) \ 171 $(CC) -g $(CFLAGS) \
172 xdelta3.c -o xdelta3-debug2 \ 172 xdelta3.c -o xdelta3-debug2 \
173 -DXD3_DEBUG=2 \ 173 -DXD3_DEBUG=3 \
174 -DXD3_MAIN=1 \ 174 -DXD3_MAIN=1 \
175 -DXD3_POSIX=1 \ 175 -DXD3_POSIX=1 \
176 -DXD3_USE_LARGEFILE64=1 \ 176 -DXD3_USE_LARGEFILE64=1 \
diff --git a/xdelta3/xdelta3-decode.h b/xdelta3/xdelta3-decode.h
index cc0a0e7..cc33d5a 100644
--- a/xdelta3/xdelta3-decode.h
+++ b/xdelta3/xdelta3-decode.h
@@ -631,9 +631,7 @@ xd3_decode_sections (xd3_stream *stream)
631 631
632 /* OPT: A possible optimization is to avoid allocating memory in 632 /* OPT: A possible optimization is to avoid allocating memory in
633 * decode_setup_buffers and to avoid a large memcpy when the window 633 * decode_setup_buffers and to avoid a large memcpy when the window
634 * consists of a single VCD_SOURCE copy instruction. The only 634 * consists of a single VCD_SOURCE copy instruction. */
635 * potential problem is if the following window is a VCD_TARGET,
636 * then you need to remember... */
637 if ((ret = xd3_decode_setup_buffers (stream))) { return ret; } 635 if ((ret = xd3_decode_setup_buffers (stream))) { return ret; }
638 636
639 return 0; 637 return 0;
diff --git a/xdelta3/xdelta3-main.h b/xdelta3/xdelta3-main.h
index 6ea6c68..df55ade 100644
--- a/xdelta3/xdelta3-main.h
+++ b/xdelta3/xdelta3-main.h
@@ -224,8 +224,10 @@ struct _main_file
224 xoff_t nread; /* for input position */ 224 xoff_t nread; /* for input position */
225 xoff_t nwrite; /* for output position */ 225 xoff_t nwrite; /* for output position */
226 uint8_t *snprintf_buf; /* internal snprintf() use */ 226 uint8_t *snprintf_buf; /* internal snprintf() use */
227 xoff_t source_position; /* for avoiding seek in getblk_func */ 227 int size_known; /* Set by main_set_souze */
228 xoff_t source_position; /* for avoiding seek in getblk_func */
228 int seek_failed; /* after seek fails once */ 229 int seek_failed; /* after seek fails once */
230 const char *decode_cmdname; /* for verbose output */
229}; 231};
230 232
231/* Various strings and magic values used to detect and call external 233/* Various strings and magic values used to detect and call external
@@ -255,13 +257,14 @@ struct _main_blklru_list
255 257
256struct _main_blklru 258struct _main_blklru
257{ 259{
258 uint8_t *blk; 260 uint8_t *blk;
259 xoff_t blkno; 261 xoff_t blkno;
260 usize_t size; 262 usize_t size;
261 main_blklru_list link; 263 main_blklru_list link;
262}; 264};
263 265
264#define LRU_SIZE 32U 266#define MAX_LRU_SIZE 32U
267#define MIN_LRU_SIZE 1U
265#define XD3_MINSRCWINSZ XD3_ALLOCSIZE 268#define XD3_MINSRCWINSZ XD3_ALLOCSIZE
266 269
267/* ... represented as a list (no cache index). */ 270/* ... represented as a list (no cache index). */
@@ -478,7 +481,7 @@ main_malloc1 (usize_t size)
478{ 481{
479 void* r = malloc (size); 482 void* r = malloc (size);
480 if (r == NULL) { XPR(NT "malloc: %s\n", xd3_mainerror (ENOMEM)); } 483 if (r == NULL) { XPR(NT "malloc: %s\n", xd3_mainerror (ENOMEM)); }
481 else if (option_verbose > 3) { XPR(NT "malloc: %u: %p\n", size, r); } 484 else if (option_verbose > 4) { XPR(NT "malloc: %u: %p\n", size, r); }
482 return r; 485 return r;
483} 486}
484 487
@@ -501,7 +504,7 @@ main_alloc (void *opaque,
501static void 504static void
502main_free1 (void *opaque, void *ptr) 505main_free1 (void *opaque, void *ptr)
503{ 506{
504 if (option_verbose > 3) { XPR(NT "free: %p\n", ptr); } 507 if (option_verbose > 4) { XPR(NT "free: %p\n", ptr); }
505 free (ptr); 508 free (ptr);
506} 509}
507 510
@@ -1030,7 +1033,7 @@ main_file_read (main_file *ifile,
1030 } 1033 }
1031 else 1034 else
1032 { 1035 {
1033 if (option_verbose > 3) { XPR(NT "main read: %s: %u\n", 1036 if (option_verbose > 3) { XPR(NT "read %s: %u bytes\n",
1034 ifile->filename, (*nread)); } 1037 ifile->filename, (*nread)); }
1035 ifile->nread += (*nread); 1038 ifile->nread += (*nread);
1036 } 1039 }
@@ -1071,7 +1074,7 @@ main_file_write (main_file *ofile, uint8_t *buf, usize_t size, const char *msg)
1071 } 1074 }
1072 else 1075 else
1073 { 1076 {
1074 if (option_verbose > 3) { XPR(NT "main write: %s: %u\n", 1077 if (option_verbose > 4) { XPR(NT "write %s: %u bytes\n",
1075 ofile->filename, size); } 1078 ofile->filename, size); }
1076 ofile->nwrite += size; 1079 ofile->nwrite += size;
1077 } 1080 }
@@ -1139,32 +1142,6 @@ main_write_output (xd3_stream* stream, main_file *ofile)
1139 return 0; 1142 return 0;
1140} 1143}
1141 1144
1142/* Called when the stream transitions from unknown status to
1143 * possibly/definitely non-seekable. */
1144static void
1145main_internal_do_not_lru ()
1146{
1147 usize_t i;
1148
1149 if (do_not_lru)
1150 {
1151 /* Already set */
1152 return;
1153 }
1154
1155 do_not_lru = 1;
1156
1157 /* It's possible that we've already ejected in a non-LRU fashion,
1158 * report on that. */
1159 for (i = 0; i < lru_size; i += 1)
1160 {
1161 if (lru[i].blkno == (xoff_t) -1)
1162 {
1163 continue;
1164 }
1165 }
1166}
1167
1168static int 1145static int
1169main_set_secondary_flags (xd3_config *config) 1146main_set_secondary_flags (xd3_config *config)
1170{ 1147{
@@ -2347,10 +2324,10 @@ main_input_decompress_setup (const main_extcomp *decomp,
2347 * is passed to the pipe copier. This avoids using the same size 2324 * is passed to the pipe copier. This avoids using the same size
2348 * buffer in both cases. */ 2325 * buffer in both cases. */
2349static int 2326static int
2350main_secondary_decompress_check (main_file *ifile, 2327main_secondary_decompress_check (main_file *file,
2351 uint8_t *input_buf, 2328 uint8_t *input_buf,
2352 usize_t input_size, 2329 usize_t input_size,
2353 usize_t *nread) 2330 usize_t *nread)
2354{ 2331{
2355 int ret; 2332 int ret;
2356 usize_t i; 2333 usize_t i;
@@ -2358,7 +2335,7 @@ main_secondary_decompress_check (main_file *ifile,
2358 usize_t check_nread; 2335 usize_t check_nread;
2359 uint8_t check_buf[XD3_ALLOCSIZE]; /* TODO: stack limit */ 2336 uint8_t check_buf[XD3_ALLOCSIZE]; /* TODO: stack limit */
2360 2337
2361 if ((ret = main_file_read (ifile, check_buf, 2338 if ((ret = main_file_read (file, check_buf,
2362 try_read, 2339 try_read,
2363 & check_nread, "input read failed"))) 2340 & check_nread, "input read failed")))
2364 { 2341 {
@@ -2373,20 +2350,11 @@ main_secondary_decompress_check (main_file *ifile,
2373 /* The following expr skips decompression if we are trying 2350 /* The following expr skips decompression if we are trying
2374 * to read a VCDIFF input and that is the magic number. */ 2351 * to read a VCDIFF input and that is the magic number. */
2375 !((decomp->flags & RD_NONEXTERNAL) && 2352 !((decomp->flags & RD_NONEXTERNAL) &&
2376 (ifile->flags & RD_NONEXTERNAL)) && 2353 (file->flags & RD_NONEXTERNAL)) &&
2377 memcmp (check_buf, decomp->magic, decomp->magic_size) == 0) 2354 memcmp (check_buf, decomp->magic, decomp->magic_size) == 0)
2378 { 2355 {
2379 if (! option_quiet) 2356 file->size_known = 0;
2380 { 2357 return main_input_decompress_setup (decomp, file,
2381 XPR(NT "%s | %s %s\n",
2382 ifile->filename,
2383 decomp->decomp_cmdname,
2384 decomp->decomp_options);
2385 }
2386
2387 main_internal_do_not_lru ();
2388
2389 return main_input_decompress_setup (decomp, ifile,
2390 input_buf, input_size, 2358 input_buf, input_size,
2391 check_buf, XD3_ALLOCSIZE, 2359 check_buf, XD3_ALLOCSIZE,
2392 check_nread, nread); 2360 check_nread, nread);
@@ -2398,7 +2366,7 @@ main_secondary_decompress_check (main_file *ifile,
2398 2366
2399 if (check_nread == try_read) 2367 if (check_nread == try_read)
2400 { 2368 {
2401 ret = main_file_read (ifile, 2369 ret = main_file_read (file,
2402 input_buf + try_read, 2370 input_buf + try_read,
2403 input_size - try_read, 2371 input_size - try_read,
2404 nread, 2372 nread,
@@ -2799,7 +2767,7 @@ main_open_output (xd3_stream *stream, main_file *ofile)
2799 return ret; 2767 return ret;
2800 } 2768 }
2801 2769
2802 if (option_verbose > 1) { XPR(NT "output file: %s\n", ofile->filename); } 2770 if (option_verbose > 1) { XPR(NT "output %s\n", ofile->filename); }
2803 } 2771 }
2804 2772
2805#if EXTERNAL_COMPRESSION 2773#if EXTERNAL_COMPRESSION
@@ -2833,153 +2801,207 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd,
2833{ 2801{
2834 int ret = 0; 2802 int ret = 0;
2835 usize_t i; 2803 usize_t i;
2836 uint8_t *tmp_buf = NULL; 2804 usize_t blksize;
2837 xoff_t source_size = 0; 2805 xoff_t source_size = 0;
2838 int source_size_known = 0; 2806 main_blklru block0;
2807
2808 XD3_ASSERT (lru == NULL);
2809 XD3_ASSERT (stream->src == NULL);
2810 XD3_ASSERT (option_srcwinsz >= XD3_MINSRCWINSZ);
2839 2811
2840 main_blklru_list_init (& lru_list); 2812 main_blklru_list_init (& lru_list);
2841 main_blklru_list_init (& lru_free); 2813 main_blklru_list_init (& lru_free);
2842 2814
2843 /* Open it, check for seekability, set required xd3_source fields. */
2844 if (allow_fake_source) 2815 if (allow_fake_source)
2845 { 2816 {
2846 sfile->mode = XO_READ; 2817 sfile->mode = XO_READ;
2847 sfile->realname = sfile->filename; 2818 sfile->realname = sfile->filename;
2848 sfile->nread = 0; 2819 sfile->nread = 0;
2849 source_size_known = 1;
2850 } 2820 }
2851 else 2821 else
2852 { 2822 {
2853 int stat_val;
2854
2855 if ((ret = main_file_open (sfile, sfile->filename, XO_READ))) 2823 if ((ret = main_file_open (sfile, sfile->filename, XO_READ)))
2856 { 2824 {
2857 goto error; 2825 return ret;
2858 } 2826 }
2859 2827
2860 stat_val = main_file_stat (sfile, &source_size); 2828 sfile->size_known = (main_file_stat (sfile, &source_size) == 0);
2861 if (stat_val == 0)
2862 {
2863 source_size_known = 1;
2864 }
2865 else
2866 {
2867 source_size_known = 0;
2868 }
2869 } 2829 }
2870 2830
2871 if (source_size_known && source_size < option_srcwinsz) 2831 if (sfile->size_known && source_size < option_srcwinsz)
2872 { 2832 {
2873 /* Reduce sizes to actual source size, read whole file. */ 2833 blksize = (source_size / MIN_LRU_SIZE);
2874 option_srcwinsz = source_size;
2875 source->blksize = source_size;
2876 } 2834 }
2877 else 2835 else
2878 { 2836 {
2879 option_srcwinsz = max(option_srcwinsz, XD3_MINSRCWINSZ); 2837 blksize = (option_srcwinsz / MAX_LRU_SIZE);
2880 source->blksize = (option_srcwinsz / LRU_SIZE);
2881 } 2838 }
2882 2839
2883 if (source_size_known) 2840 blksize = max (blksize, XD3_MINSRCWINSZ);
2884 { 2841
2885 IF_DEBUG2 (DP(RINT "[main_set_source] %s size %"Q"u\n", 2842 /* The API requires power-of-two blocksize, */
2886 sfile->filename, source_size)); 2843 blksize = xd3_pow2_roundup (blksize);
2887 } 2844
2888 else 2845 memset (&block0, 0, sizeof (block0));
2846 block0.blkno = (xoff_t) -1;
2847
2848 /* Allocate the first block. Even if the size is known at this
2849 * point, we do not lower it because decompression may happen. */
2850 if ((block0.blk = (uint8_t*) main_malloc (blksize)) == NULL)
2889 { 2851 {
2890 IF_DEBUG2 (DP(RINT "[main_set_source] %s size not known\n", 2852 ret = ENOMEM;
2891 sfile->filename, source_size)); 2853 return ret;
2892 main_internal_do_not_lru ();
2893 } 2854 }
2894 2855
2856 source->blksize = blksize;
2895 source->name = sfile->filename; 2857 source->name = sfile->filename;
2896 source->ioh = sfile; 2858 source->ioh = sfile;
2897 source->curblkno = 0; 2859 source->curblkno = (xoff_t) -1;
2898 source->curblk = NULL; 2860 source->curblk = NULL;
2899 2861
2900 /* DO NOT call xd3_set_source_and_size because of potential 2862 /* We have to read the first block into the cache now, because
2901 * secondary compression. */ 2863 * size_known can still change (due to secondary
2902 ret = xd3_set_source (stream, source); 2864 * decompression). Calls main_decompress_input_check() via
2903 if (ret) 2865 * main_read_primary_input(). */
2866 lru_size = 1;
2867 lru = &block0;
2868 main_blklru_list_push_back (& lru_free, & lru[0]);
2869 ret = main_getblk_func (stream, source, 0);
2870 main_blklru_list_remove (& lru[0]);
2871 lru = NULL;
2872
2873 if (ret != 0)
2904 { 2874 {
2905 XPR(NT XD3_LIB_ERRMSG (stream, ret)); 2875 main_free (block0.blk);
2906 goto error; 2876
2877 XPR(NT "error reading source %s: %s\n",
2878 sfile->filename,
2879 xd3_mainerror (ret));
2880
2881 return ret;
2907 } 2882 }
2908 XD3_ASSERT (stream->src == source);
2909 2883
2910 lru_size = (option_srcwinsz + source->blksize - 1) / source->blksize; 2884 source->onblk = block0.size;
2911 lru_size = max(lru_size, 1U);
2912 IF_DEBUG1 (DP(RINT "[lru_size] == %d\n", lru_size));
2913 option_srcwinsz = lru_size * source->blksize;
2914 2885
2915 if (option_verbose) 2886 /* If the file is smaller than a block, size is known. */
2887 if (!sfile->size_known && source->onblk < blksize)
2916 { 2888 {
2917 static char winszbuf[32]; 2889 source_size = source->onblk;
2918 static char srcszbuf[32]; 2890 sfile->size_known = 1;
2919 static char blkszbuf[32]; 2891 }
2920 if (source_size_known)
2921 {
2922 sprintf(srcszbuf, " size %"Q"u", source_size);
2923 }
2924 else
2925 {
2926 strcpy(srcszbuf, " size not known");
2927 }
2928 2892
2929 XPR(NT "source %s winsize %s blksize %s%s\n", 2893 /* source->size_known is finally determined. we update lru_size
2930 sfile->filename, 2894 * accordingly, and modify option_srcwinsz, which will be passed via
2931 main_format_bcnt(option_srcwinsz, winszbuf), 2895 * xd3_config. */
2932 main_format_bcnt(source->blksize, blkszbuf), 2896 if (sfile->size_known && source_size <= option_srcwinsz)
2933 srcszbuf); 2897 {
2898 lru_size = (source_size + blksize - 1) / blksize;
2899 option_srcwinsz = lru_size * blksize;
2900 }
2901 else
2902 {
2903 lru_size = (option_srcwinsz + blksize - 1) / blksize;
2904 option_srcwinsz = lru_size * blksize;
2934 } 2905 }
2935 2906
2936 XD3_ASSERT (lru == NULL); 2907 XD3_ASSERT (lru_size >= 1);
2937 2908
2938 if ((lru = (main_blklru*) 2909 if ((lru = (main_blklru*) main_malloc (lru_size * sizeof (main_blklru))) == NULL)
2939 main_malloc (sizeof (main_blklru) * lru_size)) == NULL)
2940 { 2910 {
2941 ret = ENOMEM; 2911 ret = ENOMEM;
2942 goto error; 2912 return ret;
2943 } 2913 }
2944 2914
2945 for (i = 0; i < lru_size; i += 1) 2915 lru[0].blk = block0.blk;
2916 lru[0].blkno = 0;
2917 lru[0].size = source->onblk;
2918
2919 if (! sfile->size_known)
2920 {
2921 do_not_lru = 1;
2922 }
2923 else if (! do_not_lru)
2924 {
2925 main_blklru_list_push_back (& lru_list, & lru[0]);
2926 }
2927
2928 for (i = 1; i < lru_size; i += 1)
2946 { 2929 {
2947 lru[i].blkno = (xoff_t) -1; 2930 lru[i].blkno = (xoff_t) -1;
2948 2931
2949 if ((lru[i].blk = (uint8_t*) main_malloc (source->blksize)) == NULL) 2932 if ((lru[i].blk = (uint8_t*) main_malloc (source->blksize)) == NULL)
2950 { 2933 {
2951 ret = ENOMEM; 2934 ret = ENOMEM;
2952 goto error; 2935 return ret;
2953 } 2936 }
2954 2937
2955 if (! do_not_lru) 2938 if (do_not_lru == 0)
2956 { 2939 {
2957 main_blklru_list_push_back (& lru_free, & lru[i]); 2940 main_blklru_list_push_back (& lru_free, & lru[i]);
2958 } 2941 }
2959 } 2942 }
2960 2943
2961 if ((ret = main_getblk_func (stream, source, 0))) 2944 if (sfile->size_known)
2945 {
2946 ret = xd3_set_source_and_size (stream, source, source_size);
2947 }
2948 else
2949 {
2950 ret = xd3_set_source (stream, source);
2951 }
2952
2953 if (ret)
2962 { 2954 {
2963 XPR(NT "error reading first block: %s\n", xd3_mainerror (ret)); 2955 XPR(NT XD3_LIB_ERRMSG (stream, ret));
2964 return ret; 2956 return ret;
2965 } 2957 }
2966 2958
2967 return 0; 2959 XD3_ASSERT (stream->src == source);
2960 XD3_ASSERT (source->blksize == blksize);
2968 2961
2969 error: 2962 if (option_verbose)
2970 IF_DEBUG2 (DP(RINT "[main_set_source] error %s\n", xd3_strerror (ret)));
2971 if (tmp_buf != NULL)
2972 { 2963 {
2973 main_free (tmp_buf); 2964 static char srcszbuf[32];
2965 static char srccntbuf[32];
2966 static char winszbuf[32];
2967 static char blkszbuf[32];
2968 static char nbufs[32];
2969
2970 if (sfile->size_known)
2971 {
2972 sprintf (srcszbuf, "source size %s [%"Q"u]",
2973 main_format_bcnt (source_size, srccntbuf),
2974 source_size);
2975 }
2976 else
2977 {
2978 strcpy(srcszbuf, "source size unknown");
2979 }
2980
2981 nbufs[0] = 0;
2982
2983 if (option_verbose > 1)
2984 {
2985 sprintf(nbufs, " #bufs %u", lru_size);
2986 }
2987
2988 XPR(NT "source %s %s blksize %s window %s%s%s\n",
2989 sfile->filename,
2990 srcszbuf,
2991 main_format_bcnt (blksize, blkszbuf),
2992 main_format_bcnt (option_srcwinsz, winszbuf),
2993 nbufs,
2994 do_not_lru ? " (FIFO)" : "");
2974 } 2995 }
2975 2996
2976 return ret; 2997 return 0;
2977} 2998}
2978 2999
2979static usize_t 3000static usize_t
2980main_get_winsize (main_file *ifile) { 3001main_get_winsize (main_file *ifile) {
2981 xoff_t file_size = 0; 3002 xoff_t file_size = 0;
2982 usize_t size = option_winsize; 3003 usize_t size = option_winsize;
3004 static char iszbuf[32];
2983 3005
2984 if (main_file_stat (ifile, &file_size) == 0) 3006 if (main_file_stat (ifile, &file_size) == 0)
2985 { 3007 {
@@ -2990,7 +3012,9 @@ main_get_winsize (main_file *ifile) {
2990 3012
2991 if (option_verbose > 1) 3013 if (option_verbose > 1)
2992 { 3014 {
2993 XPR(NT "input window size: %u\n", size); 3015 XPR(NT "input %s window size %s\n",
3016 ifile->filename,
3017 main_format_bcnt (size, iszbuf));
2994 } 3018 }
2995 3019
2996 return size; 3020 return size;
@@ -3368,7 +3392,7 @@ main_input (xd3_cmd cmd,
3368 } 3392 }
3369 else 3393 else
3370 { 3394 {
3371 if (option_verbose > 1) 3395 if (option_verbose > 2)
3372 { 3396 {
3373 XPR(NT "compression level: %d\n", option_level); 3397 XPR(NT "compression level: %d\n", option_level);
3374 } 3398 }
@@ -3590,13 +3614,15 @@ main_input (xd3_cmd cmd,
3590 XD3_ASSERT (stream.src != NULL); 3614 XD3_ASSERT (stream.src != NULL);
3591 } 3615 }
3592 3616
3593 /* Limited i-buffer size affects source copies */ 3617 /* Limited i-buffer size affects source copies
3594 if (option_verbose > 1 && 3618 * when the sourcewin is decided early. */
3619 if (option_verbose &&
3620 stream.srcwin_decided_early &&
3595 stream.i_slots_used > stream.iopt_size) 3621 stream.i_slots_used > stream.iopt_size)
3596 { 3622 {
3597 XPR(NT "warning: input position %"Q"u overflowed " 3623 XPR(NT "warning: input position %"Q"u overflowed "
3598 "instruction buffer, needed %u (vs. %u), " 3624 "instruction buffer, needed %u (vs. %u), "
3599 "consider raising -I\n", 3625 "consider changing -I\n",
3600 stream.current_window * winsize, 3626 stream.current_window * winsize,
3601 stream.i_slots_used, stream.iopt_size); 3627 stream.i_slots_used, stream.iopt_size);
3602 } 3628 }
diff --git a/xdelta3/xdelta3.c b/xdelta3/xdelta3.c
index 100f058..2231fe1 100644
--- a/xdelta3/xdelta3.c
+++ b/xdelta3/xdelta3.c
@@ -2486,7 +2486,6 @@ inline
2486xoff_t xd3_source_eof(const xd3_source *src) 2486xoff_t xd3_source_eof(const xd3_source *src)
2487{ 2487{
2488 xoff_t r = (src->blksize * src->max_blkno) + (xoff_t)src->onlastblk; 2488 xoff_t r = (src->blksize * src->max_blkno) + (xoff_t)src->onlastblk;
2489 IF_DEBUG2 (DP(RINT "[src] source_size == %"Q"u\n", r));
2490 return r; 2489 return r;
2491} 2490}
2492 2491
@@ -2496,7 +2495,6 @@ usize_t xd3_bytes_on_srcblk (xd3_source *src, xoff_t blkno)
2496 usize_t r = (blkno == src->max_blkno ? 2495 usize_t r = (blkno == src->max_blkno ?
2497 src->onlastblk : 2496 src->onlastblk :
2498 src->blksize); 2497 src->blksize);
2499 IF_DEBUG2 (DP(RINT "[src] source last block size %u\n", r));
2500 return r; 2498 return r;
2501} 2499}
2502 2500
@@ -2773,6 +2771,11 @@ xd3_iopt_finish_encoding (xd3_stream *stream, xd3_rinst *inst)
2773 { 2771 {
2774 if ((ret = xd3_srcwin_setup (stream))) { return ret; } 2772 if ((ret = xd3_srcwin_setup (stream))) { return ret; }
2775 } 2773 }
2774 else
2775 {
2776 stream->srcwin_decided_early = (!stream->src->eof_known ||
2777 (stream->srcwin_cksum_pos < xd3_source_eof (stream->src)));
2778 }
2776 2779
2777 /* xtra field indicates the copy is from the source */ 2780 /* xtra field indicates the copy is from the source */
2778 if (inst->xtra) 2781 if (inst->xtra)
@@ -3688,6 +3691,7 @@ xd3_encode_reset (xd3_stream *stream)
3688 stream->src->srcbase = 0; 3691 stream->src->srcbase = 0;
3689 stream->src->srclen = 0; 3692 stream->src->srclen = 0;
3690 stream->srcwin_decided = 0; 3693 stream->srcwin_decided = 0;
3694 stream->srcwin_decided_early = 0;
3691 stream->match_minaddr = 0; 3695 stream->match_minaddr = 0;
3692 stream->match_maxaddr = 0; 3696 stream->match_maxaddr = 0;
3693 stream->taroff = 0; 3697 stream->taroff = 0;
diff --git a/xdelta3/xdelta3.h b/xdelta3/xdelta3.h
index 6258957..5b99a72 100644
--- a/xdelta3/xdelta3.h
+++ b/xdelta3/xdelta3.h
@@ -834,9 +834,12 @@ struct _xd3_stream
834 834
835 // SRCWIN 835 // SRCWIN
836 // these variables plus srcwin_maxsz above (set by config) 836 // these variables plus srcwin_maxsz above (set by config)
837 int srcwin_decided; /* boolean: true if the 837 int srcwin_decided; /* boolean: true if srclen and
838 srclen,srcbase have been 838 srcbase have been
839 decided. */ 839 decided. */
840 int srcwin_decided_early; /* boolean: true if srclen
841 and srcbase were
842 decided early. */
840 xoff_t srcwin_cksum_pos; /* Source checksum position */ 843 xoff_t srcwin_cksum_pos; /* Source checksum position */
841 844
842 // MATCH 845 // MATCH