Esempio n. 1
0
/**
 * Load printf-template from file, specified by options or config.
 */
static int load_printf_template(void)
{
	FILE* fd = fopen(opt.template_file, "rb");
	char buffer[8192];
	size_t len;
	int error = 0;

	if(!fd) {
		log_file_error(opt.template_file);
		return 0;
	}

	rhash_data.template_text = rsh_str_new();

	while(!feof(fd)) {
		len = fread(buffer, 1, 8192, fd);
		/* read can return -1 on error */
		if(len == (size_t)-1) 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);
			error = 1;
		}
	}

	if(ferror(fd)) {
		log_file_error(opt.template_file);
		error = 1;
	}

	fclose(fd);
	rhash_data.printf_str = rhash_data.template_text->str;
	return !error;
}
Esempio n. 2
0
/**
 * Save torrent file to the given path.
 *
 * @param path the path to save torrent file to
 * @param rctx the context containing torrent data
 */
void save_torrent_to(const char* path, rhash_context* rctx)
{
	FILE* fd;
	struct rsh_stat_struct stat_buf;
	size_t text_len;
	char *str;

	/* get torrent file content */
	text_len = rhash_transmit(RMSG_BT_GET_TEXT, rctx, RHASH_STR2UPTR(&str), 0);
	assert(text_len != RHASH_ERROR);

	if(rsh_stat(path, &stat_buf) >= 0) {
		/* make backup copy of the existing torrent file */
		char *bak_path = str_append(path, ".bak");
		unlink(bak_path);
		rename(path, bak_path);
		free(bak_path);
	}

	/* write torrent file */
	fd = rsh_fopen_bin(path, "wb");
	if(fd && text_len == fwrite(str, 1, text_len, fd) &&
		!ferror(fd) && !fflush(fd))
	{
		log_msg(_("%s saved\n"), path);
	} else {
		log_file_error(path);
	}
	if(fd) fclose(fd);
}
Esempio n. 3
0
void process_files(const char* paths[], size_t count,
	find_file_options* opt)
{
	struct file_t file;
	size_t i;
	memset(&file, 0, sizeof(file));

	for(i = 0; i < count && !(opt->options & FIND_CANCEL); i++) {
		file.path = (char*)paths[i];

		if(!IS_DASH_STR(file.path) && rsh_file_stat2(&file, USE_LSTAT) < 0) {
			if((opt->options & FIND_LOG_ERRORS) != 0) {
				log_file_error(file.path);
				opt->errors_count++;
			}
			continue;
		}
		if(!IS_DASH_STR(file.path) && (file.mode & FILE_IFDIR) != 0) {
			find_file(&file, opt);
		} else {
			file.mode |= FILE_ISROOT;
			opt->call_back(&file, opt->call_back_data);
		}
	}

	rsh_file_cleanup(&file);
}
Esempio n. 4
0
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++)
	{
		file_t* file = get_root_file(data, i);
		assert(!!(file->mode & FILE_IFROOT));

		/* 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) {
				dir_scan(file, data);
			} else if ((data->options & FIND_LOG_ERRORS) != 0) {
				errno = EISDIR;
				log_file_error(file->path);
			}
		} else {
			/* process a regular file or a dash '-' path */
			data->call_back(file, data->call_back_data);
		}
	}
}
Esempio n. 5
0
/* Load configfile from directories
 */
int load_user_config(t_session *session) {
	char *search, *conffile;
	int length, result;

	if (session->file_on_disk == NULL) {
		return 0;
	}

	search = session->file_on_disk;
	while (*search != '\0') {
		if (*search == '/') {
			length = search - session->file_on_disk + 1;
			if ((conffile = (char*)malloc(length + 10)) == NULL) {
				return -1;
			} else {
				memcpy(conffile, session->file_on_disk, length);
				memcpy(conffile + length, ".hiawatha\0", 10);
				result = read_user_configfile(conffile, session->host, &(session->tempdata));

				if (result != 0) {
					log_file_error(session, conffile, "error in configuration file on line %d", result);
					free(conffile);
					return -1;
				}

				free(conffile);
			}
		}

		search++;
	}

	return 0;
}
Esempio n. 6
0
File: output.c Progetto: rhash/RHash
static void setup_log_stream(FILE **p_stream, const opt_tchar* stream_path)
{
	if (stream_path && !(*p_stream = rsh_tfopen(stream_path, RSH_T("w"))) ) {
		log_file_error(t2c(stream_path));
		rsh_exit(2);
	}
}
Esempio n. 7
0
/**
 * Hash, check or update files according to work mode.
 */
static void process_files(void)
{
	timedelta_t timer;
	struct rsh_stat_struct stat_buf;
	int i;
	rhash_timer_start(&timer);
	rhash_data.processed = 0;

	/* process filenames */
	for(i = 0; i < opt.n_files; i++) {
		int res = 0;
		char* filepath = opt.files[i];
		stat_buf.st_mode = 0;

		if(!IS_DASH_STR(filepath) && rsh_stat(filepath, &stat_buf) < 0) {
			log_file_error(filepath);
			continue;
		}
		if(opt.flags & OPT_RECURSIVE) {
			if(S_ISDIR(stat_buf.st_mode)) {
				find_file(filepath, find_file_callback, 0, opt.find_max_depth, NULL);
				continue;
			}
		} else {
			if(S_ISDIR(stat_buf.st_mode)){
				if(opt.flags & OPT_VERBOSE){
					log_warning(_("%s: is a directory\n"), filepath);
				}
				continue;
			}
		}

		if(opt.mode & (MODE_CHECK | MODE_CHECK_EMBEDDED)) {
			res = check_hash_file(filepath, 0);
		} else if(opt.mode & MODE_UPDATE) {
			res = update_hash_file(filepath);
		} else {
			res = calculate_and_print_sums(rhash_data.out, filepath, filepath, &stat_buf);
			rhash_data.processed++;
		}
		if(res < 0) rhash_data.error_flag = 1;
	}

	if((opt.mode & MODE_CHECK_EMBEDDED) && rhash_data.processed > 1) {
		print_check_stats();
	}

	if((opt.flags & OPT_SPEED) && !(opt.mode&(MODE_CHECK | MODE_UPDATE)) &&
		rhash_data.processed > 1) {
			double time = rhash_timer_stop(&timer);
			print_time_stats(time, rhash_data.total_size, 1);
	}
}
Esempio n. 8
0
/* Load configfile from directories
 */
int load_user_config(t_session *session) {
	char *search, *conffile;
	size_t length;
	int result;
	t_user_config_mode read_mode;

	if (session->file_on_disk == NULL) {
		return 0;
	} else if ((length = strlen(session->file_on_disk)) <= 1) {
		return 0;
	} else if ((conffile = (char*)malloc(length + 10)) == NULL) {
		return -1;
	}

	search = session->file_on_disk + 1;
	while (*search != '\0') {
		if (*search == '/') {
			length = search - session->file_on_disk + 1;

			if (length - 1 != session->host->website_root_len) {
				read_mode = non_root_config;
			} else if (memcmp(session->file_on_disk, session->host->website_root, length - 1) != 0) {
				read_mode = non_root_config;
			} else {
				read_mode = ignore_root_config;
			}

			memcpy(conffile, session->file_on_disk, length);
			memcpy(conffile + length, ".hiawatha\0", 10);
			result = read_user_configfile(conffile, session->host, &(session->tempdata), read_mode);

			if (result != 0) {
				log_file_error(session, conffile, "error in configuration file on line %d", result);
				free(conffile);
				return -1;
			}
		}

		search++;
	}

	free(conffile);

	return 0;
}
Esempio n. 9
0
int load_user_root_config(t_session *session) {
	char *conffile;
	int result;

	if ((conffile = malloc(session->host->website_root_len + 11)) == NULL) {
		return -1;
	}

	memcpy(conffile, session->host->website_root, session->host->website_root_len);
	memcpy(conffile + session->host->website_root_len, "/.hiawatha\0", 11);

	if ((result = read_user_configfile(conffile, session->host, &(session->tempdata), only_root_config)) != 0) {
		log_file_error(session, conffile, "error in configuration file on line %d", result);
		result = -1;
	}

	free(conffile);

	return result;
}
Esempio n. 10
0
/* Run a program
 */
