Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
path.cpp
Go to the documentation of this file.
1
29#ifndef _WIN32
30# ifdef __linux__
31 // for symlink()
32# ifndef _XOPEN_SOURCE
33# define _XOPEN_SOURCE
34# endif
35# ifndef _XOPEN_SOURCE_EXTENDED
36# define _XOPEN_SOURCE_EXTENDED
37# endif
38# endif // __linux__
39
40# include <unistd.h> // for getcwd()
41# include <sys/stat.h> // for struct stat, stat()
42#else
43# include <direct.h> // for struct _stat
44# include <io.h>
45# include <windows.h> // for _getcwd()
46# include <sys/types.h>
47# include <sys/stat.h> // for struct stat, stat()
48#endif // _WIN32
49
50
51#include "path.h"
52
53#include "diagnostic.h" // for issue_diag()
54
55#include <cassert> // for assert()
56#include <cerrno> // for ERANGE
57#include <cstdlib> // for getenv()
58#include <cstring> // for strerror()
59#include <string> // for string
60
61
62static char* get_cwd (char* s, std::size_t l)
63{
64#if !defined (_MSC_VER)
65 return getcwd (s, l);
66#else
67 return _getcwd (s, l);
68#endif
69}
70
71
72#if !defined (_WIN32) && !defined (__CYGWIN__)
73
74void
75create_symlink (const std::string &dir,
76 const std::string &xname,
77 const std::string &sname)
78{
79 int ret = 0;
80 char* pret = 0;
81 char buf [1024];
82
83 if (dir.size ()) {
84 pret = get_cwd (buf, 1024);
85 if (pret == 0) {
86 issue_diag (213, true, 0,
87 "could not retrieve current working directory\n") ;
88 }
89
90 ret = chdir (dir.c_str ());
91 if (ret == -1)
92 issue_diag (214, false, 0, "could not change directory to %s\n",
93 dir.c_str ()) ;
94 }
95
96 ret = symlink(xname.c_str(), sname.c_str());
97
98#ifdef EEXIST
99
100 if (ret == -1 && errno != EEXIST) {
101 issue_diag (215, false, 0,
102 "could not create symbolic link to %s "
103 "locale database (%s)\n",
104 xname.c_str (), std::strerror (errno)) ;
105 }
106
107#endif // EEXIST
108
109 // go back to previous wd
110 if (dir.size ()) {
111 chdir (pret);
112 }
113}
114
115#endif // !_WIN32 && !__CYGWIN__
116
117
118inline int
119filemode (const char *path)
120{
121 assert (0 != path);
122
123 struct stat buf;
124 return stat (path, &buf) ? 0 : buf.st_mode;
125}
126
127
128std::string
129get_pathname (const std::string &fname,
130 const std::string &other /* = std::string () */)
131{
132 // use absolute path as given by fname
133#if !defined (_WIN32)
134 if (fname.size () && _RWSTD_PATH_SEP == fname [0])
135#else
136 if (fname.size () &&
137 fname [1] && fname [1] == ':' &&
138 fname [2] && fname [2] == _RWSTD_PATH_SEP)
139#endif
140 return fname;
141
142 std::string pathname;
143 std::string dir_other (
144 other.substr (0,other.rfind (_RWSTD_PATH_SEP) + 1));
145
146 // OR use the path given through "other", be it relative or absolute
147#if !defined (_WIN32)
148 if (other.size () && _RWSTD_PATH_SEP == other [0]) {
149#else
150 if (other.size () &&
151 other [1] && other [1] == ':' &&
152 other [2] && other [2] == _RWSTD_PATH_SEP) {
153#endif
154 // other is an absolute path; compose dirname(other) + fname
155 (pathname += dir_other) += fname;
156
157 } else {
158 pathname.resize (1024);
159
160 // other is a relative path; compose cwd() + dirname(other) + fname
161 while (!get_cwd (&pathname [0], pathname.size ())) {
162 if (ERANGE != errno) {
163 issue_diag (213, true, 0,
164 "could not retrieve current working directory\n");
165 return fname;
166 }
167 // buffer too small, reallocate
168 pathname.resize (pathname.size () * 2);
169 }
170
171 pathname.resize (std::strlen (pathname.data ()));
172
173 if (pathname.size() &&
174 pathname [pathname.size () - 1] != _RWSTD_PATH_SEP)
175 pathname += _RWSTD_PATH_SEP;
176
177 (pathname += dir_other) += fname;
178 }
179
180#if !defined (_MSC_VER)
181 if (S_ISREG (filemode (pathname.c_str ())))
182#else
183 if (S_IFREG & filemode (pathname.c_str ()))
184#endif // !defined (_MSC_VER)
185 return pathname;
186
187
188 // use the value of RWSTD_SRC_ROOT
189 const char* const src_root = std::getenv ("RWSTD_SRC_ROOT");
190 if (src_root && *src_root) {
191 // if the environment variable is not empty, append `fname'
192 // to it and see if the file exists and names a regular file
193 // if so, return its pathname
194 pathname = src_root;
195 (((pathname += _RWSTD_PATH_SEP) += "src") += _RWSTD_PATH_SEP) += fname;
196
197#if !defined (_MSC_VER)
198 if (S_ISREG (filemode (pathname.c_str ())))
199#else
200 if (S_IFREG & filemode (pathname.c_str ()))
201#endif // !defined (_MSC_VER)
202 return pathname;
203 }
204
205 // allocate a sufficiently large buffer for the cwd
206 pathname.resize (1024);
207
208 // use current working directory
209 while (!get_cwd (&pathname [0], pathname.size ())) {
210
211 if (ERANGE != errno) {
212 issue_diag (213, true, 0,
213 "could not retrieve current working directory\n");
214 return fname;
215 }
216
217 // buffer too small, reallocate
218 pathname.resize (pathname.size () * 2);
219 }
220
221 // chop off everything past the terminating NUL
222 pathname.resize (std::strlen (pathname.data ()));
223 pathname += fname;
224
225#if !defined (_MSC_VER)
226 if (S_ISREG (filemode (pathname.c_str ())))
227#else
228 if (S_IFREG & filemode (pathname.c_str ()))
229#endif // !defined (_MSC_VER)
230 return pathname;
231
232 return fname;
233}
234
235
236int makedir (const char *name)
237{
238#ifdef _WIN32
239
240 if ( 0 == CreateDirectory (name, NULL)
241 && GetLastError () != ERROR_ALREADY_EXISTS) {
242
243 LPVOID lpMsgBuf;
244
245 FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER
246 | FORMAT_MESSAGE_FROM_SYSTEM
247 | FORMAT_MESSAGE_IGNORE_INSERTS,
248 0,
249 GetLastError (),
250 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
251 (LPTSTR)&lpMsgBuf,
252 0,
253 0);
254
255 issue_diag (E_CALL, true, 0, (char*)lpMsgBuf);
256
257 return -1;
258 }
259
260#else // ifndef _WIN32
261
262 if (-1 == mkdir (name, 0755)) {
263
264# ifdef EEXIST
265
266 if (errno != EEXIST) {
267 issue_diag (E_CALL, true, 0, "failed to create directory %s: %s\n",
268 name, std::strerror (errno));
269
270 return -1;
271 }
272
273# endif // EEXIST
274
275 }
276
277#endif // _WIN32
278
279 return 0;
280}
#define buf
Definition 17.names.cpp:452
#define s
#define ERANGE
#define assert(expr)
Definition _cassert.h:40
#define NULL
#define _RWSTD_PATH_SEP
Definition _config.h:297
A TOML path.
Definition path.hpp:209
const char * name
Definition codecvt1.cpp:72
bool issue_diag(int type, bool, const Scanner::token_t *token, const char *fmt,...)
@ E_CALL
Definition diagnostic.h:57
int filemode(const char *path)
Definition path.cpp:119
void create_symlink(const std::string &dir, const std::string &xname, const std::string &sname)
Definition path.cpp:75
std::string get_pathname(const std::string &fname, const std::string &other)
Definition path.cpp:129
int makedir(const char *name)
Definition path.cpp:236