1
1

Merge branch '2069_memory_leaks'

* 2069_memory_leaks:
  Applied MC indentation policy.
  Ticket #2119: Fixed memory leaks in command_completion_function() function.
  Ticket #2108: Fixed memory leak in fish_linear_start() function.
  lib/util.c: Fixed memleak  in load_mc_home_file() function
  Fixed memory leak in mc_search__cond_struct_new_regex_accum_append().
  Free FS info before closing panel.
  Fixed memory leaks in viewer.
  Destroy converter before quit from editor.
  Fixed memory leaks in edit_search_cmd().
  Fixed memory leak in mc_closedir().
  Fixed memory leak in vfs_free_handle().
  Fixed memory leak in vfs_s_getlocalcopy().
  Ticket #2069: fixed memory leaks.
Этот коммит содержится в:
Andrew Borodin 2010-03-30 16:22:47 +04:00
родитель afa93bbb36 5b68413e62
Коммит a5be507432
15 изменённых файлов: 5116 добавлений и 4259 удалений

Просмотреть файл

@ -44,8 +44,7 @@ mc_config_t *mc_panels_config;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static gboolean static gboolean
mc_config_new_or_override_file (mc_config_t * mc_config, const gchar * ini_path, mc_config_new_or_override_file (mc_config_t * mc_config, const gchar * ini_path, GError ** error)
GError **error)
{ {
gchar *data, *written_data; gchar *data, *written_data;
gsize len, total_written; gsize len, total_written;
@ -54,7 +53,8 @@ mc_config_new_or_override_file (mc_config_t * mc_config, const gchar * ini_path,
ssize_t cur_written; ssize_t cur_written;
data = g_key_file_to_data (mc_config->handle, &len, NULL); data = g_key_file_to_data (mc_config->handle, &len, NULL);
if (!exist_file (ini_path)) { if (!exist_file (ini_path))
{
ret = g_file_set_contents (ini_path, data, len, error); ret = g_file_set_contents (ini_path, data, len, error);
g_free (data); g_free (data);
return ret; return ret;
@ -62,8 +62,11 @@ mc_config_new_or_override_file (mc_config_t * mc_config, const gchar * ini_path,
mc_util_make_backup_if_possible (ini_path, "~"); mc_util_make_backup_if_possible (ini_path, "~");
fd = mc_open (ini_path, O_WRONLY | O_TRUNC | O_SYNC, 0); fd = mc_open (ini_path, O_WRONLY | O_TRUNC | O_SYNC, 0);
if (fd == -1) { if (fd == -1)
g_propagate_error (error, g_error_new (mc_main_error_quark() ,0, "%s", unix_error_string (errno))); {
g_propagate_error (error,
g_error_new (mc_main_error_quark (), 0, "%s",
unix_error_string (errno)));
g_free (data); g_free (data);
return FALSE; return FALSE;
} }
@ -74,9 +77,12 @@ mc_config_new_or_override_file (mc_config_t * mc_config, const gchar * ini_path,
mc_close (fd); mc_close (fd);
g_free (data); g_free (data);
if (cur_written == -1) { if (cur_written == -1)
{
mc_util_restore_from_backup_if_possible (ini_path, "~"); mc_util_restore_from_backup_if_possible (ini_path, "~");
g_propagate_error (error, g_error_new (mc_main_error_quark() ,0, "%s", unix_error_string (errno))); g_propagate_error (error,
g_error_new (mc_main_error_quark (), 0, "%s",
unix_error_string (errno)));
return FALSE; return FALSE;
} }
@ -100,15 +106,18 @@ mc_config_init (const gchar * ini_path)
return NULL; return NULL;
mc_config->handle = g_key_file_new (); mc_config->handle = g_key_file_new ();
if (mc_config->handle == NULL) { if (mc_config->handle == NULL)
{
g_free (mc_config); g_free (mc_config);
return NULL; return NULL;
} }
if (!ini_path || !exist_file (ini_path)) { if (!ini_path || !exist_file (ini_path))
{
return mc_config; return mc_config;
} }
if (!mc_stat (ini_path, &st) && st.st_size) { if (!mc_stat (ini_path, &st) && st.st_size)
{
/* file present and not empty */ /* file present and not empty */
g_key_file_load_from_file (mc_config->handle, ini_path, G_KEY_FILE_KEEP_COMMENTS, NULL); g_key_file_load_from_file (mc_config->handle, ini_path, G_KEY_FILE_KEEP_COMMENTS, NULL);
} }
@ -195,7 +204,8 @@ mc_config_read_file (mc_config_t * mc_config, const gchar * ini_path)
gchar **keys, **curr_key; gchar **keys, **curr_key;
gchar *value; gchar *value;
if (mc_config == NULL) { if (mc_config == NULL)
{
return FALSE; return FALSE;
} }
@ -206,11 +216,16 @@ mc_config_read_file (mc_config_t * mc_config, const gchar * ini_path)
groups = mc_config_get_groups (tmp_config, NULL); groups = mc_config_get_groups (tmp_config, NULL);
if (groups == NULL) if (groups == NULL)
{
mc_config_deinit (tmp_config);
return FALSE; return FALSE;
}
for (curr_grp = groups; *curr_grp != NULL; curr_grp++) { for (curr_grp = groups; *curr_grp != NULL; curr_grp++)
{
keys = mc_config_get_keys (tmp_config, *curr_grp, NULL); keys = mc_config_get_keys (tmp_config, *curr_grp, NULL);
for (curr_key = keys; *curr_key != NULL; curr_key++) { for (curr_key = keys; *curr_key != NULL; curr_key++)
{
value = g_key_file_get_value (tmp_config->handle, *curr_grp, *curr_key, NULL); value = g_key_file_get_value (tmp_config->handle, *curr_grp, *curr_key, NULL);
if (value == NULL) if (value == NULL)
continue; continue;
@ -230,7 +245,8 @@ mc_config_read_file (mc_config_t * mc_config, const gchar * ini_path)
gboolean gboolean
mc_config_save_file (mc_config_t * mc_config, GError ** error) mc_config_save_file (mc_config_t * mc_config, GError ** error)
{ {
if (mc_config == NULL || mc_config->ini_path == NULL) { if (mc_config == NULL || mc_config->ini_path == NULL)
{
return FALSE; return FALSE;
} }
return mc_config_new_or_override_file (mc_config, mc_config->ini_path, error); return mc_config_new_or_override_file (mc_config, mc_config->ini_path, error);
@ -241,8 +257,8 @@ mc_config_save_file (mc_config_t * mc_config, GError **error)
gboolean gboolean
mc_config_save_to_file (mc_config_t * mc_config, const gchar * ini_path, GError ** error) mc_config_save_to_file (mc_config_t * mc_config, const gchar * ini_path, GError ** error)
{ {
if (mc_config == NULL)
if (mc_config == NULL) { {
return FALSE; return FALSE;
} }
return mc_config_new_or_override_file (mc_config, ini_path, error); return mc_config_new_or_override_file (mc_config, ini_path, error);

Просмотреть файл

@ -44,7 +44,8 @@
/*** file scope type declarations ****************************************************************/ /*** file scope type declarations ****************************************************************/
typedef enum { typedef enum
{
REPLACE_T_NO_TRANSFORM = 0, REPLACE_T_NO_TRANSFORM = 0,
REPLACE_T_UPP_TRANSFORM_CHAR = 1, REPLACE_T_UPP_TRANSFORM_CHAR = 1,
REPLACE_T_LOW_TRANSFORM_CHAR = 2, REPLACE_T_LOW_TRANSFORM_CHAR = 2,
@ -81,18 +82,24 @@ mc_search__regex_str_append_if_special (GString * copy_to, GString * regex_str,
tmp_regex_str = &(regex_str->str[*offset]); tmp_regex_str = &(regex_str->str[*offset]);
while (*spec_chr) { while (*spec_chr)
{
spec_chr_len = strlen (*spec_chr); spec_chr_len = strlen (*spec_chr);
if (!strncmp (tmp_regex_str, *spec_chr, spec_chr_len)) { if (!strncmp (tmp_regex_str, *spec_chr, spec_chr_len))
if (!strutils_is_char_escaped (regex_str->str, tmp_regex_str)) { {
if (!strncmp ("\\x", *spec_chr, spec_chr_len)) { if (!strutils_is_char_escaped (regex_str->str, tmp_regex_str))
if (*(tmp_regex_str + spec_chr_len) == '{') { {
if (!strncmp ("\\x", *spec_chr, spec_chr_len))
{
if (*(tmp_regex_str + spec_chr_len) == '{')
{
while ((spec_chr_len < regex_str->len - *offset) while ((spec_chr_len < regex_str->len - *offset)
&& *(tmp_regex_str + spec_chr_len) != '}') && *(tmp_regex_str + spec_chr_len) != '}')
spec_chr_len++; spec_chr_len++;
if (*(tmp_regex_str + spec_chr_len) == '}') if (*(tmp_regex_str + spec_chr_len) == '}')
spec_chr_len++; spec_chr_len++;
} else }
else
spec_chr_len += 2; spec_chr_len += 2;
} }
g_string_append_len (copy_to, tmp_regex_str, spec_chr_len); g_string_append_len (copy_to, tmp_regex_str, spec_chr_len);
@ -118,16 +125,20 @@ mc_search__cond_struct_new_regex_hex_add (const char *charset, GString * str_to,
upp = mc_search__toupper_case_str (charset, one_char, str_len); upp = mc_search__toupper_case_str (charset, one_char, str_len);
low = mc_search__tolower_case_str (charset, one_char, str_len); low = mc_search__tolower_case_str (charset, one_char, str_len);
for (loop = 0; loop < upp->len; loop++) { for (loop = 0; loop < upp->len; loop++)
{
if (loop < low->len) { if (loop < low->len)
{
if (upp->str[loop] == low->str[loop]) if (upp->str[loop] == low->str[loop])
tmp_str = g_strdup_printf ("\\x%02X", (unsigned char) upp->str[loop]); tmp_str = g_strdup_printf ("\\x%02X", (unsigned char) upp->str[loop]);
else else
tmp_str = tmp_str =
g_strdup_printf ("[\\x%02X\\x%02X]", (unsigned char) upp->str[loop], g_strdup_printf ("[\\x%02X\\x%02X]", (unsigned char) upp->str[loop],
(unsigned char) low->str[loop]); (unsigned char) low->str[loop]);
} else { }
else
{
tmp_str = g_strdup_printf ("\\x%02X", (unsigned char) upp->str[loop]); tmp_str = g_strdup_printf ("\\x%02X", (unsigned char) upp->str[loop]);
} }
g_string_append (str_to, tmp_str); g_string_append (str_to, tmp_str);
@ -144,31 +155,34 @@ mc_search__cond_struct_new_regex_accum_append (const char *charset, GString * st
GString * str_from) GString * str_from)
{ {
GString *recoded_part; GString *recoded_part;
gsize loop = 0;
recoded_part = g_string_sized_new (32);
while (loop < str_from->len)
{
gchar *one_char; gchar *one_char;
gsize loop; gsize one_char_len;
gboolean just_letters; gboolean just_letters;
loop = 0;
recoded_part = g_string_new ("");
while (loop < str_from->len) {
one_char = one_char =
mc_search__get_one_symbol (charset, &(str_from->str[loop]), mc_search__get_one_symbol (charset, &(str_from->str[loop]),
(str_from->len - loop > 6) ? 6 : str_from->len - loop, min (str_from->len - loop, 6), &just_letters);
&just_letters); one_char_len = strlen (one_char);
if (!strlen (one_char)) {
if (one_char_len == 0)
loop++; loop++;
continue; else
} {
if (just_letters) { loop += one_char_len;
if (just_letters)
mc_search__cond_struct_new_regex_hex_add (charset, recoded_part, one_char, mc_search__cond_struct_new_regex_hex_add (charset, recoded_part, one_char,
strlen (one_char)); one_char_len);
} else { else
g_string_append (recoded_part, one_char); g_string_append_len (recoded_part, one_char, one_char_len);
} }
loop += strlen (one_char);
if (!strlen (one_char))
loop++;
g_free (one_char); g_free (one_char);
} }
@ -193,20 +207,23 @@ mc_search__cond_struct_new_regex_ci_str (const char *charset, const char *str, g
spec_char = g_string_new (""); spec_char = g_string_new ("");
loop = 0; loop = 0;
while (loop <= str_len) { while (loop <= str_len)
if (mc_search__regex_str_append_if_special (spec_char, tmp, &loop)) { {
if (mc_search__regex_str_append_if_special (spec_char, tmp, &loop))
{
mc_search__cond_struct_new_regex_accum_append (charset, ret_str, accumulator); mc_search__cond_struct_new_regex_accum_append (charset, ret_str, accumulator);
g_string_append_len (ret_str, spec_char->str, spec_char->len); g_string_append_len (ret_str, spec_char->str, spec_char->len);
g_string_set_size (spec_char, 0); g_string_set_size (spec_char, 0);
continue; continue;
} }
if (tmp->str[loop] == '[' && !strutils_is_char_escaped (tmp->str, &(tmp->str[loop]))) { if (tmp->str[loop] == '[' && !strutils_is_char_escaped (tmp->str, &(tmp->str[loop])))
{
mc_search__cond_struct_new_regex_accum_append (charset, ret_str, accumulator); mc_search__cond_struct_new_regex_accum_append (charset, ret_str, accumulator);
while (loop < str_len && !(tmp->str[loop] == ']' while (loop < str_len && !(tmp->str[loop] == ']'
&& !strutils_is_char_escaped (tmp->str, && !strutils_is_char_escaped (tmp->str, &(tmp->str[loop]))))
&(tmp->str[loop])))) { {
g_string_append_c (ret_str, tmp->str[loop]); g_string_append_c (ret_str, tmp->str[loop]);
loop++; loop++;
@ -240,12 +257,15 @@ mc_search__regex_found_cond_one (mc_search_t * lc_mc_search, mc_search_regex_t *
if (!g_regex_match_full if (!g_regex_match_full
(regex, search_str->str, -1, 0, G_REGEX_MATCH_NEWLINE_ANY, &lc_mc_search->regex_match_info, (regex, search_str->str, -1, 0, G_REGEX_MATCH_NEWLINE_ANY, &lc_mc_search->regex_match_info,
&error)) { &error))
{
g_match_info_free (lc_mc_search->regex_match_info); g_match_info_free (lc_mc_search->regex_match_info);
lc_mc_search->regex_match_info = NULL; lc_mc_search->regex_match_info = NULL;
if (error) { if (error)
{
lc_mc_search->error = MC_SEARCH_E_REGEX; lc_mc_search->error = MC_SEARCH_E_REGEX;
lc_mc_search->error_str = str_conv_gerror_message (error, _(" Regular expression error ")); lc_mc_search->error_str =
str_conv_gerror_message (error, _(" Regular expression error "));
g_error_free (error); g_error_free (error);
return COND__FOUND_ERROR; return COND__FOUND_ERROR;
} }
@ -254,9 +274,10 @@ mc_search__regex_found_cond_one (mc_search_t * lc_mc_search, mc_search_regex_t *
lc_mc_search->num_rezults = g_match_info_get_match_count (lc_mc_search->regex_match_info); lc_mc_search->num_rezults = g_match_info_get_match_count (lc_mc_search->regex_match_info);
#else /* SEARCH_TYPE_GLIB */ #else /* SEARCH_TYPE_GLIB */
lc_mc_search->num_rezults = pcre_exec (regex, lc_mc_search->regex_match_info, lc_mc_search->num_rezults = pcre_exec (regex, lc_mc_search->regex_match_info,
search_str->str, search_str->len - 1, 0, 0, lc_mc_search->iovector, search_str->str, search_str->len - 1, 0, 0,
MC_SEARCH__NUM_REPLACE_ARGS); lc_mc_search->iovector, MC_SEARCH__NUM_REPLACE_ARGS);
if (lc_mc_search->num_rezults < 0) { if (lc_mc_search->num_rezults < 0)
{
return COND__NOT_FOUND; return COND__NOT_FOUND;
} }
#endif /* SEARCH_TYPE_GLIB */ #endif /* SEARCH_TYPE_GLIB */
@ -273,13 +294,16 @@ mc_search__regex_found_cond (mc_search_t * lc_mc_search, GString * search_str)
mc_search_cond_t *mc_search_cond; mc_search_cond_t *mc_search_cond;
mc_search__found_cond_t ret; mc_search__found_cond_t ret;
for (loop1 = 0; loop1 < lc_mc_search->conditions->len; loop1++) { for (loop1 = 0; loop1 < lc_mc_search->conditions->len; loop1++)
{
mc_search_cond = (mc_search_cond_t *) g_ptr_array_index (lc_mc_search->conditions, loop1); mc_search_cond = (mc_search_cond_t *) g_ptr_array_index (lc_mc_search->conditions, loop1);
if (!mc_search_cond->regex_handle) if (!mc_search_cond->regex_handle)
continue; continue;
ret = mc_search__regex_found_cond_one (lc_mc_search, mc_search_cond->regex_handle, search_str); ret =
mc_search__regex_found_cond_one (lc_mc_search, mc_search_cond->regex_handle,
search_str);
if (ret != COND__NOT_FOUND) if (ret != COND__NOT_FOUND)
return ret; return ret;
@ -294,15 +318,18 @@ mc_search_regex__get_max_num_of_replace_tokens (const gchar * str, gsize len)
{ {
int max_token = 0; int max_token = 0;
gsize loop; gsize loop;
for (loop = 0; loop < len - 1; loop++) { for (loop = 0; loop < len - 1; loop++)
if (str[loop] == '\\' && (str[loop + 1] & (char) 0xf0) == 0x30 /* 0-9 */ ) { {
if (str[loop] == '\\' && (str[loop + 1] & (char) 0xf0) == 0x30 /* 0-9 */ )
{
if (strutils_is_char_escaped (str, &str[loop])) if (strutils_is_char_escaped (str, &str[loop]))
continue; continue;
if (max_token < str[loop + 1] - '0') if (max_token < str[loop + 1] - '0')
max_token = str[loop + 1] - '0'; max_token = str[loop + 1] - '0';
continue; continue;
} }
if (str[loop] == '$' && str[loop + 1] == '{') { if (str[loop] == '$' && str[loop + 1] == '{')
{
gsize tmp_len; gsize tmp_len;
char *tmp_str; char *tmp_str;
int tmp_token; int tmp_token;
@ -312,7 +339,8 @@ mc_search_regex__get_max_num_of_replace_tokens (const gchar * str, gsize len)
for (tmp_len = 0; for (tmp_len = 0;
loop + tmp_len + 2 < len && (str[loop + 2 + tmp_len] & (char) 0xf0) == 0x30; loop + tmp_len + 2 < len && (str[loop + 2 + tmp_len] & (char) 0xf0) == 0x30;
tmp_len++); tmp_len++);
if (str[loop + 2 + tmp_len] == '}') { if (str[loop + 2 + tmp_len] == '}')
{
tmp_str = g_strndup (&str[loop + 2], tmp_len); tmp_str = g_strndup (&str[loop + 2], tmp_len);
tmp_token = atoi (tmp_str); tmp_token = atoi (tmp_str);
if (max_token < tmp_token) if (max_token < tmp_token)
@ -359,8 +387,10 @@ mc_search_regex__process_replace_str (const GString * replace_str, const gsize c
*skip_len = 0; *skip_len = 0;
if (*curr_str == '$' && *(curr_str + 1) == '{' && (*(curr_str + 2) & (char) 0xf0) == 0x30) { if (*curr_str == '$' && *(curr_str + 1) == '{' && (*(curr_str + 2) & (char) 0xf0) == 0x30)
if (strutils_is_char_escaped (replace_str->str, curr_str)) { {
if (strutils_is_char_escaped (replace_str->str, curr_str))
{
*skip_len = 1; *skip_len = 1;
return -1; return -1;
} }
@ -383,20 +413,24 @@ mc_search_regex__process_replace_str (const GString * replace_str, const gsize c
return ret; return ret;
} }
if (*curr_str == '\\') { if (*curr_str == '\\')
if (strutils_is_char_escaped (replace_str->str, curr_str)) { {
if (strutils_is_char_escaped (replace_str->str, curr_str))
{
*skip_len = 1; *skip_len = 1;
return -1; return -1;
} }
if ((*(curr_str + 1) & (char) 0xf0) == 0x30) { if ((*(curr_str + 1) & (char) 0xf0) == 0x30)
{
ret = *(curr_str + 1) - '0'; ret = *(curr_str + 1) - '0';
*skip_len = 2; /* \\ and one digit */ *skip_len = 2; /* \\ and one digit */
return ret; return ret;
} }
ret = -2; ret = -2;
*skip_len += 2; *skip_len += 2;
switch (*(curr_str + 1)) { switch (*(curr_str + 1))
{
case 'U': case 'U':
*replace_flags |= REPLACE_T_UPP_TRANSFORM; *replace_flags |= REPLACE_T_UPP_TRANSFORM;
*replace_flags &= ~REPLACE_T_LOW_TRANSFORM; *replace_flags &= ~REPLACE_T_LOW_TRANSFORM;
@ -433,36 +467,47 @@ mc_search_regex__process_append_str (GString * dest_str, const char *from, gsize
if (len == (gsize) - 1) if (len == (gsize) - 1)
len = strlen (from); len = strlen (from);
if (*replace_flags == REPLACE_T_NO_TRANSFORM) { if (*replace_flags == REPLACE_T_NO_TRANSFORM)
{
g_string_append_len (dest_str, from, len); g_string_append_len (dest_str, from, len);
return; return;
} }
while (loop < len) { while (loop < len)
{
tmp_str = mc_search__get_one_symbol (NULL, from + loop, len - loop, NULL); tmp_str = mc_search__get_one_symbol (NULL, from + loop, len - loop, NULL);
char_len = strlen (tmp_str); char_len = strlen (tmp_str);
if (*replace_flags & REPLACE_T_UPP_TRANSFORM_CHAR) { if (*replace_flags & REPLACE_T_UPP_TRANSFORM_CHAR)
{
*replace_flags &= !REPLACE_T_UPP_TRANSFORM_CHAR; *replace_flags &= !REPLACE_T_UPP_TRANSFORM_CHAR;
tmp_string = mc_search__toupper_case_str (NULL, tmp_str, char_len); tmp_string = mc_search__toupper_case_str (NULL, tmp_str, char_len);
g_string_append (dest_str, tmp_string->str); g_string_append (dest_str, tmp_string->str);
g_string_free (tmp_string, TRUE); g_string_free (tmp_string, TRUE);
} else if (*replace_flags & REPLACE_T_LOW_TRANSFORM_CHAR) { }
else if (*replace_flags & REPLACE_T_LOW_TRANSFORM_CHAR)
{
*replace_flags &= !REPLACE_T_LOW_TRANSFORM_CHAR; *replace_flags &= !REPLACE_T_LOW_TRANSFORM_CHAR;
tmp_string = mc_search__toupper_case_str (NULL, tmp_str, char_len); tmp_string = mc_search__toupper_case_str (NULL, tmp_str, char_len);
g_string_append (dest_str, tmp_string->str); g_string_append (dest_str, tmp_string->str);
g_string_free (tmp_string, TRUE); g_string_free (tmp_string, TRUE);
} else if (*replace_flags & REPLACE_T_UPP_TRANSFORM) { }
else if (*replace_flags & REPLACE_T_UPP_TRANSFORM)
{
tmp_string = mc_search__toupper_case_str (NULL, tmp_str, char_len); tmp_string = mc_search__toupper_case_str (NULL, tmp_str, char_len);
g_string_append (dest_str, tmp_string->str); g_string_append (dest_str, tmp_string->str);
g_string_free (tmp_string, TRUE); g_string_free (tmp_string, TRUE);
} else if (*replace_flags & REPLACE_T_LOW_TRANSFORM) { }
else if (*replace_flags & REPLACE_T_LOW_TRANSFORM)
{
tmp_string = mc_search__tolower_case_str (NULL, tmp_str, char_len); tmp_string = mc_search__tolower_case_str (NULL, tmp_str, char_len);
g_string_append (dest_str, tmp_string->str); g_string_append (dest_str, tmp_string->str);
g_string_free (tmp_string, TRUE); g_string_free (tmp_string, TRUE);
} else { }
else
{
g_string_append (dest_str, tmp_str); g_string_append (dest_str, tmp_str);
} }
g_free (tmp_str); g_free (tmp_str);
@ -485,7 +530,8 @@ mc_search__cond_struct_new_init_regex (const char *charset, mc_search_t * lc_mc_
int erroffset; int erroffset;
#endif /* SEARCH_TYPE_GLIB */ #endif /* SEARCH_TYPE_GLIB */
if (!lc_mc_search->is_case_sentitive) { if (!lc_mc_search->is_case_sentitive)
{
tmp = g_string_new_len (mc_search_cond->str->str, mc_search_cond->str->len); tmp = g_string_new_len (mc_search_cond->str->str, mc_search_cond->str->len);
g_string_free (mc_search_cond->str, TRUE); g_string_free (mc_search_cond->str, TRUE);
mc_search_cond->str = mc_search__cond_struct_new_regex_ci_str (charset, tmp->str, tmp->len); mc_search_cond->str = mc_search__cond_struct_new_regex_ci_str (charset, tmp->str, tmp->len);
@ -496,7 +542,8 @@ mc_search__cond_struct_new_init_regex (const char *charset, mc_search_t * lc_mc_
g_regex_new (mc_search_cond->str->str, G_REGEX_OPTIMIZE | G_REGEX_RAW | G_REGEX_DOTALL, 0, g_regex_new (mc_search_cond->str->str, G_REGEX_OPTIMIZE | G_REGEX_RAW | G_REGEX_DOTALL, 0,
&error); &error);
if (error != NULL) { if (error != NULL)
{
lc_mc_search->error = MC_SEARCH_E_REGEX_COMPILE; lc_mc_search->error = MC_SEARCH_E_REGEX_COMPILE;
lc_mc_search->error_str = str_conv_gerror_message (error, _(" Regular expression error ")); lc_mc_search->error_str = str_conv_gerror_message (error, _(" Regular expression error "));
g_error_free (error); g_error_free (error);
@ -505,14 +552,17 @@ mc_search__cond_struct_new_init_regex (const char *charset, mc_search_t * lc_mc_
#else /* SEARCH_TYPE_GLIB */ #else /* SEARCH_TYPE_GLIB */
mc_search_cond->regex_handle = mc_search_cond->regex_handle =
pcre_compile (mc_search_cond->str->str, PCRE_EXTRA, &error, &erroffset, NULL); pcre_compile (mc_search_cond->str->str, PCRE_EXTRA, &error, &erroffset, NULL);
if (mc_search_cond->regex_handle == NULL) { if (mc_search_cond->regex_handle == NULL)
{
lc_mc_search->error = MC_SEARCH_E_REGEX_COMPILE; lc_mc_search->error = MC_SEARCH_E_REGEX_COMPILE;
lc_mc_search->error_str = g_strdup (error); lc_mc_search->error_str = g_strdup (error);
return; return;
} }
lc_mc_search->regex_match_info = pcre_study (mc_search_cond->regex_handle, 0, &error); lc_mc_search->regex_match_info = pcre_study (mc_search_cond->regex_handle, 0, &error);
if (lc_mc_search->regex_match_info == NULL) { if (lc_mc_search->regex_match_info == NULL)
if (error) { {
if (error)
{
lc_mc_search->error = MC_SEARCH_E_REGEX_COMPILE; lc_mc_search->error = MC_SEARCH_E_REGEX_COMPILE;
lc_mc_search->error_str = g_strdup (error); lc_mc_search->error_str = g_strdup (error);
g_free (mc_search_cond->regex_handle); g_free (mc_search_cond->regex_handle);
@ -540,11 +590,13 @@ mc_search__run_regex (mc_search_t * lc_mc_search, const void *user_data,
lc_mc_search->regex_buffer = g_string_new (""); lc_mc_search->regex_buffer = g_string_new ("");
virtual_pos = current_pos = start_search; virtual_pos = current_pos = start_search;
while (virtual_pos <= end_search) { while (virtual_pos <= end_search)
{
g_string_set_size (lc_mc_search->regex_buffer, 0); g_string_set_size (lc_mc_search->regex_buffer, 0);
lc_mc_search->start_buffer = current_pos; lc_mc_search->start_buffer = current_pos;
while (1) { while (1)
{
current_chr = mc_search__get_char (lc_mc_search, user_data, current_pos); current_chr = mc_search__get_char (lc_mc_search, user_data, current_pos);
if (current_chr == MC_SEARCH_CB_ABORT) if (current_chr == MC_SEARCH_CB_ABORT)
break; break;
@ -566,7 +618,8 @@ mc_search__run_regex (mc_search_t * lc_mc_search, const void *user_data,
break; break;
} }
switch (mc_search__regex_found_cond (lc_mc_search, lc_mc_search->regex_buffer)) { switch (mc_search__regex_found_cond (lc_mc_search, lc_mc_search->regex_buffer))
{
case COND__FOUND_OK: case COND__FOUND_OK:
#ifdef SEARCH_TYPE_GLIB #ifdef SEARCH_TYPE_GLIB
g_match_info_fetch_pos (lc_mc_search->regex_match_info, 0, &start_pos, &end_pos); g_match_info_fetch_pos (lc_mc_search->regex_match_info, 0, &start_pos, &end_pos);
@ -626,7 +679,8 @@ mc_search_regex_prepare_replace_str (mc_search_t * lc_mc_search, GString * repla
return g_string_new_len (replace_str->str, replace_str->len); return g_string_new_len (replace_str->str, replace_str->len);
if (num_replace_tokens > lc_mc_search->num_rezults - 1 if (num_replace_tokens > lc_mc_search->num_rezults - 1
|| num_replace_tokens > MC_SEARCH__NUM_REPLACE_ARGS) { || num_replace_tokens > MC_SEARCH__NUM_REPLACE_ARGS)
{
lc_mc_search->error = MC_SEARCH_E_REGEX_REPLACE; lc_mc_search->error = MC_SEARCH_E_REGEX_REPLACE;
lc_mc_search->error_str = g_strdup (STR_E_RPL_NOT_EQ_TO_FOUND); lc_mc_search->error_str = g_strdup (STR_E_RPL_NOT_EQ_TO_FOUND);
return NULL; return NULL;
@ -634,11 +688,14 @@ mc_search_regex_prepare_replace_str (mc_search_t * lc_mc_search, GString * repla
ret = g_string_new (""); ret = g_string_new ("");
prev_str = replace_str->str; prev_str = replace_str->str;
for (loop = 0; loop < replace_str->len - 1; loop++) { for (loop = 0; loop < replace_str->len - 1; loop++)
{
lc_index = mc_search_regex__process_replace_str (replace_str, loop, &len, &replace_flags); lc_index = mc_search_regex__process_replace_str (replace_str, loop, &len, &replace_flags);
if (lc_index == -1) { if (lc_index == -1)
if (len != 0) { {
if (len != 0)
{
mc_search_regex__process_append_str (ret, prev_str, mc_search_regex__process_append_str (ret, prev_str,
replace_str->str - prev_str + loop, replace_str->str - prev_str + loop,
&replace_flags); &replace_flags);
@ -650,7 +707,8 @@ mc_search_regex_prepare_replace_str (mc_search_t * lc_mc_search, GString * repla
continue; continue;
} }
if (lc_index == -2) { if (lc_index == -2)
{
if (loop) if (loop)
mc_search_regex__process_append_str (ret, prev_str, mc_search_regex__process_append_str (ret, prev_str,
replace_str->str - prev_str + loop, replace_str->str - prev_str + loop,
@ -660,7 +718,8 @@ mc_search_regex_prepare_replace_str (mc_search_t * lc_mc_search, GString * repla
continue; continue;
} }
if (lc_index > lc_mc_search->num_rezults) { if (lc_index > lc_mc_search->num_rezults)
{
g_string_free (ret, TRUE); g_string_free (ret, TRUE);
lc_mc_search->error = MC_SEARCH_E_REGEX_REPLACE; lc_mc_search->error = MC_SEARCH_E_REGEX_REPLACE;
lc_mc_search->error_str = g_strdup_printf (STR_E_RPL_INVALID_TOKEN, lc_index); lc_mc_search->error_str = g_strdup_printf (STR_E_RPL_INVALID_TOKEN, lc_index);

Просмотреть файл

@ -663,6 +663,7 @@ load_mc_home_file (const char *_mc_home, const char *_mc_home_alt, const char *f
/* Fall back to the two-letter language code */ /* Fall back to the two-letter language code */
if (lang[0] && lang[1]) if (lang[0] && lang[1])
lang[2] = 0; lang[2] = 0;
g_free (hintfile);
hintfile = g_strconcat (hintfile_base, ".", lang, (char *) NULL); hintfile = g_strconcat (hintfile_base, ".", lang, (char *) NULL);
data = load_file (hintfile); data = load_file (hintfile);

Просмотреть файл

@ -102,27 +102,34 @@ vfs_s_free_inode (struct vfs_class *me, struct vfs_s_inode *ino)
vfs_die ("Don't pass NULL to me"); vfs_die ("Don't pass NULL to me");
/* ==0 can happen if freshly created entry is deleted */ /* ==0 can happen if freshly created entry is deleted */
if (ino->st.st_nlink <= 1){ if (ino->st.st_nlink <= 1)
while (ino->subdir){ {
while (ino->subdir)
{
vfs_s_free_entry (me, ino->subdir); vfs_s_free_entry (me, ino->subdir);
} }
CALL (free_inode) (me, ino); CALL (free_inode) (me, ino);
g_free (ino->linkname); g_free (ino->linkname);
if (ino->localname){ if (ino->localname)
{
unlink (ino->localname); unlink (ino->localname);
g_free (ino->localname); g_free (ino->localname);
} }
total_inodes--; total_inodes--;
ino->super->ino_usage--; ino->super->ino_usage--;
g_free (ino); g_free (ino);
} else ino->st.st_nlink--; }
else
ino->st.st_nlink--;
} }
void void
vfs_s_free_entry (struct vfs_class *me, struct vfs_s_entry *ent) vfs_s_free_entry (struct vfs_class *me, struct vfs_s_entry *ent)
{ {
if (ent->prevp){ /* It is possible that we are deleting freshly created entry */ if (ent->prevp)
{
/* It is possible that we are deleting freshly created entry */
*ent->prevp = ent->next; *ent->prevp = ent->next;
if (ent->next) if (ent->next)
ent->next->prevp = ent->prevp; ent->next->prevp = ent->prevp;
@ -131,7 +138,8 @@ vfs_s_free_entry (struct vfs_class *me, struct vfs_s_entry *ent)
g_free (ent->name); g_free (ent->name);
ent->name = NULL; ent->name = NULL;
if (ent->ino){ if (ent->ino)
{
ent->ino->ent = NULL; ent->ino->ent = NULL;
vfs_s_free_inode (me, ent->ino); vfs_s_free_inode (me, ent->ino);
ent->ino = NULL; ent->ino = NULL;
@ -183,7 +191,8 @@ vfs_s_default_stat (struct vfs_class *me, mode_t mode)
} }
struct vfs_s_entry * struct vfs_s_entry *
vfs_s_generate_entry (struct vfs_class *me, const char *name, struct vfs_s_inode *parent, mode_t mode) vfs_s_generate_entry (struct vfs_class *me, const char *name, struct vfs_s_inode *parent,
mode_t mode)
{ {
struct vfs_s_inode *inode; struct vfs_s_inode *inode;
struct stat *st; struct stat *st;
@ -214,8 +223,7 @@ vfs_s_automake (struct vfs_class *me, struct vfs_s_inode *dir, char *path, int f
/* If the entry is a symlink, find the entry for its target */ /* If the entry is a symlink, find the entry for its target */
static struct vfs_s_entry * static struct vfs_s_entry *
vfs_s_resolve_symlink (struct vfs_class *me, struct vfs_s_entry *entry, vfs_s_resolve_symlink (struct vfs_class *me, struct vfs_s_entry *entry, int follow)
int follow)
{ {
char *linkname; char *linkname;
char *fullname = NULL; char *fullname = NULL;
@ -235,18 +243,18 @@ vfs_s_resolve_symlink (struct vfs_class *me, struct vfs_s_entry *entry,
ERRNOR (EFAULT, NULL); ERRNOR (EFAULT, NULL);
/* make full path from relative */ /* make full path from relative */
if (*linkname != PATH_SEP) { if (*linkname != PATH_SEP)
{
char *fullpath = vfs_s_fullpath (me, entry->dir); char *fullpath = vfs_s_fullpath (me, entry->dir);
if (fullpath) { if (fullpath)
{
fullname = g_strconcat (fullpath, "/", linkname, (char *) NULL); fullname = g_strconcat (fullpath, "/", linkname, (char *) NULL);
linkname = fullname; linkname = fullname;
g_free (fullpath); g_free (fullpath);
} }
} }
target = target = (MEDATA->find_entry) (me, entry->dir->super->root, linkname, follow - 1, 0);
(MEDATA->find_entry) (me, entry->dir->super->root, linkname,
follow - 1, 0);
g_free (fullname); g_free (fullname);
return target; return target;
} }
@ -267,11 +275,13 @@ vfs_s_find_entry_tree (struct vfs_class *me, struct vfs_s_inode *root,
/* canonicalize as well, but don't remove '../' from path */ /* canonicalize as well, but don't remove '../' from path */
custom_canonicalize_pathname (path, CANON_PATH_ALL & (~CANON_PATH_REMDOUBLEDOTS)); custom_canonicalize_pathname (path, CANON_PATH_ALL & (~CANON_PATH_REMDOUBLEDOTS));
while (root) { while (root)
{
while (*path == PATH_SEP) /* Strip leading '/' */ while (*path == PATH_SEP) /* Strip leading '/' */
path++; path++;
if (!path[0]) { if (!path[0])
{
g_free (pathref); g_free (pathref);
return ent; return ent;
} }
@ -279,25 +289,21 @@ vfs_s_find_entry_tree (struct vfs_class *me, struct vfs_s_inode *root,
for (pseg = 0; path[pseg] && path[pseg] != PATH_SEP; pseg++); for (pseg = 0; path[pseg] && path[pseg] != PATH_SEP; pseg++);
for (ent = root->subdir; ent != NULL; ent = ent->next) for (ent = root->subdir; ent != NULL; ent = ent->next)
if (strlen (ent->name) == pseg if (strlen (ent->name) == pseg && (!strncmp (ent->name, path, pseg)))
&& (!strncmp (ent->name, path, pseg)))
/* FOUND! */ /* FOUND! */
break; break;
if (!ent && (flags & (FL_MKFILE | FL_MKDIR))) if (!ent && (flags & (FL_MKFILE | FL_MKDIR)))
ent = vfs_s_automake (me, root, path, flags); ent = vfs_s_automake (me, root, path, flags);
if (!ent) { if (!ent)
{
me->verrno = ENOENT; me->verrno = ENOENT;
goto cleanup; goto cleanup;
} }
path += pseg; path += pseg;
/* here we must follow leading directories always; /* here we must follow leading directories always;
only the actual file is optional */ only the actual file is optional */
ent = ent = vfs_s_resolve_symlink (me, ent, strchr (path, PATH_SEP) ? LINK_FOLLOW : follow);
vfs_s_resolve_symlink (me, ent,
strchr (path,
PATH_SEP) ? LINK_FOLLOW :
follow);
if (!ent) if (!ent)
goto cleanup; goto cleanup;
root = ent->ino; root = ent->ino;
@ -315,11 +321,14 @@ split_dir_name (struct vfs_class *me, char *path, char **dir, char **name, char
(void) me; (void) me;
s = strrchr (path, PATH_SEP); s = strrchr (path, PATH_SEP);
if (s == NULL) { if (s == NULL)
{
*save = NULL; *save = NULL;
*name = path; *name = path;
*dir = path + strlen (path); /* an empty string */ *dir = path + strlen (path); /* an empty string */
} else { }
else
{
*save = s; *save = s;
*dir = path; *dir = path;
*s++ = '\0'; *s++ = '\0';
@ -341,13 +350,12 @@ vfs_s_find_entry_linear (struct vfs_class *me, struct vfs_s_inode *root,
/* canonicalize as well, but don't remove '../' from path */ /* canonicalize as well, but don't remove '../' from path */
custom_canonicalize_pathname (path, CANON_PATH_ALL & (~CANON_PATH_REMDOUBLEDOTS)); custom_canonicalize_pathname (path, CANON_PATH_ALL & (~CANON_PATH_REMDOUBLEDOTS));
if (!(flags & FL_DIR)) { if (!(flags & FL_DIR))
{
char *dirname, *name, *save; char *dirname, *name, *save;
struct vfs_s_inode *ino; struct vfs_s_inode *ino;
split_dir_name (me, path, &dirname, &name, &save); split_dir_name (me, path, &dirname, &name, &save);
ino = ino = vfs_s_find_inode (me, root->super, dirname, follow, flags | FL_DIR);
vfs_s_find_inode (me, root->super, dirname, follow,
flags | FL_DIR);
if (save) if (save)
*save = PATH_SEP; *save = PATH_SEP;
retval = vfs_s_find_entry_tree (me, ino, name, follow, flags); retval = vfs_s_find_entry_tree (me, ino, name, follow, flags);
@ -359,7 +367,8 @@ vfs_s_find_entry_linear (struct vfs_class *me, struct vfs_s_inode *root,
if (!strcmp (ent->name, path)) if (!strcmp (ent->name, path))
break; break;
if (ent && (!(MEDATA->dir_uptodate) (me, ent->ino))) { if (ent && (!(MEDATA->dir_uptodate) (me, ent->ino)))
{
#if 1 #if 1
print_vfs_message (_("Directory cache expired for %s"), path); print_vfs_message (_("Directory cache expired for %s"), path);
#endif #endif
@ -367,14 +376,14 @@ vfs_s_find_entry_linear (struct vfs_class *me, struct vfs_s_inode *root,
ent = NULL; ent = NULL;
} }
if (!ent) { if (!ent)
{
struct vfs_s_inode *ino; struct vfs_s_inode *ino;
ino = ino = vfs_s_new_inode (me, root->super, vfs_s_default_stat (me, S_IFDIR | 0755));
vfs_s_new_inode (me, root->super,
vfs_s_default_stat (me, S_IFDIR | 0755));
ent = vfs_s_new_entry (me, path, ino); ent = vfs_s_new_entry (me, path, ino);
if ((MEDATA->dir_load) (me, ino, path) == -1) { if ((MEDATA->dir_load) (me, ino, path) == -1)
{
vfs_s_free_entry (me, ent); vfs_s_free_entry (me, ent);
g_free (path); g_free (path);
return NULL; return NULL;
@ -389,7 +398,8 @@ vfs_s_find_entry_linear (struct vfs_class *me, struct vfs_s_inode *root,
vfs_die ("find_linear: success but directory is not there\n"); vfs_die ("find_linear: success but directory is not there\n");
#if 0 #if 0
if (!vfs_s_resolve_symlink (me, ent, follow)) { if (!vfs_s_resolve_symlink (me, ent, follow))
{
g_free (path); g_free (path);
return NULL; return NULL;
} }
@ -438,7 +448,8 @@ vfs_s_insert_super (struct vfs_class *me, struct vfs_s_super *super)
static void static void
vfs_s_free_super (struct vfs_class *me, struct vfs_s_super *super) vfs_s_free_super (struct vfs_class *me, struct vfs_s_super *super)
{ {
if (super->root){ if (super->root)
{
vfs_s_free_inode (me, super->root); vfs_s_free_inode (me, super->root);
super->root = NULL; super->root = NULL;
} }
@ -447,14 +458,14 @@ vfs_s_free_super (struct vfs_class *me, struct vfs_s_super *super)
/* FIXME: We currently leak small ammount of memory, sometimes. Fix it if you can. */ /* FIXME: We currently leak small ammount of memory, sometimes. Fix it if you can. */
if (super->ino_usage) if (super->ino_usage)
message (D_ERROR, " Direntry warning ", message (D_ERROR, " Direntry warning ",
"Super ino_usage is %d, memory leak", "Super ino_usage is %d, memory leak", super->ino_usage);
super->ino_usage);
if (super->want_stale) if (super->want_stale)
message (D_ERROR, " Direntry warning ", "Super has want_stale set"); message (D_ERROR, " Direntry warning ", "Super has want_stale set");
#endif #endif
if (super->prevp){ if (super->prevp)
{
*super->prevp = super->next; *super->prevp = super->next;
if (super->next) if (super->next)
super->next->prevp = super->prevp; super->next->prevp = super->prevp;
@ -471,8 +482,7 @@ vfs_s_free_super (struct vfs_class *me, struct vfs_s_super *super)
* can be changed and the result may point inside the original string. * can be changed and the result may point inside the original string.
*/ */
const char * const char *
vfs_s_get_path_mangle (struct vfs_class *me, char *inname, vfs_s_get_path_mangle (struct vfs_class *me, char *inname, struct vfs_s_super **archive, int flags)
struct vfs_s_super **archive, int flags)
{ {
const char *retval; const char *retval;
char *local, *op; char *local, *op;
@ -489,10 +499,12 @@ vfs_s_get_path_mangle (struct vfs_class *me, char *inname,
if (!(cookie = MEDATA->archive_check (me, archive_name, op))) if (!(cookie = MEDATA->archive_check (me, archive_name, op)))
return NULL; return NULL;
for (super = MEDATA->supers; super != NULL; super = super->next) { for (super = MEDATA->supers; super != NULL; super = super->next)
{
/* 0 == other, 1 == same, return it, 2 == other but stop scanning */ /* 0 == other, 1 == same, return it, 2 == other but stop scanning */
int i = MEDATA->archive_same (me, super, archive_name, op, cookie); int i = MEDATA->archive_same (me, super, archive_name, op, cookie);
if (i != 0) { if (i != 0)
{
if (i == 1) if (i == 1)
goto return_success; goto return_success;
else else
@ -505,7 +517,8 @@ vfs_s_get_path_mangle (struct vfs_class *me, char *inname,
super = vfs_s_new_super (me); super = vfs_s_new_super (me);
result = MEDATA->open_archive (me, super, archive_name, op); result = MEDATA->open_archive (me, super, archive_name, op);
if (result == -1) { if (result == -1)
{
vfs_s_free_super (me, super); vfs_s_free_super (me, super);
ERRNOR (EIO, NULL); ERRNOR (EIO, NULL);
} }
@ -528,8 +541,7 @@ vfs_s_get_path_mangle (struct vfs_class *me, char *inname,
* The result should be freed. * The result should be freed.
*/ */
static char * static char *
vfs_s_get_path (struct vfs_class *me, const char *inname, vfs_s_get_path (struct vfs_class *me, const char *inname, struct vfs_s_super **archive, int flags)
struct vfs_s_super **archive, int flags)
{ {
char *buf, *retval; char *buf, *retval;
@ -542,7 +554,8 @@ vfs_s_get_path (struct vfs_class *me, const char *inname,
void void
vfs_s_invalidate (struct vfs_class *me, struct vfs_s_super *super) vfs_s_invalidate (struct vfs_class *me, struct vfs_s_super *super)
{ {
if (!super->want_stale){ if (!super->want_stale)
{
vfs_s_free_inode (me, super->root); vfs_s_free_inode (me, super->root);
super->root = vfs_s_new_inode (me, super, vfs_s_default_stat (me, S_IFDIR | 0755)); super->root = vfs_s_new_inode (me, super, vfs_s_default_stat (me, S_IFDIR | 0755));
} }
@ -554,11 +567,13 @@ vfs_s_fullpath (struct vfs_class *me, struct vfs_s_inode *ino)
if (!ino->ent) if (!ino->ent)
ERRNOR (EAGAIN, NULL); ERRNOR (EAGAIN, NULL);
if (!(MEDATA->flags & VFS_S_REMOTE)) { if (!(MEDATA->flags & VFS_S_REMOTE))
{
/* archives */ /* archives */
char *newpath; char *newpath;
char *path = g_strdup (ino->ent->name); char *path = g_strdup (ino->ent->name);
while (1) { while (1)
{
ino = ino->ent->dir; ino = ino->ent->dir;
if (ino == ino->super->root) if (ino == ino->super->root)
break; break;
@ -573,8 +588,7 @@ vfs_s_fullpath (struct vfs_class *me, struct vfs_s_inode *ino)
if ((!ino->ent->dir) || (!ino->ent->dir->ent)) if ((!ino->ent->dir) || (!ino->ent->dir->ent))
return g_strdup (ino->ent->name); return g_strdup (ino->ent->name);
return g_strconcat (ino->ent->dir->ent->name, PATH_SEP_STR, return g_strconcat (ino->ent->dir->ent->name, PATH_SEP_STR, ino->ent->name, (char *) NULL);
ino->ent->name, (char *) NULL);
} }
/* Support of archives */ /* Support of archives */
@ -592,20 +606,19 @@ vfs_s_inode_from_path (struct vfs_class *me, const char *name, int flags)
ino = ino =
vfs_s_find_inode (me, super, q, vfs_s_find_inode (me, super, q,
flags & FL_FOLLOW ? LINK_FOLLOW : LINK_NO_FOLLOW, flags & FL_FOLLOW ? LINK_FOLLOW : LINK_NO_FOLLOW, flags & ~FL_FOLLOW);
flags & ~FL_FOLLOW);
if ((!ino) && (!*q)) if ((!ino) && (!*q))
/* We are asking about / directory of ftp server: assume it exists */ /* We are asking about / directory of ftp server: assume it exists */
ino = ino =
vfs_s_find_inode (me, super, q, vfs_s_find_inode (me, super, q,
flags & FL_FOLLOW ? LINK_FOLLOW : flags & FL_FOLLOW ? LINK_FOLLOW :
LINK_NO_FOLLOW, LINK_NO_FOLLOW, FL_DIR | (flags & ~FL_FOLLOW));
FL_DIR | (flags & ~FL_FOLLOW));
g_free (q); g_free (q);
return ino; return ino;
} }
struct dirhandle { struct dirhandle
{
struct vfs_s_entry *cur; struct vfs_s_entry *cur;
struct vfs_s_inode *dir; struct vfs_s_inode *dir;
}; };
@ -643,9 +656,12 @@ vfs_s_readdir(void *data)
if (!(info->cur)) if (!(info->cur))
return NULL; return NULL;
if (info->cur->name) { if (info->cur->name)
{
g_strlcpy (dir.dent.d_name, info->cur->name, MC_MAXPATHLEN); g_strlcpy (dir.dent.d_name, info->cur->name, MC_MAXPATHLEN);
} else { }
else
{
vfs_die ("Null in structure-cannot happen"); vfs_die ("Null in structure-cannot happen");
} }
@ -744,18 +760,21 @@ vfs_s_open (struct vfs_class *me, const char *file, int flags, int mode)
if ((q = vfs_s_get_path (me, file, &super, 0)) == NULL) if ((q = vfs_s_get_path (me, file, &super, 0)) == NULL)
return NULL; return NULL;
ino = vfs_s_find_inode (me, super, q, LINK_FOLLOW, FL_NONE); ino = vfs_s_find_inode (me, super, q, LINK_FOLLOW, FL_NONE);
if (ino && ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))) { if (ino && ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)))
{
g_free (q); g_free (q);
ERRNOR (EEXIST, NULL); ERRNOR (EEXIST, NULL);
} }
if (!ino) { if (!ino)
{
char *dirname, *name, *save; char *dirname, *name, *save;
struct vfs_s_entry *ent; struct vfs_s_entry *ent;
struct vfs_s_inode *dir; struct vfs_s_inode *dir;
int tmp_handle; int tmp_handle;
/* If the filesystem is read-only, disable file creation */ /* If the filesystem is read-only, disable file creation */
if (!(flags & O_CREAT) || !(me->write)) { if (!(flags & O_CREAT) || !(me->write))
{
g_free (q); g_free (q);
return NULL; return NULL;
} }
@ -769,7 +788,8 @@ vfs_s_open (struct vfs_class *me, const char *file, int flags, int mode)
ino = ent->ino; ino = ent->ino;
vfs_s_insert_entry (me, dir, ent); vfs_s_insert_entry (me, dir, ent);
tmp_handle = vfs_mkstemps (&ino->localname, me->name, name); tmp_handle = vfs_mkstemps (&ino->localname, me->name, name);
if (tmp_handle == -1) { if (tmp_handle == -1)
{
g_free (q); g_free (q);
return NULL; return NULL;
} }
@ -789,20 +809,25 @@ vfs_s_open (struct vfs_class *me, const char *file, int flags, int mode)
fh->changed = was_changed; fh->changed = was_changed;
fh->linear = 0; fh->linear = 0;
if (IS_LINEAR (flags)) { if (IS_LINEAR (flags))
if (MEDATA->linear_start) { {
if (MEDATA->linear_start)
{
print_vfs_message (_("Starting linear transfer...")); print_vfs_message (_("Starting linear transfer..."));
fh->linear = LS_LINEAR_PREOPEN; fh->linear = LS_LINEAR_PREOPEN;
} }
} else if ((MEDATA->fh_open) }
&& (MEDATA->fh_open (me, fh, flags, mode))) { else if ((MEDATA->fh_open) && (MEDATA->fh_open (me, fh, flags, mode)))
{
g_free (fh); g_free (fh);
return NULL; return NULL;
} }
if (fh->ino->localname) { if (fh->ino->localname)
{
fh->handle = open (fh->ino->localname, NO_LINEAR (flags), mode); fh->handle = open (fh->ino->localname, NO_LINEAR (flags), mode);
if (fh->handle == -1) { if (fh->handle == -1)
{
g_free (fh); g_free (fh);
ERRNOR (errno, NULL); ERRNOR (errno, NULL);
} }
@ -821,7 +846,8 @@ vfs_s_read (void *fh, char *buffer, int count)
int n; int n;
struct vfs_class *me = FH_SUPER->me; struct vfs_class *me = FH_SUPER->me;
if (FH->linear == LS_LINEAR_PREOPEN) { if (FH->linear == LS_LINEAR_PREOPEN)
{
if (!MEDATA->linear_start (me, FH, FH->pos)) if (!MEDATA->linear_start (me, FH, FH->pos))
return -1; return -1;
} }
@ -832,7 +858,8 @@ vfs_s_read (void *fh, char *buffer, int count)
if (FH->linear == LS_LINEAR_OPEN) if (FH->linear == LS_LINEAR_OPEN)
return MEDATA->linear_read (me, FH, buffer, count); return MEDATA->linear_read (me, FH, buffer, count);
if (FH->handle != -1){ if (FH->handle != -1)
{
n = read (FH->handle, buffer, count); n = read (FH->handle, buffer, count);
if (n < 0) if (n < 0)
me->verrno = errno; me->verrno = errno;
@ -852,7 +879,8 @@ vfs_s_write (void *fh, const char *buffer, int count)
vfs_die ("no writing to linear files, please"); vfs_die ("no writing to linear files, please");
FH->changed = 1; FH->changed = 1;
if (FH->handle != -1){ if (FH->handle != -1)
{
n = write (FH->handle, buffer, count); n = write (FH->handle, buffer, count);
if (n < 0) if (n < 0)
me->verrno = errno; me->verrno = errno;
@ -870,18 +898,22 @@ vfs_s_lseek (void *fh, off_t offset, int whence)
if (FH->linear == LS_LINEAR_OPEN) if (FH->linear == LS_LINEAR_OPEN)
vfs_die ("cannot lseek() after linear_read!"); vfs_die ("cannot lseek() after linear_read!");
if (FH->handle != -1){ /* If we have local file opened, we want to work with it */ if (FH->handle != -1)
{ /* If we have local file opened, we want to work with it */
int retval = lseek (FH->handle, offset, whence); int retval = lseek (FH->handle, offset, whence);
if (retval == -1) if (retval == -1)
FH->ino->super->me->verrno = errno; FH->ino->super->me->verrno = errno;
return retval; return retval;
} }
switch (whence){ switch (whence)
{
case SEEK_CUR: case SEEK_CUR:
offset += FH->pos; break; offset += FH->pos;
break;
case SEEK_END: case SEEK_END:
offset += size; break; offset += size;
break;
} }
if (offset < 0) if (offset < 0)
FH->pos = 0; FH->pos = 0;
@ -906,11 +938,13 @@ vfs_s_close (void *fh)
MEDATA->linear_close (me, fh); MEDATA->linear_close (me, fh);
if (MEDATA->fh_close) if (MEDATA->fh_close)
res = MEDATA->fh_close (me, fh); res = MEDATA->fh_close (me, fh);
if (FH->changed && MEDATA->file_store){ if (FH->changed && MEDATA->file_store)
{
char *s = vfs_s_fullpath (me, FH->ino); char *s = vfs_s_fullpath (me, FH->ino);
if (!s) if (!s)
res = -1; res = -1;
else { else
{
res = MEDATA->file_store (me, fh, s, FH->ino->localname); res = MEDATA->file_store (me, fh, s, FH->ino->localname);
g_free (s); g_free (s);
} }
@ -931,19 +965,17 @@ vfs_s_print_stats (const char *fs_name, const char *action,
static const char *i18n_percent_transf_format = NULL; static const char *i18n_percent_transf_format = NULL;
static const char *i18n_transf_format = NULL; static const char *i18n_transf_format = NULL;
if (i18n_percent_transf_format == NULL) { if (i18n_percent_transf_format == NULL)
i18n_percent_transf_format = {
_("%s: %s: %s %3d%% (%lu bytes transferred)"); i18n_percent_transf_format = _("%s: %s: %s %3d%% (%lu bytes transferred)");
i18n_transf_format = _("%s: %s: %s %lu bytes transferred"); i18n_transf_format = _("%s: %s: %s %lu bytes transferred");
} }
if (need) if (need)
print_vfs_message (i18n_percent_transf_format, fs_name, action, print_vfs_message (i18n_percent_transf_format, fs_name, action,
file_name, (int) ((double) have * 100 / need), file_name, (int) ((double) have * 100 / need), (unsigned long) have);
(unsigned long) have);
else else
print_vfs_message (i18n_transf_format, fs_name, action, file_name, print_vfs_message (i18n_transf_format, fs_name, action, file_name, (unsigned long) have);
(unsigned long) have);
} }
int int
@ -962,7 +994,8 @@ vfs_s_retrieve_file (struct vfs_class *me, struct vfs_s_inode *ino)
fh.handle = -1; fh.handle = -1;
handle = vfs_mkstemps (&ino->localname, me->name, ino->ent->name); handle = vfs_mkstemps (&ino->localname, me->name, ino->ent->name);
if (handle == -1) { if (handle == -1)
{
me->verrno = errno; me->verrno = errno;
goto error_4; goto error_4;
} }
@ -974,20 +1007,21 @@ vfs_s_retrieve_file (struct vfs_class *me, struct vfs_s_inode *ino)
tty_got_interrupt (); tty_got_interrupt ();
tty_enable_interrupt_key (); tty_enable_interrupt_key ();
while ((n = MEDATA->linear_read (me, &fh, buffer, sizeof (buffer)))) { while ((n = MEDATA->linear_read (me, &fh, buffer, sizeof (buffer))))
{
int t; int t;
if (n < 0) if (n < 0)
goto error_1; goto error_1;
total += n; total += n;
vfs_s_print_stats (me->name, _("Getting file"), ino->ent->name, vfs_s_print_stats (me->name, _("Getting file"), ino->ent->name, total, stat_size);
total, stat_size);
if (tty_got_interrupt ()) if (tty_got_interrupt ())
goto error_1; goto error_1;
t = write (handle, buffer, n); t = write (handle, buffer, n);
if (t != n) { if (t != n)
{
if (t == -1) if (t == -1)
me->verrno = errno; me->verrno = errno;
goto error_1; goto error_1;
@ -1019,7 +1053,8 @@ vfs_s_fill_names (struct vfs_class *me, fill_names_f func)
struct vfs_s_super *a = MEDATA->supers; struct vfs_s_super *a = MEDATA->supers;
char *name; char *name;
while (a){ while (a)
{
name = g_strconcat (a->name, "#", me->prefix, "/", name = g_strconcat (a->name, "#", me->prefix, "/",
/* a->current_dir->name, */ (char *) NULL); /* a->current_dir->name, */ (char *) NULL);
(*func) (name); (*func) (name);
@ -1042,14 +1077,18 @@ static char *
vfs_s_getlocalcopy (struct vfs_class *me, const char *path) vfs_s_getlocalcopy (struct vfs_class *me, const char *path)
{ {
struct vfs_s_fh *fh; struct vfs_s_fh *fh;
char *local; char *local = NULL;
fh = vfs_s_open (me, path, O_RDONLY, 0); fh = vfs_s_open (me, path, O_RDONLY, 0);
if (!fh || !fh->ino || !fh->ino->localname)
return NULL;
if (fh != NULL)
{
if ((fh->ino != NULL) && (fh->ino->localname != NULL))
local = g_strdup (fh->ino->localname); local = g_strdup (fh->ino->localname);
vfs_s_close (fh); vfs_s_close (fh);
}
return local; return local;
} }
@ -1058,8 +1097,7 @@ vfs_s_getlocalcopy (struct vfs_class *me, const char *path)
* the cache will be removed when the archive is closed. * the cache will be removed when the archive is closed.
*/ */
static int static int
vfs_s_ungetlocalcopy (struct vfs_class *me, const char *path, vfs_s_ungetlocalcopy (struct vfs_class *me, const char *path, const char *local, int has_changed)
const char *local, int has_changed)
{ {
(void) me; (void) me;
(void) path; (void) path;
@ -1071,7 +1109,8 @@ vfs_s_ungetlocalcopy (struct vfs_class *me, const char *path,
static int static int
vfs_s_setctl (struct vfs_class *me, const char *path, int ctlop, void *arg) vfs_s_setctl (struct vfs_class *me, const char *path, int ctlop, void *arg)
{ {
switch (ctlop) { switch (ctlop)
{
case VFS_SETCTL_STALE_DATA: case VFS_SETCTL_STALE_DATA:
{ {
struct vfs_s_inode *ino = vfs_s_inode_from_path (me, path, 0); struct vfs_s_inode *ino = vfs_s_inode_from_path (me, path, 0);
@ -1080,7 +1119,8 @@ vfs_s_setctl (struct vfs_class *me, const char *path, int ctlop, void *arg)
return 0; return 0;
if (arg) if (arg)
ino->super->want_stale = 1; ino->super->want_stale = 1;
else { else
{
ino->super->want_stale = 0; ino->super->want_stale = 0;
vfs_s_invalidate (me, ino->super); vfs_s_invalidate (me, ino->super);
} }
@ -1130,7 +1170,8 @@ vfs_s_dir_uptodate (struct vfs_class *me, struct vfs_s_inode *ino)
{ {
struct timeval tim; struct timeval tim;
if (MEDATA->flush) { if (MEDATA->flush)
{
MEDATA->flush = 0; MEDATA->flush = 0;
return 0; return 0;
} }
@ -1150,7 +1191,8 @@ vfs_s_init_class (struct vfs_class *vclass, struct vfs_s_subclass *sub)
vclass->open = vfs_s_open; vclass->open = vfs_s_open;
vclass->close = vfs_s_close; vclass->close = vfs_s_close;
vclass->read = vfs_s_read; vclass->read = vfs_s_read;
if (!(sub->flags & VFS_S_READONLY)) { if (!(sub->flags & VFS_S_READONLY))
{
vclass->write = vfs_s_write; vclass->write = vfs_s_write;
} }
vclass->opendir = vfs_s_opendir; vclass->opendir = vfs_s_opendir;
@ -1166,11 +1208,14 @@ vfs_s_init_class (struct vfs_class *vclass, struct vfs_s_subclass *sub)
vclass->getid = vfs_s_getid; vclass->getid = vfs_s_getid;
vclass->nothingisopen = vfs_s_nothingisopen; vclass->nothingisopen = vfs_s_nothingisopen;
vclass->free = vfs_s_free; vclass->free = vfs_s_free;
if (sub->flags & VFS_S_REMOTE) { if (sub->flags & VFS_S_REMOTE)
{
vclass->getlocalcopy = vfs_s_getlocalcopy; vclass->getlocalcopy = vfs_s_getlocalcopy;
vclass->ungetlocalcopy = vfs_s_ungetlocalcopy; vclass->ungetlocalcopy = vfs_s_ungetlocalcopy;
sub->find_entry = vfs_s_find_entry_linear; sub->find_entry = vfs_s_find_entry_linear;
} else { }
else
{
sub->find_entry = vfs_s_find_entry_tree; sub->find_entry = vfs_s_find_entry_tree;
} }
vclass->setctl = vfs_s_setctl; vclass->setctl = vfs_s_setctl;
@ -1210,14 +1255,17 @@ vfs_s_get_line (struct vfs_class *me, int sock, char *buf, int buf_len, char ter
int i; int i;
char c; char c;
for (i = 0; i < buf_len - 1; i++, buf++){ for (i = 0; i < buf_len - 1; i++, buf++)
{
if (read (sock, buf, sizeof (char)) <= 0) if (read (sock, buf, sizeof (char)) <= 0)
return 0; return 0;
if (logfile){ if (logfile)
{
fwrite (buf, 1, 1, logfile); fwrite (buf, 1, 1, logfile);
fflush (logfile); fflush (logfile);
} }
if (*buf == term){ if (*buf == term)
{
*buf = 0; *buf = 0;
return 1; return 1;
} }
@ -1225,8 +1273,10 @@ vfs_s_get_line (struct vfs_class *me, int sock, char *buf, int buf_len, char ter
/* Line is too long - terminate buffer and discard the rest of line */ /* Line is too long - terminate buffer and discard the rest of line */
*buf = 0; *buf = 0;
while (read (sock, &c, sizeof (c)) > 0) { while (read (sock, &c, sizeof (c)) > 0)
if (logfile){ {
if (logfile)
{
fwrite (&c, 1, 1, logfile); fwrite (&c, 1, 1, logfile);
fflush (logfile); fflush (logfile);
} }
@ -1245,18 +1295,22 @@ vfs_s_get_line_interruptible (struct vfs_class *me, char *buffer, int size, int
(void) me; (void) me;
tty_enable_interrupt_key (); tty_enable_interrupt_key ();
for (i = 0; i < size-1; i++){ for (i = 0; i < size - 1; i++)
{
n = read (fd, buffer + i, 1); n = read (fd, buffer + i, 1);
tty_disable_interrupt_key (); tty_disable_interrupt_key ();
if (n == -1 && errno == EINTR){ if (n == -1 && errno == EINTR)
{
buffer[i] = 0; buffer[i] = 0;
return EINTR; return EINTR;
} }
if (n == 0){ if (n == 0)
{
buffer[i] = 0; buffer[i] = 0;
return 0; return 0;
} }
if (buffer [i] == '\n'){ if (buffer[i] == '\n')
{
buffer[i] = 0; buffer[i] = 0;
return 1; return 1;
} }

Просмотреть файл

@ -99,46 +99,53 @@ static struct vfs_class vfs_fish_ops;
static int static int
fish_command (struct vfs_class *me, struct vfs_s_super *super, fish_command (struct vfs_class *me, struct vfs_s_super *super,
int wait_reply, const char *fmt, ...) int wait_reply, const char *fmt, ...) __attribute__ ((format (__printf__, 4, 5)));
__attribute__ ((format (__printf__, 4, 5)));
static int fish_decode_reply (char *s, int was_garbage) static int
fish_decode_reply (char *s, int was_garbage)
{ {
int code; int code;
if (!sscanf(s, "%d", &code)) { if (!sscanf (s, "%d", &code))
{
code = 500; code = 500;
return 5; return 5;
} }
if (code<100) return was_garbage ? ERROR : (!code ? COMPLETE : PRELIM); if (code < 100)
return was_garbage ? ERROR : (!code ? COMPLETE : PRELIM);
return code / 100; return code / 100;
} }
/* Returns a reply code, check /usr/include/arpa/ftp.h for possible values */ /* Returns a reply code, check /usr/include/arpa/ftp.h for possible values */
static int fish_get_reply (struct vfs_class *me, int sock, char *string_buf, int string_len) static int
fish_get_reply (struct vfs_class *me, int sock, char *string_buf, int string_len)
{ {
char answer[1024]; char answer[1024];
int was_garbage = 0; int was_garbage = 0;
for (;;) { for (;;)
if (!vfs_s_get_line(me, sock, answer, sizeof(answer), '\n')) { {
if (!vfs_s_get_line (me, sock, answer, sizeof (answer), '\n'))
{
if (string_buf) if (string_buf)
*string_buf = 0; *string_buf = 0;
return 4; return 4;
} }
if (strncmp(answer, "### ", 4)) { if (strncmp (answer, "### ", 4))
{
was_garbage = 1; was_garbage = 1;
if (string_buf) if (string_buf)
g_strlcpy (string_buf, answer, string_len); g_strlcpy (string_buf, answer, string_len);
} else return fish_decode_reply(answer+4, was_garbage); }
else
return fish_decode_reply (answer + 4, was_garbage);
} }
} }
#define SUP super->u.fish #define SUP super->u.fish
static int static int
fish_command (struct vfs_class *me, struct vfs_s_super *super, fish_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply, const char *fmt, ...)
int wait_reply, const char *fmt, ...)
{ {
va_list ap; va_list ap;
char *str; char *str;
@ -150,7 +157,8 @@ fish_command (struct vfs_class *me, struct vfs_s_super *super,
str = g_strdup_vprintf (fmt, ap); str = g_strdup_vprintf (fmt, ap);
va_end (ap); va_end (ap);
if (logfile) { if (logfile)
{
fwrite (str, strlen (str), 1, logfile); fwrite (str, strlen (str), 1, logfile);
fflush (logfile); fflush (logfile);
} }
@ -174,9 +182,9 @@ fish_command (struct vfs_class *me, struct vfs_s_super *super,
static void static void
fish_free_archive (struct vfs_class *me, struct vfs_s_super *super) fish_free_archive (struct vfs_class *me, struct vfs_s_super *super)
{ {
if ((SUP.sockw != -1) || (SUP.sockr != -1)) { if ((SUP.sockw != -1) || (SUP.sockr != -1))
print_vfs_message (_("fish: Disconnecting from %s"), {
super->name ? super->name : "???"); print_vfs_message (_("fish: Disconnecting from %s"), super->name ? super->name : "???");
fish_command (me, super, NONE, "#BYE\nexit\n"); fish_command (me, super, NONE, "#BYE\nexit\n");
close (SUP.sockw); close (SUP.sockw);
close (SUP.sockr); close (SUP.sockr);
@ -197,29 +205,37 @@ fish_pipeopen(struct vfs_s_super *super, const char *path, const char *argv[])
if ((pipe (fileset1) < 0) || (pipe (fileset2) < 0)) if ((pipe (fileset1) < 0) || (pipe (fileset2) < 0))
vfs_die ("Cannot pipe(): %m."); vfs_die ("Cannot pipe(): %m.");
if ((res = fork())) { if ((res = fork ()))
if (res<0) vfs_die("Cannot fork(): %m."); {
if (res < 0)
vfs_die ("Cannot fork(): %m.");
/* We are the parent */ /* We are the parent */
close (fileset1[0]); close (fileset1[0]);
SUP.sockw = fileset1[1]; SUP.sockw = fileset1[1];
close (fileset2[1]); close (fileset2[1]);
SUP.sockr = fileset2[0]; SUP.sockr = fileset2[0];
} else { }
else
{
close (0); close (0);
dup (fileset1[0]); dup (fileset1[0]);
close(fileset1[0]); close(fileset1[1]); close (fileset1[0]);
close(1); close(2); close (fileset1[1]);
close (1);
close (2);
dup (fileset2[1]); dup (fileset2[1]);
/* stderr to /dev/null */ /* stderr to /dev/null */
open ("/dev/null", O_WRONLY); open ("/dev/null", O_WRONLY);
close(fileset2[0]); close(fileset2[1]); close (fileset2[0]);
close (fileset2[1]);
execvp (path, const_cast (char **, argv)); execvp (path, const_cast (char **, argv));
_exit (3); _exit (3);
} }
} }
/* The returned directory should always contain a trailing slash */ /* The returned directory should always contain a trailing slash */
static char *fish_getcwd(struct vfs_class *me, struct vfs_s_super *super) static char *
fish_getcwd (struct vfs_class *me, struct vfs_s_super *super)
{ {
if (fish_command (me, super, WANT_STRING, "#PWD\npwd; echo '### 200'\n") == COMPLETE) if (fish_command (me, super, WANT_STRING, "#PWD\npwd; echo '### 200'\n") == COMPLETE)
return g_strconcat (reply_str, "/", (char *) NULL); return g_strconcat (reply_str, "/", (char *) NULL);
@ -253,7 +269,8 @@ fish_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
* option breaks it for some) * option breaks it for some)
*/ */
if (SUP.user) { if (SUP.user)
{
argv[i++] = "-l"; argv[i++] = "-l";
argv[i++] = SUP.user; argv[i++] = SUP.user;
} }
@ -275,19 +292,19 @@ fish_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
if (!vfs_s_get_line (me, SUP.sockr, answer, sizeof (answer), ':')) if (!vfs_s_get_line (me, SUP.sockr, answer, sizeof (answer), ':'))
ERRNOR (E_PROTO, -1); ERRNOR (E_PROTO, -1);
print_vfs_message ("%s", answer); print_vfs_message ("%s", answer);
if (strstr (answer, "assword")) { if (strstr (answer, "assword"))
{
/* Currently, this does not work. ssh reads passwords from /* Currently, this does not work. ssh reads passwords from
/dev/tty, not from stdin :-(. */ /dev/tty, not from stdin :-(. */
message (D_ERROR, MSG_ERROR, message (D_ERROR, MSG_ERROR,
_ _("Sorry, we cannot do password authenticated connections for now."));
("Sorry, we cannot do password authenticated connections for now."));
ERRNOR (EPERM, -1); ERRNOR (EPERM, -1);
if (!SUP.password) { if (!SUP.password)
{
char *p, *op; char *p, *op;
p = g_strconcat (_(" fish: Password required for "), p = g_strconcat (_(" fish: Password required for "), SUP.user, " ", (char *) NULL);
SUP.user, " ", (char *) NULL);
op = vfs_get_password (p); op = vfs_get_password (p);
g_free (p); g_free (p);
if (op == NULL) if (op == NULL)
@ -307,36 +324,29 @@ fish_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
*/ */
if (fish_command if (fish_command
(me, super, WAIT_REPLY, (me, super, WAIT_REPLY,
"#FISH\necho; start_fish_server 2>&1; echo '### 200'\n") != "#FISH\necho; start_fish_server 2>&1; echo '### 200'\n") != COMPLETE)
COMPLETE)
ERRNOR (E_PROTO, -1); ERRNOR (E_PROTO, -1);
print_vfs_message (_("fish: Handshaking version...")); print_vfs_message (_("fish: Handshaking version..."));
if (fish_command if (fish_command (me, super, WAIT_REPLY, "#VER 0.0.0\necho '### 000'\n") != COMPLETE)
(me, super, WAIT_REPLY,
"#VER 0.0.0\necho '### 000'\n") != COMPLETE)
ERRNOR (E_PROTO, -1); ERRNOR (E_PROTO, -1);
/* Set up remote locale to C, otherwise dates cannot be recognized */ /* Set up remote locale to C, otherwise dates cannot be recognized */
if (fish_command if (fish_command
(me, super, WAIT_REPLY, (me, super, WAIT_REPLY,
"LANG=C; LC_ALL=C; LC_TIME=C\n" "LANG=C; LC_ALL=C; LC_TIME=C\n"
"export LANG; export LC_ALL; export LC_TIME\n" "echo '### 200'\n") "export LANG; export LC_ALL; export LC_TIME\n" "echo '### 200'\n") != COMPLETE)
!= COMPLETE)
ERRNOR (E_PROTO, -1); ERRNOR (E_PROTO, -1);
print_vfs_message (_("fish: Setting up current directory...")); print_vfs_message (_("fish: Setting up current directory..."));
SUP.cwdir = fish_getcwd (me, super); SUP.cwdir = fish_getcwd (me, super);
print_vfs_message (_("fish: Connected, home %s."), SUP.cwdir); print_vfs_message (_("fish: Connected, home %s."), SUP.cwdir);
#if 0 #if 0
super->name = super->name = g_strconcat ("/#sh:", SUP.user, "@", SUP.host, "/", (char *) NULL);
g_strconcat ("/#sh:", SUP.user, "@", SUP.host, "/", (char *) NULL);
#endif #endif
super->name = g_strdup (PATH_SEP_STR); super->name = g_strdup (PATH_SEP_STR);
super->root = super->root = vfs_s_new_inode (me, super, vfs_s_default_stat (me, S_IFDIR | 0755));
vfs_s_new_inode (me, super,
vfs_s_default_stat (me, S_IFDIR | 0755));
return 0; return 0;
} }
@ -386,8 +396,7 @@ fish_archive_same (struct vfs_class *me, struct vfs_s_super *super,
user = vfs_get_local_username (); user = vfs_get_local_username ();
result = ((strcmp (host, SUP.host) == 0) result = ((strcmp (host, SUP.host) == 0)
&& (strcmp (user, SUP.user) == 0) && (strcmp (user, SUP.user) == 0) && (flags == SUP.flags));
&& (flags == SUP.flags));
g_free (host); g_free (host);
g_free (user); g_free (user);
@ -423,6 +432,7 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
gettimeofday (&dir->timestamp, NULL); gettimeofday (&dir->timestamp, NULL);
dir->timestamp.tv_sec += fish_directory_timeout; dir->timestamp.tv_sec += fish_directory_timeout;
quoted_path = strutils_shell_escape (remote_path); quoted_path = strutils_shell_escape (remote_path);
/* *INDENT-OFF* */
shell_commands = g_strconcat ( shell_commands = g_strconcat (
"#LIST /%s\n" "#LIST /%s\n"
"if `perl -v > /dev/null 2>&1` ; then\n" "if `perl -v > /dev/null 2>&1` ; then\n"
@ -445,8 +455,7 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
"my $linkname = readlink (\"$dirname/$filename\");\n" "my $linkname = readlink (\"$dirname/$filename\");\n"
"$linkname =~ $strutils_shell_escape_regex;\n" "$linkname =~ $strutils_shell_escape_regex;\n"
"\n" "\n"
"printf(\"R%%o %%o $uid.$gid\\n" "printf(\"R%%o %%o $uid.$gid\\n" "S$size\\n"
"S$size\\n"
"d$mloctime\\n" "d$mloctime\\n"
":\\\"$e_filename\\\" -> \\\"$linkname\\\"\\n" ":\\\"$e_filename\\\" -> \\\"$linkname\\\"\\n"
"\\n\", S_IMODE($mode), S_IFMT($mode));\n" "\\n\", S_IMODE($mode), S_IFMT($mode));\n"
@ -484,8 +493,7 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
"if [ $ADD = 0 ]; then\n" "if [ $ADD = 0 ]; then\n"
"echo \"P$p $u.$g\nS$s\nd$m $d $y\n:$n\n\"\n" "echo \"P$p $u.$g\nS$s\nd$m $d $y\n:$n\n\"\n"
"elif `sed --version >/dev/null 2>&1` ; then\n" "elif `sed --version >/dev/null 2>&1` ; then\n"
"file=`echo $n | sed -e 's#^\\(.*\\) -> \\(.*\\)#\\1\" -> \"\\2#'`\n" "file=`echo $n | sed -e 's#^\\(.*\\) -> \\(.*\\)#\\1\" -> \"\\2#'`\n",
,
"echo \"P$p $u $g\nS$s\nd$m $d $y\n:\"$file\"\n\"\n" "echo \"P$p $u $g\nS$s\nd$m $d $y\n:\"$file\"\n\"\n"
"else\n" "else\n"
"echo \"P$p $u $g\nS$s\nd$m $d $y\n:\"$n\"\n\"\n" "echo \"P$p $u $g\nS$s\nd$m $d $y\n:\"$n\"\n\"\n"
@ -511,8 +519,9 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
"else\n" "else\n"
"echo '### 500'\n" "echo '### 500'\n"
"fi\n" "fi\n"
, (char *) NULL ,
); (char *) NULL);
/* *INDENT-ON* */
fish_command (me, super, NONE, shell_commands, fish_command (me, super, NONE, shell_commands,
quoted_path, quoted_path, quoted_path, quoted_path, quoted_path, quoted_path); quoted_path, quoted_path, quoted_path, quoted_path, quoted_path, quoted_path);
@ -520,22 +529,27 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
g_free (shell_commands); g_free (shell_commands);
g_free (quoted_path); g_free (quoted_path);
ent = vfs_s_generate_entry (me, NULL, dir, 0); ent = vfs_s_generate_entry (me, NULL, dir, 0);
while (1) { while (1)
{
int res = vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), SUP.sockr); int res = vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), SUP.sockr);
if ((!res) || (res == EINTR)) { if ((!res) || (res == EINTR))
{
vfs_s_free_entry (me, ent); vfs_s_free_entry (me, ent);
me->verrno = ECONNRESET; me->verrno = ECONNRESET;
goto error; goto error;
} }
if (logfile) { if (logfile)
{
fputs (buffer, logfile); fputs (buffer, logfile);
fputs ("\n", logfile); fputs ("\n", logfile);
fflush (logfile); fflush (logfile);
} }
if (!strncmp (buffer, "### ", 4)) if (!strncmp (buffer, "### ", 4))
break; break;
if ((!buffer[0])) { if ((!buffer[0]))
if (ent->name) { {
if (ent->name)
{
vfs_s_insert_entry (me, dir, ent); vfs_s_insert_entry (me, dir, ent);
ent = vfs_s_generate_entry (me, NULL, dir, 0); ent = vfs_s_generate_entry (me, NULL, dir, 0);
} }
@ -544,8 +558,10 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
#define ST ent->ino->st #define ST ent->ino->st
switch(buffer[0]) { switch (buffer[0])
case ':': { {
case ':':
{
char *temp; char *temp;
char *data_start = buffer + 1; char *data_start = buffer + 1;
char *filename = data_start; char *filename = data_start;
@ -555,7 +571,8 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
if (!strcmp (data_start, "\".\"") || !strcmp (data_start, "\"..\"")) if (!strcmp (data_start, "\".\"") || !strcmp (data_start, "\"..\""))
break; /* We'll do "." and ".." ourselves */ break; /* We'll do "." and ".." ourselves */
if (S_ISLNK(ST.st_mode)) { if (S_ISLNK (ST.st_mode))
{
/* we expect: "escaped-name" -> "escaped-name" /* we expect: "escaped-name" -> "escaped-name"
// -> cannot occur in filenames, // -> cannot occur in filenames,
// because it will be escaped to -\> */ // because it will be escaped to -\> */
@ -568,8 +585,7 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
{ {
/* broken client, or smth goes wrong */ /* broken client, or smth goes wrong */
linkname = filename_bound; linkname = filename_bound;
if (filename_bound > filename if (filename_bound > filename && *(filename_bound - 1) == '"')
&& *(filename_bound - 1) == '"')
--filename_bound; /* skip trailing " */ --filename_bound; /* skip trailing " */
} }
else else
@ -589,7 +605,9 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
temp = ent->ino->linkname; temp = ent->ino->linkname;
ent->ino->linkname = strutils_shell_unescape (ent->ino->linkname); ent->ino->linkname = strutils_shell_unescape (ent->ino->linkname);
g_free (temp); g_free (temp);
} else { }
else
{
/* we expect: "escaped-name" */ /* we expect: "escaped-name" */
if (filename_bound - filename > 2) if (filename_bound - filename > 2)
{ {
@ -616,12 +634,14 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
ST.st_size = (off_t) atof (buffer + 1); ST.st_size = (off_t) atof (buffer + 1);
#endif #endif
break; break;
case 'P': { case 'P':
{
size_t skipped; size_t skipped;
vfs_parse_filemode (buffer + 1, &skipped, &ST.st_mode); vfs_parse_filemode (buffer + 1, &skipped, &ST.st_mode);
break; break;
} }
case 'R': { case 'R':
{
/* /*
raw filemode: raw filemode:
we expect: Roctal-filemode octal-filetype uid.gid we expect: Roctal-filemode octal-filetype uid.gid
@ -630,14 +650,16 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
vfs_parse_raw_filemode (buffer + 1, &skipped, &ST.st_mode); vfs_parse_raw_filemode (buffer + 1, &skipped, &ST.st_mode);
break; break;
} }
case 'd': { case 'd':
{
vfs_split_text (buffer + 1); vfs_split_text (buffer + 1);
if (!vfs_parse_filedate (0, &ST.st_ctime)) if (!vfs_parse_filedate (0, &ST.st_ctime))
break; break;
ST.st_atime = ST.st_mtime = ST.st_ctime; ST.st_atime = ST.st_mtime = ST.st_ctime;
} }
break; break;
case 'D': { case 'D':
{
struct tm tim; struct tm tim;
if (sscanf (buffer + 1, "%d %d %d %d %d %d", &tim.tm_year, &tim.tm_mon, if (sscanf (buffer + 1, "%d %d %d %d %d %d", &tim.tm_year, &tim.tm_mon,
&tim.tm_mday, &tim.tm_hour, &tim.tm_min, &tim.tm_sec) != 6) &tim.tm_mday, &tim.tm_hour, &tim.tm_min, &tim.tm_sec) != 6)
@ -645,7 +667,8 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
ST.st_atime = ST.st_mtime = ST.st_ctime = mktime (&tim); ST.st_atime = ST.st_mtime = ST.st_ctime = mktime (&tim);
} }
break; break;
case 'E': { case 'E':
{
int maj, min; int maj, min;
if (sscanf (buffer + 1, "%d,%d", &maj, &min) != 2) if (sscanf (buffer + 1, "%d,%d", &maj, &min) != 2)
break; break;
@ -658,14 +681,19 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
vfs_s_free_entry (me, ent); vfs_s_free_entry (me, ent);
reply_code = fish_decode_reply (buffer + 4, 0); reply_code = fish_decode_reply (buffer + 4, 0);
if (reply_code == COMPLETE) { if (reply_code == COMPLETE)
{
g_free (SUP.cwdir); g_free (SUP.cwdir);
SUP.cwdir = g_strdup (remote_path); SUP.cwdir = g_strdup (remote_path);
print_vfs_message (_("%s: done."), me->name); print_vfs_message (_("%s: done."), me->name);
return 0; return 0;
} else if (reply_code == ERROR) { }
else if (reply_code == ERROR)
{
me->verrno = EACCES; me->verrno = EACCES;
} else { }
else
{
me->verrno = E_REMOTE; me->verrno = E_REMOTE;
} }
@ -689,7 +717,8 @@ fish_file_store(struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *loc
if (h == -1) if (h == -1)
ERRNOR (EIO, -1); ERRNOR (EIO, -1);
if (fstat(h, &s)<0) { if (fstat (h, &s) < 0)
{
close (h); close (h);
ERRNOR (EIO, -1); ERRNOR (EIO, -1);
} }
@ -728,6 +757,7 @@ fish_file_store(struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *loc
/* FIXME: File size is limited to ULONG_MAX */ /* FIXME: File size is limited to ULONG_MAX */
if (!fh->u.fish.append) if (!fh->u.fish.append)
/* *INDENT-OFF* */
n = fish_command (me, super, WAIT_REPLY, n = fish_command (me, super, WAIT_REPLY,
"#STOR %lu /%s\n" "#STOR %lu /%s\n"
"echo '### 001'\n" "echo '### 001'\n"
@ -749,9 +779,10 @@ fish_file_store(struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *loc
"done\n" "done\n"
"}; echo '### 200'\n", "}; echo '### 200'\n",
(unsigned long) s.st_size, quoted_name, (unsigned long) s.st_size, quoted_name,
quoted_name, (unsigned long) s.st_size, quoted_name, (unsigned long) s.st_size, (unsigned long) s.st_size);
(unsigned long) s.st_size); /* *INDENT-ON* */
else else
/* *INDENT-OFF* */
n = fish_command (me, super, WAIT_REPLY, n = fish_command (me, super, WAIT_REPLY,
"#STOR %lu /%s\n" "#STOR %lu /%s\n"
"echo '### 001'\n" "echo '### 001'\n"
@ -767,16 +798,21 @@ fish_file_store(struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *loc
"}; echo '### 200'\n", "}; echo '### 200'\n",
(unsigned long) s.st_size, quoted_name, (unsigned long) s.st_size, quoted_name,
quoted_name, (unsigned long) s.st_size); quoted_name, (unsigned long) s.st_size);
/* *INDENT-ON* */
if (n != PRELIM) { if (n != PRELIM)
{
close (h); close (h);
ERRNOR (E_REMOTE, -1); ERRNOR (E_REMOTE, -1);
} }
total = 0; total = 0;
while (1) { while (1)
{
int t; int t;
while ((n = read(h, buffer, sizeof(buffer))) < 0) { while ((n = read (h, buffer, sizeof (buffer))) < 0)
{
if ((errno == EINTR) && tty_got_interrupt ()) if ((errno == EINTR) && tty_got_interrupt ())
continue; continue;
print_vfs_message (_("fish: Local read failed, sending zeros")); print_vfs_message (_("fish: Local read failed, sending zeros"));
@ -785,10 +821,14 @@ fish_file_store(struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *loc
} }
if (n == 0) if (n == 0)
break; break;
if ((t = write (SUP.sockw, buffer, n)) != n) { if ((t = write (SUP.sockw, buffer, n)) != n)
if (t == -1) { {
if (t == -1)
{
me->verrno = errno; me->verrno = errno;
} else { }
else
{
me->verrno = EIO; me->verrno = EIO;
} }
goto error_return; goto error_return;
@ -796,8 +836,7 @@ fish_file_store(struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *loc
tty_disable_interrupt_key (); tty_disable_interrupt_key ();
total += n; total += n;
print_vfs_message (_("fish: storing %s %d (%lu)"), print_vfs_message (_("fish: storing %s %d (%lu)"),
was_error ? _("zeros") : _("file"), total, was_error ? _("zeros") : _("file"), total, (unsigned long) s.st_size);
(unsigned long) s.st_size);
} }
close (h); close (h);
g_free (quoted_name); g_free (quoted_name);
@ -819,9 +858,10 @@ fish_linear_start (struct vfs_class *me, struct vfs_s_fh *fh, off_t offset)
if (offset) if (offset)
ERRNOR (E_NOTSUPP, 0); ERRNOR (E_NOTSUPP, 0);
name = vfs_s_fullpath (me, fh->ino); name = vfs_s_fullpath (me, fh->ino);
if (!name) if (name == NULL)
return 0; return 0;
quoted_name = strutils_shell_escape (name); quoted_name = strutils_shell_escape (name);
g_free (name);
fh->u.fish.append = 0; fh->u.fish.append = 0;
/* /*
@ -830,6 +870,7 @@ fish_linear_start (struct vfs_class *me, struct vfs_s_fh *fh, off_t offset)
* with exit status of 0 use `cat' to send the file contents to the * with exit status of 0 use `cat' to send the file contents to the
* standard output (i.e. over the network). * standard output (i.e. over the network).
*/ */
/* *INDENT-OFF* */
offset = fish_command (me, FH_SUPER, WANT_STRING, offset = fish_command (me, FH_SUPER, WANT_STRING,
"#RETR /%s\n" "#RETR /%s\n"
"if dd if=/%s of=/dev/null bs=1 count=1 2>/dev/null ;\n" "if dd if=/%s of=/dev/null bs=1 count=1 2>/dev/null ;\n"
@ -845,8 +886,10 @@ fish_linear_start (struct vfs_class *me, struct vfs_s_fh *fh, off_t offset)
"echo '### 500'\n" "echo '### 500'\n"
"fi\n", "fi\n",
quoted_name, quoted_name, quoted_name, quoted_name); quoted_name, quoted_name, quoted_name, quoted_name);
/* *INDENT-ON* */
g_free (quoted_name); g_free (quoted_name);
if (offset != PRELIM) ERRNOR (E_REMOTE, 0); if (offset != PRELIM)
ERRNOR (E_REMOTE, 0);
fh->linear = LS_LINEAR_OPEN; fh->linear = LS_LINEAR_OPEN;
fh->u.fish.got = 0; fh->u.fish.got = 0;
errno = 0; errno = 0;
@ -868,14 +911,17 @@ fish_linear_abort (struct vfs_class *me, struct vfs_s_fh *fh)
int n; int n;
print_vfs_message (_("Aborting transfer...")); print_vfs_message (_("Aborting transfer..."));
do { do
{
n = MIN (8192, fh->u.fish.total - fh->u.fish.got); n = MIN (8192, fh->u.fish.total - fh->u.fish.got);
if (n) { if (n)
{
if ((n = read (SUP.sockr, buffer, n)) < 0) if ((n = read (SUP.sockr, buffer, n)) < 0)
return; return;
fh->u.fish.got += n; fh->u.fish.got += n;
} }
} while (n); }
while (n);
if (fish_get_reply (me, SUP.sockr, NULL, 0) != COMPLETE) if (fish_get_reply (me, SUP.sockr, NULL, 0) != COMPLETE)
print_vfs_message (_("Error reported after abort.")); print_vfs_message (_("Error reported after abort."));
@ -890,15 +936,18 @@ fish_linear_read (struct vfs_class *me, struct vfs_s_fh *fh, void *buf, int len)
int n = 0; int n = 0;
len = MIN (fh->u.fish.total - fh->u.fish.got, len); len = MIN (fh->u.fish.total - fh->u.fish.got, len);
tty_disable_interrupt_key (); tty_disable_interrupt_key ();
while (len && ((n = read (SUP.sockr, buf, len))<0)) { while (len && ((n = read (SUP.sockr, buf, len)) < 0))
{
if ((errno == EINTR) && !tty_got_interrupt ()) if ((errno == EINTR) && !tty_got_interrupt ())
continue; continue;
break; break;
} }
tty_enable_interrupt_key (); tty_enable_interrupt_key ();
if (n>0) fh->u.fish.got += n; if (n > 0)
if (n<0) fish_linear_abort(me, fh); fh->u.fish.got += n;
if (n < 0)
fish_linear_abort (me, fh);
if ((!n) && ((fish_get_reply (me, SUP.sockr, NULL, 0) != COMPLETE))) if ((!n) && ((fish_get_reply (me, SUP.sockr, NULL, 0) != COMPLETE)))
ERRNOR (E_REMOTE, -1); ERRNOR (E_REMOTE, -1);
ERRNOR (errno, n); ERRNOR (errno, n);
@ -919,7 +968,8 @@ fish_ctl (void *fh, int ctlop, void *arg)
(void) ctlop; (void) ctlop;
return 0; return 0;
#if 0 #if 0
switch (ctlop) { switch (ctlop)
{
case VFS_CTL_IS_NOTREADY: case VFS_CTL_IS_NOTREADY:
{ {
int v; int v;
@ -947,7 +997,8 @@ fish_send_command(struct vfs_class *me, struct vfs_s_super *super, const char *c
r = fish_command (me, super, WAIT_REPLY, "%s", cmd); r = fish_command (me, super, WAIT_REPLY, "%s", cmd);
vfs_stamp_create (&vfs_fish_ops, super); vfs_stamp_create (&vfs_fish_ops, super);
if (r != COMPLETE) ERRNOR (E_REMOTE, -1); if (r != COMPLETE)
ERRNOR (E_REMOTE, -1);
if (flags & OPT_FLUSH) if (flags & OPT_FLUSH)
vfs_s_invalidate (me, super); vfs_s_invalidate (me, super);
return 0; return 0;
@ -958,7 +1009,8 @@ fish_send_command(struct vfs_class *me, struct vfs_s_super *super, const char *c
const char *crpath; \ const char *crpath; \
char *rpath, *mpath = g_strdup (path); \ char *rpath, *mpath = g_strdup (path); \
struct vfs_s_super *super; \ struct vfs_s_super *super; \
if (!(crpath = vfs_s_get_path_mangle (me, mpath, &super, 0))) { \ if (!(crpath = vfs_s_get_path_mangle (me, mpath, &super, 0))) \
{ \
g_free (mpath); \ g_free (mpath); \
return -1; \ return -1; \
} \ } \
@ -973,14 +1025,16 @@ static int
fish_chmod (struct vfs_class *me, const char *path, int mode) fish_chmod (struct vfs_class *me, const char *path, int mode)
{ {
PREFIX PREFIX
g_snprintf(buf, sizeof(buf), "#CHMOD %4.4o /%s\n" /* *INDENT-OFF* */
g_snprintf (buf, sizeof (buf),
"#CHMOD %4.4o /%s\n"
"if chmod %4.4o /%s 2>/dev/null; then\n" "if chmod %4.4o /%s 2>/dev/null; then\n"
"echo '### 000'\n" "echo '### 000'\n"
"else\n" "else\n"
"echo '### 500'\n" "echo '### 500'\n"
"fi\n", "fi\n",
mode & 07777, rpath, mode & 07777, rpath, mode & 07777, rpath);
mode & 07777, rpath); /* *INDENT-ON* */
POSTFIX (OPT_FLUSH); POSTFIX (OPT_FLUSH);
} }
@ -991,11 +1045,13 @@ static int fish_##name (struct vfs_class *me, const char *path1, const char *pat
const char *crpath1, *crpath2; \ const char *crpath1, *crpath2; \
char *rpath1, *rpath2, *mpath1, *mpath2; \ char *rpath1, *rpath2, *mpath1, *mpath2; \
struct vfs_s_super *super1, *super2; \ struct vfs_s_super *super1, *super2; \
if (!(crpath1 = vfs_s_get_path_mangle (me, mpath1 = g_strdup(path1), &super1, 0))) { \ if (!(crpath1 = vfs_s_get_path_mangle (me, mpath1 = g_strdup(path1), &super1, 0))) \
{ \
g_free (mpath1); \ g_free (mpath1); \
return -1; \ return -1; \
} \ } \
if (!(crpath2 = vfs_s_get_path_mangle (me, mpath2 = g_strdup(path2), &super2, 0))) { \ if (!(crpath2 = vfs_s_get_path_mangle (me, mpath2 = g_strdup(path2), &super2, 0))) \
{ \
g_free (mpath1); \ g_free (mpath1); \
g_free (mpath2); \ g_free (mpath2); \
return -1; \ return -1; \
@ -1010,24 +1066,30 @@ static int fish_##name (struct vfs_class *me, const char *path1, const char *pat
return fish_send_command(me, super2, buf, OPT_FLUSH); \ return fish_send_command(me, super2, buf, OPT_FLUSH); \
} }
FISH_OP(rename, "#RENAME /%s /%s\n" /* *INDENT-OFF* */
FISH_OP (rename,
"#RENAME /%s /%s\n"
"if mv /%s /%s 2>/dev/null; then\n" "if mv /%s /%s 2>/dev/null; then\n"
"echo '### 000'\n" "echo '### 000'\n"
"else\n" "else\n"
"echo '### 500'\n" "echo '### 500'\n"
"fi\n") "fi\n")
FISH_OP(link, "#LINK /%s /%s\n"
FISH_OP (link,
"#LINK /%s /%s\n"
"if ln /%s /%s 2>/dev/null; then\n" "if ln /%s /%s 2>/dev/null; then\n"
"echo '### 000'\n" "echo '### 000'\n"
"else\n" "else\n"
"echo '### 500'\n" "echo '### 500'\n"
"fi\n") "fi\n")
/* *INDENT-ON* */
static int fish_symlink (struct vfs_class *me, const char *setto, const char *path) static int
fish_symlink (struct vfs_class *me, const char *setto, const char *path)
{ {
char *qsetto; char *qsetto;
PREFIX PREFIX qsetto = strutils_shell_escape (setto);
qsetto = strutils_shell_escape (setto); /* *INDENT-OFF* */
g_snprintf (buf, sizeof (buf), g_snprintf (buf, sizeof (buf),
"#SYMLINK %s /%s\n" "#SYMLINK %s /%s\n"
"if ln -s %s /%s 2>/dev/null; then\n" "if ln -s %s /%s 2>/dev/null; then\n"
@ -1036,6 +1098,7 @@ static int fish_symlink (struct vfs_class *me, const char *setto, const char *pa
"echo '### 500'\n" "echo '### 500'\n"
"fi\n", "fi\n",
qsetto, rpath, qsetto, rpath); qsetto, rpath, qsetto, rpath);
/* *INDENT-ON* */
g_free (qsetto); g_free (qsetto);
POSTFIX (OPT_FLUSH); POSTFIX (OPT_FLUSH);
} }
@ -1057,6 +1120,7 @@ fish_chown (struct vfs_class *me, const char *path, int owner, int group)
sgroup = gr->gr_name; sgroup = gr->gr_name;
{ {
PREFIX PREFIX
/* *INDENT-OFF* */
g_snprintf (buf, sizeof (buf), g_snprintf (buf, sizeof (buf),
"#CHOWN %s:%s /%s\n" "#CHOWN %s:%s /%s\n"
"if chown %s:%s /%s 2>/dev/null; then\n" "if chown %s:%s /%s 2>/dev/null; then\n"
@ -1064,18 +1128,20 @@ fish_chown (struct vfs_class *me, const char *path, int owner, int group)
"else\n" "else\n"
"echo '### 500'\n" "echo '### 500'\n"
"fi\n", "fi\n",
sowner, sgroup, rpath, sowner, sgroup, rpath, sowner, sgroup, rpath);
sowner, sgroup, rpath); /* *INDENT-ON* */
fish_send_command (me, super, buf, OPT_FLUSH); fish_send_command (me, super, buf, OPT_FLUSH);
/* FIXME: what should we report if chgrp succeeds but chown fails? */ /* FIXME: what should we report if chgrp succeeds but chown fails? */
/* fish_send_command(me, super, buf, OPT_FLUSH); */ /* fish_send_command(me, super, buf, OPT_FLUSH); */
POSTFIX (OPT_FLUSH) POSTFIX (OPT_FLUSH)}
}
} }
static int fish_unlink (struct vfs_class *me, const char *path) static int
fish_unlink (struct vfs_class *me, const char *path)
{ {
PREFIX PREFIX
/* *INDENT-OFF* */
g_snprintf (buf, sizeof (buf), g_snprintf (buf, sizeof (buf),
"#DELE /%s\n" "#DELE /%s\n"
"if rm -f /%s 2>/dev/null; then\n" "if rm -f /%s 2>/dev/null; then\n"
@ -1084,18 +1150,23 @@ static int fish_unlink (struct vfs_class *me, const char *path)
"echo '### 500'\n" "echo '### 500'\n"
"fi\n", "fi\n",
rpath, rpath); rpath, rpath);
/* *INDENT-ON* */
POSTFIX (OPT_FLUSH); POSTFIX (OPT_FLUSH);
} }
static int fish_exists (struct vfs_class *me, const char *path) static int
fish_exists (struct vfs_class *me, const char *path)
{ {
PREFIX PREFIX
/* *INDENT-OFF* */
g_snprintf (buf, sizeof (buf), g_snprintf (buf, sizeof (buf),
"#ISEXISTS /%s\n" "#ISEXISTS /%s\n"
"ls -l /%s >/dev/null 2>/dev/null\n" "ls -l /%s >/dev/null 2>/dev/null\n"
"echo '### '$?\n", "echo '### '$?\n",
rpath, rpath); rpath, rpath);
/* *INDENT-ON* */
g_free (rpath); g_free (rpath);
@ -1106,14 +1177,14 @@ static int fish_exists (struct vfs_class *me, const char *path)
} }
static int fish_mkdir (struct vfs_class *me, const char *path, mode_t mode) static int
fish_mkdir (struct vfs_class *me, const char *path, mode_t mode)
{ {
int ret_code; int ret_code;
PREFIX PREFIX (void) mode;
(void) mode;
/* *INDENT-OFF* */
g_snprintf (buf, sizeof (buf), g_snprintf (buf, sizeof (buf),
"#MKD /%s\n" "#MKD /%s\n"
"if mkdir /%s 2>/dev/null; then\n" "if mkdir /%s 2>/dev/null; then\n"
@ -1122,6 +1193,7 @@ static int fish_mkdir (struct vfs_class *me, const char *path, mode_t mode)
"echo '### 500'\n" "echo '### 500'\n"
"fi\n", "fi\n",
rpath, rpath); rpath, rpath);
/* *INDENT-ON* */
g_free (rpath); g_free (rpath);
ret_code = fish_send_command (me, super, buf, OPT_FLUSH); ret_code = fish_send_command (me, super, buf, OPT_FLUSH);
@ -1129,15 +1201,18 @@ static int fish_mkdir (struct vfs_class *me, const char *path, mode_t mode)
if (ret_code != 0) if (ret_code != 0)
return ret_code; return ret_code;
if ( ! fish_exists (me, path) ){ if (!fish_exists (me, path))
{
ERRNOR (EACCES, -1); ERRNOR (EACCES, -1);
} }
return 0; return 0;
} }
static int fish_rmdir (struct vfs_class *me, const char *path) static int
fish_rmdir (struct vfs_class *me, const char *path)
{ {
PREFIX PREFIX
/* *INDENT-OFF* */
g_snprintf (buf, sizeof (buf), g_snprintf (buf, sizeof (buf),
"#RMD /%s\n" "#RMD /%s\n"
"if rmdir /%s 2>/dev/null; then\n" "if rmdir /%s 2>/dev/null; then\n"
@ -1146,22 +1221,23 @@ static int fish_rmdir (struct vfs_class *me, const char *path)
"echo '### 500'\n" "echo '### 500'\n"
"fi\n", "fi\n",
rpath, rpath); rpath, rpath);
/* *INDENT-ON* */
POSTFIX (OPT_FLUSH); POSTFIX (OPT_FLUSH);
} }
static int static int
fish_fh_open (struct vfs_class *me, struct vfs_s_fh *fh, int flags, fish_fh_open (struct vfs_class *me, struct vfs_s_fh *fh, int flags, int mode)
int mode)
{ {
(void) mode; (void) mode;
fh->u.fish.append = 0; fh->u.fish.append = 0;
/* File will be written only, so no need to retrieve it */ /* File will be written only, so no need to retrieve it */
if (((flags & O_WRONLY) == O_WRONLY) && !(flags & (O_RDONLY | O_RDWR))) { if (((flags & O_WRONLY) == O_WRONLY) && !(flags & (O_RDONLY | O_RDWR)))
{
fh->u.fish.append = flags & O_APPEND; fh->u.fish.append = flags & O_APPEND;
if (!fh->ino->localname) { if (!fh->ino->localname)
int tmp_handle = {
vfs_mkstemps (&fh->ino->localname, me->name, int tmp_handle = vfs_mkstemps (&fh->ino->localname, me->name,
fh->ino->ent->name); fh->ino->ent->name);
if (tmp_handle == -1) if (tmp_handle == -1)
return -1; return -1;
@ -1206,8 +1282,7 @@ fish_fill_names (struct vfs_class *me, fill_names_f func)
break; break;
} }
name = g_strconcat ("/#sh:", SUP.user, "@", SUP.host, flags, name = g_strconcat ("/#sh:", SUP.user, "@", SUP.host, flags, "/", SUP.cwdir, (char *) NULL);
"/", SUP.cwdir, (char *) NULL);
(*func) (name); (*func) (name);
g_free (name); g_free (name);
super = super->next; super = super->next;

Просмотреть файл

@ -75,13 +75,15 @@
static struct vfs_class *current_vfs; static struct vfs_class *current_vfs;
static char *current_dir; static char *current_dir;
struct vfs_openfile { struct vfs_openfile
{
int handle; int handle;
struct vfs_class *vclass; struct vfs_class *vclass;
void *fsinfo; void *fsinfo;
}; };
struct vfs_dirinfo{ struct vfs_dirinfo
{
DIR *info; DIR *info;
GIConv converter; GIConv converter;
}; };
@ -121,11 +123,14 @@ vfs_new_handle (struct vfs_class *vclass, void *fsinfo)
/* Allocate the first free handle */ /* Allocate the first free handle */
h->handle = vfs_free_handle_list; h->handle = vfs_free_handle_list;
if (h->handle == -1) { if (h->handle == -1)
{
/* No free allocated handles, allocate one */ /* No free allocated handles, allocate one */
h->handle = vfs_openfiles->len; h->handle = vfs_openfiles->len;
g_ptr_array_add (vfs_openfiles, h); g_ptr_array_add (vfs_openfiles, h);
} else { }
else
{
vfs_free_handle_list = (long) g_ptr_array_index (vfs_openfiles, vfs_free_handle_list); vfs_free_handle_list = (long) g_ptr_array_index (vfs_openfiles, vfs_free_handle_list);
g_ptr_array_index (vfs_openfiles, h->handle) = h; g_ptr_array_index (vfs_openfiles, h->handle) = h;
} }
@ -140,12 +145,10 @@ vfs_op (int handle)
{ {
struct vfs_openfile *h; struct vfs_openfile *h;
if (handle < VFS_FIRST_HANDLE || if (handle < VFS_FIRST_HANDLE || (guint) (handle - VFS_FIRST_HANDLE) >= vfs_openfiles->len)
(guint)(handle - VFS_FIRST_HANDLE) >= vfs_openfiles->len)
return NULL; return NULL;
h = (struct vfs_openfile *) g_ptr_array_index ( h = (struct vfs_openfile *) g_ptr_array_index (vfs_openfiles, handle - VFS_FIRST_HANDLE);
vfs_openfiles, handle - VFS_FIRST_HANDLE);
if (!h) if (!h)
return NULL; return NULL;
@ -160,12 +163,10 @@ vfs_info (int handle)
{ {
struct vfs_openfile *h; struct vfs_openfile *h;
if (handle < VFS_FIRST_HANDLE || if (handle < VFS_FIRST_HANDLE || (guint) (handle - VFS_FIRST_HANDLE) >= vfs_openfiles->len)
(guint)(handle - VFS_FIRST_HANDLE) >= vfs_openfiles->len)
return NULL; return NULL;
h = (struct vfs_openfile *) g_ptr_array_index ( h = (struct vfs_openfile *) g_ptr_array_index (vfs_openfiles, handle - VFS_FIRST_HANDLE);
vfs_openfiles, handle - VFS_FIRST_HANDLE);
if (!h) if (!h)
return NULL; return NULL;
@ -178,13 +179,17 @@ vfs_info (int handle)
static void static void
vfs_free_handle (int handle) vfs_free_handle (int handle)
{ {
if (handle < VFS_FIRST_HANDLE || const int idx = handle - VFS_FIRST_HANDLE;
(guint)(handle - VFS_FIRST_HANDLE) >= vfs_openfiles->len)
return;
g_ptr_array_index (vfs_openfiles, handle - VFS_FIRST_HANDLE) = if (handle >= VFS_FIRST_HANDLE && (guint) idx < vfs_openfiles->len)
(void *) vfs_free_handle_list; {
vfs_free_handle_list = handle - VFS_FIRST_HANDLE; struct vfs_openfile *h;
h = (struct vfs_openfile *) g_ptr_array_index (vfs_openfiles, idx);
g_free (h);
g_ptr_array_index (vfs_openfiles, idx) = (void *) vfs_free_handle_list;
vfs_free_handle_list = idx;
}
} }
static struct vfs_class *vfs_list; static struct vfs_class *vfs_list;
@ -209,14 +214,15 @@ vfs_prefix_to_class (char *prefix)
struct vfs_class *vfs; struct vfs_class *vfs;
/* Avoid last class (localfs) that would accept any prefix */ /* Avoid last class (localfs) that would accept any prefix */
for (vfs = vfs_list; vfs->next; vfs = vfs->next) { for (vfs = vfs_list; vfs->next; vfs = vfs->next)
if (vfs->which) { {
if (vfs->which)
{
if ((*vfs->which) (vfs, prefix) == -1) if ((*vfs->which) (vfs, prefix) == -1)
continue; continue;
return vfs; return vfs;
} }
if (vfs->prefix if (vfs->prefix && !strncmp (prefix, vfs->prefix, strlen (vfs->prefix)))
&& !strncmp (prefix, vfs->prefix, strlen (vfs->prefix)))
return vfs; return vfs;
} }
return NULL; return NULL;
@ -241,15 +247,17 @@ vfs_strip_suffix_from_filename (const char *filename)
return p; return p;
/* Avoid last class (localfs) that would accept any prefix */ /* Avoid last class (localfs) that would accept any prefix */
for (vfs = vfs_list; vfs->next; vfs = vfs->next) { for (vfs = vfs_list; vfs->next; vfs = vfs->next)
if (vfs->which) { {
if (vfs->which)
{
if ((*vfs->which) (vfs, semi + 1) == -1) if ((*vfs->which) (vfs, semi + 1) == -1)
continue; continue;
*semi = '\0'; /* Found valid suffix */ *semi = '\0'; /* Found valid suffix */
return p; return p;
} }
if (vfs->prefix if (vfs->prefix && !strncmp (semi + 1, vfs->prefix, strlen (vfs->prefix)))
&& !strncmp (semi + 1, vfs->prefix, strlen (vfs->prefix))) { {
*semi = '\0'; /* Found valid suffix */ *semi = '\0'; /* Found valid suffix */
return p; return p;
} }
@ -305,7 +313,8 @@ vfs_split (char *path, char **inpath, char **op)
if (slash) if (slash)
*slash = 0; *slash = 0;
if ((ret = vfs_prefix_to_class (semi+1))){ if ((ret = vfs_prefix_to_class (semi + 1)))
{
if (op) if (op)
*op = semi + 1; *op = semi + 1;
if (inpath) if (inpath)
@ -376,7 +385,8 @@ vfs_get_encoding (const char *path)
work = g_strdup (path); work = g_strdup (path);
semi = g_strrstr (work, "#enc:"); semi = g_strrstr (work, "#enc:");
if (semi != NULL) { if (semi != NULL)
{
semi += 5 * sizeof (char); semi += 5 * sizeof (char);
slash = strchr (semi, PATH_SEP); slash = strchr (semi, PATH_SEP);
if (slash != NULL) if (slash != NULL)
@ -385,7 +395,9 @@ vfs_get_encoding (const char *path)
g_strlcpy (result, semi, sizeof (result)); g_strlcpy (result, semi, sizeof (result));
g_free (work); g_free (work);
return result; return result;
} else { }
else
{
g_free (work); g_free (work);
return NULL; return NULL;
} }
@ -394,11 +406,13 @@ vfs_get_encoding (const char *path)
/* return if encoding can by used in vfs (is ascci full compactible) */ /* return if encoding can by used in vfs (is ascci full compactible) */
/* contains only a few encoding now */ /* contains only a few encoding now */
static int static int
vfs_supported_enconding (const char *encoding) { vfs_supported_enconding (const char *encoding)
{
int t; int t;
int result = 0; int result = 0;
for (t = 0; supported_encodings[t] != NULL; t++) { for (t = 0; supported_encodings[t] != NULL; t++)
{
result += (g_ascii_strncasecmp (encoding, supported_encodings[t], result += (g_ascii_strncasecmp (encoding, supported_encodings[t],
strlen (supported_encodings[t])) == 0); strlen (supported_encodings[t])) == 0);
} }
@ -415,8 +429,7 @@ vfs_supported_enconding (const char *encoding) {
* buffer - used to store result of translation * buffer - used to store result of translation
*/ */
static estr_t static estr_t
_vfs_translate_path (const char *path, int size, _vfs_translate_path (const char *path, int size, GIConv defcnv, GString * buffer)
GIConv defcnv, GString *buffer)
{ {
const char *semi; const char *semi;
const char *ps; const char *ps;
@ -426,18 +439,21 @@ _vfs_translate_path (const char *path, int size,
GIConv coder; GIConv coder;
int ms; int ms;
if (size == 0) return 0; if (size == 0)
return 0;
size = (size > 0) ? size : (signed int) strlen (path); size = (size > 0) ? size : (signed int) strlen (path);
/* try found #end: */ /* try found #end: */
semi = g_strrstr_len (path, size, "#enc:"); semi = g_strrstr_len (path, size, "#enc:");
if (semi != NULL) { if (semi != NULL)
{
/* first must be translated part before #enc: */ /* first must be translated part before #enc: */
ms = semi - path; ms = semi - path;
/* remove '/' before #enc */ /* remove '/' before #enc */
ps = str_cget_prev_char (semi); ps = str_cget_prev_char (semi);
if (ps[0] == PATH_SEP) ms = ps - path; if (ps[0] == PATH_SEP)
ms = ps - path;
state = _vfs_translate_path (path, ms, defcnv, buffer); state = _vfs_translate_path (path, ms, defcnv, buffer);
@ -448,29 +464,37 @@ _vfs_translate_path (const char *path, int size,
semi += 5; semi += 5;
slash = strchr (semi, PATH_SEP); slash = strchr (semi, PATH_SEP);
/* ignore slashes after size; */ /* ignore slashes after size; */
if (slash - path >= size) slash = NULL; if (slash - path >= size)
slash = NULL;
ms = (slash != NULL) ? slash - semi : (int) strlen (semi); ms = (slash != NULL) ? slash - semi : (int) strlen (semi);
ms = min ((unsigned int) ms, sizeof (encoding) - 1); ms = min ((unsigned int) ms, sizeof (encoding) - 1);
/* limit encoding size (ms) to path size (size) */ /* limit encoding size (ms) to path size (size) */
if (semi + ms > path + size) ms = path + size - semi; if (semi + ms > path + size)
ms = path + size - semi;
memcpy (encoding, semi, ms); memcpy (encoding, semi, ms);
encoding[ms] = '\0'; encoding[ms] = '\0';
switch (vfs_supported_enconding (encoding)) { switch (vfs_supported_enconding (encoding))
{
case 1: case 1:
coder = str_crt_conv_to (encoding); coder = str_crt_conv_to (encoding);
if (coder != INVALID_CONV) { if (coder != INVALID_CONV)
if (slash != NULL) { {
state = str_vfs_convert_to (coder, slash, if (slash != NULL)
path + size - slash, buffer); {
} else if (buffer->str[0] == '\0') { state = str_vfs_convert_to (coder, slash, path + size - slash, buffer);
}
else if (buffer->str[0] == '\0')
{
/* exmaple "/#enc:utf-8" */ /* exmaple "/#enc:utf-8" */
g_string_append_c (buffer, PATH_SEP); g_string_append_c (buffer, PATH_SEP);
} }
str_close_conv (coder); str_close_conv (coder);
return state; return state;
} else { }
else
{
errno = EINVAL; errno = EINVAL;
return ESTR_FAILURE; return ESTR_FAILURE;
} }
@ -479,7 +503,9 @@ _vfs_translate_path (const char *path, int size,
errno = EINVAL; errno = EINVAL;
return ESTR_FAILURE; return ESTR_FAILURE;
} }
} else { }
else
{
/* path can be translated whole at once */ /* path can be translated whole at once */
state = str_vfs_convert_to (defcnv, path, size, buffer); state = str_vfs_convert_to (defcnv, path, size, buffer);
return state; return state;
@ -540,18 +566,22 @@ mc_open (const char *filename, int flags, ...)
va_list ap; va_list ap;
char *file = vfs_canon_and_translate (filename); char *file = vfs_canon_and_translate (filename);
if (file != NULL) { if (file != NULL)
{
struct vfs_class *vfs = vfs_get_class (file); struct vfs_class *vfs = vfs_get_class (file);
/* Get the mode flag */ /* Get the mode flag */
if (flags & O_CREAT) { if (flags & O_CREAT)
{
va_start (ap, flags); va_start (ap, flags);
mode = va_arg (ap, int); mode = va_arg (ap, int);
va_end (ap); va_end (ap);
} else }
else
mode = 0; mode = 0;
if (!vfs->open) { if (!vfs->open)
{
g_free (file); g_free (file);
errno = -EOPNOTSUPP; errno = -EOPNOTSUPP;
return -1; return -1;
@ -559,13 +589,16 @@ mc_open (const char *filename, int flags, ...)
info = (*vfs->open) (vfs, file, flags, mode); /* open must be supported */ info = (*vfs->open) (vfs, file, flags, mode); /* open must be supported */
g_free (file); g_free (file);
if (!info){ if (!info)
{
errno = ferrno (vfs); errno = ferrno (vfs);
return -1; return -1;
} }
return vfs_new_handle (vfs, info); return vfs_new_handle (vfs, info);
} else return -1; }
else
return -1;
} }
@ -597,9 +630,7 @@ MC_NAMEOP (unlink, (const char *path), (vfs, mpath))
MC_NAMEOP (mkdir, (const char *path, mode_t mode), (vfs, mpath, mode)) MC_NAMEOP (mkdir, (const char *path, mode_t mode), (vfs, mpath, mode))
MC_NAMEOP (rmdir, (const char *path), (vfs, mpath)) MC_NAMEOP (rmdir, (const char *path), (vfs, mpath))
MC_NAMEOP (mknod, (const char *path, mode_t mode, dev_t dev), (vfs, mpath, mode, dev)) MC_NAMEOP (mknod, (const char *path, mode_t mode, dev_t dev), (vfs, mpath, mode, dev))
int mc_symlink (const char *name1, const char *path)
int
mc_symlink (const char *name1, const char *path)
{ {
struct vfs_class *vfs; struct vfs_class *vfs;
int result; int result;
@ -608,12 +639,14 @@ mc_symlink (const char *name1, const char *path)
char *tmp; char *tmp;
mpath = vfs_canon_and_translate (path); mpath = vfs_canon_and_translate (path);
if (mpath != NULL) { if (mpath != NULL)
{
tmp = g_strdup (name1); tmp = g_strdup (name1);
lpath = vfs_translate_path_n (tmp); lpath = vfs_translate_path_n (tmp);
g_free (tmp); g_free (tmp);
if (lpath != NULL) { if (lpath != NULL)
{
vfs = vfs_get_class (mpath); vfs = vfs_get_class (mpath);
result = vfs->symlink ? (*vfs->symlink) (vfs, lpath, mpath) : -1; result = vfs->symlink ? (*vfs->symlink) (vfs, lpath, mpath) : -1;
g_free (lpath); g_free (lpath);
@ -646,8 +679,6 @@ ssize_t mc_##name inarg \
MC_HANDLEOP (read, (int handle, void *buffer, int count), (vfs_info (handle), buffer, count)) MC_HANDLEOP (read, (int handle, void *buffer, int count), (vfs_info (handle), buffer, count))
MC_HANDLEOP (write, (int handle, const void *buf, int nbyte), (vfs_info (handle), buf, nbyte)) MC_HANDLEOP (write, (int handle, const void *buf, int nbyte), (vfs_info (handle), buf, nbyte))
#define MC_RENAMEOP(name) \ #define MC_RENAMEOP(name) \
int mc_##name (const char *fname1, const char *fname2) \ int mc_##name (const char *fname1, const char *fname2) \
{ \ { \
@ -677,11 +708,7 @@ int mc_##name (const char *fname1, const char *fname2) \
} \ } \
} else return -1; \ } else return -1; \
} }
MC_RENAMEOP (link) MC_RENAMEOP (rename)
MC_RENAMEOP (link)
MC_RENAMEOP (rename)
int int
mc_ctl (int handle, int ctlop, void *arg) mc_ctl (int handle, int ctlop, void *arg)
{ {
@ -704,12 +731,15 @@ mc_setctl (const char *path, int ctlop, void *arg)
vfs_die ("You don't want to pass NULL to mc_setctl."); vfs_die ("You don't want to pass NULL to mc_setctl.");
mpath = vfs_canon_and_translate (path); mpath = vfs_canon_and_translate (path);
if (mpath != NULL) { if (mpath != NULL)
{
vfs = vfs_get_class (mpath); vfs = vfs_get_class (mpath);
result = vfs->setctl ? (*vfs->setctl) (vfs, mpath, ctlop, arg) : 0; result = vfs->setctl ? (*vfs->setctl) (vfs, mpath, ctlop, arg) : 0;
g_free (mpath); g_free (mpath);
return result; return result;
} else return -1; }
else
return -1;
} }
int int
@ -752,12 +782,14 @@ mc_opendir (const char *dirname)
canon = vfs_canon (dirname); canon = vfs_canon (dirname);
dname = vfs_translate_path_n (canon); dname = vfs_translate_path_n (canon);
if (dname != NULL) { if (dname != NULL)
{
vfs = vfs_get_class (dname); vfs = vfs_get_class (dname);
info = vfs->opendir ? (*vfs->opendir) (vfs, dname) : NULL; info = vfs->opendir ? (*vfs->opendir) (vfs, dname) : NULL;
g_free (dname); g_free (dname);
if (info == NULL) { if (info == NULL)
{
errno = vfs->opendir ? ferrno (vfs) : E_NOTSUPP; errno = vfs->opendir ? ferrno (vfs) : E_NOTSUPP;
g_free (canon); g_free (canon);
return NULL; return NULL;
@ -768,16 +800,18 @@ mc_opendir (const char *dirname)
encoding = vfs_get_encoding (canon); encoding = vfs_get_encoding (canon);
g_free (canon); g_free (canon);
dirinfo->converter = (encoding != NULL) ? str_crt_conv_from (encoding) : dirinfo->converter = (encoding != NULL) ? str_crt_conv_from (encoding) : str_cnv_from_term;
str_cnv_from_term; if (dirinfo->converter == INVALID_CONV)
if (dirinfo->converter == INVALID_CONV) dirinfo->converter =str_cnv_from_term; dirinfo->converter = str_cnv_from_term;
handle = vfs_new_handle (vfs, dirinfo); handle = vfs_new_handle (vfs, dirinfo);
handlep = g_new (int, 1); handlep = g_new (int, 1);
*handlep = handle; *handlep = handle;
return (DIR *) handlep; return (DIR *) handlep;
} else { }
else
{
g_free (canon); g_free (canon);
return NULL; return NULL;
} }
@ -809,7 +843,8 @@ mc_readdir (DIR *dirp)
mc_readdir_result = (struct dirent *) g_malloc (sizeof (struct dirent) + MAXNAMLEN + 1); mc_readdir_result = (struct dirent *) g_malloc (sizeof (struct dirent) + MAXNAMLEN + 1);
} }
if (!dirp) { if (!dirp)
{
errno = EFAULT; errno = EFAULT;
return NULL; return NULL;
} }
@ -820,16 +855,18 @@ mc_readdir (DIR *dirp)
return NULL; return NULL;
dirinfo = vfs_info (handle); dirinfo = vfs_info (handle);
if (vfs->readdir) { if (vfs->readdir)
{
entry = (*vfs->readdir) (dirinfo->info); entry = (*vfs->readdir) (dirinfo->info);
if (entry == NULL) return NULL; if (entry == NULL)
return NULL;
g_string_set_size (vfs_str_buffer, 0); g_string_set_size (vfs_str_buffer, 0);
state = str_vfs_convert_from (dirinfo->converter, state = str_vfs_convert_from (dirinfo->converter, entry->d_name, vfs_str_buffer);
entry->d_name, vfs_str_buffer);
mc_readdir_result->d_ino = entry->d_ino; mc_readdir_result->d_ino = entry->d_ino;
g_strlcpy (mc_readdir_result->d_name, vfs_str_buffer->str, MAXNAMLEN + 1); g_strlcpy (mc_readdir_result->d_name, vfs_str_buffer->str, MAXNAMLEN + 1);
} }
if (entry == NULL) errno = vfs->readdir ? ferrno (vfs) : E_NOTSUPP; if (entry == NULL)
errno = vfs->readdir ? ferrno (vfs) : E_NOTSUPP;
return (entry != NULL) ? mc_readdir_result : NULL; return (entry != NULL) ? mc_readdir_result : NULL;
} }
@ -837,24 +874,29 @@ int
mc_closedir (DIR * dirp) mc_closedir (DIR * dirp)
{ {
int handle = *(int *) dirp; int handle = *(int *) dirp;
struct vfs_class *vfs = vfs_op (handle); struct vfs_class *vfs;
int result; int result = -1;
vfs = vfs_op (handle);
if (vfs != NULL)
{
struct vfs_dirinfo *dirinfo; struct vfs_dirinfo *dirinfo;
if (vfs == NULL)
return -1;
dirinfo = vfs_info (handle); dirinfo = vfs_info (handle);
if (dirinfo->converter != str_cnv_from_term) str_close_conv (dirinfo->converter); if (dirinfo->converter != str_cnv_from_term)
str_close_conv (dirinfo->converter);
result = vfs->closedir ? (*vfs->closedir) (dirinfo->info) : -1; result = vfs->closedir ? (*vfs->closedir) (dirinfo->info) : -1;
vfs_free_handle (handle); vfs_free_handle (handle);
g_free (dirinfo); g_free (dirinfo);
}
g_free (dirp); g_free (dirp);
return result; return result;
} }
int mc_stat (const char *filename, struct stat *buf) { int
mc_stat (const char *filename, struct stat *buf)
{
struct vfs_class *vfs; struct vfs_class *vfs;
int result; int result;
char *path; char *path;
@ -866,7 +908,8 @@ int mc_stat (const char *filename, struct stat *buf) {
vfs = vfs_get_class (path); vfs = vfs_get_class (path);
if (vfs == NULL) { if (vfs == NULL)
{
g_free (path); g_free (path);
return -1; return -1;
} }
@ -880,7 +923,9 @@ int mc_stat (const char *filename, struct stat *buf) {
return result; return result;
} }
int mc_lstat (const char *filename, struct stat *buf) { int
mc_lstat (const char *filename, struct stat *buf)
{
struct vfs_class *vfs; struct vfs_class *vfs;
int result; int result;
char *path; char *path;
@ -891,7 +936,8 @@ int mc_lstat (const char *filename, struct stat *buf) {
return -1; return -1;
vfs = vfs_get_class (path); vfs = vfs_get_class (path);
if (vfs == NULL) { if (vfs == NULL)
{
g_free (path); g_free (path);
return -1; return -1;
} }
@ -903,7 +949,9 @@ int mc_lstat (const char *filename, struct stat *buf) {
return result; return result;
} }
int mc_fstat (int handle, struct stat *buf) { int
mc_fstat (int handle, struct stat *buf)
{
struct vfs_class *vfs; struct vfs_class *vfs;
int result; int result;
@ -931,14 +979,17 @@ _vfs_get_cwd (void)
trans = vfs_translate_path_n (current_dir); trans = vfs_translate_path_n (current_dir);
if (_vfs_get_class (trans) == NULL) { if (_vfs_get_class (trans) == NULL)
{
const char *encoding = vfs_get_encoding (current_dir); const char *encoding = vfs_get_encoding (current_dir);
if (encoding == NULL) { if (encoding == NULL)
{
char *tmp; char *tmp;
tmp = g_get_current_dir (); tmp = g_get_current_dir ();
if (tmp != NULL) { /* One of the directories in the path is not readable */ if (tmp != NULL)
{ /* One of the directories in the path is not readable */
estr_t state; estr_t state;
char *sys_cwd; char *sys_cwd;
@ -947,16 +998,17 @@ _vfs_get_cwd (void)
g_free (tmp); g_free (tmp);
sys_cwd = (state == ESTR_SUCCESS) ? g_strdup (vfs_str_buffer->str) : NULL; sys_cwd = (state == ESTR_SUCCESS) ? g_strdup (vfs_str_buffer->str) : NULL;
if (sys_cwd != NULL) { if (sys_cwd != NULL)
{
struct stat my_stat, my_stat2; struct stat my_stat, my_stat2;
/* Check if it is O.K. to use the current_dir */ /* Check if it is O.K. to use the current_dir */
if (cd_symlinks if (cd_symlinks
&& mc_stat (sys_cwd, &my_stat) == 0 && mc_stat (sys_cwd, &my_stat) == 0
&& mc_stat (current_dir, &my_stat2) == 0 && mc_stat (current_dir, &my_stat2) == 0
&& my_stat.st_ino == my_stat2.st_ino && my_stat.st_ino == my_stat2.st_ino && my_stat.st_dev == my_stat2.st_dev)
&& my_stat.st_dev == my_stat2.st_dev)
g_free (sys_cwd); g_free (sys_cwd);
else { else
{
g_free (current_dir); g_free (current_dir);
current_dir = sys_cwd; current_dir = sys_cwd;
} }
@ -1003,7 +1055,8 @@ vfs_get_current_dir (void)
return current_dir; return current_dir;
} }
off_t mc_lseek (int fd, off_t offset, int whence) off_t
mc_lseek (int fd, off_t offset, int whence)
{ {
struct vfs_class *vfs; struct vfs_class *vfs;
int result; int result;
@ -1034,7 +1087,8 @@ vfs_canon (const char *path)
vfs_die ("Cannot canonicalize NULL"); vfs_die ("Cannot canonicalize NULL");
/* Relative to current directory */ /* Relative to current directory */
if (*path != PATH_SEP){ if (*path != PATH_SEP)
{
char *local, *result; char *local, *result;
local = concat_dir_and_file (current_dir, path); local = concat_dir_and_file (current_dir, path);
@ -1070,9 +1124,11 @@ mc_chdir (const char *path)
new_dir = vfs_canon (path); new_dir = vfs_canon (path);
trans_dir = vfs_translate_path_n (new_dir); trans_dir = vfs_translate_path_n (new_dir);
if (trans_dir != NULL) { if (trans_dir != NULL)
{
new_vfs = vfs_get_class (trans_dir); new_vfs = vfs_get_class (trans_dir);
if (!new_vfs->chdir) { if (!new_vfs->chdir)
{
g_free (new_dir); g_free (new_dir);
g_free (trans_dir); g_free (trans_dir);
return -1; return -1;
@ -1080,7 +1136,8 @@ mc_chdir (const char *path)
result = (*new_vfs->chdir) (new_vfs, trans_dir); result = (*new_vfs->chdir) (new_vfs, trans_dir);
if (result == -1) { if (result == -1)
{
errno = ferrno (new_vfs); errno = ferrno (new_vfs);
g_free (new_dir); g_free (new_dir);
g_free (trans_dir); g_free (trans_dir);
@ -1099,7 +1156,8 @@ mc_chdir (const char *path)
vfs_stamp_create (old_vfs, old_vfsid); vfs_stamp_create (old_vfs, old_vfsid);
/* Sometimes we assume no trailing slash on cwd */ /* Sometimes we assume no trailing slash on cwd */
if (*current_dir) { if (*current_dir)
{
char *p; char *p;
p = strchr (current_dir, 0) - 1; p = strchr (current_dir, 0) - 1;
if (*p == PATH_SEP && p > current_dir) if (*p == PATH_SEP && p > current_dir)
@ -1108,7 +1166,9 @@ mc_chdir (const char *path)
g_free (trans_dir); g_free (trans_dir);
return 0; return 0;
} else { }
else
{
g_free (new_dir); g_free (new_dir);
return -1; return -1;
} }
@ -1129,11 +1189,14 @@ vfs_file_class_flags (const char *filename)
char *fname; char *fname;
fname = vfs_canon_and_translate (filename); fname = vfs_canon_and_translate (filename);
if (fname != NULL) { if (fname != NULL)
{
vfs = vfs_get_class (fname); vfs = vfs_get_class (fname);
g_free (fname); g_free (fname);
return vfs->flags; return vfs->flags;
} else return -1; }
else
return -1;
} }
static char * static char *
@ -1153,7 +1216,8 @@ mc_def_getlocalcopy (const char *filename)
if (fdout == -1) if (fdout == -1)
goto fail; goto fail;
while ((i = mc_read (fdin, buffer, sizeof (buffer))) > 0) { while ((i = mc_read (fdin, buffer, sizeof (buffer))) > 0)
{
if (write (fdout, buffer, i) != i) if (write (fdout, buffer, i) != i)
goto fail; goto fail;
} }
@ -1163,12 +1227,14 @@ mc_def_getlocalcopy (const char *filename)
fdin = -1; fdin = -1;
if (i == -1) if (i == -1)
goto fail; goto fail;
if (close (fdout) == -1) { if (close (fdout) == -1)
{
fdout = -1; fdout = -1;
goto fail; goto fail;
} }
if (mc_stat (filename, &mystat) != -1) { if (mc_stat (filename, &mystat) != -1)
{
chmod (tmp, mystat.st_mode); chmod (tmp, mystat.st_mode);
} }
return tmp; return tmp;
@ -1189,16 +1255,18 @@ mc_getlocalcopy (const char *pathname)
char *path; char *path;
path = vfs_canon_and_translate (pathname); path = vfs_canon_and_translate (pathname);
if (path != NULL) { if (path != NULL)
{
struct vfs_class *vfs = vfs_get_class (path); struct vfs_class *vfs = vfs_get_class (path);
result = vfs->getlocalcopy ? (*vfs->getlocalcopy)(vfs, path) : result = vfs->getlocalcopy ? (*vfs->getlocalcopy) (vfs, path) : mc_def_getlocalcopy (path);
mc_def_getlocalcopy (path);
g_free (path); g_free (path);
if (!result) if (!result)
errno = ferrno (vfs); errno = ferrno (vfs);
return result; return result;
} else return NULL; }
else
return NULL;
} }
static int static int
@ -1206,7 +1274,8 @@ mc_def_ungetlocalcopy (struct vfs_class *vfs, const char *filename,
const char *local, int has_changed) const char *local, int has_changed)
{ {
int fdin = -1, fdout = -1, i; int fdin = -1, fdout = -1, i;
if (has_changed) { if (has_changed)
{
char buffer[8192]; char buffer[8192];
if (!vfs->write) if (!vfs->write)
@ -1218,19 +1287,22 @@ mc_def_ungetlocalcopy (struct vfs_class *vfs, const char *filename,
fdout = mc_open (filename, O_WRONLY | O_TRUNC); fdout = mc_open (filename, O_WRONLY | O_TRUNC);
if (fdout == -1) if (fdout == -1)
goto failed; goto failed;
while ((i = read (fdin, buffer, sizeof (buffer))) > 0) { while ((i = read (fdin, buffer, sizeof (buffer))) > 0)
{
if (mc_write (fdout, buffer, i) != i) if (mc_write (fdout, buffer, i) != i)
goto failed; goto failed;
} }
if (i == -1) if (i == -1)
goto failed; goto failed;
if (close (fdin) == -1) { if (close (fdin) == -1)
{
fdin = -1; fdin = -1;
goto failed; goto failed;
} }
fdin = -1; fdin = -1;
if (mc_close (fdout) == -1) { if (mc_close (fdout) == -1)
{
fdout = -1; fdout = -1;
goto failed; goto failed;
} }
@ -1255,7 +1327,8 @@ mc_ungetlocalcopy (const char *pathname, const char *local, int has_changed)
char *path; char *path;
path = vfs_canon_and_translate (pathname); path = vfs_canon_and_translate (pathname);
if (path != NULL) { if (path != NULL)
{
struct vfs_class *vfs = vfs_get_class (path); struct vfs_class *vfs = vfs_get_class (path);
return_value = vfs->ungetlocalcopy ? return_value = vfs->ungetlocalcopy ?
@ -1263,7 +1336,9 @@ mc_ungetlocalcopy (const char *pathname, const char *local, int has_changed)
mc_def_ungetlocalcopy (vfs, path, local, has_changed); mc_def_ungetlocalcopy (vfs, path, local, has_changed);
g_free (path); g_free (path);
return return_value; return return_value;
} else return -1; }
else
return -1;
} }
@ -1339,16 +1414,21 @@ vfs_fill_names (fill_names_f func)
* not recognized as url, g_strdup(url) is returned. * not recognized as url, g_strdup(url) is returned.
*/ */
static const struct { static const struct
{
const char *name; const char *name;
size_t name_len; size_t name_len;
const char *substitute; const char *substitute;
} url_table[] = { {"ftp://", 6, "/#ftp:"}, } url_table[] =
{
/* *INDENT-OFF* */
{ "ftp://", 6, "/#ftp:" },
{ "mc://", 5, "/#mc:" }, { "mc://", 5, "/#mc:" },
{ "smb://", 6, "/#smb:" }, { "smb://", 6, "/#smb:" },
{ "sh://", 5, "/#sh:" }, { "sh://", 5, "/#sh:" },
{ "ssh://", 6, "/#sh:" }, { "ssh://", 6, "/#sh:" },
{ "a:", 2, "/#a" } { "a:", 2, "/#a" }
/* *INDENT-ON* */
}; };
char * char *
@ -1358,12 +1438,14 @@ vfs_translate_url (const char *url)
for (i = 0; i < sizeof (url_table) / sizeof (url_table[0]); i++) for (i = 0; i < sizeof (url_table) / sizeof (url_table[0]); i++)
if (strncmp (url, url_table[i].name, url_table[i].name_len) == 0) if (strncmp (url, url_table[i].name, url_table[i].name_len) == 0)
return g_strconcat (url_table[i].substitute, url + url_table[i].name_len, (char*) NULL); return g_strconcat (url_table[i].substitute, url + url_table[i].name_len,
(char *) NULL);
return g_strdup (url); return g_strdup (url);
} }
int vfs_file_is_local (const char *filename) int
vfs_file_is_local (const char *filename)
{ {
return vfs_file_class_flags (filename) & VFSF_LOCAL; return vfs_file_class_flags (filename) & VFSF_LOCAL;
} }

Просмотреть файл

@ -56,7 +56,8 @@ typedef char *CompletionFunction (const char * text, int state, INPUT_COMPLETE_F
/* /*
* Useful to print/debug completion flags * Useful to print/debug completion flags
*/ */
static const char * show_c_flags(INPUT_COMPLETE_FLAGS flags) static const char *
show_c_flags (INPUT_COMPLETE_FLAGS flags)
{ {
static char s_cf[] = "FHCVUDS"; static char s_cf[] = "FHCVUDS";
@ -70,6 +71,7 @@ static const char * show_c_flags(INPUT_COMPLETE_FLAGS flags)
return s_cf; return s_cf;
} }
#define SHOW_C_CTX(func) fprintf(stderr, "%s: text='%s' flags=%s\n", func, text, show_c_flags(flags)) #define SHOW_C_CTX(func) fprintf(stderr, "%s: text='%s' flags=%s\n", func, text, show_c_flags(flags))
#else #else
#define SHOW_C_CTX(func) #define SHOW_C_CTX(func)
@ -107,17 +109,21 @@ filename_completion_function (const char * text, int state, INPUT_COMPLETE_FLAGS
} }
/* If we're starting the match process, initialize us a bit. */ /* If we're starting the match process, initialize us a bit. */
if (!state){ if (!state)
{
const char *temp; const char *temp;
g_free (dirname); g_free (dirname);
g_free (filename); g_free (filename);
g_free (users_dirname); g_free (users_dirname);
if ((*text) && (temp = strrchr (text, PATH_SEP))){ if ((*text) && (temp = strrchr (text, PATH_SEP)))
{
filename = g_strdup (++temp); filename = g_strdup (++temp);
dirname = g_strndup (text, temp - text); dirname = g_strndup (text, temp - text);
} else { }
else
{
dirname = g_strdup ("."); dirname = g_strdup (".");
filename = g_strdup (text); filename = g_strdup (text);
} }
@ -139,16 +145,20 @@ filename_completion_function (const char * text, int state, INPUT_COMPLETE_FLAGS
/* Now that we have some state, we can read the directory. */ /* Now that we have some state, we can read the directory. */
while (directory && (entry = mc_readdir (directory))){ while (directory && (entry = mc_readdir (directory)))
{
if (!str_is_valid_string (entry->d_name)) if (!str_is_valid_string (entry->d_name))
continue; continue;
/* Special case for no filename. /* Special case for no filename.
All entries except "." and ".." match. */ All entries except "." and ".." match. */
if (filename_len == 0) { if (filename_len == 0)
{
if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, "..")) if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, ".."))
continue; continue;
} else { }
else
{
/* Otherwise, if these match up to the length of filename, then /* Otherwise, if these match up to the length of filename, then
it may be a match. */ it may be a match. */
if ((entry->d_name[0] != filename[0]) || if ((entry->d_name[0] != filename[0]) ||
@ -156,7 +166,8 @@ filename_completion_function (const char * text, int state, INPUT_COMPLETE_FLAGS
strncmp (filename, entry->d_name, filename_len)) strncmp (filename, entry->d_name, filename_len))
continue; continue;
} }
isdir = 1; isexec = 0; isdir = 1;
isexec = 0;
{ {
char *tmp; char *tmp;
struct stat tempstat; struct stat tempstat;
@ -164,11 +175,13 @@ filename_completion_function (const char * text, int state, INPUT_COMPLETE_FLAGS
tmp = g_strconcat (dirname, PATH_SEP_STR, entry->d_name, (char *) NULL); tmp = g_strconcat (dirname, PATH_SEP_STR, entry->d_name, (char *) NULL);
canonicalize_pathname (tmp); canonicalize_pathname (tmp);
/* Unix version */ /* Unix version */
if (!mc_stat (tmp, &tempstat)){ if (!mc_stat (tmp, &tempstat))
{
uid_t my_uid = getuid (); uid_t my_uid = getuid ();
gid_t my_gid = getgid (); gid_t my_gid = getgid ();
if (!S_ISDIR (tempstat.st_mode)){ if (!S_ISDIR (tempstat.st_mode))
{
isdir = 0; isdir = 0;
if ((!my_uid && (tempstat.st_mode & 0111)) || if ((!my_uid && (tempstat.st_mode & 0111)) ||
(my_uid == tempstat.st_uid && (tempstat.st_mode & 0100)) || (my_uid == tempstat.st_uid && (tempstat.st_mode & 0100)) ||
@ -184,18 +197,18 @@ filename_completion_function (const char * text, int state, INPUT_COMPLETE_FLAGS
} }
g_free (tmp); g_free (tmp);
} }
if ((flags & INPUT_COMPLETE_COMMANDS) if ((flags & INPUT_COMPLETE_COMMANDS) && (isexec || isdir))
&& (isexec || isdir))
break; break;
if ((flags & INPUT_COMPLETE_CD) if ((flags & INPUT_COMPLETE_CD) && isdir)
&& isdir)
break; break;
if (flags & (INPUT_COMPLETE_FILENAMES)) if (flags & (INPUT_COMPLETE_FILENAMES))
break; break;
} }
if (!entry){ if (!entry)
if (directory){ {
if (directory)
{
mc_closedir (directory); mc_closedir (directory);
directory = NULL; directory = NULL;
} }
@ -206,20 +219,26 @@ filename_completion_function (const char * text, int state, INPUT_COMPLETE_FLAGS
g_free (users_dirname); g_free (users_dirname);
users_dirname = NULL; users_dirname = NULL;
return NULL; return NULL;
} else { }
else
{
char *temp; char *temp;
if (users_dirname && (users_dirname[0] != '.' || users_dirname[1])){ if (users_dirname && (users_dirname[0] != '.' || users_dirname[1]))
{
size_t dirlen = strlen (users_dirname); size_t dirlen = strlen (users_dirname);
temp = g_malloc (3 + dirlen + NLENGTH (entry)); temp = g_malloc (3 + dirlen + NLENGTH (entry));
strcpy (temp, users_dirname); strcpy (temp, users_dirname);
/* We need a `/' at the end. */ /* We need a `/' at the end. */
if (users_dirname[dirlen - 1] != PATH_SEP){ if (users_dirname[dirlen - 1] != PATH_SEP)
{
temp[dirlen] = PATH_SEP; temp[dirlen] = PATH_SEP;
temp[dirlen + 1] = 0; temp[dirlen + 1] = 0;
} }
strcat (temp, entry->d_name); strcat (temp, entry->d_name);
} else { }
else
{
temp = g_malloc (2 + NLENGTH (entry)); temp = g_malloc (2 + NLENGTH (entry));
strcpy (temp, entry->d_name); strcpy (temp, entry->d_name);
} }
@ -243,16 +262,17 @@ username_completion_function (const char *text, int state, INPUT_COMPLETE_FLAGS
if (text[0] == '\\' && text[1] == '~') if (text[0] == '\\' && text[1] == '~')
text++; text++;
if (!state){ /* Initialization stuff */ if (!state)
{ /* Initialization stuff */
setpwent (); setpwent ();
userlen = strlen (text + 1); userlen = strlen (text + 1);
} }
while ((entry = getpwent ()) != NULL){ while ((entry = getpwent ()) != NULL)
{
/* Null usernames should result in all users as possible completions. */ /* Null usernames should result in all users as possible completions. */
if (userlen == 0) if (userlen == 0)
break; break;
if (text[1] == entry->pw_name[0] if (text[1] == entry->pw_name[0] && !strncmp (text + 1, entry->pw_name, userlen))
&& !strncmp (text + 1, entry->pw_name, userlen))
break; break;
} }
@ -280,13 +300,15 @@ variable_completion_function (const char *text, int state, INPUT_COMPLETE_FLAGS
(void) flags; (void) flags;
SHOW_C_CTX ("variable_completion_function"); SHOW_C_CTX ("variable_completion_function");
if (!state){ /* Initialization stuff */ if (!state)
{ /* Initialization stuff */
isbrace = (text[1] == '{'); isbrace = (text[1] == '{');
varlen = strlen (text + 1 + isbrace); varlen = strlen (text + 1 + isbrace);
env_p = environ; env_p = environ;
} }
while (*env_p){ while (*env_p)
{
p = strchr (*env_p, '='); p = strchr (*env_p, '=');
if (p && p - *env_p >= varlen && !strncmp (text + 1 + isbrace, *env_p, varlen)) if (p && p - *env_p >= varlen && !strncmp (text + 1 + isbrace, *env_p, varlen))
break; break;
@ -295,7 +317,8 @@ variable_completion_function (const char *text, int state, INPUT_COMPLETE_FLAGS
if (!*env_p) if (!*env_p)
return NULL; return NULL;
else { else
{
char *temp = g_malloc (2 + 2 * isbrace + p - *env_p); char *temp = g_malloc (2 + 2 * isbrace + p - *env_p);
*temp = '$'; *temp = '$';
@ -317,7 +340,8 @@ variable_completion_function (const char *text, int state, INPUT_COMPLETE_FLAGS
static char **hosts = NULL; static char **hosts = NULL;
static char **hosts_p = NULL; static char **hosts_p = NULL;
static int hosts_alloclen = 0; static int hosts_alloclen = 0;
static void fetch_hosts (const char *filename) static void
fetch_hosts (const char *filename)
{ {
FILE *file = fopen (filename, "r"); FILE *file = fopen (filename, "r");
char buffer[256], *name; char buffer[256], *name;
@ -327,17 +351,17 @@ static void fetch_hosts (const char *filename)
if (!file) if (!file)
return; return;
while (fgets (buffer, 255, file) != NULL){ while (fgets (buffer, 255, file) != NULL)
{
/* Skip to first character. */ /* Skip to first character. */
for (bi = buffer; for (bi = buffer; bi[0] != '\0' && str_isspace (bi); str_next_char (&bi));
bi[0] != '\0' && str_isspace (bi);
str_next_char (&bi));
/* Ignore comments... */ /* Ignore comments... */
if (bi[0] == '#') if (bi[0] == '#')
continue; continue;
/* Handle $include. */ /* Handle $include. */
if (!strncmp (bi, "$include ", 9)){ if (!strncmp (bi, "$include ", 9))
{
char *includefile = bi + 9; char *includefile = bi + 9;
char *t; char *t;
@ -360,34 +384,38 @@ static void fetch_hosts (const char *filename)
str_next_char (&bi); str_next_char (&bi);
/* Get the host names separated by white space. */ /* Get the host names separated by white space. */
while (bi[0] != '\0' && bi[0] != '#'){ while (bi[0] != '\0' && bi[0] != '#')
{
while (bi[0] != '\0' && str_isspace (bi)) while (bi[0] != '\0' && str_isspace (bi))
str_next_char (&bi); str_next_char (&bi);
if (bi[0] == '#') if (bi[0] == '#')
continue; continue;
for (start = bi; for (start = bi; bi[0] != '\0' && !str_isspace (bi); str_next_char (&bi));
bi[0] != '\0' && !str_isspace (bi);
str_next_char (&bi));
if (bi - start == 0) continue; if (bi - start == 0)
continue;
name = g_strndup (start, bi - start); name = g_strndup (start, bi - start);
{ {
char **host_p; char **host_p;
if (hosts_p - hosts >= hosts_alloclen){ if (hosts_p - hosts >= hosts_alloclen)
{
int j = hosts_p - hosts; int j = hosts_p - hosts;
hosts = g_realloc ((void *)hosts, ((hosts_alloclen += 30) + 1) * sizeof (char *)); hosts =
g_realloc ((void *) hosts, ((hosts_alloclen += 30) + 1) * sizeof (char *));
hosts_p = hosts + j; hosts_p = hosts + j;
} }
for (host_p = hosts; host_p < hosts_p; host_p++) for (host_p = hosts; host_p < hosts_p; host_p++)
if (!strcmp (name, *host_p)) if (!strcmp (name, *host_p))
break; /* We do not want any duplicates */ break; /* We do not want any duplicates */
if (host_p == hosts_p){ if (host_p == hosts_p)
{
*(hosts_p++) = name; *(hosts_p++) = name;
*hosts_p = NULL; *hosts_p = NULL;
} else }
else
g_free (name); g_free (name);
} }
} }
@ -404,10 +432,12 @@ hostname_completion_function (const char *text, int state, INPUT_COMPLETE_FLAGS
(void) flags; (void) flags;
SHOW_C_CTX ("hostname_completion_function"); SHOW_C_CTX ("hostname_completion_function");
if (!state){ /* Initialization stuff */ if (!state)
{ /* Initialization stuff */
const char *p; const char *p;
if (hosts != NULL){ if (hosts != NULL)
{
for (host_p = hosts; *host_p; host_p++) for (host_p = hosts; *host_p; host_p++)
g_free (*host_p); g_free (*host_p);
g_free (hosts); g_free (hosts);
@ -421,7 +451,8 @@ hostname_completion_function (const char *text, int state, INPUT_COMPLETE_FLAGS
textlen = strlen (text + textstart); textlen = strlen (text + textstart);
} }
while (*host_p){ while (*host_p)
{
if (!textlen) if (!textlen)
break; /* Match all of them */ break; /* Match all of them */
else if (!strncmp (text + textstart, *host_p, textlen)) else if (!strncmp (text + textstart, *host_p, textlen))
@ -429,13 +460,16 @@ hostname_completion_function (const char *text, int state, INPUT_COMPLETE_FLAGS
host_p++; host_p++;
} }
if (!*host_p){ if (!*host_p)
{
for (host_p = hosts; *host_p; host_p++) for (host_p = hosts; *host_p; host_p++)
g_free (*host_p); g_free (*host_p);
g_free (hosts); g_free (hosts);
hosts = NULL; hosts = NULL;
return NULL; return NULL;
} else { }
else
{
char *temp = g_malloc (2 + strlen (*host_p)); char *temp = g_malloc (2 + strlen (*host_p));
if (textstart) if (textstart)
@ -459,7 +493,7 @@ command_completion_function (const char *_text, int state, INPUT_COMPLETE_FLAGS
static const char *path_end; static const char *path_end;
static gboolean isabsolute; static gboolean isabsolute;
static int phase; static int phase;
static int text_len; static size_t text_len;
static const char *const *words; static const char *const *words;
static char *path; static char *path;
static char *cur_path; static char *cur_path;
@ -487,26 +521,32 @@ command_completion_function (const char *_text, int state, INPUT_COMPLETE_FLAGS
text = strutils_shell_unescape (_text); text = strutils_shell_unescape (_text);
flags &= ~INPUT_COMPLETE_SHELL_ESC; flags &= ~INPUT_COMPLETE_SHELL_ESC;
if (!state) { /* Initialize us a little bit */ if (!state)
{ /* Initialize us a little bit */
isabsolute = strchr (text, PATH_SEP) != NULL; isabsolute = strchr (text, PATH_SEP) != NULL;
if (!isabsolute) { if (!isabsolute)
{
words = bash_reserved; words = bash_reserved;
phase = 0; phase = 0;
text_len = strlen (text); text_len = strlen (text);
if (!path && (path = g_strdup (getenv ("PATH"))) != NULL) { if (!path && (path = g_strdup (getenv ("PATH"))) != NULL)
{
p = path; p = path;
path_end = strchr (p, 0); path_end = strchr (p, 0);
while ((p = strchr (p, PATH_ENV_SEP))) { while ((p = strchr (p, PATH_ENV_SEP)))
{
*p++ = 0; *p++ = 0;
} }
} }
} }
} }
if (isabsolute) { if (isabsolute)
{
p = filename_completion_function (text, state, flags); p = filename_completion_function (text, state, flags);
if (p) { if (p)
{
char *temp_p = p; char *temp_p = p;
p = strutils_shell_escape (p); p = strutils_shell_escape (p);
g_free (temp_p); g_free (temp_p);
@ -517,19 +557,28 @@ command_completion_function (const char *_text, int state, INPUT_COMPLETE_FLAGS
} }
found = NULL; found = NULL;
switch (phase) { switch (phase)
{
case 0: /* Reserved words */ case 0: /* Reserved words */
while (*words) { while (*words)
if (!strncmp (*words, text, text_len)) {
if (strncmp (*words, text, text_len) == 0)
{
g_free (text);
return g_strdup (*(words++)); return g_strdup (*(words++));
}
words++; words++;
} }
phase++; phase++;
words = bash_builtins; words = bash_builtins;
case 1: /* Builtin commands */ case 1: /* Builtin commands */
while (*words) { while (*words)
if (!strncmp (*words, text, text_len)) {
if (strncmp (*words, text, text_len) == 0)
{
g_free (text);
return g_strdup (*(words++)); return g_strdup (*(words++));
}
words++; words++;
} }
phase++; phase++;
@ -538,8 +587,10 @@ command_completion_function (const char *_text, int state, INPUT_COMPLETE_FLAGS
cur_path = path; cur_path = path;
cur_word = NULL; cur_word = NULL;
case 2: /* And looking through the $PATH */ case 2: /* And looking through the $PATH */
while (!found) { while (!found)
if (!cur_word) { {
if (!cur_word)
{
char *expanded; char *expanded;
if (cur_path >= path_end) if (cur_path >= path_end)
@ -551,20 +602,22 @@ command_completion_function (const char *_text, int state, INPUT_COMPLETE_FLAGS
cur_path = strchr (cur_path, 0) + 1; cur_path = strchr (cur_path, 0) + 1;
init_state = state; init_state = state;
} }
found = found = filename_completion_function (cur_word, state - init_state, flags);
filename_completion_function (cur_word, if (!found)
state - init_state, flags); {
if (!found) {
g_free (cur_word); g_free (cur_word);
cur_word = NULL; cur_word = NULL;
} }
} }
} }
if (found == NULL) { if (found == NULL)
{
g_free (path); g_free (path);
path = NULL; path = NULL;
} else if ((p = strrchr (found, PATH_SEP)) != NULL) { }
else if ((p = strrchr (found, PATH_SEP)) != NULL)
{
char *tmp = found; char *tmp = found;
found = strutils_shell_escape (p + 1); found = strutils_shell_escape (p + 1);
g_free (tmp); g_free (tmp);
@ -604,9 +657,11 @@ completion_matches (const char *text, CompletionFunction entry_function, INPUT_C
match_list[1] = NULL; match_list[1] = NULL;
while ((string = (*entry_function) (text, matches, flags)) != NULL){ while ((string = (*entry_function) (text, matches, flags)) != NULL)
{
if (matches + 1 == match_list_size) if (matches + 1 == match_list_size)
match_list = (char **) g_realloc (match_list, ((match_list_size += 30) + 1) * sizeof (char *)); match_list =
(char **) g_realloc (match_list, ((match_list_size += 30) + 1) * sizeof (char *));
match_list[++matches] = string; match_list[++matches] = string;
match_list[matches + 1] = NULL; match_list[matches + 1] = NULL;
} }
@ -619,10 +674,13 @@ completion_matches (const char *text, CompletionFunction entry_function, INPUT_C
int low = 4096; /* Count of max-matched characters. */ int low = 4096; /* Count of max-matched characters. */
/* If only one match, just use that. */ /* If only one match, just use that. */
if (matches == 1){ if (matches == 1)
{
match_list[0] = match_list[1]; match_list[0] = match_list[1];
match_list[1] = NULL; match_list[1] = NULL;
} else { }
else
{
int j; int j;
qsort (match_list + 1, matches, sizeof (char *), match_compare); qsort (match_list + 1, matches, sizeof (char *), match_compare);
@ -637,36 +695,43 @@ completion_matches (const char *text, CompletionFunction entry_function, INPUT_C
char *si, *sj; char *si, *sj;
char *ni, *nj; char *ni, *nj;
for (si = match_list[i], sj = match_list[j]; for (si = match_list[i], sj = match_list[j]; si[0] && sj[0];)
si[0] && sj[0];) { {
ni = str_get_next_char (si); ni = str_get_next_char (si);
nj = str_get_next_char (sj); nj = str_get_next_char (sj);
if (ni - si != nj - sj) break; if (ni - si != nj - sj)
if (strncmp (si, sj, ni - si) != 0) break; break;
if (strncmp (si, sj, ni - si) != 0)
break;
si = ni; si = ni;
sj = nj; sj = nj;
} }
if (si[0] == '\0' && sj[0] == '\0'){ /* Two equal strings */ if (si[0] == '\0' && sj[0] == '\0')
{ /* Two equal strings */
g_free (match_list[j]); g_free (match_list[j]);
j++; j++;
if (j > matches) if (j > matches)
break; break;
continue; /* Look for a run of equal strings */ continue; /* Look for a run of equal strings */
} else }
if (low > si - match_list[i]) low = si - match_list[i]; else if (low > si - match_list[i])
low = si - match_list[i];
if (i + 1 != j) /* So there's some gap */ if (i + 1 != j) /* So there's some gap */
match_list[i + 1] = match_list[j]; match_list[i + 1] = match_list[j];
i++; j++; i++;
j++;
} }
matches = i; matches = i;
match_list[matches + 1] = NULL; match_list[matches + 1] = NULL;
match_list[0] = g_strndup (match_list[1], low); match_list[0] = g_strndup (match_list[1], low);
} }
} else { /* There were no matches. */ }
else
{ /* There were no matches. */
g_free (match_list); g_free (match_list);
match_list = NULL; match_list = NULL;
} }
@ -721,18 +786,21 @@ try_complete (char *text, int *start, int *end, INPUT_COMPLETE_FLAGS flags)
the start of the line (ignoring preceding whitespace), or if it the start of the line (ignoring preceding whitespace), or if it
appears after a character that separates commands. And we have to appears after a character that separates commands. And we have to
be in a INPUT_COMPLETE_COMMANDS flagged Input line. */ be in a INPUT_COMPLETE_COMMANDS flagged Input line. */
if (!is_cd && (flags & INPUT_COMPLETE_COMMANDS)){ if (!is_cd && (flags & INPUT_COMPLETE_COMMANDS))
{
ti = str_get_prev_char (&text[*start]); ti = str_get_prev_char (&text[*start]);
while (ti > text && (ti[0] == ' ' || ti[0] == '\t')) while (ti > text && (ti[0] == ' ' || ti[0] == '\t'))
str_prev_char (&ti); str_prev_char (&ti);
if (ti <= text && (ti[0] == ' ' || ti[0] == '\t')) if (ti <= text && (ti[0] == ' ' || ti[0] == '\t'))
in_command_position++; in_command_position++;
else if (strchr (command_separator_chars, ti[0])){ else if (strchr (command_separator_chars, ti[0]))
{
register int this_char, prev_char; register int this_char, prev_char;
in_command_position++; in_command_position++;
if (ti > text){ if (ti > text)
{
/* Handle the two character tokens `>&', `<&', and `>|'. /* Handle the two character tokens `>&', `<&', and `>|'.
We are not in a command position after one of these. */ We are not in a command position after one of these. */
this_char = ti[0]; this_char = ti[0];
@ -754,14 +822,16 @@ try_complete (char *text, int *start, int *end, INPUT_COMPLETE_FLAGS flags)
q = strrchr (word, '$'); q = strrchr (word, '$');
if (flags & INPUT_COMPLETE_HOSTNAMES) if (flags & INPUT_COMPLETE_HOSTNAMES)
r = strrchr (word, '@'); r = strrchr (word, '@');
if (q && q [1] == '(' && INPUT_COMPLETE_COMMANDS){ if (q && q[1] == '(' && INPUT_COMPLETE_COMMANDS)
{
if (q > p) if (q > p)
p = str_get_next_char (q); p = str_get_next_char (q);
q = NULL; q = NULL;
} }
/* Command substitution? */ /* Command substitution? */
if (p > q && p > r){ if (p > q && p > r)
{
SHOW_C_CTX ("try_complete:cmd_backq_subst"); SHOW_C_CTX ("try_complete:cmd_backq_subst");
matches = completion_matches (str_cget_next_char (p), matches = completion_matches (str_cget_next_char (p),
command_completion_function, command_completion_function,
@ -771,7 +841,8 @@ try_complete (char *text, int *start, int *end, INPUT_COMPLETE_FLAGS flags)
} }
/* Variable name? */ /* Variable name? */
else if (q > p && q > r){ else if (q > p && q > r)
{
SHOW_C_CTX ("try_complete:var_subst"); SHOW_C_CTX ("try_complete:var_subst");
matches = completion_matches (q, variable_completion_function, flags); matches = completion_matches (q, variable_completion_function, flags);
if (matches) if (matches)
@ -780,7 +851,8 @@ try_complete (char *text, int *start, int *end, INPUT_COMPLETE_FLAGS flags)
/* Starts with '@', then look through the known hostnames for /* Starts with '@', then look through the known hostnames for
completion first. */ completion first. */
else if (r > p && r > q){ else if (r > p && r > q)
{
SHOW_C_CTX ("try_complete:host_subst"); SHOW_C_CTX ("try_complete:host_subst");
matches = completion_matches (r, hostname_completion_function, flags); matches = completion_matches (r, hostname_completion_function, flags);
if (matches) if (matches)
@ -802,20 +874,25 @@ try_complete (char *text, int *start, int *end, INPUT_COMPLETE_FLAGS flags)
if (!matches && in_command_position) if (!matches && in_command_position)
{ {
SHOW_C_CTX ("try_complete:cmd_subst"); SHOW_C_CTX ("try_complete:cmd_subst");
matches = completion_matches (word, command_completion_function, flags & (~INPUT_COMPLETE_FILENAMES)); matches =
completion_matches (word, command_completion_function,
flags & (~INPUT_COMPLETE_FILENAMES));
} }
else if (!matches && (flags & INPUT_COMPLETE_FILENAMES)){ else if (!matches && (flags & INPUT_COMPLETE_FILENAMES))
{
if (is_cd) if (is_cd)
flags &= ~(INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_COMMANDS); flags &= ~(INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_COMMANDS);
SHOW_C_CTX ("try_complete:filename_subst_1"); SHOW_C_CTX ("try_complete:filename_subst_1");
matches = completion_matches (word, filename_completion_function, flags); matches = completion_matches (word, filename_completion_function, flags);
if (!matches && is_cd && *word != PATH_SEP && *word != '~'){ if (!matches && is_cd && *word != PATH_SEP && *word != '~')
{
q = text + *start; q = text + *start;
for (p = text; *p && p < q && (*p == ' ' || *p == '\t'); str_next_char (&p)); for (p = text; *p && p < q && (*p == ' ' || *p == '\t'); str_next_char (&p));
if (!strncmp (p, "cd", 2)) if (!strncmp (p, "cd", 2))
for (p += 2; *p && p < q && (*p == ' ' || *p == '\t'); str_next_char (&p)); for (p += 2; *p && p < q && (*p == ' ' || *p == '\t'); str_next_char (&p));
if (p == q){ if (p == q)
{
char *const cdpath_ref = g_strdup (getenv ("CDPATH")); char *const cdpath_ref = g_strdup (getenv ("CDPATH"));
char *cdpath = cdpath_ref; char *cdpath = cdpath_ref;
char c, *s; char c, *s;
@ -824,13 +901,15 @@ try_complete (char *text, int *start, int *end, INPUT_COMPLETE_FLAGS flags)
c = 0; c = 0;
else else
c = ':'; c = ':';
while (!matches && c == ':'){ while (!matches && c == ':')
{
s = strchr (cdpath, ':'); s = strchr (cdpath, ':');
if (s == NULL) if (s == NULL)
s = strchr (cdpath, 0); s = strchr (cdpath, 0);
c = *s; c = *s;
*s = 0; *s = 0;
if (*cdpath){ if (*cdpath)
{
r = concat_dir_and_file (cdpath, word); r = concat_dir_and_file (cdpath, word);
SHOW_C_CTX ("try_complete:filename_subst_2"); SHOW_C_CTX ("try_complete:filename_subst_2");
matches = completion_matches (r, filename_completion_function, flags); matches = completion_matches (r, filename_completion_function, flags);
@ -849,7 +928,8 @@ try_complete (char *text, int *start, int *end, INPUT_COMPLETE_FLAGS flags)
return matches; return matches;
} }
void free_completions (WInput *in) void
free_completions (WInput * in)
{ {
char **p; char **p;
@ -872,21 +952,26 @@ insert_text (WInput *in, char *text, ssize_t size)
int buff_len = str_length (in->buffer); int buff_len = str_length (in->buffer);
size = min (size, (ssize_t) strlen (text)) + start - end; size = min (size, (ssize_t) strlen (text)) + start - end;
if (strlen (in->buffer) + size >= (size_t) in->current_max_size){ if (strlen (in->buffer) + size >= (size_t) in->current_max_size)
{
/* Expand the buffer */ /* Expand the buffer */
char *narea = g_try_realloc (in->buffer, in->current_max_size char *narea = g_try_realloc (in->buffer, in->current_max_size + size + in->field_width);
+ size + in->field_width); if (narea != NULL)
if (narea != NULL) { {
in->buffer = narea; in->buffer = narea;
in->current_max_size += size + in->field_width; in->current_max_size += size + in->field_width;
} }
} }
if (strlen (in->buffer)+1 < (size_t) in->current_max_size){ if (strlen (in->buffer) + 1 < (size_t) in->current_max_size)
if (size > 0){ {
if (size > 0)
{
int i = strlen (&in->buffer[end]); int i = strlen (&in->buffer[end]);
for (; i >= 0; i--) for (; i >= 0; i--)
in->buffer[end + size + i] = in->buffer[end + i]; in->buffer[end + size + i] = in->buffer[end + i];
} else if (size < 0){ }
else if (size < 0)
{
char *p = in->buffer + end + size, *q = in->buffer + end; char *p = in->buffer + end + size, *q = in->buffer + end;
while (*q) while (*q)
*(p++) = *(q++); *(p++) = *(q++);
@ -901,15 +986,16 @@ insert_text (WInput *in, char *text, ssize_t size)
} }
static cb_ret_t static cb_ret_t
query_callback (Dlg_head *h, Widget *sender, query_callback (Dlg_head * h, Widget * sender, dlg_msg_t msg, int parm, void *data)
dlg_msg_t msg, int parm, void *data)
{ {
static char buff[MB_LEN_MAX] = ""; static char buff[MB_LEN_MAX] = "";
static int bl = 0; static int bl = 0;
switch (msg) { switch (msg)
{
case DLG_KEY: case DLG_KEY:
switch (parm) { switch (parm)
{
case KEY_LEFT: case KEY_LEFT:
case KEY_RIGHT: case KEY_RIGHT:
bl = 0; bl = 0;
@ -919,19 +1005,23 @@ query_callback (Dlg_head *h, Widget *sender,
case KEY_BACKSPACE: case KEY_BACKSPACE:
bl = 0; bl = 0;
if (end == min_end) { if (end == min_end)
{
h->ret_value = 0; h->ret_value = 0;
dlg_stop (h); dlg_stop (h);
} else { }
else
{
int i; int i;
GList *e; GList *e;
for (i = 0, e = ((WListbox *) h->current)->list; for (i = 0, e = ((WListbox *) h->current)->list;
e != NULL; e != NULL; i++, e = g_list_next (e))
i++, e = g_list_next (e)) { {
WLEntry *le = (WLEntry *) e->data; WLEntry *le = (WLEntry *) e->data;
if (strncmp (input->buffer + start, le->text, end - start - 1) == 0) { if (strncmp (input->buffer + start, le->text, end - start - 1) == 0)
{
listbox_select_entry ((WListbox *) h->current, i); listbox_select_entry ((WListbox *) h->current, i);
end = str_get_prev_char (&(input->buffer[end])) - input->buffer; end = str_get_prev_char (&(input->buffer[end])) - input->buffer;
handle_char (input, parm); handle_char (input, parm);
@ -943,18 +1033,23 @@ query_callback (Dlg_head *h, Widget *sender,
return MSG_HANDLED; return MSG_HANDLED;
default: default:
if (parm < 32 || parm > 256) { if (parm < 32 || parm > 256)
{
bl = 0; bl = 0;
if (is_in_input_map (input, parm) == 2) { if (is_in_input_map (input, parm) == 2)
{
if (end == min_end) if (end == min_end)
return MSG_HANDLED; return MSG_HANDLED;
h->ret_value = B_USER; /* This means we want to refill the h->ret_value = B_USER; /* This means we want to refill the
list box and start again */ list box and start again */
dlg_stop (h); dlg_stop (h);
return MSG_HANDLED; return MSG_HANDLED;
} else }
else
return MSG_NOT_HANDLED; return MSG_NOT_HANDLED;
} else { }
else
{
GList *e; GList *e;
int i; int i;
int need_redraw = 0; int need_redraw = 0;
@ -964,7 +1059,8 @@ query_callback (Dlg_head *h, Widget *sender,
buff[bl] = (char) parm; buff[bl] = (char) parm;
bl++; bl++;
buff[bl] = '\0'; buff[bl] = '\0';
switch (str_is_valid_char (buff, bl)) { switch (str_is_valid_char (buff, bl))
{
case -1: case -1:
bl = 0; bl = 0;
case -2: case -2:
@ -972,20 +1068,24 @@ query_callback (Dlg_head *h, Widget *sender,
} }
for (i = 0, e = ((WListbox *) h->current)->list; for (i = 0, e = ((WListbox *) h->current)->list;
e != NULL; e != NULL; i++, e = g_list_next (e))
i++, e = g_list_next (e)) { {
WLEntry *le = (WLEntry *) e->data; WLEntry *le = (WLEntry *) e->data;
if (strncmp (input->buffer + start, le->text, end - start) == 0) { if (strncmp (input->buffer + start, le->text, end - start) == 0)
if (strncmp (&le->text[end - start], buff, bl) == 0) { {
if (need_redraw) { if (strncmp (&le->text[end - start], buff, bl) == 0)
{
if (need_redraw)
{
char *si, *sl; char *si, *sl;
char *nexti, *nextl; char *nexti, *nextl;
si = &(le->text[end - start]); si = &(le->text[end - start]);
sl = &(last_text[end - start]); sl = &(last_text[end - start]);
for (; si[0] != '\0' && sl[0] != '\0';) { for (; si[0] != '\0' && sl[0] != '\0';)
{
nexti = str_get_next_char (si); nexti = str_get_next_char (si);
nextl = str_get_next_char (sl); nextl = str_get_next_char (sl);
@ -1003,7 +1103,9 @@ query_callback (Dlg_head *h, Widget *sender,
last_text = le->text; last_text = le->text;
need_redraw = 2; need_redraw = 2;
} else { }
else
{
need_redraw = 1; need_redraw = 1;
listbox_select_entry ((WListbox *) h->current, i); listbox_select_entry ((WListbox *) h->current, i);
last_text = le->text; last_text = le->text;
@ -1012,10 +1114,13 @@ query_callback (Dlg_head *h, Widget *sender,
} }
} }
if (need_redraw == 2) { if (need_redraw == 2)
{
insert_text (input, last_text, low); insert_text (input, last_text, low);
send_message (h->current, WIDGET_DRAW, 0); send_message (h->current, WIDGET_DRAW, 0);
} else if (need_redraw == 1) { }
else if (need_redraw == 1)
{
h->ret_value = B_ENTER; h->ret_value = B_ENTER;
dlg_stop (h); dlg_stop (h);
} }
@ -1040,12 +1145,16 @@ complete_engine (WInput *in, int what_to_do)
if (in->completions && (str_offset_to_pos (in->buffer, in->point)) != end) if (in->completions && (str_offset_to_pos (in->buffer, in->point)) != end)
free_completions (in); free_completions (in);
if (!in->completions){ if (!in->completions)
{
end = str_offset_to_pos (in->buffer, in->point); end = str_offset_to_pos (in->buffer, in->point);
for (s = in->point ? in->point - 1 : 0; s >= 0; s--) { for (s = in->point ? in->point - 1 : 0; s >= 0; s--)
{
start = str_offset_to_pos (in->buffer, s); start = str_offset_to_pos (in->buffer, s);
if (strchr (" \t;|<>", in->buffer [start])) { if (strchr (" \t;|<>", in->buffer[start]))
if (start < end) start = str_offset_to_pos (in->buffer, s + 1); {
if (start < end)
start = str_offset_to_pos (in->buffer, s + 1);
/* FIXME: maybe need check '\\' prev char /* FIXME: maybe need check '\\' prev char
if (start > 0 && in->buffer [start-1] == '\\') if (start > 0 && in->buffer [start-1] == '\\')
*/ */
@ -1055,18 +1164,23 @@ complete_engine (WInput *in, int what_to_do)
in->completions = try_complete (in->buffer, &start, &end, in->completion_flags); in->completions = try_complete (in->buffer, &start, &end, in->completion_flags);
} }
if (in->completions){ if (in->completions)
if (what_to_do & DO_INSERTION || ((what_to_do & DO_QUERY) && !in->completions[1])) { {
if (what_to_do & DO_INSERTION || ((what_to_do & DO_QUERY) && !in->completions[1]))
{
char *lc_complete = in->completions[0]; char *lc_complete = in->completions[0];
if (insert_text (in, lc_complete, strlen (lc_complete))){ if (insert_text (in, lc_complete, strlen (lc_complete)))
{
if (in->completions[1]) if (in->completions[1])
tty_beep (); tty_beep ();
else else
free_completions (in); free_completions (in);
} else }
else
tty_beep (); tty_beep ();
} }
if ((what_to_do & DO_QUERY) && in->completions && in->completions [1]) { if ((what_to_do & DO_QUERY) && in->completions && in->completions[1])
{
int maxlen = 0, i, count = 0; int maxlen = 0, i, count = 0;
int x, y, w, h; int x, y, w, h;
int start_x, start_y; int start_x, start_y;
@ -1079,14 +1193,20 @@ complete_engine (WInput *in, int what_to_do)
maxlen = i; maxlen = i;
start_x = in->widget.x; start_x = in->widget.x;
start_y = in->widget.y; start_y = in->widget.y;
if (start_y - 2 >= count) { if (start_y - 2 >= count)
{
y = start_y - 2 - count; y = start_y - 2 - count;
h = 2 + count; h = 2 + count;
} else { }
if (start_y >= LINES - start_y - 1) { else
{
if (start_y >= LINES - start_y - 1)
{
y = 0; y = 0;
h = start_y; h = start_y;
} else { }
else
{
y = start_y + 1; y = start_y + 1;
h = LINES - start_y - 1; h = LINES - start_y - 1;
} }
@ -1112,7 +1232,8 @@ complete_engine (WInput *in, int what_to_do)
listbox_add_item (query_list, LISTBOX_APPEND_AT_END, 0, *p, NULL); listbox_add_item (query_list, LISTBOX_APPEND_AT_END, 0, *p, NULL);
run_dlg (query_dlg); run_dlg (query_dlg);
q = NULL; q = NULL;
if (query_dlg->ret_value == B_ENTER){ if (query_dlg->ret_value == B_ENTER)
{
listbox_get_current (query_list, &q, NULL); listbox_get_current (query_list, &q, NULL);
if (q) if (q)
insert_text (in, q, strlen (q)); insert_text (in, q, strlen (q));
@ -1124,16 +1245,19 @@ complete_engine (WInput *in, int what_to_do)
if (i == B_USER) if (i == B_USER)
return 1; return 1;
} }
} else }
else
tty_beep (); tty_beep ();
return 0; return 0;
} }
void complete (WInput *in) void
complete (WInput * in)
{ {
int engine_flags; int engine_flags;
if (!str_is_valid_string (in->buffer)) return; if (!str_is_valid_string (in->buffer))
return;
if (in->completions) if (in->completions)
engine_flags = DO_QUERY; engine_flags = DO_QUERY;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1881,7 +1881,6 @@ void
edit_search_cmd (WEdit * edit, int again) edit_search_cmd (WEdit * edit, int again)
{ {
char *search_string = NULL, *search_string_dup = NULL; char *search_string = NULL, *search_string_dup = NULL;
gsize len = 0; gsize len = 0;
if (!edit) if (!edit)
@ -1910,36 +1909,45 @@ edit_search_cmd (WEdit * edit, int again)
{ {
#ifdef HAVE_CHARSET #ifdef HAVE_CHARSET
GString *tmp; GString *tmp;
if (search_string && *search_string) if (search_string && *search_string)
{ {
tmp = str_convert_to_display (search_string); tmp = str_convert_to_display (search_string);
if (tmp != NULL)
g_free (search_string_dup); {
search_string_dup = NULL; if (tmp->len == 0)
g_string_free (tmp, TRUE);
if (tmp && tmp->len) else
search_string = search_string_dup = tmp->str; {
g_string_free (tmp, FALSE); g_free (search_string);
search_string = search_string_dup = g_string_free (tmp, FALSE);
}
}
} }
#endif /* HAVE_CHARSET */ #endif /* HAVE_CHARSET */
editcmd_dialog_search_show (edit, &search_string); editcmd_dialog_search_show (edit, &search_string);
g_free (search_string_dup);
search_string_dup = NULL;
#ifdef HAVE_CHARSET #ifdef HAVE_CHARSET
if (search_string && *search_string) if (search_string && *search_string)
{ {
tmp = str_convert_to_input (search_string); tmp = str_convert_to_input (search_string);
if (tmp && tmp->len) if (tmp != NULL)
search_string = tmp->str; {
if (tmp->len == 0)
g_string_free (tmp, FALSE); g_string_free (tmp, TRUE);
else
if (search_string_dup) {
g_free (search_string_dup); g_free (search_string);
search_string = g_string_free (tmp, FALSE);
}
}
} }
#endif /* HAVE_CHARSET */ #endif /* HAVE_CHARSET */
edit_push_action (edit, KEY_PRESS + edit->start_display); edit_push_action (edit, KEY_PRESS + edit->start_display);
if (!search_string) if (search_string == NULL)
{ {
edit->force |= REDRAW_COMPLETELY; edit->force |= REDRAW_COMPLETELY;
edit_scroll_screen_over_cursor (edit); edit_scroll_screen_over_cursor (edit);
@ -1959,8 +1967,10 @@ edit_search_cmd (WEdit * edit, int again)
if (edit->search == NULL) if (edit->search == NULL)
{ {
edit->search_start = edit->curs1; edit->search_start = edit->curs1;
g_free (search_string);
return; return;
} }
edit->search->search_type = edit_search_options.type; edit->search->search_type = edit_search_options.type;
edit->search->is_all_charsets = edit_search_options.all_codepages; edit->search->is_all_charsets = edit_search_options.all_codepages;
edit->search->is_case_sentitive = edit_search_options.case_sens; edit->search->is_case_sentitive = edit_search_options.case_sens;
@ -1968,6 +1978,8 @@ edit_search_cmd (WEdit * edit, int again)
edit->search->search_fn = edit_search_cmd_callback; edit->search->search_fn = edit_search_cmd_callback;
} }
g_free (search_string);
if (search_create_bookmark) if (search_create_bookmark)
{ {
edit_search_cmd_search_create_bookmark (edit); edit_search_cmd_search_create_bookmark (edit);

Просмотреть файл

@ -93,7 +93,7 @@ void
editcmd_dialog_replace_show (WEdit * edit, const char *search_default, const char *replace_default, editcmd_dialog_replace_show (WEdit * edit, const char *search_default, const char *replace_default,
/*@out@ */ char **search_text, /*@out@ */ char **replace_text) /*@out@ */ char **search_text, /*@out@ */ char **replace_text)
{ {
if (*search_default == '\0') if ((search_default == NULL) || (*search_default == '\0'))
search_default = INPUT_LAST_TEXT; search_default = INPUT_LAST_TEXT;
{ {
@ -162,7 +162,7 @@ editcmd_dialog_search_show (WEdit * edit, char **search_text)
{ {
(void) edit; (void) edit;
if (*search_text == '\0') if (*search_text == NULL)
*search_text = INPUT_LAST_TEXT; *search_text = INPUT_LAST_TEXT;
{ {

Просмотреть файл

@ -151,7 +151,8 @@ static int get_fs_usage (char *path, struct fs_usage *fsp);
static struct mount_entry *mount_list = NULL; static struct mount_entry *mount_list = NULL;
static void free_mount_entry (struct mount_entry *me) static void
free_mount_entry (struct mount_entry *me)
{ {
if (!me) if (!me)
return; return;
@ -169,12 +170,14 @@ static void free_mount_entry (struct mount_entry *me)
No prefix (like '0x') or suffix (like 'h') is expected to be No prefix (like '0x') or suffix (like 'h') is expected to be
part of CP. */ part of CP. */
static int xatoi (const char *cp) static int
xatoi (const char *cp)
{ {
int val; int val;
val = 0; val = 0;
while (*cp) { while (*cp)
{
if (*cp >= 'a' && *cp <= 'f') if (*cp >= 'a' && *cp <= 'f')
val = val * 16 + *cp - 'a' + 10; val = val * 16 + *cp - 'a' + 10;
else if (*cp >= 'A' && *cp <= 'F') else if (*cp >= 'A' && *cp <= 'F')
@ -192,9 +195,11 @@ static int xatoi (const char *cp)
#ifdef MOUNTED_GETMNTINFO #ifdef MOUNTED_GETMNTINFO
#ifndef HAVE_STRUCT_STATFS_F_FSTYPENAME #ifndef HAVE_STRUCT_STATFS_F_FSTYPENAME
static char *fstype_to_string (short t) static char *
fstype_to_string (short t)
{
switch (t)
{ {
switch (t) {
#ifdef MOUNT_PC #ifdef MOUNT_PC
case MOUNT_PC: case MOUNT_PC:
return "pc"; return "pc";
@ -334,9 +339,9 @@ read_filesystem_list (int need_fs_type, int all_fs)
if (fp == NULL) if (fp == NULL)
return NULL; return NULL;
while ((mnt = getmntent (fp))) { while ((mnt = getmntent (fp)))
if (!all_fs && (!strcmp (mnt->mnt_type, "ignore") {
|| !strcmp (mnt->mnt_type, "auto"))) if (!all_fs && (!strcmp (mnt->mnt_type, "ignore") || !strcmp (mnt->mnt_type, "auto")))
continue; continue;
me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
@ -344,12 +349,14 @@ read_filesystem_list (int need_fs_type, int all_fs)
me->me_mountdir = strdup (mnt->mnt_dir); me->me_mountdir = strdup (mnt->mnt_dir);
me->me_type = strdup (mnt->mnt_type); me->me_type = strdup (mnt->mnt_type);
devopt = strstr (mnt->mnt_opts, "dev="); devopt = strstr (mnt->mnt_opts, "dev=");
if (devopt) { if (devopt)
{
if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X')) if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
me->me_dev = xatoi (devopt + 6); me->me_dev = xatoi (devopt + 6);
else else
me->me_dev = xatoi (devopt + 4); me->me_dev = xatoi (devopt + 4);
} else }
else
me->me_dev = -1; /* Magic; means not known yet. */ me->me_dev = -1; /* Magic; means not known yet. */
me->me_next = NULL; me->me_next = NULL;
@ -372,7 +379,8 @@ read_filesystem_list (int need_fs_type, int all_fs)
entries = getmntinfo (&fsp, MNT_NOWAIT); entries = getmntinfo (&fsp, MNT_NOWAIT);
if (entries < 0) if (entries < 0)
return NULL; return NULL;
while (entries-- > 0) { while (entries-- > 0)
{
me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
me->me_devname = strdup (fsp->f_mntfromname); me->me_devname = strdup (fsp->f_mntfromname);
me->me_mountdir = strdup (fsp->f_mntonname); me->me_mountdir = strdup (fsp->f_mntonname);
@ -400,7 +408,8 @@ read_filesystem_list (int need_fs_type, int all_fs)
entries = getmntinfo (&fsp, MNT_NOWAIT); entries = getmntinfo (&fsp, MNT_NOWAIT);
if (entries < 0) if (entries < 0)
return NULL; return NULL;
for (; entries-- > 0; fsp++) { for (; entries-- > 0; fsp++)
{
me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
me->me_devname = strdup (fsp->f_mntfromname); me->me_devname = strdup (fsp->f_mntfromname);
me->me_mountdir = strdup (fsp->f_mntonname); me->me_mountdir = strdup (fsp->f_mntonname);
@ -420,8 +429,8 @@ read_filesystem_list (int need_fs_type, int all_fs)
int val; int val;
struct fs_data fsd; struct fs_data fsd;
while ((val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, while ((val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, NULL)) > 0)
NULL)) > 0) { {
me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
me->me_devname = strdup (fsd.fd_req.devname); me->me_devname = strdup (fsd.fd_req.devname);
me->me_mountdir = strdup (fsd.fd_req.path); me->me_mountdir = strdup (fsd.fd_req.path);
@ -451,11 +460,13 @@ read_filesystem_list (int need_fs_type, int all_fs)
stats = (struct statfs *) malloc (bufsize); stats = (struct statfs *) malloc (bufsize);
numsys = getfsstat (stats, bufsize, MNT_WAIT); numsys = getfsstat (stats, bufsize, MNT_WAIT);
if (numsys < 0) { if (numsys < 0)
{
free (stats); free (stats);
return (NULL); return (NULL);
} }
for (counter = 0; counter < numsys; counter++) { for (counter = 0; counter < numsys; counter++)
{
me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
me->me_devname = strdup (stats[counter].f_mntfromname); me->me_devname = strdup (stats[counter].f_mntfromname);
me->me_mountdir = strdup (stats[counter].f_mntonname); me->me_mountdir = strdup (stats[counter].f_mntonname);
@ -482,7 +493,8 @@ read_filesystem_list (int need_fs_type, int all_fs)
if (fp == NULL) if (fp == NULL)
return NULL; return NULL;
while (fread (&mnt, sizeof mnt, 1, fp) > 0) { while (fread (&mnt, sizeof mnt, 1, fp) > 0)
{
me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
#ifdef GETFSTYP /* SVR3. */ #ifdef GETFSTYP /* SVR3. */
me->me_devname = strdup (mnt.mt_dev); me->me_devname = strdup (mnt.mt_dev);
@ -495,7 +507,8 @@ read_filesystem_list (int need_fs_type, int all_fs)
me->me_dev = -1; /* Magic; means not known yet. */ me->me_dev = -1; /* Magic; means not known yet. */
me->me_type = ""; me->me_type = "";
#ifdef GETFSTYP /* SVR3. */ #ifdef GETFSTYP /* SVR3. */
if (need_fs_type) { if (need_fs_type)
{
struct statfs fsd; struct statfs fsd;
char typebuf[FSTYPSZ]; char typebuf[FSTYPSZ];
@ -519,7 +532,8 @@ read_filesystem_list (int need_fs_type, int all_fs)
#ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */ #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */
{ {
struct mntent **mnttbl = getmnttbl (), **ent; struct mntent **mnttbl = getmnttbl (), **ent;
for (ent = mnttbl; *ent; ent++) { for (ent = mnttbl; *ent; ent++)
{
me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
me->me_devname = strdup ((*ent)->mt_resource); me->me_devname = strdup ((*ent)->mt_resource);
me->me_mountdir = strdup ((*ent)->mt_directory); me->me_mountdir = strdup ((*ent)->mt_directory);
@ -546,7 +560,8 @@ read_filesystem_list (int need_fs_type, int all_fs)
if (fp == NULL) if (fp == NULL)
return NULL; return NULL;
while ((ret = getmntent (fp, &mnt)) == 0) { while ((ret = getmntent (fp, &mnt)) == 0)
{
me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
me->me_devname = strdup (mnt.mnt_special); me->me_devname = strdup (mnt.mnt_special);
me->me_mountdir = strdup (mnt.mnt_mountp); me->me_mountdir = strdup (mnt.mnt_mountp);
@ -578,11 +593,12 @@ read_filesystem_list (int need_fs_type, int all_fs)
/* Get the list of mounted filesystems. */ /* Get the list of mounted filesystems. */
mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries); mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
for (thisent = entries; thisent < entries + bufsize; for (thisent = entries; thisent < entries + bufsize; thisent += vmp->vmt_length)
thisent += vmp->vmt_length) { {
vmp = (struct vmount *) thisent; vmp = (struct vmount *) thisent;
me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
if (vmp->vmt_flags & MNT_REMOTE) { if (vmp->vmt_flags & MNT_REMOTE)
{
char *host, *path; char *host, *path;
/* Prepend the remote pathname. */ /* Prepend the remote pathname. */
@ -592,9 +608,10 @@ read_filesystem_list (int need_fs_type, int all_fs)
strcpy (me->me_devname, host); strcpy (me->me_devname, host);
strcat (me->me_devname, ":"); strcat (me->me_devname, ":");
strcat (me->me_devname, path); strcat (me->me_devname, path);
} else { }
me->me_devname = strdup (thisent + else
vmp->vmt_data[VMT_OBJECT].vmt_off); {
me->me_devname = strdup (thisent + vmp->vmt_data[VMT_OBJECT].vmt_off);
} }
me->me_mountdir = strdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off); me->me_mountdir = strdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
me->me_type = strdup (fstype_to_string (vmp->vmt_gfstype)); me->me_type = strdup (fstype_to_string (vmp->vmt_gfstype));
@ -638,38 +655,61 @@ read_filesystem_list(int need_fs_type, int all_fs)
if (me) if (me)
{ {
if (me->me_devname) free(me->me_devname); if (me->me_devname)
if (me->me_mountdir) free(me->me_mountdir); free (me->me_devname);
if (me->me_type) free(me->me_type); if (me->me_mountdir)
free (me->me_mountdir);
if (me->me_type)
free (me->me_type);
} }
else else
me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
if (!getcwd(dir, _POSIX_PATH_MAX)) return (NULL); if (!getcwd (dir, _POSIX_PATH_MAX))
return (NULL);
if ((fd = open(dir, O_RDONLY)) == -1) return (NULL); if ((fd = open (dir, O_RDONLY)) == -1)
return (NULL);
i = disk_get_entry (fd, &de); i = disk_get_entry (fd, &de);
close (fd); close (fd);
if (i == -1) return (NULL); if (i == -1)
return (NULL);
switch (de.disk_type) switch (de.disk_type)
{ {
case _UNMOUNTED: tp = "unmounted"; break; case _UNMOUNTED:
case _FLOPPY: tp = "Floppy"; break; tp = "unmounted";
case _HARD: tp = "Hard"; break; break;
case _RAMDISK: tp = "Ram"; break; case _FLOPPY:
case _REMOVABLE: tp = "Removable"; break; tp = "Floppy";
case _TAPE: tp = "Tape"; break; break;
case _CDROM: tp = "CDROM"; break; case _HARD:
default: tp = "unknown"; tp = "Hard";
break;
case _RAMDISK:
tp = "Ram";
break;
case _REMOVABLE:
tp = "Removable";
break;
case _TAPE:
tp = "Tape";
break;
case _CDROM:
tp = "CDROM";
break;
default:
tp = "unknown";
} }
if (fsys_get_mount_dev(dir, &dev) == -1) return (NULL); if (fsys_get_mount_dev (dir, &dev) == -1)
return (NULL);
if (fsys_get_mount_pt(dev, &dir) == -1) return (NULL); if (fsys_get_mount_pt (dev, &dir) == -1)
return (NULL);
me->me_devname = strdup (dev); me->me_devname = strdup (dev);
me->me_mountdir = strdup (dir); me->me_mountdir = strdup (dir);
@ -677,7 +717,8 @@ read_filesystem_list(int need_fs_type, int all_fs)
me->me_dev = de.disk_type; me->me_dev = de.disk_type;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "disk_get_entry():\n\tdisk_type=%d (%s)\n\tdriver_name='%-*.*s'\n\tdisk_drv=%d\n", fprintf (stderr,
"disk_get_entry():\n\tdisk_type=%d (%s)\n\tdriver_name='%-*.*s'\n\tdisk_drv=%d\n",
de.disk_type, tp, _DRIVER_NAME_LEN, _DRIVER_NAME_LEN, de.driver_name, de.disk_drv); de.disk_type, tp, _DRIVER_NAME_LEN, _DRIVER_NAME_LEN, de.driver_name, de.disk_drv);
fprintf (stderr, "fsys_get_mount_dev():\n\tdevice='%s'\n", dev); fprintf (stderr, "fsys_get_mount_dev():\n\tdevice='%s'\n", dev);
fprintf (stderr, "fsys_get_mount_pt():\n\tmount point='%s'\n", dir); fprintf (stderr, "fsys_get_mount_pt():\n\tmount point='%s'\n", dir);
@ -688,15 +729,25 @@ read_filesystem_list(int need_fs_type, int all_fs)
#endif /* HAVE_INFOMOUNT_QNX */ #endif /* HAVE_INFOMOUNT_QNX */
void void
init_my_statfs (void) free_my_statfs (void)
{ {
#ifdef HAVE_INFOMOUNT_LIST #ifdef HAVE_INFOMOUNT_LIST
while (mount_list) { while (mount_list)
{
struct mount_entry *next = mount_list->me_next; struct mount_entry *next = mount_list->me_next;
free_mount_entry (mount_list); free_mount_entry (mount_list);
mount_list = next; mount_list = next;
} }
mount_list = NULL;
#endif /* HAVE_INFOMOUNT_LIST */
}
void
init_my_statfs (void)
{
#ifdef HAVE_INFOMOUNT_LIST
free_my_statfs ();
mount_list = read_filesystem_list (1, 1); mount_list = read_filesystem_list (1, 1);
#endif /* HAVE_INFOMOUNT_LIST */ #endif /* HAVE_INFOMOUNT_LIST */
} }
@ -710,17 +761,20 @@ my_statfs (struct my_statfs *myfs_stats, const char *path)
struct mount_entry *temp = mount_list; struct mount_entry *temp = mount_list;
struct fs_usage fs_use; struct fs_usage fs_use;
while (temp){ while (temp)
{
i = strlen (temp->me_mountdir); i = strlen (temp->me_mountdir);
if (i > len && (strncmp (path, temp->me_mountdir, i) == 0)) if (i > len && (strncmp (path, temp->me_mountdir, i) == 0))
if (!entry || (path [i] == PATH_SEP || path [i] == 0)){ if (!entry || (path[i] == PATH_SEP || path[i] == 0))
{
len = i; len = i;
entry = temp; entry = temp;
} }
temp = temp->me_next; temp = temp->me_next;
} }
if (entry){ if (entry)
{
memset (&fs_use, 0, sizeof (struct fs_usage)); memset (&fs_use, 0, sizeof (struct fs_usage));
get_fs_usage (entry->me_mountdir, &fs_use); get_fs_usage (entry->me_mountdir, &fs_use);
@ -732,7 +786,8 @@ my_statfs (struct my_statfs *myfs_stats, const char *path)
myfs_stats->total = fs_use.fsu_blocks / 2; myfs_stats->total = fs_use.fsu_blocks / 2;
myfs_stats->nfree = fs_use.fsu_ffree; myfs_stats->nfree = fs_use.fsu_ffree;
myfs_stats->nodes = fs_use.fsu_files; myfs_stats->nodes = fs_use.fsu_files;
} else }
else
#endif /* HAVE_INFOMOUNT_LIST */ #endif /* HAVE_INFOMOUNT_LIST */
#ifdef HAVE_INFOMOUNT_QNX #ifdef HAVE_INFOMOUNT_QNX
@ -796,7 +851,8 @@ fs_adjust_blocks (fsblkcnt_t blocks, int fromsize, int tosize)
#if defined(_AIX) && defined(_I386) #if defined(_AIX) && defined(_I386)
/* AIX PS/2 does not supply statfs. */ /* AIX PS/2 does not supply statfs. */
static int aix_statfs (char *path, struct statfs *fsb) static int
aix_statfs (char *path, struct statfs *fsb)
{ {
struct stat stats; struct stat stats;
struct dustat fsd; struct dustat fsd;
@ -816,6 +872,7 @@ static int aix_statfs (char *path, struct statfs *fsb)
fsb->f_fsid.val[1] = fsd.du_pckno; fsb->f_fsid.val[1] = fsd.du_pckno;
return 0; return 0;
} }
#define statfs(path,fsb) aix_statfs(path,fsb) #define statfs(path,fsb) aix_statfs(path,fsb)
#endif /* _AIX && _I386 */ #endif /* _AIX && _I386 */

Просмотреть файл

@ -23,7 +23,8 @@
#define MC_MOUNTLIST_H #define MC_MOUNTLIST_H
/* Filesystem status */ /* Filesystem status */
struct my_statfs { struct my_statfs
{
int type; int type;
char *typename; char *typename;
const char *mpoint; const char *mpoint;
@ -36,5 +37,6 @@ struct my_statfs {
void init_my_statfs (void); void init_my_statfs (void);
void my_statfs (struct my_statfs *myfs_stats, const char *path); void my_statfs (struct my_statfs *myfs_stats, const char *path);
void free_my_statfs (void);
#endif #endif

Просмотреть файл

@ -3100,6 +3100,7 @@ panel_callback (Widget * w, widget_msg_t msg, int parm)
case WIDGET_DESTROY: case WIDGET_DESTROY:
panel_destroy (panel); panel_destroy (panel);
free_my_statfs ();
return MSG_HANDLED; return MSG_HANDLED;
default: default:

Просмотреть файл

@ -138,11 +138,7 @@ mcview_dialog_search (mcview_t * view)
g_free (view->last_search_string); g_free (view->last_search_string);
view->last_search_string = exp; view->last_search_string = exp;
mcview_nroff_seq_free (&view->search_nroff_seq);
if (view->search_nroff_seq != NULL)
mcview_nroff_seq_free (&(view->search_nroff_seq));
if (view->search != NULL)
mc_search_free (view->search); mc_search_free (view->search);
view->search = mc_search_new (view->last_search_string, -1); view->search = mc_search_new (view->last_search_string, -1);

Просмотреть файл

@ -191,12 +191,20 @@ mcview_done (mcview_t * view)
coord_cache_free (view->coord_cache), view->coord_cache = NULL; coord_cache_free (view->coord_cache), view->coord_cache = NULL;
if (!(view->converter == INVALID_CONV || view->converter != str_cnv_from_term)) if (view->converter == INVALID_CONV)
view->converter = str_cnv_from_term;
if (view->converter != str_cnv_from_term)
{ {
str_close_conv (view->converter); str_close_conv (view->converter);
view->converter = str_cnv_from_term; view->converter = str_cnv_from_term;
} }
mc_search_free (view->search);
view->search = NULL;
g_free (view->last_search_string);
view->last_search_string = NULL;
mcview_nroff_seq_free (&view->search_nroff_seq);
mcview_hexedit_free_change_list (view); mcview_hexedit_free_change_list (view);
} }