1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010-2012 Lennart Poettering
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.
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.
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/>.
31 #include <sys/statvfs.h>
37 #include "path-util.h"
39 bool path_is_absolute(const char *p) {
43 bool is_path(const char *p) {
44 return !!strchr(p, '/');
47 char *path_get_file_name(const char *p) {
52 if ((r = strrchr(p, '/')))
58 int path_get_parent(const char *path, char **_r) {
59 const char *e, *a = NULL, *b = NULL, *p;
69 for (e = path; *e; e++) {
71 if (!slash && *e == '/') {
75 } else if (slash && *e != '/')
90 r = strndup(path, p-path);
99 char **path_split_and_make_absolute(const char *p) {
103 if (!(l = strv_split(p, ":")))
106 if (!path_strv_make_absolute_cwd(l)) {
114 char *path_make_absolute(const char *p, const char *prefix) {
117 /* Makes every item in the list an absolute path by prepending
118 * the prefix, if specified and necessary */
120 if (path_is_absolute(p) || !prefix)
123 return join(prefix, "/", p, NULL);
126 char *path_make_absolute_cwd(const char *p) {
131 /* Similar to path_make_absolute(), but prefixes with the
132 * current working directory. */
134 if (path_is_absolute(p))
137 if (!(cwd = get_current_dir_name()))
140 r = path_make_absolute(p, cwd);
146 char **path_strv_make_absolute_cwd(char **l) {
149 /* Goes through every item in the string list and makes it
150 * absolute. This works in place and won't rollback any
151 * changes on failure. */
156 if (!(t = path_make_absolute_cwd(*s)))
166 char **path_strv_canonicalize(char **l) {
174 /* Goes through every item in the string list and canonicalize
175 * the path. This works in place and won't rollback any
176 * changes on failure. */
181 t = path_make_absolute_cwd(*s);
190 u = canonicalize_file_name(t);
194 if (errno == ENOMEM || !errno)
211 char **path_strv_remove_empty(char **l) {
217 for (f = t = l; *f; f++) {
219 if (dir_is_empty(*f) > 0) {
231 char *path_kill_slashes(char *path) {
235 /* Removes redundant inner and trailing slashes. Modifies the
236 * passed string in-place.
238 * ///foo///bar/ becomes /foo/bar
241 for (f = path, t = path; *f; f++) {
256 /* Special rule, if we are talking of the root directory, a
257 trailing slash is good */
259 if (t == path && slash)
266 bool path_startswith(const char *path, const char *prefix) {
270 if ((path[0] == '/') != (prefix[0] == '/'))
276 path += strspn(path, "/");
277 prefix += strspn(prefix, "/");
285 a = strcspn(path, "/");
286 b = strcspn(prefix, "/");
291 if (memcmp(path, prefix, a) != 0)
299 bool path_equal(const char *a, const char *b) {
303 if ((a[0] == '/') != (b[0] == '/'))
312 if (*a == 0 && *b == 0)
315 if (*a == 0 || *b == 0)
324 if (memcmp(a, b, j) != 0)
332 int path_is_mount_point(const char *t, bool allow_symlink) {
349 r = path_get_parent(t, &parent);
353 r = lstat(parent, &b);
359 return a.st_dev != b.st_dev;
362 int path_is_read_only_fs(const char *path) {
367 if (statvfs(path, &st) < 0)
370 return !!(st.f_flag & ST_RDONLY);