1987da915Sopenharmony_ci/* 2987da915Sopenharmony_ci * realpath.c - realpath() aware of device mapper 3987da915Sopenharmony_ci * Originated from the util-linux project. 4987da915Sopenharmony_ci */ 5987da915Sopenharmony_ci 6987da915Sopenharmony_ci#ifdef HAVE_CONFIG_H 7987da915Sopenharmony_ci#include "config.h" 8987da915Sopenharmony_ci#endif 9987da915Sopenharmony_ci 10987da915Sopenharmony_ci#include <stdlib.h> 11987da915Sopenharmony_ci#include <stdio.h> 12987da915Sopenharmony_ci#include <string.h> 13987da915Sopenharmony_ci 14987da915Sopenharmony_ci#ifdef HAVE_LIMITS_H 15987da915Sopenharmony_ci#include <limits.h> 16987da915Sopenharmony_ci#endif 17987da915Sopenharmony_ci#ifdef HAVE_CTYPE_H 18987da915Sopenharmony_ci#include <ctype.h> 19987da915Sopenharmony_ci#endif 20987da915Sopenharmony_ci 21987da915Sopenharmony_ci#include "param.h" 22987da915Sopenharmony_ci#include "realpath.h" 23987da915Sopenharmony_ci 24987da915Sopenharmony_ci/* If there is no realpath() on the system, provide a dummy one. */ 25987da915Sopenharmony_ci#ifndef HAVE_REALPATH 26987da915Sopenharmony_cichar *ntfs_realpath(const char *path, char *resolved_path) 27987da915Sopenharmony_ci{ 28987da915Sopenharmony_ci strncpy(resolved_path, path, PATH_MAX); 29987da915Sopenharmony_ci resolved_path[PATH_MAX] = '\0'; 30987da915Sopenharmony_ci return resolved_path; 31987da915Sopenharmony_ci} 32987da915Sopenharmony_ci#endif 33987da915Sopenharmony_ci 34987da915Sopenharmony_ci 35987da915Sopenharmony_ci#ifdef linux 36987da915Sopenharmony_ci 37987da915Sopenharmony_ci/* 38987da915Sopenharmony_ci * Converts private "dm-N" names to "/dev/mapper/<name>" 39987da915Sopenharmony_ci * 40987da915Sopenharmony_ci * Since 2.6.29 (patch 784aae735d9b0bba3f8b9faef4c8b30df3bf0128) kernel sysfs 41987da915Sopenharmony_ci * provides the real DM device names in /sys/block/<ptname>/dm/name 42987da915Sopenharmony_ci */ 43987da915Sopenharmony_cistatic char * 44987da915Sopenharmony_cicanonicalize_dm_name(const char *ptname, char *canonical) 45987da915Sopenharmony_ci{ 46987da915Sopenharmony_ci FILE *f; 47987da915Sopenharmony_ci size_t sz; 48987da915Sopenharmony_ci char name[MAPPERNAMELTH + 16]; 49987da915Sopenharmony_ci char path[sizeof(name) + 16]; 50987da915Sopenharmony_ci char *res = NULL; 51987da915Sopenharmony_ci 52987da915Sopenharmony_ci snprintf(path, sizeof(path), "/sys/block/%s/dm/name", ptname); 53987da915Sopenharmony_ci if (!(f = fopen(path, "r"))) 54987da915Sopenharmony_ci return NULL; 55987da915Sopenharmony_ci 56987da915Sopenharmony_ci /* read "<name>\n" from sysfs */ 57987da915Sopenharmony_ci if (fgets(name, sizeof(name), f) && (sz = strlen(name)) > 1) { 58987da915Sopenharmony_ci name[sz - 1] = '\0'; 59987da915Sopenharmony_ci snprintf(path, sizeof(path), "/dev/mapper/%s", name); 60987da915Sopenharmony_ci res = strcpy(canonical, path); 61987da915Sopenharmony_ci } 62987da915Sopenharmony_ci fclose(f); 63987da915Sopenharmony_ci return res; 64987da915Sopenharmony_ci} 65987da915Sopenharmony_ci 66987da915Sopenharmony_ci/* 67987da915Sopenharmony_ci * Canonicalize a device path 68987da915Sopenharmony_ci * 69987da915Sopenharmony_ci * Workaround from "basinilya" for fixing device mapper paths. 70987da915Sopenharmony_ci * 71987da915Sopenharmony_ci * Background (Phillip Susi, 2011-04-09) 72987da915Sopenharmony_ci * - ntfs-3g canonicalizes the device name so that if you mount with 73987da915Sopenharmony_ci * /dev/mapper/foo, the device name listed in mtab is /dev/dm-n, 74987da915Sopenharmony_ci * so you can not umount /dev/mapper/foo 75987da915Sopenharmony_ci * - umount won't even recognize and translate /dev/dm-n to the mount 76987da915Sopenharmony_ci * point, apparently because of the '-' involved. Editing mtab and 77987da915Sopenharmony_ci * removing the '-' allows you to umount /dev/dmn successfully. 78987da915Sopenharmony_ci * 79987da915Sopenharmony_ci * This code restores the devmapper name after canonicalization, 80987da915Sopenharmony_ci * until a proper fix is implemented. 81987da915Sopenharmony_ci */ 82987da915Sopenharmony_ci 83987da915Sopenharmony_cichar *ntfs_realpath_canonicalize(const char *path, char *canonical) 84987da915Sopenharmony_ci{ 85987da915Sopenharmony_ci char *p; 86987da915Sopenharmony_ci 87987da915Sopenharmony_ci if (path == NULL) 88987da915Sopenharmony_ci return NULL; 89987da915Sopenharmony_ci 90987da915Sopenharmony_ci if (!ntfs_realpath(path, canonical)) 91987da915Sopenharmony_ci return NULL; 92987da915Sopenharmony_ci 93987da915Sopenharmony_ci p = strrchr(canonical, '/'); 94987da915Sopenharmony_ci if (p && strncmp(p, "/dm-", 4) == 0 && isdigit(*(p + 4))) { 95987da915Sopenharmony_ci p = canonicalize_dm_name(p+1, canonical); 96987da915Sopenharmony_ci if (p) 97987da915Sopenharmony_ci return p; 98987da915Sopenharmony_ci } 99987da915Sopenharmony_ci 100987da915Sopenharmony_ci return canonical; 101987da915Sopenharmony_ci} 102987da915Sopenharmony_ci 103987da915Sopenharmony_ci#endif 104