2 This file is part of systemd.
4 Copyright 2016 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include "bus-error.h"
26 #include "bus-unit-util.h"
29 #include "fstab-util.h"
31 #include "parse-util.h"
32 #include "path-util.h"
33 #include "spawn-polkit-agent.h"
35 #include "udev-util.h"
36 #include "unit-name.h"
37 #include "terminal-util.h"
44 } arg_action
= ACTION_DEFAULT
;
46 static bool arg_no_block
= false;
47 static bool arg_no_pager
= false;
48 static bool arg_ask_password
= true;
49 static bool arg_quiet
= false;
50 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
51 static bool arg_user
= false;
52 static const char *arg_host
= NULL
;
53 static bool arg_discover
= false;
54 static char *arg_mount_what
= NULL
;
55 static char *arg_mount_where
= NULL
;
56 static char *arg_mount_type
= NULL
;
57 static char *arg_mount_options
= NULL
;
58 static char *arg_description
= NULL
;
59 static char **arg_property
= NULL
;
60 static usec_t arg_timeout_idle
= USEC_INFINITY
;
61 static bool arg_timeout_idle_set
= false;
62 static char **arg_automount_property
= NULL
;
63 static int arg_bind_device
= -1;
64 static bool arg_fsck
= true;
66 static void polkit_agent_open_if_enabled(void) {
68 /* Open the polkit agent as a child process if necessary */
69 if (!arg_ask_password
)
72 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
78 static void help(void) {
79 printf("%s [OPTIONS...] WHAT [WHERE]\n\n"
80 "Establish a mount or auto-mount point transiently.\n\n"
81 " -h --help Show this help\n"
82 " --version Show package version\n"
83 " --no-block Do not wait until operation finished\n"
84 " --no-pager Do not pipe output into a pager\n"
85 " --no-ask-password Do not prompt for password\n"
86 " -q --quiet Suppress information messages during runtime\n"
87 " --user Run as user unit\n"
88 " -H --host=[USER@]HOST Operate on remote host\n"
89 " -M --machine=CONTAINER Operate on local container\n"
90 " --discover Discover mount device metadata\n"
91 " -t --type=TYPE File system type\n"
92 " -o --options=OPTIONS Mount options\n"
93 " --fsck=no Don't run file system check before mount\n"
94 " --description=TEXT Description for unit\n"
95 " -p --property=NAME=VALUE Set mount unit property\n"
96 " -A --automount=BOOL Create an auto-mount point\n"
97 " --timeout-idle-sec=SEC Specify automount idle timeout\n"
98 " --automount-property=NAME=VALUE\n"
99 " Set automount unit property\n"
100 " --bind-device Bind automount unit to device\n"
101 " --list List mountable block devices\n"
102 , program_invocation_short_name
);
105 static int parse_argv(int argc
, char *argv
[]) {
121 ARG_AUTOMOUNT_PROPERTY
,
126 static const struct option options
[] = {
127 { "help", no_argument
, NULL
, 'h' },
128 { "version", no_argument
, NULL
, ARG_VERSION
},
129 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
130 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
131 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
132 { "quiet", no_argument
, NULL
, 'q' },
133 { "user", no_argument
, NULL
, ARG_USER
},
134 { "system", no_argument
, NULL
, ARG_SYSTEM
},
135 { "host", required_argument
, NULL
, 'H' },
136 { "machine", required_argument
, NULL
, 'M' },
137 { "discover", no_argument
, NULL
, ARG_DISCOVER
},
138 { "type", required_argument
, NULL
, 't' },
139 { "options", required_argument
, NULL
, 'o' },
140 { "description", required_argument
, NULL
, ARG_DESCRIPTION
},
141 { "property", required_argument
, NULL
, 'p' },
142 { "automount", required_argument
, NULL
, ARG_AUTOMOUNT
},
143 { "timeout-idle-sec", required_argument
, NULL
, ARG_TIMEOUT_IDLE
},
144 { "automount-property", required_argument
, NULL
, ARG_AUTOMOUNT_PROPERTY
},
145 { "bind-device", no_argument
, NULL
, ARG_BIND_DEVICE
},
146 { "list", no_argument
, NULL
, ARG_LIST
},
155 while ((c
= getopt_long(argc
, argv
, "hqH:M:t:o:p:A", options
, NULL
)) >= 0)
174 case ARG_NO_ASK_PASSWORD
:
175 arg_ask_password
= false;
191 arg_transport
= BUS_TRANSPORT_REMOTE
;
196 arg_transport
= BUS_TRANSPORT_MACHINE
;
205 if (free_and_strdup(&arg_mount_type
, optarg
) < 0)
210 if (free_and_strdup(&arg_mount_options
, optarg
) < 0)
215 r
= parse_boolean(optarg
);
217 return log_error_errno(r
, "Failed to parse --fsck= argument: %s", optarg
);
222 case ARG_DESCRIPTION
:
223 if (free_and_strdup(&arg_description
, optarg
) < 0)
228 if (strv_extend(&arg_property
, optarg
) < 0)
234 arg_action
= ACTION_AUTOMOUNT
;
238 r
= parse_boolean(optarg
);
240 return log_error_errno(r
, "--automount= expects a valid boolean parameter: %s", optarg
);
242 arg_action
= r
? ACTION_AUTOMOUNT
: ACTION_MOUNT
;
245 case ARG_TIMEOUT_IDLE
:
246 r
= parse_sec(optarg
, &arg_timeout_idle
);
248 return log_error_errno(r
, "Failed to parse timeout: %s", optarg
);
252 case ARG_AUTOMOUNT_PROPERTY
:
253 if (strv_extend(&arg_automount_property
, optarg
) < 0)
258 case ARG_BIND_DEVICE
:
259 arg_bind_device
= true;
263 arg_action
= ACTION_LIST
;
270 assert_not_reached("Unhandled option");
273 if (arg_user
&& arg_transport
!= BUS_TRANSPORT_LOCAL
) {
274 log_error("Execution in user context is not supported on non-local systems.");
278 if (arg_action
== ACTION_LIST
) {
280 log_error("Too many arguments.");
284 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
285 log_error("Listing devices only supported locally.");
289 if (optind
>= argc
) {
290 log_error("At least one argument required.");
294 if (argc
> optind
+2) {
295 log_error("At most two arguments required.");
299 arg_mount_what
= fstab_node_to_udev_node(argv
[optind
]);
303 if (argc
> optind
+1) {
304 r
= path_make_absolute_cwd(argv
[optind
+1], &arg_mount_where
);
306 return log_error_errno(r
, "Failed to make path absolute: %m");
310 if (arg_discover
&& arg_transport
!= BUS_TRANSPORT_LOCAL
) {
311 log_error("Automatic mount location discovery is only supported locally.");
319 static int transient_unit_set_properties(sd_bus_message
*m
, char **properties
) {
322 if (!isempty(arg_description
)) {
323 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", arg_description
);
328 if (arg_bind_device
&& is_device_path(arg_mount_what
)) {
329 _cleanup_free_
char *device_unit
= NULL
;
331 r
= unit_name_from_path(arg_mount_what
, ".device", &device_unit
);
335 r
= sd_bus_message_append(m
, "(sv)(sv)",
336 "After", "as", 1, device_unit
,
337 "BindsTo", "as", 1, device_unit
);
342 r
= bus_append_unit_property_assignment_many(m
, properties
);
349 static int transient_mount_set_properties(sd_bus_message
*m
) {
354 r
= transient_unit_set_properties(m
, arg_property
);
358 if (arg_mount_what
) {
359 r
= sd_bus_message_append(m
, "(sv)", "What", "s", arg_mount_what
);
364 if (arg_mount_type
) {
365 r
= sd_bus_message_append(m
, "(sv)", "Type", "s", arg_mount_type
);
370 if (arg_mount_options
) {
371 r
= sd_bus_message_append(m
, "(sv)", "Options", "s", arg_mount_options
);
377 _cleanup_free_
char *fsck
= NULL
;
379 r
= unit_name_from_path_instance("systemd-fsck", arg_mount_what
, ".service", &fsck
);
383 r
= sd_bus_message_append(m
,
385 "Requires", "as", 1, fsck
,
386 "After", "as", 1, fsck
);
394 static int transient_automount_set_properties(sd_bus_message
*m
) {
399 r
= transient_unit_set_properties(m
, arg_automount_property
);
403 if (arg_timeout_idle
!= USEC_INFINITY
) {
404 r
= sd_bus_message_append(m
, "(sv)", "TimeoutIdleUSec", "t", arg_timeout_idle
);
412 static int start_transient_mount(
416 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
417 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
418 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
419 _cleanup_free_
char *mount_unit
= NULL
;
423 r
= bus_wait_for_jobs_new(bus
, &w
);
425 return log_error_errno(r
, "Could not watch jobs: %m");
428 r
= unit_name_from_path(arg_mount_where
, ".mount", &mount_unit
);
430 return log_error_errno(r
, "Failed to make mount unit name: %m");
432 r
= sd_bus_message_new_method_call(
435 "org.freedesktop.systemd1",
436 "/org/freedesktop/systemd1",
437 "org.freedesktop.systemd1.Manager",
438 "StartTransientUnit");
440 return bus_log_create_error(r
);
442 r
= sd_bus_message_set_allow_interactive_authorization(m
, arg_ask_password
);
444 return bus_log_create_error(r
);
447 r
= sd_bus_message_append(m
, "ss", mount_unit
, "fail");
449 return bus_log_create_error(r
);
452 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
454 return bus_log_create_error(r
);
456 r
= transient_mount_set_properties(m
);
458 return bus_log_create_error(r
);
460 r
= sd_bus_message_close_container(m
);
462 return bus_log_create_error(r
);
464 /* Auxiliary units */
465 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
467 return bus_log_create_error(r
);
469 polkit_agent_open_if_enabled();
471 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
473 return log_error_errno(r
, "Failed to start transient mount unit: %s", bus_error_message(&error
, r
));
478 r
= sd_bus_message_read(reply
, "o", &object
);
480 return bus_log_parse_error(r
);
482 r
= bus_wait_for_jobs_one(w
, object
, arg_quiet
);
488 log_info("Started unit %s%s%s for mount point: %s%s%s",
489 ansi_highlight(), mount_unit
, ansi_normal(),
490 ansi_highlight(), arg_mount_where
, ansi_normal());
495 static int start_transient_automount(
499 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
500 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
501 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
502 _cleanup_free_
char *automount_unit
= NULL
, *mount_unit
= NULL
;
506 r
= bus_wait_for_jobs_new(bus
, &w
);
508 return log_error_errno(r
, "Could not watch jobs: %m");
511 r
= unit_name_from_path(arg_mount_where
, ".automount", &automount_unit
);
513 return log_error_errno(r
, "Failed to make automount unit name: %m");
515 r
= unit_name_from_path(arg_mount_where
, ".mount", &mount_unit
);
517 return log_error_errno(r
, "Failed to make mount unit name: %m");
519 r
= sd_bus_message_new_method_call(
522 "org.freedesktop.systemd1",
523 "/org/freedesktop/systemd1",
524 "org.freedesktop.systemd1.Manager",
525 "StartTransientUnit");
527 return bus_log_create_error(r
);
529 r
= sd_bus_message_set_allow_interactive_authorization(m
, arg_ask_password
);
531 return bus_log_create_error(r
);
534 r
= sd_bus_message_append(m
, "ss", automount_unit
, "fail");
536 return bus_log_create_error(r
);
539 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
541 return bus_log_create_error(r
);
543 r
= transient_automount_set_properties(m
);
545 return bus_log_create_error(r
);
547 r
= sd_bus_message_close_container(m
);
549 return bus_log_create_error(r
);
551 /* Auxiliary units */
552 r
= sd_bus_message_open_container(m
, 'a', "(sa(sv))");
554 return bus_log_create_error(r
);
556 r
= sd_bus_message_open_container(m
, 'r', "sa(sv)");
558 return bus_log_create_error(r
);
560 r
= sd_bus_message_append(m
, "s", mount_unit
);
562 return bus_log_create_error(r
);
564 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
566 return bus_log_create_error(r
);
568 r
= transient_mount_set_properties(m
);
570 return bus_log_create_error(r
);
572 r
= sd_bus_message_close_container(m
);
574 return bus_log_create_error(r
);
576 r
= sd_bus_message_close_container(m
);
578 return bus_log_create_error(r
);
580 r
= sd_bus_message_close_container(m
);
582 return bus_log_create_error(r
);
584 polkit_agent_open_if_enabled();
586 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
588 return log_error_errno(r
, "Failed to start transient automount unit: %s", bus_error_message(&error
, r
));
593 r
= sd_bus_message_read(reply
, "o", &object
);
595 return bus_log_parse_error(r
);
597 r
= bus_wait_for_jobs_one(w
, object
, arg_quiet
);
603 log_info("Started unit %s%s%s for mount point: %s%s%s",
604 ansi_highlight(), automount_unit
, ansi_normal(),
605 ansi_highlight(), arg_mount_where
, ansi_normal());
610 static int acquire_mount_type(struct udev_device
*d
) {
618 v
= udev_device_get_property_value(d
, "ID_FS_TYPE");
622 arg_mount_type
= strdup(v
);
626 log_debug("Discovered type=%s", arg_mount_type
);
630 static int acquire_mount_options(struct udev_device
*d
) {
633 if (arg_mount_options
)
636 v
= udev_device_get_property_value(d
, "SYSTEMD_MOUNT_OPTIONS");
640 arg_mount_options
= strdup(v
);
641 if (!arg_mount_options
)
644 log_debug("Discovered options=%s", arg_mount_options
);
648 static const char *get_model(struct udev_device
*d
) {
653 model
= udev_device_get_property_value(d
, "ID_MODEL_FROM_DATABASE");
657 return udev_device_get_property_value(d
, "ID_MODEL");
660 static const char* get_label(struct udev_device
*d
) {
665 label
= udev_device_get_property_value(d
, "ID_FS_LABEL");
669 return udev_device_get_property_value(d
, "ID_PART_ENTRY_NAME");
672 static int acquire_mount_where(struct udev_device
*d
) {
678 v
= udev_device_get_property_value(d
, "SYSTEMD_MOUNT_WHERE");
680 _cleanup_free_
char *escaped
= NULL
;
689 dn
= udev_device_get_devnode(d
);
696 escaped
= xescape(name
, "\\");
697 if (!filename_is_valid(escaped
))
700 arg_mount_where
= strjoin("/run/media/system/", escaped
, NULL
);
702 arg_mount_where
= strdup(v
);
704 if (!arg_mount_where
)
707 log_debug("Discovered where=%s", arg_mount_where
);
711 static int acquire_description(struct udev_device
*d
) {
712 const char *model
, *label
;
717 model
= get_model(d
);
719 label
= get_label(d
);
721 label
= udev_device_get_property_value(d
, "ID_PART_ENTRY_NUMBER");
724 arg_description
= strjoin(model
, " ", label
, NULL
);
726 arg_description
= strdup(label
);
728 arg_description
= strdup(model
);
732 if (!arg_description
)
735 log_debug("Discovered description=%s", arg_description
);
739 static int acquire_removable(struct udev_device
*d
) {
742 /* Shortcut this if there's no reason to check it */
743 if (arg_action
!= ACTION_DEFAULT
&& arg_timeout_idle_set
&& arg_bind_device
>= 0)
747 v
= udev_device_get_sysattr_value(d
, "removable");
751 d
= udev_device_get_parent(d
);
755 if (!streq_ptr(udev_device_get_subsystem(d
), "block"))
759 if (parse_boolean(v
) <= 0)
762 log_debug("Discovered removable device.");
764 if (arg_action
== ACTION_DEFAULT
) {
765 log_debug("Automatically turning on automount.");
766 arg_action
= ACTION_AUTOMOUNT
;
769 if (!arg_timeout_idle_set
) {
770 log_debug("Setting idle timeout to 1s.");
771 arg_timeout_idle
= USEC_PER_SEC
;
774 if (arg_bind_device
< 0) {
775 log_debug("Binding automount unit to device.");
776 arg_bind_device
= true;
782 static int discover_device(void) {
783 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
784 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
792 if (!is_device_path(arg_mount_what
)) {
793 log_error("Discovery only supported for block devices, don't know what to do.");
797 if (stat(arg_mount_what
, &st
) < 0)
798 return log_error_errno(errno
, "Can't stat %s: %m", arg_mount_what
);
800 if (!S_ISBLK(st
.st_mode
)) {
801 log_error("Path %s is not a block device, don't know what to do.", arg_mount_what
);
809 d
= udev_device_new_from_devnum(udev
, 'b', st
.st_rdev
);
813 v
= udev_device_get_property_value(d
, "ID_FS_USAGE");
814 if (!streq_ptr(v
, "filesystem")) {
815 log_error("%s does not contain a file system.", arg_mount_what
);
819 r
= acquire_mount_type(d
);
823 r
= acquire_mount_options(d
);
827 r
= acquire_mount_where(d
);
831 r
= acquire_description(d
);
835 r
= acquire_removable(d
);
854 char* columns
[_COLUMN_MAX
];
857 static int compare_item(const void *a
, const void *b
) {
858 const struct item
*x
= a
, *y
= b
;
860 if (x
->columns
[COLUMN_NODE
] == y
->columns
[COLUMN_NODE
])
862 if (!x
->columns
[COLUMN_NODE
])
864 if (!y
->columns
[COLUMN_NODE
])
867 return path_compare(x
->columns
[COLUMN_NODE
], y
->columns
[COLUMN_NODE
]);
870 static int list_devices(void) {
872 static const char * const titles
[_COLUMN_MAX
] = {
873 [COLUMN_NODE
] = "NODE",
874 [COLUMN_PATH
] = "PATH",
875 [COLUMN_MODEL
] = "MODEL",
876 [COLUMN_WWN
] = "WWN",
877 [COLUMN_FSTYPE
] = "TYPE",
878 [COLUMN_LABEL
] = "LABEL",
879 [COLUMN_UUID
] = "UUID"
882 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
883 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
884 struct udev_list_entry
*item
= NULL
, *first
= NULL
;
885 size_t n_allocated
= 0, n
= 0, i
;
886 size_t column_width
[_COLUMN_MAX
];
887 struct item
*items
= NULL
;
891 for (c
= 0; c
< _COLUMN_MAX
; c
++)
892 column_width
[c
] = strlen(titles
[c
]);
898 e
= udev_enumerate_new(udev
);
902 r
= udev_enumerate_add_match_subsystem(e
, "block");
904 return log_error_errno(r
, "Failed to add block match: %m");
906 r
= udev_enumerate_add_match_property(e
, "ID_FS_USAGE", "filesystem");
908 return log_error_errno(r
, "Failed to add property match: %m");
910 r
= udev_enumerate_scan_devices(e
);
912 return log_error_errno(r
, "Failed to scan devices: %m");
914 first
= udev_enumerate_get_list_entry(e
);
915 udev_list_entry_foreach(item
, first
) {
916 _cleanup_udev_device_unref_
struct udev_device
*d
;
919 d
= udev_device_new_from_syspath(udev
, udev_list_entry_get_name(item
));
925 if (!GREEDY_REALLOC0(items
, n_allocated
, n
+1)) {
932 for (c
= 0; c
< _COLUMN_MAX
; c
++) {
939 x
= udev_device_get_devnode(d
);
943 x
= udev_device_get_property_value(d
, "ID_PATH");
951 x
= udev_device_get_property_value(d
, "ID_WWN");
955 x
= udev_device_get_property_value(d
, "ID_FS_TYPE");
963 x
= udev_device_get_property_value(d
, "ID_FS_UUID");
970 j
->columns
[c
] = strdup(x
);
971 if (!j
->columns
[c
]) {
977 if (k
> column_width
[c
])
983 log_info("No devices found.");
987 qsort_safe(items
, n
, sizeof(struct item
), compare_item
);
989 pager_open(arg_no_pager
, false);
991 fputs(ansi_underline(), stdout
);
992 for (c
= 0; c
< _COLUMN_MAX
; c
++) {
996 printf("%-*s", (int) column_width
[c
], titles
[c
]);
998 fputs(ansi_normal(), stdout
);
1001 for (i
= 0; i
< n
; i
++) {
1002 for (c
= 0; c
< _COLUMN_MAX
; c
++) {
1006 printf("%-*s", (int) column_width
[c
], strna(items
[i
].columns
[c
]));
1008 fputc('\n', stdout
);
1014 for (i
= 0; i
< n
; i
++)
1015 for (c
= 0; c
< _COLUMN_MAX
; c
++)
1016 free(items
[i
].columns
[c
]);
1022 int main(int argc
, char* argv
[]) {
1023 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
1026 log_parse_environment();
1029 r
= parse_argv(argc
, argv
);
1033 if (arg_action
== ACTION_LIST
) {
1038 r
= discover_device();
1041 if (!arg_mount_where
) {
1042 log_error("Can't figure out where to mount %s.", arg_mount_what
);
1047 path_kill_slashes(arg_mount_where
);
1049 if (path_equal(arg_mount_where
, "/")) {
1050 log_error("Refusing to operate on root directory.");
1055 if (!path_is_safe(arg_mount_where
)) {
1056 log_error("Path is contains unsafe components.");
1061 if (streq_ptr(arg_mount_type
, "auto"))
1062 arg_mount_type
= mfree(arg_mount_type
);
1063 if (streq_ptr(arg_mount_options
, "defaults"))
1064 arg_mount_options
= mfree(arg_mount_options
);
1066 if (!is_device_path(arg_mount_what
))
1069 if (arg_fsck
&& arg_mount_type
&& arg_transport
== BUS_TRANSPORT_LOCAL
) {
1070 r
= fsck_exists(arg_mount_type
);
1072 log_warning_errno(r
, "Couldn't determine whether fsck for %s exists, proceeding anyway.", arg_mount_type
);
1074 log_debug("Disabling file system check as fsck for %s doesn't exist.", arg_mount_type
);
1075 arg_fsck
= false; /* fsck doesn't exist, let's not attempt it */
1079 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, arg_user
, &bus
);
1081 log_error_errno(r
, "Failed to create bus connection: %m");
1085 switch (arg_action
) {
1088 case ACTION_DEFAULT
:
1089 r
= start_transient_mount(bus
, argv
+ optind
);
1092 case ACTION_AUTOMOUNT
:
1093 r
= start_transient_automount(bus
, argv
+ optind
);
1097 assert_not_reached("Unexpected action.");
1101 bus
= sd_bus_flush_close_unref(bus
);
1105 free(arg_mount_what
);
1106 free(arg_mount_where
);
1107 free(arg_mount_type
);
1108 free(arg_mount_options
);
1109 free(arg_description
);
1110 strv_free(arg_property
);
1111 strv_free(arg_automount_property
);
1113 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;