Beispiel #1
0
/**
 * 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++;

	if (dir_path[0] == '.' && dir_path[1] == 0) {
		/* do not extend filename for dir_path="." */
		return rsh_strdup(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;
}
Beispiel #2
0
/**
 * Allocate an empty vector.
 *
 * @param destructor pointer to the cleanup/deallocate function called
 *                   on each element when the vector is destructed,
 *                   NULL if items doesn't need to be freed
 * @return allocated vector
 */
vector_t* rsh_vector_new(void (*destructor)(void*))
{
	vector_t* ptr = (vector_t*)rsh_malloc(sizeof(vector_t));
	memset(ptr, 0, sizeof(vector_t));
	ptr->destructor = destructor;
	return ptr;
}
Beispiel #3
0
/**
 * Print EDonkey 2000 url for given file to a stream.
 *
 * @param out the stream where to print url to
 * @param filename the file name
 * @param filesize the file size
 * @param sums the file hash sums
 */
static void fprint_ed2k_url(FILE* out, struct file_info *info, int print_type)
{
	const char *filename = get_basename(file_info_get_utf8_print_path(info));
	int upper_case = (print_type & PRINT_FLAG_UPPERCASE ? RHPR_UPPERCASE : 0);
	int len = urlencode(NULL, filename) + int_len(info->size) + (info->sums_flags & RHASH_AICH ? 84 : 49);
	char* buf = (char*)rsh_malloc( len + 1 );
	char* dst = buf;

	assert(info->sums_flags & (RHASH_ED2K|RHASH_AICH));
	assert(info->rctx);

	strcpy(dst, "ed2k://|file|");
	dst += 13;
	dst += urlencode(dst, filename);
	*dst++ = '|';
	sprintI64(dst, info->size, 0);
	dst += strlen(dst);
	*dst++ = '|';
	rhash_print(dst, info->rctx, RHASH_ED2K, upper_case);
	dst += 32;
	if((info->sums_flags & RHASH_AICH) != 0) {
		strcpy(dst, "|h=");
		rhash_print(dst += 3, info->rctx, RHASH_AICH, RHPR_BASE32 | upper_case);
		dst += 32;
	}
	strcpy(dst, "|/");
	fprintf(out, "%s", buf);
	free(buf);
}
Beispiel #4
0
/**
 * Concatenate directory path with filename, unicode version.
 *
 * @param dir_path directory path
 * @param dir_len length of directory path in characters
 * @param filename the file name to append to the directory
 * @return concatenated path
 */
wchar_t* make_pathw(const wchar_t* dir_path, size_t dir_len, wchar_t* filename)
{
	wchar_t* res;
	size_t len;

	if(dir_path == 0) dir_len = 0;
	else {
		/* remove leading path separators from filename */
		while(IS_PATH_SEPARATOR_W(*filename)) filename++;

		if(dir_len == (size_t)-1) dir_len = wcslen(dir_path);
	}
	len = wcslen(filename);

	res = (wchar_t*)rsh_malloc((dir_len + len + 2) * sizeof(wchar_t));
	if(dir_len > 0) {
		memcpy(res, dir_path, dir_len * sizeof(wchar_t));
		if(res[dir_len - 1] != (wchar_t)SYS_PATH_SEPARATOR) {
			/* append path separator to the directory */
			res[dir_len++] = (wchar_t)SYS_PATH_SEPARATOR;
		}
	}

	/* append filename */
	memcpy(res + dir_len, filename, (len + 1) * sizeof(wchar_t));
	return res;
}
/**
 * Convert a c-string to wide character string using given codepage
 *
 * @param str the string to convert
 * @param codepage the codepage to use
 * @return converted string on success, NULL on fail
 */
static wchar_t* cstr_to_wchar(const char* str, int codepage)
{
	wchar_t* buf;
	int size = MultiByteToWideChar(codepage, MB_ERR_INVALID_CHARS, str, -1, NULL, 0);
	if(size == 0) return NULL; /* conversion failed */

	buf = (wchar_t*)rsh_malloc(size * sizeof(wchar_t));
	MultiByteToWideChar(codepage, 0, str, -1, buf, size);
	return buf;
}
Beispiel #6
0
/**
 * Allocate new print_item.
 *
 * @param flags the print_item flags
 * @param hash_id optional hash_id
 * @param data optional string to store
 * @return allocated print_item
 */
