From 5b68413e62b0974365a6e9e9b99e9391bf1d8d63 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Tue, 30 Mar 2010 12:10:25 +0400 Subject: [PATCH] Applied MC indentation policy. Applied MC indentation policy to all files modified in this branch with some simple manual modifications. Signed-off-by: Andrew Borodin --- lib/mcconfig/common.c | 58 +- lib/search/regex.c | 178 ++- lib/vfs/mc-vfs/direntry.c | 929 ++++++------ lib/vfs/mc-vfs/fish.c | 2600 ++++++++++++++++---------------- lib/vfs/mc-vfs/vfs.c | 847 ++++++----- src/complete.c | 1372 +++++++++-------- src/editor/edit.c | 3591 +++++++++++++++++++++++++-------------------- src/mountlist.c | 1880 ++++++++++++------------ src/mountlist.h | 3 +- 9 files changed, 6135 insertions(+), 5323 deletions(-) rewrite lib/vfs/mc-vfs/fish.c (62%) rewrite src/mountlist.c (60%) diff --git a/lib/mcconfig/common.c b/lib/mcconfig/common.c index f94deafe..6ed79f00 100644 --- a/lib/mcconfig/common.c +++ b/lib/mcconfig/common.c @@ -23,10 +23,10 @@ #include #include #include -#include /* extern int errno */ +#include /* extern int errno */ #include "lib/global.h" -#include "lib/vfs/mc-vfs/vfs.h" /* mc_stat */ +#include "lib/vfs/mc-vfs/vfs.h" /* mc_stat */ #include "lib/mcconfig.h" /*** global variables **************************************************/ @@ -44,8 +44,7 @@ mc_config_t *mc_panels_config; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ static gboolean -mc_config_new_or_override_file (mc_config_t * mc_config, const gchar * ini_path, - GError **error) +mc_config_new_or_override_file (mc_config_t * mc_config, const gchar * ini_path, GError ** error) { gchar *data, *written_data; 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; 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); g_free (data); return ret; @@ -62,9 +62,12 @@ mc_config_new_or_override_file (mc_config_t * mc_config, const gchar * ini_path, mc_util_make_backup_if_possible (ini_path, "~"); fd = mc_open (ini_path, O_WRONLY | O_TRUNC | O_SYNC, 0); - if (fd == -1) { - g_propagate_error (error, g_error_new (mc_main_error_quark() ,0, "%s", unix_error_string (errno))); - g_free(data); + if (fd == -1) + { + g_propagate_error (error, + g_error_new (mc_main_error_quark (), 0, "%s", + unix_error_string (errno))); + g_free (data); return FALSE; } @@ -74,9 +77,12 @@ mc_config_new_or_override_file (mc_config_t * mc_config, const gchar * ini_path, mc_close (fd); g_free (data); - if (cur_written == -1) { + if (cur_written == -1) + { 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; } @@ -100,15 +106,18 @@ mc_config_init (const gchar * ini_path) return NULL; mc_config->handle = g_key_file_new (); - if (mc_config->handle == NULL) { + if (mc_config->handle == NULL) + { g_free (mc_config); return NULL; } - if (!ini_path || !exist_file (ini_path)) { + if (!ini_path || !exist_file (ini_path)) + { 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 */ 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 *value; - if (mc_config == NULL) { + if (mc_config == NULL) + { return FALSE; } @@ -205,14 +215,17 @@ mc_config_read_file (mc_config_t * mc_config, const gchar * ini_path) groups = mc_config_get_groups (tmp_config, NULL); - if (groups == NULL) { + if (groups == NULL) + { mc_config_deinit (tmp_config); 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); - 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); if (value == NULL) continue; @@ -230,9 +243,10 @@ mc_config_read_file (mc_config_t * mc_config, const gchar * ini_path) /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 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 mc_config_new_or_override_file (mc_config, mc_config->ini_path, error); @@ -241,10 +255,10 @@ mc_config_save_file (mc_config_t * mc_config, GError **error) /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 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 mc_config_new_or_override_file (mc_config, ini_path, error); diff --git a/lib/search/regex.c b/lib/search/regex.c index bb2a7b8a..1bcfa8ca 100644 --- a/lib/search/regex.c +++ b/lib/search/regex.c @@ -44,7 +44,8 @@ /*** file scope type declarations ****************************************************************/ -typedef enum { +typedef enum +{ REPLACE_T_NO_TRANSFORM = 0, REPLACE_T_UPP_TRANSFORM_CHAR = 1, 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]); - while (*spec_chr) { + while (*spec_chr) + { spec_chr_len = strlen (*spec_chr); - 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 (*(tmp_regex_str + 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 (*(tmp_regex_str + spec_chr_len) == '{') + { while ((spec_chr_len < regex_str->len - *offset) && *(tmp_regex_str + spec_chr_len) != '}') spec_chr_len++; if (*(tmp_regex_str + spec_chr_len) == '}') spec_chr_len++; - } else + } + else spec_chr_len += 2; } 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); 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]) tmp_str = g_strdup_printf ("\\x%02X", (unsigned char) upp->str[loop]); else tmp_str = g_strdup_printf ("[\\x%02X\\x%02X]", (unsigned char) upp->str[loop], (unsigned char) low->str[loop]); - } else { + } + else + { tmp_str = g_strdup_printf ("\\x%02X", (unsigned char) upp->str[loop]); } g_string_append (str_to, tmp_str); @@ -148,7 +159,8 @@ mc_search__cond_struct_new_regex_accum_append (const char *charset, GString * st recoded_part = g_string_sized_new (32); - while (loop < str_from->len) { + while (loop < str_from->len) + { gchar *one_char; gsize one_char_len; gboolean just_letters; @@ -160,12 +172,13 @@ mc_search__cond_struct_new_regex_accum_append (const char *charset, GString * st if (one_char_len == 0) loop++; - else { + else + { loop += one_char_len; if (just_letters) mc_search__cond_struct_new_regex_hex_add (charset, recoded_part, one_char, - one_char_len); + one_char_len); else g_string_append_len (recoded_part, one_char, one_char_len); } @@ -194,20 +207,23 @@ mc_search__cond_struct_new_regex_ci_str (const char *charset, const char *str, g spec_char = g_string_new (""); loop = 0; - while (loop <= str_len) { - if (mc_search__regex_str_append_if_special (spec_char, tmp, &loop)) { + while (loop <= str_len) + { + if (mc_search__regex_str_append_if_special (spec_char, tmp, &loop)) + { 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_set_size (spec_char, 0); 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); while (loop < str_len && !(tmp->str[loop] == ']' - && !strutils_is_char_escaped (tmp->str, - &(tmp->str[loop])))) { + && !strutils_is_char_escaped (tmp->str, &(tmp->str[loop])))) + { g_string_append_c (ret_str, tmp->str[loop]); loop++; @@ -241,12 +257,15 @@ mc_search__regex_found_cond_one (mc_search_t * lc_mc_search, mc_search_regex_t * if (!g_regex_match_full (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); lc_mc_search->regex_match_info = NULL; - if (error) { + if (error) + { 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); return COND__FOUND_ERROR; } @@ -255,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); #else /* SEARCH_TYPE_GLIB */ 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, - MC_SEARCH__NUM_REPLACE_ARGS); - if (lc_mc_search->num_rezults < 0) { + search_str->str, search_str->len - 1, 0, 0, + lc_mc_search->iovector, MC_SEARCH__NUM_REPLACE_ARGS); + if (lc_mc_search->num_rezults < 0) + { return COND__NOT_FOUND; } #endif /* SEARCH_TYPE_GLIB */ @@ -274,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__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); if (!mc_search_cond->regex_handle) 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) return ret; @@ -295,15 +318,18 @@ mc_search_regex__get_max_num_of_replace_tokens (const gchar * str, gsize len) { int max_token = 0; gsize loop; - for (loop = 0; loop < len - 1; loop++) { - if (str[loop] == '\\' && (str[loop + 1] & (char) 0xf0) == 0x30 /* 0-9 */ ) { + for (loop = 0; loop < len - 1; loop++) + { + if (str[loop] == '\\' && (str[loop + 1] & (char) 0xf0) == 0x30 /* 0-9 */ ) + { if (strutils_is_char_escaped (str, &str[loop])) continue; if (max_token < str[loop + 1] - '0') max_token = str[loop + 1] - '0'; continue; } - if (str[loop] == '$' && str[loop + 1] == '{') { + if (str[loop] == '$' && str[loop + 1] == '{') + { gsize tmp_len; char *tmp_str; int tmp_token; @@ -313,7 +339,8 @@ mc_search_regex__get_max_num_of_replace_tokens (const gchar * str, gsize len) for (tmp_len = 0; loop + tmp_len + 2 < len && (str[loop + 2 + tmp_len] & (char) 0xf0) == 0x30; tmp_len++); - if (str[loop + 2 + tmp_len] == '}') { + if (str[loop + 2 + tmp_len] == '}') + { tmp_str = g_strndup (&str[loop + 2], tmp_len); tmp_token = atoi (tmp_str); if (max_token < tmp_token) @@ -360,8 +387,10 @@ mc_search_regex__process_replace_str (const GString * replace_str, const gsize c *skip_len = 0; - if (*curr_str == '$' && *(curr_str + 1) == '{' && (*(curr_str + 2) & (char) 0xf0) == 0x30) { - if (strutils_is_char_escaped (replace_str->str, curr_str)) { + if (*curr_str == '$' && *(curr_str + 1) == '{' && (*(curr_str + 2) & (char) 0xf0) == 0x30) + { + if (strutils_is_char_escaped (replace_str->str, curr_str)) + { *skip_len = 1; return -1; } @@ -384,20 +413,24 @@ mc_search_regex__process_replace_str (const GString * replace_str, const gsize c return ret; } - if (*curr_str == '\\') { - if (strutils_is_char_escaped (replace_str->str, curr_str)) { + if (*curr_str == '\\') + { + if (strutils_is_char_escaped (replace_str->str, curr_str)) + { *skip_len = 1; return -1; } - if ((*(curr_str + 1) & (char) 0xf0) == 0x30) { + if ((*(curr_str + 1) & (char) 0xf0) == 0x30) + { ret = *(curr_str + 1) - '0'; *skip_len = 2; /* \\ and one digit */ return ret; } ret = -2; *skip_len += 2; - switch (*(curr_str + 1)) { + switch (*(curr_str + 1)) + { case 'U': *replace_flags |= REPLACE_T_UPP_TRANSFORM; *replace_flags &= ~REPLACE_T_LOW_TRANSFORM; @@ -431,39 +464,50 @@ mc_search_regex__process_append_str (GString * dest_str, const char *from, gsize char *tmp_str; GString *tmp_string; - if (len == (gsize) -1) + if (len == (gsize) - 1) 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); return; } - while (loop < len) { + while (loop < len) + { tmp_str = mc_search__get_one_symbol (NULL, from + loop, len - loop, NULL); 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; tmp_string = mc_search__toupper_case_str (NULL, tmp_str, char_len); g_string_append (dest_str, tmp_string->str); 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; tmp_string = mc_search__toupper_case_str (NULL, tmp_str, char_len); g_string_append (dest_str, tmp_string->str); 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); g_string_append (dest_str, tmp_string->str); 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); g_string_append (dest_str, tmp_string->str); g_string_free (tmp_string, TRUE); - } else { + } + else + { g_string_append (dest_str, tmp_str); } g_free (tmp_str); @@ -486,7 +530,8 @@ mc_search__cond_struct_new_init_regex (const char *charset, mc_search_t * lc_mc_ int erroffset; #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); 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); @@ -497,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, &error); - if (error != NULL) { + if (error != NULL) + { lc_mc_search->error = MC_SEARCH_E_REGEX_COMPILE; lc_mc_search->error_str = str_conv_gerror_message (error, _(" Regular expression error ")); g_error_free (error); @@ -506,14 +552,17 @@ mc_search__cond_struct_new_init_regex (const char *charset, mc_search_t * lc_mc_ #else /* SEARCH_TYPE_GLIB */ mc_search_cond->regex_handle = 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_str = g_strdup (error); return; } lc_mc_search->regex_match_info = pcre_study (mc_search_cond->regex_handle, 0, &error); - if (lc_mc_search->regex_match_info == NULL) { - if (error) { + if (lc_mc_search->regex_match_info == NULL) + { + if (error) + { lc_mc_search->error = MC_SEARCH_E_REGEX_COMPILE; lc_mc_search->error_str = g_strdup (error); g_free (mc_search_cond->regex_handle); @@ -541,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 (""); 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); lc_mc_search->start_buffer = current_pos; - while (1) { + while (1) + { current_chr = mc_search__get_char (lc_mc_search, user_data, current_pos); if (current_chr == MC_SEARCH_CB_ABORT) break; @@ -567,7 +618,8 @@ mc_search__run_regex (mc_search_t * lc_mc_search, const void *user_data, 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: #ifdef SEARCH_TYPE_GLIB g_match_info_fetch_pos (lc_mc_search->regex_match_info, 0, &start_pos, &end_pos); @@ -588,8 +640,8 @@ mc_search__run_regex (mc_search_t * lc_mc_search, const void *user_data, return FALSE; break; } - if (( lc_mc_search->update_fn != NULL ) && - ( (lc_mc_search->update_fn) (user_data, current_pos) == MC_SEARCH_CB_ABORT)) + if ((lc_mc_search->update_fn != NULL) && + ((lc_mc_search->update_fn) (user_data, current_pos) == MC_SEARCH_CB_ABORT)) current_chr = MC_SEARCH_CB_ABORT; if (current_chr == MC_SEARCH_CB_ABORT) @@ -627,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); 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_str = g_strdup (STR_E_RPL_NOT_EQ_TO_FOUND); return NULL; @@ -635,11 +688,14 @@ mc_search_regex_prepare_replace_str (mc_search_t * lc_mc_search, GString * repla ret = g_string_new (""); 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); - if (lc_index == -1) { - if (len != 0) { + if (lc_index == -1) + { + if (len != 0) + { mc_search_regex__process_append_str (ret, prev_str, replace_str->str - prev_str + loop, &replace_flags); @@ -651,7 +707,8 @@ mc_search_regex_prepare_replace_str (mc_search_t * lc_mc_search, GString * repla continue; } - if (lc_index == -2) { + if (lc_index == -2) + { if (loop) mc_search_regex__process_append_str (ret, prev_str, replace_str->str - prev_str + loop, @@ -661,7 +718,8 @@ mc_search_regex_prepare_replace_str (mc_search_t * lc_mc_search, GString * repla continue; } - if (lc_index > lc_mc_search->num_rezults) { + if (lc_index > lc_mc_search->num_rezults) + { g_string_free (ret, TRUE); lc_mc_search->error = MC_SEARCH_E_REGEX_REPLACE; lc_mc_search->error_str = g_strdup_printf (STR_E_RPL_INVALID_TOKEN, lc_index); diff --git a/lib/vfs/mc-vfs/direntry.c b/lib/vfs/mc-vfs/direntry.c index 3b2b7bf7..4e6a1334 100644 --- a/lib/vfs/mc-vfs/direntry.c +++ b/lib/vfs/mc-vfs/direntry.c @@ -31,22 +31,22 @@ #include #include -#include /* include fcntl.h -> sys/fcntl.h only */ - /* includes fcntl.h see IEEE Std 1003.1-2008 */ +#include /* include fcntl.h -> sys/fcntl.h only */ + /* includes fcntl.h see IEEE Std 1003.1-2008 */ #include -#include /* gettimeofday() */ +#include /* gettimeofday() */ #include "lib/global.h" -#include "lib/tty/tty.h" /* enable/disable interrupt key */ +#include "lib/tty/tty.h" /* enable/disable interrupt key */ -#include "src/wtools.h" /* message() */ -#include "src/main.h" /* print_vfs_message */ +#include "src/wtools.h" /* message() */ +#include "src/main.h" /* print_vfs_message */ #include "vfs.h" #include "utilvfs.h" #include "vfs-impl.h" -#include "gc.h" /* vfs_rmstamp */ +#include "gc.h" /* vfs_rmstamp */ #include "xdirentry.h" #define CALL(x) if (MEDATA->x) MEDATA->x @@ -60,7 +60,7 @@ vfs_s_new_inode (struct vfs_class *me, struct vfs_s_super *super, struct stat *i ino = g_try_new0 (struct vfs_s_inode, 1); if (ino == NULL) - return NULL; + return NULL; if (initstat) ino->st = *initstat; @@ -86,7 +86,7 @@ vfs_s_new_entry (struct vfs_class *me, const char *name, struct vfs_s_inode *ino total_entries++; if (name) - entry->name = g_strdup (name); + entry->name = g_strdup (name); entry->ino = inode; entry->ino->ent = entry; @@ -99,46 +99,54 @@ static void vfs_s_free_inode (struct vfs_class *me, struct vfs_s_inode *ino) { if (!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 */ - if (ino->st.st_nlink <= 1){ - while (ino->subdir){ - vfs_s_free_entry (me, ino->subdir); - } - - CALL (free_inode) (me, ino); - g_free (ino->linkname); - if (ino->localname){ - unlink (ino->localname); - g_free(ino->localname); - } - total_inodes--; - ino->super->ino_usage--; - g_free(ino); - } else ino->st.st_nlink--; + if (ino->st.st_nlink <= 1) + { + while (ino->subdir) + { + vfs_s_free_entry (me, ino->subdir); + } + + CALL (free_inode) (me, ino); + g_free (ino->linkname); + if (ino->localname) + { + unlink (ino->localname); + g_free (ino->localname); + } + total_inodes--; + ino->super->ino_usage--; + g_free (ino); + } + else + ino->st.st_nlink--; } void 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 */ - *ent->prevp = ent->next; - if (ent->next) - ent->next->prevp = ent->prevp; + if (ent->prevp) + { + /* It is possible that we are deleting freshly created entry */ + *ent->prevp = ent->next; + if (ent->next) + ent->next->prevp = ent->prevp; } g_free (ent->name); ent->name = NULL; - - if (ent->ino){ - ent->ino->ent = NULL; - vfs_s_free_inode (me, ent->ino); - ent->ino = NULL; + + if (ent->ino) + { + ent->ino->ent = NULL; + vfs_s_free_inode (me, ent->ino); + ent->ino = NULL; } total_entries--; - g_free(ent); + g_free (ent); } void @@ -149,7 +157,7 @@ vfs_s_insert_entry (struct vfs_class *me, struct vfs_s_inode *dir, struct vfs_s_ (void) me; for (ep = &dir->subdir; *ep != NULL; ep = &((*ep)->next)) - ; + ; ent->prevp = ep; ent->next = NULL; ent->dir = dir; @@ -183,7 +191,8 @@ vfs_s_default_stat (struct vfs_class *me, mode_t mode) } 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 stat *st; @@ -200,53 +209,52 @@ vfs_s_automake (struct vfs_class *me, struct vfs_s_inode *dir, char *path, int f { struct vfs_s_entry *res; char *sep = strchr (path, PATH_SEP); - + if (sep) - *sep = 0; + *sep = 0; res = vfs_s_generate_entry (me, path, dir, flags & FL_MKDIR ? (0777 | S_IFDIR) : 0777); vfs_s_insert_entry (me, dir, res); if (sep) - *sep = PATH_SEP; + *sep = PATH_SEP; return res; } /* If the entry is a symlink, find the entry for its target */ static struct vfs_s_entry * -vfs_s_resolve_symlink (struct vfs_class *me, struct vfs_s_entry *entry, - int follow) +vfs_s_resolve_symlink (struct vfs_class *me, struct vfs_s_entry *entry, int follow) { char *linkname; char *fullname = NULL; struct vfs_s_entry *target; if (follow == LINK_NO_FOLLOW) - return entry; + return entry; if (follow == 0) - ERRNOR (ELOOP, NULL); + ERRNOR (ELOOP, NULL); if (!entry) - ERRNOR (ENOENT, NULL); + ERRNOR (ENOENT, NULL); if (!S_ISLNK (entry->ino->st.st_mode)) - return entry; + return entry; linkname = entry->ino->linkname; if (linkname == NULL) - ERRNOR (EFAULT, NULL); + ERRNOR (EFAULT, NULL); /* make full path from relative */ - if (*linkname != PATH_SEP) { - char *fullpath = vfs_s_fullpath (me, entry->dir); - if (fullpath) { - fullname = g_strconcat (fullpath, "/", linkname, (char *) NULL); - linkname = fullname; - g_free (fullpath); - } + if (*linkname != PATH_SEP) + { + char *fullpath = vfs_s_fullpath (me, entry->dir); + if (fullpath) + { + fullname = g_strconcat (fullpath, "/", linkname, (char *) NULL); + linkname = fullname; + g_free (fullpath); + } } - target = - (MEDATA->find_entry) (me, entry->dir->super->root, linkname, - follow - 1, 0); + target = (MEDATA->find_entry) (me, entry->dir->super->root, linkname, follow - 1, 0); g_free (fullname); return target; } @@ -257,52 +265,50 @@ vfs_s_resolve_symlink (struct vfs_class *me, struct vfs_s_entry *entry, */ static struct vfs_s_entry * vfs_s_find_entry_tree (struct vfs_class *me, struct vfs_s_inode *root, - const char *a_path, int follow, int flags) + const char *a_path, int follow, int flags) { size_t pseg; struct vfs_s_entry *ent = NULL; - char * const pathref = g_strdup (a_path); + char *const pathref = g_strdup (a_path); char *path = pathref; /* canonicalize as well, but don't remove '../' from path */ custom_canonicalize_pathname (path, CANON_PATH_ALL & (~CANON_PATH_REMDOUBLEDOTS)); - while (root) { - while (*path == PATH_SEP) /* Strip leading '/' */ - path++; - - if (!path[0]) { - g_free (pathref); - return ent; - } - - for (pseg = 0; path[pseg] && path[pseg] != PATH_SEP; pseg++); - - for (ent = root->subdir; ent != NULL; ent = ent->next) - if (strlen (ent->name) == pseg - && (!strncmp (ent->name, path, pseg))) - /* FOUND! */ - break; - - if (!ent && (flags & (FL_MKFILE | FL_MKDIR))) - ent = vfs_s_automake (me, root, path, flags); - if (!ent) { - me->verrno = ENOENT; - goto cleanup; - } - path += pseg; - /* here we must follow leading directories always; - only the actual file is optional */ - ent = - vfs_s_resolve_symlink (me, ent, - strchr (path, - PATH_SEP) ? LINK_FOLLOW : - follow); - if (!ent) - goto cleanup; - root = ent->ino; + while (root) + { + while (*path == PATH_SEP) /* Strip leading '/' */ + path++; + + if (!path[0]) + { + g_free (pathref); + return ent; + } + + for (pseg = 0; path[pseg] && path[pseg] != PATH_SEP; pseg++); + + for (ent = root->subdir; ent != NULL; ent = ent->next) + if (strlen (ent->name) == pseg && (!strncmp (ent->name, path, pseg))) + /* FOUND! */ + break; + + if (!ent && (flags & (FL_MKFILE | FL_MKDIR))) + ent = vfs_s_automake (me, root, path, flags); + if (!ent) + { + me->verrno = ENOENT; + goto cleanup; + } + path += pseg; + /* here we must follow leading directories always; + only the actual file is optional */ + ent = vfs_s_resolve_symlink (me, ent, strchr (path, PATH_SEP) ? LINK_FOLLOW : follow); + if (!ent) + goto cleanup; + root = ent->ino; } -cleanup: + cleanup: g_free (pathref); return NULL; } @@ -315,83 +321,87 @@ split_dir_name (struct vfs_class *me, char *path, char **dir, char **name, char (void) me; s = strrchr (path, PATH_SEP); - if (s == NULL) { - *save = NULL; - *name = path; - *dir = path + strlen(path); /* an empty string */ - } else { - *save = s; - *dir = path; - *s++ = '\0'; - *name = s; + if (s == NULL) + { + *save = NULL; + *name = path; + *dir = path + strlen (path); /* an empty string */ + } + else + { + *save = s; + *dir = path; + *s++ = '\0'; + *name = s; } } static struct vfs_s_entry * vfs_s_find_entry_linear (struct vfs_class *me, struct vfs_s_inode *root, - const char *a_path, int follow, int flags) + const char *a_path, int follow, int flags) { struct vfs_s_entry *ent = NULL; - char * const path = g_strdup (a_path); + char *const path = g_strdup (a_path); struct vfs_s_entry *retval = NULL; if (root->super->root != root) - vfs_die ("We have to use _real_ root. Always. Sorry."); + vfs_die ("We have to use _real_ root. Always. Sorry."); /* canonicalize as well, but don't remove '../' from path */ custom_canonicalize_pathname (path, CANON_PATH_ALL & (~CANON_PATH_REMDOUBLEDOTS)); - if (!(flags & FL_DIR)) { - char *dirname, *name, *save; - struct vfs_s_inode *ino; - split_dir_name (me, path, &dirname, &name, &save); - ino = - vfs_s_find_inode (me, root->super, dirname, follow, - flags | FL_DIR); - if (save) - *save = PATH_SEP; - retval = vfs_s_find_entry_tree (me, ino, name, follow, flags); - g_free (path); - return retval; + if (!(flags & FL_DIR)) + { + char *dirname, *name, *save; + struct vfs_s_inode *ino; + split_dir_name (me, path, &dirname, &name, &save); + ino = vfs_s_find_inode (me, root->super, dirname, follow, flags | FL_DIR); + if (save) + *save = PATH_SEP; + retval = vfs_s_find_entry_tree (me, ino, name, follow, flags); + g_free (path); + return retval; } for (ent = root->subdir; ent != NULL; ent = ent->next) - if (!strcmp (ent->name, path)) - break; + if (!strcmp (ent->name, path)) + break; - if (ent && (!(MEDATA->dir_uptodate) (me, ent->ino))) { + if (ent && (!(MEDATA->dir_uptodate) (me, ent->ino))) + { #if 1 - print_vfs_message (_("Directory cache expired for %s"), path); + print_vfs_message (_("Directory cache expired for %s"), path); #endif - vfs_s_free_entry (me, ent); - ent = NULL; + vfs_s_free_entry (me, ent); + ent = NULL; } - if (!ent) { - struct vfs_s_inode *ino; - - ino = - vfs_s_new_inode (me, root->super, - vfs_s_default_stat (me, S_IFDIR | 0755)); - ent = vfs_s_new_entry (me, path, ino); - if ((MEDATA->dir_load) (me, ino, path) == -1) { - vfs_s_free_entry (me, ent); - g_free (path); - return NULL; - } - vfs_s_insert_entry (me, root, ent); - - for (ent = root->subdir; ent != NULL; ent = ent->next) - if (!strcmp (ent->name, path)) - break; + if (!ent) + { + struct vfs_s_inode *ino; + + ino = vfs_s_new_inode (me, root->super, vfs_s_default_stat (me, S_IFDIR | 0755)); + ent = vfs_s_new_entry (me, path, ino); + if ((MEDATA->dir_load) (me, ino, path) == -1) + { + vfs_s_free_entry (me, ent); + g_free (path); + return NULL; + } + vfs_s_insert_entry (me, root, ent); + + for (ent = root->subdir; ent != NULL; ent = ent->next) + if (!strcmp (ent->name, path)) + break; } if (!ent) - 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 (!vfs_s_resolve_symlink (me, ent, follow)) { - g_free (path); - return NULL; + if (!vfs_s_resolve_symlink (me, ent, follow)) + { + g_free (path); + return NULL; } #endif g_free (path); @@ -400,12 +410,12 @@ vfs_s_find_entry_linear (struct vfs_class *me, struct vfs_s_inode *root, struct vfs_s_inode * vfs_s_find_inode (struct vfs_class *me, const struct vfs_s_super *super, - const char *path, int follow, int flags) + const char *path, int follow, int flags) { struct vfs_s_entry *ent; if (((MEDATA->flags & VFS_S_REMOTE) == 0) && (*path == '\0')) - return super->root; + return super->root; ent = (MEDATA->find_entry) (me, super->root, path, follow, flags); return (ent != NULL) ? ent->ino : NULL; @@ -431,38 +441,39 @@ vfs_s_insert_super (struct vfs_class *me, struct vfs_s_super *super) super->prevp = &MEDATA->supers; if (MEDATA->supers != NULL) - MEDATA->supers->prevp = &super->next; + MEDATA->supers->prevp = &super->next; MEDATA->supers = super; -} +} static void vfs_s_free_super (struct vfs_class *me, struct vfs_s_super *super) { - if (super->root){ - vfs_s_free_inode (me, super->root); - super->root = NULL; + if (super->root) + { + vfs_s_free_inode (me, super->root); + super->root = NULL; } #if 0 /* FIXME: We currently leak small ammount of memory, sometimes. Fix it if you can. */ if (super->ino_usage) - message (D_ERROR, " Direntry warning ", - "Super ino_usage is %d, memory leak", - super->ino_usage); + message (D_ERROR, " Direntry warning ", + "Super ino_usage is %d, memory leak", super->ino_usage); 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 - if (super->prevp){ - *super->prevp = super->next; - if (super->next) - super->next->prevp = super->prevp; + if (super->prevp) + { + *super->prevp = super->next; + if (super->next) + super->next->prevp = super->prevp; } CALL (free_archive) (me, super); g_free (super->name); - g_free(super); + g_free (super); } @@ -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. */ const char * -vfs_s_get_path_mangle (struct vfs_class *me, char *inname, - struct vfs_s_super **archive, int flags) +vfs_s_get_path_mangle (struct vfs_class *me, char *inname, struct vfs_s_super **archive, int flags) { const char *retval; char *local, *op; @@ -486,33 +496,36 @@ vfs_s_get_path_mangle (struct vfs_class *me, char *inname, retval = (local) ? local : ""; if (MEDATA->archive_check) - if (!(cookie = MEDATA->archive_check (me, archive_name, op))) - return NULL; - - for (super = MEDATA->supers; super != NULL; super = super->next) { - /* 0 == other, 1 == same, return it, 2 == other but stop scanning */ - int i = MEDATA->archive_same (me, super, archive_name, op, cookie); - if (i != 0) { - if (i == 1) - goto return_success; - else - break; - } + if (!(cookie = MEDATA->archive_check (me, archive_name, op))) + return NULL; + + for (super = MEDATA->supers; super != NULL; super = super->next) + { + /* 0 == other, 1 == same, return it, 2 == other but stop scanning */ + int i = MEDATA->archive_same (me, super, archive_name, op, cookie); + if (i != 0) + { + if (i == 1) + goto return_success; + else + break; + } } if (flags & FL_NO_OPEN) - ERRNOR (EIO, NULL); + ERRNOR (EIO, NULL); super = vfs_s_new_super (me); result = MEDATA->open_archive (me, super, archive_name, op); - if (result == -1) { - vfs_s_free_super (me, super); - ERRNOR (EIO, NULL); + if (result == -1) + { + vfs_s_free_super (me, super); + ERRNOR (EIO, NULL); } if (!super->name) - vfs_die ("You have to fill name\n"); + vfs_die ("You have to fill name\n"); if (!super->root) - vfs_die ("You have to fill root inode\n"); + vfs_die ("You have to fill root inode\n"); vfs_s_insert_super (me, super); vfs_stamp_create (me, super); @@ -528,8 +541,7 @@ vfs_s_get_path_mangle (struct vfs_class *me, char *inname, * The result should be freed. */ static char * -vfs_s_get_path (struct vfs_class *me, const char *inname, - struct vfs_s_super **archive, int flags) +vfs_s_get_path (struct vfs_class *me, const char *inname, struct vfs_s_super **archive, int flags) { char *buf, *retval; @@ -542,9 +554,10 @@ vfs_s_get_path (struct vfs_class *me, const char *inname, void vfs_s_invalidate (struct vfs_class *me, struct vfs_s_super *super) { - if (!super->want_stale){ - vfs_s_free_inode (me, super->root); - super->root = vfs_s_new_inode (me, super, vfs_s_default_stat (me, S_IFDIR | 0755)); + if (!super->want_stale) + { + vfs_s_free_inode (me, super->root); + super->root = vfs_s_new_inode (me, super, vfs_s_default_stat (me, S_IFDIR | 0755)); } } @@ -552,29 +565,30 @@ char * vfs_s_fullpath (struct vfs_class *me, struct vfs_s_inode *ino) { if (!ino->ent) - ERRNOR (EAGAIN, NULL); - - if (!(MEDATA->flags & VFS_S_REMOTE)) { - /* archives */ - char *newpath; - char *path = g_strdup (ino->ent->name); - while (1) { - ino = ino->ent->dir; - if (ino == ino->super->root) - break; - newpath = g_strconcat (ino->ent->name, "/", path, (char *) NULL); - g_free (path); - path = newpath; - } - return path; + ERRNOR (EAGAIN, NULL); + + if (!(MEDATA->flags & VFS_S_REMOTE)) + { + /* archives */ + char *newpath; + char *path = g_strdup (ino->ent->name); + while (1) + { + ino = ino->ent->dir; + if (ino == ino->super->root) + break; + newpath = g_strconcat (ino->ent->name, "/", path, (char *) NULL); + g_free (path); + path = newpath; + } + return path; } /* remote systems */ 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, - ino->ent->name, (char *) NULL); + return g_strconcat (ino->ent->dir->ent->name, PATH_SEP_STR, ino->ent->name, (char *) NULL); } /* Support of archives */ @@ -588,24 +602,23 @@ vfs_s_inode_from_path (struct vfs_class *me, const char *name, int flags) char *q; if (!(q = vfs_s_get_path (me, name, &super, 0))) - return NULL; + return NULL; ino = - vfs_s_find_inode (me, super, q, - flags & FL_FOLLOW ? LINK_FOLLOW : LINK_NO_FOLLOW, - flags & ~FL_FOLLOW); + vfs_s_find_inode (me, super, q, + flags & FL_FOLLOW ? LINK_FOLLOW : LINK_NO_FOLLOW, flags & ~FL_FOLLOW); if ((!ino) && (!*q)) - /* We are asking about / directory of ftp server: assume it exists */ - ino = - vfs_s_find_inode (me, super, q, - flags & FL_FOLLOW ? LINK_FOLLOW : - LINK_NO_FOLLOW, - FL_DIR | (flags & ~FL_FOLLOW)); + /* We are asking about / directory of ftp server: assume it exists */ + ino = + vfs_s_find_inode (me, super, q, + flags & FL_FOLLOW ? LINK_FOLLOW : + LINK_NO_FOLLOW, FL_DIR | (flags & ~FL_FOLLOW)); g_free (q); return ino; } -struct dirhandle { +struct dirhandle +{ struct vfs_s_entry *cur; struct vfs_s_inode *dir; }; @@ -618,14 +631,14 @@ vfs_s_opendir (struct vfs_class *me, const char *dirname) dir = vfs_s_inode_from_path (me, dirname, FL_DIR | FL_FOLLOW); if (!dir) - return NULL; + return NULL; if (!S_ISDIR (dir->st.st_mode)) - ERRNOR (ENOTDIR, NULL); + ERRNOR (ENOTDIR, NULL); dir->st.st_nlink++; #if 0 - if (!dir->subdir) /* This can actually happen if we allow empty directories */ - ERRNOR (EAGAIN, NULL); + if (!dir->subdir) /* This can actually happen if we allow empty directories */ + ERRNOR (EAGAIN, NULL); #endif info = g_new (struct dirhandle, 1); info->cur = dir->subdir; @@ -635,21 +648,24 @@ vfs_s_opendir (struct vfs_class *me, const char *dirname) } static void * -vfs_s_readdir(void *data) +vfs_s_readdir (void *data) { static union vfs_dirent dir; struct dirhandle *info = (struct dirhandle *) data; if (!(info->cur)) - return NULL; + return NULL; - if (info->cur->name) { - g_strlcpy (dir.dent.d_name, info->cur->name, MC_MAXPATHLEN); - } else { - vfs_die("Null in structure-cannot happen"); + if (info->cur->name) + { + g_strlcpy (dir.dent.d_name, info->cur->name, MC_MAXPATHLEN); + } + else + { + vfs_die ("Null in structure-cannot happen"); } - compute_namelen(&dir.dent); + compute_namelen (&dir.dent); info->cur = info->cur->next; return (void *) &dir; @@ -671,7 +687,7 @@ vfs_s_chdir (struct vfs_class *me, const char *path) { void *data; if (!(data = vfs_s_opendir (me, path))) - return -1; + return -1; vfs_s_closedir (data); return 0; } @@ -716,17 +732,17 @@ vfs_s_readlink (struct vfs_class *me, const char *path, char *buf, size_t size) ino = vfs_s_inode_from_path (me, path, 0); if (!ino) - return -1; + return -1; if (!S_ISLNK (ino->st.st_mode)) - ERRNOR (EINVAL, -1); + ERRNOR (EINVAL, -1); if (ino->linkname == NULL) - ERRNOR (EFAULT, -1); + ERRNOR (EFAULT, -1); len = strlen (ino->linkname); if (size < len) - len = size; + len = size; /* readlink() does not append a NUL character to buf */ memcpy (buf, ino->linkname, len); return len; @@ -742,45 +758,49 @@ vfs_s_open (struct vfs_class *me, const char *file, int flags, int mode) struct vfs_s_inode *ino; 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); - if (ino && ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))) { - g_free (q); - ERRNOR (EEXIST, NULL); + if (ino && ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))) + { + g_free (q); + ERRNOR (EEXIST, NULL); } - if (!ino) { - char *dirname, *name, *save; - struct vfs_s_entry *ent; - struct vfs_s_inode *dir; - int tmp_handle; - - /* If the filesystem is read-only, disable file creation */ - if (!(flags & O_CREAT) || !(me->write)) { - g_free (q); - return NULL; - } - - split_dir_name (me, q, &dirname, &name, &save); - /* FIXME: check if vfs_s_find_inode returns NULL */ - dir = vfs_s_find_inode (me, super, dirname, LINK_FOLLOW, FL_DIR); - if (save) - *save = PATH_SEP; - ent = vfs_s_generate_entry (me, name, dir, 0755); - ino = ent->ino; - vfs_s_insert_entry (me, dir, ent); - tmp_handle = vfs_mkstemps (&ino->localname, me->name, name); - if (tmp_handle == -1) { - g_free (q); - return NULL; - } - close (tmp_handle); - was_changed = 1; + if (!ino) + { + char *dirname, *name, *save; + struct vfs_s_entry *ent; + struct vfs_s_inode *dir; + int tmp_handle; + + /* If the filesystem is read-only, disable file creation */ + if (!(flags & O_CREAT) || !(me->write)) + { + g_free (q); + return NULL; + } + + split_dir_name (me, q, &dirname, &name, &save); + /* FIXME: check if vfs_s_find_inode returns NULL */ + dir = vfs_s_find_inode (me, super, dirname, LINK_FOLLOW, FL_DIR); + if (save) + *save = PATH_SEP; + ent = vfs_s_generate_entry (me, name, dir, 0755); + ino = ent->ino; + vfs_s_insert_entry (me, dir, ent); + tmp_handle = vfs_mkstemps (&ino->localname, me->name, name); + if (tmp_handle == -1) + { + g_free (q); + return NULL; + } + close (tmp_handle); + was_changed = 1; } g_free (q); if (S_ISDIR (ino->st.st_mode)) - ERRNOR (EISDIR, NULL); + ERRNOR (EISDIR, NULL); fh = g_new (struct vfs_s_fh, 1); fh->pos = 0; @@ -789,23 +809,28 @@ vfs_s_open (struct vfs_class *me, const char *file, int flags, int mode) fh->changed = was_changed; fh->linear = 0; - if (IS_LINEAR (flags)) { - if (MEDATA->linear_start) { - print_vfs_message (_("Starting linear transfer...")); - fh->linear = LS_LINEAR_PREOPEN; - } - } else if ((MEDATA->fh_open) - && (MEDATA->fh_open (me, fh, flags, mode))) { - g_free (fh); - return NULL; + if (IS_LINEAR (flags)) + { + if (MEDATA->linear_start) + { + print_vfs_message (_("Starting linear transfer...")); + fh->linear = LS_LINEAR_PREOPEN; + } + } + else if ((MEDATA->fh_open) && (MEDATA->fh_open (me, fh, flags, mode))) + { + g_free (fh); + return NULL; } - if (fh->ino->localname) { - fh->handle = open (fh->ino->localname, NO_LINEAR (flags), mode); - if (fh->handle == -1) { - g_free (fh); - ERRNOR (errno, NULL); - } + if (fh->ino->localname) + { + fh->handle = open (fh->ino->localname, NO_LINEAR (flags), mode); + if (fh->handle == -1) + { + g_free (fh); + ERRNOR (errno, NULL); + } } /* i.e. we had no open files and now we have one */ @@ -821,9 +846,10 @@ vfs_s_read (void *fh, char *buffer, int count) int n; struct vfs_class *me = FH_SUPER->me; - if (FH->linear == LS_LINEAR_PREOPEN) { - if (!MEDATA->linear_start (me, FH, FH->pos)) - return -1; + if (FH->linear == LS_LINEAR_PREOPEN) + { + if (!MEDATA->linear_start (me, FH, FH->pos)) + return -1; } if (FH->linear == LS_LINEAR_CLOSED) @@ -831,12 +857,13 @@ vfs_s_read (void *fh, char *buffer, int count) if (FH->linear == LS_LINEAR_OPEN) return MEDATA->linear_read (me, FH, buffer, count); - - if (FH->handle != -1){ - n = read (FH->handle, buffer, count); - if (n < 0) - me->verrno = errno; - return n; + + if (FH->handle != -1) + { + n = read (FH->handle, buffer, count); + if (n < 0) + me->verrno = errno; + return n; } vfs_die ("vfs_s_read: This should not happen\n"); return -1; @@ -847,16 +874,17 @@ vfs_s_write (void *fh, const char *buffer, int count) { int n; struct vfs_class *me = FH_SUPER->me; - + if (FH->linear) - vfs_die ("no writing to linear files, please"); - + vfs_die ("no writing to linear files, please"); + FH->changed = 1; - if (FH->handle != -1){ - n = write (FH->handle, buffer, count); - if (n < 0) - me->verrno = errno; - return n; + if (FH->handle != -1) + { + n = write (FH->handle, buffer, count); + if (n < 0) + me->verrno = errno; + return n; } vfs_die ("vfs_s_write: This should not happen\n"); return 0; @@ -870,25 +898,29 @@ vfs_s_lseek (void *fh, off_t offset, int whence) if (FH->linear == LS_LINEAR_OPEN) vfs_die ("cannot lseek() after linear_read!"); - if (FH->handle != -1){ /* If we have local file opened, we want to work with it */ - int retval = lseek (FH->handle, offset, whence); - if (retval == -1) - FH->ino->super->me->verrno = errno; - return retval; + if (FH->handle != -1) + { /* If we have local file opened, we want to work with it */ + int retval = lseek (FH->handle, offset, whence); + if (retval == -1) + FH->ino->super->me->verrno = errno; + return retval; } - switch (whence){ - case SEEK_CUR: - offset += FH->pos; break; - case SEEK_END: - offset += size; break; + switch (whence) + { + case SEEK_CUR: + offset += FH->pos; + break; + case SEEK_END: + offset += size; + break; } if (offset < 0) - FH->pos = 0; + FH->pos = 0; else if (offset < size) - FH->pos = offset; + FH->pos = offset; else - FH->pos = size; + FH->pos = size; return FH->pos; } @@ -900,25 +932,27 @@ vfs_s_close (void *fh) FH_SUPER->fd_usage--; if (!FH_SUPER->fd_usage) - vfs_stamp_create (me, FH_SUPER); + vfs_stamp_create (me, FH_SUPER); if (FH->linear == LS_LINEAR_OPEN) - MEDATA->linear_close (me, fh); + MEDATA->linear_close (me, fh); if (MEDATA->fh_close) - res = MEDATA->fh_close (me, fh); - if (FH->changed && MEDATA->file_store){ - char *s = vfs_s_fullpath (me, FH->ino); - if (!s) - res = -1; - else { - res = MEDATA->file_store (me, fh, s, FH->ino->localname); - g_free (s); - } - vfs_s_invalidate (me, FH_SUPER); + res = MEDATA->fh_close (me, fh); + if (FH->changed && MEDATA->file_store) + { + char *s = vfs_s_fullpath (me, FH->ino); + if (!s) + res = -1; + else + { + res = MEDATA->file_store (me, fh, s, FH->ino->localname); + g_free (s); + } + vfs_s_invalidate (me, FH_SUPER); } if (FH->handle != -1) - close (FH->handle); - + close (FH->handle); + vfs_s_free_inode (me, FH->ino); g_free (fh); return res; @@ -926,24 +960,22 @@ vfs_s_close (void *fh) static void vfs_s_print_stats (const char *fs_name, const char *action, - const char *file_name, off_t have, off_t need) + const char *file_name, off_t have, off_t need) { static const char *i18n_percent_transf_format = NULL; static const char *i18n_transf_format = NULL; - if (i18n_percent_transf_format == NULL) { - i18n_percent_transf_format = - _("%s: %s: %s %3d%% (%lu bytes transferred)"); - i18n_transf_format = _("%s: %s: %s %lu bytes transferred"); + if (i18n_percent_transf_format == NULL) + { + i18n_percent_transf_format = _("%s: %s: %s %3d%% (%lu bytes transferred)"); + i18n_transf_format = _("%s: %s: %s %lu bytes transferred"); } if (need) - print_vfs_message (i18n_percent_transf_format, fs_name, action, - file_name, (int) ((double) have * 100 / need), - (unsigned long) have); + print_vfs_message (i18n_percent_transf_format, fs_name, action, + file_name, (int) ((double) have * 100 / need), (unsigned long) have); else - print_vfs_message (i18n_transf_format, fs_name, action, file_name, - (unsigned long) have); + print_vfs_message (i18n_transf_format, fs_name, action, file_name, (unsigned long) have); } int @@ -962,36 +994,38 @@ vfs_s_retrieve_file (struct vfs_class *me, struct vfs_s_inode *ino) fh.handle = -1; handle = vfs_mkstemps (&ino->localname, me->name, ino->ent->name); - if (handle == -1) { - me->verrno = errno; - goto error_4; + if (handle == -1) + { + me->verrno = errno; + goto error_4; } if (!MEDATA->linear_start (me, &fh, 0)) - goto error_3; + goto error_3; /* Clear the interrupt status */ tty_got_interrupt (); tty_enable_interrupt_key (); - while ((n = MEDATA->linear_read (me, &fh, buffer, sizeof (buffer)))) { - int t; - if (n < 0) - goto error_1; - - total += n; - vfs_s_print_stats (me->name, _("Getting file"), ino->ent->name, - total, stat_size); - - if (tty_got_interrupt ()) - goto error_1; - - t = write (handle, buffer, n); - if (t != n) { - if (t == -1) - me->verrno = errno; - goto error_1; - } + while ((n = MEDATA->linear_read (me, &fh, buffer, sizeof (buffer)))) + { + int t; + if (n < 0) + goto error_1; + + total += n; + vfs_s_print_stats (me->name, _("Getting file"), ino->ent->name, total, stat_size); + + if (tty_got_interrupt ()) + goto error_1; + + t = write (handle, buffer, n); + if (t != n) + { + if (t == -1) + me->verrno = errno; + goto error_1; + } } MEDATA->linear_close (me, &fh); close (handle); @@ -1018,13 +1052,14 @@ vfs_s_fill_names (struct vfs_class *me, fill_names_f func) { struct vfs_s_super *a = MEDATA->supers; char *name; - - while (a){ - name = g_strconcat ( a->name, "#", me->prefix, "/", + + while (a) + { + name = g_strconcat (a->name, "#", me->prefix, "/", /* a->current_dir->name, */ (char *) NULL); - (*func)(name); - g_free (name); - a = a->next; + (*func) (name); + g_free (name); + a = a->next; } } @@ -1046,11 +1081,12 @@ vfs_s_getlocalcopy (struct vfs_class *me, const char *path) fh = vfs_s_open (me, path, O_RDONLY, 0); - if (fh != NULL) { - if ((fh->ino != NULL) && (fh->ino->localname != NULL)) - local = g_strdup (fh->ino->localname); + if (fh != NULL) + { + if ((fh->ino != NULL) && (fh->ino->localname != NULL)) + local = g_strdup (fh->ino->localname); - vfs_s_close (fh); + vfs_s_close (fh); } return local; @@ -1061,8 +1097,7 @@ vfs_s_getlocalcopy (struct vfs_class *me, const char *path) * the cache will be removed when the archive is closed. */ static int -vfs_s_ungetlocalcopy (struct vfs_class *me, const char *path, - const char *local, int has_changed) +vfs_s_ungetlocalcopy (struct vfs_class *me, const char *path, const char *local, int has_changed) { (void) me; (void) path; @@ -1074,27 +1109,29 @@ vfs_s_ungetlocalcopy (struct vfs_class *me, const char *path, static int vfs_s_setctl (struct vfs_class *me, const char *path, int ctlop, void *arg) { - switch (ctlop) { + switch (ctlop) + { case VFS_SETCTL_STALE_DATA: - { - struct vfs_s_inode *ino = vfs_s_inode_from_path (me, path, 0); - - if (!ino) - return 0; - if (arg) - ino->super->want_stale = 1; - else { - ino->super->want_stale = 0; - vfs_s_invalidate (me, ino->super); - } - return 1; - } + { + struct vfs_s_inode *ino = vfs_s_inode_from_path (me, path, 0); + + if (!ino) + return 0; + if (arg) + ino->super->want_stale = 1; + else + { + ino->super->want_stale = 0; + vfs_s_invalidate (me, ino->super); + } + return 1; + } case VFS_SETCTL_LOGFILE: - MEDATA->logfile = fopen ((char *) arg, "w"); - return 1; + MEDATA->logfile = fopen ((char *) arg, "w"); + return 1; case VFS_SETCTL_FLUSH: - MEDATA->flush = 1; - return 1; + MEDATA->flush = 1; + return 1; } return 0; } @@ -1109,9 +1146,9 @@ vfs_s_getid (struct vfs_class *me, const char *path) char *p; if (!(p = vfs_s_get_path (me, path, &archive, FL_NO_OPEN))) - return NULL; - g_free(p); - return (vfsid) archive; + return NULL; + g_free (p); + return (vfsid) archive; } static int @@ -1125,7 +1162,7 @@ vfs_s_nothingisopen (vfsid id) static void vfs_s_free (vfsid id) { - vfs_s_free_super (((struct vfs_s_super *)id)->me, (struct vfs_s_super *)id); + vfs_s_free_super (((struct vfs_s_super *) id)->me, (struct vfs_s_super *) id); } static int @@ -1133,14 +1170,15 @@ vfs_s_dir_uptodate (struct vfs_class *me, struct vfs_s_inode *ino) { struct timeval tim; - if (MEDATA->flush) { - MEDATA->flush = 0; - return 0; + if (MEDATA->flush) + { + MEDATA->flush = 0; + return 0; } - gettimeofday(&tim, NULL); + gettimeofday (&tim, NULL); if (tim.tv_sec < ino->timestamp.tv_sec) - return 1; + return 1; return 0; } @@ -1153,8 +1191,9 @@ vfs_s_init_class (struct vfs_class *vclass, struct vfs_s_subclass *sub) vclass->open = vfs_s_open; vclass->close = vfs_s_close; vclass->read = vfs_s_read; - if (!(sub->flags & VFS_S_READONLY)) { - vclass->write = vfs_s_write; + if (!(sub->flags & VFS_S_READONLY)) + { + vclass->write = vfs_s_write; } vclass->opendir = vfs_s_opendir; vclass->readdir = vfs_s_readdir; @@ -1169,12 +1208,15 @@ vfs_s_init_class (struct vfs_class *vclass, struct vfs_s_subclass *sub) vclass->getid = vfs_s_getid; vclass->nothingisopen = vfs_s_nothingisopen; vclass->free = vfs_s_free; - if (sub->flags & VFS_S_REMOTE) { - vclass->getlocalcopy = vfs_s_getlocalcopy; - vclass->ungetlocalcopy = vfs_s_ungetlocalcopy; - sub->find_entry = vfs_s_find_entry_linear; - } else { - sub->find_entry = vfs_s_find_entry_tree; + if (sub->flags & VFS_S_REMOTE) + { + vclass->getlocalcopy = vfs_s_getlocalcopy; + vclass->ungetlocalcopy = vfs_s_ungetlocalcopy; + sub->find_entry = vfs_s_find_entry_linear; + } + else + { + sub->find_entry = vfs_s_find_entry_tree; } vclass->setctl = vfs_s_setctl; sub->dir_uptodate = vfs_s_dir_uptodate; @@ -1191,18 +1233,18 @@ vfs_s_select_on_two (int fd1, int fd2) int v; int maxfd = (fd1 > fd2 ? fd1 : fd2) + 1; - time_out.tv_sec = 1; + time_out.tv_sec = 1; time_out.tv_usec = 0; FD_ZERO (&set); FD_SET (fd1, &set); FD_SET (fd2, &set); v = select (maxfd, &set, 0, 0, &time_out); if (v <= 0) - return v; + return v; if (FD_ISSET (fd1, &set)) - return 1; + return 1; if (FD_ISSET (fd2, &set)) - return 2; + return 2; return -1; } @@ -1213,28 +1255,33 @@ vfs_s_get_line (struct vfs_class *me, int sock, char *buf, int buf_len, char ter int i; char c; - for (i = 0; i < buf_len - 1; i++, buf++){ - if (read (sock, buf, sizeof(char)) <= 0) - return 0; - if (logfile){ - fwrite (buf, 1, 1, logfile); - fflush (logfile); - } - if (*buf == term){ - *buf = 0; - return 1; - } + for (i = 0; i < buf_len - 1; i++, buf++) + { + if (read (sock, buf, sizeof (char)) <= 0) + return 0; + if (logfile) + { + fwrite (buf, 1, 1, logfile); + fflush (logfile); + } + if (*buf == term) + { + *buf = 0; + return 1; + } } /* Line is too long - terminate buffer and discard the rest of line */ *buf = 0; - while (read (sock, &c, sizeof (c)) > 0) { - if (logfile){ - fwrite (&c, 1, 1, logfile); - fflush (logfile); - } - if (c == '\n') - return 1; + while (read (sock, &c, sizeof (c)) > 0) + { + if (logfile) + { + fwrite (&c, 1, 1, logfile); + fflush (logfile); + } + if (c == '\n') + return 1; } return 0; } @@ -1248,23 +1295,27 @@ vfs_s_get_line_interruptible (struct vfs_class *me, char *buffer, int size, int (void) me; tty_enable_interrupt_key (); - for (i = 0; i < size-1; i++){ - n = read (fd, buffer+i, 1); - tty_disable_interrupt_key (); - if (n == -1 && errno == EINTR){ - buffer [i] = 0; - return EINTR; - } - if (n == 0){ - buffer [i] = 0; - return 0; - } - if (buffer [i] == '\n'){ - buffer [i] = 0; - return 1; - } + for (i = 0; i < size - 1; i++) + { + n = read (fd, buffer + i, 1); + tty_disable_interrupt_key (); + if (n == -1 && errno == EINTR) + { + buffer[i] = 0; + return EINTR; + } + if (n == 0) + { + buffer[i] = 0; + return 0; + } + if (buffer[i] == '\n') + { + buffer[i] = 0; + return 1; + } } - buffer [size-1] = 0; + buffer[size - 1] = 0; return 0; } #endif /* USE_NETCODE */ diff --git a/lib/vfs/mc-vfs/fish.c b/lib/vfs/mc-vfs/fish.c dissimilarity index 62% index 1f20c95d..966317f3 100644 --- a/lib/vfs/mc-vfs/fish.c +++ b/lib/vfs/mc-vfs/fish.c @@ -1,1263 +1,1337 @@ -/* Virtual File System: FISH implementation for transfering files over - shell connections. - - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - 2007 Free Software Foundation, Inc. - - Written by: 1998 Pavel Machek - Spaces fix: 2000 Michal Svec - - Derived from ftpfs.c. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License - as published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/** - * \file - * \brief Source: Virtual File System: FISH implementation for transfering files over - * shell connections - * \author Pavel Machek - * \author Michal Svec - * \date 1998, 2000 - * - * Derived from ftpfs.c - * Read README.fish for protocol specification. - * - * Syntax of path is: \verbatim /#sh:user@host[:Cr]/path \endverbatim - * where C means you want compressed connection, - * and r means you want to use rsh - * - * Namespace: fish_vfs_ops exported. - */ - -/* Define this if your ssh can take -I option */ - -#include -#include -#include -#include -#include -#include /* gettimeofday() */ -#include -#include - -#include "lib/global.h" -#include "lib/fs.h" -#include "lib/tty/tty.h" /* enable/disable interrupt key */ -#include "lib/strescape.h" -#include "lib/unixcompat.h" - -#include "src/wtools.h" /* message() */ -#include "src/main.h" /* print_vfs_message */ -#include "utilvfs.h" -#include "xdirentry.h" -#include "vfs.h" -#include "vfs-impl.h" -#include "gc.h" /* vfs_stamp_create */ -#include "netutil.h" -#include "fish.h" - -int fish_directory_timeout = 900; - -#define DO_RESOLVE_SYMLINK 1 -#define DO_OPEN 2 -#define DO_FREE_RESOURCE 4 - -#define FISH_FLAG_COMPRESSED 1 -#define FISH_FLAG_RSH 2 - -#define OPT_FLUSH 1 -#define OPT_IGNORE_ERROR 2 - -/* - * Reply codes. - */ -#define PRELIM 1 /* positive preliminary */ -#define COMPLETE 2 /* positive completion */ -#define CONTINUE 3 /* positive intermediate */ -#define TRANSIENT 4 /* transient negative completion */ -#define ERROR 5 /* permanent negative completion */ - -/* command wait_flag: */ -#define NONE 0x00 -#define WAIT_REPLY 0x01 -#define WANT_STRING 0x02 -static char reply_str [80]; - -static struct vfs_class vfs_fish_ops; - -static int - fish_command (struct vfs_class *me, struct vfs_s_super *super, - int wait_reply, const char *fmt, ...) - __attribute__ ((format (__printf__, 4, 5))); - -static int fish_decode_reply (char *s, int was_garbage) -{ - int code; - if (!sscanf(s, "%d", &code)) { - code = 500; - return 5; - } - if (code<100) return was_garbage ? ERROR : (!code ? COMPLETE : PRELIM); - return code / 100; -} - -/* 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) -{ - char answer[1024]; - int was_garbage = 0; - - for (;;) { - if (!vfs_s_get_line(me, sock, answer, sizeof(answer), '\n')) { - if (string_buf) - *string_buf = 0; - return 4; - } - - if (strncmp(answer, "### ", 4)) { - was_garbage = 1; - if (string_buf) - g_strlcpy(string_buf, answer, string_len); - } else return fish_decode_reply(answer+4, was_garbage); - } -} - -#define SUP super->u.fish - -static int -fish_command (struct vfs_class *me, struct vfs_s_super *super, - int wait_reply, const char *fmt, ...) -{ - va_list ap; - char *str; - int status; - FILE *logfile = MEDATA->logfile; - - va_start (ap, fmt); - - str = g_strdup_vprintf (fmt, ap); - va_end (ap); - - if (logfile) { - fwrite (str, strlen (str), 1, logfile); - fflush (logfile); - } - - tty_enable_interrupt_key (); - - status = write (SUP.sockw, str, strlen (str)); - g_free (str); - - tty_disable_interrupt_key (); - if (status < 0) - return TRANSIENT; - - if (wait_reply) - return fish_get_reply (me, SUP.sockr, - (wait_reply & WANT_STRING) ? reply_str : - NULL, sizeof (reply_str) - 1); - return COMPLETE; -} - -static void -fish_free_archive (struct vfs_class *me, struct vfs_s_super *super) -{ - if ((SUP.sockw != -1) || (SUP.sockr != -1)) { - print_vfs_message (_("fish: Disconnecting from %s"), - super->name ? super->name : "???"); - fish_command (me, super, NONE, "#BYE\nexit\n"); - close (SUP.sockw); - close (SUP.sockr); - SUP.sockw = SUP.sockr = -1; - } - g_free (SUP.host); - g_free (SUP.user); - g_free (SUP.cwdir); - g_free (SUP.password); -} - -static void -fish_pipeopen(struct vfs_s_super *super, const char *path, const char *argv[]) -{ - int fileset1[2], fileset2[2]; - int res; - - if ((pipe(fileset1)<0) || (pipe(fileset2)<0)) - vfs_die("Cannot pipe(): %m."); - - if ((res = fork())) { - if (res<0) vfs_die("Cannot fork(): %m."); - /* We are the parent */ - close(fileset1[0]); - SUP.sockw = fileset1[1]; - close(fileset2[1]); - SUP.sockr = fileset2[0]; - } else { - close(0); - dup(fileset1[0]); - close(fileset1[0]); close(fileset1[1]); - close(1); close(2); - dup(fileset2[1]); - /* stderr to /dev/null */ - open ("/dev/null", O_WRONLY); - close(fileset2[0]); close(fileset2[1]); - execvp(path, const_cast(char **, argv)); - _exit(3); - } -} - -/* The returned directory should always contain a trailing slash */ -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) - return g_strconcat (reply_str, "/", (char *) NULL); - ERRNOR (EIO, NULL); -} - -static int -fish_open_archive_int (struct vfs_class *me, struct vfs_s_super *super) -{ - { - char gbuf[10]; - const char *argv[10]; /* All of 10 is used now */ - const char *xsh = (SUP.flags == FISH_FLAG_RSH ? "rsh" : "ssh"); - int i = 0; - - argv[i++] = xsh; - if (SUP.flags == FISH_FLAG_COMPRESSED) - argv[i++] = "-C"; - - if (SUP.flags > FISH_FLAG_RSH) - { - argv[i++] = "-p"; - g_snprintf (gbuf, sizeof (gbuf), "%d", SUP.flags); - argv[i++] = gbuf; - } - - /* - * Add the user name to the ssh command line only if it was explicitly - * set in vfs URL. rsh/ssh will get current user by default - * plus we can set convenient overrides in ~/.ssh/config (explicit -l - * option breaks it for some) - */ - - if (SUP.user) { - argv[i++] = "-l"; - argv[i++] = SUP.user; - } - else - { - /* The rest of the code assumes it to be a valid username */ - SUP.user = vfs_get_local_username(); - } - - argv[i++] = SUP.host; - argv[i++] = "echo FISH:; /bin/sh"; - argv[i++] = NULL; - - fish_pipeopen (super, xsh, argv); - } - { - char answer[2048]; - print_vfs_message (_("fish: Waiting for initial line...")); - if (!vfs_s_get_line (me, SUP.sockr, answer, sizeof (answer), ':')) - ERRNOR (E_PROTO, -1); - print_vfs_message ("%s", answer); - if (strstr (answer, "assword")) { - - /* Currently, this does not work. ssh reads passwords from - /dev/tty, not from stdin :-(. */ - - message (D_ERROR, MSG_ERROR, - _ - ("Sorry, we cannot do password authenticated connections for now.")); - ERRNOR (EPERM, -1); - if (!SUP.password) { - char *p, *op; - p = g_strconcat (_(" fish: Password required for "), - SUP.user, " ", (char *) NULL); - op = vfs_get_password (p); - g_free (p); - if (op == NULL) - ERRNOR (EPERM, -1); - SUP.password = op; - } - print_vfs_message (_("fish: Sending password...")); - write (SUP.sockw, SUP.password, strlen (SUP.password)); - write (SUP.sockw, "\n", 1); - } - } - - print_vfs_message (_("fish: Sending initial line...")); - /* - * Run `start_fish_server'. If it doesn't exist - no problem, - * we'll talk directly to the shell. - */ - if (fish_command - (me, super, WAIT_REPLY, - "#FISH\necho; start_fish_server 2>&1; echo '### 200'\n") != - COMPLETE) - ERRNOR (E_PROTO, -1); - - print_vfs_message (_("fish: Handshaking version...")); - if (fish_command - (me, super, WAIT_REPLY, - "#VER 0.0.0\necho '### 000'\n") != COMPLETE) - ERRNOR (E_PROTO, -1); - - /* Set up remote locale to C, otherwise dates cannot be recognized */ - if (fish_command - (me, super, WAIT_REPLY, - "LANG=C; LC_ALL=C; LC_TIME=C\n" - "export LANG; export LC_ALL; export LC_TIME\n" "echo '### 200'\n") - != COMPLETE) - ERRNOR (E_PROTO, -1); - - print_vfs_message (_("fish: Setting up current directory...")); - SUP.cwdir = fish_getcwd (me, super); - print_vfs_message (_("fish: Connected, home %s."), SUP.cwdir); -#if 0 - super->name = - g_strconcat ("/#sh:", SUP.user, "@", SUP.host, "/", (char *) NULL); -#endif - super->name = g_strdup (PATH_SEP_STR); - - super->root = - vfs_s_new_inode (me, super, - vfs_s_default_stat (me, S_IFDIR | 0755)); - return 0; -} - -static int -fish_open_archive (struct vfs_class *me, struct vfs_s_super *super, - const char *archive_name, char *op) -{ - char *host, *user, *password, *p; - int flags; - - (void) archive_name; - - p = vfs_split_url (strchr (op, ':') + 1, &host, &user, &flags, - &password, 0, URL_NOSLASH | URL_USE_ANONYMOUS); - - g_free (p); - - SUP.host = host; - SUP.user = user; - SUP.flags = flags; - if (!strncmp (op, "rsh:", 4)) - SUP.flags = FISH_FLAG_RSH; - SUP.cwdir = NULL; - if (password) - SUP.password = password; - return fish_open_archive_int (me, super); -} - -static int -fish_archive_same (struct vfs_class *me, struct vfs_s_super *super, - const char *archive_name, char *op, void *cookie) -{ - char *host, *user; - int flags; - int result; - - (void) me; - (void) archive_name; - (void) cookie; - - op = vfs_split_url (strchr (op, ':') + 1, &host, &user, &flags, 0, 0, - URL_NOSLASH | URL_USE_ANONYMOUS); - - g_free (op); - - if (user == NULL) - user = vfs_get_local_username(); - - result = ((strcmp (host, SUP.host) == 0) - && (strcmp (user, SUP.user) == 0) - && (flags == SUP.flags)); - - g_free (host); - g_free (user); - - return result; -} - -static int -fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path) -{ - struct vfs_s_super *super = dir->super; - char buffer[8192]; - struct vfs_s_entry *ent = NULL; - FILE *logfile; - char *quoted_path; - int reply_code; - gchar *shell_commands; - -#if 0 - /* - * Simple FISH debug interface :] - */ - if (!(MEDATA->logfile)) - { - MEDATA->logfile = fopen("/tmp/mc-FISH.sh", "w"); - } -#endif /* 0 */ - - logfile = MEDATA->logfile; - - print_vfs_message(_("fish: Reading directory %s..."), remote_path); - - gettimeofday(&dir->timestamp, NULL); - dir->timestamp.tv_sec += fish_directory_timeout; - quoted_path = strutils_shell_escape (remote_path); - shell_commands = g_strconcat( - "#LIST /%s\n" - "if `perl -v > /dev/null 2>&1` ; then\n" - "perl -e '\n" - "use strict;\n" - "use POSIX;\n" - "use Fcntl;\n" - "use POSIX \":fcntl_h\"; #S_ISLNK was here until 5.6\n" - "import Fcntl \":mode\" unless defined &S_ISLNK; #and is now here\n" - "my $dirname = $ARGV[0];\n" - "if (opendir ( DIR, $dirname )) {\n" - "while( (my $filename = readdir(DIR))){\n" - "my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = lstat(\"$dirname/$filename\");\n" - "my $mloctime= strftime(\"%%m-%%d-%%Y %%H:%%M\", localtime $mtime);\n" - , - "my $strutils_shell_escape_regex= s/([;<>\\*\\|`&\\$!#\\(\\)\\[\\]\\{\\}:'\\''\"\\ \\\\])/\\\\$1/g;\n" - "my $e_filename = $filename;\n" - "$e_filename =~ $strutils_shell_escape_regex;\n" - "if (S_ISLNK($mode) ) {\n" - "my $linkname = readlink (\"$dirname/$filename\");\n" - "$linkname =~ $strutils_shell_escape_regex;\n" - "\n" - "printf(\"R%%o %%o $uid.$gid\\n" - "S$size\\n" - "d$mloctime\\n" - ":\\\"$e_filename\\\" -> \\\"$linkname\\\"\\n" - "\\n\", S_IMODE($mode), S_IFMT($mode));\n" - "} else {\n" - "printf(\"R%%o %%o $uid.$gid\\n" - "S$size\\n" - "d$mloctime\\n" - ":\\\"$e_filename\\\"\\n" - "\\n\", S_IMODE($mode), S_IFMT($mode));\n" - "}}\n" - , - "printf(\"### 200\\n\");\n" - "closedir(DIR);\n" - "} else {\n" - "printf(\"### 500\\n\");\n" - "}\n" - "exit 0\n" - "' /%s ||\n" /* ARGV[0] - path to browse */ - " echo '### 500'\n" /* do not hang if perl is to eval it */ - "elif `ls -1 /%s >/dev/null 2>&1` ; then\n" - "if `ls -Q /%s >/dev/null 2>&1`; then\n" - "LSOPT=\"-Qlan\";\n" - "ADD=0;\n" - "else\n" - "LSOPT=\"-lan\";\n" - "ADD=1;\n" - "fi\n" - "ls $LSOPT /%s 2>/dev/null | grep '^[^cbt]' | (\n" - "while read p l u g s m d y n n2 n3; do\n" - "if test \"$m\" = \"0\" ; then \n" - "s=$d; m=$y; d=$n y=$n2; n=$n3\n" - "else\n" - "n=$n\" \"$n2\" \"$n3\n" - "fi\n" - "if [ $ADD = 0 ]; then\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" - "file=`echo $n | sed -e 's#^\\(.*\\) -> \\(.*\\)#\\1\" -> \"\\2#'`\n" - , - "echo \"P$p $u $g\nS$s\nd$m $d $y\n:\"$file\"\n\"\n" - "else\n" - "echo \"P$p $u $g\nS$s\nd$m $d $y\n:\"$n\"\n\"\n" - "fi\n" - "done )\n" - "ls $LSOPT /%s 2>/dev/null | grep '^[cb]' | (\n" - "while read p l u g a i m d y n n2 n3; do\n" - "if test \"$a\" = \"0\" ; then \n" - "a=$m; i=$d; m=$y; d=$n y=$n2; n=$n3\n" - "else\n" - "n=$n\" \"$n2\" \"$n3\n" - "fi\n" - "if [ $ADD = 0 ]; then\n" - "echo \"P$p $u.$g\nE$a$i\nd$m $d $y\n:$n\n\"\n" - "elif `sed --version >/dev/null 2>&1` ; then\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" - "else\n" - "echo \"P$p $u $g\nS$s\nd$m $d $y\n:\"$n\"\n\"\n" - "fi\n" - "done)\n" - "echo '### 200'\n" - "else\n" - "echo '### 500'\n" - "fi\n" - , (char *) NULL - ); - - fish_command (me, super, NONE, shell_commands, - quoted_path, quoted_path, quoted_path, quoted_path, quoted_path, quoted_path); - - g_free(shell_commands); - g_free (quoted_path); - ent = vfs_s_generate_entry(me, NULL, dir, 0); - while (1) { - int res = vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), SUP.sockr); - if ((!res) || (res == EINTR)) { - vfs_s_free_entry(me, ent); - me->verrno = ECONNRESET; - goto error; - } - if (logfile) { - fputs (buffer, logfile); - fputs ("\n", logfile); - fflush (logfile); - } - if (!strncmp(buffer, "### ", 4)) - break; - if ((!buffer[0])) { - if (ent->name) { - vfs_s_insert_entry(me, dir, ent); - ent = vfs_s_generate_entry(me, NULL, dir, 0); - } - continue; - } - -#define ST ent->ino->st - - switch(buffer[0]) { - case ':': { - char *temp; - char *data_start = buffer+1; - char *filename = data_start; - char *linkname = data_start; - char *filename_bound = filename + strlen(filename); - char *linkname_bound = filename_bound; - if (!strcmp(data_start, "\".\"") || !strcmp(data_start, "\"..\"")) - break; /* We'll do "." and ".." ourselves */ - - if (S_ISLNK(ST.st_mode)) { - /* we expect: "escaped-name" -> "escaped-name" - // -> cannot occur in filenames, - // because it will be escaped to -\> */ - - if (*filename == '"') - ++filename; - - linkname = strstr(filename, "\" -> \""); - if (!linkname) - { - /* broken client, or smth goes wrong */ - linkname = filename_bound; - if (filename_bound > filename - && *(filename_bound - 1) == '"') - --filename_bound; /* skip trailing " */ - } - else - { - filename_bound = linkname; - linkname += 6; /* strlen ("\" -> \"") */ - if (*(linkname_bound - 1) == '"') - --linkname_bound; /* skip trailing " */ - } - - ent->name = str_dup_range(filename, filename_bound); - temp = ent->name; - ent->name = strutils_shell_unescape(ent->name); - g_free(temp); - - ent->ino->linkname = str_dup_range(linkname, linkname_bound); - temp = ent->ino->linkname; - ent->ino->linkname = strutils_shell_unescape(ent->ino->linkname); - g_free(temp); - } else { - /* we expect: "escaped-name" */ - if (filename_bound - filename > 2) - { - /* - there is at least 2 " - and we skip them - */ - if (*filename == '"') - ++filename; - if (*(filename_bound - 1) == '"') - --filename_bound; - } - ent->name = str_dup_range(filename, filename_bound); - temp = ent->name; - ent->name = strutils_shell_unescape(ent->name); - g_free(temp); - } - break; - } - case 'S': -#ifdef HAVE_ATOLL - ST.st_size = (off_t) atoll (buffer+1); -#else - ST.st_size = (off_t) atof (buffer+1); -#endif - break; - case 'P': { - size_t skipped; - vfs_parse_filemode (buffer + 1, &skipped, &ST.st_mode); - break; - } - case 'R': { - /* - raw filemode: - we expect: Roctal-filemode octal-filetype uid.gid - */ - size_t skipped; - vfs_parse_raw_filemode (buffer + 1, &skipped, &ST.st_mode); - break; - } - case 'd': { - vfs_split_text(buffer+1); - if (!vfs_parse_filedate(0, &ST.st_ctime)) - break; - ST.st_atime = ST.st_mtime = ST.st_ctime; - } - break; - case 'D': { - struct tm tim; - 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) - break; - ST.st_atime = ST.st_mtime = ST.st_ctime = mktime(&tim); - } - break; - case 'E': { - int maj, min; - if (sscanf(buffer+1, "%d,%d", &maj, &min) != 2) - break; -#ifdef HAVE_STRUCT_STAT_ST_RDEV - ST.st_rdev = makedev (maj, min); -#endif - } - } - } - - vfs_s_free_entry (me, ent); - reply_code = fish_decode_reply(buffer + 4, 0); - if (reply_code == COMPLETE) { - g_free (SUP.cwdir); - SUP.cwdir = g_strdup (remote_path); - print_vfs_message (_("%s: done."), me->name); - return 0; - } else if (reply_code == ERROR) { - me->verrno = EACCES; - } else { - me->verrno = E_REMOTE; - } - -error: - print_vfs_message (_("%s: failure"), me->name); - return -1; -} - -static int -fish_file_store(struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *localname) -{ - struct vfs_s_super *super = FH_SUPER; - int n, total; - char buffer[8192]; - struct stat s; - int was_error = 0; - int h; - char *quoted_name; - - h = open (localname, O_RDONLY); - - if (h == -1) - ERRNOR (EIO, -1); - if (fstat(h, &s)<0) { - close (h); - ERRNOR (EIO, -1); - } - - /* First, try this as stor: - * - * ( head -c number ) | ( cat > file; cat >/dev/null ) - * - * If `head' is not present on the remote system, `dd' will be used. - * Unfortunately, we cannot trust most non-GNU `head' implementations - * even if `-c' options is supported. Therefore, we separate GNU head - * (and other modern heads?) using `-q' and `-' . This causes another - * implementations to fail (because of "incorrect options"). - * - * Fallback is: - * - * rest= - * while [ $rest -gt 0 ] - * do - * cnt=`expr \( $rest + 255 \) / 256` - * n=`dd bs=256 count=$cnt | tee -a | wc -c` - * rest=`expr $rest - $n` - * done - * - * `dd' was not designed for full filling of input buffers, - * and does not report exact number of bytes (not blocks). - * Therefore a more complex shell script is needed. - * - * On some systems non-GNU head writes "Usage:" error report to stdout - * instead of stderr. It makes impossible the use of "head || dd" - * algorithm for file appending case, therefore just "dd" is used for it. - */ - - quoted_name = strutils_shell_escape(name); - print_vfs_message(_("fish: store %s: sending command..."), quoted_name ); - - /* FIXME: File size is limited to ULONG_MAX */ - if (!fh->u.fish.append) - n = fish_command (me, super, WAIT_REPLY, - "#STOR %lu /%s\n" - "echo '### 001'\n" - "file=/%s\n" - "res=`exec 3>&1\n" - "(\n" - "head -c %lu -q - || echo DD >&3\n" - ") 2>/dev/null | (\n" - "cat > $file\n" - "cat > /dev/null\n" - ")`; [ \"$res\" = DD ] && {\n" - "> \"$file\"\n" - "rest=%lu\n" - "while [ $rest -gt 0 ]\n" - "do\n" - " cnt=`expr \\( $rest + 255 \\) / 256`\n" - " n=`dd bs=256 count=$cnt | tee -a \"$file\" | wc -c`\n" - " rest=`expr $rest - $n`\n" - "done\n" - "}; echo '### 200'\n", - (unsigned long) s.st_size, quoted_name, - quoted_name, (unsigned long) s.st_size, - (unsigned long) s.st_size); - else - n = fish_command (me, super, WAIT_REPLY, - "#STOR %lu /%s\n" - "echo '### 001'\n" - "{\n" - "file=/%s\n" - "rest=%lu\n" - "while [ $rest -gt 0 ]\n" - "do\n" - " cnt=`expr \\( $rest + 255 \\) / 256`\n" - " n=`dd bs=256 count=$cnt | tee -a $file | wc -c`\n" - " rest=`expr $rest - $n`\n" - "done\n" - "}; echo '### 200'\n", - (unsigned long) s.st_size, quoted_name, - quoted_name, (unsigned long) s.st_size); - - if (n != PRELIM) { - close (h); - ERRNOR(E_REMOTE, -1); - } - total = 0; - - while (1) { - int t; - while ((n = read(h, buffer, sizeof(buffer))) < 0) { - if ((errno == EINTR) && tty_got_interrupt ()) - continue; - print_vfs_message(_("fish: Local read failed, sending zeros") ); - close(h); - h = open( "/dev/zero", O_RDONLY ); - } - if (n == 0) - break; - if ((t = write (SUP.sockw, buffer, n)) != n) { - if (t == -1) { - me->verrno = errno; - } else { - me->verrno = EIO; - } - goto error_return; - } - tty_disable_interrupt_key (); - total += n; - print_vfs_message(_("fish: storing %s %d (%lu)"), - was_error ? _("zeros") : _("file"), total, - (unsigned long) s.st_size); - } - close(h); - g_free(quoted_name); - if ((fish_get_reply (me, SUP.sockr, NULL, 0) != COMPLETE) || was_error) - ERRNOR (E_REMOTE, -1); - return 0; -error_return: - close(h); - fish_get_reply(me, SUP.sockr, NULL, 0); - g_free(quoted_name); - return -1; -} - -static int -fish_linear_start (struct vfs_class *me, struct vfs_s_fh *fh, off_t offset) -{ - char *name; - char *quoted_name; - if (offset) - ERRNOR (E_NOTSUPP, 0); - name = vfs_s_fullpath (me, fh->ino); - if (name == NULL) - return 0; - quoted_name = strutils_shell_escape (name); - g_free (name); - fh->u.fish.append = 0; - - /* - * Check whether the remote file is readable by using `dd' to copy - * a single byte from the remote file to /dev/null. If `dd' completes - * with exit status of 0 use `cat' to send the file contents to the - * standard output (i.e. over the network). - */ - offset = fish_command (me, FH_SUPER, WANT_STRING, - "#RETR /%s\n" - "if dd if=/%s of=/dev/null bs=1 count=1 2>/dev/null ;\n" - "then\n" - "ls -ln /%s 2>/dev/null | (\n" - "read p l u g s r\n" - "echo $s\n" - ")\n" - "echo '### 100'\n" - "cat /%s\n" - "echo '### 200'\n" - "else\n" - "echo '### 500'\n" - "fi\n", - quoted_name, quoted_name, quoted_name, quoted_name ); - g_free (quoted_name); - if (offset != PRELIM) ERRNOR (E_REMOTE, 0); - fh->linear = LS_LINEAR_OPEN; - fh->u.fish.got = 0; - errno = 0; -#if SIZEOF_OFF_T == SIZEOF_LONG - fh->u.fish.total = strtol (reply_str, NULL, 10); -#else - fh->u.fish.total = strtoll (reply_str, NULL, 10); -#endif - if (errno != 0) - ERRNOR (E_REMOTE, 0); - return 1; -} - -static void -fish_linear_abort (struct vfs_class *me, struct vfs_s_fh *fh) -{ - struct vfs_s_super *super = FH_SUPER; - char buffer[8192]; - int n; - - print_vfs_message( _("Aborting transfer...") ); - do { - n = MIN(8192, fh->u.fish.total - fh->u.fish.got); - if (n) { - if ((n = read(SUP.sockr, buffer, n)) < 0) - return; - fh->u.fish.got += n; - } - } while (n); - - if (fish_get_reply (me, SUP.sockr, NULL, 0) != COMPLETE) - print_vfs_message( _("Error reported after abort.") ); - else - print_vfs_message( _("Aborted transfer would be successful.") ); -} - -static int -fish_linear_read (struct vfs_class *me, struct vfs_s_fh *fh, void *buf, int len) -{ - struct vfs_s_super *super = FH_SUPER; - int n = 0; - len = MIN( fh->u.fish.total - fh->u.fish.got, len ); - tty_disable_interrupt_key (); - while (len && ((n = read (SUP.sockr, buf, len))<0)) { - if ((errno == EINTR) && !tty_got_interrupt ()) - continue; - break; - } - tty_enable_interrupt_key(); - - if (n>0) fh->u.fish.got += n; - if (n<0) fish_linear_abort(me, fh); - if ((!n) && ((fish_get_reply (me, SUP.sockr, NULL, 0) != COMPLETE))) - ERRNOR (E_REMOTE, -1); - ERRNOR (errno, n); -} - -static void -fish_linear_close (struct vfs_class *me, struct vfs_s_fh *fh) -{ - if (fh->u.fish.total != fh->u.fish.got) - fish_linear_abort(me, fh); -} - -static int -fish_ctl (void *fh, int ctlop, void *arg) -{ - (void) arg; - (void) fh; - (void) ctlop; - return 0; -#if 0 - switch (ctlop) { - case VFS_CTL_IS_NOTREADY: - { - int v; - - if (!FH->linear) - vfs_die ("You may not do this"); - if (FH->linear == LS_LINEAR_CLOSED || FH->linear == LS_LINEAR_PREOPEN) - return 0; - - v = vfs_s_select_on_two (FH_SUPER->u.fish.sockr, 0); - if (((v < 0) && (errno == EINTR)) || v == 0) - return 1; - return 0; - } - default: - return 0; - } -#endif -} - -static int -fish_send_command(struct vfs_class *me, struct vfs_s_super *super, const char *cmd, int flags) -{ - int r; - - r = fish_command (me, super, WAIT_REPLY, "%s", cmd); - vfs_stamp_create (&vfs_fish_ops, super); - if (r != COMPLETE) ERRNOR (E_REMOTE, -1); - if (flags & OPT_FLUSH) - vfs_s_invalidate(me, super); - return 0; -} - -#define PREFIX \ - char buf[BUF_LARGE]; \ - const char *crpath; \ - char *rpath, *mpath = g_strdup (path); \ - struct vfs_s_super *super; \ - if (!(crpath = vfs_s_get_path_mangle (me, mpath, &super, 0))) { \ - g_free (mpath); \ - return -1; \ - } \ - rpath = strutils_shell_escape(crpath); \ - g_free (mpath); - -#define POSTFIX(flags) \ - g_free (rpath); \ - return fish_send_command(me, super, buf, flags); - -static int -fish_chmod (struct vfs_class *me, const char *path, int mode) -{ - PREFIX - g_snprintf(buf, sizeof(buf), "#CHMOD %4.4o /%s\n" - "if chmod %4.4o /%s 2>/dev/null; then\n" - "echo '### 000'\n" - "else\n" - "echo '### 500'\n" - "fi\n", - mode & 07777, rpath, - mode & 07777, rpath); - POSTFIX(OPT_FLUSH); -} - -#define FISH_OP(name, string) \ -static int fish_##name (struct vfs_class *me, const char *path1, const char *path2) \ -{ \ - char buf[BUF_LARGE]; \ - const char *crpath1, *crpath2; \ - char *rpath1, *rpath2, *mpath1, *mpath2; \ - struct vfs_s_super *super1, *super2; \ - if (!(crpath1 = vfs_s_get_path_mangle (me, mpath1 = g_strdup(path1), &super1, 0))) { \ - g_free (mpath1); \ - return -1; \ - } \ - if (!(crpath2 = vfs_s_get_path_mangle (me, mpath2 = g_strdup(path2), &super2, 0))) { \ - g_free (mpath1); \ - g_free (mpath2); \ - return -1; \ - } \ - rpath1 = strutils_shell_escape (crpath1); \ - g_free (mpath1); \ - rpath2 = strutils_shell_escape (crpath2); \ - g_free (mpath2); \ - g_snprintf(buf, sizeof(buf), string "\n", rpath1, rpath2, rpath1, rpath2); \ - g_free (rpath1); \ - g_free (rpath2); \ - return fish_send_command(me, super2, buf, OPT_FLUSH); \ -} - -FISH_OP(rename, "#RENAME /%s /%s\n" - "if mv /%s /%s 2>/dev/null; then\n" - "echo '### 000'\n" - "else\n" - "echo '### 500'\n" - "fi\n") -FISH_OP(link, "#LINK /%s /%s\n" - "if ln /%s /%s 2>/dev/null; then\n" - "echo '### 000'\n" - "else\n" - "echo '### 500'\n" - "fi\n") - -static int fish_symlink (struct vfs_class *me, const char *setto, const char *path) -{ - char *qsetto; - PREFIX - qsetto = strutils_shell_escape (setto); - g_snprintf(buf, sizeof(buf), - "#SYMLINK %s /%s\n" - "if ln -s %s /%s 2>/dev/null; then\n" - "echo '### 000'\n" - "else\n" - "echo '### 500'\n" - "fi\n", - qsetto, rpath, qsetto, rpath); - g_free (qsetto); - POSTFIX(OPT_FLUSH); -} - -static int -fish_chown (struct vfs_class *me, const char *path, int owner, int group) -{ - char *sowner, *sgroup; - struct passwd *pw; - struct group *gr; - - if ((pw = getpwuid (owner)) == NULL) - return 0; - - if ((gr = getgrgid (group)) == NULL) - return 0; - - sowner = pw->pw_name; - sgroup = gr->gr_name; - { - PREFIX - g_snprintf (buf, sizeof(buf), - "#CHOWN %s:%s /%s\n" - "if chown %s:%s /%s 2>/dev/null; then\n" - "echo '### 000'\n" - "else\n" - "echo '### 500'\n" - "fi\n", - sowner, sgroup, rpath, - sowner, sgroup, rpath); - fish_send_command (me, super, buf, OPT_FLUSH); - /* FIXME: what should we report if chgrp succeeds but chown fails? */ - /* fish_send_command(me, super, buf, OPT_FLUSH); */ - POSTFIX (OPT_FLUSH) - } -} - -static int fish_unlink (struct vfs_class *me, const char *path) -{ - PREFIX - g_snprintf(buf, sizeof(buf), - "#DELE /%s\n" - "if rm -f /%s 2>/dev/null; then\n" - "echo '### 000'\n" - "else\n" - "echo '### 500'\n" - "fi\n", - rpath, rpath); - POSTFIX(OPT_FLUSH); -} - -static int fish_exists (struct vfs_class *me, const char *path) -{ - PREFIX - - g_snprintf(buf, sizeof(buf), - "#ISEXISTS /%s\n" - "ls -l /%s >/dev/null 2>/dev/null\n" - "echo '### '$?\n", - rpath, rpath); - - g_free (rpath); - - if ( fish_send_command(me, super, buf, OPT_FLUSH) == 0 ) - return 1; - - return 0; -} - - -static int fish_mkdir (struct vfs_class *me, const char *path, mode_t mode) -{ - int ret_code; - - PREFIX - - (void) mode; - - g_snprintf(buf, sizeof(buf), - "#MKD /%s\n" - "if mkdir /%s 2>/dev/null; then\n" - "echo '### 000'\n" - "else\n" - "echo '### 500'\n" - "fi\n", - rpath, rpath); - - g_free (rpath); - ret_code = fish_send_command(me, super, buf, OPT_FLUSH); - - if ( ret_code != 0 ) - return ret_code; - - if ( ! fish_exists (me, path) ){ - ERRNOR (EACCES, -1); - } - return 0; -} - -static int fish_rmdir (struct vfs_class *me, const char *path) -{ - PREFIX - g_snprintf(buf, sizeof(buf), - "#RMD /%s\n" - "if rmdir /%s 2>/dev/null; then\n" - "echo '### 000'\n" - "else\n" - "echo '### 500'\n" - "fi\n", - rpath, rpath); - POSTFIX(OPT_FLUSH); -} - -static int -fish_fh_open (struct vfs_class *me, struct vfs_s_fh *fh, int flags, - int mode) -{ - (void) mode; - - fh->u.fish.append = 0; - /* File will be written only, so no need to retrieve it */ - if (((flags & O_WRONLY) == O_WRONLY) && !(flags & (O_RDONLY | O_RDWR))) { - fh->u.fish.append = flags & O_APPEND; - if (!fh->ino->localname) { - int tmp_handle = - vfs_mkstemps (&fh->ino->localname, me->name, - fh->ino->ent->name); - if (tmp_handle == -1) - return -1; - close (tmp_handle); - } - return 0; - } - if (!fh->ino->localname) - if (vfs_s_retrieve_file (me, fh->ino) == -1) - return -1; - if (!fh->ino->localname) - vfs_die ("retrieve_file failed to fill in localname"); - return 0; -} - -static void -fish_fill_names (struct vfs_class *me, fill_names_f func) -{ - struct vfs_s_super *super = MEDATA->supers; - char *name; - - char gbuf[10]; - - while (super) - { - const char *flags = ""; - switch (SUP.flags) - { - case FISH_FLAG_RSH: - flags = ":r"; - break; - case FISH_FLAG_COMPRESSED: - flags = ":C"; - break; - default: - if (SUP.flags > FISH_FLAG_RSH) - { - break; - g_snprintf (gbuf, sizeof (gbuf), ":%d", SUP.flags); - flags = gbuf; - } - break; - } - - name = g_strconcat ("/#sh:", SUP.user, "@", SUP.host, flags, - "/", SUP.cwdir, (char *) NULL); - (*func)(name); - g_free (name); - super = super->next; - } -} - -static void * -fish_open (struct vfs_class *me, const char *file, int flags, int mode) -{ - /* - sorry, i've places hack here - cause fish don't able to open files with O_EXCL flag - */ - flags &= ~O_EXCL; - return vfs_s_open (me, file, flags, mode); -} - - -void -init_fish (void) -{ - static struct vfs_s_subclass fish_subclass; - - tcp_init(); - - fish_subclass.flags = VFS_S_REMOTE; - fish_subclass.archive_same = fish_archive_same; - fish_subclass.open_archive = fish_open_archive; - fish_subclass.free_archive = fish_free_archive; - fish_subclass.fh_open = fish_fh_open; - fish_subclass.dir_load = fish_dir_load; - fish_subclass.file_store = fish_file_store; - fish_subclass.linear_start = fish_linear_start; - fish_subclass.linear_read = fish_linear_read; - fish_subclass.linear_close = fish_linear_close; - - vfs_s_init_class (&vfs_fish_ops, &fish_subclass); - vfs_fish_ops.name = "fish"; - vfs_fish_ops.prefix = "sh:"; - vfs_fish_ops.fill_names = fish_fill_names; - vfs_fish_ops.chmod = fish_chmod; - vfs_fish_ops.chown = fish_chown; - vfs_fish_ops.open = fish_open; - vfs_fish_ops.symlink = fish_symlink; - vfs_fish_ops.link = fish_link; - vfs_fish_ops.unlink = fish_unlink; - vfs_fish_ops.rename = fish_rename; - vfs_fish_ops.mkdir = fish_mkdir; - vfs_fish_ops.rmdir = fish_rmdir; - vfs_fish_ops.ctl = fish_ctl; - vfs_register_class (&vfs_fish_ops); -} +/* Virtual File System: FISH implementation for transfering files over + shell connections. + + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, + 2007 Free Software Foundation, Inc. + + Written by: 1998 Pavel Machek + Spaces fix: 2000 Michal Svec + + Derived from ftpfs.c. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License + as published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/** + * \file + * \brief Source: Virtual File System: FISH implementation for transfering files over + * shell connections + * \author Pavel Machek + * \author Michal Svec + * \date 1998, 2000 + * + * Derived from ftpfs.c + * Read README.fish for protocol specification. + * + * Syntax of path is: \verbatim /#sh:user@host[:Cr]/path \endverbatim + * where C means you want compressed connection, + * and r means you want to use rsh + * + * Namespace: fish_vfs_ops exported. + */ + +/* Define this if your ssh can take -I option */ + +#include +#include +#include +#include +#include +#include /* gettimeofday() */ +#include +#include + +#include "lib/global.h" +#include "lib/fs.h" +#include "lib/tty/tty.h" /* enable/disable interrupt key */ +#include "lib/strescape.h" +#include "lib/unixcompat.h" + +#include "src/wtools.h" /* message() */ +#include "src/main.h" /* print_vfs_message */ +#include "utilvfs.h" +#include "xdirentry.h" +#include "vfs.h" +#include "vfs-impl.h" +#include "gc.h" /* vfs_stamp_create */ +#include "netutil.h" +#include "fish.h" + +int fish_directory_timeout = 900; + +#define DO_RESOLVE_SYMLINK 1 +#define DO_OPEN 2 +#define DO_FREE_RESOURCE 4 + +#define FISH_FLAG_COMPRESSED 1 +#define FISH_FLAG_RSH 2 + +#define OPT_FLUSH 1 +#define OPT_IGNORE_ERROR 2 + +/* + * Reply codes. + */ +#define PRELIM 1 /* positive preliminary */ +#define COMPLETE 2 /* positive completion */ +#define CONTINUE 3 /* positive intermediate */ +#define TRANSIENT 4 /* transient negative completion */ +#define ERROR 5 /* permanent negative completion */ + +/* command wait_flag: */ +#define NONE 0x00 +#define WAIT_REPLY 0x01 +#define WANT_STRING 0x02 +static char reply_str[80]; + +static struct vfs_class vfs_fish_ops; + +static int +fish_command (struct vfs_class *me, struct vfs_s_super *super, + int wait_reply, const char *fmt, ...) __attribute__ ((format (__printf__, 4, 5))); + +static int +fish_decode_reply (char *s, int was_garbage) +{ + int code; + if (!sscanf (s, "%d", &code)) + { + code = 500; + return 5; + } + if (code < 100) + return was_garbage ? ERROR : (!code ? COMPLETE : PRELIM); + return code / 100; +} + +/* 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) +{ + char answer[1024]; + int was_garbage = 0; + + for (;;) + { + if (!vfs_s_get_line (me, sock, answer, sizeof (answer), '\n')) + { + if (string_buf) + *string_buf = 0; + return 4; + } + + if (strncmp (answer, "### ", 4)) + { + was_garbage = 1; + if (string_buf) + g_strlcpy (string_buf, answer, string_len); + } + else + return fish_decode_reply (answer + 4, was_garbage); + } +} + +#define SUP super->u.fish + +static int +fish_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply, const char *fmt, ...) +{ + va_list ap; + char *str; + int status; + FILE *logfile = MEDATA->logfile; + + va_start (ap, fmt); + + str = g_strdup_vprintf (fmt, ap); + va_end (ap); + + if (logfile) + { + fwrite (str, strlen (str), 1, logfile); + fflush (logfile); + } + + tty_enable_interrupt_key (); + + status = write (SUP.sockw, str, strlen (str)); + g_free (str); + + tty_disable_interrupt_key (); + if (status < 0) + return TRANSIENT; + + if (wait_reply) + return fish_get_reply (me, SUP.sockr, + (wait_reply & WANT_STRING) ? reply_str : + NULL, sizeof (reply_str) - 1); + return COMPLETE; +} + +static void +fish_free_archive (struct vfs_class *me, struct vfs_s_super *super) +{ + if ((SUP.sockw != -1) || (SUP.sockr != -1)) + { + print_vfs_message (_("fish: Disconnecting from %s"), super->name ? super->name : "???"); + fish_command (me, super, NONE, "#BYE\nexit\n"); + close (SUP.sockw); + close (SUP.sockr); + SUP.sockw = SUP.sockr = -1; + } + g_free (SUP.host); + g_free (SUP.user); + g_free (SUP.cwdir); + g_free (SUP.password); +} + +static void +fish_pipeopen (struct vfs_s_super *super, const char *path, const char *argv[]) +{ + int fileset1[2], fileset2[2]; + int res; + + if ((pipe (fileset1) < 0) || (pipe (fileset2) < 0)) + vfs_die ("Cannot pipe(): %m."); + + if ((res = fork ())) + { + if (res < 0) + vfs_die ("Cannot fork(): %m."); + /* We are the parent */ + close (fileset1[0]); + SUP.sockw = fileset1[1]; + close (fileset2[1]); + SUP.sockr = fileset2[0]; + } + else + { + close (0); + dup (fileset1[0]); + close (fileset1[0]); + close (fileset1[1]); + close (1); + close (2); + dup (fileset2[1]); + /* stderr to /dev/null */ + open ("/dev/null", O_WRONLY); + close (fileset2[0]); + close (fileset2[1]); + execvp (path, const_cast (char **, argv)); + _exit (3); + } +} + +/* The returned directory should always contain a trailing slash */ +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) + return g_strconcat (reply_str, "/", (char *) NULL); + ERRNOR (EIO, NULL); +} + +static int +fish_open_archive_int (struct vfs_class *me, struct vfs_s_super *super) +{ + { + char gbuf[10]; + const char *argv[10]; /* All of 10 is used now */ + const char *xsh = (SUP.flags == FISH_FLAG_RSH ? "rsh" : "ssh"); + int i = 0; + + argv[i++] = xsh; + if (SUP.flags == FISH_FLAG_COMPRESSED) + argv[i++] = "-C"; + + if (SUP.flags > FISH_FLAG_RSH) + { + argv[i++] = "-p"; + g_snprintf (gbuf, sizeof (gbuf), "%d", SUP.flags); + argv[i++] = gbuf; + } + + /* + * Add the user name to the ssh command line only if it was explicitly + * set in vfs URL. rsh/ssh will get current user by default + * plus we can set convenient overrides in ~/.ssh/config (explicit -l + * option breaks it for some) + */ + + if (SUP.user) + { + argv[i++] = "-l"; + argv[i++] = SUP.user; + } + else + { + /* The rest of the code assumes it to be a valid username */ + SUP.user = vfs_get_local_username (); + } + + argv[i++] = SUP.host; + argv[i++] = "echo FISH:; /bin/sh"; + argv[i++] = NULL; + + fish_pipeopen (super, xsh, argv); + } + { + char answer[2048]; + print_vfs_message (_("fish: Waiting for initial line...")); + if (!vfs_s_get_line (me, SUP.sockr, answer, sizeof (answer), ':')) + ERRNOR (E_PROTO, -1); + print_vfs_message ("%s", answer); + if (strstr (answer, "assword")) + { + + /* Currently, this does not work. ssh reads passwords from + /dev/tty, not from stdin :-(. */ + + message (D_ERROR, MSG_ERROR, + _("Sorry, we cannot do password authenticated connections for now.")); + ERRNOR (EPERM, -1); + if (!SUP.password) + { + char *p, *op; + p = g_strconcat (_(" fish: Password required for "), SUP.user, " ", (char *) NULL); + op = vfs_get_password (p); + g_free (p); + if (op == NULL) + ERRNOR (EPERM, -1); + SUP.password = op; + } + print_vfs_message (_("fish: Sending password...")); + write (SUP.sockw, SUP.password, strlen (SUP.password)); + write (SUP.sockw, "\n", 1); + } + } + + print_vfs_message (_("fish: Sending initial line...")); + /* + * Run `start_fish_server'. If it doesn't exist - no problem, + * we'll talk directly to the shell. + */ + if (fish_command + (me, super, WAIT_REPLY, + "#FISH\necho; start_fish_server 2>&1; echo '### 200'\n") != COMPLETE) + ERRNOR (E_PROTO, -1); + + print_vfs_message (_("fish: Handshaking version...")); + if (fish_command (me, super, WAIT_REPLY, "#VER 0.0.0\necho '### 000'\n") != COMPLETE) + ERRNOR (E_PROTO, -1); + + /* Set up remote locale to C, otherwise dates cannot be recognized */ + if (fish_command + (me, super, WAIT_REPLY, + "LANG=C; LC_ALL=C; LC_TIME=C\n" + "export LANG; export LC_ALL; export LC_TIME\n" "echo '### 200'\n") != COMPLETE) + ERRNOR (E_PROTO, -1); + + print_vfs_message (_("fish: Setting up current directory...")); + SUP.cwdir = fish_getcwd (me, super); + print_vfs_message (_("fish: Connected, home %s."), SUP.cwdir); +#if 0 + super->name = g_strconcat ("/#sh:", SUP.user, "@", SUP.host, "/", (char *) NULL); +#endif + super->name = g_strdup (PATH_SEP_STR); + + super->root = vfs_s_new_inode (me, super, vfs_s_default_stat (me, S_IFDIR | 0755)); + return 0; +} + +static int +fish_open_archive (struct vfs_class *me, struct vfs_s_super *super, + const char *archive_name, char *op) +{ + char *host, *user, *password, *p; + int flags; + + (void) archive_name; + + p = vfs_split_url (strchr (op, ':') + 1, &host, &user, &flags, + &password, 0, URL_NOSLASH | URL_USE_ANONYMOUS); + + g_free (p); + + SUP.host = host; + SUP.user = user; + SUP.flags = flags; + if (!strncmp (op, "rsh:", 4)) + SUP.flags = FISH_FLAG_RSH; + SUP.cwdir = NULL; + if (password) + SUP.password = password; + return fish_open_archive_int (me, super); +} + +static int +fish_archive_same (struct vfs_class *me, struct vfs_s_super *super, + const char *archive_name, char *op, void *cookie) +{ + char *host, *user; + int flags; + int result; + + (void) me; + (void) archive_name; + (void) cookie; + + op = vfs_split_url (strchr (op, ':') + 1, &host, &user, &flags, 0, 0, + URL_NOSLASH | URL_USE_ANONYMOUS); + + g_free (op); + + if (user == NULL) + user = vfs_get_local_username (); + + result = ((strcmp (host, SUP.host) == 0) + && (strcmp (user, SUP.user) == 0) && (flags == SUP.flags)); + + g_free (host); + g_free (user); + + return result; +} + +static int +fish_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path) +{ + struct vfs_s_super *super = dir->super; + char buffer[8192]; + struct vfs_s_entry *ent = NULL; + FILE *logfile; + char *quoted_path; + int reply_code; + gchar *shell_commands; + +#if 0 + /* + * Simple FISH debug interface :] + */ + if (!(MEDATA->logfile)) + { + MEDATA->logfile = fopen ("/tmp/mc-FISH.sh", "w"); + } +#endif /* 0 */ + + logfile = MEDATA->logfile; + + print_vfs_message (_("fish: Reading directory %s..."), remote_path); + + gettimeofday (&dir->timestamp, NULL); + dir->timestamp.tv_sec += fish_directory_timeout; + quoted_path = strutils_shell_escape (remote_path); + /* *INDENT-OFF* */ + shell_commands = g_strconcat ( + "#LIST /%s\n" + "if `perl -v > /dev/null 2>&1` ; then\n" + "perl -e '\n" + "use strict;\n" + "use POSIX;\n" + "use Fcntl;\n" + "use POSIX \":fcntl_h\"; #S_ISLNK was here until 5.6\n" + "import Fcntl \":mode\" unless defined &S_ISLNK; #and is now here\n" + "my $dirname = $ARGV[0];\n" + "if (opendir ( DIR, $dirname )) {\n" + "while( (my $filename = readdir(DIR))){\n" + "my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = lstat(\"$dirname/$filename\");\n" + "my $mloctime= strftime(\"%%m-%%d-%%Y %%H:%%M\", localtime $mtime);\n" + , + "my $strutils_shell_escape_regex = s/([;<>\\*\\|`&\\$!#\\(\\)\\[\\]\\{\\}:'\\''\"\\ \\\\])/\\\\$1/g;\n" + "my $e_filename = $filename;\n" + "$e_filename =~ $strutils_shell_escape_regex;\n" + "if (S_ISLNK($mode) ) {\n" + "my $linkname = readlink (\"$dirname/$filename\");\n" + "$linkname =~ $strutils_shell_escape_regex;\n" + "\n" + "printf(\"R%%o %%o $uid.$gid\\n" "S$size\\n" + "d$mloctime\\n" + ":\\\"$e_filename\\\" -> \\\"$linkname\\\"\\n" + "\\n\", S_IMODE($mode), S_IFMT($mode));\n" + "} else {\n" + "printf(\"R%%o %%o $uid.$gid\\n" + "S$size\\n" + "d$mloctime\\n" + ":\\\"$e_filename\\\"\\n" + "\\n\", S_IMODE($mode), S_IFMT($mode));\n" + "}}\n" + , + "printf(\"### 200\\n\");\n" + "closedir(DIR);\n" + "} else {\n" + "printf(\"### 500\\n\");\n" + "}\n" + "exit 0\n" + "' /%s ||\n" /* ARGV[0] - path to browse */ + " echo '### 500'\n" /* do not hang if perl is to eval it */ + "elif `ls -1 /%s >/dev/null 2>&1` ; then\n" + "if `ls -Q /%s >/dev/null 2>&1`; then\n" + "LSOPT=\"-Qlan\";\n" + "ADD=0;\n" + "else\n" + "LSOPT=\"-lan\";\n" + "ADD=1;\n" + "fi\n" + "ls $LSOPT /%s 2>/dev/null | grep '^[^cbt]' | (\n" + "while read p l u g s m d y n n2 n3; do\n" + "if test \"$m\" = \"0\" ; then \n" + "s=$d; m=$y; d=$n y=$n2; n=$n3\n" + "else\n" + "n=$n\" \"$n2\" \"$n3\n" + "fi\n" + "if [ $ADD = 0 ]; then\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" + "file=`echo $n | sed -e 's#^\\(.*\\) -> \\(.*\\)#\\1\" -> \"\\2#'`\n", + "echo \"P$p $u $g\nS$s\nd$m $d $y\n:\"$file\"\n\"\n" + "else\n" + "echo \"P$p $u $g\nS$s\nd$m $d $y\n:\"$n\"\n\"\n" + "fi\n" + "done )\n" + "ls $LSOPT /%s 2>/dev/null | grep '^[cb]' | (\n" + "while read p l u g a i m d y n n2 n3; do\n" + "if test \"$a\" = \"0\" ; then \n" + "a=$m; i=$d; m=$y; d=$n y=$n2; n=$n3\n" + "else\n" + "n=$n\" \"$n2\" \"$n3\n" + "fi\n" + "if [ $ADD = 0 ]; then\n" + "echo \"P$p $u.$g\nE$a$i\nd$m $d $y\n:$n\n\"\n" + "elif `sed --version >/dev/null 2>&1` ; then\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" + "else\n" + "echo \"P$p $u $g\nS$s\nd$m $d $y\n:\"$n\"\n\"\n" + "fi\n" + "done)\n" + "echo '### 200'\n" + "else\n" + "echo '### 500'\n" + "fi\n" + , + (char *) NULL); + /* *INDENT-ON* */ + + fish_command (me, super, NONE, shell_commands, + quoted_path, quoted_path, quoted_path, quoted_path, quoted_path, quoted_path); + + g_free (shell_commands); + g_free (quoted_path); + ent = vfs_s_generate_entry (me, NULL, dir, 0); + while (1) + { + int res = vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), SUP.sockr); + if ((!res) || (res == EINTR)) + { + vfs_s_free_entry (me, ent); + me->verrno = ECONNRESET; + goto error; + } + if (logfile) + { + fputs (buffer, logfile); + fputs ("\n", logfile); + fflush (logfile); + } + if (!strncmp (buffer, "### ", 4)) + break; + if ((!buffer[0])) + { + if (ent->name) + { + vfs_s_insert_entry (me, dir, ent); + ent = vfs_s_generate_entry (me, NULL, dir, 0); + } + continue; + } + +#define ST ent->ino->st + + switch (buffer[0]) + { + case ':': + { + char *temp; + char *data_start = buffer + 1; + char *filename = data_start; + char *linkname = data_start; + char *filename_bound = filename + strlen (filename); + char *linkname_bound = filename_bound; + if (!strcmp (data_start, "\".\"") || !strcmp (data_start, "\"..\"")) + break; /* We'll do "." and ".." ourselves */ + + if (S_ISLNK (ST.st_mode)) + { + /* we expect: "escaped-name" -> "escaped-name" + // -> cannot occur in filenames, + // because it will be escaped to -\> */ + + if (*filename == '"') + ++filename; + + linkname = strstr (filename, "\" -> \""); + if (!linkname) + { + /* broken client, or smth goes wrong */ + linkname = filename_bound; + if (filename_bound > filename && *(filename_bound - 1) == '"') + --filename_bound; /* skip trailing " */ + } + else + { + filename_bound = linkname; + linkname += 6; /* strlen ("\" -> \"") */ + if (*(linkname_bound - 1) == '"') + --linkname_bound; /* skip trailing " */ + } + + ent->name = str_dup_range (filename, filename_bound); + temp = ent->name; + ent->name = strutils_shell_unescape (ent->name); + g_free (temp); + + ent->ino->linkname = str_dup_range (linkname, linkname_bound); + temp = ent->ino->linkname; + ent->ino->linkname = strutils_shell_unescape (ent->ino->linkname); + g_free (temp); + } + else + { + /* we expect: "escaped-name" */ + if (filename_bound - filename > 2) + { + /* + there is at least 2 " + and we skip them + */ + if (*filename == '"') + ++filename; + if (*(filename_bound - 1) == '"') + --filename_bound; + } + ent->name = str_dup_range (filename, filename_bound); + temp = ent->name; + ent->name = strutils_shell_unescape (ent->name); + g_free (temp); + } + break; + } + case 'S': +#ifdef HAVE_ATOLL + ST.st_size = (off_t) atoll (buffer + 1); +#else + ST.st_size = (off_t) atof (buffer + 1); +#endif + break; + case 'P': + { + size_t skipped; + vfs_parse_filemode (buffer + 1, &skipped, &ST.st_mode); + break; + } + case 'R': + { + /* + raw filemode: + we expect: Roctal-filemode octal-filetype uid.gid + */ + size_t skipped; + vfs_parse_raw_filemode (buffer + 1, &skipped, &ST.st_mode); + break; + } + case 'd': + { + vfs_split_text (buffer + 1); + if (!vfs_parse_filedate (0, &ST.st_ctime)) + break; + ST.st_atime = ST.st_mtime = ST.st_ctime; + } + break; + case 'D': + { + struct tm tim; + 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) + break; + ST.st_atime = ST.st_mtime = ST.st_ctime = mktime (&tim); + } + break; + case 'E': + { + int maj, min; + if (sscanf (buffer + 1, "%d,%d", &maj, &min) != 2) + break; +#ifdef HAVE_STRUCT_STAT_ST_RDEV + ST.st_rdev = makedev (maj, min); +#endif + } + } + } + + vfs_s_free_entry (me, ent); + reply_code = fish_decode_reply (buffer + 4, 0); + if (reply_code == COMPLETE) + { + g_free (SUP.cwdir); + SUP.cwdir = g_strdup (remote_path); + print_vfs_message (_("%s: done."), me->name); + return 0; + } + else if (reply_code == ERROR) + { + me->verrno = EACCES; + } + else + { + me->verrno = E_REMOTE; + } + + error: + print_vfs_message (_("%s: failure"), me->name); + return -1; +} + +static int +fish_file_store (struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *localname) +{ + struct vfs_s_super *super = FH_SUPER; + int n, total; + char buffer[8192]; + struct stat s; + int was_error = 0; + int h; + char *quoted_name; + + h = open (localname, O_RDONLY); + + if (h == -1) + ERRNOR (EIO, -1); + if (fstat (h, &s) < 0) + { + close (h); + ERRNOR (EIO, -1); + } + + /* First, try this as stor: + * + * ( head -c number ) | ( cat > file; cat >/dev/null ) + * + * If `head' is not present on the remote system, `dd' will be used. + * Unfortunately, we cannot trust most non-GNU `head' implementations + * even if `-c' options is supported. Therefore, we separate GNU head + * (and other modern heads?) using `-q' and `-' . This causes another + * implementations to fail (because of "incorrect options"). + * + * Fallback is: + * + * rest= + * while [ $rest -gt 0 ] + * do + * cnt=`expr \( $rest + 255 \) / 256` + * n=`dd bs=256 count=$cnt | tee -a | wc -c` + * rest=`expr $rest - $n` + * done + * + * `dd' was not designed for full filling of input buffers, + * and does not report exact number of bytes (not blocks). + * Therefore a more complex shell script is needed. + * + * On some systems non-GNU head writes "Usage:" error report to stdout + * instead of stderr. It makes impossible the use of "head || dd" + * algorithm for file appending case, therefore just "dd" is used for it. + */ + + quoted_name = strutils_shell_escape (name); + print_vfs_message (_("fish: store %s: sending command..."), quoted_name); + + /* FIXME: File size is limited to ULONG_MAX */ + if (!fh->u.fish.append) + /* *INDENT-OFF* */ + n = fish_command (me, super, WAIT_REPLY, + "#STOR %lu /%s\n" + "echo '### 001'\n" + "file=/%s\n" + "res=`exec 3>&1\n" + "(\n" + "head -c %lu -q - || echo DD >&3\n" + ") 2>/dev/null | (\n" + "cat > $file\n" + "cat > /dev/null\n" + ")`; [ \"$res\" = DD ] && {\n" + "> \"$file\"\n" + "rest=%lu\n" + "while [ $rest -gt 0 ]\n" + "do\n" + " cnt=`expr \\( $rest + 255 \\) / 256`\n" + " n=`dd bs=256 count=$cnt | tee -a \"$file\" | wc -c`\n" + " rest=`expr $rest - $n`\n" + "done\n" + "}; echo '### 200'\n", + (unsigned long) s.st_size, quoted_name, + quoted_name, (unsigned long) s.st_size, (unsigned long) s.st_size); + /* *INDENT-ON* */ + else + /* *INDENT-OFF* */ + n = fish_command (me, super, WAIT_REPLY, + "#STOR %lu /%s\n" + "echo '### 001'\n" + "{\n" + "file=/%s\n" + "rest=%lu\n" + "while [ $rest -gt 0 ]\n" + "do\n" + " cnt=`expr \\( $rest + 255 \\) / 256`\n" + " n=`dd bs=256 count=$cnt | tee -a $file | wc -c`\n" + " rest=`expr $rest - $n`\n" + "done\n" + "}; echo '### 200'\n", + (unsigned long) s.st_size, quoted_name, + quoted_name, (unsigned long) s.st_size); + /* *INDENT-ON* */ + + if (n != PRELIM) + { + close (h); + ERRNOR (E_REMOTE, -1); + } + + total = 0; + + while (1) + { + int t; + while ((n = read (h, buffer, sizeof (buffer))) < 0) + { + if ((errno == EINTR) && tty_got_interrupt ()) + continue; + print_vfs_message (_("fish: Local read failed, sending zeros")); + close (h); + h = open ("/dev/zero", O_RDONLY); + } + if (n == 0) + break; + if ((t = write (SUP.sockw, buffer, n)) != n) + { + if (t == -1) + { + me->verrno = errno; + } + else + { + me->verrno = EIO; + } + goto error_return; + } + tty_disable_interrupt_key (); + total += n; + print_vfs_message (_("fish: storing %s %d (%lu)"), + was_error ? _("zeros") : _("file"), total, (unsigned long) s.st_size); + } + close (h); + g_free (quoted_name); + if ((fish_get_reply (me, SUP.sockr, NULL, 0) != COMPLETE) || was_error) + ERRNOR (E_REMOTE, -1); + return 0; + error_return: + close (h); + fish_get_reply (me, SUP.sockr, NULL, 0); + g_free (quoted_name); + return -1; +} + +static int +fish_linear_start (struct vfs_class *me, struct vfs_s_fh *fh, off_t offset) +{ + char *name; + char *quoted_name; + if (offset) + ERRNOR (E_NOTSUPP, 0); + name = vfs_s_fullpath (me, fh->ino); + if (name == NULL) + return 0; + quoted_name = strutils_shell_escape (name); + g_free (name); + fh->u.fish.append = 0; + + /* + * Check whether the remote file is readable by using `dd' to copy + * a single byte from the remote file to /dev/null. If `dd' completes + * with exit status of 0 use `cat' to send the file contents to the + * standard output (i.e. over the network). + */ + /* *INDENT-OFF* */ + offset = fish_command (me, FH_SUPER, WANT_STRING, + "#RETR /%s\n" + "if dd if=/%s of=/dev/null bs=1 count=1 2>/dev/null ;\n" + "then\n" + "ls -ln /%s 2>/dev/null | (\n" + "read p l u g s r\n" + "echo $s\n" + ")\n" + "echo '### 100'\n" + "cat /%s\n" + "echo '### 200'\n" + "else\n" + "echo '### 500'\n" + "fi\n", + quoted_name, quoted_name, quoted_name, quoted_name); + /* *INDENT-ON* */ + g_free (quoted_name); + if (offset != PRELIM) + ERRNOR (E_REMOTE, 0); + fh->linear = LS_LINEAR_OPEN; + fh->u.fish.got = 0; + errno = 0; +#if SIZEOF_OFF_T == SIZEOF_LONG + fh->u.fish.total = strtol (reply_str, NULL, 10); +#else + fh->u.fish.total = strtoll (reply_str, NULL, 10); +#endif + if (errno != 0) + ERRNOR (E_REMOTE, 0); + return 1; +} + +static void +fish_linear_abort (struct vfs_class *me, struct vfs_s_fh *fh) +{ + struct vfs_s_super *super = FH_SUPER; + char buffer[8192]; + int n; + + print_vfs_message (_("Aborting transfer...")); + do + { + n = MIN (8192, fh->u.fish.total - fh->u.fish.got); + if (n) + { + if ((n = read (SUP.sockr, buffer, n)) < 0) + return; + fh->u.fish.got += n; + } + } + while (n); + + if (fish_get_reply (me, SUP.sockr, NULL, 0) != COMPLETE) + print_vfs_message (_("Error reported after abort.")); + else + print_vfs_message (_("Aborted transfer would be successful.")); +} + +static int +fish_linear_read (struct vfs_class *me, struct vfs_s_fh *fh, void *buf, int len) +{ + struct vfs_s_super *super = FH_SUPER; + int n = 0; + len = MIN (fh->u.fish.total - fh->u.fish.got, len); + tty_disable_interrupt_key (); + while (len && ((n = read (SUP.sockr, buf, len)) < 0)) + { + if ((errno == EINTR) && !tty_got_interrupt ()) + continue; + break; + } + tty_enable_interrupt_key (); + + if (n > 0) + fh->u.fish.got += n; + if (n < 0) + fish_linear_abort (me, fh); + if ((!n) && ((fish_get_reply (me, SUP.sockr, NULL, 0) != COMPLETE))) + ERRNOR (E_REMOTE, -1); + ERRNOR (errno, n); +} + +static void +fish_linear_close (struct vfs_class *me, struct vfs_s_fh *fh) +{ + if (fh->u.fish.total != fh->u.fish.got) + fish_linear_abort (me, fh); +} + +static int +fish_ctl (void *fh, int ctlop, void *arg) +{ + (void) arg; + (void) fh; + (void) ctlop; + return 0; +#if 0 + switch (ctlop) + { + case VFS_CTL_IS_NOTREADY: + { + int v; + + if (!FH->linear) + vfs_die ("You may not do this"); + if (FH->linear == LS_LINEAR_CLOSED || FH->linear == LS_LINEAR_PREOPEN) + return 0; + + v = vfs_s_select_on_two (FH_SUPER->u.fish.sockr, 0); + if (((v < 0) && (errno == EINTR)) || v == 0) + return 1; + return 0; + } + default: + return 0; + } +#endif +} + +static int +fish_send_command (struct vfs_class *me, struct vfs_s_super *super, const char *cmd, int flags) +{ + int r; + + r = fish_command (me, super, WAIT_REPLY, "%s", cmd); + vfs_stamp_create (&vfs_fish_ops, super); + if (r != COMPLETE) + ERRNOR (E_REMOTE, -1); + if (flags & OPT_FLUSH) + vfs_s_invalidate (me, super); + return 0; +} + +#define PREFIX \ + char buf[BUF_LARGE]; \ + const char *crpath; \ + char *rpath, *mpath = g_strdup (path); \ + struct vfs_s_super *super; \ + if (!(crpath = vfs_s_get_path_mangle (me, mpath, &super, 0))) \ + { \ + g_free (mpath); \ + return -1; \ + } \ + rpath = strutils_shell_escape(crpath); \ + g_free (mpath); + +#define POSTFIX(flags) \ + g_free (rpath); \ + return fish_send_command(me, super, buf, flags); + +static int +fish_chmod (struct vfs_class *me, const char *path, int mode) +{ + PREFIX + /* *INDENT-OFF* */ + g_snprintf (buf, sizeof (buf), + "#CHMOD %4.4o /%s\n" + "if chmod %4.4o /%s 2>/dev/null; then\n" + "echo '### 000'\n" + "else\n" + "echo '### 500'\n" + "fi\n", + mode & 07777, rpath, mode & 07777, rpath); + /* *INDENT-ON* */ + POSTFIX (OPT_FLUSH); +} + +#define FISH_OP(name, string) \ +static int fish_##name (struct vfs_class *me, const char *path1, const char *path2) \ +{ \ + char buf[BUF_LARGE]; \ + const char *crpath1, *crpath2; \ + char *rpath1, *rpath2, *mpath1, *mpath2; \ + struct vfs_s_super *super1, *super2; \ + if (!(crpath1 = vfs_s_get_path_mangle (me, mpath1 = g_strdup(path1), &super1, 0))) \ + { \ + g_free (mpath1); \ + return -1; \ + } \ + if (!(crpath2 = vfs_s_get_path_mangle (me, mpath2 = g_strdup(path2), &super2, 0))) \ + { \ + g_free (mpath1); \ + g_free (mpath2); \ + return -1; \ + } \ + rpath1 = strutils_shell_escape (crpath1); \ + g_free (mpath1); \ + rpath2 = strutils_shell_escape (crpath2); \ + g_free (mpath2); \ + g_snprintf (buf, sizeof(buf), string "\n", rpath1, rpath2, rpath1, rpath2); \ + g_free (rpath1); \ + g_free (rpath2); \ + return fish_send_command(me, super2, buf, OPT_FLUSH); \ +} + +/* *INDENT-OFF* */ +FISH_OP (rename, + "#RENAME /%s /%s\n" + "if mv /%s /%s 2>/dev/null; then\n" + "echo '### 000'\n" + "else\n" + "echo '### 500'\n" + "fi\n") + +FISH_OP (link, + "#LINK /%s /%s\n" + "if ln /%s /%s 2>/dev/null; then\n" + "echo '### 000'\n" + "else\n" + "echo '### 500'\n" + "fi\n") +/* *INDENT-ON* */ + +static int +fish_symlink (struct vfs_class *me, const char *setto, const char *path) +{ + char *qsetto; + PREFIX qsetto = strutils_shell_escape (setto); + /* *INDENT-OFF* */ + g_snprintf (buf, sizeof (buf), + "#SYMLINK %s /%s\n" + "if ln -s %s /%s 2>/dev/null; then\n" + "echo '### 000'\n" + "else\n" + "echo '### 500'\n" + "fi\n", + qsetto, rpath, qsetto, rpath); + /* *INDENT-ON* */ + g_free (qsetto); + POSTFIX (OPT_FLUSH); +} + +static int +fish_chown (struct vfs_class *me, const char *path, int owner, int group) +{ + char *sowner, *sgroup; + struct passwd *pw; + struct group *gr; + + if ((pw = getpwuid (owner)) == NULL) + return 0; + + if ((gr = getgrgid (group)) == NULL) + return 0; + + sowner = pw->pw_name; + sgroup = gr->gr_name; + { + PREFIX + /* *INDENT-OFF* */ + g_snprintf (buf, sizeof (buf), + "#CHOWN %s:%s /%s\n" + "if chown %s:%s /%s 2>/dev/null; then\n" + "echo '### 000'\n" + "else\n" + "echo '### 500'\n" + "fi\n", + sowner, sgroup, rpath, sowner, sgroup, rpath); + /* *INDENT-ON* */ + fish_send_command (me, super, buf, OPT_FLUSH); + /* FIXME: what should we report if chgrp succeeds but chown fails? */ + /* fish_send_command(me, super, buf, OPT_FLUSH); */ + POSTFIX (OPT_FLUSH)} +} + +static int +fish_unlink (struct vfs_class *me, const char *path) +{ + PREFIX + + /* *INDENT-OFF* */ + g_snprintf (buf, sizeof (buf), + "#DELE /%s\n" + "if rm -f /%s 2>/dev/null; then\n" + "echo '### 000'\n" + "else\n" + "echo '### 500'\n" + "fi\n", + rpath, rpath); + /* *INDENT-ON* */ + + POSTFIX (OPT_FLUSH); +} + +static int +fish_exists (struct vfs_class *me, const char *path) +{ + PREFIX + + /* *INDENT-OFF* */ + g_snprintf (buf, sizeof (buf), + "#ISEXISTS /%s\n" + "ls -l /%s >/dev/null 2>/dev/null\n" + "echo '### '$?\n", + rpath, rpath); + /* *INDENT-ON* */ + + g_free (rpath); + + if (fish_send_command (me, super, buf, OPT_FLUSH) == 0) + return 1; + + return 0; +} + + +static int +fish_mkdir (struct vfs_class *me, const char *path, mode_t mode) +{ + int ret_code; + + PREFIX (void) mode; + + /* *INDENT-OFF* */ + g_snprintf (buf, sizeof (buf), + "#MKD /%s\n" + "if mkdir /%s 2>/dev/null; then\n" + "echo '### 000'\n" + "else\n" + "echo '### 500'\n" + "fi\n", + rpath, rpath); + /* *INDENT-ON* */ + + g_free (rpath); + ret_code = fish_send_command (me, super, buf, OPT_FLUSH); + + if (ret_code != 0) + return ret_code; + + if (!fish_exists (me, path)) + { + ERRNOR (EACCES, -1); + } + return 0; +} + +static int +fish_rmdir (struct vfs_class *me, const char *path) +{ + PREFIX + /* *INDENT-OFF* */ + g_snprintf (buf, sizeof (buf), + "#RMD /%s\n" + "if rmdir /%s 2>/dev/null; then\n" + "echo '### 000'\n" + "else\n" + "echo '### 500'\n" + "fi\n", + rpath, rpath); + /* *INDENT-ON* */ + POSTFIX (OPT_FLUSH); +} + +static int +fish_fh_open (struct vfs_class *me, struct vfs_s_fh *fh, int flags, int mode) +{ + (void) mode; + + fh->u.fish.append = 0; + /* File will be written only, so no need to retrieve it */ + if (((flags & O_WRONLY) == O_WRONLY) && !(flags & (O_RDONLY | O_RDWR))) + { + fh->u.fish.append = flags & O_APPEND; + if (!fh->ino->localname) + { + int tmp_handle = vfs_mkstemps (&fh->ino->localname, me->name, + fh->ino->ent->name); + if (tmp_handle == -1) + return -1; + close (tmp_handle); + } + return 0; + } + if (!fh->ino->localname) + if (vfs_s_retrieve_file (me, fh->ino) == -1) + return -1; + if (!fh->ino->localname) + vfs_die ("retrieve_file failed to fill in localname"); + return 0; +} + +static void +fish_fill_names (struct vfs_class *me, fill_names_f func) +{ + struct vfs_s_super *super = MEDATA->supers; + char *name; + + char gbuf[10]; + + while (super) + { + const char *flags = ""; + switch (SUP.flags) + { + case FISH_FLAG_RSH: + flags = ":r"; + break; + case FISH_FLAG_COMPRESSED: + flags = ":C"; + break; + default: + if (SUP.flags > FISH_FLAG_RSH) + { + break; + g_snprintf (gbuf, sizeof (gbuf), ":%d", SUP.flags); + flags = gbuf; + } + break; + } + + name = g_strconcat ("/#sh:", SUP.user, "@", SUP.host, flags, "/", SUP.cwdir, (char *) NULL); + (*func) (name); + g_free (name); + super = super->next; + } +} + +static void * +fish_open (struct vfs_class *me, const char *file, int flags, int mode) +{ + /* + sorry, i've places hack here + cause fish don't able to open files with O_EXCL flag + */ + flags &= ~O_EXCL; + return vfs_s_open (me, file, flags, mode); +} + + +void +init_fish (void) +{ + static struct vfs_s_subclass fish_subclass; + + tcp_init (); + + fish_subclass.flags = VFS_S_REMOTE; + fish_subclass.archive_same = fish_archive_same; + fish_subclass.open_archive = fish_open_archive; + fish_subclass.free_archive = fish_free_archive; + fish_subclass.fh_open = fish_fh_open; + fish_subclass.dir_load = fish_dir_load; + fish_subclass.file_store = fish_file_store; + fish_subclass.linear_start = fish_linear_start; + fish_subclass.linear_read = fish_linear_read; + fish_subclass.linear_close = fish_linear_close; + + vfs_s_init_class (&vfs_fish_ops, &fish_subclass); + vfs_fish_ops.name = "fish"; + vfs_fish_ops.prefix = "sh:"; + vfs_fish_ops.fill_names = fish_fill_names; + vfs_fish_ops.chmod = fish_chmod; + vfs_fish_ops.chown = fish_chown; + vfs_fish_ops.open = fish_open; + vfs_fish_ops.symlink = fish_symlink; + vfs_fish_ops.link = fish_link; + vfs_fish_ops.unlink = fish_unlink; + vfs_fish_ops.rename = fish_rename; + vfs_fish_ops.mkdir = fish_mkdir; + vfs_fish_ops.rmdir = fish_rmdir; + vfs_fish_ops.ctl = fish_ctl; + vfs_register_class (&vfs_fish_ops); +} diff --git a/lib/vfs/mc-vfs/vfs.c b/lib/vfs/mc-vfs/vfs.c index 4f71ce63..0ed1bdbd 100644 --- a/lib/vfs/mc-vfs/vfs.c +++ b/lib/vfs/mc-vfs/vfs.c @@ -1,16 +1,16 @@ /* Virtual File System switch code Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. - + Written by: 1995 Miguel de Icaza - 1995 Jakub Jelinek - 1998 Pavel Machek - + 1995 Jakub Jelinek + 1998 Pavel Machek + This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -38,13 +38,13 @@ #include #include -#include /* For atol() */ +#include /* For atol() */ #include #include #include #include #include -#include /* is_digit() */ +#include /* is_digit() */ #include #include #include @@ -53,8 +53,8 @@ #include "lib/global.h" #include "lib/strutil.h" -#include "src/wtools.h" /* message() */ -#include "src/main.h" /* print_vfs_message */ +#include "src/wtools.h" /* message() */ +#include "src/main.h" /* print_vfs_message */ #include "utilvfs.h" #include "gc.h" @@ -75,13 +75,15 @@ static struct vfs_class *current_vfs; static char *current_dir; -struct vfs_openfile { +struct vfs_openfile +{ int handle; struct vfs_class *vclass; void *fsinfo; }; -struct vfs_dirinfo{ +struct vfs_dirinfo +{ DIR *info; GIConv converter; }; @@ -95,9 +97,9 @@ static struct vfs_class *localfs_class; static GString *vfs_str_buffer; static const char *supported_encodings[] = { - "UTF8", + "UTF8", "UTF-8", - "BIG5", + "BIG5", "ASCII", "ISO8859", "ISO-8859", @@ -121,11 +123,14 @@ vfs_new_handle (struct vfs_class *vclass, void *fsinfo) /* Allocate the first free handle */ h->handle = vfs_free_handle_list; - if (h->handle == -1) { + if (h->handle == -1) + { /* No free allocated handles, allocate one */ h->handle = vfs_openfiles->len; g_ptr_array_add (vfs_openfiles, h); - } else { + } + else + { vfs_free_handle_list = (long) g_ptr_array_index (vfs_openfiles, vfs_free_handle_list); g_ptr_array_index (vfs_openfiles, h->handle) = h; } @@ -140,14 +145,12 @@ vfs_op (int handle) { struct vfs_openfile *h; - if (handle < VFS_FIRST_HANDLE || - (guint)(handle - VFS_FIRST_HANDLE) >= vfs_openfiles->len) + if (handle < VFS_FIRST_HANDLE || (guint) (handle - VFS_FIRST_HANDLE) >= vfs_openfiles->len) return NULL; - h = (struct vfs_openfile *) g_ptr_array_index ( - vfs_openfiles, handle - VFS_FIRST_HANDLE); + h = (struct vfs_openfile *) g_ptr_array_index (vfs_openfiles, handle - VFS_FIRST_HANDLE); if (!h) - return NULL; + return NULL; g_assert (h->handle == handle); @@ -160,14 +163,12 @@ vfs_info (int handle) { struct vfs_openfile *h; - if (handle < VFS_FIRST_HANDLE || - (guint)(handle - VFS_FIRST_HANDLE) >= vfs_openfiles->len) + if (handle < VFS_FIRST_HANDLE || (guint) (handle - VFS_FIRST_HANDLE) >= vfs_openfiles->len) return NULL; - h = (struct vfs_openfile *) g_ptr_array_index ( - vfs_openfiles, handle - VFS_FIRST_HANDLE); + h = (struct vfs_openfile *) g_ptr_array_index (vfs_openfiles, handle - VFS_FIRST_HANDLE); if (!h) - return NULL; + return NULL; g_assert (h->handle == handle); @@ -180,13 +181,14 @@ vfs_free_handle (int handle) { const int idx = handle - VFS_FIRST_HANDLE; - if (handle >= VFS_FIRST_HANDLE && (guint) idx < vfs_openfiles->len) { - struct vfs_openfile *h; + if (handle >= VFS_FIRST_HANDLE && (guint) idx < vfs_openfiles->len) + { + 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; + 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; } } @@ -195,9 +197,9 @@ static struct vfs_class *vfs_list; int vfs_register_class (struct vfs_class *vfs) { - if (vfs->init) /* vfs has own initialization function */ - if (!(*vfs->init)(vfs)) /* but it failed */ - return 0; + if (vfs->init) /* vfs has own initialization function */ + if (!(*vfs->init) (vfs)) /* but it failed */ + return 0; vfs->next = vfs_list; vfs_list = vfs; @@ -212,15 +214,16 @@ vfs_prefix_to_class (char *prefix) struct vfs_class *vfs; /* Avoid last class (localfs) that would accept any prefix */ - for (vfs = vfs_list; vfs->next; vfs = vfs->next) { - if (vfs->which) { - if ((*vfs->which) (vfs, prefix) == -1) - continue; - return vfs; - } - if (vfs->prefix - && !strncmp (prefix, vfs->prefix, strlen (vfs->prefix))) - return vfs; + for (vfs = vfs_list; vfs->next; vfs = vfs->next) + { + if (vfs->which) + { + if ((*vfs->which) (vfs, prefix) == -1) + continue; + return vfs; + } + if (vfs->prefix && !strncmp (prefix, vfs->prefix, strlen (vfs->prefix))) + return vfs; } return NULL; } @@ -237,25 +240,27 @@ vfs_strip_suffix_from_filename (const char *filename) char *p; if (!filename) - vfs_die ("vfs_strip_suffix_from_path got NULL: impossible"); + vfs_die ("vfs_strip_suffix_from_path got NULL: impossible"); p = g_strdup (filename); if (!(semi = strrchr (p, '#'))) - return p; + return p; /* Avoid last class (localfs) that would accept any prefix */ - for (vfs = vfs_list; vfs->next; vfs = vfs->next) { - if (vfs->which) { - if ((*vfs->which) (vfs, semi + 1) == -1) - continue; - *semi = '\0'; /* Found valid suffix */ - return p; - } - if (vfs->prefix - && !strncmp (semi + 1, vfs->prefix, strlen (vfs->prefix))) { - *semi = '\0'; /* Found valid suffix */ - return p; - } + for (vfs = vfs_list; vfs->next; vfs = vfs->next) + { + if (vfs->which) + { + if ((*vfs->which) (vfs, semi + 1) == -1) + continue; + *semi = '\0'; /* Found valid suffix */ + return p; + } + if (vfs->prefix && !strncmp (semi + 1, vfs->prefix, strlen (vfs->prefix))) + { + *semi = '\0'; /* Found valid suffix */ + return p; + } } return p; } @@ -265,7 +270,7 @@ path_magic (const char *path) { struct stat buf; - if (!stat(path, &buf)) + if (!stat (path, &buf)) return 0; return 1; @@ -290,35 +295,36 @@ vfs_split (char *path, char **inpath, char **op) struct vfs_class *ret; if (!path) - vfs_die("Cannot split NULL"); - + vfs_die ("Cannot split NULL"); + semi = strrchr (path, '#'); - if (!semi || !path_magic(path)) - return NULL; + if (!semi || !path_magic (path)) + return NULL; slash = strchr (semi, PATH_SEP); *semi = 0; if (op) - *op = NULL; + *op = NULL; if (inpath) - *inpath = NULL; + *inpath = NULL; if (slash) - *slash = 0; - - if ((ret = vfs_prefix_to_class (semi+1))){ - if (op) - *op = semi + 1; - if (inpath) - *inpath = slash ? slash + 1 : NULL; - return ret; + *slash = 0; + + if ((ret = vfs_prefix_to_class (semi + 1))) + { + if (op) + *op = semi + 1; + if (inpath) + *inpath = slash ? slash + 1 : NULL; + return ret; } if (slash) - *slash = PATH_SEP; + *slash = PATH_SEP; ret = vfs_split (path, inpath, op); *semi = '#'; return ret; @@ -331,23 +337,23 @@ _vfs_get_class (char *path) char *slash; struct vfs_class *ret; - g_return_val_if_fail(path, NULL); + g_return_val_if_fail (path, NULL); semi = strrchr (path, '#'); if (!semi || !path_magic (path)) - return NULL; - + return NULL; + slash = strchr (semi, PATH_SEP); *semi = 0; if (slash) - *slash = 0; - - ret = vfs_prefix_to_class (semi+1); + *slash = 0; + + ret = vfs_prefix_to_class (semi + 1); if (slash) - *slash = PATH_SEP; + *slash = PATH_SEP; if (!ret) - ret = _vfs_get_class (path); + ret = _vfs_get_class (path); *semi = '#'; return ret; @@ -363,7 +369,7 @@ vfs_get_class (const char *pathname) g_free (path); if (!vfs) - vfs = localfs_class; + vfs = localfs_class; return vfs; } @@ -375,20 +381,23 @@ vfs_get_encoding (const char *path) char *work; char *semi; char *slash; - + work = g_strdup (path); semi = g_strrstr (work, "#enc:"); - - if (semi != NULL) { - semi+= 5 * sizeof (char); + + if (semi != NULL) + { + semi += 5 * sizeof (char); slash = strchr (semi, PATH_SEP); if (slash != NULL) slash[0] = '\0'; - - g_strlcpy (result, semi, sizeof(result)); + + g_strlcpy (result, semi, sizeof (result)); g_free (work); return result; - } else { + } + else + { g_free (work); return NULL; } @@ -396,16 +405,18 @@ vfs_get_encoding (const char *path) /* return if encoding can by used in vfs (is ascci full compactible) */ /* contains only a few encoding now */ -static int -vfs_supported_enconding (const char *encoding) { +static int +vfs_supported_enconding (const char *encoding) +{ int t; int result = 0; - - for (t = 0; supported_encodings[t] != NULL; t++) { - result+= (g_ascii_strncasecmp (encoding, supported_encodings[t], - strlen (supported_encodings[t])) == 0); + + for (t = 0; supported_encodings[t] != NULL; t++) + { + result += (g_ascii_strncasecmp (encoding, supported_encodings[t], + strlen (supported_encodings[t])) == 0); } - + return result; } @@ -416,10 +427,9 @@ vfs_supported_enconding (const char *encoding) { * defcnv - convertor, that is used as default, when path does not contain any * #enc: subtring * buffer - used to store result of translation - */ + */ static estr_t -_vfs_translate_path (const char *path, int size, - GIConv defcnv, GString *buffer) +_vfs_translate_path (const char *path, int size, GIConv defcnv, GString * buffer) { const char *semi; const char *ps; @@ -429,60 +439,73 @@ _vfs_translate_path (const char *path, int size, GIConv coder; int ms; - if (size == 0) return 0; - size = ( size > 0) ? size : (signed int)strlen (path); + if (size == 0) + return 0; + size = (size > 0) ? size : (signed int) strlen (path); /* try found #end: */ semi = g_strrstr_len (path, size, "#enc:"); - if (semi != NULL) { + if (semi != NULL) + { /* first must be translated part before #enc: */ ms = semi - path; /* remove '/' before #enc */ 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); if (state != ESTR_SUCCESS) - return state; + return state; /* now can be translated part after #enc: */ - semi+= 5; + semi += 5; slash = strchr (semi, PATH_SEP); /* 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 = min ((unsigned int) ms, sizeof (encoding) - 1); /* 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); encoding[ms] = '\0'; - switch (vfs_supported_enconding (encoding)) { - case 1: - coder = str_crt_conv_to (encoding); - if (coder != INVALID_CONV) { - if (slash != NULL) { - state = str_vfs_convert_to (coder, slash, - path + size - slash, buffer); - } else if (buffer->str[0] == '\0') { - /* exmaple "/#enc:utf-8" */ - g_string_append_c(buffer, PATH_SEP); - } - str_close_conv (coder); - return state; - } else { - errno = EINVAL; - return ESTR_FAILURE; + switch (vfs_supported_enconding (encoding)) + { + case 1: + coder = str_crt_conv_to (encoding); + if (coder != INVALID_CONV) + { + if (slash != NULL) + { + state = str_vfs_convert_to (coder, slash, path + size - slash, buffer); + } + else if (buffer->str[0] == '\0') + { + /* exmaple "/#enc:utf-8" */ + g_string_append_c (buffer, PATH_SEP); } - break; - default: + str_close_conv (coder); + return state; + } + else + { errno = EINVAL; return ESTR_FAILURE; + } + break; + default: + errno = EINVAL; + return ESTR_FAILURE; } - } else { + } + else + { /* path can be translated whole at once */ state = str_vfs_convert_to (defcnv, path, size, buffer); return state; @@ -492,21 +515,21 @@ _vfs_translate_path (const char *path, int size, } char * -vfs_translate_path (const char *path) +vfs_translate_path (const char *path) { estr_t state; - g_string_set_size(vfs_str_buffer,0); + g_string_set_size (vfs_str_buffer, 0); state = _vfs_translate_path (path, -1, str_cnv_from_term, vfs_str_buffer); /* - strict version - return (state == 0) ? vfs_str_buffer->data : NULL; - */ + strict version + return (state == 0) ? vfs_str_buffer->data : NULL; + */ return (state != ESTR_FAILURE) ? vfs_str_buffer->str : NULL; } char * -vfs_translate_path_n (const char *path) +vfs_translate_path_n (const char *path) { char *result; @@ -515,7 +538,7 @@ vfs_translate_path_n (const char *path) } char * -vfs_canon_and_translate (const char *path) +vfs_canon_and_translate (const char *path) { char *canon; char *result; @@ -531,44 +554,51 @@ vfs_canon_and_translate (const char *path) static int ferrno (struct vfs_class *vfs) { - return vfs->ferrno ? (*vfs->ferrno)(vfs) : E_UNKNOWN; + return vfs->ferrno ? (*vfs->ferrno) (vfs) : E_UNKNOWN; /* Hope that error message is obscure enough ;-) */ } int mc_open (const char *filename, int flags, ...) { - int mode; + int mode; void *info; va_list ap; char *file = vfs_canon_and_translate (filename); - if (file != NULL) { - struct vfs_class *vfs = vfs_get_class (file); - - /* Get the mode flag */ - if (flags & O_CREAT) { - va_start (ap, flags); - mode = va_arg (ap, int); - va_end (ap); - } else - mode = 0; - - if (!vfs->open) { - g_free (file); - errno = -EOPNOTSUPP; - return -1; - } + if (file != NULL) + { + struct vfs_class *vfs = vfs_get_class (file); + + /* Get the mode flag */ + if (flags & O_CREAT) + { + va_start (ap, flags); + mode = va_arg (ap, int); + va_end (ap); + } + else + mode = 0; + + if (!vfs->open) + { + g_free (file); + errno = -EOPNOTSUPP; + return -1; + } - info = (*vfs->open) (vfs, file, flags, mode); /* open must be supported */ - g_free (file); - if (!info){ - errno = ferrno (vfs); - return -1; - } + info = (*vfs->open) (vfs, file, flags, mode); /* open must be supported */ + g_free (file); + if (!info) + { + errno = ferrno (vfs); + return -1; + } - return vfs_new_handle (vfs, info); - } else return -1; + return vfs_new_handle (vfs, info); + } + else + return -1; } @@ -594,39 +624,39 @@ int mc_##name inarg \ MC_NAMEOP (chmod, (const char *path, mode_t mode), (vfs, mpath, mode)) MC_NAMEOP (chown, (const char *path, uid_t owner, gid_t group), (vfs, mpath, owner, group)) -MC_NAMEOP (utime, (const char *path, struct utimbuf *times), (vfs, mpath, times)) +MC_NAMEOP (utime, (const char *path, struct utimbuf * times), (vfs, mpath, times)) MC_NAMEOP (readlink, (const char *path, char *buf, int bufsiz), (vfs, mpath, buf, bufsiz)) MC_NAMEOP (unlink, (const char *path), (vfs, mpath)) MC_NAMEOP (mkdir, (const char *path, mode_t mode), (vfs, mpath, mode)) MC_NAMEOP (rmdir, (const char *path), (vfs, mpath)) 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) -{ - struct vfs_class *vfs; - int result; + int mc_symlink (const char *name1, const char *path) +{ + struct vfs_class *vfs; + int result; char *mpath; char *lpath; char *tmp; - - mpath = vfs_canon_and_translate (path); - if (mpath != NULL) { + + mpath = vfs_canon_and_translate (path); + if (mpath != NULL) + { tmp = g_strdup (name1); lpath = vfs_translate_path_n (tmp); g_free (tmp); - - if (lpath != NULL) { - vfs = vfs_get_class (mpath); + + if (lpath != NULL) + { + vfs = vfs_get_class (mpath); result = vfs->symlink ? (*vfs->symlink) (vfs, lpath, mpath) : -1; g_free (lpath); g_free (mpath); - if (result == -1) - errno = vfs->symlink ? ferrno (vfs) : E_NOTSUPP; - return result; - } - g_free (mpath); + if (result == -1) + errno = vfs->symlink ? ferrno (vfs) : E_NOTSUPP; + return result; + } + g_free (mpath); } return -1; } @@ -647,10 +677,8 @@ ssize_t mc_##name inarg \ return result; \ } -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 (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)) #define MC_RENAMEOP(name) \ int mc_##name (const char *fname1, const char *fname2) \ { \ @@ -680,20 +708,16 @@ int mc_##name (const char *fname1, const char *fname2) \ } \ } else return -1; \ } - -MC_RENAMEOP (link) -MC_RENAMEOP (rename) - - -int -mc_ctl (int handle, int ctlop, void *arg) + MC_RENAMEOP (link) MC_RENAMEOP (rename) + int + mc_ctl (int handle, int ctlop, void *arg) { struct vfs_class *vfs = vfs_op (handle); if (vfs == NULL) return 0; - return vfs->ctl ? (*vfs->ctl)(vfs_info (handle), ctlop, arg) : 0; + return vfs->ctl ? (*vfs->ctl) (vfs_info (handle), ctlop, arg) : 0; } int @@ -704,15 +728,18 @@ mc_setctl (const char *path, int ctlop, void *arg) char *mpath; if (!path) - 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); - if (mpath != NULL) { - vfs = vfs_get_class (mpath); - result = vfs->setctl ? (*vfs->setctl)(vfs, mpath, ctlop, arg) : 0; - g_free (mpath); - return result; - } else return -1; + if (mpath != NULL) + { + vfs = vfs_get_class (mpath); + result = vfs->setctl ? (*vfs->setctl) (vfs, mpath, ctlop, arg) : 0; + g_free (mpath); + return result; + } + else + return -1; } int @@ -722,29 +749,29 @@ mc_close (int handle) int result; if (handle == -1 || !vfs_info (handle)) - return -1; - + return -1; + vfs = vfs_op (handle); if (vfs == NULL) - return -1; + return -1; if (handle < 3) - return close (handle); + return close (handle); if (!vfs->close) vfs_die ("VFS must support close.\n"); - result = (*vfs->close)(vfs_info (handle)); + result = (*vfs->close) (vfs_info (handle)); vfs_free_handle (handle); if (result == -1) - errno = ferrno (vfs); - + errno = ferrno (vfs); + return result; } DIR * mc_opendir (const char *dirname) { - int handle, *handlep; + int handle, *handlep; void *info; struct vfs_class *vfs; char *canon; @@ -755,12 +782,14 @@ mc_opendir (const char *dirname) canon = vfs_canon (dirname); dname = vfs_translate_path_n (canon); - if (dname != NULL) { + if (dname != NULL) + { vfs = vfs_get_class (dname); - info = vfs->opendir ? (*vfs->opendir)(vfs, dname) : NULL; + info = vfs->opendir ? (*vfs->opendir) (vfs, dname) : NULL; g_free (dname); - if (info == NULL) { + if (info == NULL) + { errno = vfs->opendir ? ferrno (vfs) : E_NOTSUPP; g_free (canon); return NULL; @@ -771,25 +800,27 @@ mc_opendir (const char *dirname) encoding = vfs_get_encoding (canon); g_free (canon); - dirinfo->converter = (encoding != NULL) ? str_crt_conv_from (encoding) : - str_cnv_from_term; - if (dirinfo->converter == INVALID_CONV) dirinfo->converter =str_cnv_from_term; + dirinfo->converter = (encoding != NULL) ? str_crt_conv_from (encoding) : str_cnv_from_term; + if (dirinfo->converter == INVALID_CONV) + dirinfo->converter = str_cnv_from_term; handle = vfs_new_handle (vfs, dirinfo); handlep = g_new (int, 1); *handlep = handle; return (DIR *) handlep; - } else { + } + else + { g_free (canon); return NULL; } } -static struct dirent * mc_readdir_result = NULL; +static struct dirent *mc_readdir_result = NULL; struct dirent * -mc_readdir (DIR *dirp) +mc_readdir (DIR * dirp) { int handle; struct vfs_class *vfs; @@ -809,57 +840,63 @@ mc_readdir (DIR *dirp) * structures, holding dirent size. But we don't use it in libc infrastructure. * TODO: to make simpler homemade dirent-alike structure. */ - 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) { - errno = EFAULT; - return NULL; + if (!dirp) + { + errno = EFAULT; + return NULL; } handle = *(int *) dirp; vfs = vfs_op (handle); if (vfs == NULL) - return NULL; + return NULL; dirinfo = vfs_info (handle); - if (vfs->readdir) { + if (vfs->readdir) + { entry = (*vfs->readdir) (dirinfo->info); - if (entry == NULL) return NULL; - g_string_set_size(vfs_str_buffer,0); - state = str_vfs_convert_from (dirinfo->converter, - entry->d_name, vfs_str_buffer); + if (entry == NULL) + return NULL; + g_string_set_size (vfs_str_buffer, 0); + state = str_vfs_convert_from (dirinfo->converter, entry->d_name, vfs_str_buffer); mc_readdir_result->d_ino = entry->d_ino; 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; } int -mc_closedir (DIR *dirp) +mc_closedir (DIR * dirp) { int handle = *(int *) dirp; struct vfs_class *vfs; int result = -1; vfs = vfs_op (handle); - if (vfs != NULL) { - struct vfs_dirinfo *dirinfo; + if (vfs != NULL) + { + struct vfs_dirinfo *dirinfo; - dirinfo = vfs_info (handle); - if (dirinfo->converter != str_cnv_from_term) - str_close_conv (dirinfo->converter); + dirinfo = vfs_info (handle); + if (dirinfo->converter != str_cnv_from_term) + str_close_conv (dirinfo->converter); - result = vfs->closedir ? (*vfs->closedir)(dirinfo->info) : -1; - vfs_free_handle (handle); - g_free (dirinfo); + result = vfs->closedir ? (*vfs->closedir) (dirinfo->info) : -1; + vfs_free_handle (handle); + g_free (dirinfo); } g_free (dirp); return result; } -int mc_stat (const char *filename, struct stat *buf) { +int +mc_stat (const char *filename, struct stat *buf) +{ struct vfs_class *vfs; int result; char *path; @@ -867,13 +904,14 @@ int mc_stat (const char *filename, struct stat *buf) { path = vfs_canon_and_translate (filename); if (path == NULL) - return -1; + return -1; vfs = vfs_get_class (path); - if (vfs == NULL) { - g_free (path); - return -1; + if (vfs == NULL) + { + g_free (path); + return -1; } result = vfs->stat ? (*vfs->stat) (vfs, path, buf) : -1; @@ -881,11 +919,13 @@ int mc_stat (const char *filename, struct stat *buf) { g_free (path); if (result == -1) - errno = vfs->name ? ferrno (vfs) : E_NOTSUPP; + errno = vfs->name ? ferrno (vfs) : E_NOTSUPP; return result; } -int mc_lstat (const char *filename, struct stat *buf) { +int +mc_lstat (const char *filename, struct stat *buf) +{ struct vfs_class *vfs; int result; char *path; @@ -893,35 +933,38 @@ int mc_lstat (const char *filename, struct stat *buf) { path = vfs_canon_and_translate (filename); if (path == NULL) - return -1; + return -1; vfs = vfs_get_class (path); - if (vfs == NULL) { - g_free (path); - return -1; + if (vfs == NULL) + { + g_free (path); + return -1; } result = vfs->lstat ? (*vfs->lstat) (vfs, path, buf) : -1; g_free (path); if (result == -1) - errno = vfs->name ? ferrno (vfs) : E_NOTSUPP; + errno = vfs->name ? ferrno (vfs) : E_NOTSUPP; return result; } -int mc_fstat (int handle, struct stat *buf) { +int +mc_fstat (int handle, struct stat *buf) +{ struct vfs_class *vfs; int result; if (handle == -1) - return -1; + return -1; vfs = vfs_op (handle); if (vfs == NULL) - return -1; + return -1; result = vfs->fstat ? (*vfs->fstat) (vfs_info (handle), buf) : -1; if (result == -1) - errno = vfs->name ? ferrno (vfs) : E_NOTSUPP; + errno = vfs->name ? ferrno (vfs) : E_NOTSUPP; return result; } @@ -936,14 +979,17 @@ _vfs_get_cwd (void) 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); - if (encoding == NULL) { + if (encoding == NULL) + { char *tmp; 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; char *sys_cwd; @@ -952,16 +998,17 @@ _vfs_get_cwd (void) g_free (tmp); 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; /* Check if it is O.K. to use the current_dir */ if (cd_symlinks && mc_stat (sys_cwd, &my_stat) == 0 && mc_stat (current_dir, &my_stat2) == 0 - && my_stat.st_ino == my_stat2.st_ino - && my_stat.st_dev == my_stat2.st_dev) + && my_stat.st_ino == my_stat2.st_ino && my_stat.st_dev == my_stat2.st_dev) g_free (sys_cwd); - else { + else + { g_free (current_dir); current_dir = sys_cwd; } @@ -981,7 +1028,7 @@ vfs_setup_wd (void) _vfs_get_cwd (); if (strlen (current_dir) > MC_MAXPATHLEN - 2) - vfs_die ("Current dir too long.\n"); + vfs_die ("Current dir too long.\n"); current_vfs = vfs_get_class (current_dir); } @@ -1008,19 +1055,20 @@ vfs_get_current_dir (void) 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; int result; if (fd == -1) - return -1; + return -1; vfs = vfs_op (fd); if (vfs == NULL) - return -1; + return -1; - result = vfs->lseek ? (*vfs->lseek)(vfs_info (fd), offset, whence) : -1; + result = vfs->lseek ? (*vfs->lseek) (vfs_info (fd), offset, whence) : -1; if (result == -1) errno = vfs->lseek ? ferrno (vfs) : E_NOTSUPP; return result; @@ -1036,17 +1084,18 @@ char * vfs_canon (const char *path) { if (!path) - vfs_die("Cannot canonicalize NULL"); + vfs_die ("Cannot canonicalize NULL"); /* Relative to current directory */ - if (*path != PATH_SEP){ - char *local, *result; + if (*path != PATH_SEP) + { + char *local, *result; - local = concat_dir_and_file (current_dir, path); + local = concat_dir_and_file (current_dir, path); - result = vfs_canon (local); - g_free (local); - return result; + result = vfs_canon (local); + g_free (local); + return result; } /* @@ -1054,8 +1103,8 @@ vfs_canon (const char *path) * /p1/p2#op/.././././p3#op/p4. Good luck. */ { - char *result = g_strdup (path); - canonicalize_pathname (result); + char *result = g_strdup (path); + canonicalize_pathname (result); return result; } } @@ -1075,45 +1124,51 @@ mc_chdir (const char *path) new_dir = vfs_canon (path); trans_dir = vfs_translate_path_n (new_dir); - if (trans_dir != NULL) { + if (trans_dir != NULL) + { new_vfs = vfs_get_class (trans_dir); - if (!new_vfs->chdir) { - g_free (new_dir); + if (!new_vfs->chdir) + { + g_free (new_dir); g_free (trans_dir); - return -1; - } + return -1; + } result = (*new_vfs->chdir) (new_vfs, trans_dir); - if (result == -1) { - errno = ferrno (new_vfs); - g_free (new_dir); + if (result == -1) + { + errno = ferrno (new_vfs); + g_free (new_dir); g_free (trans_dir); - return -1; - } + return -1; + } - old_vfsid = vfs_getid (current_vfs, current_dir); - old_vfs = current_vfs; + old_vfsid = vfs_getid (current_vfs, current_dir); + old_vfs = current_vfs; - /* Actually change directory */ - g_free (current_dir); - current_dir = new_dir; - current_vfs = new_vfs; - - /* This function uses the new current_dir implicitly */ - vfs_stamp_create (old_vfs, old_vfsid); - - /* Sometimes we assume no trailing slash on cwd */ - if (*current_dir) { - char *p; - p = strchr (current_dir, 0) - 1; - if (*p == PATH_SEP && p > current_dir) - *p = 0; - } + /* Actually change directory */ + g_free (current_dir); + current_dir = new_dir; + current_vfs = new_vfs; + + /* This function uses the new current_dir implicitly */ + vfs_stamp_create (old_vfs, old_vfsid); + + /* Sometimes we assume no trailing slash on cwd */ + if (*current_dir) + { + char *p; + p = strchr (current_dir, 0) - 1; + if (*p == PATH_SEP && p > current_dir) + *p = 0; + } g_free (trans_dir); - return 0; - } else { + return 0; + } + else + { g_free (new_dir); return -1; } @@ -1134,11 +1189,14 @@ vfs_file_class_flags (const char *filename) char *fname; fname = vfs_canon_and_translate (filename); - if (fname != NULL) { - vfs = vfs_get_class (fname); - g_free (fname); - return vfs->flags; - } else return -1; + if (fname != NULL) + { + vfs = vfs_get_class (fname); + g_free (fname); + return vfs->flags; + } + else + return -1; } static char * @@ -1152,37 +1210,40 @@ mc_def_getlocalcopy (const char *filename) fdin = mc_open (filename, O_RDONLY | O_LINEAR); if (fdin == -1) - return NULL; + return NULL; fdout = vfs_mkstemps (&tmp, "vfs", filename); if (fdout == -1) - goto fail; - while ((i = mc_read (fdin, buffer, sizeof (buffer))) > 0) { - if (write (fdout, buffer, i) != i) - goto fail; + goto fail; + while ((i = mc_read (fdin, buffer, sizeof (buffer))) > 0) + { + if (write (fdout, buffer, i) != i) + goto fail; } if (i == -1) - goto fail; + goto fail; i = mc_close (fdin); fdin = -1; if (i == -1) - goto fail; - if (close (fdout) == -1) { - fdout = -1; - goto fail; + goto fail; + if (close (fdout) == -1) + { + fdout = -1; + goto fail; } - if (mc_stat (filename, &mystat) != -1) { - chmod (tmp, mystat.st_mode); + if (mc_stat (filename, &mystat) != -1) + { + chmod (tmp, mystat.st_mode); } return tmp; fail: if (fdout != -1) - close (fdout); + close (fdout); if (fdin != -1) - mc_close (fdin); + mc_close (fdin); g_free (tmp); return NULL; } @@ -1192,53 +1253,59 @@ mc_getlocalcopy (const char *pathname) { char *result; char *path; - + path = vfs_canon_and_translate (pathname); - if (path != NULL) { - struct vfs_class *vfs = vfs_get_class (path); + if (path != NULL) + { + struct vfs_class *vfs = vfs_get_class (path); - result = vfs->getlocalcopy ? (*vfs->getlocalcopy)(vfs, path) : - mc_def_getlocalcopy (path); - g_free (path); - if (!result) - errno = ferrno (vfs); - return result; - } else return NULL; + result = vfs->getlocalcopy ? (*vfs->getlocalcopy) (vfs, path) : mc_def_getlocalcopy (path); + g_free (path); + if (!result) + errno = ferrno (vfs); + return result; + } + else + return NULL; } static int 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; - if (has_changed) { - char buffer[8192]; - - if (!vfs->write) - goto failed; - - fdin = open (local, O_RDONLY); - if (fdin == -1) - goto failed; - fdout = mc_open (filename, O_WRONLY | O_TRUNC); - if (fdout == -1) - goto failed; - while ((i = read (fdin, buffer, sizeof (buffer))) > 0) { - if (mc_write (fdout, buffer, i) != i) - goto failed; - } - if (i == -1) - goto failed; - - if (close (fdin) == -1) { - fdin = -1; - goto failed; - } - fdin = -1; - if (mc_close (fdout) == -1) { - fdout = -1; - goto failed; - } + if (has_changed) + { + char buffer[8192]; + + if (!vfs->write) + goto failed; + + fdin = open (local, O_RDONLY); + if (fdin == -1) + goto failed; + fdout = mc_open (filename, O_WRONLY | O_TRUNC); + if (fdout == -1) + goto failed; + while ((i = read (fdin, buffer, sizeof (buffer))) > 0) + { + if (mc_write (fdout, buffer, i) != i) + goto failed; + } + if (i == -1) + goto failed; + + if (close (fdin) == -1) + { + fdin = -1; + goto failed; + } + fdin = -1; + if (mc_close (fdout) == -1) + { + fdout = -1; + goto failed; + } } unlink (local); return 0; @@ -1246,9 +1313,9 @@ mc_def_ungetlocalcopy (struct vfs_class *vfs, const char *filename, failed: message (D_ERROR, _("Changes to file lost"), "%s", filename); if (fdout != -1) - mc_close (fdout); + mc_close (fdout); if (fdin != -1) - close (fdin); + close (fdin); unlink (local); return -1; } @@ -1258,17 +1325,20 @@ mc_ungetlocalcopy (const char *pathname, const char *local, int has_changed) { int return_value = 0; char *path; - + path = vfs_canon_and_translate (pathname); - if (path != NULL) { - struct vfs_class *vfs = vfs_get_class (path); + if (path != NULL) + { + struct vfs_class *vfs = vfs_get_class (path); - return_value = vfs->ungetlocalcopy ? - (*vfs->ungetlocalcopy)(vfs, path, local, has_changed) : + return_value = vfs->ungetlocalcopy ? + (*vfs->ungetlocalcopy) (vfs, path, local, has_changed) : mc_def_ungetlocalcopy (vfs, path, local, has_changed); - g_free (path); - return return_value; - } else return -1; + g_free (path); + return return_value; + } + else + return -1; } @@ -1278,9 +1348,9 @@ vfs_init (void) /* create the VFS handle array */ vfs_openfiles = g_ptr_array_new (); - vfs_str_buffer = g_string_new(""); + vfs_str_buffer = g_string_new (""); /* localfs needs to be the first one */ - init_localfs(); + init_localfs (); /* fallback value for vfs_get_class() */ localfs_class = vfs_list; @@ -1317,8 +1387,8 @@ vfs_shut (void) g_free (current_dir); for (vfs = vfs_list; vfs; vfs = vfs->next) - if (vfs->done) - (*vfs->done) (vfs); + if (vfs->done) + (*vfs->done) (vfs); g_ptr_array_free (vfs_openfiles, TRUE); g_string_free (vfs_str_buffer, TRUE); @@ -1334,9 +1404,9 @@ vfs_fill_names (fill_names_f func) { struct vfs_class *vfs; - for (vfs=vfs_list; vfs; vfs=vfs->next) + for (vfs = vfs_list; vfs; vfs = vfs->next) if (vfs->fill_names) - (*vfs->fill_names) (vfs, func); + (*vfs->fill_names) (vfs, func); } /* @@ -1344,16 +1414,21 @@ vfs_fill_names (fill_names_f func) * not recognized as url, g_strdup(url) is returned. */ -static const struct { +static const struct +{ const char *name; size_t name_len; const char *substitute; -} url_table[] = { {"ftp://", 6, "/#ftp:"}, - {"mc://", 5, "/#mc:"}, - {"smb://", 6, "/#smb:"}, - {"sh://", 5, "/#sh:"}, - {"ssh://", 6, "/#sh:"}, - {"a:", 2, "/#a"} +} url_table[] = +{ + /* *INDENT-OFF* */ + { "ftp://", 6, "/#ftp:" }, + { "mc://", 5, "/#mc:" }, + { "smb://", 6, "/#smb:" }, + { "sh://", 5, "/#sh:" }, + { "ssh://", 6, "/#sh:" }, + { "a:", 2, "/#a" } + /* *INDENT-ON* */ }; char * @@ -1361,14 +1436,16 @@ vfs_translate_url (const char *url) { size_t 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) - return g_strconcat (url_table[i].substitute, url + url_table[i].name_len, (char*) NULL); + 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) + return g_strconcat (url_table[i].substitute, url + url_table[i].name_len, + (char *) NULL); 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; } diff --git a/src/complete.c b/src/complete.c index f09f4e9e..7a27af23 100644 --- a/src/complete.c +++ b/src/complete.c @@ -1,16 +1,16 @@ /* Input line filename/username/hostname/variable/command completion. (Let mc type for you...) - + Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. - + Written by: 1995 Jakub Jelinek - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -39,7 +39,7 @@ #include "lib/global.h" #include "lib/tty/tty.h" -#include "lib/tty/key.h" /* XCTRL and ALT macros */ +#include "lib/tty/key.h" /* XCTRL and ALT macros */ #include "lib/vfs/mc-vfs/vfs.h" #include "lib/strescape.h" #include "lib/strutil.h" @@ -47,36 +47,38 @@ #include "dialog.h" #include "widget.h" #include "wtools.h" -#include "main.h" /* show_all_if_ambiguous */ +#include "main.h" /* show_all_if_ambiguous */ -typedef char *CompletionFunction (const char * text, int state, INPUT_COMPLETE_FLAGS flags); +typedef char *CompletionFunction (const char *text, int state, INPUT_COMPLETE_FLAGS flags); /* #define DO_COMPLETION_DEBUG */ #ifdef DO_COMPLETION_DEBUG /* * 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"; s_cf[0] = (flags & INPUT_COMPLETE_FILENAMES) ? 'F' : ' '; s_cf[1] = (flags & INPUT_COMPLETE_HOSTNAMES) ? 'H' : ' '; - s_cf[2] = (flags & INPUT_COMPLETE_COMMANDS) ? 'C' : ' '; + s_cf[2] = (flags & INPUT_COMPLETE_COMMANDS) ? 'C' : ' '; s_cf[3] = (flags & INPUT_COMPLETE_VARIABLES) ? 'V' : ' '; s_cf[4] = (flags & INPUT_COMPLETE_USERNAMES) ? 'U' : ' '; - s_cf[5] = (flags & INPUT_COMPLETE_CD) ? 'D' : ' '; + s_cf[5] = (flags & INPUT_COMPLETE_CD) ? 'D' : ' '; s_cf[6] = (flags & INPUT_COMPLETE_SHELL_ESC) ? 'S' : ' '; return s_cf; } + #define SHOW_C_CTX(func) fprintf(stderr, "%s: text='%s' flags=%s\n", func, text, show_c_flags(flags)) #else #define SHOW_C_CTX(func) #endif /* DO_CMPLETION_DEBUG */ static char * -filename_completion_function (const char * text, int state, INPUT_COMPLETE_FLAGS flags) +filename_completion_function (const char *text, int state, INPUT_COMPLETE_FLAGS flags) { static DIR *directory; static char *filename = NULL; @@ -87,13 +89,13 @@ filename_completion_function (const char * text, int state, INPUT_COMPLETE_FLAGS struct dirent *entry = NULL; - SHOW_C_CTX("filename_completion_function"); + SHOW_C_CTX ("filename_completion_function"); if (text && (flags & INPUT_COMPLETE_SHELL_ESC)) { - char * u_text; - char * result; - char * e_result; + char *u_text; + char *result; + char *e_result; u_text = strutils_shell_unescape (text); @@ -107,31 +109,35 @@ filename_completion_function (const char * text, int state, INPUT_COMPLETE_FLAGS } /* If we're starting the match process, initialize us a bit. */ - if (!state){ + if (!state) + { const char *temp; g_free (dirname); g_free (filename); g_free (users_dirname); - if ((*text) && (temp = strrchr (text, PATH_SEP))){ - filename = g_strdup (++temp); - dirname = g_strndup (text, temp - text); - } else { - dirname = g_strdup ("."); - filename = g_strdup (text); - } + if ((*text) && (temp = strrchr (text, PATH_SEP))) + { + filename = g_strdup (++temp); + dirname = g_strndup (text, temp - text); + } + else + { + dirname = g_strdup ("."); + filename = g_strdup (text); + } /* We aren't done yet. We also support the "~user" syntax. */ /* Save the version of the directory that the user typed. */ users_dirname = dirname; - dirname = tilde_expand (dirname); - canonicalize_pathname (dirname); + dirname = tilde_expand (dirname); + canonicalize_pathname (dirname); - /* Here we should do something with variable expansion - and `command`. - Maybe a dream - UNIMPLEMENTED yet. */ + /* Here we should do something with variable expansion + and `command`. + Maybe a dream - UNIMPLEMENTED yet. */ directory = mc_opendir (dirname); filename_len = strlen (filename); @@ -139,94 +145,107 @@ filename_completion_function (const char * text, int state, INPUT_COMPLETE_FLAGS /* Now that we have some state, we can read the directory. */ - while (directory && (entry = mc_readdir (directory))){ - if (!str_is_valid_string (entry->d_name)) - continue; + while (directory && (entry = mc_readdir (directory))) + { + if (!str_is_valid_string (entry->d_name)) + continue; /* Special case for no filename. - All entries except "." and ".." match. */ - if (filename_len == 0) { - if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, "..")) - continue; - } else { - /* Otherwise, if these match up to the length of filename, then - it may be a match. */ - if ((entry->d_name[0] != filename[0]) || - ((NLENGTH (entry)) < filename_len) || - strncmp (filename, entry->d_name, filename_len)) - continue; - } - isdir = 1; isexec = 0; - { - char *tmp; - struct stat tempstat; - - tmp = g_strconcat (dirname, PATH_SEP_STR, entry->d_name, (char *) NULL); - canonicalize_pathname (tmp); - /* Unix version */ - if (!mc_stat (tmp, &tempstat)){ - uid_t my_uid = getuid (); - gid_t my_gid = getgid (); - - if (!S_ISDIR (tempstat.st_mode)){ - isdir = 0; - if ((!my_uid && (tempstat.st_mode & 0111)) || - (my_uid == tempstat.st_uid && (tempstat.st_mode & 0100)) || - (my_gid == tempstat.st_gid && (tempstat.st_mode & 0010)) || - (tempstat.st_mode & 0001)) - isexec = 1; - } - } - else - { - /* stat failed, strange. not a dir in any case */ - isdir = 0; - } - g_free (tmp); - } - if ((flags & INPUT_COMPLETE_COMMANDS) - && (isexec || isdir)) - break; - if ((flags & INPUT_COMPLETE_CD) - && isdir) - break; - if (flags & (INPUT_COMPLETE_FILENAMES)) - break; + All entries except "." and ".." match. */ + if (filename_len == 0) + { + if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, "..")) + continue; + } + else + { + /* Otherwise, if these match up to the length of filename, then + it may be a match. */ + if ((entry->d_name[0] != filename[0]) || + ((NLENGTH (entry)) < filename_len) || + strncmp (filename, entry->d_name, filename_len)) + continue; + } + isdir = 1; + isexec = 0; + { + char *tmp; + struct stat tempstat; + + tmp = g_strconcat (dirname, PATH_SEP_STR, entry->d_name, (char *) NULL); + canonicalize_pathname (tmp); + /* Unix version */ + if (!mc_stat (tmp, &tempstat)) + { + uid_t my_uid = getuid (); + gid_t my_gid = getgid (); + + if (!S_ISDIR (tempstat.st_mode)) + { + isdir = 0; + if ((!my_uid && (tempstat.st_mode & 0111)) || + (my_uid == tempstat.st_uid && (tempstat.st_mode & 0100)) || + (my_gid == tempstat.st_gid && (tempstat.st_mode & 0010)) || + (tempstat.st_mode & 0001)) + isexec = 1; + } + } + else + { + /* stat failed, strange. not a dir in any case */ + isdir = 0; + } + g_free (tmp); + } + if ((flags & INPUT_COMPLETE_COMMANDS) && (isexec || isdir)) + break; + if ((flags & INPUT_COMPLETE_CD) && isdir) + break; + if (flags & (INPUT_COMPLETE_FILENAMES)) + break; } - if (!entry){ - if (directory){ - mc_closedir (directory); - directory = NULL; - } - g_free (dirname); - dirname = NULL; - g_free (filename); - filename = NULL; - g_free (users_dirname); - users_dirname = NULL; + if (!entry) + { + if (directory) + { + mc_closedir (directory); + directory = NULL; + } + g_free (dirname); + dirname = NULL; + g_free (filename); + filename = NULL; + g_free (users_dirname); + users_dirname = NULL; return NULL; - } else { + } + else + { char *temp; - if (users_dirname && (users_dirname[0] != '.' || users_dirname[1])){ - size_t dirlen = strlen (users_dirname); - temp = g_malloc (3 + dirlen + NLENGTH (entry)); - strcpy (temp, users_dirname); - /* We need a `/' at the end. */ - if (users_dirname[dirlen - 1] != PATH_SEP){ - temp[dirlen] = PATH_SEP; - temp[dirlen + 1] = 0; - } - strcat (temp, entry->d_name); - } else { - temp = g_malloc (2 + NLENGTH (entry)); - strcpy (temp, entry->d_name); - } - if (isdir) - strcat (temp, PATH_SEP_STR); - - return temp; + if (users_dirname && (users_dirname[0] != '.' || users_dirname[1])) + { + size_t dirlen = strlen (users_dirname); + temp = g_malloc (3 + dirlen + NLENGTH (entry)); + strcpy (temp, users_dirname); + /* We need a `/' at the end. */ + if (users_dirname[dirlen - 1] != PATH_SEP) + { + temp[dirlen] = PATH_SEP; + temp[dirlen + 1] = 0; + } + strcat (temp, entry->d_name); + } + else + { + temp = g_malloc (2 + NLENGTH (entry)); + strcpy (temp, entry->d_name); + } + if (isdir) + strcat (temp, PATH_SEP_STR); + + return temp; } } @@ -239,25 +258,26 @@ username_completion_function (const char *text, int state, INPUT_COMPLETE_FLAGS static size_t userlen; (void) flags; - SHOW_C_CTX("username_completion_function"); + SHOW_C_CTX ("username_completion_function"); if (text[0] == '\\' && text[1] == '~') - text++; - if (!state){ /* Initialization stuff */ + text++; + if (!state) + { /* Initialization stuff */ setpwent (); userlen = strlen (text + 1); } - while ((entry = getpwent ()) != NULL){ + while ((entry = getpwent ()) != NULL) + { /* Null usernames should result in all users as possible completions. */ if (userlen == 0) break; - if (text[1] == entry->pw_name[0] - && !strncmp (text + 1, entry->pw_name, userlen)) - break; + if (text[1] == entry->pw_name[0] && !strncmp (text + 1, entry->pw_name, userlen)) + break; } if (entry) - return g_strconcat ("~", entry->pw_name, PATH_SEP_STR, (char *) NULL); + return g_strconcat ("~", entry->pw_name, PATH_SEP_STR, (char *) NULL); endpwent (); return NULL; @@ -278,34 +298,37 @@ variable_completion_function (const char *text, int state, INPUT_COMPLETE_FLAGS const char *p = NULL; (void) flags; - SHOW_C_CTX("variable_completion_function"); + SHOW_C_CTX ("variable_completion_function"); - if (!state){ /* Initialization stuff */ - isbrace = (text [1] == '{'); + if (!state) + { /* Initialization stuff */ + isbrace = (text[1] == '{'); varlen = strlen (text + 1 + isbrace); env_p = environ; } - while (*env_p){ - p = strchr (*env_p, '='); - if (p && p - *env_p >= varlen && !strncmp (text + 1 + isbrace, *env_p, varlen)) - break; - env_p++; + while (*env_p) + { + p = strchr (*env_p, '='); + if (p && p - *env_p >= varlen && !strncmp (text + 1 + isbrace, *env_p, varlen)) + break; + env_p++; } if (!*env_p) return NULL; - else { + else + { char *temp = g_malloc (2 + 2 * isbrace + p - *env_p); - *temp = '$'; - if (isbrace) - temp [1] = '{'; - memcpy (temp + 1 + isbrace, *env_p, p - *env_p); + *temp = '$'; + if (isbrace) + temp[1] = '{'; + memcpy (temp + 1 + isbrace, *env_p, p - *env_p); if (isbrace) strcpy (temp + 2 + (p - *env_p), "}"); else - temp [1 + p - *env_p] = 0; + temp[1 + p - *env_p] = 0; env_p++; return temp; } @@ -317,7 +340,8 @@ variable_completion_function (const char *text, int state, INPUT_COMPLETE_FLAGS static char **hosts = NULL; static char **hosts_p = NULL; static int hosts_alloclen = 0; -static void fetch_hosts (const char *filename) +static void +fetch_hosts (const char *filename) { FILE *file = fopen (filename, "r"); char buffer[256], *name; @@ -327,70 +351,74 @@ static void fetch_hosts (const char *filename) if (!file) return; - while (fgets (buffer, 255, file) != NULL){ + while (fgets (buffer, 255, file) != NULL) + { /* Skip to first character. */ - for (bi = buffer; - bi[0] != '\0' && str_isspace (bi); - str_next_char (&bi)); - + for (bi = buffer; bi[0] != '\0' && str_isspace (bi); str_next_char (&bi)); + /* Ignore comments... */ if (bi[0] == '#') continue; /* Handle $include. */ - if (!strncmp (bi, "$include ", 9)){ - char *includefile = bi + 9; - char *t; - - /* Find start of filename. */ - while (*includefile && whitespace (*includefile)) - includefile++; - t = includefile; - - /* Find end of filename. */ - while (t[0] != '\0' && !str_isspace (t)) - str_next_char (&t); - *t = '\0'; - - fetch_hosts (includefile); - continue; - } + if (!strncmp (bi, "$include ", 9)) + { + char *includefile = bi + 9; + char *t; + + /* Find start of filename. */ + while (*includefile && whitespace (*includefile)) + includefile++; + t = includefile; + + /* Find end of filename. */ + while (t[0] != '\0' && !str_isspace (t)) + str_next_char (&t); + *t = '\0'; + + fetch_hosts (includefile); + continue; + } /* Skip IP #s. */ - while (bi[0] != '\0' && !str_isspace (bi)) - str_next_char (&bi); + while (bi[0] != '\0' && !str_isspace (bi)) + str_next_char (&bi); /* Get the host names separated by white space. */ - while (bi[0] != '\0' && bi[0] != '#'){ - while (bi[0] != '\0' && str_isspace (bi)) - str_next_char (&bi); - if (bi[0] == '#') - continue; - for (start = bi; - bi[0] != '\0' && !str_isspace (bi); - str_next_char (&bi)); - - if (bi - start == 0) continue; - - name = g_strndup (start, bi - start); - { - char **host_p; - - if (hosts_p - hosts >= hosts_alloclen){ - int j = hosts_p - hosts; - - hosts = g_realloc ((void *)hosts, ((hosts_alloclen += 30) + 1) * sizeof (char *)); - hosts_p = hosts + j; - } - for (host_p = hosts; host_p < hosts_p; host_p++) - if (!strcmp (name, *host_p)) - break; /* We do not want any duplicates */ - if (host_p == hosts_p){ - *(hosts_p++) = name; - *hosts_p = NULL; - } else - g_free (name); - } - } + while (bi[0] != '\0' && bi[0] != '#') + { + while (bi[0] != '\0' && str_isspace (bi)) + str_next_char (&bi); + if (bi[0] == '#') + continue; + for (start = bi; bi[0] != '\0' && !str_isspace (bi); str_next_char (&bi)); + + if (bi - start == 0) + continue; + + name = g_strndup (start, bi - start); + { + char **host_p; + + if (hosts_p - hosts >= hosts_alloclen) + { + int j = hosts_p - hosts; + + hosts = + g_realloc ((void *) hosts, ((hosts_alloclen += 30) + 1) * sizeof (char *)); + hosts_p = hosts + j; + } + for (host_p = hosts; host_p < hosts_p; host_p++) + if (!strcmp (name, *host_p)) + break; /* We do not want any duplicates */ + if (host_p == hosts_p) + { + *(hosts_p++) = name; + *hosts_p = NULL; + } + else + g_free (name); + } + } } fclose (file); } @@ -402,47 +430,53 @@ hostname_completion_function (const char *text, int state, INPUT_COMPLETE_FLAGS static int textstart, textlen; (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; - - if (hosts != NULL){ - for (host_p = hosts; *host_p; host_p++) - g_free (*host_p); - g_free (hosts); - } - hosts = g_new (char *, (hosts_alloclen = 30) + 1); - *hosts = NULL; - hosts_p = hosts; - fetch_hosts ((p = getenv ("HOSTFILE")) ? p : "/etc/hosts"); - host_p = hosts; - textstart = (*text == '@') ? 1 : 0; - textlen = strlen (text + textstart); + + if (hosts != NULL) + { + for (host_p = hosts; *host_p; host_p++) + g_free (*host_p); + g_free (hosts); + } + hosts = g_new (char *, (hosts_alloclen = 30) + 1); + *hosts = NULL; + hosts_p = hosts; + fetch_hosts ((p = getenv ("HOSTFILE")) ? p : "/etc/hosts"); + host_p = hosts; + textstart = (*text == '@') ? 1 : 0; + textlen = strlen (text + textstart); } - - while (*host_p){ - if (!textlen) - break; /* Match all of them */ - else if (!strncmp (text + textstart, *host_p, textlen)) - break; - host_p++; + + while (*host_p) + { + if (!textlen) + break; /* Match all of them */ + else if (!strncmp (text + textstart, *host_p, textlen)) + break; + host_p++; } - - if (!*host_p){ - for (host_p = hosts; *host_p; host_p++) - g_free (*host_p); - g_free (hosts); - hosts = NULL; - return NULL; - } else { - char *temp = g_malloc (2 + strlen (*host_p)); - - if (textstart) - *temp = '@'; - strcpy (temp + textstart, *host_p); - host_p++; - return temp; + + if (!*host_p) + { + for (host_p = hosts; *host_p; host_p++) + g_free (*host_p); + g_free (hosts); + hosts = NULL; + return NULL; + } + else + { + char *temp = g_malloc (2 + strlen (*host_p)); + + if (textstart) + *temp = '@'; + strcpy (temp + textstart, *host_p); + host_p++; + return temp; } } @@ -466,122 +500,137 @@ command_completion_function (const char *_text, int state, INPUT_COMPLETE_FLAGS static char *cur_word; static int init_state; static const char *const bash_reserved[] = { - "if", "then", "else", "elif", "fi", "case", "esac", "for", - "select", "while", "until", "do", "done", "in", "function", 0 + "if", "then", "else", "elif", "fi", "case", "esac", "for", + "select", "while", "until", "do", "done", "in", "function", 0 }; static const char *const bash_builtins[] = { - "alias", "bg", "bind", "break", "builtin", "cd", "command", - "continue", "declare", "dirs", "echo", "enable", "eval", - "exec", "exit", "export", "fc", "fg", "getopts", "hash", - "help", "history", "jobs", "kill", "let", "local", "logout", - "popd", "pushd", "pwd", "read", "readonly", "return", "set", - "shift", "source", "suspend", "test", "times", "trap", "type", - "typeset", "ulimit", "umask", "unalias", "unset", "wait", 0 + "alias", "bg", "bind", "break", "builtin", "cd", "command", + "continue", "declare", "dirs", "echo", "enable", "eval", + "exec", "exit", "export", "fc", "fg", "getopts", "hash", + "help", "history", "jobs", "kill", "let", "local", "logout", + "popd", "pushd", "pwd", "read", "readonly", "return", "set", + "shift", "source", "suspend", "test", "times", "trap", "type", + "typeset", "ulimit", "umask", "unalias", "unset", "wait", 0 }; char *p, *found; - SHOW_C_CTX("command_completion_function"); + SHOW_C_CTX ("command_completion_function"); if (!(flags & INPUT_COMPLETE_COMMANDS)) return 0; - text = strutils_shell_unescape(_text); + text = strutils_shell_unescape (_text); flags &= ~INPUT_COMPLETE_SHELL_ESC; - if (!state) { /* Initialize us a little bit */ - isabsolute = strchr (text, PATH_SEP) != NULL; - if (!isabsolute) { - words = bash_reserved; - phase = 0; - text_len = strlen (text); - if (!path && (path = g_strdup (getenv ("PATH"))) != NULL) { - p = path; - path_end = strchr (p, 0); - while ((p = strchr (p, PATH_ENV_SEP))) { - *p++ = 0; - } - } - } + if (!state) + { /* Initialize us a little bit */ + isabsolute = strchr (text, PATH_SEP) != NULL; + if (!isabsolute) + { + words = bash_reserved; + phase = 0; + text_len = strlen (text); + if (!path && (path = g_strdup (getenv ("PATH"))) != NULL) + { + p = path; + path_end = strchr (p, 0); + while ((p = strchr (p, PATH_ENV_SEP))) + { + *p++ = 0; + } + } + } } - if (isabsolute) { - p = filename_completion_function (text, state, flags); + if (isabsolute) + { + p = filename_completion_function (text, state, flags); - if (p) { - char *temp_p = p; - p = strutils_shell_escape (p); - g_free (temp_p); - } + if (p) + { + char *temp_p = p; + p = strutils_shell_escape (p); + g_free (temp_p); + } - g_free (text); - return p; + g_free (text); + return p; } found = NULL; - switch (phase) { - case 0: /* Reserved words */ - while (*words) { - if (strncmp (*words, text, text_len) == 0) { - g_free (text); - return g_strdup (*(words++)); - } - words++; - } - phase++; - words = bash_builtins; - case 1: /* Builtin commands */ - while (*words) { - if (strncmp (*words, text, text_len) == 0) { - g_free (text); - return g_strdup (*(words++)); - } - words++; - } - phase++; - if (!path) - break; - cur_path = path; - cur_word = NULL; - case 2: /* And looking through the $PATH */ - while (!found) { - if (!cur_word) { - char *expanded; - - if (cur_path >= path_end) - break; - expanded = tilde_expand (*cur_path ? cur_path : "."); - cur_word = concat_dir_and_file (expanded, text); - g_free (expanded); - canonicalize_pathname (cur_word); - cur_path = strchr (cur_path, 0) + 1; - init_state = state; - } - found = - filename_completion_function (cur_word, - state - init_state, flags); - if (!found) { - g_free (cur_word); - cur_word = NULL; - } - } + switch (phase) + { + case 0: /* Reserved words */ + while (*words) + { + if (strncmp (*words, text, text_len) == 0) + { + g_free (text); + return g_strdup (*(words++)); + } + words++; + } + phase++; + words = bash_builtins; + case 1: /* Builtin commands */ + while (*words) + { + if (strncmp (*words, text, text_len) == 0) + { + g_free (text); + return g_strdup (*(words++)); + } + words++; + } + phase++; + if (!path) + break; + cur_path = path; + cur_word = NULL; + case 2: /* And looking through the $PATH */ + while (!found) + { + if (!cur_word) + { + char *expanded; + + if (cur_path >= path_end) + break; + expanded = tilde_expand (*cur_path ? cur_path : "."); + cur_word = concat_dir_and_file (expanded, text); + g_free (expanded); + canonicalize_pathname (cur_word); + cur_path = strchr (cur_path, 0) + 1; + init_state = state; + } + found = filename_completion_function (cur_word, state - init_state, flags); + if (!found) + { + g_free (cur_word); + cur_word = NULL; + } + } } - if (found == NULL) { - g_free (path); - path = NULL; - } else if ((p = strrchr (found, PATH_SEP)) != NULL) { - char *tmp = found; - found = strutils_shell_escape (p + 1); - g_free (tmp); + if (found == NULL) + { + g_free (path); + path = NULL; + } + else if ((p = strrchr (found, PATH_SEP)) != NULL) + { + char *tmp = found; + found = strutils_shell_escape (p + 1); + g_free (tmp); } - g_free(text); + g_free (text); return found; } static int match_compare (const void *a, const void *b) { - return strcmp (*(char **)a, *(char **)b); + return strcmp (*(char **) a, *(char **) b); } /* Returns an array of char * matches with the longest common denominator @@ -608,9 +657,11 @@ completion_matches (const char *text, CompletionFunction entry_function, INPUT_C 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) - 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 + 1] = NULL; } @@ -620,57 +671,67 @@ completion_matches (const char *text, CompletionFunction entry_function, INPUT_C if (matches) { register int i = 1; - int low = 4096; /* Count of max-matched characters. */ + int low = 4096; /* Count of max-matched characters. */ /* If only one match, just use that. */ - if (matches == 1){ - match_list[0] = match_list[1]; - match_list[1] = NULL; - } else { + if (matches == 1) + { + match_list[0] = match_list[1]; + match_list[1] = NULL; + } + else + { int j; - - qsort (match_list + 1, matches, sizeof (char *), match_compare); - /* And compare each member of the list with - the next, finding out where they stop matching. - If we find two equal strings, we have to put one away... */ + qsort (match_list + 1, matches, sizeof (char *), match_compare); - j = i + 1; - while (j < matches + 1) - { + /* And compare each member of the list with + the next, finding out where they stop matching. + If we find two equal strings, we have to put one away... */ + + j = i + 1; + while (j < matches + 1) + { char *si, *sj; char *ni, *nj; - for (si = match_list[i], sj = match_list[j]; - si[0] && sj[0];) { + for (si = match_list[i], sj = match_list[j]; si[0] && sj[0];) + { ni = str_get_next_char (si); nj = str_get_next_char (sj); - - if (ni - si != nj - sj) break; - if (strncmp (si, sj, ni - si) != 0) break; + + if (ni - si != nj - sj) + break; + if (strncmp (si, sj, ni - si) != 0) + break; si = ni; sj = nj; } - - if (si[0] == '\0' && sj[0] == '\0'){ /* Two equal strings */ - g_free (match_list [j]); - j++; - if (j > matches) - break; - continue; /* Look for a run of equal strings */ - } else - if (low > si - match_list[i]) low = si - match_list[i]; - if (i + 1 != j) /* So there's some gap */ - match_list [i + 1] = match_list [j]; - i++; j++; - } - matches = i; - match_list [matches + 1] = NULL; - match_list[0] = g_strndup(match_list[1], low); - } - } else { /* There were no matches. */ + + if (si[0] == '\0' && sj[0] == '\0') + { /* Two equal strings */ + g_free (match_list[j]); + j++; + if (j > matches) + break; + continue; /* Look for a run of equal strings */ + } + else if (low > si - match_list[i]) + low = si - match_list[i]; + if (i + 1 != j) /* So there's some gap */ + match_list[i + 1] = match_list[j]; + i++; + j++; + } + matches = i; + match_list[matches + 1] = NULL; + match_list[0] = g_strndup (match_list[1], low); + } + } + else + { /* There were no matches. */ g_free (match_list); match_list = NULL; } @@ -684,24 +745,24 @@ check_is_cd (const char *text, int start, INPUT_COMPLETE_FLAGS flags) char *p, *q; int test = 0; - SHOW_C_CTX("check_is_cd"); + SHOW_C_CTX ("check_is_cd"); if (!(flags & INPUT_COMPLETE_CD)) - return 0; + return 0; /* Skip initial spaces */ - p = (char*)text; - q = (char*)text + start; + p = (char *) text; + q = (char *) text + start; while (p < q && p[0] != '\0' && str_isspace (p)) - str_next_char (&p); + str_next_char (&p); /* Check if the command is "cd" and the cursor is after it */ - text+= p[0] == 'c'; + text += p[0] == 'c'; str_next_char (&p); - text+= p[0] == 'd'; + text += p[0] == 'd'; str_next_char (&p); - text+= str_isspace (p); + text += str_isspace (p); if (test == 3 && (p < q)) - return 1; + return 1; return 0; } @@ -718,65 +779,71 @@ try_complete (char *text, int *start, int *end, INPUT_COMPLETE_FLAGS flags) int is_cd = check_is_cd (text, *start, flags); char *ti; - SHOW_C_CTX("try_complete"); + SHOW_C_CTX ("try_complete"); word = g_strndup (text + *start, *end - *start); /* Determine if this could be a command word. It is if it appears at the start of the line (ignoring preceding whitespace), or if it appears after a character that separates commands. And we have to 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]); while (ti > text && (ti[0] == ' ' || ti[0] == '\t')) str_prev_char (&ti); - if (ti <= text&& (ti[0] == ' ' || ti[0] == '\t')) + if (ti <= text && (ti[0] == ' ' || ti[0] == '\t')) 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; in_command_position++; - if (ti > text){ + if (ti > text) + { /* Handle the two character tokens `>&', `<&', and `>|'. We are not in a command position after one of these. */ this_char = ti[0]; prev_char = str_get_prev_char (ti)[0]; if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) || - (this_char == '|' && prev_char == '>')) - in_command_position = 0; + (this_char == '|' && prev_char == '>')) + in_command_position = 0; - else if (ti > text && str_get_prev_char (ti)[0] == '\\') /* Quoted */ - in_command_position = 0; - } - } + else if (ti > text && str_get_prev_char (ti)[0] == '\\') /* Quoted */ + in_command_position = 0; + } + } } if (flags & INPUT_COMPLETE_COMMANDS) - p = strrchr (word, '`'); + p = strrchr (word, '`'); if (flags & (INPUT_COMPLETE_COMMANDS | INPUT_COMPLETE_VARIABLES)) q = strrchr (word, '$'); - if (flags & INPUT_COMPLETE_HOSTNAMES) + if (flags & INPUT_COMPLETE_HOSTNAMES) r = strrchr (word, '@'); - if (q && q [1] == '(' && INPUT_COMPLETE_COMMANDS){ - if (q > p) - p = str_get_next_char (q); - q = NULL; + if (q && q[1] == '(' && INPUT_COMPLETE_COMMANDS) + { + if (q > p) + p = str_get_next_char (q); + q = NULL; } /* Command substitution? */ - if (p > q && p > r){ - SHOW_C_CTX("try_complete:cmd_backq_subst"); + if (p > q && p > r) + { + SHOW_C_CTX ("try_complete:cmd_backq_subst"); matches = completion_matches (str_cget_next_char (p), - command_completion_function, + command_completion_function, flags & (~INPUT_COMPLETE_FILENAMES)); if (matches) *start += str_get_next_char (p) - word; } /* Variable name? */ - else if (q > p && q > r){ - SHOW_C_CTX("try_complete:var_subst"); + else if (q > p && q > r) + { + SHOW_C_CTX ("try_complete:var_subst"); matches = completion_matches (q, variable_completion_function, flags); if (matches) *start += q - word; @@ -784,8 +851,9 @@ try_complete (char *text, int *start, int *end, INPUT_COMPLETE_FLAGS flags) /* Starts with '@', then look through the known hostnames for completion first. */ - else if (r > p && r > q){ - SHOW_C_CTX("try_complete:host_subst"); + else if (r > p && r > q) + { + SHOW_C_CTX ("try_complete:host_subst"); matches = completion_matches (r, hostname_completion_function, flags); if (matches) *start += r - word; @@ -795,7 +863,7 @@ try_complete (char *text, int *start, int *end, INPUT_COMPLETE_FLAGS flags) try completing this word as a username. */ if (!matches && *word == '~' && (flags & INPUT_COMPLETE_USERNAMES) && !strchr (word, PATH_SEP)) { - SHOW_C_CTX("try_complete:user_subst"); + SHOW_C_CTX ("try_complete:user_subst"); matches = completion_matches (word, username_completion_function, flags); } @@ -805,47 +873,54 @@ try_complete (char *text, int *start, int *end, INPUT_COMPLETE_FLAGS flags) and command names. */ if (!matches && in_command_position) { - SHOW_C_CTX("try_complete:cmd_subst"); - matches = completion_matches (word, command_completion_function, flags & (~INPUT_COMPLETE_FILENAMES)); + SHOW_C_CTX ("try_complete:cmd_subst"); + matches = + completion_matches (word, command_completion_function, + flags & (~INPUT_COMPLETE_FILENAMES)); } - else if (!matches && (flags & INPUT_COMPLETE_FILENAMES)){ - if (is_cd) - flags &= ~(INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_COMMANDS); - SHOW_C_CTX("try_complete:filename_subst_1"); - matches = completion_matches (word, filename_completion_function, flags); - if (!matches && is_cd && *word != PATH_SEP && *word != '~'){ - q = text + *start; - for (p = text; *p && p < q && (*p == ' ' || *p == '\t'); str_next_char (&p)); - if (!strncmp (p, "cd", 2)) - for (p += 2; *p && p < q && (*p == ' ' || *p == '\t'); str_next_char (&p)); - if (p == q){ - char * const cdpath_ref = g_strdup (getenv ("CDPATH")); - char *cdpath = cdpath_ref; - char c, *s; - - if (cdpath == NULL) - c = 0; - else - c = ':'; - while (!matches && c == ':'){ - s = strchr (cdpath, ':'); - if (s == NULL) - s = strchr (cdpath, 0); - c = *s; - *s = 0; - if (*cdpath){ - r = concat_dir_and_file (cdpath, word); - SHOW_C_CTX("try_complete:filename_subst_2"); - matches = completion_matches (r, filename_completion_function, flags); - g_free (r); - } - *s = c; - cdpath = str_get_next_char (s); - } - g_free (cdpath_ref); - } - } + else if (!matches && (flags & INPUT_COMPLETE_FILENAMES)) + { + if (is_cd) + flags &= ~(INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_COMMANDS); + SHOW_C_CTX ("try_complete:filename_subst_1"); + matches = completion_matches (word, filename_completion_function, flags); + if (!matches && is_cd && *word != PATH_SEP && *word != '~') + { + q = text + *start; + for (p = text; *p && p < q && (*p == ' ' || *p == '\t'); str_next_char (&p)); + if (!strncmp (p, "cd", 2)) + for (p += 2; *p && p < q && (*p == ' ' || *p == '\t'); str_next_char (&p)); + if (p == q) + { + char *const cdpath_ref = g_strdup (getenv ("CDPATH")); + char *cdpath = cdpath_ref; + char c, *s; + + if (cdpath == NULL) + c = 0; + else + c = ':'; + while (!matches && c == ':') + { + s = strchr (cdpath, ':'); + if (s == NULL) + s = strchr (cdpath, 0); + c = *s; + *s = 0; + if (*cdpath) + { + r = concat_dir_and_file (cdpath, word); + SHOW_C_CTX ("try_complete:filename_subst_2"); + matches = completion_matches (r, filename_completion_function, flags); + g_free (r); + } + *s = c; + cdpath = str_get_next_char (s); + } + g_free (cdpath_ref); + } + } } g_free (word); @@ -853,14 +928,15 @@ try_complete (char *text, int *start, int *end, INPUT_COMPLETE_FLAGS flags) return matches; } -void free_completions (WInput *in) +void +free_completions (WInput * in) { char **p; if (!in->completions) - return; - for (p=in->completions; *p; p++) - g_free (*p); + return; + for (p = in->completions; *p; p++) + g_free (*p); g_free (in->completions); in->completions = NULL; } @@ -871,125 +947,145 @@ static int min_end; static int start, end; static int -insert_text (WInput *in, char *text, ssize_t size) +insert_text (WInput * in, char *text, ssize_t size) { int buff_len = str_length (in->buffer); size = min (size, (ssize_t) strlen (text)) + start - end; - if (strlen (in->buffer) + size >= (size_t) in->current_max_size){ - /* Expand the buffer */ - char *narea = g_try_realloc (in->buffer, in->current_max_size - + size + in->field_width); - if (narea != NULL) { - in->buffer = narea; - in->current_max_size += size + in->field_width; - } + if (strlen (in->buffer) + size >= (size_t) in->current_max_size) + { + /* Expand the buffer */ + char *narea = g_try_realloc (in->buffer, in->current_max_size + size + in->field_width); + if (narea != NULL) + { + in->buffer = narea; + in->current_max_size += size + in->field_width; + } } - if (strlen (in->buffer)+1 < (size_t) in->current_max_size){ - if (size > 0){ - int i = strlen (&in->buffer [end]); - for (; i >= 0; i--) - in->buffer [end + size + i] = in->buffer [end + i]; - } else if (size < 0){ - char *p = in->buffer + end + size, *q = in->buffer + end; - while (*q) - *(p++) = *(q++); - *p = 0; - } - memcpy (in->buffer + start, text, size - start + end); - in->point+= str_length (in->buffer) - buff_len; - update_input (in, 1); - end+= size; + if (strlen (in->buffer) + 1 < (size_t) in->current_max_size) + { + if (size > 0) + { + int i = strlen (&in->buffer[end]); + for (; i >= 0; i--) + in->buffer[end + size + i] = in->buffer[end + i]; + } + else if (size < 0) + { + char *p = in->buffer + end + size, *q = in->buffer + end; + while (*q) + *(p++) = *(q++); + *p = 0; + } + memcpy (in->buffer + start, text, size - start + end); + in->point += str_length (in->buffer) - buff_len; + update_input (in, 1); + end += size; } return size != 0; } static cb_ret_t -query_callback (Dlg_head *h, Widget *sender, - dlg_msg_t msg, int parm, void *data) +query_callback (Dlg_head * h, Widget * sender, dlg_msg_t msg, int parm, void *data) { static char buff[MB_LEN_MAX] = ""; static int bl = 0; - switch (msg) { + switch (msg) + { case DLG_KEY: - switch (parm) { - case KEY_LEFT: - case KEY_RIGHT: + switch (parm) + { + case KEY_LEFT: + case KEY_RIGHT: bl = 0; - h->ret_value = 0; - dlg_stop (h); - return MSG_HANDLED; + h->ret_value = 0; + dlg_stop (h); + return MSG_HANDLED; - case KEY_BACKSPACE: + case KEY_BACKSPACE: bl = 0; - if (end == min_end) { - h->ret_value = 0; - dlg_stop (h); - } else { - int i; - GList *e; - - for (i = 0, e = ((WListbox *) h->current)->list; - e != NULL; - i++, e = g_list_next (e)) { - WLEntry *le = (WLEntry *) e->data; - - if (strncmp (input->buffer + start, le->text, end - start - 1) == 0) { - listbox_select_entry ((WListbox *) h->current, i); - end = str_get_prev_char (&(input->buffer[end])) - input->buffer; - handle_char (input, parm); - send_message (h->current, WIDGET_DRAW, 0); - break; - } - } - } - return MSG_HANDLED; - - default: - if (parm < 32 || parm > 256) { + if (end == min_end) + { + h->ret_value = 0; + dlg_stop (h); + } + else + { + int i; + GList *e; + + for (i = 0, e = ((WListbox *) h->current)->list; + e != NULL; i++, e = g_list_next (e)) + { + WLEntry *le = (WLEntry *) e->data; + + if (strncmp (input->buffer + start, le->text, end - start - 1) == 0) + { + listbox_select_entry ((WListbox *) h->current, i); + end = str_get_prev_char (&(input->buffer[end])) - input->buffer; + handle_char (input, parm); + send_message (h->current, WIDGET_DRAW, 0); + break; + } + } + } + return MSG_HANDLED; + + default: + if (parm < 32 || parm > 256) + { bl = 0; - if (is_in_input_map (input, parm) == 2) { - if (end == min_end) - return MSG_HANDLED; - h->ret_value = B_USER; /* This means we want to refill the - list box and start again */ - dlg_stop (h); - return MSG_HANDLED; - } else - return MSG_NOT_HANDLED; - } else { - GList *e; - int i; - int need_redraw = 0; - int low = 4096; - char *last_text = NULL; + if (is_in_input_map (input, parm) == 2) + { + if (end == min_end) + return MSG_HANDLED; + h->ret_value = B_USER; /* This means we want to refill the + list box and start again */ + dlg_stop (h); + return MSG_HANDLED; + } + else + return MSG_NOT_HANDLED; + } + else + { + GList *e; + int i; + int need_redraw = 0; + int low = 4096; + char *last_text = NULL; buff[bl] = (char) parm; bl++; buff[bl] = '\0'; - switch (str_is_valid_char (buff, bl)) { - case -1: - bl = 0; - case -2: - return MSG_HANDLED; + switch (str_is_valid_char (buff, bl)) + { + case -1: + bl = 0; + case -2: + return MSG_HANDLED; } - for (i = 0, e = ((WListbox *) h->current)->list; - e != NULL; - i++, e = g_list_next (e)) { - WLEntry *le = (WLEntry *) e->data; + for (i = 0, e = ((WListbox *) h->current)->list; + e != NULL; i++, e = g_list_next (e)) + { + WLEntry *le = (WLEntry *) e->data; - if (strncmp (input->buffer + start, le->text, end - start) == 0) { - if (strncmp (&le->text[end - start], buff, bl) == 0) { - if (need_redraw) { - char *si, *sl; - char *nexti, *nextl; + if (strncmp (input->buffer + start, le->text, end - start) == 0) + { + if (strncmp (&le->text[end - start], buff, bl) == 0) + { + if (need_redraw) + { + char *si, *sl; + char *nexti, *nextl; si = &(le->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); nextl = str_get_next_char (sl); @@ -1002,35 +1098,40 @@ query_callback (Dlg_head *h, Widget *sender, sl = nextl; } - if (low > si - &le->text[end - start]) - low = si - &le->text[end - start]; - - last_text = le->text; - need_redraw = 2; - } else { - need_redraw = 1; - listbox_select_entry ((WListbox *) h->current, i); - last_text = le->text; - } - } - } - } - - if (need_redraw == 2) { - insert_text (input, last_text, low); - send_message (h->current, WIDGET_DRAW, 0); - } else if (need_redraw == 1) { - h->ret_value = B_ENTER; - dlg_stop (h); - } + if (low > si - &le->text[end - start]) + low = si - &le->text[end - start]; + + last_text = le->text; + need_redraw = 2; + } + else + { + need_redraw = 1; + listbox_select_entry ((WListbox *) h->current, i); + last_text = le->text; + } + } + } + } + + if (need_redraw == 2) + { + insert_text (input, last_text, low); + send_message (h->current, WIDGET_DRAW, 0); + } + else if (need_redraw == 1) + { + h->ret_value = B_ENTER; + dlg_stop (h); + } bl = 0; - } - return MSG_HANDLED; - } - break; + } + return MSG_HANDLED; + } + break; default: - return default_dlg_callback (h, sender, msg, parm, data); + return default_dlg_callback (h, sender, msg, parm, data); } } @@ -1038,115 +1139,134 @@ query_callback (Dlg_head *h, Widget *sender, #define DO_QUERY 2 /* Returns 1 if the user would like to see us again */ static int -complete_engine (WInput *in, int what_to_do) +complete_engine (WInput * in, int what_to_do) { int s; if (in->completions && (str_offset_to_pos (in->buffer, in->point)) != end) - free_completions (in); - if (!in->completions){ + free_completions (in); + if (!in->completions) + { 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); - if (strchr (" \t;|<>", in->buffer [start])) { - if (start < end) start = str_offset_to_pos (in->buffer, s + 1); + if (strchr (" \t;|<>", in->buffer[start])) + { + if (start < end) + start = str_offset_to_pos (in->buffer, s + 1); /* FIXME: maybe need check '\\' prev char if (start > 0 && in->buffer [start-1] == '\\') - */ + */ break; } } in->completions = try_complete (in->buffer, &start, &end, in->completion_flags); } - if (in->completions){ - if (what_to_do & DO_INSERTION || ((what_to_do & DO_QUERY) && !in->completions[1])) { - char * lc_complete = in->completions [0]; - if (insert_text (in, lc_complete, strlen (lc_complete))){ - if (in->completions [1]) - tty_beep (); - else - free_completions (in); - } else - tty_beep (); + if (in->completions) + { + if (what_to_do & DO_INSERTION || ((what_to_do & DO_QUERY) && !in->completions[1])) + { + char *lc_complete = in->completions[0]; + if (insert_text (in, lc_complete, strlen (lc_complete))) + { + if (in->completions[1]) + tty_beep (); + else + free_completions (in); + } + else + tty_beep (); } - if ((what_to_do & DO_QUERY) && in->completions && in->completions [1]) { - int maxlen = 0, i, count = 0; - int x, y, w, h; - int start_x, start_y; - char **p, *q; - Dlg_head *query_dlg; - WListbox *query_list; - - for (p=in->completions + 1; *p; count++, p++) - if ((i = str_term_width1 (*p)) > maxlen) - maxlen = i; - start_x = in->widget.x; - start_y = in->widget.y; - if (start_y - 2 >= count) { - y = start_y - 2 - count; - h = 2 + count; - } else { - if (start_y >= LINES - start_y - 1) { - y = 0; - h = start_y; - } else { - y = start_y + 1; - h = LINES - start_y - 1; - } - } - x = start - in->term_first_shown - 2 + start_x; - w = maxlen + 4; - if (x + w > COLS) - x = COLS - w; - if (x < 0) - x = 0; - if (x + w > COLS) - w = COLS; - input = in; - min_end = end; - query_height = h; - query_width = w; - query_dlg = create_dlg (y, x, query_height, query_width, - dialog_colors, query_callback, - "[Completion]", NULL, DLG_COMPACT); - query_list = listbox_new (1, 1, h - 2, w - 2, FALSE, NULL); - add_widget (query_dlg, query_list); - for (p = in->completions + 1; *p; p++) - listbox_add_item (query_list, LISTBOX_APPEND_AT_END, 0, *p, NULL); - run_dlg (query_dlg); - q = NULL; - if (query_dlg->ret_value == B_ENTER){ - listbox_get_current (query_list, &q, NULL); - if (q) - insert_text (in, q, strlen (q)); - } - if (q || end != min_end) - free_completions (in); - i = query_dlg->ret_value; /* B_USER if user wants to start over again */ - destroy_dlg (query_dlg); - if (i == B_USER) - return 1; - } - } else - tty_beep (); + if ((what_to_do & DO_QUERY) && in->completions && in->completions[1]) + { + int maxlen = 0, i, count = 0; + int x, y, w, h; + int start_x, start_y; + char **p, *q; + Dlg_head *query_dlg; + WListbox *query_list; + + for (p = in->completions + 1; *p; count++, p++) + if ((i = str_term_width1 (*p)) > maxlen) + maxlen = i; + start_x = in->widget.x; + start_y = in->widget.y; + if (start_y - 2 >= count) + { + y = start_y - 2 - count; + h = 2 + count; + } + else + { + if (start_y >= LINES - start_y - 1) + { + y = 0; + h = start_y; + } + else + { + y = start_y + 1; + h = LINES - start_y - 1; + } + } + x = start - in->term_first_shown - 2 + start_x; + w = maxlen + 4; + if (x + w > COLS) + x = COLS - w; + if (x < 0) + x = 0; + if (x + w > COLS) + w = COLS; + input = in; + min_end = end; + query_height = h; + query_width = w; + query_dlg = create_dlg (y, x, query_height, query_width, + dialog_colors, query_callback, + "[Completion]", NULL, DLG_COMPACT); + query_list = listbox_new (1, 1, h - 2, w - 2, FALSE, NULL); + add_widget (query_dlg, query_list); + for (p = in->completions + 1; *p; p++) + listbox_add_item (query_list, LISTBOX_APPEND_AT_END, 0, *p, NULL); + run_dlg (query_dlg); + q = NULL; + if (query_dlg->ret_value == B_ENTER) + { + listbox_get_current (query_list, &q, NULL); + if (q) + insert_text (in, q, strlen (q)); + } + if (q || end != min_end) + free_completions (in); + i = query_dlg->ret_value; /* B_USER if user wants to start over again */ + destroy_dlg (query_dlg); + if (i == B_USER) + return 1; + } + } + else + tty_beep (); return 0; } -void complete (WInput *in) +void +complete (WInput * in) { int engine_flags; - if (!str_is_valid_string (in->buffer)) return; + if (!str_is_valid_string (in->buffer)) + return; if (in->completions) - engine_flags = DO_QUERY; + engine_flags = DO_QUERY; else { - engine_flags = DO_INSERTION; + engine_flags = DO_INSERTION; - if (show_all_if_ambiguous) - engine_flags |= DO_QUERY; + if (show_all_if_ambiguous) + engine_flags |= DO_QUERY; } while (complete_engine (in, engine_flags)); diff --git a/src/editor/edit.c b/src/editor/edit.c index a1935695..fadbe262 100644 --- a/src/editor/edit.c +++ b/src/editor/edit.c @@ -19,7 +19,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ + */ /** \file * \brief Source: editor low level data handling and cursor fundamentals @@ -41,21 +41,21 @@ #include "lib/global.h" -#include "lib/tty/color.h" -#include "lib/tty/tty.h" /* attrset() */ -#include "lib/tty/key.h" /* is_idle() */ -#include "lib/skin.h" /* EDITOR_NORMAL_COLOR */ +#include "lib/tty/color.h" +#include "lib/tty/tty.h" /* attrset() */ +#include "lib/tty/key.h" /* is_idle() */ +#include "lib/skin.h" /* EDITOR_NORMAL_COLOR */ #include "lib/vfs/mc-vfs/vfs.h" -#include "lib/strutil.h" /* utf string functions */ +#include "lib/strutil.h" /* utf string functions */ #include "src/widget.h" -#include "src/cmd.h" /* view_other_cmd() */ -#include "src/user.h" /* user_menu_cmd() */ -#include "src/wtools.h" /* query_dialog() */ -#include "lib/timefmt.h" /* time formatting */ -#include "src/charsets.h" /* get_codepage_id */ -#include "src/main.h" /* source_codepage */ -#include "src/learn.h" /* learn_keys */ +#include "src/cmd.h" /* view_other_cmd() */ +#include "src/user.h" /* user_menu_cmd() */ +#include "src/wtools.h" /* query_dialog() */ +#include "lib/timefmt.h" /* time formatting */ +#include "src/charsets.h" /* get_codepage_id */ +#include "src/main.h" /* source_codepage */ +#include "src/learn.h" /* learn_keys */ #include "src/cmddef.h" #include "edit-impl.h" @@ -90,9 +90,10 @@ const char *option_whole_chars_search = "0123456789abcdefghijklmnopqrstuvwxyz_"; char *option_backup_ext = NULL; int edit_stack_iterator = 0; -edit_stack_type edit_history_moveto [MAX_HISTORY_MOVETO]; +edit_stack_type edit_history_moveto[MAX_HISTORY_MOVETO]; /* magic sequense for say than block is vertical */ -const char VERTICAL_MAGIC[] = {'\1', '\1', '\1', '\1', '\n'}; +const char VERTICAL_MAGIC[] = { '\1', '\1', '\1', '\1', '\n' }; + /*- * * here's a quick sketch of the layout: (don't run this through indent.) @@ -124,37 +125,48 @@ const char VERTICAL_MAGIC[] = {'\1', '\1', '\1', '\1', '\n'}; const global_keymap_t *editor_map; const global_keymap_t *editor_x_map; -static void user_menu (WEdit *edit); +static void user_menu (WEdit * edit); -int edit_get_byte (WEdit * edit, long byte_index) +int +edit_get_byte (WEdit * edit, long byte_index) { unsigned long p; if (byte_index >= (edit->curs1 + edit->curs2) || byte_index < 0) - return '\n'; + return '\n'; - if (byte_index >= edit->curs1) { - p = edit->curs1 + edit->curs2 - byte_index - 1; - return edit->buffers2[p >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (p & M_EDIT_BUF_SIZE) - 1]; - } else { - return edit->buffers1[byte_index >> S_EDIT_BUF_SIZE][byte_index & M_EDIT_BUF_SIZE]; + if (byte_index >= edit->curs1) + { + p = edit->curs1 + edit->curs2 - byte_index - 1; + return edit->buffers2[p >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (p & M_EDIT_BUF_SIZE) - 1]; + } + else + { + return edit->buffers1[byte_index >> S_EDIT_BUF_SIZE][byte_index & M_EDIT_BUF_SIZE]; } } -char *edit_get_byte_ptr (WEdit * edit, long byte_index) +char * +edit_get_byte_ptr (WEdit * edit, long byte_index) { unsigned long p; if (byte_index >= (edit->curs1 + edit->curs2) || byte_index < 0) - return NULL; + return NULL; - if (byte_index >= edit->curs1) { - p = edit->curs1 + edit->curs2 - byte_index - 1; - return (char *) (edit->buffers2[p >> S_EDIT_BUF_SIZE]+(EDIT_BUF_SIZE - (p & M_EDIT_BUF_SIZE) - 1)); - } else { - return (char *) (edit->buffers1[byte_index >> S_EDIT_BUF_SIZE]+(byte_index & M_EDIT_BUF_SIZE)); + if (byte_index >= edit->curs1) + { + p = edit->curs1 + edit->curs2 - byte_index - 1; + return (char *) (edit->buffers2[p >> S_EDIT_BUF_SIZE] + + (EDIT_BUF_SIZE - (p & M_EDIT_BUF_SIZE) - 1)); + } + else + { + return (char *) (edit->buffers1[byte_index >> S_EDIT_BUF_SIZE] + + (byte_index & M_EDIT_BUF_SIZE)); } } -char *edit_get_buf_ptr (WEdit * edit, long byte_index) +char * +edit_get_buf_ptr (WEdit * edit, long byte_index) { unsigned long p; @@ -164,15 +176,20 @@ char *edit_get_buf_ptr (WEdit * edit, long byte_index) if (byte_index < 0) return NULL; - if (byte_index >= edit->curs1) { - p = edit->curs1 + edit->curs2 - 1; - return (char *) (edit->buffers2[p >> S_EDIT_BUF_SIZE] + (EDIT_BUF_SIZE - (p & M_EDIT_BUF_SIZE) - 1)); - } else { - return (char *) (edit->buffers1[byte_index >> S_EDIT_BUF_SIZE] + (0 & M_EDIT_BUF_SIZE)); + if (byte_index >= edit->curs1) + { + p = edit->curs1 + edit->curs2 - 1; + return (char *) (edit->buffers2[p >> S_EDIT_BUF_SIZE] + + (EDIT_BUF_SIZE - (p & M_EDIT_BUF_SIZE) - 1)); + } + else + { + return (char *) (edit->buffers1[byte_index >> S_EDIT_BUF_SIZE] + (0 & M_EDIT_BUF_SIZE)); } } -int edit_get_utf (WEdit * edit, long byte_index, int *char_width) +int +edit_get_utf (WEdit * edit, long byte_index, int *char_width) { gchar *str = NULL; int res = -1; @@ -180,30 +197,38 @@ int edit_get_utf (WEdit * edit, long byte_index, int *char_width) gchar *next_ch = NULL; int width = 0; - if (byte_index >= (edit->curs1 + edit->curs2) || byte_index < 0) { + if (byte_index >= (edit->curs1 + edit->curs2) || byte_index < 0) + { *char_width = 0; return '\n'; } str = edit_get_byte_ptr (edit, byte_index); - if (str == NULL) { + if (str == NULL) + { *char_width = 0; return 0; } res = g_utf8_get_char_validated (str, -1); - if (res < 0) { + if (res < 0) + { ch = *str; width = 0; - } else { + } + else + { ch = res; /* Calculate UTF-8 char width */ next_ch = g_utf8_next_char (str); - if (next_ch) { + if (next_ch) + { width = next_ch - str; - } else { + } + else + { ch = 0; width = 0; } @@ -212,7 +237,8 @@ int edit_get_utf (WEdit * edit, long byte_index, int *char_width) return ch; } -int edit_get_prev_utf (WEdit * edit, long byte_index, int *char_width) +int +edit_get_prev_utf (WEdit * edit, long byte_index, int *char_width) { gchar *str, *buf = NULL; int res = -1; @@ -223,21 +249,24 @@ int edit_get_prev_utf (WEdit * edit, long byte_index, int *char_width) if (byte_index > 0) byte_index--; - if (byte_index >= (edit->curs1 + edit->curs2) || byte_index < 0) { + if (byte_index >= (edit->curs1 + edit->curs2) || byte_index < 0) + { *char_width = 0; return 0; } ch = edit_get_utf (edit, byte_index, &width); - if (width == 1) { + if (width == 1) + { *char_width = width; return ch; } str = edit_get_byte_ptr (edit, byte_index); buf = edit_get_buf_ptr (edit, byte_index); - if (str == NULL || buf == NULL) { + if (str == NULL || buf == NULL) + { *char_width = 0; return 0; } @@ -247,16 +276,22 @@ int edit_get_prev_utf (WEdit * edit, long byte_index, int *char_width) res = g_utf8_get_char_validated (str, -1); - if (res < 0) { + if (res < 0) + { ch = *str; width = 0; - } else { + } + else + { ch = res; /* Calculate UTF-8 char width */ - next_ch = g_utf8_next_char(str); - if (next_ch) { + next_ch = g_utf8_next_char (str); + if (next_ch) + { width = next_ch - str; - } else { + } + else + { ch = 0; width = 0; } @@ -269,13 +304,14 @@ int edit_get_prev_utf (WEdit * edit, long byte_index, int *char_width) * Initialize the buffers for an empty files. */ static void -edit_init_buffers (WEdit *edit) +edit_init_buffers (WEdit * edit) { int j; - for (j = 0; j <= MAXBUFF; j++) { - edit->buffers1[j] = NULL; - edit->buffers2[j] = NULL; + for (j = 0; j <= MAXBUFF; j++) + { + edit->buffers1[j] = NULL; + edit->buffers2[j] = NULL; } edit->curs1 = 0; @@ -288,34 +324,35 @@ edit_init_buffers (WEdit *edit) * Return 1 on error. */ static int -edit_load_file_fast (WEdit *edit, const char *filename) +edit_load_file_fast (WEdit * edit, const char *filename) { long buf, buf2; int file = -1; edit->curs2 = edit->last_byte; buf2 = edit->curs2 >> S_EDIT_BUF_SIZE; edit->utf8 = 0; - if ((file = mc_open (filename, O_RDONLY | O_BINARY)) == -1) { - GString *errmsg = g_string_new(NULL); - g_string_sprintf(errmsg, _(" Cannot open %s for reading "), filename); - edit_error_dialog (_("Error"), get_sys_error (errmsg->str)); - g_string_free (errmsg, TRUE); - return 1; + if ((file = mc_open (filename, O_RDONLY | O_BINARY)) == -1) + { + GString *errmsg = g_string_new (NULL); + g_string_sprintf (errmsg, _(" Cannot open %s for reading "), filename); + edit_error_dialog (_("Error"), get_sys_error (errmsg->str)); + g_string_free (errmsg, TRUE); + return 1; } if (!edit->buffers2[buf2]) - edit->buffers2[buf2] = g_malloc0 (EDIT_BUF_SIZE); + edit->buffers2[buf2] = g_malloc0 (EDIT_BUF_SIZE); mc_read (file, - (char *) edit->buffers2[buf2] + EDIT_BUF_SIZE - - (edit->curs2 & M_EDIT_BUF_SIZE), - edit->curs2 & M_EDIT_BUF_SIZE); + (char *) edit->buffers2[buf2] + EDIT_BUF_SIZE - + (edit->curs2 & M_EDIT_BUF_SIZE), edit->curs2 & M_EDIT_BUF_SIZE); - for (buf = buf2 - 1; buf >= 0; buf--) { - /* edit->buffers2[0] is already allocated */ - if (!edit->buffers2[buf]) - edit->buffers2[buf] = g_malloc0 (EDIT_BUF_SIZE); - mc_read (file, (char *) edit->buffers2[buf], EDIT_BUF_SIZE); + for (buf = buf2 - 1; buf >= 0; buf--) + { + /* edit->buffers2[0] is already allocated */ + if (!edit->buffers2[buf]) + edit->buffers2[buf] = g_malloc0 (EDIT_BUF_SIZE); + mc_read (file, (char *) edit->buffers2[buf], EDIT_BUF_SIZE); } mc_close (file); @@ -326,30 +363,36 @@ edit_load_file_fast (WEdit *edit, const char *filename) /* detecting an error on read, is not so easy 'cos there is not way to tell whether you read everything or not. */ /* FIXME: add proper `triple_pipe_open' to read, write and check errors. */ -static const struct edit_filters { +static const struct edit_filters +{ const char *read, *write, *extension; -} all_filters[] = { - { "xz -cd %s 2>&1", "xz > %s", ".xz" }, - { "lzma -cd %s 2>&1", "lzma > %s", ".lzma" }, - { "bzip2 -cd %s 2>&1", "bzip2 > %s", ".bz2" }, - { "gzip -cd %s 2>&1", "gzip > %s", ".gz" }, - { "gzip -cd %s 2>&1", "gzip > %s", ".Z" } +} all_filters[] = +{ + /* *INDENT-OFF* */ + { "xz -cd %s 2>&1", "xz > %s", ".xz"}, + { "lzma -cd %s 2>&1", "lzma > %s", ".lzma" }, + { "bzip2 -cd %s 2>&1", "bzip2 > %s", ".bz2" }, + { "gzip -cd %s 2>&1", "gzip > %s", ".gz" }, + { "gzip -cd %s 2>&1", "gzip > %s", ".Z" } + /* *INDENT-ON* */ }; /* Return index of the filter or -1 is there is no appropriate filter */ -static int edit_find_filter (const char *filename) +static int +edit_find_filter (const char *filename) { size_t i, l, e; if (filename == NULL) - return -1; + return -1; l = strlen (filename); - for (i = 0; i < sizeof (all_filters) / sizeof (all_filters[0]); i++) { - e = strlen (all_filters[i].extension); - if (l > e) - if (!strcmp (all_filters[i].extension, filename + l - e)) - return i; + for (i = 0; i < sizeof (all_filters) / sizeof (all_filters[0]); i++) + { + e = strlen (all_filters[i].extension); + if (l > e) + if (!strcmp (all_filters[i].extension, filename + l - e)) + return i; } return -1; } @@ -362,10 +405,10 @@ edit_get_filter (const char *filename) i = edit_find_filter (filename); if (i < 0) - return NULL; + return NULL; quoted_name = name_quote (filename, 0); - p = g_strdup_printf(all_filters[i].read, quoted_name); + p = g_strdup_printf (all_filters[i].read, quoted_name); g_free (quoted_name); return p; } @@ -378,10 +421,10 @@ edit_get_write_filter (const char *write_name, const char *filename) i = edit_find_filter (filename); if (i < 0) - return NULL; + return NULL; writename = name_quote (write_name, 0); - p = g_strdup_printf(all_filters[i].write, writename); + p = g_strdup_printf (all_filters[i].write, writename); g_free (writename); return p; } @@ -391,93 +434,103 @@ edit_insert_stream (WEdit * edit, FILE * f) { int c; long i = 0; - while ((c = fgetc (f)) >= 0) { - edit_insert (edit, c); - i++; + while ((c = fgetc (f)) >= 0) + { + edit_insert (edit, c); + i++; } return i; } -long edit_write_stream (WEdit * edit, FILE * f) +long +edit_write_stream (WEdit * edit, FILE * f) { long i; - if (edit->lb == LB_ASIS) { - for (i = 0; i < edit->last_byte; i++) - if (fputc (edit_get_byte (edit, i), f) < 0) - break; - return i; + if (edit->lb == LB_ASIS) + { + for (i = 0; i < edit->last_byte; i++) + if (fputc (edit_get_byte (edit, i), f) < 0) + break; + return i; } /* change line breaks */ - for (i = 0; i < edit->last_byte; i++) { - unsigned char c = edit_get_byte (edit, i); - - if (!(c == '\n' || c == '\r')) { - /* not line break */ - if (fputc (c, f) < 0) - return i; - } else { /* (c == '\n' || c == '\r') */ - unsigned char c1 = edit_get_byte (edit, i + 1); /* next char */ - - switch (edit->lb) { - case LB_UNIX: /* replace "\r\n" or '\r' to '\n' */ - /* put one line break unconditionally */ - if (fputc ('\n', f) < 0) - return i; - - i++; /* 2 chars are processed */ - - if (c == '\r' && c1 == '\n') - /* Windows line break; go to the next char */ - break; - - if (c == '\r' && c1 == '\r') { - /* two Macintosh line breaks; put second line break */ - if (fputc ('\n', f) < 0) - return i; - break; - } - - if (fputc (c1, f) < 0) - return i; - break; - - case LB_WIN: /* replace '\n' or '\r' to "\r\n" */ - /* put one line break unconditionally */ - if (fputc ('\r', f) < 0 || fputc ('\n', f) < 0) - return i; - - if (c == '\r' && c1 == '\n') - /* Windows line break; go to the next char */ - i++; - break; - - case LB_MAC: /* replace "\r\n" or '\n' to '\r' */ - /* put one line break unconditionally */ - if (fputc ('\r', f) < 0) - return i; - - i++; /* 2 chars are processed */ - - if (c == '\r' && c1 == '\n') - /* Windows line break; go to the next char */ - break; - - if (c == '\n' && c1 == '\n') { - /* two Windows line breaks; put second line break */ - if (fputc ('\r', f) < 0) - return i; - break; - } - - if (fputc (c1, f) < 0) - return i; - break; - case LB_ASIS: /* default without changes */ - break; - } - } + for (i = 0; i < edit->last_byte; i++) + { + unsigned char c = edit_get_byte (edit, i); + + if (!(c == '\n' || c == '\r')) + { + /* not line break */ + if (fputc (c, f) < 0) + return i; + } + else + { /* (c == '\n' || c == '\r') */ + unsigned char c1 = edit_get_byte (edit, i + 1); /* next char */ + + switch (edit->lb) + { + case LB_UNIX: /* replace "\r\n" or '\r' to '\n' */ + /* put one line break unconditionally */ + if (fputc ('\n', f) < 0) + return i; + + i++; /* 2 chars are processed */ + + if (c == '\r' && c1 == '\n') + /* Windows line break; go to the next char */ + break; + + if (c == '\r' && c1 == '\r') + { + /* two Macintosh line breaks; put second line break */ + if (fputc ('\n', f) < 0) + return i; + break; + } + + if (fputc (c1, f) < 0) + return i; + break; + + case LB_WIN: /* replace '\n' or '\r' to "\r\n" */ + /* put one line break unconditionally */ + if (fputc ('\r', f) < 0 || fputc ('\n', f) < 0) + return i; + + if (c == '\r' && c1 == '\n') + /* Windows line break; go to the next char */ + i++; + break; + + case LB_MAC: /* replace "\r\n" or '\n' to '\r' */ + /* put one line break unconditionally */ + if (fputc ('\r', f) < 0) + return i; + + i++; /* 2 chars are processed */ + + if (c == '\r' && c1 == '\n') + /* Windows line break; go to the next char */ + break; + + if (c == '\n' && c1 == '\n') + { + /* two Windows line breaks; put second line break */ + if (fputc ('\r', f) < 0) + return i; + break; + } + + if (fputc (c1, f) < 0) + return i; + break; + case LB_ASIS: /* default without changes */ + break; + } + } } return edit->last_byte; @@ -487,72 +540,87 @@ long edit_write_stream (WEdit * edit, FILE * f) /* inserts a file at the cursor, returns 1 on success */ int -edit_insert_file (WEdit *edit, const char *filename) +edit_insert_file (WEdit * edit, const char *filename) { char *p; p = edit_get_filter (filename); - if (p != NULL) { - FILE *f; - long current = edit->curs1; - f = (FILE *) popen (p, "r"); - if (f != NULL) { - edit_insert_stream (edit, f); - edit_cursor_move (edit, current - edit->curs1); - if (pclose (f) > 0) { - char *errmsg; - errmsg = g_strdup_printf(_(" Error reading from pipe: %s "), p); - edit_error_dialog (_("Error"), errmsg); - g_free (errmsg); - g_free (p); - return 0; - } - } else { - char *errmsg; - errmsg = g_strdup_printf (_(" Cannot open pipe for reading: %s "), p); - edit_error_dialog (_("Error"), errmsg); - g_free (errmsg); - g_free (p); - return 0; - } - g_free (p); - } else { - int i, file, blocklen; - long current = edit->curs1; - int vertical_insertion = 0; - char *buf; - if ((file = mc_open (filename, O_RDONLY | O_BINARY)) == -1) - return 0; - buf = g_malloc0 (TEMP_BUF_LEN); - blocklen = mc_read (file, buf, sizeof(VERTICAL_MAGIC)); - if (blocklen > 0) { + if (p != NULL) + { + FILE *f; + long current = edit->curs1; + f = (FILE *) popen (p, "r"); + if (f != NULL) + { + edit_insert_stream (edit, f); + edit_cursor_move (edit, current - edit->curs1); + if (pclose (f) > 0) + { + char *errmsg; + errmsg = g_strdup_printf (_(" Error reading from pipe: %s "), p); + edit_error_dialog (_("Error"), errmsg); + g_free (errmsg); + g_free (p); + return 0; + } + } + else + { + char *errmsg; + errmsg = g_strdup_printf (_(" Cannot open pipe for reading: %s "), p); + edit_error_dialog (_("Error"), errmsg); + g_free (errmsg); + g_free (p); + return 0; + } + g_free (p); + } + else + { + int i, file, blocklen; + long current = edit->curs1; + int vertical_insertion = 0; + char *buf; + if ((file = mc_open (filename, O_RDONLY | O_BINARY)) == -1) + return 0; + buf = g_malloc0 (TEMP_BUF_LEN); + blocklen = mc_read (file, buf, sizeof (VERTICAL_MAGIC)); + if (blocklen > 0) + { /* if contain signature VERTICAL_MAGIC tnen it vertical block */ - if ( memcmp(buf, VERTICAL_MAGIC, sizeof(VERTICAL_MAGIC)) == 0 ) { + if (memcmp (buf, VERTICAL_MAGIC, sizeof (VERTICAL_MAGIC)) == 0) + { vertical_insertion = 1; - } else { + } + else + { mc_lseek (file, 0, SEEK_SET); } } - if (vertical_insertion) { + if (vertical_insertion) + { blocklen = edit_insert_column_of_text_from_file (edit, file); - } else { - while ((blocklen = mc_read (file, (char *) buf, TEMP_BUF_LEN)) > 0) { + } + else + { + while ((blocklen = mc_read (file, (char *) buf, TEMP_BUF_LEN)) > 0) + { for (i = 0; i < blocklen; i++) edit_insert (edit, buf[i]); } - } - edit_cursor_move (edit, current - edit->curs1); - g_free (buf); - mc_close (file); - if (blocklen) - return 0; + } + edit_cursor_move (edit, current - edit->curs1); + g_free (buf); + mc_close (file); + if (blocklen) + return 0; } return 1; } /* Open file and create it if necessary. Return 0 for success, 1 for error. */ static int -check_file_access (WEdit *edit, const char *filename, struct stat *st) +check_file_access (WEdit * edit, const char *filename, struct stat *st) { int file; GString *errmsg = (GString *) 0; @@ -560,58 +628,62 @@ check_file_access (WEdit *edit, const char *filename, struct stat *st) /* Try opening an existing file */ file = mc_open (filename, O_NONBLOCK | O_RDONLY | O_BINARY, 0666); - if (file < 0) { - /* - * Try creating the file. O_EXCL prevents following broken links - * and opening existing files. - */ - file = - mc_open (filename, - O_NONBLOCK | O_RDONLY | O_BINARY | O_CREAT | O_EXCL, - 0666); - if (file < 0) { - g_string_sprintf (errmsg = g_string_new (NULL), - _(" Cannot open %s for reading "), filename); - goto cleanup; - } else { - /* New file, delete it if it's not modified or saved */ - edit->delete_file = 1; - } + if (file < 0) + { + /* + * Try creating the file. O_EXCL prevents following broken links + * and opening existing files. + */ + file = mc_open (filename, O_NONBLOCK | O_RDONLY | O_BINARY | O_CREAT | O_EXCL, 0666); + if (file < 0) + { + g_string_sprintf (errmsg = g_string_new (NULL), + _(" Cannot open %s for reading "), filename); + goto cleanup; + } + else + { + /* New file, delete it if it's not modified or saved */ + edit->delete_file = 1; + } } /* Check what we have opened */ - if (mc_fstat (file, st) < 0) { - g_string_sprintf (errmsg = g_string_new (NULL), - _(" Cannot get size/permissions for %s "), filename); - goto cleanup; + if (mc_fstat (file, st) < 0) + { + g_string_sprintf (errmsg = g_string_new (NULL), + _(" Cannot get size/permissions for %s "), filename); + goto cleanup; } /* We want to open regular files only */ - if (!S_ISREG (st->st_mode)) { - g_string_sprintf (errmsg = g_string_new (NULL), - _(" %s is not a regular file "), filename); - goto cleanup; + if (!S_ISREG (st->st_mode)) + { + g_string_sprintf (errmsg = g_string_new (NULL), _(" %s is not a regular file "), filename); + goto cleanup; } /* * Don't delete non-empty files. * O_EXCL should prevent it, but let's be on the safe side. */ - if (st->st_size > 0) { - edit->delete_file = 0; + if (st->st_size > 0) + { + edit->delete_file = 0; } - if (st->st_size >= SIZE_LIMIT) { - g_string_sprintf (errmsg = g_string_new (NULL), - _(" File %s is too large "), filename); + if (st->st_size >= SIZE_LIMIT) + { + g_string_sprintf (errmsg = g_string_new (NULL), _(" File %s is too large "), filename); } -cleanup: + cleanup: (void) mc_close (file); - if (errmsg) { - edit_error_dialog (_("Error"), errmsg->str); - g_string_free (errmsg, TRUE); - return 1; + if (errmsg) + { + edit_error_dialog (_("Error"), errmsg->str); + g_string_free (errmsg, TRUE); + return 1; } return 0; } @@ -626,60 +698,68 @@ cleanup: * edit_insert_file. */ static int -edit_load_file (WEdit *edit) +edit_load_file (WEdit * edit) { int fast_load = 1; /* Cannot do fast load if a filter is used */ if (edit_find_filter (edit->filename) >= 0) - fast_load = 0; + fast_load = 0; /* * VFS may report file size incorrectly, and slow load is not a big * deal considering overhead in VFS. */ if (!vfs_file_is_local (edit->filename)) - fast_load = 0; + fast_load = 0; /* * FIXME: line end translation should disable fast loading as well * Consider doing fseek() to the end and ftell() for the real size. */ - if (*edit->filename) { - /* If we are dealing with a real file, check that it exists */ - if (check_file_access (edit, edit->filename, &edit->stat1)) - return 1; - } else { - /* nothing to load */ - fast_load = 0; + if (*edit->filename) + { + /* If we are dealing with a real file, check that it exists */ + if (check_file_access (edit, edit->filename, &edit->stat1)) + return 1; + } + else + { + /* nothing to load */ + fast_load = 0; } edit_init_buffers (edit); - if (fast_load) { - edit->last_byte = edit->stat1.st_size; - edit_load_file_fast (edit, edit->filename); - /* If fast load was used, the number of lines wasn't calculated */ - edit->total_lines = edit_count_lines (edit, 0, edit->last_byte); - } else { + if (fast_load) + { + edit->last_byte = edit->stat1.st_size; + edit_load_file_fast (edit, edit->filename); + /* If fast load was used, the number of lines wasn't calculated */ + edit->total_lines = edit_count_lines (edit, 0, edit->last_byte); + } + else + { #ifdef HAVE_CHARSET - const char *codepage_id; + const char *codepage_id; #endif - edit->last_byte = 0; - if (*edit->filename) { - edit->stack_disable = 1; - if (!edit_insert_file (edit, edit->filename)) { - edit_clean (edit); - return 1; - } - edit->stack_disable = 0; - } + edit->last_byte = 0; + if (*edit->filename) + { + edit->stack_disable = 1; + if (!edit_insert_file (edit, edit->filename)) + { + edit_clean (edit); + return 1; + } + edit->stack_disable = 0; + } #ifdef HAVE_CHARSET - codepage_id = get_codepage_id( source_codepage ); - if ( codepage_id ) - edit->utf8 = str_isutf8 ( codepage_id ); + codepage_id = get_codepage_id (source_codepage); + if (codepage_id) + edit->utf8 = str_isutf8 (codepage_id); #endif } edit->lb = LB_ASIS; @@ -688,23 +768,26 @@ edit_load_file (WEdit *edit) /* Restore saved cursor position in the file */ static void -edit_load_position (WEdit *edit) +edit_load_position (WEdit * edit) { char *filename; long line, column; off_t offset; if (!edit->filename || !*edit->filename) - return; + return; filename = vfs_canon (edit->filename); load_file_position (filename, &line, &column, &offset); g_free (filename); - if (line > 0) { + if (line > 0) + { edit_move_to_line (edit, line - 1); edit->prev_col = column; - } else if (offset > 0) { + } + else if (offset > 0) + { edit_cursor_move (edit, offset); line = edit->curs_line; } @@ -714,12 +797,12 @@ edit_load_position (WEdit *edit) /* Save cursor position in the file */ static void -edit_save_position (WEdit *edit) +edit_save_position (WEdit * edit) { char *filename; if (!edit->filename || !*edit->filename) - return; + return; filename = vfs_canon (edit->filename); save_file_position (filename, edit->curs_line + 1, edit->curs_col, edit->curs1); @@ -728,12 +811,12 @@ edit_save_position (WEdit *edit) /* Clean the WEdit stricture except the widget part */ static void -edit_purge_widget (WEdit *edit) +edit_purge_widget (WEdit * edit) { size_t len = sizeof (WEdit) - sizeof (Widget); char *start = (char *) edit + sizeof (Widget); memset (start, 0, len); - edit->macro_i = -1; /* not recording a macro */ + edit->macro_i = -1; /* not recording a macro */ } static void @@ -741,11 +824,11 @@ edit_set_keymap (void) { editor_map = default_editor_keymap; if (editor_keymap && editor_keymap->len > 0) - editor_map = (global_keymap_t *) editor_keymap->data; + editor_map = (global_keymap_t *) editor_keymap->data; editor_x_map = default_editor_x_keymap; if (editor_x_keymap && editor_x_keymap->len > 0) - editor_x_map = (global_keymap_t *) editor_x_keymap->data; + editor_x_map = (global_keymap_t *) editor_x_keymap->data; } @@ -759,45 +842,50 @@ edit_set_keymap (void) * cursor on that line and show it in the middle of the screen. */ WEdit * -edit_init (WEdit *edit, int lines, int columns, const char *filename, - long line) +edit_init (WEdit * edit, int lines, int columns, const char *filename, long line) { int to_free = 0; - option_auto_syntax = 1; /* Resetting to auto on every invokation */ - if ( option_line_state ) { + option_auto_syntax = 1; /* Resetting to auto on every invokation */ + if (option_line_state) + { option_line_state_width = LINE_STATE_WIDTH; - } else { + } + else + { option_line_state_width = 0; } - if (!edit) { + if (!edit) + { #ifdef ENABLE_NLS - /* - * Expand option_whole_chars_search by national letters using - * current locale - */ - - static char option_whole_chars_search_buf[256]; - - if (option_whole_chars_search_buf != option_whole_chars_search) { - size_t i; - size_t len = str_term_width1 (option_whole_chars_search); - - strcpy (option_whole_chars_search_buf, - option_whole_chars_search); - - for (i = 1; i <= sizeof (option_whole_chars_search_buf); i++) { - if (g_ascii_islower ((gchar) i) && !strchr (option_whole_chars_search, i)) { - option_whole_chars_search_buf[len++] = i; - } - } - - option_whole_chars_search_buf[len] = 0; - option_whole_chars_search = option_whole_chars_search_buf; - } -#endif /* ENABLE_NLS */ - edit = g_malloc0 (sizeof (WEdit)); - edit->search = NULL; - to_free = 1; + /* + * Expand option_whole_chars_search by national letters using + * current locale + */ + + static char option_whole_chars_search_buf[256]; + + if (option_whole_chars_search_buf != option_whole_chars_search) + { + size_t i; + size_t len = str_term_width1 (option_whole_chars_search); + + strcpy (option_whole_chars_search_buf, option_whole_chars_search); + + for (i = 1; i <= sizeof (option_whole_chars_search_buf); i++) + { + if (g_ascii_islower ((gchar) i) && !strchr (option_whole_chars_search, i)) + { + option_whole_chars_search_buf[len++] = i; + } + } + + option_whole_chars_search_buf[len] = 0; + option_whole_chars_search = option_whole_chars_search_buf; + } +#endif /* ENABLE_NLS */ + edit = g_malloc0 (sizeof (WEdit)); + edit->search = NULL; + to_free = 1; } edit_purge_widget (edit); edit->num_widget_lines = lines; @@ -813,31 +901,33 @@ edit_init (WEdit *edit, int lines, int columns, const char *filename, edit->stack_size = START_STACK_SIZE; edit->stack_size_mask = START_STACK_SIZE - 1; edit->undo_stack = g_malloc0 ((edit->stack_size + 10) * sizeof (long)); - if (edit_load_file (edit)) { - /* edit_load_file already gives an error message */ - if (to_free) - g_free (edit); - return 0; + if (edit_load_file (edit)) + { + /* edit_load_file already gives an error message */ + if (to_free) + g_free (edit); + return 0; } edit->utf8 = 0; edit->converter = str_cnv_from_term; #ifdef HAVE_CHARSET { - const char *cp_id = NULL; - cp_id = get_codepage_id (source_codepage >= 0 ? - source_codepage : display_codepage); - - if (cp_id != NULL) { - GIConv conv; - conv = str_crt_conv_from (cp_id); - if (conv != INVALID_CONV) { - if (edit->converter != str_cnv_from_term) - str_close_conv (edit->converter); - edit->converter = conv; + const char *cp_id = NULL; + cp_id = get_codepage_id (source_codepage >= 0 ? source_codepage : display_codepage); + + if (cp_id != NULL) + { + GIConv conv; + conv = str_crt_conv_from (cp_id); + if (conv != INVALID_CONV) + { + if (edit->converter != str_cnv_from_term) + str_close_conv (edit->converter); + edit->converter = conv; + } } - } - if (cp_id != NULL) - edit->utf8 = str_isutf8 (cp_id); + if (cp_id != NULL) + edit->utf8 = str_isutf8 (cp_id); } #endif @@ -846,18 +936,21 @@ edit_init (WEdit *edit, int lines, int columns, const char *filename, edit->locked = 0; edit_load_syntax (edit, 0, 0); { - int color; - edit_get_syntax_color (edit, -1, &color); + int color; + edit_get_syntax_color (edit, -1, &color); } /* load saved cursor position */ - if ((line == 0) && option_save_position) { - edit_load_position (edit); - } else { - if (line <= 0) - line = 1; - edit_move_display (edit, line - 1); - edit_move_to_line (edit, line - 1); + if ((line == 0) && option_save_position) + { + edit_load_position (edit); + } + else + { + if (line <= 0) + line = 1; + edit_move_display (edit, line - 1); + edit_move_to_line (edit, line - 1); } edit_set_keymap (); @@ -867,30 +960,31 @@ edit_init (WEdit *edit, int lines, int columns, const char *filename, /* Clear the edit struct, freeing everything in it. Return 1 on success */ int -edit_clean (WEdit *edit) +edit_clean (WEdit * edit) { int j = 0; if (!edit) - return 0; + return 0; /* a stale lock, remove it */ if (edit->locked) - edit->locked = edit_unlock_file (edit->filename); + edit->locked = edit_unlock_file (edit->filename); /* save cursor position */ if (option_save_position) - edit_save_position (edit); + edit_save_position (edit); /* File specified on the mcedit command line and never saved */ if (edit->delete_file) - unlink (edit->filename); + unlink (edit->filename); edit_free_syntax_rules (edit); book_mark_flush (edit, -1); - for (; j <= MAXBUFF; j++) { - g_free (edit->buffers1[j]); - g_free (edit->buffers2[j]); + for (; j <= MAXBUFF; j++) + { + g_free (edit->buffers1[j]); + g_free (edit->buffers2[j]); } g_free (edit->undo_stack); @@ -926,7 +1020,7 @@ edit_renew (WEdit * edit) * Return 1 on success, 0 on failure. */ int -edit_reload (WEdit *edit, const char *filename) +edit_reload (WEdit * edit, const char *filename) { WEdit *e; int lines = edit->num_widget_lines; @@ -934,9 +1028,10 @@ edit_reload (WEdit *edit, const char *filename) e = g_malloc0 (sizeof (WEdit)); e->widget = edit->widget; - if (!edit_init (e, lines, columns, filename, 0)) { - g_free (e); - return 0; + if (!edit_init (e, lines, columns, filename, 0)) + { + g_free (e); + return 0; } edit_clean (edit); memcpy (edit, e, sizeof (WEdit)); @@ -951,7 +1046,7 @@ edit_reload (WEdit *edit, const char *filename) * Return 1 on success, 0 on failure. */ int -edit_reload_line (WEdit *edit, const char *filename, long line) +edit_reload_line (WEdit * edit, const char *filename, long line) { WEdit *e; int lines = edit->num_widget_lines; @@ -959,9 +1054,10 @@ edit_reload_line (WEdit *edit, const char *filename, long line) e = g_malloc0 (sizeof (WEdit)); e->widget = edit->widget; - if (!edit_init (e, lines, columns, filename, line)) { - g_free (e); - return 0; + if (!edit_init (e, lines, columns, filename, line)) + { + g_free (e); + return 0; } edit_clean (edit); memcpy (edit, e, sizeof (WEdit)); @@ -979,7 +1075,7 @@ edit_reload_line (WEdit *edit, const char *filename, long line) eg: - pushed: stored: + pushed: stored: a b a @@ -1008,81 +1104,94 @@ edit_reload_line (WEdit *edit, const char *filename, long line) over KEY_PRESS. We then assign this number less KEY_PRESS to start_display. So undo tracks scrolling and key actions exactly. (KEY_PRESS is about (2^31) * (2/3) = 1400'000'000) -*/ + */ -void edit_push_action (WEdit * edit, long c,...) +void +edit_push_action (WEdit * edit, long c, ...) { unsigned long sp = edit->stack_pointer; unsigned long spm1; long *t; -/* first enlarge the stack if necessary */ - if (sp > edit->stack_size - 10) { /* say */ - if (option_max_undo < 256) - option_max_undo = 256; - if (edit->stack_size < (unsigned long) option_max_undo) { - t = g_realloc (edit->undo_stack, (edit->stack_size * 2 + 10) * sizeof (long)); - if (t) { - edit->undo_stack = t; - edit->stack_size <<= 1; - edit->stack_size_mask = edit->stack_size - 1; - } - } + /* first enlarge the stack if necessary */ + if (sp > edit->stack_size - 10) + { /* say */ + if (option_max_undo < 256) + option_max_undo = 256; + if (edit->stack_size < (unsigned long) option_max_undo) + { + t = g_realloc (edit->undo_stack, (edit->stack_size * 2 + 10) * sizeof (long)); + if (t) + { + edit->undo_stack = t; + edit->stack_size <<= 1; + edit->stack_size_mask = edit->stack_size - 1; + } + } } spm1 = (edit->stack_pointer - 1) & edit->stack_size_mask; if (edit->stack_disable) - return; + return; #ifdef FAST_MOVE_CURSOR - if (c == CURS_LEFT_LOTS || c == CURS_RIGHT_LOTS) { - va_list ap; - edit->undo_stack[sp] = c == CURS_LEFT_LOTS ? CURS_LEFT : CURS_RIGHT; - edit->stack_pointer = (edit->stack_pointer + 1) & edit->stack_size_mask; - va_start (ap, c); - c = -(va_arg (ap, int)); - va_end (ap); - } else -#endif /* ! FAST_MOVE_CURSOR */ + if (c == CURS_LEFT_LOTS || c == CURS_RIGHT_LOTS) + { + va_list ap; + edit->undo_stack[sp] = c == CURS_LEFT_LOTS ? CURS_LEFT : CURS_RIGHT; + edit->stack_pointer = (edit->stack_pointer + 1) & edit->stack_size_mask; + va_start (ap, c); + c = -(va_arg (ap, int)); + va_end (ap); + } + else +#endif /* ! FAST_MOVE_CURSOR */ if (edit->stack_bottom != sp - && spm1 != edit->stack_bottom - && ((sp - 2) & edit->stack_size_mask) != edit->stack_bottom) { - int d; - if (edit->undo_stack[spm1] < 0) { - d = edit->undo_stack[(sp - 2) & edit->stack_size_mask]; - if (d == c) { - if (edit->undo_stack[spm1] > -1000000000) { - if (c < KEY_PRESS) /* --> no need to push multiple do-nothings */ - edit->undo_stack[spm1]--; - return; - } - } -/* #define NO_STACK_CURSMOVE_ANIHILATION */ + && spm1 != edit->stack_bottom + && ((sp - 2) & edit->stack_size_mask) != edit->stack_bottom) + { + int d; + if (edit->undo_stack[spm1] < 0) + { + d = edit->undo_stack[(sp - 2) & edit->stack_size_mask]; + if (d == c) + { + if (edit->undo_stack[spm1] > -1000000000) + { + if (c < KEY_PRESS) /* --> no need to push multiple do-nothings */ + edit->undo_stack[spm1]--; + return; + } + } + /* #define NO_STACK_CURSMOVE_ANIHILATION */ #ifndef NO_STACK_CURSMOVE_ANIHILATION - else if ((c == CURS_LEFT && d == CURS_RIGHT) - || (c == CURS_RIGHT && d == CURS_LEFT)) { /* a left then a right anihilate each other */ - if (edit->undo_stack[spm1] == -2) - edit->stack_pointer = spm1; - else - edit->undo_stack[spm1]++; - return; - } + else if ((c == CURS_LEFT && d == CURS_RIGHT) || (c == CURS_RIGHT && d == CURS_LEFT)) + { /* a left then a right anihilate each other */ + if (edit->undo_stack[spm1] == -2) + edit->stack_pointer = spm1; + else + edit->undo_stack[spm1]++; + return; + } #endif - } else { - d = edit->undo_stack[spm1]; - if (d == c) { - if (c >= KEY_PRESS) - return; /* --> no need to push multiple do-nothings */ - edit->undo_stack[sp] = -2; - goto check_bottom; - } + } + else + { + d = edit->undo_stack[spm1]; + if (d == c) + { + if (c >= KEY_PRESS) + return; /* --> no need to push multiple do-nothings */ + edit->undo_stack[sp] = -2; + goto check_bottom; + } #ifndef NO_STACK_CURSMOVE_ANIHILATION - else if ((c == CURS_LEFT && d == CURS_RIGHT) - || (c == CURS_RIGHT && d == CURS_LEFT)) { /* a left then a right anihilate each other */ - edit->stack_pointer = spm1; - return; - } + else if ((c == CURS_LEFT && d == CURS_RIGHT) || (c == CURS_RIGHT && d == CURS_LEFT)) + { /* a left then a right anihilate each other */ + edit->stack_pointer = spm1; + return; + } #endif - } + } } edit->undo_stack[sp] = c; @@ -1094,14 +1203,18 @@ void edit_push_action (WEdit * edit, long c,...) * stack_bottom forward one "key press" */ c = (edit->stack_pointer + 2) & edit->stack_size_mask; if ((unsigned long) c == edit->stack_bottom || - (((unsigned long) c + 1) & edit->stack_size_mask) == edit->stack_bottom) - do { - edit->stack_bottom = (edit->stack_bottom + 1) & edit->stack_size_mask; - } while (edit->undo_stack[edit->stack_bottom] < KEY_PRESS && edit->stack_bottom != edit->stack_pointer); + (((unsigned long) c + 1) & edit->stack_size_mask) == edit->stack_bottom) + do + { + edit->stack_bottom = (edit->stack_bottom + 1) & edit->stack_size_mask; + } + while (edit->undo_stack[edit->stack_bottom] < KEY_PRESS + && edit->stack_bottom != edit->stack_pointer); -/*If a single key produced enough pushes to wrap all the way round then we would notice that the [stack_bottom] does not contain KEY_PRESS. The stack is then initialised: */ - if (edit->stack_pointer != edit->stack_bottom && edit->undo_stack[edit->stack_bottom] < KEY_PRESS) - edit->stack_bottom = edit->stack_pointer = 0; + /*If a single key produced enough pushes to wrap all the way round then we would notice that the [stack_bottom] does not contain KEY_PRESS. The stack is then initialised: */ + if (edit->stack_pointer != edit->stack_bottom + && edit->undo_stack[edit->stack_bottom] < KEY_PRESS) + edit->stack_bottom = edit->stack_pointer = 0; } /* @@ -1113,37 +1226,43 @@ pop_action (WEdit * edit) { long c; unsigned long sp = edit->stack_pointer; - if (sp == edit->stack_bottom) { - return STACK_BOTTOM; + if (sp == edit->stack_bottom) + { + return STACK_BOTTOM; } sp = (sp - 1) & edit->stack_size_mask; - if ((c = edit->undo_stack[sp]) >= 0) { -/* edit->undo_stack[sp] = '@'; */ - edit->stack_pointer = (edit->stack_pointer - 1) & edit->stack_size_mask; - return c; + if ((c = edit->undo_stack[sp]) >= 0) + { + /* edit->undo_stack[sp] = '@'; */ + edit->stack_pointer = (edit->stack_pointer - 1) & edit->stack_size_mask; + return c; } - if (sp == edit->stack_bottom) { - return STACK_BOTTOM; + if (sp == edit->stack_bottom) + { + return STACK_BOTTOM; } c = edit->undo_stack[(sp - 1) & edit->stack_size_mask]; - if (edit->undo_stack[sp] == -2) { -/* edit->undo_stack[sp] = '@'; */ - edit->stack_pointer = sp; - } else - edit->undo_stack[sp]++; + if (edit->undo_stack[sp] == -2) + { + /* edit->undo_stack[sp] = '@'; */ + edit->stack_pointer = sp; + } + else + edit->undo_stack[sp]++; return c; } /* is called whenever a modification is made by one of the four routines below */ -static void edit_modification (WEdit * edit) +static void +edit_modification (WEdit * edit) { edit->caches_valid = 0; edit->screen_modified = 1; /* raise lock when file modified */ if (!edit->modified && !edit->delete_file) - edit->locked = edit_lock_file (edit->filename); + edit->locked = edit_lock_file (edit->filename); edit->modified = 1; } @@ -1153,31 +1272,34 @@ static void edit_modification (WEdit * edit) */ void -edit_insert (WEdit *edit, int c) +edit_insert (WEdit * edit, int c) { /* check if file has grown to large */ if (edit->last_byte >= SIZE_LIMIT) - return; + return; /* first we must update the position of the display window */ - if (edit->curs1 < edit->start_display) { - edit->start_display++; - if (c == '\n') - edit->start_line++; + if (edit->curs1 < edit->start_display) + { + edit->start_display++; + if (c == '\n') + edit->start_line++; } /* Mark file as modified, unless the file hasn't been fully loaded */ - if (edit->loading_done) { - edit_modification (edit); + if (edit->loading_done) + { + edit_modification (edit); } /* now we must update some info on the file and check if a redraw is required */ - if (c == '\n') { - if (edit->book_mark) - book_mark_inc (edit, edit->curs_line); - edit->curs_line++; - edit->total_lines++; - edit->force |= REDRAW_LINE_ABOVE | REDRAW_AFTER_CURSOR; + if (c == '\n') + { + if (edit->book_mark) + book_mark_inc (edit, edit->curs_line); + edit->curs_line++; + edit->total_lines++; + edit->force |= REDRAW_LINE_ABOVE | REDRAW_AFTER_CURSOR; } /* save the reverse command onto the undo stack */ @@ -1190,13 +1312,11 @@ edit_insert (WEdit *edit, int c) /* add a new buffer if we've reached the end of the last one */ if (!(edit->curs1 & M_EDIT_BUF_SIZE)) - edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = - g_malloc0 (EDIT_BUF_SIZE); + edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = g_malloc0 (EDIT_BUF_SIZE); /* perform the insertion */ - edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE][edit-> - curs1 & M_EDIT_BUF_SIZE] - = (unsigned char) c; + edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE][edit->curs1 & M_EDIT_BUF_SIZE] + = (unsigned char) c; /* update file length */ edit->last_byte++; @@ -1210,28 +1330,32 @@ edit_insert_over (WEdit * edit) { int i; - for ( i = 0; i < edit->over_col; i++ ) { + for (i = 0; i < edit->over_col; i++) + { edit_insert (edit, ' '); } edit->over_col = 0; } /* same as edit_insert and move left */ -void edit_insert_ahead (WEdit * edit, int c) +void +edit_insert_ahead (WEdit * edit, int c) { if (edit->last_byte >= SIZE_LIMIT) - return; - if (edit->curs1 < edit->start_display) { - edit->start_display++; - if (c == '\n') - edit->start_line++; + return; + if (edit->curs1 < edit->start_display) + { + edit->start_display++; + if (c == '\n') + edit->start_line++; } edit_modification (edit); - if (c == '\n') { - if (edit->book_mark) - book_mark_inc (edit, edit->curs_line); - edit->total_lines++; - edit->force |= REDRAW_AFTER_CURSOR; + if (c == '\n') + { + if (edit->book_mark) + book_mark_inc (edit, edit->curs_line); + edit->total_lines++; + edit->force |= REDRAW_AFTER_CURSOR; } edit_push_action (edit, DELCHAR); @@ -1240,40 +1364,47 @@ void edit_insert_ahead (WEdit * edit, int c) edit->last_get_rule += (edit->last_get_rule >= edit->curs1); if (!((edit->curs2 + 1) & M_EDIT_BUF_SIZE)) - edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc0 (EDIT_BUF_SIZE); - edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - 1] = c; + edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc0 (EDIT_BUF_SIZE); + edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - + 1] = c; edit->last_byte++; edit->curs2++; } -int edit_delete (WEdit * edit, const int byte_delete) +int +edit_delete (WEdit * edit, const int byte_delete) { int p = 0; int cw = 1; int i; if (!edit->curs2) - return 0; + return 0; edit->mark1 -= (edit->mark1 > edit->curs1); edit->mark2 -= (edit->mark2 > edit->curs1); edit->last_get_rule -= (edit->last_get_rule > edit->curs1); cw = 1; - /* if byte_delete = 1 then delete only one byte not multibyte char*/ - if ( edit->utf8 && byte_delete == 0 ) { + /* if byte_delete = 1 then delete only one byte not multibyte char */ + if (edit->utf8 && byte_delete == 0) + { edit_get_utf (edit, edit->curs1, &cw); - if ( cw < 1 ) + if (cw < 1) cw = 1; } - for ( i = 1; i<= cw; i++ ) { - p = edit->buffers2[(edit->curs2 - 1) >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - ((edit->curs2 - 1) & M_EDIT_BUF_SIZE) - 1]; - - if (!(edit->curs2 & M_EDIT_BUF_SIZE)) { - g_free (edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE]); - edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = NULL; + for (i = 1; i <= cw; i++) + { + p = edit->buffers2[(edit->curs2 - 1) >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - + ((edit->curs2 - + 1) & M_EDIT_BUF_SIZE) - 1]; + + if (!(edit->curs2 & M_EDIT_BUF_SIZE)) + { + g_free (edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE]); + edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = NULL; } edit->last_byte--; edit->curs2--; @@ -1281,16 +1412,18 @@ int edit_delete (WEdit * edit, const int byte_delete) } edit_modification (edit); - if (p == '\n') { - if (edit->book_mark) - book_mark_dec (edit, edit->curs_line); - edit->total_lines--; - edit->force |= REDRAW_AFTER_CURSOR; + if (p == '\n') + { + if (edit->book_mark) + book_mark_dec (edit, edit->curs_line); + edit->total_lines--; + edit->force |= REDRAW_AFTER_CURSOR; } - if (edit->curs1 < edit->start_display) { - edit->start_display--; - if (p == '\n') - edit->start_line--; + if (edit->curs1 < edit->start_display) + { + edit->start_display--; + if (p == '\n') + edit->start_line--; } return p; @@ -1305,41 +1438,47 @@ edit_backspace (WEdit * edit, const int byte_delete) int i; if (!edit->curs1) - return 0; + return 0; edit->mark1 -= (edit->mark1 >= edit->curs1); edit->mark2 -= (edit->mark2 >= edit->curs1); edit->last_get_rule -= (edit->last_get_rule >= edit->curs1); cw = 1; - if ( edit->utf8 && byte_delete == 0 ) { + if (edit->utf8 && byte_delete == 0) + { edit_get_prev_utf (edit, edit->curs1, &cw); - if ( cw < 1 ) + if (cw < 1) cw = 1; } - for ( i = 1; i<= cw; i++ ) { - p = *(edit->buffers1[(edit->curs1 - 1) >> S_EDIT_BUF_SIZE] + ((edit->curs1 - 1) & M_EDIT_BUF_SIZE)); - if (!((edit->curs1 - 1) & M_EDIT_BUF_SIZE)) { - g_free (edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE]); - edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = NULL; + for (i = 1; i <= cw; i++) + { + p = *(edit->buffers1[(edit->curs1 - 1) >> S_EDIT_BUF_SIZE] + + ((edit->curs1 - 1) & M_EDIT_BUF_SIZE)); + if (!((edit->curs1 - 1) & M_EDIT_BUF_SIZE)) + { + g_free (edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE]); + edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = NULL; } edit->last_byte--; edit->curs1--; edit_push_action (edit, p); } edit_modification (edit); - if (p == '\n') { - if (edit->book_mark) - book_mark_dec (edit, edit->curs_line); - edit->curs_line--; - edit->total_lines--; - edit->force |= REDRAW_AFTER_CURSOR; + if (p == '\n') + { + if (edit->book_mark) + book_mark_dec (edit, edit->curs_line); + edit->curs_line--; + edit->total_lines--; + edit->force |= REDRAW_AFTER_CURSOR; } - if (edit->curs1 < edit->start_display) { - edit->start_display--; - if (p == '\n') - edit->start_line--; + if (edit->curs1 < edit->start_display) + { + edit->start_display--; + if (p == '\n') + edit->start_line--; } return p; @@ -1347,243 +1486,281 @@ edit_backspace (WEdit * edit, const int byte_delete) #ifdef FAST_MOVE_CURSOR -static void memqcpy (WEdit * edit, unsigned char *dest, unsigned char *src, int n) +static void +memqcpy (WEdit * edit, unsigned char *dest, unsigned char *src, int n) { unsigned long next; - while ((next = (unsigned long) memccpy (dest, src, '\n', n))) { - edit->curs_line--; - next -= (unsigned long) dest; - n -= next; - src += next; - dest += next; + while ((next = (unsigned long) memccpy (dest, src, '\n', n))) + { + edit->curs_line--; + next -= (unsigned long) dest; + n -= next; + src += next; + dest += next; } } int -edit_move_backward_lots (WEdit *edit, long increment) +edit_move_backward_lots (WEdit * edit, long increment) { int r, s, t; unsigned char *p = NULL; if (increment > edit->curs1) - increment = edit->curs1; + increment = edit->curs1; if (increment <= 0) - return -1; + return -1; edit_push_action (edit, CURS_RIGHT_LOTS, increment); t = r = EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE); if (r > increment) - r = increment; + r = increment; s = edit->curs1 & M_EDIT_BUF_SIZE; - if (s > r) { - memqcpy (edit, - edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + t - r, - edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] + s - r, - r); - } else { - if (s) { - memqcpy (edit, - edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + t - - s, edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE], s); - p = edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE]; - edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = 0; - } - memqcpy (edit, - edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + t - r, - edit->buffers1[(edit->curs1 >> S_EDIT_BUF_SIZE) - 1] + - EDIT_BUF_SIZE - (r - s), r - s); + if (s > r) + { + memqcpy (edit, + edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + t - r, + edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] + s - r, r); + } + else + { + if (s) + { + memqcpy (edit, + edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + t - + s, edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE], s); + p = edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE]; + edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = 0; + } + memqcpy (edit, + edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + t - r, + edit->buffers1[(edit->curs1 >> S_EDIT_BUF_SIZE) - 1] + + EDIT_BUF_SIZE - (r - s), r - s); } increment -= r; edit->curs1 -= r; edit->curs2 += r; - if (!(edit->curs2 & M_EDIT_BUF_SIZE)) { - if (p) - edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = p; - else - edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = - g_malloc0 (EDIT_BUF_SIZE); - } else { - g_free (p); + if (!(edit->curs2 & M_EDIT_BUF_SIZE)) + { + if (p) + edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = p; + else + edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = g_malloc0 (EDIT_BUF_SIZE); + } + else + { + g_free (p); } s = edit->curs1 & M_EDIT_BUF_SIZE; - while (increment) { - p = 0; - r = EDIT_BUF_SIZE; - if (r > increment) - r = increment; - t = s; - if (r < t) - t = r; - memqcpy (edit, - edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + - EDIT_BUF_SIZE - t, - edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] + s - t, - t); - if (r >= s) { - if (t) { - p = edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE]; - edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = 0; - } - memqcpy (edit, - edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + - EDIT_BUF_SIZE - r, - edit->buffers1[(edit->curs1 >> S_EDIT_BUF_SIZE) - 1] + - EDIT_BUF_SIZE - (r - s), r - s); - } - increment -= r; - edit->curs1 -= r; - edit->curs2 += r; - if (!(edit->curs2 & M_EDIT_BUF_SIZE)) { - if (p) - edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = p; - else - edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = - g_malloc0 (EDIT_BUF_SIZE); - } else { - g_free (p); - } + while (increment) + { + p = 0; + r = EDIT_BUF_SIZE; + if (r > increment) + r = increment; + t = s; + if (r < t) + t = r; + memqcpy (edit, + edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + + EDIT_BUF_SIZE - t, edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] + s - t, t); + if (r >= s) + { + if (t) + { + p = edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE]; + edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = 0; + } + memqcpy (edit, + edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + + EDIT_BUF_SIZE - r, + edit->buffers1[(edit->curs1 >> S_EDIT_BUF_SIZE) - 1] + + EDIT_BUF_SIZE - (r - s), r - s); + } + increment -= r; + edit->curs1 -= r; + edit->curs2 += r; + if (!(edit->curs2 & M_EDIT_BUF_SIZE)) + { + if (p) + edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = p; + else + edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = g_malloc0 (EDIT_BUF_SIZE); + } + else + { + g_free (p); + } } return edit_get_byte (edit, edit->curs1); } -#endif /* ! FAST_MOVE_CURSOR */ +#endif /* ! FAST_MOVE_CURSOR */ /* moves the cursor right or left: increment positive or negative respectively */ -void edit_cursor_move (WEdit * edit, long increment) +void +edit_cursor_move (WEdit * edit, long increment) { -/* this is the same as a combination of two of the above routines, with only one push onto the undo stack */ + /* this is the same as a combination of two of the above routines, with only one push onto the undo stack */ int c; #ifdef FAST_MOVE_CURSOR - if (increment < -256) { - edit->force |= REDRAW_PAGE; - edit_move_backward_lots (edit, -increment); - return; - } -#endif /* ! FAST_MOVE_CURSOR */ - - if (increment < 0) { - for (; increment < 0; increment++) { - if (!edit->curs1) - return; - - edit_push_action (edit, CURS_RIGHT); - - c = edit_get_byte (edit, edit->curs1 - 1); - if (!((edit->curs2 + 1) & M_EDIT_BUF_SIZE)) - edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc0 (EDIT_BUF_SIZE); - edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - 1] = c; - edit->curs2++; - c = edit->buffers1[(edit->curs1 - 1) >> S_EDIT_BUF_SIZE][(edit->curs1 - 1) & M_EDIT_BUF_SIZE]; - if (!((edit->curs1 - 1) & M_EDIT_BUF_SIZE)) { - g_free (edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE]); - edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = NULL; - } - edit->curs1--; - if (c == '\n') { - edit->curs_line--; - edit->force |= REDRAW_LINE_BELOW; - } - } - - } else if (increment > 0) { - for (; increment > 0; increment--) { - if (!edit->curs2) - return; - - edit_push_action (edit, CURS_LEFT); - - c = edit_get_byte (edit, edit->curs1); - if (!(edit->curs1 & M_EDIT_BUF_SIZE)) - edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = g_malloc0 (EDIT_BUF_SIZE); - edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE][edit->curs1 & M_EDIT_BUF_SIZE] = c; - edit->curs1++; - c = edit->buffers2[(edit->curs2 - 1) >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - ((edit->curs2 - 1) & M_EDIT_BUF_SIZE) - 1]; - if (!(edit->curs2 & M_EDIT_BUF_SIZE)) { - g_free (edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE]); - edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = 0; - } - edit->curs2--; - if (c == '\n') { - edit->curs_line++; - edit->force |= REDRAW_LINE_ABOVE; - } - } + if (increment < -256) + { + edit->force |= REDRAW_PAGE; + edit_move_backward_lots (edit, -increment); + return; + } +#endif /* ! FAST_MOVE_CURSOR */ + + if (increment < 0) + { + for (; increment < 0; increment++) + { + if (!edit->curs1) + return; + + edit_push_action (edit, CURS_RIGHT); + + c = edit_get_byte (edit, edit->curs1 - 1); + if (!((edit->curs2 + 1) & M_EDIT_BUF_SIZE)) + edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc0 (EDIT_BUF_SIZE); + edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - + (edit->curs2 & M_EDIT_BUF_SIZE) - 1] = c; + edit->curs2++; + c = edit-> + buffers1[(edit->curs1 - 1) >> S_EDIT_BUF_SIZE][(edit->curs1 - 1) & M_EDIT_BUF_SIZE]; + if (!((edit->curs1 - 1) & M_EDIT_BUF_SIZE)) + { + g_free (edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE]); + edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = NULL; + } + edit->curs1--; + if (c == '\n') + { + edit->curs_line--; + edit->force |= REDRAW_LINE_BELOW; + } + } + + } + else if (increment > 0) + { + for (; increment > 0; increment--) + { + if (!edit->curs2) + return; + + edit_push_action (edit, CURS_LEFT); + + c = edit_get_byte (edit, edit->curs1); + if (!(edit->curs1 & M_EDIT_BUF_SIZE)) + edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = g_malloc0 (EDIT_BUF_SIZE); + edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE][edit->curs1 & M_EDIT_BUF_SIZE] = c; + edit->curs1++; + c = edit->buffers2[(edit->curs2 - 1) >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - + ((edit->curs2 - + 1) & M_EDIT_BUF_SIZE) - 1]; + if (!(edit->curs2 & M_EDIT_BUF_SIZE)) + { + g_free (edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE]); + edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = 0; + } + edit->curs2--; + if (c == '\n') + { + edit->curs_line++; + edit->force |= REDRAW_LINE_ABOVE; + } + } } } /* These functions return positions relative to lines */ /* returns index of last char on line + 1 */ -long edit_eol (WEdit * edit, long current) -{ - if (current < edit->last_byte) { - for (;; current++) - if (edit_get_byte (edit, current) == '\n') - break; - } else - return edit->last_byte; +long +edit_eol (WEdit * edit, long current) +{ + if (current < edit->last_byte) + { + for (;; current++) + if (edit_get_byte (edit, current) == '\n') + break; + } + else + return edit->last_byte; return current; } /* returns index of first char on line */ -long edit_bol (WEdit * edit, long current) -{ - if (current > 0) { - for (;; current--) - if (edit_get_byte (edit, current - 1) == '\n') - break; - } else - return 0; +long +edit_bol (WEdit * edit, long current) +{ + if (current > 0) + { + for (;; current--) + if (edit_get_byte (edit, current - 1) == '\n') + break; + } + else + return 0; return current; } -long edit_count_lines (WEdit * edit, long current, long upto) +long +edit_count_lines (WEdit * edit, long current, long upto) { long lines = 0; if (upto > edit->last_byte) - upto = edit->last_byte; + upto = edit->last_byte; if (current < 0) - current = 0; + current = 0; while (current < upto) - if (edit_get_byte (edit, current++) == '\n') - lines++; + if (edit_get_byte (edit, current++) == '\n') + lines++; return lines; } /* If lines is zero this returns the count of lines from current to upto. */ /* If upto is zero returns index of lines forward current. */ -long edit_move_forward (WEdit * edit, long current, long lines, long upto) +long +edit_move_forward (WEdit * edit, long current, long lines, long upto) { - if (upto) { - return edit_count_lines (edit, current, upto); - } else { - long next; - if (lines < 0) - lines = 0; - while (lines--) { - next = edit_eol (edit, current) + 1; - if (next > edit->last_byte) - break; - else - current = next; - } - return current; + if (upto) + { + return edit_count_lines (edit, current, upto); + } + else + { + long next; + if (lines < 0) + lines = 0; + while (lines--) + { + next = edit_eol (edit, current) + 1; + if (next > edit->last_byte) + break; + else + current = next; + } + return current; } } /* Returns offset of 'lines' lines up from current */ -long edit_move_backward (WEdit * edit, long current, long lines) +long +edit_move_backward (WEdit * edit, long current, long lines) { if (lines < 0) - lines = 0; + lines = 0; current = edit_bol (edit, current); - while((lines--) && current != 0) - current = edit_bol (edit, current - 1); + while ((lines--) && current != 0) + current = edit_bol (edit, current - 1); return current; } @@ -1595,57 +1772,67 @@ edit_move_forward3 (WEdit * edit, long current, int cols, long upto) long p, q; int col; - if (upto) { - q = upto; - cols = -10; - } else - q = edit->last_byte + 2; + if (upto) + { + q = upto; + cols = -10; + } + else + q = edit->last_byte + 2; - for (col = 0, p = current; p < q; p++) { - int c, orig_c; - int utf_ch = 0; + for (col = 0, p = current; p < q; p++) + { + int c, orig_c; + int utf_ch = 0; #ifdef HAVE_CHARSET - int cw = 1; + int cw = 1; #endif - if (cols != -10) { - if (col == cols) - return p; - if (col > cols) - return p - 1; - } - orig_c = c = edit_get_byte (edit, p); + if (cols != -10) + { + if (col == cols) + return p; + if (col > cols) + return p - 1; + } + orig_c = c = edit_get_byte (edit, p); #ifdef HAVE_CHARSET - if (edit->utf8) { - utf_ch = edit_get_utf (edit, p, &cw); - if (utf8_display) { - if (cw > 1) - col -= cw - 1; - if (g_unichar_iswide (utf_ch)) - col++; - } else if (cw > 1 && g_unichar_isprint (utf_ch)) - col -= cw - 1; - } + if (edit->utf8) + { + utf_ch = edit_get_utf (edit, p, &cw); + if (utf8_display) + { + if (cw > 1) + col -= cw - 1; + if (g_unichar_iswide (utf_ch)) + col++; + } + else if (cw > 1 && g_unichar_isprint (utf_ch)) + col -= cw - 1; + } #endif - c = convert_to_display_c (c); - if (c == '\t') - col += TAB_SIZE - col % TAB_SIZE; - else if (c == '\n') { - if (upto) - return col; - else - return p; - } else if ((c < 32 || c == 127) && (orig_c == c || (!utf8_display && !edit->utf8))) - /* '\r' is shown as ^M, so we must advance 2 characters */ - /* Caret notation for control characters */ - col += 2; - else - col++; + c = convert_to_display_c (c); + if (c == '\t') + col += TAB_SIZE - col % TAB_SIZE; + else if (c == '\n') + { + if (upto) + return col; + else + return p; + } + else if ((c < 32 || c == 127) && (orig_c == c || (!utf8_display && !edit->utf8))) + /* '\r' is shown as ^M, so we must advance 2 characters */ + /* Caret notation for control characters */ + col += 2; + else + col++; } return col; } /* returns the current column position of the cursor */ -int edit_get_col (WEdit * edit) +int +edit_get_col (WEdit * edit) { return edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0, edit->curs1); } @@ -1653,84 +1840,94 @@ int edit_get_col (WEdit * edit) /* Scrolling functions */ -void edit_update_curs_row (WEdit * edit) +void +edit_update_curs_row (WEdit * edit) { edit->curs_row = edit->curs_line - edit->start_line; } -void edit_update_curs_col (WEdit * edit) +void +edit_update_curs_col (WEdit * edit) { - edit->curs_col = edit_move_forward3(edit, edit_bol(edit, edit->curs1), 0, edit->curs1); + edit->curs_col = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0, edit->curs1); } int -edit_get_curs_col (const WEdit *edit) +edit_get_curs_col (const WEdit * edit) { return edit->curs_col; } /*moves the display start position up by i lines */ -void edit_scroll_upward (WEdit * edit, unsigned long i) +void +edit_scroll_upward (WEdit * edit, unsigned long i) { unsigned long lines_above = edit->start_line; if (i > lines_above) - i = lines_above; - if (i) { - edit->start_line -= i; - edit->start_display = edit_move_backward (edit, edit->start_display, i); - edit->force |= REDRAW_PAGE; - edit->force &= (0xfff - REDRAW_CHAR_ONLY); + i = lines_above; + if (i) + { + edit->start_line -= i; + edit->start_display = edit_move_backward (edit, edit->start_display, i); + edit->force |= REDRAW_PAGE; + edit->force &= (0xfff - REDRAW_CHAR_ONLY); } edit_update_curs_row (edit); } /* returns 1 if could scroll, 0 otherwise */ -void edit_scroll_downward (WEdit * edit, int i) +void +edit_scroll_downward (WEdit * edit, int i) { int lines_below; lines_below = edit->total_lines - edit->start_line - (edit->num_widget_lines - 1); - if (lines_below > 0) { - if (i > lines_below) - i = lines_below; - edit->start_line += i; - edit->start_display = edit_move_forward (edit, edit->start_display, i, 0); - edit->force |= REDRAW_PAGE; - edit->force &= (0xfff - REDRAW_CHAR_ONLY); + if (lines_below > 0) + { + if (i > lines_below) + i = lines_below; + edit->start_line += i; + edit->start_display = edit_move_forward (edit, edit->start_display, i, 0); + edit->force |= REDRAW_PAGE; + edit->force &= (0xfff - REDRAW_CHAR_ONLY); } edit_update_curs_row (edit); } -void edit_scroll_right (WEdit * edit, int i) +void +edit_scroll_right (WEdit * edit, int i) { edit->force |= REDRAW_PAGE; edit->force &= (0xfff - REDRAW_CHAR_ONLY); edit->start_col -= i; } -void edit_scroll_left (WEdit * edit, int i) +void +edit_scroll_left (WEdit * edit, int i) { - if (edit->start_col) { - edit->start_col += i; - if (edit->start_col > 0) - edit->start_col = 0; - edit->force |= REDRAW_PAGE; - edit->force &= (0xfff - REDRAW_CHAR_ONLY); + if (edit->start_col) + { + edit->start_col += i; + if (edit->start_col > 0) + edit->start_col = 0; + edit->force |= REDRAW_PAGE; + edit->force &= (0xfff - REDRAW_CHAR_ONLY); } } /* high level cursor movement commands */ -static int is_in_indent (WEdit *edit) +static int +is_in_indent (WEdit * edit) { long p = edit_bol (edit, edit->curs1); while (p < edit->curs1) - if (!strchr (" \t", edit_get_byte (edit, p++))) - return 0; + if (!strchr (" \t", edit_get_byte (edit, p++))) + return 0; return 1; } -static int left_of_four_spaces (WEdit *edit); +static int left_of_four_spaces (WEdit * edit); void edit_move_to_prev_col (WEdit * edit, long p) @@ -1739,46 +1936,59 @@ edit_move_to_prev_col (WEdit * edit, long p) int over = edit->over_col; edit_cursor_move (edit, edit_move_forward3 (edit, p, prev + edit->over_col, 0) - edit->curs1); - if (option_cursor_beyond_eol) { - long line_len = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0, edit_eol(edit, edit->curs1)); + if (option_cursor_beyond_eol) + { + long line_len = + edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0, + edit_eol (edit, edit->curs1)); - if (line_len < prev + edit->over_col) { + if (line_len < prev + edit->over_col) + { edit->over_col = prev + over - line_len; edit->prev_col = line_len; edit->curs_col = line_len; - } else { + } + else + { edit->curs_col = prev + over; edit->prev_col = edit->curs_col; edit->over_col = 0; } - } else { + } + else + { edit->over_col = 0; - if (is_in_indent (edit) && option_fake_half_tabs) { + if (is_in_indent (edit) && option_fake_half_tabs) + { edit_update_curs_col (edit); if (space_width) - if (edit->curs_col % (HALF_TAB_SIZE * space_width)) { - int q = edit->curs_col; - edit->curs_col -= (edit->curs_col % (HALF_TAB_SIZE * space_width)); - p = edit_bol (edit, edit->curs1); - edit_cursor_move (edit, edit_move_forward3 (edit, p, edit->curs_col, 0) - edit->curs1); - if (!left_of_four_spaces (edit)) - edit_cursor_move (edit, edit_move_forward3 (edit, p, q, 0) - edit->curs1); - } + if (edit->curs_col % (HALF_TAB_SIZE * space_width)) + { + int q = edit->curs_col; + edit->curs_col -= (edit->curs_col % (HALF_TAB_SIZE * space_width)); + p = edit_bol (edit, edit->curs1); + edit_cursor_move (edit, + edit_move_forward3 (edit, p, edit->curs_col, + 0) - edit->curs1); + if (!left_of_four_spaces (edit)) + edit_cursor_move (edit, edit_move_forward3 (edit, p, q, 0) - edit->curs1); + } } } } static int -is_blank (WEdit *edit, long offset) +is_blank (WEdit * edit, long offset) { long s, f; int c; s = edit_bol (edit, offset); f = edit_eol (edit, offset) - 1; - while (s <= f) { - c = edit_get_byte (edit, s++); - if (!isspace (c)) - return 0; + while (s <= f) + { + c = edit_get_byte (edit, s++); + if (!isspace (c)) + return 0; } return 1; } @@ -1786,48 +1996,54 @@ is_blank (WEdit *edit, long offset) /* returns the offset of line i */ static long -edit_find_line (WEdit *edit, int line) +edit_find_line (WEdit * edit, int line) { int i, j = 0; int m = 2000000000; - if (!edit->caches_valid) { - for (i = 0; i < N_LINE_CACHES; i++) - edit->line_numbers[i] = edit->line_offsets[i] = 0; -/* three offsets that we *know* are line 0 at 0 and these two: */ - edit->line_numbers[1] = edit->curs_line; - edit->line_offsets[1] = edit_bol (edit, edit->curs1); - edit->line_numbers[2] = edit->total_lines; - edit->line_offsets[2] = edit_bol (edit, edit->last_byte); - edit->caches_valid = 1; + if (!edit->caches_valid) + { + for (i = 0; i < N_LINE_CACHES; i++) + edit->line_numbers[i] = edit->line_offsets[i] = 0; + /* three offsets that we *know* are line 0 at 0 and these two: */ + edit->line_numbers[1] = edit->curs_line; + edit->line_offsets[1] = edit_bol (edit, edit->curs1); + edit->line_numbers[2] = edit->total_lines; + edit->line_offsets[2] = edit_bol (edit, edit->last_byte); + edit->caches_valid = 1; } if (line >= edit->total_lines) - return edit->line_offsets[2]; + return edit->line_offsets[2]; if (line <= 0) - return 0; -/* find the closest known point */ - for (i = 0; i < N_LINE_CACHES; i++) { - int n; - n = abs (edit->line_numbers[i] - line); - if (n < m) { - m = n; - j = i; - } + return 0; + /* find the closest known point */ + for (i = 0; i < N_LINE_CACHES; i++) + { + int n; + n = abs (edit->line_numbers[i] - line); + if (n < m) + { + m = n; + j = i; + } } if (m == 0) - return edit->line_offsets[j]; /* know the offset exactly */ + return edit->line_offsets[j]; /* know the offset exactly */ if (m == 1 && j >= 3) - i = j; /* one line different - caller might be looping, so stay in this cache */ + i = j; /* one line different - caller might be looping, so stay in this cache */ else - i = 3 + (rand () % (N_LINE_CACHES - 3)); + i = 3 + (rand () % (N_LINE_CACHES - 3)); if (line > edit->line_numbers[j]) - edit->line_offsets[i] = edit_move_forward (edit, edit->line_offsets[j], line - edit->line_numbers[j], 0); + edit->line_offsets[i] = + edit_move_forward (edit, edit->line_offsets[j], line - edit->line_numbers[j], 0); else - edit->line_offsets[i] = edit_move_backward (edit, edit->line_offsets[j], edit->line_numbers[j] - line); + edit->line_offsets[i] = + edit_move_backward (edit, edit->line_offsets[j], edit->line_numbers[j] - line); edit->line_numbers[i] = line; return edit->line_offsets[i]; } -int line_is_blank (WEdit * edit, long line) +int +line_is_blank (WEdit * edit, long line) { return is_blank (edit, edit_find_line (edit, line)); } @@ -1838,24 +2054,32 @@ static void edit_move_up_paragraph (WEdit * edit, int do_scroll) { int i = 0; - if (edit->curs_line > 1) { - if (line_is_blank (edit, edit->curs_line)) { - if (line_is_blank (edit, edit->curs_line - 1)) { - for (i = edit->curs_line - 1; i; i--) - if (!line_is_blank (edit, i)) { - i++; - break; - } - } else { - for (i = edit->curs_line - 1; i; i--) - if (line_is_blank (edit, i)) - break; - } - } else { - for (i = edit->curs_line - 1; i; i--) - if (line_is_blank (edit, i)) - break; - } + if (edit->curs_line > 1) + { + if (line_is_blank (edit, edit->curs_line)) + { + if (line_is_blank (edit, edit->curs_line - 1)) + { + for (i = edit->curs_line - 1; i; i--) + if (!line_is_blank (edit, i)) + { + i++; + break; + } + } + else + { + for (i = edit->curs_line - 1; i; i--) + if (line_is_blank (edit, i)) + break; + } + } + else + { + for (i = edit->curs_line - 1; i; i--) + if (line_is_blank (edit, i)) + break; + } } edit_move_up (edit, edit->curs_line - i, do_scroll); } @@ -1866,37 +2090,49 @@ static void edit_move_down_paragraph (WEdit * edit, int do_scroll) { int i; - if (edit->curs_line >= edit->total_lines - 1) { - i = edit->total_lines; - } else { - if (line_is_blank (edit, edit->curs_line)) { - if (line_is_blank (edit, edit->curs_line + 1)) { - for (i = edit->curs_line + 1; i; i++) - if (!line_is_blank (edit, i) || i > edit->total_lines) { - i--; - break; - } - } else { - for (i = edit->curs_line + 1; i; i++) - if (line_is_blank (edit, i) || i >= edit->total_lines) - break; - } - } else { - for (i = edit->curs_line + 1; i; i++) - if (line_is_blank (edit, i) || i >= edit->total_lines) - break; - } + if (edit->curs_line >= edit->total_lines - 1) + { + i = edit->total_lines; + } + else + { + if (line_is_blank (edit, edit->curs_line)) + { + if (line_is_blank (edit, edit->curs_line + 1)) + { + for (i = edit->curs_line + 1; i; i++) + if (!line_is_blank (edit, i) || i > edit->total_lines) + { + i--; + break; + } + } + else + { + for (i = edit->curs_line + 1; i; i++) + if (line_is_blank (edit, i) || i >= edit->total_lines) + break; + } + } + else + { + for (i = edit->curs_line + 1; i; i++) + if (line_is_blank (edit, i) || i >= edit->total_lines) + break; + } } edit_move_down (edit, i - edit->curs_line, do_scroll); } -static void edit_begin_page (WEdit *edit) +static void +edit_begin_page (WEdit * edit) { edit_update_curs_row (edit); edit_move_up (edit, edit->curs_row, 0); } -static void edit_end_page (WEdit *edit) +static void +edit_end_page (WEdit * edit) { edit_update_curs_row (edit); edit_move_down (edit, edit->num_widget_lines - edit->curs_row - 1, 0); @@ -1904,32 +2140,37 @@ static void edit_end_page (WEdit *edit) /* goto beginning of text */ -static void edit_move_to_top (WEdit * edit) +static void +edit_move_to_top (WEdit * edit) { - if (edit->curs_line) { - edit_cursor_move (edit, -edit->curs1); - edit_move_to_prev_col (edit, 0); - edit->force |= REDRAW_PAGE; - edit->search_start = 0; - edit_update_curs_row(edit); + if (edit->curs_line) + { + edit_cursor_move (edit, -edit->curs1); + edit_move_to_prev_col (edit, 0); + edit->force |= REDRAW_PAGE; + edit->search_start = 0; + edit_update_curs_row (edit); } } /* goto end of text */ -static void edit_move_to_bottom (WEdit * edit) +static void +edit_move_to_bottom (WEdit * edit) { - if (edit->curs_line < edit->total_lines) { - edit_move_down (edit, edit->total_lines - edit->curs_row, 0); - edit->start_display = edit->last_byte; - edit->start_line = edit->total_lines; - edit_scroll_upward (edit, edit->num_widget_lines - 1); - edit->force |= REDRAW_PAGE; + if (edit->curs_line < edit->total_lines) + { + edit_move_down (edit, edit->total_lines - edit->curs_row, 0); + edit->start_display = edit->last_byte; + edit->start_line = edit->total_lines; + edit_scroll_upward (edit, edit->num_widget_lines - 1); + edit->force |= REDRAW_PAGE; } } /* goto beginning of line */ -static void edit_cursor_to_bol (WEdit * edit) +static void +edit_cursor_to_bol (WEdit * edit) { edit_cursor_move (edit, edit_bol (edit, edit->curs1) - edit->curs1); edit->search_start = edit->curs1; @@ -1938,7 +2179,8 @@ static void edit_cursor_to_bol (WEdit * edit) } /* goto end of line */ -static void edit_cursor_to_eol (WEdit * edit) +static void +edit_cursor_to_eol (WEdit * edit) { edit_cursor_move (edit, edit_eol (edit, edit->curs1) - edit->curs1); edit->search_start = edit->curs1; @@ -1947,32 +2189,36 @@ static void edit_cursor_to_eol (WEdit * edit) } /* move cursor to line 'line' */ -void edit_move_to_line (WEdit * e, long line) +void +edit_move_to_line (WEdit * e, long line) { - if(line < e->curs_line) - edit_move_up (e, e->curs_line - line, 0); + if (line < e->curs_line) + edit_move_up (e, e->curs_line - line, 0); else - edit_move_down (e, line - e->curs_line, 0); + edit_move_down (e, line - e->curs_line, 0); edit_scroll_screen_over_cursor (e); } /* scroll window so that first visible line is 'line' */ -void edit_move_display (WEdit * e, long line) +void +edit_move_display (WEdit * e, long line) { - if(line < e->start_line) - edit_scroll_upward (e, e->start_line - line); + if (line < e->start_line) + edit_scroll_upward (e, e->start_line - line); else - edit_scroll_downward (e, line - e->start_line); + edit_scroll_downward (e, line - e->start_line); } /* save markers onto undo stack */ -void edit_push_markers (WEdit * edit) +void +edit_push_markers (WEdit * edit) { edit_push_action (edit, MARK_1 + edit->mark1); edit_push_action (edit, MARK_2 + edit->mark2); } -void edit_set_markers (WEdit * edit, long m1, long m2, int c1, int c2) +void +edit_set_markers (WEdit * edit, long m1, long m2, int c1, int c2) { edit->mark1 = m1; edit->mark2 = m2; @@ -1982,18 +2228,26 @@ void edit_set_markers (WEdit * edit, long m1, long m2, int c1, int c2) /* highlight marker toggle */ -void edit_mark_cmd (WEdit * edit, int unmark) +void +edit_mark_cmd (WEdit * edit, int unmark) { edit_push_markers (edit); - if (unmark) { - edit_set_markers (edit, 0, 0, 0, 0); - edit->force |= REDRAW_PAGE; - } else { - if (edit->mark2 >= 0) { - edit_set_markers (edit, edit->curs1, -1, edit->curs_col+edit->over_col, edit->curs_col+edit->over_col); - edit->force |= REDRAW_PAGE; - } else - edit_set_markers (edit, edit->mark1, edit->curs1, edit->column1, edit->curs_col+edit->over_col); + if (unmark) + { + edit_set_markers (edit, 0, 0, 0, 0); + edit->force |= REDRAW_PAGE; + } + else + { + if (edit->mark2 >= 0) + { + edit_set_markers (edit, edit->curs1, -1, edit->curs_col + edit->over_col, + edit->curs_col + edit->over_col); + edit->force |= REDRAW_PAGE; + } + else + edit_set_markers (edit, edit->mark1, edit->curs1, edit->column1, + edit->curs_col + edit->over_col); } } @@ -2003,135 +2257,150 @@ my_type_of (int c) int x, r = 0; const char *p, *q; const char option_chars_move_whole_word[] = - "!=&|<>^~ !:;, !'!`!.?!\"!( !) !Aa0 !+-*/= |<> ![ !] !\\#! "; + "!=&|<>^~ !:;, !'!`!.?!\"!( !) !Aa0 !+-*/= |<> ![ !] !\\#! "; if (!c) - return 0; - if (c == '!') { - if (*option_chars_move_whole_word == '!') - return 2; - return 0x80000000UL; + return 0; + if (c == '!') + { + if (*option_chars_move_whole_word == '!') + return 2; + return 0x80000000UL; } if (g_ascii_isupper ((gchar) c)) - c = 'A'; + c = 'A'; else if (g_ascii_islower ((gchar) c)) - c = 'a'; + c = 'a'; else if (g_ascii_isalpha (c)) - c = 'a'; + c = 'a'; else if (isdigit (c)) - c = '0'; + c = '0'; else if (isspace (c)) - c = ' '; + c = ' '; q = strchr (option_chars_move_whole_word, c); if (!q) - return 0xFFFFFFFFUL; - do { - for (x = 1, p = option_chars_move_whole_word; p < q; p++) - if (*p == '!') - x <<= 1; - r |= x; - } while ((q = strchr (q + 1, c))); + return 0xFFFFFFFFUL; + do + { + for (x = 1, p = option_chars_move_whole_word; p < q; p++) + if (*p == '!') + x <<= 1; + r |= x; + } + while ((q = strchr (q + 1, c))); return r; } static void -edit_left_word_move (WEdit *edit, int s) -{ - for (;;) { - int c1, c2; - if (column_highlighting - && edit->mark1 != edit->mark2 - && edit->over_col == 0 - && edit->curs1 == edit_bol(edit, edit->curs1)) - break; - edit_cursor_move (edit, -1); - if (!edit->curs1) - break; - c1 = edit_get_byte (edit, edit->curs1 - 1); - c2 = edit_get_byte (edit, edit->curs1); - if (!(my_type_of (c1) & my_type_of (c2))) - break; - if (isspace (c1) && !isspace (c2)) - break; - if (s) - if (!isspace (c1) && isspace (c2)) - break; - } -} - -static void edit_left_word_move_cmd (WEdit * edit) +edit_left_word_move (WEdit * edit, int s) +{ + for (;;) + { + int c1, c2; + if (column_highlighting + && edit->mark1 != edit->mark2 + && edit->over_col == 0 && edit->curs1 == edit_bol (edit, edit->curs1)) + break; + edit_cursor_move (edit, -1); + if (!edit->curs1) + break; + c1 = edit_get_byte (edit, edit->curs1 - 1); + c2 = edit_get_byte (edit, edit->curs1); + if (!(my_type_of (c1) & my_type_of (c2))) + break; + if (isspace (c1) && !isspace (c2)) + break; + if (s) + if (!isspace (c1) && isspace (c2)) + break; + } +} + +static void +edit_left_word_move_cmd (WEdit * edit) { edit_left_word_move (edit, 0); edit->force |= REDRAW_PAGE; } static void -edit_right_word_move (WEdit *edit, int s) -{ - for (;;) { - int c1, c2; - if (column_highlighting - && edit->mark1 != edit->mark2 - && edit->over_col == 0 - && edit->curs1 == edit_eol(edit, edit->curs1) - ) - break; - edit_cursor_move (edit, 1); - if (edit->curs1 >= edit->last_byte) - break; - c1 = edit_get_byte (edit, edit->curs1 - 1); - c2 = edit_get_byte (edit, edit->curs1); - if (!(my_type_of (c1) & my_type_of (c2))) - break; - if (isspace (c1) && !isspace (c2)) - break; - if (s) - if (!isspace (c1) && isspace (c2)) - break; - } -} - -static void edit_right_word_move_cmd (WEdit * edit) +edit_right_word_move (WEdit * edit, int s) +{ + for (;;) + { + int c1, c2; + if (column_highlighting + && edit->mark1 != edit->mark2 + && edit->over_col == 0 && edit->curs1 == edit_eol (edit, edit->curs1)) + break; + edit_cursor_move (edit, 1); + if (edit->curs1 >= edit->last_byte) + break; + c1 = edit_get_byte (edit, edit->curs1 - 1); + c2 = edit_get_byte (edit, edit->curs1); + if (!(my_type_of (c1) & my_type_of (c2))) + break; + if (isspace (c1) && !isspace (c2)) + break; + if (s) + if (!isspace (c1) && isspace (c2)) + break; + } +} + +static void +edit_right_word_move_cmd (WEdit * edit) { edit_right_word_move (edit, 0); edit->force |= REDRAW_PAGE; } -static void edit_right_char_move_cmd (WEdit * edit) +static void +edit_right_char_move_cmd (WEdit * edit) { int cw = 1; int c = 0; - if ( edit->utf8 ) { + if (edit->utf8) + { c = edit_get_utf (edit, edit->curs1, &cw); - if ( cw < 1 ) + if (cw < 1) cw = 1; - } else { + } + else + { c = edit_get_byte (edit, edit->curs1); } - if (option_cursor_beyond_eol && c == '\n') { + if (option_cursor_beyond_eol && c == '\n') + { edit->over_col++; - } else { + } + else + { edit_cursor_move (edit, cw); } } -static void edit_left_char_move_cmd (WEdit * edit) +static void +edit_left_char_move_cmd (WEdit * edit) { int cw = 1; if (column_highlighting && option_cursor_beyond_eol && edit->mark1 != edit->mark2 - && edit->over_col == 0 - && edit->curs1 == edit_bol(edit, edit->curs1)) + && edit->over_col == 0 && edit->curs1 == edit_bol (edit, edit->curs1)) return; - if ( edit->utf8 ) { + if (edit->utf8) + { edit_get_prev_utf (edit, edit->curs1, &cw); - if ( cw < 1 ) + if (cw < 1) cw = 1; } - if (option_cursor_beyond_eol && edit->over_col > 0) { + if (option_cursor_beyond_eol && edit->over_col > 0) + { edit->over_col--; - } else { + } + else + { edit_cursor_move (edit, -cw); } } @@ -2144,36 +2413,34 @@ static void edit_move_updown (WEdit * edit, unsigned long i, int do_scroll, gboolean direction) { unsigned long p; - unsigned long l = (direction) - ? edit->curs_line - : edit->total_lines - edit->curs_line; + unsigned long l = (direction) ? edit->curs_line : edit->total_lines - edit->curs_line; if (i > l) - i = l; + i = l; if (i == 0) - return; + return; if (i > 1) - edit->force |= REDRAW_PAGE; - if (do_scroll) { - if (direction) - edit_scroll_upward (edit, i); - else - edit_scroll_downward (edit, i); + edit->force |= REDRAW_PAGE; + if (do_scroll) + { + if (direction) + edit_scroll_upward (edit, i); + else + edit_scroll_downward (edit, i); } p = edit_bol (edit, edit->curs1); - p = (direction) - ? edit_move_backward (edit, p, i) - : edit_move_forward (edit, p, i, 0); + p = (direction) ? edit_move_backward (edit, p, i) : edit_move_forward (edit, p, i, 0); edit_cursor_move (edit, p - edit->curs1); edit_move_to_prev_col (edit, p); /* search start of current multibyte char (like CJK) */ - if (edit->curs1 + 1 < edit->last_byte) { + if (edit->curs1 + 1 < edit->last_byte) + { edit_right_char_move_cmd (edit); edit_left_char_move_cmd (edit); } @@ -2182,33 +2449,37 @@ edit_move_updown (WEdit * edit, unsigned long i, int do_scroll, gboolean directi edit->found_len = 0; } -static void edit_right_delete_word (WEdit * edit) +static void +edit_right_delete_word (WEdit * edit) { int c1, c2; - for (;;) { - if (edit->curs1 >= edit->last_byte) - break; - c1 = edit_delete (edit, 1); - c2 = edit_get_byte (edit, edit->curs1); - if ((isspace (c1) == 0) != (isspace (c2) == 0)) - break; - if (!(my_type_of (c1) & my_type_of (c2))) - break; + for (;;) + { + if (edit->curs1 >= edit->last_byte) + break; + c1 = edit_delete (edit, 1); + c2 = edit_get_byte (edit, edit->curs1); + if ((isspace (c1) == 0) != (isspace (c2) == 0)) + break; + if (!(my_type_of (c1) & my_type_of (c2))) + break; } } -static void edit_left_delete_word (WEdit * edit) +static void +edit_left_delete_word (WEdit * edit) { int c1, c2; - for (;;) { - if (edit->curs1 <= 0) - break; - c1 = edit_backspace (edit, 1); - c2 = edit_get_byte (edit, edit->curs1 - 1); - if ((isspace (c1) == 0) != (isspace (c2) == 0)) - break; - if (!(my_type_of (c1) & my_type_of (c2))) - break; + for (;;) + { + if (edit->curs1 <= 0) + break; + c1 = edit_backspace (edit, 1); + c2 = edit_get_byte (edit, edit->curs1 - 1); + if ((isspace (c1) == 0) != (isspace (c2) == 0)) + break; + if (!(my_type_of (c1) & my_type_of (c2))) + break; } } @@ -2222,89 +2493,102 @@ edit_do_undo (WEdit * edit) long ac; long count = 0; - edit->stack_disable = 1; /* don't record undo's onto undo stack! */ + edit->stack_disable = 1; /* don't record undo's onto undo stack! */ edit->over_col = 0; - while ((ac = pop_action (edit)) < KEY_PRESS) { - switch ((int) ac) { - case STACK_BOTTOM: - goto done_undo; - case CURS_RIGHT: - edit_cursor_move (edit, 1); - break; - case CURS_LEFT: - edit_cursor_move (edit, -1); - break; - case BACKSPACE: - edit_backspace (edit, 1); - break; - case DELCHAR: - edit_delete (edit, 1); - break; - case COLUMN_ON: - column_highlighting = 1; - break; - case COLUMN_OFF: - column_highlighting = 0; - break; - } - if (ac >= 256 && ac < 512) - edit_insert_ahead (edit, ac - 256); - if (ac >= 0 && ac < 256) - edit_insert (edit, ac); - - if (ac >= MARK_1 - 2 && ac < MARK_2 - 2) { - edit->mark1 = ac - MARK_1; - edit->column1 = edit_move_forward3 (edit, edit_bol (edit, edit->mark1), 0, edit->mark1); - } else if (ac >= MARK_2 - 2 && ac < KEY_PRESS) { - edit->mark2 = ac - MARK_2; - edit->column2 = edit_move_forward3 (edit, edit_bol (edit, edit->mark2), 0, edit->mark2); - } - if (count++) - edit->force |= REDRAW_PAGE; /* more than one pop usually means something big */ - } - - if (edit->start_display > ac - KEY_PRESS) { - edit->start_line -= edit_count_lines (edit, ac - KEY_PRESS, edit->start_display); - edit->force |= REDRAW_PAGE; - } else if (edit->start_display < ac - KEY_PRESS) { - edit->start_line += edit_count_lines (edit, edit->start_display, ac - KEY_PRESS); - edit->force |= REDRAW_PAGE; - } - edit->start_display = ac - KEY_PRESS; /* see push and pop above */ + while ((ac = pop_action (edit)) < KEY_PRESS) + { + switch ((int) ac) + { + case STACK_BOTTOM: + goto done_undo; + case CURS_RIGHT: + edit_cursor_move (edit, 1); + break; + case CURS_LEFT: + edit_cursor_move (edit, -1); + break; + case BACKSPACE: + edit_backspace (edit, 1); + break; + case DELCHAR: + edit_delete (edit, 1); + break; + case COLUMN_ON: + column_highlighting = 1; + break; + case COLUMN_OFF: + column_highlighting = 0; + break; + } + if (ac >= 256 && ac < 512) + edit_insert_ahead (edit, ac - 256); + if (ac >= 0 && ac < 256) + edit_insert (edit, ac); + + if (ac >= MARK_1 - 2 && ac < MARK_2 - 2) + { + edit->mark1 = ac - MARK_1; + edit->column1 = edit_move_forward3 (edit, edit_bol (edit, edit->mark1), 0, edit->mark1); + } + else if (ac >= MARK_2 - 2 && ac < KEY_PRESS) + { + edit->mark2 = ac - MARK_2; + edit->column2 = edit_move_forward3 (edit, edit_bol (edit, edit->mark2), 0, edit->mark2); + } + if (count++) + edit->force |= REDRAW_PAGE; /* more than one pop usually means something big */ + } + + if (edit->start_display > ac - KEY_PRESS) + { + edit->start_line -= edit_count_lines (edit, ac - KEY_PRESS, edit->start_display); + edit->force |= REDRAW_PAGE; + } + else if (edit->start_display < ac - KEY_PRESS) + { + edit->start_line += edit_count_lines (edit, edit->start_display, ac - KEY_PRESS); + edit->force |= REDRAW_PAGE; + } + edit->start_display = ac - KEY_PRESS; /* see push and pop above */ edit_update_curs_row (edit); done_undo:; edit->stack_disable = 0; } -static void edit_delete_to_line_end (WEdit * edit) +static void +edit_delete_to_line_end (WEdit * edit) { - while (edit_get_byte (edit, edit->curs1) != '\n') { - if (!edit->curs2) - break; - edit_delete (edit, 1); + while (edit_get_byte (edit, edit->curs1) != '\n') + { + if (!edit->curs2) + break; + edit_delete (edit, 1); } } -static void edit_delete_to_line_begin (WEdit * edit) +static void +edit_delete_to_line_begin (WEdit * edit) { - while (edit_get_byte (edit, edit->curs1 - 1) != '\n') { - if (!edit->curs1) - break; - edit_backspace (edit, 1); + while (edit_get_byte (edit, edit->curs1 - 1) != '\n') + { + if (!edit->curs1) + break; + edit_backspace (edit, 1); } } void -edit_delete_line (WEdit *edit) +edit_delete_line (WEdit * edit) { /* * Delete right part of the line. * Note that edit_get_byte() returns '\n' when byte position is * beyond EOF. */ - while (edit_get_byte (edit, edit->curs1) != '\n') { - (void) edit_delete (edit, 1); + while (edit_get_byte (edit, edit->curs1) != '\n') + { + (void) edit_delete (edit, 1); } /* @@ -2318,67 +2602,78 @@ edit_delete_line (WEdit *edit) * Delete left part of the line. * Note, that edit_get_byte() returns '\n' when byte position is < 0. */ - while (edit_get_byte (edit, edit->curs1 - 1) != '\n') { - (void) edit_backspace (edit, 1); + while (edit_get_byte (edit, edit->curs1 - 1) != '\n') + { + (void) edit_backspace (edit, 1); } } -void insert_spaces_tab (WEdit * edit, int half) +void +insert_spaces_tab (WEdit * edit, int half) { int i; edit_update_curs_col (edit); - i = ((edit->curs_col / (option_tab_spacing * space_width / (half + 1))) + 1) * (option_tab_spacing * space_width / (half + 1)) - edit->curs_col; - while (i > 0) { - edit_insert (edit, ' '); - i -= space_width; + i = ((edit->curs_col / (option_tab_spacing * space_width / (half + 1))) + + 1) * (option_tab_spacing * space_width / (half + 1)) - edit->curs_col; + while (i > 0) + { + edit_insert (edit, ' '); + i -= space_width; } } -static int is_aligned_on_a_tab (WEdit * edit) +static int +is_aligned_on_a_tab (WEdit * edit) { edit_update_curs_col (edit); return !((edit->curs_col % (TAB_SIZE * space_width)) - && edit->curs_col % (TAB_SIZE * space_width) != (HALF_TAB_SIZE * space_width)); + && edit->curs_col % (TAB_SIZE * space_width) != (HALF_TAB_SIZE * space_width)); } -static int right_of_four_spaces (WEdit *edit) +static int +right_of_four_spaces (WEdit * edit) { int i, ch = 0; for (i = 1; i <= HALF_TAB_SIZE; i++) - ch |= edit_get_byte (edit, edit->curs1 - i); + ch |= edit_get_byte (edit, edit->curs1 - i); if (ch == ' ') - return is_aligned_on_a_tab (edit); + return is_aligned_on_a_tab (edit); return 0; } -static int left_of_four_spaces (WEdit *edit) +static int +left_of_four_spaces (WEdit * edit) { int i, ch = 0; for (i = 0; i < HALF_TAB_SIZE; i++) - ch |= edit_get_byte (edit, edit->curs1 + i); + ch |= edit_get_byte (edit, edit->curs1 + i); if (ch == ' ') - return is_aligned_on_a_tab (edit); + return is_aligned_on_a_tab (edit); return 0; } -int edit_indent_width (WEdit * edit, long p) +int +edit_indent_width (WEdit * edit, long p) { long q = p; - while (strchr ("\t ", edit_get_byte (edit, q)) && q < edit->last_byte - 1) /* move to the end of the leading whitespace of the line */ - q++; - return edit_move_forward3 (edit, p, 0, q); /* count the number of columns of indentation */ + while (strchr ("\t ", edit_get_byte (edit, q)) && q < edit->last_byte - 1) /* move to the end of the leading whitespace of the line */ + q++; + return edit_move_forward3 (edit, p, 0, q); /* count the number of columns of indentation */ } -void edit_insert_indent (WEdit * edit, int indent) +void +edit_insert_indent (WEdit * edit, int indent) { - if (!option_fill_tabs_with_spaces) { - while (indent >= TAB_SIZE) { - edit_insert (edit, '\t'); - indent -= TAB_SIZE; - } + if (!option_fill_tabs_with_spaces) + { + while (indent >= TAB_SIZE) + { + edit_insert (edit, '\t'); + indent -= TAB_SIZE; + } } while (indent-- > 0) - edit_insert (edit, ' '); + edit_insert (edit, ' '); } static void @@ -2390,11 +2685,12 @@ edit_auto_indent (WEdit * edit) /* use the previous line as a template */ p = edit_move_backward (edit, p, 1); /* copy the leading whitespace of the line */ - for (;;) { /* no range check - the line _is_ \n-terminated */ - c = edit_get_byte (edit, p++); - if (c != ' ' && c != '\t') - break; - edit_insert (edit, c); + for (;;) + { /* no range check - the line _is_ \n-terminated */ + c = edit_get_byte (edit, p++); + if (c != ' ' && c != '\t') + break; + edit_insert (edit, c); } } @@ -2403,9 +2699,9 @@ edit_double_newline (WEdit * edit) { edit_insert (edit, '\n'); if (edit_get_byte (edit, edit->curs1) == '\n') - return; + return; if (edit_get_byte (edit, edit->curs1 - 2) == '\n') - return; + return; edit->force |= REDRAW_PAGE; edit_insert (edit, '\n'); } @@ -2415,128 +2711,146 @@ edit_tab_cmd (WEdit * edit) { int i; - if (option_fake_half_tabs) { - if (is_in_indent (edit)) { - /*insert a half tab (usually four spaces) unless there is a - half tab already behind, then delete it and insert a - full tab. */ - if (!option_fill_tabs_with_spaces && right_of_four_spaces (edit)) { - for (i = 1; i <= HALF_TAB_SIZE; i++) - edit_backspace (edit, 1); - edit_insert (edit, '\t'); - } else { - insert_spaces_tab (edit, 1); - } - return; - } + if (option_fake_half_tabs) + { + if (is_in_indent (edit)) + { + /*insert a half tab (usually four spaces) unless there is a + half tab already behind, then delete it and insert a + full tab. */ + if (!option_fill_tabs_with_spaces && right_of_four_spaces (edit)) + { + for (i = 1; i <= HALF_TAB_SIZE; i++) + edit_backspace (edit, 1); + edit_insert (edit, '\t'); + } + else + { + insert_spaces_tab (edit, 1); + } + return; + } } - if (option_fill_tabs_with_spaces) { - insert_spaces_tab (edit, 0); - } else { - edit_insert (edit, '\t'); + if (option_fill_tabs_with_spaces) + { + insert_spaces_tab (edit, 0); + } + else + { + edit_insert (edit, '\t'); } } -static void check_and_wrap_line (WEdit * edit) +static void +check_and_wrap_line (WEdit * edit) { int curs, c; if (!option_typewriter_wrap) - return; + return; edit_update_curs_col (edit); if (edit->curs_col < option_word_wrap_line_length) - return; + return; curs = edit->curs1; - for (;;) { - curs--; - c = edit_get_byte (edit, curs); - if (c == '\n' || curs <= 0) { - edit_insert (edit, '\n'); - return; - } - if (c == ' ' || c == '\t') { - int current = edit->curs1; - edit_cursor_move (edit, curs - edit->curs1 + 1); - edit_insert (edit, '\n'); - edit_cursor_move (edit, current - edit->curs1 + 1); - return; - } + for (;;) + { + curs--; + c = edit_get_byte (edit, curs); + if (c == '\n' || curs <= 0) + { + edit_insert (edit, '\n'); + return; + } + if (c == ' ' || c == '\t') + { + int current = edit->curs1; + edit_cursor_move (edit, curs - edit->curs1 + 1); + edit_insert (edit, '\n'); + edit_cursor_move (edit, current - edit->curs1 + 1); + return; + } } } -static inline void edit_execute_macro (WEdit *edit, struct macro macro[], int n); +static inline void edit_execute_macro (WEdit * edit, struct macro macro[], int n); -void edit_push_key_press (WEdit * edit) +void +edit_push_key_press (WEdit * edit) { edit_push_action (edit, KEY_PRESS + edit->start_display); if (edit->mark2 == -1) - edit_push_action (edit, MARK_1 + edit->mark1); + edit_push_action (edit, MARK_1 + edit->mark1); } /* this find the matching bracket in either direction, and sets edit->bracket */ -static long edit_get_bracket (WEdit * edit, int in_screen, unsigned long furthest_bracket_search) +static long +edit_get_bracket (WEdit * edit, int in_screen, unsigned long furthest_bracket_search) { - const char * const b = "{}{[][()(", *p; + const char *const b = "{}{[][()(", *p; int i = 1, a, inc = -1, c, d, n = 0; unsigned long j = 0; long q; edit_update_curs_row (edit); c = edit_get_byte (edit, edit->curs1); p = strchr (b, c); -/* no limit */ + /* no limit */ if (!furthest_bracket_search) - furthest_bracket_search--; -/* not on a bracket at all */ + furthest_bracket_search--; + /* not on a bracket at all */ if (!p) - return -1; -/* the matching bracket */ + return -1; + /* the matching bracket */ d = p[1]; -/* going left or right? */ + /* going left or right? */ if (strchr ("{[(", c)) - inc = 1; - for (q = edit->curs1 + inc;; q += inc) { -/* out of buffer? */ - if (q >= edit->last_byte || q < 0) - break; - a = edit_get_byte (edit, q); -/* don't want to eat CPU */ - if (j++ > furthest_bracket_search) - break; -/* out of screen? */ - if (in_screen) { - if (q < edit->start_display) - break; -/* count lines if searching downward */ - if (inc > 0 && a == '\n') - if (n++ >= edit->num_widget_lines - edit->curs_row) /* out of screen */ - break; - } -/* count bracket depth */ - i += (a == c) - (a == d); -/* return if bracket depth is zero */ - if (!i) - return q; - } -/* no match */ + inc = 1; + for (q = edit->curs1 + inc;; q += inc) + { + /* out of buffer? */ + if (q >= edit->last_byte || q < 0) + break; + a = edit_get_byte (edit, q); + /* don't want to eat CPU */ + if (j++ > furthest_bracket_search) + break; + /* out of screen? */ + if (in_screen) + { + if (q < edit->start_display) + break; + /* count lines if searching downward */ + if (inc > 0 && a == '\n') + if (n++ >= edit->num_widget_lines - edit->curs_row) /* out of screen */ + break; + } + /* count bracket depth */ + i += (a == c) - (a == d); + /* return if bracket depth is zero */ + if (!i) + return q; + } + /* no match */ return -1; } static long last_bracket = -1; -void edit_find_bracket (WEdit * edit) +void +edit_find_bracket (WEdit * edit) { edit->bracket = edit_get_bracket (edit, 1, 10000); if (last_bracket != edit->bracket) - edit->force |= REDRAW_PAGE; + edit->force |= REDRAW_PAGE; last_bracket = edit->bracket; } static inline void -edit_goto_matching_bracket (WEdit *edit) +edit_goto_matching_bracket (WEdit * edit) { long q; q = edit_get_bracket (edit, 0, 0); - if (q >= 0) { + if (q >= 0) + { edit->bracket = edit->curs1; edit->force |= REDRAW_PAGE; edit_cursor_move (edit, q - edit->curs1); @@ -2553,33 +2867,36 @@ edit_goto_matching_bracket (WEdit *edit) * inserted at the cursor. */ void -edit_execute_key_command (WEdit *edit, unsigned long command, int char_for_insertion) +edit_execute_key_command (WEdit * edit, unsigned long command, int char_for_insertion) { - if (command == CK_Begin_Record_Macro) { - edit->macro_i = 0; - edit->force |= REDRAW_CHAR_ONLY | REDRAW_LINE; - return; + if (command == CK_Begin_Record_Macro) + { + edit->macro_i = 0; + edit->force |= REDRAW_CHAR_ONLY | REDRAW_LINE; + return; } - if (command == CK_End_Record_Macro && edit->macro_i != -1) { - edit->force |= REDRAW_COMPLETELY; - edit_save_macro_cmd (edit, edit->macro, edit->macro_i); - edit->macro_i = -1; - return; + if (command == CK_End_Record_Macro && edit->macro_i != -1) + { + edit->force |= REDRAW_COMPLETELY; + edit_save_macro_cmd (edit, edit->macro, edit->macro_i); + edit->macro_i = -1; + return; } - if (edit->macro_i >= 0 && edit->macro_i < MAX_MACRO_LENGTH - 1) { - edit->macro[edit->macro_i].command = command; - edit->macro[edit->macro_i++].ch = char_for_insertion; + if (edit->macro_i >= 0 && edit->macro_i < MAX_MACRO_LENGTH - 1) + { + edit->macro[edit->macro_i].command = command; + edit->macro[edit->macro_i++].ch = char_for_insertion; } /* record the beginning of a set of editing actions initiated by a key press */ if (command != CK_Undo && command != CK_Ext_Mode) - edit_push_key_press (edit); + edit_push_key_press (edit); edit_execute_cmd (edit, command, char_for_insertion); if (column_highlighting) - edit->force |= REDRAW_PAGE; + edit->force |= REDRAW_PAGE; } -static const char * const shell_cmd[] = SHELL_COMMANDS_i; +static const char *const shell_cmd[] = SHELL_COMMANDS_i; /* This executes a command at a lower level than macro recording. @@ -2588,79 +2905,94 @@ static const char * const shell_cmd[] = SHELL_COMMANDS_i; all of them. It also does not check for the Undo command. */ void -edit_execute_cmd (WEdit *edit, unsigned long command, int char_for_insertion) +edit_execute_cmd (WEdit * edit, unsigned long command, int char_for_insertion) { edit->force |= REDRAW_LINE; /* The next key press will unhighlight the found string, so update * the whole page */ if (edit->found_len || column_highlighting) - edit->force |= REDRAW_PAGE; - - if (command / 100 == 6) { /* a highlight command like shift-arrow */ - column_highlighting = 0; - if (!edit->highlight - || (edit->mark2 != -1 && edit->mark1 != edit->mark2)) { - edit_mark_cmd (edit, 1); /* clear */ - edit_mark_cmd (edit, 0); /* marking on */ - } - edit->highlight = 1; - } else { /* any other command */ - if (edit->highlight) - edit_mark_cmd (edit, 0); /* clear */ - edit->highlight = 0; + edit->force |= REDRAW_PAGE; + + if (command / 100 == 6) + { /* a highlight command like shift-arrow */ + column_highlighting = 0; + if (!edit->highlight || (edit->mark2 != -1 && edit->mark1 != edit->mark2)) + { + edit_mark_cmd (edit, 1); /* clear */ + edit_mark_cmd (edit, 0); /* marking on */ + } + edit->highlight = 1; + } + else + { /* any other command */ + if (edit->highlight) + edit_mark_cmd (edit, 0); /* clear */ + edit->highlight = 0; } /* first check for undo */ - if (command == CK_Undo) { - edit_do_undo (edit); - edit->found_len = 0; - edit->prev_col = edit_get_col (edit); - edit->search_start = edit->curs1; - return; + if (command == CK_Undo) + { + edit_do_undo (edit); + edit->found_len = 0; + edit->prev_col = edit_get_col (edit); + edit->search_start = edit->curs1; + return; } /* An ordinary key press */ - if (char_for_insertion >= 0) { - if (edit->overwrite) { - if (edit_get_byte (edit, edit->curs1) != '\n') - edit_delete (edit, 0); - } - if ( option_cursor_beyond_eol && edit->over_col > 0 ) + if (char_for_insertion >= 0) + { + if (edit->overwrite) + { + if (edit_get_byte (edit, edit->curs1) != '\n') + edit_delete (edit, 0); + } + if (option_cursor_beyond_eol && edit->over_col > 0) edit_insert_over (edit); #ifdef HAVE_CHARSET - if ( char_for_insertion > 255 && utf8_display == 0 ) { + if (char_for_insertion > 255 && utf8_display == 0) + { unsigned char str[6 + 1]; size_t i = 0; - int res = g_unichar_to_utf8 (char_for_insertion, (char *)str); - if ( res == 0 ) { + int res = g_unichar_to_utf8 (char_for_insertion, (char *) str); + if (res == 0) + { str[0] = '.'; str[1] = '\0'; - } else { + } + else + { str[res] = '\0'; } - while ( str[i] != 0 && i<=6) { - char_for_insertion = str[i]; - edit_insert (edit, char_for_insertion); - i++; - } - } else + while (str[i] != 0 && i <= 6) + { + char_for_insertion = str[i]; + edit_insert (edit, char_for_insertion); + i++; + } + } + else #endif - edit_insert (edit, char_for_insertion); + edit_insert (edit, char_for_insertion); - if (option_auto_para_formatting) { - format_paragraph (edit, 0); - edit->force |= REDRAW_PAGE; - } else - check_and_wrap_line (edit); - edit->found_len = 0; - edit->prev_col = edit_get_col (edit); - edit->search_start = edit->curs1; - edit_find_bracket (edit); - return; + if (option_auto_para_formatting) + { + format_paragraph (edit, 0); + edit->force |= REDRAW_PAGE; + } + else + check_and_wrap_line (edit); + edit->found_len = 0; + edit->prev_col = edit_get_col (edit); + edit->search_start = edit->curs1; + edit_find_bracket (edit); + return; } - switch (command) { + switch (command) + { case CK_Begin_Page: case CK_End_Page: case CK_Begin_Page_Highlight: @@ -2671,8 +3003,10 @@ edit_execute_cmd (WEdit *edit, unsigned long command, int char_for_insertion) case CK_Down: case CK_Left: case CK_Right: - if ( edit->mark2 >= 0 ) { - if ( !option_persistent_selections ) { + if (edit->mark2 >= 0) + { + if (!option_persistent_selections) + { if (column_highlighting) edit_push_action (edit, COLUMN_ON); column_highlighting = 0; @@ -2681,7 +3015,8 @@ edit_execute_cmd (WEdit *edit, unsigned long command, int char_for_insertion) } } - switch (command) { + switch (command) + { case CK_Begin_Page: case CK_End_Page: case CK_Begin_Page_Highlight: @@ -2696,340 +3031,368 @@ edit_execute_cmd (WEdit *edit, unsigned long command, int char_for_insertion) case CK_Down_Highlight: case CK_Up_Alt_Highlight: case CK_Down_Alt_Highlight: - if (edit->mark2 == -1) - break; /*marking is following the cursor: may need to highlight a whole line */ + if (edit->mark2 == -1) + break; /*marking is following the cursor: may need to highlight a whole line */ case CK_Left: case CK_Right: case CK_Left_Highlight: case CK_Right_Highlight: - edit->force |= REDRAW_CHAR_ONLY; + edit->force |= REDRAW_CHAR_ONLY; } /* basic cursor key commands */ - switch (command) { + switch (command) + { case CK_BackSpace: /* if non persistent selection and text selected */ - if ( !option_persistent_selections ) { - if ( edit->mark1 != edit->mark2 ) { + if (!option_persistent_selections) + { + if (edit->mark1 != edit->mark2) + { edit_block_delete_cmd (edit); break; } } - if ( option_cursor_beyond_eol && edit->over_col > 0 ) { + if (option_cursor_beyond_eol && edit->over_col > 0) + { edit->over_col--; break; } - if (option_backspace_through_tabs && is_in_indent (edit)) { - while (edit_get_byte (edit, edit->curs1 - 1) != '\n' - && edit->curs1 > 0) - edit_backspace (edit, 1); - break; - } else { - if (option_fake_half_tabs) { - int i; - if (is_in_indent (edit) && right_of_four_spaces (edit)) { - for (i = 0; i < HALF_TAB_SIZE; i++) - edit_backspace (edit, 1); - break; - } - } - } - edit_backspace (edit, 0); - break; + if (option_backspace_through_tabs && is_in_indent (edit)) + { + while (edit_get_byte (edit, edit->curs1 - 1) != '\n' && edit->curs1 > 0) + edit_backspace (edit, 1); + break; + } + else + { + if (option_fake_half_tabs) + { + int i; + if (is_in_indent (edit) && right_of_four_spaces (edit)) + { + for (i = 0; i < HALF_TAB_SIZE; i++) + edit_backspace (edit, 1); + break; + } + } + } + edit_backspace (edit, 0); + break; case CK_Delete: /* if non persistent selection and text selected */ - if ( !option_persistent_selections ) { - if ( edit->mark1 != edit->mark2 ) { + if (!option_persistent_selections) + { + if (edit->mark1 != edit->mark2) + { edit_block_delete_cmd (edit); break; } } - if ( option_cursor_beyond_eol && edit->over_col > 0 ) + if (option_cursor_beyond_eol && edit->over_col > 0) edit_insert_over (edit); - if (option_fake_half_tabs) { - int i; - if (is_in_indent (edit) && left_of_four_spaces (edit)) { - for (i = 1; i <= HALF_TAB_SIZE; i++) - edit_delete (edit, 1); - break; - } - } - edit_delete (edit, 0); - break; + if (option_fake_half_tabs) + { + int i; + if (is_in_indent (edit) && left_of_four_spaces (edit)) + { + for (i = 1; i <= HALF_TAB_SIZE; i++) + edit_delete (edit, 1); + break; + } + } + edit_delete (edit, 0); + break; case CK_Delete_Word_Left: edit->over_col = 0; - edit_left_delete_word (edit); - break; + edit_left_delete_word (edit); + break; case CK_Delete_Word_Right: - if ( option_cursor_beyond_eol && edit->over_col > 0 ) + if (option_cursor_beyond_eol && edit->over_col > 0) edit_insert_over (edit); - edit_right_delete_word (edit); - break; + edit_right_delete_word (edit); + break; case CK_Delete_Line: - edit_delete_line (edit); - break; + edit_delete_line (edit); + break; case CK_Delete_To_Line_End: - edit_delete_to_line_end (edit); - break; + edit_delete_to_line_end (edit); + break; case CK_Delete_To_Line_Begin: - edit_delete_to_line_begin (edit); - break; + edit_delete_to_line_begin (edit); + break; case CK_Enter: edit->over_col = 0; - if (option_auto_para_formatting) { - edit_double_newline (edit); - if (option_return_does_auto_indent) - edit_auto_indent (edit); - format_paragraph (edit, 0); - } else { - edit_insert (edit, '\n'); - if (option_return_does_auto_indent) { - edit_auto_indent (edit); - } - } - break; + if (option_auto_para_formatting) + { + edit_double_newline (edit); + if (option_return_does_auto_indent) + edit_auto_indent (edit); + format_paragraph (edit, 0); + } + else + { + edit_insert (edit, '\n'); + if (option_return_does_auto_indent) + { + edit_auto_indent (edit); + } + } + break; case CK_Return: - edit_insert (edit, '\n'); - break; + edit_insert (edit, '\n'); + break; case CK_Page_Up_Alt_Highlight: column_highlighting = 1; case CK_Page_Up: case CK_Page_Up_Highlight: - edit_move_up (edit, edit->num_widget_lines - 1, 1); - break; + edit_move_up (edit, edit->num_widget_lines - 1, 1); + break; case CK_Page_Down_Alt_Highlight: column_highlighting = 1; case CK_Page_Down: case CK_Page_Down_Highlight: - edit_move_down (edit, edit->num_widget_lines - 1, 1); - break; + edit_move_down (edit, edit->num_widget_lines - 1, 1); + break; case CK_Left_Alt_Highlight: column_highlighting = 1; case CK_Left: case CK_Left_Highlight: - if (option_fake_half_tabs) { - if (is_in_indent (edit) && right_of_four_spaces (edit)) { - if ( option_cursor_beyond_eol && edit->over_col > 0) - edit->over_col--; - else - edit_cursor_move (edit, -HALF_TAB_SIZE); - edit->force &= (0xFFF - REDRAW_CHAR_ONLY); - break; - } - } - edit_left_char_move_cmd (edit); - break; + if (option_fake_half_tabs) + { + if (is_in_indent (edit) && right_of_four_spaces (edit)) + { + if (option_cursor_beyond_eol && edit->over_col > 0) + edit->over_col--; + else + edit_cursor_move (edit, -HALF_TAB_SIZE); + edit->force &= (0xFFF - REDRAW_CHAR_ONLY); + break; + } + } + edit_left_char_move_cmd (edit); + break; case CK_Right_Alt_Highlight: column_highlighting = 1; case CK_Right: case CK_Right_Highlight: - if (option_fake_half_tabs) { - if (is_in_indent (edit) && left_of_four_spaces (edit)) { - edit_cursor_move (edit, HALF_TAB_SIZE); - edit->force &= (0xFFF - REDRAW_CHAR_ONLY); - break; - } - } - edit_right_char_move_cmd (edit); - break; + if (option_fake_half_tabs) + { + if (is_in_indent (edit) && left_of_four_spaces (edit)) + { + edit_cursor_move (edit, HALF_TAB_SIZE); + edit->force &= (0xFFF - REDRAW_CHAR_ONLY); + break; + } + } + edit_right_char_move_cmd (edit); + break; case CK_Begin_Page: case CK_Begin_Page_Highlight: - edit_begin_page (edit); - break; + edit_begin_page (edit); + break; case CK_End_Page: case CK_End_Page_Highlight: - edit_end_page (edit); - break; + edit_end_page (edit); + break; case CK_Word_Left: case CK_Word_Left_Highlight: - edit->over_col = 0; - edit_left_word_move_cmd (edit); - break; + edit->over_col = 0; + edit_left_word_move_cmd (edit); + break; case CK_Word_Right: case CK_Word_Right_Highlight: - edit->over_col = 0; - edit_right_word_move_cmd (edit); - break; + edit->over_col = 0; + edit_right_word_move_cmd (edit); + break; case CK_Up_Alt_Highlight: column_highlighting = 1; case CK_Up: case CK_Up_Highlight: - edit_move_up (edit, 1, 0); - break; + edit_move_up (edit, 1, 0); + break; case CK_Down_Alt_Highlight: column_highlighting = 1; case CK_Down: case CK_Down_Highlight: - edit_move_down (edit, 1, 0); - break; + edit_move_down (edit, 1, 0); + break; case CK_Paragraph_Up_Alt_Highlight: column_highlighting = 1; case CK_Paragraph_Up: case CK_Paragraph_Up_Highlight: - edit_move_up_paragraph (edit, 0); - break; + edit_move_up_paragraph (edit, 0); + break; case CK_Paragraph_Down_Alt_Highlight: column_highlighting = 1; case CK_Paragraph_Down: case CK_Paragraph_Down_Highlight: - edit_move_down_paragraph (edit, 0); - break; + edit_move_down_paragraph (edit, 0); + break; case CK_Scroll_Up_Alt_Highlight: column_highlighting = 1; case CK_Scroll_Up: case CK_Scroll_Up_Highlight: - edit_move_up (edit, 1, 1); - break; + edit_move_up (edit, 1, 1); + break; case CK_Scroll_Down_Alt_Highlight: column_highlighting = 1; case CK_Scroll_Down: case CK_Scroll_Down_Highlight: - edit_move_down (edit, 1, 1); - break; + edit_move_down (edit, 1, 1); + break; case CK_Home: case CK_Home_Highlight: - edit_cursor_to_bol (edit); - break; + edit_cursor_to_bol (edit); + break; case CK_End: case CK_End_Highlight: - edit_cursor_to_eol (edit); - break; + edit_cursor_to_eol (edit); + break; case CK_Tab: /* if text marked shift block */ - if ( edit->mark1 != edit->mark2 && !option_persistent_selections ) { + if (edit->mark1 != edit->mark2 && !option_persistent_selections) + { if (edit->mark2 < 0) edit_mark_cmd (edit, 0); edit_move_block_to_right (edit); - } else { - if ( option_cursor_beyond_eol ) + } + else + { + if (option_cursor_beyond_eol) edit_insert_over (edit); edit_tab_cmd (edit); - if (option_auto_para_formatting) { + if (option_auto_para_formatting) + { format_paragraph (edit, 0); edit->force |= REDRAW_PAGE; - } else { + } + else + { check_and_wrap_line (edit); } } break; case CK_Toggle_Insert: - edit->overwrite = (edit->overwrite == 0); - break; + edit->overwrite = (edit->overwrite == 0); + break; case CK_Mark: - if (edit->mark2 >= 0) { - if (column_highlighting) - edit_push_action (edit, COLUMN_ON); - column_highlighting = 0; - } - edit_mark_cmd (edit, 0); - break; + if (edit->mark2 >= 0) + { + if (column_highlighting) + edit_push_action (edit, COLUMN_ON); + column_highlighting = 0; + } + edit_mark_cmd (edit, 0); + break; case CK_Column_Mark: - if (!column_highlighting) - edit_push_action (edit, COLUMN_OFF); - column_highlighting = 1; - edit_mark_cmd (edit, 0); - break; + if (!column_highlighting) + edit_push_action (edit, COLUMN_OFF); + column_highlighting = 1; + edit_mark_cmd (edit, 0); + break; case CK_Mark_All: - edit_set_markers (edit, 0, edit->last_byte, 0, 0); - edit->force |= REDRAW_PAGE; - break; + edit_set_markers (edit, 0, edit->last_byte, 0, 0); + edit->force |= REDRAW_PAGE; + break; case CK_Unmark: - if (column_highlighting) - edit_push_action (edit, COLUMN_ON); - column_highlighting = 0; - edit_mark_cmd (edit, 1); - break; + if (column_highlighting) + edit_push_action (edit, COLUMN_ON); + column_highlighting = 0; + edit_mark_cmd (edit, 1); + break; case CK_Toggle_Line_State: - option_line_state = !option_line_state; - if ( option_line_state ) { - option_line_state_width = LINE_STATE_WIDTH; - } else { - option_line_state_width = 0; - } - edit->force |= REDRAW_PAGE; - break; + option_line_state = !option_line_state; + if (option_line_state) + { + option_line_state_width = LINE_STATE_WIDTH; + } + else + { + option_line_state_width = 0; + } + edit->force |= REDRAW_PAGE; + break; case CK_Toggle_Show_Margin: - show_right_margin = !show_right_margin; - edit->force |= REDRAW_PAGE; - break; + show_right_margin = !show_right_margin; + edit->force |= REDRAW_PAGE; + break; case CK_Toggle_Bookmark: - book_mark_clear (edit, edit->curs_line, BOOK_MARK_FOUND_COLOR); - if (book_mark_query_color (edit, edit->curs_line, BOOK_MARK_COLOR)) - book_mark_clear (edit, edit->curs_line, BOOK_MARK_COLOR); - else - book_mark_insert (edit, edit->curs_line, BOOK_MARK_COLOR); - break; + book_mark_clear (edit, edit->curs_line, BOOK_MARK_FOUND_COLOR); + if (book_mark_query_color (edit, edit->curs_line, BOOK_MARK_COLOR)) + book_mark_clear (edit, edit->curs_line, BOOK_MARK_COLOR); + else + book_mark_insert (edit, edit->curs_line, BOOK_MARK_COLOR); + break; case CK_Flush_Bookmarks: - book_mark_flush (edit, BOOK_MARK_COLOR); - book_mark_flush (edit, BOOK_MARK_FOUND_COLOR); - edit->force |= REDRAW_PAGE; - break; + book_mark_flush (edit, BOOK_MARK_COLOR); + book_mark_flush (edit, BOOK_MARK_FOUND_COLOR); + edit->force |= REDRAW_PAGE; + break; case CK_Next_Bookmark: - if (edit->book_mark) { - struct _book_mark *p; - p = (struct _book_mark *) book_mark_find (edit, - edit->curs_line); - if (p->next) { - p = p->next; - if (p->line >= edit->start_line + edit->num_widget_lines - || p->line < edit->start_line) - edit_move_display (edit, - p->line - - edit->num_widget_lines / 2); - edit_move_to_line (edit, p->line); - } - } - break; + if (edit->book_mark) + { + struct _book_mark *p; + p = (struct _book_mark *) book_mark_find (edit, edit->curs_line); + if (p->next) + { + p = p->next; + if (p->line >= edit->start_line + edit->num_widget_lines + || p->line < edit->start_line) + edit_move_display (edit, p->line - edit->num_widget_lines / 2); + edit_move_to_line (edit, p->line); + } + } + break; case CK_Prev_Bookmark: - if (edit->book_mark) { - struct _book_mark *p; - p = (struct _book_mark *) book_mark_find (edit, - edit->curs_line); - while (p->line == edit->curs_line) - if (p->prev) - p = p->prev; - if (p->line >= 0) { - if (p->line >= edit->start_line + edit->num_widget_lines - || p->line < edit->start_line) - edit_move_display (edit, - p->line - - edit->num_widget_lines / 2); - edit_move_to_line (edit, p->line); - } - } - break; + if (edit->book_mark) + { + struct _book_mark *p; + p = (struct _book_mark *) book_mark_find (edit, edit->curs_line); + while (p->line == edit->curs_line) + if (p->prev) + p = p->prev; + if (p->line >= 0) + { + if (p->line >= edit->start_line + edit->num_widget_lines + || p->line < edit->start_line) + edit_move_display (edit, p->line - edit->num_widget_lines / 2); + edit_move_to_line (edit, p->line); + } + } + break; case CK_Beginning_Of_Text: case CK_Beginning_Of_Text_Highlight: - edit_move_to_top (edit); - break; + edit_move_to_top (edit); + break; case CK_End_Of_Text: case CK_End_Of_Text_Highlight: - edit_move_to_bottom (edit); - break; + edit_move_to_bottom (edit); + break; case CK_Copy: - if ( option_cursor_beyond_eol && edit->over_col > 0 ) + if (option_cursor_beyond_eol && edit->over_col > 0) edit_insert_over (edit); - edit_block_copy_cmd (edit); - break; + edit_block_copy_cmd (edit); + break; case CK_Remove: - edit_block_delete_cmd (edit); - break; + edit_block_delete_cmd (edit); + break; case CK_Move: - if ( option_cursor_beyond_eol && edit->over_col > 0 ) + if (option_cursor_beyond_eol && edit->over_col > 0) edit_insert_over (edit); - edit_block_move_cmd (edit); - break; + edit_block_move_cmd (edit); + break; case CK_Shift_Block_Left: if (edit->mark1 != edit->mark2) @@ -3040,199 +3403,203 @@ edit_execute_cmd (WEdit *edit, unsigned long command, int char_for_insertion) edit_move_block_to_right (edit); break; case CK_XStore: - edit_copy_to_X_buf_cmd (edit); - break; + edit_copy_to_X_buf_cmd (edit); + break; case CK_XCut: - edit_cut_to_X_buf_cmd (edit); - break; + edit_cut_to_X_buf_cmd (edit); + break; case CK_XPaste: - if ( option_cursor_beyond_eol && edit->over_col > 0 ) + if (option_cursor_beyond_eol && edit->over_col > 0) edit_insert_over (edit); - edit_paste_from_X_buf_cmd (edit); - break; + edit_paste_from_X_buf_cmd (edit); + break; case CK_Selection_History: - edit_paste_from_history (edit); - break; + edit_paste_from_history (edit); + break; case CK_Save_As: - edit_save_as_cmd (edit); - break; + edit_save_as_cmd (edit); + break; case CK_Save: - edit_save_confirm_cmd (edit); - break; + edit_save_confirm_cmd (edit); + break; case CK_Load: - edit_load_cmd (edit, EDIT_FILE_COMMON); - break; + edit_load_cmd (edit, EDIT_FILE_COMMON); + break; case CK_Save_Block: - edit_save_block_cmd (edit); - break; + edit_save_block_cmd (edit); + break; case CK_Insert_File: - edit_insert_file_cmd (edit); - break; + edit_insert_file_cmd (edit); + break; case CK_Load_Prev_File: - edit_load_back_cmd (edit); - break; + edit_load_back_cmd (edit); + break; case CK_Load_Next_File: - edit_load_forward_cmd (edit); - break; + edit_load_forward_cmd (edit); + break; case CK_Load_Syntax_File: - edit_load_cmd (edit, EDIT_FILE_SYNTAX); - break; + edit_load_cmd (edit, EDIT_FILE_SYNTAX); + break; case CK_Choose_Syntax: - edit_syntax_dialog (); - break; + edit_syntax_dialog (); + break; case CK_Load_Menu_File: - edit_load_cmd (edit, EDIT_FILE_MENU); - break; + edit_load_cmd (edit, EDIT_FILE_MENU); + break; case CK_Toggle_Syntax: - if ((option_syntax_highlighting ^= 1) == 1) - edit_load_syntax (edit, NULL, option_syntax_type); - edit->force |= REDRAW_PAGE; - break; + if ((option_syntax_highlighting ^= 1) == 1) + edit_load_syntax (edit, NULL, option_syntax_type); + edit->force |= REDRAW_PAGE; + break; case CK_Toggle_Tab_TWS: - enable_show_tabs_tws ^= 1; - edit->force |= REDRAW_PAGE; - break; + enable_show_tabs_tws ^= 1; + edit->force |= REDRAW_PAGE; + break; case CK_Find: - edit_search_cmd (edit, 0); - break; + edit_search_cmd (edit, 0); + break; case CK_Find_Again: - edit_search_cmd (edit, 1); - break; + edit_search_cmd (edit, 1); + break; case CK_Replace: - edit_replace_cmd (edit, 0); - break; + edit_replace_cmd (edit, 0); + break; case CK_Replace_Again: - edit_replace_cmd (edit, 1); - break; + edit_replace_cmd (edit, 1); + break; case CK_Complete_Word: /* if text marked shift block */ - if ( edit->mark1 != edit->mark2 && !option_persistent_selections ) { + if (edit->mark1 != edit->mark2 && !option_persistent_selections) + { edit_move_block_to_left (edit); - } else { + } + else + { edit_complete_word_cmd (edit); } - break; + break; case CK_Find_Definition: - edit_get_match_keyword_cmd (edit); - break; + edit_get_match_keyword_cmd (edit); + break; case CK_Quit: - dlg_stop (edit->widget.parent); - break; + dlg_stop (edit->widget.parent); + break; case CK_New: - edit_new_cmd (edit); - break; + edit_new_cmd (edit); + break; case CK_Help: - edit_help_cmd (edit); - break; + edit_help_cmd (edit); + break; case CK_Refresh: - edit_refresh_cmd (edit); - break; + edit_refresh_cmd (edit); + break; case CK_SaveSetupCmd: - save_setup_cmd (); - break; + save_setup_cmd (); + break; case CK_About: - query_dialog (_(" About "), - _("\n Cooledit v3.11.5\n\n" - " Copyright (C) 1996 the Free Software Foundation\n\n" - " A user friendly text editor written\n" - " for the Midnight Commander.\n"), D_NORMAL, - 1, _("&OK")); - break; + query_dialog (_(" About "), + _("\n Cooledit v3.11.5\n\n" + " Copyright (C) 1996 the Free Software Foundation\n\n" + " A user friendly text editor written\n" + " for the Midnight Commander.\n"), D_NORMAL, 1, _("&OK")); + break; case CK_LearnKeys: - learn_keys (); - break; + learn_keys (); + break; case CK_Edit_Options: - edit_options_dialog (); - break; + edit_options_dialog (); + break; case CK_Edit_Save_Mode: - menu_save_mode_cmd (); - break; + menu_save_mode_cmd (); + break; case CK_Date: - { - char s[BUF_MEDIUM]; - /* fool gcc to prevent a Y2K warning */ - char time_format[] = "_c"; - time_format[0] = '%'; - - FMT_LOCALTIME_CURRENT(s, sizeof(s), time_format); - edit_print_string (edit, s); - edit->force |= REDRAW_PAGE; - break; - } - break; + { + char s[BUF_MEDIUM]; + /* fool gcc to prevent a Y2K warning */ + char time_format[] = "_c"; + time_format[0] = '%'; + + FMT_LOCALTIME_CURRENT (s, sizeof (s), time_format); + edit_print_string (edit, s); + edit->force |= REDRAW_PAGE; + break; + } + break; case CK_Goto: - edit_goto_cmd (edit); - break; + edit_goto_cmd (edit); + break; case CK_Paragraph_Format: - format_paragraph (edit, 1); - edit->force |= REDRAW_PAGE; - break; + format_paragraph (edit, 1); + edit->force |= REDRAW_PAGE; + break; case CK_Delete_Macro: - edit_delete_macro_cmd (edit); - break; + edit_delete_macro_cmd (edit); + break; case CK_Match_Bracket: - edit_goto_matching_bracket (edit); - break; + edit_goto_matching_bracket (edit); + break; case CK_User_Menu: - user_menu (edit); - break; + user_menu (edit); + break; case CK_Sort: - edit_sort_cmd (edit); - break; + edit_sort_cmd (edit); + break; case CK_ExtCmd: - edit_ext_cmd (edit); - break; + edit_ext_cmd (edit); + break; case CK_Mail: - edit_mail_dialog (edit); - break; + edit_mail_dialog (edit); + break; case CK_Shell: - view_other_cmd (); - break; + view_other_cmd (); + break; case CK_SelectCodepage: - edit_select_codepage_cmd (edit); - break; + edit_select_codepage_cmd (edit); + break; case CK_Insert_Literal: - edit_insert_literal_cmd (edit); - break; + edit_insert_literal_cmd (edit); + break; case CK_Execute_Macro: - edit_execute_macro_cmd (edit); - break; + edit_execute_macro_cmd (edit); + break; case CK_Begin_End_Macro: - edit_begin_end_macro_cmd (edit); - break; + edit_begin_end_macro_cmd (edit); + break; case CK_Ext_Mode: - edit->extmod = 1; - break; + edit->extmod = 1; + break; default: - break; + break; } /* CK_Pipe_Block */ - if ((command / 1000) == 1) /* a shell command */ - edit_block_process_cmd (edit, shell_cmd[command - 1000], 1); - if (command > CK_Macro (0) && command <= CK_Last_Macro) { /* a macro command */ - struct macro m[MAX_MACRO_LENGTH]; - int nm; - if (edit_load_macro_cmd (edit, m, &nm, command - 2000)) - edit_execute_macro (edit, m, nm); + if ((command / 1000) == 1) /* a shell command */ + edit_block_process_cmd (edit, shell_cmd[command - 1000], 1); + if (command > CK_Macro (0) && command <= CK_Last_Macro) + { /* a macro command */ + struct macro m[MAX_MACRO_LENGTH]; + int nm; + if (edit_load_macro_cmd (edit, m, &nm, command - 2000)) + edit_execute_macro (edit, m, nm); } /* keys which must set the col position, and the search vars */ - switch (command) { + switch (command) + { case CK_Find: case CK_Find_Again: case CK_Replace: case CK_Replace_Again: case CK_Complete_Word: - edit->prev_col = edit_get_col (edit); - break; + edit->prev_col = edit_get_col (edit); + break; case CK_Up: case CK_Up_Highlight: case CK_Up_Alt_Highlight: @@ -3261,44 +3628,48 @@ edit_execute_cmd (WEdit *edit, unsigned long command, int char_for_insertion) case CK_Scroll_Down: case CK_Scroll_Down_Highlight: case CK_Scroll_Down_Alt_Highlight: - edit->search_start = edit->curs1; - edit->found_len = 0; - break; + edit->search_start = edit->curs1; + edit->found_len = 0; + break; default: - edit->found_len = 0; - edit->prev_col = edit_get_col (edit); - edit->search_start = edit->curs1; + edit->found_len = 0; + edit->prev_col = edit_get_col (edit); + edit->search_start = edit->curs1; } edit_find_bracket (edit); - if (option_auto_para_formatting) { - switch (command) { - case CK_BackSpace: - case CK_Delete: - case CK_Delete_Word_Left: - case CK_Delete_Word_Right: - case CK_Delete_To_Line_End: - case CK_Delete_To_Line_Begin: - format_paragraph (edit, 0); - edit->force |= REDRAW_PAGE; - } + if (option_auto_para_formatting) + { + switch (command) + { + case CK_BackSpace: + case CK_Delete: + case CK_Delete_Word_Left: + case CK_Delete_Word_Right: + case CK_Delete_To_Line_End: + case CK_Delete_To_Line_Begin: + format_paragraph (edit, 0); + edit->force |= REDRAW_PAGE; + } } } static void -edit_execute_macro (WEdit *edit, struct macro macro[], int n) +edit_execute_macro (WEdit * edit, struct macro macro[], int n) { int i = 0; - if (edit->macro_depth++ > 256) { - edit_error_dialog (_("Error"), _("Macro recursion is too deep")); - edit->macro_depth--; - return; + if (edit->macro_depth++ > 256) + { + edit_error_dialog (_("Error"), _("Macro recursion is too deep")); + edit->macro_depth--; + return; } edit->force |= REDRAW_PAGE; - for (; i < n; i++) { - edit_execute_cmd (edit, macro[i].command, macro[i].ch); + for (; i < n; i++) + { + edit_execute_cmd (edit, macro[i].command, macro[i].ch); } edit_update_screen (edit); edit->macro_depth--; @@ -3317,27 +3688,29 @@ user_menu (WEdit * edit) nomark = eval_marks (edit, &start_mark, &end_mark); if (nomark == 0) - edit_save_block (edit, block_file, start_mark, end_mark); + edit_save_block (edit, block_file, start_mark, end_mark); /* run shell scripts from menu */ user_menu_cmd (edit); - if ((mc_stat (block_file, &status) == 0) && (status.st_size != 0)) { - int rc = 0; - FILE *fd; + if ((mc_stat (block_file, &status) == 0) && (status.st_size != 0)) + { + int rc = 0; + FILE *fd; - if (nomark == 0) { - /* i.e. we have marked block */ - rc = edit_block_delete_cmd (edit); - } + if (nomark == 0) + { + /* i.e. we have marked block */ + rc = edit_block_delete_cmd (edit); + } - if (rc == 0) - edit_insert_file (edit, block_file); + if (rc == 0) + edit_insert_file (edit, block_file); - /* truncate block file */ - fd = fopen (block_file, "w"); - if (fd != NULL) - fclose (fd); + /* truncate block file */ + fd = fopen (block_file, "w"); + if (fd != NULL) + fclose (fd); } edit_refresh_cmd (edit); edit->force |= REDRAW_COMPLETELY; @@ -3348,11 +3721,10 @@ user_menu (WEdit * edit) void edit_stack_init (void) { - for (edit_stack_iterator = 0; - edit_stack_iterator < MAX_HISTORY_MOVETO; - edit_stack_iterator++ ) { - edit_history_moveto[edit_stack_iterator].filename = NULL; - edit_history_moveto[edit_stack_iterator].line = -1; + for (edit_stack_iterator = 0; edit_stack_iterator < MAX_HISTORY_MOVETO; edit_stack_iterator++) + { + edit_history_moveto[edit_stack_iterator].filename = NULL; + edit_history_moveto[edit_stack_iterator].line = -1; } edit_stack_iterator = 0; @@ -3361,10 +3733,8 @@ edit_stack_init (void) void edit_stack_free (void) { - for (edit_stack_iterator = 0; - edit_stack_iterator < MAX_HISTORY_MOVETO; - edit_stack_iterator++) - g_free (edit_history_moveto[edit_stack_iterator].filename); + for (edit_stack_iterator = 0; edit_stack_iterator < MAX_HISTORY_MOVETO; edit_stack_iterator++) + g_free (edit_history_moveto[edit_stack_iterator].filename); } /* move i lines */ @@ -3380,4 +3750,3 @@ edit_move_down (WEdit * edit, unsigned long i, int do_scroll) { edit_move_updown (edit, i, do_scroll, FALSE); } - diff --git a/src/mountlist.c b/src/mountlist.c dissimilarity index 60% index a773c6dd..199a66ca 100644 --- a/src/mountlist.c +++ b/src/mountlist.c @@ -1,916 +1,964 @@ -/* mountlist.c -- return a list of mounted filesystems - Copyright (C) 1991, 1992 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/** \file mountlist.c - * \brief Source: list of mounted filesystems - */ - -#include - -#include -#include - -#include - -/* This header needs to be included before sys/mount.h on *BSD */ -#ifdef HAVE_SYS_PARAM_H -#include -#endif - -#if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */ -#include -#include -#endif /* MOUNTED_GETFSSTAT */ - -#ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ -#include -#if !defined(MOUNTED) -#if defined(MNT_MNTTAB) /* HP-UX. */ -#define MOUNTED MNT_MNTTAB -#endif -#if defined(MNTTABNAME) /* Dynix. */ -#define MOUNTED MNTTABNAME -#endif -#endif -#endif - -#ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ -#include -#endif - -#ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */ -#include -#endif - -#ifdef MOUNTED_GETMNT /* Ultrix. */ -#include -#include -#endif - -#ifdef MOUNTED_FREAD /* SVR2. */ -#include -#endif - -#ifdef MOUNTED_FREAD_FSTYP /* SVR3. */ -#include -#include -#include -#endif - -#ifdef MOUNTED_GETMNTENT2 /* SVR4. */ -#include -#endif - -#ifdef MOUNTED_VMOUNT /* AIX. */ -#include -#include -#endif - -#ifdef HAVE_SYS_STATFS_H -#include -#endif - -#ifdef HAVE_INFOMOUNT_QNX -#include -#include -#endif - -#ifdef HAVE_SYS_MOUNT_H -#include -#endif - -#ifdef HAVE_SYS_VFS_H -#include -#endif - -#ifdef HAVE_SYS_FILSYS_H -#include /* SVR2. */ -#endif - -#ifdef HAVE_DUSTAT_H /* AIX PS/2. */ -#include -#endif - -#ifdef HAVE_SYS_STATVFS_H /* SVR4. */ -#include -#endif - -#include "lib/global.h" -#include "mountlist.h" - -#ifdef DOLPHIN -/* So special that it's not worth putting this in autoconf. */ -#undef MOUNTED_FREAD_FSTYP -#define MOUNTED_GETMNTTBL -#endif - -#if defined (__QNX__) && !defined(__QNXNTO__) && !defined (HAVE_INFOMOUNT_LIST) -# define HAVE_INFOMOUNT_QNX -#endif - -#if defined(HAVE_INFOMOUNT_LIST) || defined(HAVE_INFOMOUNT_QNX) -# define HAVE_INFOMOUNT -#endif - -/* A mount table entry. */ -struct mount_entry -{ - char *me_devname; /* Device node pathname, including "/dev/". */ - char *me_mountdir; /* Mount point directory pathname. */ - char *me_type; /* "nfs", "4.2", etc. */ - dev_t me_dev; /* Device number of me_mountdir. */ - struct mount_entry *me_next; -}; - -struct fs_usage -{ - fsblkcnt_t fsu_blocks; /* Total blocks. */ - fsblkcnt_t fsu_bfree; /* Free blocks available to superuser. */ - fsblkcnt_t fsu_bavail; /* Free blocks available to non-superuser. */ - fsfilcnt_t fsu_files; /* Total file nodes. */ - fsfilcnt_t fsu_ffree; /* Free file nodes. */ -}; - -static int get_fs_usage (char *path, struct fs_usage *fsp); - -#ifdef HAVE_INFOMOUNT_LIST - -static struct mount_entry *mount_list = NULL; - -static void free_mount_entry (struct mount_entry *me) -{ - if (!me) - return; - if (me->me_devname) - free (me->me_devname); - if (me->me_mountdir) - free (me->me_mountdir); - if (me->me_type) - free (me->me_type); - free (me); -} - -#ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ -/* Return the value of the hexadecimal number represented by CP. - No prefix (like '0x') or suffix (like 'h') is expected to be - part of CP. */ - -static int xatoi (const char *cp) -{ - int val; - - val = 0; - while (*cp) { - if (*cp >= 'a' && *cp <= 'f') - val = val * 16 + *cp - 'a' + 10; - else if (*cp >= 'A' && *cp <= 'F') - val = val * 16 + *cp - 'A' + 10; - else if (*cp >= '0' && *cp <= '9') - val = val * 16 + *cp - '0'; - else - break; - cp++; - } - return val; -} -#endif /* MOUNTED_GETMNTENT1 */ - -#ifdef MOUNTED_GETMNTINFO - -#ifndef HAVE_STRUCT_STATFS_F_FSTYPENAME -static char *fstype_to_string (short t) -{ - switch (t) { -#ifdef MOUNT_PC - case MOUNT_PC: - return "pc"; -#endif -#ifdef MOUNT_MFS - case MOUNT_MFS: - return "mfs"; -#endif -#ifdef MOUNT_LO - case MOUNT_LO: - return "lo"; -#endif -#ifdef MOUNT_TFS - case MOUNT_TFS: - return "tfs"; -#endif -#ifdef MOUNT_TMP - case MOUNT_TMP: - return "tmp"; -#endif -#ifdef MOUNT_UFS - case MOUNT_UFS: - return "ufs" ; -#endif -#ifdef MOUNT_NFS - case MOUNT_NFS: - return "nfs" ; -#endif -#ifdef MOUNT_MSDOS - case MOUNT_MSDOS: - return "msdos" ; -#endif -#ifdef MOUNT_LFS - case MOUNT_LFS: - return "lfs" ; -#endif -#ifdef MOUNT_LOFS - case MOUNT_LOFS: - return "lofs" ; -#endif -#ifdef MOUNT_FDESC - case MOUNT_FDESC: - return "fdesc" ; -#endif -#ifdef MOUNT_PORTAL - case MOUNT_PORTAL: - return "portal" ; -#endif -#ifdef MOUNT_NULL - case MOUNT_NULL: - return "null" ; -#endif -#ifdef MOUNT_UMAP - case MOUNT_UMAP: - return "umap" ; -#endif -#ifdef MOUNT_KERNFS - case MOUNT_KERNFS: - return "kernfs" ; -#endif -#ifdef MOUNT_PROCFS - case MOUNT_PROCFS: - return "procfs" ; -#endif -#ifdef MOUNT_AFS - case MOUNT_AFS: - return "afs" ; -#endif -#ifdef MOUNT_CD9660 - case MOUNT_CD9660: - return "cd9660" ; -#endif -#ifdef MOUNT_UNION - case MOUNT_UNION: - return "union" ; -#endif -#ifdef MOUNT_DEVFS - case MOUNT_DEVFS: - return "devfs" ; -#endif -#ifdef MOUNT_EXT2FS - case MOUNT_EXT2FS: - return "ext2fs" ; -#endif - default: - return "?"; - } -} -#endif /* ! HAVE_STRUCT_STATFS_F_FSTYPENAME */ - -#endif /* MOUNTED_GETMNTINFO */ - -#ifdef MOUNTED_VMOUNT /* AIX. */ -static char * -fstype_to_string (int t) -{ - struct vfs_ent *e; - - e = getvfsbytype (t); - if (!e || !e->vfsent_name) - return "none"; - else - return e->vfsent_name; -} -#endif /* MOUNTED_VMOUNT */ - -/* Return a list of the currently mounted filesystems, or NULL on error. - Add each entry to the tail of the list so that they stay in order. - If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in - the returned list are valid. Otherwise, they might not be. - If ALL_FS is zero, do not return entries for filesystems that - are automounter (dummy) entries. */ - -static struct mount_entry * -read_filesystem_list (int need_fs_type, int all_fs) -{ - struct mount_entry *mlist; - struct mount_entry *me; - struct mount_entry *mtail; - - (void) need_fs_type; - (void) all_fs; - - /* Start the list off with a dummy entry. */ - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); - me->me_next = NULL; - mlist = mtail = me; - -#ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ -#ifdef MOUNTED - { - struct mntent *mnt; - FILE *fp; - const char *devopt; - - fp = setmntent (MOUNTED, "r"); - if (fp == NULL) - return NULL; - - while ((mnt = getmntent (fp))) { - if (!all_fs && (!strcmp (mnt->mnt_type, "ignore") - || !strcmp (mnt->mnt_type, "auto"))) - continue; - - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); - me->me_devname = strdup (mnt->mnt_fsname); - me->me_mountdir = strdup (mnt->mnt_dir); - me->me_type = strdup (mnt->mnt_type); - devopt = strstr (mnt->mnt_opts, "dev="); - if (devopt) { - if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X')) - me->me_dev = xatoi (devopt + 6); - else - me->me_dev = xatoi (devopt + 4); - } else - me->me_dev = -1; /* Magic; means not known yet. */ - me->me_next = NULL; - - /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; - } - - if (endmntent (fp) == 0) - return NULL; - } -#endif /* MOUNTED */ -#endif /* MOUNTED_GETMNTENT1 */ - -#ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ - { - struct statfs *fsp; - int entries; - - entries = getmntinfo (&fsp, MNT_NOWAIT); - if (entries < 0) - return NULL; - while (entries-- > 0) { - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); - me->me_devname = strdup (fsp->f_mntfromname); - me->me_mountdir = strdup (fsp->f_mntonname); -#ifdef HAVE_STRUCT_STATFS_F_FSTYPENAME - me->me_type = strdup (fsp->f_fstypename); -#else - me->me_type = fstype_to_string (fsp->f_type); -#endif - me->me_dev = -1; /* Magic; means not known yet. */ - me->me_next = NULL; - - /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; - fsp++; - } - } -#endif /* MOUNTED_GETMNTINFO */ - -#ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */ - { - struct statvfs *fsp; - int entries; - - entries = getmntinfo (&fsp, MNT_NOWAIT); - if (entries < 0) - return NULL; - for (; entries-- > 0; fsp++) { - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); - me->me_devname = strdup (fsp->f_mntfromname); - me->me_mountdir = strdup (fsp->f_mntonname); - me->me_type = strdup (fsp->f_fstypename); - me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ - - /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; - } - } -#endif /* MOUNTED_GETMNTINFO2 */ - -#ifdef MOUNTED_GETMNT /* Ultrix. */ - { - int offset = 0; - int val; - struct fs_data fsd; - - while ((val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, - NULL)) > 0) { - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); - me->me_devname = strdup (fsd.fd_req.devname); - me->me_mountdir = strdup (fsd.fd_req.path); - me->me_type = gt_names[fsd.fd_req.fstype]; - me->me_dev = fsd.fd_req.dev; - me->me_next = NULL; - - /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; - } - if (val < 0) - return NULL; - } -#endif /* MOUNTED_GETMNT */ - -#ifdef MOUNTED_GETFSSTAT /* __alpha running OSF_1 */ - { - int numsys, counter, bufsize; - struct statfs *stats; - - numsys = getfsstat ((struct statfs *) 0, 0L, MNT_WAIT); - if (numsys < 0) - return (NULL); - - bufsize = (1 + numsys) * sizeof (struct statfs); - stats = (struct statfs *) malloc (bufsize); - numsys = getfsstat (stats, bufsize, MNT_WAIT); - - if (numsys < 0) { - free (stats); - return (NULL); - } - for (counter = 0; counter < numsys; counter++) { - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); - me->me_devname = strdup (stats[counter].f_mntfromname); - me->me_mountdir = strdup (stats[counter].f_mntonname); - me->me_type = mnt_names[stats[counter].f_type]; - me->me_dev = -1; /* Magic; means not known yet. */ - me->me_next = NULL; - - /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; - } - - free (stats); - } -#endif /* MOUNTED_GETFSSTAT */ - -#if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */ - { - struct mnttab mnt; - char *table = "/etc/mnttab"; - FILE *fp; - - fp = fopen (table, "r"); - if (fp == NULL) - return NULL; - - while (fread (&mnt, sizeof mnt, 1, fp) > 0) { - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); -#ifdef GETFSTYP /* SVR3. */ - me->me_devname = strdup (mnt.mt_dev); -#else - me->me_devname = malloc (strlen (mnt.mt_dev) + 6); - strcpy (me->me_devname, "/dev/"); - strcpy (me->me_devname + 5, mnt.mt_dev); -#endif - me->me_mountdir = strdup (mnt.mt_filsys); - me->me_dev = -1; /* Magic; means not known yet. */ - me->me_type = ""; -#ifdef GETFSTYP /* SVR3. */ - if (need_fs_type) { - struct statfs fsd; - char typebuf[FSTYPSZ]; - - if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1 - && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1) - me->me_type = strdup (typebuf); - } -#endif - me->me_next = NULL; - - /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; - } - - if (fclose (fp) == EOF) - return NULL; - } -#endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP */ - -#ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */ - { - struct mntent **mnttbl = getmnttbl (), **ent; - for (ent = mnttbl; *ent; ent++) { - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); - me->me_devname = strdup ((*ent)->mt_resource); - me->me_mountdir = strdup ((*ent)->mt_directory); - me->me_type = strdup ((*ent)->mt_fstype); - me->me_dev = -1; /* Magic; means not known yet. */ - me->me_next = NULL; - - /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; - } - endmnttbl (); - } -#endif /* MOUNTED_GETMNTTBL */ - -#ifdef MOUNTED_GETMNTENT2 /* SVR4. */ - { - struct mnttab mnt; - char *table = MNTTAB; - FILE *fp; - int ret; - - fp = fopen (table, "r"); - if (fp == NULL) - return NULL; - - while ((ret = getmntent (fp, &mnt)) == 0) { - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); - me->me_devname = strdup (mnt.mnt_special); - me->me_mountdir = strdup (mnt.mnt_mountp); - me->me_type = strdup (mnt.mnt_fstype); - me->me_dev = -1; /* Magic; means not known yet. */ - me->me_next = NULL; - /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; - } - - if (ret > 0) - return NULL; - if (fclose (fp) == EOF) - return NULL; - } -#endif /* MOUNTED_GETMNTENT2 */ - -#ifdef MOUNTED_VMOUNT /* AIX. */ - { - int bufsize; - char *entries, *thisent; - struct vmount *vmp; - - /* Ask how many bytes to allocate for the mounted filesystem info. */ - mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize); - entries = malloc (bufsize); - - /* Get the list of mounted filesystems. */ - mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries); - - for (thisent = entries; thisent < entries + bufsize; - thisent += vmp->vmt_length) { - vmp = (struct vmount *) thisent; - me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); - if (vmp->vmt_flags & MNT_REMOTE) { - char *host, *path; - - /* Prepend the remote pathname. */ - host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off; - path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off; - me->me_devname = malloc (strlen (host) + strlen (path) + 2); - strcpy (me->me_devname, host); - strcat (me->me_devname, ":"); - strcat (me->me_devname, path); - } else { - 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_type = strdup (fstype_to_string (vmp->vmt_gfstype)); - me->me_dev = -1; /* vmt_fsid might be the info we want. */ - me->me_next = NULL; - - /* Add to the linked list. */ - mtail->me_next = me; - mtail = me; - } - free (entries); - } -#endif /* MOUNTED_VMOUNT */ - - /* Free the dummy head. */ - me = mlist; - mlist = mlist->me_next; - free (me); - return mlist; -} -#endif /* HAVE_INFOMOUNT_LIST */ - -#ifdef HAVE_INFOMOUNT_QNX -/* -** QNX has no [gs]etmnt*(), [gs]etfs*(), or /etc/mnttab, but can do -** this via the following code. -** Note that, as this is based on CWD, it only fills one mount_entry -** structure. See my_statfs() in utilunix.c for the "other side" of -** this hack. -*/ - -static struct mount_entry * -read_filesystem_list(int need_fs_type, int all_fs) -{ - struct _disk_entry de; - struct statfs fs; - int i, fd; - char *tp, dev[_POSIX_NAME_MAX], dir[_POSIX_PATH_MAX]; - - static struct mount_entry *me = NULL; - - if (me) - { - if (me->me_devname) free(me->me_devname); - if (me->me_mountdir) free(me->me_mountdir); - if (me->me_type) free(me->me_type); - } - else - me = (struct mount_entry *)malloc(sizeof(struct mount_entry)); - - if (!getcwd(dir, _POSIX_PATH_MAX)) return (NULL); - - if ((fd = open(dir, O_RDONLY)) == -1) return (NULL); - - i = disk_get_entry(fd, &de); - - close(fd); - - if (i == -1) return (NULL); - - switch (de.disk_type) - { - case _UNMOUNTED: tp = "unmounted"; break; - case _FLOPPY: tp = "Floppy"; break; - case _HARD: 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_pt(dev, &dir) == -1) return (NULL); - - me->me_devname = strdup(dev); - me->me_mountdir = strdup(dir); - me->me_type = strdup(tp); - me->me_dev = de.disk_type; - -#ifdef DEBUG - 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); - fprintf(stderr, "fsys_get_mount_dev():\n\tdevice='%s'\n", dev); - fprintf(stderr, "fsys_get_mount_pt():\n\tmount point='%s'\n", dir); -#endif /* DEBUG */ - - return (me); -} -#endif /* HAVE_INFOMOUNT_QNX */ - -void -free_my_statfs (void) -{ -#ifdef HAVE_INFOMOUNT_LIST - while (mount_list) { - struct mount_entry *next = mount_list->me_next; - free_mount_entry (mount_list); - 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); -#endif /* HAVE_INFOMOUNT_LIST */ -} - -void -my_statfs (struct my_statfs *myfs_stats, const char *path) -{ -#ifdef HAVE_INFOMOUNT_LIST - int i, len = 0; - struct mount_entry *entry = NULL; - struct mount_entry *temp = mount_list; - struct fs_usage fs_use; - - while (temp){ - i = strlen (temp->me_mountdir); - if (i > len && (strncmp (path, temp->me_mountdir, i) == 0)) - if (!entry || (path [i] == PATH_SEP || path [i] == 0)){ - len = i; - entry = temp; - } - temp = temp->me_next; - } - - if (entry){ - memset (&fs_use, 0, sizeof (struct fs_usage)); - get_fs_usage (entry->me_mountdir, &fs_use); - - myfs_stats->type = entry->me_dev; - myfs_stats->typename = entry->me_type; - myfs_stats->mpoint = entry->me_mountdir; - myfs_stats->device = entry->me_devname; - myfs_stats->avail = getuid () ? fs_use.fsu_bavail/2 : fs_use.fsu_bfree/2; - myfs_stats->total = fs_use.fsu_blocks/2; - myfs_stats->nfree = fs_use.fsu_ffree; - myfs_stats->nodes = fs_use.fsu_files; - } else -#endif /* HAVE_INFOMOUNT_LIST */ - -#ifdef HAVE_INFOMOUNT_QNX -/* -** This is the "other side" of the hack to read_filesystem_list() in -** mountlist.c. -** It's not the most efficient approach, but consumes less memory. It -** also accomodates QNX's ability to mount filesystems on the fly. -*/ - struct mount_entry *entry; - struct fs_usage fs_use; - - if ((entry = read_filesystem_list(0, 0)) != NULL) - { - get_fs_usage(entry->me_mountdir, &fs_use); - - myfs_stats->type = entry->me_dev; - myfs_stats->typename = entry->me_type; - myfs_stats->mpoint = entry->me_mountdir; - myfs_stats->device = entry->me_devname; - - myfs_stats->avail = fs_use.fsu_bfree / 2; - myfs_stats->total = fs_use.fsu_blocks / 2; - myfs_stats->nfree = fs_use.fsu_ffree; - myfs_stats->nodes = fs_use.fsu_files; - } - else -#endif /* HAVE_INFOMOUNT_QNX */ - { - myfs_stats->type = 0; - myfs_stats->mpoint = "unknown"; - myfs_stats->device = "unknown"; - myfs_stats->avail = 0; - myfs_stats->total = 0; - myfs_stats->nfree = 0; - myfs_stats->nodes = 0; - } -} - -#ifdef HAVE_INFOMOUNT - -/* Return the number of TOSIZE-byte blocks used by - BLOCKS FROMSIZE-byte blocks, rounding away from zero. - TOSIZE must be positive. Return -1 if FROMSIZE is not positive. */ - -static fsblkcnt_t -fs_adjust_blocks (fsblkcnt_t blocks, int fromsize, int tosize) -{ - if (tosize <= 0) - abort (); - if (fromsize <= 0) - return -1; - - if (fromsize == tosize) /* E.g., from 512 to 512. */ - return blocks; - else if (fromsize > tosize) /* E.g., from 2048 to 512. */ - return blocks * (fromsize / tosize); - else /* E.g., from 256 to 512. */ - return blocks / (tosize / fromsize); -} - -#if defined(_AIX) && defined(_I386) -/* AIX PS/2 does not supply statfs. */ -static int aix_statfs (char *path, struct statfs *fsb) -{ - struct stat stats; - struct dustat fsd; - - if (stat (path, &stats)) - return -1; - if (dustat (stats.st_dev, 0, &fsd, sizeof (fsd))) - return -1; - fsb->f_type = 0; - fsb->f_bsize = fsd.du_bsize; - fsb->f_blocks = fsd.du_fsize - fsd.du_isize; - fsb->f_bfree = fsd.du_tfree; - fsb->f_bavail = fsd.du_tfree; - fsb->f_files = (fsd.du_isize - 2) * fsd.du_inopb; - fsb->f_ffree = fsd.du_tinode; - fsb->f_fsid.val[0] = fsd.du_site; - fsb->f_fsid.val[1] = fsd.du_pckno; - return 0; -} -#define statfs(path,fsb) aix_statfs(path,fsb) -#endif /* _AIX && _I386 */ - -/* Fill in the fields of FSP with information about space usage for - the filesystem on which PATH resides. - Return 0 if successful, -1 if not. */ - -static int -get_fs_usage (char *path, struct fs_usage *fsp) -{ -#ifdef STAT_STATFS3_OSF1 - struct statfs fsd; - - if (statfs (path, &fsd, sizeof (struct statfs)) != 0) - return -1; -#define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_fsize, 512) -#endif /* STAT_STATFS3_OSF1 */ - -#ifdef STAT_STATFS2_FS_DATA /* Ultrix. */ - struct fs_data fsd; - - if (statfs (path, &fsd) != 1) - return -1; -#define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), 1024, 512) - fsp->fsu_blocks = CONVERT_BLOCKS (fsd.fd_req.btot); - fsp->fsu_bfree = CONVERT_BLOCKS (fsd.fd_req.bfree); - fsp->fsu_bavail = CONVERT_BLOCKS (fsd.fd_req.bfreen); - fsp->fsu_files = fsd.fd_req.gtot; - fsp->fsu_ffree = fsd.fd_req.gfree; -#endif - -#ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX. */ - struct statfs fsd; - - if (statfs (path, &fsd) < 0) - return -1; -#define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_bsize, 512) -#endif - -#ifdef STAT_STATFS2_FSIZE /* 4.4BSD. */ - struct statfs fsd; - - if (statfs (path, &fsd) < 0) - return -1; -#define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_fsize, 512) -#endif - -#ifdef STAT_STATFS4 /* SVR3, Dynix, Irix, AIX. */ - struct statfs fsd; - - if (statfs (path, &fsd, sizeof fsd, 0) < 0) - return -1; - /* Empirically, the block counts on most SVR3 and SVR3-derived - systems seem to always be in terms of 512-byte blocks, - no matter what value f_bsize has. */ -#if _AIX -#define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_bsize, 512) -#else -#define CONVERT_BLOCKS(b) (b) -#ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx. */ -#ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */ -#define f_bavail f_bfree -#endif -#endif -#endif -#endif - -#ifdef STAT_STATVFS /* SVR4. */ - struct statvfs fsd; - - if (statvfs (path, &fsd) < 0) - return -1; - /* f_frsize isn't guaranteed to be supported. */ -#define CONVERT_BLOCKS(b) \ - fs_adjust_blocks ((b), fsd.f_frsize ? fsd.f_frsize : fsd.f_bsize, 512) -#endif - -#if defined(CONVERT_BLOCKS) && !defined(STAT_STATFS2_FS_DATA) && !defined(STAT_READ_FILSYS) /* !Ultrix && !SVR2. */ - fsp->fsu_blocks = CONVERT_BLOCKS (fsd.f_blocks); - fsp->fsu_bfree = CONVERT_BLOCKS (fsd.f_bfree); - fsp->fsu_bavail = CONVERT_BLOCKS (fsd.f_bavail); - fsp->fsu_files = fsd.f_files; - fsp->fsu_ffree = fsd.f_ffree; -#endif - - return 0; -} - -#endif /* HAVE_INFOMOUNT */ +/* mountlist.c -- return a list of mounted filesystems + Copyright (C) 1991, 1992 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/** \file mountlist.c + * \brief Source: list of mounted filesystems + */ + +#include + +#include +#include + +#include + +/* This header needs to be included before sys/mount.h on *BSD */ +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */ +#include +#include +#endif /* MOUNTED_GETFSSTAT */ + +#ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ +#include +#if !defined(MOUNTED) +#if defined(MNT_MNTTAB) /* HP-UX. */ +#define MOUNTED MNT_MNTTAB +#endif +#if defined(MNTTABNAME) /* Dynix. */ +#define MOUNTED MNTTABNAME +#endif +#endif +#endif + +#ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ +#include +#endif + +#ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */ +#include +#endif + +#ifdef MOUNTED_GETMNT /* Ultrix. */ +#include +#include +#endif + +#ifdef MOUNTED_FREAD /* SVR2. */ +#include +#endif + +#ifdef MOUNTED_FREAD_FSTYP /* SVR3. */ +#include +#include +#include +#endif + +#ifdef MOUNTED_GETMNTENT2 /* SVR4. */ +#include +#endif + +#ifdef MOUNTED_VMOUNT /* AIX. */ +#include +#include +#endif + +#ifdef HAVE_SYS_STATFS_H +#include +#endif + +#ifdef HAVE_INFOMOUNT_QNX +#include +#include +#endif + +#ifdef HAVE_SYS_MOUNT_H +#include +#endif + +#ifdef HAVE_SYS_VFS_H +#include +#endif + +#ifdef HAVE_SYS_FILSYS_H +#include /* SVR2. */ +#endif + +#ifdef HAVE_DUSTAT_H /* AIX PS/2. */ +#include +#endif + +#ifdef HAVE_SYS_STATVFS_H /* SVR4. */ +#include +#endif + +#include "lib/global.h" +#include "mountlist.h" + +#ifdef DOLPHIN +/* So special that it's not worth putting this in autoconf. */ +#undef MOUNTED_FREAD_FSTYP +#define MOUNTED_GETMNTTBL +#endif + +#if defined (__QNX__) && !defined(__QNXNTO__) && !defined (HAVE_INFOMOUNT_LIST) +# define HAVE_INFOMOUNT_QNX +#endif + +#if defined(HAVE_INFOMOUNT_LIST) || defined(HAVE_INFOMOUNT_QNX) +# define HAVE_INFOMOUNT +#endif + +/* A mount table entry. */ +struct mount_entry +{ + char *me_devname; /* Device node pathname, including "/dev/". */ + char *me_mountdir; /* Mount point directory pathname. */ + char *me_type; /* "nfs", "4.2", etc. */ + dev_t me_dev; /* Device number of me_mountdir. */ + struct mount_entry *me_next; +}; + +struct fs_usage +{ + fsblkcnt_t fsu_blocks; /* Total blocks. */ + fsblkcnt_t fsu_bfree; /* Free blocks available to superuser. */ + fsblkcnt_t fsu_bavail; /* Free blocks available to non-superuser. */ + fsfilcnt_t fsu_files; /* Total file nodes. */ + fsfilcnt_t fsu_ffree; /* Free file nodes. */ +}; + +static int get_fs_usage (char *path, struct fs_usage *fsp); + +#ifdef HAVE_INFOMOUNT_LIST + +static struct mount_entry *mount_list = NULL; + +static void +free_mount_entry (struct mount_entry *me) +{ + if (!me) + return; + if (me->me_devname) + free (me->me_devname); + if (me->me_mountdir) + free (me->me_mountdir); + if (me->me_type) + free (me->me_type); + free (me); +} + +#ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ +/* Return the value of the hexadecimal number represented by CP. + No prefix (like '0x') or suffix (like 'h') is expected to be + part of CP. */ + +static int +xatoi (const char *cp) +{ + int val; + + val = 0; + while (*cp) + { + if (*cp >= 'a' && *cp <= 'f') + val = val * 16 + *cp - 'a' + 10; + else if (*cp >= 'A' && *cp <= 'F') + val = val * 16 + *cp - 'A' + 10; + else if (*cp >= '0' && *cp <= '9') + val = val * 16 + *cp - '0'; + else + break; + cp++; + } + return val; +} +#endif /* MOUNTED_GETMNTENT1 */ + +#ifdef MOUNTED_GETMNTINFO + +#ifndef HAVE_STRUCT_STATFS_F_FSTYPENAME +static char * +fstype_to_string (short t) +{ + switch (t) + { +#ifdef MOUNT_PC + case MOUNT_PC: + return "pc"; +#endif +#ifdef MOUNT_MFS + case MOUNT_MFS: + return "mfs"; +#endif +#ifdef MOUNT_LO + case MOUNT_LO: + return "lo"; +#endif +#ifdef MOUNT_TFS + case MOUNT_TFS: + return "tfs"; +#endif +#ifdef MOUNT_TMP + case MOUNT_TMP: + return "tmp"; +#endif +#ifdef MOUNT_UFS + case MOUNT_UFS: + return "ufs"; +#endif +#ifdef MOUNT_NFS + case MOUNT_NFS: + return "nfs"; +#endif +#ifdef MOUNT_MSDOS + case MOUNT_MSDOS: + return "msdos"; +#endif +#ifdef MOUNT_LFS + case MOUNT_LFS: + return "lfs"; +#endif +#ifdef MOUNT_LOFS + case MOUNT_LOFS: + return "lofs"; +#endif +#ifdef MOUNT_FDESC + case MOUNT_FDESC: + return "fdesc"; +#endif +#ifdef MOUNT_PORTAL + case MOUNT_PORTAL: + return "portal"; +#endif +#ifdef MOUNT_NULL + case MOUNT_NULL: + return "null"; +#endif +#ifdef MOUNT_UMAP + case MOUNT_UMAP: + return "umap"; +#endif +#ifdef MOUNT_KERNFS + case MOUNT_KERNFS: + return "kernfs"; +#endif +#ifdef MOUNT_PROCFS + case MOUNT_PROCFS: + return "procfs"; +#endif +#ifdef MOUNT_AFS + case MOUNT_AFS: + return "afs"; +#endif +#ifdef MOUNT_CD9660 + case MOUNT_CD9660: + return "cd9660"; +#endif +#ifdef MOUNT_UNION + case MOUNT_UNION: + return "union"; +#endif +#ifdef MOUNT_DEVFS + case MOUNT_DEVFS: + return "devfs"; +#endif +#ifdef MOUNT_EXT2FS + case MOUNT_EXT2FS: + return "ext2fs"; +#endif + default: + return "?"; + } +} +#endif /* ! HAVE_STRUCT_STATFS_F_FSTYPENAME */ + +#endif /* MOUNTED_GETMNTINFO */ + +#ifdef MOUNTED_VMOUNT /* AIX. */ +static char * +fstype_to_string (int t) +{ + struct vfs_ent *e; + + e = getvfsbytype (t); + if (!e || !e->vfsent_name) + return "none"; + else + return e->vfsent_name; +} +#endif /* MOUNTED_VMOUNT */ + +/* Return a list of the currently mounted filesystems, or NULL on error. + Add each entry to the tail of the list so that they stay in order. + If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in + the returned list are valid. Otherwise, they might not be. + If ALL_FS is zero, do not return entries for filesystems that + are automounter (dummy) entries. */ + +static struct mount_entry * +read_filesystem_list (int need_fs_type, int all_fs) +{ + struct mount_entry *mlist; + struct mount_entry *me; + struct mount_entry *mtail; + + (void) need_fs_type; + (void) all_fs; + + /* Start the list off with a dummy entry. */ + me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); + me->me_next = NULL; + mlist = mtail = me; + +#ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ +#ifdef MOUNTED + { + struct mntent *mnt; + FILE *fp; + const char *devopt; + + fp = setmntent (MOUNTED, "r"); + if (fp == NULL) + return NULL; + + while ((mnt = getmntent (fp))) + { + if (!all_fs && (!strcmp (mnt->mnt_type, "ignore") || !strcmp (mnt->mnt_type, "auto"))) + continue; + + me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); + me->me_devname = strdup (mnt->mnt_fsname); + me->me_mountdir = strdup (mnt->mnt_dir); + me->me_type = strdup (mnt->mnt_type); + devopt = strstr (mnt->mnt_opts, "dev="); + if (devopt) + { + if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X')) + me->me_dev = xatoi (devopt + 6); + else + me->me_dev = xatoi (devopt + 4); + } + else + me->me_dev = -1; /* Magic; means not known yet. */ + me->me_next = NULL; + + /* Add to the linked list. */ + mtail->me_next = me; + mtail = me; + } + + if (endmntent (fp) == 0) + return NULL; + } +#endif /* MOUNTED */ +#endif /* MOUNTED_GETMNTENT1 */ + +#ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ + { + struct statfs *fsp; + int entries; + + entries = getmntinfo (&fsp, MNT_NOWAIT); + if (entries < 0) + return NULL; + while (entries-- > 0) + { + me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); + me->me_devname = strdup (fsp->f_mntfromname); + me->me_mountdir = strdup (fsp->f_mntonname); +#ifdef HAVE_STRUCT_STATFS_F_FSTYPENAME + me->me_type = strdup (fsp->f_fstypename); +#else + me->me_type = fstype_to_string (fsp->f_type); +#endif + me->me_dev = -1; /* Magic; means not known yet. */ + me->me_next = NULL; + + /* Add to the linked list. */ + mtail->me_next = me; + mtail = me; + fsp++; + } + } +#endif /* MOUNTED_GETMNTINFO */ + +#ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */ + { + struct statvfs *fsp; + int entries; + + entries = getmntinfo (&fsp, MNT_NOWAIT); + if (entries < 0) + return NULL; + for (; entries-- > 0; fsp++) + { + me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); + me->me_devname = strdup (fsp->f_mntfromname); + me->me_mountdir = strdup (fsp->f_mntonname); + me->me_type = strdup (fsp->f_fstypename); + me->me_dev = (dev_t) - 1; /* Magic; means not known yet. */ + + /* Add to the linked list. */ + mtail->me_next = me; + mtail = me; + } + } +#endif /* MOUNTED_GETMNTINFO2 */ + +#ifdef MOUNTED_GETMNT /* Ultrix. */ + { + int offset = 0; + int val; + struct fs_data fsd; + + while ((val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, NULL)) > 0) + { + me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); + me->me_devname = strdup (fsd.fd_req.devname); + me->me_mountdir = strdup (fsd.fd_req.path); + me->me_type = gt_names[fsd.fd_req.fstype]; + me->me_dev = fsd.fd_req.dev; + me->me_next = NULL; + + /* Add to the linked list. */ + mtail->me_next = me; + mtail = me; + } + if (val < 0) + return NULL; + } +#endif /* MOUNTED_GETMNT */ + +#ifdef MOUNTED_GETFSSTAT /* __alpha running OSF_1 */ + { + int numsys, counter, bufsize; + struct statfs *stats; + + numsys = getfsstat ((struct statfs *) 0, 0L, MNT_WAIT); + if (numsys < 0) + return (NULL); + + bufsize = (1 + numsys) * sizeof (struct statfs); + stats = (struct statfs *) malloc (bufsize); + numsys = getfsstat (stats, bufsize, MNT_WAIT); + + if (numsys < 0) + { + free (stats); + return (NULL); + } + for (counter = 0; counter < numsys; counter++) + { + me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); + me->me_devname = strdup (stats[counter].f_mntfromname); + me->me_mountdir = strdup (stats[counter].f_mntonname); + me->me_type = mnt_names[stats[counter].f_type]; + me->me_dev = -1; /* Magic; means not known yet. */ + me->me_next = NULL; + + /* Add to the linked list. */ + mtail->me_next = me; + mtail = me; + } + + free (stats); + } +#endif /* MOUNTED_GETFSSTAT */ + +#if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */ + { + struct mnttab mnt; + char *table = "/etc/mnttab"; + FILE *fp; + + fp = fopen (table, "r"); + if (fp == NULL) + return NULL; + + while (fread (&mnt, sizeof mnt, 1, fp) > 0) + { + me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); +#ifdef GETFSTYP /* SVR3. */ + me->me_devname = strdup (mnt.mt_dev); +#else + me->me_devname = malloc (strlen (mnt.mt_dev) + 6); + strcpy (me->me_devname, "/dev/"); + strcpy (me->me_devname + 5, mnt.mt_dev); +#endif + me->me_mountdir = strdup (mnt.mt_filsys); + me->me_dev = -1; /* Magic; means not known yet. */ + me->me_type = ""; +#ifdef GETFSTYP /* SVR3. */ + if (need_fs_type) + { + struct statfs fsd; + char typebuf[FSTYPSZ]; + + if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1 + && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1) + me->me_type = strdup (typebuf); + } +#endif + me->me_next = NULL; + + /* Add to the linked list. */ + mtail->me_next = me; + mtail = me; + } + + if (fclose (fp) == EOF) + return NULL; + } +#endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP */ + +#ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */ + { + struct mntent **mnttbl = getmnttbl (), **ent; + for (ent = mnttbl; *ent; ent++) + { + me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); + me->me_devname = strdup ((*ent)->mt_resource); + me->me_mountdir = strdup ((*ent)->mt_directory); + me->me_type = strdup ((*ent)->mt_fstype); + me->me_dev = -1; /* Magic; means not known yet. */ + me->me_next = NULL; + + /* Add to the linked list. */ + mtail->me_next = me; + mtail = me; + } + endmnttbl (); + } +#endif /* MOUNTED_GETMNTTBL */ + +#ifdef MOUNTED_GETMNTENT2 /* SVR4. */ + { + struct mnttab mnt; + char *table = MNTTAB; + FILE *fp; + int ret; + + fp = fopen (table, "r"); + if (fp == NULL) + return NULL; + + while ((ret = getmntent (fp, &mnt)) == 0) + { + me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); + me->me_devname = strdup (mnt.mnt_special); + me->me_mountdir = strdup (mnt.mnt_mountp); + me->me_type = strdup (mnt.mnt_fstype); + me->me_dev = -1; /* Magic; means not known yet. */ + me->me_next = NULL; + /* Add to the linked list. */ + mtail->me_next = me; + mtail = me; + } + + if (ret > 0) + return NULL; + if (fclose (fp) == EOF) + return NULL; + } +#endif /* MOUNTED_GETMNTENT2 */ + +#ifdef MOUNTED_VMOUNT /* AIX. */ + { + int bufsize; + char *entries, *thisent; + struct vmount *vmp; + + /* Ask how many bytes to allocate for the mounted filesystem info. */ + mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize); + entries = malloc (bufsize); + + /* Get the list of mounted filesystems. */ + mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries); + + for (thisent = entries; thisent < entries + bufsize; thisent += vmp->vmt_length) + { + vmp = (struct vmount *) thisent; + me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); + if (vmp->vmt_flags & MNT_REMOTE) + { + char *host, *path; + + /* Prepend the remote pathname. */ + host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off; + path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off; + me->me_devname = malloc (strlen (host) + strlen (path) + 2); + strcpy (me->me_devname, host); + strcat (me->me_devname, ":"); + strcat (me->me_devname, path); + } + else + { + 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_type = strdup (fstype_to_string (vmp->vmt_gfstype)); + me->me_dev = -1; /* vmt_fsid might be the info we want. */ + me->me_next = NULL; + + /* Add to the linked list. */ + mtail->me_next = me; + mtail = me; + } + free (entries); + } +#endif /* MOUNTED_VMOUNT */ + + /* Free the dummy head. */ + me = mlist; + mlist = mlist->me_next; + free (me); + return mlist; +} +#endif /* HAVE_INFOMOUNT_LIST */ + +#ifdef HAVE_INFOMOUNT_QNX +/* + ** QNX has no [gs]etmnt*(), [gs]etfs*(), or /etc/mnttab, but can do + ** this via the following code. + ** Note that, as this is based on CWD, it only fills one mount_entry + ** structure. See my_statfs() in utilunix.c for the "other side" of + ** this hack. + */ + +static struct mount_entry * +read_filesystem_list (int need_fs_type, int all_fs) +{ + struct _disk_entry de; + struct statfs fs; + int i, fd; + char *tp, dev[_POSIX_NAME_MAX], dir[_POSIX_PATH_MAX]; + + static struct mount_entry *me = NULL; + + if (me) + { + if (me->me_devname) + free (me->me_devname); + if (me->me_mountdir) + free (me->me_mountdir); + if (me->me_type) + free (me->me_type); + } + else + me = (struct mount_entry *) malloc (sizeof (struct mount_entry)); + + if (!getcwd (dir, _POSIX_PATH_MAX)) + return (NULL); + + if ((fd = open (dir, O_RDONLY)) == -1) + return (NULL); + + i = disk_get_entry (fd, &de); + + close (fd); + + if (i == -1) + return (NULL); + + switch (de.disk_type) + { + case _UNMOUNTED: + tp = "unmounted"; + break; + case _FLOPPY: + tp = "Floppy"; + break; + case _HARD: + 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_pt (dev, &dir) == -1) + return (NULL); + + me->me_devname = strdup (dev); + me->me_mountdir = strdup (dir); + me->me_type = strdup (tp); + me->me_dev = de.disk_type; + +#ifdef DEBUG + 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); + fprintf (stderr, "fsys_get_mount_dev():\n\tdevice='%s'\n", dev); + fprintf (stderr, "fsys_get_mount_pt():\n\tmount point='%s'\n", dir); +#endif /* DEBUG */ + + return (me); +} +#endif /* HAVE_INFOMOUNT_QNX */ + +void +free_my_statfs (void) +{ +#ifdef HAVE_INFOMOUNT_LIST + while (mount_list) + { + struct mount_entry *next = mount_list->me_next; + free_mount_entry (mount_list); + 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); +#endif /* HAVE_INFOMOUNT_LIST */ +} + +void +my_statfs (struct my_statfs *myfs_stats, const char *path) +{ +#ifdef HAVE_INFOMOUNT_LIST + int i, len = 0; + struct mount_entry *entry = NULL; + struct mount_entry *temp = mount_list; + struct fs_usage fs_use; + + while (temp) + { + i = strlen (temp->me_mountdir); + if (i > len && (strncmp (path, temp->me_mountdir, i) == 0)) + if (!entry || (path[i] == PATH_SEP || path[i] == 0)) + { + len = i; + entry = temp; + } + temp = temp->me_next; + } + + if (entry) + { + memset (&fs_use, 0, sizeof (struct fs_usage)); + get_fs_usage (entry->me_mountdir, &fs_use); + + myfs_stats->type = entry->me_dev; + myfs_stats->typename = entry->me_type; + myfs_stats->mpoint = entry->me_mountdir; + myfs_stats->device = entry->me_devname; + myfs_stats->avail = getuid ()? fs_use.fsu_bavail / 2 : fs_use.fsu_bfree / 2; + myfs_stats->total = fs_use.fsu_blocks / 2; + myfs_stats->nfree = fs_use.fsu_ffree; + myfs_stats->nodes = fs_use.fsu_files; + } + else +#endif /* HAVE_INFOMOUNT_LIST */ + +#ifdef HAVE_INFOMOUNT_QNX + /* + ** This is the "other side" of the hack to read_filesystem_list() in + ** mountlist.c. + ** It's not the most efficient approach, but consumes less memory. It + ** also accomodates QNX's ability to mount filesystems on the fly. + */ + struct mount_entry *entry; + struct fs_usage fs_use; + + if ((entry = read_filesystem_list (0, 0)) != NULL) + { + get_fs_usage (entry->me_mountdir, &fs_use); + + myfs_stats->type = entry->me_dev; + myfs_stats->typename = entry->me_type; + myfs_stats->mpoint = entry->me_mountdir; + myfs_stats->device = entry->me_devname; + + myfs_stats->avail = fs_use.fsu_bfree / 2; + myfs_stats->total = fs_use.fsu_blocks / 2; + myfs_stats->nfree = fs_use.fsu_ffree; + myfs_stats->nodes = fs_use.fsu_files; + } + else +#endif /* HAVE_INFOMOUNT_QNX */ + { + myfs_stats->type = 0; + myfs_stats->mpoint = "unknown"; + myfs_stats->device = "unknown"; + myfs_stats->avail = 0; + myfs_stats->total = 0; + myfs_stats->nfree = 0; + myfs_stats->nodes = 0; + } +} + +#ifdef HAVE_INFOMOUNT + +/* Return the number of TOSIZE-byte blocks used by + BLOCKS FROMSIZE-byte blocks, rounding away from zero. + TOSIZE must be positive. Return -1 if FROMSIZE is not positive. */ + +static fsblkcnt_t +fs_adjust_blocks (fsblkcnt_t blocks, int fromsize, int tosize) +{ + if (tosize <= 0) + abort (); + if (fromsize <= 0) + return -1; + + if (fromsize == tosize) /* E.g., from 512 to 512. */ + return blocks; + else if (fromsize > tosize) /* E.g., from 2048 to 512. */ + return blocks * (fromsize / tosize); + else /* E.g., from 256 to 512. */ + return blocks / (tosize / fromsize); +} + +#if defined(_AIX) && defined(_I386) +/* AIX PS/2 does not supply statfs. */ +static int +aix_statfs (char *path, struct statfs *fsb) +{ + struct stat stats; + struct dustat fsd; + + if (stat (path, &stats)) + return -1; + if (dustat (stats.st_dev, 0, &fsd, sizeof (fsd))) + return -1; + fsb->f_type = 0; + fsb->f_bsize = fsd.du_bsize; + fsb->f_blocks = fsd.du_fsize - fsd.du_isize; + fsb->f_bfree = fsd.du_tfree; + fsb->f_bavail = fsd.du_tfree; + fsb->f_files = (fsd.du_isize - 2) * fsd.du_inopb; + fsb->f_ffree = fsd.du_tinode; + fsb->f_fsid.val[0] = fsd.du_site; + fsb->f_fsid.val[1] = fsd.du_pckno; + return 0; +} + +#define statfs(path,fsb) aix_statfs(path,fsb) +#endif /* _AIX && _I386 */ + +/* Fill in the fields of FSP with information about space usage for + the filesystem on which PATH resides. + Return 0 if successful, -1 if not. */ + +static int +get_fs_usage (char *path, struct fs_usage *fsp) +{ +#ifdef STAT_STATFS3_OSF1 + struct statfs fsd; + + if (statfs (path, &fsd, sizeof (struct statfs)) != 0) + return -1; +#define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_fsize, 512) +#endif /* STAT_STATFS3_OSF1 */ + +#ifdef STAT_STATFS2_FS_DATA /* Ultrix. */ + struct fs_data fsd; + + if (statfs (path, &fsd) != 1) + return -1; +#define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), 1024, 512) + fsp->fsu_blocks = CONVERT_BLOCKS (fsd.fd_req.btot); + fsp->fsu_bfree = CONVERT_BLOCKS (fsd.fd_req.bfree); + fsp->fsu_bavail = CONVERT_BLOCKS (fsd.fd_req.bfreen); + fsp->fsu_files = fsd.fd_req.gtot; + fsp->fsu_ffree = fsd.fd_req.gfree; +#endif + +#ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX. */ + struct statfs fsd; + + if (statfs (path, &fsd) < 0) + return -1; +#define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_bsize, 512) +#endif + +#ifdef STAT_STATFS2_FSIZE /* 4.4BSD. */ + struct statfs fsd; + + if (statfs (path, &fsd) < 0) + return -1; +#define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_fsize, 512) +#endif + +#ifdef STAT_STATFS4 /* SVR3, Dynix, Irix, AIX. */ + struct statfs fsd; + + if (statfs (path, &fsd, sizeof fsd, 0) < 0) + return -1; + /* Empirically, the block counts on most SVR3 and SVR3-derived + systems seem to always be in terms of 512-byte blocks, + no matter what value f_bsize has. */ +#if _AIX +#define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_bsize, 512) +#else +#define CONVERT_BLOCKS(b) (b) +#ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx. */ +#ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */ +#define f_bavail f_bfree +#endif +#endif +#endif +#endif + +#ifdef STAT_STATVFS /* SVR4. */ + struct statvfs fsd; + + if (statvfs (path, &fsd) < 0) + return -1; + /* f_frsize isn't guaranteed to be supported. */ +#define CONVERT_BLOCKS(b) \ + fs_adjust_blocks ((b), fsd.f_frsize ? fsd.f_frsize : fsd.f_bsize, 512) +#endif + +#if defined(CONVERT_BLOCKS) && !defined(STAT_STATFS2_FS_DATA) && !defined(STAT_READ_FILSYS) /* !Ultrix && !SVR2. */ + fsp->fsu_blocks = CONVERT_BLOCKS (fsd.f_blocks); + fsp->fsu_bfree = CONVERT_BLOCKS (fsd.f_bfree); + fsp->fsu_bavail = CONVERT_BLOCKS (fsd.f_bavail); + fsp->fsu_files = fsd.f_files; + fsp->fsu_ffree = fsd.f_ffree; +#endif + + return 0; +} + +#endif /* HAVE_INFOMOUNT */ diff --git a/src/mountlist.h b/src/mountlist.h index 390a356c..cf878f87 100644 --- a/src/mountlist.h +++ b/src/mountlist.h @@ -23,7 +23,8 @@ #define MC_MOUNTLIST_H /* Filesystem status */ -struct my_statfs { +struct my_statfs +{ int type; char *typename; const char *mpoint; -- 2.11.4.GIT