1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2016 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "bus-error.h"
27 #include "bus-unit-util.h"
29 #include "dirent-util.h"
34 #include "fstab-util.h"
35 #include "mount-util.h"
37 #include "parse-util.h"
38 #include "path-util.h"
39 #include "spawn-polkit-agent.h"
40 #include "stat-util.h"
42 #include "udev-util.h"
44 #include "unit-name.h"
45 #include "user-util.h"
46 #include "terminal-util.h"
54 } arg_action
= ACTION_DEFAULT
;
56 static bool arg_no_block
= false;
57 static bool arg_no_pager
= false;
58 static bool arg_ask_password
= true;
59 static bool arg_quiet
= false;
60 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
61 static bool arg_user
= false;
62 static const char *arg_host
= NULL
;
63 static bool arg_discover
= false;
64 static char *arg_mount_what
= NULL
;
65 static char *arg_mount_where
= NULL
;
66 static char *arg_mount_type
= NULL
;
67 static char *arg_mount_options
= NULL
;
68 static char *arg_description
= NULL
;
69 static char **arg_property
= NULL
;
70 static usec_t arg_timeout_idle
= USEC_INFINITY
;
71 static bool arg_timeout_idle_set
= false;
72 static char **arg_automount_property
= NULL
;
73 static int arg_bind_device
= -1;
74 static uid_t arg_uid
= UID_INVALID
;
75 static gid_t arg_gid
= GID_INVALID
;
76 static bool arg_fsck
= true;
77 static bool arg_aggressive_gc
= false;
79 static void help(void) {
80 printf("systemd-mount [OPTIONS...] WHAT [WHERE]\n"
81 "systemd-mount [OPTIONS...] --list\n"
82 "%s [OPTIONS...] %sWHAT|WHERE...\n\n"
83 "Establish a mount or auto-mount point transiently.\n\n"
84 " -h --help Show this help\n"
85 " --version Show package version\n"
86 " --no-block Do not wait until operation finished\n"
87 " --no-pager Do not pipe output into a pager\n"
88 " --no-ask-password Do not prompt for password\n"
89 " -q --quiet Suppress information messages during runtime\n"
90 " --user Run as user unit\n"
91 " -H --host=[USER@]HOST Operate on remote host\n"
92 " -M --machine=CONTAINER Operate on local container\n"
93 " --discover Discover mount device metadata\n"
94 " -t --type=TYPE File system type\n"
95 " -o --options=OPTIONS Mount options\n"
96 " --owner=USER Add uid= and gid= options for USER\n"
97 " --fsck=no Don't run file system check before mount\n"
98 " --description=TEXT Description for unit\n"
99 " -p --property=NAME=VALUE Set mount unit property\n"
100 " -A --automount=BOOL Create an auto-mount point\n"
101 " --timeout-idle-sec=SEC Specify automount idle timeout\n"
102 " --automount-property=NAME=VALUE\n"
103 " Set automount unit property\n"
104 " --bind-device Bind automount unit to device\n"
105 " --list List mountable block devices\n"
106 " -u --umount Unmount mount points\n"
107 " -G --collect Unload unit after it stopped, even when failed\n",
108 program_invocation_short_name
,
109 streq(program_invocation_short_name
, "systemd-umount") ? "" : "--umount ");
112 static int parse_argv(int argc
, char *argv
[]) {
129 ARG_AUTOMOUNT_PROPERTY
,
134 static const struct option options
[] = {
135 { "help", no_argument
, NULL
, 'h' },
136 { "version", no_argument
, NULL
, ARG_VERSION
},
137 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
138 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
139 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
140 { "quiet", no_argument
, NULL
, 'q' },
141 { "user", no_argument
, NULL
, ARG_USER
},
142 { "system", no_argument
, NULL
, ARG_SYSTEM
},
143 { "host", required_argument
, NULL
, 'H' },
144 { "machine", required_argument
, NULL
, 'M' },
145 { "discover", no_argument
, NULL
, ARG_DISCOVER
},
146 { "type", required_argument
, NULL
, 't' },
147 { "options", required_argument
, NULL
, 'o' },
148 { "owner", required_argument
, NULL
, ARG_OWNER
},
149 { "fsck", required_argument
, NULL
, ARG_FSCK
},
150 { "description", required_argument
, NULL
, ARG_DESCRIPTION
},
151 { "property", required_argument
, NULL
, 'p' },
152 { "automount", required_argument
, NULL
, ARG_AUTOMOUNT
},
153 { "timeout-idle-sec", required_argument
, NULL
, ARG_TIMEOUT_IDLE
},
154 { "automount-property", required_argument
, NULL
, ARG_AUTOMOUNT_PROPERTY
},
155 { "bind-device", no_argument
, NULL
, ARG_BIND_DEVICE
},
156 { "list", no_argument
, NULL
, ARG_LIST
},
157 { "umount", no_argument
, NULL
, 'u' },
158 { "unmount", no_argument
, NULL
, 'u' },
159 { "collect", no_argument
, NULL
, 'G' },
168 if (strstr(program_invocation_short_name
, "systemd-umount"))
169 arg_action
= ACTION_UMOUNT
;
171 while ((c
= getopt_long(argc
, argv
, "hqH:M:t:o:p:AuG", options
, NULL
)) >= 0)
190 case ARG_NO_ASK_PASSWORD
:
191 arg_ask_password
= false;
207 arg_transport
= BUS_TRANSPORT_REMOTE
;
212 arg_transport
= BUS_TRANSPORT_MACHINE
;
221 if (free_and_strdup(&arg_mount_type
, optarg
) < 0)
226 if (free_and_strdup(&arg_mount_options
, optarg
) < 0)
231 const char *user
= optarg
;
233 r
= get_user_creds(&user
, &arg_uid
, &arg_gid
, NULL
, NULL
);
235 return log_error_errno(r
,
236 r
== -EBADMSG
? "UID or GID of user %s are invalid."
237 : "Cannot use \"%s\" as owner: %m",
243 r
= parse_boolean(optarg
);
245 return log_error_errno(r
, "Failed to parse --fsck= argument: %s", optarg
);
250 case ARG_DESCRIPTION
:
251 if (free_and_strdup(&arg_description
, optarg
) < 0)
256 if (strv_extend(&arg_property
, optarg
) < 0)
262 arg_action
= ACTION_AUTOMOUNT
;
266 r
= parse_boolean(optarg
);
268 return log_error_errno(r
, "--automount= expects a valid boolean parameter: %s", optarg
);
270 arg_action
= r
? ACTION_AUTOMOUNT
: ACTION_MOUNT
;
273 case ARG_TIMEOUT_IDLE
:
274 r
= parse_sec(optarg
, &arg_timeout_idle
);
276 return log_error_errno(r
, "Failed to parse timeout: %s", optarg
);
280 case ARG_AUTOMOUNT_PROPERTY
:
281 if (strv_extend(&arg_automount_property
, optarg
) < 0)
286 case ARG_BIND_DEVICE
:
287 arg_bind_device
= true;
291 arg_action
= ACTION_LIST
;
295 arg_action
= ACTION_UMOUNT
;
299 arg_aggressive_gc
= true;
306 assert_not_reached("Unhandled option");
309 if (arg_user
&& arg_transport
!= BUS_TRANSPORT_LOCAL
) {
310 log_error("Execution in user context is not supported on non-local systems.");
314 if (arg_action
== ACTION_LIST
) {
316 log_error("Too many arguments.");
320 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
321 log_error("Listing devices only supported locally.");
324 } else if (arg_action
== ACTION_UMOUNT
) {
325 if (optind
>= argc
) {
326 log_error("At least one argument required.");
330 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
333 for (i
= optind
; i
< argc
; i
++)
334 if (!path_is_absolute(argv
[i
]) ) {
335 log_error("Only absolute path is supported: %s", argv
[i
]);
340 if (optind
>= argc
) {
341 log_error("At least one argument required.");
345 if (argc
> optind
+2) {
346 log_error("At most two arguments required.");
350 if (arg_mount_type
&& (fstype_is_api_vfs(arg_mount_type
) || fstype_is_network(arg_mount_type
))) {
351 arg_mount_what
= strdup(argv
[optind
]);
355 } else if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
356 _cleanup_free_
char *u
= NULL
;
358 u
= fstab_node_to_udev_node(argv
[optind
]);
362 r
= chase_symlinks(u
, NULL
, 0, &arg_mount_what
);
364 return log_error_errno(r
, "Failed to make path %s absolute: %m", u
);
366 arg_mount_what
= strdup(argv
[optind
]);
370 path_kill_slashes(arg_mount_what
);
372 if (!path_is_absolute(arg_mount_what
)) {
373 log_error("Only absolute path is supported: %s", arg_mount_what
);
378 if (argc
> optind
+1) {
379 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
380 r
= chase_symlinks(argv
[optind
+1], NULL
, CHASE_NONEXISTENT
, &arg_mount_where
);
382 return log_error_errno(r
, "Failed to make path %s absolute: %m", argv
[optind
+1]);
384 arg_mount_where
= strdup(argv
[optind
+1]);
385 if (!arg_mount_where
)
388 path_kill_slashes(arg_mount_where
);
390 if (!path_is_absolute(arg_mount_where
)) {
391 log_error("Only absolute path is supported: %s", arg_mount_where
);
398 if (arg_discover
&& arg_transport
!= BUS_TRANSPORT_LOCAL
) {
399 log_error("Automatic mount location discovery is only supported locally.");
407 static int transient_unit_set_properties(sd_bus_message
*m
, UnitType t
, char **properties
) {
410 if (!isempty(arg_description
)) {
411 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", arg_description
);
416 if (arg_bind_device
&& is_device_path(arg_mount_what
)) {
417 _cleanup_free_
char *device_unit
= NULL
;
419 r
= unit_name_from_path(arg_mount_what
, ".device", &device_unit
);
423 r
= sd_bus_message_append(m
, "(sv)(sv)",
424 "After", "as", 1, device_unit
,
425 "BindsTo", "as", 1, device_unit
);
430 if (arg_aggressive_gc
) {
431 r
= sd_bus_message_append(m
, "(sv)", "CollectMode", "s", "inactive-or-failed");
436 r
= bus_append_unit_property_assignment_many(m
, t
, properties
);
443 static int transient_mount_set_properties(sd_bus_message
*m
) {
444 _cleanup_free_
char *options
= NULL
;
449 r
= transient_unit_set_properties(m
, UNIT_MOUNT
, arg_property
);
453 if (arg_mount_what
) {
454 r
= sd_bus_message_append(m
, "(sv)", "What", "s", arg_mount_what
);
459 if (arg_mount_type
) {
460 r
= sd_bus_message_append(m
, "(sv)", "Type", "s", arg_mount_type
);
465 /* Prepend uid=…,gid=… if arg_uid is set */
466 if (arg_uid
!= UID_INVALID
) {
467 r
= asprintf(&options
,
468 "uid=" UID_FMT
",gid=" GID_FMT
"%s%s",
470 arg_mount_options
? "," : "", arg_mount_options
);
475 if (options
|| arg_mount_options
) {
476 log_debug("Using mount options: %s", options
?: arg_mount_options
);
478 r
= sd_bus_message_append(m
, "(sv)", "Options", "s", options
?: arg_mount_options
);
482 log_debug("Not using any mount options");
485 _cleanup_free_
char *fsck
= NULL
;
487 r
= unit_name_from_path_instance("systemd-fsck", arg_mount_what
, ".service", &fsck
);
491 r
= sd_bus_message_append(m
,
493 "Requires", "as", 1, fsck
,
494 "After", "as", 1, fsck
);
502 static int transient_automount_set_properties(sd_bus_message
*m
) {
507 r
= transient_unit_set_properties(m
, UNIT_AUTOMOUNT
, arg_automount_property
);
511 if (arg_timeout_idle
!= USEC_INFINITY
) {
512 r
= sd_bus_message_append(m
, "(sv)", "TimeoutIdleUSec", "t", arg_timeout_idle
);
520 static int start_transient_mount(
524 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
525 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
526 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
527 _cleanup_free_
char *mount_unit
= NULL
;
531 r
= bus_wait_for_jobs_new(bus
, &w
);
533 return log_error_errno(r
, "Could not watch jobs: %m");
536 r
= unit_name_from_path(arg_mount_where
, ".mount", &mount_unit
);
538 return log_error_errno(r
, "Failed to make mount unit name: %m");
540 r
= sd_bus_message_new_method_call(
543 "org.freedesktop.systemd1",
544 "/org/freedesktop/systemd1",
545 "org.freedesktop.systemd1.Manager",
546 "StartTransientUnit");
548 return bus_log_create_error(r
);
550 r
= sd_bus_message_set_allow_interactive_authorization(m
, arg_ask_password
);
552 return bus_log_create_error(r
);
555 r
= sd_bus_message_append(m
, "ss", mount_unit
, "fail");
557 return bus_log_create_error(r
);
560 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
562 return bus_log_create_error(r
);
564 r
= transient_mount_set_properties(m
);
566 return bus_log_create_error(r
);
568 r
= sd_bus_message_close_container(m
);
570 return bus_log_create_error(r
);
572 /* Auxiliary units */
573 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
575 return bus_log_create_error(r
);
577 polkit_agent_open_if_enabled(arg_transport
, arg_ask_password
);
579 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
581 return log_error_errno(r
, "Failed to start transient mount unit: %s", bus_error_message(&error
, r
));
586 r
= sd_bus_message_read(reply
, "o", &object
);
588 return bus_log_parse_error(r
);
590 r
= bus_wait_for_jobs_one(w
, object
, arg_quiet
);
596 log_info("Started unit %s%s%s for mount point: %s%s%s",
597 ansi_highlight(), mount_unit
, ansi_normal(),
598 ansi_highlight(), arg_mount_where
, ansi_normal());
603 static int start_transient_automount(
607 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
608 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
609 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
610 _cleanup_free_
char *automount_unit
= NULL
, *mount_unit
= NULL
;
614 r
= bus_wait_for_jobs_new(bus
, &w
);
616 return log_error_errno(r
, "Could not watch jobs: %m");
619 r
= unit_name_from_path(arg_mount_where
, ".automount", &automount_unit
);
621 return log_error_errno(r
, "Failed to make automount unit name: %m");
623 r
= unit_name_from_path(arg_mount_where
, ".mount", &mount_unit
);
625 return log_error_errno(r
, "Failed to make mount unit name: %m");
627 r
= sd_bus_message_new_method_call(
630 "org.freedesktop.systemd1",
631 "/org/freedesktop/systemd1",
632 "org.freedesktop.systemd1.Manager",
633 "StartTransientUnit");
635 return bus_log_create_error(r
);
637 r
= sd_bus_message_set_allow_interactive_authorization(m
, arg_ask_password
);
639 return bus_log_create_error(r
);
642 r
= sd_bus_message_append(m
, "ss", automount_unit
, "fail");
644 return bus_log_create_error(r
);
647 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
649 return bus_log_create_error(r
);
651 r
= transient_automount_set_properties(m
);
653 return bus_log_create_error(r
);
655 r
= sd_bus_message_close_container(m
);
657 return bus_log_create_error(r
);
659 /* Auxiliary units */
660 r
= sd_bus_message_open_container(m
, 'a', "(sa(sv))");
662 return bus_log_create_error(r
);
664 r
= sd_bus_message_open_container(m
, 'r', "sa(sv)");
666 return bus_log_create_error(r
);
668 r
= sd_bus_message_append(m
, "s", mount_unit
);
670 return bus_log_create_error(r
);
672 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
674 return bus_log_create_error(r
);
676 r
= transient_mount_set_properties(m
);
678 return bus_log_create_error(r
);
680 r
= sd_bus_message_close_container(m
);
682 return bus_log_create_error(r
);
684 r
= sd_bus_message_close_container(m
);
686 return bus_log_create_error(r
);
688 r
= sd_bus_message_close_container(m
);
690 return bus_log_create_error(r
);
692 polkit_agent_open_if_enabled(arg_transport
, arg_ask_password
);
694 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
696 return log_error_errno(r
, "Failed to start transient automount unit: %s", bus_error_message(&error
, r
));
701 r
= sd_bus_message_read(reply
, "o", &object
);
703 return bus_log_parse_error(r
);
705 r
= bus_wait_for_jobs_one(w
, object
, arg_quiet
);
711 log_info("Started unit %s%s%s for mount point: %s%s%s",
712 ansi_highlight(), automount_unit
, ansi_normal(),
713 ansi_highlight(), arg_mount_where
, ansi_normal());
718 static int find_mount_points(const char *what
, char ***list
) {
719 _cleanup_fclose_
FILE *proc_self_mountinfo
= NULL
;
720 _cleanup_strv_free_
char **l
= NULL
;
721 size_t bufsize
= 0, n
= 0;
726 /* Returns all mount points obtained from /proc/self/mountinfo in *list,
727 * and the number of mount points as return value. */
729 proc_self_mountinfo
= fopen("/proc/self/mountinfo", "re");
730 if (!proc_self_mountinfo
)
731 return log_error_errno(errno
, "Can't open /proc/self/mountinfo: %m");
734 _cleanup_free_
char *path
= NULL
, *where
= NULL
, *dev
= NULL
;
737 r
= fscanf(proc_self_mountinfo
,
738 "%*s " /* (1) mount id */
739 "%*s " /* (2) parent id */
740 "%*s " /* (3) major:minor */
741 "%*s " /* (4) root */
742 "%ms " /* (5) mount point */
743 "%*s" /* (6) mount options */
744 "%*[^-]" /* (7) optional fields */
745 "- " /* (8) separator */
746 "%*s " /* (9) file system type */
747 "%ms" /* (10) mount source */
748 "%*s" /* (11) mount options 2 */
749 "%*[^\n]", /* some rubbish at the end */
758 if (!streq(what
, dev
))
761 r
= cunescape(path
, UNESCAPE_RELAX
, &where
);
765 /* one extra slot is needed for the terminating NULL */
766 if (!GREEDY_REALLOC(l
, bufsize
, n
+ 2))
769 l
[n
++] = TAKE_PTR(where
);
772 if (!GREEDY_REALLOC(l
, bufsize
, n
+ 1))
781 static int find_loop_device(const char *backing_file
, char **loop_dev
) {
782 _cleanup_closedir_
DIR *d
= NULL
;
784 _cleanup_free_
char *l
= NULL
;
786 assert(backing_file
);
789 d
= opendir("/sys/devices/virtual/block");
793 FOREACH_DIRENT(de
, d
, return -errno
) {
794 _cleanup_free_
char *sys
= NULL
, *fname
= NULL
;
797 dirent_ensure_type(d
, de
);
799 if (de
->d_type
!= DT_DIR
)
802 if (!startswith(de
->d_name
, "loop"))
805 sys
= strjoin("/sys/devices/virtual/block/", de
->d_name
, "/loop/backing_file");
809 r
= read_one_line_file(sys
, &fname
);
811 log_debug_errno(r
, "Failed to read %s, ignoring: %m", sys
);
815 if (files_same(fname
, backing_file
, 0) <= 0)
818 l
= strjoin("/dev/", de
->d_name
);
828 *loop_dev
= TAKE_PTR(l
);
833 static int stop_mount(
836 const char *suffix
) {
838 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
839 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
840 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
841 _cleanup_free_
char *mount_unit
= NULL
;
845 r
= bus_wait_for_jobs_new(bus
, &w
);
847 return log_error_errno(r
, "Could not watch jobs: %m");
850 r
= unit_name_from_path(where
, suffix
, &mount_unit
);
852 return log_error_errno(r
, "Failed to make %s unit name from path %s: %m", suffix
+ 1, where
);
854 r
= sd_bus_message_new_method_call(
857 "org.freedesktop.systemd1",
858 "/org/freedesktop/systemd1",
859 "org.freedesktop.systemd1.Manager",
862 return bus_log_create_error(r
);
864 r
= sd_bus_message_set_allow_interactive_authorization(m
, arg_ask_password
);
866 return bus_log_create_error(r
);
869 r
= sd_bus_message_append(m
, "ss", mount_unit
, "fail");
871 return bus_log_create_error(r
);
873 polkit_agent_open_if_enabled(arg_transport
, arg_ask_password
);
875 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
877 if (streq(suffix
, ".automount") &&
878 sd_bus_error_has_name(&error
, "org.freedesktop.systemd1.NoSuchUnit"))
880 return log_error_errno(r
, "Failed to stop %s unit: %s", suffix
+ 1, bus_error_message(&error
, r
));
886 r
= sd_bus_message_read(reply
, "o", &object
);
888 return bus_log_parse_error(r
);
890 r
= bus_wait_for_jobs_one(w
, object
, arg_quiet
);
896 log_info("Stopped unit %s%s%s for mount point: %s%s%s",
897 ansi_highlight(), mount_unit
, ansi_normal(),
898 ansi_highlight(), where
, ansi_normal());
903 static int stop_mounts(
909 if (path_equal(where
, "/")) {
910 log_error("Refusing to operate on root directory: %s", where
);
914 if (!path_is_normalized(where
)) {
915 log_error("Path contains non-normalized components: %s", where
);
919 r
= stop_mount(bus
, where
, ".mount");
923 r
= stop_mount(bus
, where
, ".automount");
930 static int umount_by_device(sd_bus
*bus
, const char *what
) {
931 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
932 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
933 _cleanup_strv_free_
char **list
= NULL
;
941 if (stat(what
, &st
) < 0)
942 return log_error_errno(errno
, "Can't stat %s: %m", what
);
944 if (!S_ISBLK(st
.st_mode
)) {
945 log_error("Not a block device: %s", what
);
953 d
= udev_device_new_from_devnum(udev
, 'b', st
.st_rdev
);
957 v
= udev_device_get_property_value(d
, "ID_FS_USAGE");
958 if (!streq_ptr(v
, "filesystem")) {
959 log_error("%s does not contain a known file system.", what
);
963 v
= udev_device_get_property_value(d
, "SYSTEMD_MOUNT_WHERE");
965 r2
= stop_mounts(bus
, v
);
967 r
= find_mount_points(what
, &list
);
971 for (l
= list
; *l
; l
++) {
972 r
= stop_mounts(bus
, *l
);
980 static int umount_loop(sd_bus
*bus
, const char *backing_file
) {
981 _cleanup_free_
char *loop_dev
= NULL
;
984 assert(backing_file
);
986 r
= find_loop_device(backing_file
, &loop_dev
);
988 return log_error_errno(r
, r
== -ENXIO
? "File %s is not mounted." : "Can't get loop device for %s: %m", backing_file
);
990 return umount_by_device(bus
, loop_dev
);
993 static int action_umount(
1000 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
1001 for (i
= optind
; i
< argc
; i
++) {
1002 _cleanup_free_
char *p
= NULL
;
1004 p
= strdup(argv
[i
]);
1008 path_kill_slashes(p
);
1010 r
= stop_mounts(bus
, p
);
1017 for (i
= optind
; i
< argc
; i
++) {
1018 _cleanup_free_
char *u
= NULL
, *p
= NULL
;
1021 u
= fstab_node_to_udev_node(argv
[i
]);
1025 r
= chase_symlinks(u
, NULL
, 0, &p
);
1027 r2
= log_error_errno(r
, "Failed to make path %s absolute: %m", argv
[i
]);
1031 if (stat(p
, &st
) < 0)
1032 return log_error_errno(errno
, "Can't stat %s (from %s): %m", p
, argv
[i
]);
1034 if (S_ISBLK(st
.st_mode
))
1035 r
= umount_by_device(bus
, p
);
1036 else if (S_ISREG(st
.st_mode
))
1037 r
= umount_loop(bus
, p
);
1038 else if (S_ISDIR(st
.st_mode
))
1039 r
= stop_mounts(bus
, p
);
1041 log_error("Invalid file type: %s (from %s)", p
, argv
[i
]);
1052 static int acquire_mount_type(struct udev_device
*d
) {
1060 v
= udev_device_get_property_value(d
, "ID_FS_TYPE");
1064 arg_mount_type
= strdup(v
);
1065 if (!arg_mount_type
)
1068 log_debug("Discovered type=%s", arg_mount_type
);
1072 static int acquire_mount_options(struct udev_device
*d
) {
1075 if (arg_mount_options
)
1078 v
= udev_device_get_property_value(d
, "SYSTEMD_MOUNT_OPTIONS");
1082 arg_mount_options
= strdup(v
);
1083 if (!arg_mount_options
)
1086 log_debug("Discovered options=%s", arg_mount_options
);
1090 static const char *get_model(struct udev_device
*d
) {
1095 model
= udev_device_get_property_value(d
, "ID_MODEL_FROM_DATABASE");
1099 return udev_device_get_property_value(d
, "ID_MODEL");
1102 static const char* get_label(struct udev_device
*d
) {
1107 label
= udev_device_get_property_value(d
, "ID_FS_LABEL");
1111 return udev_device_get_property_value(d
, "ID_PART_ENTRY_NAME");
1114 static int acquire_mount_where(struct udev_device
*d
) {
1117 if (arg_mount_where
)
1120 v
= udev_device_get_property_value(d
, "SYSTEMD_MOUNT_WHERE");
1122 _cleanup_free_
char *escaped
= NULL
;
1125 name
= get_label(d
);
1127 name
= get_model(d
);
1131 dn
= udev_device_get_devnode(d
);
1135 name
= basename(dn
);
1138 escaped
= xescape(name
, "\\");
1141 if (!filename_is_valid(escaped
))
1144 arg_mount_where
= strjoin("/run/media/system/", escaped
);
1146 arg_mount_where
= strdup(v
);
1148 if (!arg_mount_where
)
1151 log_debug("Discovered where=%s", arg_mount_where
);
1155 static int acquire_mount_where_for_loop_dev(const char *loop_dev
) {
1156 _cleanup_strv_free_
char **list
= NULL
;
1159 if (arg_mount_where
)
1162 r
= find_mount_points(loop_dev
, &list
);
1166 log_error("Can't find mount point of %s. It is expected that %s is already mounted on a place.", loop_dev
, loop_dev
);
1168 } else if (r
>= 2) {
1169 log_error("%s is mounted on %d places. It is expected that %s is mounted on a place.", loop_dev
, r
, loop_dev
);
1173 arg_mount_where
= strdup(list
[0]);
1174 if (!arg_mount_where
)
1177 log_debug("Discovered where=%s", arg_mount_where
);
1181 static int acquire_description(struct udev_device
*d
) {
1182 const char *model
, *label
;
1184 if (arg_description
)
1187 model
= get_model(d
);
1189 label
= get_label(d
);
1191 label
= udev_device_get_property_value(d
, "ID_PART_ENTRY_NUMBER");
1194 arg_description
= strjoin(model
, " ", label
);
1196 arg_description
= strdup(label
);
1198 arg_description
= strdup(model
);
1202 if (!arg_description
)
1205 log_debug("Discovered description=%s", arg_description
);
1209 static int acquire_removable(struct udev_device
*d
) {
1212 /* Shortcut this if there's no reason to check it */
1213 if (arg_action
!= ACTION_DEFAULT
&& arg_timeout_idle_set
&& arg_bind_device
>= 0)
1217 v
= udev_device_get_sysattr_value(d
, "removable");
1221 d
= udev_device_get_parent(d
);
1225 if (!streq_ptr(udev_device_get_subsystem(d
), "block"))
1229 if (parse_boolean(v
) <= 0)
1232 log_debug("Discovered removable device.");
1234 if (arg_action
== ACTION_DEFAULT
) {
1235 log_debug("Automatically turning on automount.");
1236 arg_action
= ACTION_AUTOMOUNT
;
1239 if (!arg_timeout_idle_set
) {
1240 log_debug("Setting idle timeout to 1s.");
1241 arg_timeout_idle
= USEC_PER_SEC
;
1244 if (arg_bind_device
< 0) {
1245 log_debug("Binding automount unit to device.");
1246 arg_bind_device
= true;
1252 static int discover_loop_backing_file(void) {
1253 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
1254 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
1255 _cleanup_free_
char *loop_dev
= NULL
;
1260 r
= find_loop_device(arg_mount_what
, &loop_dev
);
1261 if (r
< 0 && r
!= -ENXIO
)
1262 return log_error_errno(errno
, "Can't get loop device for %s: %m", arg_mount_what
);
1265 _cleanup_free_
char *escaped
= NULL
;
1267 if (arg_mount_where
)
1270 escaped
= xescape(basename(arg_mount_what
), "\\");
1273 if (!filename_is_valid(escaped
)) {
1274 log_error("Escaped name %s is not a valid filename.", escaped
);
1278 arg_mount_where
= strjoin("/run/media/system/", escaped
);
1279 if (!arg_mount_where
)
1282 log_debug("Discovered where=%s", arg_mount_where
);
1286 if (stat(loop_dev
, &st
) < 0)
1287 return log_error_errno(errno
, "Can't stat %s: %m", loop_dev
);
1289 if (!S_ISBLK(st
.st_mode
)) {
1290 log_error("Invalid file type: %s", loop_dev
);
1298 d
= udev_device_new_from_devnum(udev
, 'b', st
.st_rdev
);
1302 v
= udev_device_get_property_value(d
, "ID_FS_USAGE");
1303 if (!streq_ptr(v
, "filesystem")) {
1304 log_error("%s does not contain a known file system.", arg_mount_what
);
1308 r
= acquire_mount_type(d
);
1312 r
= acquire_mount_options(d
);
1316 r
= acquire_mount_where_for_loop_dev(loop_dev
);
1320 r
= acquire_description(d
);
1327 static int discover_device(void) {
1328 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
1329 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
1334 if (stat(arg_mount_what
, &st
) < 0)
1335 return log_error_errno(errno
, "Can't stat %s: %m", arg_mount_what
);
1337 if (S_ISREG(st
.st_mode
))
1338 return discover_loop_backing_file();
1340 if (!S_ISBLK(st
.st_mode
)) {
1341 log_error("Invalid file type: %s", arg_mount_what
);
1349 d
= udev_device_new_from_devnum(udev
, 'b', st
.st_rdev
);
1353 v
= udev_device_get_property_value(d
, "ID_FS_USAGE");
1354 if (!streq_ptr(v
, "filesystem")) {
1355 log_error("%s does not contain a known file system.", arg_mount_what
);
1359 r
= acquire_mount_type(d
);
1363 r
= acquire_mount_options(d
);
1367 r
= acquire_mount_where(d
);
1371 r
= acquire_description(d
);
1375 r
= acquire_removable(d
);
1394 char* columns
[_COLUMN_MAX
];
1397 static int compare_item(const void *a
, const void *b
) {
1398 const struct item
*x
= a
, *y
= b
;
1400 if (x
->columns
[COLUMN_NODE
] == y
->columns
[COLUMN_NODE
])
1402 if (!x
->columns
[COLUMN_NODE
])
1404 if (!y
->columns
[COLUMN_NODE
])
1407 return path_compare(x
->columns
[COLUMN_NODE
], y
->columns
[COLUMN_NODE
]);
1410 static int list_devices(void) {
1412 static const char * const titles
[_COLUMN_MAX
] = {
1413 [COLUMN_NODE
] = "NODE",
1414 [COLUMN_PATH
] = "PATH",
1415 [COLUMN_MODEL
] = "MODEL",
1416 [COLUMN_WWN
] = "WWN",
1417 [COLUMN_FSTYPE
] = "TYPE",
1418 [COLUMN_LABEL
] = "LABEL",
1419 [COLUMN_UUID
] = "UUID"
1422 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
1423 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
1424 struct udev_list_entry
*item
= NULL
, *first
= NULL
;
1425 size_t n_allocated
= 0, n
= 0, i
;
1426 size_t column_width
[_COLUMN_MAX
];
1427 struct item
*items
= NULL
;
1431 for (c
= 0; c
< _COLUMN_MAX
; c
++)
1432 column_width
[c
] = strlen(titles
[c
]);
1438 e
= udev_enumerate_new(udev
);
1442 r
= udev_enumerate_add_match_subsystem(e
, "block");
1444 return log_error_errno(r
, "Failed to add block match: %m");
1446 r
= udev_enumerate_add_match_property(e
, "ID_FS_USAGE", "filesystem");
1448 return log_error_errno(r
, "Failed to add property match: %m");
1450 r
= udev_enumerate_scan_devices(e
);
1452 return log_error_errno(r
, "Failed to scan devices: %m");
1454 first
= udev_enumerate_get_list_entry(e
);
1455 udev_list_entry_foreach(item
, first
) {
1456 _cleanup_udev_device_unref_
struct udev_device
*d
;
1459 d
= udev_device_new_from_syspath(udev
, udev_list_entry_get_name(item
));
1465 if (!GREEDY_REALLOC0(items
, n_allocated
, n
+1)) {
1472 for (c
= 0; c
< _COLUMN_MAX
; c
++) {
1473 const char *x
= NULL
;
1479 x
= udev_device_get_devnode(d
);
1483 x
= udev_device_get_property_value(d
, "ID_PATH");
1491 x
= udev_device_get_property_value(d
, "ID_WWN");
1495 x
= udev_device_get_property_value(d
, "ID_FS_TYPE");
1503 x
= udev_device_get_property_value(d
, "ID_FS_UUID");
1510 j
->columns
[c
] = strdup(x
);
1511 if (!j
->columns
[c
]) {
1517 if (k
> column_width
[c
])
1518 column_width
[c
] = k
;
1523 log_info("No devices found.");
1527 qsort_safe(items
, n
, sizeof(struct item
), compare_item
);
1529 (void) pager_open(arg_no_pager
, false);
1531 fputs(ansi_underline(), stdout
);
1532 for (c
= 0; c
< _COLUMN_MAX
; c
++) {
1536 printf("%-*s", (int) column_width
[c
], titles
[c
]);
1538 fputs(ansi_normal(), stdout
);
1539 fputc('\n', stdout
);
1541 for (i
= 0; i
< n
; i
++) {
1542 for (c
= 0; c
< _COLUMN_MAX
; c
++) {
1546 printf("%-*s", (int) column_width
[c
], strna(items
[i
].columns
[c
]));
1548 fputc('\n', stdout
);
1554 for (i
= 0; i
< n
; i
++)
1555 for (c
= 0; c
< _COLUMN_MAX
; c
++)
1556 free(items
[i
].columns
[c
]);
1562 int main(int argc
, char* argv
[]) {
1566 log_parse_environment();
1569 r
= parse_argv(argc
, argv
);
1573 if (arg_action
== ACTION_LIST
) {
1578 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, arg_user
, &bus
);
1580 log_error_errno(r
, "Failed to create bus connection: %m");
1584 if (arg_action
== ACTION_UMOUNT
) {
1585 r
= action_umount(bus
, argc
, argv
);
1589 if (!path_is_normalized(arg_mount_what
)) {
1590 log_error("Path contains non-normalized components: %s", arg_mount_what
);
1596 r
= discover_device();
1601 if (!arg_mount_where
) {
1602 log_error("Can't figure out where to mount %s.", arg_mount_what
);
1607 if (path_equal(arg_mount_where
, "/")) {
1608 log_error("Refusing to operate on root directory.");
1613 if (!path_is_normalized(arg_mount_where
)) {
1614 log_error("Path contains non-normalized components: %s", arg_mount_where
);
1619 if (streq_ptr(arg_mount_type
, "auto"))
1620 arg_mount_type
= mfree(arg_mount_type
);
1621 if (streq_ptr(arg_mount_options
, "defaults"))
1622 arg_mount_options
= mfree(arg_mount_options
);
1624 if (!is_device_path(arg_mount_what
))
1627 if (arg_fsck
&& arg_mount_type
&& arg_transport
== BUS_TRANSPORT_LOCAL
) {
1628 r
= fsck_exists(arg_mount_type
);
1630 log_warning_errno(r
, "Couldn't determine whether fsck for %s exists, proceeding anyway.", arg_mount_type
);
1632 log_debug("Disabling file system check as fsck for %s doesn't exist.", arg_mount_type
);
1633 arg_fsck
= false; /* fsck doesn't exist, let's not attempt it */
1637 /* The kernel (properly) refuses mounting file systems with unknown uid=,gid= options,
1638 * but not for all filesystem types. Let's try to catch the cases where the option
1639 * would be used if the file system does not support it. It is also possible to
1640 * autodetect the file system, but that's only possible with disk-based file systems
1641 * which incidentally seem to be implemented more carefully and reject unknown options,
1642 * so it's probably OK that we do the check only when the type is specified.
1644 if (arg_mount_type
&&
1645 !streq(arg_mount_type
, "auto") &&
1646 arg_uid
!= UID_INVALID
&&
1647 !fstype_can_uid_gid(arg_mount_type
)) {
1648 log_error("File system type %s is not known to support uid=/gid=, refusing.",
1654 switch (arg_action
) {
1657 case ACTION_DEFAULT
:
1658 r
= start_transient_mount(bus
, argv
+ optind
);
1661 case ACTION_AUTOMOUNT
:
1662 r
= start_transient_automount(bus
, argv
+ optind
);
1666 assert_not_reached("Unexpected action.");
1670 /* make sure we terminate the bus connection first, and then close the
1671 * pager, see issue #3543 for the details. */
1672 bus
= sd_bus_flush_close_unref(bus
);
1675 free(arg_mount_what
);
1676 free(arg_mount_where
);
1677 free(arg_mount_type
);
1678 free(arg_mount_options
);
1679 free(arg_description
);
1680 strv_free(arg_property
);
1681 strv_free(arg_automount_property
);
1683 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;