1//
2// Path_UNIX.cpp
3//
4// Library: Foundation
5// Package: Filesystem
6// Module: Path
7//
8// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/Path_UNIX.h"
16#include "Poco/Exception.h"
17#include "Poco/Environment_UNIX.h"
18#include "Poco/Ascii.h"
19#include <unistd.h>
20#include <stdlib.h>
21#include <sys/types.h>
22#if !defined(POCO_VXWORKS)
23#include <pwd.h>
24#endif
25#include <climits>
26
27
28#ifndef PATH_MAX
29#define PATH_MAX 1024 // fallback
30#endif
31
32
33namespace Poco {
34
35
36std::string PathImpl::currentImpl()
37{
38 std::string path;
39 char cwd[PATH_MAX];
40 if (getcwd(cwd, sizeof(cwd)))
41 path = cwd;
42 else
43 throw SystemException("cannot get current directory");
44 std::string::size_type n = path.size();
45 if (n > 0 && path[n - 1] != '/') path.append("/");
46 return path;
47}
48
49
50std::string PathImpl::homeImpl()
51{
52#if defined(POCO_VXWORKS)
53 if (EnvironmentImpl::hasImpl("HOME"))
54 return EnvironmentImpl::getImpl("HOME");
55 else
56 return "/";
57#else
58 std::string path;
59 struct passwd* pwd = getpwuid(getuid());
60 if (pwd)
61 path = pwd->pw_dir;
62 else
63 {
64 pwd = getpwuid(geteuid());
65 if (pwd)
66 path = pwd->pw_dir;
67 else
68 if (EnvironmentImpl::hasImpl("HOME"))
69 path = EnvironmentImpl::getImpl("HOME");
70 }
71 std::string::size_type n = path.size();
72 if (n > 0 && path[n - 1] != '/') path.append("/");
73 return path;
74#endif
75}
76
77
78std::string PathImpl::configHomeImpl()
79{
80#if defined(POCO_VXWORKS)
81 return PathImpl::homeImpl();
82#elif POCO_OS == POCO_OS_MAC_OS_X
83 std::string path = PathImpl::homeImpl();
84 std::string::size_type n = path.size();
85 if (n > 0 && path[n - 1] == '/')
86 path.append("Library/Preferences/");
87 return path;
88#else
89 std::string path;
90 if (EnvironmentImpl::hasImpl("XDG_CONFIG_HOME"))
91 path = EnvironmentImpl::getImpl("XDG_CONFIG_HOME");
92 if (!path.empty())
93 return path;
94
95 path = PathImpl::homeImpl();
96 std::string::size_type n = path.size();
97 if (n > 0 && path[n - 1] == '/')
98 path.append(".config/");
99
100 return path;
101#endif
102}
103
104
105std::string PathImpl::dataHomeImpl()
106{
107#if defined(POCO_VXWORKS)
108 return PathImpl::homeImpl();
109#elif POCO_OS == POCO_OS_MAC_OS_X
110 std::string path = PathImpl::homeImpl();
111 std::string::size_type n = path.size();
112 if (n > 0 && path[n - 1] == '/')
113 path.append("Library/Application Support/");
114 return path;
115#else
116 std::string path;
117 if (EnvironmentImpl::hasImpl("XDG_DATA_HOME"))
118 path = EnvironmentImpl::getImpl("XDG_DATA_HOME");
119 if (!path.empty())
120 return path;
121
122 path = PathImpl::homeImpl();
123 std::string::size_type n = path.size();
124 if (n > 0 && path[n - 1] == '/')
125 path.append(".local/share/");
126
127 return path;
128#endif
129}
130
131
132std::string PathImpl::cacheHomeImpl()
133{
134#if defined(POCO_VXWORKS)
135 return PathImpl::tempImpl();
136#elif POCO_OS == POCO_OS_MAC_OS_X
137 std::string path = PathImpl::homeImpl();
138 std::string::size_type n = path.size();
139 if (n > 0 && path[n - 1] == '/')
140 path.append("Library/Caches/");
141 return path;
142#else
143 std::string path;
144 if (EnvironmentImpl::hasImpl("XDG_CACHE_HOME"))
145 path = EnvironmentImpl::getImpl("XDG_CACHE_HOME");
146 if (!path.empty())
147 return path;
148
149 path = PathImpl::homeImpl();
150 std::string::size_type n = path.size();
151 if (n > 0 && path[n - 1] == '/')
152 path.append(".cache/");
153
154 return path;
155#endif
156}
157
158
159std::string PathImpl::tempImpl()
160{
161 std::string path;
162 char* tmp = getenv("TMPDIR");
163 if (tmp)
164 {
165 path = tmp;
166 std::string::size_type n = path.size();
167 if (n > 0 && path[n - 1] != '/') path.append("/");
168 }
169 else
170 {
171 path = "/tmp/";
172 }
173 return path;
174}
175
176
177std::string PathImpl::configImpl()
178{
179 std::string path;
180
181#if POCO_OS == POCO_OS_MAC_OS_X
182 path = "/Library/Preferences/";
183#else
184 path = "/etc/";
185#endif
186 return path;
187}
188
189
190std::string PathImpl::nullImpl()
191{
192#if defined(POCO_VXWORKS)
193 return "/null";
194#else
195 return "/dev/null";
196#endif
197}
198
199
200std::string PathImpl::expandImpl(const std::string& path)
201{
202 std::string result;
203 std::string::const_iterator it = path.begin();
204 std::string::const_iterator end = path.end();
205 if (it != end && *it == '~')
206 {
207 ++it;
208 if (it != end && *it == '/')
209 {
210 const char* homeEnv = getenv("HOME");
211 if (homeEnv)
212 {
213 result += homeEnv;
214 std::string::size_type resultSize = result.size();
215 if (resultSize > 0 && result[resultSize - 1] != '/')
216 result.append("/");
217 }
218 else
219 {
220 result += homeImpl();
221 }
222 ++it;
223 }
224 else result += '~';
225 }
226 while (it != end)
227 {
228 if (*it == '\\')
229 {
230 ++it;
231 if (*it == '$')
232 {
233 result += *it++;
234 }
235 }
236 else if (*it == '$')
237 {
238 std::string var;
239 ++it;
240 if (it != end && *it == '{')
241 {
242 ++it;
243 while (it != end && *it != '}') var += *it++;
244 if (it != end) ++it;
245 }
246 else
247 {
248 while (it != end && (Ascii::isAlphaNumeric(*it) || *it == '_')) var += *it++;
249 }
250 char* val = getenv(var.c_str());
251 if (val) result += val;
252 }
253 else result += *it++;
254 }
255 return result;
256}
257
258
259void PathImpl::listRootsImpl(std::vector<std::string>& roots)
260{
261 roots.clear();
262 roots.push_back("/");
263}
264
265
266} // namespace Poco
267