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