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))
773 if (!GREEDY_REALLOC(l
, bufsize
, n
+ 1))
778 l
= NULL
; /* avoid freeing */
783 static int find_loop_device(const char *backing_file
, char **loop_dev
) {
784 _cleanup_closedir_
DIR *d
= NULL
;
786 _cleanup_free_
char *l
= NULL
;
788 assert(backing_file
);
791 d
= opendir("/sys/devices/virtual/block");
795 FOREACH_DIRENT(de
, d
, return -errno
) {
796 _cleanup_free_
char *sys
= NULL
, *fname
= NULL
;
799 dirent_ensure_type(d
, de
);
801 if (de
->d_type
!= DT_DIR
)
804 if (!startswith(de
->d_name
, "loop"))
807 sys
= strjoin("/sys/devices/virtual/block/", de
->d_name
, "/loop/backing_file");
811 r
= read_one_line_file(sys
, &fname
);
813 log_debug_errno(r
, "Failed to read %s, ignoring: %m", sys
);
817 if (files_same(fname
, backing_file
, 0) <= 0)
820 l
= strjoin("/dev/", de
->d_name
);
831 l
= NULL
; /* avoid freeing */
836 static int stop_mount(
839 const char *suffix
) {
841 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
842 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
843 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
844 _cleanup_free_
char *mount_unit
= NULL
;
848 r
= bus_wait_for_jobs_new(bus
, &w
);
850 return log_error_errno(r
, "Could not watch jobs: %m");
853 r
= unit_name_from_path(where
, suffix
, &mount_unit
);
855 return log_error_errno(r
, "Failed to make %s unit name from path %s: %m", suffix
+ 1, where
);
857 r
= sd_bus_message_new_method_call(
860 "org.freedesktop.systemd1",
861 "/org/freedesktop/systemd1",
862 "org.freedesktop.systemd1.Manager",
865 return bus_log_create_error(r
);
867 r
= sd_bus_message_set_allow_interactive_authorization(m
, arg_ask_password
);
869 return bus_log_create_error(r
);
872 r
= sd_bus_message_append(m
, "ss", mount_unit
, "fail");
874 return bus_log_create_error(r
);
876 polkit_agent_open_if_enabled(arg_transport
, arg_ask_password
);
878 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
880 if (streq(suffix
, ".automount") &&
881 sd_bus_error_has_name(&error
, "org.freedesktop.systemd1.NoSuchUnit"))
883 return log_error_errno(r
, "Failed to stop %s unit: %s", suffix
+ 1, bus_error_message(&error
, r
));
889 r
= sd_bus_message_read(reply
, "o", &object
);
891 return bus_log_parse_error(r
);
893 r
= bus_wait_for_jobs_one(w
, object
, arg_quiet
);
899 log_info("Stopped unit %s%s%s for mount point: %s%s%s",
900 ansi_highlight(), mount_unit
, ansi_normal(),
901 ansi_highlight(), where
, ansi_normal());
906 static int stop_mounts(
912 if (path_equal(where
, "/")) {
913 log_error("Refusing to operate on root directory: %s", where
);
917 if (!path_is_normalized(where
)) {
918 log_error("Path contains non-normalized components: %s", where
);
922 r
= stop_mount(bus
, where
, ".mount");
926 r
= stop_mount(bus
, where
, ".automount");
933 static int umount_by_device(sd_bus
*bus
, const char *what
) {
934 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
935 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
936 _cleanup_strv_free_
char **list
= NULL
;
944 if (stat(what
, &st
) < 0)
945 return log_error_errno(errno
, "Can't stat %s: %m", what
);
947 if (!S_ISBLK(st
.st_mode
)) {
948 log_error("Not a block device: %s", what
);
956 d
= udev_device_new_from_devnum(udev
, 'b', st
.st_rdev
);
960 v
= udev_device_get_property_value(d
, "ID_FS_USAGE");
961 if (!streq_ptr(v
, "filesystem")) {
962 log_error("%s does not contain a known file system.", what
);
966 v
= udev_device_get_property_value(d
, "SYSTEMD_MOUNT_WHERE");
968 r2
= stop_mounts(bus
, v
);
970 r
= find_mount_points(what
, &list
);
974 for (l
= list
; *l
; l
++) {
975 r
= stop_mounts(bus
, *l
);
983 static int umount_loop(sd_bus
*bus
, const char *backing_file
) {
984 _cleanup_free_
char *loop_dev
= NULL
;
987 assert(backing_file
);
989 r
= find_loop_device(backing_file
, &loop_dev
);
991 return log_error_errno(r
, r
== -ENXIO
? "File %s is not mounted." : "Can't get loop device for %s: %m", backing_file
);
993 return umount_by_device(bus
, loop_dev
);
996 static int action_umount(
1003 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
1004 for (i
= optind
; i
< argc
; i
++) {
1005 _cleanup_free_
char *p
= NULL
;
1007 p
= strdup(argv
[i
]);
1011 path_kill_slashes(p
);
1013 r
= stop_mounts(bus
, p
);
1020 for (i
= optind
; i
< argc
; i
++) {
1021 _cleanup_free_
char *u
= NULL
, *p
= NULL
;
1024 u
= fstab_node_to_udev_node(argv
[i
]);
1028 r
= chase_symlinks(u
, NULL
, 0, &p
);
1030 r2
= log_error_errno(r
, "Failed to make path %s absolute: %m", argv
[i
]);
1034 if (stat(p
, &st
) < 0)
1035 return log_error_errno(errno
, "Can't stat %s (from %s): %m", p
, argv
[i
]);
1037 if (S_ISBLK(st
.st_mode
))
1038 r
= umount_by_device(bus
, p
);
1039 else if (S_ISREG(st
.st_mode
))
1040 r
= umount_loop(bus
, p
);
1041 else if (S_ISDIR(st
.st_mode
))
1042 r
= stop_mounts(bus
, p
);
1044 log_error("Invalid file type: %s (from %s)", p
, argv
[i
]);
1055 static int acquire_mount_type(struct udev_device
*d
) {
1063 v
= udev_device_get_property_value(d
, "ID_FS_TYPE");
1067 arg_mount_type
= strdup(v
);
1068 if (!arg_mount_type
)
1071 log_debug("Discovered type=%s", arg_mount_type
);
1075 static int acquire_mount_options(struct udev_device
*d
) {
1078 if (arg_mount_options
)
1081 v
= udev_device_get_property_value(d
, "SYSTEMD_MOUNT_OPTIONS");
1085 arg_mount_options
= strdup(v
);
1086 if (!arg_mount_options
)
1089 log_debug("Discovered options=%s", arg_mount_options
);
1093 static const char *get_model(struct udev_device
*d
) {
1098 model
= udev_device_get_property_value(d
, "ID_MODEL_FROM_DATABASE");
1102 return udev_device_get_property_value(d
, "ID_MODEL");
1105 static const char* get_label(struct udev_device
*d
) {
1110 label
= udev_device_get_property_value(d
, "ID_FS_LABEL");
1114 return udev_device_get_property_value(d
, "ID_PART_ENTRY_NAME");
1117 static int acquire_mount_where(struct udev_device
*d
) {
1120 if (arg_mount_where
)
1123 v
= udev_device_get_property_value(d
, "SYSTEMD_MOUNT_WHERE");
1125 _cleanup_free_
char *escaped
= NULL
;
1128 name
= get_label(d
);
1130 name
= get_model(d
);
1134 dn
= udev_device_get_devnode(d
);
1138 name
= basename(dn
);
1141 escaped
= xescape(name
, "\\");
1144 if (!filename_is_valid(escaped
))
1147 arg_mount_where
= strjoin("/run/media/system/", escaped
);
1149 arg_mount_where
= strdup(v
);
1151 if (!arg_mount_where
)
1154 log_debug("Discovered where=%s", arg_mount_where
);
1158 static int acquire_mount_where_for_loop_dev(const char *loop_dev
) {
1159 _cleanup_strv_free_
char **list
= NULL
;
1162 if (arg_mount_where
)
1165 r
= find_mount_points(loop_dev
, &list
);
1169 log_error("Can't find mount point of %s. It is expected that %s is already mounted on a place.", loop_dev
, loop_dev
);
1171 } else if (r
>= 2) {
1172 log_error("%s is mounted on %d places. It is expected that %s is mounted on a place.", loop_dev
, r
, loop_dev
);
1176 arg_mount_where
= strdup(list
[0]);
1177 if (!arg_mount_where
)
1180 log_debug("Discovered where=%s", arg_mount_where
);
1184 static int acquire_description(struct udev_device
*d
) {
1185 const char *model
, *label
;
1187 if (arg_description
)
1190 model
= get_model(d
);
1192 label
= get_label(d
);
1194 label
= udev_device_get_property_value(d
, "ID_PART_ENTRY_NUMBER");
1197 arg_description
= strjoin(model
, " ", label
);
1199 arg_description
= strdup(label
);
1201 arg_description
= strdup(model
);
1205 if (!arg_description
)
1208 log_debug("Discovered description=%s", arg_description
);
1212 static int acquire_removable(struct udev_device
*d
) {
1215 /* Shortcut this if there's no reason to check it */
1216 if (arg_action
!= ACTION_DEFAULT
&& arg_timeout_idle_set
&& arg_bind_device
>= 0)
1220 v
= udev_device_get_sysattr_value(d
, "removable");
1224 d
= udev_device_get_parent(d
);
1228 if (!streq_ptr(udev_device_get_subsystem(d
), "block"))
1232 if (parse_boolean(v
) <= 0)
1235 log_debug("Discovered removable device.");
1237 if (arg_action
== ACTION_DEFAULT
) {
1238 log_debug("Automatically turning on automount.");
1239 arg_action
= ACTION_AUTOMOUNT
;
1242 if (!arg_timeout_idle_set
) {
1243 log_debug("Setting idle timeout to 1s.");
1244 arg_timeout_idle
= USEC_PER_SEC
;
1247 if (arg_bind_device
< 0) {
1248 log_debug("Binding automount unit to device.");
1249 arg_bind_device
= true;
1255 static int discover_loop_backing_file(void) {
1256 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
1257 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
1258 _cleanup_free_
char *loop_dev
= NULL
;
1263 r
= find_loop_device(arg_mount_what
, &loop_dev
);
1264 if (r
< 0 && r
!= -ENXIO
)
1265 return log_error_errno(errno
, "Can't get loop device for %s: %m", arg_mount_what
);
1268 _cleanup_free_
char *escaped
= NULL
;
1270 if (arg_mount_where
)
1273 escaped
= xescape(basename(arg_mount_what
), "\\");
1276 if (!filename_is_valid(escaped
)) {
1277 log_error("Escaped name %s is not a valid filename.", escaped
);
1281 arg_mount_where
= strjoin("/run/media/system/", escaped
);
1282 if (!arg_mount_where
)
1285 log_debug("Discovered where=%s", arg_mount_where
);
1289 if (stat(loop_dev
, &st
) < 0)
1290 return log_error_errno(errno
, "Can't stat %s: %m", loop_dev
);
1292 if (!S_ISBLK(st
.st_mode
)) {
1293 log_error("Invalid file type: %s", loop_dev
);
1301 d
= udev_device_new_from_devnum(udev
, 'b', st
.st_rdev
);
1305 v
= udev_device_get_property_value(d
, "ID_FS_USAGE");
1306 if (!streq_ptr(v
, "filesystem")) {
1307 log_error("%s does not contain a known file system.", arg_mount_what
);
1311 r
= acquire_mount_type(d
);
1315 r
= acquire_mount_options(d
);
1319 r
= acquire_mount_where_for_loop_dev(loop_dev
);
1323 r
= acquire_description(d
);
1330 static int discover_device(void) {
1331 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
1332 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
1337 if (stat(arg_mount_what
, &st
) < 0)
1338 return log_error_errno(errno
, "Can't stat %s: %m", arg_mount_what
);
1340 if (S_ISREG(st
.st_mode
))
1341 return discover_loop_backing_file();
1343 if (!S_ISBLK(st
.st_mode
)) {
1344 log_error("Invalid file type: %s", arg_mount_what
);
1352 d
= udev_device_new_from_devnum(udev
, 'b', st
.st_rdev
);
1356 v
= udev_device_get_property_value(d
, "ID_FS_USAGE");
1357 if (!streq_ptr(v
, "filesystem")) {
1358 log_error("%s does not contain a known file system.", arg_mount_what
);
1362 r
= acquire_mount_type(d
);
1366 r
= acquire_mount_options(d
);
1370 r
= acquire_mount_where(d
);
1374 r
= acquire_description(d
);
1378 r
= acquire_removable(d
);
1397 char* columns
[_COLUMN_MAX
];
1400 static int compare_item(const void *a
, const void *b
) {
1401 const struct item
*x
= a
, *y
= b
;
1403 if (x
->columns
[COLUMN_NODE
] == y
->columns
[COLUMN_NODE
])
1405 if (!x
->columns
[COLUMN_NODE
])
1407 if (!y
->columns
[COLUMN_NODE
])
1410 return path_compare(x
->columns
[COLUMN_NODE
], y
->columns
[COLUMN_NODE
]);
1413 static int list_devices(void) {
1415 static const char * const titles
[_COLUMN_MAX
] = {
1416 [COLUMN_NODE
] = "NODE",
1417 [COLUMN_PATH
] = "PATH",
1418 [COLUMN_MODEL
] = "MODEL",
1419 [COLUMN_WWN
] = "WWN",
1420 [COLUMN_FSTYPE
] = "TYPE",
1421 [COLUMN_LABEL
] = "LABEL",
1422 [COLUMN_UUID
] = "UUID"
1425 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
1426 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
1427 struct udev_list_entry
*item
= NULL
, *first
= NULL
;
1428 size_t n_allocated
= 0, n
= 0, i
;
1429 size_t column_width
[_COLUMN_MAX
];
1430 struct item
*items
= NULL
;
1434 for (c
= 0; c
< _COLUMN_MAX
; c
++)
1435 column_width
[c
] = strlen(titles
[c
]);
1441 e
= udev_enumerate_new(udev
);
1445 r
= udev_enumerate_add_match_subsystem(e
, "block");
1447 return log_error_errno(r
, "Failed to add block match: %m");
1449 r
= udev_enumerate_add_match_property(e
, "ID_FS_USAGE", "filesystem");
1451 return log_error_errno(r
, "Failed to add property match: %m");
1453 r
= udev_enumerate_scan_devices(e
);
1455 return log_error_errno(r
, "Failed to scan devices: %m");
1457 first
= udev_enumerate_get_list_entry(e
);
1458 udev_list_entry_foreach(item
, first
) {
1459 _cleanup_udev_device_unref_
struct udev_device
*d
;
1462 d
= udev_device_new_from_syspath(udev
, udev_list_entry_get_name(item
));
1468 if (!GREEDY_REALLOC0(items
, n_allocated
, n
+1)) {
1475 for (c
= 0; c
< _COLUMN_MAX
; c
++) {
1476 const char *x
= NULL
;
1482 x
= udev_device_get_devnode(d
);
1486 x
= udev_device_get_property_value(d
, "ID_PATH");
1494 x
= udev_device_get_property_value(d
, "ID_WWN");
1498 x
= udev_device_get_property_value(d
, "ID_FS_TYPE");
1506 x
= udev_device_get_property_value(d
, "ID_FS_UUID");
1513 j
->columns
[c
] = strdup(x
);
1514 if (!j
->columns
[c
]) {
1520 if (k
> column_width
[c
])
1521 column_width
[c
] = k
;
1526 log_info("No devices found.");
1530 qsort_safe(items
, n
, sizeof(struct item
), compare_item
);
1532 pager_open(arg_no_pager
, false);
1534 fputs(ansi_underline(), stdout
);
1535 for (c
= 0; c
< _COLUMN_MAX
; c
++) {
1539 printf("%-*s", (int) column_width
[c
], titles
[c
]);
1541 fputs(ansi_normal(), stdout
);
1542 fputc('\n', stdout
);
1544 for (i
= 0; i
< n
; i
++) {
1545 for (c
= 0; c
< _COLUMN_MAX
; c
++) {
1549 printf("%-*s", (int) column_width
[c
], strna(items
[i
].columns
[c
]));
1551 fputc('\n', stdout
);
1557 for (i
= 0; i
< n
; i
++)
1558 for (c
= 0; c
< _COLUMN_MAX
; c
++)
1559 free(items
[i
].columns
[c
]);
1565 int main(int argc
, char* argv
[]) {
1569 log_parse_environment();
1572 r
= parse_argv(argc
, argv
);
1576 if (arg_action
== ACTION_LIST
) {
1581 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, arg_user
, &bus
);
1583 log_error_errno(r
, "Failed to create bus connection: %m");
1587 if (arg_action
== ACTION_UMOUNT
) {
1588 r
= action_umount(bus
, argc
, argv
);
1592 if (!path_is_normalized(arg_mount_what
)) {
1593 log_error("Path contains non-normalized components: %s", arg_mount_what
);
1599 r
= discover_device();
1604 if (!arg_mount_where
) {
1605 log_error("Can't figure out where to mount %s.", arg_mount_what
);
1610 if (path_equal(arg_mount_where
, "/")) {
1611 log_error("Refusing to operate on root directory.");
1616 if (!path_is_normalized(arg_mount_where
)) {
1617 log_error("Path contains non-normalized components: %s", arg_mount_where
);
1622 if (streq_ptr(arg_mount_type
, "auto"))
1623 arg_mount_type
= mfree(arg_mount_type
);
1624 if (streq_ptr(arg_mount_options
, "defaults"))
1625 arg_mount_options
= mfree(arg_mount_options
);
1627 if (!is_device_path(arg_mount_what
))
1630 if (arg_fsck
&& arg_mount_type
&& arg_transport
== BUS_TRANSPORT_LOCAL
) {
1631 r
= fsck_exists(arg_mount_type
);
1633 log_warning_errno(r
, "Couldn't determine whether fsck for %s exists, proceeding anyway.", arg_mount_type
);
1635 log_debug("Disabling file system check as fsck for %s doesn't exist.", arg_mount_type
);
1636 arg_fsck
= false; /* fsck doesn't exist, let's not attempt it */
1640 /* The kernel (properly) refuses mounting file systems with unknown uid=,gid= options,
1641 * but not for all filesystem types. Let's try to catch the cases where the option
1642 * would be used if the file system does not support it. It is also possible to
1643 * autodetect the file system, but that's only possible with disk-based file systems
1644 * which incidentally seem to be implemented more carefully and reject unknown options,
1645 * so it's probably OK that we do the check only when the type is specified.
1647 if (arg_mount_type
&&
1648 !streq(arg_mount_type
, "auto") &&
1649 arg_uid
!= UID_INVALID
&&
1650 !fstype_can_uid_gid(arg_mount_type
)) {
1651 log_error("File system type %s is not known to support uid=/gid=, refusing.",
1657 switch (arg_action
) {
1660 case ACTION_DEFAULT
:
1661 r
= start_transient_mount(bus
, argv
+ optind
);
1664 case ACTION_AUTOMOUNT
:
1665 r
= start_transient_automount(bus
, argv
+ optind
);
1669 assert_not_reached("Unexpected action.");
1673 /* make sure we terminate the bus connection first, and then close the
1674 * pager, see issue #3543 for the details. */
1675 bus
= sd_bus_flush_close_unref(bus
);
1678 free(arg_mount_what
);
1679 free(arg_mount_where
);
1680 free(arg_mount_type
);
1681 free(arg_mount_options
);
1682 free(arg_description
);
1683 strv_free(arg_property
);
1684 strv_free(arg_automount_property
);
1686 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;