diff options
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 @@ | |||
1 | The author is Joshua MacDonald, <jmacd@cs.berkeley.edu>. The Rsync | ||
2 | algorithm, which inspired the core delta algorithm, is due to Andrew | ||
3 | Tridgell 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 | ||
12 | freedom to share and change it. By contrast, the GNU General Public | ||
13 | License is intended to guarantee your freedom to share and change free | ||
14 | software--to make sure the software is free for all its users. This | ||
15 | General Public License applies to most of the Free Software | ||
16 | Foundation's software and to any other program whose authors commit to | ||
17 | using it. (Some other Free Software Foundation software is covered by | ||
18 | the GNU Library General Public License instead.) You can apply it to | ||
19 | your programs, too. | ||
20 | |||
21 | When we speak of free software, we are referring to freedom, not | ||
22 | price. Our General Public Licenses are designed to make sure that you | ||
23 | have the freedom to distribute copies of free software (and charge for | ||
24 | this service if you wish), that you receive source code or can get it | ||
25 | if you want it, that you can change the software or use pieces of it | ||
26 | in 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 | ||
29 | anyone to deny you these rights or to ask you to surrender the rights. | ||
30 | These restrictions translate to certain responsibilities for you if you | ||
31 | distribute copies of the software, or if you modify it. | ||
32 | |||
33 | For example, if you distribute copies of such a program, whether | ||
34 | gratis or for a fee, you must give the recipients all the rights that | ||
35 | you have. You must make sure that they, too, receive or can get the | ||
36 | source code. And you must show them these terms so they know their | ||
37 | rights. | ||
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, | ||
41 | distribute and/or modify the software. | ||
42 | |||
43 | Also, for each author's protection and ours, we want to make certain | ||
44 | that everyone understands that there is no warranty for this free | ||
45 | software. If the software is modified by someone else and passed on, we | ||
46 | want its recipients to know that what they have is not the original, so | ||
47 | that any problems introduced by others will not reflect on the original | ||
48 | authors' reputations. | ||
49 | |||
50 | Finally, any free program is threatened constantly by software | ||
51 | patents. We wish to avoid the danger that redistributors of a free | ||
52 | program will individually obtain patent licenses, in effect making the | ||
53 | program proprietary. To prevent this, we have made it clear that any | ||
54 | patent must be licensed for everyone's free use or not licensed at all. | ||
55 | |||
56 | The precise terms and conditions for copying, distribution and | ||
57 | modification 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 | ||
63 | a notice placed by the copyright holder saying it may be distributed | ||
64 | under the terms of this General Public License. The "Program", below, | ||
65 | refers to any such program or work, and a "work based on the Program" | ||
66 | means either the Program or any derivative work under copyright law: | ||
67 | that is to say, a work containing the Program or a portion of it, | ||
68 | either verbatim or with modifications and/or translated into another | ||
69 | language. (Hereinafter, translation is included without limitation in | ||
70 | the term "modification".) Each licensee is addressed as "you". | ||
71 | |||
72 | Activities other than copying, distribution and modification are not | ||
73 | covered by this License; they are outside its scope. The act of | ||
74 | running the Program is not restricted, and the output from the Program | ||
75 | is covered only if its contents constitute a work based on the | ||
76 | Program (independent of having been made by running the Program). | ||
77 | Whether that is true depends on what the Program does. | ||
78 | |||
79 | 1. You may copy and distribute verbatim copies of the Program's | ||
80 | source code as you receive it, in any medium, provided that you | ||
81 | conspicuously and appropriately publish on each copy an appropriate | ||
82 | copyright notice and disclaimer of warranty; keep intact all the | ||
83 | notices that refer to this License and to the absence of any warranty; | ||
84 | and give any other recipients of the Program a copy of this License | ||
85 | along with the Program. | ||
86 | |||
87 | You may charge a fee for the physical act of transferring a copy, and | ||
88 | you 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 | ||
91 | of it, thus forming a work based on the Program, and copy and | ||
92 | distribute such modifications or work under the terms of Section 1 | ||
93 | above, 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 | |||
114 | These requirements apply to the modified work as a whole. If | ||
115 | identifiable sections of that work are not derived from the Program, | ||
116 | and can be reasonably considered independent and separate works in | ||
117 | themselves, then this License, and its terms, do not apply to those | ||
118 | sections when you distribute them as separate works. But when you | ||
119 | distribute the same sections as part of a whole which is a work based | ||
120 | on the Program, the distribution of the whole must be on the terms of | ||
121 | this License, whose permissions for other licensees extend to the | ||
122 | entire whole, and thus to each and every part regardless of who wrote it. | ||
123 | |||
124 | Thus, it is not the intent of this section to claim rights or contest | ||
125 | your rights to work written entirely by you; rather, the intent is to | ||
126 | exercise the right to control the distribution of derivative or | ||
127 | collective works based on the Program. | ||
128 | |||
129 | In addition, mere aggregation of another work not based on the Program | ||
130 | with the Program (or with a work based on the Program) on a volume of | ||
131 | a storage or distribution medium does not bring the other work under | ||
132 | the scope of this License. | ||
133 | |||
134 | 3. You may copy and distribute the Program (or a work based on it, | ||
135 | under Section 2) in object code or executable form under the terms of | ||
136 | Sections 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 | |||
155 | The source code for a work means the preferred form of the work for | ||
156 | making modifications to it. For an executable work, complete source | ||
157 | code means all the source code for all modules it contains, plus any | ||
158 | associated interface definition files, plus the scripts used to | ||
159 | control compilation and installation of the executable. However, as a | ||
160 | special exception, the source code distributed need not include | ||
161 | anything that is normally distributed (in either source or binary | ||
162 | form) with the major components (compiler, kernel, and so on) of the | ||
163 | operating system on which the executable runs, unless that component | ||
164 | itself accompanies the executable. | ||
165 | |||
166 | If distribution of executable or object code is made by offering | ||
167 | access to copy from a designated place, then offering equivalent | ||
168 | access to copy the source code from the same place counts as | ||
169 | distribution of the source code, even though third parties are not | ||
170 | compelled to copy the source along with the object code. | ||
171 | |||
172 | 4. You may not copy, modify, sublicense, or distribute the Program | ||
173 | except as expressly provided under this License. Any attempt | ||
174 | otherwise to copy, modify, sublicense or distribute the Program is | ||
175 | void, and will automatically terminate your rights under this License. | ||
176 | However, parties who have received copies, or rights, from you under | ||
177 | this License will not have their licenses terminated so long as such | ||
178 | parties remain in full compliance. | ||
179 | |||
180 | 5. You are not required to accept this License, since you have not | ||
181 | signed it. However, nothing else grants you permission to modify or | ||
182 | distribute the Program or its derivative works. These actions are | ||
183 | prohibited by law if you do not accept this License. Therefore, by | ||
184 | modifying or distributing the Program (or any work based on the | ||
185 | Program), you indicate your acceptance of this License to do so, and | ||
186 | all its terms and conditions for copying, distributing or modifying | ||
187 | the Program or works based on it. | ||
188 | |||
189 | 6. Each time you redistribute the Program (or any work based on the | ||
190 | Program), the recipient automatically receives a license from the | ||
191 | original licensor to copy, distribute or modify the Program subject to | ||
192 | these terms and conditions. You may not impose any further | ||
193 | restrictions on the recipients' exercise of the rights granted herein. | ||
194 | You are not responsible for enforcing compliance by third parties to | ||
195 | this License. | ||
196 | |||
197 | 7. If, as a consequence of a court judgment or allegation of patent | ||
198 | infringement or for any other reason (not limited to patent issues), | ||
199 | conditions are imposed on you (whether by court order, agreement or | ||
200 | otherwise) that contradict the conditions of this License, they do not | ||
201 | excuse you from the conditions of this License. If you cannot | ||
202 | distribute so as to satisfy simultaneously your obligations under this | ||
203 | License and any other pertinent obligations, then as a consequence you | ||
204 | may not distribute the Program at all. For example, if a patent | ||
205 | license would not permit royalty-free redistribution of the Program by | ||
206 | all those who receive copies directly or indirectly through you, then | ||
207 | the only way you could satisfy both it and this License would be to | ||
208 | refrain entirely from distribution of the Program. | ||
209 | |||
210 | If any portion of this section is held invalid or unenforceable under | ||
211 | any particular circumstance, the balance of the section is intended to | ||
212 | apply and the section as a whole is intended to apply in other | ||
213 | circumstances. | ||
214 | |||
215 | It is not the purpose of this section to induce you to infringe any | ||
216 | patents or other property right claims or to contest validity of any | ||
217 | such claims; this section has the sole purpose of protecting the | ||
218 | integrity of the free software distribution system, which is | ||
219 | implemented by public license practices. Many people have made | ||
220 | generous contributions to the wide range of software distributed | ||
221 | through that system in reliance on consistent application of that | ||
222 | system; it is up to the author/donor to decide if he or she is willing | ||
223 | to distribute software through any other system and a licensee cannot | ||
224 | impose that choice. | ||
225 | |||
226 | This section is intended to make thoroughly clear what is believed to | ||
227 | be a consequence of the rest of this License. | ||
228 | |||
229 | 8. If the distribution and/or use of the Program is restricted in | ||
230 | certain countries either by patents or by copyrighted interfaces, the | ||
231 | original copyright holder who places the Program under this License | ||
232 | may add an explicit geographical distribution limitation excluding | ||
233 | those countries, so that distribution is permitted only in or among | ||
234 | countries not thus excluded. In such case, this License incorporates | ||
235 | the limitation as if written in the body of this License. | ||
236 | |||
237 | 9. The Free Software Foundation may publish revised and/or new versions | ||
238 | of the General Public License from time to time. Such new versions will | ||
239 | be similar in spirit to the present version, but may differ in detail to | ||
240 | address new problems or concerns. | ||
241 | |||
242 | Each version is given a distinguishing version number. If the Program | ||
243 | specifies a version number of this License which applies to it and "any | ||
244 | later version", you have the option of following the terms and conditions | ||
245 | either of that version or of any later version published by the Free | ||
246 | Software Foundation. If the Program does not specify a version number of | ||
247 | this License, you may choose any version ever published by the Free Software | ||
248 | Foundation. | ||
249 | |||
250 | 10. If you wish to incorporate parts of the Program into other free | ||
251 | programs whose distribution conditions are different, write to the author | ||
252 | to ask for permission. For software which is copyrighted by the Free | ||
253 | Software Foundation, write to the Free Software Foundation; we sometimes | ||
254 | make exceptions for this. Our decision will be guided by the two goals | ||
255 | of preserving the free status of all derivatives of our free software and | ||
256 | of 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 | ||
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN | ||
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES | ||
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED | ||
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS | ||
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE | ||
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, | ||
268 | REPAIR OR CORRECTION. | ||
269 | |||
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | ||
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR | ||
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, | ||
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING | ||
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED | ||
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY | ||
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER | ||
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE | ||
278 | POSSIBILITY 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 | ||
285 | possible use to the public, the best way to achieve this is to make it | ||
286 | free 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 | ||
289 | to attach them to the start of each source file to most effectively | ||
290 | convey the exclusion of warranty; and each file should have at least | ||
291 | the "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 | |||
310 | Also add information on how to contact you by electronic and paper mail. | ||
311 | |||
312 | If the program is interactive, make it output a short notice like this | ||
313 | when 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 | |||
320 | The hypothetical commands `show w' and `show c' should show the appropriate | ||
321 | parts of the General Public License. Of course, the commands you use may | ||
322 | be called something other than `show w' and `show c'; they could even be | ||
323 | mouse-clicks or menu items--whatever suits your program. | ||
324 | |||
325 | You should also get your employer (if you work as a programmer) or your | ||
326 | school, if any, to sign a "copyright disclaimer" for the program, if | ||
327 | necessary. 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 | |||
335 | This General Public License does not permit incorporating your program into | ||
336 | proprietary programs. If your program is a subroutine library, you may | ||
337 | consider it more useful to permit linking proprietary applications with the | ||
338 | library. If this is what you want to do, use the GNU Library General | ||
339 | Public 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 | |||
3 | XDelta depends on | ||
4 | |||
5 | glib 1.2.8 or later | ||
6 | zlib 1.1.3 or later | ||
7 | |||
8 | You can get glib from | ||
9 | |||
10 | ftp://ftp.gtk.org/pub/gtk/v1.2 | ||
11 | |||
12 | You can get zlib from | ||
13 | |||
14 | ftp://ftp.cdrom.com/pub/infozip/zlib | ||
15 | |||
16 | To install, make sure these packages are installed and your compiler | ||
17 | and linker either locates zlib by default or that the CFLAGS | ||
18 | environment variable contains an appropriate include directive and the | ||
19 | LDFLAGS environment variable contains a suitable linker directive. | ||
20 | |||
21 | Then run | ||
22 | |||
23 | ./configure | ||
24 | |||
25 | Then run | ||
26 | |||
27 | make | ||
28 | |||
29 | Then run | ||
30 | |||
31 | make install | ||
32 | |||
33 | Below follows the standard GNU INSTALL file, which contains general | ||
34 | troubleshooting tips. | ||
35 | |||
36 | Basic Installation | ||
37 | ================== | ||
38 | |||
39 | These are generic installation instructions. | ||
40 | |||
41 | The `configure' shell script attempts to guess correct values for | ||
42 | various system-dependent variables used during compilation. It uses | ||
43 | those values to create a `Makefile' in each directory of the package. | ||
44 | It may also create one or more `.h' files containing system-dependent | ||
45 | definitions. Finally, it creates a shell script `config.status' that | ||
46 | you 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 | ||
48 | reconfiguring, 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 | ||
52 | to figure out how `configure' could check whether to do them, and mail | ||
53 | diffs or instructions to the address given in the `README' so they can | ||
54 | be considered for the next release. If at some point `config.cache' | ||
55 | contains 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 | ||
58 | called `autoconf'. You only need `configure.in' if you want to change | ||
59 | it or regenerate `configure' using a newer version of `autoconf'. | ||
60 | |||
61 | The 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 | |||
89 | Compilers and Options | ||
90 | ===================== | ||
91 | |||
92 | Some systems require unusual options for compilation or linking that | ||
93 | the `configure' script does not know about. You can give `configure' | ||
94 | initial values for variables by setting them in the environment. Using | ||
95 | a Bourne-compatible shell, you can do that on the command line like | ||
96 | this: | ||
97 | CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure | ||
98 | |||
99 | Or on systems that have the `env' program, you can do it like this: | ||
100 | env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure | ||
101 | |||
102 | Compiling For Multiple Architectures | ||
103 | ==================================== | ||
104 | |||
105 | You can compile the package for more than one kind of computer at the | ||
106 | same time, by placing the object files for each architecture in their | ||
107 | own directory. To do this, you must use a version of `make' that | ||
108 | supports the `VPATH' variable, such as GNU `make'. `cd' to the | ||
109 | directory where you want the object files and executables to go and run | ||
110 | the `configure' script. `configure' automatically checks for the | ||
111 | source 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' | ||
114 | variable, you have to compile the package for one architecture at a time | ||
115 | in the source code directory. After you have installed the package for | ||
116 | one architecture, use `make distclean' before reconfiguring for another | ||
117 | architecture. | ||
118 | |||
119 | Installation 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 | ||
124 | installation prefix other than `/usr/local' by giving `configure' the | ||
125 | option `--prefix=PATH'. | ||
126 | |||
127 | You can specify separate installation prefixes for | ||
128 | architecture-specific files and architecture-independent files. If you | ||
129 | give `configure' the option `--exec-prefix=PATH', the package will use | ||
130 | PATH as the prefix for installing programs and libraries. | ||
131 | Documentation and other data files will still use the regular prefix. | ||
132 | |||
133 | In addition, if you use an unusual directory layout you can give | ||
134 | options like `--bindir=PATH' to specify different values for particular | ||
135 | kinds of files. Run `configure --help' for a list of the directories | ||
136 | you can set and what kinds of files go in them. | ||
137 | |||
138 | If the package supports it, you can cause programs to be installed | ||
139 | with an extra prefix or suffix on their names by giving `configure' the | ||
140 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. | ||
141 | |||
142 | Optional Features | ||
143 | ================= | ||
144 | |||
145 | Some packages pay attention to `--enable-FEATURE' options to | ||
146 | `configure', where FEATURE indicates an optional part of the package. | ||
147 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE | ||
148 | is something like `gnu-as' or `x' (for the X Window System). The | ||
149 | `README' should mention any `--enable-' and `--with-' options that the | ||
150 | package recognizes. | ||
151 | |||
152 | For packages that use the X Window System, `configure' can usually | ||
153 | find the X include and library files automatically, but if it doesn't, | ||
154 | you can use the `configure' options `--x-includes=DIR' and | ||
155 | `--x-libraries=DIR' to specify their locations. | ||
156 | |||
157 | Specifying the System Type | ||
158 | ========================== | ||
159 | |||
160 | There may be some features `configure' can not figure out | ||
161 | automatically, but needs to determine by the type of host the package | ||
162 | will run on. Usually `configure' can figure that out, but if it prints | ||
163 | a 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 | ||
165 | type, such as `sun4', or a canonical name with three fields: | ||
166 | CPU-COMPANY-SYSTEM | ||
167 | |||
168 | See 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 | ||
170 | need to know the host type. | ||
171 | |||
172 | If you are building compiler tools for cross-compiling, you can also | ||
173 | use the `--target=TYPE' option to select the type of system they will | ||
174 | produce code for and the `--build=TYPE' option to select the type of | ||
175 | system on which you are compiling the package. | ||
176 | |||
177 | Sharing Defaults | ||
178 | ================ | ||
179 | |||
180 | If you want to set default values for `configure' scripts to share, | ||
181 | you can create a site shell script called `config.site' that gives | ||
182 | default 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. | ||
186 | A warning: not all `configure' scripts look for a site script. | ||
187 | |||
188 | Operation Controls | ||
189 | ================== | ||
190 | |||
191 | `configure' recognizes the following options to control how it | ||
192 | operates. | ||
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 | |||
2 | INCLUDES = -I$(top_srcdir)/libedsio $(GLIB_CFLAGS) | ||
3 | |||
4 | bin_PROGRAMS = xdelta | ||
5 | bin_SCRIPTS = xdelta-config | ||
6 | |||
7 | xdelta_SOURCES = xdmain.c getopt.c getopt1.c | ||
8 | |||
9 | xdelta_LDADD = libxdelta.la \ | ||
10 | $(top_srcdir)/libedsio/libedsio.la \ | ||
11 | $(GLIB_LIBS) \ | ||
12 | -lz | ||
13 | |||
14 | include_HEADERS = xdelta.h xd_edsio.h | ||
15 | noinst_HEADERS = xdeltapriv.h getopt.h | ||
16 | |||
17 | lib_LTLIBRARIES = libxdelta.la | ||
18 | |||
19 | libxdelta_la_SOURCES = xdelta.c xdapply.c $(SER_SOURCES) | ||
20 | libxdelta_la_LIBADD = $(GLIB_LIBS) | ||
21 | |||
22 | EXTRA_DIST = xd.ser $(SER_OUT) xdelta.magic xdelta.prj xdelta.m4 \ | ||
23 | autogen.sh xdelta.dsp xdelta.dsw stamp-ser xdrsync.c | ||
24 | |||
25 | SUBDIRS = libedsio . test doc djgpp | ||
26 | |||
27 | m4datadir = $(datadir)/aclocal | ||
28 | m4data_DATA = xdelta.m4 | ||
29 | |||
30 | ## $Format: "libxdelta_la_LDFLAGS = -version-info $LibCurrent$:$LibRevision$:$LibAge$" $ | ||
31 | libxdelta_la_LDFLAGS = -version-info 2:0:0 | ||
32 | |||
33 | # | ||
34 | # Rules for the generated code | ||
35 | # | ||
36 | |||
37 | stamp-ser: $(top_srcdir)/libedsio/edsio.el xd.ser | ||
38 | $(top_srcdir)/libedsio/edsio-comp xd.ser | ||
39 | touch stamp-ser | ||
40 | |||
41 | SER_OUT = xd_edsio.h xd_edsio.c | ||
42 | |||
43 | $(SER_OUT): stamp-ser | ||
44 | |||
45 | SER_SOURCES = xd_edsio.c | ||
46 | BUILT_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 @@ | |||
1 | XDelta NEWS -- history of user-visible changes. -*- Text -*- | ||
2 | $Date: Sun, 24 Feb 2002 11:31:12 -0800 $ | ||
3 | $ReleaseVersion: 1.1.4 $ | ||
4 | |||
5 | Please 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 | |||
5 | Announcing version 1.1.2 of Xdelta. Xdelta is an application program | ||
6 | designed to compute changes between files. These changes (deltas) are | ||
7 | similar to the output of the "diff" program in that they may be used | ||
8 | to store and transmit only the changes between files. However, unlike | ||
9 | diff, the output of Xdelta is not expressed in a human-readable | ||
10 | format--Xdelta can also also apply these deltas to a copy of the | ||
11 | original file. Xdelta uses a fast, linear algorithm and performs well | ||
12 | on both binary and text files. | ||
13 | |||
14 | Xdelta 1.1.2 is a stable, maintenence release. New, ongoing work on | ||
15 | Xdelta has focused on a new storage system with features similar to | ||
16 | the RCS command set. For more information on new development, see the | ||
17 | Xdelta-2.0 release series at http://xdelta.sourceforge.net. | ||
18 | |||
19 | Xdelta was designed and implemented by Joshua MacDonald. The delta | ||
20 | algorithm is based on the Rsync algorithm, though implementation and | ||
21 | interface considerations leave the two programs quite distinct. The | ||
22 | Rsync algorithm is due to Andrew Tridgell and Paul Mackerras. | ||
23 | |||
24 | To compile and install Xdelta, read the instructions in the INSTALL | ||
25 | file. Once you have done this, you should at least read the first few | ||
26 | sections of the documentation. It is available in info format. All | ||
27 | documentation is located in the doc/ subdirectory. | ||
28 | |||
29 | This release, version 1.1.2, and future releases of Xdelta can be | ||
30 | found at http://xdelta.sourceforge.net. | ||
31 | |||
32 | Xdelta is released under the GNU Library Public License (GPL), see the | ||
33 | file COPYING for details. | ||
34 | |||
35 | There is mailing list for announcements: | ||
36 | |||
37 | xdelta-announce@lists.sourceforge.net | ||
38 | |||
39 | you can subscribe to the mailing list or file bug reports through | ||
40 | Sourceforge at: | ||
41 | |||
42 | http://sourceforge.net/projects/xdelta/ | ||
43 | |||
44 | Comments about Xdelta can be addressed to the following addresses: | ||
45 | |||
46 | jmacd@cs.berkeley.edu | ||
47 | |||
48 | The man page describes how to use Xdelta in more detail: | ||
49 | |||
50 | NAME | ||
51 | xdelta - Invoke Xdelta | ||
52 | |||
53 | SYNOPSIS | ||
54 | xdelta subcommand [ option... ] [ operand... ] | ||
55 | |||
56 | DESCRIPTION | ||
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 | |||
4 | DIE=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 | |||
30 | if test "$DIE" -eq 1; then | ||
31 | exit 1 | ||
32 | fi | ||
33 | |||
34 | (test -f xdelta.c) || { | ||
35 | echo "You must run this script in the top-level xdelta directory" | ||
36 | exit 1 | ||
37 | } | ||
38 | |||
39 | if 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." | ||
42 | fi | ||
43 | |||
44 | for i in . | ||
45 | do | ||
46 | echo processing $i | ||
47 | (cd $i; \ | ||
48 | libtoolize --copy --force; \ | ||
49 | aclocal $ACLOCAL_FLAGS; autoheader; \ | ||
50 | automake --add-missing; \ | ||
51 | autoheader; \ | ||
52 | autoconf) | ||
53 | done | ||
54 | |||
55 | echo "Running ./configure --enable-maintainer-mode" "$@" | ||
56 | ./configure --enable-maintainer-mode "$@" | ||
57 | |||
58 | echo | ||
59 | echo "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 @@ | |||
1 | dnl -*-Mode: C; comment-start: "dnl "-*- | ||
2 | dnl Process this file with autoconf to produce a configure script. | ||
3 | AC_REVISION([configure.in,v 1.2 1998/10/03 00:17:50 jmacd Exp])dnl | ||
4 | AC_INIT(xdelta.c) | ||
5 | AM_CONFIG_HEADER(config.h) | ||
6 | |||
7 | dnl $Format: "AM_INIT_AUTOMAKE(xdelta, $ReleaseVersion$, no-define)" $ | ||
8 | AM_INIT_AUTOMAKE(xdelta, 1.1.4, no-define) | ||
9 | |||
10 | AM_MAINTAINER_MODE | ||
11 | |||
12 | DEBUGFLAG= | ||
13 | PROFILEFLAG= | ||
14 | |||
15 | AC_ARG_ENABLE(debug, [ --enable-debug turn on debugging [default=no]]) | ||
16 | AC_ARG_ENABLE(profile, [ --enable-profile turn on profiling [default=no]]) | ||
17 | |||
18 | TMPCFLAGS="$CFLAGS" | ||
19 | CFLAGS= | ||
20 | |||
21 | AC_PROG_CC | ||
22 | AC_PROG_CPP | ||
23 | |||
24 | CFLAGS=$TMPCFLAGS | ||
25 | |||
26 | changequote(,)dnl | ||
27 | if 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 | ||
59 | fi | ||
60 | changequote([,])dnl | ||
61 | |||
62 | AM_PROG_LIBTOOL | ||
63 | AC_HEADER_STDC | ||
64 | AC_PROG_MAKE_SET | ||
65 | |||
66 | AC_CHECK_FUNCS(gettimeofday) | ||
67 | AC_HEADER_TIME | ||
68 | |||
69 | AC_PATH_PROGS(EMACS, emacs xemacs, emacs) | ||
70 | |||
71 | top_srcdir_absolute=`cd $srcdir; pwd` | ||
72 | AC_SUBST(top_srcdir_absolute) | ||
73 | |||
74 | AM_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 | |||
77 | dnl AC_CHECK_LIB(z, gzsetparams, */ | ||
78 | dnl AC_CHECK_HEADER(zlib.h,, */ | ||
79 | dnl AC_MSG_ERROR(ZLIB headers not found)), */ | ||
80 | dnl AC_MSG_ERROR(ZLIB library not found)) */ | ||
81 | |||
82 | AC_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 | |||
7 | gmake distclean | ||
8 | CC="cc -Ae" \ | ||
9 | CFLAGS="+O2 +Onolimit +DAportable" \ | ||
10 | CPPFLAGS="-I/usr/local/include/glib-1.2 -I/usr/local/include/zlib" \ | ||
11 | LDFLAGS="-L/usr/local/lib/glib-1.2 -L/usr/local/lib/zlib -lz" ./configure | ||
12 | |||
13 | gmake | ||
14 | gmake check | ||
15 | exit | ||
16 | :> ./TIME | ||
17 | sleep 1 | ||
18 | gmake install | ||
19 | mkdir -p /usr/local/docs/glib | ||
20 | find /usr/local/* -newer ./TIME | grep -v `pwd` > THIS_WAS_INSTALLED | ||
21 | gmake 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 | |||
2 | EXTRA_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 @@ | |||
1 | Hello. | ||
2 | |||
3 | I'm please to announce the release of the DJGPP port of XDelta 1.1.2. | ||
4 | This release contains mainly minor bugfixes over the previous | ||
5 | version (1.1.1). Please see the file 'contrib/xdlt112/news' for | ||
6 | a complete list of changes. | ||
7 | |||
8 | Here is a description of XDelta, from its 'readme' file: | ||
9 | |||
10 | "XDelta is a library interface and application program designed to compute | ||
11 | changes between files. These changes (deltas) are similar to the output | ||
12 | of the "diff" program in that they may be used to store and transmit only | ||
13 | the changes between files. However, unlike diff, the output of XDelta is | ||
14 | not expressed in a human-readable format--XDelta can also also apply these | ||
15 | deltas to a copy of the original file(s). XDelta uses a fast, linear | ||
16 | algorithm and performs well on both binary and text files. XDelta | ||
17 | typically outperforms GNU diff in both time and generated-delta-size, even | ||
18 | for plain text files. XDelta also includes a simple implementation of the | ||
19 | Rsync algorithm and several advanced features for implementing RCS-like | ||
20 | file-archival with." | ||
21 | |||
22 | XDelta is distributed under the GNU General Public License. | ||
23 | |||
24 | The port is available from the DJGPP archive on SimTel.NET: | ||
25 | |||
26 | http://www.simtel.net/gnudlpage.php?product=/gnu/djgpp/v2apps/xdlt112b.zip&name=xdlt112b.zip | ||
27 | http://www.simtel.net/gnudlpage.php?product=/gnu/djgpp/v2apps/xdlt112s.zip&name=xdlt112s.zip | ||
28 | |||
29 | These are binary and source distributions respectively. If you only want | ||
30 | to use XDelta, please download the binary distribution. If you would like | ||
31 | to rebuild XDelta, please download the source distribution. No changes | ||
32 | were required to port XDelta to DJGPP. | ||
33 | |||
34 | Thanks to Joshua MacDonald for incorporating the DJGPP patches into | ||
35 | XDelta. Thanks to Eli Zaretskii for his detailed bug reports, suggestions | ||
36 | and testing of XDelta in the past. | ||
37 | |||
38 | If you have any problems, suggestions, etc. about the port, please mail | ||
39 | me. | ||
40 | |||
41 | Bye, | ||
42 | |||
43 | -- | ||
44 | Richard Dawe | ||
45 | http://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 @@ | |||
1 | DJGPP Port of XDelta 1.1.2 | ||
2 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
3 | |||
4 | Installing the Binary Package | ||
5 | ----------------------------- | ||
6 | |||
7 | Unzip the distribution preserving the directory structure - use PKUNZIP's -d | ||
8 | option; use an equivalent option with other unzippers. Unzip into the top | ||
9 | DJGPP installation directory, e.g. c:\djgpp. | ||
10 | |||
11 | XDelta should now be ready for use. A man page for XDelta is provided - use: | ||
12 | |||
13 | man xdelta | ||
14 | |||
15 | to view it. You will need to have installed the man program from the v2apps/ | ||
16 | directory of the DJGPP archive for this to work. | ||
17 | |||
18 | Installing the Source Package | ||
19 | ----------------------------- | ||
20 | |||
21 | You should only install the source package if you want to rebuild XDelta from | ||
22 | the 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 | |||
36 | It may be possible to build XDelta with other versions of each package, but | ||
37 | this has not been tested. | ||
38 | |||
39 | Unzip the distribution preserving the directory structure - use PKUNZIP's -d | ||
40 | option; use an equivalent option with other unzippers. Unzip into the top | ||
41 | DJGPP installation directory, e.g. c:\djgpp. | ||
42 | |||
43 | No changes were needed to XDelta to make it work with DJGPP. | ||
44 | |||
45 | Before building XDelta, it must be configured. This is done from bash | ||
46 | in the source directory using: | ||
47 | |||
48 | ./configure --disable-shared | ||
49 | |||
50 | The parameter '--disable-shared' is needed to get round a bug in | ||
51 | libtool 1.4. libtool tries to use gcc's '-fPIC' option, which produces | ||
52 | code that binutils does not understand (for DJGPP). '-fPIC' is used | ||
53 | for generating relocatable code for dynamic linking. Since DJGPP does not | ||
54 | support dynamic linking, we can use '--disable-shared' to stop '-fPIC' | ||
55 | from being used. | ||
56 | |||
57 | For more information on the libtool problem, please see the following | ||
58 | post on djgpp-workers: | ||
59 | |||
60 | http://www.delorie.com/djgpp/mail-archives/browse.cgi?p=djgpp-workers/2001/06/18/16:32:47 | ||
61 | |||
62 | You may wish to install XDelta somewhere else. In that case, use | ||
63 | the '--prefix' option, e.g. | ||
64 | |||
65 | ./configure --disable-shared --prefix=/where/i/want/xdelta | ||
66 | |||
67 | Once this has compelted, build using: | ||
68 | |||
69 | make | ||
70 | |||
71 | If these compelte successfully, XDelta and its libraries can be installed | ||
72 | using: | ||
73 | |||
74 | make install | ||
75 | |||
76 | Some 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 | |||
107 | libxdelta and libedsio | ||
108 | ---------------------- | ||
109 | |||
110 | XDelta is actually just a front-end for two libraries - libxdelta | ||
111 | and libedsio. libxdelta is a library for handling XDelta-format deltas. | ||
112 | libedsio is a library for handling serialised I/O. Both these libraries are | ||
113 | included in the port and can be used in your own programs. | ||
114 | |||
115 | Unfortunately, there is no documentation for these libraries - the only | ||
116 | reference is the source code. If you are interested in libxdelta and libedsio, | ||
117 | please download the source distribution. Please note that I am not familiar | ||
118 | with these libraries and I will not be able to answer any queries on them. | ||
119 | |||
120 | libxdelta and libedsio come with *-config files, which return compilation | ||
121 | and 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 | |||
128 | Finally | ||
129 | ------- | ||
130 | |||
131 | If you have any comments or problems with this port, please feel free to | ||
132 | e-mail me. I hope this port is useful. | ||
133 | |||
134 | Thanks, bye, | ||
135 | |||
136 | Richard 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 @@ | |||
1 | man_MANS = xdelta.1 | ||
2 | |||
3 | EXTRA_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 | ||
27 | xdelta \- Invoke Xdelta | ||
28 | .SH SYNOPSIS | ||
29 | .B xdelta | ||
30 | .I subcommand | ||
31 | [ | ||
32 | .IR option ".\|.\|. | ||
33 | ] [ | ||
34 | .IR operand .\|.\|. | ||
35 | ] | ||
36 | .SH DESCRIPTION | ||
37 | Xdelta provides the ability to generate deltas between a pair of files | ||
38 | and later apply those deltas. It operates similar to the | ||
39 | .B diff | ||
40 | and | ||
41 | .B patch | ||
42 | commands, but works on binary files and does not produce a human | ||
43 | readable output. | ||
44 | .PP | ||
45 | |||
46 | Xdelta has three subcommands, delta, patch, and info. Delta accepts | ||
47 | two file versions and produces a delta, while patch accepts the | ||
48 | original file version and delta and produces the second version. The | ||
49 | info command prints useful information about a delta. Each subcommand | ||
50 | will be detailed seperately. | ||
51 | |||
52 | .SS Gzip processing | ||
53 | Attempting to compute a delta between compressed input files usually | ||
54 | results in poor compression. This is because small differences | ||
55 | between the original contents causes changes in the compression of | ||
56 | whole blocks of data. To simplify things, Xdelta implements a special | ||
57 | case for | ||
58 | .IR gzip (1) | ||
59 | compressed files. If any version input to the delta command is | ||
60 | recognized as having gzip compression, it will be automatically | ||
61 | decompressed into a temporary location prior to comparison. This | ||
62 | temporary location is either the value of the | ||
63 | .IR TMPDIR | ||
64 | environment variable, if set, otherwise "/tmp". | ||
65 | |||
66 | The Xdelta patch header contains a flag indicating that the | ||
67 | reconstructed version should be recompressed after applying the | ||
68 | patch. In general, this allows Xdelta to operate transparently on | ||
69 | gzip compressed inputs. | ||
70 | |||
71 | There is one potential problem when automatically processing gzip | ||
72 | compressed files, which is that the recompressed content does not | ||
73 | always match byte-for-byte with the original compressed content. The | ||
74 | uncompressed content still matches, but if there is an external | ||
75 | integrity check such as cryptographic signature verification, it may | ||
76 | fail. To prevent this from happening, the --pristine option disables | ||
77 | automatic gzip processing. | ||
78 | |||
79 | .SS MD5 integrity check | ||
80 | By default, Xdelta always verifies the MD5 checksum of the files it | ||
81 | reconstructs. This prevents you from supplying an incorrect input | ||
82 | during patch, which would result in corrupt output. Because of this | ||
83 | feature, you can feel confident that patch has produced valid results. | ||
84 | The --noverify option disables MD5 verification, but this is only | ||
85 | recommended for performance testing. | ||
86 | |||
87 | .SS Compressed patch format | ||
88 | Xdelta uses a fairly simple encoding for its delta, then applies zlib | ||
89 | compression to the result. You should not have to post-compress an | ||
90 | Xdelta delta. | ||
91 | |||
92 | .SS Delta | ||
93 | The 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 | |||
104 | Computes a delta from | ||
105 | .IR fromfile | ||
106 | to | ||
107 | .IR tofile | ||
108 | and writes it to | ||
109 | .IR patchout | ||
110 | |||
111 | .SS Patch | ||
112 | The 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 | |||
126 | Applies | ||
127 | .IR patchin | ||
128 | to | ||
129 | .IR fromfile | ||
130 | and produces a reconstructed version of | ||
131 | .IR tofile. | ||
132 | |||
133 | If fromfile was omitted, Xdelta attempts to use the original fromfile | ||
134 | name, which is stored in the delta. The from file must be identical | ||
135 | to the one used to create the delta. If its length or MD5 checksum | ||
136 | differs, patch will abort with an error message. | ||
137 | |||
138 | If tofile was omitted, Xdelta attempts to use the original tofile | ||
139 | name, which is also stored in the delta. If the original tofile name | ||
140 | already exists, a unique filename extension will be added to avoid | ||
141 | destroying any existing data. | ||
142 | |||
143 | .SS Info | ||
144 | The info subcommand has the following synopsis: | ||
145 | |||
146 | .B xdelta | ||
147 | .I info | ||
148 | .IR patchinfo | ||
149 | |||
150 | Prints information about | ||
151 | .IR patchinfo | ||
152 | and the version it reconstructs, including file names, lengths, and | ||
153 | MD5 checksums. | ||
154 | |||
155 | .SS Options | ||
156 | |||
157 | .IP -0..9 | ||
158 | Set the zlib compression level. Zero indicates no compression. Nine | ||
159 | indicates maximum compression. | ||
160 | |||
161 | .IP "-h, --help" | ||
162 | Print a short help message and exit. | ||
163 | |||
164 | .IP "-q, --quiet" | ||
165 | Quiet. Surpresses several warning messages. | ||
166 | |||
167 | .IP "-v, --version" | ||
168 | Print the Xdelta version number and exit. | ||
169 | |||
170 | .IP "-V, --verbose" | ||
171 | Verbose. Prints a bit of extra information. | ||
172 | |||
173 | .IP "-n, --noverify" | ||
174 | No verify. Turns off MD5 checksum verification of the input and | ||
175 | output files. | ||
176 | |||
177 | .IP "-m=SIZE, --maxmem=SIZE" | ||
178 | Set an upper bound on the size of an in-memory page cache. For | ||
179 | example, --maxmem=32M will use a 32 megabyte page cache. | ||
180 | |||
181 | .IP "-s=BLOCK_SIZE" | ||
182 | Set the block size, unless it was hard coded (20% speed improvement). | ||
183 | Should be a power of 2. | ||
184 | |||
185 | .IP "-p, --pristine" | ||
186 | Disable the automatic decompression of gzipped inputs, to prevent | ||
187 | unexpected differences in the re-compressed content. | ||
188 | |||
189 | .SH RETURN VALUES | ||
190 | The delta command exits with status 0 to indicate that no differences | ||
191 | were found, with status 1 to indicate that some differences were | ||
192 | found, and with status 2 to indicate an error of some kind. The patch | ||
193 | and info commands exit with status 0 on success and 2 on failure. | ||
194 | |||
195 | .SH IDENTIFICATION | ||
196 | Author: Joshua P. MacDonald, jmacd@cs.berkeley.edu | ||
197 | .br | ||
198 | .\" $Format: "Manual Page Revision: $Revision$; Release Date: $ProjectDate$."$ | ||
199 | Manual Page Revision: 1.6; Release Date: Sun, 28 Jan 2007 10:02:26 -0800. | ||
200 | .br | ||
201 | Copyright \(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 @@ | |||
1 | Xdelta(1) Xdelta(1) | ||
2 | |||
3 | NAME | ||
4 | xdelta - Invoke Xdelta | ||
5 | |||
6 | SYNOPSIS | ||
7 | xdelta subcommand [ option... ] [ operand... ] | ||
8 | |||
9 | DESCRIPTION | ||
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 | |||
135 | IDENTIFICATION | ||
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 | |||
85 | char *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. */ | ||
100 | int 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 | |||
109 | static char *nextchar; | ||
110 | |||
111 | /* Callers store zero here to inhibit the error message | ||
112 | for unrecognized options. */ | ||
113 | |||
114 | int 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 | |||
120 | int 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 | |||
151 | static enum | ||
152 | { | ||
153 | REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER | ||
154 | } ordering; | ||
155 | |||
156 | /* Value of POSIXLY_CORRECT environment variable. */ | ||
157 | static 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 | |||
171 | char *getenv (); | ||
172 | |||
173 | static char * | ||
174 | my_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. */ | ||
195 | extern 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 | |||
207 | static int first_nonopt; | ||
208 | static 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 | |||
219 | static void | ||
220 | exchange (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 | |||
277 | static 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 | |||
367 | int | ||
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 | |||
665 | int | ||
666 | getopt (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 | |||
684 | int | ||
685 | main (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 | ||
22 | extern "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 | |||
31 | extern 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 | |||
45 | extern int optind; | ||
46 | |||
47 | /* Callers store zero here to inhibit the error message `getopt' prints | ||
48 | for unrecognized options. */ | ||
49 | |||
50 | extern int opterr; | ||
51 | |||
52 | /* Set to an option character which was unrecognized. */ | ||
53 | |||
54 | extern 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 | |||
77 | struct 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. */ | ||
102 | extern int getopt (int argc, char *const *argv, const char *shortopts); | ||
103 | #else /* not __GNU_LIBRARY__ */ | ||
104 | extern int getopt (); | ||
105 | #endif /* not __GNU_LIBRARY__ */ | ||
106 | extern int getopt_long (int argc, char *const *argv, const char *shortopts, | ||
107 | const struct option *longopts, int *longind); | ||
108 | extern 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. */ | ||
113 | extern 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__ */ | ||
118 | extern int getopt (); | ||
119 | extern int getopt_long (); | ||
120 | extern int getopt_long_only (); | ||
121 | |||
122 | extern 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 | ||
51 | char *getenv (); | ||
52 | #endif | ||
53 | |||
54 | #ifndef NULL | ||
55 | #define NULL 0 | ||
56 | #endif | ||
57 | |||
58 | int | ||
59 | getopt_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 | |||
74 | int | ||
75 | getopt_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 | |||
92 | int | ||
93 | main (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 | |||
2 | INCLUDES = $(GLIB_CFLAGS) | ||
3 | |||
4 | noinst_SCRIPTS = edsio-comp | ||
5 | |||
6 | lib_LTLIBRARIES = libedsio.la | ||
7 | |||
8 | noinst_PROGRAMS = edsiotest | ||
9 | |||
10 | edsiotest_SOURCES = edsiotest.c | ||
11 | |||
12 | edsiotest_LDADD = libedsio.la $(GLIB_LIBS) | ||
13 | |||
14 | noinst_HEADERS = maketime.h partime.h | ||
15 | |||
16 | include_HEADERS = edsio.h edsio_edsio.h | ||
17 | |||
18 | libedsio_la_LIBADD = $(GLIB_LIBS) | ||
19 | |||
20 | libedsio_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 | |||
34 | EXTRA_DIST = edsio.el edsio.ser $(SER_OUT1) edsio-comp.in edsio.prj stamp-ser1 | ||
35 | |||
36 | # | ||
37 | # Rules for the generated code | ||
38 | # | ||
39 | |||
40 | stamp-ser1: $(top_srcdir)/libedsio/edsio.el edsio.ser | ||
41 | $(top_srcdir)/libedsio/edsio-comp edsio.ser | ||
42 | touch stamp-ser1 | ||
43 | |||
44 | SER_OUT1 = edsio_edsio.c edsio_edsio.h | ||
45 | |||
46 | $(SER_OUT1): stamp-ser1 | ||
47 | |||
48 | BUILT_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 | |||
15 | static 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 | |||
23 | static gint16 base64_inverse_table[128]; | ||
24 | |||
25 | static void | ||
26 | init_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 | |||
40 | GByteArray* | ||
41 | edsio_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 | |||
61 | gboolean | ||
62 | edsio_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 | |||
102 | GByteArray* | ||
103 | edsio_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 | |||
123 | gboolean | ||
124 | edsio_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 | */ | ||
210 | typedef struct _Base64Sink Base64Sink; | ||
211 | |||
212 | static gboolean base64_sink_close (SerialSink* sink); | ||
213 | static gboolean base64_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len); | ||
214 | static void base64_sink_free (SerialSink* sink); | ||
215 | static gboolean base64_sink_quantum (SerialSink* sink); | ||
216 | |||
217 | struct _Base64Sink | ||
218 | { | ||
219 | SerialSink sink; | ||
220 | |||
221 | SerialSink* out; | ||
222 | |||
223 | guint32 word; | ||
224 | guint32 count; | ||
225 | }; | ||
226 | |||
227 | SerialSink* | ||
228 | serializeio_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 | |||
245 | gboolean | ||
246 | base64_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 | |||
288 | gboolean | ||
289 | base64_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 | |||
352 | void | ||
353 | base64_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 | |||
362 | gboolean | ||
363 | base64_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 | |||
376 | typedef struct _Base64Source Base64Source; | ||
377 | |||
378 | struct _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 | |||
390 | static gboolean base64_source_close (SerialSource* source); | ||
391 | static gboolean base64_source_read (SerialSource* source, guint8 *ptr, guint32 len); | ||
392 | static void base64_source_free (SerialSource* source); | ||
393 | |||
394 | SerialSource* | ||
395 | serializeio_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 | |||
413 | gboolean | ||
414 | base64_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 | |||
424 | gboolean | ||
425 | base64_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 | |||
517 | void | ||
518 | base64_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 | |||
15 | static gboolean | ||
16 | sink_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 | |||
28 | static gboolean | ||
29 | sink_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 | |||
36 | static gboolean | ||
37 | sink_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 | |||
44 | static gboolean | ||
45 | sink_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 | |||
71 | static gboolean | ||
72 | sink_next_uint8 (SerialSink* sink, guint8 val) | ||
73 | { | ||
74 | return sink->sink_write (sink, &val, 1); | ||
75 | } | ||
76 | |||
77 | static gboolean | ||
78 | sink_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 | |||
85 | static gboolean | ||
86 | sink_next_string (SerialSink* sink, const char *ptr) | ||
87 | { | ||
88 | return sink->next_bytes (sink, ptr, strlen (ptr)); | ||
89 | } | ||
90 | |||
91 | static gboolean | ||
92 | sink_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 | |||
98 | static gboolean | ||
99 | sink_next_bytes_known (SerialSink* sink, const guint8 *ptr, guint32 len) | ||
100 | { | ||
101 | return sink->sink_write (sink, ptr, len); | ||
102 | } | ||
103 | |||
104 | void | ||
105 | serializeio_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 | |||
140 | static SerialType | ||
141 | source_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 | |||
159 | static gboolean | ||
160 | source_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 | |||
172 | static gboolean | ||
173 | source_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 | |||
185 | static gboolean | ||
186 | source_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 | |||
221 | static gboolean | ||
222 | source_next_uint8 (SerialSource* source, guint8 *ptr) | ||
223 | { | ||
224 | return source->source_read (source, ptr, 1); | ||
225 | } | ||
226 | |||
227 | static gboolean | ||
228 | source_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 | |||
243 | static gboolean | ||
244 | source_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 | |||
262 | static gboolean | ||
263 | source_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 | |||
280 | static gboolean | ||
281 | source_next_bytes_known (SerialSource* source, guint8 *ptr, guint32 len) | ||
282 | { | ||
283 | return source->source_read (source, ptr, len); | ||
284 | } | ||
285 | |||
286 | void* | ||
287 | serializeio_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 | |||
310 | void | ||
311 | serializeio_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 | |||
22 | EMACS=@EMACS@ | ||
23 | TOP_SRCDIR=@top_srcdir_absolute@/libedsio | ||
24 | |||
25 | SCRIPT=$TMPDIR/script.$$ | ||
26 | |||
27 | trap "rm -f $SCRIPT" 0 | ||
28 | |||
29 | if test $# != 1; then | ||
30 | echo 1>&2 "usage: $0 INPUT" | ||
31 | exit 1 | ||
32 | else | ||
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 | ||
46 | fi | ||
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 | |||
31 | static GHashTable* all_event_defs = NULL; | ||
32 | |||
33 | static GPtrArray* all_event_watchers = NULL; | ||
34 | |||
35 | typedef struct _ErrorDeliveryWatcher ErrorDeliveryWatcher; | ||
36 | typedef struct _DelayedEvent DelayedEvent; | ||
37 | |||
38 | struct _ErrorDeliveryWatcher { | ||
39 | ErrorDeliveryFunc deliver; | ||
40 | }; | ||
41 | |||
42 | struct _DelayedEvent { | ||
43 | GenericEvent ev; | ||
44 | GenericEventDef *def; | ||
45 | const char *msg; | ||
46 | }; | ||
47 | |||
48 | void | ||
49 | eventdelivery_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 | |||
71 | void | ||
72 | eventdelivery_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 | |||
84 | GenericEventDef* | ||
85 | eventdelivery_event_lookup (gint code) | ||
86 | { | ||
87 | return g_hash_table_lookup (all_event_defs, & code); | ||
88 | } | ||
89 | |||
90 | void | ||
91 | eventdelivery_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 | |||
240 | const char* | ||
241 | eventdelivery_int_to_string (int x) | ||
242 | { | ||
243 | return g_strdup_printf ("%d", x); | ||
244 | } | ||
245 | |||
246 | const char* | ||
247 | eventdelivery_string_to_string (const char* x) | ||
248 | { | ||
249 | return g_strdup (x); | ||
250 | } | ||
251 | |||
252 | const char* | ||
253 | eventdelivery_source_to_string (SerialSource* x) | ||
254 | { | ||
255 | return g_strdup ("@@@SerialSource"); | ||
256 | } | ||
257 | |||
258 | const char* | ||
259 | eventdelivery_sink_to_string (SerialSink* x) | ||
260 | { | ||
261 | return g_strdup ("@@@SerialSink"); | ||
262 | } | ||
263 | |||
264 | const char* | ||
265 | eventdelivery_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 | |||
275 | gboolean | ||
276 | edsio_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 | |||
323 | gchar* | ||
324 | edsio_time_to_iso8601 (SerialGenericTime *tp) | ||
325 | { | ||
326 | return edsio_time_t_to_iso8601 (tp->seconds); | ||
327 | } | ||
328 | |||
329 | gchar* | ||
330 | edsio_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(<, 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 | |||
356 | static gboolean | ||
357 | strtosl_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 | |||
375 | gboolean | ||
376 | strtosi_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 | |||
400 | gboolean | ||
401 | strtoss_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 | |||
425 | gboolean | ||
426 | strtoui_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 | |||
459 | gboolean | ||
460 | strtous_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 | |||
493 | gint | ||
494 | edsio_md5_equal (gconstpointer v, | ||
495 | gconstpointer v2) | ||
496 | { | ||
497 | return memcmp (v, v2, 16) == 0; | ||
498 | } | ||
499 | |||
500 | guint | ||
501 | edsio_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 | |||
513 | void | ||
514 | serializeio_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 | |||
531 | void | ||
532 | edsio_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 | |||
540 | static gboolean | ||
541 | from_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 | |||
568 | gboolean | ||
569 | edsio_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 | |||
606 | const 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 | |||
619 | typedef struct _EdsioHostType EdsioHostType; | ||
620 | typedef struct _EdsioPropertyType EdsioPropertyType; | ||
621 | |||
622 | struct _EdsioPropertyType { | ||
623 | const char *type_name; | ||
624 | PropFreeFunc freer; | ||
625 | PropGSFunc getter; | ||
626 | PropGSFunc setter; | ||
627 | PropSerialize serialize; | ||
628 | PropUnserialize unserialize; | ||
629 | }; | ||
630 | |||
631 | struct _EdsioHostType { | ||
632 | const char *host_name; | ||
633 | PropertyTableFunc ptable; | ||
634 | PersistSourceFunc source; | ||
635 | PersistSinkFunc sink; | ||
636 | PersistIssetFunc isset; | ||
637 | PersistUnsetFunc unset; | ||
638 | }; | ||
639 | |||
640 | struct _EdsioProperty { | ||
641 | guint32 prop_code; | ||
642 | const char *prop_name; | ||
643 | guint32 prop_flags; | ||
644 | EdsioPropertyType *type; | ||
645 | EdsioHostType *host; | ||
646 | }; | ||
647 | |||
648 | union _EdsioPropertyEntry { | ||
649 | guint32 as_uint32; | ||
650 | SerialEdsioBytes as_bytes; | ||
651 | gpointer as_vptr; | ||
652 | const char* as_string; | ||
653 | }; | ||
654 | |||
655 | struct _EdsioGenericProperty | ||
656 | { | ||
657 | guint32 code; | ||
658 | }; | ||
659 | |||
660 | static GHashTable* all_property_types = NULL; | ||
661 | static GHashTable* all_host_types = NULL; | ||
662 | static GHashTable* all_properties = NULL; | ||
663 | static GHashTable* all_property_codes = NULL; | ||
664 | static guint32 property_code_sequence = 0; | ||
665 | |||
666 | void | ||
667 | edsio_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 | |||
698 | void | ||
699 | edsio_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 | |||
732 | gboolean | ||
733 | edsio_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 | |||
792 | static EdsioProperty* | ||
793 | edsio_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 | |||
827 | EdsioPropertyEntry* | ||
828 | edsio_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 | |||
872 | gboolean | ||
873 | edsio_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 | |||
917 | gboolean | ||
918 | edsio_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 | |||
958 | gboolean | ||
959 | edsio_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 | |||
1001 | static gboolean | ||
1002 | edsio_false () | ||
1003 | { | ||
1004 | return FALSE; | ||
1005 | } | ||
1006 | |||
1007 | PropGSFunc | ||
1008 | edsio_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 | |||
1016 | PropGSFunc | ||
1017 | edsio_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 | */ | ||
1030 | gboolean | ||
1031 | edsio_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 | |||
1043 | gboolean | ||
1044 | edsio_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 | |||
1053 | void | ||
1054 | edsio_property_uint_free (gpointer obj) | ||
1055 | { | ||
1056 | g_free (obj); | ||
1057 | } | ||
1058 | |||
1059 | gboolean | ||
1060 | unserialize_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 | |||
1079 | gboolean | ||
1080 | serialize_uint_obj (SerialSink *sink, guint32* x) | ||
1081 | { | ||
1082 | return serialize_edsiouint (sink, *x); | ||
1083 | } | ||
1084 | |||
1085 | /* String | ||
1086 | */ | ||
1087 | |||
1088 | void | ||
1089 | edsio_property_string_free (gpointer obj) | ||
1090 | { | ||
1091 | g_free (obj); | ||
1092 | } | ||
1093 | |||
1094 | gboolean | ||
1095 | edsio_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 | |||
1103 | gboolean | ||
1104 | edsio_property_string_setter (gpointer obj, EdsioProperty* prop, const char* set) | ||
1105 | { | ||
1106 | return edsio_property_set (obj, prop, (EdsioPropertyEntry*) set); | ||
1107 | } | ||
1108 | |||
1109 | gboolean | ||
1110 | unserialize_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 | |||
1124 | gboolean | ||
1125 | serialize_string_obj (SerialSink *sink, const char* x) | ||
1126 | { | ||
1127 | return serialize_edsiostring (sink, x); | ||
1128 | } | ||
1129 | |||
1130 | /* Bytes | ||
1131 | */ | ||
1132 | |||
1133 | gboolean | ||
1134 | unserialize_bytes (SerialSource *source, SerialEdsioBytes** x) | ||
1135 | { | ||
1136 | return unserialize_edsiobytes (source, x); | ||
1137 | } | ||
1138 | |||
1139 | gboolean | ||
1140 | serialize_bytes_obj (SerialSink *sink, SerialEdsioBytes *x) | ||
1141 | { | ||
1142 | return serialize_edsiobytes_obj (sink, x); | ||
1143 | } | ||
1144 | |||
1145 | gboolean | ||
1146 | edsio_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 | |||
1159 | gboolean | ||
1160 | edsio_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 | |||
1170 | void | ||
1171 | edsio_property_bytes_free (gpointer obj) | ||
1172 | { | ||
1173 | g_free (obj); | ||
1174 | } | ||
1175 | |||
1176 | /* Vptr | ||
1177 | */ | ||
1178 | |||
1179 | gboolean | ||
1180 | edsio_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 | |||
1188 | gboolean | ||
1189 | edsio_property_vptr_setter (gpointer obj, EdsioProperty* prop, void* set) | ||
1190 | { | ||
1191 | return edsio_property_set (obj, prop, (EdsioPropertyEntry*) set); | ||
1192 | } | ||
1193 | |||
1194 | void | ||
1195 | edsio_property_vptr_free (gpointer obj) | ||
1196 | { | ||
1197 | /* nothing */ | ||
1198 | } | ||
1199 | |||
1200 | /* Testing | ||
1201 | */ | ||
1202 | |||
1203 | #ifdef DEBUG_LIBEDSIO | ||
1204 | |||
1205 | GHashTable** | ||
1206 | edsio_proptest_property_table (PropTest *pt) | ||
1207 | { | ||
1208 | return & pt->_edsio_property_table; | ||
1209 | } | ||
1210 | |||
1211 | SerialSource* | ||
1212 | edsio_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 | |||
1231 | static void | ||
1232 | pt_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 | |||
1249 | SerialSink* | ||
1250 | edsio_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 | |||
1257 | gboolean | ||
1258 | edsio_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 | |||
1266 | gboolean | ||
1267 | edsio_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 | |||
1291 | SerialSink* | ||
1292 | serializeio_gzip_sink (SerialSink* sink) | ||
1293 | { | ||
1294 | /* @@@ not implemented */ | ||
1295 | return sink; | ||
1296 | } | ||
1297 | |||
1298 | SerialSource* | ||
1299 | serializeio_gzip_source (SerialSource* source) | ||
1300 | { | ||
1301 | /* @@@ not implemented */ | ||
1302 | return source; | ||
1303 | } | ||
1304 | |||
1305 | /* Checksum sink | ||
1306 | */ | ||
1307 | typedef struct _ChecksumSink ChecksumSink; | ||
1308 | |||
1309 | static gboolean checksum_sink_close (SerialSink* sink); | ||
1310 | static gboolean checksum_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len); | ||
1311 | static void checksum_sink_free (SerialSink* sink); | ||
1312 | static gboolean checksum_sink_quantum (SerialSink* sink); | ||
1313 | |||
1314 | struct _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 | |||
1326 | SerialSink* | ||
1327 | serializeio_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 | |||
1346 | gboolean | ||
1347 | checksum_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 | |||
1359 | gboolean | ||
1360 | checksum_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 | |||
1379 | void | ||
1380 | checksum_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 | |||
1389 | gboolean | ||
1390 | checksum_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 | |||
1403 | typedef struct _ChecksumSource ChecksumSource; | ||
1404 | |||
1405 | struct _ChecksumSource { | ||
1406 | SerialSource source; | ||
1407 | |||
1408 | SerialSource *in; | ||
1409 | |||
1410 | EdsioMD5Ctx ctx; | ||
1411 | }; | ||
1412 | |||
1413 | static gboolean checksum_source_close (SerialSource* source); | ||
1414 | static gboolean checksum_source_read (SerialSource* source, guint8 *ptr, guint32 len); | ||
1415 | static void checksum_source_free (SerialSource* source); | ||
1416 | |||
1417 | SerialSource* | ||
1418 | serializeio_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 | |||
1438 | gboolean | ||
1439 | checksum_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 | |||
1462 | gboolean | ||
1463 | checksum_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 | |||
1475 | void | ||
1476 | checksum_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 | |||
1488 | GQueue * | ||
1489 | g_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 | |||
1500 | void | ||
1501 | g_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 | |||
1512 | guint | ||
1513 | g_queue_get_size (GQueue *q) | ||
1514 | { | ||
1515 | return (q == NULL) ? 0 : q->list_size; | ||
1516 | } | ||
1517 | |||
1518 | |||
1519 | void | ||
1520 | g_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 | |||
1534 | void | ||
1535 | g_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 | |||
1551 | gpointer | ||
1552 | g_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 | |||
1582 | gpointer | ||
1583 | g_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 | ||
20 | definition file so that operations may be performed on everything in | ||
21 | the 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 | ||
536 | replacement 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 | ||
14 | extern "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 | |||
25 | typedef struct _SerialSource SerialSource; | ||
26 | typedef struct _SerialSink SerialSink; | ||
27 | typedef gint32 SerialType; | ||
28 | typedef struct _HandleFuncTable HandleFuncTable; | ||
29 | typedef struct _PropTest PropTest; | ||
30 | typedef struct _FileHandle FileHandle; | ||
31 | typedef struct _AllocList AllocList; | ||
32 | |||
33 | struct _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 */ | ||
53 | struct _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 | |||
70 | struct _AllocList { | ||
71 | AllocList *next; | ||
72 | void *ptr; | ||
73 | }; | ||
74 | |||
75 | struct _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 | |||
106 | struct _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 | |||
131 | void 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 | |||
138 | const char* serializeio_generic_type_to_string (SerialType type); | ||
139 | void serializeio_generic_print (SerialType type, void* object, guint indent_spaces); | ||
140 | |||
141 | gboolean serializeio_serialize_generic (SerialSink *sink, | ||
142 | SerialType object_type, | ||
143 | void *object); | ||
144 | |||
145 | gboolean serializeio_serialize_generic_internal (SerialSink *sink, | ||
146 | SerialType object_type, | ||
147 | void *object, | ||
148 | gboolean set_allocation); | ||
149 | |||
150 | guint serializeio_generic_count (SerialType object_type, | ||
151 | void *object); | ||
152 | |||
153 | gboolean serializeio_unserialize_generic (SerialSource *source, | ||
154 | SerialType *object_type, | ||
155 | void **object); | ||
156 | |||
157 | gboolean serializeio_unserialize_generic_internal (SerialSource *source, | ||
158 | SerialType *object_type, | ||
159 | void **object, | ||
160 | gboolean set_allocation); | ||
161 | |||
162 | gboolean serializeio_unserialize_generic_acceptable (SerialSource* source, | ||
163 | guint32 acceptable, | ||
164 | SerialType *object_type, | ||
165 | void **object); | ||
166 | |||
167 | void 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 | |||
179 | void 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. */ | ||
193 | void* serializeio_source_alloc (SerialSource* source, | ||
194 | guint32 len); | ||
195 | |||
196 | SerialSink* serializeio_gzip_sink (SerialSink* sink); | ||
197 | SerialSource* serializeio_gzip_source (SerialSource* source); | ||
198 | |||
199 | SerialSink* serializeio_checksum_sink (SerialSink* sink); | ||
200 | SerialSource* serializeio_checksum_source (SerialSource* source); | ||
201 | |||
202 | SerialSink* serializeio_base64_sink (SerialSink* sink); | ||
203 | SerialSource* serializeio_base64_source (SerialSource* source); | ||
204 | |||
205 | SerialSource* handle_source (FileHandle *fh); | ||
206 | SerialSink* handle_sink (FileHandle *fh, | ||
207 | gpointer data1, | ||
208 | gpointer data2, | ||
209 | gpointer data3, | ||
210 | gboolean (* cont_onclose) (gpointer data1, gpointer data2, gpointer data3)); | ||
211 | |||
212 | gboolean unserialize_uint (SerialSource *source, guint32** x); | ||
213 | gboolean serialize_uint_obj (SerialSink *sink, guint32* x); | ||
214 | |||
215 | gboolean unserialize_string (SerialSource *source, const char** x); | ||
216 | gboolean 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. */ | ||
220 | gboolean unserialize_bytes (SerialSource *source, SerialEdsioBytes** x); | ||
221 | gboolean serialize_bytes_obj (SerialSink *sink, SerialEdsioBytes *x); | ||
222 | |||
223 | /* Event delivery | ||
224 | */ | ||
225 | |||
226 | enum _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 | |||
235 | typedef enum _EventLevel EventLevel; | ||
236 | |||
237 | enum _EventFlags | ||
238 | { | ||
239 | EF_None = 1<<0, | ||
240 | EF_OpenSSL = 1<<1 | ||
241 | }; | ||
242 | |||
243 | typedef enum _EventFlags EventFlags; | ||
244 | |||
245 | const char* eventdelivery_int_to_string (int x); | ||
246 | const char* eventdelivery_string_to_string (const char* x); | ||
247 | const char* eventdelivery_source_to_string (SerialSource* x); | ||
248 | const char* eventdelivery_sink_to_string (SerialSink* x); | ||
249 | const char* eventdelivery_handle_to_string (FileHandle* x); | ||
250 | |||
251 | void serializeio_print_bytes (const guint8* buf, guint len); | ||
252 | |||
253 | /* Event delivery privates | ||
254 | */ | ||
255 | |||
256 | typedef struct _GenericEventDef GenericEventDef; | ||
257 | typedef struct _GenericEvent GenericEvent; | ||
258 | |||
259 | struct _GenericEvent | ||
260 | { | ||
261 | gint code; | ||
262 | const char* srcfile; | ||
263 | guint srcline; | ||
264 | }; | ||
265 | |||
266 | GenericEventDef* eventdelivery_event_lookup (gint code); | ||
267 | |||
268 | void eventdelivery_event_deliver (GenericEvent* e); | ||
269 | |||
270 | typedef gboolean (* ErrorDeliveryFunc) (GenericEvent* ev, GenericEventDef* def, const char* message); | ||
271 | |||
272 | void eventdelivery_event_watch_all (ErrorDeliveryFunc func); | ||
273 | |||
274 | void 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 | |||
281 | const char* eventdelivery_ssl_errors_to_string (void); | ||
282 | |||
283 | struct _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. */ | ||
319 | typedef 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 | |||
325 | void edsio_md5_init (EdsioMD5Ctx *); | ||
326 | void edsio_md5_update (EdsioMD5Ctx *, const guint8 *, guint); | ||
327 | void edsio_md5_final (guint8*, EdsioMD5Ctx *); | ||
328 | |||
329 | gint edsio_md5_equal (gconstpointer v, | ||
330 | gconstpointer v2); | ||
331 | guint edsio_md5_hash (gconstpointer v); | ||
332 | |||
333 | void edsio_md5_to_string (const guint8* md5, char buf[33]); | ||
334 | gboolean 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 | |||
343 | typedef 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 | |||
350 | void edsio_sha_init (EdsioSHACtx *); | ||
351 | void edsio_sha_update (EdsioSHACtx *, const guint8 *, guint); | ||
352 | void edsio_sha_final (guint8 *, EdsioSHACtx *); | ||
353 | |||
354 | gint edsio_sha_equal (gconstpointer v, | ||
355 | gconstpointer v2); | ||
356 | guint 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 | */ | ||
365 | gboolean strtosi_checked (const char* str, gint32* i, const char* errmsg); | ||
366 | gboolean strtoss_checked (const char* str, gint16* s, const char* errmsg); | ||
367 | |||
368 | gboolean strtoui_checked (const char* str, guint32* i, const char* errmsg); | ||
369 | gboolean strtous_checked (const char* str, guint16* i, const char* errmsg); | ||
370 | |||
371 | const char* edsio_intern_string (const char* str); | ||
372 | |||
373 | GByteArray* edsio_base64_encode_region (const guint8* data, guint data_len); | ||
374 | GByteArray* edsio_base64_decode_region (const guint8* data, guint data_len); | ||
375 | gboolean edsio_base64_encode_region_into (const guint8* data, guint data_len, guint8* out, guint *out_len); | ||
376 | gboolean edsio_base64_decode_region_into (const guint8* data, guint data_len, guint8* out, guint *out_len); | ||
377 | |||
378 | gchar* edsio_time_to_iso8601 (SerialGenericTime* time); | ||
379 | gchar* edsio_time_t_to_iso8601 (GTime time); | ||
380 | gboolean edsio_time_of_day (SerialGenericTime* time); | ||
381 | |||
382 | enum _SimpleBufferFlags { | ||
383 | SBF_None = 0, | ||
384 | SBF_Compress = 1 << 0, | ||
385 | SBF_Checksum = 1 << 1, | ||
386 | SBF_Base64 = 1 << 2 | ||
387 | }; | ||
388 | |||
389 | typedef enum _SimpleBufferFlags SimpleBufferFlags; | ||
390 | |||
391 | SerialSource* edsio_simple_source (const guint8* data, guint len, guint flags); | ||
392 | SerialSink* edsio_simple_sink (gpointer data, | ||
393 | guint flags, | ||
394 | gboolean free_result, | ||
395 | void (* success) (gpointer data, GByteArray* result), | ||
396 | GByteArray **result); | ||
397 | |||
398 | gboolean edsio_library_check (guint32 number); | ||
399 | void edsio_library_register (guint32 number, const char*name); | ||
400 | |||
401 | /* (Persistent) Property stuff. | ||
402 | */ | ||
403 | |||
404 | enum _PropertyFlags { | ||
405 | PF_None = 0, | ||
406 | PF_Persistent = 1 | ||
407 | }; | ||
408 | |||
409 | typedef enum _PropertyFlags PropertyFlags; | ||
410 | |||
411 | typedef struct _EdsioProperty EdsioProperty; | ||
412 | typedef union _EdsioPropertyEntry EdsioPropertyEntry; | ||
413 | typedef struct _EdsioGenericProperty EdsioGenericProperty; | ||
414 | |||
415 | typedef void (* PropFreeFunc) (gpointer obj); | ||
416 | typedef gboolean (* PropGSFunc) (/*gpointer obj, GHashTable** obj_table, EdsioProperty* prop, ... */); | ||
417 | typedef gboolean (* PropSerialize) (/*SerialSink* sink, ... */); | ||
418 | typedef gboolean (* PropUnserialize) (/*SerialSource* source, ... */); | ||
419 | |||
420 | typedef GHashTable** (* PropertyTableFunc) (gpointer obj); | ||
421 | typedef SerialSource* (* PersistSourceFunc) (gpointer obj, const char* prop_name); | ||
422 | typedef SerialSink* (* PersistSinkFunc) (gpointer obj, const char* prop_name); | ||
423 | typedef gboolean (* PersistIssetFunc) (gpointer obj, const char* prop_name); | ||
424 | typedef gboolean (* PersistUnsetFunc) (gpointer obj, const char* prop_name); | ||
425 | |||
426 | void edsio_initialize_property_type (const char* t, PropFreeFunc freer, PropGSFunc getter, PropGSFunc setter, PropSerialize ser, PropUnserialize unser); | ||
427 | void edsio_initialize_host_type (const char* ph, | ||
428 | PropertyTableFunc ptable, | ||
429 | PersistSourceFunc source, | ||
430 | PersistSinkFunc sink, | ||
431 | PersistIssetFunc isset, | ||
432 | PersistUnsetFunc unset); | ||
433 | |||
434 | gboolean edsio_property_isset (const char* ph, const char* t, guint32 code, gpointer obj); | ||
435 | gboolean edsio_property_unset (const char* ph, const char* t, guint32 code, gpointer obj); | ||
436 | |||
437 | PropGSFunc edsio_property_getter (const char* ph, const char* t, guint32 code, EdsioProperty** prop); | ||
438 | PropGSFunc edsio_property_setter (const char* ph, const char* t, guint32 code, EdsioProperty** prop); | ||
439 | |||
440 | void edsio_property_uint_free (gpointer obj); | ||
441 | gboolean edsio_property_uint_getter (gpointer obj, EdsioProperty* ep, guint32* get); | ||
442 | gboolean edsio_property_uint_setter (gpointer obj, EdsioProperty* ep, guint32 set); | ||
443 | |||
444 | void edsio_property_string_free (gpointer obj); | ||
445 | gboolean edsio_property_string_getter (gpointer obj, EdsioProperty* ep, const char** get); | ||
446 | gboolean edsio_property_string_setter (gpointer obj, EdsioProperty* ep, const char* set); | ||
447 | |||
448 | void edsio_property_bytes_free (gpointer obj); | ||
449 | gboolean edsio_property_bytes_getter (gpointer obj, EdsioProperty* ep, guint8** get, guint32 *get_len); | ||
450 | gboolean edsio_property_bytes_setter (gpointer obj, EdsioProperty* ep, guint8* set, guint32 set_len); | ||
451 | |||
452 | void edsio_property_vptr_free (gpointer obj); | ||
453 | gboolean edsio_property_vptr_getter (gpointer obj, EdsioProperty* ep, void** get); | ||
454 | gboolean edsio_property_vptr_setter (gpointer obj, EdsioProperty* ep, void* set); | ||
455 | |||
456 | EdsioPropertyEntry* edsio_property_get (gpointer obj, EdsioProperty* ep); | ||
457 | gboolean edsio_property_set (gpointer obj, EdsioProperty* ep, EdsioPropertyEntry* set); | ||
458 | |||
459 | gboolean 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 | ||
467 | struct _PropTest | ||
468 | { | ||
469 | GHashTable* _edsio_property_table; | ||
470 | |||
471 | GHashTable* ptable; | ||
472 | |||
473 | const char* kludge; | ||
474 | }; | ||
475 | |||
476 | GHashTable** edsio_proptest_property_table (PropTest *pt); | ||
477 | SerialSource* edsio_persist_proptest_source (PropTest *pt, const char* prop_name); | ||
478 | SerialSink* edsio_persist_proptest_sink (PropTest *pt, const char* prop_name); | ||
479 | gboolean edsio_persist_proptest_isset (PropTest *pt, const char* prop_name); | ||
480 | gboolean edsio_persist_proptest_unset (PropTest *pt, const char* prop_name); | ||
481 | |||
482 | #endif | ||
483 | |||
484 | /* Missing glib stuff | ||
485 | */ | ||
486 | |||
487 | typedef struct _GQueue GQueue; | ||
488 | |||
489 | struct _GQueue | ||
490 | { | ||
491 | GList *list; | ||
492 | GList *list_end; | ||
493 | guint list_size; | ||
494 | }; | ||
495 | |||
496 | /* Queues | ||
497 | */ | ||
498 | |||
499 | GQueue * g_queue_new (void); | ||
500 | void g_queue_free (GQueue *q); | ||
501 | guint g_queue_get_size (GQueue *q); | ||
502 | void g_queue_push_front (GQueue *q, gpointer data); | ||
503 | void g_queue_push_back (GQueue *q, gpointer data); | ||
504 | gpointer g_queue_pop_front (GQueue *q); | ||
505 | gpointer 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 | |||
12 | void | ||
13 | test1 () | ||
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 | |||
45 | void | ||
46 | test2 () | ||
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 | |||
80 | void | ||
81 | test3 () | ||
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 | |||
115 | void | ||
116 | test4 () | ||
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 | |||
149 | void 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 | |||
176 | void | ||
177 | test6 () | ||
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 | |||
197 | int | ||
198 | main () | ||
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 | */ | ||
14 | typedef struct _HandleSerialSource HandleSerialSource; | ||
15 | typedef struct _HandleSerialSink HandleSerialSink; | ||
16 | |||
17 | struct _HandleSerialSource { | ||
18 | SerialSource source; | ||
19 | |||
20 | FileHandle* fh; | ||
21 | }; | ||
22 | |||
23 | struct _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 | |||
33 | static SerialType handle_source_type (SerialSource* source, gboolean set_allocation); | ||
34 | static gboolean handle_source_close (SerialSource* source); | ||
35 | static gboolean handle_source_read (SerialSource* source, guint8 *ptr, guint32 len); | ||
36 | static void handle_source_free (SerialSource* source); | ||
37 | |||
38 | static gboolean handle_sink_type (SerialSink* sink, SerialType type, guint len, gboolean set_allocation); | ||
39 | static gboolean handle_sink_close (SerialSink* sink); | ||
40 | static gboolean handle_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len); | ||
41 | static void handle_sink_free (SerialSink* sink); | ||
42 | |||
43 | SerialSource* | ||
44 | handle_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 | |||
61 | SerialSink* | ||
62 | handle_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 | |||
82 | SerialType | ||
83 | handle_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 | |||
102 | gboolean | ||
103 | handle_source_close (SerialSource* source) | ||
104 | { | ||
105 | HandleSerialSource* ssource = (HandleSerialSource*) source; | ||
106 | |||
107 | return ssource->fh->table->table_handle_close (ssource->fh, 0); | ||
108 | } | ||
109 | |||
110 | gboolean | ||
111 | handle_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 | |||
118 | void | ||
119 | handle_source_free (SerialSource* source) | ||
120 | { | ||
121 | g_free (source); | ||
122 | } | ||
123 | |||
124 | gboolean | ||
125 | handle_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 | |||
139 | gboolean | ||
140 | handle_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 | |||
155 | gboolean | ||
156 | handle_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 | |||
163 | void | ||
164 | handle_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 | |||
15 | typedef 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 | |||
24 | static GArray *ser_array; | ||
25 | static gboolean ser_array_sorted; | ||
26 | |||
27 | void | ||
28 | serializeio_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 | |||
52 | static int | ||
53 | ser_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 | |||
61 | static SerEntry* | ||
62 | serializeio_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 | |||
108 | gboolean | ||
109 | serializeio_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 | |||
133 | gboolean | ||
134 | serializeio_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 | |||
141 | gboolean | ||
142 | serializeio_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 | |||
149 | gboolean | ||
150 | serializeio_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 | |||
169 | const char* | ||
170 | serializeio_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 | |||
183 | guint | ||
184 | serializeio_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 | |||
198 | void | ||
199 | serializeio_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 | |||
218 | gboolean | ||
219 | serializeio_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 | |||
13 | typedef struct _Library Library; | ||
14 | |||
15 | struct _Library { | ||
16 | const char* name; | ||
17 | const char* libname; | ||
18 | gint index; | ||
19 | gboolean loaded; | ||
20 | }; | ||
21 | |||
22 | static Library known_libraries[] = { | ||
23 | { "xd", "xdelta", 3 }, | ||
24 | { "edsio", "edsio", 6 }, | ||
25 | }; | ||
26 | |||
27 | static GHashTable* loaded_libraries; | ||
28 | |||
29 | static void | ||
30 | edsio_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 | |||
48 | void | ||
49 | edsio_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 | |||
72 | gboolean | ||
73 | edsio_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 | |||
61 | char const maketId[] = | ||
62 | "$Id: maketime.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $"; | ||
63 | |||
64 | static int isleap P ((int)); | ||
65 | static int month_days P ((struct tm const *)); | ||
66 | static 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 | |||
75 | static int | ||
76 | isleap (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 */ | ||
83 | static 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. */ | ||
89 | static int | ||
90 | month_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. */ | ||
100 | struct tm * | ||
101 | time2tm (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. */ | ||
117 | time_t | ||
118 | difftm (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 | */ | ||
147 | void | ||
148 | adjzone (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 | */ | ||
212 | time_t | ||
213 | tm2time (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 | */ | ||
291 | static time_t | ||
292 | maketime (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. */ | ||
359 | time_t | ||
360 | str2time (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> | ||
376 | int | ||
377 | main (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 | |||
35 | struct tm *time2tm __MAKETIME_P ((time_t, int)); | ||
36 | time_t difftm __MAKETIME_P ((struct tm const *, struct tm const *)); | ||
37 | time_t str2time __MAKETIME_P ((char const *, time_t, long)); | ||
38 | time_t tm2time __MAKETIME_P ((struct tm *, int)); | ||
39 | void 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 | ||
9 | Algorithm" in all material mentioning or referencing this software | ||
10 | or this function. | ||
11 | |||
12 | License is also granted to make and use derivative works provided | ||
13 | that such works are identified as "derived from the RSA Data | ||
14 | Security, Inc. MD5 Message-Digest Algorithm" in all material | ||
15 | mentioning or referencing the derived work. | ||
16 | |||
17 | RSA Data Security, Inc. makes no representations concerning either | ||
18 | the merchantability of this software or the suitability of this | ||
19 | software for any particular purpose. It is provided "as is" | ||
20 | without express or implied warranty of any kind. | ||
21 | |||
22 | These notices must be retained in any copies of any part of this | ||
23 | documentation 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 | |||
49 | static void MD5Transform (guint32 [4], unsigned const char [64]); | ||
50 | static void Encode (unsigned char *, guint32 *, unsigned int); | ||
51 | static void Decode (guint32 *, unsigned const char *, unsigned int); | ||
52 | |||
53 | #define MD5_memcpy memcpy | ||
54 | #define MD5_memset memset | ||
55 | |||
56 | static 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 | */ | ||
99 | void 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 | */ | ||
114 | void 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 | */ | ||
153 | void 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 | */ | ||
179 | static 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 | */ | ||
270 | static 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 | */ | ||
288 | static 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 | |||
70 | char 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 | |||
78 | struct name_val | ||
79 | { | ||
80 | char name[NAME_LENGTH_MAXIMUM]; | ||
81 | int val; | ||
82 | }; | ||
83 | |||
84 | |||
85 | static char const *parse_decimal P ((char const *, int, int, int, int, int *, int *)); | ||
86 | static char const *parse_fixed P ((char const *, int, int *)); | ||
87 | static char const *parse_pattern_letter P ((char const *, int, struct partime *)); | ||
88 | static char const *parse_prefix P ((char const *, struct partime *, int *)); | ||
89 | static char const *parse_ranged P ((char const *, int, int, int, int *)); | ||
90 | static int lookup P ((char const *, struct name_val const[])); | ||
91 | static int merge_partime P ((struct partime *, struct partime const *)); | ||
92 | static void undefine P ((struct partime *)); | ||
93 | |||
94 | |||
95 | static 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 | |||
112 | static 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 | |||
129 | static 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. */ | ||
184 | static int | ||
185 | lookup (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. */ | ||
213 | static void | ||
214 | undefine (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. */ | ||
228 | static 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. */ | ||
256 | static char const * | ||
257 | parse_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. */ | ||
303 | static char const * | ||
304 | parse_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. */ | ||
325 | static char const * | ||
326 | parse_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. */ | ||
340 | static char const * | ||
341 | parse_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. */ | ||
377 | char * | ||
378 | parzone (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. */ | ||
472 | static char const * | ||
473 | parse_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. */ | ||
677 | static int | ||
678 | merge_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. */ | ||
717 | char * | ||
718 | partime (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 | |||
36 | struct 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 | |||
66 | char *partime __PARTIME_P ((char const *, struct partime *)); | ||
67 | char *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 | |||
80 | static 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 | |||
142 | static 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 | |||
163 | void 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 | |||
177 | void 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 | |||
215 | void 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 | |||
15 | typedef struct _ByteArraySource ByteArraySource; | ||
16 | |||
17 | struct _ByteArraySource { | ||
18 | SerialSource source; | ||
19 | |||
20 | const guint8* in_data; | ||
21 | guint in_len; | ||
22 | |||
23 | guint read_pos; | ||
24 | guint flags; | ||
25 | }; | ||
26 | |||
27 | static gboolean byte_array_source_close (SerialSource* source); | ||
28 | static gboolean byte_array_source_read (SerialSource* source, guint8 *ptr, guint32 len); | ||
29 | static void byte_array_source_free (SerialSource* source); | ||
30 | |||
31 | SerialSource* | ||
32 | edsio_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 | |||
61 | gboolean | ||
62 | byte_array_source_close (SerialSource* source) | ||
63 | { | ||
64 | return TRUE; | ||
65 | } | ||
66 | |||
67 | gboolean | ||
68 | byte_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 | |||
85 | void | ||
86 | byte_array_source_free (SerialSource* source) | ||
87 | { | ||
88 | g_free (source); | ||
89 | } | ||
90 | |||
91 | /* BASE64 Sink | ||
92 | */ | ||
93 | |||
94 | typedef struct _ByteArraySink ByteArraySink; | ||
95 | |||
96 | struct _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 | |||
107 | static gboolean byte_array_sink_close (SerialSink* sink); | ||
108 | static gboolean byte_array_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len); | ||
109 | static void byte_array_sink_free (SerialSink* sink); | ||
110 | |||
111 | SerialSink* | ||
112 | edsio_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 | |||
149 | gboolean | ||
150 | byte_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 | |||
160 | gboolean | ||
161 | byte_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 | |||
170 | void | ||
171 | byte_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 | |||
3 | OUT1=$TMPDIR/out1 | ||
4 | OUT2=$TMPDIR/out2 | ||
5 | OUT3=$TMPDIR/out3 | ||
6 | XDELTA=./xdelta | ||
7 | |||
8 | while 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 | ||
48 | done; | ||
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 | |||
2 | EXTRA_DIST = xdeltatest.c README.test | ||
3 | |||
4 | INCLUDES = -I$(top_srcdir)/libedsio $(GLIB_CFLAGS) | ||
5 | |||
6 | noinst_PROGRAMS = xdeltatest | ||
7 | |||
8 | xdeltatest_SOURCES = xdeltatest.c | ||
9 | |||
10 | xdeltatest_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 @@ | |||
1 | The code in this directory produces a test for Xdelta. To run it you | ||
2 | have to edit the hard-coded constants at the top of the file, which | ||
3 | include "cmd_data_source", which should be the name of a big file | ||
4 | containing source data that the test uses to construct sample inputs. | ||
5 | This allows you to test on whatever kind of data you want, but the | ||
6 | synthetic edits are still hardcoded. Have a look. | ||
7 | |||
8 | Of course, a better test would let you run it without any | ||
9 | configuration, 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 | |||
57 | const char* cmd_data_source = "/tmp/big.1"; | ||
58 | guint cmd_size = 1<<20; | ||
59 | |||
60 | guint cmd_warmups = 2; | ||
61 | guint cmd_reps = 20; | ||
62 | |||
63 | guint cmd_changes = 1000; | ||
64 | guint cmd_deletion_length = 30; | ||
65 | guint 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 | |||
78 | typedef struct _File File; | ||
79 | typedef struct _Patch Patch; | ||
80 | typedef struct _TestProfile TestProfile; | ||
81 | typedef struct _Instruction Instruction; | ||
82 | |||
83 | struct _Instruction { | ||
84 | guint32 offset; | ||
85 | guint32 length; | ||
86 | Instruction* next; | ||
87 | }; | ||
88 | |||
89 | struct _File | ||
90 | { | ||
91 | char name[MAXPATHLEN]; | ||
92 | }; | ||
93 | |||
94 | struct _Patch | ||
95 | { | ||
96 | guint8 *data; | ||
97 | guint32 length; | ||
98 | }; | ||
99 | |||
100 | struct _TestProfile | ||
101 | { | ||
102 | const char *name; | ||
103 | const char *progname; | ||
104 | int flags; | ||
105 | }; | ||
106 | |||
107 | #undef BUFSIZ | ||
108 | #define BUFSIZ (1<<24) | ||
109 | |||
110 | guint8 __tmp_buffer[BUFSIZ]; | ||
111 | |||
112 | // Note: Of course you should be able to set all this up on the | ||
113 | // command line. | ||
114 | |||
115 | TestProfile 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 | |||
122 | int cmd_slevels[] = { 16, 32, 64 }; | ||
123 | int cmd_zlevels[] = { 0, 1, 3, 6, 9 }; | ||
124 | guint16 cmd_seed[3] = { 47384, 8594, 27489 }; | ||
125 | |||
126 | FILE* data_source_handle; | ||
127 | guint data_source_length; | ||
128 | File* data_source_file; | ||
129 | |||
130 | long current_to_size; | ||
131 | long current_from_size; | ||
132 | |||
133 | double __total_time; | ||
134 | off_t __dsize; | ||
135 | |||
136 | void | ||
137 | reset_stats () | ||
138 | { | ||
139 | __total_time = 0; | ||
140 | __dsize = -1; | ||
141 | } | ||
142 | |||
143 | void add_tv (GTimer *timer) | ||
144 | { | ||
145 | __total_time += g_timer_elapsed (timer, NULL); | ||
146 | } | ||
147 | |||
148 | void | ||
149 | report (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 | |||
188 | guint32 | ||
189 | random_offset (guint len) | ||
190 | { | ||
191 | return lrand48 () % (data_source_length - len); | ||
192 | } | ||
193 | |||
194 | void | ||
195 | fail () | ||
196 | { | ||
197 | g_warning ("FAILURE\n"); | ||
198 | abort (); | ||
199 | } | ||
200 | |||
201 | gboolean starts_with (const char* s, const char *start) | ||
202 | { | ||
203 | return strncmp (s, start, strlen (start)) == 0; | ||
204 | } | ||
205 | |||
206 | Patch* | ||
207 | read_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 | |||
227 | File* | ||
228 | empty_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 | |||
238 | void | ||
239 | compare_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 | |||
283 | int | ||
284 | write_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 | |||
325 | Instruction* | ||
326 | perform_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 | |||
367 | Instruction* | ||
368 | perform_change (Instruction* inst, guint* len) | ||
369 | { | ||
370 | return perform_change_rec (inst, lrand48() % ((* len) - cmd_deletion_length), len); | ||
371 | } | ||
372 | |||
373 | gboolean | ||
374 | xdelta_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 | |||
413 | gboolean | ||
414 | run_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 | |||
561 | void | ||
562 | test1 (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 | |||
656 | int | ||
657 | main (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. */ | ||
35 | static gboolean | ||
36 | xdp_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 | |||
64 | gboolean | ||
65 | xdp_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 | |||
2 | I have placed version 0.13 of XDELTA, new delta generator and | ||
3 | prototype RCS-replacement program at: | ||
4 | |||
5 | ftp://www.xcf.berkeley.edu/pub/jmacd/xdelta-0.13.tar.gz | ||
6 | |||
7 | ====== | ||
8 | |||
9 | Hereafter, the algorithm and program are described. A delta algorithm | ||
10 | operates on two files, a FROM file and a TO file. It computes enough | ||
11 | informnation to reconstruct the TO file from the FROM file. So the | ||
12 | delta and it's inverse, patch, work as follows: | ||
13 | |||
14 | P = delta (FROM, TO) | ||
15 | TO = patch (FROM, P) | ||
16 | |||
17 | The delta generator portion of this program is a delta algorithm which | ||
18 | searches for substring matches between the files and then outputs | ||
19 | instructions to reconstruct the new file from the old file. It | ||
20 | produces a set of copy/insert instructions that tell how to | ||
21 | reconstruct the file as a sequence of copies from the FROM file and | ||
22 | inserts from the delta itself. In this regard, the program is much | ||
23 | closer to a compression program than to a diff program. However, the | ||
24 | delta is not "compressed", in that the delta's entropy H(P) will be | ||
25 | very similar to the entropy of the portions of the TO file not found | ||
26 | within the FROM file. The delta will compress just as well as the TO | ||
27 | file will. This is a fundamentally different method of computing | ||
28 | deltas than in the traditional "diff" program. The diff program and | ||
29 | it's variants use a least-common-subsequence (LCS) algorithm to find a | ||
30 | list of inserts and deletes that will modify the FROM file into the TO | ||
31 | file. LCS is more expensive to compute and is sometimes more useful, | ||
32 | especially to the human reader. Since LCS is a fairly expensive | ||
33 | algorithm, diff programs usually divide the input files into | ||
34 | newline-separated "atoms" before computing a delta. This is a fine | ||
35 | approximation for text files, but not binary files. | ||
36 | |||
37 | I propose this delta generator as a replacement for "diff" in | ||
38 | applications where the insert/delete delta is not required. Since the | ||
39 | copy/insert delta is easier to compute, it does not have to make the | ||
40 | reduction in input size by breaking the file into lines. The delta | ||
41 | generator works well on binary files. | ||
42 | |||
43 | The next question is whether it is actually desirable to compute | ||
44 | deltas between binary files. The answer is certainly yes, even though | ||
45 | some binary file formats will not have a great degree of similarity | ||
46 | between versions which were generated between minor modifications to | ||
47 | their sources. First, I have evidence that some file formats (notably | ||
48 | FrameMaker documents) work very well. Machine-dependant object files | ||
49 | and executables don't work very well, but it is still worth doing. | ||
50 | The reason it is still worthwhile is that compression takes longer | ||
51 | than finding these deltas, so any space savings the delta generator | ||
52 | produces it very likely to reduce the total archival time. Even if | ||
53 | the delta generator saves no space, the total time well end up less | ||
54 | than twice the time of compression. I will include some measurements | ||
55 | at the end of this writing. | ||
56 | |||
57 | With the delta generator as a building block, I have written a | ||
58 | replacement for RCS. It does not have all the user-level features | ||
59 | someone would want in RCS, but these things only get in the way when | ||
60 | the code is used by higher level version control programs such as | ||
61 | PRCS. For now, the prototype supports the following actions: | ||
62 | |||
63 | register create an empty version file | ||
64 | checkin create a new version | ||
65 | checkout extract an old version | ||
66 | |||
67 | The program departs from the RCS model in that it does not branch it's | ||
68 | versions. The reason for doing this is to solve several problems with | ||
69 | RCS (aside from it's use of diff which is solved by using my delta | ||
70 | generator). | ||
71 | |||
72 | 1. Development very often ends up off the "main trunk" of the RCS | ||
73 | file, which causes an O(N) extract, where N deltas must be applied to | ||
74 | the head of the trunk before getting the desired file. Once this | ||
75 | occurs, things get worse and worse. Of course, it is possible to | ||
76 | remedy the situation by checking it in once on the trunk, but that | ||
77 | defeats the purpose of branching, because you lose the information | ||
78 | about branch of development you are on. Further, the notion of | ||
79 | branching individual files conflicts with the model presented by | ||
80 | higher level version control programs such as PRCS, which would rather | ||
81 | not have to go to extra trouble to insure that development does not | ||
82 | end up off the trunk. | ||
83 | |||
84 | 2. Deltas are never used more than once in a particular version | ||
85 | history, even if they contain the same data as another delta. | ||
86 | |||
87 | Conceptually, to get rid of RCS-like branching and retain the "deltas | ||
88 | are computed between a file and its parent", the xdelta version | ||
89 | control library computes a reverse delta between the new file and the | ||
90 | entire version file. The most recently checked in version is always | ||
91 | the "head", in RCS terms. It is always the quickest and easiest to | ||
92 | extract. For a repository with N versions, version I requires the | ||
93 | application of (N-I) deltas, regardless of how the set of versions are | ||
94 | related. | ||
95 | |||
96 | Each delta contains a set of instructions and all data which was | ||
97 | originally part of a file version but missing in the FROM file. This | ||
98 | data is represented without compression or modification. As a result, | ||
99 | each delta may be used as an input for finding future deltas just as a | ||
100 | regular file may be. | ||
101 | |||
102 | Several 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 | |||
119 | Checkin 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 | |||
132 | an 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 | |||
139 | Now I will describe why this is just as good as branching, even though | ||
140 | the branches do not affect which files are used for computing deltas, | ||
141 | and why it is just as good as the RCS model. | ||
142 | |||
143 | Suppose the we have a sequence of checkins with RCS version numbers | ||
144 | and their sequence numbers: | ||
145 | |||
146 | F0: 1.1 | ||
147 | F1: 1.2 | ||
148 | F2: 1.3 | ||
149 | F3: 1.1.1.1 | ||
150 | F4: 1.1.1.2 | ||
151 | F5: 1.1.1.3 | ||
152 | F6: 1.4 | ||
153 | F7: 1.5 | ||
154 | |||
155 | Of interest are the 4th checkin, from 1.3 to 1.1.1.1, and the 7th | ||
156 | checkin, from 1.1.1.3 to 1.4. I will now use the '-' sign to denote | ||
157 | the taking of a delta and '+' for patch. Thus, delta(A,B) is | ||
158 | equivalent to B-A, and patch(A,xdelta(A,B)) is equivalent to A+(B-A), | ||
159 | or B, as it should be. In the above sequence of checkins, these | ||
160 | deltas are produced: | ||
161 | |||
162 | D0=F0-F1 | ||
163 | D1=F1-F2-D0 | ||
164 | D2=F2-F3-D1-D0 | ||
165 | D3=F3-F4-D2-D1-D0 | ||
166 | D4=F4-F5-D3-D2-D1-D0 | ||
167 | D5=F5-F6-D4-D3-D2-D1-D0 | ||
168 | D6=F6-F7-D5-D4-D3-D2-D1-D0 | ||
169 | |||
170 | The checkin of F3 produces D2. The concern is whether any deletions | ||
171 | between 1.1 and 1.3 have to be inserted into D2. They have not, | ||
172 | because any deletions between 1.1 and 1.3 appear in D0 and D1. Thus, | ||
173 | using D0, D1, and F3 as an input for computing D2 achieves the desired | ||
174 | results: the deletion is not reflected twice in separate deltas. | ||
175 | |||
176 | The properties of this version format differ from the RCS format. It | ||
177 | ensures that recently checked-in versions are quick to check out, no | ||
178 | matter where in the "tree" they occur. One potential problem with | ||
179 | this formulation is that according to the formulae above, the ammount | ||
180 | of memory and computation required for checking in each new version | ||
181 | grows with the number of previous versions. To prevent this it only | ||
182 | uses up to some limiting value (currently set at 10) of previous | ||
183 | deltas in computing new deltas. This means that deletions on a branch | ||
184 | over 10 checkins old will be duplicated on a checkin. Another | ||
185 | property is that to delete a version all older versions must first be | ||
186 | deleted or off-line processing may be done to reconstruct the delta | ||
187 | log with the version removed (an expensive but not time-critical | ||
188 | operation). It also lends itself to keeping windowed histories, such | ||
189 | as "only keep the last 20 revisions, anything earlier than that may be | ||
190 | thrown away". | ||
191 | |||
192 | --- | ||
193 | |||
194 | The current prototype implementation is complete. The program, | ||
195 | 'xdelta', has a command syntax similar to PRCS: | ||
196 | |||
197 | xdelta COMMAND [OPTIONS] ARG1 ARG2 ... | ||
198 | |||
199 | There 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 | |||
208 | The -r option specifies a version (the latest version is always the | ||
209 | default). Versions are sequentially numbered. The file itself is a | ||
210 | GNU DBM database which stores the deltas and latest version. The file | ||
211 | format is subject to change as I look for storage methods that are | ||
212 | portable to Windows (otherwise, the delta generator has already been | ||
213 | tested on Windows). | ||
214 | |||
215 | The DELTA and PATCH commands are unrelated to the rest, and simply | ||
216 | serve to generate deltas (and could be used as replacements for "diff" | ||
217 | and "patch"). All operations are verified with MD5 checksums, which | ||
218 | are saved for each version in the version file and the FROM and TO | ||
219 | files when generating and applying deltas. | ||
220 | |||
221 | --- | ||
222 | |||
223 | Some timing comparisons (remember all times include MD5 computations) | ||
224 | on a 300MHz Alpha: | ||
225 | |||
226 | Two kernels: | ||
227 | |||
228 | 7875136 /genvmunix | ||
229 | 6677320 /vmunix | ||
230 | |||
231 | And the times to compress and delta them: | ||
232 | |||
233 | time(s) size(bytes) | ||
234 | |||
235 | xdelta delta /genvmunix /vmunix patch: 10.1 4338029 | ||
236 | gzip --best /genvmunix: 34.0 3413963 | ||
237 | gzip --best /vmunix: 63.7 2501766 | ||
238 | gzip --best patch: 51.9 1531163 | ||
239 | |||
240 | (I'm not sure why there's such a variation in gzip times--it was | ||
241 | repeatable.) | ||
242 | |||
243 | xdelta produces a patch which is 4338029 bytes, approximately 2.6 | ||
244 | megabytes smaller than its TO file. The total space required for | ||
245 | saving the two kernels compressed is 5915729 bytes, produced in 97.7 | ||
246 | seconds. The total space for storing /genvmunix and the delta | ||
247 | compressed is 4945126 bytes, produced in 96.0 seconds. Using the | ||
248 | delta saved approximately one megabyte and two seconds. | ||
249 | |||
250 | --- | ||
251 | |||
252 | All the files in PRCS 1.0.0 and 1.2.0 concatenated (files ordered | ||
253 | lexigraphically): | ||
254 | |||
255 | 1678837 /tmp/1.0.0 | ||
256 | 2021819 /tmp/1.2.0 | ||
257 | |||
258 | time(s) space(bytes) | ||
259 | |||
260 | xdelta delta /tmp/1.0.0 /tmp/1.2.0 /tmp/patch: 1.5 695893 | ||
261 | gdiff -a --rcs /tmp/1.0.0 /tmp/1.2.0 /tmp/patch: 3.7 1524705 | ||
262 | |||
263 | Even though both files were completely text, gdiff missed a lot of | ||
264 | similar regions because a line had been partially modified. Xdelta | ||
265 | performs better in both dimensions. | ||
266 | |||
267 | --- | ||
268 | |||
269 | All the .c and .h files in GNU gcc 2.7.2 and 2.7.2.3 concatenated (files | ||
270 | ordered 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 | |||
276 | xdelta delta /tmp/2.7.2 /tmp/2.7.2.3 /tmp/patch: 7.3 11922 | ||
277 | gdiff -a --rcs /tmp/2.7.2 /tmp/2.7.2.3: 4.8 19477 | ||
278 | |||
279 | Here xdelta takes a about 50% longer and produces a slightly smaller | ||
280 | diff. I think the improved performance in the other two examples | ||
281 | makes xdelta an all around winner. | ||
282 | |||
283 | --- | ||
284 | |||
285 | A note on FrameMaker files, which I happen to know a fair bit about. | ||
286 | Even making radical modifications to a Frame+SGML document leaves much | ||
287 | of its content unchanged, due to the fact that the EDD and various | ||
288 | catalogs do not change. When only minimal modifications are performed | ||
289 | |||
290 | Take a 24 page document, chapter 15 of the SGML developers guide for | ||
291 | version 5.5. I replaced 38 occurances of "document" with | ||
292 | "abcdefghijklmnop" and added the source of this README from here up at | ||
293 | the end, making it 33 pages. | ||
294 | |||
295 | 250880 graphics.before.fm | ||
296 | 272384 graphics.after.fm | ||
297 | |||
298 | The document grew by about 22 kbytes. The patch 32780 bytes. The | ||
299 | same diff generated by GNU diff is 101097 bytes. Clearly, Frame | ||
300 | documents are very good for binary version control. | ||
301 | |||
302 | --- | ||
303 | |||
304 | I also have evidence that the program works well on uncompressed image | ||
305 | formats such as the GIMP's XCF file format. | ||
306 | |||
307 | This program will be the basis of PRCS version 2, which will support | ||
308 | client/server distributed version control. | ||
309 | |||
310 | Please send any comments, questions, thoughts, or interest to me, | ||
311 | jmacd@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 | |||
3 | glib_libs="@GLIB_LIBS@" | ||
4 | glib_cflags="@GLIB_CFLAGS@" | ||
5 | |||
6 | prefix=@prefix@ | ||
7 | exec_prefix=@exec_prefix@ | ||
8 | exec_prefix_set=no | ||
9 | |||
10 | usage() | ||
11 | { | ||
12 | cat <<EOF | ||
13 | Usage: xdelta-config [OPTIONS] [LIBRARIES] | ||
14 | Options: | ||
15 | [--prefix[=DIR]] | ||
16 | [--exec-prefix[=DIR]] | ||
17 | [--version] | ||
18 | [--libs] | ||
19 | [--cflags] | ||
20 | Libraries: | ||
21 | xdelta | ||
22 | EOF | ||
23 | exit $1 | ||
24 | } | ||
25 | |||
26 | if test $# -eq 0; then | ||
27 | usage 1 1>&2 | ||
28 | fi | ||
29 | |||
30 | lib_xdelta=yes | ||
31 | |||
32 | while 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 | ||
74 | done | ||
75 | |||
76 | if test "$echo_prefix" = "yes"; then | ||
77 | echo $prefix | ||
78 | fi | ||
79 | |||
80 | if test "$echo_exec_prefix" = "yes"; then | ||
81 | echo $exec_prefix | ||
82 | fi | ||
83 | |||
84 | if 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 | ||
94 | fi | ||
95 | |||
96 | if 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 | ||
115 | fi | ||
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$;" $ */ | ||
36 | const guint xdelta_major_version = 1; | ||
37 | /* $Format: "const guint xdelta_minor_version = $ReleaseMinorVersion$;" $ */ | ||
38 | const guint xdelta_minor_version = 1; | ||
39 | /* $Format: "const guint xdelta_micro_version = $ReleaseMicroVersion$;" $ */ | ||
40 | const guint xdelta_micro_version = 4; | ||
41 | |||
42 | /* Control functions. | ||
43 | */ | ||
44 | |||
45 | static XdeltaControl* control_version_0 (SerialVersion0Control* cont) ; | ||
46 | static void control_copy (XdeltaControl* cont, XdeltaSource* src, guint from, guint to); | ||
47 | static gboolean control_add_info (XdeltaControl* cont, XdeltaSource* src, const guint8* md5, guint len); | ||
48 | |||
49 | #ifndef XDELTA_HARDCODE_SIZE | ||
50 | int QUERY_SIZE = 0; | ||
51 | int QUERY_SIZE_POW = 0; | ||
52 | int QUERY_SIZE_MASK = 0; | ||
53 | #endif | ||
54 | |||
55 | int 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 | |||
83 | int | ||
84 | xdp_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 | |||
94 | const char* | ||
95 | xdp_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 | |||
108 | const 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 | |||
150 | static void | ||
151 | init_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 | |||
170 | static gboolean | ||
171 | generate_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 | |||
233 | XdeltaGenerator* | ||
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 | |||
253 | void | ||
254 | xdp_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 | |||
266 | void | ||
267 | init_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 | |||
276 | gboolean | ||
277 | check_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 | |||
309 | static gboolean | ||
310 | xdp_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 | |||
333 | static gboolean | ||
334 | xdp_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 | |||
371 | gboolean | ||
372 | xdp_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 | |||
386 | XdeltaSource* | ||
387 | xdp_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 | |||
407 | static gboolean | ||
408 | xdp_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 | |||
419 | void | ||
420 | xdp_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 | |||
431 | void | ||
432 | xdp_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 | |||
444 | guint | ||
445 | c_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 | |||
454 | static gboolean | ||
455 | region_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 | |||
480 | static gboolean | ||
481 | region_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 | |||
494 | gboolean | ||
495 | unmap_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 | |||
511 | gboolean | ||
512 | map_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 | |||
544 | static gboolean | ||
545 | try_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 | |||
603 | doneback: | ||
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 | |||
685 | done: | ||
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 | |||
709 | bail: | ||
710 | *xpos_ptr = xpos; | ||
711 | src->source_pos = ypos; | ||
712 | return FALSE; | ||
713 | } | ||
714 | |||
715 | static gboolean | ||
716 | compute_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 | |||
867 | bail: | ||
868 | |||
869 | if (! unmap_page (stream, &xpos)) | ||
870 | return FALSE; | ||
871 | |||
872 | return ret; | ||
873 | } | ||
874 | |||
875 | static gboolean | ||
876 | just_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 | |||
952 | static gboolean | ||
953 | xdp_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 | |||
1069 | XdeltaControl* | ||
1070 | xdp_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 | |||
1137 | XdeltaControl* | ||
1138 | control_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 | |||
1148 | static void | ||
1149 | control_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 | |||
1163 | gboolean | ||
1164 | control_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 | |||
1187 | void | ||
1188 | xdp_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 | |||
1197 | void | ||
1198 | control_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 | ||
1228 | static void | ||
1229 | print_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 | |||
1240 | static void | ||
1241 | print_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 | |||
1254 | static void | ||
1255 | xdp_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 | ||
1278 | void | ||
1279 | check_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 | |||
1296 | static gboolean | ||
1297 | unpack_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 | |||
1340 | static gboolean | ||
1341 | pack_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 | |||
1382 | gboolean | ||
1383 | xdp_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 | |||
1412 | XdeltaControl* | ||
1413 | xdp_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 | |||
1455 | XdeltaControl* | ||
1456 | control_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 | |||
31 | typedef SerialRsyncIndex XdeltaRsync; | ||
32 | typedef SerialRsyncIndexElt XdeltaRsyncElt; | ||
33 | typedef SerialXdeltaChecksum XdeltaChecksum; | ||
34 | typedef SerialXdeltaIndex XdeltaIndex; | ||
35 | typedef SerialXdeltaSourceInfo XdeltaSourceInfo; | ||
36 | typedef SerialXdeltaControl XdeltaControl; | ||
37 | typedef SerialXdeltaInstruction XdeltaInstruction; | ||
38 | |||
39 | typedef struct _XdeltaGenerator XdeltaGenerator; | ||
40 | typedef struct _XdeltaSource XdeltaSource; | ||
41 | |||
42 | typedef FileHandle XdeltaStream; | ||
43 | typedef 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 | |||
61 | extern const guint xdelta_major_version; | ||
62 | extern const guint xdelta_minor_version; | ||
63 | extern 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 | ||
92 | extern int QUERY_SIZE; | ||
93 | extern int QUERY_SIZE_POW; | ||
94 | extern 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. */ | ||
101 | int xdp_set_query_size_pow (int size_pow); | ||
102 | int 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 | |||
126 | XdeltaGenerator* __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 | |||
135 | XdeltaSource* 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. */ | ||
142 | gboolean 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. */ | ||
147 | void 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. */ | ||
152 | XdeltaControl* 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. */ | ||
158 | XdeltaControl* xdp_control_read (XdeltaStream *cont_in); | ||
159 | |||
160 | /* Writes a control object to a stream. */ | ||
161 | gboolean xdp_control_write (XdeltaControl *cont, | ||
162 | XdeltaOutStream *cont_out); | ||
163 | |||
164 | /* Free the above structures */ | ||
165 | void xdp_source_free (XdeltaSource *src); | ||
166 | void xdp_generator_free (XdeltaGenerator *gen); | ||
167 | void 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 | |||
172 | gboolean xdp_apply_delta (XdeltaControl *cont, | ||
173 | XdeltaOutStream *res); | ||
174 | |||
175 | /* Rsync: Undocumented, experimental code. Have a look. May not | ||
176 | * compile. */ | ||
177 | |||
178 | XdeltaRsync* xdp_rsync_index (XdeltaStream *file, | ||
179 | guint seg_len, | ||
180 | XdeltaStream *cache_in, | ||
181 | XdeltaOutStream *cache_out); | ||
182 | |||
183 | void xdp_rsync_index_free (XdeltaRsync *rsync); | ||
184 | |||
185 | GArray* xdp_rsync_request (XdeltaStream *file, | ||
186 | XdeltaRsync *rsync); | ||
187 | |||
188 | gboolean xdp_apply_rsync_reply (XdeltaRsync *rsync, | ||
189 | XdeltaStream *from, | ||
190 | XdeltaStream *reply, | ||
191 | XdeltaStream *out); | ||
192 | |||
193 | const 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 | |||
4 | dnl AM_PATH_XDELTA([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) | ||
5 | dnl Test for XDELTA, and define XDELTA_CFLAGS and XDELTA_LIBS, if "gmodule" or | ||
6 | dnl | ||
7 | AC_DEFUN(AM_PATH_XDELTA, | ||
8 | [dnl | ||
9 | dnl Get the cflags and libraries from the xdelta-config script | ||
10 | dnl | ||
11 | AC_ARG_WITH(xdelta-prefix,[ --with-xdelta-prefix=PFX Prefix where XDELTA is installed (optional)], | ||
12 | xdelta_config_prefix="$withval", xdelta_config_prefix="") | ||
13 | AC_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="") | ||
15 | AC_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" | ||
51 | dnl | ||
52 | dnl Now check if the installed XDELTA is sufficiently new. (Also sanity | ||
53 | dnl checks the results of xdelta-config to some extent | ||
54 | dnl | ||
55 | rm -f conf.xdeltatest | ||
56 | AC_TRY_RUN([ | ||
57 | #include <xdelta.h> | ||
58 | #include <stdio.h> | ||
59 | #include <stdlib.h> | ||
60 | |||
61 | int | ||
62 | main () | ||
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, µ) != 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 | # | ||
4 | 0 string %XDELTA% XDelta binary patch file 0.14 | ||
5 | 0 string %XDZ000% XDelta binary patch file 0.18 | ||
6 | 0 string %XDZ001% XDelta binary patch file 0.20 | ||
7 | 0 string %XDZ002% XDelta binary patch file 1.0 | ||
8 | 0 string %XDZ003% XDelta binary patch file 1.0.4 | ||
9 | 0 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 | |||
46 | typedef struct _XdeltaPos XdeltaPos; | ||
47 | typedef struct _RsyncHash RsyncHash; | ||
48 | |||
49 | #define XPOS(p) (((p).page * (p).page_size) + (p).off) | ||
50 | |||
51 | struct _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 | |||
71 | struct _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 | |||
99 | struct _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 | |||
121 | extern const guint16 single_hash[256]; | ||
122 | |||
123 | void init_pos (XdeltaStream* str, XdeltaPos* pos); | ||
124 | gboolean unmap_page (XdeltaStream* stream, XdeltaPos* pos); | ||
125 | gboolean map_page (XdeltaStream* stream, XdeltaPos* pos); | ||
126 | gboolean check_stream_integrity (XdeltaStream* str, const guint8* md5, guint len); | ||
127 | XdeltaControl* control_new (void); | ||
128 | |||
129 | guint 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 | |||
67 | static 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 | |||
110 | typedef struct _LRU LRU; | ||
111 | |||
112 | struct _LRU | ||
113 | { | ||
114 | LRU *next; | ||
115 | LRU *prev; | ||
116 | |||
117 | gint refs; | ||
118 | guint page; | ||
119 | guint8* buffer; | ||
120 | }; | ||
121 | |||
122 | typedef struct _XdFileHandle XdFileHandle; | ||
123 | |||
124 | typedef 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 | |||
151 | struct _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$\"; " $ */ | ||
196 | static const char xdelta_version[] = "1.1.4"; | ||
197 | |||
198 | typedef struct _Command Command; | ||
199 | |||
200 | struct _Command { | ||
201 | gchar* name; | ||
202 | gint (* func) (gint argc, gchar** argv); | ||
203 | gint nargs; | ||
204 | }; | ||
205 | |||
206 | static gint delta_command (gint argc, gchar** argv); | ||
207 | static gint patch_command (gint argc, gchar** argv); | ||
208 | static gint info_command (gint argc, gchar** argv); | ||
209 | |||
210 | static 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 | |||
218 | static 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 | |||
231 | static const gchar* program_name; | ||
232 | static gint compress_level = Z_DEFAULT_COMPRESSION; | ||
233 | static gint no_verify = FALSE; | ||
234 | static gint pristine = FALSE; | ||
235 | static gint verbose = FALSE; | ||
236 | static gint max_mapped_pages = G_MAXINT; | ||
237 | static gint quiet = FALSE; | ||
238 | |||
239 | #define xd_error g_warning | ||
240 | |||
241 | static void | ||
242 | usage () | ||
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 | |||
249 | static void | ||
250 | help () | ||
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 | |||
271 | static void | ||
272 | version () | ||
273 | { | ||
274 | xd_error ("version %s\n", xdelta_version); | ||
275 | exit (2); | ||
276 | } | ||
277 | |||
278 | static FILE* xd_error_file = NULL; | ||
279 | |||
280 | static void | ||
281 | xd_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 | |||
292 | static gboolean | ||
293 | event_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 | |||
307 | static gboolean | ||
308 | event_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 | |||
321 | gint | ||
322 | main (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 | |||
488 | static gssize xd_handle_map_page (XdFileHandle *fh, guint pgno, const guint8** mem); | ||
489 | static gboolean xd_handle_unmap_page (XdFileHandle *fh, guint pgno, const guint8** mem); | ||
490 | |||
491 | static gboolean | ||
492 | xd_fwrite (XdFileHandle* fh, const void* buf, gint nbyte) | ||
493 | { | ||
494 | return fwrite (buf, nbyte, 1, fh->out) == 1; | ||
495 | } | ||
496 | |||
497 | static gboolean | ||
498 | xd_fread (XdFileHandle* fh, void* buf, gint nbyte) | ||
499 | { | ||
500 | return fread (buf, nbyte, 1, fh->in) == 1; | ||
501 | } | ||
502 | |||
503 | static gboolean | ||
504 | xd_fclose (XdFileHandle* fh) | ||
505 | { | ||
506 | return fclose (fh->out) == 0; | ||
507 | } | ||
508 | |||
509 | static gboolean | ||
510 | xd_frclose (XdFileHandle* fh) | ||
511 | { | ||
512 | return fclose (fh->in) == 0; | ||
513 | } | ||
514 | |||
515 | static gboolean | ||
516 | xd_gzwrite (XdFileHandle* fh, const void* buf, gint nbyte) | ||
517 | { | ||
518 | return gzwrite (fh->out, (void*) buf, nbyte) == nbyte; | ||
519 | } | ||
520 | |||
521 | static gboolean | ||
522 | xd_gzread (XdFileHandle* fh, void* buf, gint nbyte) | ||
523 | { | ||
524 | return gzread (fh->in, buf, nbyte) == nbyte; | ||
525 | } | ||
526 | |||
527 | static gboolean | ||
528 | xd_gzclose (XdFileHandle* fh) | ||
529 | { | ||
530 | return gzclose (fh->out) == Z_OK; | ||
531 | } | ||
532 | |||
533 | static gboolean | ||
534 | xd_gzrclose (XdFileHandle* fh) | ||
535 | { | ||
536 | return gzclose (fh->in) == Z_OK; | ||
537 | } | ||
538 | |||
539 | static void | ||
540 | init_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 | |||
548 | static XdFileHandle* | ||
549 | open_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 | |||
586 | static gboolean | ||
587 | file_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 | |||
612 | static const char* | ||
613 | xd_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 | |||
636 | static const char* | ||
637 | file_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 | |||
676 | static XdFileHandle* | ||
677 | open_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 | |||
727 | static void | ||
728 | xd_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 | |||
744 | static XdFileHandle* | ||
745 | open_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 | |||
776 | static XdFileHandle* | ||
777 | open_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 | |||
805 | static gint | ||
806 | xd_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 | |||
851 | static gboolean | ||
852 | xd_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 | |||
883 | static gssize | ||
884 | xd_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 | |||
892 | static gssize | ||
893 | xd_handle_pages (XdFileHandle *fh) | ||
894 | { | ||
895 | g_assert (fh->type & READ_TYPE); | ||
896 | return xd_handle_length (fh) / XD_PAGE_SIZE; | ||
897 | } | ||
898 | |||
899 | static gssize | ||
900 | xd_handle_pagesize (XdFileHandle *fh) | ||
901 | { | ||
902 | g_assert (fh->type & READ_TYPE); | ||
903 | return XD_PAGE_SIZE; | ||
904 | } | ||
905 | |||
906 | static gint | ||
907 | on_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 | |||
918 | static gboolean | ||
919 | xd_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 | |||
946 | static const guint8* | ||
947 | xd_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 | |||
983 | static gboolean | ||
984 | xd_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 | |||
1006 | static gboolean | ||
1007 | xd_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 | |||
1052 | static guint | ||
1053 | xd_handle_get_pos (XdFileHandle* fh) | ||
1054 | { | ||
1055 | return fh->current_pos - fh->narrow_low; | ||
1056 | } | ||
1057 | |||
1058 | static const gchar* | ||
1059 | xd_handle_name (XdFileHandle *fh) | ||
1060 | { | ||
1061 | return g_strdup (fh->name); | ||
1062 | } | ||
1063 | |||
1064 | static gssize | ||
1065 | xd_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 | |||
1084 | static gboolean | ||
1085 | xd_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 | |||
1112 | static gboolean | ||
1113 | xd_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 | |||
1126 | static LRU* | ||
1127 | pull_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 | |||
1156 | static gboolean | ||
1157 | really_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 | ||
1199 | static void | ||
1200 | print_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 | |||
1214 | static gboolean | ||
1215 | make_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 | |||
1230 | static gssize | ||
1231 | xd_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 | |||
1339 | static gboolean | ||
1340 | xd_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 | |||
1379 | static gboolean | ||
1380 | xd_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 | |||
1446 | static gboolean | ||
1447 | xd_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 | |||
1454 | static gboolean | ||
1455 | xd_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 | |||
1465 | static 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 | |||
1485 | static void | ||
1486 | htonl_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 | |||
1494 | static void | ||
1495 | ntohl_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 | |||
1503 | static gint | ||
1504 | delta_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 | |||
1656 | static XdeltaPatch* | ||
1657 | process_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 | |||
1807 | static gint | ||
1808 | info_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 | |||
1863 | static gint | ||
1864 | patch_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 | |||
35 | static void | ||
36 | init_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 | |||
52 | static XdeltaRsync* | ||
53 | xdp_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 | |||
125 | static XdeltaRsync* | ||
126 | xdp_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 | |||
140 | static gboolean | ||
141 | xdp_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 | |||
158 | XdeltaRsync* | ||
159 | xdp_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 | |||
194 | bail: | ||
195 | |||
196 | xdp_rsync_index_free (rsync); | ||
197 | |||
198 | return NULL; | ||
199 | } | ||
200 | |||
201 | void | ||
202 | xdp_rsync_index_free (XdeltaRsync *rsync) | ||
203 | { | ||
204 | /* ??? */ | ||
205 | } | ||
206 | |||
207 | static | ||
208 | gboolean 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 | |||
238 | static void | ||
239 | incr_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 | |||
252 | GArray* | ||
253 | xdp_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 | |||
406 | gboolean | ||
407 | xdp_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 | } | ||