]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - lib/canonicalize.c
854e611465b0ed9215da3fcde0087d0cd35b9253
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"
19 #include "pathnames.h"
22 #include "fileutils.h"
25 * Converts private "dm-N" names to "/dev/mapper/<name>"
27 * Since 2.6.29 (patch 784aae735d9b0bba3f8b9faef4c8b30df3bf0128) kernel sysfs
28 * provides the real DM device names in /sys/block/<ptname>/dm/name
30 * The @prefix allows /sys to be mounted or stored outside the system root
33 char *ul_canonicalize_dm_name_prefixed(const char *prefix
, const char *ptname
)
37 char path
[256], name
[sizeof(path
) - sizeof(_PATH_DEV_MAPPER
)], *res
= NULL
;
39 if (!ptname
|| !*ptname
)
45 snprintf(path
, sizeof(path
), "%s/sys/block/%s/dm/name", prefix
, ptname
);
46 if (!(f
= fopen(path
, "r" UL_CLOEXECSTR
)))
49 /* read "<name>\n" from sysfs */
50 if (fgets(name
, sizeof(name
), f
) && (sz
= strlen(name
)) > 1) {
52 snprintf(path
, sizeof(path
), _PATH_DEV_MAPPER
"/%s", name
);
54 if ((prefix
&& *prefix
) || access(path
, F_OK
) == 0)
61 char *ul_canonicalize_dm_name(const char *ptname
)
63 return ul_canonicalize_dm_name_prefixed(NULL
, ptname
);
66 static int is_dm_devname(char *canonical
, char **name
)
69 char *p
= strrchr(canonical
, '/');
74 || strncmp(p
, "/dm-", 4) != 0
76 || stat(canonical
, &sb
) != 0
77 || !S_ISBLK(sb
.st_mode
))
85 * This function does not canonicalize the path! It just prepends CWD before a
86 * relative path. If the path is no relative than returns NULL. The path does
89 char *ul_absolute_path(const char *path
)
91 char cwd
[PATH_MAX
], *res
, *p
;
94 if (!ul_is_relative_path(path
)) {
98 if (!getcwd(cwd
, sizeof(cwd
)))
101 /* simple clean up */
102 if (ul_startswith(path
, "./"))
104 else if (strcmp(path
, ".") == 0)
113 p
= res
= malloc(csz
+ 1 + psz
+ 1);
117 p
= mempcpy(p
, cwd
, csz
);
119 memcpy(p
, path
, psz
+ 1);
125 * Returns: <0 on error, 1 is cannot be canonicalized (errno is set); 0 on success
127 static int __attribute__((nonnull(2)))
128 do_canonicalize(const char *path
, char **result
,
129 void *data
__attribute__((__unused__
)))
131 char *canonical
, *dmname
;
135 if (!path
|| !*path
) {
141 canonical
= realpath(path
, NULL
);
145 if (is_dm_devname(canonical
, &dmname
)) {
146 char *dm
= ul_canonicalize_dm_name(dmname
);
159 * Always returns a newly allocated string or NULL in case of an error. An
160 * unreachable path is not an error (!), and in this case, it just duplicates
163 char *ul_canonicalize_path(const char *path
)
165 char *canonical
= NULL
;
167 if (do_canonicalize(path
, &canonical
, NULL
) == 1)
174 * Drop permissions (e.g., suid) and canonicalize the path. If the path is
175 * unreadable (for example, due to missing permissions), it returns NULL.
177 char *ul_canonicalize_path_restricted(const char *path
)
179 return ul_restricted_path_oper(path
, do_canonicalize
, NULL
);
182 #ifdef TEST_PROGRAM_CANONICALIZE
183 int main(int argc
, char **argv
)
188 fprintf(stderr
, "usage: %s <device>\n", argv
[0]);
192 fprintf(stdout
, "orig: %s\n", argv
[1]);
194 p
= ul_canonicalize_path(argv
[1]);
195 fprintf(stdout
, "real: %s\n", p
);
198 p
= ul_canonicalize_path_restricted(argv
[1]);
199 fprintf(stdout
, "real-restricted: %s\n", p
);