📄 vfs-volume.c
字号:
/** C Implementation: vfs-volume** Description: *** Author: Hong Jen Yee (PCMan) <pcman.tw (AT) gmail.com>, (C) 2006** Copyright: See COPYING file that comes with this distribution**/#ifdef HAVE_CONFIG_H#include <config.h>#endif#include "vfs-volume.h"#include "glib-mem.h"#include <glib/gi18n.h>#ifdef HAVE_HAL#include <dbus/dbus.h>#include <dbus/dbus-glib.h>#include <dbus/dbus-glib-lowlevel.h>#include <libhal.h> /* #include <libhal-storage.h> */struct _VFSVolume{ char* udi; char* storage_udi; char* disp_name; char* icon; char* mount_point; gboolean is_mounted; gboolean is_hotpluggable; gboolean is_removable; gboolean requires_eject;};typedef struct _VFSVolumeCallbackData{ VFSVolumeCallback cb; gpointer user_data;}VFSVolumeCallbackData;static LibHalContext* hal_context = NULL;static DBusConnection * dbus_connection = NULL;/* FIXME: Will it be better if we use GSList? */static GArray* volumes = NULL;static GArray* callbacks = NULL;static call_callbacks( VFSVolume* vol, VFSVolumeState state ){ int i; VFSVolumeCallbackData* e; if ( !callbacks ) return ; e = ( VFSVolumeCallbackData* ) callbacks->data; for ( i = 0; i < callbacks->len; ++i ) { ( *e[ i ].cb ) ( vol, state, e[ i ].user_data ); }}static void vfs_volume_set_from_udi( VFSVolume* volume, const char* udi ){ g_free( volume->udi ); volume->udi = g_strdup( udi ); g_free( volume->mount_point ); volume->mount_point = libhal_device_get_property_string ( hal_context, udi, "volume.mount_point", NULL ); if ( volume->mount_point && !*volume->mount_point ) { libhal_free_string( volume->mount_point ); volume->mount_point = NULL; } g_free( volume->storage_udi ); volume->storage_udi = libhal_device_get_property_string ( hal_context, udi, "block.storage_device", NULL ); if ( G_UNLIKELY( ! volume->mount_point ) ) volume->is_mounted = FALSE; else volume->is_mounted = libhal_device_get_property_bool ( hal_context, udi, "volume.is_mounted", NULL ); volume->is_hotpluggable = libhal_device_get_property_bool ( hal_context, volume->storage_udi, "storage.hotpluggable", NULL ); volume->requires_eject = libhal_device_get_property_bool ( hal_context, volume->storage_udi, "storage.requires_eject", NULL ); volume->is_removable = libhal_device_get_property_bool ( hal_context, volume->storage_udi, "storage.removable", NULL );}static VFSVolume* vfs_volume_new( const char* udi ){ VFSVolume * volume; const char* storage_udi; volume = g_slice_new0( VFSVolume ); vfs_volume_set_from_udi( volume, udi ); return volume;}void vfs_volume_free( VFSVolume* volume ){ g_free( volume->udi ); if ( volume->mount_point ) libhal_free_string( volume->mount_point ); if ( volume->storage_udi ) libhal_free_string( volume->storage_udi ); g_free( volume->disp_name ); g_slice_free( VFSVolume, volume );}static void vfs_volume_update_disp_name( VFSVolume* vol ){ char * disp_name = NULL; char* label; g_free( vol->disp_name ); if( G_UNLIKELY(vol->mount_point && 0 == strcmp("/", vol->mount_point)) ) { vol->disp_name = g_strdup(_("File System")); return; } label = libhal_device_get_property_string ( hal_context, vol->udi, "volume.label", NULL ); if ( G_LIKELY( label ) ) { if ( *label ) disp_name = g_strdup( label ); libhal_free_string( label ); } /* FIXME: Display better names for cdroms and other removable media */ if ( ! disp_name ) { char * device; device = libhal_device_get_property_string ( hal_context, vol->udi, "block.device", NULL ); if ( G_LIKELY( device ) ) { if ( *device ) disp_name = g_path_get_basename( device ); libhal_free_string( device ); } } vol->disp_name = disp_name;}static void on_hal_device_added( LibHalContext *ctx, const char *udi ){ VFSVolume * volume; char* fs; if ( libhal_device_get_property_bool ( ctx, udi, "volume.ignore", NULL ) ) return ; if ( ! libhal_device_property_exists ( ctx, udi, "volume.fsusage", NULL ) ) return ; /* g_debug("device added: %s", udi); */ fs = libhal_device_get_property_string ( ctx, udi, "volume.fsusage", NULL ); if ( !fs || ( ( strcmp ( fs, "filesystem" ) != 0 ) && ( strcmp ( fs, "crypto" ) != 0 ) ) ) { libhal_free_string ( fs ); return ; }g_debug("device added: %s", udi); volume = vfs_volume_new( udi ); /* FIXME: sort items */ volumes = g_array_append_val( volumes, volume ); call_callbacks( volume, VFS_VOLUME_ADDED );}static void on_hal_device_removed( LibHalContext *ctx, const char *udi ){ int i; VFSVolume **v, *volume; if ( !volumes ) return ; /* g_debug("device removed: %s", udi); */ v = ( VFSVolume** ) volumes->data; for ( i = 0; i < volumes->len; ++i ) { if ( 0 == strcmp( v[ i ] ->udi, udi ) ) { volume = v[ i ]; volumes = g_array_remove_index( volumes, i ); call_callbacks( volume, VFS_VOLUME_REMOVED ); vfs_volume_free( volume ); break; } }}static void on_hal_property_modified( LibHalContext *ctx, const char *udi, const char *key, dbus_bool_t is_removed, dbus_bool_t is_added ){ /* FIXME: on_hal_property_modified: this func is not efficient, nor correct */ int i; VFSVolume** v; if ( !volumes ) return ; v = ( VFSVolume** ) volumes->data; for ( i = 0; i < volumes->len; ++i ) { if ( 0 == strcmp( v[ i ] ->udi , udi ) ) { vfs_volume_set_from_udi( v[ i ], udi ); vfs_volume_update_disp_name( v[ i ] ); call_callbacks( v[ i ], VFS_VOLUME_CHANGED ); break; } }}static void on_hal_condition ( LibHalContext *ctx, const char *udi, const char *condition_name, const char *condition_detail ){ /* FIXME: on_hal_condition: this func is not efficient, nor correct */ /* g_debug( "condition changed: %s, %s, %s\n", condition_name, condition_detail, udi ); */ int i; VFSVolume** v; if ( !volumes ) return ; v = ( VFSVolume** ) volumes->data; for ( i = 0; i < volumes->len; ++i ) { if ( 0 == strcmp( v[ i ] ->udi , udi ) ) { vfs_volume_set_from_udi( v[ i ], udi ); call_callbacks( v[ i ], VFS_VOLUME_CHANGED ); break; } }}/* This function is taken from gnome volumen manager */static dbus_bool_thal_mainloop_integration ( LibHalContext *ctx, DBusError *error ){ dbus_connection = dbus_bus_get ( DBUS_BUS_SYSTEM, error ); if ( dbus_error_is_set ( error ) ) return FALSE; dbus_connection_setup_with_g_main ( dbus_connection, NULL ); libhal_ctx_set_dbus_connection ( ctx, dbus_connection ); return TRUE;}gboolean vfs_volume_init(){ DBusError error; char** devices; char** device; int n; if ( hal_context ) return TRUE; hal_context = libhal_ctx_new (); if ( hal_context ) { dbus_error_init ( &error ); if ( hal_mainloop_integration ( hal_context, &error ) ) { libhal_ctx_set_device_added ( hal_context, on_hal_device_added ); libhal_ctx_set_device_removed ( hal_context, on_hal_device_removed ); libhal_ctx_set_device_property_modified ( hal_context, on_hal_property_modified ); /* libhal_ctx_set_device_new_capability (ctx, on_hal_device_new_capability); libhal_ctx_set_device_lost_capability (ctx, on_hal_device_lost_capability); */ libhal_ctx_set_device_condition( hal_context, on_hal_condition ); if ( libhal_ctx_init ( hal_context, &error ) ) { devices = libhal_find_device_by_capability ( hal_context, "volume", &n, &error ); if ( devices ) { volumes = g_array_sized_new( FALSE, FALSE, sizeof( VFSVolume* ), n + 4 ); for ( device = devices; *device; ++device ) { on_hal_device_added( hal_context, *device ); } libhal_free_string_array ( devices ); } else volumes = g_array_sized_new( FALSE, FALSE, sizeof( VFSVolume* ), 4 ); if ( libhal_device_property_watch_all ( hal_context, &error ) ) { dbus_error_free ( &error ); return TRUE; } else { g_warning ( "%s\n", error.message ); } } else { g_warning ( "%s\n", error.message ); } } libhal_ctx_free ( hal_context ); hal_context = NULL; dbus_error_free ( &error ); } else { g_warning ( "%s\n", error.message ); } return FALSE;}gboolean vfs_volume_clean(){ int i; VFSVolume** vols; if ( callbacks ) g_array_free( callbacks, TRUE ); if ( volumes ) { vols = ( VFSVolume** ) volumes->data; for ( i = 0; i < volumes->len; ++i )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -