summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh MacDonald <josh.macdonald@gmail.com>2016-02-26 21:44:41 -0800
committerJosh MacDonald <josh.macdonald@gmail.com>2016-02-26 21:44:41 -0800
commit275903904f716ff12d56f8acdc27416d29cf27f9 (patch)
treef10a20d74922ebca7a7109dc93ad8d2be561782b
parent4b4aed71a959fe11852e45242bb6524be85d3709 (diff)
parentd594fbe514e2a381541a510fe01041e546f56a67 (diff)
Merge branch 'release3_0' into release3_1
Removal of xdelta1.
-rw-r--r--xdelta1/AUTHORS3
-rw-r--r--xdelta1/COPYING339
-rw-r--r--xdelta1/INSTALL217
-rw-r--r--xdelta1/Makefile.am50
-rw-r--r--xdelta1/NEWS217
-rw-r--r--xdelta1/README180
-rw-r--r--xdelta1/autogen.sh59
-rw-r--r--xdelta1/configure.in91
-rw-r--r--xdelta1/contrib/build_hpux21
-rw-r--r--xdelta1/djgpp/Makefile.am2
-rw-r--r--xdelta1/djgpp/announce.djg45
-rw-r--r--xdelta1/djgpp/readme.djg136
-rw-r--r--xdelta1/doc/Makefile.am3
-rw-r--r--xdelta1/doc/xdelta.1201
-rw-r--r--xdelta1/doc/xdelta.cat138
-rw-r--r--xdelta1/getopt.c749
-rw-r--r--xdelta1/getopt.h129
-rw-r--r--xdelta1/getopt1.c180
-rw-r--r--xdelta1/libedsio/Makefile.am52
-rw-r--r--xdelta1/libedsio/base64.c525
-rw-r--r--xdelta1/libedsio/default.c343
-rw-r--r--xdelta1/libedsio/edsio-comp.in46
-rw-r--r--xdelta1/libedsio/edsio.c1610
-rw-r--r--xdelta1/libedsio/edsio.el1864
-rw-r--r--xdelta1/libedsio/edsio.h531
-rw-r--r--xdelta1/libedsio/edsio.ser129
-rw-r--r--xdelta1/libedsio/edsiotest.c213
-rw-r--r--xdelta1/libedsio/fh.c167
-rw-r--r--xdelta1/libedsio/generic.c252
-rw-r--r--xdelta1/libedsio/library.c121
-rw-r--r--xdelta1/libedsio/maketime.c391
-rw-r--r--xdelta1/libedsio/maketime.h39
-rw-r--r--xdelta1/libedsio/md5c.c298
-rw-r--r--xdelta1/libedsio/partime.c742
-rw-r--r--xdelta1/libedsio/partime.h67
-rw-r--r--xdelta1/libedsio/sha.c239
-rw-r--r--xdelta1/libedsio/simple.c179
-rw-r--r--xdelta1/runtest48
-rw-r--r--xdelta1/test/Makefile.am13
-rw-r--r--xdelta1/test/README.test9
-rw-r--r--xdelta1/test/xdeltatest.c681
-rw-r--r--xdelta1/xd.ser138
-rw-r--r--xdelta1/xdapply.c91
-rw-r--r--xdelta1/xdelta-0.13.README311
-rw-r--r--xdelta1/xdelta-1.1.2.tar.gzbin290553 -> 0 bytes
-rw-r--r--xdelta1/xdelta-1.1.3.tar.gzbin242101 -> 0 bytes
-rw-r--r--xdelta1/xdelta-config.in115
-rw-r--r--xdelta1/xdelta.c1541
-rw-r--r--xdelta1/xdelta.h195
-rw-r--r--xdelta1/xdelta.m4183
-rw-r--r--xdelta1/xdelta.magic9
-rw-r--r--xdelta1/xdelta.prj123
-rw-r--r--xdelta1/xdeltapriv.h131
-rw-r--r--xdelta1/xdmain.c1965
-rw-r--r--xdelta1/xdrsync.c443
55 files changed, 0 insertions, 16564 deletions
diff --git a/xdelta1/AUTHORS b/xdelta1/AUTHORS
deleted file mode 100644
index 562970c..0000000
--- a/xdelta1/AUTHORS
+++ /dev/null
@@ -1,3 +0,0 @@
1The author is Joshua MacDonald, <jmacd@cs.berkeley.edu>. The Rsync
2algorithm, which inspired the core delta algorithm, is due to Andrew
3Tridgell and Paul Mackerras.
diff --git a/xdelta1/COPYING b/xdelta1/COPYING
deleted file mode 100644
index a43ea21..0000000
--- a/xdelta1/COPYING
+++ /dev/null
@@ -1,339 +0,0 @@
1 GNU GENERAL PUBLIC LICENSE
2 Version 2, June 1991
3
4 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5 675 Mass Ave, Cambridge, MA 02139, USA
6 Everyone is permitted to copy and distribute verbatim copies
7 of this license document, but changing it is not allowed.
8
9 Preamble
10
11 The licenses for most software are designed to take away your
12freedom to share and change it. By contrast, the GNU General Public
13License is intended to guarantee your freedom to share and change free
14software--to make sure the software is free for all its users. This
15General Public License applies to most of the Free Software
16Foundation's software and to any other program whose authors commit to
17using it. (Some other Free Software Foundation software is covered by
18the GNU Library General Public License instead.) You can apply it to
19your programs, too.
20
21 When we speak of free software, we are referring to freedom, not
22price. Our General Public Licenses are designed to make sure that you
23have the freedom to distribute copies of free software (and charge for
24this service if you wish), that you receive source code or can get it
25if you want it, that you can change the software or use pieces of it
26in new free programs; and that you know you can do these things.
27
28 To protect your rights, we need to make restrictions that forbid
29anyone to deny you these rights or to ask you to surrender the rights.
30These restrictions translate to certain responsibilities for you if you
31distribute copies of the software, or if you modify it.
32
33 For example, if you distribute copies of such a program, whether
34gratis or for a fee, you must give the recipients all the rights that
35you have. You must make sure that they, too, receive or can get the
36source code. And you must show them these terms so they know their
37rights.
38
39 We protect your rights with two steps: (1) copyright the software, and
40(2) offer you this license which gives you legal permission to copy,
41distribute and/or modify the software.
42
43 Also, for each author's protection and ours, we want to make certain
44that everyone understands that there is no warranty for this free
45software. If the software is modified by someone else and passed on, we
46want its recipients to know that what they have is not the original, so
47that any problems introduced by others will not reflect on the original
48authors' reputations.
49
50 Finally, any free program is threatened constantly by software
51patents. We wish to avoid the danger that redistributors of a free
52program will individually obtain patent licenses, in effect making the
53program proprietary. To prevent this, we have made it clear that any
54patent must be licensed for everyone's free use or not licensed at all.
55
56 The precise terms and conditions for copying, distribution and
57modification follow.
58
59 GNU GENERAL PUBLIC LICENSE
60 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
62 0. This License applies to any program or other work which contains
63a notice placed by the copyright holder saying it may be distributed
64under the terms of this General Public License. The "Program", below,
65refers to any such program or work, and a "work based on the Program"
66means either the Program or any derivative work under copyright law:
67that is to say, a work containing the Program or a portion of it,
68either verbatim or with modifications and/or translated into another
69language. (Hereinafter, translation is included without limitation in
70the term "modification".) Each licensee is addressed as "you".
71
72Activities other than copying, distribution and modification are not
73covered by this License; they are outside its scope. The act of
74running the Program is not restricted, and the output from the Program
75is covered only if its contents constitute a work based on the
76Program (independent of having been made by running the Program).
77Whether that is true depends on what the Program does.
78
79 1. You may copy and distribute verbatim copies of the Program's
80source code as you receive it, in any medium, provided that you
81conspicuously and appropriately publish on each copy an appropriate
82copyright notice and disclaimer of warranty; keep intact all the
83notices that refer to this License and to the absence of any warranty;
84and give any other recipients of the Program a copy of this License
85along with the Program.
86
87You may charge a fee for the physical act of transferring a copy, and
88you may at your option offer warranty protection in exchange for a fee.
89
90 2. You may modify your copy or copies of the Program or any portion
91of it, thus forming a work based on the Program, and copy and
92distribute such modifications or work under the terms of Section 1
93above, provided that you also meet all of these conditions:
94
95 a) You must cause the modified files to carry prominent notices
96 stating that you changed the files and the date of any change.
97
98 b) You must cause any work that you distribute or publish, that in
99 whole or in part contains or is derived from the Program or any
100 part thereof, to be licensed as a whole at no charge to all third
101 parties under the terms of this License.
102
103 c) If the modified program normally reads commands interactively
104 when run, you must cause it, when started running for such
105 interactive use in the most ordinary way, to print or display an
106 announcement including an appropriate copyright notice and a
107 notice that there is no warranty (or else, saying that you provide
108 a warranty) and that users may redistribute the program under
109 these conditions, and telling the user how to view a copy of this
110 License. (Exception: if the Program itself is interactive but
111 does not normally print such an announcement, your work based on
112 the Program is not required to print an announcement.)
113
114These requirements apply to the modified work as a whole. If
115identifiable sections of that work are not derived from the Program,
116and can be reasonably considered independent and separate works in
117themselves, then this License, and its terms, do not apply to those
118sections when you distribute them as separate works. But when you
119distribute the same sections as part of a whole which is a work based
120on the Program, the distribution of the whole must be on the terms of
121this License, whose permissions for other licensees extend to the
122entire whole, and thus to each and every part regardless of who wrote it.
123
124Thus, it is not the intent of this section to claim rights or contest
125your rights to work written entirely by you; rather, the intent is to
126exercise the right to control the distribution of derivative or
127collective works based on the Program.
128
129In addition, mere aggregation of another work not based on the Program
130with the Program (or with a work based on the Program) on a volume of
131a storage or distribution medium does not bring the other work under
132the scope of this License.
133
134 3. You may copy and distribute the Program (or a work based on it,
135under Section 2) in object code or executable form under the terms of
136Sections 1 and 2 above provided that you also do one of the following:
137
138 a) Accompany it with the complete corresponding machine-readable
139 source code, which must be distributed under the terms of Sections
140 1 and 2 above on a medium customarily used for software interchange; or,
141
142 b) Accompany it with a written offer, valid for at least three
143 years, to give any third party, for a charge no more than your
144 cost of physically performing source distribution, a complete
145 machine-readable copy of the corresponding source code, to be
146 distributed under the terms of Sections 1 and 2 above on a medium
147 customarily used for software interchange; or,
148
149 c) Accompany it with the information you received as to the offer
150 to distribute corresponding source code. (This alternative is
151 allowed only for noncommercial distribution and only if you
152 received the program in object code or executable form with such
153 an offer, in accord with Subsection b above.)
154
155The source code for a work means the preferred form of the work for
156making modifications to it. For an executable work, complete source
157code means all the source code for all modules it contains, plus any
158associated interface definition files, plus the scripts used to
159control compilation and installation of the executable. However, as a
160special exception, the source code distributed need not include
161anything that is normally distributed (in either source or binary
162form) with the major components (compiler, kernel, and so on) of the
163operating system on which the executable runs, unless that component
164itself accompanies the executable.
165
166If distribution of executable or object code is made by offering
167access to copy from a designated place, then offering equivalent
168access to copy the source code from the same place counts as
169distribution of the source code, even though third parties are not
170compelled to copy the source along with the object code.
171
172 4. You may not copy, modify, sublicense, or distribute the Program
173except as expressly provided under this License. Any attempt
174otherwise to copy, modify, sublicense or distribute the Program is
175void, and will automatically terminate your rights under this License.
176However, parties who have received copies, or rights, from you under
177this License will not have their licenses terminated so long as such
178parties remain in full compliance.
179
180 5. You are not required to accept this License, since you have not
181signed it. However, nothing else grants you permission to modify or
182distribute the Program or its derivative works. These actions are
183prohibited by law if you do not accept this License. Therefore, by
184modifying or distributing the Program (or any work based on the
185Program), you indicate your acceptance of this License to do so, and
186all its terms and conditions for copying, distributing or modifying
187the Program or works based on it.
188
189 6. Each time you redistribute the Program (or any work based on the
190Program), the recipient automatically receives a license from the
191original licensor to copy, distribute or modify the Program subject to
192these terms and conditions. You may not impose any further
193restrictions on the recipients' exercise of the rights granted herein.
194You are not responsible for enforcing compliance by third parties to
195this License.
196
197 7. If, as a consequence of a court judgment or allegation of patent
198infringement or for any other reason (not limited to patent issues),
199conditions are imposed on you (whether by court order, agreement or
200otherwise) that contradict the conditions of this License, they do not
201excuse you from the conditions of this License. If you cannot
202distribute so as to satisfy simultaneously your obligations under this
203License and any other pertinent obligations, then as a consequence you
204may not distribute the Program at all. For example, if a patent
205license would not permit royalty-free redistribution of the Program by
206all those who receive copies directly or indirectly through you, then
207the only way you could satisfy both it and this License would be to
208refrain entirely from distribution of the Program.
209
210If any portion of this section is held invalid or unenforceable under
211any particular circumstance, the balance of the section is intended to
212apply and the section as a whole is intended to apply in other
213circumstances.
214
215It is not the purpose of this section to induce you to infringe any
216patents or other property right claims or to contest validity of any
217such claims; this section has the sole purpose of protecting the
218integrity of the free software distribution system, which is
219implemented by public license practices. Many people have made
220generous contributions to the wide range of software distributed
221through that system in reliance on consistent application of that
222system; it is up to the author/donor to decide if he or she is willing
223to distribute software through any other system and a licensee cannot
224impose that choice.
225
226This section is intended to make thoroughly clear what is believed to
227be a consequence of the rest of this License.
228
229 8. If the distribution and/or use of the Program is restricted in
230certain countries either by patents or by copyrighted interfaces, the
231original copyright holder who places the Program under this License
232may add an explicit geographical distribution limitation excluding
233those countries, so that distribution is permitted only in or among
234countries not thus excluded. In such case, this License incorporates
235the limitation as if written in the body of this License.
236
237 9. The Free Software Foundation may publish revised and/or new versions
238of the General Public License from time to time. Such new versions will
239be similar in spirit to the present version, but may differ in detail to
240address new problems or concerns.
241
242Each version is given a distinguishing version number. If the Program
243specifies a version number of this License which applies to it and "any
244later version", you have the option of following the terms and conditions
245either of that version or of any later version published by the Free
246Software Foundation. If the Program does not specify a version number of
247this License, you may choose any version ever published by the Free Software
248Foundation.
249
250 10. If you wish to incorporate parts of the Program into other free
251programs whose distribution conditions are different, write to the author
252to ask for permission. For software which is copyrighted by the Free
253Software Foundation, write to the Free Software Foundation; we sometimes
254make exceptions for this. Our decision will be guided by the two goals
255of preserving the free status of all derivatives of our free software and
256of promoting the sharing and reuse of software generally.
257
258 NO WARRANTY
259
260 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268REPAIR OR CORRECTION.
269
270 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278POSSIBILITY OF SUCH DAMAGES.
279
280 END OF TERMS AND CONDITIONS
281
282 Appendix: How to Apply These Terms to Your New Programs
283
284 If you develop a new program, and you want it to be of the greatest
285possible use to the public, the best way to achieve this is to make it
286free software which everyone can redistribute and change under these terms.
287
288 To do so, attach the following notices to the program. It is safest
289to attach them to the start of each source file to most effectively
290convey the exclusion of warranty; and each file should have at least
291the "copyright" line and a pointer to where the full notice is found.
292
293 <one line to give the program's name and a brief idea of what it does.>
294 Copyright (C) 19yy <name of author>
295
296 This program is free software; you can redistribute it and/or modify
297 it under the terms of the GNU General Public License as published by
298 the Free Software Foundation; either version 2 of the License, or
299 (at your option) any later version.
300
301 This program is distributed in the hope that it will be useful,
302 but WITHOUT ANY WARRANTY; without even the implied warranty of
303 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 GNU General Public License for more details.
305
306 You should have received a copy of the GNU General Public License
307 along with this program; if not, write to the Free Software
308 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
309
310Also add information on how to contact you by electronic and paper mail.
311
312If the program is interactive, make it output a short notice like this
313when it starts in an interactive mode:
314
315 Gnomovision version 69, Copyright (C) 19yy name of author
316 Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 This is free software, and you are welcome to redistribute it
318 under certain conditions; type `show c' for details.
319
320The hypothetical commands `show w' and `show c' should show the appropriate
321parts of the General Public License. Of course, the commands you use may
322be called something other than `show w' and `show c'; they could even be
323mouse-clicks or menu items--whatever suits your program.
324
325You should also get your employer (if you work as a programmer) or your
326school, if any, to sign a "copyright disclaimer" for the program, if
327necessary. Here is a sample; alter the names:
328
329 Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
332 <signature of Ty Coon>, 1 April 1989
333 Ty Coon, President of Vice
334
335This General Public License does not permit incorporating your program into
336proprietary programs. If your program is a subroutine library, you may
337consider it more useful to permit linking proprietary applications with the
338library. If this is what you want to do, use the GNU Library General
339Public License instead of this License.
diff --git a/xdelta1/INSTALL b/xdelta1/INSTALL
deleted file mode 100644
index 6319012..0000000
--- a/xdelta1/INSTALL
+++ /dev/null
@@ -1,217 +0,0 @@
1-*- Text -*-
2
3XDelta depends on
4
5 glib 1.2.8 or later
6 zlib 1.1.3 or later
7
8You can get glib from
9
10 ftp://ftp.gtk.org/pub/gtk/v1.2
11
12You can get zlib from
13
14 ftp://ftp.cdrom.com/pub/infozip/zlib
15
16To install, make sure these packages are installed and your compiler
17and linker either locates zlib by default or that the CFLAGS
18environment variable contains an appropriate include directive and the
19LDFLAGS environment variable contains a suitable linker directive.
20
21Then run
22
23 ./configure
24
25Then run
26
27 make
28
29Then run
30
31 make install
32
33Below follows the standard GNU INSTALL file, which contains general
34troubleshooting tips.
35
36Basic Installation
37==================
38
39 These are generic installation instructions.
40
41 The `configure' shell script attempts to guess correct values for
42various system-dependent variables used during compilation. It uses
43those values to create a `Makefile' in each directory of the package.
44It may also create one or more `.h' files containing system-dependent
45definitions. Finally, it creates a shell script `config.status' that
46you can run in the future to recreate the current configuration, a file
47`config.cache' that saves the results of its tests to speed up
48reconfiguring, and a file `config.log' containing compiler output
49(useful mainly for debugging `configure').
50
51 If you need to do unusual things to compile the package, please try
52to figure out how `configure' could check whether to do them, and mail
53diffs or instructions to the address given in the `README' so they can
54be considered for the next release. If at some point `config.cache'
55contains results you don't want to keep, you may remove or edit it.
56
57 The file `configure.in' is used to create `configure' by a program
58called `autoconf'. You only need `configure.in' if you want to change
59it or regenerate `configure' using a newer version of `autoconf'.
60
61The simplest way to compile this package is:
62
63 1. `cd' to the directory containing the package's source code and type
64 `./configure' to configure the package for your system. If you're
65 using `csh' on an old version of System V, you might need to type
66 `sh ./configure' instead to prevent `csh' from trying to execute
67 `configure' itself.
68
69 Running `configure' takes awhile. While running, it prints some
70 messages telling which features it is checking for.
71
72 2. Type `make' to compile the package.
73
74 3. Optionally, type `make check' to run any self-tests that come with
75 the package.
76
77 4. Type `make install' to install the programs and any data files and
78 documentation.
79
80 5. You can remove the program binaries and object files from the
81 source code directory by typing `make clean'. To also remove the
82 files that `configure' created (so you can compile the package for
83 a different kind of computer), type `make distclean'. There is
84 also a `make maintainer-clean' target, but that is intended mainly
85 for the package's developers. If you use it, you may have to get
86 all sorts of other programs in order to regenerate files that came
87 with the distribution.
88
89Compilers and Options
90=====================
91
92 Some systems require unusual options for compilation or linking that
93the `configure' script does not know about. You can give `configure'
94initial values for variables by setting them in the environment. Using
95a Bourne-compatible shell, you can do that on the command line like
96this:
97 CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
98
99Or on systems that have the `env' program, you can do it like this:
100 env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
101
102Compiling For Multiple Architectures
103====================================
104
105 You can compile the package for more than one kind of computer at the
106same time, by placing the object files for each architecture in their
107own directory. To do this, you must use a version of `make' that
108supports the `VPATH' variable, such as GNU `make'. `cd' to the
109directory where you want the object files and executables to go and run
110the `configure' script. `configure' automatically checks for the
111source code in the directory that `configure' is in and in `..'.
112
113 If you have to use a `make' that does not supports the `VPATH'
114variable, you have to compile the package for one architecture at a time
115in the source code directory. After you have installed the package for
116one architecture, use `make distclean' before reconfiguring for another
117architecture.
118
119Installation Names
120==================
121
122 By default, `make install' will install the package's files in
123`/usr/local/bin', `/usr/local/man', etc. You can specify an
124installation prefix other than `/usr/local' by giving `configure' the
125option `--prefix=PATH'.
126
127 You can specify separate installation prefixes for
128architecture-specific files and architecture-independent files. If you
129give `configure' the option `--exec-prefix=PATH', the package will use
130PATH as the prefix for installing programs and libraries.
131Documentation and other data files will still use the regular prefix.
132
133 In addition, if you use an unusual directory layout you can give
134options like `--bindir=PATH' to specify different values for particular
135kinds of files. Run `configure --help' for a list of the directories
136you can set and what kinds of files go in them.
137
138 If the package supports it, you can cause programs to be installed
139with an extra prefix or suffix on their names by giving `configure' the
140option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
141
142Optional Features
143=================
144
145 Some packages pay attention to `--enable-FEATURE' options to
146`configure', where FEATURE indicates an optional part of the package.
147They may also pay attention to `--with-PACKAGE' options, where PACKAGE
148is something like `gnu-as' or `x' (for the X Window System). The
149`README' should mention any `--enable-' and `--with-' options that the
150package recognizes.
151
152 For packages that use the X Window System, `configure' can usually
153find the X include and library files automatically, but if it doesn't,
154you can use the `configure' options `--x-includes=DIR' and
155`--x-libraries=DIR' to specify their locations.
156
157Specifying the System Type
158==========================
159
160 There may be some features `configure' can not figure out
161automatically, but needs to determine by the type of host the package
162will run on. Usually `configure' can figure that out, but if it prints
163a message saying it can not guess the host type, give it the
164`--host=TYPE' option. TYPE can either be a short name for the system
165type, such as `sun4', or a canonical name with three fields:
166 CPU-COMPANY-SYSTEM
167
168See the file `config.sub' for the possible values of each field. If
169`config.sub' isn't included in this package, then this package doesn't
170need to know the host type.
171
172 If you are building compiler tools for cross-compiling, you can also
173use the `--target=TYPE' option to select the type of system they will
174produce code for and the `--build=TYPE' option to select the type of
175system on which you are compiling the package.
176
177Sharing Defaults
178================
179
180 If you want to set default values for `configure' scripts to share,
181you can create a site shell script called `config.site' that gives
182default values for variables like `CC', `cache_file', and `prefix'.
183`configure' looks for `PREFIX/share/config.site' if it exists, then
184`PREFIX/etc/config.site' if it exists. Or, you can set the
185`CONFIG_SITE' environment variable to the location of the site script.
186A warning: not all `configure' scripts look for a site script.
187
188Operation Controls
189==================
190
191 `configure' recognizes the following options to control how it
192operates.
193
194`--cache-file=FILE'
195 Use and save the results of the tests in FILE instead of
196 `./config.cache'. Set FILE to `/dev/null' to disable caching, for
197 debugging `configure'.
198
199`--help'
200 Print a summary of the options to `configure', and exit.
201
202`--quiet'
203`--silent'
204`-q'
205 Do not print messages saying which checks are being made. To
206 suppress all normal output, redirect it to `/dev/null' (any error
207 messages will still be shown).
208
209`--srcdir=DIR'
210 Look for the package's source code in directory DIR. Usually
211 `configure' can determine that directory automatically.
212
213`--version'
214 Print the version of Autoconf used to generate the `configure'
215 script, and exit.
216
217`configure' also accepts some other, not widely useful, options.
diff --git a/xdelta1/Makefile.am b/xdelta1/Makefile.am
deleted file mode 100644
index 41b217e..0000000
--- a/xdelta1/Makefile.am
+++ /dev/null
@@ -1,50 +0,0 @@
1
2INCLUDES = -I$(top_srcdir)/libedsio $(GLIB_CFLAGS)
3
4bin_PROGRAMS = xdelta
5bin_SCRIPTS = xdelta-config
6
7xdelta_SOURCES = xdmain.c getopt.c getopt1.c
8
9xdelta_LDADD = libxdelta.la \
10 $(top_srcdir)/libedsio/libedsio.la \
11 $(GLIB_LIBS) \
12 -lz
13
14include_HEADERS = xdelta.h xd_edsio.h
15noinst_HEADERS = xdeltapriv.h getopt.h
16
17lib_LTLIBRARIES = libxdelta.la
18
19libxdelta_la_SOURCES = xdelta.c xdapply.c $(SER_SOURCES)
20libxdelta_la_LIBADD = $(GLIB_LIBS)
21
22EXTRA_DIST = xd.ser $(SER_OUT) xdelta.magic xdelta.prj xdelta.m4 \
23 autogen.sh xdelta.dsp xdelta.dsw stamp-ser xdrsync.c
24
25SUBDIRS = libedsio . test doc djgpp
26
27m4datadir = $(datadir)/aclocal
28m4data_DATA = xdelta.m4
29
30## $Format: "libxdelta_la_LDFLAGS = -version-info $LibCurrent$:$LibRevision$:$LibAge$" $
31libxdelta_la_LDFLAGS = -version-info 2:0:0
32
33#
34# Rules for the generated code
35#
36
37stamp-ser: $(top_srcdir)/libedsio/edsio.el xd.ser
38 $(top_srcdir)/libedsio/edsio-comp xd.ser
39 touch stamp-ser
40
41SER_OUT = xd_edsio.h xd_edsio.c
42
43$(SER_OUT): stamp-ser
44
45SER_SOURCES = xd_edsio.c
46BUILT_SOURCES = $(SER_SOURCES)
47
48#
49#
50#
diff --git a/xdelta1/NEWS b/xdelta1/NEWS
deleted file mode 100644
index 6bbcbf9..0000000
--- a/xdelta1/NEWS
+++ /dev/null
@@ -1,217 +0,0 @@
1XDelta NEWS -- history of user-visible changes. -*- Text -*-
2$Date: Sun, 24 Feb 2002 11:31:12 -0800 $
3$ReleaseVersion: 1.1.4 $
4
5Please send bug reports to xdelta-bugs@XCF.Berkeley.EDU. See the file
6`README' for a description of how to report bugs.
7
8
9** Changes since version 1.1.3
10
11* Add an implementation of xdp_generator_free() for users of the
12 libxdelta API. Previously there were no such users of the 1.x API,
13 but Elliot Lee <sopwith@redhat.com> has written a program for
14 providing delta operations on RPM files. See http://@@@
15
16* The man page now documents return values.
17
18** Changes since version 1.1.2
19
20* Correct error message format for the case when gzread fails trying
21 to automatically decompress a corrupted GZIP file. The situation
22 itself--corrupt GZIP files--should be dealt with the -p (--pristine)
23 option, which disables GZIP file recognition. Reported by Ben
24 Escoto.
25
26* Apply a patch from Klaus Dittrich for building on HPUX with the
27 native compiler. There is now a script called "contrib/build_hpux".
28
29
30** Changes since version 1.1.1
31
32* This code release is a distant fork of the 2.0 release. It will
33 hopefully be replaced.
34
35* When 'patch' supplies its default TO file name recorded in the
36 delta, it still generates a unique file name to avoid overwriting an
37 existing copy. Use the 'xdelta info' command to see what file names
38 are contained in the delta.
39
40* The code for writing patches to stdout was broken in the case where
41 gzip compression is used. Writing patches to stdout has therefore
42 been disabled. The problem is a limitation in the gzdopen/gzwrite
43 functions provided by zlib--you cannot determine how many bytes have
44 been written to the file descriptor without dup-ing the FD
45 beforehand and then lseek-ing afterwards, which does not work
46 correctly if the output file is not seekable.
47
48* By default, Xdelta uses a hard-coded 16 byte block size. If you're
49 working with large files, try #undef XDELTA_HARDCODE_SIZE in
50 xdelta.h then use -s BLOCKSIZE (--blocksize=BLOCKSIZE), which should
51 be a power of 2.
52
53* New test program in the 'test' subdirectory, which runs comparisons
54 against "diff --rcs -a" and also verifies the "xdelta patch"
55 command.
56
57* Incorporate DJGPP patches from Richard Dawe <richdawe@bigfoot.com>.
58 You can find his versions directly at:
59
60 ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2apps/xdlt112b.zip
61 ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2apps/xdlt112s.zip
62
63* Updated xdelta(1) man page.
64
65* Updated autoconf (2.50), automake (1.4-p4), libtool (1.4) scripts,
66 which includes updated config.guess and config.sub scripts.
67
68* Correct some backward compatibility issues: strcmp() was not being
69 tested == 0 for formats older than 1.0.4.
70
71* Update GLIB version requirement, now 1.2.8.
72
73* We really need support for 64bit file sizes... perhaps the next
74 version?
75
76
77** Changes since version 1.1.0
78
79* No one was were able to build the 1.1.0 release because it depended
80 on a version of glib which will not be distributed for some time.
81 This version backs out those dependencies and now requires
82 glib-1.2.1.
83
84
85** Changes since version 1.0.6
86
87* The 64M limit on file sizes has been lifted. File lengths are now
88 limited by the size of a 32-bit integer.
89
90* The internal data structures were changed and some of the
91 experimental bits of the interface have been moved out of libxdelta,
92 resulting in a simpler interface. Old patch files are still
93 supported.
94
95
96** Changes since version 1.0.5
97
98* There are 8 bytes of space in the patch format's header that are
99 reserved for future use. They are not currently used, but were also
100 not being initialized, making it possible for two deltas produced in
101 the same manner to differ. This was exposed by comparing deltas
102 produced between the same files on Windows and Linux. With this
103 patch, the results should be identical.
104
105
106** Changes since version 1.0.4
107
108* The code now compiles natively under Windows. I used MS VC++ 5.0.
109 It depends on glib and zlib, but I don't feel like documenting
110 the build process yet. I have had some trouble with the zlib DLLs
111 and had to build my own, so you can't build it yourself yet. There
112 is a pre-built version at
113
114 ftp://ftp.xcf.berkeley.edu/pub/xdelta/xdelta-1.0.5.win32.zip
115
116* Many changes required to keep Xdelta working with PRCS 2. Mostly
117 this involved keeping up to date with some code that is shared
118 between the two. All the shared code is now in the "libedsio"
119 subdirectory, which stands for "Error Delivery and Serialized IO".
120
121
122** Changes since version 1.0.3
123
124* Slight change in file format to improve detection of and error
125 messages regarding corrupt deltas (specifically, those left behing
126 when an xdelta process is killed while computing a delta). This
127 means 1.0.0-1.0.3 will not read these new deltas, they will report a
128 bad magic number.
129
130* Improve several error messages related to corrupt deltas.
131
132
133** Changes since version 1.0.2
134
135* Fix a few bugs, especially one related to the implementation of -m,
136 and a couple more which were shaken out by testing on a pair of
137 emacs releases (~55M each). These changes only affect the xdelta
138 application, the library is unchanged.
139
140* Add a new command `xdelta info' that lists information about a
141 delta, for example:
142
143 $ xdelta info some.patch
144 xdelta: version 1.0.3 found patch version 1.0 in some.patch
145 xdelta: patch contents are compressed
146 xdelta: patch from: from
147 xdelta: patch from length: 53309440
148 xdelta: patch from md5: c0ddcb6904d40da7cf1eae5e6bdbbc01
149 xdelta: patch to: to
150 xdelta: patch to length: 55377920
151 xdelta: patch to md5: 00b3dd4d1a9b450bc5b8991b183013fb
152 xdelta: patch insert length: 2436426
153 xdelta: patch inst count: 253649
154
155
156** Changes since version 1.0.1
157
158* Fix minor typos, and build improvements. There is now a gtk-style
159 'xdelta-config' program and autoconf macro to locate the library.
160
161
162** Changes since version 1.0.0
163
164* Fix incorrect usage report in --help output for the patch command.
165
166* Abort when directories are specified, there is no recursive mode.
167
168* Now requires glib-1.1.5.
169
170* The new ``pristine'' option (-p, --pristine) disables
171 automatic uncompression of compressed input data, and is for use
172 when data integrity is being externally verified. This enables a
173 tool written by Manish Singh (yosh@gimp.org) to compute deltas
174 between the Debian dpkg utility's .deb format.
175
176* A draft paper describing its algorithms, rational, advanced
177 features, and future work is now available at
178 ftp://ftp.xcf.berkeley.edu/pub/xdelta/xdelta.ps.
179
180** Changes since version 0.24
181
182* This version is a complete rewrite, and removes some of the features
183 available in version 0. Featuring:
184
185 - A completely new and much improved library interface. This code is
186 a complete rewrite.
187 - An optimized implementation of the XDelta algorithm.
188 - A drastic memory reduction.
189 - The library stream-processes files where possible and uses a page-
190 based interface when seeking is required (allowing the application
191 to run in bounded memory on large files).
192 - There is now a little documentation. A man page and the
193 beginnings of texinfo documentation.
194 - Includes several advanced features used by PRCS version 2, see the
195 documentation for more information.
196 - Includes a minimal implementation of the Rsync algorithm, also used
197 by PRCS version 2.
198 - Uses an abstract file handle interface, the library has very few
199 system dependencies. This allows the library client to compute
200 MD5 checksums in a single-pass as XDelta reads files, use pre-
201 computed checksums, or disable checksum verification entirely.
202 - Compression and file-unarchival have been removed from the library,
203 these features are orthogonal.
204
205 At the application level:
206
207 - GDBM archive experiment has been removed. This functionality is
208 implemented directly in PRCS version 2 using the present library
209 interface.
210 - Base 64 encoding support has been removed for technical reasons.
211 - Can no longer accept patches from stdin, due to the same
212 technical reasons (the patch instruction index is stored at the
213 end of the file, requiring seeking).
214 - Automatic detection and un-archival of RPM and dpkg file formats
215 has been removed. Automatic uncompression of gzipped files is
216 still supported.
217 - The GIMP plugin is no longer supported.
diff --git a/xdelta1/README b/xdelta1/README
deleted file mode 100644
index 3e72daa..0000000
--- a/xdelta1/README
+++ /dev/null
@@ -1,180 +0,0 @@
1 -*- Text -*-
2
3 Xdelta -- A binary delta generator
4
5Announcing version 1.1.2 of Xdelta. Xdelta is an application program
6designed to compute changes between files. These changes (deltas) are
7similar to the output of the "diff" program in that they may be used
8to store and transmit only the changes between files. However, unlike
9diff, the output of Xdelta is not expressed in a human-readable
10format--Xdelta can also also apply these deltas to a copy of the
11original file. Xdelta uses a fast, linear algorithm and performs well
12on both binary and text files.
13
14Xdelta 1.1.2 is a stable, maintenence release. New, ongoing work on
15Xdelta has focused on a new storage system with features similar to
16the RCS command set. For more information on new development, see the
17Xdelta-2.0 release series at http://xdelta.sourceforge.net.
18
19Xdelta was designed and implemented by Joshua MacDonald. The delta
20algorithm is based on the Rsync algorithm, though implementation and
21interface considerations leave the two programs quite distinct. The
22Rsync algorithm is due to Andrew Tridgell and Paul Mackerras.
23
24To compile and install Xdelta, read the instructions in the INSTALL
25file. Once you have done this, you should at least read the first few
26sections of the documentation. It is available in info format. All
27documentation is located in the doc/ subdirectory.
28
29This release, version 1.1.2, and future releases of Xdelta can be
30found at http://xdelta.sourceforge.net.
31
32Xdelta is released under the GNU Library Public License (GPL), see the
33file COPYING for details.
34
35There is mailing list for announcements:
36
37 xdelta-announce@lists.sourceforge.net
38
39you can subscribe to the mailing list or file bug reports through
40Sourceforge at:
41
42 http://sourceforge.net/projects/xdelta/
43
44Comments about Xdelta can be addressed to the following addresses:
45
46 jmacd@cs.berkeley.edu
47
48The man page describes how to use Xdelta in more detail:
49
50NAME
51 xdelta - Invoke Xdelta
52
53SYNOPSIS
54 xdelta subcommand [ option... ] [ operand... ]
55
56DESCRIPTION
57
58 Xdelta provides the ability to generate deltas between a pair
59 of files and later apply those deltas. It operates similar to
60 the diff and patch commands, but works on binary files and does
61 not produce a human readable output.
62
63 Xdelta has three subcommands, delta, patch, and info. Delta
64 accepts two file versions and produces a delta, while patch
65 accepts the original file version and delta and produces the
66 second version. The info command prints useful information
67 about a delta. Each subcommand will be detailed seperately.
68
69 Gzip processing
70
71 Attempting to compute a delta between compressed input files
72 usually results in poor compression. This is because small
73 differences between the original contents causes changes in the
74 compression of whole blocks of data. To simplify things,
75 Xdelta implements a special case for gzip(1) compressed files.
76 If any version input to the delta command is recognized as
77 having gzip compression, it will be automatically decompressed
78 into a temporary location prior to comparison. This temporary
79 location is either the value of the TMPDIR environment
80 variable, if set, otherwise "/tmp".
81
82 The Xdelta patch header contains a flag indicating that the
83 reconstructed version should be recompressed after applying
84 the patch. In general, this allows Xdelta to operate
85 transparently on gzip compressed inputs.
86
87 There is one potential problem when automatically processing
88 gzip compressed files, which is that the recompressed content
89 does not always match byte-for-byte with the original
90 compressed content. The uncompressed content still matches,
91 but if there is an external integrity check such as
92 cryptographic signature verification, it may fail. To prevent
93 this from happening, the --pristine option disables automatic
94 gzip processing.
95
96 MD5 integrity check
97
98 By default, Xdelta always verifies the MD5 checksum of the
99 files it reconstructs. This prevents you from supplying an
100 incorrect input during patch, which would result in corrupt
101 output. Because of this feature, you can feel confident that
102 patch has produced valid results. The --noverify option
103 disables MD5 verification, but this is only recommended for
104 performance testing.
105
106 Compressed patch format
107
108 Xdelta uses a fairly simple encoding for its delta, then
109 applies zlib compression to the result. You should not have to
110 post-compress an Xdelta delta.
111
112 Delta
113
114 The delta subcommand has the following synopsis:
115
116 xdelta delta [ option... ] fromfile tofile patchout
117
118 Computes a delta from fromfile to tofile and writes it to patchout
119
120 Patch
121
122 The patch subcommand has the following synopsis:
123
124 xdelta patch [ option... ] patchin [ fromfile [ tofile ]]
125
126 Applies patchin to fromfile and produces a reconstructed
127 version of tofile.
128
129 If fromfile was omitted, Xdelta attempts to use the original
130 fromfile name, which is stored in the delta. The from file
131 must be identical to the one used to create the delta. If its
132 length or MD5 checksum differs, patch will abort with an error
133 message.
134
135 If tofile was omitted, Xdelta attempts to use the original
136 tofile name, which is also stored in the delta. If the
137 original tofile name already exists, a unique filename
138 extension will be added to avoid destroying any existing data.
139
140 Info
141 The info subcommand has the following synopsis:
142
143 xdelta info patchinfo
144
145 Prints information about patchinfo and the version it
146 reconstructs, including file names, lengths, and MD5 checksums.
147
148 Options
149 -0..9 Set the zlib compression level. Zero indicates no
150 compression. Nine indicates maximum compression.
151
152 -h, --help
153 Print a short help message and exit.
154
155 -q, --quiet
156 Quiet. Surpresses several warning messages.
157
158 -v, --version
159 Print the Xdelta version number and exit.
160
161 -V, --verbose
162 Verbose. Prints a bit of extra information.
163
164 -n, --noverify
165 No verify. Turns off MD5 checksum verification of the
166 input and output files.
167
168 -m=SIZE, --maxmem=SIZE
169 Set an upper bound on the size of an in-memory page
170 cache. For example, --maxmem=32M will use a 32 megabyte
171 page cache.
172
173 -s=BLOCK_SIZE
174 Set the block size, unless it was hard coded (20% speed
175 improvement). Should be a power of 2.
176
177 -p, --pristine
178 Disable the automatic decompression of gzipped
179 inputs, to prevent unexpected differences in the
180 re-compressed content.
diff --git a/xdelta1/autogen.sh b/xdelta1/autogen.sh
deleted file mode 100644
index 5f2e9c2..0000000
--- a/xdelta1/autogen.sh
+++ /dev/null
@@ -1,59 +0,0 @@
1#!/bin/sh
2# Run this to generate all the initial makefiles, etc.
3
4DIE=0
5
6(autoconf --version) < /dev/null > /dev/null 2>&1 || {
7 echo
8 echo "You must have autoconf installed to compile xdelta."
9 echo "Download the appropriate package for your distribution,"
10 echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
11 DIE=1
12}
13
14(libtool --version) < /dev/null > /dev/null 2>&1 || {
15 echo
16 echo "You must have libtool installed to compile xdelta."
17 echo "Get ftp://alpha.gnu.org/gnu/libtool-1.2d.tar.gz"
18 echo "(or a newer version if it is available)"
19 DIE=1
20}
21
22(automake --version) < /dev/null > /dev/null 2>&1 || {
23 echo
24 echo "You must have automake installed to compile xdelta."
25 echo "Get ftp://ftp.cygnus.com/pub/home/tromey/automake-1.4.tar.gz"
26 echo "(or a newer version if it is available)"
27 DIE=1
28}
29
30if test "$DIE" -eq 1; then
31 exit 1
32fi
33
34(test -f xdelta.c) || {
35 echo "You must run this script in the top-level xdelta directory"
36 exit 1
37}
38
39if test -z "$*"; then
40 echo "I am going to run ./configure with no arguments - if you wish "
41 echo "to pass any to it, please specify them on the $0 command line."
42fi
43
44for i in .
45do
46 echo processing $i
47 (cd $i; \
48 libtoolize --copy --force; \
49 aclocal $ACLOCAL_FLAGS; autoheader; \
50 automake --add-missing; \
51 autoheader; \
52 autoconf)
53done
54
55echo "Running ./configure --enable-maintainer-mode" "$@"
56./configure --enable-maintainer-mode "$@"
57
58echo
59echo "Now type 'make' to compile xdelta."
diff --git a/xdelta1/configure.in b/xdelta1/configure.in
deleted file mode 100644
index 76a71f4..0000000
--- a/xdelta1/configure.in
+++ /dev/null
@@ -1,91 +0,0 @@
1dnl -*-Mode: C; comment-start: "dnl "-*-
2dnl Process this file with autoconf to produce a configure script.
3AC_REVISION([configure.in,v 1.2 1998/10/03 00:17:50 jmacd Exp])dnl
4AC_INIT(xdelta.c)
5AM_CONFIG_HEADER(config.h)
6
7dnl $Format: "AM_INIT_AUTOMAKE(xdelta, $ReleaseVersion$, no-define)" $
8AM_INIT_AUTOMAKE(xdelta, 1.1.4, no-define)
9
10AM_MAINTAINER_MODE
11
12DEBUGFLAG=
13PROFILEFLAG=
14
15AC_ARG_ENABLE(debug, [ --enable-debug turn on debugging [default=no]])
16AC_ARG_ENABLE(profile, [ --enable-profile turn on profiling [default=no]])
17
18TMPCFLAGS="$CFLAGS"
19CFLAGS=
20
21AC_PROG_CC
22AC_PROG_CPP
23
24CFLAGS=$TMPCFLAGS
25
26changequote(,)dnl
27if test "x$GCC" = "xyes"; then
28 case " $CFLAGS " in
29 *[\ \ ]-Wall[\ \ ]*) ;;
30 *) CFLAGS="$CFLAGS -Wall" ;;
31 esac
32
33 if test "x$enable_debug" = "xyes"; then
34 DEBUGFLAG="-g"
35 fi
36
37 if test "x$enable_profile" = "xyes"; then
38 PROFILEFLAG="-pg"
39 fi
40
41 if test -n "$DEBUGFLAG"; then
42 case " $CFLAGS " in
43 *[\ \ ]$DEBUGFLAG[\ \ ]*) ;;
44 *) CFLAGS="$DEBUGFLAG $CFLAGS" ;;
45 esac
46 else
47 case " $CFLAGS " in
48 *[\ \ ]-O[0-9\ \ ]*) ;;
49 *) CFLAGS="$CFLAGS -O3" ;;
50 esac
51 fi
52
53 if test -n "$PROFILEFLAG"; then
54 case " $CFLAGS " in
55 *[\ \ ]$PROFILEFLAG[\ \ ]*) ;;
56 *) CFLAGS="$PROFILEFLAG $CFLAGS" ;;
57 esac
58 fi
59fi
60changequote([,])dnl
61
62AM_PROG_LIBTOOL
63AC_HEADER_STDC
64AC_PROG_MAKE_SET
65
66AC_CHECK_FUNCS(gettimeofday)
67AC_HEADER_TIME
68
69AC_PATH_PROGS(EMACS, emacs xemacs, emacs)
70
71top_srcdir_absolute=`cd $srcdir; pwd`
72AC_SUBST(top_srcdir_absolute)
73
74AM_PATH_GLIB(1.2.8,,
75 AC_MSG_ERROR(Test for GLIB failed. Download it from ftp://ftp.gtk.org/pub/gtk/v1.2/))
76
77dnl AC_CHECK_LIB(z, gzsetparams, */
78dnl AC_CHECK_HEADER(zlib.h,, */
79dnl AC_MSG_ERROR(ZLIB headers not found)), */
80dnl AC_MSG_ERROR(ZLIB library not found)) */
81
82AC_OUTPUT(Makefile
83 doc/Makefile
84 test/Makefile
85 djgpp/Makefile
86 xdelta-config
87 libedsio/Makefile
88 libedsio/edsio-comp,
89
90 chmod +x libedsio/edsio-comp xdelta-config
91 )
diff --git a/xdelta1/contrib/build_hpux b/xdelta1/contrib/build_hpux
deleted file mode 100644
index a4c0ad4..0000000
--- a/xdelta1/contrib/build_hpux
+++ /dev/null
@@ -1,21 +0,0 @@
1#!/usr/bin/ksh
2#
3# Changed configure to install in /usr/local/lib/glib-1.2.
4#
5# Script was contributed by Klaus Dittrich
6
7gmake distclean
8CC="cc -Ae" \
9CFLAGS="+O2 +Onolimit +DAportable" \
10CPPFLAGS="-I/usr/local/include/glib-1.2 -I/usr/local/include/zlib" \
11LDFLAGS="-L/usr/local/lib/glib-1.2 -L/usr/local/lib/zlib -lz" ./configure
12
13gmake
14gmake check
15exit
16:> ./TIME
17sleep 1
18gmake install
19mkdir -p /usr/local/docs/glib
20find /usr/local/* -newer ./TIME | grep -v `pwd` > THIS_WAS_INSTALLED
21gmake distclean
diff --git a/xdelta1/djgpp/Makefile.am b/xdelta1/djgpp/Makefile.am
deleted file mode 100644
index 7ab6d22..0000000
--- a/xdelta1/djgpp/Makefile.am
+++ /dev/null
@@ -1,2 +0,0 @@
1
2EXTRA_DIST = readme.djg announce.djg
diff --git a/xdelta1/djgpp/announce.djg b/xdelta1/djgpp/announce.djg
deleted file mode 100644
index 6ec3dc7..0000000
--- a/xdelta1/djgpp/announce.djg
+++ /dev/null
@@ -1,45 +0,0 @@
1Hello.
2
3I'm please to announce the release of the DJGPP port of XDelta 1.1.2.
4This release contains mainly minor bugfixes over the previous
5version (1.1.1). Please see the file 'contrib/xdlt112/news' for
6a complete list of changes.
7
8Here is a description of XDelta, from its 'readme' file:
9
10"XDelta is a library interface and application program designed to compute
11changes between files. These changes (deltas) are similar to the output
12of the "diff" program in that they may be used to store and transmit only
13the changes between files. However, unlike diff, the output of XDelta is
14not expressed in a human-readable format--XDelta can also also apply these
15deltas to a copy of the original file(s). XDelta uses a fast, linear
16algorithm and performs well on both binary and text files. XDelta
17typically outperforms GNU diff in both time and generated-delta-size, even
18for plain text files. XDelta also includes a simple implementation of the
19Rsync algorithm and several advanced features for implementing RCS-like
20file-archival with."
21
22XDelta is distributed under the GNU General Public License.
23
24The port is available from the DJGPP archive on SimTel.NET:
25
26http://www.simtel.net/gnudlpage.php?product=/gnu/djgpp/v2apps/xdlt112b.zip&name=xdlt112b.zip
27http://www.simtel.net/gnudlpage.php?product=/gnu/djgpp/v2apps/xdlt112s.zip&name=xdlt112s.zip
28
29These are binary and source distributions respectively. If you only want
30to use XDelta, please download the binary distribution. If you would like
31to rebuild XDelta, please download the source distribution. No changes
32were required to port XDelta to DJGPP.
33
34Thanks to Joshua MacDonald for incorporating the DJGPP patches into
35XDelta. Thanks to Eli Zaretskii for his detailed bug reports, suggestions
36and testing of XDelta in the past.
37
38If you have any problems, suggestions, etc. about the port, please mail
39me.
40
41Bye,
42
43--
44Richard Dawe
45http://www.phekda.freeserve.co.uk/richdawe/
diff --git a/xdelta1/djgpp/readme.djg b/xdelta1/djgpp/readme.djg
deleted file mode 100644
index e0868c3..0000000
--- a/xdelta1/djgpp/readme.djg
+++ /dev/null
@@ -1,136 +0,0 @@
1DJGPP Port of XDelta 1.1.2
2~~~~~~~~~~~~~~~~~~~~~~~~~~
3
4Installing the Binary Package
5-----------------------------
6
7Unzip the distribution preserving the directory structure - use PKUNZIP's -d
8option; use an equivalent option with other unzippers. Unzip into the top
9DJGPP installation directory, e.g. c:\djgpp.
10
11XDelta should now be ready for use. A man page for XDelta is provided - use:
12
13 man xdelta
14
15to view it. You will need to have installed the man program from the v2apps/
16directory of the DJGPP archive for this to work.
17
18Installing the Source Package
19-----------------------------
20
21You should only install the source package if you want to rebuild XDelta from
22the sources. To build the port, I used the following packages:
23
24. DJGPP 2.03
25. GNU bash 2.04
26. GNU gcc 2.95.3
27. GNU binutils 2.11.2
28. GNU sed 3.02
29. GNU awk 3.0.3
30. GNU fileutils 4.0
31. GNU shellutils 1.12
32. GNU textutils 2.0
33. glib 1.2.10
34. zlib 1.1.3
35
36It may be possible to build XDelta with other versions of each package, but
37this has not been tested.
38
39Unzip the distribution preserving the directory structure - use PKUNZIP's -d
40option; use an equivalent option with other unzippers. Unzip into the top
41DJGPP installation directory, e.g. c:\djgpp.
42
43No changes were needed to XDelta to make it work with DJGPP.
44
45Before building XDelta, it must be configured. This is done from bash
46in the source directory using:
47
48 ./configure --disable-shared
49
50The parameter '--disable-shared' is needed to get round a bug in
51libtool 1.4. libtool tries to use gcc's '-fPIC' option, which produces
52code that binutils does not understand (for DJGPP). '-fPIC' is used
53for generating relocatable code for dynamic linking. Since DJGPP does not
54support dynamic linking, we can use '--disable-shared' to stop '-fPIC'
55from being used.
56
57For more information on the libtool problem, please see the following
58post on djgpp-workers:
59
60http://www.delorie.com/djgpp/mail-archives/browse.cgi?p=djgpp-workers/2001/06/18/16:32:47
61
62You may wish to install XDelta somewhere else. In that case, use
63the '--prefix' option, e.g.
64
65 ./configure --disable-shared --prefix=/where/i/want/xdelta
66
67Once this has compelted, build using:
68
69 make
70
71If these compelte successfully, XDelta and its libraries can be installed
72using:
73
74 make install
75
76Some notes on using XDelta
77--------------------------
78
79* XDelta is fairly simple - to see what options are available, use:
80
81 xdelta --help
82
83* The '-p' or '--pristine' option prevents XDelta from using gzip
84 compression, this avoids creating temporary files. This option
85 is presented because gzip does not support exact re-compression,
86 since there is no way to save the configuration used to produce
87 a particular gzip file.
88
89* XDelta's buffers are sized (by default) according to the amount of
90 free physical memory. It defaults to using 87.5% (7/8) of
91 the available memory.
92
93 Under Windows this sometimes does not detect the amount of
94 free memory correctly (well, on this author's machine at least).
95 Sometimes it was necessary to tell xdelta what amount of memory
96 to use:
97
98 xdelta patch --maxmem=32M ...
99
100 NB: More memory means faster patching, with large patches & files.
101
102 It is recommend you run XDelta in verbose mode, to see how much
103 memory it is using:
104
105 xdelta patch -V ...
106
107libxdelta and libedsio
108----------------------
109
110XDelta is actually just a front-end for two libraries - libxdelta
111and libedsio. libxdelta is a library for handling XDelta-format deltas.
112libedsio is a library for handling serialised I/O. Both these libraries are
113included in the port and can be used in your own programs.
114
115Unfortunately, there is no documentation for these libraries - the only
116reference is the source code. If you are interested in libxdelta and libedsio,
117please download the source distribution. Please note that I am not familiar
118with these libraries and I will not be able to answer any queries on them.
119
120libxdelta and libedsio come with *-config files, which return compilation
121and linking parameters. They are similar to glib-config. Example:
122
123 bash-2.04$ xdelta-config --cflags
124 -I/dev/env/DJDIR/lib/glib/include -I/dev/env/DJDIR/include
125 bash-2.04$ $DJDIR/bin/xdelta-config --libs
126 -L/dev/env/DJDIR/lib -lxdelta -ledsio -lglib
127
128Finally
129-------
130
131If you have any comments or problems with this port, please feel free to
132e-mail me. I hope this port is useful.
133
134Thanks, bye,
135
136Richard Dawe <rich@phekda.freeserve.co.uk> 2001-10-05
diff --git a/xdelta1/doc/Makefile.am b/xdelta1/doc/Makefile.am
deleted file mode 100644
index 062008a..0000000
--- a/xdelta1/doc/Makefile.am
+++ /dev/null
@@ -1,3 +0,0 @@
1man_MANS = xdelta.1
2
3EXTRA_DIST = xdelta.1 xdelta.cat
diff --git a/xdelta1/doc/xdelta.1 b/xdelta1/doc/xdelta.1
deleted file mode 100644
index 7bd0a8c..0000000
--- a/xdelta1/doc/xdelta.1
+++ /dev/null
@@ -1,201 +0,0 @@
1.ds p \&\s-1Xdelta\s0
2.if n .ds - \%--
3.if t .ds - \(em
4.if !\n(.g \{\
5. if !\w|\*(lq| \{\
6. ds lq ``
7. if \w'\(lq' .ds lq "\(lq
8. \}
9. if !\w|\*(rq| \{\
10. ds rq ''
11. if \w'\(rq' .ds rq "\(rq
12. \}
13.\}
14.de PE
15.sp \\n()Pu
16.ne 2
17.nf
18.IP
19..
20.de EP
21.fi
22.PP
23.sp \\n()Pu
24..
25.TH Xdelta 1
26.SH NAME
27xdelta \- Invoke Xdelta
28.SH SYNOPSIS
29.B xdelta
30.I subcommand
31[
32.IR option ".\|.\|.
33] [
34.IR operand .\|.\|.
35]
36.SH DESCRIPTION
37Xdelta provides the ability to generate deltas between a pair of files
38and later apply those deltas. It operates similar to the
39.B diff
40and
41.B patch
42commands, but works on binary files and does not produce a human
43readable output.
44.PP
45
46Xdelta has three subcommands, delta, patch, and info. Delta accepts
47two file versions and produces a delta, while patch accepts the
48original file version and delta and produces the second version. The
49info command prints useful information about a delta. Each subcommand
50will be detailed seperately.
51
52.SS Gzip processing
53Attempting to compute a delta between compressed input files usually
54results in poor compression. This is because small differences
55between the original contents causes changes in the compression of
56whole blocks of data. To simplify things, Xdelta implements a special
57case for
58.IR gzip (1)
59compressed files. If any version input to the delta command is
60recognized as having gzip compression, it will be automatically
61decompressed into a temporary location prior to comparison. This
62temporary location is either the value of the
63.IR TMPDIR
64environment variable, if set, otherwise "/tmp".
65
66The Xdelta patch header contains a flag indicating that the
67reconstructed version should be recompressed after applying the
68patch. In general, this allows Xdelta to operate transparently on
69gzip compressed inputs.
70
71There is one potential problem when automatically processing gzip
72compressed files, which is that the recompressed content does not
73always match byte-for-byte with the original compressed content. The
74uncompressed content still matches, but if there is an external
75integrity check such as cryptographic signature verification, it may
76fail. To prevent this from happening, the --pristine option disables
77automatic gzip processing.
78
79.SS MD5 integrity check
80By default, Xdelta always verifies the MD5 checksum of the files it
81reconstructs. This prevents you from supplying an incorrect input
82during patch, which would result in corrupt output. Because of this
83feature, you can feel confident that patch has produced valid results.
84The --noverify option disables MD5 verification, but this is only
85recommended for performance testing.
86
87.SS Compressed patch format
88Xdelta uses a fairly simple encoding for its delta, then applies zlib
89compression to the result. You should not have to post-compress an
90Xdelta delta.
91
92.SS Delta
93The delta subcommand has the following synopsis:
94
95.B xdelta
96.I delta
97[
98.IR option ".\|.\|.
99]
100.IR fromfile
101.IR tofile
102.IR patchout
103
104Computes a delta from
105.IR fromfile
106to
107.IR tofile
108and writes it to
109.IR patchout
110
111.SS Patch
112The patch subcommand has the following synopsis:
113
114.B xdelta
115.I patch
116[
117.IR option ".\|.\|.
118]
119.IR patchin
120[
121.IR fromfile
122[
123.IR tofile
124]]
125
126Applies
127.IR patchin
128to
129.IR fromfile
130and produces a reconstructed version of
131.IR tofile.
132
133If fromfile was omitted, Xdelta attempts to use the original fromfile
134name, which is stored in the delta. The from file must be identical
135to the one used to create the delta. If its length or MD5 checksum
136differs, patch will abort with an error message.
137
138If tofile was omitted, Xdelta attempts to use the original tofile
139name, which is also stored in the delta. If the original tofile name
140already exists, a unique filename extension will be added to avoid
141destroying any existing data.
142
143.SS Info
144The info subcommand has the following synopsis:
145
146.B xdelta
147.I info
148.IR patchinfo
149
150Prints information about
151.IR patchinfo
152and the version it reconstructs, including file names, lengths, and
153MD5 checksums.
154
155.SS Options
156
157.IP -0..9
158Set the zlib compression level. Zero indicates no compression. Nine
159indicates maximum compression.
160
161.IP "-h, --help"
162Print a short help message and exit.
163
164.IP "-q, --quiet"
165Quiet. Surpresses several warning messages.
166
167.IP "-v, --version"
168Print the Xdelta version number and exit.
169
170.IP "-V, --verbose"
171Verbose. Prints a bit of extra information.
172
173.IP "-n, --noverify"
174No verify. Turns off MD5 checksum verification of the input and
175output files.
176
177.IP "-m=SIZE, --maxmem=SIZE"
178Set an upper bound on the size of an in-memory page cache. For
179example, --maxmem=32M will use a 32 megabyte page cache.
180
181.IP "-s=BLOCK_SIZE"
182Set the block size, unless it was hard coded (20% speed improvement).
183Should be a power of 2.
184
185.IP "-p, --pristine"
186Disable the automatic decompression of gzipped inputs, to prevent
187unexpected differences in the re-compressed content.
188
189.SH RETURN VALUES
190The delta command exits with status 0 to indicate that no differences
191were found, with status 1 to indicate that some differences were
192found, and with status 2 to indicate an error of some kind. The patch
193and info commands exit with status 0 on success and 2 on failure.
194
195.SH IDENTIFICATION
196Author: Joshua P. MacDonald, jmacd@cs.berkeley.edu
197.br
198.\" $Format: "Manual Page Revision: $Revision$; Release Date: $ProjectDate$."$
199Manual Page Revision: 1.6; Release Date: Sun, 28 Jan 2007 10:02:26 -0800.
200.br
201Copyright \(co 1997, 1998, 1999, 2000, 2001
diff --git a/xdelta1/doc/xdelta.cat b/xdelta1/doc/xdelta.cat
deleted file mode 100644
index 7bc1ed6..0000000
--- a/xdelta1/doc/xdelta.cat
+++ /dev/null
@@ -1,138 +0,0 @@
1Xdelta(1) Xdelta(1)
2
3NAME
4 xdelta - Invoke Xdelta
5
6SYNOPSIS
7 xdelta subcommand [ option... ] [ operand... ]
8
9DESCRIPTION
10
11 Xdelta provides the ability to generate deltas between a pair
12 of files and later apply those deltas. It operates similar to
13 the diff and patch commands, but works on binary files and does
14 not produce a human readable output.
15
16 Xdelta has three subcommands, delta, patch, and info. Delta
17 accepts two file versions and produces a delta, while patch
18 accepts the original file version and delta and produces the
19 second version. The info command prints useful information
20 about a delta. Each subcommand will be detailed seperately.
21
22 Gzip processing
23
24 Attempting to compute a delta between compressed input files
25 usually results in poor compression. This is because small
26 differences between the original contents causes changes in the
27 compression of whole blocks of data. To simplify things,
28 Xdelta implements a special case for gzip(1) compressed files.
29 If any version input to the delta command is recognized as
30 having gzip compression, it will be automatically decompressed
31 into a temporary location prior to comparison. This temporary
32 location is either the value of the TMPDIR environment
33 variable, if set, otherwise "/tmp".
34
35 The Xdelta patch header contains a flag indicating that the
36 reconstructed version should be recompressed after applying
37 the patch. In general, this allows Xdelta to operate
38 transparently on gzip compressed inputs.
39
40 There is one potential problem when automatically processing
41 gzip compressed files, which is that the recompressed content
42 does not always match byte-for-byte with the original
43 compressed content. The uncompressed content still matches,
44 but if there is an external integrity check such as
45 cryptographic signature verification, it may fail. To prevent
46 this from happening, the --pristine option disables automatic
47 gzip processing.
48
49 MD5 integrity check
50
51 By default, Xdelta always verifies the MD5 checksum of the
52 files it reconstructs. This prevents you from supplying an
53 incorrect input during patch, which would result in corrupt
54 output. Because of this feature, you can feel confident that
55 patch has produced valid results. The --noverify option
56 disables MD5 verification, but this is only recommended for
57 performance testing.
58
59 Compressed patch format
60
61 Xdelta uses a fairly simple encoding for its delta, then
62 applies zlib compression to the result. You should not have to
63 post-compress an Xdelta delta.
64
65 Delta
66
67 The delta subcommand has the following synopsis:
68
69 xdelta delta [ option... ] fromfile tofile patchout
70
71 Computes a delta from fromfile to tofile and writes it to patchout
72
73 Patch
74
75 The patch subcommand has the following synopsis:
76
77 xdelta patch [ option... ] patchin [ fromfile [ tofile ]]
78
79 Applies patchin to fromfile and produces a reconstructed
80 version of tofile.
81
82 If fromfile was omitted, Xdelta attempts to use the original
83 fromfile name, which is stored in the delta. The from file
84 must be identical to the one used to create the delta. If its
85 length or MD5 checksum differs, patch will abort with an error
86 message.
87
88 If tofile was omitted, Xdelta attempts to use the original
89 tofile name, which is also stored in the delta. If the
90 original tofile name already exists, a unique filename
91 extension will be added to avoid destroying any existing data.
92
93 Info
94 The info subcommand has the following synopsis:
95
96 xdelta info patchinfo
97
98 Prints information about patchinfo and the version it
99 reconstructs, including file names, lengths, and MD5 checksums.
100
101 Options
102 -0..9 Set the zlib compression level. Zero indicates no
103 compression. Nine indicates maximum compression.
104
105 -h, --help
106 Print a short help message and exit.
107
108 -q, --quiet
109 Quiet. Surpresses several warning messages.
110
111 -v, --version
112 Print the Xdelta version number and exit.
113
114 -V, --verbose
115 Verbose. Prints a bit of extra information.
116
117 -n, --noverify
118 No verify. Turns off MD5 checksum verification of the
119 input and output files.
120
121 -m=SIZE, --maxmem=SIZE
122 Set an upper bound on the size of an in-memory page
123 cache. For example, --maxmem=32M will use a 32 megabyte
124 page cache.
125
126 -s=BLOCK_SIZE
127 Set the block size, unless it was hard coded (20% speed
128 improvement). Should be a power of 2.
129
130 -p, --pristine
131 Disable the automatic decompression of gzipped
132 inputs, to prevent unexpected differences in the
133 re-compressed content.
134
135IDENTIFICATION
136 Author: Joshua P. MacDonald, jmacd@cs.berkeley.edu
137 Manual Page Revision: 1.2; Release Date: Mon, 11 Jun 2001 03:39:53 -0700.
138 Copyright © 1997, 1998, 1999, 2000, 2001
diff --git a/xdelta1/getopt.c b/xdelta1/getopt.c
deleted file mode 100644
index 28b8fea..0000000
--- a/xdelta1/getopt.c
+++ /dev/null
@@ -1,749 +0,0 @@
1/* Getopt for GNU.
2 NOTE: getopt is now part of the C library, so if you don't know what
3 "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
4 before changing it!
5
6 Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
7 Free Software Foundation, Inc.
8
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
12 later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22
23/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
24 Ditto for AIX 3.2 and <stdlib.h>. */
25#ifndef _NO_PROTO
26#define _NO_PROTO
27#endif
28
29#ifndef __STDC__
30/* This is a separate conditional since some stdc systems
31 reject `defined (const)'. */
32#ifndef const
33#define const
34#endif
35#endif
36
37#ifdef HAVE_CONFIG_H
38#include <config.h>
39#endif
40
41#include <stdio.h>
42#include <string.h>
43
44/* Comment out all this code if we are using the GNU C Library, and are not
45 actually compiling the library itself. This code is part of the GNU C
46 Library, but also included in many other GNU distributions. Compiling
47 and linking in this code is a waste when using the GNU C library
48 (especially if it is a shared library). Rather than having every GNU
49 program understand `configure --with-gnu-libc' and omit the object files,
50 it is simpler to just do this in the source for each such file. */
51
52#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
53
54
55/* This needs to come after some library #include
56 to get __GNU_LIBRARY__ defined. */
57#ifdef __GNU_LIBRARY__
58/* Don't include stdlib.h for non-GNU C libraries because some of them
59 contain conflicting prototypes for getopt. */
60#include <stdlib.h>
61#endif /* GNU C library. */
62
63/* This version of `getopt' appears to the caller like standard Unix `getopt'
64 but it behaves differently for the user, since it allows the user
65 to intersperse the options with the other arguments.
66
67 As `getopt' works, it permutes the elements of ARGV so that,
68 when it is done, all the options precede everything else. Thus
69 all application programs are extended to handle flexible argument order.
70
71 Setting the environment variable POSIXLY_CORRECT disables permutation.
72 Then the behavior is completely standard.
73
74 GNU application programs can use a third alternative mode in which
75 they can distinguish the relative order of options and other arguments. */
76
77#include "getopt.h"
78
79/* For communication from `getopt' to the caller.
80 When `getopt' finds an option that takes an argument,
81 the argument value is returned here.
82 Also, when `ordering' is RETURN_IN_ORDER,
83 each non-option ARGV-element is returned here. */
84
85char *optarg = NULL;
86
87/* Index in ARGV of the next element to be scanned.
88 This is used for communication to and from the caller
89 and for communication between successive calls to `getopt'.
90
91 On entry to `getopt', zero means this is the first call; initialize.
92
93 When `getopt' returns EOF, this is the index of the first of the
94 non-option elements that the caller should itself scan.
95
96 Otherwise, `optind' communicates from one call to the next
97 how much of ARGV has been scanned so far. */
98
99/* XXX 1003.2 says this must be 1 before any call. */
100int optind = 0;
101
102/* The next char to be scanned in the option-element
103 in which the last option character we returned was found.
104 This allows us to pick up the scan where we left off.
105
106 If this is zero, or a null string, it means resume the scan
107 by advancing to the next ARGV-element. */
108
109static char *nextchar;
110
111/* Callers store zero here to inhibit the error message
112 for unrecognized options. */
113
114int opterr = 1;
115
116/* Set to an option character which was unrecognized.
117 This must be initialized on some systems to avoid linking in the
118 system's own getopt implementation. */
119
120int optopt = '?';
121
122/* Describe how to deal with options that follow non-option ARGV-elements.
123
124 If the caller did not specify anything,
125 the default is REQUIRE_ORDER if the environment variable
126 POSIXLY_CORRECT is defined, PERMUTE otherwise.
127
128 REQUIRE_ORDER means don't recognize them as options;
129 stop option processing when the first non-option is seen.
130 This is what Unix does.
131 This mode of operation is selected by either setting the environment
132 variable POSIXLY_CORRECT, or using `+' as the first character
133 of the list of option characters.
134
135 PERMUTE is the default. We permute the contents of ARGV as we scan,
136 so that eventually all the non-options are at the end. This allows options
137 to be given in any order, even with programs that were not written to
138 expect this.
139
140 RETURN_IN_ORDER is an option available to programs that were written
141 to expect options and other ARGV-elements in any order and that care about
142 the ordering of the two. We describe each non-option ARGV-element
143 as if it were the argument of an option with character code 1.
144 Using `-' as the first character of the list of option characters
145 selects this mode of operation.
146
147 The special argument `--' forces an end of option-scanning regardless
148 of the value of `ordering'. In the case of RETURN_IN_ORDER, only
149 `--' can cause `getopt' to return EOF with `optind' != ARGC. */
150
151static enum
152{
153 REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
154} ordering;
155
156/* Value of POSIXLY_CORRECT environment variable. */
157static char *posixly_correct;
158
159#ifdef __GNU_LIBRARY__
160/* We want to avoid inclusion of string.h with non-GNU libraries
161 because there are many ways it can cause trouble.
162 On some systems, it contains special magic macros that don't work
163 in GCC. */
164#include <string.h>
165#define my_index strchr
166#else
167
168/* Avoid depending on library functions or files
169 whose names are inconsistent. */
170
171char *getenv ();
172
173static char *
174my_index (str, chr)
175 const char *str;
176 int chr;
177{
178 while (*str)
179 {
180 if (*str == chr)
181 return (char *) str;
182 str++;
183 }
184 return 0;
185}
186
187/* If using GCC, we can safely declare strlen this way.
188 If not using GCC, it is ok not to declare it. */
189#ifdef __GNUC__
190/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
191 That was relevant to code that was here before. */
192#ifndef __STDC__
193/* gcc with -traditional declares the built-in strlen to return int,
194 and has done so at least since version 2.4.5. -- rms. */
195extern int strlen (const char *);
196#endif /* not __STDC__ */
197#endif /* __GNUC__ */
198
199#endif /* not __GNU_LIBRARY__ */
200
201/* Handle permutation of arguments. */
202
203/* Describe the part of ARGV that contains non-options that have
204 been skipped. `first_nonopt' is the index in ARGV of the first of them;
205 `last_nonopt' is the index after the last of them. */
206
207static int first_nonopt;
208static int last_nonopt;
209
210/* Exchange two adjacent subsequences of ARGV.
211 One subsequence is elements [first_nonopt,last_nonopt)
212 which contains all the non-options that have been skipped so far.
213 The other is elements [last_nonopt,optind), which contains all
214 the options processed since those non-options were skipped.
215
216 `first_nonopt' and `last_nonopt' are relocated so that they describe
217 the new indices of the non-options in ARGV after they are moved. */
218
219static void
220exchange (argv)
221 char **argv;
222{
223 int bottom = first_nonopt;
224 int middle = last_nonopt;
225 int top = optind;
226 char *tem;
227
228 /* Exchange the shorter segment with the far end of the longer segment.
229 That puts the shorter segment into the right place.
230 It leaves the longer segment in the right place overall,
231 but it consists of two parts that need to be swapped next. */
232
233 while (top > middle && middle > bottom)
234 {
235 if (top - middle > middle - bottom)
236 {
237 /* Bottom segment is the short one. */
238 int len = middle - bottom;
239 register int i;
240
241 /* Swap it with the top part of the top segment. */
242 for (i = 0; i < len; i++)
243 {
244 tem = argv[bottom + i];
245 argv[bottom + i] = argv[top - (middle - bottom) + i];
246 argv[top - (middle - bottom) + i] = tem;
247 }
248 /* Exclude the moved bottom segment from further swapping. */
249 top -= len;
250 }
251 else
252 {
253 /* Top segment is the short one. */
254 int len = top - middle;
255 register int i;
256
257 /* Swap it with the bottom part of the bottom segment. */
258 for (i = 0; i < len; i++)
259 {
260 tem = argv[bottom + i];
261 argv[bottom + i] = argv[middle + i];
262 argv[middle + i] = tem;
263 }
264 /* Exclude the moved top segment from further swapping. */
265 bottom += len;
266 }
267 }
268
269 /* Update records for the slots the non-options now occupy. */
270
271 first_nonopt += (optind - last_nonopt);
272 last_nonopt = optind;
273}
274
275/* Initialize the internal data when the first call is made. */
276
277static const char *
278_getopt_initialize (optstring)
279 const char *optstring;
280{
281 /* Start processing options with ARGV-element 1 (since ARGV-element 0
282 is the program name); the sequence of previously skipped
283 non-option ARGV-elements is empty. */
284
285 first_nonopt = last_nonopt = optind = 1;
286
287 nextchar = NULL;
288
289 posixly_correct = getenv ("POSIXLY_CORRECT");
290
291 /* Determine how to handle the ordering of options and nonoptions. */
292
293 if (optstring[0] == '-')
294 {
295 ordering = RETURN_IN_ORDER;
296 ++optstring;
297 }
298 else if (optstring[0] == '+')
299 {
300 ordering = REQUIRE_ORDER;
301 ++optstring;
302 }
303 else if (posixly_correct != NULL)
304 ordering = REQUIRE_ORDER;
305 else
306 ordering = PERMUTE;
307
308 return optstring;
309}
310
311/* Scan elements of ARGV (whose length is ARGC) for option characters
312 given in OPTSTRING.
313
314 If an element of ARGV starts with '-', and is not exactly "-" or "--",
315 then it is an option element. The characters of this element
316 (aside from the initial '-') are option characters. If `getopt'
317 is called repeatedly, it returns successively each of the option characters
318 from each of the option elements.
319
320 If `getopt' finds another option character, it returns that character,
321 updating `optind' and `nextchar' so that the next call to `getopt' can
322 resume the scan with the following option character or ARGV-element.
323
324 If there are no more option characters, `getopt' returns `EOF'.
325 Then `optind' is the index in ARGV of the first ARGV-element
326 that is not an option. (The ARGV-elements have been permuted
327 so that those that are not options now come last.)
328
329 OPTSTRING is a string containing the legitimate option characters.
330 If an option character is seen that is not listed in OPTSTRING,
331 return '?' after printing an error message. If you set `opterr' to
332 zero, the error message is suppressed but we still return '?'.
333
334 If a char in OPTSTRING is followed by a colon, that means it wants an arg,
335 so the following text in the same ARGV-element, or the text of the following
336 ARGV-element, is returned in `optarg'. Two colons mean an option that
337 wants an optional arg; if there is text in the current ARGV-element,
338 it is returned in `optarg', otherwise `optarg' is set to zero.
339
340 If OPTSTRING starts with `-' or `+', it requests different methods of
341 handling the non-option ARGV-elements.
342 See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
343
344 Long-named options begin with `--' instead of `-'.
345 Their names may be abbreviated as long as the abbreviation is unique
346 or is an exact match for some defined option. If they have an
347 argument, it follows the option name in the same ARGV-element, separated
348 from the option name by a `=', or else the in next ARGV-element.
349 When `getopt' finds a long-named option, it returns 0 if that option's
350 `flag' field is nonzero, the value of the option's `val' field
351 if the `flag' field is zero.
352
353 The elements of ARGV aren't really const, because we permute them.
354 But we pretend they're const in the prototype to be compatible
355 with other systems.
356
357 LONGOPTS is a vector of `struct option' terminated by an
358 element containing a name which is zero.
359
360 LONGIND returns the index in LONGOPT of the long-named option found.
361 It is only valid when a long-named option has been found by the most
362 recent call.
363
364 If LONG_ONLY is nonzero, '-' as well as '--' can introduce
365 long-named options. */
366
367int
368_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
369 int argc;
370 char *const *argv;
371 const char *optstring;
372 const struct option *longopts;
373 int *longind;
374 int long_only;
375{
376 optarg = NULL;
377
378 if (optind == 0)
379 optstring = _getopt_initialize (optstring);
380
381 if (nextchar == NULL || *nextchar == '\0')
382 {
383 /* Advance to the next ARGV-element. */
384
385 if (ordering == PERMUTE)
386 {
387 /* If we have just processed some options following some non-options,
388 exchange them so that the options come first. */
389
390 if (first_nonopt != last_nonopt && last_nonopt != optind)
391 exchange ((char **) argv);
392 else if (last_nonopt != optind)
393 first_nonopt = optind;
394
395 /* Skip any additional non-options
396 and extend the range of non-options previously skipped. */
397
398 while (optind < argc
399 && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
400 optind++;
401 last_nonopt = optind;
402 }
403
404 /* The special ARGV-element `--' means premature end of options.
405 Skip it like a null option,
406 then exchange with previous non-options as if it were an option,
407 then skip everything else like a non-option. */
408
409 if (optind != argc && !strcmp (argv[optind], "--"))
410 {
411 optind++;
412
413 if (first_nonopt != last_nonopt && last_nonopt != optind)
414 exchange ((char **) argv);
415 else if (first_nonopt == last_nonopt)
416 first_nonopt = optind;
417 last_nonopt = argc;
418
419 optind = argc;
420 }
421
422 /* If we have done all the ARGV-elements, stop the scan
423 and back over any non-options that we skipped and permuted. */
424
425 if (optind == argc)
426 {
427 /* Set the next-arg-index to point at the non-options
428 that we previously skipped, so the caller will digest them. */
429 if (first_nonopt != last_nonopt)
430 optind = first_nonopt;
431 return EOF;
432 }
433
434 /* If we have come to a non-option and did not permute it,
435 either stop the scan or describe it to the caller and pass it by. */
436
437 if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
438 {
439 if (ordering == REQUIRE_ORDER)
440 return EOF;
441 optarg = argv[optind++];
442 return 1;
443 }
444
445 /* We have found another option-ARGV-element.
446 Skip the initial punctuation. */
447
448 nextchar = (argv[optind] + 1
449 + (longopts != NULL && argv[optind][1] == '-'));
450 }
451
452 /* Decode the current option-ARGV-element. */
453
454 /* Check whether the ARGV-element is a long option.
455
456 If long_only and the ARGV-element has the form "-f", where f is
457 a valid short option, don't consider it an abbreviated form of
458 a long option that starts with f. Otherwise there would be no
459 way to give the -f short option.
460
461 On the other hand, if there's a long option "fubar" and
462 the ARGV-element is "-fu", do consider that an abbreviation of
463 the long option, just like "--fu", and not "-f" with arg "u".
464
465 This distinction seems to be the most useful approach. */
466
467 if (longopts != NULL
468 && (argv[optind][1] == '-'
469 || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
470 {
471 char *nameend;
472 const struct option *p;
473 const struct option *pfound = NULL;
474 int exact = 0;
475 int ambig = 0;
476 int indfound;
477 int option_index;
478
479 for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
480 /* Do nothing. */ ;
481
482 /* Test all long options for either exact match
483 or abbreviated matches. */
484 for (p = longopts, option_index = 0; p->name; p++, option_index++)
485 if (!strncmp (p->name, nextchar, nameend - nextchar))
486 {
487 if (nameend - nextchar == strlen (p->name))
488 {
489 /* Exact match found. */
490 pfound = p;
491 indfound = option_index;
492 exact = 1;
493 break;
494 }
495 else if (pfound == NULL)
496 {
497 /* First nonexact match found. */
498 pfound = p;
499 indfound = option_index;
500 }
501 else
502 /* Second or later nonexact match found. */
503 ambig = 1;
504 }
505
506 if (ambig && !exact)
507 {
508 if (opterr)
509 fprintf (stderr, "%s: option `%s' is ambiguous\n",
510 argv[0], argv[optind]);
511 nextchar += strlen (nextchar);
512 optind++;
513 return '?';
514 }
515
516 if (pfound != NULL)
517 {
518 option_index = indfound;
519 optind++;
520 if (*nameend)
521 {
522 /* Don't test has_arg with >, because some C compilers don't
523 allow it to be used on enums. */
524 if (pfound->has_arg)
525 optarg = nameend + 1;
526 else
527 {
528 if (opterr)
529 {
530 if (argv[optind - 1][1] == '-')
531 /* --option */
532 fprintf (stderr,
533 "%s: option `--%s' doesn't allow an argument\n",
534 argv[0], pfound->name);
535 else
536 /* +option or -option */
537 fprintf (stderr,
538 "%s: option `%c%s' doesn't allow an argument\n",
539 argv[0], argv[optind - 1][0], pfound->name);
540 }
541 nextchar += strlen (nextchar);
542 return '?';
543 }
544 }
545 else if (pfound->has_arg == 1)
546 {
547 if (optind < argc)
548 optarg = argv[optind++];
549 else
550 {
551 if (opterr)
552 fprintf (stderr, "%s: option `%s' requires an argument\n",
553 argv[0], argv[optind - 1]);
554 nextchar += strlen (nextchar);
555 return optstring[0] == ':' ? ':' : '?';
556 }
557 }
558 nextchar += strlen (nextchar);
559 if (longind != NULL)
560 *longind = option_index;
561 if (pfound->flag)
562 {
563 *(pfound->flag) = pfound->val;
564 return 0;
565 }
566 return pfound->val;
567 }
568
569 /* Can't find it as a long option. If this is not getopt_long_only,
570 or the option starts with '--' or is not a valid short
571 option, then it's an error.
572 Otherwise interpret it as a short option. */
573 if (!long_only || argv[optind][1] == '-'
574 || my_index (optstring, *nextchar) == NULL)
575 {
576 if (opterr)
577 {
578 if (argv[optind][1] == '-')
579 /* --option */
580 fprintf (stderr, "%s: unrecognized option `--%s'\n",
581 argv[0], nextchar);
582 else
583 /* +option or -option */
584 fprintf (stderr, "%s: unrecognized option `%c%s'\n",
585 argv[0], argv[optind][0], nextchar);
586 }
587 nextchar = (char *) "";
588 optind++;
589 return '?';
590 }
591 }
592
593 /* Look at and handle the next short option-character. */
594
595 {
596 char c = *nextchar++;
597 char *temp = my_index (optstring, c);
598
599 /* Increment `optind' when we start to process its last character. */
600 if (*nextchar == '\0')
601 ++optind;
602
603 if (temp == NULL || c == ':')
604 {
605 if (opterr)
606 {
607 if (posixly_correct)
608 /* 1003.2 specifies the format of this message. */
609 fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
610 else
611 fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c);
612 }
613 optopt = c;
614 return '?';
615 }
616 if (temp[1] == ':')
617 {
618 if (temp[2] == ':')
619 {
620 /* This is an option that accepts an argument optionally. */
621 if (*nextchar != '\0')
622 {
623 optarg = nextchar;
624 optind++;
625 }
626 else
627 optarg = NULL;
628 nextchar = NULL;
629 }
630 else
631 {
632 /* This is an option that requires an argument. */
633 if (*nextchar != '\0')
634 {
635 optarg = nextchar;
636 /* If we end this ARGV-element by taking the rest as an arg,
637 we must advance to the next element now. */
638 optind++;
639 }
640 else if (optind == argc)
641 {
642 if (opterr)
643 {
644 /* 1003.2 specifies the format of this message. */
645 fprintf (stderr, "%s: option requires an argument -- %c\n",
646 argv[0], c);
647 }
648 optopt = c;
649 if (optstring[0] == ':')
650 c = ':';
651 else
652 c = '?';
653 }
654 else
655 /* We already incremented `optind' once;
656 increment it again when taking next ARGV-elt as argument. */
657 optarg = argv[optind++];
658 nextchar = NULL;
659 }
660 }
661 return c;
662 }
663}
664
665int
666getopt (argc, argv, optstring)
667 int argc;
668 char *const *argv;
669 const char *optstring;
670{
671 return _getopt_internal (argc, argv, optstring,
672 (const struct option *) 0,
673 (int *) 0,
674 0);
675}
676
677#endif /* _LIBC or not __GNU_LIBRARY__. */
678
679#ifdef TEST
680
681/* Compile with -DTEST to make an executable for use in testing
682 the above definition of `getopt'. */
683
684int
685main (argc, argv)
686 int argc;
687 char **argv;
688{
689 int c;
690 int digit_optind = 0;
691
692 while (1)
693 {
694 int this_option_optind = optind ? optind : 1;
695
696 c = getopt (argc, argv, "abc:d:0123456789");
697 if (c == EOF)
698 break;
699
700 switch (c)
701 {
702 case '0':
703 case '1':
704 case '2':
705 case '3':
706 case '4':
707 case '5':
708 case '6':
709 case '7':
710 case '8':
711 case '9':
712 if (digit_optind != 0 && digit_optind != this_option_optind)
713 printf ("digits occur in two different argv-elements.\n");
714 digit_optind = this_option_optind;
715 printf ("option %c\n", c);
716 break;
717
718 case 'a':
719 printf ("option a\n");
720 break;
721
722 case 'b':
723 printf ("option b\n");
724 break;
725
726 case 'c':
727 printf ("option c with value `%s'\n", optarg);
728 break;
729
730 case '?':
731 break;
732
733 default:
734 printf ("?? getopt returned character code 0%o ??\n", c);
735 }
736 }
737
738 if (optind < argc)
739 {
740 printf ("non-option ARGV-elements: ");
741 while (optind < argc)
742 printf ("%s ", argv[optind++]);
743 printf ("\n");
744 }
745
746 exit (0);
747}
748
749#endif /* TEST */
diff --git a/xdelta1/getopt.h b/xdelta1/getopt.h
deleted file mode 100644
index 45541f5..0000000
--- a/xdelta1/getopt.h
+++ /dev/null
@@ -1,129 +0,0 @@
1/* Declarations for getopt.
2 Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 2, or (at your option) any
7 later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18#ifndef _GETOPT_H
19#define _GETOPT_H 1
20
21#ifdef __cplusplus
22extern "C" {
23#endif
24
25/* For communication from `getopt' to the caller.
26 When `getopt' finds an option that takes an argument,
27 the argument value is returned here.
28 Also, when `ordering' is RETURN_IN_ORDER,
29 each non-option ARGV-element is returned here. */
30
31extern char *optarg;
32
33/* Index in ARGV of the next element to be scanned.
34 This is used for communication to and from the caller
35 and for communication between successive calls to `getopt'.
36
37 On entry to `getopt', zero means this is the first call; initialize.
38
39 When `getopt' returns EOF, this is the index of the first of the
40 non-option elements that the caller should itself scan.
41
42 Otherwise, `optind' communicates from one call to the next
43 how much of ARGV has been scanned so far. */
44
45extern int optind;
46
47/* Callers store zero here to inhibit the error message `getopt' prints
48 for unrecognized options. */
49
50extern int opterr;
51
52/* Set to an option character which was unrecognized. */
53
54extern int optopt;
55
56/* Describe the long-named options requested by the application.
57 The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
58 of `struct option' terminated by an element containing a name which is
59 zero.
60
61 The field `has_arg' is:
62 no_argument (or 0) if the option does not take an argument,
63 required_argument (or 1) if the option requires an argument,
64 optional_argument (or 2) if the option takes an optional argument.
65
66 If the field `flag' is not NULL, it points to a variable that is set
67 to the value given in the field `val' when the option is found, but
68 left unchanged if the option is not found.
69
70 To have a long-named option do something other than set an `int' to
71 a compiled-in constant, such as set a value from `optarg', set the
72 option's `flag' field to zero and its `val' field to a nonzero
73 value (the equivalent single-letter option character, if there is
74 one). For long options that have a zero `flag' field, `getopt'
75 returns the contents of the `val' field. */
76
77struct option
78{
79#if __STDC__
80 const char *name;
81#else
82 char *name;
83#endif
84 /* has_arg can't be an enum because some compilers complain about
85 type mismatches in all the code that assumes it is an int. */
86 int has_arg;
87 int *flag;
88 int val;
89};
90
91/* Names for the values of the `has_arg' field of `struct option'. */
92
93#define no_argument 0
94#define required_argument 1
95#define optional_argument 2
96
97#if __STDC__
98#if defined(__GNU_LIBRARY__)
99/* Many other libraries have conflicting prototypes for getopt, with
100 differences in the consts, in stdlib.h. To avoid compilation
101 errors, only prototype getopt for the GNU C library. */
102extern int getopt (int argc, char *const *argv, const char *shortopts);
103#else /* not __GNU_LIBRARY__ */
104extern int getopt ();
105#endif /* not __GNU_LIBRARY__ */
106extern int getopt_long (int argc, char *const *argv, const char *shortopts,
107 const struct option *longopts, int *longind);
108extern int getopt_long_only (int argc, char *const *argv,
109 const char *shortopts,
110 const struct option *longopts, int *longind);
111
112/* Internal only. Users should not call this directly. */
113extern int _getopt_internal (int argc, char *const *argv,
114 const char *shortopts,
115 const struct option *longopts, int *longind,
116 int long_only);
117#else /* not __STDC__ */
118extern int getopt ();
119extern int getopt_long ();
120extern int getopt_long_only ();
121
122extern int _getopt_internal ();
123#endif /* not __STDC__ */
124
125#ifdef __cplusplus
126}
127#endif
128
129#endif /* _GETOPT_H */
diff --git a/xdelta1/getopt1.c b/xdelta1/getopt1.c
deleted file mode 100644
index 725c653..0000000
--- a/xdelta1/getopt1.c
+++ /dev/null
@@ -1,180 +0,0 @@
1/* getopt_long and getopt_long_only entry points for GNU getopt.
2 Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
3 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
8 later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18
19#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
22
23#include "getopt.h"
24
25#ifndef __STDC__
26/* This is a separate conditional since some stdc systems
27 reject `defined (const)'. */
28#ifndef const
29#define const
30#endif
31#endif
32
33#include <stdio.h>
34
35/* Comment out all this code if we are using the GNU C Library, and are not
36 actually compiling the library itself. This code is part of the GNU C
37 Library, but also included in many other GNU distributions. Compiling
38 and linking in this code is a waste when using the GNU C library
39 (especially if it is a shared library). Rather than having every GNU
40 program understand `configure --with-gnu-libc' and omit the object files,
41 it is simpler to just do this in the source for each such file. */
42
43#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
44
45
46/* This needs to come after some library #include
47 to get __GNU_LIBRARY__ defined. */
48#ifdef __GNU_LIBRARY__
49#include <stdlib.h>
50#else
51char *getenv ();
52#endif
53
54#ifndef NULL
55#define NULL 0
56#endif
57
58int
59getopt_long (argc, argv, options, long_options, opt_index)
60 int argc;
61 char *const *argv;
62 const char *options;
63 const struct option *long_options;
64 int *opt_index;
65{
66 return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
67}
68
69/* Like getopt_long, but '-' as well as '--' can indicate a long option.
70 If an option that starts with '-' (not '--') doesn't match a long option,
71 but does match a short option, it is parsed as a short option
72 instead. */
73
74int
75getopt_long_only (argc, argv, options, long_options, opt_index)
76 int argc;
77 char *const *argv;
78 const char *options;
79 const struct option *long_options;
80 int *opt_index;
81{
82 return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
83}
84
85
86#endif /* _LIBC or not __GNU_LIBRARY__. */
87
88#ifdef TEST
89
90#include <stdio.h>
91
92int
93main (argc, argv)
94 int argc;
95 char **argv;
96{
97 int c;
98 int digit_optind = 0;
99
100 while (1)
101 {
102 int this_option_optind = optind ? optind : 1;
103 int option_index = 0;
104 static struct option long_options[] =
105 {
106 {"add", 1, 0, 0},
107 {"append", 0, 0, 0},
108 {"delete", 1, 0, 0},
109 {"verbose", 0, 0, 0},
110 {"create", 0, 0, 0},
111 {"file", 1, 0, 0},
112 {0, 0, 0, 0}
113 };
114
115 c = getopt_long (argc, argv, "abc:d:0123456789",
116 long_options, &option_index);
117 if (c == EOF)
118 break;
119
120 switch (c)
121 {
122 case 0:
123 printf ("option %s", long_options[option_index].name);
124 if (optarg)
125 printf (" with arg %s", optarg);
126 printf ("\n");
127 break;
128
129 case '0':
130 case '1':
131 case '2':
132 case '3':
133 case '4':
134 case '5':
135 case '6':
136 case '7':
137 case '8':
138 case '9':
139 if (digit_optind != 0 && digit_optind != this_option_optind)
140 printf ("digits occur in two different argv-elements.\n");
141 digit_optind = this_option_optind;
142 printf ("option %c\n", c);
143 break;
144
145 case 'a':
146 printf ("option a\n");
147 break;
148
149 case 'b':
150 printf ("option b\n");
151 break;
152
153 case 'c':
154 printf ("option c with value `%s'\n", optarg);
155 break;
156
157 case 'd':
158 printf ("option d with value `%s'\n", optarg);
159 break;
160
161 case '?':
162 break;
163
164 default:
165 printf ("?? getopt returned character code 0%o ??\n", c);
166 }
167 }
168
169 if (optind < argc)
170 {
171 printf ("non-option ARGV-elements: ");
172 while (optind < argc)
173 printf ("%s ", argv[optind++]);
174 printf ("\n");
175 }
176
177 exit (0);
178}
179
180#endif /* TEST */
diff --git a/xdelta1/libedsio/Makefile.am b/xdelta1/libedsio/Makefile.am
deleted file mode 100644
index 298aa02..0000000
--- a/xdelta1/libedsio/Makefile.am
+++ /dev/null
@@ -1,52 +0,0 @@
1
2INCLUDES = $(GLIB_CFLAGS)
3
4noinst_SCRIPTS = edsio-comp
5
6lib_LTLIBRARIES = libedsio.la
7
8noinst_PROGRAMS = edsiotest
9
10edsiotest_SOURCES = edsiotest.c
11
12edsiotest_LDADD = libedsio.la $(GLIB_LIBS)
13
14noinst_HEADERS = maketime.h partime.h
15
16include_HEADERS = edsio.h edsio_edsio.h
17
18libedsio_la_LIBADD = $(GLIB_LIBS)
19
20libedsio_la_SOURCES = \
21 library.c \
22 simple.c \
23 edsio.c \
24 edsio_edsio.c \
25 sha.c \
26 md5c.c \
27 fh.c \
28 generic.c \
29 default.c \
30 base64.c \
31 maketime.c \
32 partime.c
33
34EXTRA_DIST = edsio.el edsio.ser $(SER_OUT1) edsio-comp.in edsio.prj stamp-ser1
35
36#
37# Rules for the generated code
38#
39
40stamp-ser1: $(top_srcdir)/libedsio/edsio.el edsio.ser
41 $(top_srcdir)/libedsio/edsio-comp edsio.ser
42 touch stamp-ser1
43
44SER_OUT1 = edsio_edsio.c edsio_edsio.h
45
46$(SER_OUT1): stamp-ser1
47
48BUILT_SOURCES = edsio_edsio.c
49
50#
51#
52#
diff --git a/xdelta1/libedsio/base64.c b/xdelta1/libedsio/base64.c
deleted file mode 100644
index c37ddae..0000000
--- a/xdelta1/libedsio/base64.c
+++ /dev/null
@@ -1,525 +0,0 @@
1/* -*-Mode: C;-*-
2 * $Id: base64.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $
3 *
4 * Copyright (C) 1998, 1999, Josh MacDonald.
5 * All Rights Reserved.
6 *
7 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
8 */
9
10#include "edsio.h"
11
12/* BASE64 Encoding
13 */
14
15static const unsigned char base64_table[64] = {
16 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
17 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a',
18 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
19 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2',
20 '3', '4', '5', '6', '7', '8', '9', '+', '/'
21};
22
23static gint16 base64_inverse_table[128];
24
25static void
26init_inverse_table (void)
27{
28 static int i = 0;
29 static int j = 0;
30
31 for (; j < 128; j += 1)
32 base64_inverse_table[j] = -1;
33
34 for (; i < 64; i += 1)
35 base64_inverse_table[base64_table[i]] = i;
36
37 base64_inverse_table['='] = 0;
38}
39
40GByteArray*
41edsio_base64_encode_region (const guint8* data, guint len)
42{
43 GByteArray* out = g_byte_array_new ();
44 guint real_len;
45
46 g_byte_array_set_size (out, (len+2)*4/3);
47
48 real_len = out->len;
49
50 if (! edsio_base64_encode_region_into (data, len, out->data, &real_len))
51 {
52 g_byte_array_free (out, TRUE);
53 return NULL;
54 }
55
56 g_byte_array_set_size (out, real_len);
57
58 return out;
59}
60
61gboolean
62edsio_base64_encode_region_into (const guint8* data, guint len, guint8* out, guint *out_len)
63{
64 gint i;
65 guint32 word = 0, count = 0;
66
67 if ((*out_len) < (len + 2) * 4/3)
68 {
69 edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
70 return FALSE;
71 }
72
73 *out_len = 0;
74
75 for (i = 0; i < len; i += 1)
76 {
77 word |= data[i] << (8*(2-(count++)));
78
79 if (count == 3)
80 {
81 out[(*out_len)++] = base64_table[(word>>18) & 0x3f];
82 out[(*out_len)++] = base64_table[(word>>12) & 0x3f];
83 out[(*out_len)++] = base64_table[(word>> 6) & 0x3f];
84 out[(*out_len)++] = base64_table[(word ) & 0x3f];
85
86 count = 0;
87 word = 0;
88 }
89 }
90
91 if (count > 0)
92 {
93 out[(*out_len)++] = base64_table[(word>>18) & 0x3f];
94 out[(*out_len)++] = base64_table[(word>>12) & 0x3f];
95 out[(*out_len)++] = (count > 1) ? base64_table[(word>>6) & 0x3f] : '=';
96 out[(*out_len)++] = '=';
97 }
98
99 return TRUE;
100}
101
102GByteArray*
103edsio_base64_decode_region (const guint8* data, guint data_len)
104{
105 GByteArray* it = g_byte_array_new ();
106 guint real_len;
107
108 g_byte_array_set_size (it, data_len*3/4);
109
110 real_len = it->len;
111
112 if (! edsio_base64_decode_region_into (data, data_len, it->data, &real_len))
113 {
114 g_byte_array_free (it, TRUE);
115 return NULL;
116 }
117
118 g_byte_array_set_size (it, real_len);
119
120 return it;
121}
122
123gboolean
124edsio_base64_decode_region_into (const guint8* data, guint len, guint8* out, guint *out_len)
125{
126 guint32 pos = 0;
127 gboolean found_end = FALSE;
128 gint found_end_at = 0;
129
130 init_inverse_table ();
131
132 if ((*out_len) < (len*3/4))
133 {
134 edsio_generate_void_event (EC_EdsioOutputBufferShort);
135 return FALSE;
136 }
137
138 (*out_len) = 0;
139
140 while (pos < len)
141 {
142 gint i, x;
143 gint word = 0, junk = 0;
144
145 if (len - pos < 4)
146 {
147 edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
148 return FALSE;
149 }
150
151 for (i = 0; i < 4; i += 1)
152 {
153 x = data[pos++];
154
155 if (x > 127 || base64_inverse_table[x] < 0)
156 {
157 edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
158 return FALSE;
159 }
160
161 if (x == '=')
162 {
163 if (! found_end)
164 found_end_at = i;
165
166 found_end = TRUE;
167 }
168 else
169 {
170 if (found_end)
171 {
172 edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
173 return FALSE;
174 }
175
176 word |= base64_inverse_table[x] << (6*(3-i));
177 }
178 }
179
180 if (found_end)
181 {
182 if (found_end_at < 2)
183 {
184 edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
185 return FALSE;
186 }
187
188 if (found_end_at == 2)
189 junk = 2;
190 else if (found_end_at == 3)
191 junk = 1;
192 }
193 else
194 junk = 0;
195
196 out[(*out_len)++] = (word >> 16) & 0xff;
197
198 if (junk < 2)
199 out[(*out_len)++] = (word >> 8) & 0xff;
200
201 if (junk < 1)
202 out[(*out_len)++] = (word >> 0) & 0xff;
203 }
204
205 return TRUE;
206}
207
208/* Base64 sink
209 */
210typedef struct _Base64Sink Base64Sink;
211
212static gboolean base64_sink_close (SerialSink* sink);
213static gboolean base64_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len);
214static void base64_sink_free (SerialSink* sink);
215static gboolean base64_sink_quantum (SerialSink* sink);
216
217struct _Base64Sink
218{
219 SerialSink sink;
220
221 SerialSink* out;
222
223 guint32 word;
224 guint32 count;
225};
226
227SerialSink*
228serializeio_base64_sink (SerialSink* out)
229{
230 Base64Sink* it = g_new0 (Base64Sink, 1);
231 SerialSink* sink = (SerialSink*) it;
232
233 serializeio_sink_init (sink,
234 NULL,
235 base64_sink_close,
236 base64_sink_write,
237 base64_sink_free,
238 base64_sink_quantum);
239
240 it->out = out;
241
242 return sink;
243}
244
245gboolean
246base64_sink_write (SerialSink* fsink, const guint8 *ptr, guint32 len)
247{
248 guint32 i;
249
250 Base64Sink* sink = (Base64Sink*) fsink;
251
252 for (i = 0; i < len; )
253 {
254 if (sink->count == 3)
255 {
256 guint8 out[4];
257
258 out[0] = base64_table[(sink->word>>18) & 0x3f];
259 out[1] = base64_table[(sink->word>>12) & 0x3f];
260 out[2] = base64_table[(sink->word>> 6) & 0x3f];
261 out[3] = base64_table[(sink->word ) & 0x3f];
262
263#if 0
264 g_print ("%02x %02x %02x -> %c%c%c%c (3)\n",
265 (sink->word>>16) & 0xff,
266 (sink->word>>8) & 0xff,
267 (sink->word>>0) & 0xff,
268 out[0],
269 out[1],
270 out[2],
271 out[3]);
272#endif
273
274 if (! sink->out->sink_write (sink->out, out, 4))
275 return FALSE;
276
277 sink->count = 0;
278 sink->word = 0;
279 }
280
281 while (sink->count < 3 && i < len)
282 sink->word |= ptr[i++] << (8*(2-(sink->count++)));
283 }
284
285 return TRUE;
286}
287
288gboolean
289base64_sink_close (SerialSink* fsink)
290{
291 Base64Sink* sink = (Base64Sink*) fsink;
292
293 if (sink->count == 3)
294 {
295 guint8 out[4];
296
297 out[0] = base64_table[(sink->word>>18) & 0x3f];
298 out[1] = base64_table[(sink->word>>12) & 0x3f];
299 out[2] = base64_table[(sink->word>> 6) & 0x3f];
300 out[3] = base64_table[(sink->word ) & 0x3f];
301
302#if 0
303 g_print ("%02x %02x %02x -> %c%c%c%c (3)\n",
304 (sink->word>>16) & 0xff,
305 (sink->word>>8) & 0xff,
306 (sink->word>>0) & 0xff,
307 out[0],
308 out[1],
309 out[2],
310 out[3]);
311#endif
312
313 if (! sink->out->sink_write (sink->out, out, 4))
314 return FALSE;
315
316 sink->count = 0;
317 sink->word = 0;
318 }
319
320 if (sink->count > 0)
321 {
322 guint8 out[4];
323
324 out[0] = base64_table[(sink->word>>18) & 0x3f];
325 out[1] = base64_table[(sink->word>>12) & 0x3f];
326 out[2] = (sink->count > 1) ? base64_table[(sink->word>>6) & 0x3f] : '=';
327 out[3] = '=';
328
329#if 0
330 g_print ("%02x %02x %02x -> %c%c%c%c (%d)\n",
331 (sink->word>>16) & 0xff,
332 (sink->word>>8) & 0xff,
333 (sink->word>>0) & 0xff,
334 out[0],
335 out[1],
336 out[2],
337 out[3],
338 sink->count);
339#endif
340
341 if (! sink->out->sink_write (sink->out, out, 4))
342 return FALSE;
343
344 sink->count = 0;
345 sink->word = 0;
346 }
347
348 return sink->out->sink_close (sink->out);
349}
350
351
352void
353base64_sink_free (SerialSink* fsink)
354{
355 Base64Sink* sink = (Base64Sink*) fsink;
356
357 sink->out->sink_free (sink->out);
358
359 g_free (sink);
360}
361
362gboolean
363base64_sink_quantum (SerialSink* fsink)
364{
365 Base64Sink* sink = (Base64Sink*) fsink;
366
367 if (sink->out->sink_quantum)
368 return sink->out->sink_quantum (sink->out);
369
370 return TRUE;
371}
372
373/* Base64 source
374 */
375
376typedef struct _Base64Source Base64Source;
377
378struct _Base64Source {
379 SerialSource source;
380
381 SerialSource *in;
382
383 guint32 avail;
384 guint32 count;
385 gboolean found_end;
386 gint found_end_at;
387 guint8 buf[3];
388};
389
390static gboolean base64_source_close (SerialSource* source);
391static gboolean base64_source_read (SerialSource* source, guint8 *ptr, guint32 len);
392static void base64_source_free (SerialSource* source);
393
394SerialSource*
395serializeio_base64_source (SerialSource* in0)
396{
397 Base64Source* it = g_new0 (Base64Source, 1);
398 SerialSource* source = (SerialSource*) it;
399
400 serializeio_source_init (source,
401 NULL,
402 base64_source_close,
403 base64_source_read,
404 base64_source_free,
405 NULL,
406 NULL);
407
408 it->in = in0;
409
410 return source;
411}
412
413gboolean
414base64_source_close (SerialSource* fsource)
415{
416 Base64Source* source = (Base64Source*) fsource;
417
418 if (! source->in->source_close (source->in))
419 return FALSE;
420
421 return TRUE;
422}
423
424gboolean
425base64_source_read (SerialSource* fsource, guint8 *ptr, guint32 len)
426{
427 guint32 pos;
428 Base64Source* source = (Base64Source*) fsource;
429
430 init_inverse_table ();
431
432 for (pos = 0; pos < len; )
433 {
434 if (source->count == 0)
435 {
436 guint8 buf[4];
437 guint32 i, word = 0, junk;
438
439 if (source->found_end)
440 {
441 edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
442 return FALSE;
443 }
444
445 if (! source->in->source_read (source->in, buf, 4))
446 return FALSE;
447
448 for (i = 0; i < 4; i += 1)
449 {
450 gint x = buf[i];
451
452 if (x > 127 || base64_inverse_table[x] < 0)
453 {
454 edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
455 return FALSE;
456 }
457
458 if (x == '=')
459 {
460 if (! source->found_end)
461 source->found_end_at = i;
462
463 source->found_end = TRUE;
464 }
465 else
466 {
467 if (source->found_end)
468 {
469 edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
470 return FALSE;
471 }
472
473 word |= base64_inverse_table[x] << (6*(3-i));
474 }
475 }
476
477 if (source->found_end)
478 {
479 if (source->found_end_at == 2)
480 junk = 2;
481 else if (source->found_end_at == 3)
482 junk = 1;
483 else
484 {
485 edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
486 return FALSE;
487 }
488 }
489 else
490 junk = 0;
491
492 source->avail = source->count = 3 - junk;
493
494 source->buf[0] = (word >> 16) & 0xff;
495 source->buf[1] = (word >> 8) & 0xff;
496 source->buf[2] = (word >> 0) & 0xff;
497
498#if 0
499 g_print ("%c%c%c%c -> %02x %02x %02x (%d)\n",
500 buf[0],
501 buf[1],
502 buf[2],
503 buf[3],
504 (word>>16) & 0xff,
505 (word>>8) & 0xff,
506 (word>>0) & 0xff,
507 3-junk);
508#endif
509 }
510
511 ptr[pos++] = source->buf[source->avail-(source->count--)];
512 }
513
514 return TRUE;
515}
516
517void
518base64_source_free (SerialSource* fsource)
519{
520 Base64Source* source = (Base64Source*) fsource;
521
522 source->in->source_free (source->in);
523
524 g_free (source);
525}
diff --git a/xdelta1/libedsio/default.c b/xdelta1/libedsio/default.c
deleted file mode 100644
index 0da2176..0000000
--- a/xdelta1/libedsio/default.c
+++ /dev/null
@@ -1,343 +0,0 @@
1/* -*-Mode: C;-*-
2 * $Id: default.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $
3 *
4 * Copyright (C) 1998, 1999, Josh MacDonald.
5 * All Rights Reserved.
6 *
7 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
8 */
9
10#include "edsio.h"
11
12/* Default Sink methods
13 */
14
15static gboolean
16sink_type_default (SerialSink* sink, SerialType type, guint32 len, gboolean set_allocation)
17{
18 if (! sink->next_uint32 (sink, type))
19 return FALSE;
20
21 /* Note: set_allocation is deprecated in 1.1.4 */
22 if (set_allocation && !sink->next_uint32 (sink, len))
23 return FALSE;
24
25 return TRUE;
26}
27
28static gboolean
29sink_next_uint16 (SerialSink* sink, guint16 num)
30{
31 num = g_htons (num);
32
33 return sink->sink_write (sink, (guint8*) &num, sizeof (num));
34}
35
36static gboolean
37sink_next_uint32 (SerialSink* sink, guint32 num)
38{
39 num = g_htonl (num);
40
41 return sink->sink_write (sink, (guint8*) &num, sizeof (num));
42}
43
44static gboolean
45sink_next_uint (SerialSink* sink, guint32 num)
46{
47 /* This is mostly because I dislike endian, and less to save space
48 * on small ints. However, the uint32 and uint16 functions are used
49 * when the number is expected to be large, in which case this
50 * format can expand the number. */
51
52 guint8 sink_buf[16]; /* this is enough room for a 12-byte int */
53 guint sink_count = 0;
54
55 do
56 {
57 guint left = num & 0x7f;
58 guint outnum;
59
60 num >>= 7;
61
62 outnum = left | (num ? 0x80 : 0);
63
64 sink_buf[sink_count++] = outnum;
65 }
66 while (num);
67
68 return sink->sink_write (sink, sink_buf, sink_count);
69}
70
71static gboolean
72sink_next_uint8 (SerialSink* sink, guint8 val)
73{
74 return sink->sink_write (sink, &val, 1);
75}
76
77static gboolean
78sink_next_bool (SerialSink* sink, gboolean val)
79{
80 guint8 sink_buf[1];
81 sink_buf[0] = val;
82 return sink->sink_write (sink, sink_buf, 1);
83}
84
85static gboolean
86sink_next_string (SerialSink* sink, const char *ptr)
87{
88 return sink->next_bytes (sink, ptr, strlen (ptr));
89}
90
91static gboolean
92sink_next_bytes (SerialSink* sink, const guint8 *ptr, guint32 len)
93{
94 return sink->next_uint (sink, len) &&
95 sink->sink_write (sink, ptr, len);
96}
97
98static gboolean
99sink_next_bytes_known (SerialSink* sink, const guint8 *ptr, guint32 len)
100{
101 return sink->sink_write (sink, ptr, len);
102}
103
104void
105serializeio_sink_init (SerialSink* it,
106 gboolean (* sink_type) (SerialSink* sink,
107 SerialType type,
108 guint32 mem_size,
109 gboolean set_allocation),
110 gboolean (* sink_close) (SerialSink* sink),
111 gboolean (* sink_write) (SerialSink* sink,
112 const guint8 *ptr,
113 guint32 len),
114 void (* sink_free) (SerialSink* sink),
115 gboolean (* sink_quantum) (SerialSink* sink))
116{
117 it->next_bytes_known = sink_next_bytes_known;
118 it->next_bytes = sink_next_bytes;
119 it->next_uint = sink_next_uint;
120 it->next_uint32 = sink_next_uint32;
121 it->next_uint16 = sink_next_uint16;
122 it->next_uint8 = sink_next_uint8;
123 it->next_bool = sink_next_bool;
124 it->next_string = sink_next_string;
125
126 if (sink_type)
127 it->sink_type = sink_type;
128 else
129 it->sink_type = sink_type_default;
130
131 it->sink_close = sink_close;
132 it->sink_write = sink_write;
133 it->sink_free = sink_free;
134 it->sink_quantum = sink_quantum;
135}
136
137/* Default Source methods
138 */
139
140static SerialType
141source_type_default (SerialSource* source, gboolean set_allocation)
142{
143 guint32 x;
144
145 if (! source->next_uint32 (source, & x))
146 return ST_Error;
147
148 if (set_allocation)
149 {
150 /* Note: set_allocation is deprecated in 1.1.4 */
151 guint32 bogus;
152 if (! source->next_uint32 (source, &bogus))
153 return ST_Error;
154 }
155
156 return x;
157}
158
159static gboolean
160source_next_uint32 (SerialSource* source, guint32 *ptr)
161{
162 guint32 x;
163
164 if (! source->source_read (source, (guint8*) &x, sizeof (x)))
165 return FALSE;
166
167 (*ptr) = g_ntohl (x);
168
169 return TRUE;
170}
171
172static gboolean
173source_next_uint16 (SerialSource* source, guint16 *ptr)
174{
175 guint16 x;
176
177 if (! source->source_read (source, (guint8*) &x, sizeof (x)))
178 return FALSE;
179
180 (*ptr) = g_ntohs (x);
181
182 return TRUE;
183}
184
185static gboolean
186source_next_uint (SerialSource* source, guint32 *ptr)
187{
188 /* This is mostly because I dislike endian, and less to save space
189 * on small ints */
190 guint8 c;
191 guint8 arr[16];
192 gint i = 0;
193 gint donebit = 1;
194 gint bits;
195
196 while (source->next_uint8 (source, &c))
197 {
198 donebit = c & 0x80;
199 bits = c & 0x7f;
200
201 arr[i++] = bits;
202
203 if (!donebit)
204 break;
205 }
206
207 if (donebit)
208 return FALSE;
209
210 *ptr = 0;
211
212 for (i -= 1; i >= 0; i -= 1)
213 {
214 *ptr <<= 7;
215 *ptr |= arr[i];
216 }
217
218 return TRUE;
219}
220
221static gboolean
222source_next_uint8 (SerialSource* source, guint8 *ptr)
223{
224 return source->source_read (source, ptr, 1);
225}
226
227static gboolean
228source_next_bool (SerialSource* source, gboolean *ptr)
229{
230 guint8 sink_buf[1];
231
232 if (! source->source_read (source, sink_buf, 1))
233 return FALSE;
234
235 if (sink_buf[0])
236 *ptr = TRUE;
237 else
238 *ptr = FALSE;
239
240 return TRUE;
241}
242
243static gboolean
244source_next_string (SerialSource* source, const char **ptr)
245{
246 guint32 len;
247 guint8* buf;
248
249 if (! source->next_uint (source, &len))
250 return FALSE;
251
252 if (! (buf = serializeio_source_alloc (source, len+1)))
253 return FALSE;
254
255 buf[len] = 0;
256
257 (*ptr) = buf;
258
259 return source->source_read (source, buf, len);
260}
261
262static gboolean
263source_next_bytes (SerialSource* source, const guint8 **ptr, guint32 *len_ptr)
264{
265 guint32 len;
266 guint8* buf;
267
268 if (! source->next_uint (source, &len))
269 return FALSE;
270
271 if (! (buf = serializeio_source_alloc (source, len)))
272 return FALSE;
273
274 (*len_ptr) = len;
275 (*ptr) = buf;
276
277 return source->source_read (source, buf, len);
278}
279
280static gboolean
281source_next_bytes_known (SerialSource* source, guint8 *ptr, guint32 len)
282{
283 return source->source_read (source, ptr, len);
284}
285
286void*
287serializeio_source_alloc (SerialSource* source, guint32 len)
288{
289 AllocList *al;
290 void* ret;
291
292 if (source->salloc_func)
293 {
294 ret = source->salloc_func (source, len);
295 al = source->salloc_func (source, sizeof(AllocList));
296 }
297 else
298 {
299 ret = g_malloc0 (len);
300 al = g_malloc0 (sizeof(AllocList));
301 }
302
303 al->ptr = ret;
304 al->next = source->alloc_list;
305 source->alloc_list = al;
306
307 return ret;
308}
309
310void
311serializeio_source_init (SerialSource* it,
312 SerialType (* source_type) (SerialSource* source,
313 gboolean set_allocation),
314 gboolean (* source_close) (SerialSource* source),
315 gboolean (* source_read) (SerialSource* source,
316 guint8 *ptr,
317 guint32 len),
318 void (* source_free) (SerialSource* source),
319 void* (* salloc_func) (SerialSource* source,
320 guint32 len),
321 void (* sfree_func) (SerialSource* source,
322 void* ptr))
323{
324 it->alloc_list = NULL;
325 it->next_bytes_known = source_next_bytes_known;
326 it->next_bytes = source_next_bytes;
327 it->next_uint = source_next_uint;
328 it->next_uint32 = source_next_uint32;
329 it->next_uint16 = source_next_uint16;
330 it->next_uint8 = source_next_uint8;
331 it->next_bool = source_next_bool;
332 it->next_string = source_next_string;
333
334 if (source_type != NULL)
335 it->source_type = source_type;
336 else
337 it->source_type = source_type_default;
338 it->source_close = source_close;
339 it->source_read = source_read;
340 it->source_free = source_free;
341 it->salloc_func = salloc_func;
342 it->sfree_func = sfree_func;
343}
diff --git a/xdelta1/libedsio/edsio-comp.in b/xdelta1/libedsio/edsio-comp.in
deleted file mode 100644
index 51b55d7..0000000
--- a/xdelta1/libedsio/edsio-comp.in
+++ /dev/null
@@ -1,46 +0,0 @@
1#!/bin/sh
2
3# Derived from:
4
5# Copyright (C) 1995 Free Software Foundation, Inc.
6# François Pinard <pinard@iro.umontreal.ca>, 1995.
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2, or (at your option)
11# any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22EMACS=@EMACS@
23TOP_SRCDIR=@top_srcdir_absolute@/libedsio
24
25SCRIPT=$TMPDIR/script.$$
26
27trap "rm -f $SCRIPT" 0
28
29if test $# != 1; then
30 echo 1>&2 "usage: $0 INPUT"
31 exit 1
32else
33 if test -z "$EMACS" || test "$EMACS" = "t"; then
34 # Value of "t" means we are running in a shell under Emacs.
35 # Just assume Emacs is called "emacs".
36 EMACS=emacs
37 fi
38
39 INPUT=$1
40 INPUT_PREF=`echo $INPUT | sed 's/\.[^\.]*$//'`
41
42 echo "(load-file \"$TOP_SRCDIR/edsio.el\") " \
43 "(generate-ser \"$INPUT\" \"$INPUT_PREF\")" > $SCRIPT
44
45 $EMACS --batch -l $SCRIPT
46fi
diff --git a/xdelta1/libedsio/edsio.c b/xdelta1/libedsio/edsio.c
deleted file mode 100644
index 4d110f6..0000000
--- a/xdelta1/libedsio/edsio.c
+++ /dev/null
@@ -1,1610 +0,0 @@
1/* -*-Mode: C;-*-
2 * $Id: edsio.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $
3 *
4 * Copyright (C) 1998, 1999, Josh MacDonald.
5 * All Rights Reserved.
6 *
7 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
8 */
9
10#include "edsio.h"
11#include <stdio.h>
12
13#if TIME_WITH_SYS_TIME
14# include <sys/time.h>
15# include <time.h>
16#else
17# if HAVE_SYS_TIME_H
18# include <sys/time.h>
19# else
20# include <time.h>
21# endif
22#endif
23
24#include "maketime.h"
25
26/*#define DEBUG_PROPS*/
27
28/* Event delivery
29 */
30
31static GHashTable* all_event_defs = NULL;
32
33static GPtrArray* all_event_watchers = NULL;
34
35typedef struct _ErrorDeliveryWatcher ErrorDeliveryWatcher;
36typedef struct _DelayedEvent DelayedEvent;
37
38struct _ErrorDeliveryWatcher {
39 ErrorDeliveryFunc deliver;
40};
41
42struct _DelayedEvent {
43 GenericEvent ev;
44 GenericEventDef *def;
45 const char *msg;
46};
47
48void
49eventdelivery_initialize_event_def (gint code,
50 gint level,
51 gint flags,
52 const char* name,
53 const char* oneline,
54 const char * (* field_to_string) (GenericEvent* ev, gint field))
55{
56 GenericEventDef* def = g_new0 (GenericEventDef, 1);
57
58 if (! all_event_defs)
59 all_event_defs = g_hash_table_new (g_int_hash, g_int_equal);
60
61 def->code = code;
62 def->level = level;
63 def->flags = flags;
64 def->name = name;
65 def->oneline = oneline;
66 def->field_to_string = field_to_string;
67
68 g_hash_table_insert (all_event_defs, & def->code, def);
69}
70
71void
72eventdelivery_event_watch_all (ErrorDeliveryFunc func)
73{
74 ErrorDeliveryWatcher* w = g_new0 (ErrorDeliveryWatcher, 1);
75
76 w->deliver = func;
77
78 if (! all_event_watchers)
79 all_event_watchers = g_ptr_array_new ();
80
81 g_ptr_array_add (all_event_watchers, w);
82}
83
84GenericEventDef*
85eventdelivery_event_lookup (gint code)
86{
87 return g_hash_table_lookup (all_event_defs, & code);
88}
89
90void
91eventdelivery_event_deliver (GenericEvent* e)
92{
93 static gint in_call = FALSE;
94 static GQueue* queued = NULL;
95 static GPtrArray* free_strings = NULL;
96
97 if (! queued)
98 {
99 queued = g_queue_new ();
100 free_strings = g_ptr_array_new ();
101 }
102
103 in_call += 1;
104
105 g_assert (e);
106
107 edsio_edsio_init ();
108
109 if (all_event_defs)
110 {
111 GenericEventDef* def = g_hash_table_lookup (all_event_defs, & e->code);
112
113 if (def)
114 {
115 GString* out;
116 const char* oneline = def->oneline;
117 char c;
118
119 out = g_string_new (NULL);
120
121 while ((c = *oneline++))
122 {
123 switch (c)
124 {
125 case '$':
126 {
127 const char* field;
128 char *end;
129 int f;
130
131 if ((*oneline++) != '{')
132 goto badevent;
133
134 f = strtol (oneline, &end, 10);
135
136 if (f < 0 || !end || end[0] != '}')
137 goto badevent;
138
139 oneline = end+1;
140
141 g_assert (def->field_to_string);
142
143 field = def->field_to_string (e, f);
144
145 if (field)
146 {
147 g_string_append (out, field);
148
149 g_free ((void*) field);
150 }
151 else
152 goto badevent;
153 }
154 break;
155 default:
156 g_string_append_c (out, c);
157 }
158 }
159
160 if (! all_event_watchers)
161 {
162 fprintf (stderr, "%s:%d: %s\n", e->srcfile, e->srcline, out->str);
163
164 g_string_free (out, TRUE);
165 }
166 else if (in_call == 1)
167 {
168 gint i;
169
170 for (i = 0; i < all_event_watchers->len; i += 1)
171 {
172 ErrorDeliveryWatcher* w = all_event_watchers->pdata[i];
173
174 if (! w->deliver (e, def, out->str))
175 {
176 g_warning ("%s:%d: An error delivery routine failed: %s\n", e->srcfile, e->srcline, out->str);
177 in_call = 0;
178 return;
179 }
180 }
181
182 while (g_queue_get_size (queued) > 0)
183 {
184 DelayedEvent* de = g_queue_pop (queued);
185
186 for (i = 0; i < all_event_watchers->len; i += 1)
187 {
188 ErrorDeliveryWatcher* w = all_event_watchers->pdata[i];
189
190 if (! w->deliver (& de->ev, de->def, de->msg))
191 {
192 g_warning ("%s:%d: An error delivery routine failed: %s\n", e->srcfile, e->srcline, out->str);
193 in_call = 0;
194 return;
195 }
196 }
197 }
198
199 for (i = 0; i < free_strings->len; i += 1)
200 g_string_free (free_strings->pdata[i], TRUE);
201
202 g_ptr_array_set_size (free_strings, 0);
203
204 g_string_free (out, TRUE);
205 }
206 else
207 {
208 DelayedEvent* de = g_new (DelayedEvent, 1);
209
210 de->ev = *e;
211 de->def = def;
212 de->msg = out->str;
213
214 g_queue_push (queued, de);
215
216 g_ptr_array_add (free_strings, out);
217 }
218
219 in_call -= 1;
220
221 return;
222 }
223 }
224
225 g_warning ("%s:%d: Unrecognized event delivered (code=%d)\n", e->srcfile, e->srcline, e->code);
226
227 in_call -= 1;
228
229 return;
230
231 badevent:
232
233 g_warning ("%s:%d: An malformed error could not print here (code=%d)\n", e->srcfile, e->srcline, e->code);
234
235 in_call -= 1;
236
237 return;
238}
239
240const char*
241eventdelivery_int_to_string (int x)
242{
243 return g_strdup_printf ("%d", x);
244}
245
246const char*
247eventdelivery_string_to_string (const char* x)
248{
249 return g_strdup (x);
250}
251
252const char*
253eventdelivery_source_to_string (SerialSource* x)
254{
255 return g_strdup ("@@@SerialSource");
256}
257
258const char*
259eventdelivery_sink_to_string (SerialSink* x)
260{
261 return g_strdup ("@@@SerialSink");
262}
263
264const char*
265eventdelivery_handle_to_string (FileHandle* x)
266{
267 g_return_val_if_fail (x, g_strdup ("*error*"));
268
269 return x->table->table_handle_name (x);
270}
271
272/* Misc crap.
273 */
274
275gboolean
276edsio_time_of_day (SerialGenericTime* setme)
277{
278#if HAVE_GETTIMEOFDAY
279
280 struct timeval tv;
281
282 if (gettimeofday (& tv, NULL))
283 {
284 edsio_generate_errno_event (EC_EdsioGetTimeOfDayFailure);
285 goto bail;
286 }
287
288 if (setme)
289 {
290 setme->nanos = tv.tv_usec * 1000;
291 setme->seconds = tv.tv_sec;
292 }
293
294#else
295
296 struct timeval tv;
297 time_t t = time (NULL);
298
299 if (t < 0)
300 {
301 edsio_generate_errno_event (EC_EdsioTimeFailure);
302 goto bail;
303 }
304
305 if (setme)
306 {
307 setme->nanos = 0;
308 setme->seconds = tv.tv_sec;
309 }
310
311#endif
312
313 return TRUE;
314
315 bail:
316
317 setme->nanos = 0;
318 setme->seconds = 10;
319
320 return FALSE;
321}
322
323gchar*
324edsio_time_to_iso8601 (SerialGenericTime *tp)
325{
326 return edsio_time_t_to_iso8601 (tp->seconds);
327}
328
329gchar*
330edsio_time_t_to_iso8601 (GTime t0)
331{
332 static char timebuf[64];
333 time_t t = t0;
334
335 struct tm lt = *localtime(&t);
336 int utc_offset = difftm(&lt, gmtime(&t));
337 char sign = utc_offset < 0 ? '-' : '+';
338 int minutes = abs (utc_offset) / 60;
339 int hours = minutes / 60;
340
341 sprintf(timebuf,
342 "%d-%02d-%02d %02d:%02d:%02d%c%02d%02d",
343 lt.tm_year + 1900,
344 lt.tm_mon + 1,
345 lt.tm_mday,
346 lt.tm_hour,
347 lt.tm_min,
348 lt.tm_sec,
349 sign,
350 hours,
351 minutes % 60);
352
353 return timebuf;
354}
355
356static gboolean
357strtosl_checked (const char* str, long* l, const char* errmsg)
358{
359 char* end;
360
361 (*l) = strtol (str, &end, 10);
362
363 if (!end || end[0])
364 {
365 if (errmsg)
366 edsio_generate_stringstring_event (EC_EdsioInvalidIntegerString, errmsg, str);
367
368 (*l) = 0;
369 return FALSE;
370 }
371
372 return TRUE;
373}
374
375gboolean
376strtosi_checked (const char* str, gint32* i, const char* errmsg)
377{
378 long l;
379
380 if (! strtosl_checked (str, &l, errmsg))
381 {
382 (*i) = 0;
383 return FALSE;
384 }
385
386 if (l > G_MAXINT || l < G_MININT)
387 {
388 if (errmsg)
389 edsio_generate_stringstring_event (EC_EdsioIntegerOutOfRange, errmsg, str);
390
391 (*i) = 0;
392 return FALSE;
393 }
394
395 (*i) = l;
396
397 return TRUE;
398}
399
400gboolean
401strtoss_checked (const char* str, gint16* i, const char* errmsg)
402{
403 long l;
404
405 if (! strtosl_checked (str, &l, errmsg))
406 {
407 (*i) = 0;
408 return FALSE;
409 }
410
411 if (l > G_MAXSHORT || l < G_MINSHORT)
412 {
413 if (errmsg)
414 edsio_generate_stringstring_event (EC_EdsioIntegerOutOfRange, errmsg, str);
415
416 (*i) = 0;
417 return FALSE;
418 }
419
420 (*i) = l;
421
422 return TRUE;
423}
424
425gboolean
426strtoui_checked (const char* str, guint32* i, const char* errmsg)
427{
428 long l;
429
430 if (! strtosl_checked (str, &l, errmsg))
431 {
432 (*i) = 0;
433 return FALSE;
434 }
435
436 if (l < 0)
437 {
438 if (errmsg)
439 edsio_generate_stringstring_event (EC_EdsioInvalidIntegerSign, errmsg, str);
440
441 (*i) = 0;
442 return FALSE;
443 }
444
445 (*i) = l;
446
447 if (l != (*i))
448 {
449 if (errmsg)
450 edsio_generate_stringstring_event (EC_EdsioIntegerOutOfRange, errmsg, str);
451
452 (*i) = 0;
453 return FALSE;
454 }
455
456 return TRUE;
457}
458
459gboolean
460strtous_checked (const char* str, guint16* i, const char* errmsg)
461{
462 long l;
463
464 if (! strtosl_checked (str, &l, errmsg))
465 {
466 (*i) = 0;
467 return FALSE;
468 }
469
470 if (l < 0)
471 {
472 if (errmsg)
473 edsio_generate_stringstring_event (EC_EdsioInvalidIntegerSign, errmsg, str);
474
475 (*i) = 0;
476 return FALSE;
477 }
478
479 (*i) = l;
480
481 if (l != (*i))
482 {
483 if (errmsg)
484 edsio_generate_stringstring_event (EC_EdsioIntegerOutOfRange, errmsg, str);
485
486 (*i) = 0;
487 return FALSE;
488 }
489
490 return TRUE;
491}
492
493gint
494edsio_md5_equal (gconstpointer v,
495 gconstpointer v2)
496{
497 return memcmp (v, v2, 16) == 0;
498}
499
500guint
501edsio_md5_hash (gconstpointer v)
502{
503 guint8* md5 = (guint8*) v;
504 guint x = 0;
505 gint i, j;
506
507 for (i = 0, j = 0; i < 16; i += 1, j += 1, j %= sizeof (guint32))
508 x ^= md5[i] << (8*j);
509
510 return x;
511}
512
513void
514serializeio_print_bytes (const guint8* bytes, guint len0)
515{
516 char buf[100];
517 int i;
518 guint len;
519
520 len = MIN (len0, 32);
521
522 for (i = 0; i < len; i += 1)
523 sprintf (buf + 2*i, "%02x", bytes[i]);
524
525 if (len0 > len)
526 strcat (buf, "...");
527
528 g_print ("%s\n", buf);
529}
530
531void
532edsio_md5_to_string (const guint8* md5, char buf[33])
533{
534 gint i;
535
536 for (i = 0; i < 16; i += 1)
537 sprintf (buf + 2*i, "%02x", md5[i]);
538}
539
540static gboolean
541from_hex (char c, int* x, const char* ctx)
542{
543 char buf[2];
544
545 if (c >= '0' && c <= '9')
546 {
547 (*x) = c - '0';
548 return TRUE;
549 }
550 else if (c >= 'A' && c <= 'F')
551 {
552 (*x) = c - 'A' + 10;
553 return TRUE;
554 }
555 else if (c >= 'a' && c <= 'f')
556 {
557 (*x) = c - 'a' + 10;
558 return TRUE;
559 }
560
561 buf[0] = c;
562 buf[1] = 0;
563
564 edsio_generate_stringstring_event (EC_EdsioInvalidHexDigit, buf, ctx);
565 return FALSE;
566}
567
568gboolean
569edsio_md5_from_string (guint8* md5, const char buf[33])
570{
571 gint i;
572 gint l = strlen (buf);
573
574 if (l < 32)
575 {
576 edsio_generate_string_event (EC_EdsioMD5StringShort, buf);
577 return FALSE;
578 }
579 else if (l > 32)
580 {
581 edsio_generate_string_event (EC_EdsioMD5StringLong, buf);
582 return FALSE;
583 }
584
585 for (i = 0; i < 16; i += 1)
586 {
587 char c1 = buf[(2*i)];
588 char c2 = buf[(2*i)+1];
589 int x1, x2;
590
591 if (! from_hex (c1, &x1, buf))
592 return FALSE;
593
594 if (! from_hex (c2, &x2, buf))
595 return FALSE;
596
597 md5[i] = (x1 << 4) | x2;
598 }
599
600 return TRUE;
601}
602
603/* Strings
604 */
605
606const char* edsio_intern_string (const char* str)
607{
608 static GStringChunk* chunk = NULL;
609
610 if (! chunk)
611 chunk = g_string_chunk_new (256);
612
613 return g_string_chunk_insert_const (chunk, str);
614}
615
616/* Properties
617 */
618
619typedef struct _EdsioHostType EdsioHostType;
620typedef struct _EdsioPropertyType EdsioPropertyType;
621
622struct _EdsioPropertyType {
623 const char *type_name;
624 PropFreeFunc freer;
625 PropGSFunc getter;
626 PropGSFunc setter;
627 PropSerialize serialize;
628 PropUnserialize unserialize;
629};
630
631struct _EdsioHostType {
632 const char *host_name;
633 PropertyTableFunc ptable;
634 PersistSourceFunc source;
635 PersistSinkFunc sink;
636 PersistIssetFunc isset;
637 PersistUnsetFunc unset;
638};
639
640struct _EdsioProperty {
641 guint32 prop_code;
642 const char *prop_name;
643 guint32 prop_flags;
644 EdsioPropertyType *type;
645 EdsioHostType *host;
646};
647
648union _EdsioPropertyEntry {
649 guint32 as_uint32;
650 SerialEdsioBytes as_bytes;
651 gpointer as_vptr;
652 const char* as_string;
653};
654
655struct _EdsioGenericProperty
656{
657 guint32 code;
658};
659
660static GHashTable* all_property_types = NULL;
661static GHashTable* all_host_types = NULL;
662static GHashTable* all_properties = NULL;
663static GHashTable* all_property_codes = NULL;
664static guint32 property_code_sequence = 0;
665
666void
667edsio_initialize_property_type (const char* t, PropFreeFunc freer, PropGSFunc getter, PropGSFunc setter, PropSerialize ser, PropUnserialize unser)
668{
669 EdsioPropertyType* type;
670
671 t = edsio_intern_string (t);
672
673 if (! all_property_types)
674 all_property_types = g_hash_table_new (g_direct_hash, g_direct_equal);
675
676 if ((type = g_hash_table_lookup (all_property_types, t)) != NULL)
677 {
678 if (getter != type->getter ||
679 setter != type->setter ||
680 ser != type->serialize ||
681 unser != type->unserialize)
682 edsio_generate_string_event (EC_EdsioDuplicatePropertyTypeRegistered, t);
683 return;
684 }
685
686 type = g_new0 (EdsioPropertyType, 1);
687
688 type->type_name = t;
689 type->freer = freer;
690 type->getter = getter;
691 type->setter = setter;
692 type->serialize = ser;
693 type->unserialize = unser;
694
695 g_hash_table_insert (all_property_types, (gpointer) t, type);
696}
697
698void
699edsio_initialize_host_type (const char* ph,
700 PropertyTableFunc ptable,
701 PersistSourceFunc source,
702 PersistSinkFunc sink,
703 PersistIssetFunc isset,
704 PersistUnsetFunc unset)
705{
706 EdsioHostType* host;
707
708 ph = edsio_intern_string (ph);
709
710 if (! all_host_types)
711 all_host_types = g_hash_table_new (g_direct_hash, g_direct_equal);
712
713 if (g_hash_table_lookup (all_host_types, ph))
714 {
715 edsio_generate_string_event (EC_EdsioDuplicateHostTypeRegistered, ph);
716 return;
717 }
718
719 host = g_new0 (EdsioHostType, 1);
720
721 host->host_name = ph;
722 host->ptable = ptable;
723 host->source = source;
724 host->sink = sink;
725 host->isset = isset;
726 host->unset = unset;
727
728 g_hash_table_insert (all_host_types, (gpointer) ph, host);
729
730}
731
732gboolean
733edsio_new_property (const char* name, const char* ph, const char* t, guint32 flags, EdsioGenericProperty *ret_prop)
734{
735 EdsioProperty* prop;
736 EdsioPropertyType* type;
737 EdsioHostType* host;
738
739 name = edsio_intern_string (name);
740 ph = edsio_intern_string (ph);
741 t = edsio_intern_string (t);
742
743 g_assert (all_property_types);
744
745 if (! all_properties)
746 {
747 all_properties = g_hash_table_new (g_direct_hash, g_direct_equal);
748 all_property_codes = g_hash_table_new (g_int_hash, g_int_equal);
749 }
750
751 if ((prop = g_hash_table_lookup (all_properties, name)) != NULL)
752 {
753 edsio_generate_string_event (EC_EdsioDuplicatePropertyNameRegistered, name);
754 ret_prop->code = prop->prop_code;
755 return TRUE;
756 }
757
758 if ((type = g_hash_table_lookup (all_property_types, t)) == NULL)
759 {
760 edsio_generate_string_event (EC_EdsioNoSuchPropertyType, t);
761 return FALSE;
762 }
763
764 if ((host = g_hash_table_lookup (all_host_types, ph)) == NULL)
765 {
766 edsio_generate_string_event (EC_EdsioNoSuchHostType, ph);
767 return FALSE;
768 }
769
770 if (flags & PF_Persistent && ! host->isset)
771 {
772 edsio_generate_stringstring_event (EC_EdsioPersistenceUnavailable, name, ph);
773 return FALSE;
774 }
775
776 prop = g_new0 (EdsioProperty, 1);
777
778 prop->prop_code = ++property_code_sequence;
779 prop->prop_name = name;
780 prop->prop_flags = flags;
781 prop->type = type;
782 prop->host = host;
783
784 g_hash_table_insert (all_properties, (gpointer) name, prop);
785 g_hash_table_insert (all_property_codes, & prop->prop_code, prop);
786
787 ret_prop->code = prop->prop_code;
788
789 return TRUE;
790}
791
792static EdsioProperty*
793edsio_property_find (const char* ph, const char* t, guint32 code)
794{
795 EdsioProperty* prop;
796
797 ph = edsio_intern_string (ph);
798 t = edsio_intern_string (t);
799
800 if (code <= 0 || code > property_code_sequence)
801 {
802 edsio_generate_int_event (EC_EdsioNoSuchProperty, code);
803 return NULL;
804 }
805
806 if (! (prop = g_hash_table_lookup (all_property_codes, & code)))
807 {
808 edsio_generate_int_event (EC_EdsioNoSuchProperty, code);
809 return NULL;
810 }
811
812 if (prop->host->host_name != ph)
813 {
814 edsio_generate_stringstringstring_event (EC_EdsioWrongHostType, prop->prop_name, ph, prop->host->host_name);
815 return NULL;
816 }
817
818 if (prop->type->type_name != t)
819 {
820 edsio_generate_stringstringstring_event (EC_EdsioWrongDataType, prop->prop_name, t, prop->type->type_name);
821 return NULL;
822 }
823
824 return prop;
825}
826
827EdsioPropertyEntry*
828edsio_property_get (gpointer obj, EdsioProperty* prop)
829{
830 EdsioPropertyEntry* ent;
831 GHashTable* table = * prop->host->ptable (obj);
832 gboolean persist = prop->prop_flags & PF_Persistent;
833
834#ifdef DEBUG_PROPS
835 g_print ("get %p.%s\n", obj, prop->prop_name);
836#endif
837
838 if (table && (ent = g_hash_table_lookup (table, & prop->prop_code)) != NULL)
839 return ent;
840
841 if (persist)
842 {
843 SerialSource* src;
844
845 if (! (src = prop->host->source (obj, prop->prop_name)))
846 return NULL;
847
848 g_assert (prop->type->unserialize);
849
850 if (! prop->type->unserialize (src, & ent))
851 return NULL;
852
853 g_assert (ent);
854
855 if (! src->source_close (src))
856 return NULL;
857
858 src->source_free (src);
859
860 if (! table)
861 table = (* prop->host->ptable (obj)) = g_hash_table_new (g_int_hash, g_int_equal);
862
863 g_hash_table_insert (table, & prop->prop_code, ent);
864
865 return ent;
866 }
867
868 edsio_generate_string_event (EC_EdsioPropertyNotSet, prop->prop_name);
869 return NULL;
870}
871
872gboolean
873edsio_property_set (gpointer obj, EdsioProperty* prop, EdsioPropertyEntry* set)
874{
875 EdsioPropertyEntry* ent;
876 gboolean persist = prop->prop_flags & PF_Persistent;
877 GHashTable* table = * prop->host->ptable (obj);
878
879#ifdef DEBUG_PROPS
880 g_print ("set %p.%s\n", obj, prop->prop_name);
881#endif
882
883 if (! table)
884 table = (* prop->host->ptable (obj)) = g_hash_table_new (g_int_hash, g_int_equal);
885
886 ent = g_hash_table_lookup (table, & prop->prop_code);
887
888 if (ent)
889 {
890 g_hash_table_remove (table, & prop->prop_code);
891 prop->type->freer (ent);
892 }
893
894 g_hash_table_insert (table, & prop->prop_code, set);
895
896 if (persist)
897 {
898 SerialSink* sink;
899
900 if (! (sink = prop->host->sink (obj, prop->prop_name)))
901 return FALSE;
902
903 g_assert (prop->type->serialize);
904
905 if (! prop->type->serialize (sink, set))
906 return FALSE;
907
908 if (! sink->sink_close (sink))
909 return FALSE;
910
911 sink->sink_free (sink);
912 }
913
914 return TRUE;
915}
916
917gboolean
918edsio_property_isset (const char* ph, const char* t, guint32 code, gpointer obj)
919{
920 EdsioProperty* prop;
921 GHashTable* table;
922 gboolean persist;
923 gboolean result = FALSE;
924
925 if (! (prop = edsio_property_find (ph, t, code)))
926 goto done;
927
928 persist = prop->prop_flags & PF_Persistent;
929
930 table = * prop->host->ptable (obj);
931
932 if (persist)
933 {
934 PersistIssetFunc issetfunc = prop->host->isset;
935 if (issetfunc(obj, prop->prop_name))
936 {
937 if (! edsio_property_get (obj, prop))
938 goto done;
939
940 table = * prop->host->ptable (obj);
941 }
942 }
943
944 if (! table)
945 goto done;
946
947 result = (g_hash_table_lookup (table, & code) != NULL);
948
949 done:
950
951#ifdef DEBUG_PROPS
952 g_print ("isset %p.%s = %s\n", obj, prop->prop_name, result ? "true" : "false");
953#endif
954
955 return result;
956}
957
958gboolean
959edsio_property_unset (const char* ph, const char* t, guint32 code, gpointer obj)
960{
961 EdsioProperty* prop;
962 gboolean persist;
963 GHashTable* table;
964
965 if (! (prop = edsio_property_find (ph, t, code)))
966 return FALSE;
967
968#ifdef DEBUG_PROPS
969 g_print ("unset %p.%s\n", obj, prop->prop_name);
970#endif
971
972 persist = prop->prop_flags & PF_Persistent;
973 table = * prop->host->ptable (obj);
974
975 if (table)
976 {
977 EdsioPropertyEntry* ent;
978
979 ent = g_hash_table_lookup (table, & code);
980
981 g_hash_table_remove (table, & code);
982
983 if (g_hash_table_size (table) == 0)
984 {
985 g_hash_table_destroy (table);
986 table = (* prop->host->ptable (obj)) = NULL;
987 }
988
989 /*g_free (ent);*/
990 }
991
992 if (persist)
993 {
994 if (! prop->host->unset (obj, prop->prop_name))
995 return FALSE;
996 }
997
998 return TRUE;
999}
1000
1001static gboolean
1002edsio_false ()
1003{
1004 return FALSE;
1005}
1006
1007PropGSFunc
1008edsio_property_getter (const char* ph, const char* t, guint32 code, EdsioProperty** ep)
1009{
1010 if (! ((*ep) = edsio_property_find (ph, t, code)))
1011 return & edsio_false;
1012
1013 return (* ep)->type->getter;
1014}
1015
1016PropGSFunc
1017edsio_property_setter (const char* ph, const char* t, guint32 code, EdsioProperty** ep)
1018{
1019 if (! ((* ep) = edsio_property_find (ph, t, code)))
1020 return & edsio_false;
1021
1022 return (* ep)->type->setter;
1023}
1024
1025/* Primitive type serializers
1026 */
1027
1028/* integer
1029 */
1030gboolean
1031edsio_property_uint_getter (gpointer obj, EdsioProperty* prop, guint32* get)
1032{
1033 EdsioPropertyEntry *ent;
1034
1035 if (! (ent = edsio_property_get (obj, prop)))
1036 return FALSE;
1037
1038 (*get) = ent->as_uint32;
1039
1040 return TRUE;
1041}
1042
1043gboolean
1044edsio_property_uint_setter (gpointer obj, EdsioProperty* prop, guint32 set)
1045{
1046 EdsioPropertyEntry *ent = g_new (EdsioPropertyEntry, 1);
1047
1048 ent->as_uint32 = set;
1049
1050 return edsio_property_set (obj, prop, ent);
1051}
1052
1053void
1054edsio_property_uint_free (gpointer obj)
1055{
1056 g_free (obj);
1057}
1058
1059gboolean
1060unserialize_uint (SerialSource *source, guint32** x)
1061{
1062 SerialEdsioUint *s;
1063 guint32 *n;
1064
1065 if (! unserialize_edsiouint (source, & s))
1066 return FALSE;
1067
1068 n = g_new (guint32, 1);
1069
1070 (* x) = n;
1071
1072 (* n) = s->val;
1073
1074 g_free (s);
1075
1076 return TRUE;
1077}
1078
1079gboolean
1080serialize_uint_obj (SerialSink *sink, guint32* x)
1081{
1082 return serialize_edsiouint (sink, *x);
1083}
1084
1085/* String
1086 */
1087
1088void
1089edsio_property_string_free (gpointer obj)
1090{
1091 g_free (obj);
1092}
1093
1094gboolean
1095edsio_property_string_getter (gpointer obj, EdsioProperty* prop, const char** get)
1096{
1097 if (! ((*get) = (const char*) edsio_property_get (obj, prop)))
1098 return FALSE;
1099
1100 return TRUE;
1101}
1102
1103gboolean
1104edsio_property_string_setter (gpointer obj, EdsioProperty* prop, const char* set)
1105{
1106 return edsio_property_set (obj, prop, (EdsioPropertyEntry*) set);
1107}
1108
1109gboolean
1110unserialize_string (SerialSource *source, const char** x)
1111{
1112 SerialEdsioString *s;
1113
1114 if (! unserialize_edsiostring (source, & s))
1115 return FALSE;
1116
1117 (*x) = g_strdup (s->val);
1118
1119 g_free (s);
1120
1121 return TRUE;
1122}
1123
1124gboolean
1125serialize_string_obj (SerialSink *sink, const char* x)
1126{
1127 return serialize_edsiostring (sink, x);
1128}
1129
1130/* Bytes
1131 */
1132
1133gboolean
1134unserialize_bytes (SerialSource *source, SerialEdsioBytes** x)
1135{
1136 return unserialize_edsiobytes (source, x);
1137}
1138
1139gboolean
1140serialize_bytes_obj (SerialSink *sink, SerialEdsioBytes *x)
1141{
1142 return serialize_edsiobytes_obj (sink, x);
1143}
1144
1145gboolean
1146edsio_property_bytes_getter (gpointer obj, EdsioProperty* prop, guint8** get, guint32* get_len)
1147{
1148 EdsioPropertyEntry *ent;
1149
1150 if (! (ent = edsio_property_get (obj, prop)))
1151 return FALSE;
1152
1153 (* get) = (gpointer) ent->as_bytes.val;
1154 (* get_len) = ent->as_bytes.val_len;
1155
1156 return TRUE;
1157}
1158
1159gboolean
1160edsio_property_bytes_setter (gpointer obj, EdsioProperty* prop, guint8* set, guint32 set_len)
1161{
1162 EdsioPropertyEntry *ent = g_new (EdsioPropertyEntry, 1);
1163
1164 ent->as_bytes.val = set;
1165 ent->as_bytes.val_len = set_len;
1166
1167 return edsio_property_set (obj, prop, ent);
1168}
1169
1170void
1171edsio_property_bytes_free (gpointer obj)
1172{
1173 g_free (obj);
1174}
1175
1176/* Vptr
1177 */
1178
1179gboolean
1180edsio_property_vptr_getter (gpointer obj, EdsioProperty* prop, void** get)
1181{
1182 if (! ((*get) = edsio_property_get (obj, prop)))
1183 return FALSE;
1184
1185 return TRUE;
1186}
1187
1188gboolean
1189edsio_property_vptr_setter (gpointer obj, EdsioProperty* prop, void* set)
1190{
1191 return edsio_property_set (obj, prop, (EdsioPropertyEntry*) set);
1192}
1193
1194void
1195edsio_property_vptr_free (gpointer obj)
1196{
1197 /* nothing */
1198}
1199
1200/* Testing
1201 */
1202
1203#ifdef DEBUG_LIBEDSIO
1204
1205GHashTable**
1206edsio_proptest_property_table (PropTest *pt)
1207{
1208 return & pt->_edsio_property_table;
1209}
1210
1211SerialSource*
1212edsio_persist_proptest_source (PropTest *pt, const char* prop_name)
1213{
1214 GByteArray* array;
1215
1216 if (! pt->ptable)
1217 {
1218 g_warning ("can't get persist property, no table\n");
1219 return NULL;
1220 }
1221
1222 if (! (array = g_hash_table_lookup (pt->ptable, prop_name)))
1223 {
1224 g_warning ("can't lookup persist property\n");
1225 return NULL;
1226 }
1227
1228 return edsio_simple_source (array->data, array->len, SBF_None);
1229}
1230
1231static void
1232pt_success (gpointer data, GByteArray* result)
1233{
1234 PropTest* pt = data;
1235
1236 GByteArray* old;
1237
1238 if (! pt->ptable)
1239 pt->ptable = g_hash_table_new (g_str_hash, g_str_equal);
1240
1241 old = g_hash_table_lookup (pt->ptable, (gpointer) pt->kludge);
1242
1243 if (old)
1244 g_byte_array_free (old, TRUE);
1245
1246 g_hash_table_insert (pt->ptable, (gpointer) pt->kludge, result);
1247}
1248
1249SerialSink*
1250edsio_persist_proptest_sink (PropTest *pt, const char* prop_name)
1251{
1252 pt->kludge = prop_name;
1253
1254 return edsio_simple_sink (pt, SBF_None, FALSE, pt_success, NULL);
1255}
1256
1257gboolean
1258edsio_persist_proptest_isset (PropTest *pt, const char* prop_name)
1259{
1260 if (! pt->ptable)
1261 return FALSE;
1262
1263 return g_hash_table_lookup (pt->ptable, prop_name) != NULL;
1264}
1265
1266gboolean
1267edsio_persist_proptest_unset (PropTest *pt, const char* prop_name)
1268{
1269 GByteArray* old;
1270
1271 if (! pt->ptable)
1272 return FALSE;
1273
1274 old = g_hash_table_lookup (pt->ptable, prop_name);
1275
1276 if (old)
1277 {
1278 g_byte_array_free (old, TRUE);
1279 g_hash_table_remove (pt->ptable, prop_name);
1280 return TRUE;
1281 }
1282
1283 return FALSE;
1284}
1285
1286#endif
1287
1288/* Misc source/sink stuff
1289 */
1290
1291SerialSink*
1292serializeio_gzip_sink (SerialSink* sink)
1293{
1294 /* @@@ not implemented */
1295 return sink;
1296}
1297
1298SerialSource*
1299serializeio_gzip_source (SerialSource* source)
1300{
1301 /* @@@ not implemented */
1302 return source;
1303}
1304
1305/* Checksum sink
1306 */
1307typedef struct _ChecksumSink ChecksumSink;
1308
1309static gboolean checksum_sink_close (SerialSink* sink);
1310static gboolean checksum_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len);
1311static void checksum_sink_free (SerialSink* sink);
1312static gboolean checksum_sink_quantum (SerialSink* sink);
1313
1314struct _ChecksumSink
1315{
1316 SerialSink sink;
1317
1318 SerialSink* out;
1319
1320 EdsioMD5Ctx ctx;
1321 guint8 md5[16];
1322 gboolean md5_done;
1323 gboolean md5_written;
1324};
1325
1326SerialSink*
1327serializeio_checksum_sink (SerialSink* out)
1328{
1329 ChecksumSink* it = g_new0 (ChecksumSink, 1);
1330 SerialSink* sink = (SerialSink*) it;
1331
1332 serializeio_sink_init (sink,
1333 NULL,
1334 checksum_sink_close,
1335 checksum_sink_write,
1336 checksum_sink_free,
1337 checksum_sink_quantum);
1338
1339 it->out = out;
1340
1341 edsio_md5_init (& it->ctx);
1342
1343 return sink;
1344}
1345
1346gboolean
1347checksum_sink_write (SerialSink* fsink, const guint8 *ptr, guint32 len)
1348{
1349 ChecksumSink* sink = (ChecksumSink*) fsink;
1350
1351 if (! sink->out->sink_write (sink->out, ptr, len))
1352 return FALSE;
1353
1354 edsio_md5_update (& sink->ctx, ptr, len);
1355
1356 return TRUE;
1357}
1358
1359gboolean
1360checksum_sink_close (SerialSink* fsink)
1361{
1362 ChecksumSink* sink = (ChecksumSink*) fsink;
1363
1364 if (! sink->md5_done)
1365 {
1366 edsio_md5_final (sink->md5, & sink->ctx);
1367 sink->md5_done = TRUE;
1368 }
1369
1370 if (! sink->out->sink_write (sink->out, sink->md5, 16))
1371 return FALSE;
1372
1373 if (! sink->out->sink_close (sink->out))
1374 return FALSE;
1375
1376 return TRUE;
1377}
1378
1379void
1380checksum_sink_free (SerialSink* fsink)
1381{
1382 ChecksumSink* sink = (ChecksumSink*) fsink;
1383
1384 sink->out->sink_free (sink->out);
1385
1386 g_free (sink);
1387}
1388
1389gboolean
1390checksum_sink_quantum (SerialSink* fsink)
1391{
1392 ChecksumSink* sink = (ChecksumSink*) fsink;
1393
1394 if (sink->out->sink_quantum)
1395 return sink->out->sink_quantum (sink->out);
1396
1397 return TRUE;
1398}
1399
1400/* Checksum source
1401 */
1402
1403typedef struct _ChecksumSource ChecksumSource;
1404
1405struct _ChecksumSource {
1406 SerialSource source;
1407
1408 SerialSource *in;
1409
1410 EdsioMD5Ctx ctx;
1411};
1412
1413static gboolean checksum_source_close (SerialSource* source);
1414static gboolean checksum_source_read (SerialSource* source, guint8 *ptr, guint32 len);
1415static void checksum_source_free (SerialSource* source);
1416
1417SerialSource*
1418serializeio_checksum_source (SerialSource* in0)
1419{
1420 ChecksumSource* it = g_new0 (ChecksumSource, 1);
1421 SerialSource* source = (SerialSource*) it;
1422
1423 serializeio_source_init (source,
1424 NULL,
1425 checksum_source_close,
1426 checksum_source_read,
1427 checksum_source_free,
1428 NULL,
1429 NULL);
1430
1431 it->in = in0;
1432
1433 edsio_md5_init (& it->ctx);
1434
1435 return source;
1436}
1437
1438gboolean
1439checksum_source_close (SerialSource* fsource)
1440{
1441 ChecksumSource* source = (ChecksumSource*) fsource;
1442 guint8 buf1[16];
1443 guint8 buf2[16];
1444
1445 if (! source->in->source_read (source->in, buf1, 16))
1446 return FALSE;
1447
1448 edsio_md5_final (buf2, & source->ctx);
1449
1450 if (memcmp (buf1, buf2, 16) != 0)
1451 {
1452 edsio_generate_void_event (EC_EdsioInvalidStreamChecksum);
1453 return FALSE;
1454 }
1455
1456 if (! source->in->source_close (source->in))
1457 return FALSE;
1458
1459 return TRUE;
1460}
1461
1462gboolean
1463checksum_source_read (SerialSource* fsource, guint8 *ptr, guint32 len)
1464{
1465 ChecksumSource* source = (ChecksumSource*) fsource;
1466
1467 if (! source->in->source_read (source->in, ptr, len))
1468 return FALSE;
1469
1470 edsio_md5_update (& source->ctx, ptr, len);
1471
1472 return TRUE;
1473}
1474
1475void
1476checksum_source_free (SerialSource* fsource)
1477{
1478 ChecksumSource* source = (ChecksumSource*) fsource;
1479
1480 source->in->source_free (source->in);
1481
1482 g_free (source);
1483}
1484
1485/* Missing glib stuff
1486 */
1487
1488GQueue *
1489g_queue_new (void)
1490{
1491 GQueue *q = g_new (GQueue, 1);
1492
1493 q->list = q->list_end = NULL;
1494 q->list_size = 0;
1495
1496 return q;
1497}
1498
1499
1500void
1501g_queue_free (GQueue *q)
1502{
1503 if (q)
1504 {
1505 if (q->list)
1506 g_list_free (q->list);
1507 g_free (q);
1508 }
1509}
1510
1511
1512guint
1513g_queue_get_size (GQueue *q)
1514{
1515 return (q == NULL) ? 0 : q->list_size;
1516}
1517
1518
1519void
1520g_queue_push_front (GQueue *q, gpointer data)
1521{
1522 if (q)
1523 {
1524 q->list = g_list_prepend (q->list, data);
1525
1526 if (q->list_end == NULL)
1527 q->list_end = q->list;
1528
1529 q->list_size++;
1530 }
1531}
1532
1533
1534void
1535g_queue_push_back (GQueue *q, gpointer data)
1536{
1537 if (q)
1538 {
1539 q->list_end = g_list_append (q->list_end, data);
1540
1541 if (! q->list)
1542 q->list = q->list_end;
1543 else
1544 q->list_end = q->list_end->next;
1545
1546 q->list_size++;
1547 }
1548}
1549
1550
1551gpointer
1552g_queue_pop_front (GQueue *q)
1553{
1554 gpointer data = NULL;
1555
1556 if ((q) && (q->list))
1557 {
1558 GList *node;
1559
1560 node = q->list;
1561 data = node->data;
1562
1563 if (! node->next)
1564 {
1565 q->list = q->list_end = NULL;
1566 q->list_size = 0;
1567 }
1568 else
1569 {
1570 q->list = node->next;
1571 q->list->prev = NULL;
1572 q->list_size--;
1573 }
1574
1575 g_list_free_1 (node);
1576 }
1577
1578 return data;
1579}
1580
1581
1582gpointer
1583g_queue_pop_back (GQueue *q)
1584{
1585 gpointer data = NULL;
1586
1587 if ((q) && (q->list))
1588 {
1589 GList *node;
1590
1591 node = q->list_end;
1592 data = node->data;
1593
1594 if (! node->prev)
1595 {
1596 q->list = q->list_end = NULL;
1597 q->list_size = 0;
1598 }
1599 else
1600 {
1601 q->list_end = node->prev;
1602 q->list_end->next = NULL;
1603 q->list_size--;
1604 }
1605
1606 g_list_free_1 (node);
1607 }
1608
1609 return data;
1610}
diff --git a/xdelta1/libedsio/edsio.el b/xdelta1/libedsio/edsio.el
deleted file mode 100644
index 8c15215..0000000
--- a/xdelta1/libedsio/edsio.el
+++ /dev/null
@@ -1,1864 +0,0 @@
1;; -*- Emacs-Lisp -*-
2
3(require 'cl)
4(require 'pp)
5
6(eval-and-compile (setq load-path (cons ".." (cons "." load-path))))
7(provide 'edsio)
8(eval-and-compile (setq load-path (cdr (cdr load-path))))
9
10;; Turn of assertions in compiled code.
11(eval-and-compile
12 (setq cl-optimize-speed 3)
13 (setq cl-optimize-safety 1)
14 )
15
16;; Begin
17
18(defconst *definition-state* nil
19 "List of all the names of variables containing state from the
20definition file so that operations may be performed on everything in
21the definition file.")
22(defconst *definition-attrs* nil
23 "List of attributes for sharing indices.")
24(defconst *all-objects* nil)
25(defconst *output-files* nil
26 "List of lists (NAME BUFFER) used during output of headers.")
27(defconst *output-prefix* nil
28 "Prefix used for outputing header files.")
29(defconst *cpp-extension* "c")
30
31;; This defines several functions and one macro. The indirection makes
32;; it a little bit confusing to read. It defines the macro DEFDNAME,
33;; a function DEFDNAME*, MAKE-DNAME, and a setter and getter for each arg.
34(eval-and-compile
35(defmacro attr-index (attr)
36 `(- (length *definition-attrs*) (length (memq ,attr *definition-attrs*))))
37
38(defmacro defastmacro(dtype args attrs)
39 "Defines a macro named DEFDTYPE for defining various AST properties."
40 (let ((def-macr (intern (format "def%s" dtype)))
41 (def-func (intern (format "def%s*" dtype)))
42 (make-func (intern (format "make-%s" dtype)))
43 (state (intern (format "*%s-defs*" dtype)))
44 (exprs nil))
45 (if (not *definition-attrs*)
46 (setq *definition-attrs* '(menunode menuline)))
47 (let ((fields (append args attrs)))
48 (while fields
49 (if (not (memq (car fields) *definition-attrs*))
50 (setq *definition-attrs* (append *definition-attrs* (list (car fields)))))
51 (setq fields (cdr fields))
52 )
53 )
54 ;; Add it to *definition-state*
55 (setq *definition-state* (cons state *definition-state*))
56 ;; DEFCONST it
57 (setq exprs (cons (list 'defconst state (quote nil)) exprs))
58 ;; DEFMACRO DEFDTYPE
59 (setq exprs (cons (list 'defmacro
60 def-macr
61 args
62 (append (list 'list (list 'quote def-func))
63 (mapcar (function (lambda (x)
64 (list 'list (list 'quote 'quote) x)
65 )
66 )
67 args)
68 )
69 )
70 exprs
71 )
72 )
73 ;; DEFUN DEFDTYPE*
74 (setq exprs (cons (list 'defun
75 def-func
76 args
77 (list 'setq
78 state
79 (list 'cons
80 (cons make-func args)
81 state
82 )
83 )
84 )
85 exprs
86 )
87 )
88 ;; MAKE-DTYPE
89 (setq exprs (cons (list 'defun
90 make-func
91 args
92 (list 'let (list (list 'it (list 'make-vector (length *definition-attrs*) nil)))
93 (if args
94 (cons 'progn (mapcar
95 (function
96 (lambda (x)
97 (list 'aset 'it (attr-index x) x)
98 )
99 )
100 args
101 )
102 )
103 )
104 (if attrs
105 (cons 'progn (mapcar
106 (function
107 (lambda (x)
108 (list 'aset 'it (attr-index x) nil)
109 )
110 )
111 attrs
112 )
113 )
114 )
115 (if (memq 'menu args)
116 (list 'progn
117 (list 'aset 'it (attr-index 'menunode) (list 'function (intern (format "%s-menunode" dtype))))
118 (list 'aset 'it (attr-index 'menuline) (list 'function (intern (format "%s-menuline" dtype))))
119 )
120 )
121 (list 'cons (list 'quote dtype) 'it)
122 )
123 )
124 exprs
125 )
126 )
127 ;; Add the fake arguments:
128 (if (memq 'menu args)
129 (setq attrs (append (list 'menunode 'menuline) attrs)))
130 (setq args (append args attrs))
131 (while args
132 (let* ((thearg (car args))
133 (arg-set (intern (format "%s-%s-set" dtype thearg)))
134 (arg-get (intern (format "%s-%s-get" dtype thearg))))
135 ;; DTYPE-ARG-GET
136 (setq exprs (cons (list 'defmacro
137 (intern (format "%s-%s-get" dtype thearg))
138 '(obj)
139 (list 'list
140 (list 'quote 'aref)
141 (list 'list (list 'quote 'cdr) 'obj)
142 (attr-index thearg))
143 )
144 exprs
145 )
146 )
147 ;; DTYPE-ARG-SET
148 (setq exprs (cons (list 'defmacro
149 (intern (format "%s-%s-set" dtype thearg))
150 '(obj val)
151 (list 'list
152 (list 'quote 'aset)
153 (list 'list (list 'quote 'cdr) 'obj)
154 (attr-index thearg)
155 'val)
156 )
157 exprs
158 )
159 )
160 )
161 (setq args (cdr args))
162 )
163 ;; To see what it's generating uncomment the next 2 lines.
164 ;;(setq message-log-max t)
165 ;;(mapcar (function pp) exprs)
166 (cons 'progn exprs)
167 )
168 )
169
170
171;; This is, as the name suggests, really bogus. Basically, each DEFASTMACRO
172;; call adds to the list *definition-state*. To compile it, however, it has
173;; to be done at compile time, so this macro gets evaluated when being compiled
174;; and clears the list. Then the DEFASTMACRO calls are made, and then DEFCDS
175;; is called to define CLEAR-DEFINITION-STATE which resets the list to the
176;; compile-time computed value of *definition-state*, it would otherwise be
177;; empty when running compiled code.
178(defmacro bogus ()
179 (setq *definition-state* nil)
180 (setq *definition-attrs* nil)
181 )
182
183 (bogus)
184
185;; Each DEFASTMACRO statement defines a directive for the definition
186;; file along with it's argument names.
187(defastmacro sertype (name number fields transients) ())
188(defastmacro module (name id header pheader) ())
189(defastmacro import (name) (prefix))
190
191(defastmacro event (name level uargs sargs desc) ())
192(defastmacro etype (name ctype) ())
193
194(defastmacro prophost (name letter ctype persist) (proptypes))
195(defastmacro prophosttype (host type) ())
196
197(defmacro defcds ()
198 (let ((exprs nil))
199 (setq exprs (list (list 'defun 'clear-definition-state nil
200 '(setq *all-objects* nil)
201 (list 'setq '*definition-state* (list 'quote *definition-state*))
202 (list 'setq '*definition-attrs* (list 'quote *definition-attrs*))
203 '(mapcar (function (lambda (x) (set x nil))) *definition-state*)
204 )
205
206 )
207 )
208 (mapcar
209 (function
210 (lambda (x)
211 (setq exprs (cons (list 'defmacro
212 (intern (format "obj-%s-get" x))
213 '(obj)
214 (list 'list
215 (list 'quote 'aref)
216 (list 'list (list 'quote 'cdr) 'obj)
217 (attr-index x))
218 )
219 exprs
220 )
221 )
222 (setq exprs (cons (list 'defmacro
223 (intern (format "obj-%s-set" x))
224 '(obj val)
225 (list 'list
226 (list 'quote 'aset)
227 (list 'list (list 'quote 'cdr) 'obj)
228 (attr-index x)
229 'val)
230 )
231 exprs
232 )
233 )
234 (let ((get (intern (format "obj-%s-get" x))))
235 (setq exprs (cons (list 'defun
236 (intern (format "obj-%s-eq" x))
237 '(val olist)
238 `(let ((ret nil))
239 (while (and (not ret) olist)
240 (if (eq val (,get (car olist)))
241 (setq ret (car olist))
242 )
243 (setq olist (cdr olist))
244 )
245 ret
246 )
247 )
248 exprs
249 )
250 )
251 )
252 )
253 )
254 *definition-attrs*
255 )
256 ;;(setq message-log-max t)
257 ;;(mapcar (function pp) exprs)
258 (cons 'progn exprs)
259 )
260 )
261
262(defcds)
263)
264;; Entry Points
265
266(defun generate-ser-noargs ()
267 (interactive)
268 (generate-ser "edsio.ser" "edsio")
269 )
270
271(defun generate-ser (input-file output-prefix)
272 ;(interactive "finput: \nsoutput: \nsid: ")
273 (let ((make-backup-files nil)
274 (executing-kbd-macro t))
275 (clear-definition-state)
276
277 (do-it input-file output-prefix)
278 )
279 )
280
281(defconst *library-id* nil
282 "Identifier of this library.")
283
284(defconst *library-header* nil
285 "Header of this library.")
286(defconst *library-pheader* nil
287 "Header of this library.")
288
289(defconst *prefix-with-library-header* t)
290
291(defun load-defs(file)
292 (load-file file)
293 (setq *import-defs* (reverse *import-defs*))
294 (setq *module-defs* (reverse *module-defs*))
295 (setq *sertype-defs* (reverse *sertype-defs*))
296
297 (setq *event-defs* (reverse *event-defs*))
298 (setq *etype-defs* (reverse *etype-defs*))
299
300 (setq *prophost-defs* (reverse *prophost-defs*))
301 (setq *prophosttype-defs* (reverse *prophosttype-defs*))
302 )
303
304(defconst *header-typedef-marker* nil)
305(defconst *source-init-marker* nil)
306(defconst *source-top-marker* nil)
307
308(defun do-it (input-file output-prefix)
309 (setq *output-files* nil)
310 (setq *output-prefix* output-prefix)
311
312 (load-defs input-file)
313
314 (if (not *module-defs*)
315 (error "no defmodule in %s" input-file))
316
317 (if (> (length *module-defs*) 1)
318 (error "too many defmodules in %s" input-file))
319
320 (setq *library-id* (module-id-get (car *module-defs*)))
321 (setq *library-header* (module-header-get (car *module-defs*)))
322 (setq *library-pheader* (module-pheader-get (car *module-defs*)))
323
324 (when (not *library-header*)
325 (setq *prefix-with-library-header* nil)
326 (setq *library-header* (format "%s_edsio.h" *output-prefix*))
327 )
328
329 (if (or (<= *library-id* 0)
330 (>= *library-id* 256))
331 (error "Library-id is out of range"))
332
333 (if (> (length *sertype-defs*) 24)
334 (error "no more than 24 types"))
335
336 (unwind-protect
337 (progn
338
339 (output-header-file "_edsio")
340
341 (read-imports)
342
343 (insert "/* Initialize this library. */\n\n")
344 (insert "gboolean " *output-prefix* "_edsio_init (void);\n\n")
345
346 (insert "/* Types defined here. */\n\n")
347 (setq *header-typedef-marker* (point-marker))
348
349 (insert "/* Functions declared here. */\n\n")
350
351 (output-source-file "_edsio")
352
353 (insert "#include \"" *library-header* "\"\n\n")
354 (insert "#include <errno.h>\n\n")
355
356 (if *library-pheader*
357 (insert "#include \"" *library-pheader* "\"\n\n"))
358
359 (insert "/* Declarations. */\n\n")
360 (setq *source-top-marker* (point-marker))
361
362 (insert "\n")
363
364 (insert "/* initialize this library. */\n\n")
365 (insert "gboolean\n" *output-prefix* "_edsio_init (void)\n{\n")
366 (insert " static gboolean once = FALSE;\n")
367 (insert " static gboolean result = FALSE;\n")
368 (insert " if (once) return result;\n")
369 (insert " once = TRUE;\n")
370
371 (setq *source-init-marker* (point-marker))
372
373 (insert (format " edsio_library_register (%d, \"%s\");\n" *library-id* *output-prefix*))
374 (insert " result = TRUE;\n")
375 (insert " return TRUE;\n")
376 (insert "};\n\n")
377
378 (if *prophosttype-defs*
379 (generate-properties))
380
381 (if *sertype-defs*
382 (generate-code))
383
384 (if *event-defs*
385 (generate-events))
386
387; (message "source file:\n%s" (buffer-string))
388
389 (mapcar (function (lambda (x) (output-finish-file x))) *output-files*)
390 )
391 (mapcar (function (lambda (x) (kill-buffer (cadr x)))) *output-files*)
392 )
393 )
394
395(defvar *all-sertype-defs* nil)
396(defvar *all-prophost-defs* nil)
397(defvar *all-etype-defs* nil)
398
399(defun read-imports ()
400
401 (setq *all-sertype-defs* *sertype-defs*)
402 (setq *all-etype-defs* *etype-defs*)
403 (setq *all-prophost-defs* *prophost-defs*)
404
405 (let ((mods *module-defs*)
406 (imps0 *import-defs*)
407 (imps *import-defs*)
408 (types *sertype-defs*)
409 (events *event-defs*)
410 (etypes *etype-defs*)
411 (phosts *prophost-defs*)
412 (phts *prophosttype-defs*)
413 )
414
415 (while imps
416 (clear-definition-state)
417
418 (load-defs (import-name-get (car imps)))
419
420 (setq *all-sertype-defs* (append *all-sertype-defs* *sertype-defs*))
421 (setq *all-etype-defs* (append *all-etype-defs* *etype-defs*))
422 (setq *all-prophost-defs* (append *all-prophost-defs* *prophost-defs*))
423
424 (import-prefix-set (car imps) (module-name-get (car *module-defs*)))
425
426 (when (or *sertype-defs* *event-defs*)
427 (output-header-file "_edsio")
428 (insert (format "#include \"%s_edsio.h\"\n\n" (import-prefix-get (car imps))))
429 )
430
431 (setq imps (cdr imps))
432 )
433
434 (setq *module-defs* mods)
435 (setq *import-defs* imps0)
436 (setq *sertype-defs* types)
437 (setq *event-defs* events)
438 (setq *etype-defs* etypes)
439 (setq *prophost-defs* phosts)
440 (setq *prophosttype-defs* phts)
441 )
442 )
443
444
445(defun output-header-file (name)
446 (output-file (format "%s.h" name) 'c-header *output-prefix*))
447
448(defun output-source-file (name)
449 (output-file (format "%s.%s" name *cpp-extension*) 'c *output-prefix*))
450
451(defun output-source-include-file (name)
452 (output-file (format "%s.%si" name *cpp-extension*) 'c *output-prefix*))
453
454(defun output-plain-file (name)
455 (output-file (format "%s" name) 'plain ""))
456
457(defun output-file (name type prefix)
458 (let* ((name (format "%s%s" prefix name))
459 (it (assoc name *output-files*)))
460 (if it
461 (set-buffer (cadr it))
462 (let ((nbuf (get-buffer-create (generate-new-buffer-name name))))
463 (setq *output-files* (cons (list name nbuf type) *output-files*))
464 (set-buffer nbuf)
465 )
466 )
467 )
468 )
469
470(defun output-finish-file (file)
471 (let ((name (car file))
472 (buf (cadr file))
473 (type (caddr file)))
474 (set-buffer buf)
475 ;(message "printing %s: %s" file (buffer-string))
476 (cond ((eq type 'c)
477 (output-to-c name nil))
478 ((eq type 'c-header)
479 (output-to-c name t))
480 )
481 (write-file-if-different buf name)
482 )
483 )
484
485(defun output-to-c (name is-header)
486 (goto-char (point-min))
487 (insert "/* -*-Mode: C;-*-
488 * Copyright (C) 1997, 1998, 1999 Josh MacDonald
489 *
490 * This program is free software; you can redistribute it and/or modify
491 * it under the terms of the GNU General Public License as published by
492 * the Free Software Foundation; either version 2 of the License, or
493 * (at your option) any later version.
494 *
495 * This program is distributed in the hope that it will be useful,
496 * but WITHOUT ANY WARRANTY; without even the implied warranty of
497 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
498 * GNU General Public License for more details.
499 *
500 * You should have received a copy of the GNU General Public License
501 * along with this program; if not, write to the Free Software
502 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
503 *
504 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
505 *
506 * This file was AUTOMATICALLY GENERATED using:
507 *
508 * $Id: edsio.el 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $
509 */
510
511")
512
513 (if is-header
514 (let ((cppname (string-replace-regexp (upcase name) "[-./]" "_")))
515 (insert "#include \"edsio.h\"\n\n")
516
517 (if *prefix-with-library-header*
518 (insert "#include \"" *library-header* "\"\n\n"))
519
520 (insert "#ifndef _" cppname "_\n")
521 (insert "#define _" cppname "_\n\n")
522 (insert "#ifdef __cplusplus\n")
523 (insert "extern \"C\" {\n")
524 (insert "#endif\n\n")
525 (goto-char (point-max))
526 (insert "#ifdef __cplusplus\n")
527 (insert "}\n")
528 (insert "#endif\n")
529 (insert "\n#endif /* _" cppname "_ */\n\n")
530 )
531 )
532 )
533
534(defun string-replace-regexp (str regexp to-string)
535 "Result of replacing all occurrences in STR of REGEXP by TO-STRING. The
536replacement is as for replace-regexp."
537 (let ((work (get-buffer-create "*string-tmp*")))
538 (save-excursion
539 (set-buffer work)
540 (erase-buffer)
541 (insert str)
542 (beginning-of-buffer)
543 (while (re-search-forward regexp nil t)
544 (replace-match to-string nil nil))
545 (buffer-string))))
546
547(defun write-file-if-different (buf filename)
548 (save-excursion
549 (if (not (file-exists-p filename))
550 (write-file filename)
551 (set-buffer buf)
552 (let ((old (get-buffer-create (generate-new-buffer-name filename)))
553 (bmin (point-min))
554 (bmax (point-max)))
555 (unwind-protect
556 (progn
557 (set-buffer old)
558 (insert-file filename)
559 (let ((omin (point-min))
560 (omax (point-max))
561 (case-fold-search nil))
562 (if (= 0 (compare-buffer-substrings old omin omax buf bmin bmax))
563 (message "Output file %s is unchanged." filename)
564 (set-buffer buf)
565 (write-file filename)
566 )
567 )
568 )
569 (kill-buffer old)
570 )
571 )
572 )
573 )
574 )
575
576
577(defun format-comlist (func l)
578 (let ((x ""))
579 (while l
580 (setq x (concat x (funcall func (car l))))
581 (if (cdr l)
582 (setq x (concat x ", ")))
583 (setq l (cdr l))
584 )
585 x
586 )
587 )
588
589(defun format-semilist (func l)
590 (let ((x ""))
591 (while l
592 (setq x (concat x (funcall func (car l))))
593 (if (cdr l)
594 (setq x (concat x "; ")))
595 (setq l (cdr l))
596 )
597 x
598 )
599 )
600
601(defun format-numbered-comlist (func l)
602 (let ((x "")
603 (n 0))
604 (while l
605 (setq x (concat x (funcall func (car l) n)))
606 (setq n (+ n 1))
607 (if (cdr l)
608 (setq x (concat x ", ")))
609 (setq l (cdr l))
610 )
611 x
612 )
613 )
614
615(defun capitalize1(s)
616 (let ((work (get-buffer-create "*string-tmp*")))
617 (save-excursion
618 (set-buffer work)
619 (erase-buffer)
620 (insert (format "%s" s))
621 (upcase-region (point-min) (+ (point-min) 1))
622 (buffer-substring-no-properties (point-min) (point-max))
623 )
624 )
625 )
626
627(defun upcase-string (s)
628 (let ((work (get-buffer-create "*string-tmp*")))
629 (save-excursion
630 (set-buffer work)
631 (erase-buffer)
632 (insert (format "%s" s))
633 (upcase-region (point-min) (point-max))
634 (buffer-substring-no-properties (point-min) (point-max))
635 )
636 )
637 )
638
639(defun downcase-string (s)
640 (let ((work (get-buffer-create "*string-tmp*")))
641 (save-excursion
642 (set-buffer work)
643 (erase-buffer)
644 (insert (format "%s" s))
645 (downcase-region (point-min) (point-max))
646 (buffer-substring-no-properties (point-min) (point-max))
647 )
648 )
649 )
650
651;; HERE IT IS
652
653(defun generate-code ()
654
655 (let ((all-codes nil))
656 (mapcar
657 (function
658 (lambda (st)
659 (let ((x (sertype-number-get st)))
660 (cond ((member x all-codes)
661 (error "serial type number %d defined twice" x))
662 ((> x 24)
663 (error "serial type value %d too high" x))
664 ((< x 0)
665 (error "serial type value %d too low" x))
666 (t (setq all-codes (cons x all-codes))))))
667 )
668 *sertype-defs*)
669 )
670
671 (output-header-file "_edsio")
672
673 (insert "/* Serial Types */\n\n")
674 (insert (format "enum _Serial%sType {\n" (capitalize1 *output-prefix*)))
675 (insert (format-comlist
676 (function
677 (lambda (x)
678 (format "\n ST_%s = (1<<(%d+EDSIO_LIBRARY_OFFSET_BITS))+%d" (sertype-name-get x) (sertype-number-get x) *library-id*))) *sertype-defs*))
679 (insert "\n};\n\n")
680
681 (insert "\n\n")
682
683 (output-source-file "_edsio")
684
685 (save-excursion
686 (goto-char *source-top-marker*)
687
688 (insert "static void print_spaces (guint n) { int i; for (i = 0; i < n; i += 1) g_print (\" \"); }\n\n")
689 )
690
691 (mapcar (function generate-code-entry) *sertype-defs*)
692
693 )
694
695(defun generate-code-entry (entry)
696 (let ((ent-upcase (sertype-name-get entry))
697 (ent-downcase (downcase-string (sertype-name-get entry))))
698
699 (output-header-file "_edsio")
700
701 ;; The typedef, structure, and declarations.
702
703 (save-excursion
704 (goto-char *header-typedef-marker*)
705 (insert (format "typedef struct _Serial%s Serial%s;\n" ent-upcase ent-upcase))
706 )
707
708 (insert (format "/* %s Structure\n */\n\n" ent-upcase))
709
710 (insert (format "struct _Serial%s {\n" ent-upcase))
711
712 (apply (function insert)
713 (mapcar (function
714 (lambda (x)
715 (format " %s;\n" x)))
716 (entry-typename-pairs entry nil)))
717
718 (apply (function insert)
719 (mapcar (function
720 (lambda (x)
721 (format " %s;\n" x)))
722 (sertype-transients-get entry)))
723
724 (insert "};\n\n")
725
726 (insert (format "void serializeio_print_%s_obj (Serial%s* obj, guint indent_spaces);\n\n" ent-downcase ent-upcase))
727
728 (insert (format "gboolean unserialize_%s (SerialSource *source, Serial%s**);\n" ent-downcase ent-upcase))
729 (insert (format "gboolean unserialize_%s_internal (SerialSource *source, Serial%s** );\n" ent-downcase ent-upcase))
730 (insert (format "gboolean unserialize_%s_internal_noalloc (SerialSource *source, Serial%s* );\n" ent-downcase ent-upcase))
731 (insert (format "gboolean serialize_%s (SerialSink *sink%s);\n" ent-downcase (entry-arglist t entry)))
732 (insert (format "gboolean serialize_%s_obj (SerialSink *sink, const Serial%s* obj);\n" ent-downcase ent-upcase))
733 (insert (format "gboolean serialize_%s_internal (SerialSink *sink%s);\n" ent-downcase (entry-arglist t entry)))
734 (insert (format "gboolean serialize_%s_obj_internal (SerialSink *sink, Serial%s* obj);\n" ent-downcase ent-upcase))
735 (insert (format "guint serializeio_count_%s (%s);\n" ent-downcase (entry-arglist nil entry)))
736 (insert (format "guint serializeio_count_%s_obj (Serial%s const* obj);\n" ent-downcase ent-upcase))
737 (insert (format "\n"))
738
739 (output-source-file "_edsio")
740
741 ;; The init entry
742
743 (save-excursion
744 (goto-char *source-init-marker*)
745 (insert (format " serializeio_initialize_type (\"ST_%s\", ST_%s, &unserialize_%s_internal, &serialize_%s_obj_internal, &serializeio_count_%s_obj, &serializeio_print_%s_obj);\n" ent-upcase ent-upcase ent-downcase ent-downcase ent-downcase ent-downcase))
746 )
747
748 ;; Count code
749
750 (insert (format "/* %s Count\n */\n\n" ent-upcase))
751
752 (insert (format "guint\nserializeio_count_%s (%s) {\n" ent-downcase (entry-arglist nil entry)))
753 (insert (format " guint size = sizeof (Serial%s);\n" ent-upcase))
754 (apply (function insert)
755 (mapcar (function (lambda (x) (concat
756 (format " ALIGN_8 (size);\n")
757 (entry-count-field entry x (format "%s" (car x)) " " t))))
758 (sertype-fields-get entry)))
759 (insert (format " ALIGN_8 (size);\n"))
760 (insert (format " return size;\n"))
761 (insert (format "}\n\n"))
762
763 ;; Count Object code
764
765 (insert (format "guint\nserializeio_count_%s_obj (Serial%s const* obj) {\n" ent-downcase ent-upcase))
766 (insert (format " return serializeio_count_%s (%s);\n" ent-downcase (entry-plist t nil "obj->" entry)))
767 (insert (format "}\n\n"))
768
769 ;; Print object code
770
771 (insert (format "/* %s Print\n */\n\n" ent-upcase))
772
773 (insert (format "void\nserializeio_print_%s_obj (Serial%s* obj, guint indent_spaces) {\n" ent-downcase ent-upcase))
774 (insert (format " print_spaces (indent_spaces);\n"))
775
776 (insert (format " g_print (\"[ST_%s]\\n\");\n" ent-upcase))
777
778 (apply (function insert)
779 (mapcar (function (lambda (x) (entry-print-field entry x (format "obj->%s" (car x)) " " t)))
780 (sertype-fields-get entry)))
781
782 (insert (format "}\n\n"))
783
784 ;; Print internal code
785
786 ;; Serialize code
787
788 (insert (format "/* %s Serialize\n */\n\n" ent-upcase))
789
790 (insert (format "gboolean\nserialize_%s_internal (SerialSink *sink%s)\n" ent-downcase (entry-arglist t entry)))
791 (insert (format "{\n"))
792
793 (apply (function insert)
794 (mapcar (function (lambda (x) (entry-serialize-field entry x (format "%s" (car x)) " " t)))
795 (sertype-fields-get entry)))
796
797 (insert (format " return TRUE;\n"))
798 (if (sertype-fields-get entry)
799 (insert (format "bail:\n return FALSE;\n")))
800 (insert (format "}\n\n"))
801
802 ;; Internal Serialize Object code
803
804 (insert (format "gboolean\nserialize_%s_obj_internal (SerialSink *sink, Serial%s* obj)\n" ent-downcase ent-upcase))
805 (insert (format "{\n"))
806 (insert (format " return serialize_%s_internal (sink%s);\n" ent-downcase (entry-plist t t "obj->" entry)))
807 (insert (format "}\n\n"))
808
809 ;; External Serialize code
810
811 (insert (format "gboolean\nserialize_%s (SerialSink *sink%s)\n" ent-downcase (entry-arglist t entry)))
812 (insert (format "{\n"))
813
814 (insert (format " if (! (* sink->sink_type) (sink, ST_%s, serializeio_count_%s (%s), TRUE)) goto bail;\n" ent-upcase ent-downcase (entry-plist nil nil "" entry)))
815
816 (insert (format " if (! serialize_%s_internal (sink%s)) goto bail;\n" ent-downcase (entry-plist nil t "" entry)))
817 (insert (format " if (sink->sink_quantum && ! sink->sink_quantum (sink)) goto bail;\n"))
818
819 (insert (format " return TRUE;\n"))
820 (insert (format "bail:\n"))
821 (insert (format " return FALSE;\n"))
822 (insert (format "}\n\n"))
823
824 ;; External serialize_obj
825
826 (insert (format "gboolean\nserialize_%s_obj (SerialSink *sink, const Serial%s* obj) {\n\n" ent-downcase ent-upcase))
827 (insert (format " return serialize_%s (sink%s);\n" ent-downcase (entry-plist t t "obj->" entry)))
828 (insert (format "}\n\n"))
829
830 ;; Unserialize code
831
832 (insert (format "/* %s Unserialize\n */\n\n" ent-upcase))
833
834 (insert (format "gboolean\nunserialize_%s_internal_noalloc (SerialSource *source, Serial%s* result)\n" ent-downcase ent-upcase))
835 (insert (format "{\n"))
836
837 (apply (function insert)
838 (mapcar (function (lambda (x) (entry-unserialize-field entry x (format "result->%s" (car x)) " ")))
839 (sertype-fields-get entry)))
840
841 (insert (format " return TRUE;\n"))
842 (if (sertype-fields-get entry)
843 (insert (format "bail:\n return FALSE;\n")))
844 (insert (format "}\n\n"))
845
846
847 (insert (format "gboolean\nunserialize_%s_internal (SerialSource *source, Serial%s** result)\n" ent-downcase ent-upcase))
848 (insert (format "{\n"))
849
850 (insert (format " Serial%s* unser;\n" ent-upcase))
851 (insert (format " (*result) = NULL;\n"))
852 (insert (format " unser = serializeio_source_alloc (source, sizeof (Serial%s));\n" ent-upcase))
853 (insert (format " if (! unser) goto bail;\n"))
854
855 (insert (format " if (! unserialize_%s_internal_noalloc (source, unser)) goto bail;\n" ent-downcase))
856
857 (insert (format " (*result) = unser;\n"))
858 (insert (format " return TRUE;\n"))
859 (insert (format "bail:\n"))
860 (insert (format " return FALSE;\n"))
861 (insert (format "}\n\n"))
862
863 ;; External unserialize
864
865 (insert (format "gboolean\nunserialize_%s (SerialSource *source, Serial%s** result)\n" ent-downcase ent-upcase))
866 (insert (format "{\n"))
867
868 (insert (format " if ( (* source->source_type) (source, TRUE) != ST_%s) goto bail;\n" ent-upcase))
869
870 (insert (format " if (! unserialize_%s_internal (source, result)) goto bail;\n" ent-downcase))
871
872 (insert (format " return TRUE;\n"))
873 (insert (format "bail:\n"))
874 (insert (format " return FALSE;\n"))
875
876 (insert (format "}\n\n"))
877
878 )
879 )
880
881(defun entry-typename-pairs (entry is-param)
882 (let ((pairs nil)
883 (fields (sertype-fields-get entry)))
884 (while fields
885 (let ((field (car fields)))
886 (when (or (equal (cadr field) 'bytes)
887 (and (consp (cadr field)) (equal (caadr field) 'array)))
888 (setq pairs (cons (format "guint32 %s_len" (car field)) pairs))
889 )
890 (when (equal (cadr field) 'object)
891 (setq pairs (cons (format "guint32 %s_type" (car field)) pairs))
892 )
893 (setq pairs (cons (field-decl field is-param) pairs))
894 )
895 (setq fields (cdr fields))
896 )
897 (nreverse pairs)
898 )
899 )
900
901(defun entry-param-names (prefix entry need_pbr)
902 (let ((pairs nil)
903 (fields (sertype-fields-get entry)))
904 (while fields
905 (let ((field (car fields)))
906 (when (or (equal (cadr field) 'bytes)
907 (and (consp (cadr field)) (equal (caadr field) 'array)))
908 (setq pairs (cons (format "%s%s_len" prefix (car field)) pairs))
909 )
910 (when (equal (cadr field) 'object)
911 (setq pairs (cons (format "%s%s_type" prefix (car field)) pairs))
912 )
913 (setq pairs (cons (format "%s%s%s" (if (and need_pbr (needs-ref field)) "&" "") prefix (car field)) pairs))
914 )
915 (setq fields (cdr fields))
916 )
917 (nreverse pairs)
918 )
919 )
920
921(defun field-ctype (field)
922 (cond ((equal (cadr field) 'string)
923 "const gchar*")
924 ((equal (cadr field) 'uint)
925 "guint32")
926 ((equal (cadr field) 'uint32)
927 "guint32")
928 ((equal (cadr field) 'uint16)
929 "guint16")
930 ((equal (cadr field) 'uint8)
931 "guint8")
932 ((equal (cadr field) 'boolean)
933 "gboolean")
934 ((equal (cadr field) 'bytes)
935 "const guint8*")
936 ((equal (cadr field) 'object)
937 "void*")
938 ((member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))
939 (format "Serial%s" (cadr field)))
940 ((equal (car (cadr field)) 'bytes)
941 "const guint8*")
942 ((member (car (cadr field)) '(array ptr))
943 (concat (field-ctype (cadr field)) "*"))
944 (t (error "unrecognized field type: %s" (cadr field))))
945 )
946
947(defun field-decl (field is-param)
948 (if (and (consp (cadr field))
949 (equal (car (cadr field)) 'bytes))
950 (format "%sguint8 %s[%d]" (if is-param "const " "") (car field) (cadr (cadr field)))
951 ;(message "foo %s %s" field (member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)))
952 (format "%s %s"
953 (cond ((member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))
954 (format "Serial%s%s" (cadr field) (if is-param " const*" "")))
955 ((equal (cadr field) 'string)
956 "const gchar*")
957 ((equal (cadr field) 'uint)
958 "guint32")
959 ((equal (cadr field) 'uint32)
960 "guint32")
961 ((equal (cadr field) 'uint16)
962 "guint16")
963 ((equal (cadr field) 'uint8)
964 "guint8")
965 ((equal (cadr field) 'boolean)
966 "gboolean")
967 ((equal (cadr field) 'bytes)
968 "const guint8*")
969 ((equal (cadr field) 'object)
970 "void*")
971 ((member (car (cadr field)) '(array ptr))
972 (concat (field-ctype (cadr field)) (if is-param " const*" "*")))
973 (t (error "unrecognized field type: %s" (cadr field))))
974 (car field)))
975 )
976
977(defun entry-arglist (need_first entry)
978 (concat
979 (if (and need_first (sertype-fields-get entry)) ", " "")
980 (format-comlist (function (lambda (x) x)) (entry-typename-pairs entry t))))
981
982(defun needs-ref (field)
983 (member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))
984 )
985
986(defun entry-plist (need_pbr need_first prefix entry)
987 (concat
988 (if (and need_first (sertype-fields-get entry)) ", " "")
989 (format-comlist (function (lambda (x) (format "%s" x)))
990 (entry-param-names prefix entry need_pbr))))
991
992(defun entry-unserialize-field (entry field name prefix)
993 (cond ((equal (cadr field) 'uint)
994 (format "%sif (! (* source->next_uint) (source, &%s)) goto bail;\n" prefix name))
995 ((equal (cadr field) 'uint32)
996 (format "%sif (! (* source->next_uint32) (source, &%s)) goto bail;\n" prefix name))
997 ((equal (cadr field) 'uint16)
998 (format "%sif (! (* source->next_uint16) (source, &%s)) goto bail;\n" prefix name))
999 ((equal (cadr field) 'uint8)
1000 (format "%sif (! (* source->next_uint8) (source, &%s)) goto bail;\n" prefix name))
1001 ((equal (cadr field) 'boolean)
1002 (format "%sif (! (* source->next_bool) (source, &%s)) goto bail;\n" prefix name))
1003 ((equal (cadr field) 'string)
1004 (format "%sif (! (* source->next_string) (source, &%s)) goto bail;\n" prefix name))
1005 ((equal (cadr field) 'bytes)
1006 (format "%sif (! (* source->next_bytes) (source, &%s, &%s_len)) goto bail;\n" prefix name name))
1007 ((equal (cadr field) 'object)
1008 (format "%sif (! serializeio_unserialize_generic_internal (source, &%s_type, &%s, FALSE)) goto bail;\n" prefix name name))
1009 ((member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))
1010 (format "%sif (! unserialize_%s_internal_noalloc (source, &%s)) goto bail;\n" prefix (downcase-string (cadr field)) name))
1011 ((and (equal (car (cadr field)) 'ptr)
1012 (member (cadr (cadr field)) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)))
1013 (format "%sif (! unserialize_%s_internal (source, &%s)) goto bail;\n" prefix (downcase-string (cadr (cadr field))) name))
1014 ((equal (car (cadr field)) 'bytes)
1015 (format "%sif (! (* source->next_bytes_known) (source, %s, %d)) goto bail;\n" prefix name (cadr (cadr field))))
1016 ((equal (car (cadr field)) 'array)
1017 (format "%s{
1018%s gint i;
1019%s if (! (* source->next_uint) (source, &%s_len)) goto bail;
1020%s if ((%s_len > 0) && ! (%s = serializeio_source_alloc (source, sizeof (%s) * %s_len))) goto bail;
1021%s for (i = 0; i < %s_len; i += 1)
1022%s {
1023%s%s }
1024%s}
1025"
1026 prefix
1027 prefix prefix
1028 name
1029 prefix
1030 name
1031 name
1032 (field-ctype (cadr field))
1033 name
1034 prefix
1035 name
1036 prefix
1037 prefix
1038 (entry-unserialize-field entry (cadr field) (concat "(" name "[i])") (concat prefix " "))
1039 prefix
1040 ))
1041 (t (error "unrecognized field type: %s" (cadr field)))))
1042
1043
1044(defun entry-serialize-field (entry field name prefix is-param)
1045 (cond ((equal (cadr field) 'uint)
1046 (format "%sif (! (* sink->next_uint) (sink, %s)) goto bail;\n" prefix name))
1047 ((equal (cadr field) 'uint16)
1048 (format "%sif (! (* sink->next_uint16) (sink, %s)) goto bail;\n" prefix name))
1049 ((equal (cadr field) 'uint8)
1050 (format "%sif (! (* sink->next_uint8) (sink, %s)) goto bail;\n" prefix name))
1051 ((equal (cadr field) 'uint32)
1052 (format "%sif (! (* sink->next_uint32) (sink, %s)) goto bail;\n" prefix name))
1053 ((equal (cadr field) 'boolean)
1054 (format "%sif (! (* sink->next_bool) (sink, %s)) goto bail;\n" prefix name))
1055 ((equal (cadr field) 'string)
1056 (format "%sif (! (* sink->next_string) (sink, %s)) goto bail;\n" prefix name))
1057 ((equal (cadr field) 'bytes)
1058 (format "%sif (! (* sink->next_bytes) (sink, %s, %s_len)) goto bail;\n" prefix name name))
1059 ((equal (cadr field) 'object)
1060 (format "%sif (! serializeio_serialize_generic_internal (sink, %s_type, %s, FALSE)) goto bail;\n" prefix name name))
1061 ((member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))
1062 (format "%sif (! serialize_%s_internal (sink%s)) goto bail;\n" prefix (downcase-string (cadr field))
1063 (entry-plist t t (concat name (if is-param "->" ".")) (obj-name-eq (cadr field) *all-sertype-defs*))))
1064 ((and (equal (car (cadr field)) 'ptr)
1065 (member (cadr (cadr field)) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)))
1066 (format "%sif (! serialize_%s_internal (sink%s)) goto bail;\n" prefix (downcase-string (cadr (cadr field)))
1067 (entry-plist t t (concat name "->") (obj-name-eq (cadr (cadr field)) *all-sertype-defs*))))
1068 ((equal (car (cadr field)) 'bytes)
1069 (format "%sif (! (* sink->next_bytes_known) (sink, %s, %d)) goto bail;\n" prefix name (cadr (cadr field))))
1070 ((equal (car (cadr field)) 'array)
1071 (format "%s{
1072%s gint i;
1073%s if (! (* sink->next_uint) (sink, %s_len)) goto bail;
1074%s for (i = 0; i < %s_len; i += 1)
1075%s {
1076%s%s }
1077%s}
1078"
1079 prefix prefix prefix
1080 name
1081 prefix
1082 name
1083 prefix
1084 prefix
1085 (entry-serialize-field entry (cadr field) (array-index name (cadr field)) (concat prefix " ") nil)
1086 prefix
1087 ))
1088 (t (error "unrecognized field type: %s" (cadr field)))))
1089
1090(defun array-index (name field)
1091 ;(concat "(" (if (needs-ref field) "&" "") name "[i])")
1092 (concat "(" name "[i])")
1093 )
1094
1095(defun entry-count-field (entry field name prefix is-param)
1096 (cond ((equal (cadr field) 'uint)
1097 ;(format "%ssize += sizeof (guint32);\n" prefix)
1098 ""
1099 )
1100 ((equal (cadr field) 'uint32)
1101 ;(format "%ssize += sizeof (guint32);\n" prefix)
1102 ""
1103 )
1104 ((equal (cadr field) 'uint16)
1105 ;(format "%ssize += sizeof (guint16);\n" prefix)
1106 ""
1107 )
1108 ((equal (cadr field) 'uint8)
1109 ;(format "%ssize += sizeof (guint8);\n" prefix)
1110 ""
1111 )
1112 ((equal (cadr field) 'boolean)
1113 ;(format "%ssize += sizeof (gboolean);\n" prefix)
1114 ""
1115 )
1116 ((equal (cadr field) 'string)
1117 (format "%ssize += strlen (%s) + 1;\n" prefix name)
1118 )
1119 ((equal (cadr field) 'bytes)
1120 (format "%ssize += %s_len;\n" prefix name)
1121 )
1122 ((equal (cadr field) 'object)
1123 (format "%ssize += serializeio_generic_count (%s_type, %s);\n" prefix name name)
1124 )
1125 ((member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))
1126 (format "%ssize += serializeio_count_%s_obj (%s%s) - sizeof (Serial%s);\n"
1127 prefix
1128 (downcase-string (cadr field))
1129 (if is-param "" "& ")
1130 name
1131 (cadr field)
1132 )
1133 )
1134 ((and (equal (car (cadr field)) 'ptr)
1135 (member (cadr (cadr field)) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)))
1136 (format "%ssize += serializeio_count_%s_obj (%s);\n" prefix (downcase-string (cadr (cadr field))) name)
1137 )
1138 ((equal (car (cadr field)) 'bytes)
1139 ;(format "%ssize += 0;\n" prefix (cadr (cadr field)))
1140 ""
1141 )
1142 ((equal (car (cadr field)) 'array)
1143 (format "%s{
1144%s gint i;
1145%s for (i = 0; i < %s_len; i += 1)
1146%s {
1147%s%s }
1148%s}
1149"
1150 prefix prefix prefix
1151 name
1152 prefix
1153 prefix
1154 (entry-count-array-field entry (cadr field) (array-index name (cadr field)) (concat prefix " ") nil)
1155 prefix
1156 ))
1157 (t (error "unrecognized field type: %s" (cadr field)))))
1158
1159(defun entry-count-array-field (entry field name prefix is-param)
1160 (cond ((equal (cadr field) 'uint)
1161 (format "%ssize += sizeof (guint32);\n" prefix)
1162 )
1163 ((equal (cadr field) 'uint32)
1164 (format "%ssize += sizeof (guint32);\n" prefix)
1165 )
1166 ((equal (cadr field) 'uint16)
1167 (format "%ssize += sizeof (guint16);\n" prefix)
1168 )
1169 ((equal (cadr field) 'uint8)
1170 (format "%ssize += sizeof (guint8);\n" prefix)
1171 )
1172 ((equal (cadr field) 'boolean)
1173 (format "%ssize += sizeof (gboolean);\n" prefix)
1174 )
1175 ((equal (cadr field) 'string)
1176 (format "%ssize += strlen (%s) + 1 + sizeof (void*);\n" prefix name)
1177 )
1178 ((equal (cadr field) 'bytes)
1179 (error "can't do that: bytes1")
1180 )
1181 ((equal (cadr field) 'object)
1182 (error "can't do that: object")
1183 )
1184 ((member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))
1185 (format "%ssize += serializeio_count_%s_obj (%s%s);\n"
1186 prefix
1187 (downcase-string (cadr field))
1188 (if is-param "" "& ")
1189 name
1190 (cadr field)
1191 )
1192 )
1193 ((and (equal (car (cadr field)) 'ptr)
1194 (member (cadr (cadr field)) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)))
1195 (format "%ssize += serializeio_count_%s_obj (%s) + sizeof (void*);\n" prefix (downcase-string (cadr (cadr field))) name)
1196 )
1197 ((equal (car (cadr field)) 'bytes)
1198 (error "can't do that: bytes2")
1199 )
1200 ((equal (car (cadr field)) 'array)
1201 (error "can't do that: array")
1202 )
1203 (t (error "unrecognized field type: %s" (cadr field)))))
1204
1205(defun entry-print-field (entry field name prefix is-param)
1206 (concat
1207 (format "%sprint_spaces (indent_spaces);\n" prefix)
1208 (if is-param (format "%sg_print (\"%s = \");\n" prefix (car field)) "")
1209 (cond ((equal (cadr field) 'uint)
1210 (format "%sg_print (\"%%d\\n\", %s);\n" prefix name))
1211 ((equal (cadr field) 'uint32)
1212 (format "%sg_print (\"%%d\\n\", %s);\n" prefix name))
1213 ((equal (cadr field) 'uint16)
1214 (format "%sg_print (\"%%d\\n\", %s);\n" prefix name))
1215 ((equal (cadr field) 'uint8)
1216 (format "%sg_print (\"%%d\\n\", %s);\n" prefix name))
1217 ((equal (cadr field) 'boolean)
1218 (format "%sg_print (\"%%s\\n\", %s ? \"true\" : \"false\");\n" prefix name))
1219 ((equal (cadr field) 'string)
1220 (format "%sg_print (\"%%s\\n\", %s);\n" prefix name))
1221 ((equal (cadr field) 'bytes)
1222 (format "%sserializeio_print_bytes (%s, %s_len);\n" prefix name name))
1223 ((equal (cadr field) 'object)
1224 (concat
1225 (if is-param (format "%sg_print (\"{\\n\");\n" prefix) "")
1226 (format "%sserializeio_generic_print (%s_type, %s, indent_spaces + 2);\n" prefix name name)
1227 (format "%sprint_spaces (indent_spaces);\n;\n" prefix)
1228 (if is-param (format "%sg_print (\"}\\n\");\n" prefix) "")
1229 )
1230 )
1231 ((member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))
1232 (concat
1233 (if is-param (format "%sg_print (\"{\\n\");\n" prefix) "")
1234 (format "%sserializeio_print_%s_obj (& %s, indent_spaces + 2);\n" prefix (downcase-string (cadr field)) name name)
1235 (format "%sprint_spaces (indent_spaces);\n;\n" prefix)
1236 (if is-param (format "%sg_print (\"}\\n\");\n" prefix) "")
1237 )
1238 )
1239 ((and (equal (car (cadr field)) 'ptr)
1240 (member (cadr (cadr field)) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)))
1241 (concat
1242 (if is-param (format "%sg_print (\"{\\n\");\n" prefix) "")
1243 (format "%sserializeio_print_%s_obj (%s, indent_spaces + 2);\n"
1244 prefix (downcase-string (cadr (cadr field))) name name)
1245 (format "%sprint_spaces (indent_spaces);\n;\n" prefix)
1246 (if is-param (format "%sg_print (\"}\\n\");\n" prefix) "")
1247 )
1248 )
1249 ((equal (car (cadr field)) 'bytes)
1250 (format "%sserializeio_print_bytes (%s, %d);\n" prefix name (cadr (cadr field))))
1251 ((equal (car (cadr field)) 'array)
1252 (concat
1253 (if is-param (format "%sg_print (\"{\\n\");\n" prefix) "")
1254 (format "%s{
1255%s gint i;
1256%s for (i = 0; i < %s_len; i += 1)
1257%s {
1258%s print_spaces (indent_spaces);
1259%s g_print (\"%%d:\\n\", i);
1260%s%s }
1261%s}
1262"
1263 prefix prefix prefix
1264 name
1265 prefix
1266 prefix
1267 prefix
1268 prefix
1269 (entry-print-field entry (cadr field) (array-index name (cadr field)) (concat prefix " ") nil)
1270 prefix
1271 )
1272 (if is-param (format "%sg_print (\"}\\n\");\n" prefix) "")))
1273 (t (error "unrecognized field type: %s" (cadr field)))))
1274 )
1275
1276(defconst *event-id* 0)
1277
1278(defconst *event-types* nil)
1279
1280(defun generate-events ()
1281 (let ((events *event-defs*))
1282 (while events
1283
1284 (let* ((event (car events))
1285 (uargs (event-uargs-get event))
1286 (sargs (event-sargs-get event))
1287 (type-prefix (intern (apply (function concat)
1288 (append (mapcar (function (lambda (x) (capitalize1 (cadr x)))) uargs)
1289 (mapcar (function (lambda (x) (capitalize1 x))) sargs)))))
1290 (capprefix (capitalize1 *output-prefix*)))
1291
1292 (if (and (not uargs) (not sargs))
1293 (setq type-prefix "Void"))
1294
1295 (when (not (member type-prefix *event-types*))
1296 (setq *event-types* (cons type-prefix *event-types*))
1297
1298 (output-header-file "_edsio")
1299
1300 (save-excursion
1301 (goto-char *header-typedef-marker*)
1302
1303 (insert (format "/* %s%sEventCode.\n */\n\n" capprefix type-prefix))
1304
1305 (insert (format "typedef struct _%s%sEventCode %s%sEventCode;\n" capprefix type-prefix capprefix type-prefix))
1306 (insert (format "struct _%s%sEventCode { gint code; };\n\n" capprefix type-prefix))
1307
1308 (insert (format "typedef struct _%s%sEvent %s%sEvent;\n" capprefix type-prefix capprefix type-prefix))
1309 (insert (format "struct _%s%sEvent { gint code; const char* srcfile; guint srcline;%s%s };\n\n" capprefix type-prefix (event-struct-entries event) (event-struct-sys-entries event)))
1310 )
1311
1312 (insert (format "void %s_generate_%s_event_internal (%s%sEventCode code, const char* srcfile, gint srcline%s);\n"
1313 *output-prefix*
1314 (downcase-string type-prefix)
1315 capprefix
1316 type-prefix
1317 (event-uargs-plist uargs t)
1318 ))
1319 (insert (format "#define %s_generate_%s_event(ecode%s) %s_generate_%s_event_internal((ecode),__FILE__,__LINE__%s)\n\n"
1320 *output-prefix*
1321 (downcase-string type-prefix)
1322 (event-uargs-alist uargs t)
1323 *output-prefix*
1324 (downcase-string type-prefix)
1325 (event-uargs-mlist uargs t)))
1326
1327 (output-source-file "_edsio")
1328
1329 (insert (format "void\n%s_generate_%s_event_internal (%s%sEventCode _code, const char* _srcfile, gint _srcline%s)\n"
1330 *output-prefix*
1331 (downcase-string type-prefix)
1332 capprefix
1333 type-prefix
1334 (event-uargs-plist uargs t)
1335 ))
1336 (insert (format "{\n"))
1337 (insert (format " %s%sEvent *_e = g_new0 (%s%sEvent, 1);\n" capprefix type-prefix capprefix type-prefix))
1338 (insert (format " _e->code = _code.code;\n _e->srcline = _srcline;\n _e->srcfile = _srcfile;\n"))
1339 (insert (event-uargs-copy "_e" event))
1340 (insert (event-sargs-copy "_e" event))
1341 (insert (format " eventdelivery_event_deliver ((GenericEvent*) _e);\n"))
1342 (insert (format "}\n\n"))
1343
1344 ;; Field to string def
1345
1346 (unless (equal type-prefix "Void")
1347 (save-excursion
1348 (goto-char *source-top-marker*)
1349 (insert (format "static const char* %s_%s_event_field_to_string (GenericEvent* ev, gint field);\n" capprefix type-prefix))
1350 )
1351
1352 (insert (format "const char*\n%s_%s_event_field_to_string (GenericEvent* ev, gint field)\n"
1353 capprefix type-prefix))
1354 (insert (format "{\n"))
1355
1356 (unless (equal type-prefix (intern "Ssl"))
1357 (insert (format " %s%sEvent* it = (%s%sEvent*) ev;\n" capprefix type-prefix capprefix type-prefix)))
1358 (insert (format " switch (field)\n"))
1359 (insert (format " {\n"))
1360
1361 (let ((uargs (event-uargs-get event))
1362 (i 0))
1363 (while uargs
1364 (let ((uarg (car uargs)))
1365 (insert (format " case %d: return eventdelivery_%s_to_string (it->%s);\n" i (cadr uarg) (car uarg)))
1366 )
1367 (setq i (+ i 1))
1368 (setq uargs (cdr uargs))
1369 )
1370 )
1371
1372 (if (< 1 (length (event-sargs-get event)))
1373 (error "unhandled case, too many sargs"))
1374
1375 (when (event-sargs-get event)
1376 (let ((sarg (car (event-sargs-get event))))
1377 (insert (format " case %d: " (length (event-uargs-get event))))
1378
1379 (if (not (member sarg '(ssl errno)))
1380 (error "what type of sarg is %s" sarg))
1381
1382 (if (eq sarg 'errno)
1383 (insert (format "return g_strdup (g_strerror (it->ev_errno));\n")))
1384
1385 (if (eq sarg 'ssl)
1386 (insert (format "return eventdelivery_ssl_errors_to_string ();\n")))
1387 )
1388 )
1389
1390 (insert (format " default: abort ();\n"))
1391 (insert (format " }\n"))
1392
1393 (insert (format "}\n\n"))
1394 )
1395 )
1396
1397 (output-header-file "_edsio")
1398
1399 (insert (format "extern const %s%sEventCode EC_%s%s;\n"
1400 capprefix
1401 type-prefix
1402 capprefix
1403 (event-name-get event)))
1404
1405 (insert (format "#define EC_%s%sValue ((%d<<EDSIO_LIBRARY_OFFSET_BITS)+%d)\n\n"
1406 capprefix
1407 (event-name-get event)
1408 *event-id*
1409 *library-id*))
1410
1411 (output-source-file "_edsio")
1412
1413 (insert (format "const %s%sEventCode EC_%s%s = { EC_%s%sValue };\n\n"
1414 capprefix
1415 type-prefix
1416 capprefix
1417 (event-name-get event)
1418 capprefix
1419 (event-name-get event)))
1420
1421
1422 (save-excursion
1423 (goto-char *source-init-marker*)
1424
1425 (insert (format " eventdelivery_initialize_event_def (EC_%s%sValue, EL_%s, %s, \"%s\", \"%s\", %s);\n"
1426 capprefix
1427 (event-name-get event)
1428 (event-level-get event)
1429 (event-flags-string event)
1430 (event-name-get event)
1431 (fixup-oneline event (event-desc-get event))
1432 (if (equal type-prefix "Void")
1433 "NULL"
1434 (format "& %s_%s_event_field_to_string" capprefix type-prefix))))
1435 )
1436
1437 (setq *event-id* (+ 1 *event-id*))
1438
1439 )
1440
1441 (setq events (cdr events))
1442 )
1443 )
1444 )
1445
1446(defun event-flags-string (event)
1447 (if (member 'ssl (event-sargs-get event))
1448 "EF_OpenSSL"
1449 "EF_None")
1450 )
1451
1452(defun event-struct-entries (event)
1453 (apply (function concat)
1454 (mapcar (function (lambda (x) (format " %s %s;" (event-type-to-ctype (cadr x)) (car x))))
1455 (event-uargs-get event)))
1456 )
1457
1458(defun event-struct-sys-entries (event)
1459 (if (member 'errno (event-sargs-get event))
1460 " gint ev_errno;"
1461 "")
1462 )
1463
1464(defun event-uargs-copy (name event)
1465 (apply (function concat)
1466 (mapcar (function (lambda (x) (format " %s->%s = %s;\n" name (car x) (car x))))
1467 (event-uargs-get event)))
1468 )
1469
1470(defun event-sargs-copy (name event)
1471 (if (member 'errno (event-sargs-get event))
1472 (format " %s->ev_errno = errno;\n" name)
1473 "")
1474 )
1475
1476(defun event-type-to-ctype (etype)
1477 (let ((it (obj-name-eq etype *all-etype-defs*)))
1478 (if (not it)
1479 (message "no ctype for %s" etype))
1480 (etype-ctype-get it)
1481 )
1482 )
1483
1484(defun event-uargs-plist(uargs need_first)
1485 (concat
1486 (if (and need_first uargs) ", " "")
1487 (format-comlist (function (lambda (x) (format "%s %s" (event-type-to-ctype (cadr x)) (car x)))) uargs))
1488 )
1489
1490(defun event-uargs-alist(uargs need_first)
1491 (concat
1492 (if (and need_first uargs) ", " "")
1493 (format-comlist (function (lambda (x) (format "%s" (car x)))) uargs))
1494 )
1495
1496(defun event-uargs-mlist(uargs need_first)
1497 (concat
1498 (if (and need_first uargs) ", " "")
1499 (format-comlist (function (lambda (x) (format "(%s)" (car x)))) uargs))
1500 )
1501
1502(defun fixup-oneline (event oneline)
1503 (let ((work (get-buffer-create "*string-tmp2*")))
1504 (save-excursion
1505 (set-buffer work)
1506 (erase-buffer)
1507 (insert oneline)
1508 (beginning-of-buffer)
1509
1510 (while (re-search-forward "${\\(\\w+\\)}" nil t)
1511
1512 (let* ((it (intern (downcase-string (match-string 1))))
1513 (uargs (event-uargs-get event))
1514 (i 0)
1515 (repl nil))
1516
1517 (while uargs
1518
1519 (if (eq (car (car uargs)) it)
1520 (setq repl (format "${%d}" i)))
1521
1522 (setq uargs (cdr uargs))
1523 (setq i (+ i 1))
1524 )
1525
1526 (when (eq it 'strerror)
1527 (if repl
1528 (error "No wildcards named STRERROR"))
1529 (setq repl (format "${%d}" i))
1530 )
1531
1532 (when (eq it 'ssl)
1533 (if repl
1534 (error "No wildcards named SSL"))
1535 (setq repl (format "${%d}" i))
1536 )
1537
1538 (if (not repl)
1539 (error "Illegal wildcard %s in %s" it oneline))
1540
1541 (replace-match repl nil nil)
1542 )
1543 )
1544
1545 (buffer-string)
1546 )
1547 )
1548 )
1549
1550;; Properties
1551
1552(defun generate-properties ()
1553 (let ((cap-prefix (capitalize1 *output-prefix*))
1554 (unique-types nil))
1555 (output-header-file "_edsio")
1556
1557 (insert (format "/* Property definitions */\n\n"))
1558
1559 ;; Types
1560
1561 (output-source-file "_edsio")
1562
1563 (mapcar
1564 (function
1565 (lambda (pht)
1566 (let ((type (prophosttype-type-get pht)))
1567 (unless (member type unique-types)
1568 (setq unique-types (cons type unique-types))
1569
1570 (save-excursion
1571 (goto-char *source-init-marker*)
1572
1573 ;(message "%s -> %s %s" type (type-free-func type) (member type (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)))
1574
1575 (insert (format " edsio_initialize_property_type (\"%s\", %s, %s, %s, %s, %s);\n"
1576 type
1577 (type-free-func type)
1578 (type-gs-func type "getter")
1579 (type-gs-func type "setter")
1580 (type-serialize-func type)
1581 (type-unserialize-func type)))
1582 )
1583 )
1584 )
1585 )
1586 )
1587 *prophosttype-defs*
1588 )
1589
1590 ;; Host reg
1591
1592 (mapcar
1593 (function
1594 (lambda (prophost)
1595 (save-excursion
1596 (goto-char *source-init-marker*)
1597 (insert (format " edsio_initialize_host_type (\"%s\", %s, %s, %s, %s, %s);\n"
1598 (prophost-name-get prophost)
1599 (format "(PropertyTableFunc) & edsio_%s_property_table"
1600 (downcase-string (prophost-name-get prophost)))
1601 (prophost-persist prophost "source")
1602 (prophost-persist prophost "sink")
1603 (prophost-persist prophost "isset")
1604 (prophost-persist prophost "unset")
1605 ))
1606 )
1607 )
1608 )
1609 *prophost-defs*)
1610
1611 ;; Compute each distinct (host type) x (prop type)
1612
1613 (mapcar
1614 (function
1615 (lambda (prophost)
1616
1617 (mapcar
1618 (function
1619 (lambda (prophosttype)
1620
1621 (when (equal (prophosttype-host-get prophosttype) (prophost-name-get prophost))
1622
1623 (when (not (member (prophosttype-type-get prophosttype) (prophost-proptypes-get prophost)))
1624 (prophost-proptypes-set prophost (cons (prophosttype-type-get prophosttype) (prophost-proptypes-get prophost)))
1625 )
1626 )))
1627 *prophosttype-defs*
1628 )
1629
1630 ;; Output the get/set functions for each property type
1631
1632 (mapcar
1633 (function
1634 (lambda (type)
1635
1636 (let ((it (property-code-typename type prophost)))
1637
1638 ;; Header
1639
1640 (output-header-file "_edsio")
1641
1642 (insert (format "/* Property get/set for %s/%s\n */\n\n" (prophost-name-get prophost) type))
1643
1644 (insert (format "typedef struct _%s %s;\n" it it))
1645
1646 (insert (format "struct _%s { guint32 code; };\n\n" it))
1647
1648 (insert (format "gboolean edsio_new_%s_%s_property (const char* name, guint32 flags, %s* prop);\n"
1649 (downcase-string (prophost-name-get prophost))
1650 (type-canon-name type)
1651 it
1652 ))
1653
1654 (insert (format "gboolean %s_get_%s (%s obj, %s prop%s);\n"
1655 (downcase-string (prophost-name-get prophost))
1656 (type-canon-name type)
1657 (prophost-ctype-get prophost)
1658 it
1659 (prop-type-to-get-fps type)))
1660
1661 (insert (format "gboolean %s_set_%s (%s obj, %s prop%s);\n"
1662 (downcase-string (prophost-name-get prophost))
1663 (type-canon-name type)
1664 (prophost-ctype-get prophost)
1665 it
1666 (prop-type-to-set-fps type)))
1667
1668 (insert (format "gboolean %s_unset_%s (%s obj, %s prop);\n"
1669 (downcase-string (prophost-name-get prophost))
1670 (type-canon-name type)
1671 (prophost-ctype-get prophost)
1672 it))
1673
1674 (insert (format "gboolean %s_isset_%s (%s obj, %s prop);\n\n"
1675 (downcase-string (prophost-name-get prophost))
1676 (type-canon-name type)
1677 (prophost-ctype-get prophost)
1678 it))
1679
1680 ;; Source
1681
1682 (output-source-file "_edsio")
1683
1684 (insert (format "gboolean edsio_new_%s_%s_property (const char* name, guint32 flags, %s* prop)\n{\n"
1685 (downcase-string (prophost-name-get prophost))
1686 (type-canon-name type)
1687 it
1688 ))
1689 (insert (format " return edsio_new_property (name, \"%s\", \"%s\", flags, (EdsioGenericProperty*) prop);\n" (prophost-name-get prophost) type))
1690 (insert (format "}\n\n"))
1691
1692 (insert (format "gboolean\n%s_get_%s (%s obj, %s prop%s)\n{\n"
1693 (downcase-string (prophost-name-get prophost))
1694 (type-canon-name type)
1695 (prophost-ctype-get prophost)
1696 it
1697 (prop-type-to-get-fps type)))
1698 (insert (format " EdsioProperty* ep;\n"))
1699 (insert (format " g_return_val_if_fail (obj, FALSE);\n"))
1700 (insert (format " return (* edsio_property_getter (\"%s\", \"%s\", prop.code, & ep)) (obj, ep%s);\n"
1701 (prophost-name-get prophost)
1702 type
1703 (prop-type-to-args type)
1704 ))
1705
1706 (insert (format "}\n\n"))
1707
1708 (insert (format "gboolean\n%s_set_%s (%s obj, %s prop%s)\n{\n"
1709 (downcase-string (prophost-name-get prophost))
1710 (type-canon-name type)
1711 (prophost-ctype-get prophost)
1712 it
1713 (prop-type-to-set-fps type)))
1714 (insert (format " EdsioProperty* ep;\n"))
1715 (insert (format " g_return_val_if_fail (obj, FALSE);\n"))
1716 (insert (format " return (* edsio_property_setter (\"%s\", \"%s\", prop.code, & ep)) (obj, ep%s);\n"
1717 (prophost-name-get prophost)
1718 type
1719 (prop-type-to-args type)
1720 ))
1721
1722 (insert (format "}\n\n"))
1723
1724 (insert (format "gboolean\n%s_unset_%s (%s obj, %s prop)\n{\n"
1725 (downcase-string (prophost-name-get prophost))
1726 (type-canon-name type)
1727 (prophost-ctype-get prophost)
1728 it))
1729 (insert (format " g_return_val_if_fail (obj, FALSE);\n"))
1730 (insert (format " return edsio_property_unset (\"%s\", \"%s\", prop.code, obj);\n"
1731 (prophost-name-get prophost)
1732 type
1733 ""
1734 ))
1735
1736 (insert (format "}\n\n"))
1737
1738 (insert (format "gboolean\n%s_isset_%s (%s obj, %s prop)\n{\n"
1739 (downcase-string (prophost-name-get prophost))
1740 (type-canon-name type)
1741 (prophost-ctype-get prophost)
1742 it))
1743 (insert (format " g_return_val_if_fail (obj, FALSE);\n"))
1744 (insert (format " return edsio_property_isset (\"%s\", \"%s\", prop.code, obj);\n"
1745 (prophost-name-get prophost)
1746 type
1747 ))
1748
1749 (insert (format "}\n\n"))
1750
1751 )
1752 )
1753 )
1754 (prophost-proptypes-get prophost)
1755 )
1756 )
1757 )
1758 *all-prophost-defs*
1759 )
1760 )
1761 )
1762
1763(defun property-code-typename(type prophost)
1764 (format "%s%s%sProperty"
1765 (capitalize1 *output-prefix*)
1766 (prophost-name-get prophost)
1767 (capitalize1 type))
1768 )
1769
1770(defun prop-typename-ctypes (type)
1771 (cond ((equal type 'string)
1772 (list (list 'arg "const gchar*")))
1773 ((equal type 'uint)
1774 (list (list 'arg "guint32")))
1775 ((equal type 'uint32)
1776 (list (list 'arg "guint32")))
1777 ((equal type 'uint16)
1778 (list (list 'arg "guint16")))
1779 ((equal type 'uint8)
1780 (list (list 'arg "guint8")))
1781 ((equal type 'boolean)
1782 (list (list 'arg "gboolean")))
1783 ((equal type 'bytes)
1784 (list (list 'arg "const guint8*") (list 'arg_len "guint32")))
1785 ((equal type 'object)
1786 (list (list 'arg "void*") (list 'arg_type "guint32")))
1787 ((member type (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))
1788 (list (list 'arg (format "Serial%s*" type))))
1789 ((equal (car type) 'bytes)
1790 (list (list 'arg "const guint8*")))
1791 ((equal (car type) 'array)
1792 (list (list 'arg (format "%s*" (cadr (car (prop-typename-ctypes (cadr type))))))
1793 (list 'arg_len "guint32")))
1794 ((equal (car type) 'ptr)
1795 (list (list 'arg (format "%s*" (cadr (car (prop-typename-ctypes (cadr type))))))))
1796 (t (error "unrecognized field type: %s" type)))
1797 )
1798
1799(defun prop-type-to-get-fps (type)
1800 (concat ", "
1801 (format-comlist
1802 (function
1803 (lambda (pair)
1804 (format "%s* %s" (cadr pair) (car pair))
1805 )
1806 )
1807 (prop-typename-ctypes type))
1808 )
1809 )
1810
1811(defun prop-type-to-set-fps (type)
1812 (concat ", "
1813 (format-comlist
1814 (function
1815 (lambda (pair)
1816 (format "%s %s" (cadr pair) (car pair))
1817 )
1818 )
1819 (prop-typename-ctypes type))
1820 )
1821 )
1822
1823(defun prop-type-to-args (type)
1824 (concat ", "
1825 (format-comlist
1826 (function
1827 (lambda (pair)
1828 (format "%s" (car pair))
1829 )
1830 )
1831 (prop-typename-ctypes type))
1832 )
1833 )
1834
1835(defun type-canon-name (type)
1836 ; @@@ does not work for (array ...), etc
1837 (downcase-string type))
1838
1839(defun type-serialize-func (type)
1840 (format "serialize_%s_obj" (downcase-string type))
1841 )
1842
1843(defun type-unserialize-func (type)
1844 (format "unserialize_%s" (downcase-string type))
1845 )
1846
1847(defun type-gs-func (type name)
1848 (if (member type (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))
1849 (format "& edsio_property_vptr_%s" name)
1850 (format "& edsio_property_%s_%s" type name)))
1851
1852(defun type-free-func (type)
1853 (if (member type (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))
1854 (format "& edsio_property_vptr_free")
1855 (format "& edsio_property_%s_free" type)))
1856
1857(defun prophost-persist (prophost func)
1858 (if (prophost-persist-get prophost)
1859 (format "(Persist%sFunc) & %s_persist_%s_%s"
1860 (capitalize1 func)
1861 *output-prefix*
1862 (downcase-string (prophost-name-get prophost))
1863 func)
1864 "NULL"))
diff --git a/xdelta1/libedsio/edsio.h b/xdelta1/libedsio/edsio.h
deleted file mode 100644
index 98f899e..0000000
--- a/xdelta1/libedsio/edsio.h
+++ /dev/null
@@ -1,531 +0,0 @@
1/* -*-Mode: C;-*-
2 * $Id: edsio.h 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $
3 *
4 * Copyright (C) 1998, 1999, Josh MacDonald.
5 * All Rights Reserved.
6 *
7 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
8 */
9
10#ifndef _EDSIO_H_
11#define _EDSIO_H_
12
13#ifdef __cplusplus
14extern "C" {
15#endif
16
17#ifdef HAVE_CONFIG_H
18#include <config.h>
19#endif
20
21#include <stdlib.h>
22#include <string.h>
23#include <glib.h>
24
25typedef struct _SerialSource SerialSource;
26typedef struct _SerialSink SerialSink;
27typedef gint32 SerialType;
28typedef struct _HandleFuncTable HandleFuncTable;
29typedef struct _PropTest PropTest;
30typedef struct _FileHandle FileHandle;
31typedef struct _AllocList AllocList;
32
33struct _FileHandle {
34 const HandleFuncTable* table;
35
36 /* This is an opaque type, feel free to define your own, just make
37 * sure that the first field of yours is one of these, and that you
38 * supply a table. */
39};
40
41#define EDSIO_LIBRARY_OFFSET_BITS 8
42#define EDSIO_LIBRARY_OFFSET_MASK 0xff
43
44#include "edsio_edsio.h"
45
46#define ST_Error -1
47#define ST_IncorrectType -2
48#define ST_NotFound -3
49
50#define ALIGN_8(v) if (((v) % 8) != 0) { (v) += 8; (v) &= ~7; }
51
52/* This serves as a virtual table for I/O to the FileHandle */
53struct _HandleFuncTable
54{
55 gssize (* table_handle_length) (FileHandle *fh);
56 gssize (* table_handle_pages) (FileHandle *fh);
57 gssize (* table_handle_pagesize) (FileHandle *fh);
58 gssize (* table_handle_map_page) (FileHandle *fh, guint pgno, const guint8** mem);
59 gboolean (* table_handle_unmap_page) (FileHandle *fh, guint pgno, const guint8** mem);
60 const guint8* (* table_handle_checksum_md5) (FileHandle *fh);
61 gboolean (* table_handle_close) (FileHandle *fh, gint flags);
62 gboolean (* table_handle_write) (FileHandle *fh, const guint8 *buf, gsize nbyte);
63 gboolean (* table_handle_copy) (FileHandle *from, FileHandle *to, guint off, guint len);
64 gboolean (* table_handle_getui) (FileHandle *fh, guint32* i);
65 gboolean (* table_handle_putui) (FileHandle *fh, guint32 i);
66 gssize (* table_handle_read) (FileHandle *fh, guint8 *buf, gsize nbyte);
67 const gchar* (* table_handle_name) (FileHandle *fh); /* user must free */
68};
69
70struct _AllocList {
71 AllocList *next;
72 void *ptr;
73};
74
75struct _SerialSource {
76 /* Internal variables: don't touch. */
77 AllocList *alloc_list;
78
79 /* These are setup by init.
80 */
81 SerialType (* source_type) (SerialSource* source, gboolean set_allocation);
82 gboolean (* source_close) (SerialSource* source);
83 gboolean (* source_read) (SerialSource* source, guint8 *ptr, guint32 len);
84 void (* source_free) (SerialSource* source);
85
86 /* These may be NULL
87 */
88 void* (* salloc_func) (SerialSource* source,
89 guint32 len);
90 void (* sfree_func) (SerialSource* source,
91 void* ptr);
92
93 /* Public functions, defaulted, but may be over-ridden
94 * before calls to unserialize.
95 */
96 gboolean (* next_bytes_known) (SerialSource* source, guint8 *ptr, guint32 len);
97 gboolean (* next_bytes) (SerialSource* source, const guint8 **ptr, guint32 *len);
98 gboolean (* next_uint) (SerialSource* source, guint32 *ptr);
99 gboolean (* next_uint32) (SerialSource* source, guint32 *ptr);
100 gboolean (* next_uint16) (SerialSource* source, guint16 *ptr);
101 gboolean (* next_uint8) (SerialSource* source, guint8 *ptr);
102 gboolean (* next_bool) (SerialSource* source, gboolean *ptr);
103 gboolean (* next_string) (SerialSource* source, const char **ptr);
104};
105
106struct _SerialSink {
107
108 /* These are setup by init.
109 */
110 gboolean (* sink_type) (SerialSink* sink, SerialType type, guint32 mem_size, gboolean set_allocation);
111 gboolean (* sink_close) (SerialSink* sink);
112 gboolean (* sink_write) (SerialSink* sink, const guint8 *ptr, guint32 len);
113 void (* sink_free) (SerialSink* sink);
114
115 /* This may be null, called after each object is serialized. */
116 gboolean (* sink_quantum) (SerialSink* sink);
117
118 /* Public functions, defaulted, but may be over-ridden
119 * before calls to serialize.
120 */
121 gboolean (* next_bytes_known) (SerialSink* sink, const guint8 *ptr, guint32 len);
122 gboolean (* next_bytes) (SerialSink* sink, const guint8 *ptr, guint32 len);
123 gboolean (* next_uint) (SerialSink* sink, guint32 ptr);
124 gboolean (* next_uint32) (SerialSink* sink, guint32 ptr);
125 gboolean (* next_uint16) (SerialSink* sink, guint16 ptr);
126 gboolean (* next_uint8) (SerialSink* sink, guint8 ptr);
127 gboolean (* next_bool) (SerialSink* sink, gboolean ptr);
128 gboolean (* next_string) (SerialSink* sink, const char *ptr);
129};
130
131void serializeio_initialize_type (const char* name,
132 guint32 val,
133 gboolean (*unserialize_func) (),
134 gboolean (*serialize_func) (),
135 guint (*count_func) (),
136 void (*print_func) ());
137
138const char* serializeio_generic_type_to_string (SerialType type);
139void serializeio_generic_print (SerialType type, void* object, guint indent_spaces);
140
141gboolean serializeio_serialize_generic (SerialSink *sink,
142 SerialType object_type,
143 void *object);
144
145gboolean serializeio_serialize_generic_internal (SerialSink *sink,
146 SerialType object_type,
147 void *object,
148 gboolean set_allocation);
149
150guint serializeio_generic_count (SerialType object_type,
151 void *object);
152
153gboolean serializeio_unserialize_generic (SerialSource *source,
154 SerialType *object_type,
155 void **object);
156
157gboolean serializeio_unserialize_generic_internal (SerialSource *source,
158 SerialType *object_type,
159 void **object,
160 gboolean set_allocation);
161
162gboolean serializeio_unserialize_generic_acceptable (SerialSource* source,
163 guint32 acceptable,
164 SerialType *object_type,
165 void **object);
166
167void serializeio_sink_init (SerialSink* sink,
168 gboolean (* sink_type) (SerialSink* sink,
169 SerialType type,
170 guint32 mem_size,
171 gboolean set_allocation),
172 gboolean (* sink_close) (SerialSink* sink),
173 gboolean (* sink_write) (SerialSink* sink,
174 const guint8 *ptr,
175 guint32 len),
176 void (* sink_free) (SerialSink* sink),
177 gboolean (* sink_quantum) (SerialSink* sink));
178
179void serializeio_source_init (SerialSource* source,
180 SerialType (* source_type) (SerialSource* source,
181 gboolean set_allocation),
182 gboolean (* source_close) (SerialSource* source),
183 gboolean (* source_read) (SerialSource* source,
184 guint8 *ptr,
185 guint32 len),
186 void (* source_free) (SerialSource* source),
187 void* (* salloc_func) (SerialSource* source,
188 guint32 len),
189 void (* sfree_func) (SerialSource* source,
190 void* ptr));
191
192/* This function is internal, don't use. */
193void* serializeio_source_alloc (SerialSource* source,
194 guint32 len);
195
196SerialSink* serializeio_gzip_sink (SerialSink* sink);
197SerialSource* serializeio_gzip_source (SerialSource* source);
198
199SerialSink* serializeio_checksum_sink (SerialSink* sink);
200SerialSource* serializeio_checksum_source (SerialSource* source);
201
202SerialSink* serializeio_base64_sink (SerialSink* sink);
203SerialSource* serializeio_base64_source (SerialSource* source);
204
205SerialSource* handle_source (FileHandle *fh);
206SerialSink* handle_sink (FileHandle *fh,
207 gpointer data1,
208 gpointer data2,
209 gpointer data3,
210 gboolean (* cont_onclose) (gpointer data1, gpointer data2, gpointer data3));
211
212gboolean unserialize_uint (SerialSource *source, guint32** x);
213gboolean serialize_uint_obj (SerialSink *sink, guint32* x);
214
215gboolean unserialize_string (SerialSource *source, const char** x);
216gboolean serialize_string_obj (SerialSink *sink, const char* x);
217
218/* These are a bit odd, and edsio_property_bytes_{g,s}etter account for it.
219 * Try not to use yourself. */
220gboolean unserialize_bytes (SerialSource *source, SerialEdsioBytes** x);
221gboolean serialize_bytes_obj (SerialSink *sink, SerialEdsioBytes *x);
222
223/* Event delivery
224 */
225
226enum _EventLevel
227{
228 EL_Information = 1<<0,
229 EL_Warning = 1<<5,
230 EL_Error = 1<<10,
231 EL_InternalError = 1<<15,
232 EL_FatalError = 1<<20
233};
234
235typedef enum _EventLevel EventLevel;
236
237enum _EventFlags
238{
239 EF_None = 1<<0,
240 EF_OpenSSL = 1<<1
241};
242
243typedef enum _EventFlags EventFlags;
244
245const char* eventdelivery_int_to_string (int x);
246const char* eventdelivery_string_to_string (const char* x);
247const char* eventdelivery_source_to_string (SerialSource* x);
248const char* eventdelivery_sink_to_string (SerialSink* x);
249const char* eventdelivery_handle_to_string (FileHandle* x);
250
251void serializeio_print_bytes (const guint8* buf, guint len);
252
253/* Event delivery privates
254 */
255
256typedef struct _GenericEventDef GenericEventDef;
257typedef struct _GenericEvent GenericEvent;
258
259struct _GenericEvent
260{
261 gint code;
262 const char* srcfile;
263 guint srcline;
264};
265
266GenericEventDef* eventdelivery_event_lookup (gint code);
267
268void eventdelivery_event_deliver (GenericEvent* e);
269
270typedef gboolean (* ErrorDeliveryFunc) (GenericEvent* ev, GenericEventDef* def, const char* message);
271
272void eventdelivery_event_watch_all (ErrorDeliveryFunc func);
273
274void eventdelivery_initialize_event_def (gint code,
275 gint level,
276 gint flags,
277 const char* name,
278 const char* oneline,
279 const char * (* field_to_string) (GenericEvent* ev, gint field));
280
281const char* eventdelivery_ssl_errors_to_string (void);
282
283struct _GenericEventDef
284{
285 gint code;
286 gint level;
287 gint flags;
288 const char *name;
289 const char *oneline;
290
291 const char * (* field_to_string) (GenericEvent* ev, gint field);
292};
293
294/* MD5.H - header file for MD5C.C */
295
296/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
297 rights reserved.
298
299 License to copy and use this software is granted provided that it
300 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
301 Algorithm" in all material mentioning or referencing this software
302 or this function.
303
304 License is also granted to make and use derivative works provided
305 that such works are identified as "derived from the RSA Data
306 Security, Inc. MD5 Message-Digest Algorithm" in all material
307 mentioning or referencing the derived work.
308
309 RSA Data Security, Inc. makes no representations concerning either
310 the merchantability of this software or the suitability of this
311 software for any particular purpose. It is provided "as is"
312 without express or implied warranty of any kind.
313
314 These notices must be retained in any copies of any part of this
315 documentation and/or software.
316 */
317
318/* MD5 context. */
319typedef struct {
320 guint32 state[4]; /* state (ABCD) */
321 guint32 count[2]; /* number of bits, modulo 2^64 (lsb first) */
322 guint8 buffer[64]; /* input buffer */
323} EdsioMD5Ctx;
324
325void edsio_md5_init (EdsioMD5Ctx *);
326void edsio_md5_update (EdsioMD5Ctx *, const guint8 *, guint);
327void edsio_md5_final (guint8*, EdsioMD5Ctx *);
328
329gint edsio_md5_equal (gconstpointer v,
330 gconstpointer v2);
331guint edsio_md5_hash (gconstpointer v);
332
333void edsio_md5_to_string (const guint8* md5, char buf[33]);
334gboolean edsio_md5_from_string (guint8* md5, const char buf[33]);
335
336/* NIST Secure Hash Algorithm */
337/* heavily modified from Peter C. Gutmann's implementation */
338/* then taken from from Uwe Hollerbach, */
339/* and then modified a little by Josh MacDonald. */
340
341/* This code is in the public domain */
342
343typedef struct {
344 guint32 digest[5]; /* message digest */
345 guint32 count_lo, count_hi; /* 64-bit bit count */
346 guint32 data[16]; /* SHA data buffer */
347 int local; /* unprocessed amount in data */
348} EdsioSHACtx;
349
350void edsio_sha_init (EdsioSHACtx *);
351void edsio_sha_update (EdsioSHACtx *, const guint8 *, guint);
352void edsio_sha_final (guint8 *, EdsioSHACtx *);
353
354gint edsio_sha_equal (gconstpointer v,
355 gconstpointer v2);
356guint edsio_sha_hash (gconstpointer v);
357
358/* Misc stuff.
359 */
360
361/* These raise an error if errmsg is non-null. The errmsg should
362 * be something like "Invalid port number". See edsio.ser for the
363 * format.
364 */
365gboolean strtosi_checked (const char* str, gint32* i, const char* errmsg);
366gboolean strtoss_checked (const char* str, gint16* s, const char* errmsg);
367
368gboolean strtoui_checked (const char* str, guint32* i, const char* errmsg);
369gboolean strtous_checked (const char* str, guint16* i, const char* errmsg);
370
371const char* edsio_intern_string (const char* str);
372
373GByteArray* edsio_base64_encode_region (const guint8* data, guint data_len);
374GByteArray* edsio_base64_decode_region (const guint8* data, guint data_len);
375gboolean edsio_base64_encode_region_into (const guint8* data, guint data_len, guint8* out, guint *out_len);
376gboolean edsio_base64_decode_region_into (const guint8* data, guint data_len, guint8* out, guint *out_len);
377
378gchar* edsio_time_to_iso8601 (SerialGenericTime* time);
379gchar* edsio_time_t_to_iso8601 (GTime time);
380gboolean edsio_time_of_day (SerialGenericTime* time);
381
382enum _SimpleBufferFlags {
383 SBF_None = 0,
384 SBF_Compress = 1 << 0,
385 SBF_Checksum = 1 << 1,
386 SBF_Base64 = 1 << 2
387};
388
389typedef enum _SimpleBufferFlags SimpleBufferFlags;
390
391SerialSource* edsio_simple_source (const guint8* data, guint len, guint flags);
392SerialSink* edsio_simple_sink (gpointer data,
393 guint flags,
394 gboolean free_result,
395 void (* success) (gpointer data, GByteArray* result),
396 GByteArray **result);
397
398gboolean edsio_library_check (guint32 number);
399void edsio_library_register (guint32 number, const char*name);
400
401/* (Persistent) Property stuff.
402 */
403
404enum _PropertyFlags {
405 PF_None = 0,
406 PF_Persistent = 1
407};
408
409typedef enum _PropertyFlags PropertyFlags;
410
411typedef struct _EdsioProperty EdsioProperty;
412typedef union _EdsioPropertyEntry EdsioPropertyEntry;
413typedef struct _EdsioGenericProperty EdsioGenericProperty;
414
415typedef void (* PropFreeFunc) (gpointer obj);
416typedef gboolean (* PropGSFunc) (/*gpointer obj, GHashTable** obj_table, EdsioProperty* prop, ... */);
417typedef gboolean (* PropSerialize) (/*SerialSink* sink, ... */);
418typedef gboolean (* PropUnserialize) (/*SerialSource* source, ... */);
419
420typedef GHashTable** (* PropertyTableFunc) (gpointer obj);
421typedef SerialSource* (* PersistSourceFunc) (gpointer obj, const char* prop_name);
422typedef SerialSink* (* PersistSinkFunc) (gpointer obj, const char* prop_name);
423typedef gboolean (* PersistIssetFunc) (gpointer obj, const char* prop_name);
424typedef gboolean (* PersistUnsetFunc) (gpointer obj, const char* prop_name);
425
426void edsio_initialize_property_type (const char* t, PropFreeFunc freer, PropGSFunc getter, PropGSFunc setter, PropSerialize ser, PropUnserialize unser);
427void edsio_initialize_host_type (const char* ph,
428 PropertyTableFunc ptable,
429 PersistSourceFunc source,
430 PersistSinkFunc sink,
431 PersistIssetFunc isset,
432 PersistUnsetFunc unset);
433
434gboolean edsio_property_isset (const char* ph, const char* t, guint32 code, gpointer obj);
435gboolean edsio_property_unset (const char* ph, const char* t, guint32 code, gpointer obj);
436
437PropGSFunc edsio_property_getter (const char* ph, const char* t, guint32 code, EdsioProperty** prop);
438PropGSFunc edsio_property_setter (const char* ph, const char* t, guint32 code, EdsioProperty** prop);
439
440void edsio_property_uint_free (gpointer obj);
441gboolean edsio_property_uint_getter (gpointer obj, EdsioProperty* ep, guint32* get);
442gboolean edsio_property_uint_setter (gpointer obj, EdsioProperty* ep, guint32 set);
443
444void edsio_property_string_free (gpointer obj);
445gboolean edsio_property_string_getter (gpointer obj, EdsioProperty* ep, const char** get);
446gboolean edsio_property_string_setter (gpointer obj, EdsioProperty* ep, const char* set);
447
448void edsio_property_bytes_free (gpointer obj);
449gboolean edsio_property_bytes_getter (gpointer obj, EdsioProperty* ep, guint8** get, guint32 *get_len);
450gboolean edsio_property_bytes_setter (gpointer obj, EdsioProperty* ep, guint8* set, guint32 set_len);
451
452void edsio_property_vptr_free (gpointer obj);
453gboolean edsio_property_vptr_getter (gpointer obj, EdsioProperty* ep, void** get);
454gboolean edsio_property_vptr_setter (gpointer obj, EdsioProperty* ep, void* set);
455
456EdsioPropertyEntry* edsio_property_get (gpointer obj, EdsioProperty* ep);
457gboolean edsio_property_set (gpointer obj, EdsioProperty* ep, EdsioPropertyEntry* set);
458
459gboolean edsio_new_property (const char* name, const char* ph, const char* t, guint32 flags, EdsioGenericProperty* prop);
460
461/* Testing...
462 */
463
464#define DEBUG_LIBEDSIO
465
466#ifdef DEBUG_LIBEDSIO
467struct _PropTest
468{
469 GHashTable* _edsio_property_table;
470
471 GHashTable* ptable;
472
473 const char* kludge;
474};
475
476GHashTable** edsio_proptest_property_table (PropTest *pt);
477SerialSource* edsio_persist_proptest_source (PropTest *pt, const char* prop_name);
478SerialSink* edsio_persist_proptest_sink (PropTest *pt, const char* prop_name);
479gboolean edsio_persist_proptest_isset (PropTest *pt, const char* prop_name);
480gboolean edsio_persist_proptest_unset (PropTest *pt, const char* prop_name);
481
482#endif
483
484/* Missing glib stuff
485 */
486
487typedef struct _GQueue GQueue;
488
489struct _GQueue
490{
491 GList *list;
492 GList *list_end;
493 guint list_size;
494};
495
496/* Queues
497 */
498
499GQueue * g_queue_new (void);
500void g_queue_free (GQueue *q);
501guint g_queue_get_size (GQueue *q);
502void g_queue_push_front (GQueue *q, gpointer data);
503void g_queue_push_back (GQueue *q, gpointer data);
504gpointer g_queue_pop_front (GQueue *q);
505gpointer g_queue_pop_back (GQueue *q);
506
507#define g_queue_empty(queue) \
508 ((((GQueue *)(queue)) && ((GQueue *)(queue))->list) ? FALSE : TRUE)
509
510#define g_queue_peek_front(queue) \
511 ((((GQueue *)(queue)) && ((GQueue *)(queue))->list) ? \
512 ((GQueue *)(queue))->list->data : NULL)
513
514#define g_queue_peek_back(queue) \
515 ((((GQueue *)(queue)) && ((GQueue *)(queue))->list_end) ? \
516 ((GQueue *)(queue))->list_end->data : NULL)
517
518#define g_queue_index(queue,ptr) \
519 ((((GQueue *)(queue)) && ((GQueue *)(queue))->list) ? \
520 g_list_index (((GQueue *)(queue))->list, (ptr)) : -1)
521
522#define g_queue_push g_queue_push_back
523#define g_queue_pop g_queue_pop_front
524#define g_queue_peek g_queue_peek_front
525
526
527#ifdef __cplusplus
528}
529#endif
530
531#endif /* _EDSIO_H_ */
diff --git a/xdelta1/libedsio/edsio.ser b/xdelta1/libedsio/edsio.ser
deleted file mode 100644
index ada3b11..0000000
--- a/xdelta1/libedsio/edsio.ser
+++ /dev/null
@@ -1,129 +0,0 @@
1;; -*- Emacs-Lisp -*-
2
3(defmodule edsio 6 "edsio.h" nil)
4
5(defsertype EdsioUint 1
6 ((val uint))
7 ()
8 )
9
10(defsertype EdsioBytes 2
11 ((val bytes))
12 ()
13 )
14
15(defsertype EdsioString 3
16 ((val string))
17 ()
18 )
19
20(defsertype GenericTime 4
21 ((seconds uint)
22 (nanos uint)
23 )
24 ()
25 )
26
27(defetype source "SerialSource*")
28(defetype sink "SerialSink*")
29(defetype int "int")
30(defetype string "const char*")
31
32(defevent GetTimeOfDayFailure Error () (errno)
33 "Gettimeofday failed: ${STRERROR}")
34
35(defevent TimeFailure Error () (errno)
36 "Time failed: ${STRERROR}")
37
38(defevent UnregisteredType Error ((library int) (number int)) ()
39 "Unregistered serial type: library=${LIBRARY} number=${NUMBER}")
40
41(defevent UnexpectedLibraryType Error ((expected int) (received int)) ()
42 "Unexpected serial library type: expected ${EXPECTED}, received ${RECEIVED}")
43
44(defevent UnexpectedType Error () ()
45 "Unexpected serial type")
46
47(defevent OutputBufferShort Error () ()
48 "Output buffer is too short")
49
50(defevent InvalidBase64Encoding Error () ()
51 "Invalid base64 encoding")
52
53(defevent MissingChecksum Error () ()
54 "Missing embedded checksum in base64 encoding")
55
56(defevent InvalidChecksum Error () ()
57 "Checksum verification failed")
58
59(defevent SourceEof Error ((source source)) ()
60 "${SOURCE}: Unexpected EOF")
61
62(defevent IncorrectAllocation Error ((source source)) ()
63 "${SOURCE}: Incorrect allocation")
64
65(defevent InvalidIntegerString Error ((msg string) (arg string)) ()
66 "${MSG}: not an integer: ${ARG}")
67
68(defevent IntegerOutOfRange Error ((msg string) (arg string)) ()
69 "${MSG}: integer out of range: ${ARG}")
70
71(defevent InvalidIntegerSign Error ((msg string) (arg string)) ()
72 "${MSG}: expected an unsigned integer: ${ARG}")
73
74(defevent DuplicatePropertyTypeRegistered Error ((name string)) ()
75 "Property type registered twice: ${NAME}")
76
77(defevent DuplicateHostTypeRegistered Error ((name string)) ()
78 "Property host registered twice: ${NAME}")
79
80(defevent DuplicatePropertyNameRegistered Warning ((name string)) ()
81 "Property name registered twice (ignored): ${NAME}")
82
83(defevent NoSuchProperty Error ((num int)) ()
84 "Unregistered property: ${NUM}")
85
86(defevent NoSuchPropertyType Error ((name string)) ()
87 "Unregistered property type: ${NAME}")
88
89(defevent NoSuchHostType Error ((name string)) ()
90 "Unregistered host type: ${NAME}")
91
92(defevent WrongHostType Error ((name string) (recv string) (expect string)) ()
93 "Wrong property host type: received ${RECV}, expected ${EXPECT}")
94
95(defevent WrongDataType Error ((name string) (recv string) (expect string)) ()
96 "Wrong property data type: received ${RECV}, expected ${EXPECT}")
97
98(defevent PropertyNotSet Error ((name string)) ()
99 "${NAME} property not set")
100
101(defevent PersistenceUnavailable Error ((name string) (host string)) ()
102 "Persistence is unavailable in host ${HOST} for property ${NAME}")
103
104(defevent InvalidStreamChecksum Error () ()
105 "Incorrect stream checksum")
106
107(defevent InvalidHexDigit Error ((bad string) (ctx string)) ()
108 "Invalid hex digit ${BAD} in context: ${CTX}")
109
110(defevent MD5StringShort Error ((short string)) ()
111 "MD5 string too short: ${SHORT}")
112
113(defevent MD5StringLong Error ((long string)) ()
114 "MD5 string too long: ${LONG}")
115
116(defevent UnregisteredLibrary Error ((number int)) ()
117 "Unregistered library: ${NUMBER}")
118
119(defevent GModuleError Error ((file string) (msg string)) ()
120 "GModule: ${FILE}: ${MSG}")
121
122;; properties
123
124(defprophost PropTest "P" "PropTest*" t)
125
126(defprophosttype PropTest uint)
127(defprophosttype PropTest bytes)
128(defprophosttype PropTest string)
129(defprophosttype PropTest EdsioUint)
diff --git a/xdelta1/libedsio/edsiotest.c b/xdelta1/libedsio/edsiotest.c
deleted file mode 100644
index 1d30dc0..0000000
--- a/xdelta1/libedsio/edsiotest.c
+++ /dev/null
@@ -1,213 +0,0 @@
1/* -*-Mode: C;-*-
2 * $Id: edsiotest.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $
3 *
4 * Copyright (C) 1998, 1999, Josh MacDonald.
5 * All Rights Reserved.
6 *
7 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
8 */
9
10#include "edsio.h"
11
12void
13test1 ()
14{
15 guint32 x = 0;
16
17 PropTest *pt = g_new0 (PropTest, 1);
18
19 EdsioPropTestUintProperty prop;
20
21 g_assert (edsio_edsio_init ());
22
23 g_assert (edsio_new_proptest_uint_property ("Just testing (1)...", PF_Persistent, & prop));
24
25 g_assert (! proptest_isset_uint (pt, prop));
26
27 g_assert (proptest_set_uint (pt, prop, 42));
28
29 g_assert (proptest_isset_uint (pt, prop));
30
31 g_assert (proptest_get_uint (pt, prop, & x) && x == 42);
32
33 /* kill the cache, to test persistence. */
34 pt->_edsio_property_table = NULL;
35
36 g_assert (proptest_get_uint (pt, prop, & x) && x == 42);
37
38 g_assert (proptest_unset_uint (pt, prop));
39
40 g_assert (! proptest_isset_uint (pt, prop));
41
42 g_assert (! pt->_edsio_property_table);
43}
44
45void
46test2 ()
47{
48 const char* str = "hello there";
49 const char* str2;
50 guint32 str2_len;
51
52 PropTest *pt = g_new0 (PropTest, 1);
53
54 EdsioPropTestBytesProperty prop;
55
56 g_assert (edsio_edsio_init ());
57
58 g_assert (edsio_new_proptest_bytes_property ("Just testing (2)...", PF_Persistent, & prop));
59
60 g_assert (! proptest_isset_bytes (pt, prop));
61
62 g_assert (proptest_set_bytes (pt, prop, (guint8*) str, strlen (str) + 1));
63
64 g_assert (proptest_isset_bytes (pt, prop));
65
66 g_assert (proptest_get_bytes (pt, prop, (const guint8**) & str2, & str2_len) && str2_len == (strlen (str) + 1) && strcmp (str, str2) == 0);
67
68 /* kill the cache, to test persistence. */
69 pt->_edsio_property_table = NULL;
70
71 g_assert (proptest_get_bytes (pt, prop, (const guint8**) & str2, & str2_len) && str2_len == (strlen (str) + 1) && strcmp (str, str2) == 0);
72
73 g_assert (proptest_unset_bytes (pt, prop));
74
75 g_assert (! proptest_isset_bytes (pt, prop));
76
77 g_assert (! pt->_edsio_property_table);
78}
79
80void
81test3 ()
82{
83 SerialEdsioUint x;
84 SerialEdsioUint *p;
85 EdsioPropTestEdsioUintProperty prop;
86
87 PropTest *pt = g_new0 (PropTest, 1);
88
89 x.val = 42;
90
91 g_assert (edsio_edsio_init ());
92
93 g_assert (edsio_new_proptest_edsiouint_property ("Just testing (3)...", PF_Persistent, & prop));
94
95 g_assert (! proptest_isset_edsiouint (pt, prop));
96
97 g_assert (proptest_set_edsiouint (pt, prop, & x));
98
99 g_assert (proptest_isset_edsiouint (pt, prop));
100
101 g_assert (proptest_get_edsiouint (pt, prop, & p) && x.val == p->val);
102
103 /* kill the cache, to test persistence. */
104 pt->_edsio_property_table = NULL;
105
106 g_assert (proptest_get_edsiouint (pt, prop, & p) && x.val == p->val);
107
108 g_assert (proptest_unset_edsiouint (pt, prop));
109
110 g_assert (! proptest_isset_edsiouint (pt, prop));
111
112 g_assert (! pt->_edsio_property_table);
113}
114
115void
116test4 ()
117{
118 const char* str = "hello there";
119 const char* str2;
120
121 PropTest *pt = g_new0 (PropTest, 1);
122
123 EdsioPropTestStringProperty prop;
124
125 g_assert (edsio_edsio_init ());
126
127 g_assert (edsio_new_proptest_string_property ("Just testing (4)...", PF_Persistent, & prop));
128
129 g_assert (! proptest_isset_string (pt, prop));
130
131 g_assert (proptest_set_string (pt, prop, str));
132
133 g_assert (proptest_isset_string (pt, prop));
134
135 g_assert (proptest_get_string (pt, prop, & str2) && strcmp (str, str2) == 0);
136
137 /* kill the cache, to test persistence. */
138 pt->_edsio_property_table = NULL;
139
140 g_assert (proptest_get_string (pt, prop, & str2) && strcmp (str, str2) == 0);
141
142 g_assert (proptest_unset_string (pt, prop));
143
144 g_assert (! proptest_isset_string (pt, prop));
145
146 g_assert (! pt->_edsio_property_table);
147}
148
149void test5 ()
150{
151 GByteArray* sink_result;
152 SerialSink* sink = edsio_simple_sink (NULL, SBF_Checksum | SBF_Base64 | SBF_Compress, FALSE, NULL, & sink_result);
153 SerialSource* src;
154 const char* input = "hello there!!!!!!!!";
155 SerialEdsioString *output;
156 guint8 zero[1];
157 zero[0] = 0;
158
159 g_assert (serialize_edsiostring (sink, input));
160
161 g_assert (sink->sink_close (sink));
162
163 g_byte_array_append (sink_result, zero, 1);
164
165 g_print ("%s -> %s\n", input, sink_result->data);
166
167 src = edsio_simple_source (sink_result->data, sink_result->len - 1, SBF_Checksum | SBF_Base64 | SBF_Compress);
168
169 g_assert (unserialize_edsiostring (src, & output));
170
171 g_assert (src->source_close (src));
172
173 g_assert (strcmp (output->val, input) == 0);
174}
175
176void
177test6 ()
178{
179 const char* md5str = "aed3918c4ccb89f2dcf74d5dcab22989";
180 const char* md5strbad1 = "aed3918c4cXb89f2dcf74d5dcab22989";
181 const char* md5strbad2 = "aed3918c4cab89f2dcf74d5dcab22989X";
182 const char* md5strbad3 = "aed3918c4cab89f2dcf74d5dcab2298";
183 char md5str2[33];
184 guint8 md5[16];
185
186 g_assert (! edsio_md5_from_string (md5, md5strbad1));
187 g_assert (! edsio_md5_from_string (md5, md5strbad2));
188 g_assert (! edsio_md5_from_string (md5, md5strbad3));
189
190 g_assert (edsio_md5_from_string (md5, md5str));
191
192 edsio_md5_to_string (md5, md5str2);
193
194 g_assert (strcmp (md5str, md5str2) == 0);
195}
196
197int
198main ()
199{
200 test1 ();
201
202 test2 ();
203
204 test3 ();
205
206 test4 ();
207
208 test5 ();
209
210 test6 ();
211
212 return 0;
213}
diff --git a/xdelta1/libedsio/fh.c b/xdelta1/libedsio/fh.c
deleted file mode 100644
index 6b27cbf..0000000
--- a/xdelta1/libedsio/fh.c
+++ /dev/null
@@ -1,167 +0,0 @@
1/* -*-Mode: C;-*-
2 * $Id: fh.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $
3 *
4 * Copyright (C) 1998, 1999, Josh MacDonald.
5 * All Rights Reserved.
6 *
7 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
8 */
9
10#include "edsio.h"
11
12/* Handle source/sink impls
13 */
14typedef struct _HandleSerialSource HandleSerialSource;
15typedef struct _HandleSerialSink HandleSerialSink;
16
17struct _HandleSerialSource {
18 SerialSource source;
19
20 FileHandle* fh;
21};
22
23struct _HandleSerialSink {
24 SerialSink sink;
25
26 FileHandle* fh;
27 gpointer data1;
28 gpointer data2;
29 gpointer data3;
30 gboolean (* cont_onclose) (gpointer data1, gpointer data2, gpointer data3);
31};
32
33static SerialType handle_source_type (SerialSource* source, gboolean set_allocation);
34static gboolean handle_source_close (SerialSource* source);
35static gboolean handle_source_read (SerialSource* source, guint8 *ptr, guint32 len);
36static void handle_source_free (SerialSource* source);
37
38static gboolean handle_sink_type (SerialSink* sink, SerialType type, guint len, gboolean set_allocation);
39static gboolean handle_sink_close (SerialSink* sink);
40static gboolean handle_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len);
41static void handle_sink_free (SerialSink* sink);
42
43SerialSource*
44handle_source (FileHandle* fh)
45{
46 HandleSerialSource* it = g_new0 (HandleSerialSource, 1);
47
48 serializeio_source_init (&it->source,
49 handle_source_type,
50 handle_source_close,
51 handle_source_read,
52 handle_source_free,
53 NULL,
54 NULL);
55
56 it->fh = fh;
57
58 return &it->source;
59}
60
61SerialSink*
62handle_sink (FileHandle* fh, gpointer data1, gpointer data2, gpointer data3, gboolean (* cont_onclose) (gpointer data1, gpointer data2, gpointer data3))
63{
64 HandleSerialSink* it = g_new0 (HandleSerialSink, 1);
65
66 serializeio_sink_init (&it->sink,
67 handle_sink_type,
68 handle_sink_close,
69 handle_sink_write,
70 handle_sink_free,
71 NULL);
72
73 it->fh = fh;
74 it->data1 = data1;
75 it->data2 = data2;
76 it->data3 = data3;
77 it->cont_onclose = cont_onclose;
78
79 return &it->sink;
80}
81
82SerialType
83handle_source_type (SerialSource* source, gboolean set_allocation)
84{
85 HandleSerialSource* ssource = (HandleSerialSource*) source;
86 guint32 x;
87
88 if (! ssource->fh->table->table_handle_getui (ssource->fh, &x))
89 return ST_Error;
90
91 if (set_allocation)
92 {
93 /* Note: set_allocation is deprecated in 1.1.4 */
94 guint32 bogus;
95 if (! ssource->fh->table->table_handle_getui (ssource->fh, &bogus))
96 return ST_Error;
97 }
98
99 return x;
100}
101
102gboolean
103handle_source_close (SerialSource* source)
104{
105 HandleSerialSource* ssource = (HandleSerialSource*) source;
106
107 return ssource->fh->table->table_handle_close (ssource->fh, 0);
108}
109
110gboolean
111handle_source_read (SerialSource* source, guint8 *ptr, guint32 len)
112{
113 HandleSerialSource* ssource = (HandleSerialSource*) source;
114
115 return ssource->fh->table->table_handle_read (ssource->fh, ptr, len) == len;
116}
117
118void
119handle_source_free (SerialSource* source)
120{
121 g_free (source);
122}
123
124gboolean
125handle_sink_type (SerialSink* sink, SerialType type, guint len, gboolean set_allocation)
126{
127 HandleSerialSink* ssink = (HandleSerialSink*) sink;
128
129 if (! ssink->fh->table->table_handle_putui (ssink->fh, type))
130 return FALSE;
131
132 /* Note: set_allocation is deprecated in 1.1.4 */
133 if (set_allocation && ! ssink->fh->table->table_handle_putui (ssink->fh, len))
134 return FALSE;
135
136 return TRUE;
137}
138
139gboolean
140handle_sink_close (SerialSink* sink)
141{
142 HandleSerialSink* ssink = (HandleSerialSink*) sink;
143
144 if (ssink->fh->table->table_handle_close (ssink->fh, 0))
145 {
146 if (ssink->cont_onclose)
147 return ssink->cont_onclose (ssink->data1, ssink->data2, ssink->data3);
148
149 return TRUE;
150 }
151
152 return FALSE;
153}
154
155gboolean
156handle_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len)
157{
158 HandleSerialSink* ssink = (HandleSerialSink*) sink;
159
160 return ssink->fh->table->table_handle_write (ssink->fh, ptr, len);
161}
162
163void
164handle_sink_free (SerialSink* sink)
165{
166 g_free (sink);
167}
diff --git a/xdelta1/libedsio/generic.c b/xdelta1/libedsio/generic.c
deleted file mode 100644
index 96d246a..0000000
--- a/xdelta1/libedsio/generic.c
+++ /dev/null
@@ -1,252 +0,0 @@
1/* -*-Mode: C;-*-
2 * $Id: generic.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $
3 *
4 * Copyright (C) 1998, 1999, Josh MacDonald.
5 * All Rights Reserved.
6 *
7 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
8 */
9
10#include "edsio.h"
11
12/* Type-based selectors for unknown types
13 */
14
15typedef struct {
16 const char* name;
17 gboolean (*unserialize_func) ();
18 gboolean (*serialize_func) ();
19 guint (*count_func) ();
20 void (*print_func) ();
21 guint32 val;
22} SerEntry;
23
24static GArray *ser_array;
25static gboolean ser_array_sorted;
26
27void
28serializeio_initialize_type (const char* name,
29 guint32 val,
30 gboolean (*unserialize_func) (),
31 gboolean (*serialize_func) (),
32 guint (*count_func) (),
33 void (*print_func) ())
34{
35 SerEntry it;
36
37 it.name = name;
38 it.val = val;
39 it.unserialize_func = unserialize_func;
40 it.serialize_func = serialize_func;
41 it.count_func = count_func;
42 it.print_func = print_func;
43
44 if (ser_array == NULL)
45 ser_array = g_array_new (FALSE, TRUE, sizeof (SerEntry));
46
47 g_array_append_val (ser_array, it);
48
49 ser_array_sorted = FALSE;
50}
51
52static int
53ser_entry_compare (const void* va, const void* vb)
54{
55 SerEntry* a = (SerEntry*) va;
56 SerEntry* b = (SerEntry*) vb;
57
58 return a->val - b->val;
59}
60
61static SerEntry*
62serializeio_find_entry (SerialType type)
63{
64 if (! edsio_library_check (type & EDSIO_LIBRARY_OFFSET_MASK))
65 return NULL;
66
67 if (ser_array)
68 {
69 gint high_index = ser_array->len;
70 gint low_index = 0;
71 gint index;
72 gint this_val;
73
74 if (! ser_array_sorted)
75 {
76 ser_array_sorted = TRUE;
77 qsort (ser_array->data, ser_array->len, sizeof (SerEntry), ser_entry_compare);
78 }
79
80 again:
81
82 index = (low_index + high_index) / 2;
83
84 this_val = g_array_index (ser_array, SerEntry, index).val;
85
86 if (this_val < type)
87 {
88 low_index = index + 1;
89 goto again;
90 }
91 else if (this_val > type)
92 {
93 high_index = index - 1;
94 goto again;
95 }
96 else
97 {
98 return & g_array_index (ser_array, SerEntry, index);
99 }
100 }
101
102 edsio_generate_intint_event (EC_EdsioUnregisteredType,
103 type & EDSIO_LIBRARY_OFFSET_MASK,
104 type >> EDSIO_LIBRARY_OFFSET_BITS);
105 return NULL;
106}
107
108gboolean
109serializeio_unserialize_generic_internal (SerialSource *source,
110 SerialType *object_type,
111 void **object,
112 gboolean set_allocation)
113{
114 SerialType type = (* source->source_type) (source, set_allocation);
115 SerEntry* ent;
116 gboolean res = FALSE;
117
118 if (type < 0)
119 return FALSE;
120
121 ent = serializeio_find_entry (type);
122
123 (*object_type) = type;
124
125 if (ent)
126 {
127 res = ent->unserialize_func (source, object);
128 }
129
130 return res;
131}
132
133gboolean
134serializeio_unserialize_generic (SerialSource *source,
135 SerialType *object_type,
136 void **object)
137{
138 return serializeio_unserialize_generic_internal (source, object_type, object, TRUE);
139}
140
141gboolean
142serializeio_serialize_generic (SerialSink *sink,
143 SerialType object_type,
144 void *object)
145{
146 return serializeio_serialize_generic_internal (sink, object_type, object, TRUE);
147}
148
149gboolean
150serializeio_serialize_generic_internal (SerialSink *sink,
151 SerialType object_type,
152 void *object,
153 gboolean set_allocation)
154{
155 SerEntry* ent;
156 gboolean res = FALSE;
157
158 if (! (* sink->sink_type) (sink, object_type, set_allocation ? serializeio_generic_count (object_type, object) : 0, set_allocation))
159 return FALSE;
160
161 ent = serializeio_find_entry (object_type);
162
163 if (ent)
164 res = ent->serialize_func (sink, object);
165
166 return res;
167}
168
169const char*
170serializeio_generic_type_to_string (SerialType type)
171{
172 SerEntry* ent;
173 const char* res = "*Unknown*";
174
175 ent = serializeio_find_entry (type);
176
177 if (ent)
178 res = ent->name;
179
180 return res;
181}
182
183guint
184serializeio_generic_count (SerialType object_type,
185 void *object)
186{
187 SerEntry* ent;
188 gboolean res = FALSE;
189
190 ent = serializeio_find_entry (object_type);
191
192 if (ent)
193 res = ent->count_func (object);
194
195 return res;
196}
197
198void
199serializeio_generic_print (SerialType type, void* object, guint indent_spaces)
200{
201 SerEntry* ent;
202
203 ent = serializeio_find_entry (type);
204
205 if (ent)
206 ent->print_func (object, indent_spaces);
207 else
208 {
209 int i = 0;
210
211 for (; i < indent_spaces; i += 1)
212 g_print (" ");
213
214 g_print ("*Type Not Registered*\n");
215 }
216}
217
218gboolean
219serializeio_unserialize_generic_acceptable (SerialSource *source,
220 guint32 accept,
221 SerialType *object_type,
222 void **object)
223{
224 gboolean s;
225
226 s = serializeio_unserialize_generic (source, object_type, object);
227
228 if (s)
229 {
230 if (accept != -1)
231 {
232 if ((*object_type & EDSIO_LIBRARY_OFFSET_MASK) != (accept & EDSIO_LIBRARY_OFFSET_MASK))
233 {
234 edsio_generate_intint_event (EC_EdsioUnexpectedLibraryType,
235 accept & EDSIO_LIBRARY_OFFSET_MASK,
236 *object_type & EDSIO_LIBRARY_OFFSET_MASK);
237
238 return FALSE;
239 }
240
241 if (! ((*object_type & ~EDSIO_LIBRARY_OFFSET_MASK) |
242 (accept & ~EDSIO_LIBRARY_OFFSET_MASK)))
243 {
244 edsio_generate_void_event (EC_EdsioUnexpectedType);
245
246 return FALSE;
247 }
248 }
249 }
250
251 return s;
252}
diff --git a/xdelta1/libedsio/library.c b/xdelta1/libedsio/library.c
deleted file mode 100644
index f13193c..0000000
--- a/xdelta1/libedsio/library.c
+++ /dev/null
@@ -1,121 +0,0 @@
1/* -*-Mode: C;-*-
2 * $Id: library.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $
3 *
4 * Copyright (C) 1998, 1999, Josh MacDonald.
5 * All Rights Reserved.
6 *
7 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
8 */
9
10#include "edsio.h"
11#include <gmodule.h>
12
13typedef struct _Library Library;
14
15struct _Library {
16 const char* name;
17 const char* libname;
18 gint index;
19 gboolean loaded;
20};
21
22static Library known_libraries[] = {
23 { "xd", "xdelta", 3 },
24 { "edsio", "edsio", 6 },
25};
26
27static GHashTable* loaded_libraries;
28
29static void
30edsio_library_init ()
31{
32 if (! loaded_libraries)
33 {
34 gint i;
35 gint n = sizeof (known_libraries) / sizeof (Library);;
36
37 loaded_libraries = g_hash_table_new (g_int_hash, g_int_equal);
38
39 for (i = 0; i < n; i += 1)
40 {
41 Library* lib = known_libraries + i;
42
43 g_hash_table_insert (loaded_libraries, & lib->index, lib);
44 }
45 }
46}
47
48void
49edsio_library_register (guint32 number, const char* name)
50{
51 Library* lib;
52
53 edsio_library_init ();
54
55 lib = g_hash_table_lookup (loaded_libraries, & number);
56
57 if (lib)
58 {
59 lib->loaded = TRUE;
60 return;
61 }
62
63 lib = g_new0 (Library, 1);
64
65 lib->index = number;
66 lib->name = name;
67 lib->loaded = TRUE;
68
69 g_hash_table_insert (loaded_libraries, & lib->index, lib);
70}
71
72gboolean
73edsio_library_check (guint32 number)
74{
75 Library* lib;
76
77 edsio_library_init ();
78
79 lib = g_hash_table_lookup (loaded_libraries, & number);
80
81 if (lib)
82 {
83 lib->loaded = TRUE;
84 return TRUE;
85 }
86
87#if 0
88 if (lib->libname && g_module_supported ())
89 {
90 GModule *module;
91 GString *module_name = g_string_new (NULL);
92 GString *symbol_name = g_string_new (NULL);
93 gboolean (* init) (void);
94
95 if (! (module = g_module_open (module_name->str, 0)))
96 {
97 edsio_generate_stringstring_event (EC_EdsioGModuleError, module_name->str, g_module_error ());
98 return FALSE;
99 }
100
101 if (! g_module_symbol (module,
102 symbol_name->str,
103 (void**) & init))
104 {
105 edsio_generate_stringstring_event (EC_EdsioGModuleError, g_module_name (module), g_module_error ());
106 return FALSE;
107 }
108
109 g_module_make_resident (module);
110
111 g_module_close (module);
112
113 lib->loaded = TRUE;
114
115 return (* init) ();
116 }
117#endif
118
119 edsio_generate_int_event (EC_EdsioUnregisteredLibrary, number);
120 return FALSE;
121}
diff --git a/xdelta1/libedsio/maketime.c b/xdelta1/libedsio/maketime.c
deleted file mode 100644
index 5feddae..0000000
--- a/xdelta1/libedsio/maketime.c
+++ /dev/null
@@ -1,391 +0,0 @@
1/* Convert struct partime into time_t. */
2
3/* Copyright 1992, 1993, 1994, 1995, 1997 Paul Eggert
4 Distributed under license by the Free Software Foundation, Inc.
5
6 This file is part of RCS.
7
8 RCS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 RCS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with RCS; see the file COPYING.
20 If not, write to the Free Software Foundation,
21 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23 Report problems and direct all questions to:
24
25 rcs-bugs@cs.purdue.edu
26
27 */
28
29#if has_conf_h
30# include <conf.h>
31#else
32# if HAVE_CONFIG_H
33# include <config.h>
34# else
35# ifndef __STDC__
36# define const
37# endif
38# endif
39 /* MIPS RISCOS4.52 defines time_t in <sys/types.h> not <time.h>. */
40# include <sys/types.h>
41# if HAVE_LIMITS_H
42# include <limits.h>
43# endif
44# ifndef LONG_MIN
45# define LONG_MIN (-1-2147483647L)
46# endif
47# if STDC_HEADERS
48# include <stdlib.h>
49# endif
50# include <time.h>
51# ifdef __STDC__
52# define P(x) x
53# else
54# define P(x) ()
55# endif
56#endif
57
58#include <partime.h>
59#include <maketime.h>
60
61char const maketId[] =
62 "$Id: maketime.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $";
63
64static int isleap P ((int));
65static int month_days P ((struct tm const *));
66static time_t maketime P ((struct partime const *, time_t));
67
68/* For maximum portability, use only localtime and gmtime.
69 Make no assumptions about the time_t epoch or the range of time_t values.
70 Avoid mktime because it's not universal and because there's no easy,
71 portable way for mktime to yield the inverse of gmtime. */
72
73#define TM_YEAR_ORIGIN 1900
74
75static int
76isleap (y)
77 int y;
78{
79 return (y & 3) == 0 && (y % 100 != 0 || y % 400 == 0);
80}
81
82/* days in year before start of months 0-12 */
83static int const month_yday[] =
84{
85 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
86};
87
88/* Yield the number of days in TM's month. */
89static int
90month_days (tm)
91 struct tm const *tm;
92{
93 int m = tm->tm_mon;
94 return (month_yday[m + 1] - month_yday[m]
95 + (m == 1 && isleap (tm->tm_year + TM_YEAR_ORIGIN)));
96}
97
98/* Convert UNIXTIME to struct tm form.
99 Use gmtime if available and if !LOCALZONE, localtime otherwise. */
100struct tm *
101time2tm (unixtime, localzone)
102 time_t unixtime;
103 int localzone;
104{
105 struct tm *tm;
106#ifdef TZ_is_unset
107 static char const *TZ;
108 if (!TZ && !(TZ = getenv ("TZ")))
109 TZ_is_unset ("The TZ environment variable is not set; please set it to your timezone");
110#endif
111 if (localzone || !(tm = gmtime (&unixtime)))
112 tm = localtime (&unixtime);
113 return tm;
114}
115
116/* Yield A - B, measured in seconds. */
117time_t
118difftm (a, b)
119 struct tm const *a;
120 struct tm const *b;
121{
122 int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
123 int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
124 int ac = ay / 100 - (ay % 100 < 0);
125 int bc = by / 100 - (by % 100 < 0);
126 int difference_in_day_of_year = a->tm_yday - b->tm_yday;
127 int intervening_leap_days = (((ay >> 2) - (by >> 2))
128 - (ac - bc)
129 + ((ac >> 2) - (bc >> 2)));
130 time_t difference_in_years = ay - by;
131 time_t difference_in_days
132 = (difference_in_years * 365
133 + (intervening_leap_days + difference_in_day_of_year));
134 return (((((difference_in_days * 24
135 + (a->tm_hour - b->tm_hour))
136 * 60)
137 + (a->tm_min - b->tm_min))
138 * 60)
139 + (a->tm_sec - b->tm_sec));
140}
141
142/*
143 * Adjust time T by adding SECONDS. SECONDS must be at most 24 hours' worth.
144 * Adjust only T's year, mon, mday, hour, min and sec members;
145 * plus adjust wday if it is defined.
146 */
147void
148adjzone (t, seconds)
149 register struct tm *t;
150 long seconds;
151{
152 /*
153 * This code can be off by a second if SECONDS is not a multiple of 60,
154 * if T is local time, and if a leap second happens during this minute.
155 * But this bug has never occurred, and most likely will not ever occur.
156 * Liberia, the last country for which SECONDS % 60 was nonzero,
157 * switched to UTC in May 1972; the first leap second was in June 1972.
158 */
159 int leap_second = t->tm_sec == 60;
160 long sec = seconds + (t->tm_sec - leap_second);
161 if (sec < 0)
162 {
163 if ((t->tm_min -= (59 - sec) / 60) < 0)
164 {
165 if ((t->tm_hour -= (59 - t->tm_min) / 60) < 0)
166 {
167 t->tm_hour += 24;
168 if (TM_DEFINED (t->tm_wday) && --t->tm_wday < 0)
169 t->tm_wday = 6;
170 if (--t->tm_mday <= 0)
171 {
172 if (--t->tm_mon < 0)
173 {
174 --t->tm_year;
175 t->tm_mon = 11;
176 }
177 t->tm_mday = month_days (t);
178 }
179 }
180 t->tm_min += 24 * 60;
181 }
182 sec += 24L * 60 * 60;
183 }
184 else if (60 <= (t->tm_min += sec / 60))
185 if (24 <= (t->tm_hour += t->tm_min / 60))
186 {
187 t->tm_hour -= 24;
188 if (TM_DEFINED (t->tm_wday) && ++t->tm_wday == 7)
189 t->tm_wday = 0;
190 if (month_days (t) < ++t->tm_mday)
191 {
192 if (11 < ++t->tm_mon)
193 {
194 ++t->tm_year;
195 t->tm_mon = 0;
196 }
197 t->tm_mday = 1;
198 }
199 }
200 t->tm_min %= 60;
201 t->tm_sec = (int) (sec % 60) + leap_second;
202}
203
204/*
205 * Convert TM to time_t, using localtime if LOCALZONE and gmtime otherwise.
206 * Use only TM's year, mon, mday, hour, min, and sec members.
207 * Ignore TM's old tm_yday and tm_wday, but fill in their correct values.
208 * Yield -1 on failure (e.g. a member out of range).
209 * Posix 1003.1-1990 doesn't allow leap seconds, but some implementations
210 * have them anyway, so allow them if localtime/gmtime does.
211 */
212time_t
213tm2time (tm, localzone)
214 struct tm *tm;
215 int localzone;
216{
217 /* Cache the most recent t,tm pairs; 1 for gmtime, 1 for localtime. */
218 static time_t t_cache[2];
219 static struct tm tm_cache[2];
220
221 time_t d, gt;
222 struct tm const *gtm;
223 /*
224 * The maximum number of iterations should be enough to handle any
225 * combinations of leap seconds, time zone rule changes, and solar time.
226 * 4 is probably enough; we use a bigger number just to be safe.
227 */
228 int remaining_tries = 8;
229
230 /* Avoid subscript errors. */
231 if (12 <= (unsigned) tm->tm_mon)
232 return -1;
233
234 tm->tm_yday = month_yday[tm->tm_mon] + tm->tm_mday
235 - (tm->tm_mon < 2 || !isleap (tm->tm_year + TM_YEAR_ORIGIN));
236
237 /* Make a first guess. */
238 gt = t_cache[localzone];
239 gtm = gt ? &tm_cache[localzone] : time2tm (gt, localzone);
240
241 /* Repeatedly use the error from the guess to improve the guess. */
242 while ((d = difftm (tm, gtm)) != 0)
243 {
244 if (--remaining_tries == 0)
245 return -1;
246 gt += d;
247 gtm = time2tm (gt, localzone);
248 }
249
250 /*
251 * Check that the guess actually matches;
252 * overflow can cause difftm to yield 0 even on differing times,
253 * or tm may have members out of range (e.g. bad leap seconds).
254 */
255#define TM_DIFFER(a,b) \
256 ( \
257 ((a)->tm_year ^ (b)->tm_year) | \
258 ((a)->tm_mon ^ (b)->tm_mon) | \
259 ((a)->tm_mday ^ (b)->tm_mday) | \
260 ((a)->tm_hour ^ (b)->tm_hour) | \
261 ((a)->tm_min ^ (b)->tm_min) | \
262 ((a)->tm_sec ^ (b)->tm_sec) \
263 )
264 if (TM_DIFFER (tm, gtm))
265 {
266 /*
267 * If gt is a leap second, try gt+1; if it is one greater than
268 * a leap second, try gt-1; otherwise, it doesn't matter.
269 * Leap seconds always fall at month end.
270 */
271 int yd = tm->tm_year - gtm->tm_year;
272 gt += yd + (yd ? 0 : tm->tm_mon - gtm->tm_mon);
273 gtm = time2tm (gt, localzone);
274 if (TM_DIFFER (tm, gtm))
275 return -1;
276 }
277 t_cache[localzone] = gt;
278 tm_cache[localzone] = *gtm;
279
280 tm->tm_wday = gtm->tm_wday;
281 return gt;
282}
283
284/*
285 * Check *PT and convert it to time_t.
286 * If it is incompletely specified, use DEFAULT_TIME to fill it out.
287 * Use localtime if PT->zone is the special value TM_LOCAL_ZONE.
288 * Yield -1 on failure.
289 * ISO 8601 day-of-year and week numbers are not yet supported.
290 */
291static time_t
292maketime (pt, default_time)
293 struct partime const *pt;
294 time_t default_time;
295{
296 int localzone, wday;
297 struct tm tm;
298 struct tm *tm0 = 0;
299 time_t r;
300
301 tm0 = 0; /* Keep gcc -Wall happy. */
302 localzone = pt->zone == TM_LOCAL_ZONE;
303
304 tm = pt->tm;
305
306 if (TM_DEFINED (pt->ymodulus) || !TM_DEFINED (tm.tm_year))
307 {
308 /* Get tm corresponding to default time. */
309 tm0 = time2tm (default_time, localzone);
310 if (!localzone)
311 adjzone (tm0, pt->zone);
312 }
313
314 if (TM_DEFINED (pt->ymodulus))
315 tm.tm_year +=
316 (tm0->tm_year + TM_YEAR_ORIGIN) / pt->ymodulus * pt->ymodulus;
317 else if (!TM_DEFINED (tm.tm_year))
318 {
319 /* Set default year, month, day from current time. */
320 tm.tm_year = tm0->tm_year + TM_YEAR_ORIGIN;
321 if (!TM_DEFINED (tm.tm_mon))
322 {
323 tm.tm_mon = tm0->tm_mon;
324 if (!TM_DEFINED (tm.tm_mday))
325 tm.tm_mday = tm0->tm_mday;
326 }
327 }
328
329 /* Convert from partime year (Gregorian) to Posix year. */
330 tm.tm_year -= TM_YEAR_ORIGIN;
331
332 /* Set remaining default fields to be their minimum values. */
333 if (!TM_DEFINED (tm.tm_mon))
334 tm.tm_mon = 0;
335 if (!TM_DEFINED (tm.tm_mday))
336 tm.tm_mday = 1;
337 if (!TM_DEFINED (tm.tm_hour))
338 tm.tm_hour = 0;
339 if (!TM_DEFINED (tm.tm_min))
340 tm.tm_min = 0;
341 if (!TM_DEFINED (tm.tm_sec))
342 tm.tm_sec = 0;
343
344 if (!localzone)
345 adjzone (&tm, -pt->zone);
346 wday = tm.tm_wday;
347
348 /* Convert and fill in the rest of the tm. */
349 r = tm2time (&tm, localzone);
350
351 /* Check weekday. */
352 if (r != -1 && TM_DEFINED (wday) && wday != tm.tm_wday)
353 return -1;
354
355 return r;
356}
357
358/* Parse a free-format date in SOURCE, yielding a Unix format time. */
359time_t
360str2time (source, default_time, default_zone)
361 char const *source;
362 time_t default_time;
363 long default_zone;
364{
365 struct partime pt;
366
367 if (*partime (source, &pt))
368 return -1;
369 if (pt.zone == TM_UNDEFINED_ZONE)
370 pt.zone = default_zone;
371 return maketime (&pt, default_time);
372}
373
374#if TEST
375#include <stdio.h>
376int
377main (argc, argv)
378 int argc;
379 char **argv;
380{
381 time_t default_time = time ((time_t *) 0);
382 long default_zone = argv[1] ? atol (argv[1]) : 0;
383 char buf[1000];
384 while (fgets (buf, sizeof (buf), stdin))
385 {
386 time_t t = str2time (buf, default_time, default_zone);
387 printf ("%s", asctime (gmtime (&t)));
388 }
389 return 0;
390}
391#endif
diff --git a/xdelta1/libedsio/maketime.h b/xdelta1/libedsio/maketime.h
deleted file mode 100644
index 3948eda..0000000
--- a/xdelta1/libedsio/maketime.h
+++ /dev/null
@@ -1,39 +0,0 @@
1/* Yield time_t from struct partime yielded by partime. */
2
3/* Copyright 1993, 1994, 1995 Paul Eggert
4 Distributed under license by the Free Software Foundation, Inc.
5
6 This file is part of RCS.
7
8 RCS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 RCS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with RCS; see the file COPYING.
20 If not, write to the Free Software Foundation,
21 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23 Report problems and direct all questions to:
24
25 rcs-bugs@cs.purdue.edu
26
27 */
28
29#if defined __STDC__ || has_prototypes
30# define __MAKETIME_P(x) x
31#else
32# define __MAKETIME_P(x) ()
33#endif
34
35struct tm *time2tm __MAKETIME_P ((time_t, int));
36time_t difftm __MAKETIME_P ((struct tm const *, struct tm const *));
37time_t str2time __MAKETIME_P ((char const *, time_t, long));
38time_t tm2time __MAKETIME_P ((struct tm *, int));
39void adjzone __MAKETIME_P ((struct tm *, long));
diff --git a/xdelta1/libedsio/md5c.c b/xdelta1/libedsio/md5c.c
deleted file mode 100644
index 0a76927..0000000
--- a/xdelta1/libedsio/md5c.c
+++ /dev/null
@@ -1,298 +0,0 @@
1/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
2 */
3
4/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
5 rights reserved.
6
7 License to copy and use this software is granted provided that it
8 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
9Algorithm" in all material mentioning or referencing this software
10or this function.
11
12License is also granted to make and use derivative works provided
13that such works are identified as "derived from the RSA Data
14Security, Inc. MD5 Message-Digest Algorithm" in all material
15mentioning or referencing the derived work.
16
17RSA Data Security, Inc. makes no representations concerning either
18the merchantability of this software or the suitability of this
19software for any particular purpose. It is provided "as is"
20without express or implied warranty of any kind.
21
22These notices must be retained in any copies of any part of this
23documentation and/or software.
24*/
25
26#include "edsio.h"
27#include <string.h>
28
29
30/* Constants for MD5Transform routine.
31 */
32#define S11 7
33#define S12 12
34#define S13 17
35#define S14 22
36#define S21 5
37#define S22 9
38#define S23 14
39#define S24 20
40#define S31 4
41#define S32 11
42#define S33 16
43#define S34 23
44#define S41 6
45#define S42 10
46#define S43 15
47#define S44 21
48
49static void MD5Transform (guint32 [4], unsigned const char [64]);
50static void Encode (unsigned char *, guint32 *, unsigned int);
51static void Decode (guint32 *, unsigned const char *, unsigned int);
52
53#define MD5_memcpy memcpy
54#define MD5_memset memset
55
56static unsigned char PADDING[64] = {
57 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
58 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
60};
61
62/* F, G, H and I are basic MD5 functions.
63 */
64#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
65#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
66#define H(x, y, z) ((x) ^ (y) ^ (z))
67#define I(x, y, z) ((y) ^ ((x) | (~z)))
68
69/* ROTATE_LEFT rotates x left n bits.
70 */
71#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
72
73/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
74 Rotation is separate from addition to prevent recomputation.
75 */
76#define FF(a, b, c, d, x, s, ac) { \
77 (a) += F ((b), (c), (d)) + (x) + (guint32)(ac); \
78 (a) = ROTATE_LEFT ((a), (s)); \
79 (a) += (b); \
80 }
81#define GG(a, b, c, d, x, s, ac) { \
82 (a) += G ((b), (c), (d)) + (x) + (guint32)(ac); \
83 (a) = ROTATE_LEFT ((a), (s)); \
84 (a) += (b); \
85 }
86#define HH(a, b, c, d, x, s, ac) { \
87 (a) += H ((b), (c), (d)) + (x) + (guint32)(ac); \
88 (a) = ROTATE_LEFT ((a), (s)); \
89 (a) += (b); \
90 }
91#define II(a, b, c, d, x, s, ac) { \
92 (a) += I ((b), (c), (d)) + (x) + (guint32)(ac); \
93 (a) = ROTATE_LEFT ((a), (s)); \
94 (a) += (b); \
95 }
96
97/* MD5 initialization. Begins an MD5 operation, writing a new context.
98 */
99void edsio_md5_init (EdsioMD5Ctx *context)
100{
101 context->count[0] = context->count[1] = 0;
102 /* Load magic initialization constants.
103 */
104 context->state[0] = 0x67452301;
105 context->state[1] = 0xefcdab89;
106 context->state[2] = 0x98badcfe;
107 context->state[3] = 0x10325476;
108}
109
110/* MD5 block update operation. Continues an MD5 message-digest
111 operation, processing another message block, and updating the
112 context.
113 */
114void edsio_md5_update (EdsioMD5Ctx *context, const guint8* input, guint inputLen)
115{
116 unsigned int i, index, partLen;
117
118 /* Compute number of bytes mod 64 */
119 index = (unsigned int)((context->count[0] >> 3) & 0x3F);
120
121 /* Update number of bits */
122 if ((context->count[0] += ((guint32)inputLen << 3))
123 < ((guint32)inputLen << 3))
124 context->count[1]++;
125 context->count[1] += ((guint32)inputLen >> 29);
126
127 partLen = 64 - index;
128
129 /* Transform as many times as possible.
130 */
131 if (inputLen >= partLen) {
132 MD5_memcpy
133 ((guint8*)&context->buffer[index], (guint8*)input, partLen);
134 MD5Transform (context->state, context->buffer);
135
136 for (i = partLen; i + 63 < inputLen; i += 64)
137 MD5Transform (context->state, &input[i]);
138
139 index = 0;
140 }
141 else
142 i = 0;
143
144 /* Buffer remaining input */
145 MD5_memcpy
146 ((guint8*)&context->buffer[index], (guint8*)&input[i],
147 inputLen-i);
148}
149
150/* MD5 finalization. Ends an MD5 message-digest operation, writing the
151 the message digest and zeroizing the context.
152 */
153void edsio_md5_final (guint8* digest, EdsioMD5Ctx* context)
154{
155 unsigned char bits[8];
156 unsigned int index, padLen;
157
158 /* Save number of bits */
159 Encode (bits, context->count, 8);
160
161 /* Pad out to 56 mod 64.
162 */
163 index = (unsigned int)((context->count[0] >> 3) & 0x3f);
164 padLen = (index < 56) ? (56 - index) : (120 - index);
165 edsio_md5_update (context, PADDING, padLen);
166
167 /* Append length (before padding) */
168 edsio_md5_update (context, bits, 8);
169 /* Store state in digest */
170 Encode (digest, context->state, 16);
171
172 /* Zeroize sensitive information.
173 */
174 MD5_memset ((guint8*)context, 0, sizeof (*context));
175}
176
177/* MD5 basic transformation. Transforms state based on block.
178 */
179static void MD5Transform (guint32 state[4], const guint8 block[64])
180{
181 guint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
182
183 Decode (x, block, 64);
184
185 /* Round 1 */
186 FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
187 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
188 FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
189 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
190 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
191 FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
192 FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
193 FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
194 FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
195 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
196 FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
197 FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
198 FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
199 FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
200 FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
201 FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
202
203 /* Round 2 */
204 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
205 GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
206 GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
207 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
208 GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
209 GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
210 GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
211 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
212 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
213 GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
214 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
215 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
216 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
217 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
218 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
219 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
220
221 /* Round 3 */
222 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
223 HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
224 HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
225 HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
226 HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
227 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
228 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
229 HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
230 HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
231 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
232 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
233 HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
234 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
235 HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
236 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
237 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
238
239 /* Round 4 */
240 II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
241 II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
242 II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
243 II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
244 II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
245 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
246 II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
247 II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
248 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
249 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
250 II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
251 II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
252 II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
253 II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
254 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
255 II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
256
257 state[0] += a;
258 state[1] += b;
259 state[2] += c;
260 state[3] += d;
261
262 /* Zeroize sensitive information.
263 */
264 MD5_memset ((guint8*)x, 0, sizeof (x));
265}
266
267/* Encodes input (guint32) into output (unsigned char). Assumes len is
268 a multiple of 4.
269 */
270static void Encode (output, input, len)
271 unsigned char *output;
272 guint32 *input;
273 unsigned int len;
274{
275 unsigned int i, j;
276
277 for (i = 0, j = 0; j < len; i++, j += 4) {
278 output[j] = (unsigned char)(input[i] & 0xff);
279 output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
280 output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
281 output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
282 }
283}
284
285/* Decodes input (unsigned char) into output (guint32). Assumes len is
286 a multiple of 4.
287 */
288static void Decode (output, input, len)
289 guint32 *output;
290 unsigned const char *input;
291 unsigned int len;
292{
293 unsigned int i, j;
294
295 for (i = 0, j = 0; j < len; i++, j += 4)
296 output[i] = ((guint32)input[j]) | (((guint32)input[j+1]) << 8) |
297 (((guint32)input[j+2]) << 16) | (((guint32)input[j+3]) << 24);
298}
diff --git a/xdelta1/libedsio/partime.c b/xdelta1/libedsio/partime.c
deleted file mode 100644
index 4cce654..0000000
--- a/xdelta1/libedsio/partime.c
+++ /dev/null
@@ -1,742 +0,0 @@
1/* Parse a string, yielding a struct partime that describes it. */
2
3/* Copyright 1993, 1994, 1995, 1997 Paul Eggert
4 Distributed under license by the Free Software Foundation, Inc.
5
6 This file is part of RCS.
7
8 RCS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 RCS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with RCS; see the file COPYING.
20 If not, write to the Free Software Foundation,
21 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23 Report problems and direct all questions to:
24
25 rcs-bugs@cs.purdue.edu
26
27 */
28
29#if has_conf_h
30# include <conf.h>
31#else
32# if HAVE_CONFIG_H
33# include <config.h>
34# else
35# ifndef __STDC__
36# define const
37# endif
38# endif
39# if HAVE_LIMITS_H
40# include <limits.h>
41# endif
42# ifndef LONG_MIN
43# define LONG_MIN (-1-2147483647L)
44# endif
45# if STDC_HEADERS
46# include <stdlib.h>
47# endif
48# include <time.h>
49# ifdef __STDC__
50# define P(x) x
51# else
52# define P(x) ()
53# endif
54#endif
55
56#include <ctype.h>
57#if STDC_HEADERS
58# define CTYPE_DOMAIN(c) 1
59#else
60# define CTYPE_DOMAIN(c) ((unsigned) (c) <= 0177)
61#endif
62#define ISALNUM(c) (CTYPE_DOMAIN (c) && isalnum (c))
63#define ISALPHA(c) (CTYPE_DOMAIN (c) && isalpha (c))
64#define ISSPACE(c) (CTYPE_DOMAIN (c) && isspace (c))
65#define ISUPPER(c) (CTYPE_DOMAIN (c) && isupper (c))
66#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
67
68#include <partime.h>
69
70char const partimeId[] =
71 "$Id: partime.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $";
72
73
74/* Lookup tables for names of months, weekdays, time zones. */
75
76#define NAME_LENGTH_MAXIMUM 4
77
78struct name_val
79 {
80 char name[NAME_LENGTH_MAXIMUM];
81 int val;
82 };
83
84
85static char const *parse_decimal P ((char const *, int, int, int, int, int *, int *));
86static char const *parse_fixed P ((char const *, int, int *));
87static char const *parse_pattern_letter P ((char const *, int, struct partime *));
88static char const *parse_prefix P ((char const *, struct partime *, int *));
89static char const *parse_ranged P ((char const *, int, int, int, int *));
90static int lookup P ((char const *, struct name_val const[]));
91static int merge_partime P ((struct partime *, struct partime const *));
92static void undefine P ((struct partime *));
93
94
95static struct name_val const month_names[] =
96{
97 {"jan", 0},
98 {"feb", 1},
99 {"mar", 2},
100 {"apr", 3},
101 {"may", 4},
102 {"jun", 5},
103 {"jul", 6},
104 {"aug", 7},
105 {"sep", 8},
106 {"oct", 9},
107 {"nov", 10},
108 {"dec", 11},
109 {"", TM_UNDEFINED}
110};
111
112static struct name_val const weekday_names[] =
113{
114 {"sun", 0},
115 {"mon", 1},
116 {"tue", 2},
117 {"wed", 3},
118 {"thu", 4},
119 {"fri", 5},
120 {"sat", 6},
121 {"", TM_UNDEFINED}
122};
123
124#define hr60nonnegative(t) ((t)/100 * 60 + (t)%100)
125#define hr60(t) ((t)<0 ? -hr60nonnegative(-(t)) : hr60nonnegative(t))
126#define zs(t,s) {s, hr60(t)}
127#define zd(t,s,d) zs(t, s), zs((t)+100, d)
128
129static struct name_val const zone_names[] =
130{
131 zs (-1000, "hst"), /* Hawaii */
132 zd (-1000, "hast", "hadt"), /* Hawaii-Aleutian */
133 zd (- 900, "akst", "akdt"), /* Alaska */
134 zd (- 800, "pst" , "pdt" ), /* Pacific */
135 zd (- 700, "mst" , "mdt" ), /* Mountain */
136 zd (- 600, "cst" , "cdt" ), /* Central */
137 zd (- 500, "est" , "edt" ), /* Eastern */
138 zd (- 400, "ast" , "adt" ), /* Atlantic */
139 zd (- 330, "nst" , "ndt" ), /* Newfoundland */
140 zs ( 000, "utc" ), /* Coordinated Universal */
141 zs ( 000, "uct" ), /* " */
142 zs ( 000, "cut" ), /* " */
143 zs ( 000, "ut"), /* Universal */
144 zs ( 000, "z"), /* Zulu (required by ISO 8601) */
145 zd ( 000, "gmt" , "bst" ), /* Greenwich Mean, British Summer */
146 zd ( 000, "wet" , "west"), /* Western European */
147 zd ( 100, "cet" , "cest"), /* Central European */
148 zd ( 100, "met" , "mest"), /* Middle European (bug in old tz versions) */
149 zd ( 100, "mez" , "mesz"), /* Mittel-Europaeische Zeit */
150 zd ( 200, "eet" , "eest"), /* Eastern European */
151 zs ( 530, "ist" ), /* India */
152 zd ( 900, "jst" , "jdt" ), /* Japan */
153 zd ( 900, "kst" , "kdt" ), /* Korea */
154 zd ( 1200, "nzst", "nzdt"), /* New Zealand */
155 {"lt", 1},
156#if 0
157 /* The following names are duplicates or are not well attested.
158 There are lots more where these came from. */
159 zs (-1100, "sst" ), /* Samoan */
160 zd (- 900, "yst" , "ydt" ), /* Yukon - name is no longer used */
161 zd (- 500, "ast" , "adt" ), /* Acre */
162 zd (- 400, "wst" , "wdt" ), /* Western Brazil */
163 zd (- 400, "cst" , "cdt" ), /* Chile */
164 zd (- 200, "fst" , "fdt" ), /* Fernando de Noronha */
165 zs ( 000, "wat" ), /* West African */
166 zs ( 100, "cat" ), /* Central African */
167 zs ( 200, "sat" ), /* South African */
168 zd ( 200, "ist" , "idt" ), /* Israel */
169 zs ( 300, "eat" ), /* East African */
170 zd ( 300, "msk" , "msd" ), /* Moscow */
171 zd ( 330, "ist" , "idt" ), /* Iran */
172 zs ( 800, "hkt" ), /* Hong Kong */
173 zs ( 800, "sgt" ), /* Singapore */
174 zd ( 800, "cst" , "cdt" ), /* China */
175 zd ( 800, "wst" , "wst" ), /* Western Australia */
176 zd ( 930, "cst" , "cst" ), /* Central Australia */
177 zs ( 1000, "gst" ), /* Guam */
178 zd ( 1000, "est" , "est" ), /* Eastern Australia */
179#endif
180 {"", -1}
181};
182
183/* Look for a prefix of S in TABLE, returning val for first matching entry. */
184static int
185lookup (s, table)
186 char const *s;
187 struct name_val const table[];
188{
189 int j;
190 char buf[NAME_LENGTH_MAXIMUM];
191
192 for (j = 0; j < NAME_LENGTH_MAXIMUM; j++)
193 {
194 unsigned char c = *s++;
195 if (! ISALPHA (c))
196 {
197 buf[j] = '\0';
198 break;
199 }
200 buf[j] = ISUPPER (c) ? tolower (c) : c;
201 }
202
203 for (;; table++)
204 for (j = 0; ; j++)
205 if (j == NAME_LENGTH_MAXIMUM || ! table[0].name[j])
206 return table[0].val;
207 else if (buf[j] != table[0].name[j])
208 break;
209}
210
211
212/* Set *T to ``undefined'' values. */
213static void
214undefine (t)
215 struct partime *t;
216{
217 t->tm.tm_sec = t->tm.tm_min = t->tm.tm_hour = t->tm.tm_mday = t->tm.tm_mon
218 = t->tm.tm_year = t->tm.tm_wday = t->tm.tm_yday
219 = t->ymodulus = t->yweek
220 = TM_UNDEFINED;
221 t->zone = TM_UNDEFINED_ZONE;
222}
223
224/* Array of patterns to look for in a date string.
225 Order is important: we look for the first matching pattern
226 whose values do not contradict values that we already know about.
227 See `parse_pattern_letter' below for the meaning of the pattern codes. */
228static char const *const patterns[] =
229{
230 /* These traditional patterns must come first,
231 to prevent an ISO 8601 format from misinterpreting their prefixes. */
232 "E_n_y", "x", /* RFC 822 */
233 "E_n", "n_E", "n", "t:m:s_A", "t:m_A", "t_A", /* traditional */
234 "y/N/D$", /* traditional RCS */
235
236 /* ISO 8601:1988 formats, generalized a bit. */
237 "y-N-D$", "4ND$", "Y-N$",
238 "RND$", "-R=N$", "-R$", "--N=D$", "N=DT",
239 "--N$", "---D$", "DT",
240 "Y-d$", "4d$", "R=d$", "-d$", "dT",
241 "y-W-X", "yWX", "y=W",
242 "-r-W-X", "r-W-XT", "-rWX", "rWXT", "-W=X", "W=XT", "-W",
243 "-w-X", "w-XT", "---X$", "XT", "4$",
244 "T",
245 "h:m:s$", "hms$", "h:m$", "hm$", "h$", "-m:s$", "-ms$", "-m$", "--s$",
246 "Y", "Z",
247
248 0
249};
250
251/* Parse an initial prefix of STR, setting *T accordingly.
252 Return the first character after the prefix, or 0 if it couldn't be parsed.
253 Start with pattern *PI; if success, set *PI to the next pattern to try.
254 Set *PI to -1 if we know there are no more patterns to try;
255 if *PI is initially negative, give up immediately. */
256static char const *
257parse_prefix (str, t, pi)
258 char const *str;
259 struct partime *t;
260 int *pi;
261{
262 int i = *pi;
263 char const *pat;
264 unsigned char c;
265
266 if (i < 0)
267 return 0;
268
269 /* Remove initial noise. */
270 while (! ISALNUM (c = *str) && c != '-' && c != '+')
271 {
272 if (! c)
273 {
274 undefine (t);
275 *pi = -1;
276 return str;
277 }
278 str++;
279 }
280
281 /* Try a pattern until one succeeds. */
282 while ((pat = patterns[i++]) != 0)
283 {
284 char const *s = str;
285 undefine (t);
286 do
287 {
288 if (! (c = *pat++))
289 {
290 *pi = i;
291 return s;
292 }
293 }
294 while ((s = parse_pattern_letter (s, c, t)) != 0);
295 }
296
297 return 0;
298}
299
300/* Parse an initial prefix of S of length DIGITS; it must be a number.
301 Store the parsed number into *RES.
302 Return the first character after the prefix, or 0 if it wasn't parsed. */
303static char const *
304parse_fixed (s, digits, res)
305 char const *s;
306 int digits, *res;
307{
308 int n = 0;
309 char const *lim = s + digits;
310 while (s < lim)
311 {
312 unsigned d = *s++ - '0';
313 if (9 < d)
314 return 0;
315 n = 10 * n + d;
316 }
317 *res = n;
318 return s;
319}
320
321/* Parse an initial prefix of S of length DIGITS;
322 it must be a number in the range LO through HI.
323 Store the parsed number into *RES.
324 Return the first character after the prefix, or 0 if it wasn't parsed. */
325static char const *
326parse_ranged (s, digits, lo, hi, res)
327 char const *s;
328 int digits, lo, hi, *res;
329{
330 s = parse_fixed (s, digits, res);
331 return s && lo <= *res && *res <= hi ? s : 0;
332}
333
334/* Parse an initial prefix of S of length DIGITS;
335 it must be a number in the range LO through HI
336 and it may be followed by a fraction to be computed using RESOLUTION.
337 Store the parsed number into *RES; store the fraction times RESOLUTION,
338 rounded to the nearest integer, into *FRES.
339 Return the first character after the prefix, or 0 if it wasn't parsed. */
340static char const *
341parse_decimal (s, digits, lo, hi, resolution, res, fres)
342 char const *s;
343 int digits, lo, hi, resolution, *res, *fres;
344{
345 s = parse_fixed (s, digits, res);
346 if (s && lo <= *res && *res <= hi)
347 {
348 int f = 0;
349 if ((s[0] == ',' || s[0] == '.') && ISDIGIT (s[1]))
350 {
351 char const *s1 = ++s;
352 int num10 = 0, denom10 = 10, product;
353 while (ISDIGIT (*++s))
354 {
355 int d = denom10 * 10;
356 if (d / 10 != denom10)
357 return 0; /* overflow */
358 denom10 = d;
359 }
360 s = parse_fixed (s1, (int) (s - s1), &num10);
361 product = num10 * resolution;
362 f = (product + (denom10 >> 1)) / denom10;
363 f -= f & (product % denom10 == denom10 >> 1); /* round to even */
364 if (f < 0 || product/resolution != num10)
365 return 0; /* overflow */
366 }
367 *fres = f;
368 return s;
369 }
370 return 0;
371}
372
373/* Parse an initial prefix of S; it must denote a time zone.
374 Set *ZONE to the number of seconds east of GMT,
375 or to TM_LOCAL_ZONE if it is the local time zone.
376 Return the first character after the prefix, or 0 if it wasn't parsed. */
377char *
378parzone (s, zone)
379 char const *s;
380 long *zone;
381{
382 char sign;
383 int hh, mm, ss;
384 int minutesEastOfUTC;
385 long offset, z;
386
387 /* The formats are LT, n, n DST, nDST, no, o
388 where n is a time zone name
389 and o is a time zone offset of the form [-+]hh[:mm[:ss]]. */
390 switch (*s)
391 {
392 case '-':
393 case '+':
394 z = 0;
395 break;
396
397 default:
398 minutesEastOfUTC = lookup (s, zone_names);
399 if (minutesEastOfUTC == -1)
400 return 0;
401
402 /* Don't bother to check rest of spelling. */
403 while (ISALPHA ((unsigned char) *s))
404 s++;
405
406 /* Don't modify LT. */
407 if (minutesEastOfUTC == 1)
408 {
409 *zone = TM_LOCAL_ZONE;
410 return (char *) s;
411 }
412
413 z = minutesEastOfUTC * 60L;
414
415 /* Look for trailing " DST". */
416 if ((s[-1] == 'T' || s[-1] == 't')
417 && (s[-2] == 'S' || s[-2] == 's')
418 && (s[-3] == 'D' || s[-3] == 'd'))
419 goto trailing_dst;
420 while (ISSPACE ((unsigned char) *s))
421 s++;
422 if ((s[0] == 'D' || s[0] == 'd')
423 && (s[1] == 'S' || s[1] == 's')
424 && (s[2] == 'T' || s[2] == 't'))
425 {
426 s += 3;
427 trailing_dst:
428 *zone = z + 60*60;
429 return (char *) s;
430 }
431
432 switch (*s)
433 {
434 case '-':
435 case '+':
436 break;
437
438 default:
439 *zone = z;
440 return (char *) s;
441 }
442
443 break;
444 }
445
446 sign = *s++;
447
448 if (! (s = parse_ranged (s, 2, 0, 23, &hh)))
449 return 0;
450 mm = ss = 0;
451 if (*s == ':')
452 s++;
453 if (ISDIGIT (*s))
454 {
455 if (! (s = parse_ranged (s, 2, 0, 59, &mm)))
456 return 0;
457 if (*s == ':' && s[-3] == ':' && ISDIGIT (s[1])
458 && ! (s = parse_ranged (s + 1, 2, 0, 59, &ss)))
459 return 0;
460 }
461 if (ISDIGIT (*s))
462 return 0;
463 offset = (hh * 60 + mm) * 60L + ss;
464 *zone = z + (sign == '-' ? -offset : offset);
465 /* ?? Are fractions allowed here? If so, they're not implemented. */
466 return (char *) s;
467}
468
469/* Parse an initial prefix of S, matching the pattern whose code is C.
470 Set *T accordingly.
471 Return the first character after the prefix, or 0 if it wasn't parsed. */
472static char const *
473parse_pattern_letter (s, c, t)
474 char const *s;
475 int c;
476 struct partime *t;
477{
478 switch (c)
479 {
480 case '$': /* The next character must be a non-digit. */
481 if (ISDIGIT (*s))
482 return 0;
483 break;
484
485 case '-':
486 case '/':
487 case ':':
488 /* These characters stand for themselves. */
489 if (*s++ != c)
490 return 0;
491 break;
492
493 case '4': /* 4-digit year */
494 s = parse_fixed (s, 4, &t->tm.tm_year);
495 break;
496
497 case '=': /* optional '-' */
498 s += *s == '-';
499 break;
500
501 case 'A': /* AM or PM */
502 /* This matches the regular expression [AaPp][Mm]?.
503 It must not be followed by a letter or digit;
504 otherwise it would match prefixes of strings like "PST". */
505 switch (*s++)
506 {
507 case 'A':
508 case 'a':
509 if (t->tm.tm_hour == 12)
510 t->tm.tm_hour = 0;
511 break;
512
513 case 'P':
514 case 'p':
515 if (t->tm.tm_hour != 12)
516 t->tm.tm_hour += 12;
517 break;
518
519 default:
520 return 0;
521 }
522 switch (*s)
523 {
524 case 'M':
525 case 'm':
526 s++;
527 break;
528 }
529 if (ISALNUM ((unsigned char) *s))
530 return 0;
531 break;
532
533 case 'D': /* day of month [01-31] */
534 s = parse_ranged (s, 2, 1, 31, &t->tm.tm_mday);
535 break;
536
537 case 'd': /* day of year [001-366] */
538 s = parse_ranged (s, 3, 1, 366, &t->tm.tm_yday);
539 t->tm.tm_yday--;
540 break;
541
542 case 'E': /* extended day of month [1-9, 01-31] */
543 s = parse_ranged (s, (ISDIGIT (s[0]) && ISDIGIT (s[1])) + 1, 1, 31,
544 &t->tm.tm_mday);
545 break;
546
547 case 'h': /* hour [00-23 followed by optional fraction] */
548 {
549 int frac;
550 s = parse_decimal (s, 2, 0, 23, 60 * 60, &t->tm.tm_hour, &frac);
551 t->tm.tm_min = frac / 60;
552 t->tm.tm_sec = frac % 60;
553 }
554 break;
555
556 case 'm': /* minute [00-59 followed by optional fraction] */
557 s = parse_decimal (s, 2, 0, 59, 60, &t->tm.tm_min, &t->tm.tm_sec);
558 break;
559
560 case 'n': /* month name [e.g. "Jan"] */
561 if (! TM_DEFINED (t->tm.tm_mon = lookup (s, month_names)))
562 return 0;
563 /* Don't bother to check rest of spelling. */
564 while (ISALPHA ((unsigned char) *s))
565 s++;
566 break;
567
568 case 'N': /* month [01-12] */
569 s = parse_ranged (s, 2, 1, 12, &t->tm.tm_mon);
570 t->tm.tm_mon--;
571 break;
572
573 case 'r': /* year % 10 (remainder in origin-0 decade) [0-9] */
574 s = parse_fixed (s, 1, &t->tm.tm_year);
575 t->ymodulus = 10;
576 break;
577
578 case_R:
579 case 'R': /* year % 100 (remainder in origin-0 century) [00-99] */
580 s = parse_fixed (s, 2, &t->tm.tm_year);
581 t->ymodulus = 100;
582 break;
583
584 case 's': /* second [00-60 followed by optional fraction] */
585 {
586 int frac;
587 s = parse_decimal (s, 2, 0, 60, 1, &t->tm.tm_sec, &frac);
588 t->tm.tm_sec += frac;
589 }
590 break;
591
592 case 'T': /* 'T' or 't' */
593 switch (*s++)
594 {
595 case 'T':
596 case 't':
597 break;
598 default:
599 return 0;
600 }
601 break;
602
603 case 't': /* traditional hour [1-9 or 01-12] */
604 s = parse_ranged (s, (ISDIGIT (s[0]) && ISDIGIT (s[1])) + 1, 1, 12,
605 &t->tm.tm_hour);
606 break;
607
608 case 'w': /* 'W' or 'w' only (stands for current week) */
609 switch (*s++)
610 {
611 case 'W':
612 case 'w':
613 break;
614 default:
615 return 0;
616 }
617 break;
618
619 case 'W': /* 'W' or 'w', followed by a week of year [00-53] */
620 switch (*s++)
621 {
622 case 'W':
623 case 'w':
624 break;
625 default:
626 return 0;
627 }
628 s = parse_ranged (s, 2, 0, 53, &t->yweek);
629 break;
630
631 case 'X': /* weekday (1=Mon ... 7=Sun) [1-7] */
632 s = parse_ranged (s, 1, 1, 7, &t->tm.tm_wday);
633 t->tm.tm_wday--;
634 break;
635
636 case 'x': /* weekday name [e.g. "Sun"] */
637 if (! TM_DEFINED (t->tm.tm_wday = lookup (s, weekday_names)))
638 return 0;
639 /* Don't bother to check rest of spelling. */
640 while (ISALPHA ((unsigned char) *s))
641 s++;
642 break;
643
644 case 'y': /* either R or Y */
645 if (ISDIGIT (s[0]) && ISDIGIT (s[1]) && ! ISDIGIT (s[2]))
646 goto case_R;
647 /* fall into */
648 case 'Y': /* year in full [4 or more digits] */
649 {
650 int len = 0;
651 while (ISDIGIT (s[len]))
652 len++;
653 if (len < 4)
654 return 0;
655 s = parse_fixed (s, len, &t->tm.tm_year);
656 }
657 break;
658
659 case 'Z': /* time zone */
660 s = parzone (s, &t->zone);
661 break;
662
663 case '_': /* possibly empty sequence of non-alphanumerics */
664 while (! ISALNUM ((unsigned char) *s) && *s)
665 s++;
666 break;
667
668 default: /* bad pattern */
669 return 0;
670 }
671
672 return s;
673}
674
675/* If there is no conflict, merge into *T the additional information in *U
676 and return 0. Otherwise do nothing and return -1. */
677static int
678merge_partime (t, u)
679 struct partime *t;
680 struct partime const *u;
681{
682# define conflict(a,b) ((a) != (b) && TM_DEFINED (a) && TM_DEFINED (b))
683 if (conflict (t->tm.tm_sec, u->tm.tm_sec)
684 || conflict (t->tm.tm_min, u->tm.tm_min)
685 || conflict (t->tm.tm_hour, u->tm.tm_hour)
686 || conflict (t->tm.tm_mday, u->tm.tm_mday)
687 || conflict (t->tm.tm_mon, u->tm.tm_mon)
688 || conflict (t->tm.tm_year, u->tm.tm_year)
689 || conflict (t->tm.tm_wday, u->tm.tm_yday)
690 || conflict (t->ymodulus, u->ymodulus)
691 || conflict (t->yweek, u->yweek)
692 || (t->zone != u->zone
693 && t->zone != TM_UNDEFINED_ZONE
694 && u->zone != TM_UNDEFINED_ZONE))
695 return -1;
696# undef conflict
697# define merge_(a,b) if (TM_DEFINED (b)) (a) = (b);
698 merge_ (t->tm.tm_sec, u->tm.tm_sec)
699 merge_ (t->tm.tm_min, u->tm.tm_min)
700 merge_ (t->tm.tm_hour, u->tm.tm_hour)
701 merge_ (t->tm.tm_mday, u->tm.tm_mday)
702 merge_ (t->tm.tm_mon, u->tm.tm_mon)
703 merge_ (t->tm.tm_year, u->tm.tm_year)
704 merge_ (t->tm.tm_wday, u->tm.tm_yday)
705 merge_ (t->ymodulus, u->ymodulus)
706 merge_ (t->yweek, u->yweek)
707# undef merge_
708 if (u->zone != TM_UNDEFINED_ZONE)
709 t->zone = u->zone;
710 return 0;
711}
712
713/* Parse a date/time prefix of S, putting the parsed result into *T.
714 Return the first character after the prefix.
715 The prefix may contain no useful information;
716 in that case, *T will contain only undefined values. */
717char *
718partime (s, t)
719 char const *s;
720 struct partime *t;
721{
722 struct partime p;
723
724 undefine (t);
725
726 while (*s)
727 {
728 int i = 0;
729 char const *s1;
730
731 do
732 {
733 if (! (s1 = parse_prefix (s, &p, &i)))
734 return (char *) s;
735 }
736 while (merge_partime (t, &p) != 0);
737
738 s = s1;
739 }
740
741 return (char *) s;
742}
diff --git a/xdelta1/libedsio/partime.h b/xdelta1/libedsio/partime.h
deleted file mode 100644
index bcc8165..0000000
--- a/xdelta1/libedsio/partime.h
+++ /dev/null
@@ -1,67 +0,0 @@
1/* Parse a string, yielding a struct partime that describes it. */
2
3/* Copyright 1993, 1994, 1995, 1997 Paul Eggert
4 Distributed under license by the Free Software Foundation, Inc.
5
6 This file is part of RCS.
7
8 RCS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 RCS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with RCS; see the file COPYING.
20 If not, write to the Free Software Foundation,
21 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23 Report problems and direct all questions to:
24
25 rcs-bugs@cs.purdue.edu
26
27 */
28
29#define TM_UNDEFINED (-1)
30#define TM_DEFINED(x) (0 <= (x))
31
32/* #include <limits.h> if you want to use these symbols. */
33#define TM_LOCAL_ZONE LONG_MIN
34#define TM_UNDEFINED_ZONE (LONG_MIN + 1)
35
36struct partime
37 {
38 /* This structure describes the parsed time.
39 Only the following tm_* values in it are used:
40 sec, min, hour, mday, mon, year, wday, yday.
41 If TM_UNDEFINED (value), the parser never found the value.
42 The tm_year field is the actual year, not the year - 1900;
43 but see ymodulus below. */
44 struct tm tm;
45
46 /* If !TM_UNDEFINED (ymodulus),
47 then tm.tm_year is actually modulo ymodulus. */
48 int ymodulus;
49
50 /* Week of year, ISO 8601 style.
51 If TM_UNDEFINED (yweek), the parser never found yweek.
52 Weeks start on Mondays.
53 Week 1 includes Jan 4. */
54 int yweek;
55
56 /* Seconds east of UTC; or TM_LOCAL_ZONE or TM_UNDEFINED_ZONE. */
57 long zone;
58 };
59
60#if defined __STDC__ || has_prototypes
61# define __PARTIME_P(x) x
62#else
63# define __PARTIME_P(x) ()
64#endif
65
66char *partime __PARTIME_P ((char const *, struct partime *));
67char *parzone __PARTIME_P ((char const *, long *));
diff --git a/xdelta1/libedsio/sha.c b/xdelta1/libedsio/sha.c
deleted file mode 100644
index 503fe85..0000000
--- a/xdelta1/libedsio/sha.c
+++ /dev/null
@@ -1,239 +0,0 @@
1/* NIST Secure Hash Algorithm */
2/* heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> */
3/* from Peter C. Gutmann's implementation as found in */
4/* Applied Cryptography by Bruce Schneier */
5/* Further modifications to include the "UNRAVEL" stuff, below */
6
7/* This code is in the public domain */
8
9#include "edsio.h"
10#include <string.h>
11
12#define SHA_BLOCKSIZE 64
13#define SHA_DIGESTSIZE 20
14
15/* UNRAVEL should be fastest & biggest */
16/* UNROLL_LOOPS should be just as big, but slightly slower */
17/* both undefined should be smallest and slowest */
18
19#define UNRAVEL
20/* #define UNROLL_LOOPS */
21
22/* by default, compile for little-endian machines (Intel, Vax) */
23/* change for big-endian machines; for machines which are neither, */
24/* you will need to change the definition of maybe_byte_reverse */
25
26#ifndef WORDS_BIGENDIAN /* from config.h */
27#define SHA_LITTLE_ENDIAN
28#endif
29
30/* NIST's proposed modification to SHA of 7/11/94 may be */
31/* activated by defining USE_MODIFIED_SHA; leave it off for now */
32#undef USE_MODIFIED_SHA
33
34/* SHA f()-functions */
35
36#define f1(x,y,z) ((x & y) | (~x & z))
37#define f2(x,y,z) (x ^ y ^ z)
38#define f3(x,y,z) ((x & y) | (x & z) | (y & z))
39#define f4(x,y,z) (x ^ y ^ z)
40
41/* SHA constants */
42
43#define CONST1 0x5a827999L
44#define CONST2 0x6ed9eba1L
45#define CONST3 0x8f1bbcdcL
46#define CONST4 0xca62c1d6L
47
48/* 32-bit rotate */
49
50#define ROT32(x,n) ((x << n) | (x >> (32 - n)))
51
52/* the generic case, for when the overall rotation is not unraveled */
53
54#define FG(n) \
55 T = ROT32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n; \
56 E = D; D = C; C = ROT32(B,30); B = A; A = T
57
58/* specific cases, for when the overall rotation is unraveled */
59
60#define FA(n) \
61 T = ROT32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n; B = ROT32(B,30)
62
63#define FB(n) \
64 E = ROT32(T,5) + f##n(A,B,C) + D + *WP++ + CONST##n; A = ROT32(A,30)
65
66#define FC(n) \
67 D = ROT32(E,5) + f##n(T,A,B) + C + *WP++ + CONST##n; T = ROT32(T,30)
68
69#define FD(n) \
70 C = ROT32(D,5) + f##n(E,T,A) + B + *WP++ + CONST##n; E = ROT32(E,30)
71
72#define FE(n) \
73 B = ROT32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n; D = ROT32(D,30)
74
75#define FT(n) \
76 A = ROT32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n; C = ROT32(C,30)
77
78/* do SHA transformation */
79
80static void sha_transform(EdsioSHACtx *ctx)
81{
82 int i;
83 guint32 T, A, B, C, D, E, W[80], *WP;
84
85 for (i = 0; i < 16; ++i) {
86 W[i] = ctx->data[i];
87 }
88 for (i = 16; i < 80; ++i) {
89 W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
90#ifdef USE_MODIFIED_SHA
91 W[i] = ROT32(W[i], 1);
92#endif /* USE_MODIFIED_SHA */
93 }
94 A = ctx->digest[0];
95 B = ctx->digest[1];
96 C = ctx->digest[2];
97 D = ctx->digest[3];
98 E = ctx->digest[4];
99 WP = W;
100#ifdef UNRAVEL
101 FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1);
102 FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1);
103 FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2);
104 FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2);
105 FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3);
106 FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3);
107 FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4);
108 FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4);
109 ctx->digest[0] += E;
110 ctx->digest[1] += T;
111 ctx->digest[2] += A;
112 ctx->digest[3] += B;
113 ctx->digest[4] += C;
114#else /* !UNRAVEL */
115#ifdef UNROLL_LOOPS
116 FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
117 FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
118 FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
119 FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
120 FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
121 FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
122 FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
123 FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
124#else /* !UNROLL_LOOPS */
125 for (i = 0; i < 20; ++i) { FG(1); }
126 for (i = 20; i < 40; ++i) { FG(2); }
127 for (i = 40; i < 60; ++i) { FG(3); }
128 for (i = 60; i < 80; ++i) { FG(4); }
129#endif /* !UNROLL_LOOPS */
130 ctx->digest[0] += A;
131 ctx->digest[1] += B;
132 ctx->digest[2] += C;
133 ctx->digest[3] += D;
134 ctx->digest[4] += E;
135#endif /* !UNRAVEL */
136}
137
138#ifdef SHA_LITTLE_ENDIAN
139
140/* change endianness of data */
141
142static void maybe_byte_reverse(guint32 *buffer, int count)
143{
144 int i;
145 guint32 in;
146
147 count /= sizeof(guint32);
148 for (i = 0; i < count; ++i) {
149 in = *buffer;
150 *buffer++ = ((in << 24) & 0xff000000) | ((in << 8) & 0x00ff0000) |
151 ((in >> 8) & 0x0000ff00) | ((in >> 24) & 0x000000ff);
152 }
153}
154
155#else /* !SHA_LITTLE_ENDIAN */
156
157#define maybe_byte_reverse(a,b) /* do nothing */
158
159#endif /* SHA_LITTLE_ENDIAN */
160
161/* initialize the SHA digest */
162
163void edsio_sha_init(EdsioSHACtx *ctx)
164{
165 ctx->digest[0] = 0x67452301L;
166 ctx->digest[1] = 0xefcdab89L;
167 ctx->digest[2] = 0x98badcfeL;
168 ctx->digest[3] = 0x10325476L;
169 ctx->digest[4] = 0xc3d2e1f0L;
170 ctx->count_lo = 0L;
171 ctx->count_hi = 0L;
172 ctx->local = 0;
173}
174
175/* update the SHA digest */
176
177void edsio_sha_update(EdsioSHACtx *ctx, const guint8 *buffer, guint count)
178{
179 int i;
180
181 if ((ctx->count_lo + ((guint32) count << 3)) < ctx->count_lo) {
182 ++ctx->count_hi;
183 }
184 ctx->count_lo += (guint32) count << 3;
185 ctx->count_hi += (guint32) count >> 29;
186 if (ctx->local) {
187 i = SHA_BLOCKSIZE - ctx->local;
188 if (i > count) {
189 i = count;
190 }
191 memcpy(((guint8 *) ctx->data) + ctx->local, buffer, i);
192 count -= i;
193 buffer += i;
194 ctx->local += i;
195 if (ctx->local == SHA_BLOCKSIZE) {
196 maybe_byte_reverse(ctx->data, SHA_BLOCKSIZE);
197 sha_transform(ctx);
198 } else {
199 return;
200 }
201 }
202 while (count >= SHA_BLOCKSIZE) {
203 memcpy(ctx->data, buffer, SHA_BLOCKSIZE);
204 buffer += SHA_BLOCKSIZE;
205 count -= SHA_BLOCKSIZE;
206 maybe_byte_reverse(ctx->data, SHA_BLOCKSIZE);
207 sha_transform(ctx);
208 }
209 memcpy(ctx->data, buffer, count);
210 ctx->local = count;
211}
212
213/* finish computing the SHA digest */
214
215void edsio_sha_final(guint8* digest, EdsioSHACtx *ctx)
216{
217 int count;
218 guint32 lo_bit_count, hi_bit_count;
219
220 lo_bit_count = ctx->count_lo;
221 hi_bit_count = ctx->count_hi;
222 count = (int) ((lo_bit_count >> 3) & 0x3f);
223 ((guint8 *) ctx->data)[count++] = 0x80;
224 if (count > SHA_BLOCKSIZE - 8) {
225 memset(((guint8 *) ctx->data) + count, 0, SHA_BLOCKSIZE - count);
226 maybe_byte_reverse(ctx->data, SHA_BLOCKSIZE);
227 sha_transform(ctx);
228 memset((guint8 *) ctx->data, 0, SHA_BLOCKSIZE - 8);
229 } else {
230 memset(((guint8 *) ctx->data) + count, 0,
231 SHA_BLOCKSIZE - 8 - count);
232 }
233 maybe_byte_reverse(ctx->data, SHA_BLOCKSIZE);
234 ctx->data[14] = hi_bit_count;
235 ctx->data[15] = lo_bit_count;
236 sha_transform(ctx);
237
238 memcpy (digest, ctx->digest, 20);
239}
diff --git a/xdelta1/libedsio/simple.c b/xdelta1/libedsio/simple.c
deleted file mode 100644
index cda509e..0000000
--- a/xdelta1/libedsio/simple.c
+++ /dev/null
@@ -1,179 +0,0 @@
1/* -*-Mode: C;-*-
2 * $Id: simple.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $
3 *
4 * Copyright (C) 1998, 1999, Josh MacDonald.
5 * All Rights Reserved.
6 *
7 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
8 */
9
10#include "edsio.h"
11
12/* Simple Source
13 */
14
15typedef struct _ByteArraySource ByteArraySource;
16
17struct _ByteArraySource {
18 SerialSource source;
19
20 const guint8* in_data;
21 guint in_len;
22
23 guint read_pos;
24 guint flags;
25};
26
27static gboolean byte_array_source_close (SerialSource* source);
28static gboolean byte_array_source_read (SerialSource* source, guint8 *ptr, guint32 len);
29static void byte_array_source_free (SerialSource* source);
30
31SerialSource*
32edsio_simple_source (const guint8* data, guint len, guint flags)
33{
34 ByteArraySource* it = g_new0 (ByteArraySource, 1);
35 SerialSource* src = (SerialSource*) it;
36
37 serializeio_source_init (& it->source,
38 NULL,
39 byte_array_source_close,
40 byte_array_source_read,
41 byte_array_source_free,
42 NULL,
43 NULL);
44
45 it->in_data = data;
46 it->in_len = len;
47 it->flags = flags;
48
49 if (flags & SBF_Base64)
50 src = serializeio_base64_source (src);
51
52 if (flags & SBF_Checksum)
53 src = serializeio_checksum_source (src);
54
55 if (flags & SBF_Compress)
56 src = serializeio_gzip_source (src);
57
58 return src;
59}
60
61gboolean
62byte_array_source_close (SerialSource* source)
63{
64 return TRUE;
65}
66
67gboolean
68byte_array_source_read (SerialSource* source, guint8 *buf, guint32 len)
69{
70 ByteArraySource* ssource = (ByteArraySource*) source;
71
72 if (len + ssource->read_pos > ssource->in_len)
73 {
74 edsio_generate_source_event (EC_EdsioSourceEof, source);
75 return FALSE;
76 }
77
78 memcpy (buf, ssource->in_data + ssource->read_pos, len);
79
80 ssource->read_pos += len;
81
82 return TRUE;
83}
84
85void
86byte_array_source_free (SerialSource* source)
87{
88 g_free (source);
89}
90
91/* BASE64 Sink
92 */
93
94typedef struct _ByteArraySink ByteArraySink;
95
96struct _ByteArraySink {
97 SerialSink sink;
98
99 GByteArray* out;
100
101 gpointer data;
102 guint flags;
103 gboolean free_result;
104 void (* success) (gpointer data, GByteArray* result);
105};
106
107static gboolean byte_array_sink_close (SerialSink* sink);
108static gboolean byte_array_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len);
109static void byte_array_sink_free (SerialSink* sink);
110
111SerialSink*
112edsio_simple_sink (gpointer data,
113 guint flags,
114 gboolean free_result,
115 void (* success) (gpointer data, GByteArray* result),
116 GByteArray **result)
117{
118 ByteArraySink* it = g_new0 (ByteArraySink, 1);
119 SerialSink* sink = (SerialSink*) it;
120
121 serializeio_sink_init (&it->sink,
122 NULL,
123 byte_array_sink_close,
124 byte_array_sink_write,
125 byte_array_sink_free,
126 NULL);
127
128 it->data = data;
129 it->out = g_byte_array_new ();
130 it->flags = flags;
131 it->free_result = free_result;
132 it->success = success;
133
134 if (result)
135 (*result) = it->out;
136
137 if (flags & SBF_Base64)
138 sink = serializeio_base64_sink (sink);
139
140 if (flags & SBF_Checksum)
141 sink = serializeio_checksum_sink (sink);
142
143 if (flags & SBF_Compress)
144 sink = serializeio_gzip_sink (sink);
145
146 return sink;
147}
148
149gboolean
150byte_array_sink_close (SerialSink* sink)
151{
152 ByteArraySink* ssink = (ByteArraySink*) sink;
153
154 if (ssink->success)
155 ssink->success (ssink->data, ssink->out);
156
157 return TRUE;
158}
159
160gboolean
161byte_array_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len)
162{
163 ByteArraySink* ssink = (ByteArraySink*) sink;
164
165 g_byte_array_append (ssink->out, ptr, len);
166
167 return TRUE;
168}
169
170void
171byte_array_sink_free (SerialSink* sink)
172{
173 ByteArraySink* ssink = (ByteArraySink*) sink;
174
175 if (ssink->out && ssink->free_result)
176 g_byte_array_free (ssink->out, TRUE);
177
178 g_free (sink);
179}
diff --git a/xdelta1/runtest b/xdelta1/runtest
deleted file mode 100644
index 1088d7b..0000000
--- a/xdelta1/runtest
+++ /dev/null
@@ -1,48 +0,0 @@
1#!/bin/sh
2
3OUT1=$TMPDIR/out1
4OUT2=$TMPDIR/out2
5OUT3=$TMPDIR/out3
6XDELTA=./xdelta
7
8while test $# -gt 1; do
9
10 FROM=$1
11 TO=$2
12
13 shift
14
15 if test -d $FROM -o -d $TO; then
16 BOGUS=what
17 else
18 echo testing $FROM $TO ...
19 $XDELTA delta -q0 $FROM $TO $OUT1
20 $XDELTA patch $OUT1 $FROM $OUT2
21 cmp $OUT2 $TO
22
23 echo testing $TO $FROM ...
24 $XDELTA delta -q0 $TO $FROM $OUT1
25 $XDELTA patch $OUT1 $TO $OUT2
26 cmp $OUT2 $FROM
27
28 echo testing $TO $TO ...
29 $XDELTA delta -q0 $TO $TO $OUT1
30 $XDELTA patch $OUT1 $TO $OUT2
31 cmp $OUT2 $TO
32
33 echo testing $FROM $TO ...
34 $XDELTA delta -q6 $FROM $TO $OUT1
35 $XDELTA patch $OUT1 $FROM $OUT2
36 cmp $OUT2 $TO
37
38 echo testing $TO $FROM ...
39 $XDELTA delta -q6 $TO $FROM $OUT1
40 $XDELTA patch $OUT1 $TO $OUT2
41 cmp $OUT2 $FROM
42
43 echo testing $TO $TO ...
44 $XDELTA delta -q6 $TO $TO $OUT1
45 $XDELTA patch $OUT1 $TO $OUT2
46 cmp $OUT2 $TO
47 fi
48done;
diff --git a/xdelta1/test/Makefile.am b/xdelta1/test/Makefile.am
deleted file mode 100644
index 9ab70bf..0000000
--- a/xdelta1/test/Makefile.am
+++ /dev/null
@@ -1,13 +0,0 @@
1
2EXTRA_DIST = xdeltatest.c README.test
3
4INCLUDES = -I$(top_srcdir)/libedsio $(GLIB_CFLAGS)
5
6noinst_PROGRAMS = xdeltatest
7
8xdeltatest_SOURCES = xdeltatest.c
9
10xdeltatest_LDADD = $(top_srcdir)/libxdelta.la \
11 $(top_srcdir)/libedsio/libedsio.la \
12 -lz \
13 $(GLIB_LIBS)
diff --git a/xdelta1/test/README.test b/xdelta1/test/README.test
deleted file mode 100644
index 11ac3b8..0000000
--- a/xdelta1/test/README.test
+++ /dev/null
@@ -1,9 +0,0 @@
1The code in this directory produces a test for Xdelta. To run it you
2have to edit the hard-coded constants at the top of the file, which
3include "cmd_data_source", which should be the name of a big file
4containing source data that the test uses to construct sample inputs.
5This allows you to test on whatever kind of data you want, but the
6synthetic edits are still hardcoded. Have a look.
7
8Of course, a better test would let you run it without any
9configuration, but this is not that test.
diff --git a/xdelta1/test/xdeltatest.c b/xdelta1/test/xdeltatest.c
deleted file mode 100644
index 773e26b..0000000
--- a/xdelta1/test/xdeltatest.c
+++ /dev/null
@@ -1,681 +0,0 @@
1/* -*- Mode: C;-*-
2 *
3 * This file is part of XDelta - A binary delta generator.
4 *
5 * Copyright (C) 1997, 1998, 2001 Josh MacDonald
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
22 *
23 * $Id: xdeltatest.c 1.7.1.1 Sat, 27 Jan 2007 17:53:47 -0800 jmacd $
24 */
25
26#include <sys/param.h>
27#include <sys/types.h>
28#include <unistd.h>
29#include "config.h"
30
31#if TIME_WITH_SYS_TIME
32# include <sys/time.h>
33# include <time.h>
34#else
35# if HAVE_SYS_TIME_H
36# include <sys/time.h>
37# else
38# include <time.h>
39# endif
40#endif
41
42#include <fcntl.h>
43#include <sys/stat.h>
44#include <sys/wait.h>
45#include <sys/resource.h>
46#include <stdio.h>
47#include <zlib.h>
48
49#include "xdelta.h"
50
51//////////////////////////////////////////////////////////////////////
52// Configure these parameters
53// @@@ Of course, a real test wouldn't require this configuration,
54// fix that!
55//////////////////////////////////////////////////////////////////////
56
57const char* cmd_data_source = "/tmp/big.1";
58guint cmd_size = 1<<20;
59
60guint cmd_warmups = 2;
61guint cmd_reps = 20;
62
63guint cmd_changes = 1000;
64guint cmd_deletion_length = 30;
65guint cmd_insertion_length = 15;
66
67//////////////////////////////////////////////////////////////////////
68//
69//////////////////////////////////////////////////////////////////////
70
71#define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0]))
72
73#define TEST_PREFIX "/tmp/xdeltatest"
74
75#define TEST_IS_GZIP 1
76#define TEST_IS_XDELTA 2
77
78typedef struct _File File;
79typedef struct _Patch Patch;
80typedef struct _TestProfile TestProfile;
81typedef struct _Instruction Instruction;
82
83struct _Instruction {
84 guint32 offset;
85 guint32 length;
86 Instruction* next;
87};
88
89struct _File
90{
91 char name[MAXPATHLEN];
92};
93
94struct _Patch
95{
96 guint8 *data;
97 guint32 length;
98};
99
100struct _TestProfile
101{
102 const char *name;
103 const char *progname;
104 int flags;
105};
106
107#undef BUFSIZ
108#define BUFSIZ (1<<24)
109
110guint8 __tmp_buffer[BUFSIZ];
111
112// Note: Of course you should be able to set all this up on the
113// command line.
114
115TestProfile cmd_profiles[] =
116{
117 { "xdelta -qn ", "../xdelta", TEST_IS_XDELTA },
118 { "diff --rcs -a", "/usr/bin/diff", 0 },
119 { "gzip ", "/bin/gzip", TEST_IS_GZIP },
120};
121
122int cmd_slevels[] = { 16, 32, 64 };
123int cmd_zlevels[] = { 0, 1, 3, 6, 9 };
124guint16 cmd_seed[3] = { 47384, 8594, 27489 };
125
126FILE* data_source_handle;
127guint data_source_length;
128File* data_source_file;
129
130long current_to_size;
131long current_from_size;
132
133double __total_time;
134off_t __dsize;
135
136void
137reset_stats ()
138{
139 __total_time = 0;
140 __dsize = -1;
141}
142
143void add_tv (GTimer *timer)
144{
145 __total_time += g_timer_elapsed (timer, NULL);
146}
147
148void
149report (TestProfile *tp, int zlevel, int slevel)
150{
151 static gboolean once = TRUE;
152
153 double t = __total_time / (double) cmd_reps;
154 double s;
155 const char *u;
156 char slevel_str[16];
157
158 if (tp->flags & TEST_IS_XDELTA)
159 {
160 sprintf (slevel_str, "%d", slevel);
161 }
162 else
163 {
164 slevel_str[0] = 0;
165 }
166
167 if (tp->flags & TEST_IS_GZIP)
168 {
169 s = __dsize / (double) current_to_size;
170 u = "total size";
171 }
172 else
173 {
174 s = __dsize / (double) (cmd_changes * cmd_insertion_length);
175 u = "insertion size";
176 }
177
178 if (once)
179 {
180 once = FALSE;
181
182 g_print ("Program\t\tzlevel\tslevel\tSeconds\tNormalized\n\t\t\t\t\tcompression\n");
183 }
184
185 g_print ("%s\t%d\t%s\t%0.3f\t%0.3f (of %s)\n", tp->name, zlevel, slevel_str, t, s, u);
186}
187
188guint32
189random_offset (guint len)
190{
191 return lrand48 () % (data_source_length - len);
192}
193
194void
195fail ()
196{
197 g_warning ("FAILURE\n");
198 abort ();
199}
200
201gboolean starts_with (const char* s, const char *start)
202{
203 return strncmp (s, start, strlen (start)) == 0;
204}
205
206Patch*
207read_patch (File *file, struct stat *sbuf)
208{
209 Patch *p = g_new0 (Patch,1);
210 FILE *f = fopen (file->name, "r");
211
212 p->length = (int)sbuf->st_size;
213
214 p->data = g_malloc (p->length);
215
216 if (! f || fread (p->data, 1, p->length, f) != p->length)
217 {
218 perror ("fread");
219 fail ();
220 }
221
222 fclose (f);
223
224 return p;
225}
226
227File*
228empty_file ()
229{
230 static gint count = 0;
231 File *file = g_new0 (File, 1);
232
233 sprintf (file->name, "%s.%d.%d", TEST_PREFIX, getpid (), count++);
234
235 return file;
236}
237
238void
239compare_files (File* fromfile, File* tofile)
240{
241 gint pos = 0;
242
243 FILE* toh;
244 FILE* fromh;
245
246 guint8 buf1[1024], buf2[1024];
247
248 toh = fopen (tofile->name, "r");
249 fromh = fopen (fromfile->name, "r");
250
251 if (!toh || !fromh)
252 fail ();
253
254 for (;;)
255 {
256 gint readf = fread (buf1, 1, 1024, fromh);
257 gint readt = fread (buf2, 1, 1024, toh);
258 gint i, m = MIN(readf, readt);
259
260 if (readf < 0 || readt < 0)
261 fail ();
262
263 for (i = 0; i < m; i += 1, pos += 1)
264 {
265 if (buf1[i] != buf2[i])
266 fail ();
267 }
268
269 if (m != 1024)
270 {
271 if (readt == readf)
272 {
273 fclose (toh);
274 fclose (fromh);
275 return;
276 }
277
278 fail ();
279 }
280 }
281}
282
283int
284write_file (File* file, Instruction* inst)
285{
286 FILE* h;
287 int ret;
288 int size = 0;
289
290 if (! (h = fopen (file->name, "w"))) {
291 perror (file->name);
292 fail ();
293 }
294
295 for (; inst; inst = inst->next)
296 {
297 g_assert (inst->length <= BUFSIZ);
298
299 if ((ret = fseek (data_source_handle, inst->offset, SEEK_SET))) {
300 perror ("fseek");
301 fail ();
302 }
303
304 if ((ret = fread (__tmp_buffer, 1, inst->length, data_source_handle)) != inst->length) {
305 perror ("fread");
306 fail ();
307 }
308
309 if ((ret = fwrite (__tmp_buffer, 1, inst->length, h)) != inst->length) {
310 perror ("fwrite");
311 fail ();
312 }
313
314 size += inst->length;
315 }
316
317 if ((ret = fclose (h))) {
318 perror ("fclose");
319 fail ();
320 }
321
322 return size;
323}
324
325Instruction*
326perform_change_rec (Instruction* inst, guint32 change_off, guint* total_len)
327{
328 if (change_off < inst->length)
329 {
330 guint32 to_delete = cmd_deletion_length;
331 guint32 avail = inst->length;
332 guint32 this_delete = MIN (to_delete, avail);
333 Instruction* new_inst;
334
335 // One delete
336 inst->length -= this_delete;
337 to_delete -= this_delete;
338
339 while (to_delete > 0 && inst->next->length < to_delete)
340 {
341 to_delete -= inst->next->length;
342 inst->next = inst->next->next;
343 }
344
345 if (to_delete > 0)
346 inst->next->offset += to_delete;
347
348 // One insert
349 new_inst = g_new0 (Instruction, 1);
350
351 new_inst->offset = random_offset (cmd_insertion_length);
352 new_inst->length = cmd_insertion_length;
353 new_inst->next = inst->next;
354 inst->next = new_inst;
355
356 (* total_len) += cmd_insertion_length - cmd_deletion_length;
357
358 return inst;
359 }
360 else
361 {
362 inst->next = perform_change_rec (inst->next, change_off - inst->length, total_len);
363 return inst;
364 }
365}
366
367Instruction*
368perform_change (Instruction* inst, guint* len)
369{
370 return perform_change_rec (inst, lrand48() % ((* len) - cmd_deletion_length), len);
371}
372
373gboolean
374xdelta_verify (TestProfile *tp, int zlevel, int slevel, File* from, File* to, File* out, File *re)
375{
376 int pid, status;
377
378 if ((pid = vfork()) < 0)
379 return FALSE;
380
381 if (pid == 0)
382 {
383 execl (tp->progname,
384 tp->progname,
385 "patch",
386 out->name,
387 from->name,
388 re->name,
389 NULL);
390 perror ("execl failed");
391 _exit (127);
392 }
393
394 if (waitpid (pid, &status, 0) != pid)
395 {
396 perror ("wait failed");
397 fail ();
398 }
399
400 // Note: program is expected to return 0, 1 meaning diff or no diff,
401 // > 1 indicates failure
402 if (! WIFEXITED (status) || WEXITSTATUS (status) > 1)
403 {
404 g_warning ("patch command failed\n");
405 fail ();
406 }
407
408 compare_files (to, re);
409
410 return TRUE;
411}
412
413gboolean
414run_command (TestProfile *tp, int zlevel, int slevel, File* from, File* to, File* out, File *re, gboolean accounting)
415{
416 int pid, status, outfd;
417 struct stat sbuf;
418 char xdelta_args[16];
419 char xdelta_args2[16];
420 char diff_gzargs[16];
421 char gzip_args[16];
422
423 GTimer *timer = g_timer_new ();
424
425 sprintf (xdelta_args, "-qn%d", zlevel);
426 sprintf (xdelta_args2, "-s%d", slevel);
427 sprintf (diff_gzargs, "wb%d", zlevel);
428 sprintf (gzip_args, "-c%d", zlevel);
429
430 unlink (out->name);
431
432 g_timer_start (timer);
433
434 if ((pid = vfork()) < 0)
435 return FALSE;
436
437 if (pid == 0)
438 {
439 if (starts_with (tp->name, "xdelta"))
440 {
441 execl (tp->progname,
442 tp->progname,
443 "delta",
444 xdelta_args,
445 xdelta_args2,
446 from->name,
447 to->name,
448 out->name,
449 NULL);
450 }
451 else
452 {
453 outfd = open (out->name, O_CREAT | O_TRUNC | O_WRONLY, 0777);
454
455 if (outfd < 0)
456 {
457 perror ("open");
458 fail ();
459 }
460
461 dup2(outfd, STDOUT_FILENO);
462
463 if (close (outfd))
464 {
465 perror ("close");
466 fail ();
467 }
468
469 if (starts_with (tp->name, "diff"))
470 execl (tp->progname,
471 tp->progname,
472 "--rcs",
473 "-a",
474 from->name,
475 to->name,
476 NULL);
477 else if (starts_with (tp->name, "gzip"))
478 execl (tp->progname,
479 tp->progname,
480 gzip_args,
481 to->name,
482 NULL);
483 else
484 abort ();
485 }
486
487 perror ("execl failed");
488 _exit (127);
489 }
490
491 if (waitpid (pid, &status, 0) != pid)
492 {
493 perror ("wait failed");
494 fail ();
495 }
496
497 // Note: program is expected to return 0, 1 meaning diff or no diff,
498 // > 1 indicates failure
499 if (! WIFEXITED (status) || WEXITSTATUS (status) > 1)
500 {
501 g_warning ("delta command failed\n");
502 fail ();
503 }
504
505 if (stat (out->name, & sbuf))
506 {
507 perror ("stat");
508 fail ();
509 }
510
511 // Do zlib compression on behalf of diff
512 if (zlevel > 0 && starts_with (tp->name, "diff"))
513 {
514 Patch *patch = read_patch (out, & sbuf);
515 gzFile *rewrite = gzopen (out->name, diff_gzargs);
516
517 if (! rewrite) fail ();
518
519 if (gzwrite (rewrite, patch->data, patch->length) == 0) { perror ("gzwrite"); fail (); }
520 if (gzclose (rewrite) != Z_OK) { perror ("gzclose"); fail (); }
521 if (stat (out->name, & sbuf)) { perror ("stat"); fail (); }
522 }
523
524 g_timer_stop (timer);
525
526 if (accounting)
527 {
528 add_tv (timer);
529 }
530
531 if (__dsize < 0)
532 {
533 __dsize = sbuf.st_size;
534
535 // Verify only once
536
537 if (starts_with (tp->name, "xdelta"))
538 {
539 if (! xdelta_verify (tp, zlevel, slevel, from, to, out, re))
540 {
541 g_warning ("verify failed");
542 fail ();
543 }
544 }
545 }
546 else
547 {
548 if (__dsize != sbuf.st_size)
549 {
550 g_warning ("%s -%d: delta command produced different size deltas: %d and %d",
551 tp->progname, zlevel, (int)__dsize, (int)sbuf.st_size);
552 fail ();
553 }
554 }
555
556 g_timer_destroy (timer);
557
558 return TRUE;
559}
560
561void
562test1 (TestProfile *test_profile,
563 File *from_file,
564 File *to_file,
565 File *out_file,
566 File *re_file)
567{
568 int ret;
569 guint i, change, current_size = cmd_size;
570 guint end_size = (cmd_changes * cmd_insertion_length) + cmd_size;
571 Instruction* inst;
572 struct stat sbuf;
573 int zlevel_i, slevel_i;
574
575 seed48 (cmd_seed);
576
577 if ((ret = stat (cmd_data_source, & sbuf)))
578 {
579 perror (cmd_data_source);
580 fail ();
581 }
582
583 if (! (data_source_handle = fopen (cmd_data_source, "r")))
584 {
585 perror (cmd_data_source);
586 fail ();
587 }
588
589 data_source_length = sbuf.st_size;
590
591 /* arbitrary checks */
592 if (data_source_length < (1.5 * end_size))
593 g_warning ("data source should be longer\n");
594
595 if ((cmd_changes * cmd_deletion_length) > cmd_size)
596 {
597 g_warning ("no copies are expected\n");
598 fail ();
599 }
600
601 inst = g_new0 (Instruction, 1);
602
603 inst->offset = random_offset (cmd_size);
604 inst->length = cmd_size;
605
606 current_from_size = write_file (from_file, inst);
607
608 for (change = 0; change < cmd_changes; change += 1)
609 inst = perform_change (inst, & current_size);
610
611 current_to_size = write_file (to_file, inst);
612
613 for (slevel_i = 0; slevel_i < ARRAY_LENGTH(cmd_slevels); slevel_i += 1)
614 {
615 int slevel = cmd_slevels[slevel_i];
616
617 if ((test_profile->flags & TEST_IS_XDELTA) == 0 && slevel_i != 0)
618 {
619 continue;
620 }
621
622 for (zlevel_i = 0; zlevel_i < ARRAY_LENGTH(cmd_zlevels); zlevel_i += 1)
623 {
624 int zlevel = cmd_zlevels[zlevel_i];
625
626 if (test_profile->flags & TEST_IS_GZIP)
627 {
628 if (zlevel != 1 && zlevel != 9)
629 continue;
630 }
631
632 reset_stats ();
633
634 for (i = 0; i < cmd_warmups + cmd_reps; i += 1)
635 {
636 if (! run_command (test_profile,
637 zlevel,
638 slevel,
639 from_file,
640 to_file,
641 out_file,
642 re_file,
643 (i >= cmd_warmups) /* true => accounting */))
644 {
645 fail ();
646 }
647 }
648
649 report (test_profile, zlevel, slevel);
650 }
651
652 g_print ("\n");
653 }
654}
655
656int
657main (gint argc, gchar** argv)
658{
659 int profile_i;
660
661 File *from_file;
662 File *to_file;
663 File *out_file;
664 File *re_file;
665
666 system ("rm -rf " TEST_PREFIX "*");
667
668 from_file = empty_file ();
669 to_file = empty_file ();
670 out_file = empty_file ();
671 re_file = empty_file ();
672
673 for (profile_i = 0; profile_i < ARRAY_LENGTH(cmd_profiles); profile_i += 1)
674 {
675 test1 (& cmd_profiles[profile_i], from_file, to_file, out_file, re_file);
676
677 system ("rm -rf " TEST_PREFIX "*");
678 }
679
680 return 0;
681}
diff --git a/xdelta1/xd.ser b/xdelta1/xd.ser
deleted file mode 100644
index 7dd91c6..0000000
--- a/xdelta1/xd.ser
+++ /dev/null
@@ -1,138 +0,0 @@
1;; -*- Emacs-Lisp -*-
2
3(defmodule xd 3 "xdelta.h" nil)
4
5(defimport "libedsio/edsio.ser")
6
7(defsertype XdeltaChecksum 1
8 ((high uint16)
9 (low uint16)
10 )
11 ()
12 )
13
14(defsertype XdeltaIndex 2
15 ((file_len uint)
16 (file_md5 (bytes 16))
17 (index (array XdeltaChecksum))
18 )
19 ()
20 )
21
22(defsertype XdeltaSourceInfo 3
23 ((name string)
24 (md5 (bytes 16))
25 (len uint)
26 (isdata boolean) ;;; if true, then its source index is 0 and it is the data segment
27 (sequential boolean) ;;; if true, then offset field is not persistent, but instead
28 ;;; recomputed when loaded as the sum of
29 ;;; previous instruction's length fields, to
30 ;;; indicate a sequential read
31 )
32 ("guint32 position"
33 "guint32 copies"
34 "guint32 copy_length"
35 "FileHandle *in")
36 )
37
38(defsertype XdeltaControl 7
39 ((to_md5 (bytes 16))
40 (to_len uint)
41 (has_data boolean)
42 (source_info (array (ptr XdeltaSourceInfo)))
43 (inst (array XdeltaInstruction))
44 )
45 ("GArray *inst_array"
46 "GPtrArray *source_info_array"
47 )
48 )
49
50(defsertype XdeltaInstruction 8
51 ((index uint)
52 (offset uint)
53 (length uint)
54 )
55 ("guint32 output_start")
56 )
57
58;; rsync stuff
59
60(defsertype RsyncIndexElt 9
61 ((md5 (bytes 16))
62 (cksum XdeltaChecksum)
63 )
64 ("SerialRsyncIndexElt* next"
65 "gint match_offset")
66 )
67
68(defsertype RsyncIndex 10
69 ((seg_len uint)
70 (file_len uint)
71 (file_md5 (bytes 16))
72 (index (array RsyncIndexElt))
73 )
74 ("SerialRsyncIndexElt** table"
75 "guint table_size")
76 )
77
78;; backward compat, these are the 1.0 defs
79
80(defsertype Version0SourceInfo 4
81 ((md5 (bytes 16))
82 (real_md5 (bytes 16))
83 (length uint)
84 )
85 ()
86 )
87
88(defsertype Version0Control 5
89 ((normalized boolean)
90 (data_len uint)
91 (to_info Version0SourceInfo)
92 (source_info (array (ptr Version0SourceInfo)))
93 (inst (array Version0Instruction))
94 )
95 ("GArray *inst_array"
96 "GPtrArray *source_info_array"
97 )
98 )
99
100(defsertype Version0Instruction 6
101 ((offset uint)
102 (length uint)
103 )
104 ("guint8 type" ;; these two fields get packed into length
105 "guint8 index"
106 )
107 )
108
109;; events
110
111(defetype handle "FileHandle*")
112
113(defevent TooFewSources Error () ()
114 "Too few input sources")
115
116(defevent TooManySources Error () ()
117 "Too many input sources")
118
119(defevent OutOfRangeSourceIndex Error ((index int)) ()
120 "Instruction references out-of-range source index: ${INDEX}")
121
122(defevent InvalidControl Error () ()
123 "Delta control is corrupt")
124
125(defevent InvalidRsyncCache Error () ()
126 "The rsync checksum cache is corrupt")
127
128(defevent IncompatibleDelta Error () ()
129 "The delta was not produced according by the `xdelta delta' command")
130
131(defevent StreamChecksumFailed Error ((stream handle) (expected string) (received string)) ()
132 "${STREAM}: Checksum validation failed, expected: ${EXPECTED}, received: ${RECEIVED}")
133
134(defevent StreamLengthFailed Error ((stream handle) (expected int) (received int)) ()
135 "${STREAM}: Length validation failed, expected: ${EXPECTED}, received: ${RECEIVED}")
136
137(defevent BackwardCompatibilityMode Information ((version string)) ()
138 "Reading a version ${VERSION} delta control")
diff --git a/xdelta1/xdapply.c b/xdelta1/xdapply.c
deleted file mode 100644
index cc492d2..0000000
--- a/xdelta1/xdapply.c
+++ /dev/null
@@ -1,91 +0,0 @@
1/* -*- Mode: C;-*-
2 *
3 * This file is part of XDelta - A binary delta generator.
4 *
5 * Copyright (C) 1997, 1998, 1999 Josh MacDonald
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
22 *
23 * $Id: xdapply.c 1.1 Thu, 01 Apr 1999 23:29:11 -0800 jmacd $
24 */
25
26#include <string.h>
27#include <stdlib.h>
28
29#include "xdelta.h"
30#include "xdeltapriv.h"
31
32/* This code used to be more general, but implemented a very
33 * inefficient algorithm. It is sufficient (and efficient) for the
34 * special case below, though, so I'm leaving it. */
35static gboolean
36xdp_copy_delta_region (XdeltaControl *cont,
37 XdeltaOutStream *output_stream)
38{
39 gint i, l = cont->inst_len;
40 guint save_written = 0;
41
42 for (i = 0; i < l; i += 1)
43 {
44 const XdeltaInstruction *inst = cont->inst + i;
45 XdeltaSourceInfo* info;
46
47 if (inst->index >= cont->source_info_len)
48 {
49 xd_generate_int_event (EC_XdOutOfRangeSourceIndex, inst->index);
50 return FALSE;
51 }
52
53 info = cont->source_info[inst->index];
54
55 if (! handle_copy (info->in, output_stream, inst->offset, inst->length))
56 return FALSE;
57
58 save_written += inst->length;
59 }
60
61 return TRUE;
62}
63
64gboolean
65xdp_apply_delta (XdeltaControl *cont,
66 XdeltaOutStream *res)
67{
68 if (! xdp_copy_delta_region (cont, res))
69 return FALSE;
70
71 if (! handle_close (res, 0))
72 return FALSE;
73
74 if (! check_stream_integrity (res, cont->to_md5, cont->to_len))
75 {
76 int i;
77
78 /* to better report errors, check if the inputs were invalid now
79 */
80 for (i = 0; i < cont->source_info_len; i += 1)
81 {
82 check_stream_integrity (cont->source_info[i]->in,
83 cont->source_info[i]->md5,
84 cont->source_info[i]->len);
85 }
86
87 return FALSE;
88 }
89
90 return TRUE;
91}
diff --git a/xdelta1/xdelta-0.13.README b/xdelta1/xdelta-0.13.README
deleted file mode 100644
index f928f66..0000000
--- a/xdelta1/xdelta-0.13.README
+++ /dev/null
@@ -1,311 +0,0 @@
1
2I have placed version 0.13 of XDELTA, new delta generator and
3prototype RCS-replacement program at:
4
5 ftp://www.xcf.berkeley.edu/pub/jmacd/xdelta-0.13.tar.gz
6
7======
8
9Hereafter, the algorithm and program are described. A delta algorithm
10operates on two files, a FROM file and a TO file. It computes enough
11informnation to reconstruct the TO file from the FROM file. So the
12delta and it's inverse, patch, work as follows:
13
14P = delta (FROM, TO)
15TO = patch (FROM, P)
16
17The delta generator portion of this program is a delta algorithm which
18searches for substring matches between the files and then outputs
19instructions to reconstruct the new file from the old file. It
20produces a set of copy/insert instructions that tell how to
21reconstruct the file as a sequence of copies from the FROM file and
22inserts from the delta itself. In this regard, the program is much
23closer to a compression program than to a diff program. However, the
24delta is not "compressed", in that the delta's entropy H(P) will be
25very similar to the entropy of the portions of the TO file not found
26within the FROM file. The delta will compress just as well as the TO
27file will. This is a fundamentally different method of computing
28deltas than in the traditional "diff" program. The diff program and
29it's variants use a least-common-subsequence (LCS) algorithm to find a
30list of inserts and deletes that will modify the FROM file into the TO
31file. LCS is more expensive to compute and is sometimes more useful,
32especially to the human reader. Since LCS is a fairly expensive
33algorithm, diff programs usually divide the input files into
34newline-separated "atoms" before computing a delta. This is a fine
35approximation for text files, but not binary files.
36
37I propose this delta generator as a replacement for "diff" in
38applications where the insert/delete delta is not required. Since the
39copy/insert delta is easier to compute, it does not have to make the
40reduction in input size by breaking the file into lines. The delta
41generator works well on binary files.
42
43The next question is whether it is actually desirable to compute
44deltas between binary files. The answer is certainly yes, even though
45some binary file formats will not have a great degree of similarity
46between versions which were generated between minor modifications to
47their sources. First, I have evidence that some file formats (notably
48FrameMaker documents) work very well. Machine-dependant object files
49and executables don't work very well, but it is still worth doing.
50The reason it is still worthwhile is that compression takes longer
51than finding these deltas, so any space savings the delta generator
52produces it very likely to reduce the total archival time. Even if
53the delta generator saves no space, the total time well end up less
54than twice the time of compression. I will include some measurements
55at the end of this writing.
56
57With the delta generator as a building block, I have written a
58replacement for RCS. It does not have all the user-level features
59someone would want in RCS, but these things only get in the way when
60the code is used by higher level version control programs such as
61PRCS. For now, the prototype supports the following actions:
62
63register create an empty version file
64checkin create a new version
65checkout extract an old version
66
67The program departs from the RCS model in that it does not branch it's
68versions. The reason for doing this is to solve several problems with
69RCS (aside from it's use of diff which is solved by using my delta
70generator).
71
721. Development very often ends up off the "main trunk" of the RCS
73file, which causes an O(N) extract, where N deltas must be applied to
74the head of the trunk before getting the desired file. Once this
75occurs, things get worse and worse. Of course, it is possible to
76remedy the situation by checking it in once on the trunk, but that
77defeats the purpose of branching, because you lose the information
78about branch of development you are on. Further, the notion of
79branching individual files conflicts with the model presented by
80higher level version control programs such as PRCS, which would rather
81not have to go to extra trouble to insure that development does not
82end up off the trunk.
83
842. Deltas are never used more than once in a particular version
85history, even if they contain the same data as another delta.
86
87Conceptually, to get rid of RCS-like branching and retain the "deltas
88are computed between a file and its parent", the xdelta version
89control library computes a reverse delta between the new file and the
90entire version file. The most recently checked in version is always
91the "head", in RCS terms. It is always the quickest and easiest to
92extract. For a repository with N versions, version I requires the
93application of (N-I) deltas, regardless of how the set of versions are
94related.
95
96Each delta contains a set of instructions and all data which was
97originally part of a file version but missing in the FROM file. This
98data is represented without compression or modification. As a result,
99each delta may be used as an input for finding future deltas just as a
100regular file may be.
101
102Several equations describe the process, first some notation:
103
104 V0 is the version file with 1 version
105 V1 is the version file with 2 versions,
106 ...
107 VN is the version file with N+1 versions
108
109 F0 is the 1st file checked in, upon checkin V0 is produced
110 F1 is the 2nd file checked in, upon checkin V1 is produced
111 ...
112 FN is the Nth file checked in, upon checkin VN is produced
113
114 D0 is the 1st delta produced, upon checkin of F1
115 D1 is the 2nd delta produced, upon checkin of F2
116 ...
117 DN is the Nth delta produced, upon checkin of FN+1
118
119Checkin goes as follows:
120
121 V0 <- F0
122
123 D0 <- delta (F1, F0)
124 V1 <- F1 + D0
125
126 D1 <- delta (F2 + D0, F1)
127 V2 <- F2 + D1 + D0
128
129 D2 <- delta (F3 + D1 + D0, F2)
130 V3 <- F3 + D2 + D1 + D0
131
132an so on. To checkout:
133
134 F3 is immediate
135 F2 <- patch (F3 + D1 + D0, D2)
136 F1 <- patch (F2 + D0, D1)
137 F0 <- patch (F1, D0)
138
139Now I will describe why this is just as good as branching, even though
140the branches do not affect which files are used for computing deltas,
141and why it is just as good as the RCS model.
142
143Suppose the we have a sequence of checkins with RCS version numbers
144and their sequence numbers:
145
146F0: 1.1
147F1: 1.2
148F2: 1.3
149F3: 1.1.1.1
150F4: 1.1.1.2
151F5: 1.1.1.3
152F6: 1.4
153F7: 1.5
154
155Of interest are the 4th checkin, from 1.3 to 1.1.1.1, and the 7th
156checkin, from 1.1.1.3 to 1.4. I will now use the '-' sign to denote
157the taking of a delta and '+' for patch. Thus, delta(A,B) is
158equivalent to B-A, and patch(A,xdelta(A,B)) is equivalent to A+(B-A),
159or B, as it should be. In the above sequence of checkins, these
160deltas are produced:
161
162D0=F0-F1
163D1=F1-F2-D0
164D2=F2-F3-D1-D0
165D3=F3-F4-D2-D1-D0
166D4=F4-F5-D3-D2-D1-D0
167D5=F5-F6-D4-D3-D2-D1-D0
168D6=F6-F7-D5-D4-D3-D2-D1-D0
169
170The checkin of F3 produces D2. The concern is whether any deletions
171between 1.1 and 1.3 have to be inserted into D2. They have not,
172because any deletions between 1.1 and 1.3 appear in D0 and D1. Thus,
173using D0, D1, and F3 as an input for computing D2 achieves the desired
174results: the deletion is not reflected twice in separate deltas.
175
176The properties of this version format differ from the RCS format. It
177ensures that recently checked-in versions are quick to check out, no
178matter where in the "tree" they occur. One potential problem with
179this formulation is that according to the formulae above, the ammount
180of memory and computation required for checking in each new version
181grows with the number of previous versions. To prevent this it only
182uses up to some limiting value (currently set at 10) of previous
183deltas in computing new deltas. This means that deletions on a branch
184over 10 checkins old will be duplicated on a checkin. Another
185property is that to delete a version all older versions must first be
186deleted or off-line processing may be done to reconstruct the delta
187log with the version removed (an expensive but not time-critical
188operation). It also lends itself to keeping windowed histories, such
189as "only keep the last 20 revisions, anything earlier than that may be
190thrown away".
191
192---
193
194The current prototype implementation is complete. The program,
195'xdelta', has a command syntax similar to PRCS:
196
197xdelta COMMAND [OPTIONS] ARG1 ARG2 ...
198
199There are 5 commands:
200
201 register Create a versionfile
202 checkin Checkin a new version
203 checkout Checkout a version (latest or -r VERSION)
204 info Show information on a version (all or -r VERSION)
205 delta Produce a delta from ARG1 to ARG2 producing ARG3
206 patch Patch file ARG1 with ARG2 producing ARG3
207
208The -r option specifies a version (the latest version is always the
209default). Versions are sequentially numbered. The file itself is a
210GNU DBM database which stores the deltas and latest version. The file
211format is subject to change as I look for storage methods that are
212portable to Windows (otherwise, the delta generator has already been
213tested on Windows).
214
215The DELTA and PATCH commands are unrelated to the rest, and simply
216serve to generate deltas (and could be used as replacements for "diff"
217and "patch"). All operations are verified with MD5 checksums, which
218are saved for each version in the version file and the FROM and TO
219files when generating and applying deltas.
220
221---
222
223Some timing comparisons (remember all times include MD5 computations)
224on a 300MHz Alpha:
225
226Two kernels:
227
228 7875136 /genvmunix
229 6677320 /vmunix
230
231And the times to compress and delta them:
232
233 time(s) size(bytes)
234
235xdelta delta /genvmunix /vmunix patch: 10.1 4338029
236gzip --best /genvmunix: 34.0 3413963
237gzip --best /vmunix: 63.7 2501766
238gzip --best patch: 51.9 1531163
239
240(I'm not sure why there's such a variation in gzip times--it was
241repeatable.)
242
243xdelta produces a patch which is 4338029 bytes, approximately 2.6
244megabytes smaller than its TO file. The total space required for
245saving the two kernels compressed is 5915729 bytes, produced in 97.7
246seconds. The total space for storing /genvmunix and the delta
247compressed is 4945126 bytes, produced in 96.0 seconds. Using the
248delta saved approximately one megabyte and two seconds.
249
250---
251
252All the files in PRCS 1.0.0 and 1.2.0 concatenated (files ordered
253lexigraphically):
254
255 1678837 /tmp/1.0.0
256 2021819 /tmp/1.2.0
257
258 time(s) space(bytes)
259
260xdelta delta /tmp/1.0.0 /tmp/1.2.0 /tmp/patch: 1.5 695893
261gdiff -a --rcs /tmp/1.0.0 /tmp/1.2.0 /tmp/patch: 3.7 1524705
262
263Even though both files were completely text, gdiff missed a lot of
264similar regions because a line had been partially modified. Xdelta
265performs better in both dimensions.
266
267---
268
269All the .c and .h files in GNU gcc 2.7.2 and 2.7.2.3 concatenated (files
270ordered lexigraphically). These files are highly similar:
271
272 15590954 /tmp/2.7.2
273 15599644 /tmp/2.7.2.3
274 time(s) space(bytes)
275
276xdelta delta /tmp/2.7.2 /tmp/2.7.2.3 /tmp/patch: 7.3 11922
277gdiff -a --rcs /tmp/2.7.2 /tmp/2.7.2.3: 4.8 19477
278
279Here xdelta takes a about 50% longer and produces a slightly smaller
280diff. I think the improved performance in the other two examples
281makes xdelta an all around winner.
282
283---
284
285A note on FrameMaker files, which I happen to know a fair bit about.
286Even making radical modifications to a Frame+SGML document leaves much
287of its content unchanged, due to the fact that the EDD and various
288catalogs do not change. When only minimal modifications are performed
289
290Take a 24 page document, chapter 15 of the SGML developers guide for
291version 5.5. I replaced 38 occurances of "document" with
292"abcdefghijklmnop" and added the source of this README from here up at
293the end, making it 33 pages.
294
295 250880 graphics.before.fm
296 272384 graphics.after.fm
297
298The document grew by about 22 kbytes. The patch 32780 bytes. The
299same diff generated by GNU diff is 101097 bytes. Clearly, Frame
300documents are very good for binary version control.
301
302---
303
304I also have evidence that the program works well on uncompressed image
305formats such as the GIMP's XCF file format.
306
307This program will be the basis of PRCS version 2, which will support
308client/server distributed version control.
309
310Please send any comments, questions, thoughts, or interest to me,
311jmacd@cs.berkeley.edu.
diff --git a/xdelta1/xdelta-1.1.2.tar.gz b/xdelta1/xdelta-1.1.2.tar.gz
deleted file mode 100644
index 2fd1f74..0000000
--- a/xdelta1/xdelta-1.1.2.tar.gz
+++ /dev/null
Binary files differ
diff --git a/xdelta1/xdelta-1.1.3.tar.gz b/xdelta1/xdelta-1.1.3.tar.gz
deleted file mode 100644
index 2ded9e6..0000000
--- a/xdelta1/xdelta-1.1.3.tar.gz
+++ /dev/null
Binary files differ
diff --git a/xdelta1/xdelta-config.in b/xdelta1/xdelta-config.in
deleted file mode 100644
index 5c5056b..0000000
--- a/xdelta1/xdelta-config.in
+++ /dev/null
@@ -1,115 +0,0 @@
1#!/bin/sh
2
3glib_libs="@GLIB_LIBS@"
4glib_cflags="@GLIB_CFLAGS@"
5
6prefix=@prefix@
7exec_prefix=@exec_prefix@
8exec_prefix_set=no
9
10usage()
11{
12 cat <<EOF
13Usage: xdelta-config [OPTIONS] [LIBRARIES]
14Options:
15 [--prefix[=DIR]]
16 [--exec-prefix[=DIR]]
17 [--version]
18 [--libs]
19 [--cflags]
20Libraries:
21 xdelta
22EOF
23 exit $1
24}
25
26if test $# -eq 0; then
27 usage 1 1>&2
28fi
29
30lib_xdelta=yes
31
32while test $# -gt 0; do
33 case "$1" in
34 -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
35 *) optarg= ;;
36 esac
37
38 case $1 in
39 --prefix=*)
40 prefix=$optarg
41 if test $exec_prefix_set = no ; then
42 exec_prefix=$optarg
43 fi
44 ;;
45 --prefix)
46 echo_prefix=yes
47 ;;
48 --exec-prefix=*)
49 exec_prefix=$optarg
50 exec_prefix_set=yes
51 ;;
52 --exec-prefix)
53 echo_exec_prefix=yes
54 ;;
55 --version)
56# $Format: " echo $ReleaseVersion$" $ */
57 echo 1.1.4
58 exit 0
59 ;;
60 --cflags)
61 echo_cflags=yes
62 ;;
63 --libs)
64 echo_libs=yes
65 ;;
66 xdelta)
67 lib_xdelta=yes
68 ;;
69 *)
70 usage 1 1>&2
71 ;;
72 esac
73 shift
74done
75
76if test "$echo_prefix" = "yes"; then
77 echo $prefix
78fi
79
80if test "$echo_exec_prefix" = "yes"; then
81 echo $exec_prefix
82fi
83
84if test "$echo_cflags" = "yes"; then
85 if test @includedir@ != /usr/include ; then
86 includes=-I@includedir@
87 for i in $glib_cflags ; do
88 if test $i = -I@includedir@ ; then
89 includes=""
90 fi
91 done
92 fi
93 echo $includes $glib_cflags
94fi
95
96if test "$echo_libs" = "yes"; then
97 libdirs=-L@libdir@
98 libsp=""
99 if test "$lib_xdelta" = "yes"; then
100 my_glib_libs=
101 for i in $glib_libs ; do
102 if test $i != -L@libdir@ ; then
103 if test -z "$my_glib_libs" ; then
104 my_glib_libs="$i"
105 else
106 my_glib_libs="$my_glib_libs $i"
107 fi
108 fi
109 done
110
111 libsp="$libsp -lxdelta -ledsio $my_glib_libs"
112 fi
113
114 echo $libdirs $libsp
115fi
diff --git a/xdelta1/xdelta.c b/xdelta1/xdelta.c
deleted file mode 100644
index 890643d..0000000
--- a/xdelta1/xdelta.c
+++ /dev/null
@@ -1,1541 +0,0 @@
1/* -*- Mode: C;-*-
2 *
3 * This file is part of XDelta - A binary delta generator.
4 *
5 * Copyright (C) 1997, 1998, 1999, 2001 Josh MacDonald
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
22 *
23 * $Id: xdelta.c 1.4.1.50.1.3 Sun, 24 Feb 2002 11:30:34 -0800 jmacd $
24 */
25
26#define G_DISABLE_ASSERT
27
28#include <string.h>
29#include <stdlib.h>
30#include <ctype.h>
31
32#include "xdelta.h"
33#include "xdeltapriv.h"
34
35/* $Format: "const guint xdelta_major_version = $ReleaseMajorVersion$;" $ */
36const guint xdelta_major_version = 1;
37/* $Format: "const guint xdelta_minor_version = $ReleaseMinorVersion$;" $ */
38const guint xdelta_minor_version = 1;
39/* $Format: "const guint xdelta_micro_version = $ReleaseMicroVersion$;" $ */
40const guint xdelta_micro_version = 4;
41
42/* Control functions.
43 */
44
45static XdeltaControl* control_version_0 (SerialVersion0Control* cont) ;
46static void control_copy (XdeltaControl* cont, XdeltaSource* src, guint from, guint to);
47static gboolean control_add_info (XdeltaControl* cont, XdeltaSource* src, const guint8* md5, guint len);
48
49#ifndef XDELTA_HARDCODE_SIZE
50int QUERY_SIZE = 0;
51int QUERY_SIZE_POW = 0;
52int QUERY_SIZE_MASK = 0;
53#endif
54
55int xdp_set_query_size_pow (int size_pow)
56{
57#ifdef XDELTA_HARDCODE_SIZE
58 return XDP_QUERY_HARDCODED;
59#else
60
61 int x = 1;
62 int size_log = 0;
63
64 for (; x != 0; x <<= 1, size_log += 1)
65 {
66 if (x == size_pow)
67 goto good;
68 }
69
70 return XDP_QUERY_POW2;
71
72 good:
73
74 QUERY_SIZE = size_log;
75 QUERY_SIZE_POW = size_pow;
76 QUERY_SIZE_MASK = size_pow-1;
77
78 return 0;
79
80#endif
81}
82
83int
84xdp_blocksize ()
85{
86 if (QUERY_SIZE == 0)
87 {
88 xdp_set_query_size_pow (1<<QUERY_SIZE_DEFAULT);
89 }
90
91 return QUERY_SIZE_POW;
92}
93
94const char*
95xdp_errno (int errval)
96{
97 switch (errval)
98 {
99 case XDP_QUERY_HARDCODED:
100 return "query size hardcoded";
101 case XDP_QUERY_POW2:
102 return "query size must be a power of 2";
103 }
104
105 return g_strerror (errval);
106}
107
108const guint16 single_hash[256] =
109{
110 /* Random numbers generated using SLIB's pseudo-random number
111 * generator. */
112 0xbcd1, 0xbb65, 0x42c2, 0xdffe, 0x9666, 0x431b, 0x8504, 0xeb46,
113 0x6379, 0xd460, 0xcf14, 0x53cf, 0xdb51, 0xdb08, 0x12c8, 0xf602,
114 0xe766, 0x2394, 0x250d, 0xdcbb, 0xa678, 0x02af, 0xa5c6, 0x7ea6,
115 0xb645, 0xcb4d, 0xc44b, 0xe5dc, 0x9fe6, 0x5b5c, 0x35f5, 0x701a,
116 0x220f, 0x6c38, 0x1a56, 0x4ca3, 0xffc6, 0xb152, 0x8d61, 0x7a58,
117 0x9025, 0x8b3d, 0xbf0f, 0x95a3, 0xe5f4, 0xc127, 0x3bed, 0x320b,
118 0xb7f3, 0x6054, 0x333c, 0xd383, 0x8154, 0x5242, 0x4e0d, 0x0a94,
119 0x7028, 0x8689, 0x3a22, 0x0980, 0x1847, 0xb0f1, 0x9b5c, 0x4176,
120 0xb858, 0xd542, 0x1f6c, 0x2497, 0x6a5a, 0x9fa9, 0x8c5a, 0x7743,
121 0xa8a9, 0x9a02, 0x4918, 0x438c, 0xc388, 0x9e2b, 0x4cad, 0x01b6,
122 0xab19, 0xf777, 0x365f, 0x1eb2, 0x091e, 0x7bf8, 0x7a8e, 0x5227,
123 0xeab1, 0x2074, 0x4523, 0xe781, 0x01a3, 0x163d, 0x3b2e, 0x287d,
124 0x5e7f, 0xa063, 0xb134, 0x8fae, 0x5e8e, 0xb7b7, 0x4548, 0x1f5a,
125 0xfa56, 0x7a24, 0x900f, 0x42dc, 0xcc69, 0x02a0, 0x0b22, 0xdb31,
126 0x71fe, 0x0c7d, 0x1732, 0x1159, 0xcb09, 0xe1d2, 0x1351, 0x52e9,
127 0xf536, 0x5a4f, 0xc316, 0x6bf9, 0x8994, 0xb774, 0x5f3e, 0xf6d6,
128 0x3a61, 0xf82c, 0xcc22, 0x9d06, 0x299c, 0x09e5, 0x1eec, 0x514f,
129 0x8d53, 0xa650, 0x5c6e, 0xc577, 0x7958, 0x71ac, 0x8916, 0x9b4f,
130 0x2c09, 0x5211, 0xf6d8, 0xcaaa, 0xf7ef, 0x287f, 0x7a94, 0xab49,
131 0xfa2c, 0x7222, 0xe457, 0xd71a, 0x00c3, 0x1a76, 0xe98c, 0xc037,
132 0x8208, 0x5c2d, 0xdfda, 0xe5f5, 0x0b45, 0x15ce, 0x8a7e, 0xfcad,
133 0xaa2d, 0x4b5c, 0xd42e, 0xb251, 0x907e, 0x9a47, 0xc9a6, 0xd93f,
134 0x085e, 0x35ce, 0xa153, 0x7e7b, 0x9f0b, 0x25aa, 0x5d9f, 0xc04d,
135 0x8a0e, 0x2875, 0x4a1c, 0x295f, 0x1393, 0xf760, 0x9178, 0x0f5b,
136 0xfa7d, 0x83b4, 0x2082, 0x721d, 0x6462, 0x0368, 0x67e2, 0x8624,
137 0x194d, 0x22f6, 0x78fb, 0x6791, 0xb238, 0xb332, 0x7276, 0xf272,
138 0x47ec, 0x4504, 0xa961, 0x9fc8, 0x3fdc, 0xb413, 0x007a, 0x0806,
139 0x7458, 0x95c6, 0xccaa, 0x18d6, 0xe2ae, 0x1b06, 0xf3f6, 0x5050,
140 0xc8e8, 0xf4ac, 0xc04c, 0xf41c, 0x992f, 0xae44, 0x5f1b, 0x1113,
141 0x1738, 0xd9a8, 0x19ea, 0x2d33, 0x9698, 0x2fe9, 0x323f, 0xcde2,
142 0x6d71, 0xe37d, 0xb697, 0x2c4f, 0x4373, 0x9102, 0x075d, 0x8e25,
143 0x1672, 0xec28, 0x6acb, 0x86cc, 0x186e, 0x9414, 0xd674, 0xd1a5
144};
145
146/* Compute the hash of length len for buf, a single byte array of
147 * values, by first indexing the random array.
148 */
149
150static void
151init_query_checksum (const guint8 *buf, XdeltaChecksum *cksum)
152{
153 gint i = QUERY_SIZE_POW;
154 guint16 low = 0;
155 guint16 high = 0;
156
157 for (; i != 0; i -= 1)
158 {
159 low += CHEW(*buf++);
160 high += low;
161 }
162
163 cksum->low = low;
164 cksum->high = high;
165}
166
167/* Generate checksums
168 */
169
170static gboolean
171generate_checksums (XdeltaStream *stream,
172 XdeltaSource *source)
173{
174 gint total_checksums = handle_length (stream) / QUERY_SIZE_POW;
175 gint checksum_index = 0;
176 XdeltaChecksum cksum;
177 XdeltaChecksum *result;
178 const guint8* segment = NULL, *segment_pointer;
179 gint segment_len, orig_segment_len;
180 guint segment_page = 0;
181 guint pages;
182
183#ifdef DEBUG_CKSUM
184 g_print ("Total base checksums: %d\n", total_checksums);
185#endif
186
187 source->ck_count = total_checksums;
188
189 if (total_checksums == 0)
190 return TRUE;
191
192 /* This is the in-core FROM checksum table. */
193 result = g_new (XdeltaChecksum, total_checksums);
194 source->cksums = result;
195
196 for (pages = handle_pages (stream); segment_page <= pages; segment_page += 1)
197 {
198 segment_len = handle_map_page (stream, segment_page, &segment);
199
200 if (segment_len < 0)
201 return FALSE;
202
203 orig_segment_len = segment_len;
204
205 segment_len >>= QUERY_SIZE;
206
207 for (segment_pointer = segment;
208 segment_len != 0;
209 segment_len -= 1, segment_pointer += QUERY_SIZE_POW)
210 {
211 /* note: cheating at the boundaries */
212 init_query_checksum (segment_pointer, &cksum);
213
214#ifdef DEBUG_CKSUM
215 g_print ("New cksum %04x %04x indices %d-%d\n",
216 cksum.low, cksum.high,
217 checksum_index * QUERY_SIZE_POW, (checksum_index * QUERY_SIZE_POW) + QUERY_SIZE_POW - 1);
218#endif
219
220 result[checksum_index++] = cksum;
221 }
222
223 if (! handle_unmap_page (stream, segment_page, &segment))
224 return FALSE;
225 }
226
227 return TRUE;
228}
229
230/* $Format: "#define XDELTA_REQUIRED_VERSION \"$ReleaseMajorVersion$.$ReleaseMinorVersion$.\"" $ */
231#define XDELTA_REQUIRED_VERSION "1.1."
232
233XdeltaGenerator*
234__xdp_generator_new (const char* version)
235{
236 XdeltaGenerator* xg;
237
238 if (strncmp (version, XDELTA_REQUIRED_VERSION, strlen (XDELTA_REQUIRED_VERSION)) != 0)
239 g_error ("XDelta library version mismatched, compiled for %s, running %s\n", version, XDELTA_VERSION);
240
241 xg = g_new0 (XdeltaGenerator, 1);
242
243 xg->sources = g_ptr_array_new ();
244
245 xg->data_source = g_new0 (XdeltaSource, 1);
246 xg->data_source->name = "(patch data)";
247
248 g_ptr_array_add (xg->sources, xg->data_source);
249
250 return xg;
251}
252
253void
254xdp_generator_free (XdeltaGenerator *gen)
255{
256 int i;
257
258 for (i = 0; i < gen->sources->len; i += 1)
259 xdp_source_free (gen->sources->pdata[i]);
260
261 g_ptr_array_free (gen->sources, TRUE);
262 g_free ((void*) gen->table);
263 g_free (gen);
264}
265
266void
267init_pos (XdeltaStream* str, XdeltaPos* pos)
268{
269 g_assert (str);
270
271 memset (pos, 0, sizeof (*pos));
272
273 pos->page_size = handle_pagesize (str);
274}
275
276gboolean
277check_stream_integrity (XdeltaStream* str, const guint8* md5, guint len)
278{
279 const guint8* act_md5;
280
281 if (len != handle_length (str))
282 {
283 xd_generate_handleintint_event (EC_XdStreamLengthFailed, str, len, handle_length (str));
284 return FALSE;
285 }
286
287 act_md5 = handle_checksum_md5 (str);
288
289 if (! act_md5)
290 return FALSE;
291
292 if (memcmp (md5, act_md5, 16) != 0)
293 {
294 char exp[33], rec[33];
295
296 edsio_md5_to_string (md5, exp);
297 edsio_md5_to_string (act_md5, rec);
298
299 xd_generate_handlestringstring_event (EC_XdStreamChecksumFailed, str, exp, rec);
300 g_free ((void*) act_md5);
301 return FALSE;
302 }
303
304 g_free ((void*) act_md5);
305
306 return TRUE;
307}
308
309static gboolean
310xdp_source_index_read (XdeltaSource *xs,
311 XdeltaStream *index_in)
312{
313 SerialSource *ss = handle_source (index_in);
314 XdeltaIndex *index;
315
316 if (! ss)
317 return FALSE;
318
319 /* TODO: free ss */
320
321 if (! unserialize_xdeltaindex (ss, &index))
322 return FALSE;
323
324 if (! check_stream_integrity (xs->source_in, index->file_md5, index->file_len))
325 return FALSE;
326
327 xs->ck_count = index->index_len;
328 xs->cksums = index->index;
329
330 return TRUE;
331}
332
333static gboolean
334xdp_source_index_internal (XdeltaSource *init,
335 XdeltaStream *source_in,
336 XdeltaOutStream *index_out)
337{
338 if (! generate_checksums (source_in, init))
339 return FALSE;
340
341 if (index_out)
342 {
343 const guint8* source_in_md5;
344 SerialSink* sink = handle_sink (index_out, NULL, NULL, NULL, NULL);
345
346 if (! sink)
347 return FALSE;
348
349 if (! (source_in_md5 = handle_checksum_md5 (source_in)))
350 return FALSE;
351
352 if (! serialize_xdeltaindex (sink,
353 handle_length (source_in),
354 source_in_md5,
355 init->ck_count,
356 init->cksums))
357 {
358 g_free ((void*) source_in_md5);
359 return FALSE;
360 }
361
362 g_free ((void*) source_in_md5);
363
364 if (! handle_close (index_out, 0))
365 return FALSE;
366 }
367
368 return TRUE;
369}
370
371gboolean
372xdp_source_index (XdeltaStream *source_in,
373 XdeltaOutStream *index_out)
374{
375 XdeltaSource* xs = xdp_source_new ("(ignored)", source_in, NULL, index_out);
376
377 if (xs)
378 {
379 xdp_source_free (xs);
380 return TRUE;
381 }
382
383 return FALSE;
384}
385
386XdeltaSource*
387xdp_source_new (const char *name,
388 XdeltaStream *source_in,
389 XdeltaStream *index_in,
390 XdeltaOutStream *index_out)
391{
392 XdeltaSource* xs = g_new0 (XdeltaSource, 1);
393
394 xs->source_in = source_in;
395 xs->name = name;
396
397 g_return_val_if_fail (source_in, NULL);
398 g_return_val_if_fail (index_in ? ! index_out : TRUE, NULL);
399
400 xs->index_in = index_in;
401 xs->index_out = index_out;
402 xs->source_pos.page_size = handle_pagesize (source_in);
403
404 return xs;
405}
406
407static gboolean
408xdp_source_check_index (XdeltaSource *xs)
409{
410 if (xs->source_index == 0)
411 return TRUE;
412
413 if (! xs->index_in)
414 return xdp_source_index_internal (xs, xs->source_in, xs->index_out);
415 else
416 return xdp_source_index_read (xs, xs->index_in);
417}
418
419void
420xdp_source_free (XdeltaSource* xs)
421{
422 if (xs)
423 {
424 /* if (xs->ckarray) @@@ this is troublesome now
425 g_free (xs->ckarray);*/
426
427 g_free (xs);
428 }
429}
430
431void
432xdp_source_add (XdeltaGenerator *gen,
433 XdeltaSource *src)
434{
435 if (gen->table)
436 {
437 g_free ((gpointer)gen->table);
438 gen->table = NULL;
439 }
440
441 g_ptr_array_add (gen->sources, src);
442}
443
444guint
445c_hash (const XdeltaChecksum* c)
446{
447 const guint high = c->high;
448 const guint low = c->low;
449 const guint it = (high >> 2) + (low << 3) + (high << 16);
450
451 return (it ^ high ^ low);
452}
453
454static gboolean
455region_insert (XdeltaGenerator* gen, const XdeltaPos *xpos, guint len)
456{
457 /* This is a little bit cryptic: the xpos.mem + EXPR expression
458 * computes the offset into the current page, which is guaranteed
459 * to be correct since map_page has not occured yet. */
460 const guint8* buf = xpos->mem + (gen->to_output_pos % xpos->page_size);
461
462 if (len == 0)
463 return TRUE;
464
465#ifdef DEBUG_INST
466 g_print ("insert %d at %d\n", len, gen->to_output_pos);
467#endif
468
469 if (! handle_write (gen->data_out, buf, len))
470 return FALSE;
471
472 control_copy (gen->control, gen->data_source, gen->data_output_pos, gen->data_output_pos + len);
473
474 gen->to_output_pos += len;
475 gen->data_output_pos += len;
476
477 return TRUE;
478}
479
480static gboolean
481region_copy (XdeltaGenerator* gen, XdeltaSource* src, guint from, guint to)
482{
483#ifdef DEBUG_INST
484 g_print ("copy %d - %d (%d) to %d\n", from, to, to-from, gen->to_output_pos);
485#endif
486
487 control_copy (gen->control, src, from, to);
488
489 gen->to_output_pos += (to-from);
490
491 return TRUE;
492}
493
494gboolean
495unmap_page (XdeltaStream* stream, XdeltaPos* pos)
496{
497 if (! pos->mem)
498 return TRUE;
499
500 if (handle_unmap_page (stream,
501 pos->mem_page,
502 &pos->mem))
503 {
504 pos->mem = NULL;
505 return TRUE;
506 }
507
508 return FALSE;
509}
510
511gboolean
512map_page (XdeltaStream* stream, XdeltaPos* pos)
513{
514 gint on_page;
515
516 if (pos->mem && pos->mem_page == pos->page)
517 return TRUE;
518
519 if (pos->mem)
520 {
521 if (! handle_unmap_page (stream,
522 pos->mem_page,
523 &pos->mem))
524 return FALSE;
525
526 pos->mem = NULL;
527 }
528
529 pos->mem_page = pos->page;
530
531 on_page = handle_map_page (stream,
532 pos->mem_page,
533 &pos->mem);
534
535 if (on_page >= 0)
536 {
537 pos->mem_rem = on_page;
538 return TRUE;
539 }
540
541 return FALSE;
542}
543
544static gboolean
545try_match (XdeltaGenerator *gen,
546 XdeltaStream *in,
547 XdeltaPos *xpos_ptr,
548 XdeltaSource *src,
549 guint src_offset,
550 gboolean *found)
551{
552 XdeltaPos xpos = *xpos_ptr;
553 XdeltaPos ypos = src->source_pos;
554 gint rem, remsave;
555 gint match_forward = 0;
556 gint match_backward = 0;
557 gint match_forward_max;
558 gint match_backward_max;
559 guint to_offset = XPOS (xpos);
560 gboolean one_insert = FALSE;
561
562 *found = FALSE;
563
564 ypos.page = src_offset / ypos.page_size;
565 ypos.off = src_offset % ypos.page_size;
566
567 match_forward_max = MIN (handle_length (in) - to_offset,
568 handle_length (src->source_in) - src_offset);
569 match_backward_max = MIN (src_offset, to_offset - gen->to_output_pos);
570
571 /* Don't allow backward paging */
572 match_backward_max = MIN (match_backward_max, xpos.off);
573
574 /* We're testing against the negative below. */
575 match_backward_max = - match_backward_max;
576
577 for (; match_backward > match_backward_max; )
578 {
579 g_assert (xpos.off != 0);
580
581 if (ypos.off == 0)
582 {
583 ypos.off = ypos.page_size;
584 ypos.page -= 1;
585 }
586
587 if (! map_page (src->source_in, &ypos))
588 goto bail;
589
590 rem = MIN (xpos.off, ypos.off);
591 rem = MIN (match_backward - match_backward_max, rem);
592
593 for (; rem > 0; rem -= 1, match_backward -= 1)
594 {
595 if (xpos.mem[xpos.off-1] != ypos.mem[ypos.off-1])
596 goto doneback;
597
598 xpos.off -= 1;
599 ypos.off -= 1;
600 }
601 }
602
603doneback:
604
605 xpos.page = to_offset / xpos.page_size;
606 xpos.off = to_offset % xpos.page_size;
607
608 ypos.page = src_offset / ypos.page_size;
609 ypos.off = src_offset % ypos.page_size;
610
611 for (; match_forward < match_forward_max; )
612 {
613 if (! map_page (src->source_in, &ypos))
614 goto bail;
615
616 /* Fortunately, if this map happens it means that the match must
617 * be long enough to succeed below, therefore it is safe to write
618 * the insert out now. */
619 if (! one_insert && xpos.page != xpos.mem_page)
620 {
621 one_insert = TRUE;
622
623 if (! region_insert (gen, &xpos, (to_offset + match_backward) - gen->to_output_pos))
624 goto bail;
625 }
626
627 if (! map_page (in, &xpos))
628 goto bail;
629
630 rem = MIN (xpos.mem_rem - xpos.off, ypos.mem_rem - ypos.off);
631 rem = MIN (match_forward_max - match_forward, rem);
632
633 /* Do a int-wise comparison if the regions are aligned. */
634 if (rem > (4*sizeof(int)) && (xpos.off % sizeof (int)) == (ypos.off % sizeof(int)))
635 {
636 gint is;
637 const int *xi, *yi;
638
639 for (; xpos.off % sizeof(int); rem -= 1, match_forward += 1)
640 {
641 if (xpos.mem[xpos.off] != ypos.mem[ypos.off])
642 goto done;
643
644 xpos.off += 1;
645 ypos.off += 1;
646 }
647
648 remsave = rem;
649 rem /= sizeof(int);
650
651 xi = (const int*) (xpos.mem + xpos.off);
652 yi = (const int*) (ypos.mem + ypos.off);
653
654 is = rem;
655
656 for (; rem > 0 && *xi == *yi; )
657 {
658 rem -= 1;
659 xi += 1;
660 yi += 1;
661 }
662
663 is -= rem;
664
665 match_forward += is * sizeof(int);
666 xpos.off += is * sizeof(int);
667 ypos.off += is * sizeof(int);
668
669 rem = (rem * sizeof(int)) + (remsave % sizeof(int));
670 }
671
672 for (; rem > 0; rem -= 1, match_forward += 1)
673 {
674 if (xpos.mem[xpos.off] != ypos.mem[ypos.off])
675 goto done;
676
677 xpos.off += 1;
678 ypos.off += 1;
679 }
680
681 FLIP_FORWARD (xpos);
682 FLIP_FORWARD (ypos);
683 }
684
685done:
686
687 if (match_forward - match_backward >= QUERY_SIZE_POW)
688 {
689 *found = TRUE;
690
691 if (! one_insert)
692 {
693 if (! region_insert (gen, &xpos, (to_offset + match_backward) - gen->to_output_pos))
694 goto bail;
695 }
696
697 if (! region_copy (gen, src, src_offset + match_backward, src_offset + match_forward))
698 goto bail;
699 }
700 else
701 {
702 g_assert (! one_insert);
703 }
704
705 *xpos_ptr = xpos;
706 src->source_pos = ypos;
707 return TRUE;
708
709bail:
710 *xpos_ptr = xpos;
711 src->source_pos = ypos;
712 return FALSE;
713}
714
715static gboolean
716compute_copies (XdeltaGenerator* gen, XdeltaStream* stream)
717{
718 XdeltaChecksum cksum;
719 const XdeltaChecksum *source_cksum;
720 const guint8 *segment_pointer;
721 guint source_offset, segment_index, index, prime = gen->table_size;
722 guint source_index;
723 const guint32* table = gen->table;
724 guint16 old_c, new_c;
725 guint save_page, save_off;
726#ifdef DEBUG_MATCH_PRINT
727 guint i;
728#endif
729 XdeltaPos xpos;
730 gboolean found;
731 gboolean ret = TRUE;
732
733 if (handle_length (stream) < QUERY_SIZE_POW)
734 return TRUE;
735
736 init_pos (stream, &xpos);
737
738 while (XPOS (xpos) <= (handle_length (stream) - QUERY_SIZE_POW))
739 {
740 if (!map_page (stream, &xpos))
741 return FALSE;
742
743 g_assert (xpos.mem_rem > xpos.off);
744
745 segment_index = (xpos.mem_rem - xpos.off);
746
747 if (segment_index < QUERY_SIZE_POW)
748 goto nextpage;
749
750 segment_index -= QUERY_SIZE_POW;
751
752 segment_pointer = xpos.mem + xpos.off;
753
754 init_query_checksum (segment_pointer, &cksum);
755
756 for (; ; segment_pointer += 1)
757 {
758#ifdef DEBUG_CKSUM_UPDATE
759 XdeltaChecksum cktest;
760
761 init_query_checksum (segment_pointer, &cktest);
762
763 if (cktest.high != cksum.high || cktest.low != cktest.low)
764 abort ();
765#endif
766
767 index = c_hash (&cksum) % prime;
768
769#ifdef DEBUG_MATCH_PRINT
770 g_print ("%d: searching for match \"", XPOS(xpos));
771 for (i = 0; i < QUERY_SIZE_POW; i += 1)
772 {
773 if (isprint (segment_pointer[i]))
774 g_print ("%c", segment_pointer[i]);
775 else
776 g_print ("\\0%o", segment_pointer[i]);
777 }
778 g_print ("\"... %s\n", table[index] ? "found" : "notfound");
779#endif
780
781 if (table[index])
782 {
783 source_index = (table[index] & QUERY_SIZE_MASK) - 1;
784 source_offset = (table[index] >> QUERY_SIZE);
785
786 source_cksum = ((XdeltaSource*)gen->sources->pdata[source_index])->cksums + source_offset;
787
788 if (cksum.high == source_cksum->high &&
789 cksum.low == source_cksum->low)
790 {
791 save_page = xpos.page;
792 save_off = xpos.off;
793
794 if (! try_match (gen,
795 stream,
796 &xpos,
797 gen->sources->pdata[source_index],
798 source_offset << QUERY_SIZE,
799 &found))
800 {
801 ret = FALSE;
802 goto bail;
803 }
804
805 if (found)
806 {
807 g_assert (xpos.page*xpos.page_size+xpos.off == gen->to_output_pos);
808
809 goto reenter;
810 }
811 else
812 {
813 xpos.page = save_page;
814 xpos.off = save_off;
815 }
816 }
817 }
818
819 if (segment_index == 0)
820 goto nextpage;
821
822 segment_index -= 1;
823 xpos.off += 1;
824
825 old_c = CHEW(segment_pointer[0]);
826 new_c = CHEW(segment_pointer[QUERY_SIZE_POW]);
827
828 cksum.low -= old_c;
829 cksum.low += new_c;
830
831 cksum.high -= old_c << QUERY_SIZE;
832 cksum.high += cksum.low;
833 }
834
835 nextpage:
836
837 if (xpos.mem_rem < xpos.page_size)
838 break;
839
840 xpos.page += 1;
841 xpos.off = 0;
842
843 if (xpos.page != xpos.mem_page)
844 {
845 if (! region_insert (gen, &xpos, XPOS (xpos) - gen->to_output_pos))
846 return FALSE;
847 }
848
849 reenter:
850 (void) 0;
851 }
852
853 xpos.off = gen->to_output_pos % handle_pagesize (stream);
854
855 while (gen->to_output_pos < handle_length (stream))
856 {
857 if (! map_page (stream, &xpos))
858 return FALSE;
859
860 if (! region_insert (gen, &xpos, xpos.mem_rem - xpos.off))
861 ret = FALSE;
862
863 xpos.off = 0;
864 xpos.page += 1;
865 }
866
867bail:
868
869 if (! unmap_page (stream, &xpos))
870 return FALSE;
871
872 return ret;
873}
874
875static gboolean
876just_output (XdeltaGenerator *gen,
877 XdeltaStream *in)
878{
879 XdeltaPos pos;
880
881 init_pos (in, &pos);
882
883 while (gen->to_output_pos < handle_length (in))
884 {
885 if (! map_page (in, &pos))
886 return FALSE;
887
888 if (! region_insert (gen, &pos, pos.mem_rem - pos.off))
889 return FALSE;
890
891 pos.off = 0;
892 pos.page += 1;
893 }
894
895 if (! unmap_page (in, &pos))
896 return FALSE;
897
898 return TRUE;
899}
900
901/* Clobbering decision (see below):
902 *
903 * Algorithm A: Clobber it always (its fast!). The problem
904 * is that this prefers matches at the front of
905 * the file and leads to poor matches at the back
906 * of the file (assuming I insert going backwards).
907 *
908 * Algorithm B: Keep a table of how many times there has
909 * been a clobber at each index i, C[i].
910 * With probability 1/(C[i]+1), replace the
911 * previous entry. This gives a uniform
912 * probability of each entry surviving.
913 * The problem (supposed) with this
914 * algorithm is that the probabilities
915 * should not be uniform (though uniform is
916 * better than A) because there are more
917 * chances to match a segment at the end of
918 * the file than at the beginning.
919 *
920 * Algorithm C: Give a linear weight to each match
921 * according to it's position in the file
922 * -- number the segments from N down to 1
923 * starting at the beginning. Same as the
924 * above but with a different weight. The
925 * weight for segment i, match at checksum
926 * offset k, follows. The total number of
927 * checksums in the segment is C_i,
928 * therefore the total checksum count is
929 * C = sum_i (C_i).
930 * Now the interior weight is the (C_i-k)
931 * (the linear assumption) and the total
932 * interior weight is sum_{j=1}^{N}{j}=(N)(N+1)/2
933 * so the kth segment has interior weight
934 *
935 * [2 (C_i - k)] / [(C_i) (C_i + 1)]
936 *
937 * add in the exterior weight (after
938 * cancelling a C_i):
939 *
940 * w(i,k) = [2 (C_i - k)] / [(C_i + 1) (C)]
941 *
942 * Now, as above, we will compute whether to
943 * keep or replace the current value at the j-th
944 * decision. Let R_j be the running sum of
945 * weights considered so far. R_0 = 0. At the
946 * j-th decision,
947 *
948 * P_ikj(use new value) = w(i,k)/R_{j+1}
949 * R_{j+1} = R_j + w(i,k)
950 */
951
952static gboolean
953xdp_generate_delta_int (XdeltaGenerator *gen,
954 XdeltaStream *in,
955 XdeltaOutStream *control_out,
956 XdeltaOutStream *data_out)
957{
958 gint i, j, total_from_ck_count = 0, prime = 0, index = 0;
959 gint total_from_len = 0;
960 guint32* table = NULL;
961
962 if (QUERY_SIZE == 0)
963 {
964 xdp_set_query_size_pow (1<<QUERY_SIZE_DEFAULT);
965 }
966
967 if (gen->sources->len == 0)
968 {
969 xd_generate_void_event (EC_XdTooFewSources);
970 return FALSE;
971 }
972
973 for (i = 0; i < gen->sources->len; i += 1)
974 {
975 XdeltaSource* src = gen->sources->pdata[i];
976
977 src->used = FALSE;
978 src->sequential = TRUE;
979 src->position = 0;
980 src->source_index = i;
981
982 if (src->source_index != 0)
983 total_from_len += handle_length (src->source_in);
984 }
985
986 /* QUERY_SIZE_POW is the number of elements freed in the cksum hash
987 * table for storing segment number + (offset/QUERY_SIZE_POW) in. 1
988 * for the zero + 1 for the data segment */
989 if (gen->sources->len > (QUERY_SIZE_POW-2))
990 {
991 xd_generate_void_event (EC_XdTooManySources);
992 return FALSE;
993 }
994
995 if (handle_length (in) < QUERY_SIZE_POW || total_from_len < QUERY_SIZE_POW)
996 {
997 if (! just_output (gen, in))
998 return FALSE;
999 }
1000 else
1001 {
1002 for (i = 0; i < gen->sources->len; i += 1)
1003 {
1004 XdeltaSource* xs = (XdeltaSource*)gen->sources->pdata[i];
1005
1006 if (! xdp_source_check_index (xs))
1007 return FALSE;
1008
1009 total_from_ck_count += xs->ck_count;
1010 }
1011
1012 prime = g_spaced_primes_closest (total_from_ck_count);
1013
1014 gen->table = table = g_new0 (guint32, prime);
1015 gen->table_size = prime;
1016
1017 for (i = 0; i < gen->sources->len; i += 1)
1018 {
1019 XdeltaSource* xs = (XdeltaSource*)gen->sources->pdata[i];
1020
1021 for (j = xs->ck_count-1; j >= 0; j -= 1)
1022 {
1023 index = c_hash (xs->cksums + j) % prime;
1024
1025#ifdef DEBUG_HASH
1026 gen->hash_entries += 1;
1027
1028 if (table[index])
1029 {
1030 gen->hash_conflicts += 1;
1031
1032 /*regions_similar (gen,
1033 i,
1034 j,
1035 (table[index] & QUERY_SIZE_MASK) - 1,
1036 table[index] >> QUERY_SIZE);*/
1037 }
1038#endif
1039
1040 /* This is the real code */
1041 table[index] = (j << QUERY_SIZE) + 1 + i;
1042 }
1043 }
1044
1045#ifdef DEBUG_HASH
1046 for (i = 0; i < prime; i += 1)
1047 {
1048 if (gen->table[i])
1049 gen->hash_fill += 1;
1050 }
1051
1052 g_print ("*** Hash stats:\n");
1053 g_print ("Hash conflicts: %d\n", gen->hash_conflicts);
1054 g_print ("Hash real conflicts: %d\n", gen->hash_real_conflicts);
1055 g_print ("Hash real real conflicts: %d\n", gen->hash_real_real_conflicts);
1056 g_print ("Hash fill: %d\n", gen->hash_fill);
1057 g_print ("Hash size: %d\n", gen->table_size);
1058 g_print ("Hash entries: %d\n", gen->hash_entries);
1059 g_print ("Hash fill/entries: %f\n", (float)gen->hash_fill/(float)gen->hash_entries);
1060#endif
1061
1062 if (! compute_copies (gen, in))
1063 return FALSE;
1064 }
1065
1066 return TRUE;
1067}
1068
1069XdeltaControl*
1070xdp_generate_delta (XdeltaGenerator *gen,
1071 XdeltaStream *in,
1072 XdeltaOutStream *control_out,
1073 XdeltaOutStream *data_out)
1074{
1075 gint i;
1076 const guint8* in_md5;
1077 const guint8* data_out_md5;
1078
1079 gen->data_out = data_out;
1080 gen->control_out = control_out;
1081 gen->control = control_new ();
1082
1083 if (! xdp_generate_delta_int (gen, in, control_out, data_out))
1084 return NULL;
1085
1086 if (! handle_close (data_out, 0))
1087 return NULL;
1088
1089 if (! (in_md5 = handle_checksum_md5 (in)))
1090 return FALSE;
1091
1092 if (! (data_out_md5 = handle_checksum_md5 (data_out)))
1093 return FALSE;
1094
1095 gen->control->has_data = gen->data_source->used;
1096 gen->control->inst = &g_array_index (gen->control->inst_array, XdeltaInstruction, 0);
1097 gen->control->inst_len = gen->control->inst_array->len;
1098
1099 gen->control->to_len = handle_length (in);
1100 memcpy (gen->control->to_md5, in_md5, 16);
1101
1102 for (i = 0; i < gen->sources->len; i += 1)
1103 {
1104 XdeltaSource* src = gen->sources->pdata[i];
1105 const guint8* md5;
1106 guint len;
1107
1108 if (src->source_in)
1109 {
1110 if (! (md5 = handle_checksum_md5 (src->source_in)))
1111 return FALSE;
1112
1113 len = handle_length (src->source_in);
1114 }
1115 else
1116 {
1117 len = handle_length (data_out);
1118 md5 = data_out_md5;
1119 }
1120
1121 if (! control_add_info (gen->control, src, md5, len))
1122 return NULL;
1123 }
1124
1125 gen->control->source_info = (XdeltaSourceInfo**) gen->control->source_info_array->pdata;
1126 gen->control->source_info_len = gen->control->source_info_array->len;
1127
1128 if (control_out && ! xdp_control_write (gen->control, control_out))
1129 return NULL;
1130
1131 return gen->control;
1132}
1133
1134/* Below here boring details mostly to do with reading and writing
1135 * control. */
1136
1137XdeltaControl*
1138control_new (void)
1139{
1140 XdeltaControl* it = g_new0 (XdeltaControl, 1);
1141
1142 it->inst_array = g_array_new (FALSE, FALSE, sizeof (XdeltaInstruction));
1143 it->source_info_array = g_ptr_array_new ();
1144
1145 return it;
1146}
1147
1148static void
1149control_reindex (XdeltaControl* cont, XdeltaSource* src)
1150{
1151 gint i;
1152 gint new_index = cont->source_info_array->len;
1153
1154 for (i = 0; i < cont->inst_len; i += 1)
1155 {
1156 XdeltaInstruction* inst = cont->inst + i;
1157
1158 if (inst->index == src->source_index)
1159 inst->index = new_index;
1160 }
1161}
1162
1163gboolean
1164control_add_info (XdeltaControl* cont, XdeltaSource* src, const guint8* md5, guint len)
1165{
1166 XdeltaSourceInfo* si;
1167
1168 if (! src->used)
1169 return TRUE;
1170
1171 si = g_new0 (XdeltaSourceInfo, 1);
1172
1173 si->name = src->name;
1174 si->sequential = src->sequential;
1175 si->len = len;
1176 si->isdata = (src->source_index == 0);
1177
1178 memcpy (si->md5, md5, 16);
1179
1180 control_reindex (cont, src);
1181
1182 g_ptr_array_add (cont->source_info_array, si);
1183
1184 return TRUE;
1185}
1186
1187void
1188xdp_control_free (XdeltaControl* cont)
1189{
1190 if (cont->source_info_array)
1191 g_ptr_array_free (cont->source_info_array, TRUE);
1192 if (cont->inst_array)
1193 g_array_free (cont->inst_array, TRUE);
1194 g_free (cont);
1195}
1196
1197void
1198control_copy (XdeltaControl* cont, XdeltaSource* src, guint from, guint to)
1199{
1200 XdeltaInstruction i;
1201
1202 if (cont->inst_array->len > 0)
1203 {
1204 XdeltaInstruction* oi = & g_array_index (cont->inst_array, XdeltaInstruction, cont->inst_array->len-1);
1205
1206 if (oi->index == src->source_index && (oi->offset + oi->length) == from)
1207 {
1208 oi->length += (to - from);
1209 return;
1210 }
1211 }
1212
1213 i.index = src->source_index;
1214 i.offset = from;
1215 i.length = to - from;
1216
1217 src->used = TRUE;
1218
1219 if (src->position != from)
1220 src->sequential = FALSE;
1221
1222 src->position = to;
1223
1224 g_array_append_val (cont->inst_array, i);
1225}
1226
1227#ifdef DEBUG_CONT
1228static void
1229print_info (XdeltaSourceInfo* si)
1230{
1231 char md5str[33];
1232
1233 edsio_md5_to_string (si->md5, md5str);
1234
1235 g_print (" ** info\n");
1236 g_print (" md5: %s\n", md5str);
1237 g_print (" len: %d\n", si->length);
1238}
1239
1240static void
1241print_inst (XdeltaInstruction* i)
1242{
1243 switch (i->type)
1244 {
1245 case INST_TYPE_COPY:
1246 g_print (" copy (%c) %d-%d (%d) from %d\n", i->type, i->offset, i->offset + i->length, i->length, i->index);
1247 break;
1248 case INST_TYPE_INSERT:
1249 g_print (" insert %d\n", i->length);
1250 break;
1251 }
1252}
1253
1254static void
1255xdp_print_control (XdeltaControl *cont)
1256{
1257 gint i;
1258
1259 g_print ("*** control\n");
1260
1261 g_print (" data len: %d\n", cont->data_len);
1262 print_info (&cont->to_info);
1263
1264 g_print (" source info len: %d\n", cont->source_info_len);
1265
1266 for (i = 0; i < cont->source_info_len; i += 1)
1267 print_info (cont->source_info[i]);
1268
1269 g_print (" inst len: %d\n", cont->inst_len);
1270
1271 for (i = 0; i < cont->inst_len; i += 1)
1272 print_inst (cont->inst + i);
1273
1274}
1275#endif
1276
1277#ifdef DEBUG_CHECK_CONTROL
1278void
1279check_control (XdeltaControl* cont)
1280{
1281 gint i;
1282
1283 for (i = 0; i < cont->inst_len; i += 1)
1284 {
1285 switch (cont->inst[i].type)
1286 {
1287 case INST_TYPE_NCOPY:
1288 case INST_TYPE_COPY:
1289 if (cont->inst[i].index >= cont->source_info_len)
1290 g_error ("control has a too high instruction index\n");
1291 }
1292 }
1293}
1294#endif
1295
1296static gboolean
1297unpack_instructions (XdeltaControl* cont)
1298{
1299 gint i;
1300 guint output_pos = 0;
1301
1302 for (i = 0; i < cont->source_info_len; i += 1)
1303 {
1304 XdeltaSourceInfo* info = cont->source_info[i];
1305
1306 info->position = 0;
1307 info->copies = 0;
1308 info->copy_length = 0;
1309 }
1310
1311 for (i = 0; i < cont->inst_len; i += 1)
1312 {
1313 XdeltaSourceInfo* info;
1314 XdeltaInstruction *inst = cont->inst + i;
1315
1316 if (inst->index >= cont->source_info_len)
1317 {
1318 xd_generate_int_event (EC_XdOutOfRangeSourceIndex, inst->index);
1319 return FALSE;
1320 }
1321
1322 info = cont->source_info[inst->index];
1323
1324 if (info->sequential)
1325 {
1326 inst->offset = info->position;
1327 info->position = inst->offset + inst->length;
1328 }
1329
1330 inst->output_start = output_pos;
1331 output_pos += inst->length;
1332
1333 info->copies += 1;
1334 info->copy_length += inst->length;
1335 }
1336
1337 return TRUE;
1338}
1339
1340static gboolean
1341pack_instructions (XdeltaControl* cont)
1342{
1343 gint i;
1344
1345 for (i = 0; i < cont->source_info_len; i += 1)
1346 {
1347 XdeltaSourceInfo* info = cont->source_info[i];
1348
1349 info->position = 0;
1350 info->copies = 0;
1351 info->copy_length = 0;
1352 }
1353
1354 for (i = 0; i < cont->inst_len; i += 1)
1355 {
1356 XdeltaSourceInfo* info;
1357 XdeltaInstruction *inst = cont->inst + i;
1358
1359 if (inst->index >= cont->source_info_len)
1360 {
1361 xd_generate_int_event (EC_XdOutOfRangeSourceIndex, inst->index);
1362 return FALSE;
1363 }
1364
1365 info = cont->source_info[inst->index];
1366
1367 if (info->sequential)
1368 {
1369 g_assert (info->position == inst->offset);
1370 info->position += inst->length;
1371 inst->offset = 0;
1372 }
1373
1374 info->copies += 1;
1375 info->copy_length += inst->length;
1376 }
1377
1378 return TRUE;
1379}
1380
1381
1382gboolean
1383xdp_control_write (XdeltaControl *cont,
1384 XdeltaOutStream *cont_out)
1385{
1386 SerialSink* sink = handle_sink (cont_out, NULL, NULL, NULL, NULL);
1387
1388#ifdef DEBUG_CONT
1389 xdp_print_control (cont);
1390#endif
1391#ifdef DEBUG_CHECK_CONTROL
1392 check_control (cont);
1393#endif
1394
1395 if (! sink)
1396 return FALSE;
1397
1398 if (! pack_instructions (cont))
1399 return FALSE;
1400
1401 /* @@@ think about how the count function overcounts on the instruction
1402 * array by a factor of 2 or more. */
1403 if (! serialize_xdeltacontrol_obj (sink, cont))
1404 return FALSE;
1405
1406 if (! handle_close (cont_out, 0))
1407 return FALSE;
1408
1409 return TRUE;
1410}
1411
1412XdeltaControl*
1413xdp_control_read (XdeltaStream *cont_in)
1414{
1415 SerialSource* src = handle_source (cont_in);
1416 XdeltaControl* cont;
1417 SerialType type;
1418
1419 if (! src)
1420 return NULL;
1421
1422 /* TODO: free src */
1423
1424 if (! serializeio_unserialize_generic_acceptable (src, ST_XdeltaControl | ST_Version0Control, & type, (void**) & cont))
1425 {
1426 /* TODO: the warning below was added in 1.1.5 after a bug report
1427 * regarding an invalid delta, which would fail in patch here:
1428 * It's unclear whether this is the "right" place to print the
1429 * error. */
1430 g_warning ("patch parse error\n");
1431 return NULL;
1432 }
1433
1434 if (type == ST_Version0Control)
1435 {
1436 SerialVersion0Control *ocont = (SerialVersion0Control*) cont;
1437
1438 xd_generate_string_event (EC_XdBackwardCompatibilityMode, "1.0");
1439
1440 cont = control_version_0 (ocont);
1441
1442 g_free (ocont);
1443 }
1444
1445 if (! unpack_instructions (cont))
1446 return NULL;
1447
1448#ifdef DEBUG_CHECK_CONTROL
1449 check_control (cont);
1450#endif
1451
1452 return cont;
1453}
1454
1455XdeltaControl*
1456control_version_0 (SerialVersion0Control* ocont)
1457{
1458 XdeltaControl* cont = g_new0 (XdeltaControl, 1);
1459 gint i;
1460 XdeltaSourceInfo* dinfo;
1461
1462 g_assert (! ocont->normalized);
1463
1464 memcpy (cont->to_md5, ocont->to_info.real_md5, 16);
1465
1466 cont->to_len = ocont->to_info.length;
1467
1468 cont->has_data = TRUE;
1469
1470 cont->source_info_len = ocont->source_info_len + 1;
1471 cont->source_info = g_new (XdeltaSourceInfo*, cont->source_info_len);
1472
1473 cont->source_info[0] = dinfo = g_new0 (XdeltaSourceInfo, 1);
1474
1475 dinfo->name = "(patch data)";
1476 memcpy (dinfo->md5, ocont->to_info.md5, 15);
1477 dinfo->len = ocont->data_len;
1478 dinfo->isdata = TRUE;
1479 dinfo->sequential = FALSE;
1480
1481 for (i = 0; i < ocont->source_info_len; i += 1)
1482 {
1483 XdeltaSourceInfo* info = g_new0 (XdeltaSourceInfo, 1);
1484 SerialVersion0SourceInfo* oinfo = ocont->source_info[i];
1485
1486 cont->source_info[i+1] = info;
1487
1488 info->name = "unnamed";
1489 memcpy (info->md5, oinfo->md5, 16);
1490 info->len = oinfo->length;
1491 info->isdata = FALSE;
1492 info->sequential = FALSE;
1493 }
1494
1495 /* The old unpack */
1496#define OLD_QUERY_SIZE 4
1497 for (i = 0; i < ocont->inst_len; i += 1)
1498 {
1499 switch (ocont->inst[i].length & 3)
1500 {
1501 case 0: ocont->inst[i].type = 'N'; break;
1502 case 1: ocont->inst[i].type = 'E'; break;
1503 case 2: ocont->inst[i].type = 'C'; break;
1504 case 3: ocont->inst[i].type = 'I'; break;
1505 }
1506
1507 ocont->inst[i].length >>= 2;
1508 ocont->inst[i].index = ocont->inst[i].length & OLD_QUERY_SIZE;
1509 ocont->inst[i].length >>= OLD_QUERY_SIZE;
1510 }
1511
1512 cont->inst_len = ocont->inst_len;
1513 cont->inst = g_new (XdeltaInstruction, cont->inst_len);
1514
1515 for (i = 0; i < cont->inst_len; i += 1)
1516 {
1517 cont->inst[i].length = ocont->inst[i].length;
1518 cont->inst[i].offset = ocont->inst[i].offset;
1519
1520 switch (ocont->inst[i].type)
1521 {
1522 case 'N':
1523 case 'E':
1524 abort ();
1525 break;
1526
1527 case 'C':
1528 g_assert (ocont->inst[i].index == 0);
1529
1530 cont->inst[i].index = 1;
1531 break;
1532
1533 case 'I':
1534 cont->inst[i].index = 0;
1535 break;
1536 }
1537
1538 }
1539
1540 return cont;
1541}
diff --git a/xdelta1/xdelta.h b/xdelta1/xdelta.h
deleted file mode 100644
index dd43792..0000000
--- a/xdelta1/xdelta.h
+++ /dev/null
@@ -1,195 +0,0 @@
1/* -*- Mode: C;-*-
2 *
3 * This file is part of XDelta - A binary delta generator.
4 *
5 * Copyright (C) 1997, 1998, 2001 Josh MacDonald
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
22 *
23 * $Id: xdelta.h 1.4.1.8.1.50.1.3 Fri, 29 Jun 2001 06:01:08 -0700 jmacd $
24 */
25
26#ifndef _XDELTA_H_
27#define _XDELTA_H_
28
29#include "xd_edsio.h"
30
31typedef SerialRsyncIndex XdeltaRsync;
32typedef SerialRsyncIndexElt XdeltaRsyncElt;
33typedef SerialXdeltaChecksum XdeltaChecksum;
34typedef SerialXdeltaIndex XdeltaIndex;
35typedef SerialXdeltaSourceInfo XdeltaSourceInfo;
36typedef SerialXdeltaControl XdeltaControl;
37typedef SerialXdeltaInstruction XdeltaInstruction;
38
39typedef struct _XdeltaGenerator XdeltaGenerator;
40typedef struct _XdeltaSource XdeltaSource;
41
42typedef FileHandle XdeltaStream;
43typedef FileHandle XdeltaOutStream;
44
45/* Note: FileHandle is an opaque type, you must define it
46 * to use this library. See how its done in xdmain.c.
47 */
48
49/* $Format: "#define XDELTA_VERSION \"$ReleaseVersion$\"" $ */
50#define XDELTA_VERSION "1.1.4"
51
52/* $Format: "#define XDELTA_MAJOR_VERSION $ReleaseMajorVersion$" $ */
53#define XDELTA_MAJOR_VERSION 1
54
55/* $Format: "#define XDELTA_MINOR_VERSION $ReleaseMinorVersion$" $ */
56#define XDELTA_MINOR_VERSION 1
57
58/* $Format: "#define XDELTA_MICRO_VERSION $ReleaseMicroVersion$" $ */
59#define XDELTA_MICRO_VERSION 4
60
61extern const guint xdelta_major_version;
62extern const guint xdelta_minor_version;
63extern const guint xdelta_micro_version;
64
65/* copy segments are of length 1<<QUERY_SIZE, this must not be greater
66 * than 6 due to a space assumption, and also limits the number of
67 * sources allowed to (QUERY_SIZE_POW-1).
68 *
69 * The in-core FROM CKSUM table's size is (FROM_LEN bytes * 4 bytes-per-checksum) / (1<<QUERY_SIZE)
70 *
71 * The in-core CKSUM HASH table's size is the same size, each checksum has one 32-bit offset+srcindex
72 *
73 * With the a value of (QUERY_SIZE = 4) gives a 16 byte block size,
74 * gives FROM_LEN/4 bytes for the FROM CKSUM map, and the same for the
75 * CKSUM HASH, giving FROM_LEN/2 bytes, in addition to whatever used
76 * to cache the FROM inputs.
77 **/
78#define QUERY_SIZE_DEFAULT 4
79
80/* The query size has historically been hard coded. This gains around
81 * 20% in speed, so I've left it the default. If you're interested in
82 * large files, try undefining this (and using the -s argument to
83 * Xdelta).
84 */
85#define XDELTA_HARDCODE_SIZE
86
87#ifdef XDELTA_HARDCODE_SIZE
88#define QUERY_SIZE QUERY_SIZE_DEFAULT
89#define QUERY_SIZE_POW (1<<QUERY_SIZE)
90#define QUERY_SIZE_MASK (QUERY_SIZE_POW-1)
91#else
92extern int QUERY_SIZE;
93extern int QUERY_SIZE_POW;
94extern int QUERY_SIZE_MASK;
95#endif
96
97#define XDP_QUERY_HARDCODED -7654
98#define XDP_QUERY_POW2 -7655
99
100/* Returns if query size is hard coded. */
101int xdp_set_query_size_pow (int size_pow);
102int xdp_blocksize ();
103
104/* An xdelta consists of two pieces of information, the control and
105 * data segments. The control segment consists of instructions,
106 * metadata, and some redundent information for validation. The data
107 * segment consists of literal data not found in any of the sources.
108 *
109 * The library operates on two types of streams, random access and
110 * non-seekable. Briefly, you initialize a XdeltaGenerator with one
111 * or more XdeltaSources. These XdeltaSources contain a random access
112 * stream (a FROM file).
113 *
114 * The generator is initialized with an input stream and an output
115 * stream, these streams are not seekable.
116 *
117 * The creation of a XdeltaSource requires a complete pass through the
118 * file. This pass pre-computes an index which is used during delta
119 * computation. This index may be saved and restored to avoid
120 * computing it multiple times.
121 *
122 */
123
124#define xdp_generator_new() __xdp_generator_new (XDELTA_VERSION)
125
126XdeltaGenerator* __xdp_generator_new (const char *version);
127
128/* Create a new source. If non-null, INDEX_IN indicates that the
129 * index was previously computed and may be read from the stream. If
130 * non-null, INDEX_OUT is a stream to which the the computed index
131 * will be written. INDEX_OUT is ignored when INDEX_IN is non-null.
132 * Returns the source on success, NULL on failure.
133 */
134
135XdeltaSource* xdp_source_new (const char *name,
136 XdeltaStream *source_in,
137 XdeltaStream *index_in,
138 XdeltaOutStream *index_out);
139
140/* Simply index the source, do not save it in memory. Returns true on
141 * success, false on failure. */
142gboolean xdp_source_index (XdeltaStream *source_in,
143 XdeltaOutStream *index_out);
144
145/* Add SRC to the generator. The source will then be used for generating
146 * deltas. */
147void xdp_source_add (XdeltaGenerator *gen,
148 XdeltaSource *src);
149
150/* Actually generate a delta against the accumulated sources in GEN.
151 * Returns the delta's controller or NULL on failure. */
152XdeltaControl* xdp_generate_delta (XdeltaGenerator *gen,
153 XdeltaStream *in,
154 XdeltaOutStream *control_out,
155 XdeltaOutStream *data_out);
156
157/* Reads a control object from a stream. */
158XdeltaControl* xdp_control_read (XdeltaStream *cont_in);
159
160/* Writes a control object to a stream. */
161gboolean xdp_control_write (XdeltaControl *cont,
162 XdeltaOutStream *cont_out);
163
164/* Free the above structures */
165void xdp_source_free (XdeltaSource *src);
166void xdp_generator_free (XdeltaGenerator *gen);
167void xdp_control_free (XdeltaControl *con);
168
169/* Apply: (simple form) first set the IN field of each
170 * XdeltaSourceInfo in the control, then call this. */
171
172gboolean xdp_apply_delta (XdeltaControl *cont,
173 XdeltaOutStream *res);
174
175/* Rsync: Undocumented, experimental code. Have a look. May not
176 * compile. */
177
178XdeltaRsync* xdp_rsync_index (XdeltaStream *file,
179 guint seg_len,
180 XdeltaStream *cache_in,
181 XdeltaOutStream *cache_out);
182
183void xdp_rsync_index_free (XdeltaRsync *rsync);
184
185GArray* xdp_rsync_request (XdeltaStream *file,
186 XdeltaRsync *rsync);
187
188gboolean xdp_apply_rsync_reply (XdeltaRsync *rsync,
189 XdeltaStream *from,
190 XdeltaStream *reply,
191 XdeltaStream *out);
192
193const char* xdp_errno (int errval);
194
195#endif
diff --git a/xdelta1/xdelta.m4 b/xdelta1/xdelta.m4
deleted file mode 100644
index 5a0dc11..0000000
--- a/xdelta1/xdelta.m4
+++ /dev/null
@@ -1,183 +0,0 @@
1# Configure paths for XDELTA
2# Owen Taylor 97-11-3
3
4dnl AM_PATH_XDELTA([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]])
5dnl Test for XDELTA, and define XDELTA_CFLAGS and XDELTA_LIBS, if "gmodule" or
6dnl
7AC_DEFUN(AM_PATH_XDELTA,
8[dnl
9dnl Get the cflags and libraries from the xdelta-config script
10dnl
11AC_ARG_WITH(xdelta-prefix,[ --with-xdelta-prefix=PFX Prefix where XDELTA is installed (optional)],
12 xdelta_config_prefix="$withval", xdelta_config_prefix="")
13AC_ARG_WITH(xdelta-exec-prefix,[ --with-xdelta-exec-prefix=PFX Exec prefix where XDELTA is installed (optional)],
14 xdelta_config_exec_prefix="$withval", xdelta_config_exec_prefix="")
15AC_ARG_ENABLE(xdeltatest, [ --disable-xdeltatest Do not try to compile and run a test XDELTA program],
16 , enable_xdeltatest=yes)
17
18 if test x$xdelta_config_exec_prefix != x ; then
19 xdelta_config_args="$xdelta_config_args --exec-prefix=$xdelta_config_exec_prefix"
20 if test x${XDELTA_CONFIG+set} != xset ; then
21 XDELTA_CONFIG=$xdelta_config_exec_prefix/bin/xdelta-config
22 fi
23 fi
24 if test x$xdelta_config_prefix != x ; then
25 xdelta_config_args="$xdelta_config_args --prefix=$xdelta_config_prefix"
26 if test x${XDELTA_CONFIG+set} != xset ; then
27 XDELTA_CONFIG=$xdelta_config_prefix/bin/xdelta-config
28 fi
29 fi
30
31 AC_PATH_PROG(XDELTA_CONFIG, xdelta-config, no)
32 min_xdelta_version=ifelse([$1], ,1.0.0,$1)
33 AC_MSG_CHECKING(for XDELTA - version >= $min_xdelta_version)
34 no_xdelta=""
35 if test "$XDELTA_CONFIG" = "no" ; then
36 no_xdelta=yes
37 else
38 XDELTA_CFLAGS=`$XDELTA_CONFIG $xdelta_config_args --cflags`
39 XDELTA_LIBS=`$XDELTA_CONFIG $xdelta_config_args --libs`
40 xdelta_config_major_version=`$XDELTA_CONFIG $xdelta_config_args --version | \
41 sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
42 xdelta_config_minor_version=`$XDELTA_CONFIG $xdelta_config_args --version | \
43 sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
44 xdelta_config_micro_version=`$XDELTA_CONFIG $xdelta_config_args --version | \
45 sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
46 if test "x$enable_xdeltatest" = "xyes" ; then
47 ac_save_CFLAGS="$CFLAGS"
48 ac_save_LIBS="$LIBS"
49 CFLAGS="$CFLAGS $XDELTA_CFLAGS"
50 LIBS="$LIBS $XDELTA_LIBS"
51dnl
52dnl Now check if the installed XDELTA is sufficiently new. (Also sanity
53dnl checks the results of xdelta-config to some extent
54dnl
55 rm -f conf.xdeltatest
56 AC_TRY_RUN([
57#include <xdelta.h>
58#include <stdio.h>
59#include <stdlib.h>
60
61int
62main ()
63{
64 int major, minor, micro;
65 char *tmp_version;
66
67 system ("touch conf.xdeltatest");
68
69 /* HP/UX 9 (%@#!) writes to sscanf strings */
70 tmp_version = g_strdup("$min_xdelta_version");
71 if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
72 printf("%s, bad version string\n", "$min_xdelta_version");
73 exit(1);
74 }
75
76 if ((xdelta_major_version != $xdelta_config_major_version) ||
77 (xdelta_minor_version != $xdelta_config_minor_version) ||
78 (xdelta_micro_version != $xdelta_config_micro_version))
79 {
80 printf("\n*** 'xdelta-config --version' returned %d.%d.%d, but XDELTA (%d.%d.%d)\n",
81 $xdelta_config_major_version, $xdelta_config_minor_version, $xdelta_config_micro_version,
82 xdelta_major_version, xdelta_minor_version, xdelta_micro_version);
83 printf ("*** was found! If xdelta-config was correct, then it is best\n");
84 printf ("*** to remove the old version of XDELTA. You may also be able to fix the error\n");
85 printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
86 printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
87 printf("*** required on your system.\n");
88 printf("*** If xdelta-config was wrong, set the environment variable XDELTA_CONFIG\n");
89 printf("*** to point to the correct copy of xdelta-config, and remove the file config.cache\n");
90 printf("*** before re-running configure\n");
91 }
92 else if ((xdelta_major_version != XDELTA_MAJOR_VERSION) ||
93 (xdelta_minor_version != XDELTA_MINOR_VERSION) ||
94 (xdelta_micro_version != XDELTA_MICRO_VERSION))
95 {
96 printf("*** XDELTA header files (version %d.%d.%d) do not match\n",
97 XDELTA_MAJOR_VERSION, XDELTA_MINOR_VERSION, XDELTA_MICRO_VERSION);
98 printf("*** library (version %d.%d.%d)\n",
99 xdelta_major_version, xdelta_minor_version, xdelta_micro_version);
100 }
101 else
102 {
103 if ((xdelta_major_version > major) ||
104 ((xdelta_major_version == major) && (xdelta_minor_version > minor)) ||
105 ((xdelta_major_version == major) && (xdelta_minor_version == minor) && (xdelta_micro_version >= micro)))
106 {
107 return 0;
108 }
109 else
110 {
111 printf("\n*** An old version of XDELTA (%d.%d.%d) was found.\n",
112 xdelta_major_version, xdelta_minor_version, xdelta_micro_version);
113 printf("*** You need a version of XDELTA newer than %d.%d.%d. The latest version of\n",
114 major, minor, micro);
115 printf("*** XDELTA is always available from ftp://ftp.gtk.org.\n");
116 printf("***\n");
117 printf("*** If you have already installed a sufficiently new version, this error\n");
118 printf("*** probably means that the wrong copy of the xdelta-config shell script is\n");
119 printf("*** being found. The easiest way to fix this is to remove the old version\n");
120 printf("*** of XDELTA, but you can also set the XDELTA_CONFIG environment to point to the\n");
121 printf("*** correct copy of xdelta-config. (In this case, you will have to\n");
122 printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
123 printf("*** so that the correct libraries are found at run-time))\n");
124 }
125 }
126 return 1;
127}
128],, no_xdelta=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
129 CFLAGS="$ac_save_CFLAGS"
130 LIBS="$ac_save_LIBS"
131 fi
132 fi
133 if test "x$no_xdelta" = x ; then
134 AC_MSG_RESULT(yes)
135 ifelse([$2], , :, [$2])
136 else
137 AC_MSG_RESULT(no)
138 if test "$XDELTA_CONFIG" = "no" ; then
139 echo "*** The xdelta-config script installed by XDELTA could not be found"
140 echo "*** If XDELTA was installed in PREFIX, make sure PREFIX/bin is in"
141 echo "*** your path, or set the XDELTA_CONFIG environment variable to the"
142 echo "*** full path to xdelta-config."
143 else
144 if test -f conf.xdeltatest ; then
145 :
146 else
147 echo "*** Could not run XDELTA test program, checking why..."
148 CFLAGS="$CFLAGS $XDELTA_CFLAGS"
149 LIBS="$LIBS $XDELTA_LIBS"
150 AC_TRY_LINK([
151#include <xdelta.h>
152#include <stdio.h>
153], [ return ((xdelta_major_version) || (xdelta_minor_version) || (xdelta_micro_version)); ],
154 [ echo "*** The test program compiled, but did not run. This usually means"
155 echo "*** that the run-time linker is not finding XDELTA or finding the wrong"
156 echo "*** version of XDELTA. If it is not finding XDELTA, you'll need to set your"
157 echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
158 echo "*** to the installed location Also, make sure you have run ldconfig if that"
159 echo "*** is required on your system"
160 echo "***"
161 echo "*** If you have an old version installed, it is best to remove it, although"
162 echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
163 echo "***"
164 echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that"
165 echo "*** came with the system with the command"
166 echo "***"
167 echo "*** rpm --erase --nodeps gtk gtk-devel" ],
168 [ echo "*** The test program failed to compile or link. See the file config.log for the"
169 echo "*** exact error that occured. This usually means XDELTA was incorrectly installed"
170 echo "*** or that you have moved XDELTA since it was installed. In the latter case, you"
171 echo "*** may want to edit the xdelta-config script: $XDELTA_CONFIG" ])
172 CFLAGS="$ac_save_CFLAGS"
173 LIBS="$ac_save_LIBS"
174 fi
175 fi
176 XDELTA_CFLAGS=""
177 XDELTA_LIBS=""
178 ifelse([$3], , :, [$3])
179 fi
180 AC_SUBST(XDELTA_CFLAGS)
181 AC_SUBST(XDELTA_LIBS)
182 rm -f conf.xdeltatest
183])
diff --git a/xdelta1/xdelta.magic b/xdelta1/xdelta.magic
deleted file mode 100644
index 3e11f09..0000000
--- a/xdelta1/xdelta.magic
+++ /dev/null
@@ -1,9 +0,0 @@
1#------------------------------------------------------------------------------
2# file(1) magic(5) data for xdelta
3#
40 string %XDELTA% XDelta binary patch file 0.14
50 string %XDZ000% XDelta binary patch file 0.18
60 string %XDZ001% XDelta binary patch file 0.20
70 string %XDZ002% XDelta binary patch file 1.0
80 string %XDZ003% XDelta binary patch file 1.0.4
90 string %XDZ004% XDelta binary patch file 1.1
diff --git a/xdelta1/xdelta.prj b/xdelta1/xdelta.prj
deleted file mode 100644
index cc4b6bb..0000000
--- a/xdelta1/xdelta.prj
+++ /dev/null
@@ -1,123 +0,0 @@
1;; -*- PRCS -*-
2(Created-By-Prcs-Version 1 3 4)
3(Project-Description "")
4(Project-Version xdelta 1.1-maint 15)
5(Parent-Version xdelta 1.1-maint 14)
6(Version-Log "fixed the source allocation problem, free() was never being called and still isn't, added 2 TODOs for freeing source/control handles")
7(New-Version-Log "")
8(Checkin-Time "Sun, 28 Jan 2007 12:21:11 -0800")
9(Checkin-Login jmacd)
10(Populate-Ignore ("\\.o$"
11 "\\.deps"
12 "\\.lo$"
13 ".libs/"
14 "^\\.#"
15 "\\.la$"
16 "stamp-"
17 "mkinstalldirs"
18 "missing"
19 "ltmain\\.sh"
20 "ltconfig"
21 "install-sh"
22 "xdser\\.h"
23 "xdser\\.c"
24 "config\\."
25 "aclocal\\.m4"
26 "CVS/"
27 "Makefile\\.in$"
28 "Makefile$"
29 "\\.svn"
30 "configure$"
31 "xdelta$"
32 "libtool"
33 "doc/xdelta.info"
34 ))
35(Project-Keywords
36 (ReleaseMajorVersion 1)
37 (ReleaseMinorVersion 1)
38 (ReleaseMicroVersion 4)
39 (LibCurrent 2)
40 (LibRevision 0)
41 (LibAge 0)
42 (ReleaseVersion "$ReleaseMajorVersion$.$ReleaseMinorVersion$.$ReleaseMicroVersion$")
43)
44(Files
45 ;; Config
46 (configure.in (xdelta/1_configure. 1.10.1.38 744))
47 (Makefile.am (xdelta/2_Makefile.a 1.19.1.40.1.4 744))
48 (ChangeLog (xdelta/d/9_ChangeLog 1.6 644))
49 (runtest (xdelta/d/5_runtest 1.7 744))
50 (README (xdelta/d/6_README 1.5 744))
51 (INSTALL (xdelta/d/10_INSTALL 1.3 744))
52 (COPYING (xdelta/d/11_COPYING 1.2 744))
53 (AUTHORS (xdelta/d/12_AUTHORS 1.2 744))
54 (NEWS (xdelta/d/13_NEWS 1.15.1.9 744))
55 (xdelta.magic (xdelta/d/20_xdelta.mag 1.2 744))
56 (xdelta-config.in (xdelta/d/33_xdelta-con 1.4 744))
57 (autogen.sh (xdelta/i/7_autogen.sh 1.1 744))
58 (xdelta.m4 (xdelta/d/35_xdelta.m4 1.5 744))
59
60 ;; Library
61 (xdelta.h (xdelta/b/8_xdelta.h 1.4.1.8.1.50.1.3 744))
62 (xdeltapriv.h (xdelta/c/42_xdeltapriv 1.29 744))
63 (xdelta.c (xdelta/b/14_xdelta.c 1.4.1.50.1.4 744))
64 (xd.ser (xdelta/d/7_xd.ser 1.12 744))
65 (xdrsync.c (xdelta/d/44_xdrsync.c 1.2 744))
66 (xdapply.c (xdelta/e/37_xdapply.c 1.1 744))
67
68 ;; Application
69 (xdmain.c (xdelta/d/15_xdmain.c 1.22.1.7.1.1 744))
70 (getopt1.c (xdelta/d/17_getopt1.c 1.1 744))
71 (getopt.h (xdelta/d/18_getopt.h 1.1 744))
72 (getopt.c (xdelta/d/19_getopt.c 1.1 744))
73
74 ;; Testing
75 (test/Makefile.am (xdelta/e/39_Makefile.a 1.1.1.3 744))
76 (test/xdeltatest.c (xdelta/e/38_xdeltatest 1.7.1.1 744))
77 (test/README.test (xdelta/21_README.tes 1.2 744))
78
79 ;; Not much docs
80 (doc/Makefile.am (xdelta/d/21_Makefile.a 1.4 744))
81 (doc/xdelta.1 (xdelta/d/23_xdelta.1 1.6 744))
82 (doc/xdelta.cat (xdelta/22_xdelta.cat 1.2 744))
83
84 ;; DJGPP contrib
85 (djgpp/readme.djg (xdelta/18_readme.djg 1.2 744))
86 (djgpp/announce.djg (xdelta/19_announce.d 1.2 744))
87 (djgpp/Makefile.am (xdelta/20_Makefile.a 1.1 744))
88
89 ;; Files added by populate at Sat, 27 Jan 2007 17:51:22 -0800,
90 ;; to version 1.1-maint.10(w), by jmacd:
91
92 (xdelta-0.13.README (xdelta/i/0_xdelta-0.1 1.1 744))
93 (xdelta-1.1.2.tar.gz (xdelta/i/3_xdelta-1.1 1.1 744) :no-keywords)
94 (xdelta-1.1.3.tar.gz (xdelta/i/4_xdelta-1.1 1.1 744) :no-keywords)
95 (xdelta-config (xdelta/i/5_xdelta-con 1.1 744))
96 (contrib/build_hpux (xdelta/i/6_build_hpux 1.1 744))
97
98 ;; Files added by populate at Sun, 28 Jan 2007 10:01:31 -0800,
99 ;; to version 1.1-maint.12(w), by jmacd:
100
101 (libedsio/fh.c (xdelta/i/9_fh.c 1.2 744))
102 (libedsio/maketime.c (xdelta/i/10_maketime.c 1.1 744))
103 (libedsio/simple.c (xdelta/i/11_simple.c 1.1 744))
104 (libedsio/md5c.c (xdelta/i/12_md5c.c 1.1 744))
105 (libedsio/Makefile.am (xdelta/i/13_Makefile.a 1.1 744))
106 (libedsio/base64.c (xdelta/i/15_base64.c 1.1 744))
107 (libedsio/default.c (xdelta/i/16_default.c 1.2 744))
108 (libedsio/edsio.el (xdelta/i/18_edsio.el 1.2 744))
109 (libedsio/edsio-comp (xdelta/i/19_edsio-comp 1.1 744))
110 (libedsio/generic.c (xdelta/i/20_generic.c 1.2 744))
111 (libedsio/sha.c (xdelta/i/21_sha.c 1.1 744))
112 (libedsio/edsio.ser (xdelta/i/22_edsio.ser 1.1 744))
113 (libedsio/edsio.h (xdelta/i/23_edsio.h 1.2 744))
114 (libedsio/partime.h (xdelta/i/24_partime.h 1.1 744))
115 (libedsio/library.c (xdelta/i/25_library.c 1.1 744))
116 (libedsio/edsio.c (xdelta/i/26_edsio.c 1.1 744))
117 (libedsio/edsiotest.c (xdelta/i/27_edsiotest. 1.1 744))
118 (libedsio/partime.c (xdelta/i/28_partime.c 1.1 744))
119 (libedsio/maketime.h (xdelta/i/29_maketime.h 1.1 744))
120 (libedsio/edsio-comp.in (xdelta/i/30_edsio-comp 1.1 744))
121)
122(Merge-Parents)
123(New-Merge-Parents)
diff --git a/xdelta1/xdeltapriv.h b/xdelta1/xdeltapriv.h
deleted file mode 100644
index 9c75f09..0000000
--- a/xdelta1/xdeltapriv.h
+++ /dev/null
@@ -1,131 +0,0 @@
1/* -*- Mode: C;-*-
2 *
3 * This file is part of XDelta - A binary delta generator.
4 *
5 * Copyright (C) 1997, 1998, 1999 Josh MacDonald
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
22 *
23 * $Id: xdeltapriv.h 1.29 Sat, 03 Apr 1999 20:09:14 -0800 jmacd $
24 */
25
26#ifndef _XDELTAPRIV_H_
27#define _XDELTAPRIV_H_
28
29#if 0
30#define DEBUG_CKSUM_UPDATE
31#define DEBUG_MATCH_PRINT
32#define DEBUG_CKSUM
33#define DEBUG_HASH
34#define DEBUG_INST
35#define CLOBBER_ALGORITHM_C
36#define DEBUG_MD5
37#define DEBUG_CONT
38#define DEBUG_COPY
39#define DEBUG_FIND
40#define DEBUG_RSYNC_REQUEST
41#define DEBUG_CONT
42#define DEBUG_CONT2
43#define DEBUG_CHECK_CONTROL
44#endif
45
46typedef struct _XdeltaPos XdeltaPos;
47typedef struct _RsyncHash RsyncHash;
48
49#define XPOS(p) (((p).page * (p).page_size) + (p).off)
50
51struct _XdeltaPos {
52 guint page;
53 guint page_size;
54 guint off;
55
56 const guint8* mem;
57 guint mem_page;
58 guint mem_rem;
59};
60
61#define handle_length(x) ((* (x)->table->table_handle_length) (x))
62#define handle_pages(x) ((* (x)->table->table_handle_pages) (x))
63#define handle_pagesize(x) ((* (x)->table->table_handle_pagesize) (x))
64#define handle_map_page(x,y,z) ((* (x)->table->table_handle_map_page) ((x),(y),(z)))
65#define handle_unmap_page(x,y,z) ((* (x)->table->table_handle_unmap_page) ((x),(y),(z)))
66#define handle_checksum_md5(x) ((* (x)->table->table_handle_checksum_md5) (x))
67#define handle_close(x,y) ((* (x)->table->table_handle_close) ((x), (y)))
68#define handle_write(x,y,z) ((* (x)->table->table_handle_write) ((x),(y),(z)))
69#define handle_copy(x,y,z,a) ((* (x)->table->table_handle_copy) ((x),(y),(z),(a)))
70
71struct _XdeltaGenerator
72{
73 GPtrArray *sources;
74
75 const guint32 *table;
76 guint table_size;
77
78 guint to_output_pos;
79 guint data_output_pos;
80
81 XdeltaOutStream *data_out;
82 XdeltaOutStream *control_out;
83
84 XdeltaControl *control;
85
86 XdeltaSource *data_source;
87
88#ifdef DEBUG_HASH
89 gint hash_conflicts; /* bucket already used. */
90 gint hash_real_conflicts; /* bucket had different checksum. */
91 gint hash_real_real_conflicts; /* bucket had same checksum, different region */
92 gint hash_fill;
93 gint hash_entries;
94#endif
95
96 EdsioMD5Ctx ctx;
97};
98
99struct _XdeltaSource
100{
101 XdeltaStream *source_in;
102 XdeltaPos source_pos;
103
104 gint ck_count; /* number of elts in cksums. */
105 const XdeltaChecksum *cksums; /* array of cksums. */
106
107 const char *name;
108
109 XdeltaStream *index_in;
110 XdeltaOutStream *index_out;
111
112 gint source_index;
113 gboolean used;
114 gboolean sequential;
115 guint32 position;
116};
117
118#define CHEW(x) (single_hash[(guint)x])
119#define FLIP_FORWARD(p) if ((p).off == (p).page_size) { (p).page += 1; (p).off = 0; }
120
121extern const guint16 single_hash[256];
122
123void init_pos (XdeltaStream* str, XdeltaPos* pos);
124gboolean unmap_page (XdeltaStream* stream, XdeltaPos* pos);
125gboolean map_page (XdeltaStream* stream, XdeltaPos* pos);
126gboolean check_stream_integrity (XdeltaStream* str, const guint8* md5, guint len);
127XdeltaControl* control_new (void);
128
129guint c_hash (const XdeltaChecksum* c);
130
131#endif /* _XDELTAPRIV_H_ */
diff --git a/xdelta1/xdmain.c b/xdelta1/xdmain.c
deleted file mode 100644
index 8b6b800..0000000
--- a/xdelta1/xdmain.c
+++ /dev/null
@@ -1,1965 +0,0 @@
1/* -*- Mode: C;-*-
2 *
3 * This file is part of XDelta - A binary delta generator.
4 *
5 * Copyright (C) 1997, 1998, 1999, 2001 Josh MacDonald
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
22 *
23 * $Id: xdmain.c 1.22.1.7.1.1 Sat, 27 Jan 2007 17:53:47 -0800 jmacd $
24 */
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <errno.h>
30#include <ctype.h>
31
32#include <fcntl.h>
33#include <sys/stat.h>
34
35#if defined(_WIN32) || defined(__DJGPP__)
36#define WINHACK
37#endif
38
39#ifndef WINHACK
40#include <unistd.h>
41#include <sys/mman.h>
42// #define O_BINARY 0
43
44#else /* WINHACK */
45
46#include <io.h>
47#include <process.h>
48#ifdef __DJGPP__
49#include <unistd.h>
50#include <dpmi.h>
51#endif
52
53#define STDOUT_FILENO 1
54#define lstat stat
55
56#ifndef __DJGPP__
57#define S_IFMT _S_IFMT
58#define S_IFREG _S_IFREG
59#endif /* !__DJGPP__ */
60
61#endif /* !WINHACK_ */
62
63#include <zlib.h>
64
65#include "xdelta.h"
66
67static HandleFuncTable xd_handle_table;
68
69#define XD_PAGE_SIZE (1<<20)
70
71#define XDELTA_110_PREFIX "%XDZ004%"
72#define XDELTA_104_PREFIX "%XDZ003%"
73#define XDELTA_100_PREFIX "%XDZ002%"
74#define XDELTA_020_PREFIX "%XDZ001%"
75#define XDELTA_018_PREFIX "%XDZ000%"
76#define XDELTA_014_PREFIX "%XDELTA%"
77#define XDELTA_PREFIX XDELTA_110_PREFIX
78#define XDELTA_PREFIX_LEN 8
79
80#define HEADER_WORDS (6)
81#define HEADER_SPACE (HEADER_WORDS*4)
82/* The header is composed of 4-byte words (network byte order) as follows:
83 * word 1: flags
84 * word 2: (from name length) << 16 | (to name length)
85 * word 3: (reserved)
86 * word 4: (reserved)
87 * word 5: (reserved)
88 * word 6: (reserved)
89 * flags are:
90 */
91#define FLAG_NO_VERIFY 1
92#define FLAG_FROM_COMPRESSED 2
93#define FLAG_TO_COMPRESSED 4
94#define FLAG_PATCH_COMPRESSED 8
95/* and, the header is follwed by the from file name, then the to file
96 * name, then the data. */
97
98#ifdef WINHACK
99#define FOPEN_READ_ARG "rb"
100#define FOPEN_WRITE_ARG "wb"
101#define FILE_SEPARATOR '\\'
102#else
103#define FOPEN_READ_ARG "r"
104#define FOPEN_WRITE_ARG "w"
105#define FILE_SEPARATOR '/'
106#endif /* WINHACK */
107
108#include "getopt.h"
109
110typedef struct _LRU LRU;
111
112struct _LRU
113{
114 LRU *next;
115 LRU *prev;
116
117 gint refs;
118 guint page;
119 guint8* buffer;
120};
121
122typedef struct _XdFileHandle XdFileHandle;
123
124typedef struct {
125 gboolean patch_is_compressed;
126 const gchar* patch_name;
127 guint patch_flags;
128 const gchar* patch_version;
129 gboolean has_trailer;
130
131 XdeltaSourceInfo* data_source;
132 XdeltaSourceInfo* from_source;
133
134 gchar *from_name;
135 gchar *to_name;
136
137 guint control_offset;
138 guint header_offset;
139
140 gint16 from_name_len;
141 gint16 to_name_len;
142
143 guint32 header_space[HEADER_WORDS];
144 guint8 magic_buf[XDELTA_PREFIX_LEN];
145
146 XdFileHandle *patch_in;
147
148 XdeltaControl *cont;
149} XdeltaPatch;
150
151struct _XdFileHandle
152{
153 FileHandle fh;
154
155 guint length;
156 guint real_length;
157 gint type;
158 const char* name;
159 const char* cleanup;
160
161 guint8 md5[16];
162 EdsioMD5Ctx ctx;
163
164 /* for write */
165 int out_fd;
166 void* out;
167 gboolean (* out_write) (XdFileHandle* handle, const void* buf, gint nbyte);
168 gboolean (* out_close) (XdFileHandle* handle);
169
170 /* for read */
171 GPtrArray *lru_table;
172 LRU *lru_head; /* most recently used. */
173 LRU *lru_tail; /* least recently used. */
174 GMemChunk *lru_chunk;
175 guint lru_count;
176 guint lru_outstanding_refs;
177
178 guint narrow_low;
179 guint narrow_high;
180 guint current_pos;
181 FILE* in;
182 gboolean (* in_read) (XdFileHandle* handle, void* buf, gint nbyte);
183 gboolean (* in_close) (XdFileHandle* handle);
184 gboolean in_compressed;
185
186 const guint8* copy_page;
187 guint copy_pgno;
188 gboolean md5_good;
189 gboolean reset_length_next_write;
190
191 gint md5_page;
192 gint fd;
193};
194
195/* $Format: "static const char xdelta_version[] = \"$ReleaseVersion$\"; " $ */
196static const char xdelta_version[] = "1.1.4";
197
198typedef struct _Command Command;
199
200struct _Command {
201 gchar* name;
202 gint (* func) (gint argc, gchar** argv);
203 gint nargs;
204};
205
206static gint delta_command (gint argc, gchar** argv);
207static gint patch_command (gint argc, gchar** argv);
208static gint info_command (gint argc, gchar** argv);
209
210static const Command commands[] =
211{
212 { "delta", delta_command, -1 },
213 { "patch", patch_command, -1 },
214 { "info", info_command, 1 },
215 { NULL, NULL, 0 }
216};
217
218static struct option const long_options[] =
219{
220 {"help", no_argument, 0, 'h'},
221 {"version", no_argument, 0, 'v'},
222 {"verbose", no_argument, 0, 'V'},
223 {"noverify", no_argument, 0, 'n'},
224 {"pristine", no_argument, 0, 'p'},
225 {"quiet", no_argument, 0, 'q'},
226 {"maxmem", required_argument, 0, 'm'},
227 {"blocksize", required_argument, 0, 's'},
228 {0,0,0,0}
229};
230
231static const gchar* program_name;
232static gint compress_level = Z_DEFAULT_COMPRESSION;
233static gint no_verify = FALSE;
234static gint pristine = FALSE;
235static gint verbose = FALSE;
236static gint max_mapped_pages = G_MAXINT;
237static gint quiet = FALSE;
238
239#define xd_error g_warning
240
241static void
242usage ()
243{
244 xd_error ("usage: %s COMMAND [OPTIONS] [ARG1 ...]\n", program_name);
245 xd_error ("use --help for more help\n");
246 exit (2);
247}
248
249static void
250help ()
251{
252 xd_error ("usage: %s COMMAND [OPTIONS] [ARG1 ...]\n", program_name);
253 xd_error ("COMMAND is one of:\n");
254 xd_error (" delta Produce a delta from ARG1 to ARG2 producing ARG3\n");
255 xd_error (" info List details about delta ARG1\n");
256 xd_error (" patch Apply patch ARG1 using file ARG2 producing ARG3\n");
257 xd_error ("OPTIONS are:\n");
258 xd_error (" -v, --version Print version information\n");
259 xd_error (" -V, --verbose Print verbose error messages\n");
260 xd_error (" -h, --help Print this summary\n");
261 xd_error (" -n, --noverify Disable automatic MD5 verification\n");
262 xd_error (" -p, --pristine Disable automatic GZIP decompression\n");
263 xd_error (" -q, --quiet Do not print warnings\n");
264 xd_error (" -m, --maxmem=SIZE Set the buffer size limit, e.g. 640K, 16M\n");
265 xd_error (" -[0-9] ZLIB compress level: 0=none, 1=fast, 6=default, 9=best\n");
266 xd_error (" -s=BLOCK_SIZE Sets block size (power of 2), minimum match length\n");
267 xd_error (" In-core memory requirement is (FROM_LEN * 8) / BLOCK_SIZE\n");
268 exit (2);
269}
270
271static void
272version ()
273{
274 xd_error ("version %s\n", xdelta_version);
275 exit (2);
276}
277
278static FILE* xd_error_file = NULL;
279
280static void
281xd_error_func (const gchar *log_domain,
282 GLogLevelFlags log_level,
283 const gchar *message,
284 gpointer user_data)
285{
286 if (! xd_error_file)
287 xd_error_file = stderr;
288
289 fprintf (xd_error_file, "%s: %s", program_name, message);
290}
291
292static gboolean
293event_devel (void)
294{
295 static gboolean once = FALSE;
296 static gboolean devel = FALSE;
297
298 if (! once)
299 {
300 devel = g_getenv ("EDSIO_DEVEL") != NULL;
301 once = TRUE;
302 }
303
304 return devel;
305}
306
307static gboolean
308event_watch (GenericEvent* ev, GenericEventDef* def, const char* message)
309{
310 if (quiet && def->level <= EL_Warning)
311 return TRUE;
312
313 if (event_devel ())
314 fprintf (stderr, "%s:%d: %s\n", ev->srcfile, ev->srcline, message);
315 else
316 fprintf (stderr, "%s: %s\n", program_name, message);
317
318 return TRUE;
319}
320
321gint
322main (gint argc, gchar** argv)
323{
324 const Command *cmd = NULL;
325 gint c;
326 gint longind;
327
328 eventdelivery_event_watch_all (event_watch);
329
330 if (! xd_edsio_init ())
331 return 2;
332
333#ifdef __DJGPP__
334 /*
335 * (richdawe@bigfoot.com): Limit maximum memory usage to 87.5% of available
336 * physical memory for DJGPP. Otherwise the replacement for mmap() will
337 * exhaust memory and XDelta will fail.
338 */
339 {
340 unsigned long phys_free = _go32_dpmi_remaining_physical_memory();
341
342 max_mapped_pages = phys_free / XD_PAGE_SIZE;
343 max_mapped_pages %= 8;
344 max_mapped_pages *= 7;
345 }
346
347 /*
348 * (richdawe@bigfoot.com): Strip off the file extension 'exe' from
349 * program_name, since it makes the help messages look ugly.
350 */
351 {
352 char strip_ext[PATH_MAX + 1];
353 char *p;
354
355 strcpy (strip_ext, argv[0]);
356 p = strrchr (strip_ext, '.');
357 if ((p != NULL) && (strncasecmp (p + 1, "exe", 3) == 0))
358 *p = '\0';
359 program_name = g_basename (strip_ext);
360 }
361#else /* !__DJGPP__ */
362 program_name = g_basename (argv[0]);
363#endif /* __DJGPP__ */
364
365 g_log_set_handler (G_LOG_DOMAIN,
366 G_LOG_LEVEL_WARNING,
367 xd_error_func,
368 NULL);
369
370 if (argc < 2)
371 usage ();
372
373 for (cmd = commands; cmd->name; cmd += 1)
374 if (strcmp (cmd->name, argv[1]) == 0)
375 break;
376
377 if (strcmp (argv[1], "-h") == 0 ||
378 strcmp (argv[1], "--help") == 0)
379 help ();
380
381 if (strcmp (argv[1], "-v") == 0 ||
382 strcmp (argv[1], "--version") == 0)
383 version ();
384
385 if (!cmd->name)
386 {
387 xd_error ("unrecognized command\n");
388 help ();
389 }
390
391 argc -= 1;
392 argv += 1;
393
394 while ((c = getopt_long(argc,
395 argv,
396 "+nqphvVs:m:0123456789",
397 long_options,
398 &longind)) != EOF)
399 {
400 switch (c)
401 {
402 case 'q': quiet = TRUE; break;
403 case 'n': no_verify = TRUE; break;
404 case 'p': pristine = TRUE; break;
405 case 'V': verbose = TRUE; break;
406 case 's':
407 {
408 int ret;
409 int s = atoi (optarg);
410
411 if ((ret = xdp_set_query_size_pow (s)) && ! quiet)
412 {
413 xd_error ("illegal query size: %s\n", xdp_errno (ret));
414 }
415 }
416 break;
417 case 'm':
418 {
419 gchar* end = NULL;
420 glong l = strtol (optarg, &end, 0);
421
422 if (end && g_strcasecmp (end, "M") == 0)
423 l <<= 20;
424 else if (end && g_strcasecmp (end, "K") == 0)
425 l <<= 10;
426 else if (end || l < 0)
427 {
428 xd_error ("illegal maxmem argument %s\n", optarg);
429 return 2;
430 }
431
432#ifdef __DJGPP__
433 /*
434 * (richdawe@bigfoot.com): Old MS-DOS systems may have a maximum
435 * of 8MB memory == XD_PAGE_SIZE * 8. Therefore, do what the user
436 * asks for on MS-DOS.
437 */
438#else /* !__DJGPP__ */
439 l = MAX (l, XD_PAGE_SIZE * 8);
440#endif /* __DJGPP__ */
441
442 max_mapped_pages = l / XD_PAGE_SIZE;
443 }
444 break;
445 case 'h': help (); break;
446 case 'v': version (); break;
447 case '0': case '1': case '2': case '3': case '4':
448 case '5': case '6': case '7': case '8': case '9':
449 compress_level = c - '0';
450 break;
451 case '?':
452 default:
453 xd_error ("illegal argument, use --help for help\n");
454 return 2;
455 }
456 }
457
458 if (verbose && max_mapped_pages < G_MAXINT)
459 xd_error ("using %d kilobytes of buffer space\n", (max_mapped_pages * XD_PAGE_SIZE) >> 10);
460
461 argc -= optind;
462 argv += optind;
463
464 if (cmd->nargs >= 0 && argc != cmd->nargs)
465 {
466 xd_error ("wrong number of arguments\n");
467 help ();
468 return 2;
469 }
470
471 return (* cmd->func) (argc, argv);
472}
473
474/* Commands */
475
476#define READ_TYPE 1
477#define READ_NOSEEK_TYPE 1
478#define READ_SEEK_TYPE 3
479#define WRITE_TYPE 4
480
481/* Note to the casual reader: the filehandle implemented here is
482 * highly aware of the calling patterns of the Xdelta library. It
483 * also plays games with narrowing to implement several files in the
484 * same handle. So, if you try to modify or use this code, BEWARE.
485 * See the repository package for a complete implementation.
486 * In fact, its really quite a hack. */
487
488static gssize xd_handle_map_page (XdFileHandle *fh, guint pgno, const guint8** mem);
489static gboolean xd_handle_unmap_page (XdFileHandle *fh, guint pgno, const guint8** mem);
490
491static gboolean
492xd_fwrite (XdFileHandle* fh, const void* buf, gint nbyte)
493{
494 return fwrite (buf, nbyte, 1, fh->out) == 1;
495}
496
497static gboolean
498xd_fread (XdFileHandle* fh, void* buf, gint nbyte)
499{
500 return fread (buf, nbyte, 1, fh->in) == 1;
501}
502
503static gboolean
504xd_fclose (XdFileHandle* fh)
505{
506 return fclose (fh->out) == 0;
507}
508
509static gboolean
510xd_frclose (XdFileHandle* fh)
511{
512 return fclose (fh->in) == 0;
513}
514
515static gboolean
516xd_gzwrite (XdFileHandle* fh, const void* buf, gint nbyte)
517{
518 return gzwrite (fh->out, (void*) buf, nbyte) == nbyte;
519}
520
521static gboolean
522xd_gzread (XdFileHandle* fh, void* buf, gint nbyte)
523{
524 return gzread (fh->in, buf, nbyte) == nbyte;
525}
526
527static gboolean
528xd_gzclose (XdFileHandle* fh)
529{
530 return gzclose (fh->out) == Z_OK;
531}
532
533static gboolean
534xd_gzrclose (XdFileHandle* fh)
535{
536 return gzclose (fh->in) == Z_OK;
537}
538
539static void
540init_table (XdFileHandle* fh)
541{
542 fh->lru_table = g_ptr_array_new ();
543 fh->lru_chunk = g_mem_chunk_create(LRU, 1<<9, G_ALLOC_ONLY);
544 fh->lru_head = NULL;
545 fh->lru_tail = NULL;
546}
547
548static XdFileHandle*
549open_common (const char* name, const char* real_name)
550{
551 XdFileHandle* fh;
552
553 gint fd;
554 struct stat buf;
555
556 if ((fd = open (name, O_RDONLY | O_BINARY, 0)) < 0)
557 {
558 xd_error ("open %s failed: %s\n", name, g_strerror (errno));
559 return NULL;
560 }
561
562 if (stat (name, &buf) < 0)
563 {
564 xd_error ("stat %s failed: %s\n", name, g_strerror (errno));
565 return NULL;
566 }
567
568 /* S_ISREG() is not on Windows */
569 if ((buf.st_mode & S_IFMT) != S_IFREG)
570 {
571 xd_error ("%s is not a regular file\n", name);
572 return NULL;
573 }
574
575 fh = g_new0 (XdFileHandle, 1);
576
577 fh->fh.table = & xd_handle_table;
578 fh->name = real_name;
579 fh->fd = fd;
580 fh->length = buf.st_size;
581 fh->narrow_high = buf.st_size;
582
583 return fh;
584}
585
586static gboolean
587file_gzipped (const char* name, gboolean *is_compressed)
588{
589 FILE* f = fopen (name, FOPEN_READ_ARG);
590 guint8 buf[2];
591
592 (*is_compressed) = FALSE;
593
594 if (! f)
595 {
596 xd_error ("open %s failed: %s\n", name, g_strerror (errno));
597 return FALSE;
598 }
599
600 if (fread (buf, 2, 1, f) != 1)
601 return TRUE;
602
603#define GZIP_MAGIC1 037
604#define GZIP_MAGIC2 0213
605
606 if (buf[0] == GZIP_MAGIC1 && buf[1] == GZIP_MAGIC2)
607 (* is_compressed) = TRUE;
608
609 return TRUE;
610}
611
612static const char*
613xd_tmpname (void)
614{
615 const char* tmpdir = g_get_tmp_dir ();
616 GString* s;
617 gint x = getpid ();
618 static gint seq = 0;
619 struct stat buf;
620
621 s = g_string_new (NULL);
622
623 do
624 {
625 /*
626 * (richdawe@bigfoot.com): Limit temporary filenames to
627 * the MS-DOS 8+3 convention for DJGPP.
628 */
629 g_string_sprintf (s, "%s/xd-%05d.%03d", tmpdir, x, seq++);
630 }
631 while (lstat (s->str, &buf) == 0);
632
633 return s->str;
634}
635
636static const char*
637file_gunzip (const char* name)
638{
639 const char* new_name = xd_tmpname ();
640 FILE* out = fopen (new_name, FOPEN_WRITE_ARG);
641 gzFile in = gzopen (name, "rb");
642 guint8 buf[1024];
643 int nread, ret;
644
645 while ((nread = gzread (in, buf, 1024)) > 0)
646 {
647 if (fwrite (buf, nread, 1, out) != 1)
648 {
649 xd_error ("write %s failed (during uncompression): %s\n", new_name, g_strerror (errno));
650 return NULL;
651 }
652 }
653
654 if (nread < 0)
655 {
656 xd_error ("gzread %s failed\n", name);
657 return NULL;
658 }
659
660 ret = gzclose (in);
661 if (ret != Z_OK)
662 {
663 xd_error ("gzip input decompression failed: %s\n", name);
664 return NULL;
665 }
666
667 if (fclose (out))
668 {
669 xd_error ("close %s failed (during uncompression): %s\n", new_name, g_strerror (errno));
670 return NULL;
671 }
672
673 return new_name;
674}
675
676static XdFileHandle*
677open_read_noseek_handle (const char* name, gboolean* is_compressed, gboolean will_read, gboolean honor_pristine)
678{
679 XdFileHandle* fh;
680 const char* name0 = name;
681
682 /* we _could_ stream-read this file if compressed, but it adds a
683 * lot of complexity. the library can handle it, just set the
684 * length to (XDELTA_MAX_FILE_LEN-1) and make sure that the end
685 * of file condition is set when on the last page. However, I
686 * don't feel like it. */
687 if (honor_pristine && pristine)
688 *is_compressed = FALSE;
689 else
690 {
691 if (! file_gzipped (name, is_compressed))
692 return NULL;
693 }
694
695 if ((* is_compressed) && ! (name = file_gunzip (name)))
696 return NULL;
697
698 if (! (fh = open_common (name, name0)))
699 return NULL;
700
701 fh->type = READ_NOSEEK_TYPE;
702
703 edsio_md5_init (&fh->ctx);
704
705 if (*is_compressed)
706 fh->cleanup = name;
707
708 if (will_read)
709 {
710 g_assert (fh->fd >= 0);
711 if (! (fh->in = fdopen (dup (fh->fd), FOPEN_READ_ARG)))
712 {
713 xd_error ("fdopen: %s\n", g_strerror (errno));
714 return NULL;
715 }
716 fh->in_read = &xd_fread;
717 fh->in_close = &xd_frclose;
718 }
719 else
720 {
721 init_table (fh);
722 }
723
724 return fh;
725}
726
727static void
728xd_read_close (XdFileHandle* fh)
729{
730 /*
731 * (richdawe@bigfoot.com): On Unix you can unlink a file while it is
732 * still open. On MS-DOS this can lead to filesystem corruption. Close
733 * the file before unlinking it.
734 */
735 close (fh->fd);
736
737 if (fh->cleanup)
738 unlink (fh->cleanup);
739
740 if (fh->in)
741 (*fh->in_close) (fh);
742}
743
744static XdFileHandle*
745open_read_seek_handle (const char* name, gboolean* is_compressed, gboolean honor_pristine)
746{
747 XdFileHandle* fh;
748 const char* name0 = name;
749
750 if (honor_pristine && pristine)
751 *is_compressed = FALSE;
752 else
753 {
754 if (! file_gzipped (name, is_compressed))
755 return NULL;
756 }
757
758 if ((* is_compressed) && ! (name = file_gunzip (name)))
759 return NULL;
760
761 if (! (fh = open_common (name, name0)))
762 return NULL;
763
764 fh->type = READ_SEEK_TYPE;
765
766 if (*is_compressed)
767 fh->cleanup = name;
768
769 init_table (fh);
770
771 edsio_md5_init (&fh->ctx);
772
773 return fh;
774}
775
776static XdFileHandle*
777open_write_handle (int fd, const char* name)
778{
779 XdFileHandle* fh = g_new0 (XdFileHandle, 1);
780 int nfd;
781
782 fh->fh.table = & xd_handle_table;
783 fh->out_fd = fd;
784 fh->out_write = &xd_fwrite;
785 fh->out_close = &xd_fclose;
786
787 g_assert (fh->out_fd >= 0);
788
789 nfd = dup (fh->out_fd);
790
791 if (! (fh->out = fdopen (nfd, FOPEN_WRITE_ARG)))
792 {
793 xd_error ("fdopen %s failed: %s\n", name, g_strerror (errno));
794 return NULL;
795 }
796
797 fh->type = WRITE_TYPE;
798 fh->name = name;
799
800 edsio_md5_init (&fh->ctx);
801
802 return fh;
803}
804
805static gint
806xd_begin_compression (XdFileHandle* fh)
807{
808 gint filepos, nfd;
809
810 if (compress_level == 0)
811 return fh->real_length;
812
813 if (! (fh->out_close) (fh))
814 {
815 xd_error ("fclose failed: %s\n", g_strerror (errno));
816 return -1;
817 }
818
819 filepos = lseek (fh->out_fd, 0, SEEK_END);
820
821 if (filepos < 0)
822 {
823 xd_error ("lseek failed: %s\n", g_strerror (errno));
824 return -1;
825 }
826
827 g_assert (fh->out_fd >= 0);
828
829 nfd = dup (fh->out_fd);
830
831 fh->out = gzdopen (nfd, "wb");
832 fh->out_write = &xd_gzwrite;
833 fh->out_close = &xd_gzclose;
834
835 if (! fh->out)
836 {
837 xd_error ("gzdopen failed: %s\n", g_strerror (errno));
838 return -1;
839 }
840
841 if (gzsetparams(fh->out, compress_level, Z_DEFAULT_STRATEGY) != Z_OK)
842 {
843 int foo;
844 xd_error ("gzsetparams failed: %s\n", gzerror (fh->out, &foo));
845 return -1;
846 }
847
848 return filepos;
849}
850
851static gboolean
852xd_end_compression (XdFileHandle* fh)
853{
854 if (compress_level == 0)
855 return TRUE;
856
857 if (! (fh->out_close) (fh))
858 {
859 xd_error ("fdclose failed: %s\n", g_strerror (errno));
860 return FALSE;
861 }
862
863 if (lseek (fh->out_fd, 0, SEEK_END) < 0)
864 {
865 xd_error ("lseek failed: %s\n", g_strerror (errno));
866 return FALSE;
867 }
868
869 g_assert (fh->out_fd >= 0);
870 fh->out = fdopen (dup (fh->out_fd), FOPEN_WRITE_ARG);
871 fh->out_write = &xd_fwrite;
872 fh->out_close = &xd_fclose;
873
874 if (! fh->out)
875 {
876 xd_error ("fdopen failed: %s\n", g_strerror (errno));
877 return FALSE;
878 }
879
880 return TRUE;
881}
882
883static gssize
884xd_handle_length (XdFileHandle *fh)
885{
886 if (fh->in_compressed)
887 return fh->current_pos;
888 else
889 return fh->narrow_high - fh->narrow_low;
890}
891
892static gssize
893xd_handle_pages (XdFileHandle *fh)
894{
895 g_assert (fh->type & READ_TYPE);
896 return xd_handle_length (fh) / XD_PAGE_SIZE;
897}
898
899static gssize
900xd_handle_pagesize (XdFileHandle *fh)
901{
902 g_assert (fh->type & READ_TYPE);
903 return XD_PAGE_SIZE;
904}
905
906static gint
907on_page (XdFileHandle* fh, guint pgno)
908{
909 if (pgno > xd_handle_pages (fh))
910 return -1;
911
912 if (pgno == xd_handle_pages (fh))
913 return xd_handle_length (fh) % XD_PAGE_SIZE;
914
915 return XD_PAGE_SIZE;
916}
917
918static gboolean
919xd_handle_close (XdFileHandle *fh, gint ignore)
920{
921 /* this is really a reset for writable files */
922
923 if (fh->type == WRITE_TYPE)
924 {
925 if (fh->reset_length_next_write)
926 {
927 fh->reset_length_next_write = FALSE;
928 fh->length = 0;
929 fh->narrow_high = 0;
930 }
931
932 fh->reset_length_next_write = TRUE;
933 edsio_md5_final (fh->md5, &fh->ctx);
934 edsio_md5_init (&fh->ctx);
935 }
936 else if (fh->in)
937 {
938 edsio_md5_final (fh->md5, &fh->ctx);
939 edsio_md5_init (&fh->ctx);
940 fh->md5_good = FALSE;
941 }
942
943 return TRUE;
944}
945
946static const guint8*
947xd_handle_checksum_md5 (XdFileHandle *fh)
948{
949 if (fh->in && ! fh->md5_good)
950 {
951 edsio_md5_final (fh->md5, &fh->ctx);
952 fh->md5_good = TRUE;
953 }
954 else if (fh->type != WRITE_TYPE && !fh->in)
955 {
956 const guint8* page;
957
958 while (fh->md5_page <= xd_handle_pages (fh))
959 {
960 gint pgno = fh->md5_page;
961 gint onpage;
962
963 if ((onpage = xd_handle_map_page (fh, pgno, &page)) < 0)
964 return NULL;
965
966 if (pgno == fh->md5_page)
967 {
968 fh->md5_page += 1;
969 edsio_md5_update (&fh->ctx, page, onpage);
970
971 if (fh->md5_page > xd_handle_pages (fh))
972 edsio_md5_final (fh->md5, &fh->ctx);
973 }
974
975 if (! xd_handle_unmap_page (fh, pgno, &page))
976 return NULL;
977 }
978 }
979
980 return g_memdup (fh->md5, 16);
981}
982
983static gboolean
984xd_handle_set_pos (XdFileHandle *fh, guint pos)
985{
986 if (fh->current_pos == pos + fh->narrow_low)
987 return TRUE;
988
989 if (pos + fh->narrow_low > fh->narrow_high)
990 {
991 xd_error ("unexpected EOF in %s\n", fh->name);
992 return FALSE;
993 }
994
995 fh->current_pos = pos + fh->narrow_low;
996
997 if (fseek (fh->in, fh->current_pos, SEEK_SET))
998 {
999 xd_error ("fseek failed: %s\n", g_strerror (errno));
1000 return FALSE;
1001 }
1002
1003 return TRUE;
1004}
1005
1006static gboolean
1007xd_handle_narrow (XdFileHandle* fh, guint low, guint high, gboolean compressed)
1008{
1009 if (high > fh->length)
1010 {
1011 xd_error ("%s: corrupt or truncated delta\n", fh->name);
1012 return FALSE;
1013 }
1014
1015 fh->narrow_low = low;
1016 fh->narrow_high = high;
1017
1018 edsio_md5_init (&fh->ctx);
1019
1020 if (compressed)
1021 {
1022 (* fh->in_close) (fh);
1023
1024 if (lseek (fh->fd, low, SEEK_SET) < 0)
1025 {
1026 xd_error ("%s: corrupt or truncated delta: cannot seek to %d: %s\n", fh->name, low, g_strerror (errno));
1027 return FALSE;
1028 }
1029
1030 g_assert (fh->fd >= 0);
1031 fh->in = gzdopen (dup (fh->fd), "rb");
1032 fh->in_read = &xd_gzread;
1033 fh->in_close = &xd_gzrclose;
1034 fh->in_compressed = TRUE;
1035 fh->current_pos = 0;
1036
1037 if (! fh->in)
1038 {
1039 xd_error ("gzdopen failed: %s\n", g_strerror (errno));
1040 return -1;
1041 }
1042 }
1043 else
1044 {
1045 if (! xd_handle_set_pos (fh, 0))
1046 return FALSE;
1047 }
1048
1049 return TRUE;
1050}
1051
1052static guint
1053xd_handle_get_pos (XdFileHandle* fh)
1054{
1055 return fh->current_pos - fh->narrow_low;
1056}
1057
1058static const gchar*
1059xd_handle_name (XdFileHandle *fh)
1060{
1061 return g_strdup (fh->name);
1062}
1063
1064static gssize
1065xd_handle_read (XdFileHandle *fh, guint8 *buf, gsize nbyte)
1066{
1067 if (nbyte == 0)
1068 return 0;
1069
1070 if (! (fh->in_read) (fh, buf, nbyte)) /* This is suspicious */
1071 {
1072 xd_error ("read failed: %s\n", g_strerror (errno));
1073 return -1;
1074 }
1075
1076 if (!no_verify)
1077 edsio_md5_update (&fh->ctx, buf, nbyte);
1078
1079 fh->current_pos += nbyte;
1080
1081 return nbyte;
1082}
1083
1084static gboolean
1085xd_handle_write (XdFileHandle *fh, const guint8 *buf, gsize nbyte)
1086{
1087 g_assert (fh->type == WRITE_TYPE);
1088
1089 if (fh->reset_length_next_write)
1090 {
1091 fh->reset_length_next_write = FALSE;
1092 fh->length = 0;
1093 fh->narrow_high = 0;
1094 }
1095
1096 if (! no_verify)
1097 edsio_md5_update (&fh->ctx, buf, nbyte);
1098
1099 if (! (*fh->out_write) (fh, buf, nbyte))
1100 {
1101 xd_error ("write failed: %s\n", g_strerror (errno));
1102 return FALSE;
1103 }
1104
1105 fh->length += nbyte;
1106 fh->real_length += nbyte;
1107 fh->narrow_high += nbyte;
1108
1109 return TRUE;
1110}
1111
1112static gboolean
1113xd_handle_really_close (XdFileHandle *fh)
1114{
1115 g_assert (fh->type == WRITE_TYPE);
1116
1117 if (! (* fh->out_close) (fh) || close (fh->out_fd) < 0)
1118 {
1119 xd_error ("write failed: %s\n", g_strerror (errno));
1120 return FALSE;
1121 }
1122
1123 return TRUE;
1124}
1125
1126static LRU*
1127pull_lru (XdFileHandle* fh, LRU* lru)
1128{
1129 if (lru->next && lru->prev)
1130 {
1131 lru->next->prev = lru->prev;
1132 lru->prev->next = lru->next;
1133 }
1134 else if (lru->next)
1135 {
1136 fh->lru_tail = lru->next;
1137 lru->next->prev = NULL;
1138 }
1139 else if (lru->prev)
1140 {
1141 fh->lru_head = lru->prev;
1142 lru->prev->next = NULL;
1143 }
1144 else
1145 {
1146 fh->lru_head = NULL;
1147 fh->lru_tail = NULL;
1148 }
1149
1150 lru->next = NULL;
1151 lru->prev = NULL;
1152
1153 return lru;
1154}
1155
1156static gboolean
1157really_free_one_page (XdFileHandle* fh)
1158{
1159 LRU *lru = fh->lru_tail;
1160
1161 for (; lru; lru = lru->prev)
1162 {
1163 gint to_unmap;
1164 LRU *lru_dead;
1165
1166 if (lru->refs > 0)
1167 continue;
1168
1169 lru_dead = pull_lru (fh, lru);
1170
1171 g_assert (lru_dead->buffer);
1172
1173 to_unmap = on_page (fh, lru_dead->page);
1174
1175 fh->lru_count -= 1;
1176
1177 if (to_unmap > 0)
1178 {
1179#ifdef WINHACK
1180 g_free (lru_dead->buffer);
1181#else
1182 if (munmap (lru_dead->buffer, to_unmap))
1183 {
1184 xd_error ("munmap failed: %s\n", g_strerror (errno));
1185 return FALSE;
1186 }
1187#endif /* WINHACK */
1188 }
1189
1190 lru_dead->buffer = NULL;
1191
1192 return TRUE;
1193 }
1194
1195 return TRUE;
1196}
1197
1198#if 0
1199static void
1200print_lru (XdFileHandle* fh)
1201{
1202 LRU* lru = fh->lru_head;
1203
1204 for (; lru; lru = lru->prev)
1205 {
1206 g_print ("page %d buffer %p\n", lru->page, lru->buffer);
1207
1208 if (! lru->prev && lru != fh->lru_tail)
1209 g_print ("incorrect lru_tail\n");
1210 }
1211}
1212#endif
1213
1214static gboolean
1215make_lru_room (XdFileHandle* fh)
1216{
1217 if (fh->lru_count == max_mapped_pages)
1218 {
1219 if (! really_free_one_page (fh))
1220 return FALSE;
1221 }
1222
1223 g_assert (fh->lru_count < max_mapped_pages);
1224
1225 return TRUE;
1226}
1227
1228/*#define DEBUG_MAP*/
1229
1230static gssize
1231xd_handle_map_page (XdFileHandle *fh, guint pgno, const guint8** mem)
1232{
1233 LRU* lru;
1234 guint to_map;
1235
1236#ifdef DEBUG_MAP
1237 g_print ("map %p:%d\n", fh, pgno);
1238#endif
1239
1240 g_assert (fh->type & READ_TYPE);
1241
1242 if (fh->lru_table->len < (pgno + 1))
1243 {
1244 gint olen = fh->lru_table->len;
1245
1246 g_ptr_array_set_size (fh->lru_table, pgno + 1);
1247
1248 while (olen <= pgno)
1249 fh->lru_table->pdata[olen++] = NULL;
1250 }
1251
1252 lru = fh->lru_table->pdata[pgno];
1253
1254 if (! lru)
1255 {
1256 lru = g_chunk_new0 (LRU, fh->lru_chunk);
1257 fh->lru_table->pdata[pgno] = lru;
1258 lru->page = pgno;
1259 }
1260 else if (lru->buffer)
1261 {
1262 pull_lru (fh, lru);
1263 }
1264
1265 lru->prev = fh->lru_head;
1266 lru->next = NULL;
1267
1268 fh->lru_head = lru;
1269
1270 if (lru->prev)
1271 lru->prev->next = lru;
1272
1273 if (! fh->lru_tail)
1274 fh->lru_tail = lru;
1275
1276 to_map = on_page (fh, pgno);
1277
1278 if (to_map < 0)
1279 {
1280 xd_error ("unexpected EOF in %s\n", fh->name);
1281 return -1;
1282 }
1283
1284 if (! lru->buffer)
1285 {
1286 if (! make_lru_room (fh))
1287 return -1;
1288
1289 fh->lru_count += 1;
1290
1291 if (to_map > 0)
1292 {
1293#ifdef WINHACK
1294 lru->buffer = g_malloc (to_map);
1295
1296 if (lseek (fh->fd, pgno * XD_PAGE_SIZE, SEEK_SET) < 0)
1297 {
1298 xd_error ("lseek failed: %s\n", g_strerror (errno));
1299 return -1;
1300 }
1301
1302 if (read (fh->fd, lru->buffer, to_map) != to_map)
1303 {
1304 xd_error ("read failed: %s\n", g_strerror (errno));
1305 return -1;
1306 }
1307#else
1308 if (! (lru->buffer = mmap (NULL, to_map, PROT_READ, MAP_PRIVATE, fh->fd, pgno * XD_PAGE_SIZE)))
1309 {
1310 xd_error ("mmap failed: %s\n", g_strerror (errno));
1311 return -1;
1312 }
1313#endif
1314 }
1315 else
1316 {
1317 lru->buffer = (void*) -1;
1318 }
1319
1320 if (pgno == fh->md5_page)
1321 {
1322 if (! no_verify)
1323 edsio_md5_update (&fh->ctx, lru->buffer, to_map);
1324 fh->md5_page += 1;
1325
1326 if (fh->md5_page > xd_handle_pages (fh))
1327 edsio_md5_final (fh->md5, &fh->ctx);
1328 }
1329 }
1330
1331 (*mem) = lru->buffer;
1332
1333 lru->refs += 1;
1334 fh->lru_outstanding_refs += 1;
1335
1336 return to_map;
1337}
1338
1339static gboolean
1340xd_handle_unmap_page (XdFileHandle *fh, guint pgno, const guint8** mem)
1341{
1342 LRU* lru;
1343
1344#ifdef DEBUG_MAP
1345 g_print ("unmap %p:%d\n", fh, pgno);
1346#endif
1347
1348 g_assert (fh->type & READ_TYPE);
1349
1350 g_assert (pgno < fh->lru_table->len);
1351
1352 lru = fh->lru_table->pdata[pgno];
1353
1354 g_assert (lru && lru->refs > 0);
1355
1356 g_assert (lru->buffer == (*mem));
1357
1358 (*mem) = NULL;
1359
1360 lru->refs -= 1;
1361 fh->lru_outstanding_refs += 1;
1362
1363 if (lru->refs == 0 && fh->type == READ_NOSEEK_TYPE)
1364 {
1365 pull_lru (fh, lru);
1366
1367 lru->next = fh->lru_tail;
1368 if (lru->next) lru->next->prev = lru;
1369 lru->prev = NULL;
1370 fh->lru_tail = lru;
1371
1372 if (! really_free_one_page (fh))
1373 return FALSE;
1374 }
1375
1376 return TRUE;
1377}
1378
1379static gboolean
1380xd_handle_copy (XdFileHandle *from, XdFileHandle *to, guint off, guint len)
1381{
1382 if (from->in)
1383 {
1384 guint8 buf[1024];
1385
1386 /*if (! xd_handle_set_pos (from, off))
1387 return FALSE;*/
1388
1389 while (len > 0)
1390 {
1391 guint r = MIN (1024, len);
1392
1393 if (xd_handle_read (from, buf, r) != r)
1394 return FALSE;
1395
1396 if (! xd_handle_write (to, buf, r))
1397 return FALSE;
1398
1399 len -= r;
1400 }
1401 }
1402 else
1403 {
1404 while (len > 0)
1405 {
1406 guint off_page = off / XD_PAGE_SIZE;
1407 guint off_off = off % XD_PAGE_SIZE;
1408
1409 gint on = on_page (from, off_page);
1410 guint rem;
1411 guint copy;
1412
1413 if (on <= 0)
1414 {
1415 xd_error ("unexpected EOF in %s\n", from->name);
1416 return FALSE;
1417 }
1418
1419 rem = on - off_off;
1420 copy = MIN (len, rem);
1421
1422 if (from->copy_pgno != off_page &&
1423 from->copy_page &&
1424 ! xd_handle_unmap_page (from, from->copy_pgno, &from->copy_page))
1425 return FALSE;
1426
1427 from->copy_pgno = off_page;
1428
1429 if (xd_handle_map_page (from, off_page, &from->copy_page) < 0)
1430 return FALSE;
1431
1432 if (! xd_handle_write (to, from->copy_page + off_off, copy))
1433 return FALSE;
1434
1435 if (! xd_handle_unmap_page (from, off_page, &from->copy_page))
1436 return FALSE;
1437
1438 len -= copy;
1439 off += copy;
1440 }
1441 }
1442
1443 return TRUE;
1444}
1445
1446static gboolean
1447xd_handle_putui (XdFileHandle *fh, guint32 i)
1448{
1449 guint32 hi = g_htonl (i);
1450
1451 return xd_handle_write (fh, (guint8*)&hi, 4);
1452}
1453
1454static gboolean
1455xd_handle_getui (XdFileHandle *fh, guint32* i)
1456{
1457 if (xd_handle_read (fh, (guint8*)i, 4) != 4)
1458 return FALSE;
1459
1460 *i = g_ntohl (*i);
1461
1462 return TRUE;
1463}
1464
1465static HandleFuncTable xd_handle_table =
1466{
1467 (gssize (*) (FileHandle *fh)) xd_handle_length,
1468 (gssize (*) (FileHandle *fh)) xd_handle_pages,
1469 (gssize (*) (FileHandle *fh)) xd_handle_pagesize,
1470 (gssize (*) (FileHandle *fh, guint pgno, const guint8** mem)) xd_handle_map_page,
1471 (gboolean (*) (FileHandle *fh, guint pgno, const guint8** mem)) xd_handle_unmap_page,
1472 (const guint8* (*) (FileHandle *fh)) xd_handle_checksum_md5,
1473
1474 (gboolean (*) (FileHandle *fh, gint flags)) xd_handle_close,
1475
1476 (gboolean (*) (FileHandle *fh, const guint8 *buf, gsize nbyte)) xd_handle_write,
1477 (gboolean (*) (FileHandle *from, FileHandle *to, guint off, guint len)) xd_handle_copy,
1478
1479 (gboolean (*) (FileHandle *fh, guint32* i)) xd_handle_getui,
1480 (gboolean (*) (FileHandle *fh, guint32 i)) xd_handle_putui,
1481 (gssize (*) (FileHandle *fh, guint8 *buf, gsize nbyte)) xd_handle_read,
1482 (const gchar* (*) (FileHandle *fh)) xd_handle_name,
1483};
1484
1485static void
1486htonl_array (guint32* array, gint len)
1487{
1488 gint i;
1489
1490 for (i = 0; i < len; i += 1)
1491 array[i] = g_htonl(array[i]);
1492}
1493
1494static void
1495ntohl_array (guint32* array, gint len)
1496{
1497 gint i;
1498
1499 for (i = 0; i < len; i += 1)
1500 array[i] = g_ntohl(array[i]);
1501}
1502
1503static gint
1504delta_command (gint argc, gchar** argv)
1505{
1506 gint patch_out_fd;
1507 const char* patch_out_name;
1508 XdFileHandle *from, *to, *out;
1509 XdeltaGenerator* gen;
1510 XdeltaSource* src;
1511 XdeltaControl* cont;
1512 gboolean from_is_compressed = FALSE, to_is_compressed = FALSE;
1513 guint32 control_offset, header_offset;
1514 const char* from_name, *to_name;
1515 guint32 header_space[HEADER_WORDS];
1516 int fd;
1517
1518 memset (header_space, 0, sizeof (header_space));
1519
1520 if (argc != 3)
1521 {
1522 xd_error ("usage: %s delta fromfile tofile patchfile\n", program_name);
1523 return 2;
1524 }
1525
1526 if (verbose)
1527 {
1528 xd_error ("using block size: %d bytes\n", xdp_blocksize ());
1529 }
1530
1531 if (! (from = open_read_seek_handle (argv[0], &from_is_compressed, TRUE)))
1532 return 2;
1533
1534 if (! (to = open_read_noseek_handle (argv[1], &to_is_compressed, FALSE, TRUE)))
1535 return 2;
1536
1537 // Note: I tried support to patches to stdout, but it broke when
1538 // compression was added. Sigh
1539 fd = open (argv[2], O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
1540
1541 if (fd < 0)
1542 {
1543 xd_error ("open %s failed: %s\n", argv[2], g_strerror (errno));
1544 return 2;
1545 }
1546
1547 patch_out_fd = fd;
1548 patch_out_name = argv[2];
1549
1550 from_name = g_basename (argv[0]);
1551 to_name = g_basename (argv[1]);
1552
1553 if (! (out = open_write_handle (patch_out_fd, patch_out_name)))
1554 return 2;
1555
1556 if (! (gen = xdp_generator_new ()))
1557 return 2;
1558
1559 if (! (src = xdp_source_new (from_name, (FileHandle*) from, NULL, NULL)))
1560 return 2;
1561
1562 xdp_source_add (gen, src);
1563
1564 if (! xd_handle_write (out, XDELTA_PREFIX, XDELTA_PREFIX_LEN))
1565 return 2;
1566
1567 /* compute the header */
1568 header_space[0] = 0;
1569
1570 if (no_verify) header_space[0] |= FLAG_NO_VERIFY;
1571 if (from_is_compressed) header_space[0] |= FLAG_FROM_COMPRESSED;
1572 if (to_is_compressed) header_space[0] |= FLAG_TO_COMPRESSED;
1573 if (compress_level != 0) header_space[0] |= FLAG_PATCH_COMPRESSED;
1574
1575 header_space[1] = strlen (from_name) << 16 | strlen (to_name);
1576 /* end compute the header */
1577
1578 htonl_array (header_space, HEADER_WORDS);
1579
1580 if (! xd_handle_write (out, (guint8*) header_space, HEADER_SPACE))
1581 return 2;
1582
1583 if (! xd_handle_write (out, from_name, strlen (from_name)))
1584 return 2;
1585
1586 if (! xd_handle_write (out, to_name, strlen (to_name)))
1587 return 2;
1588
1589 if (! xd_handle_close (out, 0))
1590 return 2;
1591
1592 if ((header_offset = xd_begin_compression (out)) < 0)
1593 return 2;
1594
1595 if (! (cont = xdp_generate_delta (gen, (FileHandle*) to, NULL, (FileHandle*) out)))
1596 return 2;
1597
1598#if 0
1599 {
1600 guint32 pos = 0;
1601 gint i, l = cont->inst_len;
1602
1603 for (i = 0; i < l; i += 1)
1604 {
1605 XdeltaInstruction *inst = cont->inst + i;
1606 if (inst->index == 0) {
1607 inst->index = 999999999;
1608 inst->offset = 999999999;
1609 } else {
1610 inst->index = pos;
1611 }
1612 pos += inst->length;
1613 }
1614 }
1615 serializeio_print_xdeltacontrol_obj (cont, 0);
1616#endif
1617
1618 if (cont->has_data && cont->has_data == cont->source_info_len)
1619 {
1620 if (! quiet)
1621 xd_error ("warning: no matches found in from file, patch will apply without it\n");
1622 }
1623
1624 if (! xd_handle_close (out, 0))
1625 return 2;
1626
1627 if ((control_offset = xd_begin_compression (out)) < 0)
1628 return 2;
1629
1630 if (! xdp_control_write (cont, (FileHandle*) out))
1631 return 2;
1632
1633 if (! xd_end_compression (out))
1634 return 2;
1635
1636 if (! xd_handle_putui (out, control_offset))
1637 return 2;
1638
1639 if (! xd_handle_write (out, XDELTA_PREFIX, XDELTA_PREFIX_LEN))
1640 return 2;
1641
1642 xd_read_close (from);
1643 xd_read_close (to);
1644
1645 if (! xd_handle_really_close (out))
1646 return 2;
1647
1648 xdp_generator_free (gen);
1649
1650 /* Note: prior to 1.1.5:
1651 * return control_offset != header_offset;
1652 */
1653 return 0;
1654}
1655
1656static XdeltaPatch*
1657process_patch (const char* name)
1658{
1659 XdeltaPatch* patch;
1660 guint total_trailer;
1661
1662 patch = g_new0 (XdeltaPatch, 1);
1663
1664 patch->patch_name = name;
1665
1666 /* Strictly speaking, I'm violating the intended semantics of noseek here.
1667 * It will seek the file, which is not in fact checked in the map/unmap
1668 * logic above. This only means that it will not cache pages of this file
1669 * since it will be read piecewise sequentially. */
1670 if (! (patch->patch_in = open_read_noseek_handle (name, &patch->patch_is_compressed, TRUE, TRUE)))
1671 return NULL;
1672
1673 if (xd_handle_read (patch->patch_in, patch->magic_buf, XDELTA_PREFIX_LEN) != XDELTA_PREFIX_LEN)
1674 return NULL;
1675
1676 if (xd_handle_read (patch->patch_in, (guint8*) patch->header_space, HEADER_SPACE) != HEADER_SPACE)
1677 return NULL;
1678
1679 ntohl_array (patch->header_space, HEADER_WORDS);
1680
1681 if (strncmp (patch->magic_buf, XDELTA_110_PREFIX, XDELTA_PREFIX_LEN) == 0)
1682 {
1683 patch->has_trailer = TRUE;
1684 patch->patch_version = "1.1";
1685 }
1686 else if (strncmp (patch->magic_buf, XDELTA_104_PREFIX, XDELTA_PREFIX_LEN) == 0)
1687 {
1688 patch->has_trailer = TRUE;
1689 patch->patch_version = "1.0.4";
1690 }
1691 else if (strncmp (patch->magic_buf, XDELTA_100_PREFIX, XDELTA_PREFIX_LEN) == 0)
1692 {
1693 patch->patch_version = "1.0";
1694 }
1695 else if (strncmp (patch->magic_buf, XDELTA_020_PREFIX, XDELTA_PREFIX_LEN) == 0)
1696 goto nosupport;
1697 else if (strncmp (patch->magic_buf, XDELTA_018_PREFIX, XDELTA_PREFIX_LEN) == 0)
1698 goto nosupport;
1699 else if (strncmp (patch->magic_buf, XDELTA_014_PREFIX, XDELTA_PREFIX_LEN) == 0)
1700 goto nosupport;
1701 else
1702 {
1703 xd_error ("%s: bad magic number: not a valid delta\n", name);
1704 return NULL;
1705 }
1706
1707 patch->patch_flags = patch->header_space[0];
1708
1709 if (no_verify)
1710 xd_error ("--noverify is only accepted when creating a delta\n");
1711
1712 if (patch->patch_flags & FLAG_NO_VERIFY)
1713 no_verify = TRUE;
1714 else
1715 no_verify = FALSE;
1716
1717 patch->from_name_len = patch->header_space[1] >> 16;
1718 patch->to_name_len = patch->header_space[1] & 0xffff;
1719
1720 patch->from_name = g_malloc (patch->from_name_len+1);
1721 patch->to_name = g_malloc (patch->to_name_len+1);
1722
1723 patch->from_name[patch->from_name_len] = 0;
1724 patch->to_name[patch->to_name_len] = 0;
1725
1726 if (xd_handle_read (patch->patch_in, patch->from_name, patch->from_name_len) != patch->from_name_len)
1727 return NULL;
1728
1729 if (xd_handle_read (patch->patch_in, patch->to_name, patch->to_name_len) != patch->to_name_len)
1730 return NULL;
1731
1732 patch->header_offset = xd_handle_get_pos (patch->patch_in);
1733
1734 total_trailer = 4 + (patch->has_trailer ? XDELTA_PREFIX_LEN : 0);
1735
1736 if (! xd_handle_set_pos (patch->patch_in, xd_handle_length (patch->patch_in) - total_trailer))
1737 return NULL;
1738
1739 if (! xd_handle_getui (patch->patch_in, &patch->control_offset))
1740 return NULL;
1741
1742 if (patch->has_trailer)
1743 {
1744 guint8 trailer_buf[XDELTA_PREFIX_LEN];
1745
1746 if (xd_handle_read (patch->patch_in, trailer_buf, XDELTA_PREFIX_LEN) != XDELTA_PREFIX_LEN)
1747 return NULL;
1748
1749 if (strncmp (trailer_buf, patch->magic_buf, XDELTA_PREFIX_LEN) != 0)
1750 {
1751 xd_error ("%s: bad trailing magic number, delta is corrupt\n", name);
1752 return NULL;
1753 }
1754 }
1755
1756 if (! xd_handle_narrow (patch->patch_in, patch->control_offset,
1757 xd_handle_length (patch->patch_in) - total_trailer,
1758 patch->patch_flags & FLAG_PATCH_COMPRESSED))
1759 return NULL;
1760
1761 if (! (patch->cont = xdp_control_read ((FileHandle*) patch->patch_in)))
1762 return NULL;
1763
1764 if (patch->cont->source_info_len > 0)
1765 {
1766 XdeltaSourceInfo* info = patch->cont->source_info[0];
1767
1768 if (info->isdata)
1769 patch->data_source = info;
1770 else
1771 {
1772 patch->from_source = info;
1773
1774 if (patch->cont->source_info_len > 1)
1775 {
1776 xd_generate_void_event (EC_XdIncompatibleDelta);
1777 return NULL;
1778 }
1779 }
1780 }
1781
1782 if (patch->cont->source_info_len > 1)
1783 {
1784 patch->from_source = patch->cont->source_info[1];
1785 }
1786
1787 if (patch->cont->source_info_len > 2)
1788 {
1789 xd_generate_void_event (EC_XdIncompatibleDelta);
1790 return NULL;
1791 }
1792
1793 if (! xd_handle_narrow (patch->patch_in,
1794 patch->header_offset,
1795 patch->control_offset,
1796 patch->patch_flags & FLAG_PATCH_COMPRESSED))
1797 return NULL;
1798
1799 return patch;
1800
1801 nosupport:
1802
1803 xd_error ("delta format is unsupported (too old)\n");
1804 return NULL;
1805}
1806
1807static gint
1808info_command (gint argc, gchar** argv)
1809{
1810 XdeltaPatch* patch;
1811 char buf[33];
1812 int i;
1813 XdeltaSourceInfo* si;
1814
1815 if (! (patch = process_patch (argv[0])))
1816 return 2;
1817
1818 xd_error_file = stdout;
1819
1820 xd_error ("version %s found patch version %s in %s%s\n",
1821 xdelta_version,
1822 patch->patch_version,
1823 patch->patch_name,
1824 patch->patch_flags & FLAG_PATCH_COMPRESSED ? " (compressed)" : "");
1825
1826 if (patch->patch_flags & FLAG_NO_VERIFY)
1827 xd_error ("generated with --noverify\n");
1828
1829 if (patch->patch_flags & FLAG_FROM_COMPRESSED)
1830 xd_error ("generated with a gzipped FROM file\n");
1831
1832 if (patch->patch_flags & FLAG_TO_COMPRESSED)
1833 xd_error ("generated with a gzipped TO file\n");
1834
1835 edsio_md5_to_string (patch->cont->to_md5, buf);
1836
1837 xd_error ("output name: %s\n", patch->to_name);
1838 xd_error ("output length: %d\n", patch->cont->to_len);
1839 xd_error ("output md5: %s\n", buf);
1840
1841 xd_error ("patch from segments: %d\n", patch->cont->source_info_len);
1842
1843 xd_error ("MD5\t\t\t\t\tLength\tCopies\tUsed\tSeq?\tName\n");
1844
1845 for (i = 0; i < patch->cont->source_info_len; i += 1)
1846 {
1847 si = patch->cont->source_info[i];
1848
1849 edsio_md5_to_string (si->md5, buf);
1850
1851 xd_error ("%s\t%d\t%d\t%d\t%s\t%s\n",
1852 buf,
1853 si->len,
1854 si->copies,
1855 si->copy_length,
1856 si->sequential ? "yes" : "no",
1857 si->name);
1858 }
1859
1860 return 0;
1861}
1862
1863static gint
1864patch_command (gint argc, gchar** argv)
1865{
1866 XdFileHandle* to_out;
1867 XdeltaPatch* patch;
1868 gint to_out_fd;
1869 int count = 1;
1870 int ret;
1871
1872 if (argc < 1 || argc > 3)
1873 {
1874 xd_error ("usage: %s patch patchfile [fromfile [tofile]]\n", program_name);
1875 return 2;
1876 }
1877
1878 if (! (patch = process_patch (argv[0])))
1879 return 2;
1880
1881 if (argc > 1)
1882 patch->from_name = argv[1];
1883 else if (verbose)
1884 xd_error ("using from file name: %s\n", patch->from_name);
1885
1886 if (argc > 2)
1887 patch->to_name = argv[2];
1888 else
1889 {
1890 struct stat sbuf;
1891 gchar *defname = g_strdup (patch->to_name);
1892
1893 while ((ret = stat (patch->to_name, & sbuf)) == 0)
1894 {
1895 if (verbose)
1896 xd_error ("to file exists: %s\n", patch->to_name);
1897 patch->to_name = g_strdup_printf ("%s.xdp%d", defname, count++);
1898 }
1899
1900 if (verbose || strcmp (defname, patch->to_name) != 0)
1901 xd_error ("using to file name: %s\n", patch->to_name);
1902 }
1903
1904 if (strcmp (patch->to_name, "-") == 0)
1905 {
1906 to_out_fd = STDOUT_FILENO;
1907 patch->to_name = "standard output";
1908 }
1909 else
1910 {
1911 to_out_fd = open (patch->to_name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
1912
1913 if (to_out_fd < 0)
1914 {
1915 xd_error ("open %s failed: %s\n", patch->to_name, g_strerror (errno));
1916 return 2;
1917 }
1918 }
1919
1920 to_out = open_write_handle (to_out_fd, patch->to_name);
1921
1922 if ((patch->patch_flags & FLAG_TO_COMPRESSED) && (xd_begin_compression (to_out) < 0))
1923 return 2;
1924
1925 if (patch->from_source)
1926 {
1927 XdFileHandle* from_in;
1928 gboolean from_is_compressed = FALSE;
1929
1930 if (! (from_in = open_read_seek_handle (patch->from_name, &from_is_compressed, TRUE)))
1931 return 2;
1932
1933 if (from_is_compressed != ((patch->patch_flags & FLAG_FROM_COMPRESSED) && 1))
1934 xd_error ("warning: expected %scompressed from file (%s)\n",
1935 (patch->patch_flags & FLAG_FROM_COMPRESSED) ? "" : "un",
1936 patch->from_name);
1937
1938 if (xd_handle_length (from_in) != patch->from_source->len)
1939 {
1940 xd_error ("expected from file (%s) of %slength %d bytes\n",
1941 patch->from_name,
1942 from_is_compressed ? "uncompressed " : "",
1943 patch->from_source->len);
1944 return 2;
1945 }
1946
1947 patch->from_source->in = (XdeltaStream*) from_in;
1948 }
1949
1950 if (patch->data_source)
1951 patch->data_source->in = (XdeltaStream*) patch->patch_in;
1952
1953 if (! xdp_apply_delta (patch->cont, (FileHandle*) to_out))
1954 return 2;
1955
1956 if (patch->from_source)
1957 xd_read_close ((XdFileHandle*) patch->from_source->in);
1958
1959 xd_read_close (patch->patch_in);
1960
1961 if (! xd_handle_really_close (to_out))
1962 return 2;
1963
1964 return 0;
1965}
diff --git a/xdelta1/xdrsync.c b/xdelta1/xdrsync.c
deleted file mode 100644
index db7ed94..0000000
--- a/xdelta1/xdrsync.c
+++ /dev/null
@@ -1,443 +0,0 @@
1/* -*- Mode: C;-*-
2 *
3 * This file is part of XDelta - A binary delta generator.
4 *
5 * Copyright (C) 1997, 1998, 1999 Josh MacDonald
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
22 *
23 * $Id: xdrsync.c 1.2 Thu, 01 Apr 1999 23:29:11 -0800 jmacd $
24 */
25
26#include <string.h>
27#include <stdlib.h>
28
29#include "xdelta.h"
30#include "xdeltapriv.h"
31
32/* Rsync
33 */
34
35static void
36init_long_checksum (const guint8 *buf, guint len, XdeltaChecksum *cksum)
37{
38 guint16 low = cksum->low;
39 guint16 high = cksum->high;
40
41 /* @@@ unroll me? */
42 for (; len > 0; len -= 1)
43 {
44 low += CHEW(*buf++);
45 high += low;
46 }
47
48 cksum->low = low;
49 cksum->high = high;
50}
51
52static XdeltaRsync*
53xdp_rsync_index_int (XdeltaStream *str,
54 guint seg_len)
55{
56 guint to_index = seg_len;
57 XdeltaPos pos;
58 XdeltaChecksum cksum;
59 GArray *index;
60 EdsioMD5Ctx ctx;
61
62 index = g_array_new (FALSE, FALSE, sizeof (XdeltaRsyncElt));
63
64 init_pos (str, &pos);
65
66 memset (&cksum, 0, sizeof (cksum));
67
68 edsio_md5_init (& ctx);
69
70 for (;;)
71 {
72 gint consume;
73
74 if (! map_page (str, &pos))
75 return NULL;
76
77 consume = MIN (to_index, pos.mem_rem - pos.off);
78
79 if (consume == 0)
80 break;
81
82 to_index -= consume;
83
84 edsio_md5_update (& ctx, pos.mem + pos.off, consume);
85 init_long_checksum (pos.mem + pos.off, consume, &cksum);
86
87 if (to_index == 0)
88 {
89 XdeltaRsyncElt elt;
90
91 edsio_md5_final (elt.md5, &ctx);
92
93 elt.cksum = cksum;
94
95 g_array_append_val (index, elt);
96
97 edsio_md5_init (& ctx);
98 memset (&cksum, 0, sizeof (cksum));
99 to_index = seg_len;
100 }
101
102 pos.off += consume;
103
104 FLIP_FORWARD (pos);
105 }
106
107 if (! unmap_page (str, &pos))
108 return NULL;
109
110 {
111 XdeltaRsync* rsync = g_new (XdeltaRsync, 1);
112
113 rsync->seg_len = seg_len;
114 rsync->file_len = handle_length (str);
115
116 memcpy (rsync->file_md5, handle_checksum_md5 (str), 16);
117
118 rsync->index = &g_array_index (index, XdeltaRsyncElt, 0);
119 rsync->index_len = index->len;
120
121 return rsync;
122 }
123}
124
125static XdeltaRsync*
126xdp_rsync_read_index (XdeltaStream* cache_in)
127{
128 SerialSource* src = handle_source (cache_in);
129 XdeltaRsync* rsync;
130
131 if (! src)
132 return NULL;
133
134 if (! unserialize_rsyncindex (src, &rsync))
135 return NULL;
136
137 return rsync;
138}
139
140static gboolean
141xdp_rsync_write_index (XdeltaRsync* rsync,
142 XdeltaOutStream* cache_out)
143{
144 SerialSink* sink = handle_sink (cache_out, NULL, NULL, NULL, NULL);
145
146 if (! sink)
147 return FALSE;
148
149 if (! serialize_rsyncindex_obj (sink, rsync))
150 return FALSE;
151
152 if (! handle_close (cache_out, 0))
153 return FALSE;
154
155 return TRUE;
156}
157
158XdeltaRsync*
159xdp_rsync_index (XdeltaStream *str,
160 guint seg_len,
161 XdeltaStream *cache_in,
162 XdeltaOutStream *cache_out)
163{
164 XdeltaRsync* rsync;
165
166 if (cache_in)
167 {
168 if (! (rsync = xdp_rsync_read_index (cache_in)))
169 return NULL;
170
171 if (seg_len != rsync->seg_len ||
172 (str && ! check_stream_integrity (str, rsync->file_md5, rsync->file_len)))
173 {
174 xd_generate_void_event (EC_XdInvalidRsyncCache);
175 goto bail;
176 }
177
178 return rsync;
179 }
180 else
181 {
182 if (! (rsync = xdp_rsync_index_int (str, seg_len)))
183 return NULL;
184
185 if (cache_out)
186 {
187 if (! xdp_rsync_write_index (rsync, cache_out))
188 goto bail;
189 }
190
191 return rsync;
192 }
193
194bail:
195
196 xdp_rsync_index_free (rsync);
197
198 return NULL;
199}
200
201void
202xdp_rsync_index_free (XdeltaRsync *rsync)
203{
204 /* ??? */
205}
206
207static
208gboolean xdp_rsync_hash (XdeltaRsync* rsync)
209{
210 guint i, index, prime = 0;
211 gboolean already_hashed = rsync->table != NULL;
212 SerialRsyncIndexElt** table = NULL;
213
214 if (! already_hashed)
215 {
216 prime = rsync->table_size = g_spaced_primes_closest (rsync->index_len);
217 table = rsync->table = g_new0 (SerialRsyncIndexElt*, prime);
218 }
219
220 for (i = 0; i < rsync->index_len; i += 1)
221 {
222 SerialRsyncIndexElt* elt = rsync->index + i;
223
224 elt->match_offset = -1;
225
226 if (! already_hashed)
227 {
228 index = c_hash (& elt->cksum) % prime;
229
230 elt->next = table[index];
231 table[index] = elt;
232 }
233 }
234
235 return TRUE;
236}
237
238static void
239incr_by (XdeltaPos* pos, gint incr)
240{
241 do
242 {
243 gint rem = MIN (incr, pos->mem_rem - pos->off);
244
245 pos->off += incr;
246 incr -= rem;
247 FLIP_FORWARD (*pos);
248 }
249 while (incr > 0 && pos->mem_rem != pos->page_size);
250}
251
252GArray*
253xdp_rsync_request (XdeltaStream *file,
254 XdeltaRsync *rsync)
255{
256 XdeltaPos opos, npos;
257 XdeltaChecksum cksum;
258 guint max_buffer_index = handle_length (file);
259 GArray *request = g_array_new (FALSE, FALSE, sizeof (guint));
260 const guint8* n_pointer, *o_pointer;
261 guint thistime;
262 guint prime, index;
263 SerialRsyncIndexElt **table;
264 guint i;
265 guint matched = 0;
266 guint16 old_c, new_c;
267
268 if (max_buffer_index < rsync->seg_len)
269 return request;
270
271 max_buffer_index -= rsync->seg_len;
272
273 if (! xdp_rsync_hash (rsync))
274 return NULL;
275
276 g_assert (rsync->seg_len < handle_pagesize (file));
277
278 init_pos (file, &opos);
279 init_pos (file, &npos);
280 memset (&cksum, 0, sizeof (cksum));
281
282 prime = rsync->table_size;
283 table = rsync->table;
284
285 if (!map_page (file, &opos))
286 return NULL;
287
288 init_long_checksum (opos.mem, rsync->seg_len, &cksum);
289
290 npos.off += rsync->seg_len;
291
292 for (; XPOS (opos) < max_buffer_index; )
293 {
294 if (!map_page (file, &opos))
295 return FALSE;
296
297 if (!map_page (file, &npos))
298 return FALSE;
299
300 if (matched == rsync->index_len)
301 break;
302
303 thistime = MIN (opos.mem_rem - opos.off,
304 npos.mem_rem - npos.off);
305
306 o_pointer = opos.mem + opos.off;
307 n_pointer = npos.mem + npos.off;
308
309 for (; ; o_pointer += 1, n_pointer += 1)
310 {
311 index = c_hash (&cksum) % prime;
312
313 if (table[index])
314 {
315 gboolean md5_computed = FALSE;
316 gboolean found = FALSE;
317 guint8 md5[16];
318 SerialRsyncIndexElt* elt;
319
320 for (elt = table[index]; elt; elt = elt->next)
321 {
322 if (elt->match_offset >= 0)
323 continue;
324
325 if (elt->cksum.high != cksum.high ||
326 elt->cksum.low != cksum.low)
327 continue;
328
329 if (! md5_computed)
330 {
331 EdsioMD5Ctx ctx;
332
333 edsio_md5_init (& ctx);
334
335 if (opos.page == npos.page)
336 edsio_md5_update (& ctx, opos.mem + opos.off, rsync->seg_len);
337 else
338 {
339 edsio_md5_update (& ctx, opos.mem + opos.off, opos.mem_rem - opos.off);
340 edsio_md5_update (& ctx, npos.mem, rsync->seg_len - (opos.mem_rem - opos.off));
341 }
342
343 edsio_md5_final (md5, & ctx);
344
345 md5_computed = TRUE;
346 }
347
348 if (memcmp (md5, elt->md5, 16) == 0)
349 {
350 matched += 1;
351 found = TRUE;
352 elt->match_offset = XPOS (opos);
353 }
354 }
355
356 if (found)
357 {
358 incr_by (&opos, rsync->seg_len);
359 incr_by (&npos, rsync->seg_len);
360 goto reenter;
361 }
362 }
363
364 if (thistime == 0)
365 goto nextpage;
366
367 thistime -= 1;
368 opos.off += 1;
369 npos.off += 1;
370
371 old_c = CHEW(*o_pointer);
372 new_c = CHEW(*n_pointer);
373
374 cksum.low -= old_c;
375 cksum.low += new_c;
376
377 cksum.high -= old_c * rsync->seg_len;
378 cksum.high += cksum.low;
379 }
380
381 nextpage:
382
383 FLIP_FORWARD (opos);
384 FLIP_FORWARD (npos);
385
386 reenter:
387 (void) 0;
388 }
389
390 for (i = 0; i < rsync->index_len; i += 1)
391 {
392 SerialRsyncIndexElt* elt = rsync->index + i;
393
394 if (elt->match_offset < 0)
395 {
396#ifdef DEBUG_RSYNC_REQUEST
397 g_print ("request segment %d\n", i);
398#endif
399 g_array_append_val (request, i);
400 }
401 }
402
403 return request;
404}
405
406gboolean
407xdp_apply_rsync_reply (XdeltaRsync *rsync,
408 XdeltaStream *from,
409 XdeltaStream *reply,
410 XdeltaStream *out)
411{
412 gint i;
413 guint reply_offset = 0;
414
415 for (i = 0; i < rsync->index_len; i += 1)
416 {
417 SerialRsyncIndexElt* elt = rsync->index + i;
418
419 if (elt->match_offset >= 0)
420 {
421 if (! handle_copy (from, out, elt->match_offset, rsync->seg_len))
422 return FALSE;
423 }
424 else
425 {
426 if (! handle_copy (reply, out, reply_offset, rsync->seg_len))
427 return FALSE;
428
429 reply_offset += rsync->seg_len;
430 }
431 }
432
433 if (! handle_copy (reply, out, reply_offset, rsync->file_len % rsync->seg_len))
434 return FALSE;
435
436 if (! handle_close (out, 0))
437 return FALSE;
438
439 if (! check_stream_integrity (out, rsync->file_md5, rsync->file_len))
440 return FALSE;
441
442 return TRUE;
443}