xdelta-1.2.1/000077500000000000000000000000001525650667300130135ustar00rootroot00000000000000xdelta-1.2.1/AUTHORS000077500000000000000000000002511525650667300140640ustar00rootroot00000000000000The author is Joshua MacDonald, . The Rsync algorithm, which inspired the core delta algorithm, is due to Andrew Tridgell and Paul Mackerras. xdelta-1.2.1/BUILDING.md000066400000000000000000000010541525650667300145320ustar00rootroot00000000000000# Building Xdelta 1.2.1 Xdelta 1.2.1 uses CMake and requires a C compiler, CMake 3.20 or later, pkg-config, GLib 2, and zlib. ``` The checked-in serialization sources are generated from `xd.ser` and `libedsio/edsio.ser`. Regenerate them after changing either schema or `libedsio/edsio.el`: ```sh ./generate-edsio.sh ``` Set `EMACS` to select a non-default Emacs executable.sh cmake -S . -B build -DCMAKE_BUILD_TYPE=Release cmake --build build --parallel cmake --install build ``` Autotools is not supported. CMake is the only supported build system. xdelta-1.2.1/CMakeLists.txt000066400000000000000000000052761525650667300155650ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.20) project(xdelta VERSION 1.2.1 LANGUAGES C) include(GNUInstallDirs) include(CTest) set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS ON) find_package(PkgConfig REQUIRED) pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0 gmodule-2.0) find_package(ZLIB REQUIRED) option(XD1_WERROR "Treat compiler warnings as errors" OFF) set(XD1_WERROR_FLAGS "") if(XD1_WERROR) if(MSVC) set(XD1_WERROR_FLAGS /WX) elseif(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") set(XD1_WERROR_FLAGS -Werror -Wall -Wextra -Wformat=2 -Wimplicit-fallthrough -Wmissing-prototypes -Wpointer-arith -Wpedantic -Wshadow -Wvla ) endif() endif() configure_file(cmake/config.h.in config.h) set(EDSIO_SOURCES libedsio/base64.c libedsio/default.c libedsio/edsio.c libedsio/edsio_edsio.c libedsio/fh.c libedsio/generic.c libedsio/library.c libedsio/maketime.c libedsio/md5c.c libedsio/partime.c libedsio/sha.c libedsio/simple.c ) add_library(edsio STATIC ${EDSIO_SOURCES}) target_compile_options(edsio PRIVATE ${XD1_WERROR_FLAGS}) target_include_directories(edsio PUBLIC $ $ $ ) target_link_libraries(edsio PUBLIC PkgConfig::GLIB) add_library(xdelta_lib xdelta.c xdapply.c xd_edsio.c) set_target_properties(xdelta_lib PROPERTIES OUTPUT_NAME xdelta) target_compile_options(xdelta_lib PRIVATE ${XD1_WERROR_FLAGS}) target_include_directories(xdelta_lib PUBLIC $ $ $ $ ) target_link_libraries(xdelta_lib PUBLIC edsio) add_executable(xdelta xdmain.c getopt.c getopt1.c) target_compile_options(xdelta PRIVATE ${XD1_WERROR_FLAGS}) target_link_libraries(xdelta PRIVATE xdelta_lib ZLIB::ZLIB) if(BUILD_TESTING) add_test( NAME compatibility-1.1.4 COMMAND ${CMAKE_COMMAND} -DXDELTA=$ -DFIXTURE_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test/compat/1.1.4 -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/compatibility-1.1.4.out -P ${CMAKE_CURRENT_SOURCE_DIR}/test/compat/verify.cmake ) endif() install(TARGETS xdelta xdelta_lib edsio RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) install(FILES xdelta.h xd_edsio.h libedsio/edsio.h libedsio/edsio_edsio.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/xdelta ) xdelta-1.2.1/COPYING000077500000000000000000000430761525650667300140630ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. xdelta-1.2.1/HISTORICAL.md000066400000000000000000000010341525650667300147740ustar00rootroot00000000000000# Historical source provenance The actively maintained Xdelta 1.2.x tree in this directory was reconstructed from the historical `xdelta-1.1.4.tar.gz` source distribution. The pristine restoration is recorded in Git commit `803cbd3`; the current files have since been modernized and are not a pristine copy of that release. The archive's SHA-256 digest is: ```text 345503b60432812840991ea1d79cb10db5f34bfaba9499bd0e7d5c57ac5d5c6d ``` The restored source serves as the provenance and compatibility baseline for the modern 1.2.x release. xdelta-1.2.1/NEWS000077500000000000000000000224741525650667300135260ustar00rootroot00000000000000XDelta NEWS -- history of user-visible changes. -*- Text -*- Please file bug reports at https://github.com/jmacd/xdelta/issues. See the file `README' for a description of how to report bugs. ** Changes in version 1.2.1 * Add x86 and x86-64 Windows release packages with bundled runtime dependencies. * Install the static libraries and public headers, and document static and shared library builds for CMake consumers. * Exercise source-copy offsets beyond 2 GiB in the regression suite. ** Changes in version 1.2.0 * Add a CMake build for current C toolchains, GLib 2, and zlib. * Replace GLib 1-only memory-chunk and queue compatibility code with supported GLib 2 APIs. * Remove the obsolete Autotools build system. * Store the read handle as a void pointer, since it holds either a FILE* or a gzFile. The mismatch was a warning under older compilers but is an error under GCC 14 and later. * Verify backward compatibility by applying a checked-in patch produced by the authentic Xdelta 1.1.4 release. * Modernize legacy declarations, GLib calls, and generated serialization code, and enforce warning-free builds with GCC and Clang. * Make the EDSIO serializer generator reproducible with current Emacs and remove its deprecated Emacs Lisp dependencies. ** Changes since version 1.1.3 * Add an implementation of xdp_generator_free() for users of the libxdelta API. Previously there were no such users of the 1.x API, but Elliot Lee has written a program for providing delta operations on RPM files. * The man page now documents return values. ** Changes since version 1.1.2 * Correct error message format for the case when gzread fails trying to automatically decompress a corrupted GZIP file. The situation itself--corrupt GZIP files--should be dealt with the -p (--pristine) option, which disables GZIP file recognition. Reported by Ben Escoto. * Apply a patch from Klaus Dittrich for building on HPUX with the native compiler. There is now a script called "contrib/build_hpux". ** Changes since version 1.1.1 * This code release is a distant fork of the 2.0 release. It will hopefully be replaced. * When 'patch' supplies its default TO file name recorded in the delta, it still generates a unique file name to avoid overwriting an existing copy. Use the 'xdelta info' command to see what file names are contained in the delta. * The code for writing patches to stdout was broken in the case where gzip compression is used. Writing patches to stdout has therefore been disabled. The problem is a limitation in the gzdopen/gzwrite functions provided by zlib--you cannot determine how many bytes have been written to the file descriptor without dup-ing the FD beforehand and then lseek-ing afterwards, which does not work correctly if the output file is not seekable. * By default, Xdelta uses a hard-coded 16 byte block size. If you're working with large files, try #undef XDELTA_HARDCODE_SIZE in xdelta.h then use -s BLOCKSIZE (--blocksize=BLOCKSIZE), which should be a power of 2. * New test program in the 'test' subdirectory, which runs comparisons against "diff --rcs -a" and also verifies the "xdelta patch" command. * Incorporate DJGPP patches from Richard Dawe . You can find his versions directly at: ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2apps/xdlt112b.zip ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2apps/xdlt112s.zip * Updated xdelta(1) man page. * Updated autoconf (2.50), automake (1.4-p4), libtool (1.4) scripts, which includes updated config.guess and config.sub scripts. * Correct some backward compatibility issues: strcmp() was not being tested == 0 for formats older than 1.0.4. * Update GLIB version requirement, now 1.2.8. * We really need support for 64bit file sizes... perhaps the next version? ** Changes since version 1.1.0 * No one was were able to build the 1.1.0 release because it depended on a version of glib which will not be distributed for some time. This version backs out those dependencies and now requires glib-1.2.1. ** Changes since version 1.0.6 * The 64M limit on file sizes has been lifted. File lengths are now limited by the size of a 32-bit integer. * The internal data structures were changed and some of the experimental bits of the interface have been moved out of libxdelta, resulting in a simpler interface. Old patch files are still supported. ** Changes since version 1.0.5 * There are 8 bytes of space in the patch format's header that are reserved for future use. They are not currently used, but were also not being initialized, making it possible for two deltas produced in the same manner to differ. This was exposed by comparing deltas produced between the same files on Windows and Linux. With this patch, the results should be identical. ** Changes since version 1.0.4 * The code now compiles natively under Windows. I used MS VC++ 5.0. It depends on glib and zlib, but I don't feel like documenting the build process yet. I have had some trouble with the zlib DLLs and had to build my own, so you can't build it yourself yet. There is a pre-built version at ftp://ftp.xcf.berkeley.edu/pub/xdelta/xdelta-1.0.5.win32.zip * Many changes required to keep Xdelta working with PRCS 2. Mostly this involved keeping up to date with some code that is shared between the two. All the shared code is now in the "libedsio" subdirectory, which stands for "Error Delivery and Serialized IO". ** Changes since version 1.0.3 * Slight change in file format to improve detection of and error messages regarding corrupt deltas (specifically, those left behing when an xdelta process is killed while computing a delta). This means 1.0.0-1.0.3 will not read these new deltas, they will report a bad magic number. * Improve several error messages related to corrupt deltas. ** Changes since version 1.0.2 * Fix a few bugs, especially one related to the implementation of -m, and a couple more which were shaken out by testing on a pair of emacs releases (~55M each). These changes only affect the xdelta application, the library is unchanged. * Add a new command `xdelta info' that lists information about a delta, for example: $ xdelta info some.patch xdelta: version 1.0.3 found patch version 1.0 in some.patch xdelta: patch contents are compressed xdelta: patch from: from xdelta: patch from length: 53309440 xdelta: patch from md5: c0ddcb6904d40da7cf1eae5e6bdbbc01 xdelta: patch to: to xdelta: patch to length: 55377920 xdelta: patch to md5: 00b3dd4d1a9b450bc5b8991b183013fb xdelta: patch insert length: 2436426 xdelta: patch inst count: 253649 ** Changes since version 1.0.1 * Fix minor typos, and build improvements. There is now a gtk-style 'xdelta-config' program and autoconf macro to locate the library. ** Changes since version 1.0.0 * Fix incorrect usage report in --help output for the patch command. * Abort when directories are specified, there is no recursive mode. * Now requires glib-1.1.5. * The new ``pristine'' option (-p, --pristine) disables automatic uncompression of compressed input data, and is for use when data integrity is being externally verified. This enables a tool written by Manish Singh (yosh@gimp.org) to compute deltas between the Debian dpkg utility's .deb format. * A draft paper describing its algorithms, rational, advanced features, and future work is now available at ftp://ftp.xcf.berkeley.edu/pub/xdelta/xdelta.ps. ** Changes since version 0.24 * This version is a complete rewrite, and removes some of the features available in version 0. Featuring: - A completely new and much improved library interface. This code is a complete rewrite. - An optimized implementation of the XDelta algorithm. - A drastic memory reduction. - The library stream-processes files where possible and uses a page- based interface when seeking is required (allowing the application to run in bounded memory on large files). - There is now a little documentation. A man page and the beginnings of texinfo documentation. - Includes several advanced features used by PRCS version 2, see the documentation for more information. - Includes a minimal implementation of the Rsync algorithm, also used by PRCS version 2. - Uses an abstract file handle interface, the library has very few system dependencies. This allows the library client to compute MD5 checksums in a single-pass as XDelta reads files, use pre- computed checksums, or disable checksum verification entirely. - Compression and file-unarchival have been removed from the library, these features are orthogonal. At the application level: - GDBM archive experiment has been removed. This functionality is implemented directly in PRCS version 2 using the present library interface. - Base 64 encoding support has been removed for technical reasons. - Can no longer accept patches from stdin, due to the same technical reasons (the patch instruction index is stored at the end of the file, requiring seeking). - Automatic detection and un-archival of RPM and dpkg file formats has been removed. Automatic uncompression of gzipped files is still supported. - The GIMP plugin is no longer supported. xdelta-1.2.1/README000077500000000000000000000176271525650667300137130ustar00rootroot00000000000000# Xdelta 1.2.1 -- A binary delta generator Xdelta is an application program designed to compute changes between files. These changes (deltas) are similar to the output of the "diff" program in that they may be used to store and transmit only the changes between files. However, unlike diff, the output of Xdelta is not expressed in a human-readable format--Xdelta can also also apply these deltas to a copy of the original file. Xdelta uses a fast, linear algorithm and performs well on both binary and text files. ## Build and install Xdelta 1.2.1 is built with CMake. You need a C compiler, CMake 3.20 or newer, pkg-config, GLib 2 development files, and zlib development files. On macOS with Homebrew these are `brew install cmake pkg-config glib`; zlib comes with the system. On Debian or Ubuntu they are `apt install build-essential cmake pkg-config libglib2.0-dev zlib1g-dev`. Run all three commands, in order, from this `xdelta1` directory. The first configures the build, the second compiles it, and the third installs it; the later steps fail if an earlier one was skipped. ```sh cmake -S . -B build -DCMAKE_BUILD_TYPE=Release cmake --build build --parallel cmake --install build ``` The executable is `build/xdelta`, and you can run it from there without installing at all. The final step installs system-wide and may need `sudo`. To install into your home directory instead, pass a prefix: ```sh cmake --install build --prefix "$HOME/.local" ``` That puts the program at `$HOME/.local/bin/xdelta`, which must be on your `PATH` to run it by name. If configuring fails, CMake reports the missing dependency; install it and re-run the three commands. If a build directory is left in a bad state, delete it with `rm -rf build` and start again. For example, create and apply a delta: ```sh build/xdelta delta original-file updated-file change.xdelta build/xdelta patch change.xdelta original-file reconstructed-file ``` The historical 1.1.4 release was restored as the baseline for this modernized 1.2.1 release. See `HISTORICAL.md` for its provenance and `BUILDING.md` for the concise build reference. Xdelta was designed and implemented by Joshua MacDonald. The delta algorithm is based on the Rsync algorithm, though implementation and interface considerations leave the two programs quite distinct. The Rsync algorithm is due to Andrew Tridgell and Paul Mackerras. Xdelta is released under the GNU Library Public License (GPL), see the file COPYING for details. Comments about Xdelta can be addressed to the following addresses: https://github.com/jmacd/xdelta/issues The man page describes how to use Xdelta in more detail: NAME xdelta - Invoke Xdelta SYNOPSIS xdelta subcommand [ option... ] [ operand... ] DESCRIPTION Xdelta provides the ability to generate deltas between a pair of files and later apply those deltas. It operates similar to the diff and patch commands, but works on binary files and does not produce a human readable output. Xdelta has three subcommands, delta, patch, and info. Delta accepts two file versions and produces a delta, while patch accepts the original file version and delta and produces the second version. The info command prints useful information about a delta. Each subcommand will be detailed seperately. Gzip processing Attempting to compute a delta between compressed input files usually results in poor compression. This is because small differences between the original contents causes changes in the compression of whole blocks of data. To simplify things, Xdelta implements a special case for gzip(1) compressed files. If any version input to the delta command is recognized as having gzip compression, it will be automatically decompressed into a temporary location prior to comparison. This temporary location is either the value of the TMPDIR environment variable, if set, otherwise "/tmp". The Xdelta patch header contains a flag indicating that the reconstructed version should be recompressed after applying the patch. In general, this allows Xdelta to operate transparently on gzip compressed inputs. There is one potential problem when automatically processing gzip compressed files, which is that the recompressed content does not always match byte-for-byte with the original compressed content. The uncompressed content still matches, but if there is an external integrity check such as cryptographic signature verification, it may fail. To prevent this from happening, the --pristine option disables automatic gzip processing. MD5 integrity check By default, Xdelta always verifies the MD5 checksum of the files it reconstructs. This prevents you from supplying an incorrect input during patch, which would result in corrupt output. Because of this feature, you can feel confident that patch has produced valid results. The --noverify option disables MD5 verification, but this is only recommended for performance testing. Compressed patch format Xdelta uses a fairly simple encoding for its delta, then applies zlib compression to the result. You should not have to post-compress an Xdelta delta. Delta The delta subcommand has the following synopsis: xdelta delta [ option... ] fromfile tofile patchout Computes a delta from fromfile to tofile and writes it to patchout Patch The patch subcommand has the following synopsis: xdelta patch [ option... ] patchin [ fromfile [ tofile ]] Applies patchin to fromfile and produces a reconstructed version of tofile. If fromfile was omitted, Xdelta attempts to use the original fromfile name, which is stored in the delta. The from file must be identical to the one used to create the delta. If its length or MD5 checksum differs, patch will abort with an error message. If tofile was omitted, Xdelta attempts to use the original tofile name, which is also stored in the delta. If the original tofile name already exists, a unique filename extension will be added to avoid destroying any existing data. Info The info subcommand has the following synopsis: xdelta info patchinfo Prints information about patchinfo and the version it reconstructs, including file names, lengths, and MD5 checksums. Options -0..9 Set the zlib compression level. Zero indicates no compression. Nine indicates maximum compression. -h, --help Print a short help message and exit. -q, --quiet Quiet. Surpresses several warning messages. -v, --version Print the Xdelta version number and exit. -V, --verbose Verbose. Prints a bit of extra information. -n, --noverify No verify. Turns off MD5 checksum verification of the input and output files. -m=SIZE, --maxmem=SIZE Set an upper bound on the size of an in-memory page cache. For example, --maxmem=32M will use a 32 megabyte page cache. -s=BLOCK_SIZE Set the block size, unless it was hard coded (20% speed improvement). Should be a power of 2. -p, --pristine Disable the automatic decompression of gzipped inputs, to prevent unexpected differences in the re-compressed content. # Historical Xdelta 1.1.4 source release This directory preserves the historical Xdelta 1.1.4 source distribution. It was restored from `xdelta-1.1.4.tar.gz`. The archive's SHA-256 digest is: ```text 345503b60432812840991ea1d79cb10db5f34bfaba9499bd0e7d5c57ac5d5c6d ``` This tree is retained as the baseline for the modern 1.2.x release. xdelta-1.2.1/cmake/000077500000000000000000000000001525650667300140735ustar00rootroot00000000000000xdelta-1.2.1/cmake/config.h.in000066400000000000000000000001421525650667300161130ustar00rootroot00000000000000#cmakedefine HAVE_GETTIMEOFDAY 1 #cmakedefine HAVE_SYS_TIME_H 1 #cmakedefine TIME_WITH_SYS_TIME 1 xdelta-1.2.1/djgpp/000077500000000000000000000000001525650667300141175ustar00rootroot00000000000000xdelta-1.2.1/djgpp/announce.djg000077500000000000000000000036141525650667300164220ustar00rootroot00000000000000Hello. I'm please to announce the release of the DJGPP port of XDelta 1.1.2. This release contains mainly minor bugfixes over the previous version (1.1.1). Please see the file 'contrib/xdlt112/news' for a complete list of changes. Here is a description of XDelta, from its 'readme' file: "XDelta is a library interface and application program designed to compute changes between files. These changes (deltas) are similar to the output of the "diff" program in that they may be used to store and transmit only the changes between files. However, unlike diff, the output of XDelta is not expressed in a human-readable format--XDelta can also also apply these deltas to a copy of the original file(s). XDelta uses a fast, linear algorithm and performs well on both binary and text files. XDelta typically outperforms GNU diff in both time and generated-delta-size, even for plain text files. XDelta also includes a simple implementation of the Rsync algorithm and several advanced features for implementing RCS-like file-archival with." XDelta is distributed under the GNU General Public License. The port is available from the DJGPP archive on SimTel.NET: http://www.simtel.net/gnudlpage.php?product=/gnu/djgpp/v2apps/xdlt112b.zip&name=xdlt112b.zip http://www.simtel.net/gnudlpage.php?product=/gnu/djgpp/v2apps/xdlt112s.zip&name=xdlt112s.zip These are binary and source distributions respectively. If you only want to use XDelta, please download the binary distribution. If you would like to rebuild XDelta, please download the source distribution. No changes were required to port XDelta to DJGPP. Thanks to Joshua MacDonald for incorporating the DJGPP patches into XDelta. Thanks to Eli Zaretskii for his detailed bug reports, suggestions and testing of XDelta in the past. If you have any problems, suggestions, etc. about the port, please mail me. Bye, -- Richard Dawe http://www.phekda.freeserve.co.uk/richdawe/ xdelta-1.2.1/djgpp/readme.djg000077500000000000000000000105511525650667300160470ustar00rootroot00000000000000DJGPP Port of XDelta 1.1.2 ~~~~~~~~~~~~~~~~~~~~~~~~~~ Installing the Binary Package ----------------------------- Unzip the distribution preserving the directory structure - use PKUNZIP's -d option; use an equivalent option with other unzippers. Unzip into the top DJGPP installation directory, e.g. c:\djgpp. XDelta should now be ready for use. A man page for XDelta is provided - use: man xdelta to view it. You will need to have installed the man program from the v2apps/ directory of the DJGPP archive for this to work. Installing the Source Package ----------------------------- You should only install the source package if you want to rebuild XDelta from the sources. To build the port, I used the following packages: . DJGPP 2.03 . GNU bash 2.04 . GNU gcc 2.95.3 . GNU binutils 2.11.2 . GNU sed 3.02 . GNU awk 3.0.3 . GNU fileutils 4.0 . GNU shellutils 1.12 . GNU textutils 2.0 . glib 1.2.10 . zlib 1.1.3 It may be possible to build XDelta with other versions of each package, but this has not been tested. Unzip the distribution preserving the directory structure - use PKUNZIP's -d option; use an equivalent option with other unzippers. Unzip into the top DJGPP installation directory, e.g. c:\djgpp. No changes were needed to XDelta to make it work with DJGPP. Before building XDelta, it must be configured. This is done from bash in the source directory using: ./configure --disable-shared The parameter '--disable-shared' is needed to get round a bug in libtool 1.4. libtool tries to use gcc's '-fPIC' option, which produces code that binutils does not understand (for DJGPP). '-fPIC' is used for generating relocatable code for dynamic linking. Since DJGPP does not support dynamic linking, we can use '--disable-shared' to stop '-fPIC' from being used. For more information on the libtool problem, please see the following post on djgpp-workers: http://www.delorie.com/djgpp/mail-archives/browse.cgi?p=djgpp-workers/2001/06/18/16:32:47 You may wish to install XDelta somewhere else. In that case, use the '--prefix' option, e.g. ./configure --disable-shared --prefix=/where/i/want/xdelta Once this has compelted, build using: make If these compelte successfully, XDelta and its libraries can be installed using: make install Some notes on using XDelta -------------------------- * XDelta is fairly simple - to see what options are available, use: xdelta --help * The '-p' or '--pristine' option prevents XDelta from using gzip compression, this avoids creating temporary files. This option is presented because gzip does not support exact re-compression, since there is no way to save the configuration used to produce a particular gzip file. * XDelta's buffers are sized (by default) according to the amount of free physical memory. It defaults to using 87.5% (7/8) of the available memory. Under Windows this sometimes does not detect the amount of free memory correctly (well, on this author's machine at least). Sometimes it was necessary to tell xdelta what amount of memory to use: xdelta patch --maxmem=32M ... NB: More memory means faster patching, with large patches & files. It is recommend you run XDelta in verbose mode, to see how much memory it is using: xdelta patch -V ... libxdelta and libedsio ---------------------- XDelta is actually just a front-end for two libraries - libxdelta and libedsio. libxdelta is a library for handling XDelta-format deltas. libedsio is a library for handling serialised I/O. Both these libraries are included in the port and can be used in your own programs. Unfortunately, there is no documentation for these libraries - the only reference is the source code. If you are interested in libxdelta and libedsio, please download the source distribution. Please note that I am not familiar with these libraries and I will not be able to answer any queries on them. libxdelta and libedsio come with *-config files, which return compilation and linking parameters. They are similar to glib-config. Example: bash-2.04$ xdelta-config --cflags -I/dev/env/DJDIR/lib/glib/include -I/dev/env/DJDIR/include bash-2.04$ $DJDIR/bin/xdelta-config --libs -L/dev/env/DJDIR/lib -lxdelta -ledsio -lglib Finally ------- If you have any comments or problems with this port, please feel free to e-mail me. I hope this port is useful. Thanks, bye, Richard Dawe 2001-10-05 xdelta-1.2.1/doc/000077500000000000000000000000001525650667300135605ustar00rootroot00000000000000xdelta-1.2.1/doc/xdelta.1000077500000000000000000000124461525650667300151350ustar00rootroot00000000000000.ds p \&\s-1Xdelta\s0 .if n .ds - \%-- .if t .ds - \(em .if !\n(.g \{\ . if !\w|\*(lq| \{\ . ds lq `` . if \w'\(lq' .ds lq "\(lq . \} . if !\w|\*(rq| \{\ . ds rq '' . if \w'\(rq' .ds rq "\(rq . \} .\} .de PE .sp \\n()Pu .ne 2 .nf .IP .. .de EP .fi .PP .sp \\n()Pu .. .TH Xdelta 1 .SH NAME xdelta \- Invoke Xdelta .SH SYNOPSIS .B xdelta .I subcommand [ .IR option ".\|.\|. ] [ .IR operand .\|.\|. ] .SH DESCRIPTION Xdelta provides the ability to generate deltas between a pair of files and later apply those deltas. It operates similar to the .B diff and .B patch commands, but works on binary files and does not produce a human readable output. .PP Xdelta has three subcommands, delta, patch, and info. Delta accepts two file versions and produces a delta, while patch accepts the original file version and delta and produces the second version. The info command prints useful information about a delta. Each subcommand will be detailed seperately. .SS Gzip processing Attempting to compute a delta between compressed input files usually results in poor compression. This is because small differences between the original contents causes changes in the compression of whole blocks of data. To simplify things, Xdelta implements a special case for .IR gzip (1) compressed files. If any version input to the delta command is recognized as having gzip compression, it will be automatically decompressed into a temporary location prior to comparison. This temporary location is either the value of the .IR TMPDIR environment variable, if set, otherwise "/tmp". The Xdelta patch header contains a flag indicating that the reconstructed version should be recompressed after applying the patch. In general, this allows Xdelta to operate transparently on gzip compressed inputs. There is one potential problem when automatically processing gzip compressed files, which is that the recompressed content does not always match byte-for-byte with the original compressed content. The uncompressed content still matches, but if there is an external integrity check such as cryptographic signature verification, it may fail. To prevent this from happening, the --pristine option disables automatic gzip processing. .SS MD5 integrity check By default, Xdelta always verifies the MD5 checksum of the files it reconstructs. This prevents you from supplying an incorrect input during patch, which would result in corrupt output. Because of this feature, you can feel confident that patch has produced valid results. The --noverify option disables MD5 verification, but this is only recommended for performance testing. .SS Compressed patch format Xdelta uses a fairly simple encoding for its delta, then applies zlib compression to the result. You should not have to post-compress an Xdelta delta. .SS Delta The delta subcommand has the following synopsis: .B xdelta .I delta [ .IR option ".\|.\|. ] .IR fromfile .IR tofile .IR patchout Computes a delta from .IR fromfile to .IR tofile and writes it to .IR patchout .SS Patch The patch subcommand has the following synopsis: .B xdelta .I patch [ .IR option ".\|.\|. ] .IR patchin [ .IR fromfile [ .IR tofile ]] Applies .IR patchin to .IR fromfile and produces a reconstructed version of .IR tofile. If fromfile was omitted, Xdelta attempts to use the original fromfile name, which is stored in the delta. The from file must be identical to the one used to create the delta. If its length or MD5 checksum differs, patch will abort with an error message. If tofile was omitted, Xdelta attempts to use the original tofile name, which is also stored in the delta. If the original tofile name already exists, a unique filename extension will be added to avoid destroying any existing data. .SS Info The info subcommand has the following synopsis: .B xdelta .I info .IR patchinfo Prints information about .IR patchinfo and the version it reconstructs, including file names, lengths, and MD5 checksums. .SS Options .IP -0..9 Set the zlib compression level. Zero indicates no compression. Nine indicates maximum compression. .IP "-h, --help" Print a short help message and exit. .IP "-q, --quiet" Quiet. Surpresses several warning messages. .IP "-v, --version" Print the Xdelta version number and exit. .IP "-V, --verbose" Verbose. Prints a bit of extra information. .IP "-n, --noverify" No verify. Turns off MD5 checksum verification of the input and output files. .IP "-m=SIZE, --maxmem=SIZE" Set an upper bound on the size of an in-memory page cache. For example, --maxmem=32M will use a 32 megabyte page cache. .IP "-s=BLOCK_SIZE" Set the block size, unless it was hard coded (20% speed improvement). Should be a power of 2. .IP "-p, --pristine" Disable the automatic decompression of gzipped inputs, to prevent unexpected differences in the re-compressed content. .SH RETURN VALUES The delta command exits with status 0 to indicate that no differences were found, with status 1 to indicate that some differences were found, and with status 2 to indicate an error of some kind. The patch and info commands exit with status 0 on success and 2 on failure. .SH IDENTIFICATION Author: Joshua P. MacDonald, jmacd@cs.berkeley.edu .br .\" $Format: "Manual Page Revision: $Revision$; Release Date: $ProjectDate$."$ Manual Page Revision: 1.6; Release Date: Sun, 28 Jan 2007 12:21:11 -0800. .br Copyright \(co 1997, 1998, 1999, 2000, 2001 xdelta-1.2.1/doc/xdelta.cat000077500000000000000000000123441525650667300155410ustar00rootroot00000000000000Xdelta(1) Xdelta(1) NAME xdelta - Invoke Xdelta SYNOPSIS xdelta subcommand [ option... ] [ operand... ] DESCRIPTION Xdelta provides the ability to generate deltas between a pair of files and later apply those deltas. It operates similar to the diff and patch commands, but works on binary files and does not produce a human readable output. Xdelta has three subcommands, delta, patch, and info. Delta accepts two file versions and produces a delta, while patch accepts the original file version and delta and produces the second version. The info command prints useful information about a delta. Each subcommand will be detailed seperately. Gzip processing Attempting to compute a delta between compressed input files usually results in poor compression. This is because small differences between the original contents causes changes in the compression of whole blocks of data. To simplify things, Xdelta implements a special case for gzip(1) compressed files. If any version input to the delta command is recognized as having gzip compression, it will be automatically decompressed into a temporary location prior to comparison. This temporary location is either the value of the TMPDIR environment variable, if set, otherwise "/tmp". The Xdelta patch header contains a flag indicating that the reconstructed version should be recompressed after applying the patch. In general, this allows Xdelta to operate transparently on gzip compressed inputs. There is one potential problem when automatically processing gzip compressed files, which is that the recompressed content does not always match byte-for-byte with the original compressed content. The uncompressed content still matches, but if there is an external integrity check such as cryptographic signature verification, it may fail. To prevent this from happening, the --pristine option disables automatic gzip processing. MD5 integrity check By default, Xdelta always verifies the MD5 checksum of the files it reconstructs. This prevents you from supplying an incorrect input during patch, which would result in corrupt output. Because of this feature, you can feel confident that patch has produced valid results. The --noverify option disables MD5 verification, but this is only recommended for performance testing. Compressed patch format Xdelta uses a fairly simple encoding for its delta, then applies zlib compression to the result. You should not have to post-compress an Xdelta delta. Delta The delta subcommand has the following synopsis: xdelta delta [ option... ] fromfile tofile patchout Computes a delta from fromfile to tofile and writes it to patchout Patch The patch subcommand has the following synopsis: xdelta patch [ option... ] patchin [ fromfile [ tofile ]] Applies patchin to fromfile and produces a reconstructed version of tofile. If fromfile was omitted, Xdelta attempts to use the original fromfile name, which is stored in the delta. The from file must be identical to the one used to create the delta. If its length or MD5 checksum differs, patch will abort with an error message. If tofile was omitted, Xdelta attempts to use the original tofile name, which is also stored in the delta. If the original tofile name already exists, a unique filename extension will be added to avoid destroying any existing data. Info The info subcommand has the following synopsis: xdelta info patchinfo Prints information about patchinfo and the version it reconstructs, including file names, lengths, and MD5 checksums. Options -0..9 Set the zlib compression level. Zero indicates no compression. Nine indicates maximum compression. -h, --help Print a short help message and exit. -q, --quiet Quiet. Surpresses several warning messages. -v, --version Print the Xdelta version number and exit. -V, --verbose Verbose. Prints a bit of extra information. -n, --noverify No verify. Turns off MD5 checksum verification of the input and output files. -m=SIZE, --maxmem=SIZE Set an upper bound on the size of an in-memory page cache. For example, --maxmem=32M will use a 32 megabyte page cache. -s=BLOCK_SIZE Set the block size, unless it was hard coded (20% speed improvement). Should be a power of 2. -p, --pristine Disable the automatic decompression of gzipped inputs, to prevent unexpected differences in the re-compressed content. IDENTIFICATION Author: Joshua P. MacDonald, jmacd@cs.berkeley.edu Manual Page Revision: 1.2; Release Date: Mon, 11 Jun 2001 03:39:53 -0700. Copyright © 1997, 1998, 1999, 2000, 2001 xdelta-1.2.1/generate-edsio.sh000077500000000000000000000007011525650667300162430ustar00rootroot00000000000000#!/bin/sh set -eu emacs_bin=${EMACS:-emacs} srcdir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) if ! command -v "$emacs_bin" >/dev/null 2>&1; then echo "error: Emacs executable not found: $emacs_bin" >&2 exit 1 fi ( cd "$srcdir/libedsio" "$emacs_bin" --batch -Q -l edsio.el \ --eval '(generate-ser "edsio.ser" "edsio")' ) ( cd "$srcdir" "$emacs_bin" --batch -Q -l libedsio/edsio.el \ --eval '(generate-ser "xd.ser" "xd")' ) xdelta-1.2.1/getopt.c000077500000000000000000000521301525650667300144650ustar00rootroot00000000000000/* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu before changing it! Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO #define _NO_PROTO #endif #ifndef __STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #ifdef HAVE_CONFIG_H #include #endif #include #include #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #if defined (_LIBC) || !defined (__GNU_LIBRARY__) /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ #include #endif /* GNU C library. */ /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg = NULL; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns EOF, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* XXX 1003.2 says this must be 1 before any call. */ int optind = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return EOF with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ #include #define my_index strchr #else /* Avoid depending on library functions or files whose names are inconsistent. */ static char * my_index (const char *str, int chr) { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } /* If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ #ifndef __STDC__ /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen (const char *); #endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ static void exchange (char **argv) { int bottom = first_nonopt; int middle = last_nonopt; int top = optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ static const char * _getopt_initialize (const char *optstring) { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = optind = 1; nextchar = NULL; posixly_correct = getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns `EOF'. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal (int argc, char *const *argv, const char *optstring, const struct option *longopts, int *longind, int long_only) { optarg = NULL; if (optind == 0) optstring = _getopt_initialize (optstring); if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && (argv[optind][0] != '-' || argv[optind][1] == '\0')) optind++; last_nonopt = optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp (argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return EOF; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if ((argv[optind][0] != '-' || argv[optind][1] == '\0')) { if (ordering == REQUIRE_ORDER) return EOF; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((size_t) (nameend - nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, "%s: option `%s' is ambiguous\n", argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) { if (argv[optind - 1][1] == '-') /* --option */ fprintf (stderr, "%s: option `--%s' doesn't allow an argument\n", argv[0], pfound->name); else /* +option or -option */ fprintf (stderr, "%s: option `%c%s' doesn't allow an argument\n", argv[0], argv[optind - 1][0], pfound->name); } nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, "%s: option `%s' requires an argument\n", argv[0], argv[optind - 1]); nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' || my_index (optstring, *nextchar) == NULL) { if (opterr) { if (argv[optind][1] == '-') /* --option */ fprintf (stderr, "%s: unrecognized option `--%s'\n", argv[0], nextchar); else /* +option or -option */ fprintf (stderr, "%s: unrecognized option `%c%s'\n", argv[0], argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (opterr) { if (posixly_correct) /* 1003.2 specifies the format of this message. */ fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); else fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c); } optopt = c; return '?'; } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, "%s: option requires an argument -- %c\n", argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int getopt (int argc, char *const *argv, const char *optstring) { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* _LIBC or not __GNU_LIBRARY__. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); if (c == EOF) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ xdelta-1.2.1/getopt.h000077500000000000000000000100061525650667300144660ustar00rootroot00000000000000/* Declarations for getopt. Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _GETOPT_H #define _GETOPT_H 1 #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns EOF, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { #if __STDC__ const char *name; #else char *name; #endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 #if __STDC__ extern int getopt (int argc, char *const *argv, const char *shortopts); extern int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); extern int getopt_long_only (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind, int long_only); #else /* not __STDC__ */ extern int getopt (); extern int getopt_long (); extern int getopt_long_only (); extern int _getopt_internal (); #endif /* not __STDC__ */ #ifdef __cplusplus } #endif #endif /* _GETOPT_H */ xdelta-1.2.1/getopt1.c000077500000000000000000000077131525650667300145550ustar00rootroot00000000000000/* getopt_long and getopt_long_only entry points for GNU getopt. Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include "getopt.h" #ifndef __STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #if defined (_LIBC) || !defined (__GNU_LIBRARY__) /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #include #ifndef NULL #define NULL 0 #endif int getopt_long (int argc, char *const *argv, const char *options, const struct option *long_options, int *opt_index) { return _getopt_internal (argc, argv, options, long_options, opt_index, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option instead. */ int getopt_long_only (int argc, char *const *argv, const char *options, const struct option *long_options, int *opt_index) { return _getopt_internal (argc, argv, options, long_options, opt_index, 1); } #endif /* _LIBC or not __GNU_LIBRARY__. */ #ifdef TEST #include int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"add", 1, 0, 0}, {"append", 0, 0, 0}, {"delete", 1, 0, 0}, {"verbose", 0, 0, 0}, {"create", 0, 0, 0}, {"file", 1, 0, 0}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "abc:d:0123456789", long_options, &option_index); if (c == EOF) break; switch (c) { case 0: printf ("option %s", long_options[option_index].name); if (optarg) printf (" with arg %s", optarg); printf ("\n"); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case 'd': printf ("option d with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ xdelta-1.2.1/libedsio/000077500000000000000000000000001525650667300146055ustar00rootroot00000000000000xdelta-1.2.1/libedsio/base64.c000077500000000000000000000242531525650667300160460ustar00rootroot00000000000000/* -*-Mode: C;-*- * $Id: base64.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $ * * Copyright (C) 1998, 1999, Josh MacDonald. * All Rights Reserved. * * Author: Josh MacDonald */ #include "edsio.h" /* BASE64 Encoding */ static const unsigned char base64_table[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; static gint16 base64_inverse_table[128]; static void init_inverse_table (void) { static int i = 0; static int j = 0; for (; j < 128; j += 1) base64_inverse_table[j] = -1; for (; i < 64; i += 1) base64_inverse_table[base64_table[i]] = i; base64_inverse_table['='] = 0; } GByteArray* edsio_base64_encode_region (const guint8* data, guint len) { GByteArray* out = g_byte_array_new (); guint real_len; g_byte_array_set_size (out, (len+2)*4/3); real_len = out->len; if (! edsio_base64_encode_region_into (data, len, out->data, &real_len)) { g_byte_array_free (out, TRUE); return NULL; } g_byte_array_set_size (out, real_len); return out; } gboolean edsio_base64_encode_region_into (const guint8* data, guint len, guint8* out, guint *out_len) { guint i; guint32 word = 0, count = 0; if ((*out_len) < (len + 2) * 4/3) { edsio_generate_void_event (EC_EdsioInvalidBase64Encoding); return FALSE; } *out_len = 0; for (i = 0; i < len; i += 1) { word |= data[i] << (8*(2-(count++))); if (count == 3) { out[(*out_len)++] = base64_table[(word>>18) & 0x3f]; out[(*out_len)++] = base64_table[(word>>12) & 0x3f]; out[(*out_len)++] = base64_table[(word>> 6) & 0x3f]; out[(*out_len)++] = base64_table[(word ) & 0x3f]; count = 0; word = 0; } } if (count > 0) { out[(*out_len)++] = base64_table[(word>>18) & 0x3f]; out[(*out_len)++] = base64_table[(word>>12) & 0x3f]; out[(*out_len)++] = (count > 1) ? base64_table[(word>>6) & 0x3f] : '='; out[(*out_len)++] = '='; } return TRUE; } GByteArray* edsio_base64_decode_region (const guint8* data, guint data_len) { GByteArray* it = g_byte_array_new (); guint real_len; g_byte_array_set_size (it, data_len*3/4); real_len = it->len; if (! edsio_base64_decode_region_into (data, data_len, it->data, &real_len)) { g_byte_array_free (it, TRUE); return NULL; } g_byte_array_set_size (it, real_len); return it; } gboolean edsio_base64_decode_region_into (const guint8* data, guint len, guint8* out, guint *out_len) { guint32 pos = 0; gboolean found_end = FALSE; gint found_end_at = 0; init_inverse_table (); if ((*out_len) < (len*3/4)) { edsio_generate_void_event (EC_EdsioOutputBufferShort); return FALSE; } (*out_len) = 0; while (pos < len) { gint i, x; gint word = 0, junk = 0; if (len - pos < 4) { edsio_generate_void_event (EC_EdsioInvalidBase64Encoding); return FALSE; } for (i = 0; i < 4; i += 1) { x = data[pos++]; if (x > 127 || base64_inverse_table[x] < 0) { edsio_generate_void_event (EC_EdsioInvalidBase64Encoding); return FALSE; } if (x == '=') { if (! found_end) found_end_at = i; found_end = TRUE; } else { if (found_end) { edsio_generate_void_event (EC_EdsioInvalidBase64Encoding); return FALSE; } word |= base64_inverse_table[x] << (6*(3-i)); } } if (found_end) { if (found_end_at < 2) { edsio_generate_void_event (EC_EdsioInvalidBase64Encoding); return FALSE; } if (found_end_at == 2) junk = 2; else if (found_end_at == 3) junk = 1; } else junk = 0; out[(*out_len)++] = (word >> 16) & 0xff; if (junk < 2) out[(*out_len)++] = (word >> 8) & 0xff; if (junk < 1) out[(*out_len)++] = (word >> 0) & 0xff; } return TRUE; } /* Base64 sink */ typedef struct _Base64Sink Base64Sink; static gboolean base64_sink_close (SerialSink* sink); static gboolean base64_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len); static void base64_sink_free (SerialSink* sink); static gboolean base64_sink_quantum (SerialSink* sink); struct _Base64Sink { SerialSink sink; SerialSink* out; guint32 word; guint32 count; }; SerialSink* serializeio_base64_sink (SerialSink* out) { Base64Sink* it = g_new0 (Base64Sink, 1); SerialSink* sink = (SerialSink*) it; serializeio_sink_init (sink, NULL, base64_sink_close, base64_sink_write, base64_sink_free, base64_sink_quantum); it->out = out; return sink; } gboolean base64_sink_write (SerialSink* fsink, const guint8 *ptr, guint32 len) { guint32 i; Base64Sink* sink = (Base64Sink*) fsink; for (i = 0; i < len; ) { if (sink->count == 3) { guint8 out[4]; out[0] = base64_table[(sink->word>>18) & 0x3f]; out[1] = base64_table[(sink->word>>12) & 0x3f]; out[2] = base64_table[(sink->word>> 6) & 0x3f]; out[3] = base64_table[(sink->word ) & 0x3f]; #if 0 g_print ("%02x %02x %02x -> %c%c%c%c (3)\n", (sink->word>>16) & 0xff, (sink->word>>8) & 0xff, (sink->word>>0) & 0xff, out[0], out[1], out[2], out[3]); #endif if (! sink->out->sink_write (sink->out, out, 4)) return FALSE; sink->count = 0; sink->word = 0; } while (sink->count < 3 && i < len) sink->word |= ptr[i++] << (8*(2-(sink->count++))); } return TRUE; } gboolean base64_sink_close (SerialSink* fsink) { Base64Sink* sink = (Base64Sink*) fsink; if (sink->count == 3) { guint8 out[4]; out[0] = base64_table[(sink->word>>18) & 0x3f]; out[1] = base64_table[(sink->word>>12) & 0x3f]; out[2] = base64_table[(sink->word>> 6) & 0x3f]; out[3] = base64_table[(sink->word ) & 0x3f]; #if 0 g_print ("%02x %02x %02x -> %c%c%c%c (3)\n", (sink->word>>16) & 0xff, (sink->word>>8) & 0xff, (sink->word>>0) & 0xff, out[0], out[1], out[2], out[3]); #endif if (! sink->out->sink_write (sink->out, out, 4)) return FALSE; sink->count = 0; sink->word = 0; } if (sink->count > 0) { guint8 out[4]; out[0] = base64_table[(sink->word>>18) & 0x3f]; out[1] = base64_table[(sink->word>>12) & 0x3f]; out[2] = (sink->count > 1) ? base64_table[(sink->word>>6) & 0x3f] : '='; out[3] = '='; #if 0 g_print ("%02x %02x %02x -> %c%c%c%c (%d)\n", (sink->word>>16) & 0xff, (sink->word>>8) & 0xff, (sink->word>>0) & 0xff, out[0], out[1], out[2], out[3], sink->count); #endif if (! sink->out->sink_write (sink->out, out, 4)) return FALSE; sink->count = 0; sink->word = 0; } return sink->out->sink_close (sink->out); } void base64_sink_free (SerialSink* fsink) { Base64Sink* sink = (Base64Sink*) fsink; sink->out->sink_free (sink->out); g_free (sink); } gboolean base64_sink_quantum (SerialSink* fsink) { Base64Sink* sink = (Base64Sink*) fsink; if (sink->out->sink_quantum) return sink->out->sink_quantum (sink->out); return TRUE; } /* Base64 source */ typedef struct _Base64Source Base64Source; struct _Base64Source { SerialSource source; SerialSource *in; guint32 avail; guint32 count; gboolean found_end; gint found_end_at; guint8 buf[3]; }; static gboolean base64_source_close (SerialSource* source); static gboolean base64_source_read (SerialSource* source, guint8 *ptr, guint32 len); static void base64_source_free (SerialSource* source); SerialSource* serializeio_base64_source (SerialSource* in0) { Base64Source* it = g_new0 (Base64Source, 1); SerialSource* source = (SerialSource*) it; serializeio_source_init (source, NULL, base64_source_close, base64_source_read, base64_source_free, NULL, NULL); it->in = in0; return source; } gboolean base64_source_close (SerialSource* fsource) { Base64Source* source = (Base64Source*) fsource; if (! source->in->source_close (source->in)) return FALSE; return TRUE; } gboolean base64_source_read (SerialSource* fsource, guint8 *ptr, guint32 len) { guint32 pos; Base64Source* source = (Base64Source*) fsource; init_inverse_table (); for (pos = 0; pos < len; ) { if (source->count == 0) { guint8 buf[4]; guint32 i, word = 0, junk; if (source->found_end) { edsio_generate_void_event (EC_EdsioInvalidBase64Encoding); return FALSE; } if (! source->in->source_read (source->in, buf, 4)) return FALSE; for (i = 0; i < 4; i += 1) { gint x = buf[i]; if (x > 127 || base64_inverse_table[x] < 0) { edsio_generate_void_event (EC_EdsioInvalidBase64Encoding); return FALSE; } if (x == '=') { if (! source->found_end) source->found_end_at = i; source->found_end = TRUE; } else { if (source->found_end) { edsio_generate_void_event (EC_EdsioInvalidBase64Encoding); return FALSE; } word |= base64_inverse_table[x] << (6*(3-i)); } } if (source->found_end) { if (source->found_end_at == 2) junk = 2; else if (source->found_end_at == 3) junk = 1; else { edsio_generate_void_event (EC_EdsioInvalidBase64Encoding); return FALSE; } } else junk = 0; source->avail = source->count = 3 - junk; source->buf[0] = (word >> 16) & 0xff; source->buf[1] = (word >> 8) & 0xff; source->buf[2] = (word >> 0) & 0xff; #if 0 g_print ("%c%c%c%c -> %02x %02x %02x (%d)\n", buf[0], buf[1], buf[2], buf[3], (word>>16) & 0xff, (word>>8) & 0xff, (word>>0) & 0xff, 3-junk); #endif } ptr[pos++] = source->buf[source->avail-(source->count--)]; } return TRUE; } void base64_source_free (SerialSource* fsource) { Base64Source* source = (Base64Source*) fsource; source->in->source_free (source->in); g_free (source); } xdelta-1.2.1/libedsio/default.c000077500000000000000000000163461525650667300164120ustar00rootroot00000000000000/* -*-Mode: C;-*- * $Id: default.c 1.2 Sun, 28 Jan 2007 12:21:11 -0800 jmacd $ * * Copyright (C) 1998, 1999, Josh MacDonald. * All Rights Reserved. * * Author: Josh MacDonald */ #include "edsio.h" /* Default Sink methods */ static gboolean sink_type_default (SerialSink* sink, SerialType type, guint32 len, gboolean set_allocation) { if (! sink->next_uint32 (sink, type)) return FALSE; /* Note: set_allocation is deprecated in 1.1.4 */ if (set_allocation && !sink->next_uint32 (sink, len)) return FALSE; return TRUE; } static gboolean sink_next_uint16 (SerialSink* sink, guint16 num) { num = g_htons (num); return sink->sink_write (sink, (guint8*) &num, sizeof (num)); } static gboolean sink_next_uint32 (SerialSink* sink, guint32 num) { num = g_htonl (num); return sink->sink_write (sink, (guint8*) &num, sizeof (num)); } static gboolean sink_next_uint (SerialSink* sink, guint32 num) { /* This is mostly because I dislike endian, and less to save space * on small ints. However, the uint32 and uint16 functions are used * when the number is expected to be large, in which case this * format can expand the number. */ guint8 sink_buf[16]; /* this is enough room for a 12-byte int */ guint sink_count = 0; do { guint left = num & 0x7f; guint outnum; num >>= 7; outnum = left | (num ? 0x80 : 0); sink_buf[sink_count++] = outnum; } while (num); return sink->sink_write (sink, sink_buf, sink_count); } static gboolean sink_next_uint8 (SerialSink* sink, guint8 val) { return sink->sink_write (sink, &val, 1); } static gboolean sink_next_bool (SerialSink* sink, gboolean val) { guint8 sink_buf[1]; sink_buf[0] = val; return sink->sink_write (sink, sink_buf, 1); } static gboolean sink_next_string (SerialSink* sink, const char *ptr) { return sink->next_bytes (sink, (const guint8*) ptr, strlen (ptr)); } static gboolean sink_next_bytes (SerialSink* sink, const guint8 *ptr, guint32 len) { return sink->next_uint (sink, len) && sink->sink_write (sink, ptr, len); } static gboolean sink_next_bytes_known (SerialSink* sink, const guint8 *ptr, guint32 len) { return sink->sink_write (sink, ptr, len); } void serializeio_sink_init (SerialSink* it, gboolean (* sink_type) (SerialSink* sink, SerialType type, guint32 mem_size, gboolean set_allocation), gboolean (* sink_close) (SerialSink* sink), gboolean (* sink_write) (SerialSink* sink, const guint8 *ptr, guint32 len), void (* sink_free) (SerialSink* sink), gboolean (* sink_quantum) (SerialSink* sink)) { it->next_bytes_known = sink_next_bytes_known; it->next_bytes = sink_next_bytes; it->next_uint = sink_next_uint; it->next_uint32 = sink_next_uint32; it->next_uint16 = sink_next_uint16; it->next_uint8 = sink_next_uint8; it->next_bool = sink_next_bool; it->next_string = sink_next_string; if (sink_type) it->sink_type = sink_type; else it->sink_type = sink_type_default; it->sink_close = sink_close; it->sink_write = sink_write; it->sink_free = sink_free; it->sink_quantum = sink_quantum; } /* Default Source methods */ static SerialType source_type_default (SerialSource* source, gboolean set_allocation) { guint32 x; if (! source->next_uint32 (source, & x)) return ST_Error; if (set_allocation) { /* Note: set_allocation is deprecated in 1.1.4 */ guint32 bogus; if (! source->next_uint32 (source, &bogus)) return ST_Error; } return x; } static gboolean source_next_uint32 (SerialSource* source, guint32 *ptr) { guint32 x; if (! source->source_read (source, (guint8*) &x, sizeof (x))) return FALSE; (*ptr) = g_ntohl (x); return TRUE; } static gboolean source_next_uint16 (SerialSource* source, guint16 *ptr) { guint16 x; if (! source->source_read (source, (guint8*) &x, sizeof (x))) return FALSE; (*ptr) = g_ntohs (x); return TRUE; } static gboolean source_next_uint (SerialSource* source, guint32 *ptr) { /* This is mostly because I dislike endian, and less to save space * on small ints */ guint8 c; guint8 arr[16]; gint i = 0; gint donebit = 1; gint bits; while (source->next_uint8 (source, &c)) { donebit = c & 0x80; bits = c & 0x7f; arr[i++] = bits; if (!donebit) break; } if (donebit) return FALSE; *ptr = 0; for (i -= 1; i >= 0; i -= 1) { *ptr <<= 7; *ptr |= arr[i]; } return TRUE; } static gboolean source_next_uint8 (SerialSource* source, guint8 *ptr) { return source->source_read (source, ptr, 1); } static gboolean source_next_bool (SerialSource* source, gboolean *ptr) { guint8 sink_buf[1]; if (! source->source_read (source, sink_buf, 1)) return FALSE; if (sink_buf[0]) *ptr = TRUE; else *ptr = FALSE; return TRUE; } static gboolean source_next_string (SerialSource* source, const char **ptr) { guint32 len; guint8* buf; if (! source->next_uint (source, &len)) return FALSE; if (! (buf = serializeio_source_alloc (source, len+1))) return FALSE; buf[len] = 0; (*ptr) = (const char*) buf; return source->source_read (source, buf, len); } static gboolean source_next_bytes (SerialSource* source, const guint8 **ptr, guint32 *len_ptr) { guint32 len; guint8* buf; if (! source->next_uint (source, &len)) return FALSE; if (! (buf = serializeio_source_alloc (source, len))) return FALSE; (*len_ptr) = len; (*ptr) = buf; return source->source_read (source, buf, len); } static gboolean source_next_bytes_known (SerialSource* source, guint8 *ptr, guint32 len) { return source->source_read (source, ptr, len); } void* serializeio_source_alloc (SerialSource* source, guint32 len) { AllocList *al; void* ret; if (source->salloc_func) { ret = source->salloc_func (source, len); al = source->salloc_func (source, sizeof(AllocList)); } else { ret = g_malloc0 (len); al = g_malloc0 (sizeof(AllocList)); } al->ptr = ret; al->next = source->alloc_list; source->alloc_list = al; return ret; } void serializeio_source_init (SerialSource* it, SerialType (* source_type) (SerialSource* source, gboolean set_allocation), gboolean (* source_close) (SerialSource* source), gboolean (* source_read) (SerialSource* source, guint8 *ptr, guint32 len), void (* source_free) (SerialSource* source), void* (* salloc_func) (SerialSource* source, guint32 len), void (* sfree_func) (SerialSource* source, void* ptr)) { it->alloc_list = NULL; it->next_bytes_known = source_next_bytes_known; it->next_bytes = source_next_bytes; it->next_uint = source_next_uint; it->next_uint32 = source_next_uint32; it->next_uint16 = source_next_uint16; it->next_uint8 = source_next_uint8; it->next_bool = source_next_bool; it->next_string = source_next_string; if (source_type != NULL) it->source_type = source_type; else it->source_type = source_type_default; it->source_close = source_close; it->source_read = source_read; it->source_free = source_free; it->salloc_func = salloc_func; it->sfree_func = sfree_func; } xdelta-1.2.1/libedsio/edsio.c000077500000000000000000000673341525650667300160740ustar00rootroot00000000000000/* -*-Mode: C;-*- * $Id: edsio.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $ * * Copyright (C) 1998, 1999, Josh MacDonald. * All Rights Reserved. * * Author: Josh MacDonald */ #include "edsio.h" #include #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #include "maketime.h" /*#define DEBUG_PROPS*/ /* Event delivery */ static GHashTable* all_event_defs = NULL; static GPtrArray* all_event_watchers = NULL; typedef struct _ErrorDeliveryWatcher ErrorDeliveryWatcher; typedef struct _DelayedEvent DelayedEvent; struct _ErrorDeliveryWatcher { ErrorDeliveryFunc deliver; }; struct _DelayedEvent { GenericEvent ev; GenericEventDef *def; const char *msg; }; void eventdelivery_initialize_event_def (gint code, gint level, gint flags, const char* name, const char* oneline, const char * (* field_to_string) (GenericEvent* ev, gint field)) { GenericEventDef* def = g_new0 (GenericEventDef, 1); if (! all_event_defs) all_event_defs = g_hash_table_new (g_int_hash, g_int_equal); def->code = code; def->level = level; def->flags = flags; def->name = name; def->oneline = oneline; def->field_to_string = field_to_string; g_hash_table_insert (all_event_defs, & def->code, def); } void eventdelivery_event_watch_all (ErrorDeliveryFunc func) { ErrorDeliveryWatcher* w = g_new0 (ErrorDeliveryWatcher, 1); w->deliver = func; if (! all_event_watchers) all_event_watchers = g_ptr_array_new (); g_ptr_array_add (all_event_watchers, w); } GenericEventDef* eventdelivery_event_lookup (gint code) { return g_hash_table_lookup (all_event_defs, & code); } void eventdelivery_event_deliver (GenericEvent* e) { static gint in_call = FALSE; static GQueue* queued = NULL; static GPtrArray* free_strings = NULL; if (! queued) { queued = g_queue_new (); free_strings = g_ptr_array_new (); } in_call += 1; g_assert (e); edsio_edsio_init (); if (all_event_defs) { GenericEventDef* def = g_hash_table_lookup (all_event_defs, & e->code); if (def) { GString* out; const char* oneline = def->oneline; char c; out = g_string_new (NULL); while ((c = *oneline++)) { switch (c) { case '$': { const char* field; char *end; int f; if ((*oneline++) != '{') goto badevent; f = strtol (oneline, &end, 10); if (f < 0 || !end || end[0] != '}') goto badevent; oneline = end+1; g_assert (def->field_to_string); field = def->field_to_string (e, f); if (field) { g_string_append (out, field); g_free ((void*) field); } else goto badevent; } break; default: g_string_append_c (out, c); } } if (! all_event_watchers) { fprintf (stderr, "%s:%d: %s\n", e->srcfile, e->srcline, out->str); g_string_free (out, TRUE); } else if (in_call == 1) { guint i; for (i = 0; i < all_event_watchers->len; i += 1) { ErrorDeliveryWatcher* w = all_event_watchers->pdata[i]; if (! w->deliver (e, def, out->str)) { g_warning ("%s:%d: An error delivery routine failed: %s\n", e->srcfile, e->srcline, out->str); in_call = 0; return; } } while (g_queue_get_size (queued) > 0) { DelayedEvent* de = g_queue_pop (queued); for (i = 0; i < all_event_watchers->len; i += 1) { ErrorDeliveryWatcher* w = all_event_watchers->pdata[i]; if (! w->deliver (& de->ev, de->def, de->msg)) { g_warning ("%s:%d: An error delivery routine failed: %s\n", e->srcfile, e->srcline, out->str); in_call = 0; return; } } } for (i = 0; i < free_strings->len; i += 1) g_string_free (free_strings->pdata[i], TRUE); g_ptr_array_set_size (free_strings, 0); g_string_free (out, TRUE); } else { DelayedEvent* de = g_new (DelayedEvent, 1); de->ev = *e; de->def = def; de->msg = out->str; g_queue_push (queued, de); g_ptr_array_add (free_strings, out); } in_call -= 1; return; } } g_warning ("%s:%d: Unrecognized event delivered (code=%d)\n", e->srcfile, e->srcline, e->code); in_call -= 1; return; badevent: g_warning ("%s:%d: An malformed error could not print here (code=%d)\n", e->srcfile, e->srcline, e->code); in_call -= 1; return; } const char* eventdelivery_int_to_string (int x) { return g_strdup_printf ("%d", x); } const char* eventdelivery_string_to_string (const char* x) { return g_strdup (x); } const char* eventdelivery_source_to_string (SerialSource* x) { (void) x; return g_strdup ("@@@SerialSource"); } const char* eventdelivery_sink_to_string (SerialSink* x) { (void) x; return g_strdup ("@@@SerialSink"); } const char* eventdelivery_handle_to_string (FileHandle* x) { g_return_val_if_fail (x, g_strdup ("*error*")); return x->table->table_handle_name (x); } /* Misc crap. */ gboolean edsio_time_of_day (SerialGenericTime* setme) { #if HAVE_GETTIMEOFDAY struct timeval tv; if (gettimeofday (& tv, NULL)) { edsio_generate_errno_event (EC_EdsioGetTimeOfDayFailure); goto bail; } if (setme) { setme->nanos = tv.tv_usec * 1000; setme->seconds = tv.tv_sec; } #else time_t t = time (NULL); if (t < 0) { edsio_generate_errno_event (EC_EdsioTimeFailure); goto bail; } if (setme) { setme->nanos = 0; setme->seconds = t; } #endif return TRUE; bail: setme->nanos = 0; setme->seconds = 10; return FALSE; } gchar* edsio_time_to_iso8601 (SerialGenericTime *tp) { return edsio_time_t_to_iso8601 (tp->seconds); } gchar* edsio_time_t_to_iso8601 (guint32 t0) { static char timebuf[64]; time_t t = t0; struct tm lt = *localtime(&t); int utc_offset = difftm(<, gmtime(&t)); char sign = utc_offset < 0 ? '-' : '+'; int minutes = abs (utc_offset) / 60; int hours = minutes / 60; sprintf(timebuf, "%d-%02d-%02d %02d:%02d:%02d%c%02d%02d", lt.tm_year + 1900, lt.tm_mon + 1, lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec, sign, hours, minutes % 60); return timebuf; } static gboolean strtosl_checked (const char* str, long* l, const char* errmsg) { char* end; (*l) = strtol (str, &end, 10); if (!end || end[0]) { if (errmsg) edsio_generate_stringstring_event (EC_EdsioInvalidIntegerString, errmsg, str); (*l) = 0; return FALSE; } return TRUE; } gboolean strtosi_checked (const char* str, gint32* i, const char* errmsg) { long l; if (! strtosl_checked (str, &l, errmsg)) { (*i) = 0; return FALSE; } if (l > G_MAXINT || l < G_MININT) { if (errmsg) edsio_generate_stringstring_event (EC_EdsioIntegerOutOfRange, errmsg, str); (*i) = 0; return FALSE; } (*i) = l; return TRUE; } gboolean strtoss_checked (const char* str, gint16* i, const char* errmsg) { long l; if (! strtosl_checked (str, &l, errmsg)) { (*i) = 0; return FALSE; } if (l > G_MAXSHORT || l < G_MINSHORT) { if (errmsg) edsio_generate_stringstring_event (EC_EdsioIntegerOutOfRange, errmsg, str); (*i) = 0; return FALSE; } (*i) = l; return TRUE; } gboolean strtoui_checked (const char* str, guint32* i, const char* errmsg) { long l; if (! strtosl_checked (str, &l, errmsg)) { (*i) = 0; return FALSE; } if (l < 0) { if (errmsg) edsio_generate_stringstring_event (EC_EdsioInvalidIntegerSign, errmsg, str); (*i) = 0; return FALSE; } (*i) = l; if (l != (*i)) { if (errmsg) edsio_generate_stringstring_event (EC_EdsioIntegerOutOfRange, errmsg, str); (*i) = 0; return FALSE; } return TRUE; } gboolean strtous_checked (const char* str, guint16* i, const char* errmsg) { long l; if (! strtosl_checked (str, &l, errmsg)) { (*i) = 0; return FALSE; } if (l < 0) { if (errmsg) edsio_generate_stringstring_event (EC_EdsioInvalidIntegerSign, errmsg, str); (*i) = 0; return FALSE; } (*i) = l; if (l != (*i)) { if (errmsg) edsio_generate_stringstring_event (EC_EdsioIntegerOutOfRange, errmsg, str); (*i) = 0; return FALSE; } return TRUE; } gint edsio_md5_equal (gconstpointer v, gconstpointer v2) { return memcmp (v, v2, 16) == 0; } guint edsio_md5_hash (gconstpointer v) { guint8* md5 = (guint8*) v; guint x = 0; gint i, j; for (i = 0, j = 0; i < 16; i += 1, j += 1, j %= sizeof (guint32)) x ^= md5[i] << (8*j); return x; } void serializeio_print_bytes (const guint8* bytes, guint len0) { char buf[100]; guint i; guint len; len = MIN (len0, 32); for (i = 0; i < len; i += 1) sprintf (buf + 2*i, "%02x", bytes[i]); if (len0 > len) strcat (buf, "..."); g_print ("%s\n", buf); } void edsio_md5_to_string (const guint8* md5, char buf[33]) { gint i; for (i = 0; i < 16; i += 1) sprintf (buf + 2*i, "%02x", md5[i]); } static gboolean from_hex (char c, int* x, const char* ctx) { char buf[2]; if (c >= '0' && c <= '9') { (*x) = c - '0'; return TRUE; } else if (c >= 'A' && c <= 'F') { (*x) = c - 'A' + 10; return TRUE; } else if (c >= 'a' && c <= 'f') { (*x) = c - 'a' + 10; return TRUE; } buf[0] = c; buf[1] = 0; edsio_generate_stringstring_event (EC_EdsioInvalidHexDigit, buf, ctx); return FALSE; } gboolean edsio_md5_from_string (guint8* md5, const char buf[33]) { gint i; gint l = strlen (buf); if (l < 32) { edsio_generate_string_event (EC_EdsioMD5StringShort, buf); return FALSE; } else if (l > 32) { edsio_generate_string_event (EC_EdsioMD5StringLong, buf); return FALSE; } for (i = 0; i < 16; i += 1) { char c1 = buf[(2*i)]; char c2 = buf[(2*i)+1]; int x1, x2; if (! from_hex (c1, &x1, buf)) return FALSE; if (! from_hex (c2, &x2, buf)) return FALSE; md5[i] = (x1 << 4) | x2; } return TRUE; } /* Strings */ const char* edsio_intern_string (const char* str) { static GStringChunk* chunk = NULL; if (! chunk) chunk = g_string_chunk_new (256); return g_string_chunk_insert_const (chunk, str); } /* Properties */ typedef struct _EdsioHostType EdsioHostType; typedef struct _EdsioPropertyType EdsioPropertyType; struct _EdsioPropertyType { const char *type_name; PropFreeFunc freer; PropGSFunc getter; PropGSFunc setter; PropSerialize serialize; PropUnserialize unserialize; }; struct _EdsioHostType { const char *host_name; PropertyTableFunc ptable; PersistSourceFunc source; PersistSinkFunc sink; PersistIssetFunc isset; PersistUnsetFunc unset; }; struct _EdsioProperty { guint32 prop_code; const char *prop_name; guint32 prop_flags; EdsioPropertyType *type; EdsioHostType *host; }; union _EdsioPropertyEntry { guint32 as_uint32; SerialEdsioBytes as_bytes; gpointer as_vptr; const char* as_string; }; struct _EdsioGenericProperty { guint32 code; }; static GHashTable* all_property_types = NULL; static GHashTable* all_host_types = NULL; static GHashTable* all_properties = NULL; static GHashTable* all_property_codes = NULL; static guint32 property_code_sequence = 0; void edsio_initialize_property_type (const char* t, PropFreeFunc freer, PropGSFunc getter, PropGSFunc setter, PropSerialize ser, PropUnserialize unser) { EdsioPropertyType* type; t = edsio_intern_string (t); if (! all_property_types) all_property_types = g_hash_table_new (g_direct_hash, g_direct_equal); if ((type = g_hash_table_lookup (all_property_types, t)) != NULL) { if (getter != type->getter || setter != type->setter || ser != type->serialize || unser != type->unserialize) edsio_generate_string_event (EC_EdsioDuplicatePropertyTypeRegistered, t); return; } type = g_new0 (EdsioPropertyType, 1); type->type_name = t; type->freer = freer; type->getter = getter; type->setter = setter; type->serialize = ser; type->unserialize = unser; g_hash_table_insert (all_property_types, (gpointer) t, type); } void edsio_initialize_host_type (const char* ph, PropertyTableFunc ptable, PersistSourceFunc source, PersistSinkFunc sink, PersistIssetFunc isset, PersistUnsetFunc unset) { EdsioHostType* host; ph = edsio_intern_string (ph); if (! all_host_types) all_host_types = g_hash_table_new (g_direct_hash, g_direct_equal); if (g_hash_table_lookup (all_host_types, ph)) { edsio_generate_string_event (EC_EdsioDuplicateHostTypeRegistered, ph); return; } host = g_new0 (EdsioHostType, 1); host->host_name = ph; host->ptable = ptable; host->source = source; host->sink = sink; host->isset = isset; host->unset = unset; g_hash_table_insert (all_host_types, (gpointer) ph, host); } gboolean edsio_new_property (const char* name, const char* ph, const char* t, guint32 flags, EdsioGenericProperty *ret_prop) { EdsioProperty* prop; EdsioPropertyType* type; EdsioHostType* host; name = edsio_intern_string (name); ph = edsio_intern_string (ph); t = edsio_intern_string (t); g_assert (all_property_types); if (! all_properties) { all_properties = g_hash_table_new (g_direct_hash, g_direct_equal); all_property_codes = g_hash_table_new (g_int_hash, g_int_equal); } if ((prop = g_hash_table_lookup (all_properties, name)) != NULL) { edsio_generate_string_event (EC_EdsioDuplicatePropertyNameRegistered, name); ret_prop->code = prop->prop_code; return TRUE; } if ((type = g_hash_table_lookup (all_property_types, t)) == NULL) { edsio_generate_string_event (EC_EdsioNoSuchPropertyType, t); return FALSE; } if ((host = g_hash_table_lookup (all_host_types, ph)) == NULL) { edsio_generate_string_event (EC_EdsioNoSuchHostType, ph); return FALSE; } if (flags & PF_Persistent && ! host->isset) { edsio_generate_stringstring_event (EC_EdsioPersistenceUnavailable, name, ph); return FALSE; } prop = g_new0 (EdsioProperty, 1); prop->prop_code = ++property_code_sequence; prop->prop_name = name; prop->prop_flags = flags; prop->type = type; prop->host = host; g_hash_table_insert (all_properties, (gpointer) name, prop); g_hash_table_insert (all_property_codes, & prop->prop_code, prop); ret_prop->code = prop->prop_code; return TRUE; } static EdsioProperty* edsio_property_find (const char* ph, const char* t, guint32 code) { EdsioProperty* prop; ph = edsio_intern_string (ph); t = edsio_intern_string (t); if (code <= 0 || code > property_code_sequence) { edsio_generate_int_event (EC_EdsioNoSuchProperty, code); return NULL; } if (! (prop = g_hash_table_lookup (all_property_codes, & code))) { edsio_generate_int_event (EC_EdsioNoSuchProperty, code); return NULL; } if (prop->host->host_name != ph) { edsio_generate_stringstringstring_event (EC_EdsioWrongHostType, prop->prop_name, ph, prop->host->host_name); return NULL; } if (prop->type->type_name != t) { edsio_generate_stringstringstring_event (EC_EdsioWrongDataType, prop->prop_name, t, prop->type->type_name); return NULL; } return prop; } EdsioPropertyEntry* edsio_property_get (gpointer obj, EdsioProperty* prop) { EdsioPropertyEntry* ent; GHashTable* table = * prop->host->ptable (obj); gboolean persist = prop->prop_flags & PF_Persistent; #ifdef DEBUG_PROPS g_print ("get %p.%s\n", obj, prop->prop_name); #endif if (table && (ent = g_hash_table_lookup (table, & prop->prop_code)) != NULL) return ent; if (persist) { SerialSource* src; if (! (src = prop->host->source (obj, prop->prop_name))) return NULL; g_assert (prop->type->unserialize); if (! prop->type->unserialize (src, & ent)) return NULL; g_assert (ent); if (! src->source_close (src)) return NULL; src->source_free (src); if (! table) table = (* prop->host->ptable (obj)) = g_hash_table_new (g_int_hash, g_int_equal); g_hash_table_insert (table, & prop->prop_code, ent); return ent; } edsio_generate_string_event (EC_EdsioPropertyNotSet, prop->prop_name); return NULL; } gboolean edsio_property_set (gpointer obj, EdsioProperty* prop, EdsioPropertyEntry* set) { EdsioPropertyEntry* ent; gboolean persist = prop->prop_flags & PF_Persistent; GHashTable* table = * prop->host->ptable (obj); #ifdef DEBUG_PROPS g_print ("set %p.%s\n", obj, prop->prop_name); #endif if (! table) table = (* prop->host->ptable (obj)) = g_hash_table_new (g_int_hash, g_int_equal); ent = g_hash_table_lookup (table, & prop->prop_code); if (ent) { g_hash_table_remove (table, & prop->prop_code); prop->type->freer (ent); } g_hash_table_insert (table, & prop->prop_code, set); if (persist) { SerialSink* sink; if (! (sink = prop->host->sink (obj, prop->prop_name))) return FALSE; g_assert (prop->type->serialize); if (! prop->type->serialize (sink, set)) return FALSE; if (! sink->sink_close (sink)) return FALSE; sink->sink_free (sink); } return TRUE; } gboolean edsio_property_isset (const char* ph, const char* t, guint32 code, gpointer obj) { EdsioProperty* prop; GHashTable* table; gboolean persist; gboolean result = FALSE; if (! (prop = edsio_property_find (ph, t, code))) goto done; persist = prop->prop_flags & PF_Persistent; table = * prop->host->ptable (obj); if (persist) { PersistIssetFunc issetfunc = prop->host->isset; if (issetfunc(obj, prop->prop_name)) { if (! edsio_property_get (obj, prop)) goto done; table = * prop->host->ptable (obj); } } if (! table) goto done; result = (g_hash_table_lookup (table, & code) != NULL); done: #ifdef DEBUG_PROPS g_print ("isset %p.%s = %s\n", obj, prop->prop_name, result ? "true" : "false"); #endif return result; } gboolean edsio_property_unset (const char* ph, const char* t, guint32 code, gpointer obj) { EdsioProperty* prop; gboolean persist; GHashTable* table; if (! (prop = edsio_property_find (ph, t, code))) return FALSE; #ifdef DEBUG_PROPS g_print ("unset %p.%s\n", obj, prop->prop_name); #endif persist = prop->prop_flags & PF_Persistent; table = * prop->host->ptable (obj); if (table) { g_hash_table_remove (table, & code); if (g_hash_table_size (table) == 0) { g_hash_table_destroy (table); table = (* prop->host->ptable (obj)) = NULL; } /*g_free (ent);*/ } if (persist) { if (! prop->host->unset (obj, prop->prop_name)) return FALSE; } return TRUE; } static gboolean edsio_false (gpointer obj, EdsioProperty* prop, ...) { (void) obj; (void) prop; return FALSE; } PropGSFunc edsio_property_getter (const char* ph, const char* t, guint32 code, EdsioProperty** ep) { if (! ((*ep) = edsio_property_find (ph, t, code))) return & edsio_false; return (* ep)->type->getter; } PropGSFunc edsio_property_setter (const char* ph, const char* t, guint32 code, EdsioProperty** ep) { if (! ((* ep) = edsio_property_find (ph, t, code))) return & edsio_false; return (* ep)->type->setter; } /* Primitive type serializers */ /* integer */ gboolean edsio_property_uint_getter (gpointer obj, EdsioProperty* prop, guint32* get) { EdsioPropertyEntry *ent; if (! (ent = edsio_property_get (obj, prop))) return FALSE; (*get) = ent->as_uint32; return TRUE; } gboolean edsio_property_uint_setter (gpointer obj, EdsioProperty* prop, guint32 set) { EdsioPropertyEntry *ent = g_new (EdsioPropertyEntry, 1); ent->as_uint32 = set; return edsio_property_set (obj, prop, ent); } void edsio_property_uint_free (gpointer obj) { g_free (obj); } gboolean unserialize_uint (SerialSource *source, guint32** x) { SerialEdsioUint *s; guint32 *n; if (! unserialize_edsiouint (source, & s)) return FALSE; n = g_new (guint32, 1); (* x) = n; (* n) = s->val; g_free (s); return TRUE; } gboolean serialize_uint_obj (SerialSink *sink, guint32* x) { return serialize_edsiouint (sink, *x); } /* String */ void edsio_property_string_free (gpointer obj) { g_free (obj); } gboolean edsio_property_string_getter (gpointer obj, EdsioProperty* prop, const char** get) { if (! ((*get) = (const char*) edsio_property_get (obj, prop))) return FALSE; return TRUE; } gboolean edsio_property_string_setter (gpointer obj, EdsioProperty* prop, const char* set) { return edsio_property_set (obj, prop, (EdsioPropertyEntry*) set); } gboolean unserialize_string (SerialSource *source, const char** x) { SerialEdsioString *s; if (! unserialize_edsiostring (source, & s)) return FALSE; (*x) = g_strdup (s->val); g_free (s); return TRUE; } gboolean serialize_string_obj (SerialSink *sink, const char* x) { return serialize_edsiostring (sink, x); } /* Bytes */ gboolean unserialize_bytes (SerialSource *source, SerialEdsioBytes** x) { return unserialize_edsiobytes (source, x); } gboolean serialize_bytes_obj (SerialSink *sink, SerialEdsioBytes *x) { return serialize_edsiobytes_obj (sink, x); } gboolean edsio_property_bytes_getter (gpointer obj, EdsioProperty* prop, guint8** get, guint32* get_len) { EdsioPropertyEntry *ent; if (! (ent = edsio_property_get (obj, prop))) return FALSE; (* get) = (gpointer) ent->as_bytes.val; (* get_len) = ent->as_bytes.val_len; return TRUE; } gboolean edsio_property_bytes_setter (gpointer obj, EdsioProperty* prop, guint8* set, guint32 set_len) { EdsioPropertyEntry *ent = g_new (EdsioPropertyEntry, 1); ent->as_bytes.val = set; ent->as_bytes.val_len = set_len; return edsio_property_set (obj, prop, ent); } void edsio_property_bytes_free (gpointer obj) { g_free (obj); } /* Vptr */ gboolean edsio_property_vptr_getter (gpointer obj, EdsioProperty* prop, void** get) { if (! ((*get) = edsio_property_get (obj, prop))) return FALSE; return TRUE; } gboolean edsio_property_vptr_setter (gpointer obj, EdsioProperty* prop, void* set) { return edsio_property_set (obj, prop, (EdsioPropertyEntry*) set); } void edsio_property_vptr_free (gpointer obj) { (void) obj; /* nothing */ } /* Testing */ #ifdef DEBUG_LIBEDSIO GHashTable** edsio_proptest_property_table (PropTest *pt) { return & pt->_edsio_property_table; } SerialSource* edsio_persist_proptest_source (PropTest *pt, const char* prop_name) { GByteArray* array; if (! pt->ptable) { g_warning ("can't get persist property, no table\n"); return NULL; } if (! (array = g_hash_table_lookup (pt->ptable, prop_name))) { g_warning ("can't lookup persist property\n"); return NULL; } return edsio_simple_source (array->data, array->len, SBF_None); } static void pt_success (gpointer data, GByteArray* result) { PropTest* pt = data; GByteArray* old; if (! pt->ptable) pt->ptable = g_hash_table_new (g_str_hash, g_str_equal); old = g_hash_table_lookup (pt->ptable, (gpointer) pt->kludge); if (old) g_byte_array_free (old, TRUE); g_hash_table_insert (pt->ptable, (gpointer) pt->kludge, result); } SerialSink* edsio_persist_proptest_sink (PropTest *pt, const char* prop_name) { pt->kludge = prop_name; return edsio_simple_sink (pt, SBF_None, FALSE, pt_success, NULL); } gboolean edsio_persist_proptest_isset (PropTest *pt, const char* prop_name) { if (! pt->ptable) return FALSE; return g_hash_table_lookup (pt->ptable, prop_name) != NULL; } gboolean edsio_persist_proptest_unset (PropTest *pt, const char* prop_name) { GByteArray* old; if (! pt->ptable) return FALSE; old = g_hash_table_lookup (pt->ptable, prop_name); if (old) { g_byte_array_free (old, TRUE); g_hash_table_remove (pt->ptable, prop_name); return TRUE; } return FALSE; } #endif /* Misc source/sink stuff */ SerialSink* serializeio_gzip_sink (SerialSink* sink) { /* @@@ not implemented */ return sink; } SerialSource* serializeio_gzip_source (SerialSource* source) { /* @@@ not implemented */ return source; } /* Checksum sink */ typedef struct _ChecksumSink ChecksumSink; static gboolean checksum_sink_close (SerialSink* sink); static gboolean checksum_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len); static void checksum_sink_free (SerialSink* sink); static gboolean checksum_sink_quantum (SerialSink* sink); struct _ChecksumSink { SerialSink sink; SerialSink* out; EdsioMD5Ctx ctx; guint8 md5[16]; gboolean md5_done; gboolean md5_written; }; SerialSink* serializeio_checksum_sink (SerialSink* out) { ChecksumSink* it = g_new0 (ChecksumSink, 1); SerialSink* sink = (SerialSink*) it; serializeio_sink_init (sink, NULL, checksum_sink_close, checksum_sink_write, checksum_sink_free, checksum_sink_quantum); it->out = out; edsio_md5_init (& it->ctx); return sink; } gboolean checksum_sink_write (SerialSink* fsink, const guint8 *ptr, guint32 len) { ChecksumSink* sink = (ChecksumSink*) fsink; if (! sink->out->sink_write (sink->out, ptr, len)) return FALSE; edsio_md5_update (& sink->ctx, ptr, len); return TRUE; } gboolean checksum_sink_close (SerialSink* fsink) { ChecksumSink* sink = (ChecksumSink*) fsink; if (! sink->md5_done) { edsio_md5_final (sink->md5, & sink->ctx); sink->md5_done = TRUE; } if (! sink->out->sink_write (sink->out, sink->md5, 16)) return FALSE; if (! sink->out->sink_close (sink->out)) return FALSE; return TRUE; } void checksum_sink_free (SerialSink* fsink) { ChecksumSink* sink = (ChecksumSink*) fsink; sink->out->sink_free (sink->out); g_free (sink); } gboolean checksum_sink_quantum (SerialSink* fsink) { ChecksumSink* sink = (ChecksumSink*) fsink; if (sink->out->sink_quantum) return sink->out->sink_quantum (sink->out); return TRUE; } /* Checksum source */ typedef struct _ChecksumSource ChecksumSource; struct _ChecksumSource { SerialSource source; SerialSource *in; EdsioMD5Ctx ctx; }; static gboolean checksum_source_close (SerialSource* source); static gboolean checksum_source_read (SerialSource* source, guint8 *ptr, guint32 len); static void checksum_source_free (SerialSource* source); SerialSource* serializeio_checksum_source (SerialSource* in0) { ChecksumSource* it = g_new0 (ChecksumSource, 1); SerialSource* source = (SerialSource*) it; serializeio_source_init (source, NULL, checksum_source_close, checksum_source_read, checksum_source_free, NULL, NULL); it->in = in0; edsio_md5_init (& it->ctx); return source; } gboolean checksum_source_close (SerialSource* fsource) { ChecksumSource* source = (ChecksumSource*) fsource; guint8 buf1[16]; guint8 buf2[16]; if (! source->in->source_read (source->in, buf1, 16)) return FALSE; edsio_md5_final (buf2, & source->ctx); if (memcmp (buf1, buf2, 16) != 0) { edsio_generate_void_event (EC_EdsioInvalidStreamChecksum); return FALSE; } if (! source->in->source_close (source->in)) return FALSE; return TRUE; } gboolean checksum_source_read (SerialSource* fsource, guint8 *ptr, guint32 len) { ChecksumSource* source = (ChecksumSource*) fsource; if (! source->in->source_read (source->in, ptr, len)) return FALSE; edsio_md5_update (& source->ctx, ptr, len); return TRUE; } void checksum_source_free (SerialSource* fsource) { ChecksumSource* source = (ChecksumSource*) fsource; source->in->source_free (source->in); g_free (source); } xdelta-1.2.1/libedsio/edsio.el000077500000000000000000001573171525650667300162530ustar00rootroot00000000000000;; -*- Emacs-Lisp -*- (eval-and-compile (setq load-path (cons ".." (cons "." load-path)))) (provide 'edsio) (eval-and-compile (setq load-path (cdr (cdr load-path)))) ;; Begin (defconst *definition-state* nil "List of all the names of variables containing state from the definition file so that operations may be performed on everything in the definition file.") (defconst *definition-attrs* nil "List of attributes for sharing indices.") (defconst *all-objects* nil) (defconst *output-files* nil "List of lists (NAME BUFFER) used during output of headers.") (defconst *output-prefix* nil "Prefix used for outputing header files.") (defconst *cpp-extension* "c") ;; This defines several functions and one macro. The indirection makes ;; it a little bit confusing to read. It defines the macro DEFDNAME, ;; a function DEFDNAME*, MAKE-DNAME, and a setter and getter for each arg. (eval-and-compile (defmacro attr-index (attr) `(- (length *definition-attrs*) (length (memq ,attr *definition-attrs*)))) (defmacro defastmacro(dtype args attrs) "Defines a macro named DEFDTYPE for defining various AST properties." (let ((def-macr (intern (format "def%s" dtype))) (def-func (intern (format "def%s*" dtype))) (make-func (intern (format "make-%s" dtype))) (state (intern (format "*%s-defs*" dtype))) (exprs nil)) (if (not *definition-attrs*) (setq *definition-attrs* '(menunode menuline))) (let ((fields (append args attrs))) (while fields (if (not (memq (car fields) *definition-attrs*)) (setq *definition-attrs* (append *definition-attrs* (list (car fields))))) (setq fields (cdr fields)) ) ) ;; Add it to *definition-state* (setq *definition-state* (cons state *definition-state*)) ;; DEFCONST it (setq exprs (cons (list 'defconst state (quote nil)) exprs)) ;; DEFMACRO DEFDTYPE (setq exprs (cons (list 'defmacro def-macr args (append (list 'list (list 'quote def-func)) (mapcar (function (lambda (x) (list 'list (list 'quote 'quote) x) ) ) args) ) ) exprs ) ) ;; DEFUN DEFDTYPE* (setq exprs (cons (list 'defun def-func args (list 'setq state (list 'cons (cons make-func args) state ) ) ) exprs ) ) ;; MAKE-DTYPE (setq exprs (cons (list 'defun make-func args (list 'let (list (list 'it (list 'make-vector (length *definition-attrs*) nil))) (if args (cons 'progn (mapcar (function (lambda (x) (list 'aset 'it (attr-index x) x) ) ) args ) ) ) (if attrs (cons 'progn (mapcar (function (lambda (x) (list 'aset 'it (attr-index x) nil) ) ) attrs ) ) ) (if (memq 'menu args) (list 'progn (list 'aset 'it (attr-index 'menunode) (list 'function (intern (format "%s-menunode" dtype)))) (list 'aset 'it (attr-index 'menuline) (list 'function (intern (format "%s-menuline" dtype)))) ) ) (list 'cons (list 'quote dtype) 'it) ) ) exprs ) ) ;; Add the fake arguments: (if (memq 'menu args) (setq attrs (append (list 'menunode 'menuline) attrs))) (setq args (append args attrs)) (while args (let* ((thearg (car args)) (arg-set (intern (format "%s-%s-set" dtype thearg))) (arg-get (intern (format "%s-%s-get" dtype thearg)))) ;; DTYPE-ARG-GET (setq exprs (cons (list 'defmacro (intern (format "%s-%s-get" dtype thearg)) '(obj) (list 'list (list 'quote 'aref) (list 'list (list 'quote 'cdr) 'obj) (attr-index thearg)) ) exprs ) ) ;; DTYPE-ARG-SET (setq exprs (cons (list 'defmacro (intern (format "%s-%s-set" dtype thearg)) '(obj val) (list 'list (list 'quote 'aset) (list 'list (list 'quote 'cdr) 'obj) (attr-index thearg) 'val) ) exprs ) ) ) (setq args (cdr args)) ) ;; To see what it's generating uncomment the next 2 lines. ;;(setq message-log-max t) ;;(mapcar (function pp) exprs) (cons 'progn exprs) ) ) ;; This is, as the name suggests, really bogus. Basically, each DEFASTMACRO ;; call adds to the list *definition-state*. To compile it, however, it has ;; to be done at compile time, so this macro gets evaluated when being compiled ;; and clears the list. Then the DEFASTMACRO calls are made, and then DEFCDS ;; is called to define CLEAR-DEFINITION-STATE which resets the list to the ;; compile-time computed value of *definition-state*, it would otherwise be ;; empty when running compiled code. (defmacro bogus () (setq *definition-state* nil) (setq *definition-attrs* nil) ) (bogus) ;; Each DEFASTMACRO statement defines a directive for the definition ;; file along with it's argument names. (defastmacro sertype (name number fields transients) ()) (defastmacro module (name id header pheader) ()) (defastmacro import (name) (prefix)) (defastmacro event (name level uargs sargs desc) ()) (defastmacro etype (name ctype) ()) (defastmacro prophost (name letter ctype persist) (proptypes)) (defastmacro prophosttype (host type) ()) (defmacro defcds () (let ((exprs nil)) (setq exprs (list (list 'defun 'clear-definition-state nil '(setq *all-objects* nil) (list 'setq '*definition-state* (list 'quote *definition-state*)) (list 'setq '*definition-attrs* (list 'quote *definition-attrs*)) '(mapcar (function (lambda (x) (set x nil))) *definition-state*) ) ) ) (mapc (function (lambda (x) (setq exprs (cons (list 'defmacro (intern (format "obj-%s-get" x)) '(obj) (list 'list (list 'quote 'aref) (list 'list (list 'quote 'cdr) 'obj) (attr-index x)) ) exprs ) ) (setq exprs (cons (list 'defmacro (intern (format "obj-%s-set" x)) '(obj val) (list 'list (list 'quote 'aset) (list 'list (list 'quote 'cdr) 'obj) (attr-index x) 'val) ) exprs ) ) (let ((get (intern (format "obj-%s-get" x)))) (setq exprs (cons (list 'defun (intern (format "obj-%s-eq" x)) '(val olist) `(let ((ret nil)) (while (and (not ret) olist) (if (eq val (,get (car olist))) (setq ret (car olist)) ) (setq olist (cdr olist)) ) ret ) ) exprs ) ) ) ) ) *definition-attrs* ) ;;(setq message-log-max t) ;;(mapcar (function pp) exprs) (cons 'progn exprs) ) ) (defcds) ) ;; Entry Points (defun generate-ser-noargs () (interactive) (generate-ser "edsio.ser" "edsio") ) (defun generate-ser (input-file output-prefix) ;(interactive "finput: \nsoutput: \nsid: ") (let ((make-backup-files nil) (executing-kbd-macro t)) (clear-definition-state) (do-it input-file output-prefix) ) ) (defconst *library-id* nil "Identifier of this library.") (defconst *library-header* nil "Header of this library.") (defconst *library-pheader* nil "Header of this library.") (defconst *prefix-with-library-header* t) (defun load-defs(file) (load-file file) (setq *import-defs* (reverse *import-defs*)) (setq *module-defs* (reverse *module-defs*)) (setq *sertype-defs* (reverse *sertype-defs*)) (setq *event-defs* (reverse *event-defs*)) (setq *etype-defs* (reverse *etype-defs*)) (setq *prophost-defs* (reverse *prophost-defs*)) (setq *prophosttype-defs* (reverse *prophosttype-defs*)) ) (defconst *header-typedef-marker* nil) (defconst *source-init-marker* nil) (defconst *source-top-marker* nil) (defun do-it (input-file output-prefix) (setq *output-files* nil) (setq *output-prefix* output-prefix) (load-defs input-file) (if (not *module-defs*) (error "no defmodule in %s" input-file)) (if (> (length *module-defs*) 1) (error "too many defmodules in %s" input-file)) (setq *library-id* (module-id-get (car *module-defs*))) (setq *library-header* (module-header-get (car *module-defs*))) (setq *library-pheader* (module-pheader-get (car *module-defs*))) (when (not *library-header*) (setq *prefix-with-library-header* nil) (setq *library-header* (format "%s_edsio.h" *output-prefix*)) ) (if (or (<= *library-id* 0) (>= *library-id* 256)) (error "Library-id is out of range")) (if (> (length *sertype-defs*) 24) (error "no more than 24 types")) (unwind-protect (progn (output-header-file "_edsio") (read-imports) (insert "/* Initialize this library. */\n\n") (insert "gboolean " *output-prefix* "_edsio_init (void);\n\n") (insert "/* Types defined here. */\n\n") (setq *header-typedef-marker* (point-marker)) (insert "/* Functions declared here. */\n\n") (output-source-file "_edsio") (insert "#include \"" *library-header* "\"\n\n") (insert "#include \n\n") (if *library-pheader* (insert "#include \"" *library-pheader* "\"\n\n")) (insert "/* Declarations. */\n\n") (setq *source-top-marker* (point-marker)) (insert "\n") (insert "/* initialize this library. */\n\n") (insert "gboolean\n" *output-prefix* "_edsio_init (void)\n{\n") (insert " static gboolean once = FALSE;\n") (insert " static gboolean result = FALSE;\n") (insert " if (once) return result;\n") (insert " once = TRUE;\n") (setq *source-init-marker* (point-marker)) (insert (format " edsio_library_register (%d, \"%s\");\n" *library-id* *output-prefix*)) (insert " result = TRUE;\n") (insert " return TRUE;\n") (insert "}\n\n") (if *prophosttype-defs* (generate-properties)) (if *sertype-defs* (generate-code)) (if *event-defs* (generate-events)) ; (message "source file:\n%s" (buffer-string)) (mapc (function (lambda (x) (output-finish-file x))) *output-files*) ) (mapc (function (lambda (x) (kill-buffer (cadr x)))) *output-files*) ) ) (defvar *all-sertype-defs* nil) (defvar *all-prophost-defs* nil) (defvar *all-etype-defs* nil) (defun read-imports () (setq *all-sertype-defs* *sertype-defs*) (setq *all-etype-defs* *etype-defs*) (setq *all-prophost-defs* *prophost-defs*) (let ((mods *module-defs*) (imps0 *import-defs*) (imps *import-defs*) (types *sertype-defs*) (events *event-defs*) (etypes *etype-defs*) (phosts *prophost-defs*) (phts *prophosttype-defs*) ) (while imps (clear-definition-state) (load-defs (import-name-get (car imps))) (setq *all-sertype-defs* (append *all-sertype-defs* *sertype-defs*)) (setq *all-etype-defs* (append *all-etype-defs* *etype-defs*)) (setq *all-prophost-defs* (append *all-prophost-defs* *prophost-defs*)) (import-prefix-set (car imps) (module-name-get (car *module-defs*))) (when (or *sertype-defs* *event-defs*) (output-header-file "_edsio") (insert (format "#include \"%s_edsio.h\"\n\n" (import-prefix-get (car imps)))) ) (setq imps (cdr imps)) ) (setq *module-defs* mods) (setq *import-defs* imps0) (setq *sertype-defs* types) (setq *event-defs* events) (setq *etype-defs* etypes) (setq *prophost-defs* phosts) (setq *prophosttype-defs* phts) ) ) (defun output-header-file (name) (output-file (format "%s.h" name) 'c-header *output-prefix*)) (defun output-source-file (name) (output-file (format "%s.%s" name *cpp-extension*) 'c *output-prefix*)) (defun output-source-include-file (name) (output-file (format "%s.%si" name *cpp-extension*) 'c *output-prefix*)) (defun output-plain-file (name) (output-file (format "%s" name) 'plain "")) (defun output-file (name type prefix) (let* ((name (format "%s%s" prefix name)) (it (assoc name *output-files*))) (if it (set-buffer (cadr it)) (let ((nbuf (get-buffer-create (generate-new-buffer-name name)))) (setq *output-files* (cons (list name nbuf type) *output-files*)) (set-buffer nbuf) ) ) ) ) (defun output-finish-file (file) (let ((name (car file)) (buf (cadr file)) (type (caddr file))) (set-buffer buf) ;(message "printing %s: %s" file (buffer-string)) (cond ((eq type 'c) (output-to-c name nil)) ((eq type 'c-header) (output-to-c name t)) ) (write-file-if-different buf name) ) ) (defun output-to-c (name is-header) (goto-char (point-min)) (insert "/* -*-Mode: C;-*- * Copyright (C) 1997, 1998, 1999 Josh MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Author: Josh MacDonald * * This file was AUTOMATICALLY GENERATED using: * * $Id: edsio.el 1.2 Sun, 28 Jan 2007 12:21:11 -0800 jmacd $ */ ") (if is-header (let ((cppname (string-replace-regexp (upcase name) "[-./]" "_"))) (insert "#include \"edsio.h\"\n\n") (if *prefix-with-library-header* (insert "#include \"" *library-header* "\"\n\n")) (insert "#ifndef _" cppname "_\n") (insert "#define _" cppname "_\n\n") (insert "#ifdef __cplusplus\n") (insert "extern \"C\" {\n") (insert "#endif\n\n") (goto-char (point-max)) (insert "#ifdef __cplusplus\n") (insert "}\n") (insert "#endif\n") (insert "\n#endif /* _" cppname "_ */\n\n") ) ) ) (defun string-replace-regexp (str regexp to-string) "Result of replacing all occurrences in STR of REGEXP by TO-STRING. The replacement is as for replace-regexp." (with-temp-buffer (insert str) (goto-char (point-min)) (while (re-search-forward regexp nil t) (replace-match to-string nil nil)) (buffer-string))) (defun write-file-if-different (buf filename) (with-current-buffer buf (goto-char (point-max)) (skip-chars-backward "\n") (delete-region (point) (point-max)) (insert "\n")) (if (and (file-exists-p filename) (with-temp-buffer (insert-file-contents filename) (let ((case-fold-search nil)) (= 0 (compare-buffer-substrings (current-buffer) (point-min) (point-max) buf (with-current-buffer buf (point-min)) (with-current-buffer buf (point-max))))))) (message "Output file %s is unchanged." filename) (with-current-buffer buf (write-region (point-min) (point-max) filename nil 'silent)))) (defun format-comlist (func l) (let ((x "")) (while l (setq x (concat x (funcall func (car l)))) (if (cdr l) (setq x (concat x ", "))) (setq l (cdr l)) ) x ) ) (defun format-semilist (func l) (let ((x "")) (while l (setq x (concat x (funcall func (car l)))) (if (cdr l) (setq x (concat x "; "))) (setq l (cdr l)) ) x ) ) (defun format-numbered-comlist (func l) (let ((x "") (n 0)) (while l (setq x (concat x (funcall func (car l) n))) (setq n (+ n 1)) (if (cdr l) (setq x (concat x ", "))) (setq l (cdr l)) ) x ) ) (defun capitalize1(s) (let ((str (format "%s" s))) (concat (upcase (substring str 0 1)) (substring str 1)))) (defun upcase-string (s) (upcase (format "%s" s))) (defun downcase-string (s) (downcase (format "%s" s))) ;; HERE IT IS (defun generate-code () (let ((all-codes nil)) (mapc (function (lambda (st) (let ((x (sertype-number-get st))) (cond ((member x all-codes) (error "serial type number %d defined twice" x)) ((> x 24) (error "serial type value %d too high" x)) ((< x 0) (error "serial type value %d too low" x)) (t (setq all-codes (cons x all-codes)))))) ) *sertype-defs*) ) (output-header-file "_edsio") (insert "/* Serial Types */\n\n") (insert (format "enum _Serial%sType {\n" (capitalize1 *output-prefix*))) (insert (format-comlist (function (lambda (x) (format "\n ST_%s = (1<<(%d+EDSIO_LIBRARY_OFFSET_BITS))+%d" (sertype-name-get x) (sertype-number-get x) *library-id*))) *sertype-defs*)) (insert "\n};\n\n") (insert "\n\n") (output-source-file "_edsio") (save-excursion (goto-char *source-top-marker*) (insert "static void print_spaces (guint n) { guint i; for (i = 0; i < n; i += 1) g_print (\" \"); }\n\n") ) (mapc (function generate-code-entry) *sertype-defs*) ) (defun generate-code-entry (entry) (let ((ent-upcase (sertype-name-get entry)) (ent-downcase (downcase-string (sertype-name-get entry)))) (output-header-file "_edsio") ;; The typedef, structure, and declarations. (save-excursion (goto-char *header-typedef-marker*) (insert (format "typedef struct _Serial%s Serial%s;\n" ent-upcase ent-upcase)) ) (insert (format "/* %s Structure\n */\n\n" ent-upcase)) (insert (format "struct _Serial%s {\n" ent-upcase)) (apply (function insert) (mapcar (function (lambda (x) (format " %s;\n" x))) (entry-typename-pairs entry nil))) (apply (function insert) (mapcar (function (lambda (x) (format " %s;\n" x))) (sertype-transients-get entry))) (insert "};\n\n") (insert (format "void serializeio_print_%s_obj (Serial%s* obj, guint indent_spaces);\n\n" ent-downcase ent-upcase)) (insert (format "gboolean unserialize_%s (SerialSource *source, Serial%s**);\n" ent-downcase ent-upcase)) (insert (format "gboolean unserialize_%s_internal (SerialSource *source, Serial%s** );\n" ent-downcase ent-upcase)) (insert (format "gboolean unserialize_%s_internal_noalloc (SerialSource *source, Serial%s* );\n" ent-downcase ent-upcase)) (insert (format "gboolean serialize_%s (SerialSink *sink%s);\n" ent-downcase (entry-arglist t entry))) (insert (format "gboolean serialize_%s_obj (SerialSink *sink, const Serial%s* obj);\n" ent-downcase ent-upcase)) (insert (format "gboolean serialize_%s_internal (SerialSink *sink%s);\n" ent-downcase (entry-arglist t entry))) (insert (format "gboolean serialize_%s_obj_internal (SerialSink *sink, Serial%s* obj);\n" ent-downcase ent-upcase)) (insert (format "guint serializeio_count_%s (%s);\n" ent-downcase (entry-arglist nil entry))) (insert (format "guint serializeio_count_%s_obj (Serial%s const* obj);\n" ent-downcase ent-upcase)) (insert (format "\n")) (output-source-file "_edsio") ;; Type-safe adapters for the generic serialization registry. (save-excursion (goto-char *source-top-marker*) (insert (format "static gboolean\nunserialize_%s_generic (SerialSource* source, void** object)\n{\n Serial%s* result = NULL;\n if (! unserialize_%s_internal (source, &result)) return FALSE;\n *object = result;\n return TRUE;\n}\n\n" ent-downcase ent-upcase ent-downcase)) (insert (format "static gboolean\nserialize_%s_generic (SerialSink* sink, void* object)\n{\n return serialize_%s_obj_internal (sink, object);\n}\n\n" ent-downcase ent-downcase)) (insert (format "static guint\nserializeio_count_%s_generic (const void* object)\n{\n return serializeio_count_%s_obj (object);\n}\n\n" ent-downcase ent-downcase)) (insert (format "static void\nserializeio_print_%s_generic (void* object, guint indent_spaces)\n{\n serializeio_print_%s_obj (object, indent_spaces);\n}\n\n" ent-downcase ent-downcase)) ) ;; The init entry (save-excursion (goto-char *source-init-marker*) (insert (format " serializeio_initialize_type (\"ST_%s\", ST_%s, &unserialize_%s_generic, &serialize_%s_generic, &serializeio_count_%s_generic, &serializeio_print_%s_generic);\n" ent-upcase ent-upcase ent-downcase ent-downcase ent-downcase ent-downcase)) ) ;; Count code (insert (format "/* %s Count\n */\n\n" ent-upcase)) (insert (format "guint\nserializeio_count_%s (%s) {\n" ent-downcase (entry-arglist nil entry))) (insert (format " guint size = sizeof (Serial%s);\n" ent-upcase)) (apply (function insert) (mapcar (function (lambda (x) (format " (void) %s;\n" x))) (entry-param-names "" entry nil))) (apply (function insert) (mapcar (function (lambda (x) (concat (format " ALIGN_8 (size);\n") (entry-count-field entry x (format "%s" (car x)) " " t)))) (sertype-fields-get entry))) (insert (format " ALIGN_8 (size);\n")) (insert (format " return size;\n")) (insert (format "}\n\n")) ;; Count Object code (insert (format "guint\nserializeio_count_%s_obj (Serial%s const* obj) {\n" ent-downcase ent-upcase)) (insert (format " return serializeio_count_%s (%s);\n" ent-downcase (entry-plist t nil "obj->" entry))) (insert (format "}\n\n")) ;; Print object code (insert (format "/* %s Print\n */\n\n" ent-upcase)) (insert (format "void\nserializeio_print_%s_obj (Serial%s* obj, guint indent_spaces) {\n" ent-downcase ent-upcase)) (insert (format " print_spaces (indent_spaces);\n")) (insert (format " g_print (\"[ST_%s]\\n\");\n" ent-upcase)) (apply (function insert) (mapcar (function (lambda (x) (entry-print-field entry x (format "obj->%s" (car x)) " " t))) (sertype-fields-get entry))) (insert (format "}\n\n")) ;; Print internal code ;; Serialize code (insert (format "/* %s Serialize\n */\n\n" ent-upcase)) (insert (format "gboolean\nserialize_%s_internal (SerialSink *sink%s)\n" ent-downcase (entry-arglist t entry))) (insert (format "{\n")) (apply (function insert) (mapcar (function (lambda (x) (entry-serialize-field entry x (format "%s" (car x)) " " t))) (sertype-fields-get entry))) (insert (format " return TRUE;\n")) (if (sertype-fields-get entry) (insert (format "bail:\n return FALSE;\n"))) (insert (format "}\n\n")) ;; Internal Serialize Object code (insert (format "gboolean\nserialize_%s_obj_internal (SerialSink *sink, Serial%s* obj)\n" ent-downcase ent-upcase)) (insert (format "{\n")) (insert (format " return serialize_%s_internal (sink%s);\n" ent-downcase (entry-plist t t "obj->" entry))) (insert (format "}\n\n")) ;; External Serialize code (insert (format "gboolean\nserialize_%s (SerialSink *sink%s)\n" ent-downcase (entry-arglist t entry))) (insert (format "{\n")) (insert (format " if (! (* sink->sink_type) (sink, ST_%s, serializeio_count_%s (%s), TRUE)) goto bail;\n" ent-upcase ent-downcase (entry-plist nil nil "" entry))) (insert (format " if (! serialize_%s_internal (sink%s)) goto bail;\n" ent-downcase (entry-plist nil t "" entry))) (insert (format " if (sink->sink_quantum && ! sink->sink_quantum (sink)) goto bail;\n")) (insert (format " return TRUE;\n")) (insert (format "bail:\n")) (insert (format " return FALSE;\n")) (insert (format "}\n\n")) ;; External serialize_obj (insert (format "gboolean\nserialize_%s_obj (SerialSink *sink, const Serial%s* obj) {\n\n" ent-downcase ent-upcase)) (insert (format " return serialize_%s (sink%s);\n" ent-downcase (entry-plist t t "obj->" entry))) (insert (format "}\n\n")) ;; Unserialize code (insert (format "/* %s Unserialize\n */\n\n" ent-upcase)) (insert (format "gboolean\nunserialize_%s_internal_noalloc (SerialSource *source, Serial%s* result)\n" ent-downcase ent-upcase)) (insert (format "{\n")) (apply (function insert) (mapcar (function (lambda (x) (entry-unserialize-field entry x (format "result->%s" (car x)) " "))) (sertype-fields-get entry))) (insert (format " return TRUE;\n")) (if (sertype-fields-get entry) (insert (format "bail:\n return FALSE;\n"))) (insert (format "}\n\n")) (insert (format "gboolean\nunserialize_%s_internal (SerialSource *source, Serial%s** result)\n" ent-downcase ent-upcase)) (insert (format "{\n")) (insert (format " Serial%s* unser;\n" ent-upcase)) (insert (format " (*result) = NULL;\n")) (insert (format " unser = serializeio_source_alloc (source, sizeof (Serial%s));\n" ent-upcase)) (insert (format " if (! unser) goto bail;\n")) (insert (format " if (! unserialize_%s_internal_noalloc (source, unser)) goto bail;\n" ent-downcase)) (insert (format " (*result) = unser;\n")) (insert (format " return TRUE;\n")) (insert (format "bail:\n")) (insert (format " return FALSE;\n")) (insert (format "}\n\n")) ;; External unserialize (insert (format "gboolean\nunserialize_%s (SerialSource *source, Serial%s** result)\n" ent-downcase ent-upcase)) (insert (format "{\n")) (insert (format " if ( (* source->source_type) (source, TRUE) != ST_%s) goto bail;\n" ent-upcase)) (insert (format " if (! unserialize_%s_internal (source, result)) goto bail;\n" ent-downcase)) (insert (format " return TRUE;\n")) (insert (format "bail:\n")) (insert (format " return FALSE;\n")) (insert (format "}\n\n")) ) ) (defun entry-typename-pairs (entry is-param) (let ((pairs nil) (fields (sertype-fields-get entry))) (while fields (let ((field (car fields))) (when (or (equal (cadr field) 'bytes) (and (consp (cadr field)) (equal (caadr field) 'array))) (setq pairs (cons (format "guint32 %s_len" (car field)) pairs)) ) (when (equal (cadr field) 'object) (setq pairs (cons (format "guint32 %s_type" (car field)) pairs)) ) (setq pairs (cons (field-decl field is-param) pairs)) ) (setq fields (cdr fields)) ) (nreverse pairs) ) ) (defun entry-param-names (prefix entry need_pbr) (let ((pairs nil) (fields (sertype-fields-get entry))) (while fields (let ((field (car fields))) (when (or (equal (cadr field) 'bytes) (and (consp (cadr field)) (equal (caadr field) 'array))) (setq pairs (cons (format "%s%s_len" prefix (car field)) pairs)) ) (when (equal (cadr field) 'object) (setq pairs (cons (format "%s%s_type" prefix (car field)) pairs)) ) (setq pairs (cons (format "%s%s%s" (if (and need_pbr (needs-ref field)) "&" "") prefix (car field)) pairs)) ) (setq fields (cdr fields)) ) (nreverse pairs) ) ) (defun field-ctype (field) (cond ((equal (cadr field) 'string) "const gchar*") ((equal (cadr field) 'uint) "guint32") ((equal (cadr field) 'uint32) "guint32") ((equal (cadr field) 'uint16) "guint16") ((equal (cadr field) 'uint8) "guint8") ((equal (cadr field) 'boolean) "gboolean") ((equal (cadr field) 'bytes) "const guint8*") ((equal (cadr field) 'object) "void*") ((member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)) (format "Serial%s" (cadr field))) ((equal (car (cadr field)) 'bytes) "const guint8*") ((member (car (cadr field)) '(array ptr)) (concat (field-ctype (cadr field)) "*")) (t (error "unrecognized field type: %s" (cadr field)))) ) (defun field-decl (field is-param) (if (and (consp (cadr field)) (equal (car (cadr field)) 'bytes)) (format "%sguint8 %s[%d]" (if is-param "const " "") (car field) (cadr (cadr field))) ;(message "foo %s %s" field (member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))) (format "%s %s" (cond ((member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)) (format "Serial%s%s" (cadr field) (if is-param " const*" ""))) ((equal (cadr field) 'string) "const gchar*") ((equal (cadr field) 'uint) "guint32") ((equal (cadr field) 'uint32) "guint32") ((equal (cadr field) 'uint16) "guint16") ((equal (cadr field) 'uint8) "guint8") ((equal (cadr field) 'boolean) "gboolean") ((equal (cadr field) 'bytes) "const guint8*") ((equal (cadr field) 'object) "void*") ((member (car (cadr field)) '(array ptr)) (concat (field-ctype (cadr field)) (if is-param " const*" "*"))) (t (error "unrecognized field type: %s" (cadr field)))) (car field))) ) (defun entry-arglist (need_first entry) (concat (if (and need_first (sertype-fields-get entry)) ", " "") (format-comlist (function (lambda (x) x)) (entry-typename-pairs entry t)))) (defun needs-ref (field) (member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)) ) (defun entry-plist (need_pbr need_first prefix entry) (concat (if (and need_first (sertype-fields-get entry)) ", " "") (format-comlist (function (lambda (x) (format "%s" x))) (entry-param-names prefix entry need_pbr)))) (defun entry-unserialize-field (entry field name prefix) (cond ((equal (cadr field) 'uint) (format "%sif (! (* source->next_uint) (source, &%s)) goto bail;\n" prefix name)) ((equal (cadr field) 'uint32) (format "%sif (! (* source->next_uint32) (source, &%s)) goto bail;\n" prefix name)) ((equal (cadr field) 'uint16) (format "%sif (! (* source->next_uint16) (source, &%s)) goto bail;\n" prefix name)) ((equal (cadr field) 'uint8) (format "%sif (! (* source->next_uint8) (source, &%s)) goto bail;\n" prefix name)) ((equal (cadr field) 'boolean) (format "%sif (! (* source->next_bool) (source, &%s)) goto bail;\n" prefix name)) ((equal (cadr field) 'string) (format "%sif (! (* source->next_string) (source, &%s)) goto bail;\n" prefix name)) ((equal (cadr field) 'bytes) (format "%sif (! (* source->next_bytes) (source, &%s, &%s_len)) goto bail;\n" prefix name name)) ((equal (cadr field) 'object) (format "%sif (! serializeio_unserialize_generic_internal (source, &%s_type, &%s, FALSE)) goto bail;\n" prefix name name)) ((member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)) (format "%sif (! unserialize_%s_internal_noalloc (source, &%s)) goto bail;\n" prefix (downcase-string (cadr field)) name)) ((and (equal (car (cadr field)) 'ptr) (member (cadr (cadr field)) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))) (format "%sif (! unserialize_%s_internal (source, &%s)) goto bail;\n" prefix (downcase-string (cadr (cadr field))) name)) ((equal (car (cadr field)) 'bytes) (format "%sif (! (* source->next_bytes_known) (source, %s, %d)) goto bail;\n" prefix name (cadr (cadr field)))) ((equal (car (cadr field)) 'array) (format "%s{ %s guint32 i; %s if (! (* source->next_uint) (source, &%s_len)) goto bail; %s if (! (%s = serializeio_source_alloc (source, sizeof (%s) * %s_len))) goto bail; %s for (i = 0; i < %s_len; i += 1) %s { %s%s } %s} " prefix prefix prefix name prefix name (field-ctype (cadr field)) name prefix name prefix prefix (entry-unserialize-field entry (cadr field) (concat "(" name "[i])") (concat prefix " ")) prefix )) (t (error "unrecognized field type: %s" (cadr field))))) (defun entry-serialize-field (entry field name prefix is-param) (cond ((equal (cadr field) 'uint) (format "%sif (! (* sink->next_uint) (sink, %s)) goto bail;\n" prefix name)) ((equal (cadr field) 'uint16) (format "%sif (! (* sink->next_uint16) (sink, %s)) goto bail;\n" prefix name)) ((equal (cadr field) 'uint8) (format "%sif (! (* sink->next_uint8) (sink, %s)) goto bail;\n" prefix name)) ((equal (cadr field) 'uint32) (format "%sif (! (* sink->next_uint32) (sink, %s)) goto bail;\n" prefix name)) ((equal (cadr field) 'boolean) (format "%sif (! (* sink->next_bool) (sink, %s)) goto bail;\n" prefix name)) ((equal (cadr field) 'string) (format "%sif (! (* sink->next_string) (sink, %s)) goto bail;\n" prefix name)) ((equal (cadr field) 'bytes) (format "%sif (! (* sink->next_bytes) (sink, %s, %s_len)) goto bail;\n" prefix name name)) ((equal (cadr field) 'object) (format "%sif (! serializeio_serialize_generic_internal (sink, %s_type, %s, FALSE)) goto bail;\n" prefix name name)) ((member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)) (format "%sif (! serialize_%s_internal (sink%s)) goto bail;\n" prefix (downcase-string (cadr field)) (entry-plist t t (concat name (if is-param "->" ".")) (obj-name-eq (cadr field) *all-sertype-defs*)))) ((and (equal (car (cadr field)) 'ptr) (member (cadr (cadr field)) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))) (format "%sif (! serialize_%s_internal (sink%s)) goto bail;\n" prefix (downcase-string (cadr (cadr field))) (entry-plist t t (concat name "->") (obj-name-eq (cadr (cadr field)) *all-sertype-defs*)))) ((equal (car (cadr field)) 'bytes) (format "%sif (! (* sink->next_bytes_known) (sink, %s, %d)) goto bail;\n" prefix name (cadr (cadr field)))) ((equal (car (cadr field)) 'array) (format "%s{ %s guint32 i; %s if (! (* sink->next_uint) (sink, %s_len)) goto bail; %s for (i = 0; i < %s_len; i += 1) %s { %s%s } %s} " prefix prefix prefix name prefix name prefix prefix (entry-serialize-field entry (cadr field) (array-index name (cadr field)) (concat prefix " ") nil) prefix )) (t (error "unrecognized field type: %s" (cadr field))))) (defun array-index (name field) ;(concat "(" (if (needs-ref field) "&" "") name "[i])") (concat "(" name "[i])") ) (defun entry-count-field (entry field name prefix is-param) (cond ((equal (cadr field) 'uint) ;(format "%ssize += sizeof (guint32);\n" prefix) "" ) ((equal (cadr field) 'uint32) ;(format "%ssize += sizeof (guint32);\n" prefix) "" ) ((equal (cadr field) 'uint16) ;(format "%ssize += sizeof (guint16);\n" prefix) "" ) ((equal (cadr field) 'uint8) ;(format "%ssize += sizeof (guint8);\n" prefix) "" ) ((equal (cadr field) 'boolean) ;(format "%ssize += sizeof (gboolean);\n" prefix) "" ) ((equal (cadr field) 'string) (format "%ssize += strlen (%s) + 1;\n" prefix name) ) ((equal (cadr field) 'bytes) (format "%ssize += %s_len;\n" prefix name) ) ((equal (cadr field) 'object) (format "%ssize += serializeio_generic_count (%s_type, %s);\n" prefix name name) ) ((member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)) (format "%ssize += serializeio_count_%s_obj (%s%s) - sizeof (Serial%s);\n" prefix (downcase-string (cadr field)) (if is-param "" "& ") name (cadr field) ) ) ((and (equal (car (cadr field)) 'ptr) (member (cadr (cadr field)) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))) (format "%ssize += serializeio_count_%s_obj (%s);\n" prefix (downcase-string (cadr (cadr field))) name) ) ((equal (car (cadr field)) 'bytes) ;(format "%ssize += 0;\n" prefix (cadr (cadr field))) "" ) ((equal (car (cadr field)) 'array) (format "%s{ %s guint32 i; %s for (i = 0; i < %s_len; i += 1) %s { %s%s } %s} " prefix prefix prefix name prefix prefix (entry-count-array-field entry (cadr field) (array-index name (cadr field)) (concat prefix " ") nil) prefix )) (t (error "unrecognized field type: %s" (cadr field))))) (defun entry-count-array-field (entry field name prefix is-param) (cond ((equal (cadr field) 'uint) (format "%ssize += sizeof (guint32);\n" prefix) ) ((equal (cadr field) 'uint32) (format "%ssize += sizeof (guint32);\n" prefix) ) ((equal (cadr field) 'uint16) (format "%ssize += sizeof (guint16);\n" prefix) ) ((equal (cadr field) 'uint8) (format "%ssize += sizeof (guint8);\n" prefix) ) ((equal (cadr field) 'boolean) (format "%ssize += sizeof (gboolean);\n" prefix) ) ((equal (cadr field) 'string) (format "%ssize += strlen (%s) + 1 + sizeof (void*);\n" prefix name) ) ((equal (cadr field) 'bytes) (error "can't do that: bytes1") ) ((equal (cadr field) 'object) (error "can't do that: object") ) ((member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)) (format "%ssize += serializeio_count_%s_obj (%s%s);\n" prefix (downcase-string (cadr field)) (if is-param "" "& ") name ) ) ((and (equal (car (cadr field)) 'ptr) (member (cadr (cadr field)) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))) (format "%ssize += serializeio_count_%s_obj (%s) + sizeof (void*);\n" prefix (downcase-string (cadr (cadr field))) name) ) ((equal (car (cadr field)) 'bytes) (error "can't do that: bytes2") ) ((equal (car (cadr field)) 'array) (error "can't do that: array") ) (t (error "unrecognized field type: %s" (cadr field))))) (defun entry-print-field (entry field name prefix is-param) (concat (format "%sprint_spaces (indent_spaces);\n" prefix) (if is-param (format "%sg_print (\"%s = \");\n" prefix (car field)) "") (cond ((equal (cadr field) 'uint) (format "%sg_print (\"%%d\\n\", %s);\n" prefix name)) ((equal (cadr field) 'uint32) (format "%sg_print (\"%%d\\n\", %s);\n" prefix name)) ((equal (cadr field) 'uint16) (format "%sg_print (\"%%d\\n\", %s);\n" prefix name)) ((equal (cadr field) 'uint8) (format "%sg_print (\"%%d\\n\", %s);\n" prefix name)) ((equal (cadr field) 'boolean) (format "%sg_print (\"%%s\\n\", %s ? \"true\" : \"false\");\n" prefix name)) ((equal (cadr field) 'string) (format "%sg_print (\"%%s\\n\", %s);\n" prefix name)) ((equal (cadr field) 'bytes) (format "%sserializeio_print_bytes (%s, %s_len);\n" prefix name name)) ((equal (cadr field) 'object) (concat (if is-param (format "%sg_print (\"{\\n\");\n" prefix) "") (format "%sserializeio_generic_print (%s_type, %s, indent_spaces + 2);\n" prefix name name) (format "%sprint_spaces (indent_spaces);\n;\n" prefix) (if is-param (format "%sg_print (\"}\\n\");\n" prefix) "") ) ) ((member (cadr field) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)) (concat (if is-param (format "%sg_print (\"{\\n\");\n" prefix) "") (format "%sserializeio_print_%s_obj (& %s, indent_spaces + 2);\n" prefix (downcase-string (cadr field)) name) (format "%sprint_spaces (indent_spaces);\n;\n" prefix) (if is-param (format "%sg_print (\"}\\n\");\n" prefix) "") ) ) ((and (equal (car (cadr field)) 'ptr) (member (cadr (cadr field)) (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))) (concat (if is-param (format "%sg_print (\"{\\n\");\n" prefix) "") (format "%sserializeio_print_%s_obj (%s, indent_spaces + 2);\n" prefix (downcase-string (cadr (cadr field))) name) (format "%sprint_spaces (indent_spaces);\n;\n" prefix) (if is-param (format "%sg_print (\"}\\n\");\n" prefix) "") ) ) ((equal (car (cadr field)) 'bytes) (format "%sserializeio_print_bytes (%s, %d);\n" prefix name (cadr (cadr field)))) ((equal (car (cadr field)) 'array) (concat (if is-param (format "%sg_print (\"{\\n\");\n" prefix) "") (format "%s{ %s guint32 i; %s for (i = 0; i < %s_len; i += 1) %s { %s print_spaces (indent_spaces); %s g_print (\"%%d:\\n\", i); %s%s } %s} " prefix prefix prefix name prefix prefix prefix prefix (entry-print-field entry (cadr field) (array-index name (cadr field)) (concat prefix " ") nil) prefix ) (if is-param (format "%sg_print (\"}\\n\");\n" prefix) ""))) (t (error "unrecognized field type: %s" (cadr field))))) ) (defconst *event-id* 0) (defconst *event-types* nil) (defun generate-events () (let ((events *event-defs*)) (while events (let* ((event (car events)) (uargs (event-uargs-get event)) (sargs (event-sargs-get event)) (type-prefix (intern (apply (function concat) (append (mapcar (function (lambda (x) (capitalize1 (cadr x)))) uargs) (mapcar (function (lambda (x) (capitalize1 x))) sargs))))) (capprefix (capitalize1 *output-prefix*))) (if (and (not uargs) (not sargs)) (setq type-prefix "Void")) (when (not (member type-prefix *event-types*)) (setq *event-types* (cons type-prefix *event-types*)) (output-header-file "_edsio") (save-excursion (goto-char *header-typedef-marker*) (insert (format "/* %s%sEventCode.\n */\n\n" capprefix type-prefix)) (insert (format "typedef struct _%s%sEventCode %s%sEventCode;\n" capprefix type-prefix capprefix type-prefix)) (insert (format "struct _%s%sEventCode { gint code; };\n\n" capprefix type-prefix)) (insert (format "typedef struct _%s%sEvent %s%sEvent;\n" capprefix type-prefix capprefix type-prefix)) (insert (format "struct _%s%sEvent { gint code; const char* srcfile; guint srcline;%s%s };\n\n" capprefix type-prefix (event-struct-entries event) (event-struct-sys-entries event))) ) (insert (format "void %s_generate_%s_event_internal (%s%sEventCode code, const char* srcfile, gint srcline%s);\n" *output-prefix* (downcase-string type-prefix) capprefix type-prefix (event-uargs-plist uargs t) )) (insert (format "#define %s_generate_%s_event(ecode%s) %s_generate_%s_event_internal((ecode),__FILE__,__LINE__%s)\n\n" *output-prefix* (downcase-string type-prefix) (event-uargs-alist uargs t) *output-prefix* (downcase-string type-prefix) (event-uargs-mlist uargs t))) (output-source-file "_edsio") (insert (format "void\n%s_generate_%s_event_internal (%s%sEventCode _code, const char* _srcfile, gint _srcline%s)\n" *output-prefix* (downcase-string type-prefix) capprefix type-prefix (event-uargs-plist uargs t) )) (insert (format "{\n")) (insert (format " %s%sEvent *_e = g_new0 (%s%sEvent, 1);\n" capprefix type-prefix capprefix type-prefix)) (insert (format " _e->code = _code.code;\n _e->srcline = _srcline;\n _e->srcfile = _srcfile;\n")) (insert (event-uargs-copy "_e" event)) (insert (event-sargs-copy "_e" event)) (insert (format " eventdelivery_event_deliver ((GenericEvent*) _e);\n")) (insert (format "}\n\n")) ;; Field to string def (unless (equal type-prefix "Void") (save-excursion (goto-char *source-top-marker*) (insert (format "static const char* %s_%s_event_field_to_string (GenericEvent* ev, gint field);\n" capprefix type-prefix)) ) (insert (format "const char*\n%s_%s_event_field_to_string (GenericEvent* ev, gint field)\n" capprefix type-prefix)) (insert (format "{\n")) (unless (equal type-prefix (intern "Ssl")) (insert (format " %s%sEvent* it = (%s%sEvent*) ev;\n" capprefix type-prefix capprefix type-prefix))) (insert (format " switch (field)\n")) (insert (format " {\n")) (let ((uargs (event-uargs-get event)) (i 0)) (while uargs (let ((uarg (car uargs))) (insert (format " case %d: return eventdelivery_%s_to_string (it->%s);\n" i (cadr uarg) (car uarg))) ) (setq i (+ i 1)) (setq uargs (cdr uargs)) ) ) (if (< 1 (length (event-sargs-get event))) (error "unhandled case, too many sargs")) (when (event-sargs-get event) (let ((sarg (car (event-sargs-get event)))) (insert (format " case %d: " (length (event-uargs-get event)))) (if (not (member sarg '(ssl errno))) (error "what type of sarg is %s" sarg)) (if (eq sarg 'errno) (insert (format "return g_strdup (g_strerror (it->ev_errno));\n"))) (if (eq sarg 'ssl) (insert (format "return eventdelivery_ssl_errors_to_string ();\n"))) ) ) (insert (format " default: abort ();\n")) (insert (format " }\n")) (insert (format "}\n\n")) ) ) (output-header-file "_edsio") (insert (format "extern const %s%sEventCode EC_%s%s;\n" capprefix type-prefix capprefix (event-name-get event))) (insert (format "#define EC_%s%sValue ((%d<%s = %s;\n" name (car x) (car x)))) (event-uargs-get event))) ) (defun event-sargs-copy (name event) (if (member 'errno (event-sargs-get event)) (format " %s->ev_errno = errno;\n" name) "") ) (defun event-type-to-ctype (etype) (let ((it (obj-name-eq etype *all-etype-defs*))) (if (not it) (message "no ctype for %s" etype)) (etype-ctype-get it) ) ) (defun event-uargs-plist(uargs need_first) (concat (if (and need_first uargs) ", " "") (format-comlist (function (lambda (x) (format "%s %s" (event-type-to-ctype (cadr x)) (car x)))) uargs)) ) (defun event-uargs-alist(uargs need_first) (concat (if (and need_first uargs) ", " "") (format-comlist (function (lambda (x) (format "%s" (car x)))) uargs)) ) (defun event-uargs-mlist(uargs need_first) (concat (if (and need_first uargs) ", " "") (format-comlist (function (lambda (x) (format "(%s)" (car x)))) uargs)) ) (defun fixup-oneline (event oneline) (with-temp-buffer (insert oneline) (goto-char (point-min)) (while (re-search-forward "${\\(\\w+\\)}" nil t) (let* ((it (intern (downcase-string (match-string 1)))) (uargs (event-uargs-get event)) (i 0) (repl nil)) (while uargs (if (eq (car (car uargs)) it) (setq repl (format "${%d}" i))) (setq uargs (cdr uargs)) (setq i (+ i 1)) ) (when (eq it 'strerror) (if repl (error "No wildcards named STRERROR")) (setq repl (format "${%d}" i)) ) (when (eq it 'ssl) (if repl (error "No wildcards named SSL")) (setq repl (format "${%d}" i)) ) (if (not repl) (error "Illegal wildcard %s in %s" it oneline)) (replace-match repl nil nil) ) ) (buffer-string))) ;; Properties (defun generate-properties () (let ((cap-prefix (capitalize1 *output-prefix*)) (unique-types nil)) (output-header-file "_edsio") (insert (format "/* Property definitions */\n\n")) ;; Types (output-source-file "_edsio") (mapc (function (lambda (pht) (let ((type (prophosttype-type-get pht))) (unless (member type unique-types) (setq unique-types (cons type unique-types)) (save-excursion (goto-char *source-init-marker*) ;(message "%s -> %s %s" type (type-free-func type) (member type (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*))) (insert (format " edsio_initialize_property_type (\"%s\", %s, %s, %s, %s, %s);\n" type (type-free-func type) (type-gs-func type "getter") (type-gs-func type "setter") (type-serialize-func type) (type-unserialize-func type))) ) ) ) ) ) *prophosttype-defs* ) ;; Host reg (mapc (function (lambda (prophost) (save-excursion (goto-char *source-init-marker*) (insert (format " edsio_initialize_host_type (\"%s\", %s, %s, %s, %s, %s);\n" (prophost-name-get prophost) (format "(PropertyTableFunc) & edsio_%s_property_table" (downcase-string (prophost-name-get prophost))) (prophost-persist prophost "source") (prophost-persist prophost "sink") (prophost-persist prophost "isset") (prophost-persist prophost "unset") )) ) ) ) *prophost-defs*) ;; Compute each distinct (host type) x (prop type) (mapc (function (lambda (prophost) (mapc (function (lambda (prophosttype) (when (equal (prophosttype-host-get prophosttype) (prophost-name-get prophost)) (when (not (member (prophosttype-type-get prophosttype) (prophost-proptypes-get prophost))) (prophost-proptypes-set prophost (cons (prophosttype-type-get prophosttype) (prophost-proptypes-get prophost))) ) ))) *prophosttype-defs* ) ;; Output the get/set functions for each property type (mapc (function (lambda (type) (let ((it (property-code-typename type prophost))) ;; Header (output-header-file "_edsio") (insert (format "/* Property get/set for %s/%s\n */\n\n" (prophost-name-get prophost) type)) (insert (format "typedef struct _%s %s;\n" it it)) (insert (format "struct _%s { guint32 code; };\n\n" it)) (insert (format "gboolean edsio_new_%s_%s_property (const char* name, guint32 flags, %s* prop);\n" (downcase-string (prophost-name-get prophost)) (type-canon-name type) it )) (insert (format "gboolean %s_get_%s (%s obj, %s prop%s);\n" (downcase-string (prophost-name-get prophost)) (type-canon-name type) (prophost-ctype-get prophost) it (prop-type-to-get-fps type))) (insert (format "gboolean %s_set_%s (%s obj, %s prop%s);\n" (downcase-string (prophost-name-get prophost)) (type-canon-name type) (prophost-ctype-get prophost) it (prop-type-to-set-fps type))) (insert (format "gboolean %s_unset_%s (%s obj, %s prop);\n" (downcase-string (prophost-name-get prophost)) (type-canon-name type) (prophost-ctype-get prophost) it)) (insert (format "gboolean %s_isset_%s (%s obj, %s prop);\n\n" (downcase-string (prophost-name-get prophost)) (type-canon-name type) (prophost-ctype-get prophost) it)) ;; Source (output-source-file "_edsio") (insert (format "gboolean edsio_new_%s_%s_property (const char* name, guint32 flags, %s* prop)\n{\n" (downcase-string (prophost-name-get prophost)) (type-canon-name type) it )) (insert (format " return edsio_new_property (name, \"%s\", \"%s\", flags, (EdsioGenericProperty*) prop);\n" (prophost-name-get prophost) type)) (insert (format "}\n\n")) (insert (format "gboolean\n%s_get_%s (%s obj, %s prop%s)\n{\n" (downcase-string (prophost-name-get prophost)) (type-canon-name type) (prophost-ctype-get prophost) it (prop-type-to-get-fps type))) (insert (format " EdsioProperty* ep;\n")) (insert (format " PropGSFunc getter;\n")) (insert (format " g_return_val_if_fail (obj, FALSE);\n")) (insert (format " getter = edsio_property_getter (\"%s\", \"%s\", prop.code, & ep);\n" (prophost-name-get prophost) type )) (insert (format " return (* getter) (obj, ep%s);\n" (prop-type-to-args type) )) (insert (format "}\n\n")) (insert (format "gboolean\n%s_set_%s (%s obj, %s prop%s)\n{\n" (downcase-string (prophost-name-get prophost)) (type-canon-name type) (prophost-ctype-get prophost) it (prop-type-to-set-fps type))) (insert (format " EdsioProperty* ep;\n")) (insert (format " PropGSFunc setter;\n")) (insert (format " g_return_val_if_fail (obj, FALSE);\n")) (insert (format " setter = edsio_property_setter (\"%s\", \"%s\", prop.code, & ep);\n" (prophost-name-get prophost) type )) (insert (format " return (* setter) (obj, ep%s);\n" (prop-type-to-args type) )) (insert (format "}\n\n")) (insert (format "gboolean\n%s_unset_%s (%s obj, %s prop)\n{\n" (downcase-string (prophost-name-get prophost)) (type-canon-name type) (prophost-ctype-get prophost) it)) (insert (format " g_return_val_if_fail (obj, FALSE);\n")) (insert (format " return edsio_property_unset (\"%s\", \"%s\", prop.code, obj);\n" (prophost-name-get prophost) type )) (insert (format "}\n\n")) (insert (format "gboolean\n%s_isset_%s (%s obj, %s prop)\n{\n" (downcase-string (prophost-name-get prophost)) (type-canon-name type) (prophost-ctype-get prophost) it)) (insert (format " g_return_val_if_fail (obj, FALSE);\n")) (insert (format " return edsio_property_isset (\"%s\", \"%s\", prop.code, obj);\n" (prophost-name-get prophost) type )) (insert (format "}\n\n")) ) ) ) (prophost-proptypes-get prophost) ) ) ) *all-prophost-defs* ) ) ) (defun property-code-typename(type prophost) (format "%s%s%sProperty" (capitalize1 *output-prefix*) (prophost-name-get prophost) (capitalize1 type)) ) (defun prop-typename-ctypes (type) (cond ((equal type 'string) (list (list 'arg "const gchar*"))) ((equal type 'uint) (list (list 'arg "guint32"))) ((equal type 'uint32) (list (list 'arg "guint32"))) ((equal type 'uint16) (list (list 'arg "guint16"))) ((equal type 'uint8) (list (list 'arg "guint8"))) ((equal type 'boolean) (list (list 'arg "gboolean"))) ((equal type 'bytes) (list (list 'arg "const guint8*") (list 'arg_len "guint32"))) ((equal type 'object) (list (list 'arg "void*") (list 'arg_type "guint32"))) ((member type (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)) (list (list 'arg (format "Serial%s*" type)))) ((equal (car type) 'bytes) (list (list 'arg "const guint8*"))) ((equal (car type) 'array) (list (list 'arg (format "%s*" (cadr (car (prop-typename-ctypes (cadr type)))))) (list 'arg_len "guint32"))) ((equal (car type) 'ptr) (list (list 'arg (format "%s*" (cadr (car (prop-typename-ctypes (cadr type)))))))) (t (error "unrecognized field type: %s" type))) ) (defun prop-type-to-get-fps (type) (concat ", " (format-comlist (function (lambda (pair) (format "%s* %s" (cadr pair) (car pair)) ) ) (prop-typename-ctypes type)) ) ) (defun prop-type-to-set-fps (type) (concat ", " (format-comlist (function (lambda (pair) (format "%s %s" (cadr pair) (car pair)) ) ) (prop-typename-ctypes type)) ) ) (defun prop-type-to-args (type) (concat ", " (format-comlist (function (lambda (pair) (format "%s" (car pair)) ) ) (prop-typename-ctypes type)) ) ) (defun type-canon-name (type) ; @@@ does not work for (array ...), etc (downcase-string type)) (defun type-serialize-func (type) (format "(PropSerialize) serialize_%s_obj" (downcase-string type)) ) (defun type-unserialize-func (type) (format "(PropUnserialize) unserialize_%s" (downcase-string type)) ) (defun type-gs-func (type name) (concat "(PropGSFunc) " (if (member type (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)) (format "& edsio_property_vptr_%s" name) (format "& edsio_property_%s_%s" type name)))) (defun type-free-func (type) (if (member type (mapcar (lambda (x) (sertype-name-get x)) *all-sertype-defs*)) (format "& edsio_property_vptr_free") (format "& edsio_property_%s_free" type))) (defun prophost-persist (prophost func) (if (prophost-persist-get prophost) (format "(Persist%sFunc) & %s_persist_%s_%s" (capitalize1 func) *output-prefix* (downcase-string (prophost-name-get prophost)) func) "NULL")) xdelta-1.2.1/libedsio/edsio.h000077500000000000000000000452671525650667300161020ustar00rootroot00000000000000/* -*-Mode: C;-*- * $Id: edsio.h 1.2 Sun, 28 Jan 2007 12:21:11 -0800 jmacd $ * * Copyright (C) 1998, 1999, Josh MacDonald. * All Rights Reserved. * * Author: Josh MacDonald */ #ifndef _EDSIO_H_ #define _EDSIO_H_ #ifdef __cplusplus extern "C" { #endif #ifdef HAVE_CONFIG_H #include #endif #include #include #include typedef struct _SerialSource SerialSource; typedef struct _SerialSink SerialSink; typedef gint32 SerialType; typedef struct _HandleFuncTable HandleFuncTable; typedef struct _PropTest PropTest; typedef struct _FileHandle FileHandle; typedef struct _AllocList AllocList; struct _FileHandle { const HandleFuncTable* table; /* This is an opaque type, feel free to define your own, just make * sure that the first field of yours is one of these, and that you * supply a table. */ }; #define EDSIO_LIBRARY_OFFSET_BITS 8 #define EDSIO_LIBRARY_OFFSET_MASK 0xff #include "edsio_edsio.h" #define ST_Error -1 #define ST_IncorrectType -2 #define ST_NotFound -3 #define ALIGN_8(v) if (((v) % 8) != 0) { (v) += 8; (v) &= ~7; } /* This serves as a virtual table for I/O to the FileHandle */ struct _HandleFuncTable { gssize (* table_handle_length) (FileHandle *fh); gssize (* table_handle_pages) (FileHandle *fh); gssize (* table_handle_pagesize) (FileHandle *fh); gssize (* table_handle_map_page) (FileHandle *fh, guint pgno, const guint8** mem); gboolean (* table_handle_unmap_page) (FileHandle *fh, guint pgno, const guint8** mem); const guint8* (* table_handle_checksum_md5) (FileHandle *fh); gboolean (* table_handle_close) (FileHandle *fh, gint flags); gboolean (* table_handle_write) (FileHandle *fh, const guint8 *buf, gsize nbyte); gboolean (* table_handle_copy) (FileHandle *from, FileHandle *to, guint off, guint len); gboolean (* table_handle_getui) (FileHandle *fh, guint32* i); gboolean (* table_handle_putui) (FileHandle *fh, guint32 i); gssize (* table_handle_read) (FileHandle *fh, guint8 *buf, gsize nbyte); const gchar* (* table_handle_name) (FileHandle *fh); /* user must free */ }; struct _AllocList { AllocList *next; void *ptr; }; struct _SerialSource { /* Internal variables: don't touch. */ AllocList *alloc_list; /* These are setup by init. */ SerialType (* source_type) (SerialSource* source, gboolean set_allocation); gboolean (* source_close) (SerialSource* source); gboolean (* source_read) (SerialSource* source, guint8 *ptr, guint32 len); void (* source_free) (SerialSource* source); /* These may be NULL */ void* (* salloc_func) (SerialSource* source, guint32 len); void (* sfree_func) (SerialSource* source, void* ptr); /* Public functions, defaulted, but may be over-ridden * before calls to unserialize. */ gboolean (* next_bytes_known) (SerialSource* source, guint8 *ptr, guint32 len); gboolean (* next_bytes) (SerialSource* source, const guint8 **ptr, guint32 *len); gboolean (* next_uint) (SerialSource* source, guint32 *ptr); gboolean (* next_uint32) (SerialSource* source, guint32 *ptr); gboolean (* next_uint16) (SerialSource* source, guint16 *ptr); gboolean (* next_uint8) (SerialSource* source, guint8 *ptr); gboolean (* next_bool) (SerialSource* source, gboolean *ptr); gboolean (* next_string) (SerialSource* source, const char **ptr); }; struct _SerialSink { /* These are setup by init. */ gboolean (* sink_type) (SerialSink* sink, SerialType type, guint32 mem_size, gboolean set_allocation); gboolean (* sink_close) (SerialSink* sink); gboolean (* sink_write) (SerialSink* sink, const guint8 *ptr, guint32 len); void (* sink_free) (SerialSink* sink); /* This may be null, called after each object is serialized. */ gboolean (* sink_quantum) (SerialSink* sink); /* Public functions, defaulted, but may be over-ridden * before calls to serialize. */ gboolean (* next_bytes_known) (SerialSink* sink, const guint8 *ptr, guint32 len); gboolean (* next_bytes) (SerialSink* sink, const guint8 *ptr, guint32 len); gboolean (* next_uint) (SerialSink* sink, guint32 ptr); gboolean (* next_uint32) (SerialSink* sink, guint32 ptr); gboolean (* next_uint16) (SerialSink* sink, guint16 ptr); gboolean (* next_uint8) (SerialSink* sink, guint8 ptr); gboolean (* next_bool) (SerialSink* sink, gboolean ptr); gboolean (* next_string) (SerialSink* sink, const char *ptr); }; typedef gboolean (* SerializeioUnserializeFunc) (SerialSource* source, void** object); typedef gboolean (* SerializeioSerializeFunc) (SerialSink* sink, void* object); typedef guint (* SerializeioCountFunc) (const void* object); typedef void (* SerializeioPrintFunc) (void* object, guint indent_spaces); void serializeio_initialize_type (const char* name, guint32 val, SerializeioUnserializeFunc unserialize_func, SerializeioSerializeFunc serialize_func, SerializeioCountFunc count_func, SerializeioPrintFunc print_func); const char* serializeio_generic_type_to_string (SerialType type); void serializeio_generic_print (SerialType type, void* object, guint indent_spaces); gboolean serializeio_serialize_generic (SerialSink *sink, SerialType object_type, void *object); gboolean serializeio_serialize_generic_internal (SerialSink *sink, SerialType object_type, void *object, gboolean set_allocation); guint serializeio_generic_count (SerialType object_type, void *object); gboolean serializeio_unserialize_generic (SerialSource *source, SerialType *object_type, void **object); gboolean serializeio_unserialize_generic_internal (SerialSource *source, SerialType *object_type, void **object, gboolean set_allocation); gboolean serializeio_unserialize_generic_acceptable (SerialSource* source, guint32 acceptable, SerialType *object_type, void **object); void serializeio_sink_init (SerialSink* sink, gboolean (* sink_type) (SerialSink* sink, SerialType type, guint32 mem_size, gboolean set_allocation), gboolean (* sink_close) (SerialSink* sink), gboolean (* sink_write) (SerialSink* sink, const guint8 *ptr, guint32 len), void (* sink_free) (SerialSink* sink), gboolean (* sink_quantum) (SerialSink* sink)); void serializeio_source_init (SerialSource* source, SerialType (* source_type) (SerialSource* source, gboolean set_allocation), gboolean (* source_close) (SerialSource* source), gboolean (* source_read) (SerialSource* source, guint8 *ptr, guint32 len), void (* source_free) (SerialSource* source), void* (* salloc_func) (SerialSource* source, guint32 len), void (* sfree_func) (SerialSource* source, void* ptr)); /* This function is internal, don't use. */ void* serializeio_source_alloc (SerialSource* source, guint32 len); SerialSink* serializeio_gzip_sink (SerialSink* sink); SerialSource* serializeio_gzip_source (SerialSource* source); SerialSink* serializeio_checksum_sink (SerialSink* sink); SerialSource* serializeio_checksum_source (SerialSource* source); SerialSink* serializeio_base64_sink (SerialSink* sink); SerialSource* serializeio_base64_source (SerialSource* source); SerialSource* handle_source (FileHandle *fh); SerialSink* handle_sink (FileHandle *fh, gpointer data1, gpointer data2, gpointer data3, gboolean (* cont_onclose) (gpointer data1, gpointer data2, gpointer data3)); gboolean unserialize_uint (SerialSource *source, guint32** x); gboolean serialize_uint_obj (SerialSink *sink, guint32* x); gboolean unserialize_string (SerialSource *source, const char** x); gboolean serialize_string_obj (SerialSink *sink, const char* x); /* These are a bit odd, and edsio_property_bytes_{g,s}etter account for it. * Try not to use yourself. */ gboolean unserialize_bytes (SerialSource *source, SerialEdsioBytes** x); gboolean serialize_bytes_obj (SerialSink *sink, SerialEdsioBytes *x); /* Event delivery */ enum _EventLevel { EL_Information = 1<<0, EL_Warning = 1<<5, EL_Error = 1<<10, EL_InternalError = 1<<15, EL_FatalError = 1<<20 }; typedef enum _EventLevel EventLevel; enum _EventFlags { EF_None = 1<<0, EF_OpenSSL = 1<<1 }; typedef enum _EventFlags EventFlags; const char* eventdelivery_int_to_string (int x); const char* eventdelivery_string_to_string (const char* x); const char* eventdelivery_source_to_string (SerialSource* x); const char* eventdelivery_sink_to_string (SerialSink* x); const char* eventdelivery_handle_to_string (FileHandle* x); void serializeio_print_bytes (const guint8* buf, guint len); /* Event delivery privates */ typedef struct _GenericEventDef GenericEventDef; typedef struct _GenericEvent GenericEvent; struct _GenericEvent { gint code; const char* srcfile; guint srcline; }; GenericEventDef* eventdelivery_event_lookup (gint code); void eventdelivery_event_deliver (GenericEvent* e); typedef gboolean (* ErrorDeliveryFunc) (GenericEvent* ev, GenericEventDef* def, const char* message); void eventdelivery_event_watch_all (ErrorDeliveryFunc func); void eventdelivery_initialize_event_def (gint code, gint level, gint flags, const char* name, const char* oneline, const char * (* field_to_string) (GenericEvent* ev, gint field)); const char* eventdelivery_ssl_errors_to_string (void); struct _GenericEventDef { gint code; gint level; gint flags; const char *name; const char *oneline; const char * (* field_to_string) (GenericEvent* ev, gint field); }; /* MD5.H - header file for MD5C.C */ /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ /* MD5 context. */ typedef struct { guint32 state[4]; /* state (ABCD) */ guint32 count[2]; /* number of bits, modulo 2^64 (lsb first) */ guint8 buffer[64]; /* input buffer */ } EdsioMD5Ctx; void edsio_md5_init (EdsioMD5Ctx *); void edsio_md5_update (EdsioMD5Ctx *, const guint8 *, guint); void edsio_md5_final (guint8*, EdsioMD5Ctx *); gint edsio_md5_equal (gconstpointer v, gconstpointer v2); guint edsio_md5_hash (gconstpointer v); void edsio_md5_to_string (const guint8* md5, char buf[33]); gboolean edsio_md5_from_string (guint8* md5, const char buf[33]); /* NIST Secure Hash Algorithm */ /* heavily modified from Peter C. Gutmann's implementation */ /* then taken from from Uwe Hollerbach, */ /* and then modified a little by Josh MacDonald. */ /* This code is in the public domain */ typedef struct { guint32 digest[5]; /* message digest */ guint32 count_lo, count_hi; /* 64-bit bit count */ guint32 data[16]; /* SHA data buffer */ int local; /* unprocessed amount in data */ } EdsioSHACtx; void edsio_sha_init (EdsioSHACtx *); void edsio_sha_update (EdsioSHACtx *, const guint8 *, guint); void edsio_sha_final (guint8 *, EdsioSHACtx *); gint edsio_sha_equal (gconstpointer v, gconstpointer v2); guint edsio_sha_hash (gconstpointer v); /* Misc stuff. */ /* These raise an error if errmsg is non-null. The errmsg should * be something like "Invalid port number". See edsio.ser for the * format. */ gboolean strtosi_checked (const char* str, gint32* i, const char* errmsg); gboolean strtoss_checked (const char* str, gint16* s, const char* errmsg); gboolean strtoui_checked (const char* str, guint32* i, const char* errmsg); gboolean strtous_checked (const char* str, guint16* i, const char* errmsg); const char* edsio_intern_string (const char* str); GByteArray* edsio_base64_encode_region (const guint8* data, guint data_len); GByteArray* edsio_base64_decode_region (const guint8* data, guint data_len); gboolean edsio_base64_encode_region_into (const guint8* data, guint data_len, guint8* out, guint *out_len); gboolean edsio_base64_decode_region_into (const guint8* data, guint data_len, guint8* out, guint *out_len); gchar* edsio_time_to_iso8601 (SerialGenericTime* time); gchar* edsio_time_t_to_iso8601 (guint32 time); gboolean edsio_time_of_day (SerialGenericTime* time); enum _SimpleBufferFlags { SBF_None = 0, SBF_Compress = 1 << 0, SBF_Checksum = 1 << 1, SBF_Base64 = 1 << 2 }; typedef enum _SimpleBufferFlags SimpleBufferFlags; SerialSource* edsio_simple_source (const guint8* data, guint len, guint flags); SerialSink* edsio_simple_sink (gpointer data, guint flags, gboolean free_result, void (* success) (gpointer data, GByteArray* result), GByteArray **result); gboolean edsio_library_check (guint32 number); void edsio_library_register (guint32 number, const char*name); /* (Persistent) Property stuff. */ enum _PropertyFlags { PF_None = 0, PF_Persistent = 1 }; typedef enum _PropertyFlags PropertyFlags; typedef struct _EdsioProperty EdsioProperty; typedef union _EdsioPropertyEntry EdsioPropertyEntry; typedef struct _EdsioGenericProperty EdsioGenericProperty; typedef void (* PropFreeFunc) (gpointer obj); typedef gboolean (* PropGSFunc) (gpointer obj, EdsioProperty* prop, ...); typedef gboolean (* PropSerialize) (SerialSink* sink, EdsioPropertyEntry* value); typedef gboolean (* PropUnserialize) (SerialSource* source, EdsioPropertyEntry** value); typedef GHashTable** (* PropertyTableFunc) (gpointer obj); typedef SerialSource* (* PersistSourceFunc) (gpointer obj, const char* prop_name); typedef SerialSink* (* PersistSinkFunc) (gpointer obj, const char* prop_name); typedef gboolean (* PersistIssetFunc) (gpointer obj, const char* prop_name); typedef gboolean (* PersistUnsetFunc) (gpointer obj, const char* prop_name); void edsio_initialize_property_type (const char* t, PropFreeFunc freer, PropGSFunc getter, PropGSFunc setter, PropSerialize ser, PropUnserialize unser); void edsio_initialize_host_type (const char* ph, PropertyTableFunc ptable, PersistSourceFunc source, PersistSinkFunc sink, PersistIssetFunc isset, PersistUnsetFunc unset); gboolean edsio_property_isset (const char* ph, const char* t, guint32 code, gpointer obj); gboolean edsio_property_unset (const char* ph, const char* t, guint32 code, gpointer obj); PropGSFunc edsio_property_getter (const char* ph, const char* t, guint32 code, EdsioProperty** prop); PropGSFunc edsio_property_setter (const char* ph, const char* t, guint32 code, EdsioProperty** prop); void edsio_property_uint_free (gpointer obj); gboolean edsio_property_uint_getter (gpointer obj, EdsioProperty* ep, guint32* get); gboolean edsio_property_uint_setter (gpointer obj, EdsioProperty* ep, guint32 set); void edsio_property_string_free (gpointer obj); gboolean edsio_property_string_getter (gpointer obj, EdsioProperty* ep, const char** get); gboolean edsio_property_string_setter (gpointer obj, EdsioProperty* ep, const char* set); void edsio_property_bytes_free (gpointer obj); gboolean edsio_property_bytes_getter (gpointer obj, EdsioProperty* ep, guint8** get, guint32 *get_len); gboolean edsio_property_bytes_setter (gpointer obj, EdsioProperty* ep, guint8* set, guint32 set_len); void edsio_property_vptr_free (gpointer obj); gboolean edsio_property_vptr_getter (gpointer obj, EdsioProperty* ep, void** get); gboolean edsio_property_vptr_setter (gpointer obj, EdsioProperty* ep, void* set); EdsioPropertyEntry* edsio_property_get (gpointer obj, EdsioProperty* ep); gboolean edsio_property_set (gpointer obj, EdsioProperty* ep, EdsioPropertyEntry* set); gboolean edsio_new_property (const char* name, const char* ph, const char* t, guint32 flags, EdsioGenericProperty* prop); /* Testing... */ #define DEBUG_LIBEDSIO #ifdef DEBUG_LIBEDSIO struct _PropTest { GHashTable* _edsio_property_table; GHashTable* ptable; const char* kludge; }; GHashTable** edsio_proptest_property_table (PropTest *pt); SerialSource* edsio_persist_proptest_source (PropTest *pt, const char* prop_name); SerialSink* edsio_persist_proptest_sink (PropTest *pt, const char* prop_name); gboolean edsio_persist_proptest_isset (PropTest *pt, const char* prop_name); gboolean edsio_persist_proptest_unset (PropTest *pt, const char* prop_name); #endif #define g_queue_get_size g_queue_get_length #define g_queue_push g_queue_push_tail #define g_queue_pop g_queue_pop_head #define g_queue_peek g_queue_peek_head #ifdef __cplusplus } #endif #endif /* _EDSIO_H_ */ xdelta-1.2.1/libedsio/edsio.ser000077500000000000000000000070371525650667300164350ustar00rootroot00000000000000;; -*- Emacs-Lisp -*- (defmodule edsio 6 "edsio.h" nil) (defsertype EdsioUint 1 ((val uint)) () ) (defsertype EdsioBytes 2 ((val bytes)) () ) (defsertype EdsioString 3 ((val string)) () ) (defsertype GenericTime 4 ((seconds uint) (nanos uint) ) () ) (defetype source "SerialSource*") (defetype sink "SerialSink*") (defetype int "int") (defetype string "const char*") (defevent GetTimeOfDayFailure Error () (errno) "Gettimeofday failed: ${STRERROR}") (defevent TimeFailure Error () (errno) "Time failed: ${STRERROR}") (defevent UnregisteredType Error ((library int) (number int)) () "Unregistered serial type: library=${LIBRARY} number=${NUMBER}") (defevent UnexpectedLibraryType Error ((expected int) (received int)) () "Unexpected serial library type: expected ${EXPECTED}, received ${RECEIVED}") (defevent UnexpectedType Error () () "Unexpected serial type") (defevent OutputBufferShort Error () () "Output buffer is too short") (defevent InvalidBase64Encoding Error () () "Invalid base64 encoding") (defevent MissingChecksum Error () () "Missing embedded checksum in base64 encoding") (defevent InvalidChecksum Error () () "Checksum verification failed") (defevent SourceEof Error ((source source)) () "${SOURCE}: Unexpected EOF") (defevent IncorrectAllocation Error ((source source)) () "${SOURCE}: Incorrect allocation") (defevent InvalidIntegerString Error ((msg string) (arg string)) () "${MSG}: not an integer: ${ARG}") (defevent IntegerOutOfRange Error ((msg string) (arg string)) () "${MSG}: integer out of range: ${ARG}") (defevent InvalidIntegerSign Error ((msg string) (arg string)) () "${MSG}: expected an unsigned integer: ${ARG}") (defevent DuplicatePropertyTypeRegistered Error ((name string)) () "Property type registered twice: ${NAME}") (defevent DuplicateHostTypeRegistered Error ((name string)) () "Property host registered twice: ${NAME}") (defevent DuplicatePropertyNameRegistered Warning ((name string)) () "Property name registered twice (ignored): ${NAME}") (defevent NoSuchProperty Error ((num int)) () "Unregistered property: ${NUM}") (defevent NoSuchPropertyType Error ((name string)) () "Unregistered property type: ${NAME}") (defevent NoSuchHostType Error ((name string)) () "Unregistered host type: ${NAME}") (defevent WrongHostType Error ((name string) (recv string) (expect string)) () "Wrong property host type: received ${RECV}, expected ${EXPECT}") (defevent WrongDataType Error ((name string) (recv string) (expect string)) () "Wrong property data type: received ${RECV}, expected ${EXPECT}") (defevent PropertyNotSet Error ((name string)) () "${NAME} property not set") (defevent PersistenceUnavailable Error ((name string) (host string)) () "Persistence is unavailable in host ${HOST} for property ${NAME}") (defevent InvalidStreamChecksum Error () () "Incorrect stream checksum") (defevent InvalidHexDigit Error ((bad string) (ctx string)) () "Invalid hex digit ${BAD} in context: ${CTX}") (defevent MD5StringShort Error ((short string)) () "MD5 string too short: ${SHORT}") (defevent MD5StringLong Error ((long string)) () "MD5 string too long: ${LONG}") (defevent UnregisteredLibrary Error ((number int)) () "Unregistered library: ${NUMBER}") (defevent GModuleError Error ((file string) (msg string)) () "GModule: ${FILE}: ${MSG}") ;; properties (defprophost PropTest "P" "PropTest*" t) (defprophosttype PropTest uint) (defprophosttype PropTest bytes) (defprophosttype PropTest string) (defprophosttype PropTest EdsioUint) xdelta-1.2.1/libedsio/edsio_edsio.c000077500000000000000000001027771525650667300172600ustar00rootroot00000000000000/* -*-Mode: C;-*- * Copyright (C) 1997, 1998, 1999 Josh MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Author: Josh MacDonald * * This file was AUTOMATICALLY GENERATED using: * * $Id: edsio.el 1.2 Sun, 28 Jan 2007 12:21:11 -0800 jmacd $ */ #include "edsio.h" #include /* Declarations. */ static const char* Edsio_StringStringString_event_field_to_string (GenericEvent* ev, gint field); static const char* Edsio_Int_event_field_to_string (GenericEvent* ev, gint field); static const char* Edsio_String_event_field_to_string (GenericEvent* ev, gint field); static const char* Edsio_StringString_event_field_to_string (GenericEvent* ev, gint field); static const char* Edsio_Source_event_field_to_string (GenericEvent* ev, gint field); static const char* Edsio_IntInt_event_field_to_string (GenericEvent* ev, gint field); static const char* Edsio_Errno_event_field_to_string (GenericEvent* ev, gint field); static gboolean unserialize_generictime_generic (SerialSource* source, void** object) { SerialGenericTime* result = NULL; if (! unserialize_generictime_internal (source, &result)) return FALSE; *object = result; return TRUE; } static gboolean serialize_generictime_generic (SerialSink* sink, void* object) { return serialize_generictime_obj_internal (sink, object); } static guint serializeio_count_generictime_generic (const void* object) { return serializeio_count_generictime_obj (object); } static void serializeio_print_generictime_generic (void* object, guint indent_spaces) { serializeio_print_generictime_obj (object, indent_spaces); } static gboolean unserialize_edsiostring_generic (SerialSource* source, void** object) { SerialEdsioString* result = NULL; if (! unserialize_edsiostring_internal (source, &result)) return FALSE; *object = result; return TRUE; } static gboolean serialize_edsiostring_generic (SerialSink* sink, void* object) { return serialize_edsiostring_obj_internal (sink, object); } static guint serializeio_count_edsiostring_generic (const void* object) { return serializeio_count_edsiostring_obj (object); } static void serializeio_print_edsiostring_generic (void* object, guint indent_spaces) { serializeio_print_edsiostring_obj (object, indent_spaces); } static gboolean unserialize_edsiobytes_generic (SerialSource* source, void** object) { SerialEdsioBytes* result = NULL; if (! unserialize_edsiobytes_internal (source, &result)) return FALSE; *object = result; return TRUE; } static gboolean serialize_edsiobytes_generic (SerialSink* sink, void* object) { return serialize_edsiobytes_obj_internal (sink, object); } static guint serializeio_count_edsiobytes_generic (const void* object) { return serializeio_count_edsiobytes_obj (object); } static void serializeio_print_edsiobytes_generic (void* object, guint indent_spaces) { serializeio_print_edsiobytes_obj (object, indent_spaces); } static gboolean unserialize_edsiouint_generic (SerialSource* source, void** object) { SerialEdsioUint* result = NULL; if (! unserialize_edsiouint_internal (source, &result)) return FALSE; *object = result; return TRUE; } static gboolean serialize_edsiouint_generic (SerialSink* sink, void* object) { return serialize_edsiouint_obj_internal (sink, object); } static guint serializeio_count_edsiouint_generic (const void* object) { return serializeio_count_edsiouint_obj (object); } static void serializeio_print_edsiouint_generic (void* object, guint indent_spaces) { serializeio_print_edsiouint_obj (object, indent_spaces); } static void print_spaces (guint n) { guint i; for (i = 0; i < n; i += 1) g_print (" "); } /* initialize this library. */ gboolean edsio_edsio_init (void) { static gboolean once = FALSE; static gboolean result = FALSE; if (once) return result; once = TRUE; eventdelivery_initialize_event_def (EC_EdsioGModuleErrorValue, EL_Error, EF_None, "GModuleError", "GModule: ${0}: ${1}", & Edsio_StringString_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioUnregisteredLibraryValue, EL_Error, EF_None, "UnregisteredLibrary", "Unregistered library: ${0}", & Edsio_Int_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioMD5StringLongValue, EL_Error, EF_None, "MD5StringLong", "MD5 string too long: ${0}", & Edsio_String_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioMD5StringShortValue, EL_Error, EF_None, "MD5StringShort", "MD5 string too short: ${0}", & Edsio_String_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioInvalidHexDigitValue, EL_Error, EF_None, "InvalidHexDigit", "Invalid hex digit ${0} in context: ${1}", & Edsio_StringString_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioInvalidStreamChecksumValue, EL_Error, EF_None, "InvalidStreamChecksum", "Incorrect stream checksum", NULL); eventdelivery_initialize_event_def (EC_EdsioPersistenceUnavailableValue, EL_Error, EF_None, "PersistenceUnavailable", "Persistence is unavailable in host ${1} for property ${0}", & Edsio_StringString_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioPropertyNotSetValue, EL_Error, EF_None, "PropertyNotSet", "${0} property not set", & Edsio_String_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioWrongDataTypeValue, EL_Error, EF_None, "WrongDataType", "Wrong property data type: received ${1}, expected ${2}", & Edsio_StringStringString_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioWrongHostTypeValue, EL_Error, EF_None, "WrongHostType", "Wrong property host type: received ${1}, expected ${2}", & Edsio_StringStringString_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioNoSuchHostTypeValue, EL_Error, EF_None, "NoSuchHostType", "Unregistered host type: ${0}", & Edsio_String_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioNoSuchPropertyTypeValue, EL_Error, EF_None, "NoSuchPropertyType", "Unregistered property type: ${0}", & Edsio_String_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioNoSuchPropertyValue, EL_Error, EF_None, "NoSuchProperty", "Unregistered property: ${0}", & Edsio_Int_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioDuplicatePropertyNameRegisteredValue, EL_Warning, EF_None, "DuplicatePropertyNameRegistered", "Property name registered twice (ignored): ${0}", & Edsio_String_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioDuplicateHostTypeRegisteredValue, EL_Error, EF_None, "DuplicateHostTypeRegistered", "Property host registered twice: ${0}", & Edsio_String_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioDuplicatePropertyTypeRegisteredValue, EL_Error, EF_None, "DuplicatePropertyTypeRegistered", "Property type registered twice: ${0}", & Edsio_String_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioInvalidIntegerSignValue, EL_Error, EF_None, "InvalidIntegerSign", "${0}: expected an unsigned integer: ${1}", & Edsio_StringString_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioIntegerOutOfRangeValue, EL_Error, EF_None, "IntegerOutOfRange", "${0}: integer out of range: ${1}", & Edsio_StringString_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioInvalidIntegerStringValue, EL_Error, EF_None, "InvalidIntegerString", "${0}: not an integer: ${1}", & Edsio_StringString_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioIncorrectAllocationValue, EL_Error, EF_None, "IncorrectAllocation", "${0}: Incorrect allocation", & Edsio_Source_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioSourceEofValue, EL_Error, EF_None, "SourceEof", "${0}: Unexpected EOF", & Edsio_Source_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioInvalidChecksumValue, EL_Error, EF_None, "InvalidChecksum", "Checksum verification failed", NULL); eventdelivery_initialize_event_def (EC_EdsioMissingChecksumValue, EL_Error, EF_None, "MissingChecksum", "Missing embedded checksum in base64 encoding", NULL); eventdelivery_initialize_event_def (EC_EdsioInvalidBase64EncodingValue, EL_Error, EF_None, "InvalidBase64Encoding", "Invalid base64 encoding", NULL); eventdelivery_initialize_event_def (EC_EdsioOutputBufferShortValue, EL_Error, EF_None, "OutputBufferShort", "Output buffer is too short", NULL); eventdelivery_initialize_event_def (EC_EdsioUnexpectedTypeValue, EL_Error, EF_None, "UnexpectedType", "Unexpected serial type", NULL); eventdelivery_initialize_event_def (EC_EdsioUnexpectedLibraryTypeValue, EL_Error, EF_None, "UnexpectedLibraryType", "Unexpected serial library type: expected ${0}, received ${1}", & Edsio_IntInt_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioUnregisteredTypeValue, EL_Error, EF_None, "UnregisteredType", "Unregistered serial type: library=${0} number=${1}", & Edsio_IntInt_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioTimeFailureValue, EL_Error, EF_None, "TimeFailure", "Time failed: ${0}", & Edsio_Errno_event_field_to_string); eventdelivery_initialize_event_def (EC_EdsioGetTimeOfDayFailureValue, EL_Error, EF_None, "GetTimeOfDayFailure", "Gettimeofday failed: ${0}", & Edsio_Errno_event_field_to_string); serializeio_initialize_type ("ST_GenericTime", ST_GenericTime, &unserialize_generictime_generic, &serialize_generictime_generic, &serializeio_count_generictime_generic, &serializeio_print_generictime_generic); serializeio_initialize_type ("ST_EdsioString", ST_EdsioString, &unserialize_edsiostring_generic, &serialize_edsiostring_generic, &serializeio_count_edsiostring_generic, &serializeio_print_edsiostring_generic); serializeio_initialize_type ("ST_EdsioBytes", ST_EdsioBytes, &unserialize_edsiobytes_generic, &serialize_edsiobytes_generic, &serializeio_count_edsiobytes_generic, &serializeio_print_edsiobytes_generic); serializeio_initialize_type ("ST_EdsioUint", ST_EdsioUint, &unserialize_edsiouint_generic, &serialize_edsiouint_generic, &serializeio_count_edsiouint_generic, &serializeio_print_edsiouint_generic); edsio_initialize_host_type ("PropTest", (PropertyTableFunc) & edsio_proptest_property_table, (PersistSourceFunc) & edsio_persist_proptest_source, (PersistSinkFunc) & edsio_persist_proptest_sink, (PersistIssetFunc) & edsio_persist_proptest_isset, (PersistUnsetFunc) & edsio_persist_proptest_unset); edsio_initialize_property_type ("EdsioUint", & edsio_property_vptr_free, (PropGSFunc) & edsio_property_vptr_getter, (PropGSFunc) & edsio_property_vptr_setter, (PropSerialize) serialize_edsiouint_obj, (PropUnserialize) unserialize_edsiouint); edsio_initialize_property_type ("string", & edsio_property_string_free, (PropGSFunc) & edsio_property_string_getter, (PropGSFunc) & edsio_property_string_setter, (PropSerialize) serialize_string_obj, (PropUnserialize) unserialize_string); edsio_initialize_property_type ("bytes", & edsio_property_bytes_free, (PropGSFunc) & edsio_property_bytes_getter, (PropGSFunc) & edsio_property_bytes_setter, (PropSerialize) serialize_bytes_obj, (PropUnserialize) unserialize_bytes); edsio_initialize_property_type ("uint", & edsio_property_uint_free, (PropGSFunc) & edsio_property_uint_getter, (PropGSFunc) & edsio_property_uint_setter, (PropSerialize) serialize_uint_obj, (PropUnserialize) unserialize_uint); edsio_library_register (6, "edsio"); result = TRUE; return TRUE; } gboolean edsio_new_proptest_edsiouint_property (const char* name, guint32 flags, EdsioPropTestEdsioUintProperty* prop) { return edsio_new_property (name, "PropTest", "EdsioUint", flags, (EdsioGenericProperty*) prop); } gboolean proptest_get_edsiouint (PropTest* obj, EdsioPropTestEdsioUintProperty prop, SerialEdsioUint** arg) { EdsioProperty* ep; PropGSFunc getter; g_return_val_if_fail (obj, FALSE); getter = edsio_property_getter ("PropTest", "EdsioUint", prop.code, & ep); return (* getter) (obj, ep, arg); } gboolean proptest_set_edsiouint (PropTest* obj, EdsioPropTestEdsioUintProperty prop, SerialEdsioUint* arg) { EdsioProperty* ep; PropGSFunc setter; g_return_val_if_fail (obj, FALSE); setter = edsio_property_setter ("PropTest", "EdsioUint", prop.code, & ep); return (* setter) (obj, ep, arg); } gboolean proptest_unset_edsiouint (PropTest* obj, EdsioPropTestEdsioUintProperty prop) { g_return_val_if_fail (obj, FALSE); return edsio_property_unset ("PropTest", "EdsioUint", prop.code, obj); } gboolean proptest_isset_edsiouint (PropTest* obj, EdsioPropTestEdsioUintProperty prop) { g_return_val_if_fail (obj, FALSE); return edsio_property_isset ("PropTest", "EdsioUint", prop.code, obj); } gboolean edsio_new_proptest_string_property (const char* name, guint32 flags, EdsioPropTestStringProperty* prop) { return edsio_new_property (name, "PropTest", "string", flags, (EdsioGenericProperty*) prop); } gboolean proptest_get_string (PropTest* obj, EdsioPropTestStringProperty prop, const gchar** arg) { EdsioProperty* ep; PropGSFunc getter; g_return_val_if_fail (obj, FALSE); getter = edsio_property_getter ("PropTest", "string", prop.code, & ep); return (* getter) (obj, ep, arg); } gboolean proptest_set_string (PropTest* obj, EdsioPropTestStringProperty prop, const gchar* arg) { EdsioProperty* ep; PropGSFunc setter; g_return_val_if_fail (obj, FALSE); setter = edsio_property_setter ("PropTest", "string", prop.code, & ep); return (* setter) (obj, ep, arg); } gboolean proptest_unset_string (PropTest* obj, EdsioPropTestStringProperty prop) { g_return_val_if_fail (obj, FALSE); return edsio_property_unset ("PropTest", "string", prop.code, obj); } gboolean proptest_isset_string (PropTest* obj, EdsioPropTestStringProperty prop) { g_return_val_if_fail (obj, FALSE); return edsio_property_isset ("PropTest", "string", prop.code, obj); } gboolean edsio_new_proptest_bytes_property (const char* name, guint32 flags, EdsioPropTestBytesProperty* prop) { return edsio_new_property (name, "PropTest", "bytes", flags, (EdsioGenericProperty*) prop); } gboolean proptest_get_bytes (PropTest* obj, EdsioPropTestBytesProperty prop, const guint8** arg, guint32* arg_len) { EdsioProperty* ep; PropGSFunc getter; g_return_val_if_fail (obj, FALSE); getter = edsio_property_getter ("PropTest", "bytes", prop.code, & ep); return (* getter) (obj, ep, arg, arg_len); } gboolean proptest_set_bytes (PropTest* obj, EdsioPropTestBytesProperty prop, const guint8* arg, guint32 arg_len) { EdsioProperty* ep; PropGSFunc setter; g_return_val_if_fail (obj, FALSE); setter = edsio_property_setter ("PropTest", "bytes", prop.code, & ep); return (* setter) (obj, ep, arg, arg_len); } gboolean proptest_unset_bytes (PropTest* obj, EdsioPropTestBytesProperty prop) { g_return_val_if_fail (obj, FALSE); return edsio_property_unset ("PropTest", "bytes", prop.code, obj); } gboolean proptest_isset_bytes (PropTest* obj, EdsioPropTestBytesProperty prop) { g_return_val_if_fail (obj, FALSE); return edsio_property_isset ("PropTest", "bytes", prop.code, obj); } gboolean edsio_new_proptest_uint_property (const char* name, guint32 flags, EdsioPropTestUintProperty* prop) { return edsio_new_property (name, "PropTest", "uint", flags, (EdsioGenericProperty*) prop); } gboolean proptest_get_uint (PropTest* obj, EdsioPropTestUintProperty prop, guint32* arg) { EdsioProperty* ep; PropGSFunc getter; g_return_val_if_fail (obj, FALSE); getter = edsio_property_getter ("PropTest", "uint", prop.code, & ep); return (* getter) (obj, ep, arg); } gboolean proptest_set_uint (PropTest* obj, EdsioPropTestUintProperty prop, guint32 arg) { EdsioProperty* ep; PropGSFunc setter; g_return_val_if_fail (obj, FALSE); setter = edsio_property_setter ("PropTest", "uint", prop.code, & ep); return (* setter) (obj, ep, arg); } gboolean proptest_unset_uint (PropTest* obj, EdsioPropTestUintProperty prop) { g_return_val_if_fail (obj, FALSE); return edsio_property_unset ("PropTest", "uint", prop.code, obj); } gboolean proptest_isset_uint (PropTest* obj, EdsioPropTestUintProperty prop) { g_return_val_if_fail (obj, FALSE); return edsio_property_isset ("PropTest", "uint", prop.code, obj); } /* EdsioUint Count */ guint serializeio_count_edsiouint (guint32 val) { guint size = sizeof (SerialEdsioUint); (void) val; ALIGN_8 (size); ALIGN_8 (size); return size; } guint serializeio_count_edsiouint_obj (SerialEdsioUint const* obj) { return serializeio_count_edsiouint (obj->val); } /* EdsioUint Print */ void serializeio_print_edsiouint_obj (SerialEdsioUint* obj, guint indent_spaces) { print_spaces (indent_spaces); g_print ("[ST_EdsioUint]\n"); print_spaces (indent_spaces); g_print ("val = "); g_print ("%d\n", obj->val); } /* EdsioUint Serialize */ gboolean serialize_edsiouint_internal (SerialSink *sink, guint32 val) { if (! (* sink->next_uint) (sink, val)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_edsiouint_obj_internal (SerialSink *sink, SerialEdsioUint* obj) { return serialize_edsiouint_internal (sink, obj->val); } gboolean serialize_edsiouint (SerialSink *sink, guint32 val) { if (! (* sink->sink_type) (sink, ST_EdsioUint, serializeio_count_edsiouint (val), TRUE)) goto bail; if (! serialize_edsiouint_internal (sink, val)) goto bail; if (sink->sink_quantum && ! sink->sink_quantum (sink)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_edsiouint_obj (SerialSink *sink, const SerialEdsioUint* obj) { return serialize_edsiouint (sink, obj->val); } /* EdsioUint Unserialize */ gboolean unserialize_edsiouint_internal_noalloc (SerialSource *source, SerialEdsioUint* result) { if (! (* source->next_uint) (source, &result->val)) goto bail; return TRUE; bail: return FALSE; } gboolean unserialize_edsiouint_internal (SerialSource *source, SerialEdsioUint** result) { SerialEdsioUint* unser; (*result) = NULL; unser = serializeio_source_alloc (source, sizeof (SerialEdsioUint)); if (! unser) goto bail; if (! unserialize_edsiouint_internal_noalloc (source, unser)) goto bail; (*result) = unser; return TRUE; bail: return FALSE; } gboolean unserialize_edsiouint (SerialSource *source, SerialEdsioUint** result) { if ( (* source->source_type) (source, TRUE) != ST_EdsioUint) goto bail; if (! unserialize_edsiouint_internal (source, result)) goto bail; return TRUE; bail: return FALSE; } /* EdsioBytes Count */ guint serializeio_count_edsiobytes (guint32 val_len, const guint8* val) { guint size = sizeof (SerialEdsioBytes); (void) val_len; (void) val; ALIGN_8 (size); size += val_len; ALIGN_8 (size); return size; } guint serializeio_count_edsiobytes_obj (SerialEdsioBytes const* obj) { return serializeio_count_edsiobytes (obj->val_len, obj->val); } /* EdsioBytes Print */ void serializeio_print_edsiobytes_obj (SerialEdsioBytes* obj, guint indent_spaces) { print_spaces (indent_spaces); g_print ("[ST_EdsioBytes]\n"); print_spaces (indent_spaces); g_print ("val = "); serializeio_print_bytes (obj->val, obj->val_len); } /* EdsioBytes Serialize */ gboolean serialize_edsiobytes_internal (SerialSink *sink, guint32 val_len, const guint8* val) { if (! (* sink->next_bytes) (sink, val, val_len)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_edsiobytes_obj_internal (SerialSink *sink, SerialEdsioBytes* obj) { return serialize_edsiobytes_internal (sink, obj->val_len, obj->val); } gboolean serialize_edsiobytes (SerialSink *sink, guint32 val_len, const guint8* val) { if (! (* sink->sink_type) (sink, ST_EdsioBytes, serializeio_count_edsiobytes (val_len, val), TRUE)) goto bail; if (! serialize_edsiobytes_internal (sink, val_len, val)) goto bail; if (sink->sink_quantum && ! sink->sink_quantum (sink)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_edsiobytes_obj (SerialSink *sink, const SerialEdsioBytes* obj) { return serialize_edsiobytes (sink, obj->val_len, obj->val); } /* EdsioBytes Unserialize */ gboolean unserialize_edsiobytes_internal_noalloc (SerialSource *source, SerialEdsioBytes* result) { if (! (* source->next_bytes) (source, &result->val, &result->val_len)) goto bail; return TRUE; bail: return FALSE; } gboolean unserialize_edsiobytes_internal (SerialSource *source, SerialEdsioBytes** result) { SerialEdsioBytes* unser; (*result) = NULL; unser = serializeio_source_alloc (source, sizeof (SerialEdsioBytes)); if (! unser) goto bail; if (! unserialize_edsiobytes_internal_noalloc (source, unser)) goto bail; (*result) = unser; return TRUE; bail: return FALSE; } gboolean unserialize_edsiobytes (SerialSource *source, SerialEdsioBytes** result) { if ( (* source->source_type) (source, TRUE) != ST_EdsioBytes) goto bail; if (! unserialize_edsiobytes_internal (source, result)) goto bail; return TRUE; bail: return FALSE; } /* EdsioString Count */ guint serializeio_count_edsiostring (const gchar* val) { guint size = sizeof (SerialEdsioString); (void) val; ALIGN_8 (size); size += strlen (val) + 1; ALIGN_8 (size); return size; } guint serializeio_count_edsiostring_obj (SerialEdsioString const* obj) { return serializeio_count_edsiostring (obj->val); } /* EdsioString Print */ void serializeio_print_edsiostring_obj (SerialEdsioString* obj, guint indent_spaces) { print_spaces (indent_spaces); g_print ("[ST_EdsioString]\n"); print_spaces (indent_spaces); g_print ("val = "); g_print ("%s\n", obj->val); } /* EdsioString Serialize */ gboolean serialize_edsiostring_internal (SerialSink *sink, const gchar* val) { if (! (* sink->next_string) (sink, val)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_edsiostring_obj_internal (SerialSink *sink, SerialEdsioString* obj) { return serialize_edsiostring_internal (sink, obj->val); } gboolean serialize_edsiostring (SerialSink *sink, const gchar* val) { if (! (* sink->sink_type) (sink, ST_EdsioString, serializeio_count_edsiostring (val), TRUE)) goto bail; if (! serialize_edsiostring_internal (sink, val)) goto bail; if (sink->sink_quantum && ! sink->sink_quantum (sink)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_edsiostring_obj (SerialSink *sink, const SerialEdsioString* obj) { return serialize_edsiostring (sink, obj->val); } /* EdsioString Unserialize */ gboolean unserialize_edsiostring_internal_noalloc (SerialSource *source, SerialEdsioString* result) { if (! (* source->next_string) (source, &result->val)) goto bail; return TRUE; bail: return FALSE; } gboolean unserialize_edsiostring_internal (SerialSource *source, SerialEdsioString** result) { SerialEdsioString* unser; (*result) = NULL; unser = serializeio_source_alloc (source, sizeof (SerialEdsioString)); if (! unser) goto bail; if (! unserialize_edsiostring_internal_noalloc (source, unser)) goto bail; (*result) = unser; return TRUE; bail: return FALSE; } gboolean unserialize_edsiostring (SerialSource *source, SerialEdsioString** result) { if ( (* source->source_type) (source, TRUE) != ST_EdsioString) goto bail; if (! unserialize_edsiostring_internal (source, result)) goto bail; return TRUE; bail: return FALSE; } /* GenericTime Count */ guint serializeio_count_generictime (guint32 seconds, guint32 nanos) { guint size = sizeof (SerialGenericTime); (void) seconds; (void) nanos; ALIGN_8 (size); ALIGN_8 (size); ALIGN_8 (size); return size; } guint serializeio_count_generictime_obj (SerialGenericTime const* obj) { return serializeio_count_generictime (obj->seconds, obj->nanos); } /* GenericTime Print */ void serializeio_print_generictime_obj (SerialGenericTime* obj, guint indent_spaces) { print_spaces (indent_spaces); g_print ("[ST_GenericTime]\n"); print_spaces (indent_spaces); g_print ("seconds = "); g_print ("%d\n", obj->seconds); print_spaces (indent_spaces); g_print ("nanos = "); g_print ("%d\n", obj->nanos); } /* GenericTime Serialize */ gboolean serialize_generictime_internal (SerialSink *sink, guint32 seconds, guint32 nanos) { if (! (* sink->next_uint) (sink, seconds)) goto bail; if (! (* sink->next_uint) (sink, nanos)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_generictime_obj_internal (SerialSink *sink, SerialGenericTime* obj) { return serialize_generictime_internal (sink, obj->seconds, obj->nanos); } gboolean serialize_generictime (SerialSink *sink, guint32 seconds, guint32 nanos) { if (! (* sink->sink_type) (sink, ST_GenericTime, serializeio_count_generictime (seconds, nanos), TRUE)) goto bail; if (! serialize_generictime_internal (sink, seconds, nanos)) goto bail; if (sink->sink_quantum && ! sink->sink_quantum (sink)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_generictime_obj (SerialSink *sink, const SerialGenericTime* obj) { return serialize_generictime (sink, obj->seconds, obj->nanos); } /* GenericTime Unserialize */ gboolean unserialize_generictime_internal_noalloc (SerialSource *source, SerialGenericTime* result) { if (! (* source->next_uint) (source, &result->seconds)) goto bail; if (! (* source->next_uint) (source, &result->nanos)) goto bail; return TRUE; bail: return FALSE; } gboolean unserialize_generictime_internal (SerialSource *source, SerialGenericTime** result) { SerialGenericTime* unser; (*result) = NULL; unser = serializeio_source_alloc (source, sizeof (SerialGenericTime)); if (! unser) goto bail; if (! unserialize_generictime_internal_noalloc (source, unser)) goto bail; (*result) = unser; return TRUE; bail: return FALSE; } gboolean unserialize_generictime (SerialSource *source, SerialGenericTime** result) { if ( (* source->source_type) (source, TRUE) != ST_GenericTime) goto bail; if (! unserialize_generictime_internal (source, result)) goto bail; return TRUE; bail: return FALSE; } void edsio_generate_errno_event_internal (EdsioErrnoEventCode _code, const char* _srcfile, gint _srcline) { EdsioErrnoEvent *_e = g_new0 (EdsioErrnoEvent, 1); _e->code = _code.code; _e->srcline = _srcline; _e->srcfile = _srcfile; _e->ev_errno = errno; eventdelivery_event_deliver ((GenericEvent*) _e); } const char* Edsio_Errno_event_field_to_string (GenericEvent* ev, gint field) { EdsioErrnoEvent* it = (EdsioErrnoEvent*) ev; switch (field) { case 0: return g_strdup (g_strerror (it->ev_errno)); default: abort (); } } const EdsioErrnoEventCode EC_EdsioGetTimeOfDayFailure = { EC_EdsioGetTimeOfDayFailureValue }; const EdsioErrnoEventCode EC_EdsioTimeFailure = { EC_EdsioTimeFailureValue }; void edsio_generate_intint_event_internal (EdsioIntIntEventCode _code, const char* _srcfile, gint _srcline, int library, int number) { EdsioIntIntEvent *_e = g_new0 (EdsioIntIntEvent, 1); _e->code = _code.code; _e->srcline = _srcline; _e->srcfile = _srcfile; _e->library = library; _e->number = number; eventdelivery_event_deliver ((GenericEvent*) _e); } const char* Edsio_IntInt_event_field_to_string (GenericEvent* ev, gint field) { EdsioIntIntEvent* it = (EdsioIntIntEvent*) ev; switch (field) { case 0: return eventdelivery_int_to_string (it->library); case 1: return eventdelivery_int_to_string (it->number); default: abort (); } } const EdsioIntIntEventCode EC_EdsioUnregisteredType = { EC_EdsioUnregisteredTypeValue }; const EdsioIntIntEventCode EC_EdsioUnexpectedLibraryType = { EC_EdsioUnexpectedLibraryTypeValue }; void edsio_generate_void_event_internal (EdsioVoidEventCode _code, const char* _srcfile, gint _srcline) { EdsioVoidEvent *_e = g_new0 (EdsioVoidEvent, 1); _e->code = _code.code; _e->srcline = _srcline; _e->srcfile = _srcfile; eventdelivery_event_deliver ((GenericEvent*) _e); } const EdsioVoidEventCode EC_EdsioUnexpectedType = { EC_EdsioUnexpectedTypeValue }; const EdsioVoidEventCode EC_EdsioOutputBufferShort = { EC_EdsioOutputBufferShortValue }; const EdsioVoidEventCode EC_EdsioInvalidBase64Encoding = { EC_EdsioInvalidBase64EncodingValue }; const EdsioVoidEventCode EC_EdsioMissingChecksum = { EC_EdsioMissingChecksumValue }; const EdsioVoidEventCode EC_EdsioInvalidChecksum = { EC_EdsioInvalidChecksumValue }; void edsio_generate_source_event_internal (EdsioSourceEventCode _code, const char* _srcfile, gint _srcline, SerialSource* source) { EdsioSourceEvent *_e = g_new0 (EdsioSourceEvent, 1); _e->code = _code.code; _e->srcline = _srcline; _e->srcfile = _srcfile; _e->source = source; eventdelivery_event_deliver ((GenericEvent*) _e); } const char* Edsio_Source_event_field_to_string (GenericEvent* ev, gint field) { EdsioSourceEvent* it = (EdsioSourceEvent*) ev; switch (field) { case 0: return eventdelivery_source_to_string (it->source); default: abort (); } } const EdsioSourceEventCode EC_EdsioSourceEof = { EC_EdsioSourceEofValue }; const EdsioSourceEventCode EC_EdsioIncorrectAllocation = { EC_EdsioIncorrectAllocationValue }; void edsio_generate_stringstring_event_internal (EdsioStringStringEventCode _code, const char* _srcfile, gint _srcline, const char* msg, const char* arg) { EdsioStringStringEvent *_e = g_new0 (EdsioStringStringEvent, 1); _e->code = _code.code; _e->srcline = _srcline; _e->srcfile = _srcfile; _e->msg = msg; _e->arg = arg; eventdelivery_event_deliver ((GenericEvent*) _e); } const char* Edsio_StringString_event_field_to_string (GenericEvent* ev, gint field) { EdsioStringStringEvent* it = (EdsioStringStringEvent*) ev; switch (field) { case 0: return eventdelivery_string_to_string (it->msg); case 1: return eventdelivery_string_to_string (it->arg); default: abort (); } } const EdsioStringStringEventCode EC_EdsioInvalidIntegerString = { EC_EdsioInvalidIntegerStringValue }; const EdsioStringStringEventCode EC_EdsioIntegerOutOfRange = { EC_EdsioIntegerOutOfRangeValue }; const EdsioStringStringEventCode EC_EdsioInvalidIntegerSign = { EC_EdsioInvalidIntegerSignValue }; void edsio_generate_string_event_internal (EdsioStringEventCode _code, const char* _srcfile, gint _srcline, const char* name) { EdsioStringEvent *_e = g_new0 (EdsioStringEvent, 1); _e->code = _code.code; _e->srcline = _srcline; _e->srcfile = _srcfile; _e->name = name; eventdelivery_event_deliver ((GenericEvent*) _e); } const char* Edsio_String_event_field_to_string (GenericEvent* ev, gint field) { EdsioStringEvent* it = (EdsioStringEvent*) ev; switch (field) { case 0: return eventdelivery_string_to_string (it->name); default: abort (); } } const EdsioStringEventCode EC_EdsioDuplicatePropertyTypeRegistered = { EC_EdsioDuplicatePropertyTypeRegisteredValue }; const EdsioStringEventCode EC_EdsioDuplicateHostTypeRegistered = { EC_EdsioDuplicateHostTypeRegisteredValue }; const EdsioStringEventCode EC_EdsioDuplicatePropertyNameRegistered = { EC_EdsioDuplicatePropertyNameRegisteredValue }; void edsio_generate_int_event_internal (EdsioIntEventCode _code, const char* _srcfile, gint _srcline, int num) { EdsioIntEvent *_e = g_new0 (EdsioIntEvent, 1); _e->code = _code.code; _e->srcline = _srcline; _e->srcfile = _srcfile; _e->num = num; eventdelivery_event_deliver ((GenericEvent*) _e); } const char* Edsio_Int_event_field_to_string (GenericEvent* ev, gint field) { EdsioIntEvent* it = (EdsioIntEvent*) ev; switch (field) { case 0: return eventdelivery_int_to_string (it->num); default: abort (); } } const EdsioIntEventCode EC_EdsioNoSuchProperty = { EC_EdsioNoSuchPropertyValue }; const EdsioStringEventCode EC_EdsioNoSuchPropertyType = { EC_EdsioNoSuchPropertyTypeValue }; const EdsioStringEventCode EC_EdsioNoSuchHostType = { EC_EdsioNoSuchHostTypeValue }; void edsio_generate_stringstringstring_event_internal (EdsioStringStringStringEventCode _code, const char* _srcfile, gint _srcline, const char* name, const char* recv, const char* expect) { EdsioStringStringStringEvent *_e = g_new0 (EdsioStringStringStringEvent, 1); _e->code = _code.code; _e->srcline = _srcline; _e->srcfile = _srcfile; _e->name = name; _e->recv = recv; _e->expect = expect; eventdelivery_event_deliver ((GenericEvent*) _e); } const char* Edsio_StringStringString_event_field_to_string (GenericEvent* ev, gint field) { EdsioStringStringStringEvent* it = (EdsioStringStringStringEvent*) ev; switch (field) { case 0: return eventdelivery_string_to_string (it->name); case 1: return eventdelivery_string_to_string (it->recv); case 2: return eventdelivery_string_to_string (it->expect); default: abort (); } } const EdsioStringStringStringEventCode EC_EdsioWrongHostType = { EC_EdsioWrongHostTypeValue }; const EdsioStringStringStringEventCode EC_EdsioWrongDataType = { EC_EdsioWrongDataTypeValue }; const EdsioStringEventCode EC_EdsioPropertyNotSet = { EC_EdsioPropertyNotSetValue }; const EdsioStringStringEventCode EC_EdsioPersistenceUnavailable = { EC_EdsioPersistenceUnavailableValue }; const EdsioVoidEventCode EC_EdsioInvalidStreamChecksum = { EC_EdsioInvalidStreamChecksumValue }; const EdsioStringStringEventCode EC_EdsioInvalidHexDigit = { EC_EdsioInvalidHexDigitValue }; const EdsioStringEventCode EC_EdsioMD5StringShort = { EC_EdsioMD5StringShortValue }; const EdsioStringEventCode EC_EdsioMD5StringLong = { EC_EdsioMD5StringLongValue }; const EdsioIntEventCode EC_EdsioUnregisteredLibrary = { EC_EdsioUnregisteredLibraryValue }; const EdsioStringStringEventCode EC_EdsioGModuleError = { EC_EdsioGModuleErrorValue }; xdelta-1.2.1/libedsio/edsio_edsio.h000077500000000000000000000411551525650667300172550ustar00rootroot00000000000000/* -*-Mode: C;-*- * Copyright (C) 1997, 1998, 1999 Josh MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Author: Josh MacDonald * * This file was AUTOMATICALLY GENERATED using: * * $Id: edsio.el 1.2 Sun, 28 Jan 2007 12:21:11 -0800 jmacd $ */ #include "edsio.h" #include "edsio.h" #ifndef _EDSIO_EDSIO_H_ #define _EDSIO_EDSIO_H_ #ifdef __cplusplus extern "C" { #endif /* Initialize this library. */ gboolean edsio_edsio_init (void); /* Types defined here. */ /* EdsioStringStringStringEventCode. */ typedef struct _EdsioStringStringStringEventCode EdsioStringStringStringEventCode; struct _EdsioStringStringStringEventCode { gint code; }; typedef struct _EdsioStringStringStringEvent EdsioStringStringStringEvent; struct _EdsioStringStringStringEvent { gint code; const char* srcfile; guint srcline; const char* name; const char* recv; const char* expect; }; /* EdsioIntEventCode. */ typedef struct _EdsioIntEventCode EdsioIntEventCode; struct _EdsioIntEventCode { gint code; }; typedef struct _EdsioIntEvent EdsioIntEvent; struct _EdsioIntEvent { gint code; const char* srcfile; guint srcline; int num; }; /* EdsioStringEventCode. */ typedef struct _EdsioStringEventCode EdsioStringEventCode; struct _EdsioStringEventCode { gint code; }; typedef struct _EdsioStringEvent EdsioStringEvent; struct _EdsioStringEvent { gint code; const char* srcfile; guint srcline; const char* name; }; /* EdsioStringStringEventCode. */ typedef struct _EdsioStringStringEventCode EdsioStringStringEventCode; struct _EdsioStringStringEventCode { gint code; }; typedef struct _EdsioStringStringEvent EdsioStringStringEvent; struct _EdsioStringStringEvent { gint code; const char* srcfile; guint srcline; const char* msg; const char* arg; }; /* EdsioSourceEventCode. */ typedef struct _EdsioSourceEventCode EdsioSourceEventCode; struct _EdsioSourceEventCode { gint code; }; typedef struct _EdsioSourceEvent EdsioSourceEvent; struct _EdsioSourceEvent { gint code; const char* srcfile; guint srcline; SerialSource* source; }; /* EdsioVoidEventCode. */ typedef struct _EdsioVoidEventCode EdsioVoidEventCode; struct _EdsioVoidEventCode { gint code; }; typedef struct _EdsioVoidEvent EdsioVoidEvent; struct _EdsioVoidEvent { gint code; const char* srcfile; guint srcline; }; /* EdsioIntIntEventCode. */ typedef struct _EdsioIntIntEventCode EdsioIntIntEventCode; struct _EdsioIntIntEventCode { gint code; }; typedef struct _EdsioIntIntEvent EdsioIntIntEvent; struct _EdsioIntIntEvent { gint code; const char* srcfile; guint srcline; int library; int number; }; /* EdsioErrnoEventCode. */ typedef struct _EdsioErrnoEventCode EdsioErrnoEventCode; struct _EdsioErrnoEventCode { gint code; }; typedef struct _EdsioErrnoEvent EdsioErrnoEvent; struct _EdsioErrnoEvent { gint code; const char* srcfile; guint srcline; gint ev_errno; }; typedef struct _SerialGenericTime SerialGenericTime; typedef struct _SerialEdsioString SerialEdsioString; typedef struct _SerialEdsioBytes SerialEdsioBytes; typedef struct _SerialEdsioUint SerialEdsioUint; /* Functions declared here. */ /* Property definitions */ /* Property get/set for PropTest/EdsioUint */ typedef struct _EdsioPropTestEdsioUintProperty EdsioPropTestEdsioUintProperty; struct _EdsioPropTestEdsioUintProperty { guint32 code; }; gboolean edsio_new_proptest_edsiouint_property (const char* name, guint32 flags, EdsioPropTestEdsioUintProperty* prop); gboolean proptest_get_edsiouint (PropTest* obj, EdsioPropTestEdsioUintProperty prop, SerialEdsioUint** arg); gboolean proptest_set_edsiouint (PropTest* obj, EdsioPropTestEdsioUintProperty prop, SerialEdsioUint* arg); gboolean proptest_unset_edsiouint (PropTest* obj, EdsioPropTestEdsioUintProperty prop); gboolean proptest_isset_edsiouint (PropTest* obj, EdsioPropTestEdsioUintProperty prop); /* Property get/set for PropTest/string */ typedef struct _EdsioPropTestStringProperty EdsioPropTestStringProperty; struct _EdsioPropTestStringProperty { guint32 code; }; gboolean edsio_new_proptest_string_property (const char* name, guint32 flags, EdsioPropTestStringProperty* prop); gboolean proptest_get_string (PropTest* obj, EdsioPropTestStringProperty prop, const gchar** arg); gboolean proptest_set_string (PropTest* obj, EdsioPropTestStringProperty prop, const gchar* arg); gboolean proptest_unset_string (PropTest* obj, EdsioPropTestStringProperty prop); gboolean proptest_isset_string (PropTest* obj, EdsioPropTestStringProperty prop); /* Property get/set for PropTest/bytes */ typedef struct _EdsioPropTestBytesProperty EdsioPropTestBytesProperty; struct _EdsioPropTestBytesProperty { guint32 code; }; gboolean edsio_new_proptest_bytes_property (const char* name, guint32 flags, EdsioPropTestBytesProperty* prop); gboolean proptest_get_bytes (PropTest* obj, EdsioPropTestBytesProperty prop, const guint8** arg, guint32* arg_len); gboolean proptest_set_bytes (PropTest* obj, EdsioPropTestBytesProperty prop, const guint8* arg, guint32 arg_len); gboolean proptest_unset_bytes (PropTest* obj, EdsioPropTestBytesProperty prop); gboolean proptest_isset_bytes (PropTest* obj, EdsioPropTestBytesProperty prop); /* Property get/set for PropTest/uint */ typedef struct _EdsioPropTestUintProperty EdsioPropTestUintProperty; struct _EdsioPropTestUintProperty { guint32 code; }; gboolean edsio_new_proptest_uint_property (const char* name, guint32 flags, EdsioPropTestUintProperty* prop); gboolean proptest_get_uint (PropTest* obj, EdsioPropTestUintProperty prop, guint32* arg); gboolean proptest_set_uint (PropTest* obj, EdsioPropTestUintProperty prop, guint32 arg); gboolean proptest_unset_uint (PropTest* obj, EdsioPropTestUintProperty prop); gboolean proptest_isset_uint (PropTest* obj, EdsioPropTestUintProperty prop); /* Serial Types */ enum _SerialEdsioType { ST_EdsioUint = (1<<(1+EDSIO_LIBRARY_OFFSET_BITS))+6, ST_EdsioBytes = (1<<(2+EDSIO_LIBRARY_OFFSET_BITS))+6, ST_EdsioString = (1<<(3+EDSIO_LIBRARY_OFFSET_BITS))+6, ST_GenericTime = (1<<(4+EDSIO_LIBRARY_OFFSET_BITS))+6 }; /* EdsioUint Structure */ struct _SerialEdsioUint { guint32 val; }; void serializeio_print_edsiouint_obj (SerialEdsioUint* obj, guint indent_spaces); gboolean unserialize_edsiouint (SerialSource *source, SerialEdsioUint**); gboolean unserialize_edsiouint_internal (SerialSource *source, SerialEdsioUint** ); gboolean unserialize_edsiouint_internal_noalloc (SerialSource *source, SerialEdsioUint* ); gboolean serialize_edsiouint (SerialSink *sink, guint32 val); gboolean serialize_edsiouint_obj (SerialSink *sink, const SerialEdsioUint* obj); gboolean serialize_edsiouint_internal (SerialSink *sink, guint32 val); gboolean serialize_edsiouint_obj_internal (SerialSink *sink, SerialEdsioUint* obj); guint serializeio_count_edsiouint (guint32 val); guint serializeio_count_edsiouint_obj (SerialEdsioUint const* obj); /* EdsioBytes Structure */ struct _SerialEdsioBytes { guint32 val_len; const guint8* val; }; void serializeio_print_edsiobytes_obj (SerialEdsioBytes* obj, guint indent_spaces); gboolean unserialize_edsiobytes (SerialSource *source, SerialEdsioBytes**); gboolean unserialize_edsiobytes_internal (SerialSource *source, SerialEdsioBytes** ); gboolean unserialize_edsiobytes_internal_noalloc (SerialSource *source, SerialEdsioBytes* ); gboolean serialize_edsiobytes (SerialSink *sink, guint32 val_len, const guint8* val); gboolean serialize_edsiobytes_obj (SerialSink *sink, const SerialEdsioBytes* obj); gboolean serialize_edsiobytes_internal (SerialSink *sink, guint32 val_len, const guint8* val); gboolean serialize_edsiobytes_obj_internal (SerialSink *sink, SerialEdsioBytes* obj); guint serializeio_count_edsiobytes (guint32 val_len, const guint8* val); guint serializeio_count_edsiobytes_obj (SerialEdsioBytes const* obj); /* EdsioString Structure */ struct _SerialEdsioString { const gchar* val; }; void serializeio_print_edsiostring_obj (SerialEdsioString* obj, guint indent_spaces); gboolean unserialize_edsiostring (SerialSource *source, SerialEdsioString**); gboolean unserialize_edsiostring_internal (SerialSource *source, SerialEdsioString** ); gboolean unserialize_edsiostring_internal_noalloc (SerialSource *source, SerialEdsioString* ); gboolean serialize_edsiostring (SerialSink *sink, const gchar* val); gboolean serialize_edsiostring_obj (SerialSink *sink, const SerialEdsioString* obj); gboolean serialize_edsiostring_internal (SerialSink *sink, const gchar* val); gboolean serialize_edsiostring_obj_internal (SerialSink *sink, SerialEdsioString* obj); guint serializeio_count_edsiostring (const gchar* val); guint serializeio_count_edsiostring_obj (SerialEdsioString const* obj); /* GenericTime Structure */ struct _SerialGenericTime { guint32 seconds; guint32 nanos; }; void serializeio_print_generictime_obj (SerialGenericTime* obj, guint indent_spaces); gboolean unserialize_generictime (SerialSource *source, SerialGenericTime**); gboolean unserialize_generictime_internal (SerialSource *source, SerialGenericTime** ); gboolean unserialize_generictime_internal_noalloc (SerialSource *source, SerialGenericTime* ); gboolean serialize_generictime (SerialSink *sink, guint32 seconds, guint32 nanos); gboolean serialize_generictime_obj (SerialSink *sink, const SerialGenericTime* obj); gboolean serialize_generictime_internal (SerialSink *sink, guint32 seconds, guint32 nanos); gboolean serialize_generictime_obj_internal (SerialSink *sink, SerialGenericTime* obj); guint serializeio_count_generictime (guint32 seconds, guint32 nanos); guint serializeio_count_generictime_obj (SerialGenericTime const* obj); void edsio_generate_errno_event_internal (EdsioErrnoEventCode code, const char* srcfile, gint srcline); #define edsio_generate_errno_event(ecode) edsio_generate_errno_event_internal((ecode),__FILE__,__LINE__) extern const EdsioErrnoEventCode EC_EdsioGetTimeOfDayFailure; #define EC_EdsioGetTimeOfDayFailureValue ((0< */ #include "edsio.h" void test1 () { guint32 x = 0; PropTest *pt = g_new0 (PropTest, 1); EdsioPropTestUintProperty prop; g_assert (edsio_edsio_init ()); g_assert (edsio_new_proptest_uint_property ("Just testing (1)...", PF_Persistent, & prop)); g_assert (! proptest_isset_uint (pt, prop)); g_assert (proptest_set_uint (pt, prop, 42)); g_assert (proptest_isset_uint (pt, prop)); g_assert (proptest_get_uint (pt, prop, & x) && x == 42); /* kill the cache, to test persistence. */ pt->_edsio_property_table = NULL; g_assert (proptest_get_uint (pt, prop, & x) && x == 42); g_assert (proptest_unset_uint (pt, prop)); g_assert (! proptest_isset_uint (pt, prop)); g_assert (! pt->_edsio_property_table); } void test2 () { const char* str = "hello there"; const char* str2; guint32 str2_len; PropTest *pt = g_new0 (PropTest, 1); EdsioPropTestBytesProperty prop; g_assert (edsio_edsio_init ()); g_assert (edsio_new_proptest_bytes_property ("Just testing (2)...", PF_Persistent, & prop)); g_assert (! proptest_isset_bytes (pt, prop)); g_assert (proptest_set_bytes (pt, prop, (guint8*) str, strlen (str) + 1)); g_assert (proptest_isset_bytes (pt, prop)); g_assert (proptest_get_bytes (pt, prop, (const guint8**) & str2, & str2_len) && str2_len == (strlen (str) + 1) && strcmp (str, str2) == 0); /* kill the cache, to test persistence. */ pt->_edsio_property_table = NULL; g_assert (proptest_get_bytes (pt, prop, (const guint8**) & str2, & str2_len) && str2_len == (strlen (str) + 1) && strcmp (str, str2) == 0); g_assert (proptest_unset_bytes (pt, prop)); g_assert (! proptest_isset_bytes (pt, prop)); g_assert (! pt->_edsio_property_table); } void test3 () { SerialEdsioUint x; SerialEdsioUint *p; EdsioPropTestEdsioUintProperty prop; PropTest *pt = g_new0 (PropTest, 1); x.val = 42; g_assert (edsio_edsio_init ()); g_assert (edsio_new_proptest_edsiouint_property ("Just testing (3)...", PF_Persistent, & prop)); g_assert (! proptest_isset_edsiouint (pt, prop)); g_assert (proptest_set_edsiouint (pt, prop, & x)); g_assert (proptest_isset_edsiouint (pt, prop)); g_assert (proptest_get_edsiouint (pt, prop, & p) && x.val == p->val); /* kill the cache, to test persistence. */ pt->_edsio_property_table = NULL; g_assert (proptest_get_edsiouint (pt, prop, & p) && x.val == p->val); g_assert (proptest_unset_edsiouint (pt, prop)); g_assert (! proptest_isset_edsiouint (pt, prop)); g_assert (! pt->_edsio_property_table); } void test4 () { const char* str = "hello there"; const char* str2; PropTest *pt = g_new0 (PropTest, 1); EdsioPropTestStringProperty prop; g_assert (edsio_edsio_init ()); g_assert (edsio_new_proptest_string_property ("Just testing (4)...", PF_Persistent, & prop)); g_assert (! proptest_isset_string (pt, prop)); g_assert (proptest_set_string (pt, prop, str)); g_assert (proptest_isset_string (pt, prop)); g_assert (proptest_get_string (pt, prop, & str2) && strcmp (str, str2) == 0); /* kill the cache, to test persistence. */ pt->_edsio_property_table = NULL; g_assert (proptest_get_string (pt, prop, & str2) && strcmp (str, str2) == 0); g_assert (proptest_unset_string (pt, prop)); g_assert (! proptest_isset_string (pt, prop)); g_assert (! pt->_edsio_property_table); } void test5 () { GByteArray* sink_result; SerialSink* sink = edsio_simple_sink (NULL, SBF_Checksum | SBF_Base64 | SBF_Compress, FALSE, NULL, & sink_result); SerialSource* src; const char* input = "hello there!!!!!!!!"; SerialEdsioString *output; guint8 zero[1]; zero[0] = 0; g_assert (serialize_edsiostring (sink, input)); g_assert (sink->sink_close (sink)); g_byte_array_append (sink_result, zero, 1); g_print ("%s -> %s\n", input, sink_result->data); src = edsio_simple_source (sink_result->data, sink_result->len - 1, SBF_Checksum | SBF_Base64 | SBF_Compress); g_assert (unserialize_edsiostring (src, & output)); g_assert (src->source_close (src)); g_assert (strcmp (output->val, input) == 0); } void test6 () { const char* md5str = "aed3918c4ccb89f2dcf74d5dcab22989"; const char* md5strbad1 = "aed3918c4cXb89f2dcf74d5dcab22989"; const char* md5strbad2 = "aed3918c4cab89f2dcf74d5dcab22989X"; const char* md5strbad3 = "aed3918c4cab89f2dcf74d5dcab2298"; char md5str2[33]; guint8 md5[16]; g_assert (! edsio_md5_from_string (md5, md5strbad1)); g_assert (! edsio_md5_from_string (md5, md5strbad2)); g_assert (! edsio_md5_from_string (md5, md5strbad3)); g_assert (edsio_md5_from_string (md5, md5str)); edsio_md5_to_string (md5, md5str2); g_assert (strcmp (md5str, md5str2) == 0); } int main () { test1 (); test2 (); test3 (); test4 (); test5 (); test6 (); return 0; } xdelta-1.2.1/libedsio/fh.c000077500000000000000000000077751525650667300153710ustar00rootroot00000000000000/* -*-Mode: C;-*- * $Id: fh.c 1.2 Sun, 28 Jan 2007 12:21:11 -0800 jmacd $ * * Copyright (C) 1998, 1999, Josh MacDonald. * All Rights Reserved. * * Author: Josh MacDonald */ #include "edsio.h" /* Handle source/sink impls */ typedef struct _HandleSerialSource HandleSerialSource; typedef struct _HandleSerialSink HandleSerialSink; struct _HandleSerialSource { SerialSource source; FileHandle* fh; }; struct _HandleSerialSink { SerialSink sink; FileHandle* fh; gpointer data1; gpointer data2; gpointer data3; gboolean (* cont_onclose) (gpointer data1, gpointer data2, gpointer data3); }; static SerialType handle_source_type (SerialSource* source, gboolean set_allocation); static gboolean handle_source_close (SerialSource* source); static gboolean handle_source_read (SerialSource* source, guint8 *ptr, guint32 len); static void handle_source_free (SerialSource* source); static gboolean handle_sink_type (SerialSink* sink, SerialType type, guint len, gboolean set_allocation); static gboolean handle_sink_close (SerialSink* sink); static gboolean handle_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len); static void handle_sink_free (SerialSink* sink); SerialSource* handle_source (FileHandle* fh) { HandleSerialSource* it = g_new0 (HandleSerialSource, 1); serializeio_source_init (&it->source, handle_source_type, handle_source_close, handle_source_read, handle_source_free, NULL, NULL); it->fh = fh; return &it->source; } SerialSink* handle_sink (FileHandle* fh, gpointer data1, gpointer data2, gpointer data3, gboolean (* cont_onclose) (gpointer data1, gpointer data2, gpointer data3)) { HandleSerialSink* it = g_new0 (HandleSerialSink, 1); serializeio_sink_init (&it->sink, handle_sink_type, handle_sink_close, handle_sink_write, handle_sink_free, NULL); it->fh = fh; it->data1 = data1; it->data2 = data2; it->data3 = data3; it->cont_onclose = cont_onclose; return &it->sink; } SerialType handle_source_type (SerialSource* source, gboolean set_allocation) { HandleSerialSource* ssource = (HandleSerialSource*) source; guint32 x; if (! ssource->fh->table->table_handle_getui (ssource->fh, &x)) return ST_Error; if (set_allocation) { /* Note: set_allocation is deprecated in 1.1.4 */ guint32 bogus; if (! ssource->fh->table->table_handle_getui (ssource->fh, &bogus)) return ST_Error; } return x; } gboolean handle_source_close (SerialSource* source) { HandleSerialSource* ssource = (HandleSerialSource*) source; return ssource->fh->table->table_handle_close (ssource->fh, 0); } gboolean handle_source_read (SerialSource* source, guint8 *ptr, guint32 len) { HandleSerialSource* ssource = (HandleSerialSource*) source; return ssource->fh->table->table_handle_read (ssource->fh, ptr, len) == len; } void handle_source_free (SerialSource* source) { g_free (source); } gboolean handle_sink_type (SerialSink* sink, SerialType type, guint len, gboolean set_allocation) { HandleSerialSink* ssink = (HandleSerialSink*) sink; if (! ssink->fh->table->table_handle_putui (ssink->fh, type)) return FALSE; /* Note: set_allocation is deprecated in 1.1.4 */ if (set_allocation && ! ssink->fh->table->table_handle_putui (ssink->fh, len)) return FALSE; return TRUE; } gboolean handle_sink_close (SerialSink* sink) { HandleSerialSink* ssink = (HandleSerialSink*) sink; if (ssink->fh->table->table_handle_close (ssink->fh, 0)) { if (ssink->cont_onclose) return ssink->cont_onclose (ssink->data1, ssink->data2, ssink->data3); return TRUE; } return FALSE; } gboolean handle_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len) { HandleSerialSink* ssink = (HandleSerialSink*) sink; return ssink->fh->table->table_handle_write (ssink->fh, ptr, len); } void handle_sink_free (SerialSink* sink) { g_free (sink); } xdelta-1.2.1/libedsio/generic.c000077500000000000000000000122261525650667300163730ustar00rootroot00000000000000/* -*-Mode: C;-*- * $Id: generic.c 1.2 Sun, 28 Jan 2007 12:21:11 -0800 jmacd $ * * Copyright (C) 1998, 1999, Josh MacDonald. * All Rights Reserved. * * Author: Josh MacDonald */ #include "edsio.h" /* Type-based selectors for unknown types */ typedef struct { const char* name; SerializeioUnserializeFunc unserialize_func; SerializeioSerializeFunc serialize_func; SerializeioCountFunc count_func; SerializeioPrintFunc print_func; guint32 val; } SerEntry; static GArray *ser_array; static gboolean ser_array_sorted; void serializeio_initialize_type (const char* name, guint32 val, SerializeioUnserializeFunc unserialize_func, SerializeioSerializeFunc serialize_func, SerializeioCountFunc count_func, SerializeioPrintFunc print_func) { SerEntry it; it.name = name; it.val = val; it.unserialize_func = unserialize_func; it.serialize_func = serialize_func; it.count_func = count_func; it.print_func = print_func; if (ser_array == NULL) ser_array = g_array_new (FALSE, TRUE, sizeof (SerEntry)); g_array_append_val (ser_array, it); ser_array_sorted = FALSE; } static int ser_entry_compare (const void* va, const void* vb) { const SerEntry* a = va; const SerEntry* b = vb; return a->val - b->val; } static SerEntry* serializeio_find_entry (SerialType type) { if (! edsio_library_check (type & EDSIO_LIBRARY_OFFSET_MASK)) return NULL; if (ser_array) { gint high_index = ser_array->len; gint low_index = 0; gint index; gint this_val; if (! ser_array_sorted) { ser_array_sorted = TRUE; qsort (ser_array->data, ser_array->len, sizeof (SerEntry), ser_entry_compare); } again: index = (low_index + high_index) / 2; this_val = g_array_index (ser_array, SerEntry, index).val; if (this_val < type) { low_index = index + 1; goto again; } else if (this_val > type) { high_index = index - 1; goto again; } else { return & g_array_index (ser_array, SerEntry, index); } } edsio_generate_intint_event (EC_EdsioUnregisteredType, type & EDSIO_LIBRARY_OFFSET_MASK, type >> EDSIO_LIBRARY_OFFSET_BITS); return NULL; } gboolean serializeio_unserialize_generic_internal (SerialSource *source, SerialType *object_type, void **object, gboolean set_allocation) { SerialType type = (* source->source_type) (source, set_allocation); SerEntry* ent; gboolean res = FALSE; if (type < 0) return FALSE; ent = serializeio_find_entry (type); (*object_type) = type; if (ent) res = ent->unserialize_func (source, object); return res; } gboolean serializeio_unserialize_generic (SerialSource *source, SerialType *object_type, void **object) { return serializeio_unserialize_generic_internal (source, object_type, object, TRUE); } gboolean serializeio_serialize_generic (SerialSink *sink, SerialType object_type, void *object) { return serializeio_serialize_generic_internal (sink, object_type, object, TRUE); } gboolean serializeio_serialize_generic_internal (SerialSink *sink, SerialType object_type, void *object, gboolean set_allocation) { SerEntry* ent; gboolean res = FALSE; if (! (* sink->sink_type) (sink, object_type, set_allocation ? serializeio_generic_count (object_type, object) : 0, set_allocation)) return FALSE; ent = serializeio_find_entry (object_type); if (ent) res = ent->serialize_func (sink, object); return res; } const char* serializeio_generic_type_to_string (SerialType type) { SerEntry* ent; const char* res = "*Unknown*"; ent = serializeio_find_entry (type); if (ent) res = ent->name; return res; } guint serializeio_generic_count (SerialType object_type, void *object) { SerEntry* ent; guint res = 0; ent = serializeio_find_entry (object_type); if (ent) res = ent->count_func (object); return res; } void serializeio_generic_print (SerialType type, void* object, guint indent_spaces) { SerEntry* ent; ent = serializeio_find_entry (type); if (ent) ent->print_func (object, indent_spaces); else { guint i = 0; for (; i < indent_spaces; i += 1) g_print (" "); g_print ("*Type Not Registered*\n"); } } gboolean serializeio_unserialize_generic_acceptable (SerialSource *source, guint32 accept, SerialType *object_type, void **object) { gboolean s; s = serializeio_unserialize_generic (source, object_type, object); if (s) { if (accept != (guint32) -1) { if ((*object_type & EDSIO_LIBRARY_OFFSET_MASK) != (accept & EDSIO_LIBRARY_OFFSET_MASK)) { edsio_generate_intint_event (EC_EdsioUnexpectedLibraryType, accept & EDSIO_LIBRARY_OFFSET_MASK, *object_type & EDSIO_LIBRARY_OFFSET_MASK); return FALSE; } if (! ((*object_type & ~EDSIO_LIBRARY_OFFSET_MASK) | (accept & ~EDSIO_LIBRARY_OFFSET_MASK))) { edsio_generate_void_event (EC_EdsioUnexpectedType); return FALSE; } } } return s; } xdelta-1.2.1/libedsio/library.c000077500000000000000000000044701525650667300164250ustar00rootroot00000000000000/* -*-Mode: C;-*- * $Id: library.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $ * * Copyright (C) 1998, 1999, Josh MacDonald. * All Rights Reserved. * * Author: Josh MacDonald */ #include "edsio.h" #include typedef struct _Library Library; struct _Library { const char* name; const char* libname; gint index; gboolean loaded; }; static Library known_libraries[] = { { "xd", "xdelta", 3, FALSE }, { "edsio", "edsio", 6, FALSE }, }; static GHashTable* loaded_libraries; static void edsio_library_init (void) { if (! loaded_libraries) { gint i; gint n = sizeof (known_libraries) / sizeof (Library); loaded_libraries = g_hash_table_new (g_int_hash, g_int_equal); for (i = 0; i < n; i += 1) { Library* lib = known_libraries + i; g_hash_table_insert (loaded_libraries, & lib->index, lib); } } } void edsio_library_register (guint32 number, const char* name) { Library* lib; edsio_library_init (); lib = g_hash_table_lookup (loaded_libraries, & number); if (lib) { lib->loaded = TRUE; return; } lib = g_new0 (Library, 1); lib->index = number; lib->name = name; lib->loaded = TRUE; g_hash_table_insert (loaded_libraries, & lib->index, lib); } gboolean edsio_library_check (guint32 number) { Library* lib; edsio_library_init (); lib = g_hash_table_lookup (loaded_libraries, & number); if (lib) { lib->loaded = TRUE; return TRUE; } #if 0 if (lib->libname && g_module_supported ()) { GModule *module; GString *module_name = g_string_new (NULL); GString *symbol_name = g_string_new (NULL); gboolean (* init) (void); if (! (module = g_module_open (module_name->str, 0))) { edsio_generate_stringstring_event (EC_EdsioGModuleError, module_name->str, g_module_error ()); return FALSE; } if (! g_module_symbol (module, symbol_name->str, (void**) & init)) { edsio_generate_stringstring_event (EC_EdsioGModuleError, g_module_name (module), g_module_error ()); return FALSE; } g_module_make_resident (module); g_module_close (module); lib->loaded = TRUE; return (* init) (); } #endif edsio_generate_int_event (EC_EdsioUnregisteredLibrary, number); return FALSE; } xdelta-1.2.1/libedsio/maketime.c000077500000000000000000000237541525650667300165630ustar00rootroot00000000000000/* Convert struct partime into time_t. */ /* Copyright 1992, 1993, 1994, 1995, 1997 Paul Eggert Distributed under license by the Free Software Foundation, Inc. This file is part of RCS. RCS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. RCS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RCS; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Report problems and direct all questions to: rcs-bugs@cs.purdue.edu */ #if has_conf_h # include #else # if HAVE_CONFIG_H # include # else # ifndef __STDC__ # define const # endif # endif /* MIPS RISCOS4.52 defines time_t in not . */ # include # if HAVE_LIMITS_H # include # endif # ifndef LONG_MIN # define LONG_MIN (-1-2147483647L) # endif # if STDC_HEADERS # include # endif # include # ifdef __STDC__ # define P(x) x # else # define P(x) () # endif #endif #include #include char const maketId[] = "$Id: maketime.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $"; static int isleap P ((int)); static int month_days P ((struct tm const *)); static time_t maketime P ((struct partime const *, time_t)); /* For maximum portability, use only localtime and gmtime. Make no assumptions about the time_t epoch or the range of time_t values. Avoid mktime because it's not universal and because there's no easy, portable way for mktime to yield the inverse of gmtime. */ #define TM_YEAR_ORIGIN 1900 static int isleap (int y) { return (y & 3) == 0 && (y % 100 != 0 || y % 400 == 0); } /* days in year before start of months 0-12 */ static int const month_yday[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; /* Yield the number of days in TM's month. */ static int month_days (struct tm const *tm) { int m = tm->tm_mon; return (month_yday[m + 1] - month_yday[m] + (m == 1 && isleap (tm->tm_year + TM_YEAR_ORIGIN))); } /* Convert UNIXTIME to struct tm form. Use gmtime if available and if !LOCALZONE, localtime otherwise. */ struct tm * time2tm (time_t unixtime, int localzone) { struct tm *tm; #ifdef TZ_is_unset static char const *TZ; if (!TZ && !(TZ = getenv ("TZ"))) TZ_is_unset ("The TZ environment variable is not set; please set it to your timezone"); #endif if (localzone || !(tm = gmtime (&unixtime))) tm = localtime (&unixtime); return tm; } /* Yield A - B, measured in seconds. */ time_t difftm (struct tm const *a, struct tm const *b) { int ay = a->tm_year + (TM_YEAR_ORIGIN - 1); int by = b->tm_year + (TM_YEAR_ORIGIN - 1); int ac = ay / 100 - (ay % 100 < 0); int bc = by / 100 - (by % 100 < 0); int difference_in_day_of_year = a->tm_yday - b->tm_yday; int intervening_leap_days = (((ay >> 2) - (by >> 2)) - (ac - bc) + ((ac >> 2) - (bc >> 2))); time_t difference_in_years = ay - by; time_t difference_in_days = (difference_in_years * 365 + (intervening_leap_days + difference_in_day_of_year)); return (((((difference_in_days * 24 + (a->tm_hour - b->tm_hour)) * 60) + (a->tm_min - b->tm_min)) * 60) + (a->tm_sec - b->tm_sec)); } /* * Adjust time T by adding SECONDS. SECONDS must be at most 24 hours' worth. * Adjust only T's year, mon, mday, hour, min and sec members; * plus adjust wday if it is defined. */ void adjzone (struct tm *t, long seconds) { /* * This code can be off by a second if SECONDS is not a multiple of 60, * if T is local time, and if a leap second happens during this minute. * But this bug has never occurred, and most likely will not ever occur. * Liberia, the last country for which SECONDS % 60 was nonzero, * switched to UTC in May 1972; the first leap second was in June 1972. */ int leap_second = t->tm_sec == 60; long sec = seconds + (t->tm_sec - leap_second); if (sec < 0) { if ((t->tm_min -= (59 - sec) / 60) < 0) { if ((t->tm_hour -= (59 - t->tm_min) / 60) < 0) { t->tm_hour += 24; if (TM_DEFINED (t->tm_wday) && --t->tm_wday < 0) t->tm_wday = 6; if (--t->tm_mday <= 0) { if (--t->tm_mon < 0) { --t->tm_year; t->tm_mon = 11; } t->tm_mday = month_days (t); } } t->tm_min += 24 * 60; } sec += 24L * 60 * 60; } else if (60 <= (t->tm_min += sec / 60)) if (24 <= (t->tm_hour += t->tm_min / 60)) { t->tm_hour -= 24; if (TM_DEFINED (t->tm_wday) && ++t->tm_wday == 7) t->tm_wday = 0; if (month_days (t) < ++t->tm_mday) { if (11 < ++t->tm_mon) { ++t->tm_year; t->tm_mon = 0; } t->tm_mday = 1; } } t->tm_min %= 60; t->tm_sec = (int) (sec % 60) + leap_second; } /* * Convert TM to time_t, using localtime if LOCALZONE and gmtime otherwise. * Use only TM's year, mon, mday, hour, min, and sec members. * Ignore TM's old tm_yday and tm_wday, but fill in their correct values. * Yield -1 on failure (e.g. a member out of range). * Posix 1003.1-1990 doesn't allow leap seconds, but some implementations * have them anyway, so allow them if localtime/gmtime does. */ time_t tm2time (struct tm *tm, int localzone) { /* Cache the most recent t,tm pairs; 1 for gmtime, 1 for localtime. */ static time_t t_cache[2]; static struct tm tm_cache[2]; time_t d, gt; struct tm const *gtm; /* * The maximum number of iterations should be enough to handle any * combinations of leap seconds, time zone rule changes, and solar time. * 4 is probably enough; we use a bigger number just to be safe. */ int remaining_tries = 8; /* Avoid subscript errors. */ if (12 <= (unsigned) tm->tm_mon) return -1; tm->tm_yday = month_yday[tm->tm_mon] + tm->tm_mday - (tm->tm_mon < 2 || !isleap (tm->tm_year + TM_YEAR_ORIGIN)); /* Make a first guess. */ gt = t_cache[localzone]; gtm = gt ? &tm_cache[localzone] : time2tm (gt, localzone); /* Repeatedly use the error from the guess to improve the guess. */ while ((d = difftm (tm, gtm)) != 0) { if (--remaining_tries == 0) return -1; gt += d; gtm = time2tm (gt, localzone); } /* * Check that the guess actually matches; * overflow can cause difftm to yield 0 even on differing times, * or tm may have members out of range (e.g. bad leap seconds). */ #define TM_DIFFER(a,b) \ ( \ ((a)->tm_year ^ (b)->tm_year) | \ ((a)->tm_mon ^ (b)->tm_mon) | \ ((a)->tm_mday ^ (b)->tm_mday) | \ ((a)->tm_hour ^ (b)->tm_hour) | \ ((a)->tm_min ^ (b)->tm_min) | \ ((a)->tm_sec ^ (b)->tm_sec) \ ) if (TM_DIFFER (tm, gtm)) { /* * If gt is a leap second, try gt+1; if it is one greater than * a leap second, try gt-1; otherwise, it doesn't matter. * Leap seconds always fall at month end. */ int yd = tm->tm_year - gtm->tm_year; gt += yd + (yd ? 0 : tm->tm_mon - gtm->tm_mon); gtm = time2tm (gt, localzone); if (TM_DIFFER (tm, gtm)) return -1; } t_cache[localzone] = gt; tm_cache[localzone] = *gtm; tm->tm_wday = gtm->tm_wday; return gt; } /* * Check *PT and convert it to time_t. * If it is incompletely specified, use DEFAULT_TIME to fill it out. * Use localtime if PT->zone is the special value TM_LOCAL_ZONE. * Yield -1 on failure. * ISO 8601 day-of-year and week numbers are not yet supported. */ static time_t maketime (struct partime const *pt, time_t default_time) { int localzone, wday; struct tm tm; struct tm *tm0 = 0; time_t r; tm0 = 0; /* Keep gcc -Wall happy. */ localzone = pt->zone == TM_LOCAL_ZONE; tm = pt->tm; if (TM_DEFINED (pt->ymodulus) || !TM_DEFINED (tm.tm_year)) { /* Get tm corresponding to default time. */ tm0 = time2tm (default_time, localzone); if (!localzone) adjzone (tm0, pt->zone); } if (TM_DEFINED (pt->ymodulus)) tm.tm_year += (tm0->tm_year + TM_YEAR_ORIGIN) / pt->ymodulus * pt->ymodulus; else if (!TM_DEFINED (tm.tm_year)) { /* Set default year, month, day from current time. */ tm.tm_year = tm0->tm_year + TM_YEAR_ORIGIN; if (!TM_DEFINED (tm.tm_mon)) { tm.tm_mon = tm0->tm_mon; if (!TM_DEFINED (tm.tm_mday)) tm.tm_mday = tm0->tm_mday; } } /* Convert from partime year (Gregorian) to Posix year. */ tm.tm_year -= TM_YEAR_ORIGIN; /* Set remaining default fields to be their minimum values. */ if (!TM_DEFINED (tm.tm_mon)) tm.tm_mon = 0; if (!TM_DEFINED (tm.tm_mday)) tm.tm_mday = 1; if (!TM_DEFINED (tm.tm_hour)) tm.tm_hour = 0; if (!TM_DEFINED (tm.tm_min)) tm.tm_min = 0; if (!TM_DEFINED (tm.tm_sec)) tm.tm_sec = 0; if (!localzone) adjzone (&tm, -pt->zone); wday = tm.tm_wday; /* Convert and fill in the rest of the tm. */ r = tm2time (&tm, localzone); /* Check weekday. */ if (r != -1 && TM_DEFINED (wday) && wday != tm.tm_wday) return -1; return r; } /* Parse a free-format date in SOURCE, yielding a Unix format time. */ time_t str2time (char const *source, time_t default_time, long default_zone) { struct partime pt; if (*partime (source, &pt)) return -1; if (pt.zone == TM_UNDEFINED_ZONE) pt.zone = default_zone; return maketime (&pt, default_time); } #if TEST #include int main (argc, argv) int argc; char **argv; { time_t default_time = time ((time_t *) 0); long default_zone = argv[1] ? atol (argv[1]) : 0; char buf[1000]; while (fgets (buf, sizeof (buf), stdin)) { time_t t = str2time (buf, default_time, default_zone); printf ("%s", asctime (gmtime (&t))); } return 0; } #endif xdelta-1.2.1/libedsio/maketime.h000077500000000000000000000025141525650667300165570ustar00rootroot00000000000000/* Yield time_t from struct partime yielded by partime. */ /* Copyright 1993, 1994, 1995 Paul Eggert Distributed under license by the Free Software Foundation, Inc. This file is part of RCS. RCS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. RCS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RCS; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Report problems and direct all questions to: rcs-bugs@cs.purdue.edu */ #if defined __STDC__ || has_prototypes # define __MAKETIME_P(x) x #else # define __MAKETIME_P(x) () #endif struct tm *time2tm __MAKETIME_P ((time_t, int)); time_t difftm __MAKETIME_P ((struct tm const *, struct tm const *)); time_t str2time __MAKETIME_P ((char const *, time_t, long)); time_t tm2time __MAKETIME_P ((struct tm *, int)); void adjzone __MAKETIME_P ((struct tm *, long)); xdelta-1.2.1/libedsio/md5c.c000077500000000000000000000232151525650667300156070ustar00rootroot00000000000000/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm */ /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ #include "edsio.h" #include /* Constants for MD5Transform routine. */ #define S11 7 #define S12 12 #define S13 17 #define S14 22 #define S21 5 #define S22 9 #define S23 14 #define S24 20 #define S31 4 #define S32 11 #define S33 16 #define S34 23 #define S41 6 #define S42 10 #define S43 15 #define S44 21 static void MD5Transform (guint32 [4], unsigned const char [64]); static void Encode (unsigned char *, guint32 *, unsigned int); static void Decode (guint32 *, unsigned const char *, unsigned int); #define MD5_memcpy memcpy #define MD5_memset memset static unsigned char PADDING[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* F, G, H and I are basic MD5 functions. */ #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define I(x, y, z) ((y) ^ ((x) | (~z))) /* ROTATE_LEFT rotates x left n bits. */ #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent recomputation. */ #define FF(a, b, c, d, x, s, ac) { \ (a) += F ((b), (c), (d)) + (x) + (guint32)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define GG(a, b, c, d, x, s, ac) { \ (a) += G ((b), (c), (d)) + (x) + (guint32)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define HH(a, b, c, d, x, s, ac) { \ (a) += H ((b), (c), (d)) + (x) + (guint32)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define II(a, b, c, d, x, s, ac) { \ (a) += I ((b), (c), (d)) + (x) + (guint32)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } /* MD5 initialization. Begins an MD5 operation, writing a new context. */ void edsio_md5_init (EdsioMD5Ctx *context) { context->count[0] = context->count[1] = 0; /* Load magic initialization constants. */ context->state[0] = 0x67452301; context->state[1] = 0xefcdab89; context->state[2] = 0x98badcfe; context->state[3] = 0x10325476; } /* MD5 block update operation. Continues an MD5 message-digest operation, processing another message block, and updating the context. */ void edsio_md5_update (EdsioMD5Ctx *context, const guint8* input, guint inputLen) { unsigned int i, index, partLen; /* Compute number of bytes mod 64 */ index = (unsigned int)((context->count[0] >> 3) & 0x3F); /* Update number of bits */ if ((context->count[0] += ((guint32)inputLen << 3)) < ((guint32)inputLen << 3)) context->count[1]++; context->count[1] += ((guint32)inputLen >> 29); partLen = 64 - index; /* Transform as many times as possible. */ if (inputLen >= partLen) { MD5_memcpy ((guint8*)&context->buffer[index], (guint8*)input, partLen); MD5Transform (context->state, context->buffer); for (i = partLen; i + 63 < inputLen; i += 64) MD5Transform (context->state, &input[i]); index = 0; } else i = 0; /* Buffer remaining input */ MD5_memcpy ((guint8*)&context->buffer[index], (guint8*)&input[i], inputLen-i); } /* MD5 finalization. Ends an MD5 message-digest operation, writing the the message digest and zeroizing the context. */ void edsio_md5_final (guint8* digest, EdsioMD5Ctx* context) { unsigned char bits[8]; unsigned int index, padLen; /* Save number of bits */ Encode (bits, context->count, 8); /* Pad out to 56 mod 64. */ index = (unsigned int)((context->count[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); edsio_md5_update (context, PADDING, padLen); /* Append length (before padding) */ edsio_md5_update (context, bits, 8); /* Store state in digest */ Encode (digest, context->state, 16); /* Zeroize sensitive information. */ MD5_memset ((guint8*)context, 0, sizeof (*context)); } /* MD5 basic transformation. Transforms state based on block. */ static void MD5Transform (guint32 state[4], const guint8 block[64]) { guint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; Decode (x, block, 64); /* Round 1 */ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ /* Round 2 */ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ /* Round 3 */ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ /* Round 4 */ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; /* Zeroize sensitive information. */ MD5_memset ((guint8*)x, 0, sizeof (x)); } /* Encodes input (guint32) into output (unsigned char). Assumes len is a multiple of 4. */ static void Encode (unsigned char *output, guint32 *input, unsigned int len) { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) { output[j] = (unsigned char)(input[i] & 0xff); output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); } } /* Decodes input (unsigned char) into output (guint32). Assumes len is a multiple of 4. */ static void Decode (guint32 *output, unsigned const char *input, unsigned int len) { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) output[i] = ((guint32)input[j]) | (((guint32)input[j+1]) << 8) | (((guint32)input[j+2]) << 16) | (((guint32)input[j+3]) << 24); } xdelta-1.2.1/libedsio/partime.c000077500000000000000000000447021525650667300164240ustar00rootroot00000000000000/* Parse a string, yielding a struct partime that describes it. */ /* Copyright 1993, 1994, 1995, 1997 Paul Eggert Distributed under license by the Free Software Foundation, Inc. This file is part of RCS. RCS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. RCS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RCS; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Report problems and direct all questions to: rcs-bugs@cs.purdue.edu */ #if has_conf_h # include #else # if HAVE_CONFIG_H # include # else # ifndef __STDC__ # define const # endif # endif # if HAVE_LIMITS_H # include # endif # ifndef LONG_MIN # define LONG_MIN (-1-2147483647L) # endif # if STDC_HEADERS # include # endif # include # ifdef __STDC__ # define P(x) x # else # define P(x) () # endif #endif #include #if STDC_HEADERS # define CTYPE_DOMAIN(c) 1 #else # define CTYPE_DOMAIN(c) ((unsigned) (c) <= 0177) #endif #define ISALNUM(c) (CTYPE_DOMAIN (c) && isalnum (c)) #define ISALPHA(c) (CTYPE_DOMAIN (c) && isalpha (c)) #define ISSPACE(c) (CTYPE_DOMAIN (c) && isspace (c)) #define ISUPPER(c) (CTYPE_DOMAIN (c) && isupper (c)) #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9) #if defined(__GNUC__) || defined(__clang__) # define FALLTHROUGH __attribute__((fallthrough)) #else # define FALLTHROUGH ((void) 0) #endif #include char const partimeId[] = "$Id: partime.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $"; /* Lookup tables for names of months, weekdays, time zones. */ #define NAME_LENGTH_MAXIMUM 4 struct name_val { char name[NAME_LENGTH_MAXIMUM + 1]; int val; }; static char const *parse_decimal P ((char const *, int, int, int, int, int *, int *)); static char const *parse_fixed P ((char const *, int, int *)); static char const *parse_pattern_letter P ((char const *, int, struct partime *)); static char const *parse_prefix P ((char const *, struct partime *, int *)); static char const *parse_ranged P ((char const *, int, int, int, int *)); static int lookup P ((char const *, struct name_val const[])); static int merge_partime P ((struct partime *, struct partime const *)); static void undefine P ((struct partime *)); static struct name_val const month_names[] = { {"jan", 0}, {"feb", 1}, {"mar", 2}, {"apr", 3}, {"may", 4}, {"jun", 5}, {"jul", 6}, {"aug", 7}, {"sep", 8}, {"oct", 9}, {"nov", 10}, {"dec", 11}, {"", TM_UNDEFINED} }; static struct name_val const weekday_names[] = { {"sun", 0}, {"mon", 1}, {"tue", 2}, {"wed", 3}, {"thu", 4}, {"fri", 5}, {"sat", 6}, {"", TM_UNDEFINED} }; #define hr60nonnegative(t) ((t)/100 * 60 + (t)%100) #define hr60(t) ((t)<0 ? -hr60nonnegative(-(t)) : hr60nonnegative(t)) #define zs(t,s) {s, hr60(t)} #define zd(t,s,d) zs(t, s), zs((t)+100, d) static struct name_val const zone_names[] = { zs (-1000, "hst"), /* Hawaii */ zd (-1000, "hast", "hadt"), /* Hawaii-Aleutian */ zd (- 900, "akst", "akdt"), /* Alaska */ zd (- 800, "pst" , "pdt" ), /* Pacific */ zd (- 700, "mst" , "mdt" ), /* Mountain */ zd (- 600, "cst" , "cdt" ), /* Central */ zd (- 500, "est" , "edt" ), /* Eastern */ zd (- 400, "ast" , "adt" ), /* Atlantic */ zd (- 330, "nst" , "ndt" ), /* Newfoundland */ zs ( 000, "utc" ), /* Coordinated Universal */ zs ( 000, "uct" ), /* " */ zs ( 000, "cut" ), /* " */ zs ( 000, "ut"), /* Universal */ zs ( 000, "z"), /* Zulu (required by ISO 8601) */ zd ( 000, "gmt" , "bst" ), /* Greenwich Mean, British Summer */ zd ( 000, "wet" , "west"), /* Western European */ zd ( 100, "cet" , "cest"), /* Central European */ zd ( 100, "met" , "mest"), /* Middle European (bug in old tz versions) */ zd ( 100, "mez" , "mesz"), /* Mittel-Europaeische Zeit */ zd ( 200, "eet" , "eest"), /* Eastern European */ zs ( 530, "ist" ), /* India */ zd ( 900, "jst" , "jdt" ), /* Japan */ zd ( 900, "kst" , "kdt" ), /* Korea */ zd ( 1200, "nzst", "nzdt"), /* New Zealand */ {"lt", 1}, #if 0 /* The following names are duplicates or are not well attested. There are lots more where these came from. */ zs (-1100, "sst" ), /* Samoan */ zd (- 900, "yst" , "ydt" ), /* Yukon - name is no longer used */ zd (- 500, "ast" , "adt" ), /* Acre */ zd (- 400, "wst" , "wdt" ), /* Western Brazil */ zd (- 400, "cst" , "cdt" ), /* Chile */ zd (- 200, "fst" , "fdt" ), /* Fernando de Noronha */ zs ( 000, "wat" ), /* West African */ zs ( 100, "cat" ), /* Central African */ zs ( 200, "sat" ), /* South African */ zd ( 200, "ist" , "idt" ), /* Israel */ zs ( 300, "eat" ), /* East African */ zd ( 300, "msk" , "msd" ), /* Moscow */ zd ( 330, "ist" , "idt" ), /* Iran */ zs ( 800, "hkt" ), /* Hong Kong */ zs ( 800, "sgt" ), /* Singapore */ zd ( 800, "cst" , "cdt" ), /* China */ zd ( 800, "wst" , "wst" ), /* Western Australia */ zd ( 930, "cst" , "cst" ), /* Central Australia */ zs ( 1000, "gst" ), /* Guam */ zd ( 1000, "est" , "est" ), /* Eastern Australia */ #endif {"", -1} }; /* Look for a prefix of S in TABLE, returning val for first matching entry. */ static int lookup (char const *s, struct name_val const table[]) { int j; char buf[NAME_LENGTH_MAXIMUM]; for (j = 0; j < NAME_LENGTH_MAXIMUM; j++) { unsigned char c = *s++; if (! ISALPHA (c)) { buf[j] = '\0'; break; } buf[j] = ISUPPER (c) ? tolower (c) : c; } for (;; table++) for (j = 0; ; j++) if (j == NAME_LENGTH_MAXIMUM || ! table[0].name[j]) return table[0].val; else if (buf[j] != table[0].name[j]) break; } /* Set *T to ``undefined'' values. */ static void undefine (struct partime *t) { t->tm.tm_sec = t->tm.tm_min = t->tm.tm_hour = t->tm.tm_mday = t->tm.tm_mon = t->tm.tm_year = t->tm.tm_wday = t->tm.tm_yday = t->ymodulus = t->yweek = TM_UNDEFINED; t->zone = TM_UNDEFINED_ZONE; } /* Array of patterns to look for in a date string. Order is important: we look for the first matching pattern whose values do not contradict values that we already know about. See `parse_pattern_letter' below for the meaning of the pattern codes. */ static char const *const patterns[] = { /* These traditional patterns must come first, to prevent an ISO 8601 format from misinterpreting their prefixes. */ "E_n_y", "x", /* RFC 822 */ "E_n", "n_E", "n", "t:m:s_A", "t:m_A", "t_A", /* traditional */ "y/N/D$", /* traditional RCS */ /* ISO 8601:1988 formats, generalized a bit. */ "y-N-D$", "4ND$", "Y-N$", "RND$", "-R=N$", "-R$", "--N=D$", "N=DT", "--N$", "---D$", "DT", "Y-d$", "4d$", "R=d$", "-d$", "dT", "y-W-X", "yWX", "y=W", "-r-W-X", "r-W-XT", "-rWX", "rWXT", "-W=X", "W=XT", "-W", "-w-X", "w-XT", "---X$", "XT", "4$", "T", "h:m:s$", "hms$", "h:m$", "hm$", "h$", "-m:s$", "-ms$", "-m$", "--s$", "Y", "Z", 0 }; /* Parse an initial prefix of STR, setting *T accordingly. Return the first character after the prefix, or 0 if it couldn't be parsed. Start with pattern *PI; if success, set *PI to the next pattern to try. Set *PI to -1 if we know there are no more patterns to try; if *PI is initially negative, give up immediately. */ static char const * parse_prefix (char const *str, struct partime *t, int *pi) { int i = *pi; char const *pat; unsigned char c; if (i < 0) return 0; /* Remove initial noise. */ while (! ISALNUM (c = *str) && c != '-' && c != '+') { if (! c) { undefine (t); *pi = -1; return str; } str++; } /* Try a pattern until one succeeds. */ while ((pat = patterns[i++]) != 0) { char const *s = str; undefine (t); do { if (! (c = *pat++)) { *pi = i; return s; } } while ((s = parse_pattern_letter (s, c, t)) != 0); } return 0; } /* Parse an initial prefix of S of length DIGITS; it must be a number. Store the parsed number into *RES. Return the first character after the prefix, or 0 if it wasn't parsed. */ static char const * parse_fixed (char const *s, int digits, int *res) { int n = 0; char const *lim = s + digits; while (s < lim) { unsigned d = *s++ - '0'; if (9 < d) return 0; n = 10 * n + d; } *res = n; return s; } /* Parse an initial prefix of S of length DIGITS; it must be a number in the range LO through HI. Store the parsed number into *RES. Return the first character after the prefix, or 0 if it wasn't parsed. */ static char const * parse_ranged (char const *s, int digits, int lo, int hi, int *res) { s = parse_fixed (s, digits, res); return s && lo <= *res && *res <= hi ? s : 0; } /* Parse an initial prefix of S of length DIGITS; it must be a number in the range LO through HI and it may be followed by a fraction to be computed using RESOLUTION. Store the parsed number into *RES; store the fraction times RESOLUTION, rounded to the nearest integer, into *FRES. Return the first character after the prefix, or 0 if it wasn't parsed. */ static char const * parse_decimal (char const *s, int digits, int lo, int hi, int resolution, int *res, int *fres) { s = parse_fixed (s, digits, res); if (s && lo <= *res && *res <= hi) { int f = 0; if ((s[0] == ',' || s[0] == '.') && ISDIGIT (s[1])) { char const *s1 = ++s; int num10 = 0, denom10 = 10, product; while (ISDIGIT (*++s)) { int d = denom10 * 10; if (d / 10 != denom10) return 0; /* overflow */ denom10 = d; } s = parse_fixed (s1, (int) (s - s1), &num10); product = num10 * resolution; f = (product + (denom10 >> 1)) / denom10; f -= f & (product % denom10 == denom10 >> 1); /* round to even */ if (f < 0 || product/resolution != num10) return 0; /* overflow */ } *fres = f; return s; } return 0; } /* Parse an initial prefix of S; it must denote a time zone. Set *ZONE to the number of seconds east of GMT, or to TM_LOCAL_ZONE if it is the local time zone. Return the first character after the prefix, or 0 if it wasn't parsed. */ char * parzone (char const *s, long *zone) { char sign; int hh, mm, ss; int minutesEastOfUTC; long offset, z; /* The formats are LT, n, n DST, nDST, no, o where n is a time zone name and o is a time zone offset of the form [-+]hh[:mm[:ss]]. */ switch (*s) { case '-': case '+': z = 0; break; default: minutesEastOfUTC = lookup (s, zone_names); if (minutesEastOfUTC == -1) return 0; /* Don't bother to check rest of spelling. */ while (ISALPHA ((unsigned char) *s)) s++; /* Don't modify LT. */ if (minutesEastOfUTC == 1) { *zone = TM_LOCAL_ZONE; return (char *) s; } z = minutesEastOfUTC * 60L; /* Look for trailing " DST". */ if ((s[-1] == 'T' || s[-1] == 't') && (s[-2] == 'S' || s[-2] == 's') && (s[-3] == 'D' || s[-3] == 'd')) goto trailing_dst; while (ISSPACE ((unsigned char) *s)) s++; if ((s[0] == 'D' || s[0] == 'd') && (s[1] == 'S' || s[1] == 's') && (s[2] == 'T' || s[2] == 't')) { s += 3; trailing_dst: *zone = z + 60*60; return (char *) s; } switch (*s) { case '-': case '+': break; default: *zone = z; return (char *) s; } break; } sign = *s++; if (! (s = parse_ranged (s, 2, 0, 23, &hh))) return 0; mm = ss = 0; if (*s == ':') s++; if (ISDIGIT (*s)) { if (! (s = parse_ranged (s, 2, 0, 59, &mm))) return 0; if (*s == ':' && s[-3] == ':' && ISDIGIT (s[1]) && ! (s = parse_ranged (s + 1, 2, 0, 59, &ss))) return 0; } if (ISDIGIT (*s)) return 0; offset = (hh * 60 + mm) * 60L + ss; *zone = z + (sign == '-' ? -offset : offset); /* ?? Are fractions allowed here? If so, they're not implemented. */ return (char *) s; } /* Parse an initial prefix of S, matching the pattern whose code is C. Set *T accordingly. Return the first character after the prefix, or 0 if it wasn't parsed. */ static char const * parse_pattern_letter (char const *s, int c, struct partime *t) { switch (c) { case '$': /* The next character must be a non-digit. */ if (ISDIGIT (*s)) return 0; break; case '-': case '/': case ':': /* These characters stand for themselves. */ if (*s++ != c) return 0; break; case '4': /* 4-digit year */ s = parse_fixed (s, 4, &t->tm.tm_year); break; case '=': /* optional '-' */ s += *s == '-'; break; case 'A': /* AM or PM */ /* This matches the regular expression [AaPp][Mm]?. It must not be followed by a letter or digit; otherwise it would match prefixes of strings like "PST". */ switch (*s++) { case 'A': case 'a': if (t->tm.tm_hour == 12) t->tm.tm_hour = 0; break; case 'P': case 'p': if (t->tm.tm_hour != 12) t->tm.tm_hour += 12; break; default: return 0; } switch (*s) { case 'M': case 'm': s++; break; } if (ISALNUM ((unsigned char) *s)) return 0; break; case 'D': /* day of month [01-31] */ s = parse_ranged (s, 2, 1, 31, &t->tm.tm_mday); break; case 'd': /* day of year [001-366] */ s = parse_ranged (s, 3, 1, 366, &t->tm.tm_yday); t->tm.tm_yday--; break; case 'E': /* extended day of month [1-9, 01-31] */ s = parse_ranged (s, (ISDIGIT (s[0]) && ISDIGIT (s[1])) + 1, 1, 31, &t->tm.tm_mday); break; case 'h': /* hour [00-23 followed by optional fraction] */ { int frac; s = parse_decimal (s, 2, 0, 23, 60 * 60, &t->tm.tm_hour, &frac); t->tm.tm_min = frac / 60; t->tm.tm_sec = frac % 60; } break; case 'm': /* minute [00-59 followed by optional fraction] */ s = parse_decimal (s, 2, 0, 59, 60, &t->tm.tm_min, &t->tm.tm_sec); break; case 'n': /* month name [e.g. "Jan"] */ if (! TM_DEFINED (t->tm.tm_mon = lookup (s, month_names))) return 0; /* Don't bother to check rest of spelling. */ while (ISALPHA ((unsigned char) *s)) s++; break; case 'N': /* month [01-12] */ s = parse_ranged (s, 2, 1, 12, &t->tm.tm_mon); t->tm.tm_mon--; break; case 'r': /* year % 10 (remainder in origin-0 decade) [0-9] */ s = parse_fixed (s, 1, &t->tm.tm_year); t->ymodulus = 10; break; case_R: case 'R': /* year % 100 (remainder in origin-0 century) [00-99] */ s = parse_fixed (s, 2, &t->tm.tm_year); t->ymodulus = 100; break; case 's': /* second [00-60 followed by optional fraction] */ { int frac; s = parse_decimal (s, 2, 0, 60, 1, &t->tm.tm_sec, &frac); t->tm.tm_sec += frac; } break; case 'T': /* 'T' or 't' */ switch (*s++) { case 'T': case 't': break; default: return 0; } break; case 't': /* traditional hour [1-9 or 01-12] */ s = parse_ranged (s, (ISDIGIT (s[0]) && ISDIGIT (s[1])) + 1, 1, 12, &t->tm.tm_hour); break; case 'w': /* 'W' or 'w' only (stands for current week) */ switch (*s++) { case 'W': case 'w': break; default: return 0; } break; case 'W': /* 'W' or 'w', followed by a week of year [00-53] */ switch (*s++) { case 'W': case 'w': break; default: return 0; } s = parse_ranged (s, 2, 0, 53, &t->yweek); break; case 'X': /* weekday (1=Mon ... 7=Sun) [1-7] */ s = parse_ranged (s, 1, 1, 7, &t->tm.tm_wday); t->tm.tm_wday--; break; case 'x': /* weekday name [e.g. "Sun"] */ if (! TM_DEFINED (t->tm.tm_wday = lookup (s, weekday_names))) return 0; /* Don't bother to check rest of spelling. */ while (ISALPHA ((unsigned char) *s)) s++; break; case 'y': /* either R or Y */ if (ISDIGIT (s[0]) && ISDIGIT (s[1]) && ! ISDIGIT (s[2])) goto case_R; FALLTHROUGH; case 'Y': /* year in full [4 or more digits] */ { int len = 0; while (ISDIGIT (s[len])) len++; if (len < 4) return 0; s = parse_fixed (s, len, &t->tm.tm_year); } break; case 'Z': /* time zone */ s = parzone (s, &t->zone); break; case '_': /* possibly empty sequence of non-alphanumerics */ while (! ISALNUM ((unsigned char) *s) && *s) s++; break; default: /* bad pattern */ return 0; } return s; } /* If there is no conflict, merge into *T the additional information in *U and return 0. Otherwise do nothing and return -1. */ static int merge_partime (struct partime *t, struct partime const *u) { # define conflict(a,b) ((a) != (b) && TM_DEFINED (a) && TM_DEFINED (b)) if (conflict (t->tm.tm_sec, u->tm.tm_sec) || conflict (t->tm.tm_min, u->tm.tm_min) || conflict (t->tm.tm_hour, u->tm.tm_hour) || conflict (t->tm.tm_mday, u->tm.tm_mday) || conflict (t->tm.tm_mon, u->tm.tm_mon) || conflict (t->tm.tm_year, u->tm.tm_year) || conflict (t->tm.tm_wday, u->tm.tm_yday) || conflict (t->ymodulus, u->ymodulus) || conflict (t->yweek, u->yweek) || (t->zone != u->zone && t->zone != TM_UNDEFINED_ZONE && u->zone != TM_UNDEFINED_ZONE)) return -1; # undef conflict # define merge_(a,b) if (TM_DEFINED (b)) (a) = (b); merge_ (t->tm.tm_sec, u->tm.tm_sec) merge_ (t->tm.tm_min, u->tm.tm_min) merge_ (t->tm.tm_hour, u->tm.tm_hour) merge_ (t->tm.tm_mday, u->tm.tm_mday) merge_ (t->tm.tm_mon, u->tm.tm_mon) merge_ (t->tm.tm_year, u->tm.tm_year) merge_ (t->tm.tm_wday, u->tm.tm_yday) merge_ (t->ymodulus, u->ymodulus) merge_ (t->yweek, u->yweek) # undef merge_ if (u->zone != TM_UNDEFINED_ZONE) t->zone = u->zone; return 0; } /* Parse a date/time prefix of S, putting the parsed result into *T. Return the first character after the prefix. The prefix may contain no useful information; in that case, *T will contain only undefined values. */ char * partime (char const *s, struct partime *t) { struct partime p; undefine (t); while (*s) { int i = 0; char const *s1; do { if (! (s1 = parse_prefix (s, &p, &i))) return (char *) s; } while (merge_partime (t, &p) != 0); s = s1; } return (char *) s; } xdelta-1.2.1/libedsio/partime.h000077500000000000000000000041301525650667300164200ustar00rootroot00000000000000/* Parse a string, yielding a struct partime that describes it. */ /* Copyright 1993, 1994, 1995, 1997 Paul Eggert Distributed under license by the Free Software Foundation, Inc. This file is part of RCS. RCS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. RCS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RCS; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Report problems and direct all questions to: rcs-bugs@cs.purdue.edu */ #define TM_UNDEFINED (-1) #define TM_DEFINED(x) (0 <= (x)) /* #include if you want to use these symbols. */ #define TM_LOCAL_ZONE LONG_MIN #define TM_UNDEFINED_ZONE (LONG_MIN + 1) struct partime { /* This structure describes the parsed time. Only the following tm_* values in it are used: sec, min, hour, mday, mon, year, wday, yday. If TM_UNDEFINED (value), the parser never found the value. The tm_year field is the actual year, not the year - 1900; but see ymodulus below. */ struct tm tm; /* If !TM_UNDEFINED (ymodulus), then tm.tm_year is actually modulo ymodulus. */ int ymodulus; /* Week of year, ISO 8601 style. If TM_UNDEFINED (yweek), the parser never found yweek. Weeks start on Mondays. Week 1 includes Jan 4. */ int yweek; /* Seconds east of UTC; or TM_LOCAL_ZONE or TM_UNDEFINED_ZONE. */ long zone; }; #if defined __STDC__ || has_prototypes # define __PARTIME_P(x) x #else # define __PARTIME_P(x) () #endif char *partime __PARTIME_P ((char const *, struct partime *)); char *parzone __PARTIME_P ((char const *, long *)); xdelta-1.2.1/libedsio/sha.c000077500000000000000000000161611525650667300155340ustar00rootroot00000000000000/* NIST Secure Hash Algorithm */ /* heavily modified by Uwe Hollerbach */ /* from Peter C. Gutmann's implementation as found in */ /* Applied Cryptography by Bruce Schneier */ /* Further modifications to include the "UNRAVEL" stuff, below */ /* This code is in the public domain */ #include "edsio.h" #include #define SHA_BLOCKSIZE 64 #define SHA_DIGESTSIZE 20 /* UNRAVEL should be fastest & biggest */ /* UNROLL_LOOPS should be just as big, but slightly slower */ /* both undefined should be smallest and slowest */ #define UNRAVEL /* #define UNROLL_LOOPS */ /* by default, compile for little-endian machines (Intel, Vax) */ /* change for big-endian machines; for machines which are neither, */ /* you will need to change the definition of maybe_byte_reverse */ #ifndef WORDS_BIGENDIAN /* from config.h */ #define SHA_LITTLE_ENDIAN #endif /* NIST's proposed modification to SHA of 7/11/94 may be */ /* activated by defining USE_MODIFIED_SHA; leave it off for now */ #undef USE_MODIFIED_SHA /* SHA f()-functions */ #define f1(x,y,z) ((x & y) | (~x & z)) #define f2(x,y,z) (x ^ y ^ z) #define f3(x,y,z) ((x & y) | (x & z) | (y & z)) #define f4(x,y,z) (x ^ y ^ z) /* SHA constants */ #define CONST1 0x5a827999L #define CONST2 0x6ed9eba1L #define CONST3 0x8f1bbcdcL #define CONST4 0xca62c1d6L /* 32-bit rotate */ #define ROT32(x,n) ((x << n) | (x >> (32 - n))) /* the generic case, for when the overall rotation is not unraveled */ #define FG(n) \ T = ROT32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n; \ E = D; D = C; C = ROT32(B,30); B = A; A = T /* specific cases, for when the overall rotation is unraveled */ #define FA(n) \ T = ROT32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n; B = ROT32(B,30) #define FB(n) \ E = ROT32(T,5) + f##n(A,B,C) + D + *WP++ + CONST##n; A = ROT32(A,30) #define FC(n) \ D = ROT32(E,5) + f##n(T,A,B) + C + *WP++ + CONST##n; T = ROT32(T,30) #define FD(n) \ C = ROT32(D,5) + f##n(E,T,A) + B + *WP++ + CONST##n; E = ROT32(E,30) #define FE(n) \ B = ROT32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n; D = ROT32(D,30) #define FT(n) \ A = ROT32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n; C = ROT32(C,30) /* do SHA transformation */ static void sha_transform(EdsioSHACtx *ctx) { guint i; guint32 T, A, B, C, D, E, W[80], *WP; for (i = 0; i < 16; ++i) { W[i] = ctx->data[i]; } for (i = 16; i < 80; ++i) { W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]; #ifdef USE_MODIFIED_SHA W[i] = ROT32(W[i], 1); #endif /* USE_MODIFIED_SHA */ } A = ctx->digest[0]; B = ctx->digest[1]; C = ctx->digest[2]; D = ctx->digest[3]; E = ctx->digest[4]; WP = W; #ifdef UNRAVEL FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); ctx->digest[0] += E; ctx->digest[1] += T; ctx->digest[2] += A; ctx->digest[3] += B; ctx->digest[4] += C; #else /* !UNRAVEL */ #ifdef UNROLL_LOOPS FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); #else /* !UNROLL_LOOPS */ for (i = 0; i < 20; ++i) { FG(1); } for (i = 20; i < 40; ++i) { FG(2); } for (i = 40; i < 60; ++i) { FG(3); } for (i = 60; i < 80; ++i) { FG(4); } #endif /* !UNROLL_LOOPS */ ctx->digest[0] += A; ctx->digest[1] += B; ctx->digest[2] += C; ctx->digest[3] += D; ctx->digest[4] += E; #endif /* !UNRAVEL */ } #ifdef SHA_LITTLE_ENDIAN /* change endianness of data */ static void maybe_byte_reverse(guint32 *buffer, guint count) { guint i; guint32 in; count /= sizeof(guint32); for (i = 0; i < count; ++i) { in = *buffer; *buffer++ = ((in << 24) & 0xff000000) | ((in << 8) & 0x00ff0000) | ((in >> 8) & 0x0000ff00) | ((in >> 24) & 0x000000ff); } } #else /* !SHA_LITTLE_ENDIAN */ #define maybe_byte_reverse(a,b) /* do nothing */ #endif /* SHA_LITTLE_ENDIAN */ /* initialize the SHA digest */ void edsio_sha_init(EdsioSHACtx *ctx) { ctx->digest[0] = 0x67452301L; ctx->digest[1] = 0xefcdab89L; ctx->digest[2] = 0x98badcfeL; ctx->digest[3] = 0x10325476L; ctx->digest[4] = 0xc3d2e1f0L; ctx->count_lo = 0L; ctx->count_hi = 0L; ctx->local = 0; } /* update the SHA digest */ void edsio_sha_update(EdsioSHACtx *ctx, const guint8 *buffer, guint count) { guint i; if ((ctx->count_lo + ((guint32) count << 3)) < ctx->count_lo) { ++ctx->count_hi; } ctx->count_lo += (guint32) count << 3; ctx->count_hi += (guint32) count >> 29; if (ctx->local) { i = SHA_BLOCKSIZE - ctx->local; if (i > count) { i = count; } memcpy(((guint8 *) ctx->data) + ctx->local, buffer, i); count -= i; buffer += i; ctx->local += i; if (ctx->local == SHA_BLOCKSIZE) { maybe_byte_reverse(ctx->data, SHA_BLOCKSIZE); sha_transform(ctx); } else { return; } } while (count >= SHA_BLOCKSIZE) { memcpy(ctx->data, buffer, SHA_BLOCKSIZE); buffer += SHA_BLOCKSIZE; count -= SHA_BLOCKSIZE; maybe_byte_reverse(ctx->data, SHA_BLOCKSIZE); sha_transform(ctx); } memcpy(ctx->data, buffer, count); ctx->local = count; } /* finish computing the SHA digest */ void edsio_sha_final(guint8* digest, EdsioSHACtx *ctx) { int count; guint32 lo_bit_count, hi_bit_count; lo_bit_count = ctx->count_lo; hi_bit_count = ctx->count_hi; count = (int) ((lo_bit_count >> 3) & 0x3f); ((guint8 *) ctx->data)[count++] = 0x80; if (count > SHA_BLOCKSIZE - 8) { memset(((guint8 *) ctx->data) + count, 0, SHA_BLOCKSIZE - count); maybe_byte_reverse(ctx->data, SHA_BLOCKSIZE); sha_transform(ctx); memset((guint8 *) ctx->data, 0, SHA_BLOCKSIZE - 8); } else { memset(((guint8 *) ctx->data) + count, 0, SHA_BLOCKSIZE - 8 - count); } maybe_byte_reverse(ctx->data, SHA_BLOCKSIZE); ctx->data[14] = hi_bit_count; ctx->data[15] = lo_bit_count; sha_transform(ctx); memcpy (digest, ctx->digest, 20); } xdelta-1.2.1/libedsio/simple.c000077500000000000000000000073221525650667300162510ustar00rootroot00000000000000/* -*-Mode: C;-*- * $Id: simple.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $ * * Copyright (C) 1998, 1999, Josh MacDonald. * All Rights Reserved. * * Author: Josh MacDonald */ #include "edsio.h" /* Simple Source */ typedef struct _ByteArraySource ByteArraySource; struct _ByteArraySource { SerialSource source; const guint8* in_data; guint in_len; guint read_pos; guint flags; }; static gboolean byte_array_source_close (SerialSource* source); static gboolean byte_array_source_read (SerialSource* source, guint8 *ptr, guint32 len); static void byte_array_source_free (SerialSource* source); SerialSource* edsio_simple_source (const guint8* data, guint len, guint flags) { ByteArraySource* it = g_new0 (ByteArraySource, 1); SerialSource* src = (SerialSource*) it; serializeio_source_init (& it->source, NULL, byte_array_source_close, byte_array_source_read, byte_array_source_free, NULL, NULL); it->in_data = data; it->in_len = len; it->flags = flags; if (flags & SBF_Base64) src = serializeio_base64_source (src); if (flags & SBF_Checksum) src = serializeio_checksum_source (src); if (flags & SBF_Compress) src = serializeio_gzip_source (src); return src; } gboolean byte_array_source_close (SerialSource* source) { (void) source; return TRUE; } gboolean byte_array_source_read (SerialSource* source, guint8 *buf, guint32 len) { ByteArraySource* ssource = (ByteArraySource*) source; if (len + ssource->read_pos > ssource->in_len) { edsio_generate_source_event (EC_EdsioSourceEof, source); return FALSE; } memcpy (buf, ssource->in_data + ssource->read_pos, len); ssource->read_pos += len; return TRUE; } void byte_array_source_free (SerialSource* source) { g_free (source); } /* BASE64 Sink */ typedef struct _ByteArraySink ByteArraySink; struct _ByteArraySink { SerialSink sink; GByteArray* out; gpointer data; guint flags; gboolean free_result; void (* success) (gpointer data, GByteArray* result); }; static gboolean byte_array_sink_close (SerialSink* sink); static gboolean byte_array_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len); static void byte_array_sink_free (SerialSink* sink); SerialSink* edsio_simple_sink (gpointer data, guint flags, gboolean free_result, void (* success) (gpointer data, GByteArray* result), GByteArray **result) { ByteArraySink* it = g_new0 (ByteArraySink, 1); SerialSink* sink = (SerialSink*) it; serializeio_sink_init (&it->sink, NULL, byte_array_sink_close, byte_array_sink_write, byte_array_sink_free, NULL); it->data = data; it->out = g_byte_array_new (); it->flags = flags; it->free_result = free_result; it->success = success; if (result) (*result) = it->out; if (flags & SBF_Base64) sink = serializeio_base64_sink (sink); if (flags & SBF_Checksum) sink = serializeio_checksum_sink (sink); if (flags & SBF_Compress) sink = serializeio_gzip_sink (sink); return sink; } gboolean byte_array_sink_close (SerialSink* sink) { ByteArraySink* ssink = (ByteArraySink*) sink; if (ssink->success) ssink->success (ssink->data, ssink->out); return TRUE; } gboolean byte_array_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len) { ByteArraySink* ssink = (ByteArraySink*) sink; g_byte_array_append (ssink->out, ptr, len); return TRUE; } void byte_array_sink_free (SerialSink* sink) { ByteArraySink* ssink = (ByteArraySink*) sink; if (ssink->out && ssink->free_result) g_byte_array_free (ssink->out, TRUE); g_free (sink); } xdelta-1.2.1/test/000077500000000000000000000000001525650667300137725ustar00rootroot00000000000000xdelta-1.2.1/test/compat/000077500000000000000000000000001525650667300152555ustar00rootroot00000000000000xdelta-1.2.1/test/compat/1.1.4/000077500000000000000000000000001525650667300157165ustar00rootroot00000000000000xdelta-1.2.1/test/compat/1.1.4/README.md000066400000000000000000000015321525650667300171760ustar00rootroot00000000000000# Xdelta 1.1.4 compatibility fixture `change.xdelta` was generated by the pristine Xdelta 1.1.4 source restored in git commit `803cbd3`. That source came from `xdelta-1.1.4.tar.gz`, whose SHA-256 digest is recorded in `HISTORICAL.md`. The SHA-256 digest of `change.xdelta` is: ```text a80817bb8c0d79a5680ca92ef14ee1862c17ab840d7f081e52eca00480f2bb28 ``` The historical source was built in an `amd64` Debian container against GLib 1.2.10 and zlib. No Xdelta source files were modified. GLib 1.2.10 required GNU89 inline semantics and a compiler-compatibility change to its diagnostic use of `G_GNUC_PRETTY_FUNCTION`; neither change affects Xdelta. The fixture establishes one narrow guarantee: current Xdelta can identify and apply this patch produced by Xdelta 1.1.4. It does not establish compatibility with every option or earlier Xdelta 1.0 formats. xdelta-1.2.1/test/compat/1.1.4/change.xdelta000066400000000000000000000004461525650667300203520ustar00rootroot00000000000000%XDZ004% original.txtupdated.txt‹]ËË €0 Ñ{ªpTCK²�HVÙ–Ýó9r̓K®è‹l—D¥Ôæ1¬e¨•p¦õi¢­SN¸`NöòîÃøG…øÆlD°,éY·³e‹m’ÿ€(Ö LÜØ·ÿ6§‘¹½ Ç (patch data)KN¡õQÐD&O9ce original.txt¸iÆ•ó"%èm–%XDZ004%xdelta-1.2.1/test/compat/1.1.4/original.txt000066400000000000000000000011601525650667300202610ustar00rootroot00000000000000Xdelta compatibility fixture This file is deliberately longer than one matching block. The historical encoder should copy most of these lines. Compatibility means that a current decoder can read the old patch. The reconstructed output must match the expected file exactly. alpha: the first unchanged record bravo: the second unchanged record charlie: this record will be changed delta: the fourth unchanged record echo: the fifth unchanged record foxtrot: the sixth unchanged record golf: the seventh unchanged record hotel: the eighth unchanged record india: the ninth unchanged record juliet: the tenth unchanged record xdelta-1.2.1/test/compat/1.1.4/updated.txt000066400000000000000000000013071525650667300201060ustar00rootroot00000000000000Xdelta compatibility fixture This file is deliberately longer than one matching block. The historical encoder should copy most of these lines. Compatibility means that a current decoder can read the old patch. The reconstructed output must match the expected file exactly. alpha: the first unchanged record bravo: the second unchanged record charlie: this record was changed by the historical release delta: the fourth unchanged record echo: the fifth unchanged record foxtrot: the sixth unchanged record golf: the seventh unchanged record hotel: the eighth unchanged record india: the ninth unchanged record juliet: the tenth unchanged record This line was appended before the historical delta was created. xdelta-1.2.1/test/compat/verify.cmake000066400000000000000000000020141525650667300175600ustar00rootroot00000000000000file(REMOVE "${OUTPUT}") execute_process( COMMAND "${XDELTA}" info "${FIXTURE_DIR}/change.xdelta" RESULT_VARIABLE info_result OUTPUT_VARIABLE info_output ERROR_VARIABLE info_error ) if(NOT info_result EQUAL 0) message(FATAL_ERROR "xdelta info failed: ${info_error}") endif() if(NOT info_output MATCHES "patch version 1\\.1") message(FATAL_ERROR "fixture was not recognized as a 1.1 patch: ${info_output}") endif() execute_process( COMMAND "${XDELTA}" patch "${FIXTURE_DIR}/change.xdelta" "${FIXTURE_DIR}/original.txt" "${OUTPUT}" RESULT_VARIABLE patch_result OUTPUT_VARIABLE patch_output ERROR_VARIABLE patch_error ) if(NOT patch_result EQUAL 0) message(FATAL_ERROR "xdelta patch failed: ${patch_output}${patch_error}") endif() execute_process( COMMAND "${CMAKE_COMMAND}" -E compare_files "${FIXTURE_DIR}/updated.txt" "${OUTPUT}" RESULT_VARIABLE compare_result ) if(NOT compare_result EQUAL 0) message(FATAL_ERROR "reconstructed file differs from the expected output") endif() xdelta-1.2.1/xd.ser000077500000000000000000000061751525650667300141550ustar00rootroot00000000000000;; -*- Emacs-Lisp -*- (defmodule xd 3 "xdelta.h" nil) (defimport "libedsio/edsio.ser") (defsertype XdeltaChecksum 1 ((high uint16) (low uint16) ) () ) (defsertype XdeltaIndex 2 ((file_len uint) (file_md5 (bytes 16)) (index (array XdeltaChecksum)) ) () ) (defsertype XdeltaSourceInfo 3 ((name string) (md5 (bytes 16)) (len uint) (isdata boolean) ;;; if true, then its source index is 0 and it is the data segment (sequential boolean) ;;; if true, then offset field is not persistent, but instead ;;; recomputed when loaded as the sum of ;;; previous instruction's length fields, to ;;; indicate a sequential read ) ("guint32 position" "guint32 copies" "guint32 copy_length" "FileHandle *in") ) (defsertype XdeltaControl 7 ((to_md5 (bytes 16)) (to_len uint) (has_data boolean) (source_info (array (ptr XdeltaSourceInfo))) (inst (array XdeltaInstruction)) ) ("GArray *inst_array" "GPtrArray *source_info_array" ) ) (defsertype XdeltaInstruction 8 ((index uint) (offset uint) (length uint) ) ("guint32 output_start") ) ;; rsync stuff (defsertype RsyncIndexElt 9 ((md5 (bytes 16)) (cksum XdeltaChecksum) ) ("SerialRsyncIndexElt* next" "gint match_offset") ) (defsertype RsyncIndex 10 ((seg_len uint) (file_len uint) (file_md5 (bytes 16)) (index (array RsyncIndexElt)) ) ("SerialRsyncIndexElt** table" "guint table_size") ) ;; backward compat, these are the 1.0 defs (defsertype Version0SourceInfo 4 ((md5 (bytes 16)) (real_md5 (bytes 16)) (length uint) ) () ) (defsertype Version0Control 5 ((normalized boolean) (data_len uint) (to_info Version0SourceInfo) (source_info (array (ptr Version0SourceInfo))) (inst (array Version0Instruction)) ) ("GArray *inst_array" "GPtrArray *source_info_array" ) ) (defsertype Version0Instruction 6 ((offset uint) (length uint) ) ("guint8 type" ;; these two fields get packed into length "guint8 index" ) ) ;; events (defetype handle "FileHandle*") (defevent TooFewSources Error () () "Too few input sources") (defevent TooManySources Error () () "Too many input sources") (defevent OutOfRangeSourceIndex Error ((index int)) () "Instruction references out-of-range source index: ${INDEX}") (defevent InvalidControl Error () () "Delta control is corrupt") (defevent InvalidRsyncCache Error () () "The rsync checksum cache is corrupt") (defevent IncompatibleDelta Error () () "The delta was not produced according by the `xdelta delta' command") (defevent StreamChecksumFailed Error ((stream handle) (expected string) (received string)) () "${STREAM}: Checksum validation failed, expected: ${EXPECTED}, received: ${RECEIVED}") (defevent StreamLengthFailed Error ((stream handle) (expected int) (received int)) () "${STREAM}: Length validation failed, expected: ${EXPECTED}, received: ${RECEIVED}") (defevent BackwardCompatibilityMode Information ((version string)) () "Reading a version ${VERSION} delta control") xdelta-1.2.1/xd_edsio.c000077500000000000000000001616341525650667300147730ustar00rootroot00000000000000/* -*-Mode: C;-*- * Copyright (C) 1997, 1998, 1999 Josh MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Author: Josh MacDonald * * This file was AUTOMATICALLY GENERATED using: * * $Id: edsio.el 1.2 Sun, 28 Jan 2007 12:21:11 -0800 jmacd $ */ #include "xdelta.h" #include /* Declarations. */ static const char* Xd_String_event_field_to_string (GenericEvent* ev, gint field); static const char* Xd_HandleIntInt_event_field_to_string (GenericEvent* ev, gint field); static const char* Xd_HandleStringString_event_field_to_string (GenericEvent* ev, gint field); static const char* Xd_Int_event_field_to_string (GenericEvent* ev, gint field); static gboolean unserialize_version0instruction_generic (SerialSource* source, void** object) { SerialVersion0Instruction* result = NULL; if (! unserialize_version0instruction_internal (source, &result)) return FALSE; *object = result; return TRUE; } static gboolean serialize_version0instruction_generic (SerialSink* sink, void* object) { return serialize_version0instruction_obj_internal (sink, object); } static guint serializeio_count_version0instruction_generic (const void* object) { return serializeio_count_version0instruction_obj (object); } static void serializeio_print_version0instruction_generic (void* object, guint indent_spaces) { serializeio_print_version0instruction_obj (object, indent_spaces); } static gboolean unserialize_version0control_generic (SerialSource* source, void** object) { SerialVersion0Control* result = NULL; if (! unserialize_version0control_internal (source, &result)) return FALSE; *object = result; return TRUE; } static gboolean serialize_version0control_generic (SerialSink* sink, void* object) { return serialize_version0control_obj_internal (sink, object); } static guint serializeio_count_version0control_generic (const void* object) { return serializeio_count_version0control_obj (object); } static void serializeio_print_version0control_generic (void* object, guint indent_spaces) { serializeio_print_version0control_obj (object, indent_spaces); } static gboolean unserialize_version0sourceinfo_generic (SerialSource* source, void** object) { SerialVersion0SourceInfo* result = NULL; if (! unserialize_version0sourceinfo_internal (source, &result)) return FALSE; *object = result; return TRUE; } static gboolean serialize_version0sourceinfo_generic (SerialSink* sink, void* object) { return serialize_version0sourceinfo_obj_internal (sink, object); } static guint serializeio_count_version0sourceinfo_generic (const void* object) { return serializeio_count_version0sourceinfo_obj (object); } static void serializeio_print_version0sourceinfo_generic (void* object, guint indent_spaces) { serializeio_print_version0sourceinfo_obj (object, indent_spaces); } static gboolean unserialize_rsyncindex_generic (SerialSource* source, void** object) { SerialRsyncIndex* result = NULL; if (! unserialize_rsyncindex_internal (source, &result)) return FALSE; *object = result; return TRUE; } static gboolean serialize_rsyncindex_generic (SerialSink* sink, void* object) { return serialize_rsyncindex_obj_internal (sink, object); } static guint serializeio_count_rsyncindex_generic (const void* object) { return serializeio_count_rsyncindex_obj (object); } static void serializeio_print_rsyncindex_generic (void* object, guint indent_spaces) { serializeio_print_rsyncindex_obj (object, indent_spaces); } static gboolean unserialize_rsyncindexelt_generic (SerialSource* source, void** object) { SerialRsyncIndexElt* result = NULL; if (! unserialize_rsyncindexelt_internal (source, &result)) return FALSE; *object = result; return TRUE; } static gboolean serialize_rsyncindexelt_generic (SerialSink* sink, void* object) { return serialize_rsyncindexelt_obj_internal (sink, object); } static guint serializeio_count_rsyncindexelt_generic (const void* object) { return serializeio_count_rsyncindexelt_obj (object); } static void serializeio_print_rsyncindexelt_generic (void* object, guint indent_spaces) { serializeio_print_rsyncindexelt_obj (object, indent_spaces); } static gboolean unserialize_xdeltainstruction_generic (SerialSource* source, void** object) { SerialXdeltaInstruction* result = NULL; if (! unserialize_xdeltainstruction_internal (source, &result)) return FALSE; *object = result; return TRUE; } static gboolean serialize_xdeltainstruction_generic (SerialSink* sink, void* object) { return serialize_xdeltainstruction_obj_internal (sink, object); } static guint serializeio_count_xdeltainstruction_generic (const void* object) { return serializeio_count_xdeltainstruction_obj (object); } static void serializeio_print_xdeltainstruction_generic (void* object, guint indent_spaces) { serializeio_print_xdeltainstruction_obj (object, indent_spaces); } static gboolean unserialize_xdeltacontrol_generic (SerialSource* source, void** object) { SerialXdeltaControl* result = NULL; if (! unserialize_xdeltacontrol_internal (source, &result)) return FALSE; *object = result; return TRUE; } static gboolean serialize_xdeltacontrol_generic (SerialSink* sink, void* object) { return serialize_xdeltacontrol_obj_internal (sink, object); } static guint serializeio_count_xdeltacontrol_generic (const void* object) { return serializeio_count_xdeltacontrol_obj (object); } static void serializeio_print_xdeltacontrol_generic (void* object, guint indent_spaces) { serializeio_print_xdeltacontrol_obj (object, indent_spaces); } static gboolean unserialize_xdeltasourceinfo_generic (SerialSource* source, void** object) { SerialXdeltaSourceInfo* result = NULL; if (! unserialize_xdeltasourceinfo_internal (source, &result)) return FALSE; *object = result; return TRUE; } static gboolean serialize_xdeltasourceinfo_generic (SerialSink* sink, void* object) { return serialize_xdeltasourceinfo_obj_internal (sink, object); } static guint serializeio_count_xdeltasourceinfo_generic (const void* object) { return serializeio_count_xdeltasourceinfo_obj (object); } static void serializeio_print_xdeltasourceinfo_generic (void* object, guint indent_spaces) { serializeio_print_xdeltasourceinfo_obj (object, indent_spaces); } static gboolean unserialize_xdeltaindex_generic (SerialSource* source, void** object) { SerialXdeltaIndex* result = NULL; if (! unserialize_xdeltaindex_internal (source, &result)) return FALSE; *object = result; return TRUE; } static gboolean serialize_xdeltaindex_generic (SerialSink* sink, void* object) { return serialize_xdeltaindex_obj_internal (sink, object); } static guint serializeio_count_xdeltaindex_generic (const void* object) { return serializeio_count_xdeltaindex_obj (object); } static void serializeio_print_xdeltaindex_generic (void* object, guint indent_spaces) { serializeio_print_xdeltaindex_obj (object, indent_spaces); } static gboolean unserialize_xdeltachecksum_generic (SerialSource* source, void** object) { SerialXdeltaChecksum* result = NULL; if (! unserialize_xdeltachecksum_internal (source, &result)) return FALSE; *object = result; return TRUE; } static gboolean serialize_xdeltachecksum_generic (SerialSink* sink, void* object) { return serialize_xdeltachecksum_obj_internal (sink, object); } static guint serializeio_count_xdeltachecksum_generic (const void* object) { return serializeio_count_xdeltachecksum_obj (object); } static void serializeio_print_xdeltachecksum_generic (void* object, guint indent_spaces) { serializeio_print_xdeltachecksum_obj (object, indent_spaces); } static void print_spaces (guint n) { guint i; for (i = 0; i < n; i += 1) g_print (" "); } /* initialize this library. */ gboolean xd_edsio_init (void) { static gboolean once = FALSE; static gboolean result = FALSE; if (once) return result; once = TRUE; eventdelivery_initialize_event_def (EC_XdBackwardCompatibilityModeValue, EL_Information, EF_None, "BackwardCompatibilityMode", "Reading a version ${0} delta control", & Xd_String_event_field_to_string); eventdelivery_initialize_event_def (EC_XdStreamLengthFailedValue, EL_Error, EF_None, "StreamLengthFailed", "${0}: Length validation failed, expected: ${1}, received: ${2}", & Xd_HandleIntInt_event_field_to_string); eventdelivery_initialize_event_def (EC_XdStreamChecksumFailedValue, EL_Error, EF_None, "StreamChecksumFailed", "${0}: Checksum validation failed, expected: ${1}, received: ${2}", & Xd_HandleStringString_event_field_to_string); eventdelivery_initialize_event_def (EC_XdIncompatibleDeltaValue, EL_Error, EF_None, "IncompatibleDelta", "The delta was not produced according by the `xdelta delta' command", NULL); eventdelivery_initialize_event_def (EC_XdInvalidRsyncCacheValue, EL_Error, EF_None, "InvalidRsyncCache", "The rsync checksum cache is corrupt", NULL); eventdelivery_initialize_event_def (EC_XdInvalidControlValue, EL_Error, EF_None, "InvalidControl", "Delta control is corrupt", NULL); eventdelivery_initialize_event_def (EC_XdOutOfRangeSourceIndexValue, EL_Error, EF_None, "OutOfRangeSourceIndex", "Instruction references out-of-range source index: ${0}", & Xd_Int_event_field_to_string); eventdelivery_initialize_event_def (EC_XdTooManySourcesValue, EL_Error, EF_None, "TooManySources", "Too many input sources", NULL); eventdelivery_initialize_event_def (EC_XdTooFewSourcesValue, EL_Error, EF_None, "TooFewSources", "Too few input sources", NULL); serializeio_initialize_type ("ST_Version0Instruction", ST_Version0Instruction, &unserialize_version0instruction_generic, &serialize_version0instruction_generic, &serializeio_count_version0instruction_generic, &serializeio_print_version0instruction_generic); serializeio_initialize_type ("ST_Version0Control", ST_Version0Control, &unserialize_version0control_generic, &serialize_version0control_generic, &serializeio_count_version0control_generic, &serializeio_print_version0control_generic); serializeio_initialize_type ("ST_Version0SourceInfo", ST_Version0SourceInfo, &unserialize_version0sourceinfo_generic, &serialize_version0sourceinfo_generic, &serializeio_count_version0sourceinfo_generic, &serializeio_print_version0sourceinfo_generic); serializeio_initialize_type ("ST_RsyncIndex", ST_RsyncIndex, &unserialize_rsyncindex_generic, &serialize_rsyncindex_generic, &serializeio_count_rsyncindex_generic, &serializeio_print_rsyncindex_generic); serializeio_initialize_type ("ST_RsyncIndexElt", ST_RsyncIndexElt, &unserialize_rsyncindexelt_generic, &serialize_rsyncindexelt_generic, &serializeio_count_rsyncindexelt_generic, &serializeio_print_rsyncindexelt_generic); serializeio_initialize_type ("ST_XdeltaInstruction", ST_XdeltaInstruction, &unserialize_xdeltainstruction_generic, &serialize_xdeltainstruction_generic, &serializeio_count_xdeltainstruction_generic, &serializeio_print_xdeltainstruction_generic); serializeio_initialize_type ("ST_XdeltaControl", ST_XdeltaControl, &unserialize_xdeltacontrol_generic, &serialize_xdeltacontrol_generic, &serializeio_count_xdeltacontrol_generic, &serializeio_print_xdeltacontrol_generic); serializeio_initialize_type ("ST_XdeltaSourceInfo", ST_XdeltaSourceInfo, &unserialize_xdeltasourceinfo_generic, &serialize_xdeltasourceinfo_generic, &serializeio_count_xdeltasourceinfo_generic, &serializeio_print_xdeltasourceinfo_generic); serializeio_initialize_type ("ST_XdeltaIndex", ST_XdeltaIndex, &unserialize_xdeltaindex_generic, &serialize_xdeltaindex_generic, &serializeio_count_xdeltaindex_generic, &serializeio_print_xdeltaindex_generic); serializeio_initialize_type ("ST_XdeltaChecksum", ST_XdeltaChecksum, &unserialize_xdeltachecksum_generic, &serialize_xdeltachecksum_generic, &serializeio_count_xdeltachecksum_generic, &serializeio_print_xdeltachecksum_generic); edsio_library_register (3, "xd"); result = TRUE; return TRUE; } /* XdeltaChecksum Count */ guint serializeio_count_xdeltachecksum (guint16 high, guint16 low) { guint size = sizeof (SerialXdeltaChecksum); (void) high; (void) low; ALIGN_8 (size); ALIGN_8 (size); ALIGN_8 (size); return size; } guint serializeio_count_xdeltachecksum_obj (SerialXdeltaChecksum const* obj) { return serializeio_count_xdeltachecksum (obj->high, obj->low); } /* XdeltaChecksum Print */ void serializeio_print_xdeltachecksum_obj (SerialXdeltaChecksum* obj, guint indent_spaces) { print_spaces (indent_spaces); g_print ("[ST_XdeltaChecksum]\n"); print_spaces (indent_spaces); g_print ("high = "); g_print ("%d\n", obj->high); print_spaces (indent_spaces); g_print ("low = "); g_print ("%d\n", obj->low); } /* XdeltaChecksum Serialize */ gboolean serialize_xdeltachecksum_internal (SerialSink *sink, guint16 high, guint16 low) { if (! (* sink->next_uint16) (sink, high)) goto bail; if (! (* sink->next_uint16) (sink, low)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_xdeltachecksum_obj_internal (SerialSink *sink, SerialXdeltaChecksum* obj) { return serialize_xdeltachecksum_internal (sink, obj->high, obj->low); } gboolean serialize_xdeltachecksum (SerialSink *sink, guint16 high, guint16 low) { if (! (* sink->sink_type) (sink, ST_XdeltaChecksum, serializeio_count_xdeltachecksum (high, low), TRUE)) goto bail; if (! serialize_xdeltachecksum_internal (sink, high, low)) goto bail; if (sink->sink_quantum && ! sink->sink_quantum (sink)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_xdeltachecksum_obj (SerialSink *sink, const SerialXdeltaChecksum* obj) { return serialize_xdeltachecksum (sink, obj->high, obj->low); } /* XdeltaChecksum Unserialize */ gboolean unserialize_xdeltachecksum_internal_noalloc (SerialSource *source, SerialXdeltaChecksum* result) { if (! (* source->next_uint16) (source, &result->high)) goto bail; if (! (* source->next_uint16) (source, &result->low)) goto bail; return TRUE; bail: return FALSE; } gboolean unserialize_xdeltachecksum_internal (SerialSource *source, SerialXdeltaChecksum** result) { SerialXdeltaChecksum* unser; (*result) = NULL; unser = serializeio_source_alloc (source, sizeof (SerialXdeltaChecksum)); if (! unser) goto bail; if (! unserialize_xdeltachecksum_internal_noalloc (source, unser)) goto bail; (*result) = unser; return TRUE; bail: return FALSE; } gboolean unserialize_xdeltachecksum (SerialSource *source, SerialXdeltaChecksum** result) { if ( (* source->source_type) (source, TRUE) != ST_XdeltaChecksum) goto bail; if (! unserialize_xdeltachecksum_internal (source, result)) goto bail; return TRUE; bail: return FALSE; } /* XdeltaIndex Count */ guint serializeio_count_xdeltaindex (guint32 file_len, const guint8 file_md5[16], guint32 index_len, SerialXdeltaChecksum const* index) { guint size = sizeof (SerialXdeltaIndex); (void) file_len; (void) file_md5; (void) index_len; (void) index; ALIGN_8 (size); ALIGN_8 (size); ALIGN_8 (size); { guint32 i; for (i = 0; i < index_len; i += 1) { size += serializeio_count_xdeltachecksum_obj (& (index[i])); } } ALIGN_8 (size); return size; } guint serializeio_count_xdeltaindex_obj (SerialXdeltaIndex const* obj) { return serializeio_count_xdeltaindex (obj->file_len, obj->file_md5, obj->index_len, obj->index); } /* XdeltaIndex Print */ void serializeio_print_xdeltaindex_obj (SerialXdeltaIndex* obj, guint indent_spaces) { print_spaces (indent_spaces); g_print ("[ST_XdeltaIndex]\n"); print_spaces (indent_spaces); g_print ("file_len = "); g_print ("%d\n", obj->file_len); print_spaces (indent_spaces); g_print ("file_md5 = "); serializeio_print_bytes (obj->file_md5, 16); print_spaces (indent_spaces); g_print ("index = "); g_print ("{\n"); { guint32 i; for (i = 0; i < obj->index_len; i += 1) { print_spaces (indent_spaces); g_print ("%d:\n", i); print_spaces (indent_spaces); serializeio_print_xdeltachecksum_obj (& (obj->index[i]), indent_spaces + 2); print_spaces (indent_spaces); ; } } g_print ("}\n"); } /* XdeltaIndex Serialize */ gboolean serialize_xdeltaindex_internal (SerialSink *sink, guint32 file_len, const guint8 file_md5[16], guint32 index_len, SerialXdeltaChecksum const* index) { if (! (* sink->next_uint) (sink, file_len)) goto bail; if (! (* sink->next_bytes_known) (sink, file_md5, 16)) goto bail; { guint32 i; if (! (* sink->next_uint) (sink, index_len)) goto bail; for (i = 0; i < index_len; i += 1) { if (! serialize_xdeltachecksum_internal (sink, (index[i]).high, (index[i]).low)) goto bail; } } return TRUE; bail: return FALSE; } gboolean serialize_xdeltaindex_obj_internal (SerialSink *sink, SerialXdeltaIndex* obj) { return serialize_xdeltaindex_internal (sink, obj->file_len, obj->file_md5, obj->index_len, obj->index); } gboolean serialize_xdeltaindex (SerialSink *sink, guint32 file_len, const guint8 file_md5[16], guint32 index_len, SerialXdeltaChecksum const* index) { if (! (* sink->sink_type) (sink, ST_XdeltaIndex, serializeio_count_xdeltaindex (file_len, file_md5, index_len, index), TRUE)) goto bail; if (! serialize_xdeltaindex_internal (sink, file_len, file_md5, index_len, index)) goto bail; if (sink->sink_quantum && ! sink->sink_quantum (sink)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_xdeltaindex_obj (SerialSink *sink, const SerialXdeltaIndex* obj) { return serialize_xdeltaindex (sink, obj->file_len, obj->file_md5, obj->index_len, obj->index); } /* XdeltaIndex Unserialize */ gboolean unserialize_xdeltaindex_internal_noalloc (SerialSource *source, SerialXdeltaIndex* result) { if (! (* source->next_uint) (source, &result->file_len)) goto bail; if (! (* source->next_bytes_known) (source, result->file_md5, 16)) goto bail; { guint32 i; if (! (* source->next_uint) (source, &result->index_len)) goto bail; if (! (result->index = serializeio_source_alloc (source, sizeof (SerialXdeltaChecksum) * result->index_len))) goto bail; for (i = 0; i < result->index_len; i += 1) { if (! unserialize_xdeltachecksum_internal_noalloc (source, &(result->index[i]))) goto bail; } } return TRUE; bail: return FALSE; } gboolean unserialize_xdeltaindex_internal (SerialSource *source, SerialXdeltaIndex** result) { SerialXdeltaIndex* unser; (*result) = NULL; unser = serializeio_source_alloc (source, sizeof (SerialXdeltaIndex)); if (! unser) goto bail; if (! unserialize_xdeltaindex_internal_noalloc (source, unser)) goto bail; (*result) = unser; return TRUE; bail: return FALSE; } gboolean unserialize_xdeltaindex (SerialSource *source, SerialXdeltaIndex** result) { if ( (* source->source_type) (source, TRUE) != ST_XdeltaIndex) goto bail; if (! unserialize_xdeltaindex_internal (source, result)) goto bail; return TRUE; bail: return FALSE; } /* XdeltaSourceInfo Count */ guint serializeio_count_xdeltasourceinfo (const gchar* name, const guint8 md5[16], guint32 len, gboolean isdata, gboolean sequential) { guint size = sizeof (SerialXdeltaSourceInfo); (void) name; (void) md5; (void) len; (void) isdata; (void) sequential; ALIGN_8 (size); size += strlen (name) + 1; ALIGN_8 (size); ALIGN_8 (size); ALIGN_8 (size); ALIGN_8 (size); ALIGN_8 (size); return size; } guint serializeio_count_xdeltasourceinfo_obj (SerialXdeltaSourceInfo const* obj) { return serializeio_count_xdeltasourceinfo (obj->name, obj->md5, obj->len, obj->isdata, obj->sequential); } /* XdeltaSourceInfo Print */ void serializeio_print_xdeltasourceinfo_obj (SerialXdeltaSourceInfo* obj, guint indent_spaces) { print_spaces (indent_spaces); g_print ("[ST_XdeltaSourceInfo]\n"); print_spaces (indent_spaces); g_print ("name = "); g_print ("%s\n", obj->name); print_spaces (indent_spaces); g_print ("md5 = "); serializeio_print_bytes (obj->md5, 16); print_spaces (indent_spaces); g_print ("len = "); g_print ("%d\n", obj->len); print_spaces (indent_spaces); g_print ("isdata = "); g_print ("%s\n", obj->isdata ? "true" : "false"); print_spaces (indent_spaces); g_print ("sequential = "); g_print ("%s\n", obj->sequential ? "true" : "false"); } /* XdeltaSourceInfo Serialize */ gboolean serialize_xdeltasourceinfo_internal (SerialSink *sink, const gchar* name, const guint8 md5[16], guint32 len, gboolean isdata, gboolean sequential) { if (! (* sink->next_string) (sink, name)) goto bail; if (! (* sink->next_bytes_known) (sink, md5, 16)) goto bail; if (! (* sink->next_uint) (sink, len)) goto bail; if (! (* sink->next_bool) (sink, isdata)) goto bail; if (! (* sink->next_bool) (sink, sequential)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_xdeltasourceinfo_obj_internal (SerialSink *sink, SerialXdeltaSourceInfo* obj) { return serialize_xdeltasourceinfo_internal (sink, obj->name, obj->md5, obj->len, obj->isdata, obj->sequential); } gboolean serialize_xdeltasourceinfo (SerialSink *sink, const gchar* name, const guint8 md5[16], guint32 len, gboolean isdata, gboolean sequential) { if (! (* sink->sink_type) (sink, ST_XdeltaSourceInfo, serializeio_count_xdeltasourceinfo (name, md5, len, isdata, sequential), TRUE)) goto bail; if (! serialize_xdeltasourceinfo_internal (sink, name, md5, len, isdata, sequential)) goto bail; if (sink->sink_quantum && ! sink->sink_quantum (sink)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_xdeltasourceinfo_obj (SerialSink *sink, const SerialXdeltaSourceInfo* obj) { return serialize_xdeltasourceinfo (sink, obj->name, obj->md5, obj->len, obj->isdata, obj->sequential); } /* XdeltaSourceInfo Unserialize */ gboolean unserialize_xdeltasourceinfo_internal_noalloc (SerialSource *source, SerialXdeltaSourceInfo* result) { if (! (* source->next_string) (source, &result->name)) goto bail; if (! (* source->next_bytes_known) (source, result->md5, 16)) goto bail; if (! (* source->next_uint) (source, &result->len)) goto bail; if (! (* source->next_bool) (source, &result->isdata)) goto bail; if (! (* source->next_bool) (source, &result->sequential)) goto bail; return TRUE; bail: return FALSE; } gboolean unserialize_xdeltasourceinfo_internal (SerialSource *source, SerialXdeltaSourceInfo** result) { SerialXdeltaSourceInfo* unser; (*result) = NULL; unser = serializeio_source_alloc (source, sizeof (SerialXdeltaSourceInfo)); if (! unser) goto bail; if (! unserialize_xdeltasourceinfo_internal_noalloc (source, unser)) goto bail; (*result) = unser; return TRUE; bail: return FALSE; } gboolean unserialize_xdeltasourceinfo (SerialSource *source, SerialXdeltaSourceInfo** result) { if ( (* source->source_type) (source, TRUE) != ST_XdeltaSourceInfo) goto bail; if (! unserialize_xdeltasourceinfo_internal (source, result)) goto bail; return TRUE; bail: return FALSE; } /* XdeltaControl Count */ guint serializeio_count_xdeltacontrol (const guint8 to_md5[16], guint32 to_len, gboolean has_data, guint32 source_info_len, SerialXdeltaSourceInfo* const* source_info, guint32 inst_len, SerialXdeltaInstruction const* inst) { guint size = sizeof (SerialXdeltaControl); (void) to_md5; (void) to_len; (void) has_data; (void) source_info_len; (void) source_info; (void) inst_len; (void) inst; ALIGN_8 (size); ALIGN_8 (size); ALIGN_8 (size); ALIGN_8 (size); { guint32 i; for (i = 0; i < source_info_len; i += 1) { size += serializeio_count_xdeltasourceinfo_obj ((source_info[i])) + sizeof (void*); } } ALIGN_8 (size); { guint32 i; for (i = 0; i < inst_len; i += 1) { size += serializeio_count_xdeltainstruction_obj (& (inst[i])); } } ALIGN_8 (size); return size; } guint serializeio_count_xdeltacontrol_obj (SerialXdeltaControl const* obj) { return serializeio_count_xdeltacontrol (obj->to_md5, obj->to_len, obj->has_data, obj->source_info_len, obj->source_info, obj->inst_len, obj->inst); } /* XdeltaControl Print */ void serializeio_print_xdeltacontrol_obj (SerialXdeltaControl* obj, guint indent_spaces) { print_spaces (indent_spaces); g_print ("[ST_XdeltaControl]\n"); print_spaces (indent_spaces); g_print ("to_md5 = "); serializeio_print_bytes (obj->to_md5, 16); print_spaces (indent_spaces); g_print ("to_len = "); g_print ("%d\n", obj->to_len); print_spaces (indent_spaces); g_print ("has_data = "); g_print ("%s\n", obj->has_data ? "true" : "false"); print_spaces (indent_spaces); g_print ("source_info = "); g_print ("{\n"); { guint32 i; for (i = 0; i < obj->source_info_len; i += 1) { print_spaces (indent_spaces); g_print ("%d:\n", i); print_spaces (indent_spaces); serializeio_print_xdeltasourceinfo_obj ((obj->source_info[i]), indent_spaces + 2); print_spaces (indent_spaces); ; } } g_print ("}\n"); print_spaces (indent_spaces); g_print ("inst = "); g_print ("{\n"); { guint32 i; for (i = 0; i < obj->inst_len; i += 1) { print_spaces (indent_spaces); g_print ("%d:\n", i); print_spaces (indent_spaces); serializeio_print_xdeltainstruction_obj (& (obj->inst[i]), indent_spaces + 2); print_spaces (indent_spaces); ; } } g_print ("}\n"); } /* XdeltaControl Serialize */ gboolean serialize_xdeltacontrol_internal (SerialSink *sink, const guint8 to_md5[16], guint32 to_len, gboolean has_data, guint32 source_info_len, SerialXdeltaSourceInfo* const* source_info, guint32 inst_len, SerialXdeltaInstruction const* inst) { if (! (* sink->next_bytes_known) (sink, to_md5, 16)) goto bail; if (! (* sink->next_uint) (sink, to_len)) goto bail; if (! (* sink->next_bool) (sink, has_data)) goto bail; { guint32 i; if (! (* sink->next_uint) (sink, source_info_len)) goto bail; for (i = 0; i < source_info_len; i += 1) { if (! serialize_xdeltasourceinfo_internal (sink, (source_info[i])->name, (source_info[i])->md5, (source_info[i])->len, (source_info[i])->isdata, (source_info[i])->sequential)) goto bail; } } { guint32 i; if (! (* sink->next_uint) (sink, inst_len)) goto bail; for (i = 0; i < inst_len; i += 1) { if (! serialize_xdeltainstruction_internal (sink, (inst[i]).index, (inst[i]).offset, (inst[i]).length)) goto bail; } } return TRUE; bail: return FALSE; } gboolean serialize_xdeltacontrol_obj_internal (SerialSink *sink, SerialXdeltaControl* obj) { return serialize_xdeltacontrol_internal (sink, obj->to_md5, obj->to_len, obj->has_data, obj->source_info_len, obj->source_info, obj->inst_len, obj->inst); } gboolean serialize_xdeltacontrol (SerialSink *sink, const guint8 to_md5[16], guint32 to_len, gboolean has_data, guint32 source_info_len, SerialXdeltaSourceInfo* const* source_info, guint32 inst_len, SerialXdeltaInstruction const* inst) { if (! (* sink->sink_type) (sink, ST_XdeltaControl, serializeio_count_xdeltacontrol (to_md5, to_len, has_data, source_info_len, source_info, inst_len, inst), TRUE)) goto bail; if (! serialize_xdeltacontrol_internal (sink, to_md5, to_len, has_data, source_info_len, source_info, inst_len, inst)) goto bail; if (sink->sink_quantum && ! sink->sink_quantum (sink)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_xdeltacontrol_obj (SerialSink *sink, const SerialXdeltaControl* obj) { return serialize_xdeltacontrol (sink, obj->to_md5, obj->to_len, obj->has_data, obj->source_info_len, obj->source_info, obj->inst_len, obj->inst); } /* XdeltaControl Unserialize */ gboolean unserialize_xdeltacontrol_internal_noalloc (SerialSource *source, SerialXdeltaControl* result) { if (! (* source->next_bytes_known) (source, result->to_md5, 16)) goto bail; if (! (* source->next_uint) (source, &result->to_len)) goto bail; if (! (* source->next_bool) (source, &result->has_data)) goto bail; { guint32 i; if (! (* source->next_uint) (source, &result->source_info_len)) goto bail; if (! (result->source_info = serializeio_source_alloc (source, sizeof (SerialXdeltaSourceInfo*) * result->source_info_len))) goto bail; for (i = 0; i < result->source_info_len; i += 1) { if (! unserialize_xdeltasourceinfo_internal (source, &(result->source_info[i]))) goto bail; } } { guint32 i; if (! (* source->next_uint) (source, &result->inst_len)) goto bail; if (! (result->inst = serializeio_source_alloc (source, sizeof (SerialXdeltaInstruction) * result->inst_len))) goto bail; for (i = 0; i < result->inst_len; i += 1) { if (! unserialize_xdeltainstruction_internal_noalloc (source, &(result->inst[i]))) goto bail; } } return TRUE; bail: return FALSE; } gboolean unserialize_xdeltacontrol_internal (SerialSource *source, SerialXdeltaControl** result) { SerialXdeltaControl* unser; (*result) = NULL; unser = serializeio_source_alloc (source, sizeof (SerialXdeltaControl)); if (! unser) goto bail; if (! unserialize_xdeltacontrol_internal_noalloc (source, unser)) goto bail; (*result) = unser; return TRUE; bail: return FALSE; } gboolean unserialize_xdeltacontrol (SerialSource *source, SerialXdeltaControl** result) { if ( (* source->source_type) (source, TRUE) != ST_XdeltaControl) goto bail; if (! unserialize_xdeltacontrol_internal (source, result)) goto bail; return TRUE; bail: return FALSE; } /* XdeltaInstruction Count */ guint serializeio_count_xdeltainstruction (guint32 index, guint32 offset, guint32 length) { guint size = sizeof (SerialXdeltaInstruction); (void) index; (void) offset; (void) length; ALIGN_8 (size); ALIGN_8 (size); ALIGN_8 (size); ALIGN_8 (size); return size; } guint serializeio_count_xdeltainstruction_obj (SerialXdeltaInstruction const* obj) { return serializeio_count_xdeltainstruction (obj->index, obj->offset, obj->length); } /* XdeltaInstruction Print */ void serializeio_print_xdeltainstruction_obj (SerialXdeltaInstruction* obj, guint indent_spaces) { print_spaces (indent_spaces); g_print ("[ST_XdeltaInstruction]\n"); print_spaces (indent_spaces); g_print ("index = "); g_print ("%d\n", obj->index); print_spaces (indent_spaces); g_print ("offset = "); g_print ("%d\n", obj->offset); print_spaces (indent_spaces); g_print ("length = "); g_print ("%d\n", obj->length); } /* XdeltaInstruction Serialize */ gboolean serialize_xdeltainstruction_internal (SerialSink *sink, guint32 index, guint32 offset, guint32 length) { if (! (* sink->next_uint) (sink, index)) goto bail; if (! (* sink->next_uint) (sink, offset)) goto bail; if (! (* sink->next_uint) (sink, length)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_xdeltainstruction_obj_internal (SerialSink *sink, SerialXdeltaInstruction* obj) { return serialize_xdeltainstruction_internal (sink, obj->index, obj->offset, obj->length); } gboolean serialize_xdeltainstruction (SerialSink *sink, guint32 index, guint32 offset, guint32 length) { if (! (* sink->sink_type) (sink, ST_XdeltaInstruction, serializeio_count_xdeltainstruction (index, offset, length), TRUE)) goto bail; if (! serialize_xdeltainstruction_internal (sink, index, offset, length)) goto bail; if (sink->sink_quantum && ! sink->sink_quantum (sink)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_xdeltainstruction_obj (SerialSink *sink, const SerialXdeltaInstruction* obj) { return serialize_xdeltainstruction (sink, obj->index, obj->offset, obj->length); } /* XdeltaInstruction Unserialize */ gboolean unserialize_xdeltainstruction_internal_noalloc (SerialSource *source, SerialXdeltaInstruction* result) { if (! (* source->next_uint) (source, &result->index)) goto bail; if (! (* source->next_uint) (source, &result->offset)) goto bail; if (! (* source->next_uint) (source, &result->length)) goto bail; return TRUE; bail: return FALSE; } gboolean unserialize_xdeltainstruction_internal (SerialSource *source, SerialXdeltaInstruction** result) { SerialXdeltaInstruction* unser; (*result) = NULL; unser = serializeio_source_alloc (source, sizeof (SerialXdeltaInstruction)); if (! unser) goto bail; if (! unserialize_xdeltainstruction_internal_noalloc (source, unser)) goto bail; (*result) = unser; return TRUE; bail: return FALSE; } gboolean unserialize_xdeltainstruction (SerialSource *source, SerialXdeltaInstruction** result) { if ( (* source->source_type) (source, TRUE) != ST_XdeltaInstruction) goto bail; if (! unserialize_xdeltainstruction_internal (source, result)) goto bail; return TRUE; bail: return FALSE; } /* RsyncIndexElt Count */ guint serializeio_count_rsyncindexelt (const guint8 md5[16], SerialXdeltaChecksum const* cksum) { guint size = sizeof (SerialRsyncIndexElt); (void) md5; (void) cksum; ALIGN_8 (size); ALIGN_8 (size); size += serializeio_count_xdeltachecksum_obj (cksum) - sizeof (SerialXdeltaChecksum); ALIGN_8 (size); return size; } guint serializeio_count_rsyncindexelt_obj (SerialRsyncIndexElt const* obj) { return serializeio_count_rsyncindexelt (obj->md5, &obj->cksum); } /* RsyncIndexElt Print */ void serializeio_print_rsyncindexelt_obj (SerialRsyncIndexElt* obj, guint indent_spaces) { print_spaces (indent_spaces); g_print ("[ST_RsyncIndexElt]\n"); print_spaces (indent_spaces); g_print ("md5 = "); serializeio_print_bytes (obj->md5, 16); print_spaces (indent_spaces); g_print ("cksum = "); g_print ("{\n"); serializeio_print_xdeltachecksum_obj (& obj->cksum, indent_spaces + 2); print_spaces (indent_spaces); ; g_print ("}\n"); } /* RsyncIndexElt Serialize */ gboolean serialize_rsyncindexelt_internal (SerialSink *sink, const guint8 md5[16], SerialXdeltaChecksum const* cksum) { if (! (* sink->next_bytes_known) (sink, md5, 16)) goto bail; if (! serialize_xdeltachecksum_internal (sink, cksum->high, cksum->low)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_rsyncindexelt_obj_internal (SerialSink *sink, SerialRsyncIndexElt* obj) { return serialize_rsyncindexelt_internal (sink, obj->md5, &obj->cksum); } gboolean serialize_rsyncindexelt (SerialSink *sink, const guint8 md5[16], SerialXdeltaChecksum const* cksum) { if (! (* sink->sink_type) (sink, ST_RsyncIndexElt, serializeio_count_rsyncindexelt (md5, cksum), TRUE)) goto bail; if (! serialize_rsyncindexelt_internal (sink, md5, cksum)) goto bail; if (sink->sink_quantum && ! sink->sink_quantum (sink)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_rsyncindexelt_obj (SerialSink *sink, const SerialRsyncIndexElt* obj) { return serialize_rsyncindexelt (sink, obj->md5, &obj->cksum); } /* RsyncIndexElt Unserialize */ gboolean unserialize_rsyncindexelt_internal_noalloc (SerialSource *source, SerialRsyncIndexElt* result) { if (! (* source->next_bytes_known) (source, result->md5, 16)) goto bail; if (! unserialize_xdeltachecksum_internal_noalloc (source, &result->cksum)) goto bail; return TRUE; bail: return FALSE; } gboolean unserialize_rsyncindexelt_internal (SerialSource *source, SerialRsyncIndexElt** result) { SerialRsyncIndexElt* unser; (*result) = NULL; unser = serializeio_source_alloc (source, sizeof (SerialRsyncIndexElt)); if (! unser) goto bail; if (! unserialize_rsyncindexelt_internal_noalloc (source, unser)) goto bail; (*result) = unser; return TRUE; bail: return FALSE; } gboolean unserialize_rsyncindexelt (SerialSource *source, SerialRsyncIndexElt** result) { if ( (* source->source_type) (source, TRUE) != ST_RsyncIndexElt) goto bail; if (! unserialize_rsyncindexelt_internal (source, result)) goto bail; return TRUE; bail: return FALSE; } /* RsyncIndex Count */ guint serializeio_count_rsyncindex (guint32 seg_len, guint32 file_len, const guint8 file_md5[16], guint32 index_len, SerialRsyncIndexElt const* index) { guint size = sizeof (SerialRsyncIndex); (void) seg_len; (void) file_len; (void) file_md5; (void) index_len; (void) index; ALIGN_8 (size); ALIGN_8 (size); ALIGN_8 (size); ALIGN_8 (size); { guint32 i; for (i = 0; i < index_len; i += 1) { size += serializeio_count_rsyncindexelt_obj (& (index[i])); } } ALIGN_8 (size); return size; } guint serializeio_count_rsyncindex_obj (SerialRsyncIndex const* obj) { return serializeio_count_rsyncindex (obj->seg_len, obj->file_len, obj->file_md5, obj->index_len, obj->index); } /* RsyncIndex Print */ void serializeio_print_rsyncindex_obj (SerialRsyncIndex* obj, guint indent_spaces) { print_spaces (indent_spaces); g_print ("[ST_RsyncIndex]\n"); print_spaces (indent_spaces); g_print ("seg_len = "); g_print ("%d\n", obj->seg_len); print_spaces (indent_spaces); g_print ("file_len = "); g_print ("%d\n", obj->file_len); print_spaces (indent_spaces); g_print ("file_md5 = "); serializeio_print_bytes (obj->file_md5, 16); print_spaces (indent_spaces); g_print ("index = "); g_print ("{\n"); { guint32 i; for (i = 0; i < obj->index_len; i += 1) { print_spaces (indent_spaces); g_print ("%d:\n", i); print_spaces (indent_spaces); serializeio_print_rsyncindexelt_obj (& (obj->index[i]), indent_spaces + 2); print_spaces (indent_spaces); ; } } g_print ("}\n"); } /* RsyncIndex Serialize */ gboolean serialize_rsyncindex_internal (SerialSink *sink, guint32 seg_len, guint32 file_len, const guint8 file_md5[16], guint32 index_len, SerialRsyncIndexElt const* index) { if (! (* sink->next_uint) (sink, seg_len)) goto bail; if (! (* sink->next_uint) (sink, file_len)) goto bail; if (! (* sink->next_bytes_known) (sink, file_md5, 16)) goto bail; { guint32 i; if (! (* sink->next_uint) (sink, index_len)) goto bail; for (i = 0; i < index_len; i += 1) { if (! serialize_rsyncindexelt_internal (sink, (index[i]).md5, &(index[i]).cksum)) goto bail; } } return TRUE; bail: return FALSE; } gboolean serialize_rsyncindex_obj_internal (SerialSink *sink, SerialRsyncIndex* obj) { return serialize_rsyncindex_internal (sink, obj->seg_len, obj->file_len, obj->file_md5, obj->index_len, obj->index); } gboolean serialize_rsyncindex (SerialSink *sink, guint32 seg_len, guint32 file_len, const guint8 file_md5[16], guint32 index_len, SerialRsyncIndexElt const* index) { if (! (* sink->sink_type) (sink, ST_RsyncIndex, serializeio_count_rsyncindex (seg_len, file_len, file_md5, index_len, index), TRUE)) goto bail; if (! serialize_rsyncindex_internal (sink, seg_len, file_len, file_md5, index_len, index)) goto bail; if (sink->sink_quantum && ! sink->sink_quantum (sink)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_rsyncindex_obj (SerialSink *sink, const SerialRsyncIndex* obj) { return serialize_rsyncindex (sink, obj->seg_len, obj->file_len, obj->file_md5, obj->index_len, obj->index); } /* RsyncIndex Unserialize */ gboolean unserialize_rsyncindex_internal_noalloc (SerialSource *source, SerialRsyncIndex* result) { if (! (* source->next_uint) (source, &result->seg_len)) goto bail; if (! (* source->next_uint) (source, &result->file_len)) goto bail; if (! (* source->next_bytes_known) (source, result->file_md5, 16)) goto bail; { guint32 i; if (! (* source->next_uint) (source, &result->index_len)) goto bail; if (! (result->index = serializeio_source_alloc (source, sizeof (SerialRsyncIndexElt) * result->index_len))) goto bail; for (i = 0; i < result->index_len; i += 1) { if (! unserialize_rsyncindexelt_internal_noalloc (source, &(result->index[i]))) goto bail; } } return TRUE; bail: return FALSE; } gboolean unserialize_rsyncindex_internal (SerialSource *source, SerialRsyncIndex** result) { SerialRsyncIndex* unser; (*result) = NULL; unser = serializeio_source_alloc (source, sizeof (SerialRsyncIndex)); if (! unser) goto bail; if (! unserialize_rsyncindex_internal_noalloc (source, unser)) goto bail; (*result) = unser; return TRUE; bail: return FALSE; } gboolean unserialize_rsyncindex (SerialSource *source, SerialRsyncIndex** result) { if ( (* source->source_type) (source, TRUE) != ST_RsyncIndex) goto bail; if (! unserialize_rsyncindex_internal (source, result)) goto bail; return TRUE; bail: return FALSE; } /* Version0SourceInfo Count */ guint serializeio_count_version0sourceinfo (const guint8 md5[16], const guint8 real_md5[16], guint32 length) { guint size = sizeof (SerialVersion0SourceInfo); (void) md5; (void) real_md5; (void) length; ALIGN_8 (size); ALIGN_8 (size); ALIGN_8 (size); ALIGN_8 (size); return size; } guint serializeio_count_version0sourceinfo_obj (SerialVersion0SourceInfo const* obj) { return serializeio_count_version0sourceinfo (obj->md5, obj->real_md5, obj->length); } /* Version0SourceInfo Print */ void serializeio_print_version0sourceinfo_obj (SerialVersion0SourceInfo* obj, guint indent_spaces) { print_spaces (indent_spaces); g_print ("[ST_Version0SourceInfo]\n"); print_spaces (indent_spaces); g_print ("md5 = "); serializeio_print_bytes (obj->md5, 16); print_spaces (indent_spaces); g_print ("real_md5 = "); serializeio_print_bytes (obj->real_md5, 16); print_spaces (indent_spaces); g_print ("length = "); g_print ("%d\n", obj->length); } /* Version0SourceInfo Serialize */ gboolean serialize_version0sourceinfo_internal (SerialSink *sink, const guint8 md5[16], const guint8 real_md5[16], guint32 length) { if (! (* sink->next_bytes_known) (sink, md5, 16)) goto bail; if (! (* sink->next_bytes_known) (sink, real_md5, 16)) goto bail; if (! (* sink->next_uint) (sink, length)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_version0sourceinfo_obj_internal (SerialSink *sink, SerialVersion0SourceInfo* obj) { return serialize_version0sourceinfo_internal (sink, obj->md5, obj->real_md5, obj->length); } gboolean serialize_version0sourceinfo (SerialSink *sink, const guint8 md5[16], const guint8 real_md5[16], guint32 length) { if (! (* sink->sink_type) (sink, ST_Version0SourceInfo, serializeio_count_version0sourceinfo (md5, real_md5, length), TRUE)) goto bail; if (! serialize_version0sourceinfo_internal (sink, md5, real_md5, length)) goto bail; if (sink->sink_quantum && ! sink->sink_quantum (sink)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_version0sourceinfo_obj (SerialSink *sink, const SerialVersion0SourceInfo* obj) { return serialize_version0sourceinfo (sink, obj->md5, obj->real_md5, obj->length); } /* Version0SourceInfo Unserialize */ gboolean unserialize_version0sourceinfo_internal_noalloc (SerialSource *source, SerialVersion0SourceInfo* result) { if (! (* source->next_bytes_known) (source, result->md5, 16)) goto bail; if (! (* source->next_bytes_known) (source, result->real_md5, 16)) goto bail; if (! (* source->next_uint) (source, &result->length)) goto bail; return TRUE; bail: return FALSE; } gboolean unserialize_version0sourceinfo_internal (SerialSource *source, SerialVersion0SourceInfo** result) { SerialVersion0SourceInfo* unser; (*result) = NULL; unser = serializeio_source_alloc (source, sizeof (SerialVersion0SourceInfo)); if (! unser) goto bail; if (! unserialize_version0sourceinfo_internal_noalloc (source, unser)) goto bail; (*result) = unser; return TRUE; bail: return FALSE; } gboolean unserialize_version0sourceinfo (SerialSource *source, SerialVersion0SourceInfo** result) { if ( (* source->source_type) (source, TRUE) != ST_Version0SourceInfo) goto bail; if (! unserialize_version0sourceinfo_internal (source, result)) goto bail; return TRUE; bail: return FALSE; } /* Version0Control Count */ guint serializeio_count_version0control (gboolean normalized, guint32 data_len, SerialVersion0SourceInfo const* to_info, guint32 source_info_len, SerialVersion0SourceInfo* const* source_info, guint32 inst_len, SerialVersion0Instruction const* inst) { guint size = sizeof (SerialVersion0Control); (void) normalized; (void) data_len; (void) to_info; (void) source_info_len; (void) source_info; (void) inst_len; (void) inst; ALIGN_8 (size); ALIGN_8 (size); ALIGN_8 (size); size += serializeio_count_version0sourceinfo_obj (to_info) - sizeof (SerialVersion0SourceInfo); ALIGN_8 (size); { guint32 i; for (i = 0; i < source_info_len; i += 1) { size += serializeio_count_version0sourceinfo_obj ((source_info[i])) + sizeof (void*); } } ALIGN_8 (size); { guint32 i; for (i = 0; i < inst_len; i += 1) { size += serializeio_count_version0instruction_obj (& (inst[i])); } } ALIGN_8 (size); return size; } guint serializeio_count_version0control_obj (SerialVersion0Control const* obj) { return serializeio_count_version0control (obj->normalized, obj->data_len, &obj->to_info, obj->source_info_len, obj->source_info, obj->inst_len, obj->inst); } /* Version0Control Print */ void serializeio_print_version0control_obj (SerialVersion0Control* obj, guint indent_spaces) { print_spaces (indent_spaces); g_print ("[ST_Version0Control]\n"); print_spaces (indent_spaces); g_print ("normalized = "); g_print ("%s\n", obj->normalized ? "true" : "false"); print_spaces (indent_spaces); g_print ("data_len = "); g_print ("%d\n", obj->data_len); print_spaces (indent_spaces); g_print ("to_info = "); g_print ("{\n"); serializeio_print_version0sourceinfo_obj (& obj->to_info, indent_spaces + 2); print_spaces (indent_spaces); ; g_print ("}\n"); print_spaces (indent_spaces); g_print ("source_info = "); g_print ("{\n"); { guint32 i; for (i = 0; i < obj->source_info_len; i += 1) { print_spaces (indent_spaces); g_print ("%d:\n", i); print_spaces (indent_spaces); serializeio_print_version0sourceinfo_obj ((obj->source_info[i]), indent_spaces + 2); print_spaces (indent_spaces); ; } } g_print ("}\n"); print_spaces (indent_spaces); g_print ("inst = "); g_print ("{\n"); { guint32 i; for (i = 0; i < obj->inst_len; i += 1) { print_spaces (indent_spaces); g_print ("%d:\n", i); print_spaces (indent_spaces); serializeio_print_version0instruction_obj (& (obj->inst[i]), indent_spaces + 2); print_spaces (indent_spaces); ; } } g_print ("}\n"); } /* Version0Control Serialize */ gboolean serialize_version0control_internal (SerialSink *sink, gboolean normalized, guint32 data_len, SerialVersion0SourceInfo const* to_info, guint32 source_info_len, SerialVersion0SourceInfo* const* source_info, guint32 inst_len, SerialVersion0Instruction const* inst) { if (! (* sink->next_bool) (sink, normalized)) goto bail; if (! (* sink->next_uint) (sink, data_len)) goto bail; if (! serialize_version0sourceinfo_internal (sink, to_info->md5, to_info->real_md5, to_info->length)) goto bail; { guint32 i; if (! (* sink->next_uint) (sink, source_info_len)) goto bail; for (i = 0; i < source_info_len; i += 1) { if (! serialize_version0sourceinfo_internal (sink, (source_info[i])->md5, (source_info[i])->real_md5, (source_info[i])->length)) goto bail; } } { guint32 i; if (! (* sink->next_uint) (sink, inst_len)) goto bail; for (i = 0; i < inst_len; i += 1) { if (! serialize_version0instruction_internal (sink, (inst[i]).offset, (inst[i]).length)) goto bail; } } return TRUE; bail: return FALSE; } gboolean serialize_version0control_obj_internal (SerialSink *sink, SerialVersion0Control* obj) { return serialize_version0control_internal (sink, obj->normalized, obj->data_len, &obj->to_info, obj->source_info_len, obj->source_info, obj->inst_len, obj->inst); } gboolean serialize_version0control (SerialSink *sink, gboolean normalized, guint32 data_len, SerialVersion0SourceInfo const* to_info, guint32 source_info_len, SerialVersion0SourceInfo* const* source_info, guint32 inst_len, SerialVersion0Instruction const* inst) { if (! (* sink->sink_type) (sink, ST_Version0Control, serializeio_count_version0control (normalized, data_len, to_info, source_info_len, source_info, inst_len, inst), TRUE)) goto bail; if (! serialize_version0control_internal (sink, normalized, data_len, to_info, source_info_len, source_info, inst_len, inst)) goto bail; if (sink->sink_quantum && ! sink->sink_quantum (sink)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_version0control_obj (SerialSink *sink, const SerialVersion0Control* obj) { return serialize_version0control (sink, obj->normalized, obj->data_len, &obj->to_info, obj->source_info_len, obj->source_info, obj->inst_len, obj->inst); } /* Version0Control Unserialize */ gboolean unserialize_version0control_internal_noalloc (SerialSource *source, SerialVersion0Control* result) { if (! (* source->next_bool) (source, &result->normalized)) goto bail; if (! (* source->next_uint) (source, &result->data_len)) goto bail; if (! unserialize_version0sourceinfo_internal_noalloc (source, &result->to_info)) goto bail; { guint32 i; if (! (* source->next_uint) (source, &result->source_info_len)) goto bail; if (! (result->source_info = serializeio_source_alloc (source, sizeof (SerialVersion0SourceInfo*) * result->source_info_len))) goto bail; for (i = 0; i < result->source_info_len; i += 1) { if (! unserialize_version0sourceinfo_internal (source, &(result->source_info[i]))) goto bail; } } { guint32 i; if (! (* source->next_uint) (source, &result->inst_len)) goto bail; if (! (result->inst = serializeio_source_alloc (source, sizeof (SerialVersion0Instruction) * result->inst_len))) goto bail; for (i = 0; i < result->inst_len; i += 1) { if (! unserialize_version0instruction_internal_noalloc (source, &(result->inst[i]))) goto bail; } } return TRUE; bail: return FALSE; } gboolean unserialize_version0control_internal (SerialSource *source, SerialVersion0Control** result) { SerialVersion0Control* unser; (*result) = NULL; unser = serializeio_source_alloc (source, sizeof (SerialVersion0Control)); if (! unser) goto bail; if (! unserialize_version0control_internal_noalloc (source, unser)) goto bail; (*result) = unser; return TRUE; bail: return FALSE; } gboolean unserialize_version0control (SerialSource *source, SerialVersion0Control** result) { if ( (* source->source_type) (source, TRUE) != ST_Version0Control) goto bail; if (! unserialize_version0control_internal (source, result)) goto bail; return TRUE; bail: return FALSE; } /* Version0Instruction Count */ guint serializeio_count_version0instruction (guint32 offset, guint32 length) { guint size = sizeof (SerialVersion0Instruction); (void) offset; (void) length; ALIGN_8 (size); ALIGN_8 (size); ALIGN_8 (size); return size; } guint serializeio_count_version0instruction_obj (SerialVersion0Instruction const* obj) { return serializeio_count_version0instruction (obj->offset, obj->length); } /* Version0Instruction Print */ void serializeio_print_version0instruction_obj (SerialVersion0Instruction* obj, guint indent_spaces) { print_spaces (indent_spaces); g_print ("[ST_Version0Instruction]\n"); print_spaces (indent_spaces); g_print ("offset = "); g_print ("%d\n", obj->offset); print_spaces (indent_spaces); g_print ("length = "); g_print ("%d\n", obj->length); } /* Version0Instruction Serialize */ gboolean serialize_version0instruction_internal (SerialSink *sink, guint32 offset, guint32 length) { if (! (* sink->next_uint) (sink, offset)) goto bail; if (! (* sink->next_uint) (sink, length)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_version0instruction_obj_internal (SerialSink *sink, SerialVersion0Instruction* obj) { return serialize_version0instruction_internal (sink, obj->offset, obj->length); } gboolean serialize_version0instruction (SerialSink *sink, guint32 offset, guint32 length) { if (! (* sink->sink_type) (sink, ST_Version0Instruction, serializeio_count_version0instruction (offset, length), TRUE)) goto bail; if (! serialize_version0instruction_internal (sink, offset, length)) goto bail; if (sink->sink_quantum && ! sink->sink_quantum (sink)) goto bail; return TRUE; bail: return FALSE; } gboolean serialize_version0instruction_obj (SerialSink *sink, const SerialVersion0Instruction* obj) { return serialize_version0instruction (sink, obj->offset, obj->length); } /* Version0Instruction Unserialize */ gboolean unserialize_version0instruction_internal_noalloc (SerialSource *source, SerialVersion0Instruction* result) { if (! (* source->next_uint) (source, &result->offset)) goto bail; if (! (* source->next_uint) (source, &result->length)) goto bail; return TRUE; bail: return FALSE; } gboolean unserialize_version0instruction_internal (SerialSource *source, SerialVersion0Instruction** result) { SerialVersion0Instruction* unser; (*result) = NULL; unser = serializeio_source_alloc (source, sizeof (SerialVersion0Instruction)); if (! unser) goto bail; if (! unserialize_version0instruction_internal_noalloc (source, unser)) goto bail; (*result) = unser; return TRUE; bail: return FALSE; } gboolean unserialize_version0instruction (SerialSource *source, SerialVersion0Instruction** result) { if ( (* source->source_type) (source, TRUE) != ST_Version0Instruction) goto bail; if (! unserialize_version0instruction_internal (source, result)) goto bail; return TRUE; bail: return FALSE; } void xd_generate_void_event_internal (XdVoidEventCode _code, const char* _srcfile, gint _srcline) { XdVoidEvent *_e = g_new0 (XdVoidEvent, 1); _e->code = _code.code; _e->srcline = _srcline; _e->srcfile = _srcfile; eventdelivery_event_deliver ((GenericEvent*) _e); } const XdVoidEventCode EC_XdTooFewSources = { EC_XdTooFewSourcesValue }; const XdVoidEventCode EC_XdTooManySources = { EC_XdTooManySourcesValue }; void xd_generate_int_event_internal (XdIntEventCode _code, const char* _srcfile, gint _srcline, int index) { XdIntEvent *_e = g_new0 (XdIntEvent, 1); _e->code = _code.code; _e->srcline = _srcline; _e->srcfile = _srcfile; _e->index = index; eventdelivery_event_deliver ((GenericEvent*) _e); } const char* Xd_Int_event_field_to_string (GenericEvent* ev, gint field) { XdIntEvent* it = (XdIntEvent*) ev; switch (field) { case 0: return eventdelivery_int_to_string (it->index); default: abort (); } } const XdIntEventCode EC_XdOutOfRangeSourceIndex = { EC_XdOutOfRangeSourceIndexValue }; const XdVoidEventCode EC_XdInvalidControl = { EC_XdInvalidControlValue }; const XdVoidEventCode EC_XdInvalidRsyncCache = { EC_XdInvalidRsyncCacheValue }; const XdVoidEventCode EC_XdIncompatibleDelta = { EC_XdIncompatibleDeltaValue }; void xd_generate_handlestringstring_event_internal (XdHandleStringStringEventCode _code, const char* _srcfile, gint _srcline, FileHandle* stream, const char* expected, const char* received) { XdHandleStringStringEvent *_e = g_new0 (XdHandleStringStringEvent, 1); _e->code = _code.code; _e->srcline = _srcline; _e->srcfile = _srcfile; _e->stream = stream; _e->expected = expected; _e->received = received; eventdelivery_event_deliver ((GenericEvent*) _e); } const char* Xd_HandleStringString_event_field_to_string (GenericEvent* ev, gint field) { XdHandleStringStringEvent* it = (XdHandleStringStringEvent*) ev; switch (field) { case 0: return eventdelivery_handle_to_string (it->stream); case 1: return eventdelivery_string_to_string (it->expected); case 2: return eventdelivery_string_to_string (it->received); default: abort (); } } const XdHandleStringStringEventCode EC_XdStreamChecksumFailed = { EC_XdStreamChecksumFailedValue }; void xd_generate_handleintint_event_internal (XdHandleIntIntEventCode _code, const char* _srcfile, gint _srcline, FileHandle* stream, int expected, int received) { XdHandleIntIntEvent *_e = g_new0 (XdHandleIntIntEvent, 1); _e->code = _code.code; _e->srcline = _srcline; _e->srcfile = _srcfile; _e->stream = stream; _e->expected = expected; _e->received = received; eventdelivery_event_deliver ((GenericEvent*) _e); } const char* Xd_HandleIntInt_event_field_to_string (GenericEvent* ev, gint field) { XdHandleIntIntEvent* it = (XdHandleIntIntEvent*) ev; switch (field) { case 0: return eventdelivery_handle_to_string (it->stream); case 1: return eventdelivery_int_to_string (it->expected); case 2: return eventdelivery_int_to_string (it->received); default: abort (); } } const XdHandleIntIntEventCode EC_XdStreamLengthFailed = { EC_XdStreamLengthFailedValue }; void xd_generate_string_event_internal (XdStringEventCode _code, const char* _srcfile, gint _srcline, const char* version) { XdStringEvent *_e = g_new0 (XdStringEvent, 1); _e->code = _code.code; _e->srcline = _srcline; _e->srcfile = _srcfile; _e->version = version; eventdelivery_event_deliver ((GenericEvent*) _e); } const char* Xd_String_event_field_to_string (GenericEvent* ev, gint field) { XdStringEvent* it = (XdStringEvent*) ev; switch (field) { case 0: return eventdelivery_string_to_string (it->version); default: abort (); } } const XdStringEventCode EC_XdBackwardCompatibilityMode = { EC_XdBackwardCompatibilityModeValue }; xdelta-1.2.1/xd_edsio.h000077500000000000000000000475711525650667300150030ustar00rootroot00000000000000/* -*-Mode: C;-*- * Copyright (C) 1997, 1998, 1999 Josh MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Author: Josh MacDonald * * This file was AUTOMATICALLY GENERATED using: * * $Id: edsio.el 1.2 Sun, 28 Jan 2007 12:21:11 -0800 jmacd $ */ #include "edsio.h" #include "xdelta.h" #ifndef _XD_EDSIO_H_ #define _XD_EDSIO_H_ #ifdef __cplusplus extern "C" { #endif #include "edsio_edsio.h" /* Initialize this library. */ gboolean xd_edsio_init (void); /* Types defined here. */ /* XdStringEventCode. */ typedef struct _XdStringEventCode XdStringEventCode; struct _XdStringEventCode { gint code; }; typedef struct _XdStringEvent XdStringEvent; struct _XdStringEvent { gint code; const char* srcfile; guint srcline; const char* version; }; /* XdHandleIntIntEventCode. */ typedef struct _XdHandleIntIntEventCode XdHandleIntIntEventCode; struct _XdHandleIntIntEventCode { gint code; }; typedef struct _XdHandleIntIntEvent XdHandleIntIntEvent; struct _XdHandleIntIntEvent { gint code; const char* srcfile; guint srcline; FileHandle* stream; int expected; int received; }; /* XdHandleStringStringEventCode. */ typedef struct _XdHandleStringStringEventCode XdHandleStringStringEventCode; struct _XdHandleStringStringEventCode { gint code; }; typedef struct _XdHandleStringStringEvent XdHandleStringStringEvent; struct _XdHandleStringStringEvent { gint code; const char* srcfile; guint srcline; FileHandle* stream; const char* expected; const char* received; }; /* XdIntEventCode. */ typedef struct _XdIntEventCode XdIntEventCode; struct _XdIntEventCode { gint code; }; typedef struct _XdIntEvent XdIntEvent; struct _XdIntEvent { gint code; const char* srcfile; guint srcline; int index; }; /* XdVoidEventCode. */ typedef struct _XdVoidEventCode XdVoidEventCode; struct _XdVoidEventCode { gint code; }; typedef struct _XdVoidEvent XdVoidEvent; struct _XdVoidEvent { gint code; const char* srcfile; guint srcline; }; typedef struct _SerialVersion0Instruction SerialVersion0Instruction; typedef struct _SerialVersion0Control SerialVersion0Control; typedef struct _SerialVersion0SourceInfo SerialVersion0SourceInfo; typedef struct _SerialRsyncIndex SerialRsyncIndex; typedef struct _SerialRsyncIndexElt SerialRsyncIndexElt; typedef struct _SerialXdeltaInstruction SerialXdeltaInstruction; typedef struct _SerialXdeltaControl SerialXdeltaControl; typedef struct _SerialXdeltaSourceInfo SerialXdeltaSourceInfo; typedef struct _SerialXdeltaIndex SerialXdeltaIndex; typedef struct _SerialXdeltaChecksum SerialXdeltaChecksum; /* Functions declared here. */ /* Serial Types */ enum _SerialXdType { ST_XdeltaChecksum = (1<<(1+EDSIO_LIBRARY_OFFSET_BITS))+3, ST_XdeltaIndex = (1<<(2+EDSIO_LIBRARY_OFFSET_BITS))+3, ST_XdeltaSourceInfo = (1<<(3+EDSIO_LIBRARY_OFFSET_BITS))+3, ST_XdeltaControl = (1<<(7+EDSIO_LIBRARY_OFFSET_BITS))+3, ST_XdeltaInstruction = (1<<(8+EDSIO_LIBRARY_OFFSET_BITS))+3, ST_RsyncIndexElt = (1<<(9+EDSIO_LIBRARY_OFFSET_BITS))+3, ST_RsyncIndex = (1<<(10+EDSIO_LIBRARY_OFFSET_BITS))+3, ST_Version0SourceInfo = (1<<(4+EDSIO_LIBRARY_OFFSET_BITS))+3, ST_Version0Control = (1<<(5+EDSIO_LIBRARY_OFFSET_BITS))+3, ST_Version0Instruction = (1<<(6+EDSIO_LIBRARY_OFFSET_BITS))+3 }; /* XdeltaChecksum Structure */ struct _SerialXdeltaChecksum { guint16 high; guint16 low; }; void serializeio_print_xdeltachecksum_obj (SerialXdeltaChecksum* obj, guint indent_spaces); gboolean unserialize_xdeltachecksum (SerialSource *source, SerialXdeltaChecksum**); gboolean unserialize_xdeltachecksum_internal (SerialSource *source, SerialXdeltaChecksum** ); gboolean unserialize_xdeltachecksum_internal_noalloc (SerialSource *source, SerialXdeltaChecksum* ); gboolean serialize_xdeltachecksum (SerialSink *sink, guint16 high, guint16 low); gboolean serialize_xdeltachecksum_obj (SerialSink *sink, const SerialXdeltaChecksum* obj); gboolean serialize_xdeltachecksum_internal (SerialSink *sink, guint16 high, guint16 low); gboolean serialize_xdeltachecksum_obj_internal (SerialSink *sink, SerialXdeltaChecksum* obj); guint serializeio_count_xdeltachecksum (guint16 high, guint16 low); guint serializeio_count_xdeltachecksum_obj (SerialXdeltaChecksum const* obj); /* XdeltaIndex Structure */ struct _SerialXdeltaIndex { guint32 file_len; guint8 file_md5[16]; guint32 index_len; SerialXdeltaChecksum* index; }; void serializeio_print_xdeltaindex_obj (SerialXdeltaIndex* obj, guint indent_spaces); gboolean unserialize_xdeltaindex (SerialSource *source, SerialXdeltaIndex**); gboolean unserialize_xdeltaindex_internal (SerialSource *source, SerialXdeltaIndex** ); gboolean unserialize_xdeltaindex_internal_noalloc (SerialSource *source, SerialXdeltaIndex* ); gboolean serialize_xdeltaindex (SerialSink *sink, guint32 file_len, const guint8 file_md5[16], guint32 index_len, SerialXdeltaChecksum const* index); gboolean serialize_xdeltaindex_obj (SerialSink *sink, const SerialXdeltaIndex* obj); gboolean serialize_xdeltaindex_internal (SerialSink *sink, guint32 file_len, const guint8 file_md5[16], guint32 index_len, SerialXdeltaChecksum const* index); gboolean serialize_xdeltaindex_obj_internal (SerialSink *sink, SerialXdeltaIndex* obj); guint serializeio_count_xdeltaindex (guint32 file_len, const guint8 file_md5[16], guint32 index_len, SerialXdeltaChecksum const* index); guint serializeio_count_xdeltaindex_obj (SerialXdeltaIndex const* obj); /* XdeltaSourceInfo Structure */ struct _SerialXdeltaSourceInfo { const gchar* name; guint8 md5[16]; guint32 len; gboolean isdata; gboolean sequential; guint32 position; guint32 copies; guint32 copy_length; FileHandle *in; }; void serializeio_print_xdeltasourceinfo_obj (SerialXdeltaSourceInfo* obj, guint indent_spaces); gboolean unserialize_xdeltasourceinfo (SerialSource *source, SerialXdeltaSourceInfo**); gboolean unserialize_xdeltasourceinfo_internal (SerialSource *source, SerialXdeltaSourceInfo** ); gboolean unserialize_xdeltasourceinfo_internal_noalloc (SerialSource *source, SerialXdeltaSourceInfo* ); gboolean serialize_xdeltasourceinfo (SerialSink *sink, const gchar* name, const guint8 md5[16], guint32 len, gboolean isdata, gboolean sequential); gboolean serialize_xdeltasourceinfo_obj (SerialSink *sink, const SerialXdeltaSourceInfo* obj); gboolean serialize_xdeltasourceinfo_internal (SerialSink *sink, const gchar* name, const guint8 md5[16], guint32 len, gboolean isdata, gboolean sequential); gboolean serialize_xdeltasourceinfo_obj_internal (SerialSink *sink, SerialXdeltaSourceInfo* obj); guint serializeio_count_xdeltasourceinfo (const gchar* name, const guint8 md5[16], guint32 len, gboolean isdata, gboolean sequential); guint serializeio_count_xdeltasourceinfo_obj (SerialXdeltaSourceInfo const* obj); /* XdeltaControl Structure */ struct _SerialXdeltaControl { guint8 to_md5[16]; guint32 to_len; gboolean has_data; guint32 source_info_len; SerialXdeltaSourceInfo** source_info; guint32 inst_len; SerialXdeltaInstruction* inst; GArray *inst_array; GPtrArray *source_info_array; }; void serializeio_print_xdeltacontrol_obj (SerialXdeltaControl* obj, guint indent_spaces); gboolean unserialize_xdeltacontrol (SerialSource *source, SerialXdeltaControl**); gboolean unserialize_xdeltacontrol_internal (SerialSource *source, SerialXdeltaControl** ); gboolean unserialize_xdeltacontrol_internal_noalloc (SerialSource *source, SerialXdeltaControl* ); gboolean serialize_xdeltacontrol (SerialSink *sink, const guint8 to_md5[16], guint32 to_len, gboolean has_data, guint32 source_info_len, SerialXdeltaSourceInfo* const* source_info, guint32 inst_len, SerialXdeltaInstruction const* inst); gboolean serialize_xdeltacontrol_obj (SerialSink *sink, const SerialXdeltaControl* obj); gboolean serialize_xdeltacontrol_internal (SerialSink *sink, const guint8 to_md5[16], guint32 to_len, gboolean has_data, guint32 source_info_len, SerialXdeltaSourceInfo* const* source_info, guint32 inst_len, SerialXdeltaInstruction const* inst); gboolean serialize_xdeltacontrol_obj_internal (SerialSink *sink, SerialXdeltaControl* obj); guint serializeio_count_xdeltacontrol (const guint8 to_md5[16], guint32 to_len, gboolean has_data, guint32 source_info_len, SerialXdeltaSourceInfo* const* source_info, guint32 inst_len, SerialXdeltaInstruction const* inst); guint serializeio_count_xdeltacontrol_obj (SerialXdeltaControl const* obj); /* XdeltaInstruction Structure */ struct _SerialXdeltaInstruction { guint32 index; guint32 offset; guint32 length; guint32 output_start; }; void serializeio_print_xdeltainstruction_obj (SerialXdeltaInstruction* obj, guint indent_spaces); gboolean unserialize_xdeltainstruction (SerialSource *source, SerialXdeltaInstruction**); gboolean unserialize_xdeltainstruction_internal (SerialSource *source, SerialXdeltaInstruction** ); gboolean unserialize_xdeltainstruction_internal_noalloc (SerialSource *source, SerialXdeltaInstruction* ); gboolean serialize_xdeltainstruction (SerialSink *sink, guint32 index, guint32 offset, guint32 length); gboolean serialize_xdeltainstruction_obj (SerialSink *sink, const SerialXdeltaInstruction* obj); gboolean serialize_xdeltainstruction_internal (SerialSink *sink, guint32 index, guint32 offset, guint32 length); gboolean serialize_xdeltainstruction_obj_internal (SerialSink *sink, SerialXdeltaInstruction* obj); guint serializeio_count_xdeltainstruction (guint32 index, guint32 offset, guint32 length); guint serializeio_count_xdeltainstruction_obj (SerialXdeltaInstruction const* obj); /* RsyncIndexElt Structure */ struct _SerialRsyncIndexElt { guint8 md5[16]; SerialXdeltaChecksum cksum; SerialRsyncIndexElt* next; gint match_offset; }; void serializeio_print_rsyncindexelt_obj (SerialRsyncIndexElt* obj, guint indent_spaces); gboolean unserialize_rsyncindexelt (SerialSource *source, SerialRsyncIndexElt**); gboolean unserialize_rsyncindexelt_internal (SerialSource *source, SerialRsyncIndexElt** ); gboolean unserialize_rsyncindexelt_internal_noalloc (SerialSource *source, SerialRsyncIndexElt* ); gboolean serialize_rsyncindexelt (SerialSink *sink, const guint8 md5[16], SerialXdeltaChecksum const* cksum); gboolean serialize_rsyncindexelt_obj (SerialSink *sink, const SerialRsyncIndexElt* obj); gboolean serialize_rsyncindexelt_internal (SerialSink *sink, const guint8 md5[16], SerialXdeltaChecksum const* cksum); gboolean serialize_rsyncindexelt_obj_internal (SerialSink *sink, SerialRsyncIndexElt* obj); guint serializeio_count_rsyncindexelt (const guint8 md5[16], SerialXdeltaChecksum const* cksum); guint serializeio_count_rsyncindexelt_obj (SerialRsyncIndexElt const* obj); /* RsyncIndex Structure */ struct _SerialRsyncIndex { guint32 seg_len; guint32 file_len; guint8 file_md5[16]; guint32 index_len; SerialRsyncIndexElt* index; SerialRsyncIndexElt** table; guint table_size; }; void serializeio_print_rsyncindex_obj (SerialRsyncIndex* obj, guint indent_spaces); gboolean unserialize_rsyncindex (SerialSource *source, SerialRsyncIndex**); gboolean unserialize_rsyncindex_internal (SerialSource *source, SerialRsyncIndex** ); gboolean unserialize_rsyncindex_internal_noalloc (SerialSource *source, SerialRsyncIndex* ); gboolean serialize_rsyncindex (SerialSink *sink, guint32 seg_len, guint32 file_len, const guint8 file_md5[16], guint32 index_len, SerialRsyncIndexElt const* index); gboolean serialize_rsyncindex_obj (SerialSink *sink, const SerialRsyncIndex* obj); gboolean serialize_rsyncindex_internal (SerialSink *sink, guint32 seg_len, guint32 file_len, const guint8 file_md5[16], guint32 index_len, SerialRsyncIndexElt const* index); gboolean serialize_rsyncindex_obj_internal (SerialSink *sink, SerialRsyncIndex* obj); guint serializeio_count_rsyncindex (guint32 seg_len, guint32 file_len, const guint8 file_md5[16], guint32 index_len, SerialRsyncIndexElt const* index); guint serializeio_count_rsyncindex_obj (SerialRsyncIndex const* obj); /* Version0SourceInfo Structure */ struct _SerialVersion0SourceInfo { guint8 md5[16]; guint8 real_md5[16]; guint32 length; }; void serializeio_print_version0sourceinfo_obj (SerialVersion0SourceInfo* obj, guint indent_spaces); gboolean unserialize_version0sourceinfo (SerialSource *source, SerialVersion0SourceInfo**); gboolean unserialize_version0sourceinfo_internal (SerialSource *source, SerialVersion0SourceInfo** ); gboolean unserialize_version0sourceinfo_internal_noalloc (SerialSource *source, SerialVersion0SourceInfo* ); gboolean serialize_version0sourceinfo (SerialSink *sink, const guint8 md5[16], const guint8 real_md5[16], guint32 length); gboolean serialize_version0sourceinfo_obj (SerialSink *sink, const SerialVersion0SourceInfo* obj); gboolean serialize_version0sourceinfo_internal (SerialSink *sink, const guint8 md5[16], const guint8 real_md5[16], guint32 length); gboolean serialize_version0sourceinfo_obj_internal (SerialSink *sink, SerialVersion0SourceInfo* obj); guint serializeio_count_version0sourceinfo (const guint8 md5[16], const guint8 real_md5[16], guint32 length); guint serializeio_count_version0sourceinfo_obj (SerialVersion0SourceInfo const* obj); /* Version0Control Structure */ struct _SerialVersion0Control { gboolean normalized; guint32 data_len; SerialVersion0SourceInfo to_info; guint32 source_info_len; SerialVersion0SourceInfo** source_info; guint32 inst_len; SerialVersion0Instruction* inst; GArray *inst_array; GPtrArray *source_info_array; }; void serializeio_print_version0control_obj (SerialVersion0Control* obj, guint indent_spaces); gboolean unserialize_version0control (SerialSource *source, SerialVersion0Control**); gboolean unserialize_version0control_internal (SerialSource *source, SerialVersion0Control** ); gboolean unserialize_version0control_internal_noalloc (SerialSource *source, SerialVersion0Control* ); gboolean serialize_version0control (SerialSink *sink, gboolean normalized, guint32 data_len, SerialVersion0SourceInfo const* to_info, guint32 source_info_len, SerialVersion0SourceInfo* const* source_info, guint32 inst_len, SerialVersion0Instruction const* inst); gboolean serialize_version0control_obj (SerialSink *sink, const SerialVersion0Control* obj); gboolean serialize_version0control_internal (SerialSink *sink, gboolean normalized, guint32 data_len, SerialVersion0SourceInfo const* to_info, guint32 source_info_len, SerialVersion0SourceInfo* const* source_info, guint32 inst_len, SerialVersion0Instruction const* inst); gboolean serialize_version0control_obj_internal (SerialSink *sink, SerialVersion0Control* obj); guint serializeio_count_version0control (gboolean normalized, guint32 data_len, SerialVersion0SourceInfo const* to_info, guint32 source_info_len, SerialVersion0SourceInfo* const* source_info, guint32 inst_len, SerialVersion0Instruction const* inst); guint serializeio_count_version0control_obj (SerialVersion0Control const* obj); /* Version0Instruction Structure */ struct _SerialVersion0Instruction { guint32 offset; guint32 length; guint8 type; guint8 index; }; void serializeio_print_version0instruction_obj (SerialVersion0Instruction* obj, guint indent_spaces); gboolean unserialize_version0instruction (SerialSource *source, SerialVersion0Instruction**); gboolean unserialize_version0instruction_internal (SerialSource *source, SerialVersion0Instruction** ); gboolean unserialize_version0instruction_internal_noalloc (SerialSource *source, SerialVersion0Instruction* ); gboolean serialize_version0instruction (SerialSink *sink, guint32 offset, guint32 length); gboolean serialize_version0instruction_obj (SerialSink *sink, const SerialVersion0Instruction* obj); gboolean serialize_version0instruction_internal (SerialSink *sink, guint32 offset, guint32 length); gboolean serialize_version0instruction_obj_internal (SerialSink *sink, SerialVersion0Instruction* obj); guint serializeio_count_version0instruction (guint32 offset, guint32 length); guint serializeio_count_version0instruction_obj (SerialVersion0Instruction const* obj); void xd_generate_void_event_internal (XdVoidEventCode code, const char* srcfile, gint srcline); #define xd_generate_void_event(ecode) xd_generate_void_event_internal((ecode),__FILE__,__LINE__) extern const XdVoidEventCode EC_XdTooFewSources; #define EC_XdTooFewSourcesValue ((0< * * $Id: xdapply.c 1.1 Thu, 01 Apr 1999 23:29:11 -0800 jmacd $ */ #include #include #include "xdelta.h" #include "xdeltapriv.h" /* This code used to be more general, but implemented a very * inefficient algorithm. It is sufficient (and efficient) for the * special case below, though, so I'm leaving it. */ static gboolean xdp_copy_delta_region (XdeltaControl *cont, XdeltaOutStream *output_stream) { gint i, l = cont->inst_len; for (i = 0; i < l; i += 1) { const XdeltaInstruction *inst = cont->inst + i; XdeltaSourceInfo* info; if (inst->index >= cont->source_info_len) { xd_generate_int_event (EC_XdOutOfRangeSourceIndex, inst->index); return FALSE; } info = cont->source_info[inst->index]; if (! handle_copy (info->in, output_stream, inst->offset, inst->length)) return FALSE; } return TRUE; } gboolean xdp_apply_delta (XdeltaControl *cont, XdeltaOutStream *res) { if (! xdp_copy_delta_region (cont, res)) return FALSE; if (! handle_close (res, 0)) return FALSE; if (! check_stream_integrity (res, cont->to_md5, cont->to_len)) { guint32 i; /* to better report errors, check if the inputs were invalid now */ for (i = 0; i < cont->source_info_len; i += 1) { check_stream_integrity (cont->source_info[i]->in, cont->source_info[i]->md5, cont->source_info[i]->len); } return FALSE; } return TRUE; } xdelta-1.2.1/xdelta.c000077500000000000000000001056411525650667300144520ustar00rootroot00000000000000/* -*- Mode: C;-*- * * This file is part of XDelta - A binary delta generator. * * Copyright (C) 1997, 1998, 1999, 2001 Josh MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Author: Josh MacDonald * * $Id: xdelta.c 1.4.1.50.1.4 Sun, 28 Jan 2007 12:21:11 -0800 jmacd $ */ #define G_DISABLE_ASSERT #include #include #include #include "xdelta.h" #include "xdeltapriv.h" /* $Format: "const guint xdelta_major_version = $ReleaseMajorVersion$;" $ */ const guint xdelta_major_version = 1; /* $Format: "const guint xdelta_minor_version = $ReleaseMinorVersion$;" $ */ const guint xdelta_minor_version = 2; /* $Format: "const guint xdelta_micro_version = $ReleaseMicroVersion$;" $ */ const guint xdelta_micro_version = 0; /* Control functions. */ static XdeltaControl* control_version_0 (SerialVersion0Control* cont) ; static void control_copy (XdeltaControl* cont, XdeltaSource* src, guint from, guint to); static gboolean control_add_info (XdeltaControl* cont, XdeltaSource* src, const guint8* md5, guint len); #ifndef XDELTA_HARDCODE_SIZE int QUERY_SIZE = 0; int QUERY_SIZE_POW = 0; int QUERY_SIZE_MASK = 0; #endif int xdp_set_query_size_pow (int size_pow) { #ifdef XDELTA_HARDCODE_SIZE (void) size_pow; return XDP_QUERY_HARDCODED; #else int x = 1; int size_log = 0; for (; x != 0; x <<= 1, size_log += 1) { if (x == size_pow) goto good; } return XDP_QUERY_POW2; good: QUERY_SIZE = size_log; QUERY_SIZE_POW = size_pow; QUERY_SIZE_MASK = size_pow-1; return 0; #endif } int xdp_blocksize (void) { if (QUERY_SIZE == 0) { xdp_set_query_size_pow (1<low = low; cksum->high = high; } /* Generate checksums */ static gboolean generate_checksums (XdeltaStream *stream, XdeltaSource *source) { gint total_checksums = handle_length (stream) / QUERY_SIZE_POW; gint checksum_index = 0; XdeltaChecksum cksum; XdeltaChecksum *result; const guint8* segment = NULL, *segment_pointer; gint segment_len; guint segment_page = 0; guint pages; #ifdef DEBUG_CKSUM g_print ("Total base checksums: %d\n", total_checksums); #endif source->ck_count = total_checksums; if (total_checksums == 0) return TRUE; /* This is the in-core FROM checksum table. */ result = g_new (XdeltaChecksum, total_checksums); source->cksums = result; for (pages = handle_pages (stream); segment_page <= pages; segment_page += 1) { segment_len = handle_map_page (stream, segment_page, &segment); if (segment_len < 0) return FALSE; segment_len >>= QUERY_SIZE; for (segment_pointer = segment; segment_len != 0; segment_len -= 1, segment_pointer += QUERY_SIZE_POW) { /* note: cheating at the boundaries */ init_query_checksum (segment_pointer, &cksum); #ifdef DEBUG_CKSUM g_print ("New cksum %04x %04x indices %d-%d\n", cksum.low, cksum.high, checksum_index * QUERY_SIZE_POW, (checksum_index * QUERY_SIZE_POW) + QUERY_SIZE_POW - 1); #endif result[checksum_index++] = cksum; } if (! handle_unmap_page (stream, segment_page, &segment)) return FALSE; } return TRUE; } /* $Format: "#define XDELTA_REQUIRED_VERSION \"$ReleaseMajorVersion$.$ReleaseMinorVersion$.\"" $ */ #define XDELTA_REQUIRED_VERSION "1.2." XdeltaGenerator* __xdp_generator_new (const char* version) { XdeltaGenerator* xg; if (strncmp (version, XDELTA_REQUIRED_VERSION, strlen (XDELTA_REQUIRED_VERSION)) != 0) g_error ("XDelta library version mismatched, compiled for %s, running %s\n", version, XDELTA_VERSION); xg = g_new0 (XdeltaGenerator, 1); xg->sources = g_ptr_array_new (); xg->data_source = g_new0 (XdeltaSource, 1); xg->data_source->name = "(patch data)"; g_ptr_array_add (xg->sources, xg->data_source); return xg; } void xdp_generator_free (XdeltaGenerator *gen) { guint i; for (i = 0; i < gen->sources->len; i += 1) xdp_source_free (gen->sources->pdata[i]); g_ptr_array_free (gen->sources, TRUE); g_free ((void*) gen->table); g_free (gen); } void init_pos (XdeltaStream* str, XdeltaPos* pos) { g_assert (str); memset (pos, 0, sizeof (*pos)); pos->page_size = handle_pagesize (str); } gboolean check_stream_integrity (XdeltaStream* str, const guint8* md5, guint len) { const guint8* act_md5; if (len != handle_length (str)) { xd_generate_handleintint_event (EC_XdStreamLengthFailed, str, len, handle_length (str)); return FALSE; } act_md5 = handle_checksum_md5 (str); if (! act_md5) return FALSE; if (memcmp (md5, act_md5, 16) != 0) { char exp[33], rec[33]; edsio_md5_to_string (md5, exp); edsio_md5_to_string (act_md5, rec); xd_generate_handlestringstring_event (EC_XdStreamChecksumFailed, str, exp, rec); g_free ((void*) act_md5); return FALSE; } g_free ((void*) act_md5); return TRUE; } static gboolean xdp_source_index_read (XdeltaSource *xs, XdeltaStream *index_in) { SerialSource *ss = handle_source (index_in); XdeltaIndex *index; if (! ss) return FALSE; /* TODO: free ss */ if (! unserialize_xdeltaindex (ss, &index)) return FALSE; if (! check_stream_integrity (xs->source_in, index->file_md5, index->file_len)) return FALSE; xs->ck_count = index->index_len; xs->cksums = index->index; return TRUE; } static gboolean xdp_source_index_internal (XdeltaSource *init, XdeltaStream *source_in, XdeltaOutStream *index_out) { if (! generate_checksums (source_in, init)) return FALSE; if (index_out) { const guint8* source_in_md5; SerialSink* sink = handle_sink (index_out, NULL, NULL, NULL, NULL); if (! sink) return FALSE; if (! (source_in_md5 = handle_checksum_md5 (source_in))) return FALSE; if (! serialize_xdeltaindex (sink, handle_length (source_in), source_in_md5, init->ck_count, init->cksums)) { g_free ((void*) source_in_md5); return FALSE; } g_free ((void*) source_in_md5); if (! handle_close (index_out, 0)) return FALSE; } return TRUE; } gboolean xdp_source_index (XdeltaStream *source_in, XdeltaOutStream *index_out) { XdeltaSource* xs = xdp_source_new ("(ignored)", source_in, NULL, index_out); if (xs) { xdp_source_free (xs); return TRUE; } return FALSE; } XdeltaSource* xdp_source_new (const char *name, XdeltaStream *source_in, XdeltaStream *index_in, XdeltaOutStream *index_out) { XdeltaSource* xs = g_new0 (XdeltaSource, 1); xs->source_in = source_in; xs->name = name; g_return_val_if_fail (source_in, NULL); g_return_val_if_fail (index_in ? ! index_out : TRUE, NULL); xs->index_in = index_in; xs->index_out = index_out; xs->source_pos.page_size = handle_pagesize (source_in); return xs; } static gboolean xdp_source_check_index (XdeltaSource *xs) { if (xs->source_index == 0) return TRUE; if (! xs->index_in) return xdp_source_index_internal (xs, xs->source_in, xs->index_out); else return xdp_source_index_read (xs, xs->index_in); } void xdp_source_free (XdeltaSource* xs) { if (xs) { g_free (xs); } } void xdp_source_add (XdeltaGenerator *gen, XdeltaSource *src) { if (gen->table) { g_free ((gpointer)gen->table); gen->table = NULL; } g_ptr_array_add (gen->sources, src); } guint c_hash (const XdeltaChecksum* c) { const guint high = c->high; const guint low = c->low; const guint it = (high >> 2) + (low << 3) + (high << 16); return (it ^ high ^ low); } static gboolean region_insert (XdeltaGenerator* gen, const XdeltaPos *xpos, guint len) { /* This is a little bit cryptic: the xpos.mem + EXPR expression * computes the offset into the current page, which is guaranteed * to be correct since map_page has not occured yet. */ const guint8* buf = xpos->mem + (gen->to_output_pos % xpos->page_size); if (len == 0) return TRUE; #ifdef DEBUG_INST g_print ("insert %d at %d\n", len, gen->to_output_pos); #endif if (! handle_write (gen->data_out, buf, len)) return FALSE; control_copy (gen->control, gen->data_source, gen->data_output_pos, gen->data_output_pos + len); gen->to_output_pos += len; gen->data_output_pos += len; return TRUE; } static gboolean region_copy (XdeltaGenerator* gen, XdeltaSource* src, guint from, guint to) { #ifdef DEBUG_INST g_print ("copy %d - %d (%d) to %d\n", from, to, to-from, gen->to_output_pos); #endif control_copy (gen->control, src, from, to); gen->to_output_pos += (to-from); return TRUE; } gboolean unmap_page (XdeltaStream* stream, XdeltaPos* pos) { if (! pos->mem) return TRUE; if (handle_unmap_page (stream, pos->mem_page, &pos->mem)) { pos->mem = NULL; return TRUE; } return FALSE; } gboolean map_page (XdeltaStream* stream, XdeltaPos* pos) { gint on_page; if (pos->mem && pos->mem_page == pos->page) return TRUE; if (pos->mem) { if (! handle_unmap_page (stream, pos->mem_page, &pos->mem)) return FALSE; pos->mem = NULL; } pos->mem_page = pos->page; on_page = handle_map_page (stream, pos->mem_page, &pos->mem); if (on_page >= 0) { pos->mem_rem = on_page; return TRUE; } return FALSE; } static gboolean try_match (XdeltaGenerator *gen, XdeltaStream *in, XdeltaPos *xpos_ptr, XdeltaSource *src, guint src_offset, gboolean *found) { XdeltaPos xpos = *xpos_ptr; XdeltaPos ypos = src->source_pos; gint rem, remsave; gint match_forward = 0; gint match_backward = 0; gint match_forward_max; gint match_backward_max; guint to_offset = XPOS (xpos); gboolean one_insert = FALSE; *found = FALSE; ypos.page = src_offset / ypos.page_size; ypos.off = src_offset % ypos.page_size; match_forward_max = MIN (handle_length (in) - to_offset, handle_length (src->source_in) - src_offset); match_backward_max = MIN (src_offset, to_offset - gen->to_output_pos); /* Don't allow backward paging */ match_backward_max = MIN (match_backward_max, (gint) xpos.off); /* We're testing against the negative below. */ match_backward_max = - match_backward_max; for (; match_backward > match_backward_max; ) { g_assert (xpos.off != 0); if (ypos.off == 0) { ypos.off = ypos.page_size; ypos.page -= 1; } if (! map_page (src->source_in, &ypos)) goto bail; rem = MIN (xpos.off, ypos.off); rem = MIN (match_backward - match_backward_max, rem); for (; rem > 0; rem -= 1, match_backward -= 1) { if (xpos.mem[xpos.off-1] != ypos.mem[ypos.off-1]) goto doneback; xpos.off -= 1; ypos.off -= 1; } } doneback: xpos.page = to_offset / xpos.page_size; xpos.off = to_offset % xpos.page_size; ypos.page = src_offset / ypos.page_size; ypos.off = src_offset % ypos.page_size; for (; match_forward < match_forward_max; ) { if (! map_page (src->source_in, &ypos)) goto bail; /* Fortunately, if this map happens it means that the match must * be long enough to succeed below, therefore it is safe to write * the insert out now. */ if (! one_insert && xpos.page != xpos.mem_page) { one_insert = TRUE; if (! region_insert (gen, &xpos, (to_offset + match_backward) - gen->to_output_pos)) goto bail; } if (! map_page (in, &xpos)) goto bail; rem = MIN (xpos.mem_rem - xpos.off, ypos.mem_rem - ypos.off); rem = MIN (match_forward_max - match_forward, rem); /* Do a int-wise comparison if the regions are aligned. */ if (rem > (4 * (gint) sizeof (int)) && (xpos.off % sizeof (int)) == (ypos.off % sizeof(int))) { gint is; const int *xi, *yi; for (; xpos.off % sizeof(int); rem -= 1, match_forward += 1) { if (xpos.mem[xpos.off] != ypos.mem[ypos.off]) goto done; xpos.off += 1; ypos.off += 1; } remsave = rem; rem /= sizeof(int); xi = (const int*) (xpos.mem + xpos.off); yi = (const int*) (ypos.mem + ypos.off); is = rem; for (; rem > 0 && *xi == *yi; ) { rem -= 1; xi += 1; yi += 1; } is -= rem; match_forward += is * sizeof(int); xpos.off += is * sizeof(int); ypos.off += is * sizeof(int); rem = (rem * sizeof(int)) + (remsave % sizeof(int)); } for (; rem > 0; rem -= 1, match_forward += 1) { if (xpos.mem[xpos.off] != ypos.mem[ypos.off]) goto done; xpos.off += 1; ypos.off += 1; } FLIP_FORWARD (xpos); FLIP_FORWARD (ypos); } done: if (match_forward - match_backward >= QUERY_SIZE_POW) { *found = TRUE; if (! one_insert) { if (! region_insert (gen, &xpos, (to_offset + match_backward) - gen->to_output_pos)) goto bail; } if (! region_copy (gen, src, src_offset + match_backward, src_offset + match_forward)) goto bail; } else { g_assert (! one_insert); } *xpos_ptr = xpos; src->source_pos = ypos; return TRUE; bail: *xpos_ptr = xpos; src->source_pos = ypos; return FALSE; } static gboolean compute_copies (XdeltaGenerator* gen, XdeltaStream* stream) { XdeltaChecksum cksum; const XdeltaChecksum *source_cksum; const guint8 *segment_pointer; guint source_offset, segment_index, index, prime = gen->table_size; guint source_index; const guint32* table = gen->table; guint16 old_c, new_c; guint save_page, save_off; #ifdef DEBUG_MATCH_PRINT guint i; #endif XdeltaPos xpos; gboolean found; gboolean ret = TRUE; if (handle_length (stream) < QUERY_SIZE_POW) return TRUE; init_pos (stream, &xpos); while (XPOS (xpos) <= (handle_length (stream) - QUERY_SIZE_POW)) { if (!map_page (stream, &xpos)) return FALSE; g_assert (xpos.mem_rem > xpos.off); segment_index = (xpos.mem_rem - xpos.off); if (segment_index < QUERY_SIZE_POW) goto nextpage; segment_index -= QUERY_SIZE_POW; segment_pointer = xpos.mem + xpos.off; init_query_checksum (segment_pointer, &cksum); for (; ; segment_pointer += 1) { #ifdef DEBUG_CKSUM_UPDATE XdeltaChecksum cktest; init_query_checksum (segment_pointer, &cktest); if (cktest.high != cksum.high || cktest.low != cktest.low) abort (); #endif index = c_hash (&cksum) % prime; #ifdef DEBUG_MATCH_PRINT g_print ("%d: searching for match \"", XPOS(xpos)); for (i = 0; i < QUERY_SIZE_POW; i += 1) { if (isprint (segment_pointer[i])) g_print ("%c", segment_pointer[i]); else g_print ("\\0%o", segment_pointer[i]); } g_print ("\"... %s\n", table[index] ? "found" : "notfound"); #endif if (table[index]) { source_index = (table[index] & QUERY_SIZE_MASK) - 1; source_offset = (table[index] >> QUERY_SIZE); source_cksum = ((XdeltaSource*)gen->sources->pdata[source_index])->cksums + source_offset; if (cksum.high == source_cksum->high && cksum.low == source_cksum->low) { save_page = xpos.page; save_off = xpos.off; if (! try_match (gen, stream, &xpos, gen->sources->pdata[source_index], source_offset << QUERY_SIZE, &found)) { ret = FALSE; goto bail; } if (found) { g_assert (xpos.page*xpos.page_size+xpos.off == gen->to_output_pos); goto reenter; } else { xpos.page = save_page; xpos.off = save_off; } } } if (segment_index == 0) goto nextpage; segment_index -= 1; xpos.off += 1; old_c = CHEW(segment_pointer[0]); new_c = CHEW(segment_pointer[QUERY_SIZE_POW]); cksum.low -= old_c; cksum.low += new_c; cksum.high -= old_c << QUERY_SIZE; cksum.high += cksum.low; } nextpage: if (xpos.mem_rem < xpos.page_size) break; xpos.page += 1; xpos.off = 0; if (xpos.page != xpos.mem_page) { if (! region_insert (gen, &xpos, XPOS (xpos) - gen->to_output_pos)) return FALSE; } reenter: (void) 0; } xpos.off = gen->to_output_pos % handle_pagesize (stream); while (gen->to_output_pos < handle_length (stream)) { if (! map_page (stream, &xpos)) return FALSE; if (! region_insert (gen, &xpos, xpos.mem_rem - xpos.off)) ret = FALSE; xpos.off = 0; xpos.page += 1; } bail: if (! unmap_page (stream, &xpos)) return FALSE; return ret; } static gboolean just_output (XdeltaGenerator *gen, XdeltaStream *in) { XdeltaPos pos; init_pos (in, &pos); while (gen->to_output_pos < handle_length (in)) { if (! map_page (in, &pos)) return FALSE; if (! region_insert (gen, &pos, pos.mem_rem - pos.off)) return FALSE; pos.off = 0; pos.page += 1; } if (! unmap_page (in, &pos)) return FALSE; return TRUE; } /* Clobbering decision (see below): * * Algorithm A: Clobber it always (its fast!). The problem * is that this prefers matches at the front of * the file and leads to poor matches at the back * of the file (assuming I insert going backwards). * * Algorithm B: Keep a table of how many times there has * been a clobber at each index i, C[i]. * With probability 1/(C[i]+1), replace the * previous entry. This gives a uniform * probability of each entry surviving. * The problem (supposed) with this * algorithm is that the probabilities * should not be uniform (though uniform is * better than A) because there are more * chances to match a segment at the end of * the file than at the beginning. * * Algorithm C: Give a linear weight to each match * according to it's position in the file * -- number the segments from N down to 1 * starting at the beginning. Same as the * above but with a different weight. The * weight for segment i, match at checksum * offset k, follows. The total number of * checksums in the segment is C_i, * therefore the total checksum count is * C = sum_i (C_i). * Now the interior weight is the (C_i-k) * (the linear assumption) and the total * interior weight is sum_{j=1}^{N}{j}=(N)(N+1)/2 * so the kth segment has interior weight * * [2 (C_i - k)] / [(C_i) (C_i + 1)] * * add in the exterior weight (after * cancelling a C_i): * * w(i,k) = [2 (C_i - k)] / [(C_i + 1) (C)] * * Now, as above, we will compute whether to * keep or replace the current value at the j-th * decision. Let R_j be the running sum of * weights considered so far. R_0 = 0. At the * j-th decision, * * P_ikj(use new value) = w(i,k)/R_{j+1} * R_{j+1} = R_j + w(i,k) */ static gboolean xdp_generate_delta_int (XdeltaGenerator *gen, XdeltaStream *in, XdeltaOutStream *control_out, XdeltaOutStream *data_out) { guint i; gint j, total_from_ck_count = 0, prime = 0, index = 0; gint total_from_len = 0; guint32* table = NULL; (void) control_out; (void) data_out; if (QUERY_SIZE == 0) { xdp_set_query_size_pow (1<sources->len == 0) { xd_generate_void_event (EC_XdTooFewSources); return FALSE; } for (i = 0; i < gen->sources->len; i += 1) { XdeltaSource* src = gen->sources->pdata[i]; src->used = FALSE; src->sequential = TRUE; src->position = 0; src->source_index = i; if (src->source_index != 0) total_from_len += handle_length (src->source_in); } /* QUERY_SIZE_POW is the number of elements freed in the cksum hash * table for storing segment number + (offset/QUERY_SIZE_POW) in. 1 * for the zero + 1 for the data segment */ if (gen->sources->len > (QUERY_SIZE_POW-2)) { xd_generate_void_event (EC_XdTooManySources); return FALSE; } if (handle_length (in) < QUERY_SIZE_POW || total_from_len < QUERY_SIZE_POW) { if (! just_output (gen, in)) return FALSE; } else { for (i = 0; i < gen->sources->len; i += 1) { XdeltaSource* xs = (XdeltaSource*)gen->sources->pdata[i]; if (! xdp_source_check_index (xs)) return FALSE; total_from_ck_count += xs->ck_count; } prime = g_spaced_primes_closest (total_from_ck_count); gen->table = table = g_new0 (guint32, prime); gen->table_size = prime; for (i = 0; i < gen->sources->len; i += 1) { XdeltaSource* xs = (XdeltaSource*)gen->sources->pdata[i]; for (j = xs->ck_count-1; j >= 0; j -= 1) { index = c_hash (xs->cksums + j) % prime; #ifdef DEBUG_HASH gen->hash_entries += 1; if (table[index]) { gen->hash_conflicts += 1; /*regions_similar (gen, i, j, (table[index] & QUERY_SIZE_MASK) - 1, table[index] >> QUERY_SIZE);*/ } #endif /* This is the real code */ table[index] = (j << QUERY_SIZE) + 1 + i; } } #ifdef DEBUG_HASH for (i = 0; i < prime; i += 1) { if (gen->table[i]) gen->hash_fill += 1; } g_print ("*** Hash stats:\n"); g_print ("Hash conflicts: %d\n", gen->hash_conflicts); g_print ("Hash real conflicts: %d\n", gen->hash_real_conflicts); g_print ("Hash real real conflicts: %d\n", gen->hash_real_real_conflicts); g_print ("Hash fill: %d\n", gen->hash_fill); g_print ("Hash size: %d\n", gen->table_size); g_print ("Hash entries: %d\n", gen->hash_entries); g_print ("Hash fill/entries: %f\n", (float)gen->hash_fill/(float)gen->hash_entries); #endif if (! compute_copies (gen, in)) return FALSE; } return TRUE; } XdeltaControl* xdp_generate_delta (XdeltaGenerator *gen, XdeltaStream *in, XdeltaOutStream *control_out, XdeltaOutStream *data_out) { guint i; const guint8* in_md5; const guint8* data_out_md5; gen->data_out = data_out; gen->control_out = control_out; gen->control = control_new (); if (! xdp_generate_delta_int (gen, in, control_out, data_out)) return NULL; if (! handle_close (data_out, 0)) return NULL; if (! (in_md5 = handle_checksum_md5 (in))) return FALSE; if (! (data_out_md5 = handle_checksum_md5 (data_out))) return FALSE; gen->control->has_data = gen->data_source->used; gen->control->inst = &g_array_index (gen->control->inst_array, XdeltaInstruction, 0); gen->control->inst_len = gen->control->inst_array->len; gen->control->to_len = handle_length (in); memcpy (gen->control->to_md5, in_md5, 16); for (i = 0; i < gen->sources->len; i += 1) { XdeltaSource* src = gen->sources->pdata[i]; const guint8* md5; guint len; if (src->source_in) { if (! (md5 = handle_checksum_md5 (src->source_in))) return FALSE; len = handle_length (src->source_in); } else { len = handle_length (data_out); md5 = data_out_md5; } if (! control_add_info (gen->control, src, md5, len)) return NULL; } gen->control->source_info = (XdeltaSourceInfo**) gen->control->source_info_array->pdata; gen->control->source_info_len = gen->control->source_info_array->len; if (control_out && ! xdp_control_write (gen->control, control_out)) return NULL; return gen->control; } /* Below here boring details mostly to do with reading and writing * control. */ XdeltaControl* control_new (void) { XdeltaControl* it = g_new0 (XdeltaControl, 1); it->inst_array = g_array_new (FALSE, FALSE, sizeof (XdeltaInstruction)); it->source_info_array = g_ptr_array_new (); return it; } static void control_reindex (XdeltaControl* cont, XdeltaSource* src) { guint32 i; guint32 new_index = cont->source_info_array->len; for (i = 0; i < cont->inst_len; i += 1) { XdeltaInstruction* inst = cont->inst + i; if (inst->index == src->source_index) inst->index = new_index; } } gboolean control_add_info (XdeltaControl* cont, XdeltaSource* src, const guint8* md5, guint len) { XdeltaSourceInfo* si; if (! src->used) return TRUE; si = g_new0 (XdeltaSourceInfo, 1); si->name = src->name; si->sequential = src->sequential; si->len = len; si->isdata = (src->source_index == 0); memcpy (si->md5, md5, 16); control_reindex (cont, src); g_ptr_array_add (cont->source_info_array, si); return TRUE; } void xdp_control_free (XdeltaControl* cont) { if (cont->source_info_array) g_ptr_array_free (cont->source_info_array, TRUE); if (cont->inst_array) g_array_free (cont->inst_array, TRUE); g_free (cont); } void control_copy (XdeltaControl* cont, XdeltaSource* src, guint from, guint to) { XdeltaInstruction i; if (cont->inst_array->len > 0) { XdeltaInstruction* oi = & g_array_index (cont->inst_array, XdeltaInstruction, cont->inst_array->len-1); if (oi->index == src->source_index && (oi->offset + oi->length) == from) { oi->length += (to - from); return; } } i.index = src->source_index; i.offset = from; i.length = to - from; src->used = TRUE; if (src->position != from) src->sequential = FALSE; src->position = to; g_array_append_val (cont->inst_array, i); } #ifdef DEBUG_CONT static void print_info (XdeltaSourceInfo* si) { char md5str[33]; edsio_md5_to_string (si->md5, md5str); g_print (" ** info\n"); g_print (" md5: %s\n", md5str); g_print (" len: %d\n", si->length); } static void print_inst (XdeltaInstruction* i) { switch (i->type) { case INST_TYPE_COPY: g_print (" copy (%c) %d-%d (%d) from %d\n", i->type, i->offset, i->offset + i->length, i->length, i->index); break; case INST_TYPE_INSERT: g_print (" insert %d\n", i->length); break; } } static void xdp_print_control (XdeltaControl *cont) { guint32 i; g_print ("*** control\n"); g_print (" data len: %d\n", cont->data_len); print_info (&cont->to_info); g_print (" source info len: %d\n", cont->source_info_len); for (i = 0; i < cont->source_info_len; i += 1) print_info (cont->source_info[i]); g_print (" inst len: %d\n", cont->inst_len); for (i = 0; i < cont->inst_len; i += 1) print_inst (cont->inst + i); } #endif #ifdef DEBUG_CHECK_CONTROL void check_control (XdeltaControl* cont) { guint32 i; for (i = 0; i < cont->inst_len; i += 1) { switch (cont->inst[i].type) { case INST_TYPE_NCOPY: case INST_TYPE_COPY: if (cont->inst[i].index >= cont->source_info_len) g_error ("control has a too high instruction index\n"); } } } #endif static gboolean unpack_instructions (XdeltaControl* cont) { guint32 i; guint output_pos = 0; for (i = 0; i < cont->source_info_len; i += 1) { XdeltaSourceInfo* info = cont->source_info[i]; info->position = 0; info->copies = 0; info->copy_length = 0; } for (i = 0; i < cont->inst_len; i += 1) { XdeltaSourceInfo* info; XdeltaInstruction *inst = cont->inst + i; if (inst->index >= cont->source_info_len) { xd_generate_int_event (EC_XdOutOfRangeSourceIndex, inst->index); return FALSE; } info = cont->source_info[inst->index]; if (info->sequential) { inst->offset = info->position; info->position = inst->offset + inst->length; } inst->output_start = output_pos; output_pos += inst->length; info->copies += 1; info->copy_length += inst->length; } return TRUE; } static gboolean pack_instructions (XdeltaControl* cont) { guint32 i; for (i = 0; i < cont->source_info_len; i += 1) { XdeltaSourceInfo* info = cont->source_info[i]; info->position = 0; info->copies = 0; info->copy_length = 0; } for (i = 0; i < cont->inst_len; i += 1) { XdeltaSourceInfo* info; XdeltaInstruction *inst = cont->inst + i; if (inst->index >= cont->source_info_len) { xd_generate_int_event (EC_XdOutOfRangeSourceIndex, inst->index); return FALSE; } info = cont->source_info[inst->index]; if (info->sequential) { g_assert (info->position == inst->offset); info->position += inst->length; inst->offset = 0; } info->copies += 1; info->copy_length += inst->length; } return TRUE; } gboolean xdp_control_write (XdeltaControl *cont, XdeltaOutStream *cont_out) { SerialSink* sink = handle_sink (cont_out, NULL, NULL, NULL, NULL); #ifdef DEBUG_CONT xdp_print_control (cont); #endif #ifdef DEBUG_CHECK_CONTROL check_control (cont); #endif if (! sink) return FALSE; if (! pack_instructions (cont)) return FALSE; /* think about how the count function overcounts on the instruction * array by a factor of 2 or more. */ if (! serialize_xdeltacontrol_obj (sink, cont)) return FALSE; if (! handle_close (cont_out, 0)) return FALSE; return TRUE; } XdeltaControl* xdp_control_read (XdeltaStream *cont_in) { SerialSource* src = handle_source (cont_in); XdeltaControl* cont; SerialType type; if (! src) return NULL; /* TODO: free src */ if (! serializeio_unserialize_generic_acceptable (src, ST_XdeltaControl | ST_Version0Control, & type, (void**) & cont)) return NULL; if (type == ST_Version0Control) { SerialVersion0Control *ocont = (SerialVersion0Control*) cont; xd_generate_string_event (EC_XdBackwardCompatibilityMode, "1.0"); cont = control_version_0 (ocont); g_free (ocont); } if (! unpack_instructions (cont)) return NULL; #ifdef DEBUG_CHECK_CONTROL check_control (cont); #endif return cont; } XdeltaControl* control_version_0 (SerialVersion0Control* ocont) { XdeltaControl* cont = g_new0 (XdeltaControl, 1); guint32 i; XdeltaSourceInfo* dinfo; g_assert (! ocont->normalized); memcpy (cont->to_md5, ocont->to_info.real_md5, 16); cont->to_len = ocont->to_info.length; cont->has_data = TRUE; cont->source_info_len = ocont->source_info_len + 1; cont->source_info = g_new (XdeltaSourceInfo*, cont->source_info_len); cont->source_info[0] = dinfo = g_new0 (XdeltaSourceInfo, 1); dinfo->name = "(patch data)"; memcpy (dinfo->md5, ocont->to_info.md5, 15); dinfo->len = ocont->data_len; dinfo->isdata = TRUE; dinfo->sequential = FALSE; for (i = 0; i < ocont->source_info_len; i += 1) { XdeltaSourceInfo* info = g_new0 (XdeltaSourceInfo, 1); SerialVersion0SourceInfo* oinfo = ocont->source_info[i]; cont->source_info[i+1] = info; info->name = "unnamed"; memcpy (info->md5, oinfo->md5, 16); info->len = oinfo->length; info->isdata = FALSE; info->sequential = FALSE; } /* The old unpack */ #define OLD_QUERY_SIZE 4 for (i = 0; i < ocont->inst_len; i += 1) { switch (ocont->inst[i].length & 3) { case 0: ocont->inst[i].type = 'N'; break; case 1: ocont->inst[i].type = 'E'; break; case 2: ocont->inst[i].type = 'C'; break; case 3: ocont->inst[i].type = 'I'; break; } ocont->inst[i].length >>= 2; ocont->inst[i].index = ocont->inst[i].length & OLD_QUERY_SIZE; ocont->inst[i].length >>= OLD_QUERY_SIZE; } cont->inst_len = ocont->inst_len; cont->inst = g_new (XdeltaInstruction, cont->inst_len); for (i = 0; i < cont->inst_len; i += 1) { cont->inst[i].length = ocont->inst[i].length; cont->inst[i].offset = ocont->inst[i].offset; switch (ocont->inst[i].type) { case 'N': case 'E': abort (); break; case 'C': g_assert (ocont->inst[i].index == 0); cont->inst[i].index = 1; break; case 'I': cont->inst[i].index = 0; break; } } return cont; } xdelta-1.2.1/xdelta.h000077500000000000000000000157151525650667300144610ustar00rootroot00000000000000/* -*- Mode: C;-*- * * This file is part of XDelta - A binary delta generator. * * Copyright (C) 1997, 1998, 2001 Josh MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Author: Josh MacDonald * * $Id: xdelta.h 1.4.1.8.1.50.1.3 Fri, 29 Jun 2001 06:01:08 -0700 jmacd $ */ #ifndef _XDELTA_H_ #define _XDELTA_H_ #include "xd_edsio.h" typedef SerialRsyncIndex XdeltaRsync; typedef SerialRsyncIndexElt XdeltaRsyncElt; typedef SerialXdeltaChecksum XdeltaChecksum; typedef SerialXdeltaIndex XdeltaIndex; typedef SerialXdeltaSourceInfo XdeltaSourceInfo; typedef SerialXdeltaControl XdeltaControl; typedef SerialXdeltaInstruction XdeltaInstruction; typedef struct _XdeltaGenerator XdeltaGenerator; typedef struct _XdeltaSource XdeltaSource; typedef FileHandle XdeltaStream; typedef FileHandle XdeltaOutStream; /* Note: FileHandle is an opaque type, you must define it * to use this library. See how its done in xdmain.c. */ /* $Format: "#define XDELTA_VERSION \"$ReleaseVersion$\"" $ */ #define XDELTA_VERSION "1.2.1" /* $Format: "#define XDELTA_MAJOR_VERSION $ReleaseMajorVersion$" $ */ #define XDELTA_MAJOR_VERSION 1 /* $Format: "#define XDELTA_MINOR_VERSION $ReleaseMinorVersion$" $ */ #define XDELTA_MINOR_VERSION 2 /* $Format: "#define XDELTA_MICRO_VERSION $ReleaseMicroVersion$" $ */ #define XDELTA_MICRO_VERSION 0 extern const guint xdelta_major_version; extern const guint xdelta_minor_version; extern const guint xdelta_micro_version; /* copy segments are of length 1< * * $Id: xdeltapriv.h 1.29 Sat, 03 Apr 1999 20:09:14 -0800 jmacd $ */ #ifndef _XDELTAPRIV_H_ #define _XDELTAPRIV_H_ #if 0 #define DEBUG_CKSUM_UPDATE #define DEBUG_MATCH_PRINT #define DEBUG_CKSUM #define DEBUG_HASH #define DEBUG_INST #define CLOBBER_ALGORITHM_C #define DEBUG_MD5 #define DEBUG_CONT #define DEBUG_COPY #define DEBUG_FIND #define DEBUG_RSYNC_REQUEST #define DEBUG_CONT #define DEBUG_CONT2 #define DEBUG_CHECK_CONTROL #endif typedef struct _XdeltaPos XdeltaPos; typedef struct _RsyncHash RsyncHash; #define XPOS(p) (((p).page * (p).page_size) + (p).off) struct _XdeltaPos { guint page; guint page_size; guint off; const guint8* mem; guint mem_page; guint mem_rem; }; #define handle_length(x) ((* (x)->table->table_handle_length) (x)) #define handle_pages(x) ((* (x)->table->table_handle_pages) (x)) #define handle_pagesize(x) ((* (x)->table->table_handle_pagesize) (x)) #define handle_map_page(x,y,z) ((* (x)->table->table_handle_map_page) ((x),(y),(z))) #define handle_unmap_page(x,y,z) ((* (x)->table->table_handle_unmap_page) ((x),(y),(z))) #define handle_checksum_md5(x) ((* (x)->table->table_handle_checksum_md5) (x)) #define handle_close(x,y) ((* (x)->table->table_handle_close) ((x), (y))) #define handle_write(x,y,z) ((* (x)->table->table_handle_write) ((x),(y),(z))) #define handle_copy(x,y,z,a) ((* (x)->table->table_handle_copy) ((x),(y),(z),(a))) struct _XdeltaGenerator { GPtrArray *sources; const guint32 *table; guint table_size; guint to_output_pos; guint data_output_pos; XdeltaOutStream *data_out; XdeltaOutStream *control_out; XdeltaControl *control; XdeltaSource *data_source; #ifdef DEBUG_HASH gint hash_conflicts; /* bucket already used. */ gint hash_real_conflicts; /* bucket had different checksum. */ gint hash_real_real_conflicts; /* bucket had same checksum, different region */ gint hash_fill; gint hash_entries; #endif EdsioMD5Ctx ctx; }; struct _XdeltaSource { XdeltaStream *source_in; XdeltaPos source_pos; gint ck_count; /* number of elts in cksums. */ const XdeltaChecksum *cksums; /* array of cksums. */ const char *name; XdeltaStream *index_in; XdeltaOutStream *index_out; guint32 source_index; gboolean used; gboolean sequential; guint32 position; }; #define CHEW(x) (single_hash[(guint)x]) #define FLIP_FORWARD(p) if ((p).off == (p).page_size) { (p).page += 1; (p).off = 0; } extern const guint16 single_hash[256]; void init_pos (XdeltaStream* str, XdeltaPos* pos); gboolean unmap_page (XdeltaStream* stream, XdeltaPos* pos); gboolean map_page (XdeltaStream* stream, XdeltaPos* pos); gboolean check_stream_integrity (XdeltaStream* str, const guint8* md5, guint len); XdeltaControl* control_new (void); guint c_hash (const XdeltaChecksum* c); #endif /* _XDELTAPRIV_H_ */ xdelta-1.2.1/xdmain.c000077500000000000000000001247471525650667300144610ustar00rootroot00000000000000/* -*- Mode: C;-*- * * This file is part of XDelta - A binary delta generator. * * Copyright (C) 1997, 1998, 1999, 2001 Josh MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Author: Josh MacDonald * * $Id: xdmain.c 1.22.1.7.1.1 Sat, 27 Jan 2007 17:53:47 -0800 jmacd $ */ #include #include #include #include #include #include #include #if defined(_WIN32) || defined(__DJGPP__) #define WINHACK #endif #ifndef WINHACK #include #include #define O_BINARY 0 #else /* WINHACK */ #include #include #ifdef __DJGPP__ #include #include #endif #define STDOUT_FILENO 1 #define lstat stat #ifndef __DJGPP__ #define S_IFMT _S_IFMT #define S_IFREG _S_IFREG #endif /* !__DJGPP__ */ #endif /* !WINHACK_ */ #include #include "xdelta.h" static HandleFuncTable xd_handle_table; #define XD_PAGE_SIZE (1<<20) #define XDELTA_110_PREFIX "%XDZ004%" #define XDELTA_104_PREFIX "%XDZ003%" #define XDELTA_100_PREFIX "%XDZ002%" #define XDELTA_020_PREFIX "%XDZ001%" #define XDELTA_018_PREFIX "%XDZ000%" #define XDELTA_014_PREFIX "%XDELTA%" #define XDELTA_PREFIX XDELTA_110_PREFIX #define XDELTA_PREFIX_LEN 8 #define HEADER_WORDS (6) #define HEADER_SPACE (HEADER_WORDS*4) /* The header is composed of 4-byte words (network byte order) as follows: * word 1: flags * word 2: (from name length) << 16 | (to name length) * word 3: (reserved) * word 4: (reserved) * word 5: (reserved) * word 6: (reserved) * flags are: */ #define FLAG_NO_VERIFY 1 #define FLAG_FROM_COMPRESSED 2 #define FLAG_TO_COMPRESSED 4 #define FLAG_PATCH_COMPRESSED 8 /* and, the header is follwed by the from file name, then the to file * name, then the data. */ #ifdef WINHACK #define FOPEN_READ_ARG "rb" #define FOPEN_WRITE_ARG "wb" #define FILE_SEPARATOR '\\' #else #define FOPEN_READ_ARG "r" #define FOPEN_WRITE_ARG "w" #define FILE_SEPARATOR '/' #endif /* WINHACK */ #include "getopt.h" typedef struct _LRU LRU; struct _LRU { LRU *next; LRU *prev; gint refs; guint page; guint8* buffer; }; typedef struct _XdFileHandle XdFileHandle; typedef struct { gboolean patch_is_compressed; const gchar* patch_name; guint patch_flags; const gchar* patch_version; gboolean has_trailer; XdeltaSourceInfo* data_source; XdeltaSourceInfo* from_source; gchar *from_name; gchar *to_name; guint control_offset; guint header_offset; gint16 from_name_len; gint16 to_name_len; guint32 header_space[HEADER_WORDS]; char magic_buf[XDELTA_PREFIX_LEN]; XdFileHandle *patch_in; XdeltaControl *cont; } XdeltaPatch; struct _XdFileHandle { FileHandle fh; guint length; guint real_length; gint type; const char* name; const char* cleanup; guint8 md5[16]; EdsioMD5Ctx ctx; /* for write */ int out_fd; void* out; gboolean (* out_write) (XdFileHandle* handle, const void* buf, gint nbyte); gboolean (* out_close) (XdFileHandle* handle); /* for read */ GPtrArray *lru_table; LRU *lru_head; /* most recently used. */ LRU *lru_tail; /* least recently used. */ guint lru_count; guint lru_outstanding_refs; guint narrow_low; guint narrow_high; guint current_pos; /* Either a FILE* or a gzFile, selected by in_read/in_close below. */ void* in; gboolean (* in_read) (XdFileHandle* handle, void* buf, gint nbyte); gboolean (* in_close) (XdFileHandle* handle); gboolean in_compressed; const guint8* copy_page; guint copy_pgno; gboolean md5_good; gboolean reset_length_next_write; guint md5_page; gint fd; }; /* $Format: "static const char xdelta_version[] = \"$ReleaseVersion$\"; " $ */ static const char xdelta_version[] = "1.2.1"; typedef struct _Command Command; static const char* xd_basename (const char *path) { const char *slash = strrchr (path, '/'); const char *backslash = strrchr (path, '\\'); const char *separator = slash; if (backslash && (! separator || backslash > separator)) separator = backslash; return separator ? separator + 1 : path; } struct _Command { gchar* name; gint (* func) (gint argc, gchar** argv); gint nargs; }; static gint delta_command (gint argc, gchar** argv); static gint patch_command (gint argc, gchar** argv); static gint info_command (gint argc, gchar** argv); static const Command commands[] = { { "delta", delta_command, -1 }, { "patch", patch_command, -1 }, { "info", info_command, 1 }, { NULL, NULL, 0 } }; static struct option const long_options[] = { {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'v'}, {"verbose", no_argument, 0, 'V'}, {"noverify", no_argument, 0, 'n'}, {"pristine", no_argument, 0, 'p'}, {"quiet", no_argument, 0, 'q'}, {"maxmem", required_argument, 0, 'm'}, {"blocksize", required_argument, 0, 's'}, {0,0,0,0} }; static const gchar* program_name; static gint compress_level = Z_DEFAULT_COMPRESSION; static gint no_verify = FALSE; static gint pristine = FALSE; static gint verbose = FALSE; static gint max_mapped_pages = G_MAXINT; static gint quiet = FALSE; #define xd_error g_warning static void usage (void) { xd_error ("usage: %s COMMAND [OPTIONS] [ARG1 ...]\n", program_name); xd_error ("use --help for more help\n"); exit (0); } static void help (void) { xd_error ("usage: %s COMMAND [OPTIONS] [ARG1 ...]\n", program_name); xd_error ("COMMAND is one of:\n"); xd_error (" delta Produce a delta from ARG1 to ARG2 producing ARG3\n"); xd_error (" info List details about delta ARG1\n"); xd_error (" patch Apply patch ARG1 using file ARG2 producing ARG3\n"); xd_error ("OPTIONS are:\n"); xd_error (" -v, --version Print version information\n"); xd_error (" -V, --verbose Print verbose error messages\n"); xd_error (" -h, --help Print this summary\n"); xd_error (" -n, --noverify Disable automatic MD5 verification\n"); xd_error (" -p, --pristine Disable automatic GZIP decompression\n"); xd_error (" -m, --maxmem=SIZE Set the buffer size limit, e.g. 640K, 16M\n"); xd_error (" -[0-9] ZLIB compress level: 0=none, 1=fast, 6=default, 9=best\n"); xd_error (" -s=BLOCK_SIZE Sets block size (power of 2), minimum match length\n"); xd_error (" In-core memory requirement is (FROM_LEN * 8) / BLOCK_SIZE\n"); exit (2); } static void version (void) { xd_error ("version %s\n", xdelta_version); exit (0); } static FILE* xd_error_file = NULL; static void xd_error_func (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { (void) log_domain; (void) log_level; (void) user_data; if (! xd_error_file) xd_error_file = stderr; fprintf (xd_error_file, "%s: %s", program_name, message); } static gboolean event_devel (void) { static gboolean once = FALSE; static gboolean devel = FALSE; if (! once) { devel = g_getenv ("EDSIO_DEVEL") != NULL; once = TRUE; } return devel; } static gboolean event_watch (GenericEvent* ev, GenericEventDef* def, const char* message) { if (quiet && def->level <= EL_Warning) return TRUE; if (event_devel ()) fprintf (stderr, "%s:%d: %s\n", ev->srcfile, ev->srcline, message); else fprintf (stderr, "%s: %s\n", program_name, message); return TRUE; } gint main (gint argc, gchar** argv) { const Command *cmd = NULL; gint c; gint longind; eventdelivery_event_watch_all (event_watch); if (! xd_edsio_init ()) return 2; #ifdef __DJGPP__ /* * (richdawe@bigfoot.com): Limit maximum memory usage to 87.5% of available * physical memory for DJGPP. Otherwise the replacement for mmap() will * exhaust memory and XDelta will fail. */ { unsigned long phys_free = _go32_dpmi_remaining_physical_memory(); max_mapped_pages = phys_free / XD_PAGE_SIZE; max_mapped_pages %= 8; max_mapped_pages *= 7; } /* * (richdawe@bigfoot.com): Strip off the file extension 'exe' from * program_name, since it makes the help messages look ugly. */ { char strip_ext[PATH_MAX + 1]; char *p; strcpy (strip_ext, argv[0]); p = strrchr (strip_ext, '.'); if ((p != NULL) && (strncasecmp (p + 1, "exe", 3) == 0)) *p = '\0'; program_name = g_strdup (xd_basename (strip_ext)); } #else /* !__DJGPP__ */ program_name = xd_basename (argv[0]); #endif /* __DJGPP__ */ g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, xd_error_func, NULL); if (argc < 2) usage (); for (cmd = commands; cmd->name; cmd += 1) if (strcmp (cmd->name, argv[1]) == 0) break; if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) help (); if (strcmp (argv[1], "-v") == 0 || strcmp (argv[1], "--version") == 0) version (); if (!cmd->name) { xd_error ("unrecognized command\n"); help (); } argc -= 1; argv += 1; while ((c = getopt_long(argc, argv, "+nqphvVs:m:0123456789", long_options, &longind)) != EOF) { switch (c) { case 'q': quiet = TRUE; break; case 'n': no_verify = TRUE; break; case 'p': pristine = TRUE; break; case 'V': verbose = TRUE; break; case 's': { int ret; int s = atoi (optarg); if ((ret = xdp_set_query_size_pow (s)) && ! quiet) { xd_error ("illegal query size: %s\n", xdp_errno (ret)); } } break; case 'm': { gchar* end = NULL; glong l = strtol (optarg, &end, 0); if (end && g_ascii_strcasecmp (end, "M") == 0) l <<= 20; else if (end && g_ascii_strcasecmp (end, "K") == 0) l <<= 10; else if (end || l < 0) { xd_error ("illegal maxmem argument %s\n", optarg); return 2; } #ifdef __DJGPP__ /* * (richdawe@bigfoot.com): Old MS-DOS systems may have a maximum * of 8MB memory == XD_PAGE_SIZE * 8. Therefore, do what the user * asks for on MS-DOS. */ #else /* !__DJGPP__ */ l = MAX (l, XD_PAGE_SIZE * 8); #endif /* __DJGPP__ */ max_mapped_pages = l / XD_PAGE_SIZE; } break; case 'h': help (); break; case 'v': version (); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': compress_level = c - '0'; break; case '?': default: xd_error ("illegal argument, use --help for help\n"); return 2; } } if (verbose && max_mapped_pages < G_MAXINT) xd_error ("using %d kilobytes of buffer space\n", (max_mapped_pages * XD_PAGE_SIZE) >> 10); argc -= optind; argv += optind; if (cmd->nargs >= 0 && argc != cmd->nargs) { xd_error ("wrong number of arguments\n"); help (); return 2; } return (* cmd->func) (argc, argv); } /* Commands */ #define READ_TYPE 1 #define READ_NOSEEK_TYPE 1 #define READ_SEEK_TYPE 3 #define WRITE_TYPE 4 /* Note to the casual reader: the filehandle implemented here is * highly aware of the calling patterns of the Xdelta library. It * also plays games with narrowing to implement several files in the * same handle. So, if you try to modify or use this code, BEWARE. * See the repository package for a complete implementation. * In fact, its really quite a hack. */ static gssize xd_handle_map_page (XdFileHandle *fh, guint pgno, const guint8** mem); static gboolean xd_handle_unmap_page (XdFileHandle *fh, guint pgno, const guint8** mem); static gboolean xd_fwrite (XdFileHandle* fh, const void* buf, gint nbyte) { return fwrite (buf, nbyte, 1, fh->out) == 1; } static gboolean xd_fread (XdFileHandle* fh, void* buf, gint nbyte) { return fread (buf, nbyte, 1, fh->in) == 1; } static gboolean xd_fclose (XdFileHandle* fh) { return fclose (fh->out) == 0; } static gboolean xd_frclose (XdFileHandle* fh) { return fclose (fh->in) == 0; } static gboolean xd_gzwrite (XdFileHandle* fh, const void* buf, gint nbyte) { return gzwrite (fh->out, (void*) buf, nbyte) == nbyte; } static gboolean xd_gzread (XdFileHandle* fh, void* buf, gint nbyte) { return gzread (fh->in, buf, nbyte) == nbyte; } static gboolean xd_gzclose (XdFileHandle* fh) { return gzclose (fh->out) == Z_OK; } static gboolean xd_gzrclose (XdFileHandle* fh) { return gzclose (fh->in) == Z_OK; } static void init_table (XdFileHandle* fh) { fh->lru_table = g_ptr_array_new (); fh->lru_head = NULL; fh->lru_tail = NULL; } static XdFileHandle* open_common (const char* name, const char* real_name) { XdFileHandle* fh; gint fd; struct stat buf; if ((fd = open (name, O_RDONLY | O_BINARY, 0)) < 0) { xd_error ("open %s failed: %s\n", name, g_strerror (errno)); return NULL; } if (stat (name, &buf) < 0) { xd_error ("stat %s failed: %s\n", name, g_strerror (errno)); return NULL; } /* S_ISREG() is not on Windows */ if ((buf.st_mode & S_IFMT) != S_IFREG) { xd_error ("%s is not a regular file\n", name); return NULL; } fh = g_new0 (XdFileHandle, 1); fh->fh.table = & xd_handle_table; fh->name = real_name; fh->fd = fd; fh->length = buf.st_size; fh->narrow_high = buf.st_size; return fh; } static gboolean file_gzipped (const char* name, gboolean *is_compressed) { FILE* f = fopen (name, FOPEN_READ_ARG); guint8 buf[2]; (*is_compressed) = FALSE; if (! f) { xd_error ("open %s failed: %s\n", name, g_strerror (errno)); return FALSE; } if (fread (buf, 2, 1, f) != 1) return TRUE; #define GZIP_MAGIC1 037 #define GZIP_MAGIC2 0213 if (buf[0] == GZIP_MAGIC1 && buf[1] == GZIP_MAGIC2) (* is_compressed) = TRUE; return TRUE; } static const char* xd_tmpname (void) { const char* tmpdir = g_get_tmp_dir (); GString* s; gint x = getpid (); static gint seq = 0; struct stat buf; s = g_string_new (NULL); do { /* * (richdawe@bigfoot.com): Limit temporary filenames to * the MS-DOS 8+3 convention for DJGPP. */ g_string_printf (s, "%s/xd-%05d.%03d", tmpdir, x, seq++); } while (lstat (s->str, &buf) == 0); return s->str; } static const char* file_gunzip (const char* name) { const char* new_name = xd_tmpname (); FILE* out = fopen (new_name, FOPEN_WRITE_ARG); gzFile in = gzopen (name, "rb"); guint8 buf[1024]; int nread; while ((nread = gzread (in, buf, 1024)) > 0) { if (fwrite (buf, nread, 1, out) != 1) { xd_error ("write %s failed (during uncompression): %s\n", new_name, g_strerror (errno)); return NULL; } } if (nread < 0) { xd_error ("gzread %s failed\n", name); return NULL; } gzclose (in); if (fclose (out)) { xd_error ("close %s failed (during uncompression): %s\n", new_name, g_strerror (errno)); return NULL; } return new_name; } static XdFileHandle* open_read_noseek_handle (const char* name, gboolean* is_compressed, gboolean will_read, gboolean honor_pristine) { XdFileHandle* fh; const char* name0 = name; /* we _could_ stream-read this file if compressed, but it adds a * lot of complexity. the library can handle it, just set the * length to (XDELTA_MAX_FILE_LEN-1) and make sure that the end * of file condition is set when on the last page. However, I * don't feel like it. */ if (honor_pristine && pristine) *is_compressed = FALSE; else { if (! file_gzipped (name, is_compressed)) return NULL; } if ((* is_compressed) && ! (name = file_gunzip (name))) return NULL; if (! (fh = open_common (name, name0))) return NULL; fh->type = READ_NOSEEK_TYPE; edsio_md5_init (&fh->ctx); if (*is_compressed) fh->cleanup = name; if (will_read) { g_assert (fh->fd >= 0); if (! (fh->in = fdopen (dup (fh->fd), FOPEN_READ_ARG))) { xd_error ("fdopen: %s\n", g_strerror (errno)); return NULL; } fh->in_read = &xd_fread; fh->in_close = &xd_frclose; } else { init_table (fh); } return fh; } static void xd_read_close (XdFileHandle* fh) { /* * (richdawe@bigfoot.com): On Unix you can unlink a file while it is * still open. On MS-DOS this can lead to filesystem corruption. Close * the file before unlinking it. */ close (fh->fd); if (fh->cleanup) unlink (fh->cleanup); if (fh->in) (*fh->in_close) (fh); } static XdFileHandle* open_read_seek_handle (const char* name, gboolean* is_compressed, gboolean honor_pristine) { XdFileHandle* fh; const char* name0 = name; if (honor_pristine && pristine) *is_compressed = FALSE; else { if (! file_gzipped (name, is_compressed)) return NULL; } if ((* is_compressed) && ! (name = file_gunzip (name))) return NULL; if (! (fh = open_common (name, name0))) return NULL; fh->type = READ_SEEK_TYPE; if (*is_compressed) fh->cleanup = name; init_table (fh); edsio_md5_init (&fh->ctx); return fh; } static XdFileHandle* open_write_handle (int fd, const char* name) { XdFileHandle* fh = g_new0 (XdFileHandle, 1); int nfd; fh->fh.table = & xd_handle_table; fh->out_fd = fd; fh->out_write = &xd_fwrite; fh->out_close = &xd_fclose; g_assert (fh->out_fd >= 0); nfd = dup (fh->out_fd); if (! (fh->out = fdopen (nfd, FOPEN_WRITE_ARG))) { xd_error ("fdopen %s failed: %s\n", name, g_strerror (errno)); return NULL; } fh->type = WRITE_TYPE; fh->name = name; edsio_md5_init (&fh->ctx); return fh; } static gint xd_begin_compression (XdFileHandle* fh) { gint filepos, nfd; if (compress_level == 0) return fh->real_length; if (! (fh->out_close) (fh)) { xd_error ("fclose failed: %s\n", g_strerror (errno)); return -1; } filepos = lseek (fh->out_fd, 0, SEEK_END); if (filepos < 0) { xd_error ("lseek failed: %s\n", g_strerror (errno)); return -1; } g_assert (fh->out_fd >= 0); nfd = dup (fh->out_fd); fh->out = gzdopen (nfd, "wb"); fh->out_write = &xd_gzwrite; fh->out_close = &xd_gzclose; if (! fh->out) { xd_error ("gzdopen failed: %s\n", g_strerror (errno)); return -1; } if (gzsetparams(fh->out, compress_level, Z_DEFAULT_STRATEGY) != Z_OK) { int foo; xd_error ("gzsetparams failed: %s\n", gzerror (fh->out, &foo)); return -1; } return filepos; } static gboolean xd_end_compression (XdFileHandle* fh) { if (compress_level == 0) return TRUE; if (! (fh->out_close) (fh)) { xd_error ("fdclose failed: %s\n", g_strerror (errno)); return FALSE; } if (lseek (fh->out_fd, 0, SEEK_END) < 0) { xd_error ("lseek failed: %s\n", g_strerror (errno)); return FALSE; } g_assert (fh->out_fd >= 0); fh->out = fdopen (dup (fh->out_fd), FOPEN_WRITE_ARG); fh->out_write = &xd_fwrite; fh->out_close = &xd_fclose; if (! fh->out) { xd_error ("fdopen failed: %s\n", g_strerror (errno)); return FALSE; } return TRUE; } static gssize xd_handle_length (XdFileHandle *fh) { if (fh->in_compressed) return fh->current_pos; else return fh->narrow_high - fh->narrow_low; } static gssize xd_handle_pages (XdFileHandle *fh) { g_assert (fh->type & READ_TYPE); return xd_handle_length (fh) / XD_PAGE_SIZE; } static gssize xd_handle_pagesize (XdFileHandle *fh) { g_assert (fh->type & READ_TYPE); return XD_PAGE_SIZE; } static gint on_page (XdFileHandle* fh, guint pgno) { if (pgno > xd_handle_pages (fh)) return -1; if (pgno == xd_handle_pages (fh)) return xd_handle_length (fh) % XD_PAGE_SIZE; return XD_PAGE_SIZE; } static gboolean xd_handle_close (XdFileHandle *fh, gint ignore) { (void) ignore; /* this is really a reset for writable files */ if (fh->type == WRITE_TYPE) { if (fh->reset_length_next_write) { fh->reset_length_next_write = FALSE; fh->length = 0; fh->narrow_high = 0; } fh->reset_length_next_write = TRUE; edsio_md5_final (fh->md5, &fh->ctx); edsio_md5_init (&fh->ctx); } else if (fh->in) { edsio_md5_final (fh->md5, &fh->ctx); edsio_md5_init (&fh->ctx); fh->md5_good = FALSE; } return TRUE; } static const guint8* xd_handle_checksum_md5 (XdFileHandle *fh) { if (fh->in && ! fh->md5_good) { edsio_md5_final (fh->md5, &fh->ctx); fh->md5_good = TRUE; } else if (fh->type != WRITE_TYPE && !fh->in) { const guint8* page; while (fh->md5_page <= xd_handle_pages (fh)) { guint pgno = fh->md5_page; gint onpage; if ((onpage = xd_handle_map_page (fh, pgno, &page)) < 0) return NULL; if (pgno == fh->md5_page) { fh->md5_page += 1; edsio_md5_update (&fh->ctx, page, onpage); if (fh->md5_page > xd_handle_pages (fh)) edsio_md5_final (fh->md5, &fh->ctx); } if (! xd_handle_unmap_page (fh, pgno, &page)) return NULL; } } return g_memdup2 (fh->md5, 16); } static gboolean xd_handle_set_pos (XdFileHandle *fh, guint pos) { if (fh->current_pos == pos + fh->narrow_low) return TRUE; if (pos + fh->narrow_low > fh->narrow_high) { xd_error ("unexpected EOF in %s\n", fh->name); return FALSE; } fh->current_pos = pos + fh->narrow_low; if (fseek (fh->in, fh->current_pos, SEEK_SET)) { xd_error ("fseek failed: %s\n", g_strerror (errno)); return FALSE; } return TRUE; } static gboolean xd_handle_narrow (XdFileHandle* fh, guint low, guint high, gboolean compressed) { if (high > fh->length) { xd_error ("%s: corrupt or truncated delta\n", fh->name); return FALSE; } fh->narrow_low = low; fh->narrow_high = high; edsio_md5_init (&fh->ctx); if (compressed) { (* fh->in_close) (fh); if (lseek (fh->fd, low, SEEK_SET) < 0) { xd_error ("%s: corrupt or truncated delta: cannot seek to %d: %s\n", fh->name, low, g_strerror (errno)); return FALSE; } g_assert (fh->fd >= 0); fh->in = gzdopen (dup (fh->fd), "rb"); fh->in_read = &xd_gzread; fh->in_close = &xd_gzrclose; fh->in_compressed = TRUE; fh->current_pos = 0; if (! fh->in) { xd_error ("gzdopen failed: %s\n", g_strerror (errno)); return -1; } } else { if (! xd_handle_set_pos (fh, 0)) return FALSE; } return TRUE; } static guint xd_handle_get_pos (XdFileHandle* fh) { return fh->current_pos - fh->narrow_low; } static const gchar* xd_handle_name (XdFileHandle *fh) { return g_strdup (fh->name); } static gssize xd_handle_read (XdFileHandle *fh, void *buf, gsize nbyte) { if (nbyte == 0) return 0; if (! (fh->in_read) (fh, buf, nbyte)) /* This is suspicious */ { xd_error ("read failed: %s\n", g_strerror (errno)); return -1; } if (!no_verify) edsio_md5_update (&fh->ctx, buf, nbyte); fh->current_pos += nbyte; return nbyte; } static gboolean xd_handle_write (XdFileHandle *fh, const void *buf, gsize nbyte) { g_assert (fh->type == WRITE_TYPE); if (fh->reset_length_next_write) { fh->reset_length_next_write = FALSE; fh->length = 0; fh->narrow_high = 0; } if (! no_verify) edsio_md5_update (&fh->ctx, buf, nbyte); if (! (*fh->out_write) (fh, buf, nbyte)) { xd_error ("write failed: %s\n", g_strerror (errno)); return FALSE; } fh->length += nbyte; fh->real_length += nbyte; fh->narrow_high += nbyte; return TRUE; } static gboolean xd_handle_really_close (XdFileHandle *fh) { g_assert (fh->type == WRITE_TYPE); if (! (* fh->out_close) (fh) || close (fh->out_fd) < 0) { xd_error ("write failed: %s\n", g_strerror (errno)); return FALSE; } return TRUE; } static LRU* pull_lru (XdFileHandle* fh, LRU* lru) { if (lru->next && lru->prev) { lru->next->prev = lru->prev; lru->prev->next = lru->next; } else if (lru->next) { fh->lru_tail = lru->next; lru->next->prev = NULL; } else if (lru->prev) { fh->lru_head = lru->prev; lru->prev->next = NULL; } else { fh->lru_head = NULL; fh->lru_tail = NULL; } lru->next = NULL; lru->prev = NULL; return lru; } static gboolean really_free_one_page (XdFileHandle* fh) { LRU *lru = fh->lru_tail; for (; lru; lru = lru->prev) { gint to_unmap; LRU *lru_dead; if (lru->refs > 0) continue; lru_dead = pull_lru (fh, lru); g_assert (lru_dead->buffer); to_unmap = on_page (fh, lru_dead->page); fh->lru_count -= 1; if (to_unmap > 0) { #ifdef WINHACK g_free (lru_dead->buffer); #else if (munmap (lru_dead->buffer, to_unmap)) { xd_error ("munmap failed: %s\n", g_strerror (errno)); return FALSE; } #endif /* WINHACK */ } lru_dead->buffer = NULL; return TRUE; } return TRUE; } #if 0 static void print_lru (XdFileHandle* fh) { LRU* lru = fh->lru_head; for (; lru; lru = lru->prev) { g_print ("page %d buffer %p\n", lru->page, lru->buffer); if (! lru->prev && lru != fh->lru_tail) g_print ("incorrect lru_tail\n"); } } #endif static gboolean make_lru_room (XdFileHandle* fh) { if (fh->lru_count == (guint) max_mapped_pages) { if (! really_free_one_page (fh)) return FALSE; } g_assert (fh->lru_count < (guint) max_mapped_pages); return TRUE; } /*#define DEBUG_MAP*/ static gssize xd_handle_map_page (XdFileHandle *fh, guint pgno, const guint8** mem) { LRU* lru; gint to_map; #ifdef DEBUG_MAP g_print ("map %p:%d\n", fh, pgno); #endif g_assert (fh->type & READ_TYPE); if (fh->lru_table->len < (pgno + 1)) { guint olen = fh->lru_table->len; g_ptr_array_set_size (fh->lru_table, pgno + 1); while (olen <= pgno) fh->lru_table->pdata[olen++] = NULL; } lru = fh->lru_table->pdata[pgno]; if (! lru) { lru = g_new0 (LRU, 1); fh->lru_table->pdata[pgno] = lru; lru->page = pgno; } else if (lru->buffer) { pull_lru (fh, lru); } lru->prev = fh->lru_head; lru->next = NULL; fh->lru_head = lru; if (lru->prev) lru->prev->next = lru; if (! fh->lru_tail) fh->lru_tail = lru; to_map = on_page (fh, pgno); if (to_map < 0) { xd_error ("unexpected EOF in %s\n", fh->name); return -1; } if (! lru->buffer) { if (! make_lru_room (fh)) return -1; fh->lru_count += 1; if (to_map > 0) { #ifdef WINHACK lru->buffer = g_malloc (to_map); if (lseek (fh->fd, pgno * XD_PAGE_SIZE, SEEK_SET) < 0) { xd_error ("lseek failed: %s\n", g_strerror (errno)); return -1; } if (read (fh->fd, lru->buffer, to_map) != to_map) { xd_error ("read failed: %s\n", g_strerror (errno)); return -1; } #else if (! (lru->buffer = mmap (NULL, to_map, PROT_READ, MAP_PRIVATE, fh->fd, pgno * XD_PAGE_SIZE))) { xd_error ("mmap failed: %s\n", g_strerror (errno)); return -1; } #endif } else { lru->buffer = (void*) -1; } if (pgno == fh->md5_page) { if (! no_verify) edsio_md5_update (&fh->ctx, lru->buffer, to_map); fh->md5_page += 1; if (fh->md5_page > xd_handle_pages (fh)) edsio_md5_final (fh->md5, &fh->ctx); } } (*mem) = lru->buffer; lru->refs += 1; fh->lru_outstanding_refs += 1; return to_map; } static gboolean xd_handle_unmap_page (XdFileHandle *fh, guint pgno, const guint8** mem) { LRU* lru; #ifdef DEBUG_MAP g_print ("unmap %p:%d\n", fh, pgno); #endif g_assert (fh->type & READ_TYPE); g_assert (pgno < fh->lru_table->len); lru = fh->lru_table->pdata[pgno]; g_assert (lru && lru->refs > 0); g_assert (lru->buffer == (*mem)); (*mem) = NULL; lru->refs -= 1; fh->lru_outstanding_refs += 1; if (lru->refs == 0 && fh->type == READ_NOSEEK_TYPE) { pull_lru (fh, lru); lru->next = fh->lru_tail; if (lru->next) lru->next->prev = lru; lru->prev = NULL; fh->lru_tail = lru; if (! really_free_one_page (fh)) return FALSE; } return TRUE; } static gboolean xd_handle_copy (XdFileHandle *from, XdFileHandle *to, guint off, guint len) { if (from->in) { guint8 buf[1024]; /*if (! xd_handle_set_pos (from, off)) return FALSE;*/ while (len > 0) { guint r = MIN (1024, len); if (xd_handle_read (from, buf, r) != r) return FALSE; if (! xd_handle_write (to, buf, r)) return FALSE; len -= r; } } else { while (len > 0) { guint off_page = off / XD_PAGE_SIZE; guint off_off = off % XD_PAGE_SIZE; gint on = on_page (from, off_page); guint rem; guint copy; if (on <= 0) { xd_error ("unexpected EOF in %s\n", from->name); return FALSE; } rem = on - off_off; copy = MIN (len, rem); if (from->copy_pgno != off_page && from->copy_page && ! xd_handle_unmap_page (from, from->copy_pgno, &from->copy_page)) return FALSE; from->copy_pgno = off_page; if (xd_handle_map_page (from, off_page, &from->copy_page) < 0) return FALSE; if (! xd_handle_write (to, from->copy_page + off_off, copy)) return FALSE; if (! xd_handle_unmap_page (from, off_page, &from->copy_page)) return FALSE; len -= copy; off += copy; } } return TRUE; } static gboolean xd_handle_putui (XdFileHandle *fh, guint32 i) { guint32 hi = g_htonl (i); return xd_handle_write (fh, (guint8*)&hi, 4); } static gboolean xd_handle_getui (XdFileHandle *fh, guint32* i) { if (xd_handle_read (fh, (guint8*)i, 4) != 4) return FALSE; *i = g_ntohl (*i); return TRUE; } static HandleFuncTable xd_handle_table = { (gssize (*) (FileHandle *fh)) xd_handle_length, (gssize (*) (FileHandle *fh)) xd_handle_pages, (gssize (*) (FileHandle *fh)) xd_handle_pagesize, (gssize (*) (FileHandle *fh, guint pgno, const guint8** mem)) xd_handle_map_page, (gboolean (*) (FileHandle *fh, guint pgno, const guint8** mem)) xd_handle_unmap_page, (const guint8* (*) (FileHandle *fh)) xd_handle_checksum_md5, (gboolean (*) (FileHandle *fh, gint flags)) xd_handle_close, (gboolean (*) (FileHandle *fh, const guint8 *buf, gsize nbyte)) xd_handle_write, (gboolean (*) (FileHandle *from, FileHandle *to, guint off, guint len)) xd_handle_copy, (gboolean (*) (FileHandle *fh, guint32* i)) xd_handle_getui, (gboolean (*) (FileHandle *fh, guint32 i)) xd_handle_putui, (gssize (*) (FileHandle *fh, guint8 *buf, gsize nbyte)) xd_handle_read, (const gchar* (*) (FileHandle *fh)) xd_handle_name, }; static void htonl_array (guint32* array, gint len) { gint i; for (i = 0; i < len; i += 1) array[i] = g_htonl(array[i]); } static void ntohl_array (guint32* array, gint len) { gint i; for (i = 0; i < len; i += 1) array[i] = g_ntohl(array[i]); } static gint delta_command (gint argc, gchar** argv) { gint patch_out_fd; const char* patch_out_name; XdFileHandle *from, *to, *out; XdeltaGenerator* gen; XdeltaSource* src; XdeltaControl* cont; gboolean from_is_compressed = FALSE, to_is_compressed = FALSE; gint control_offset, header_offset; const char* from_name, *to_name; guint32 header_space[HEADER_WORDS]; int fd; memset (header_space, 0, sizeof (header_space)); if (argc != 3) { xd_error ("usage: %s delta fromfile tofile patchfile\n", program_name); return 2; } if (verbose) { xd_error ("using block size: %d bytes\n", xdp_blocksize ()); } if (! (from = open_read_seek_handle (argv[0], &from_is_compressed, TRUE))) return 2; if (! (to = open_read_noseek_handle (argv[1], &to_is_compressed, FALSE, TRUE))) return 2; // Note: I tried support to patches to stdout, but it broke when // compression was added. Sigh fd = open (argv[2], O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); if (fd < 0) { xd_error ("open %s failed: %s\n", argv[2], g_strerror (errno)); return 2; } patch_out_fd = fd; patch_out_name = argv[2]; from_name = xd_basename (argv[0]); to_name = xd_basename (argv[1]); if (! (out = open_write_handle (patch_out_fd, patch_out_name))) return 2; if (! (gen = xdp_generator_new ())) return 2; if (! (src = xdp_source_new (from_name, (FileHandle*) from, NULL, NULL))) return 2; xdp_source_add (gen, src); if (! xd_handle_write (out, XDELTA_PREFIX, XDELTA_PREFIX_LEN)) return 2; /* compute the header */ header_space[0] = 0; if (no_verify) header_space[0] |= FLAG_NO_VERIFY; if (from_is_compressed) header_space[0] |= FLAG_FROM_COMPRESSED; if (to_is_compressed) header_space[0] |= FLAG_TO_COMPRESSED; if (compress_level != 0) header_space[0] |= FLAG_PATCH_COMPRESSED; header_space[1] = strlen (from_name) << 16 | strlen (to_name); /* end compute the header */ htonl_array (header_space, HEADER_WORDS); if (! xd_handle_write (out, (guint8*) header_space, HEADER_SPACE)) return 2; if (! xd_handle_write (out, from_name, strlen (from_name))) return 2; if (! xd_handle_write (out, to_name, strlen (to_name))) return 2; if (! xd_handle_close (out, 0)) return 2; if ((header_offset = xd_begin_compression (out)) < 0) return 2; if (! (cont = xdp_generate_delta (gen, (FileHandle*) to, NULL, (FileHandle*) out))) return 2; #if 0 serializeio_print_xdeltacontrol_obj (cont, 0); #endif if (cont->has_data && cont->source_info_len == 1) { if (! quiet) xd_error ("warning: no matches found in from file, patch will apply without it\n"); } if (! xd_handle_close (out, 0)) return 2; if ((control_offset = xd_begin_compression (out)) < 0) return 2; if (! xdp_control_write (cont, (FileHandle*) out)) return 2; if (! xd_end_compression (out)) return 2; if (! xd_handle_putui (out, control_offset)) return 2; if (! xd_handle_write (out, XDELTA_PREFIX, XDELTA_PREFIX_LEN)) return 2; xd_read_close (from); xd_read_close (to); if (! xd_handle_really_close (out)) return 2; xdp_generator_free (gen); return 0; } static XdeltaPatch* process_patch (const char* name) { XdeltaPatch* patch; guint total_trailer; patch = g_new0 (XdeltaPatch, 1); patch->patch_name = name; /* Strictly speaking, I'm violating the intended semantics of noseek here. * It will seek the file, which is not in fact checked in the map/unmap * logic above. This only means that it will not cache pages of this file * since it will be read piecewise sequentially. */ if (! (patch->patch_in = open_read_noseek_handle (name, &patch->patch_is_compressed, TRUE, TRUE))) return NULL; if (xd_handle_read (patch->patch_in, patch->magic_buf, XDELTA_PREFIX_LEN) != XDELTA_PREFIX_LEN) return NULL; if (xd_handle_read (patch->patch_in, (guint8*) patch->header_space, HEADER_SPACE) != HEADER_SPACE) return NULL; ntohl_array (patch->header_space, HEADER_WORDS); if (strncmp (patch->magic_buf, XDELTA_110_PREFIX, XDELTA_PREFIX_LEN) == 0) { patch->has_trailer = TRUE; patch->patch_version = "1.1"; } else if (strncmp (patch->magic_buf, XDELTA_104_PREFIX, XDELTA_PREFIX_LEN) == 0) { patch->has_trailer = TRUE; patch->patch_version = "1.0.4"; } else if (strncmp (patch->magic_buf, XDELTA_100_PREFIX, XDELTA_PREFIX_LEN) == 0) { patch->patch_version = "1.0"; } else if (strncmp (patch->magic_buf, XDELTA_020_PREFIX, XDELTA_PREFIX_LEN) == 0) goto nosupport; else if (strncmp (patch->magic_buf, XDELTA_018_PREFIX, XDELTA_PREFIX_LEN) == 0) goto nosupport; else if (strncmp (patch->magic_buf, XDELTA_014_PREFIX, XDELTA_PREFIX_LEN) == 0) goto nosupport; else { xd_error ("%s: bad magic number: not a valid delta\n", name); return NULL; } patch->patch_flags = patch->header_space[0]; if (no_verify) xd_error ("--noverify is only accepted when creating a delta\n"); if (patch->patch_flags & FLAG_NO_VERIFY) no_verify = TRUE; else no_verify = FALSE; patch->from_name_len = patch->header_space[1] >> 16; patch->to_name_len = patch->header_space[1] & 0xffff; patch->from_name = g_malloc (patch->from_name_len+1); patch->to_name = g_malloc (patch->to_name_len+1); patch->from_name[patch->from_name_len] = 0; patch->to_name[patch->to_name_len] = 0; if (xd_handle_read (patch->patch_in, patch->from_name, patch->from_name_len) != patch->from_name_len) return NULL; if (xd_handle_read (patch->patch_in, patch->to_name, patch->to_name_len) != patch->to_name_len) return NULL; patch->header_offset = xd_handle_get_pos (patch->patch_in); total_trailer = 4 + (patch->has_trailer ? XDELTA_PREFIX_LEN : 0); if (! xd_handle_set_pos (patch->patch_in, xd_handle_length (patch->patch_in) - total_trailer)) return NULL; if (! xd_handle_getui (patch->patch_in, &patch->control_offset)) return NULL; if (patch->has_trailer) { char trailer_buf[XDELTA_PREFIX_LEN]; if (xd_handle_read (patch->patch_in, trailer_buf, XDELTA_PREFIX_LEN) != XDELTA_PREFIX_LEN) return NULL; if (strncmp (trailer_buf, patch->magic_buf, XDELTA_PREFIX_LEN) != 0) { xd_error ("%s: bad trailing magic number, delta is corrupt\n", name); return NULL; } } if (! xd_handle_narrow (patch->patch_in, patch->control_offset, xd_handle_length (patch->patch_in) - total_trailer, patch->patch_flags & FLAG_PATCH_COMPRESSED)) return NULL; if (! (patch->cont = xdp_control_read ((FileHandle*) patch->patch_in))) return NULL; if (patch->cont->source_info_len > 0) { XdeltaSourceInfo* info = patch->cont->source_info[0]; if (info->isdata) patch->data_source = info; else { patch->from_source = info; if (patch->cont->source_info_len > 1) { xd_generate_void_event (EC_XdIncompatibleDelta); return NULL; } } } if (patch->cont->source_info_len > 1) { patch->from_source = patch->cont->source_info[1]; } if (patch->cont->source_info_len > 2) { xd_generate_void_event (EC_XdIncompatibleDelta); return NULL; } if (! xd_handle_narrow (patch->patch_in, patch->header_offset, patch->control_offset, patch->patch_flags & FLAG_PATCH_COMPRESSED)) return NULL; return patch; nosupport: xd_error ("delta format is unsupported (too old)\n"); return NULL; } static gint info_command (gint argc, gchar** argv) { XdeltaPatch* patch; char buf[33]; guint32 i; XdeltaSourceInfo* si; (void) argc; if (! (patch = process_patch (argv[0]))) return 2; xd_error_file = stdout; xd_error ("version %s found patch version %s in %s%s\n", xdelta_version, patch->patch_version, patch->patch_name, patch->patch_flags & FLAG_PATCH_COMPRESSED ? " (compressed)" : ""); if (patch->patch_flags & FLAG_NO_VERIFY) xd_error ("generated with --noverify\n"); if (patch->patch_flags & FLAG_FROM_COMPRESSED) xd_error ("generated with a gzipped FROM file\n"); if (patch->patch_flags & FLAG_TO_COMPRESSED) xd_error ("generated with a gzipped TO file\n"); edsio_md5_to_string (patch->cont->to_md5, buf); xd_error ("output name: %s\n", patch->to_name); xd_error ("output length: %d\n", patch->cont->to_len); xd_error ("output md5: %s\n", buf); xd_error ("patch from segments: %d\n", patch->cont->source_info_len); xd_error ("MD5\t\t\t\t\tLength\tCopies\tUsed\tSeq?\tName\n"); for (i = 0; i < patch->cont->source_info_len; i += 1) { si = patch->cont->source_info[i]; edsio_md5_to_string (si->md5, buf); xd_error ("%s\t%d\t%d\t%d\t%s\t%s\n", buf, si->len, si->copies, si->copy_length, si->sequential ? "yes" : "no", si->name); } return 0; } static gint patch_command (gint argc, gchar** argv) { XdFileHandle* to_out; XdeltaPatch* patch; gint to_out_fd; int count = 1; int ret; if (argc < 1 || argc > 3) { xd_error ("usage: %s patch patchfile [fromfile [tofile]]\n", program_name); return 2; } if (! (patch = process_patch (argv[0]))) return 2; if (argc > 1) patch->from_name = argv[1]; else if (verbose) xd_error ("using from file name: %s\n", patch->from_name); if (argc > 2) patch->to_name = argv[2]; else { struct stat sbuf; gchar *defname = g_strdup (patch->to_name); while ((ret = stat (patch->to_name, & sbuf)) == 0) { if (verbose) xd_error ("to file exists: %s\n", patch->to_name); patch->to_name = g_strdup_printf ("%s.xdp%d", defname, count++); } if (verbose || strcmp (defname, patch->to_name) != 0) xd_error ("using to file name: %s\n", patch->to_name); } if (strcmp (patch->to_name, "-") == 0) { to_out_fd = STDOUT_FILENO; patch->to_name = "standard output"; } else { to_out_fd = open (patch->to_name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); if (to_out_fd < 0) { xd_error ("open %s failed: %s\n", patch->to_name, g_strerror (errno)); return 2; } } to_out = open_write_handle (to_out_fd, patch->to_name); if ((patch->patch_flags & FLAG_TO_COMPRESSED) && (xd_begin_compression (to_out) < 0)) return 2; if (patch->from_source) { XdFileHandle* from_in; gboolean from_is_compressed = FALSE; if (! (from_in = open_read_seek_handle (patch->from_name, &from_is_compressed, TRUE))) return 2; if (from_is_compressed != ((patch->patch_flags & FLAG_FROM_COMPRESSED) && 1)) xd_error ("warning: expected %scompressed from file (%s)\n", (patch->patch_flags & FLAG_FROM_COMPRESSED) ? "" : "un", patch->from_name); if (xd_handle_length (from_in) != patch->from_source->len) { xd_error ("expected from file (%s) of %slength %d bytes\n", patch->from_name, from_is_compressed ? "uncompressed " : "", patch->from_source->len); return 2; } patch->from_source->in = (XdeltaStream*) from_in; } if (patch->data_source) patch->data_source->in = (XdeltaStream*) patch->patch_in; if (! xdp_apply_delta (patch->cont, (FileHandle*) to_out)) return 2; if (patch->from_source) xd_read_close ((XdFileHandle*) patch->from_source->in); xd_read_close (patch->patch_in); if (! xd_handle_really_close (to_out)) return 2; return 0; } xdelta-1.2.1/xdrsync.c000077500000000000000000000213441525650667300146600ustar00rootroot00000000000000/* -*- Mode: C;-*- * * This file is part of XDelta - A binary delta generator. * * Copyright (C) 1997, 1998, 1999 Josh MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Author: Josh MacDonald * * $Id: xdrsync.c 1.2 Thu, 01 Apr 1999 23:29:11 -0800 jmacd $ */ #include #include #include "xdelta.h" #include "xdeltapriv.h" /* Rsync */ static void init_long_checksum (const guint8 *buf, guint len, XdeltaChecksum *cksum) { guint16 low = cksum->low; guint16 high = cksum->high; for (; len > 0; len -= 1) { low += CHEW(*buf++); high += low; } cksum->low = low; cksum->high = high; } static XdeltaRsync* xdp_rsync_index_int (XdeltaStream *str, guint seg_len) { guint to_index = seg_len; XdeltaPos pos; XdeltaChecksum cksum; GArray *index; EdsioMD5Ctx ctx; index = g_array_new (FALSE, FALSE, sizeof (XdeltaRsyncElt)); init_pos (str, &pos); memset (&cksum, 0, sizeof (cksum)); edsio_md5_init (& ctx); for (;;) { gint consume; if (! map_page (str, &pos)) return NULL; consume = MIN (to_index, pos.mem_rem - pos.off); if (consume == 0) break; to_index -= consume; edsio_md5_update (& ctx, pos.mem + pos.off, consume); init_long_checksum (pos.mem + pos.off, consume, &cksum); if (to_index == 0) { XdeltaRsyncElt elt; edsio_md5_final (elt.md5, &ctx); elt.cksum = cksum; g_array_append_val (index, elt); edsio_md5_init (& ctx); memset (&cksum, 0, sizeof (cksum)); to_index = seg_len; } pos.off += consume; FLIP_FORWARD (pos); } if (! unmap_page (str, &pos)) return NULL; { XdeltaRsync* rsync = g_new (XdeltaRsync, 1); rsync->seg_len = seg_len; rsync->file_len = handle_length (str); memcpy (rsync->file_md5, handle_checksum_md5 (str), 16); rsync->index = &g_array_index (index, XdeltaRsyncElt, 0); rsync->index_len = index->len; return rsync; } } static XdeltaRsync* xdp_rsync_read_index (XdeltaStream* cache_in) { SerialSource* src = handle_source (cache_in); XdeltaRsync* rsync; if (! src) return NULL; if (! unserialize_rsyncindex (src, &rsync)) return NULL; return rsync; } static gboolean xdp_rsync_write_index (XdeltaRsync* rsync, XdeltaOutStream* cache_out) { SerialSink* sink = handle_sink (cache_out, NULL, NULL, NULL, NULL); if (! sink) return FALSE; if (! serialize_rsyncindex_obj (sink, rsync)) return FALSE; if (! handle_close (cache_out, 0)) return FALSE; return TRUE; } XdeltaRsync* xdp_rsync_index (XdeltaStream *str, guint seg_len, XdeltaStream *cache_in, XdeltaOutStream *cache_out) { XdeltaRsync* rsync; if (cache_in) { if (! (rsync = xdp_rsync_read_index (cache_in))) return NULL; if (seg_len != rsync->seg_len || (str && ! check_stream_integrity (str, rsync->file_md5, rsync->file_len))) { xd_generate_void_event (EC_XdInvalidRsyncCache); goto bail; } return rsync; } else { if (! (rsync = xdp_rsync_index_int (str, seg_len))) return NULL; if (cache_out) { if (! xdp_rsync_write_index (rsync, cache_out)) goto bail; } return rsync; } bail: xdp_rsync_index_free (rsync); return NULL; } void xdp_rsync_index_free (XdeltaRsync *rsync) { /* ??? */ } static gboolean xdp_rsync_hash (XdeltaRsync* rsync) { guint i, index, prime = 0; gboolean already_hashed = rsync->table != NULL; SerialRsyncIndexElt** table = NULL; if (! already_hashed) { prime = rsync->table_size = g_spaced_primes_closest (rsync->index_len); table = rsync->table = g_new0 (SerialRsyncIndexElt*, prime); } for (i = 0; i < rsync->index_len; i += 1) { SerialRsyncIndexElt* elt = rsync->index + i; elt->match_offset = -1; if (! already_hashed) { index = c_hash (& elt->cksum) % prime; elt->next = table[index]; table[index] = elt; } } return TRUE; } static void incr_by (XdeltaPos* pos, gint incr) { do { gint rem = MIN (incr, pos->mem_rem - pos->off); pos->off += incr; incr -= rem; FLIP_FORWARD (*pos); } while (incr > 0 && pos->mem_rem != pos->page_size); } GArray* xdp_rsync_request (XdeltaStream *file, XdeltaRsync *rsync) { XdeltaPos opos, npos; XdeltaChecksum cksum; guint max_buffer_index = handle_length (file); GArray *request = g_array_new (FALSE, FALSE, sizeof (guint)); const guint8* n_pointer, *o_pointer; guint thistime; guint prime, index; SerialRsyncIndexElt **table; guint i; guint matched = 0; guint16 old_c, new_c; if (max_buffer_index < rsync->seg_len) return request; max_buffer_index -= rsync->seg_len; if (! xdp_rsync_hash (rsync)) return NULL; g_assert (rsync->seg_len < handle_pagesize (file)); init_pos (file, &opos); init_pos (file, &npos); memset (&cksum, 0, sizeof (cksum)); prime = rsync->table_size; table = rsync->table; if (!map_page (file, &opos)) return NULL; init_long_checksum (opos.mem, rsync->seg_len, &cksum); npos.off += rsync->seg_len; for (; XPOS (opos) < max_buffer_index; ) { if (!map_page (file, &opos)) return FALSE; if (!map_page (file, &npos)) return FALSE; if (matched == rsync->index_len) break; thistime = MIN (opos.mem_rem - opos.off, npos.mem_rem - npos.off); o_pointer = opos.mem + opos.off; n_pointer = npos.mem + npos.off; for (; ; o_pointer += 1, n_pointer += 1) { index = c_hash (&cksum) % prime; if (table[index]) { gboolean md5_computed = FALSE; gboolean found = FALSE; guint8 md5[16]; SerialRsyncIndexElt* elt; for (elt = table[index]; elt; elt = elt->next) { if (elt->match_offset >= 0) continue; if (elt->cksum.high != cksum.high || elt->cksum.low != cksum.low) continue; if (! md5_computed) { EdsioMD5Ctx ctx; edsio_md5_init (& ctx); if (opos.page == npos.page) edsio_md5_update (& ctx, opos.mem + opos.off, rsync->seg_len); else { edsio_md5_update (& ctx, opos.mem + opos.off, opos.mem_rem - opos.off); edsio_md5_update (& ctx, npos.mem, rsync->seg_len - (opos.mem_rem - opos.off)); } edsio_md5_final (md5, & ctx); md5_computed = TRUE; } if (memcmp (md5, elt->md5, 16) == 0) { matched += 1; found = TRUE; elt->match_offset = XPOS (opos); } } if (found) { incr_by (&opos, rsync->seg_len); incr_by (&npos, rsync->seg_len); goto reenter; } } if (thistime == 0) goto nextpage; thistime -= 1; opos.off += 1; npos.off += 1; old_c = CHEW(*o_pointer); new_c = CHEW(*n_pointer); cksum.low -= old_c; cksum.low += new_c; cksum.high -= old_c * rsync->seg_len; cksum.high += cksum.low; } nextpage: FLIP_FORWARD (opos); FLIP_FORWARD (npos); reenter: (void) 0; } for (i = 0; i < rsync->index_len; i += 1) { SerialRsyncIndexElt* elt = rsync->index + i; if (elt->match_offset < 0) { #ifdef DEBUG_RSYNC_REQUEST g_print ("request segment %d\n", i); #endif g_array_append_val (request, i); } } return request; } gboolean xdp_apply_rsync_reply (XdeltaRsync *rsync, XdeltaStream *from, XdeltaStream *reply, XdeltaStream *out) { gint i; guint reply_offset = 0; for (i = 0; i < rsync->index_len; i += 1) { SerialRsyncIndexElt* elt = rsync->index + i; if (elt->match_offset >= 0) { if (! handle_copy (from, out, elt->match_offset, rsync->seg_len)) return FALSE; } else { if (! handle_copy (reply, out, reply_offset, rsync->seg_len)) return FALSE; reply_offset += rsync->seg_len; } } if (! handle_copy (reply, out, reply_offset, rsync->file_len % rsync->seg_len)) return FALSE; if (! handle_close (out, 0)) return FALSE; if (! check_stream_integrity (out, rsync->file_md5, rsync->file_len)) return FALSE; return TRUE; }