Пример #1
0
void
dir_list_load (dir_list * list, const vfs_path_t * vpath, GCompareFunc sort,
               const dir_sort_options_t * sort_op, const char *fltr)
{
    DIR *dirp;
    struct dirent *dp;
    int link_to_dir, stale_link;
    struct stat st;
    file_entry_t *fentry;

    /* ".." (if any) must be the first entry in the list */
    if (!dir_list_init (list))
        return;

    fentry = &list->list[0];
    if (dir_get_dotdot_stat (vpath, &st))
        fentry->st = st;

    dirp = mc_opendir (vpath);
    if (dirp == NULL)
    {
        message (D_ERROR, MSG_ERROR, _("Cannot read directory contents"));
        return;
    }

    tree_store_start_check (vpath);

    {
        const char *vpath_str;

        vpath_str = vfs_path_as_str (vpath);
        /* Do not add a ".." entry to the root directory */
        if ((vpath_str[0] == PATH_SEP) && (vpath_str[1] == '\0'))
            list->len--;
    }

    while ((dp = mc_readdir (dirp)) != NULL)
    {
        if (!handle_dirent (dp, fltr, &st, &link_to_dir, &stale_link))
            continue;

        if (!dir_list_append (list, dp->d_name, &st, link_to_dir != 0, stale_link != 0))
            goto ret;

        if ((list->len & 31) == 0)
            rotate_dash (TRUE);
    }

    dir_list_sort (list, sort, sort_op);

  ret:
    mc_closedir (dirp);
    tree_store_end_check ();
    rotate_dash (FALSE);
}
Пример #2
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);
    }
}
Пример #3
0
void
dir_list_reload (dir_list * list, const vfs_path_t * vpath, GCompareFunc sort,
                 const dir_sort_options_t * sort_op, const char *fltr)
{
    DIR *dirp;
    struct dirent *dp;
    int i, link_to_dir, stale_link;
    struct stat st;
    int marked_cnt;
    GHashTable *marked_files;
    const char *tmp_path;

    dirp = mc_opendir (vpath);
    if (dirp == NULL)
    {
        message (D_ERROR, MSG_ERROR, _("Cannot read directory contents"));
        dir_list_clean (list);
        dir_list_init (list);
        return;
    }

    tree_store_start_check (vpath);

    marked_files = g_hash_table_new (g_str_hash, g_str_equal);
    alloc_dir_copy (list->len);
    for (marked_cnt = i = 0; i < list->len; i++)
    {
        file_entry_t *fentry, *dfentry;

        fentry = &list->list[i];
        dfentry = &dir_copy.list[i];

        dfentry->fnamelen = fentry->fnamelen;
        dfentry->fname = g_strndup (fentry->fname, fentry->fnamelen);
        dfentry->f.marked = fentry->f.marked;
        dfentry->f.dir_size_computed = fentry->f.dir_size_computed;
        dfentry->f.link_to_dir = fentry->f.link_to_dir;
        dfentry->f.stale_link = fentry->f.stale_link;
        dfentry->sort_key = NULL;
        dfentry->second_sort_key = NULL;
        if (fentry->f.marked)
        {
            g_hash_table_insert (marked_files, dfentry->fname, dfentry);
            marked_cnt++;
        }
    }

    /* save len for later dir_list_clean() */
    dir_copy.len = list->len;

    /* Add ".." except to the root directory. The ".." entry
       (if any) must be the first in the list. */
    tmp_path = vfs_path_get_by_index (vpath, 0)->path;
    if (vfs_path_elements_count (vpath) == 1 && IS_PATH_SEP (tmp_path[0]) && tmp_path[1] == '\0')
    {
        /* root directory */
        dir_list_clean (list);
    }
    else
    {
        dir_list_clean (list);
        if (!dir_list_init (list))
        {
            dir_list_clean (&dir_copy);
            return;
        }

        if (dir_get_dotdot_stat (vpath, &st))
        {
            file_entry_t *fentry;

            fentry = &list->list[0];
            fentry->st = st;
        }
    }

    while ((dp = mc_readdir (dirp)) != NULL)
    {
        file_entry_t *fentry;

        if (!handle_dirent (dp, fltr, &st, &link_to_dir, &stale_link))
            continue;

        if (!dir_list_append (list, dp->d_name, &st, link_to_dir != 0, stale_link != 0))
        {
            mc_closedir (dirp);
            /* Norbert (Feb 12, 1997):
               Just in case someone finds this memory leak:
               -1 means big trouble (at the moment no memory left),
               I don't bother with further cleanup because if one gets to
               this point he will have more problems than a few memory
               leaks and because one 'dir_list_clean' would not be enough (and
               because I don't want to spent the time to make it working,
               IMHO it's not worthwhile).
               dir_list_clean (&dir_copy);
             */
            tree_store_end_check ();
            g_hash_table_destroy (marked_files);
            return;
        }
        fentry = &list->list[list->len - 1];

        fentry->f.marked = 0;

        /*
         * If we have marked files in the copy, scan through the copy
         * to find matching file.  Decrease number of remaining marks if
         * we copied one.
         */
        if (marked_cnt > 0 && g_hash_table_lookup (marked_files, dp->d_name) != NULL)
        {
            fentry->f.marked = 1;
            marked_cnt--;
        }

        if ((list->len & 15) == 0)
            rotate_dash (TRUE);
    }
    mc_closedir (dirp);
    tree_store_end_check ();
    g_hash_table_destroy (marked_files);

    dir_list_sort (list, sort, sort_op);

    dir_list_clean (&dir_copy);
    rotate_dash (FALSE);
}
Пример #4
0
static char *
filename_completion_function (char *text, int state)
{
    static DIR *directory;
    static char *filename = NULL;
    static char *dirname = NULL;
    static char *users_dirname = NULL;
    static size_t filename_len;
    int isdir = 1, isexec = 0;

    struct dirent *entry = NULL;

    /* If we're starting the match process, initialize us a bit. */
    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);
	}

        /* 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);
	    /* Here we should do something with variable expansion
	       and `command`.
	       Maybe a dream - UNIMPLEMENTED yet. */
        }
        directory = mc_opendir (dirname);
        filename_len = strlen (filename);
    }

    /* Now that we have some state, we can read the directory. */

    while (directory && (entry = mc_readdir (directory))){
        /* Special case for no filename.
	   All entries except "." and ".." match. */
        if (!filename_len){
	    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 = g_malloc (3 + strlen (dirname) + NLENGTH (entry));
	    struct stat tempstat;
	    
	    strcpy (tmp, dirname);
	    strcat (tmp, PATH_SEP_STR);
	    strcat (tmp, entry->d_name);
	    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;
	        }
	    }
	   g_free (tmp);
	}
	switch (look_for_executables)
	{
	    case 2: if (!isexec)
	    	        continue;
	    	    break;
	    case 1: if (!isexec && !isdir)
	    	        continue;
	    	    break;
	}
	if (ignore_filenames && !isdir)
	    continue;
	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;
        return NULL;
    } else {
        char *temp;

        if (users_dirname && (users_dirname[0] != '.' || users_dirname[1])){
	    int 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;
    }
}
Пример #5
0
Файл: dir.c Проект: Chainie/mc
int
do_reload_dir (const vfs_path_t * vpath, dir_list * list, sortfn * sort, int count,
               gboolean lc_reverse, gboolean lc_case_sensitive, gboolean exec_ff, const char *fltr)
{
    DIR *dirp;
    struct dirent *dp;
    int next_free = 0;
    int i, status, link_to_dir, stale_link;
    struct stat st;
    int marked_cnt;
    GHashTable *marked_files;
    const char *tmp_path;

    dirp = mc_opendir (vpath);
    if (dirp == NULL)
    {
        message (D_ERROR, MSG_ERROR, _("Cannot read directory contents"));
        clean_dir (list, count);
        return set_zero_dir (list) ? 1 : 0;
    }

    tree_store_start_check (vpath);

    marked_files = g_hash_table_new (g_str_hash, g_str_equal);
    alloc_dir_copy (list->size);
    for (marked_cnt = i = 0; i < count; i++)
    {
        dir_copy.list[i].fnamelen = list->list[i].fnamelen;
        dir_copy.list[i].fname = list->list[i].fname;
        dir_copy.list[i].f.marked = list->list[i].f.marked;
        dir_copy.list[i].f.dir_size_computed = list->list[i].f.dir_size_computed;
        dir_copy.list[i].f.link_to_dir = list->list[i].f.link_to_dir;
        dir_copy.list[i].f.stale_link = list->list[i].f.stale_link;
        dir_copy.list[i].sort_key = NULL;
        dir_copy.list[i].second_sort_key = NULL;
        if (list->list[i].f.marked)
        {
            g_hash_table_insert (marked_files, dir_copy.list[i].fname, &dir_copy.list[i]);
            marked_cnt++;
        }
    }

    /* Add ".." except to the root directory. The ".." entry
       (if any) must be the first in the list. */
    tmp_path = vfs_path_get_by_index (vpath, 0)->path;
    if (!
        (vfs_path_elements_count (vpath) == 1 && (tmp_path[0] == PATH_SEP)
         && (tmp_path[1] == '\0')))
    {
        if (!set_zero_dir (list))
        {
            clean_dir (list, count);
            clean_dir (&dir_copy, count);
            return next_free;
        }

        if (get_dotdot_dir_stat (vpath, &st))
            list->list[next_free].st = st;

        next_free++;
    }

    while ((dp = mc_readdir (dirp)))
    {
        status = handle_dirent (list, fltr, dp, &st, next_free, &link_to_dir, &stale_link);
        if (status == 0)
            continue;
        if (status == -1)
        {
            mc_closedir (dirp);
            /* Norbert (Feb 12, 1997):
               Just in case someone finds this memory leak:
               -1 means big trouble (at the moment no memory left),
               I don't bother with further cleanup because if one gets to
               this point he will have more problems than a few memory
               leaks and because one 'clean_dir' would not be enough (and
               because I don't want to spent the time to make it working,
               IMHO it's not worthwhile).
               clean_dir (&dir_copy, count);
             */
            tree_store_end_check ();
            g_hash_table_destroy (marked_files);
            return next_free;
        }

        list->list[next_free].f.marked = 0;

        /*
         * If we have marked files in the copy, scan through the copy
         * to find matching file.  Decrease number of remaining marks if
         * we copied one.
         */
        if (marked_cnt > 0)
        {
            if ((g_hash_table_lookup (marked_files, dp->d_name)))
            {
                list->list[next_free].f.marked = 1;
                marked_cnt--;
            }
        }

        list->list[next_free].fnamelen = NLENGTH (dp);
        list->list[next_free].fname = g_strndup (dp->d_name, list->list[next_free].fnamelen);
        list->list[next_free].f.link_to_dir = link_to_dir;
        list->list[next_free].f.stale_link = stale_link;
        list->list[next_free].f.dir_size_computed = 0;
        list->list[next_free].st = st;
        list->list[next_free].sort_key = NULL;
        list->list[next_free].second_sort_key = NULL;
        next_free++;
        if (!(next_free % 16))
            rotate_dash ();
    }
    mc_closedir (dirp);
    tree_store_end_check ();
    g_hash_table_destroy (marked_files);
    if (next_free)
    {
        do_sort (list, sort, next_free - 1, lc_reverse, lc_case_sensitive, exec_ff);
    }
    clean_dir (&dir_copy, count);
    return next_free;
}
Пример #6
0
Файл: dir.c Проект: Chainie/mc
int
do_load_dir (const vfs_path_t * vpath, dir_list * list, sortfn * sort, gboolean lc_reverse,
             gboolean lc_case_sensitive, gboolean exec_ff, const char *fltr)
{
    DIR *dirp;
    struct dirent *dp;
    int status, link_to_dir, stale_link;
    int next_free = 0;
    struct stat st;
    char *path;

    /* ".." (if any) must be the first entry in the list */
    if (!set_zero_dir (list))
        return next_free;

    if (get_dotdot_dir_stat (vpath, &st))
        list->list[next_free].st = st;
    next_free++;

    dirp = mc_opendir (vpath);
    if (dirp == NULL)
    {
        message (D_ERROR, MSG_ERROR, _("Cannot read directory contents"));
        return next_free;
    }

    tree_store_start_check (vpath);

    /* Do not add a ".." entry to the root directory */
    path = vfs_path_to_str (vpath);
    if ((path[0] == PATH_SEP) && (path[1] == '\0'))
        next_free--;
    g_free (path);

    while ((dp = mc_readdir (dirp)) != NULL)
    {
        status = handle_dirent (list, fltr, dp, &st, next_free, &link_to_dir, &stale_link);
        if (status == 0)
            continue;
        if (status == -1)
            goto ret;

        list->list[next_free].fnamelen = NLENGTH (dp);
        list->list[next_free].fname = g_strndup (dp->d_name, list->list[next_free].fnamelen);
        list->list[next_free].f.marked = 0;
        list->list[next_free].f.link_to_dir = link_to_dir;
        list->list[next_free].f.stale_link = stale_link;
        list->list[next_free].f.dir_size_computed = 0;
        list->list[next_free].st = st;
        list->list[next_free].sort_key = NULL;
        list->list[next_free].second_sort_key = NULL;
        next_free++;

        if ((next_free & 31) == 0)
            rotate_dash ();
    }

    if (next_free != 0)
        do_sort (list, sort, next_free - 1, lc_reverse, lc_case_sensitive, exec_ff);

  ret:
    mc_closedir (dirp);
    tree_store_end_check ();
    return next_free;
}