Example #1
0
/* Compare version strings.
 *
 * @s1 first string to compare
 * @s2 second string to compare
 *
 * @return an integer less than, equal to, or greater than zero, if @s1 is <, == or > than @s2.
 */
int
filevercmp (const char *s1, const char *s2)
{
    const char *s1_pos, *s2_pos;
    const char *s1_suffix, *s2_suffix;
    size_t s1_len, s2_len;
    int simple_cmp, result;

    /* easy comparison to see if strings are identical */
    simple_cmp = strcmp (s1, s2);
    if (simple_cmp == 0)
        return 0;

    /* special handle for "", "." and ".." */
    if (*s1 == '\0')
        return -1;
    if (*s2 == '\0')
        return 1;
    if (DIR_IS_DOT (s1))
        return -1;
    if (DIR_IS_DOT (s2))
        return 1;
    if (DIR_IS_DOTDOT (s1))
        return -1;
    if (DIR_IS_DOTDOT (s2))
        return 1;

    /* special handle for other hidden files */
    if (*s1 == '.' && *s2 != '.')
        return -1;
    if (*s1 != '.' && *s2 == '.')
        return 1;
    if (*s1 == '.' && *s2 == '.')
    {
        s1++;
        s2++;
    }

    /* "cut" file suffixes */
    s1_pos = s1;
    s2_pos = s2;
    s1_suffix = match_suffix (&s1_pos);
    s2_suffix = match_suffix (&s2_pos);
    s1_len = (s1_suffix != NULL ? s1_suffix : s1_pos) - s1;
    s2_len = (s2_suffix != NULL ? s2_suffix : s2_pos) - s2;

    /* restore file suffixes if strings are identical after "cut" */
    if ((s1_suffix != NULL || s2_suffix != NULL) && (s1_len == s2_len)
        && strncmp (s1, s2, s1_len) == 0)
    {
        s1_len = s1_pos - s1;
        s2_len = s2_pos - s2;
    }

    result = verrevcmp (s1, s1_len, s2, s2_len);

    return result == 0 ? simple_cmp : result;
}
Example #2
0
gboolean
handle_path (const char *path, struct stat * buf1, int *link_to_dir, int *stale_link)
{
    vfs_path_t *vpath;

    if (DIR_IS_DOT (path) || DIR_IS_DOTDOT (path))
        return FALSE;

    vpath = vfs_path_from_str (path);
    if (mc_lstat (vpath, buf1) == -1)
    {
        vfs_path_free (vpath);
        return FALSE;
    }

    if (S_ISDIR (buf1->st_mode))
        tree_store_mark_checked (path);

    /* A link to a file or a directory? */
    *link_to_dir = 0;
    *stale_link = 0;
    if (S_ISLNK (buf1->st_mode))
    {
        struct stat buf2;

        if (mc_stat (vpath, &buf2) == 0)
            *link_to_dir = S_ISDIR (buf2.st_mode) != 0;
        else
            *stale_link = 1;
    }

    vfs_path_free (vpath);

    return TRUE;
}
Example #3
0
static gboolean
handle_dirent (struct dirent *dp, const char *fltr, struct stat *buf1, int *link_to_dir,
               int *stale_link)
{
    vfs_path_t *vpath;

    if (DIR_IS_DOT (dp->d_name) || DIR_IS_DOTDOT (dp->d_name))
        return FALSE;
    if (!panels_options.show_dot_files && (dp->d_name[0] == '.'))
        return FALSE;
    if (!panels_options.show_backups && dp->d_name[strlen (dp->d_name) - 1] == '~')
        return FALSE;

    vpath = vfs_path_from_str (dp->d_name);
    if (mc_lstat (vpath, buf1) == -1)
    {
        /*
         * lstat() fails - such entries should be identified by
         * buf1->st_mode being 0.
         * It happens on QNX Neutrino for /fs/cd0 if no CD is inserted.
         */
        memset (buf1, 0, sizeof (*buf1));
    }

    if (S_ISDIR (buf1->st_mode))
        tree_store_mark_checked (dp->d_name);

    /* A link to a file or a directory? */
    *link_to_dir = 0;
    *stale_link = 0;
    if (S_ISLNK (buf1->st_mode))
    {
        struct stat buf2;

        if (mc_stat (vpath, &buf2) == 0)
            *link_to_dir = S_ISDIR (buf2.st_mode) != 0;
        else
            *stale_link = 1;
    }

    vfs_path_free (vpath);

    return (S_ISDIR (buf1->st_mode) || *link_to_dir != 0 || fltr == NULL
            || mc_search (fltr, NULL, dp->d_name, MC_SEARCH_T_GLOB));
}
Example #4
0
static char *
filename_completion_function (const char *text, int state, input_complete_t flags)
{
    static DIR *directory = NULL;
    static char *filename = NULL;
    static char *dirname = NULL;
    static char *users_dirname = NULL;
    static size_t filename_len;
    int isdir = 1, isexec = 0;
    static vfs_path_t *dirname_vpath = NULL;

    struct dirent *entry = NULL;

    SHOW_C_CTX ("filename_completion_function");

    if (text && (flags & INPUT_COMPLETE_SHELL_ESC))
    {
        char *u_text;
        char *result;
        char *e_result;

        u_text = strutils_shell_unescape (text);

        result = filename_completion_function (u_text, state, flags & (~INPUT_COMPLETE_SHELL_ESC));
        g_free (u_text);

        e_result = strutils_shell_escape (result);
        g_free (result);

        return e_result;
    }

    /* If we're starting the match process, initialize us a bit. */
    if (state == 0)
    {
        const char *temp;

        g_free (dirname);
        g_free (filename);
        g_free (users_dirname);
        vfs_path_free (dirname_vpath);

        if ((*text != '\0') && (temp = strrchr (text, PATH_SEP)) != NULL)
        {
            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_vpath = vfs_path_from_str (dirname);

        /* Here we should do something with variable expansion
           and `command`.
           Maybe a dream - UNIMPLEMENTED yet. */

        directory = mc_opendir (dirname_vpath);
        filename_len = strlen (filename);
    }

    /* 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;

        /* Special case for no filename.
           All entries except "." and ".." match. */
        if (filename_len == 0)
        {
            if (DIR_IS_DOT (entry->d_name) || DIR_IS_DOTDOT (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;
        {
            struct stat tempstat;
            vfs_path_t *tmp_vpath;

            tmp_vpath = vfs_path_build_filename (dirname, entry->d_name, (char *) NULL);

            /* Unix version */
            if (mc_stat (tmp_vpath, &tempstat) == 0)
            {
                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;
            }
            vfs_path_free (tmp_vpath);
        }
        if ((flags & INPUT_COMPLETE_COMMANDS) && (isexec || isdir))
            break;
        if ((flags & INPUT_COMPLETE_CD) && isdir)
            break;
        if (flags & (INPUT_COMPLETE_FILENAMES))
            break;
    }

    if (entry == NULL)
    {
        if (directory)
        {
            mc_closedir (directory);
            directory = NULL;
        }
        g_free (dirname);
        dirname = NULL;
        vfs_path_free (dirname_vpath);
        dirname_vpath = NULL;
        g_free (filename);
        filename = NULL;
        g_free (users_dirname);
        users_dirname = NULL;
        return NULL;
    }

    {
        GString *temp;

        temp = g_string_sized_new (16);

        if (users_dirname != NULL && (users_dirname[0] != '.' || users_dirname[1] != '\0'))
        {
            g_string_append (temp, users_dirname);

            /* We need a '/' at the end. */
            if (temp->str[temp->len - 1] != PATH_SEP)
                g_string_append_c (temp, PATH_SEP);
        }
        g_string_append (temp, entry->d_name);
        if (isdir)
            g_string_append_c (temp, PATH_SEP);

        return g_string_free (temp, FALSE);
    }
}
Example #5
0
/** If it actually changed the directory it returns true */
void
do_subshell_chdir (const vfs_path_t * vpath, gboolean update_prompt)
{
    char *pcwd;

    pcwd = vfs_path_to_str_flags (current_panel->cwd_vpath, 0, VPF_RECODE);

    if (!(subshell_state == INACTIVE && strcmp (subshell_cwd, pcwd) != 0))
    {
        /* We have to repaint the subshell prompt if we read it from
         * the main program.  Please note that in the code after this
         * if, the cd command that is sent will make the subshell
         * repaint the prompt, so we don't have to paint it. */
        if (update_prompt)
            do_update_prompt ();
        g_free (pcwd);
        return;
    }

    /* The initial space keeps this out of the command history (in bash
       because we set "HISTCONTROL=ignorespace") */
    write_all (mc_global.tty.subshell_pty, " cd ", 4);

    if (vpath != NULL)
    {
        char *translate;

        translate = vfs_translate_path_n (vfs_path_as_str (vpath));
        if (translate != NULL)
        {
            GString *temp;

            temp = subshell_name_quote (translate);
            write_all (mc_global.tty.subshell_pty, temp->str, temp->len);
            g_string_free (temp, TRUE);

            g_free (translate);
        }
        else
        {
            write_all (mc_global.tty.subshell_pty, ".", 1);
        }
    }
    else
    {
        write_all (mc_global.tty.subshell_pty, "/", 1);
    }
    write_all (mc_global.tty.subshell_pty, "\n", 1);

    subshell_state = RUNNING_COMMAND;
    feed_subshell (QUIETLY, FALSE);

    if (subshell_alive)
    {
        int bPathNotEq = strcmp (subshell_cwd, pcwd);

        if (bPathNotEq && subshell_type == TCSH)
        {
            char rp_subshell_cwd[PATH_MAX];
            char rp_current_panel_cwd[PATH_MAX];

            char *p_subshell_cwd = mc_realpath (subshell_cwd, rp_subshell_cwd);
            char *p_current_panel_cwd = mc_realpath (pcwd, rp_current_panel_cwd);

            if (p_subshell_cwd == NULL)
                p_subshell_cwd = subshell_cwd;
            if (p_current_panel_cwd == NULL)
                p_current_panel_cwd = pcwd;
            bPathNotEq = strcmp (p_subshell_cwd, p_current_panel_cwd);
        }

        if (bPathNotEq && !DIR_IS_DOT (pcwd))
        {
            char *cwd;

            cwd = vfs_path_to_str_flags (current_panel->cwd_vpath, 0, VPF_STRIP_PASSWORD);
            vfs_print_message (_("Warning: Cannot change to %s.\n"), cwd);
            g_free (cwd);
        }
    }

    update_subshell_prompt = FALSE;

    g_free (pcwd);
    /* Make sure that MC never stores the CWD in a silly format */
    /* like /usr////lib/../bin, or the strcmp() above will fail */
}