blob: a93bc698eea6d259caa661693d53a7c1fe5f21a0
1 | /* |
2 | * realpath.c - realpath() aware of device mapper |
3 | * Originated from the util-linux project. |
4 | */ |
5 | |
6 | #ifdef HAVE_CONFIG_H |
7 | #include "config.h" |
8 | #endif |
9 | |
10 | #include <stdlib.h> |
11 | #include <stdio.h> |
12 | #include <string.h> |
13 | |
14 | #ifdef HAVE_LIMITS_H |
15 | #include <limits.h> |
16 | #endif |
17 | #ifdef HAVE_CTYPE_H |
18 | #include <ctype.h> |
19 | #endif |
20 | |
21 | #include "param.h" |
22 | #include "realpath.h" |
23 | |
24 | /* If there is no realpath() on the system, provide a dummy one. */ |
25 | #ifndef HAVE_REALPATH |
26 | char *ntfs_realpath(const char *path, char *resolved_path) |
27 | { |
28 | strncpy(resolved_path, path, PATH_MAX); |
29 | resolved_path[PATH_MAX] = '\0'; |
30 | return resolved_path; |
31 | } |
32 | #endif |
33 | |
34 | |
35 | #ifdef linux |
36 | |
37 | /* |
38 | * Converts private "dm-N" names to "/dev/mapper/<name>" |
39 | * |
40 | * Since 2.6.29 (patch 784aae735d9b0bba3f8b9faef4c8b30df3bf0128) kernel sysfs |
41 | * provides the real DM device names in /sys/block/<ptname>/dm/name |
42 | */ |
43 | static char * |
44 | canonicalize_dm_name(const char *ptname, char *canonical) |
45 | { |
46 | FILE *f; |
47 | size_t sz; |
48 | char path[MAPPERNAMELTH + 24]; |
49 | char name[MAPPERNAMELTH + 16]; |
50 | char *res = NULL; |
51 | |
52 | snprintf(path, sizeof(path), "/sys/block/%s/dm/name", ptname); |
53 | if (!(f = fopen(path, "r"))) |
54 | return NULL; |
55 | |
56 | /* read "<name>\n" from sysfs */ |
57 | if (fgets(name, sizeof(name), f) && (sz = strlen(name)) > 1) { |
58 | name[sz - 1] = '\0'; |
59 | snprintf(path, sizeof(path), "/dev/mapper/%s", name); |
60 | res = strcpy(canonical, path); |
61 | } |
62 | fclose(f); |
63 | return res; |
64 | } |
65 | |
66 | /* |
67 | * Canonicalize a device path |
68 | * |
69 | * Workaround from "basinilya" for fixing device mapper paths. |
70 | * |
71 | * Background (Phillip Susi, 2011-04-09) |
72 | * - ntfs-3g canonicalizes the device name so that if you mount with |
73 | * /dev/mapper/foo, the device name listed in mtab is /dev/dm-n, |
74 | * so you can not umount /dev/mapper/foo |
75 | * - umount won't even recognize and translate /dev/dm-n to the mount |
76 | * point, apparently because of the '-' involved. Editing mtab and |
77 | * removing the '-' allows you to umount /dev/dmn successfully. |
78 | * |
79 | * This code restores the devmapper name after canonicalization, |
80 | * until a proper fix is implemented. |
81 | */ |
82 | |
83 | char *ntfs_realpath_canonicalize(const char *path, char *canonical) |
84 | { |
85 | char *p; |
86 | |
87 | if (path == NULL) |
88 | return NULL; |
89 | |
90 | if (!ntfs_realpath(path, canonical)) |
91 | return NULL; |
92 | |
93 | p = strrchr(canonical, '/'); |
94 | if (p && strncmp(p, "/dm-", 4) == 0 && isdigit(*(p + 4))) { |
95 | p = canonicalize_dm_name(p+1, canonical); |
96 | if (p) |
97 | return p; |
98 | } |
99 | |
100 | return canonical; |
101 | } |
102 | |
103 | #endif |
104 |