1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
9 #include "load-fragment.h"
10 #include "load-dropin.h"
13 static const UnitActiveState state_translation_table
[_MOUNT_STATE_MAX
] = {
14 [MOUNT_DEAD
] = UNIT_INACTIVE
,
15 [MOUNT_MOUNTING
] = UNIT_ACTIVATING
,
16 [MOUNT_MOUNTED
] = UNIT_ACTIVE
,
17 [MOUNT_UNMOUNTING
] = UNIT_DEACTIVATING
,
18 [MOUNT_MAINTAINANCE
] = UNIT_INACTIVE
,
21 static const char* const state_string_table
[_MOUNT_STATE_MAX
] = {
22 [MOUNT_DEAD
] = "dead",
23 [MOUNT_MOUNTING
] = "mounting",
24 [MOUNT_MOUNTED
] = "mounted",
25 [MOUNT_UNMOUNTING
] = "unmounting",
26 [MOUNT_MAINTAINANCE
] = "maintainance"
29 static void mount_done(Unit
*u
) {
37 static void mount_set_state(Mount
*m
, MountState state
) {
44 log_debug("%s changed %s → %s", unit_id(UNIT(m
)), state_string_table
[old_state
], state_string_table
[state
]);
46 unit_notify(UNIT(m
), state_translation_table
[old_state
], state_translation_table
[state
]);
49 static int mount_coldplug(Unit
*u
) {
53 assert(m
->state
== MOUNT_DEAD
);
55 if (m
->from_proc_self_mountinfo
)
56 mount_set_state(m
, MOUNT_MOUNTED
);
61 static void mount_dump(Unit
*u
, FILE *f
, const char *prefix
) {
70 "%sFrom /etc/fstab: %s\n"
71 "%sFrom /proc/self/mountinfo: %s\n",
72 prefix
, state_string_table
[s
->state
],
75 prefix
, yes_no(s
->from_etc_fstab
),
76 prefix
, yes_no(s
->from_proc_self_mountinfo
));
79 static UnitActiveState
mount_active_state(Unit
*u
) {
82 return state_translation_table
[MOUNT(u
)->state
];
85 static void mount_shutdown(Manager
*m
) {
88 static int mount_add_node_links(Mount
*m
) {
95 /* Adds in links to the device that this node is based on */
97 if (!path_startswith(m
->what
, "/dev/"))
100 if (!(e
= unit_name_escape_path("node-", m
->what
+1, ".device")))
103 r
= manager_load_unit(UNIT(m
)->meta
.manager
, e
, &device
);
109 if ((r
= unit_add_dependency(UNIT(m
), UNIT_AFTER
, device
)) < 0)
112 if ((r
= unit_add_dependency(UNIT(m
), UNIT_REQUIRES
, device
)) < 0)
115 if ((r
= unit_add_dependency(device
, UNIT_WANTS
, UNIT(m
))) < 0)
121 static int mount_add_path_links(Mount
*m
) {
126 /* Adds in link to other mount points, that might lie below or
127 * above us in the hierarchy */
129 HASHMAP_FOREACH(other
, UNIT(m
)->meta
.manager
->units
, i
) {
132 if (other
->meta
.type
!= UNIT_MOUNT
)
137 if (path_startswith(m
->where
, n
->where
)) {
139 if ((r
= unit_add_dependency(UNIT(m
), UNIT_AFTER
, other
)) < 0)
142 if ((r
= unit_add_dependency(UNIT(m
), UNIT_REQUIRES
, other
)) < 0)
145 } else if (startswith(n
->where
, m
->where
)) {
147 if ((r
= unit_add_dependency(UNIT(m
), UNIT_BEFORE
, other
)) < 0)
150 if ((r
= unit_add_dependency(other
, UNIT_REQUIRES
, UNIT(m
))) < 0)
158 static int mount_add_one(Manager
*m
, const char *what
, const char *where
, bool live
) {
168 /* probably some kind of swap, which we don't cover for now */
172 if (streq(where
, "/"))
173 e
= strdup("rootfs.mount");
175 e
= unit_name_escape_path("fs-", where
+1, ".mount");
180 if (!(u
= manager_get_unit(m
, e
))) {
183 if (!(u
= unit_new(m
))) {
188 r
= unit_add_name(u
, e
);
194 if (!(MOUNT(u
)->what
= strdup(what
)) ||
195 !(MOUNT(u
)->where
= strdup(where
))) {
200 if ((r
= unit_set_description(u
, where
)) < 0)
208 MOUNT(u
)->from_proc_self_mountinfo
= true;
210 MOUNT(u
)->from_etc_fstab
= true;
212 if ((r
= mount_add_node_links(MOUNT(u
))) < 0)
215 if ((r
= mount_add_path_links(MOUNT(u
))) < 0)
218 unit_add_to_load_queue(u
);
229 static char *fstab_node_to_udev_node(char *p
) {
233 /* FIXME: to follow udev's logic 100% we need to leave valid
234 * UTF8 chars unescaped */
236 if (startswith(p
, "LABEL=")) {
238 if (!(t
= xescape(p
+6, "/ ")))
241 r
= asprintf(&dn
, "/dev/disk/by-label/%s", t
);
250 if (startswith(p
, "UUID=")) {
252 if (!(t
= xescape(p
+5, "/ ")))
255 r
= asprintf(&dn
, "/dev/disk/by-uuid/%s", ascii_strlower(t
));
267 static int mount_load_etc_fstab(Manager
*m
) {
275 if (!(f
= setmntent("/etc/fstab", "r")))
278 while ((me
= getmntent(f
))) {
281 if (!(what
= fstab_node_to_udev_node(me
->mnt_fsname
))) {
286 if (!(where
= strdup(me
->mnt_dir
))) {
293 path_kill_slashes(what
);
296 path_kill_slashes(where
);
298 r
= mount_add_one(m
, what
, where
, false);
313 static int mount_load_proc_self_mountinfo(Manager
*m
) {
319 if (!(f
= fopen("/proc/self/mountinfo", "r")))
324 char *device
, *path
, *d
, *p
;
327 "%*s " /* (1) mount id */
328 "%*s " /* (2) parent id */
329 "%*s " /* (3) major:minor */
330 "%*s " /* (4) root */
331 "%ms " /* (5) mount point */
332 "%*s" /* (6) mount options */
333 "%*[^-]" /* (7) optional fields */
334 "- " /* (8) seperator */
335 "%*s " /* (9) file system type */
336 "%ms" /* (10) mount source */
337 "%*[^\n]", /* some rubbish at the end */
353 if (!(d
= cunescape(device
))) {
361 if (!(p
= cunescape(path
))) {
369 r
= mount_add_one(m
, d
, p
, true);
385 static int mount_enumerate(Manager
*m
) {
389 if ((r
= mount_load_etc_fstab(m
)) < 0)
392 if ((r
= mount_load_proc_self_mountinfo(m
)) < 0)
402 const UnitVTable mount_vtable
= {
405 .init
= unit_load_fragment_and_dropin
,
407 .coldplug
= mount_coldplug
,
411 .active_state
= mount_active_state
,
413 .enumerate
= mount_enumerate
,
414 .shutdown
= mount_shutdown