Example #1
0
File: sort.c Project: sklnd/vifm
static int
compare_file_names(const char *s, const char *t, int ignore_case)
{
	char s_buf[NAME_MAX];
	char t_buf[NAME_MAX];

	snprintf(s_buf, sizeof(s_buf), "%s", s);
	chosp(s_buf);
	s = s_buf;
	snprintf(t_buf, sizeof(t_buf), "%s", t);
	chosp(t_buf);
	t = t_buf;

	if(ignore_case)
	{
		strtolower(s_buf);
		strtolower(t_buf);
	}

	if(!cfg.sort_numbers)
		return strcmp(s, t);
	else
#if defined(_WIN32) || defined(__APPLE__)
		return vercmp(s, t);
#else
		return strverscmp(s, t);
#endif
}
Example #2
0
File: path.c Project: jubalh/vifm
const char *
make_rel_path(const char path[], const char base[])
{
	static char buf[PATH_MAX];

	const char *p = path, *b = base;
	int i;
	int nslashes;

#ifdef _WIN32
	if(path[1] == ':' && base[1] == ':' && path[0] != base[0])
	{
		canonicalize_path(path, buf, sizeof(buf));
		return buf;
	}
#endif

	while(p[0] != '\0' && p[1] != '\0' && b[0] != '\0' && b[1] != '\0')
	{
		const char *op = p, *ob = b;
		if((p = strchr(p + 1, '/')) == NULL)
			p = path + strlen(path);
		if((b = strchr(b + 1, '/')) == NULL)
			b = base + strlen(base);
		if(p - path != b - base || strnoscmp(path, base, p - path) != 0)
		{
			p = op;
			b = ob;
			break;
		}
	}

	canonicalize_path(b, buf, sizeof(buf));
	chosp(buf);

	nslashes = 0;
	for(i = 0; buf[i] != '\0'; i++)
		if(buf[i] == '/')
			nslashes++;

	buf[0] = '\0';
	while(nslashes-- > 0)
		strcat(buf, "../");
	if(*p == '/')
		p++;
	canonicalize_path(p, buf + strlen(buf), sizeof(buf) - strlen(buf));
	chosp(buf);

	if(buf[0] == '\0')
		strcpy(buf, ".");

	return buf;
}
Example #3
0
File: path.c Project: jubalh/vifm
int
to_canonic_path(const char path[], char buf[], size_t buf_len)
{
	if(!is_path_absolute(path))
	{
		char cwd[PATH_MAX];
		char full_path[PATH_MAX];

		if(getcwd(cwd, sizeof(cwd)) == NULL)
		{
			/* getcwd() failed, we can't use relative path, so fail. */
			LOG_SERROR_MSG(errno, "Can't get CWD");
			return 1;
		}

		snprintf(full_path, sizeof(full_path), "%s/%s", cwd, path);
		canonicalize_path(full_path, buf, buf_len);
	}
	else
	{
		canonicalize_path(path, buf, buf_len);
	}

	chosp(buf);
	return 0;
}
Example #4
0
/* Checks whether path/file exists. If path is NULL, filename is assumed to
 * contain full path. */
static int
path_exists_internal(const char path[], const char filename[], int deref)
{
	char full[PATH_MAX];
	if(path == NULL)
	{
		copy_str(full, sizeof(full), filename);
	}
	else
	{
		snprintf(full, sizeof(full), "%s/%s", path, filename);
	}

	/* At least on Windows extra trailing slash can mess up the check, so get rid
	 * of it. */
	if(!is_root_dir(full))
	{
		chosp(full);
	}

	if(!deref)
	{
		struct stat st;
		return os_lstat(full, &st) == 0;
	}
	return os_access(full, F_OK) == 0;
}
Example #5
0
/* buf should be at least PATH_MAX characters length */
static void
parse_path(const char *dir, const char *path, char *buf)
{
	strcpy(buf, path);
#ifdef _WIN32
	to_forward_slash(buf);
#endif
	if(is_path_absolute(buf))
	{
		snprintf(buf, PATH_MAX, "%s", path);
	}
#ifdef _WIN32
	else if(buf[0] == '/')
	{
		snprintf(buf, PATH_MAX, "%c:%s", dir[0], path);
	}
#endif
	else
	{
		char new_path[PATH_MAX];
		snprintf(new_path, sizeof(new_path), "%s/%s", dir, path);
		canonicalize_path(new_path, buf, PATH_MAX);
	}
	if(!is_root_dir(buf))
		chosp(buf);

#ifdef _WIN32
	to_forward_slash(buf);
#endif
}
Example #6
0
/* Converts a path into canonic form.  Mind that canonic paths are usually not
 * longer than the original one, but can be extended in corner cases so several
 * extra bytes (e.g. 16) in the buffer are needed. */