static print_item* new_print_item(unsigned flags, unsigned hash_id, const char *data)
{
	print_item* item = (print_item*)rsh_malloc(sizeof(print_item));
	item->flags = flags;
	item->hash_id = hash_id;
	item->width = 0;
	item->data = (data ? rsh_strdup(data) : NULL);
	item->next = NULL;
	return item;
}
Beispiel #7
0
/**
 * Concatenates two strings and returns allocated buffer with result.
 *
 * @param orig original string
 * @param append the string to append
 * @return the buffer
 */
char* str_append(const char* orig, const char* append)
{
	size_t len1 = strlen(orig);
	size_t len2 = strlen(append);
	char* res = (char*)rsh_malloc(len1 + len2 + 1);

	/* concatenate two strings */
	memcpy(res, orig, len1);
	memcpy(res + len1, append, len2 + 1);
	return res;
}
Beispiel #8
0
/**
 * Output aligned uint64_t number to specified output stream.
 *
 * @param out the stream to output to
 * @param filesize the 64-bit integer to output, usually a file size
 * @param width minimal width of integer to output
 * @param flag =1 if the integer shall be prepent by zeros
 */
static void fprintI64(FILE* out, uint64_t filesize, int width, int zero_pad)
{
	char *buf = (char*)rsh_malloc(width > 40 ? width + 1 : 41);
	int len = int_len(filesize);
	sprintI64(buf, filesize, width);
	if(len < width && zero_pad) {
		memset(buf, '0', width-len);
	}
	fprintf(out, "%s", buf);
	free(buf);
}
Beispiel #9
0
/**
 * Find long option info, by it's name and retrieve its parameter if required.
 * Error is reported for unknown options.
 *
 * @param option structure to receive the parsed option info
 * @param parg pointer to a command line argument
 */
static void parse_long_option(parsed_option_t* option, rsh_tchar ***parg)
{
	size_t length;
	rsh_tchar* eq_sign;
	cmdline_opt_t *t;
	char* name;

#ifdef _WIN32
	rsh_tchar* wname = **parg; /* "--<option name>" */
	int fail = 0;
	assert((**parg)[0] == L'-' && (**parg)[1] == L'-');

	/* search for the '=' sign */
	length = ((eq_sign = wcschr(wname, L'=')) ? (size_t)(eq_sign - wname) : wcslen(wname));
	option->name = name = (char*)rsh_malloc(length + 1);
	rsh_vector_add_ptr(opt.mem, name);
	if(length < 30) {
		size_t i = 0;
		for(; i < length; i++) {
			if(((unsigned)wname[i]) <= 128) name[i] = (char)wname[i];
			else {
				fail = 1;
				break;
			}
		}
		name[i] = '\0';
		
		name += 2; /* skip  "--" */
		length -= 2;
	} else fail = 1;

	if(fail) fail_on_unknow_option(w2c(**parg));
#else
	option->name = **parg;
	name =  **parg + 2; /* skip "--" */
	length = ((eq_sign = strchr(name, '=')) ? (size_t)(eq_sign - name) : strlen(name));
	name[length] = '\0';
#endif
	/* search for the option by its name */
	for(t = cmdline_opt; t->type && (strncmp(name, t->long_name, length) != 0 ||
		strlen(t->long_name) != length); t++) {
	}
	if(!t->type) {
		fail_on_unknow_option(option->name); /* report error and exit */
	}

	option->o = t; /* store the option found */
	if(is_param_required(t->type)) {
		/* store parameter without a code page conversion */
		option->parameter = (eq_sign ? eq_sign + 1 : *(++(*parg)));
	}
}
Beispiel #10
0
/**
 * Parse format string.
 *
 * @return a print_item list with parsed information
 */
