Commit 6a7ee97e authored by Aleksey Kravchenko's avatar Aleksey Kravchenko

Imported Upstream version 1.3.2

parent 3cda9e74
Wed Jan 8 2014
Wed Jul 2 2014 Aleksey
* === Version 1.3.2 ===
Sat Jun 21 2014 Aleksey
* report warnings on files locked by some processes
Thu Jun 19 2014 Brad Campbell
* ignore non-regular files while scanning directories recursively
Wed Jun 18 2014 Aleksey
* option --follow for following symlinks to directories
Sun Apr 13 2014 ZinnKid
* BTIH piece length calculation updated to follow the uTorrent algorithm change
Wed Jan 8 2014 Aleksey
* === Version 1.3.1 ===
* Exclude the files specified by -o and -l from processing
......
......@@ -2,7 +2,7 @@
# compile with debug info: make CFLAGS=-g
# compile for pentiumpro: make CFLAGS="-O2 -DNDEBUG -march=i586 -mcpu=pentiumpro -fomit-frame-pointer"
# create rpm with statically linked program: make rpm ADDLDFLAGS="-static -s -Wl,--gc-sections"
VERSION = 1.3.1
VERSION = 1.3.2
PREFIX = /usr/local
CC = gcc
# using OPTFLAGS/OPTLDFLAGS for compatibilty with old scripts using this makefile
......@@ -18,7 +18,7 @@ ALLCFLAGS = -pipe $(CFLAGS) $(ADDCFLAGS) \
LDLIBRHASH = -Llibrhash -lrhash
ALLLDFLAGS = $(LDLIBRHASH) $(LDFLAGS) $(ADDLDFLAGS)
SHAREDLIB = librhash/librhash.so.0
SHRDLFLAGS = $(SHAREDLIB) $(LDFLAGS) $(ADDLDFLAGS)
SHRDLFLAGS = $(LDFLAGS) $(ADDLDFLAGS)
HEADERS = calc_sums.h hash_print.h common_func.h hash_update.h file_mask.h file_set.h find_file.h hash_check.h output.h parse_cmdline.h rhash_main.h win_utils.h version.h
SOURCES = calc_sums.c hash_print.c common_func.c hash_update.c file_mask.c file_set.c find_file.c hash_check.c output.c parse_cmdline.c rhash_main.c win_utils.c
OBJECTS = calc_sums.o hash_print.o common_func.o hash_update.o file_mask.o file_set.o find_file.o hash_check.o output.o parse_cmdline.o rhash_main.o win_utils.o
......@@ -139,11 +139,11 @@ test-libs: $(LIBRHASH) $(SHAREDLIB)
test: test-static
test-static: $(TARGET)
chmod +x tests/test_$(PROGNAME).sh
tests/test_$(PROGNAME).sh
chmod +x tests/test_rhash.sh
tests/test_rhash.sh
test-shared: $(SHARED_TRG) test-shared-lib
chmod +x tests/test_$(PROGNAME).sh
chmod +x tests/test_rhash.sh
LD_LIBRARY_PATH=../librhash:$(LD_LIBRARY_PATH) tests/test_rhash.sh ./$(SHARED_TRG)
version.h: Makefile
......@@ -161,7 +161,7 @@ $(TARGET): $(OBJECTS) $(LIBRHASH)
$(CC) $(OBJECTS) -o $@ $(ALLLDFLAGS)
$(SHARED_TRG): $(OBJECTS) $(SHAREDLIB)
$(CC) $(OBJECTS) -o $(SHARED_TRG) $(SHRDLFLAGS)
$(CC) $(OBJECTS) $(SHRDLFLAGS) -o $(SHARED_TRG) $(SHAREDLIB)
# NOTE: dependences were generated by 'gcc -Ilibrhash -MM *.c'
# we are using plain old makefile style to support BSD make
......@@ -239,7 +239,7 @@ cpp-doc:
permissions:
find . dist librhash po win32 win32/vc-2010 -maxdepth 1 -type f -exec chmod -x '{}' \;
chmod +x tests/test_$(PROGNAME).sh
chmod +x tests/test_rhash.sh
clean-bindings:
+make -C bindings distclean
......
......@@ -390,8 +390,7 @@ int calculate_and_print_sums(FILE* out, file_t* file, const char *print_path)
if(info.sums_flags) {
/* calculate sums */
if(calc_sums(&info) < 0) {
/* print error unless sharing access error occurred */
if(errno == EACCES) return 0;
/* print i/o error */
log_file_error(file->path);
res = -1;
}
......
......@@ -377,7 +377,7 @@ int rsh_file_statw(file_t* file)
if(GetFileAttributesExW(file->wpath, GetFileExInfoStandard, &data)) {
uint64_t u;
file->size = (((uint64_t)data.nFileSizeHigh) << 32) + data.nFileSizeLow;
file->mode = (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? FILE_IFDIR : 0);
file->mode = (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? FILE_IFDIR : FILE_IFREG);
/* the number of 100-nanosecond intervals since January 1, 1601 */
u = (((uint64_t)data.ftLastWriteTime.dwHighDateTime) << 32) + data.ftLastWriteTime.dwLowDateTime;
......@@ -424,13 +424,31 @@ int rsh_file_stat2(file_t* file, int use_lstat)
return -1;
#else
struct rsh_stat_struct st;
int res = -1;
res = (use_lstat ? lstat(file->path, &st) : rsh_stat(file->path, &st));
int res = 0;
file->mode = 0;
do {
if(use_lstat) {
/* check for symlink */
if(lstat(file->path, &st) < 0) return -1;
if(!S_ISLNK(st.st_mode)) break;
/* it's a symlink */
file->mode |= FILE_IFLNK;
}
res = rsh_stat(file->path, &st);
} while(0);
file->size = st.st_size;
file->mtime = st.st_mtime;
file->mode = 0;
if(S_ISDIR(st.st_mode)) file->mode |= FILE_IFDIR;
if(S_ISDIR(st.st_mode)) {
file->mode |= FILE_IFDIR;
} else if(S_ISREG(st.st_mode)) {
/* it's a regular file or a symlink pointing to a regular file */
file->mode |= FILE_IFREG;
}
return res;
#endif /* _WIN32 */
......@@ -559,12 +577,17 @@ char* rhash_strdup(const char* str, const char* srcfile, int srcline)
* @param srcline source code line to be reported on fail
* @return allocated memory buffer with copied string
*/
wchar_t* rhash_wcsdup(wchar_t* str, const char* srcfile, int srcline)
wchar_t* rhash_wcsdup(const wchar_t* str, const char* srcfile, int srcline)
{
#ifndef __STRICT_ANSI__
wchar_t* res = wcsdup(str);
#else
wchar_t* res = (wchar_t*)malloc((wcslen(str) + 1) * sizeof(wchar_t));
if(res) wcscpy(res, str);
#endif
if(!res) {
rsh_report_error(srcfile, srcline, "wcsdup() failed\n");
rsh_report_error(srcfile, srcline, "wcsdup(\"%u\") failed\n", (wcslen(str) + 1));
rsh_exit(2);
}
return res;
......
......@@ -92,9 +92,12 @@ typedef struct file_t
/* bit constants for the file_t.mode bit mask */
#define FILE_IFDIR 0x01
#define FILE_IFLNK 0x02
#define FILE_IFREG 0x04
#define FILE_IFROOT 0x10
#define FILE_IFSTDIN 0x20
#define FILE_ISDIR(file) ((file)->mode & FILE_IFDIR)
#define FILE_ISLNK(file) ((file)->mode & FILE_IFLNK)
#define FILE_ISREG(file) ((file)->mode & FILE_IFREG)
/* file functions */
......@@ -152,7 +155,7 @@ void* rhash_realloc(void* mem, size_t size, const char* srcfile, int srcline);
#ifdef _WIN32
#define rsh_wcsdup(str) rhash_wcsdup(str, __FILE__, __LINE__)
wchar_t* rhash_wcsdup(wchar_t* str, const char* srcfile, int srcline);
wchar_t* rhash_wcsdup(const wchar_t* str, const char* srcfile, int srcline);
#endif
......
......@@ -12,7 +12,7 @@ rhash \- calculate/check CRC32, MD5, SHA1, GOST, TTH, BTIH or other hash sums.
(Recursive Hasher)
computes and verifies various message digests (hash sums) of files.
Supported message digests include CRC32, MD4, MD5, SHA1, SHA256, SHA512,
Tiger, DC++ TTH, BitTorrent BTIH, AICH, ED2K, GOST R 34.11\-94,
SHA3, Tiger, DC++ TTH, BitTorrent BTIH, AICH, ED2K, GOST R 34.11\-94,
RIPEMD\-160, HAS\-160, EDON\-R 256/512, Whirlpool, Snefru\-128/256.
The program can create and verify Magnet links
......@@ -72,6 +72,8 @@ MD5: calculate and print MD5 hash sum.
SHA1: calculate and print SHA1 hash sum.
.IP "\-\-sha224, \-\-sha256, \-\-sha384, \-\-sha512"
Calculate specified SHA2 hash sum.
.IP "\-\-sha3-224, \-\-sha3-256, \-\-sha3-384, \-\-sha3-512"
Calculate specified SHA3 hash sum.
.IP "\-\-tiger"
Tiger: calculate and print Tiger hash sum.
.IP "\-T, \-\-tth"
......
......@@ -16,86 +16,90 @@ sums.
<h2><a name='sect2' href='#toc2'>Description</a></h2>
<b>RHash</b> (Recursive Hasher)
computes and verifies various message digests (hash sums) of files. Supported
message digests include CRC32, MD4, MD5, SHA1, SHA256, SHA512, Tiger, DC++
TTH, BitTorrent BTIH, AICH, ED2K, GOST R 34.11-94, RIPEMD-160, HAS-160, EDON-R
256/512, Whirlpool, Snefru-128/256.
<p> The program can create and verify Magnet
links and eDonkey ed2k:// links, see --magnet and --ed2k-link options.
<p> A dash
string parameter &lsquo;-&rsquo; is interpreted as stdin file.
<p> By default <b>rhash</b> prints
sums in SFV format with CRC32 hash sum only. The format can be changed by
options --bsd, --magnet, --simple, --printf, --template. To output all sums use the
&lsquo;-a&rsquo; option.
<p> The default output format can also be changed by renaming the
program or placing a hardlink/symlink to it with a name containing strings
&lsquo;crc32&rsquo;, &lsquo;md4&rsquo;, &lsquo;md5&rsquo;, &lsquo;sha1&rsquo;, &lsquo;sha256&rsquo; &lsquo;sha512&rsquo;, &lsquo;tiger&rsquo;, &lsquo;tth&rsquo;, &lsquo;btih&rsquo;, &lsquo;aich&rsquo;, &lsquo;ed2k&rsquo;, &lsquo;ed2k-link&rsquo;,
&lsquo;gost&rsquo;, &lsquo;gost-cryptopro&rsquo;, &lsquo;ripemd160&rsquo;, &lsquo;has160&rsquo;, &lsquo;whirlpool&rsquo;, &lsquo;edonr256&rsquo;, &lsquo;edonr512&rsquo;,
&lsquo;snefru128&rsquo;, &lsquo;snefru256&rsquo;, &lsquo;sfv&rsquo; or &lsquo;magnet&rsquo;.
message digests include CRC32, MD4, MD5, SHA1, SHA256, SHA512, SHA3, Tiger,
DC++ TTH, BitTorrent BTIH, AICH, ED2K, GOST R 34.11-94, RIPEMD-160, HAS-160,
EDON-R 256/512, Whirlpool, Snefru-128/256.
<p> The program can create and verify
Magnet links and eDonkey ed2k:// links, see --magnet and --ed2k-link options.
<p> A dash string parameter &lsquo;-&rsquo; is interpreted as stdin file.
<p> By default <b>rhash</b>
prints sums in SFV format with CRC32 hash sum only. The format can be changed
by options --bsd, --magnet, --simple, --printf, --template. To output all sums use
the &lsquo;-a&rsquo; option.
<p> The default output format can also be changed by renaming
the program or placing a hardlink/symlink to it with a name containing
strings &lsquo;crc32&rsquo;, &lsquo;md4&rsquo;, &lsquo;md5&rsquo;, &lsquo;sha1&rsquo;, &lsquo;sha256&rsquo; &lsquo;sha512&rsquo;, &lsquo;tiger&rsquo;, &lsquo;tth&rsquo;, &lsquo;btih&rsquo;, &lsquo;aich&rsquo;, &lsquo;ed2k&rsquo;,
&lsquo;ed2k-link&rsquo;, &lsquo;gost&rsquo;, &lsquo;gost-cryptopro&rsquo;, &lsquo;ripemd160&rsquo;, &lsquo;has160&rsquo;, &lsquo;whirlpool&rsquo;, &lsquo;edonr256&rsquo;,
&lsquo;edonr512&rsquo;, &lsquo;snefru128&rsquo;, &lsquo;snefru256&rsquo;, &lsquo;sfv&rsquo; or &lsquo;magnet&rsquo;.
<p>
<h2><a name='sect3' href='#toc3'>Program Mode Options</a></h2>
The default mode
is to print hash sums for all files and directory trees specified by command
line. The mode can be set by the following options.
The
default mode is to print hash sums for all files and directory trees specified
by command line. The mode can be set by the following options.
<dl>
<dt>-c, --check</dt>
<dd>Check hash files
specified by command line. RHash can verify hash files in SFV and BSD formats,
standard MD5 and SHA1 files, and text files containing magnet or ed2k links
(one link per line). Empty lines and lines starting with &lsquo;;&rsquo; or &lsquo;#&rsquo; are skipped.
In fact RHash can verify most hash files generated by itself without formating
options --printf and --template. </dd>
<dd>Check
hash files specified by command line. RHash can verify hash files in SFV
and BSD formats, standard MD5 and SHA1 files, and text files containing
magnet or ed2k links (one link per line). Empty lines and lines starting
with &lsquo;;&rsquo; or &lsquo;#&rsquo; are skipped. In fact RHash can verify most hash files generated
by itself without formating options --printf and --template. </dd>
<dt>-u, --update</dt>
<dd>Update hash files specified by command
line. The program calculates and appends hashes to the updated hash file
in the format specified by formating options. Hashes are calculated for
those files from the same directory as the hash file, which are yet not
present in it. </dd>
<dd>Update
hash files specified by command line. The program calculates and appends
hashes to the updated hash file in the format specified by formating options.
Hashes are calculated for those files from the same directory as the hash
file, which are yet not present in it. </dd>
<dt>-k, --check-embedded</dt>
<dd>Verify files by crc32 sum embedded in their
names. </dd>
<dd>Verify files by crc32
sum embedded in their names. </dd>
<dt>--torrent</dt>
<dd>Create a torrent file for each processed file. </dd>
<dd>Create a torrent file for each processed
file. </dd>
<dt>-h, --help</dt>
<dd>Help:
print help screen and exit. </dd>
<dd>Help: print help screen and exit. </dd>
<dt>-V, --version</dt>
<dd>Version: print version and exit. </dd>
<dd>Version: print version
and exit. </dd>
<dt>-B,
--benchmark</dt>
<dt>-B, --benchmark</dt>
<dd>Run benchmark for selected algorithm(s).
<p> </dd>
</dl>
<h2><a name='sect4' href='#toc4'>Hash Sums Options</a></h2>
<h2><a name='sect4' href='#toc4'>Hash Sums
Options</a></h2>
<dl>
<dt>-C, --crc32</dt>
<dd>CRC32:
calculate and print CRC32 hash sum. </dd>
<dd>CRC32: calculate and print CRC32 hash sum. </dd>
<dt>--md4</dt>
<dd>MD4: calculate and print MD4 hash
sum. </dd>
<dd>MD4: calculate
and print MD4 hash sum. </dd>
<dt>-M, --md5</dt>
<dd>MD5: calculate and print MD5 hash sum. </dd>
<dt>-H, --sha1</dt>
<dd>SHA1: calculate
and print SHA1 hash sum. </dd>
<dd>SHA1:
calculate and print SHA1 hash sum. </dd>
<dt>--sha224, --sha256, --sha384, --sha512</dt>
<dd>Calculate
specified SHA2 hash sum. </dd>
<dt>--sha3-224, --sha3-256, --sha3-384, --sha3-512</dt>
<dd>Calculate specified
SHA2 hash sum. </dd>
SHA3 hash sum. </dd>
<dt>--tiger</dt>
<dd>Tiger: calculate and print Tiger hash sum. </dd>
......
%define version 1.3.1
%define version 1.3.2
# major is the part of the shared library name after the .so
%define major 0
%define libname %mklibname rhash %{major}
......@@ -102,6 +102,7 @@ ldconfig
ldconfig
%changelog
* Wed Jul 2 2014 Aleksey <rhash.admin@gmail.com> 1.3.2-1mdk
* Wed Jan 08 2014 Aleksey <rhash.admin@gmail.com> 1.3.1-1mdk
* Tue Jun 11 2013 Aleksey <rhash.admin@gmail.com> 1.3.0-1mdk
* Tue Dec 25 2012 Aleksey <rhash.admin@gmail.com> 1.2.10-1mdk
......
......@@ -102,6 +102,7 @@ ldconfig
ldconfig
%changelog
* Wed Jul 2 2014 Aleksey <rhash.admin@gmail.com> 1.3.2-1mdk
* Wed Jan 08 2014 Aleksey <rhash.admin@gmail.com> 1.3.1-1mdk
* Tue Jun 11 2013 Aleksey <rhash.admin@gmail.com> 1.3.0-1mdk
* Tue Dec 25 2012 Aleksey <rhash.admin@gmail.com> 1.2.10-1mdk
......
......@@ -195,6 +195,7 @@ void scan_files(file_search_data* data)
{
size_t i;
size_t count = data->root_files.size;
int skip_symlink_dirs = !(data->options & FIND_FOLLOW_SYMLINKS);
for(i = 0; i < count && !(data->options & FIND_CANCEL); i++)
{
......@@ -203,13 +204,17 @@ void scan_files(file_search_data* data)
/* check if file is a directory */
if(FILE_ISDIR(file)) {
/* silently skip symlinks to directories if required */
if(skip_symlink_dirs && FILE_ISLNK(file)) {
continue;
}
if(data->max_depth != 0) {
find_file(file, data);
} else if((data->options & FIND_LOG_ERRORS) != 0) {
errno = EISDIR;
log_file_error(file->path);
}
continue;
} else {
/* process a regular file or a dash '-' path */
data->call_back(file, data->call_back_data);
......@@ -218,7 +223,7 @@ void scan_files(file_search_data* data)
}
/**
* A entry of a list containing files from a directory.
* An entry of a list containing content of a directory.
*/
typedef struct dir_entry
{
......@@ -286,7 +291,7 @@ static void dir_entry_drop_head(dir_entry** p)
*/
typedef struct dir_iterator
{
int left;
int count;
char* dir_path;
} dir_iterator;
#define MAX_DIRS_DEPTH 64
......@@ -295,16 +300,16 @@ typedef struct dir_iterator
* Walk directory tree and call given callback function to process each file/directory.
*
* @param start_dir path to the directory to walk recursively
* @param options the options specifying how to walk the directory tree
* @param data the options specifying how to walk the directory tree
* @return 0 on success, -1 on error
*/
int find_file(file_t* start_dir, file_search_data* options)
int find_file(file_t* start_dir, file_search_data* data)
{
dir_entry *dirs_stack = NULL; /* root of the dir_list */
dir_iterator* it;
int level = 0;
int max_depth = options->max_depth;
int flags = options->options;
int max_depth = data->max_depth;
int options = data->options;
file_t file;
if(max_depth < 0 || max_depth >= MAX_DIRS_DEPTH) {
......@@ -320,8 +325,8 @@ int find_file(file_t* start_dir, file_search_data* options)
}
/* check if we should descend into the root directory */
if((flags & (FIND_WALK_DEPTH_FIRST | FIND_SKIP_DIRS)) == 0) {
if(!options->call_back(start_dir, options->call_back_data))
if((options & (FIND_WALK_DEPTH_FIRST | FIND_SKIP_DIRS)) == 0) {
if(!data->call_back(start_dir, data->call_back_data))
return 0;
}
......@@ -332,12 +337,12 @@ int find_file(file_t* start_dir, file_search_data* options)
}
/* push dummy counter for the root element */
it[0].left = 1;
it[0].count = 1;
it[0].dir_path = 0;
memset(&file, 0, sizeof(file));
while(!(options->options & FIND_CANCEL))
while(!(data->options & FIND_CANCEL))
{
dir_entry **insert_at;
char* dir_path;
......@@ -345,7 +350,7 @@ int find_file(file_t* start_dir, file_search_data* options)
struct dirent *de;
/* climb down from the tree */
while(--it[level].left < 0) {
while(--it[level].count < 0) {
/* do not need this dir_path anymore */
free(it[level].dir_path);
......@@ -356,7 +361,7 @@ int find_file(file_t* start_dir, file_search_data* options)
return 0;
}
}
assert(level >= 0 && it[level].left >= 0);
assert(level >= 0 && it[level].count >= 0);
/* take a filename from dirs_stack and construct the next path */
if(level) {
......@@ -373,16 +378,16 @@ int find_file(file_t* start_dir, file_search_data* options)
/* fill the next level of directories */
level++;
assert(level < MAX_DIRS_DEPTH);
it[level].left = 0;
it[level].count = 0;
it[level].dir_path = dir_path;
if((flags & (FIND_WALK_DEPTH_FIRST | FIND_SKIP_DIRS)) == FIND_WALK_DEPTH_FIRST)
if((options & (FIND_WALK_DEPTH_FIRST | FIND_SKIP_DIRS)) == FIND_WALK_DEPTH_FIRST)
{
file.path = rsh_strdup(dir_path);
rsh_file_stat2(&file, USE_LSTAT);
/* check if we should skip the directory */
if(!options->call_back(&file, options->call_back_data)) {
if(!data->call_back(&file, data->call_back_data)) {
rsh_file_cleanup(&file);
continue;
}
......@@ -407,24 +412,26 @@ int find_file(file_t* start_dir, file_search_data* options)
res = rsh_file_stat2(&file, USE_LSTAT);
if(res >= 0) {
/* process the file or directory */
if(FILE_ISDIR(&file) && (flags & (FIND_WALK_DEPTH_FIRST | FIND_SKIP_DIRS))) {
res = 1;
} else {
if(FILE_ISDIR(&file) && (options & (FIND_WALK_DEPTH_FIRST | FIND_SKIP_DIRS))) {
res = ((options & FIND_FOLLOW_SYMLINKS) || !FILE_ISLNK(&file));
} else if (FILE_ISREG(&file)) {
/* handle file by callback function */
res = options->call_back(&file, options->call_back_data);
res = data->call_back(&file, data->call_back_data);
}
/* check if file is a directory and we need to walk it, */
/* but don't go deeper than max_depth */
if(FILE_ISDIR(&file) && res && level < max_depth) {
if(FILE_ISDIR(&file) && res && level < max_depth &&
((options & FIND_FOLLOW_SYMLINKS) || !FILE_ISLNK(&file)))
{
/* add the directory name to the dirs_stack */
if(dir_entry_insert(insert_at, de->d_name, file.mode)) {
/* the directory name was successfully inserted */
insert_at = &((*insert_at)->next);
it[level].left++;
it[level].count++;
}
}
} else if (options->options & FIND_LOG_ERRORS) {
} else if (options & FIND_LOG_ERRORS) {
/* report error only if FIND_LOG_ERRORS option is set */
log_file_error(file.path);
}
......
......@@ -14,7 +14,7 @@ extern "C" {
/* find_file options */
#define FIND_WALK_DEPTH_FIRST 1
#define FIND_FOLLOW_LINKS 2
#define FIND_FOLLOW_SYMLINKS 2
#define FIND_SKIP_DIRS 4
#define FIND_LOG_ERRORS 8
#define FIND_CANCEL 16
......@@ -37,7 +37,7 @@ void destroy_file_search_data(file_search_data* data);
void scan_files(file_search_data* data);
int find_file(file_t* start_dir, file_search_data* options);
int find_file(file_t* start_dir, file_search_data* data);
#ifdef __cplusplus
} /* extern "C" */
......
......@@ -402,12 +402,13 @@ RHASH_API int rhash_file_update(rhash ctx, FILE* fd)
buffer = pmem + align8;
while(!feof(fd)) {
if(ectx->state != STATE_ACTIVE) break; /* stop if canceled */
/* stop if canceled */
if(ectx->state != STATE_ACTIVE) break;
length = fread(buffer, 1, block_size, fd);
/* read can return -1 on error */
if(length == (size_t)-1) {
res = -1; /* note: fread sets errno */
if(ferror(fd)) {
res = -1; /* note: errno contains error code */
break;
} else if (length) {
rhash_update(ctx, buffer, length);
......
This diff is collapsed.
......@@ -35,6 +35,7 @@
#define SHA1_FINAL(ctx, result) rhash_sha1_final(&ctx->sha1_context, (result))
#endif
#define BT_MIN_HASH_LENGTH 16384
/** size of a SHA1 hash in bytes */
#define BT_HASH_SIZE 20
/** number of SHA1 hashes to store together in one block */
......@@ -48,7 +49,8 @@
void bt_init(torrent_ctx* ctx)
{
memset(ctx, 0, sizeof(torrent_ctx));
ctx->piece_length = 65536;
ctx->piece_length = BT_MIN_HASH_LENGTH;
assert(BT_MIN_HASH_LENGTH == bt_default_piece_length(0));
#ifdef USE_OPENSSL
{
......@@ -362,9 +364,9 @@ static void bt_bencode_pieces(torrent_ctx* ctx)
/**
* Calculate default torrent piece length, using uTorrent algorithm.
* Algorithm:
* length = 64K for total_size < 64M,
* length = 4M for total_size >= 2G,
* length = top_bit(total_size) / 512 otherwise.
* length = 16K for total_size < 16M,
* length = 8M for total_size >= 4G,
* length = top_bit(total_size) / 1024 otherwise.
*
* @param total_size total hashed batch size of torrent file
* @return piece length used by torrent file
......@@ -372,9 +374,9 @@ static void bt_bencode_pieces(torrent_ctx* ctx)
size_t bt_default_piece_length(uint64_t total_size)
{
uint64_t hi_bit;
if(total_size < 67108864) return 65536;
if(total_size >= I64(2147483648) ) return 4194304;
for(hi_bit = 67108864 << 1; hi_bit <= total_size; hi_bit <<= 1);
if(total_size < 16777216) return BT_MIN_HASH_LENGTH;
if(total_size >= I64(4294967296) ) return 8388608;
for(hi_bit = 16777216 << 1; hi_bit <= total_size; hi_bit <<= 1);
return (size_t)(hi_bit >> 10);
}
......
......@@ -327,6 +327,9 @@ cmdline_opt_t cmdline_opt[] =
/* other options */
{ F_UFLG, 'r', 'R', "recursive", &opt.flags, OPT_RECURSIVE },
#ifndef _WIN32 /* Unix-only option */
{ F_UFLG, 0, 0, "follow", &opt.flags, OPT_FOLLOW },
#endif
{ F_UFLG, 'v', 0, "verbose", &opt.flags, OPT_VERBOSE },
{ F_UFLG, 0, 0, "gost-reverse", &opt.flags, OPT_GOST_REVERSE },
{ F_UFLG, 0, 0, "skip-ok", &opt.flags, OPT_SKIP_OK },
......@@ -376,7 +379,7 @@ static void die(const char* msg)
*/
static void fail_on_unknow_option(const char* option_name)
{
log_error(_("unknown option: %s"), (option_name ? option_name : "?"));
log_error(_("unknown option: %s\n"), (option_name ? option_name : "?"));
rsh_exit(2);
}
......
......@@ -32,18 +32,19 @@ enum {
MODE_TORRENT = 0x10,
/* misc options */
OPT_EMBED_CRC = 0x20,
OPT_RECURSIVE = 0x40,
OPT_SKIP_OK = 0x80,
OPT_IGNORE_CASE = 0x100,
OPT_VERBOSE = 0x200,
OPT_PERCENTS = 0x400,
OPT_SPEED = 0x800,
OPT_BT_PRIVATE = 0x1000,
OPT_UPPERCASE = 0x2000,
OPT_LOWERCASE = 0x4000,
OPT_GOST_REVERSE = 0x8000,
OPT_BENCH_RAW = 0x10000,
OPT_EMBED_CRC = 0x20,
OPT_RECURSIVE = 0x40,
OPT_FOLLOW = 0x80,
OPT_SKIP_OK = 0x100,
OPT_IGNORE_CASE = 0x200,
OPT_VERBOSE = 0x400,
OPT_PERCENTS = 0x800,
OPT_SPEED = 0x1000,
OPT_BT_PRIVATE = 0x2000,
OPT_UPPERCASE = 0x4000,
OPT_LOWERCASE = 0x8000,
OPT_GOST_REVERSE = 0x10000,
OPT_BENCH_RAW = 0x20000,
#ifdef _WIN32
OPT_UTF8 = 0x10000000,
......
......@@ -144,8 +144,8 @@ static int load_printf_template(void)
while (!feof(fd)) {
len = fread(buffer, 1, 8192, fd);
/* read can return -1 on error */
if (len == (size_t)-1) break;
if (ferror(fd)) break;
rsh_str_append_n(rhash_data.template_text, buffer, len);
if (rhash_data.template_text->len >= MAX_TEMPLATE_SIZE) {
log_msg(_("%s: template file is too big\n"), opt.template_file);
......@@ -255,6 +255,7 @@ int main(int argc, char *argv[])
}
opt.search_data->options = FIND_SKIP_DIRS;
opt.search_data->options |= (opt.flags & OPT_FOLLOW ? FIND_FOLLOW_SYMLINKS : 0);
opt.search_data->call_back = find_file_callback;
if((sfv = (opt.fmt == FMT_SFV && !opt.mode))) {
......@@ -275,7 +276,7 @@ int main(int argc, char *argv[])
rhash_data.processed = 0;
/* process files */
opt.search_data->options = FIND_SKIP_DIRS | FIND_LOG_ERRORS;
opt.search_data->options |= FIND_LOG_ERRORS;
opt.search_data->call_back_data = 0;
scan_files(opt.search_data);
......
#!/bin/bash
#!/bin/sh
if [ "$1" = "--full" ]; then FULL_TEST=1; shift; fi
......@@ -12,7 +12,7 @@ fi
[ "$rhash" != "../rhash" ] && echo "Testing $rhash"
#version="`$rhash -V|sed 's/^.* v//'`"
HASHOPT="`$rhash --list-hashes|sed 's/ .*$//;s/-\([0-9R]\)/\1/'|tr A-Z a-z`"
HASHOPT="`$rhash --list-hashes|sed 's/ .*$//;/[^3]-/s/-\([0-9R]\)/\1/'|tr A-Z a-z`"
test_num=1;
sub_test=0;
......@@ -80,6 +80,18 @@ check "$TEST_RESULT" "$TEST_EXPECTED" .
TEST_RESULT=$( $rhash --simple --gost --gost-cryptopro --gost-reverse test1K.data | $rhash -vc - 2>/dev/null | grep test1K.data )
match "$TEST_RESULT" "^test1K.data *OK"
new_test "test handling empty files: "
echo -n "" > test-empty.file
TEST_RESULT=$( $rhash -p "%m" test-empty.file )
check "$TEST_RESULT" "d41d8cd98f00b204e9800998ecf8427e" .
# now test processing of empty stdin
TEST_RESULT=$( echo -n "" | $rhash -p "%m" - )
check "$TEST_RESULT" "d41d8cd98f00b204e9800998ecf8427e" .
# test verification of empty file
TEST_RESULT=$( $rhash -c test-empty.file | grep "^[^-]" )
check "$TEST_RESULT" "Everything OK"
rm test-empty.file
# Test the SFV format using test1K.data from the previous test
new_test "test default format: "
$rhash test1K.data | (
......
#define VERSION "1.3.1"
#define VERSION "1.3.2"
......@@ -191,9 +191,9 @@ int can_open_exclusive(const char* path)
}
return res;
}
/* the range of error codes for access errors */
#define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
/* the range of error codes for access errors */
#define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
#define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED
/**
......@@ -208,12 +208,12 @@ static int convert_last_error_to_errno(void)
{
case NO_ERROR:
return 0;
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
case ERROR_INVALID_DRIVE:
case ERROR_BAD_NETPATH:
case ERROR_BAD_PATHNAME:
case ERROR_FILENAME_EXCED_RANGE:
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
case ERROR_INVALID_DRIVE:
case ERROR_BAD_NETPATH:
case ERROR_BAD_PATHNAME:
case ERROR_FILENAME_EXCED_RANGE:
return ENOENT;
case ERROR_TOO_MANY_OPEN_FILES:
return EMFILE;
......@@ -248,12 +248,12 @@ static int convert_last_error_to_errno(void)
return EEXIST;
case ERROR_NESTING_NOT_ALLOWED:
return EAGAIN;
}
/* try to detect error by range */
if (MIN_EACCES_RANGE <= error_code && error_code <= MAX_EACCES_RANGE) {
return EACCES;
} else {
}
/* try to detect error by range */
if (MIN_EACCES_RANGE <= error_code && error_code <= MAX_EACCES_RANGE) {