static void
make_canonic(const char path[], char buf[], size_t buf_size)
{
	canonicalize_path(path, buf, buf_size);
	if(!is_root_dir(buf) && !ends_with_slash(path))
	{
		chosp(buf);
	}
}
Example #7
0
char *
replace_home_part(const char path[])
{
	char *result = replace_home_part_strict(path);
	if(!is_root_dir(result))
	{
		chosp(result);
	}
	return result;
}
Example #8
0
TEST(trailing_forward_slash_of_path_is_preserved, IF(windows))
{
	int line_num;
	char *path;

	strcat(test_data, "\\");

	path = parse_file_spec(test_data, &line_num, ".");

	chosp(test_data);
	strcat(test_data, "/");

	assert_string_equal(test_data, path);
	assert_int_equal(DEFAULT_LINENUM, line_num);

	free(path);

	chosp(test_data);
}
Example #9
0
/* Resolve link target and either navigate inside directory link points to or
 * navigate to directory where target is located pointing cursor on
 * it (the follow_dirs flag controls behaviour). */
static void
follow_link(FileView *view, int follow_dirs)
{
	char *dir, *file;
	char full_path[PATH_MAX];
	char linkto[PATH_MAX + NAME_MAX];
	dir_entry_t *const entry = &curr_view->dir_entry[curr_view->list_pos];

	get_full_path_of(entry, sizeof(full_path), full_path);

	if(get_link_target_abs(full_path, entry->origin, linkto, sizeof(linkto)) != 0)
	{
		show_error_msg("Error", "Can't read link.");
		return;
	}

	if(!path_exists(linkto, DEREF))
	{
		show_error_msg("Broken Link",
				"Can't access link destination.  It might be broken.");
		return;
	}

	chosp(linkto);

	if(is_dir(linkto) && !follow_dirs)
	{
		dir = strdup(entry->name);
		file = NULL;
	}
	else
	{
		dir = strdup(linkto);
		remove_last_path_component(dir);

		file = get_last_path_component(linkto);
	}

	if(dir[0] != '\0')
	{
		navigate_to(view, dir);
	}

	if(file != NULL)
	{
		const int pos = find_file_pos_in_list(view, file);
		if(pos >= 0)
		{
			flist_set_pos(view, pos);
		}
	}

	free(dir);
}
Example #10
0
/* Registers action handler for a particular combination of event and path
 * pattern.  Event name is case insensitive.  Returns zero on successful
 * registration or non-zero on error. */
static int
add_aucmd(const char event[], const char pattern[], int negated,
		const char action[], vle_aucmd_handler handler)
{
	char canonic_path[PATH_MAX];
	aucmd_info_t *autocmd;
	char *regexp;

	autocmd = DA_EXTEND(autocmds);
	if(autocmd == NULL)
	{
		return 1;
	}

	if(strchr(pattern, '/') != NULL)
	{
		canonicalize_path(pattern, canonic_path, sizeof(canonic_path));
		if(!is_root_dir(canonic_path))
		{
			chosp(canonic_path);
		}
		pattern = canonic_path;
	}

	regexp = glob_to_regex(pattern, 1);
	if(regexp == NULL)
	{
		return 1;
	}

	if(regcomp(&autocmd->regex, regexp, REG_EXTENDED | REG_ICASE) != 0)
	{
		free(regexp);
		return 1;
	}
	free(regexp);

	autocmd->event = strdup(event);
	autocmd->pattern = strdup(pattern);
	autocmd->negated = negated;
	autocmd->action = strdup(action);
	autocmd->handler = handler;
	if(autocmd->event == NULL || autocmd->pattern == NULL ||
			autocmd->action == NULL)
	{
		free_autocmd_data(autocmd);
		return 1;
	}

	DA_COMMIT(autocmds);
	/* TODO: sort by event name (case insensitive) and then by pattern? */
	return 0;
}
Example #11
0
static void
chmod_file_in_list(FileView *view, int pos, const char *mode,
		const char *inv_mode, int recurse_dirs)
{
	char *filename;
	char path_buf[PATH_MAX];

	filename = view->dir_entry[pos].name;
	snprintf(path_buf, sizeof(path_buf), "%s/%s", view->curr_dir, filename);
	chosp(path_buf);
	file_chmod(path_buf, mode, inv_mode, recurse_dirs);
}
Example #12
0
/* Implementation of :p filename modifier. */
static int
apply_p_mod(const char *path, const char *parent, char *buf, size_t buf_len)
{
	size_t len;
	if(is_path_absolute(path))
	{
		snprintf(buf, buf_len, "%s", path);
		return 0;
	}

	snprintf(buf, buf_len, "%s", parent);
	chosp(buf);
	len = strlen(buf);
	snprintf(buf + len, buf_len - len, "/%s", path);
	return 0;
}
Example #13
0
void
remove_last_path_component(char *path)
{
	char *slash;

	while(ends_with_slash(path))
	{
		chosp(path);
	}

	if((slash = strrchr(path, '/')) != NULL)
	{
		int pos = is_root_dir(path) ? 1 : 0;
		slash[pos] = '\0';
	}
}
Example #14
0
File: path.c Project: jubalh/vifm
/* Tries to expands tilde in the front of the path.  Returns the path or newly
 * allocated string without tilde. */
