00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025  
00026 #ifdef HAVE_CONFIG_H
00027 #  include <config.h>
00028 #endif
00029 
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include <dbus/dbus.h>
00034 #include <dbus/dbus-glib.h>
00035 #include <dbus/dbus-glib-lowlevel.h>
00036 
00037 #include <libmnt/libmnt.h>   
00038 
00039 #include "mntd_dbus_error.h"
00040 #include "mntd_dbus_manager.h"
00041 #include "mntd_volume_manager.h"
00042 #include "mntd_volume.h"
00043 #include "errmanager.h"
00044 #include "main.h"
00045 #include "dbug_mem.h"
00046 
00047 
00048 
00049 int cb_append_udi(void *data, void *userdata);
00050 
00051 
00052 
00053 
00054 
00055 
00065 DBusConnection* dbus_connection = NULL;
00066                                                                                                                            
00067 
00073 int 
00074 mntd_dbus_init(void *user_data)
00075 {
00076     DBusError error;
00077     int res = 0;
00078 
00079     dbus_connection_set_change_sigpipe(TRUE);
00080     
00081     dbus_error_init(&error);
00082     dbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
00083     if (dbus_connection==NULL) {
00084         MSG_INF("dbus_bus_get(): '%s'", error.message);
00085         goto error;
00086     }
00087     
00088     
00089     dbus_bus_acquire_service(dbus_connection, DBUS_SERVICE_MNT, 0, &error);
00090     if (dbus_error_is_set(&error)) {
00091         MSG_INF("dbus_bus_acquire_service(): %s: %s", error.name, error.message);
00092         goto error;
00093     }
00094     
00095     
00096     dbus_connection_add_filter(dbus_connection, mntd_dbus_manager_filter_function, 
00097                                         user_data, NULL);
00098 
00099     
00100     dbus_bus_add_match(dbus_connection,
00101         "type='signal',"
00102         "interface='" DBUS_INTERFACE_MNT_BLOCK "',"
00103         "path='" DBUS_PATH_MNT_BLOCK "'",
00104         &error);
00105     if (dbus_error_is_set(&error)) {
00106         MSG_INF("Couldn't register Block signal handler: %s: %s", error.name, error.message);
00107         goto error;
00108     }
00109     
00110     
00111     dbus_bus_add_match(dbus_connection,
00112         "type='signal',"
00113         "interface='" DBUS_INTERFACE_MNT_DISC "',"
00114         "path='" DBUS_PATH_MNT_DISC "'",
00115         &error);
00116     if (dbus_error_is_set(&error)) {
00117         MSG_INF("Couldn't register Disc signal handler: %s: %s", error.name, error.message);
00118         goto error;
00119     }
00120     
00121     
00122     dbus_bus_add_match(dbus_connection,
00123         "type='signal',"
00124         "interface='" DBUS_INTERFACE_UDEV "',"
00125         "path='" DBUS_PATH_UDEV "'",
00126         &error);
00127     if (dbus_error_is_set(&error)) {
00128         MSG_INF("Couldn't register udev signal handler: %s: %s", error.name, error.message);
00129         goto error;
00130     }
00131     
00132     
00133     dbus_bus_add_match(dbus_connection,
00134         "type='signal',"
00135         "interface='" DBUS_INTERFACE_MNT_TTY "',"
00136         "path='" DBUS_PATH_MNT_TTY "'",
00137         &error);
00138     if (dbus_error_is_set(&error)) {
00139         MSG_INF("Couldn't register Tty signal handler: %s: %s", error.name, error.message);
00140         goto error;
00141     }
00142 
00143     
00144     dbus_connection_set_exit_on_disconnect(dbus_connection, FALSE);
00145     
00146     
00147     dbus_connection_setup_with_g_main(dbus_connection, NULL);
00148     
00149     goto cleanup;
00150     
00151 error:
00152     res = -1;
00153     mntd_dbus_quit();
00154     
00155 cleanup:
00156     if (dbus_error_is_set(&error)) {
00157         dbus_error_free(&error);
00158     }
00159 
00160     return res;
00161 }
00162 
00163 
00168 int 
00169 mntd_dbus_quit(void)
00170 {
00171     if (dbus_connection != NULL) {
00172         
00173         
00174         
00175     }
00176     
00177     return 0;
00178 }
00179 
00180 
00187 void mntd_dbus_raise_no_such_device(DBusConnection* connection,
00188                                             DBusMessage* in_reply_to,
00189                                             const char* udi)
00190 {
00191     char buf[512];
00192     DBusMessage *reply;
00193     
00194     snprintf(buf, 511, "No device with id %s", udi);
00195     
00196     
00197     reply = dbus_message_new_error(in_reply_to, 
00198                                             DBUS_ERROR_NO_SUCH_DEVICE, 
00199                                             buf);
00200     if (reply==NULL) {
00201         MSG_EMERG("Out of memory");
00202         return;
00203     }
00204     if (!dbus_connection_send(connection, reply, NULL)) {
00205         MSG_EMERG("Out of memory");
00206         return;
00207     }
00208     dbus_message_unref(reply);
00209 }
00210 
00211 
00219 void mntd_dbus_raise_syntax(DBusConnection* connection,
00220                                             DBusMessage* in_reply_to,
00221                                             const char* method_name)
00222 {
00223     char buf[512];
00224     DBusMessage *reply;
00225     
00226     snprintf(buf, 511, 
00227                 "There is a syntax error in the invocation of "
00228                 "the method %s", method_name);
00229     
00230     
00231     reply = dbus_message_new_error(in_reply_to, 
00232                                             DBUS_ERROR_SYNTAX, 
00233                                             buf);
00234     if (reply==NULL) {
00235         MSG_EMERG("Out of memory");
00236         return;
00237     }
00238     if (!dbus_connection_send(connection, reply, NULL)) {
00239         MSG_EMERG("Out of memory");
00240         return;
00241     }
00242     dbus_message_unref(reply);
00243 }
00244 
00245 
00252 void mntd_dbus_raise_no_mntpnt(DBusConnection* connection,
00253                                             DBusMessage* in_reply_to,
00254                                             const char* udi)
00255 {
00256     char buf[512];
00257     DBusMessage *reply;
00258     
00259     snprintf(buf, 511, 
00260                 "No mount point for '%s' found.", udi);
00261     
00262     
00263     reply = dbus_message_new_error(in_reply_to, 
00264                                             DBUS_ERROR_NO_MNTPNT, 
00265                                             buf);
00266     if (reply==NULL) {
00267         MSG_EMERG("Out of memory");
00268         return;
00269     }
00270     if (!dbus_connection_send(connection, reply, NULL)) {
00271         MSG_EMERG("Out of memory");
00272         return;
00273     }
00274     dbus_message_unref(reply);
00275 }
00276 
00277 
00287 DBusHandlerResult mntd_dbus_manager_filter_function(DBusConnection* connection,
00288                                          DBusMessage* message,
00289                                          void* user_data)
00290 {
00291     PMNTDDATA pdata = (PMNTDDATA) user_data;
00292     g_assert(pdata!=NULL);
00293     
00294     
00295     
00296     
00297     if (dbus_message_is_method_call(message,
00298                                             DBUS_INTERFACE_MNT_MANAGER,
00299                                             "GetAllVolumes")) {
00300         MSG_DEBUG("biz.bambach.Mnt.Manager::GetAllVolumes() called");
00301         g_assert(pdata->vols!=NULL);
00302         return mntd_dbus_manager_get_all_volumes(pdata->vols, connection, message);
00303                                                 
00304     } else if (dbus_message_is_method_call(message,
00305                                             DBUS_INTERFACE_MNT_MANAGER,
00306                                             "GetMntPnt")) {
00307         MSG_DEBUG("biz.bambach.Mnt.Manager::GetMntPnt() called");
00308         g_assert(pdata->vols!=NULL);
00309         return mntd_dbus_manager_get_mntpnt(pdata->vols, connection, message);
00310                                                 
00311     } else if (dbus_message_is_method_call(message,
00312                                             DBUS_INTERFACE_MNT_MANAGER,
00313                                             "Remount")) {
00314         MSG_DEBUG("biz.bambach.Mnt.Manager::Remount() called");
00315         g_assert(pdata->vols!=NULL);
00316         return mntd_dbus_manager_remount(pdata->vols, connection, message);
00317                                                 
00318     
00319     
00320     
00321     } else if (dbus_message_is_signal(message, 
00322                                             DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, 
00323                                             "Disconnected")) {
00324         const char *path = NULL;
00325         path = dbus_message_get_path(message);
00326         if (path != NULL) {
00327             if (strcmp(DBUS_PATH_ORG_FREEDESKTOP_LOCAL, path) == 0) {
00328                 if (pdata->disconnect != NULL) {
00329                     pdata->disconnect(pdata);
00330                 }
00331             }
00332         }
00333         
00334         dbus_connection_unref(connection);
00335         
00336         return DBUS_HANDLER_RESULT_HANDLED;
00337         
00338     
00339     
00340     
00341     } else if (dbus_message_is_signal(message, 
00342                                         DBUS_INTERFACE_MNT_BLOCK, 
00343                                         "Add")) {
00344         char *devname = NULL;
00345         DBusError error;
00346         dbus_error_init(&error);
00347         if (dbus_message_get_args(message, &error, 
00348                                             DBUS_TYPE_STRING, &devname,
00349                                             DBUS_TYPE_INVALID)) {
00350             MSG_DEBUG("Add('%s') called.", devname);
00351             g_assert(pdata->vols!=NULL);
00352             pdata->vols->add_volume(pdata->vols, devname);
00353             dbus_free(devname);
00354         }
00355         
00356     } else if (dbus_message_is_signal(message, 
00357                                         DBUS_INTERFACE_MNT_BLOCK, 
00358                                         "Remove")) {
00359         char *devname = NULL;
00360         DBusError error;
00361         dbus_error_init(&error);
00362         if (dbus_message_get_args(message, &error, 
00363                                             DBUS_TYPE_STRING, &devname,
00364                                             DBUS_TYPE_INVALID)) {
00365             
00366             MSG_DEBUG("Remove('%s') called.", devname);
00367             g_assert(pdata->vols!=NULL);
00368             pdata->vols->remove_volume(pdata->vols, devname);
00369             dbus_free(devname);
00370         }
00371 
00372     
00373     
00374     
00375     } else if (dbus_message_is_signal(message, 
00376                                         DBUS_INTERFACE_MNT_DISC, 
00377                                         "Add")) {
00378         char *devname = NULL;
00379         DBusError error;
00380         dbus_error_init(&error);
00381         if (dbus_message_get_args(message, &error, 
00382                                             DBUS_TYPE_STRING, &devname,
00383                                             DBUS_TYPE_INVALID)) {
00384             MSG_DEBUG("Add('%s') called.", devname);
00385             g_assert(pdata->vols!=NULL);
00386             pdata->vols->add_volume(pdata->vols, devname);
00387             dbus_free(devname);
00388         }
00389         
00390     } else if (dbus_message_is_signal(message, 
00391                                         DBUS_INTERFACE_MNT_DISC, 
00392                                         "Remove")) {
00393         char *devname = NULL;
00394         DBusError error;
00395         dbus_error_init(&error);
00396         if (dbus_message_get_args(message, &error, 
00397                                             DBUS_TYPE_STRING, &devname,
00398                                             DBUS_TYPE_INVALID)) {
00399             
00400             MSG_DEBUG("Remove('%s') called.", devname);
00401             g_assert(pdata->vols!=NULL);
00402             pdata->vols->remove_volume(pdata->vols, devname);
00403             dbus_free(devname);
00404         }
00405 
00406     
00407     
00408     
00409     } else if (dbus_message_is_signal(message, 
00410                                         DBUS_INTERFACE_MNT_TTY, 
00411                                         "Add")) {
00412         char *devname = NULL;
00413         DBusError error;
00414         dbus_error_init(&error);
00415         if (dbus_message_get_args(message, &error, 
00416                                             DBUS_TYPE_STRING, &devname,
00417                                             DBUS_TYPE_INVALID)) {
00418             MSG_DEBUG("Add('%s') called.", devname);
00419             dbus_free(devname);
00420         }
00421         
00422     } else if (dbus_message_is_signal(message, 
00423                                         DBUS_INTERFACE_MNT_TTY, 
00424                                         "Remove")) {
00425         char *devname = NULL;
00426         DBusError error;
00427         dbus_error_init(&error);
00428         if (dbus_message_get_args(message, &error, 
00429                                             DBUS_TYPE_STRING, &devname,
00430                                             DBUS_TYPE_INVALID)) {
00431             MSG_DEBUG("Remove('%s') called.", devname);
00432             dbus_free(devname);
00433         }
00434 
00435 #ifdef DEBUG
00436     } else {
00437         int type;
00438         type = dbus_message_get_type(message);
00439         switch(type) {
00440         case DBUS_MESSAGE_TYPE_METHOD_CALL:
00441             MSG_DEBUG("DBUS_MESSAGE_TYPE_METHOD_CALL");
00442             break;
00443         case DBUS_MESSAGE_TYPE_METHOD_RETURN:
00444             MSG_DEBUG("DBUS_MESSAGE_TYPE_METHOD_RETURN");
00445             break;
00446         case DBUS_MESSAGE_TYPE_ERROR:
00447             MSG_DEBUG("DBUS_MESSAGE_TYPE_ERROR");
00448             break;
00449         case DBUS_MESSAGE_TYPE_SIGNAL:
00450             MSG_DEBUG("DBUS_MESSAGE_TYPE_SIGNAL");
00451             break;
00452         case DBUS_MESSAGE_TYPE_INVALID:
00453             MSG_DEBUG("DBUS_MESSAGE_TYPE_INVALID");
00454             break;
00455         default:
00456             MSG_DEBUG("DBUS_MESSAGE_TYPE_ .... UNKNOWN");
00457             break;
00458         }
00459         
00460         MSG_DEBUG("obj_path=%s interface=%s method=%s destination=%s sender=%s", 
00461                     dbus_message_get_path(message), 
00462                     dbus_message_get_interface(message),
00463                     dbus_message_get_member(message),
00464                     dbus_message_get_destination(message),
00465                     dbus_message_get_sender(message)
00466         );
00467 #endif
00468         
00469     }
00470     
00471     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00472 }
00473 
00474 
00480 void 
00481 mntd_dbus_manager_send_signal_volume_mounted(PVOLUME pv)
00482 {
00483     DBusMessage* message;
00484     DBusMessageIter it;
00485     
00486     
00487 
00488     g_assert(pv!=NULL);
00489     
00490     message = dbus_message_new_signal(
00491                                             DBUS_PATH_MNT_MANAGER, 
00492                                             DBUS_INTERFACE_MNT_MANAGER,
00493                                             "VolumeMounted");
00494     if (message==NULL) {
00495         MSG_EMERG("Out of memory");
00496         return;
00497     }
00498     
00499     dbus_message_iter_init(message, &it);
00500     dbus_message_iter_append_string(&it, pv->udi);
00501     dbus_message_iter_append_string(&it, pv->mntpnt);
00502     
00503     if (!dbus_connection_send(dbus_connection, message, NULL)) {
00504         MSG_EMERG("error broadcasting message");
00505     }
00506     
00507     dbus_message_unref(message);
00508 }
00509 
00510 
00516 void 
00517 mntd_dbus_manager_send_signal_volume_unmounted(PVOLUME pv)
00518 {
00519     DBusMessage* message;
00520     DBusMessageIter it;
00521     
00522     
00523 
00524     g_assert(pv!=NULL);
00525 
00526     message = dbus_message_new_signal(
00527                                             DBUS_PATH_MNT_MANAGER, 
00528                                             DBUS_INTERFACE_MNT_MANAGER,
00529                                             "VolumeUnmounted");
00530     if (message==NULL) {
00531         MSG_EMERG("Out of memory");
00532         return;
00533     }
00534     
00535     dbus_message_iter_init(message, &it);
00536     dbus_message_iter_append_string(&it, pv->udi);
00537     dbus_message_iter_append_string(&it, pv->mntpnt);
00538     
00539     if (!dbus_connection_send(dbus_connection, message, NULL)) {
00540         MSG_EMERG("error broadcasting message");
00541     }
00542     
00543     dbus_message_unref(message);
00544 }
00545 
00546 
00553 int cb_append_udi(void *data, void *userdata)
00554 {
00555     DBusMessageIter *itarr = NULL;
00556     PHASHMAPELEMENT phme = NULL;
00557     PHASHMAP phm = NULL;
00558     PVOLUME pv = NULL;
00559     char *udi = NULL;
00560     void *hashdata = NULL;
00561 
00562     if ((data==NULL) || (userdata==NULL)) {
00563         return -1;
00564     }
00565     
00566     
00567     itarr = (DBusMessageIter *) userdata;
00568     
00569     phme = (PHASHMAPELEMENT) data;
00570     
00571     phm = phme->phm;
00572     
00573     udi = phme->key;
00574     
00575     if (phm->get(phm, udi, &hashdata) == 0) {
00576         pv = (PVOLUME) hashdata;
00577         if (pv != NULL) {
00578             
00579             if (pv->is_in_mntpath(pv)) {
00580                 
00581                 dbus_message_iter_append_string(itarr, udi);
00582                 return 0;
00583             }
00584         }
00585     }
00586 
00587     return -1;
00588 }
00589 
00590 
00602 DBusHandlerResult 
00603 mntd_dbus_manager_get_all_volumes(  PVOLUMEMANAGER pvm,
00604                                                 DBusConnection* connection,
00605                                                 DBusMessage* message)
00606 {
00607     DBusMessage* reply;
00608     DBusMessageIter it;
00609     DBusMessageIter itarr;
00610     DBusHandlerResult res = DBUS_HANDLER_RESULT_HANDLED;
00611     
00612     g_assert(pvm!=NULL);
00613 
00614     
00615     reply = dbus_message_new_method_return(message);
00616     if (reply==NULL) {
00617         MSG_EMERG("Out of memory");
00618         goto error;
00619     }
00620     
00621     
00622     dbus_message_iter_init(reply, &it);
00623     dbus_message_iter_append_array(&it, &itarr, DBUS_TYPE_STRING);
00624     pvm->foreach_mounted(pvm, cb_append_udi, &itarr);
00625     
00626     
00627     if(!dbus_connection_send(connection, reply, NULL)) {
00628         MSG_EMERG("Out of memory");
00629         goto error;
00630     }
00631     
00632     goto cleanup;
00633     
00634 error:
00635     res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00636     
00637 cleanup:
00638     if (reply!=NULL) {
00639         dbus_message_unref(reply);
00640     }
00641     
00642     return res;
00643 }
00644 
00645 
00657 DBusHandlerResult 
00658 mntd_dbus_manager_get_mntpnt(           PVOLUMEMANAGER pvm,
00659                                                 DBusConnection* connection,
00660                                                 DBusMessage* message)
00661 {
00662     DBusMessage *reply = NULL;
00663     DBusMessageIter it;
00664     DBusError error;
00665     DBusHandlerResult res = DBUS_HANDLER_RESULT_HANDLED;
00666     char *udi = NULL;
00667     char *mntpnt = NULL;
00668     
00669     g_assert(pvm!=NULL);
00670 
00671     
00672     dbus_error_init(&error);
00673     if (!dbus_message_get_args(message, &error, 
00674                                         DBUS_TYPE_STRING, &udi,
00675                                         DBUS_TYPE_INVALID) )
00676     {
00677         mntd_dbus_raise_syntax(connection, message, "Manager.GetMntPnt");
00678         goto error;
00679     }
00680     
00681     
00682     reply = dbus_message_new_method_return(message);
00683     if (reply==NULL) {
00684         MSG_EMERG("Out of memory");
00685         goto error;
00686     }
00687     
00688     
00689     dbus_message_iter_init(reply, &it);
00690     if (pvm->contains(pvm, udi)) {
00691         mntpnt = pvm->get_mntpnt(pvm, udi);
00692         if (mntpnt==NULL) {
00693             mntd_dbus_raise_no_mntpnt(connection, message, udi);
00694             goto error;
00695         }
00696         dbus_message_iter_append_string(&it, mntpnt);
00697     } else {
00698         mntd_dbus_raise_no_such_device(connection, message, udi);
00699         goto error;
00700     }
00701     
00702     
00703     if(!dbus_connection_send(connection, reply, NULL)) {
00704         MSG_EMERG("Out of memory");
00705         goto error;
00706     }
00707     
00708     goto cleanup;
00709     
00710 error:
00711     res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00712     
00713 cleanup:
00714     if (reply!=NULL) {
00715         dbus_message_unref(reply);
00716     }
00717     if (udi!=NULL) {
00718         dbus_free(udi);
00719     }
00720     if (mntpnt!=NULL) {
00721         free(mntpnt);
00722     }
00723     
00724     return res;
00725 }
00726 
00727 
00735 DBusHandlerResult 
00736 mntd_dbus_manager_remount(              PVOLUMEMANAGER pvm,
00737                                                 DBusConnection* connection,
00738                                                 DBusMessage* message)
00739 {
00740     DBusMessage *reply = NULL;
00741     DBusMessageIter it;
00742     DBusError error;
00743     DBusHandlerResult res = DBUS_HANDLER_RESULT_HANDLED;
00744     char *udi = NULL;
00745     int flag = 0;
00746     int ret = -1;
00747     
00748     g_assert(pvm!=NULL);
00749 
00750     
00751     dbus_error_init(&error);
00752     if (!dbus_message_get_args(message, &error, 
00753                                         DBUS_TYPE_STRING, &udi,
00754                                         DBUS_TYPE_INT32, &flag,
00755                                         DBUS_TYPE_INVALID) )
00756     {
00757         mntd_dbus_raise_syntax(connection, message, "Manager.Remount");
00758         goto error;
00759     }
00760     
00761     
00762     reply = dbus_message_new_method_return(message);
00763     if (reply==NULL) {
00764         MSG_EMERG("Out of memory");
00765         goto error;
00766     }
00767     
00768     
00769     dbus_message_iter_init(reply, &it);
00770     if (pvm->contains(pvm, udi)) {
00771         ret = pvm->remount(pvm, udi, flag);
00772         if (ret == -1) {
00773             mntd_dbus_raise_no_mntpnt(connection, message, udi);
00774             goto error;
00775         }
00776         dbus_message_iter_append_int32(&it, ret);
00777     } else {
00778         mntd_dbus_raise_no_such_device(connection, message, udi);
00779         goto error;
00780     }
00781     
00782     
00783     if(!dbus_connection_send(connection, reply, NULL)) {
00784         MSG_EMERG("Out of memory");
00785         goto error;
00786     }
00787     
00788     goto cleanup;
00789     
00790 error:
00791     res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00792     
00793 cleanup:
00794     if (reply!=NULL) {
00795         dbus_message_unref(reply);
00796     }
00797     if (udi!=NULL) {
00798         dbus_free(udi);
00799     }
00800     
00801     return res;
00802 }
00803 
00804 
00808 
00809 
00810 
00811