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