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 name[MAPPERNAMELTH + 16]; 49 char path[sizeof(name) + 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