summaryrefslogtreecommitdiff
path: root/rsync
authorkergoth <kergoth>2002-01-25 22:14:26 (UTC)
committer kergoth <kergoth>2002-01-25 22:14:26 (UTC)
commit15318cad33835e4e2dc620d033e43cd930676cdd (patch) (unidiff)
treec2fa0399a2c47fda8e2cd0092c73a809d17f68eb /rsync
downloadopie-15318cad33835e4e2dc620d033e43cd930676cdd.zip
opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.gz
opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.bz2
Initial revision
Diffstat (limited to 'rsync') (more/less context) (ignore whitespace changes)
-rw-r--r--rsync/AUTHORS2
-rw-r--r--rsync/COPYING515
-rw-r--r--rsync/Makefile.in391
-rw-r--r--rsync/README62
-rw-r--r--rsync/THANKS21
-rw-r--r--rsync/acconfig.h55
-rw-r--r--rsync/base64.c101
-rw-r--r--rsync/buf.c214
-rw-r--r--rsync/buf.h31
-rw-r--r--rsync/checksum.c81
-rw-r--r--rsync/checksum.h30
-rw-r--r--rsync/command.c61
-rw-r--r--rsync/command.h58
-rw-r--r--rsync/config_linux.h115
-rw-r--r--rsync/config_rsync.h2
-rw-r--r--rsync/delta.c351
-rw-r--r--rsync/emit.c131
-rw-r--r--rsync/emit.h32
-rw-r--r--rsync/fileutil.c70
-rw-r--r--rsync/fileutil.h23
-rw-r--r--rsync/hex.c46
-rw-r--r--rsync/job.c251
-rw-r--r--rsync/job.h99
-rw-r--r--rsync/mdfour.c326
-rw-r--r--rsync/mksum.c155
-rw-r--r--rsync/msg.c75
-rw-r--r--rsync/netint.c185
-rw-r--r--rsync/netint.h32
-rw-r--r--rsync/patch.c317
-rw-r--r--rsync/protocol.h45
-rw-r--r--rsync/prototab.c277
-rw-r--r--rsync/prototab.h270
-rw-r--r--rsync/qrsync.cpp110
-rw-r--r--rsync/qrsync.h18
-rw-r--r--rsync/rdiff.c358
-rw-r--r--rsync/readsums.c214
-rw-r--r--rsync/rsync.h388
-rw-r--r--rsync/scoop.c271
-rw-r--r--rsync/search.c162
-rw-r--r--rsync/search.h29
-rw-r--r--rsync/snprintf.c822
-rw-r--r--rsync/stats.c114
-rw-r--r--rsync/stream.c155
-rw-r--r--rsync/stream.h46
-rw-r--r--rsync/sumset.c83
-rw-r--r--rsync/sumset.h67
-rw-r--r--rsync/trace.c225
-rw-r--r--rsync/trace.h122
-rw-r--r--rsync/tube.c264
-rw-r--r--rsync/types.h36
-rw-r--r--rsync/util.c70
-rw-r--r--rsync/util.h44
-rw-r--r--rsync/version.c33
-rw-r--r--rsync/whole.c180
-rw-r--r--rsync/whole.h24
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 @@
1Martin Pool <mbp@samba.org>
2Andrew 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
17freedom to share and change it. By contrast, the GNU General Public
18Licenses are intended to guarantee your freedom to share and change
19free software--to make sure the software is free for all its users.
20
21 This license, the Lesser General Public License, applies to some
22specially designated software packages--typically libraries--of the
23Free Software Foundation and other authors who decide to use it. You
24can use it too, but we suggest you first think carefully about whether
25this license or the ordinary General Public License is the better
26strategy to use in any particular case, based on the explanations
27below.
28
29 When we speak of free software, we are referring to freedom of use,
30not price. Our General Public Licenses are designed to make sure that
31you have the freedom to distribute copies of free software (and charge
32for this service if you wish); that you receive source code or can get
33it if you want it; that you can change the software and use pieces of
34it in new free programs; and that you are informed that you can do
35these things.
36
37 To protect your rights, we need to make restrictions that forbid
38distributors to deny you these rights or to ask you to surrender these
39rights. These restrictions translate to certain responsibilities for
40you 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
43or for a fee, you must give the recipients all the rights that we gave
44you. You must make sure that they, too, receive or can get the source
45code. If you link other code with the library, you must provide
46complete object files to the recipients, so that they can relink them
47with the library after making changes to the library and recompiling
48it. 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
51library, and (2) we offer you this license, which gives you legal
52permission to copy, distribute and/or modify the library.
53
54 To protect each distributor, we want to make it very clear that
55there is no warranty for the free library. Also, if the library is
56modified by someone else and passed on, the recipients should know
57that what they have is not the original version, so that the original
58author's reputation will not be affected by problems that might be
59introduced by others.
60^L
61 Finally, software patents pose a constant threat to the existence of
62any free program. We wish to make sure that a company cannot
63effectively restrict the users of a free program by obtaining a
64restrictive license from a patent holder. Therefore, we insist that
65any patent license obtained for a version of the library must be
66consistent with the full freedom of use specified in this license.
67
68 Most GNU software, including some libraries, is covered by the
69ordinary GNU General Public License. This license, the GNU Lesser
70General Public License, applies to certain designated libraries, and
71is quite different from the ordinary General Public License. We use
72this license for certain libraries in order to permit linking those
73libraries into non-free programs.
74
75 When a program is linked with a library, whether statically or using
76a shared library, the combination of the two is legally speaking a
77combined work, a derivative of the original library. The ordinary
78General Public License therefore permits such linking only if the
79entire combination fits its criteria of freedom. The Lesser General
80Public License permits more lax criteria for linking other code with
81the library.
82
83 We call this license the "Lesser" General Public License because it
84does Less to protect the user's freedom than the ordinary General
85Public License. It also provides other free software developers Less
86of an advantage over competing non-free programs. These disadvantages
87are the reason we use the ordinary General Public License for many
88libraries. However, the Lesser license provides advantages in certain
89special circumstances.
90
91 For example, on rare occasions, there may be a special need to
92encourage the widest possible use of a certain library, so that it
93becomes
94a de-facto standard. To achieve this, non-free programs must be
95allowed to use the library. A more frequent case is that a free
96library does the same job as widely used non-free libraries. In this
97case, there is little to gain by limiting the free library to free
98software only, so we use the Lesser General Public License.
99
100 In other cases, permission to use a particular library in non-free
101programs enables a greater number of people to use a large body of
102free software. For example, permission to use the GNU C Library in
103non-free programs enables many more people to use the whole GNU
104operating system, as well as its variant, the GNU/Linux operating
105system.
106
107 Although the Lesser General Public License is Less protective of the
108users' freedom, it does ensure that the user of a program that is
109linked with the Library has the freedom and the wherewithal to run
110that program using a modified version of the Library.
111
112 The precise terms and conditions for copying, distribution and
113modification follow. Pay close attention to the difference between a
114"work based on the library" and a "work that uses the library". The
115former contains code derived from the library, whereas the latter must
116be 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
122program which contains a notice placed by the copyright holder or
123other authorized party saying it may be distributed under the terms of
124this Lesser General Public License (also called "this License").
125Each licensee is addressed as "you".
126
127 A "library" means a collection of software functions and/or data
128prepared 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
132which has been distributed under these terms. A "work based on the
133Library" means either the Library or any derivative work under
134copyright law: that is to say, a work containing the Library or a
135portion of it, either verbatim or with modifications and/or translated
136straightforwardly into another language. (Hereinafter, translation is
137included without limitation in the term "modification".)
138
139 "Source code" for a work means the preferred form of the work for
140making modifications to it. For a library, complete source code means
141all the source code for all modules it contains, plus any associated
142interface definition files, plus the scripts used to control
143compilation
144and installation of the library.
145
146 Activities other than copying, distribution and modification are not
147covered by this License; they are outside its scope. The act of
148running a program using the Library is not restricted, and output from
149such a program is covered only if its contents constitute a work based
150on the Library (independent of the use of the Library in a tool for
151writing it). Whether that is true depends on what the Library does
152and what the program that uses the Library does.
153
154 1. You may copy and distribute verbatim copies of the Library's
155complete source code as you receive it, in any medium, provided that
156you conspicuously and appropriately publish on each copy an
157appropriate copyright notice and disclaimer of warranty; keep intact
158all the notices that refer to this License and to the absence of any
159warranty; and distribute a copy of this License along with the
160Library.
161
162 You may charge a fee for the physical act of transferring a copy,
163and you may at your option offer warranty protection in exchange for a
164fee.
165
166 2. You may modify your copy or copies of the Library or any portion
167of it, thus forming a work based on the Library, and copy and
168distribute such modifications or work under the terms of Section 1
169above, 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
194These requirements apply to the modified work as a whole. If
195identifiable sections of that work are not derived from the Library,
196and can be reasonably considered independent and separate works in
197themselves, then this License, and its terms, do not apply to those
198sections when you distribute them as separate works. But when you
199distribute the same sections as part of a whole which is a work based
200on the Library, the distribution of the whole must be on the terms of
201this License, whose permissions for other licensees extend to the
202entire whole, and thus to each and every part regardless of who wrote
203it.
204
205Thus, it is not the intent of this section to claim rights or contest
206your rights to work written entirely by you; rather, the intent is to
207exercise the right to control the distribution of derivative or
208collective works based on the Library.
209
210In addition, mere aggregation of another work not based on the Library
211with the Library (or with a work based on the Library) on a volume of
212a storage or distribution medium does not bring the other work under
213the scope of this License.
214
215 3. You may opt to apply the terms of the ordinary GNU General Public
216License instead of this License to a given copy of the Library. To do
217this, you must alter all the notices that refer to this License, so
218that they refer to the ordinary GNU General Public License, version 2,
219instead of to this License. (If a newer version than version 2 of the
220ordinary GNU General Public License has appeared, then you can specify
221that version instead if you wish.) Do not make any other change in
222these notices.
223^L
224 Once this change is made in a given copy, it is irreversible for
225that copy, so the ordinary GNU General Public License applies to all
226subsequent copies and derivative works made from that copy.
227
228 This option is useful when you wish to copy part of the code of
229the Library into a program that is not a library.
230
231 4. You may copy and distribute the Library (or a portion or
232derivative of it, under Section 2) in object code or executable form
233under the terms of Sections 1 and 2 above provided that you accompany
234it with the complete corresponding machine-readable source code, which
235must be distributed under the terms of Sections 1 and 2 above on a
236medium customarily used for software interchange.
237
238 If distribution of object code is made by offering access to copy
239from a designated place, then offering equivalent access to copy the
240source code from the same place satisfies the requirement to
241distribute the source code, even though third parties are not
242compelled to copy the source along with the object code.
243
244 5. A program that contains no derivative of any portion of the
245Library, but is designed to work with the Library by being compiled or
246linked with it, is called a "work that uses the Library". Such a
247work, in isolation, is not a derivative work of the Library, and
248therefore falls outside the scope of this License.
249
250 However, linking a "work that uses the Library" with the Library
251creates an executable that is a derivative of the Library (because it
252contains portions of the Library), rather than a "work that uses the
253library". The executable is therefore covered by this License.
254Section 6 states terms for distribution of such executables.
255
256 When a "work that uses the Library" uses material from a header file
257that is part of the Library, the object code for the work may be a
258derivative work of the Library even though the source code is not.
259Whether this is true is especially significant if the work can be
260linked without the Library, or if the work is itself a library. The
261threshold for this to be true is not precisely defined by law.
262
263 If such an object file uses only numerical parameters, data
264structure layouts and accessors, and small macros and small inline
265functions (ten lines or less in length), then the use of the object
266file is unrestricted, regardless of whether it is legally a derivative
267work. (Executables containing this object code plus portions of the
268Library will still fall under Section 6.)
269
270 Otherwise, if the work is a derivative of the Library, you may
271distribute the object code for the work under the terms of Section 6.
272Any executables containing that work also fall under Section 6,
273whether 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
276link a "work that uses the Library" with the Library to produce a
277work containing portions of the Library, and distribute that work
278under terms of your choice, provided that the terms permit
279modification of the work for the customer's own use and reverse
280engineering for debugging such modifications.
281
282 You must give prominent notice with each copy of the work that the
283Library is used in it and that the Library and its use are covered by
284this License. You must supply a copy of this License. If the work
285during execution displays copyright notices, you must include the
286copyright notice for the Library among them, as well as a reference
287directing the user to the copy of this License. Also, you must do one
288of 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
323Library" must include any data and utility programs needed for
324reproducing the executable from it. However, as a special exception,
325the materials to be distributed need not include anything that is
326normally distributed (in either source or binary form) with the major
327components (compiler, kernel, and so on) of the operating system on
328which the executable runs, unless that component itself accompanies
329the executable.
330
331 It may happen that this requirement contradicts the license
332restrictions of other proprietary libraries that do not normally
333accompany the operating system. Such a contradiction means you cannot
334use both them and the Library together in an executable that you
335distribute.
336^L
337 7. You may place library facilities that are a work based on the
338Library side-by-side in a single library together with other library
339facilities not covered by this License, and distribute such a combined
340library, provided that the separate distribution of the work based on
341the Library and of the other library facilities is otherwise
342permitted, 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
354the Library except as expressly provided under this License. Any
355attempt otherwise to copy, modify, sublicense, link with, or
356distribute the Library is void, and will automatically terminate your
357rights under this License. However, parties who have received copies,
358or rights, from you under this License will not have their licenses
359terminated so long as such parties remain in full compliance.
360
361 9. You are not required to accept this License, since you have not
362signed it. However, nothing else grants you permission to modify or
363distribute the Library or its derivative works. These actions are
364prohibited by law if you do not accept this License. Therefore, by
365modifying or distributing the Library (or any work based on the
366Library), you indicate your acceptance of this License to do so, and
367all its terms and conditions for copying, distributing or modifying
368the Library or works based on it.
369
370 10. Each time you redistribute the Library (or any work based on the
371Library), the recipient automatically receives a license from the
372original licensor to copy, distribute, link with or modify the Library
373subject to these terms and conditions. You may not impose any further
374restrictions on the recipients' exercise of the rights granted herein.
375You are not responsible for enforcing compliance by third parties with
376this License.
377^L
378 11. If, as a consequence of a court judgment or allegation of patent
379infringement or for any other reason (not limited to patent issues),
380conditions are imposed on you (whether by court order, agreement or
381otherwise) that contradict the conditions of this License, they do not
382excuse you from the conditions of this License. If you cannot
383distribute so as to satisfy simultaneously your obligations under this
384License and any other pertinent obligations, then as a consequence you
385may not distribute the Library at all. For example, if a patent
386license would not permit royalty-free redistribution of the Library by
387all those who receive copies directly or indirectly through you, then
388the only way you could satisfy both it and this License would be to
389refrain entirely from distribution of the Library.
390
391If any portion of this section is held invalid or unenforceable under
392any particular circumstance, the balance of the section is intended to
393apply, and the section as a whole is intended to apply in other
394circumstances.
395
396It is not the purpose of this section to induce you to infringe any
397patents or other property right claims or to contest validity of any
398such claims; this section has the sole purpose of protecting the
399integrity of the free software distribution system which is
400implemented by public license practices. Many people have made
401generous contributions to the wide range of software distributed
402through that system in reliance on consistent application of that
403system; it is up to the author/donor to decide if he or she is willing
404to distribute software through any other system and a licensee cannot
405impose that choice.
406
407This section is intended to make thoroughly clear what is believed to
408be a consequence of the rest of this License.
409
410 12. If the distribution and/or use of the Library is restricted in
411certain countries either by patents or by copyrighted interfaces, the
412original copyright holder who places the Library under this License
413may add an explicit geographical distribution limitation excluding those
414countries, so that distribution is permitted only in or among
415countries not thus excluded. In such case, this License incorporates
416the limitation as if written in the body of this License.
417
418 13. The Free Software Foundation may publish revised and/or new
419versions of the Lesser General Public License from time to time.
420Such new versions will be similar in spirit to the present version,
421but may differ in detail to address new problems or concerns.
422
423Each version is given a distinguishing version number. If the Library
424specifies a version number of this License which applies to it and
425"any later version", you have the option of following the terms and
426conditions either of that version or of any later version published by
427the Free Software Foundation. If the Library does not specify a
428license version number, you may choose any version ever published by
429the Free Software Foundation.
430^L
431 14. If you wish to incorporate parts of the Library into other free
432programs whose distribution conditions are incompatible with these,
433write to the author to ask for permission. For software which is
434copyrighted by the Free Software Foundation, write to the Free
435Software Foundation; we sometimes make exceptions for this. Our
436decision will be guided by the two goals of preserving the free status
437of all derivatives of our free software and of promoting the sharing
438and reuse of software generally.
439
440 NO WARRANTY
441
442 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
443WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
444EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
445OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
446KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
447IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
448PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
449LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
450THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
451
452 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
453WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
454AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
455FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
456CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
457LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
458RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
459FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
460SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
461DAMAGES.
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
468possible use to the public, we recommend making it free software that
469everyone can redistribute and change. You can do so by permitting
470redistribution under these terms (or, alternatively, under the terms
471of the ordinary General Public License).
472
473 To apply these terms, attach the following notices to the library.
474It is safest to attach them to the start of each source file to most
475effectively convey the exclusion of warranty; and each file should
476have at least the "copyright" line and a pointer to where the full
477notice is found.
478
479
480 <one line to give the library's name and a brief idea of what it
481does.>
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
498Also add information on how to contact you by electronic and paper
499mail.
500
501You should also get your employer (if you work as a programmer) or
502your
503school, if any, to sign a "copyright disclaimer" for the library, if
504necessary. 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
508Random Hacker.
509
510 <signature of Ty Coon>, 1 April 1990
511 Ty Coon, President of Vice
512
513That'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
17DESTDIR = $(QTDIR)/lib$(PROJMAK)/
18VER_MAJ = 1
19VER_MIN = 0
20VER_PATCH = 0
21 TARGET= rsync
22TARGET1 = 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
96INTERFACES =
97UICDECLS =
98UICIMPLS =
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
125all: $(DESTDIR)$(SYSCONF_LINK_TARGET)
126
127$(DESTDIR)$(SYSCONF_LINK_TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS)
128 $(SYSCONF_LINK_LIB)
129
130moc: $(SRCMOC)
131
132tmake: Makefile.in
133
134Makefile.in: rsync.pro
135 tmake rsync.pro -o Makefile.in
136
137clean:
138 -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS)
139 -rm -f *~ core
140 -rm -f allmoc.cpp
141
142####### Extension Modules
143
144listpromodules:
145 @echo
146
147listallmodules:
148 @echo
149
150listaddonpromodules:
151 @echo
152
153listaddonentmodules:
154 @echo
155
156
157REQUIRES=
158
159####### Sub-libraries
160
161
162###### Combined headers
163
164
165
166####### Compile
167
168base64.o: base64.c \
169 config.h \
170 config_linux.h \
171 rsync.h
172
173buf.o: buf.c \
174 config.h \
175 config_linux.h \
176 rsync.h \
177 trace.h \
178 buf.h \
179 util.h
180
181checksum.o: checksum.c \
182 config.h \
183 config_linux.h \
184 rsync.h \
185 checksum.h
186
187command.o: command.c \
188 config.h \
189 config_linux.h \
190 rsync.h \
191 command.h
192
193delta.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
207emit.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
220fileutil.o: fileutil.c \
221 config.h \
222 config_linux.h \
223 rsync.h \
224 fileutil.h \
225 trace.h
226
227hex.o: hex.c \
228 config.h \
229 config_linux.h \
230 rsync.h
231
232job.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
242mdfour.o: mdfour.c \
243 config.h \
244 config_linux.h \
245 rsync.h \
246 trace.h \
247 types.h
248
249mksum.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
262msg.o: msg.c \
263 config.h \
264 config_linux.h \
265 rsync.h
266
267netint.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
276patch.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
290prototab.o: prototab.c \
291 config.h \
292 config_linux.h \
293 rsync.h \
294 protocol.h \
295 command.h \
296 prototab.h
297
298readsums.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
310scoop.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
319search.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
329stats.o: stats.c \
330 config.h \
331 config_linux.h \
332 rsync.h \
333 trace.h
334
335stream.o: stream.c \
336 config.h \
337 config_linux.h \
338 rsync.h \
339 stream.h \
340 util.h \
341 trace.h
342
343sumset.o: sumset.c \
344 config.h \
345 config_linux.h \
346 rsync.h \
347 sumset.h \
348 util.h \
349 trace.h
350
351trace.o: trace.c \
352 config.h \
353 config_linux.h \
354 rsync.h \
355 util.h \
356 trace.h
357
358tube.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
367util.o: util.c \
368 config.h \
369 config_linux.h \
370 util.h \
371 rsync.h \
372 trace.h
373
374version.o: version.c \
375 config.h \
376 config_linux.h \
377 rsync.h
378
379whole.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 @@
1librsync is the next generation of librsync, and provides flexible
2checksum-based differencing. The main application at the moment in
3rproxy, but the library should eventually be generally useful.
4
5 http://linuxcare.com.au/rproxy/
6
7This library was previously known as libhsync up to version 0.9.0.
8
9To use anonymous CVS, see the file README.CVS in this directory.
10
11>> Requirements
12
13To 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
28RedHat 7.0 (Guiness) ships with a buggy version of GCC 2.96 that
29produces many warnings while compiling librsync. These are harmless
30-- the library seems to work anyhow. You can avoid the warnings by
31using the 'kgcc' version of the compiler:
32
33 $ export CC=kgcc
34 $ ./autogen.sh
35 $ make all check
36
37>> Library Versions
38
39librsync uses the GNU libtool library versioning system, so the
40filename does not correspond to the librsync release. To show the
41library release and version, use the librsyncinfo tool.
42
43>> Platforms
44
45librsync/rproxy is known to run on:
46
47GNU Linux Debian 2.2 x86
48
49SUNWspro: (use -v for more warnings)
50
51mips-sgi-irix6.5: works, but you must use GNU Make rather than the
52default SGI Make. I used gcc.
53
54>> API Documentation
55
56librsync contains markup for automatic API documentation generation
57using 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
3Andrew Tridgell and Paulus Mackerras started this whole mess. Luke
4Leighton was a tremendous help in sorting out the combined
5encoding/signature algorithm.
6
7Thanks to Linuxcare, Inc, <http://linuxcare.com/> for their support of
8this project.
9
10Neale Banks <neale@lowendale.com.au>: the first known user outside of
11OzLabs, and helped keep me honest.
12
13Paul `Rusty' Russell <rusty@linuxcare.com>
14Andrew Tridgell <tridge@samba.org>
15Paulus Mackerras <paulus@linuxcare.com>
16Peter Barker <pbarker@samba.org>
17Neale Banks <neale@lowendale.com.au>
18Luke Kenneth Casson Leighton <lkcl@samba.org>
19Tim Potter <tpot@linuxcare.com.au>
20Hugh Blemings <hugh@linuxcare.com.au>
21David 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 */
37size_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 */
71void
72rs_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 */
59int rs_inbuflen = 16000, rs_outbuflen = 16000;
60
61
62struct rs_filebuf {
63 FILE *f;
64 char *buf;
65 size_t buf_len;
66};
67
68
69
70rs_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
82void 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 */
96rs_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 */
148rs_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 */
193rs_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
23typedef struct rs_filebuf rs_filebuf_t;
24
25rs_filebuf_t *rs_filebuf_new(FILE *f, size_t buf_len);
26
27void rs_filebuf_free(rs_filebuf_t *fb);
28
29rs_result rs_infilebuf_fill(rs_job_t *, rs_buffers_t *buf, void *fb);
30
31rs_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. */
38int 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 */
44unsigned 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 */
78void 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
23rs_weak_sum_t rs_calc_weak_sum(void const *buf1, int len);
24
25void 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. */
34struct 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 */
48char 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 */
37enum 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
51typedef struct rs_op_kind_name {
52 char const *name;
53 enum rs_op_kind const kind;
54} rs_op_kind_name_t;
55
56char 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 */
86int rs_roll_paranoia = 0;
87
88
89static rs_result rs_delta_scan(rs_job_t *, rs_long_t avail_len, void *);
90
91static rs_result rs_delta_s_deferred_copy(rs_job_t *job);
92
93
94
95static 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 */
108static rs_result
109rs_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 */
159static rs_result
160rs_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
261static 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 */
281static 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 */
305static 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 */
328rs_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 */
60void
61rs_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. */
70void
71rs_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. */
101void
102rs_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. */
124void
125rs_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
29void rs_emit_delta_header(rs_job_t *);
30void rs_emit_literal_cmd(rs_job_t *, int len);
31void rs_emit_end_cmd(rs_job_t *);
32void 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 */
47FILE *
48rs_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
23FILE * 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
33void
34rs_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
56static const int rs_job_tag = 20010225;
57
58static rs_result rs_job_work(rs_job_t *job, rs_buffers_t *buffers);
59
60
61rs_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
79void rs_job_check(rs_job_t *job)
80{
81 assert(job->dogtag == rs_job_tag);
82}
83
84
85rs_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
95static 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
102static 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 */
134rs_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
158static rs_result
159rs_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 */
203const rs_stats_t *
204rs_job_statistics(rs_job_t *job)
205{
206 return &job->stats;
207}
208
209
210int
211rs_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 */
222rs_result
223rs_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
24struct 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
94rs_job_t * rs_job_new(const char *, rs_result (*statefn)(rs_job_t *));
95
96void rs_job_check(rs_job_t *job);
97const rs_stats_t *rs_job_statistics(rs_job_t *);
98
99int 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
42static 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 */
67static void
68rs_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. */
154static void
155copy64( /* @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
164static void
165copy4( /* @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 */
179static void
180rs_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
189static void
190rs_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
212void
213rs_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 */
233static void
234rs_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 */
264void
265rs_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
306void
307rs_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
318void
319rs_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. */
57static rs_result rs_sig_s_header(rs_job_t *);
58static rs_result rs_sig_s_generate(rs_job_t *);
59
60
61
62/**
63 * State of trying to send the signature header.
64 */
65static 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 */
83static rs_result
84rs_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 */
112static rs_result
113rs_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 */
144rs_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. */
47char 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 */
71rs_result
72rs_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 */
88rs_result
89rs_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
113rs_result
114rs_squirt_n4(rs_job_t *job, int val)
115{
116 return rs_squirt_netint(job, val, 4);
117}
118
119
120
121rs_result
122rs_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
146rs_result
147rs_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
159rs_result
160rs_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
171int 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
24rs_result rs_squirt_byte(rs_job_t *, unsigned char d);
25rs_result rs_squirt_netint(rs_job_t *, rs_long_t d, int len);
26rs_result rs_squirt_n4(rs_job_t *, int val);
27
28rs_result rs_suck_netint(rs_job_t *, rs_long_t *v, int len);
29rs_result rs_suck_byte(rs_job_t *, unsigned char *);
30rs_result rs_suck_n4(rs_job_t *, int *);
31
32int 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
48static rs_result rs_patch_s_cmdbyte(rs_job_t *);
49static rs_result rs_patch_s_params(rs_job_t *);
50static rs_result rs_patch_s_run(rs_job_t *);
51static rs_result rs_patch_s_literal(rs_job_t *);
52static rs_result rs_patch_s_copy(rs_job_t *);
53static 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 */
61static 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 */
89static 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 */
121static 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 */
148static 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
166static 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 */
204static 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 */
256static 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 */
306rs_job_t *
307rs_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
19const 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
4typedef 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
10extern const rs_prototab_ent_t rs_prototab[];
11
12enum {
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>
3extern "C" {
4#include "rsync.h"
5}
6#include <stdlib.h>
7
8#include <qfile.h>
9
10static const char *rdiffNewFile = "/tmp/rdiff/result";
11static size_t block_len = RS_DEFAULT_BLOCK_LEN;
12static size_t strong_len = RS_DEFAULT_STRONG_LEN;
13
14
15void 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
35void 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
70void 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
9class QRsync
10{
11public:
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
65static size_t block_len = RS_DEFAULT_BLOCK_LEN;
66static size_t strong_len = RS_DEFAULT_STRONG_LEN;
67
68static int show_stats = 0;
69
70static int bzip2_level = 0;
71static int gzip_level = 0;
72
73
74enum {
75 OPT_GZIP = 1069, OPT_BZIP2
76};
77
78extern int rs_roll_paranoia;
79
80const 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
98static 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
106static 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
115static 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
127static 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
150static 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
187static 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 */
234static 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
256static 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
296static 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
326static 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
345int 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
46static rs_result rs_loadsig_s_weak(rs_job_t *job);
47static 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 */
54static 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
89static 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
111static 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
127static 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
153static 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
174static 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 */
204rs_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
44extern char const rs_librsync_version[];
45extern 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
56typedef signed long long rs_long_t;
57#else
58typedef 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 */
69typedef 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 */
88typedef void rs_trace_fn_t(int level, char const *msg);
89
90void rs_trace_set_level(rs_loglevel level);
91
92/** Set trace callback. */
93void 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(). */
97void rs_trace_stderr(int level, char const *msg);
98
99/** Check whether the library was compiled with debugging trace
100 * suport. */
101int 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 */
110void 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 */
116size_t rs_unbase64(char *s);
117
118
119/**
120 * Encode a buffer as base64.
121 */
122void rs_base64(unsigned char const *buf, int n, char *out);
123
124
125/**
126 * \brief Return codes from nonblocking rsync operations.
127 */
128typedef 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 */
159char 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 */
168typedef 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 */
197typedef 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
206typedef unsigned int rs_weak_sum_t;
207typedef unsigned char rs_strong_sum_t[RS_MD4_LENGTH];
208
209void rs_mdfour(unsigned char *out, void const *in, size_t);
210void rs_mdfour_begin(/* @out@ */ rs_mdfour_t * md);
211void rs_mdfour_update(rs_mdfour_t * md, void const *,
212 size_t n);
213void rs_mdfour_result(rs_mdfour_t * md, unsigned char *out);
214
215char *rs_format_stats(rs_stats_t const *, char *, size_t);
216
217int rs_log_stats(rs_stats_t const *stats);
218
219
220typedef struct rs_signature rs_signature_t;
221
222void rs_free_sumset(rs_signature_t *);
223void 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 */
273struct 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 */
290typedef 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(). */
306typedef struct rs_job rs_job_t;
307
308/**
309 * Bitmask values that may be passed to the options parameter of
310 * rs_work().
311 */
312typedef enum rs_work_options {
313 RS_END = 0x01 /**< End of input file; please finish
314 * up. */
315} rs_work_options;
316
317
318rs_result rs_job_iter(rs_job_t *, rs_buffers_t *);
319
320typedef rs_result rs_driven_cb(rs_job_t *job, rs_buffers_t *buf,
321 void *opaque);
322
323rs_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
327rs_result rs_job_free(rs_job_t *);
328
329int rs_accum_value(rs_job_t *, char *sum, size_t sum_len);
330
331rs_job_t *rs_sig_begin(size_t new_block_len, size_t strong_sum_len);
332
333rs_job_t *rs_delta_begin(rs_signature_t *);
334
335rs_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 */
349typedef rs_result rs_copy_cb(void *opaque, off_t pos,
350 size_t *len, void **buf);
351
352
353
354rs_job_t *rs_patch_begin(rs_copy_cb *, void *copy_arg);
355
356
357rs_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 */
367extern 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 */
376void rs_mdfour_file(FILE *in_file, char *result);
377
378rs_result rs_sig_file(FILE *old_file, FILE *sig_file,
379 size_t block_len, size_t strong_len, rs_stats_t *);
380
381rs_result rs_loadsig_file(FILE *, rs_signature_t **, rs_stats_t *);
382
383rs_result rs_file_copy_cb(void *arg, off_t pos, size_t *len, void **buf);
384
385rs_result rs_delta_file(rs_signature_t *, FILE *new_file, FILE *delta_file, rs_stats_t *);
386
387rs_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 */
85void 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 */
136void 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 */
172rs_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 */
236rs_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 */
253rs_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 */
268size_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
60static int
61rs_compare_targets(rs_target_t const *t1, rs_target_t const *t2)
62{
63 return ((int) t1->t - (int) t2->t);
64}
65
66
67rs_result
68rs_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 */
116int
117rs_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
24int
25rs_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
99static void dopr (char *buffer, size_t maxlen, const char *format,
100 va_list args);
101static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
102 char *value, int flags, int min, int max);
103static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
104 long value, int base, int min, int max, int flags);
105static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
106 LDOUBLE fvalue, int min, int max, int flags);
107static 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
140static 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
393static 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
432static 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
522static LDOUBLE abs_val (LDOUBLE value)
523{
524 LDOUBLE result = value;
525
526 if (value < 0)
527 result = -value;
528
529 return result;
530}
531
532static 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
545static 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
557static 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
701static 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
45int
46rs_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 */
69char *
70rs_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
99static 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 */
112int 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 */
152void 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
30int rs_buffers_is_empty(rs_buffers_t *stream);
31int rs_buffers_copy(rs_buffers_t *stream, int len);
32
33int rs_tube_catchup(rs_job_t *);
34void rs_tube_write(rs_job_t *, void const *buf, size_t len);
35void rs_tube_copy(rs_job_t *, int len);
36int rs_tube_is_idle(rs_job_t const *);
37void rs_check_tube(rs_job_t *);
38
39void rs_buffers_check_exit(rs_buffers_t const *);
40
41void rs_scoop_advance(rs_job_t *, size_t len);
42rs_result rs_scoop_readahead(rs_job_t *, size_t len, void **ptr);
43rs_result rs_scoop_read(rs_job_t *, size_t len, void **ptr);
44rs_result rs_scoop_read_rest(rs_job_t *, size_t *len, void **ptr);
45size_t rs_scoop_total_avail(rs_job_t *job);
46void 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 */
39void
40rs_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 */
60void
61rs_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 */
35typedef struct rs_target {
36 unsigned short t;
37 int i;
38} rs_target_t;
39
40typedef 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 */
47struct 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 */
63struct 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
53rs_trace_fn_t *rs_trace_impl = rs_trace_stderr;
54
55int 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
63static 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 */
74static 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 */
91void
92rs_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 */
101void
102rs_trace_set_level(rs_loglevel level)
103{
104 rs_trace_level = level;
105}
106
107
108static void
109rs_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 */
139void
140rs_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. */
152void
153rs_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
163void
164rs_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. */
173void
174rs_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. */
186void
187rs_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. */
199void
200rs_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 */
215int
216rs_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
39void rs_fatal0(char const *s, ...);
40void rs_error0(char const *s, ...);
41void rs_trace0(char const *s, ...);
42
43void rs_log0_nofn(int level, char const *fmt, ...);
44
45#ifdef __GNUC__
46
47void 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
96void rs_log0(int level, char const *fn, char const *fmt, ...);
97
98
99enum {
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
116extern 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
74static 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 */
116static void
117rs_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 */
154static 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 */
184int 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. */
215int 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. */
235void 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 */
252void
253rs_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
39void
40rs_bzero(void *buf, size_t size)
41{
42 memset(buf, 0, size);
43}
44
45
46void *
47rs_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
60void *
61rs_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
25void * rs_alloc(size_t size, char const *name);
26void *rs_alloc_struct0(size_t size, char const *name);
27
28void 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. */
31char 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 */
65rs_result
66rs_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 */
103rs_result
104rs_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 */
126rs_result
127rs_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
143rs_result
144rs_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
164rs_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
24rs_result rs_whole_run(rs_job_t *job, FILE *in_file, FILE *out_file);