static int run_program(t_session *session, char *program, int return_code) {
	pid_t pid;
	char ip[MAX_IP_STR_LEN], value[10], *pos, slash = '/';

	switch (pid = fork()) {
		case -1:
			log_file_error(session, program, "fork() error");
			return -1;
		case 0:
			if (setsid() == -1) {
				log_file_error(session, program, "setsid() error");
			} else {
				/* Close all other open filedescriptors.
				 */
				close_bindings(session->config->binding);
				close_client_sockets_for_cgi_run();
				close_logfiles_for_cgi_run(session->config->first_host);

				/* Set environment variables
				 */
				setenv("REQUEST_METHOD", session->method, 1);
				setenv("DOCUMENT_ROOT", session->host->website_root, 1);
				setenv("REQUEST_URI", session->request_uri, 1);
				if (session->remote_user != NULL) {
					setenv("REMOTE_USER", session->remote_user, 1);
				}
				if (inet_ntop(session->ip_address.family, &(session->ip_address.value), ip, MAX_IP_STR_LEN) != NULL) {
					setenv("REMOTE_ADDR", ip, 1);
				}
				snprintf(value, 9, "%d", return_code);
				setenv("HTTP_RETURN_CODE", value, 1);

				http_header_to_environment(session, NULL, "Range:", "HTTP_RANGE");
				http_header_to_environment(session, NULL, "Referer:", "HTTP_REFERER");
				http_header_to_environment(session, NULL, "User-Agent:", "HTTP_USER_AGENT");

				/* Change directory to program's directory
				 */
				pos = strrchr(program, slash);
#ifdef CYGWIN
				if ((pos == NULL) && (session->config->platform == windows)) {
					slash = '\\';
					pos = strrchr(program, slash);
				}
#endif
				if (pos != NULL) {
					*pos = '\0';
					if (chdir(program) == -1) {
						exit(EXIT_FAILURE);
					}
					*pos = slash;
				}

				/* Execute program
				 */
				execlp(program, program, (char*)NULL);
				log_file_error(session, program, "exec() error");
			}
			exit(EXIT_FAILURE);
		default:
			if (session->config->wait_for_cgi) {
				waitpid(pid, NULL, 0);
			}
	}

	return 0;
}
Esempio n. 11
0
/* Handle an HTTP error.
 */
static int handle_error(t_session *session, int error_code) {
	t_error_handler *error_handler;
	char *new_fod;
	int result = -1;
#ifdef ENABLE_XSLT
	char *xslt_file;
#endif

	error_handler = session->host->error_handlers;
	while (error_handler != NULL) {
		if (error_handler->code == error_code) {
			break;
		}
		error_handler = error_handler->next;
	}

	if (error_handler == NULL) {
		return 0;
	}

	session->return_code = error_code;
	session->error_code = error_code;
	session->handling_error = true;
	session->mimetype = NULL;
	session->vars = error_handler->parameters;

	if ((new_fod = (char*)malloc(session->host->website_root_len + strlen(error_handler->handler) + 4)) == NULL) { /* + 3 for .gz (gzip encoding) */
		log_error(session, "malloc() error while handling error");
		return 500;
	}

	if (session->file_on_disk != NULL) {
		free(session->file_on_disk);
	}
	session->file_on_disk = new_fod;

	memcpy(session->file_on_disk, session->host->website_root, session->host->website_root_len);
	strcpy(session->file_on_disk + session->host->website_root_len, error_handler->handler);

	if (get_target_extension(session) == -1) {
		log_error(session, "error getting extension while handing error");
		return 500;
	}
	check_target_is_cgi(session);

	if (session->cgi_type != no_cgi) {
		result = execute_cgi(session);
#ifdef ENABLE_XSLT
	} else if ((xslt_file = find_xslt_file(session)) != NULL) {
		result = handle_xml_file(session, xslt_file);
		free(xslt_file);
#endif
	} else switch (is_directory(session->file_on_disk)) {
		case error:
			result = 500;
			break;
		case yes:
			result = 301;
			break;
		case no:
			result = send_file(session);
			break;
		case no_access:
			result = 403;
			break;
		case not_found:
			result = 404;
			break;
	}

	switch (result) {
		case 301:
			log_error(session, "ErrorHandler is a directory");
			break;
		case 403:
			log_error(session, "no access to ErrorHandler");
			break;
		case 404:
			log_error(session, "ErrorHandler not found");
			break;
		case 500:
			log_file_error(session, error_handler->handler, "internal error for ErrorHandler");
			session->keep_alive = false;
			break;
		case 503:
			log_file_error(session, error_handler->handler, "FastCGI for ErrorHandler not available");
			break;
	}

	return result;
}
Esempio n. 12
0
File: output.c Progetto: rhash/RHash
/**
 * Print file error to the program log.
 *
 * @param file the file, caused the error
 */
void log_file_t_error(struct file_t* file)
{
	log_file_error(file_cpath(file));
}
Esempio n. 13
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;
}
Esempio n. 14
0
/**
 * Walk directory tree and call given callback function to process each file/directory.
 *
 * @param start_dir path to the directory to walk recursively
 * @param data the options specifying how to walk the directory tree
 * @return 0 on success, -1 on error
 */
static int dir_scan(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 = data->max_depth;
	int options = data->options;
	file_t file;

	if (max_depth < 0 || max_depth >= MAX_DIRS_DEPTH) {
		max_depth = MAX_DIRS_DEPTH - 1;
	}

	/* skip the directory if max_depth == 0 */
	if (!max_depth) return 0;

	if (!FILE_ISDIR(start_dir)) {
		errno = ENOTDIR;
		return -1;
	}

	/* check if we should descend into the root directory */
	if ((options & (FIND_WALK_DEPTH_FIRST | FIND_SKIP_DIRS)) == 0) {
		if (!data->call_back(start_dir, data->call_back_data))
			return 0;
	}

	/* allocate array of counters of directory elements */
	it = (dir_iterator*)malloc((MAX_DIRS_DEPTH + 1) * sizeof(dir_iterator));
	if (!it) {
		return -1;
	}

	/* push dummy counter for the root element */
	it[0].count = 1;
	it[0].dir_path = 0;

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

	while (!(data->options & FIND_CANCEL))
	{
		dir_entry **insert_at;
		char* dir_path;
		DIR *dp;
		struct dirent *de;

		/* climb down from the tree */
		while (--it[level].count < 0) {
			/* do not need this dir_path anymore */
			free(it[level].dir_path);

			if (--level < 0) {
				/* walked the whole tree */
				assert(!dirs_stack);
				free(it);
				return 0;
			}
		}
		assert(level >= 0 && it[level].count >= 0);

		/* take a filename from dirs_stack and construct the next path */
		if (level) {
			assert(dirs_stack != NULL);
			dir_path = make_path(it[level].dir_path, dirs_stack->filename);
			dir_entry_drop_head(&dirs_stack);
		} else {
			/* the first cycle: start from a root directory */
			dir_path = rsh_strdup(start_dir->path);
		}

		if (!dir_path) continue;

		/* fill the next level of directories */
		level++;
		assert(level < MAX_DIRS_DEPTH);
		it[level].count = 0;
		it[level].dir_path = dir_path;

		if ((options & (FIND_WALK_DEPTH_FIRST | FIND_SKIP_DIRS)) == FIND_WALK_DEPTH_FIRST)
		{
			int res;
			file_init(&file, dir_path, 1);
			res = file_stat2(&file, USE_LSTAT);

			/* check if we should skip the directory */
			if (res < 0 || !data->call_back(&file, data->call_back_data)) {
				if (res < 0 && (options & FIND_LOG_ERRORS)) {
					data->errors_count++;
				}
				file_cleanup(&file);
				continue;
			}
		}
		file_cleanup(&file);

		/* step into directory */
		dp = opendir(dir_path);
		if (!dp) continue;

		insert_at = &dirs_stack;

		while ((de = readdir(dp)) != NULL)
		{
			int res;

			/* skip the "." and ".." directories */
			if (IS_CURRENT_OR_PARENT_DIR(de->d_name)) continue;

			file.mode = 0;
			file.path = make_path(dir_path, de->d_name);
			if (!file.path) continue;

			res  = file_stat2(&file, USE_LSTAT);
			if (res >= 0) {
				/* process the file or directory */
				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 = 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 &&
					((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].count++;
					}
				}
			} else if (options & FIND_LOG_ERRORS) {
				/* report error only if FIND_LOG_ERRORS option is set */
				log_file_error(file.path);
				data->errors_count++;
			}
			file_cleanup(&file);
		}
		closedir(dp);
	}

	while (dirs_stack) {
		dir_entry_drop_head(&dirs_stack);
	}
	while (level) {
		free(it[level--].dir_path);
	}
	free(it);
	assert(file.path == 0);
	return 0;
}
Esempio n. 15
0
/**
 * 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
 */
