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 <glib.h>
00034 #include <dbus/dbus.h>
00035 #include <dbus/dbus-glib.h>
00036
00037 #include <libmnt/libmnt.h>
00038 #include "mntd_dir.h"
00039 #include "mntd_mount.h"
00040 #include "mntd_volume.h"
00041 #include "mntd_dbus_manager.h"
00042 #include "errmanager.h"
00043
00044
00045
00046 int mntd_volume_init(PVOLUME pv);
00047 void mntd_volume_destroy(PVOLUME pv);
00048 int mntd_volume_set_device(PVOLUME pv, const char *device);
00049 char *mntd_volume_get_device(PVOLUME pv);
00050 void mntd_volume_to_string(PVOLUME pv);
00051 int mntd_volume_set_mntpnt(PVOLUME pv, const char *mntpnt);
00052 char *mntd_volume_get_mntpnt(PVOLUME pv);
00053 int mntd_volume_set_fstype(PVOLUME pv, const char *fstype);
00054 char *mntd_volume_get_fstype(PVOLUME pv);
00055 int mntd_volume_mount(PVOLUME pv);
00056 int mntd_volume_umount(PVOLUME pv);
00057 char *mntd_volume_g_build_mntpnt(PVOLUME pv, const char *base);
00058 int mntd_volume_helper_base_is_in_mntpath(const char *base, const char *mntpnt);
00059 int mntd_volume_is_in_mntpath(PVOLUME pv);
00060 int mntd_volume_send_signal(PVOLUME pv, int what);
00061 int mntd_volume_send_mounted(PVOLUME pv);
00062 int mntd_volume_send_unmounted(PVOLUME pv);
00063
00064
00080 PVOLUME new_Volume(const char *udi, const char *base)
00081 {
00082 PVOLUME pv = NULL;
00083 char *s_udi = NULL;
00084 char *s_base = NULL;
00085
00086
00087
00088 g_assert(udi!=NULL);
00089 g_assert(base!=NULL);
00090
00091
00092 pv = (PVOLUME) malloc(sizeof(VOLUME));
00093 if (pv==NULL) {
00094 return NULL;
00095 }
00096
00097
00098 memset(pv, 0, sizeof(VOLUME));
00099
00100
00101 s_udi = strdup(udi);
00102 if (s_udi == NULL) {
00103 goto error;
00104 }
00105 pv->udi = s_udi;
00106
00107
00108 s_base = strdup(base);
00109 if (s_base == NULL) {
00110 goto error;
00111 }
00112 pv->base = s_base;
00113
00114
00115 pv->init = mntd_volume_init;
00116 pv->_send_signal = mntd_volume_send_signal;
00117 pv->_send_mounted = mntd_volume_send_mounted;
00118 pv->_send_unmounted = mntd_volume_send_unmounted;
00119 pv->destroy = mntd_volume_destroy;
00120 pv->set_device = mntd_volume_set_device;
00121 pv->get_device = mntd_volume_get_device;
00122 pv->to_string = mntd_volume_to_string;
00123 pv->set_mntpnt = mntd_volume_set_mntpnt;
00124 pv->get_mntpnt = mntd_volume_get_mntpnt;
00125 pv->set_fstype = mntd_volume_set_fstype;
00126 pv->get_fstype = mntd_volume_get_fstype;
00127 pv->mount = mntd_volume_mount;
00128 pv->umount = mntd_volume_umount;
00129 pv->is_in_mntpath = mntd_volume_is_in_mntpath;
00130
00131
00132 if(pv->init(pv) == -1) {
00133 goto error;
00134 }
00135
00136
00137 goto exit;
00138
00139 error:
00140 pv->destroy(pv);
00141 pv = NULL;
00142
00143 exit:
00144 return pv;
00145 }
00146
00147
00154 int mntd_volume_init(PVOLUME pv)
00155 {
00156 g_assert(pv!=NULL);
00157
00158
00159
00160 pv->device = NULL;
00161 pv->mntpnt = NULL;
00162 pv->fstype = NULL;
00163 pv->last_signal = SIGNAL_UNKNOWN;
00164
00165 return 0;
00166 }
00167
00168
00173 void mntd_volume_destroy(PVOLUME pv)
00174 {
00175 g_assert(pv!=NULL);
00176
00177
00178
00179
00180 pv->umount(pv);
00181
00182
00183 if (pv->udi != NULL) {
00184 free(pv->udi);
00185 pv->udi = NULL;
00186 }
00187
00188
00189 if (pv->base != NULL) {
00190 free(pv->base);
00191 pv->base = NULL;
00192 }
00193
00194
00195 if (pv->device != NULL) {
00196 free(pv->device);
00197 pv->device = NULL;
00198 }
00199
00200
00201 if (pv->mntpnt != NULL) {
00202 free(pv->mntpnt);
00203 pv->mntpnt = NULL;
00204 }
00205
00206
00207 if (pv->fstype != NULL) {
00208 free(pv->fstype);
00209 pv->fstype = NULL;
00210 }
00211
00212
00213 memset(pv, 0, sizeof(VOLUME));
00214 free(pv);
00215
00216 return;
00217 }
00218
00219
00225 void
00226 mntd_volume_to_string(PVOLUME pv)
00227 {
00228
00229
00230 MSG_DEBUG("------------------------------------------------------");
00231 MSG_DEBUG("udi: %s", pv->udi);
00232 MSG_DEBUG("base: %s", pv->base);
00233 MSG_DEBUG("device: %s", pv->device);
00234 MSG_DEBUG("mntpnt: %s", pv->mntpnt);
00235 MSG_DEBUG("fstype: %s", pv->fstype);
00236
00237 return;
00238 }
00239
00240
00248 int
00249 mntd_volume_set_device(PVOLUME pv, const char *device)
00250 {
00251 char *s_device = NULL;
00252
00253
00254
00255 g_assert(pv!=NULL);
00256
00257 if (device == NULL) {
00258 if (pv->device != NULL) {
00259 free(pv->device);
00260 pv->device = NULL;
00261 }
00262 return 0;
00263 }
00264
00265
00266 if (pv->device != NULL) {
00267 if (strcmp(device, pv->device)==0) {
00268 return 0;
00269 }
00270 }
00271
00272 s_device = strdup(device);
00273 if (s_device == NULL) {
00274 return -1;
00275 }
00276
00277 if (pv->device != NULL) {
00278 free(pv->device);
00279 pv->device = NULL;
00280 }
00281
00282 pv->device = s_device;
00283
00284 MSG_DEBUG("Set device to '%s' for '%s'", s_device, pv->udi);
00285
00286
00287 pv->mount(pv);
00288
00289 return 0;
00290 }
00291
00292
00302 char *
00303 mntd_volume_get_device(PVOLUME pv)
00304 {
00305 g_assert(pv!=NULL);
00306
00307 if (pv->device != NULL) {
00308 return strdup(pv->device);
00309 }
00310
00311 return NULL;
00312 }
00313
00314
00322 int
00323 mntd_volume_set_mntpnt(PVOLUME pv, const char *mntpnt)
00324 {
00325 char *s_mntpnt = NULL;
00326
00327
00328
00329 g_assert(pv!=NULL);
00330
00331 if (mntpnt == NULL) {
00332 if (pv->mntpnt != NULL) {
00333
00334 MSG_DEBUG("Remove mount point '%s' ('%s')", pv->mntpnt, pv->udi);
00335
00336
00337 pv->_send_signal(pv, SIGNAL_UNMOUNTED);
00338
00339 free(pv->mntpnt);
00340 pv->mntpnt = NULL;
00341 }
00342 return 0;
00343 }
00344
00345
00346 if (pv->mntpnt != NULL) {
00347 if (strcmp(mntpnt, pv->mntpnt)==0) {
00348 return 0;
00349 }
00350 }
00351
00352 s_mntpnt = strdup(mntpnt);
00353 if (s_mntpnt == NULL) {
00354 return -1;
00355 }
00356
00357 if (pv->mntpnt != NULL) {
00358
00359 MSG_DEBUG("Change mount point '%s' ('%s')", pv->mntpnt, pv->udi);
00360
00361 free(pv->mntpnt);
00362 pv->mntpnt = NULL;
00363 }
00364
00365 pv->mntpnt = s_mntpnt;
00366
00367 MSG_DEBUG("Set mount point to '%s' ('%s')", s_mntpnt, pv->udi);
00368
00369
00370 pv->_send_signal(pv, SIGNAL_UNKNOWN);
00371
00372 return 0;
00373 }
00374
00375
00385 char *
00386 mntd_volume_get_mntpnt(PVOLUME pv)
00387 {
00388 g_assert(pv!=NULL);
00389
00390 if (pv->mntpnt != NULL) {
00391 return strdup(pv->mntpnt);
00392 }
00393
00394 return NULL;
00395 }
00396
00397
00405 int
00406 mntd_volume_set_fstype(PVOLUME pv, const char *fstype)
00407 {
00408 char *s_fstype = NULL;
00409
00410
00411
00412 g_assert(pv!=NULL);
00413
00414 if (fstype == NULL) {
00415 if (pv->fstype != NULL) {
00416 free(pv->fstype);
00417 pv->fstype = NULL;
00418 }
00419 return 0;
00420 }
00421
00422
00423 if (pv->fstype != NULL) {
00424 if (strcmp(fstype, pv->fstype)==0) {
00425 return 0;
00426 }
00427 }
00428
00429 s_fstype = strdup(fstype);
00430 if (s_fstype == NULL) {
00431 return -1;
00432 }
00433
00434 if (pv->fstype != NULL) {
00435 free(pv->fstype);
00436 pv->fstype = NULL;
00437 }
00438
00439 pv->fstype = s_fstype;
00440
00441
00442
00443 return 0;
00444 }
00445
00446
00456 char *
00457 mntd_volume_get_fstype(PVOLUME pv)
00458 {
00459 g_assert(pv!=NULL);
00460
00461 if (pv->fstype != NULL) {
00462 return strdup(pv->fstype);
00463 }
00464
00465 return NULL;
00466 }
00467
00468
00475 int
00476 mntd_volume_mount(PVOLUME pv)
00477 {
00478 char *path = NULL;
00479 int error=0;
00480 int res = 0;
00481
00482
00483
00484 g_assert(pv!=NULL);
00485 g_assert(pv->device!=NULL);
00486
00487
00488 if (pv->base == NULL) {
00489 MSG_ERR("base mountpoint path is not configured");
00490 goto error;
00491 }
00492
00493
00494 if (pv->mntpnt != NULL) {
00495 MSG_INF("'%s' already mounted on '%s'.", pv->device, pv->mntpnt);
00496 goto error;
00497 }
00498
00499
00500 path = mntd_volume_g_build_mntpnt(pv, pv->base);
00501 if (path == NULL) {
00502 MSG_ERR("Out of memory");
00503 goto error;
00504 }
00505
00506
00507 mntd_dir_rmdirs(path);
00508 mntd_dir_mkdirs(path, 0664, &error);
00509 if (!mntd_dir_is_dir(path)) {
00510 MSG_ERR("Couldn't create '%s' (%d)", path, error);
00511 goto error;
00512 }
00513
00514
00515 res = mntd_mount_mount("-o ro", pv->device, path);
00516 if (res != 0) {
00517 MSG_INF("Couldn't mount '%s' on '%s'. Perhaps wrong filesystem, or no filesystem on it (e.g. extended partition, ...).", pv->device, path);
00518
00519 goto error;
00520 }
00521
00522
00523 pv->set_mntpnt(pv, path);
00524
00525
00526 ;
00527
00528 MSG_INF("Mounted '%s' on '%s'.", pv->device, path);
00529
00530
00531 pv->_send_signal(pv, SIGNAL_MOUNTED);
00532
00533 goto cleanup;
00534
00535 error:
00536
00537 mntd_dir_remove(path);
00538
00539 res = -1;
00540
00541 cleanup:
00542 if (path != NULL) {
00543 free(path);
00544 path = NULL;
00545 }
00546
00547 return res;
00548 }
00549
00550
00562 int
00563 mntd_volume_umount(PVOLUME pv)
00564 {
00565 int res = 0;
00566 char *mntpnt = NULL;
00567 int status = 0;
00568
00569
00570
00571 g_assert(pv!=NULL);
00572
00573
00574 if (pv->is_in_mntpath(pv)) {
00575
00576 if (pv->mntpnt != NULL) {
00577 mntpnt = pv->get_mntpnt(pv);
00578 if (mntpnt != NULL) {
00579
00580 status = mntd_mount_umount("", mntpnt);
00581 if (status != 0) {
00582 MSG_ERR("Couldn't unmount '%s' on '%s'.", pv->device, mntpnt);
00583 goto error;
00584 } else {
00585 MSG_INF("Unmounted '%s' on '%s'.", pv->device, mntpnt);
00586
00587
00588 pv->_send_signal(pv, SIGNAL_UNMOUNTED);
00589 }
00590
00591
00592 mntd_dir_remove(mntpnt);
00593
00594
00595 pv->set_mntpnt(pv, NULL);
00596 pv->set_fstype(pv, NULL);
00597
00598 } else {
00599 MSG_ERR("mntpnt==NULL for '%s' on '%s'", pv->device, pv->udi);
00600 goto error;
00601 }
00602 } else {
00603 MSG_ERR("Volume (udi='%s') on device '%s' mounted by mntd has mntpnt==NULL !", pv->udi, pv->device);
00604 goto error;
00605 }
00606 } else {
00607 MSG_INF("Device '%s' at '%s' is not mounted by mntd -> do not unmount it.", pv->device, pv->mntpnt);
00608 goto error;
00609 }
00610
00611 goto cleanup;
00612
00613 error:
00614 res = -1;
00615
00616 cleanup:
00617 if (mntpnt != NULL) {
00618 free(mntpnt);
00619 mntpnt = NULL;
00620 }
00621
00622 return res;
00623 }
00624
00625
00633 char *
00634 mntd_volume_g_build_mntpnt(PVOLUME pv, const char *base)
00635 {
00636 gchar *res = NULL;
00637 gchar *name = NULL;
00638
00639 g_assert(pv!=NULL);
00640 g_assert(base!=NULL);
00641
00642 if (pv->device == NULL) {
00643 goto error;
00644 }
00645
00646 name = g_path_get_basename(pv->device);
00647 if(name==NULL) {
00648 goto error;
00649 }
00650
00651 if (g_path_is_absolute((gchar *)base)) {
00652 res = g_build_path(G_DIR_SEPARATOR_S, (gchar *)base, name, NULL);
00653 } else {
00654 MSG_WARNING("basepath for mount point have to be absolute (adding DIRSEP) -> check your config");
00655 res = g_build_path(G_DIR_SEPARATOR_S, G_DIR_SEPARATOR_S, (gchar *)base, name, NULL);
00656 }
00657 if (res==NULL) {
00658 goto error;
00659 }
00660
00661 goto cleanup;
00662
00663 error:
00664 res = NULL;
00665
00666 cleanup:
00667 if (name!=NULL) {
00668 g_free(name);
00669 name = NULL;
00670 }
00671
00672 return (char *)res;
00673 }
00674
00675
00683 int
00684 mntd_volume_helper_base_is_in_mntpath(const char *base, const char *mntpnt)
00685 {
00686 int res = TRUE;
00687 int abs_base = 0;
00688 int abs_mntpnt = 0;
00689 gchar *path_base = NULL;
00690 gchar *path_mntpnt = NULL;
00691
00692 g_assert(base!=NULL);
00693 g_assert(mntpnt!=NULL);
00694
00695
00696 abs_base = g_path_is_absolute((gchar *)base);
00697 abs_mntpnt = g_path_is_absolute((gchar *)mntpnt);
00698 if (abs_base != abs_mntpnt) {
00699 goto no;
00700 }
00701
00702
00703 path_base = g_build_path(G_DIR_SEPARATOR_S, (gchar *)base, NULL);
00704 if (path_base == NULL) {
00705 goto no;
00706 }
00707 path_mntpnt = g_build_path(G_DIR_SEPARATOR_S, (gchar *)mntpnt, NULL);
00708 if (path_mntpnt == NULL) {
00709 goto no;
00710 }
00711 if (!g_str_has_prefix(path_mntpnt, path_base)) {
00712 goto no;
00713 }
00714
00715 goto cleanup;
00716
00717 no:
00718 res = FALSE;
00719
00720 cleanup:
00721 if (path_base != NULL) {
00722 g_free(path_base);
00723 path_base = NULL;
00724 }
00725 if (path_mntpnt != NULL) {
00726 g_free(path_mntpnt);
00727 path_mntpnt = NULL;
00728 }
00729
00730
00731 return res;
00732 }
00733
00734
00741 int
00742 mntd_volume_is_in_mntpath(PVOLUME pv)
00743 {
00744 g_assert(pv!=NULL);
00745
00746 if ((pv->mntpnt==NULL) || (pv->base==NULL)) {
00747 return FALSE;
00748 }
00749
00750 return mntd_volume_helper_base_is_in_mntpath(pv->base, pv->mntpnt);
00751 }
00752
00753
00760 int
00761 mntd_volume_send_mounted(PVOLUME pv)
00762 {
00763 g_assert(pv!=NULL);
00764 g_assert(pv->udi!=NULL);
00765 g_assert(pv->mntpnt!=NULL);
00766
00767 if (pv->last_signal!=SIGNAL_MOUNTED) {
00768 pv->last_signal = SIGNAL_MOUNTED;
00769 MSG_DEBUG("sending 'mounted' signal for '%s' ('%s') ...", pv->mntpnt, pv->udi);
00770 mntd_dbus_manager_send_signal_volume_mounted(pv);
00771 }
00772
00773 return TRUE;
00774 }
00775
00776
00783 int
00784 mntd_volume_send_unmounted(PVOLUME pv)
00785 {
00786 g_assert(pv!=NULL);
00787 g_assert(pv->udi!=NULL);
00788 g_assert(pv->mntpnt!=NULL);
00789
00790 if (pv->last_signal!=SIGNAL_UNMOUNTED) {
00791 pv->last_signal = SIGNAL_UNMOUNTED;
00792 MSG_DEBUG("sending 'unmounted' signal for '%s' ('%s') ...", pv->mntpnt, pv->udi);
00793 mntd_dbus_manager_send_signal_volume_unmounted(pv);
00794 }
00795
00796 return TRUE;
00797 }
00798
00799
00809 int
00810 mntd_volume_send_signal(PVOLUME pv, int what)
00811 {
00812 g_assert(pv!=NULL);
00813 g_assert(pv->udi!=NULL);
00814
00815
00816 if (what==SIGNAL_MOUNTED) {
00817 pv->_send_mounted(pv);
00818
00819
00820 } else if (what==SIGNAL_UNMOUNTED) {
00821 pv->_send_unmounted(pv);
00822
00823
00824 } else {
00825 if (pv->is_in_mntpath(pv)) {
00826 if (pv->mntpnt!=NULL) {
00827 pv->_send_mounted(pv);
00828 } else {
00829 pv->_send_unmounted(pv);
00830 }
00831 }
00832 }
00833
00834 return TRUE;
00835 }
00836
00837