print_item* parse_print_string(const char* format, unsigned *sum_mask)
{
	char *buf, *p;
	print_item *list = NULL, **tail, *item = NULL;

	buf = p = (char*)rsh_malloc( strlen(format) + 1 );
	tail = &list;
	*sum_mask = 0;

	for(;;) {
		while(*format && *format != '%' && *format != '\\')
			*(p++) = *(format++);

		if(*format == '\\') {
			if(*(++format) == '0') {
				item = new_print_item(PRINT_ZERO, 0, NULL);
				format++;
			} else {
				*p++ = parse_escaped_char(&format);
				continue;
			}
		} else if(*format == '%') {
			if( *(++format) == '%' ) {
				*(p++) = *format++;
				continue;
			} else {
				item = parse_percent_item(&format);
				if(!item) {
					*(p++) = '%';
					continue;
				}
				if(item->hash_id)
					*sum_mask |= item->hash_id;
			}
		}
		if(p > buf || (!*format && list == NULL && item == NULL)) {
			*p = '\0';
			*tail = new_print_item(PRINT_STR, 0, buf);
			tail = &(*tail)->next;
			p = buf;
		}
		if(item) {
			*tail = item;
			tail = &item->next;
			item = NULL;
		}
		if(!*format)
			break;
	};
	free(buf);
	return list;
}
Beispiel #11
0
/**
 * Allocate a file_set_item structure and initialize it with a filepath.
 *
 * @param filepath a filepath to initialize the file_set_item
 * @return allocated file_set_item structure
 */
static file_set_item* file_set_item_new(const char* filepath)
{
	file_set_item *item = (file_set_item*)rsh_malloc(sizeof(file_set_item));
	memset(item, 0, sizeof(file_set_item));

	if(filepath) {
		if(!file_set_item_set_filepath(item, filepath)) {
			free(item);
			return NULL;
		}
	}
	return item;
}
Beispiel #12
0
/**
 * Add a file info into the batch of files of given torrent.
 *
 * @param ctx torrent algorithm context
 * @param path file path
 * @param size file size
 */
void torrent_add_file(torrent_ctx *ctx, const char* path, uint64_t filesize)
{
  size_t len = strlen(path);
  file_n_size_info* info = (file_n_size_info*)rsh_malloc(sizeof(uint64_t) + len + 1);
  info->size = filesize;
  memcpy(info->path, path, len + 1);
  vector_add_ptr(&ctx->files, info);

  /* recalculate piece length (but only if hashing not started yet) */
  if(ctx->blocks_hashes.size == 0 && ctx->index == 0) {
    /* note: in case of batch of files should use a total batch size */
    ctx->piece_length = torrent_default_piece_length(filesize);
  }
}
Beispiel #13
0
/**
 * 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(".");
	}
}
Beispiel #14
0
/**
 * Convert a wide character string to c-string using given codepage.
 * Optionally set a flag if conversion failed.
 *
 * @param wstr the wide string to convert
 * @param codepage the codepage to use
 * @param failed pointer to the flag, to on failed conversion, can be NULL
 * @return converted string on success, NULL on fail
 */
char* wchar_to_cstr(const wchar_t* wstr, int codepage, int* failed)
{
	int size;
	char *buf;
	BOOL bUsedDefChar, *lpUsedDefaultChar;
	if(codepage == -1) {
		codepage = (opt.flags & OPT_UTF8 ? CP_UTF8 : (opt.flags & OPT_OEM) ? CP_OEMCP : CP_ACP);
	}
	/* note: lpUsedDefaultChar must be NULL for CP_UTF8, otrherwise WideCharToMultiByte() will fail */
	lpUsedDefaultChar = (failed && codepage != CP_UTF8 ? &bUsedDefChar : NULL);

	size = WideCharToMultiByte(codepage, 0, wstr, -1, 0, 0, 0, 0);
	if(size == 0) return NULL; /* conversion failed */
	buf = (char*)rsh_malloc(size);
	WideCharToMultiByte(codepage, 0, wstr, -1, buf, size, 0, lpUsedDefaultChar);
	if(failed) *failed = (lpUsedDefaultChar && *lpUsedDefaultChar);
	return buf;
}
Beispiel #15
0
/**
 * Open a directory for reading its content.
 * For simplicity the function supposes that dir_path points to an
 * existing directory and doesn't check for this error.
 * The Unicode version of the function.
 *
 * @param dir_path directory path
 * @return pointer to directory iterator
 */
