2010-03-05 4 views
2

Je veux que mon programme connaisse toujours tous les points de montage. Après un rapide google j'ai trouvé que getmntent() et les amis peuvent me dire ce qui est monté. Je me suis rendu compte que je pouvais le faire à chaque fois que j'avais besoin de savoir ce qui était monté, mais est-il possible de reconnaître quand quelque chose est monté/démonté afin de ne pas avoir à lire le fichier? Est-ce ce que dBus fait?Comment puis-je savoir quand quelque chose est monté

Des indices seraient utiles. J'essaie de commencer à programmer (j'ai suivi un cours sur C en 2002, quand j'étais au collège) et j'ai trouvé une fonctionnalité que je veux implémenter dans un programme open source.

+1

Est-ce une question Linux? Mieux l'étiqueter comme tel ... –

+0

Ahh oui j'ai ajouté l'étiquette. Merci. – Patrick

+4

C'est ce qu'elle a dit? – newdayrising

Répondre

1

Basé sur la mention de getmntent(), je vais deviner que vous avez affaire à Linux (d'autres Unices l'incluent aussi, mais ils sont beaucoup moins courants de nos jours ...). Si c'est le cas, man inotify devrait vous aider à démarrer.

+0

Il y a une explication et un exemple de code pour 'inotify' ici: http://www.ibm.com/developerworks/linux/library/l-ubuntu-inotify/index.html?ca=drs- – bta

3

Si vous codez pour Linux (ou utilisez néanmoins des bibliothèques GNOME), GIO de GNOME fournit une bonne API pour cela. Voici un moniteur d'entraînement trivial je l'ai écrit en C qui utilise GTK et GIO:

#include <gio/gio.h> 
#include <gtk/gtk.h> 
#include <string.h> 

typedef struct { 
    GtkWidget *window; 
    GtkWidget *vbox; 
    GtkWidget *scrolled_window; 
    GtkWidget *view; 
    GtkWidget *button; 

    GtkListStore *store; 
    GVolumeMonitor *monitor; 
} Context[1]; 

enum { 
    COL_DRIVE, 
    COL_ICON, 
    COL_NAME, 
    NUM_COLS 
}; 

static int find_drive(GtkTreeModel *model, GDrive *drive, GtkTreeIter *iter) 
{ 
    gboolean valid; 

    valid = gtk_tree_model_get_iter_first(model, iter); 
    while (valid) { 
     GDrive *cur; 
     gtk_tree_model_get(model, iter, COL_DRIVE, &cur, -1); 

     if (cur == drive) 
      return 1; 

     valid = gtk_tree_model_iter_next(model, iter); 
    } 

    return 0; 
} 

static void set_drive_iter(Context ctx, GDrive *drive, GtkTreeIter *iter) 
{ 
    GIcon *icon = g_drive_get_icon(drive); 
    gchar *name = g_drive_get_name(drive); 

    gtk_list_store_set(ctx->store, iter, 
     COL_DRIVE, drive, 
     COL_ICON, icon, 
     COL_NAME, name, 
     -1); 

    g_free(name); 
} 

static void add_drive(Context ctx, GDrive *drive) 
{ 
    GtkTreeIter iter; 
    gtk_list_store_append(ctx->store, &iter); 
    set_drive_iter(ctx, drive, &iter); 
} 

static void refresh_drive_list(Context ctx) 
{ 
    GList *drives, *l; 
    drives = g_volume_monitor_get_connected_drives(ctx->monitor); 

    gtk_list_store_clear(ctx->store); 

    for (l = drives; l; l = l->next) 
     add_drive(ctx, l->data); 
} 

static void update_drive(Context ctx, GDrive *drive) 
{ 
    GtkTreeModel *model = GTK_TREE_MODEL(ctx->store); 
    GtkTreeIter iter; 

    if (find_drive(model, drive, &iter)) 
     set_drive_iter(ctx, drive, &iter); 
    else 
     refresh_drive_list(ctx); //Shouldn't happen 
} 

static void remove_drive(Context ctx, GDrive *drive) 
{ 
    GtkTreeModel *model = GTK_TREE_MODEL(ctx->store); 
    GtkTreeIter iter; 

    if (find_drive(model, drive, &iter)) 
     gtk_list_store_remove(ctx->store, &iter); 
    else 
     refresh_drive_list(ctx); //Shouldn't happen 
} 

static void init_drive_list(Context ctx) 
{ 
    ctx->store = gtk_list_store_new(3, G_TYPE_POINTER, G_TYPE_ICON, G_TYPE_STRING); 
    refresh_drive_list(ctx); 
} 

