]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/base-filesystem.c
man: fix file extension in udev rules example
[thirdparty/systemd.git] / src / shared / base-filesystem.c
CommitLineData
3577de7a
KS
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2014 Kay Sievers
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <errno.h>
23#include <sys/stat.h>
24#include <stdlib.h>
25#include <string.h>
26#include <assert.h>
27#include <unistd.h>
28
29#include "base-filesystem.h"
30#include "log.h"
31#include "macro.h"
e1ae9755 32#include "strv.h"
3577de7a
KS
33#include "util.h"
34#include "label.h"
35#include "mkdir.h"
36
37typedef struct BaseFilesystem {
38 const char *dir;
39 mode_t mode;
40 const char *target;
3fd165e5 41 const char *exists;
3577de7a
KS
42} BaseFilesystem;
43
44static const BaseFilesystem table[] = {
30d7c9c4
HH
45 { "bin", 0, "usr/bin\0", NULL },
46 { "lib", 0, "usr/lib\0", NULL },
47 { "root", 0755, NULL, NULL },
48 { "sbin", 0, "usr/sbin\0", NULL },
e1ae9755 49#if defined(__i386__) || defined(__x86_64__)
30d7c9c4
HH
50 { "lib64", 0, "usr/lib/x86_64-linux-gnu\0"
51 "usr/lib64\0", "ld-linux-x86-64.so.2" },
e1ae9755 52#endif
3577de7a
KS
53};
54
55int base_filesystem_create(const char *root) {
56 _cleanup_close_ int fd = -1;
57 unsigned i;
58 int r;
59
60 fd = open(root, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
61 if (fd < 0)
62 return -errno;
63
64 for (i = 0; i < ELEMENTSOF(table); i ++) {
65 if (table[i].target) {
e1ae9755
KS
66 const char *target = NULL;
67 const char *s;
68
afc3f9cb
KS
69 if (faccessat(fd, table[i].dir, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
70 continue;
71
e1ae9755
KS
72 /* check if one of the targets exists */
73 NULSTR_FOREACH(s, table[i].target) {
74 if (faccessat(fd, s, F_OK, AT_SYMLINK_NOFOLLOW) < 0)
75 continue;
76
3fd165e5
KS
77 /* check if a specific file exists at the target path */
78 if (table[i].exists) {
79 _cleanup_free_ char *p = NULL;
80
81 p = strjoin(s, "/", table[i].exists, NULL);
82 if (!p)
83 return log_oom();
84
85 if (faccessat(fd, p, F_OK, AT_SYMLINK_NOFOLLOW) < 0)
86 continue;
87 }
88
e1ae9755
KS
89 target = s;
90 break;
91 }
92
93 if (!target)
3577de7a
KS
94 continue;
95
e1ae9755 96 r = symlinkat(target, fd, table[i].dir);
3577de7a
KS
97 if (r < 0 && errno != EEXIST) {
98 log_error("Failed to create symlink at %s/%s: %m", root, table[i].dir);
99 return -errno;
100 }
101 continue;
102 }
103
104 RUN_WITH_UMASK(0000)
105 r = mkdirat(fd, table[i].dir, table[i].mode);
106 if (r < 0 && errno != EEXIST) {
107 log_error("Failed to create directory at %s/%s: %m", root, table[i].dir);
108 return -errno;
109 }
110 }
111
112 return 0;
113}