]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - lib/canonicalize.c
93782e894075375fbd8e2e111d4be929c6360fa7
2 * canonicalize.c -- canonicalize pathname by removing symlinks
4 * This file may be distributed under the terms of the
5 * GNU Lesser General Public License.
7 * Copyright (C) 2009-2013 Karel Zak <kzak@redhat.com>
15 #include <sys/types.h>
18 #include "canonicalize.h"
21 * Converts private "dm-N" names to "/dev/mapper/<name>"
23 * Since 2.6.29 (patch 784aae735d9b0bba3f8b9faef4c8b30df3bf0128) kernel sysfs
24 * provides the real DM device names in /sys/block/<ptname>/dm/name
26 char *canonicalize_dm_name(const char *ptname
)
30 char path
[256], name
[256], *res
= NULL
;
32 if (!ptname
|| !*ptname
)
35 snprintf(path
, sizeof(path
), "/sys/block/%s/dm/name", ptname
);
36 if (!(f
= fopen(path
, "r" UL_CLOEXECSTR
)))
39 /* read "<name>\n" from sysfs */
40 if (fgets(name
, sizeof(name
), f
) && (sz
= strlen(name
)) > 1) {
42 snprintf(path
, sizeof(path
), "/dev/mapper/%s", name
);
44 if (access(path
, F_OK
) == 0)
51 static int is_dm_devname(char *canonical
, char **name
)
54 char *p
= strrchr(canonical
, '/');
59 || strncmp(p
, "/dm-", 4) != 0
61 || stat(canonical
, &sb
) != 0
62 || !S_ISBLK(sb
.st_mode
))
70 * This function does not cannonicalize the path! It just prepends CWD before a
71 * relative path. If the path is no relative than returns NULL. The path does
74 char *absolute_path(const char *path
)
76 char cwd
[PATH_MAX
], *res
, *p
;
79 if (!is_relative_path(path
)) {
83 if (!getcwd(cwd
, sizeof(cwd
)))
87 if (startswith(path
, "./"))
89 else if (strcmp(path
, ".") == 0)
98 p
= res
= malloc(csz
+ 1 + psz
+ 1);
105 memcpy(p
, path
, psz
+ 1);
110 char *canonicalize_path(const char *path
)
112 char *canonical
, *dmname
;
117 canonical
= realpath(path
, NULL
);
121 if (is_dm_devname(canonical
, &dmname
)) {
122 char *dm
= canonicalize_dm_name(dmname
);
132 char *canonicalize_path_restricted(const char *path
)
134 char *canonical
, *dmname
;
145 /* drop permissions */
146 if (setegid(getgid()) < 0 || seteuid(getuid()) < 0)
151 canonical
= realpath(path
, NULL
);
154 else if (is_dm_devname(canonical
, &dmname
)) {
155 char *dm
= canonicalize_dm_name(dmname
);
163 if (setegid(egid
) < 0 || seteuid(euid
) < 0) {
173 #ifdef TEST_PROGRAM_CANONICALIZE
174 int main(int argc
, char **argv
)
177 fprintf(stderr
, "usage: %s <device>\n", argv
[0]);
181 fprintf(stdout
, "orig: %s\n", argv
[1]);
182 fprintf(stdout
, "real: %s\n", canonicalize_path(argv
[1]));