WIN_DIR* win_wopendir(const wchar_t* dir_path)
{
	WIN_DIR* d;

	/* append '\*' to the dir_path */
	wchar_t *wpath = make_pathw(dir_path, (size_t)-1, L"*");
	d = (WIN_DIR*)rsh_malloc(sizeof(WIN_DIR));

	d->hFind = FindFirstFileW(wpath, &d->findFileData);
	free(wpath);
	if(d->hFind == INVALID_HANDLE_VALUE && GetLastError() == ERROR_ACCESS_DENIED) {
		free(d);
		errno = EACCES;
		return NULL;
	}

	/* note: we suppose if INVALID_HANDLE_VALUE was returned, then the file listing is empty */
	d->state = (d->hFind == INVALID_HANDLE_VALUE ? -1 : 0);
	d->dir.d_name = NULL;
	return d;
}
Beispiel #16
0
/**
 * 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;
}
Beispiel #17
0
/**
 * Check hash sums in a hash file.
 * Lines beginning with ';' and '#' are ignored.
 *
 * @param hash_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 fail
 */
int check_hash_file(file_t* file, int chdir)
{
	FILE *fd;
	char buf[2048];
	size_t pos;
	const char *ralign;
	timedelta_t timer;
	struct file_info info;
	const char* hash_file_path = file->path;
	int res = 0, line_num = 0;
	double time;

	/* process --check-embedded option */
	if(opt.mode & MODE_CHECK_EMBEDDED) {
		unsigned crc32_be;
		if(find_embedded_crc32(hash_file_path, &crc32_be)) {
			/* initialize file_info structure */
			memset(&info, 0, sizeof(info));
			info.full_path = rsh_strdup(hash_file_path);
			info.file = file;
			file_info_set_print_path(&info, info.full_path);
			info.sums_flags = info.hc.hash_mask = RHASH_CRC32;
			info.hc.flags = HC_HAS_EMBCRC32;
			info.hc.embedded_crc32_be = crc32_be;

			res = verify_sums(&info);
			fflush(rhash_data.out);
			if(!rhash_data.interrupted) {
				if(res == 0) rhash_data.ok++;
				else if(res == -1 && errno == ENOENT) rhash_data.miss++;
				rhash_data.processed++;
			}

			free(info.full_path);
			file_info_destroy(&info);
		} else {
			log_warning(_("file name doesn't contain a CRC32: %s\n"), hash_file_path);
			return -1;
		}
		return 0;
	}

	/* initialize statistics */
	rhash_data.processed = rhash_data.ok = rhash_data.miss = 0;
	rhash_data.total_size = 0;

	if(file->mode & FILE_IFSTDIN) {
		fd = stdin;
		hash_file_path = "<stdin>";
	} else if( !(fd = rsh_fopen_bin(hash_file_path, "rb") )) {
		log_file_error(hash_file_path);
		return -1;
	}

	pos = strlen(hash_file_path)+16;
	ralign = str_set(buf, '-', (pos < 80 ? 80 - (int)pos : 2));
	fprintf(rhash_data.out, _("\n--( Verifying %s )%s\n"), hash_file_path, ralign);
	fflush(rhash_data.out);
	rhash_timer_start(&timer);

	/* mark the directory part of the path, by setting the pos index */
	if(chdir) {
		pos = strlen(hash_file_path);
		for(; pos > 0 && !IS_PATH_SEPARATOR(hash_file_path[pos]); pos--);
		if(IS_PATH_SEPARATOR(hash_file_path[pos])) pos++;
	} else pos = 0;

	/* read crc file line by line */
	for(line_num = 0; fgets(buf, 2048, fd); line_num++)
	{
		char* line = buf;
		char* path_without_ext = NULL;

		/* skip unicode BOM */
		if(line_num == 0 && buf[0] == (char)0xEF && buf[1] == (char)0xBB && buf[2] == (char)0xBF) line += 3;

		if(*line == 0) continue; /* skip empty lines */

		if(is_binary_string(line)) {
			log_error(_("file is binary: %s\n"), hash_file_path);
			if(fd != stdin) fclose(fd);
			return -1;
		}

		/* skip comments and empty lines */
		if(IS_COMMENT(*line) || *line == '\r' || *line == '\n') continue;

		memset(&info, 0, sizeof(info));

		if(!hash_check_parse_line(line, &info.hc, !feof(fd))) continue;
		if(info.hc.hash_mask == 0) continue;

		info.print_path = info.hc.file_path;
		info.sums_flags = info.hc.hash_mask;

		/* see if crc file contains a hash sum without a filename */
		if(info.print_path == NULL) {
			char* point;
			path_without_ext = rsh_strdup(hash_file_path);
			point = strrchr(path_without_ext, '.');

			if(point) {
				*point = '\0';
				file_info_set_print_path(&info, path_without_ext);
			}
		}

		if(info.print_path != NULL) {
			file_t file_to_check;
			int is_absolute = IS_PATH_SEPARATOR(info.print_path[0]);
			IF_WINDOWS(is_absolute = is_absolute || (info.print_path[0] && info.print_path[1] == ':'));

			/* if filename shall be prepended by a directory path */
			if(pos && !is_absolute) {
				size_t len = strlen(info.print_path);
				info.full_path = (char*)rsh_malloc(pos + len + 1);
				memcpy(info.full_path, hash_file_path, pos);
				strcpy(info.full_path + pos, info.print_path);
			} else {
				info.full_path = rsh_strdup(info.print_path);
			}
			memset(&file_to_check, 0, sizeof(file_t));
			file_to_check.path = info.full_path;
			rsh_file_stat(&file_to_check);
			info.file = &file_to_check;

			/* verify hash sums of the file */
			res = verify_sums(&info);

			fflush(rhash_data.out);
			rsh_file_cleanup(&file_to_check);
			file_info_destroy(&info);

			if(rhash_data.interrupted) {
				free(path_without_ext);
				break;
			}

			/* update statistics */
			if(res == 0) rhash_data.ok++;
			else if(res == -1 && errno == ENOENT) rhash_data.miss++;
			rhash_data.processed++;
		}
		free(path_without_ext);
	}
	time = rhash_timer_stop(&timer);

	fprintf(rhash_data.out, "%s\n", str_set(buf, '-', 80));
	print_check_stats();

	if(rhash_data.processed != rhash_data.ok) rhash_data.error_flag = 1;

	if(opt.flags & OPT_SPEED && rhash_data.processed > 1) {
		print_time_stats(time, rhash_data.total_size, 1);
	}

	rhash_data.processed = 0;
	res = ferror(fd); /* check that crc file has been read without errors */
	if(fd != stdin) fclose(fd);
	return (res == 0 ? 0 : -1);
}
Beispiel #18
0
/**
 * Rename given file inserting its crc32 sum enclosed into square braces
 * and placing it right before the file extension.
 *
 * @param info pointer to the data of the file to rename.
 * @return 0 on success, -1 on fail with error code in errno
 */