static void init_drive_view(Context ctx) 
{ 
    GtkTreeViewColumn *column; 
    GtkCellRenderer *renderer; 

    ctx->view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ctx->store)); 
    g_object_set(ctx->view, 
     "headers-visible", FALSE, 
     NULL); 

    renderer = gtk_cell_renderer_pixbuf_new(); 
    g_object_set(renderer, "stock-size", GTK_ICON_SIZE_DIALOG, NULL); 
    column = gtk_tree_view_column_new_with_attributes("Icon", renderer, "gicon", COL_ICON, NULL); 
    gtk_tree_view_column_set_resizable(column, TRUE); 
    gtk_tree_view_append_column(GTK_TREE_VIEW(ctx->view), column); 

    renderer = gtk_cell_renderer_text_new(); 
    column = gtk_tree_view_column_new_with_attributes("Name", renderer, "text", COL_NAME, NULL); 
    gtk_tree_view_column_set_resizable(column, TRUE); 
    gtk_tree_view_append_column(GTK_TREE_VIEW(ctx->view), column); 
} 

static void print_drive_info(GDrive *drive) 
{ 
    GIcon *icon; 
    gchar *name, *icon_string; 

    name = g_drive_get_name(drive); 
    icon = g_drive_get_icon(drive); 
    icon_string = g_icon_to_string(icon); 
    g_object_unref(icon); 

    g_print("\tname: %s\n\ticon: %s\n", 
     name ? name : "(null)", 
     icon_string ? icon_string : "(null)"); 

    g_free(name); 
    g_free(icon_string); 
} 

static void on_drive_changed(GVolumeMonitor *volume_monitor, GDrive *drive, Context ctx) 
{ 
    g_print("Drive changed:\n"); 
    print_drive_info(drive); 
    update_drive(ctx, drive); 
} 

static void on_drive_connected(GVolumeMonitor *volume_monitor, GDrive *drive, Context ctx) 
{ 
    g_print("Drive connected:\n"); 
    print_drive_info(drive); 
    add_drive(ctx, drive); 
} 

static void on_drive_disconnected(GVolumeMonitor *volume_monitor, GDrive *drive, Context ctx) 
{ 
    g_print("Drive disconnected:\n"); 
    print_drive_info(drive); 
    remove_drive(ctx, drive); 
} 

static void on_refresh_clicked(GtkButton *button, Context ctx) 
{ 
    refresh_drive_list(ctx); 
} 

int main(int argc, char *argv[]) 
{ 
    Context ctx; 
    memset(ctx, 0, sizeof(ctx)); 
    gtk_init(&argc, &argv); 

    ctx->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
    g_signal_connect(ctx->window, "destroy", G_CALLBACK(gtk_main_quit), NULL); 

    ctx->vbox = gtk_vbox_new(FALSE, 0); 
    gtk_widget_show(ctx->vbox); 
    gtk_container_add(GTK_CONTAINER(ctx->window), ctx->vbox); 

    ctx->scrolled_window = gtk_scrolled_window_new(NULL, NULL); 
    gtk_scrolled_window_set_policy(
     GTK_SCROLLED_WINDOW(ctx->scrolled_window), 
     GTK_POLICY_AUTOMATIC, 
     GTK_POLICY_AUTOMATIC); 
    gtk_box_pack_start(GTK_BOX(ctx->vbox), ctx->scrolled_window, TRUE, TRUE, 0); 
    gtk_widget_show(ctx->scrolled_window); 

    ctx->monitor = g_volume_monitor_get(); 
    g_signal_connect(ctx->monitor, "drive-changed", G_CALLBACK(on_drive_changed), ctx); 
    g_signal_connect(ctx->monitor, "drive-connected", G_CALLBACK(on_drive_connected), ctx); 
    g_signal_connect(ctx->monitor, "drive-disconnected", G_CALLBACK(on_drive_disconnected), ctx); 

    init_drive_list(ctx); 
    init_drive_view(ctx); 
    gtk_widget_show(ctx->view); 
    gtk_container_add(GTK_CONTAINER(ctx->scrolled_window), ctx->view); 

    ctx->button = gtk_button_new_from_stock(GTK_STOCK_REFRESH); 
    g_signal_connect(ctx->button, "clicked", G_CALLBACK(on_refresh_clicked), ctx); 
    gtk_widget_show(ctx->button); 
    gtk_box_pack_start(GTK_BOX(ctx->vbox), ctx->button, FALSE, FALSE, 0); 

    gtk_window_set_default_size(GTK_WINDOW(ctx->window), 500, 500); 
    gtk_widget_show(ctx->window); 

    gtk_main(); 
    return 0; 
} 

Compile avec gcc $(pkg-config --cflags --libs gtk+-2.0) volumes.c -o volumes. Testez-le en l'exécutant, puis en branchant une clé USB. Il devrait mettre à jour à la volée. Il affiche même les icônes appropriées.

Notez que cela surveille les lecteurs, pas les montages. GVolumeMonitor peut également surveiller les montages (voir "mount-added" et "mount-removed" dans devhelp). Vous devrez en apprendre un peu plus sur le système GObject pour l'utiliser. Bonne chance!

Questions connexes