⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vfs-file-task.c

📁 台湾人开发的Linux下的文件管理器
💻 C
📖 第 1 页 / 共 2 页
字号:
        call_state_callback( task, VFS_FILE_TASK_ERROR );    }    g_free( dest_file );}static voidvfs_file_task_delete( char* src_file, VFSFileTask* task ){    GDir * dir;    gchar* file_name;    gchar* sub_src_file;    struct stat file_stat;    int result;    task->current_file = src_file;    if ( should_abort( task ) )        return ;    if ( lstat( src_file, &file_stat ) == -1 )    {        task->error = errno;        call_state_callback( task, VFS_FILE_TASK_ERROR );        return ; /* Error occurred */    }    task->current_file = src_file;    call_progress_callback( task );    if ( S_ISDIR( file_stat.st_mode ) )    {        dir = g_dir_open( src_file, 0, NULL );        while ( (file_name = g_dir_read_name( dir )) )        {            if ( should_abort( task ) )                break;            sub_src_file = g_build_filename( src_file, file_name, NULL );            vfs_file_task_delete( sub_src_file, task );            g_free( sub_src_file );        }        g_dir_close( dir );        if ( should_abort( task ) )            return ;        result = rmdir( src_file );        if ( result != 0 )        {            task->error = errno;            call_state_callback( task, VFS_FILE_TASK_ERROR );            return ;        }        task->progress += file_stat.st_size;        call_progress_callback( task );    }    else    {        result = unlink( src_file );        if ( result != 0 )        {            task->error = errno;            call_state_callback( task, VFS_FILE_TASK_ERROR );            return ;        }        task->progress += file_stat.st_size;        call_progress_callback( task );    }}static voidvfs_file_task_link( char* src_file, VFSFileTask* task ){    struct stat src_stat, dest_stat;    int result;    gchar* dest_file;    gchar* file_name = g_path_get_basename( src_file );    if ( should_abort( task ) )        return ;    file_name = g_path_get_basename( src_file );    dest_file = g_build_filename( task->dest_dir, file_name, NULL );    g_free( file_name );    call_progress_callback( task );    if ( stat( src_file, &src_stat ) == -1 )    {        task->error = errno;        call_state_callback( task, VFS_FILE_TASK_ERROR );        if ( should_abort( task ) )            return ;    }    /* FIXME: Check overwrite!! */    result = symlink( src_file, dest_file );    g_free( dest_file );    if ( result )    {        task->error = errno;        call_state_callback( task, VFS_FILE_TASK_ERROR );        if ( should_abort( task ) )            return ;    }    task->progress += src_stat.st_size;    call_progress_callback( task );}static voidvfs_file_task_chown_chmod( char* src_file, VFSFileTask* task ){    struct stat src_stat;    int i;    GDir* dir;    gchar* sub_src_file;    gchar* file_name;    mode_t new_mode;    int result;    if( should_abort( task ) )        return ;    task->current_file = src_file;    /* g_debug("chmod_chown: %s\n", src_file); */    call_progress_callback( task );    if ( lstat( src_file, &src_stat ) == 0 )    {        /* chown */        if ( task->uid != -1 || task->gid != -1 )        {            result = chown( src_file, task->uid, task->gid );            if ( result != 0 )            {                task->error = errno;                call_state_callback( task, VFS_FILE_TASK_ERROR );                if ( should_abort( task ) )                    return ;            }        }        /* chmod */        if ( task->chmod_actions )        {            new_mode = src_stat.st_mode;            for ( i = 0; i < N_CHMOD_ACTIONS; ++i )            {                if ( task->chmod_actions[ i ] == 2 )            /* Don't change */                    continue;                if ( task->chmod_actions[ i ] == 0 )            /* Remove this bit */                    new_mode &= ~chmod_flags[ i ];                else  /* Add this bit */                    new_mode |= chmod_flags[ i ];            }            if ( new_mode != src_stat.st_mode )            {                result = chmod( src_file, new_mode );                if ( result != 0 )                {                    task->error = errno;                    call_state_callback( task, VFS_FILE_TASK_ERROR );                    if ( should_abort( task ) )                        return ;                }            }        }        task->progress += src_stat.st_size;        call_progress_callback( task );        if ( S_ISDIR( src_stat.st_mode ) && task->recursive )        {            if ( (dir = g_dir_open( src_file, 0, NULL )) )            {                while ( (file_name = g_dir_read_name( dir )) )                {                    if ( should_abort( task ) )                        break;                    sub_src_file = g_build_filename( src_file, file_name, NULL );                    vfs_file_task_chown_chmod( sub_src_file, task );                    g_free( sub_src_file );                }                g_dir_close( dir );            }            else            {                task->error = errno;                call_state_callback( task, VFS_FILE_TASK_ERROR );                if ( should_abort( task ) )                    return ;            }        }    }}static gpointer vfs_file_task_thread ( VFSFileTask* task ){    GList * l;    struct stat file_stat;    dev_t dest_dev;    char* src_path;    gboolean cancelled = FALSE;    GFunc funcs[] = {( GFunc ) vfs_file_task_move,                     ( GFunc ) vfs_file_task_copy,                     ( GFunc ) vfs_file_task_delete,                     ( GFunc ) vfs_file_task_link,                     ( GFunc ) vfs_file_task_chown_chmod};    if ( task->type < VFS_FILE_TASK_MOVE            || task->type >= VFS_FILE_TASK_LAST )        goto _exit_thread;    task->state = VFS_FILE_TASK_RUNNING;    task->current_file = ( char* ) task->src_paths->data;    task->total_size = 0;    call_progress_callback( task );    /* Calculate total size of all files */    if ( task->recursive )    {        for ( l = task->src_paths; l; l = l->next )        {            if( task->dest_dir && g_str_has_prefix( task->dest_dir, (char*)l->data ) )            {                /* FIXME: This has serious problems */                /* Check if source file is contained in destination dir */                /* The src file is already in dest dir */                if( lstat( (char*)l->data, &file_stat ) == 0                    && S_ISDIR(file_stat.st_mode) )                {                    /* It's a dir */                    if ( task->state_cb )                    {                        char* err;                        char* disp_src;                        char* disp_dest;                        disp_src = g_filename_display_name( (char*)l->data );                        disp_dest = g_filename_display_name( task->dest_dir );                        err = g_strdup_printf( _("Destination directory \"%1$s\" is contained in source \"%2$s\""), disp_dest, disp_src );                        if ( task->state_cb( task, VFS_FILE_TASK_ERROR,                             err, task->state_cb_data ) )                            task->state = VFS_FILE_TASK_RUNNING;                        else                            task->state = VFS_FILE_TASK_ABORTED;                        g_free( disp_src );                        g_free( disp_dest );                        g_free( err );                    }                    else                        task->state = VFS_FILE_TASK_ABORTED;                    if ( should_abort( task ) )                        goto _exit_thread;                }            }            get_total_size_of_dir( task, ( char* ) l->data, &task->total_size );        }    }    else    {        if ( task->type != VFS_FILE_TASK_CHMOD_CHOWN )        {            if ( task->dest_dir &&                    lstat( task->dest_dir, &file_stat ) < 0 )            {                task->error = errno;                call_state_callback( task, VFS_FILE_TASK_ERROR );                if ( should_abort( task ) )                    goto _exit_thread;            }            dest_dev = file_stat.st_dev;        }        for ( l = task->src_paths; l; l = l->next )        {            if ( lstat( ( char* ) l->data, &file_stat ) == -1 )            {                task->error = errno;                call_state_callback( task, VFS_FILE_TASK_ERROR );                if ( should_abort( task ) )                    goto _exit_thread;            }            if ( S_ISLNK( file_stat.st_mode ) )      /* Don't do deep copy for symlinks */                task->recursive = FALSE;            else if ( task->type == VFS_FILE_TASK_MOVE )                task->recursive = ( file_stat.st_dev != dest_dev );            if ( task->recursive )            {                get_total_size_of_dir( task, ( char* ) l->data,                                       &task->total_size );            }            else            {                task->total_size += file_stat.st_size;            }        }    }    g_list_foreach( task->src_paths,                    funcs[ task->type ],                    task );_exit_thread:    if ( task->state_cb )        call_state_callback( task, VFS_FILE_TASK_FINISH );    else    {        /* FIXME: Will this cause any problem? */        task->thread = NULL;        vfs_file_task_free( task );    }    return NULL;}/** source_files sould be a newly allocated list, and it will be* freed after file operation has been completed*/VFSFileTask* vfs_task_new ( VFSFileTaskType type,                            GList* src_files,                            const char* dest_dir ){    VFSFileTask * task;    task = g_slice_new0( VFSFileTask );    task->type = type;    task->src_paths = src_files;    if ( dest_dir )        task->dest_dir = g_strdup( dest_dir );    if ( task->type == VFS_FILE_TASK_COPY || task->type == VFS_FILE_TASK_DELETE )        task->recursive = TRUE;    return task;}/* Set some actions for chmod, this array will be copied* and stored in VFSFileTask */void vfs_file_task_set_chmod( VFSFileTask* task,                              guchar* chmod_actions ){    task->chmod_actions = g_slice_alloc( sizeof( guchar ) * N_CHMOD_ACTIONS );    memcpy( ( void* ) task->chmod_actions, ( void* ) chmod_actions,            sizeof( guchar ) * N_CHMOD_ACTIONS );}void vfs_file_task_set_chown( VFSFileTask* task,                              uid_t uid, gid_t gid ){    task->uid = uid;    task->gid = gid;}void vfs_file_task_run ( VFSFileTask* task ){    task->thread = g_thread_create( ( GThreadFunc ) vfs_file_task_thread,                                    task, TRUE, NULL );}void vfs_file_task_try_abort ( VFSFileTask* task ){    task->state = VFS_FILE_TASK_QUERY_ABORT;}void vfs_file_task_abort ( VFSFileTask* task ){    task->state = VFS_FILE_TASK_ABORTED;    /* Called from another thread */    if ( g_thread_self() != task->thread )    {        g_thread_join( task->thread );        task->thread = NULL;    }}void vfs_file_task_free ( VFSFileTask* task ){    if ( task->src_paths )    {        g_list_foreach( task->src_paths, ( GFunc ) g_free, NULL );        g_list_free( task->src_paths );    }    g_free( task->dest_dir );    if ( task->chmod_actions )        g_slice_free1( sizeof( guchar ) * N_CHMOD_ACTIONS,                       task->chmod_actions );    g_slice_free( VFSFileTask, task );}/** void get_total_size_of_dir( const char* path, off_t* size )* Recursively count total size of all files in the specified directory.* If the path specified is a file, the size of the file is directly returned.* cancel is used to cancel the operation. This function will check the value* pointed by cancel in every iteration. If cancel is set to TRUE, the* calculation is cancelled.* NOTE: *size should be set to zero before calling this function.*/void get_total_size_of_dir( VFSFileTask* task,                            const char* path,                            off_t* size ){    GDir * dir;    const char* name;    char* full_path;    struct stat file_stat;    if ( should_abort( task ) )        return;    lstat( path, &file_stat );    *size += file_stat.st_size;    if ( S_ISLNK( file_stat.st_mode ) )             /* Don't follow symlinks */        return ;    dir = g_dir_open( path, 0, NULL );    if ( dir )    {        while ( (name = g_dir_read_name( dir )) )        {            if ( should_abort( task ) )                break;            full_path = g_build_filename( path, name, NULL );            lstat( full_path, &file_stat );            if ( S_ISDIR( file_stat.st_mode ) )            {                get_total_size_of_dir( task, full_path, size );            }            else            {                *size += file_stat.st_size;            }            g_free( full_path );        }        g_dir_close( dir );    }}void vfs_file_task_set_recursive( VFSFileTask* task, gboolean recursive ){    task->recursive = recursive;}void vfs_file_task_set_overwrite_mode( VFSFileTask* task,                                       VFSFileTaskOverwriteMode mode ){    task->overwrite_mode = mode;}void vfs_file_task_set_progress_callback( VFSFileTask* task,                                          VFSFileTaskProgressCallback cb,                                          gpointer user_data ){    task->progress_cb = cb;    task->progress_cb_data = user_data;}void vfs_file_task_set_state_callback( VFSFileTask* task,                                       VFSFileTaskStateCallback cb,                                       gpointer user_data ){    task->state_cb = cb;    task->state_cb_data = user_data;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -