55 files changed, 8259 insertions, 0 deletions
diff --git a/rsync/AUTHORS b/rsync/AUTHORS new file mode 100644 index 0000000..f11fc44 --- a/dev/null +++ b/rsync/AUTHORS | |||
@@ -0,0 +1,2 @@ | |||
1 | Martin Pool <mbp@samba.org> | ||
2 | Andrew Tridgell <tridge@samba.org> | ||
diff --git a/rsync/COPYING b/rsync/COPYING new file mode 100644 index 0000000..c4792dd --- a/dev/null +++ b/rsync/COPYING | |||
@@ -0,0 +1,515 @@ | |||
1 | |||
2 | GNU LESSER GENERAL PUBLIC LICENSE | ||
3 | Version 2.1, February 1999 | ||
4 | |||
5 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. | ||
6 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
7 | Everyone is permitted to copy and distribute verbatim copies | ||
8 | of this license document, but changing it is not allowed. | ||
9 | |||
10 | [This is the first released version of the Lesser GPL. It also counts | ||
11 | as the successor of the GNU Library Public License, version 2, hence | ||
12 | the version number 2.1.] | ||
13 | |||
14 | Preamble | ||
15 | |||
16 | The licenses for most software are designed to take away your | ||
17 | freedom to share and change it. By contrast, the GNU General Public | ||
18 | Licenses are intended to guarantee your freedom to share and change | ||
19 | free software--to make sure the software is free for all its users. | ||
20 | |||
21 | This license, the Lesser General Public License, applies to some | ||
22 | specially designated software packages--typically libraries--of the | ||
23 | Free Software Foundation and other authors who decide to use it. You | ||
24 | can use it too, but we suggest you first think carefully about whether | ||
25 | this license or the ordinary General Public License is the better | ||
26 | strategy to use in any particular case, based on the explanations | ||
27 | below. | ||
28 | |||
29 | When we speak of free software, we are referring to freedom of use, | ||
30 | not price. Our General Public Licenses are designed to make sure that | ||
31 | you have the freedom to distribute copies of free software (and charge | ||
32 | for this service if you wish); that you receive source code or can get | ||
33 | it if you want it; that you can change the software and use pieces of | ||
34 | it in new free programs; and that you are informed that you can do | ||
35 | these things. | ||
36 | |||
37 | To protect your rights, we need to make restrictions that forbid | ||
38 | distributors to deny you these rights or to ask you to surrender these | ||
39 | rights. These restrictions translate to certain responsibilities for | ||
40 | you if you distribute copies of the library or if you modify it. | ||
41 | |||
42 | For example, if you distribute copies of the library, whether gratis | ||
43 | or for a fee, you must give the recipients all the rights that we gave | ||
44 | you. You must make sure that they, too, receive or can get the source | ||
45 | code. If you link other code with the library, you must provide | ||
46 | complete object files to the recipients, so that they can relink them | ||
47 | with the library after making changes to the library and recompiling | ||
48 | it. And you must show them these terms so they know their rights. | ||
49 | |||
50 | We protect your rights with a two-step method: (1) we copyright the | ||
51 | library, and (2) we offer you this license, which gives you legal | ||
52 | permission to copy, distribute and/or modify the library. | ||
53 | |||
54 | To protect each distributor, we want to make it very clear that | ||
55 | there is no warranty for the free library. Also, if the library is | ||
56 | modified by someone else and passed on, the recipients should know | ||
57 | that what they have is not the original version, so that the original | ||
58 | author's reputation will not be affected by problems that might be | ||
59 | introduced by others. | ||
60 | ^L | ||
61 | Finally, software patents pose a constant threat to the existence of | ||
62 | any free program. We wish to make sure that a company cannot | ||
63 | effectively restrict the users of a free program by obtaining a | ||
64 | restrictive license from a patent holder. Therefore, we insist that | ||
65 | any patent license obtained for a version of the library must be | ||
66 | consistent with the full freedom of use specified in this license. | ||
67 | |||
68 | Most GNU software, including some libraries, is covered by the | ||
69 | ordinary GNU General Public License. This license, the GNU Lesser | ||
70 | General Public License, applies to certain designated libraries, and | ||
71 | is quite different from the ordinary General Public License. We use | ||
72 | this license for certain libraries in order to permit linking those | ||
73 | libraries into non-free programs. | ||
74 | |||
75 | When a program is linked with a library, whether statically or using | ||
76 | a shared library, the combination of the two is legally speaking a | ||
77 | combined work, a derivative of the original library. The ordinary | ||
78 | General Public License therefore permits such linking only if the | ||
79 | entire combination fits its criteria of freedom. The Lesser General | ||
80 | Public License permits more lax criteria for linking other code with | ||
81 | the library. | ||
82 | |||
83 | We call this license the "Lesser" General Public License because it | ||
84 | does Less to protect the user's freedom than the ordinary General | ||
85 | Public License. It also provides other free software developers Less | ||
86 | of an advantage over competing non-free programs. These disadvantages | ||
87 | are the reason we use the ordinary General Public License for many | ||
88 | libraries. However, the Lesser license provides advantages in certain | ||
89 | special circumstances. | ||
90 | |||
91 | For example, on rare occasions, there may be a special need to | ||
92 | encourage the widest possible use of a certain library, so that it | ||
93 | becomes | ||
94 | a de-facto standard. To achieve this, non-free programs must be | ||
95 | allowed to use the library. A more frequent case is that a free | ||
96 | library does the same job as widely used non-free libraries. In this | ||
97 | case, there is little to gain by limiting the free library to free | ||
98 | software only, so we use the Lesser General Public License. | ||
99 | |||
100 | In other cases, permission to use a particular library in non-free | ||
101 | programs enables a greater number of people to use a large body of | ||
102 | free software. For example, permission to use the GNU C Library in | ||
103 | non-free programs enables many more people to use the whole GNU | ||
104 | operating system, as well as its variant, the GNU/Linux operating | ||
105 | system. | ||
106 | |||
107 | Although the Lesser General Public License is Less protective of the | ||
108 | users' freedom, it does ensure that the user of a program that is | ||
109 | linked with the Library has the freedom and the wherewithal to run | ||
110 | that program using a modified version of the Library. | ||
111 | |||
112 | The precise terms and conditions for copying, distribution and | ||
113 | modification follow. Pay close attention to the difference between a | ||
114 | "work based on the library" and a "work that uses the library". The | ||
115 | former contains code derived from the library, whereas the latter must | ||
116 | be combined with the library in order to run. | ||
117 | ^L | ||
118 | GNU LESSER GENERAL PUBLIC LICENSE | ||
119 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | ||
120 | |||
121 | 0. This License Agreement applies to any software library or other | ||
122 | program which contains a notice placed by the copyright holder or | ||
123 | other authorized party saying it may be distributed under the terms of | ||
124 | this Lesser General Public License (also called "this License"). | ||
125 | Each licensee is addressed as "you". | ||
126 | |||
127 | A "library" means a collection of software functions and/or data | ||
128 | prepared so as to be conveniently linked with application programs | ||
129 | (which use some of those functions and data) to form executables. | ||
130 | |||
131 | The "Library", below, refers to any such software library or work | ||
132 | which has been distributed under these terms. A "work based on the | ||
133 | Library" means either the Library or any derivative work under | ||
134 | copyright law: that is to say, a work containing the Library or a | ||
135 | portion of it, either verbatim or with modifications and/or translated | ||
136 | straightforwardly into another language. (Hereinafter, translation is | ||
137 | included without limitation in the term "modification".) | ||
138 | |||
139 | "Source code" for a work means the preferred form of the work for | ||
140 | making modifications to it. For a library, complete source code means | ||
141 | all the source code for all modules it contains, plus any associated | ||
142 | interface definition files, plus the scripts used to control | ||
143 | compilation | ||
144 | and installation of the library. | ||
145 | |||
146 | Activities other than copying, distribution and modification are not | ||
147 | covered by this License; they are outside its scope. The act of | ||
148 | running a program using the Library is not restricted, and output from | ||
149 | such a program is covered only if its contents constitute a work based | ||
150 | on the Library (independent of the use of the Library in a tool for | ||
151 | writing it). Whether that is true depends on what the Library does | ||
152 | and what the program that uses the Library does. | ||
153 | |||
154 | 1. You may copy and distribute verbatim copies of the Library's | ||
155 | complete source code as you receive it, in any medium, provided that | ||
156 | you conspicuously and appropriately publish on each copy an | ||
157 | appropriate copyright notice and disclaimer of warranty; keep intact | ||
158 | all the notices that refer to this License and to the absence of any | ||
159 | warranty; and distribute a copy of this License along with the | ||
160 | Library. | ||
161 | |||
162 | You may charge a fee for the physical act of transferring a copy, | ||
163 | and you may at your option offer warranty protection in exchange for a | ||
164 | fee. | ||
165 | |||
166 | 2. You may modify your copy or copies of the Library or any portion | ||
167 | of it, thus forming a work based on the Library, and copy and | ||
168 | distribute such modifications or work under the terms of Section 1 | ||
169 | above, provided that you also meet all of these conditions: | ||
170 | |||
171 | a) The modified work must itself be a software library. | ||
172 | |||
173 | b) You must cause the files modified to carry prominent notices | ||
174 | stating that you changed the files and the date of any change. | ||
175 | |||
176 | c) You must cause the whole of the work to be licensed at no | ||
177 | charge to all third parties under the terms of this License. | ||
178 | |||
179 | d) If a facility in the modified Library refers to a function or a | ||
180 | table of data to be supplied by an application program that uses | ||
181 | the facility, other than as an argument passed when the facility | ||
182 | is invoked, then you must make a good faith effort to ensure that, | ||
183 | in the event an application does not supply such function or | ||
184 | table, the facility still operates, and performs whatever part of | ||
185 | its purpose remains meaningful. | ||
186 | |||
187 | (For example, a function in a library to compute square roots has | ||
188 | a purpose that is entirely well-defined independent of the | ||
189 | application. Therefore, Subsection 2d requires that any | ||
190 | application-supplied function or table used by this function must | ||
191 | be optional: if the application does not supply it, the square | ||
192 | root function must still compute square roots.) | ||
193 | |||
194 | These requirements apply to the modified work as a whole. If | ||
195 | identifiable sections of that work are not derived from the Library, | ||
196 | and can be reasonably considered independent and separate works in | ||
197 | themselves, then this License, and its terms, do not apply to those | ||
198 | sections when you distribute them as separate works. But when you | ||
199 | distribute the same sections as part of a whole which is a work based | ||
200 | on the Library, the distribution of the whole must be on the terms of | ||
201 | this License, whose permissions for other licensees extend to the | ||
202 | entire whole, and thus to each and every part regardless of who wrote | ||
203 | it. | ||
204 | |||
205 | Thus, it is not the intent of this section to claim rights or contest | ||
206 | your rights to work written entirely by you; rather, the intent is to | ||
207 | exercise the right to control the distribution of derivative or | ||
208 | collective works based on the Library. | ||
209 | |||
210 | In addition, mere aggregation of another work not based on the Library | ||
211 | with the Library (or with a work based on the Library) on a volume of | ||
212 | a storage or distribution medium does not bring the other work under | ||
213 | the scope of this License. | ||
214 | |||
215 | 3. You may opt to apply the terms of the ordinary GNU General Public | ||
216 | License instead of this License to a given copy of the Library. To do | ||
217 | this, you must alter all the notices that refer to this License, so | ||
218 | that they refer to the ordinary GNU General Public License, version 2, | ||
219 | instead of to this License. (If a newer version than version 2 of the | ||
220 | ordinary GNU General Public License has appeared, then you can specify | ||
221 | that version instead if you wish.) Do not make any other change in | ||
222 | these notices. | ||
223 | ^L | ||
224 | Once this change is made in a given copy, it is irreversible for | ||
225 | that copy, so the ordinary GNU General Public License applies to all | ||
226 | subsequent copies and derivative works made from that copy. | ||
227 | |||
228 | This option is useful when you wish to copy part of the code of | ||
229 | the Library into a program that is not a library. | ||
230 | |||
231 | 4. You may copy and distribute the Library (or a portion or | ||
232 | derivative of it, under Section 2) in object code or executable form | ||
233 | under the terms of Sections 1 and 2 above provided that you accompany | ||
234 | it with the complete corresponding machine-readable source code, which | ||
235 | must be distributed under the terms of Sections 1 and 2 above on a | ||
236 | medium customarily used for software interchange. | ||
237 | |||
238 | If distribution of object code is made by offering access to copy | ||
239 | from a designated place, then offering equivalent access to copy the | ||
240 | source code from the same place satisfies the requirement to | ||
241 | distribute the source code, even though third parties are not | ||
242 | compelled to copy the source along with the object code. | ||
243 | |||
244 | 5. A program that contains no derivative of any portion of the | ||
245 | Library, but is designed to work with the Library by being compiled or | ||
246 | linked with it, is called a "work that uses the Library". Such a | ||
247 | work, in isolation, is not a derivative work of the Library, and | ||
248 | therefore falls outside the scope of this License. | ||
249 | |||
250 | However, linking a "work that uses the Library" with the Library | ||
251 | creates an executable that is a derivative of the Library (because it | ||
252 | contains portions of the Library), rather than a "work that uses the | ||
253 | library". The executable is therefore covered by this License. | ||
254 | Section 6 states terms for distribution of such executables. | ||
255 | |||
256 | When a "work that uses the Library" uses material from a header file | ||
257 | that is part of the Library, the object code for the work may be a | ||
258 | derivative work of the Library even though the source code is not. | ||
259 | Whether this is true is especially significant if the work can be | ||
260 | linked without the Library, or if the work is itself a library. The | ||
261 | threshold for this to be true is not precisely defined by law. | ||
262 | |||
263 | If such an object file uses only numerical parameters, data | ||
264 | structure layouts and accessors, and small macros and small inline | ||
265 | functions (ten lines or less in length), then the use of the object | ||
266 | file is unrestricted, regardless of whether it is legally a derivative | ||
267 | work. (Executables containing this object code plus portions of the | ||
268 | Library will still fall under Section 6.) | ||
269 | |||
270 | Otherwise, if the work is a derivative of the Library, you may | ||
271 | distribute the object code for the work under the terms of Section 6. | ||
272 | Any executables containing that work also fall under Section 6, | ||
273 | whether or not they are linked directly with the Library itself. | ||
274 | ^L | ||
275 | 6. As an exception to the Sections above, you may also combine or | ||
276 | link a "work that uses the Library" with the Library to produce a | ||
277 | work containing portions of the Library, and distribute that work | ||
278 | under terms of your choice, provided that the terms permit | ||
279 | modification of the work for the customer's own use and reverse | ||
280 | engineering for debugging such modifications. | ||
281 | |||
282 | You must give prominent notice with each copy of the work that the | ||
283 | Library is used in it and that the Library and its use are covered by | ||
284 | this License. You must supply a copy of this License. If the work | ||
285 | during execution displays copyright notices, you must include the | ||
286 | copyright notice for the Library among them, as well as a reference | ||
287 | directing the user to the copy of this License. Also, you must do one | ||
288 | of these things: | ||
289 | |||
290 | a) Accompany the work with the complete corresponding | ||
291 | machine-readable source code for the Library including whatever | ||
292 | changes were used in the work (which must be distributed under | ||
293 | Sections 1 and 2 above); and, if the work is an executable linked | ||
294 | with the Library, with the complete machine-readable "work that | ||
295 | uses the Library", as object code and/or source code, so that the | ||
296 | user can modify the Library and then relink to produce a modified | ||
297 | executable containing the modified Library. (It is understood | ||
298 | that the user who changes the contents of definitions files in the | ||
299 | Library will not necessarily be able to recompile the application | ||
300 | to use the modified definitions.) | ||
301 | |||
302 | b) Use a suitable shared library mechanism for linking with the | ||
303 | Library. A suitable mechanism is one that (1) uses at run time a | ||
304 | copy of the library already present on the user's computer system, | ||
305 | rather than copying library functions into the executable, and (2) | ||
306 | will operate properly with a modified version of the library, if | ||
307 | the user installs one, as long as the modified version is | ||
308 | interface-compatible with the version that the work was made with. | ||
309 | |||
310 | c) Accompany the work with a written offer, valid for at | ||
311 | least three years, to give the same user the materials | ||
312 | specified in Subsection 6a, above, for a charge no more | ||
313 | than the cost of performing this distribution. | ||
314 | |||
315 | d) If distribution of the work is made by offering access to copy | ||
316 | from a designated place, offer equivalent access to copy the above | ||
317 | specified materials from the same place. | ||
318 | |||
319 | e) Verify that the user has already received a copy of these | ||
320 | materials or that you have already sent this user a copy. | ||
321 | |||
322 | For an executable, the required form of the "work that uses the | ||
323 | Library" must include any data and utility programs needed for | ||
324 | reproducing the executable from it. However, as a special exception, | ||
325 | the materials to be distributed need not include anything that is | ||
326 | normally distributed (in either source or binary form) with the major | ||
327 | components (compiler, kernel, and so on) of the operating system on | ||
328 | which the executable runs, unless that component itself accompanies | ||
329 | the executable. | ||
330 | |||
331 | It may happen that this requirement contradicts the license | ||
332 | restrictions of other proprietary libraries that do not normally | ||
333 | accompany the operating system. Such a contradiction means you cannot | ||
334 | use both them and the Library together in an executable that you | ||
335 | distribute. | ||
336 | ^L | ||
337 | 7. You may place library facilities that are a work based on the | ||
338 | Library side-by-side in a single library together with other library | ||
339 | facilities not covered by this License, and distribute such a combined | ||
340 | library, provided that the separate distribution of the work based on | ||
341 | the Library and of the other library facilities is otherwise | ||
342 | permitted, and provided that you do these two things: | ||
343 | |||
344 | a) Accompany the combined library with a copy of the same work | ||
345 | based on the Library, uncombined with any other library | ||
346 | facilities. This must be distributed under the terms of the | ||
347 | Sections above. | ||
348 | |||
349 | b) Give prominent notice with the combined library of the fact | ||
350 | that part of it is a work based on the Library, and explaining | ||
351 | where to find the accompanying uncombined form of the same work. | ||
352 | |||
353 | 8. You may not copy, modify, sublicense, link with, or distribute | ||
354 | the Library except as expressly provided under this License. Any | ||
355 | attempt otherwise to copy, modify, sublicense, link with, or | ||
356 | distribute the Library is void, and will automatically terminate your | ||
357 | rights under this License. However, parties who have received copies, | ||
358 | or rights, from you under this License will not have their licenses | ||
359 | terminated so long as such parties remain in full compliance. | ||
360 | |||
361 | 9. You are not required to accept this License, since you have not | ||
362 | signed it. However, nothing else grants you permission to modify or | ||
363 | distribute the Library or its derivative works. These actions are | ||
364 | prohibited by law if you do not accept this License. Therefore, by | ||
365 | modifying or distributing the Library (or any work based on the | ||
366 | Library), you indicate your acceptance of this License to do so, and | ||
367 | all its terms and conditions for copying, distributing or modifying | ||
368 | the Library or works based on it. | ||
369 | |||
370 | 10. Each time you redistribute the Library (or any work based on the | ||
371 | Library), the recipient automatically receives a license from the | ||
372 | original licensor to copy, distribute, link with or modify the Library | ||
373 | subject to these terms and conditions. You may not impose any further | ||
374 | restrictions on the recipients' exercise of the rights granted herein. | ||
375 | You are not responsible for enforcing compliance by third parties with | ||
376 | this License. | ||
377 | ^L | ||
378 | 11. If, as a consequence of a court judgment or allegation of patent | ||
379 | infringement or for any other reason (not limited to patent issues), | ||
380 | conditions are imposed on you (whether by court order, agreement or | ||
381 | otherwise) that contradict the conditions of this License, they do not | ||
382 | excuse you from the conditions of this License. If you cannot | ||
383 | distribute so as to satisfy simultaneously your obligations under this | ||
384 | License and any other pertinent obligations, then as a consequence you | ||
385 | may not distribute the Library at all. For example, if a patent | ||
386 | license would not permit royalty-free redistribution of the Library by | ||
387 | all those who receive copies directly or indirectly through you, then | ||
388 | the only way you could satisfy both it and this License would be to | ||
389 | refrain entirely from distribution of the Library. | ||
390 | |||
391 | If any portion of this section is held invalid or unenforceable under | ||
392 | any particular circumstance, the balance of the section is intended to | ||
393 | apply, and the section as a whole is intended to apply in other | ||
394 | circumstances. | ||
395 | |||
396 | It is not the purpose of this section to induce you to infringe any | ||
397 | patents or other property right claims or to contest validity of any | ||
398 | such claims; this section has the sole purpose of protecting the | ||
399 | integrity of the free software distribution system which is | ||
400 | implemented by public license practices. Many people have made | ||
401 | generous contributions to the wide range of software distributed | ||
402 | through that system in reliance on consistent application of that | ||
403 | system; it is up to the author/donor to decide if he or she is willing | ||
404 | to distribute software through any other system and a licensee cannot | ||
405 | impose that choice. | ||
406 | |||
407 | This section is intended to make thoroughly clear what is believed to | ||
408 | be a consequence of the rest of this License. | ||
409 | |||
410 | 12. If the distribution and/or use of the Library is restricted in | ||
411 | certain countries either by patents or by copyrighted interfaces, the | ||
412 | original copyright holder who places the Library under this License | ||
413 | may add an explicit geographical distribution limitation excluding those | ||
414 | countries, so that distribution is permitted only in or among | ||
415 | countries not thus excluded. In such case, this License incorporates | ||
416 | the limitation as if written in the body of this License. | ||
417 | |||
418 | 13. The Free Software Foundation may publish revised and/or new | ||
419 | versions of the Lesser General Public License from time to time. | ||
420 | Such new versions will be similar in spirit to the present version, | ||
421 | but may differ in detail to address new problems or concerns. | ||
422 | |||
423 | Each version is given a distinguishing version number. If the Library | ||
424 | specifies a version number of this License which applies to it and | ||
425 | "any later version", you have the option of following the terms and | ||
426 | conditions either of that version or of any later version published by | ||
427 | the Free Software Foundation. If the Library does not specify a | ||
428 | license version number, you may choose any version ever published by | ||
429 | the Free Software Foundation. | ||
430 | ^L | ||
431 | 14. If you wish to incorporate parts of the Library into other free | ||
432 | programs whose distribution conditions are incompatible with these, | ||
433 | write to the author to ask for permission. For software which is | ||
434 | copyrighted by the Free Software Foundation, write to the Free | ||
435 | Software Foundation; we sometimes make exceptions for this. Our | ||
436 | decision will be guided by the two goals of preserving the free status | ||
437 | of all derivatives of our free software and of promoting the sharing | ||
438 | and reuse of software generally. | ||
439 | |||
440 | NO WARRANTY | ||
441 | |||
442 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO | ||
443 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. | ||
444 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR | ||
445 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY | ||
446 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE | ||
447 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
448 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE | ||
449 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME | ||
450 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | ||
451 | |||
452 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN | ||
453 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY | ||
454 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU | ||
455 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR | ||
456 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE | ||
457 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING | ||
458 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A | ||
459 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF | ||
460 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | ||
461 | DAMAGES. | ||
462 | |||
463 | END OF TERMS AND CONDITIONS | ||
464 | ^L | ||
465 | How to Apply These Terms to Your New Libraries | ||
466 | |||
467 | If you develop a new library, and you want it to be of the greatest | ||
468 | possible use to the public, we recommend making it free software that | ||
469 | everyone can redistribute and change. You can do so by permitting | ||
470 | redistribution under these terms (or, alternatively, under the terms | ||
471 | of the ordinary General Public License). | ||
472 | |||
473 | To apply these terms, attach the following notices to the library. | ||
474 | It is safest to attach them to the start of each source file to most | ||
475 | effectively convey the exclusion of warranty; and each file should | ||
476 | have at least the "copyright" line and a pointer to where the full | ||
477 | notice is found. | ||
478 | |||
479 | |||
480 | <one line to give the library's name and a brief idea of what it | ||
481 | does.> | ||
482 | Copyright (C) <year> <name of author> | ||
483 | |||
484 | This library is free software; you can redistribute it and/or | ||
485 | modify it under the terms of the GNU Lesser General Public | ||
486 | License as published by the Free Software Foundation; either | ||
487 | version 2 of the License, or (at your option) any later version. | ||
488 | |||
489 | This library is distributed in the hope that it will be useful, | ||
490 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
491 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
492 | Lesser General Public License for more details. | ||
493 | |||
494 | You should have received a copy of the GNU Lesser General Public | ||
495 | License along with this library; if not, write to the Free Software | ||
496 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
497 | |||
498 | Also add information on how to contact you by electronic and paper | ||
499 | mail. | ||
500 | |||
501 | You should also get your employer (if you work as a programmer) or | ||
502 | your | ||
503 | school, if any, to sign a "copyright disclaimer" for the library, if | ||
504 | necessary. Here is a sample; alter the names: | ||
505 | |||
506 | Yoyodyne, Inc., hereby disclaims all copyright interest in the | ||
507 | library `Frob' (a library for tweaking knobs) written by James | ||
508 | Random Hacker. | ||
509 | |||
510 | <signature of Ty Coon>, 1 April 1990 | ||
511 | Ty Coon, President of Vice | ||
512 | |||
513 | That's all there is to it! | ||
514 | |||
515 | |||
diff --git a/rsync/Makefile.in b/rsync/Makefile.in new file mode 100644 index 0000000..50e7b3d --- a/dev/null +++ b/rsync/Makefile.in | |||
@@ -0,0 +1,391 @@ | |||
1 | ############################################################################# | ||
2 | |||
3 | ####### Compiler, tools and options | ||
4 | |||
5 | CXX =$(SYSCONF_CXX) $(QT_CXX_MT) | ||
6 | CXXFLAGS=$(SYSCONF_CXXFLAGS_QT) $(SYSCONF_CXXFLAGS) $(SYSCONF_CXXFLAGS_LIB) | ||
7 | CC =$(SYSCONF_CC) $(QT_C_MT) | ||
8 | CFLAGS =$(SYSCONF_CFLAGS) $(SYSCONF_CFLAGS_LIB) | ||
9 | INCPATH =-I. | ||
10 | LFLAGS =$(SYSCONF_LFLAGS_QT) $(SYSCONF_RPATH_QT) $(SYSCONF_LFLAGS) $(QT_LFLAGS_MT) | ||
11 | LIBS =$(SUBLIBS) $(SYSCONF_LIBS_QT) $(SYSCONF_LIBS_QTAPP) | ||
12 | MOC =$(SYSCONF_MOC) | ||
13 | UIC =$(SYSCONF_UIC) | ||
14 | |||
15 | ####### Target | ||
16 | |||
17 | DESTDIR = $(QTDIR)/lib$(PROJMAK)/ | ||
18 | VER_MAJ = 1 | ||
19 | VER_MIN = 0 | ||
20 | VER_PATCH = 0 | ||
21 | TARGET= rsync | ||
22 | TARGET1 = lib$(TARGET).so.$(VER_MAJ) | ||
23 | |||
24 | ####### Files | ||
25 | |||
26 | HEADERS =buf.h \ | ||
27 | checksum.h \ | ||
28 | command.h \ | ||
29 | emit.h \ | ||
30 | fileutil.h \ | ||
31 | job.h \ | ||
32 | netint.h \ | ||
33 | protocol.h \ | ||
34 | prototab.h \ | ||
35 | rsync.h \ | ||
36 | search.h \ | ||
37 | stream.h \ | ||
38 | sumset.h \ | ||
39 | trace.h \ | ||
40 | types.h \ | ||
41 | util.h \ | ||
42 | whole.h \ | ||
43 | config.h | ||
44 | SOURCES =base64.c \ | ||
45 | buf.c \ | ||
46 | checksum.c \ | ||
47 | command.c \ | ||
48 | delta.c \ | ||
49 | emit.c \ | ||
50 | fileutil.c \ | ||
51 | hex.c \ | ||
52 | job.c \ | ||
53 | mdfour.c \ | ||
54 | mksum.c \ | ||
55 | msg.c \ | ||
56 | netint.c \ | ||
57 | patch.c \ | ||
58 | prototab.c \ | ||
59 | readsums.c \ | ||
60 | scoop.c \ | ||
61 | search.c \ | ||
62 | stats.c \ | ||
63 | stream.c \ | ||
64 | sumset.c \ | ||
65 | trace.c \ | ||
66 | tube.c \ | ||
67 | util.c \ | ||
68 | version.c \ | ||
69 | whole.c | ||
70 | OBJECTS =base64.o \ | ||
71 | buf.o \ | ||
72 | checksum.o \ | ||
73 | command.o \ | ||
74 | delta.o \ | ||
75 | emit.o \ | ||
76 | fileutil.o \ | ||
77 | hex.o \ | ||
78 | job.o \ | ||
79 | mdfour.o \ | ||
80 | mksum.o \ | ||
81 | msg.o \ | ||
82 | netint.o \ | ||
83 | patch.o \ | ||
84 | prototab.o \ | ||
85 | readsums.o \ | ||
86 | scoop.o \ | ||
87 | search.o \ | ||
88 | stats.o \ | ||
89 | stream.o \ | ||
90 | sumset.o \ | ||
91 | trace.o \ | ||
92 | tube.o \ | ||
93 | util.o \ | ||
94 | version.o \ | ||
95 | whole.o | ||
96 | INTERFACES = | ||
97 | UICDECLS = | ||
98 | UICIMPLS = | ||
99 | SRCMOC = | ||
100 | OBJMOC = | ||
101 | |||
102 | |||
103 | ####### Implicit rules | ||
104 | |||
105 | .SUFFIXES: .cpp .cxx .cc .C .c | ||
106 | |||
107 | .cpp.o: | ||
108 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< | ||
109 | |||
110 | .cxx.o: | ||
111 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< | ||
112 | |||
113 | .cc.o: | ||
114 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< | ||
115 | |||
116 | .C.o: | ||
117 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< | ||
118 | |||
119 | .c.o: | ||
120 | $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< | ||
121 | |||
122 | ####### Build rules | ||
123 | |||
124 | |||
125 | all: $(DESTDIR)$(SYSCONF_LINK_TARGET) | ||
126 | |||
127 | $(DESTDIR)$(SYSCONF_LINK_TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) | ||
128 | $(SYSCONF_LINK_LIB) | ||
129 | |||
130 | moc: $(SRCMOC) | ||
131 | |||
132 | tmake: Makefile.in | ||
133 | |||
134 | Makefile.in: rsync.pro | ||
135 | tmake rsync.pro -o Makefile.in | ||
136 | |||
137 | clean: | ||
138 | -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) | ||
139 | -rm -f *~ core | ||
140 | -rm -f allmoc.cpp | ||
141 | |||
142 | ####### Extension Modules | ||
143 | |||
144 | listpromodules: | ||
145 | @echo | ||
146 | |||
147 | listallmodules: | ||
148 | @echo | ||
149 | |||
150 | listaddonpromodules: | ||
151 | @echo | ||
152 | |||
153 | listaddonentmodules: | ||
154 | @echo | ||
155 | |||
156 | |||
157 | REQUIRES= | ||
158 | |||
159 | ####### Sub-libraries | ||
160 | |||
161 | |||
162 | ###### Combined headers | ||
163 | |||
164 | |||
165 | |||
166 | ####### Compile | ||
167 | |||
168 | base64.o: base64.c \ | ||
169 | config.h \ | ||
170 | config_linux.h \ | ||
171 | rsync.h | ||
172 | |||
173 | buf.o: buf.c \ | ||
174 | config.h \ | ||
175 | config_linux.h \ | ||
176 | rsync.h \ | ||
177 | trace.h \ | ||
178 | buf.h \ | ||
179 | util.h | ||
180 | |||
181 | checksum.o: checksum.c \ | ||
182 | config.h \ | ||
183 | config_linux.h \ | ||
184 | rsync.h \ | ||
185 | checksum.h | ||
186 | |||
187 | command.o: command.c \ | ||
188 | config.h \ | ||
189 | config_linux.h \ | ||
190 | rsync.h \ | ||
191 | command.h | ||
192 | |||
193 | delta.o: delta.c \ | ||
194 | config.h \ | ||
195 | config_linux.h \ | ||
196 | rsync.h \ | ||
197 | emit.h \ | ||
198 | stream.h \ | ||
199 | util.h \ | ||
200 | sumset.h \ | ||
201 | job.h \ | ||
202 | trace.h \ | ||
203 | checksum.h \ | ||
204 | search.h \ | ||
205 | types.h | ||
206 | |||
207 | emit.o: emit.c \ | ||
208 | config.h \ | ||
209 | config_linux.h \ | ||
210 | rsync.h \ | ||
211 | command.h \ | ||
212 | protocol.h \ | ||
213 | trace.h \ | ||
214 | emit.h \ | ||
215 | prototab.h \ | ||
216 | netint.h \ | ||
217 | sumset.h \ | ||
218 | job.h | ||
219 | |||
220 | fileutil.o: fileutil.c \ | ||
221 | config.h \ | ||
222 | config_linux.h \ | ||
223 | rsync.h \ | ||
224 | fileutil.h \ | ||
225 | trace.h | ||
226 | |||
227 | hex.o: hex.c \ | ||
228 | config.h \ | ||
229 | config_linux.h \ | ||
230 | rsync.h | ||
231 | |||
232 | job.o: job.c \ | ||
233 | config.h \ | ||
234 | config_linux.h \ | ||
235 | rsync.h \ | ||
236 | stream.h \ | ||
237 | util.h \ | ||
238 | sumset.h \ | ||
239 | job.h \ | ||
240 | trace.h | ||
241 | |||
242 | mdfour.o: mdfour.c \ | ||
243 | config.h \ | ||
244 | config_linux.h \ | ||
245 | rsync.h \ | ||
246 | trace.h \ | ||
247 | types.h | ||
248 | |||
249 | mksum.o: mksum.c \ | ||
250 | config.h \ | ||
251 | config_linux.h \ | ||
252 | rsync.h \ | ||
253 | stream.h \ | ||
254 | util.h \ | ||
255 | sumset.h \ | ||
256 | job.h \ | ||
257 | protocol.h \ | ||
258 | netint.h \ | ||
259 | trace.h \ | ||
260 | checksum.h | ||
261 | |||
262 | msg.o: msg.c \ | ||
263 | config.h \ | ||
264 | config_linux.h \ | ||
265 | rsync.h | ||
266 | |||
267 | netint.o: netint.c \ | ||
268 | config.h \ | ||
269 | config_linux.h \ | ||
270 | rsync.h \ | ||
271 | job.h \ | ||
272 | netint.h \ | ||
273 | trace.h \ | ||
274 | stream.h | ||
275 | |||
276 | patch.o: patch.c \ | ||
277 | config.h \ | ||
278 | config_linux.h \ | ||
279 | rsync.h \ | ||
280 | util.h \ | ||
281 | trace.h \ | ||
282 | protocol.h \ | ||
283 | netint.h \ | ||
284 | command.h \ | ||
285 | sumset.h \ | ||
286 | prototab.h \ | ||
287 | stream.h \ | ||
288 | job.h | ||
289 | |||
290 | prototab.o: prototab.c \ | ||
291 | config.h \ | ||
292 | config_linux.h \ | ||
293 | rsync.h \ | ||
294 | protocol.h \ | ||
295 | command.h \ | ||
296 | prototab.h | ||
297 | |||
298 | readsums.o: readsums.c \ | ||
299 | config.h \ | ||
300 | config_linux.h \ | ||
301 | rsync.h \ | ||
302 | sumset.h \ | ||
303 | job.h \ | ||
304 | trace.h \ | ||
305 | netint.h \ | ||
306 | protocol.h \ | ||
307 | util.h \ | ||
308 | stream.h | ||
309 | |||
310 | scoop.o: scoop.c \ | ||
311 | config.h \ | ||
312 | config_linux.h \ | ||
313 | rsync.h \ | ||
314 | job.h \ | ||
315 | stream.h \ | ||
316 | trace.h \ | ||
317 | util.h | ||
318 | |||
319 | search.o: search.c \ | ||
320 | config.h \ | ||
321 | config_linux.h \ | ||
322 | rsync.h \ | ||
323 | trace.h \ | ||
324 | util.h \ | ||
325 | sumset.h \ | ||
326 | search.h \ | ||
327 | checksum.h | ||
328 | |||
329 | stats.o: stats.c \ | ||
330 | config.h \ | ||
331 | config_linux.h \ | ||
332 | rsync.h \ | ||
333 | trace.h | ||
334 | |||
335 | stream.o: stream.c \ | ||
336 | config.h \ | ||
337 | config_linux.h \ | ||
338 | rsync.h \ | ||
339 | stream.h \ | ||
340 | util.h \ | ||
341 | trace.h | ||
342 | |||
343 | sumset.o: sumset.c \ | ||
344 | config.h \ | ||
345 | config_linux.h \ | ||
346 | rsync.h \ | ||
347 | sumset.h \ | ||
348 | util.h \ | ||
349 | trace.h | ||
350 | |||
351 | trace.o: trace.c \ | ||
352 | config.h \ | ||
353 | config_linux.h \ | ||
354 | rsync.h \ | ||
355 | util.h \ | ||
356 | trace.h | ||
357 | |||
358 | tube.o: tube.c \ | ||
359 | config.h \ | ||
360 | config_linux.h \ | ||
361 | rsync.h \ | ||
362 | trace.h \ | ||
363 | util.h \ | ||
364 | job.h \ | ||
365 | stream.h | ||
366 | |||
367 | util.o: util.c \ | ||
368 | config.h \ | ||
369 | config_linux.h \ | ||
370 | util.h \ | ||
371 | rsync.h \ | ||
372 | trace.h | ||
373 | |||
374 | version.o: version.c \ | ||
375 | config.h \ | ||
376 | config_linux.h \ | ||
377 | rsync.h | ||
378 | |||
379 | whole.o: whole.c \ | ||
380 | config.h \ | ||
381 | config_linux.h \ | ||
382 | rsync.h \ | ||
383 | trace.h \ | ||
384 | fileutil.h \ | ||
385 | sumset.h \ | ||
386 | job.h \ | ||
387 | buf.h \ | ||
388 | whole.h \ | ||
389 | util.h | ||
390 | |||
391 | |||
diff --git a/rsync/README b/rsync/README new file mode 100644 index 0000000..02df92a --- a/dev/null +++ b/rsync/README | |||
@@ -0,0 +1,62 @@ | |||
1 | librsync is the next generation of librsync, and provides flexible | ||
2 | checksum-based differencing. The main application at the moment in | ||
3 | rproxy, but the library should eventually be generally useful. | ||
4 | |||
5 | http://linuxcare.com.au/rproxy/ | ||
6 | |||
7 | This library was previously known as libhsync up to version 0.9.0. | ||
8 | |||
9 | To use anonymous CVS, see the file README.CVS in this directory. | ||
10 | |||
11 | >> Requirements | ||
12 | |||
13 | To build librsync: | ||
14 | |||
15 | * A C compiler and appropriate headers and libraries | ||
16 | |||
17 | * Make | ||
18 | |||
19 | * popt -- command line parsing library | ||
20 | |||
21 | Available from ftp://ftp.redhat.com/pub/redhat/code/popt | ||
22 | |||
23 | A cut-down version of popt1.5 is included and will be used | ||
24 | automatically if there is no popt library on your build host. | ||
25 | |||
26 | >> Note for RedHat 7.0 | ||
27 | |||
28 | RedHat 7.0 (Guiness) ships with a buggy version of GCC 2.96 that | ||
29 | produces many warnings while compiling librsync. These are harmless | ||
30 | -- the library seems to work anyhow. You can avoid the warnings by | ||
31 | using the 'kgcc' version of the compiler: | ||
32 | |||
33 | $ export CC=kgcc | ||
34 | $ ./autogen.sh | ||
35 | $ make all check | ||
36 | |||
37 | >> Library Versions | ||
38 | |||
39 | librsync uses the GNU libtool library versioning system, so the | ||
40 | filename does not correspond to the librsync release. To show the | ||
41 | library release and version, use the librsyncinfo tool. | ||
42 | |||
43 | >> Platforms | ||
44 | |||
45 | librsync/rproxy is known to run on: | ||
46 | |||
47 | GNU Linux Debian 2.2 x86 | ||
48 | |||
49 | SUNWspro: (use -v for more warnings) | ||
50 | |||
51 | mips-sgi-irix6.5: works, but you must use GNU Make rather than the | ||
52 | default SGI Make. I used gcc. | ||
53 | |||
54 | >> API Documentation | ||
55 | |||
56 | librsync contains markup for automatic API documentation generation | ||
57 | using the Doxygen tool: | ||
58 | |||
59 | http://www.doxygen.org/ | ||
60 | |||
61 | $Id$ | ||
62 | |||
diff --git a/rsync/THANKS b/rsync/THANKS new file mode 100644 index 0000000..2e604e7 --- a/dev/null +++ b/rsync/THANKS | |||
@@ -0,0 +1,21 @@ | |||
1 | -*- text -*- | ||
2 | |||
3 | Andrew Tridgell and Paulus Mackerras started this whole mess. Luke | ||
4 | Leighton was a tremendous help in sorting out the combined | ||
5 | encoding/signature algorithm. | ||
6 | |||
7 | Thanks to Linuxcare, Inc, <http://linuxcare.com/> for their support of | ||
8 | this project. | ||
9 | |||
10 | Neale Banks <neale@lowendale.com.au>: the first known user outside of | ||
11 | OzLabs, and helped keep me honest. | ||
12 | |||
13 | Paul `Rusty' Russell <rusty@linuxcare.com> | ||
14 | Andrew Tridgell <tridge@samba.org> | ||
15 | Paulus Mackerras <paulus@linuxcare.com> | ||
16 | Peter Barker <pbarker@samba.org> | ||
17 | Neale Banks <neale@lowendale.com.au> | ||
18 | Luke Kenneth Casson Leighton <lkcl@samba.org> | ||
19 | Tim Potter <tpot@linuxcare.com.au> | ||
20 | Hugh Blemings <hugh@linuxcare.com.au> | ||
21 | David Gibson <dgibson@linuxcare.com.au> | ||
diff --git a/rsync/acconfig.h b/rsync/acconfig.h new file mode 100644 index 0000000..94083c7 --- a/dev/null +++ b/rsync/acconfig.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* acconfig.h -- hand-written definitions to eventually go into config.h */ | ||
2 | |||
3 | /* Define this to enable trace code */ | ||
4 | #undef DO_RS_TRACE | ||
5 | |||
6 | /* Version of the libtool interface. */ | ||
7 | #define RS_LIBVERSION "unknown" | ||
8 | |||
9 | /* Define this if your sockaddr structure contains sin_len */ | ||
10 | #undef HAVE_SOCK_SIN_LEN | ||
11 | |||
12 | /* Define this if there is a connect(2) call */ | ||
13 | #undef HAVE_CONNECT | ||
14 | |||
15 | /* Define if we have an off64_t largefile type */ | ||
16 | #undef HAVE_OFF64_T | ||
17 | |||
18 | /* Ask for large file support (LFS). Should always be on, even if it | ||
19 | * achieves nothing. */ | ||
20 | #undef _LARGEFILE_SOURCE | ||
21 | #undef _LARGEFILE64_SOURCE | ||
22 | |||
23 | /* How many bits would you like to have in an off_t? */ | ||
24 | #undef _FILE_OFFSET_BITS | ||
25 | |||
26 | /* Define to include GNU C library extensions. */ | ||
27 | #undef _GNU_SOURCE | ||
28 | |||
29 | /* Define to get i18n support */ | ||
30 | #undef ENABLE_NLS | ||
31 | |||
32 | /* Define if you want the suboptimal X/Open catgets implementation */ | ||
33 | #undef HAVE_CATGETS | ||
34 | |||
35 | /* Define if you want the nice new GNU and Uniforum gettext system */ | ||
36 | #undef HAVE_GETTEXT | ||
37 | |||
38 | /* Define if your system has the LC_MESSAGES locale category */ | ||
39 | #undef HAVE_LC_MESSAGES | ||
40 | |||
41 | /* Define if you have stpcpy (copy a string and return a pointer to | ||
42 | * the end of the result.) */ | ||
43 | #undef HAVE_STPCPY | ||
44 | |||
45 | /* GNU extension of saving argv[0] to program_invocation_short_name */ | ||
46 | #undef HAVE_PROGRAM_INVOCATION_NAME | ||
47 | |||
48 | /* Canonical GNU hostname */ | ||
49 | #define RS_CANONICAL_HOST "unknown" | ||
50 | |||
51 | /* Define to a replacement type if intmax_t is not a builtin, or in | ||
52 | sys/types.h or stdlib.h or stddef.h */ | ||
53 | #undef intmax_t | ||
54 | |||
55 | /* end of acconfig.h */ | ||
diff --git a/rsync/base64.c b/rsync/base64.c new file mode 100644 index 0000000..cbe7a8c --- a/dev/null +++ b/rsync/base64.c | |||
@@ -0,0 +1,101 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | |||
24 | #include <config_rsync.h> | ||
25 | |||
26 | #include <string.h> | ||
27 | #include <stdlib.h> | ||
28 | #include <stdio.h> | ||
29 | |||
30 | #include "rsync.h" | ||
31 | |||
32 | /* | ||
33 | * Decode a base64 string in-place - simple and slow algorithm | ||
34 | * | ||
35 | * See RFC1521 for the specification of base64. | ||
36 | */ | ||
37 | size_t rs_unbase64(char *s) | ||
38 | { | ||
39 | char const *b64 = | ||
40 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | ||
41 | int bit_offset, byte_offset, idx, i, n; | ||
42 | unsigned char *d = (unsigned char *) s; | ||
43 | char *p; | ||
44 | |||
45 | n = i = 0; | ||
46 | |||
47 | while (*s && (p = strchr(b64, *s))) { | ||
48 | idx = (int) (p - b64); | ||
49 | byte_offset = (i * 6) / 8; | ||
50 | bit_offset = (i * 6) % 8; | ||
51 | d[byte_offset] &= ~((1 << (8 - bit_offset)) - 1); | ||
52 | if (bit_offset < 3) { | ||
53 | d[byte_offset] |= (idx << (2 - bit_offset)); | ||
54 | n = byte_offset + 1; | ||
55 | } else { | ||
56 | d[byte_offset] |= (idx >> (bit_offset - 2)); | ||
57 | d[byte_offset + 1] = 0; | ||
58 | d[byte_offset + 1] |= (idx << (8 - (bit_offset - 2))) & 0xFF; | ||
59 | n = byte_offset + 2; | ||
60 | } | ||
61 | s++; | ||
62 | i++; | ||
63 | } | ||
64 | |||
65 | return n; | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * Encode a buffer as base64 - simple and slow algorithm. | ||
70 | */ | ||
71 | void | ||
72 | rs_base64(unsigned char const *buf, int n, char *out) | ||
73 | { | ||
74 | char const *b64 = | ||
75 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | ||
76 | int bytes, i; | ||
77 | |||
78 | /* work out how many bytes of output there are */ | ||
79 | bytes = ((n * 8) + 5) / 6; | ||
80 | |||
81 | for (i = 0; i < bytes; i++) { | ||
82 | int byte = (i * 6) / 8; | ||
83 | int bit = (i * 6) % 8; | ||
84 | |||
85 | if (bit < 3) { | ||
86 | if (byte >= n) | ||
87 | abort(); | ||
88 | *out = b64[(buf[byte] >> (2 - bit)) & 0x3F]; | ||
89 | } else { | ||
90 | if (byte + 1 == n) { | ||
91 | *out = b64[(buf[byte] << (bit - 2)) & 0x3F]; | ||
92 | } else { | ||
93 | *out = b64[(buf[byte] << (bit - 2) | | ||
94 | buf[byte + 1] >> (10 - bit)) & 0x3F]; | ||
95 | } | ||
96 | } | ||
97 | out++; | ||
98 | } | ||
99 | *out = 0; | ||
100 | } | ||
101 | |||
diff --git a/rsync/buf.c b/rsync/buf.c new file mode 100644 index 0000000..2814583 --- a/dev/null +++ b/rsync/buf.c | |||
@@ -0,0 +1,214 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | | Pick a window, Jimmy, you're leaving. | ||
25 | | -- Martin Schwenke, regularly | ||
26 | */ | ||
27 | |||
28 | |||
29 | /* | ||
30 | * buf.c -- Buffers that map between stdio file streams and librsync | ||
31 | * streams. As the stream consumes input and produces output, it is | ||
32 | * refilled from appropriate input and output FILEs. A dynamically | ||
33 | * allocated buffer of configurable size is used as an intermediary. | ||
34 | * | ||
35 | * TODO: Perhaps be more efficient by filling the buffer on every call | ||
36 | * even if not yet completely empty. Check that it's really our | ||
37 | * buffer, and shuffle remaining data down to the front. | ||
38 | * | ||
39 | * TODO: Perhaps expose a routine for shuffling the buffers. | ||
40 | */ | ||
41 | |||
42 | |||
43 | #include <config_rsync.h> | ||
44 | |||
45 | #include <assert.h> | ||
46 | #include <stdlib.h> | ||
47 | #include <stdio.h> | ||
48 | #include <errno.h> | ||
49 | #include <string.h> | ||
50 | |||
51 | #include "rsync.h" | ||
52 | #include "trace.h" | ||
53 | #include "buf.h" | ||
54 | #include "util.h" | ||
55 | |||
56 | /** | ||
57 | * File IO buffer sizes. | ||
58 | */ | ||
59 | int rs_inbuflen = 16000, rs_outbuflen = 16000; | ||
60 | |||
61 | |||
62 | struct rs_filebuf { | ||
63 | FILE *f; | ||
64 | char *buf; | ||
65 | size_t buf_len; | ||
66 | }; | ||
67 | |||
68 | |||
69 | |||
70 | rs_filebuf_t *rs_filebuf_new(FILE *f, size_t buf_len) | ||
71 | { | ||
72 | rs_filebuf_t *pf = rs_alloc_struct(rs_filebuf_t); | ||
73 | |||
74 | pf->buf = rs_alloc(buf_len, "file buffer"); | ||
75 | pf->buf_len = buf_len; | ||
76 | pf->f = f; | ||
77 | |||
78 | return pf; | ||
79 | } | ||
80 | |||
81 | |||
82 | void rs_filebuf_free(rs_filebuf_t *fb) | ||
83 | { | ||
84 | if ( fb->buf ) | ||
85 | free ( fb->buf ); | ||
86 | rs_bzero(fb, sizeof *fb); | ||
87 | free(fb); | ||
88 | } | ||
89 | |||
90 | |||
91 | /* | ||
92 | * If the stream has no more data available, read some from F into | ||
93 | * BUF, and let the stream use that. On return, SEEN_EOF is true if | ||
94 | * the end of file has passed into the stream. | ||
95 | */ | ||
96 | rs_result rs_infilebuf_fill(rs_job_t *job, rs_buffers_t *buf, | ||
97 | void *opaque) | ||
98 | { | ||
99 | int len; | ||
100 | rs_filebuf_t *fb = (rs_filebuf_t *) opaque; | ||
101 | FILE *f = fb->f; | ||
102 | |||
103 | /* This is only allowed if either the buf has no input buffer | ||
104 | * yet, or that buffer could possibly be BUF. */ | ||
105 | if (buf->next_in != NULL) { | ||
106 | assert(buf->avail_in <= fb->buf_len); | ||
107 | assert(buf->next_in >= fb->buf); | ||
108 | assert(buf->next_in <= fb->buf + fb->buf_len); | ||
109 | } else { | ||
110 | assert(buf->avail_in == 0); | ||
111 | } | ||
112 | |||
113 | if (buf->eof_in || (buf->eof_in = feof(f))) { | ||
114 | rs_trace("seen end of file on input"); | ||
115 | buf->eof_in = 1; | ||
116 | return RS_DONE; | ||
117 | } | ||
118 | |||
119 | if (buf->avail_in) | ||
120 | /* Still some data remaining. Perhaps we should read | ||
121 | anyhow? */ | ||
122 | return RS_DONE; | ||
123 | |||
124 | len = fread(fb->buf, 1, fb->buf_len, f); | ||
125 | if (len < 0) { | ||
126 | if (ferror(f)) { | ||
127 | rs_error("error filling buf from file: %s", | ||
128 | strerror(errno)); | ||
129 | return RS_IO_ERROR; | ||
130 | } else { | ||
131 | rs_error("no error bit, but got %d return when trying to read", | ||
132 | len); | ||
133 | return RS_IO_ERROR; | ||
134 | } | ||
135 | } | ||
136 | buf->avail_in = len; | ||
137 | buf->next_in = fb->buf; | ||
138 | |||
139 | return RS_DONE; | ||
140 | } | ||
141 | |||
142 | |||
143 | /* | ||
144 | * The buf is already using BUF for an output buffer, and probably | ||
145 | * contains some buffered output now. Write this out to F, and reset | ||
146 | * the buffer cursor. | ||
147 | */ | ||
148 | rs_result rs_outfilebuf_drain(rs_job_t *job, rs_buffers_t *buf, void *opaque) | ||
149 | { | ||
150 | int present; | ||
151 | rs_filebuf_t *fb = (rs_filebuf_t *) opaque; | ||
152 | FILE *f = fb->f; | ||
153 | |||
154 | /* This is only allowed if either the buf has no output buffer | ||
155 | * yet, or that buffer could possibly be BUF. */ | ||
156 | if (buf->next_out == NULL) { | ||
157 | assert(buf->avail_out == 0); | ||
158 | |||
159 | buf->next_out = fb->buf; | ||
160 | buf->avail_out = fb->buf_len; | ||
161 | |||
162 | return RS_DONE; | ||
163 | } | ||
164 | |||
165 | assert(buf->avail_out <= fb->buf_len); | ||
166 | assert(buf->next_out >= fb->buf); | ||
167 | assert(buf->next_out <= fb->buf + fb->buf_len); | ||
168 | |||
169 | present = buf->next_out - fb->buf; | ||
170 | if (present > 0) { | ||
171 | int result; | ||
172 | |||
173 | assert(present > 0); | ||
174 | |||
175 | result = fwrite(fb->buf, 1, present, f); | ||
176 | if (present != result) { | ||
177 | rs_error("error draining buf to file: %s", | ||
178 | strerror(errno)); | ||
179 | return RS_IO_ERROR; | ||
180 | } | ||
181 | |||
182 | buf->next_out = fb->buf; | ||
183 | buf->avail_out = fb->buf_len; | ||
184 | } | ||
185 | |||
186 | return RS_DONE; | ||
187 | } | ||
188 | |||
189 | |||
190 | /** | ||
191 | * Default copy implementation that retrieves a part of a stdio file. | ||
192 | */ | ||
193 | rs_result rs_file_copy_cb(void *arg, off_t pos, size_t *len, void **buf) | ||
194 | { | ||
195 | int got; | ||
196 | FILE *f = (FILE *) arg; | ||
197 | |||
198 | if (fseek(f, pos, SEEK_SET)) { | ||
199 | rs_log(RS_LOG_ERR, "seek failed: %s", strerror(errno)); | ||
200 | return RS_IO_ERROR; | ||
201 | } | ||
202 | |||
203 | got = fread(*buf, 1, *len, f); | ||
204 | if (got == -1) { | ||
205 | rs_error(strerror(errno)); | ||
206 | return RS_IO_ERROR; | ||
207 | } else if (got == 0) { | ||
208 | rs_error("unexpected eof on fd%d", fileno(f)); | ||
209 | return RS_INPUT_ENDED; | ||
210 | } else { | ||
211 | *len = got; | ||
212 | return RS_DONE; | ||
213 | } | ||
214 | } | ||
diff --git a/rsync/buf.h b/rsync/buf.h new file mode 100644 index 0000000..cb8386e --- a/dev/null +++ b/rsync/buf.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | typedef struct rs_filebuf rs_filebuf_t; | ||
24 | |||
25 | rs_filebuf_t *rs_filebuf_new(FILE *f, size_t buf_len); | ||
26 | |||
27 | void rs_filebuf_free(rs_filebuf_t *fb); | ||
28 | |||
29 | rs_result rs_infilebuf_fill(rs_job_t *, rs_buffers_t *buf, void *fb); | ||
30 | |||
31 | rs_result rs_outfilebuf_drain(rs_job_t *, rs_buffers_t *, void *fb); | ||
diff --git a/rsync/checksum.c b/rsync/checksum.c new file mode 100644 index 0000000..eab9e46 --- a/dev/null +++ b/rsync/checksum.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * Copyright (C) 1996 by Andrew Tridgell | ||
8 | * Copyright (C) 1996 by Paul Mackerras | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU Lesser General Public License as published by | ||
12 | * the Free Software Foundation; either version 2.1 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU Lesser General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU Lesser General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | #include <config_rsync.h> | ||
26 | |||
27 | #include <assert.h> | ||
28 | #include <stdlib.h> | ||
29 | #include <stdio.h> | ||
30 | |||
31 | #include "rsync.h" | ||
32 | #include "checksum.h" | ||
33 | |||
34 | |||
35 | /* This can possibly be used to restart the checksum system in the | ||
36 | * case where we detected corruption. I'm not sure yet how to make | ||
37 | * this useful in librsync. */ | ||
38 | int checksum_seed = 0; | ||
39 | |||
40 | /* | ||
41 | * A simple 32 bit checksum that can be updated from either end | ||
42 | * (inspired by Mark Adler's Adler-32 checksum) | ||
43 | */ | ||
44 | unsigned int rs_calc_weak_sum(void const *p, int len) | ||
45 | { | ||
46 | int i; | ||
47 | unsigned s1, s2; | ||
48 | unsigned char const *buf = (unsigned char const *) p; | ||
49 | |||
50 | s1 = s2 = 0; | ||
51 | for (i = 0; i < (len - 4); i += 4) { | ||
52 | s2 += 4 * (s1 + buf[i]) + 3 * buf[i + 1] + | ||
53 | 2 * buf[i + 2] + buf[i + 3] + 10 * RS_CHAR_OFFSET; | ||
54 | s1 += (buf[i + 0] + buf[i + 1] + buf[i + 2] + buf[i + 3] + | ||
55 | 4 * RS_CHAR_OFFSET); | ||
56 | } | ||
57 | for (; i < len; i++) { | ||
58 | s1 += (buf[i] + RS_CHAR_OFFSET); | ||
59 | s2 += s1; | ||
60 | } | ||
61 | return (s1 & 0xffff) + (s2 << 16); | ||
62 | } | ||
63 | |||
64 | |||
65 | /** | ||
66 | * Calculate and store into SUM a strong MD4 checksum of the file | ||
67 | * blocks seen so far. | ||
68 | * | ||
69 | * In plain rsync, the checksum is perturbed by a seed value. This is | ||
70 | * used when retrying a failed transmission: we've discovered that the | ||
71 | * hashes collided at some point, so we're going to try again with | ||
72 | * different hashes to see if we can get it right. (Check tridge's | ||
73 | * thesis for details and to see if that's correct.) | ||
74 | * | ||
75 | * Since we can't retry a web transaction I'm not sure if it's very | ||
76 | * useful in rproxy. | ||
77 | */ | ||
78 | void rs_calc_strong_sum(void const *buf, size_t len, rs_strong_sum_t *sum) | ||
79 | { | ||
80 | rs_mdfour((unsigned char *) sum, buf, len); | ||
81 | } | ||
diff --git a/rsync/checksum.h b/rsync/checksum.h new file mode 100644 index 0000000..b9fe543 --- a/dev/null +++ b/rsync/checksum.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Lesser General Public License as published by | ||
10 | * the Free Software Foundation; either version 2.1 of the License, or | ||
11 | * (at your option) 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 Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | rs_weak_sum_t rs_calc_weak_sum(void const *buf1, int len); | ||
24 | |||
25 | void rs_calc_strong_sum(void const *buf, size_t buf_len, rs_strong_sum_t *); | ||
26 | |||
27 | /* We should make this something other than zero to improve the | ||
28 | * checksum algorithm: tridge suggests a prime number. */ | ||
29 | #define RS_CHAR_OFFSET 31 | ||
30 | |||
diff --git a/rsync/command.c b/rsync/command.c new file mode 100644 index 0000000..9d56733 --- a/dev/null +++ b/rsync/command.c | |||
@@ -0,0 +1,61 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | |||
24 | #include <config_rsync.h> | ||
25 | |||
26 | #include <assert.h> | ||
27 | #include <stdlib.h> | ||
28 | #include <stdio.h> | ||
29 | |||
30 | #include "rsync.h" | ||
31 | #include "command.h" | ||
32 | |||
33 | /* For debugging purposes, here are some human-readable forms. */ | ||
34 | struct rs_op_kind_name const rs_op_kind_names[] = { | ||
35 | {"END", RS_KIND_END }, | ||
36 | {"COPY", RS_KIND_COPY }, | ||
37 | {"LITERAL", RS_KIND_LITERAL }, | ||
38 | {"SIGNATURE", RS_KIND_SIGNATURE }, | ||
39 | {"CHECKSUM", RS_KIND_CHECKSUM }, | ||
40 | {"INVALID", RS_KIND_INVALID }, | ||
41 | {NULL, 0 } | ||
42 | }; | ||
43 | |||
44 | |||
45 | /* | ||
46 | * Return a human-readable name for KIND. | ||
47 | */ | ||
48 | char const * rs_op_kind_name(enum rs_op_kind kind) | ||
49 | { | ||
50 | const struct rs_op_kind_name *k; | ||
51 | |||
52 | for (k = rs_op_kind_names; k->kind; k++) { | ||
53 | if (k->kind == kind) { | ||
54 | return k->name; | ||
55 | } | ||
56 | } | ||
57 | |||
58 | return NULL; | ||
59 | } | ||
60 | |||
61 | |||
diff --git a/rsync/command.h b/rsync/command.h new file mode 100644 index 0000000..43da19d --- a/dev/null +++ b/rsync/command.h | |||
@@ -0,0 +1,58 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * Copyright (C) 1999 by Andrew Tridgell <tridge@samba.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU Lesser General Public License | ||
11 | * as published by the Free Software Foundation; either version 2.1 of | ||
12 | * the License, or (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public | ||
20 | * License along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | |||
25 | /* | ||
26 | * command.h -- Types of commands present in the encoding stream. | ||
27 | * | ||
28 | * The vague idea is that eventually this file will be more abstract | ||
29 | * than protocol.h, but it's not clear that will ever be required. | ||
30 | */ | ||
31 | |||
32 | |||
33 | /** | ||
34 | * Classes of operation that can be present. Each may have several different | ||
35 | * possible representations. | ||
36 | */ | ||
37 | enum rs_op_kind { | ||
38 | RS_KIND_END = 1000, | ||
39 | RS_KIND_LITERAL, | ||
40 | RS_KIND_SIGNATURE, | ||
41 | RS_KIND_COPY, | ||
42 | RS_KIND_CHECKSUM, | ||
43 | RS_KIND_RESERVED, /* for future expansion */ | ||
44 | |||
45 | /* This one should never occur in file streams. It's an | ||
46 | * internal marker for invalid commands. */ | ||
47 | RS_KIND_INVALID | ||
48 | }; | ||
49 | |||
50 | |||
51 | typedef struct rs_op_kind_name { | ||
52 | char const *name; | ||
53 | enum rs_op_kind const kind; | ||
54 | } rs_op_kind_name_t; | ||
55 | |||
56 | char const * rs_op_kind_name(enum rs_op_kind); | ||
57 | |||
58 | |||
diff --git a/rsync/config_linux.h b/rsync/config_linux.h new file mode 100644 index 0000000..e5ff3e4 --- a/dev/null +++ b/rsync/config_linux.h | |||
@@ -0,0 +1,115 @@ | |||
1 | /* config.h. Generated automatically by configure. */ | ||
2 | /* config.h.in. Generated automatically from configure.in by autoheader 2.13. */ | ||
3 | |||
4 | /* Define to empty if the keyword does not work. */ | ||
5 | /* #undef const */ | ||
6 | |||
7 | /* Define to `long' if <sys/types.h> doesn't define. */ | ||
8 | /* #undef off_t */ | ||
9 | |||
10 | /* Define to `unsigned' if <sys/types.h> doesn't define. */ | ||
11 | /* #undef size_t */ | ||
12 | |||
13 | /* Define if you have the ANSI C header files. */ | ||
14 | #define STDC_HEADERS 1 | ||
15 | |||
16 | /* Define this if your sockaddr structure contains sin_len */ | ||
17 | /* #undef HAVE_SOCK_SIN_LEN */ | ||
18 | |||
19 | /* How many bits would you like to have in an off_t? */ | ||
20 | #define _FILE_OFFSET_BITS 64 | ||
21 | |||
22 | /* Define to include GNU C library extensions. */ | ||
23 | #define _GNU_SOURCE 1 | ||
24 | |||
25 | /* GNU extension of saving argv[0] to program_invocation_short_name */ | ||
26 | #define HAVE_PROGRAM_INVOCATION_NAME 1 | ||
27 | |||
28 | /* Define to a replacement type if intmax_t is not a builtin, or in | ||
29 | sys/types.h or stdlib.h or stddef.h */ | ||
30 | /* #undef intmax_t */ | ||
31 | |||
32 | /* The number of bytes in a int. */ | ||
33 | #define SIZEOF_INT 4 | ||
34 | |||
35 | /* The number of bytes in a long. */ | ||
36 | #define SIZEOF_LONG 4 | ||
37 | |||
38 | /* The number of bytes in a off_t. */ | ||
39 | #define SIZEOF_OFF_T 8 | ||
40 | |||
41 | /* The number of bytes in a short. */ | ||
42 | #define SIZEOF_SHORT 2 | ||
43 | |||
44 | /* The number of bytes in a size_t. */ | ||
45 | #define SIZEOF_SIZE_T 4 | ||
46 | |||
47 | /* The number of bytes in a unsigned char. */ | ||
48 | #define SIZEOF_UNSIGNED_CHAR 1 | ||
49 | |||
50 | /* The number of bytes in a unsigned int. */ | ||
51 | #define SIZEOF_UNSIGNED_INT 4 | ||
52 | |||
53 | /* The number of bytes in a unsigned long. */ | ||
54 | #define SIZEOF_UNSIGNED_LONG 4 | ||
55 | |||
56 | /* The number of bytes in a unsigned short. */ | ||
57 | #define SIZEOF_UNSIGNED_SHORT 2 | ||
58 | |||
59 | /* Define if you have the mtrace function. */ | ||
60 | #define HAVE_MTRACE 1 | ||
61 | |||
62 | /* Define if you have the snprintf function. */ | ||
63 | #define HAVE_SNPRINTF 1 | ||
64 | |||
65 | /* Define if you have the strerror function. */ | ||
66 | #define HAVE_STRERROR 1 | ||
67 | |||
68 | /* Define if you have the vsnprintf function. */ | ||
69 | #define HAVE_VSNPRINTF 1 | ||
70 | |||
71 | /* Define if you have the <alloca.h> header file. */ | ||
72 | #define HAVE_ALLOCA_H 1 | ||
73 | |||
74 | /* Define if you have the <bzlib.h> header file. */ | ||
75 | #define HAVE_BZLIB_H 1 | ||
76 | |||
77 | /* Define if you have the <config.h> header file. */ | ||
78 | /* #undef HAVE_CONFIG_H */ | ||
79 | |||
80 | /* Define if you have the <dlfcn.h> header file. */ | ||
81 | #define HAVE_DLFCN_H 1 | ||
82 | |||
83 | /* Define if you have the <libintl.h> header file. */ | ||
84 | #define HAVE_LIBINTL_H 1 | ||
85 | |||
86 | /* Define if you have the <mcheck.h> header file. */ | ||
87 | #define HAVE_MCHECK_H 1 | ||
88 | |||
89 | /* Define if you have the <stdint.h> header file. */ | ||
90 | #define HAVE_STDINT_H 1 | ||
91 | |||
92 | /* Define if you have the <unistd.h> header file. */ | ||
93 | #define HAVE_UNISTD_H 1 | ||
94 | |||
95 | /* Define if you have the popt library (-lpopt). */ | ||
96 | #define HAVE_LIBPOPT 1 | ||
97 | |||
98 | /* Name of package */ | ||
99 | #define PACKAGE "librsync" | ||
100 | |||
101 | /* Version number of package */ | ||
102 | #define VERSION "0.9.5" | ||
103 | |||
104 | /* Number of bits in a file offset, on hosts where this is settable. */ | ||
105 | #define _FILE_OFFSET_BITS 64 | ||
106 | |||
107 | /* Define to make ftello visible on some hosts (e.g. HP-UX 10.20). */ | ||
108 | /* #undef _LARGEFILE_SOURCE */ | ||
109 | |||
110 | /* Define for large files, on AIX-style hosts. */ | ||
111 | /* #undef _LARGE_FILES */ | ||
112 | |||
113 | /* Define to make ftello visible on some hosts (e.g. glibc 2.1.3). */ | ||
114 | /* #undef _XOPEN_SOURCE */ | ||
115 | |||
diff --git a/rsync/config_rsync.h b/rsync/config_rsync.h new file mode 100644 index 0000000..a646eba --- a/dev/null +++ b/rsync/config_rsync.h | |||
@@ -0,0 +1,2 @@ | |||
1 | #include "config_linux.h" | ||
2 | |||
diff --git a/rsync/delta.c b/rsync/delta.c new file mode 100644 index 0000000..323c079 --- a/dev/null +++ b/rsync/delta.c | |||
@@ -0,0 +1,351 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Lesser General Public License as published by | ||
10 | * the Free Software Foundation; either version 2.1 of the License, or | ||
11 | * (at your option) 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 Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | | Let's climb to the TOP of that | ||
25 | | MOUNTAIN and think about STRIP | ||
26 | | MINING!! | ||
27 | */ | ||
28 | |||
29 | |||
30 | /* | ||
31 | * delta.c -- Generate in streaming mode an rsync delta given a set of | ||
32 | * signatures, and a new file. | ||
33 | * | ||
34 | * The size of blocks for signature generation is determined by the | ||
35 | * block size in the incoming signature. | ||
36 | * | ||
37 | * To calculate a signature, we need to be able to see at least one | ||
38 | * block of the new file at a time. Once we have that, we calculate | ||
39 | * its weak signature, and see if there is any block in the signature | ||
40 | * hash table that has the same weak sum. If there is one, then we | ||
41 | * also compute the strong sum of the new block, and cross check that. | ||
42 | * If they're the same, then we can assume we have a match. | ||
43 | * | ||
44 | * The final block of the file has to be handled a little differently, | ||
45 | * because it may be a short match. Short blocks in the signature | ||
46 | * don't include their length -- we just allow for the final short | ||
47 | * block of the file to match any block in the signature, and if they | ||
48 | * have the same checksum we assume they must have the same length. | ||
49 | * Therefore, when we emit a COPY command, we have to send it with a | ||
50 | * length that is the same as the block matched, and not the block | ||
51 | * length from the signature. | ||
52 | */ | ||
53 | |||
54 | /* | ||
55 | * Profiling results as of v1.26, 2001-03-18: | ||
56 | * | ||
57 | * If everything matches, then we spend almost all our time in | ||
58 | * rs_mdfour64 and rs_weak_sum, which is unavoidable and therefore a | ||
59 | * good profile. | ||
60 | * | ||
61 | * If nothing matches, it is not so good. | ||
62 | */ | ||
63 | |||
64 | |||
65 | #include <config_rsync.h> | ||
66 | |||
67 | #include <assert.h> | ||
68 | #include <stdlib.h> | ||
69 | #include <stdio.h> | ||
70 | |||
71 | #include "rsync.h" | ||
72 | #include "emit.h" | ||
73 | #include "stream.h" | ||
74 | #include "util.h" | ||
75 | #include "sumset.h" | ||
76 | #include "job.h" | ||
77 | #include "trace.h" | ||
78 | #include "checksum.h" | ||
79 | #include "search.h" | ||
80 | #include "types.h" | ||
81 | |||
82 | |||
83 | /** | ||
84 | * Turn this on to make all rolling checksums be checked from scratch. | ||
85 | */ | ||
86 | int rs_roll_paranoia = 0; | ||
87 | |||
88 | |||
89 | static rs_result rs_delta_scan(rs_job_t *, rs_long_t avail_len, void *); | ||
90 | |||
91 | static rs_result rs_delta_s_deferred_copy(rs_job_t *job); | ||
92 | |||
93 | |||
94 | |||
95 | static rs_result rs_delta_s_end(rs_job_t *job) | ||
96 | { | ||
97 | rs_emit_end_cmd(job); | ||
98 | return RS_DONE; | ||
99 | } | ||
100 | |||
101 | |||
102 | /** | ||
103 | * \brief Get a block of data if possible, and see if it matches. | ||
104 | * | ||
105 | * On each call, we try to process all of the input data available on | ||
106 | * the scoop and input buffer. | ||
107 | */ | ||
108 | static rs_result | ||
109 | rs_delta_s_scan(rs_job_t *job) | ||
110 | { | ||
111 | size_t this_len, avail_len; | ||
112 | int is_ending; | ||
113 | void *inptr; | ||
114 | rs_result result; | ||
115 | |||
116 | rs_job_check(job); | ||
117 | |||
118 | avail_len = rs_scoop_total_avail(job); | ||
119 | this_len = job->block_len; | ||
120 | is_ending = job->stream->eof_in; | ||
121 | |||
122 | /* Now, we have avail_len bytes, and we need to scan through them | ||
123 | * looking for a match. We'll always end up emitting exactly one | ||
124 | * command, either a literal or a copy, and after discovering that | ||
125 | * we will skip over the appropriate number of bytes. */ | ||
126 | if (avail_len == 0) { | ||
127 | if (is_ending) { | ||
128 | /* no more delta to do */ | ||
129 | job->statefn = rs_delta_s_end; | ||
130 | } | ||
131 | return RS_BLOCKED; | ||
132 | } | ||
133 | |||
134 | /* must read at least one block, or give up */ | ||
135 | if ((avail_len < job->block_len) && !is_ending) { | ||
136 | /* we know we won't get it, but we have to try for a whole | ||
137 | * block anyhow so that it gets into the scoop. */ | ||
138 | rs_scoop_input(job, job->block_len); | ||
139 | return RS_BLOCKED; | ||
140 | } | ||
141 | |||
142 | result = rs_scoop_readahead(job, avail_len, &inptr); | ||
143 | if (result != RS_DONE) | ||
144 | return result; | ||
145 | |||
146 | return rs_delta_scan(job, avail_len, inptr); | ||
147 | } | ||
148 | |||
149 | |||
150 | |||
151 | /** | ||
152 | * Scan for a matching block in the next \p avail_len bytes of input. | ||
153 | * | ||
154 | * If nonmatching data is found, then a LITERAL command will be put in | ||
155 | * the tube immediately. If matching data is found, then its position | ||
156 | * will be saved in the job, and the job state set up to write out a | ||
157 | * COPY command after handling the literal. | ||
158 | */ | ||
159 | static rs_result | ||
160 | rs_delta_scan(rs_job_t *job, rs_long_t avail_len, void *p) | ||
161 | { | ||
162 | rs_long_t match_where; | ||
163 | int search_pos, end_pos; | ||
164 | unsigned char *inptr = (unsigned char *) p; | ||
165 | uint32_t s1 = job->weak_sig & 0xFFFF; | ||
166 | uint32_t s2 = job->weak_sig >> 16; | ||
167 | |||
168 | /* So, we have avail_len bytes of data, and we want to look | ||
169 | * through it for a match at some point. It's OK if it's not at | ||
170 | * the start of the available input data. If we're approaching | ||
171 | * the end and can't get a match, then we just block and get more | ||
172 | * later. */ | ||
173 | |||
174 | /* FIXME: Perhaps we should be working in signed chars for the | ||
175 | * rolling sum? */ | ||
176 | |||
177 | if (job->stream->eof_in) | ||
178 | end_pos = avail_len - 1; | ||
179 | else | ||
180 | end_pos = avail_len - job->block_len; | ||
181 | |||
182 | for (search_pos = 0; search_pos <= end_pos; search_pos++) { | ||
183 | size_t this_len = job->block_len; | ||
184 | |||
185 | if (search_pos + this_len > avail_len) { | ||
186 | this_len = avail_len - search_pos; | ||
187 | rs_trace("block reduced to %d", this_len); | ||
188 | } else if (job->have_weak_sig) { | ||
189 | unsigned char a = inptr[search_pos + this_len - 1]; | ||
190 | /* roll in the newly added byte, if any */ | ||
191 | s1 += a + RS_CHAR_OFFSET; | ||
192 | s2 += s1; | ||
193 | |||
194 | job->weak_sig = (s1 & 0xffff) | (s2 << 16); | ||
195 | } | ||
196 | |||
197 | if (!job->have_weak_sig) { | ||
198 | rs_trace("calculate weak sum from scratch"); | ||
199 | job->weak_sig = rs_calc_weak_sum(inptr + search_pos, this_len); | ||
200 | s1 = job->weak_sig & 0xFFFF; | ||
201 | s2 = job->weak_sig >> 16; | ||
202 | job->have_weak_sig = 1; | ||
203 | } | ||
204 | |||
205 | if (rs_roll_paranoia) { | ||
206 | rs_weak_sum_t verify = rs_calc_weak_sum(inptr + search_pos, this_len); | ||
207 | if (verify != job->weak_sig) { | ||
208 | rs_fatal("mismatch between rolled sum %#x and check %#x", | ||
209 | job->weak_sig, verify); | ||
210 | } | ||
211 | } | ||
212 | |||
213 | if (rs_search_for_block(job->weak_sig, inptr + search_pos, this_len, | ||
214 | job->signature, &job->stats, &match_where)) { | ||
215 | /* So, we got a match. Cool. However, there may be | ||
216 | * leading unmatched data that we need to flush. Thus we | ||
217 | * set our statefn to be rs_delta_s_deferred_copy so that | ||
218 | * we can write out the command later. */ | ||
219 | |||
220 | rs_trace("matched %.0f bytes at %.0f!", | ||
221 | (double) this_len, (double) match_where); | ||
222 | job->basis_pos = match_where; | ||
223 | job->basis_len = this_len; | ||
224 | job->statefn = rs_delta_s_deferred_copy; | ||
225 | job->have_weak_sig = 0; | ||
226 | break; | ||
227 | } else { | ||
228 | /* advance by one; roll out the byte we just moved over. */ | ||
229 | unsigned char a = inptr[search_pos]; | ||
230 | unsigned char shift = a + RS_CHAR_OFFSET; | ||
231 | |||
232 | s1 -= shift; | ||
233 | s2 -= this_len * shift; | ||
234 | job->weak_sig = (s1 & 0xffff) | (s2 << 16); | ||
235 | } | ||
236 | } | ||
237 | |||
238 | if (search_pos > 0) { | ||
239 | /* We may or may not have found a block, but we know we found | ||
240 | * some literal data at the start of the buffer. Therefore, | ||
241 | * we have to flush that out before we can continue on and | ||
242 | * emit the copy command or keep searching. */ | ||
243 | |||
244 | /* FIXME: At the moment, if you call with very short buffers, | ||
245 | * then you will get a series of very short LITERAL commands. | ||
246 | * Perhaps this is what you deserve, or perhaps we should try | ||
247 | * to get more readahead and avoid that. */ | ||
248 | |||
249 | /* There's some literal data at the start of this window which | ||
250 | * we know is not in any block. */ | ||
251 | rs_trace("got %d bytes of literal data", search_pos); | ||
252 | rs_emit_literal_cmd(job, search_pos); | ||
253 | rs_tube_copy(job, search_pos); | ||
254 | } | ||
255 | |||
256 | return RS_RUNNING; | ||
257 | } | ||
258 | |||
259 | |||
260 | |||
261 | static rs_result rs_delta_s_deferred_copy(rs_job_t *job) | ||
262 | { | ||
263 | if (!job->basis_len) { | ||
264 | rs_log(RS_LOG_ERR, "somehow got zero basis_len"); | ||
265 | return RS_INTERNAL_ERROR; | ||
266 | } | ||
267 | |||
268 | rs_emit_copy_cmd(job, job->basis_pos, job->basis_len); | ||
269 | rs_scoop_advance(job, job->basis_len); | ||
270 | |||
271 | job->statefn = rs_delta_s_scan; | ||
272 | |||
273 | return RS_RUNNING; | ||
274 | } | ||
275 | |||
276 | |||
277 | /** | ||
278 | * \brief State function that does a slack delta containing only | ||
279 | * literal data to recreate the input. | ||
280 | */ | ||
281 | static rs_result rs_delta_s_slack(rs_job_t *job) | ||
282 | { | ||
283 | rs_buffers_t * const stream = job->stream; | ||
284 | size_t avail = stream->avail_in; | ||
285 | |||
286 | if (avail) { | ||
287 | rs_trace("emit slack delta for %.0f available bytes", (double) avail); | ||
288 | rs_emit_literal_cmd(job, avail); | ||
289 | rs_tube_copy(job, avail); | ||
290 | return RS_RUNNING; | ||
291 | } else { | ||
292 | if (rs_job_input_is_ending(job)) { | ||
293 | job->statefn = rs_delta_s_end; | ||
294 | return RS_RUNNING; | ||
295 | } else { | ||
296 | return RS_BLOCKED; | ||
297 | } | ||
298 | } | ||
299 | } | ||
300 | |||
301 | |||
302 | /** | ||
303 | * State function for writing out the header of the encoding job. | ||
304 | */ | ||
305 | static rs_result rs_delta_s_header(rs_job_t *job) | ||
306 | { | ||
307 | rs_emit_delta_header(job); | ||
308 | |||
309 | if (job->block_len) { | ||
310 | if (!job->signature) { | ||
311 | rs_error("no signature is loaded into the job"); | ||
312 | return RS_PARAM_ERROR; | ||
313 | } | ||
314 | job->statefn = rs_delta_s_scan; | ||
315 | } else { | ||
316 | rs_trace("block length is zero for this delta; " | ||
317 | "therefore using slack deltas"); | ||
318 | job->statefn = rs_delta_s_slack; | ||
319 | } | ||
320 | |||
321 | return RS_RUNNING; | ||
322 | } | ||
323 | |||
324 | |||
325 | /** | ||
326 | * Prepare to compute a streaming delta. | ||
327 | */ | ||
328 | rs_job_t *rs_delta_begin(rs_signature_t *sig) | ||
329 | { | ||
330 | rs_job_t *job; | ||
331 | |||
332 | job = rs_job_new("delta", rs_delta_s_header); | ||
333 | job->signature = sig; | ||
334 | |||
335 | if ((job->block_len = sig->block_len) < 0) { | ||
336 | rs_log(RS_LOG_ERR, "unreasonable block_len %d in signature", | ||
337 | job->block_len); | ||
338 | return NULL; | ||
339 | } | ||
340 | |||
341 | job->strong_sum_len = sig->strong_sum_len; | ||
342 | if (job->strong_sum_len < 0 || job->strong_sum_len > RS_MD4_LENGTH) { | ||
343 | rs_log(RS_LOG_ERR, "unreasonable strong_sum_len %d in signature", | ||
344 | job->strong_sum_len); | ||
345 | return NULL; | ||
346 | } | ||
347 | |||
348 | return job; | ||
349 | } | ||
350 | |||
351 | |||
diff --git a/rsync/emit.c b/rsync/emit.c new file mode 100644 index 0000000..bdfc6d1 --- a/dev/null +++ b/rsync/emit.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- dynamic caching and delta update in HTTP | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | |||
24 | /* | ||
25 | * [almost sobbing] They don't sleep | ||
26 | * anymore on the beach. They don't | ||
27 | * sleep on the beach anymore. | ||
28 | */ | ||
29 | |||
30 | /* | ||
31 | * TODO: Pluggable encoding formats: | ||
32 | * | ||
33 | * - gdiff-style | ||
34 | * - rsync 24 | ||
35 | * - ed (text) | ||
36 | * - Delta HTTP | ||
37 | */ | ||
38 | |||
39 | |||
40 | #include <config_rsync.h> | ||
41 | |||
42 | #include <assert.h> | ||
43 | #include <stdlib.h> | ||
44 | #include <stdio.h> | ||
45 | |||
46 | #include "rsync.h" | ||
47 | #include "command.h" | ||
48 | #include "protocol.h" | ||
49 | #include "trace.h" | ||
50 | #include "emit.h" | ||
51 | #include "prototab.h" | ||
52 | #include "netint.h" | ||
53 | #include "sumset.h" | ||
54 | #include "job.h" | ||
55 | |||
56 | |||
57 | /* | ||
58 | * Write the magic for the start of a delta. | ||
59 | */ | ||
60 | void | ||
61 | rs_emit_delta_header(rs_job_t *job) | ||
62 | { | ||
63 | rs_trace("emit DELTA magic"); | ||
64 | rs_squirt_n4(job, RS_DELTA_MAGIC); | ||
65 | } | ||
66 | |||
67 | |||
68 | |||
69 | /* Write a LITERAL command. */ | ||
70 | void | ||
71 | rs_emit_literal_cmd(rs_job_t *job, int len) | ||
72 | { | ||
73 | int cmd; | ||
74 | int param_len; | ||
75 | |||
76 | switch (param_len = rs_int_len(len)) { | ||
77 | case 1: | ||
78 | cmd = RS_OP_LITERAL_N1; | ||
79 | break; | ||
80 | case 2: | ||
81 | cmd = RS_OP_LITERAL_N2; | ||
82 | break; | ||
83 | case 4: | ||
84 | cmd = RS_OP_LITERAL_N4; | ||
85 | break; | ||
86 | default: | ||
87 | rs_fatal("What?"); | ||
88 | } | ||
89 | |||
90 | rs_trace("emit LITERAL_N%d(len=%d), cmd_byte=%#x", param_len, len, cmd); | ||
91 | rs_squirt_byte(job, cmd); | ||
92 | rs_squirt_netint(job, len, param_len); | ||
93 | |||
94 | job->stats.lit_cmds++; | ||
95 | job->stats.lit_bytes += len; | ||
96 | job->stats.lit_cmdbytes += 1 + param_len; | ||
97 | } | ||
98 | |||
99 | |||
100 | /** Write a COPY command. */ | ||
101 | void | ||
102 | rs_emit_copy_cmd(rs_job_t *job, rs_long_t where, rs_long_t len) | ||
103 | { | ||
104 | int cmd; | ||
105 | rs_stats_t *stats = &job->stats; | ||
106 | |||
107 | cmd = RS_OP_COPY_N4_N4; | ||
108 | |||
109 | rs_trace("emit COPY_N4_N4(where=%.0f, len=%.0f), cmd_byte=%#x", | ||
110 | (double) where, (double) len, cmd); | ||
111 | rs_squirt_byte(job, cmd); | ||
112 | rs_squirt_netint(job, where, 4); | ||
113 | rs_squirt_netint(job, len, 4); | ||
114 | |||
115 | stats->copy_cmds++; | ||
116 | stats->copy_bytes += len; | ||
117 | stats->copy_cmdbytes += 1 + 4 + 4; | ||
118 | |||
119 | /* TODO: All the stats */ | ||
120 | } | ||
121 | |||
122 | |||
123 | /** Write an END command. */ | ||
124 | void | ||
125 | rs_emit_end_cmd(rs_job_t *job) | ||
126 | { | ||
127 | int cmd = RS_OP_END; | ||
128 | |||
129 | rs_trace("emit END, cmd_byte=%#x", cmd); | ||
130 | rs_squirt_byte(job, cmd); | ||
131 | } | ||
diff --git a/rsync/emit.h b/rsync/emit.h new file mode 100644 index 0000000..96bff89 --- a/dev/null +++ b/rsync/emit.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- dynamic caching and delta update in HTTP | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Lesser General Public License as published by | ||
10 | * the Free Software Foundation; either version 2.1 of the License, or | ||
11 | * (at your option) 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 Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | |||
24 | /* | ||
25 | * emit.h -- How to emit commands to the client | ||
26 | */ | ||
27 | |||
28 | |||
29 | void rs_emit_delta_header(rs_job_t *); | ||
30 | void rs_emit_literal_cmd(rs_job_t *, int len); | ||
31 | void rs_emit_end_cmd(rs_job_t *); | ||
32 | void rs_emit_copy_cmd(rs_job_t *job, rs_long_t where, rs_long_t len); | ||
diff --git a/rsync/fileutil.c b/rsync/fileutil.c new file mode 100644 index 0000000..75a6bb4 --- a/dev/null +++ b/rsync/fileutil.c | |||
@@ -0,0 +1,70 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * Copyright (C) 1999 by Andrew Tridgell <tridge@samba.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU Lesser General Public License as published by | ||
11 | * the Free Software Foundation; either version 2.1 of the License, or | ||
12 | * (at your option) any 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 Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <config_rsync.h> | ||
25 | |||
26 | #include <assert.h> | ||
27 | #include <stdlib.h> | ||
28 | #include <unistd.h> | ||
29 | #include <stdio.h> | ||
30 | #include <fcntl.h> | ||
31 | #include <sys/file.h> | ||
32 | #include <string.h> | ||
33 | #include <errno.h> | ||
34 | |||
35 | #include "rsync.h" | ||
36 | #include "fileutil.h" | ||
37 | #include "trace.h" | ||
38 | |||
39 | |||
40 | |||
41 | /** | ||
42 | * \brief Open a file, with special handling for `-' or unspecified | ||
43 | * parameters on input and output. | ||
44 | * | ||
45 | * \param fopen-style mode string. | ||
46 | */ | ||
47 | FILE * | ||
48 | rs_file_open(char const *filename, char const *mode) | ||
49 | { | ||
50 | FILE *f; | ||
51 | int is_write; | ||
52 | |||
53 | is_write = mode[0] == 'w'; | ||
54 | |||
55 | if (!filename || !strcmp("-", filename)) { | ||
56 | if (is_write) | ||
57 | return stdout; | ||
58 | else | ||
59 | return stdin; | ||
60 | } | ||
61 | |||
62 | if (!(f = fopen(filename, mode))) { | ||
63 | rs_error("Error opening \"%s\" for %s: %s", filename, | ||
64 | is_write ? "write" : "read", | ||
65 | strerror(errno)); | ||
66 | exit(RS_IO_ERROR); | ||
67 | } | ||
68 | |||
69 | return f; | ||
70 | } | ||
diff --git a/rsync/fileutil.h b/rsync/fileutil.h new file mode 100644 index 0000000..b46f7c1 --- a/dev/null +++ b/rsync/fileutil.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- * | ||
2 | * | ||
3 | * librsync -- library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Lesser General Public License as published by | ||
10 | * the Free Software Foundation; either version 2.1 of the License, or | ||
11 | * (at your option) 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 Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | FILE * rs_file_open(char const *filename, char const * mode); | ||
diff --git a/rsync/hex.c b/rsync/hex.c new file mode 100644 index 0000000..e10b686 --- a/dev/null +++ b/rsync/hex.c | |||
@@ -0,0 +1,46 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * rproxy -- dynamic caching and delta update in HTTP | ||
3 | * $Id$ | ||
4 | * | ||
5 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Lesser General Public License as published by | ||
9 | * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser 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 | |||
22 | #include <config_rsync.h> | ||
23 | |||
24 | #include <assert.h> | ||
25 | #include <sys/types.h> | ||
26 | #include <inttypes.h> | ||
27 | #include <stdlib.h> | ||
28 | #include <stdio.h> | ||
29 | |||
30 | #include "rsync.h" | ||
31 | |||
32 | |||
33 | void | ||
34 | rs_hexify(char *to_buf, void const *from, int from_len) | ||
35 | { | ||
36 | static const char hex_chars[] = "0123456789abcdef"; | ||
37 | unsigned char const *from_buf = (unsigned char const *) from; | ||
38 | |||
39 | while (from_len-- > 0) { | ||
40 | *(to_buf++) = hex_chars[((*from_buf) >> 4) & 0xf]; | ||
41 | *(to_buf++) = hex_chars[(*from_buf) & 0xf]; | ||
42 | from_buf++; | ||
43 | } | ||
44 | |||
45 | *to_buf = 0; | ||
46 | } | ||
diff --git a/rsync/job.c b/rsync/job.c new file mode 100644 index 0000000..680982d --- a/dev/null +++ b/rsync/job.c | |||
@@ -0,0 +1,251 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | |||
24 | /* | ||
25 | | The hard, lifeless I covered up the | ||
26 | | warm, pulsing It; protecting and | ||
27 | | sheltering. | ||
28 | */ | ||
29 | |||
30 | /* | ||
31 | * job.c -- Generic state-machine interface. The point of this is | ||
32 | * that we need to be able to suspend and resume processing at any | ||
33 | * point at which the buffers may block. We could do that using | ||
34 | * setjmp or similar tricks, but this is probably simpler. | ||
35 | * | ||
36 | * TODO: We have a few functions to do with reading a netint, stashing | ||
37 | * it somewhere, then moving into a different state. Is it worth | ||
38 | * writing generic functions fo r that, or would it be too confusing? | ||
39 | */ | ||
40 | |||
41 | |||
42 | #include <config_rsync.h> | ||
43 | |||
44 | #include <stdlib.h> | ||
45 | #include <assert.h> | ||
46 | #include <stdio.h> | ||
47 | |||
48 | #include "rsync.h" | ||
49 | #include "stream.h" | ||
50 | #include "util.h" | ||
51 | #include "sumset.h" | ||
52 | #include "job.h" | ||
53 | #include "trace.h" | ||
54 | |||
55 | |||
56 | static const int rs_job_tag = 20010225; | ||
57 | |||
58 | static rs_result rs_job_work(rs_job_t *job, rs_buffers_t *buffers); | ||
59 | |||
60 | |||
61 | rs_job_t * rs_job_new(char const *job_name, rs_result (*statefn)(rs_job_t *)) | ||
62 | { | ||
63 | rs_job_t *job; | ||
64 | |||
65 | job = rs_alloc_struct(rs_job_t); | ||
66 | |||
67 | job->job_name = job_name; | ||
68 | job->dogtag = rs_job_tag; | ||
69 | job->statefn = statefn; | ||
70 | |||
71 | job->stats.op = job_name; | ||
72 | |||
73 | rs_trace("start %s job", job_name); | ||
74 | |||
75 | return job; | ||
76 | } | ||
77 | |||
78 | |||
79 | void rs_job_check(rs_job_t *job) | ||
80 | { | ||
81 | assert(job->dogtag == rs_job_tag); | ||
82 | } | ||
83 | |||
84 | |||
85 | rs_result rs_job_free(rs_job_t *job) | ||
86 | { | ||
87 | rs_bzero(job, sizeof *job); | ||
88 | free(job); | ||
89 | |||
90 | return RS_DONE; | ||
91 | } | ||
92 | |||
93 | |||
94 | |||
95 | static rs_result rs_job_s_complete(rs_job_t *job) | ||
96 | { | ||
97 | rs_fatal("should not be reached"); | ||
98 | return RS_INTERNAL_ERROR; | ||
99 | } | ||
100 | |||
101 | |||
102 | static rs_result rs_job_complete(rs_job_t *job, rs_result result) | ||
103 | { | ||
104 | rs_job_check(job); | ||
105 | |||
106 | job->statefn = rs_job_s_complete; | ||
107 | job->final_result = result; | ||
108 | |||
109 | if (result != RS_DONE) { | ||
110 | rs_error("%s job failed: %s", job->job_name, rs_strerror(result)); | ||
111 | } else { | ||
112 | rs_trace("%s job complete", job->job_name); | ||
113 | } | ||
114 | |||
115 | if (result == RS_DONE && !rs_tube_is_idle(job)) | ||
116 | /* Processing is finished, but there is still some data | ||
117 | * waiting to get into the output buffer. */ | ||
118 | return RS_BLOCKED; | ||
119 | else | ||
120 | return result; | ||
121 | } | ||
122 | |||
123 | |||
124 | /** | ||
125 | * \brief Run a ::rs_job_t state machine until it blocks | ||
126 | * (::RS_BLOCKED), returns an error, or completes (::RS_COMPLETE). | ||
127 | * | ||
128 | * \return The ::rs_result that caused iteration to stop. | ||
129 | * | ||
130 | * \param ending True if there is no more data after what's in the | ||
131 | * input buffer. The final block checksum will run across whatever's | ||
132 | * in there, without trying to accumulate anything else. | ||
133 | */ | ||
134 | rs_result rs_job_iter(rs_job_t *job, rs_buffers_t *buffers) | ||
135 | { | ||
136 | rs_result result; | ||
137 | rs_long_t orig_in, orig_out; | ||
138 | |||
139 | orig_in = buffers->avail_in; | ||
140 | orig_out = buffers->avail_out; | ||
141 | |||
142 | result = rs_job_work(job, buffers); | ||
143 | |||
144 | if (result == RS_BLOCKED || result == RS_DONE) | ||
145 | if ((orig_in == buffers->avail_in) && (orig_out == buffers->avail_out) | ||
146 | && orig_in && orig_out) { | ||
147 | rs_log(RS_LOG_ERR, "internal error: job made no progress " | ||
148 | "[orig_in=%.0f, orig_out=%.0f, final_in=%.0f, final_out=%.0f]", | ||
149 | (double) orig_in, (double) orig_out, (double) buffers->avail_in, | ||
150 | (double) buffers->avail_out); | ||
151 | return RS_INTERNAL_ERROR; | ||
152 | } | ||
153 | |||
154 | return result; | ||
155 | } | ||
156 | |||
157 | |||
158 | static rs_result | ||
159 | rs_job_work(rs_job_t *job, rs_buffers_t *buffers) | ||
160 | { | ||
161 | rs_result result; | ||
162 | |||
163 | rs_job_check(job); | ||
164 | |||
165 | if (!buffers) { | ||
166 | rs_error("NULL buffer passed to rs_job_iter"); | ||
167 | return RS_PARAM_ERROR; | ||
168 | } | ||
169 | job->stream = buffers; | ||
170 | |||
171 | while (1) { | ||
172 | result = rs_tube_catchup(job); | ||
173 | if (result == RS_BLOCKED) | ||
174 | return result; | ||
175 | else if (result != RS_DONE) | ||
176 | return rs_job_complete(job, result); | ||
177 | |||
178 | if (job->statefn == rs_job_s_complete) { | ||
179 | if (rs_tube_is_idle(job)) | ||
180 | return RS_DONE; | ||
181 | else | ||
182 | return RS_BLOCKED; | ||
183 | } else { | ||
184 | result = job->statefn(job); | ||
185 | if (result == RS_RUNNING) | ||
186 | continue; | ||
187 | else if (result == RS_BLOCKED) | ||
188 | return result; | ||
189 | else | ||
190 | return rs_job_complete(job, result); | ||
191 | } | ||
192 | } | ||
193 | |||
194 | /* TODO: Before returning, check that we actually made some | ||
195 | * progress. If not, and we're not returning an error, this is a | ||
196 | * bug. */ | ||
197 | } | ||
198 | |||
199 | |||
200 | /** | ||
201 | * Return pointer to statistics accumulated about this job. | ||
202 | */ | ||
203 | const rs_stats_t * | ||
204 | rs_job_statistics(rs_job_t *job) | ||
205 | { | ||
206 | return &job->stats; | ||
207 | } | ||
208 | |||
209 | |||
210 | int | ||
211 | rs_job_input_is_ending(rs_job_t *job) | ||
212 | { | ||
213 | return job->stream->eof_in; | ||
214 | } | ||
215 | |||
216 | |||
217 | |||
218 | /** | ||
219 | * Actively process a job, by making callbacks to fill and empty the | ||
220 | * buffers until the job is done. | ||
221 | */ | ||
222 | rs_result | ||
223 | rs_job_drive(rs_job_t *job, rs_buffers_t *buf, | ||
224 | rs_driven_cb in_cb, void *in_opaque, | ||
225 | rs_driven_cb out_cb, void *out_opaque) | ||
226 | { | ||
227 | rs_result result, iores; | ||
228 | |||
229 | rs_bzero(buf, sizeof *buf); | ||
230 | |||
231 | do { | ||
232 | if (!buf->eof_in && in_cb) { | ||
233 | iores = in_cb(job, buf, in_opaque); | ||
234 | if (iores != RS_DONE) | ||
235 | return iores; | ||
236 | } | ||
237 | |||
238 | result = rs_job_iter(job, buf); | ||
239 | if (result != RS_DONE && result != RS_BLOCKED) | ||
240 | return result; | ||
241 | |||
242 | if (out_cb) { | ||
243 | iores = (out_cb)(job, buf, out_opaque); | ||
244 | if (iores != RS_DONE) | ||
245 | return iores; | ||
246 | } | ||
247 | } while (result != RS_DONE); | ||
248 | |||
249 | return result; | ||
250 | } | ||
251 | |||
diff --git a/rsync/job.h b/rsync/job.h new file mode 100644 index 0000000..33c0cd7 --- a/dev/null +++ b/rsync/job.h | |||
@@ -0,0 +1,99 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | |||
24 | struct rs_job { | ||
25 | int dogtag; | ||
26 | |||
27 | /** Human-readable job operation name. */ | ||
28 | const char *job_name; | ||
29 | |||
30 | rs_buffers_t *stream; | ||
31 | |||
32 | /** Callback for each processing step. */ | ||
33 | rs_result (*statefn)(rs_job_t *); | ||
34 | |||
35 | /** Final result of processing job. Used by rs_job_s_failed(). */ | ||
36 | rs_result final_result; | ||
37 | |||
38 | /* XXX: These next two are redundant with their equivalents in the | ||
39 | * signature field. Perhaps we should get rid of them, but | ||
40 | * they're also used in the mksum operation. */ | ||
41 | int block_len; | ||
42 | int strong_sum_len; | ||
43 | |||
44 | /** Signature that's either being read in, or used for | ||
45 | * generating a delta. */ | ||
46 | rs_signature_t *signature; | ||
47 | |||
48 | /** Command byte currently being processed, if any. */ | ||
49 | unsigned char op; | ||
50 | |||
51 | /** If in the middle of reading a signature (rs_loadsig_s_weak()), | ||
52 | * or generating a delta, this contains the weak signature. */ | ||
53 | rs_weak_sum_t weak_sig; | ||
54 | |||
55 | /** If generating a delta, this is true if we have a valid weak signature and | ||
56 | * can roll it forward. */ | ||
57 | int have_weak_sig; | ||
58 | |||
59 | /** Lengths of expected parameters. */ | ||
60 | rs_long_t param1, param2; | ||
61 | |||
62 | struct rs_prototab_ent const *cmd; | ||
63 | rs_mdfour_t output_md4; | ||
64 | |||
65 | /** Encoding statistics. */ | ||
66 | rs_stats_t stats; | ||
67 | |||
68 | /** Buffer of data left over in the scoop. Allocation is | ||
69 | * scoop_buf..scoop_alloc, and scoop_next[0..scoop_avail] | ||
70 | * contains valid data. */ | ||
71 | char *scoop_buf; | ||
72 | char *scoop_next; | ||
73 | size_t scoop_alloc; | ||
74 | size_t scoop_avail; | ||
75 | |||
76 | /** If USED is >0, then buf contains that much write data to | ||
77 | * be sent out. */ | ||
78 | char write_buf[16]; | ||
79 | int write_len; | ||
80 | |||
81 | /** If \p copy_len is >0, then that much data should be copied | ||
82 | * through from the input. */ | ||
83 | rs_long_t copy_len; | ||
84 | |||
85 | /** Copy from the basis position. */ | ||
86 | rs_long_t basis_pos, basis_len; | ||
87 | |||
88 | /** Callback used to copy data from the basis into the output. */ | ||
89 | rs_copy_cb *copy_cb; | ||
90 | void *copy_arg; | ||
91 | }; | ||
92 | |||
93 | |||
94 | rs_job_t * rs_job_new(const char *, rs_result (*statefn)(rs_job_t *)); | ||
95 | |||
96 | void rs_job_check(rs_job_t *job); | ||
97 | const rs_stats_t *rs_job_statistics(rs_job_t *); | ||
98 | |||
99 | int rs_job_input_is_ending(rs_job_t *job); | ||
diff --git a/rsync/mdfour.c b/rsync/mdfour.c new file mode 100644 index 0000000..4c3568d --- a/dev/null +++ b/rsync/mdfour.c | |||
@@ -0,0 +1,326 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * Copyright (C) 1997-1999 by Andrew Tridgell | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU Lesser General Public License as published by | ||
11 | * the Free Software Foundation; either version 2.1 of the License, or | ||
12 | * (at your option) any 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 Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | /* MD4 message digest algorithm. | ||
25 | * | ||
26 | * TODO: Perhaps use the MD4 routine from OpenSSL if it's installed. | ||
27 | * It's probably not worth the trouble. | ||
28 | * | ||
29 | * This was originally written by Andrew Tridgell for use in Samba. */ | ||
30 | |||
31 | #include <config_rsync.h> | ||
32 | |||
33 | #include <stdlib.h> | ||
34 | #include <string.h> | ||
35 | #include <stdio.h> | ||
36 | |||
37 | #include "rsync.h" | ||
38 | #include "trace.h" | ||
39 | #include "types.h" | ||
40 | |||
41 | |||
42 | static void (*rs_mdfour_block)(rs_mdfour_t *md, void const *p) = NULL; | ||
43 | |||
44 | |||
45 | #define F(X,Y,Z) (((X)&(Y)) | ((~(X))&(Z))) | ||
46 | #define G(X,Y,Z) (((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z))) | ||
47 | #define H(X,Y,Z) ((X)^(Y)^(Z)) | ||
48 | #define lshift(x,s) (((x)<<(s)) | ((x)>>(32-(s)))) | ||
49 | |||
50 | #define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s) | ||
51 | #define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + 0x5A827999,s) | ||
52 | #define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + 0x6ED9EBA1,s) | ||
53 | |||
54 | /** | ||
55 | * Update an MD4 accumulator from a 64-byte chunk. | ||
56 | * | ||
57 | * This cannot be used for the last chunk of the file, which must be | ||
58 | * padded and contain the file length. rs_mdfour_tail() is used for | ||
59 | * that. | ||
60 | * | ||
61 | * \todo Recode to be fast, and to use system integer types. Perhaps | ||
62 | * if we can find an mdfour implementation already on the system | ||
63 | * (e.g. in OpenSSL) then we should use it instead of our own? | ||
64 | * | ||
65 | * \param X A series of integer, read little-endian from the file. | ||
66 | */ | ||
67 | static void | ||
68 | rs_mdfour64(rs_mdfour_t * m, const void *p) | ||
69 | { | ||
70 | uint32_t AA, BB, CC, DD; | ||
71 | uint32_t A, B, C, D; | ||
72 | const uint32_t *X = (const uint32_t *) p; | ||
73 | |||
74 | A = m->A; | ||
75 | B = m->B; | ||
76 | C = m->C; | ||
77 | D = m->D; | ||
78 | AA = A; | ||
79 | BB = B; | ||
80 | CC = C; | ||
81 | DD = D; | ||
82 | |||
83 | ROUND1(A, B, C, D, 0, 3); | ||
84 | ROUND1(D, A, B, C, 1, 7); | ||
85 | ROUND1(C, D, A, B, 2, 11); | ||
86 | ROUND1(B, C, D, A, 3, 19); | ||
87 | ROUND1(A, B, C, D, 4, 3); | ||
88 | ROUND1(D, A, B, C, 5, 7); | ||
89 | ROUND1(C, D, A, B, 6, 11); | ||
90 | ROUND1(B, C, D, A, 7, 19); | ||
91 | ROUND1(A, B, C, D, 8, 3); | ||
92 | ROUND1(D, A, B, C, 9, 7); | ||
93 | ROUND1(C, D, A, B, 10, 11); | ||
94 | ROUND1(B, C, D, A, 11, 19); | ||
95 | ROUND1(A, B, C, D, 12, 3); | ||
96 | ROUND1(D, A, B, C, 13, 7); | ||
97 | ROUND1(C, D, A, B, 14, 11); | ||
98 | ROUND1(B, C, D, A, 15, 19); | ||
99 | |||
100 | ROUND2(A, B, C, D, 0, 3); | ||
101 | ROUND2(D, A, B, C, 4, 5); | ||
102 | ROUND2(C, D, A, B, 8, 9); | ||
103 | ROUND2(B, C, D, A, 12, 13); | ||
104 | ROUND2(A, B, C, D, 1, 3); | ||
105 | ROUND2(D, A, B, C, 5, 5); | ||
106 | ROUND2(C, D, A, B, 9, 9); | ||
107 | ROUND2(B, C, D, A, 13, 13); | ||
108 | ROUND2(A, B, C, D, 2, 3); | ||
109 | ROUND2(D, A, B, C, 6, 5); | ||
110 | ROUND2(C, D, A, B, 10, 9); | ||
111 | ROUND2(B, C, D, A, 14, 13); | ||
112 | ROUND2(A, B, C, D, 3, 3); | ||
113 | ROUND2(D, A, B, C, 7, 5); | ||
114 | ROUND2(C, D, A, B, 11, 9); | ||
115 | ROUND2(B, C, D, A, 15, 13); | ||
116 | |||
117 | ROUND3(A, B, C, D, 0, 3); | ||
118 | ROUND3(D, A, B, C, 8, 9); | ||
119 | ROUND3(C, D, A, B, 4, 11); | ||
120 | ROUND3(B, C, D, A, 12, 15); | ||
121 | ROUND3(A, B, C, D, 2, 3); | ||
122 | ROUND3(D, A, B, C, 10, 9); | ||
123 | ROUND3(C, D, A, B, 6, 11); | ||
124 | ROUND3(B, C, D, A, 14, 15); | ||
125 | ROUND3(A, B, C, D, 1, 3); | ||
126 | ROUND3(D, A, B, C, 9, 9); | ||
127 | ROUND3(C, D, A, B, 5, 11); | ||
128 | ROUND3(B, C, D, A, 13, 15); | ||
129 | ROUND3(A, B, C, D, 3, 3); | ||
130 | ROUND3(D, A, B, C, 11, 9); | ||
131 | ROUND3(C, D, A, B, 7, 11); | ||
132 | ROUND3(B, C, D, A, 15, 15); | ||
133 | |||
134 | A += AA; | ||
135 | B += BB; | ||
136 | C += CC; | ||
137 | D += DD; | ||
138 | |||
139 | m->A = A; | ||
140 | m->B = B; | ||
141 | m->C = C; | ||
142 | m->D = D; | ||
143 | } | ||
144 | |||
145 | |||
146 | /* These next two routines are necessary because MD4 is specified in | ||
147 | * terms of little-endian int32s, but we have a byte buffer. On | ||
148 | * little-endian platforms, I think we can just use the buffer pointer | ||
149 | * directly. | ||
150 | * | ||
151 | * There are some nice endianness routines in glib, including | ||
152 | * assembler variants. If we ever depended on glib, then it could be | ||
153 | * good to use them instead. */ | ||
154 | static void | ||
155 | copy64( /* @out@ */ uint32_t * M, unsigned char const *in) | ||
156 | { | ||
157 | int i; | ||
158 | |||
159 | for (i = 0; i < 16; i++) | ||
160 | M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) | | ||
161 | (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0); | ||
162 | } | ||
163 | |||
164 | static void | ||
165 | copy4( /* @out@ */ unsigned char *out, uint32_t const x) | ||
166 | { | ||
167 | out[0] = x & 0xFF; | ||
168 | out[1] = (x >> 8) & 0xFF; | ||
169 | out[2] = (x >> 16) & 0xFF; | ||
170 | out[3] = (x >> 24) & 0xFF; | ||
171 | } | ||
172 | |||
173 | |||
174 | |||
175 | /** | ||
176 | * Accumulate a block, making appropriate conversions for bigendian | ||
177 | * machines. | ||
178 | */ | ||
179 | static void | ||
180 | rs_mdfour_block_slow(rs_mdfour_t *md, void const *p) | ||
181 | { | ||
182 | uint32_t M[16]; | ||
183 | |||
184 | copy64(M, p); | ||
185 | rs_mdfour64(md, M); | ||
186 | } | ||
187 | |||
188 | |||
189 | static void | ||
190 | rs_mdfour_choose_packer(void) | ||
191 | { | ||
192 | static const char foo[] = { 0xde, 0xad, 0xbe, 0xef}; | ||
193 | const uint32_t *p = (const uint32_t *) foo; | ||
194 | |||
195 | if (sizeof(uint32_t) != 4) | ||
196 | rs_fatal("internal error: uint32_t is not really 32 bits!"); | ||
197 | if (sizeof(foo) != 4) | ||
198 | rs_fatal("internal error: something wierd about char arrays"); | ||
199 | |||
200 | if (*p == 0xdeadbeef) { | ||
201 | rs_trace("big-endian machine"); | ||
202 | rs_mdfour_block = rs_mdfour_block_slow; | ||
203 | } else if (*p == 0xefbeadde) { | ||
204 | rs_trace("little-endian machine"); | ||
205 | rs_mdfour_block = rs_mdfour64; | ||
206 | } else { | ||
207 | rs_fatal("can't determine endianness from %#x", *p); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | |||
212 | void | ||
213 | rs_mdfour_begin(rs_mdfour_t * md) | ||
214 | { | ||
215 | if (!rs_mdfour_block) | ||
216 | rs_mdfour_choose_packer(); | ||
217 | |||
218 | memset(md, 0, sizeof(*md)); | ||
219 | md->A = 0x67452301; | ||
220 | md->B = 0xefcdab89; | ||
221 | md->C = 0x98badcfe; | ||
222 | md->D = 0x10325476; | ||
223 | md->totalN = 0; | ||
224 | } | ||
225 | |||
226 | |||
227 | /** | ||
228 | * Handle special behaviour for processing the last block of a file | ||
229 | * when calculating its MD4 checksum. | ||
230 | * | ||
231 | * This must be called exactly once per file. | ||
232 | */ | ||
233 | static void | ||
234 | rs_mdfour_tail(rs_mdfour_t * m, unsigned char const *in, int n) | ||
235 | { | ||
236 | unsigned char buf[128]; | ||
237 | uint32_t b; | ||
238 | |||
239 | m->totalN += n; | ||
240 | |||
241 | b = m->totalN * 8; | ||
242 | |||
243 | memset(buf, 0, 128); | ||
244 | if (n) | ||
245 | memcpy(buf, in, n); | ||
246 | buf[n] = 0x80; | ||
247 | |||
248 | if (n <= 55) { | ||
249 | copy4(buf + 56, b); | ||
250 | rs_mdfour_block(m, buf); | ||
251 | } else { | ||
252 | copy4(buf + 120, b); | ||
253 | rs_mdfour_block(m, buf); | ||
254 | rs_mdfour_block(m, buf + 64); | ||
255 | } | ||
256 | } | ||
257 | |||
258 | |||
259 | /** | ||
260 | * Feed some data into the MD4 accumulator. | ||
261 | * | ||
262 | * \param n Number of bytes fed in. | ||
263 | */ | ||
264 | void | ||
265 | rs_mdfour_update(rs_mdfour_t * md, void const *in_void, size_t n) | ||
266 | { | ||
267 | unsigned char const *in = (unsigned char const *) in_void; | ||
268 | |||
269 | if (n == 0) | ||
270 | return; | ||
271 | |||
272 | if (md->tail_len) { | ||
273 | size_t tail_gap = 64 - md->tail_len; | ||
274 | |||
275 | /* If there's any leftover data in the tail buffer, then first | ||
276 | * we have to make it up to a whole block and process it. */ | ||
277 | if (tail_gap > n) | ||
278 | tail_gap = n; | ||
279 | memcpy(&md->tail[md->tail_len], in, tail_gap); | ||
280 | md->tail_len += tail_gap; | ||
281 | in += tail_gap; | ||
282 | n -= tail_gap; | ||
283 | |||
284 | if (md->tail_len != 64) | ||
285 | return; | ||
286 | |||
287 | rs_mdfour_block(md, md->tail); | ||
288 | md->tail_len = 0; | ||
289 | md->totalN += 64; | ||
290 | } | ||
291 | |||
292 | while (n >= 64) { | ||
293 | rs_mdfour_block(md, in); | ||
294 | in += 64; | ||
295 | n -= 64; | ||
296 | md->totalN += 64; | ||
297 | } | ||
298 | |||
299 | if (n) { | ||
300 | memcpy(md->tail, in, n); | ||
301 | md->tail_len = n; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | |||
306 | void | ||
307 | rs_mdfour_result(rs_mdfour_t * md, unsigned char *out) | ||
308 | { | ||
309 | rs_mdfour_tail(md, md->tail, md->tail_len); | ||
310 | |||
311 | copy4(out, md->A); | ||
312 | copy4(out + 4, md->B); | ||
313 | copy4(out + 8, md->C); | ||
314 | copy4(out + 12, md->D); | ||
315 | } | ||
316 | |||
317 | |||
318 | void | ||
319 | rs_mdfour(unsigned char *out, void const *in, size_t n) | ||
320 | { | ||
321 | rs_mdfour_t md; | ||
322 | |||
323 | rs_mdfour_begin(&md); | ||
324 | rs_mdfour_update(&md, in, n); | ||
325 | rs_mdfour_result(&md, out); | ||
326 | } | ||
diff --git a/rsync/mksum.c b/rsync/mksum.c new file mode 100644 index 0000000..d55bcfb --- a/dev/null +++ b/rsync/mksum.c | |||
@@ -0,0 +1,155 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * Copyright (C) 1999 by Andrew Tridgell <tridge@samba.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU Lesser General Public License as published by | ||
11 | * the Free Software Foundation; either version 2.1 of the License, or | ||
12 | * (at your option) any 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 Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | |||
25 | /* | ||
26 | * mksum.c -- Generate file signatures. | ||
27 | * | ||
28 | * Generating checksums is pretty easy, since we can always just | ||
29 | * process whatever data is available. When a whole block has | ||
30 | * arrived, or we've reached the end of the file, we write the | ||
31 | * checksum out. | ||
32 | */ | ||
33 | |||
34 | /* TODO: Perhaps force blocks to be a multiple of 64 bytes, so that we | ||
35 | * can be sure checksum generation will be more efficient. I guess it | ||
36 | * will be OK at the moment, though, because tails are only used if | ||
37 | * necessary. */ | ||
38 | |||
39 | #include <config_rsync.h> | ||
40 | |||
41 | #include <stdlib.h> | ||
42 | #include <stdio.h> | ||
43 | #include <assert.h> | ||
44 | |||
45 | #include "rsync.h" | ||
46 | #include "stream.h" | ||
47 | #include "util.h" | ||
48 | #include "sumset.h" | ||
49 | #include "job.h" | ||
50 | #include "protocol.h" | ||
51 | #include "netint.h" | ||
52 | #include "trace.h" | ||
53 | #include "checksum.h" | ||
54 | |||
55 | |||
56 | /* Possible state functions for signature generation. */ | ||
57 | static rs_result rs_sig_s_header(rs_job_t *); | ||
58 | static rs_result rs_sig_s_generate(rs_job_t *); | ||
59 | |||
60 | |||
61 | |||
62 | /** | ||
63 | * State of trying to send the signature header. | ||
64 | */ | ||
65 | static rs_result rs_sig_s_header(rs_job_t *job) | ||
66 | { | ||
67 | rs_squirt_n4(job, RS_SIG_MAGIC); | ||
68 | rs_squirt_n4(job, job->block_len); | ||
69 | rs_squirt_n4(job, job->strong_sum_len); | ||
70 | rs_trace("sent header (magic %#x, block len = %d, strong sum len = %d)", | ||
71 | RS_SIG_MAGIC, (int) job->block_len, (int) job->strong_sum_len); | ||
72 | job->stats.block_len = job->block_len; | ||
73 | |||
74 | job->statefn = rs_sig_s_generate; | ||
75 | return RS_RUNNING; | ||
76 | } | ||
77 | |||
78 | |||
79 | /** | ||
80 | * Generate the checksums for a block and write it out. Called when | ||
81 | * we already know we have enough data in memory at \p block. | ||
82 | */ | ||
83 | static rs_result | ||
84 | rs_sig_do_block(rs_job_t *job, const void *block, size_t len) | ||
85 | { | ||
86 | unsigned int weak_sum; | ||
87 | rs_strong_sum_t strong_sum; | ||
88 | |||
89 | weak_sum = rs_calc_weak_sum(block, len); | ||
90 | |||
91 | rs_calc_strong_sum(block, len, &strong_sum); | ||
92 | |||
93 | rs_squirt_n4(job, weak_sum); | ||
94 | rs_tube_write(job, strong_sum, job->strong_sum_len); | ||
95 | |||
96 | if (rs_trace_enabled()) { | ||
97 | char strong_sum_hex[RS_MD4_LENGTH * 2 + 1]; | ||
98 | rs_hexify(strong_sum_hex, strong_sum, job->strong_sum_len); | ||
99 | rs_trace("sent weak sum 0x%08x and strong sum %s", weak_sum, | ||
100 | strong_sum_hex); | ||
101 | } | ||
102 | |||
103 | job->stats.sig_blocks++; | ||
104 | |||
105 | return RS_RUNNING; | ||
106 | } | ||
107 | |||
108 | |||
109 | /* | ||
110 | * State of reading a block and trying to generate its sum. | ||
111 | */ | ||
112 | static rs_result | ||
113 | rs_sig_s_generate(rs_job_t *job) | ||
114 | { | ||
115 | rs_result result; | ||
116 | size_t len; | ||
117 | void *block; | ||
118 | |||
119 | /* must get a whole block, otherwise try again */ | ||
120 | len = job->block_len; | ||
121 | result = rs_scoop_read(job, len, &block); | ||
122 | |||
123 | /* unless we're near eof, in which case we'll accept | ||
124 | * whatever's in there */ | ||
125 | if ((result == RS_BLOCKED && rs_job_input_is_ending(job))) { | ||
126 | result = rs_scoop_read_rest(job, &len, &block); | ||
127 | } else if (result == RS_INPUT_ENDED) { | ||
128 | return RS_DONE; | ||
129 | } else if (result != RS_DONE) { | ||
130 | rs_trace("generate stopped: %s", rs_strerror(result)); | ||
131 | return result; | ||
132 | } | ||
133 | |||
134 | rs_trace("got %d byte block", len); | ||
135 | |||
136 | return rs_sig_do_block(job, block, len); | ||
137 | } | ||
138 | |||
139 | |||
140 | /** \brief Set up a new encoding job. | ||
141 | * | ||
142 | * \sa rs_sig_file() | ||
143 | */ | ||
144 | rs_job_t * rs_sig_begin(size_t new_block_len, size_t strong_sum_len) | ||
145 | { | ||
146 | rs_job_t *job; | ||
147 | |||
148 | job = rs_job_new("signature", rs_sig_s_header); | ||
149 | job->block_len = new_block_len; | ||
150 | |||
151 | assert(strong_sum_len > 0 && strong_sum_len <= RS_MD4_LENGTH); | ||
152 | job->strong_sum_len = strong_sum_len; | ||
153 | |||
154 | return job; | ||
155 | } | ||
diff --git a/rsync/msg.c b/rsync/msg.c new file mode 100644 index 0000000..aad2eb5 --- a/dev/null +++ b/rsync/msg.c | |||
@@ -0,0 +1,75 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | |||
24 | /* | ||
25 | | Welcome to Arco AM/PM Mini-Market. We | ||
26 | | would like to advise our customers | ||
27 | | that any individual who offers to | ||
28 | | pump gas, wash windows or solicit | ||
29 | | products is not employed by or | ||
30 | | associated with this facility. We | ||
31 | | discourage any contact with these | ||
32 | | individuals and ask that you report | ||
33 | | any problems to uniformed personal | ||
34 | | inside. Thankyou for shopping at | ||
35 | | Arco, and have a nice day. | ||
36 | */ | ||
37 | |||
38 | #include <config_rsync.h> | ||
39 | |||
40 | #include <stdlib.h> | ||
41 | #include <stdio.h> | ||
42 | |||
43 | #include "rsync.h" | ||
44 | |||
45 | |||
46 | /** \brief Translate from rs_result to human-readable messages. */ | ||
47 | char const *rs_strerror(rs_result r) | ||
48 | { | ||
49 | switch (r) { | ||
50 | case RS_DONE: | ||
51 | return "OK"; | ||
52 | case RS_RUNNING: | ||
53 | return "still running"; | ||
54 | case RS_BAD_MAGIC: | ||
55 | return "bad magic number at start of stream"; | ||
56 | case RS_BLOCKED: | ||
57 | return "blocked waiting for input or output buffers"; | ||
58 | case RS_INPUT_ENDED: | ||
59 | return "unexpected end of input"; | ||
60 | case RS_CORRUPT: | ||
61 | return "stream corrupt"; | ||
62 | case RS_UNIMPLEMENTED: | ||
63 | return "unimplemented case"; | ||
64 | case RS_MEM_ERROR: | ||
65 | return "out of memory"; | ||
66 | case RS_IO_ERROR: | ||
67 | return "IO error"; | ||
68 | case RS_SYNTAX_ERROR: | ||
69 | return "bad command line syntax"; | ||
70 | case RS_INTERNAL_ERROR: | ||
71 | return "library internal error"; | ||
72 | default: | ||
73 | return "unexplained problem"; | ||
74 | } | ||
75 | } | ||
diff --git a/rsync/netint.c b/rsync/netint.c new file mode 100644 index 0000000..71e3f9d --- a/dev/null +++ b/rsync/netint.c | |||
@@ -0,0 +1,185 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * Copyright (C) 1999 by Andrew Tridgell <tridge@samba.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU Lesser General Public License | ||
11 | * as published by the Free Software Foundation; either version 2.1 of | ||
12 | * the License, or (at your option) any 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 Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public | ||
20 | * License along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | /* | ||
25 | | Ummm, well, OK. The network's the | ||
26 | | network, the computer's the | ||
27 | | computer. Sorry for the confusion. | ||
28 | | -- Sun Microsystems | ||
29 | */ | ||
30 | |||
31 | /* | ||
32 | * Network-byte-order output to the tube. | ||
33 | * | ||
34 | * All the `suck' routines return a result code. The most common | ||
35 | * values are RS_DONE if they have enough data, or RS_BLOCKED if there | ||
36 | * is not enough input to proceed. | ||
37 | * | ||
38 | * All the netint operations are done in a fairly simpleminded way, | ||
39 | * since we don't want to rely on stdint types that may not be | ||
40 | * available on some platforms. | ||
41 | */ | ||
42 | |||
43 | /* | ||
44 | * TODO: If we don't have <stdint.h> (or perhaps even if we do), | ||
45 | * determine endianness and integer size by hand and use that to do | ||
46 | * our own conversion routines. We possibly need this anyhow to do | ||
47 | * 64-bit integers, since there seems to be no ntohs() analog. | ||
48 | */ | ||
49 | |||
50 | #include <config_rsync.h> | ||
51 | |||
52 | #include <assert.h> | ||
53 | #include <sys/types.h> | ||
54 | #include <stdlib.h> | ||
55 | #include <stdio.h> | ||
56 | #include <string.h> | ||
57 | |||
58 | #include "rsync.h" | ||
59 | |||
60 | #include "job.h" | ||
61 | #include "netint.h" | ||
62 | #include "trace.h" | ||
63 | #include "stream.h" | ||
64 | |||
65 | #define RS_MAX_INT_BYTES 8 | ||
66 | |||
67 | |||
68 | /** | ||
69 | * \brief Write a single byte to a stream output. | ||
70 | */ | ||
71 | rs_result | ||
72 | rs_squirt_byte(rs_job_t *job, unsigned char d) | ||
73 | { | ||
74 | rs_tube_write(job, &d, 1); | ||
75 | return RS_DONE; | ||
76 | } | ||
77 | |||
78 | |||
79 | /** | ||
80 | * \brief Write a variable-length integer to a stream. | ||
81 | * | ||
82 | * \param job Job of data. | ||
83 | * | ||
84 | * \param d Datum to write out. | ||
85 | * | ||
86 | * \param len Length of integer, in bytes. | ||
87 | */ | ||
88 | rs_result | ||
89 | rs_squirt_netint(rs_job_t *job, rs_long_t d, int len) | ||
90 | { | ||
91 | unsigned char buf[RS_MAX_INT_BYTES]; | ||
92 | int i, j; | ||
93 | |||
94 | if (len <= 0 || len > RS_MAX_INT_BYTES) { | ||
95 | rs_error("Illegal integer length %d", len); | ||
96 | return RS_INTERNAL_ERROR; | ||
97 | } | ||
98 | |||
99 | /* Fill the output buffer with a bigendian representation of the | ||
100 | * number. */ | ||
101 | for (i = 0, j = len-1; i < len; i++, j--) { | ||
102 | buf[j] = d; /* truncated */ | ||
103 | d >>= 8; | ||
104 | } | ||
105 | |||
106 | rs_tube_write(job, buf, len); | ||
107 | |||
108 | return RS_DONE; | ||
109 | } | ||
110 | |||
111 | |||
112 | |||
113 | rs_result | ||
114 | rs_squirt_n4(rs_job_t *job, int val) | ||
115 | { | ||
116 | return rs_squirt_netint(job, val, 4); | ||
117 | } | ||
118 | |||
119 | |||
120 | |||
121 | rs_result | ||
122 | rs_suck_netint(rs_job_t *job, rs_long_t *v, int len) | ||
123 | { | ||
124 | unsigned char *buf; | ||
125 | int i; | ||
126 | rs_result result; | ||
127 | |||
128 | if (len <= 0 || len > RS_MAX_INT_BYTES) { | ||
129 | rs_error("Illegal integer length %d", len); | ||
130 | return RS_INTERNAL_ERROR; | ||
131 | } | ||
132 | |||
133 | if ((result = rs_scoop_read(job, len, (void **) &buf)) != RS_DONE) | ||
134 | return result; | ||
135 | |||
136 | *v = 0; | ||
137 | |||
138 | for (i = 0; i < len; i++) { | ||
139 | *v = *v<<8 | buf[i]; | ||
140 | } | ||
141 | |||
142 | return RS_DONE; | ||
143 | } | ||
144 | |||
145 | |||
146 | rs_result | ||
147 | rs_suck_byte(rs_job_t *job, unsigned char *v) | ||
148 | { | ||
149 | void *inb; | ||
150 | rs_result result; | ||
151 | |||
152 | if ((result = rs_scoop_read(job, 1, &inb)) == RS_DONE) | ||
153 | *v = *((unsigned char *) inb); | ||
154 | |||
155 | return result; | ||
156 | } | ||
157 | |||
158 | |||
159 | rs_result | ||
160 | rs_suck_n4(rs_job_t *job, int *v) | ||
161 | { | ||
162 | rs_result result; | ||
163 | rs_long_t d; | ||
164 | |||
165 | result = rs_suck_netint(job, &d, 4); | ||
166 | *v = d; | ||
167 | return result; | ||
168 | } | ||
169 | |||
170 | |||
171 | int rs_int_len(rs_long_t val) | ||
172 | { | ||
173 | if (!(val & ~0xffL)) | ||
174 | return 1; | ||
175 | else if (!(val & ~0xffffL)) | ||
176 | return 2; | ||
177 | else if (!(val & ~0xffffffffL)) | ||
178 | return 4; | ||
179 | else if (!(val & ~0xffffffffffffffffL)) | ||
180 | return 8; | ||
181 | else { | ||
182 | rs_fatal("can't encode integer %.0f yet", (double) val); | ||
183 | } | ||
184 | } | ||
185 | |||
diff --git a/rsync/netint.h b/rsync/netint.h new file mode 100644 index 0000000..ee02b94 --- a/dev/null +++ b/rsync/netint.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * Copyright (C) 1999 by Andrew Tridgell <tridge@samba.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU Lesser General Public License as published by | ||
11 | * the Free Software Foundation; either version 2.1 of the License, or | ||
12 | * (at your option) any 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 Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | rs_result rs_squirt_byte(rs_job_t *, unsigned char d); | ||
25 | rs_result rs_squirt_netint(rs_job_t *, rs_long_t d, int len); | ||
26 | rs_result rs_squirt_n4(rs_job_t *, int val); | ||
27 | |||
28 | rs_result rs_suck_netint(rs_job_t *, rs_long_t *v, int len); | ||
29 | rs_result rs_suck_byte(rs_job_t *, unsigned char *); | ||
30 | rs_result rs_suck_n4(rs_job_t *, int *); | ||
31 | |||
32 | int rs_int_len(rs_long_t val); | ||
diff --git a/rsync/patch.c b/rsync/patch.c new file mode 100644 index 0000000..d2daa85 --- a/dev/null +++ b/rsync/patch.c | |||
@@ -0,0 +1,317 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | |||
24 | /* | ||
25 | | This is Tranquility Base. | ||
26 | */ | ||
27 | |||
28 | |||
29 | #include <config_rsync.h> | ||
30 | |||
31 | #include <assert.h> | ||
32 | #include <stdlib.h> | ||
33 | #include <stdio.h> | ||
34 | |||
35 | #include "rsync.h" | ||
36 | #include "util.h" | ||
37 | #include "trace.h" | ||
38 | #include "protocol.h" | ||
39 | #include "netint.h" | ||
40 | #include "command.h" | ||
41 | #include "sumset.h" | ||
42 | #include "prototab.h" | ||
43 | #include "stream.h" | ||
44 | #include "job.h" | ||
45 | |||
46 | |||
47 | |||
48 | static rs_result rs_patch_s_cmdbyte(rs_job_t *); | ||
49 | static rs_result rs_patch_s_params(rs_job_t *); | ||
50 | static rs_result rs_patch_s_run(rs_job_t *); | ||
51 | static rs_result rs_patch_s_literal(rs_job_t *); | ||
52 | static rs_result rs_patch_s_copy(rs_job_t *); | ||
53 | static rs_result rs_patch_s_copying(rs_job_t *); | ||
54 | |||
55 | |||
56 | /** | ||
57 | * State of trying to read the first byte of a command. Once we've | ||
58 | * taken that in, we can know how much data to read to get the | ||
59 | * arguments. | ||
60 | */ | ||
61 | static rs_result rs_patch_s_cmdbyte(rs_job_t *job) | ||
62 | { | ||
63 | rs_result result; | ||
64 | |||
65 | if ((result = rs_suck_byte(job, &job->op)) != RS_DONE) | ||
66 | return result; | ||
67 | |||
68 | job->cmd = &rs_prototab[job->op]; | ||
69 | |||
70 | rs_trace("got command byte 0x%02x (%s), len_1=%.0f", job->op, | ||
71 | rs_op_kind_name(job->cmd->kind), | ||
72 | (double) job->cmd->len_1); | ||
73 | |||
74 | if (job->cmd->len_1) | ||
75 | job->statefn = rs_patch_s_params; | ||
76 | else { | ||
77 | job->param1 = job->cmd->immediate; | ||
78 | job->statefn = rs_patch_s_run; | ||
79 | } | ||
80 | |||
81 | return RS_RUNNING; | ||
82 | } | ||
83 | |||
84 | |||
85 | /** | ||
86 | * Called after reading a command byte to pull in its parameters and | ||
87 | * then setup to execute the command. | ||
88 | */ | ||
89 | static rs_result rs_patch_s_params(rs_job_t *job) | ||
90 | { | ||
91 | rs_result result; | ||
92 | int len = job->cmd->len_1 + job->cmd->len_2; | ||
93 | void *p; | ||
94 | |||
95 | assert(len); | ||
96 | |||
97 | result = rs_scoop_readahead(job, len, &p); | ||
98 | if (result != RS_DONE) | ||
99 | return result; | ||
100 | |||
101 | /* we now must have LEN bytes buffered */ | ||
102 | result = rs_suck_netint(job, &job->param1, job->cmd->len_1); | ||
103 | /* shouldn't fail, since we already checked */ | ||
104 | assert(result == RS_DONE); | ||
105 | |||
106 | if (job->cmd->len_2) { | ||
107 | result = rs_suck_netint(job, &job->param2, job->cmd->len_2); | ||
108 | assert(result == RS_DONE); | ||
109 | } | ||
110 | |||
111 | job->statefn = rs_patch_s_run; | ||
112 | |||
113 | return RS_RUNNING; | ||
114 | } | ||
115 | |||
116 | |||
117 | |||
118 | /** | ||
119 | * Called when we've read in the whole command and we need to execute it. | ||
120 | */ | ||
121 | static rs_result rs_patch_s_run(rs_job_t *job) | ||
122 | { | ||
123 | rs_trace("running command 0x%x, kind %d", job->op, job->cmd->kind); | ||
124 | |||
125 | switch (job->cmd->kind) { | ||
126 | case RS_KIND_LITERAL: | ||
127 | job->statefn = rs_patch_s_literal; | ||
128 | return RS_RUNNING; | ||
129 | |||
130 | case RS_KIND_END: | ||
131 | return RS_DONE; | ||
132 | /* so we exit here; trying to continue causes an error */ | ||
133 | |||
134 | case RS_KIND_COPY: | ||
135 | job->statefn = rs_patch_s_copy; | ||
136 | return RS_RUNNING; | ||
137 | |||
138 | default: | ||
139 | rs_error("bogus command 0x%02x", job->op); | ||
140 | return RS_CORRUPT; | ||
141 | } | ||
142 | } | ||
143 | |||
144 | |||
145 | /** | ||
146 | * Called when trying to copy through literal data. | ||
147 | */ | ||
148 | static rs_result rs_patch_s_literal(rs_job_t *job) | ||
149 | { | ||
150 | rs_long_t len = job->param1; | ||
151 | |||
152 | rs_trace("LITERAL(len=%.0f)", (double) len); | ||
153 | |||
154 | job->stats.lit_cmds++; | ||
155 | job->stats.lit_bytes += len; | ||
156 | job->stats.lit_cmdbytes += 1 + job->cmd->len_1; | ||
157 | |||
158 | rs_tube_copy(job, len); | ||
159 | |||
160 | job->statefn = rs_patch_s_cmdbyte; | ||
161 | return RS_RUNNING; | ||
162 | } | ||
163 | |||
164 | |||
165 | |||
166 | static rs_result rs_patch_s_copy(rs_job_t *job) | ||
167 | { | ||
168 | rs_long_t where, len; | ||
169 | rs_stats_t *stats; | ||
170 | |||
171 | where = job->param1; | ||
172 | len = job->param2; | ||
173 | |||
174 | rs_trace("COPY(where=%.0f, len=%.0f)", (double) where, (double) len); | ||
175 | |||
176 | if (len < 0) { | ||
177 | rs_log(RS_LOG_ERR, "invalid length=%.0f on COPY command", (double) len); | ||
178 | return RS_CORRUPT; | ||
179 | } | ||
180 | |||
181 | if (where < 0) { | ||
182 | rs_log(RS_LOG_ERR, "invalid where=%.0f on COPY command", (double) where); | ||
183 | return RS_CORRUPT; | ||
184 | } | ||
185 | |||
186 | job->basis_pos = where; | ||
187 | job->basis_len = len; | ||
188 | |||
189 | stats = &job->stats; | ||
190 | |||
191 | stats->copy_cmds++; | ||
192 | stats->copy_bytes += len; | ||
193 | stats->copy_cmdbytes += 1 + job->cmd->len_1 + job->cmd->len_2; | ||
194 | |||
195 | job->statefn = rs_patch_s_copying; | ||
196 | return RS_RUNNING; | ||
197 | } | ||
198 | |||
199 | |||
200 | /** | ||
201 | * Called when we're executing a COPY command and waiting for all the | ||
202 | * data to be retrieved from the callback. | ||
203 | */ | ||
204 | static rs_result rs_patch_s_copying(rs_job_t *job) | ||
205 | { | ||
206 | rs_result result; | ||
207 | size_t len; | ||
208 | void *buf, *ptr; | ||
209 | rs_buffers_t *buffs = job->stream; | ||
210 | |||
211 | len = job->basis_len; | ||
212 | |||
213 | /* copy only as much as will fit in the output buffer, so that we | ||
214 | * don't have to block or store the input. */ | ||
215 | if (len > buffs->avail_out) | ||
216 | len = buffs->avail_out; | ||
217 | |||
218 | if (!len) | ||
219 | return RS_BLOCKED; | ||
220 | |||
221 | rs_trace("copy %.0f bytes from basis at offset %.0f", | ||
222 | (double) len, (double) job->basis_pos); | ||
223 | |||
224 | ptr = buf = rs_alloc(len, "basis buffer"); | ||
225 | |||
226 | result = (job->copy_cb)(job->copy_arg, job->basis_pos, &len, &ptr); | ||
227 | if (result != RS_DONE) | ||
228 | return result; | ||
229 | else | ||
230 | rs_trace("copy callback returned %s", rs_strerror(result)); | ||
231 | |||
232 | rs_trace("got %.0f bytes back from basis callback", (double) len); | ||
233 | |||
234 | memcpy(buffs->next_out, ptr, len); | ||
235 | |||
236 | buffs->next_out += len; | ||
237 | buffs->avail_out -= len; | ||
238 | |||
239 | job->basis_pos += len; | ||
240 | job->basis_len -= len; | ||
241 | |||
242 | free(buf); | ||
243 | |||
244 | if (!job->basis_len) { | ||
245 | /* Done! */ | ||
246 | job->statefn = rs_patch_s_cmdbyte; | ||
247 | } | ||
248 | |||
249 | return RS_RUNNING; | ||
250 | } | ||
251 | |||
252 | |||
253 | /** | ||
254 | * Called while we're trying to read the header of the patch. | ||
255 | */ | ||
256 | static rs_result rs_patch_s_header(rs_job_t *job) | ||
257 | { | ||
258 | int v; | ||
259 | rs_result result; | ||
260 | |||
261 | |||
262 | if ((result = rs_suck_n4(job, &v)) != RS_DONE) | ||
263 | return result; | ||
264 | |||
265 | if (v != RS_DELTA_MAGIC) { | ||
266 | rs_log(RS_LOG_ERR, | ||
267 | "got magic number %#x rather than expected value %#x", | ||
268 | v, RS_DELTA_MAGIC); | ||
269 | return RS_BAD_MAGIC; | ||
270 | } else | ||
271 | rs_trace("got patch magic %#x", v); | ||
272 | |||
273 | |||
274 | job->statefn = rs_patch_s_cmdbyte; | ||
275 | |||
276 | return RS_RUNNING; | ||
277 | } | ||
278 | |||
279 | |||
280 | |||
281 | /** | ||
282 | * \brief Apply a \ref gloss_delta to a \ref gloss_basis to recreate | ||
283 | * the new file. | ||
284 | * | ||
285 | * This gives you back a ::rs_job_t object, which can be cranked by | ||
286 | * calling rs_job_iter() and updating the stream pointers. When | ||
287 | * finished, call rs_job_finish() to dispose of it. | ||
288 | * | ||
289 | * \param stream Contains pointers to input and output buffers, to be | ||
290 | * adjusted by caller on each iteration. | ||
291 | * | ||
292 | * \param copy_cb Callback used to retrieve content from the basis | ||
293 | * file. | ||
294 | * | ||
295 | * \param copy_arg Opaque environment pointer passed through to the | ||
296 | * callback. | ||
297 | * | ||
298 | * \todo As output is produced, accumulate the MD4 checksum of the | ||
299 | * output. Then if we find a CHECKSUM command we can check it's | ||
300 | * contents against the output. | ||
301 | * | ||
302 | * \todo Implement COPY commands. | ||
303 | * | ||
304 | * \sa rs_patch_file() | ||
305 | */ | ||
306 | rs_job_t * | ||
307 | rs_patch_begin(rs_copy_cb *copy_cb, void *copy_arg) | ||
308 | { | ||
309 | rs_job_t *job = rs_job_new("patch", rs_patch_s_header); | ||
310 | |||
311 | job->copy_cb = copy_cb; | ||
312 | job->copy_arg = copy_arg; | ||
313 | |||
314 | rs_mdfour_begin(&job->output_md4); | ||
315 | |||
316 | return job; | ||
317 | } | ||
diff --git a/rsync/protocol.h b/rsync/protocol.h new file mode 100644 index 0000000..bee63f1 --- a/dev/null +++ b/rsync/protocol.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * Copyright (C) 1999 by Andrew Tridgell | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU Lesser General Public License | ||
11 | * as published by the Free Software Foundation; either version 2.1 of | ||
12 | * the License, or (at your option) any 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 Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public | ||
20 | * License along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
22 | |||
23 | |||
24 | /* | ||
25 | * TODO: Have a way to copy from the old signature into the new | ||
26 | * one. This will be useful for the case where the files are in fact | ||
27 | * identical, which will be significantly common. | ||
28 | */ | ||
29 | |||
30 | |||
31 | /* | ||
32 | | "The IETF already has more than enough | ||
33 | | RFCs that codify the obvious, make | ||
34 | | stupidity illegal, support truth, | ||
35 | | justice, and the IETF way, and generally | ||
36 | | demonstrate the author is a brilliant and | ||
37 | | valuable Contributor to The Standards | ||
38 | | Process." | ||
39 | | -- Vernon Schryver | ||
40 | */ | ||
41 | |||
42 | |||
43 | |||
44 | #define RS_DELTA_MAGIC 0x72730236 /* r s \2 6 */ | ||
45 | #define RS_SIG_MAGIC 0x72730136 /* r s \1 6 */ | ||
diff --git a/rsync/prototab.c b/rsync/prototab.c new file mode 100644 index 0000000..bce7d42 --- a/dev/null +++ b/rsync/prototab.c | |||
@@ -0,0 +1,277 @@ | |||
1 | |||
2 | /* AUTOGENERATED BY ./mkprototab.pl, DO NOT EDIT */ | ||
3 | |||
4 | #include <config_rsync.h> | ||
5 | |||
6 | #include <stdlib.h> | ||
7 | #include <stdio.h> | ||
8 | |||
9 | #include <rsync.h> | ||
10 | #include <protocol.h> | ||
11 | #include <command.h> | ||
12 | #include <prototab.h> | ||
13 | |||
14 | /* This file defines an array mapping command IDs to the operation kind, | ||
15 | * implied literal value, and length of the first and second parameters. | ||
16 | * The implied value is only used | ||
17 | * if the first parameter length is zero. */ | ||
18 | |||
19 | const struct rs_prototab_ent rs_prototab[] = { | ||
20 | {RS_KIND_END , 0, 0, 0 } /* RS_OP_END = 0 */, | ||
21 | {RS_KIND_LITERAL , 1, 0, 0 } /* RS_OP_LITERAL_1 = 0x1 */, | ||
22 | {RS_KIND_LITERAL , 2, 0, 0 } /* RS_OP_LITERAL_2 = 0x2 */, | ||
23 | {RS_KIND_LITERAL , 3, 0, 0 } /* RS_OP_LITERAL_3 = 0x3 */, | ||
24 | {RS_KIND_LITERAL , 4, 0, 0 } /* RS_OP_LITERAL_4 = 0x4 */, | ||
25 | {RS_KIND_LITERAL , 5, 0, 0 } /* RS_OP_LITERAL_5 = 0x5 */, | ||
26 | {RS_KIND_LITERAL , 6, 0, 0 } /* RS_OP_LITERAL_6 = 0x6 */, | ||
27 | {RS_KIND_LITERAL , 7, 0, 0 } /* RS_OP_LITERAL_7 = 0x7 */, | ||
28 | {RS_KIND_LITERAL , 8, 0, 0 } /* RS_OP_LITERAL_8 = 0x8 */, | ||
29 | {RS_KIND_LITERAL , 9, 0, 0 } /* RS_OP_LITERAL_9 = 0x9 */, | ||
30 | {RS_KIND_LITERAL , 10, 0, 0 } /* RS_OP_LITERAL_10 = 0xa */, | ||
31 | {RS_KIND_LITERAL , 11, 0, 0 } /* RS_OP_LITERAL_11 = 0xb */, | ||
32 | {RS_KIND_LITERAL , 12, 0, 0 } /* RS_OP_LITERAL_12 = 0xc */, | ||
33 | {RS_KIND_LITERAL , 13, 0, 0 } /* RS_OP_LITERAL_13 = 0xd */, | ||
34 | {RS_KIND_LITERAL , 14, 0, 0 } /* RS_OP_LITERAL_14 = 0xe */, | ||
35 | {RS_KIND_LITERAL , 15, 0, 0 } /* RS_OP_LITERAL_15 = 0xf */, | ||
36 | {RS_KIND_LITERAL , 16, 0, 0 } /* RS_OP_LITERAL_16 = 0x10 */, | ||
37 | {RS_KIND_LITERAL , 17, 0, 0 } /* RS_OP_LITERAL_17 = 0x11 */, | ||
38 | {RS_KIND_LITERAL , 18, 0, 0 } /* RS_OP_LITERAL_18 = 0x12 */, | ||
39 | {RS_KIND_LITERAL , 19, 0, 0 } /* RS_OP_LITERAL_19 = 0x13 */, | ||
40 | {RS_KIND_LITERAL , 20, 0, 0 } /* RS_OP_LITERAL_20 = 0x14 */, | ||
41 | {RS_KIND_LITERAL , 21, 0, 0 } /* RS_OP_LITERAL_21 = 0x15 */, | ||
42 | {RS_KIND_LITERAL , 22, 0, 0 } /* RS_OP_LITERAL_22 = 0x16 */, | ||
43 | {RS_KIND_LITERAL , 23, 0, 0 } /* RS_OP_LITERAL_23 = 0x17 */, | ||
44 | {RS_KIND_LITERAL , 24, 0, 0 } /* RS_OP_LITERAL_24 = 0x18 */, | ||
45 | {RS_KIND_LITERAL , 25, 0, 0 } /* RS_OP_LITERAL_25 = 0x19 */, | ||
46 | {RS_KIND_LITERAL , 26, 0, 0 } /* RS_OP_LITERAL_26 = 0x1a */, | ||
47 | {RS_KIND_LITERAL , 27, 0, 0 } /* RS_OP_LITERAL_27 = 0x1b */, | ||
48 | {RS_KIND_LITERAL , 28, 0, 0 } /* RS_OP_LITERAL_28 = 0x1c */, | ||
49 | {RS_KIND_LITERAL , 29, 0, 0 } /* RS_OP_LITERAL_29 = 0x1d */, | ||
50 | {RS_KIND_LITERAL , 30, 0, 0 } /* RS_OP_LITERAL_30 = 0x1e */, | ||
51 | {RS_KIND_LITERAL , 31, 0, 0 } /* RS_OP_LITERAL_31 = 0x1f */, | ||
52 | {RS_KIND_LITERAL , 32, 0, 0 } /* RS_OP_LITERAL_32 = 0x20 */, | ||
53 | {RS_KIND_LITERAL , 33, 0, 0 } /* RS_OP_LITERAL_33 = 0x21 */, | ||
54 | {RS_KIND_LITERAL , 34, 0, 0 } /* RS_OP_LITERAL_34 = 0x22 */, | ||
55 | {RS_KIND_LITERAL , 35, 0, 0 } /* RS_OP_LITERAL_35 = 0x23 */, | ||
56 | {RS_KIND_LITERAL , 36, 0, 0 } /* RS_OP_LITERAL_36 = 0x24 */, | ||
57 | {RS_KIND_LITERAL , 37, 0, 0 } /* RS_OP_LITERAL_37 = 0x25 */, | ||
58 | {RS_KIND_LITERAL , 38, 0, 0 } /* RS_OP_LITERAL_38 = 0x26 */, | ||
59 | {RS_KIND_LITERAL , 39, 0, 0 } /* RS_OP_LITERAL_39 = 0x27 */, | ||
60 | {RS_KIND_LITERAL , 40, 0, 0 } /* RS_OP_LITERAL_40 = 0x28 */, | ||
61 | {RS_KIND_LITERAL , 41, 0, 0 } /* RS_OP_LITERAL_41 = 0x29 */, | ||
62 | {RS_KIND_LITERAL , 42, 0, 0 } /* RS_OP_LITERAL_42 = 0x2a */, | ||
63 | {RS_KIND_LITERAL , 43, 0, 0 } /* RS_OP_LITERAL_43 = 0x2b */, | ||
64 | {RS_KIND_LITERAL , 44, 0, 0 } /* RS_OP_LITERAL_44 = 0x2c */, | ||
65 | {RS_KIND_LITERAL , 45, 0, 0 } /* RS_OP_LITERAL_45 = 0x2d */, | ||
66 | {RS_KIND_LITERAL , 46, 0, 0 } /* RS_OP_LITERAL_46 = 0x2e */, | ||
67 | {RS_KIND_LITERAL , 47, 0, 0 } /* RS_OP_LITERAL_47 = 0x2f */, | ||
68 | {RS_KIND_LITERAL , 48, 0, 0 } /* RS_OP_LITERAL_48 = 0x30 */, | ||
69 | {RS_KIND_LITERAL , 49, 0, 0 } /* RS_OP_LITERAL_49 = 0x31 */, | ||
70 | {RS_KIND_LITERAL , 50, 0, 0 } /* RS_OP_LITERAL_50 = 0x32 */, | ||
71 | {RS_KIND_LITERAL , 51, 0, 0 } /* RS_OP_LITERAL_51 = 0x33 */, | ||
72 | {RS_KIND_LITERAL , 52, 0, 0 } /* RS_OP_LITERAL_52 = 0x34 */, | ||
73 | {RS_KIND_LITERAL , 53, 0, 0 } /* RS_OP_LITERAL_53 = 0x35 */, | ||
74 | {RS_KIND_LITERAL , 54, 0, 0 } /* RS_OP_LITERAL_54 = 0x36 */, | ||
75 | {RS_KIND_LITERAL , 55, 0, 0 } /* RS_OP_LITERAL_55 = 0x37 */, | ||
76 | {RS_KIND_LITERAL , 56, 0, 0 } /* RS_OP_LITERAL_56 = 0x38 */, | ||
77 | {RS_KIND_LITERAL , 57, 0, 0 } /* RS_OP_LITERAL_57 = 0x39 */, | ||
78 | {RS_KIND_LITERAL , 58, 0, 0 } /* RS_OP_LITERAL_58 = 0x3a */, | ||
79 | {RS_KIND_LITERAL , 59, 0, 0 } /* RS_OP_LITERAL_59 = 0x3b */, | ||
80 | {RS_KIND_LITERAL , 60, 0, 0 } /* RS_OP_LITERAL_60 = 0x3c */, | ||
81 | {RS_KIND_LITERAL , 61, 0, 0 } /* RS_OP_LITERAL_61 = 0x3d */, | ||
82 | {RS_KIND_LITERAL , 62, 0, 0 } /* RS_OP_LITERAL_62 = 0x3e */, | ||
83 | {RS_KIND_LITERAL , 63, 0, 0 } /* RS_OP_LITERAL_63 = 0x3f */, | ||
84 | {RS_KIND_LITERAL , 64, 0, 0 } /* RS_OP_LITERAL_64 = 0x40 */, | ||
85 | {RS_KIND_LITERAL , 0, 1, 0 } /* RS_OP_LITERAL_N1 = 0x41 */, | ||
86 | {RS_KIND_LITERAL , 0, 2, 0 } /* RS_OP_LITERAL_N2 = 0x42 */, | ||
87 | {RS_KIND_LITERAL , 0, 4, 0 } /* RS_OP_LITERAL_N4 = 0x43 */, | ||
88 | {RS_KIND_LITERAL , 0, 8, 0 } /* RS_OP_LITERAL_N8 = 0x44 */, | ||
89 | {RS_KIND_COPY , 0, 1, 1 } /* RS_OP_COPY_N1_N1 = 0x45 */, | ||
90 | {RS_KIND_COPY , 0, 1, 2 } /* RS_OP_COPY_N1_N2 = 0x46 */, | ||
91 | {RS_KIND_COPY , 0, 1, 4 } /* RS_OP_COPY_N1_N4 = 0x47 */, | ||
92 | {RS_KIND_COPY , 0, 1, 8 } /* RS_OP_COPY_N1_N8 = 0x48 */, | ||
93 | {RS_KIND_COPY , 0, 2, 1 } /* RS_OP_COPY_N2_N1 = 0x49 */, | ||
94 | {RS_KIND_COPY , 0, 2, 2 } /* RS_OP_COPY_N2_N2 = 0x4a */, | ||
95 | {RS_KIND_COPY , 0, 2, 4 } /* RS_OP_COPY_N2_N4 = 0x4b */, | ||
96 | {RS_KIND_COPY , 0, 2, 8 } /* RS_OP_COPY_N2_N8 = 0x4c */, | ||
97 | {RS_KIND_COPY , 0, 4, 1 } /* RS_OP_COPY_N4_N1 = 0x4d */, | ||
98 | {RS_KIND_COPY , 0, 4, 2 } /* RS_OP_COPY_N4_N2 = 0x4e */, | ||
99 | {RS_KIND_COPY , 0, 4, 4 } /* RS_OP_COPY_N4_N4 = 0x4f */, | ||
100 | {RS_KIND_COPY , 0, 4, 8 } /* RS_OP_COPY_N4_N8 = 0x50 */, | ||
101 | {RS_KIND_COPY , 0, 8, 1 } /* RS_OP_COPY_N8_N1 = 0x51 */, | ||
102 | {RS_KIND_COPY , 0, 8, 2 } /* RS_OP_COPY_N8_N2 = 0x52 */, | ||
103 | {RS_KIND_COPY , 0, 8, 4 } /* RS_OP_COPY_N8_N4 = 0x53 */, | ||
104 | {RS_KIND_COPY , 0, 8, 8 } /* RS_OP_COPY_N8_N8 = 0x54 */, | ||
105 | {RS_KIND_RESERVED , 85, 0, 0 } /* RS_OP_RESERVED_85 = 0x55 */, | ||
106 | {RS_KIND_RESERVED , 86, 0, 0 } /* RS_OP_RESERVED_86 = 0x56 */, | ||
107 | {RS_KIND_RESERVED , 87, 0, 0 } /* RS_OP_RESERVED_87 = 0x57 */, | ||
108 | {RS_KIND_RESERVED , 88, 0, 0 } /* RS_OP_RESERVED_88 = 0x58 */, | ||
109 | {RS_KIND_RESERVED , 89, 0, 0 } /* RS_OP_RESERVED_89 = 0x59 */, | ||
110 | {RS_KIND_RESERVED , 90, 0, 0 } /* RS_OP_RESERVED_90 = 0x5a */, | ||
111 | {RS_KIND_RESERVED , 91, 0, 0 } /* RS_OP_RESERVED_91 = 0x5b */, | ||
112 | {RS_KIND_RESERVED , 92, 0, 0 } /* RS_OP_RESERVED_92 = 0x5c */, | ||
113 | {RS_KIND_RESERVED , 93, 0, 0 } /* RS_OP_RESERVED_93 = 0x5d */, | ||
114 | {RS_KIND_RESERVED , 94, 0, 0 } /* RS_OP_RESERVED_94 = 0x5e */, | ||
115 | {RS_KIND_RESERVED , 95, 0, 0 } /* RS_OP_RESERVED_95 = 0x5f */, | ||
116 | {RS_KIND_RESERVED , 96, 0, 0 } /* RS_OP_RESERVED_96 = 0x60 */, | ||
117 | {RS_KIND_RESERVED , 97, 0, 0 } /* RS_OP_RESERVED_97 = 0x61 */, | ||
118 | {RS_KIND_RESERVED , 98, 0, 0 } /* RS_OP_RESERVED_98 = 0x62 */, | ||
119 | {RS_KIND_RESERVED , 99, 0, 0 } /* RS_OP_RESERVED_99 = 0x63 */, | ||
120 | {RS_KIND_RESERVED , 100, 0, 0 } /* RS_OP_RESERVED_100 = 0x64 */, | ||
121 | {RS_KIND_RESERVED , 101, 0, 0 } /* RS_OP_RESERVED_101 = 0x65 */, | ||
122 | {RS_KIND_RESERVED , 102, 0, 0 } /* RS_OP_RESERVED_102 = 0x66 */, | ||
123 | {RS_KIND_RESERVED , 103, 0, 0 } /* RS_OP_RESERVED_103 = 0x67 */, | ||
124 | {RS_KIND_RESERVED , 104, 0, 0 } /* RS_OP_RESERVED_104 = 0x68 */, | ||
125 | {RS_KIND_RESERVED , 105, 0, 0 } /* RS_OP_RESERVED_105 = 0x69 */, | ||
126 | {RS_KIND_RESERVED , 106, 0, 0 } /* RS_OP_RESERVED_106 = 0x6a */, | ||
127 | {RS_KIND_RESERVED , 107, 0, 0 } /* RS_OP_RESERVED_107 = 0x6b */, | ||
128 | {RS_KIND_RESERVED , 108, 0, 0 } /* RS_OP_RESERVED_108 = 0x6c */, | ||
129 | {RS_KIND_RESERVED , 109, 0, 0 } /* RS_OP_RESERVED_109 = 0x6d */, | ||
130 | {RS_KIND_RESERVED , 110, 0, 0 } /* RS_OP_RESERVED_110 = 0x6e */, | ||
131 | {RS_KIND_RESERVED , 111, 0, 0 } /* RS_OP_RESERVED_111 = 0x6f */, | ||
132 | {RS_KIND_RESERVED , 112, 0, 0 } /* RS_OP_RESERVED_112 = 0x70 */, | ||
133 | {RS_KIND_RESERVED , 113, 0, 0 } /* RS_OP_RESERVED_113 = 0x71 */, | ||
134 | {RS_KIND_RESERVED , 114, 0, 0 } /* RS_OP_RESERVED_114 = 0x72 */, | ||
135 | {RS_KIND_RESERVED , 115, 0, 0 } /* RS_OP_RESERVED_115 = 0x73 */, | ||
136 | {RS_KIND_RESERVED , 116, 0, 0 } /* RS_OP_RESERVED_116 = 0x74 */, | ||
137 | {RS_KIND_RESERVED , 117, 0, 0 } /* RS_OP_RESERVED_117 = 0x75 */, | ||
138 | {RS_KIND_RESERVED , 118, 0, 0 } /* RS_OP_RESERVED_118 = 0x76 */, | ||
139 | {RS_KIND_RESERVED , 119, 0, 0 } /* RS_OP_RESERVED_119 = 0x77 */, | ||
140 | {RS_KIND_RESERVED , 120, 0, 0 } /* RS_OP_RESERVED_120 = 0x78 */, | ||
141 | {RS_KIND_RESERVED , 121, 0, 0 } /* RS_OP_RESERVED_121 = 0x79 */, | ||
142 | {RS_KIND_RESERVED , 122, 0, 0 } /* RS_OP_RESERVED_122 = 0x7a */, | ||
143 | {RS_KIND_RESERVED , 123, 0, 0 } /* RS_OP_RESERVED_123 = 0x7b */, | ||
144 | {RS_KIND_RESERVED , 124, 0, 0 } /* RS_OP_RESERVED_124 = 0x7c */, | ||
145 | {RS_KIND_RESERVED , 125, 0, 0 } /* RS_OP_RESERVED_125 = 0x7d */, | ||
146 | {RS_KIND_RESERVED , 126, 0, 0 } /* RS_OP_RESERVED_126 = 0x7e */, | ||
147 | {RS_KIND_RESERVED , 127, 0, 0 } /* RS_OP_RESERVED_127 = 0x7f */, | ||
148 | {RS_KIND_RESERVED , 128, 0, 0 } /* RS_OP_RESERVED_128 = 0x80 */, | ||
149 | {RS_KIND_RESERVED , 129, 0, 0 } /* RS_OP_RESERVED_129 = 0x81 */, | ||
150 | {RS_KIND_RESERVED , 130, 0, 0 } /* RS_OP_RESERVED_130 = 0x82 */, | ||
151 | {RS_KIND_RESERVED , 131, 0, 0 } /* RS_OP_RESERVED_131 = 0x83 */, | ||
152 | {RS_KIND_RESERVED , 132, 0, 0 } /* RS_OP_RESERVED_132 = 0x84 */, | ||
153 | {RS_KIND_RESERVED , 133, 0, 0 } /* RS_OP_RESERVED_133 = 0x85 */, | ||
154 | {RS_KIND_RESERVED , 134, 0, 0 } /* RS_OP_RESERVED_134 = 0x86 */, | ||
155 | {RS_KIND_RESERVED , 135, 0, 0 } /* RS_OP_RESERVED_135 = 0x87 */, | ||
156 | {RS_KIND_RESERVED , 136, 0, 0 } /* RS_OP_RESERVED_136 = 0x88 */, | ||
157 | {RS_KIND_RESERVED , 137, 0, 0 } /* RS_OP_RESERVED_137 = 0x89 */, | ||
158 | {RS_KIND_RESERVED , 138, 0, 0 } /* RS_OP_RESERVED_138 = 0x8a */, | ||
159 | {RS_KIND_RESERVED , 139, 0, 0 } /* RS_OP_RESERVED_139 = 0x8b */, | ||
160 | {RS_KIND_RESERVED , 140, 0, 0 } /* RS_OP_RESERVED_140 = 0x8c */, | ||
161 | {RS_KIND_RESERVED , 141, 0, 0 } /* RS_OP_RESERVED_141 = 0x8d */, | ||
162 | {RS_KIND_RESERVED , 142, 0, 0 } /* RS_OP_RESERVED_142 = 0x8e */, | ||
163 | {RS_KIND_RESERVED , 143, 0, 0 } /* RS_OP_RESERVED_143 = 0x8f */, | ||
164 | {RS_KIND_RESERVED , 144, 0, 0 } /* RS_OP_RESERVED_144 = 0x90 */, | ||
165 | {RS_KIND_RESERVED , 145, 0, 0 } /* RS_OP_RESERVED_145 = 0x91 */, | ||
166 | {RS_KIND_RESERVED , 146, 0, 0 } /* RS_OP_RESERVED_146 = 0x92 */, | ||
167 | {RS_KIND_RESERVED , 147, 0, 0 } /* RS_OP_RESERVED_147 = 0x93 */, | ||
168 | {RS_KIND_RESERVED , 148, 0, 0 } /* RS_OP_RESERVED_148 = 0x94 */, | ||
169 | {RS_KIND_RESERVED , 149, 0, 0 } /* RS_OP_RESERVED_149 = 0x95 */, | ||
170 | {RS_KIND_RESERVED , 150, 0, 0 } /* RS_OP_RESERVED_150 = 0x96 */, | ||
171 | {RS_KIND_RESERVED , 151, 0, 0 } /* RS_OP_RESERVED_151 = 0x97 */, | ||
172 | {RS_KIND_RESERVED , 152, 0, 0 } /* RS_OP_RESERVED_152 = 0x98 */, | ||
173 | {RS_KIND_RESERVED , 153, 0, 0 } /* RS_OP_RESERVED_153 = 0x99 */, | ||
174 | {RS_KIND_RESERVED , 154, 0, 0 } /* RS_OP_RESERVED_154 = 0x9a */, | ||
175 | {RS_KIND_RESERVED , 155, 0, 0 } /* RS_OP_RESERVED_155 = 0x9b */, | ||
176 | {RS_KIND_RESERVED , 156, 0, 0 } /* RS_OP_RESERVED_156 = 0x9c */, | ||
177 | {RS_KIND_RESERVED , 157, 0, 0 } /* RS_OP_RESERVED_157 = 0x9d */, | ||
178 | {RS_KIND_RESERVED , 158, 0, 0 } /* RS_OP_RESERVED_158 = 0x9e */, | ||
179 | {RS_KIND_RESERVED , 159, 0, 0 } /* RS_OP_RESERVED_159 = 0x9f */, | ||
180 | {RS_KIND_RESERVED , 160, 0, 0 } /* RS_OP_RESERVED_160 = 0xa0 */, | ||
181 | {RS_KIND_RESERVED , 161, 0, 0 } /* RS_OP_RESERVED_161 = 0xa1 */, | ||
182 | {RS_KIND_RESERVED , 162, 0, 0 } /* RS_OP_RESERVED_162 = 0xa2 */, | ||
183 | {RS_KIND_RESERVED , 163, 0, 0 } /* RS_OP_RESERVED_163 = 0xa3 */, | ||
184 | {RS_KIND_RESERVED , 164, 0, 0 } /* RS_OP_RESERVED_164 = 0xa4 */, | ||
185 | {RS_KIND_RESERVED , 165, 0, 0 } /* RS_OP_RESERVED_165 = 0xa5 */, | ||
186 | {RS_KIND_RESERVED , 166, 0, 0 } /* RS_OP_RESERVED_166 = 0xa6 */, | ||
187 | {RS_KIND_RESERVED , 167, 0, 0 } /* RS_OP_RESERVED_167 = 0xa7 */, | ||
188 | {RS_KIND_RESERVED , 168, 0, 0 } /* RS_OP_RESERVED_168 = 0xa8 */, | ||
189 | {RS_KIND_RESERVED , 169, 0, 0 } /* RS_OP_RESERVED_169 = 0xa9 */, | ||
190 | {RS_KIND_RESERVED , 170, 0, 0 } /* RS_OP_RESERVED_170 = 0xaa */, | ||
191 | {RS_KIND_RESERVED , 171, 0, 0 } /* RS_OP_RESERVED_171 = 0xab */, | ||
192 | {RS_KIND_RESERVED , 172, 0, 0 } /* RS_OP_RESERVED_172 = 0xac */, | ||
193 | {RS_KIND_RESERVED , 173, 0, 0 } /* RS_OP_RESERVED_173 = 0xad */, | ||
194 | {RS_KIND_RESERVED , 174, 0, 0 } /* RS_OP_RESERVED_174 = 0xae */, | ||
195 | {RS_KIND_RESERVED , 175, 0, 0 } /* RS_OP_RESERVED_175 = 0xaf */, | ||
196 | {RS_KIND_RESERVED , 176, 0, 0 } /* RS_OP_RESERVED_176 = 0xb0 */, | ||
197 | {RS_KIND_RESERVED , 177, 0, 0 } /* RS_OP_RESERVED_177 = 0xb1 */, | ||
198 | {RS_KIND_RESERVED , 178, 0, 0 } /* RS_OP_RESERVED_178 = 0xb2 */, | ||
199 | {RS_KIND_RESERVED , 179, 0, 0 } /* RS_OP_RESERVED_179 = 0xb3 */, | ||
200 | {RS_KIND_RESERVED , 180, 0, 0 } /* RS_OP_RESERVED_180 = 0xb4 */, | ||
201 | {RS_KIND_RESERVED , 181, 0, 0 } /* RS_OP_RESERVED_181 = 0xb5 */, | ||
202 | {RS_KIND_RESERVED , 182, 0, 0 } /* RS_OP_RESERVED_182 = 0xb6 */, | ||
203 | {RS_KIND_RESERVED , 183, 0, 0 } /* RS_OP_RESERVED_183 = 0xb7 */, | ||
204 | {RS_KIND_RESERVED , 184, 0, 0 } /* RS_OP_RESERVED_184 = 0xb8 */, | ||
205 | {RS_KIND_RESERVED , 185, 0, 0 } /* RS_OP_RESERVED_185 = 0xb9 */, | ||
206 | {RS_KIND_RESERVED , 186, 0, 0 } /* RS_OP_RESERVED_186 = 0xba */, | ||
207 | {RS_KIND_RESERVED , 187, 0, 0 } /* RS_OP_RESERVED_187 = 0xbb */, | ||
208 | {RS_KIND_RESERVED , 188, 0, 0 } /* RS_OP_RESERVED_188 = 0xbc */, | ||
209 | {RS_KIND_RESERVED , 189, 0, 0 } /* RS_OP_RESERVED_189 = 0xbd */, | ||
210 | {RS_KIND_RESERVED , 190, 0, 0 } /* RS_OP_RESERVED_190 = 0xbe */, | ||
211 | {RS_KIND_RESERVED , 191, 0, 0 } /* RS_OP_RESERVED_191 = 0xbf */, | ||
212 | {RS_KIND_RESERVED , 192, 0, 0 } /* RS_OP_RESERVED_192 = 0xc0 */, | ||
213 | {RS_KIND_RESERVED , 193, 0, 0 } /* RS_OP_RESERVED_193 = 0xc1 */, | ||
214 | {RS_KIND_RESERVED , 194, 0, 0 } /* RS_OP_RESERVED_194 = 0xc2 */, | ||
215 | {RS_KIND_RESERVED , 195, 0, 0 } /* RS_OP_RESERVED_195 = 0xc3 */, | ||
216 | {RS_KIND_RESERVED , 196, 0, 0 } /* RS_OP_RESERVED_196 = 0xc4 */, | ||
217 | {RS_KIND_RESERVED , 197, 0, 0 } /* RS_OP_RESERVED_197 = 0xc5 */, | ||
218 | {RS_KIND_RESERVED , 198, 0, 0 } /* RS_OP_RESERVED_198 = 0xc6 */, | ||
219 | {RS_KIND_RESERVED , 199, 0, 0 } /* RS_OP_RESERVED_199 = 0xc7 */, | ||
220 | {RS_KIND_RESERVED , 200, 0, 0 } /* RS_OP_RESERVED_200 = 0xc8 */, | ||
221 | {RS_KIND_RESERVED , 201, 0, 0 } /* RS_OP_RESERVED_201 = 0xc9 */, | ||
222 | {RS_KIND_RESERVED , 202, 0, 0 } /* RS_OP_RESERVED_202 = 0xca */, | ||
223 | {RS_KIND_RESERVED , 203, 0, 0 } /* RS_OP_RESERVED_203 = 0xcb */, | ||
224 | {RS_KIND_RESERVED , 204, 0, 0 } /* RS_OP_RESERVED_204 = 0xcc */, | ||
225 | {RS_KIND_RESERVED , 205, 0, 0 } /* RS_OP_RESERVED_205 = 0xcd */, | ||
226 | {RS_KIND_RESERVED , 206, 0, 0 } /* RS_OP_RESERVED_206 = 0xce */, | ||
227 | {RS_KIND_RESERVED , 207, 0, 0 } /* RS_OP_RESERVED_207 = 0xcf */, | ||
228 | {RS_KIND_RESERVED , 208, 0, 0 } /* RS_OP_RESERVED_208 = 0xd0 */, | ||
229 | {RS_KIND_RESERVED , 209, 0, 0 } /* RS_OP_RESERVED_209 = 0xd1 */, | ||
230 | {RS_KIND_RESERVED , 210, 0, 0 } /* RS_OP_RESERVED_210 = 0xd2 */, | ||
231 | {RS_KIND_RESERVED , 211, 0, 0 } /* RS_OP_RESERVED_211 = 0xd3 */, | ||
232 | {RS_KIND_RESERVED , 212, 0, 0 } /* RS_OP_RESERVED_212 = 0xd4 */, | ||
233 | {RS_KIND_RESERVED , 213, 0, 0 } /* RS_OP_RESERVED_213 = 0xd5 */, | ||
234 | {RS_KIND_RESERVED , 214, 0, 0 } /* RS_OP_RESERVED_214 = 0xd6 */, | ||
235 | {RS_KIND_RESERVED , 215, 0, 0 } /* RS_OP_RESERVED_215 = 0xd7 */, | ||
236 | {RS_KIND_RESERVED , 216, 0, 0 } /* RS_OP_RESERVED_216 = 0xd8 */, | ||
237 | {RS_KIND_RESERVED , 217, 0, 0 } /* RS_OP_RESERVED_217 = 0xd9 */, | ||
238 | {RS_KIND_RESERVED , 218, 0, 0 } /* RS_OP_RESERVED_218 = 0xda */, | ||
239 | {RS_KIND_RESERVED , 219, 0, 0 } /* RS_OP_RESERVED_219 = 0xdb */, | ||
240 | {RS_KIND_RESERVED , 220, 0, 0 } /* RS_OP_RESERVED_220 = 0xdc */, | ||
241 | {RS_KIND_RESERVED , 221, 0, 0 } /* RS_OP_RESERVED_221 = 0xdd */, | ||
242 | {RS_KIND_RESERVED , 222, 0, 0 } /* RS_OP_RESERVED_222 = 0xde */, | ||
243 | {RS_KIND_RESERVED , 223, 0, 0 } /* RS_OP_RESERVED_223 = 0xdf */, | ||
244 | {RS_KIND_RESERVED , 224, 0, 0 } /* RS_OP_RESERVED_224 = 0xe0 */, | ||
245 | {RS_KIND_RESERVED , 225, 0, 0 } /* RS_OP_RESERVED_225 = 0xe1 */, | ||
246 | {RS_KIND_RESERVED , 226, 0, 0 } /* RS_OP_RESERVED_226 = 0xe2 */, | ||
247 | {RS_KIND_RESERVED , 227, 0, 0 } /* RS_OP_RESERVED_227 = 0xe3 */, | ||
248 | {RS_KIND_RESERVED , 228, 0, 0 } /* RS_OP_RESERVED_228 = 0xe4 */, | ||
249 | {RS_KIND_RESERVED , 229, 0, 0 } /* RS_OP_RESERVED_229 = 0xe5 */, | ||
250 | {RS_KIND_RESERVED , 230, 0, 0 } /* RS_OP_RESERVED_230 = 0xe6 */, | ||
251 | {RS_KIND_RESERVED , 231, 0, 0 } /* RS_OP_RESERVED_231 = 0xe7 */, | ||
252 | {RS_KIND_RESERVED , 232, 0, 0 } /* RS_OP_RESERVED_232 = 0xe8 */, | ||
253 | {RS_KIND_RESERVED , 233, 0, 0 } /* RS_OP_RESERVED_233 = 0xe9 */, | ||
254 | {RS_KIND_RESERVED , 234, 0, 0 } /* RS_OP_RESERVED_234 = 0xea */, | ||
255 | {RS_KIND_RESERVED , 235, 0, 0 } /* RS_OP_RESERVED_235 = 0xeb */, | ||
256 | {RS_KIND_RESERVED , 236, 0, 0 } /* RS_OP_RESERVED_236 = 0xec */, | ||
257 | {RS_KIND_RESERVED , 237, 0, 0 } /* RS_OP_RESERVED_237 = 0xed */, | ||
258 | {RS_KIND_RESERVED , 238, 0, 0 } /* RS_OP_RESERVED_238 = 0xee */, | ||
259 | {RS_KIND_RESERVED , 239, 0, 0 } /* RS_OP_RESERVED_239 = 0xef */, | ||
260 | {RS_KIND_RESERVED , 240, 0, 0 } /* RS_OP_RESERVED_240 = 0xf0 */, | ||
261 | {RS_KIND_RESERVED , 241, 0, 0 } /* RS_OP_RESERVED_241 = 0xf1 */, | ||
262 | {RS_KIND_RESERVED , 242, 0, 0 } /* RS_OP_RESERVED_242 = 0xf2 */, | ||
263 | {RS_KIND_RESERVED , 243, 0, 0 } /* RS_OP_RESERVED_243 = 0xf3 */, | ||
264 | {RS_KIND_RESERVED , 244, 0, 0 } /* RS_OP_RESERVED_244 = 0xf4 */, | ||
265 | {RS_KIND_RESERVED , 245, 0, 0 } /* RS_OP_RESERVED_245 = 0xf5 */, | ||
266 | {RS_KIND_RESERVED , 246, 0, 0 } /* RS_OP_RESERVED_246 = 0xf6 */, | ||
267 | {RS_KIND_RESERVED , 247, 0, 0 } /* RS_OP_RESERVED_247 = 0xf7 */, | ||
268 | {RS_KIND_RESERVED , 248, 0, 0 } /* RS_OP_RESERVED_248 = 0xf8 */, | ||
269 | {RS_KIND_RESERVED , 249, 0, 0 } /* RS_OP_RESERVED_249 = 0xf9 */, | ||
270 | {RS_KIND_RESERVED , 250, 0, 0 } /* RS_OP_RESERVED_250 = 0xfa */, | ||
271 | {RS_KIND_RESERVED , 251, 0, 0 } /* RS_OP_RESERVED_251 = 0xfb */, | ||
272 | {RS_KIND_RESERVED , 252, 0, 0 } /* RS_OP_RESERVED_252 = 0xfc */, | ||
273 | {RS_KIND_RESERVED , 253, 0, 0 } /* RS_OP_RESERVED_253 = 0xfd */, | ||
274 | {RS_KIND_RESERVED , 254, 0, 0 } /* RS_OP_RESERVED_254 = 0xfe */, | ||
275 | {RS_KIND_RESERVED , 255, 0, 0 } /* RS_OP_RESERVED_255 = 0xff */ | ||
276 | }; | ||
277 | /* END OF AUTOGENERATED CODE */ | ||
diff --git a/rsync/prototab.h b/rsync/prototab.h new file mode 100644 index 0000000..3a9d771 --- a/dev/null +++ b/rsync/prototab.h | |||
@@ -0,0 +1,270 @@ | |||
1 | |||
2 | /* AUTOGENERATED BY ./mkprototab.pl, DO NOT EDIT */ | ||
3 | |||
4 | typedef struct rs_prototab_ent { | ||
5 | enum rs_op_kind kind; | ||
6 | int immediate; | ||
7 | size_t len_1, len_2; | ||
8 | } rs_prototab_ent_t; | ||
9 | |||
10 | extern const rs_prototab_ent_t rs_prototab[]; | ||
11 | |||
12 | enum { | ||
13 | RS_OP_END = 0, | ||
14 | RS_OP_LITERAL_1 = 0x1, | ||
15 | RS_OP_LITERAL_2 = 0x2, | ||
16 | RS_OP_LITERAL_3 = 0x3, | ||
17 | RS_OP_LITERAL_4 = 0x4, | ||
18 | RS_OP_LITERAL_5 = 0x5, | ||
19 | RS_OP_LITERAL_6 = 0x6, | ||
20 | RS_OP_LITERAL_7 = 0x7, | ||
21 | RS_OP_LITERAL_8 = 0x8, | ||
22 | RS_OP_LITERAL_9 = 0x9, | ||
23 | RS_OP_LITERAL_10 = 0xa, | ||
24 | RS_OP_LITERAL_11 = 0xb, | ||
25 | RS_OP_LITERAL_12 = 0xc, | ||
26 | RS_OP_LITERAL_13 = 0xd, | ||
27 | RS_OP_LITERAL_14 = 0xe, | ||
28 | RS_OP_LITERAL_15 = 0xf, | ||
29 | RS_OP_LITERAL_16 = 0x10, | ||
30 | RS_OP_LITERAL_17 = 0x11, | ||
31 | RS_OP_LITERAL_18 = 0x12, | ||
32 | RS_OP_LITERAL_19 = 0x13, | ||
33 | RS_OP_LITERAL_20 = 0x14, | ||
34 | RS_OP_LITERAL_21 = 0x15, | ||
35 | RS_OP_LITERAL_22 = 0x16, | ||
36 | RS_OP_LITERAL_23 = 0x17, | ||
37 | RS_OP_LITERAL_24 = 0x18, | ||
38 | RS_OP_LITERAL_25 = 0x19, | ||
39 | RS_OP_LITERAL_26 = 0x1a, | ||
40 | RS_OP_LITERAL_27 = 0x1b, | ||
41 | RS_OP_LITERAL_28 = 0x1c, | ||
42 | RS_OP_LITERAL_29 = 0x1d, | ||
43 | RS_OP_LITERAL_30 = 0x1e, | ||
44 | RS_OP_LITERAL_31 = 0x1f, | ||
45 | RS_OP_LITERAL_32 = 0x20, | ||
46 | RS_OP_LITERAL_33 = 0x21, | ||
47 | RS_OP_LITERAL_34 = 0x22, | ||
48 | RS_OP_LITERAL_35 = 0x23, | ||
49 | RS_OP_LITERAL_36 = 0x24, | ||
50 | RS_OP_LITERAL_37 = 0x25, | ||
51 | RS_OP_LITERAL_38 = 0x26, | ||
52 | RS_OP_LITERAL_39 = 0x27, | ||
53 | RS_OP_LITERAL_40 = 0x28, | ||
54 | RS_OP_LITERAL_41 = 0x29, | ||
55 | RS_OP_LITERAL_42 = 0x2a, | ||
56 | RS_OP_LITERAL_43 = 0x2b, | ||
57 | RS_OP_LITERAL_44 = 0x2c, | ||
58 | RS_OP_LITERAL_45 = 0x2d, | ||
59 | RS_OP_LITERAL_46 = 0x2e, | ||
60 | RS_OP_LITERAL_47 = 0x2f, | ||
61 | RS_OP_LITERAL_48 = 0x30, | ||
62 | RS_OP_LITERAL_49 = 0x31, | ||
63 | RS_OP_LITERAL_50 = 0x32, | ||
64 | RS_OP_LITERAL_51 = 0x33, | ||
65 | RS_OP_LITERAL_52 = 0x34, | ||
66 | RS_OP_LITERAL_53 = 0x35, | ||
67 | RS_OP_LITERAL_54 = 0x36, | ||
68 | RS_OP_LITERAL_55 = 0x37, | ||
69 | RS_OP_LITERAL_56 = 0x38, | ||
70 | RS_OP_LITERAL_57 = 0x39, | ||
71 | RS_OP_LITERAL_58 = 0x3a, | ||
72 | RS_OP_LITERAL_59 = 0x3b, | ||
73 | RS_OP_LITERAL_60 = 0x3c, | ||
74 | RS_OP_LITERAL_61 = 0x3d, | ||
75 | RS_OP_LITERAL_62 = 0x3e, | ||
76 | RS_OP_LITERAL_63 = 0x3f, | ||
77 | RS_OP_LITERAL_64 = 0x40, | ||
78 | RS_OP_LITERAL_N1 = 0x41, | ||
79 | RS_OP_LITERAL_N2 = 0x42, | ||
80 | RS_OP_LITERAL_N4 = 0x43, | ||
81 | RS_OP_LITERAL_N8 = 0x44, | ||
82 | RS_OP_COPY_N1_N1 = 0x45, | ||
83 | RS_OP_COPY_N1_N2 = 0x46, | ||
84 | RS_OP_COPY_N1_N4 = 0x47, | ||
85 | RS_OP_COPY_N1_N8 = 0x48, | ||
86 | RS_OP_COPY_N2_N1 = 0x49, | ||
87 | RS_OP_COPY_N2_N2 = 0x4a, | ||
88 | RS_OP_COPY_N2_N4 = 0x4b, | ||
89 | RS_OP_COPY_N2_N8 = 0x4c, | ||
90 | RS_OP_COPY_N4_N1 = 0x4d, | ||
91 | RS_OP_COPY_N4_N2 = 0x4e, | ||
92 | RS_OP_COPY_N4_N4 = 0x4f, | ||
93 | RS_OP_COPY_N4_N8 = 0x50, | ||
94 | RS_OP_COPY_N8_N1 = 0x51, | ||
95 | RS_OP_COPY_N8_N2 = 0x52, | ||
96 | RS_OP_COPY_N8_N4 = 0x53, | ||
97 | RS_OP_COPY_N8_N8 = 0x54, | ||
98 | RS_OP_RESERVED_85 = 0x55, | ||
99 | RS_OP_RESERVED_86 = 0x56, | ||
100 | RS_OP_RESERVED_87 = 0x57, | ||
101 | RS_OP_RESERVED_88 = 0x58, | ||
102 | RS_OP_RESERVED_89 = 0x59, | ||
103 | RS_OP_RESERVED_90 = 0x5a, | ||
104 | RS_OP_RESERVED_91 = 0x5b, | ||
105 | RS_OP_RESERVED_92 = 0x5c, | ||
106 | RS_OP_RESERVED_93 = 0x5d, | ||
107 | RS_OP_RESERVED_94 = 0x5e, | ||
108 | RS_OP_RESERVED_95 = 0x5f, | ||
109 | RS_OP_RESERVED_96 = 0x60, | ||
110 | RS_OP_RESERVED_97 = 0x61, | ||
111 | RS_OP_RESERVED_98 = 0x62, | ||
112 | RS_OP_RESERVED_99 = 0x63, | ||
113 | RS_OP_RESERVED_100 = 0x64, | ||
114 | RS_OP_RESERVED_101 = 0x65, | ||
115 | RS_OP_RESERVED_102 = 0x66, | ||
116 | RS_OP_RESERVED_103 = 0x67, | ||
117 | RS_OP_RESERVED_104 = 0x68, | ||
118 | RS_OP_RESERVED_105 = 0x69, | ||
119 | RS_OP_RESERVED_106 = 0x6a, | ||
120 | RS_OP_RESERVED_107 = 0x6b, | ||
121 | RS_OP_RESERVED_108 = 0x6c, | ||
122 | RS_OP_RESERVED_109 = 0x6d, | ||
123 | RS_OP_RESERVED_110 = 0x6e, | ||
124 | RS_OP_RESERVED_111 = 0x6f, | ||
125 | RS_OP_RESERVED_112 = 0x70, | ||
126 | RS_OP_RESERVED_113 = 0x71, | ||
127 | RS_OP_RESERVED_114 = 0x72, | ||
128 | RS_OP_RESERVED_115 = 0x73, | ||
129 | RS_OP_RESERVED_116 = 0x74, | ||
130 | RS_OP_RESERVED_117 = 0x75, | ||
131 | RS_OP_RESERVED_118 = 0x76, | ||
132 | RS_OP_RESERVED_119 = 0x77, | ||
133 | RS_OP_RESERVED_120 = 0x78, | ||
134 | RS_OP_RESERVED_121 = 0x79, | ||
135 | RS_OP_RESERVED_122 = 0x7a, | ||
136 | RS_OP_RESERVED_123 = 0x7b, | ||
137 | RS_OP_RESERVED_124 = 0x7c, | ||
138 | RS_OP_RESERVED_125 = 0x7d, | ||
139 | RS_OP_RESERVED_126 = 0x7e, | ||
140 | RS_OP_RESERVED_127 = 0x7f, | ||
141 | RS_OP_RESERVED_128 = 0x80, | ||
142 | RS_OP_RESERVED_129 = 0x81, | ||
143 | RS_OP_RESERVED_130 = 0x82, | ||
144 | RS_OP_RESERVED_131 = 0x83, | ||
145 | RS_OP_RESERVED_132 = 0x84, | ||
146 | RS_OP_RESERVED_133 = 0x85, | ||
147 | RS_OP_RESERVED_134 = 0x86, | ||
148 | RS_OP_RESERVED_135 = 0x87, | ||
149 | RS_OP_RESERVED_136 = 0x88, | ||
150 | RS_OP_RESERVED_137 = 0x89, | ||
151 | RS_OP_RESERVED_138 = 0x8a, | ||
152 | RS_OP_RESERVED_139 = 0x8b, | ||
153 | RS_OP_RESERVED_140 = 0x8c, | ||
154 | RS_OP_RESERVED_141 = 0x8d, | ||
155 | RS_OP_RESERVED_142 = 0x8e, | ||
156 | RS_OP_RESERVED_143 = 0x8f, | ||
157 | RS_OP_RESERVED_144 = 0x90, | ||
158 | RS_OP_RESERVED_145 = 0x91, | ||
159 | RS_OP_RESERVED_146 = 0x92, | ||
160 | RS_OP_RESERVED_147 = 0x93, | ||
161 | RS_OP_RESERVED_148 = 0x94, | ||
162 | RS_OP_RESERVED_149 = 0x95, | ||
163 | RS_OP_RESERVED_150 = 0x96, | ||
164 | RS_OP_RESERVED_151 = 0x97, | ||
165 | RS_OP_RESERVED_152 = 0x98, | ||
166 | RS_OP_RESERVED_153 = 0x99, | ||
167 | RS_OP_RESERVED_154 = 0x9a, | ||
168 | RS_OP_RESERVED_155 = 0x9b, | ||
169 | RS_OP_RESERVED_156 = 0x9c, | ||
170 | RS_OP_RESERVED_157 = 0x9d, | ||
171 | RS_OP_RESERVED_158 = 0x9e, | ||
172 | RS_OP_RESERVED_159 = 0x9f, | ||
173 | RS_OP_RESERVED_160 = 0xa0, | ||
174 | RS_OP_RESERVED_161 = 0xa1, | ||
175 | RS_OP_RESERVED_162 = 0xa2, | ||
176 | RS_OP_RESERVED_163 = 0xa3, | ||
177 | RS_OP_RESERVED_164 = 0xa4, | ||
178 | RS_OP_RESERVED_165 = 0xa5, | ||
179 | RS_OP_RESERVED_166 = 0xa6, | ||
180 | RS_OP_RESERVED_167 = 0xa7, | ||
181 | RS_OP_RESERVED_168 = 0xa8, | ||
182 | RS_OP_RESERVED_169 = 0xa9, | ||
183 | RS_OP_RESERVED_170 = 0xaa, | ||
184 | RS_OP_RESERVED_171 = 0xab, | ||
185 | RS_OP_RESERVED_172 = 0xac, | ||
186 | RS_OP_RESERVED_173 = 0xad, | ||
187 | RS_OP_RESERVED_174 = 0xae, | ||
188 | RS_OP_RESERVED_175 = 0xaf, | ||
189 | RS_OP_RESERVED_176 = 0xb0, | ||
190 | RS_OP_RESERVED_177 = 0xb1, | ||
191 | RS_OP_RESERVED_178 = 0xb2, | ||
192 | RS_OP_RESERVED_179 = 0xb3, | ||
193 | RS_OP_RESERVED_180 = 0xb4, | ||
194 | RS_OP_RESERVED_181 = 0xb5, | ||
195 | RS_OP_RESERVED_182 = 0xb6, | ||
196 | RS_OP_RESERVED_183 = 0xb7, | ||
197 | RS_OP_RESERVED_184 = 0xb8, | ||
198 | RS_OP_RESERVED_185 = 0xb9, | ||
199 | RS_OP_RESERVED_186 = 0xba, | ||
200 | RS_OP_RESERVED_187 = 0xbb, | ||
201 | RS_OP_RESERVED_188 = 0xbc, | ||
202 | RS_OP_RESERVED_189 = 0xbd, | ||
203 | RS_OP_RESERVED_190 = 0xbe, | ||
204 | RS_OP_RESERVED_191 = 0xbf, | ||
205 | RS_OP_RESERVED_192 = 0xc0, | ||
206 | RS_OP_RESERVED_193 = 0xc1, | ||
207 | RS_OP_RESERVED_194 = 0xc2, | ||
208 | RS_OP_RESERVED_195 = 0xc3, | ||
209 | RS_OP_RESERVED_196 = 0xc4, | ||
210 | RS_OP_RESERVED_197 = 0xc5, | ||
211 | RS_OP_RESERVED_198 = 0xc6, | ||
212 | RS_OP_RESERVED_199 = 0xc7, | ||
213 | RS_OP_RESERVED_200 = 0xc8, | ||
214 | RS_OP_RESERVED_201 = 0xc9, | ||
215 | RS_OP_RESERVED_202 = 0xca, | ||
216 | RS_OP_RESERVED_203 = 0xcb, | ||
217 | RS_OP_RESERVED_204 = 0xcc, | ||
218 | RS_OP_RESERVED_205 = 0xcd, | ||
219 | RS_OP_RESERVED_206 = 0xce, | ||
220 | RS_OP_RESERVED_207 = 0xcf, | ||
221 | RS_OP_RESERVED_208 = 0xd0, | ||
222 | RS_OP_RESERVED_209 = 0xd1, | ||
223 | RS_OP_RESERVED_210 = 0xd2, | ||
224 | RS_OP_RESERVED_211 = 0xd3, | ||
225 | RS_OP_RESERVED_212 = 0xd4, | ||
226 | RS_OP_RESERVED_213 = 0xd5, | ||
227 | RS_OP_RESERVED_214 = 0xd6, | ||
228 | RS_OP_RESERVED_215 = 0xd7, | ||
229 | RS_OP_RESERVED_216 = 0xd8, | ||
230 | RS_OP_RESERVED_217 = 0xd9, | ||
231 | RS_OP_RESERVED_218 = 0xda, | ||
232 | RS_OP_RESERVED_219 = 0xdb, | ||
233 | RS_OP_RESERVED_220 = 0xdc, | ||
234 | RS_OP_RESERVED_221 = 0xdd, | ||
235 | RS_OP_RESERVED_222 = 0xde, | ||
236 | RS_OP_RESERVED_223 = 0xdf, | ||
237 | RS_OP_RESERVED_224 = 0xe0, | ||
238 | RS_OP_RESERVED_225 = 0xe1, | ||
239 | RS_OP_RESERVED_226 = 0xe2, | ||
240 | RS_OP_RESERVED_227 = 0xe3, | ||
241 | RS_OP_RESERVED_228 = 0xe4, | ||
242 | RS_OP_RESERVED_229 = 0xe5, | ||
243 | RS_OP_RESERVED_230 = 0xe6, | ||
244 | RS_OP_RESERVED_231 = 0xe7, | ||
245 | RS_OP_RESERVED_232 = 0xe8, | ||
246 | RS_OP_RESERVED_233 = 0xe9, | ||
247 | RS_OP_RESERVED_234 = 0xea, | ||
248 | RS_OP_RESERVED_235 = 0xeb, | ||
249 | RS_OP_RESERVED_236 = 0xec, | ||
250 | RS_OP_RESERVED_237 = 0xed, | ||
251 | RS_OP_RESERVED_238 = 0xee, | ||
252 | RS_OP_RESERVED_239 = 0xef, | ||
253 | RS_OP_RESERVED_240 = 0xf0, | ||
254 | RS_OP_RESERVED_241 = 0xf1, | ||
255 | RS_OP_RESERVED_242 = 0xf2, | ||
256 | RS_OP_RESERVED_243 = 0xf3, | ||
257 | RS_OP_RESERVED_244 = 0xf4, | ||
258 | RS_OP_RESERVED_245 = 0xf5, | ||
259 | RS_OP_RESERVED_246 = 0xf6, | ||
260 | RS_OP_RESERVED_247 = 0xf7, | ||
261 | RS_OP_RESERVED_248 = 0xf8, | ||
262 | RS_OP_RESERVED_249 = 0xf9, | ||
263 | RS_OP_RESERVED_250 = 0xfa, | ||
264 | RS_OP_RESERVED_251 = 0xfb, | ||
265 | RS_OP_RESERVED_252 = 0xfc, | ||
266 | RS_OP_RESERVED_253 = 0xfd, | ||
267 | RS_OP_RESERVED_254 = 0xfe, | ||
268 | RS_OP_RESERVED_255 = 0xff | ||
269 | }; | ||
270 | /* END OF AUTOGENERATED CODE */ | ||
diff --git a/rsync/qrsync.cpp b/rsync/qrsync.cpp new file mode 100644 index 0000000..fe5f1bc --- a/dev/null +++ b/rsync/qrsync.cpp | |||
@@ -0,0 +1,110 @@ | |||
1 | #include "qrsync.h" | ||
2 | #include <stdio.h> | ||
3 | extern "C" { | ||
4 | #include "rsync.h" | ||
5 | } | ||
6 | #include <stdlib.h> | ||
7 | |||
8 | #include <qfile.h> | ||
9 | |||
10 | static const char *rdiffNewFile = "/tmp/rdiff/result"; | ||
11 | static size_t block_len = RS_DEFAULT_BLOCK_LEN; | ||
12 | static size_t strong_len = RS_DEFAULT_STRONG_LEN; | ||
13 | |||
14 | |||
15 | void QRsync::generateSignature( QString baseFile, QString sigFile ) | ||
16 | { | ||
17 | |||
18 | if ( QFile::exists( baseFile ) ) { | ||
19 | FILE *basis_file, *sig_file; | ||
20 | rs_result result; | ||
21 | |||
22 | basis_file = fopen( baseFile.latin1(), "rb" ); | ||
23 | sig_file = fopen( sigFile.latin1(), "wb" ); | ||
24 | |||
25 | result = rs_sig_file(basis_file, sig_file, block_len, strong_len, 0); | ||
26 | |||
27 | fclose( basis_file ); | ||
28 | fclose( sig_file ); | ||
29 | if (result != RS_DONE) | ||
30 | printf("error in rdiffGenSig: %d", result ); | ||
31 | } | ||
32 | } | ||
33 | |||
34 | |||
35 | void QRsync::generateDiff( QString baseFile, QString sigFile, QString deltaFile ) | ||
36 | { | ||
37 | if ( QFile::exists( baseFile ) && QFile::exists( sigFile ) ) { | ||
38 | FILE *sig_file, *new_file, *delta_file; | ||
39 | rs_result result; | ||
40 | rs_signature_t *sumset; | ||
41 | |||
42 | sig_file = fopen(sigFile.latin1(), "rb"); | ||
43 | new_file = fopen(baseFile.latin1(), "rb"); | ||
44 | delta_file = fopen(deltaFile.latin1(), "wb"); | ||
45 | |||
46 | result = rs_loadsig_file(sig_file, &sumset, 0); | ||
47 | if (result != RS_DONE) { | ||
48 | qDebug( "rdiffGenDiff: loading of sig file failed, error=%d", result ); | ||
49 | } else { | ||
50 | result = rs_build_hash_table(sumset); | ||
51 | if ( result != RS_DONE) { | ||
52 | qDebug( "rdiffGenDiff: building of hash table failed, error=%d", result ); | ||
53 | } else { | ||
54 | result = rs_delta_file(sumset, new_file, delta_file, 0); | ||
55 | if ( result != RS_DONE) { | ||
56 | qDebug( "rdiffGenDiff: writing of diff file failed, error=%d", result ); | ||
57 | } | ||
58 | } | ||
59 | } | ||
60 | |||
61 | if ( sumset ) | ||
62 | rs_free_sumset( sumset ); | ||
63 | fclose( new_file ); | ||
64 | fclose( delta_file ); | ||
65 | fclose( sig_file ); | ||
66 | |||
67 | } | ||
68 | } | ||
69 | |||
70 | void QRsync::applyDiff( QString baseFile, QString deltaFile ) | ||
71 | { | ||
72 | if ( QFile::exists( baseFile ) && QFile::exists( deltaFile ) ) { | ||
73 | FILE *basis_file, *delta_file, *new_file; | ||
74 | rs_result result; | ||
75 | |||
76 | basis_file = fopen(baseFile.latin1(), "rb"); | ||
77 | delta_file = fopen(deltaFile.latin1(), "rb"); | ||
78 | #ifdef Q_WS_WIN | ||
79 | new_file = fopen( (baseFile + ".new").latin1(), "wb" ); | ||
80 | #else | ||
81 | new_file = fopen(rdiffNewFile, "wb"); | ||
82 | #endif | ||
83 | |||
84 | result = rs_patch_file(basis_file, delta_file, new_file, 0); | ||
85 | |||
86 | fclose( basis_file ); | ||
87 | fclose( delta_file ); | ||
88 | fclose( new_file ); | ||
89 | |||
90 | if (result != RS_DONE) { | ||
91 | qDebug( "rdiffApplyDiff failed with result %d", result ); | ||
92 | return; | ||
93 | } | ||
94 | |||
95 | |||
96 | #ifdef Q_WS_WIN | ||
97 | QDir dir; | ||
98 | QFile backup = baseFile + "~"; | ||
99 | dir.rename( baseFile, backup ); | ||
100 | dir.rename( (baseFile + ".new"), baseFile ); | ||
101 | dir.remove( backup ); | ||
102 | #else | ||
103 | QString cmd = "mv "; | ||
104 | cmd += rdiffNewFile; | ||
105 | cmd += " " + baseFile; | ||
106 | system( cmd.latin1() ); | ||
107 | #endif | ||
108 | } | ||
109 | |||
110 | } | ||
diff --git a/rsync/qrsync.h b/rsync/qrsync.h new file mode 100644 index 0000000..293c0ff --- a/dev/null +++ b/rsync/qrsync.h | |||
@@ -0,0 +1,18 @@ | |||
1 | /***** | ||
2 | */ | ||
3 | |||
4 | #ifndef QRSYNC_H | ||
5 | #define QRSYNC_H | ||
6 | |||
7 | #include <qstring.h> | ||
8 | |||
9 | class QRsync | ||
10 | { | ||
11 | public: | ||
12 | static void generateSignature( QString baseFile, QString sigFile ); | ||
13 | static void generateDiff( QString baseFile, QString sigFile, QString diffFile ); | ||
14 | static void applyDiff( QString baseFile, QString diffFile ); | ||
15 | }; | ||
16 | |||
17 | |||
18 | #endif | ||
diff --git a/rsync/rdiff.c b/rsync/rdiff.c new file mode 100644 index 0000000..e08095a --- a/dev/null +++ b/rsync/rdiff.c | |||
@@ -0,0 +1,358 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Lesser General Public License as published by | ||
10 | * the Free Software Foundation; either version 2.1 of the License, or | ||
11 | * (at your option) 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 Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | | .. after a year and a day, mourning is | ||
25 | | dangerous to the survivor and troublesome | ||
26 | | to the dead. | ||
27 | | -- Harold Bloom | ||
28 | */ | ||
29 | |||
30 | /* | ||
31 | * rdiff.c -- Command-line network-delta tool. | ||
32 | * | ||
33 | * TODO: Add a -z option to gzip/gunzip patches. This would be | ||
34 | * somewhat useful, but more importantly a good test of the streaming | ||
35 | * API. Also add -I for bzip2. | ||
36 | * | ||
37 | * If built with debug support and we have mcheck, then turn it on. | ||
38 | * (Optionally?) | ||
39 | */ | ||
40 | |||
41 | #include <config_rsync.h> | ||
42 | |||
43 | #include <stdlib.h> | ||
44 | #include <stdio.h> | ||
45 | #include <fcntl.h> | ||
46 | #include <popt.h> | ||
47 | |||
48 | #ifdef HAVE_ZLIB_H | ||
49 | #include <zlib.h> | ||
50 | #endif | ||
51 | |||
52 | #ifdef HAVE_BZLIB_H | ||
53 | #include <bzlib.h> | ||
54 | #endif | ||
55 | |||
56 | #include "rsync.h" | ||
57 | #include "fileutil.h" | ||
58 | #include "util.h" | ||
59 | #include "trace.h" | ||
60 | #include "isprefix.h" | ||
61 | |||
62 | |||
63 | #define PROGRAM "rdiff" | ||
64 | |||
65 | static size_t block_len = RS_DEFAULT_BLOCK_LEN; | ||
66 | static size_t strong_len = RS_DEFAULT_STRONG_LEN; | ||
67 | |||
68 | static int show_stats = 0; | ||
69 | |||
70 | static int bzip2_level = 0; | ||
71 | static int gzip_level = 0; | ||
72 | |||
73 | |||
74 | enum { | ||
75 | OPT_GZIP = 1069, OPT_BZIP2 | ||
76 | }; | ||
77 | |||
78 | extern int rs_roll_paranoia; | ||
79 | |||
80 | const struct poptOption opts[] = { | ||
81 | { "verbose", 'v', POPT_ARG_NONE, 0, 'v' }, | ||
82 | { "version", 'V', POPT_ARG_NONE, 0, 'V' }, | ||
83 | { "input-size", 'I', POPT_ARG_INT, &rs_inbuflen }, | ||
84 | { "output-size", 'O', POPT_ARG_INT, &rs_outbuflen }, | ||
85 | { "help", '?', POPT_ARG_NONE, 0, 'h' }, | ||
86 | { 0, 'h', POPT_ARG_NONE, 0, 'h' }, | ||
87 | { "block-size", 'b', POPT_ARG_INT, &block_len }, | ||
88 | { "sum-size", 'S', POPT_ARG_INT, &strong_len }, | ||
89 | { "statistics", 's', POPT_ARG_NONE, &show_stats }, | ||
90 | { "stats", 0, POPT_ARG_NONE, &show_stats }, | ||
91 | { "gzip", 0, POPT_ARG_NONE, 0, OPT_GZIP }, | ||
92 | { "bzip2", 0, POPT_ARG_NONE, 0, OPT_BZIP2 }, | ||
93 | { "paranoia", 0, POPT_ARG_NONE, &rs_roll_paranoia }, | ||
94 | { 0 } | ||
95 | }; | ||
96 | |||
97 | |||
98 | static void rdiff_usage(const char *error) | ||
99 | { | ||
100 | fprintf(stderr, "%s\n" | ||
101 | "Try `%s --help' for more information.\n", | ||
102 | error, PROGRAM); | ||
103 | } | ||
104 | |||
105 | |||
106 | static void rdiff_no_more_args(poptContext opcon) | ||
107 | { | ||
108 | if (poptGetArg(opcon)) { | ||
109 | rdiff_usage("rdiff: too many arguments"); | ||
110 | exit(RS_SYNTAX_ERROR); | ||
111 | } | ||
112 | } | ||
113 | |||
114 | |||
115 | static void bad_option(poptContext opcon, int error) | ||
116 | { | ||
117 | char msgbuf[1000]; | ||
118 | |||
119 | snprintf(msgbuf, sizeof msgbuf-1, "%s: %s: %s", | ||
120 | PROGRAM, poptStrerror(error), poptBadOption(opcon, 0)); | ||
121 | rdiff_usage(msgbuf); | ||
122 | |||
123 | exit(RS_SYNTAX_ERROR); | ||
124 | } | ||
125 | |||
126 | |||
127 | static void help(void) { | ||
128 | printf("Usage: rdiff [OPTIONS] signature [BASIS [SIGNATURE]]\n" | ||
129 | " [OPTIONS] delta SIGNATURE [NEWFILE [DELTA]]\n" | ||
130 | " [OPTIONS] patch BASIS [DELTA [NEWFILE]]\n" | ||
131 | "\n" | ||
132 | "Options:\n" | ||
133 | " -v, --verbose Trace internal processing\n" | ||
134 | " -V, --version Show program version\n" | ||
135 | " -?, --help Show this help message\n" | ||
136 | " -s, --statistics Show performance statistics\n" | ||
137 | "Delta-encoding options:\n" | ||
138 | " -b, --block-size=BYTES Signature block size\n" | ||
139 | " -S, --sum-size=BYTES Set signature strength\n" | ||
140 | " --paranoia Verify all rolling checksums\n" | ||
141 | "IO options:\n" | ||
142 | " -I, --input-size=BYTES Input buffer size\n" | ||
143 | " -O, --output-size=BYTES Output buffer size\n" | ||
144 | " -z, --gzip[=LEVEL] gzip-compress deltas\n" | ||
145 | " -i, --bzip2[=LEVEL] bzip2-compress deltas\n" | ||
146 | ); | ||
147 | } | ||
148 | |||
149 | |||
150 | static void rdiff_show_version(void) | ||
151 | { | ||
152 | /* | ||
153 | * This little declaration is dedicated to Stephen Kapp and Reaper | ||
154 | * Technologies, who by all appearances redistributed a modified but | ||
155 | * unacknowledged version of GNU Keyring in violation of the licence | ||
156 | * and all laws of politeness and good taste. | ||
157 | */ | ||
158 | char const *bzlib = "", *zlib = "", *trace = ""; | ||
159 | |||
160 | #ifdef HAVE_LIBZ | ||
161 | zlib = ", gzip"; | ||
162 | #endif | ||
163 | |||
164 | #ifdef HAVE_LIBBZ2 | ||
165 | bzlib = ", bzip2"; | ||
166 | #endif | ||
167 | |||
168 | #ifndef DO_RS_TRACE | ||
169 | trace = ", trace disabled"; | ||
170 | #endif | ||
171 | |||
172 | printf("rdiff (%s) [%s]\n" | ||
173 | "Copyright (C) 1997-2001 by Martin Pool, Andrew Tridgell and others.\n" | ||
174 | "http://rproxy.samba.org/\n" | ||
175 | "Capabilities: %d bit files%s%s%s\n" | ||
176 | "\n" | ||
177 | "librsync comes with NO WARRANTY, to the extent permitted by law.\n" | ||
178 | "You may redistribute copies of librsync under the terms of the GNU\n" | ||
179 | "Lesser General Public License. For more information about these\n" | ||
180 | "matters, see the files named COPYING.\n", | ||
181 | rs_librsync_version, RS_CANONICAL_HOST, | ||
182 | 8 * sizeof(rs_long_t), zlib, bzlib, trace); | ||
183 | } | ||
184 | |||
185 | |||
186 | |||
187 | static void rdiff_options(poptContext opcon) | ||
188 | { | ||
189 | int c; | ||
190 | char const *a; | ||
191 | |||
192 | while ((c = poptGetNextOpt(opcon)) != -1) { | ||
193 | switch (c) { | ||
194 | case 'h': | ||
195 | help(); | ||
196 | exit(RS_DONE); | ||
197 | case 'V': | ||
198 | rdiff_show_version(); | ||
199 | exit(RS_DONE); | ||
200 | case 'v': | ||
201 | if (!rs_supports_trace()) { | ||
202 | rs_error("library does not support trace"); | ||
203 | } | ||
204 | rs_trace_set_level(RS_LOG_DEBUG); | ||
205 | break; | ||
206 | |||
207 | case OPT_GZIP: | ||
208 | case OPT_BZIP2: | ||
209 | if ((a = poptGetOptArg(opcon))) { | ||
210 | int l = atoi(a); | ||
211 | if (c == OPT_GZIP) | ||
212 | gzip_level = l; | ||
213 | else | ||
214 | bzip2_level = l; | ||
215 | } else { | ||
216 | if (c == OPT_GZIP) | ||
217 | gzip_level = -1; /* library default */ | ||
218 | else | ||
219 | bzip2_level = 9; /* demand the best */ | ||
220 | } | ||
221 | rs_error("sorry, compression is not really implemented yet"); | ||
222 | exit(RS_UNIMPLEMENTED); | ||
223 | |||
224 | default: | ||
225 | bad_option(opcon, c); | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | |||
230 | |||
231 | /** | ||
232 | * Generate signature from remaining command line arguments. | ||
233 | */ | ||
234 | static rs_result rdiff_sig(poptContext opcon) | ||
235 | { | ||
236 | FILE *basis_file, *sig_file; | ||
237 | rs_stats_t stats; | ||
238 | rs_result result; | ||
239 | |||
240 | basis_file = rs_file_open(poptGetArg(opcon), "rb"); | ||
241 | sig_file = rs_file_open(poptGetArg(opcon), "wb"); | ||
242 | |||
243 | rdiff_no_more_args(opcon); | ||
244 | |||
245 | result = rs_sig_file(basis_file, sig_file, block_len, strong_len, &stats); | ||
246 | if (result != RS_DONE) | ||
247 | return result; | ||
248 | |||
249 | if (show_stats) | ||
250 | rs_log_stats(&stats); | ||
251 | |||
252 | return result; | ||
253 | } | ||
254 | |||
255 | |||
256 | static rs_result rdiff_delta(poptContext opcon) | ||
257 | { | ||
258 | FILE *sig_file, *new_file, *delta_file; | ||
259 | char const *sig_name; | ||
260 | rs_result result; | ||
261 | rs_signature_t *sumset; | ||
262 | rs_stats_t stats; | ||
263 | |||
264 | if (!(sig_name = poptGetArg(opcon))) { | ||
265 | rdiff_usage("Usage for delta: " | ||
266 | "rdiff [OPTIONS] delta SIGNATURE [NEWFILE [DELTA]]"); | ||
267 | return RS_SYNTAX_ERROR; | ||
268 | } | ||
269 | |||
270 | sig_file = rs_file_open(sig_name, "rb"); | ||
271 | new_file = rs_file_open(poptGetArg(opcon), "rb"); | ||
272 | delta_file = rs_file_open(poptGetArg(opcon), "wb"); | ||
273 | |||
274 | rdiff_no_more_args(opcon); | ||
275 | |||
276 | result = rs_loadsig_file(sig_file, &sumset, &stats); | ||
277 | if (result != RS_DONE) | ||
278 | return result; | ||
279 | |||
280 | if (show_stats) | ||
281 | rs_log_stats(&stats); | ||
282 | |||
283 | if ((result = rs_build_hash_table(sumset)) != RS_DONE) | ||
284 | return result; | ||
285 | |||
286 | result = rs_delta_file(sumset, new_file, delta_file, &stats); | ||
287 | |||
288 | if (show_stats) | ||
289 | rs_log_stats(&stats); | ||
290 | |||
291 | return result; | ||
292 | } | ||
293 | |||
294 | |||
295 | |||
296 | static rs_result rdiff_patch(poptContext opcon) | ||
297 | { | ||
298 | /* patch BASIS [DELTA [NEWFILE]] */ | ||
299 | FILE *basis_file, *delta_file, *new_file; | ||
300 | char const *basis_name; | ||
301 | rs_stats_t stats; | ||
302 | rs_result result; | ||
303 | |||
304 | if (!(basis_name = poptGetArg(opcon))) { | ||
305 | rdiff_usage("Usage for patch: " | ||
306 | "rdiff [OPTIONS] patch BASIS [DELTA [NEW]]"); | ||
307 | return RS_SYNTAX_ERROR; | ||
308 | } | ||
309 | |||
310 | basis_file = rs_file_open(basis_name, "rb"); | ||
311 | delta_file = rs_file_open(poptGetArg(opcon), "rb"); | ||
312 | new_file = rs_file_open(poptGetArg(opcon), "wb"); | ||
313 | |||
314 | rdiff_no_more_args(opcon); | ||
315 | |||
316 | result = rs_patch_file(basis_file, delta_file, new_file, &stats); | ||
317 | |||
318 | if (show_stats) | ||
319 | rs_log_stats(&stats); | ||
320 | |||
321 | return result; | ||
322 | } | ||
323 | |||
324 | |||
325 | |||
326 | static rs_result rdiff_action(poptContext opcon) | ||
327 | { | ||
328 | const char *action; | ||
329 | |||
330 | action = poptGetArg(opcon); | ||
331 | if (!action) | ||
332 | ; | ||
333 | else if (isprefix(action, "signature")) | ||
334 | return rdiff_sig(opcon); | ||
335 | else if (isprefix(action, "delta")) | ||
336 | return rdiff_delta(opcon); | ||
337 | else if (isprefix(action, "patch")) | ||
338 | return rdiff_patch(opcon); | ||
339 | |||
340 | rdiff_usage("rdiff: You must specify an action: `signature', `delta', or `patch'."); | ||
341 | return RS_SYNTAX_ERROR; | ||
342 | } | ||
343 | |||
344 | |||
345 | int main(const int argc, const char *argv[]) | ||
346 | { | ||
347 | poptContext opcon; | ||
348 | rs_result result; | ||
349 | |||
350 | opcon = poptGetContext(PROGRAM, argc, argv, opts, 0); | ||
351 | rdiff_options(opcon); | ||
352 | result = rdiff_action(opcon); | ||
353 | |||
354 | if (result != RS_DONE) | ||
355 | rs_log(RS_LOG_ERR|RS_LOG_NONAME, "%s", rs_strerror(result)); | ||
356 | |||
357 | return result; | ||
358 | } | ||
diff --git a/rsync/readsums.c b/rsync/readsums.c new file mode 100644 index 0000000..21b5ecd --- a/dev/null +++ b/rsync/readsums.c | |||
@@ -0,0 +1,214 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * Copyright (C) 1999 by Andrew Tridgell <tridge@samba.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU Lesser General Public License | ||
11 | * as published by the Free Software Foundation; either version 2.1 of | ||
12 | * the License, or (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public | ||
20 | * License along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | |||
25 | /* | ||
26 | * readsums.c -- Load signatures from a file into an ::rs_signature_t. | ||
27 | */ | ||
28 | |||
29 | #include <config_rsync.h> | ||
30 | |||
31 | #include <assert.h> | ||
32 | #include <stdlib.h> | ||
33 | #include <stdio.h> | ||
34 | #include <string.h> | ||
35 | |||
36 | #include "rsync.h" | ||
37 | #include "sumset.h" | ||
38 | #include "job.h" | ||
39 | #include "trace.h" | ||
40 | #include "netint.h" | ||
41 | #include "protocol.h" | ||
42 | #include "util.h" | ||
43 | #include "stream.h" | ||
44 | |||
45 | |||
46 | static rs_result rs_loadsig_s_weak(rs_job_t *job); | ||
47 | static rs_result rs_loadsig_s_strong(rs_job_t *job); | ||
48 | |||
49 | |||
50 | |||
51 | /** | ||
52 | * Add a just-read-in checksum pair to the signature block. | ||
53 | */ | ||
54 | static rs_result rs_loadsig_add_sum(rs_job_t *job, rs_strong_sum_t *strong) | ||
55 | { | ||
56 | size_t new_size; | ||
57 | rs_signature_t *sig = job->signature; | ||
58 | rs_block_sig_t *asignature; | ||
59 | |||
60 | sig->count++; | ||
61 | new_size = sig->count * sizeof(rs_block_sig_t); | ||
62 | |||
63 | sig->block_sigs = realloc(sig->block_sigs, new_size); | ||
64 | |||
65 | if (sig->block_sigs == NULL) { | ||
66 | return RS_MEM_ERROR; | ||
67 | } | ||
68 | asignature = &(sig->block_sigs[sig->count - 1]); | ||
69 | |||
70 | asignature->weak_sum = job->weak_sig; | ||
71 | asignature->i = sig->count; | ||
72 | |||
73 | memcpy(asignature->strong_sum, strong, sig->strong_sum_len); | ||
74 | |||
75 | if (rs_trace_enabled()) { | ||
76 | char hexbuf[RS_MD4_LENGTH * 2 + 2]; | ||
77 | rs_hexify(hexbuf, strong, sig->strong_sum_len); | ||
78 | |||
79 | rs_trace("read in checksum: weak=%#x, strong=%s", asignature->weak_sum, | ||
80 | hexbuf); | ||
81 | } | ||
82 | |||
83 | job->stats.sig_blocks++; | ||
84 | |||
85 | return RS_RUNNING; | ||
86 | } | ||
87 | |||
88 | |||
89 | static rs_result rs_loadsig_s_weak(rs_job_t *job) | ||
90 | { | ||
91 | int l; | ||
92 | rs_result result; | ||
93 | |||
94 | result = rs_suck_n4(job, &l); | ||
95 | if (result == RS_DONE) | ||
96 | ; | ||
97 | else if (result == RS_INPUT_ENDED) /* ending here is OK */ | ||
98 | return RS_DONE; | ||
99 | else | ||
100 | return result; | ||
101 | |||
102 | job->weak_sig = l; | ||
103 | |||
104 | job->statefn = rs_loadsig_s_strong; | ||
105 | |||
106 | return RS_RUNNING; | ||
107 | } | ||
108 | |||
109 | |||
110 | |||
111 | static rs_result rs_loadsig_s_strong(rs_job_t *job) | ||
112 | { | ||
113 | rs_result result; | ||
114 | rs_strong_sum_t *strongsum; | ||
115 | |||
116 | result = rs_scoop_read(job, job->signature->strong_sum_len, | ||
117 | (void **) &strongsum); | ||
118 | if (result != RS_DONE) return result; | ||
119 | |||
120 | job->statefn = rs_loadsig_s_weak; | ||
121 | |||
122 | return rs_loadsig_add_sum(job, strongsum); | ||
123 | } | ||
124 | |||
125 | |||
126 | |||
127 | static rs_result rs_loadsig_s_stronglen(rs_job_t *job) | ||
128 | { | ||
129 | int l; | ||
130 | rs_result result; | ||
131 | |||
132 | if ((result = rs_suck_n4(job, &l)) != RS_DONE) | ||
133 | return result; | ||
134 | job->strong_sum_len = l; | ||
135 | |||
136 | if (l < 0 || l > RS_MD4_LENGTH) { | ||
137 | rs_error("strong sum length %d is implausible", l); | ||
138 | return RS_CORRUPT; | ||
139 | } | ||
140 | |||
141 | job->signature->block_len = job->block_len; | ||
142 | job->signature->strong_sum_len = job->strong_sum_len; | ||
143 | |||
144 | rs_trace("allocated sigset_t (strong_sum_len=%d, block_len=%d)", | ||
145 | (int) job->strong_sum_len, (int) job->block_len); | ||
146 | |||
147 | job->statefn = rs_loadsig_s_weak; | ||
148 | |||
149 | return RS_RUNNING; | ||
150 | } | ||
151 | |||
152 | |||
153 | static rs_result rs_loadsig_s_blocklen(rs_job_t *job) | ||
154 | { | ||
155 | int l; | ||
156 | rs_result result; | ||
157 | |||
158 | if ((result = rs_suck_n4(job, &l)) != RS_DONE) | ||
159 | return result; | ||
160 | job->block_len = l; | ||
161 | |||
162 | if (job->block_len < 1) { | ||
163 | rs_error("block length of %d is bogus", (int) job->block_len); | ||
164 | return RS_CORRUPT; | ||
165 | } | ||
166 | |||
167 | job->statefn = rs_loadsig_s_stronglen; | ||
168 | job->stats.block_len = job->block_len; | ||
169 | |||
170 | return RS_RUNNING; | ||
171 | } | ||
172 | |||
173 | |||
174 | static rs_result rs_loadsig_s_magic(rs_job_t *job) | ||
175 | { | ||
176 | int l; | ||
177 | rs_result result; | ||
178 | |||
179 | if ((result = rs_suck_n4(job, &l)) != RS_DONE) { | ||
180 | return result; | ||
181 | } else if (l != RS_SIG_MAGIC) { | ||
182 | rs_error("wrong magic number %#10x for signature", l); | ||
183 | return RS_BAD_MAGIC; | ||
184 | } else { | ||
185 | rs_trace("got signature magic %#10x", l); | ||
186 | } | ||
187 | |||
188 | job->statefn = rs_loadsig_s_blocklen; | ||
189 | |||
190 | return RS_RUNNING; | ||
191 | } | ||
192 | |||
193 | |||
194 | /** | ||
195 | * \brief Read a signature from a file into an ::rs_signature_t structure | ||
196 | * in memory. | ||
197 | * | ||
198 | * Once there, it can be used to generate a delta to a newer version of | ||
199 | * the file. | ||
200 | * | ||
201 | * \note After loading the signatures, you must call | ||
202 | * rs_build_hash_table() before you can use them. | ||
203 | */ | ||
204 | rs_job_t *rs_loadsig_begin(rs_signature_t **signature) | ||
205 | { | ||
206 | rs_job_t *job; | ||
207 | |||
208 | job = rs_job_new("loadsig", rs_loadsig_s_magic); | ||
209 | *signature = job->signature = rs_alloc_struct(rs_signature_t); | ||
210 | job->signature->count = 0; | ||
211 | |||
212 | return job; | ||
213 | } | ||
214 | |||
diff --git a/rsync/rsync.h b/rsync/rsync.h new file mode 100644 index 0000000..a80a368 --- a/dev/null +++ b/rsync/rsync.h | |||
@@ -0,0 +1,388 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Lesser General Public License as published by | ||
10 | * the Free Software Foundation; either version 2.1 of the License, or | ||
11 | * (at your option) 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 Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | | You should never wear your best | ||
25 | | trousers when you go out to fight for | ||
26 | | freedom and liberty. | ||
27 | | -- Henrik Ibsen | ||
28 | */ | ||
29 | |||
30 | |||
31 | /** \file rsync.h | ||
32 | * | ||
33 | * \brief Main public interface to librsync. | ||
34 | * \author Martin Pool <mbp@samba.org> | ||
35 | * \version librsync-0.9.1 | ||
36 | * | ||
37 | * $Id$ | ||
38 | * | ||
39 | * See \ref intro for an introduction to use of this library. | ||
40 | */ | ||
41 | |||
42 | #include <sys/types.h> | ||
43 | |||
44 | extern char const rs_librsync_version[]; | ||
45 | extern char const rs_licence_string[]; | ||
46 | |||
47 | |||
48 | /** | ||
49 | * \brief A long integer type that can handle the largest file | ||
50 | * offsets. | ||
51 | * | ||
52 | * Perhaps this might have to be configured to be 'long long', 'long', | ||
53 | * or something else depending on the platform. | ||
54 | */ | ||
55 | #if SIZEOF_LONG_LONG | ||
56 | typedef signed long long rs_long_t; | ||
57 | #else | ||
58 | typedef long rs_long_t; | ||
59 | #endif | ||
60 | |||
61 | |||
62 | /** | ||
63 | * \brief Log severity levels. | ||
64 | * | ||
65 | * These are the same as syslog, at least in glibc. | ||
66 | * | ||
67 | * \sa rs_trace_set_level() | ||
68 | */ | ||
69 | typedef enum { | ||
70 | RS_LOG_EMERG = 0, /**< System is unusable */ | ||
71 | RS_LOG_ALERT = 1, /**< Action must be taken immediately */ | ||
72 | RS_LOG_CRIT = 2, /**< Critical conditions */ | ||
73 | RS_LOG_ERR = 3, /**< Error conditions */ | ||
74 | RS_LOG_WARNING = 4, /**< Warning conditions */ | ||
75 | RS_LOG_NOTICE = 5, /**< Normal but significant condition */ | ||
76 | RS_LOG_INFO = 6, /**< Informational */ | ||
77 | RS_LOG_DEBUG = 7 /**< Debug-level messages */ | ||
78 | } rs_loglevel; | ||
79 | |||
80 | |||
81 | |||
82 | /** | ||
83 | * \typedef rs_trace_fn_t | ||
84 | * \brief Callback to write out log messages. | ||
85 | * \param level a syslog level. | ||
86 | * \param msg message to be logged. | ||
87 | */ | ||
88 | typedef void rs_trace_fn_t(int level, char const *msg); | ||
89 | |||
90 | void rs_trace_set_level(rs_loglevel level); | ||
91 | |||
92 | /** Set trace callback. */ | ||
93 | void rs_trace_to(rs_trace_fn_t *); | ||
94 | |||
95 | /** Default trace callback that writes to stderr. Implements | ||
96 | * ::rs_trace_fn_t, and may be passed to rs_trace_to(). */ | ||
97 | void rs_trace_stderr(int level, char const *msg); | ||
98 | |||
99 | /** Check whether the library was compiled with debugging trace | ||
100 | * suport. */ | ||
101 | int rs_supports_trace(void); | ||
102 | |||
103 | |||
104 | |||
105 | /** | ||
106 | * Convert FROM_LEN bytes at FROM_BUF into a hex representation in | ||
107 | * TO_BUF, which must be twice as long plus one byte for the null | ||
108 | * terminator. | ||
109 | */ | ||
110 | void rs_hexify(char *to_buf, void const *from_buf, int from_len); | ||
111 | |||
112 | /** | ||
113 | * Decode a base64 buffer in place. \return the number of binary | ||
114 | * bytes. | ||
115 | */ | ||
116 | size_t rs_unbase64(char *s); | ||
117 | |||
118 | |||
119 | /** | ||
120 | * Encode a buffer as base64. | ||
121 | */ | ||
122 | void rs_base64(unsigned char const *buf, int n, char *out); | ||
123 | |||
124 | |||
125 | /** | ||
126 | * \brief Return codes from nonblocking rsync operations. | ||
127 | */ | ||
128 | typedef enum { | ||
129 | RS_DONE = 0,/**< Completed successfully. */ | ||
130 | RS_BLOCKED = 1, /**< Blocked waiting for more data. */ | ||
131 | RS_RUNNING = 2, /**< Not yet finished or blocked. | ||
132 | * This value should never be returned | ||
133 | * to the caller. */ | ||
134 | |||
135 | RS_TEST_SKIPPED = 77, /**< Test neither passed or failed. */ | ||
136 | |||
137 | RS_IO_ERROR =100, /**< Error in file or network IO. */ | ||
138 | RS_SYNTAX_ERROR = 101, /**< Command line syntax error. */ | ||
139 | RS_MEM_ERROR =102, /**< Out of memory. */ | ||
140 | RS_INPUT_ENDED = 103,/**< End of input file, possibly | ||
141 | unexpected. */ | ||
142 | RS_BAD_MAGIC = 104, /**< Bad magic number at start of | ||
143 | stream. Probably not a librsync | ||
144 | file, or possibly the wrong kind of | ||
145 | file or from an incompatible | ||
146 | library version. */ | ||
147 | RS_UNIMPLEMENTED = 105, /**< Author is lazy. */ | ||
148 | RS_CORRUPT = 106, /**< Unbelievable value in stream. */ | ||
149 | RS_INTERNAL_ERROR = 107, /**< Probably a library bug. */ | ||
150 | RS_PARAM_ERROR = 108 /**< Bad value passed in to library, | ||
151 | * probably an application bug. */ | ||
152 | } rs_result; | ||
153 | |||
154 | |||
155 | |||
156 | /** | ||
157 | * Return an English description of a ::rs_result value. | ||
158 | */ | ||
159 | char const *rs_strerror(rs_result r); | ||
160 | |||
161 | |||
162 | /** | ||
163 | * \brief Performance statistics from a librsync encoding or decoding | ||
164 | * operation. | ||
165 | * | ||
166 | * \sa rs_format_stats(), rs_log_stats() | ||
167 | */ | ||
168 | typedef struct rs_stats { | ||
169 | char const *op; /**< Human-readable name of current | ||
170 | * operation. For example, "delta". */ | ||
171 | int lit_cmds; /**< Number of literal commands. */ | ||
172 | rs_long_t lit_bytes; /**< Number of literal bytes. */ | ||
173 | rs_long_t lit_cmdbytes; /**< Number of bytes used in literal | ||
174 | * command headers. */ | ||
175 | |||
176 | rs_long_t copy_cmds, copy_bytes, copy_cmdbytes; | ||
177 | rs_long_t sig_cmds, sig_bytes; | ||
178 | int false_matches; | ||
179 | |||
180 | rs_long_t sig_blocks; /**< Number of blocks described by the | ||
181 | signature. */ | ||
182 | |||
183 | size_t block_len; | ||
184 | |||
185 | rs_long_t in_bytes; /**< Total bytes read from input. */ | ||
186 | rs_long_t out_bytes; /**< Total bytes written to output. */ | ||
187 | } rs_stats_t; | ||
188 | |||
189 | |||
190 | /** \typedef struct rs_mdfour rs_mdfour_t | ||
191 | * | ||
192 | * \brief MD4 message-digest accumulator. | ||
193 | * | ||
194 | * \sa rs_mdfour(), rs_mdfour_begin(), rs_mdfour_update(), | ||
195 | * rs_mdfour_result() | ||
196 | */ | ||
197 | typedef struct rs_mdfour { | ||
198 | int A, B, C, D; | ||
199 | int totalN; | ||
200 | int tail_len; | ||
201 | unsigned char tail[64]; | ||
202 | } rs_mdfour_t; | ||
203 | |||
204 | #define RS_MD4_LENGTH 16 | ||
205 | |||
206 | typedef unsigned int rs_weak_sum_t; | ||
207 | typedef unsigned char rs_strong_sum_t[RS_MD4_LENGTH]; | ||
208 | |||
209 | void rs_mdfour(unsigned char *out, void const *in, size_t); | ||
210 | void rs_mdfour_begin(/* @out@ */ rs_mdfour_t * md); | ||
211 | void rs_mdfour_update(rs_mdfour_t * md, void const *, | ||
212 | size_t n); | ||
213 | void rs_mdfour_result(rs_mdfour_t * md, unsigned char *out); | ||
214 | |||
215 | char *rs_format_stats(rs_stats_t const *, char *, size_t); | ||
216 | |||
217 | int rs_log_stats(rs_stats_t const *stats); | ||
218 | |||
219 | |||
220 | typedef struct rs_signature rs_signature_t; | ||
221 | |||
222 | void rs_free_sumset(rs_signature_t *); | ||
223 | void rs_sumset_dump(rs_signature_t const *); | ||
224 | |||
225 | |||
226 | /** | ||
227 | * Stream through which the calling application feeds data to and from the | ||
228 | * library. | ||
229 | * | ||
230 | * On each call to rs_job_iter, the caller can make available | ||
231 | * | ||
232 | * - avail_in bytes of input data at next_in | ||
233 | * - avail_out bytes of output space at next_out | ||
234 | * - some of both | ||
235 | * | ||
236 | * Buffers must be allocated and passed in by the caller. This | ||
237 | * routine never allocates, reallocates or frees buffers. | ||
238 | * | ||
239 | * Pay attention to the meaning of the returned pointer and length | ||
240 | * values. They do \b not indicate the location and amount of | ||
241 | * returned data. Rather, if \p *out_ptr was originally set to \p | ||
242 | * out_buf, then the output data begins at \p out_buf, and has length | ||
243 | * \p *out_ptr - \p out_buf. | ||
244 | * | ||
245 | * Note also that if \p *avail_in is nonzero on return, then not all of | ||
246 | * the input data has been consumed. The caller should either provide | ||
247 | * more output buffer space and call rs_work() again passing the same | ||
248 | * \p next_in and \p avail_in, or put the remaining input data into some | ||
249 | * persistent buffer and call rs_work() with it again when there is | ||
250 | * more output space. | ||
251 | * | ||
252 | * \param next_in References a pointer which on entry should point to | ||
253 | * the start of the data to be encoded. Updated to point to the byte | ||
254 | * after the last one consumed. | ||
255 | * | ||
256 | * \param avail_in References the length of available input. Updated to | ||
257 | * be the number of unused data bytes, which will be zero if all the | ||
258 | * input was consumed. May be zero if there is no new input, but the | ||
259 | * caller just wants to drain output. | ||
260 | * | ||
261 | * \param next_out References a pointer which on entry points to the | ||
262 | * start of the output buffer. Updated to point to the byte after the | ||
263 | * last one filled. | ||
264 | * | ||
265 | * \param avail_out References the size of available output buffer. | ||
266 | * Updated to the size of unused output buffer. | ||
267 | * | ||
268 | * \return The ::rs_result that caused iteration to stop. | ||
269 | * | ||
270 | * \sa rs_buffers_t | ||
271 | * \sa \ref api_buffers | ||
272 | */ | ||
273 | struct rs_buffers_s { | ||
274 | char *next_in; /**< Next input byte */ | ||
275 | size_t avail_in; /**< Number of bytes available at next_in */ | ||
276 | int eof_in; /**< True if there is no more data | ||
277 | * after this. */ | ||
278 | |||
279 | char *next_out; /**< Next output byte should be put there */ | ||
280 | size_t avail_out; /**< Remaining free space at next_out */ | ||
281 | }; | ||
282 | |||
283 | /** | ||
284 | * Stream through which the calling application feeds data to and from the | ||
285 | * library. | ||
286 | * | ||
287 | * \sa struct rs_buffers_s | ||
288 | * \sa \ref api_buffers | ||
289 | */ | ||
290 | typedef struct rs_buffers_s rs_buffers_t; | ||
291 | |||
292 | /** Default length of strong signatures, in bytes. The MD4 checksum | ||
293 | * is truncated to this size. */ | ||
294 | #define RS_DEFAULT_STRONG_LEN 8 | ||
295 | |||
296 | /** Default block length, if not determined by any other factors. */ | ||
297 | #define RS_DEFAULT_BLOCK_LEN 2048 | ||
298 | |||
299 | |||
300 | /** \typedef struct rs_job rs_job_t | ||
301 | * | ||
302 | * \brief Job of work to be done. | ||
303 | * | ||
304 | * Created by functions such as rs_sig_begin(), and then iterated | ||
305 | * over by rs_job_iter(). */ | ||
306 | typedef struct rs_job rs_job_t; | ||
307 | |||
308 | /** | ||
309 | * Bitmask values that may be passed to the options parameter of | ||
310 | * rs_work(). | ||
311 | */ | ||
312 | typedef enum rs_work_options { | ||
313 | RS_END = 0x01 /**< End of input file; please finish | ||
314 | * up. */ | ||
315 | } rs_work_options; | ||
316 | |||
317 | |||
318 | rs_result rs_job_iter(rs_job_t *, rs_buffers_t *); | ||
319 | |||
320 | typedef rs_result rs_driven_cb(rs_job_t *job, rs_buffers_t *buf, | ||
321 | void *opaque); | ||
322 | |||
323 | rs_result rs_job_drive(rs_job_t *job, rs_buffers_t *buf, | ||
324 | rs_driven_cb in_cb, void *in_opaque, | ||
325 | rs_driven_cb out_cb, void *out_opaque); | ||
326 | |||
327 | rs_result rs_job_free(rs_job_t *); | ||
328 | |||
329 | int rs_accum_value(rs_job_t *, char *sum, size_t sum_len); | ||
330 | |||
331 | rs_job_t *rs_sig_begin(size_t new_block_len, size_t strong_sum_len); | ||
332 | |||
333 | rs_job_t *rs_delta_begin(rs_signature_t *); | ||
334 | |||
335 | rs_job_t *rs_loadsig_begin(rs_signature_t **); | ||
336 | |||
337 | /** | ||
338 | * \brief Callback used to retrieve parts of the basis file. | ||
339 | * | ||
340 | * \param pos Position where copying should begin. | ||
341 | * | ||
342 | * \param len On input, the amount of data that should be retrieved. | ||
343 | * Updated to show how much is actually available. | ||
344 | * | ||
345 | * \param buf On input, a buffer of at least \p *len bytes. May be | ||
346 | * updated to point to a buffer allocated by the callback if it | ||
347 | * prefers. | ||
348 | */ | ||
349 | typedef rs_result rs_copy_cb(void *opaque, off_t pos, | ||
350 | size_t *len, void **buf); | ||
351 | |||
352 | |||
353 | |||
354 | rs_job_t *rs_patch_begin(rs_copy_cb *, void *copy_arg); | ||
355 | |||
356 | |||
357 | rs_result rs_build_hash_table(rs_signature_t* sums); | ||
358 | |||
359 | |||
360 | |||
361 | #ifndef RSYNC_NO_STDIO_INTERFACE | ||
362 | /** | ||
363 | * Buffer sizes for file IO. | ||
364 | * | ||
365 | * You probably only need to change these in testing. | ||
366 | */ | ||
367 | extern int rs_inbuflen, rs_outbuflen; | ||
368 | |||
369 | |||
370 | /** | ||
371 | * Calculate the MD4 sum of a file. | ||
372 | * | ||
373 | * \param result Binary (not hex) MD4 of the whole contents of the | ||
374 | * file. | ||
375 | */ | ||
376 | void rs_mdfour_file(FILE *in_file, char *result); | ||
377 | |||
378 | rs_result rs_sig_file(FILE *old_file, FILE *sig_file, | ||
379 | size_t block_len, size_t strong_len, rs_stats_t *); | ||
380 | |||
381 | rs_result rs_loadsig_file(FILE *, rs_signature_t **, rs_stats_t *); | ||
382 | |||
383 | rs_result rs_file_copy_cb(void *arg, off_t pos, size_t *len, void **buf); | ||
384 | |||
385 | rs_result rs_delta_file(rs_signature_t *, FILE *new_file, FILE *delta_file, rs_stats_t *); | ||
386 | |||
387 | rs_result rs_patch_file(FILE *basis_file, FILE *delta_file, FILE *new_file, rs_stats_t *); | ||
388 | #endif | ||
diff --git a/rsync/scoop.c b/rsync/scoop.c new file mode 100644 index 0000000..9f68a60 --- a/dev/null +++ b/rsync/scoop.c | |||
@@ -0,0 +1,271 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * scoop.c -- This file deals with readahead from caller-supplied | ||
25 | * buffers. | ||
26 | * | ||
27 | * Many functions require a certain minimum amount of input to do their | ||
28 | * processing. For example, to calculate a strong checksum of a block | ||
29 | * we need at least a block of input. | ||
30 | * | ||
31 | * Since we put the buffers completely under the control of the caller, | ||
32 | * we can't count on ever getting this much data all in one go. We | ||
33 | * can't simply wait, because the caller might have a smaller buffer | ||
34 | * than we require and so we'll never get it. For the same reason we | ||
35 | * must always accept all the data we're given. | ||
36 | * | ||
37 | * So, stream input data that's required for readahead is put into a | ||
38 | * special buffer, from which the caller can then read. It's | ||
39 | * essentially like an internal pipe, which on any given read request | ||
40 | * may or may not be able to actually supply the data. | ||
41 | * | ||
42 | * As a future optimization, we might try to take data directly from the | ||
43 | * input buffer if there's already enough there. | ||
44 | */ | ||
45 | |||
46 | /* | ||
47 | * TODO: We probably know a maximum amount of data that can be scooped | ||
48 | * up, so we could just avoid dynamic allocation. However that can't | ||
49 | * be fixed at compile time, because when generating a delta it needs | ||
50 | * to be large enough to hold one full block. Perhaps we can set it | ||
51 | * up when the job is allocated? It would be kind of nice to not do | ||
52 | * any memory allocation after startup, as bzlib does this. | ||
53 | */ | ||
54 | |||
55 | |||
56 | /* | ||
57 | | To walk on water you've gotta sink | ||
58 | | in the ice. | ||
59 | | -- Shihad, `The General Electric'. | ||
60 | */ | ||
61 | |||
62 | #include <config_rsync.h> | ||
63 | |||
64 | #include <assert.h> | ||
65 | #include <stdlib.h> | ||
66 | #include <stdio.h> | ||
67 | #include <string.h> | ||
68 | |||
69 | #include "rsync.h" | ||
70 | #include "job.h" | ||
71 | #include "stream.h" | ||
72 | #include "trace.h" | ||
73 | #include "util.h" | ||
74 | |||
75 | |||
76 | #if 0 | ||
77 | # undef rs_trace | ||
78 | # define rs_trace(s...) | ||
79 | #endif | ||
80 | |||
81 | |||
82 | /** | ||
83 | * Try to accept a from the input buffer to get LEN bytes in the scoop. | ||
84 | */ | ||
85 | void rs_scoop_input(rs_job_t *job, size_t len) | ||
86 | { | ||
87 | rs_buffers_t *stream = job->stream; | ||
88 | size_t tocopy; | ||
89 | |||
90 | assert(len > job->scoop_avail); | ||
91 | |||
92 | if (job->scoop_alloc < len) { | ||
93 | /* need to allocate a new buffer, too */ | ||
94 | char *newbuf; | ||
95 | int newsize = 2 * len; | ||
96 | newbuf = rs_alloc(newsize, "scoop buffer"); | ||
97 | if (job->scoop_avail) | ||
98 | memcpy(newbuf, job->scoop_next, job->scoop_avail); | ||
99 | if (job->scoop_buf) | ||
100 | free(job->scoop_buf); | ||
101 | job->scoop_buf = job->scoop_next = newbuf; | ||
102 | rs_trace("resized scoop buffer to %.0f bytes from %.0f", | ||
103 | (double) newsize, (double) job->scoop_alloc); | ||
104 | job->scoop_alloc = newsize; | ||
105 | } else { | ||
106 | /* this buffer size is fine, but move the existing | ||
107 | * data down to the front. */ | ||
108 | memmove(job->scoop_buf, job->scoop_next, job->scoop_avail); | ||
109 | job->scoop_next = job->scoop_buf; | ||
110 | } | ||
111 | |||
112 | /* take as much input as is available, to give up to LEN bytes | ||
113 | * in the scoop. */ | ||
114 | tocopy = len - job->scoop_avail; | ||
115 | if (tocopy > stream->avail_in) | ||
116 | tocopy = stream->avail_in; | ||
117 | assert(tocopy + job->scoop_avail <= job->scoop_alloc); | ||
118 | |||
119 | memcpy(job->scoop_next + job->scoop_avail, stream->next_in, tocopy); | ||
120 | rs_trace("accepted %.0f bytes from input to scoop", (double) tocopy); | ||
121 | job->scoop_avail += tocopy; | ||
122 | stream->next_in += tocopy; | ||
123 | stream->avail_in -= tocopy; | ||
124 | } | ||
125 | |||
126 | |||
127 | /** | ||
128 | * Advance the input cursor forward \p len bytes. This is used after | ||
129 | * doing readahead, when you decide you want to keep it. \p len must | ||
130 | * be no more than the amount of available data, so you can't cheat. | ||
131 | * | ||
132 | * So when creating a delta, we require one block of readahead. But | ||
133 | * after examining that block, we might decide to advance over all of | ||
134 | * it (if there is a match), or just one byte (if not). | ||
135 | */ | ||
136 | void rs_scoop_advance(rs_job_t *job, size_t len) | ||
137 | { | ||
138 | rs_buffers_t *stream = job->stream; | ||
139 | |||
140 | /* It never makes sense to advance over a mixture of bytes from | ||
141 | * the scoop and input, because you couldn't possibly have looked | ||
142 | * at them all at the same time. */ | ||
143 | if (job->scoop_avail) { | ||
144 | /* reading from the scoop buffer */ | ||
145 | rs_trace("advance over %d bytes from scoop", len); | ||
146 | assert(len <= job->scoop_avail); | ||
147 | job->scoop_avail -= len; | ||
148 | job->scoop_next += len; | ||
149 | } else { | ||
150 | rs_trace("advance over %d bytes from input buffer", len); | ||
151 | assert(len <= stream->avail_in); | ||
152 | stream->avail_in -= len; | ||
153 | stream->next_in += len; | ||
154 | } | ||
155 | } | ||
156 | |||
157 | |||
158 | |||
159 | /** | ||
160 | * \brief Read from scoop without advancing. | ||
161 | * | ||
162 | * Ask for LEN bytes of input from the stream. If that much data is | ||
163 | * available, then return a pointer to it in PTR, advance the stream | ||
164 | * input pointer over the data, and return RS_DONE. If there's not | ||
165 | * enough data, then accept whatever is there into a buffer, advance | ||
166 | * over it, and return RS_BLOCKED. | ||
167 | * | ||
168 | * The data is not actually removed from the input, so this function | ||
169 | * lets you do readahead. If you want to keep any of the data, you | ||
170 | * should also call rs_scoop_advance() to skip over it. | ||
171 | */ | ||
172 | rs_result rs_scoop_readahead(rs_job_t *job, size_t len, void **ptr) | ||
173 | { | ||
174 | rs_buffers_t *stream = job->stream; | ||
175 | rs_job_check(job); | ||
176 | |||
177 | if (job->scoop_avail >= len) { | ||
178 | /* We have enough data queued to satisfy the request, | ||
179 | * so go straight from the scoop buffer. */ | ||
180 | rs_trace("got %.0f bytes direct from scoop", (double) len); | ||
181 | *ptr = job->scoop_next; | ||
182 | return RS_DONE; | ||
183 | } else if (job->scoop_avail) { | ||
184 | /* We have some data in the scoop, but not enough to | ||
185 | * satisfy the request. */ | ||
186 | rs_trace("data is present in the scoop and must be used"); | ||
187 | rs_scoop_input(job, len); | ||
188 | |||
189 | if (job->scoop_avail < len) { | ||
190 | rs_trace("still have only %.0f bytes in scoop", | ||
191 | (double) job->scoop_avail); | ||
192 | return RS_BLOCKED; | ||
193 | } else { | ||
194 | rs_trace("scoop now has %.0f bytes, this is enough", | ||
195 | (double) job->scoop_avail); | ||
196 | *ptr = job->scoop_next; | ||
197 | return RS_DONE; | ||
198 | } | ||
199 | } else if (stream->avail_in >= len) { | ||
200 | /* There's enough data in the stream's input */ | ||
201 | *ptr = stream->next_in; | ||
202 | rs_trace("got %.0f bytes from input buffer", (double) len); | ||
203 | return RS_DONE; | ||
204 | } else if (stream->avail_in > 0) { | ||
205 | /* Nothing was queued before, but we don't have enough | ||
206 | * data to satisfy the request. So queue what little | ||
207 | * we have, and try again next time. */ | ||
208 | rs_trace("couldn't satisfy request for %.0f, scooping %.0f bytes", | ||
209 | (double) len, (double) job->scoop_avail); | ||
210 | rs_scoop_input(job, len); | ||
211 | return RS_BLOCKED; | ||
212 | } else if (stream->eof_in) { | ||
213 | /* Nothing is queued before, and nothing is in the input | ||
214 | * buffer at the moment. */ | ||
215 | rs_trace("reached end of input stream"); | ||
216 | return RS_INPUT_ENDED; | ||
217 | } else { | ||
218 | /* Nothing queued at the moment. */ | ||
219 | rs_trace("blocked with no data in scoop or input buffer"); | ||
220 | return RS_BLOCKED; | ||
221 | } | ||
222 | } | ||
223 | |||
224 | |||
225 | |||
226 | /** | ||
227 | * Read LEN bytes if possible, and remove them from the input scoop. | ||
228 | * If there's not enough data yet, return RS_BLOCKED. | ||
229 | * | ||
230 | * \param ptr will be updated to point to a read-only buffer holding | ||
231 | * the data, if enough is available. | ||
232 | * | ||
233 | * \return RS_DONE if all the data was available, RS_BLOCKED if it's | ||
234 | * not there. | ||
235 | */ | ||
236 | rs_result rs_scoop_read(rs_job_t *job, size_t len, void **ptr) | ||
237 | { | ||
238 | rs_result result; | ||
239 | |||
240 | result = rs_scoop_readahead(job, len, ptr); | ||
241 | if (result == RS_DONE) | ||
242 | rs_scoop_advance(job, len); | ||
243 | |||
244 | return result; | ||
245 | } | ||
246 | |||
247 | |||
248 | |||
249 | /* | ||
250 | * Read whatever remains in the input stream, assuming that it runs up | ||
251 | * to the end of the file. Set LEN appropriately. | ||
252 | */ | ||
253 | rs_result rs_scoop_read_rest(rs_job_t *job, size_t *len, void **ptr) | ||
254 | { | ||
255 | rs_buffers_t *stream = job->stream; | ||
256 | |||
257 | *len = job->scoop_avail + stream->avail_in; | ||
258 | |||
259 | return rs_scoop_read(job, *len, ptr); | ||
260 | } | ||
261 | |||
262 | |||
263 | |||
264 | /** | ||
265 | * Return the total number of bytes available including the scoop and input | ||
266 | * buffer. | ||
267 | */ | ||
268 | size_t rs_scoop_total_avail(rs_job_t *job) | ||
269 | { | ||
270 | return job->scoop_avail + job->stream->avail_in; | ||
271 | } | ||
diff --git a/rsync/search.c b/rsync/search.c new file mode 100644 index 0000000..3e0c5e2 --- a/dev/null +++ b/rsync/search.c | |||
@@ -0,0 +1,162 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * Copyright (C) 1999 by Andrew Tridgell | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU Lesser General Public License as published by | ||
11 | * the Free Software Foundation; either version 2.1 of the License, or | ||
12 | * (at your option) any 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 Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | /* | ||
25 | * This file contains code for searching the sumset for matching | ||
26 | * values. | ||
27 | */ | ||
28 | |||
29 | /* | ||
30 | * TODO: The common case is that the next block in both streams | ||
31 | * match. Can we make that a bit faster at all? We'd need to perhaps | ||
32 | * add a link forward between blocks in the sum_struct corresponding | ||
33 | * to the order they're found in the input; then before doing a search | ||
34 | * we can just check that pointer. | ||
35 | */ | ||
36 | |||
37 | #include <config_rsync.h> | ||
38 | |||
39 | #include <string.h> | ||
40 | #include <assert.h> | ||
41 | #include <stdlib.h> | ||
42 | #include <stdio.h> | ||
43 | |||
44 | #include "rsync.h" | ||
45 | #include "trace.h" | ||
46 | #include "util.h" | ||
47 | #include "sumset.h" | ||
48 | #include "search.h" | ||
49 | #include "checksum.h" | ||
50 | |||
51 | |||
52 | #define TABLESIZE (1<<16) | ||
53 | #define NULL_TAG (-1) | ||
54 | |||
55 | |||
56 | #define gettag2(s1,s2) (((s1) + (s2)) & 0xFFFF) | ||
57 | #define gettag(sum) gettag2((sum)&0xFFFF,(sum)>>16) | ||
58 | |||
59 | |||
60 | static int | ||
61 | rs_compare_targets(rs_target_t const *t1, rs_target_t const *t2) | ||
62 | { | ||
63 | return ((int) t1->t - (int) t2->t); | ||
64 | } | ||
65 | |||
66 | |||
67 | rs_result | ||
68 | rs_build_hash_table(rs_signature_t * sums) | ||
69 | { | ||
70 | int i; | ||
71 | |||
72 | sums->tag_table = calloc(TABLESIZE, sizeof sums->tag_table[0]); | ||
73 | if (!sums->tag_table) | ||
74 | return RS_MEM_ERROR; | ||
75 | |||
76 | if (sums->count > 0) { | ||
77 | sums->targets = calloc(sums->count, sizeof(rs_target_t)); | ||
78 | if (!sums->targets) | ||
79 | return RS_MEM_ERROR; | ||
80 | |||
81 | for (i = 0; i < sums->count; i++) { | ||
82 | sums->targets[i].i = i; | ||
83 | sums->targets[i].t = gettag(sums->block_sigs[i].weak_sum); | ||
84 | } | ||
85 | |||
86 | /* FIXME: Perhaps if this operating system has comparison_fn_t | ||
87 | * like GNU, then use it in the cast. But really does anyone | ||
88 | * care? */ | ||
89 | qsort(sums->targets, sums->count, | ||
90 | sizeof(sums->targets[0]), | ||
91 | (int (*)(const void *, const void *)) rs_compare_targets); | ||
92 | } | ||
93 | |||
94 | for (i = 0; i < TABLESIZE; i++) | ||
95 | sums->tag_table[i] = NULL_TAG; | ||
96 | |||
97 | for (i = sums->count - 1; i >= 0; i--) { | ||
98 | sums->tag_table[sums->targets[i].t] = i; | ||
99 | } | ||
100 | |||
101 | rs_trace("done"); | ||
102 | return RS_DONE; | ||
103 | } | ||
104 | |||
105 | |||
106 | |||
107 | /* | ||
108 | * See if there is a match for the specified block INBUF..BLOCK_LEN in | ||
109 | * the checksum set, using precalculated WEAK_SUM. | ||
110 | * | ||
111 | * If we don't find a match on the weak checksum, then we just give | ||
112 | * up. If we do find a weak match, then we proceed to calculate the | ||
113 | * strong checksum for the current block, and see if it will match | ||
114 | * anything. | ||
115 | */ | ||
116 | int | ||
117 | rs_search_for_block(rs_weak_sum_t weak_sum, | ||
118 | char const *inbuf, size_t block_len, | ||
119 | rs_signature_t const *sig, rs_stats_t * stats, | ||
120 | rs_long_t * match_where) | ||
121 | { | ||
122 | int hash_tag = gettag(weak_sum); | ||
123 | int j = sig->tag_table[hash_tag]; | ||
124 | rs_strong_sum_t strong_sum; | ||
125 | int got_strong = 0; | ||
126 | |||
127 | if (j == NULL_TAG) { | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | for (; j < sig->count && sig->targets[j].t == hash_tag; j++) { | ||
132 | int i = sig->targets[j].i; | ||
133 | int token; | ||
134 | |||
135 | if (weak_sum != sig->block_sigs[i].weak_sum) | ||
136 | continue; | ||
137 | |||
138 | token = sig->block_sigs[i].i; | ||
139 | |||
140 | rs_trace("found weak match for %08x in token %d", weak_sum, token); | ||
141 | |||
142 | if (!got_strong) { | ||
143 | rs_calc_strong_sum(inbuf, block_len, &strong_sum); | ||
144 | got_strong = 1; | ||
145 | } | ||
146 | |||
147 | /* FIXME: Use correct dynamic sum length! */ | ||
148 | if (memcmp(strong_sum, sig->block_sigs[i].strong_sum, | ||
149 | sig->strong_sum_len) == 0) { | ||
150 | /* XXX: This is a remnant of rsync: token number 1 is the | ||
151 | * block at offset 0. It would be good to clear this | ||
152 | * up. */ | ||
153 | *match_where = (token - 1) * sig->block_len; | ||
154 | return 1; | ||
155 | } else { | ||
156 | rs_trace("this was a false positive, the strong sig doesn't match"); | ||
157 | stats->false_matches++; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | return 0; | ||
162 | } | ||
diff --git a/rsync/search.h b/rsync/search.h new file mode 100644 index 0000000..a1d0cd8 --- a/dev/null +++ b/rsync/search.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 1999, 2000 by Martin Pool <mbp@samba.org> | ||
7 | * Copyright (C) 1999 by Andrew Tridgell | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU Lesser General Public License as published by | ||
11 | * the Free Software Foundation; either version 2.1 of the License, or | ||
12 | * (at your option) any 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 Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | int | ||
25 | rs_search_for_block(rs_weak_sum_t weak_sum, | ||
26 | char const *inbuf, size_t block_len, | ||
27 | rs_signature_t const *sums, rs_stats_t * stats, | ||
28 | rs_long_t * match_where); | ||
29 | |||
diff --git a/rsync/snprintf.c b/rsync/snprintf.c new file mode 100644 index 0000000..348ef2d --- a/dev/null +++ b/rsync/snprintf.c | |||
@@ -0,0 +1,822 @@ | |||
1 | /* $Id$ */ | ||
2 | |||
3 | /* | ||
4 | * Copyright Patrick Powell 1995 | ||
5 | * This code is based on code written by Patrick Powell (papowell@astart.com) | ||
6 | * It may be used for any purpose as long as this notice remains intact | ||
7 | * on all source code distributions | ||
8 | */ | ||
9 | |||
10 | /************************************************************** | ||
11 | * Original: | ||
12 | * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 | ||
13 | * A bombproof version of doprnt (dopr) included. | ||
14 | * Sigh. This sort of thing is always nasty do deal with. Note that | ||
15 | * the version here does not include floating point... | ||
16 | * | ||
17 | * snprintf() is used instead of sprintf() as it does limit checks | ||
18 | * for string length. This covers a nasty loophole. | ||
19 | * | ||
20 | * The other functions are there to prevent NULL pointers from | ||
21 | * causing nast effects. | ||
22 | * | ||
23 | * More Recently: | ||
24 | * Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43 | ||
25 | * This was ugly. It is still ugly. I opted out of floating point | ||
26 | * numbers, but the formatter understands just about everything | ||
27 | * from the normal C string format, at least as far as I can tell from | ||
28 | * the Solaris 2.5 printf(3S) man page. | ||
29 | * | ||
30 | * Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1 | ||
31 | * Ok, added some minimal floating point support, which means this | ||
32 | * probably requires libm on most operating systems. Don't yet | ||
33 | * support the exponent (e,E) and sigfig (g,G). Also, fmtint() | ||
34 | * was pretty badly broken, it just wasn't being exercised in ways | ||
35 | * which showed it, so that's been fixed. Also, formated the code | ||
36 | * to mutt conventions, and removed dead code left over from the | ||
37 | * original. Also, there is now a builtin-test, just compile with: | ||
38 | * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm | ||
39 | * and run snprintf for results. | ||
40 | * | ||
41 | * Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i | ||
42 | * The PGP code was using unsigned hexadecimal formats. | ||
43 | * Unfortunately, unsigned formats simply didn't work. | ||
44 | * | ||
45 | * Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8 | ||
46 | * The original code assumed that both snprintf() and vsnprintf() were | ||
47 | * missing. Some systems only have snprintf() but not vsnprintf(), so | ||
48 | * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. | ||
49 | * | ||
50 | * Andrew Tridgell <tridge@samba.org> Oct 1998 | ||
51 | * fixed handling of %.0f | ||
52 | * added test for HAVE_LONG_DOUBLE | ||
53 | * | ||
54 | **************************************************************/ | ||
55 | |||
56 | #include <config_rsync.h> | ||
57 | |||
58 | #include <string.h> | ||
59 | # include <ctype.h> | ||
60 | #include <sys/types.h> | ||
61 | |||
62 | #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) | ||
63 | |||
64 | /* Define this as a fall through, HAVE_STDARG_H is probably already set */ | ||
65 | |||
66 | #define HAVE_VARARGS_H | ||
67 | |||
68 | /* varargs declarations: */ | ||
69 | |||
70 | #if defined(HAVE_STDARG_H) | ||
71 | # include <stdarg.h> | ||
72 | # define HAVE_STDARGS /* let's hope that works everywhere (mj) */ | ||
73 | # define VA_LOCAL_DECL va_list ap | ||
74 | # define VA_START(f) va_start(ap, f) | ||
75 | # define VA_SHIFT(v,t) ; /* no-op for ANSI */ | ||
76 | # define VA_END va_end(ap) | ||
77 | #else | ||
78 | # if defined(HAVE_VARARGS_H) | ||
79 | # include <varargs.h> | ||
80 | # undef HAVE_STDARGS | ||
81 | # define VA_LOCAL_DECL va_list ap | ||
82 | # define VA_START(f) va_start(ap) /* f is ignored! */ | ||
83 | # define VA_SHIFT(v,t) v = va_arg(ap,t) | ||
84 | # define VA_END va_end(ap) | ||
85 | # else | ||
86 | /*XX ** NO VARARGS ** XX*/ | ||
87 | # endif | ||
88 | #endif | ||
89 | |||
90 | #ifdef HAVE_LONG_DOUBLE | ||
91 | #define LDOUBLE long double | ||
92 | #else | ||
93 | #define LDOUBLE double | ||
94 | #endif | ||
95 | |||
96 | /*int snprintf (char *str, size_t count, const char *fmt, ...);*/ | ||
97 | /*int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);*/ | ||
98 | |||
99 | static void dopr (char *buffer, size_t maxlen, const char *format, | ||
100 | va_list args); | ||
101 | static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, | ||
102 | char *value, int flags, int min, int max); | ||
103 | static void fmtint (char *buffer, size_t *currlen, size_t maxlen, | ||
104 | long value, int base, int min, int max, int flags); | ||
105 | static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, | ||
106 | LDOUBLE fvalue, int min, int max, int flags); | ||
107 | static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c ); | ||
108 | |||
109 | /* | ||
110 | * dopr(): poor man's version of doprintf | ||
111 | */ | ||
112 | |||
113 | /* format read states */ | ||
114 | #define DP_S_DEFAULT 0 | ||
115 | #define DP_S_FLAGS 1 | ||
116 | #define DP_S_MIN 2 | ||
117 | #define DP_S_DOT 3 | ||
118 | #define DP_S_MAX 4 | ||
119 | #define DP_S_MOD 5 | ||
120 | #define DP_S_CONV 6 | ||
121 | #define DP_S_DONE 7 | ||
122 | |||
123 | /* format flags - Bits */ | ||
124 | #define DP_F_MINUS (1 << 0) | ||
125 | #define DP_F_PLUS (1 << 1) | ||
126 | #define DP_F_SPACE (1 << 2) | ||
127 | #define DP_F_NUM (1 << 3) | ||
128 | #define DP_F_ZERO (1 << 4) | ||
129 | #define DP_F_UP (1 << 5) | ||
130 | #define DP_F_UNSIGNED (1 << 6) | ||
131 | |||
132 | /* Conversion Flags */ | ||
133 | #define DP_C_SHORT 1 | ||
134 | #define DP_C_LONG 2 | ||
135 | #define DP_C_LDOUBLE 3 | ||
136 | |||
137 | #define char_to_int(p) (p - '0') | ||
138 | #define MAX(p,q) ((p >= q) ? p : q) | ||
139 | |||
140 | static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) | ||
141 | { | ||
142 | char ch; | ||
143 | long value; | ||
144 | LDOUBLE fvalue; | ||
145 | char *strvalue; | ||
146 | int min; | ||
147 | int max; | ||
148 | int state; | ||
149 | int flags; | ||
150 | int cflags; | ||
151 | size_t currlen; | ||
152 | |||
153 | state = DP_S_DEFAULT; | ||
154 | currlen = flags = cflags = min = 0; | ||
155 | max = -1; | ||
156 | ch = *format++; | ||
157 | |||
158 | while (state != DP_S_DONE) | ||
159 | { | ||
160 | if ((ch == '\0') || (currlen >= maxlen)) | ||
161 | state = DP_S_DONE; | ||
162 | |||
163 | switch(state) | ||
164 | { | ||
165 | case DP_S_DEFAULT: | ||
166 | if (ch == '%') | ||
167 | state = DP_S_FLAGS; | ||
168 | else | ||
169 | dopr_outch (buffer, &currlen, maxlen, ch); | ||
170 | ch = *format++; | ||
171 | break; | ||
172 | case DP_S_FLAGS: | ||
173 | switch (ch) | ||
174 | { | ||
175 | case '-': | ||
176 | flags |= DP_F_MINUS; | ||
177 | ch = *format++; | ||
178 | break; | ||
179 | case '+': | ||
180 | flags |= DP_F_PLUS; | ||
181 | ch = *format++; | ||
182 | break; | ||
183 | case ' ': | ||
184 | flags |= DP_F_SPACE; | ||
185 | ch = *format++; | ||
186 | break; | ||
187 | case '#': | ||
188 | flags |= DP_F_NUM; | ||
189 | ch = *format++; | ||
190 | break; | ||
191 | case '0': | ||
192 | flags |= DP_F_ZERO; | ||
193 | ch = *format++; | ||
194 | break; | ||
195 | default: | ||
196 | state = DP_S_MIN; | ||
197 | break; | ||
198 | } | ||
199 | break; | ||
200 | case DP_S_MIN: | ||
201 | if (isdigit((unsigned char)ch)) | ||
202 | { | ||
203 | min = 10*min + char_to_int (ch); | ||
204 | ch = *format++; | ||
205 | } | ||
206 | else if (ch == '*') | ||
207 | { | ||
208 | min = va_arg (args, int); | ||
209 | ch = *format++; | ||
210 | state = DP_S_DOT; | ||
211 | } | ||
212 | else | ||
213 | state = DP_S_DOT; | ||
214 | break; | ||
215 | case DP_S_DOT: | ||
216 | if (ch == '.') | ||
217 | { | ||
218 | state = DP_S_MAX; | ||
219 | ch = *format++; | ||
220 | } | ||
221 | else | ||
222 | state = DP_S_MOD; | ||
223 | break; | ||
224 | case DP_S_MAX: | ||
225 | if (isdigit((unsigned char)ch)) | ||
226 | { | ||
227 | if (max < 0) | ||
228 | max = 0; | ||
229 | max = 10*max + char_to_int (ch); | ||
230 | ch = *format++; | ||
231 | } | ||
232 | else if (ch == '*') | ||
233 | { | ||
234 | max = va_arg (args, int); | ||
235 | ch = *format++; | ||
236 | state = DP_S_MOD; | ||
237 | } | ||
238 | else | ||
239 | state = DP_S_MOD; | ||
240 | break; | ||
241 | case DP_S_MOD: | ||
242 | /* Currently, we don't support Long Long, bummer */ | ||
243 | switch (ch) | ||
244 | { | ||
245 | case 'h': | ||
246 | cflags = DP_C_SHORT; | ||
247 | ch = *format++; | ||
248 | break; | ||
249 | case 'l': | ||
250 | cflags = DP_C_LONG; | ||
251 | ch = *format++; | ||
252 | break; | ||
253 | case 'L': | ||
254 | cflags = DP_C_LDOUBLE; | ||
255 | ch = *format++; | ||
256 | break; | ||
257 | default: | ||
258 | break; | ||
259 | } | ||
260 | state = DP_S_CONV; | ||
261 | break; | ||
262 | case DP_S_CONV: | ||
263 | switch (ch) | ||
264 | { | ||
265 | case 'd': | ||
266 | case 'i': | ||
267 | if (cflags == DP_C_SHORT) | ||
268 | value = va_arg (args, short int); | ||
269 | else if (cflags == DP_C_LONG) | ||
270 | value = va_arg (args, long int); | ||
271 | else | ||
272 | value = va_arg (args, int); | ||
273 | fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); | ||
274 | break; | ||
275 | case 'o': | ||
276 | flags |= DP_F_UNSIGNED; | ||
277 | if (cflags == DP_C_SHORT) | ||
278 | value = va_arg (args, unsigned short int); | ||
279 | else if (cflags == DP_C_LONG) | ||
280 | value = (long)va_arg (args, unsigned long int); | ||
281 | else | ||
282 | value = (long)va_arg (args, unsigned int); | ||
283 | fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); | ||
284 | break; | ||
285 | case 'u': | ||
286 | flags |= DP_F_UNSIGNED; | ||
287 | if (cflags == DP_C_SHORT) | ||
288 | value = va_arg (args, unsigned short int); | ||
289 | else if (cflags == DP_C_LONG) | ||
290 | value = (long)va_arg (args, unsigned long int); | ||
291 | else | ||
292 | value = (long)va_arg (args, unsigned int); | ||
293 | fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); | ||
294 | break; | ||
295 | case 'X': | ||
296 | flags |= DP_F_UP; | ||
297 | case 'x': | ||
298 | flags |= DP_F_UNSIGNED; | ||
299 | if (cflags == DP_C_SHORT) | ||
300 | value = va_arg (args, unsigned short int); | ||
301 | else if (cflags == DP_C_LONG) | ||
302 | value = (long)va_arg (args, unsigned long int); | ||
303 | else | ||
304 | value = (long)va_arg (args, unsigned int); | ||
305 | fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); | ||
306 | break; | ||
307 | case 'f': | ||
308 | if (cflags == DP_C_LDOUBLE) | ||
309 | fvalue = va_arg (args, LDOUBLE); | ||
310 | else | ||
311 | fvalue = va_arg (args, double); | ||
312 | /* um, floating point? */ | ||
313 | fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); | ||
314 | break; | ||
315 | case 'E': | ||
316 | flags |= DP_F_UP; | ||
317 | case 'e': | ||
318 | if (cflags == DP_C_LDOUBLE) | ||
319 | fvalue = va_arg (args, LDOUBLE); | ||
320 | else | ||
321 | fvalue = va_arg (args, double); | ||
322 | break; | ||
323 | case 'G': | ||
324 | flags |= DP_F_UP; | ||
325 | case 'g': | ||
326 | if (cflags == DP_C_LDOUBLE) | ||
327 | fvalue = va_arg (args, LDOUBLE); | ||
328 | else | ||
329 | fvalue = va_arg (args, double); | ||
330 | break; | ||
331 | case 'c': | ||
332 | dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); | ||
333 | break; | ||
334 | case 's': | ||
335 | strvalue = va_arg (args, char *); | ||
336 | if (max < 0) | ||
337 | max = maxlen; /* ie, no max */ | ||
338 | fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); | ||
339 | break; | ||
340 | case 'p': | ||
341 | strvalue = va_arg (args, void *); | ||
342 | fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); | ||
343 | break; | ||
344 | case 'n': | ||
345 | if (cflags == DP_C_SHORT) | ||
346 | { | ||
347 | short int *num; | ||
348 | num = va_arg (args, short int *); | ||
349 | *num = currlen; | ||
350 | } | ||
351 | else if (cflags == DP_C_LONG) | ||
352 | { | ||
353 | long int *num; | ||
354 | num = va_arg (args, long int *); | ||
355 | *num = (long int)currlen; | ||
356 | } | ||
357 | else | ||
358 | { | ||
359 | int *num; | ||
360 | num = va_arg (args, int *); | ||
361 | *num = currlen; | ||
362 | } | ||
363 | break; | ||
364 | case '%': | ||
365 | dopr_outch (buffer, &currlen, maxlen, ch); | ||
366 | break; | ||
367 | case 'w': | ||
368 | /* not supported yet, treat as next char */ | ||
369 | ch = *format++; | ||
370 | break; | ||
371 | default: | ||
372 | /* Unknown, skip */ | ||
373 | break; | ||
374 | } | ||
375 | ch = *format++; | ||
376 | state = DP_S_DEFAULT; | ||
377 | flags = cflags = min = 0; | ||
378 | max = -1; | ||
379 | break; | ||
380 | case DP_S_DONE: | ||
381 | break; | ||
382 | default: | ||
383 | /* hmm? */ | ||
384 | break; /* some picky compilers need this */ | ||
385 | } | ||
386 | } | ||
387 | if (currlen < maxlen - 1) | ||
388 | buffer[currlen] = '\0'; | ||
389 | else | ||
390 | buffer[maxlen - 1] = '\0'; | ||
391 | } | ||
392 | |||
393 | static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, | ||
394 | char *value, int flags, int min, int max) | ||
395 | { | ||
396 | int padlen, strln; /* amount to pad */ | ||
397 | int cnt = 0; | ||
398 | |||
399 | if (value == 0) | ||
400 | { | ||
401 | value = "<NULL>"; | ||
402 | } | ||
403 | |||
404 | for (strln = 0; value[strln]; ++strln); /* strlen */ | ||
405 | padlen = min - strln; | ||
406 | if (padlen < 0) | ||
407 | padlen = 0; | ||
408 | if (flags & DP_F_MINUS) | ||
409 | padlen = -padlen; /* Left Justify */ | ||
410 | |||
411 | while ((padlen > 0) && (cnt < max)) | ||
412 | { | ||
413 | dopr_outch (buffer, currlen, maxlen, ' '); | ||
414 | --padlen; | ||
415 | ++cnt; | ||
416 | } | ||
417 | while (*value && (cnt < max)) | ||
418 | { | ||
419 | dopr_outch (buffer, currlen, maxlen, *value++); | ||
420 | ++cnt; | ||
421 | } | ||
422 | while ((padlen < 0) && (cnt < max)) | ||
423 | { | ||
424 | dopr_outch (buffer, currlen, maxlen, ' '); | ||
425 | ++padlen; | ||
426 | ++cnt; | ||
427 | } | ||
428 | } | ||
429 | |||
430 | /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ | ||
431 | |||
432 | static void fmtint (char *buffer, size_t *currlen, size_t maxlen, | ||
433 | long value, int base, int min, int max, int flags) | ||
434 | { | ||
435 | int signvalue = 0; | ||
436 | unsigned long uvalue; | ||
437 | char convert[20]; | ||
438 | int place = 0; | ||
439 | int spadlen = 0; /* amount to space pad */ | ||
440 | int zpadlen = 0; /* amount to zero pad */ | ||
441 | int caps = 0; | ||
442 | |||
443 | if (max < 0) | ||
444 | max = 0; | ||
445 | |||
446 | uvalue = value; | ||
447 | |||
448 | if(!(flags & DP_F_UNSIGNED)) | ||
449 | { | ||
450 | if( value < 0 ) { | ||
451 | signvalue = '-'; | ||
452 | uvalue = -value; | ||
453 | } | ||
454 | else | ||
455 | if (flags & DP_F_PLUS) /* Do a sign (+/i) */ | ||
456 | signvalue = '+'; | ||
457 | else | ||
458 | if (flags & DP_F_SPACE) | ||
459 | signvalue = ' '; | ||
460 | } | ||
461 | |||
462 | if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ | ||
463 | |||
464 | do { | ||
465 | convert[place++] = | ||
466 | (caps? "0123456789ABCDEF":"0123456789abcdef") | ||
467 | [uvalue % (unsigned)base ]; | ||
468 | uvalue = (uvalue / (unsigned)base ); | ||
469 | } while(uvalue && (place < 20)); | ||
470 | if (place == 20) place--; | ||
471 | convert[place] = 0; | ||
472 | |||
473 | zpadlen = max - place; | ||
474 | spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); | ||
475 | if (zpadlen < 0) zpadlen = 0; | ||
476 | if (spadlen < 0) spadlen = 0; | ||
477 | if (flags & DP_F_ZERO) | ||
478 | { | ||
479 | zpadlen = MAX(zpadlen, spadlen); | ||
480 | spadlen = 0; | ||
481 | } | ||
482 | if (flags & DP_F_MINUS) | ||
483 | spadlen = -spadlen; /* Left Justifty */ | ||
484 | |||
485 | #ifdef DEBUG_SNPRINTF | ||
486 | printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", | ||
487 | zpadlen, spadlen, min, max, place); | ||
488 | #endif | ||
489 | |||
490 | /* Spaces */ | ||
491 | while (spadlen > 0) | ||
492 | { | ||
493 | dopr_outch (buffer, currlen, maxlen, ' '); | ||
494 | --spadlen; | ||
495 | } | ||
496 | |||
497 | /* Sign */ | ||
498 | if (signvalue) | ||
499 | dopr_outch (buffer, currlen, maxlen, signvalue); | ||
500 | |||
501 | /* Zeros */ | ||
502 | if (zpadlen > 0) | ||
503 | { | ||
504 | while (zpadlen > 0) | ||
505 | { | ||
506 | dopr_outch (buffer, currlen, maxlen, '0'); | ||
507 | --zpadlen; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | /* Digits */ | ||
512 | while (place > 0) | ||
513 | dopr_outch (buffer, currlen, maxlen, convert[--place]); | ||
514 | |||
515 | /* Left Justified spaces */ | ||
516 | while (spadlen < 0) { | ||
517 | dopr_outch (buffer, currlen, maxlen, ' '); | ||
518 | ++spadlen; | ||
519 | } | ||
520 | } | ||
521 | |||
522 | static LDOUBLE abs_val (LDOUBLE value) | ||
523 | { | ||
524 | LDOUBLE result = value; | ||
525 | |||
526 | if (value < 0) | ||
527 | result = -value; | ||
528 | |||
529 | return result; | ||
530 | } | ||
531 | |||
532 | static LDOUBLE pow10 (int exp) | ||
533 | { | ||
534 | LDOUBLE result = 1; | ||
535 | |||
536 | while (exp) | ||
537 | { | ||
538 | result *= 10; | ||
539 | exp--; | ||
540 | } | ||
541 | |||
542 | return result; | ||
543 | } | ||
544 | |||
545 | static long round (LDOUBLE value) | ||
546 | { | ||
547 | long intpart; | ||
548 | |||
549 | intpart = (long)value; | ||
550 | value = value - intpart; | ||
551 | if (value >= 0.5) | ||
552 | intpart++; | ||
553 | |||
554 | return intpart; | ||
555 | } | ||
556 | |||
557 | static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, | ||
558 | LDOUBLE fvalue, int min, int max, int flags) | ||
559 | { | ||
560 | int signvalue = 0; | ||
561 | LDOUBLE ufvalue; | ||
562 | char iconvert[20]; | ||
563 | char fconvert[20]; | ||
564 | int iplace = 0; | ||
565 | int fplace = 0; | ||
566 | int padlen = 0; /* amount to pad */ | ||
567 | int zpadlen = 0; | ||
568 | int caps = 0; | ||
569 | long intpart; | ||
570 | long fracpart; | ||
571 | |||
572 | /* | ||
573 | * AIX manpage says the default is 0, but Solaris says the default | ||
574 | * is 6, and sprintf on AIX defaults to 6 | ||
575 | */ | ||
576 | if (max < 0) | ||
577 | max = 6; | ||
578 | |||
579 | ufvalue = abs_val (fvalue); | ||
580 | |||
581 | if (fvalue < 0) | ||
582 | signvalue = '-'; | ||
583 | else | ||
584 | if (flags & DP_F_PLUS) /* Do a sign (+/i) */ | ||
585 | signvalue = '+'; | ||
586 | else | ||
587 | if (flags & DP_F_SPACE) | ||
588 | signvalue = ' '; | ||
589 | |||
590 | #if 0 | ||
591 | if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ | ||
592 | #endif | ||
593 | |||
594 | intpart = (long)ufvalue; | ||
595 | |||
596 | /* | ||
597 | * Sorry, we only support 9 digits past the decimal because of our | ||
598 | * conversion method | ||
599 | */ | ||
600 | if (max > 9) | ||
601 | max = 9; | ||
602 | |||
603 | /* We "cheat" by converting the fractional part to integer by | ||
604 | * multiplying by a factor of 10 | ||
605 | */ | ||
606 | fracpart = round ((pow10 (max)) * (ufvalue - intpart)); | ||
607 | |||
608 | if (fracpart >= pow10 (max)) | ||
609 | { | ||
610 | intpart++; | ||
611 | fracpart -= pow10 (max); | ||
612 | } | ||
613 | |||
614 | #ifdef DEBUG_SNPRINTF | ||
615 | printf("fmtfp: %g %d.%d min=%d max=%d\n", | ||
616 | (double)fvalue, intpart, fracpart, min, max); | ||
617 | #endif | ||
618 | |||
619 | /* Convert integer part */ | ||
620 | do { | ||
621 | iconvert[iplace++] = | ||
622 | (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10]; | ||
623 | intpart = (intpart / 10); | ||
624 | } while(intpart && (iplace < 20)); | ||
625 | if (iplace == 20) iplace--; | ||
626 | iconvert[iplace] = 0; | ||
627 | |||
628 | /* Convert fractional part */ | ||
629 | do { | ||
630 | fconvert[fplace++] = | ||
631 | (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10]; | ||
632 | fracpart = (fracpart / 10); | ||
633 | } while(fracpart && (fplace < 20)); | ||
634 | if (fplace == 20) fplace--; | ||
635 | fconvert[fplace] = 0; | ||
636 | |||
637 | /* -1 for decimal point, another -1 if we are printing a sign */ | ||
638 | padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); | ||
639 | zpadlen = max - fplace; | ||
640 | if (zpadlen < 0) | ||
641 | zpadlen = 0; | ||
642 | if (padlen < 0) | ||
643 | padlen = 0; | ||
644 | if (flags & DP_F_MINUS) | ||
645 | padlen = -padlen; /* Left Justifty */ | ||
646 | |||
647 | if ((flags & DP_F_ZERO) && (padlen > 0)) | ||
648 | { | ||
649 | if (signvalue) | ||
650 | { | ||
651 | dopr_outch (buffer, currlen, maxlen, signvalue); | ||
652 | --padlen; | ||
653 | signvalue = 0; | ||
654 | } | ||
655 | while (padlen > 0) | ||
656 | { | ||
657 | dopr_outch (buffer, currlen, maxlen, '0'); | ||
658 | --padlen; | ||
659 | } | ||
660 | } | ||
661 | while (padlen > 0) | ||
662 | { | ||
663 | dopr_outch (buffer, currlen, maxlen, ' '); | ||
664 | --padlen; | ||
665 | } | ||
666 | if (signvalue) | ||
667 | dopr_outch (buffer, currlen, maxlen, signvalue); | ||
668 | |||
669 | while (iplace > 0) | ||
670 | dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); | ||
671 | |||
672 | |||
673 | #ifdef DEBUG_SNPRINTF | ||
674 | printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen); | ||
675 | #endif | ||
676 | |||
677 | /* | ||
678 | * Decimal point. This should probably use locale to find the correct | ||
679 | * char to print out. | ||
680 | */ | ||
681 | if (max > 0) { | ||
682 | dopr_outch (buffer, currlen, maxlen, '.'); | ||
683 | |||
684 | while (fplace > 0) | ||
685 | dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); | ||
686 | } | ||
687 | |||
688 | while (zpadlen > 0) | ||
689 | { | ||
690 | dopr_outch (buffer, currlen, maxlen, '0'); | ||
691 | --zpadlen; | ||
692 | } | ||
693 | |||
694 | while (padlen < 0) | ||
695 | { | ||
696 | dopr_outch (buffer, currlen, maxlen, ' '); | ||
697 | ++padlen; | ||
698 | } | ||
699 | } | ||
700 | |||
701 | static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c) | ||
702 | { | ||
703 | if (*currlen < maxlen) | ||
704 | buffer[(*currlen)++] = c; | ||
705 | } | ||
706 | #endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */ | ||
707 | |||
708 | #ifndef HAVE_VSNPRINTF | ||
709 | int vsnprintf (char *str, size_t count, const char *fmt, va_list args) | ||
710 | { | ||
711 | str[0] = 0; | ||
712 | dopr(str, count, fmt, args); | ||
713 | return(strlen(str)); | ||
714 | } | ||
715 | #endif /* !HAVE_VSNPRINTF */ | ||
716 | |||
717 | #ifndef HAVE_SNPRINTF | ||
718 | /* VARARGS3 */ | ||
719 | #ifdef HAVE_STDARGS | ||
720 | int snprintf (char *str,size_t count,const char *fmt,...) | ||
721 | #else | ||
722 | int snprintf (va_alist) va_dcl | ||
723 | #endif | ||
724 | { | ||
725 | #ifndef HAVE_STDARGS | ||
726 | char *str; | ||
727 | size_t count; | ||
728 | char *fmt; | ||
729 | #endif | ||
730 | VA_LOCAL_DECL; | ||
731 | |||
732 | VA_START (fmt); | ||
733 | VA_SHIFT (str, char *); | ||
734 | VA_SHIFT (count, size_t ); | ||
735 | VA_SHIFT (fmt, char *); | ||
736 | (void) vsnprintf(str, count, fmt, ap); | ||
737 | VA_END; | ||
738 | return(strlen(str)); | ||
739 | } | ||
740 | |||
741 | |||
742 | #else | ||
743 | /* keep compilers happy about empty files */ | ||
744 | void dummy_snprintf(void) {} | ||
745 | #endif /* !HAVE_SNPRINTF */ | ||
746 | |||
747 | #ifdef TEST_SNPRINTF | ||
748 | #ifndef LONG_STRING | ||
749 | #define LONG_STRING 1024 | ||
750 | #endif | ||
751 | int main (void) | ||
752 | { | ||
753 | char buf1[LONG_STRING]; | ||
754 | char buf2[LONG_STRING]; | ||
755 | char *fp_fmt[] = { | ||
756 | "%-1.5f", | ||
757 | "%1.5f", | ||
758 | "%123.9f", | ||
759 | "%10.5f", | ||
760 | "% 10.5f", | ||
761 | "%+22.9f", | ||
762 | "%+4.9f", | ||
763 | "%01.3f", | ||
764 | "%4f", | ||
765 | "%3.1f", | ||
766 | "%3.2f", | ||
767 | "%.0f", | ||
768 | "%.1f", | ||
769 | NULL | ||
770 | }; | ||
771 | double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, | ||
772 | 0.9996, 1.996, 4.136, 0}; | ||
773 | char *int_fmt[] = { | ||
774 | "%-1.5d", | ||
775 | "%1.5d", | ||
776 | "%123.9d", | ||
777 | "%5.5d", | ||
778 | "%10.5d", | ||
779 | "% 10.5d", | ||
780 | "%+22.33d", | ||
781 | "%01.3d", | ||
782 | "%4d", | ||
783 | NULL | ||
784 | }; | ||
785 | long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; | ||
786 | int x, y; | ||
787 | int fail = 0; | ||
788 | int num = 0; | ||
789 | |||
790 | printf ("Testing snprintf format codes against system sprintf...\n"); | ||
791 | |||
792 | for (x = 0; fp_fmt[x] != NULL ; x++) | ||
793 | for (y = 0; fp_nums[y] != 0 ; y++) | ||
794 | { | ||
795 | snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]); | ||
796 | sprintf (buf2, fp_fmt[x], fp_nums[y]); | ||
797 | if (strcmp (buf1, buf2)) | ||
798 | { | ||
799 | printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", | ||
800 | fp_fmt[x], buf1, buf2); | ||
801 | fail++; | ||
802 | } | ||
803 | num++; | ||
804 | } | ||
805 | |||
806 | for (x = 0; int_fmt[x] != NULL ; x++) | ||
807 | for (y = 0; int_nums[y] != 0 ; y++) | ||
808 | { | ||
809 | snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]); | ||
810 | sprintf (buf2, int_fmt[x], int_nums[y]); | ||
811 | if (strcmp (buf1, buf2)) | ||
812 | { | ||
813 | printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", | ||
814 | int_fmt[x], buf1, buf2); | ||
815 | fail++; | ||
816 | } | ||
817 | num++; | ||
818 | } | ||
819 | printf ("%d tests failed out of %d.\n", fail, num); | ||
820 | } | ||
821 | #endif /* SNPRINTF_TEST */ | ||
822 | |||
diff --git a/rsync/stats.c b/rsync/stats.c new file mode 100644 index 0000000..5767d52 --- a/dev/null +++ b/rsync/stats.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * $Id$ | ||
4 | * | ||
5 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Lesser General Public License as published by | ||
9 | * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser 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 | |||
22 | |||
23 | #include <config_rsync.h> | ||
24 | |||
25 | #include <assert.h> | ||
26 | #include <stdlib.h> | ||
27 | #include <stdio.h> | ||
28 | #include <unistd.h> | ||
29 | #include <sys/file.h> | ||
30 | #include <string.h> | ||
31 | |||
32 | #include "rsync.h" | ||
33 | #include "trace.h" | ||
34 | |||
35 | /* | ||
36 | * TODO: Other things to show in statistics: | ||
37 | * | ||
38 | * Number of input and output bytes. | ||
39 | * | ||
40 | * Number of times we blocked waiting for input or output. | ||
41 | * | ||
42 | * Number of blocks. | ||
43 | */ | ||
44 | |||
45 | int | ||
46 | rs_log_stats(rs_stats_t const *stats) | ||
47 | { | ||
48 | char buf[1000]; | ||
49 | |||
50 | rs_format_stats(stats, buf, sizeof buf - 1); | ||
51 | rs_log(RS_LOG_INFO|RS_LOG_NONAME, "%s", buf); | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | |||
56 | |||
57 | /** | ||
58 | * \brief Return a human-readable representation of statistics. | ||
59 | * | ||
60 | * The string is truncated if it does not fit. 100 characters should | ||
61 | * be sufficient space. | ||
62 | * | ||
63 | * \param stats Statistics from an encoding or decoding operation. | ||
64 | * | ||
65 | * \param buf Buffer to receive result. | ||
66 | * \param size Size of buffer. | ||
67 | * \return buf | ||
68 | */ | ||
69 | char * | ||
70 | rs_format_stats(rs_stats_t const * stats, | ||
71 | char *buf, size_t size) | ||
72 | { | ||
73 | char const *op = stats->op; | ||
74 | int len; | ||
75 | |||
76 | if (!op) | ||
77 | op = "noop"; | ||
78 | |||
79 | len = snprintf(buf, size, "%s statistics: ", op); | ||
80 | |||
81 | if (stats->lit_cmds) { | ||
82 | len += snprintf(buf+len, size-len, | ||
83 | "literal[%d cmds, %.0f bytes, %.0f cmdbytes] ", | ||
84 | stats->lit_cmds, | ||
85 | (double) stats->lit_bytes, | ||
86 | (double) stats->lit_cmdbytes); | ||
87 | } | ||
88 | |||
89 | if (stats->sig_cmds) { | ||
90 | len += snprintf(buf+len, size-len, | ||
91 | "in-place-signature[%.0f cmds, %.0f bytes] ", | ||
92 | (double) stats->sig_cmds, | ||
93 | (double) stats->sig_bytes); | ||
94 | } | ||
95 | |||
96 | if (stats->copy_cmds || stats->false_matches) { | ||
97 | len += snprintf(buf+len, size-len, | ||
98 | "copy[%.0f cmds, %.0f bytes, %.0f false, %.0f cmdbytes]", | ||
99 | (double) stats->copy_cmds, | ||
100 | (double) stats->copy_bytes, | ||
101 | (double) stats->false_matches, | ||
102 | (double) stats->copy_cmdbytes); | ||
103 | } | ||
104 | |||
105 | |||
106 | if (stats->sig_blocks) { | ||
107 | len += snprintf(buf+len, size-len, | ||
108 | "signature[%.0f blocks, %.0f bytes per block]", | ||
109 | (double) stats->sig_blocks, | ||
110 | (double) stats->block_len); | ||
111 | } | ||
112 | |||
113 | return buf; | ||
114 | } | ||
diff --git a/rsync/stream.c b/rsync/stream.c new file mode 100644 index 0000000..d20d866 --- a/dev/null +++ b/rsync/stream.c | |||
@@ -0,0 +1,155 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- dynamic caching and delta update in HTTP | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * Programming languages should be designed not | ||
25 | * by piling feature on top of feature, but by | ||
26 | * removing the weaknesses and restrictions that | ||
27 | * make additional features appear necessary. | ||
28 | * -- Revised^5 Report on Scheme | ||
29 | */ | ||
30 | |||
31 | |||
32 | /* | ||
33 | * OK, so I'll admit IO here is a little complex. The most important | ||
34 | * player here is the stream, which is an object for managing filter | ||
35 | * operations. It has both input and output sides, both of which is | ||
36 | * just a (pointer,len) pair into a buffer provided by the client. | ||
37 | * The code controlling the stream handles however much data it wants, | ||
38 | * and the client provides or accepts however much is convenient. | ||
39 | * | ||
40 | * At the same time as being friendly to the client, we also try to be | ||
41 | * very friendly to the internal code. It wants to be able to ask for | ||
42 | * arbitrary amounts of input or output and get it without having to | ||
43 | * keep track of partial completion. So there are functions which | ||
44 | * either complete, or queue whatever was not sent and return | ||
45 | * RS_BLOCKED. | ||
46 | * | ||
47 | * The output buffer is a little more clever than simply a data | ||
48 | * buffer. Instead it knows that we can send either literal data, or | ||
49 | * data copied through from the input of the stream. | ||
50 | * | ||
51 | * In buf.c you will find functions that then map buffers onto stdio | ||
52 | * files. | ||
53 | * | ||
54 | * So on return from an encoding function, either the input or the | ||
55 | * output or possibly both will have no more bytes available. | ||
56 | */ | ||
57 | |||
58 | /* | ||
59 | * Manage librsync streams of IO. See scoop.c and tube.c for related | ||
60 | * code for input and output respectively. | ||
61 | * | ||
62 | * librsync never does IO or memory allocation, but relies on the | ||
63 | * caller. This is very nice for integration, but means that we have | ||
64 | * to be fairly flexible as to when we can `read' or `write' stuff | ||
65 | * internally. | ||
66 | * | ||
67 | * librsync basically does two types of IO. It reads network integers | ||
68 | * of various lengths which encode command and control information | ||
69 | * such as versions and signatures. It also does bulk data transfer. | ||
70 | * | ||
71 | * IO of network integers is internally buffered, because higher | ||
72 | * levels of the code need to see them transmitted atomically: it's no | ||
73 | * good to read half of a uint32. So there is a small and fixed | ||
74 | * length internal buffer which accumulates these. Unlike previous | ||
75 | * versions of the library, we don't require that the caller hold the | ||
76 | * start until the whole thing has arrived, which guarantees that we | ||
77 | * can always make progress. | ||
78 | * | ||
79 | * On each call into a stream iterator, it should begin by trying to | ||
80 | * flush output. This may well use up all the remaining stream space, | ||
81 | * in which case nothing else can be done. | ||
82 | */ | ||
83 | |||
84 | /* TODO: Return errors rather than aborting if something goes wrong. */ | ||
85 | |||
86 | |||
87 | #include <config_rsync.h> | ||
88 | |||
89 | #include <assert.h> | ||
90 | #include <stdlib.h> | ||
91 | #include <string.h> | ||
92 | #include <stdio.h> | ||
93 | |||
94 | #include "rsync.h" | ||
95 | #include "stream.h" | ||
96 | #include "util.h" | ||
97 | #include "trace.h" | ||
98 | |||
99 | static const int RS_STREAM_DOGTAG = 2001125; | ||
100 | |||
101 | |||
102 | /** | ||
103 | * \brief Copy up to \p max_len bytes from input of \b stream to its output. | ||
104 | * | ||
105 | * Return the number of bytes actually copied, which may be less than | ||
106 | * LEN if there is not enough space in one or the other stream. | ||
107 | * | ||
108 | * This always does the copy immediately. Most functions should call | ||
109 | * rs_tube_copy() to cause the copy to happen gradually as space | ||
110 | * becomes available. | ||
111 | */ | ||
112 | int rs_buffers_copy(rs_buffers_t *stream, int max_len) | ||
113 | { | ||
114 | int len = max_len; | ||
115 | |||
116 | assert(len > 0); | ||
117 | |||
118 | if ((unsigned) len > stream->avail_in) { | ||
119 | rs_trace("copy limited to %d available input bytes", | ||
120 | stream->avail_in); | ||
121 | len = stream->avail_in; | ||
122 | } | ||
123 | |||
124 | |||
125 | if ((unsigned) len > stream->avail_out) { | ||
126 | rs_trace("copy limited to %d available output bytes", | ||
127 | stream->avail_out); | ||
128 | len = stream->avail_out; | ||
129 | } | ||
130 | |||
131 | if (!len) | ||
132 | return 0; | ||
133 | /* rs_trace("stream copied chunk of %d bytes", len); */ | ||
134 | |||
135 | memcpy(stream->next_out, stream->next_in, len); | ||
136 | |||
137 | stream->next_out += len; | ||
138 | stream->avail_out -= len; | ||
139 | |||
140 | stream->next_in += len; | ||
141 | stream->avail_in -= len; | ||
142 | |||
143 | return len; | ||
144 | } | ||
145 | |||
146 | |||
147 | /** | ||
148 | * Whenever a stream processing function exits, it should have done so | ||
149 | * because it has either consumed all the input or has filled the | ||
150 | * output buffer. This function checks that simple postcondition. | ||
151 | */ | ||
152 | void rs_buffers_check_exit(rs_buffers_t const *stream) | ||
153 | { | ||
154 | assert(stream->avail_in == 0 || stream->avail_out == 0); | ||
155 | } | ||
diff --git a/rsync/stream.h b/rsync/stream.h new file mode 100644 index 0000000..e2d0da8 --- a/dev/null +++ b/rsync/stream.h | |||
@@ -0,0 +1,46 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | /* Two wars in a lifetime bear hard on the little places. | ||
24 | * In winter when storms come rushing out of the dark, | ||
25 | * And the bay boils like a cauldron of sharks, | ||
26 | * The old remember the trenches at Paschendale | ||
27 | * And sons who died on the Burma Railway. */ | ||
28 | |||
29 | |||
30 | int rs_buffers_is_empty(rs_buffers_t *stream); | ||
31 | int rs_buffers_copy(rs_buffers_t *stream, int len); | ||
32 | |||
33 | int rs_tube_catchup(rs_job_t *); | ||
34 | void rs_tube_write(rs_job_t *, void const *buf, size_t len); | ||
35 | void rs_tube_copy(rs_job_t *, int len); | ||
36 | int rs_tube_is_idle(rs_job_t const *); | ||
37 | void rs_check_tube(rs_job_t *); | ||
38 | |||
39 | void rs_buffers_check_exit(rs_buffers_t const *); | ||
40 | |||
41 | void rs_scoop_advance(rs_job_t *, size_t len); | ||
42 | rs_result rs_scoop_readahead(rs_job_t *, size_t len, void **ptr); | ||
43 | rs_result rs_scoop_read(rs_job_t *, size_t len, void **ptr); | ||
44 | rs_result rs_scoop_read_rest(rs_job_t *, size_t *len, void **ptr); | ||
45 | size_t rs_scoop_total_avail(rs_job_t *job); | ||
46 | void rs_scoop_input(rs_job_t *job, size_t len); | ||
diff --git a/rsync/sumset.c b/rsync/sumset.c new file mode 100644 index 0000000..c03aeb4 --- a/dev/null +++ b/rsync/sumset.c | |||
@@ -0,0 +1,83 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * Copyright (C) 1999 by Andrew Tridgell | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU Lesser General Public License as published by | ||
11 | * the Free Software Foundation; either version 2.1 of the License, or | ||
12 | * (at your option) any 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 Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <config_rsync.h> | ||
25 | |||
26 | #include <assert.h> | ||
27 | #include <stdlib.h> | ||
28 | #include <stdio.h> | ||
29 | |||
30 | #include "rsync.h" | ||
31 | #include "sumset.h" | ||
32 | #include "util.h" | ||
33 | #include "trace.h" | ||
34 | |||
35 | |||
36 | /** | ||
37 | * Deep deallocation of checksums. | ||
38 | */ | ||
39 | void | ||
40 | rs_free_sumset(rs_signature_t * psums) | ||
41 | { | ||
42 | if (psums->block_sigs) | ||
43 | free(psums->block_sigs); | ||
44 | |||
45 | if (psums->tag_table) | ||
46 | free(psums->tag_table); | ||
47 | |||
48 | if (psums->targets) | ||
49 | free(psums->targets); | ||
50 | |||
51 | rs_bzero(psums, sizeof *psums); | ||
52 | free(psums); | ||
53 | } | ||
54 | |||
55 | |||
56 | |||
57 | /** | ||
58 | * Dump signatures to the log. | ||
59 | */ | ||
60 | void | ||
61 | rs_sumset_dump(rs_signature_t const *sums) | ||
62 | { | ||
63 | int i; | ||
64 | char strong_hex[RS_MD4_LENGTH * 3]; | ||
65 | |||
66 | rs_log(RS_LOG_INFO, | ||
67 | "sumset info: block_len=%d, file length=%lu, " | ||
68 | "number of chunks=%d, remainder=%d", | ||
69 | sums->block_len, | ||
70 | (unsigned long) sums->flength, sums->count, | ||
71 | sums->remainder); | ||
72 | |||
73 | for (i = 0; i < sums->count; i++) { | ||
74 | rs_hexify(strong_hex, sums->block_sigs[i].strong_sum, | ||
75 | sums->strong_sum_len); | ||
76 | rs_log(RS_LOG_INFO, | ||
77 | "sum %6d: weak=%08x, strong=%s", | ||
78 | i, sums->block_sigs[i].weak_sum, strong_hex); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | |||
83 | |||
diff --git a/rsync/sumset.h b/rsync/sumset.h new file mode 100644 index 0000000..a501b23 --- a/dev/null +++ b/rsync/sumset.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * Copyright (C) 1999 by Andrew Tridgell <tridge@samba.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU Lesser General Public License | ||
11 | * as published by the Free Software Foundation; either version 2.1 of | ||
12 | * the License, or (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public | ||
20 | * License along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | |||
25 | /* | ||
26 | * TODO: These structures are not terribly useful. Perhaps we need a | ||
27 | * splay tree or something that will let us smoothly grow as data is | ||
28 | * read in. | ||
29 | */ | ||
30 | |||
31 | |||
32 | /** | ||
33 | * \brief Description of the match described by a signature. | ||
34 | */ | ||
35 | typedef struct rs_target { | ||
36 | unsigned short t; | ||
37 | int i; | ||
38 | } rs_target_t; | ||
39 | |||
40 | typedef struct rs_block_sig rs_block_sig_t; | ||
41 | |||
42 | /* | ||
43 | * This structure describes all the sums generated for an instance of | ||
44 | * a file. It incorporates some redundancy to make it easier to | ||
45 | * search. | ||
46 | */ | ||
47 | struct rs_signature { | ||
48 | rs_long_t flength;/* total file length */ | ||
49 | int count; /* how many chunks */ | ||
50 | int remainder;/* flength % block_length */ | ||
51 | int block_len;/* block_length */ | ||
52 | int strong_sum_len; | ||
53 | rs_block_sig_t *block_sigs; /* points to info for each chunk */ | ||
54 | int *tag_table; | ||
55 | rs_target_t *targets; | ||
56 | }; | ||
57 | |||
58 | |||
59 | /* | ||
60 | * All blocks are the same length in the current algorithm except for | ||
61 | * the last block which may be short. | ||
62 | */ | ||
63 | struct rs_block_sig { | ||
64 | int i; /* index of this chunk */ | ||
65 | rs_weak_sum_t weak_sum;/* simple checksum */ | ||
66 | rs_strong_sum_t strong_sum;/* checksum */ | ||
67 | }; | ||
diff --git a/rsync/trace.c b/rsync/trace.c new file mode 100644 index 0000000..b7e2b87 --- a/dev/null +++ b/rsync/trace.c | |||
@@ -0,0 +1,225 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Lesser General Public License as published by | ||
10 | * the Free Software Foundation; either version 2.1 of the License, or | ||
11 | * (at your option) 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 Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | | Finality is death. | ||
25 | | Perfection is finality. | ||
26 | | Nothing is perfect. | ||
27 | | There are lumps in it. | ||
28 | */ | ||
29 | |||
30 | |||
31 | |||
32 | /* | ||
33 | * TODO: Have a bit set in the log level that says not to include the | ||
34 | * function name. | ||
35 | */ | ||
36 | |||
37 | #include <config_rsync.h> | ||
38 | |||
39 | #include <unistd.h> | ||
40 | #include <stdio.h> | ||
41 | #include <sys/file.h> | ||
42 | #include <string.h> | ||
43 | #include <errno.h> | ||
44 | #include <stdlib.h> | ||
45 | #include <assert.h> | ||
46 | #include <stdarg.h> | ||
47 | |||
48 | #include "rsync.h" | ||
49 | #include "util.h" | ||
50 | #include "trace.h" | ||
51 | |||
52 | |||
53 | rs_trace_fn_t *rs_trace_impl = rs_trace_stderr; | ||
54 | |||
55 | int rs_trace_level = RS_LOG_INFO; | ||
56 | |||
57 | #ifdef HAVE_PROGRAM_INVOCATION_NAME | ||
58 | # define MY_NAME program_invocation_short_name | ||
59 | #else | ||
60 | # define MY_NAME "librsync" | ||
61 | #endif | ||
62 | |||
63 | static void rs_log_va(int level, char const *fn, char const *fmt, va_list va); | ||
64 | |||
65 | #if SIZEOF_SIZE_T > SIZEOF_LONG | ||
66 | # warning size_t is larger than a long integer, values in trace messages may be wrong | ||
67 | #endif | ||
68 | |||
69 | |||
70 | /** | ||
71 | * Log severity strings, if any. Must match ordering in | ||
72 | * ::rs_loglevel. | ||
73 | */ | ||
74 | static const char *rs_severities[] = { | ||
75 | "EMERGENCY! ", "ALERT! ", "CRITICAL! ", "ERROR: ", "Warning: ", | ||
76 | "", "", "" | ||
77 | }; | ||
78 | |||
79 | |||
80 | |||
81 | /** | ||
82 | * \brief Set the destination of trace information. | ||
83 | * | ||
84 | * The callback scheme allows for use within applications that may | ||
85 | * have their own particular ways of reporting errors: log files for a | ||
86 | * web server, perhaps, and an error dialog for a browser. | ||
87 | * | ||
88 | * \todo Do we really need such fine-grained control, or just yes/no | ||
89 | * tracing? | ||
90 | */ | ||
91 | void | ||
92 | rs_trace_to(rs_trace_fn_t * new_impl) | ||
93 | { | ||
94 | rs_trace_impl = new_impl; | ||
95 | } | ||
96 | |||
97 | |||
98 | /** | ||
99 | * Set the least important message severity that will be output. | ||
100 | */ | ||
101 | void | ||
102 | rs_trace_set_level(rs_loglevel level) | ||
103 | { | ||
104 | rs_trace_level = level; | ||
105 | } | ||
106 | |||
107 | |||
108 | static void | ||
109 | rs_log_va(int flags, char const *fn, char const *fmt, va_list va) | ||
110 | { | ||
111 | int level = flags & RS_LOG_PRIMASK; | ||
112 | |||
113 | if (rs_trace_impl && level <= rs_trace_level) { | ||
114 | char buf[1000]; | ||
115 | char full_buf[1000]; | ||
116 | |||
117 | vsnprintf(buf, sizeof buf - 1, fmt, va); | ||
118 | |||
119 | if (flags & RS_LOG_NONAME) { | ||
120 | snprintf(full_buf, sizeof full_buf - 1, | ||
121 | "%s: %s%s\n", | ||
122 | MY_NAME, rs_severities[level], buf); | ||
123 | } else { | ||
124 | snprintf(full_buf, sizeof full_buf - 1, | ||
125 | "%s: %s(%s) %s\n", | ||
126 | MY_NAME, rs_severities[level], fn, buf); | ||
127 | } | ||
128 | |||
129 | rs_trace_impl(level, full_buf); | ||
130 | } | ||
131 | } | ||
132 | |||
133 | |||
134 | |||
135 | /** | ||
136 | * Called by a macro, used on platforms where we can't determine the | ||
137 | * calling function name. | ||
138 | */ | ||
139 | void | ||
140 | rs_log0_nofn(int level, char const *fmt, ...) | ||
141 | { | ||
142 | va_list va; | ||
143 | |||
144 | va_start(va, fmt); | ||
145 | rs_log_va(level, PACKAGE, fmt, va); | ||
146 | va_end(va); | ||
147 | } | ||
148 | |||
149 | |||
150 | /* Called by a macro that prepends the calling function name, | ||
151 | * etc. */ | ||
152 | void | ||
153 | rs_log0(int level, char const *fn, char const *fmt, ...) | ||
154 | { | ||
155 | va_list va; | ||
156 | |||
157 | va_start(va, fmt); | ||
158 | rs_log_va(level, fn, fmt, va); | ||
159 | va_end(va); | ||
160 | } | ||
161 | |||
162 | |||
163 | void | ||
164 | rs_trace_stderr(int UNUSED(level), char const *msg) | ||
165 | { | ||
166 | /* NOTE NO TRAILING NUL */ | ||
167 | write(STDERR_FILENO, msg, strlen(msg)); | ||
168 | } | ||
169 | |||
170 | |||
171 | /* This is called directly if the machine doesn't allow varargs | ||
172 | * macros. */ | ||
173 | void | ||
174 | rs_fatal0(char const *s, ...) | ||
175 | { | ||
176 | va_listva; | ||
177 | |||
178 | va_start(va, s); | ||
179 | rs_log_va(RS_LOG_CRIT, PACKAGE, s, va); | ||
180 | va_end(va); | ||
181 | } | ||
182 | |||
183 | |||
184 | /* This is called directly if the machine doesn't allow varargs | ||
185 | * macros. */ | ||
186 | void | ||
187 | rs_error0(char const *s, ...) | ||
188 | { | ||
189 | va_listva; | ||
190 | |||
191 | va_start(va, s); | ||
192 | rs_log_va(RS_LOG_ERR, PACKAGE, s, va); | ||
193 | va_end(va); | ||
194 | } | ||
195 | |||
196 | |||
197 | /* This is called directly if the machine doesn't allow varargs | ||
198 | * macros. */ | ||
199 | void | ||
200 | rs_trace0(char const *s, ...) | ||
201 | { | ||
202 | va_listva; | ||
203 | |||
204 | va_start(va, s); | ||
205 | rs_log_va(RS_LOG_DEBUG, PACKAGE, s, va); | ||
206 | va_end(va); | ||
207 | } | ||
208 | |||
209 | |||
210 | /** | ||
211 | * Return true if the library contains trace code; otherwise false. | ||
212 | * If this returns false, then trying to turn trace on will achieve | ||
213 | * nothing. | ||
214 | */ | ||
215 | int | ||
216 | rs_supports_trace(void) | ||
217 | { | ||
218 | #ifdef DO_RS_TRACE | ||
219 | return 1; | ||
220 | #else | ||
221 | return 0; | ||
222 | #endif /* !DO_RS_TRACE */ | ||
223 | } | ||
224 | |||
225 | |||
diff --git a/rsync/trace.h b/rsync/trace.h new file mode 100644 index 0000000..60a6477 --- a/dev/null +++ b/rsync/trace.h | |||
@@ -0,0 +1,122 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- generate and apply network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Lesser General Public License as published by | ||
10 | * the Free Software Foundation; either version 2.1 of the License, or | ||
11 | * (at your option) 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 Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | |||
24 | /* | ||
25 | * TODO: A function like perror that includes strerror output. Apache | ||
26 | * does this by adding flags as well as the severity level which say | ||
27 | * whether such information should be included. | ||
28 | */ | ||
29 | |||
30 | |||
31 | /* | ||
32 | * trace may be turned off. | ||
33 | * | ||
34 | * error is always on, but you can return and continue in some way | ||
35 | * | ||
36 | * fatal terminates the whole process | ||
37 | */ | ||
38 | |||
39 | void rs_fatal0(char const *s, ...); | ||
40 | void rs_error0(char const *s, ...); | ||
41 | void rs_trace0(char const *s, ...); | ||
42 | |||
43 | void rs_log0_nofn(int level, char const *fmt, ...); | ||
44 | |||
45 | #ifdef __GNUC__ | ||
46 | |||
47 | void rs_log0(int level, char const *fn, char const *fmt, ...) | ||
48 | __attribute__ ((format(printf, 3, 4))); | ||
49 | |||
50 | #ifdef DO_RS_TRACE | ||
51 | # define rs_trace(fmt, arg...) \ | ||
52 | do { rs_log0(RS_LOG_DEBUG, __FUNCTION__, fmt , ##arg); \ | ||
53 | } while (0) | ||
54 | #else | ||
55 | # define rs_trace(s, str...) | ||
56 | #endif/* !DO_RS_TRACE */ | ||
57 | |||
58 | /* | ||
59 | * TODO: Don't assume this is a gcc thing; rather test in autoconf for | ||
60 | * support for __FUNCTION__ and varargs macros. One simple way might | ||
61 | * just be to try compiling the definition of one of these functions! | ||
62 | * | ||
63 | * TODO: Also look for the C9X predefined identifier `_function', or | ||
64 | * whatever it's called. | ||
65 | */ | ||
66 | |||
67 | #define rs_log(l, s, str...) do { \ | ||
68 | rs_log0((l), __FUNCTION__, (s) , ##str); \ | ||
69 | } while (0) | ||
70 | |||
71 | |||
72 | #define rs_error(s, str...) do { \ | ||
73 | rs_log0(RS_LOG_ERR, __FUNCTION__, (s) , ##str); \ | ||
74 | } while (0) | ||
75 | |||
76 | |||
77 | #define rs_fatal(s, str...) do { \ | ||
78 | rs_log0(RS_LOG_CRIT, __FUNCTION__, \ | ||
79 | (s) , ##str); \ | ||
80 | abort(); \ | ||
81 | } while (0) | ||
82 | |||
83 | |||
84 | #else /************************* ! __GNUC__ */ | ||
85 | |||
86 | # define rs_fatal rs_fatal0 | ||
87 | # define rs_error rs_error0 | ||
88 | # define rs_log rs_log0_nofn | ||
89 | |||
90 | # ifdef DO_RS_TRACE | ||
91 | # define rs_trace rs_trace0 | ||
92 | # endif /* DO_RS_TRACE */ | ||
93 | #endif /* ! __GNUC__ */ | ||
94 | |||
95 | |||
96 | void rs_log0(int level, char const *fn, char const *fmt, ...); | ||
97 | |||
98 | |||
99 | enum { | ||
100 | RS_LOG_PRIMASK = 7, /**< Mask to extract priority | ||
101 | part. \internal */ | ||
102 | |||
103 | RS_LOG_NONAME = 8 /**< \b Don't show function name in | ||
104 | message. */ | ||
105 | }; | ||
106 | |||
107 | |||
108 | |||
109 | /** | ||
110 | * \macro rs_trace_enabled() | ||
111 | * | ||
112 | * Call this before putting too much effort into generating trace | ||
113 | * messages. | ||
114 | */ | ||
115 | |||
116 | extern int rs_trace_level; | ||
117 | |||
118 | #ifdef DO_RS_TRACE | ||
119 | # define rs_trace_enabled() ((rs_trace_level & RS_LOG_PRIMASK) >= RS_LOG_DEBUG) | ||
120 | #else | ||
121 | # define rs_trace_enabled() 0 | ||
122 | #endif | ||
diff --git a/rsync/tube.c b/rsync/tube.c new file mode 100644 index 0000000..0b82adc --- a/dev/null +++ b/rsync/tube.c | |||
@@ -0,0 +1,264 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- dynamic caching and delta update in HTTP | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Lesser General Public License as published by | ||
10 | * the Free Software Foundation; either version 2.1 of the License, or | ||
11 | * (at your option) 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 Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | | Where a calculator on the ENIAC is | ||
25 | | equpped with 18,000 vaccuum tubes and | ||
26 | | weighs 30 tons, computers in the | ||
27 | | future may have only 1,000 vaccuum | ||
28 | | tubes and perhaps weigh 1 1/2 | ||
29 | | tons. | ||
30 | | -- Popular Mechanics, March 1949 | ||
31 | */ | ||
32 | |||
33 | |||
34 | /* tube: a somewhat elastic but fairly small buffer for data passing | ||
35 | * through a stream. | ||
36 | * | ||
37 | * In most cases the iter can adjust to send just as much data will | ||
38 | * fit. In some cases that would be too complicated, because it has | ||
39 | * to transmit an integer or something similar. So in that case we | ||
40 | * stick whatever won't fit into a small buffer. | ||
41 | * | ||
42 | * A tube can contain some literal data to go out (typically command | ||
43 | * bytes), and also an instruction to copy data from the stream's | ||
44 | * input or from some other location. Both literal data and a copy | ||
45 | * command can be queued at the same time, but only in that order and | ||
46 | * at most one of each. */ | ||
47 | |||
48 | |||
49 | /* | ||
50 | * TODO: As an optimization, write it directly to the stream if | ||
51 | * possible. But for simplicity don't do that yet. | ||
52 | * | ||
53 | * TODO: I think our current copy code will lock up if the application | ||
54 | * only ever calls us with either input or output buffers, and not | ||
55 | * both. So I guess in that case we might need to copy into some | ||
56 | * temporary buffer space, and then back out again later. | ||
57 | */ | ||
58 | |||
59 | |||
60 | #include <config_rsync.h> | ||
61 | |||
62 | #include <assert.h> | ||
63 | #include <stdlib.h> | ||
64 | #include <string.h> | ||
65 | #include <stdio.h> | ||
66 | |||
67 | #include "rsync.h" | ||
68 | #include "trace.h" | ||
69 | #include "util.h" | ||
70 | #include "job.h" | ||
71 | #include "stream.h" | ||
72 | |||
73 | |||
74 | static void rs_tube_catchup_write(rs_job_t *job) | ||
75 | { | ||
76 | rs_buffers_t *stream = job->stream; | ||
77 | int len, remain; | ||
78 | |||
79 | len = job->write_len; | ||
80 | assert(len > 0); | ||
81 | |||
82 | assert(len > 0); | ||
83 | if ((size_t) len > stream->avail_out) | ||
84 | len = stream->avail_out; | ||
85 | |||
86 | if (!stream->avail_out) { | ||
87 | rs_trace("no output space available"); | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | memcpy(stream->next_out, job->write_buf, len); | ||
92 | stream->next_out += len; | ||
93 | stream->avail_out -= len; | ||
94 | |||
95 | remain = job->write_len - len; | ||
96 | rs_trace("transmitted %d write bytes from tube, " | ||
97 | "%d remain to be sent", | ||
98 | len, remain); | ||
99 | |||
100 | if (remain > 0) { | ||
101 | /* Still something left in the tube... */ | ||
102 | memmove(job->write_buf, job->write_buf + len, remain); | ||
103 | } else { | ||
104 | assert(remain == 0); | ||
105 | } | ||
106 | |||
107 | job->write_len = remain; | ||
108 | } | ||
109 | |||
110 | |||
111 | /** | ||
112 | * Execute a copy command, taking data from the scoop. | ||
113 | * | ||
114 | * \sa rs_tube_catchup_copy() | ||
115 | */ | ||
116 | static void | ||
117 | rs_tube_copy_from_scoop(rs_job_t *job) | ||
118 | { | ||
119 | size_t this_len; | ||
120 | rs_buffers_t *stream = job->stream; | ||
121 | |||
122 | this_len = job->copy_len; | ||
123 | if (this_len > job->scoop_avail) { | ||
124 | this_len = job->scoop_avail; | ||
125 | } | ||
126 | if (this_len > stream->avail_out) { | ||
127 | this_len = stream->avail_out; | ||
128 | } | ||
129 | |||
130 | memcpy(stream->next_out, job->scoop_next, this_len); | ||
131 | |||
132 | stream->next_out += this_len; | ||
133 | stream->avail_out -= this_len; | ||
134 | |||
135 | job->scoop_avail -= this_len; | ||
136 | job->scoop_next += this_len; | ||
137 | |||
138 | job->copy_len -= this_len; | ||
139 | |||
140 | rs_trace("caught up on %ld copied bytes from scoop, %ld remain there, " | ||
141 | "%ld remain to be copied", | ||
142 | (long) this_len, (long) job->scoop_avail, (long) job->copy_len); | ||
143 | } | ||
144 | |||
145 | |||
146 | |||
147 | /** | ||
148 | * Catch up on an outstanding copy command. | ||
149 | * | ||
150 | * Takes data from the scoop, and the input (in that order), and | ||
151 | * writes as much as will fit to the output, up to the limit of the | ||
152 | * outstanding copy. | ||
153 | */ | ||
154 | static void rs_tube_catchup_copy(rs_job_t *job) | ||
155 | { | ||
156 | rs_buffers_t *stream = job->stream; | ||
157 | |||
158 | assert(job->write_len == 0); | ||
159 | assert(job->copy_len > 0); | ||
160 | |||
161 | if (job->scoop_avail && job->copy_len) { | ||
162 | /* there's still some data in the scoop, so we should use that. */ | ||
163 | rs_tube_copy_from_scoop(job); | ||
164 | } | ||
165 | |||
166 | if (job->copy_len) { | ||
167 | size_t this_copy; | ||
168 | |||
169 | this_copy = rs_buffers_copy(stream, job->copy_len); | ||
170 | |||
171 | job->copy_len -= this_copy; | ||
172 | |||
173 | rs_trace("copied %.0f bytes from input buffer, %.0f remain to be copied", | ||
174 | (double) this_copy, (double) job->copy_len); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | |||
179 | /* | ||
180 | * Put whatever will fit from the tube into the output of the stream. | ||
181 | * Return RS_DONE if the tube is now empty and ready to accept another | ||
182 | * command, RS_BLOCKED if there is still stuff waiting to go out. | ||
183 | */ | ||
184 | int rs_tube_catchup(rs_job_t *job) | ||
185 | { | ||
186 | if (job->write_len) | ||
187 | rs_tube_catchup_write(job); | ||
188 | |||
189 | if (job->write_len) { | ||
190 | /* there is still write data queued, so we can't send | ||
191 | * anything else. */ | ||
192 | return RS_BLOCKED; | ||
193 | } | ||
194 | |||
195 | if (job->copy_len) | ||
196 | rs_tube_catchup_copy(job); | ||
197 | |||
198 | if (job->copy_len) { | ||
199 | if (job->stream->eof_in && !job->stream->avail_in && !job->scoop_avail) { | ||
200 | rs_log(RS_LOG_ERR, | ||
201 | "reached end of file while copying literal data through buffers"); | ||
202 | return RS_INPUT_ENDED; | ||
203 | } | ||
204 | |||
205 | return RS_BLOCKED; | ||
206 | } | ||
207 | |||
208 | return RS_DONE; | ||
209 | } | ||
210 | |||
211 | |||
212 | /* Check whether there is data in the tube waiting to go out. So if true | ||
213 | * this basically means that the previous command has finished doing all its | ||
214 | * output. */ | ||
215 | int rs_tube_is_idle(rs_job_t const *job) | ||
216 | { | ||
217 | return job->write_len == 0 && job->copy_len == 0; | ||
218 | } | ||
219 | |||
220 | |||
221 | /** | ||
222 | * Queue up a request to copy through \p len bytes from the input to | ||
223 | * the output of the stream. | ||
224 | * | ||
225 | * The data is copied from the scoop (if there is anything there) or | ||
226 | * from the input, on the next call to rs_tube_write(). | ||
227 | * | ||
228 | * We can only accept this request if there is no copy command already | ||
229 | * pending. | ||
230 | */ | ||
231 | /* TODO: Try to do the copy immediately, and return a result. Then, | ||
232 | * people can try to continue if possible. Is this really required? | ||
233 | * Callers can just go out and back in again after flushing the | ||
234 | * tube. */ | ||
235 | void rs_tube_copy(rs_job_t *job, int len) | ||
236 | { | ||
237 | assert(job->copy_len == 0); | ||
238 | |||
239 | job->copy_len = len; | ||
240 | } | ||
241 | |||
242 | |||
243 | |||
244 | /* | ||
245 | * Push some data into the tube for storage. The tube's never | ||
246 | * supposed to get very big, so this will just pop loudly if you do | ||
247 | * that. | ||
248 | * | ||
249 | * We can't accept write data if there's already a copy command in the | ||
250 | * tube, because the write data comes out first. | ||
251 | */ | ||
252 | void | ||
253 | rs_tube_write(rs_job_t *job, const void *buf, size_t len) | ||
254 | { | ||
255 | assert(job->copy_len == 0); | ||
256 | |||
257 | if (len > sizeof(job->write_buf) - job->write_len) { | ||
258 | rs_fatal("tube popped when trying to write %ld bytes!", | ||
259 | (long) len); | ||
260 | } | ||
261 | |||
262 | memcpy(job->write_buf + job->write_len, buf, len); | ||
263 | job->write_len += len; | ||
264 | } | ||
diff --git a/rsync/types.h b/rsync/types.h new file mode 100644 index 0000000..47ff97c --- a/dev/null +++ b/rsync/types.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | |||
24 | |||
25 | #if defined(HAVE_STDINT_H) | ||
26 | # include <stdint.h> | ||
27 | #elif SIZEOF_UNSIGNED_INT == 4 | ||
28 | # define uint32_t unsigned int | ||
29 | #elif SIZEOF_UNSIGNED_LONG == 4 | ||
30 | # define uint32_t unsigned long | ||
31 | #elif SIZEOF_UNSIGNED_SHORT == 4 | ||
32 | # define uint32_t unsigned short | ||
33 | #else | ||
34 | # error "can't find an appropriate 32-bit integer type" | ||
35 | #endif | ||
36 | |||
diff --git a/rsync/util.c b/rsync/util.c new file mode 100644 index 0000000..f0f3973 --- a/dev/null +++ b/rsync/util.c | |||
@@ -0,0 +1,70 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Lesser General Public License as published by | ||
10 | * the Free Software Foundation; either version 2.1 of the License, or | ||
11 | * (at your option) 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 Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | |||
24 | /* | ||
25 | | On heroin, I have all the answers. | ||
26 | */ | ||
27 | |||
28 | |||
29 | #include <config_rsync.h> | ||
30 | |||
31 | #include <stdlib.h> | ||
32 | #include <string.h> | ||
33 | #include <stdio.h> | ||
34 | |||
35 | #include "util.h" | ||
36 | #include "rsync.h" | ||
37 | #include "trace.h" | ||
38 | |||
39 | void | ||
40 | rs_bzero(void *buf, size_t size) | ||
41 | { | ||
42 | memset(buf, 0, size); | ||
43 | } | ||
44 | |||
45 | |||
46 | void * | ||
47 | rs_alloc_struct0(size_t size, char const *name) | ||
48 | { | ||
49 | void *p; | ||
50 | |||
51 | if (!(p = malloc(size))) { | ||
52 | rs_fatal("couldn't allocate instance of %s", name); | ||
53 | } | ||
54 | rs_bzero(p, size); | ||
55 | return p; | ||
56 | } | ||
57 | |||
58 | |||
59 | |||
60 | void * | ||
61 | rs_alloc(size_t size, char const *name) | ||
62 | { | ||
63 | void *p; | ||
64 | |||
65 | if (!(p = malloc(size))) { | ||
66 | rs_fatal("couldn't allocate instance of %s", name); | ||
67 | } | ||
68 | |||
69 | return p; | ||
70 | } | ||
diff --git a/rsync/util.h b/rsync/util.h new file mode 100644 index 0000000..2793256 --- a/dev/null +++ b/rsync/util.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * Copyright (C) 1999 by Andrew Tridgell <tridge@samba.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU Lesser General Public License | ||
11 | * as published by the Free Software Foundation; either version 2.1 of | ||
12 | * the License, or (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public | ||
20 | * License along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | |||
25 | void * rs_alloc(size_t size, char const *name); | ||
26 | void *rs_alloc_struct0(size_t size, char const *name); | ||
27 | |||
28 | void rs_bzero(void *buf, size_t size); | ||
29 | |||
30 | |||
31 | /* | ||
32 | * Allocate and zero-fill an instance of TYPE. | ||
33 | */ | ||
34 | #define rs_alloc_struct(type) \ | ||
35 | ((type *) rs_alloc_struct0(sizeof(type), #type)) | ||
36 | |||
37 | |||
38 | #ifdef __GNUC__ | ||
39 | # define UNUSED(x) x __attribute__((unused)) | ||
40 | #elif __LCLINT__ | ||
41 | # define UNUSED(x) /*@unused@*/ x | ||
42 | #else /* !__GNUC__ && !__LCLINT__ */ | ||
43 | # define UNUSED(x) x | ||
44 | #endif /* !__GNUC__ && !__LCLINT__ */ | ||
diff --git a/rsync/version.c b/rsync/version.c new file mode 100644 index 0000000..a76f826 --- a/dev/null +++ b/rsync/version.c | |||
@@ -0,0 +1,33 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- dynamic caching and delta update in HTTP | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <config_rsync.h> | ||
24 | |||
25 | #include <stdio.h> | ||
26 | |||
27 | #include "rsync.h" | ||
28 | |||
29 | |||
30 | /** \brief Library version string. */ | ||
31 | char const rs_librsync_version[] = (PACKAGE " " VERSION); | ||
32 | |||
33 | |||
diff --git a/rsync/whole.c b/rsync/whole.c new file mode 100644 index 0000000..153d402 --- a/dev/null +++ b/rsync/whole.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | | Is it possible that software is not | ||
25 | | like anything else, that it is meant | ||
26 | | to be discarded: that the whole point | ||
27 | | is to always see it as a soap bubble? | ||
28 | | -- Alan Perlis | ||
29 | */ | ||
30 | |||
31 | |||
32 | |||
33 | #include <config_rsync.h> | ||
34 | |||
35 | #include <assert.h> | ||
36 | #include <stdlib.h> | ||
37 | #include <unistd.h> | ||
38 | #include <stdio.h> | ||
39 | #include <string.h> | ||
40 | #include <errno.h> | ||
41 | |||
42 | #include <rsync.h> | ||
43 | |||
44 | #include "trace.h" | ||
45 | #include "fileutil.h" | ||
46 | #include "sumset.h" | ||
47 | #include "job.h" | ||
48 | #include "buf.h" | ||
49 | #include "whole.h" | ||
50 | #include "util.h" | ||
51 | |||
52 | /** | ||
53 | * Run a job continuously, with input to/from the two specified files. | ||
54 | * The job should already be set up, and must be free by the caller | ||
55 | * after return. | ||
56 | * | ||
57 | * Buffers of ::rs_inbuflen and ::rs_outbuflen are allocated for | ||
58 | * temporary storage. | ||
59 | * | ||
60 | * \param in_file Source of input bytes, or NULL if the input buffer | ||
61 | * should not be filled. | ||
62 | * | ||
63 | * \return RS_DONE if the job completed, or otherwise an error result. | ||
64 | */ | ||
65 | rs_result | ||
66 | rs_whole_run(rs_job_t *job, FILE *in_file, FILE *out_file) | ||
67 | { | ||
68 | rs_buffers_t buf; | ||
69 | rs_result result; | ||
70 | rs_filebuf_t *in_fb = NULL, *out_fb = NULL; | ||
71 | |||
72 | if (in_file) | ||
73 | in_fb = rs_filebuf_new(in_file, rs_inbuflen); | ||
74 | |||
75 | if (out_file) | ||
76 | out_fb = rs_filebuf_new(out_file, rs_outbuflen); | ||
77 | |||
78 | result = rs_job_drive(job, &buf, | ||
79 | in_fb ? rs_infilebuf_fill : NULL, in_fb, | ||
80 | out_fb ? rs_outfilebuf_drain : NULL, out_fb); | ||
81 | |||
82 | if (in_fb) | ||
83 | rs_filebuf_free(in_fb); | ||
84 | |||
85 | if (out_fb) | ||
86 | rs_filebuf_free(out_fb); | ||
87 | |||
88 | return result; | ||
89 | } | ||
90 | |||
91 | |||
92 | |||
93 | /** | ||
94 | * Generate the signature of a basis file, and write it out to | ||
95 | * another. | ||
96 | * | ||
97 | * \param new_block_len block size for signature generation, in bytes | ||
98 | * | ||
99 | * \param strong_len truncated length of strong checksums, in bytes | ||
100 | * | ||
101 | * \sa rs_sig_begin() | ||
102 | */ | ||
103 | rs_result | ||
104 | rs_sig_file(FILE *old_file, FILE *sig_file, size_t new_block_len, | ||
105 | size_t strong_len, rs_stats_t *stats) | ||
106 | { | ||
107 | rs_job_t *job; | ||
108 | rs_result r; | ||
109 | |||
110 | job = rs_sig_begin(new_block_len, strong_len); | ||
111 | r = rs_whole_run(job, old_file, sig_file); | ||
112 | if (stats) | ||
113 | memcpy(stats, &job->stats, sizeof *stats); | ||
114 | rs_job_free(job); | ||
115 | |||
116 | return r; | ||
117 | } | ||
118 | |||
119 | |||
120 | /** | ||
121 | * Load signatures from a signature file into memory. Return a | ||
122 | * pointer to the newly allocated structure in SUMSET. | ||
123 | * | ||
124 | * \sa rs_readsig_begin() | ||
125 | */ | ||
126 | rs_result | ||
127 | rs_loadsig_file(FILE *sig_file, rs_signature_t **sumset, rs_stats_t *stats) | ||
128 | { | ||
129 | rs_job_t *job; | ||
130 | rs_result r; | ||
131 | |||
132 | job = rs_loadsig_begin(sumset); | ||
133 | r = rs_whole_run(job, sig_file, NULL); | ||
134 | if (stats) | ||
135 | memcpy(stats, &job->stats, sizeof *stats); | ||
136 | rs_job_free(job); | ||
137 | |||
138 | return r; | ||
139 | } | ||
140 | |||
141 | |||
142 | |||
143 | rs_result | ||
144 | rs_delta_file(rs_signature_t *sig, FILE *new_file, FILE *delta_file, | ||
145 | rs_stats_t *stats) | ||
146 | { | ||
147 | rs_job_t *job; | ||
148 | rs_result r; | ||
149 | |||
150 | job = rs_delta_begin(sig); | ||
151 | |||
152 | r = rs_whole_run(job, new_file, delta_file); | ||
153 | |||
154 | if (stats) | ||
155 | memcpy(stats, &job->stats, sizeof *stats); | ||
156 | |||
157 | rs_job_free(job); | ||
158 | |||
159 | return r; | ||
160 | } | ||
161 | |||
162 | |||
163 | |||
164 | rs_result rs_patch_file(FILE *basis_file, FILE *delta_file, FILE *new_file, | ||
165 | rs_stats_t *stats) | ||
166 | { | ||
167 | rs_job_t *job; | ||
168 | rs_result r; | ||
169 | |||
170 | job = rs_patch_begin(rs_file_copy_cb, basis_file); | ||
171 | |||
172 | r = rs_whole_run(job, delta_file, new_file); | ||
173 | |||
174 | if (stats) | ||
175 | memcpy(stats, &job->stats, sizeof *stats); | ||
176 | |||
177 | rs_job_free(job); | ||
178 | |||
179 | return r; | ||
180 | } | ||
diff --git a/rsync/whole.h b/rsync/whole.h new file mode 100644 index 0000000..67e54f7 --- a/dev/null +++ b/rsync/whole.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- the library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | |||
24 | rs_result rs_whole_run(rs_job_t *job, FILE *in_file, FILE *out_file); | ||