static char *
try_replace_tilde(const char path[])
{
#ifndef _WIN32
	char name[NAME_MAX];
	const char *p;
	char *result;
	struct passwd *pw;
#endif

	if(path[0] != '~')
	{
		return (char *)path;
	}

	if(path[1] == '\0' || path[1] == '/')
	{
		char *const result = format_str("%s%s", cfg.home_dir,
				(path[1] == '/') ? (path + 2) : "");
		return result;
	}

#ifndef _WIN32
	if((p = strchr(path, '/')) == NULL)
	{
		p = path + strlen(path);
		copy_str(name, sizeof(name), path + 1);
	}
	else
	{
		snprintf(name, p - (path + 1) + 1, "%s", path + 1);
		p++;
	}

	if((pw = getpwnam(name)) == NULL)
	{
		return (char *)path;
	}

	chosp(pw->pw_dir);
	result = format_str("%s/%s", pw->pw_dir, p);

	return result;
#else
	return (char *)path;
#endif
}
Example #15
0
File: path.c Project: jubalh/vifm
void
remove_last_path_component(char path[])
{
	char *slash;

	while(ends_with_slash(path))
	{
		chosp(path);
	}

	slash = strrchr(path, '/');
	if(slash != NULL)
	{
		const int offset = is_root_dir(path) ? 1 : 0;
		slash[offset] = '\0';
	}
}
Example #16
0
File: fs.c Project: cfillion/vifm
SymLinkType
get_symlink_type(const char path[])
{
	char cwd[PATH_MAX];
	char linkto[PATH_MAX + NAME_MAX];
	int saved_errno;
	char *filename_copy;
	char *p;

	if(get_cwd(cwd, sizeof(cwd)) == NULL)
	{
		/* getcwd() failed, just use "." rather than fail. */
		strcpy(cwd, ".");
	}

	/* Use readlink() (in get_link_target_abs) before realpath() to check for
	 * target at slow file system.  realpath() doesn't fit in this case as it
	 * resolves chains of symbolic links and we want to try only the first one. */
	if(get_link_target_abs(path, cwd, linkto, sizeof(linkto)) != 0)
	{
		LOG_SERROR_MSG(errno, "Can't readlink \"%s\"", path);
		log_cwd();
		return SLT_UNKNOWN;
	}
	if(refers_to_slower_fs(path, linkto))
	{
		return SLT_SLOW;
	}

	filename_copy = strdup(path);
	chosp(filename_copy);

	p = os_realpath(filename_copy, linkto);
	saved_errno = errno;

	free(filename_copy);

	if(p == linkto)
	{
		return is_dir(linkto) ? SLT_DIR : SLT_UNKNOWN;
	}

	LOG_SERROR_MSG(saved_errno, "Can't realpath \"%s\"", path);
	log_cwd();
	return SLT_UNKNOWN;
}
Example #17
0
File: fs.c Project: cfillion/vifm
int
is_symlink(const char path[])
{
#ifndef _WIN32
	struct stat st;
	return os_lstat(path, &st) == 0 && S_ISLNK(st.st_mode);
#else
	char filename[PATH_MAX];
	DWORD attr;
	wchar_t *utf16_filename;
	HANDLE hfind;
	WIN32_FIND_DATAW ffd;

	attr = win_get_file_attrs(path);
	if(attr == INVALID_FILE_ATTRIBUTES)
	{
		LOG_WERROR(GetLastError());
		return 0;
	}

	if(!(attr & FILE_ATTRIBUTE_REPARSE_POINT))
	{
		return 0;
	}

	copy_str(filename, sizeof(filename), path);
	chosp(filename);

	utf16_filename = utf8_to_utf16(path);
	hfind = FindFirstFileW(utf16_filename, &ffd);
	free(utf16_filename);

	if(hfind == INVALID_HANDLE_VALUE)
	{
		LOG_WERROR(GetLastError());
		return 0;
	}

	if(!FindClose(hfind))
	{
		LOG_WERROR(GetLastError());
	}

	return ffd.dwReserved0 == IO_REPARSE_TAG_SYMLINK;
#endif
}
Example #18
0
/* Sets values of the mark.  The force parameter controls whether mark is
 * updated even when it already points to the specified directory-file pair. */
