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