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