ConfigPath.cxx 2.95 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright (C) 2003-2013 The Music Player Daemon Project
3
 * http://www.musicpd.org
Warren Dukes's avatar
Warren Dukes committed
4 5 6 7 8 9 10 11 12 13
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
14 15 16 17
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Warren Dukes's avatar
Warren Dukes committed
18 19
 */

20
#include "config.h"
Max Kellermann's avatar
Max Kellermann committed
21
#include "ConfigPath.hxx"
22
#include "fs/AllocatedPath.hxx"
23
#include "fs/Traits.hxx"
24
#include "fs/Domain.hxx"
25
#include "util/Error.hxx"
26
#include "ConfigGlobal.hxx"
Warren Dukes's avatar
Warren Dukes committed
27

28 29
#include <glib.h>

30 31
#include <assert.h>
#include <string.h>
32 33 34

#ifndef WIN32
#include <pwd.h>
35 36 37 38

/**
 * Determine a given user's home directory.
 */
39
static AllocatedPath
40 41 42 43 44 45
GetHome(const char *user, Error &error)
{
	passwd *pw = getpwnam(user);
	if (pw == nullptr) {
		error.Format(path_domain,
			     "no such user: %s", user);
46
		return AllocatedPath::Null();
47 48
	}

49
	return AllocatedPath::FromFS(pw->pw_dir);
50 51 52 53 54
}

/**
 * Determine the current user's home directory.
 */
55
static AllocatedPath
56 57 58
GetHome(Error &error)
{
	const char *home = g_get_home_dir();
59
	if (home == nullptr) {
60 61
		error.Set(path_domain,
			  "problems getting home for current user");
62
		return AllocatedPath::Null();
63
	}
64

65
	return AllocatedPath::FromUTF8(home, error);
66 67 68 69 70
}

/**
 * Determine the configured user's home directory.
 */
71
static AllocatedPath
72 73 74 75 76 77 78 79
GetConfiguredHome(Error &error)
{
	const char *user = config_get_string(CONF_USER, nullptr);
	return user != nullptr
		? GetHome(user, error)
		: GetHome(error);
}

80
#endif
81

82
AllocatedPath
83
ParsePath(const char *path, Error &error)
84
{
Max Kellermann's avatar
Max Kellermann committed
85
	assert(path != nullptr);
86

87
#ifndef WIN32
88
	if (path[0] == '~') {
89 90
		++path;

91 92 93
		if (*path == '\0')
			return GetConfiguredHome(error);

94
		AllocatedPath home = AllocatedPath::Null();
95 96

		if (*path == '/') {
97
			home = GetConfiguredHome(error);
98 99

			++path;
100
		} else {
101
			const char *slash = strchr(path, '/');
102 103 104 105 106
			const char *end = slash == nullptr
					? path + strlen(path)
					: slash;
			const std::string user(path, end);
			home = GetHome(user.c_str(), error);
107

108 109 110 111
			if (slash == nullptr)
				return home;

			path = slash + 1;
112 113
		}

114
		if (home.IsNull())
115
			return AllocatedPath::Null();
116

117
		AllocatedPath path2 = AllocatedPath::FromUTF8(path, error);
118
		if (path2.IsNull())
119
			return AllocatedPath::Null();
120

121
		return AllocatedPath::Build(home, path2);
122
	} else if (!PathTraits::IsAbsoluteUTF8(path)) {
123 124
		error.Format(path_domain,
			     "not an absolute path: %s", path);
125
		return AllocatedPath::Null();
126
	} else {
127
#endif
128
		return AllocatedPath::FromUTF8(path, error);
129
#ifndef WIN32
130
	}
131
#endif
132
}