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 #include <limits.h>
00037
00038 #include <libmnt/libmnt.h>
00039 #include "dir.h"
00040 #include "main.h"
00041 #include "mntd_mount.h"
00042 #include "mntd_volume.h"
00043 #include "mntd_volume_config.h"
00044 #include "mntd_dbus_manager.h"
00045 #include "errmanager.h"
00046 #include "dbug_mem.h"
00047
00048
00049
00050 int mntd_volume_init(PVOLUME pv);
00051 void mntd_volume_destroy(PVOLUME pv);
00052 int mntd_volume_set_device(PVOLUME pv, const char *device);
00053 char *mntd_volume_get_device(PVOLUME pv);
00054 void mntd_volume_to_string(PVOLUME pv);
00055 int mntd_volume_set_mntpnt(PVOLUME pv, const char *mntpnt);
00056 char *mntd_volume_get_mntpnt(PVOLUME pv);
00057 int mntd_volume_set_fstype(PVOLUME pv, const char *fstype);
00058 char *mntd_volume_get_fstype(PVOLUME pv);
00059 int mntd_volume_mount(PVOLUME pv);
00060 int mntd_volume_umount(PVOLUME pv);
00061 char *mntd_volume_g_build_mntpnt(PVOLUME pv, const char *base, const char *prefix);
00062 int mntd_volume_helper_base_is_in_mntpath(const char *base, const char *mntpnt);
00063 int mntd_volume_is_in_mntpath(PVOLUME pv);
00064 int mntd_volume_send_signal(PVOLUME pv, int what);
00065 int mntd_volume_send_mounted(PVOLUME pv);
00066 int mntd_volume_send_unmounted(PVOLUME pv);
00067 int mntd_volume_remount(PVOLUME pv, int flag);
00068
00069
00086 PVOLUME new_Volume(const char *udi, const char *base, const char *prefix)
00087 {
00088 PVOLUME pv = NULL;
00089 char *s_udi = NULL;
00090 char *s_base = NULL;
00091 char *s_prefix = NULL;
00092
00093
00094
00095 g_assert(udi!=NULL);
00096 g_assert(base!=NULL);
00097 g_assert(prefix!=NULL);
00098
00099
00100 pv = (PVOLUME) malloc(sizeof(VOLUME));
00101 if (pv==NULL) {
00102 return NULL;
00103 }
00104
00105
00106 memset(pv, 0, sizeof(VOLUME));
00107
00108
00109 s_udi = strdup(udi);
00110 if (s_udi == NULL) {
00111 goto error;
00112 }
00113 pv->udi = s_udi;
00114
00115
00116 s_base = strdup(base);
00117 if (s_base == NULL) {
00118 goto error;
00119 }
00120 pv->base = s_base;
00121
00122
00123 s_prefix = strdup(prefix);
00124 if (s_prefix == NULL) {
00125 goto error;
00126 }
00127 pv->prefix = s_prefix;
00128
00129
00130 pv->init = mntd_volume_init;
00131 pv->_send_signal = mntd_volume_send_signal;
00132 pv->_send_mounted = mntd_volume_send_mounted;
00133 pv->_send_unmounted = mntd_volume_send_unmounted;
00134 pv->destroy = mntd_volume_destroy;
00135 pv->set_device = mntd_volume_set_device;
00136 pv->get_device = mntd_volume_get_device;
00137 pv->to_string = mntd_volume_to_string;
00138 pv->set_mntpnt = mntd_volume_set_mntpnt;
00139 pv->get_mntpnt = mntd_volume_get_mntpnt;
00140 pv->set_fstype = mntd_volume_set_fstype;
00141 pv->get_fstype = mntd_volume_get_fstype;
00142 pv->mount = mntd_volume_mount;
00143 pv->umount = mntd_volume_umount;
00144 pv->remount = mntd_volume_remount;
00145 pv->is_in_mntpath = mntd_volume_is_in_mntpath;
00146
00147
00148 if(pv->init(pv) == -1) {
00149 goto error;
00150 }
00151
00152
00153 goto exit;
00154
00155 error:
00156 pv->destroy(pv);
00157 pv = NULL;
00158
00159 exit:
00160 return pv;
00161 }
00162
00163
00170 int mntd_volume_init(PVOLUME pv)
00171 {
00172 g_assert(pv!=NULL);
00173
00174
00175
00176 pv->device = NULL;
00177 pv->mntpnt = NULL;
00178 pv->fstype = NULL;
00179 pv->last_signal = SIGNAL_UNKNOWN;
00180
00181 return 0;
00182 }
00183
00184
00189 void mntd_volume_destroy(PVOLUME pv)
00190 {
00191 g_assert(pv!=NULL);
00192
00193
00194
00195
00196 if (pmd->configdata->umount_on_exit == UMOUNT_ON_EXIT_FALSE) {
00197
00198 } else if (pmd->configdata->umount_on_exit == UMOUNT_ON_EXIT_READONLY) {
00199
00200 pv->remount(pv, MOUNT_RD);
00201 } else {
00202
00203 pv->umount(pv);
00204 }
00205
00206
00207 if (pv->udi != NULL) {
00208 free(pv->udi);
00209 pv->udi = NULL;
00210 }
00211
00212
00213 if (pv->base != NULL) {
00214 free(pv->base);
00215 pv->base = NULL;
00216 }
00217
00218
00219 if (pv->prefix != NULL) {
00220 free(pv->prefix);
00221 pv->prefix = NULL;
00222 }
00223
00224
00225 if (pv->device != NULL) {
00226 free(pv->device);
00227 pv->device = NULL;
00228 }
00229
00230
00231 if (pv->mntpnt != NULL) {
00232 free(pv->mntpnt);
00233 pv->mntpnt = NULL;
00234 }
00235
00236
00237 if (pv->fstype != NULL) {
00238 free(pv->fstype);
00239 pv->fstype = NULL;
00240 }
00241
00242
00243 memset(pv, 0, sizeof(VOLUME));
00244 free(pv);
00245
00246 return;
00247 }
00248
00249
00254 void
00255 mntd_volume_to_string(PVOLUME pv)
00256 {
00257
00258
00259 MSG_DEBUG("------------------------------------------------------");
00260 MSG_DEBUG("udi: %s", pv->udi);
00261 MSG_DEBUG("base: %s", pv->base);
00262 MSG_DEBUG("prefix: %s", pv->prefix);
00263 MSG_DEBUG("device: %s", pv->device);
00264 MSG_DEBUG("mntpnt: %s", pv->mntpnt);
00265 MSG_DEBUG("fstype: %s", pv->fstype);
00266
00267 return;
00268 }
00269
00270
00277 int
00278 mntd_volume_set_device(PVOLUME pv, const char *device)
00279 {
00280 char *s_device = NULL;
00281
00282
00283
00284 g_assert(pv!=NULL);
00285
00286 if (device == NULL) {
00287 if (pv->device != NULL) {
00288 free(pv->device);
00289 pv->device = NULL;
00290 }
00291 return 0;
00292 }
00293
00294
00295 if (pv->device != NULL) {
00296 if (strcmp(device, pv->device)==0) {
00297 return 0;
00298 }
00299 }
00300
00301 s_device = strdup(device);
00302 if (s_device == NULL) {
00303 return -1;
00304 }
00305
00306 if (pv->device != NULL) {
00307 free(pv->device);
00308 pv->device = NULL;
00309 }
00310
00311 pv->device = s_device;
00312
00313 MSG_DEBUG("Set device to '%s' for udi '%s'", s_device, pv->udi);
00314
00315
00316 pv->mount(pv);
00317
00318 return 0;
00319 }
00320
00321
00330 char *
00331 mntd_volume_get_device(PVOLUME pv)
00332 {
00333 g_assert(pv!=NULL);
00334
00335 if (pv->device != NULL) {
00336 return strdup(pv->device);
00337 }
00338
00339 return NULL;
00340 }
00341
00342
00349 int
00350 mntd_volume_set_mntpnt(PVOLUME pv, const char *mntpnt)
00351 {
00352 char *s_mntpnt = NULL;
00353
00354
00355
00356 g_assert(pv!=NULL);
00357
00358 if (mntpnt == NULL) {
00359 if (pv->mntpnt != NULL) {
00360
00361 MSG_DEBUG("Remove mount point '%s' ('%s')", pv->mntpnt, pv->udi);
00362
00363
00364 pv->_send_signal(pv, SIGNAL_UNMOUNTED);
00365
00366 free(pv->mntpnt);
00367 pv->mntpnt = NULL;
00368 }
00369 return 0;
00370 }
00371
00372
00373 if (pv->mntpnt != NULL) {
00374 if (strcmp(mntpnt, pv->mntpnt)==0) {
00375 return 0;
00376 }
00377 }
00378
00379 s_mntpnt = strdup(mntpnt);
00380 if (s_mntpnt == NULL) {
00381 return -1;
00382 }
00383
00384 if (pv->mntpnt != NULL) {
00385
00386 MSG_DEBUG("Change mount point '%s' ('%s')", pv->mntpnt, pv->udi);
00387
00388 free(pv->mntpnt);
00389 pv->mntpnt = NULL;
00390 }
00391
00392 pv->mntpnt = s_mntpnt;
00393
00394 MSG_DEBUG("Set mount point to '%s' ('%s')", s_mntpnt, pv->udi);
00395
00396
00397 pv->_send_signal(pv, SIGNAL_UNKNOWN);
00398
00399 return 0;
00400 }
00401
00402
00411 char *
00412 mntd_volume_get_mntpnt(PVOLUME pv)
00413 {
00414 g_assert(pv!=NULL);
00415
00416 if (pv->mntpnt != NULL) {
00417 return strdup(pv->mntpnt);
00418 }
00419
00420 return NULL;
00421 }
00422
00423
00430 int
00431 mntd_volume_set_fstype(PVOLUME pv, const char *fstype)
00432 {
00433 char *s_fstype = NULL;
00434
00435
00436
00437 g_assert(pv!=NULL);
00438
00439 if (fstype == NULL) {
00440 if (pv->fstype != NULL) {
00441 free(pv->fstype);
00442 pv->fstype = NULL;
00443 }
00444 return 0;
00445 }
00446
00447
00448 if (pv->fstype != NULL) {
00449 if (strcmp(fstype, pv->fstype)==0) {
00450 return 0;
00451 }
00452 }
00453
00454 s_fstype = strdup(fstype);
00455 if (s_fstype == NULL) {
00456 return -1;
00457 }
00458
00459 if (pv->fstype != NULL) {
00460 free(pv->fstype);
00461 pv->fstype = NULL;
00462 }
00463
00464 pv->fstype = s_fstype;
00465
00466
00467
00468 return 0;
00469 }
00470
00471
00480 char *
00481 mntd_volume_get_fstype(PVOLUME pv)
00482 {
00483 g_assert(pv!=NULL);
00484
00485 if (pv->fstype != NULL) {
00486 return strdup(pv->fstype);
00487 }
00488
00489 return NULL;
00490 }
00491
00492
00498 int
00499 mntd_volume_mount(PVOLUME pv)
00500 {
00501 char *path = NULL;
00502 int error=0;
00503 int res = 0;
00504
00505
00506
00507 g_assert(pv!=NULL);
00508 g_assert(pv->device!=NULL);
00509 g_assert(pv->base!=NULL);
00510 g_assert(pv->prefix!=NULL);
00511
00512
00513 if (pv->base == NULL) {
00514 MSG_ERR("base mountpoint path is not configured");
00515 goto error;
00516 }
00517
00518
00519 if (pv->mntpnt != NULL) {
00520 MSG_INF("'%s' already mounted on '%s'.", pv->device, pv->mntpnt);
00521 goto error;
00522 }
00523
00524
00525 path = mntd_volume_g_build_mntpnt(pv, pv->base, pv->prefix);
00526 if (path == NULL) {
00527 MSG_ERR("Out of memory");
00528 goto error;
00529 }
00530
00531
00532 sb_dir_rmdirs(path);
00533 sb_dir_mkdirs(path, 0775, &error);
00534 if (!sb_dir_is_dir(path)) {
00535 MSG_ERR("Couldn't create '%s' (%d)", path, error);
00536 goto error;
00537 }
00538
00539
00540 res = mntd_mount_mount(pv->device, path);
00541 if (res != 0) {
00542 MSG_INF("Couldn't mount '%s' on '%s'. Perhaps wrong filesystem, or no filesystem on it (e.g. extended partition, ...).", pv->device, path);
00543
00544 goto error;
00545 }
00546
00547
00548 pv->set_mntpnt(pv, path);
00549
00550
00551 ;
00552
00553 MSG_INF("Mounted '%s' on '%s'.", pv->device, path);
00554
00555
00556 pv->_send_signal(pv, SIGNAL_MOUNTED);
00557
00558 goto cleanup;
00559
00560 error:
00561
00562 sb_dir_remove(path);
00563
00564 res = -1;
00565
00566 cleanup:
00567 if (path != NULL) {
00568 g_free(path);
00569 path = NULL;
00570 }
00571
00572 return res;
00573 }
00574
00575
00586 int
00587 mntd_volume_umount(PVOLUME pv)
00588 {
00589 int res = 0;
00590 char *mntpnt = NULL;
00591 int status = 0;
00592
00593
00594
00595 g_assert(pv!=NULL);
00596
00597
00598 if (pv->is_in_mntpath(pv)) {
00599
00600 if (pv->mntpnt != NULL) {
00601 mntpnt = pv->get_mntpnt(pv);
00602 if (mntpnt != NULL) {
00603
00604 status = mntd_mount_umount(mntpnt);
00605 if (status != 0) {
00606 MSG_ERR("Couldn't unmount '%s' on '%s'.", pv->device, mntpnt);
00607 goto error;
00608 } else {
00609 MSG_INF("Unmounted '%s' on '%s'.", pv->device, mntpnt);
00610
00611
00612 pv->_send_signal(pv, SIGNAL_UNMOUNTED);
00613 }
00614
00615
00616 sb_dir_remove(mntpnt);
00617
00618
00619 pv->set_mntpnt(pv, NULL);
00620 pv->set_fstype(pv, NULL);
00621
00622 } else {
00623 MSG_ERR("mntpnt==NULL for '%s' on '%s'", pv->device, pv->udi);
00624 goto error;
00625 }
00626 } else {
00627 MSG_ERR("Volume (udi='%s') on device '%s' mounted by mntd has mntpnt==NULL !", pv->udi, pv->device);
00628 goto error;
00629 }
00630 } else {
00631
00632 goto error;
00633 }
00634
00635 goto cleanup;
00636
00637 error:
00638 res = -1;
00639
00640 cleanup:
00641 if (mntpnt != NULL) {
00642 free(mntpnt);
00643 mntpnt = NULL;
00644 }
00645
00646 return res;
00647 }
00648
00649
00656 int
00657 mntd_volume_remount(PVOLUME pv, int flag)
00658 {
00659 int res = -1;
00660
00661 g_assert(pv!=NULL);
00662
00663 if (pv->mntpnt != NULL) {
00664 if (flag==MOUNT_RW) {
00665 res = mntd_mount_remount_rw(pv->mntpnt);
00666 } else {
00667 res = mntd_mount_remount_rd(pv->mntpnt);
00668 }
00669 }
00670
00671 return res;
00672 }
00673
00674
00683 gchar *
00684 mntd_volume_g_build_mntpnt(PVOLUME pv, const char *base, const char *prefix)
00685 {
00686 gchar *res = NULL;
00687 char *name = NULL;
00688 unsigned int counter = 0;
00689 int maxchars = 0;
00690 gchar *longname = NULL;
00691 gchar **tokens = NULL;
00692
00693 g_assert(pv!=NULL);
00694 g_assert(base!=NULL);
00695 g_assert(prefix!=NULL);
00696
00697 if (pv->device == NULL) {
00698 goto error;
00699 }
00700
00701 if (prefix==NULL || (prefix!=NULL && strlen(prefix)==0))
00702 {
00703
00704 tokens = g_strsplit(pv->device, G_DIR_SEPARATOR_S, 0);
00705 if (tokens==NULL) {
00706 goto error;
00707 }
00708 longname = g_strjoinv("_", tokens);
00709 if (longname==NULL) {
00710 goto error;
00711 }
00712 if (g_path_is_absolute((gchar *)base)) {
00713 res = g_build_path(G_DIR_SEPARATOR_S, (gchar *)base, longname, NULL);
00714 } else {
00715 MSG_WARNING("basepath for mount point have to be absolute (adding DIRSEP) -> check your config");
00716 res = g_build_path(G_DIR_SEPARATOR_S, G_DIR_SEPARATOR_S,
00717 (gchar *)base, longname, NULL);
00718 }
00719 if (res==NULL) {
00720 goto error;
00721 }
00722
00723 } else {
00724
00725 maxchars = strlen(prefix)+20;
00726 name = (char *) malloc(sizeof(char)*maxchars);
00727 if (name == NULL) {
00728 goto error;
00729 }
00730
00731
00732 for (counter = 0; counter <= UINT_MAX; counter++) {
00733
00734 memset(name, 0, maxchars);
00735 snprintf(name, maxchars-1, "%s%d", prefix, counter);
00736 if (g_path_is_absolute((gchar *)base)) {
00737 res = g_build_path(G_DIR_SEPARATOR_S, (gchar *)base, name, NULL);
00738 } else {
00739 MSG_WARNING("basepath for mount point have to be absolute (adding DIRSEP) -> check your config");
00740 res = g_build_path(G_DIR_SEPARATOR_S, G_DIR_SEPARATOR_S, (gchar *)base, name, NULL);
00741 }
00742 if (res==NULL) {
00743 goto error;
00744 }
00745
00746
00747 if (!sb_dir_is_dir(res)) {
00748 break;
00749 } else {
00750 g_free(res);
00751 res = NULL;
00752 }
00753 }
00754 }
00755
00756 goto cleanup;
00757
00758 error:
00759 res = NULL;
00760
00761 cleanup:
00762 if (longname != NULL) {
00763 g_free(longname);
00764 longname = NULL;
00765 }
00766 if (name != NULL) {
00767 free(name);
00768 name = NULL;
00769 }
00770
00771 return (char *)res;
00772 }
00773
00774
00782 int
00783 mntd_volume_helper_base_is_in_mntpath(const char *base, const char *mntpnt)
00784 {
00785 int res = TRUE;
00786 int abs_base = 0;
00787 int abs_mntpnt = 0;
00788 gchar *path_base = NULL;
00789 gchar *path_mntpnt = NULL;
00790
00791 g_assert(base!=NULL);
00792 g_assert(mntpnt!=NULL);
00793
00794
00795 abs_base = g_path_is_absolute((gchar *)base);
00796 abs_mntpnt = g_path_is_absolute((gchar *)mntpnt);
00797 if (abs_base != abs_mntpnt) {
00798 goto no;
00799 }
00800
00801
00802 path_base = g_build_path(G_DIR_SEPARATOR_S, (gchar *)base, NULL);
00803 if (path_base == NULL) {
00804 goto no;
00805 }
00806 path_mntpnt = g_build_path(G_DIR_SEPARATOR_S, (gchar *)mntpnt, NULL);
00807 if (path_mntpnt == NULL) {
00808 goto no;
00809 }
00810 if (!g_str_has_prefix(path_mntpnt, path_base)) {
00811 goto no;
00812 }
00813
00814 goto cleanup;
00815
00816 no:
00817 res = FALSE;
00818
00819 cleanup:
00820 if (path_base != NULL) {
00821 g_free(path_base);
00822 path_base = NULL;
00823 }
00824 if (path_mntpnt != NULL) {
00825 g_free(path_mntpnt);
00826 path_mntpnt = NULL;
00827 }
00828
00829
00830 return res;
00831 }
00832
00833
00840 int
00841 mntd_volume_is_in_mntpath(PVOLUME pv)
00842 {
00843 g_assert(pv!=NULL);
00844
00845 if ((pv->mntpnt==NULL) || (pv->base==NULL)) {
00846 return FALSE;
00847 }
00848
00849 return mntd_volume_helper_base_is_in_mntpath(pv->base, pv->mntpnt);
00850 }
00851
00852
00859 int
00860 mntd_volume_send_mounted(PVOLUME pv)
00861 {
00862 g_assert(pv!=NULL);
00863 g_assert(pv->udi!=NULL);
00864 g_assert(pv->mntpnt!=NULL);
00865
00866 if (pv->last_signal!=SIGNAL_MOUNTED) {
00867 pv->last_signal = SIGNAL_MOUNTED;
00868 MSG_DEBUG("sending 'mounted' signal for '%s' ('%s') ...", pv->mntpnt, pv->udi);
00869 mntd_dbus_manager_send_signal_volume_mounted(pv);
00870 }
00871
00872 return TRUE;
00873 }
00874
00875
00882 int
00883 mntd_volume_send_unmounted(PVOLUME pv)
00884 {
00885 g_assert(pv!=NULL);
00886 g_assert(pv->udi!=NULL);
00887 g_assert(pv->mntpnt!=NULL);
00888
00889 if (pv->last_signal!=SIGNAL_UNMOUNTED) {
00890 pv->last_signal = SIGNAL_UNMOUNTED;
00891 MSG_DEBUG("sending 'unmounted' signal for '%s' ('%s') ...", pv->mntpnt, pv->udi);
00892 mntd_dbus_manager_send_signal_volume_unmounted(pv);
00893 }
00894
00895 return TRUE;
00896 }
00897
00898
00908 int
00909 mntd_volume_send_signal(PVOLUME pv, int what)
00910 {
00911 g_assert(pv!=NULL);
00912 g_assert(pv->udi!=NULL);
00913
00914
00915 if (what==SIGNAL_MOUNTED) {
00916 pv->_send_mounted(pv);
00917
00918
00919 } else if (what==SIGNAL_UNMOUNTED) {
00920 pv->_send_unmounted(pv);
00921
00922
00923 } else {
00924 if (pv->is_in_mntpath(pv)) {
00925 if (pv->mntpnt!=NULL) {
00926 pv->_send_mounted(pv);
00927 } else {
00928 pv->_send_unmounted(pv);
00929 }
00930 }
00931 }
00932
00933 return TRUE;
00934 }
00935
00936