Commit c6706f67 authored by Aleksey Kravchenko's avatar Aleksey Kravchenko

Imported Upstream version 1.2.6

parent 3a811f0f
RHash License
Copyright (c) 2005-2011 Alexey Kravchenko <rhash.admin@gmail.com>
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
......@@ -5,6 +10,6 @@ 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
The Software 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!
Thu Jun 16 2011 Aleksey
* === Version 1.2.6 ===
Sat Jun 11 2011 Aleksey
* allowed options to be intermixed with file names in arbitrary order
* switched option -G and the '%G' printf pattern to print GOST hash
* Bugfix: --output failed for cyrillic file name
Wed Jun 8 2011 Aleksey
* librhash: better shared library compilation/testing support
Mon Jun 6 2011 Aleksey
* librhash: exported benchmarking functions in the shared library
* librhash: added prefix to all functions to avoid poluting linker namespace
* librhash: fixed rare alignment bugs in rhash_print and EDON-R 512
Sat May 28 2011 Aleksey
* librhash: loading openssl at runtime if it is present
* Bugfix: LLVM GOST amd64 asm compilation error
Wed May 18 2011 Aleksey
* === Version 1.2.5 ===
* option --openssl allows to replace some algorithms by the OpenSSL ones
......
......@@ -7,15 +7,17 @@ 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'.
To test the 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"
make ADDCFLAGS="-DUSE_OPENSSL -DOPENSSL_RUNTIME -rdynamic" ADDLDFLAGS="-ldl"
The LibRHash library can be compiled using
'make lib-static' or 'make lib-shared'
Windows Installation:
=====================
......@@ -24,3 +26,6 @@ You need MinGW compiler and MSYS enviropment.
To compile the program run 'make'.
Otionally you can run 'make test'.
The LibRHash DLL can be created by
cd librhash && make dll test-dll
This diff is collapsed.
=== RHash program ===
RHash is a console utility for calculation and verification of magnet links
and a wide range of hash sums like CRC32, MD4, MD5, SHA1, SHA256, SHA512,
AICH, ED2K, Tiger, DC++ TTH, BitTorrent BTIH, GOST R 34.11-94, RIPEMD-160,
HAS-160, EDON-R, Whirlpool and Snefru.
Hash sums are used to ensure and verify integrity of large volumes of data
for a long-term storing or transferring.
Features:
* Output in a predefined (SFV, BSD-like) or a user-defined format.
* Can calculate Magnet links and EDonkey 2000 links.
* Updating hash files (adding hash sums of files missing in the hash file).
* Ability to process directories recursively.
* Portability: the program works the same on Linux, *BSD or Windows.
=== The LibRHash library ===
LibRHash is a professional, portable, thread-safe C library for computing
a wide variety of hash sums, such as CRC32, MD4, MD5, SHA1, SHA256, SHA512,
AICH, ED2K, Tiger, DC++ TTH, BitTorrent BTIH, GOST R 34.11-94, RIPEMD-160
HAS-160, EDON-R, Whirlpool and Snefru.
Hash sums are used to ensure and verify integrity of large volumes of data
for a long-term storing or transferring.
Features:
* Small and easy to learn interface.
* Hi-level and Low-level API.
* Allows calculating of several hash functions simultaniously.
* Portability: the library works on Linux, *BSD and Windows.
=== About hash functions ===
* RHash hash functions descriptions http://rhash.anz.ru/hashes.php
* Table of the hash functions supported by RHash
https://sourceforge.net/apps/mediawiki/rhash/index.php?title=Hash_sums
* ECRYPT: The Hash Function Zoo
http://ehash.iaik.tugraz.at/wiki/The_Hash_Function_Zoo
=== Notes on RHash License ===
The RHash program and LibRHash library are distributed under RHash License,
see the COPYING file for details. In particluar, the program, the library
and source code can be used free of charge under the MIT, BSD, GPL,
commercial or freeware license without additional restrictions. In the case
the OSI-approved license is required the MIT license should be used.
......@@ -13,7 +13,6 @@
#include "librhash/hex.h"
#include "librhash/rhash.h"
#include "librhash/torrent.h"
#include "librhash/timing.h"
#include "parse_cmdline.h"
#include "rhash_main.h"
......@@ -26,55 +25,36 @@
#include "calc_sums.h"
/**
* Calculate hash sums simultaneously, according to info->sums.flags.
* Initialize BTIH hash function. Unlike other algorithms BTIH
* requires more data for correct computation.
*
* @param fdin file descriptor to read from
* @param info the file data to store calculated hashes to
* @return 0 on success. On error -1 is returned and errno is set
* @param info the file data
*/
static int calc_sums_fd(FILE* fd, struct file_info *info)
static void init_btih_data(struct file_info *info)
{
assert(info->rctx == 0);
info->rctx = rhash_init(info->sums.flags);
/* initialize bittorrent data */
if(info->sums.flags & RHASH_BTIH) {
torrent_ctx *bt_ctx = (torrent_ctx*)rhash_get_context_ptr(info->rctx, RHASH_BTIH);
torrent_add_file(bt_ctx, get_basename(file_info_get_utf8_print_path(info)), info->size);
torrent_set_program_name(bt_ctx, PROGRAM_NAME "/" VERSION);
if(opt.flags & OPT_BT_PRIVATE) {
torrent_set_options(bt_ctx, BT_OPT_PRIVATE);
}
if(opt.bt_announce) {
torrent_set_announce(bt_ctx, opt.bt_announce);
}
if(opt.bt_piece_length) {
torrent_set_piece_length(bt_ctx, opt.bt_piece_length);
}
}
assert((info->rctx->hash_id & RHASH_BTIH) != 0);
rhash_transmit(RMSG_BT_ADD_FILE, info->rctx, RHASH_STR2UPTR((char*)get_basename(file_info_get_utf8_print_path(info))), (rhash_uptr_t)&info->size);
rhash_transmit(RMSG_BT_SET_PROGRAM_NAME, info->rctx, RHASH_STR2UPTR(PROGRAM_NAME "/" VERSION), 0);
if(percents_output->update != 0) {
rhash_set_callback(info->rctx, (rhash_callback_t)percents_output->update, info);
}
if(opt.flags & OPT_BT_PRIVATE) {
rhash_transmit(RMSG_BT_SET_OPTIONS, info->rctx, RHASH_BT_OPT_PRIVATE, 0);
}
/* read and hash file content */
if(rhash_file_update(info->rctx, fd) == -1) return -1;
if(opt.bt_announce) {
rhash_transmit(RMSG_BT_SET_ANNOUNCE, info->rctx, RHASH_STR2UPTR(opt.bt_announce), 0);
}
rhash_final(info->rctx, 0); /* finalize hashing */
info->size = info->rctx->msg_size;
rhash_data.total_size += info->size;
/*if(info->infohash) infohash_add_file(info->infohash, info->full_path, filesize);*/
return 0;
if(opt.bt_piece_length) {
rhash_transmit(RMSG_BT_SET_PIECE_LENGTH, info->rctx, RHASH_STR2UPTR(opt.bt_piece_length), 0);
}
}
/**
* Calculate hash sums simultaneously, according to the info->sums.flags.
* Calculated hashes are stored in info->rctx.
*
* @param info file data. The info->full_path can be "-" to denote stdin
* @return 0 on success. On error -1 is returned and errno is set
* @return 0 on success, -1 on fail with error code stored in errno
*/
static int calc_sums(struct file_info *info)
{
......@@ -85,7 +65,7 @@ static int calc_sums(struct file_info *info)
info->print_path = "(stdin)";
#ifdef _WIN32
/* using 0, wich is _fileno(stdin). _fileno() is undefined under 'gcc -ansi' */
/* using 0 instead of _fileno(stdin). _fileno() is undefined under 'gcc -ansi' */
if(setmode(0, _O_BINARY) < 0) {
return -1;
}
......@@ -113,8 +93,27 @@ static int calc_sums(struct file_info *info)
return -1;
}
}
assert(info->rctx == 0);
info->rctx = rhash_init(info->sums.flags);
/* initialize bittorrent data */
if(info->sums.flags & RHASH_BTIH) {
init_btih_data(info);
}
if(percents_output->update != 0) {
rhash_set_callback(info->rctx, (rhash_callback_t)percents_output->update, info);
}
/* read and hash file content */
if((res = rhash_file_update(info->rctx, fd)) != -1) {
rhash_final(info->rctx, 0); /* finalize hashing */
info->size = info->rctx->msg_size;
rhash_data.total_size += info->size;
}
res = calc_sums_fd(fd, info);
if(fd != stdin) fclose(fd);
return res;
}
......@@ -197,7 +196,7 @@ static int find_embedded_crc32(const char* filepath, unsigned* crc32_be)
const char *p = e + 8;
for(; p > e && IS_HEX(*p); p--);
if(p == e) {
hex_to_byte(e + 1, (char unsigned*)crc32_be, 8);
rhash_hex_to_byte(e + 1, (char unsigned*)crc32_be, 8);
return 1;
}
e -= 9;
......@@ -280,25 +279,24 @@ static void save_torrent(struct file_info* info)
char *str;
FILE* fd;
struct rsh_stat_struct stat_buf;
size_t len = strlen(info->full_path);
char* path = rsh_malloc(len + 9);
torrent_ctx* bt_ctx = rhash_get_context_ptr(info->rctx, RHASH_BTIH);
assert(bt_ctx);
size_t path_len = strlen(info->full_path);
size_t text_len;
char* path = (char*)rsh_malloc(path_len + 9);
/* append .torrent extension to the file path */
memcpy(path, info->full_path, len);
memcpy(path + len, ".torrent", 9);
memcpy(path, info->full_path, path_len);
memcpy(path + path_len, ".torrent", 9);
/* get torrent file content */
len = torrent_get_text(bt_ctx, &str);
text_len = rhash_transmit(RMSG_BT_GET_TEXT, info->rctx, (unsigned long)&str, 0);
assert(text_len != RHASH_ERROR);
if(rsh_stat(path, &stat_buf) >= 0) {
errno = EEXIST;
log_file_error(path);
} else {
fd = rsh_fopen_bin(path, "wb");
if(fd && len == fwrite(str, 1, len, fd) && !ferror(fd)) {
if(fd && text_len == fwrite(str, 1, text_len, fd) && !ferror(fd)) {
log_msg("%s saved\n", path);
} else {
log_file_error(path);
......@@ -314,7 +312,7 @@ static void save_torrent(struct file_info* info)
* @param out a stream to print to
* @param filepath path to the file to calculate sums for
* @param fullpath fullpath to the file relative to the current directory
* @return 0 on success, -1 on error
* @return 0 on success, -1 on fail
*/
int calculate_and_print_sums(FILE* out, const char *print_path, const char *full_path, struct rsh_stat_struct* stat_buf)
{
......@@ -351,7 +349,7 @@ int calculate_and_print_sums(FILE* out, const char *print_path, const char *full
/* initialize percents output */
init_percents(&info);
timer_start(&timer);
rhash_timer_start(&timer);
if(info.sums.flags) {
/* calculate sums */
......@@ -363,7 +361,7 @@ int calculate_and_print_sums(FILE* out, const char *print_path, const char *full
}
}
info.time = timer_stop(&timer);
info.time = rhash_timer_stop(&timer);
finish_percents(&info, res);
if(opt.mode & MODE_TORRENT) {
......@@ -543,14 +541,14 @@ static int verify_sums(struct file_info *info)
/* initialize percents output */
init_percents(info);
timer_start(&timer);
rhash_timer_start(&timer);
if(calc_sums(info) < 0) {
finish_percents(info, -1);
return -1;
}
fill_sums_struct(info);
info->time = timer_stop(&timer);
info->time = rhash_timer_stop(&timer);
/* compare the sums and fill info->wrong_sums flags */
if((orig_sums.flags & RHASH_CRC32) && info->sums.crc32.be != orig_sums.crc32.be) {
......@@ -655,7 +653,7 @@ static int verify_sums(struct file_info *info)
*
* @param crc_file_path - the path of the file with hash sums to verify.
* @param chdir - true if function should emulate chdir to directory of filepath before checking it.
* @return zero on success, -1 on error
* @return zero on success, -1 on fail
*/
int check_crc_file(const char* crc_file_path, int chdir)
{
......@@ -710,7 +708,7 @@ int check_crc_file(const char* crc_file_path, int chdir)
ralign = str_set(buf, '-', (pos < 80 ? 80 - (int)pos : 2));
fprintf(rhash_data.out, "\n--( Verifying %s )%s\n", crc_file_path, ralign);
fflush(rhash_data.out);
timer_start(&timer);
rhash_timer_start(&timer);
/* mark dirname part of the path, by setting pos */
if(chdir) {
......@@ -783,7 +781,7 @@ int check_crc_file(const char* crc_file_path, int chdir)
rhash_data.processed++;
free(path_without_ext);
}
time = timer_stop(&timer);
time = rhash_timer_stop(&timer);
fprintf(rhash_data.out, "%s\n", str_set(buf, '-', 80));
print_check_stats();
......@@ -806,7 +804,7 @@ int check_crc_file(const char* crc_file_path, int chdir)
* @param out a stream to print info to
* @param printpath relative file path to print
* @param fullpath a path to the file relative to the current directory.
* @return 0 on success, -1 on error with error stored in errno
* @return 0 on success, -1 on fail with error code stored in errno
*/
int print_sfv_header_line(FILE* out, const char* printpath, const char* fullpath)
{
......
......@@ -75,7 +75,7 @@ int urlencode(char *dst, const char *name)
*dst++ = *name;
} else {
*dst++ = '%';
dst = put_hex_char(dst, *name, 'A');
dst = rhash_print_hex_byte(dst, *name, 'A');
}
}
*dst = 0;
......
......@@ -47,6 +47,7 @@ char* make_path(const char* dir, const char* filename);
# define IF_WINDOWS(code) code
# define SYS_PATH_SEPARATOR '\\'
# define IS_PATH_SEPARATOR(c) ((c) == '\\' || (c) == '/')
# define IS_PATH_SEPARATOR_W(c) ((c) == L'\\' || (c) == L'/')
# 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)
......
......@@ -211,10 +211,10 @@ print_item* parse_percent_item(const char** str)
int pad_with_zero_bit = 0;
print_item* item = NULL;
static const char *short_hash = "CMHGTWRAE";
static const char *short_hash = "CMHTGWRAE";
static const char *short_other = "Llpfus";
static const unsigned hash_ids[] = {
RHASH_CRC32, RHASH_MD5, RHASH_SHA1, RHASH_TIGER, RHASH_TTH,
RHASH_CRC32, RHASH_MD5, RHASH_SHA1, RHASH_TTH, RHASH_GOST,
RHASH_WHIRLPOOL, RHASH_RIPEMD160, RHASH_AICH, RHASH_ED2K
};
static const unsigned other_flags[] = {
......@@ -436,9 +436,9 @@ void free_print_list(print_item* list)
void init_hash_info_table(void)
{
unsigned index, bit;
unsigned short_opt_mask = RHASH_CRC32 | RHASH_MD5 | RHASH_SHA1 | RHASH_TIGER | RHASH_TTH |
RHASH_ED2K | RHASH_AICH | RHASH_WHIRLPOOL | RHASH_RIPEMD160 | OPT_ED2K_LINK;
char* short_opt = "cmhgteawrl";
unsigned short_opt_mask = RHASH_CRC32 | RHASH_MD5 | RHASH_SHA1 | RHASH_TTH | RHASH_ED2K |
RHASH_AICH | RHASH_WHIRLPOOL | RHASH_RIPEMD160 | RHASH_GOST | OPT_ED2K_LINK;
char* short_opt = "cmhteawrgl";
print_hash_info *info = hash_info_table;
unsigned fullmask = RHASH_ALL_HASHES | OPT_ED2K_LINK;
......@@ -472,7 +472,7 @@ void init_hash_info_table(void)
void init_printf_format(strbuf_t* out)
{
const char* fmt, *tail = 0;
unsigned bit, index = get_ctz(opt.sum_flags);
unsigned bit, index = rhash_ctz(opt.sum_flags);
int uppercase;
char up_flag;
......@@ -484,10 +484,10 @@ void init_printf_format(strbuf_t* out)
(!(opt.flags & OPT_LOWERCASE) && (opt.fmt & FMT_SFV)));
up_flag = (uppercase ? ~0x20 : 0xFF);
strbuf_ensure_size(out, 1024); /* allocate big enough buffer */
rsh_str_ensure_size(out, 1024); /* allocate big enough buffer */
if(opt.sum_flags & OPT_ED2K_LINK) {
str_append_n(out, "%l", 2);
rsh_str_append_n(out, "%l", 2);
out->str[1] &= up_flag;
return;
}
......@@ -497,13 +497,13 @@ void init_printf_format(strbuf_t* out)
if(opt.fmt == FMT_BSD) {
fmt = "\003(%p) = \001\\n";
} else if(opt.fmt == FMT_MAGNET) {
str_append(out, "magnet:?xl=%s&dn=%{urlname}");
rsh_str_append(out, "magnet:?xl=%s&dn=%{urlname}");
fmt = "&xt=urn:\002:\001";
tail = "\\n";
} else if(opt.fmt == FMT_SIMPLE && 0 == (opt.sum_flags & (opt.sum_flags - 1))) {
fmt = "\001 %p\\n";
} else {
str_append_n(out, "%p", 2);
rsh_str_append_n(out, "%p", 2);
fmt = (opt.fmt == FMT_SFV ? " \001" : " \001");
tail = "\\n";
}
......@@ -515,7 +515,7 @@ void init_printf_format(strbuf_t* out)
print_hash_info *info = &hash_info_table[index];
if((bit & opt.sum_flags) == 0) continue;
strbuf_ensure_size(out, out->len + 256); /* allocate big enough buffer */
rsh_str_ensure_size(out, out->len + 256); /* allocate big enough buffer */
for(;;) {
int i;
......@@ -530,16 +530,16 @@ void init_printf_format(strbuf_t* out)
char *letter;
out->str[out->len++] = '{';
letter = out->str + out->len;
str_append(out, info->short_name);
rsh_str_append(out, info->short_name);
*letter &= up_flag;
out->str[out->len++] = '}';
}
break;
case 2:
str_append(out, info->urn);
rsh_str_append(out, info->urn);
break;
case 3:
str_append(out, info->name);
rsh_str_append(out, info->name);
i = (int)strlen(info->name);
for(i = (i < 5 ? 6 - i : 1); i > 0; i--) out->str[out->len++] = ' ';
break;
......@@ -547,7 +547,7 @@ void init_printf_format(strbuf_t* out)
}
}
if(tail) {
str_append(out, tail);
rsh_str_append(out, tail);
}
out->str[out->len] = '\0';
}
......@@ -42,7 +42,7 @@ int update_crc_file(const char* crc_file_path)
crc_entries = file_set_new();
res = file_set_load_from_crc_file(crc_entries, crc_file_path);
if(opt.flags & OPT_SPEED) timer_start(&timer);
if(opt.flags & OPT_SPEED) rhash_timer_start(&timer);
rhash_data.total_size = 0;
rhash_data.processed = 0;
......@@ -57,7 +57,7 @@ int update_crc_file(const char* crc_file_path)
file_set_free(crc_entries);
if(opt.flags & OPT_SPEED && rhash_data.processed > 0) {
double time = timer_stop(&timer);
double time = rhash_timer_stop(&timer);
print_time_stats(time, rhash_data.total_size, 1);
}
......
; The RHash config file config
; crc32 is default sum
; crc32 is the default hash sum
#crc32=on
#md5=on
#sha1=on
......
......@@ -15,7 +15,7 @@
*/
static void file_mask_add(file_mask_array* arr, const char* mask)
{
vector_add_ptr(arr, str_tolower(mask));
rsh_vector_add_ptr(arr, str_tolower(mask));
}
/**
......
......@@ -11,8 +11,8 @@ extern "C" {
/* an array to store rules for file acceptance */
typedef struct vector_t file_mask_array;
#define file_mask_new vector_new_simple
#define file_mask_free(array) vector_free(array);
#define file_mask_new rsh_vector_new_simple
#define file_mask_free(array) rsh_vector_free(array);
file_mask_array* file_mask_new_from_list(const char* comma_separated_list);
void file_mask_add_list(file_mask_array*, const char* comma_separated_list);
......
......@@ -67,7 +67,7 @@ int file_item_set_filepath(file_item* item, const char* filepath)
/* Note: strcasecmp() is not used instead of search_filepath due to portability issue */
/* Note: item->search_filepath is always correctly freed by file_item_free() */
item->search_filepath = (opt.flags&OPT_IGNORE_CASE ? str_tolower(item->filepath) : item->filepath);
item->hash = get_crc32_str(0, item->search_filepath);
item->hash = rhash_get_crc32_str(0, item->search_filepath);
return 1;
}
......@@ -128,7 +128,7 @@ file_item* file_set_find(file_set *set, const char* filepath)
( opt.flags&OPT_IGNORE_CASE ? str_tolower(filepath) : (char*)filepath );
/* generate hash to speedup the search */
hash = get_crc32_str(0, search_filepath);
hash = rhash_get_crc32_str(0, search_filepath);
/* fast binary search */
for(a = -1, b = set->size; (a + 1) < b;) {
......@@ -267,9 +267,9 @@ static void put_hash_sum(struct rhash_sums_t* sums, const char* str, unsigned ha
/* parse hexadecimal or base32 formated hash sum */
if( (int)length == len ) {
hex_to_byte(str, psum, (int)length);
rhash_hex_to_byte(str, psum, (int)length);
} else {
base32tobyte(str, psum, (int)length);
rhash_base32_to_byte(str, psum, (int)length);
}
}
......
......@@ -25,10 +25,10 @@ file_item* file_item_new(const char* filepath);
void file_item_free(file_item *item);
int file_item_set_filepath(file_item* item, const char* filepath);
#define file_set_new() vector_new((void(*)(void*))file_item_free) /* allocate new file set */
#define file_set_free(set) vector_free(set); /* free memory */
#define file_set_new() rsh_vector_new((void(*)(void*))file_item_free) /* allocate new file set */
#define file_set_free(set) rsh_vector_free(set); /* free memory */
#define file_set_get(set, index) ((file_item*)((set)->array[i])) /* get i-th element */
#define file_set_add(set, item) vector_add_ptr(set, item) /* add a file_item to file_set */
#define file_set_add(set, item) rsh_vector_add_ptr(set, item) /* add a file_item to file_set */
void file_set_add_name(file_set *set, const char* filename);
void file_set_sort(file_set *set);
......
......@@ -34,11 +34,11 @@
typedef struct dir_entry
{
struct dir_entry *next;
char* filename;
/*unsigned short level; nesting level */
unsigned type; /* dir,link, e.t.c. */
/*bool operator < (struct dir_entry &right) { return (name < right.name); }*/
struct dir_entry *next;
char* filename;
/*unsigned short level; nesting level */
unsigned type; /* dir,link, e.t.c. */
/*bool operator < (struct dir_entry &right) { return (name < right.name); }*/
} dir_entry;
/**
......@@ -51,20 +51,20 @@ typedef struct dir_entry
*/
static dir_entry* dir_entry_new(dir_entry *next, char* filename, unsigned type)
{
dir_entry* e = (dir_entry*)malloc(sizeof(dir_entry));
if(!e) return NULL;
if(filename) {
e->filename = rsh_strdup(filename);
if(!e->filename) {
free(e);
return NULL;
}
} else {
e->filename = NULL;
}
e->next = next;
e->type = type;
return e;
dir_entry* e = (dir_entry*)malloc(sizeof(dir_entry));
if(!e) return NULL;
if(filename) {
e->filename = rsh_strdup(filename);
if(!e->filename) {
free(e);
return NULL;
}
} else {
e->filename = NULL;
}
e->next = next;
e->type = type;
return e;
}
/**
......@@ -77,9 +77,9 @@ static dir_entry* dir_entry_new(dir_entry *next, char* filename, unsigned type)
*/
static dir_entry* dir_entry_insert(dir_entry **at, char* filename, unsigned type)
{
dir_entry* e = dir_entry_new(*at, filename, type);
if(e) *at = e;
return e;
dir_entry* e = dir_entry_new(*at, filename, type);
if(e) *at = e;
return e;
}
/**
......@@ -89,8 +89,8 @@ static dir_entry* dir_entry_insert(dir_entry **at, char* filename, unsigned type
*/
static void dir_entry_free(dir_entry* e)
{
free(e->filename);
free(e);
free(e->filename);
free(e);
}
/**
......@@ -98,8 +98,8 @@ static void dir_entry_free(dir_entry* e)
*/
typedef struct dir_iterator
{
int left;
char* prev_dir;
int left;
char* prev_dir;
} dir_iterator;
#define MAX_DIRS_DEPTH 64
......@@ -115,125 +115,113 @@ int find_file(const char* start_dir,
int (*call_back)(const char* filepath, int type, void* data),
int options, int max_depth, void* call_back_data)
{
dir_entry *dirs_stack = NULL; /* root of the dir_list */
dir_iterator* it;
int level = 1;
dir_entry* entry;
struct rsh_stat_struct st;
if(max_depth < 0 || max_depth >= MAX_DIRS_DEPTH) {
max_depth = MAX_DIRS_DEPTH;
}
/* skip the directory if max_depth == 0 */
if(max_depth == 0) {
return 0;
}
/* check that start_dir is a drectory */
if(rsh_stat(start_dir, &st) < 0) {
return -1; /* errno is already set by stat */
}
if( !S_ISDIR(st.st_mode) ) {
errno = ENOTDIR;
return -1;
}
/*#ifdef _WIN32
const char* cur_dirpath;
if( options&FIND_CHDIR ) {
cur_dirpath = getcwd(NULL, 2);
}
#else
int root_fd;
if( options&FIND_CHDIR ) {
root_fd = open(".");
}
#endif*/
dir_entry *dirs_stack = NULL; /* root of the dir_list */
dir_iterator* it;
int level = 1;
dir_entry* entry;
struct rsh_stat_struct st;
if(max_depth < 0 || max_depth >= MAX_DIRS_DEPTH) {
max_depth = MAX_DIRS_DEPTH;
}
/* skip the directory if max_depth == 0 */
if(max_depth == 0) {
return 0;
}
/* check that start_dir is a drectory */
if(rsh_stat(start_dir, &st) < 0) {
return -1; /* errno is already set by stat */
}
if( !S_ISDIR(st.st_mode) ) {
errno = ENOTDIR;
return -1;
}
/* check if we should descend into the root directory */
if