int rename_file_by_embeding_crc32(struct file_info *info)
{
	size_t len = strlen(info->full_path);
	const char* p = info->full_path + len;
	const char* c = p - 1;
	char* new_path;
	char* insertion_point;
	unsigned crc32_be;
	assert((info->rctx->hash_id & RHASH_CRC32) != 0);

	/* check if the filename contains a CRC32 hash sum */
	if(find_embedded_crc32(info->print_path, &crc32_be)) {
		unsigned char* c =
			(unsigned char*)rhash_get_context_ptr(info->rctx, RHASH_CRC32);
		unsigned actual_crc32 = ((unsigned)c[0] << 24) |
			((unsigned)c[1] << 16) | ((unsigned)c[2] << 8) | (unsigned)c[3];

		/* compare with calculated CRC32 */
		if(crc32_be != actual_crc32) {
			char crc32_str[9];
			rhash_print(crc32_str, info->rctx, RHASH_CRC32, RHPR_UPPERCASE);
			/* TRANSLATORS: sample filename with embedded CRC32: file_[A1B2C3D4].mkv */
			log_warning(_("wrong embedded CRC32, should be %s\n"), crc32_str);
		} else return 0;
	}

	/* find file extension (as the place to insert the hash sum) */
	for(; c >= info->full_path && !IS_PATH_SEPARATOR(*c); c--) {
		if(*c == '.') {
			p = c;
			break;
		}
	}

	/* now p is the point to insert delimiter + hash string in brackets */
	new_path = (char*)rsh_malloc(len + 12);
	insertion_point = new_path + (p - info->full_path);
	memcpy(new_path, info->full_path, p - info->full_path);
	if(opt.embed_crc_delimiter && *opt.embed_crc_delimiter) *(insertion_point++) = *opt.embed_crc_delimiter;
	rhash_print(insertion_point+1, info->rctx, RHASH_CRC32, RHPR_UPPERCASE);
	insertion_point[0] = '[';
	insertion_point[9] = ']'; /* ']' overrides '\0' inserted by rhash_print_sum() */
	strcpy(insertion_point + 10, p); /* append file extension */

	/* rename the file */
	if(rename(info->full_path, new_path) < 0) {
		log_error(_("can't move %s to %s: %s\n"), info->full_path, new_path,
			strerror(errno));
		free(new_path);
		return -1;
	}

	/* change file name in the file info structure */
	if(info->print_path >= info->full_path && info->print_path < p) {
		file_info_set_print_path(info, new_path + len - strlen(info->print_path));
	} else {
		file_info_set_print_path(info, new_path);
	}

	free(info->full_path);
	info->full_path = new_path;
	return 0;
}
Beispiel #19
0
/**
 * Parse command line arguments.
 *
 * @param cmd_line structure to store parsed options data
 */
