pax_global_header00006660000000000000000000000064141070264730014516gustar00rootroot0000000000000052 comment=85067ba03468417527040dc435e2a46cc4f4b491 dcfldd-1.7.1/000077500000000000000000000000001410702647300127445ustar00rootroot00000000000000dcfldd-1.7.1/.github/000077500000000000000000000000001410702647300143045ustar00rootroot00000000000000dcfldd-1.7.1/.github/workflows/000077500000000000000000000000001410702647300163415ustar00rootroot00000000000000dcfldd-1.7.1/.github/workflows/full-check.yml000066400000000000000000000012161410702647300211010ustar00rootroot00000000000000name: full-check on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: first_build run: | ./autogen.sh ./configure make sudo make install sudo make uninstall make distclean - name: second_build run: | ./autogen.sh ./configure make sudo make install - name: run_program run: | dcfldd if=.github/workflows/test.txt of=/tmp/test2.txt hash=md5,sha1,sha256,sha384,sha512 ls -lh /tmp/test2.txt head -n3 /tmp/test2.txt dcfldd-1.7.1/.github/workflows/release-tarball.yml000066400000000000000000000030241410702647300221220ustar00rootroot00000000000000name: Release tarball on: push: tags: - "**" jobs: release: name: "Release" runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: "Determine tag" id: "determine-tag" run: "echo \"::set-output name=tag::${GITHUB_REF#refs/tags/v}\"" - name: "Determine configure.ac version" id: "determine-ac" run: "echo \"::set-output name=version::`sed -n -E 's/AC_INIT\\(\\[dcfldd\\], \\[(.+?)\\],.*$/\\1/p' configure.ac`\"" - name: "Fail when tag version != configure.ac version" run: "exit 1" if: steps.determine-tag.outputs.tag != steps.determine-ac.outputs.version - name: Build and check distribution tarball run: | ./autogen.sh ./configure make distcheck - name: Create Release id: create_release uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: v${{ steps.determine-tag.outputs.tag }} release_name: Release ${{ steps.determine-tag.outputs.tag }} draft: false prerelease: false - name: Upload Release Asset id: upload-release-asset uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: ./dcfldd-${{ steps.determine-tag.outputs.tag }}.tar.gz asset_name: dcfldd-${{ steps.determine-tag.outputs.tag }}.tar.gz asset_content_type: application/gzip dcfldd-1.7.1/.github/workflows/test.txt000066400000000000000000000433731410702647300200730ustar00rootroot00000000000000Autopkgtest - Defining tests for Debian packages This document describes how autopkgtest interprets and executes tests found in Debian source packages. Overview The source package provides a test metadata file debian/tests/control. This enumerates the tests and specifies their dependencies and requirements for the testbed. It contains zero or more RFC822-style stanzas, along these lines: Tests: fred, bill, bongo Depends: pkg1, pkg2 [amd64] | pkg3 (>= 3) Restrictions: needs-root, breaks-testbed This example defines three tests, called fred, bill and bongo. The tests will be performed by executing debian/tests/fred, debian/tests/bill, etc. Each test program should, on success, exit with status 0 and print nothing to stderr; if a test exits nonzero, or prints to stderr, it is considered to have failed. The cwd of each test is guaranteed to be the root of the source package, which will have been unpacked but not built. However note that the tests must test the installed version of the package, as opposed to programs or any other file from the built tree. Tests may not modify the source tree (and may not have write access to it). If the file to be executed has no execute bits set, chmod a+x is applied to it (this means that tests can be added in patches without the need for additional chmod; contrast this with debian/rules). During execution of the test, the environment variable $AUTOPKGTEST_TMP will point to a directory for the execution of this particular test, which starts empty and will be deleted afterwards (so there is no need for the test to clean up files left there). If tests want to create artifacts which are useful to attach to test results, such as additional log files or screenshots, they can put them into the directory specified by the $AUTOPKGTEST_ARTIFACTS environment variable. When using the --output-dir option, they will be copied into outputdir/artifacts/. Tests must declare all applicable Restrictions - see below. The '#' character introduces a comment. Everything from '#' to the end of line will be entirely ignored. Examples Simplest possible control file that installs all of the source package's binary packages and runs the standalone debian/tests/smoke test script as user, without any further limitations: Tests: smoke Control file for an inline test command that just calls a program foo-cli from package foo (which usually should be a binary of the source package that contains this test control) as root, and makes sure it exits with zero: Test-Command: foo-cli --list --verbose Depends: foo Restrictions: needs-root Control fields The fields which may appear in debian/tests/control stanzas are: Tests: name-of-test [, name-of-another-test ...] This field names the tests which are defined by this stanza, and map to executables/scripts in the test directory. All of the other fields in the same stanza apply to all of the named tests. Either this field or Test-Command: must be present. Test names are separated by comma and/or whitespace and should contain only characters which are legal in package names. It is permitted, but not encouraged, to use upper-case characters as well. Test-Command: shell command If your test only contains a shell command or two, or you want to re-use an existing upstream test executable and just need to wrap it with some command like dbus-launch or env, you can use this field to specify the shell command directly. It will be run under bash -e. This is mutually exclusive with the Tests: field. This is also useful for running the same script under different interpreters and/or with different dependencies, such as Test-Command: python debian/tests/mytest.py and Test-Command: python3 debian/tests/mytest.py. Restrictions: restriction-name [, another-restriction-name ...] Declares some restrictions or problems with the tests defined in this stanza. Depending on the test environment capabilities, user requests, and so on, restrictions can cause tests to be skipped or can cause the test to be run in a different manner. Tests which declare unknown restrictions will be skipped. See below for the defined restrictions. Restrictions are separated by commas and/or whitespace. Features: feature-name [, another-feature-name ...] Declares some additional capabilities or good properties of the tests defined in this stanza. Any unknown features declared will be completely ignored. See below for the defined features. Features are separated by commas and/or whitespace. Depends: dpkg dependency field syntax Declares that the specified packages must be installed for the test to go ahead. This supports all features of dpkg dependencies, including the architecture qualifiers (see https://www.debian.org/doc/debian-policy/ch-relationships.html), plus the following extensions: @ stands for the package(s) generated by the source package containing the tests; each dependency (strictly, or-clause, which may contain |s but not commas) containing @ is replicated once for each such binary package, with the binary package name substituted for each @ (but normally @ should occur only once and without a version restriction). @builddeps@ will be replaced by the package's Build-Depends:, Build-Depends-Indep:, Build-Depends-Arch:, and build-essential. This is useful if you have many build dependencies which are only necessary for running the test suite and you don't want to replicate them in the test Depends:. However, please use this sparingly, as this can easily lead to missing binary package dependencies being overlooked if they get pulled in via build dependencies. If no Depends field is present, Depends: @ is assumed. Note that the source tree's Build-Dependencies are not necessarily installed, and if you specify any Depends, no binary packages from the source are installed unless explicitly requested. Tests-Directory: path Replaces the path segment debian/tests in the filenames of the test programs with path. I. e., the tests are run by executing built/source/tree/path/testname. path must be a relative path and is interpreted starting from the root of the built source tree. This allows tests to live outside the debian/ metadata area, so that they can more palatably be shared with non-Debian distributions. Classes: class-1 [, class-2 ...] Most package tests should work in a minimal environment and are usually not hardware specific. However, some packages like the kernel, X.org, or graphics drivers should be tested on particular hardware, and also run on a set of different platforms rather than just a single virtual testbeds. This field can specify a list of abstract class names such as "desktop" or "graphics-driver". Consumers of autopkgtest can then map these class names to particular machines/platforms/policies. Unknown class names should be ignored. This is purely an informational field for autopkgtest itself and will be ignored. Classes are separated by commas and/or whitespace. Any unknown fields will cause the whole stanza to be skipped. Defined restrictions rw-build-tree The test(s) needs write access to the built source tree (so it may need to be copied first). Even with this restriction, the test is not allowed to make any change to the built source tree which (i) isn't cleaned up by debian/rules clean, (ii) affects the future results of any test, or (iii) affects binary packages produced by the build tree in the future. breaks-testbed The test, when run, is liable to break the testbed system. This includes causing data loss, causing services that the machine is running to malfunction, or permanently disabling services; it does not include causing services on the machine to temporarily fail. When this restriction is present the test will usually be skipped unless the testbed's virtualisation arrangements are sufficiently powerful, or alternatively if the user explicitly requests. needs-root The test script must be run as root. While running tests with this restriction, some test runners will set the AUTOPKGTEST_NORMAL_USER environment variable to the name of an ordinary user account. If so, the test script may drop privileges from root to that user, for example via the runuser command. Test scripts must not assume that this environment variable will always be set. build-needed The tests need to be run from a built source tree. The test runner will build the source tree (honouring the source package's build dependencies), before running the tests. However, the tests are not entitled to assume that the source package's build dependencies will be installed when the test is run. Please use this considerately, as for large builds it unnecessarily builds the entire project when you only need a tiny subset (like the tests/ subdirectory). It is often possible to run make -C tests instead, or copy the test code to $AUTOPKGTEST_TMP and build it there with some custom commands. This cuts down the load on the Continuous Integration servers and also makes tests more robust as it prevents accidentally running them against the built source tree instead of the installed packages. allow-stderr Output to stderr is not considered a failure. This is useful for tests which write e. g. lots of logging to stderr. isolation-container The test wants to start services or open network TCP ports. This commonly fails in a simple chroot/schroot, so tests need to be run in their own container (e. g. autopkgtest-virt-lxc) or their own machine/VM (e. g. autopkgtest-virt-qemu or autopkgtest-virt-null). When running the test in a virtualization server which does not provide this (like autopkgtest-schroot) it will be skipped. isolation-machine The test wants to interact with the kernel, reboot the machine, or other things which fail in a simple schroot and even a container. Those tests need to be run in their own machine/VM (e. g. autopkgtest-virt-qemu or autopkgtest-virt-null). When running the test in a virtualization server which does not provide this it will be skipped. needs-reboot The test wants to reboot the machine using /tmp/autopkgtest-reboot (see below). needs-recommends (deprecated) Enable installation of recommended packages in apt for the test dependencies. This does not affect build dependencies. Don't use this for new tests, we want to remove it altogether. See https://lists.debian.org/debian-ci/2018/06/msg00016.html and bug 896698 for the rationale. flaky The test is expected to fail intermittently, and is not suitable for gating continuous integration. This indicates a bug in either the package under test, a dependency or the test itself, but such bugs can be difficult to fix, and it is often difficult to know when the bug has been fixed without running the test for a while. If a flaky test succeeds, it will be treated like any other successful test, but if it fails it will be treated as though it had been skipped. skippable The test might need to be skipped for reasons that cannot be described by an existing restriction such as isolation-machine or breaks-testbed, but must instead be detected at runtime. If the test exits with status 77 (a convention borrowed from Automake), it will be treated as though it had been skipped. If it exits with any other status, its success or failure will be derived from the exit status and stderr as usual. Test authors must be careful to ensure that skippable tests never exit with status 77 for reasons that should be treated as a failure. skip-not-installable This test might have test dependencies that can't be fulfilled on all architectures. Therefore, when apt-get installs the dependencies, it will fail. Don't treat this as a test failure, but instead treat it as if the test was skipped. hint-testsuite-triggers This test exists purely as a hint to suggest when rerunning the tests is likely to be useful. Specifically, it exists to influence the way dpkg-source generates the Testsuite-Triggers .dsc header from test metadata: the Depends for this test are to be added to Testsuite-Triggers. (Just as they are for any other test.) The test with the hint-testsuite-triggers restriction should not actually be run. Future systems which understand per-test update triggering should treat the Depends of the test with this restriction, as triggering packages for all tests in this debian/tests/control. The packages listed as Depends for this test are usually indirect dependencies, updates to which are considered to pose a risk of regressions in other tests defined in this package. There is currently no way to specify this hint on a per-test basis; but in any case the debian.org machinery is not able to think about triggering individual tests. superficial The test does not provide significant test coverage, so if it passes, that does not necessarily mean that the package under test is actually functional. If a superficial test fails, it will be treated like any other failing test, but if it succeeds, this is only a weak indication of success. Continuous integration systems should treat a package where all non-superficial tests are skipped as equivalent to a package where all tests are skipped. For example, a C library might have a superficial test that simply compiles, links and executes a "hello world" program against the library under test but does not attempt to make use of the library's functionality, while a Python or Perl library might have a superficial test that runs import foo or require Foo; but does not attempt to use the library beyond that. Defined features test-name Set an explicit test name for the log heading and the summary file for a Test-Command: inline test. When not given, these are enumerated like command1. Source package header To allow test execution environments to discover packages which provide tests, their source packages need to have a Testsuite: header containing autopkgtest (or a value like autopkgtest-pkg-perl, see below). Multiple values get comma separated, as usual in control files. This tag is added automatically by dpkg-source version 1.17.11 or later, so normally you don't need to worry about this field. Automatic test control file for known package types There are groups of similarly-structured packages for which the contents of debian/tests/control would be mostly identical, such as Perl or Ruby libraries. If debian/tests/control is absent, the autodep8 tool can generate an automatic control file. If installed, autopkgtest will automatically use it; this can be disabled with the --no-auto-control option. Those packages do not have to provide debian/tests/, but they should still include an appropriate source package header (Testsuite: autopkgtest-pkg-perl or similar) so that they can be discovered in the archive. Reboot during a test Some testbeds support rebooting; for those, the testbed will have a /tmp/autopkgtest-reboot command which tests can call to cause a reboot. Do not use reboot and similar commands directly without at least checking for the presence of that script! They will cause testbeds like null or schroot to reboot the entire host, and even for lxc or qemu it will just cause the test to fail as there is no state keeping to resume a test at the right position after reboot without further preparation (see below). The particular steps for a rebooting tests are: The test calls /tmp/autopkgtest-reboot my_mark with a "mark" identifier. autopkgtest-reboot will cause the test to terminate (with SIGKILL). autopkgtest backs up the current state of the test source tree and any $AUTOPKGTEST_ARTIFACTS that were created so far, reboots the testbed, and restores the test source tree and artifacts. The test gets run again, this time with a new environment variable $AUTOPKGTEST_REBOOT_MARK containing the argument to autopkgtest-reboot, e. g. my_mark. The test needs to check $AUTOPKGTEST_REBOOT_MARK and jump to the appropriate point. A nonexisting variable means "start from the beginning". This example test will reboot the testbed two times in between: #!/bin/sh -e case "$AUTOPKGTEST_REBOOT_MARK" in "") echo "test beginning"; /tmp/autopkgtest-reboot mark1 ;; mark1) echo "test in mark1"; /tmp/autopkgtest-reboot mark2 ;; mark2) echo "test in mark2" ;; esac echo "test end" In some cases your test needs to do the reboot by itself, e. g. through kexec, or a reboot command that is hardcoded in the piece of software that you want to test. To support those, you need to call /tmp/autopkgtest-reboot-prepare my_mark at a point as close as possible to the reboot instead; this will merely save the state but not issue the actual reboot by itself. Note that all logs and artifacts from the time between calling autopkgtest-reboot-prepare and rebooting will be lost. Other than that, the usage is very similar to above. Example: #!/bin/sh if [ "$AUTOPKGTEST_REBOOT_MARK" = phase1 ]; then echo "continuing test after reboot" ls -l /var/post-request-action echo "end of test" else echo "beginning test" /tmp/autopkgtest-reboot-prepare phase1 touch /var/post-request-action reboot fi Network access autopkgtest needs access to the network at least for downloading test dependencies and possibly dist-upgrading testbeds. In environments with restricted internet access you need to set up an apt proxy and configure the testbed to use it. (Note that the standard tools like autopkgtest-build-lxc or mk-sbuild automatically use the apt proxy from the host system.) In general, tests are also allowed to access the internet. As this usually makes tests less reliable, this should be kept to a minimum; but for many packages their main purpose is to interact with remote web services and thus their testing should actually cover those too, to ensure that the distribution package keeps working with their corresponding web service. Debian's production CI infrastructure allows unrestricted network access, in Ubuntu's infrastructure access to sites other than *.ubuntu.com and *.launchpad.net happens via a proxy (limited to DNS and http/https). dcfldd-1.7.1/AUTHORS000066400000000000000000000002571410702647300140200ustar00rootroot00000000000000GNU dd by Paul Rubin, David MacKenzie and Stuart Kemp dcfldd by Nicholas Harbour and some colaborators In 2019, the project was migrated to GitHub by Joao Eriberto Mota Filho dcfldd-1.7.1/CONTRIBUTING.md000066400000000000000000000017261410702647300152030ustar00rootroot00000000000000## HOW TO CONTRIBUTE TO DCFLDD DEVELOPMENT dcfldd is available at https://github.com/resurrecting-open-source-projects/dcfldd If you are interested in contribute to dcfldd development, please, follow these steps: 1. Send a patch that fix an issue or that implement a new feature. Alternatively, you can do a 'pull request'[1] in GitHub. [1] https://help.github.com/articles/about-pull-requests 2. Ask for join to the dcfldd project in GitHub, if you want to work officially. Note that this second step is not compulsory. However, to accept you in project, is needed a minimum previous collaboration. To find issues and bugs to fix, you can check these addresses: - https://github.com/resurrecting-open-source-projects/dcfldd - https://bugs.debian.org/cgi-bin/pkgreport.cgi?dist=unstable;package=dcfldd - https://bugs.launchpad.net/ubuntu/+source/dcfldd/+bugs If you want to join, please make a contact. -- Eriberto, Mon, 28 Oct 2019 23:29:53 -0300. dcfldd-1.7.1/COPYING000066400000000000000000000432541410702647300140070ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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 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) 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) year 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 Lesser General Public License instead of this License. dcfldd-1.7.1/ChangeLog000066400000000000000000000075021410702647300145220ustar00rootroot000000000000002021-08-17 Joao Eriberto Mota Filho Version 1.7.1 [ Joao Eriberto Mota Filho ] * Changes to process manpage in main Makefile.am. * Created CI test in GitHub. * Updated install system, removed warnings and bumped required autoconf to 2.69. [ David Polverari ] * New internal feature: release make distcheck tarball on tag push (automated distcheck), via GitHub actions. 2020-02-02 Joao Eriberto Mota Filho Version 1.7 [ David Polverari ] * src/sizeprobe.c: fixed destination size unit. (Debian bug #886647) * src/util.c: fixed non-Linux build error. 2020-01-13 Joao Eriberto Mota Filho Version 1.6 [ Joao Eriberto Mota Filho ] * Updated bash completion script. [ David Polverari ] * Fixed a segfault when using 'errlog='. 2019-11-02 Joao Eriberto Mota Filho Version 1.5 [ Joao Eriberto Mota Filho ] * Autotools files: - Added a distclean-local target in Makefile.am. - Added the autogen.sh file. - Improved the configure.ac and Makefile.am files. - Moved some build lines from Makefile.am to src/Makefile.am. - Removed all autogenerated files. * Added a bash completion script (from Debian). * Created CONTRIBUTING.md file. * Fixed some building warnings. * Fixed the message when using hashes (add a newline to generate a space between the summary message and hashes. * Manpage and help page: - Added all new features from David Loveall to manpage and help page. - Full reviewed and improved the manpage and help page. Added examples in manpage. - Using txt2man to produce an updated manpage. * Moved all source code to src/. * Reorganized AUTHORS and ChangeLog files. * Rewritten README file, now called README.md. * Set -fgnu89-inline in CFLAGS to avoid warning (fix: 'warning: inline function 'quit' declared but never defined'). * Updated all headers and rights. * Updated GPL-2 text in all headers and in COPYING files. [ Bernhard Übelacker ] * Fixed include order to avoid different definitions of off_t. Patch from Debian. [ David Loveall ] * Several changes and improvements. Patch from SF.net[1]. Changes from Dave. Additions: - Allows for partial write of block during conv=sync if at the end of input. - Allows limit=<# of bytes> to limit the count of input, rather than count=<# of blocks>. - Closes all popened processes. (Uses internal popen call, rather than original popen2.) - Allows sizeprobe=<# of bytes> to manually specify. - Allows for splitformat=MAC to use output file naming of foo.dmg, foo.002.dmgpart, ..., foo.999.dmgpart, foo.1000.dmgpart, .... - Allows for splitformat=WIN to use output file naming of foo.001, foo.002, ..., foo.999, foo.1000, .... - Fixes too many opened files bug. [ Martin Scharrer ] * Fix exception for statusinterval=0. Patch from SF.net. [ Miah Gregory ] * Fixed implicit declaration warnings. Patch from Debian. * Fixed a spelling error. Patch from Debian. [ Vangelis Koukis ] * Fixed size probing of large block devices. Patch from Debian. * Fixed the sizeprobe=of option. Patch from Debian. ---- OLD AND INCOMPLETE CHANGELOG ---- Changes from version 1.2.2: - Added ability to write to multiple output files. - Added split capability with the "split=" and "splitformat=" switches. - Converts "if=/dev/zero" to "pattern=00" to force efficiency. - Fixed a few bugs with verify. Changes from version 1.2.1: - Fixed large file support bug - added verify capability Changes from version 1.0: - Added SHA-1, SHA-256, SHA-384 and SHA-512 support - Fixed compile errors. - Fixed Megabyte constant. - Fixed problem with not displaying the final hash remainder. - Created an entirely new (and trim) build environment. dcfldd-1.7.1/Makefile.am000066400000000000000000000022731410702647300150040ustar00rootroot00000000000000# configure.ac, was previously configure.in (before 2019) # # Copyright ?-2002 Jim Meyering # Copyright 2002-2006 Nicholas Harbour # Copyright 2019-2021 Joao Eriberto Mota Filho # # 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., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. AUTOMAKE_OPTIONS = foreign no-dependencies SUBDIRS = src man_MANS = man/dcfldd.1 distclean-local: rm -rf autom4te.cache rm -f aclocal.m4 compile config.* configure depcomp install-sh \ Makefile.in missing man/Makefile.in src/Makefile.in dcfldd-1.7.1/NEWS000066400000000000000000000002371410702647300134450ustar00rootroot00000000000000Version 1.5 ----------- New options: - limit - using bytes in sizeprobe - MAC/WIN in split format Added several examples in manpage. See the manpage. dcfldd-1.7.1/README000077700000000000000000000000001410702647300150762README.mdustar00rootroot00000000000000dcfldd-1.7.1/README.md000066400000000000000000000046611410702647300142320ustar00rootroot00000000000000# dcfldd #### dcfldd - enhanced version of dd for forensics and security ## Help this project ## dcfldd needs your help. **If you are a programmer** and if you wants to help a nice project, this is your opportunity. dcfldd was imported from some tarballs (the original homepage[1] and developers are inactive). After this, all patches found in Debian project and other places for this program were applied. All initial work was registered in ChangeLog file (version 1.5 and later releases). dcfldd is being packaged in Debian[2] Project. If you are interested to help dcfldd, read the [CONTRIBUTING.md](CONTRIBUTING.md) file. [1]: https://sourceforge.net/projects/dcfldd [2]: https://tracker.debian.org/pkg/dcfldd ## What is dcfldd? ## dcfldd is a modified version of GNU dd. The major features added are: - Hashing on-the-fly: dcfldd can hash the input data as it is being transferred, helping to ensure data integrity. - Status output: dcfldd can update the user of its progress in terms of the amount of data transferred and how much longer operation will take. - Flexible disk wipes: dcfldd can be used to wipe disks quickly and with a known pattern if desired. - Image/wipe verify: dcfldd can verify that a target drive is a bit-for-bit match of the specified input file or pattern. - Multiple outputs: dcfldd can output to multiple files or disks at the same time. - Split output: dcfldd can split output to multiple files with more configurability than the split command. - Piped output and logs: dcfldd can send all its log data and output to commands as well as files natively. dcfldd was originally created by Nicholas Harbour from the DoD Computer Forensics Laboratory (DCFL). Nick Harbour still maintaining the package, although he was no longer affiliated with the DCFL. Nowadays, dcfldd is maintained by volunteers. ## Build and Install ## To build and install, run the following commands: $ ./autogen.sh $ ./configure $ make # make install To return to original source code you can use '$ make distclean' command. On Debian systems you can use '# apt install dcfldd'. There is a bash completion file inside doc/ directory in source code. ## Author ## dcfldd was originally developed by Nicholas Harbour under GPL-2+ license. Currently, the source code and newer versions are available at https://github.com/resurrecting-open-source-projects/dcfldd See AUTHORS file for more information. dcfldd-1.7.1/autogen.sh000077500000000000000000000043661410702647300147560ustar00rootroot00000000000000#!/bin/sh # autogen.sh with clean option # Copyright 2016 Joao Eriberto Mota Filho # # This file is under BSD-3-Clause license. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the authors nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # Use clean option if [ "$1" = "clean" -a ! -e Makefile ] then echo "Vanishing the code" rm -rf aclocal.m4 autom4te.cache compile config.guess config.h.in \ config.sub configure depcomp install-sh Makefile.in missing \ man/Makefile.in src/Makefile.in exit 0 fi # Do not use clean option if [ "$1" = "clean" -a -e Makefile ] then echo "I can not clean. Use '$ make distclean'." exit 0 fi # Do autoreconf autoreconf -i \ && { echo " "; \ echo "Done. You can use the 'clean' option to vanish the source code."; \ echo "Example of use: $ ./autogen clean"; \ } \ || { echo "We have a problem..."; exit 1; } dcfldd-1.7.1/configure.ac000066400000000000000000000026441410702647300152400ustar00rootroot00000000000000# configure.ac, was previously configure.in (before 2019) # # Copyright ?-2001 Jim Meyering # Copyright 2001-2006 Nicholas Harbour # Copyright 2019-2021 Joao Eriberto Mota Filho # # 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., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. AC_PREREQ([2.69]) AC_INIT([dcfldd],[1.7.1],[https://github.com/resurrecting-open-source-projects/dcfldd/issues]) AC_CONFIG_SRCDIR(src/dcfldd.c) AM_INIT_AUTOMAKE AC_CONFIG_HEADERS([config.h]) AC_CANONICAL_HOST AC_PROG_CC AC_PROG_CPP AC_PROG_GCC_TRADITIONAL AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET AC_PROG_RANLIB AC_PROG_EGREP AC_C_CONST AC_TYPE_OFF_T AC_TYPE_SIZE_T AC_CHECK_DECLS([strtol, strtoul, strtoumax, strndup]) AC_CONFIG_FILES([Makefile src/Makefile]) AC_OUTPUT dcfldd-1.7.1/doc/000077500000000000000000000000001410702647300135115ustar00rootroot00000000000000dcfldd-1.7.1/doc/UPDATE-CHECK000066400000000000000000000004571410702647300152370ustar00rootroot00000000000000When updating, change the following files (if needed): - Update rights - ChangeLog - Check for spelling errors in ChangeLog, manpage and README. - Check final manpage with man command. - configure.ac (VERSION) - man/create-man.sh (DATE, version) - Generate a new manpage. - README - Test in Debian Sid dcfldd-1.7.1/doc/dcfldd-bash_completion000066400000000000000000000035441410702647300200260ustar00rootroot00000000000000# bash completion for dcfldd -*- shell-script -*- # Copyright 2017-2020 Joao Eriberto Mota Filho # Version: 20200113 # Based in dd completion script. _dcfldd() { local cur prev words cword _init_completion -n = || return case $cur in conv=*) cur=${cur#*=} COMPREPLY=( $( compgen -W 'ascii ebcdic ibm block unblock lcase notrunc ucase swab noerror sync' -- "$cur" ) ) return 0 ;; errlog=*|if=*|of=*|md5log=*|sha1log=*|sha256log=*|sha384log=*|sha512log=*|verifylog=*|vf=*) cur=${cur#*=} _filedir return 0 ;; hash=*) cur=${cur#*=} realcur=${cur##*,} COMPREPLY=( $( compgen -W 'md5 sha1 sha256 sha384 sha512' -- "$realcur" ) ) return 0 ;; hashconv=*) cur=${cur#*=} COMPREPLY=( $( compgen -W 'before after' -- "$cur" ) ) return 0 ;; status=*) cur=${cur#*=} COMPREPLY=( $( compgen -W 'on off' -- "$cur" ) ) return 0 ;; sizeprobe=*) cur=${cur#*=} COMPREPLY=( $( compgen -W 'if of' -- "$cur" ) ) return 0 ;; esac _expand || return 0 COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "$cur" ) \ $( compgen -W 'bs cbs conv count limit ibs if obs of seek skip pattern textpattern errlog hash md5log sha1log sha256log sha384log sha512log hashwindow hashconv hashformat totalhashformat status statusinterval sizeprobe split splitformat vf verifylog' -S '=' -- "$cur" ) ) } && complete -F _dcfldd -o nospace dcfldd dcfldd-1.7.1/man/000077500000000000000000000000001410702647300135175ustar00rootroot00000000000000dcfldd-1.7.1/man/create-man.sh000077500000000000000000000011571410702647300160760ustar00rootroot00000000000000#!/bin/bash # Copyright 2015-2019 Joao Eriberto Mota Filho # Create a manpage using txt2man command. # # This script can be used under BSD-3-Clause license. T2M_DATE="02 Feb 2020" T2M_NAME=dcfldd T2M_VERSION=1.7 T2M_LEVEL=1 T2M_DESC="enhanced version of dd for forensics and security" # Don't change the following lines TEST=$(txt2man -h 2> /dev/null) [ "$TEST" ] || { echo -e "\nYou need to install txt2man, from https://github.com/mvertes/txt2man.\n"; exit 1; } txt2man -d "$T2M_DATE" -t $T2M_NAME -r $T2M_NAME-$T2M_VERSION -s $T2M_LEVEL -v "$T2M_DESC" $T2M_NAME.txt > $T2M_NAME.$T2M_LEVEL dcfldd-1.7.1/man/dcfldd.1000066400000000000000000000277451410702647300150400ustar00rootroot00000000000000.\" Text automatically generated by txt2man .TH dcfldd 1 "02 Feb 2020" "dcfldd-1.7" "enhanced version of dd for forensics and security" .SH NAME \fBdcfldd \fP- enhanced version of dd for forensics and security \fB .SH SYNOPSIS .nf .fam C \fBdcfldd\fP [OPTION]\.\.\. .fam T .fi .fam T .fi .SH DESCRIPTION Copy a file, converting and formatting according to the options. .PP \fBdcfldd\fP was initially developed at Department of Defense Computer Forensics Lab (DCFL). This tool is based on the dd program with the following additional features: .IP \(bu 3 Hashing on-the-fly: \fBdcfldd\fP can hash the input data as it is being transferred, helping to ensure data integrity. .IP \(bu 3 Status output: \fBdcfldd\fP can update the user of its progress in terms of the amount of data transferred and how much longer operation will take. .IP \(bu 3 Flexible disk wipes: \fBdcfldd\fP can be used to wipe disks quickly and with a known pattern if desired. .IP \(bu 3 Image/wipe verify: \fBdcfldd\fP can verify that a target drive is a bit-for-bit match of the specified input file or pattern. .IP \(bu 3 Multiple outputs: \fBdcfldd\fP can output to multiple files or disks at the same time. .IP \(bu 3 Split output: \fBdcfldd\fP can split output to multiple files with more configurability than the split command. .IP \(bu 3 Piped output and logs: \fBdcfldd\fP can send all its log data and output to commands as well as files natively. .IP \(bu 3 When dd uses a default block size (bs, ibs, obs) of 512 bytes, \fBdcfldd\fP uses 32768 bytes (32 KiB) which is HUGELY more efficient. .IP \(bu 3 The following options are present in \fBdcfldd\fP but not in dd: ALGORITHMlog:, errlog, hash, hashconv, hashformat, hashlog, hashlog:, hashwindow, limit, of:, pattern, sizeprobe, split, splitformat, statusinterval, textpattern, totalhashformat, verifylog, verifylog:, vf. .PP \fBdcfldd\fP supports the following letters to specify amount of data: k for kilo, M for Mega, G for Giga, T for Tera, P for Peta, E for Exa, Z for Zetta and Y for Yotta. E.g. 10M is equal to 10 MiB. See the BLOCKS AND BYTES section to get other possibilities. .SH OPTIONS .TP .B bs=BYTES Force ibs=BYTES and obs=BYTES. Default value is 32768 (32KiB). See BLOCKS AND BYTES section. Warning: the block size will be created in RAM. Make sure you have sufficient amount of free memory. .TP .B cbs=BYTES Convert BYTES bytes at a time. (see BLOCKS AND BYTES section) .TP .B conv=KEYWORDS Convert the file as per the comma separated keyword list. .TP .B count=BLOCKS Copy only BLOCKS input blocks. (see BLOCKS AND BYTES section) .TP .B limit=BYTES Similar to count but using BYTES instead of BLOCKS. (see BLOCKS AND BYTES section) .TP .B ibs=BYTES Read BYTES bytes at a time. (see BLOCKS AND BYTES section) .TP .B if=FILE Read from FILE instead of stdin. (see BLOCKS AND BYTES section) .TP .B obs=BYTES Write BYTES bytes at a time. (see BLOCKS AND BYTES section) .TP .B of=FILE Write to FILE instead of stdout. NOTE: of=FILE may be used several times to write output to multiple files simultaneously. .TP .B of:=COMMAND Exec and write output to process COMMAND. .TP .B seek=BLOCKS Skip BLOCKS obs-sized blocks at start of output. (see BLOCKS AND BYTES section) .TP .B skip=BLOCKS Skip BLOCKS ibs-sized blocks at start of input. (see BLOCKS AND BYTES section) .TP .B pattern=HEX Use the specified binary pattern as input. You can use a byte only. .TP .B textpattern=TEXT Use repeating TEXT as input. You can use a character only. .TP .B errlog=FILE Send error messages to FILE as well as stderr. .TP .B hash=NAME Do hash calculation in parallel with the disk reading. Either md5, sha1, sha256, sha384 or sha512 can be used. Default algorithm is md5. To select multiple algorithms to run simultaneously enter the names in a comma separated list. .TP .B hashlog=FILE Send hash output to FILE instead of stderr. If you are using multiple hash algorithms you can send each to a separate file using the convention ALGORITHMlog=FILE, for example md5log=FILE1, sha1log=FILE2, etc. .TP .B hashwindow=BYTES Perform a hash on every BYTES amount of data. The partial results will be shown in screen. The default hash is md5 but you can use hash= option to choose other. .TP .B hashlog:=COMMAND Exec and write hashlog to process COMMAND. .TP .B ALGORITHMlog:=COMMAND Also works in the same fashion of hashlog:=COMMAND. .TP .B hashconv=[before|after] Perform the hashing before or after the conversions. .TP .B hashformat=FORMAT Display each hashwindow according to FORMAT the hash format mini-language is described below. .TP .B totalhashformat=FORMAT Display the total hash value according to FORMAT the hash format mini-language is described below. .TP .B status=[on|off] Display a continual status message on stderr. Default state is "on". .TP .B statusinterval=N Update the status message every N blocks. Default value is 256. .TP .B sizeprobe=[if|of|BYTES] Determine the size of the input or output file or an amount of BYTES for use with status messages. This option gives you a percentage indicator around the sizeprobe value. WARNING: do not use this option against a tape device. (see BLOCKS AND BYTES section) .TP .B split=BYTES Write every BYTES amount of data to a new file. This operation applies to any of=FILE that follows (split= must be put before of=). (see BLOCKS AND BYTES section) .TP .B splitformat=[TEXT|MAC|WIN] The file extension format for split operation. You may use "a" for letters and "n" for numbers. If you use annn, an extension started as a000 will be appended; the last possible extension for this format will be z999. splitformat=an will provide a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, b0, b1, b2, b3\.\.\. If nothing is specified the default format is "nnn". NOTE: the split and splitformat options take effect only for output files (option of=) specified AFTER these options appear in the command line (e.g. split=50M splitformat=annn of=/tmp/test.iso). Likewise, you may specify it several times for different output files within the same command line. You may use as many digits in any combination you would like. E.g. "anaannnaana" would be valid, but a quite insane (see BLOCKS AND BYTES section). Other possible approach is MAC. If "MAC" is used, a suffix dmg and several dmgpart will be appended. In other words, it will generate a partial disk image file, used by the Mac OS X operating system. dmgpart files are usually provided with a corresponding dmg file, which is the master file for the split archive. If dmg is opened in Mac OS X, all dmgpart will be read too. The last option is WIN, which will automatically output file naming of foo.001, foo.002, \.\.\., foo.999, foo.1000, \.\.\.. .TP .B vf=FILE Verify that FILE matches the specified input. .TP .B verifylog=FILE Send verify results to FILE instead of stderr. .TP .B verifylog:=COMMAND Exec and write verify results to process COMMAND. .TP .B \fB--help\fP Display a help page and exit. .TP .B \fB--version\fP Output version information and exit. .SH BLOCKS AND BYTES BLOCKS and BYTES may be followed by the following multiplicative suffixes: xM M, c 1, w 2, b 512, kD 1000, k 1024, MD 1,000,000, M 1,048,576, GD 1,000,000,000, G 1,073,741,824, and so on for T, P, E, Z, Y. .SH KEYWORDS Each KEYWORD may be: .TP .B ascii From EBCDIC to ASCII. .TP .B ebcdic From ASCII to EBCDIC. .TP .B ibm From ASCII to alternated EBCDIC. .TP .B block Pad newline-terminated records with spaces to cbs-size. .TP .B unblock Replace trailing spaces in cbs-size records with newline. .TP .B lcase Change upper case to lower case. .TP .B notrunc Do not truncate the output file. .TP .B ucase Change lower case to upper case. .TP .B swab Swap every pair of input bytes. .TP .B noerror Continue after read errors. .TP .B sync Pad every input block with NULs to ibs-size. When used with block or unblock, pad with spaces rather than NULs. .SH FORMAT The structure of FORMAT may contain any valid text and special variables. The built-in variables are the following format: #variable_name#. To pass FORMAT strings to the program from a command line, it may be .TP .B necessary to surround your FORMAT strings with "quotes." The built-in variables are listed below: .TP .B window_start The beginning byte offset of the hashwindow. .TP .B window_end The ending byte offset of the hashwindow. .TP .B block_start The beginning block (by input blocksize) of the window. .TP .B block_end The ending block (by input blocksize) of the hash window. .TP .B hash The hash value. .TP .B algorithm The name of the hash algorithm. .PP For example, the default FORMAT for hashformat and totalhashformat are: .PP .nf .fam C hashformat="#window_start# - #window_end#: #hash#" totalhashformat="Total (#algorithm#): #hash#" .fam T .fi The FORMAT structure accepts the following escape codes: .TP .B \\n Newline .TP .B \\t Tab .TP .B \\r Carriage return .TP .B \\ Insert the '\\' character .TP .B ## Insert the '#' character as text, not a variable .SH EXAMPLES Each following line will create a 100 MiB file containing zeros: .PP .nf .fam C $ dcfldd if=/dev/zero of=test bs=1M count=100 $ dcfldd if=/dev/zero of=test bs=100M count=1 $ dcfldd if=/dev/zero of=test bs=50M count=2 $ dcfldd if=/dev/zero of=test limit=100M .fam T .fi To create a copy (forensics image) from a disk called /dev/sdb inside a file, using input/output blocks of 4096 bytes (4 KiB) instead of 32 KiB (default): .PP .nf .fam C $ dcfldd if=/dev/sdb bs=4096 of=sdb.img .fam T .fi As the last example, plus calculating MD5 and SHA256 hashes, putting the results inside sdb.md5 and sdb.sha256. It is very useful for forensics works because the hashes will be processed in real time, avoiding a waste of time to make something as 'dd + md5 + sha256'. Considering that I/O disk is very slow and RAM is very fast, the hashes will be calculated, bit per bit in memory, when the next portion of the disk is read. When all disk was read, all hashes are now ready. .PP .nf .fam C $ dcfldd if=/dev/sdb bs=4096 hash=md5,sha256 md5log=sdb.md5 sha256log=sdb.sha256 of=sdb.img .fam T .fi To validate the image file against the original source: .PP .nf .fam C $ dcfldd if=/dev/sdb vf=sdb.img .fam T .fi Splitting the image in 500 MiB slices, using the default bs value (32 KiB). Note that split= must be put before of= to work: .PP .nf .fam C $ dcfldd if=/dev/sdb split=500M of=sdb.img .fam T .fi At the last example, using from a0000 up to z9999 as suffix for each split file: .PP .nf .fam C $ dcfldd if=/dev/sdb split=500M splitformat=annnn of=sdb.img .fam T .fi Now, \fBdcfldd\fP will work byte per byte (bs=1) and will hop 1056087439 bytes. After this, \fBdcfldd\fP will collect 200000 bytes and write the results to a file called airplane.jpg. .PP .nf .fam C $ dcfldd if=/dev/sda3 bs=1 skip=1056087439 count=200000 of=airplane.jpg .fam T .fi In the last example, the same result could be obtained using "limit" instead of "count". The main difference is that count uses 200000*bs and limit uses 200000 bytes (regardless of the value declared in bs option): .PP .nf .fam C $ dcfldd if=/dev/sda3 bs=1 skip=1056087439 limit=200000 of=airplane.jpg .fam T .fi To write something inside a file, you can use seek. Suppose you want to write a message from a file called message.txt inside a file called target.iso, hopping 200000 bytes from start of file: .PP .nf .fam C $ dcfldd if=message.txt bs=1 seek=200000 of=target.iso .fam T .fi \fBdcfldd\fP also can send a result to be processed by an external command: .PP .nf .fam C $ dcfldd if=text.txt of:="cat | sort -u" .fam T .fi To convert a file from ASCII to EBCDIC: .PP .nf .fam C $ dcfldd if=text.asc conv=ebcdic of=text.ebcdic .fam T .fi To convert a file from EBCDIC to ASCII: .PP .nf .fam C $ dcfldd if=text.ebcdic conv=ascii of=text.asc .fam T .fi .SH SEE ALSO \fBdd\fP(1) .SH REPORTING BUGS Report bugs at https://github.com/resurrecting-open-source-projects/\fBdcfldd\fP/issues .SH AUTHORS \fBdcfldd\fP was originally written by Nicholas Harbour. Currently is maintained by some volunteers. .PP GNU dd was written by Paul Rubin, David MacKenzie and Stuart Kemp. .PP This manpage was written by dd authors, Nicholas Harbour, Joao Eriberto Mota Filho and others. dcfldd-1.7.1/man/dcfldd.txt000066400000000000000000000302771410702647300155110ustar00rootroot00000000000000NAME dcfldd - enhanced version of dd for forensics and security SYNOPSIS dcfldd [OPTION]... DESCRIPTION Copy a file, converting and formatting according to the options. dcfldd was initially developed at Department of Defense Computer Forensics Lab (DCFL). This tool is based on the dd program with the following additional features: - Hashing on-the-fly: dcfldd can hash the input data as it is being transferred, helping to ensure data integrity. - Status output: dcfldd can update the user of its progress in terms of the amount of data transferred and how much longer operation will take. - Flexible disk wipes: dcfldd can be used to wipe disks quickly and with a known pattern if desired. - Image/wipe verify: dcfldd can verify that a target drive is a bit-for-bit match of the specified input file or pattern. - Multiple outputs: dcfldd can output to multiple files or disks at the same time. - Split output: dcfldd can split output to multiple files with more configurability than the split command. - Piped output and logs: dcfldd can send all its log data and output to commands as well as files natively. - When dd uses a default block size (bs, ibs, obs) of 512 bytes, dcfldd uses 32768 bytes (32 KiB) which is HUGELY more efficient. - The following options are present in dcfldd but not in dd: ALGORITHMlog:, errlog, hash, hashconv, hashformat, hashlog, hashlog:, hashwindow, limit, of:, pattern, sizeprobe, split, splitformat, statusinterval, textpattern, totalhashformat, verifylog, verifylog:, vf. dcfldd supports the following letters to specify amount of data: k for kilo, M for Mega, G for Giga, T for Tera, P for Peta, E for Exa, Z for Zetta and Y for Yotta. E.g. 10M is equal to 10 MiB. See the BLOCKS AND BYTES section to get other possibilities. OPTIONS bs=BYTES Force ibs=BYTES and obs=BYTES. Default value is 32768 (32KiB). See BLOCKS AND BYTES section. Warning: the block size will be created in RAM. Make sure you have sufficient amount of free memory. cbs=BYTES Convert BYTES bytes at a time. (see BLOCKS AND BYTES section) conv=KEYWORDS Convert the file as per the comma separated keyword list. count=BLOCKS Copy only BLOCKS input blocks. (see BLOCKS AND BYTES section) limit=BYTES Similar to count but using BYTES instead of BLOCKS. (see BLOCKS AND BYTES section) ibs=BYTES Read BYTES bytes at a time. (see BLOCKS AND BYTES section) if=FILE Read from FILE instead of stdin. (see BLOCKS AND BYTES section) obs=BYTES Write BYTES bytes at a time. (see BLOCKS AND BYTES section) of=FILE Write to FILE instead of stdout. NOTE: of=FILE may be used several times to write output to multiple files simultaneously. of:=COMMAND Exec and write output to process COMMAND. seek=BLOCKS Skip BLOCKS obs-sized blocks at start of output. (see BLOCKS AND BYTES section) skip=BLOCKS Skip BLOCKS ibs-sized blocks at start of input. (see BLOCKS AND BYTES section) pattern=HEX Use the specified binary pattern as input. You can use a byte only. textpattern=TEXT Use repeating TEXT as input. You can use a character only. errlog=FILE Send error messages to FILE as well as stderr. hash=NAME Do hash calculation in parallel with the disk reading. Either md5, sha1, sha256, sha384 or sha512 can be used. Default algorithm is md5. To select multiple algorithms to run simultaneously enter the names in a comma separated list. hashlog=FILE Send hash output to FILE instead of stderr. If you are using multiple hash algorithms you can send each to a separate file using the convention ALGORITHMlog=FILE, for example md5log=FILE1, sha1log=FILE2, etc. hashwindow=BYTES Perform a hash on every BYTES amount of data. The partial results will be shown in screen. The default hash is md5 but you can use hash= option to choose other. hashlog:=COMMAND Exec and write hashlog to process COMMAND. ALGORITHMlog:=COMMAND Also works in the same fashion of hashlog:=COMMAND. hashconv=[before|after] Perform the hashing before or after the conversions. hashformat=FORMAT Display each hashwindow according to FORMAT the hash format mini-language is described below. totalhashformat=FORMAT Display the total hash value according to FORMAT the hash format mini-language is described below. status=[on|off] Display a continual status message on stderr. Default state is "on". statusinterval=N Update the status message every N blocks. Default value is 256. sizeprobe=[if|of|BYTES] Determine the size of the input or output file or an amount of BYTES for use with status messages. This option gives you a percentage indicator around the sizeprobe value. WARNING: do not use this option against a tape device. (see BLOCKS AND BYTES section) split=BYTES Write every BYTES amount of data to a new file. This operation applies to any of=FILE that follows (split= must be put before of=). (see BLOCKS AND BYTES section) splitformat=[TEXT|MAC|WIN] The file extension format for split operation. You may use "a" for letters and "n" for numbers. If you use annn, an extension started as a000 will be appended; the last possible extension for this format will be z999. splitformat=an will provide a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, b0, b1, b2, b3... If nothing is specified the default format is "nnn". NOTE: the split and splitformat options take effect only for output files (option of=) specified AFTER these options appear in the command line (e.g. split=50M splitformat=annn of=/tmp/test.iso). Likewise, you may specify it several times for different output files within the same command line. You may use as many digits in any combination you would like. E.g. "anaannnaana" would be valid, but a quite insane (see BLOCKS AND BYTES section). Other possible approach is MAC. If "MAC" is used, a suffix dmg and several dmgpart will be appended. In other words, it will generate a partial disk image file, used by the Mac OS X operating system. dmgpart files are usually provided with a corresponding dmg file, which is the master file for the split archive. If dmg is opened in Mac OS X, all dmgpart will be read too. The last option is WIN, which will automatically output file naming of foo.001, foo.002, ..., foo.999, foo.1000, .... vf=FILE Verify that FILE matches the specified input. verifylog=FILE Send verify results to FILE instead of stderr. verifylog:=COMMAND Exec and write verify results to process COMMAND. --help Display a help page and exit. --version Output version information and exit. BLOCKS AND BYTES BLOCKS and BYTES may be followed by the following multiplicative suffixes: xM M, c 1, w 2, b 512, kD 1000, k 1024, MD 1,000,000, M 1,048,576, GD 1,000,000,000, G 1,073,741,824, and so on for T, P, E, Z, Y. KEYWORDS Each KEYWORD may be: ascii From EBCDIC to ASCII. ebcdic From ASCII to EBCDIC. ibm From ASCII to alternated EBCDIC. block Pad newline-terminated records with spaces to cbs-size. unblock Replace trailing spaces in cbs-size records with newline. lcase Change upper case to lower case. notrunc Do not truncate the output file. ucase Change lower case to upper case. swab Swap every pair of input bytes. noerror Continue after read errors. sync Pad every input block with NULs to ibs-size. When used with block or unblock, pad with spaces rather than NULs. FORMAT The structure of FORMAT may contain any valid text and special variables. The built-in variables are the following format: #variable_name#. To pass FORMAT strings to the program from a command line, it may be necessary to surround your FORMAT strings with "quotes." The built-in variables are listed below: window_start The beginning byte offset of the hashwindow. window_end The ending byte offset of the hashwindow. block_start The beginning block (by input blocksize) of the window. block_end The ending block (by input blocksize) of the hash window. hash The hash value. algorithm The name of the hash algorithm. For example, the default FORMAT for hashformat and totalhashformat are: hashformat="#window_start# - #window_end#: #hash#" totalhashformat="Total (#algorithm#): #hash#" The FORMAT structure accepts the following escape codes: \\n Newline \\t Tab \\r Carriage return \\ Insert the '\\' character ## Insert the '#' character as text, not a variable EXAMPLES Each following line will create a 100 MiB file containing zeros: $ dcfldd if=/dev/zero of=test bs=1M count=100 $ dcfldd if=/dev/zero of=test bs=100M count=1 $ dcfldd if=/dev/zero of=test bs=50M count=2 $ dcfldd if=/dev/zero of=test limit=100M To create a copy (forensics image) from a disk called /dev/sdb inside a file, using input/output blocks of 4096 bytes (4 KiB) instead of 32 KiB (default): $ dcfldd if=/dev/sdb bs=4096 of=sdb.img As the last example, plus calculating MD5 and SHA256 hashes, putting the results inside sdb.md5 and sdb.sha256. It is very useful for forensics works because the hashes will be processed in real time, avoiding a waste of time to make something as 'dd + md5 + sha256'. Considering that I/O disk is very slow and RAM is very fast, the hashes will be calculated, bit per bit in memory, when the next portion of the disk is read. When all disk was read, all hashes are now ready. $ dcfldd if=/dev/sdb bs=4096 hash=md5,sha256 md5log=sdb.md5 sha256log=sdb.sha256 of=sdb.img To validate the image file against the original source: $ dcfldd if=/dev/sdb vf=sdb.img Splitting the image in 500 MiB slices, using the default bs value (32 KiB). Note that split= must be put before of= to work: $ dcfldd if=/dev/sdb split=500M of=sdb.img At the last example, using from a0000 up to z9999 as suffix for each split file: $ dcfldd if=/dev/sdb split=500M splitformat=annnn of=sdb.img Now, dcfldd will work byte per byte (bs=1) and will hop 1056087439 bytes. After this, dcfldd will collect 200000 bytes and write the results to a file called airplane.jpg. $ dcfldd if=/dev/sda3 bs=1 skip=1056087439 count=200000 of=airplane.jpg In the last example, the same result could be obtained using "limit" instead of "count". The main difference is that count uses 200000*bs and limit uses 200000 bytes (regardless of the value declared in bs option): $ dcfldd if=/dev/sda3 bs=1 skip=1056087439 limit=200000 of=airplane.jpg To write something inside a file, you can use seek. Suppose you want to write a message from a file called message.txt inside a file called target.iso, hopping 200000 bytes from start of file: $ dcfldd if=message.txt bs=1 seek=200000 of=target.iso dcfldd also can send a result to be processed by an external command: $ dcfldd if=text.txt of:="cat | sort -u" To convert a file from ASCII to EBCDIC: $ dcfldd if=text.asc conv=ebcdic of=text.ebcdic To convert a file from EBCDIC to ASCII: $ dcfldd if=text.ebcdic conv=ascii of=text.asc SEE ALSO dd(1) REPORTING BUGS Report bugs at https://github.com/resurrecting-open-source-projects/dcfldd/issues AUTHORS dcfldd was originally written by Nicholas Harbour. Currently is maintained by some volunteers. GNU dd was written by Paul Rubin, David MacKenzie and Stuart Kemp. This manpage was written by dd authors, Nicholas Harbour, Joao Eriberto Mota Filho and others. dcfldd-1.7.1/src/000077500000000000000000000000001410702647300135335ustar00rootroot00000000000000dcfldd-1.7.1/src/Makefile.am000066400000000000000000000037701410702647300155760ustar00rootroot00000000000000# configure.ac, was previously configure.in (before 2019) # # Copyright ?-2002 Jim Meyering # Copyright 2002-2006 Nicholas Harbour # Copyright 2019 Joao Eriberto Mota Filho # # 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., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. bin_PROGRAMS = dcfldd AM_CFLAGS = -fgnu89-inline dcfldd_SOURCES = dcfldd.c \ md5.c md5.h \ sha1.c sha1.h \ sha2.c sha2.h \ human.c human.h \ getpagesize.h \ long-options.c long-options.h \ safe-read.c safe-read.h \ xstrtol.c xstrtol.h \ version-etc.c version-etc.h \ system.h sys2.h pathmax.h xalloc.h \ argmatch.c argmatch.h \ xstrtoul.c \ full-write.c \ xstrtoumax.c \ copy.c copy.h \ dcfldd.h \ hash.h hash.c \ verify.c verify.h \ translate.c translate.h \ sizeprobe.c sizeprobe.h \ pattern.c pattern.h \ util.c util.h \ log.c log.h \ full-write.h \ output.c output.h \ split.c split.h \ hashformat.c hashformat.h dcfldd-1.7.1/src/argmatch.c000066400000000000000000000176611410702647300155000ustar00rootroot00000000000000/* argmatch.c -- find a match for a string in an array Copyright 1990, 1998, 1999 Free Software Foundation, Inc. Copyright 2019 Joao Eriberto Mota Filho 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by David MacKenzie Modified by Akim Demaille */ #include "dcfldd.h" #include "argmatch.h" #include "log.h" #include #ifdef STDC_HEADERS # include #endif #if HAVE_LOCALE_H # include #endif #if ENABLE_NLS # include # define _(Text) gettext (Text) #else # define _(Text) Text #endif /* When reporting an invalid argument, show nonprinting characters by using the quoting style ARGMATCH_QUOTING_STYLE. Do not use literal_quoting_style. */ #ifndef ARGMATCH_QUOTING_STYLE # define ARGMATCH_QUOTING_STYLE locale_quoting_style #endif /* The following test is to work around the gross typo in systems like Sony NEWS-OS Release 4.0C, whereby EXIT_FAILURE is defined to 0, not 1. */ #if !EXIT_FAILURE # undef EXIT_FAILURE # define EXIT_FAILURE 1 #endif /* Non failing version of argmatch call this function after failing. */ #ifndef ARGMATCH_DIE # define ARGMATCH_DIE exit (EXIT_FAILURE) #endif #ifdef ARGMATCH_DIE_DECL ARGMATCH_DIE_DECL; #endif static void __argmatch_die (void) { ARGMATCH_DIE; } /* Used by XARGMATCH and XARGCASEMATCH. See description in argmatch.h. Default to __argmatch_die, but allow caller to change this at run-time. */ argmatch_exit_fn argmatch_die = __argmatch_die; /* If ARG is an unambiguous match for an element of the null-terminated array ARGLIST, return the index in ARGLIST of the matched element, else -1 if it does not match any element or -2 if it is ambiguous (is a prefix of more than one element). If SENSITIVE, comparison is case sensitive. If VALLIST is none null, use it to resolve ambiguities limited to synonyms, i.e., for "yes", "yop" -> 0 "no", "nope" -> 1 "y" is a valid argument, for `0', and "n" for `1'. */ static int __argmatch_internal (const char *arg, const char *const *arglist, const char *vallist, size_t valsize, int case_sensitive) { int i; /* Temporary index in ARGLIST. */ size_t arglen; /* Length of ARG. */ int matchind = -1; /* Index of first nonexact match. */ int ambiguous = 0; /* If nonzero, multiple nonexact match(es). */ arglen = strlen (arg); /* Test all elements for either exact match or abbreviated matches. */ for (i = 0; arglist[i]; i++) { if (case_sensitive ? !strncmp (arglist[i], arg, arglen) : !strncasecmp (arglist[i], arg, arglen)) { if (strlen (arglist[i]) == arglen) /* Exact match found. */ return i; else if (matchind == -1) /* First nonexact match found. */ matchind = i; else { /* Second nonexact match found. */ if (vallist == NULL || memcmp (vallist + valsize * matchind, vallist + valsize * i, valsize)) { /* There is a real ambiguity, or we could not disambiguate. */ ambiguous = 1; } } } } if (ambiguous) return -2; else return matchind; } /* argmatch - case sensitive version */ int argmatch (const char *arg, const char *const *arglist, const char *vallist, size_t valsize) { return __argmatch_internal (arg, arglist, vallist, valsize, 1); } /* argcasematch - case insensitive version */ int argcasematch (const char *arg, const char *const *arglist, const char *vallist, size_t valsize) { return __argmatch_internal (arg, arglist, vallist, valsize, 0); } /* Error reporting for argmatch. CONTEXT is a description of the type of entity that was being matched. VALUE is the invalid value that was given. PROBLEM is the return value from argmatch. */ void argmatch_invalid (const char *context, const char *value, int problem) { char *format = (problem == -1 ? "invalid argument %s for `%s'" : "ambiguous argument %s for `%s'"); log_info(format, value, context); } /* List the valid arguments for argmatch. ARGLIST is the same as in argmatch. VALLIST is a pointer to an array of values. VALSIZE is the size of the elements of VALLIST */ void argmatch_valid (const char *const *arglist, const char *vallist, size_t valsize) { int i; const char *last_val = NULL; /* We try to put synonyms on the same line. The assumption is that synonyms follow each other */ fprintf (stderr, "Valid arguments are:"); for (i = 0; arglist[i]; i++) if ((i == 0) || memcmp (last_val, vallist + valsize * i, valsize)) { log_info("\n - `%s'", arglist[i]); last_val = vallist + valsize * i; } else { log_info(", `%s'", arglist[i]); } putc ('\n', stderr); } /* Never failing versions of the previous functions. CONTEXT is the context for which argmatch is called (e.g., "--version-control", or "$VERSION_CONTROL" etc.). Upon failure, calls the (supposed never to return) function EXIT_FN. */ int __xargmatch_internal (const char *context, const char *arg, const char *const *arglist, const char *vallist, size_t valsize, int case_sensitive, argmatch_exit_fn exit_fn) { int res = __argmatch_internal (arg, arglist, vallist, valsize, case_sensitive); if (res >= 0) /* Success. */ return res; /* We failed. Explain why. */ argmatch_invalid (context, arg, res); argmatch_valid (arglist, vallist, valsize); (*exit_fn) (); return -1; /* To please the compilers. */ } /* Look for VALUE in VALLIST, an array of objects of size VALSIZE and return the first corresponding argument in ARGLIST */ const char * argmatch_to_argument (const char *value, const char *const *arglist, const char *vallist, size_t valsize) { int i; for (i = 0; arglist[i]; i++) if (!memcmp (value, vallist + valsize * i, valsize)) return arglist[i]; return NULL; } #ifdef TEST /* * Based on "getversion.c" by David MacKenzie */ char *program_name; extern const char *getenv (); /* When to make backup files. */ enum backup_type { /* Never make backups. */ none, /* Make simple backups of every file. */ simple, /* Make numbered backups of files that already have numbered backups, and simple backups of the others. */ numbered_existing, /* Make numbered backups of every file. */ numbered }; /* Two tables describing arguments (keys) and their corresponding values */ static const char *const backup_args[] = { "no", "none", "off", "simple", "never", "existing", "nil", "numbered", "t", 0 }; static const enum backup_type backup_vals[] = { none, none, none, simple, simple, numbered_existing, numbered_existing, numbered, numbered }; int main (int argc, const char *const *argv) { const char *cp; enum backup_type backup_type = none; program_name = (char *) argv[0]; if (argc > 2) { fprintf(stderr, "Usage: %s [VERSION_CONTROL]\n", program_name); exit (1); } if ((cp = getenv ("VERSION_CONTROL"))) backup_type = XARGCASEMATCH ("$VERSION_CONTROL", cp, backup_args, backup_vals); if (argc == 2) backup_type = XARGCASEMATCH (program_name, argv[1], backup_args, backup_vals); printf ("The version control is `%s'\n", ARGMATCH_TO_ARGUMENT (backup_type, backup_args, backup_vals)); return 0; } #endif dcfldd-1.7.1/src/argmatch.h000066400000000000000000000107571410702647300155040ustar00rootroot00000000000000/* argmatch.h -- definitions and prototypes for argmatch.c Copyright (C) 1990, 1998, 1999 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by David MacKenzie Modified by Akim Demaille */ #ifndef ARGMATCH_H_ # define ARGMATCH_H_ 1 # if HAVE_CONFIG_H # include # endif # include # ifndef PARAMS # if PROTOTYPES || (defined (__STDC__) && __STDC__) # define PARAMS(args) args # else # define PARAMS(args) () # endif /* GCC. */ # endif /* Not PARAMS. */ /* Assert there are as many real arguments as there are values (argument list ends with a NULL guard). There is no execution cost, since it will be statically evalauted to `assert (0)' or `assert (1)'. Unfortunately there is no -Wassert-0. */ # undef ARRAY_CARDINALITY # define ARRAY_CARDINALITY(Array) (sizeof ((Array)) / sizeof (*(Array))) # define ARGMATCH_ASSERT(Arglist, Vallist) \ assert (ARRAY_CARDINALITY ((Arglist)) == ARRAY_CARDINALITY ((Vallist)) + 1) /* Return the index of the element of ARGLIST (NULL terminated) that matches with ARG. If VALLIST is not NULL, then use it to resolve false ambiguities (i.e., different matches of ARG but corresponding to the same values in VALLIST). */ int argmatch PARAMS ((const char *arg, const char *const *arglist, const char *vallist, size_t valsize)); int argcasematch PARAMS ((const char *arg, const char *const *arglist, const char *vallist, size_t valsize)); # define ARGMATCH(Arg, Arglist, Vallist) \ argmatch ((Arg), (Arglist), (const char *) (Vallist), sizeof (*(Vallist))) # define ARGCASEMATCH(Arg, Arglist, Vallist) \ argcasematch ((Arg), (Arglist), (const char *) (Vallist), sizeof (*(Vallist))) /* xargmatch calls this function when it fails. This function should not return. By default, this is a function that calls ARGMATCH_DIE which in turn defaults to `exit (EXIT_FAILURE)'. */ typedef void (*argmatch_exit_fn) PARAMS ((void)); extern argmatch_exit_fn argmatch_die; /* Report on stderr why argmatch failed. Report correct values. */ void argmatch_invalid PARAMS ((const char *context, const char *value, int problem)); /* Left for compatibility with the old name invalid_arg */ # define invalid_arg(Context, Value, Problem) \ argmatch_invalid ((Context), (Value), (Problem)) /* Report on stderr the list of possible arguments. */ void argmatch_valid PARAMS ((const char *const *arglist, const char *vallist, size_t valsize)); # define ARGMATCH_VALID(Arglist, Vallist) \ argmatch_valid (Arglist, (const char *) Vallist, sizeof (*(Vallist))) /* Same as argmatch, but upon failure, reports a explanation on the failure, and exits using the function EXIT_FN. */ int __xargmatch_internal PARAMS ((const char *context, const char *arg, const char *const *arglist, const char *vallist, size_t valsize, int case_sensitive, argmatch_exit_fn exit_fn)); /* Programmer friendly interface to __xargmatch_internal. */ # define XARGMATCH(Context, Arg, Arglist, Vallist) \ (Vallist [__xargmatch_internal ((Context), (Arg), (Arglist), \ (const char *) (Vallist), \ sizeof (*(Vallist)), \ 1, argmatch_die)]) # define XARGCASEMATCH(Context, Arg, Arglist, Vallist) \ (Vallist [__xargmatch_internal ((Context), (Arg), (Arglist), \ (const char *) (Vallist), \ sizeof (*(Vallist)), \ 0, argmatch_die)]) /* Convert a value into a corresponding argument. */ const char *argmatch_to_argument PARAMS ((char const *value, const char *const *arglist, const char *vallist, size_t valsize)); # define ARGMATCH_TO_ARGUMENT(Value, Arglist, Vallist) \ argmatch_to_argument ((char const *) &(Value), (Arglist), \ (const char *) (Vallist), sizeof (*(Vallist))) #endif /* ARGMATCH_H_ */ dcfldd-1.7.1/src/copy.c000066400000000000000000000336751410702647300146670ustar00rootroot00000000000000/* $Id: copy.c,v 1.6 2005/05/19 20:59:12 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright 85, 90, 91, 1995-2001, 2005 Free Software Foundation, Inc. Copyright 2008 David Loveall Copyright 2015 Joao Eriberto Mota Filho 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #include "dcfldd.h" #include #include #include #include "hash.h" #include "getpagesize.h" #include "safe-read.h" #include "full-write.h" #include "translate.h" #include "sizeprobe.h" #include "pattern.h" #include "util.h" #include "log.h" #include "output.h" static void write_output(void); static void copy_simple(unsigned char const *, int); static void copy_with_block(unsigned char const *, size_t); static void copy_with_unblock(unsigned char const *, size_t); /* Output buffer. */ unsigned char *obuf; /* Current index into `obuf'. */ static size_t oc; /* Index into current line, for `conv=block' and `conv=unblock'. */ static size_t col; /* Write, then empty, the output buffer `obuf'. */ static void write_output(void) { /*int nwritten = full_write(STDOUT_FILENO, obuf, output_blocksize); */ int nwritten = outputlist_write(obuf, output_blocksize); if (nwritten != output_blocksize) { if (nwritten > 0) w_partial++; quit(1); } else w_full++; oc = 0; } /* Copy NREAD bytes of BUF, with no conversions. */ static void copy_simple(unsigned char const *buf, int nread) { int nfree; /* Number of unused bytes in `obuf'. */ const unsigned char *start = buf; /* First uncopied char in BUF. */ do { nfree = output_blocksize - oc; if (nfree > nread) nfree = nread; memcpy((char *) (obuf + oc), (char *) start, nfree); nread -= nfree; /* Update the number of bytes left to copy. */ start += nfree; oc += nfree; if (oc >= output_blocksize) write_output(); } while (nread > 0); } /* Copy NREAD bytes of BUF, doing conv=block (pad newline-terminated records to `conversion_blocksize', replacing the newline with trailing spaces). */ static void copy_with_block(unsigned char const *buf, size_t nread) { size_t i; for (i = nread; i; i--, buf++) { if (*buf == newline_character) { if (col < conversion_blocksize) { size_t j; for (j = col; j < conversion_blocksize; j++) output_char(space_character); } col = 0; } else { if (col == conversion_blocksize) r_truncate++; else if (col < conversion_blocksize) output_char(*buf); col++; } } } /* Copy NREAD bytes of BUF, doing conv=unblock (replace trailing spaces in `conversion_blocksize'-sized records with a newline). */ static void copy_with_unblock(unsigned char const *buf, size_t nread) { size_t i; unsigned char c; static int pending_spaces = 0; for (i = 0; i < nread; i++) { c = buf[i]; if (col++ >= conversion_blocksize) { col = pending_spaces = 0; /* Wipe out any pending spaces. */ i--; /* Push the char back; get it later. */ output_char(newline_character); } else if (c == space_character) pending_spaces++; else { /* `c' is the character after a run of spaces that were not at the end of the conversion buffer. Output them. */ while (pending_spaces) { output_char(space_character); --pending_spaces; } output_char(c); } } } /* The main loop. */ int dd_copy(void) { unsigned char *ibuf, *bufstart; /* Input buffer. */ unsigned char *real_buf; /* real buffer address before alignment */ unsigned char *real_obuf; ssize_t nread; /* Bytes read in the current block. */ int exit_status = 0; int input_from_stream = !!input_file; int input_from_pattern = !input_from_stream; size_t page_size = getpagesize(); size_t n_bytes_read; /* Leave at least one extra byte at the beginning and end of `ibuf' for conv=swab, but keep the buffer address even. But some peculiar device drivers work only with word-aligned buffers, so leave an extra two bytes. */ /* Some devices require alignment on a sector or page boundary (e.g. character disk devices). Align the input buffer to a page boundary to cover all bases. Note that due to the swab algorithm, we must have at least one byte in the page before the input buffer; thus we allocate 2 pages of slop in the real buffer. 8k above the blocksize shouldn't bother anyone. The page alignment is necessary on any linux system that supports either the SGI raw I/O patch or Steven Tweedies raw I/O patch. It is necessary when accessing raw (i.e. character special) disk devices on Unixware or other SVR4-derived system. */ real_buf = (unsigned char *) malloc(input_blocksize + 2 * SWAB_ALIGN_OFFSET + 2 * page_size - 1); ibuf = real_buf; ibuf += SWAB_ALIGN_OFFSET; /* allow space for swab */ ibuf = PTR_ALIGN(ibuf, page_size); /* Init */ if (do_hash) hash_update(ihashlist, NULL, 0); if (conversions_mask & C_TWOBUFS) { /* Page-align the output buffer, too. */ real_obuf = (unsigned char *) malloc(output_blocksize + page_size - 1); obuf = PTR_ALIGN(real_obuf, page_size); } else { real_obuf = NULL; obuf = ibuf; } if (!input_from_pattern) if (skip_records != 0) skip(STDIN_FILENO, input_file, skip_records, input_blocksize, ibuf); if (seek_records != 0) { outputlist_t *listptr; for (listptr = outputlist; listptr != NULL; listptr = listptr->next) { skip(listptr->data.fd, "", seek_records, output_blocksize, obuf); } } if (max_records == 0) quit(exit_status); if (input_from_pattern) { replicate_pattern(pattern, ibuf, input_blocksize); nread = n_bytes_read = input_blocksize; } while (1) { /* Display an update message */ if (do_status && w_full % update_thresh == 0 && w_full != 0) { off_t total_bytes = w_full * input_blocksize; off_t total_mb = total_bytes / 1048576; if (probe == PROBE_NONE || probed_size == 0) fprintf(stderr, "\r%llu blocks (%lluMb) written.", /* [FIX] copy.c:226:25: warning: format ‘%llu’ expects argument of type ‘long long unsigned int’, but argument {3,4} has type ‘uintmax_t’ [-Wformat=] */ (long long unsigned int) w_full, (long long unsigned int) total_mb); else { time_t curr_time = time(NULL); int seconds = (int)difftime(curr_time, start_time); off_t probed_mb = probed_size / 1048576; float fprcnt = total_bytes / (float)probed_size; float fprcnt_remaining = 1.0 - fprcnt; int prcnt = (int)(fprcnt * 100); int seconds_remaining = (int)(seconds * (fprcnt_remaining / fprcnt)); char secstr[100]; time_left(secstr, sizeof secstr, seconds_remaining); fprintf(stderr, "\r[%d%% of %lluMb] %llu blocks (%lluMb) written. %s", /* [FIX] copy.c:240:25: warning: format ‘%llu’ expects argument of type ‘long long unsigned int’, but argument {4,5,6} has type ‘off_t’ [-Wformat=] */ prcnt, (long long unsigned int) probed_mb, (long long unsigned int) w_full, (long long unsigned int) total_mb, secstr); } } if (r_partial + r_full >= max_records) break; /* Zero the buffer before reading, so that if we get a read error, whatever data we are able to read is followed by zeros. This minimizes data loss. */ if (!input_from_pattern) { if ((conversions_mask & C_SYNC) && (conversions_mask & C_NOERROR)) memset((char *) ibuf, (conversions_mask & (C_BLOCK | C_UNBLOCK)) ? ' ' : '\0', input_blocksize); nread = safe_read(STDIN_FILENO, ibuf, input_blocksize); } if (nread == 0) break; /* EOF. */ if (nread < 0 && !input_from_pattern) { syscall_error_noexit(input_file); if (conversions_mask & C_NOERROR) { print_stats(); /* Seek past the bad block if possible. */ lseek(STDIN_FILENO, (off_t) input_blocksize, SEEK_CUR); if (conversions_mask & C_SYNC) { /* Replace the missing input with null bytes and proceed normally. */ // EXPERIMENTAL: let's try re-zeroing this buffer memset((char *) ibuf, (conversions_mask & (C_BLOCK | C_UNBLOCK)) ? ' ' : '\0', input_blocksize); nread = 0; } else continue; } else { /* Write any partial block. */ exit_status = 2; break; } } n_bytes_read = nread; if (r_partial + r_full + 1 == max_records) n_bytes_read = MIN(n_bytes_read, max_records_extrabytes); if (do_hash && hashconv == HASHCONV_BEFORE) hash_update(ihashlist, ibuf, n_bytes_read); if (n_bytes_read < input_blocksize) { r_partial++; if (conversions_mask & C_SYNC) { if (!(conversions_mask & C_NOERROR)) /* If C_NOERROR, we zeroed the block before reading. */ memset((char *) (ibuf + n_bytes_read), (conversions_mask & (C_BLOCK | C_UNBLOCK)) ? ' ' : '\0', input_blocksize - n_bytes_read); /* If this is the final read for the drive and there wasn't a whole block read, trunc the end */ if ((probe == PROBE_INPUT) && (probed_size != 0) && ((probed_size - ((w_full + w_partial) * input_blocksize)) < input_blocksize)) { n_bytes_read = MAX((probed_size - ((w_full + w_partial) * input_blocksize)), n_bytes_read); } else { n_bytes_read = input_blocksize; } } } else r_full++; if (ibuf == obuf) { /* If not C_TWOBUFS. */ /* int nwritten = full_write(STDOUT_FILENO, obuf, n_bytes_read); */ int nwritten = outputlist_write(obuf, n_bytes_read); if (nwritten < 0) syscall_error(output_file); else if (n_bytes_read == input_blocksize) w_full++; else w_partial++; } else { /* If C_TWOBUFS */ /* Do any translations on the whole buffer at once. */ if (translation_needed) translate_buffer(ibuf, n_bytes_read); if (conversions_mask & C_SWAB) bufstart = swab_buffer(ibuf, &n_bytes_read); else bufstart = ibuf; if (conversions_mask & C_BLOCK) copy_with_block(bufstart, n_bytes_read); else if (conversions_mask & C_UNBLOCK) copy_with_unblock(bufstart, n_bytes_read); else copy_simple(bufstart, n_bytes_read); } if (do_hash && hashconv == HASHCONV_AFTER) hash_update(ihashlist, ibuf, n_bytes_read); } /* If we have a char left as a result of conv=swab, output it. */ if (char_is_saved) { if (conversions_mask & C_BLOCK) copy_with_block(&saved_char, 1); else if (conversions_mask & C_UNBLOCK) copy_with_unblock(&saved_char, 1); else output_char(saved_char); } if ((conversions_mask & C_BLOCK) && col > 0) { /* If the final input line didn't end with a '\n', pad the output block to `conversion_blocksize' chars. */ unsigned int i; for (i = col; i < conversion_blocksize; i++) output_char(space_character); } if ((conversions_mask & C_UNBLOCK) && col == conversion_blocksize) /* Add a final '\n' if there are exactly `conversion_blocksize' characters in the final record. */ output_char(newline_character); /* Write out the last block. */ if (oc != 0) { /* int nwritten = full_write(STDOUT_FILENO, obuf, oc); */ int nwritten = outputlist_write(obuf, oc); if (nwritten > 0) w_partial++; if (nwritten < 0) { syscall_error(output_file); } } free(real_buf); if (real_obuf) free(real_obuf); if (do_hash) { hash_remainder(ihashlist, WINDOW_CTX); display_totalhash(ihashlist, TOTAL_CTX); } return exit_status; } dcfldd-1.7.1/src/copy.h000066400000000000000000000020471410702647300146610ustar00rootroot00000000000000/* $Id: copy.h,v 1.3 2005/05/13 18:52:06 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright (C) 85, 90, 91, 1995-2001, 2005 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #ifndef COPY_H #define COPY_H extern int dd_copy(void); #endif /* COPY_H */ dcfldd-1.7.1/src/dcfldd.c000066400000000000000000000565221410702647300151310ustar00rootroot00000000000000/* $Id: dcfldd.c,v 1.7 2005/06/15 14:33:04 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright 85, 90, 91, 1995-2001, 2005 Free Software Foundation, Inc. Copyright 2005 Martin Scharrer Copyright 2008 David Loveall Copyright 2012 Miah Gregory Copyright 2014 Vangelis Koukis 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #include "dcfldd.h" /* * * How bored are you? sitting around reading source code, its sad. * */ #include "config.h" #include #include #include #include #include #if HAVE_INTTYPES_H # include #endif #include #include #include #include #include #include #include #include #include "system.h" #include "human.h" #include "long-options.h" #include "safe-read.h" #include "xstrtol.h" #include "full-write.h" #include "copy.h" #include "hash.h" #include "verify.h" #include "translate.h" #include "sizeprobe.h" #include "pattern.h" #include "output.h" #include "split.h" #include "hashformat.h" #include "util.h" #include "log.h" /* The name this program was run with. */ char *program_name; /* The name of the input file, or NULL for the standard input. */ char *input_file = NULL; /* The name of the output file, or NULL for the standard output. */ char *output_file = NULL; /* The number of bytes in which atomic reads are done. */ size_t input_blocksize = 0; /* The number of bytes in which atomic writes are done. */ size_t output_blocksize = 0; /* Conversion buffer size, in bytes. 0 prevents conversions. */ size_t conversion_blocksize = 0; /* Skip this many records of `input_blocksize' bytes before input. */ uintmax_t skip_records = 0; /* Skip this many records of `output_blocksize' bytes before output. */ uintmax_t seek_records = 0; /* Copy only this many records. The default is effectively infinity. */ uintmax_t max_records = (uintmax_t) -1; /* Copy only this many bytes from the input. The default is infinity. */ uintmax_t limit = 0; /* Copy only this many bytes from the max_record(s). The default is effectively infinity. */ uintmax_t max_records_extrabytes = (uintmax_t) -1; /* Bit vector of conversions to apply. */ int conversions_mask = 0; /* Number of partial blocks written. */ uintmax_t w_partial = 0; /* Number of full blocks written. */ uintmax_t w_full = 0; /* Number of partial blocks read. */ uintmax_t r_partial = 0; /* Number of full blocks read. */ uintmax_t r_full = 0; /* If nonzero, filter characters through the translation table. */ int translation_needed = 0; /* Records truncated by conv=block. */ uintmax_t r_truncate = 0; /* If nonnzero, the last char from the previous call to `swab_buffer' is saved in `saved_char'. */ int char_is_saved = 0; /* Odd char from previous call. */ unsigned char saved_char; int do_status = 1; int do_hash = 0; int do_verify = 0; int do_split = 0; hashconv_t hashconv = DEFAULT_HASHCONV; static char *splitformat = DEFAULT_SPLIT_FORMAT; static off_t splitsize; /* How many blocks in between screen writes for status output. */ ssize_t update_thresh = 256; time_t start_time; static struct conversion conversions[] = { {"ascii", C_ASCII | C_TWOBUFS}, /* EBCDIC to ASCII. */ {"ebcdic", C_EBCDIC | C_TWOBUFS}, /* ASCII to EBCDIC. */ {"ibm", C_IBM | C_TWOBUFS}, /* Slightly different ASCII to EBCDIC. */ {"block", C_BLOCK | C_TWOBUFS}, /* Variable to fixed length records. */ {"unblock", C_UNBLOCK | C_TWOBUFS}, /* Fixed to variable length records. */ {"lcase", C_LCASE | C_TWOBUFS}, /* Translate upper to lower case. */ {"ucase", C_UCASE | C_TWOBUFS}, /* Translate lower to upper case. */ {"swab", C_SWAB | C_TWOBUFS}, /* Swap bytes of input. */ {"noerror", C_NOERROR}, /* Ignore i/o errors. */ {"notrunc", C_NOTRUNC}, /* Do not truncate output file. */ {"sync", C_SYNC}, /* Pad input records to ibs with NULs. */ {NULL, 0} }; FILE *popened[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; void usage(int status) { if (status != 0) log_info("Try `%s --help' for more information.\n", program_name); else { printf("Usage: %s [OPTION]...\n", program_name); printf("\ Enhanced version of dd for forensics and security.\n\ \n\ bs=BYTES force ibs=BYTES and obs=BYTES (default=32768)\n\ cbs=BYTES convert BYTES bytes at a time\n\ conv=KEYWORDS convert the file as per the comma separated keyword list\n\ count=BLOCKS copy only BLOCKS input blocks\n\ limit=BYTES similar to count but using BYTES instead of BLOCKS\n\ ibs=BYTES read BYTES bytes at a time\n\ if=FILE read from FILE instead of stdin\n\ obs=BYTES write BYTES bytes at a time\n\ of=FILE write to FILE instead of stdout\n\ of:=COMMAND exec and write output to process COMMAND\n\ seek=BLOCKS skip BLOCKS obs-sized blocks at start of output\n\ skip=BLOCKS skip BLOCKS ibs-sized blocks at start of input\n\ pattern=HEX use the specified binary pattern as input\n\ textpattern=TEXT use repeating TEXT as input\n\ errlog=FILE send error messages to FILE as well as stderr\n\ hash=NAME do hash calculation (md5, sha1, sha256, sha384 or sha512)\n\ hashlog=FILE send hash output to FILE instead of stderr\n\ hashwindow=BYTES perform a hash on every BYTES amount of data\n\ hashlog:=COMMAND exec and write hashlog to process COMMAND\n\ ALGORITHMlog:=COMMAND also works in the same fashion of hashlog:=COMMAND\n\ hashconv=[before|after] perform the hashing before or after the conversions\n\ hashformat=FORMAT display each hashwindow according to FORMAT\n\ totalhashformat=FORMAT display the total hash value according to FORMAT\n\ status=[on|off] display a continual status message on stderr\n\ statusinterval=N update the status message every N blocks\n\ sizeprobe=[if|of|BYTES] what to use as value to percentage indicator\n\ split=BYTES write every BYTES amount of data to a new file\n\ splitformat=[TEXT|MAC|WIN] the file extension format for split operation\n\ vf=FILE verify that FILE matches the specified input\n\ verifylog=FILE send verify results to FILE instead of stderr\n\ verifylog:=COMMAND exec and write verify results to process COMMAND\n\ \n\ --help display this help and exit\n\ --version output version information and exit\n\ \n\ Read the manpage dcfldd(1) for more details about each option and to see\n\ some examples.\n\ "); puts("\nReport bugs at\nhttps://github.com/resurrecting-open-source-projects/dcfldd/issues\n"); } exit(status); } void print_stats(void) { char buf[2][LONGEST_HUMAN_READABLE + 1]; log_info("%s+%s records in\n", human_readable (r_full, buf[0], 1, 1), human_readable (r_partial, buf[1], 1, 1)); log_info("%s+%s records out\n", human_readable (w_full, buf[0], 1, 1), human_readable (w_partial, buf[1], 1, 1)); if (r_truncate > 0) { log_info("%s %s\n", human_readable (r_truncate, buf[0], 1, 1), (r_truncate == 1 ? "truncated record" : "truncated records")); } } void cleanup(void) { if (do_status) fprintf(stderr, "\n"); if (!do_verify) print_stats(); if (close(STDIN_FILENO) < 0) ; if (close(STDOUT_FILENO) < 0) ; int i; for (i = 0; i<8; i++) if (popened[i] != NULL) pclose(popened[i]); outputlist_t *listptr; for (listptr = outputlist; listptr != NULL; listptr = listptr->next) if (listptr->stream != NULL) pclose(listptr->stream); } inline void quit(int code) { cleanup(); exit(code); } static void interrupt_handler(int sig) { #ifdef SA_NOCLDSTOP struct sigaction sigact; sigact.sa_handler = SIG_DFL; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigaction(sig, &sigact, NULL); #else signal(sig, SIG_DFL); #endif cleanup(); kill(getpid(), sig); } static void siginfo_handler(int sig) { print_stats(); } /* Encapsulate portability mess of establishing signal handlers. */ static void install_handler(int sig_num, void (*sig_handler) (int sig)) { #ifdef SA_NOCLDSTOP struct sigaction sigact; sigaction(sig_num, NULL, &sigact); if (sigact.sa_handler != SIG_IGN) { sigact.sa_handler = sig_handler; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigaction(sig_num, &sigact, NULL); } #else if (signal(sig_num, SIG_IGN) != SIG_IGN) signal(sig_num, sig_handler); #endif } /* Open a file to a particular file descriptor. This is like standard `open', except it always returns DESIRED_FD if successful. */ static int open_fd(int desired_fd, char const *filename, int options, mode_t mode) { int fd; close(desired_fd); fd = open(filename, options, mode); if (fd < 0) return -1; if (fd != desired_fd) { if (dup2(fd, desired_fd) != desired_fd) desired_fd = -1; if (close(fd) != 0) return -1; } return desired_fd; } /* Interpret one "conv=..." option. * As a by product, this function replaces each `,' in STR with a NUL byte. */ void parse_conversion(char *str) { char *new; unsigned int i; do { new = strchr(str, ','); if (new != NULL) *new++ = '\0'; for (i = 0; conversions[i].convname != NULL; i++) if (STREQ(conversions[i].convname, str)) { conversions_mask |= conversions[i].conversion; break; } if (conversions[i].convname == NULL) { log_info("invalid conversion: %s\n", str); usage(1); } str = new; } while (new != NULL); } void parse_hash(char *str) { char *new; unsigned int i; do { new = strchr(str, ','); if (new != NULL) *new++ = '\0'; for (i = 0; hashops[i].name != NULL; i++) if (STREQ(hashops[i].name, str)) { hashflags |= hashops[i].flag; break; } if (hashops[i].name == NULL) { log_info("invalid hash: %s\n", str); usage(1); } str = new; } while (new != NULL); } /* Return the value of STR, interpreted as a non-negative decimal integer, * optionally multiplied by various values. * Assign nonzero to *INVALID if STR does not represent a number in * this format. */ #if HAVE_DECL_STRTOUMAX # define __strtol_t uintmax_t # define __strtol xstrtoumax #elif HAVE_DECL_STRTOUL # define __strtol_t unsigned long int # define __strtol xstrtoul #else # define __strtol_t long int # define __strtol xstrtol #endif __strtol_t parse_integer(const char *str, int *invalid) { __strtol_t n; char *suffix; enum strtol_error e = __strtol(str, &suffix, 10, &n, "bcEGkMPTwYZ0"); if (e == LONGINT_INVALID_SUFFIX_CHAR && *suffix == 'x') { __strtol_t multiplier = parse_integer(suffix + 1, invalid); if (multiplier != 0 && n * multiplier / multiplier != n) { *invalid = 1; return 0; } n *= multiplier; } else if (e != LONGINT_OK) { *invalid = 1; return 0; } return n; } int hex2char(char *hstr) { int retval; if (strlen(hstr) != 2) return -1; if (EOF == sscanf(hstr, "%x", &retval)) return -1; return retval; } static void scanargs(int argc, char **argv) { int i; --argc; ++argv; for (i = optind; i < argc; i++) { char *name, *val; name = argv[i]; val = strchr(name, '='); if (val == NULL) { log_info("%s: unrecognized option %s\n", program_name, name); usage(1); } *val++ = '\0'; if (STREQ(name, "if")) if (STREQ(val, "/dev/zero")) { /* replace if=/dev/zero with pattern=00 */ pattern = make_pattern("00"); pattern_len = 1; input_from_pattern = 1; } else input_file = val; else if (STREQ(name, "of")) if (do_split) outputlist_add(SPLIT_FILE, val, splitformat, splitsize); else open_output(val); else if (STREQ(name, "of:")) open_output_pipe(val); else if (STREQ(name, "vf")) { verify_file = val; do_verify++; } else if (STREQ(name, "conv")) parse_conversion(val); else if (STREQ(name, "pattern")) { pattern = make_pattern(val); if (pattern == NULL) { log_info("%s: invalid hex pattern: %s", program_name, val); quit(1); } input_from_pattern = 1; } else if (STREQ(name, "textpattern")) { pattern = val; pattern_len = strlen(pattern); input_from_pattern = 1; } else if (STREQ(name, "hashlog")) { hash_log = fopen(val, "w"); if (hash_log == NULL) syscall_error(val); do_hash++; } else if (STREQ(name, "hashlog:")) { popened[0] = hash_log = popen(val, "w"); if (hash_log == NULL) syscall_error(val); do_hash++; } else if (STREQ(name, "hashformat")) hashformat = parse_hashformat(val); else if (STREQ(name, "totalhashformat")) totalhashformat = parse_hashformat(val); else if (STREQ(name, "md5log")) { hashops[MD5].log = fopen(val, "w"); if (hashops[MD5].log == NULL) syscall_error(val); do_hash++; } else if (STREQ(name, "md5log:")) { popened[1] = hashops[MD5].log = popen(val, "w"); if (hashops[MD5].log == NULL) syscall_error(val); do_hash++; } else if (STREQ(name, "sha1log")) { hashops[SHA1].log = fopen(val, "w"); if (hashops[SHA1].log == NULL) syscall_error(val); do_hash++; } else if (STREQ(name, "sha1log:")) { popened[2] = hashops[SHA1].log = popen(val, "w"); if (hashops[SHA1].log == NULL) syscall_error(val); do_hash++; } else if (STREQ(name, "sha256log")) { hashops[SHA256].log = fopen(val, "w"); if (hashops[SHA256].log == NULL) syscall_error(val); do_hash++; } else if (STREQ(name, "sha256log:")) { popened[3] = hashops[SHA256].log = popen(val, "w"); if (hashops[SHA256].log == NULL) syscall_error(val); do_hash++; } else if (STREQ(name, "sha384log")) { hashops[SHA384].log = fopen(val, "w"); if (hashops[SHA384].log == NULL) syscall_error(val); do_hash++; } else if (STREQ(name, "sha384log:")) { popened[4] = hashops[SHA384].log = popen(val, "w"); if (hashops[SHA384].log == NULL) syscall_error(val); do_hash++; } else if (STREQ(name, "sha512log")) { hashops[SHA512].log = fopen(val, "w"); if (hashops[SHA512].log == NULL) syscall_error(val); do_hash++; } else if (STREQ(name, "sha512log:")) { popened[5] = hashops[SHA512].log = popen(val, "w"); if (hashops[SHA512].log == NULL) syscall_error(val); do_hash++; } else if (STREQ(name, "verifylog")) { verify_log = fopen(val, "w"); if (verify_log == NULL) syscall_error(val); } else if (STREQ(name, "verifylog:")) { popened[6] = verify_log = popen(val, "w"); if (verify_log == NULL) syscall_error(val); } else if (STREQ(name, "errlog")) { errlog = fopen(val, "w"); if (errlog == NULL) syscall_error(val); } else if (STREQ(name, "errlog:")) { popened[7] = errlog = popen(val, "w"); if (errlog == NULL) syscall_error(val); } else if (STREQ(name, "splitformat")) splitformat = val; else if (STREQ(name, "status")) { if (STREQ(val, "off")) do_status = 0; else if (STREQ(val, "on")) do_status = 1; } else if (STREQ(name, "hashalgorithm") || STREQ(name, "hash")) { parse_hash(val); do_hash++; } else if (STREQ(name, "hashconv")) if (STREQ(val, "before")) hashconv = HASHCONV_BEFORE; else if (STREQ(val, "after")) hashconv = HASHCONV_AFTER; else user_error("invalid hashconv value \"%s\"", val); else if (STREQ(name, "sizeprobe")) { if (STREQ(val, "if")) probe = PROBE_INPUT; else if (STREQ(val, "of")) probe = PROBE_OUTPUT; else { int invalid = 0; uintmax_t n = parse_integer(val, &invalid); probe = PROBE_INPUT_PROVIDED; probed_size = n; if (invalid) probe = PROBE_NONE; } } else { int invalid = 0; uintmax_t n = parse_integer(val, &invalid); if (STREQ(name, "ibs")) { input_blocksize = n; invalid |= input_blocksize != n || input_blocksize == 0; conversions_mask |= C_TWOBUFS; } else if (STREQ(name, "obs")) { output_blocksize = n; invalid |= output_blocksize != n || output_blocksize == 0; conversions_mask |= C_TWOBUFS; } else if (STREQ(name, "bs")) { output_blocksize = input_blocksize = n; invalid |= output_blocksize != n || output_blocksize == 0; } else if (STREQ(name, "cbs")) { conversion_blocksize = n; invalid |= (conversion_blocksize != n || conversion_blocksize == 0); } else if (STREQ(name, "skip")) skip_records = n; else if (STREQ(name, "vskip")) vskip_records = n; else if (STREQ(name, "seek")) seek_records = n; else if (STREQ(name, "count")) { max_records = n; limit = 0; } else if (STREQ(name, "limit")) limit = n; else if (STREQ(name, "split")) { splitsize = n; do_split++; } else if (STREQ(name, "hashwindow")) { hash_windowlen = n; do_hash++; } else if (STREQ(name, "statusinterval")) { if (n == 0) { invalid = 1; } else { update_thresh = n; } } else { log_info("%s: unrecognized option %s=%s", program_name, name, val); usage(1); } if (invalid) log_info("%s: invalid number %s", program_name, val); } } /* If bs= was given, both `input_blocksize' and `output_blocksize' will have been set to positive values. If either has not been set, bs= was not given, so make sure two buffers are used. */ if (input_blocksize == 0 || output_blocksize == 0) conversions_mask |= C_TWOBUFS; if (input_blocksize == 0) input_blocksize = DEFAULT_BLOCKSIZE; if (output_blocksize == 0) output_blocksize = DEFAULT_BLOCKSIZE; if (conversion_blocksize == 0) conversions_mask &= ~(C_BLOCK | C_UNBLOCK); if (limit != 0) { max_records = (limit / input_blocksize) + 1; max_records_extrabytes = limit % input_blocksize; } /* set all unset hashlogs to go to the overall hashlog */ for (i = 0; hashops[i].name != NULL; i++) if (hashops[i].log == NULL) hashops[i].log = hash_log; if (do_hash && hashflags == 0) hashflags = hashops[DEFAULT_HASH].flag; if (do_verify) { do_hash = 0; init_hashlist(&ihashlist, hashops[VERIFY_HASH].flag); } else if (do_hash) init_hashlist(&ihashlist, hashflags); /* make sure selected options make sense */ if (output_file != NULL && verify_file != NULL) user_error("Please select either an output file or a verify file, not both."); } int main(int argc, char **argv) { int i; int exit_status; char *def_hashwin_fmt; char *def_totalhash_fmt; def_hashwin_fmt = strndup(DEFAULT_HASHWINDOW_FORMAT, strlen(DEFAULT_HASHWINDOW_FORMAT)); def_totalhash_fmt = strndup(DEFAULT_TOTALHASH_FORMAT, strlen(DEFAULT_TOTALHASH_FORMAT)); /* disable buffering on stderr */ setbuf(stderr, NULL); hash_log = stderr; verify_log = stderr; program_name = argv[0]; hashformat = parse_hashformat(def_hashwin_fmt); totalhashformat = parse_hashformat(def_totalhash_fmt); /* Arrange to close stdout if parse_long_options exits. */ //atexit (close_stdout_wrapper); parse_long_options(argc, argv, PROGRAM_NAME, PACKAGE, VERSION, AUTHORS, usage); /* Don't close stdout on exit from here on. */ //closeout_func = NULL; /* Initialize translation table to identity translation. */ for (i = 0; i < 256; i++) trans_table[i] = i; /* Decode arguments. */ scanargs(argc, argv); apply_translations(); if (input_file != NULL) { if (open_fd(STDIN_FILENO, input_file, O_RDONLY, 0) < 0) syscall_error(input_file); } else if (pattern == NULL) input_file = "standard input"; if (verify_file != NULL) if ((verify_fd = open(verify_file, O_RDONLY)) < 0) syscall_error(verify_file); if (outputlist == NULL) outputlist_add(SINGLE_FILE, STDOUT_FILENO); install_handler(SIGINT, interrupt_handler); install_handler(SIGQUIT, interrupt_handler); install_handler(SIGPIPE, interrupt_handler); install_handler(SIGINFO, siginfo_handler); if (probe == PROBE_INPUT) if (input_from_pattern) probe = PROBE_NONE; else sizeprobe(STDIN_FILENO); else if (probe == PROBE_OUTPUT) sizeprobe(outputlist->data.fd); start_time = time(NULL); if (do_verify) exit_status = dd_verify(); else exit_status = dd_copy(); close(1); quit(exit_status); } dcfldd-1.7.1/src/dcfldd.h000066400000000000000000000107661410702647300151360ustar00rootroot00000000000000/* $Id: dcfldd.h,v 1.7 2005/05/19 21:00:07 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright 85, 90, 91, 1995-2001, 2005 Free Software Foundation, Inc. Copyright 2008 David Loveall Copyright 2017-2019 Joao Eriberto Mota Filho 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #ifndef DCFLDD_H #define DCFLDD_H #define _FILE_OFFSET_BITS 64 #define LARGEFILE_SOURCE #if HAVE_INTTYPES_H # include #endif #include #include #include #include #include "config.h" #include "system.h" #include "hash.h" /* The official name of this program (e.g., no `g' prefix). */ #define PROGRAM_NAME "dcfldd" #define AUTHORS "dcfldd by Nicholas Harbour and others.\nGNU dd by Paul Rubin, David MacKenzie and Stuart Kemp.\nCurrently, the source code is at\nhttps://github.com/resurrecting-open-source-projects/dcfldd" #define SWAB_ALIGN_OFFSET 2 #ifndef SIGINFO # define SIGINFO SIGUSR1 #endif #ifndef S_TYPEISSHM # define S_TYPEISSHM(Stat_ptr) 0 #endif #define ROUND_UP_OFFSET(X, M) ((M) - 1 - (((X) + (M) - 1) % (M))) #define PTR_ALIGN(Ptr, M) ((Ptr) \ + ROUND_UP_OFFSET ((char *)(Ptr) - (char *)0, (M))) #define max(a, b) ((a) > (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) #define output_char(c) \ do \ { \ obuf[oc++] = (c); \ if (oc >= output_blocksize) \ write_output (); \ } \ while (0) /* Default input and output blocksize. */ /* #define DEFAULT_BLOCKSIZE 512 */ #ifndef DEFAULT_BLOCKSIZE #define DEFAULT_BLOCKSIZE 32768 /* 32k blocksize is HUGELY more efficient * for large device IO than 512 */ #endif /* DEFAULT_BLOCKSIZE */ #ifndef DEFAULT_SPLIT_FORMAT #define DEFAULT_SPLIT_FORMAT "nnn" #endif /* DEFAULT_SPLIT_FORMAT */ #ifndef DEFAULT_HASHWINDOW_FORMAT #define DEFAULT_HASHWINDOW_FORMAT "#window_start# - #window_end#: #hash#" #endif /* DEFAULT_HASHWINDOW_FORMAT */ #ifndef DEFAULT_TOTALHASH_FORMAT #define DEFAULT_TOTALHASH_FORMAT "\nTotal (#algorithm#): #hash#" #endif /* DEFAULT_TOTALHASH_FORMAT */ #ifndef DEFAULT_HASHCONV #define DEFAULT_HASHCONV HASHCONV_BEFORE #endif /* DEFAULT_HASHCONV */ /* Conversions bit masks. */ #define C_ASCII 01 #define C_EBCDIC 02 #define C_IBM 04 #define C_BLOCK 010 #define C_UNBLOCK 020 #define C_LCASE 040 #define C_UCASE 0100 #define C_SWAB 0200 #define C_NOERROR 0400 #define C_NOTRUNC 01000 #define C_SYNC 02000 /* Use separate input and output buffers, and combine partial input blocks. */ #define C_TWOBUFS 04000 typedef enum { HASHCONV_BEFORE, HASHCONV_AFTER } hashconv_t; extern hashconv_t hashconv; extern char *program_name; extern char *input_file; extern char *output_file; extern size_t input_blocksize; extern size_t output_blocksize; extern size_t conversion_blocksize; extern uintmax_t skip_records; extern uintmax_t seek_records; extern uintmax_t max_records; extern uintmax_t max_records_extrabytes; extern int conversions_mask; extern int translation_needed; extern uintmax_t w_partial; extern uintmax_t w_full; extern uintmax_t r_partial; extern uintmax_t r_full; extern uintmax_t r_partial; extern uintmax_t r_truncate; extern int do_hash; extern int do_verify; extern int do_status; extern int char_is_saved; extern unsigned char saved_char; extern time_t start_time; extern ssize_t update_thresh; struct conversion { char *convname; int conversion; }; /* FIXME: Figure out where usage() is getting called from and delete this if needed */ extern void usage(int); extern void print_stats(void); extern void cleanup(void); extern inline void quit(int); extern void parse_conversion(char *); extern int hex2char(char *); #endif /* DCFLDD_H */ dcfldd-1.7.1/src/full-write.c000066400000000000000000000035631410702647300160000ustar00rootroot00000000000000/* full-write.c -- an interface to write that retries after interrupts Copyright (C) 1993, 1994, 1997, 1998, 2000 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Copied largely from GNU C's cccp.c. */ #include "dcfldd.h" #if HAVE_CONFIG_H # include #endif #include #if HAVE_UNISTD_H # include #endif #include #ifndef errno extern int errno; #endif /* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted. Return LEN upon success, write's (negative) error code otherwise. */ int full_write (int desc, const char *ptr, size_t len) { int total_written; total_written = 0; while (len > 0) { int written = write (desc, ptr, len); /* write on an old Slackware Linux 1.2.13 returns zero when I try to write more data than there is room on a floppy disk. This puts dd into an infinite loop. Reproduce with dd if=/dev/zero of=/dev/fd0. If you have this problem, consider upgrading to a newer kernel. */ if (written < 0) { #ifdef EINTR if (errno == EINTR) continue; #endif return written; } total_written += written; ptr += written; len -= written; } return total_written; } dcfldd-1.7.1/src/full-write.h000066400000000000000000000021201410702647300157710ustar00rootroot00000000000000/* $Id: full-write.h,v 1.3 2005/05/13 18:52:06 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright (C) 85, 90, 91, 1995-2001, 2005 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #ifndef FULL_WRITE_H #define FULL_WRITE_H int full_write(int, const char *, size_t); #endif /* FULL_WRITE_H */ dcfldd-1.7.1/src/getpagesize.h000066400000000000000000000016241410702647300162160ustar00rootroot00000000000000/* Emulate getpagesize on systems that lack it. */ #ifndef HAVE_GETPAGESIZE #ifdef HAVE_UNISTD_H # include #endif #if !defined getpagesize && defined _SC_PAGESIZE # if !(defined VMS && __VMS_VER < 70000000) # define getpagesize() sysconf (_SC_PAGESIZE) # endif #endif #if !defined getpagesize && defined VMS # ifdef __ALPHA # define getpagesize() 8192 # else # define getpagesize() 512 # endif #endif /* This is for BeOS. */ #if !defined getpagesize && HAVE_OS_H # include # if defined B_PAGE_SIZE # define getpagesize() B_PAGE_SIZE # endif #endif #ifndef getpagesize # include # ifdef EXEC_PAGESIZE # define getpagesize() EXEC_PAGESIZE # else # ifdef NBPG # ifndef CLSIZE # define CLSIZE 1 # endif # define getpagesize() (NBPG * CLSIZE) # else # ifdef NBPC # define getpagesize() NBPC # endif # endif # endif #endif #endif /* not HAVE_GETPAGESIZE */ dcfldd-1.7.1/src/hash.c000066400000000000000000000232571410702647300146330ustar00rootroot00000000000000/* $Id: hash.c,v 1.4 2005/05/14 23:20:30 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright (C) 85, 90, 91, 1995-2001, 2005 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #include "dcfldd.h" #include #include #include #include "md5.h" #include "sha1.h" #include "sha2.h" #include "hash.h" #include "log.h" hashflag_t hashflags = 0; /* Md5 global data */ MD5_CTX MD5_total_context; MD5_CTX MD5_window_context; MD5_CTX MD5_vtotal_context; MD5_CTX MD5_vwindow_context; char MD5_hashstr[MD5_DIGEST_STRING_LENGTH + 1] = {'\0'}; /* SHA1 global data */ SHA1Context SHA1_total_context; SHA1Context SHA1_window_context; SHA1Context SHA1_vtotal_context; SHA1Context SHA1_vwindow_context; char SHA1_hashstr[SHA1_DIGEST_STRING_LENGTH + 1] = {'\0'}; /* SHA256 global data */ SHA256_CTX SHA256_total_context; SHA256_CTX SHA256_window_context; SHA256_CTX SHA256_vtotal_context; SHA256_CTX SHA256_vwindow_context; char SHA256_hashstr[SHA256_DIGEST_STRING_LENGTH + 1] = {'\0'}; /* SHA384 global data */ SHA384_CTX SHA384_total_context; SHA384_CTX SHA384_window_context; SHA384_CTX SHA384_vtotal_context; SHA384_CTX SHA384_vwindow_context; char SHA384_hashstr[SHA384_DIGEST_STRING_LENGTH + 1] = {'\0'}; /* SHA512 global data */ SHA512_CTX SHA512_total_context; SHA512_CTX SHA512_window_context; SHA512_CTX SHA512_vtotal_context; SHA512_CTX SHA512_vwindow_context; char SHA512_hashstr[SHA512_DIGEST_STRING_LENGTH + 1] = {'\0'}; off_t hash_windowlen = 0; off_t window_beginning = 0; off_t bytes_in_window = 0; off_t bytes_in_total = 0; void (*hashinit)(void *); void (*hashupdate)(void *, const void *, size_t); void (*hashfinal)(void *, void *); void *hashstr_buf; size_t hashstr_buf_size; FILE *hash_log; /* Hash algorithms */ hashlist_t *ihashlist; hashtype_t hashops[] = { {"md5", 1, &MD5_window_context, &MD5_total_context, &MD5_vwindow_context, &MD5_vtotal_context, (void (*)(void *)) MD5Init, (void (*)(void *, const void *, size_t)) MD5Update, (void (*)(void *, void *)) MD5Final, &MD5_hashstr[0], sizeof (MD5_hashstr), NULL}, {"sha1", 1<<1, &SHA1_window_context, &SHA1_total_context, &SHA1_vwindow_context, &SHA1_vtotal_context, (void (*)(void *)) SHA1Init, (void (*)(void *, const void *, size_t)) SHA1Update, (void (*)(void *, void *)) SHA1End, &SHA1_hashstr[0], sizeof (SHA1_hashstr), NULL}, {"sha256", 1<<2, &SHA256_window_context, &SHA256_total_context, &SHA256_vwindow_context, &SHA256_vtotal_context, (void (*)(void *)) SHA256_Init, (void (*)(void *, const void *, size_t)) SHA256_Update, (void (*)(void *, void *)) SHA256_End, SHA256_hashstr, sizeof (SHA256_hashstr), NULL}, {"sha384", 1<<3, &SHA384_window_context, &SHA384_total_context, &SHA384_vwindow_context, &SHA384_vtotal_context, (void (*)(void *)) SHA384_Init, (void (*)(void *, const void *, size_t)) SHA384_Update, (void (*)(void *, void *)) SHA384_End, &SHA384_hashstr[0], sizeof (SHA384_hashstr), NULL}, {"sha512", 1<<4, &SHA512_window_context, &SHA512_total_context, &SHA512_vwindow_context, &SHA512_vtotal_context, (void (*)(void *)) SHA512_Init, (void (*)(void *, const void *, size_t)) SHA512_Update, (void (*)(void *, void *)) SHA512_End, &SHA512_hashstr[0], sizeof (SHA512_hashstr), NULL}, {NULL, 0, NULL, NULL, NULL, NULL, (void (*)(void *)) NULL, (void (*)(void *, const void *, size_t)) NULL, (void (*)(void *, void *)) NULL, NULL, 0, NULL} }; static void add_hash(hashlist_t **hashlist, int hash) { hashlist_t *hlptr = *hashlist; int i; if (hlptr == NULL) { hlptr = malloc(sizeof (hashlist_t)); *hashlist = hlptr; } else { for ( ; hlptr->next != NULL; hlptr = hlptr->next) ; hlptr->next = malloc(sizeof (hashlist_t)); hlptr = hlptr->next; } hlptr->next = NULL; hlptr->hash = &hashops[hash]; } /* add all the appropriate hashops according to the flags */ void init_hashlist(hashlist_t **hashlist, hashflag_t flags) { int i; for (i = 0; hashops[i].name != NULL; i++) if (hashops[i].flag & flags) add_hash(hashlist, i); } /* not to be confused with init_hashlist, this function calls * the hashtype specific init function for each hash type in * the list */ void hashl_init(hashlist_t *hashlist, int context) { hashlist_t *hptr; for (hptr = hashlist; hptr != NULL; hptr = hptr->next) { void *ctx; switch (context) { case WINDOW_CTX: ctx = hptr->hash->window_context; break; case TOTAL_CTX: ctx = hptr->hash->total_context; break; case VWINDOW_CTX: ctx = hptr->hash->vwindow_context; break; case VTOTAL_CTX: ctx = hptr->hash->vtotal_context; break; default: internal_error("unreachable branch encountered in hashl_init()"); break; } (hptr->hash->init)(ctx); } } void hashl_update(hashlist_t *hashlist, int context, const void *buf, size_t len) { hashlist_t *hptr; for (hptr = hashlist; hptr != NULL; hptr = hptr->next) { void *ctx; switch (context) { case WINDOW_CTX: ctx = hptr->hash->window_context; break; case TOTAL_CTX: ctx = hptr->hash->total_context; break; case VWINDOW_CTX: ctx = hptr->hash->vwindow_context; break; case VTOTAL_CTX: ctx = hptr->hash->vtotal_context; break; default: internal_error("unreachable branch encountered in hashl_update()"); break; } (hptr->hash->update)(ctx, buf, len); } } void hashl_final(hashlist_t *hashlist, int context) { hashlist_t *hptr; for (hptr = hashlist; hptr != NULL; hptr = hptr->next) { void *ctx; switch (context) { case WINDOW_CTX: ctx = hptr->hash->window_context; break; case TOTAL_CTX: ctx = hptr->hash->total_context; break; case VWINDOW_CTX: ctx = hptr->hash->vwindow_context; break; case VTOTAL_CTX: ctx = hptr->hash->vtotal_context; break; default: internal_error("unreachable branch encountered in hashl_final()"); break; } /* note that this writes the hash string to the global buffer * for the specific hashtype, when calling this multiple times * (i.e. like in verify) copy that buffer out before finalizing * another list */ (hptr->hash->final)(ctx, hptr->hash->hashstr_buf); } } void hash_update_buf(hashlist_t *hashlist, int winctx, int ttlctx, void *buf, size_t len) { if (hash_windowlen != 0) { hashl_update(hashlist, winctx, buf, len); if (winctx == WINDOW_CTX) /* don't do this for verify or you'll get double */ bytes_in_window += len; } hashl_update(hashlist, ttlctx, buf, len); if(ttlctx == TOTAL_CTX) bytes_in_total += len; } void hash_update(hashlist_t *hashlist, void *buf, size_t len) { size_t left_in_window = hash_windowlen - bytes_in_window; if (bytes_in_total == 0) hashl_init(hashlist, TOTAL_CTX); if (hash_windowlen == 0) hash_update_buf(hashlist, WINDOW_CTX, TOTAL_CTX, buf, len); else { if (bytes_in_window == 0) hashl_init(hashlist, WINDOW_CTX); if (len >= left_in_window) { hash_update_buf(hashlist, WINDOW_CTX, TOTAL_CTX, buf, left_in_window); hashl_final(hashlist, WINDOW_CTX); display_windowhash(hashlist, hash_windowlen); window_beginning += hash_windowlen; bytes_in_window = 0; hash_update(hashlist, buf + left_in_window, len - left_in_window); } else hash_update_buf(hashlist, WINDOW_CTX, TOTAL_CTX, buf, len); } } void display_windowhash(hashlist_t *hashlist, off_t windowlen) { hashlist_t *hptr; for (hptr = hashlist; hptr != NULL; hptr = hptr->next) log_hashwindow(hptr->hash, window_beginning, (window_beginning + windowlen), input_blocksize, hptr->hash->hashstr_buf); } void display_totalhash(hashlist_t *hashlist, int ttlctx) { hashlist_t *hptr; hashl_final(hashlist, ttlctx); for (hptr = hashlist; hptr != NULL; hptr = hptr->next) log_hashtotal(hptr->hash, 0, 0, input_blocksize, hptr->hash->hashstr_buf); } void hash_remainder(hashlist_t *hashlist, int winctx) { if (hash_windowlen > 0 && bytes_in_window > 0) { hashl_final(hashlist, winctx); display_windowhash(hashlist, bytes_in_window); } } dcfldd-1.7.1/src/hash.h000066400000000000000000000060541410702647300146340ustar00rootroot00000000000000/* $Id: hash.h,v 1.4 2005/05/14 23:20:30 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright 85, 90, 91, 1995-2001, 2005 Free Software Foundation, Inc. Copyright 2012 Miah Gregory 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #ifndef HASH_H #define HASH_H #include "dcfldd.h" #include "md5.h" #include "sha1.h" #include "sha2.h" #include #include /* bytes_in_window and bytes_in_total are only used for dd_copy() */ extern off_t bytes_in_window; extern off_t bytes_in_total; extern void (*hashinit)(void *); extern void (*hashupdate)(void *, const void *, size_t); extern void (*hashfinal)(void *, void *); extern void *hashstr_buf; extern size_t hashstr_buf_size; typedef uint32_t hashflag_t; extern hashflag_t hashflags; typedef struct hashtype { char *name; hashflag_t flag; void *window_context; void *total_context; void *vwindow_context; void *vtotal_context; void (*init)(void *); void (*update)(void *, const void *, size_t); void (*final)(void *, void *); void *hashstr_buf; size_t hashstr_buf_size; FILE *log; } hashtype_t; typedef struct hashlist_s { struct hashlist_s *next; hashtype_t *hash; } hashlist_t; extern hashlist_t *ihashlist; extern struct hashtype hashops[]; extern FILE *hash_log; /* this enum order must correspond to their position in the hashops[] array */ enum {MD5 = 0, SHA1, SHA256, SHA384, SHA512}; enum {WINDOW_CTX, TOTAL_CTX, VWINDOW_CTX, VTOTAL_CTX}; #ifndef VERIFY_HASH #define VERIFY_HASH MD5 #endif #ifndef DEFAULT_HASH #define DEFAULT_HASH MD5 #endif extern off_t bytes_in_window; extern off_t bytes_in_total; extern off_t hash_windowlen; extern off_t window_beginning; extern void display_windowhash(hashlist_t *, off_t); extern void display_totalhash(hashlist_t *, int); extern void hash_update(hashlist_t *, void *, size_t); extern void hash_update_buf(hashlist_t *, int, int, void *, size_t); extern void hash_remainder(hashlist_t *, int); extern void init_hashlist(hashlist_t **hashlist, hashflag_t flags); /* inner hashl_* funcitons are for iterating over hashlists */ extern void hashl_init(hashlist_t *, int); extern void hashl_update(hashlist_t *, int, const void *, size_t); extern void hashl_final(hashlist_t *, int); #endif /* HASH_H */ dcfldd-1.7.1/src/hashformat.c000066400000000000000000000116411410702647300160360ustar00rootroot00000000000000/* $Id: hashformat.c,v 1.2 2005/05/15 13:18:27 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright (C) 85, 90, 91, 1995-2001, 2005 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #include "dcfldd.h" #include "hashformat.h" #include "log.h" #include "util.h" #include "sys2.h" #include #include #include #include #include format_t *hashformat = NULL; format_t *totalhashformat = NULL; static fmtatom_op_t fmt_string_op; static fmtatom_op_t fmt_window_start_op; static fmtatom_op_t fmt_window_end_op; static fmtatom_op_t fmt_winblk_start_op; static fmtatom_op_t fmt_winblk_end_op; static fmtatom_op_t fmt_algorithm_op; static fmtatom_op_t *fmtatom_op_table[] = { /* order must conform to fmtatom_t enum */ fmt_string_op, fmt_window_start_op, fmt_window_end_op, fmt_winblk_start_op, fmt_winblk_end_op, fmt_string_op, fmt_algorithm_op }; static void add_fmtatom(format_t **, fmtatom_t, void *); static void add_fmtatom(format_t **format, fmtatom_t atom, void *data) { format_t *fmt; if (*format == NULL) { *format = malloc(sizeof **format); fmt = *format; } else { /* cycle to the end of the list */ for (fmt = *format; fmt->next != NULL; fmt = fmt->next) ; fmt->next = malloc(sizeof *fmt); fmt = fmt->next; } fmt->next = NULL; fmt->type = atom; fmt->op = fmtatom_op_table[atom]; fmt->data = data; } format_t *parse_hashformat(char *str) { format_t *fmt = NULL; int i; if (str == NULL || strlen(str) == 0) return NULL; replace_escapes(str); if (*str == VARIABLE_HOOK) { for (i = 1; str[i] != '\0' && str[i] != VARIABLE_HOOK; i++) ; if (str[i] == '\0') user_error("invalid variable specifier \"%s\", variables should be terminated with another \'%c\'", str, VARIABLE_HOOK); else if (i == 1) { /* if there is two HOOKs with nothing between, remove the second and * push up all the following chars one position */ for (i = 0; str[i] != '\0'; i++) str[i] = str[i + 1]; } else { str[i] = '\0'; str++; if (STREQ(str, "window_start")) add_fmtatom(&fmt, FMT_WINDOW_START, NULL); else if (STREQ(str, "window_end")) add_fmtatom(&fmt, FMT_WINDOW_END, NULL); else if (STREQ(str, "block_start")) add_fmtatom(&fmt, FMT_WINBLK_START, NULL); else if (STREQ(str, "block_end")) add_fmtatom(&fmt, FMT_WINBLK_END, NULL); else if (STREQ(str, "hash")) add_fmtatom(&fmt, FMT_HASH, NULL); else if (STREQ(str, "algorithm")) add_fmtatom(&fmt, FMT_ALGORITHM, NULL); else user_error("invalid variable specifier \"%c%s%c\"", VARIABLE_HOOK, str, VARIABLE_HOOK); fmt->next = parse_hashformat(&str[i]); return fmt; } } /* this loop needs to start at 1 so that "$$" will display a '$' properly */ for (i = 1; str[i] != '\0' && str[i] != VARIABLE_HOOK; i++) ; add_fmtatom(&fmt, FMT_STRING, strndup(str, i)); fmt->next = parse_hashformat(&str[i]); return fmt; } void print_fmt(format_t *fmt, FMTATOMOP_ARGS) { for (; fmt != NULL; fmt = fmt->next) (fmt->op)(stream, wina, winb, blksize, alg, fmt->data == NULL ? data : fmt->data); fputc('\n', stream); } static void fmt_string_op(FMTATOMOP_ARGS) { char *str = (char *)data; fputs(str, stream); } static void fmt_window_start_op(FMTATOMOP_ARGS) { fprintf(stream, "%llu", (unsigned long long int) wina); } static void fmt_window_end_op(FMTATOMOP_ARGS) { fprintf(stream, "%llu", (unsigned long long int) winb); } static void fmt_winblk_start_op(FMTATOMOP_ARGS) { fprintf(stream, "%llu", (unsigned long long int) wina / blksize); } static void fmt_winblk_end_op(FMTATOMOP_ARGS) { fprintf(stream, "%llu", (unsigned long long int) winb / blksize); } static void fmt_algorithm_op(FMTATOMOP_ARGS) { fputs(alg, stream); } dcfldd-1.7.1/src/hashformat.h000066400000000000000000000034601410702647300160430ustar00rootroot00000000000000/* $Id: hashformat.h,v 1.1 2005/05/14 23:20:30 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright (C) 85, 90, 91, 1995-2001, 2005 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #ifndef HASH_FORMAT_H #define HASH_FORMAT_H #include "dcfldd.h" #include "hash.h" #include #include typedef enum { FMT_STRING, FMT_WINDOW_START, FMT_WINDOW_END, FMT_WINBLK_START, /* window offsets / blocksize */ FMT_WINBLK_END, FMT_HASH, FMT_ALGORITHM } fmtatom_t; #define FMTATOMOP_ARGS FILE *stream, off_t wina, off_t winb, size_t blksize, char *alg, void *data typedef void (fmtatom_op_t)(FMTATOMOP_ARGS); #ifndef VARIABLE_HOOK #define VARIABLE_HOOK '#' #endif typedef struct format_s { struct format_s *next; fmtatom_t type; fmtatom_op_t *op; void *data; /* optional */ } format_t; extern format_t *hashformat; extern format_t *totalhashformat; extern void print_fmt(format_t *, FMTATOMOP_ARGS); extern format_t *parse_hashformat(char *); #endif /* HASH_FORMAT_H */ dcfldd-1.7.1/src/human.c000066400000000000000000000204111410702647300150050ustar00rootroot00000000000000/* human.c -- print human readable file size Copyright (C) 1996, 1997, 1998, 1999, 2000 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Originally contributed by lm@sgi.com; --si, output block size selection, and large file support added by eggert@twinsun.com. */ #if HAVE_CONFIG_H # include #endif #include #include #if HAVE_LIMITS_H # include #endif #if HAVE_STRING_H # include #else # include #endif #ifndef CHAR_BIT # define CHAR_BIT 8 #endif #if HAVE_STDLIB_H # include #endif #if ENABLE_NLS # include # define _(Text) gettext (Text) #else # define _(Text) Text #endif #include #include #include "human.h" static const char suffixes[] = { 0, /* not used */ 'k', /* kilo */ 'M', /* Mega */ 'G', /* Giga */ 'T', /* Tera */ 'P', /* Peta */ 'E', /* Exa */ 'Z', /* Zetta */ 'Y' /* Yotta */ }; /* If INEXACT_STYLE is not human_round_to_even, and if easily possible, adjust VALUE according to the style. */ static double adjust_value (enum human_inexact_style inexact_style, double value) { /* Do not use the floor or ceil functions, as that would mean linking with the standard math library, which is a porting pain. So leave the value alone if it is too large to easily round. */ if (inexact_style != human_round_to_even && value < (uintmax_t) -1) { uintmax_t u = value; value = u + (inexact_style == human_ceiling && u != value); } return value; } /* Like human_readable_inexact, except always round to even. */ char * human_readable (uintmax_t n, char *buf, int from_block_size, int output_block_size) { return human_readable_inexact (n, buf, from_block_size, output_block_size, human_round_to_even); } /* Convert N to a human readable format in BUF. N is expressed in units of FROM_BLOCK_SIZE. FROM_BLOCK_SIZE must be nonnegative. OUTPUT_BLOCK_SIZE must be nonzero. If it is positive, use units of OUTPUT_BLOCK_SIZE in the output number. Use INEXACT_STYLE to determine whether to take the ceiling or floor of any result that cannot be expressed exactly. If OUTPUT_BLOCK_SIZE is negative, use a format like "127k" if possible, using powers of -OUTPUT_BLOCK_SIZE; otherwise, use ordinary decimal format. Normally -OUTPUT_BLOCK_SIZE is either 1000 or 1024; it must be at least 2. Most people visually process strings of 3-4 digits effectively, but longer strings of digits are more prone to misinterpretation. Hence, converting to an abbreviated form usually improves readability. Use a suffix indicating which power is being used. For example, assuming -OUTPUT_BLOCK_SIZE is 1024, 8500 would be converted to 8.3k, 133456345 to 127M, 56990456345 to 53G, and so on. Numbers smaller than -OUTPUT_BLOCK_SIZE aren't modified. */ char * human_readable_inexact (uintmax_t n, char *buf, int from_block_size, int output_block_size, enum human_inexact_style inexact_style) { uintmax_t amt; int base; int to_block_size; int tenths = 0; int power; char *p; /* 0 means adjusted N == AMT.TENTHS; 1 means AMT.TENTHS < adjusted N < AMT.TENTHS + 0.05; 2 means adjusted N == AMT.TENTHS + 0.05; 3 means AMT.TENTHS + 0.05 < adjusted N < AMT.TENTHS + 0.1. */ int rounding = 0; if (output_block_size < 0) { base = -output_block_size; to_block_size = 1; } else { base = 0; to_block_size = output_block_size; } p = buf + LONGEST_HUMAN_READABLE; *p = '\0'; #ifdef lint /* Suppress `used before initialized' warning. */ power = 0; #endif /* Adjust AMT out of FROM_BLOCK_SIZE units and into TO_BLOCK_SIZE units. */ { int multiplier; int divisor; int r2; int r10; if (to_block_size <= from_block_size ? (from_block_size % to_block_size != 0 || (multiplier = from_block_size / to_block_size, (amt = n * multiplier) / multiplier != n)) : (from_block_size == 0 || to_block_size % from_block_size != 0 || (divisor = to_block_size / from_block_size, r10 = (n % divisor) * 10, r2 = (r10 % divisor) * 2, amt = n / divisor, tenths = r10 / divisor, rounding = r2 < divisor ? 0 < r2 : 2 + (divisor < r2), 0))) { /* Either the result cannot be computed easily using uintmax_t, or from_block_size is zero. Fall back on floating point. FIXME: This can yield answers that are slightly off. */ double damt = n * (from_block_size / (double) to_block_size); if (! base) sprintf (buf, "%.0f", adjust_value (inexact_style, damt)); else { double e = 1; power = 0; do { e *= base; power++; } while (e * base <= damt && power < sizeof suffixes - 1); damt /= e; sprintf (buf, "%.1f%c", adjust_value (inexact_style, damt), suffixes[power]); if (4 < strlen (buf)) sprintf (buf, "%.0f%c", adjust_value (inexact_style, damt * 10) / 10, suffixes[power]); } return buf; } } /* Use power of BASE notation if adjusted AMT is large enough. */ if (base && base <= amt) { power = 0; do { int r10 = (amt % base) * 10 + tenths; int r2 = (r10 % base) * 2 + (rounding >> 1); amt /= base; tenths = r10 / base; rounding = (r2 < base ? 0 < r2 + rounding : 2 + (base < r2 + rounding)); power++; } while (base <= amt && power < sizeof suffixes - 1); *--p = suffixes[power]; if (amt < 10) { if (2 * (1 - (int) inexact_style) < rounding + (tenths & (inexact_style == human_round_to_even))) { tenths++; rounding = 0; if (tenths == 10) { amt++; tenths = 0; } } if (amt < 10) { *--p = '0' + tenths; *--p = '.'; tenths = rounding = 0; } } } if (inexact_style == human_ceiling ? 0 < tenths + rounding : inexact_style == human_round_to_even ? 5 < tenths + (2 < rounding + (amt & 1)) : /* inexact_style == human_floor */ 0) { amt++; if (amt == base && power < sizeof suffixes - 1) { *p = suffixes[power + 1]; *--p = '0'; *--p = '.'; amt = 1; } } do *--p = '0' + (int) (amt % 10); while ((amt /= 10) != 0); return p; } /* The default block size used for output. This number may change in the future as disks get larger. */ #ifndef DEFAULT_BLOCK_SIZE # define DEFAULT_BLOCK_SIZE 1024 #endif static char const *const block_size_args[] = { "human-readable", "si", 0 }; static int const block_size_types[] = { -1024, -1000 }; static int default_block_size (void) { return getenv ("POSIXLY_CORRECT") ? 512 : DEFAULT_BLOCK_SIZE; } static strtol_error humblock (char const *spec, int *block_size) { int i; if (! spec && ! (spec = getenv ("BLOCK_SIZE"))) *block_size = default_block_size (); else if (0 <= (i = ARGMATCH (spec, block_size_args, block_size_types))) *block_size = block_size_types[i]; else { char *ptr; unsigned long val; strtol_error e = xstrtoul (spec, &ptr, 0, &val, "eEgGkKmMpPtTyYzZ0"); if (e != LONGINT_OK) return e; if (*ptr) return LONGINT_INVALID_SUFFIX_CHAR; if ((int) val < 0 || val != (int) val) return LONGINT_OVERFLOW; *block_size = (int) val; } return LONGINT_OK; } void human_block_size (char const *spec, int report_errors, int *block_size) { strtol_error e = humblock (spec, block_size); if (*block_size == 0) { *block_size = default_block_size (); e = LONGINT_INVALID; } if (e != LONGINT_OK && report_errors) fprintf(stderr, "Invalid block size entered\n"); } dcfldd-1.7.1/src/human.h000066400000000000000000000016761410702647300150260ustar00rootroot00000000000000#ifndef HUMAN_H_ # define HUMAN_H_ 1 # if HAVE_CONFIG_H # include # endif # if HAVE_INTTYPES_H # include # endif /* A conservative bound on the maximum length of a human-readable string. The output can be the product of the largest uintmax_t and the largest int, so add their sizes before converting to a bound on digits. */ # define LONGEST_HUMAN_READABLE ((sizeof (uintmax_t) + sizeof (int)) \ * CHAR_BIT / 3) # ifndef PARAMS # if defined PROTOTYPES || (defined __STDC__ && __STDC__) # define PARAMS(Args) Args # else # define PARAMS(Args) () # endif # endif enum human_inexact_style { human_floor = -1, human_round_to_even = 0, human_ceiling = 1 }; char *human_readable PARAMS ((uintmax_t, char *, int, int)); char *human_readable_inexact PARAMS ((uintmax_t, char *, int, int, enum human_inexact_style)); void human_block_size PARAMS ((char const *, int, int *)); #endif /* HUMAN_H_ */ dcfldd-1.7.1/src/log.c000066400000000000000000000061411410702647300144620ustar00rootroot00000000000000/* $Id: log.c,v 1.6 2005/05/15 20:15:28 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright 85, 90, 91, 1995-2001, 2005 Free Software Foundation, Inc. Copyright 2020 David Polverari 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #include "dcfldd.h" #include #include #include #include #include "log.h" #include "hash.h" #include "verify.h" #include #include "hashformat.h" FILE *errlog = NULL; void syscall_error(char *str) { syscall_error_noexit(str); exit(1); } void syscall_error_noexit(char *str) { char *errstr = strerror(errno); fprintf(stderr, "%s:%s: %s\n", program_name, str == NULL ? "" : str, errstr); if (errlog != NULL) fprintf(errlog, "%s:%s: %s\n", program_name, str == NULL ? "" : str, errstr); } void user_error(char *str, ...) { va_list ap; va_start(ap, str); fprintf(stderr, "%s: ", program_name); vfprintf(stderr, str, ap); fprintf(stderr, "\n"); if (errlog != NULL) { fprintf(errlog, "%s: ", program_name); vfprintf(errlog, str, ap); fprintf(errlog, "\n"); } va_end(ap); exit(1); } void log_info(char *str, ...) { va_list ap, ap2; va_start(ap, str); va_copy(ap2, ap); vfprintf(stderr, str, ap); if (errlog != NULL) { vfprintf(errlog, str, ap2); va_end(ap2); } va_end(ap); } void internal_error(char *str) { fprintf(stderr, "%s: internal error: %s\n", program_name, str); if (errlog != NULL) fprintf(errlog, "%s: internal error: %s\n", program_name, str); exit(1); } void log_hashwindow(hashtype_t *htype, off_t wina, off_t winb, size_t bs, char *hash) { print_fmt(hashformat, htype->log, wina, winb, bs, htype->name, hash); } void log_hashtotal(hashtype_t *htype, off_t wina, off_t winb, size_t bs, char *hash) { print_fmt(totalhashformat, htype->log, wina, winb, bs, htype->name, hash); } void log_verifywindow(hashtype_t *htype, off_t wina, off_t winb, int mismatch) { fprintf(htype->log, "%llu - %llu: %s\n", (unsigned long long int) wina, (unsigned long long int) winb, mismatch ? "Mismatch" : "Match"); } void log_verifytotal(hashtype_t *htype, int mismatch) { fprintf(htype->log, "Total: %s\n", mismatch ? "Mismatch" : "Match"); } dcfldd-1.7.1/src/log.h000066400000000000000000000030751410702647300144720ustar00rootroot00000000000000/* $Id: log.h,v 1.5 2005/05/15 20:15:28 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright (C) 85, 90, 91, 1995-2001, 2005 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #ifndef LOG_H #define LOG_H #include "dcfldd.h" #include "hash.h" #include #include #include extern FILE *errlog; extern void syscall_error(char *); extern void syscall_error_noexit(char *); extern void user_error(char *, ...); extern void internal_error(char *); extern void log_info(char *, ...); extern void log_hashwindow(hashtype_t *, off_t, off_t, size_t, char *); extern void log_hashtotal(hashtype_t *, off_t, off_t, size_t, char *); extern void log_verifywindow(hashtype_t *, off_t, off_t, int); extern void log_verifytotal(hashtype_t *, int); #endif /* LOG_H */ dcfldd-1.7.1/src/long-options.c000066400000000000000000000043741410702647300163370ustar00rootroot00000000000000/* Utility to accept --help and --version options as unobtrusively as possible. Copyright (C) 1993, 1994, 1998, 1999, 2000 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by Jim Meyering. */ #if HAVE_CONFIG_H # include #endif #include #include #if HAVE_STDLIB_H # include #endif #include "long-options.h" #include "version-etc.h" #if ENABLE_NLS # include # define _(Text) gettext (Text) #else # define _(Text) Text #endif static struct option const long_options[] = { {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'v'}, {0, 0, 0, 0} }; /* Process long options --help and --version, but only if argc == 2. Be careful not to gobble up `--'. */ void parse_long_options (int argc, char **argv, const char *command_name, const char *package, const char *version, const char *authors, void (*usage_func)()) { int c; int saved_opterr; saved_opterr = opterr; /* Don't print an error message for unrecognized options. */ opterr = 0; if (argc == 2 && (c = getopt_long (argc, argv, "+", long_options, NULL)) != -1) { switch (c) { case 'h': (*usage_func) (0); case 'v': version_etc (stdout, command_name, package, version, authors); exit (0); default: /* Don't process any other long-named options. */ break; } } /* Restore previous value. */ opterr = saved_opterr; /* Reset this to zero so that getopt internals get initialized from the probably-new parameters when/if getopt is called later. */ optind = 0; } dcfldd-1.7.1/src/long-options.h000066400000000000000000000023651410702647300163420ustar00rootroot00000000000000/* long-options.h -- declaration for --help- and --version-handling function. Copyright (C) 1993, 1994, 1998, 1999 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by Jim Meyering. */ #ifndef PARAMS # if defined PROTOTYPES || (defined __STDC__ && __STDC__) # define PARAMS(Args) Args # else # define PARAMS(Args) () # endif #endif void parse_long_options PARAMS ((int _argc, char **_argv, const char *_command_name, const char *_package, const char *_version, const char *_authors, void (*_usage) (int))); dcfldd-1.7.1/src/md5.c000066400000000000000000000240711410702647300143700ustar00rootroot00000000000000/* ********************************************************************** ** md5.c ** ** RSA Data Security, Inc. MD5 Message Digest Algorithm ** ** Created: 2/17/90 RLR ** ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version ** ********************************************************************** */ /* ********************************************************************** ** Copyright (C) 1990, RSA Data Security, Inc. 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 the following line if the md5.h header file is separate -- */ #include "md5.h" /* forward declaration */ static void Transform (); static unsigned char PADDING[64] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* F, G and H are basic MD5 functions: selection, majority, parity */ #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) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define GG(a, b, c, d, x, s, ac) \ {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define HH(a, b, c, d, x, s, ac) \ {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define II(a, b, c, d, x, s, ac) \ {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } void MD5Init (mdContext) MD5_CTX *mdContext; { mdContext->i[0] = mdContext->i[1] = (UINT4)0; /* Load magic initialization constants. */ mdContext->buf[0] = (UINT4)0x67452301; mdContext->buf[1] = (UINT4)0xefcdab89; mdContext->buf[2] = (UINT4)0x98badcfe; mdContext->buf[3] = (UINT4)0x10325476; } void MD5Update (mdContext, inBuf, inLen) MD5_CTX *mdContext; const unsigned char *inBuf; unsigned int inLen; { UINT4 in[16]; int mdi; unsigned int i, ii; /* compute number of bytes mod 64 */ mdi = (int)((mdContext->i[0] >> 3) & 0x3F); /* update number of bits */ if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) mdContext->i[1]++; mdContext->i[0] += ((UINT4)inLen << 3); mdContext->i[1] += ((UINT4)inLen >> 29); while (inLen--) { /* add new character to buffer, increment mdi */ mdContext->in[mdi++] = *inBuf++; /* transform if necessary */ if (mdi == 0x40) { for (i = 0, ii = 0; i < 16; i++, ii += 4) in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | (((UINT4)mdContext->in[ii+2]) << 16) | (((UINT4)mdContext->in[ii+1]) << 8) | ((UINT4)mdContext->in[ii]); Transform (mdContext->buf, in); mdi = 0; } } } void MD5Final (mdContext, buf) MD5_CTX *mdContext; char *buf; { UINT4 in[16]; int mdi; unsigned int i, ii; unsigned int padLen; /* save number of bits */ in[14] = mdContext->i[0]; in[15] = mdContext->i[1]; /* compute number of bytes mod 64 */ mdi = (int)((mdContext->i[0] >> 3) & 0x3F); /* pad out to 56 mod 64 */ padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); MD5Update (mdContext, PADDING, padLen); /* append length in bits and transform */ for (i = 0, ii = 0; i < 14; i++, ii += 4) in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | (((UINT4)mdContext->in[ii+2]) << 16) | (((UINT4)mdContext->in[ii+1]) << 8) | ((UINT4)mdContext->in[ii]); Transform (mdContext->buf, in); /* store buffer in digest */ for (i = 0, ii = 0; i < 4; i++, ii += 4) { mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); mdContext->digest[ii+1] = (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); mdContext->digest[ii+2] = (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); mdContext->digest[ii+3] = (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); } MD5Sprint(mdContext, buf); } /* Print the context to the given buffer (32 digits) */ void MD5Sprint (mdContext, buf) MD5_CTX *mdContext; char *buf; { int i; for (i = 0; i < 16; i++) sprintf (&buf[i*2], "%02x", mdContext->digest[i]); } /* Basic MD5 step. Transform buf based on in. */ static void Transform (buf, in) UINT4 *buf; UINT4 *in; { UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; /* Round 1 */ #define S11 7 #define S12 12 #define S13 17 #define S14 22 FF ( a, b, c, d, in[ 0], S11, 3614090360u); /* 1 */ FF ( d, a, b, c, in[ 1], S12, 3905402710u); /* 2 */ FF ( c, d, a, b, in[ 2], S13, 606105819u); /* 3 */ FF ( b, c, d, a, in[ 3], S14, 3250441966u); /* 4 */ FF ( a, b, c, d, in[ 4], S11, 4118548399u); /* 5 */ FF ( d, a, b, c, in[ 5], S12, 1200080426u); /* 6 */ FF ( c, d, a, b, in[ 6], S13, 2821735955u); /* 7 */ FF ( b, c, d, a, in[ 7], S14, 4249261313u); /* 8 */ FF ( a, b, c, d, in[ 8], S11, 1770035416u); /* 9 */ FF ( d, a, b, c, in[ 9], S12, 2336552879u); /* 10 */ FF ( c, d, a, b, in[10], S13, 4294925233u); /* 11 */ FF ( b, c, d, a, in[11], S14, 2304563134u); /* 12 */ FF ( a, b, c, d, in[12], S11, 1804603682u); /* 13 */ FF ( d, a, b, c, in[13], S12, 4254626195u); /* 14 */ FF ( c, d, a, b, in[14], S13, 2792965006u); /* 15 */ FF ( b, c, d, a, in[15], S14, 1236535329u); /* 16 */ /* Round 2 */ #define S21 5 #define S22 9 #define S23 14 #define S24 20 GG ( a, b, c, d, in[ 1], S21, 4129170786u); /* 17 */ GG ( d, a, b, c, in[ 6], S22, 3225465664u); /* 18 */ GG ( c, d, a, b, in[11], S23, 643717713u); /* 19 */ GG ( b, c, d, a, in[ 0], S24, 3921069994u); /* 20 */ GG ( a, b, c, d, in[ 5], S21, 3593408605u); /* 21 */ GG ( d, a, b, c, in[10], S22, 38016083u); /* 22 */ GG ( c, d, a, b, in[15], S23, 3634488961u); /* 23 */ GG ( b, c, d, a, in[ 4], S24, 3889429448u); /* 24 */ GG ( a, b, c, d, in[ 9], S21, 568446438u); /* 25 */ GG ( d, a, b, c, in[14], S22, 3275163606u); /* 26 */ GG ( c, d, a, b, in[ 3], S23, 4107603335u); /* 27 */ GG ( b, c, d, a, in[ 8], S24, 1163531501u); /* 28 */ GG ( a, b, c, d, in[13], S21, 2850285829u); /* 29 */ GG ( d, a, b, c, in[ 2], S22, 4243563512u); /* 30 */ GG ( c, d, a, b, in[ 7], S23, 1735328473u); /* 31 */ GG ( b, c, d, a, in[12], S24, 2368359562u); /* 32 */ /* Round 3 */ #define S31 4 #define S32 11 #define S33 16 #define S34 23 HH ( a, b, c, d, in[ 5], S31, 4294588738u); /* 33 */ HH ( d, a, b, c, in[ 8], S32, 2272392833u); /* 34 */ HH ( c, d, a, b, in[11], S33, 1839030562u); /* 35 */ HH ( b, c, d, a, in[14], S34, 4259657740u); /* 36 */ HH ( a, b, c, d, in[ 1], S31, 2763975236u); /* 37 */ HH ( d, a, b, c, in[ 4], S32, 1272893353u); /* 38 */ HH ( c, d, a, b, in[ 7], S33, 4139469664u); /* 39 */ HH ( b, c, d, a, in[10], S34, 3200236656u); /* 40 */ HH ( a, b, c, d, in[13], S31, 681279174u); /* 41 */ HH ( d, a, b, c, in[ 0], S32, 3936430074u); /* 42 */ HH ( c, d, a, b, in[ 3], S33, 3572445317u); /* 43 */ HH ( b, c, d, a, in[ 6], S34, 76029189u); /* 44 */ HH ( a, b, c, d, in[ 9], S31, 3654602809u); /* 45 */ HH ( d, a, b, c, in[12], S32, 3873151461u); /* 46 */ HH ( c, d, a, b, in[15], S33, 530742520u); /* 47 */ HH ( b, c, d, a, in[ 2], S34, 3299628645u); /* 48 */ /* Round 4 */ #define S41 6 #define S42 10 #define S43 15 #define S44 21 II ( a, b, c, d, in[ 0], S41, 4096336452u); /* 49 */ II ( d, a, b, c, in[ 7], S42, 1126891415u); /* 50 */ II ( c, d, a, b, in[14], S43, 2878612391u); /* 51 */ II ( b, c, d, a, in[ 5], S44, 4237533241u); /* 52 */ II ( a, b, c, d, in[12], S41, 1700485571u); /* 53 */ II ( d, a, b, c, in[ 3], S42, 2399980690u); /* 54 */ II ( c, d, a, b, in[10], S43, 4293915773u); /* 55 */ II ( b, c, d, a, in[ 1], S44, 2240044497u); /* 56 */ II ( a, b, c, d, in[ 8], S41, 1873313359u); /* 57 */ II ( d, a, b, c, in[15], S42, 4264355552u); /* 58 */ II ( c, d, a, b, in[ 6], S43, 2734768916u); /* 59 */ II ( b, c, d, a, in[13], S44, 1309151649u); /* 60 */ II ( a, b, c, d, in[ 4], S41, 4149444226u); /* 61 */ II ( d, a, b, c, in[11], S42, 3174756917u); /* 62 */ II ( c, d, a, b, in[ 2], S43, 718787259u); /* 63 */ II ( b, c, d, a, in[ 9], S44, 3951481745u); /* 64 */ buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } dcfldd-1.7.1/src/md5.h000066400000000000000000000061661410702647300144020ustar00rootroot00000000000000/* ********************************************************************** ** md5.h -- Header file for implementation of MD5 ** ** RSA Data Security, Inc. MD5 Message Digest Algorithm ** ** Created: 2/17/90 RLR ** ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** ** Revised (for MD5): RLR 4/27/91 ** ** -- G modified to have y&~z instead of y&z ** ** -- FF, GG, HH modified to add in last register done ** ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 ** ** -- distinct additive constant for each step ** ** -- round 4 added, working mod 7 ** ********************************************************************** */ /* ********************************************************************** ** Copyright (C) 1990, RSA Data Security, Inc. 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. ** ********************************************************************** */ #ifndef MD5_H #define MD5_H #if HAVE_INTTYPES_H # include #else # if HAVE_STDINT_H # include # endif #endif #include "hash.h" /* typedef a 32 bit type */ typedef uint32_t UINT4; #define MD5_DIGEST_STRING_LENGTH 32 /* Data structure for MD5 (Message Digest) computation */ typedef struct { UINT4 i[2]; /* number of _bits_ handled mod 2^64 */ UINT4 buf[4]; /* scratch buffer */ unsigned char in[64]; /* input buffer */ unsigned char digest[16]; /* actual digest after MD5Final call */ } MD5_CTX; void MD5Init (MD5_CTX *); void MD5Update (MD5_CTX *, const unsigned char *, unsigned int); void MD5Final (MD5_CTX *, char *); void MD5Sprint (MD5_CTX *, char *); #endif /* MD5_H */ dcfldd-1.7.1/src/output.c000066400000000000000000000115421410702647300152420ustar00rootroot00000000000000/* $Id: output.c,v 1.5 2005/06/15 14:33:04 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright 85, 90, 91, 1995-2001, 2005 Free Software Foundation, Inc. Copyright 2008 David Loveall 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #include "dcfldd.h" #include "output.h" #include "full-write.h" #include "config.h" #include #include #include #include #include #include #include #include "split.h" #include "log.h" #include "util.h" outputlist_t *outputlist = NULL; void open_output(char *filename) { mode_t perms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; int fd; int opts = (O_CREAT | (seek_records || (conversions_mask & C_NOTRUNC) ? 0 : O_TRUNC)); /* Open the output file with *read* access only if we might need to read to satisfy a `seek=' request. If we can't read the file, go ahead with write-only access; it might work. */ if ((! seek_records || (fd = open(filename, O_RDWR | opts, perms)) < 0) && (fd = open(filename, O_WRONLY | opts, perms)) < 0) { syscall_error(filename); } #if HAVE_FTRUNCATE if (seek_records != 0 && !(conversions_mask & C_NOTRUNC)) { struct stat statbuf; off_t o = seek_records * output_blocksize; if (o / output_blocksize != seek_records) syscall_error(filename); if (fstat(fd, &statbuf) != 0) syscall_error(filename); /* Complain only when ftruncate fails on a regular file, a directory, or a shared memory object, as the 2000-08 POSIX draft specifies ftruncate's behavior only for these file types. For example, do not complain when Linux 2.4 ftruncate fails on /dev/fd0. */ if (ftruncate(fd, o) != 0 && (S_ISREG(statbuf.st_mode) || S_ISDIR(statbuf.st_mode) || S_TYPEISSHM(&statbuf))) { char buf[LONGEST_HUMAN_READABLE + 1]; log_info("%s: %s: advancing past %s bytes in output file %s", program_name, strerror(errno), human_readable(o, buf, 1, 1), filename); } } #endif /* HAVE_FTRUNCATE */ outputlist_add(SINGLE_FILE, fd); } void open_output_pipe(char *command) { FILE *stream; stream = popen(command, "w"); if (stream == NULL) syscall_error(command); outputlist_add(STREAM, stream); } void outputlist_add(outputtype_t type, ...) { va_list ap; outputlist_t *ptr; split_t *split; va_start(ap, type); /* forward to the last struct in outputlist */ for (ptr = outputlist; ptr != NULL && ptr->next != NULL; ptr = ptr->next) ; if (ptr == NULL) outputlist = ptr = malloc(sizeof (*ptr)); else { ptr->next = malloc(sizeof (*ptr)); ptr = ptr->next; } ptr->next = NULL; ptr->type = type; switch (type) { case SINGLE_FILE: ptr->data.fd = va_arg(ap, int); break; case STREAM: ptr->type = SINGLE_FILE; ptr->stream = va_arg(ap, FILE *); ptr->data.fd = fileno(ptr->stream); break; case SPLIT_FILE: split = malloc(sizeof *split); split->name = strdup(va_arg(ap, char *)); split->format = strdup(va_arg(ap, char *)); split->max_bytes = va_arg(ap, off_t); split->total_bytes = 0; split->curr_bytes = 0; split->currfd = -1; ptr->data.split = split; break; } va_end(ap); } int outputlist_write(const char *buf, size_t len) { outputlist_t *ptr; int nwritten = 0; for (ptr = outputlist; ptr != NULL; ptr = ptr->next) { nwritten = 0; switch (ptr->type) { case SINGLE_FILE: nwritten = full_write(ptr->data.fd, buf, len); break; case SPLIT_FILE: nwritten = split_write(ptr->data.split, buf, len); break; } if (nwritten < len) break; } return nwritten; } dcfldd-1.7.1/src/output.h000066400000000000000000000031621410702647300152460ustar00rootroot00000000000000/* $Id: output.h,v 1.4 2005/05/15 20:15:28 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright 85, 90, 91, 1995-2001, 2005 Free Software Foundation, Inc. Copyright 2008 David Loveall 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #ifndef OUTPUT_H #define OUTPUT_H #include "dcfldd.h" #include #include "split.h" typedef enum { NONE, SINGLE_FILE, SPLIT_FILE, STREAM } outputtype_t; typedef struct outputlist_s { struct outputlist_s *next; outputtype_t type; FILE *stream; union { int fd; split_t *split; } data; } outputlist_t; extern outputlist_t *outputlist; extern void open_output(char *); extern void open_output_pipe(char *); extern void outputlist_add(outputtype_t, ...); extern int outputlist_write(const char *, size_t); #endif /* OUTPUT_H */ dcfldd-1.7.1/src/pathmax.h000066400000000000000000000033501410702647300153470ustar00rootroot00000000000000/* Define PATH_MAX somehow. Requires sys/types.h. Copyright (C) 1992, 1999 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _PATHMAX_H # define _PATHMAX_H # ifdef HAVE_UNISTD_H # include # endif /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define PATH_MAX but might cause redefinition warnings when sys/param.h is later included (as on MORE/BSD 4.3). */ # if defined(_POSIX_VERSION) || (defined(HAVE_LIMITS_H) && !defined(__GNUC__)) # include # endif # ifndef _POSIX_PATH_MAX # define _POSIX_PATH_MAX 255 # endif # if !defined(PATH_MAX) && defined(_PC_PATH_MAX) # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 \ : pathconf ("/", _PC_PATH_MAX)) # endif /* Don't include sys/param.h if it already has been. */ # if defined(HAVE_SYS_PARAM_H) && !defined(PATH_MAX) && !defined(MAXPATHLEN) # include # endif # if !defined(PATH_MAX) && defined(MAXPATHLEN) # define PATH_MAX MAXPATHLEN # endif # ifndef PATH_MAX # define PATH_MAX _POSIX_PATH_MAX # endif #endif /* _PATHMAX_H */ dcfldd-1.7.1/src/pattern.c000066400000000000000000000035531410702647300153620ustar00rootroot00000000000000/* $Id: pattern.c,v 1.3 2005/05/13 18:52:06 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright (C) 85, 90, 91, 1995-2001, 2005 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #include "dcfldd.h" #include /* Pattern to be written out */ char *pattern; size_t pattern_len; int input_from_pattern; char *make_pattern(char *pattern) { size_t plen, numbytes, i; char *buffer; plen = strlen(pattern); if (plen == 0 || plen % 2 != 0) return NULL; numbytes = plen / 2; buffer = malloc(numbytes); for (i = 0; i < numbytes; i++) { char tmpstring[3]; int byteval; strncpy(tmpstring, &pattern[i*2], 2); tmpstring[2] = '\0'; byteval = hex2char(tmpstring); if (byteval == -1) { free(buffer); return NULL; } buffer[i] = (char)byteval; } pattern_len = numbytes; return buffer; } void replicate_pattern(char *pattern, char *buffer, size_t size) { size_t i; for (i = 0; i < size; i++) buffer[i] = pattern[i % pattern_len]; } dcfldd-1.7.1/src/pattern.h000066400000000000000000000023601410702647300153620ustar00rootroot00000000000000/* $Id: pattern.h,v 1.3 2005/05/13 18:52:06 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright (C) 85, 90, 91, 1995-2001, 2005 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #ifndef PATTERN_H #define PATTERN_H #include "dcfldd.h" #include extern char *pattern; extern size_t pattern_len; extern int input_from_pattern; extern char *make_pattern(char *); extern void replicate_pattern(char *, char *, size_t); #endif /* PATTERN_H */ dcfldd-1.7.1/src/safe-read.c000066400000000000000000000027241410702647300155330ustar00rootroot00000000000000/* safe-read.c -- an interface to read that retries after interrupts Copyright (C) 1993, 1994, 1998 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #if HAVE_CONFIG_H # include #endif #include #if HAVE_UNISTD_H # include #endif #include #ifndef errno extern int errno; #endif #include "safe-read.h" /* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted. Return the actual number of bytes read, zero for EOF, or negative for an error. */ ssize_t safe_read (int desc, void *ptr, size_t len) { ssize_t n_chars; if (len <= 0) return len; #ifdef EINTR do { n_chars = read (desc, ptr, len); } while (n_chars < 0 && errno == EINTR); #else n_chars = read (desc, ptr, len); #endif return n_chars; } dcfldd-1.7.1/src/safe-read.h000066400000000000000000000003241410702647300155320ustar00rootroot00000000000000#ifndef PARAMS # if defined PROTOTYPES || (defined __STDC__ && __STDC__) # define PARAMS(Args) Args # else # define PARAMS(Args) () # endif #endif ssize_t safe_read PARAMS ((int desc, void *ptr, size_t len)); dcfldd-1.7.1/src/sha1.c000066400000000000000000000362271410702647300145450ustar00rootroot00000000000000/*- * Copyright (c) 2001-2003 Allan Saddi * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY ALLAN SADDI AND HIS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL ALLAN SADDI OR HIS CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * $Id: sha1.c,v 1.3 2005/05/13 18:52:06 harbourn Exp $ */ /* * Define WORDS_BIGENDIAN if compiling on a big-endian architecture. * * Define SHA1_TEST to test the implementation using the NIST's * sample messages. The output should be: * * a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d * 84983e44 1c3bd26e baae4aa1 f95129e5 e54670f1 * 34aa973c d4c4daa4 f61eeb2b dbad2731 6534016f */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #if HAVE_INTTYPES_H # include #else # if HAVE_STDINT_H # include # endif #endif #include #include "sha1.h" #ifndef lint static const char rcsid[] = "$Id: sha1.c,v 1.3 2005/05/13 18:52:06 harbourn Exp $"; #endif /* !lint */ #define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) #define ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) #define F_0_19(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) #define F_20_39(x, y, z) ((x) ^ (y) ^ (z)) #define F_40_59(x, y, z) (((x) & ((y) | (z))) | ((y) & (z))) #define F_60_79(x, y, z) ((x) ^ (y) ^ (z)) #define DO_ROUND(F, K) { \ temp = ROTL(a, 5) + F(b, c, d) + e + *(W++) + K; \ e = d; \ d = c; \ c = ROTL(b, 30); \ b = a; \ a = temp; \ } #define K_0_19 0x5a827999L #define K_20_39 0x6ed9eba1L #define K_40_59 0x8f1bbcdcL #define K_60_79 0xca62c1d6L #ifndef RUNTIME_ENDIAN #ifdef WORDS_BIGENDIAN #define BYTESWAP(x) (x) #define BYTESWAP64(x) (x) #else /* WORDS_BIGENDIAN */ #define BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00L) | \ (ROTL((x), 8) & 0x00ff00ffL)) #define BYTESWAP64(x) _byteswap64(x) static inline uint64_t _byteswap64(uint64_t x) { uint32_t a = x >> 32; uint32_t b = (uint32_t) x; return ((uint64_t) BYTESWAP(b) << 32) | (uint64_t) BYTESWAP(a); } #endif /* WORDS_BIGENDIAN */ #else /* !RUNTIME_ENDIAN */ #define BYTESWAP(x) _byteswap(sc->littleEndian, x) #define BYTESWAP64(x) _byteswap64(sc->littleEndian, x) #define _BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00L) | \ (ROTL((x), 8) & 0x00ff00ffL)) #define _BYTESWAP64(x) __byteswap64(x) static inline uint64_t __byteswap64(uint64_t x) { uint32_t a = x >> 32; uint32_t b = (uint32_t) x; return ((uint64_t) _BYTESWAP(b) << 32) | (uint64_t) _BYTESWAP(a); } static inline uint32_t _byteswap(int littleEndian, uint32_t x) { if (!littleEndian) return x; else return _BYTESWAP(x); } static inline uint64_t _byteswap64(int littleEndian, uint64_t x) { if (!littleEndian) return x; else return _BYTESWAP64(x); } static inline void setEndian(int *littleEndianp) { union { uint32_t w; uint8_t b[4]; } endian; endian.w = 1L; *littleEndianp = endian.b[0] != 0; } #endif /* !RUNTIME_ENDIAN */ static const uint8_t padding[64] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; void SHA1Init (SHA1Context *sc) { #ifdef RUNTIME_ENDIAN setEndian (&sc->littleEndian); #endif /* RUNTIME_ENDIAN */ sc->totalLength = 0LL; sc->hash[0] = 0x67452301L; sc->hash[1] = 0xefcdab89L; sc->hash[2] = 0x98badcfeL; sc->hash[3] = 0x10325476L; sc->hash[4] = 0xc3d2e1f0L; sc->bufferLength = 0L; } static void burnStack (int size) { char buf[128]; memset (buf, 0, sizeof (buf)); size -= sizeof (buf); if (size > 0) burnStack (size); } static void SHA1Guts (SHA1Context *sc, const uint32_t *cbuf) { uint32_t buf[80]; uint32_t *W, *W3, *W8, *W14, *W16; uint32_t a, b, c, d, e, temp; int i; W = buf; for (i = 15; i >= 0; i--) { *(W++) = BYTESWAP(*cbuf); cbuf++; } W16 = &buf[0]; W14 = &buf[2]; W8 = &buf[8]; W3 = &buf[13]; for (i = 63; i >= 0; i--) { *W = *(W3++) ^ *(W8++) ^ *(W14++) ^ *(W16++); *W = ROTL(*W, 1); W++; } a = sc->hash[0]; b = sc->hash[1]; c = sc->hash[2]; d = sc->hash[3]; e = sc->hash[4]; W = buf; #ifndef SHA1_UNROLL #define SHA1_UNROLL 20 #endif /* !SHA1_UNROLL */ #if SHA1_UNROLL == 1 for (i = 19; i >= 0; i--) DO_ROUND(F_0_19, K_0_19); for (i = 19; i >= 0; i--) DO_ROUND(F_20_39, K_20_39); for (i = 19; i >= 0; i--) DO_ROUND(F_40_59, K_40_59); for (i = 19; i >= 0; i--) DO_ROUND(F_60_79, K_60_79); #elif SHA1_UNROLL == 2 for (i = 9; i >= 0; i--) { DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); } for (i = 9; i >= 0; i--) { DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); } for (i = 9; i >= 0; i--) { DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); } for (i = 9; i >= 0; i--) { DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); } #elif SHA1_UNROLL == 4 for (i = 4; i >= 0; i--) { DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); } for (i = 4; i >= 0; i--) { DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); } for (i = 4; i >= 0; i--) { DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); } for (i = 4; i >= 0; i--) { DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); } #elif SHA1_UNROLL == 5 for (i = 3; i >= 0; i--) { DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); } for (i = 3; i >= 0; i--) { DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); } for (i = 3; i >= 0; i--) { DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); } for (i = 3; i >= 0; i--) { DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); } #elif SHA1_UNROLL == 10 for (i = 1; i >= 0; i--) { DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); } for (i = 1; i >= 0; i--) { DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); } for (i = 1; i >= 0; i--) { DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); } for (i = 1; i >= 0; i--) { DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); } #elif SHA1_UNROLL == 20 DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_0_19, K_0_19); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_20_39, K_20_39); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_40_59, K_40_59); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); DO_ROUND(F_60_79, K_60_79); #else /* SHA1_UNROLL */ #error SHA1_UNROLL must be 1, 2, 4, 5, 10 or 20! #endif sc->hash[0] += a; sc->hash[1] += b; sc->hash[2] += c; sc->hash[3] += d; sc->hash[4] += e; } void SHA1Update (SHA1Context *sc, const void *vdata, uint32_t len) { const uint8_t *data = vdata; uint32_t bufferBytesLeft; uint32_t bytesToCopy; int needBurn = 0; #ifdef SHA1_FAST_COPY if (sc->bufferLength) { bufferBytesLeft = 64L - sc->bufferLength; bytesToCopy = bufferBytesLeft; if (bytesToCopy > len) bytesToCopy = len; memcpy (&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy); sc->totalLength += bytesToCopy * 8L; sc->bufferLength += bytesToCopy; data += bytesToCopy; len -= bytesToCopy; if (sc->bufferLength == 64L) { SHA1Guts (sc, sc->buffer.words); needBurn = 1; sc->bufferLength = 0L; } } while (len > 63) { sc->totalLength += 512L; SHA1Guts (sc, data); needBurn = 1; data += 64L; len -= 64L; } if (len) { memcpy (&sc->buffer.bytes[sc->bufferLength], data, len); sc->totalLength += len * 8L; sc->bufferLength += len; } #else /* SHA1_FAST_COPY */ while (len) { bufferBytesLeft = 64L - sc->bufferLength; bytesToCopy = bufferBytesLeft; if (bytesToCopy > len) bytesToCopy = len; memcpy (&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy); sc->totalLength += bytesToCopy * 8L; sc->bufferLength += bytesToCopy; data += bytesToCopy; len -= bytesToCopy; if (sc->bufferLength == 64L) { SHA1Guts (sc, sc->buffer.words); needBurn = 1; sc->bufferLength = 0L; } } #endif /* SHA1_FAST_COPY */ if (needBurn) burnStack (sizeof (uint32_t[86]) + sizeof (uint32_t *[5]) + sizeof (int)); } void SHA1Final (SHA1Context *sc, uint8_t hash[SHA1_HASH_SIZE]) { uint32_t bytesToPad; uint64_t lengthPad; int i; bytesToPad = 120L - sc->bufferLength; if (bytesToPad > 64L) bytesToPad -= 64L; lengthPad = BYTESWAP64(sc->totalLength); SHA1Update (sc, padding, bytesToPad); SHA1Update (sc, &lengthPad, 8L); if (hash) { for (i = 0; i < SHA1_HASH_WORDS; i++) { #ifdef SHA1_FAST_COPY *((uint32_t *) hash) = BYTESWAP(sc->hash[i]); #else /* SHA1_FAST_COPY */ hash[0] = (uint8_t) (sc->hash[i] >> 24); hash[1] = (uint8_t) (sc->hash[i] >> 16); hash[2] = (uint8_t) (sc->hash[i] >> 8); hash[3] = (uint8_t) sc->hash[i]; #endif /* SHA1_FAST_COPY */ hash += 4; } } } void SHA1End (SHA1Context *sc, char *hashstrbuf) { static const char *sha1_hex_digits = "0123456789abcdef"; uint8_t digest[SHA1_HASH_SIZE], *d = digest; int i; /* Sanity check: */ if (sc == NULL) return; if (hashstrbuf == NULL) return; SHA1Final(sc, digest); for (i = 0; i < SHA1_HASH_SIZE; i++) { *hashstrbuf++ = sha1_hex_digits[(*d & 0xf0) >> 4]; *hashstrbuf++ = sha1_hex_digits[(*d & 0x0f)]; d++; } *hashstrbuf = '\0'; } #ifdef SHA1_TEST #include #include #include int main (int argc, char *argv[]) { SHA1Context foo; uint8_t hash[SHA1_HASH_SIZE]; char buf[1000]; int i; SHA1Init (&foo); SHA1Update (&foo, "abc", 3); SHA1Final (&foo, hash); for (i = 0; i < SHA1_HASH_SIZE;) { printf ("%02x", hash[i++]); if (!(i % 4)) printf (" "); } printf ("\n"); SHA1Init (&foo); SHA1Update (&foo, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56); SHA1Final (&foo, hash); for (i = 0; i < SHA1_HASH_SIZE;) { printf ("%02x", hash[i++]); if (!(i % 4)) printf (" "); } printf ("\n"); SHA1Init (&foo); memset (buf, 'a', sizeof (buf)); for (i = 0; i < 1000; i++) SHA1Update (&foo, buf, sizeof (buf)); SHA1Final (&foo, hash); for (i = 0; i < SHA1_HASH_SIZE;) { printf ("%02x", hash[i++]); if (!(i % 4)) printf (" "); } printf ("\n"); exit (0); } #endif /* SHA1_TEST */ dcfldd-1.7.1/src/sha1.h000066400000000000000000000043771410702647300145530ustar00rootroot00000000000000/*- * Copyright (c) 2001-2003 Allan Saddi * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY ALLAN SADDI AND HIS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL ALLAN SADDI OR HIS CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * $Id: sha1.h,v 1.3 2005/05/13 18:52:06 harbourn Exp $ */ #ifndef _SHA1_H #define _SHA1_H #if HAVE_INTTYPES_H # include #else # if HAVE_STDINT_H # include # endif #endif #define SHA1_HASH_SIZE 20 #define SHA1_DIGEST_STRING_LENGTH 40 /* Hash size in 32-bit words */ #define SHA1_HASH_WORDS 5 struct _SHA1Context { uint64_t totalLength; uint32_t hash[SHA1_HASH_WORDS]; uint32_t bufferLength; union { uint32_t words[16]; uint8_t bytes[64]; } buffer; #ifdef RUNTIME_ENDIAN int littleEndian; #endif /* RUNTIME_ENDIAN */ }; typedef struct _SHA1Context SHA1Context; #ifdef __cplusplus extern "C" { #endif void SHA1Init (SHA1Context *sc); void SHA1Update (SHA1Context *sc, const void *data, uint32_t len); void SHA1Final (SHA1Context *sc, uint8_t hash[SHA1_HASH_SIZE]); void SHA1End (SHA1Context *sc, char *hashstrbuf); #ifdef __cplusplus } #endif #endif /* _SHA1_H */ dcfldd-1.7.1/src/sha2.c000066400000000000000000000764471410702647300145560ustar00rootroot00000000000000/* * FILE: sha2.c * AUTHOR: Aaron D. Gifford * * Copyright (c) 2000-2001, Aaron D. Gifford * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: sha2.c,v 1.3 2005/05/13 18:52:06 harbourn Exp $ */ #include /* memcpy()/memset() or bcopy()/bzero() */ #include /* assert() */ #include "sha2.h" /* * ASSERT NOTE: * Some sanity checking code is included using assert(). On my FreeBSD * system, this additional code can be removed by compiling with NDEBUG * defined. Check your own systems manpage on assert() to see how to * compile WITHOUT the sanity checking code on your system. * * UNROLLED TRANSFORM LOOP NOTE: * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform * loop version for the hash transform rounds (defined using macros * later in this file). Either define on the command line, for example: * * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c * * or define below: * * #define SHA2_UNROLL_TRANSFORM * */ /*** SHA-256/384/512 Machine Architecture Definitions *****************/ /* * BYTE_ORDER NOTE: * * Please make sure that your system defines BYTE_ORDER. If your * architecture is little-endian, make sure it also defines * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are * equivilent. * * If your system does not define the above, then you can do so by * hand like this: * * #define LITTLE_ENDIAN 1234 * #define BIG_ENDIAN 4321 * * And for little-endian machines, add: * * #define BYTE_ORDER LITTLE_ENDIAN * * Or for big-endian machines: * * #define BYTE_ORDER BIG_ENDIAN * * The FreeBSD machine this was written on defines BYTE_ORDER * appropriately by including (which in turn includes * where the appropriate definitions are actually * made). */ #if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) #error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN #endif /* * Define the followingsha2_* types to types of the correct length on * the native archtecture. Most BSD systems and Linux define u_intXX_t * types. Machines with very recent ANSI C headers, can use the * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H * during compile or in the sha.h header file. * * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t * will need to define these three typedefs below (and the appropriate * ones in sha.h too) by hand according to their system architecture. * * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t * types and pointing out recent ANSI C support for uintXX_t in inttypes.h. */ #ifdef SHA2_USE_INTTYPES_H typedef uint8_t sha2_byte; /* Exactly 1 byte */ typedef uint32_t sha2_word32; /* Exactly 4 bytes */ typedef uint64_t sha2_word64; /* Exactly 8 bytes */ #else /* SHA2_USE_INTTYPES_H */ typedef u_int8_t sha2_byte; /* Exactly 1 byte */ typedef u_int32_t sha2_word32; /* Exactly 4 bytes */ typedef u_int64_t sha2_word64; /* Exactly 8 bytes */ #endif /* SHA2_USE_INTTYPES_H */ /*** SHA-256/384/512 Various Length Definitions ***********************/ /* NOTE: Most of these are in sha2.h */ #define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) #define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16) #define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) /*** ENDIAN REVERSAL MACROS *******************************************/ #if BYTE_ORDER == LITTLE_ENDIAN #define REVERSE32(w,x) { \ sha2_word32 tmp = (w); \ tmp = (tmp >> 16) | (tmp << 16); \ (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ } #define REVERSE64(w,x) { \ sha2_word64 tmp = (w); \ tmp = (tmp >> 32) | (tmp << 32); \ tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \ ((tmp & 0x00ff00ff00ff00ffULL) << 8); \ (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ ((tmp & 0x0000ffff0000ffffULL) << 16); \ } #endif /* BYTE_ORDER == LITTLE_ENDIAN */ /* * Macro for incrementally adding the unsigned 64-bit integer n to the * unsigned 128-bit integer (represented using a two-element array of * 64-bit words): */ #define ADDINC128(w,n) { \ (w)[0] += (sha2_word64)(n); \ if ((w)[0] < (n)) { \ (w)[1]++; \ } \ } /* * Macros for copying blocks of memory and for zeroing out ranges * of memory. Using these macros makes it easy to switch from * using memset()/memcpy() and using bzero()/bcopy(). * * Please define either SHA2_USE_MEMSET_MEMCPY or define * SHA2_USE_BZERO_BCOPY depending on which function set you * choose to use: */ #if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY) /* Default to memset()/memcpy() if no option is specified */ #define SHA2_USE_MEMSET_MEMCPY 1 #endif #if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY) /* Abort with an error if BOTH options are defined */ #error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both! #endif #ifdef SHA2_USE_MEMSET_MEMCPY #define MEMSET_BZERO(p,l) memset((p), 0, (l)) #define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l)) #endif #ifdef SHA2_USE_BZERO_BCOPY #define MEMSET_BZERO(p,l) bzero((p), (l)) #define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l)) #endif /*** THE SIX LOGICAL FUNCTIONS ****************************************/ /* * Bit shifting and rotation (used by the six SHA-XYZ logical functions: * * NOTE: The naming of R and S appears backwards here (R is a SHIFT and * S is a ROTATION) because the SHA-256/384/512 description document * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this * same "backwards" definition. */ /* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ #define R(b,x) ((x) >> (b)) /* 32-bit Rotate-right (used in SHA-256): */ #define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) /* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ #define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) /* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ #define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) #define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) /* Four of six logical functions used in SHA-256: */ #define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) #define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) #define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) #define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) /* Four of six logical functions used in SHA-384 and SHA-512: */ #define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) #define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) #define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) #define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) /*** INTERNAL FUNCTION PROTOTYPES *************************************/ /* NOTE: These should not be accessed directly from outside this * library -- they are intended for private internal visibility/use * only. */ void SHA512_Last(SHA512_CTX*); void SHA256_Transform(SHA256_CTX*, const sha2_word32*); void SHA512_Transform(SHA512_CTX*, const sha2_word64*); /*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ /* Hash constant words K for SHA-256: */ const static sha2_word32 K256[64] = { 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL }; /* Initial hash value H for SHA-256: */ const static sha2_word32 sha256_initial_hash_value[8] = { 0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL, 0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL }; /* Hash constant words K for SHA-384 and SHA-512: */ const static sha2_word64 K512[80] = { 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL }; /* Initial hash value H for SHA-384 */ const static sha2_word64 sha384_initial_hash_value[8] = { 0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, 0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL, 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL, 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL }; /* Initial hash value H for SHA-512 */ const static sha2_word64 sha512_initial_hash_value[8] = { 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL }; /* * Constant used by SHA256/384/512_End() functions for converting the * digest to a readable hexadecimal character string: */ static const char *sha2_hex_digits = "0123456789abcdef"; /*** SHA-256: *********************************************************/ void SHA256_Init(SHA256_CTX* context) { if (context == (SHA256_CTX*)0) { return; } MEMCPY_BCOPY(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH); MEMSET_BZERO(context->buffer, SHA256_BLOCK_LENGTH); context->bitcount = 0; } #ifdef SHA2_UNROLL_TRANSFORM /* Unrolled SHA-256 round macros: */ #if BYTE_ORDER == LITTLE_ENDIAN #define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ REVERSE32(*data++, W256[j]); \ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ K256[j] + W256[j]; \ (d) += T1; \ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ j++ #else /* BYTE_ORDER == LITTLE_ENDIAN */ #define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ K256[j] + (W256[j] = *data++); \ (d) += T1; \ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ j++ #endif /* BYTE_ORDER == LITTLE_ENDIAN */ #define ROUND256(a,b,c,d,e,f,g,h) \ s0 = W256[(j+1)&0x0f]; \ s0 = sigma0_256(s0); \ s1 = W256[(j+14)&0x0f]; \ s1 = sigma1_256(s1); \ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \ (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ (d) += T1; \ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ j++ void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) { sha2_word32 a, b, c, d, e, f, g, h, s0, s1; sha2_word32 T1, *W256; int j; W256 = (sha2_word32*)context->buffer; /* Initialize registers with the prev. intermediate value */ a = context->state[0]; b = context->state[1]; c = context->state[2]; d = context->state[3]; e = context->state[4]; f = context->state[5]; g = context->state[6]; h = context->state[7]; j = 0; do { /* Rounds 0 to 15 (unrolled): */ ROUND256_0_TO_15(a,b,c,d,e,f,g,h); ROUND256_0_TO_15(h,a,b,c,d,e,f,g); ROUND256_0_TO_15(g,h,a,b,c,d,e,f); ROUND256_0_TO_15(f,g,h,a,b,c,d,e); ROUND256_0_TO_15(e,f,g,h,a,b,c,d); ROUND256_0_TO_15(d,e,f,g,h,a,b,c); ROUND256_0_TO_15(c,d,e,f,g,h,a,b); ROUND256_0_TO_15(b,c,d,e,f,g,h,a); } while (j < 16); /* Now for the remaining rounds to 64: */ do { ROUND256(a,b,c,d,e,f,g,h); ROUND256(h,a,b,c,d,e,f,g); ROUND256(g,h,a,b,c,d,e,f); ROUND256(f,g,h,a,b,c,d,e); ROUND256(e,f,g,h,a,b,c,d); ROUND256(d,e,f,g,h,a,b,c); ROUND256(c,d,e,f,g,h,a,b); ROUND256(b,c,d,e,f,g,h,a); } while (j < 64); /* Compute the current intermediate hash value */ context->state[0] += a; context->state[1] += b; context->state[2] += c; context->state[3] += d; context->state[4] += e; context->state[5] += f; context->state[6] += g; context->state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = 0; } #else /* SHA2_UNROLL_TRANSFORM */ void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) { sha2_word32 a, b, c, d, e, f, g, h, s0, s1; sha2_word32 T1, T2, *W256; int j; W256 = (sha2_word32*)context->buffer; /* Initialize registers with the prev. intermediate value */ a = context->state[0]; b = context->state[1]; c = context->state[2]; d = context->state[3]; e = context->state[4]; f = context->state[5]; g = context->state[6]; h = context->state[7]; j = 0; do { #if BYTE_ORDER == LITTLE_ENDIAN /* Copy data while converting to host byte order */ REVERSE32(*data++,W256[j]); /* Apply the SHA-256 compression function to update a..h */ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; #else /* BYTE_ORDER == LITTLE_ENDIAN */ /* Apply the SHA-256 compression function to update a..h with copy */ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++); #endif /* BYTE_ORDER == LITTLE_ENDIAN */ T2 = Sigma0_256(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 16); do { /* Part of the message block expansion: */ s0 = W256[(j+1)&0x0f]; s0 = sigma0_256(s0); s1 = W256[(j+14)&0x0f]; s1 = sigma1_256(s1); /* Apply the SHA-256 compression function to update a..h */ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); T2 = Sigma0_256(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 64); /* Compute the current intermediate hash value */ context->state[0] += a; context->state[1] += b; context->state[2] += c; context->state[3] += d; context->state[4] += e; context->state[5] += f; context->state[6] += g; context->state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = T2 = 0; } #endif /* SHA2_UNROLL_TRANSFORM */ void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) { unsigned int freespace, usedspace; if (len == 0) { /* Calling with no data is valid - we do nothing */ return; } /* Sanity check: */ assert(context != (SHA256_CTX*)0 && data != (sha2_byte*)0); usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; if (usedspace > 0) { /* Calculate how much free space is available in the buffer */ freespace = SHA256_BLOCK_LENGTH - usedspace; if (len >= freespace) { /* Fill the buffer completely and process it */ MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); context->bitcount += freespace << 3; len -= freespace; data += freespace; SHA256_Transform(context, (sha2_word32*)context->buffer); } else { /* The buffer is not yet full */ MEMCPY_BCOPY(&context->buffer[usedspace], data, len); context->bitcount += len << 3; /* Clean up: */ usedspace = freespace = 0; return; } } while (len >= SHA256_BLOCK_LENGTH) { /* Process as many complete blocks as we can */ SHA256_Transform(context, (sha2_word32*)data); context->bitcount += SHA256_BLOCK_LENGTH << 3; len -= SHA256_BLOCK_LENGTH; data += SHA256_BLOCK_LENGTH; } if (len > 0) { /* There's left-overs, so save 'em */ MEMCPY_BCOPY(context->buffer, data, len); context->bitcount += len << 3; } /* Clean up: */ usedspace = freespace = 0; } void SHA256_Final(SHA256_CTX* context, sha2_byte digest[]) { sha2_word32 *d = (sha2_word32*)digest; unsigned int usedspace; /* Sanity check: */ assert(context != (SHA256_CTX*)0); /* If no digest buffer is passed, we don't bother doing this: */ if (digest != (sha2_byte*)0) { usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; #if BYTE_ORDER == LITTLE_ENDIAN /* Convert FROM host byte order */ REVERSE64(context->bitcount,context->bitcount); #endif if (usedspace > 0) { /* Begin padding with a 1 bit: */ context->buffer[usedspace++] = 0x80; if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { /* Set-up for the last transform: */ MEMSET_BZERO(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace); } else { if (usedspace < SHA256_BLOCK_LENGTH) { MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace); } /* Do second-to-last transform: */ SHA256_Transform(context, (sha2_word32*)context->buffer); /* And set-up for the last transform: */ MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH); } } else { /* Set-up for the last transform: */ MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH); /* Begin padding with a 1 bit: */ *context->buffer = 0x80; } /* Set the bit count: */ *(sha2_word64*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount; /* Final transform: */ SHA256_Transform(context, (sha2_word32*)context->buffer); #if BYTE_ORDER == LITTLE_ENDIAN { /* Convert TO host byte order */ int j; for (j = 0; j < 8; j++) { REVERSE32(context->state[j],context->state[j]); *d++ = context->state[j]; } } #else MEMCPY_BCOPY(d, context->state, SHA256_DIGEST_LENGTH); #endif } /* Clean up state data: */ MEMSET_BZERO(context, sizeof(context)); usedspace = 0; } char *SHA256_End(SHA256_CTX* context, char buffer[]) { sha2_byte digest[SHA256_DIGEST_LENGTH], *d = digest; int i; /* Sanity check: */ assert(context != (SHA256_CTX*)0); if (buffer != (char*)0) { SHA256_Final(context, digest); for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; *buffer++ = sha2_hex_digits[*d & 0x0f]; d++; } *buffer = (char)0; } else { MEMSET_BZERO(context, sizeof(context)); } MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH); return buffer; } char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) { SHA256_CTX context; SHA256_Init(&context); SHA256_Update(&context, data, len); return SHA256_End(&context, digest); } /*** SHA-512: *********************************************************/ void SHA512_Init(SHA512_CTX* context) { if (context == (SHA512_CTX*)0) { return; } MEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH); MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH); context->bitcount[0] = context->bitcount[1] = 0; } #ifdef SHA2_UNROLL_TRANSFORM /* Unrolled SHA-512 round macros: */ #if BYTE_ORDER == LITTLE_ENDIAN #define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ REVERSE64(*data++, W512[j]); \ T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ K512[j] + W512[j]; \ (d) += T1, \ (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \ j++ #else /* BYTE_ORDER == LITTLE_ENDIAN */ #define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ K512[j] + (W512[j] = *data++); \ (d) += T1; \ (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ j++ #endif /* BYTE_ORDER == LITTLE_ENDIAN */ #define ROUND512(a,b,c,d,e,f,g,h) \ s0 = W512[(j+1)&0x0f]; \ s0 = sigma0_512(s0); \ s1 = W512[(j+14)&0x0f]; \ s1 = sigma1_512(s1); \ T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \ (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ (d) += T1; \ (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ j++ void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) { sha2_word64 a, b, c, d, e, f, g, h, s0, s1; sha2_word64 T1, *W512 = (sha2_word64*)context->buffer; int j; /* Initialize registers with the prev. intermediate value */ a = context->state[0]; b = context->state[1]; c = context->state[2]; d = context->state[3]; e = context->state[4]; f = context->state[5]; g = context->state[6]; h = context->state[7]; j = 0; do { ROUND512_0_TO_15(a,b,c,d,e,f,g,h); ROUND512_0_TO_15(h,a,b,c,d,e,f,g); ROUND512_0_TO_15(g,h,a,b,c,d,e,f); ROUND512_0_TO_15(f,g,h,a,b,c,d,e); ROUND512_0_TO_15(e,f,g,h,a,b,c,d); ROUND512_0_TO_15(d,e,f,g,h,a,b,c); ROUND512_0_TO_15(c,d,e,f,g,h,a,b); ROUND512_0_TO_15(b,c,d,e,f,g,h,a); } while (j < 16); /* Now for the remaining rounds up to 79: */ do { ROUND512(a,b,c,d,e,f,g,h); ROUND512(h,a,b,c,d,e,f,g); ROUND512(g,h,a,b,c,d,e,f); ROUND512(f,g,h,a,b,c,d,e); ROUND512(e,f,g,h,a,b,c,d); ROUND512(d,e,f,g,h,a,b,c); ROUND512(c,d,e,f,g,h,a,b); ROUND512(b,c,d,e,f,g,h,a); } while (j < 80); /* Compute the current intermediate hash value */ context->state[0] += a; context->state[1] += b; context->state[2] += c; context->state[3] += d; context->state[4] += e; context->state[5] += f; context->state[6] += g; context->state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = 0; } #else /* SHA2_UNROLL_TRANSFORM */ void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) { sha2_word64 a, b, c, d, e, f, g, h, s0, s1; sha2_word64 T1, T2, *W512 = (sha2_word64*)context->buffer; int j; /* Initialize registers with the prev. intermediate value */ a = context->state[0]; b = context->state[1]; c = context->state[2]; d = context->state[3]; e = context->state[4]; f = context->state[5]; g = context->state[6]; h = context->state[7]; j = 0; do { #if BYTE_ORDER == LITTLE_ENDIAN /* Convert TO host byte order */ REVERSE64(*data++, W512[j]); /* Apply the SHA-512 compression function to update a..h */ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; #else /* BYTE_ORDER == LITTLE_ENDIAN */ /* Apply the SHA-512 compression function to update a..h with copy */ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++); #endif /* BYTE_ORDER == LITTLE_ENDIAN */ T2 = Sigma0_512(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 16); do { /* Part of the message block expansion: */ s0 = W512[(j+1)&0x0f]; s0 = sigma0_512(s0); s1 = W512[(j+14)&0x0f]; s1 = sigma1_512(s1); /* Apply the SHA-512 compression function to update a..h */ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); T2 = Sigma0_512(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; j++; } while (j < 80); /* Compute the current intermediate hash value */ context->state[0] += a; context->state[1] += b; context->state[2] += c; context->state[3] += d; context->state[4] += e; context->state[5] += f; context->state[6] += g; context->state[7] += h; /* Clean up */ a = b = c = d = e = f = g = h = T1 = T2 = 0; } #endif /* SHA2_UNROLL_TRANSFORM */ void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) { unsigned int freespace, usedspace; if (len == 0) { /* Calling with no data is valid - we do nothing */ return; } /* Sanity check: */ assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0); usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; if (usedspace > 0) { /* Calculate how much free space is available in the buffer */ freespace = SHA512_BLOCK_LENGTH - usedspace; if (len >= freespace) { /* Fill the buffer completely and process it */ MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); ADDINC128(context->bitcount, freespace << 3); len -= freespace; data += freespace; SHA512_Transform(context, (sha2_word64*)context->buffer); } else { /* The buffer is not yet full */ MEMCPY_BCOPY(&context->buffer[usedspace], data, len); ADDINC128(context->bitcount, len << 3); /* Clean up: */ usedspace = freespace = 0; return; } } while (len >= SHA512_BLOCK_LENGTH) { /* Process as many complete blocks as we can */ SHA512_Transform(context, (sha2_word64*)data); ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3); len -= SHA512_BLOCK_LENGTH; data += SHA512_BLOCK_LENGTH; } if (len > 0) { /* There's left-overs, so save 'em */ MEMCPY_BCOPY(context->buffer, data, len); ADDINC128(context->bitcount, len << 3); } /* Clean up: */ usedspace = freespace = 0; } void SHA512_Last(SHA512_CTX* context) { unsigned int usedspace; usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; #if BYTE_ORDER == LITTLE_ENDIAN /* Convert FROM host byte order */ REVERSE64(context->bitcount[0],context->bitcount[0]); REVERSE64(context->bitcount[1],context->bitcount[1]); #endif if (usedspace > 0) { /* Begin padding with a 1 bit: */ context->buffer[usedspace++] = 0x80; if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) { /* Set-up for the last transform: */ MEMSET_BZERO(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace); } else { if (usedspace < SHA512_BLOCK_LENGTH) { MEMSET_BZERO(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace); } /* Do second-to-last transform: */ SHA512_Transform(context, (sha2_word64*)context->buffer); /* And set-up for the last transform: */ MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2); } } else { /* Prepare for final transform: */ MEMSET_BZERO(context->buffer, SHA512_SHORT_BLOCK_LENGTH); /* Begin padding with a 1 bit: */ *context->buffer = 0x80; } /* Store the length of input data (in bits): */ *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1]; *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0]; /* Final transform: */ SHA512_Transform(context, (sha2_word64*)context->buffer); } void SHA512_Final(SHA512_CTX* context, sha2_byte digest[]) { sha2_word64 *d = (sha2_word64*)digest; /* Sanity check: */ assert(context != (SHA512_CTX*)0); /* If no digest buffer is passed, we don't bother doing this: */ if (digest != (sha2_byte*)0) { SHA512_Last(context); /* Save the hash data for output: */ #if BYTE_ORDER == LITTLE_ENDIAN { /* Convert TO host byte order */ int j; for (j = 0; j < 8; j++) { REVERSE64(context->state[j],context->state[j]); *d++ = context->state[j]; } } #else MEMCPY_BCOPY(d, context->state, SHA512_DIGEST_LENGTH); #endif } /* Zero out state data */ MEMSET_BZERO(context, sizeof(context)); } char *SHA512_End(SHA512_CTX* context, char buffer[]) { sha2_byte digest[SHA512_DIGEST_LENGTH], *d = digest; int i; /* Sanity check: */ assert(context != (SHA512_CTX*)0); if (buffer != (char*)0) { SHA512_Final(context, digest); for (i = 0; i < SHA512_DIGEST_LENGTH; i++) { *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; *buffer++ = sha2_hex_digits[*d & 0x0f]; d++; } *buffer = (char)0; } else { MEMSET_BZERO(context, sizeof(context)); } MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH); return buffer; } char* SHA512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) { SHA512_CTX context; SHA512_Init(&context); SHA512_Update(&context, data, len); return SHA512_End(&context, digest); } /*** SHA-384: *********************************************************/ void SHA384_Init(SHA384_CTX* context) { if (context == (SHA384_CTX*)0) { return; } MEMCPY_BCOPY(context->state, sha384_initial_hash_value, SHA512_DIGEST_LENGTH); MEMSET_BZERO(context->buffer, SHA384_BLOCK_LENGTH); context->bitcount[0] = context->bitcount[1] = 0; } void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) { SHA512_Update((SHA512_CTX*)context, data, len); } void SHA384_Final(SHA384_CTX* context, sha2_byte digest[]) { sha2_word64 *d = (sha2_word64*)digest; /* Sanity check: */ assert(context != (SHA384_CTX*)0); /* If no digest buffer is passed, we don't bother doing this: */ if (digest != (sha2_byte*)0) { SHA512_Last((SHA512_CTX*)context); /* Save the hash data for output: */ #if BYTE_ORDER == LITTLE_ENDIAN { /* Convert TO host byte order */ int j; for (j = 0; j < 6; j++) { REVERSE64(context->state[j],context->state[j]); *d++ = context->state[j]; } } #else MEMCPY_BCOPY(d, context->state, SHA384_DIGEST_LENGTH); #endif } /* Zero out state data */ MEMSET_BZERO(context, sizeof(context)); } char *SHA384_End(SHA384_CTX* context, char buffer[]) { sha2_byte digest[SHA384_DIGEST_LENGTH], *d = digest; int i; /* Sanity check: */ assert(context != (SHA384_CTX*)0); if (buffer != (char*)0) { SHA384_Final(context, digest); for (i = 0; i < SHA384_DIGEST_LENGTH; i++) { *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; *buffer++ = sha2_hex_digits[*d & 0x0f]; d++; } *buffer = (char)0; } else { MEMSET_BZERO(context, sizeof(context)); } MEMSET_BZERO(digest, SHA384_DIGEST_LENGTH); return buffer; } char* SHA384_Data(const sha2_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) { SHA384_CTX context; SHA384_Init(&context); SHA384_Update(&context, data, len); return SHA384_End(&context, digest); } dcfldd-1.7.1/src/sha2.h000066400000000000000000000144361410702647300145510ustar00rootroot00000000000000/* * FILE: sha2.h * AUTHOR: Aaron D. Gifford * * Copyright (c) 2000-2001, Aaron D. Gifford * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: sha2.h,v 1.3 2005/05/13 18:52:06 harbourn Exp $ */ #ifndef __SHA2_H__ #define __SHA2_H__ #ifdef __cplusplus extern "C" { #endif /* * Import u_intXX_t size_t type definitions from system headers. You * may need to change this, or define these things yourself in this * file. */ #include #include #ifdef SHA2_USE_INTTYPES_H #include #endif /* SHA2_USE_INTTYPES_H */ /*** SHA-256/384/512 Various Length Definitions ***********************/ #define SHA256_BLOCK_LENGTH 64 #define SHA256_DIGEST_LENGTH 32 #define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) #define SHA384_BLOCK_LENGTH 128 #define SHA384_DIGEST_LENGTH 48 #define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) #define SHA512_BLOCK_LENGTH 128 #define SHA512_DIGEST_LENGTH 64 #define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) /*** SHA-256/384/512 Context Structures *******************************/ /* NOTE: If your architecture does not define either u_intXX_t types or * uintXX_t (from inttypes.h), you may need to define things by hand * for your system: */ #if 0 typedef unsigned char u_int8_t; /* 1-byte (8-bits) */ typedef unsigned int u_int32_t; /* 4-bytes (32-bits) */ typedef unsigned long long u_int64_t; /* 8-bytes (64-bits) */ #endif /* * Most BSD systems already define u_intXX_t types, as does Linux. * Some systems, however, like Compaq's Tru64 Unix instead can use * uintXX_t types defined by very recent ANSI C standards and included * in the file: * * #include * * If you choose to use then please define: * * #define SHA2_USE_INTTYPES_H * * Or on the command line during compile: * * cc -DSHA2_USE_INTTYPES_H ... */ #ifdef SHA2_USE_INTTYPES_H typedef struct _SHA256_CTX { uint32_t state[8]; uint64_t bitcount; uint8_t buffer[SHA256_BLOCK_LENGTH]; } SHA256_CTX; typedef struct _SHA512_CTX { uint64_t state[8]; uint64_t bitcount[2]; uint8_t buffer[SHA512_BLOCK_LENGTH]; } SHA512_CTX; #else /* SHA2_USE_INTTYPES_H */ typedef struct _SHA256_CTX { u_int32_t state[8]; u_int64_t bitcount; u_int8_t buffer[SHA256_BLOCK_LENGTH]; } SHA256_CTX; typedef struct _SHA512_CTX { u_int64_t state[8]; u_int64_t bitcount[2]; u_int8_t buffer[SHA512_BLOCK_LENGTH]; } SHA512_CTX; #endif /* SHA2_USE_INTTYPES_H */ typedef SHA512_CTX SHA384_CTX; /*** SHA-256/384/512 Function Prototypes ******************************/ #ifndef NOPROTO #ifdef SHA2_USE_INTTYPES_H void SHA256_Init(SHA256_CTX *); void SHA256_Update(SHA256_CTX*, const uint8_t*, size_t); void SHA256_Final(SHA256_CTX *, uint8_t[SHA256_DIGEST_LENGTH]); char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]); char* SHA256_Data(const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]); void SHA384_Init(SHA384_CTX*); void SHA384_Update(SHA384_CTX*, const uint8_t*, size_t); void SHA384_Final(SHA384_CTX*, uint8_t[SHA384_DIGEST_LENGTH]); char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]); char* SHA384_Data(const uint8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]); void SHA512_Init(SHA512_CTX*); void SHA512_Update(SHA512_CTX*, const uint8_t*, size_t); void SHA512_Final(SHA512_CTX*, uint8_t[SHA512_DIGEST_LENGTH]); char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]); char* SHA512_Data(const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]); #else /* SHA2_USE_INTTYPES_H */ void SHA256_Init(SHA256_CTX *); void SHA256_Update(SHA256_CTX*, const u_int8_t*, size_t); void SHA256_Final(SHA256_CTX*, u_int8_t[SHA256_DIGEST_LENGTH]); char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]); char* SHA256_Data(const u_int8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]); void SHA384_Init(SHA384_CTX*); void SHA384_Update(SHA384_CTX*, const u_int8_t*, size_t); void SHA384_Final(SHA384_CTX*, u_int8_t[SHA384_DIGEST_LENGTH]); char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]); char* SHA384_Data(const u_int8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]); void SHA512_Init(SHA512_CTX*); void SHA512_Update(SHA512_CTX*, const u_int8_t*, size_t); void SHA512_Final(SHA512_CTX*, u_int8_t[SHA512_DIGEST_LENGTH]); char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]); char* SHA512_Data(const u_int8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]); #endif /* SHA2_USE_INTTYPES_H */ #else /* NOPROTO */ void SHA256_Init(); void SHA256_Update(); void SHA256_Final(); char* SHA256_End(); char* SHA256_Data(); void SHA384_Init(); void SHA384_Update(); void SHA384_Final(); char* SHA384_End(); char* SHA384_Data(); void SHA512_Init(); void SHA512_Update(); void SHA512_Final(); char* SHA512_End(); char* SHA512_Data(); #endif /* NOPROTO */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __SHA2_H__ */ dcfldd-1.7.1/src/sizeprobe.c000066400000000000000000000132611410702647300157040ustar00rootroot00000000000000/* $Id: sizeprobe.c,v 1.4 2005/05/15 20:15:28 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright 85, 90, 91, 1995-2001, 2005 Free Software Foundation, Inc. * Copyright 2014 Vangelis Koukis * Copyright 2020 David Polverari 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #include "dcfldd.h" #include #include #include #include #include #include "config.h" #include "system.h" #include "sizeprobe.h" #include "log.h" static off_t midpoint(off_t a, off_t b, long blksize); static off_t get_dev_size(int, long); /* Which file (if any) to probe the size of */ int probe = PROBE_NONE; off_t probed_size; /* * Compute a block-resolution midpoint (c) of a and b */ static off_t midpoint(off_t a, off_t b, long blksize) { off_t aprime = a / blksize; off_t bprime = b / blksize; off_t c, cprime; cprime = (bprime - aprime) / 2 + aprime; c = cprime * blksize; return c; } #if defined (__linux__) #include #include /* I stole this from Jesse Kornblum's md5deep */ static off_t get_dev_size(int fd, long blksize) { off_t num_bytes = 0; /* * Use BLKGETSIZE64 unconditionally, since dcfldd.h #defines _FILE_OFFSET_BITS 64 * and off_t is guaranteed to be large enough to hold the result. */ if (ioctl(fd, BLKGETSIZE64, &num_bytes)) log_info("%s: ioctl call to BLKGETSIZE64 failed.\n", program_name); else return (num_bytes); } #elif defined (__MacOSX__) #include #include #include #include /* I also stole this from Jesse Kornblum's md5deep */ static static off_t get_dev_size(int fd, long blksize) { FILE *f = fdopen(fd, "r"); off_t total = 0; off_t original = ftello(f); int ok = TRUE; if (S_ISBLK(info.st_mode)) { daddr_t blocksize = 0; daddr_t blockcount = 0; /* Get the block size */ if (ioctl(fd, DKIOCGETBLOCKSIZE,blocksize) < 0) { ok = FALSE; #if defined(__DEBUG) perror("DKIOCGETBLOCKSIZE failed"); #endif } /* Get the number of blocks */ if (ok) { if (ioctl(fd, DKIOCGETBLOCKCOUNT, blockcount) < 0) { #if defined(__DEBUG) perror("DKIOCGETBLOCKCOUNT failed"); #endif } } total = blocksize * blockcount; } else { /* I don't know why, but if you don't initialize this value you'll get wildly innacurate results when you try to run this function */ if ((fseeko(f,0,SEEK_END))) return 0; total = ftello(f); if ((fseeko(f,original,SEEK_SET))) return 0; } return (total - original); } #else /* all other *nix */ /* * Guess the size of a device file. * Note: this is only used to give time estimates. * Even if this is way off or broken, * the forensic validity of the tool remains. ************************************************** * This algorithm works by reading a block starting * at offset 0 then 1, 2, 4, 8, 16, etc and doubles * until it reaches a point where it fails, then it * iteratively backtracks by half the distance to * the last known good read. It goes back and forth * until it knows the last readable block on the * device. Theoretically, this should give EXACTLY * the size of the device considering that the * seeks and reads work. this algorithm will * obviously wreak havok if you try it against a * tape device, you have been warned. */ static off_t get_dev_size(int fd, long blksize) { /* this function is awesome */ off_t curr = 0, amount = 0; void *buf; off_t told; if (blksize == 0) return 0; buf = malloc(blksize); for (;;) { ssize_t nread; lseek(fd, curr, SEEK_SET); nread = read(fd, buf, blksize); if (nread < blksize) { if (nread <= 0) { if (curr == amount) { free(buf); lseek(fd, 0, SEEK_SET); return amount; } curr = midpoint(amount, curr, blksize); } else { /* 0 < nread < blksize */ free(buf); lseek(fd, 0, SEEK_SET); return amount + nread; } } else { amount = curr + blksize; curr = amount * 2; } } free(buf); lseek(fd, 0, SEEK_SET); return amount; } #endif /* if defined (__linux__), etc.. */ void sizeprobe(int fd) { struct stat statbuf; if (fstat(fd, &statbuf) == -1) { log_info("%s: stating file", strerror(errno)); return; } if (S_ISREG(statbuf.st_mode) || S_ISDIR(statbuf.st_mode)) probed_size = statbuf.st_size; else if (S_ISCHR(statbuf.st_mode) || S_ISBLK(statbuf.st_mode)) probed_size = get_dev_size(fd, statbuf.st_blksize); } dcfldd-1.7.1/src/sizeprobe.h000066400000000000000000000024451410702647300157130ustar00rootroot00000000000000/* $Id: sizeprobe.h,v 1.3 2005/05/13 18:52:06 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright 85, 90, 91, 1995-2001, 2005 Free Software Foundation, Inc. Copyright 2008 David Loveall 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #ifndef SIZEPROBE_H #define SIZEPROBE_H #include "dcfldd.h" #include enum {PROBE_NONE = 0, PROBE_INPUT, PROBE_OUTPUT, PROBE_INPUT_PROVIDED}; extern int probe; extern off_t probed_size; extern void sizeprobe(int); #endif /* SIZEPROBE_H */ dcfldd-1.7.1/src/split.c000066400000000000000000000107711410702647300150400ustar00rootroot00000000000000/* $Id: split.c,v 1.3 2005/05/13 18:52:06 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright 85, 90, 91, 1995-2001, 2005 Free Software Foundation, Inc. Copyright 2008 David Loveall Copyright 2012 Miah Gregory Copyright 2015-2019 Joao Eriberto Mota Filho Copyright 2019 Bernhard Übelacker 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #define _GNU_SOURCE 1 #include "dcfldd.h" #include #include "split.h" #include #include #include #include #include #include #include "full-write.h" #include "log.h" /* for portability, use these arrays for referencing numbers and letters */ static char *numbers = "0123456789"; #define NUM_NUMBERS 10 static char *letters = "abcdefghijklmnopqrstuvwxyz"; #define NUM_LETTERS 26 static char *getext(char *, int); static int maxsplits(char *); /* Generate a split file extension string based on * the specified format string and a given number */ static char *getext(char *fmt, int num) { int fmtlen = strlen(fmt); int i; char *retval; assert(fmtlen > 0); if (strcmp(fmt, "MAC") == 0) { if (num == 0) { if(asprintf(&retval, "dmg")) {}; } else { if(asprintf(&retval, "%03d.dmgpart", num+1)) {}; } return retval; } if (strcmp(fmt, "WIN") == 0) { if(asprintf(&retval, "%03d", num+1)) {}; return retval; } retval = malloc(fmtlen); /* Fill the retval in reverse while constantly dividing num apropriately */ for (i = fmtlen - 1; i >= 0; i--) { int x; if (fmt[i] == 'a') { x = num % NUM_LETTERS; retval[i] = letters[x]; num = num / NUM_LETTERS; } else { x = num % NUM_NUMBERS; retval[i] = numbers[x]; num = num / NUM_NUMBERS; } } retval[fmtlen] = '\0'; return retval; } /* Given a format string, determine the maximum number of splits * that can be used. */ static int maxsplits(char *fmt) { int fmtlen = strlen(fmt); int i; int retval = 1; assert(fmtlen > 0); for (i = fmtlen - 1; i >= 0; i--) retval *= fmt[i] == 'a' ? NUM_LETTERS : NUM_NUMBERS; return retval; } /* Open the next extension in a split sequence */ static void open_split(split_t *split) { int fd; int splitnum = split->total_bytes / split->max_bytes; mode_t perms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; char *ext, *fname; ext = getext(split->format, splitnum); /* [FIX] split.c:105:5: warning: ignoring return value of ‘asprintf’, declared with attribute warn_unused_result [-Wunused-result] */ if( asprintf(&fname, "%s.%s", split->name, ext) == -1) { return; } free(ext); fd = open(fname, O_WRONLY | O_CREAT, perms); if (fd < 0) syscall_error(fname); close(split->currfd); split->currfd = fd; split->curr_bytes = 0; free(fname); } int split_write(split_t *split, const char *buf, size_t len) { off_t left = split->max_bytes - split->curr_bytes; int nwritten = 0; if (left == 0 || split->currfd == -1) { open_split(split); left = split->max_bytes; } if (len <= left) { nwritten = full_write(split->currfd, buf, len); split->total_bytes += nwritten; split->curr_bytes += nwritten; } else { nwritten = full_write(split->currfd, buf, left); split->total_bytes += nwritten; split->curr_bytes += nwritten; nwritten += split_write(split, &buf[nwritten], len - nwritten); } return nwritten; } dcfldd-1.7.1/src/split.h000066400000000000000000000025451410702647300150450ustar00rootroot00000000000000/* $Id: split.h,v 1.3 2005/05/13 18:52:06 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright (C) 85, 90, 91, 1995-2001, 2005 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #ifndef SPLIT_H #define SPLIT_H #include "dcfldd.h" #include typedef struct { int currfd; off_t max_bytes; /* The split size */ off_t total_bytes; /* Total Bytes written sofar */ off_t curr_bytes; /* Bytes written to current split file */ char *name; char *format; } split_t; extern int split_write(split_t *, const char *, size_t); #endif /* SPLIT_H */ dcfldd-1.7.1/src/sys2.h000066400000000000000000000326531410702647300146150ustar00rootroot00000000000000#ifndef SYS2_H #define SYS2_H #if STAT_MACROS_BROKEN # undef S_ISBLK # undef S_ISCHR # undef S_ISDIR # undef S_ISDOOR # undef S_ISFIFO # undef S_ISLNK # undef S_ISMPB # undef S_ISMPC # undef S_ISNWK # undef S_ISREG # undef S_ISSOCK #endif /* STAT_MACROS_BROKEN. */ #ifndef S_IFMT # define S_IFMT 0170000 #endif #if !defined(S_ISBLK) && defined(S_IFBLK) # define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) #endif #if !defined(S_ISCHR) && defined(S_IFCHR) # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) #endif #if !defined(S_ISDIR) && defined(S_IFDIR) # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif #if !defined(S_ISREG) && defined(S_IFREG) # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #endif #if !defined(S_ISFIFO) && defined(S_IFIFO) # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) #endif #if !defined(S_ISLNK) && defined(S_IFLNK) # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) #endif #if !defined(S_ISSOCK) && defined(S_IFSOCK) # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) #endif #if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */ # define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) # define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) #endif #if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */ # define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) #endif #if !defined(S_ISDOOR) && defined(S_IFDOOR) /* Solaris 2.5 and up */ # define S_ISDOOR(m) (((m) & S_IFMT) == S_IFDOOR) #endif #if !S_ISUID # define S_ISUID 04000 #endif #if !S_ISGID # define S_ISGID 02000 #endif /* S_ISVTX is a common extension to POSIX.1. */ #ifndef S_ISVTX # define S_ISVTX 01000 #endif #if !S_IRUSR && S_IREAD # define S_IRUSR S_IREAD #endif #if !S_IRUSR # define S_IRUSR 00400 #endif #if !S_IRGRP # define S_IRGRP (S_IRUSR >> 3) #endif #if !S_IROTH # define S_IROTH (S_IRUSR >> 6) #endif #if !S_IWUSR && S_IWRITE # define S_IWUSR S_IWRITE #endif #if !S_IWUSR # define S_IWUSR 00200 #endif #if !S_IWGRP # define S_IWGRP (S_IWUSR >> 3) #endif #if !S_IWOTH # define S_IWOTH (S_IWUSR >> 6) #endif #if !S_IXUSR && S_IEXEC # define S_IXUSR S_IEXEC #endif #if !S_IXUSR # define S_IXUSR 00100 #endif #if !S_IXGRP # define S_IXGRP (S_IXUSR >> 3) #endif #if !S_IXOTH # define S_IXOTH (S_IXUSR >> 6) #endif #if !S_IRWXU # define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) #endif #if !S_IRWXG # define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) #endif #if !S_IRWXO # define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) #endif /* S_IXUGO is a common extension to POSIX.1. */ #if !S_IXUGO # define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH) #endif #ifndef S_IRWXUGO # define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO) #endif /* All the mode bits that can be affected by chmod. */ #define CHMOD_MODE_BITS \ (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) #ifdef ST_MTIM_NSEC # define ST_TIME_CMP_NS(a, b, ns) ((a).ns < (b).ns ? -1 : (a).ns > (b).ns) #else # define ST_TIME_CMP_NS(a, b, ns) 0 #endif #define ST_TIME_CMP(a, b, s, ns) \ ((a).s < (b).s ? -1 : (a).s > (b).s ? 1 : ST_TIME_CMP_NS(a, b, ns)) #define ATIME_CMP(a, b) ST_TIME_CMP (a, b, st_atime, st_atim.ST_MTIM_NSEC) #define CTIME_CMP(a, b) ST_TIME_CMP (a, b, st_ctime, st_ctim.ST_MTIM_NSEC) #define MTIME_CMP(a, b) ST_TIME_CMP (a, b, st_mtime, st_mtim.ST_MTIM_NSEC) #ifndef RETSIGTYPE #define RETSIGTYPE void #endif #ifndef __GNUC__ # if HAVE_ALLOCA_H # include # else # ifdef _AIX # pragma alloca # else # ifdef _WIN32 # include # include # else # ifndef alloca char *alloca (); # endif # endif # endif # endif #endif #ifdef __DJGPP__ /* We need the declaration of setmode. */ # include /* We need the declaration of __djgpp_set_ctrl_c. */ # include #endif #if HAVE_STDINT_H # include #endif #if HAVE_INTTYPES_H # include /* for the definition of UINTMAX_MAX */ #endif #include /* Jim Meyering writes: "... Some ctype macros are valid only for character codes that isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when using /bin/cc or gcc but without giving an ansi option). So, all ctype uses should be through macros like ISPRINT... If STDC_HEADERS is defined, then autoconf has verified that the ctype macros don't need to be guarded with references to isascii. ... Defining isascii to 1 should let any compiler worth its salt eliminate the && through constant folding." Bruno Haible adds: "... Furthermore, isupper(c) etc. have an undefined result if c is outside the range -1 <= c <= 255. One is tempted to write isupper(c) with c being of type `char', but this is wrong if c is an 8-bit character >= 128 which gets sign-extended to a negative value. The macro ISUPPER protects against this as well." */ #if STDC_HEADERS || (!defined (isascii) && !HAVE_ISASCII) # define IN_CTYPE_DOMAIN(c) 1 #else # define IN_CTYPE_DOMAIN(c) isascii(c) #endif #ifdef isblank # define ISBLANK(c) (IN_CTYPE_DOMAIN (c) && isblank (c)) #else # define ISBLANK(c) ((c) == ' ' || (c) == '\t') #endif #ifdef isgraph # define ISGRAPH(c) (IN_CTYPE_DOMAIN (c) && isgraph (c)) #else # define ISGRAPH(c) (IN_CTYPE_DOMAIN (c) && isprint (c) && !isspace (c)) #endif /* This is defined in on at least Solaris2.6 systems. */ #undef ISPRINT #define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c)) #define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum (c)) #define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c)) #define ISCNTRL(c) (IN_CTYPE_DOMAIN (c) && iscntrl (c)) #define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c)) #define ISPUNCT(c) (IN_CTYPE_DOMAIN (c) && ispunct (c)) #define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c)) #define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c)) #define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (c)) #define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c)) #if STDC_HEADERS # define TOLOWER(Ch) tolower (Ch) # define TOUPPER(Ch) toupper (Ch) #else # define TOLOWER(Ch) (ISUPPER (Ch) ? tolower (Ch) : (Ch)) # define TOUPPER(Ch) (ISLOWER (Ch) ? toupper (Ch) : (Ch)) #endif /* ISDIGIT differs from ISDIGIT_LOCALE, as follows: - Its arg may be any int or unsigned int; it need not be an unsigned char. - It's guaranteed to evaluate its argument exactly once. - It's typically faster. Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that only '0' through '9' are digits. Prefer ISDIGIT to ISDIGIT_LOCALE unless it's important to use the locale's definition of `digit' even when the host does not conform to Posix. */ #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9) #ifndef PARAMS # if PROTOTYPES # define PARAMS(Args) Args # else # define PARAMS(Args) () # endif #endif /* Take care of NLS matters. */ #if HAVE_LOCALE_H # include #endif #if !HAVE_SETLOCALE # define setlocale(Category, Locale) /* empty */ #endif #if ENABLE_NLS # include # if HAVE_GETTEXT && !HAVE_DCGETTEXT && !defined dcgettext # define dcgettext(Domain, Text, Category) Text # endif # define _(Text) gettext (Text) #else # undef bindtextdomain # define bindtextdomain(Domain, Directory) /* empty */ # undef textdomain # define textdomain(Domain) /* empty */ # undef dcgettext # define dcgettext(Domainname, Text, Category) Text # define _(Text) Text #endif #define N_(Text) Text #define STREQ(a, b) (strcmp ((a), (b)) == 0) /* This is needed on some AIX systems. */ #if !HAVE_DECL_STRTOUL unsigned long strtoul (); #endif /* This is needed on some AIX systems. */ #if !HAVE_DECL_STRTOULL && HAVE_UNSIGNED_LONG_LONG unsigned long long strtoull (); #endif #if !HAVE_DECL_GETLOGIN char *getlogin (); #endif #if !HAVE_DECL_TTYNAME char *ttyname (); #endif #if !HAVE_DECL_GETEUID uid_t geteuid (); #endif #if !HAVE_DECL_GETPWUID struct passwd *getpwuid (); #endif #if !HAVE_DECL_GETGRGID struct group *getgrgid (); #endif #if !HAVE_DECL_GETUID uid_t getuid (); #endif #include "xalloc.h" #if ! defined HAVE_MEMPCPY && ! defined mempcpy /* Be CAREFUL that there are no side effects in N. */ # define mempcpy(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N))) #endif /* These are wrappers for functions/macros from GNU libc. The standard I/O functions are thread-safe. These *_unlocked ones are more efficient but not thread-safe. That they're not thread-safe is fine since all these applications are single threaded. */ #if HAVE_CLEARERR_UNLOCKED # undef clearerr # define clearerr(S) clearerr_unlocked (S) #endif #if HAVE_FEOF_UNLOCKED # undef feof # define feof(S) feof_unlocked (S) #endif #if HAVE_FERROR_UNLOCKED # undef ferror # define ferror(S) ferror_unlocked (S) #endif #if HAVE_FFLUSH_UNLOCKED # undef fflush # define fflush(S) fflush_unlocked (S) #endif #if HAVE_FPUTC_UNLOCKED # undef fputc # define fputc(C, S) fputc_unlocked (C, S) #endif #if HAVE_FREAD_UNLOCKED # undef fread # define fread(P, Z, N, S) fread_unlocked (P, Z, N, S) #endif #if HAVE_FWRITE_UNLOCKED # undef fwrite # define fwrite(P, Z, N, S) fwrite_unlocked (P, Z, N, S) #endif #if HAVE_GETC_UNLOCKED # undef getc # define getc(S) getc_unlocked (S) #endif #if HAVE_GETCHAR_UNLOCKED # undef getchar # define getchar(S) getchar_unlocked (S) #endif #if HAVE_PUTC_UNLOCKED # undef putc # define putc(C, S) putc_unlocked (C, S) #endif #if HAVE_PUTCHAR_UNLOCKED # undef putchar # define putchar(C) putchar_unlocked (C) #endif #define SAME_INODE(Stat_buf_1, Stat_buf_2) \ ((Stat_buf_1).st_ino == (Stat_buf_2).st_ino \ && (Stat_buf_1).st_dev == (Stat_buf_2).st_dev) #define DOT_OR_DOTDOT(Basename) \ (Basename[0] == '.' && (Basename[1] == '\0' \ || (Basename[1] == '.' && Basename[2] == '\0'))) #if SETVBUF_REVERSED # define SETVBUF(Stream, Buffer, Type, Size) \ setvbuf (Stream, Type, Buffer, Size) #else # define SETVBUF(Stream, Buffer, Type, Size) \ setvbuf (Stream, Buffer, Type, Size) #endif char *base_name PARAMS ((char const *)); /* Factor out some of the common --help and --version processing code. */ /* These enum values cannot possibly conflict with the option values ordinarily used by commands, including CHAR_MAX + 1, etc. Avoid CHAR_MIN - 1, as it may equal -1, the getopt end-of-options value. */ enum { GETOPT_HELP_CHAR = (CHAR_MIN - 2), GETOPT_VERSION_CHAR = (CHAR_MIN - 3) }; #define GETOPT_HELP_OPTION_DECL \ "help", no_argument, 0, GETOPT_HELP_CHAR #define GETOPT_VERSION_OPTION_DECL \ "version", no_argument, 0, GETOPT_VERSION_CHAR #define case_GETOPT_HELP_CHAR \ case GETOPT_HELP_CHAR: \ usage (EXIT_SUCCESS); \ break; #include "version-etc.h" #define case_GETOPT_VERSION_CHAR(Program_name, Authors) \ case GETOPT_VERSION_CHAR: \ version_etc (stdout, Program_name, PACKAGE, VERSION, Authors); \ exit (EXIT_SUCCESS); \ break; #ifndef MAX # define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif #ifndef MIN # define MIN(a,b) (((a) < (b)) ? (a) : (b)) #endif #ifndef CHAR_BIT # define CHAR_BIT 8 #endif /* The extra casts work around common compiler bugs. */ #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) /* The outer cast is needed to work around a bug in Cray C 5.0.3.0. It is necessary at least when t == time_t. */ #define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \ ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0)) #define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t))) /* Upper bound on the string length of an integer converted to string. 302 / 1000 is ceil (log10 (2.0)). Subtract 1 for the sign bit; add 1 for integer division truncation; add 1 more for a minus sign. */ #define INT_STRLEN_BOUND(t) ((sizeof (t) * CHAR_BIT - 1) * 302 / 1000 + 2) #ifndef CHAR_MIN # define CHAR_MIN TYPE_MINIMUM (char) #endif #ifndef CHAR_MAX # define CHAR_MAX TYPE_MAXIMUM (char) #endif #ifndef SCHAR_MIN # define SCHAR_MIN (-1 - SCHAR_MAX) #endif #ifndef SCHAR_MAX # define SCHAR_MAX (CHAR_MAX == UCHAR_MAX ? CHAR_MAX / 2 : CHAR_MAX) #endif #ifndef UCHAR_MAX # define UCHAR_MAX TYPE_MAXIMUM (unsigned char) #endif #ifndef SHRT_MIN # define SHRT_MIN TYPE_MINIMUM (short int) #endif #ifndef SHRT_MAX # define SHRT_MAX TYPE_MAXIMUM (short int) #endif #ifndef INT_MAX # define INT_MAX TYPE_MAXIMUM (int) #endif #ifndef UINT_MAX # define UINT_MAX TYPE_MAXIMUM (unsigned int) #endif #ifndef LONG_MAX # define LONG_MAX TYPE_MAXIMUM (long) #endif #ifndef ULONG_MAX # define ULONG_MAX TYPE_MAXIMUM (unsigned long) #endif #ifndef SIZE_MAX # define SIZE_MAX TYPE_MAXIMUM (size_t) #endif #ifndef UINTMAX_MAX # define UINTMAX_MAX TYPE_MAXIMUM (uintmax_t) #endif #ifndef OFF_T_MIN # define OFF_T_MIN TYPE_MINIMUM (off_t) #endif #ifndef OFF_T_MAX # define OFF_T_MAX TYPE_MAXIMUM (off_t) #endif #ifndef UID_T_MAX # define UID_T_MAX TYPE_MAXIMUM (uid_t) #endif #ifndef GID_T_MAX # define GID_T_MAX TYPE_MAXIMUM (gid_t) #endif #ifndef PID_T_MAX # define PID_T_MAX TYPE_MAXIMUM (pid_t) #endif #ifndef CHAR_BIT # define CHAR_BIT 8 #endif /* Use this to suppress gcc's `...may be used before initialized' warnings. */ #ifdef lint # define IF_LINT(Code) Code #else # define IF_LINT(Code) /* empty */ #endif #ifndef __attribute__ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ # define __attribute__(x) # endif #endif #ifndef ATTRIBUTE_NORETURN # define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) #endif #ifndef ATTRIBUTE_UNUSED # define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) #endif #if defined strdupa # define ASSIGN_STRDUPA(DEST, S) \ do { DEST = strdupa(S); } while (0) #else # define ASSIGN_STRDUPA(DEST, S) \ do \ { \ const char *s_ = (S); \ size_t len_ = strlen (s_) + 1; \ char *tmp_dest_ = (char *) alloca (len_); \ DEST = memcpy (tmp_dest_, (s_), len_); \ } \ while (0) #endif #endif /* SYS2_H */ dcfldd-1.7.1/src/system.h000066400000000000000000000153061410702647300152350ustar00rootroot00000000000000/* system-dependent definitions for fileutils, textutils, and sh-utils packages. Copyright (C) 1989, 1991-2000 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Include sys/types.h before this file. */ #include #if !defined(HAVE_MKFIFO) # define mkfifo(path, mode) (mknod ((path), (mode) | S_IFIFO, 0)) #endif #if HAVE_SYS_PARAM_H # include #endif /* should be included before any preprocessor test of _POSIX_VERSION. */ #if HAVE_UNISTD_H # include #endif #ifndef STDIN_FILENO # define STDIN_FILENO 0 #endif #ifndef STDOUT_FILENO # define STDOUT_FILENO 1 #endif #ifndef STDERR_FILENO # define STDERR_FILENO 2 #endif #if HAVE_LIMITS_H /* limits.h must come before pathmax.h because limits.h on some systems undefs PATH_MAX, whereas pathmax.h sets PATH_MAX. */ # include #endif #include "pathmax.h" #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif /* Since major is a function on SVR4, we can't use `ifndef major'. */ #if MAJOR_IN_MKDEV # include # define HAVE_MAJOR #endif #if MAJOR_IN_SYSMACROS # include # define HAVE_MAJOR #endif #ifdef major /* Might be defined in sys/types.h. */ # define HAVE_MAJOR #endif #ifndef HAVE_MAJOR # define major(dev) (((dev) >> 8) & 0xff) # define minor(dev) ((dev) & 0xff) # define makedev(maj, min) (((maj) << 8) | (min)) #endif #undef HAVE_MAJOR #if HAVE_UTIME_H # include #endif /* Don't use bcopy! Use memmove if source and destination may overlap, memcpy otherwise. */ #if HAVE_STRING_H # if !STDC_HEADERS && HAVE_MEMORY_H # include # endif # include #else # include #endif #include #ifndef errno extern int errno; #endif #if HAVE_STDLIB_H # define getopt system_getopt # include # undef getopt #endif /* The following test is to work around the gross typo in systems like Sony NEWS-OS Release 4.0C, whereby EXIT_FAILURE is defined to 0, not 1. */ #if !EXIT_FAILURE # undef EXIT_FAILURE # define EXIT_FAILURE 1 #endif #ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 #endif #if HAVE_FCNTL_H # include #else # include #endif #if !defined (SEEK_SET) # define SEEK_SET 0 # define SEEK_CUR 1 # define SEEK_END 2 #endif #ifndef F_OK # define F_OK 0 # define X_OK 1 # define W_OK 2 # define R_OK 4 #endif /* For systems that distinguish between text and binary I/O. O_BINARY is usually declared in fcntl.h */ #if !defined O_BINARY && defined _O_BINARY /* For MSC-compatible compilers. */ # define O_BINARY _O_BINARY # define O_TEXT _O_TEXT #endif #ifdef __BEOS__ /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */ # undef O_BINARY # undef O_TEXT #endif #if O_BINARY # ifndef __DJGPP__ # define setmode _setmode # define fileno(_fp) _fileno (_fp) # endif /* not DJGPP */ # define SET_BINARY(_f) do {if (!isatty(_f)) setmode (_f, O_BINARY);} while (0) # define SET_BINARY2(_f1, _f2) \ do { \ if (!isatty (_f1)) \ { \ setmode (_f1, O_BINARY); \ if (!isatty (_f2)) \ setmode (_f2, O_BINARY); \ } \ } while(0) #else # define SET_BINARY(f) (void)0 # define SET_BINARY2(f1,f2) (void)0 # define O_BINARY 0 # define O_TEXT 0 #endif /* O_BINARY */ #if HAVE_DIRENT_H # include # define NLENGTH(direct) (strlen((direct)->d_name)) #else /* not HAVE_DIRENT_H */ # define dirent direct # define NLENGTH(direct) ((direct)->d_namlen) # if HAVE_SYS_NDIR_H # include # endif /* HAVE_SYS_NDIR_H */ # if HAVE_SYS_DIR_H # include # endif /* HAVE_SYS_DIR_H */ # if HAVE_NDIR_H # include # endif /* HAVE_NDIR_H */ #endif /* HAVE_DIRENT_H */ #if CLOSEDIR_VOID /* Fake a return value. */ # define CLOSEDIR(d) (closedir (d), 0) #else # define CLOSEDIR(d) closedir (d) #endif /* Get or fake the disk device blocksize. Usually defined by sys/param.h (if at all). */ #if !defined DEV_BSIZE && defined BSIZE # define DEV_BSIZE BSIZE #endif #if !defined DEV_BSIZE && defined BBSIZE /* SGI */ # define DEV_BSIZE BBSIZE #endif #ifndef DEV_BSIZE # define DEV_BSIZE 4096 #endif /* Extract or fake data from a `struct stat'. ST_BLKSIZE: Preferred I/O blocksize for the file, in bytes. ST_NBLOCKS: Number of blocks in the file, including indirect blocks. ST_NBLOCKSIZE: Size of blocks used when calculating ST_NBLOCKS. */ #ifndef HAVE_STRUCT_STAT_ST_BLOCKS # define ST_BLKSIZE(statbuf) DEV_BSIZE # if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE. */ # define ST_NBLOCKS(statbuf) \ (S_ISREG ((statbuf).st_mode) \ || S_ISDIR ((statbuf).st_mode) \ ? (statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0) : 0) # else /* !_POSIX_SOURCE && BSIZE */ # define ST_NBLOCKS(statbuf) \ (S_ISREG ((statbuf).st_mode) \ || S_ISDIR ((statbuf).st_mode) \ ? st_blocks ((statbuf).st_size) : 0) # endif /* !_POSIX_SOURCE && BSIZE */ #else /* HAVE_STRUCT_STAT_ST_BLOCKS */ /* Some systems, like Sequents, return st_blksize of 0 on pipes. */ # define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \ ? (statbuf).st_blksize : DEV_BSIZE) # if defined(hpux) || defined(__hpux__) || defined(__hpux) /* HP-UX counts st_blocks in 1024-byte units. This loses when mixing HP-UX and BSD filesystems with NFS. */ # define ST_NBLOCKSIZE 1024 # else /* !hpux */ # if defined(_AIX) && defined(_I386) /* AIX PS/2 counts st_blocks in 4K units. */ # define ST_NBLOCKSIZE (4 * 1024) # else /* not AIX PS/2 */ # if defined(_CRAY) # define ST_NBLOCKS(statbuf) \ (S_ISREG ((statbuf).st_mode) \ || S_ISDIR ((statbuf).st_mode) \ ? (statbuf).st_blocks * ST_BLKSIZE(statbuf)/ST_NBLOCKSIZE : 0) # endif /* _CRAY */ # endif /* not AIX PS/2 */ # endif /* !hpux */ #endif /* HAVE_STRUCT_STAT_ST_BLOCKS */ #ifndef ST_NBLOCKS # define ST_NBLOCKS(statbuf) \ (S_ISREG ((statbuf).st_mode) \ || S_ISDIR ((statbuf).st_mode) \ ? (statbuf).st_blocks : 0) #endif #ifndef ST_NBLOCKSIZE # define ST_NBLOCKSIZE 512 #endif #include "sys2.h" dcfldd-1.7.1/src/translate.c000066400000000000000000000176271410702647300157110ustar00rootroot00000000000000/* $Id: translate.c,v 1.4 2005/05/15 20:15:28 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright 85, 90, 91, 1995-2001, 2005 Free Software Foundation, Inc. Copyright 2012 Miah Gregory 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #include "dcfldd.h" #include "log.h" #include "util.h" /* Output representation of newline and space characters. They change if we're converting to EBCDIC. */ unsigned char newline_character = '\n'; unsigned char space_character = ' '; /* Translation table formed by applying successive transformations. */ unsigned char trans_table[256]; unsigned char const ascii_to_ebcdic[] = { 0, 01, 02, 03, 067, 055, 056, 057, 026, 05, 045, 013, 014, 015, 016, 017, 020, 021, 022, 023, 074, 075, 062, 046, 030, 031, 077, 047, 034, 035, 036, 037, 0100, 0117, 0177, 0173, 0133, 0154, 0120, 0175, 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, 0347, 0350, 0351, 0112, 0340, 0132, 0137, 0155, 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, 0247, 0250, 0251, 0300, 0152, 0320, 0241, 07, 040, 041, 042, 043, 044, 025, 06, 027, 050, 051, 052, 053, 054, 011, 012, 033, 060, 061, 032, 063, 064, 065, 066, 010, 070, 071, 072, 073, 04, 024, 076, 0341, 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377 }; unsigned char const ascii_to_ibm[] = { 0, 01, 02, 03, 067, 055, 056, 057, 026, 05, 045, 013, 014, 015, 016, 017, 020, 021, 022, 023, 074, 075, 062, 046, 030, 031, 077, 047, 034, 035, 036, 037, 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, 0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155, 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, 0247, 0250, 0251, 0300, 0117, 0320, 0241, 07, 040, 041, 042, 043, 044, 025, 06, 027, 050, 051, 052, 053, 054, 011, 012, 033, 060, 061, 032, 063, 064, 065, 066, 010, 070, 071, 072, 073, 04, 024, 076, 0341, 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377 }; unsigned char const ebcdic_to_ascii[] = { 0, 01, 02, 03, 0234, 011, 0206, 0177, 0227, 0215, 0216, 013, 014, 015, 016, 017, 020, 021, 022, 023, 0235, 0205, 010, 0207, 030, 031, 0222, 0217, 034, 035, 036, 037, 0200, 0201, 0202, 0203, 0204, 012, 027, 033, 0210, 0211, 0212, 0213, 0214, 05, 06, 07, 0220, 0221, 026, 0223, 0224, 0225, 0226, 04, 0230, 0231, 0232, 0233, 024, 025, 0236, 032, 040, 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, 0250, 0133, 056, 074, 050, 053, 041, 046, 0251, 0252, 0253, 0254, 0255, 0256, 0257, 0260, 0261, 0135, 044, 052, 051, 073, 0136, 055, 057, 0262, 0263, 0264, 0265, 0266, 0267, 0270, 0271, 0174, 054, 045, 0137, 076, 077, 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, 0302, 0140, 072, 043, 0100, 047, 075, 042, 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147, 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311, 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160, 0161, 0162, 0313, 0314, 0315, 0316, 0317, 0320, 0321, 0176, 0163, 0164, 0165, 0166, 0167, 0170, 0171, 0172, 0322, 0323, 0324, 0325, 0326, 0327, 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355, 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120, 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363, 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130, 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371, 060, 061, 062, 063, 064, 065, 066, 067, 070, 071, 0372, 0373, 0374, 0375, 0376, 0377 }; static void translate_charset(const unsigned char *new_trans) { unsigned int i; for (i = 0; i < 256; i++) trans_table[i] = new_trans[trans_table[i]]; translation_needed = 1; } /* Fix up translation table. */ void apply_translations(void) { unsigned int i; #define MX(a) (bit_count (conversions_mask & (a))) if ((MX (C_ASCII | C_EBCDIC | C_IBM) > 1) || (MX (C_BLOCK | C_UNBLOCK) > 1) || (MX (C_LCASE | C_UCASE) > 1) || (MX (C_UNBLOCK | C_SYNC) > 1)) { log_info("\ only one conv in {ascii,ebcdic,ibm}, {lcase,ucase}, {block,unblock}, {unblock,sync}"); } #undef MX if (conversions_mask & C_ASCII) translate_charset(ebcdic_to_ascii); if (conversions_mask & C_UCASE) { for (i = 0; i < 256; i++) if (ISLOWER(trans_table[i])) trans_table[i] = TOUPPER(trans_table[i]); translation_needed = 1; } else if (conversions_mask & C_LCASE) { for (i = 0; i < 256; i++) if (ISUPPER(trans_table[i])) trans_table[i] = TOLOWER(trans_table[i]); translation_needed = 1; } if (conversions_mask & C_EBCDIC) { translate_charset (ascii_to_ebcdic); newline_character = ascii_to_ebcdic['\n']; space_character = ascii_to_ebcdic[' ']; } else if (conversions_mask & C_IBM) { translate_charset (ascii_to_ibm); newline_character = ascii_to_ibm['\n']; space_character = ascii_to_ibm[' ']; } } /* Apply the character-set translations specified by the user to the NREAD bytes in BUF. */ void translate_buffer(unsigned char *buf, size_t nread) { unsigned char *cp; size_t i; for (i = nread, cp = buf; i; i--, cp++) *cp = trans_table[*cp]; } dcfldd-1.7.1/src/translate.h000066400000000000000000000026451410702647300157100ustar00rootroot00000000000000/* $Id: translate.h,v 1.3 2005/05/13 18:52:06 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright (C) 85, 90, 91, 1995-2001, 2005 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #ifndef TRANSLATE_H #define TRANSLATE_H #include "dcfldd.h" #include extern unsigned char newline_character; extern unsigned char space_character; extern unsigned char trans_table[]; extern unsigned char const ascii_to_ebcdic[]; extern unsigned char const ascii_to_ibm[]; extern unsigned char const ebcdic_to_ascii[]; extern void translate_buffer(unsigned char *, size_t); extern void apply_translations(void); #endif /* TRANSLATE_H */ dcfldd-1.7.1/src/util.c000066400000000000000000000302451410702647300146600ustar00rootroot00000000000000/* $Id: util.c,v 1.7 2005/06/15 14:33:04 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright 85, 90, 91, 1995-2001, 2005 Free Software Foundation, Inc. Copyright 2012 Miah Gregory Copyright 2020 David Polverari 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ /* Return nonzero iff the file referenced by FDESC is of a type for which lseek's return value is known to be invalid on some systems. Otherwise, return zero. For example, return nonzero if FDESC references a character device (on any system) because the lseek on many Linux systems incorrectly returns an offset implying it succeeds for tape devices, even though the function fails to perform the requested operation. In that case, lseek should return nonzero and set errno. */ #include "dcfldd.h" #include #include #include #include #include #include "log.h" #include #include "config.h" #include #include #include "safe-read.h" int buggy_lseek_support(int fdesc) { /* We have to resort to this because on some systems, lseek doesn't work on some special files but doesn't return an error, either. In particular, the Linux tape drivers are a problem. For example, when I did the following using dd-4.0y or earlier on a Linux-2.2.17 system with an Exabyte SCSI tape drive: dev=/dev/nst0 reset='mt -f $dev rewind; mt -f $dev fsf 1' eval $reset; dd if=$dev bs=32k of=out1 eval $reset; dd if=$dev bs=32k of=out2 skip=1 the resulting files, out1 and out2, would compare equal. */ struct stat stats; return (fstat(fdesc, &stats) == 0 && (S_ISCHR(stats.st_mode))); } /* Throw away RECORDS blocks of BLOCKSIZE bytes on file descriptor FDESC, which is open with read permission for FILE. Store up to BLOCKSIZE bytes of the data at a time in BUF, if necessary. RECORDS must be nonzero. */ void skip2(int fdesc, char *file, uintmax_t records, size_t blocksize, unsigned char *buf) { off_t offset = records * blocksize; /* Try lseek and if an error indicates it was an inappropriate operation, fall back on using read. Some broken versions of lseek may return zero, so count that as an error too as a valid zero return is not possible here. */ if (offset / blocksize != records || buggy_lseek_support(fdesc) || lseek(fdesc, offset, SEEK_CUR) <= 0) { while (records--) { ssize_t nread = safe_read(fdesc, buf, blocksize); if (nread < 0) { log_info("%s: reading %s", strerror(errno), file); quit(1); } /* POSIX doesn't say what to do when dd detects it has been asked to skip past EOF, so I assume it's non-fatal. FIXME: maybe give a warning. */ if (nread == 0) break; } } } /* This is a wrapper for lseek. It detects and warns about a kernel bug that makes lseek a no-op for tape devices, even though the kernel lseek return value suggests that the function succeeded. The parameters are the same as those of the lseek function, but with the addition of FILENAME, the name of the file associated with descriptor FDESC. The file name is used solely in the warning that's printed when the bug is detected. Return the same value that lseek would have returned, but when the lseek bug is detected, return -1 to indicate that lseek failed. The offending behavior has been confirmed with an Exabyte SCSI tape drive accessed via /dev/nst0 on both Linux-2.2.17 and Linux-2.4.16. */ #ifdef __linux__ # include # include # define MT_SAME_POSITION(P, Q) \ ((P).mt_resid == (Q).mt_resid \ && (P).mt_fileno == (Q).mt_fileno \ && (P).mt_blkno == (Q).mt_blkno) static off_t skip_via_lseek(char const *filename, int fdesc, off_t offset, int whence) { struct mtget s1; struct mtget s2; int got_original_tape_position = (ioctl (fdesc, MTIOCGET, &s1) == 0); /* known bad device type */ /* && s.mt_type == MT_ISSCSI2 */ off_t new_position = lseek (fdesc, offset, whence); if (0 <= new_position && got_original_tape_position && ioctl (fdesc, MTIOCGET, &s2) == 0 && MT_SAME_POSITION (s1, s2)) { error (0, 0, _("warning: working around lseek kernel bug for file (%s)\n\ of mt_type=0x%0lx -- see for the list of types"), filename, s2.mt_type); errno = 0; new_position = -1; } return new_position; } #else # define skip_via_lseek(Filename, Fd, Offset, Whence) lseek(Fd, Offset, Whence) #endif /* Throw away RECORDS blocks of BLOCKSIZE bytes on file descriptor FDESC, which is open with read permission for FILE. Store up to BLOCKSIZE bytes of the data at a time in BUF, if necessary. RECORDS must be nonzero. If fdesc is STDIN_FILENO, advance the input offset. Return the number of records remaining, i.e., that were not skipped because EOF was reached. */ uintmax_t skip(int fdesc, char const *file, uintmax_t records, size_t blocksize, char *buf) { uintmax_t offset = records * blocksize; off_t lseekretval; /* Try lseek and if an error indicates it was an inappropriate operation -- or if the the file offset is not representable as an off_t -- fall back on using read. */ errno = 0; lseekretval = skip_via_lseek(file, fdesc, offset, SEEK_CUR); if (records <= OFF_T_MAX / blocksize && 0 <= lseekretval) { return 0; } else { int lseek_errno = errno; do { ssize_t nread = read(fdesc, buf, blocksize); if (nread < 0) { if (fdesc == STDIN_FILENO) { log_info("%s: reading %s", strerror(errno), file); if (conversions_mask & C_NOERROR) { print_stats(); continue; } } else log_info("%s: cannot seek %s", strerror(lseek_errno), file); quit(1); } if (nread == 0) break; } while (--records != 0); return records; } } void time_left(char *secstr, size_t bufsize, int seconds) { int hr = seconds / (60 * 60); int min = seconds / 60 - hr * 60; int sec = seconds - (hr * 60 * 60 + min * 60); snprintf(secstr, bufsize, "%.02d:%.02d:%.02d remaining.", hr, min, sec); } /* Swap NREAD bytes in BUF, plus possibly an initial char from the previous call. If NREAD is odd, save the last char for the next call. Return the new start of the BUF buffer. */ unsigned char *swab_buffer(unsigned char *buf, size_t *nread) { unsigned char *bufstart = buf; register unsigned char *cp; register int i; /* Is a char left from last time? */ if (char_is_saved) { *--bufstart = saved_char; (*nread)++; char_is_saved = 0; } if (*nread & 1) { /* An odd number of chars are in the buffer. */ saved_char = bufstart[--*nread]; char_is_saved = 1; } /* Do the byte-swapping by moving every second character two positions toward the end, working from the end of the buffer toward the beginning. This way we only move half of the data. */ cp = bufstart + *nread; /* Start one char past the last. */ for (i = *nread / 2; i; i--, cp -= 2) *cp = *(cp - 2); return ++bufstart; } /* Return the number of 1 bits in `i'. */ int bit_count(register unsigned int i) { register int set_bits; for (set_bits = 0; i != 0; set_bits++) i &= i - 1; return set_bits; } /* * convert escape codes (i.e. "\n") in a string * WARNING: this modifies the data pointed to by str */ void replace_escapes(char *str) { if (str == NULL) return; for (; *str != '\0'; str++) if (*str == '\\') { char *sptr; switch (*(str + 1)) { case 'n': *str++ = '\n'; break; case '\\': *str++ = '\\'; break; case 't': *str++ = '\t'; break; case 'r': *str++ = '\r'; break; default: user_error("invalid escape code \"\\%c\"", *str); } /* move all remaining chars in the string up one position */ for (sptr = str; *sptr != '\0'; sptr++) *sptr = *(sptr + 1); replace_escapes(str + 1); return; } } #if (!HAVE_DECL_STRNDUP) char *strndup(const char *str, size_t n) { char *retval; int i; if (str == NULL || n == 0) return NULL; retval = malloc(n + 1); for (i = 0; i < n; i++) retval[i] = str[i]; retval[i] = '\0'; return retval; } #endif /* !HAVE_DECL_STRNDUP */ //////////////////////////////////////////////////////// // private popen2() - in-fact this is exact copy of // newlib/libc/posix.c/popen.c with fork() instead of vfork() static struct pid { struct pid *next; FILE *fp; pid_t pid; } *pidlist; FILE * popen2(const char *program, const char *type) { struct pid *cur; FILE *iop; int pdes[2], pid; if ((*type != 'r' && *type != 'w') || (type[1] && (type[2] || (type[1] != 'b' && type[1] != 't')) )) { errno = EINVAL; return (NULL); } if ((cur = malloc(sizeof(struct pid))) == NULL) return (NULL); if (pipe(pdes) < 0) { free(cur); return (NULL); } switch (pid = fork()) { case -1: /* Error. */ (void)close(pdes[0]); (void)close(pdes[1]); free(cur); return (NULL); /* NOTREACHED */ case 0: /* Child. */ if (*type == 'r') { if (pdes[1] != STDOUT_FILENO) { (void)dup2(pdes[1], STDOUT_FILENO); (void)close(pdes[1]); } (void) close(pdes[0]); } else { if (pdes[0] != STDIN_FILENO) { (void)dup2(pdes[0], STDIN_FILENO); (void)close(pdes[0]); } (void)close(pdes[1]); } execl("/bin/sh", "sh", "-c", program, NULL); /* On cygwin32, we may not have /bin/sh. In that case, try to find sh on PATH. */ execlp("sh", "sh", "-c", program, NULL); _exit(127); /* NOTREACHED */ } /* Parent; assume fdopen can't fail. */ if (*type == 'r') { iop = fdopen(pdes[0], type); (void)close(pdes[1]); } else { iop = fdopen(pdes[1], type); (void)close(pdes[0]); } /* Link into list of file descriptors. */ cur->fp = iop; cur->pid = pid; cur->next = pidlist; pidlist = cur; return (iop); } /* * pclose -- * Pclose returns -1 if stream is not associated with a `popened' command, * if already `pclosed', or waitpid returns an error. */ int pclose2(FILE *iop) { register struct pid *cur, *last; int pstat; pid_t pid; (void)fclose(iop); /* Find the appropriate file pointer. */ for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next) if (cur->fp == iop) break; if (cur == NULL) return (-1); do { pid = waitpid(cur->pid, &pstat, 0); } while (pid == -1 && errno == EINTR); /* Remove the entry from the linked list. */ if (last == NULL) pidlist = cur->next; else last->next = cur->next; free(cur); return (pid == -1 ? -1 : pstat); } dcfldd-1.7.1/src/util.h000066400000000000000000000032551410702647300146660ustar00rootroot00000000000000/* $Id: util.h,v 1.6 2005/06/15 14:33:04 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright 85, 90, 91, 1995-2001, 2005 Free Software Foundation, Inc. Copyright 2012 Miah Gregory 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #ifndef UTIL_H #define UTIL_H #include "dcfldd.h" #include "config.h" #if HAVE_INTTYPES_H # include #endif #include #include #include extern int buggy_lseek_support(int); extern uintmax_t skip(int, char *, uintmax_t, size_t, unsigned char *); extern unsigned char *swab_buffer(unsigned char *, size_t *); extern void time_left(char *, size_t, int); extern int bit_count(register unsigned int); extern void replace_escapes(char *); extern FILE *popen2(const char *, const char *); extern int pclose2(FILE *); #if (!HAVE_DECL_STRNDUP) extern char *strndup(const char *, size_t); #endif #endif /* UTIL_H */ dcfldd-1.7.1/src/verify.c000066400000000000000000000233601410702647300152070ustar00rootroot00000000000000/* $Id: verify.c,v 1.3 2005/05/13 18:52:06 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright 85, 90, 91, 1995-2001, 2005 Free Software Foundation, Inc. Copyright 2015 Joao Eriberto Mota Filho Copyright 2019 Bernhard Übelacker 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #include "dcfldd.h" #include #include #include #include "config.h" #include "hash.h" #include "getpagesize.h" #include "safe-read.h" #include "sizeprobe.h" #include "pattern.h" #include "util.h" #include "log.h" static int verify_update(hashlist_t *, void *, void *, size_t, size_t); static void verify_remainder(hashlist_t *); /* The name of the verify file, or NULL if none. * Verify file is used as a secondary input file and the input * file is compared against it via the use of their hashes. */ char *verify_file = NULL; int verify_fd; FILE *verify_log; /* Skip this many records of `input_blocksize' bytes before reading */ uintmax_t vskip_records = 0; static int verify_update(hashlist_t *hashl, void *ibuf, void *vbuf, size_t ilen, size_t vlen) { size_t left_in_window = hash_windowlen - (bytes_in_window); int cmp = 0; if (bytes_in_total == 0) { hashl_init(hashl, TOTAL_CTX); hashl_init(hashl, VTOTAL_CTX); } if (hash_windowlen == 0) { hash_update_buf(hashl, WINDOW_CTX, TOTAL_CTX, ibuf, ilen); hash_update_buf(hashl, VWINDOW_CTX, VTOTAL_CTX, vbuf, vlen); } else { if (bytes_in_window == 0) { hashl_init(hashl, WINDOW_CTX); hashl_init(hashl, VWINDOW_CTX); } if (ilen >= left_in_window || vlen >= left_in_window) { char *ihash, *vhash; hash_update_buf(hashl, WINDOW_CTX, TOTAL_CTX, ibuf, min(ilen, left_in_window)); hash_update_buf(hashl, VWINDOW_CTX, VTOTAL_CTX, vbuf, min(vlen, left_in_window)); /* if verify ever wants to do more than one hash, change this */ hashl_final(hashl, WINDOW_CTX); ihash = strdup(hashl->hash->hashstr_buf); hashl_final(hashl, VWINDOW_CTX); vhash = hashl->hash->hashstr_buf; cmp = memcmp(ihash, vhash, hashl->hash->hashstr_buf_size); free(ihash); if (cmp != 0) { log_verifywindow(hashl->hash, window_beginning, (window_beginning + hash_windowlen), cmp); return 1; } window_beginning += hash_windowlen; bytes_in_window = 0; verify_update(hashl, ibuf + left_in_window, vbuf + left_in_window, ilen - left_in_window, vlen - left_in_window); } else { hash_update_buf(hashl, WINDOW_CTX, TOTAL_CTX, ibuf, ilen); hash_update_buf(hashl, VWINDOW_CTX, VTOTAL_CTX, vbuf, vlen); } } return 0; } static void verify_remainder(hashlist_t *hashl) { int cmp = 0; if (hash_windowlen > 0 && bytes_in_window > 0) { char *ihash, *vhash; hashl_final(hashl, WINDOW_CTX); ihash = strdup(hashl->hash->hashstr_buf); hashl_final(hashl, VWINDOW_CTX); vhash = hashl->hash->hashstr_buf; cmp = memcmp(ihash, vhash, hashl->hash->hashstr_buf_size); free(ihash); if (cmp != 0) log_verifywindow(hashl->hash, window_beginning, (window_beginning + hash_windowlen), cmp); } } /* The main loop when using the verify option. */ int dd_verify(void) { unsigned char *ibuf; /* Input buffer. */ unsigned char *vbuf; /* Verify buffer. */ unsigned char *real_ibuf; unsigned char *real_vbuf; ssize_t i_nread; /* Bytes read in the current input block. */ ssize_t v_nread; /* Bytes read in the current verify block. */ int exit_status = 0; int input_from_stream = !!input_file; int input_from_pattern = !input_from_stream; size_t page_size = getpagesize(); size_t n_bytes_read; char *i_hashstr_buf; char *v_hashstr_buf; size_t left_in_window; int mismatch = 0; int cmp = 0; real_ibuf = (unsigned char *) malloc(input_blocksize + 2 * SWAB_ALIGN_OFFSET + 2 * page_size - 1); ibuf = real_ibuf; ibuf += SWAB_ALIGN_OFFSET; /* allow space for swab */ ibuf = PTR_ALIGN(ibuf, page_size); real_vbuf = (unsigned char *) malloc(input_blocksize + 2 * SWAB_ALIGN_OFFSET + 2 * page_size - 1); vbuf = real_vbuf; vbuf += SWAB_ALIGN_OFFSET; /* allow space for swab */ vbuf = PTR_ALIGN(vbuf, page_size); i_hashstr_buf = malloc(hashstr_buf_size); v_hashstr_buf = malloc(hashstr_buf_size); if (!input_from_pattern) if (skip_records != 0) skip(STDIN_FILENO, input_file, skip_records, input_blocksize, ibuf); if (vskip_records != 0) skip(verify_fd, verify_file, vskip_records, input_blocksize, vbuf); if (max_records == 0) quit(exit_status); if (input_from_pattern) { replicate_pattern(pattern, ibuf, input_blocksize); i_nread = input_blocksize; } while (1) { /* Display an update message */ if (do_status && w_full % update_thresh == 0 && w_full != 0) { off_t total_bytes = w_full * input_blocksize; off_t total_mb = total_bytes / 1048576; if (probe == PROBE_NONE || probed_size == 0) fprintf(stderr, "\r%llu blocks (%lluMb) written.", /* [FIX] verify.c:195:25: warning: format ‘%llu’ expects argument of type ‘long long unsigned int’, but argument {3,4} has type ‘uintmax_t’ [-Wformat=] */ (long long unsigned int) w_full, (long long unsigned int) total_mb); else { time_t curr_time = time(NULL); int seconds = (int)difftime(curr_time, start_time); off_t probed_mb = probed_size / 1048576; float fprcnt = total_bytes / (float)probed_size; float fprcnt_remaining = 1.0 - fprcnt; int prcnt = (int)(fprcnt * 100); int seconds_remaining = (int)(seconds * (fprcnt_remaining / fprcnt)); char secstr[100]; time_left(secstr, sizeof secstr, seconds_remaining); fprintf(stderr, "\r[%d%% of %lluMb] %llu blocks (%lluMb) written. %s", /* [FIX] verify.c:210:25: warning: format ‘%llu’ expects argument of type ‘long long unsigned int’, but argument {4,5,6} has type ‘off_t’ [-Wformat=] */ prcnt, (long long unsigned int) probed_mb, (long long unsigned int) w_full, (long long unsigned int) total_mb, secstr); } } if (r_partial + r_full >= max_records) break; v_nread = safe_read(verify_fd, vbuf, input_blocksize); if (v_nread < 0) syscall_error(input_file); /* Zero the buffer before reading, so that if we get a read error, whatever data we are able to read is followed by zeros. This minimizes data loss. */ if (input_from_pattern) { replicate_pattern(pattern, ibuf, v_nread); i_nread = v_nread; } else i_nread = safe_read(STDIN_FILENO, ibuf, input_blocksize); if (i_nread < 0 && !input_from_pattern) syscall_error(input_file); if (i_nread == 0 && v_nread == 0) break; left_in_window = hash_windowlen - bytes_in_window; mismatch = verify_update(ihashlist, ibuf, vbuf, i_nread, v_nread); if (i_nread != v_nread || (mismatch && i_nread < left_in_window)) { log_verifywindow(ihashlist->hash, window_beginning, (window_beginning + bytes_in_window), 1); mismatch = 1; } if (mismatch) break; } free(real_ibuf); free(real_vbuf); /* verifying a remainder and total wouldnt make sense if we * they won't match due to different amounts read. */ if (!mismatch) { char *ihash, *vhash; verify_remainder(ihashlist); hashl_final(ihashlist, TOTAL_CTX); ihash = strdup(ihashlist->hash->hashstr_buf); hashl_final(ihashlist, VTOTAL_CTX); vhash = ihashlist->hash->hashstr_buf; cmp = memcmp(ihash, vhash, ihashlist->hash->hashstr_buf_size); free(ihash); if (cmp != 0) log_verifywindow(ihashlist->hash, window_beginning, (window_beginning + bytes_in_window), cmp); log_verifytotal(ihashlist->hash, cmp); } else log_verifytotal(ihashlist->hash, 1); return exit_status; } dcfldd-1.7.1/src/verify.h000066400000000000000000000024371410702647300152160ustar00rootroot00000000000000/* $Id: verify.h,v 1.3 2005/05/13 18:52:06 harbourn Exp $ * dcfldd - The Enhanced Forensic DD * By Nicholas Harbour */ /* Copyright (C) 85, 90, 91, 1995-2001, 2005 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */ #ifndef VERIFY_H #define VERIFY_H #if HAVE_INTTYPES_H # include #endif #include #include "config.h" #include "dcfldd.h" #include "hash.h" extern char *verify_file; extern int verify_fd; extern FILE *verify_log; extern uintmax_t vskip_records; extern int dd_verify(void); #endif /* VERIFY_H */ dcfldd-1.7.1/src/version-etc.c000066400000000000000000000036171410702647300161440ustar00rootroot00000000000000/* Utility to help print --version output in a consistent format. Copyright (C) 1999, 2000, 2001 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by Jim Meyering. */ #if HAVE_CONFIG_H # include #endif #include #include "version-etc.h" /* Default copyright goes to the FSF. */ char* version_etc_copyright = "Copyright (C) 1985-2006 Free Software Foundation, Inc."; /* Display the --version information the standard way. If COMMAND_NAME is NULL, the PACKAGE is asumed to be the name of the program. The formats are therefore: PACKAGE VERSION or COMMAND_NAME (PACKAGE) VERSION. */ void version_etc (FILE *stream, const char *command_name, const char *package, const char *version, const char *authors) { if (command_name) fprintf (stream, "%s (%s) %s\n", command_name, package, version); else fprintf (stream, "%s %s\n", package, version); fprintf (stream, "Written by: %s.\n", authors); putc ('\n', stream); fputs (version_etc_copyright, stream); putc ('\n', stream); fputs ("\ This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n", stream); } dcfldd-1.7.1/src/version-etc.h000066400000000000000000000023701410702647300161440ustar00rootroot00000000000000/* Utility to help print --version output in a consistent format. Copyright (C) 1999 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by Jim Meyering. */ #ifndef VERSION_ETC_H # define VERSION_ETC_H 1 # ifndef PARAMS # if defined PROTOTYPES || (defined __STDC__ && __STDC__) # define PARAMS(Args) Args # else # define PARAMS(Args) () # endif # endif extern char *version_etc_copyright; void version_etc PARAMS ((FILE *stream, const char *command_name, const char *package, const char *version, const char *authors)); #endif /* VERSION_ETC_H */ dcfldd-1.7.1/src/xalloc.h000066400000000000000000000060501410702647300151670ustar00rootroot00000000000000/* xalloc.h -- malloc with out-of-memory checking Copyright (C) 1990-1998, 1999, 2000 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef XALLOC_H_ # define XALLOC_H_ # ifndef PARAMS # if defined PROTOTYPES || (defined __STDC__ && __STDC__) # define PARAMS(Args) Args # else # define PARAMS(Args) () # endif # endif # ifndef __attribute__ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ # define __attribute__(x) # endif # endif # ifndef ATTRIBUTE_NORETURN # define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) # endif /* Exit value when the requested amount of memory is not available. It is initialized to EXIT_FAILURE, but the caller may set it to some other value. */ extern int xalloc_exit_failure; /* If this pointer is non-zero, run the specified function upon each allocation failure. It is initialized to zero. */ extern void (*xalloc_fail_func) PARAMS ((void)); /* If XALLOC_FAIL_FUNC is undefined or a function that returns, this message is output. It is translated via gettext. Its value is "memory exhausted". */ extern char const xalloc_msg_memory_exhausted[]; /* This function is always triggered when memory is exhausted. It is in charge of honoring the three previous items. This is the function to call when one wants the program to die because of a memory allocation failure. */ extern void xalloc_die PARAMS ((void)) ATTRIBUTE_NORETURN; void *xmalloc PARAMS ((size_t n)); void *xcalloc PARAMS ((size_t n, size_t s)); void *xrealloc PARAMS ((void *p, size_t n)); char *xstrdup PARAMS ((const char *str)); # define XMALLOC(Type, N_items) ((Type *) xmalloc (sizeof (Type) * (N_items))) # define XCALLOC(Type, N_items) ((Type *) xcalloc (sizeof (Type), (N_items))) # define XREALLOC(Ptr, Type, N_items) \ ((Type *) xrealloc ((void *) (Ptr), sizeof (Type) * (N_items))) /* Declare and alloc memory for VAR of type TYPE. */ # define NEW(Type, Var) Type *(Var) = XMALLOC (Type, 1) /* Free VAR only if non NULL. */ # define XFREE(Var) \ do { \ if (Var) \ free (Var); \ } while (0) /* Return a pointer to a malloc'ed copy of the array SRC of NUM elements. */ # define CCLONE(Src, Num) \ (memcpy (xmalloc (sizeof (*Src) * (Num)), (Src), sizeof (*Src) * (Num))) /* Return a malloc'ed copy of SRC. */ # define CLONE(Src) CCLONE (Src, 1) #endif /* !XALLOC_H_ */ dcfldd-1.7.1/src/xstrtol.c000066400000000000000000000132361410702647300154230ustar00rootroot00000000000000/* A more useful interface to strtol. Copyright (C) 1995, 1996, 1998-2000 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by Jim Meyering. */ #if HAVE_CONFIG_H # include #endif #ifndef __strtol # define __strtol strtol # define __strtol_t long int # define __xstrtol xstrtol #endif /* Some pre-ANSI implementations (e.g. SunOS 4) need stderr defined if assertion checking is enabled. */ #include #if STDC_HEADERS # include #endif #if HAVE_STRING_H # include #else # include # ifndef strchr # define strchr index # endif #endif #include #include #include #ifndef errno extern int errno; #endif #if HAVE_LIMITS_H # include #endif #ifndef CHAR_BIT # define CHAR_BIT 8 #endif /* The extra casts work around common compiler bugs. */ #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) /* The outer cast is needed to work around a bug in Cray C 5.0.3.0. It is necessary at least when t == time_t. */ #define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \ ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0)) #define TYPE_MAXIMUM(t) (~ (t) 0 - TYPE_MINIMUM (t)) #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) # define IN_CTYPE_DOMAIN(c) 1 #else # define IN_CTYPE_DOMAIN(c) isascii(c) #endif #define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c)) #include "xstrtol.h" #ifndef strtol long int strtol (); #endif #ifndef strtoul unsigned long int strtoul (); #endif #ifndef strtoumax uintmax_t strtoumax (); #endif static int bkm_scale (__strtol_t *x, int scale_factor) { __strtol_t product = *x * scale_factor; if (*x != product / scale_factor) return 1; *x = product; return 0; } static int bkm_scale_by_power (__strtol_t *x, int base, int power) { while (power--) if (bkm_scale (x, base)) return 1; return 0; } /* FIXME: comment. */ strtol_error __xstrtol (const char *s, char **ptr, int strtol_base, __strtol_t *val, const char *valid_suffixes) { char *t_ptr; char **p; __strtol_t tmp; assert (0 <= strtol_base && strtol_base <= 36); p = (ptr ? ptr : &t_ptr); if (! TYPE_SIGNED (__strtol_t)) { const char *q = s; while (ISSPACE ((unsigned char) *q)) ++q; if (*q == '-') return LONGINT_INVALID; } errno = 0; tmp = __strtol (s, p, strtol_base); if (errno != 0) return LONGINT_OVERFLOW; if (*p == s) return LONGINT_INVALID; /* Let valid_suffixes == NULL mean `allow any suffix'. */ /* FIXME: update all callers except the ones that allow suffixes after the number, changing last parameter NULL to `""'. */ if (!valid_suffixes) { *val = tmp; return LONGINT_OK; } if (**p != '\0') { int base = 1024; int suffixes = 1; int overflow; if (!strchr (valid_suffixes, **p)) { *val = tmp; return LONGINT_INVALID_SUFFIX_CHAR; } if (strchr (valid_suffixes, '0')) { /* The ``valid suffix'' '0' is a special flag meaning that an optional second suffix is allowed, which can change the base, e.g. "100MD" for 100 megabytes decimal. */ switch (p[0][1]) { case 'B': suffixes++; break; case 'D': base = 1000; suffixes++; break; } } switch (**p) { case 'b': overflow = bkm_scale (&tmp, 512); break; case 'B': overflow = bkm_scale (&tmp, 1024); break; case 'c': overflow = 0; break; case 'E': /* Exa */ overflow = bkm_scale_by_power (&tmp, base, 6); break; case 'G': /* Giga */ case 'g': /* 'g' is undocumented; for compatibility only */ overflow = bkm_scale_by_power (&tmp, base, 3); break; case 'k': /* kilo */ overflow = bkm_scale_by_power (&tmp, base, 1); break; case 'M': /* Mega */ case 'm': /* 'm' is undocumented; for compatibility only */ overflow = bkm_scale_by_power (&tmp, base, 2); break; case 'P': /* Peta */ overflow = bkm_scale_by_power (&tmp, base, 5); break; case 'T': /* Tera */ case 't': /* 't' is undocumented; for compatibility only */ overflow = bkm_scale_by_power (&tmp, base, 4); break; case 'w': overflow = bkm_scale (&tmp, 2); break; case 'Y': /* Yotta */ overflow = bkm_scale_by_power (&tmp, base, 8); break; case 'Z': /* Zetta */ overflow = bkm_scale_by_power (&tmp, base, 7); break; default: *val = tmp; return LONGINT_INVALID_SUFFIX_CHAR; break; } if (overflow) return LONGINT_OVERFLOW; (*p) += suffixes; } *val = tmp; return LONGINT_OK; } #ifdef TESTING_XSTRTO # include # include "error.h" char *program_name; int main (int argc, char** argv) { strtol_error s_err; int i; program_name = argv[0]; for (i=1; i%lu (%s)\n", argv[i], val, p); } else { STRTOL_FATAL_ERROR (argv[i], "arg", s_err); } } exit (0); } #endif /* TESTING_XSTRTO */ dcfldd-1.7.1/src/xstrtol.h000066400000000000000000000032351410702647300154260ustar00rootroot00000000000000#ifndef XSTRTOL_H_ # define XSTRTOL_H_ 1 # if HAVE_INTTYPES_H # include /* for uintmax_t */ # endif # ifndef PARAMS # if defined PROTOTYPES || (defined __STDC__ && __STDC__) # define PARAMS(Args) Args # else # define PARAMS(Args) () # endif # endif # ifndef _STRTOL_ERROR enum strtol_error { LONGINT_OK, LONGINT_INVALID, LONGINT_INVALID_SUFFIX_CHAR, LONGINT_OVERFLOW }; typedef enum strtol_error strtol_error; # endif # define _DECLARE_XSTRTOL(name, type) \ strtol_error \ name PARAMS ((const char *s, char **ptr, int base, \ type *val, const char *valid_suffixes)); _DECLARE_XSTRTOL (xstrtol, long int) _DECLARE_XSTRTOL (xstrtoul, unsigned long int) _DECLARE_XSTRTOL (xstrtoumax, uintmax_t) # define _STRTOL_ERROR(Exit_code, Str, Argument_type_string, Err) \ do \ { \ switch ((Err)) \ { \ case LONGINT_OK: \ abort (); \ \ case LONGINT_INVALID: \ error ((Exit_code), 0, "invalid %s `%s'", \ (Argument_type_string), (Str)); \ break; \ \ case LONGINT_INVALID_SUFFIX_CHAR: \ error ((Exit_code), 0, "invalid character following %s `%s'", \ (Argument_type_string), (Str)); \ break; \ \ case LONGINT_OVERFLOW: \ error ((Exit_code), 0, "%s `%s' too large", \ (Argument_type_string), (Str)); \ break; \ } \ } \ while (0) # define STRTOL_FATAL_ERROR(Str, Argument_type_string, Err) \ _STRTOL_ERROR (2, Str, Argument_type_string, Err) # define STRTOL_FAIL_WARN(Str, Argument_type_string, Err) \ _STRTOL_ERROR (0, Str, Argument_type_string, Err) #endif /* not XSTRTOL_H_ */ dcfldd-1.7.1/src/xstrtoul.c000066400000000000000000000002721410702647300156040ustar00rootroot00000000000000#if HAVE_CONFIG_H # include "config.h" #endif #if HAVE_DECL_STRTOUL #define __strtol strtoul #define __strtol_t unsigned long int #define __xstrtol xstrtoul #include "xstrtol.c" #endif dcfldd-1.7.1/src/xstrtoumax.c000066400000000000000000000020661410702647300161410ustar00rootroot00000000000000/* xstrtoumax.c -- A more useful interface to strtoumax. Copyright 1999 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by Paul Eggert. */ #if HAVE_CONFIG_H # include #endif #if HAVE_INTTYPES_H # include #endif #if HAVE_DECL_STRTOUMAX #define __strtol strtoumax #define __strtol_t uintmax_t #define __xstrtol xstrtoumax #include "xstrtol.c" #endif