Commit 3a811f0f authored by Aleksey Kravchenko's avatar Aleksey Kravchenko

Imported Upstream version 1.2.5

parents
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so.
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. Use this program at your own risk!
This diff is collapsed.
Linux Installation:
===================
You need GCC (or Intel Compiler) and GNU Make.
To compile and install the program just type
'make install'
To test compiled program run 'make test'.
RPM package can be created by commands
'make rpm' or 'setarch i586 make rpm'.
Create a Debian package with 'make deb'.
To compile with openssl support use the following flags
make ADDCFLAGS="-DUSE_OPENSSL" ADDLDFLAGS="-lcrypto"
Windows Installation:
=====================
You need MinGW compiler and MSYS enviropment.
To compile the program run 'make'.
Otionally you can run 'make test'.
# Samples of usage:
# compile with debug info: make OPTFLAGS=-g OPTLDFLAGS= TARGET=rhash.debug
# compile for pentiumpro: make OPTFLAGS="-O2 -DNDEBUG -march=i586 -mcpu=pentiumpro -fomit-frame-pointer"
# create rpm with statically linked program: make rpm LDFLAGS="-Llibrhash -lrhash -static -s -Wl,--gc-sections"
CC = gcc
VERSION = 1.2.5
DESTDIR =
PREFIX = /usr/local
OPTFLAGS = -O2 -DNDEBUG -fomit-frame-pointer -ffunction-sections -fdata-sections
#DEFFLAGS = -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -ffunction-sections -fdata-sections
ADDCFLAGS =
ADDLDFLAGS =
CFLAGS := -pipe $(OPTFLAGS) $(ADDCFLAGS) \
-Wall -W -Wstrict-prototypes -Wnested-externs -Winline -Wpointer-arith \
-Wbad-function-cast -Wmissing-prototypes -Wmissing-declarations
OPTLDFLAGS = -s
LDFLAGS = -Llibrhash -lrhash $(OPTLDFLAGS) $(ADDLDFLAGS)
HEADERS = calc_sums.h crc_print.h common_func.h crc_update.h file_mask.h file_set.h find_file.h output.h parse_cmdline.h rhash_main.h win_utils.h version.h
SOURCES = calc_sums.c crc_print.c common_func.c crc_update.c file_mask.c file_set.c find_file.c output.c parse_cmdline.c rhash_main.c win_utils.c
OBJECTS = calc_sums.o crc_print.o common_func.o crc_update.o file_mask.o file_set.o find_file.o output.o parse_cmdline.o rhash_main.o win_utils.o
TARGET = rhash
SYMLINKS = sfv-hash tiger-hash tth-hash whirlpool-hash has160-hash gost-hash ed2k-link magnet-link
SPECFILE = $(TARGET).spec
LIN_DIST_FILES = Makefile ChangeLog INSTALL COPYING $(SPECFILE) $(SPECFILE).in $(SOURCES) $(HEADERS) \
tests/test_rhash.sh rhash.1 rhash.1.win.sed rhash.1.html rhash.1.txt
WIN_DIST_FILES = win-dist/MD5.bat win-dist/magnet.bat win-dist/rhashrc \
win-dist/RhashCalculateMd5.reg win-dist/RHashVerify.reg
WIN_SRC_FILES = win32/dirent.h win32/stdint.h win32/unistd.h win32/platform-dependent.h \
win32/vc-2005/rhash.vcproj win32/vc-2010/rhash.vcxproj
LIBRHASH_FILES = librhash/algorithms.c librhash/algorithms.h \
librhash/byte_order.c librhash/byte_order.h librhash/timing.c librhash/timing.h \
librhash/plug_openssl.c librhash/plug_openssl.h librhash/rhash.c librhash/rhash.h \
librhash/aich.c librhash/aich.h librhash/crc32.c librhash/crc32.h \
librhash/ed2k.c librhash/ed2k.h librhash/edonr.c librhash/edonr.h \
librhash/gost.c librhash/gost.h librhash/has160.c librhash/has160.h \
librhash/hex.c librhash/hex.h librhash/md4.c librhash/md4.h librhash/md5.c librhash/md5.h \
librhash/ripemd-160.c librhash/ripemd-160.h librhash/sha1.c librhash/sha1.h \
librhash/sha256.c librhash/sha256.h librhash/sha512.c librhash/sha512.h \
librhash/snefru.c librhash/snefru.h librhash/tiger.c librhash/tiger.h \
librhash/tiger_sbox.c librhash/tth.c librhash/tth.h librhash/whirlpool.c \
librhash/whirlpool.h librhash/whirlpool_sbox.c librhash/test_sums.c \
librhash/test_sums.h librhash/torrent.h librhash/torrent.c \
librhash/util.c librhash/util.h librhash/config.h librhash/Makefile
DIST_FILES = $(LIN_DIST_FILES) $(LIBRHASH_FILES) $(WIN_DIST_FILES) $(WIN_SRC_FILES)
ARCHIVE_BZIP = $(TARGET)-$(VERSION)-src.tar.bz2
ARCHIVE_GZIP = $(TARGET)-$(VERSION)-src.tar.gz
ARCHIVE_7Z = $(TARGET)-$(VERSION)-src.tar.7z
ARCHIVE_ZIP = $(TARGET)-$(VERSION)-win32.zip
ARCHIVE_DEB_GZ = ../$(TARGET)_$(VERSION).orig.tar.gz
BINDIR = $(DESTDIR)$(PREFIX)/bin
MANDIR = $(DESTDIR)$(PREFIX)/share/man
RPMTOP = rpms
RPMDIRS = SOURCES SPECS BUILD SRPMS RPMS
all: $(TARGET)
install: install-program install-symlinks
uninstall: uninstall-program uninstall-symlinks
# NOTE: dependences were generated by 'gcc -Ilibrhash -MM *.c'
# we are using plain old makefile style to support BSD make
calc_sums.o: calc_sums.c librhash/hex.h librhash/rhash.h \
librhash/torrent.h common_func.h librhash/util.h parse_cmdline.h \
rhash_main.h file_set.h calc_sums.h crc_print.h output.h win_utils.h \
version.h
$(CC) -c $(CFLAGS) $< -o $@
common_func.o: common_func.c librhash/hex.h win_utils.h parse_cmdline.h \
common_func.h librhash/util.h
$(CC) -c $(CFLAGS) $< -o $@
crc_print.o: crc_print.c librhash/hex.h librhash/byte_order.h \
common_func.h librhash/util.h calc_sums.h librhash/rhash.h \
parse_cmdline.h crc_print.h
$(CC) -c $(CFLAGS) $< -o $@
crc_update.o: crc_update.c common_func.h librhash/util.h win_utils.h \
parse_cmdline.h output.h rhash_main.h file_set.h calc_sums.h \
librhash/rhash.h file_mask.h crc_update.h
$(CC) -c $(CFLAGS) $< -o $@
file_mask.o: file_mask.c common_func.h librhash/util.h file_mask.h
$(CC) -c $(CFLAGS) $< -o $@
file_set.o: file_set.c librhash/hex.h librhash/crc32.h common_func.h \
librhash/util.h crc_print.h parse_cmdline.h rhash_main.h output.h \
file_set.h calc_sums.h librhash/rhash.h
$(CC) -c $(CFLAGS) $< -o $@
find_file.o: find_file.c common_func.h librhash/util.h win_utils.h \
find_file.h
$(CC) -c $(CFLAGS) $< -o $@
output.o: output.c librhash/rhash.h common_func.h librhash/util.h \
calc_sums.h parse_cmdline.h rhash_main.h output.h
parse_cmdline.o: parse_cmdline.c librhash/rhash.h common_func.h \
librhash/util.h win_utils.h file_mask.h output.h rhash_main.h version.h \
parse_cmdline.h
$(CC) -c $(CFLAGS) $< -o $@
rhash_main.o: rhash_main.c librhash/torrent.h common_func.h \
librhash/util.h win_utils.h find_file.h file_set.h calc_sums.h \
librhash/rhash.h crc_update.h file_mask.h crc_print.h parse_cmdline.h \
output.h rhash_main.h
$(CC) -c $(CFLAGS) $< -o $@
win_utils.o: win_utils.c common_func.h librhash/util.h version.h \
parse_cmdline.h rhash_main.h win_utils.h
$(CC) -c $(CFLAGS) $< -o $@
shared-lib :
cd librhash && make shared SHRFLAGS="-fpic"
librhash/librhash.a: $(LIBRHASH_FILES)
cd librhash && make
$(TARGET): $(OBJECTS) librhash/librhash.a
$(CC) $(OBJECTS) -o $(TARGET) $(LDFLAGS)
test-sums: $(TARGET)
cd librhash && make test
test: test-sums $(TARGET)
chmod +x tests/test_$(TARGET).sh
tests/test_$(TARGET).sh
version.h : Makefile
echo "#define VERSION \"$(VERSION)\"" > version.h
win-dist/rhash.1.html: rhash.1 rhash.1.win.sed
sed -f rhash.1.win.sed rhash.1 | rman -fHTML -roff | \
sed -e '/<BODY/s/\(bgcolor=\)"[^"]*"/\1"white"/i' > win-dist/rhash.1.html
rhash.1.html: rhash.1
-which rman &>/dev/null && (rman -fHTML -roff rhash.1 | sed -e '/<BODY/s/\(bgcolor=\)"[^"]*"/\1"white"/i' > rhash.1.html)
rhash.1.txt: rhash.1
-which groff &>/dev/null && (groff -t -e -mandoc -Tascii rhash.1 | sed -e 's/.\[[0-9]*m//g' > rhash.1.txt)
cppdoc:
cppdoc_cmd -title=RHash -company=Animegorodok -classdir=classdoc -module="cppdoc-standard" -overwrite -extensions="c,h" -languages="c=cpp,h=cpp" -generate-deprecations-list=false $(SOURCES) $(HEADERS) ./Documentation/CppDoc/index.html
install-program: all
install -d $(BINDIR) $(MANDIR)/man1 $(DESTDIR)/etc
install -m 755 $(TARGET) $(BINDIR)
install -m 644 rhash.1 $(MANDIR)/man1/rhash.1
sed -e 's/\x0D//g' win-dist/rhashrc > rhashrc && install -m 644 rhashrc $(DESTDIR)/etc/rhashrc
rm -f rhashrc
install-symlinks:
test -x $(BINDIR)/$(TARGET)
for f in $(SYMLINKS); do ln -s rhash $(BINDIR)/$$f; done
cd $(MANDIR)/man1 && for f in $(SYMLINKS); do ln -s rhash.1* $$f.1; done
uninstall-program:
rm -f $(BINDIR)/$(TARGET)
rm -f $(MANDIR)/man1/rhash.1
uninstall-symlinks:
for f in $(SYMLINKS); do rm -f $(BINDIR)/$$f; done
check: check-version
check-version: version.h
grep -q '\* === Version $(VERSION) ===' ChangeLog
grep -q "^- === Version $(VERSION) ===" rhash.spec.in
[ ! -f debian/changelog ] || grep -q '^rhash ($(VERSION)-' debian/changelog
grep -q '^#define VERSION "$(VERSION)"' version.h
# check that man pages were correctly generated
[ -s rhash.1.txt -a -s rhash.1.html ]
permissions:
chmod -x $(DIST_FILES)
chmod +x tests/test_$(TARGET).sh
-chmod +x debian/rules
dist: gzip
gzip: check-version $(ARCHIVE_GZIP)
bzip: check-version $(ARCHIVE_BZIP)
7z: check-version $(ARCHIVE_7Z)
zip : $(ARCHIVE_ZIP)
win-dist : $(ARCHIVE_ZIP)
$(ARCHIVE_GZIP): $(DIST_FILES)
make permissions
rm -rf $(TARGET)-$(VERSION)
mkdir $(TARGET)-$(VERSION)
cp -rl --parents $(DIST_FILES) $(TARGET)-$(VERSION)/
tar czf $(ARCHIVE_GZIP) $(TARGET)-$(VERSION)/
rm -rf $(TARGET)-$(VERSION)
$(ARCHIVE_BZIP): $(DIST_FILES)
make permissions
rm -rf $(TARGET)-$(VERSION)
mkdir $(TARGET)-$(VERSION)
cp -rl --parents $(DIST_FILES) $(TARGET)-$(VERSION)/
tar cjf $(ARCHIVE_BZIP) $(TARGET)-$(VERSION)/
rm -rf $(TARGET)-$(VERSION)
$(ARCHIVE_7Z): $(DIST_FILES)
make permissions
rm -rf $(TARGET)-$(VERSION)
mkdir $(TARGET)-$(VERSION)
cp -rl --parents $(DIST_FILES) $(TARGET)-$(VERSION)/
tar cf - $(TARGET)-$(VERSION)/ | 7zr a -si $(ARCHIVE_7Z)
rm -rf $(TARGET)-$(VERSION)
WIN32_ZIP_DIR := RHash-$(VERSION)-win32
$(ARCHIVE_ZIP): $(TARGET) $(WIN_DIST_FILES) win-dist/rhash.1.html rhash.1.txt
[ -s win-dist/rhash.1.html ]
-rm -rf $(WIN32_ZIP_DIR)
mkdir $(WIN32_ZIP_DIR)
cp $(TARGET).exe win-dist/rhash.1.html rhash.1.txt ChangeLog $(WIN_DIST_FILES) $(WIN32_ZIP_DIR)/
zip -9r $(ARCHIVE_ZIP) $(WIN32_ZIP_DIR)
rm -rf $(WIN32_ZIP_DIR)
$(SPECFILE): $(SPECFILE).in Makefile
sed -e 's/@VERSION@/$(VERSION)/' $(SPECFILE).in > $(SPECFILE)
rpm: gzip
-for i in $(RPMDIRS); do mkdir -p $(RPMTOP)/$$i; done
cp -f $(ARCHIVE_GZIP) $(RPMTOP)/SOURCES
rpmbuild -ba --clean --define "_topdir `pwd`/$(RPMTOP)" $(SPECFILE)
mv -f `find $(RPMTOP) -name "rhash-*$(VERSION)*.rpm"` .
rm -rf $(RPMTOP)
$(ARCHIVE_DEB_GZ) : $(DIST_FILES)
make $(ARCHIVE_GZIP)
mv -f $(ARCHIVE_GZIP) $(ARCHIVE_DEB_GZ)
deb: $(ARCHIVE_DEB_GZ)
debuild
rm -rf debian/rhash
lintian ../rhash_$(VERSION)-*.changes
ubuntu: deb-src
deb-src:
debuild -S
lintian ../rhash_$(VERSION)-*_source.changes
dist-clean: clean
clean:
cd librhash && make clean
rm -f *.o $(TARGET)
This diff is collapsed.
/* calc_sums.h */
#ifndef CALC_SUMS_H
#define CALC_SUMS_H
#include <stdint.h>
#include "librhash/rhash.h"
#include "common_func.h"
#ifdef __cplusplus
extern "C" {
#endif
/* binary result of calculations */
typedef struct rhash_sums_t
{
unsigned flags;
union {
unsigned char digest[4];
unsigned be;
} crc32;
unsigned char md4_digest[16];
unsigned char md5_digest[16];
unsigned char ed2k_digest[16];
unsigned char sha1_digest[20];
unsigned char tiger_digest[24];
unsigned char tth_digest[24];
unsigned char aich_digest[20];
unsigned char whirlpool_digest[64];
unsigned char ripemd160_digest[20];
unsigned char gost_digest[32];
unsigned char gost_cryptopro_digest[32];
unsigned char snefru256_digest[32];
unsigned char snefru128_digest[16];
unsigned char has160_digest[20];
unsigned char btih_digest[20];
unsigned char sha224_digest[28];
unsigned char sha256_digest[32];
unsigned char sha384_digest[48];
unsigned char sha512_digest[64];
unsigned char edonr256_digest[32];
unsigned char edonr512_digest[64];
} rhash_sums_t;
#include <sys/types.h> /* struct stat */
#include <sys/stat.h> /* stat() */
/* information about currently processed file */
struct file_info {
char* full_path;
const char* print_path;
char* utf8_print_path;
uint64_t size; /* the size of the file */
double time; /* file processing time in seconds */
struct infohash_ctx *infohash;
struct rhash_sums_t *orig_sums; /* sums from a crc file */
rhash rctx; /* state of hash algorithms */
unsigned wrong_sums; /* sum comparison results */
int error; /* -1 for i/o error, -2 for wrong sum, 0 on success */
char* allocated_ptr;
/* note: rsh_stat_struct size depends on _FILE_OFFSET_BITS */
struct rsh_stat_struct stat_buf; /* file attributes */
struct rhash_sums_t sums; /* sums of the file */
};
void file_info_destroy(struct file_info*); /* free allocated memory */
const char* file_info_get_utf8_print_path(struct file_info*);
unsigned char* rhash_get_digest_ptr(struct rhash_sums_t *sums, unsigned hash_id);
int calculate_and_print_sums(FILE* out, const char *print_path, const char *full_path, struct rsh_stat_struct* stat_buf);
int check_crc_file(const char* crc_file_path, int chdir);
int rename_file_to_embed_crc32(struct file_info *info);
void print_sfv_banner(FILE* out);
int print_sfv_header_line(FILE* out, const char* printpath, const char* fullpath);
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* CALC_SUMS_H */
/* common_func.c */
#include "common_func.h" /* should be included before the C library files */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <stdint.h>
#include <time.h>
#include "librhash/hex.h"
#include "win_utils.h"
#include "parse_cmdline.h"
/**
* Print a 0-terminated string representation of a 64-bit number to char buffer.
*/
void sprintI64(char *dst, uint64_t number, int max_width)
{
char buf[24];
size_t len;
char *p = buf + 23;
*(p--) = 0; /* last symbol should be '\0' */
if(number == 0) {
*(p--) = '0';
} else {
for(; p >= buf && number != 0; p--, number /= 10) {
*p = '0' + (char)(number % 10);
}
}
len = buf + 22 - p;
if((size_t)max_width > len) {
memset(dst, 0x20, max_width - len);
dst += max_width - len;
}
memcpy(dst, p+1, len+1);
}
/**
* Calculate length of decimal representation of given 64-bit integer.
*
* @param num integer to calculate the length for
* @return length of decimal representation
*/
int int_len(uint64_t num)
{
int len;
for(len = 0; num; len++, num /= 10);
return (len == 0 ? 1 : len); /* note: int_len(0) == 1 */
}
/* unsafe characters are "<>{}[]%#/|\^~`@:;?=&+ */
#define IS_GOOD_URL_CHAR(c) (((unsigned char)(c) < 128 && isalnum(c)) || strchr("$-_.!*'(),", c))
/**
* URL-encode given string.
*
* @param dst buffer to recieve result or NULL to calculate encoded string size
* @param filename the file name
* @return the length of the result string
*/
int urlencode(char *dst, const char *name)
{
const char *start;
if(!dst) {
int len;
for(len = 0; *name; name++) len += (IS_GOOD_URL_CHAR(*name) ? 1 : 3);
/* ed2k://|file|<fname>|<fsize>|2E398E5533AE4A83475B1AF001C6CEE6|h=RKLBEXT4O2H4RZER676WAVWGACIHQ56Z|/ */
return len;
}
/* encode URL as specified by RFC 1738 */
for(start = dst; *name; name++) {
if( IS_GOOD_URL_CHAR(*name) ) {
*dst++ = *name;
} else {
*dst++ = '%';
dst = put_hex_char(dst, *name, 'A');
}
}
*dst = 0;
return (int)(dst - start);
}
/**
* Convert given string to lower case.
* The result string will be allocated by malloc.
* The allocated memory should be freed by calling free().
*
* @param str a string to convert
* @return converted string allocated by malloc
*/
char* str_tolower(const char* str)
{
char* buf = rsh_strdup(str);
char* p;
if(buf) {
for(p = buf; *p; p++) *p = tolower(*p);
}
return buf;
}
/**
* Remove spaces from the begin and the end of the string.
*
* @param str the modifiable buffer with the string
* @return trimmed string
*/
char* str_trim(char* str)
{
char* last = str + strlen(str) - 1;
while(isspace(*str)) str++;
while(isspace(*last) && last > str) *(last--) = 0;
return str;
}
/**
* Fill a buffer with NULL-terminated string consisting
* solely of a given repeated character.
*
* @param buf the modifiable buffer to fill
* @param ch the character to fill string with
* @param length the length of the string to construct
* @return the buffer
*/
char* str_set(char* buf, int ch, int length)
{
memset(buf, ch, length);
buf[length] = '\0';
return buf;
}
/**
* Check if a string is a binary string, which means the string contain
* a character with ACII code below 0x20 other than '\r', '\n', '\t'.
*
* @param str a string to check
* @return non zero if string is binary
*/
int is_binary_string(const char* str)
{
for(; *str; str++) {
if(((unsigned char)*str) < 32 && ((1 << (unsigned char)*str) & ~0x2600)) {
return 1;
}
}
return 0;
}
/**
* Count number of utf8 characters in a 0-terminated string
*
* @param str the string to measure
* @return number of utf8 characters in the string
*/
size_t strlen_utf8_c(const char *str)
{
size_t length = 0;
for(; *str; str++) {
if((*str & 0xc0) != 0x80) length++;
}
return length;
}
/**
* Exit the program, with restoring console state.
*
* @param code the program exit code
*/
void rhash_exit(int code)
{
IF_WINDOWS(restore_console());
exit(code);
}
/* FILE FUNCTIONS */
/**
* Return filename without path.
*
* @param path file path
* @return filename
*/
const char* get_basename(const char* path)
{
const char *p = path + strlen(path) - 1;
for(; p >= path && !IS_PATH_SEPARATOR(*p); p--);
return (p+1);
}
/**
* Return allocated buffer with the directory part of the path.
* The buffer must be freed by calling free().
*
* @param path file path
* @return directory
*/
char* get_dirname(const char* path)
{
const char *p = path + strlen(path) - 1;
char *res;
for(; p > path && !IS_PATH_SEPARATOR(*p); p--);
if((p - path) > 1) {
res = (char*)rsh_malloc(p-path+1);
memcpy(res, path, p-path);
res[p-path] = 0;
return res;
} else {
return rsh_strdup(".");
}
}
/**
* Assemble a filepath from its directory and filename.
*
* @param dir_path directory path
* @param filename file name
* @return filepath
*/
char* make_path(const char* dir_path, const char* filename)
{
char* buf;
size_t len;
assert(dir_path);
assert(filename);
/* remove leading path separators from filename */
while(IS_PATH_SEPARATOR(*filename)) filename++;
/* copy directory path */
len = strlen(dir_path);
buf = (char*)rsh_malloc(len + strlen(filename) + 2);
strcpy(buf, dir_path);
/* separate directory from filename */
if(len > 0 && !IS_PATH_SEPARATOR(buf[len-1]))
buf[len++] = SYS_PATH_SEPARATOR;
/* append filename */
strcpy(buf+len, filename);
return buf;
}
/**
* Print time formated as hh:mm.ss YYYY-MM-DD to a file stream.
*
* @param out the stream to print time to
* @param time the time to print
*/
void print_time(FILE *out, time_t time)
{
struct tm *t = localtime(&time);
static struct tm zero_tm;
if(t == NULL) {
/* if strange day, then print `00:00.00 1900-01-00' */
t = &zero_tm;
t->tm_hour = t->tm_min = t->tm_sec =
t->tm_year = t->tm_mon = t->tm_mday = 0;
}
fprintf(out, "%02u:%02u.%02u %4u-%02u-%02u", t->tm_hour, t->tm_min,
t->tm_sec, (1900+t->tm_year), t->tm_mon+1, t->tm_mday);
}
#ifdef _WIN32
#include <windows.h>
#endif
/**
* Return ticks in milliseconds for time intervals measurement.
* This function should be not precise but the fastest one
* to retrive internal clock value.
*
* @return ticks count in milliseconds
*/
unsigned rhash_get_ticks(void)
{
#ifdef _WIN32
return GetTickCount();
#else
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
#endif
}
/* common_func.h */
#ifndef COMMON_FUNC_H
#define COMMON_FUNC_H
/* use 64-bit off_t */
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#include <stdint.h>
#include <stdio.h>
#include <time.h> /* for time_t */
#include "librhash/util.h"
#ifndef _WIN32
#include <sys/time.h> /* for timeval */
/*#else
#include <windows.h>*/
#elif _MSC_VER > 1300
#include "win32/platform-dependent.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* string function */
void sprintI64(char *dst, uint64_t number, int max_width);
int int_len(uint64_t num);
int urlencode(char *dst, const char *name);
int is_binary_string(const char* str);
char* str_tolower(const char* str);
char* str_trim(char* str);
char* str_set(char* buf, int ch, int size);
size_t strlen_utf8_c(const char *str);
#define IS_DASH_STR(s) ((s)[0] == '-' && (s)[1] == '\0')
#define IS_COMMENT(c) ((c) == ';' || (c) == '#')
/* file function */
const char* get_basename(const char* path);
char* get_dirname(const char* path);
char* make_path(const char* dir, const char* filename);
#ifdef _WIN32
# define IF_WINDOWS(code) code
# define SYS_PATH_SEPARATOR '\\'
# define IS_PATH_SEPARATOR(c) ((c) == '\\' || (c) == '/')
# define rsh_fopen_bin(path, mode) win_fopen_bin(path, mode)
# define is_utf8() win_is_utf8()
# define to_utf8(str) win_to_utf8(str)
#else /* non _WIN32 part */
# define IF_WINDOWS(code)
# define SYS_PATH_SEPARATOR '/'
# define IS_PATH_SEPARATOR(c) ((c) == '/')
# define rsh_fopen_bin(path, mode) fopen(path, mode)
/* stub for utf8 */
# define is_utf8() 1
# define to_utf8(str) NULL
#endif /* _WIN32 */
/* rhash stat function */
#if (__MSVCRT_VERSION__ >= 0x0601) || (_MSC_VER >= 1400)
# define rsh_stat_struct __stat64
# define rsh_time_struct __time64_t
# define rsh_stat(path, st) win_stat(path, st)
# define clib_wstat(path, st) _wstat64(path, st)
#elif defined(_WIN32) && (defined(__MSVCRT__) || defined(_MSC_VER))
# define rsh_stat_struct _stati64
# define rsh_time_struct __time64_t