static void parse_cmdline_options(struct parsed_cmd_line_t* cmd_line)
{
	int argc;
	int n_files = 0, b_opt_end = 0;
	rsh_tchar** files;
	rsh_tchar **parg, **end_arg;
	parsed_option_t *next_opt;

#ifdef _WIN32
	parg = cmd_line->warg = CommandLineToArgvW(GetCommandLineW(), &argc);
	if( NULL == parg || argc < 1) {
		die(_("CommandLineToArgvW failed\n"));
	}
#else
	argc = cmd_line->argc;
	parg = cmd_line->argv;
#endif

	/* allocate array for files */
	files = (rsh_tchar**)rsh_malloc(argc * sizeof(rsh_tchar*));
	end_arg = parg + argc;

	/* loop by program arguments */
	for(parg++; parg < end_arg; parg++)
	{
		/* if argument is not an option */
		if((*parg)[0] != RSH_T('-') || (*parg)[1] == 0 || b_opt_end) {
			/* it's a file, note that '-' is interpreted as stdin */
			files[n_files++] = *parg;
			continue;
		}

		assert((*parg)[0] == RSH_T('-') && (*parg)[1] != 0);
		
		if((*parg)[1] == L'-' && (*parg)[2] == 0) {
			b_opt_end = 1; /* string "--" means end of options */
			continue;
		}

		/* check for "--" */
		if((*parg)[1] == RSH_T('-')) {
			cmdline_opt_t *t;

			/* allocate parsed_option */
			rsh_blocks_vector_add_empty(&cmd_line->options, 16, sizeof(parsed_option_t));
			next_opt = rsh_blocks_vector_get_item(&cmd_line->options, cmd_line->options.size - 1, 16, parsed_option_t);

			/* find the long option */
			parse_long_option(next_opt, &parg);
			t = next_opt->o;

			/* process encoding and -o/-l options early */
			if(is_output_modifier(t->type)) {
				apply_option(&opt, next_opt);
			}
		} else if((*parg)[1] != 0) {
			/* found '-'<some string> */
			rsh_tchar* ptr;
			
			/* parse short options. A string of several characters is interpreted
			 * as separate short options */
			for(ptr = *parg + 1; *ptr; ptr++) {
				cmdline_opt_t *t;
				char ch = (char)*ptr;

#ifdef _WIN32
				if(((unsigned)*ptr) >= 128) {
					ptr[1] = 0;
					fail_on_unknow_option(w2c(ptr));
				}
#endif
				/* allocate parsed_option */
				rsh_blocks_vector_add_empty(&cmd_line->options, 16, sizeof(parsed_option_t));
				next_opt = rsh_blocks_vector_get_item(&cmd_line->options, cmd_line->options.size - 1, 16, parsed_option_t);

				next_opt->buf[0] = '-', next_opt->buf[1] = ch, next_opt->buf[2] = '\0';
				next_opt->name = next_opt->buf;
				next_opt->parameter = NULL;
				
				/* search for the short option */
				for(t = cmdline_opt; t->type && ch != t->short1 && ch != t->short2; t++);
				if(!t->type) fail_on_unknow_option(next_opt->buf);
				next_opt->o = t;
				if(is_param_required(t->type)) {
					next_opt->parameter = (ptr[1] ? ptr + 1 : *(++parg));
					if(!next_opt->parameter) {
						/* note: need to check for parameter here, for early -o/-l options processing */
						log_error(_("argument is required for option %s\n"), next_opt->name);
						rsh_exit(2);
					}
				}

				/* process encoding and -o/-l options early */
				if(is_output_modifier(t->type)) {
					apply_option(&opt, next_opt);
				}
				if(next_opt->parameter) break;  /* a parameter ends the short options string */
			}
		}

	} /* for */

	cmd_line->n_files = n_files;
	cmd_line->files = files;
}
Beispiel #20
0
/**
 * Print formated file information to given output stream.
 *
 * @param out the stream to print information to
 * @param list the format according to which information shall be printed
 * @param info the file information
 */
