void vfs_dir_class_init( VFSDirClass* klass ) { GObjectClass * object_class; object_class = ( GObjectClass * ) klass; parent_class = g_type_class_peek_parent ( klass ); object_class->set_property = vfs_dir_set_property; object_class->get_property = vfs_dir_get_property; object_class->finalize = vfs_dir_finalize; /* signals */ // klass->file_created = on_vfs_dir_file_created; // klass->file_deleted = on_vfs_dir_file_deleted; // klass->file_changed = on_vfs_dir_file_changed; /* * file-created is emitted when there is a new file created in the dir. * The param is VFSFileInfo of the newly created file. */ signals[ FILE_CREATED_SIGNAL ] = g_signal_new ( "file-created", G_TYPE_FROM_CLASS ( klass ), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET ( VFSDirClass, file_created ), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER ); /* * file-deleted is emitted when there is a file deleted in the dir. * The param is VFSFileInfo of the newly created file. */ signals[ FILE_DELETED_SIGNAL ] = g_signal_new ( "file-deleted", G_TYPE_FROM_CLASS ( klass ), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET ( VFSDirClass, file_deleted ), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER ); /* * file-changed is emitted when there is a file changed in the dir. * The param is VFSFileInfo of the newly created file. */ signals[ FILE_CHANGED_SIGNAL ] = g_signal_new ( "file-changed", G_TYPE_FROM_CLASS ( klass ), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET ( VFSDirClass, file_changed ), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER ); signals[ THUMBNAIL_LOADED_SIGNAL ] = g_signal_new ( "thumbnail-loaded", G_TYPE_FROM_CLASS ( klass ), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET ( VFSDirClass, thumbnail_loaded ), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER ); signals[ FILE_LISTED_SIGNAL ] = g_signal_new ( "file-listed", G_TYPE_FROM_CLASS ( klass ), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET ( VFSDirClass, file_listed ), NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN ); /* FIXME: Is there better way to do this? */ if( G_UNLIKELY( ! is_desktop_set ) ) vfs_get_desktop_dir(); if( ! home_trash_dir ) vfs_get_trash_dir(); }
static gpointer vfs_file_task_thread ( VFSFileTask* task ) { GList * l; struct stat file_stat; dev_t dest_dev = 0; GFunc funcs[] = {( GFunc ) vfs_file_task_move, ( GFunc ) vfs_file_task_copy, ( GFunc ) vfs_file_task_move, /* trash */ ( 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; if( task->type == VFS_FILE_TASK_TRASH ) { task->dest_dir = g_build_filename( vfs_get_trash_dir(), "files", NULL ); /* Create the trash dir if it doesn't exist */ if( ! g_file_test( task->dest_dir, G_FILE_TEST_EXISTS ) ) g_mkdir_with_parents( task->dest_dir, 0700 ); } 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->type == VFS_FILE_TASK_TRASH ) 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; }