static void
set_mark(const char m, const char directory[], const char file[],
		time_t timestamp, int force)
{
	mark_t *const mark = get_mark_by_name(m);
	if(mark != NULL && (force || !is_mark_points_to(mark, directory, file)))
	{
		reset_mark(mark);

		mark->directory = strdup(directory);
		mark->file = strdup(file);
		mark->timestamp = timestamp;

		/* Remove any trailing slashes, they might be convenient in configuration
		 * file (hence they are permitted), but shouldn't be stored internally. */
		chosp(mark->file);
	}
}
Example #19
0
void
vle_aucmd_execute(const char event[], const char path[], void *arg)
{
	size_t i;
	char canonic_path[PATH_MAX];

	canonicalize_path(path, canonic_path, sizeof(canonic_path));
	if(!is_root_dir(canonic_path))
	{
		chosp(canonic_path);
	}

	for(i = 0U; i < DA_SIZE(autocmds); ++i)
	{
		if(strcasecmp(event, autocmds[i].event) == 0 &&
				is_pattern_match(&autocmds[i], canonic_path))
		{
			autocmds[i].handler(autocmds[i].action, arg);
		}
	}
}
Example #20
0
int
ensure_file_is_selected(FileView *view, const char name[])
{
	int file_pos;
	char nm[NAME_MAX];

	/* Don't reset filters to find "file with empty name". */
	if(name[0] == '\0')
	{
		return 0;
	}

	/* This is for compatibility with paths loaded from vifminfo that have
	 * trailing slash. */
	copy_str(nm, sizeof(nm), name);
	chosp(nm);

	file_pos = find_file_pos_in_list(view, nm);
	if(file_pos < 0 && file_can_be_displayed(view->curr_dir, nm))
	{
		if(nm[0] == '.')
		{
			set_dot_files_visible(view, 1);
			file_pos = find_file_pos_in_list(view, nm);
		}

		if(file_pos < 0)
		{
			remove_filename_filter(view);

			/* remove_filename_filter() postpones list of files reloading. */
			populate_dir_list(view, 1);

			file_pos = find_file_pos_in_list(view, nm);
		}
	}

	flist_set_pos(view, (file_pos < 0) ? 0 : file_pos);
	return file_pos >= 0;
}
Example #21
0
File: path.c Project: jubalh/vifm
char *
replace_home_part(const char directory[])
{
	static char buf[PATH_MAX];
	size_t len;

	len = strlen(cfg.home_dir) - 1;
	if(strnoscmp(directory, cfg.home_dir, len) == 0 &&
			(directory[len] == '\0' || directory[len] == '/'))
	{
		strncat(strcpy(buf, "~"), directory + len, sizeof(buf) - strlen(buf) - 1);
	}
	else
	{
		copy_str(buf, sizeof(buf), directory);
	}

	if(!is_root_dir(buf))
		chosp(buf);

	return buf;
}
Example #22
0
File: utils.c Project: acklinr/vifm
void
make_abs_path(char buf[], size_t buf_len, const char base[], const char sub[],
		const char cwd[])
{
	char local_buf[buf_len];

	if(is_path_absolute(base))
	{
		snprintf(local_buf, buf_len, "%s%s%s", base, (sub[0] == '\0' ? "" : "/"),
				sub);
	}
	else
	{
		snprintf(local_buf, buf_len, "%s/%s%s%s", cwd, base,
				(sub[0] == '\0' ? "" : "/"), sub);
	}

	canonicalize_path(local_buf, buf, buf_len);
	if(!ends_with_slash(sub) && !is_root_dir(buf))
	{
		chosp(buf);
	}
}
Example #23
0
/*
 * type: CT_*
 */
void
filename_completion(const char *str, CompletionType type)
{
	/* TODO refactor filename_completion(...) function */
	DIR * dir;
	char * dirname;
	char * filename;
	char * temp;

	if(str[0] == '~' && strchr(str, '/') == NULL)
	{
		char *const tilde_expanded = expand_tilde(str);
		vle_compl_add_path_match(tilde_expanded);
		free(tilde_expanded);
		return;
	}

	dirname = expand_tilde(str);
	filename = strdup(dirname);

	temp = cmds_expand_envvars(dirname);
	free(dirname);
	dirname = temp;

	temp = strrchr(dirname, '/');
	if(temp != NULL && type != CT_FILE && type != CT_FILE_WOE)
	{
		strcpy(filename, ++temp);
		*temp = '\0';
	}
	else
	{
		dirname = realloc(dirname, 2);
		strcpy(dirname, ".");
	}

#ifdef _WIN32
	if(is_unc_root(dirname) ||
			(stroscmp(dirname, ".") == 0 && is_unc_root(curr_view->curr_dir)) ||
			(stroscmp(dirname, "/") == 0 && is_unc_path(curr_view->curr_dir)))
	{
		char buf[PATH_MAX];
		if(!is_unc_root(dirname))
			snprintf(buf,
					strchr(curr_view->curr_dir + 2, '/') - curr_view->curr_dir + 1, "%s",
					curr_view->curr_dir);
		else
			snprintf(buf, sizeof(buf), "%s", dirname);

		complete_with_shared(buf, filename);
		free(filename);
		free(dirname);
		return;
	}
	if(is_unc_path(curr_view->curr_dir))
	{
		char buf[PATH_MAX];
		if(is_path_absolute(dirname) && !is_unc_root(curr_view->curr_dir))
			snprintf(buf,
					strchr(curr_view->curr_dir + 2, '/') - curr_view->curr_dir + 2, "%s",
					curr_view->curr_dir);
		else
			snprintf(buf, sizeof(buf), "%s", curr_view->curr_dir);
		strcat(buf, dirname);
		chosp(buf);
		(void)replace_string(&dirname, buf);
	}
#endif

	dir = opendir(dirname);

	if(dir == NULL || vifm_chdir(dirname) != 0)
	{
		vle_compl_add_path_match(filename);
	}
	else
	{
		filename_completion_internal(dir, dirname, filename, type);
		(void)vifm_chdir(curr_view->curr_dir);
	}

	free(filename);
	free(dirname);

	if(dir != NULL)
	{
		closedir(dir);
	}
}
Example #24
0
File: fs.c Project: cfillion/vifm
int
get_link_target(const char *link, char *buf, size_t buf_len)
{
	LOG_FUNC_ENTER;

#ifndef _WIN32
	char *filename;
	ssize_t len;

	if(buf_len == 0)
	{
		return -1;
	}

	filename = strdup(link);
	chosp(filename);

	len = readlink(filename, buf, buf_len - 1);

	free(filename);

	if(len == -1)
	{
		return -1;
	}

	buf[len] = '\0';
	return 0;
#else
	char filename[PATH_MAX];
	DWORD attr;
	wchar_t *utf16_filename;
	HANDLE hfile;
	char rdb[2048];
	char *t;
	REPARSE_DATA_BUFFER *sbuf;
	WCHAR *path;

	if(!is_symlink(link))
	{
		return -1;
	}

	copy_str(filename, sizeof(filename), link);
	chosp(filename);

	utf16_filename = utf8_to_utf16(filename);
	hfile = CreateFileW(utf16_filename, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
			NULL, OPEN_EXISTING,
			FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
	free(utf16_filename);

	if(hfile == INVALID_HANDLE_VALUE)
	{
		LOG_WERROR(GetLastError());
		return -1;
	}

	if(!DeviceIoControl(hfile, FSCTL_GET_REPARSE_POINT, NULL, 0, rdb,
			sizeof(rdb), &attr, NULL))
	{
		LOG_WERROR(GetLastError());
		CloseHandle(hfile);
		return -1;
	}
	CloseHandle(hfile);

	sbuf = (REPARSE_DATA_BUFFER *)rdb;
	path = sbuf->SymbolicLinkReparseBuffer.PathBuffer;
	path[sbuf->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR) +
			sbuf->SymbolicLinkReparseBuffer.PrintNameLength/sizeof(WCHAR)] = L'\0';
	t = to_multibyte(path +
			sbuf->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR));
	if(strncmp(t, "\\??\\", 4) == 0)
		strncpy(buf, t + 4, buf_len);
	else
		strncpy(buf, t, buf_len);
	buf[buf_len - 1] = '\0';
	free(t);
	to_forward_slash(buf);
	return 0;
#endif
}