void print_line(FILE* out, print_item* list, struct file_info *info)
{
	const char* basename = get_basename(info->print_path), *tmp;
	char *url = NULL, *ed2k_url = NULL;
	char buffer[130];

	for(; list; list = list->next) {
		int print_type = list->flags & ~(PRINT_FLAGS_ALL);
		size_t len;

		/* output a hash function digest */
		if(list->hash_id && print_type != PRINT_ED2K_LINK) {
			unsigned hash_id = list->hash_id;
			int print_flags = (list->flags & PRINT_FLAG_UPPERCASE ? RHPR_UPPERCASE : 0)
				| (list->flags & PRINT_FLAG_RAW ? RHPR_RAW : 0)
				| (list->flags & PRINT_FLAG_BASE32 ? RHPR_BASE32 : 0)
				| (list->flags & PRINT_FLAG_BASE64 ? RHPR_BASE64 : 0)
				| (list->flags & PRINT_FLAG_HEX ? RHPR_HEX : 0);
			if((hash_id == RHASH_GOST || hash_id == RHASH_GOST_CRYPTOPRO) && (opt.flags & OPT_GOST_REVERSE))
				print_flags |= RHPR_REVERSE;

			len = rhash_print(buffer, info->rctx, hash_id, print_flags);
			assert(len < sizeof(buffer));

			/* output the hash, exit on fail */
			if(fwrite(buffer, 1, len, out) != len) break;
			continue;
		}

		/* output other special items: filepath, URL-encoded filename etc. */
		switch(print_type) {
			case PRINT_STR:
				fprintf(out, "%s", list->data);
				break;
			case PRINT_ZERO: /* the '\0' character */
				fprintf(out, "%c", 0);
				break;
			case PRINT_FILEPATH:
				fprintf(out, "%s", info->print_path);
				break;
			case PRINT_BASENAME: /* the filename without directory */
				fprintf(out, "%s", basename);
				break;
			case PRINT_URLNAME: /* URL-encoded filename */
				if(!url) {
					tmp = get_basename(file_info_get_utf8_print_path(info));
					url = (char*)rsh_malloc(urlencode(NULL, tmp) + 1);
					urlencode(url, tmp);
				}
				fprintf(out, "%s", url);
				break;
			case PRINT_MTIME: /* the last-modified tine of the filename */
				print_time(out, info->stat_buf.st_mtime);
				break;
			case PRINT_SIZE: /* file size */
				fprintI64(out, info->size, list->width, (list->flags & PRINT_FLAG_PAD_WITH_ZERO));
				break;
			case PRINT_ED2K_LINK:
				fprint_ed2k_url(out, info, list->flags);
				break;
		}
	}
	free(url);
	free(ed2k_url);
}
Beispiel #21
0
/* allocate and fill the file_search_data */
file_search_data* create_file_search_data(rsh_tchar** paths, size_t count, int max_depth)
{
	size_t i;

	file_search_data* data = (file_search_data*)rsh_malloc(sizeof(file_search_data));
	memset(data, 0, sizeof(file_search_data));
	rsh_blocks_vector_init(&data->root_files);
	data->max_depth = max_depth;

#ifdef _WIN32
	/* expand wildcards and fill the root_files */
	for (i = 0; i < count; i++)
	{
		int added = 0;
		size_t length, index;
		wchar_t* path = paths[i];
		wchar_t* p = wcschr(path, L'\0') - 1;

		/* strip trailing '\','/' symbols (if not preceded by ':') */
		for (; p > path && IS_PATH_SEPARATOR_W(*p) && p[-1] != L':'; p--) *p = 0;

		/* Expand a wildcard in the current file path and store results into data->root_files.
		 * If a wildcard is not found then just the file path is stored.
		 * NB, only wildcards in the last filename of the path are expanded. */

		length = p - path + 1;
		index = wcscspn(path, L"*?");

		if (index < length && wcscspn(path + index, L"/\\") >= (length - index))
		{
			/* a wildcard is found without a directory separator after it */
			wchar_t* parent;
			WIN32_FIND_DATAW d;
			HANDLE handle;

			/* find a directory separator before the file name */
			for (; index > 0 && !IS_PATH_SEPARATOR(path[index]); index--);
			parent = (IS_PATH_SEPARATOR(path[index]) ? path : 0);

			handle = FindFirstFileW(path, &d);
			if (INVALID_HANDLE_VALUE != handle)
			{
				do {
					file_t file;
					int failed;
					if (IS_CURRENT_OR_PARENT_DIRW(d.cFileName)) continue;

					memset(&file, 0, sizeof(file));
					file.wpath = make_pathw(parent, index + 1, d.cFileName);
					if (!file.wpath) continue;

					/* skip directories if not in recursive mode */
					if (data->max_depth == 0 && (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) continue;

					/* convert file name */
					file.path = wchar_to_cstr(file.wpath, WIN_DEFAULT_ENCODING, &failed);
					if (!failed) {
						failed = (file_statw(&file) < 0);
					}

					/* quietly skip unconvertible file names */
					if (!file.path || failed) {
						if (failed) {
							data->errors_count++;
						}
						free(file.path);
						free(file.wpath);
						continue;
					}

					/* fill the file information */
					file.mode |= FILE_IFROOT;
					add_root_file(data, &file);
					added++;
				} while (FindNextFileW(handle, &d));
				FindClose(handle);
			} else {
				/* report error on the specified wildcard */
				char * cpath = wchar_to_cstr(path, WIN_DEFAULT_ENCODING, NULL);
				set_errno_from_last_file_error();
				log_file_error(cpath);
				free(cpath);
				data->errors_count++;
			}
		}
		else
		{
			int failed;
			file_t file;
			memset(&file, 0, sizeof(file));

			/* if filepath is a dash string "-" */
			if ((path[0] == L'-' && path[1] == L'\0'))
			{
				file.mode = FILE_IFSTDIN;
				file.path = rsh_strdup("(stdin)");
			} else {
				file.path = wchar_to_cstr(path, WIN_DEFAULT_ENCODING, &failed);
				if (failed) {
					log_error(_("Can't convert the path to local encoding: %s\n"), file.path);
					free(file.path);
					data->errors_count++;
					continue;
				}
				file.wpath = path;
				if (file_statw(&file) < 0) {
					log_file_error(file.path);
					free(file.path);
					data->errors_count++;
					continue;
				}
			}

			/* mark the file as obtained from the command line */
			file.mode |= FILE_IFROOT;
			file.wpath = rsh_wcsdup(path);
			add_root_file(data, &file);
		}
	} /* for */
#else
	/* copy file paths */
	for (i = 0; i < count; i++)
	{
		file_t file;
		file_init(&file, paths[i], 0);

		if (IS_DASH_STR(file.path))
		{
			file.mode = FILE_IFSTDIN;
		}
		else if (file_stat2(&file, USE_LSTAT) < 0) {
			log_file_error(file.path);
			file_cleanup(&file);
			data->errors_count++;
			continue;
		}

		file.mode |= FILE_IFROOT;
		add_root_file(data, &file);
	}
#endif
	return data;
}