]>
git.ipfire.org Git - people/stevee/pakfire.git/blob - src/libpakfire/fhs.c
1 /*#############################################################################
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2021 Pakfire development team #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 #############################################################################*/
23 #include <pakfire/fhs.h>
24 #include <pakfire/file.h>
25 #include <pakfire/logging.h>
26 #include <pakfire/pakfire.h>
27 #include <pakfire/util.h>
30 This struct defines any FHS checks.
32 They are being processed in order from top to bottom which is why we are starting
33 with some more prominent matches and have the less important stuff at the bottom.
35 static const struct pakfire_fhs_check
{
38 enum pakfire_fhs_check_flags
{
39 PAKFIRE_FHS_MUSTNOTEXIST
= (1 << 0),
44 } pakfire_fhs_check
[] = {
46 { "/usr", S_IFDIR
, 0, 0755, "root", "root" },
47 { "/usr/bin", S_IFDIR
, 0, 0755, "root", "root" },
48 { "/usr/include", S_IFDIR
, 0, 0755, "root", "root" },
49 { "/usr/lib", S_IFDIR
, 0, 0755, "root", "root" },
50 { "/usr/lib64", S_IFDIR
, 0, 0755, "root", "root" },
51 { "/usr/sbin", S_IFDIR
, 0, 0755, "root", "root" },
52 { "/usr/share", S_IFDIR
, 0, 0755, "root", "root" },
53 { "/usr/src", S_IFDIR
, 0, 0755, "root", "root" },
55 // Allow no further files in /usr & /usr/src
56 { "/usr/*", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
57 { "/usr/src/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
59 // There cannot be any subdirectories in /usr/bin & /usr/sbin
60 { "/usr/bin/*", S_IFDIR
, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
61 { "/usr/sbin/*", S_IFDIR
, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
64 { "/var", S_IFDIR
, 0, 0755, "root", "root" },
65 { "/var/cache", S_IFDIR
, 0, 0755, "root", "root" },
66 { "/var/db", S_IFDIR
, 0, 0755, "root", "root" },
67 { "/var/empty", S_IFDIR
, 0, 0755, "root", "root" },
68 { "/var/lib", S_IFDIR
, 0, 0755, "root", "root" },
69 { "/var/log", S_IFDIR
, 0, 0755, "root", "root" },
70 { "/var/mail", S_IFDIR
, 0, 0755, "root", "root" },
71 { "/var/opt", S_IFDIR
, 0, 0755, "root", "root" },
72 { "/var/run", S_IFLNK
, 0, 0755, "root", "root" },
73 { "/var/spool", S_IFDIR
, 0, 0755, "root", "root" },
74 { "/var/tmp", S_IFDIR
, 0, 0755, "root", "root" },
75 { "/var/tmp/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
78 { "/boot", S_IFDIR
, 0, 0755, "root", "root" },
79 { "/boot/efi", S_IFDIR
, 0, 0755, "root", "root" },
81 // /dev (nothing may exist in it)
82 { "/dev", S_IFDIR
, 0, 0755, "root", "root" },
83 { "/dev/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
86 { "/etc", S_IFDIR
, 0, 0755, "root", "root" },
89 { "/home", S_IFDIR
, 0, 0755, "root", "root" },
90 { "/home/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
93 { "/opt", S_IFDIR
, 0, 0755, "root", "root" },
94 // These directories belong to the "local administrator"
95 // https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch03s13.html
96 { "/opt/bin", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
97 { "/opt/doc", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
98 { "/opt/include", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
99 { "/opt/info", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
100 { "/opt/lib", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
101 { "/opt/man", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
104 { "/proc", S_IFDIR
, 0, 0755, "root", "root" },
105 { "/proc/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
108 { "/run", S_IFDIR
, 0, 0755, "root", "root" },
109 { "/run/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
112 { "/sys", S_IFDIR
, 0, 0755, "root", "root" },
113 { "/sys/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
116 { "/tmp", S_IFDIR
, 0, 1755, "root", "root" },
117 { "/tmp/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
120 { "/media", S_IFDIR
, 0, 0755, "root", "root" },
121 { "/mnt", S_IFDIR
, 0, 0755, "root", "root" },
122 { "/srv", S_IFDIR
, 0, 0755, "root", "root" },
124 // /bin, /sbin, /lib, and /lib64 have to be symlinks
125 { "/bin", S_IFLNK
, 0, 0777, NULL
, NULL
},
126 { "/lib", S_IFLNK
, 0, 0777, NULL
, NULL
},
127 { "/lib64", S_IFLNK
, 0, 0777, NULL
, NULL
},
128 { "/sbin", S_IFLNK
, 0, 0777, NULL
, NULL
},
130 // There cannot be anything else in /
131 { "/*", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
133 // Catch all so that we won't throw an error
134 { "/**", 0, 0, 0, NULL
, NULL
},
140 static const struct pakfire_fhs_check
* pakfire_fhs_find_check(
141 struct pakfire
* pakfire
, struct pakfire_file
* file
) {
142 const struct pakfire_fhs_check
* check
= NULL
;
145 // Fetch the file type
146 const mode_t type
= pakfire_file_get_type(file
);
149 const char* path
= pakfire_file_get_path(file
);
151 // Walk through all possible checks
152 for (check
= pakfire_fhs_check
; check
->path
; check
++) {
153 // Skip this check if the filetype doesn't match
154 if (check
->type
&& check
->type
!= type
)
158 r
= pakfire_path_match(check
->path
, path
);
166 DEBUG(pakfire
, "%s matches check '%s'\n", path
, check
->path
);
177 ERROR(pakfire
, "Could not find FHS entry for %s: %m\n", path
);
182 static int pakfire_fhs_check_perms(struct pakfire
* pakfire
,
183 const struct pakfire_fhs_check
* check
, struct pakfire_file
* file
) {
184 // No permissions defined. Skipping check...
188 const char* path
= pakfire_file_get_path(file
);
191 const mode_t perms
= pakfire_file_get_perms(file
);
193 // Check if they match
194 if (check
->perms
!= perms
) {
195 DEBUG(pakfire
, "%s: Permissions do not match\n", path
);
203 static int pakfire_fhs_check_ownership(struct pakfire
* pakfire
,
204 const struct pakfire_fhs_check
* check
, struct pakfire_file
* file
) {
205 const char* path
= pakfire_file_get_path(file
);
209 const char* uname
= pakfire_file_get_uname(file
);
213 if (strcmp(check
->uname
, uname
) != 0) {
214 DEBUG(pakfire
, "%s: uname does not match\n", path
);
221 const char* gname
= pakfire_file_get_gname(file
);
225 if (strcmp(check
->gname
, gname
) != 0) {
226 DEBUG(pakfire
, "%s: gname does not match\n", path
);
235 int pakfire_fhs_check_file(struct pakfire
* pakfire
, struct pakfire_file
* file
) {
236 const struct pakfire_fhs_check
* check
= NULL
;
240 const char* path
= pakfire_file_get_path(file
);
245 check
= pakfire_fhs_find_check(pakfire
, file
);
247 ERROR(pakfire
, "Could not match file %s: %m\n", path
);
251 // Should this file exist at all?
252 if (check
->flags
& PAKFIRE_FHS_MUSTNOTEXIST
) {
253 ERROR(pakfire
, "%s must not exist here\n", path
);
258 r
= pakfire_fhs_check_perms(pakfire
, check
, file
);
263 r
= pakfire_fhs_check_ownership(pakfire
, check
, file
);