int find_file(file_t* start_dir, find_file_options* options)
{
	dir_entry *dirs_stack = NULL; /* root of the dir_list */
	dir_iterator* it;
	int level = 1;
	int max_depth = options->max_depth;
	int flags = options->options;
	dir_entry* entry;
	file_t file;

	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;
	}

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

	if((start_dir->mode & FILE_IFDIR) == 0) {
		errno = ENOTDIR;
		return -1;
	}

	/* 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))
			return 0;
	}

	it = (dir_iterator*)malloc(MAX_DIRS_DEPTH * sizeof(dir_iterator));
	if(!it) return 0;

	/* push root directory into dirs_stack */
	it[0].left = 1;
	it[0].prev_dir = rsh_strdup(start_dir->path);
	it[1].prev_dir = NULL;
	if(!it[0].prev_dir) {
		errno = ENOMEM;
		return -1;
	}
	entry = dir_entry_insert(&dirs_stack, NULL, 0);
	if(!entry) {
		free(it[0].prev_dir);
		free(it);
		errno = ENOMEM;
		return -1;
	}

	while(!(options->options & FIND_CANCEL)) {
		dir_entry *dir, **insert_at;
		char* dir_path;
		DIR *dp;
		struct dirent *de;

		/* walk back */
		while((--level) >= 0 && it[level].left <= 0) free(it[level+1].prev_dir);
		if(level < 0) break;
		assert(dirs_stack != NULL);
		/* on the first cycle: level == 0, stack[0] == 0; */

		dir = dirs_stack; /* take last dir from the list */
		dirs_stack = dirs_stack->next; /* remove last dir from the list */
		it[level].left--;

		dir_path = (!dir->filename ? rsh_strdup(it[level].prev_dir) :
			make_path(it[level].prev_dir, dir->filename) );
		dir_entry_free(dir);
		if(!dir_path) continue;

		level++;
		it[level].left = 0;
		it[level].prev_dir = dir_path;

		if((flags & (FIND_WALK_DEPTH_FIRST | FIND_SKIP_DIRS))
			== FIND_WALK_DEPTH_FIRST) {
			rsh_file_cleanup(&file);
			file.path = dir_path;
			/* check if we should skip the directory */
			if(!options->call_back(&file, options->call_back_data))
				continue;
		}

		/* read dir */
		dp = opendir(dir_path);
		if(dp == NULL) continue;

		insert_at = &dirs_stack;

		while((de = readdir(dp)) != NULL) {
			int res;
			/* skip "." and ".." dirs */
			if(de->d_name[0] == '.' && (de->d_name[1] == 0 ||
				(de->d_name[1] == '.' && de->d_name[2] == 0 )))
				continue;

			if( !(file.path = make_path(dir_path, de->d_name)) ) continue;

			res  = rsh_file_stat2(&file, USE_LSTAT);
			/* process */
			if(res >= 0) {
				if((file.mode & FILE_IFDIR) &&
					(flags & (FIND_WALK_DEPTH_FIRST | FIND_SKIP_DIRS))) res = 1;
				else {
					/* handle file by callback function */
					res = options->call_back(&file, options->call_back_data);
				}

				/* if file is a directory and we need to walk it */
				if((file.mode & FILE_IFDIR) && res && level < max_depth) {
					/* don't go deeper if max_depth reached */

					/* add directory to dirs_stack */
					if(dir_entry_insert(insert_at, de->d_name, file.mode)) {
						/* if really added */
						insert_at = &((*insert_at)->next);
						it[level].left++;
					}
				}
			} else if (options->options & FIND_LOG_ERRORS) {
				log_file_error(file.path);
			}
			rsh_file_cleanup(&file);
			free(file.path);
		}
		closedir(dp);

		if(it[level].left > 0) level++;
	}
	assert(dirs_stack == NULL);

	free(it);
	return 0;
}
Esempio n. 16
0
/**
 * Calculate and print file hash sums using printf format.
 *
 * @param out a stream to print to
 * @param file the file to calculate sums for
 * @param print_path the path to print
 * @return 0 on success, -1 on fail
 */
