1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
9 #include "load-fragment.h"
10 #include "load-fstab.h"
11 #include "load-dropin.h"
14 static int mount_init(Unit *u) {
20 /* Load a .mount file */
21 if ((r = unit_load_fragment(u)) < 0)
24 /* Load entry from /etc/fstab */
25 if ((r = unit_load_fstab(u)) < 0)
28 /* Load drop-in directory data */
29 if ((r = unit_load_dropin(u)) < 0)
35 static void mount_done(Unit *u) {
43 static void mount_dump(Unit *u, FILE *f, const char *prefix) {
45 static const char* const state_table[_MOUNT_STATE_MAX] = {
46 [MOUNT_DEAD] = "dead",
47 [MOUNT_MOUNTING] = "mounting",
48 [MOUNT_MOUNTED] = "mounted",
49 [MOUNT_UNMOUNTING] = "unmounting",
50 [MOUNT_MAINTAINANCE] = "maintainance"
61 prefix, state_table[s->state],
66 static void mount_shutdown(Manager *m) {
69 static int mount_add_node_links(Mount *m) {
76 /* Adds in links to the device that this node is based on */
78 if (!path_startswith(m->what, "/dev/"))
81 if (!(e = unit_name_escape_path("node-", m->what+1, ".device")))
84 r = manager_load_unit(UNIT(m)->meta.manager, e, &device);
90 if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, device)) < 0)
93 if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, device)) < 0)
96 if ((r = unit_add_dependency(device, UNIT_WANTS, UNIT(m))) < 0)
102 static int mount_add_path_links(Mount *m) {
107 /* Adds in link to other mount points, that might lie below or
108 * above us in the hierarchy */
110 HASHMAP_FOREACH(other, UNIT(m)->meta.manager->units, i) {
113 if (other->meta.type != UNIT_MOUNT)
118 if (path_startswith(m->where, n->where)) {
120 if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, other)) < 0)
123 if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, other)) < 0)
126 } else if (startswith(n->where, m->where)) {
128 if ((r = unit_add_dependency(UNIT(m), UNIT_BEFORE, other)) < 0)
131 if ((r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m))) < 0)
139 static int mount_add_one(Manager *m, const char *what, const char *where) {
148 /* probably some kind of swap, which we don't cover for now */
152 if (streq(where, "/"))
153 e = strdup("rootfs.mount");
155 e = unit_name_escape_path("fs-", where+1, ".mount");
160 if (!(u = manager_get_unit(m, e))) {
163 if (!(u = unit_new(m))) {
168 r = unit_add_name(u, e);
174 if (!(MOUNT(u)->what = strdup(what)) ||
175 !(MOUNT(u)->where = strdup(where)) ||
176 !(u->meta.description = strdup(where))) {
185 if ((r = mount_add_node_links(MOUNT(u))) < 0)
188 if ((r = mount_add_path_links(MOUNT(u))) < 0)
191 unit_add_to_load_queue(u);
201 static char *fstab_node_to_udev_node(char *p) {
205 /* FIXME: to follow udev's logic 100% we need to leave valid
206 * UTF8 chars unescaped */
208 if (startswith(p, "LABEL=")) {
210 if (!(t = strdup(p+6)))
213 r = asprintf(&dn, "/dev/disk/by-label/%s", xescape(t, "/ "));
222 if (startswith(p, "UUID=")) {
224 if (!(t = strdup(p+5)))
227 r = asprintf(&dn, "/dev/disk/by-uuid/%s", ascii_strlower(xescape(t, "/ ")));
239 static int mount_load_etc_fstab(Manager *m) {
247 if (!(f = setmntent("/etc/fstab", "r")))
250 while ((me = getmntent(f))) {
253 if (!(what = fstab_node_to_udev_node(me->mnt_fsname))) {
258 if (!(where = strdup(me->mnt_dir))) {
265 path_kill_slashes(what);
268 path_kill_slashes(where);
270 r = mount_add_one(m, what, where);
285 static int mount_load_proc_mounts(Manager *m) {
291 if (!(f = fopen("/proc/self/mountinfo", "r")))
296 char *device, *path, *d, *p;
299 "%*s " /* (1) mount id */
300 "%*s " /* (2) parent id */
301 "%*s " /* (3) major:minor */
302 "%*s " /* (4) root */
303 "%ms " /* (5) mount point */
304 "%*s" /* (6) mount options */
305 "%*[^-]" /* (7) optional fields */
306 "- " /* (8) seperator */
307 "%*s " /* (9) file system type */
308 "%ms" /* (10) mount source */
309 "%*[^\n]", /* some rubbish at the end */
325 if (!(d = cunescape(device))) {
333 if (!(p = cunescape(path))) {
341 r = mount_add_one(m, d, p);
357 static int mount_enumerate(Manager *m) {
361 if ((r = mount_load_etc_fstab(m)) < 0)
364 if ((r = mount_load_proc_mounts(m)) < 0)
374 static UnitActiveState mount_active_state(Unit *u) {
376 static const UnitActiveState table[_MOUNT_STATE_MAX] = {
377 [MOUNT_DEAD] = UNIT_INACTIVE,
378 [MOUNT_MOUNTING] = UNIT_ACTIVATING,
379 [MOUNT_MOUNTED] = UNIT_ACTIVE,
380 [MOUNT_UNMOUNTING] = UNIT_DEACTIVATING,
381 [MOUNT_MAINTAINANCE] = UNIT_INACTIVE,
384 return table[MOUNT(u)->state];
387 const UnitVTable mount_vtable = {
394 .enumerate = mount_enumerate,
395 .shutdown = mount_shutdown,
397 .active_state = mount_active_state