From clauflibitFriiDump-0.5.3.1
This commit is contained in:
parent
fe937e7f4b
commit
87b108d6a1
63 changed files with 11067 additions and 26 deletions
161
CMakeLists.txt
Normal file
161
CMakeLists.txt
Normal file
|
@ -0,0 +1,161 @@
|
|||
# The name of our project is "HELLO". CMakeLists files in this project can
|
||||
# refer to the root source directory of the project as ${HELLO_SOURCE_DIR} and
|
||||
# to the root binary directory of the project as ${HELLO_BINARY_DIR}.
|
||||
project (FriiDump)
|
||||
|
||||
if (MSVC)
|
||||
# msvc2005 deprecated warnings
|
||||
add_definitions (-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
|
||||
else (MSVC)
|
||||
if (NOT WIN32)
|
||||
add_definitions (-fPIC)
|
||||
endif (NOT WIN32)
|
||||
endif (MSVC)
|
||||
|
||||
|
||||
include (TestBigEndian)
|
||||
|
||||
test_big_endian (CMAKE_WORDS_BIGENDIAN)
|
||||
|
||||
|
||||
include (CheckIncludeFiles)
|
||||
|
||||
check_include_files (stdbool.h HAVE_STDBOOL_H)
|
||||
|
||||
|
||||
include (CheckFunctionExists)
|
||||
|
||||
check_function_exists (fseeko HAVE_FSEEKO)
|
||||
check_function_exists (ftello HAVE_FTELLO)
|
||||
check_function_exists (fseek64 HAVE_FSEEK64)
|
||||
check_function_exists (ftell64 HAVE_FTELL64)
|
||||
|
||||
|
||||
include(CheckTypeSize)
|
||||
|
||||
set (CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64)
|
||||
|
||||
set (CMAKE_EXTRA_INCLUDE_FILES sys/types.h)
|
||||
check_type_size ("off_t" OFF_T)
|
||||
set (CMAKE_EXTRA_INCLUDE_FILES)
|
||||
|
||||
set (CMAKE_EXTRA_INCLUDE_FILES stdio.h)
|
||||
check_type_size ("fpos_t" FPOS_T)
|
||||
set (CMAKE_EXTRA_INCLUDE_FILES)
|
||||
|
||||
set (CMAKE_REQUIRED_DEFINITIONS)
|
||||
|
||||
|
||||
option (
|
||||
DEBUG
|
||||
"Enable debugging messages"
|
||||
OFF
|
||||
)
|
||||
|
||||
|
||||
option (
|
||||
BUILD_STATIC_BINARY
|
||||
"Build a static binary (has precedence over ALL_LIBS_SHARED)"
|
||||
OFF
|
||||
)
|
||||
|
||||
option (
|
||||
BUILD_ALL_LIBS_SHARED
|
||||
"Build all libraries as shared"
|
||||
OFF
|
||||
)
|
||||
|
||||
if (BUILD_STATIC_BINARY)
|
||||
set (libmultihash_type STATIC)
|
||||
set (libfriidump_type STATIC)
|
||||
elseif (BUILD_ALL_LIBS_SHARED)
|
||||
set (libmultihash_type SHARED)
|
||||
set (libfriidump_type SHARED)
|
||||
else (BUILD_STATIC_BINARY)
|
||||
# This is how we build libraries by default
|
||||
set (libmultihash_type STATIC)
|
||||
set (libfriidump_type SHARED)
|
||||
endif (BUILD_STATIC_BINARY)
|
||||
|
||||
|
||||
# set (CMAKE_BUILD_TYPE superoptimized)
|
||||
set (CMAKE_C_FLAGS_SUPEROPTIMIZED "-march=athlon-xp -m3dnow -O3 -funroll-all-loops")
|
||||
|
||||
set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall")
|
||||
|
||||
# set (CMAKE_BUILD_TYPE release)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
include_directories (
|
||||
${FriiDump_BINARY_DIR}
|
||||
)
|
||||
|
||||
# Recurse into the "Hello" and "Demo" subdirectories. This does not actually
|
||||
# cause another cmake executable to run. The same process will walk through
|
||||
# the project's entire directory structure.
|
||||
add_subdirectory (libmultihash)
|
||||
add_subdirectory (libfriidump)
|
||||
add_subdirectory (src)
|
||||
|
||||
|
||||
if (WIN32)
|
||||
install (FILES AUTHORS DESTINATION / RENAME Authors.txt)
|
||||
#install (CODE "exec_program (${CMAKE_CURRENT_SOURCE_DIR}/utils/unix2dos.exe ${CMAKE_OUTPUT_BINARY_DIR} ARGS Authors.txt)")
|
||||
install (FILES ChangeLog DESTINATION / RENAME ChangeLog.txt)
|
||||
install (FILES COPYING DESTINATION / RENAME Copying.txt)
|
||||
install (FILES README DESTINATION / RENAME ReadMe.txt)
|
||||
install (FILES TODO DESTINATION / RENAME ToDo.txt)
|
||||
endif (WIN32)
|
||||
|
||||
|
||||
# CPack stuff
|
||||
include (InstallRequiredSystemLibraries)
|
||||
|
||||
set (CPACK_PACKAGE_NAME "friidump")
|
||||
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Dump Nintendo GameCube/Wii discs")
|
||||
set (CPACK_PACKAGE_VENDOR "Arep")
|
||||
set (CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/docs/README")
|
||||
set (CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/docs/COPYING")
|
||||
set (CPACK_PACKAGE_VERSION_MAJOR "0")
|
||||
set (CPACK_PACKAGE_VERSION_MINOR "3")
|
||||
set (CPACK_PACKAGE_VERSION_PATCH "0")
|
||||
set (CPACK_PACKAGE_INSTALL_DIRECTORY "FriiDump ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||
set (CPACK_PACKAGE_EXECUTABLES "friidump" "FriiDump")
|
||||
|
||||
set (CPACK_SOURCE_GENERATOR "TBZ2;ZIP")
|
||||
set (CPACK_SOURCE_IGNORE_FILES
|
||||
"/CVS/"
|
||||
"/\\\\.svn/"
|
||||
"~$"
|
||||
"tags"
|
||||
"\\\\.kdevses$"
|
||||
"\\\\.kdevelop\\\\.pcs$"
|
||||
"/BUILD.*/"
|
||||
"/RELEASES/"
|
||||
"/utils/"
|
||||
"/doc.*/"
|
||||
)
|
||||
set (CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||
|
||||
if(WIN32 AND NOT UNIX)
|
||||
set (CPACK_GENERATOR "NSIS;ZIP")
|
||||
# There is a bug in NSI that does not handle full unix paths properly. Make
|
||||
# sure there is at least one set of four (4) backlasshes.
|
||||
# set (CPACK_PACKAGE_ICON "${CMake_SOURCE_DIR}/Utilities/Release\\\\InstallIcon.bmp")
|
||||
# set (CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\MyExecutable.exe")
|
||||
set (CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} installer")
|
||||
set (CPACK_NSIS_HELP_LINK "http:\\\\\\\\wii.console-tribe.com")
|
||||
set (CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.my-personal-home-page.com")
|
||||
set (CPACK_NSIS_CONTACT "arep@no.net")
|
||||
set (CPACK_NSIS_MODIFY_PATH ON)
|
||||
|
||||
set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}-Win32")
|
||||
else(WIN32 AND NOT UNIX)
|
||||
set (CPACK_GENERATOR "TBZ2")
|
||||
set (CPACK_STRIP_FILES "bin/friidump;lib/libfriidump.so.1.0.0")
|
||||
# set (CPACK_SOURCE_STRIP_FILES "")
|
||||
set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}-LinuxBin")
|
||||
endif(WIN32 AND NOT UNIX)
|
||||
|
||||
include (CPack)
|
284
Doxyfile
Normal file
284
Doxyfile
Normal file
|
@ -0,0 +1,284 @@
|
|||
# Doxyfile 1.5.1-KDevelop
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
PROJECT_NAME = FriiDump
|
||||
PROJECT_NUMBER = 0.3pre
|
||||
OUTPUT_DIRECTORY =
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
USE_WINDOWS_ENCODING = NO
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF = "The $name class" \
|
||||
"The $name widget" \
|
||||
"The $name file" \
|
||||
is \
|
||||
provides \
|
||||
specifies \
|
||||
contains \
|
||||
represents \
|
||||
a \
|
||||
an \
|
||||
the
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
DETAILS_AT_TOP = YES
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 8
|
||||
ALIASES =
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
SUBGROUPING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = NO
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_STATIC = NO
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
HIDE_UNDOC_MEMBERS = YES
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = YES
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
SHOW_INCLUDE_FILES = NO
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = NO
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = NO
|
||||
SHOW_DIRECTORIES = NO
|
||||
FILE_VERSION_FILTER =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = libfriidump \
|
||||
libmultihash
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cc \
|
||||
*.cxx \
|
||||
*.cpp \
|
||||
*.c++ \
|
||||
*.d \
|
||||
*.java \
|
||||
*.ii \
|
||||
*.ixx \
|
||||
*.ipp \
|
||||
*.i++ \
|
||||
*.inl \
|
||||
*.h \
|
||||
*.hh \
|
||||
*.hxx \
|
||||
*.hpp \
|
||||
*.h++ \
|
||||
*.idl \
|
||||
*.odl \
|
||||
*.cs \
|
||||
*.php \
|
||||
*.php3 \
|
||||
*.inc \
|
||||
*.m \
|
||||
*.mm \
|
||||
*.dox \
|
||||
*.py \
|
||||
*.C \
|
||||
*.CC \
|
||||
*.C++ \
|
||||
*.II \
|
||||
*.I++ \
|
||||
*.H \
|
||||
*.HH \
|
||||
*.H++ \
|
||||
*.CS \
|
||||
*.PHP \
|
||||
*.PHP3 \
|
||||
*.M \
|
||||
*.MM \
|
||||
*.PY \
|
||||
*.C \
|
||||
*.H \
|
||||
*.tlh \
|
||||
*.diff \
|
||||
*.patch \
|
||||
*.moc \
|
||||
*.xpm \
|
||||
*.dox
|
||||
RECURSIVE = YES
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = NO
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = YES
|
||||
REFERENCES_RELATION = YES
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = YES
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = doxygen-html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
GENERATE_HTMLHELP = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
BINARY_TOC = YES
|
||||
TOC_EXPAND = NO
|
||||
DISABLE_INDEX = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
GENERATE_TREEVIEW = YES
|
||||
TREEVIEW_WIDTH = 250
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4wide
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
PDF_HYPERLINKS = NO
|
||||
USE_PDFLATEX = NO
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_SCHEMA =
|
||||
XML_DTD =
|
||||
XML_PROGRAMLISTING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = NO
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = NO
|
||||
TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = NO
|
||||
CALLER_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MAX_DOT_GRAPH_WIDTH = 1024
|
||||
MAX_DOT_GRAPH_HEIGHT = 1024
|
||||
MAX_DOT_GRAPH_DEPTH = 1000
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to the search engine
|
||||
#---------------------------------------------------------------------------
|
||||
SEARCHENGINE = YES
|
|
@ -1,4 +0,0 @@
|
|||
friidump
|
||||
========
|
||||
|
||||
FriiDump - Dump Nintendo Wii and GameCube discs
|
42
config.h.cmake
Normal file
42
config.h.cmake
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* Define to 1 if your processor stores words with the most significant byte
|
||||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
#cmakedefine WORDS_BIGENDIAN ${CMAKE_WORDS_BIGENDIAN}
|
||||
|
||||
/* Define to 1 if stdbool.h conforms to C99. */
|
||||
#cmakedefine HAVE_STDBOOL_H 1
|
||||
|
||||
/* Debug support */
|
||||
#cmakedefine DEBUG 1
|
||||
|
||||
#cmakedefine HAVE_FSEEKO
|
||||
#cmakedefine HAVE_FTELLO
|
||||
#cmakedefine HAVE_FSEEK64
|
||||
#cmakedefine HAVE_FTELL64
|
||||
|
||||
#cmakedefine HAVE_OFF_T
|
||||
#ifdef HAVE_OFF_T
|
||||
#cmakedefine OFF_T ${OFF_T}
|
||||
#define SIZEOF_OFF_T OFF_T
|
||||
#endif
|
||||
|
||||
#cmakedefine HAVE_FPOS_T
|
||||
#ifdef HAVE_FPOS_T
|
||||
#cmakedefine FPOS_T ${FPOS_T}
|
||||
#define SIZEOF_FPOS_T FPOS_T
|
||||
#endif
|
||||
|
||||
|
||||
/* Large file support - Can't this be done better with CMake!? What about on Windows? */
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#define _LARGEFILE_SOURCE 1
|
||||
#define _LARGE_FILES
|
||||
#define HAVE_LARGEFILE_SUPPORT
|
||||
|
||||
#if defined(_FILE_OFFSET_BITS)
|
||||
# if (_FILE_OFFSET_BITS<64)
|
||||
# undef _FILE_OFFSET_BITS
|
||||
# define _FILE_OFFSET_BITS 64
|
||||
# endif
|
||||
#else
|
||||
# define _FILE_OFFSET_BITS 64
|
||||
#endif
|
41
docs/AUTHORS
Normal file
41
docs/AUTHORS
Normal file
|
@ -0,0 +1,41 @@
|
|||
FriiDump came to existance thanks to the work by a lot of people, most of which
|
||||
are probably not aware of this fact ;). So here is proper credit:
|
||||
|
||||
The DVD seed bruteforcing algorithm and code were taken from unscrambler 0.4
|
||||
by Victor Muñoz (xt5@ingenieria-inversa.cl,
|
||||
http://www.ingenieria-inversa.cl/?lp_lang_pref=en).
|
||||
|
||||
The theoritical basis of the dumping methods were suggested in several comments
|
||||
to Victor's post. The most important comments came from Victor himself (xt5),
|
||||
FuzzyLogic and svpe.
|
||||
|
||||
The code to actually perform the dumping was derived from the work of Kevin
|
||||
East, AKA SeventhSon (kev@kev.nu, http://www.kev.nu/360/), which, in turn,
|
||||
derives from work by a lot of other people. See his page for full details.
|
||||
|
||||
Many hints were taken from RawDump, whose author is unknown.
|
||||
|
||||
A program that helped me a lot to understand the drive cache behaviour is
|
||||
PLScsi by Pat LaVarre (http://members.aol.com/plscsi/).
|
||||
|
||||
Nintendo disc structure information was taken from:
|
||||
- http://www.gc-linux.org/docs/yagcd.html
|
||||
- http://www.wiili.org/index.php/GameCube_Optical_Disc
|
||||
|
||||
Code to tell whether a Wii disc contains an update or was inspired by a program
|
||||
by wiidevel@stacktic.org. Sorry but I cannot find the URL anymore :(.
|
||||
|
||||
Other minor pieces of code were taken from tcpdump (www.tcpdump.org), Python
|
||||
(www.python.org) and the glibc printf manpage.
|
||||
|
||||
GDR8163B and Windows testing was performed by tasso85.
|
||||
|
||||
Thanks also go out to the ConsoleTribe staff for giving me the possibility to
|
||||
use their forum for the program support.
|
||||
|
||||
Glue, endless hours spent understanding drive cache behaviour and rest of the
|
||||
code are by me, Arep <arep@no.net>.
|
||||
|
||||
Finally, obvious thanks go out to Nintendo for making all of their great
|
||||
consoles, who constantly help me to waste the rest of my spare time I do not
|
||||
spend coding ;).
|
|
@ -1,12 +1,12 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
|
@ -15,7 +15,7 @@ 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
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
|
@ -55,8 +55,8 @@ 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
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
|
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
|
|||
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
|
||||
|
@ -168,7 +168,7 @@ 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
|
||||
|
@ -225,7 +225,7 @@ 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
|
||||
|
@ -255,7 +255,7 @@ 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
|
||||
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
|
||||
|
@ -277,9 +277,9 @@ 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
|
||||
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
|
||||
|
@ -290,8 +290,8 @@ 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.
|
||||
|
||||
{description}
|
||||
Copyright (C) {year} {fullname}
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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
|
||||
|
@ -303,9 +303,10 @@ the "copyright" line and a pointer to where the full notice is found.
|
|||
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.
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
|
@ -329,11 +330,11 @@ 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.
|
||||
|
||||
{signature of Ty Coon}, 1 April 1989
|
||||
<signature of Ty Coon>, 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
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
45
docs/ChangeLog
Normal file
45
docs/ChangeLog
Normal file
|
@ -0,0 +1,45 @@
|
|||
0.5.3 (15/03/2010)
|
||||
- Fixed failing after 1st DL media layer with non-Hitachi methods.
|
||||
- Fixed still hashing with 'nohash' parameter when resuming.
|
||||
- Fixed resuming larger files (~4 GB).
|
||||
- Fixed unscrambling larger files.
|
||||
- Faster file unscrambling.
|
||||
- Slight modifications to methods;
|
||||
possible performance increase with Hitachi based devices.
|
||||
- Restructured methods and added some new ones.
|
||||
- Added layer break information.
|
||||
- Added current position output when error occurs.
|
||||
- Added SH-D162A, SH-D162B, SH-D162C & SH-D162D as supported.
|
||||
> Jackal, gorelord4e, themabus
|
||||
0.5.2 (10/01/2010)
|
||||
- Corrected handling of standard DVDs
|
||||
(type should be forced to 3, when dumping or unscrambling).
|
||||
- Better response to 'speed' parameter.
|
||||
- Uniform raw output for all devices: unscrambled data + headers.
|
||||
- Slight performance increase (~1650 MB/h on LH-18A1H).
|
||||
- Added LH-18A1P, LH-20A1H, LH-20A1P to list of supported devices.
|
||||
> Jackal, themabus
|
||||
0.5.1 (01/12/2009)
|
||||
- New command 'vanilla 2384'.
|
||||
- Restructured methods, some now support optional parameters.
|
||||
- Ability to select standard DVDs as source.
|
||||
- Limited recognized Lite-On drives to LH-18A1H.
|
||||
> Jackal, themabus
|
||||
0.5.0 (27/11/2009)
|
||||
- Regions: Italy, France, Germany, Spain, Australia, PAL-X, PAL-Y.
|
||||
- Updated publisher list from http://wiitdb.com/Company/HomePage
|
||||
- Included GDR8082N & GDR8161B as supported Hitachi drives.
|
||||
- Lite-On, Renesas & vanilla memory buffer access commands.
|
||||
Lite-On tested on LH-18A1H, should work on many more
|
||||
(LH*, SH, DH*, DW* & possibly other MediaTek drives)
|
||||
- Shifted methods 1..4 to 0..3 and added new ones 4..6
|
||||
Associated known drives with default methods.
|
||||
- Additional commandline parameters:
|
||||
stop, speed, command, type, size
|
||||
- Some minor changes and fixes.
|
||||
> Jackal, Truman, themabus
|
||||
0.4 (08/03/2008)
|
||||
- Support for DL Wii DVDs.
|
||||
> mado3689
|
||||
0.3 (06/10/2007)
|
||||
- First public release.
|
1
docs/INSTALL
Normal file
1
docs/INSTALL
Normal file
|
@ -0,0 +1 @@
|
|||
See README.
|
53
docs/NEWS
Normal file
53
docs/NEWS
Normal file
|
@ -0,0 +1,53 @@
|
|||
Since last official version original method 1 have been renamed to method 0
|
||||
and it undergone certain changes. Methods 2, 3, 4 have been renamed to 7, 8
|
||||
and 9 respectively. Method 0 should work with all drives as long as they
|
||||
are supported by one of memory dump commands, so if drive is unrecognized it
|
||||
is preferable to keep method at 0, and try all commands. If one of such
|
||||
combinations turns out to work, you can proceed then testing other methods
|
||||
with this commad. In case none of commands work, you could try to determine
|
||||
drive's Read Buffer command's parameters with supplied 'BruteForce3C.exe'.
|
||||
|
||||
Generally program's overall bahaviour regarding commandline haven't changed
|
||||
and you should be able to use same options as with official versions, though
|
||||
in case you were using unrecognized drive, which would nevertheless work with
|
||||
Hitachi command, you'll need to set command to 2 now (e.g. --command 2) and
|
||||
method to 7, 8 or 9.
|
||||
|
||||
Performance have increased since official release and should be now about the
|
||||
same as with 'RawDump'.
|
||||
|
||||
Regarding supported drives:
|
||||
|
||||
1. Hitachi-LG GDR8161B, GDR8162B, GDR8163B, GDR8164B, GDR8082N
|
||||
Those drives can read GC/Wii media without swapping. Expected performance is
|
||||
1600..1900 MB/h for *4B, *3B and 2100..2600 MB/h for *2B, *1B. Custom memory
|
||||
dump command is used, which returns 2064 bytes of data. It was reproted that
|
||||
they can not read other (e.g. PC) discs this way though, this needs
|
||||
confirmation.
|
||||
|
||||
2. Lite-On LH-18A1H, DVDRW LH-18A1P, DVDRW LH-20A1H, DVDRW LH-20A1P
|
||||
Reading performance for PC DVDs can go up to 5000 MB/h, which means program's
|
||||
core as well as new methods are capable to output data at least at this rate.
|
||||
Reading performance for GC was about 1600..1700 MB/h so likely this slowdown is
|
||||
caused by drive logic itself. Though I only had one GC game to test with, so
|
||||
possibly better results can be achieved depending on media. Best results were
|
||||
obtained, when using method 5 with parameter 16,27 (--method5=16,27). This
|
||||
combination isn't set as default because it can cause noticable delays
|
||||
depending on medium quality and to make methods more general for use with other
|
||||
devices. Lite-On won't read GC/Wii DVDs at all without swapping. Lite-On
|
||||
returns 2384 bytes of data (2064 + ECC) by means of vendor specific READ BUFFER
|
||||
command. Tested with models LH-18A1H, LH-18A1P and LH-20A1H.
|
||||
|
||||
3. Plextor
|
||||
Plextor would return 2064 bytes of already unscrambled data with READ BUFFER
|
||||
command. It works good with ordinary DVDs but due the lack of streamed reading
|
||||
support is practically useless for GC/Wii dumping because of very low
|
||||
performance. Works nevertheless and could be used for some experiments and
|
||||
testing. Results from PX-760A.
|
||||
|
||||
4. Toshiba Samsung SH-D162A, SH-D162B, SH-D162C, SH-D162D
|
||||
Returns 2384 data bytes per sector like Lite-On does. Appears to support
|
||||
streamed reading but performance with tested model (SH-D162D) was somewhat low
|
||||
and unstable even with ordinary DVDs. Looks promising, if only good-working
|
||||
method could be determined. Latest drives added, definitely need more testing
|
||||
at this point.
|
187
docs/README
Normal file
187
docs/README
Normal file
|
@ -0,0 +1,187 @@
|
|||
FriiDump - A program to dump Nintendo Wii and GameCube disc
|
||||
===============================================================================
|
||||
|
||||
FriiDump is a program that lets you dump Nintendo Wii and GameCube disc from
|
||||
your computer, without using original Nintendo hardware. It basically performs
|
||||
the same functions as the famous "RawDump" program, but with a big difference,
|
||||
which should be clear straight from its name: FriiDump is free software, where
|
||||
"free" is to be intended both as in "free speech" and in "free beer". As such,
|
||||
FriiDump is distributed with its sources.
|
||||
|
||||
This leads to a number of good consequences:
|
||||
- Having the sources available, it can be easily ported to different operating
|
||||
systems and hardware platforms. At the moment it is developed under a
|
||||
GNU/Linux system, but it also runs natively on Windows. A MacOS X version can
|
||||
be easily created, although I don't have a Mac, so I can't do it myself.
|
||||
- Also, having the sources and these being well-organized (I know I'm a modest
|
||||
guy) allows support for new DVD-ROM drives to be added relatively easily. At
|
||||
the moment the same drives as RawDump are supported, but this might improve
|
||||
in the future, if anyone takes the effort... See README.technical for
|
||||
details.
|
||||
- The sources might also be used as a reference for several things regarding
|
||||
Nintendo Wii/GameCube discs and the hacks used to read them on an ordinary
|
||||
drive.
|
||||
|
||||
Furthermore, FriiDump also features some functional improvements over RawDump:
|
||||
- FriiDump can use 4 different methods to read the disc, with different
|
||||
performance.
|
||||
- FriiDump dumps a lot of useful information about the discs it dumps,
|
||||
such as whether the disc contains an update or not, which can help avoid
|
||||
bricking your Wii ;).
|
||||
- FriiDump calculates the CRC32, MD4, MD5, SHA-1 and ED2K hashes of dumped
|
||||
discs, so you can immediately know if your dump is good or not, by comparing
|
||||
the hashes with the well-known ones available on several Internet sites.
|
||||
- FriiDump comes in the form of a library and a command-line front-end, which
|
||||
allows its functions to be easily reused in other programs.
|
||||
|
||||
Unfortunately, there is also a main downfall:
|
||||
- Even the fastest dump method used by FriiDump is not as fast as RawDump (but
|
||||
not that much slower, either, see the table below).
|
||||
|
||||
Anyway, I'm sure that people who cannot use RawDump (i.e.: GNU/Linux, *BSD and
|
||||
MacOS X users) will be happy anyway. Besides, you get the sources, so you can
|
||||
improve them yourself.
|
||||
|
||||
Note that FriiDump is only useful to dump *original* Nintendo discs. To dump
|
||||
backup copies you can use any DVD-dumping program (i.e.: dd under UNIX ;)).
|
||||
|
||||
FriiDump came to existance thanks to the work by a lot of people, most of which
|
||||
are probably not aware of this fact ;). Please see the AUTHORS file for the
|
||||
credits.
|
||||
|
||||
|
||||
===============================================================================
|
||||
Supported drives
|
||||
===============================================================================
|
||||
At the moment the same drives as RawDump are supported. This is due to various
|
||||
reasons, explained in the README.technical file, which also contains
|
||||
information about what is needed to add support for more drives.
|
||||
|
||||
Currently supported drives are:
|
||||
- LG GDR-8161B (untested, but should work)
|
||||
- LG GDR-8162B (ditto)
|
||||
- LG GDR-8163B (HL-DT-ST/DVD-ROM GDR8163B)
|
||||
- LG GDR-8164B (HL-DT-ST/DVD-ROM GDR8164B)
|
||||
|
||||
Other drives might work, most likely those based on the Hitachi MN103
|
||||
microcontroller. If you find any of them, please report so that they can be
|
||||
added to the compatibility list.
|
||||
|
||||
|
||||
===============================================================================
|
||||
Installation
|
||||
===============================================================================
|
||||
If you are a Windows user, probably you will have downloaded the binaries,
|
||||
either zipped or together with an installer, so the installation should be
|
||||
straightforward.
|
||||
|
||||
If you downloaded the sources, you will need to compile them. FriiDump uses
|
||||
CMake, for easy portability, so you will need to get it from cmake.org. On
|
||||
Windows you will also need a compiler like Visual Studio (the only tested one,
|
||||
so far) or CygWin/MinGW. On UNIX just do the following, from the directory
|
||||
where you unpacked the sources into:
|
||||
|
||||
$ mkdir BUILD
|
||||
$ cd BUILD
|
||||
$ cmake ..
|
||||
$ make
|
||||
$ make install
|
||||
|
||||
Linux-specific note: You need root privileges to issue certain commands to the
|
||||
DVD-ROM drive. Hence you have the following possibilities:
|
||||
- Run FriiDump as root: discouraged.
|
||||
- Run it through sudo: better but nevertheless discouraged.
|
||||
- Set the setuid bit on the executable: this is the recommended way to run
|
||||
FriiDump under Linux. This way, the code run with superuser privileges will
|
||||
be reduced to a minimum, guaranteeing a certain level of security (note that
|
||||
security-related bugs might exist anyway!!!). Also note that, even when the
|
||||
setuid bit is set, the attempt to open the drive for reading will be done
|
||||
after privileges have been dropped, so you will need explicit read access to
|
||||
the DVD-ROM drive. Usually having the system administrator add you to the
|
||||
"cdrom" group is enough. To set the setuid bit on the executable, run as
|
||||
root:
|
||||
|
||||
$ chown root:root /usr/local/bin/friidump
|
||||
$ chmod u+s /usr/local/bin/friidump
|
||||
|
||||
|
||||
===============================================================================
|
||||
Usage
|
||||
===============================================================================
|
||||
FriiDump is a command-line program, so you will need to run it from a terminal
|
||||
or a command-prompt under Windows. The basic usage is as follows:
|
||||
|
||||
friidump -d <drive> -a
|
||||
|
||||
where <drive> will usually be something like "/dev/hda" on Unix-like systems,
|
||||
and something like "e:" for Windows users. With this command, the disc will be
|
||||
dumped to an ISO image file with an automatically-chosen name. Drop -a and use
|
||||
the -i option if you prefer to specify the filename yourself. If you want to
|
||||
resume an existing dump, use -s. If you want to dump the disc to a raw format
|
||||
image file, use -r. Note that you can create a raw and an ISO image at the same
|
||||
time.
|
||||
|
||||
Other options you might want to use are -1 through -4, to set the dump method,
|
||||
although the default is method 4, which is the fastest one, so most likely you
|
||||
will not need them.
|
||||
|
||||
Finally, use -h for a listing of all available options.
|
||||
|
||||
|
||||
===============================================================================
|
||||
Performance
|
||||
===============================================================================
|
||||
As stated above, FriiDump is not as fast as RawDump. On my PC (Athlon64 3200+),
|
||||
performance is as follows:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
| Method | Dump speed | GameCube disc dump time | Wii disc dump time |
|
||||
-------------------------------------------------------------------------------
|
||||
| 1 | Too slow ;) | Eternity | More than eternity |
|
||||
| 2 | ~570 MB/h | 2.5 hours | 8 hours |
|
||||
| 3 | ~740 MB/h | 2 hours | 6 hours |
|
||||
| 4 | ~1250 MB/h | 1.2 hours | 3.5 hours |
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
===============================================================================
|
||||
Support
|
||||
===============================================================================
|
||||
I'm releasing this program under the nickname of "Arep". This is because I am
|
||||
not sure about the legal status of the program, and I do not want to encounter
|
||||
any consequences. Actually, I'm pretty sure FriiDump goes against the DMCA,
|
||||
being a program that circumvents copy-protection, but it might be objected that
|
||||
the format used by Nintendo discs is not a copy-protection method, but just
|
||||
their own, undocumented, disc format. Although, I think it can be freely used
|
||||
in Europe and other coutries without laws similar to the DMCA.
|
||||
|
||||
For the same reason, I am not putting an e-mail address here (that @no.net you
|
||||
find in the program is obviously a pun), but support will be provided through
|
||||
the forums of the Italian ConsoleTribe forum, at http://wii.console-tribe.com.
|
||||
If you need help, just open a thread in any section there, even in English: I
|
||||
will *not* reply, but you might stand assured I will read everything you write.
|
||||
FriiDump users are encouraged to help each other there ;).
|
||||
|
||||
Patches are welcome, too: just attach them to your post, and maybe put
|
||||
something like "[PATCH]" in the topic subject, so that I can easily spot them.
|
||||
|
||||
New releases will be announced on that forum, and also on QJ.net, if I find a
|
||||
good way to notify them.
|
||||
|
||||
If you want to donate to the project, do not do it, and donate to one of the
|
||||
free Wii modchip projects out there, such as OpenWii, WiiFree or YAOSM.
|
||||
|
||||
|
||||
===============================================================================
|
||||
Disclaimer
|
||||
===============================================================================
|
||||
FriiDump is distributed under the GNU General Public License version 2. See the
|
||||
COPYING file for details.
|
||||
|
||||
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.
|
||||
|
||||
Also, please note that this program is not meant to be used to spread game
|
||||
piracy, but rather to be instrument to make backups of your own precious
|
||||
legally-bought games.
|
234
docs/README.technical
Normal file
234
docs/README.technical
Normal file
|
@ -0,0 +1,234 @@
|
|||
FriiDump Techincal info
|
||||
===============================================================================
|
||||
|
||||
This document is a reworking and unification of information found all over the
|
||||
net, regarding the structure of Nintendo Gamecube/Wii Optical Discs and how to
|
||||
read them on an ordinary DVD-ROM drive. All the due credits can be found in the
|
||||
AUTHORS file.
|
||||
|
||||
|
||||
===============================================================================
|
||||
Nintendo Gamecube/Wii Optical Disc (GOD/WOD) structure
|
||||
===============================================================================
|
||||
|
||||
In order to understand how a Gamecube or WII Optical Disk is made, let us
|
||||
first take a look at a standard DVD-ROM. The complete standard is explained in
|
||||
the ECMA-267 Standard.
|
||||
|
||||
The user data stored on the DVD is divided in blocks, each 2048 bytes long.
|
||||
Each 2048-byte block is then encapsulated in a 2064-byte structure, adding some
|
||||
other data needed for error-correction and head positioning. A 2064-byte block
|
||||
is called a "Data frame", and its logical layout is as follows:
|
||||
|
||||
4bytes 2bytes 6bytes 2048bytes 4bytes
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
| ID | IED | CPR_MAI | User Data Frame | EDC |
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
- Identification Data (ID): Contains the PSN (Physical Sector Number), info
|
||||
about the sector itself, like the layer, reflectivity, zone, etc.
|
||||
- ID Error Detection Code (IED)
|
||||
- Copyright Management Information (CPR_MAI): Its use is application-specific,
|
||||
for instance it can be used to store a sector key in videos that use CSS, or
|
||||
a scrambling key in the XBox and XBox360 Security Sectors.
|
||||
- User Data: This is the data available for the end user.
|
||||
- Error Detection Code (EDC): It is the checksum data for all the fields above,
|
||||
its polinomial is x^32 + x^31 + x^4 + 1.
|
||||
|
||||
For various reasons (not related to copy protection), the User Data Frame is
|
||||
XOR'ed with a stream cipher generated by an 15bits LFSR (Linear Feedback Shift
|
||||
Register), with bits 10 and 14 used as taps. The seeds are obtained from a
|
||||
table of the ECMA-267 standard, the index of the seed is the 4 MSB of the last
|
||||
byte of the "ID" field of the Data Frame. The same stream cipher is then used
|
||||
by 16 consecutive Data Frames: for this and other reasons (again related to
|
||||
error correction), data from the DVD are always read in 16-data frame blocks.
|
||||
|
||||
4bytes 2bytes 6bytes 2048bytes 4bytes
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
| ID | IED | CPR_MAI | User Data Frame | EDC |
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
^ | 2048bytes cipher stream |
|
||||
^ - - - - - - - - - -
|
||||
Scrambling
|
||||
seed index
|
||||
|
||||
Now, the first problem when dealing with Gamecube/Wii Optical Discs is that
|
||||
they use a different (and yet unknown) set of seeds. This means that when an
|
||||
ordinary DVD-ROM drive tries to read a GOD/WOD disc, it will unscramble the
|
||||
User Data Frame with the wrong seed, causing the EDC check to fail and a read
|
||||
error to be reported to the operating system, which means the inability to read
|
||||
the disc.
|
||||
|
||||
Furthermore, Gamecube/Wii Optical Disks use a slightly different structure for
|
||||
the Data Frame, as shown in the following figure:
|
||||
|
||||
4bytes 2bytes 2048bytes 6bytes 4bytes
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
| ID | IED | User Data Frame | CPR_MAI | EDC |
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
| 2048bytes cipher stream |
|
||||
- - - - - - - - - -
|
||||
|
||||
Basically, the User Data Frame and the CPR_MAI fields are swapped, while the
|
||||
scrambled bytes remain the same.
|
||||
|
||||
|
||||
===============================================================================
|
||||
Tricks used to read a GOD/WOD on a standard DVD-ROM drive.
|
||||
===============================================================================
|
||||
To cope with the above-mentioned problems, some methods have been suggested by
|
||||
many people on the net. They vary in performance, but the basic idea is always
|
||||
the same:
|
||||
|
||||
1. Issue a read command for the sector of interest (this is actually a
|
||||
16-sector block, not a single sector, as stated above).
|
||||
2. Let the read return failure.
|
||||
3. At this moment, the DVD-ROM drive must have cached the data read from the
|
||||
disc somewhere in its internal memory, to be able to unscramble them and to
|
||||
check the EDC. So, we can dump the data from the drive's internal RAM.
|
||||
|
||||
Unfortunately, this is not as easy as it seems, due to the fact that there is
|
||||
no standard "Dump drive memory" command. This is probably implemented in many
|
||||
drives for firmware debugging purposes, but, as such, it is a vendor-specific
|
||||
command, which are usually undocumented and vary from vendor to vendor (or even
|
||||
from drive model to drive model).
|
||||
|
||||
This is where the work that many hackers around the world have done, in order
|
||||
to crack the Microsoft XBox360 console, becomes useful. They needed some way to
|
||||
read and write data to the XBox360 drive's internal memory, so they
|
||||
disassembled the drive's firmware and patiently tried to understand what each
|
||||
of the vendor-specific commands did. This way, they discovered that a certain
|
||||
command could be used to read an arbitrary portion of the drive's internal RAM.
|
||||
They also managed to map the RAM addresses, so that it is known where data
|
||||
read from the disc are temporarily stored.
|
||||
|
||||
Fortunately, the XBox360 drive is not too different from some retail DVD-ROM
|
||||
drives, namely some models from LG, which means that the discovered command
|
||||
works on them as well. Hence, we now have some sort of access to the disc data.
|
||||
|
||||
Although, this comes at the price of speed: dumping the drive's internal memory
|
||||
is a slow process, as it uses Programmed I/O (PIO) instead of Direct Memory
|
||||
Access (DMA) to transfer data from the drive to the computer's memory. For this
|
||||
reason, some have proposed the use of the "streaming read" command: it is a
|
||||
standard command thought for those applications where the constant flow of data
|
||||
is more important than its absolute correctness, such as audio or video
|
||||
applications. Thus, this command does not perform the EDC on the data read from
|
||||
the disc, but returns it immediately. Anyway, the command will only return the
|
||||
User Data Frame, which means that only a portion of the data will be read this
|
||||
way, while the rest (i.e.: the first 12 and the last 4 bytes) will have to be
|
||||
read using the memory dump method. Nevertheless, this combined method will be
|
||||
faster overall, as only some dozens of bytes have to be transfered through PIO,
|
||||
instead of the whole sectors.
|
||||
|
||||
We still have to cope with the unknown seeds. This problem can be easily solved
|
||||
through the use of brute force: as there are only 15 bits to try (and commonly
|
||||
only 17 seeds per GOD/WOD), this approach only takes about 30 seconds. The
|
||||
bruteforce process is very simple: the LFSR is seeded from 0 to 7FFFh and for
|
||||
each seed the corresponding stream cipher is generated and XOR'ed with the
|
||||
proper section of the Data Frame and the EDC is computed. If the EDC is the same
|
||||
as the one in the EDC field then we have the correct seed.
|
||||
|
||||
|
||||
===============================================================================
|
||||
The FriiDump approach
|
||||
===============================================================================
|
||||
FriiDump can use four different disc dump methods. They have been developed
|
||||
gradually, empirically and heuristically, by experimenting with the PLScsi tool
|
||||
and comparing the retrieved data with a known-good dump. In this section the
|
||||
inner working of every dump method will be described. The code implementing the
|
||||
different methods can be found in the "disc_read_sector_X" functions of disc.c.
|
||||
|
||||
Please note that the desibed behaviour is that of my LG GDR8164B drive, which I
|
||||
assume to be shared by similar drives. Other, more different drives, might
|
||||
behave differently and require totally different methods.
|
||||
|
||||
Also note that all of the methods read 16-sector blocks.
|
||||
|
||||
|
||||
Method 1
|
||||
|
||||
This method is very slow. So slow that I have never dumped a whole disc with
|
||||
it. Although, it served me to prove that I was going in the right direction and
|
||||
that my efforts could eventually come to a working end. It also showed me that
|
||||
the first versions of RawDump create bad dumps, sometimes.
|
||||
|
||||
Basically this method is the same used by those early versions of RawDump,
|
||||
which took 50+ hours to dump a whole disc. It works like this:
|
||||
|
||||
1. Issue a read command for the required sector. This will cause the 16-sector
|
||||
block to which the sector belongs to be placed at the beginning of the
|
||||
drive's cache memory. Do not even bother to see what the read command
|
||||
returns, as it will surely be a data read error.
|
||||
2. Dump the 16-sector block.
|
||||
|
||||
|
||||
Method 2
|
||||
|
||||
Method 2 is similar to method 1, but uses the above-mentioned "streaming read"
|
||||
method, which somehow allows us to dump 5 blocks at a time.
|
||||
|
||||
1. Issue a "streaming read" command for the required sector. This will cause
|
||||
the 16-sector block to which the sector belongs to be placed at the
|
||||
beginning of the drive's cache memory, together with the 4 following
|
||||
16-sector blocks. Do not bother to see what the read command returns.
|
||||
2. Dump the 5 16-sector blocks.
|
||||
|
||||
|
||||
Method 3
|
||||
|
||||
This is similar to the previous method, but instead of dumping the whole
|
||||
sectors from memory, it uses the (not EDC checked) data returned by the
|
||||
"streaming read" command. and completes it dumping only the missing bits from
|
||||
memory.
|
||||
|
||||
1. Issue a "streaming read" command for the required sector. This will cause
|
||||
the 16-sector block to which the sector belongs to be placed at the
|
||||
beginning of the drive's cache memory, together with the 4 following
|
||||
16-sector blocks.
|
||||
2. For each sector of each block, reconstruct the whole Data Frame, as follows:
|
||||
- Dump 12 bytes from memory.
|
||||
- Use 2048 bytes returned by the read command.
|
||||
- Dump 4 more bytes from memory.
|
||||
|
||||
Note that this method has a small issue, as sometimes the beginning of the
|
||||
cache will be dirty and contain invalid data, needing the sector to be read
|
||||
again. As this seems to happen quite often, we always read a dummy sector
|
||||
before the requested sector.
|
||||
|
||||
|
||||
Method 4
|
||||
|
||||
Method 4 is just method 3 with a trick to use a single dump command for every
|
||||
sector that has to be reconstructed, instead of two. It is the faster dump
|
||||
method currently supported and, as such, the default one.
|
||||
|
||||
1. Issue a "streaming read" command for the required sector. This will cause
|
||||
the 16-sector block to which the sector belongs to be placed at the
|
||||
beginning of the drive's cache memory, together with the 4 following
|
||||
16-sector blocks.
|
||||
2. For each sector of each block, reconstruct the whole Data Frame, as follows:
|
||||
- If this is the first sector of a block, dump 12 bytes from memory.
|
||||
Otherwise, use the last 12 bytes of the preceding dump.
|
||||
- Use 2048 bytes returned by the read command.
|
||||
- Dump 16 bytes from memory, and use the first 4. This leaves 12 bytes to be
|
||||
used for the reconstruction of the next sector.
|
||||
|
||||
Note that the issue of method 3 applies to this method, too.
|
||||
|
||||
|
||||
===============================================================================
|
||||
How to add support for a new drive
|
||||
===============================================================================
|
||||
If you read all the above stuff, it should be clear that, in order to add
|
||||
support for a new DVD-ROM drive, all that is needed is a way to dump the
|
||||
drive's internal memory, in particular the portion where the data read from the
|
||||
disc is cached. As explained above, this function might not be present in all
|
||||
drives, and might not be easy to find or to use. In case you manage to discover
|
||||
it, just copy the file "hitachi.c" to a new one, and modify it opportunely.
|
||||
|
||||
Some modifications will also be needed in "dvd_drive.c", in order to add
|
||||
autodetection for the new drive, in the "dvd_assign_functions" function.
|
||||
|
||||
Apart from this, the cache behaviour of the new drive might not be the same
|
||||
as that of the currently supported models, so the program architecture might
|
||||
need radical changes. In this case, please report.
|
13
docs/TODO
Normal file
13
docs/TODO
Normal file
|
@ -0,0 +1,13 @@
|
|||
- Hashes are wrongly calculated on big-endian machines. This just needs fixing
|
||||
of some #define's in the multihash library.
|
||||
- Add MacOS X-specific code. All that is needed is a way to send MMC commands
|
||||
to the DVD-ROM drive. Inspiration can be taken from the libcdio sources. If
|
||||
only I had a Mac... Same goes for *BSD, anyway.
|
||||
- Maybe write a graphical client. I will not do this as I am no GUI fanatic,
|
||||
but I am sure many Windows users will still use RawDump as it has a GUI,
|
||||
while we do not. This is actually quite easy, as the program is split into a
|
||||
library (libfriidump) and a frontend. If anybody does it, please try to make
|
||||
a portable GUI, maybe by using GTK+, qt, wxWidgets or whatever similar
|
||||
toolkit you might find.
|
||||
- Make FriiDump as fast as RawDump (i.e.: 2.5 hours for a Wii disc).
|
||||
- Improve and better document the library API.
|
64
docs/options
Normal file
64
docs/options
Normal file
|
@ -0,0 +1,64 @@
|
|||
FriiDump 0.5.3 - Copyright (C) 2007 Arep
|
||||
This software comes with ABSOLUTELY NO WARRANTY.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; see COPYING for details.
|
||||
|
||||
Official support forum: http://wii.console-tribe.com
|
||||
|
||||
Forum for this UNOFFICIAL VERSION: http://forum.redump.org
|
||||
|
||||
|
||||
Available command line options:
|
||||
|
||||
-h, --help Show this help
|
||||
-a, --autodump Dump the disc to an ISO file with an
|
||||
automatically-generated name, resuming the dump
|
||||
if possible
|
||||
-g, --gui Use more verbose output that can be easily
|
||||
parsed by a GUI frontend
|
||||
-d, --device <device> Dump disc from device <device>
|
||||
-p, --stop Instruct device to stop disc rotation
|
||||
-c, --command <nr> Force memory dump command:
|
||||
0 - vanilla 2064
|
||||
1 - vanilla 2384
|
||||
2 - Hitachi
|
||||
3 - Lite-On
|
||||
4 - Renesas
|
||||
-x, --speed <x> Set streaming speed (1, 24, 32, 64, etc.,
|
||||
where 1 = 150 KiB/s and so on)
|
||||
-T, --type <nr> Force disc type:
|
||||
0 - GameCube
|
||||
1 - Wii
|
||||
2 - Wii_DL
|
||||
3 - DVD
|
||||
-S, --size <sectors> Force disc size
|
||||
-r, --raw <file> Output to file <file> in raw format (2064-byte
|
||||
sectors)
|
||||
-i, --iso <file> Output to file <file> in ISO format (2048-byte
|
||||
sectors)
|
||||
-u, --unscramble <file> Convert (unscramble) raw image contained in
|
||||
<file> to ISO format
|
||||
-H, --nohash Do not compute CRC32/MD5/SHA-1 hashes
|
||||
for generated files
|
||||
-s, --resume Resume partial dump
|
||||
- General -----------------------------------
|
||||
-0, --method0[=<req>,<exp>] Use dumping method 0 (Optional argument
|
||||
specifies how many sectors to request from disc
|
||||
and read from cache at a time. Values should be
|
||||
separated with a comma. Default 16,16)
|
||||
- Non-Streaming -----------------------------
|
||||
-1, --method1[=<req>,<exp>] Use dumping method 1 (Default 16,16)
|
||||
-2, --method2[=<req>,<exp>] Use dumping method 2 (Default 16,16)
|
||||
-3, --method3[=<req>,<exp>] Use dumping method 3 (Default 16,16)
|
||||
- Streaming ---------------------------------
|
||||
-4, --method4[=<req>,<exp>] Use dumping method 4 (Default 27,27)
|
||||
-5, --method5[=<req>,<exp>] Use dumping method 5 (Default 27,27)
|
||||
-6, --method6[=<req>,<exp>] Use dumping method 6 (Default 27,27)
|
||||
- Hitachi -----------------------------------
|
||||
-7, --method7 Use dumping method 7 (Read and dump 5 blocks
|
||||
at a time, using streaming read)
|
||||
-8, --method8 Use dumping method 8 (Read and dump 5 blocks
|
||||
at a time, using streaming read, using DMA)
|
||||
-9, --method9 Use dumping method 9 (Read and dump 5 blocks
|
||||
at a time, using streaming read, using DMA and
|
||||
some speed tricks)
|
11
libfriidump.pc.in
Normal file
11
libfriidump.pc.in
Normal file
|
@ -0,0 +1,11 @@
|
|||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: LibFriiDump
|
||||
Description: Library to dump Nintendo GameCube/Wii discs
|
||||
Version: @VERSION@
|
||||
URL: http://wii.console-tribe.com
|
||||
Libs: -L${libdir} -lfriidump
|
||||
Cflags: -I${includedir}/libfriidump
|
105
libfriidump/CMakeLists.txt
Normal file
105
libfriidump/CMakeLists.txt
Normal file
|
@ -0,0 +1,105 @@
|
|||
# Create a library called "Hello" which includes the source file "hello.cxx".
|
||||
# The extension is already found. Any number of sources could be listed here.
|
||||
add_library (
|
||||
friidumplib
|
||||
${libfriidump_type}
|
||||
#SHARED
|
||||
#STATIC
|
||||
|
||||
brickblocker.h
|
||||
brickblocker.c
|
||||
byteorder.h
|
||||
constants.h
|
||||
disc.h
|
||||
disc.c
|
||||
dumper.h
|
||||
dumper.c
|
||||
dvd_drive.h
|
||||
dvd_drive.c
|
||||
hitachi.c
|
||||
ecma-267.h
|
||||
ecma-267.c
|
||||
lite-on.c
|
||||
misc.h
|
||||
misc.c
|
||||
renesas.c
|
||||
rs.h
|
||||
rs.c
|
||||
unscrambler.h
|
||||
unscrambler.c
|
||||
vanilla_2064.c
|
||||
vanilla_2384.c
|
||||
win32compat.h
|
||||
win32compat.c
|
||||
)
|
||||
|
||||
set_target_properties (friidumplib PROPERTIES OUTPUT_NAME "friidump")
|
||||
|
||||
include_directories (
|
||||
${FriiDump_SOURCE_DIR}/libmultihash
|
||||
)
|
||||
|
||||
# Make sure the linker can find the Hello library once it is built.
|
||||
link_directories (
|
||||
${FriiDump_BINARY_DIR}/libmultihash
|
||||
)
|
||||
|
||||
# Link the executable to the Hello library.
|
||||
target_link_libraries (
|
||||
friidumplib
|
||||
|
||||
multihashlib
|
||||
)
|
||||
|
||||
# Before making a release, the LTVERSION string should be modified.
|
||||
# The string is of the form CURRENT:REVISION:AGE.
|
||||
#
|
||||
# CURRENT (C)
|
||||
# The most recent interface number that this library implements.
|
||||
#
|
||||
# REVISION (R)
|
||||
# The implementation number that this library implements.
|
||||
#
|
||||
# AGE (A)
|
||||
# The difference between the newest and oldest interfaces that this
|
||||
# library implements. In other works, the library implements all the
|
||||
# interface numbers in the range from number 'CURRENT - AGE' to
|
||||
# 'CURRENT'.
|
||||
#
|
||||
# This means that:
|
||||
#
|
||||
# - If interfaces have been changed or added, but binary compatibility has
|
||||
# been preserved, change to C+1:0:A+1
|
||||
#
|
||||
# - If binary compatibility has been broken (eg removed or changed
|
||||
# interfaces) change to C+1:0:0
|
||||
#
|
||||
# - If the interface is the same as the previous version, change to C:R+1:A
|
||||
#
|
||||
#set_target_properties (friidumplib PROPERTIES SOVERSION 1.0.0)
|
||||
|
||||
|
||||
# Windows stuff to correctly build DLL or static library
|
||||
#get_target_property (libfriidump_type friidumplib TYPE)
|
||||
if (WIN32)
|
||||
if (libfriidump_type STREQUAL "SHARED")
|
||||
# MESSAGE ("Building libfriidump DLL")
|
||||
ADD_DEFINITIONS (-DFRIIDUMPLIB_BUILD_DLL)
|
||||
set_target_properties (friidumplib PROPERTIES DEFINE_SYMBOL FRIIDUMPLIB_EXPORTS)
|
||||
|
||||
install (
|
||||
TARGETS friidumplib
|
||||
RUNTIME DESTINATION /
|
||||
#ARCHIVE DESTINATION lib
|
||||
)
|
||||
endif (libfriidump_type STREQUAL "SHARED")
|
||||
else (WIN32)
|
||||
# Install stuff, only if a shared library is being built
|
||||
if (libfriidump_type STREQUAL "SHARED")
|
||||
install (
|
||||
TARGETS friidumplib
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib/static
|
||||
)
|
||||
endif (libfriidump_type STREQUAL "SHARED")
|
||||
endif (WIN32)
|
22
libfriidump/brickblocker.c
Normal file
22
libfriidump/brickblocker.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/* wiidevel@stacktic.org */
|
20
libfriidump/brickblocker.h
Normal file
20
libfriidump/brickblocker.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
77
libfriidump/byteorder.h
Normal file
77
libfriidump/byteorder.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "misc.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
/*************************** BYTE SWAPPING MACROS ***************************/
|
||||
// WORDS_BIGENDIAN is defined by the AC_C_BIGENDIAN autoconf macro, in case. On Windows please (un)define manually.
|
||||
#ifdef WORDS_BIGENDIAN //!< Swapping macros on big endian systems (Where host b. o. = network b. o.)
|
||||
|
||||
/* This machine's order to big endian */
|
||||
#define bo_my2big_16(a) ((u_int16_t)(a))
|
||||
#define bo_my2big_32(a) ((u_int32_t)(a))
|
||||
|
||||
/* This machine's order to little endian */
|
||||
#define bo_my2little_16(a) ( \
|
||||
((((u_int16_t) (a)) & 0x00FF) << 8) + \
|
||||
(((u_int16_t) (a)) >> 8) \
|
||||
)
|
||||
#define bo_my2little_32(a) ( \
|
||||
((((u_int32_t) (a)) & 0x000000FF) << 24) + \
|
||||
((((u_int32_t) (a)) & 0x0000FF00) << 8) + \
|
||||
((((u_int32_t) (a)) & 0x00FF0000) >> 8) + \
|
||||
(((u_int32_t) (a)) >> 24) \
|
||||
)
|
||||
#else //!< Swapping macros on little endian systems
|
||||
/* This machine's order to big endian */
|
||||
#define bo_my2big_16(a) ( \
|
||||
((((u_int16_t) (a)) & 0x00FF) << 8) + \
|
||||
(((u_int16_t) (a)) >> 8) \
|
||||
)
|
||||
#define bo_my2big_32(a) ( \
|
||||
((((u_int32_t) (a)) & 0x000000FF) << 24) + \
|
||||
((((u_int32_t) (a)) & 0x0000FF00) << 8) + \
|
||||
((((u_int32_t) (a)) & 0x00FF0000) >> 8) + \
|
||||
(((u_int32_t) (a)) >> 24) \
|
||||
)
|
||||
|
||||
/* This machine's order to little endian */
|
||||
#define bo_my2little_16(a) ((u_int16_t)(a))
|
||||
#define bo_my2little_32(a) ((u_int32_t)(a))
|
||||
#endif
|
||||
|
||||
/* These will be handy */
|
||||
/* Big endian to this machine's order */
|
||||
#define bo_big2my_16(x) bo_my2big_16(x)
|
||||
#define bo_big2my_32(x) bo_my2big_32(x)
|
||||
|
||||
/* Little endian to this machine's order */
|
||||
#define bo_little2my_16(x) bo_my2little_16(x)
|
||||
#define bo_little2my_32(x) bo_my2little_32(x)
|
||||
|
||||
/* There are the most useful ones */
|
||||
#define my_htons(x) bo_my2big_16(x)
|
||||
#define my_htonl(x) bo_my2big_32(x)
|
||||
#define my_ntohs(x) my_htons(x)
|
||||
#define my_ntohl(x) my_htonl(x)
|
||||
|
||||
/************************ END OF BYTE SWAPPING MACROS ***********************/
|
46
libfriidump/constants.h
Normal file
46
libfriidump/constants.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/*! \file
|
||||
* \brief Nintendo GameCube/Wii disc geometry constants.
|
||||
*
|
||||
* This file contains constants that describe the general layout of Nintendo GameCube/Wii discs and that can be used throughout the whole program.
|
||||
*/
|
||||
|
||||
#ifndef CONSTANTS_H_INCLUDED
|
||||
#define CONSTANTS_H_INCLUDED
|
||||
|
||||
/*! \brief Size of a scrambled sector */
|
||||
#define RAW_SECTOR_SIZE 2064
|
||||
|
||||
/*! \brief Size of an unscrambled sector */
|
||||
#define SECTOR_SIZE 2048
|
||||
|
||||
/*! \brief Number of sectors in a block */
|
||||
#define SECTORS_PER_BLOCK 16
|
||||
|
||||
/*! \brief Size of a scrambled block */
|
||||
#define RAW_BLOCK_SIZE (RAW_SECTOR_SIZE * SECTORS_PER_BLOCK)
|
||||
|
||||
/*! \brief Size of an unscrambled block */
|
||||
#define BLOCK_SIZE (SECTOR_SIZE * SECTORS_PER_BLOCK)
|
||||
|
||||
#endif
|
1675
libfriidump/disc.c
Normal file
1675
libfriidump/disc.c
Normal file
File diff suppressed because it is too large
Load diff
94
libfriidump/disc.h
Normal file
94
libfriidump/disc.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef DISC_H_INCLUDED
|
||||
#define DISC_H_INCLUDED
|
||||
|
||||
#include "misc.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
DISC_TYPE_GAMECUBE,
|
||||
DISC_TYPE_WII,
|
||||
DISC_TYPE_WII_DL,
|
||||
DISC_TYPE_DVD
|
||||
} disc_type;
|
||||
|
||||
|
||||
typedef enum {
|
||||
DISC_REGION_PAL,
|
||||
DISC_REGION_NTSC,
|
||||
DISC_REGION_JAPAN,
|
||||
DISC_REGION_AUSTRALIA,
|
||||
DISC_REGION_FRANCE,
|
||||
DISC_REGION_GERMANY,
|
||||
DISC_REGION_ITALY,
|
||||
DISC_REGION_SPAIN,
|
||||
DISC_REGION_PAL_X,
|
||||
DISC_REGION_PAL_Y,
|
||||
DISC_REGION_UNKNOWN
|
||||
} disc_region;
|
||||
|
||||
|
||||
typedef struct disc_s disc;
|
||||
|
||||
|
||||
/* Functions */
|
||||
FRIIDUMPLIB_EXPORT disc *disc_new (char *dvd_device, u_int32_t command);
|
||||
FRIIDUMPLIB_EXPORT bool disc_init (disc *d, u_int32_t forced_type, u_int32_t sectors_no);
|
||||
FRIIDUMPLIB_EXPORT void *disc_destroy (disc *d);
|
||||
FRIIDUMPLIB_EXPORT int disc_read_sector (disc *d, u_int32_t sector_no, u_int8_t **data, u_int8_t **rawdata);
|
||||
FRIIDUMPLIB_EXPORT bool disc_set_read_method (disc *d, int method);
|
||||
FRIIDUMPLIB_EXPORT void disc_set_unscrambling (disc *d, bool unscramble);
|
||||
FRIIDUMPLIB_EXPORT void disc_set_speed (disc *d, u_int32_t speed);
|
||||
FRIIDUMPLIB_EXPORT void disc_set_streaming_speed (disc *d, u_int32_t speed);
|
||||
FRIIDUMPLIB_EXPORT bool disc_stop_unit (disc *d, bool start);
|
||||
FRIIDUMPLIB_EXPORT void init_range (disc *d, u_int32_t sec_disc, u_int32_t sec_mem);
|
||||
|
||||
/* Getters */
|
||||
FRIIDUMPLIB_EXPORT u_int32_t disc_get_sectors_no (disc *d);
|
||||
FRIIDUMPLIB_EXPORT u_int32_t disc_get_layerbreak (disc *d);
|
||||
FRIIDUMPLIB_EXPORT u_int32_t disc_get_command (disc *d);
|
||||
FRIIDUMPLIB_EXPORT u_int32_t disc_get_method (disc *d);
|
||||
FRIIDUMPLIB_EXPORT u_int32_t disc_get_def_method (disc *d);
|
||||
FRIIDUMPLIB_EXPORT u_int32_t disc_get_sec_disc (disc *d);
|
||||
FRIIDUMPLIB_EXPORT u_int32_t disc_get_sec_mem (disc *d);
|
||||
|
||||
FRIIDUMPLIB_EXPORT char *disc_get_type (disc *d, disc_type *dt, char **dt_s);
|
||||
FRIIDUMPLIB_EXPORT char *disc_get_gameid (disc *d, char **gid_s);
|
||||
FRIIDUMPLIB_EXPORT char *disc_get_region (disc *d, disc_region *dr, char **dr_s);
|
||||
FRIIDUMPLIB_EXPORT char *disc_get_maker (disc *d, char **m, char **m_s);
|
||||
FRIIDUMPLIB_EXPORT char *disc_get_version (disc *d, u_int8_t *v, char **v_s);
|
||||
FRIIDUMPLIB_EXPORT char *disc_get_title (disc *d, char **t_s);
|
||||
FRIIDUMPLIB_EXPORT bool disc_get_update (disc *d);
|
||||
|
||||
FRIIDUMPLIB_EXPORT char *disc_get_drive_model_string (disc *d);
|
||||
FRIIDUMPLIB_EXPORT bool disc_get_drive_support_status (disc *d);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
439
libfriidump/dumper.c
Normal file
439
libfriidump/dumper.c
Normal file
|
@ -0,0 +1,439 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://www.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "misc.h"
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <multihash.h>
|
||||
#include "constants.h"
|
||||
#include "disc.h"
|
||||
#include "dumper.h"
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
struct dumper_s {
|
||||
disc *dsk;
|
||||
char *outfile_raw;
|
||||
u_int32_t start_sector_raw;
|
||||
FILE *fp_raw;
|
||||
char *outfile_iso;
|
||||
u_int32_t start_sector_iso;
|
||||
FILE *fp_iso;
|
||||
u_int32_t start_sector;
|
||||
bool hashing;
|
||||
bool flushing;
|
||||
|
||||
multihash hash_raw;
|
||||
multihash hash_iso;
|
||||
|
||||
progress_func progress;
|
||||
void *progress_data;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tries to open the output file for writing and to find out if it contains valid data so that the dump can continue.
|
||||
* @param dvd
|
||||
* @param outfile
|
||||
* @param[out] fp The file pointer to write to.
|
||||
* @param[out] start_sector The sector to start reading from.
|
||||
* @return true if the dumping can start/continue, false otherwise (for instance if outfile cannot be written to).
|
||||
*/
|
||||
bool dumper_set_raw_output_file (dumper *dmp, char *outfile_raw, bool resume) {
|
||||
bool out;
|
||||
my_off_t filesize;
|
||||
FILE *fp;
|
||||
|
||||
if (!outfile_raw) {
|
||||
/* Raw output disabled */
|
||||
out = true;
|
||||
dmp -> start_sector_raw = -1;
|
||||
my_free (dmp -> outfile_raw);
|
||||
dmp -> outfile_raw = NULL;
|
||||
} else if (dmp -> outfile_raw) {
|
||||
error ("Raw output file already defined");
|
||||
out = false;
|
||||
} else if (!(fp = fopen (outfile_raw, "rb"))) { /** @todo Maybe we could not open file for permission problems */
|
||||
/* Raw output file does not exist, start from scratch */
|
||||
out = true;
|
||||
dmp -> start_sector_raw = 0;
|
||||
my_strdup (dmp -> outfile_raw, outfile_raw);
|
||||
} else if (resume) {
|
||||
/* Raw output file exists and resume was requested, so see how many dumped sectors it contains */
|
||||
my_fseek (fp, 0, SEEK_END);
|
||||
filesize = my_ftell (fp);
|
||||
fclose (fp);
|
||||
out = true;
|
||||
dmp -> start_sector_raw = (u_int32_t) (filesize / RAW_SECTOR_SIZE / SECTORS_PER_BLOCK) * SECTORS_PER_BLOCK;
|
||||
debug ("Raw output can restart from sector %u", dmp -> start_sector_raw);
|
||||
my_strdup (dmp -> outfile_raw, outfile_raw);
|
||||
} else {
|
||||
/* Raw output file exists but resume was not requested, error */
|
||||
fclose (fp);
|
||||
error ("Raw output file exists, but resume was not requested.");
|
||||
out = false;
|
||||
dmp -> start_sector_raw = -1;
|
||||
my_free (dmp -> outfile_raw);
|
||||
dmp -> outfile_raw = NULL;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
bool dumper_set_iso_output_file (dumper *dmp, char *outfile_iso, bool resume) {
|
||||
bool out;
|
||||
my_off_t filesize;
|
||||
FILE *fp;
|
||||
|
||||
if (!outfile_iso) {
|
||||
/* Raw output disabled */
|
||||
out = true;
|
||||
dmp -> start_sector_iso = -1;
|
||||
my_free (dmp -> outfile_iso);
|
||||
dmp -> outfile_iso = NULL;
|
||||
} else if (dmp -> outfile_iso) {
|
||||
error ("ISO output file already defined");
|
||||
out = false;
|
||||
} else if (!(fp = fopen (outfile_iso, "rb"))) { /** @todo Maybe we could not open file for permission problems */
|
||||
/* Raw output file does not exist, start from scratch */
|
||||
out = true;
|
||||
dmp -> start_sector_iso = 0;
|
||||
my_strdup (dmp -> outfile_iso, outfile_iso);
|
||||
} else if (resume) {
|
||||
/* Raw output file exists and resume was requested, so see how many dumped sectors it contains */
|
||||
my_fseek (fp, 0, SEEK_END);
|
||||
filesize = my_ftell (fp);
|
||||
fclose (fp);
|
||||
out = true;
|
||||
dmp -> start_sector_iso = (u_int32_t) (filesize / SECTOR_SIZE / SECTORS_PER_BLOCK) * SECTORS_PER_BLOCK;
|
||||
debug ("ISO output can restart from sector %u", dmp -> start_sector_iso);
|
||||
my_strdup (dmp -> outfile_iso, outfile_iso);
|
||||
} else {
|
||||
/* Raw output file exists but resume was not requested, error */
|
||||
fclose (fp);
|
||||
error ("ISO output file exists, but resume was not requested.");
|
||||
out = false;
|
||||
dmp -> start_sector_iso = -1;
|
||||
my_free (dmp -> outfile_iso);
|
||||
dmp -> outfile_iso = NULL;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
bool dumper_prepare (dumper *dmp) {
|
||||
bool out;
|
||||
u_int8_t buf[RAW_SECTOR_SIZE];
|
||||
size_t r;
|
||||
u_int32_t i;
|
||||
|
||||
/* Outputting to both files, resume must start from the file with the least sectors. Hopefully they will have the same number of sectors, anyway... */
|
||||
if (dmp -> outfile_raw && dmp -> outfile_iso && dmp -> start_sector_raw != dmp -> start_sector_iso) {
|
||||
if (dmp -> start_sector_raw < dmp -> start_sector_iso)
|
||||
dmp -> start_sector = dmp -> start_sector_raw;
|
||||
else
|
||||
dmp -> start_sector = dmp -> start_sector_iso;
|
||||
} else if (dmp -> outfile_raw) {
|
||||
dmp -> start_sector = dmp -> start_sector_raw;
|
||||
} else if (dmp -> outfile_iso) {
|
||||
dmp -> start_sector = dmp -> start_sector_iso;
|
||||
} else {
|
||||
MY_ASSERT (0);
|
||||
}
|
||||
|
||||
/* Prepare hashes */
|
||||
if (dmp -> hashing) {
|
||||
multihash_init (&(dmp -> hash_raw));
|
||||
multihash_init (&(dmp -> hash_iso));
|
||||
}
|
||||
|
||||
/* Setup raw output file */
|
||||
if (dmp -> outfile_raw) {
|
||||
dmp -> fp_raw = fopen (dmp -> outfile_raw, "a+b");
|
||||
|
||||
if (dmp -> hashing) {
|
||||
debug ("Calculating hashes for pre-existing raw dump data");
|
||||
if (dmp -> start_sector > 0) {
|
||||
for (i = 0; i < dmp -> start_sector && (r = fread (buf, RAW_SECTOR_SIZE, 1, dmp -> fp_raw)) > 0; i++)
|
||||
multihash_update (&(dmp -> hash_raw), buf, RAW_SECTOR_SIZE);
|
||||
MY_ASSERT (r > 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now call fseek as file will only be written, from now on */
|
||||
if (my_fseek (dmp -> fp_raw, dmp -> start_sector * RAW_SECTOR_SIZE, SEEK_SET) == 0 &&
|
||||
ftruncate (fileno (dmp -> fp_raw), (int64_t) dmp -> start_sector * RAW_SECTOR_SIZE) == 0) {
|
||||
out = true;
|
||||
debug ("Writing to file \"%s\" in raw format (fseeked() to %lld)", dmp -> outfile_raw, my_ftell (dmp -> fp_raw));
|
||||
} else {
|
||||
out = false;
|
||||
fclose (dmp -> fp_raw);
|
||||
dmp -> fp_raw = NULL;
|
||||
}
|
||||
} else {
|
||||
dmp -> fp_raw = NULL;
|
||||
}
|
||||
|
||||
/* Setup ISO output file */
|
||||
if (dmp -> outfile_iso) {
|
||||
dmp -> fp_iso = fopen (dmp -> outfile_iso, "a+b");
|
||||
|
||||
if (dmp -> hashing) {
|
||||
debug ("Calculating hashes for pre-existing ISO dump data");
|
||||
if (dmp -> start_sector > 0) {
|
||||
for (i = 0; i < dmp -> start_sector && (r = fread (buf, SECTOR_SIZE, 1, dmp -> fp_iso)) > 0; i++)
|
||||
multihash_update (&(dmp -> hash_iso), buf, SECTOR_SIZE);
|
||||
MY_ASSERT (r > 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (my_fseek (dmp -> fp_iso, dmp -> start_sector * SECTOR_SIZE, SEEK_SET) == 0 &&
|
||||
ftruncate (fileno (dmp -> fp_iso), (int64_t) dmp -> start_sector * SECTOR_SIZE) == 0) {
|
||||
out = true;
|
||||
debug ("Writing to file \"%s\" in ISO format (fseeked() to %lld)", dmp -> outfile_iso, my_ftell (dmp -> fp_iso));
|
||||
} else {
|
||||
out = false;
|
||||
fclose (dmp -> fp_iso);
|
||||
dmp -> fp_iso = NULL;
|
||||
}
|
||||
} else {
|
||||
dmp -> fp_iso = NULL;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
int dumper_dump (dumper *dmp, u_int32_t *current_sector) {
|
||||
bool out;
|
||||
u_int8_t *rawbuf, *isobuf;
|
||||
u_int32_t i, sectors_no, last_sector;
|
||||
#ifdef DEBUGaa
|
||||
bool no_unscrambling;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUGaa
|
||||
no_unscrambling = dd -> no_unscrambling;
|
||||
if (fp_iso && no_unscrambling) {
|
||||
warning ("Output to ISO format requested, ignoring no_unscrambling!");
|
||||
no_unscrambling = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
sectors_no = disc_get_sectors_no (dmp -> dsk);
|
||||
#if 0
|
||||
if (dd -> start_sector != -1) {
|
||||
if (dd -> start_sector >= sectors_no) {
|
||||
error ("Cannot start dumping from sector %u as the inserted disc only has %u sectors\n", dd -> start_sector, sectors_no);
|
||||
out = false;
|
||||
} else {
|
||||
warning ("Start sector forced to %u\n", dd -> start_sector);
|
||||
ss = dd -> start_sector;
|
||||
|
||||
if (fp_iso)
|
||||
fseek (fp_iso, ss * 2048, SEEK_SET);
|
||||
if (fp_raw)
|
||||
fseek (fp_raw, ss * 2064, SEEK_SET);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (true) {
|
||||
debug ("Starting dump process from sector %u...\n", dmp -> start_sector);
|
||||
|
||||
/* First call to progress function */
|
||||
if (dmp -> progress)
|
||||
dmp -> progress (true, dmp -> start_sector, sectors_no, dmp -> progress_data);
|
||||
|
||||
last_sector=sectors_no-1;
|
||||
|
||||
for (i = dmp -> start_sector, out = true; i < sectors_no && out; i++) {
|
||||
disc_read_sector (dmp -> dsk, i, &isobuf, &rawbuf);
|
||||
|
||||
if (dmp -> fp_raw) {
|
||||
clearerr (dmp -> fp_raw);
|
||||
|
||||
if (!rawbuf) {
|
||||
error ("NULL buffer");
|
||||
out = false;
|
||||
*(current_sector) = i;
|
||||
}
|
||||
else fwrite (rawbuf, RAW_SECTOR_SIZE, 1, dmp -> fp_raw);
|
||||
if (ferror (dmp -> fp_raw)) {
|
||||
error ("fwrite() to raw output file failed");
|
||||
out = false;
|
||||
*(current_sector) = i;
|
||||
}
|
||||
|
||||
if (dmp -> flushing)
|
||||
fflush (dmp -> fp_raw);
|
||||
|
||||
if (dmp -> hashing && out)
|
||||
multihash_update (&(dmp -> hash_raw), rawbuf, RAW_SECTOR_SIZE);
|
||||
}
|
||||
|
||||
if (dmp -> fp_iso) {
|
||||
clearerr (dmp -> fp_iso);
|
||||
|
||||
if (!isobuf) {
|
||||
error ("NULL buffer");
|
||||
out = false;
|
||||
*(current_sector) = i;
|
||||
}
|
||||
else fwrite (isobuf, SECTOR_SIZE, 1, dmp -> fp_iso);
|
||||
|
||||
if (ferror (dmp -> fp_iso)) {
|
||||
error ("fwrite() to ISO output file failed");
|
||||
out = false;
|
||||
*(current_sector) = i;
|
||||
}
|
||||
|
||||
if (dmp -> flushing)
|
||||
fflush (dmp -> fp_iso);
|
||||
|
||||
if (dmp -> hashing && out)
|
||||
multihash_update (&(dmp -> hash_iso), isobuf, SECTOR_SIZE);
|
||||
}
|
||||
|
||||
if ((i % 320 == 0) || (i == last_sector)) { //speedhack
|
||||
if (dmp -> progress)
|
||||
dmp -> progress (false, i + 1, sectors_no, dmp -> progress_data); /* i + 1 'cause sectors range from 0 to N */
|
||||
}
|
||||
}
|
||||
|
||||
if (dmp -> hashing) {
|
||||
multihash_finish (&(dmp -> hash_raw));
|
||||
multihash_finish (&(dmp -> hash_iso));
|
||||
}
|
||||
|
||||
if (dmp -> fp_raw)
|
||||
fclose (dmp -> fp_raw);
|
||||
if (dmp -> fp_iso)
|
||||
fclose (dmp -> fp_iso);
|
||||
if (out) {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
dumper *dumper_new (disc *d) {
|
||||
dumper *dmp;
|
||||
|
||||
dmp = (dumper *) malloc (sizeof (dumper));
|
||||
memset (dmp, 0, sizeof (dumper));
|
||||
dmp -> dsk = d;
|
||||
dumper_set_hashing (dmp, true);
|
||||
dumper_set_flushing (dmp, true);
|
||||
|
||||
return (dmp);
|
||||
}
|
||||
|
||||
|
||||
void dumper_set_progress_callback (dumper *dmp, progress_func progress, void *progress_data) {
|
||||
dmp -> progress = progress;
|
||||
dmp -> progress_data = progress_data;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void dumper_set_hashing (dumper *dmp, bool h) {
|
||||
dmp -> hashing = h;
|
||||
debug ("Hashing %s", h ? "enabled" : "disabled");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void dumper_set_flushing (dumper *dmp, bool f) {
|
||||
dmp -> flushing = f;
|
||||
debug ("Flushing %s", f ? "enabled" : "disabled");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void *dumper_destroy (dumper *dmp) {
|
||||
my_free (dmp -> outfile_raw);
|
||||
my_free (dmp -> outfile_iso);
|
||||
my_free (dmp);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_iso_crc32 (dumper *dmp) {
|
||||
return ((dmp -> hash_iso).crc32_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_raw_crc32 (dumper *dmp) {
|
||||
return ((dmp -> hash_raw).crc32_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_iso_md4 (dumper *dmp) {
|
||||
return ((dmp -> hash_iso).md4_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_raw_md4 (dumper *dmp) {
|
||||
return ((dmp -> hash_raw).md4_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_iso_md5 (dumper *dmp) {
|
||||
return ((dmp -> hash_iso).md5_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_raw_md5 (dumper *dmp) {
|
||||
return ((dmp -> hash_raw).md5_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_iso_ed2k (dumper *dmp) {
|
||||
return ((dmp -> hash_iso).ed2k_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_raw_ed2k (dumper *dmp) {
|
||||
return ((dmp -> hash_raw).ed2k_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_iso_sha1 (dumper *dmp) {
|
||||
return ((dmp -> hash_iso).sha1_s);
|
||||
}
|
||||
|
||||
|
||||
char *dumper_get_raw_sha1 (dumper *dmp) {
|
||||
return ((dmp -> hash_raw).sha1_s);
|
||||
}
|
60
libfriidump/dumper.h
Normal file
60
libfriidump/dumper.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://www.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef DUMPER_H_INCLUDED
|
||||
#define DUMPER_H_INCLUDED
|
||||
|
||||
#include "misc.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct dumper_s dumper;
|
||||
|
||||
typedef void (*progress_func) (bool start, u_int32_t current_sector, u_int32_t total_sectors, void *progress_data);
|
||||
|
||||
FRIIDUMPLIB_EXPORT bool dumper_set_raw_output_file (dumper *dmp, char *outfile_raw, bool resume);
|
||||
FRIIDUMPLIB_EXPORT bool dumper_set_iso_output_file (dumper *dmp, char *outfile_iso, bool resume);
|
||||
FRIIDUMPLIB_EXPORT bool dumper_prepare (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT int dumper_dump (dumper *dmp, u_int32_t *current_sector);
|
||||
FRIIDUMPLIB_EXPORT dumper *dumper_new (disc *d);
|
||||
FRIIDUMPLIB_EXPORT void dumper_set_progress_callback (dumper *dmp, progress_func progress, void *progress_data);
|
||||
FRIIDUMPLIB_EXPORT void dumper_set_hashing (dumper *dmp, bool h);
|
||||
FRIIDUMPLIB_EXPORT void dumper_set_flushing (dumper *dmp, bool f);
|
||||
FRIIDUMPLIB_EXPORT void *dumper_destroy (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_iso_crc32 (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_raw_crc32 (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_iso_md4 (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_raw_md4 (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_iso_md5 (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_raw_md5 (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_iso_ed2k (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_raw_ed2k (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_iso_sha1 (dumper *dmp);
|
||||
FRIIDUMPLIB_EXPORT char *dumper_get_raw_sha1 (dumper *dmp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
755
libfriidump/dvd_drive.c
Normal file
755
libfriidump/dvd_drive.c
Normal file
|
@ -0,0 +1,755 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/*! \file
|
||||
* \brief A class to send raw MMC commands to a CD/DVD-ROM drive.
|
||||
*
|
||||
* This class can be used to send raw MMC commands to a CD/DVD-ROM drive. It uses own structures and data types to represent the commands, which are
|
||||
* then transformed in the proper OS-dependent structures when the command is executed, achieving portability. Currently Linux and Windows are supported, but
|
||||
* all that is needed to add support to a new OS is a proper <code>dvd_execute_cmd()</code> function, so it should be very easy. I hope that someone can add
|
||||
* compatibility with MacOS X and *BSD: libcdio is a good place to understand how it should be done :). Actally, we could have used libcdio right from the start,
|
||||
* but I didn't want to add a dependency on a library that cannot be easily found in binary format for all the target OS's.
|
||||
*
|
||||
* This file contains code derived from the work of Kevin East (SeventhSon), kev@kev.nu, http://www.kev.nu/360/ , which, in turn, derives from work by
|
||||
* a lot of other people. See his page for full details.
|
||||
*/
|
||||
|
||||
#include "rs.h"
|
||||
#include "misc.h"
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
//#include <sys/time.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include "dvd_drive.h"
|
||||
#include "disc.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <ntddscsi.h>
|
||||
#else
|
||||
#include <linux/cdrom.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
/*! \brief Timeout for MMC commands.
|
||||
*
|
||||
* This must be expressed in seconds (Windows uses seconds, right?).
|
||||
*/
|
||||
#define MMC_CMD_TIMEOUT 10
|
||||
|
||||
|
||||
/* Imported drive-specific functions */
|
||||
int vanilla_2064_dvd_dump_mem (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
|
||||
int vanilla_2384_dvd_dump_mem (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
|
||||
int hitachi_dvd_dump_mem (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
|
||||
int liteon_dvd_dump_mem (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
|
||||
int renesas_dvd_dump_mem (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
|
||||
|
||||
|
||||
/*! \brief A structure that represents a CD/DVD-ROM drive.
|
||||
*/
|
||||
struct dvd_drive_s {
|
||||
/* Device special file */
|
||||
char *device; //!< The path to the drive (i.e.: /dev/something on Unix, x: on Windows).
|
||||
|
||||
/* Data about the drive */
|
||||
char *vendor; //!< The drive vendor.
|
||||
char *prod_id; //!< The drive product ID.
|
||||
char *prod_rev; //!< The drive product revision (Usually firmware version).
|
||||
char *model_string; //!< The above three strings, joined in a single one.
|
||||
u_int32_t def_method;
|
||||
u_int32_t command;
|
||||
|
||||
/* Device-dependent internal memory dump function */
|
||||
/*! The intended area should start where sector data is stored upon a READ command. Here we assume that sectors are
|
||||
* stored one after the other, as heuristics showed it is the case for the Hitachi MN103-based drives, but this model
|
||||
* might be changed in the future, if we get support for other drives.
|
||||
*/
|
||||
dvd_drive_memdump_func memdump; //!< A pointer to a function that is able to dump the drive's internal memory area.
|
||||
bool supported; //!< True if the drive is a supported model, false otherwise.
|
||||
|
||||
|
||||
/* File descriptor & stuff used to access drive */
|
||||
#ifdef WIN32
|
||||
HANDLE fd; //!< The HANDLE to interact with the drive on Windows.
|
||||
#else
|
||||
int fd; //!< The file descriptor to interact with the drive on Unix.
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/** \brief Supported MMC commands.
|
||||
*/
|
||||
enum mmc_commands_e {
|
||||
SPC_INQUIRY = 0x12,
|
||||
MMC_READ_12 = 0xA8,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initializes a structure representing an MMC command.
|
||||
* @param mmc A pointer to the MMC command structure.
|
||||
* @param buf The buffer where results of the MMC command execution provided by the drive should be stored, or NULL if no buffer will be provided.
|
||||
* @param len The length of the buffer (ignored in case buf is NULL).
|
||||
* @param sense A pointer to a structure which will hold the SENSE DATA got from the drive after the command has been executed, or NULL.
|
||||
*/
|
||||
void dvd_init_command (mmc_command *mmc, u_int8_t *buf, int len, req_sense *sense) {
|
||||
memset (mmc, 0, sizeof (mmc_command));
|
||||
if (buf)
|
||||
memset (buf, 0, len);
|
||||
mmc -> buffer = buf;
|
||||
mmc -> buflen = buf ? len : 0;
|
||||
mmc -> sense = sense;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
/* Doc is under the UNIX function */
|
||||
int dvd_execute_cmd (dvd_drive *dvd, mmc_command *mmc, bool ignore_errors) {
|
||||
SCSI_PASS_THROUGH_DIRECT *sptd;
|
||||
unsigned char sptd_sense[sizeof (*sptd) + 18], *sense;
|
||||
DWORD bytes;
|
||||
int out;
|
||||
|
||||
sptd = (SCSI_PASS_THROUGH_DIRECT *) sptd_sense;
|
||||
sense = &sptd_sense[sizeof (*sptd)];
|
||||
|
||||
memset (sptd, 0, sizeof (sptd_sense));
|
||||
memcpy (sptd -> Cdb, mmc -> cmd, sizeof (mmc -> cmd));
|
||||
sptd -> Length = sizeof (SCSI_PASS_THROUGH);
|
||||
sptd -> CdbLength = 12;
|
||||
sptd -> SenseInfoLength = 18;
|
||||
sptd -> DataIn = SCSI_IOCTL_DATA_IN;
|
||||
sptd -> DataBuffer = mmc -> buffer;
|
||||
// Quick hack: Windows hates sptd->DataTransferLength = 1, so we set it to 2 and ignore the second byte.
|
||||
if (mmc -> buflen == 1) // TODO
|
||||
sptd -> DataTransferLength = 2;
|
||||
else
|
||||
sptd -> DataTransferLength = mmc -> buflen;
|
||||
sptd -> TimeOutValue = MMC_CMD_TIMEOUT;
|
||||
sptd -> SenseInfoOffset = sizeof (*sptd);
|
||||
|
||||
//fprintf (stdout,"mmc->cmd[00] = %d \n",mmc->cmd[00]);
|
||||
//Set streaming hack
|
||||
if (mmc->cmd[00]==0xB6) {
|
||||
sptd -> DataIn = SCSI_IOCTL_DATA_OUT;
|
||||
sptd -> DataTransferLength = 28;
|
||||
}
|
||||
|
||||
if (!DeviceIoControl (dvd -> fd, IOCTL_SCSI_PASS_THROUGH_DIRECT, sptd, sizeof (*sptd) + 18, sptd, sizeof (*sptd) + 18, &bytes, NULL) && !ignore_errors) {
|
||||
out = -1; /* Failure */
|
||||
error ("Execution of MMC command failed: %s", strerror (errno));
|
||||
// error ("DeviceIOControl() failed with %d\n", GetLastError());
|
||||
debug ("Command was: ");
|
||||
hex_and_ascii_print ("", mmc -> cmd, sizeof (mmc -> cmd));
|
||||
debug ("Sense data: %02X/%02X/%02X\n", sense[2] & 0x0F, sense[12], sense[13]);
|
||||
} else {
|
||||
out = 0;
|
||||
}
|
||||
|
||||
if (mmc -> sense) {
|
||||
mmc -> sense -> sense_key = sense[2];
|
||||
mmc -> sense -> asc = sense[12];
|
||||
mmc -> sense -> ascq = sense[13];
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* Executes an MMC command.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param mmc The command to be executed.
|
||||
* @param ignore_errors If set to true, no error will be printed if the command fails.
|
||||
* @return 0 if the command was executed successfully, < 0 otherwise.
|
||||
*/
|
||||
int dvd_execute_cmd (dvd_drive *dvd, mmc_command *mmc, bool ignore_errors) {
|
||||
int out;
|
||||
struct cdrom_generic_command cgc;
|
||||
struct request_sense sense;
|
||||
|
||||
#if 0
|
||||
debug ("Executing MMC command: ");
|
||||
hex_and_ascii_print ("", mmc -> cmd, sizeof (mmc -> cmd));
|
||||
#endif
|
||||
|
||||
/* Init Linux-format MMC command */
|
||||
memset (&cgc, 0, sizeof (struct cdrom_generic_command));
|
||||
memcpy (cgc.cmd, mmc -> cmd, sizeof (mmc -> cmd));
|
||||
cgc.buffer = (unsigned char *) mmc -> buffer;
|
||||
cgc.buflen = mmc -> buflen;
|
||||
cgc.data_direction = CGC_DATA_READ;
|
||||
cgc.timeout = MMC_CMD_TIMEOUT * 1000; /* Linux uses milliseconds */
|
||||
cgc.sense = &sense;
|
||||
if (ioctl (dvd -> fd, CDROM_SEND_PACKET, &cgc) < 0 && !ignore_errors) {
|
||||
out = -1; /* Failure */
|
||||
error ("Execution of MMC command failed: %s", strerror (errno));
|
||||
debug ("Command was:");
|
||||
hex_and_ascii_print ("", cgc.cmd, sizeof (cgc.cmd));
|
||||
debug ("Sense data: %02X/%02X/%02X", sense.sense_key, sense.asc, sense.ascq);
|
||||
} else {
|
||||
out = 0;
|
||||
}
|
||||
|
||||
if (mmc -> sense) {
|
||||
mmc -> sense -> sense_key = sense.sense_key;
|
||||
mmc -> sense -> asc = sense.asc;
|
||||
mmc -> sense -> ascq = sense.ascq;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Sends an INQUIRY command to the drive to retrieve drive identification strings.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @return 0 if the command was executed successfully, < 0 otherwise.
|
||||
*/
|
||||
static int dvd_get_drive_info (dvd_drive *dvd) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t buf[36];
|
||||
char tmp[36 * 4];
|
||||
|
||||
dvd_init_command (&mmc, buf, sizeof (buf), NULL);
|
||||
mmc.cmd[0] = SPC_INQUIRY;
|
||||
mmc.cmd[4] = sizeof (buf);
|
||||
if ((out = dvd_execute_cmd (dvd, &mmc, false)) >= 0) {
|
||||
my_strndup (dvd -> vendor, buf + 8, 8);
|
||||
strtrimr (dvd -> vendor);
|
||||
my_strndup (dvd -> prod_id, buf + 16, 16);
|
||||
strtrimr (dvd -> prod_id);
|
||||
my_strndup (dvd -> prod_rev, buf + 32, 4);
|
||||
strtrimr (dvd -> prod_rev);
|
||||
snprintf (tmp, sizeof (tmp), "%s/%s/%s", dvd -> vendor, dvd -> prod_id, dvd -> prod_rev);
|
||||
my_strdup (dvd -> model_string, tmp);
|
||||
|
||||
debug ("DVD drive is \"%s\"", dvd -> model_string);
|
||||
} else {
|
||||
error ("Cannot identify DVD drive\n");
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assigns the proper memory dump functions to a dvd_drive object, according to vendor, model and other parameters. Actually this scheme probably needs to
|
||||
* to be improved, but it is enough for the moment.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
*/
|
||||
static void dvd_assign_functions (dvd_drive *dvd, u_int32_t command) {
|
||||
dvd -> def_method = 0;
|
||||
if (strcmp (dvd -> vendor, "HL-DT-ST") == 0 && (
|
||||
// strcmp (dvd -> prod_id, "DVDRAM GSA-T10N") == 0 ||
|
||||
strcmp (dvd -> prod_id, "DVD-ROM GDR8082N") == 0 ||
|
||||
strcmp (dvd -> prod_id, "DVD-ROM GDR8161B") == 0 ||
|
||||
strcmp (dvd -> prod_id, "DVD-ROM GDR8162B") == 0 ||
|
||||
strcmp (dvd -> prod_id, "DVD-ROM GDR8163B") == 0 ||
|
||||
strcmp (dvd -> prod_id, "DVD-ROM GDR8164B") == 0
|
||||
)) {
|
||||
debug ("Hitachi MN103-based DVD drive detected, using Hitachi memory dump command");
|
||||
dvd -> memdump = &hitachi_dvd_dump_mem;
|
||||
dvd -> command = 2;
|
||||
dvd -> supported = true;
|
||||
dvd -> def_method = 9;
|
||||
|
||||
} else if (strcmp (dvd -> vendor, "LITE-ON") == 0 && (
|
||||
strcmp (dvd ->prod_id, "DVDRW LH-18A1H") == 0 ||
|
||||
strcmp (dvd ->prod_id, "DVDRW LH-18A1P") == 0 ||
|
||||
strcmp (dvd ->prod_id, "DVDRW LH-20A1H") == 0 ||
|
||||
strcmp (dvd ->prod_id, "DVDRW LH-20A1P") == 0
|
||||
)) {
|
||||
debug ("Lite-On DVD drive detected, using Lite-On memory dump command");
|
||||
dvd -> memdump = &liteon_dvd_dump_mem;
|
||||
dvd -> command = 3;
|
||||
dvd -> supported = true;
|
||||
dvd -> def_method = 5;
|
||||
|
||||
} else if (strcmp (dvd -> vendor, "TSSTcorp") == 0 && (
|
||||
strcmp (dvd ->prod_id, "DVD-ROM SH-D162A") == 0 ||
|
||||
strcmp (dvd ->prod_id, "DVD-ROM SH-D162B") == 0 ||
|
||||
strcmp (dvd ->prod_id, "DVD-ROM SH-D162C") == 0 ||
|
||||
strcmp (dvd ->prod_id, "DVD-ROM SH-D162D") == 0
|
||||
)) {
|
||||
debug ("Toshiba Samsung DVD drive detected, using vanilla 2384 memory dump command");
|
||||
dvd -> memdump = &vanilla_2384_dvd_dump_mem;
|
||||
dvd -> command = 1;
|
||||
dvd -> supported = true;
|
||||
dvd -> def_method = 0;
|
||||
|
||||
} else if (strcmp (dvd -> vendor, "PLEXTOR") == 0) {
|
||||
debug ("Plextor DVD drive detected, using vanilla 2064 memory dump command");
|
||||
dvd -> memdump = &vanilla_2064_dvd_dump_mem;
|
||||
dvd -> command = 0;
|
||||
dvd -> supported = true;
|
||||
dvd -> def_method = 2;
|
||||
|
||||
} else {
|
||||
/* This is an unsupported drive (yet). */
|
||||
dvd -> memdump = &vanilla_2064_dvd_dump_mem;
|
||||
dvd -> command = 0;
|
||||
dvd -> supported = false;
|
||||
}
|
||||
|
||||
if (command!=-1) {
|
||||
dvd -> command = command;
|
||||
if (command == 0) dvd -> memdump = &vanilla_2064_dvd_dump_mem;
|
||||
else if (command == 1) dvd -> memdump = &vanilla_2384_dvd_dump_mem;
|
||||
else if (command == 2) dvd -> memdump = &hitachi_dvd_dump_mem;
|
||||
else if (command == 3) dvd -> memdump = &liteon_dvd_dump_mem;
|
||||
else if (command == 4) dvd -> memdump = &renesas_dvd_dump_mem;
|
||||
}
|
||||
|
||||
//init Reed-Solomon for Lite-On
|
||||
generate_gf();
|
||||
gen_poly();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new structure representing a CD/DVD-ROM drive.
|
||||
* @param device The CD/DVD-ROM device, in OS-dependent format (i.e.: /dev/something on Unix, x: on Windows).
|
||||
* @return The newly-created structure, to be used with the other commands, or NULL if the drive could not be initialized.
|
||||
*/
|
||||
dvd_drive *dvd_drive_new (char *device, u_int32_t command) {
|
||||
dvd_drive *dvd;
|
||||
#ifdef WIN32
|
||||
HANDLE fd;
|
||||
char dev[40];
|
||||
#else
|
||||
int fd;
|
||||
#endif
|
||||
|
||||
/* Force the dropping of privileges: in our model, privileges are only used to execute memory dump commands, the user
|
||||
must gain access to the device somehow else (i. e. get added to the "cdrom" group or similar things) */
|
||||
drop_euid ();
|
||||
|
||||
debug ("Trying to open DVD device %s", device);
|
||||
#ifdef WIN32
|
||||
sprintf (dev, "\\\\.\\%c:", device[0]);
|
||||
if ((fd = CreateFile (dev, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) {
|
||||
error ("Cannot open drive: %d", GetLastError ());
|
||||
#else
|
||||
if ((fd = open (device, O_RDONLY | O_NONBLOCK)) < 0) {
|
||||
perror ("Cannot open drive");
|
||||
#endif
|
||||
dvd = NULL;
|
||||
} else {
|
||||
debug ("Opened successfully");
|
||||
drop_euid ();
|
||||
dvd = (dvd_drive *) malloc (sizeof (dvd_drive));
|
||||
my_strdup (dvd -> device, device);
|
||||
dvd -> fd = fd;
|
||||
dvd_get_drive_info (dvd);
|
||||
dvd_assign_functions (dvd, command);
|
||||
}
|
||||
|
||||
return (dvd);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees resources used by a DVD drive structure and destroys it.
|
||||
* @param dvd The DVD drive structure to be destroyed.
|
||||
* @return NULL.
|
||||
*/
|
||||
void *dvd_drive_destroy (dvd_drive *dvd) {
|
||||
if (dvd) {
|
||||
#ifdef WIN32
|
||||
CloseHandle (dvd -> fd);
|
||||
#else
|
||||
close (dvd -> fd);
|
||||
#endif
|
||||
my_free (dvd -> device);
|
||||
my_free (dvd -> vendor);
|
||||
my_free (dvd -> prod_id);
|
||||
my_free (dvd -> prod_rev);
|
||||
my_free (dvd);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes the drive-dependent function to dump the drive sector cache, and returns the dumped data.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param block_off The offset to start dumping, WRT the beginning of the sector cache.
|
||||
* @param block_len The number of blocks to dump.
|
||||
* @param block_size The block size to be used for dumping.
|
||||
* @param buf A buffer where to store the dumped data. Note that this must be able to hold at least block_len * block_size bytes.
|
||||
* @return 0 if the command was executed successfully, < 0 otherwise.
|
||||
*/
|
||||
int dvd_memdump (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
|
||||
int out;
|
||||
|
||||
/* Upgrade privileges and call actual dump functions */
|
||||
upgrade_euid ();
|
||||
out = dvd -> memdump (dvd, block_off, block_len, block_size, buf);
|
||||
drop_euid ();
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Issues a READ(12) command without bothering to return the results. Uses the FUA (Force Unit Access bit) so that the requested sectors are actually read
|
||||
* at the beginning of the cache and can be dumped later.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param sector The sector to be read. What will be cached is the 16-sectors block to which the sector belongs.
|
||||
* @param sense A pointer to a structure which will hold the SENSE DATA got from the drive after the command has been executed.
|
||||
* @return 0 if the command was executed successfully, < 0 otherwise.
|
||||
*/
|
||||
int dvd_read_sector_dummy (dvd_drive *dvd, u_int32_t sector, u_int32_t sectors, req_sense *sense, u_int8_t *extbuf, size_t extbufsize) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t intbuf[64 * 1024], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
/* We need some buffer, be it provided externally or not */
|
||||
if (extbuf) {
|
||||
buf = extbuf;
|
||||
bufsize = extbufsize;
|
||||
} else {
|
||||
buf = intbuf;
|
||||
bufsize = sizeof (intbuf);
|
||||
}
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[0] = MMC_READ_12;
|
||||
mmc.cmd[1] = 0x08; /* FUA bit set */
|
||||
mmc.cmd[2] = (u_int8_t) ((sector & 0xFF000000) >> 24); /* LBA from MSB to LSB */
|
||||
mmc.cmd[3] = (u_int8_t) ((sector & 0x00FF0000) >> 16);
|
||||
mmc.cmd[4] = (u_int8_t) ((sector & 0x0000FF00) >> 8);
|
||||
mmc.cmd[5] = (u_int8_t) (sector & 0x000000FF);
|
||||
mmc.cmd[6] = (u_int8_t) ((sectors & 0xFF000000) >> 24); /* Size from MSB to LSB */
|
||||
mmc.cmd[7] = (u_int8_t) ((sectors & 0x00FF0000) >> 16);
|
||||
mmc.cmd[8] = (u_int8_t) ((sectors & 0x0000FF00) >> 8);
|
||||
mmc.cmd[9] = (u_int8_t) (sectors & 0x000000FF);
|
||||
out = dvd_execute_cmd (dvd, &mmc, true); /* Ignore errors! */
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Issues a READ(12) command using the STREAMING bit, which causes the requested 16-sector block to be read into memory,
|
||||
* together with the following four. This way we will be able to dump 5 sector with a single READ request.
|
||||
*
|
||||
* Note the strange need for a big buffer even though we must only pass 0x10 as the transfer length, otherwise the drive will hang (!?).
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param sector The sector to be read. What will be cached is the 16-sectors block to which the sector belongs, and the following 4 blocks.
|
||||
* @param sense A pointer to a structure which will hold the SENSE DATA got from the drive after the command has been executed.
|
||||
* @param extbuf A buffer where to store the read data, or NULL.
|
||||
* @param extbufsize The size of the buffer.
|
||||
* @return
|
||||
*/
|
||||
int dvd_read_sector_streaming (dvd_drive *dvd, u_int32_t sector, req_sense *sense, u_int8_t *extbuf, size_t extbufsize) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t intbuf[2048 * 16], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
/* We need some buffer, be it provided externally or not */
|
||||
if (extbuf) {
|
||||
buf = extbuf;
|
||||
bufsize = extbufsize;
|
||||
} else {
|
||||
buf = intbuf;
|
||||
bufsize = sizeof (intbuf);
|
||||
}
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[0] = MMC_READ_12;
|
||||
mmc.cmd[2] = (u_int8_t) ((sector & 0xFF000000) >> 24); /* LBA from MSB to LSB */
|
||||
mmc.cmd[3] = (u_int8_t) ((sector & 0x00FF0000) >> 16);
|
||||
mmc.cmd[4] = (u_int8_t) ((sector & 0x0000FF00) >> 8);
|
||||
mmc.cmd[5] = (u_int8_t) (sector & 0x000000FF);
|
||||
mmc.cmd[6] = 0;
|
||||
mmc.cmd[7] = 0;
|
||||
mmc.cmd[8] = 0;
|
||||
mmc.cmd[9] = 0x10;
|
||||
mmc.cmd[10] = 0x80; /* STREAMING bit set */
|
||||
out = dvd_execute_cmd (dvd, &mmc, true); /* Ignore errors! */
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
int dvd_read_streaming (dvd_drive *dvd, u_int32_t sector, u_int32_t sectors, req_sense *sense, u_int8_t *extbuf, size_t extbufsize) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t intbuf[64 * 1024], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
/* We need some buffer, be it provided externally or not */
|
||||
if (extbuf) {
|
||||
buf = extbuf;
|
||||
bufsize = extbufsize;
|
||||
} else {
|
||||
buf = intbuf;
|
||||
bufsize = sizeof (intbuf);
|
||||
}
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[0] = MMC_READ_12;
|
||||
mmc.cmd[2] = (u_int8_t) ((sector & 0xFF000000) >> 24); /* LBA from MSB to LSB */
|
||||
mmc.cmd[3] = (u_int8_t) ((sector & 0x00FF0000) >> 16);
|
||||
mmc.cmd[4] = (u_int8_t) ((sector & 0x0000FF00) >> 8);
|
||||
mmc.cmd[5] = (u_int8_t) (sector & 0x000000FF);
|
||||
mmc.cmd[6] = (u_int8_t) ((sectors & 0xFF000000) >> 24); /* Size from MSB to LSB */
|
||||
mmc.cmd[7] = (u_int8_t) ((sectors & 0x00FF0000) >> 16);
|
||||
mmc.cmd[8] = (u_int8_t) ((sectors & 0x0000FF00) >> 8);
|
||||
mmc.cmd[9] = (u_int8_t) (sectors & 0x000000FF);
|
||||
mmc.cmd[10] = 0x80; /* STREAMING bit set */
|
||||
out = dvd_execute_cmd (dvd, &mmc, true); /* Ignore errors! */
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
int dvd_flush_cache_READ12 (dvd_drive *dvd, u_int32_t sector, req_sense *sense) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t intbuf[64], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
buf = intbuf;
|
||||
bufsize = 0;
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[0] = MMC_READ_12;
|
||||
mmc.cmd[1] = 0x08;
|
||||
mmc.cmd[2] = (u_int8_t) ((sector & 0xFF000000) >> 24); /* LBA from MSB to LSB */
|
||||
mmc.cmd[3] = (u_int8_t) ((sector & 0x00FF0000) >> 16);
|
||||
mmc.cmd[4] = (u_int8_t) ((sector & 0x0000FF00) >> 8);
|
||||
mmc.cmd[5] = (u_int8_t) (sector & 0x000000FF);
|
||||
out = dvd_execute_cmd (dvd, &mmc, true);
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
int dvd_stop_unit (dvd_drive *dvd, bool start, req_sense *sense) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t intbuf[64], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
buf = intbuf;
|
||||
bufsize = 0;
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[0] = 0x1B;
|
||||
if (start) mmc.cmd[4] = 1;
|
||||
else mmc.cmd[4] = 0;
|
||||
out = dvd_execute_cmd (dvd, &mmc, true);
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
int dvd_set_speed (dvd_drive *dvd, u_int32_t speed, req_sense *sense) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t intbuf[64], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
buf = intbuf;
|
||||
bufsize = 0;
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[0] = 0xBB;
|
||||
mmc.cmd[2] = (u_int8_t) ((speed & 0x0000FF00) >> 8);
|
||||
mmc.cmd[3] = (u_int8_t) (speed & 0x000000FF);
|
||||
out = dvd_execute_cmd (dvd, &mmc, true);
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
int dvd_get_size (dvd_drive *dvd, u_int32_t *size, req_sense *sense) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t intbuf[64], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
buf = intbuf;
|
||||
bufsize = 0x22;
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[0] = 0x52;
|
||||
mmc.cmd[1] = 0x01;
|
||||
mmc.cmd[5] = 0x01;
|
||||
mmc.cmd[8] = 0x22;
|
||||
out = dvd_execute_cmd (dvd, &mmc, true);
|
||||
|
||||
*(size)=*(size) << 8 | intbuf[0x18];
|
||||
*(size)=*(size) << 8 | intbuf[0x19];
|
||||
*(size)=*(size) << 8 | intbuf[0x1a];
|
||||
*(size)=*(size) << 8 | intbuf[0x1b];
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
int dvd_get_layerbreak (dvd_drive *dvd, u_int32_t *layerbreak, req_sense *sense) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t intbuf[2052], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
buf = intbuf;
|
||||
bufsize = 2052;
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[0] = 0xad;
|
||||
mmc.cmd[8] = 0x08;
|
||||
mmc.cmd[9] = 0x04;
|
||||
out = dvd_execute_cmd (dvd, &mmc, true);
|
||||
|
||||
*(layerbreak)=*(layerbreak) << 8;
|
||||
*(layerbreak)=*(layerbreak) << 8 | intbuf[0x11];
|
||||
*(layerbreak)=*(layerbreak) << 8 | intbuf[0x12];
|
||||
*(layerbreak)=*(layerbreak) << 8 | intbuf[0x13];
|
||||
if (*(layerbreak) > 0) *(layerbreak)=*(layerbreak) - 0x30000 + 1;
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
int dvd_set_streaming (dvd_drive *dvd, u_int32_t speed, req_sense *sense) {
|
||||
/*
|
||||
DVD Decrypter->
|
||||
DeviceIoControl : \Device\CdRom5
|
||||
Command : IOCTL_SCSI_PASS_THROUGH_DIRECT
|
||||
Length : 44 (0x002C)
|
||||
ScsiStatus : 0
|
||||
PathId : 0
|
||||
TargedId : 0
|
||||
Lun : 0
|
||||
CdbLength : 12 (0x0C)
|
||||
SenseInfoLength : 24 (0x18)
|
||||
DataTransferLength : 28 (0x0000001C)
|
||||
DataIn : 0
|
||||
TimeOutValue : 5000
|
||||
|
||||
CDB:
|
||||
00000000 B6 00 00 00 00 00 00 00 00 00 1C 00 ¶...........
|
||||
|
||||
Data Sent:
|
||||
00000000 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF ............____
|
||||
00000010 00 00 03 E8 FF FF FF FF 00 00 03 E8 ...è____...è
|
||||
*/
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int8_t inbuf[28], *buf;
|
||||
size_t bufsize;
|
||||
|
||||
buf = inbuf;
|
||||
bufsize = 28;
|
||||
|
||||
dvd_init_command (&mmc, buf, bufsize, sense);
|
||||
mmc.cmd[00] = 0xB6;
|
||||
mmc.cmd[10] = 28;
|
||||
|
||||
*(buf+ 0)=0;//2
|
||||
*(buf+ 1)=0;
|
||||
*(buf+ 2)=0;
|
||||
*(buf+ 3)=0;
|
||||
*(buf+ 4)=0; //MSB
|
||||
*(buf+ 5)=0; //
|
||||
*(buf+ 6)=0; //
|
||||
*(buf+ 7)=0; //LSB
|
||||
|
||||
*(buf+ 8)=0xff; //MSB
|
||||
*(buf+ 9)=0xff; //
|
||||
*(buf+10)=0xff; //
|
||||
*(buf+11)=0xff; //LSB
|
||||
|
||||
*(buf+12)=(u_int8_t) ((speed & 0xFF000000) >> 24);
|
||||
*(buf+13)=(u_int8_t) ((speed & 0x00FF0000) >> 16);
|
||||
*(buf+14)=(u_int8_t) ((speed & 0x0000FF00) >> 8);
|
||||
*(buf+15)=(u_int8_t) (speed & 0x000000FF);
|
||||
|
||||
*(buf+16)=(u_int8_t) ((1000 & 0xFF000000) >> 24);
|
||||
*(buf+17)=(u_int8_t) ((1000 & 0x00FF0000) >> 16);
|
||||
*(buf+18)=(u_int8_t) ((1000 & 0x0000FF00) >> 8);
|
||||
*(buf+19)=(u_int8_t) (1000 & 0x000000FF);
|
||||
|
||||
*(buf+20)=(u_int8_t) ((speed & 0xFF000000) >> 24);
|
||||
*(buf+21)=(u_int8_t) ((speed & 0x00FF0000) >> 16);
|
||||
*(buf+22)=(u_int8_t) ((speed & 0x0000FF00) >> 8);
|
||||
*(buf+23)=(u_int8_t) (speed & 0x000000FF);
|
||||
|
||||
*(buf+24)=(u_int8_t) ((1000 & 0xFF000000) >> 24);
|
||||
*(buf+25)=(u_int8_t) ((1000 & 0x00FF0000) >> 16);
|
||||
*(buf+26)=(u_int8_t) ((1000 & 0x0000FF00) >> 8);
|
||||
*(buf+27)=(u_int8_t) (1000 & 0x000000FF);
|
||||
|
||||
out = dvd_execute_cmd (dvd, &mmc, true);
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
char *dvd_get_vendor (dvd_drive *dvd) {
|
||||
return (dvd -> vendor);
|
||||
}
|
||||
|
||||
|
||||
char *dvd_get_product_id (dvd_drive *dvd) {
|
||||
return (dvd -> prod_id);
|
||||
}
|
||||
|
||||
|
||||
char *dvd_get_product_revision (dvd_drive *dvd) {
|
||||
return (dvd -> prod_rev);
|
||||
}
|
||||
|
||||
|
||||
char *dvd_get_model_string (dvd_drive *dvd) {
|
||||
return (dvd -> model_string);
|
||||
}
|
||||
|
||||
|
||||
bool dvd_get_support_status (dvd_drive *dvd) {
|
||||
return (dvd -> supported);
|
||||
}
|
||||
|
||||
u_int32_t dvd_get_def_method (dvd_drive *dvd){
|
||||
return (dvd -> def_method);
|
||||
}
|
||||
|
||||
u_int32_t dvd_get_command (dvd_drive *dvd){
|
||||
return (dvd -> command);
|
||||
}
|
73
libfriidump/dvd_drive.h
Normal file
73
libfriidump/dvd_drive.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef DVD_DRIVE_H_INCLUDED
|
||||
#define DVD_DRIVE_H_INCLUDED
|
||||
|
||||
#include "misc.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
typedef struct dvd_drive_s dvd_drive;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int sense_key;
|
||||
int asc;
|
||||
int ascq;
|
||||
} req_sense;
|
||||
|
||||
|
||||
typedef struct {
|
||||
u_int8_t cmd[12];
|
||||
req_sense *sense;
|
||||
u_int8_t *buffer;
|
||||
int buflen;
|
||||
} mmc_command;
|
||||
|
||||
|
||||
/* Functions */
|
||||
dvd_drive *dvd_drive_new (char *device, u_int32_t command);
|
||||
void *dvd_drive_destroy (dvd_drive *d);
|
||||
int dvd_read_sector_dummy (dvd_drive *dvd, u_int32_t sector, u_int32_t sectors, req_sense *sense, u_int8_t *extbuf, size_t extbufsize);
|
||||
int dvd_read_sector_streaming (dvd_drive *dvd, u_int32_t sector, req_sense *sense, u_int8_t *extbuf, size_t extbufsize);
|
||||
int dvd_read_streaming (dvd_drive *dvd, u_int32_t sector, u_int32_t sectors, req_sense *sense, u_int8_t *extbuf, size_t extbufsize);
|
||||
int dvd_flush_cache_READ12 (dvd_drive *dvd, u_int32_t sector, req_sense *sense);
|
||||
int dvd_stop_unit (dvd_drive *dvd, bool start, req_sense *sense);
|
||||
int dvd_set_speed (dvd_drive *dvd, u_int32_t speed, req_sense *sense);
|
||||
int dvd_get_size (dvd_drive *dvd, u_int32_t *size, req_sense *sense);
|
||||
int dvd_get_layerbreak (dvd_drive *dvd, u_int32_t *layerbreak, req_sense *sense);
|
||||
int dvd_set_streaming (dvd_drive *dvd, u_int32_t speed, req_sense *sense);
|
||||
int dvd_memdump (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
|
||||
char *dvd_get_vendor (dvd_drive *dvd);
|
||||
char *dvd_get_product_id (dvd_drive *dvd);
|
||||
char *dvd_get_product_revision (dvd_drive *dvd);
|
||||
char *dvd_get_model_string (dvd_drive *dvd);
|
||||
bool dvd_get_support_status (dvd_drive *dvd);
|
||||
u_int32_t dvd_get_def_method (dvd_drive *dvd);
|
||||
u_int32_t dvd_get_command (dvd_drive *dvd);
|
||||
|
||||
/* The following are exported for use by drive-specific functions */
|
||||
typedef int (*dvd_drive_memdump_func) (dvd_drive *dvd, u_int32_t block_off, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf);
|
||||
void dvd_init_command (mmc_command *mmc, u_int8_t *buf, int len, req_sense *sense);
|
||||
int dvd_execute_cmd (dvd_drive *dvd, mmc_command *mmc, bool ignore_errors);
|
||||
|
||||
#endif
|
109
libfriidump/ecma-267.c
Normal file
109
libfriidump/ecma-267.c
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
unscrambler 0.4: unscramble not standard IVs scrambled DVDs thru
|
||||
bruteforce, intended for Gamecube/WII Optical Disks.
|
||||
|
||||
Copyright (C) 2006 Victor Muñoz (xt5@ingenieria-inversa.cl)
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "ecma-267.h"
|
||||
|
||||
/* EDC stuff */
|
||||
unsigned int edc_table[256] = {
|
||||
0x00000000, 0x80000011, 0x80000033, 0x00000022, 0x80000077, 0x00000066, 0x00000044, 0x80000055,
|
||||
0x800000FF, 0x000000EE, 0x000000CC, 0x800000DD, 0x00000088, 0x80000099, 0x800000BB, 0x000000AA,
|
||||
0x800001EF, 0x000001FE, 0x000001DC, 0x800001CD, 0x00000198, 0x80000189, 0x800001AB, 0x000001BA,
|
||||
0x00000110, 0x80000101, 0x80000123, 0x00000132, 0x80000167, 0x00000176, 0x00000154, 0x80000145,
|
||||
0x800003CF, 0x000003DE, 0x000003FC, 0x800003ED, 0x000003B8, 0x800003A9, 0x8000038B, 0x0000039A,
|
||||
0x00000330, 0x80000321, 0x80000303, 0x00000312, 0x80000347, 0x00000356, 0x00000374, 0x80000365,
|
||||
0x00000220, 0x80000231, 0x80000213, 0x00000202, 0x80000257, 0x00000246, 0x00000264, 0x80000275,
|
||||
0x800002DF, 0x000002CE, 0x000002EC, 0x800002FD, 0x000002A8, 0x800002B9, 0x8000029B, 0x0000028A,
|
||||
0x8000078F, 0x0000079E, 0x000007BC, 0x800007AD, 0x000007F8, 0x800007E9, 0x800007CB, 0x000007DA,
|
||||
0x00000770, 0x80000761, 0x80000743, 0x00000752, 0x80000707, 0x00000716, 0x00000734, 0x80000725,
|
||||
0x00000660, 0x80000671, 0x80000653, 0x00000642, 0x80000617, 0x00000606, 0x00000624, 0x80000635,
|
||||
0x8000069F, 0x0000068E, 0x000006AC, 0x800006BD, 0x000006E8, 0x800006F9, 0x800006DB, 0x000006CA,
|
||||
0x00000440, 0x80000451, 0x80000473, 0x00000462, 0x80000437, 0x00000426, 0x00000404, 0x80000415,
|
||||
0x800004BF, 0x000004AE, 0x0000048C, 0x8000049D, 0x000004C8, 0x800004D9, 0x800004FB, 0x000004EA,
|
||||
0x800005AF, 0x000005BE, 0x0000059C, 0x8000058D, 0x000005D8, 0x800005C9, 0x800005EB, 0x000005FA,
|
||||
0x00000550, 0x80000541, 0x80000563, 0x00000572, 0x80000527, 0x00000536, 0x00000514, 0x80000505,
|
||||
0x80000F0F, 0x00000F1E, 0x00000F3C, 0x80000F2D, 0x00000F78, 0x80000F69, 0x80000F4B, 0x00000F5A,
|
||||
0x00000FF0, 0x80000FE1, 0x80000FC3, 0x00000FD2, 0x80000F87, 0x00000F96, 0x00000FB4, 0x80000FA5,
|
||||
0x00000EE0, 0x80000EF1, 0x80000ED3, 0x00000EC2, 0x80000E97, 0x00000E86, 0x00000EA4, 0x80000EB5,
|
||||
0x80000E1F, 0x00000E0E, 0x00000E2C, 0x80000E3D, 0x00000E68, 0x80000E79, 0x80000E5B, 0x00000E4A,
|
||||
0x00000CC0, 0x80000CD1, 0x80000CF3, 0x00000CE2, 0x80000CB7, 0x00000CA6, 0x00000C84, 0x80000C95,
|
||||
0x80000C3F, 0x00000C2E, 0x00000C0C, 0x80000C1D, 0x00000C48, 0x80000C59, 0x80000C7B, 0x00000C6A,
|
||||
0x80000D2F, 0x00000D3E, 0x00000D1C, 0x80000D0D, 0x00000D58, 0x80000D49, 0x80000D6B, 0x00000D7A,
|
||||
0x00000DD0, 0x80000DC1, 0x80000DE3, 0x00000DF2, 0x80000DA7, 0x00000DB6, 0x00000D94, 0x80000D85,
|
||||
0x00000880, 0x80000891, 0x800008B3, 0x000008A2, 0x800008F7, 0x000008E6, 0x000008C4, 0x800008D5,
|
||||
0x8000087F, 0x0000086E, 0x0000084C, 0x8000085D, 0x00000808, 0x80000819, 0x8000083B, 0x0000082A,
|
||||
0x8000096F, 0x0000097E, 0x0000095C, 0x8000094D, 0x00000918, 0x80000909, 0x8000092B, 0x0000093A,
|
||||
0x00000990, 0x80000981, 0x800009A3, 0x000009B2, 0x800009E7, 0x000009F6, 0x000009D4, 0x800009C5,
|
||||
0x80000B4F, 0x00000B5E, 0x00000B7C, 0x80000B6D, 0x00000B38, 0x80000B29, 0x80000B0B, 0x00000B1A,
|
||||
0x00000BB0, 0x80000BA1, 0x80000B83, 0x00000B92, 0x80000BC7, 0x00000BD6, 0x00000BF4, 0x80000BE5,
|
||||
0x00000AA0, 0x80000AB1, 0x80000A93, 0x00000A82, 0x80000AD7, 0x00000AC6, 0x00000AE4, 0x80000AF5,
|
||||
0x80000A5F, 0x00000A4E, 0x00000A6C, 0x80000A7D, 0x00000A28, 0x80000A39, 0x80000A1B, 0x00000A0AL
|
||||
};
|
||||
|
||||
u32 edc_calc(u32 edc, u8 *ptr, u32 len) {
|
||||
while (len--) edc=edc_table[((edc>>24)^*ptr++)&0xFF]^(edc<<8);
|
||||
return edc;
|
||||
}
|
||||
|
||||
/* end of EDC stuff */
|
||||
|
||||
/* LFSR stuff */
|
||||
|
||||
u16 ecma267_ivs[]= {
|
||||
0x0001, 0x5500, 0x0002, 0x2A00,
|
||||
0x0004, 0x5400, 0x0008, 0x2800,
|
||||
0x0010, 0x5000, 0x0020, 0x2001,
|
||||
0x0040, 0x4002, 0x0080, 0x0005
|
||||
};
|
||||
|
||||
|
||||
unsigned short LFSR;
|
||||
|
||||
void LFSR_ecma_init(int iv) {
|
||||
LFSR=ecma267_ivs[iv];
|
||||
}
|
||||
|
||||
void LFSR_init(u16 seed) {
|
||||
LFSR=seed;
|
||||
}
|
||||
|
||||
int LFSR_tick() {
|
||||
int ret;
|
||||
int n;
|
||||
|
||||
ret=LFSR>>14;
|
||||
|
||||
n=ret^((LFSR>>10)&1);
|
||||
LFSR=((LFSR<<1)|n)&0x7FFF;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned char LFSR_byte() {
|
||||
u8 ret;
|
||||
int i;
|
||||
|
||||
ret=0;
|
||||
for(i=0; i<8; i++) ret=(ret<<1)|LFSR_tick();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* end of LFSR stuff */
|
47
libfriidump/ecma-267.h
Normal file
47
libfriidump/ecma-267.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
unscrambler 0.4: unscramble not standard IVs scrambled DVDs thru
|
||||
bruteforce, intended for Gamecube/WII Optical Disks.
|
||||
|
||||
Copyright (C) 2006 Victor Muñoz (xt5@ingenieria-inversa.cl)
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
typedef unsigned int u32;
|
||||
typedef int s32;
|
||||
|
||||
typedef unsigned short u16;
|
||||
typedef short s16;
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef char s8;
|
||||
|
||||
/* EDC stuff */
|
||||
|
||||
u32 edc_calc(u32 edc, u8 *ptr, u32 len);
|
||||
|
||||
/* end of EDC stuff */
|
||||
|
||||
/* LFSR stuff */
|
||||
|
||||
void LFSR_ecma_init(int iv);
|
||||
|
||||
void LFSR_init(u16 seed);
|
||||
|
||||
int LFSR_tick();
|
||||
|
||||
u8 LFSR_byte();
|
||||
|
||||
/* end of LFSR stuff */
|
147
libfriidump/hitachi.c
Normal file
147
libfriidump/hitachi.c
Normal file
|
@ -0,0 +1,147 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/*! \file
|
||||
* \brief Memory dump functions specific to drives based on the Hitachi MN103 chip.
|
||||
*
|
||||
* Drives which are supported by this set of functions are, for instance, the LG GDR-8161B, GDR-8162B, GDR-8163B and GDR-8164B. All testing has been performed
|
||||
* with the latter model, so I'm not really sure about the others, but they should work ;). Please report any issues and more compatible drives!
|
||||
*
|
||||
* This file contains code derived from the work of Kevin East (SeventhSon), kev@kev.nu, http://www.kev.nu/360/ , which, in turn, derives from work by
|
||||
* a lot of other people. See his page for full details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "misc.h"
|
||||
#include "dvd_drive.h"
|
||||
|
||||
/*! \brief Memory offset at which the drive cache memory is mapped.
|
||||
*
|
||||
* During READ, sector data is cached beginning at this address.
|
||||
*/
|
||||
|
||||
#define HITACHI_MEM_BASE 0x80000000
|
||||
|
||||
|
||||
/**
|
||||
* Dumps a single block (with arbitrary size) of the address space of the MN103 microcontroller within the Hitachi-LG Xbox 360 DVD drive and similar drives.
|
||||
* This function is derived from the work of Kevin East (SeventhSon), kev@kev.nu, http://www.kev.nu/360/.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The absolute memory offset to start dumping.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int hitachi_dvd_dump_memblock (dvd_drive *dvd, u_int32_t offset, u_int32_t block_size, u_int8_t *buf) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else if (!block_size || block_size > 65535) {
|
||||
error ("invalid block_size (valid: 1 - 65535)");
|
||||
out = -2;
|
||||
} else {
|
||||
dvd_init_command (&mmc, buf, block_size, NULL);
|
||||
mmc.cmd[0] = 0xE7; // vendor specific command (discovered by DaveX)
|
||||
mmc.cmd[1] = 0x48; // H
|
||||
mmc.cmd[2] = 0x49; // I
|
||||
mmc.cmd[3] = 0x54; // T
|
||||
mmc.cmd[4] = 0x01; // read MCU memory sub-command
|
||||
mmc.cmd[6] = (unsigned char) ((offset & 0xFF000000) >> 24); // address MSB
|
||||
mmc.cmd[7] = (unsigned char) ((offset & 0x00FF0000) >> 16); // address
|
||||
mmc.cmd[8] = (unsigned char) ((offset & 0x0000FF00) >> 8); // address
|
||||
mmc.cmd[9] = (unsigned char) (offset & 0x000000FF); // address LSB
|
||||
mmc.cmd[10] = (unsigned char) ((block_size & 0xFF00) >> 8); // length MSB
|
||||
mmc.cmd[11] = (unsigned char) (block_size & 0x00FF); // length LSB
|
||||
|
||||
out = dvd_execute_cmd (dvd, &mmc, false);
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dumps a given portion of the address space of the MN103 microcontroller within the Hitachi-LG Xbox 360 DVD drive.
|
||||
* WARNING: it can take a while to dump a lot of data.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The absolute memory offset to start dumping.
|
||||
* @param block_len The number of blocks to dump.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int hitachi_dvd_dump_mem_generic (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
|
||||
u_int32_t i;
|
||||
int r, out;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else {
|
||||
r = -10;
|
||||
for (i = 0; i < block_len; i++) {
|
||||
if ((r = hitachi_dvd_dump_memblock (dvd, offset + i * block_size, block_size, buf + i * block_size)) < 0) {
|
||||
error ("hitachi_dvd_read_block() failed with %d", r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
out = r;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dumps a given portion of the address space of the MN103 microcontroller within the Hitachi-LG Xbox 360 DVD drive, starting at the offset at which
|
||||
* sector data are cached.
|
||||
* WARNING: it can take a while to dump a lot of data.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The memory offset to start dumping, relative to the cache start offset.
|
||||
* @param block_len The number of blocks to dump.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int hitachi_dvd_dump_mem (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
|
||||
u_int32_t i;
|
||||
int r, out;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else {
|
||||
r = -10;
|
||||
for (i = 0; i < block_len; i++) {
|
||||
if ((r = hitachi_dvd_dump_memblock (dvd, HITACHI_MEM_BASE + offset + i * block_size, block_size, buf + i * block_size)) < 0) {
|
||||
error ("hitachi_dvd_read_block() failed with %d", r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
out = r;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
154
libfriidump/lite-on.c
Normal file
154
libfriidump/lite-on.c
Normal file
|
@ -0,0 +1,154 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "rs.h"
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "misc.h"
|
||||
#include "dvd_drive.h"
|
||||
|
||||
/**
|
||||
* Command found in Lite-On LH-18A1H; verified with LH-18A1P and LH-20A1H
|
||||
* Expected to work with: DH*, DW*, LH*, SH* series
|
||||
* Possibly would work with other Mediatek based drives:
|
||||
* Samsung SE*, SH* series
|
||||
* Some Dell drives
|
||||
* Some Sony drives
|
||||
* Asus DRW-1814* (DRW* series?)
|
||||
*/
|
||||
|
||||
//u_int8_t tmp[64*1024];
|
||||
|
||||
/**
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The absolute memory offset to start dumping.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int liteon_dvd_dump_memblock (dvd_drive *dvd, u_int32_t offset, u_int32_t block_size, u_int8_t *buf) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int32_t raw_block_size;
|
||||
u_int32_t raw_offset;
|
||||
|
||||
u_int32_t src_offset;
|
||||
u_int32_t dst_offset;
|
||||
u_int32_t row_nr;
|
||||
u_int32_t sec_nr;
|
||||
u_int32_t sec_cnt;
|
||||
u_int32_t first_sec_nr;
|
||||
u_int8_t tmp[64*1024];
|
||||
//u_int8_t *tmp;
|
||||
|
||||
raw_block_size = (block_size / 2064) * 0x950;
|
||||
raw_offset = (offset / 2064) * 0x950;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else if (!block_size || raw_block_size >= 65535) {
|
||||
error ("invalid raw_block_size (valid: 1 - 65534)");
|
||||
error ("raw_block_size = (block_size / 2064) * 2384");
|
||||
out = -2;
|
||||
} else {
|
||||
//tmp = malloc(64*1024);
|
||||
dvd_init_command (&mmc, tmp, raw_block_size, NULL); //64*1024
|
||||
mmc.cmd[0] = 0x3C; // READ BUFFER
|
||||
mmc.cmd[1] = 0x01; // Vendor specific - sole parameter supported by Lite-On
|
||||
mmc.cmd[2] = 0x01; // == 0x02; 0xE2 = EEPROM; 0xF1 = KEYPARA;
|
||||
mmc.cmd[3] = (unsigned char) ((raw_offset & 0x00FF0000) >> 16);// address MSB
|
||||
mmc.cmd[4] = (unsigned char) ((raw_offset & 0x0000FF00) >> 8); // address
|
||||
mmc.cmd[5] = (unsigned char) ( raw_offset & 0x000000FF); // address LSB
|
||||
mmc.cmd[6] = (unsigned char) ((raw_block_size & 0x00FF0000) >> 16); // length MSB
|
||||
mmc.cmd[7] = (unsigned char) ((raw_block_size & 0x0000FF00) >> 8); // length
|
||||
mmc.cmd[8] = (unsigned char) ( raw_block_size & 0x000000FF); // length LSB
|
||||
|
||||
out = dvd_execute_cmd (dvd, &mmc, false);
|
||||
|
||||
src_offset = 0;
|
||||
dst_offset = 0;
|
||||
first_sec_nr = 0x55555555;
|
||||
sec_cnt = 0;
|
||||
while (src_offset < raw_block_size) {
|
||||
sec_nr=(*(tmp+src_offset+1)<<16)+(*(tmp+src_offset+2)<<8)+(*(tmp+src_offset+3));
|
||||
//fprintf (stdout,"sec_nr: %x\n", sec_nr);
|
||||
if (first_sec_nr==0x55555555) {
|
||||
first_sec_nr=sec_nr;
|
||||
rs_decode(tmp+src_offset, 0, 0);
|
||||
}
|
||||
else
|
||||
if (sec_nr==first_sec_nr+sec_cnt) {
|
||||
rs_decode(tmp+src_offset, 0, 0); //sector seq = ok
|
||||
}
|
||||
else { //sector seq broken -> corrupt
|
||||
error ("sector sequence broken");
|
||||
out = -3;
|
||||
*(tmp+src_offset+0)=0xff;
|
||||
*(tmp+src_offset+1)=0xff;
|
||||
*(tmp+src_offset+2)=0xff;
|
||||
*(tmp+src_offset+3)=0xff;
|
||||
break;
|
||||
}
|
||||
for (row_nr=0; row_nr<12; row_nr++) {
|
||||
memcpy(buf+dst_offset, tmp+src_offset, 172);
|
||||
dst_offset += 172;
|
||||
src_offset += 182;
|
||||
}
|
||||
src_offset += 200;
|
||||
sec_cnt += 1;
|
||||
}
|
||||
//free(tmp);
|
||||
}
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* WARNING: it can take a while to dump a lot of data.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The memory offset to start dumping, relative to the cache start offset.
|
||||
* @param block_len The number of blocks to dump.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int liteon_dvd_dump_mem (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
|
||||
u_int32_t i;
|
||||
int r, out;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else {
|
||||
r = -10;
|
||||
for (i = 0; i < block_len; i++) {
|
||||
if ((r = liteon_dvd_dump_memblock (dvd, offset + i * block_size, block_size, buf + i * block_size)) < 0) {
|
||||
error ("liteon_dvd_dump_memblock() failed with %d", r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
out = r;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
314
libfriidump/misc.c
Normal file
314
libfriidump/misc.c
Normal file
|
@ -0,0 +1,314 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "misc.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
//#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
/*** LOGGING STUFF ***/
|
||||
/* Uses code from the printf man page */
|
||||
static int my_vasprintf (char **dst, const char *fmt, va_list ap) {
|
||||
char *p;
|
||||
int n, size;
|
||||
bool done;
|
||||
va_list ap2;
|
||||
|
||||
/* Guess we need no more than 100 bytes. */
|
||||
size = 100;
|
||||
if ((p = (char *) malloc (size)) != NULL) {
|
||||
do {
|
||||
done = false;
|
||||
va_copy (ap2, ap);
|
||||
n = vsnprintf (p, size, fmt, ap2);
|
||||
va_end (ap2);
|
||||
|
||||
/* If that worked, return the string. */
|
||||
if (n > -1 && n < size)
|
||||
done = true;
|
||||
else {
|
||||
/* Else try again with more space. */
|
||||
if (n > -1) /* glibc 2.1 */
|
||||
size = n + 1; /* precisely what is needed */
|
||||
else /* glibc 2.0 */
|
||||
size *= 2; /* twice the old size */
|
||||
|
||||
if ((p = (char *) realloc (p, size)) == NULL)
|
||||
done = true;
|
||||
}
|
||||
} while (!done);
|
||||
}
|
||||
|
||||
/* Return -1 if memory allocation failed */
|
||||
if (!(*dst = p))
|
||||
n = -1;
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
||||
|
||||
/* Appends a print-like string to the log file, with respect to the verbosity setting */
|
||||
void _logprintf (int level, char tag[], char format[], ...) {
|
||||
static bool last_nocr = false;
|
||||
char *buffer, t[50];
|
||||
va_list ap;
|
||||
struct timeval now;
|
||||
time_t nowtt;
|
||||
struct tm nowtm;
|
||||
|
||||
va_start (ap, format);
|
||||
my_vasprintf (&buffer, format, ap);
|
||||
va_end (ap);
|
||||
|
||||
/* Start of line, including time and tag */
|
||||
if (!last_nocr) {
|
||||
gettimeofday (&now, NULL);
|
||||
nowtt = (time_t) now.tv_sec;
|
||||
if (localtime_r (&nowtt, &nowtm))
|
||||
strftime (t, 50, "%H:%M:%S", &nowtm);
|
||||
if (tag)
|
||||
fprintf (stderr, "[%s/%s] ", t, tag);
|
||||
else
|
||||
fprintf (stderr, "[%s] ", t);
|
||||
|
||||
/* Debug level tag */
|
||||
if (level & LOG_WARNING)
|
||||
fprintf (stderr, "WARNING: ");
|
||||
else if (level & LOG_ERROR)
|
||||
fprintf (stderr, "ERROR: ");
|
||||
#ifdef DEBUG
|
||||
else if (level & LOG_DEBUG)
|
||||
fprintf (stderr, "DEBUG: ");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Actual message */
|
||||
fprintf (stderr, "%s%s", buffer, level & LOG_NOCR ? "" : "\n");
|
||||
fflush (stderr);
|
||||
free (buffer);
|
||||
|
||||
if (level & LOG_NOCR)
|
||||
last_nocr = true;
|
||||
else
|
||||
last_nocr = false;
|
||||
|
||||
return;
|
||||
}
|
||||
/******/
|
||||
|
||||
|
||||
/***************** TAKEN FROM TCPDUMP ****************/
|
||||
|
||||
#define ASCII_LINELENGTH 300
|
||||
#define HEXDUMP_BYTES_PER_LINE 16
|
||||
#define HEXDUMP_SHORTS_PER_LINE (HEXDUMP_BYTES_PER_LINE / 2)
|
||||
#define HEXDUMP_HEXSTUFF_PER_SHORT 5 /* 4 hex digits and a space */
|
||||
#define HEXDUMP_HEXSTUFF_PER_LINE (HEXDUMP_HEXSTUFF_PER_SHORT * HEXDUMP_SHORTS_PER_LINE)
|
||||
|
||||
void hex_and_ascii_print_with_offset (const char *ident, register const u_int8_t *cp,
|
||||
register u_int16_t length, register u_int16_t oset) {
|
||||
register u_int16_t i;
|
||||
register int s1, s2;
|
||||
register int nshorts;
|
||||
char hexstuff[HEXDUMP_SHORTS_PER_LINE*HEXDUMP_HEXSTUFF_PER_SHORT+1], *hsp;
|
||||
char asciistuff[ASCII_LINELENGTH+1], *asp;
|
||||
|
||||
nshorts = length / sizeof(unsigned short);
|
||||
i = 0;
|
||||
hsp = hexstuff;
|
||||
asp = asciistuff;
|
||||
while (--nshorts >= 0) {
|
||||
s1 = *cp++;
|
||||
s2 = *cp++;
|
||||
(void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
|
||||
" %02x%02x", s1, s2);
|
||||
hsp += HEXDUMP_HEXSTUFF_PER_SHORT;
|
||||
*(asp++) = (isgraph(s1) ? s1 : '.');
|
||||
*(asp++) = (isgraph(s2) ? s2 : '.');
|
||||
i++;
|
||||
if (i >= HEXDUMP_SHORTS_PER_LINE) {
|
||||
*hsp = *asp = '\0';
|
||||
(void)printf("%s0x%04x: %-*s %s",
|
||||
ident, oset, HEXDUMP_HEXSTUFF_PER_LINE,
|
||||
hexstuff, asciistuff);
|
||||
i = 0;
|
||||
hsp = hexstuff;
|
||||
asp = asciistuff;
|
||||
oset += HEXDUMP_BYTES_PER_LINE;
|
||||
}
|
||||
}
|
||||
if (length & 1) {
|
||||
s1 = *cp++;
|
||||
(void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
|
||||
" %02x", s1);
|
||||
hsp += 3;
|
||||
*(asp++) = (isgraph(s1) ? s1 : '.');
|
||||
++i;
|
||||
}
|
||||
if (i > 0) {
|
||||
*hsp = *asp = '\0';
|
||||
debug ("%s0x%04x: %-*s %s",
|
||||
ident, oset, HEXDUMP_HEXSTUFF_PER_LINE,
|
||||
hexstuff, asciistuff);
|
||||
}
|
||||
|
||||
debug ("\n"); // Final spacing
|
||||
}
|
||||
|
||||
char *strtrimr (char *s) {
|
||||
int i;
|
||||
|
||||
for (i = strlen (s) - 1; i >= 0 && isspace (s[i]); i--)
|
||||
s[i] = '\0';
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
|
||||
/*** The following was taken from the Python sources */
|
||||
#if !defined(HAVE_LARGEFILE_SUPPORT)
|
||||
#error "Large file support must be enabled for this program"
|
||||
#else
|
||||
|
||||
/* A portable fseek() function
|
||||
return 0 on success, non-zero on failure (with errno set) */
|
||||
int my_fseek (FILE *fp, my_off_t offset, int whence) {
|
||||
#if defined(HAVE_FSEEKO) && SIZEOF_OFF_T >= 8
|
||||
return fseeko(fp, offset, whence);
|
||||
#elif defined(_MSC_VER)
|
||||
return _fseeki64(fp, (__int64) offset, whence);
|
||||
#elif defined(HAVE_FSEEK64)
|
||||
return fseek64(fp, offset, whence);
|
||||
#elif defined(__BEOS__)
|
||||
return _fseek(fp, offset, whence);
|
||||
#elif SIZEOF_FPOS_T >= 8
|
||||
/* lacking a 64-bit capable fseek(), use a 64-bit capable fsetpos()
|
||||
and fgetpos() to implement fseek()*/
|
||||
fpos_t pos;
|
||||
|
||||
switch (whence) {
|
||||
case SEEK_END:
|
||||
#ifdef MS_WINDOWS
|
||||
fflush (fp);
|
||||
if (_lseeki64 (fileno(fp), 0, 2) == -1)
|
||||
return -1;
|
||||
#else
|
||||
if (fseek (fp, 0, SEEK_END) != 0)
|
||||
return -1;
|
||||
#endif
|
||||
// fall through
|
||||
case SEEK_CUR:
|
||||
if (fgetpos (fp, &pos) != 0)
|
||||
return -1;
|
||||
offset += pos;
|
||||
break;
|
||||
// case SEEK_SET: break;
|
||||
}
|
||||
return fsetpos(fp, &offset);
|
||||
#else
|
||||
#error "Large file support, but no way to fseek."
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* A portable ftell() function
|
||||
Return -1 on failure with errno set appropriately, current file
|
||||
position on success */
|
||||
my_off_t my_ftell (FILE* fp) {
|
||||
#if defined(HAVE_FTELLO) && SIZEOF_OFF_T >= 8
|
||||
return ftello (fp);
|
||||
#elif defined(_MSC_VER)
|
||||
return _ftelli64 (fp);
|
||||
#elif defined(HAVE_FTELL64)
|
||||
return ftell64 (fp);
|
||||
#elif SIZEOF_FPOS_T >= 8
|
||||
fpos_t pos;
|
||||
|
||||
if (fgetpos (fp, &pos) != 0)
|
||||
return -1;
|
||||
|
||||
return pos;
|
||||
#else
|
||||
#error "Large file support, but no way to ftell."
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*** STUFF FOR DROPPING PRIVILEGES ***/
|
||||
|
||||
/* WARNING: I'm not sure at all that the privileges-dropping system I have implemented is secure, so don't rely too much on it. */
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Drops privileges to those of the real user (i. e. set euid to ruid).
|
||||
*/
|
||||
void drop_euid () {
|
||||
#ifndef WIN32
|
||||
uid_t uid, euid;
|
||||
|
||||
uid = getuid ();
|
||||
euid = geteuid ();
|
||||
if (uid != 0 && uid != euid) {
|
||||
#if 1
|
||||
seteuid (uid);
|
||||
#else
|
||||
if (seteuid (uid) != 0)
|
||||
debug ("seteuid() to uid %d failed", uid);
|
||||
else
|
||||
debug ("Changed euid from %d to %d", euid, uid);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Upgrades priviles to those of root (i. e. set euid to 0).
|
||||
*/
|
||||
void upgrade_euid () {
|
||||
#ifndef WIN32
|
||||
if (getuid () != 0) {
|
||||
#if 1
|
||||
seteuid (0);
|
||||
#else
|
||||
if (seteuid (0) != 0)
|
||||
debug ("seteuid() to root failed");
|
||||
else
|
||||
debug ("Changed euid to root");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
140
libfriidump/misc.h
Normal file
140
libfriidump/misc.h
Normal file
|
@ -0,0 +1,140 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MISC_H_INCLUDED
|
||||
#define MISC_H_INCLUDED
|
||||
|
||||
/*** Include site configuration ***/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
/******/
|
||||
|
||||
/*** Windows stuff ***/
|
||||
#include "win32compat.h"
|
||||
|
||||
#define _GNU_SOURCE // For strndup()
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
/*** ASSERTIONS ***/
|
||||
#define MY_ASSERT(cond) \
|
||||
if (!(cond)) { \
|
||||
fprintf (stderr, "*** ASSERTION FAILED at " __FILE__ ":%d: " # cond "\n", __LINE__); \
|
||||
exit (9); \
|
||||
}
|
||||
|
||||
/*** LOGGING STUFF ***/
|
||||
enum {
|
||||
LOG_NORMAL = 1 << 0,
|
||||
LOG_WARNING = 1 << 1,
|
||||
LOG_ERROR = 1 << 2,
|
||||
#ifdef DEBUG
|
||||
LOG_DEBUG = 1 << 4,
|
||||
#endif
|
||||
LOG_NOCR = 1 << 15 /* Use in OR to avoid a trailing newline */
|
||||
};
|
||||
|
||||
/* Don't use this function explicitly. Use the macros below. */
|
||||
void _logprintf (int level, char tag[], char format[], ...);
|
||||
|
||||
#ifdef DEBUG
|
||||
#define logprintf(level, ...) _logprintf (level, (char *) __FUNCTION__, __VA_ARGS__)
|
||||
|
||||
#define debug(...) logprintf(LOG_DEBUG, __VA_ARGS__)
|
||||
#define debug_nocr(...) logprintf(LOG_DEBUG | LOG_NOCR, __VA_ARGS__)
|
||||
#else
|
||||
#define logprintf(level, ...) _logprintf (level, NULL, __VA_ARGS__)
|
||||
|
||||
#define debug(...) do {;} while (0);
|
||||
#define debug_nocr(...) do {;} while (0);
|
||||
#endif
|
||||
|
||||
#if defined (DEBUG) || defined (VERBOSE)
|
||||
#define log(...) logprintf (LOG_NORMAL, __VA_ARGS__)
|
||||
#define warning(...) logprintf (LOG_WARNING, __VA_ARGS__)
|
||||
#define error(...) logprintf (LOG_ERROR, __VA_ARGS__)
|
||||
#else
|
||||
#define log(...)
|
||||
#define warning(...)
|
||||
#define error(...)
|
||||
#endif
|
||||
/******/
|
||||
|
||||
void hex_and_ascii_print_with_offset(const char *ident, register const u_int8_t *cp,
|
||||
register u_int16_t length, register u_int16_t oset);
|
||||
#define hex_and_ascii_print(ident, cp, length) hex_and_ascii_print_with_offset(ident, cp, length, 0)
|
||||
|
||||
|
||||
#define my_strdup(dest, src) \
|
||||
if (!(dest = strdup (src))) { \
|
||||
fprintf (stderr, "strdup() failed\n"); \
|
||||
exit (101); \
|
||||
}
|
||||
|
||||
#define my_strndup(dest, src, c) \
|
||||
if (!(dest = strndup ((const char *) src, c))) { \
|
||||
fprintf (stderr, "strndup() failed\n"); \
|
||||
exit (102); \
|
||||
}
|
||||
|
||||
char *strtrimr (char *s);
|
||||
|
||||
#define my_free(p) \
|
||||
if (p) { \
|
||||
free (p); \
|
||||
p = NULL; \
|
||||
}
|
||||
|
||||
|
||||
/*** STUFF FOR PORTABLE LARGE-FILES FSEEK ***/
|
||||
#if defined (HAVE_OFF_T) && SIZEOF_OFF_T >= 8
|
||||
typedef off_t my_off_t;
|
||||
#elif defined (HAVE_FPOS_T) && SIZEOF_FPOS_T >= 8
|
||||
typedef fpos_t my_off_t;
|
||||
#else
|
||||
typedef u_int64_t my_off_t;
|
||||
#endif
|
||||
|
||||
int my_fseek (FILE *fp, my_off_t offset, int whence);
|
||||
my_off_t my_ftell (FILE* fp);
|
||||
/*******/
|
||||
|
||||
|
||||
/*** STUFF FOR DROPPING PRIVILEGES ***/
|
||||
FRIIDUMPLIB_EXPORT void drop_euid ();
|
||||
FRIIDUMPLIB_EXPORT void upgrade_euid ();
|
||||
/******/
|
||||
|
||||
|
||||
/*** STUFF FOR BOOLEAN DATA TYPE ***/
|
||||
#ifdef HAVE_STDBOOL_H
|
||||
/* If using a C99 compiler, use the builtin boolean type */
|
||||
#include <stdbool.h>
|
||||
#else
|
||||
typedef enum {false,true} bool;
|
||||
#endif
|
||||
/******/
|
||||
|
||||
#endif
|
132
libfriidump/renesas.c
Normal file
132
libfriidump/renesas.c
Normal file
|
@ -0,0 +1,132 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "rs.h"
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "misc.h"
|
||||
#include "dvd_drive.h"
|
||||
|
||||
/**
|
||||
* Command found in Lite-On LH-18A1H
|
||||
* Expected to work with: DH*, DW*, LH*, SH* series
|
||||
* Possibly would work with other Mediatek based drives:
|
||||
* Samsung SE*, SH* series
|
||||
* Some Dell drives
|
||||
* Some Sony drives
|
||||
* Asus DRW-1814* (DRW* series?)
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The absolute memory offset to start dumping.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int renesas_dvd_dump_memblock (dvd_drive *dvd, u_int32_t offset, u_int32_t block_size, u_int8_t *buf) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
|
||||
u_int32_t src_offset;
|
||||
u_int32_t sec_nr;
|
||||
u_int32_t sec_cnt;
|
||||
u_int32_t first_sec_nr;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else if (!block_size || block_size > 65535) {
|
||||
error ("invalid block_size (valid: 1 - 65535)");
|
||||
out = -2;
|
||||
} else {
|
||||
dvd_init_command (&mmc, buf, block_size, NULL);
|
||||
mmc.cmd[0] = 0x3C;
|
||||
mmc.cmd[1] = 0x05;
|
||||
mmc.cmd[2] = (unsigned char) ((offset & 0xFF000000) >> 24); // address MSB
|
||||
mmc.cmd[3] = (unsigned char) ((offset & 0x00FF0000) >> 16); // address MSB
|
||||
mmc.cmd[4] = (unsigned char) ((offset & 0x0000FF00) >> 8); // address
|
||||
mmc.cmd[5] = (unsigned char) ( offset & 0x000000FF); // address LSB
|
||||
// mmc.cmd[6] = (unsigned char) ((block_size & 0x00FF0000) >> 16);// length MSB
|
||||
mmc.cmd[6] = 0;
|
||||
mmc.cmd[7] = (unsigned char) ((block_size & 0x0000FF00) >> 8); // length
|
||||
mmc.cmd[8] = (unsigned char) ( block_size & 0x000000FF); // length LSB
|
||||
mmc.cmd[9] = 0x44;
|
||||
|
||||
out = dvd_execute_cmd (dvd, &mmc, false);
|
||||
|
||||
src_offset = 0;
|
||||
first_sec_nr = 0x55555555;
|
||||
sec_cnt = 0;
|
||||
while (src_offset < block_size) {
|
||||
sec_nr=(*(buf+src_offset+1)<<16)+(*(buf+src_offset+2)<<8)+(*(buf+src_offset+3));
|
||||
if (first_sec_nr==0x55555555) {
|
||||
first_sec_nr=sec_nr;
|
||||
}
|
||||
else
|
||||
if (sec_nr!=first_sec_nr+sec_cnt) {
|
||||
error ("sector sequence broken");
|
||||
out = -3;
|
||||
*(buf+src_offset+0)=0xff;
|
||||
*(buf+src_offset+1)=0xff;
|
||||
*(buf+src_offset+2)=0xff;
|
||||
*(buf+src_offset+3)=0xff;
|
||||
break;
|
||||
}
|
||||
src_offset += 2064;
|
||||
sec_cnt += 1;
|
||||
}
|
||||
}
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* WARNING: it can take a while to dump a lot of data.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The memory offset to start dumping, relative to the cache start offset.
|
||||
* @param block_len The number of blocks to dump.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int renesas_dvd_dump_mem (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
|
||||
u_int32_t i;
|
||||
int r, out;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else {
|
||||
r = -10;
|
||||
for (i = 0; i < block_len; i++) {
|
||||
if ((r = renesas_dvd_dump_memblock (dvd, offset + i * block_size, block_size, buf + i * block_size)) < 0) {
|
||||
error ("renesas_dvd_dump_memblock() failed with %d", r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
out = r;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
316
libfriidump/rs.c
Normal file
316
libfriidump/rs.c
Normal file
|
@ -0,0 +1,316 @@
|
|||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define mm 8 /* RS code over GF(2**mm) - change to suit */
|
||||
#define n 256 /* n = size of the field */
|
||||
#define nn 182 /* nn=2**mm -1 length of codeword */
|
||||
#define kk 172 /* kk = nn-2*tt */ /* Degree of g(x) = 2*tt */
|
||||
|
||||
//#define NN n-1
|
||||
//#define FCR 0
|
||||
//#define PRIM 1
|
||||
#define _NROOTS nn-kk
|
||||
//#define PAD NN-nn
|
||||
//#define A0 NN
|
||||
//#define IPRIM 1
|
||||
|
||||
const int NN = n-1;
|
||||
const int FCR = 0;
|
||||
const int PRIM = 1;
|
||||
const int NROOTS = nn-kk;
|
||||
const int PAD = (n-1)-nn;
|
||||
const int A0 = n-1;
|
||||
const int IPRIM = 1;
|
||||
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/**** Primitive polynomial ****/
|
||||
int pp [mm+1] = { 1, 0, 1, 1, 1, 0, 0, 0, 1}; /* 1+x^2+x^3+x^4+x^8 */
|
||||
|
||||
/* generator polynomial, tables for Galois field */
|
||||
int alpha_to[n], index_of[n], gg[nn-kk+1];
|
||||
|
||||
int b0 = 1;
|
||||
|
||||
/* data[] is the info vector, bb[] is the parity vector, recd[] is the
|
||||
noise corrupted received vector */
|
||||
int recd[nn], data[kk], bb[nn-kk];
|
||||
|
||||
int modnn(int x){
|
||||
while (x >= 0xff) {
|
||||
x -= 0xff;
|
||||
x = (x >> 0xff) + (x & 0xff);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
void generate_gf()
|
||||
{
|
||||
register int i, mask ;
|
||||
|
||||
mask = 1 ;
|
||||
alpha_to[mm] = 0 ;
|
||||
for (i=0; i<mm; i++)
|
||||
{ alpha_to[i] = mask ;
|
||||
index_of[alpha_to[i]] = i ;
|
||||
if (pp[i]!=0) /* If pp[i] == 1 then, term @^i occurs in poly-repr of @^mm */
|
||||
alpha_to[mm] ^= mask ; /* Bit-wise EXOR operation */
|
||||
mask <<= 1 ; /* single left-shift */
|
||||
}
|
||||
index_of[alpha_to[mm]] = mm ;
|
||||
/* Have obtained poly-repr of @^mm. Poly-repr of @^(i+1) is given by
|
||||
poly-repr of @^i shifted left one-bit and accounting for any @^mm
|
||||
term that may occur when poly-repr of @^i is shifted. */
|
||||
mask >>= 1 ;
|
||||
for (i=mm+1; i<255; i++)
|
||||
{ if (alpha_to[i-1] >= mask)
|
||||
alpha_to[i] = alpha_to[mm] ^ ((alpha_to[i-1]^mask)<<1) ;
|
||||
else alpha_to[i] = alpha_to[i-1]<<1 ;
|
||||
index_of[alpha_to[i]] = i ;
|
||||
}
|
||||
index_of[0] = A0 ;//-1
|
||||
}
|
||||
|
||||
|
||||
void gen_poly()
|
||||
/* Obtain the generator polynomial of the tt-error correcting, length */
|
||||
{
|
||||
register int i, j, root;
|
||||
|
||||
gg[0] = 1;
|
||||
|
||||
for (i = 0,root=0*1; i < nn-kk; i++,root += 1) {
|
||||
gg[i+1] = 1;
|
||||
|
||||
for (j = i; j > 0; j--){
|
||||
if (gg[j] != 0)
|
||||
gg[j] = gg[j-1] ^ alpha_to[modnn(index_of[gg[j]] + root)];
|
||||
else
|
||||
gg[j] = gg[j-1];
|
||||
}
|
||||
|
||||
gg[0] = alpha_to[modnn(index_of[gg[0]] + root)];
|
||||
}
|
||||
for (i=0; i <= nn-kk; i++) {
|
||||
gg[i] = index_of[gg[i]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void rs_encode(unsigned char *data, unsigned char *bb)
|
||||
{
|
||||
register int i,j ;
|
||||
int feedback;
|
||||
|
||||
for (i=0; i<NROOTS; i++) bb[i] = 0; //nullify result
|
||||
|
||||
for(i=0;i<NN-NROOTS-PAD;i++){
|
||||
feedback = index_of[data[i] ^ bb[0]];
|
||||
|
||||
if(feedback != A0){ /* feedback term is non-zero */
|
||||
for(j=1;j<NROOTS;j++) {
|
||||
bb[j] ^= alpha_to[modnn(feedback + gg[NROOTS-j])];
|
||||
}
|
||||
}
|
||||
/* Shift */
|
||||
memmove(&bb[0],&bb[1], NROOTS-1);
|
||||
//for (j=0; j<NROOTS-1; j++) bb[j] = bb[j+1];
|
||||
|
||||
if(feedback != A0)
|
||||
bb[NROOTS-1] = alpha_to[modnn(feedback + gg[0])];
|
||||
else
|
||||
bb[NROOTS-1] = 0;
|
||||
}
|
||||
}
|
||||
///*
|
||||
int rs_decode(unsigned char *data, int *eras_pos, int no_eras){
|
||||
int deg_lambda, el, deg_omega;
|
||||
int i, j, r,k;
|
||||
unsigned char u,q,tmp,num1,num2,den,discr_r;
|
||||
unsigned char lambda[_NROOTS+1], s[_NROOTS];
|
||||
unsigned char b[_NROOTS+1], t[_NROOTS+1], omega[_NROOTS+1];
|
||||
unsigned char root[_NROOTS], reg[_NROOTS+1], loc[_NROOTS];
|
||||
int syn_error, count;
|
||||
|
||||
|
||||
// form the syndromes; i.e., evaluate data(x) at roots of g(x)
|
||||
for(i=0;i<NROOTS;i++)
|
||||
s[i] = data[0];
|
||||
|
||||
for(j=1;j<NN-PAD;j++){
|
||||
for(i=0;i<NROOTS;i++){
|
||||
if(s[i] == 0){
|
||||
s[i] = data[j];
|
||||
} else {
|
||||
s[i] = data[j] ^ alpha_to[modnn(index_of[s[i]] + (FCR+i)*PRIM)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert syndromes to index form, checking for nonzero condition
|
||||
syn_error = 0;
|
||||
for(i=0;i<NROOTS;i++){
|
||||
syn_error |= s[i];
|
||||
s[i] = index_of[s[i]];
|
||||
}
|
||||
|
||||
if (!syn_error) {
|
||||
// if syndrome is zero, data[] is a codeword and there are no
|
||||
// errors to correct. So return data[] unmodified
|
||||
//
|
||||
count = 0;
|
||||
goto finish;
|
||||
}
|
||||
memset(&lambda[1],0,NROOTS*sizeof(lambda[0]));
|
||||
lambda[0] = 1;
|
||||
|
||||
if (no_eras > 0) {
|
||||
/* Init lambda to be the erasure locator polynomial */
|
||||
lambda[1] = alpha_to[modnn(PRIM*(NN-1-eras_pos[0]))];
|
||||
for (i = 1; i < no_eras; i++) {
|
||||
u = modnn(PRIM*(NN-1-eras_pos[i]));
|
||||
for (j = i+1; j > 0; j--) {
|
||||
tmp = index_of[lambda[j - 1]];
|
||||
if(tmp != A0)
|
||||
lambda[j] ^= alpha_to[modnn(u + tmp)];
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i=0;i<NROOTS+1;i++)
|
||||
b[i] = index_of[lambda[i]];
|
||||
|
||||
/*
|
||||
* Begin Berlekamp-Massey algorithm to determine error+erasure
|
||||
* locator polynomial
|
||||
*/
|
||||
r = no_eras;
|
||||
el = no_eras;
|
||||
|
||||
while (++r <= NROOTS) { /* r is the step number */
|
||||
/* Compute discrepancy at the r-th step in poly-form */
|
||||
discr_r = 0;
|
||||
for (i = 0; i < r; i++){
|
||||
if ((lambda[i] != 0) && (s[r-i-1] != A0)) {
|
||||
discr_r ^= alpha_to[modnn(index_of[lambda[i]] + s[r-i-1])];
|
||||
}
|
||||
}
|
||||
discr_r = index_of[discr_r]; /* Index form */
|
||||
if (discr_r == A0) {
|
||||
/* 2 lines below: B(x) <-- x*B(x) */
|
||||
memmove(&b[1],b,NROOTS*sizeof(b[0]));
|
||||
b[0] = A0;
|
||||
} else {
|
||||
/* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
|
||||
t[0] = lambda[0];
|
||||
for (i = 0 ; i < NROOTS; i++) {
|
||||
if(b[i] != A0)
|
||||
t[i+1] = lambda[i+1] ^ alpha_to[modnn(discr_r + b[i])];
|
||||
else
|
||||
t[i+1] = lambda[i+1];
|
||||
}
|
||||
if (2 * el <= r + no_eras - 1) {
|
||||
el = r + no_eras - el;
|
||||
/*
|
||||
* 2 lines below: B(x) <-- inv(discr_r) *
|
||||
* lambda(x)
|
||||
*/
|
||||
for (i = 0; i <= NROOTS; i++)
|
||||
b[i] = (lambda[i] == 0) ? A0 : modnn(index_of[lambda[i]] - discr_r + NN);
|
||||
} else {
|
||||
/* 2 lines below: B(x) <-- x*B(x) */
|
||||
memmove(&b[1],b,NROOTS*sizeof(b[0]));
|
||||
b[0] = A0;
|
||||
}
|
||||
memcpy(lambda,t,(NROOTS+1)*sizeof(t[0]));
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert lambda to index form and compute deg(lambda(x)) */
|
||||
deg_lambda = 0;
|
||||
for(i=0;i<NROOTS+1;i++){
|
||||
lambda[i] = index_of[lambda[i]];
|
||||
if(lambda[i] != A0)
|
||||
deg_lambda = i;
|
||||
}
|
||||
/* Find roots of the error+erasure locator polynomial by Chien search */
|
||||
memcpy(®[1],&lambda[1],NROOTS*sizeof(reg[0]));
|
||||
count = 0; /* Number of roots of lambda(x) */
|
||||
for (i = 1,k=IPRIM-1; i <= NN; i++,k = modnn(k+IPRIM)) {
|
||||
q = 1; /* lambda[0] is always 0 */
|
||||
for (j = deg_lambda; j > 0; j--){
|
||||
if (reg[j] != A0) {
|
||||
reg[j] = modnn(reg[j] + j);
|
||||
q ^= alpha_to[reg[j]];
|
||||
}
|
||||
}
|
||||
if (q != 0)
|
||||
continue; /* Not a root */
|
||||
/* store root (index-form) and error location number */
|
||||
root[count] = i;
|
||||
loc[count] = k;
|
||||
/* If we've already found max possible roots,
|
||||
* abort the search to save time
|
||||
*/
|
||||
if(++count == deg_lambda)
|
||||
break;
|
||||
}
|
||||
|
||||
if (deg_lambda != count) {
|
||||
/*
|
||||
* deg(lambda) unequal to number of roots => uncorrectable
|
||||
* error detected
|
||||
*/
|
||||
count = -1;
|
||||
goto finish;
|
||||
}
|
||||
/*
|
||||
* Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
|
||||
* x**NROOTS). in index form. Also find deg(omega).
|
||||
*/
|
||||
deg_omega = deg_lambda-1;
|
||||
for (i = 0; i <= deg_omega;i++){
|
||||
tmp = 0;
|
||||
for(j=i;j >= 0; j--){
|
||||
if ((s[i - j] != A0) && (lambda[j] != A0))
|
||||
tmp ^= alpha_to[modnn(s[i - j] + lambda[j])];
|
||||
}
|
||||
omega[i] = index_of[tmp];
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
|
||||
* inv(X(l))**(FCR-1) and den = lambda_pr(inv(X(l))) all in poly-form
|
||||
*/
|
||||
for (j = count-1; j >=0; j--) {
|
||||
num1 = 0;
|
||||
for (i = deg_omega; i >= 0; i--) {
|
||||
if (omega[i] != A0)
|
||||
num1 ^= alpha_to[modnn(omega[i] + i * root[j])];
|
||||
}
|
||||
num2 = alpha_to[modnn(root[j] * (FCR - 1) + NN)];
|
||||
den = 0;
|
||||
|
||||
/* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
|
||||
for (i = min(deg_lambda,NROOTS-1) & ~1; i >= 0; i -=2) {
|
||||
if(lambda[i+1] != A0)
|
||||
den ^= alpha_to[modnn(lambda[i+1] + i * root[j])];
|
||||
}
|
||||
/* Apply error to data */
|
||||
if (num1 != 0 && loc[j] >= PAD) {
|
||||
data[loc[j]-PAD] ^= alpha_to[modnn(index_of[num1] + index_of[num2] + NN - index_of[den])];
|
||||
}
|
||||
}
|
||||
|
||||
finish:
|
||||
if(eras_pos != NULL){
|
||||
for(i=0;i<count;i++)
|
||||
eras_pos[i] = loc[i];
|
||||
}
|
||||
return count;
|
||||
}
|
10
libfriidump/rs.h
Normal file
10
libfriidump/rs.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int modnn(int x);
|
||||
void generate_gf();
|
||||
void gen_poly();
|
||||
void rs_encode(unsigned char *data, unsigned char *bb);
|
||||
int rs_decode(unsigned char *data, int *eras_pos, int no_eras);
|
370
libfriidump/unscrambler.c
Normal file
370
libfriidump/unscrambler.c
Normal file
|
@ -0,0 +1,370 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/*! \file
|
||||
* \brief Unscrambler for Nintendo GameCube/Wii discs.
|
||||
*
|
||||
* As Nintendo GameCube/Wii discs use the standars DVD-ROM scrambling algorithm, but with different, unknown, seeds, the actual seeds have to be brute-forced.
|
||||
* The functions in this file take care of the brute-forcing and of the actual unscrambling of the read sectors.
|
||||
*
|
||||
* The code in this file has been derived from unscrambler 0.4, Copyright (C) 2006 Victor Muñoz (xt5@ingenieria-inversa.cl), GPL v2+,
|
||||
* http://www.ingenieria-inversa.cl/?lp_lang_pref=en .
|
||||
*/
|
||||
|
||||
#include "misc.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "constants.h"
|
||||
#include "byteorder.h"
|
||||
#include "ecma-267.h"
|
||||
#include "unscrambler.h"
|
||||
|
||||
// #define unscramblerdebug(...) debug (__VA_ARGS__);
|
||||
#define unscramblerdebug(...)
|
||||
|
||||
/*! \brief Size of the seeds cache (Do not touch) */
|
||||
#define MAX_SEEDS 4
|
||||
|
||||
/*! \brief Number of bytes of a sector on which the EDC is calculated */
|
||||
#define EDC_LENGTH (RAW_SECTOR_SIZE - 4) /* The EDC value is contained in the bottom 4 bytes of a frame */
|
||||
|
||||
|
||||
/*! \brief A structure that represents a seed
|
||||
*/
|
||||
typedef struct t_seed {
|
||||
int seed; //!< The seed, in numeric format.
|
||||
unsigned char streamcipher[SECTOR_SIZE]; //!< The stream cipher generated from the seed through the LFSR.
|
||||
} t_seed;
|
||||
|
||||
|
||||
/*! \brief A structure that represents an unscrambler
|
||||
*/
|
||||
struct unscrambler_s {
|
||||
t_seed seeds[(MAX_SEEDS + 1) * 16]; //!< The seeds cache.
|
||||
bool bruteforce_seeds; //!< If true, whenever a seed for a sector is not cached, it will be found via a bruteforce attack, otherwise an error will be returned.
|
||||
};
|
||||
|
||||
void unscrambler_set_disctype (u_int8_t disc_type){
|
||||
disctype = disc_type;
|
||||
// fprintf (stdout,"%d",disctype);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a seed to the cache, calculating its streamcipher.
|
||||
* @param seeds The seed cache.
|
||||
* @param seed The seed to add.
|
||||
* @return A structure representing the added seed, or NULL if it could not be added.
|
||||
*/
|
||||
static t_seed *add_seed (t_seed *seeds, unsigned short seed) {
|
||||
int i;
|
||||
t_seed *out;
|
||||
|
||||
unscramblerdebug ("Caching seed %04x\n", seed);
|
||||
|
||||
if (seeds -> seed == -2) {
|
||||
out = NULL;
|
||||
} else {
|
||||
seeds -> seed = seed;
|
||||
|
||||
LFSR_init (seed);
|
||||
for (i = 0; i < SECTOR_SIZE; i++)
|
||||
seeds -> streamcipher[i] = LFSR_byte ();
|
||||
|
||||
out = seeds;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests if the specified seed is the one used for the specified sector block: the check is done comparing the generated EDC with the one at the bottom of each
|
||||
* sector. Sectors are processed in blocks, as the same seed is used for 16 consecutive sectors.
|
||||
* @param buf The sector.
|
||||
* @param j The seed.
|
||||
* @return true if the seed is correct, false otherwise.
|
||||
*/
|
||||
static bool test_seed (u_int8_t *buf, int j) {
|
||||
int i;
|
||||
u_int8_t tmp[RAW_SECTOR_SIZE];
|
||||
u_int32_t edc_calculated, edc_correct;
|
||||
bool out;
|
||||
|
||||
memcpy (tmp, buf, RAW_SECTOR_SIZE);
|
||||
|
||||
LFSR_init (j);
|
||||
for (i = 12; i < EDC_LENGTH; i++)
|
||||
tmp[i] ^= LFSR_byte ();
|
||||
|
||||
edc_calculated = edc_calc (0x00000000, tmp, EDC_LENGTH);
|
||||
edc_correct = my_ntohl (*((u_int32_t *) (&tmp[EDC_LENGTH])));
|
||||
if (edc_calculated == edc_correct)
|
||||
out = true;
|
||||
else
|
||||
out = false;
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unscramble a complete block, using an already-cached seed.
|
||||
* @param seed The seed to use for the unscrambling.
|
||||
* @param _bin The 16-sector block to unscramble (RAW_BLOCK_SIZE).
|
||||
* @param _bout The unscrambled 16-sector block (BLOCK_SIZE).
|
||||
* @return True if the unscrambling was successful, false otherwise.
|
||||
*/
|
||||
static bool unscramble_frame (t_seed *seed, u_int8_t *_bin, u_int8_t *_bout) {
|
||||
int i, j;
|
||||
u_int8_t tmp[RAW_SECTOR_SIZE], *bin, *bout;
|
||||
u_int32_t *_4bin, *_4cipher, edc_calculated, edc_correct;
|
||||
bool out;
|
||||
|
||||
out = true;
|
||||
for(j = 0; j < 16; j++) {
|
||||
bin = &_bin[RAW_SECTOR_SIZE * j];
|
||||
bout = &_bout[SECTOR_SIZE * j];
|
||||
|
||||
memcpy (tmp, bin, RAW_SECTOR_SIZE);
|
||||
_4bin = (u_int32_t *) &tmp[12]; /* Scrambled data begin at byte 12 */
|
||||
_4cipher = (u_int32_t *) seed -> streamcipher;
|
||||
for (i = 0; i < 512; i++) /* Well, the scrambling algorithm is just a bitwise XOR... */
|
||||
_4bin[i] ^= _4cipher[i];
|
||||
|
||||
//memcpy (bout, tmp + 6, SECTOR_SIZE); // copy CPR_MAI bytes
|
||||
|
||||
if (disctype==3) { //Regular
|
||||
memcpy (bout, tmp + 12, SECTOR_SIZE); // DVD: copy 2048 bytes (starting from CPR_MAI)
|
||||
}
|
||||
else { //Nintendo
|
||||
memcpy (bout, tmp + 6, SECTOR_SIZE); // Nintendo: copy 2048 bytes (up to CPR_MAI)
|
||||
memcpy (&_bin[(RAW_SECTOR_SIZE * j)+2054], &tmp[2054], 6);
|
||||
}
|
||||
|
||||
edc_calculated = edc_calc (0x00000000, tmp, EDC_LENGTH);
|
||||
edc_correct = my_ntohl (*((u_int32_t *) (&tmp[EDC_LENGTH])));
|
||||
if (edc_calculated != edc_correct) {
|
||||
debug ("Bad EDC (%08x), must be %08x (sector = %d)", edc_calculated, edc_correct, j);
|
||||
out = false;
|
||||
}
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the seed cache.
|
||||
* @param u The unscrambler structure.
|
||||
*/
|
||||
static void unscrambler_init_seeds (unscrambler *u) {
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
for (j = 0; j < MAX_SEEDS; j++)
|
||||
u -> seeds[i * MAX_SEEDS + j].seed = -1;
|
||||
|
||||
u -> seeds[i * MAX_SEEDS + j].seed = -2; // TODO Check what this does
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new structure representing an unscrambler.
|
||||
* @return The newly-created structure, to be used with the other commands.
|
||||
*/
|
||||
unscrambler *unscrambler_new (void) {
|
||||
unscrambler *u;
|
||||
|
||||
u = (unscrambler *) malloc (sizeof (unscrambler));
|
||||
unscrambler_init_seeds (u);
|
||||
u -> bruteforce_seeds = true;
|
||||
|
||||
return (u);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees resources used by an unscrambler structure and destroys it.
|
||||
* @param u The unscrambler structure.
|
||||
* @return NULL.
|
||||
*/
|
||||
void *unscrambler_destroy (unscrambler *u) {
|
||||
my_free (u);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
void unscrambler_set_bruteforce (unscrambler *u, bool b) {
|
||||
u -> bruteforce_seeds = b;
|
||||
debug ("Seed bruteforcing %s", b ? "enabled" : "disabled");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unscrambles a 16-sector block.
|
||||
* @param u The unscrambler structure.
|
||||
* @param sector_no The number of the first sector in the block.
|
||||
* @param inbuf The 16-sector block to unscramble. Each block must be RAW_SECTOR_SIZE bytes long, so that the total size is RAW_BLOCK_SIZE.
|
||||
* @param outbuf The unscrambled 16-sector block. Each block will be SECTOR_SIZE bytes long, so that the total size is BLOCK_SIZE.
|
||||
* @return True if the unscrambling was successful, false otherwise.
|
||||
*/
|
||||
bool unscrambler_unscramble_16sectors (unscrambler *u, u_int32_t sector_no, u_int8_t *inbuf, u_int8_t *outbuf) {
|
||||
t_seed *seeds;
|
||||
t_seed *current_seed;
|
||||
int j;
|
||||
bool out;
|
||||
|
||||
out = true;
|
||||
|
||||
seeds = &(u -> seeds[((sector_no / 16) & 0x0F) * MAX_SEEDS]);
|
||||
|
||||
/* Try to find the seed used for this sector */
|
||||
current_seed = NULL;
|
||||
while (!current_seed && (seeds -> seed) >= 0) {
|
||||
if (test_seed (inbuf, seeds -> seed))
|
||||
current_seed = seeds;
|
||||
else
|
||||
seeds++;
|
||||
}
|
||||
|
||||
if (!current_seed && u -> bruteforce_seeds) {
|
||||
/* The seed is not cached, yet. Try to find it with brute force... */
|
||||
unscramblerdebug ("Brute-forcing seed for sector %d...", sector_no);
|
||||
|
||||
for (j = 0; !current_seed && j < 0x7FFF; j++) {
|
||||
if (test_seed (inbuf, j)) {
|
||||
if (!(current_seed = add_seed (seeds, j))) {
|
||||
error ("No enough cache space for caching seed");
|
||||
out = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (current_seed)
|
||||
unscramblerdebug ("Seed found: %04x", --j);
|
||||
}
|
||||
|
||||
if (current_seed) {
|
||||
/* OK, somehow seed was found: unscramble frame, write it and go on */
|
||||
if (!unscramble_frame (current_seed, inbuf, outbuf)) {
|
||||
error ("Error unscrambling frame %u\n", sector_no);
|
||||
out = false;
|
||||
} else {
|
||||
out = true;
|
||||
}
|
||||
} else {
|
||||
/* Well, we only get here if there are read errors */
|
||||
error ("Cannot find seed for frame %u", sector_no);
|
||||
out = false;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unscrambles a complete file.
|
||||
* @param u The unscrambler structure.
|
||||
* @param infile The input file name.
|
||||
* @param outfile The output file name.
|
||||
* @param progress A function to be called repeatedly during the operation, useful to report progress data/statistics.
|
||||
* @param progress_data Data to be passed as-is to the progress function.
|
||||
* @return True if the unscrambling was successful, false otherwise.
|
||||
*/
|
||||
bool unscrambler_unscramble_file (unscrambler *u, char *infile, char *outfile, unscrambler_progress_func progress, void *progress_data, u_int32_t *current_sector) {
|
||||
FILE *in, *outfp;
|
||||
bool out;
|
||||
u_int8_t b_in[RAW_BLOCK_SIZE], b_out[BLOCK_SIZE];
|
||||
size_t r;
|
||||
my_off_t filesize;
|
||||
int s;
|
||||
u_int32_t total_sectors;
|
||||
|
||||
out = false;
|
||||
if(!(in = fopen (infile ? infile : "", "rb"))) {
|
||||
error ("Cannot open input file \"%s\"", infile);
|
||||
} else if (!(outfp = fopen (outfile ? outfile : "", "wb"))) {
|
||||
error ("Cannot open output file \"%s\"", outfile);
|
||||
fclose (in);
|
||||
} else {
|
||||
/* Find out how many sectors we need to process */
|
||||
my_fseek (in, 0, SEEK_END);
|
||||
filesize = my_ftell (in);
|
||||
total_sectors = (u_int32_t) (filesize / RAW_SECTOR_SIZE);
|
||||
rewind (in);
|
||||
|
||||
/* First call to progress function */
|
||||
if (progress)
|
||||
progress (true, 0, total_sectors, progress_data);
|
||||
|
||||
s = 0, out = true;
|
||||
while ((r = fread (b_in, 1, RAW_BLOCK_SIZE, in)) > 0 && out) {
|
||||
if (r < RAW_BLOCK_SIZE) {
|
||||
warning ("Short block read (%u bytes), padding with zeroes!", r);
|
||||
memset (b_in + r, 0, sizeof (b_in) - r);
|
||||
}
|
||||
|
||||
if (unscrambler_unscramble_16sectors (u, s, b_in, b_out)) {
|
||||
clearerr (outfp);
|
||||
|
||||
if (!b_out) {
|
||||
error ("NULL buffer");
|
||||
out = false;
|
||||
*(current_sector) = s;
|
||||
}
|
||||
else fwrite (b_out, SECTOR_SIZE, SECTORS_PER_BLOCK, outfp);
|
||||
if (ferror (outfp)) {
|
||||
error ("fwrite() to ISO output file failed");
|
||||
out = false;
|
||||
*(current_sector) = s;
|
||||
}
|
||||
} else {
|
||||
debug ("unscrambler_unscramble_16sectors() failed");
|
||||
out = false;
|
||||
*(current_sector) = s;
|
||||
}
|
||||
|
||||
s += 16;
|
||||
|
||||
if ((s % 320 == 0) || (s == total_sectors)) { //speedhack
|
||||
if (progress)
|
||||
progress (false, s, total_sectors, progress_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (out) {
|
||||
debug ("Image successfully unscrambled");
|
||||
}
|
||||
|
||||
fclose (in);
|
||||
fclose (outfp);
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
43
libfriidump/unscrambler.h
Normal file
43
libfriidump/unscrambler.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef UNSCRAMBLER_H_INCLUDED
|
||||
#define UNSCRAMBLER_H_INCLUDED
|
||||
|
||||
#include "misc.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef struct unscrambler_s unscrambler;
|
||||
|
||||
/* We want this module to be independent of the library framework, so that it can be easily recycled. Hence we just define the type of
|
||||
the progress function the same format we use elsewhere */
|
||||
typedef void (*unscrambler_progress_func) (bool start, u_int32_t current_sector, u_int32_t total_sectors, void *progress_data);
|
||||
|
||||
u_int8_t disctype;
|
||||
|
||||
FRIIDUMPLIB_EXPORT unscrambler *unscrambler_new (void);
|
||||
FRIIDUMPLIB_EXPORT void *unscrambler_destroy (unscrambler *u);
|
||||
FRIIDUMPLIB_EXPORT bool unscrambler_unscramble_16sectors (unscrambler *u, u_int32_t sector_no, u_int8_t *inbuf, u_int8_t *outbuf);
|
||||
FRIIDUMPLIB_EXPORT bool unscrambler_unscramble_file (unscrambler *u, char *infile, char *outfile, unscrambler_progress_func progress, void *progress_data, u_int32_t *current_sector);
|
||||
FRIIDUMPLIB_EXPORT void unscrambler_set_bruteforce (unscrambler *u, bool b);
|
||||
FRIIDUMPLIB_EXPORT void unscrambler_set_disctype (u_int8_t disc_type);
|
||||
|
||||
#endif
|
131
libfriidump/vanilla_2064.c
Normal file
131
libfriidump/vanilla_2064.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
//#include "rs.h"
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "misc.h"
|
||||
#include "dvd_drive.h"
|
||||
|
||||
/**
|
||||
* Command found in Lite-On LH-18A1H
|
||||
* Expected to work with: DH*, DW*, LH*, SH* series
|
||||
* Possibly would work with other Mediatek based drives:
|
||||
* Samsung SE*, SH* series
|
||||
* Some Dell drives
|
||||
* Some Sony drives
|
||||
* Asus DRW-1814* (DRW* series?)
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The absolute memory offset to start dumping.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int vanilla_2064_dvd_dump_memblock (dvd_drive *dvd, u_int32_t offset, u_int32_t block_size, u_int8_t *buf) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
|
||||
u_int32_t src_offset;
|
||||
u_int32_t sec_nr;
|
||||
u_int32_t sec_cnt;
|
||||
u_int32_t first_sec_nr;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else if (!block_size || block_size > 65535) {
|
||||
error ("invalid block_size (valid: 1 - 65535)");
|
||||
out = -2;
|
||||
} else {
|
||||
dvd_init_command (&mmc, buf, block_size, NULL);
|
||||
mmc.cmd[0] = 0x3C;
|
||||
mmc.cmd[1] = 0x02;
|
||||
mmc.cmd[2] = 0x00;
|
||||
mmc.cmd[3] = (unsigned char) ((offset & 0x00FF0000) >> 16); // address MSB
|
||||
mmc.cmd[4] = (unsigned char) ((offset & 0x0000FF00) >> 8); // address
|
||||
mmc.cmd[5] = (unsigned char) ( offset & 0x000000FF); // address LSB
|
||||
mmc.cmd[6] = (unsigned char) ((block_size & 0x00FF0000) >> 16);// length MSB
|
||||
mmc.cmd[7] = (unsigned char) ((block_size & 0x0000FF00) >> 8); // length
|
||||
mmc.cmd[8] = (unsigned char) ( block_size & 0x000000FF); // length LSB
|
||||
|
||||
out = dvd_execute_cmd (dvd, &mmc, false);
|
||||
|
||||
src_offset = 0;
|
||||
first_sec_nr = 0x55555555;
|
||||
sec_cnt = 0;
|
||||
while (src_offset < block_size) {
|
||||
sec_nr=(*(buf+src_offset+1)<<16)+(*(buf+src_offset+2)<<8)+(*(buf+src_offset+3));
|
||||
if (first_sec_nr==0x55555555) {
|
||||
first_sec_nr=sec_nr;
|
||||
}
|
||||
else
|
||||
if (sec_nr!=first_sec_nr+sec_cnt) {
|
||||
error ("sector sequence broken");
|
||||
out = -3;
|
||||
*(buf+src_offset+0)=0xff;
|
||||
*(buf+src_offset+1)=0xff;
|
||||
*(buf+src_offset+2)=0xff;
|
||||
*(buf+src_offset+3)=0xff;
|
||||
break;
|
||||
}
|
||||
src_offset += 2064;
|
||||
sec_cnt += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* WARNING: it can take a while to dump a lot of data.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The memory offset to start dumping, relative to the cache start offset.
|
||||
* @param block_len The number of blocks to dump.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int vanilla_2064_dvd_dump_mem (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
|
||||
u_int32_t i;
|
||||
int r, out;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else {
|
||||
r = -10;
|
||||
for (i = 0; i < block_len; i++) {
|
||||
if ((r = vanilla_2064_dvd_dump_memblock (dvd, offset + i * block_size, block_size, buf + i * block_size)) < 0) {
|
||||
error ("vanilla_2064_dvd_dump_memblock() failed with %d", r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
out = r;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
153
libfriidump/vanilla_2384.c
Normal file
153
libfriidump/vanilla_2384.c
Normal file
|
@ -0,0 +1,153 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
//#include "rs.h"
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "misc.h"
|
||||
#include "dvd_drive.h"
|
||||
|
||||
/**
|
||||
* Command found in Lite-On LH-18A1H
|
||||
* Expected to work with: DH*, DW*, LH*, SH* series
|
||||
* Possibly would work with other Mediatek based drives:
|
||||
* Samsung SE*, SH* series
|
||||
* Some Dell drives
|
||||
* Some Sony drives
|
||||
* Asus DRW-1814* (DRW* series?)
|
||||
*/
|
||||
|
||||
//u_int8_t tmp[64*1024];
|
||||
|
||||
/**
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The absolute memory offset to start dumping.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int vanilla_2384_dvd_dump_memblock (dvd_drive *dvd, u_int32_t offset, u_int32_t block_size, u_int8_t *buf) {
|
||||
mmc_command mmc;
|
||||
int out;
|
||||
u_int32_t raw_block_size;
|
||||
u_int32_t raw_offset;
|
||||
|
||||
u_int32_t src_offset;
|
||||
u_int32_t dst_offset;
|
||||
u_int32_t row_nr;
|
||||
u_int32_t sec_nr;
|
||||
u_int32_t sec_cnt;
|
||||
u_int32_t first_sec_nr;
|
||||
u_int8_t tmp[64*1024];
|
||||
//u_int8_t *tmp;
|
||||
|
||||
raw_block_size = (block_size / 2064) * 0x950;
|
||||
raw_offset = (offset / 2064) * 0x950;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else if (!block_size || raw_block_size > 65535) {
|
||||
error ("invalid raw_block_size (valid: 1 - 65535)");
|
||||
error ("raw_block_size = (block_size / 2064) * 2384");
|
||||
out = -2;
|
||||
} else {
|
||||
//tmp = malloc(64*1024);
|
||||
dvd_init_command (&mmc, tmp, raw_block_size, NULL);
|
||||
mmc.cmd[0] = 0x3C;
|
||||
mmc.cmd[1] = 0x02;
|
||||
mmc.cmd[2] = 0x00;
|
||||
mmc.cmd[3] = (unsigned char) ((raw_offset & 0x00FF0000) >> 16);// address MSB
|
||||
mmc.cmd[4] = (unsigned char) ((raw_offset & 0x0000FF00) >> 8); // address
|
||||
mmc.cmd[5] = (unsigned char) ( raw_offset & 0x000000FF); // address LSB
|
||||
mmc.cmd[6] = (unsigned char) ((raw_block_size & 0x00FF0000) >> 16); // length MSB
|
||||
mmc.cmd[7] = (unsigned char) ((raw_block_size & 0x0000FF00) >> 8); // length
|
||||
mmc.cmd[8] = (unsigned char) ( raw_block_size & 0x000000FF); // length LSB
|
||||
|
||||
out = dvd_execute_cmd (dvd, &mmc, false);
|
||||
|
||||
src_offset = 0;
|
||||
dst_offset = 0;
|
||||
first_sec_nr = 0x55555555;
|
||||
sec_cnt = 0;
|
||||
while (src_offset < raw_block_size) {
|
||||
sec_nr=(*(tmp+src_offset+1)<<16)+(*(tmp+src_offset+2)<<8)+(*(tmp+src_offset+3));
|
||||
if (first_sec_nr==0x55555555) {
|
||||
first_sec_nr=sec_nr;
|
||||
// rs_decode(tmp+src_offset, 0, 0);
|
||||
}
|
||||
else
|
||||
if (sec_nr==first_sec_nr+sec_cnt) {
|
||||
// rs_decode(tmp+src_offset, 0, 0); //sector seq = ok
|
||||
}
|
||||
else { //sector seq broken -> corrupt
|
||||
error ("sector sequence broken");
|
||||
out = -3;
|
||||
*(tmp+src_offset+0)=0xff;
|
||||
*(tmp+src_offset+1)=0xff;
|
||||
*(tmp+src_offset+2)=0xff;
|
||||
*(tmp+src_offset+3)=0xff;
|
||||
break;
|
||||
}
|
||||
for (row_nr=0; row_nr<12; row_nr++) {
|
||||
memcpy(buf+dst_offset, tmp+src_offset, 172);
|
||||
dst_offset += 172;
|
||||
src_offset += 182;
|
||||
}
|
||||
src_offset += 200;
|
||||
sec_cnt += 1;
|
||||
}
|
||||
//free(tmp);
|
||||
}
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* WARNING: it can take a while to dump a lot of data.
|
||||
* @param dvd The DVD drive the command should be exectued on.
|
||||
* @param offset The memory offset to start dumping, relative to the cache start offset.
|
||||
* @param block_len The number of blocks to dump.
|
||||
* @param block_size The block size for the dump.
|
||||
* @param buf Where to place the dumped data. This must have been setup by the caller to store up to block_size bytes.
|
||||
* @return < 0 if an error occurred, 0 otherwise.
|
||||
*/
|
||||
int vanilla_2384_dvd_dump_mem (dvd_drive *dvd, u_int32_t offset, u_int32_t block_len, u_int32_t block_size, u_int8_t *buf) {
|
||||
u_int32_t i;
|
||||
int r, out;
|
||||
|
||||
if (!buf) {
|
||||
error ("NULL buffer");
|
||||
out = -1;
|
||||
} else {
|
||||
r = -10;
|
||||
for (i = 0; i < block_len; i++) {
|
||||
if ((r = vanilla_2384_dvd_dump_memblock (dvd, offset + i * block_size, block_size, buf + i * block_size)) < 0) {
|
||||
error ("vanilla_2384_dvd_dump_memblock() failed with %d", r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
out = r;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
75
libfriidump/win32compat.c
Normal file
75
libfriidump/win32compat.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://www.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "win32compat.h"
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#include <sys/timeb.h>
|
||||
|
||||
|
||||
char *strndup (const char *src, int c) {
|
||||
char *dest;
|
||||
|
||||
if ((dest = (char *) malloc ((c + 1) * sizeof (char)))) {
|
||||
memcpy (dest, src, c);
|
||||
dest[c] = '\0';
|
||||
}
|
||||
|
||||
return (dest);
|
||||
}
|
||||
|
||||
|
||||
int ftruncate (int fd, __int64 size) {
|
||||
return (_chsize_s (fd, size));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The following gettimeofday() replacement function was taken from Snort, GPLv2 */
|
||||
/****************************************************************************
|
||||
*
|
||||
* Function: gettimeofday(struct timeval *, struct timezone *)
|
||||
*
|
||||
* Purpose: Get current time of day.
|
||||
*
|
||||
* Arguments: tv => Place to store the curent time of day.
|
||||
* tz => Ignored.
|
||||
*
|
||||
* Returns: 0 => Success.
|
||||
*
|
||||
****************************************************************************/
|
||||
int gettimeofday(struct timeval *tv, struct timezone *tz) {
|
||||
struct _timeb tb;
|
||||
|
||||
if (tv == NULL) {
|
||||
return -1;
|
||||
}
|
||||
_ftime(&tb);
|
||||
tv->tv_sec = (long) tb.time;
|
||||
tv->tv_usec = ((int) tb.millitm) * 1000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
68
libfriidump/win32compat.h
Normal file
68
libfriidump/win32compat.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://www.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
/*** WINDOWS COMPATIBILITY STUFF ***/
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <time.h>
|
||||
|
||||
/* Stuff to export library symbols */
|
||||
#ifdef FRIIDUMPLIB_BUILD_DLL
|
||||
#ifdef FRIIDUMPLIB_EXPORTS
|
||||
#define FRIIDUMPLIB_EXPORT __declspec(dllexport) /* Building the lib */
|
||||
#else
|
||||
#define FRIIDUMPLIB_EXPORT __declspec(dllimport) /* Building user code */
|
||||
#endif
|
||||
#else
|
||||
#define FRIIDUMPLIB_EXPORT
|
||||
#endif
|
||||
|
||||
/* Definition of the types we use for Windows */
|
||||
#define u_int8_t BYTE
|
||||
#define u_int16_t WORD
|
||||
#define int32_t INT32
|
||||
#define u_int32_t DWORD
|
||||
#define int64_t INT64
|
||||
#define u_int64_t ULONGLONG
|
||||
typedef long suseconds_t;
|
||||
|
||||
/* Some functions have different names */
|
||||
#define snprintf _snprintf
|
||||
#define strdup _strdup
|
||||
#define strcasecmp lstrcmpi
|
||||
#define va_copy(ap1, ap2) ((ap1) = (ap2)) // MSVC doesn't have va_copy, how crap...
|
||||
|
||||
/* Some functions do not exist (export them for applications, too) */
|
||||
FRIIDUMPLIB_EXPORT char *strndup (const char *src, int c);
|
||||
FRIIDUMPLIB_EXPORT int ftruncate (int fd, __int64 size);
|
||||
FRIIDUMPLIB_EXPORT int gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
|
||||
/* Windows does have a different localtime() */
|
||||
#define localtime_r(x, y) !localtime_s (y, x)
|
||||
|
||||
#else
|
||||
|
||||
#define FRIIDUMPLIB_EXPORT
|
||||
|
||||
#endif
|
||||
/******/
|
77
libmultihash/CMakeLists.txt
Normal file
77
libmultihash/CMakeLists.txt
Normal file
|
@ -0,0 +1,77 @@
|
|||
# Create a library called "Hello" which includes the source file "hello.cxx".
|
||||
# The extension is already found. Any number of sources could be listed here.
|
||||
add_library (
|
||||
multihashlib
|
||||
${libmultihash_type}
|
||||
#SHARED
|
||||
#STATIC
|
||||
|
||||
crc32.c
|
||||
edonkey.c
|
||||
md4.c
|
||||
md5.c
|
||||
multihash.c
|
||||
sha1.c
|
||||
crc32.h
|
||||
edonkey.h
|
||||
md4.h
|
||||
md5.h
|
||||
multihash.h
|
||||
sha1.h
|
||||
)
|
||||
|
||||
set_target_properties (multihashlib PROPERTIES OUTPUT_NAME "multihash")
|
||||
|
||||
# Before making a release, the LTVERSION string should be modified.
|
||||
# The string is of the form CURRENT:REVISION:AGE.
|
||||
#
|
||||
# CURRENT (C)
|
||||
# The most recent interface number that this library implements.
|
||||
#
|
||||
# REVISION (R)
|
||||
# The implementation number that this library implements.
|
||||
#
|
||||
# AGE (A)
|
||||
# The difference between the newest and oldest interfaces that this
|
||||
# library implements. In other works, the library implements all the
|
||||
# interface numbers in the range from number 'CURRENT - AGE' to
|
||||
# 'CURRENT'.
|
||||
#
|
||||
# This means that:
|
||||
#
|
||||
# - If interfaces have been changed or added, but binary compatibility has
|
||||
# been preserved, change to C+1:0:A+1
|
||||
#
|
||||
# - If binary compatibility has been broken (eg removed or changed
|
||||
# interfaces) change to C+1:0:0
|
||||
#
|
||||
# - If the interface is the same as the previous version, change to C:R+1:A
|
||||
#
|
||||
set_target_properties (multihashlib PROPERTIES SOVERSION 1.0.0)
|
||||
|
||||
|
||||
#get_target_property(libhash_type multihashlib TYPE)
|
||||
if (WIN32)
|
||||
if (libhash_type STREQUAL "SHARED")
|
||||
# MESSAGE ("Building libmultihash DLL")
|
||||
ADD_DEFINITIONS (-DMULTIHASH_BUILD_DLL)
|
||||
|
||||
set_target_properties (multihashlib PROPERTIES DEFINE_SYMBOL MULTIHASH_EXPORTS)
|
||||
|
||||
install (
|
||||
TARGETS multihashlib
|
||||
RUNTIME DESTINATION /
|
||||
#ARCHIVE DESTINATION lib
|
||||
)
|
||||
endif (libhash_type STREQUAL "SHARED")
|
||||
else (WIN32)
|
||||
# Install stuff, only if a shared library is being built
|
||||
if (libhash_type STREQUAL "SHARED")
|
||||
install (
|
||||
TARGETS multihashlib
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib/static
|
||||
)
|
||||
endif (libhash_type STREQUAL "SHARED")
|
||||
endif (WIN32)
|
||||
|
120
libmultihash/crc32.c
Normal file
120
libmultihash/crc32.c
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (c) 1995, Edward B. Hamrick
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that
|
||||
*
|
||||
* (i) the above copyright notice and the text in this "C" comment block
|
||||
* appear in all copies of the software and related documentation, and
|
||||
*
|
||||
* (ii) any modifications to this source file must be sent, via e-mail
|
||||
* to the copyright owner (currently hamrick@primenet.com) within
|
||||
* 30 days of such modification.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL EDWARD B. HAMRICK BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
|
||||
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "crc32.h"
|
||||
|
||||
/* This is a pre-computed table to make crc computations efficient */
|
||||
static unsigned long crctable[] = {
|
||||
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL,
|
||||
0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
|
||||
0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
|
||||
0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
|
||||
0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
|
||||
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
|
||||
0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
|
||||
0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
|
||||
0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
|
||||
0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
|
||||
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L,
|
||||
0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
|
||||
0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L,
|
||||
0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
|
||||
0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
|
||||
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
|
||||
0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
|
||||
0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
|
||||
0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L,
|
||||
0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
|
||||
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
|
||||
0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
|
||||
0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL,
|
||||
0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
|
||||
0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
|
||||
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
|
||||
0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
|
||||
0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
|
||||
0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L,
|
||||
0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
|
||||
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L,
|
||||
0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
|
||||
0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
|
||||
0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
|
||||
0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
|
||||
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
|
||||
0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
|
||||
0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
|
||||
0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
|
||||
0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
|
||||
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L,
|
||||
0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
|
||||
0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L,
|
||||
0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
|
||||
0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
|
||||
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
|
||||
0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
|
||||
0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
|
||||
0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL,
|
||||
0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
|
||||
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
|
||||
0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
|
||||
0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL,
|
||||
0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
|
||||
0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
|
||||
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
|
||||
0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
|
||||
0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
|
||||
0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L,
|
||||
0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
|
||||
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L,
|
||||
0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
|
||||
0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
|
||||
0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
|
||||
};
|
||||
|
||||
/*
|
||||
* This CRC algorithm is the same as that used in zip. Normally it
|
||||
* should be initialized with 0xffffffff, and the final CRC stored
|
||||
* should be crc ^ 0xffffffff.
|
||||
*
|
||||
* It implements the polynomial:
|
||||
*
|
||||
* x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
|
||||
*/
|
||||
|
||||
unsigned long CrcUpdate( /* returns updated crc */
|
||||
unsigned long crc, /* starting crc */
|
||||
unsigned char *buffer, /* buffer to use to update crc */
|
||||
long length /* length of buffer */
|
||||
)
|
||||
{
|
||||
long i;
|
||||
|
||||
for (i=0; i<length; i++)
|
||||
{
|
||||
crc = crctable[buffer[i] ^ ((unsigned char) crc)] ^ (crc >> 8);
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
53
libmultihash/crc32.h
Normal file
53
libmultihash/crc32.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 1995, Edward B. Hamrick
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that
|
||||
*
|
||||
* (i) the above copyright notice and the text in this "C" comment block
|
||||
* appear in all copies of the software and related documentation, and
|
||||
*
|
||||
* (ii) any modifications to this source file must be sent, via e-mail
|
||||
* to the copyright owner (currently hamrick@primenet.com) within
|
||||
* 30 days of such modification.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL EDWARD B. HAMRICK BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
|
||||
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This CRC algorithm is the same as that used in zip. Normally it
|
||||
* should be initialized with 0xffffffff, and the final CRC stored
|
||||
* should be crc ^ 0xffffffff.
|
||||
*
|
||||
* It implements the polynomial:
|
||||
*
|
||||
* x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
|
||||
*/
|
||||
|
||||
#ifndef __CRC_H
|
||||
#define __CRC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
unsigned long CrcUpdate( /* returns updated crc */
|
||||
unsigned long crc, /* starting crc */
|
||||
unsigned char *buffer, /* buffer to use to update crc */
|
||||
long length /* length of buffer */
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
83
libmultihash/edonkey.c
Normal file
83
libmultihash/edonkey.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by SukkoPera *
|
||||
* sukkopera@sukkology.net *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/* As Wikipedia (http://en.wikipedia.org/wiki/Ed2k_link) says:
|
||||
* The ed2k hash function is a MD4 root hash of a MD4 hash list, and gives a
|
||||
* different result than simply MD4: The file data is divided into full
|
||||
* chunks of 9728000 bytes plus a remainder chunk, and a separate 128-bit
|
||||
* MD4 checksum is computed for each. The ed2k hash is computed by
|
||||
* concatenating the chunks' MD4 checksums in order and hashing the result
|
||||
*using MD4.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "edonkey.h"
|
||||
#include "md4.h"
|
||||
|
||||
void ed2khash_starts (ed2khash_context *ctx) {
|
||||
md4_starts (&(ctx -> md4cur));
|
||||
md4_starts (&(ctx -> md4final));
|
||||
ctx -> bytes_processed = 0;
|
||||
ctx -> chunks = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void ed2khash_update (ed2khash_context *ctx, unsigned char *input, int ilen) {
|
||||
unsigned long x;
|
||||
|
||||
while (ilen > 0) {
|
||||
if (ctx -> bytes_processed + ilen >= ED2KHASH_CHUNKSIZE)
|
||||
x = ED2KHASH_CHUNKSIZE - ctx -> bytes_processed;
|
||||
else
|
||||
x = ilen;
|
||||
|
||||
md4_update (&(ctx -> md4cur), input, x);
|
||||
|
||||
if ((ctx -> bytes_processed += x) % ED2KHASH_CHUNKSIZE == 0) {
|
||||
/* End of a chunk, save current MD4 and start a new one */
|
||||
md4_finish (&(ctx -> md4cur), ctx -> lastmd4);
|
||||
md4_starts (&(ctx -> md4cur));
|
||||
ctx -> bytes_processed = 0;
|
||||
ctx -> chunks++;
|
||||
|
||||
md4_update (&(ctx -> md4final), ctx -> lastmd4, MD4_DIGESTSIZE);
|
||||
}
|
||||
ilen -= x;
|
||||
input += x;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void ed2khash_finish (ed2khash_context *ctx, unsigned char *output) {
|
||||
if (ctx -> chunks > 0) {
|
||||
md4_finish (&(ctx -> md4cur), ctx -> lastmd4);
|
||||
md4_update (&(ctx -> md4final), ctx -> lastmd4, MD4_DIGESTSIZE);
|
||||
md4_finish (&(ctx -> md4final), output);
|
||||
} else {
|
||||
/* If we have a single chunk, use its MD4 straight away */
|
||||
md4_finish (&(ctx -> md4cur), output);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
36
libmultihash/edonkey.h
Normal file
36
libmultihash/edonkey.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by SukkoPera *
|
||||
* sukkopera@sukkology.net *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "md4.h"
|
||||
|
||||
#define ED2KHASH_CHUNKSIZE 9728000
|
||||
#define MD4_DIGESTSIZE 16
|
||||
|
||||
typedef struct {
|
||||
unsigned long bytes_processed;
|
||||
unsigned int chunks;
|
||||
md4_context md4cur;
|
||||
md4_context md4final;
|
||||
unsigned char lastmd4[MD4_DIGESTSIZE];
|
||||
} ed2khash_context;
|
||||
|
||||
void ed2khash_starts (ed2khash_context *ctx);
|
||||
void ed2khash_update (ed2khash_context *ctx, unsigned char *input, int ilen);
|
||||
void ed2khash_finish (ed2khash_context *ctx, unsigned char *output);
|
441
libmultihash/md4.c
Normal file
441
libmultihash/md4.c
Normal file
|
@ -0,0 +1,441 @@
|
|||
/*
|
||||
* RFC 1186/1320 compliant MD4 implementation
|
||||
*
|
||||
* Copyright (C) 2006-2007 Christophe Devine
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License, version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
* The MD4 algorithm was designed by Ron Rivest in 1990.
|
||||
*
|
||||
* http://www.ietf.org/rfc/rfc1186.txt
|
||||
* http://www.ietf.org/rfc/rfc1320.txt
|
||||
*/
|
||||
|
||||
#ifndef _CRT_SECURE_NO_DEPRECATE
|
||||
#define _CRT_SECURE_NO_DEPRECATE 1
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "md4.h"
|
||||
|
||||
/*
|
||||
* 32-bit integer manipulation macros (little endian)
|
||||
*/
|
||||
#ifndef GET_UINT32_LE
|
||||
#define GET_UINT32_LE(n,b,i) \
|
||||
{ \
|
||||
(n) = ( (unsigned long) (b)[(i) ] ) \
|
||||
| ( (unsigned long) (b)[(i) + 1] << 8 ) \
|
||||
| ( (unsigned long) (b)[(i) + 2] << 16 ) \
|
||||
| ( (unsigned long) (b)[(i) + 3] << 24 ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef PUT_UINT32_LE
|
||||
#define PUT_UINT32_LE(n,b,i) \
|
||||
{ \
|
||||
(b)[(i) ] = (unsigned char) ( (n) ); \
|
||||
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
|
||||
(b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
|
||||
(b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MD4 context setup
|
||||
*/
|
||||
void md4_starts( md4_context *ctx )
|
||||
{
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
|
||||
ctx->state[0] = 0x67452301;
|
||||
ctx->state[1] = 0xEFCDAB89;
|
||||
ctx->state[2] = 0x98BADCFE;
|
||||
ctx->state[3] = 0x10325476;
|
||||
}
|
||||
|
||||
static void md4_process( md4_context *ctx, unsigned char data[64] )
|
||||
{
|
||||
unsigned long X[16], A, B, C, D;
|
||||
|
||||
GET_UINT32_LE( X[ 0], data, 0 );
|
||||
GET_UINT32_LE( X[ 1], data, 4 );
|
||||
GET_UINT32_LE( X[ 2], data, 8 );
|
||||
GET_UINT32_LE( X[ 3], data, 12 );
|
||||
GET_UINT32_LE( X[ 4], data, 16 );
|
||||
GET_UINT32_LE( X[ 5], data, 20 );
|
||||
GET_UINT32_LE( X[ 6], data, 24 );
|
||||
GET_UINT32_LE( X[ 7], data, 28 );
|
||||
GET_UINT32_LE( X[ 8], data, 32 );
|
||||
GET_UINT32_LE( X[ 9], data, 36 );
|
||||
GET_UINT32_LE( X[10], data, 40 );
|
||||
GET_UINT32_LE( X[11], data, 44 );
|
||||
GET_UINT32_LE( X[12], data, 48 );
|
||||
GET_UINT32_LE( X[13], data, 52 );
|
||||
GET_UINT32_LE( X[14], data, 56 );
|
||||
GET_UINT32_LE( X[15], data, 60 );
|
||||
|
||||
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
|
||||
|
||||
A = ctx->state[0];
|
||||
B = ctx->state[1];
|
||||
C = ctx->state[2];
|
||||
D = ctx->state[3];
|
||||
|
||||
#define F(x, y, z) ((x & y) | ((~x) & z))
|
||||
#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
|
||||
|
||||
P( A, B, C, D, X[ 0], 3 );
|
||||
P( D, A, B, C, X[ 1], 7 );
|
||||
P( C, D, A, B, X[ 2], 11 );
|
||||
P( B, C, D, A, X[ 3], 19 );
|
||||
P( A, B, C, D, X[ 4], 3 );
|
||||
P( D, A, B, C, X[ 5], 7 );
|
||||
P( C, D, A, B, X[ 6], 11 );
|
||||
P( B, C, D, A, X[ 7], 19 );
|
||||
P( A, B, C, D, X[ 8], 3 );
|
||||
P( D, A, B, C, X[ 9], 7 );
|
||||
P( C, D, A, B, X[10], 11 );
|
||||
P( B, C, D, A, X[11], 19 );
|
||||
P( A, B, C, D, X[12], 3 );
|
||||
P( D, A, B, C, X[13], 7 );
|
||||
P( C, D, A, B, X[14], 11 );
|
||||
P( B, C, D, A, X[15], 19 );
|
||||
|
||||
#undef P
|
||||
#undef F
|
||||
|
||||
#define F(x,y,z) ((x & y) | (x & z) | (y & z))
|
||||
#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
|
||||
|
||||
P( A, B, C, D, X[ 0], 3 );
|
||||
P( D, A, B, C, X[ 4], 5 );
|
||||
P( C, D, A, B, X[ 8], 9 );
|
||||
P( B, C, D, A, X[12], 13 );
|
||||
P( A, B, C, D, X[ 1], 3 );
|
||||
P( D, A, B, C, X[ 5], 5 );
|
||||
P( C, D, A, B, X[ 9], 9 );
|
||||
P( B, C, D, A, X[13], 13 );
|
||||
P( A, B, C, D, X[ 2], 3 );
|
||||
P( D, A, B, C, X[ 6], 5 );
|
||||
P( C, D, A, B, X[10], 9 );
|
||||
P( B, C, D, A, X[14], 13 );
|
||||
P( A, B, C, D, X[ 3], 3 );
|
||||
P( D, A, B, C, X[ 7], 5 );
|
||||
P( C, D, A, B, X[11], 9 );
|
||||
P( B, C, D, A, X[15], 13 );
|
||||
|
||||
#undef P
|
||||
#undef F
|
||||
|
||||
#define F(x,y,z) (x ^ y ^ z)
|
||||
#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
|
||||
|
||||
P( A, B, C, D, X[ 0], 3 );
|
||||
P( D, A, B, C, X[ 8], 9 );
|
||||
P( C, D, A, B, X[ 4], 11 );
|
||||
P( B, C, D, A, X[12], 15 );
|
||||
P( A, B, C, D, X[ 2], 3 );
|
||||
P( D, A, B, C, X[10], 9 );
|
||||
P( C, D, A, B, X[ 6], 11 );
|
||||
P( B, C, D, A, X[14], 15 );
|
||||
P( A, B, C, D, X[ 1], 3 );
|
||||
P( D, A, B, C, X[ 9], 9 );
|
||||
P( C, D, A, B, X[ 5], 11 );
|
||||
P( B, C, D, A, X[13], 15 );
|
||||
P( A, B, C, D, X[ 3], 3 );
|
||||
P( D, A, B, C, X[11], 9 );
|
||||
P( C, D, A, B, X[ 7], 11 );
|
||||
P( B, C, D, A, X[15], 15 );
|
||||
|
||||
#undef F
|
||||
#undef P
|
||||
|
||||
ctx->state[0] += A;
|
||||
ctx->state[1] += B;
|
||||
ctx->state[2] += C;
|
||||
ctx->state[3] += D;
|
||||
}
|
||||
|
||||
/*
|
||||
* MD4 process buffer
|
||||
*/
|
||||
void md4_update( md4_context *ctx, unsigned char *input, int ilen )
|
||||
{
|
||||
int fill;
|
||||
unsigned long left;
|
||||
|
||||
if( ilen <= 0 )
|
||||
return;
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += ilen;
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if( ctx->total[0] < (unsigned long) ilen )
|
||||
ctx->total[1]++;
|
||||
|
||||
if( left && ilen >= fill )
|
||||
{
|
||||
memcpy( (void *) (ctx->buffer + left),
|
||||
(void *) input, fill );
|
||||
md4_process( ctx, ctx->buffer );
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while( ilen >= 64 )
|
||||
{
|
||||
md4_process( ctx, input );
|
||||
input += 64;
|
||||
ilen -= 64;
|
||||
}
|
||||
|
||||
if( ilen > 0 )
|
||||
{
|
||||
memcpy( (void *) (ctx->buffer + left),
|
||||
(void *) input, ilen );
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned char md4_padding[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* MD4 final digest
|
||||
*/
|
||||
void md4_finish( md4_context *ctx, unsigned char *output )
|
||||
{
|
||||
unsigned long last, padn;
|
||||
unsigned long high, low;
|
||||
unsigned char msglen[8];
|
||||
|
||||
high = ( ctx->total[0] >> 29 )
|
||||
| ( ctx->total[1] << 3 );
|
||||
low = ( ctx->total[0] << 3 );
|
||||
|
||||
PUT_UINT32_LE( low, msglen, 0 );
|
||||
PUT_UINT32_LE( high, msglen, 4 );
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
||||
|
||||
md4_update( ctx, (unsigned char *) md4_padding, padn );
|
||||
md4_update( ctx, msglen, 8 );
|
||||
|
||||
PUT_UINT32_LE( ctx->state[0], output, 0 );
|
||||
PUT_UINT32_LE( ctx->state[1], output, 4 );
|
||||
PUT_UINT32_LE( ctx->state[2], output, 8 );
|
||||
PUT_UINT32_LE( ctx->state[3], output, 12 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Output = MD4( input buffer )
|
||||
*/
|
||||
void md4( unsigned char *input, int ilen,
|
||||
unsigned char *output )
|
||||
{
|
||||
md4_context ctx;
|
||||
|
||||
md4_starts( &ctx );
|
||||
md4_update( &ctx, input, ilen );
|
||||
md4_finish( &ctx, output );
|
||||
|
||||
memset( &ctx, 0, sizeof( md4_context ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Output = MD4( file contents )
|
||||
*/
|
||||
int md4_file( char *path, unsigned char *output )
|
||||
{
|
||||
FILE *f;
|
||||
size_t n;
|
||||
md4_context ctx;
|
||||
unsigned char buf[1024];
|
||||
|
||||
if( ( f = fopen( path, "rb" ) ) == NULL )
|
||||
return( 1 );
|
||||
|
||||
md4_starts( &ctx );
|
||||
|
||||
while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
|
||||
md4_update( &ctx, buf, (int) n );
|
||||
|
||||
md4_finish( &ctx, output );
|
||||
|
||||
memset( &ctx, 0, sizeof( md4_context ) );
|
||||
|
||||
if( ferror( f ) != 0 )
|
||||
{
|
||||
fclose( f );
|
||||
return( 2 );
|
||||
}
|
||||
|
||||
fclose( f );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* MD4 HMAC context setup
|
||||
*/
|
||||
void md4_hmac_starts( md4_context *ctx,
|
||||
unsigned char *key, int keylen )
|
||||
{
|
||||
int i;
|
||||
|
||||
memset( ctx->ipad, 0x36, 64 );
|
||||
memset( ctx->opad, 0x5C, 64 );
|
||||
|
||||
for( i = 0; i < keylen; i++ )
|
||||
{
|
||||
if( i >= 64 ) break;
|
||||
|
||||
ctx->ipad[i] ^= key[i];
|
||||
ctx->opad[i] ^= key[i];
|
||||
}
|
||||
|
||||
md4_starts( ctx );
|
||||
md4_update( ctx, ctx->ipad, 64 );
|
||||
}
|
||||
|
||||
/*
|
||||
* MD4 HMAC process buffer
|
||||
*/
|
||||
void md4_hmac_update( md4_context *ctx,
|
||||
unsigned char *input, int ilen )
|
||||
{
|
||||
md4_update( ctx, input, ilen );
|
||||
}
|
||||
|
||||
/*
|
||||
* MD4 HMAC final digest
|
||||
*/
|
||||
void md4_hmac_finish( md4_context *ctx, unsigned char *output )
|
||||
{
|
||||
unsigned char tmpbuf[16];
|
||||
|
||||
md4_finish( ctx, tmpbuf );
|
||||
md4_starts( ctx );
|
||||
md4_update( ctx, ctx->opad, 64 );
|
||||
md4_update( ctx, tmpbuf, 16 );
|
||||
md4_finish( ctx, output );
|
||||
|
||||
memset( tmpbuf, 0, sizeof( tmpbuf ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Output = HMAC-MD4( hmac key, input buffer )
|
||||
*/
|
||||
void md4_hmac( unsigned char *key, int keylen,
|
||||
unsigned char *input, int ilen,
|
||||
unsigned char *output )
|
||||
{
|
||||
md4_context ctx;
|
||||
|
||||
md4_hmac_starts( &ctx, key, keylen );
|
||||
md4_hmac_update( &ctx, input, ilen );
|
||||
md4_hmac_finish( &ctx, output );
|
||||
|
||||
memset( &ctx, 0, sizeof( md4_context ) );
|
||||
}
|
||||
|
||||
static const char _md4_src[] = "_md4_src";
|
||||
|
||||
#if defined(SELF_TEST)
|
||||
/*
|
||||
* RFC 1320 test vectors
|
||||
*/
|
||||
static const char md4_test_str[7][81] =
|
||||
{
|
||||
{ "" },
|
||||
{ "a" },
|
||||
{ "abc" },
|
||||
{ "message digest" },
|
||||
{ "abcdefghijklmnopqrstuvwxyz" },
|
||||
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
|
||||
{ "12345678901234567890123456789012345678901234567890123456789012" \
|
||||
"345678901234567890" }
|
||||
};
|
||||
|
||||
static const unsigned char md4_test_sum[7][16] =
|
||||
{
|
||||
{ 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
|
||||
0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
|
||||
{ 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
|
||||
0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
|
||||
{ 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
|
||||
0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
|
||||
{ 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
|
||||
0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
|
||||
{ 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
|
||||
0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
|
||||
{ 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
|
||||
0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
|
||||
{ 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
|
||||
0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
|
||||
};
|
||||
|
||||
/*
|
||||
* Checkup routine
|
||||
*/
|
||||
int md4_self_test( int verbose )
|
||||
{
|
||||
int i;
|
||||
unsigned char md4sum[16];
|
||||
|
||||
for( i = 0; i < 7; i++ )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
printf( " MD4 test #%d: ", i + 1 );
|
||||
|
||||
md4( (unsigned char *) md4_test_str[i],
|
||||
strlen( md4_test_str[i] ), md4sum );
|
||||
|
||||
if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
printf( "failed\n" );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
printf( "passed\n" );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
printf( "\n" );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#else
|
||||
int md4_self_test( int verbose )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
#endif
|
121
libmultihash/md4.h
Normal file
121
libmultihash/md4.h
Normal file
|
@ -0,0 +1,121 @@
|
|||
/**
|
||||
* \file md4.h
|
||||
*/
|
||||
#ifndef _MD4_H
|
||||
#define _MD4_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief MD4 context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned long total[2]; /*!< number of bytes processed */
|
||||
unsigned long state[4]; /*!< intermediate digest state */
|
||||
unsigned char buffer[64]; /*!< data block being processed */
|
||||
unsigned char ipad[64]; /*!< HMAC: inner padding */
|
||||
unsigned char opad[64]; /*!< HMAC: outer padding */
|
||||
}
|
||||
md4_context;
|
||||
|
||||
/**
|
||||
* \brief MD4 context setup
|
||||
*
|
||||
* \param ctx context to be initialized
|
||||
*/
|
||||
void md4_starts( md4_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief MD4 process buffer
|
||||
*
|
||||
* \param ctx MD4 context
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
*/
|
||||
void md4_update( md4_context *ctx, unsigned char *input, int ilen );
|
||||
|
||||
/**
|
||||
* \brief MD4 final digest
|
||||
*
|
||||
* \param ctx MD4 context
|
||||
* \param output MD4 checksum result
|
||||
*/
|
||||
void md4_finish( md4_context *ctx, unsigned char *output );
|
||||
|
||||
/**
|
||||
* \brief Output = MD4( input buffer )
|
||||
*
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
* \param output MD4 checksum result
|
||||
*/
|
||||
void md4( unsigned char *input, int ilen,
|
||||
unsigned char *output );
|
||||
|
||||
/**
|
||||
* \brief Output = MD4( file contents )
|
||||
*
|
||||
* \param path input file name
|
||||
* \param output MD4 checksum result
|
||||
*
|
||||
* \return 0 if successful, 1 if fopen failed,
|
||||
* or 2 if fread failed
|
||||
*/
|
||||
int md4_file( char *path, unsigned char *output );
|
||||
|
||||
/**
|
||||
* \brief MD4 HMAC context setup
|
||||
*
|
||||
* \param ctx HMAC context to be initialized
|
||||
* \param key HMAC secret key
|
||||
* \param keylen length of the HMAC key
|
||||
*/
|
||||
void md4_hmac_starts( md4_context *ctx,
|
||||
unsigned char *key, int keylen );
|
||||
|
||||
/**
|
||||
* \brief MD4 HMAC process buffer
|
||||
*
|
||||
* \param ctx HMAC context
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
*/
|
||||
void md4_hmac_update( md4_context *ctx,
|
||||
unsigned char *input, int ilen );
|
||||
|
||||
/**
|
||||
* \brief MD4 HMAC final digest
|
||||
*
|
||||
* \param ctx HMAC context
|
||||
* \param output MD4 HMAC checksum result
|
||||
*/
|
||||
void md4_hmac_finish( md4_context *ctx, unsigned char *output );
|
||||
|
||||
/**
|
||||
* \brief Output = HMAC-MD4( hmac key, input buffer )
|
||||
*
|
||||
* \param key HMAC secret key
|
||||
* \param keylen length of the HMAC key
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
* \param output HMAC-MD4 result
|
||||
*/
|
||||
void md4_hmac( unsigned char *key, int keylen,
|
||||
unsigned char *input, int ilen,
|
||||
unsigned char *output );
|
||||
|
||||
/**
|
||||
* \brief Checkup routine
|
||||
*
|
||||
* \return 0 if successful, or 1 if the test failed
|
||||
*/
|
||||
int md4_self_test( int verbose );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* md4.h */
|
477
libmultihash/md5.c
Normal file
477
libmultihash/md5.c
Normal file
|
@ -0,0 +1,477 @@
|
|||
/*
|
||||
**********************************************************************
|
||||
** 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;
|
||||
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)
|
||||
MD5_CTX *mdContext;
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
** End of md5.c **
|
||||
******************************* (cut) ********************************
|
||||
*/
|
||||
|
||||
#if 0
|
||||
/*
|
||||
**********************************************************************
|
||||
** md5driver.c -- sample routines to test **
|
||||
** RSA Data Security, Inc. MD5 message digest algorithm. **
|
||||
** Created: 2/16/90 RLR **
|
||||
** Updated: 1/91 SRD **
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
|
||||
** **
|
||||
** 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 <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
/* -- include the following file if the file md5.h is separate -- */
|
||||
/* #include "md5.h" */
|
||||
|
||||
/* Prints message digest buffer in mdContext as 32 hexadecimal digits.
|
||||
Order is from low-order byte to high-order byte of digest.
|
||||
Each byte is printed with high-order hexadecimal digit first.
|
||||
*/
|
||||
static void MDPrint (mdContext)
|
||||
MD5_CTX *mdContext;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
printf ("%02x", mdContext->digest[i]);
|
||||
}
|
||||
|
||||
/* size of test block */
|
||||
#define TEST_BLOCK_SIZE 1000
|
||||
|
||||
/* number of blocks to process */
|
||||
#define TEST_BLOCKS 10000
|
||||
|
||||
/* number of test bytes = TEST_BLOCK_SIZE * TEST_BLOCKS */
|
||||
static long TEST_BYTES = (long)TEST_BLOCK_SIZE * (long)TEST_BLOCKS;
|
||||
|
||||
/* A time trial routine, to measure the speed of MD5.
|
||||
Measures wall time required to digest TEST_BLOCKS * TEST_BLOCK_SIZE
|
||||
characters.
|
||||
*/
|
||||
static void MDTimeTrial ()
|
||||
{
|
||||
MD5_CTX mdContext;
|
||||
time_t endTime, startTime;
|
||||
unsigned char data[TEST_BLOCK_SIZE];
|
||||
unsigned int i;
|
||||
|
||||
/* initialize test data */
|
||||
for (i = 0; i < TEST_BLOCK_SIZE; i++)
|
||||
data[i] = (unsigned char)(i & 0xFF);
|
||||
|
||||
/* start timer */
|
||||
printf ("MD5 time trial. Processing %ld characters...\n", TEST_BYTES);
|
||||
time (&startTime);
|
||||
|
||||
/* digest data in TEST_BLOCK_SIZE byte blocks */
|
||||
MD5Init (&mdContext);
|
||||
for (i = TEST_BLOCKS; i > 0; i--)
|
||||
MD5Update (&mdContext, data, TEST_BLOCK_SIZE);
|
||||
MD5Final (&mdContext);
|
||||
|
||||
/* stop timer, get time difference */
|
||||
time (&endTime);
|
||||
MDPrint (&mdContext);
|
||||
printf (" is digest of test input.\n");
|
||||
printf
|
||||
("Seconds to process test input: %ld\n", (long)(endTime-startTime));
|
||||
printf
|
||||
("Characters processed per second: %ld\n",
|
||||
TEST_BYTES/(endTime-startTime));
|
||||
}
|
||||
|
||||
/* Computes the message digest for string inString.
|
||||
Prints out message digest, a space, the string (in quotes) and a
|
||||
carriage return.
|
||||
*/
|
||||
static void MDString (inString)
|
||||
char *inString;
|
||||
{
|
||||
MD5_CTX mdContext;
|
||||
unsigned int len = strlen (inString);
|
||||
|
||||
MD5Init (&mdContext);
|
||||
MD5Update (&mdContext, inString, len);
|
||||
MD5Final (&mdContext);
|
||||
MDPrint (&mdContext);
|
||||
printf (" \"%s\"\n\n", inString);
|
||||
}
|
||||
|
||||
/* Computes the message digest for a specified file.
|
||||
Prints out message digest, a space, the file name, and a carriage
|
||||
return.
|
||||
*/
|
||||
static void MDFile (filename)
|
||||
char *filename;
|
||||
{
|
||||
FILE *inFile = fopen (filename, "rb");
|
||||
MD5_CTX mdContext;
|
||||
int bytes;
|
||||
unsigned char data[1024];
|
||||
|
||||
if (inFile == NULL) {
|
||||
printf ("%s can't be opened.\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
MD5Init (&mdContext);
|
||||
while ((bytes = fread (data, 1, 1024, inFile)) != 0)
|
||||
MD5Update (&mdContext, data, bytes);
|
||||
MD5Final (&mdContext);
|
||||
MDPrint (&mdContext);
|
||||
printf (" %s\n", filename);
|
||||
fclose (inFile);
|
||||
}
|
||||
|
||||
/* Writes the message digest of the data from stdin onto stdout,
|
||||
followed by a carriage return.
|
||||
*/
|
||||
static void MDFilter ()
|
||||
{
|
||||
MD5_CTX mdContext;
|
||||
int bytes;
|
||||
unsigned char data[16];
|
||||
|
||||
MD5Init (&mdContext);
|
||||
while ((bytes = fread (data, 1, 16, stdin)) != 0)
|
||||
MD5Update (&mdContext, data, bytes);
|
||||
MD5Final (&mdContext);
|
||||
MDPrint (&mdContext);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
/* Runs a standard suite of test data.
|
||||
*/
|
||||
static void MDTestSuite ()
|
||||
{
|
||||
printf ("MD5 test suite results:\n\n");
|
||||
MDString ("");
|
||||
MDString ("a");
|
||||
MDString ("abc");
|
||||
MDString ("message digest");
|
||||
MDString ("abcdefghijklmnopqrstuvwxyz");
|
||||
MDString
|
||||
("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
|
||||
MDString
|
||||
("1234567890123456789012345678901234567890\
|
||||
1234567890123456789012345678901234567890");
|
||||
/* Contents of file foo are "abc" */
|
||||
MDFile ("foo");
|
||||
}
|
||||
|
||||
void main (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int i;
|
||||
|
||||
/* For each command line argument in turn:
|
||||
** filename -- prints message digest and name of file
|
||||
** -sstring -- prints message digest and contents of string
|
||||
** -t -- prints time trial statistics for 1M characters
|
||||
** -x -- execute a standard suite of test data
|
||||
** (no args) -- writes messages digest of stdin onto stdout
|
||||
*/
|
||||
if (argc == 1)
|
||||
MDFilter ();
|
||||
else
|
||||
for (i = 1; i < argc; i++)
|
||||
if (argv[i][0] == '-' && argv[i][1] == 's')
|
||||
MDString (argv[i] + 2);
|
||||
else if (strcmp (argv[i], "-t") == 0)
|
||||
MDTimeTrial ();
|
||||
else if (strcmp (argv[i], "-x") == 0)
|
||||
MDTestSuite ();
|
||||
else MDFile (argv[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
** End of md5driver.c **
|
||||
******************************* (cut) ********************************
|
||||
*/
|
||||
#endif
|
59
libmultihash/md5.h
Normal file
59
libmultihash/md5.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
**********************************************************************
|
||||
** 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. **
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/* typedef a 32 bit type */
|
||||
typedef unsigned long int UINT4;
|
||||
|
||||
/* 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 ();
|
||||
void MD5Update ();
|
||||
void MD5Final ();
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
** End of md5.h **
|
||||
******************************* (cut) ********************************
|
||||
*/
|
130
libmultihash/multihash.c
Normal file
130
libmultihash/multihash.c
Normal file
|
@ -0,0 +1,130 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by SukkoPera *
|
||||
* sukkopera@sukkology.net *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "multihash.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define READBUF_SIZE 8192
|
||||
|
||||
|
||||
void multihash_init (multihash *mh) {
|
||||
#ifdef USE_CRC32
|
||||
(mh -> crc32_s)[0] = '\0';
|
||||
mh -> crc32 = 0xffffffff;
|
||||
#endif
|
||||
#ifdef USE_MD4
|
||||
(mh -> md4_s)[0] = '\0';
|
||||
md4_starts (&(mh -> md4));
|
||||
#endif
|
||||
#ifdef USE_MD5
|
||||
(mh -> md5_s)[0] = '\0';
|
||||
MD5Init (&(mh -> md5));
|
||||
#endif
|
||||
#ifdef USE_ED2K
|
||||
(mh -> ed2k_s)[0] = '\0';
|
||||
ed2khash_starts (&(mh -> ed2k));
|
||||
#endif
|
||||
#ifdef USE_SHA1
|
||||
(mh -> sha1_s)[0] = '\0';
|
||||
SHA1Init (&(mh -> sha1));
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void multihash_update (multihash *mh, unsigned char *data, int bytes) {
|
||||
#ifdef USE_CRC32
|
||||
mh -> crc32 = CrcUpdate (mh -> crc32, data, bytes);
|
||||
#endif
|
||||
#ifdef USE_MD4
|
||||
// md4_update (&(mh -> md4), data, bytes);
|
||||
#endif
|
||||
#ifdef USE_MD5
|
||||
MD5Update (&(mh -> md5), data, bytes);
|
||||
#endif
|
||||
#ifdef USE_ED2K
|
||||
// ed2khash_update (&(mh -> ed2k), data, bytes);
|
||||
#endif
|
||||
#ifdef USE_SHA1
|
||||
SHA1Update (&(mh -> sha1), data, bytes); /* WARNING: SHA1Update() destroys data! */
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void multihash_finish (multihash *mh) {
|
||||
unsigned char buf[MAX_DIGESTSIZE];
|
||||
int bytes;
|
||||
|
||||
#ifdef USE_CRC32
|
||||
mh -> crc32 ^= 0xffffffff;
|
||||
snprintf (mh -> crc32_s, LEN_CRC32 + 1, "%08x", mh -> crc32);
|
||||
#endif
|
||||
#ifdef USE_MD4
|
||||
md4_finish (&(mh -> md4), buf);
|
||||
for (bytes = 0; bytes < LEN_MD4 / 2; bytes++)
|
||||
sprintf (mh -> md4_s, "%s%02x", mh -> md4_s, buf[bytes]);
|
||||
(mh -> md4_s)[LEN_MD4] = '\0';
|
||||
#endif
|
||||
#ifdef USE_MD5
|
||||
MD5Final (&(mh -> md5));
|
||||
for (bytes = 0; bytes < LEN_MD5 / 2; bytes++)
|
||||
sprintf (mh -> md5_s, "%s%02x", mh -> md5_s, (mh -> md5).digest[bytes]);
|
||||
(mh -> md5_s)[LEN_MD5] = '\0';
|
||||
#endif
|
||||
#ifdef USE_ED2K
|
||||
ed2khash_finish (&(mh -> ed2k), buf);
|
||||
for (bytes = 0; bytes < LEN_ED2K / 2; bytes++)
|
||||
sprintf (mh -> ed2k_s, "%s%02x", mh -> ed2k_s, buf[bytes]);
|
||||
(mh -> ed2k_s)[LEN_ED2K] = '\0';
|
||||
#endif
|
||||
#ifdef USE_SHA1
|
||||
SHA1Final (buf, &(mh -> sha1));
|
||||
for (bytes = 0; bytes < LEN_SHA1 / 2; bytes++)
|
||||
sprintf (mh -> sha1_s, "%s%02x", mh -> sha1_s, buf[bytes]);
|
||||
(mh -> sha1_s)[LEN_SHA1] = '\0';
|
||||
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int multihash_file (multihash *mh, char *filename) {
|
||||
FILE *fp;
|
||||
int bytes, out;
|
||||
unsigned char data[READBUF_SIZE];
|
||||
|
||||
multihash_init (mh);
|
||||
if ((fp = fopen (filename, "r"))) {
|
||||
while ((bytes = fread (data, 1, READBUF_SIZE, fp)) != 0)
|
||||
multihash_update (mh, data, bytes);
|
||||
multihash_finish (mh);
|
||||
fclose (fp);
|
||||
out = 0;
|
||||
} else {
|
||||
/* Cannot open file */
|
||||
out = -1;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
127
libmultihash/multihash.h
Normal file
127
libmultihash/multihash.h
Normal file
|
@ -0,0 +1,127 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by SukkoPera *
|
||||
* sukkopera@sukkology.net *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MULTIHASH_H_INCLUDED
|
||||
#define MULTIHASH_H_INCLUDED
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
|
||||
/* Definition of the types we use for Windows */
|
||||
#define u_int8_t BYTE
|
||||
#define u_int16_t WORD
|
||||
#define u_int32_t DWORD
|
||||
|
||||
/* Some functions have different names */
|
||||
#define snprintf _snprintf
|
||||
|
||||
/* Stuff to export library symbols */
|
||||
#ifdef MULTIHASH_BUILD_DLL
|
||||
#ifdef MULTIHASH_EXPORTS
|
||||
#define MULTIHASH_EXPORT __declspec(dllexport) /* Building the lib */
|
||||
#else
|
||||
#define MULTIHASH_EXPORT __declspec(dllimport) /* Building user code */
|
||||
#endif
|
||||
#else
|
||||
#define MULTIHASH_EXPORT
|
||||
#endif
|
||||
|
||||
#else /* !WIN32 */
|
||||
|
||||
#define MULTIHASH_EXPORT
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define USE_CRC32
|
||||
#define USE_MD4
|
||||
#define USE_MD5
|
||||
#define USE_ED2K
|
||||
#define USE_SHA1
|
||||
|
||||
#ifdef USE_CRC32
|
||||
#include <sys/types.h>
|
||||
#include "crc32.h"
|
||||
#define LEN_CRC32 8
|
||||
#endif
|
||||
|
||||
#ifdef USE_MD4
|
||||
#include "md4.h"
|
||||
#define LEN_MD4 32
|
||||
#define MD4_DIGESTSIZE 16
|
||||
#endif
|
||||
|
||||
#ifdef USE_MD5
|
||||
#include "md5.h"
|
||||
#define LEN_MD5 32
|
||||
#endif
|
||||
|
||||
#ifdef USE_ED2K
|
||||
#include "edonkey.h"
|
||||
#define LEN_ED2K 32
|
||||
#endif
|
||||
|
||||
#ifdef USE_SHA1
|
||||
#include "sha1.h"
|
||||
#define LEN_SHA1 40
|
||||
#endif
|
||||
|
||||
/* This must be as long as the longest hash (in bytes) */
|
||||
#define MAX_DIGESTSIZE 20
|
||||
|
||||
typedef struct {
|
||||
#ifdef USE_CRC32
|
||||
u_int32_t crc32;
|
||||
char crc32_s[LEN_CRC32 + 1];
|
||||
#endif
|
||||
#ifdef USE_MD4
|
||||
md4_context md4;
|
||||
char md4_s[LEN_MD4 + 1];
|
||||
#endif
|
||||
#ifdef USE_MD5
|
||||
MD5_CTX md5;
|
||||
char md5_s[LEN_MD5 + 1];
|
||||
#endif
|
||||
#ifdef USE_ED2K
|
||||
ed2khash_context ed2k;
|
||||
char ed2k_s[LEN_ED2K + 1];
|
||||
#endif
|
||||
#ifdef USE_SHA1
|
||||
SHA1_CTX sha1;
|
||||
char sha1_s[LEN_SHA1 + 1];
|
||||
#endif
|
||||
} multihash;
|
||||
|
||||
|
||||
/* Prototypes */
|
||||
MULTIHASH_EXPORT void multihash_init (multihash *mh);
|
||||
MULTIHASH_EXPORT void multihash_update (multihash *mh, unsigned char *data, int bytes);
|
||||
MULTIHASH_EXPORT void multihash_finish (multihash *mh);
|
||||
MULTIHASH_EXPORT int multihash_file (multihash *mh, char *filename);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
231
libmultihash/sha1.c
Normal file
231
libmultihash/sha1.c
Normal file
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
** sha1.c
|
||||
**
|
||||
** Contains all of the SHA1 functions: SHA1Transform, SHA1Init, SHA1Update, and SHA1Final.
|
||||
** Make sure to define _LITTLE_ENDIAN if running on a little endian machine and NOT to
|
||||
** define it otherwise.
|
||||
**
|
||||
** Copyright NTT MCL, 2000.
|
||||
**
|
||||
** Satomi Okazaki
|
||||
** Security Group, NTT MCL
|
||||
** November 1999
|
||||
**
|
||||
**************************
|
||||
** 13 December 1999. In SHA1Transform, changed "buffer" to be const.
|
||||
** In SHA1Update, changed "data to be const. -- S.O.
|
||||
*/
|
||||
#include "sha1.h"
|
||||
|
||||
#define _LITTLE_ENDIAN /* should be defined if so */
|
||||
|
||||
/* Rotation of "value" by "bits" to the left */
|
||||
#define rotLeft(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||
|
||||
/* Basic SHA1 functions */
|
||||
#define f(u,v,w) (((u) & (v)) | ((~u) & (w)))
|
||||
#define g(u,v,w) (((u) & (v)) | ((u) & (w)) | ((v) & (w)))
|
||||
#define h(u,v,w) ((u) ^ (v) ^ (w))
|
||||
|
||||
/* These are the 16 4-byte words of the 64-byte block */
|
||||
#ifdef _LITTLE_ENDIAN
|
||||
/* Reverse the order of the bytes in the i-th 4-byte word */
|
||||
#define x(i) (block->l[i] = (rotLeft(block->l[i], 24)& 0xff00ff00) \
|
||||
| (rotLeft(block->l[i], 8) & 0x00ff00ff))
|
||||
#else
|
||||
#define x(i) (block->l[i])
|
||||
#endif
|
||||
|
||||
/* Used in expanding from a 16 word block into an 80 word block */
|
||||
#define X(i) (block->l[(i)%16] = rotLeft (block->l[((i)-3)%16] ^ block->l[((i)-8)%16] \
|
||||
^ block->l[((i)-14)%16] ^ block->l[((i)-16)%16],1))
|
||||
|
||||
/* (R0+R1), R2, R3, R4 are the different round operations used in SHA1 */
|
||||
#define R0(a, b, c, d, e, i) { \
|
||||
(e) += f((b), (c), (d)) + (x(i)) + 0x5A827999 + rotLeft((a),5); \
|
||||
(b) = rotLeft((b), 30); \
|
||||
}
|
||||
#define R1(a, b, c, d, e, i) { \
|
||||
(e) += f((b), (c), (d)) + (X(i)) + 0x5A827999 + rotLeft((a),5); \
|
||||
(b) = rotLeft((b), 30); \
|
||||
}
|
||||
#define R2(a, b, c, d, e, i) { \
|
||||
(e) += h((b), (c), (d)) + (X(i)) + 0x6ED9EBA1 + rotLeft((a),5); \
|
||||
(b) = rotLeft((b), 30); \
|
||||
}
|
||||
#define R3(a, b, c, d, e, i) { \
|
||||
(e) += g((b), (c), (d)) + (X(i)) + 0x8F1BBCDC + rotLeft((a),5); \
|
||||
(b) = rotLeft((b), 30); \
|
||||
}
|
||||
#define R4(a, b, c, d, e, i) { \
|
||||
(e) += h((b), (c), (d)) + (X(i)) + 0xCA62C1D6 + rotLeft((a),5); \
|
||||
(b) = rotLeft((b), 30); \
|
||||
}
|
||||
|
||||
/* Hashes a single 512-bit block. This is the compression function - the core of the algorithm.
|
||||
**/
|
||||
void SHA1Transform(
|
||||
unsigned long state[5],
|
||||
const unsigned char buffer[SHA1_BLOCKSIZE]
|
||||
)
|
||||
{
|
||||
unsigned long a, b, c, d, e;
|
||||
|
||||
typedef union {
|
||||
unsigned char c[64];
|
||||
unsigned long l[16];
|
||||
} CHAR64LONG16;
|
||||
|
||||
/* This is for the X array */
|
||||
CHAR64LONG16* block = (CHAR64LONG16*)buffer;
|
||||
|
||||
/* Initialize working variables */
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
e = state[4];
|
||||
|
||||
/* 4 rounds of 20 operations each. */
|
||||
/* Round 1 */
|
||||
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
|
||||
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
|
||||
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e, 10); R0(e,a,b,c,d, 11);
|
||||
R0(d,e,a,b,c, 12); R0(c,d,e,a,b, 13); R0(b,c,d,e,a, 14); R0(a,b,c,d,e, 15);
|
||||
R1(e,a,b,c,d, 16); R1(d,e,a,b,c, 17); R1(c,d,e,a,b, 18); R1(b,c,d,e,a, 19);
|
||||
|
||||
/* Round 2 */
|
||||
R2(a,b,c,d,e, 20); R2(e,a,b,c,d, 21); R2(d,e,a,b,c, 22); R2(c,d,e,a,b, 23);
|
||||
R2(b,c,d,e,a, 24); R2(a,b,c,d,e, 25); R2(e,a,b,c,d, 26); R2(d,e,a,b,c, 27);
|
||||
R2(c,d,e,a,b, 28); R2(b,c,d,e,a, 29); R2(a,b,c,d,e, 30); R2(e,a,b,c,d, 31);
|
||||
R2(d,e,a,b,c, 32); R2(c,d,e,a,b, 33); R2(b,c,d,e,a, 34); R2(a,b,c,d,e, 35);
|
||||
R2(e,a,b,c,d, 36); R2(d,e,a,b,c, 37); R2(c,d,e,a,b, 38); R2(b,c,d,e,a, 39);
|
||||
|
||||
/* Round 3 */
|
||||
R3(a,b,c,d,e, 40); R3(e,a,b,c,d, 41); R3(d,e,a,b,c, 42); R3(c,d,e,a,b, 43);
|
||||
R3(b,c,d,e,a, 44); R3(a,b,c,d,e, 45); R3(e,a,b,c,d, 46); R3(d,e,a,b,c, 47);
|
||||
R3(c,d,e,a,b, 48); R3(b,c,d,e,a, 49); R3(a,b,c,d,e, 50); R3(e,a,b,c,d, 51);
|
||||
R3(d,e,a,b,c, 52); R3(c,d,e,a,b, 53); R3(b,c,d,e,a, 54); R3(a,b,c,d,e, 55);
|
||||
R3(e,a,b,c,d, 56); R3(d,e,a,b,c, 57); R3(c,d,e,a,b, 58); R3(b,c,d,e,a, 59);
|
||||
|
||||
/* Round 4 */
|
||||
R4(a,b,c,d,e, 60); R4(e,a,b,c,d, 61); R4(d,e,a,b,c, 62); R4(c,d,e,a,b, 63);
|
||||
R4(b,c,d,e,a, 64); R4(a,b,c,d,e, 65); R4(e,a,b,c,d, 66); R4(d,e,a,b,c, 67);
|
||||
R4(c,d,e,a,b, 68); R4(b,c,d,e,a, 69); R4(a,b,c,d,e, 70); R4(e,a,b,c,d, 71);
|
||||
R4(d,e,a,b,c, 72); R4(c,d,e,a,b, 73); R4(b,c,d,e,a, 74); R4(a,b,c,d,e, 75);
|
||||
R4(e,a,b,c,d, 76); R4(d,e,a,b,c, 77); R4(c,d,e,a,b, 78); R4(b,c,d,e,a, 79);
|
||||
|
||||
/* Update the chaining values */
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
state[4] += e;
|
||||
|
||||
/* Wipe variables */
|
||||
a = b = c = d = e = 0;
|
||||
}
|
||||
|
||||
/* SHA1Init - Initialize new context.
|
||||
**/
|
||||
void SHA1Init(
|
||||
SHA1_CTX* context
|
||||
)
|
||||
{
|
||||
/* SHA1 initialization constants */
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xEFCDAB89;
|
||||
context->state[2] = 0x98BADCFE;
|
||||
context->state[3] = 0x10325476;
|
||||
context->state[4] = 0xC3D2E1F0;
|
||||
context->count[0] = context->count[1] = 0;
|
||||
}
|
||||
|
||||
/* Run your data through this. This will call the compression function SHA1Transform for each
|
||||
** 64-byte block of data.
|
||||
**/
|
||||
void SHA1Update(
|
||||
SHA1_CTX* context,
|
||||
const unsigned char* data,
|
||||
unsigned long dataLen
|
||||
)
|
||||
{
|
||||
unsigned long numByteDataProcessed; /* Number of bytes processed so far */
|
||||
unsigned long numByteInBuffMod64; /* Number of bytes in the buffer mod 64 */
|
||||
|
||||
numByteInBuffMod64 = (context->count[0] >> 3) % 64;
|
||||
|
||||
/* Adding in the number of bits of data */
|
||||
if ((context->count[0] += dataLen << 3) < (dataLen << 3)) {
|
||||
context->count[1]++; /* add in the carry bit */
|
||||
}
|
||||
context->count[1] += (dataLen >> 29);
|
||||
|
||||
/* If there is at least one block to be processed... */
|
||||
if ((numByteInBuffMod64 + dataLen) > 63) {
|
||||
|
||||
/* Copy over 64-numByteInBuffMod64 bytes of data to the end of buffer */
|
||||
memcpy(&context->buffer[numByteInBuffMod64], data,
|
||||
(numByteDataProcessed = 64 - numByteInBuffMod64));
|
||||
|
||||
/* Perform the transform on the buffer */
|
||||
SHA1Transform(context->state, context->buffer);
|
||||
|
||||
/* As long as there are 64-bit blocks of data remaining, transform each one. */
|
||||
for ( ; numByteDataProcessed + 63 < dataLen; numByteDataProcessed += 64) {
|
||||
SHA1Transform(context->state, &data[numByteDataProcessed]);
|
||||
}
|
||||
|
||||
numByteInBuffMod64 = 0;
|
||||
}
|
||||
/* Else there is not enough to process one block. */
|
||||
else
|
||||
numByteDataProcessed = 0;
|
||||
|
||||
/* Copy over the remaining data into the buffer */
|
||||
memcpy(&context->buffer[numByteInBuffMod64], &data[numByteDataProcessed],
|
||||
dataLen - numByteDataProcessed);
|
||||
}
|
||||
|
||||
/* Add padding and return the message digest.
|
||||
**/
|
||||
void SHA1Final(
|
||||
unsigned char digest[SHA1_DIGESTSIZE],
|
||||
SHA1_CTX* context
|
||||
)
|
||||
{
|
||||
unsigned long i, j;
|
||||
unsigned char numBits[8];
|
||||
|
||||
/* Record the number of bits */
|
||||
for (i = 1, j = 0; j < 8; i--, j += 4) {
|
||||
numBits[j] = (unsigned char)((context->count[i] >> 24) & 0xff);
|
||||
numBits[j+1] = (unsigned char)((context->count[i] >> 16) & 0xff);
|
||||
numBits[j+2] = (unsigned char)((context->count[i] >> 8) & 0xff);
|
||||
numBits[j+3] = (unsigned char)(context->count[i] & 0xff);
|
||||
}
|
||||
|
||||
/* Add padding */
|
||||
SHA1Update(context, (unsigned char *)"\200", 1);
|
||||
while ((context->count[0] & 504) != 448)
|
||||
SHA1Update(context, (unsigned char *)"\0", 1);
|
||||
|
||||
/* Append length */
|
||||
SHA1Update(context, numBits, 8); /* Should cause a SHA1Transform() */
|
||||
|
||||
/* Store state in digest */
|
||||
for (i = 0, j = 0; j < 20; i++, j += 4) {
|
||||
digest[j] = (unsigned char)((context->state[i] >> 24) & 0xff);
|
||||
digest[j+1] = (unsigned char)((context->state[i] >> 16) & 0xff);
|
||||
digest[j+2] = (unsigned char)((context->state[i] >> 8) & 0xff);
|
||||
digest[j+3] = (unsigned char)((context->state[i]) & 0xff);
|
||||
}
|
||||
|
||||
/* Wipe variables */
|
||||
i = 0;
|
||||
j = 0;
|
||||
memset(context->buffer, 0, 64);
|
||||
memset(context->state, 0, 20);
|
||||
memset(context->count, 0, 8);
|
||||
memset(&numBits, 0, 8);
|
||||
}
|
39
libmultihash/sha1.h
Normal file
39
libmultihash/sha1.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
** sha1.h
|
||||
**
|
||||
** Copyright NTT MCL, 2000.
|
||||
**
|
||||
** Satomi Okazaki
|
||||
** Security Group, NTT MCL
|
||||
** November 1999
|
||||
**
|
||||
**************************
|
||||
** 13 December 1999. In SHA1Transform, changed "buffer" to be const.
|
||||
** In SHA1Update, changed "data to be const. -- S.O.
|
||||
*/
|
||||
#ifndef __SHA1_H__
|
||||
#define __SHA1_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef SHA1_DIGESTSIZE
|
||||
#define SHA1_DIGESTSIZE 20
|
||||
#endif
|
||||
|
||||
#ifndef SHA1_BLOCKSIZE
|
||||
#define SHA1_BLOCKSIZE 64
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned long state[5];
|
||||
unsigned long count[2]; /* stores the number of bits */
|
||||
unsigned char buffer[SHA1_BLOCKSIZE];
|
||||
} SHA1_CTX;
|
||||
|
||||
void SHA1Transform(unsigned long state[5], const unsigned char buffer[SHA1_BLOCKSIZE]);
|
||||
void SHA1Init(SHA1_CTX *context);
|
||||
void SHA1Update(SHA1_CTX *context, const unsigned char *data, unsigned long len);
|
||||
void SHA1Final(unsigned char digest[SHA1_DIGESTSIZE], SHA1_CTX *context);
|
||||
|
||||
#endif /* __SHA1_H__ */
|
50
src/CMakeLists.txt
Normal file
50
src/CMakeLists.txt
Normal file
|
@ -0,0 +1,50 @@
|
|||
# Make sure the compiler can find include files from our Hello library.
|
||||
include_directories (
|
||||
${FriiDump_SOURCE_DIR}/libfriidump
|
||||
)
|
||||
|
||||
# Make sure the linker can find the Hello library once it is built.
|
||||
link_directories (
|
||||
${FriiDump_BINARY_DIR}/libfriidump
|
||||
)
|
||||
|
||||
# Add executable called "helloDemo" that is built from the source files
|
||||
# "demo.cxx" and "demo_b.cxx". The extensions are automatically found.
|
||||
if (WIN32)
|
||||
set(
|
||||
additional_sources
|
||||
|
||||
getopt-win32.h
|
||||
getopt-win32.c
|
||||
getopt_long-win32.c
|
||||
)
|
||||
endif (WIN32)
|
||||
|
||||
add_executable (
|
||||
friidump
|
||||
|
||||
friidump.c
|
||||
${additional_sources}
|
||||
)
|
||||
|
||||
# Link the executable to the Hello library.
|
||||
target_link_libraries (
|
||||
friidump
|
||||
|
||||
friidumplib
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
# We only want a version number on Windows (Is it any use?)
|
||||
set_target_properties (friidump PROPERTIES VERSION 0.2)
|
||||
|
||||
install(
|
||||
TARGETS friidump
|
||||
RUNTIME DESTINATION /
|
||||
)
|
||||
else (WIN32)
|
||||
install(
|
||||
TARGETS friidump
|
||||
RUNTIME DESTINATION bin
|
||||
)
|
||||
endif (WIN32)
|
11
src/Makefile.am
Normal file
11
src/Makefile.am
Normal file
|
@ -0,0 +1,11 @@
|
|||
mylibdir = $(top_builddir)/libfriidump
|
||||
myincludedir = $(top_srcdir)/libfriidump
|
||||
|
||||
bin_PROGRAMS = friidump
|
||||
friidump_SOURCES = config.h.cmake friidump.c
|
||||
friidump_LDADD = $(mylibdir)/libfriidump.la
|
||||
friidump_LDFLAGS = $(all_libraries)
|
||||
|
||||
# noinst_HEADERS =
|
||||
INCLUDES = $(all_includes) -I$(myincludedir)
|
||||
|
455
src/Makefile.in
Normal file
455
src/Makefile.in
Normal file
|
@ -0,0 +1,455 @@
|
|||
# Makefile.in generated by automake 1.9.6 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
top_builddir = ..
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
INSTALL = @INSTALL@
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
bin_PROGRAMS = friidump$(EXEEXT)
|
||||
subdir = src
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.in
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am_friidump_OBJECTS = friidump.$(OBJEXT)
|
||||
friidump_OBJECTS = $(am_friidump_OBJECTS)
|
||||
friidump_DEPENDENCIES = $(mylibdir)/libfriidump.la
|
||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
SOURCES = $(friidump_SOURCES)
|
||||
DIST_SOURCES = $(friidump_SOURCES)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMDEP_FALSE = @AMDEP_FALSE@
|
||||
AMDEP_TRUE = @AMDEP_TRUE@
|
||||
AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO = @ECHO@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
F77 = @F77@
|
||||
FFLAGS = @FFLAGS@
|
||||
GREP = @GREP@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_F77 = @ac_ct_F77@
|
||||
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
|
||||
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
|
||||
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
|
||||
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
mylibdir = $(top_builddir)/libfriidump
|
||||
myincludedir = $(top_srcdir)/libfriidump
|
||||
friidump_SOURCES = config.h.cmake friidump.c
|
||||
friidump_LDADD = $(mylibdir)/libfriidump.la
|
||||
friidump_LDFLAGS = $(all_libraries)
|
||||
|
||||
# noinst_HEADERS =
|
||||
INCLUDES = $(all_includes) -I$(myincludedir)
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu src/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
|
||||
@list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
|
||||
if test -f $$p \
|
||||
|| test -f $$p1 \
|
||||
; then \
|
||||
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
|
||||
echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
|
||||
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
|
||||
else :; fi; \
|
||||
done
|
||||
|
||||
uninstall-binPROGRAMS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
|
||||
echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(bindir)/$$f"; \
|
||||
done
|
||||
|
||||
clean-binPROGRAMS:
|
||||
@list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||
f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
|
||||
echo " rm -f $$p $$f"; \
|
||||
rm -f $$p $$f ; \
|
||||
done
|
||||
friidump$(EXEEXT): $(friidump_OBJECTS) $(friidump_DEPENDENCIES)
|
||||
@rm -f friidump$(EXEEXT)
|
||||
$(LINK) $(friidump_LDFLAGS) $(friidump_OBJECTS) $(friidump_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/friidump.Po@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
distclean-libtool:
|
||||
-rm -f libtool
|
||||
uninstall-info-am:
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(DISTFILES)'; for file in $$list; do \
|
||||
case $$file in \
|
||||
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
|
||||
esac; \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||
dir="/$$dir"; \
|
||||
$(mkdir_p) "$(distdir)$$dir"; \
|
||||
else \
|
||||
dir=''; \
|
||||
fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(PROGRAMS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(bindir)"; do \
|
||||
test -z "$$dir" || $(mkdir_p) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-libtool distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-exec-am: install-binPROGRAMS
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-man:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-binPROGRAMS uninstall-info-am
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
|
||||
clean-generic clean-libtool ctags distclean distclean-compile \
|
||||
distclean-generic distclean-libtool distclean-tags distdir dvi \
|
||||
dvi-am html html-am info info-am install install-am \
|
||||
install-binPROGRAMS install-data install-data-am install-exec \
|
||||
install-exec-am install-info install-info-am install-man \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
||||
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
|
||||
pdf pdf-am ps ps-am tags uninstall uninstall-am \
|
||||
uninstall-binPROGRAMS uninstall-info-am
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
760
src/friidump.c
Normal file
760
src/friidump.c
Normal file
|
@ -0,0 +1,760 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://wii.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "misc.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include "disc.h"
|
||||
#include "dumper.h"
|
||||
#include "unscrambler.h"
|
||||
|
||||
#define USECS_PER_SEC 1000000
|
||||
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "friidump"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "arep@no.net"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "FriiDump"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "0.5.3.1"
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "getopt-win32.h"
|
||||
|
||||
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* Struct for program options */
|
||||
struct {
|
||||
char *device;
|
||||
bool autodump;
|
||||
bool gui;
|
||||
char *raw_in;
|
||||
char *raw_out;
|
||||
char *iso_out;
|
||||
bool resume;
|
||||
int dump_method;
|
||||
u_int32_t command;
|
||||
u_int32_t start_sector;
|
||||
u_int32_t sectors_no;
|
||||
u_int32_t speed;
|
||||
u_int32_t disctype;
|
||||
u_int32_t sec_disc;
|
||||
u_int32_t sec_mem;
|
||||
bool no_hashing;
|
||||
bool no_unscrambling;
|
||||
bool no_flushing;
|
||||
bool stop_unit;
|
||||
bool allmethods;
|
||||
} options;
|
||||
|
||||
|
||||
/* Struct for progress data */
|
||||
typedef struct {
|
||||
struct timeval start_time;
|
||||
struct timeval end_time;
|
||||
double mb_total;
|
||||
double mb_total_real;
|
||||
u_int32_t sectors_skipped;
|
||||
} progstats;
|
||||
|
||||
|
||||
void progress_for_guis (bool start, u_int32_t sectors_done, u_int32_t total_sectors, progstats *stats) {
|
||||
int perc;
|
||||
double elapsed, mb_done, mb_done_real, mb_hour, seconds_left;
|
||||
struct timeval now;
|
||||
time_t eta;
|
||||
struct tm etatm;
|
||||
char buf[50];
|
||||
|
||||
if (start) {
|
||||
gettimeofday (&(stats -> start_time), NULL);
|
||||
stats -> mb_total = (double) total_sectors * 2064 / 1024 / 1024;
|
||||
stats -> mb_total_real = (double) (total_sectors - sectors_done) * 2064 / 1024 / 1024;
|
||||
stats -> sectors_skipped = sectors_done;
|
||||
} else {
|
||||
perc = (int) (100.0 * sectors_done / total_sectors);
|
||||
gettimeofday (&now, NULL);
|
||||
elapsed = difftime (now.tv_sec, (stats -> start_time).tv_sec);
|
||||
mb_done = (double) sectors_done * 2064 / 1024 / 1024;
|
||||
mb_done_real = (double) (sectors_done - stats -> sectors_skipped) * 2064 / 1024 / 1024;
|
||||
mb_hour = mb_done_real / elapsed * 60 * 60;
|
||||
seconds_left = stats -> mb_total_real / mb_hour * 60 * 60;
|
||||
eta = (time_t) ((stats -> start_time).tv_sec + seconds_left);
|
||||
if (localtime_r (&eta, &etatm))
|
||||
strftime (buf, 50, "%d/%m/%Y %H:%M:%S", &etatm);
|
||||
else
|
||||
sprintf (buf, "N/A");
|
||||
|
||||
/* This is the only thing we print to stdout, so that other programs can easily capture and parse our output */
|
||||
fprintf (stdout, "%d%%|%u/%u sectors|%.2lf/%.0lf MB|%.0lf/%.0lf seconds|%.2lf MB/h|%s\n",
|
||||
perc, sectors_done, total_sectors, mb_done, stats -> mb_total, elapsed, seconds_left, mb_hour, buf);
|
||||
fflush (stdout);
|
||||
}
|
||||
|
||||
/* Save return time, in case this will be the last call */
|
||||
gettimeofday (&(stats -> end_time), NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void progress (bool start, u_int32_t sectors_done, u_int32_t total_sectors, progstats *stats) {
|
||||
int perc, i;
|
||||
double elapsed, mb_done, mb_done_real, mb_hour, seconds_left;
|
||||
struct timeval now;
|
||||
time_t eta;
|
||||
struct tm etatm;
|
||||
char buf[50];
|
||||
|
||||
if (start) {
|
||||
gettimeofday (&(stats -> start_time), NULL);
|
||||
stats -> mb_total = (double) total_sectors * 2064 / 1024 / 1024;
|
||||
stats -> mb_total_real = (double) (total_sectors - sectors_done) * 2064 / 1024 / 1024;
|
||||
stats -> sectors_skipped = sectors_done;
|
||||
} else {
|
||||
perc = (int) (100.0 * sectors_done / total_sectors);
|
||||
gettimeofday (&now, NULL);
|
||||
elapsed = difftime (now.tv_sec, (stats -> start_time).tv_sec);
|
||||
mb_done = (double) sectors_done * 2064 / 1024 / 1024;
|
||||
mb_done_real = (double) (sectors_done - stats -> sectors_skipped) * 2064 / 1024 / 1024;
|
||||
mb_hour = mb_done_real / elapsed * 60 * 60;
|
||||
seconds_left = stats -> mb_total_real / mb_hour * 60 * 60;
|
||||
eta = (time_t) ((stats -> start_time).tv_sec + seconds_left);
|
||||
if (localtime_r (&eta, &etatm))
|
||||
strftime (buf, 50, "%d/%m/%Y %H:%M:%S", &etatm);
|
||||
else
|
||||
sprintf (buf, "N/A");
|
||||
|
||||
fprintf (stdout, "\r%3d%% ", perc);
|
||||
fprintf (stdout, "|");
|
||||
for (i = 0; i < 100 / 3; i++) {
|
||||
if (i == perc / 3)
|
||||
fprintf (stdout, "*");
|
||||
else
|
||||
fprintf (stdout, "-");
|
||||
}
|
||||
fprintf (stdout, "| ");
|
||||
fprintf (stdout, "%.2lf MB/h, ETA: %s", mb_hour, buf);
|
||||
fflush (stdout);
|
||||
}
|
||||
|
||||
if (sectors_done == total_sectors)
|
||||
printf ("\n");
|
||||
|
||||
/* Save return time, in case this will be the last call */
|
||||
gettimeofday (&(stats -> end_time), NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void welcome (void) {
|
||||
/* Welcome text */
|
||||
fprintf (stderr,
|
||||
"FriiDump " PACKAGE_VERSION " - Copyright (C) 2007 Arep\n"
|
||||
"This software comes with ABSOLUTELY NO WARRANTY.\n"
|
||||
"This is free software, and you are welcome to redistribute it\n"
|
||||
"under certain conditions; see COPYING for details.\n"
|
||||
"\n"
|
||||
"Official support forum: http://wii.console-tribe.com\n"
|
||||
"\n"
|
||||
"Forum for this UNOFFICIAL VERSION: http://forum.redump.org\n"
|
||||
"\n"
|
||||
);
|
||||
fflush (stderr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void help (void) {
|
||||
/* 80 cols guide:
|
||||
* |-------------------------------------------------------------------------------|
|
||||
*/
|
||||
fprintf (stderr, "\n"
|
||||
"Available command line options:\n"
|
||||
"\n"
|
||||
" -h, --help Show this help\n"
|
||||
" -a, --autodump Dump the disc to an ISO file with an\n"
|
||||
" automatically-generated name, resuming the dump\n"
|
||||
" if possible\n"
|
||||
" -g, --gui Use more verbose output that can be easily\n"
|
||||
" parsed by a GUI frontend\n"
|
||||
" -d, --device <device> Dump disc from device <device>\n"
|
||||
" -p, --stop Instruct device to stop disc rotation\n"
|
||||
" -c, --command <nr> Force memory dump command:\n"
|
||||
" 0 - vanilla 2064\n"
|
||||
" 1 - vanilla 2384\n"
|
||||
" 2 - Hitachi\n"
|
||||
" 3 - Lite-On\n"
|
||||
" 4 - Renesas\n"
|
||||
" -x, --speed <x> Set streaming speed (1, 24, 32, 64, etc.,\n"
|
||||
" where 1 = 150 KiB/s and so on)\n"
|
||||
" -T, --type <nr> Force disc type:\n"
|
||||
" 0 - GameCube\n"
|
||||
" 1 - Wii\n"
|
||||
" 2 - Wii_DL\n"
|
||||
" 3 - DVD\n"
|
||||
" -S, --size <sectors> Force disc size\n"
|
||||
" -r, --raw <file> Output to file <file> in raw format (2064-byte\n"
|
||||
" sectors)\n"
|
||||
" -i, --iso <file> Output to file <file> in ISO format (2048-byte\n"
|
||||
" sectors)\n"
|
||||
" -u, --unscramble <file> Convert (unscramble) raw image contained in\n"
|
||||
" <file> to ISO format\n"
|
||||
" -H, --nohash Do not compute CRC32/MD5/SHA-1 hashes\n"
|
||||
" for generated files\n"
|
||||
" -s, --resume Resume partial dump\n"
|
||||
" - General -----------------------------------\n"
|
||||
" -0, --method0[=<req>,<exp>] Use dumping method 0 (Optional argument\n"
|
||||
" specifies how many sectors to request from disc\n"
|
||||
" and read from cache at a time. Values should be\n"
|
||||
" separated with a comma. Default 16,16)\n"
|
||||
" - Non-Streaming -----------------------------\n"
|
||||
" -1, --method1[=<req>,<exp>] Use dumping method 1 (Default 16,16)\n"
|
||||
" -2, --method2[=<req>,<exp>] Use dumping method 2 (Default 16,16)\n"
|
||||
" -3, --method3[=<req>,<exp>] Use dumping method 3 (Default 16,16)\n"
|
||||
" - Streaming ---------------------------------\n"
|
||||
" -4, --method4[=<req>,<exp>] Use dumping method 4 (Default 27,27)\n"
|
||||
" -5, --method5[=<req>,<exp>] Use dumping method 5 (Default 27,27)\n"
|
||||
" -6, --method6[=<req>,<exp>] Use dumping method 6 (Default 27,27)\n"
|
||||
" - Hitachi -----------------------------------\n"
|
||||
" -7, --method7 Use dumping method 7 (Read and dump 5 blocks\n"
|
||||
" at a time, using streaming read)\n"
|
||||
" -8, --method8 Use dumping method 8 (Read and dump 5 blocks\n"
|
||||
" at a time, using streaming read, using DMA)\n"
|
||||
" -9, --method9 Use dumping method 9 (Read and dump 5 blocks\n"
|
||||
" at a time, using streaming read, using DMA and\n"
|
||||
" some speed tricks)\n"
|
||||
" -A, --allmethods Try all known methods and commands until\n"
|
||||
" one works.\n"
|
||||
#ifdef DEBUG
|
||||
" -n, --donottunscramble Do not try unscrambling to check EDC. Only\n"
|
||||
" useful for testing the raw performance of the\n"
|
||||
" different methods\n"
|
||||
" -f, --donottflush Do not call fflush() after every fwrite()\n"
|
||||
#endif
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool optparse (int argc, char **argv) {
|
||||
bool out;
|
||||
char *result = NULL;
|
||||
int c;
|
||||
int option_index = 0;
|
||||
static struct option long_options[] = {
|
||||
{"help", 0, 0, 'h'}, //0 - no_argument
|
||||
{"autodump", 0, 0, 'a'},
|
||||
{"gui", 0, 0, 'g'},
|
||||
{"device", 1, 0, 'd'}, //1 - required_argument
|
||||
{"raw", 1, 0, 'r'},
|
||||
{"iso", 1, 0, 'i'},
|
||||
{"unscramble", 1, 0, 'u'},
|
||||
{"nohash", 0, 0, 'H'},
|
||||
{"resume", 0, 0, 's'},
|
||||
{"method0", 2, 0, '0'}, //2 - optional_argument
|
||||
{"method1", 2, 0, '1'},
|
||||
{"method2", 2, 0, '2'},
|
||||
{"method3", 2, 0, '3'},
|
||||
{"method4", 2, 0, '4'},
|
||||
{"method5", 2, 0, '5'},
|
||||
{"method6", 2, 0, '6'},
|
||||
{"method7", 0, 0, '7'},
|
||||
{"method8", 0, 0, '8'},
|
||||
{"method9", 0, 0, '9'},
|
||||
{"stop", 0, 0, 'p'},
|
||||
{"command", 1, 0, 'c'},
|
||||
{"startsector", 1, 0, 't'},
|
||||
{"size", 1, 0, 'S'},
|
||||
{"speed", 1, 0, 'x'},
|
||||
{"type", 1, 0, 'T'},
|
||||
{"allmethods", 0, 0, 'A'},
|
||||
#ifdef DEBUG
|
||||
/* We don't want newbies to generate and put into circulation bad dumps, so this options are disabled for releases */
|
||||
{"donottunscramble", 0, 0, 'n'},
|
||||
{"donottflush", 0, 0, 'f'},
|
||||
#endif
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
if (argc == 1) {
|
||||
help ();
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Init options to default values */
|
||||
options.device = NULL;
|
||||
options.autodump = false;
|
||||
options.gui = false;
|
||||
options.raw_in = NULL;
|
||||
options.raw_out = NULL;
|
||||
options.iso_out = NULL;
|
||||
options.no_hashing = false;
|
||||
options.resume = false;
|
||||
options.dump_method = -1;
|
||||
options.command = -1;
|
||||
options.start_sector = -1;
|
||||
options.sectors_no = -1;
|
||||
options.speed = -1;
|
||||
options.disctype = -1;
|
||||
options.sec_disc = -1;
|
||||
options.sec_mem = -1;
|
||||
options.no_unscrambling = false;
|
||||
options.no_flushing = false;
|
||||
options.stop_unit = false;
|
||||
options.allmethods = false;
|
||||
|
||||
do {
|
||||
#ifdef DEBUG
|
||||
c = getopt_long (argc, argv, "hpagd:r:i:u:Hs0::1::2::3::4::5::6::789c:t:S:x:T:Anf", long_options, &option_index);
|
||||
#else
|
||||
c = getopt_long (argc, argv, "hpagd:r:i:u:Hs0::1::2::3::4::5::6::789c:t:S:x:T:A", long_options, &option_index);
|
||||
#endif
|
||||
|
||||
switch (c) {
|
||||
case 'h':
|
||||
help ();
|
||||
exit (1);
|
||||
break;
|
||||
case 'p':
|
||||
options.stop_unit = true;
|
||||
break;
|
||||
case 'a':
|
||||
options.autodump = true;
|
||||
options.resume = true;
|
||||
break;
|
||||
case 'g':
|
||||
options.gui = true;
|
||||
break;
|
||||
case 'd':
|
||||
my_strdup (options.device, optarg);
|
||||
break;
|
||||
case 'r':
|
||||
my_strdup (options.raw_out, optarg);
|
||||
break;
|
||||
case 'i':
|
||||
my_strdup (options.iso_out, optarg);
|
||||
break;
|
||||
case 'u':
|
||||
my_strdup (options.raw_in, optarg);
|
||||
break;
|
||||
case 'H':
|
||||
options.no_hashing = true;
|
||||
break;
|
||||
case 's':
|
||||
options.resume = true;
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
options.dump_method = c - '0';
|
||||
if (optarg) {
|
||||
result = strtok(optarg, ",");
|
||||
result = strtok(NULL, ",");
|
||||
options.sec_disc = atol(strpbrk(optarg,"1234567890"));
|
||||
if (result) options.sec_mem = atol(result);
|
||||
else {
|
||||
help ();
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
options.dump_method = c - '0';
|
||||
break;
|
||||
case 'c':
|
||||
options.command = atol (optarg);
|
||||
if (options.command > 4) {
|
||||
help ();
|
||||
exit (1);
|
||||
};
|
||||
break;
|
||||
case 't':
|
||||
options.start_sector = atol (optarg);
|
||||
break;
|
||||
case 'S':
|
||||
options.sectors_no = atol (optarg);
|
||||
break;
|
||||
case 'x':
|
||||
options.speed = atol (optarg);
|
||||
break;
|
||||
case 'T':
|
||||
options.disctype = atol (optarg);
|
||||
if (options.disctype > 3) {
|
||||
help ();
|
||||
exit (1);
|
||||
};
|
||||
unscrambler_set_disctype (options.disctype);
|
||||
break;
|
||||
case 'A':
|
||||
options.allmethods = true;
|
||||
options.resume = true;
|
||||
break;
|
||||
#ifdef DEBUG
|
||||
case 'n':
|
||||
options.no_unscrambling = true;
|
||||
break;
|
||||
case 'f':
|
||||
options.no_flushing = true;
|
||||
break;
|
||||
#endif
|
||||
case -1:
|
||||
break;
|
||||
default:
|
||||
// fprintf (stderr, "?? getopt returned character code 0%o ??\n", c);
|
||||
exit (7);
|
||||
break;
|
||||
}
|
||||
} while (c != -1);
|
||||
|
||||
if (optind < argc) {
|
||||
/* Command-line arguments remaining. Ignore them, warning the user. */
|
||||
fprintf (stderr, "WARNING: Extra parameters ignored\n");
|
||||
}
|
||||
|
||||
/* Sanity checks... */
|
||||
out = false;
|
||||
if (!options.device && !options.raw_in) {
|
||||
fprintf (stderr, "No operation specified. Please use the -d or -u options.\n");
|
||||
} else if (options.raw_in && options.raw_out) {
|
||||
fprintf (stderr,
|
||||
"Are you sure you want to convert a raw image to another raw image? ;)\n"
|
||||
"Take a look at the -i and -a options!\n"
|
||||
);
|
||||
} else if (options.autodump && (options.raw_out || options.iso_out)) {
|
||||
fprintf (stderr, "The -r and -i options cannot be used together with -a.\n");
|
||||
} else {
|
||||
/* Specified options seem to make sense */
|
||||
out = true;
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
int dologic (disc *d, progstats stats) {
|
||||
disc_type type_id;
|
||||
char *type, *game_id, *region, *maker_id, *maker, *version, *title, tmp[0x03E0 + 4 + 1];
|
||||
bool drive_supported;
|
||||
int out;
|
||||
dumper *dmp;
|
||||
u_int32_t current_sector;
|
||||
|
||||
|
||||
|
||||
if (options.stop_unit) { //stop rotation, if requested
|
||||
fprintf (stderr, "Issuing STOP command... %s\n", (disc_stop_unit (d, false)) ? "OK" : "Failed");
|
||||
exit (1);
|
||||
}
|
||||
else disc_stop_unit(d, true); //else start rotation
|
||||
|
||||
drive_supported = disc_get_drive_support_status (d);
|
||||
fprintf (stderr,
|
||||
"\n"
|
||||
"Drive information:\n"
|
||||
"----------------------------------------------------------------------\n"
|
||||
"Drive model........: %s\n"
|
||||
"Supported..........: %s\n", disc_get_drive_model_string (d), drive_supported ? "Yes" : "No"
|
||||
);
|
||||
|
||||
init_range(d, options.sec_disc, options.sec_mem);
|
||||
|
||||
if (!(disc_set_read_method (d, options.dump_method)))
|
||||
exit (2);
|
||||
|
||||
if (options.command!=-1) fprintf (stderr,
|
||||
"Command............: %d (forced)\n", disc_get_command(d));
|
||||
else fprintf (stderr,
|
||||
"Command............: %d\n", disc_get_command(d));
|
||||
options.dump_method=disc_get_method(d);
|
||||
if (disc_get_def_method(d)!=options.dump_method) fprintf (stderr,
|
||||
"Method.............: %d (forced)\n", options.dump_method);
|
||||
else fprintf (stderr,
|
||||
"Method.............: %d\n", options.dump_method);
|
||||
if ((options.dump_method==0)
|
||||
|| (options.dump_method==1) || (options.dump_method==2) || (options.dump_method==3)
|
||||
|| (options.dump_method==4) || (options.dump_method==5) || (options.dump_method==6)
|
||||
){
|
||||
fprintf (stderr,
|
||||
"Requested sectors..: %d\n", disc_get_sec_disc(d));
|
||||
fprintf (stderr,
|
||||
"Expected sectors...: %d\n", disc_get_sec_mem(d));
|
||||
}
|
||||
|
||||
fprintf (stderr, "\nPress Ctrl+C at any time to terminate\n");
|
||||
fprintf (stderr, "\nRetrieving disc seeds, this might take a while... ");
|
||||
|
||||
//set speed for 1st time
|
||||
if (options.speed != -1) disc_set_speed(d, options.speed * 177);
|
||||
if (options.speed != -1) disc_set_streaming_speed(d, options.speed * 177);
|
||||
// disc_set_speed(d, 0xffff);
|
||||
|
||||
if (!disc_init (d, options.disctype, options.sectors_no)) {
|
||||
fprintf (stderr, "Failed\n");
|
||||
out = false;
|
||||
} else {
|
||||
fprintf (stderr, "OK\n");
|
||||
disc_get_type (d, &type_id, &type);
|
||||
disc_get_gameid (d, &game_id);
|
||||
disc_get_region (d, NULL, ®ion);
|
||||
disc_get_maker (d, &maker_id, &maker);
|
||||
disc_get_version (d, NULL, &version);
|
||||
disc_get_title (d, &title);
|
||||
fprintf (stderr,
|
||||
"\n"
|
||||
"Disc information:\n"
|
||||
"----------------------------------------------------------------------\n");
|
||||
|
||||
if (options.disctype!=-1) fprintf (stderr,
|
||||
"Disc type..........: %s (forced)\n", type);
|
||||
else fprintf (stderr,
|
||||
"Disc type..........: %s\n", type);
|
||||
if (options.sectors_no!=-1) fprintf (stderr,
|
||||
"Disc size..........: %d (forced)\n", disc_get_sectors_no(d));
|
||||
else fprintf (stderr,
|
||||
"Disc size..........: %d\n", disc_get_sectors_no(d));
|
||||
|
||||
if (disc_get_layerbreak(d)>0 && type_id==DISC_TYPE_DVD) fprintf (stderr,
|
||||
"Layer break........: %d\n", disc_get_layerbreak(d));
|
||||
|
||||
if ((type_id==DISC_TYPE_GAMECUBE) || (type_id==DISC_TYPE_WII) || (type_id==DISC_TYPE_WII_DL)) fprintf (stderr,
|
||||
"Game ID............: %s\n"
|
||||
"Region.............: %s\n"
|
||||
"Maker..............: %s - %s\n"
|
||||
"Version............: %s\n"
|
||||
"Game title.........: %s\n", game_id, region, maker_id, maker, version, title
|
||||
);
|
||||
|
||||
if (type_id == DISC_TYPE_WII || type_id == DISC_TYPE_WII_DL)
|
||||
fprintf (stderr, "Contains update....: %s\n" , disc_get_update (d) ? "Yes" : "No");
|
||||
fprintf (stderr, "\n");
|
||||
|
||||
disc_set_unscrambling (d, !options.no_unscrambling);
|
||||
|
||||
unscrambler_set_disctype (type_id);
|
||||
|
||||
if (options.autodump) {
|
||||
snprintf (tmp, sizeof (tmp), "%s.iso", title);
|
||||
my_strdup (options.iso_out, tmp);
|
||||
}
|
||||
|
||||
//set speed 2nd time after rotation is started and some sectors read
|
||||
if (options.speed != -1) disc_set_streaming_speed(d, options.speed * 177);
|
||||
if (options.speed != -1) disc_set_speed(d, options.speed * 177);
|
||||
|
||||
/* If at least an output file was specified, proceed dumping, otherwise stop here */
|
||||
if (options.raw_out || options.iso_out) {
|
||||
if (options.raw_out)
|
||||
fprintf (stderr, "Writing to file \"%s\" in raw format\n", options.raw_out);
|
||||
if (options.iso_out)
|
||||
fprintf (stderr, "Writing to file \"%s\" in ISO format\n", options.iso_out);
|
||||
fprintf (stderr, "\n");
|
||||
|
||||
dmp = dumper_new (d);
|
||||
|
||||
dumper_set_hashing (dmp, !options.no_hashing);
|
||||
dumper_set_flushing (dmp, !options.no_flushing);
|
||||
|
||||
if (!dumper_set_raw_output_file (dmp, options.raw_out, options.resume)) {
|
||||
fprintf (stderr, "Cannot setup raw output file\n");
|
||||
} else if (!dumper_set_iso_output_file (dmp, options.iso_out, options.resume)) {
|
||||
fprintf (stderr, "Cannot setup ISO output file\n");
|
||||
} else if (!dumper_prepare (dmp)) {
|
||||
fprintf (stderr, "Cannot prepare dumper");
|
||||
} else {
|
||||
// fprintf (stderr, "Starting dump process from sector %u...\n", dmp -> start_sector);
|
||||
// opdd.start_sector = options.start_sector;
|
||||
|
||||
if (options.gui)
|
||||
dumper_set_progress_callback (dmp, (progress_func) progress_for_guis, &stats);
|
||||
else
|
||||
dumper_set_progress_callback (dmp, (progress_func) progress, &stats);
|
||||
|
||||
if (dumper_dump (dmp, ¤t_sector)) {
|
||||
fprintf (stderr, "Dump completed successfully!\n");
|
||||
if (!options.no_hashing && options.raw_out)
|
||||
fprintf (stderr,
|
||||
"Raw image hashes:\n"
|
||||
"CRC32...: %s\n"
|
||||
//"MD4.....: %s\n"
|
||||
"MD5.....: %s\n"
|
||||
"SHA-1...: %s\n"
|
||||
/*"ED2K....: %s\n"*/,
|
||||
dumper_get_raw_crc32 (dmp), /*dumper_get_raw_md4 (dmp),*/ dumper_get_raw_md5 (dmp),
|
||||
dumper_get_raw_sha1 (dmp)/*, dumper_get_raw_ed2k (dmp)*/
|
||||
);
|
||||
if (!options.no_hashing && options.iso_out)
|
||||
fprintf (stderr,
|
||||
"ISO image hashes:\n"
|
||||
"CRC32...: %s\n"
|
||||
//"MD4.....: %s\n"
|
||||
"MD5.....: %s\n"
|
||||
"SHA-1...: %s\n"
|
||||
/*"ED2K....: %s\n"*/,
|
||||
dumper_get_iso_crc32 (dmp), /*dumper_get_iso_md4 (dmp),*/ dumper_get_iso_md5 (dmp),
|
||||
dumper_get_iso_sha1 (dmp)/*, dumper_get_iso_ed2k (dmp)*/
|
||||
);
|
||||
|
||||
out = true;
|
||||
disc_stop_unit (d, 0);
|
||||
} else {
|
||||
fprintf (stderr, "\nDump failed at sectors: %u..%u\n", current_sector, current_sector+15);
|
||||
out = false;
|
||||
//disc_stop_unit (d, 0);
|
||||
}
|
||||
}
|
||||
|
||||
dmp = dumper_destroy (dmp);
|
||||
} else {
|
||||
fprintf (stderr, "No output file for dumping specified, please take a look at the -i, -r and -a options\n");
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
disc *d;
|
||||
progstats stats;
|
||||
double duration;
|
||||
suseconds_t us;
|
||||
int out, ret;
|
||||
unscrambler *u;
|
||||
unscrambler_progress_func pfunc;
|
||||
u_int32_t current_sector;
|
||||
|
||||
/* First of all... */
|
||||
drop_euid ();
|
||||
|
||||
welcome ();
|
||||
|
||||
d = NULL;
|
||||
out = false;
|
||||
if (optparse (argc, argv)) {
|
||||
if (options.device) {
|
||||
/* Dump DVD to file */
|
||||
fprintf (stderr, "Initializing DVD drive... ");
|
||||
|
||||
if (!(d = disc_new (options.device, options.command))) {
|
||||
fprintf (stderr, "Failed\n");
|
||||
#ifndef WIN32
|
||||
fprintf (stderr,
|
||||
"Probably you do not have access to the DVD device. Ask the administrator\n"
|
||||
"to add you to the proper group, or use 'sudo'.\n"
|
||||
);
|
||||
#endif
|
||||
} else {
|
||||
fprintf (stderr, "OK\n");
|
||||
|
||||
if(options.allmethods)
|
||||
{
|
||||
fprintf (stderr, "Trying all methods... This will take a LOOOONG time and generate an insanely long console output :p\n");
|
||||
for(options.command=0;options.command<=4;options.command++)
|
||||
{
|
||||
for(options.dump_method=0;options.dump_method<=9;options.dump_method++)
|
||||
{
|
||||
fprintf (stderr, "Trying with command %d, method %d\n", options.command, options.dump_method);
|
||||
out = dologic(d, stats);
|
||||
if(out==true)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(out==true)
|
||||
{
|
||||
fprintf (stderr, "Command %d and method %d combination worked!\n", options.command, options.dump_method);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out = dologic(d, stats);
|
||||
}
|
||||
|
||||
d = disc_destroy (d);
|
||||
}
|
||||
} else if (options.raw_in) {
|
||||
/* Convert raw image to ISO format */
|
||||
u = unscrambler_new ();
|
||||
|
||||
if (options.gui)
|
||||
pfunc = (unscrambler_progress_func) progress_for_guis;
|
||||
else
|
||||
pfunc = (unscrambler_progress_func) progress;
|
||||
|
||||
if ((out = unscrambler_unscramble_file (u, options.raw_in, options.iso_out, pfunc, &stats, ¤t_sector)))
|
||||
fprintf (stderr, "Unscrambling completed successfully!\n");
|
||||
else
|
||||
fprintf (stderr, "\nUnscrambling failed at sectors: %u..%u\n", current_sector, current_sector+15);
|
||||
|
||||
u = unscrambler_destroy (u);
|
||||
} else {
|
||||
MY_ASSERT (0);
|
||||
}
|
||||
|
||||
if (out) {
|
||||
duration = stats.end_time.tv_sec - stats.start_time.tv_sec;
|
||||
if (stats.end_time.tv_usec >= stats.start_time.tv_usec) {
|
||||
us = stats.end_time.tv_usec - stats.start_time.tv_usec;
|
||||
} else {
|
||||
if (duration > 0)
|
||||
duration--;
|
||||
us = USECS_PER_SEC + stats.end_time.tv_usec - stats.start_time.tv_usec;
|
||||
}
|
||||
duration += ((double) us / (double) USECS_PER_SEC);
|
||||
if (duration < 0)
|
||||
duration = 0;
|
||||
fprintf (stderr, "Operation took %.2f seconds\n", duration);
|
||||
|
||||
ret = EXIT_SUCCESS;
|
||||
} else {
|
||||
ret = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
my_free (options.device);
|
||||
my_free (options.iso_out);
|
||||
my_free (options.raw_out);
|
||||
my_free (options.raw_in);
|
||||
}
|
||||
|
||||
return (out);
|
||||
}
|
130
src/getopt-win32.c
Normal file
130
src/getopt-win32.c
Normal file
|
@ -0,0 +1,130 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
** Copyright (C) 2002 Martin Roesch <roesch@sourcefire.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License Version 2 as
|
||||
** published by the Free Software Foundation. You may not use, modify or
|
||||
** distribute this program under any other version of the GNU General
|
||||
** Public License.
|
||||
**
|
||||
** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifdef SNORT_GETOPT
|
||||
|
||||
#include <stdio.h> /* for EOF */
|
||||
#include <string.h> /* for strchr() */
|
||||
|
||||
#include "getopt.h"
|
||||
|
||||
/* static (global) variables that are specified as exported by getopt() */
|
||||
char *optarg = NULL; /* pointer to the start of the option argument */
|
||||
int optind = 1; /* number of the next argv[] to be evaluated */
|
||||
int opterr = 1; /* non-zero if a question mark should be returned
|
||||
when a non-valid option character is detected */
|
||||
int optopt;
|
||||
|
||||
int getopt(int argc, char *argv[], char *opstring)
|
||||
{
|
||||
static char *pIndexPosition = NULL; /* place inside current argv string */
|
||||
char *pArgString = NULL; /* where to start from next */
|
||||
char *pOptString; /* the string in our program */
|
||||
|
||||
|
||||
if (pIndexPosition != NULL) {
|
||||
/* we last left off inside an argv string */
|
||||
if (*(++pIndexPosition)) {
|
||||
/* there is more to come in the most recent argv */
|
||||
pArgString = pIndexPosition;
|
||||
}
|
||||
}
|
||||
|
||||
if (pArgString == NULL) {
|
||||
/* we didn't leave off in the middle of an argv string */
|
||||
if (optind >= argc) {
|
||||
/* more command-line arguments than the argument count */
|
||||
pIndexPosition = NULL; /* not in the middle of anything */
|
||||
return EOF; /* used up all command-line arguments */
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
* If the next argv[] is not an option, there can be no more options.
|
||||
*-------------------------------------------------------------------*/
|
||||
pArgString = argv[optind++]; /* set this to the next argument ptr */
|
||||
|
||||
if (('/' != *pArgString) && /* doesn't start with a slash or a dash? */
|
||||
('-' != *pArgString)) {
|
||||
--optind; /* point to current arg once we're done */
|
||||
optarg = NULL; /* no argument follows the option */
|
||||
pIndexPosition = NULL; /* not in the middle of anything */
|
||||
return EOF; /* used up all the command-line flags */
|
||||
}
|
||||
|
||||
/* check for special end-of-flags markers */
|
||||
if ((strcmp(pArgString, "-") == 0) ||
|
||||
(strcmp(pArgString, "--") == 0)) {
|
||||
optarg = NULL; /* no argument follows the option */
|
||||
pIndexPosition = NULL; /* not in the middle of anything */
|
||||
return EOF; /* encountered the special flag */
|
||||
}
|
||||
|
||||
pArgString++; /* look past the / or - */
|
||||
}
|
||||
|
||||
if (':' == *pArgString) { /* is it a colon? */
|
||||
/*---------------------------------------------------------------------
|
||||
* Rare case: if opterr is non-zero, return a question mark;
|
||||
* otherwise, just return the colon we're on.
|
||||
*-------------------------------------------------------------------*/
|
||||
return (opterr ? (int)'?' : (int)':');
|
||||
}
|
||||
else if ((pOptString = strchr(opstring, *pArgString)) == 0) {
|
||||
/*---------------------------------------------------------------------
|
||||
* The letter on the command-line wasn't any good.
|
||||
*-------------------------------------------------------------------*/
|
||||
optarg = NULL; /* no argument follows the option */
|
||||
pIndexPosition = NULL; /* not in the middle of anything */
|
||||
return (opterr ? (int)'?' : (int)*pArgString);
|
||||
}
|
||||
else {
|
||||
/*---------------------------------------------------------------------
|
||||
* The letter on the command-line matches one we expect to see
|
||||
*-------------------------------------------------------------------*/
|
||||
if (':' == _next_char(pOptString)) { /* is the next letter a colon? */
|
||||
/* It is a colon. Look for an argument string. */
|
||||
if ('\0' != _next_char(pArgString)) { /* argument in this argv? */
|
||||
optarg = &pArgString[1]; /* Yes, it is */
|
||||
}
|
||||
else {
|
||||
/*-------------------------------------------------------------
|
||||
* The argument string must be in the next argv.
|
||||
* But, what if there is none (bad input from the user)?
|
||||
* In that case, return the letter, and optarg as NULL.
|
||||
*-----------------------------------------------------------*/
|
||||
if (optind < argc)
|
||||
optarg = argv[optind++];
|
||||
else {
|
||||
optarg = NULL;
|
||||
return (opterr ? (int)'?' : (int)*pArgString);
|
||||
}
|
||||
}
|
||||
|
||||
pIndexPosition = NULL; /* not in the middle of anything */
|
||||
}
|
||||
else {
|
||||
/* it's not a colon, so just return the letter */
|
||||
optarg = NULL; /* no argument follows the option */
|
||||
pIndexPosition = pArgString; /* point to the letter we're on */
|
||||
}
|
||||
return (int)*pArgString; /* return the letter that matched */
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
36
src/getopt-win32.h
Normal file
36
src/getopt-win32.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
** Copyright (C) 2002 Martin Roesch <roesch@sourcefire.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License Version 2 as
|
||||
** published by the Free Software Foundation. You may not use, modify or
|
||||
** distribute this program under any other version of the GNU General
|
||||
** Public License.
|
||||
**
|
||||
** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _SNORT_GETOPT_H_
|
||||
#define _SNORT_GETOPT_H_
|
||||
|
||||
#ifdef SNORT_GETOPT
|
||||
#define _next_char(string) (char)(*(string+1))
|
||||
|
||||
extern char * optarg;
|
||||
extern int optind;
|
||||
|
||||
int getopt(int, char**, char*);
|
||||
|
||||
#else
|
||||
#include "getopt1.h"
|
||||
#endif
|
||||
|
||||
#endif /* _SNORT_GETOPT_H_ */
|
130
src/getopt1.h
Normal file
130
src/getopt1.h
Normal file
|
@ -0,0 +1,130 @@
|
|||
/* Declarations for getopt.
|
||||
Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
it under the terms of the GNU General Public License Version 2 as
|
||||
published by the Free Software Foundation. You may not use, modify or
|
||||
distribute this program under any other version of the GNU General
|
||||
Public License.
|
||||
|
||||
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. */
|
||||
|
||||
#ifndef _GETOPT1_H
|
||||
#define _GETOPT1_H 1
|
||||
|
||||
#ifndef HAVE_GETOPT_LONG
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* For communication from `getopt' to the caller.
|
||||
When `getopt' finds an option that takes an argument,
|
||||
the argument value is returned here.
|
||||
Also, when `ordering' is RETURN_IN_ORDER,
|
||||
each non-option ARGV-element is returned here. */
|
||||
|
||||
extern char *optarg;
|
||||
|
||||
/* Index in ARGV of the next element to be scanned.
|
||||
This is used for communication to and from the caller
|
||||
and for communication between successive calls to `getopt'.
|
||||
|
||||
On entry to `getopt', zero means this is the first call; initialize.
|
||||
|
||||
When `getopt' returns EOF, this is the index of the first of the
|
||||
non-option elements that the caller should itself scan.
|
||||
|
||||
Otherwise, `optind' communicates from one call to the next
|
||||
how much of ARGV has been scanned so far. */
|
||||
|
||||
extern int optind;
|
||||
|
||||
/* Callers store zero here to inhibit the error message `getopt' prints
|
||||
for unrecognized options. */
|
||||
|
||||
extern int opterr;
|
||||
|
||||
/* Set to an option character which was unrecognized. */
|
||||
|
||||
extern int optopt;
|
||||
|
||||
/* Describe the long-named options requested by the application.
|
||||
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
|
||||
of `struct option' terminated by an element containing a name which is
|
||||
zero.
|
||||
|
||||
The field `has_arg' is:
|
||||
no_argument (or 0) if the option does not take an argument,
|
||||
required_argument (or 1) if the option requires an argument,
|
||||
optional_argument (or 2) if the option takes an optional argument.
|
||||
|
||||
If the field `flag' is not NULL, it points to a variable that is set
|
||||
to the value given in the field `val' when the option is found, but
|
||||
left unchanged if the option is not found.
|
||||
|
||||
To have a long-named option do something other than set an `int' to
|
||||
a compiled-in constant, such as set a value from `optarg', set the
|
||||
option's `flag' field to zero and its `val' field to a nonzero
|
||||
value (the equivalent single-letter option character, if there is
|
||||
one). For long options that have a zero `flag' field, `getopt'
|
||||
returns the contents of the `val' field. */
|
||||
|
||||
struct option
|
||||
{
|
||||
#if __STDC__
|
||||
const char *name;
|
||||
#else
|
||||
char *name;
|
||||
#endif
|
||||
/* has_arg can't be an enum because some compilers complain about
|
||||
type mismatches in all the code that assumes it is an int. */
|
||||
int has_arg;
|
||||
int *flag;
|
||||
int val;
|
||||
};
|
||||
|
||||
/* Names for the values of the `has_arg' field of `struct option'. */
|
||||
|
||||
#define no_argument 0
|
||||
#define required_argument 1
|
||||
#define optional_argument 2
|
||||
|
||||
#if __STDC__
|
||||
|
||||
#ifndef HAVE_GETOPT
|
||||
extern int getopt (int argc, char *const *argv, const char *optstring);
|
||||
#endif
|
||||
|
||||
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
|
||||
const struct option *longopts, int *longind);
|
||||
extern int getopt_long_only (int argc, char *const *argv,
|
||||
const char *shortopts,
|
||||
const struct option *longopts, int *longind);
|
||||
|
||||
/* Internal only. Users should not call this directly. */
|
||||
extern int _getopt_internal (int argc, char *const *argv,
|
||||
const char *shortopts,
|
||||
const struct option *longopts, int *longind,
|
||||
int long_only);
|
||||
#else /* not __STDC__ */
|
||||
|
||||
#ifndef HAVE_GETOPT
|
||||
extern int getopt ();
|
||||
#endif
|
||||
extern int getopt_long ();
|
||||
extern int getopt_long_only ();
|
||||
|
||||
extern int _getopt_internal ();
|
||||
#endif /* not __STDC__ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_GETOPT_LONG */
|
||||
|
||||
#endif /* _GETOPT_H */
|
727
src/getopt_long-win32.c
Normal file
727
src/getopt_long-win32.c
Normal file
|
@ -0,0 +1,727 @@
|
|||
/* Getopt for GNU.
|
||||
NOTE: getopt is now part of the C library, so if you don't know what
|
||||
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
|
||||
before changing it!
|
||||
|
||||
Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
it under the terms of the GNU General Public License Version 2 as
|
||||
published by the Free Software Foundation. You may not use, modify or
|
||||
distribute this program under any other version of the GNU General
|
||||
Public License.
|
||||
|
||||
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. */
|
||||
|
||||
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
|
||||
Ditto for AIX 3.2 and <stdlib.h>. */
|
||||
#ifndef _NO_PROTO
|
||||
#define _NO_PROTO
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#if defined (emacs) || defined (CONFIG_BROKETS)
|
||||
/* We use <config.h> instead of "config.h" so that a compilation
|
||||
using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
|
||||
(which it would do because it found this file in $srcdir). */
|
||||
#include <config.h>
|
||||
#else
|
||||
#include "config.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __STDC__
|
||||
/* This is a separate conditional since some stdc systems
|
||||
reject `defined (const)'. */
|
||||
#ifndef const
|
||||
#define const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
and linking in this code is a waste when using the GNU C library
|
||||
(especially if it is a shared library). Rather than having every GNU
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
|
||||
#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
|
||||
|
||||
|
||||
/* This needs to come after some library #include
|
||||
to get __GNU_LIBRARY__ defined. */
|
||||
#ifdef __GNU_LIBRARY__
|
||||
/* Don't include stdlib.h for non-GNU C libraries because some of them
|
||||
contain conflicting prototypes for getopt. */
|
||||
#include <stdlib.h>
|
||||
#endif /* GNU C library. */
|
||||
|
||||
/* This version of `getopt' appears to the caller like standard Unix `getopt'
|
||||
but it behaves differently for the user, since it allows the user
|
||||
to intersperse the options with the other arguments.
|
||||
|
||||
As `getopt' works, it permutes the elements of ARGV so that,
|
||||
when it is done, all the options precede everything else. Thus
|
||||
all application programs are extended to handle flexible argument order.
|
||||
|
||||
Setting the environment variable POSIXLY_CORRECT disables permutation.
|
||||
Then the behavior is completely standard.
|
||||
|
||||
GNU application programs can use a third alternative mode in which
|
||||
they can distinguish the relative order of options and other arguments. */
|
||||
|
||||
#include "getopt1.h"
|
||||
|
||||
/* For communication from `getopt' to the caller.
|
||||
When `getopt' finds an option that takes an argument,
|
||||
the argument value is returned here.
|
||||
Also, when `ordering' is RETURN_IN_ORDER,
|
||||
each non-option ARGV-element is returned here. */
|
||||
|
||||
char *optarg = NULL;
|
||||
|
||||
/* Index in ARGV of the next element to be scanned.
|
||||
This is used for communication to and from the caller
|
||||
and for communication between successive calls to `getopt'.
|
||||
|
||||
On entry to `getopt', zero means this is the first call; initialize.
|
||||
|
||||
When `getopt' returns EOF, this is the index of the first of the
|
||||
non-option elements that the caller should itself scan.
|
||||
|
||||
Otherwise, `optind' communicates from one call to the next
|
||||
how much of ARGV has been scanned so far. */
|
||||
|
||||
/* XXX 1003.2 says this must be 1 before any call. */
|
||||
int optind = 0;
|
||||
|
||||
/* The next char to be scanned in the option-element
|
||||
in which the last option character we returned was found.
|
||||
This allows us to pick up the scan where we left off.
|
||||
|
||||
If this is zero, or a null string, it means resume the scan
|
||||
by advancing to the next ARGV-element. */
|
||||
|
||||
static char *nextchar;
|
||||
|
||||
/* Callers store zero here to inhibit the error message
|
||||
for unrecognized options. */
|
||||
|
||||
int opterr = 1;
|
||||
|
||||
/* Set to an option character which was unrecognized.
|
||||
This must be initialized on some systems to avoid linking in the
|
||||
system's own getopt implementation. */
|
||||
|
||||
int optopt = '?';
|
||||
|
||||
/* Describe how to deal with options that follow non-option ARGV-elements.
|
||||
|
||||
If the caller did not specify anything,
|
||||
the default is REQUIRE_ORDER if the environment variable
|
||||
POSIXLY_CORRECT is defined, PERMUTE otherwise.
|
||||
|
||||
REQUIRE_ORDER means don't recognize them as options;
|
||||
stop option processing when the first non-option is seen.
|
||||
This is what Unix does.
|
||||
This mode of operation is selected by either setting the environment
|
||||
variable POSIXLY_CORRECT, or using `+' as the first character
|
||||
of the list of option characters.
|
||||
|
||||
PERMUTE is the default. We permute the contents of ARGV as we scan,
|
||||
so that eventually all the non-options are at the end. This allows options
|
||||
to be given in any order, even with programs that were not written to
|
||||
expect this.
|
||||
|
||||
RETURN_IN_ORDER is an option available to programs that were written
|
||||
to expect options and other ARGV-elements in any order and that care about
|
||||
the ordering of the two. We describe each non-option ARGV-element
|
||||
as if it were the argument of an option with character code 1.
|
||||
Using `-' as the first character of the list of option characters
|
||||
selects this mode of operation.
|
||||
|
||||
The special argument `--' forces an end of option-scanning regardless
|
||||
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
|
||||
`--' can cause `getopt' to return EOF with `optind' != ARGC. */
|
||||
|
||||
static enum
|
||||
{
|
||||
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
|
||||
} ordering;
|
||||
|
||||
/* Value of POSIXLY_CORRECT environment variable. */
|
||||
static char *posixly_correct;
|
||||
|
||||
#ifdef __GNU_LIBRARY__
|
||||
/* We want to avoid inclusion of string.h with non-GNU libraries
|
||||
because there are many ways it can cause trouble.
|
||||
On some systems, it contains special magic macros that don't work
|
||||
in GCC. */
|
||||
#include <string.h>
|
||||
#define my_index strchr
|
||||
#else
|
||||
|
||||
/* Avoid depending on library functions or files
|
||||
whose names are inconsistent. */
|
||||
|
||||
#if !defined(_WIN32)
|
||||
char *getenv ();
|
||||
#endif
|
||||
|
||||
static char *
|
||||
my_index (str, chr)
|
||||
const char *str;
|
||||
int chr;
|
||||
{
|
||||
while (*str)
|
||||
{
|
||||
if (*str == chr)
|
||||
return (char *) str;
|
||||
str++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If using GCC, we can safely declare strlen this way.
|
||||
If not using GCC, it is ok not to declare it. */
|
||||
#ifdef __GNUC__
|
||||
/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
|
||||
That was relevant to code that was here before. */
|
||||
#ifndef __STDC__
|
||||
/* gcc with -traditional declares the built-in strlen to return int,
|
||||
and has done so at least since version 2.4.5. -- rms. */
|
||||
extern int strlen (const char *);
|
||||
#endif /* not __STDC__ */
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#endif /* not __GNU_LIBRARY__ */
|
||||
|
||||
/* Handle permutation of arguments. */
|
||||
|
||||
/* Describe the part of ARGV that contains non-options that have
|
||||
been skipped. `first_nonopt' is the index in ARGV of the first of them;
|
||||
`last_nonopt' is the index after the last of them. */
|
||||
|
||||
static int first_nonopt;
|
||||
static int last_nonopt;
|
||||
|
||||
/* Exchange two adjacent subsequences of ARGV.
|
||||
One subsequence is elements [first_nonopt,last_nonopt)
|
||||
which contains all the non-options that have been skipped so far.
|
||||
The other is elements [last_nonopt,optind), which contains all
|
||||
the options processed since those non-options were skipped.
|
||||
|
||||
`first_nonopt' and `last_nonopt' are relocated so that they describe
|
||||
the new indices of the non-options in ARGV after they are moved. */
|
||||
|
||||
static void
|
||||
exchange (argv)
|
||||
char **argv;
|
||||
{
|
||||
int bottom = first_nonopt;
|
||||
int middle = last_nonopt;
|
||||
int top = optind;
|
||||
char *tem;
|
||||
|
||||
/* Exchange the shorter segment with the far end of the longer segment.
|
||||
That puts the shorter segment into the right place.
|
||||
It leaves the longer segment in the right place overall,
|
||||
but it consists of two parts that need to be swapped next. */
|
||||
|
||||
while (top > middle && middle > bottom)
|
||||
{
|
||||
if (top - middle > middle - bottom)
|
||||
{
|
||||
/* Bottom segment is the short one. */
|
||||
int len = middle - bottom;
|
||||
register int i;
|
||||
|
||||
/* Swap it with the top part of the top segment. */
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
tem = argv[bottom + i];
|
||||
argv[bottom + i] = argv[top - (middle - bottom) + i];
|
||||
argv[top - (middle - bottom) + i] = tem;
|
||||
}
|
||||
/* Exclude the moved bottom segment from further swapping. */
|
||||
top -= len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Top segment is the short one. */
|
||||
int len = top - middle;
|
||||
register int i;
|
||||
|
||||
/* Swap it with the bottom part of the bottom segment. */
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
tem = argv[bottom + i];
|
||||
argv[bottom + i] = argv[middle + i];
|
||||
argv[middle + i] = tem;
|
||||
}
|
||||
/* Exclude the moved top segment from further swapping. */
|
||||
bottom += len;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update records for the slots the non-options now occupy. */
|
||||
|
||||
first_nonopt += (optind - last_nonopt);
|
||||
last_nonopt = optind;
|
||||
}
|
||||
|
||||
/* Initialize the internal data when the first call is made. */
|
||||
|
||||
static const char *
|
||||
_getopt_initialize (optstring)
|
||||
const char *optstring;
|
||||
{
|
||||
/* Start processing options with ARGV-element 1 (since ARGV-element 0
|
||||
is the program name); the sequence of previously skipped
|
||||
non-option ARGV-elements is empty. */
|
||||
|
||||
first_nonopt = last_nonopt = optind = 1;
|
||||
|
||||
nextchar = NULL;
|
||||
|
||||
posixly_correct = getenv ("POSIXLY_CORRECT");
|
||||
|
||||
/* Determine how to handle the ordering of options and nonoptions. */
|
||||
|
||||
if (optstring[0] == '-')
|
||||
{
|
||||
ordering = RETURN_IN_ORDER;
|
||||
++optstring;
|
||||
}
|
||||
else if (optstring[0] == '+')
|
||||
{
|
||||
ordering = REQUIRE_ORDER;
|
||||
++optstring;
|
||||
}
|
||||
else if (posixly_correct != NULL)
|
||||
ordering = REQUIRE_ORDER;
|
||||
else
|
||||
ordering = PERMUTE;
|
||||
|
||||
return optstring;
|
||||
}
|
||||
|
||||
/* Scan elements of ARGV (whose length is ARGC) for option characters
|
||||
given in OPTSTRING.
|
||||
|
||||
If an element of ARGV starts with '-', and is not exactly "-" or "--",
|
||||
then it is an option element. The characters of this element
|
||||
(aside from the initial '-') are option characters. If `getopt'
|
||||
is called repeatedly, it returns successively each of the option characters
|
||||
from each of the option elements.
|
||||
|
||||
If `getopt' finds another option character, it returns that character,
|
||||
updating `optind' and `nextchar' so that the next call to `getopt' can
|
||||
resume the scan with the following option character or ARGV-element.
|
||||
|
||||
If there are no more option characters, `getopt' returns `EOF'.
|
||||
Then `optind' is the index in ARGV of the first ARGV-element
|
||||
that is not an option. (The ARGV-elements have been permuted
|
||||
so that those that are not options now come last.)
|
||||
|
||||
OPTSTRING is a string containing the legitimate option characters.
|
||||
If an option character is seen that is not listed in OPTSTRING,
|
||||
return '?' after printing an error message. If you set `opterr' to
|
||||
zero, the error message is suppressed but we still return '?'.
|
||||
|
||||
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
|
||||
so the following text in the same ARGV-element, or the text of the following
|
||||
ARGV-element, is returned in `optarg'. Two colons mean an option that
|
||||
wants an optional arg; if there is text in the current ARGV-element,
|
||||
it is returned in `optarg', otherwise `optarg' is set to zero.
|
||||
|
||||
If OPTSTRING starts with `-' or `+', it requests different methods of
|
||||
handling the non-option ARGV-elements.
|
||||
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
|
||||
|
||||
Long-named options begin with `--' instead of `-'.
|
||||
Their names may be abbreviated as long as the abbreviation is unique
|
||||
or is an exact match for some defined option. If they have an
|
||||
argument, it follows the option name in the same ARGV-element, separated
|
||||
from the option name by a `=', or else the in next ARGV-element.
|
||||
When `getopt' finds a long-named option, it returns 0 if that option's
|
||||
`flag' field is nonzero, the value of the option's `val' field
|
||||
if the `flag' field is zero.
|
||||
|
||||
The elements of ARGV aren't really const, because we permute them.
|
||||
But we pretend they're const in the prototype to be compatible
|
||||
with other systems.
|
||||
|
||||
LONGOPTS is a vector of `struct option' terminated by an
|
||||
element containing a name which is zero.
|
||||
|
||||
LONGIND returns the index in LONGOPT of the long-named option found.
|
||||
It is only valid when a long-named option has been found by the most
|
||||
recent call.
|
||||
|
||||
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
|
||||
long-named options. */
|
||||
|
||||
int
|
||||
_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *optstring;
|
||||
const struct option *longopts;
|
||||
int *longind;
|
||||
int long_only;
|
||||
{
|
||||
optarg = NULL;
|
||||
|
||||
if (optind == 0)
|
||||
optstring = _getopt_initialize (optstring);
|
||||
|
||||
if (nextchar == NULL || *nextchar == '\0')
|
||||
{
|
||||
/* Advance to the next ARGV-element. */
|
||||
if (ordering == PERMUTE)
|
||||
{
|
||||
/* If we have just processed some options following some non-options,
|
||||
exchange them so that the options come first. */
|
||||
|
||||
if (first_nonopt != last_nonopt && last_nonopt != optind)
|
||||
exchange ((char **) argv);
|
||||
else if (last_nonopt != optind)
|
||||
first_nonopt = optind;
|
||||
|
||||
/* Skip any additional non-options
|
||||
and extend the range of non-options previously skipped. */
|
||||
while (optind < argc
|
||||
&& (argv[optind][0] != '-' || argv[optind][1] == '\0'))
|
||||
optind++;
|
||||
last_nonopt = optind;
|
||||
}
|
||||
|
||||
/* The special ARGV-element `--' means premature end of options.
|
||||
Skip it like a null option,
|
||||
then exchange with previous non-options as if it were an option,
|
||||
then skip everything else like a non-option. */
|
||||
if (optind != argc && !strcmp (argv[optind], "--"))
|
||||
{
|
||||
optind++;
|
||||
|
||||
if (first_nonopt != last_nonopt && last_nonopt != optind)
|
||||
exchange ((char **) argv);
|
||||
else if (first_nonopt == last_nonopt)
|
||||
first_nonopt = optind;
|
||||
last_nonopt = argc;
|
||||
|
||||
optind = argc;
|
||||
}
|
||||
|
||||
/* If we have done all the ARGV-elements, stop the scan
|
||||
and back over any non-options that we skipped and permuted. */
|
||||
if (optind == argc)
|
||||
{
|
||||
/* Set the next-arg-index to point at the non-options
|
||||
that we previously skipped, so the caller will digest them. */
|
||||
if (first_nonopt != last_nonopt)
|
||||
optind = first_nonopt;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/* If we have come to a non-option and did not permute it,
|
||||
either stop the scan or describe it to the caller and pass it by. */
|
||||
if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
|
||||
{
|
||||
if (ordering == REQUIRE_ORDER)
|
||||
return EOF;
|
||||
optarg = argv[optind++];
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We have found another option-ARGV-element.
|
||||
Skip the initial punctuation. */
|
||||
nextchar = (argv[optind] + 1
|
||||
+ (longopts != NULL && argv[optind][1] == '-'));
|
||||
}
|
||||
|
||||
/* Decode the current option-ARGV-element. */
|
||||
|
||||
/* Check whether the ARGV-element is a long option.
|
||||
|
||||
If long_only and the ARGV-element has the form "-f", where f is
|
||||
a valid short option, don't consider it an abbreviated form of
|
||||
a long option that starts with f. Otherwise there would be no
|
||||
way to give the -f short option.
|
||||
|
||||
On the other hand, if there's a long option "fubar" and
|
||||
the ARGV-element is "-fu", do consider that an abbreviation of
|
||||
the long option, just like "--fu", and not "-f" with arg "u".
|
||||
|
||||
This distinction seems to be the most useful approach. */
|
||||
if (longopts != NULL
|
||||
&& (argv[optind][1] == '-'
|
||||
|| (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
|
||||
{
|
||||
char *nameend;
|
||||
const struct option *p;
|
||||
const struct option *pfound = NULL;
|
||||
int exact = 0;
|
||||
int ambig = 0;
|
||||
int indfound;
|
||||
int option_index;
|
||||
|
||||
for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
|
||||
/* Do nothing. */ ;
|
||||
|
||||
/* Test all long options for either exact match
|
||||
or abbreviated matches. */
|
||||
for (p = longopts, option_index = 0; p->name; p++, option_index++)
|
||||
if (!strncmp (p->name, nextchar, nameend - nextchar))
|
||||
{
|
||||
if (nameend - nextchar == (int) strlen (p->name))
|
||||
{
|
||||
/* Exact match found. */
|
||||
pfound = p;
|
||||
indfound = option_index;
|
||||
exact = 1;
|
||||
break;
|
||||
}
|
||||
else if (pfound == NULL)
|
||||
{
|
||||
/* First nonexact match found. */
|
||||
pfound = p;
|
||||
indfound = option_index;
|
||||
}
|
||||
else
|
||||
/* Second or later nonexact match found. */
|
||||
ambig = 1;
|
||||
}
|
||||
|
||||
if (ambig && !exact)
|
||||
{
|
||||
if (opterr)
|
||||
fprintf (stderr, "%s: option `%s' is ambiguous\n",
|
||||
argv[0], argv[optind]);
|
||||
nextchar += strlen (nextchar);
|
||||
optind++;
|
||||
return '?';
|
||||
}
|
||||
|
||||
if (pfound != NULL)
|
||||
{
|
||||
option_index = indfound;
|
||||
optind++;
|
||||
if (*nameend)
|
||||
{
|
||||
/* Don't test has_arg with >, because some C compilers don't
|
||||
allow it to be used on enums. */
|
||||
if (pfound->has_arg)
|
||||
optarg = nameend + 1;
|
||||
else
|
||||
{
|
||||
if (opterr)
|
||||
{
|
||||
if (argv[optind - 1][1] == '-')
|
||||
/* --option */
|
||||
fprintf (stderr,
|
||||
"%s: option `--%s' doesn't allow an argument\n",
|
||||
argv[0], pfound->name);
|
||||
else
|
||||
/* +option or -option */
|
||||
fprintf (stderr,
|
||||
"%s: option `%c%s' doesn't allow an argument\n",
|
||||
argv[0], argv[optind - 1][0], pfound->name);
|
||||
}
|
||||
nextchar += strlen (nextchar);
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
else if (pfound->has_arg == 1)
|
||||
{
|
||||
if (optind < argc)
|
||||
optarg = argv[optind++];
|
||||
else
|
||||
{
|
||||
if (opterr)
|
||||
fprintf (stderr, "%s: option `%s' requires an argument\n",
|
||||
argv[0], argv[optind - 1]);
|
||||
nextchar += strlen (nextchar);
|
||||
return optstring[0] == ':' ? ':' : '?';
|
||||
}
|
||||
}
|
||||
|
||||
nextchar += strlen (nextchar);
|
||||
if (longind != NULL)
|
||||
*longind = option_index;
|
||||
if (pfound->flag)
|
||||
{
|
||||
*(pfound->flag) = pfound->val;
|
||||
return 0;
|
||||
}
|
||||
return pfound->val;
|
||||
}
|
||||
|
||||
/* Can't find it as a long option. If this is not getopt_long_only,
|
||||
or the option starts with '--' or is not a valid short
|
||||
option, then it's an error.
|
||||
Otherwise interpret it as a short option. */
|
||||
if (!long_only || argv[optind][1] == '-'
|
||||
|| my_index (optstring, *nextchar) == NULL)
|
||||
{
|
||||
if (opterr)
|
||||
{
|
||||
if (argv[optind][1] == '-')
|
||||
/* --option */
|
||||
fprintf (stderr, "%s: unrecognized option `--%s'\n",
|
||||
argv[0], nextchar);
|
||||
else
|
||||
/* +option or -option */
|
||||
fprintf (stderr, "%s: unrecognized option `%c%s'\n",
|
||||
argv[0], argv[optind][0], nextchar);
|
||||
}
|
||||
nextchar = (char *) "";
|
||||
optind++;
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
/* Look at and handle the next short option-character. */
|
||||
{
|
||||
char c = *nextchar++;
|
||||
char *temp = my_index (optstring, c);
|
||||
|
||||
/* Increment `optind' when we start to process its last character. */
|
||||
if (*nextchar == '\0')
|
||||
++optind;
|
||||
|
||||
if (temp == NULL || c == ':')
|
||||
{
|
||||
if (opterr)
|
||||
{
|
||||
if (posixly_correct)
|
||||
/* 1003.2 specifies the format of this message. */
|
||||
fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
|
||||
else
|
||||
fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c);
|
||||
}
|
||||
optopt = c;
|
||||
return '?';
|
||||
}
|
||||
if (temp[1] == ':')
|
||||
{
|
||||
if (temp[2] == ':')
|
||||
{
|
||||
/* This is an option that accepts an argument optionally. */
|
||||
if (*nextchar != '\0')
|
||||
{
|
||||
optarg = nextchar;
|
||||
optind++;
|
||||
}
|
||||
else
|
||||
optarg = NULL;
|
||||
nextchar = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is an option that requires an argument. */
|
||||
if (*nextchar != '\0')
|
||||
{
|
||||
optarg = nextchar;
|
||||
/* If we end this ARGV-element by taking the rest as an arg,
|
||||
we must advance to the next element now. */
|
||||
optind++;
|
||||
}
|
||||
else if (optind == argc)
|
||||
{
|
||||
if (opterr)
|
||||
{
|
||||
/* 1003.2 specifies the format of this message. */
|
||||
fprintf (stderr, "%s: option requires an argument -- %c\n",
|
||||
argv[0], c);
|
||||
}
|
||||
optopt = c;
|
||||
if (optstring[0] == ':')
|
||||
c = ':';
|
||||
else
|
||||
c = '?';
|
||||
}
|
||||
else
|
||||
/* We already incremented `optind' once;
|
||||
increment it again when taking next ARGV-elt as argument. */
|
||||
optarg = argv[optind++];
|
||||
nextchar = NULL;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
getopt (argc, argv, optstring)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *optstring;
|
||||
{
|
||||
return _getopt_internal (argc, argv, optstring,
|
||||
(const struct option *) 0,
|
||||
(int *) 0,
|
||||
0);
|
||||
}
|
||||
|
||||
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
||||
Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
it under the terms of the GNU General Public License Version 2 as
|
||||
published by the Free Software Foundation. You may not use, modify or
|
||||
distribute this program under any other version of the GNU General
|
||||
Public License.
|
||||
|
||||
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. */
|
||||
|
||||
int
|
||||
getopt_long (argc, argv, options, long_options, opt_index)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *options;
|
||||
const struct option *long_options;
|
||||
int *opt_index;
|
||||
{
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
|
||||
}
|
||||
|
||||
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
|
||||
If an option that starts with '-' (not '--') doesn't match a long option,
|
||||
but does match a short option, it is parsed as a short option
|
||||
instead. */
|
||||
|
||||
int
|
||||
getopt_long_only (argc, argv, options, long_options, opt_index)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *options;
|
||||
const struct option *long_options;
|
||||
int *opt_index;
|
||||
{
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
|
||||
}
|
||||
|
||||
|
||||
#endif /* _LIBC or not __GNU_LIBRARY__. */
|
20
templates/c
Normal file
20
templates/c
Normal file
|
@ -0,0 +1,20 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://www.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
20
templates/h
Normal file
20
templates/h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Arep *
|
||||
* Support is provided through the forums at *
|
||||
* http://www.console-tribe.com *
|
||||
* *
|
||||
* 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
Loading…
Add table
Add a link
Reference in a new issue