int calculate_and_print_sums(FILE* out, file_t* file, const char *print_path)
{
	struct file_info info;
	timedelta_t timer;
	int res = 0;

	memset(&info, 0, sizeof(info));
	info.file = file;
	info.full_path = rsh_strdup(file->path);
	file_info_set_print_path(&info, print_path);
	info.size = 0;

	info.sums_flags = opt.sum_flags;

	if(file->mode & FILE_IFSTDIN) {
		print_path = "(stdin)";
	} else {
		if(file->mode & FILE_IFDIR) return 0; /* don't handle directories */
		info.size = file->size; /* total size, in bytes */
	}

	/* initialize percents output */
	init_percents(&info);
	rhash_timer_start(&timer);

	if(info.sums_flags) {
		/* calculate sums */
		if(calc_sums(&info) < 0) {
			/* print error unless sharing access error occurred */
			if(errno == EACCES) return 0;
			log_file_error(file->path);
			res = -1;
		}
		if(rhash_data.interrupted) {
			report_interrupted();
			return 0;
		}
	}

	info.time = rhash_timer_stop(&timer);
	finish_percents(&info, res);

	if(opt.flags & OPT_EMBED_CRC) {
		/* rename the file */
		rename_file_by_embeding_crc32(&info);
	}

	if((opt.mode & MODE_TORRENT) && !opt.bt_batch_file) {
		save_torrent(&info);
	}

	if((opt.mode & MODE_UPDATE) && opt.fmt == FMT_SFV) {
		/* updating SFV file: print SFV header line */
		print_sfv_header_line(rhash_data.upd_fd, file, 0);
		if(opt.flags & OPT_VERBOSE) {
			print_sfv_header_line(rhash_data.log, file, 0);
			fflush(rhash_data.log);
		}
		rsh_file_cleanup(file);
	}

	if(rhash_data.print_list && res >= 0) {
		if (!opt.bt_batch_file) {
			print_line(out, rhash_data.print_list, &info);
			fflush(out);

			/* print calculated line to stderr or log-file if verbose */
			if((opt.mode & MODE_UPDATE) && (opt.flags & OPT_VERBOSE)) {
				print_line(rhash_data.log, rhash_data.print_list, &info);
				fflush(rhash_data.log);
			}
		}

		if((opt.flags & OPT_SPEED) && info.sums_flags) {
			print_file_time_stats(&info);
		}
	}
	free(info.full_path);
	file_info_destroy(&info);
	return res;
}
Esempio n. 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);
}
Esempio n. 18
0
File: log.c Progetto: wdlth/hiawatha
/* Log an error
 */
void log_error(t_session *session, char *mesg) {
	log_file_error(session, session->file_on_disk, mesg);
}