]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/mount/mount-tool.c
mount-tool: rely on format-table.c's ersatz logic
[thirdparty/systemd.git] / src / mount / mount-tool.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <getopt.h>
4
5 #include "sd-bus.h"
6 #include "sd-device.h"
7
8 #include "build.h"
9 #include "bus-error.h"
10 #include "bus-locator.h"
11 #include "bus-unit-util.h"
12 #include "bus-wait-for-jobs.h"
13 #include "chase.h"
14 #include "device-util.h"
15 #include "dirent-util.h"
16 #include "escape.h"
17 #include "fd-util.h"
18 #include "fileio.h"
19 #include "format-table.h"
20 #include "format-util.h"
21 #include "fs-util.h"
22 #include "fstab-util.h"
23 #include "libmount-util.h"
24 #include "main-func.h"
25 #include "mount-util.h"
26 #include "mountpoint-util.h"
27 #include "pager.h"
28 #include "parse-argument.h"
29 #include "parse-util.h"
30 #include "path-util.h"
31 #include "pretty-print.h"
32 #include "process-util.h"
33 #include "sort-util.h"
34 #include "spawn-polkit-agent.h"
35 #include "stat-util.h"
36 #include "strv.h"
37 #include "terminal-util.h"
38 #include "umask-util.h"
39 #include "unit-def.h"
40 #include "unit-name.h"
41 #include "user-util.h"
42
43 enum {
44 ACTION_DEFAULT,
45 ACTION_MOUNT,
46 ACTION_AUTOMOUNT,
47 ACTION_UMOUNT,
48 ACTION_LIST,
49 } arg_action = ACTION_DEFAULT;
50
51 static bool arg_no_block = false;
52 static PagerFlags arg_pager_flags = 0;
53 static bool arg_legend = true;
54 static bool arg_full = false;
55 static bool arg_ask_password = true;
56 static bool arg_quiet = false;
57 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
58 static RuntimeScope arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
59 static const char *arg_host = NULL;
60 static bool arg_discover = false;
61 static char *arg_mount_what = NULL;
62 static char *arg_mount_where = NULL;
63 static char *arg_mount_type = NULL;
64 static char *arg_mount_options = NULL;
65 static char *arg_description = NULL;
66 static char **arg_property = NULL;
67 static usec_t arg_timeout_idle = USEC_INFINITY;
68 static bool arg_timeout_idle_set = false;
69 static char **arg_automount_property = NULL;
70 static int arg_bind_device = -1;
71 static uid_t arg_uid = UID_INVALID;
72 static gid_t arg_gid = GID_INVALID;
73 static bool arg_fsck = true;
74 static bool arg_aggressive_gc = false;
75 static bool arg_tmpfs = false;
76
77 STATIC_DESTRUCTOR_REGISTER(arg_mount_what, freep);
78 STATIC_DESTRUCTOR_REGISTER(arg_mount_where, freep);
79 STATIC_DESTRUCTOR_REGISTER(arg_mount_type, freep);
80 STATIC_DESTRUCTOR_REGISTER(arg_mount_options, freep);
81 STATIC_DESTRUCTOR_REGISTER(arg_description, freep);
82 STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep);
83 STATIC_DESTRUCTOR_REGISTER(arg_automount_property, strv_freep);
84
85 static int parse_where(const char *input, char **ret_where) {
86 int r;
87
88 assert(input);
89 assert(ret_where);
90
91 if (arg_transport == BUS_TRANSPORT_LOCAL) {
92 r = chase(input, NULL, CHASE_NONEXISTENT, ret_where, NULL);
93 if (r < 0)
94 return log_error_errno(r, "Failed to make path %s absolute: %m", input);
95 } else {
96 if (!path_is_absolute(input))
97 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
98 "Path must be absolute when operating remotely: %s",
99 input);
100
101 r = path_simplify_alloc(input, ret_where);
102 if (r < 0)
103 return log_error_errno(r, "Failed to simplify path %s: %m", input);
104 }
105
106 return 0;
107 }
108
109 static int help(void) {
110 _cleanup_free_ char *link = NULL;
111 int r;
112
113 r = terminal_urlify_man("systemd-mount", "1", &link);
114 if (r < 0)
115 return log_oom();
116
117 printf("systemd-mount [OPTIONS...] WHAT [WHERE]\n"
118 "systemd-mount [OPTIONS...] --tmpfs [NAME] WHERE\n"
119 "systemd-mount [OPTIONS...] --list\n"
120 "%s [OPTIONS...] %sWHAT|WHERE...\n\n"
121 "Establish a mount or auto-mount point transiently.\n\n"
122 " -h --help Show this help\n"
123 " --version Show package version\n"
124 " --no-block Do not wait until operation finished\n"
125 " --no-pager Do not pipe output into a pager\n"
126 " --no-legend Do not show the headers\n"
127 " -l --full Do not ellipsize output\n"
128 " --no-ask-password Do not prompt for password\n"
129 " -q --quiet Suppress information messages during runtime\n"
130 " --user Run as user unit\n"
131 " -H --host=[USER@]HOST Operate on remote host\n"
132 " -M --machine=CONTAINER Operate on local container\n"
133 " --discover Discover mount device metadata\n"
134 " -t --type=TYPE File system type\n"
135 " -o --options=OPTIONS Mount options\n"
136 " --owner=USER Add uid= and gid= options for USER\n"
137 " --fsck=no Don't run file system check before mount\n"
138 " --description=TEXT Description for unit\n"
139 " -p --property=NAME=VALUE Set mount unit property\n"
140 " -A --automount=BOOL Create an auto-mount point\n"
141 " --timeout-idle-sec=SEC Specify automount idle timeout\n"
142 " --automount-property=NAME=VALUE\n"
143 " Set automount unit property\n"
144 " --bind-device Bind automount unit to device\n"
145 " --list List mountable block devices\n"
146 " -u --umount Unmount mount points\n"
147 " -G --collect Unload unit after it stopped, even when failed\n"
148 " -T --tmpfs Create a new tmpfs on the mount point\n"
149 "\nSee the %s for details.\n",
150 program_invocation_short_name,
151 streq(program_invocation_short_name, "systemd-umount") ? "" : "--umount ",
152 link);
153
154 return 0;
155 }
156
157 static int parse_argv(int argc, char *argv[]) {
158
159 enum {
160 ARG_VERSION = 0x100,
161 ARG_NO_BLOCK,
162 ARG_NO_PAGER,
163 ARG_NO_LEGEND,
164 ARG_NO_ASK_PASSWORD,
165 ARG_USER,
166 ARG_SYSTEM,
167 ARG_DISCOVER,
168 ARG_MOUNT_TYPE,
169 ARG_MOUNT_OPTIONS,
170 ARG_OWNER,
171 ARG_FSCK,
172 ARG_DESCRIPTION,
173 ARG_TIMEOUT_IDLE,
174 ARG_AUTOMOUNT,
175 ARG_AUTOMOUNT_PROPERTY,
176 ARG_BIND_DEVICE,
177 ARG_LIST,
178 };
179
180 static const struct option options[] = {
181 { "help", no_argument, NULL, 'h' },
182 { "version", no_argument, NULL, ARG_VERSION },
183 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
184 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
185 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
186 { "full", no_argument, NULL, 'l' },
187 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
188 { "quiet", no_argument, NULL, 'q' },
189 { "user", no_argument, NULL, ARG_USER },
190 { "system", no_argument, NULL, ARG_SYSTEM },
191 { "host", required_argument, NULL, 'H' },
192 { "machine", required_argument, NULL, 'M' },
193 { "discover", no_argument, NULL, ARG_DISCOVER },
194 { "type", required_argument, NULL, 't' },
195 { "options", required_argument, NULL, 'o' },
196 { "owner", required_argument, NULL, ARG_OWNER },
197 { "fsck", required_argument, NULL, ARG_FSCK },
198 { "description", required_argument, NULL, ARG_DESCRIPTION },
199 { "property", required_argument, NULL, 'p' },
200 { "automount", required_argument, NULL, ARG_AUTOMOUNT },
201 { "timeout-idle-sec", required_argument, NULL, ARG_TIMEOUT_IDLE },
202 { "automount-property", required_argument, NULL, ARG_AUTOMOUNT_PROPERTY },
203 { "bind-device", no_argument, NULL, ARG_BIND_DEVICE },
204 { "list", no_argument, NULL, ARG_LIST },
205 { "umount", no_argument, NULL, 'u' },
206 { "unmount", no_argument, NULL, 'u' }, /* Compat spelling */
207 { "collect", no_argument, NULL, 'G' },
208 { "tmpfs", no_argument, NULL, 'T' },
209 {},
210 };
211
212 int r, c;
213
214 assert(argc >= 0);
215 assert(argv);
216
217 if (invoked_as(argv, "systemd-umount"))
218 arg_action = ACTION_UMOUNT;
219
220 while ((c = getopt_long(argc, argv, "hqH:M:t:o:p:AuGlT", options, NULL)) >= 0)
221
222 switch (c) {
223
224 case 'h':
225 return help();
226
227 case ARG_VERSION:
228 return version();
229
230 case ARG_NO_BLOCK:
231 arg_no_block = true;
232 break;
233
234 case ARG_NO_PAGER:
235 arg_pager_flags |= PAGER_DISABLE;
236 break;
237
238 case ARG_NO_LEGEND:
239 arg_legend = false;
240 break;
241
242 case 'l':
243 arg_full = true;
244 break;
245
246 case ARG_NO_ASK_PASSWORD:
247 arg_ask_password = false;
248 break;
249
250 case 'q':
251 arg_quiet = true;
252 break;
253
254 case ARG_USER:
255 arg_runtime_scope = RUNTIME_SCOPE_USER;
256 break;
257
258 case ARG_SYSTEM:
259 arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
260 break;
261
262 case 'H':
263 arg_transport = BUS_TRANSPORT_REMOTE;
264 arg_host = optarg;
265 break;
266
267 case 'M':
268 arg_transport = BUS_TRANSPORT_MACHINE;
269 arg_host = optarg;
270 break;
271
272 case ARG_DISCOVER:
273 arg_discover = true;
274 break;
275
276 case 't':
277 r = free_and_strdup_warn(&arg_mount_type, optarg);
278 if (r < 0)
279 return r;
280 break;
281
282 case 'o':
283 r = free_and_strdup_warn(&arg_mount_options, optarg);
284 if (r < 0)
285 return r;
286 break;
287
288 case ARG_OWNER: {
289 const char *user = optarg;
290
291 r = get_user_creds(&user, &arg_uid, &arg_gid, NULL, NULL, 0);
292 if (r < 0)
293 return log_error_errno(r,
294 r == -EBADMSG ? "UID or GID of user %s are invalid."
295 : "Cannot use \"%s\" as owner: %m",
296 optarg);
297 break;
298 }
299
300 case ARG_FSCK:
301 r = parse_boolean_argument("--fsck=", optarg, &arg_fsck);
302 if (r < 0)
303 return r;
304 break;
305
306 case ARG_DESCRIPTION:
307 r = free_and_strdup_warn(&arg_description, optarg);
308 if (r < 0)
309 return r;
310 break;
311
312 case 'p':
313 if (strv_extend(&arg_property, optarg) < 0)
314 return log_oom();
315
316 break;
317
318 case 'A':
319 arg_action = ACTION_AUTOMOUNT;
320 break;
321
322 case ARG_AUTOMOUNT:
323 r = parse_boolean_argument("--automount=", optarg, NULL);
324 if (r < 0)
325 return r;
326
327 arg_action = r ? ACTION_AUTOMOUNT : ACTION_MOUNT;
328 break;
329
330 case ARG_TIMEOUT_IDLE:
331 r = parse_sec(optarg, &arg_timeout_idle);
332 if (r < 0)
333 return log_error_errno(r, "Failed to parse timeout: %s", optarg);
334
335 break;
336
337 case ARG_AUTOMOUNT_PROPERTY:
338 if (strv_extend(&arg_automount_property, optarg) < 0)
339 return log_oom();
340
341 break;
342
343 case ARG_BIND_DEVICE:
344 arg_bind_device = true;
345 break;
346
347 case ARG_LIST:
348 arg_action = ACTION_LIST;
349 break;
350
351 case 'u':
352 arg_action = ACTION_UMOUNT;
353 break;
354
355 case 'G':
356 arg_aggressive_gc = true;
357 break;
358
359 case 'T':
360 arg_tmpfs = true;
361 break;
362
363 case '?':
364 return -EINVAL;
365
366 default:
367 assert_not_reached();
368 }
369
370 if (arg_runtime_scope == RUNTIME_SCOPE_USER) {
371 arg_ask_password = false;
372
373 if (arg_transport != BUS_TRANSPORT_LOCAL)
374 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
375 "Execution in user context is not supported on non-local systems.");
376 }
377
378 if (arg_action == ACTION_LIST) {
379 if (optind < argc)
380 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
381 "Too many arguments.");
382
383 if (arg_transport != BUS_TRANSPORT_LOCAL)
384 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
385 "Listing devices only supported locally.");
386 } else if (arg_action == ACTION_UMOUNT) {
387 if (optind >= argc)
388 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
389 "At least one argument required.");
390
391 if (arg_transport != BUS_TRANSPORT_LOCAL)
392 for (int i = optind; i < argc; i++)
393 if (!path_is_absolute(argv[i]))
394 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
395 "Path must be absolute when operating remotely: %s",
396 argv[i]);
397 } else {
398 if (optind >= argc)
399 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
400 "At least one argument required.");
401
402 if (argc > optind+2)
403 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
404 "More than two arguments are not allowed.");
405
406 if (arg_tmpfs) {
407 if (argc <= optind+1) {
408 arg_mount_what = strdup("tmpfs");
409 if (!arg_mount_what)
410 return log_oom();
411
412 r = parse_where(argv[optind], &arg_mount_where);
413 if (r < 0)
414 return r;
415 } else {
416 arg_mount_what = strdup(argv[optind]);
417 if (!arg_mount_what)
418 return log_oom();
419 }
420
421 if (!strv_contains(arg_property, "Type=tmpfs") &&
422 strv_extend(&arg_property, "Type=tmpfs") < 0)
423 return log_oom();
424 } else {
425 if (arg_mount_type && !fstype_is_blockdev_backed(arg_mount_type)) {
426 arg_mount_what = strdup(argv[optind]);
427 if (!arg_mount_what)
428 return log_oom();
429
430 } else if (arg_transport == BUS_TRANSPORT_LOCAL) {
431 _cleanup_free_ char *u = NULL;
432
433 u = fstab_node_to_udev_node(argv[optind]);
434 if (!u)
435 return log_oom();
436
437 r = chase(u, NULL, 0, &arg_mount_what, NULL);
438 if (r < 0)
439 return log_error_errno(r, "Failed to make path %s absolute: %m", u);
440
441 } else {
442 if (!path_is_absolute(argv[optind]))
443 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
444 "Path must be absolute when operating remotely: %s",
445 argv[optind]);
446
447 r = path_simplify_alloc(argv[optind], &arg_mount_what);
448 if (r < 0)
449 return log_error_errno(r, "Failed to simplify path: %m");
450 }
451 }
452
453 if (argc > optind+1) {
454 r = parse_where(argv[optind+1], &arg_mount_where);
455 if (r < 0)
456 return r;
457 } else if (!arg_tmpfs)
458 arg_discover = true;
459
460 if (arg_discover && arg_transport != BUS_TRANSPORT_LOCAL)
461 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
462 "Automatic mount location discovery is only supported locally.");
463 }
464
465 return 1;
466 }
467
468 static int transient_unit_set_properties(sd_bus_message *m, UnitType t, char **properties) {
469 int r;
470
471 if (!isempty(arg_description)) {
472 r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description);
473 if (r < 0)
474 return r;
475 }
476
477 if (arg_bind_device && is_device_path(arg_mount_what)) {
478 _cleanup_free_ char *device_unit = NULL;
479
480 r = unit_name_from_path(arg_mount_what, ".device", &device_unit);
481 if (r < 0)
482 return r;
483
484 r = sd_bus_message_append(m, "(sv)(sv)",
485 "After", "as", 1, device_unit,
486 "BindsTo", "as", 1, device_unit);
487 if (r < 0)
488 return r;
489 }
490
491 if (arg_aggressive_gc) {
492 r = sd_bus_message_append(m, "(sv)", "CollectMode", "s", "inactive-or-failed");
493 if (r < 0)
494 return r;
495 }
496
497 r = bus_append_unit_property_assignment_many(m, t, properties);
498 if (r < 0)
499 return r;
500
501 return 0;
502 }
503
504 static int transient_mount_set_properties(sd_bus_message *m) {
505 int r;
506
507 assert(m);
508
509 r = transient_unit_set_properties(m, UNIT_MOUNT, arg_property);
510 if (r < 0)
511 return r;
512
513 if (arg_mount_what) {
514 r = sd_bus_message_append(m, "(sv)", "What", "s", arg_mount_what);
515 if (r < 0)
516 return r;
517 }
518
519 if (arg_mount_type) {
520 r = sd_bus_message_append(m, "(sv)", "Type", "s", arg_mount_type);
521 if (r < 0)
522 return r;
523 }
524
525 _cleanup_free_ char *options = NULL;
526
527 /* Prepend uid=…,gid=… if arg_uid is set */
528 if (arg_uid != UID_INVALID) {
529 r = strextendf_with_separator(&options, ",",
530 "uid="UID_FMT",gid="GID_FMT, arg_uid, arg_gid);
531 if (r < 0)
532 return r;
533 }
534
535 /* Override the default for tmpfs mounts. The kernel sets the sticky bit on the root directory by
536 * default. This makes sense for the case when the user does 'mount -t tmpfs tmpfs /tmp', but less so
537 * for other directories.
538 *
539 * Let's also set some reasonable limits. We use the current umask, to match what a command to create
540 * directory would use, e.g. mkdir. */
541 if (arg_tmpfs) {
542 mode_t mask;
543
544 r = get_process_umask(0, &mask);
545 if (r < 0)
546 return r;
547
548 assert((mask & ~0777) == 0);
549 r = strextendf_with_separator(&options, ",",
550 "mode=0%o,nodev,nosuid%s", 0777 & ~mask, NESTED_TMPFS_LIMITS);
551 if (r < 0)
552 return r;
553 }
554
555 if (arg_mount_options)
556 if (!strextend_with_separator(&options, ",", arg_mount_options))
557 return -ENOMEM;
558
559 if (options) {
560 log_debug("Using mount options: %s", options);
561 r = sd_bus_message_append(m, "(sv)", "Options", "s", options);
562 if (r < 0)
563 return r;
564 } else
565 log_debug("Not using any mount options");
566
567 if (arg_fsck) {
568 _cleanup_free_ char *fsck = NULL;
569
570 r = unit_name_from_path_instance("systemd-fsck", arg_mount_what, ".service", &fsck);
571 if (r < 0)
572 return r;
573
574 r = sd_bus_message_append(m,
575 "(sv)(sv)",
576 "Requires", "as", 1, fsck,
577 "After", "as", 1, fsck);
578 if (r < 0)
579 return r;
580 }
581
582 return 0;
583 }
584
585 static int transient_automount_set_properties(sd_bus_message *m) {
586 int r;
587
588 assert(m);
589
590 r = transient_unit_set_properties(m, UNIT_AUTOMOUNT, arg_automount_property);
591 if (r < 0)
592 return r;
593
594 if (arg_timeout_idle != USEC_INFINITY) {
595 r = sd_bus_message_append(m, "(sv)", "TimeoutIdleUSec", "t", arg_timeout_idle);
596 if (r < 0)
597 return r;
598 }
599
600 return 0;
601 }
602
603 static int start_transient_mount(
604 sd_bus *bus,
605 char **argv) {
606
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 *mount_unit = NULL;
611 int r;
612
613 if (!arg_no_block) {
614 r = bus_wait_for_jobs_new(bus, &w);
615 if (r < 0)
616 return log_error_errno(r, "Could not watch jobs: %m");
617 }
618
619 r = unit_name_from_path(arg_mount_where, ".mount", &mount_unit);
620 if (r < 0)
621 return log_error_errno(r, "Failed to make mount unit name: %m");
622
623 r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "StartTransientUnit");
624 if (r < 0)
625 return bus_log_create_error(r);
626
627 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
628 if (r < 0)
629 return bus_log_create_error(r);
630
631 /* Name and mode */
632 r = sd_bus_message_append(m, "ss", mount_unit, "fail");
633 if (r < 0)
634 return bus_log_create_error(r);
635
636 /* Properties */
637 r = sd_bus_message_open_container(m, 'a', "(sv)");
638 if (r < 0)
639 return bus_log_create_error(r);
640
641 r = transient_mount_set_properties(m);
642 if (r < 0)
643 return bus_log_create_error(r);
644
645 r = sd_bus_message_close_container(m);
646 if (r < 0)
647 return bus_log_create_error(r);
648
649 /* Auxiliary units */
650 r = sd_bus_message_append(m, "a(sa(sv))", 0);
651 if (r < 0)
652 return bus_log_create_error(r);
653
654 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
655
656 r = sd_bus_call(bus, m, 0, &error, &reply);
657 if (r < 0)
658 return log_error_errno(r, "Failed to start transient mount unit: %s", bus_error_message(&error, r));
659
660 if (w) {
661 const char *object;
662
663 r = sd_bus_message_read(reply, "o", &object);
664 if (r < 0)
665 return bus_log_parse_error(r);
666
667 r = bus_wait_for_jobs_one(w, object, arg_quiet, NULL);
668 if (r < 0)
669 return r;
670 }
671
672 if (!arg_quiet)
673 log_info("Started unit %s%s%s for mount point: %s%s%s",
674 ansi_highlight(), mount_unit, ansi_normal(),
675 ansi_highlight(), arg_mount_where, ansi_normal());
676
677 return 0;
678 }
679
680 static int start_transient_automount(
681 sd_bus *bus,
682 char **argv) {
683
684 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
685 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
686 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
687 _cleanup_free_ char *automount_unit = NULL, *mount_unit = NULL;
688 int r;
689
690 if (!arg_no_block) {
691 r = bus_wait_for_jobs_new(bus, &w);
692 if (r < 0)
693 return log_error_errno(r, "Could not watch jobs: %m");
694 }
695
696 r = unit_name_from_path(arg_mount_where, ".automount", &automount_unit);
697 if (r < 0)
698 return log_error_errno(r, "Failed to make automount unit name: %m");
699
700 r = unit_name_from_path(arg_mount_where, ".mount", &mount_unit);
701 if (r < 0)
702 return log_error_errno(r, "Failed to make mount unit name: %m");
703
704 r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "StartTransientUnit");
705 if (r < 0)
706 return bus_log_create_error(r);
707
708 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
709 if (r < 0)
710 return bus_log_create_error(r);
711
712 /* Name and mode */
713 r = sd_bus_message_append(m, "ss", automount_unit, "fail");
714 if (r < 0)
715 return bus_log_create_error(r);
716
717 /* Properties */
718 r = sd_bus_message_open_container(m, 'a', "(sv)");
719 if (r < 0)
720 return bus_log_create_error(r);
721
722 r = transient_automount_set_properties(m);
723 if (r < 0)
724 return bus_log_create_error(r);
725
726 r = sd_bus_message_close_container(m);
727 if (r < 0)
728 return bus_log_create_error(r);
729
730 /* Auxiliary units */
731 r = sd_bus_message_open_container(m, 'a', "(sa(sv))");
732 if (r < 0)
733 return bus_log_create_error(r);
734
735 r = sd_bus_message_open_container(m, 'r', "sa(sv)");
736 if (r < 0)
737 return bus_log_create_error(r);
738
739 r = sd_bus_message_append(m, "s", mount_unit);
740 if (r < 0)
741 return bus_log_create_error(r);
742
743 r = sd_bus_message_open_container(m, 'a', "(sv)");
744 if (r < 0)
745 return bus_log_create_error(r);
746
747 r = transient_mount_set_properties(m);
748 if (r < 0)
749 return bus_log_create_error(r);
750
751 r = sd_bus_message_close_container(m);
752 if (r < 0)
753 return bus_log_create_error(r);
754
755 r = sd_bus_message_close_container(m);
756 if (r < 0)
757 return bus_log_create_error(r);
758
759 r = sd_bus_message_close_container(m);
760 if (r < 0)
761 return bus_log_create_error(r);
762
763 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
764
765 r = sd_bus_call(bus, m, 0, &error, &reply);
766 if (r < 0)
767 return log_error_errno(r, "Failed to start transient automount unit: %s", bus_error_message(&error, r));
768
769 if (w) {
770 const char *object;
771
772 r = sd_bus_message_read(reply, "o", &object);
773 if (r < 0)
774 return bus_log_parse_error(r);
775
776 r = bus_wait_for_jobs_one(w, object, arg_quiet, NULL);
777 if (r < 0)
778 return r;
779 }
780
781 if (!arg_quiet)
782 log_info("Started unit %s%s%s for mount point: %s%s%s",
783 ansi_highlight(), automount_unit, ansi_normal(),
784 ansi_highlight(), arg_mount_where, ansi_normal());
785
786 return 0;
787 }
788
789 static int find_mount_points(const char *what, char ***list) {
790 _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
791 _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
792 _cleanup_strv_free_ char **l = NULL;
793 size_t n = 0;
794 int r;
795
796 assert(what);
797 assert(list);
798
799 /* Returns all mount points obtained from /proc/self/mountinfo in *list,
800 * and the number of mount points as return value. */
801
802 r = libmount_parse(NULL, NULL, &table, &iter);
803 if (r < 0)
804 return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m");
805
806 for (;;) {
807 struct libmnt_fs *fs;
808 const char *source, *target;
809
810 r = mnt_table_next_fs(table, iter, &fs);
811 if (r == 1)
812 break;
813 if (r < 0)
814 return log_error_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
815
816 source = mnt_fs_get_source(fs);
817 target = mnt_fs_get_target(fs);
818 if (!source || !target)
819 continue;
820
821 if (!path_equal(source, what))
822 continue;
823
824 /* one extra slot is needed for the terminating NULL */
825 if (!GREEDY_REALLOC0(l, n + 2))
826 return log_oom();
827
828 l[n] = strdup(target);
829 if (!l[n])
830 return log_oom();
831 n++;
832 }
833
834 if (!GREEDY_REALLOC0(l, n + 1))
835 return log_oom();
836
837 *list = TAKE_PTR(l);
838 return n;
839 }
840
841 static int find_loop_device(const char *backing_file, sd_device **ret) {
842 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
843 int r;
844
845 assert(backing_file);
846 assert(ret);
847
848 r = sd_device_enumerator_new(&e);
849 if (r < 0)
850 return log_oom();
851
852 r = sd_device_enumerator_add_match_subsystem(e, "block", /* match = */ true);
853 if (r < 0)
854 return log_error_errno(r, "Failed to add subsystem match: %m");
855
856 r = sd_device_enumerator_add_match_property(e, "ID_FS_USAGE", "filesystem");
857 if (r < 0)
858 return log_error_errno(r, "Failed to add property match: %m");
859
860 r = sd_device_enumerator_add_match_sysname(e, "loop*");
861 if (r < 0)
862 return log_error_errno(r, "Failed to add sysname match: %m");
863
864 r = sd_device_enumerator_add_match_sysattr(e, "loop/backing_file", /* value = */ NULL, /* match = */ true);
865 if (r < 0)
866 return log_error_errno(r, "Failed to add sysattr match: %m");
867
868 FOREACH_DEVICE(e, dev) {
869 const char *s;
870
871 r = sd_device_get_sysattr_value(dev, "loop/backing_file", &s);
872 if (r < 0) {
873 log_device_debug_errno(dev, r, "Failed to read \"loop/backing_file\" sysattr, ignoring: %m");
874 continue;
875 }
876
877 if (inode_same(s, backing_file, 0) <= 0)
878 continue;
879
880 *ret = sd_device_ref(dev);
881 return 0;
882 }
883
884 return -ENXIO;
885 }
886
887 static int stop_mount(
888 sd_bus *bus,
889 const char *where,
890 const char *suffix) {
891
892 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
893 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
894 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
895 _cleanup_free_ char *mount_unit = NULL;
896 int r;
897
898 if (!arg_no_block) {
899 r = bus_wait_for_jobs_new(bus, &w);
900 if (r < 0)
901 return log_error_errno(r, "Could not watch jobs: %m");
902 }
903
904 r = unit_name_from_path(where, suffix, &mount_unit);
905 if (r < 0)
906 return log_error_errno(r, "Failed to make %s unit name from path %s: %m", suffix + 1, where);
907
908 r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "StopUnit");
909 if (r < 0)
910 return bus_log_create_error(r);
911
912 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
913 if (r < 0)
914 return bus_log_create_error(r);
915
916 /* Name and mode */
917 r = sd_bus_message_append(m, "ss", mount_unit, "fail");
918 if (r < 0)
919 return bus_log_create_error(r);
920
921 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
922
923 r = sd_bus_call(bus, m, 0, &error, &reply);
924 if (r < 0) {
925 if (streq(suffix, ".automount") &&
926 sd_bus_error_has_name(&error, "org.freedesktop.systemd1.NoSuchUnit"))
927 return 0;
928 return log_error_errno(r, "Failed to stop %s unit: %s", suffix + 1, bus_error_message(&error, r));
929 }
930
931 if (w) {
932 const char *object;
933
934 r = sd_bus_message_read(reply, "o", &object);
935 if (r < 0)
936 return bus_log_parse_error(r);
937
938 r = bus_wait_for_jobs_one(w, object, arg_quiet, NULL);
939 if (r < 0)
940 return r;
941 }
942
943 if (!arg_quiet)
944 log_info("Stopped unit %s%s%s for mount point: %s%s%s",
945 ansi_highlight(), mount_unit, ansi_normal(),
946 ansi_highlight(), where, ansi_normal());
947
948 return 0;
949 }
950
951 static int stop_mounts(
952 sd_bus *bus,
953 const char *where) {
954
955 int r;
956
957 if (path_equal(where, "/"))
958 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
959 "Refusing to operate on root directory: %s", where);
960
961 if (!path_is_normalized(where))
962 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
963 "Path contains non-normalized components: %s", where);
964
965 r = stop_mount(bus, where, ".mount");
966 if (r < 0)
967 return r;
968
969 r = stop_mount(bus, where, ".automount");
970 if (r < 0)
971 return r;
972
973 return 0;
974 }
975
976 static int umount_by_device(sd_bus *bus, sd_device *dev) {
977 _cleanup_(sd_device_unrefp) sd_device *d = NULL;
978 _cleanup_strv_free_ char **list = NULL;
979 const char *v;
980 int r, ret = 0;
981
982 assert(bus);
983 assert(dev);
984
985 if (sd_device_get_property_value(d, "SYSTEMD_MOUNT_WHERE", &v) >= 0)
986 ret = stop_mounts(bus, v);
987
988 r = sd_device_get_devname(dev, &v);
989 if (r < 0)
990 return r;
991
992 r = find_mount_points(v, &list);
993 if (r < 0)
994 return r;
995
996 STRV_FOREACH(l, list) {
997 r = stop_mounts(bus, *l);
998 if (r < 0)
999 ret = r;
1000 }
1001
1002 return ret;
1003 }
1004
1005 static int umount_by_device_node(sd_bus *bus, const char *node) {
1006 _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
1007 const char *v;
1008 int r;
1009
1010 assert(bus);
1011 assert(node);
1012
1013 r = sd_device_new_from_devname(&dev, node);
1014 if (r < 0)
1015 return log_error_errno(r, "Failed to get device from %s: %m", node);
1016
1017 r = sd_device_get_property_value(dev, "ID_FS_USAGE", &v);
1018 if (r < 0)
1019 return log_device_error_errno(dev, r, "Failed to get \"ID_FS_USAGE\" device property: %m");
1020
1021 if (!streq(v, "filesystem"))
1022 return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL),
1023 "%s does not contain a known file system.", node);
1024
1025 return umount_by_device(bus, dev);
1026 }
1027
1028 static int umount_loop(sd_bus *bus, const char *backing_file) {
1029 _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
1030 int r;
1031
1032 assert(backing_file);
1033
1034 r = find_loop_device(backing_file, &dev);
1035 if (r < 0)
1036 return log_error_errno(r, r == -ENXIO ? "File %s is not mounted." : "Can't get loop device for %s: %m", backing_file);
1037
1038 return umount_by_device(bus, dev);
1039 }
1040
1041 static int action_umount(
1042 sd_bus *bus,
1043 int argc,
1044 char **argv) {
1045
1046 int r, r2 = 0;
1047
1048 if (arg_transport != BUS_TRANSPORT_LOCAL) {
1049 for (int i = optind; i < argc; i++) {
1050 _cleanup_free_ char *p = NULL;
1051
1052 r = path_simplify_alloc(argv[i], &p);
1053 if (r < 0)
1054 return r;
1055
1056 r = stop_mounts(bus, p);
1057 if (r < 0)
1058 r2 = r;
1059 }
1060 return r2;
1061 }
1062
1063 for (int i = optind; i < argc; i++) {
1064 _cleanup_free_ char *u = NULL, *p = NULL;
1065 struct stat st;
1066
1067 u = fstab_node_to_udev_node(argv[i]);
1068 if (!u)
1069 return log_oom();
1070
1071 r = chase(u, NULL, 0, &p, NULL);
1072 if (r < 0) {
1073 r2 = log_error_errno(r, "Failed to make path %s absolute: %m", argv[i]);
1074 continue;
1075 }
1076
1077 if (stat(p, &st) < 0)
1078 return log_error_errno(errno, "Can't stat %s (from %s): %m", p, argv[i]);
1079
1080 if (S_ISBLK(st.st_mode))
1081 r = umount_by_device_node(bus, p);
1082 else if (S_ISREG(st.st_mode))
1083 r = umount_loop(bus, p);
1084 else if (S_ISDIR(st.st_mode))
1085 r = stop_mounts(bus, p);
1086 else {
1087 log_error("Invalid file type: %s (from %s)", p, argv[i]);
1088 r = -EINVAL;
1089 }
1090
1091 if (r < 0)
1092 r2 = r;
1093 }
1094
1095 return r2;
1096 }
1097
1098 static int acquire_mount_type(sd_device *d) {
1099 const char *v;
1100
1101 assert(d);
1102
1103 if (arg_mount_type)
1104 return 0;
1105
1106 if (sd_device_get_property_value(d, "ID_FS_TYPE", &v) < 0)
1107 return 0;
1108
1109 arg_mount_type = strdup(v);
1110 if (!arg_mount_type)
1111 return log_oom();
1112
1113 log_debug("Discovered type=%s", arg_mount_type);
1114 return 1;
1115 }
1116
1117 static int acquire_mount_options(sd_device *d) {
1118 const char *v;
1119
1120 assert(d);
1121
1122 if (arg_mount_options)
1123 return 0;
1124
1125 if (sd_device_get_property_value(d, "SYSTEMD_MOUNT_OPTIONS", &v) < 0)
1126 return 0;
1127
1128 arg_mount_options = strdup(v);
1129 if (!arg_mount_options)
1130 return log_oom();
1131
1132 log_debug("Discovered options=%s", arg_mount_options);
1133 return 1;
1134 }
1135
1136 static const char *get_model(sd_device *d) {
1137 const char *model;
1138
1139 assert(d);
1140
1141 if (sd_device_get_property_value(d, "ID_MODEL_FROM_DATABASE", &model) >= 0)
1142 return model;
1143
1144 if (sd_device_get_property_value(d, "ID_MODEL", &model) >= 0)
1145 return model;
1146
1147 return NULL;
1148 }
1149
1150 static const char* get_label(sd_device *d) {
1151 const char *label;
1152
1153 assert(d);
1154
1155 if (sd_device_get_property_value(d, "ID_FS_LABEL", &label) >= 0)
1156 return label;
1157
1158 if (sd_device_get_property_value(d, "ID_PART_ENTRY_NAME", &label) >= 0)
1159 return label;
1160
1161 return NULL;
1162 }
1163
1164 static int acquire_mount_where(sd_device *d) {
1165 const char *v;
1166 int r;
1167
1168 if (arg_mount_where)
1169 return 0;
1170
1171 if (sd_device_get_property_value(d, "SYSTEMD_MOUNT_WHERE", &v) < 0) {
1172 _cleanup_free_ char *escaped = NULL, *devname_bn = NULL;
1173 const char *name;
1174
1175 name = get_label(d);
1176 if (!name)
1177 name = get_model(d);
1178 if (!name) {
1179 const char *dn;
1180
1181 if (sd_device_get_devname(d, &dn) < 0)
1182 return 0;
1183
1184 r = path_extract_filename(dn, &devname_bn);
1185 if (r < 0)
1186 return log_error_errno(r, "Failed to extract file name from '%s': %m", dn);
1187
1188 name = devname_bn;
1189 }
1190
1191 escaped = xescape(name, "\\");
1192 if (!escaped)
1193 return log_oom();
1194 if (!filename_is_valid(escaped))
1195 return 0;
1196
1197 arg_mount_where = path_join("/run/media/system", escaped);
1198 } else
1199 arg_mount_where = strdup(v);
1200
1201 if (!arg_mount_where)
1202 return log_oom();
1203
1204 log_debug("Discovered where=%s", arg_mount_where);
1205 return 1;
1206 }
1207
1208 static int acquire_mount_where_for_loop_dev(sd_device *dev) {
1209 _cleanup_strv_free_ char **list = NULL;
1210 const char *node;
1211 int r;
1212
1213 assert(dev);
1214
1215 if (arg_mount_where)
1216 return 0;
1217
1218 r = sd_device_get_devname(dev, &node);
1219 if (r < 0)
1220 return r;
1221
1222 r = find_mount_points(node, &list);
1223 if (r < 0)
1224 return r;
1225 if (r == 0)
1226 return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL),
1227 "Can't find mount point of %s. It is expected that %s is already mounted on a place.",
1228 node, node);
1229 if (r >= 2)
1230 return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL),
1231 "%s is mounted on %d places. It is expected that %s is mounted on a place.",
1232 node, r, node);
1233
1234 arg_mount_where = strdup(list[0]);
1235 if (!arg_mount_where)
1236 return log_oom();
1237
1238 log_debug("Discovered where=%s", arg_mount_where);
1239 return 1;
1240 }
1241
1242 static int acquire_description(sd_device *d) {
1243 const char *model, *label;
1244
1245 if (arg_description)
1246 return 0;
1247
1248 model = get_model(d);
1249
1250 label = get_label(d);
1251 if (!label)
1252 (void) sd_device_get_property_value(d, "ID_PART_ENTRY_NUMBER", &label);
1253
1254 if (model && label)
1255 arg_description = strjoin(model, " ", label);
1256 else if (label)
1257 arg_description = strdup(label);
1258 else if (model)
1259 arg_description = strdup(model);
1260 else
1261 return 0;
1262
1263 if (!arg_description)
1264 return log_oom();
1265
1266 log_debug("Discovered description=%s", arg_description);
1267 return 1;
1268 }
1269
1270 static int acquire_removable(sd_device *d) {
1271 const char *v;
1272
1273 /* Shortcut this if there's no reason to check it */
1274 if (arg_action != ACTION_DEFAULT && arg_timeout_idle_set && arg_bind_device >= 0)
1275 return 0;
1276
1277 for (;;) {
1278 if (sd_device_get_sysattr_value(d, "removable", &v) >= 0)
1279 break;
1280
1281 if (sd_device_get_parent(d, &d) < 0)
1282 return 0;
1283
1284 if (sd_device_get_subsystem(d, &v) < 0 || !streq(v, "block"))
1285 return 0;
1286 }
1287
1288 if (parse_boolean(v) <= 0)
1289 return 0;
1290
1291 log_debug("Discovered removable device.");
1292
1293 if (arg_action == ACTION_DEFAULT) {
1294 log_debug("Automatically turning on automount.");
1295 arg_action = ACTION_AUTOMOUNT;
1296 }
1297
1298 if (!arg_timeout_idle_set) {
1299 log_debug("Setting idle timeout to 1s.");
1300 arg_timeout_idle = USEC_PER_SEC;
1301 }
1302
1303 if (arg_bind_device < 0) {
1304 log_debug("Binding automount unit to device.");
1305 arg_bind_device = true;
1306 }
1307
1308 return 1;
1309 }
1310
1311 static int discover_loop_backing_file(void) {
1312 _cleanup_(sd_device_unrefp) sd_device *d = NULL;
1313 int r;
1314
1315 r = find_loop_device(arg_mount_what, &d);
1316 if (r < 0 && r != -ENXIO)
1317 return log_error_errno(errno, "Can't get loop device for %s: %m", arg_mount_what);
1318
1319 if (r == -ENXIO) {
1320 _cleanup_free_ char *escaped = NULL, *bn = NULL;
1321
1322 if (arg_mount_where)
1323 return 0;
1324
1325 r = path_extract_filename(arg_mount_what, &bn);
1326 if (r < 0)
1327 return log_error_errno(r, "Failed to extract file name from backing file path '%s': %m", arg_mount_what);
1328
1329 escaped = xescape(bn, "\\");
1330 if (!escaped)
1331 return log_oom();
1332 if (!filename_is_valid(escaped))
1333 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1334 "Escaped name %s is not a valid filename.",
1335 escaped);
1336
1337 arg_mount_where = path_join("/run/media/system", escaped);
1338 if (!arg_mount_where)
1339 return log_oom();
1340
1341 log_debug("Discovered where=%s", arg_mount_where);
1342 return 0;
1343 }
1344
1345 r = acquire_mount_type(d);
1346 if (r < 0)
1347 return r;
1348
1349 r = acquire_mount_options(d);
1350 if (r < 0)
1351 return r;
1352
1353 r = acquire_mount_where_for_loop_dev(d);
1354 if (r < 0)
1355 return r;
1356
1357 r = acquire_description(d);
1358 if (r < 0)
1359 return r;
1360
1361 return 0;
1362 }
1363
1364 static int discover_device(void) {
1365 _cleanup_(sd_device_unrefp) sd_device *d = NULL;
1366 struct stat st;
1367 const char *v;
1368 int r;
1369
1370 if (stat(arg_mount_what, &st) < 0)
1371 return log_error_errno(errno, "Can't stat %s: %m", arg_mount_what);
1372
1373 if (S_ISREG(st.st_mode))
1374 return discover_loop_backing_file();
1375
1376 if (!S_ISBLK(st.st_mode))
1377 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1378 "Invalid file type: %s",
1379 arg_mount_what);
1380
1381 r = sd_device_new_from_stat_rdev(&d, &st);
1382 if (r < 0)
1383 return log_error_errno(r, "Failed to get device from device number: %m");
1384
1385 if (sd_device_get_property_value(d, "ID_FS_USAGE", &v) < 0 || !streq(v, "filesystem"))
1386 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1387 "%s does not contain a known file system.",
1388 arg_mount_what);
1389
1390 r = acquire_mount_type(d);
1391 if (r < 0)
1392 return r;
1393
1394 r = acquire_mount_options(d);
1395 if (r < 0)
1396 return r;
1397
1398 r = acquire_mount_where(d);
1399 if (r < 0)
1400 return r;
1401
1402 r = acquire_description(d);
1403 if (r < 0)
1404 return r;
1405
1406 r = acquire_removable(d);
1407 if (r < 0)
1408 return r;
1409
1410 return 0;
1411 }
1412
1413 static int list_devices(void) {
1414 enum {
1415 COLUMN_NODE,
1416 COLUMN_PATH,
1417 COLUMN_MODEL,
1418 COLUMN_WWN,
1419 COLUMN_FSTYPE,
1420 COLUMN_LABEL,
1421 COLUMN_UUID,
1422 _COLUMN_MAX,
1423 };
1424
1425 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
1426 _cleanup_(table_unrefp) Table *table = NULL;
1427 int r;
1428
1429 r = sd_device_enumerator_new(&e);
1430 if (r < 0)
1431 return log_oom();
1432
1433 r = sd_device_enumerator_add_match_subsystem(e, "block", true);
1434 if (r < 0)
1435 return log_error_errno(r, "Failed to add block match: %m");
1436
1437 r = sd_device_enumerator_add_match_property(e, "ID_FS_USAGE", "filesystem");
1438 if (r < 0)
1439 return log_error_errno(r, "Failed to add property match: %m");
1440
1441 table = table_new("NODE", "PATH", "MODEL", "WWN", "TYPE", "LABEL", "UUID");
1442 if (!table)
1443 return log_oom();
1444
1445 if (arg_full)
1446 table_set_width(table, 0);
1447
1448 r = table_set_sort(table, (size_t) 0);
1449 if (r < 0)
1450 return log_error_errno(r, "Failed to set sort index: %m");
1451
1452 table_set_header(table, arg_legend);
1453 table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
1454
1455 FOREACH_DEVICE(e, d) {
1456 for (unsigned c = 0; c < _COLUMN_MAX; c++) {
1457 const char *x = NULL;
1458
1459 switch (c) {
1460
1461 case COLUMN_NODE:
1462 (void) sd_device_get_devname(d, &x);
1463 break;
1464
1465 case COLUMN_PATH:
1466 (void) sd_device_get_property_value(d, "ID_PATH", &x);
1467 break;
1468
1469 case COLUMN_MODEL:
1470 x = get_model(d);
1471 break;
1472
1473 case COLUMN_WWN:
1474 (void) sd_device_get_property_value(d, "ID_WWN", &x);
1475 break;
1476
1477 case COLUMN_FSTYPE:
1478 (void) sd_device_get_property_value(d, "ID_FS_TYPE", &x);
1479 break;
1480
1481 case COLUMN_LABEL:
1482 x = get_label(d);
1483 break;
1484
1485 case COLUMN_UUID:
1486 (void) sd_device_get_property_value(d, "ID_FS_UUID", &x);
1487 break;
1488 }
1489
1490 r = table_add_cell(table, NULL, c == COLUMN_NODE ? TABLE_PATH : TABLE_STRING, x);
1491 if (r < 0)
1492 return table_log_add_error(r);
1493 }
1494 }
1495
1496 pager_open(arg_pager_flags);
1497
1498 r = table_print(table, NULL);
1499 if (r < 0)
1500 return table_log_print_error(r);
1501
1502 return 0;
1503 }
1504
1505 static int run(int argc, char* argv[]) {
1506 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
1507 int r;
1508
1509 log_show_color(true);
1510 log_parse_environment();
1511 log_open();
1512
1513 r = parse_argv(argc, argv);
1514 if (r <= 0)
1515 return r;
1516
1517 if (arg_action == ACTION_LIST)
1518 return list_devices();
1519
1520 r = bus_connect_transport_systemd(arg_transport, arg_host, arg_runtime_scope, &bus);
1521 if (r < 0)
1522 return bus_log_connect_error(r, arg_transport);
1523
1524 if (arg_action == ACTION_UMOUNT)
1525 return action_umount(bus, argc, argv);
1526
1527 if ((!arg_mount_type || fstype_is_blockdev_backed(arg_mount_type))
1528 && !path_is_normalized(arg_mount_what))
1529 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1530 "Path contains non-normalized components: %s",
1531 arg_mount_what);
1532
1533 if (arg_discover) {
1534 r = discover_device();
1535 if (r < 0)
1536 return r;
1537 }
1538
1539 if (!arg_mount_where)
1540 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1541 "Can't figure out where to mount %s.",
1542 arg_mount_what);
1543
1544 if (path_equal(arg_mount_where, "/"))
1545 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1546 "Refusing to operate on root directory.");
1547
1548 if (!path_is_normalized(arg_mount_where))
1549 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1550 "Path contains non-normalized components: %s",
1551 arg_mount_where);
1552
1553 if (streq_ptr(arg_mount_type, "auto"))
1554 arg_mount_type = mfree(arg_mount_type);
1555 if (streq_ptr(arg_mount_options, "defaults"))
1556 arg_mount_options = mfree(arg_mount_options);
1557
1558 if (!is_device_path(arg_mount_what))
1559 arg_fsck = false;
1560
1561 if (arg_fsck && arg_mount_type && arg_transport == BUS_TRANSPORT_LOCAL) {
1562 r = fsck_exists_for_fstype(arg_mount_type);
1563 if (r < 0)
1564 log_warning_errno(r, "Couldn't determine whether fsck for %s exists, proceeding anyway.", arg_mount_type);
1565 else if (r == 0) {
1566 log_debug("Disabling file system check as fsck for %s doesn't exist.", arg_mount_type);
1567 arg_fsck = false; /* fsck doesn't exist, let's not attempt it */
1568 }
1569 }
1570
1571 /* The kernel (properly) refuses mounting file systems with unknown uid=,gid= options,
1572 * but not for all filesystem types. Let's try to catch the cases where the option
1573 * would be used if the file system does not support it. It is also possible to
1574 * autodetect the file system, but that's only possible with disk-based file systems
1575 * which incidentally seem to be implemented more carefully and reject unknown options,
1576 * so it's probably OK that we do the check only when the type is specified.
1577 */
1578 if (arg_mount_type &&
1579 !streq(arg_mount_type, "auto") &&
1580 arg_uid != UID_INVALID &&
1581 !fstype_can_uid_gid(arg_mount_type))
1582 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1583 "File system type %s is not known to support uid=/gid=, refusing.",
1584 arg_mount_type);
1585
1586 switch (arg_action) {
1587
1588 case ACTION_MOUNT:
1589 case ACTION_DEFAULT:
1590 r = start_transient_mount(bus, argv + optind);
1591 break;
1592
1593 case ACTION_AUTOMOUNT:
1594 r = start_transient_automount(bus, argv + optind);
1595 break;
1596
1597 default:
1598 assert_not_reached();
1599 }
1600
1601 return r;
1602 }
1603
1604 DEFINE_MAIN_FUNCTION(run);