Mercurial > octave
comparison liboctave/system/file-ops.cc @ 21733:cb0fdd941d84
use namespace for system file_ops class
* file-ops.h, file-ops.cc: Put file_ops class and related functions in
octave::sys:: namespace. Change all uses.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 19 May 2016 00:33:18 -0400 |
parents | 6a1eded90355 |
children | 11af9c03400c |
comparison
equal
deleted
inserted
replaced
21732:6a1eded90355 | 21733:cb0fdd941d84 |
---|---|
56 | 56 |
57 #if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) | 57 #if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) |
58 # include <algorithm> | 58 # include <algorithm> |
59 #endif | 59 #endif |
60 | 60 |
61 file_ops *file_ops::instance = 0; | 61 namespace |
62 | 62 octave |
63 bool | |
64 file_ops::instance_ok (void) | |
65 { | 63 { |
66 bool retval = true; | 64 namespace |
67 | 65 sys |
68 if (! instance) | 66 { |
69 { | 67 file_ops *octave::sys::file_ops::instance = 0; |
68 | |
69 bool | |
70 octave::sys::file_ops::instance_ok (void) | |
71 { | |
72 bool retval = true; | |
73 | |
74 if (! instance) | |
75 { | |
70 #if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) | 76 #if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) |
71 char system_dir_sep_char = '\\'; | 77 char system_dir_sep_char = '\\'; |
72 std::string system_dir_sep_str = "\\"; | 78 std::string system_dir_sep_str = "\\"; |
73 #else | 79 #else |
74 char system_dir_sep_char = '/'; | 80 char system_dir_sep_char = '/'; |
75 std::string system_dir_sep_str = "/"; | 81 std::string system_dir_sep_str = "/"; |
76 #endif | 82 #endif |
77 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) | 83 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) |
78 std::string system_dir_sep_chars = "/\\"; | 84 std::string system_dir_sep_chars = "/\\"; |
79 #else | 85 #else |
80 std::string system_dir_sep_chars = system_dir_sep_str; | 86 std::string system_dir_sep_chars = system_dir_sep_str; |
81 #endif | 87 #endif |
82 | 88 |
83 instance = new file_ops (system_dir_sep_char, system_dir_sep_str, | 89 instance = new file_ops (system_dir_sep_char, system_dir_sep_str, |
84 system_dir_sep_chars); | 90 system_dir_sep_chars); |
85 | 91 |
86 if (instance) | 92 if (instance) |
87 singleton_cleanup_list::add (cleanup_instance); | 93 singleton_cleanup_list::add (cleanup_instance); |
88 } | 94 } |
89 | 95 |
90 if (! instance) | 96 if (! instance) |
91 (*current_liboctave_error_handler) | 97 (*current_liboctave_error_handler) |
92 ("unable to create file_ops object!"); | 98 ("unable to create file_ops object!"); |
93 | 99 |
94 return retval; | 100 return retval; |
95 } | 101 } |
96 | 102 |
97 // The following tilde-expansion code was stolen and adapted from | 103 // The following tilde-expansion code was stolen and adapted from |
98 // readline. | 104 // readline. |
99 | 105 |
100 // The default value of tilde_additional_prefixes. This is set to | 106 // The default value of tilde_additional_prefixes. This is set to |
101 // whitespace preceding a tilde so that simple programs which do not | 107 // whitespace preceding a tilde so that simple programs which do not |
102 // perform any word separation get desired behavior. | 108 // perform any word separation get desired behavior. |
103 static const char *default_prefixes[] = { " ~", "\t~", ":~", 0 }; | 109 static const char *default_prefixes[] = { " ~", "\t~", ":~", 0 }; |
104 | 110 |
105 // The default value of tilde_additional_suffixes. This is set to | 111 // The default value of tilde_additional_suffixes. This is set to |
106 // whitespace or newline so that simple programs which do not perform | 112 // whitespace or newline so that simple programs which do not perform |
107 // any word separation get desired behavior. | 113 // any word separation get desired behavior. |
108 static const char *default_suffixes[] = { " ", "\n", ":", 0 }; | 114 static const char *default_suffixes[] = { " ", "\n", ":", 0 }; |
109 | 115 |
110 // If non-null, this contains the address of a function that the | 116 // If non-null, this contains the address of a function that the |
111 // application wants called before trying the standard tilde | 117 // application wants called before trying the standard tilde |
112 // expansions. The function is called with the text sans tilde, and | 118 // expansions. The function is called with the text sans tilde, and |
113 // returns a malloc()'ed string which is the expansion, or a NULL | 119 // returns a malloc()'ed string which is the expansion, or a NULL |
114 // pointer if the expansion fails. | 120 // pointer if the expansion fails. |
115 file_ops::tilde_expansion_hook file_ops::tilde_expansion_preexpansion_hook = 0; | 121 octave::sys::file_ops::tilde_expansion_hook octave::sys::file_ops::tilde_expansion_preexpansion_hook = 0; |
116 | 122 |
117 // If non-null, this contains the address of a function to call if the | 123 // If non-null, this contains the address of a function to call if the |
118 // standard meaning for expanding a tilde fails. The function is | 124 // standard meaning for expanding a tilde fails. The function is |
119 // called with the text (sans tilde, as in "foo"), and returns a | 125 // called with the text (sans tilde, as in "foo"), and returns a |
120 // malloc()'ed string which is the expansion, or a NULL pointer if | 126 // malloc()'ed string which is the expansion, or a NULL pointer if |
121 // there is no expansion. | 127 // there is no expansion. |
122 file_ops::tilde_expansion_hook file_ops::tilde_expansion_failure_hook = 0; | 128 octave::sys::file_ops::tilde_expansion_hook octave::sys::file_ops::tilde_expansion_failure_hook = 0; |
123 | 129 |
124 // When non-null, this is a NULL terminated array of strings which are | 130 // When non-null, this is a NULL terminated array of strings which are |
125 // duplicates for a tilde prefix. Bash uses this to expand '=~' and | 131 // duplicates for a tilde prefix. Bash uses this to expand '=~' and |
126 // ':~'. | 132 // ':~'. |
127 string_vector file_ops::tilde_additional_prefixes = default_prefixes; | 133 string_vector octave::sys::file_ops::tilde_additional_prefixes = default_prefixes; |
128 | 134 |
129 // When non-null, this is a NULL terminated array of strings which | 135 // When non-null, this is a NULL terminated array of strings which |
130 // match the end of a username, instead of just "/". Bash sets this | 136 // match the end of a username, instead of just "/". Bash sets this |
131 // to ':' and '=~'. | 137 // to ':' and '=~'. |
132 string_vector file_ops::tilde_additional_suffixes = default_suffixes; | 138 string_vector octave::sys::file_ops::tilde_additional_suffixes = default_suffixes; |
133 | 139 |
134 // Find the start of a tilde expansion in S, and return the index | 140 // Find the start of a tilde expansion in S, and return the index |
135 // of the tilde which starts the expansion. Place the length of the | 141 // of the tilde which starts the expansion. Place the length of the |
136 // text which identified this tilde starter in LEN, excluding the | 142 // text which identified this tilde starter in LEN, excluding the |
137 // tilde itself. | 143 // tilde itself. |
138 | 144 |
139 static size_t | 145 static size_t |
140 tilde_find_prefix (const std::string& s, size_t& len) | 146 tilde_find_prefix (const std::string& s, size_t& len) |
141 { | 147 { |
142 len = 0; | 148 len = 0; |
143 | 149 |
144 size_t s_len = s.length (); | 150 size_t s_len = s.length (); |
145 | 151 |
146 if (s_len == 0 || s[0] == '~') | 152 if (s_len == 0 || s[0] == '~') |
147 return 0; | 153 return 0; |
148 | 154 |
149 string_vector prefixes = file_ops::tilde_additional_prefixes; | 155 string_vector prefixes = octave::sys::file_ops::tilde_additional_prefixes; |
150 | 156 |
151 if (! prefixes.empty ()) | 157 if (! prefixes.empty ()) |
152 { | 158 { |
153 for (size_t i = 0; i < s_len; i++) | 159 for (size_t i = 0; i < s_len; i++) |
154 { | |
155 for (int j = 0; j < prefixes.numel (); j++) | |
156 { | 160 { |
157 size_t pfx_len = prefixes[j].length (); | 161 for (int j = 0; j < prefixes.numel (); j++) |
158 | |
159 if (prefixes[j] == s.substr (i, pfx_len)) | |
160 { | 162 { |
161 len = pfx_len - 1; | 163 size_t pfx_len = prefixes[j].length (); |
162 return i + len; | 164 |
165 if (prefixes[j] == s.substr (i, pfx_len)) | |
166 { | |
167 len = pfx_len - 1; | |
168 return i + len; | |
169 } | |
163 } | 170 } |
164 } | 171 } |
165 } | 172 } |
166 } | 173 |
167 | 174 return s_len; |
168 return s_len; | 175 } |
169 } | 176 |
170 | 177 // Find the end of a tilde expansion in S, and return the index |
171 // Find the end of a tilde expansion in S, and return the index | 178 // of the character which ends the tilde definition. |
172 // of the character which ends the tilde definition. | 179 |
173 | 180 static size_t |
174 static size_t | 181 tilde_find_suffix (const std::string& s) |
175 tilde_find_suffix (const std::string& s) | 182 { |
176 { | 183 size_t s_len = s.length (); |
177 size_t s_len = s.length (); | 184 |
178 | 185 string_vector suffixes = octave::sys::file_ops::tilde_additional_suffixes; |
179 string_vector suffixes = file_ops::tilde_additional_suffixes; | 186 |
180 | 187 size_t i = 0; |
181 size_t i = 0; | 188 |
182 | 189 for ( ; i < s_len; i++) |
183 for ( ; i < s_len; i++) | 190 { |
184 { | 191 if (octave::sys::file_ops::is_dir_sep (s[i])) |
185 if (file_ops::is_dir_sep (s[i])) | 192 break; |
186 break; | 193 |
187 | 194 if (! suffixes.empty ()) |
188 if (! suffixes.empty ()) | |
189 { | |
190 for (int j = 0; j < suffixes.numel (); j++) | |
191 { | 195 { |
192 size_t sfx_len = suffixes[j].length (); | 196 for (int j = 0; j < suffixes.numel (); j++) |
193 | 197 { |
194 if (suffixes[j] == s.substr (i, sfx_len)) | 198 size_t sfx_len = suffixes[j].length (); |
195 return i; | 199 |
200 if (suffixes[j] == s.substr (i, sfx_len)) | |
201 return i; | |
202 } | |
196 } | 203 } |
197 } | 204 } |
198 } | 205 |
199 | 206 return i; |
200 return i; | 207 } |
201 } | 208 |
202 | 209 // Take FNAME and return the tilde prefix we want expanded. |
203 // Take FNAME and return the tilde prefix we want expanded. | 210 |
204 | 211 static std::string |
205 static std::string | 212 isolate_tilde_prefix (const std::string& fname) |
206 isolate_tilde_prefix (const std::string& fname) | 213 { |
207 { | 214 size_t f_len = fname.length (); |
208 size_t f_len = fname.length (); | 215 |
209 | 216 size_t len = 1; |
210 size_t len = 1; | 217 |
211 | 218 while (len < f_len && ! octave::sys::file_ops::is_dir_sep (fname[len])) |
212 while (len < f_len && ! file_ops::is_dir_sep (fname[len])) | 219 len++; |
213 len++; | 220 |
214 | 221 return fname.substr (1, len); |
215 return fname.substr (1, len); | 222 } |
216 } | 223 |
217 | 224 // Do the work of tilde expansion on FILENAME. FILENAME starts with a |
218 // Do the work of tilde expansion on FILENAME. FILENAME starts with a | 225 // tilde. |
219 // tilde. | 226 |
220 | 227 static std::string |
221 static std::string | 228 tilde_expand_word (const std::string& filename) |
222 tilde_expand_word (const std::string& filename) | 229 { |
223 { | 230 size_t f_len = filename.length (); |
224 size_t f_len = filename.length (); | 231 |
225 | 232 if (f_len == 0 || filename[0] != '~') |
226 if (f_len == 0 || filename[0] != '~') | 233 return filename; |
227 return filename; | 234 |
228 | 235 // A leading '~/' or a bare '~' is *always* translated to the value |
229 // A leading '~/' or a bare '~' is *always* translated to the value | 236 // of $HOME or the home directory of the current user, regardless of |
230 // of $HOME or the home directory of the current user, regardless of | 237 // any preexpansion hook. |
231 // any preexpansion hook. | 238 |
232 | 239 if (f_len == 1 || octave::sys::file_ops::is_dir_sep (filename[1])) |
233 if (f_len == 1 || file_ops::is_dir_sep (filename[1])) | 240 return octave::sys::env::get_home_directory () + filename.substr (1); |
234 return octave::sys::env::get_home_directory () + filename.substr (1); | 241 |
235 | 242 std::string username = isolate_tilde_prefix (filename); |
236 std::string username = isolate_tilde_prefix (filename); | 243 |
237 | 244 size_t user_len = username.length (); |
238 size_t user_len = username.length (); | 245 |
239 | 246 std::string dirname; |
240 std::string dirname; | 247 |
241 | 248 if (octave::sys::file_ops::tilde_expansion_preexpansion_hook) |
242 if (file_ops::tilde_expansion_preexpansion_hook) | |
243 { | |
244 std::string expansion | |
245 = file_ops::tilde_expansion_preexpansion_hook (username); | |
246 | |
247 if (! expansion.empty ()) | |
248 return expansion + filename.substr (user_len+1); | |
249 } | |
250 | |
251 // No preexpansion hook, or the preexpansion hook failed. Look in the | |
252 // password database. | |
253 | |
254 octave::sys::password pw = octave::sys::password::getpwnam (username); | |
255 | |
256 if (! pw) | |
257 { | |
258 // If the calling program has a special syntax for expanding tildes, | |
259 // and we couldn't find a standard expansion, then let them try. | |
260 | |
261 if (file_ops::tilde_expansion_failure_hook) | |
262 { | 249 { |
263 std::string expansion | 250 std::string expansion |
264 = file_ops::tilde_expansion_failure_hook (username); | 251 = octave::sys::file_ops::tilde_expansion_preexpansion_hook (username); |
265 | 252 |
266 if (! expansion.empty ()) | 253 if (! expansion.empty ()) |
267 dirname = expansion + filename.substr (user_len+1); | 254 return expansion + filename.substr (user_len+1); |
268 } | 255 } |
269 | 256 |
270 // If we don't have a failure hook, or if the failure hook did not | 257 // No preexpansion hook, or the preexpansion hook failed. Look in the |
271 // expand the tilde, return a copy of what we were passed. | 258 // password database. |
272 | 259 |
273 if (dirname.length () == 0) | 260 octave::sys::password pw = octave::sys::password::getpwnam (username); |
274 dirname = filename; | 261 |
275 } | 262 if (! pw) |
276 else | 263 { |
277 dirname = pw.dir () + filename.substr (user_len+1); | 264 // If the calling program has a special syntax for expanding tildes, |
278 | 265 // and we couldn't find a standard expansion, then let them try. |
279 return dirname; | 266 |
280 } | 267 if (octave::sys::file_ops::tilde_expansion_failure_hook) |
281 | |
282 // If NAME has a leading ~ or ~user, Unix-style, expand it to the | |
283 // user's home directory. If no ~, or no <pwd.h>, just return NAME. | |
284 | |
285 std::string | |
286 file_ops::tilde_expand (const std::string& name) | |
287 { | |
288 if (name.find ('~') == std::string::npos) | |
289 return name; | |
290 else | |
291 { | |
292 std::string result; | |
293 | |
294 size_t name_len = name.length (); | |
295 | |
296 // Scan through S expanding tildes as we come to them. | |
297 | |
298 size_t pos = 0; | |
299 | |
300 while (1) | |
301 { | |
302 if (pos > name_len) | |
303 break; | |
304 | |
305 size_t len; | |
306 | |
307 // Make START point to the tilde which starts the expansion. | |
308 | |
309 size_t start = tilde_find_prefix (name.substr (pos), len); | |
310 | |
311 result.append (name.substr (pos, start)); | |
312 | |
313 // Advance STRING to the starting tilde. | |
314 | |
315 pos += start; | |
316 | |
317 // Make FINI be the index of one after the last character of the | |
318 // username. | |
319 | |
320 size_t fini = tilde_find_suffix (name.substr (pos)); | |
321 | |
322 // If both START and FINI are zero, we are all done. | |
323 | |
324 if (! (start || fini)) | |
325 break; | |
326 | |
327 // Expand the entire tilde word, and copy it into RESULT. | |
328 | |
329 std::string tilde_word = name.substr (pos, fini); | |
330 | |
331 pos += fini; | |
332 | |
333 std::string expansion = tilde_expand_word (tilde_word); | |
334 | |
335 result.append (expansion); | |
336 } | |
337 | |
338 return result; | |
339 } | |
340 } | |
341 | |
342 // A vector version of the above. | |
343 | |
344 string_vector | |
345 file_ops::tilde_expand (const string_vector& names) | |
346 { | |
347 string_vector retval; | |
348 | |
349 int n = names.numel (); | |
350 | |
351 retval.resize (n); | |
352 | |
353 for (int i = 0; i < n; i++) | |
354 retval[i] = tilde_expand (names[i]); | |
355 | |
356 return retval; | |
357 } | |
358 | |
359 std::string | |
360 file_ops::concat (const std::string& dir, const std::string& file) | |
361 { | |
362 return dir.empty () | |
363 ? file | |
364 : (is_dir_sep (dir[dir.length ()-1]) | |
365 ? dir + file | |
366 : dir + dir_sep_char () + file); | |
367 } | |
368 | |
369 std::string | |
370 file_ops::native_separator_path (const std::string& path) | |
371 { | |
372 std::string retval; | |
373 | |
374 if (dir_sep_char () == '/') | |
375 retval = path; | |
376 else | |
377 { | |
378 size_t n = path.length (); | |
379 for (size_t i = 0; i < n; i++) | |
380 { | |
381 if (path[i] == '/') | |
382 retval += dir_sep_char(); | |
383 else | |
384 retval += path[i]; | |
385 } | |
386 } | |
387 | |
388 return retval; | |
389 } | |
390 | |
391 int | |
392 octave_mkdir (const std::string& nm, mode_t md) | |
393 { | |
394 std::string msg; | |
395 return octave_mkdir (nm, md, msg); | |
396 } | |
397 | |
398 int | |
399 octave_mkdir (const std::string& name, mode_t mode, std::string& msg) | |
400 { | |
401 msg = ""; | |
402 | |
403 int status = -1; | |
404 | |
405 status = gnulib::mkdir (name.c_str (), mode); | |
406 | |
407 if (status < 0) | |
408 msg = gnulib::strerror (errno); | |
409 | |
410 return status; | |
411 } | |
412 | |
413 int | |
414 octave_mkfifo (const std::string& nm, mode_t md) | |
415 { | |
416 std::string msg; | |
417 return octave_mkfifo (nm, md, msg); | |
418 } | |
419 | |
420 int | |
421 octave_mkfifo (const std::string& name, mode_t mode, std::string& msg) | |
422 { | |
423 msg = ""; | |
424 | |
425 int status = -1; | |
426 | |
427 // With gnulib we will always have mkfifo, but some systems like MinGW | |
428 // don't have working mkfifo functions. On those systems, mkfifo will | |
429 // always return -1 and set errno. | |
430 | |
431 status = gnulib::mkfifo (name.c_str (), mode); | |
432 | |
433 if (status < 0) | |
434 msg = gnulib::strerror (errno); | |
435 | |
436 return status; | |
437 } | |
438 | |
439 int | |
440 octave_link (const std::string& old_name, const std::string& new_name) | |
441 { | |
442 std::string msg; | |
443 return octave_link (old_name, new_name, msg); | |
444 } | |
445 | |
446 int | |
447 octave_link (const std::string& old_name, | |
448 const std::string& new_name, std::string& msg) | |
449 { | |
450 msg = ""; | |
451 | |
452 int status = -1; | |
453 | |
454 status = gnulib::link (old_name.c_str (), new_name.c_str ()); | |
455 | |
456 if (status < 0) | |
457 msg = gnulib::strerror (errno); | |
458 | |
459 return status; | |
460 } | |
461 | |
462 int | |
463 octave_symlink (const std::string& old_name, const std::string& new_name) | |
464 { | |
465 std::string msg; | |
466 return octave_symlink (old_name, new_name, msg); | |
467 } | |
468 | |
469 int | |
470 octave_symlink (const std::string& old_name, | |
471 const std::string& new_name, std::string& msg) | |
472 { | |
473 msg = ""; | |
474 | |
475 int status = -1; | |
476 | |
477 status = gnulib::symlink (old_name.c_str (), new_name.c_str ()); | |
478 | |
479 if (status < 0) | |
480 msg = gnulib::strerror (errno); | |
481 | |
482 return status; | |
483 } | |
484 | |
485 int | |
486 octave_readlink (const std::string& path, std::string& result) | |
487 { | |
488 std::string msg; | |
489 return octave_readlink (path, result, msg); | |
490 } | |
491 | |
492 int | |
493 octave_readlink (const std::string& path, std::string& result, | |
494 std::string& msg) | |
495 { | |
496 int status = -1; | |
497 | |
498 msg = ""; | |
499 | |
500 char buf[MAXPATHLEN+1]; | |
501 | |
502 status = gnulib::readlink (path.c_str (), buf, MAXPATHLEN); | |
503 | |
504 if (status < 0) | |
505 msg = gnulib::strerror (errno); | |
506 else | |
507 { | |
508 buf[status] = '\0'; | |
509 result = std::string (buf); | |
510 status = 0; | |
511 } | |
512 | |
513 return status; | |
514 } | |
515 | |
516 int | |
517 octave_rename (const std::string& from, const std::string& to) | |
518 { | |
519 std::string msg; | |
520 return octave_rename (from, to, msg); | |
521 } | |
522 | |
523 int | |
524 octave_rename (const std::string& from, const std::string& to, | |
525 std::string& msg) | |
526 { | |
527 int status = -1; | |
528 | |
529 msg = ""; | |
530 | |
531 status = gnulib::rename (from.c_str (), to.c_str ()); | |
532 | |
533 if (status < 0) | |
534 msg = gnulib::strerror (errno); | |
535 | |
536 return status; | |
537 } | |
538 | |
539 int | |
540 octave_rmdir (const std::string& name) | |
541 { | |
542 std::string msg; | |
543 return octave_rmdir (name, msg); | |
544 } | |
545 | |
546 int | |
547 octave_rmdir (const std::string& name, std::string& msg) | |
548 { | |
549 msg = ""; | |
550 | |
551 int status = -1; | |
552 | |
553 status = gnulib::rmdir (name.c_str ()); | |
554 | |
555 if (status < 0) | |
556 msg = gnulib::strerror (errno); | |
557 | |
558 return status; | |
559 } | |
560 | |
561 // And a version that works recursively. | |
562 | |
563 int | |
564 octave_recursive_rmdir (const std::string& name) | |
565 { | |
566 std::string msg; | |
567 return octave_recursive_rmdir (name, msg); | |
568 } | |
569 | |
570 int | |
571 octave_recursive_rmdir (const std::string& name, std::string& msg) | |
572 { | |
573 msg = ""; | |
574 | |
575 int status = 0; | |
576 | |
577 dir_entry dir (name); | |
578 | |
579 if (dir) | |
580 { | |
581 string_vector dirlist = dir.read (); | |
582 | |
583 for (octave_idx_type i = 0; i < dirlist.numel (); i++) | |
584 { | |
585 octave_quit (); | |
586 | |
587 std::string nm = dirlist[i]; | |
588 | |
589 // Skip current directory and parent. | |
590 if (nm == "." || nm == "..") | |
591 continue; | |
592 | |
593 std::string fullnm = name + file_ops::dir_sep_str () + nm; | |
594 | |
595 // Get info about the file. Don't follow links. | |
596 file_stat fs (fullnm, false); | |
597 | |
598 if (fs) | |
599 { | 268 { |
600 if (fs.is_dir ()) | 269 std::string expansion |
270 = octave::sys::file_ops::tilde_expansion_failure_hook (username); | |
271 | |
272 if (! expansion.empty ()) | |
273 dirname = expansion + filename.substr (user_len+1); | |
274 } | |
275 | |
276 // If we don't have a failure hook, or if the failure hook did not | |
277 // expand the tilde, return a copy of what we were passed. | |
278 | |
279 if (dirname.length () == 0) | |
280 dirname = filename; | |
281 } | |
282 else | |
283 dirname = pw.dir () + filename.substr (user_len+1); | |
284 | |
285 return dirname; | |
286 } | |
287 | |
288 // If NAME has a leading ~ or ~user, Unix-style, expand it to the | |
289 // user's home directory. If no ~, or no <pwd.h>, just return NAME. | |
290 | |
291 std::string | |
292 octave::sys::file_ops::tilde_expand (const std::string& name) | |
293 { | |
294 if (name.find ('~') == std::string::npos) | |
295 return name; | |
296 else | |
297 { | |
298 std::string result; | |
299 | |
300 size_t name_len = name.length (); | |
301 | |
302 // Scan through S expanding tildes as we come to them. | |
303 | |
304 size_t pos = 0; | |
305 | |
306 while (1) | |
307 { | |
308 if (pos > name_len) | |
309 break; | |
310 | |
311 size_t len; | |
312 | |
313 // Make START point to the tilde which starts the expansion. | |
314 | |
315 size_t start = tilde_find_prefix (name.substr (pos), len); | |
316 | |
317 result.append (name.substr (pos, start)); | |
318 | |
319 // Advance STRING to the starting tilde. | |
320 | |
321 pos += start; | |
322 | |
323 // Make FINI be the index of one after the last character of the | |
324 // username. | |
325 | |
326 size_t fini = tilde_find_suffix (name.substr (pos)); | |
327 | |
328 // If both START and FINI are zero, we are all done. | |
329 | |
330 if (! (start || fini)) | |
331 break; | |
332 | |
333 // Expand the entire tilde word, and copy it into RESULT. | |
334 | |
335 std::string tilde_word = name.substr (pos, fini); | |
336 | |
337 pos += fini; | |
338 | |
339 std::string expansion = tilde_expand_word (tilde_word); | |
340 | |
341 result.append (expansion); | |
342 } | |
343 | |
344 return result; | |
345 } | |
346 } | |
347 | |
348 // A vector version of the above. | |
349 | |
350 string_vector | |
351 octave::sys::file_ops::tilde_expand (const string_vector& names) | |
352 { | |
353 string_vector retval; | |
354 | |
355 int n = names.numel (); | |
356 | |
357 retval.resize (n); | |
358 | |
359 for (int i = 0; i < n; i++) | |
360 retval[i] = tilde_expand (names[i]); | |
361 | |
362 return retval; | |
363 } | |
364 | |
365 std::string | |
366 octave::sys::file_ops::concat (const std::string& dir, const std::string& file) | |
367 { | |
368 return dir.empty () | |
369 ? file | |
370 : (is_dir_sep (dir[dir.length ()-1]) | |
371 ? dir + file | |
372 : dir + dir_sep_char () + file); | |
373 } | |
374 | |
375 std::string | |
376 octave::sys::file_ops::native_separator_path (const std::string& path) | |
377 { | |
378 std::string retval; | |
379 | |
380 if (dir_sep_char () == '/') | |
381 retval = path; | |
382 else | |
383 { | |
384 size_t n = path.length (); | |
385 for (size_t i = 0; i < n; i++) | |
386 { | |
387 if (path[i] == '/') | |
388 retval += dir_sep_char(); | |
389 else | |
390 retval += path[i]; | |
391 } | |
392 } | |
393 | |
394 return retval; | |
395 } | |
396 | |
397 int | |
398 mkdir (const std::string& nm, mode_t md) | |
399 { | |
400 std::string msg; | |
401 return octave::sys::mkdir (nm, md, msg); | |
402 } | |
403 | |
404 int | |
405 mkdir (const std::string& name, mode_t mode, std::string& msg) | |
406 { | |
407 msg = ""; | |
408 | |
409 int status = -1; | |
410 | |
411 status = gnulib::mkdir (name.c_str (), mode); | |
412 | |
413 if (status < 0) | |
414 msg = gnulib::strerror (errno); | |
415 | |
416 return status; | |
417 } | |
418 | |
419 int | |
420 mkfifo (const std::string& nm, mode_t md) | |
421 { | |
422 std::string msg; | |
423 return mkfifo (nm, md, msg); | |
424 } | |
425 | |
426 int | |
427 mkfifo (const std::string& name, mode_t mode, std::string& msg) | |
428 { | |
429 msg = ""; | |
430 | |
431 int status = -1; | |
432 | |
433 // With gnulib we will always have mkfifo, but some systems like MinGW | |
434 // don't have working mkfifo functions. On those systems, mkfifo will | |
435 // always return -1 and set errno. | |
436 | |
437 status = gnulib::mkfifo (name.c_str (), mode); | |
438 | |
439 if (status < 0) | |
440 msg = gnulib::strerror (errno); | |
441 | |
442 return status; | |
443 } | |
444 | |
445 int | |
446 link (const std::string& old_name, const std::string& new_name) | |
447 { | |
448 std::string msg; | |
449 return link (old_name, new_name, msg); | |
450 } | |
451 | |
452 int | |
453 link (const std::string& old_name, const std::string& new_name, | |
454 std::string& msg) | |
455 { | |
456 msg = ""; | |
457 | |
458 int status = -1; | |
459 | |
460 status = gnulib::link (old_name.c_str (), new_name.c_str ()); | |
461 | |
462 if (status < 0) | |
463 msg = gnulib::strerror (errno); | |
464 | |
465 return status; | |
466 } | |
467 | |
468 int | |
469 symlink (const std::string& old_name, const std::string& new_name) | |
470 { | |
471 std::string msg; | |
472 return symlink (old_name, new_name, msg); | |
473 } | |
474 | |
475 int | |
476 symlink (const std::string& old_name, | |
477 const std::string& new_name, std::string& msg) | |
478 { | |
479 msg = ""; | |
480 | |
481 int status = -1; | |
482 | |
483 status = gnulib::symlink (old_name.c_str (), new_name.c_str ()); | |
484 | |
485 if (status < 0) | |
486 msg = gnulib::strerror (errno); | |
487 | |
488 return status; | |
489 } | |
490 | |
491 int | |
492 readlink (const std::string& path, std::string& result) | |
493 { | |
494 std::string msg; | |
495 return readlink (path, result, msg); | |
496 } | |
497 | |
498 int | |
499 readlink (const std::string& path, std::string& result, std::string& msg) | |
500 { | |
501 int status = -1; | |
502 | |
503 msg = ""; | |
504 | |
505 char buf[MAXPATHLEN+1]; | |
506 | |
507 status = gnulib::readlink (path.c_str (), buf, MAXPATHLEN); | |
508 | |
509 if (status < 0) | |
510 msg = gnulib::strerror (errno); | |
511 else | |
512 { | |
513 buf[status] = '\0'; | |
514 result = std::string (buf); | |
515 status = 0; | |
516 } | |
517 | |
518 return status; | |
519 } | |
520 | |
521 int | |
522 rename (const std::string& from, const std::string& to) | |
523 { | |
524 std::string msg; | |
525 return rename (from, to, msg); | |
526 } | |
527 | |
528 int | |
529 rename (const std::string& from, const std::string& to, std::string& msg) | |
530 { | |
531 int status = -1; | |
532 | |
533 msg = ""; | |
534 | |
535 status = gnulib::rename (from.c_str (), to.c_str ()); | |
536 | |
537 if (status < 0) | |
538 msg = gnulib::strerror (errno); | |
539 | |
540 return status; | |
541 } | |
542 | |
543 int | |
544 rmdir (const std::string& name) | |
545 { | |
546 std::string msg; | |
547 return rmdir (name, msg); | |
548 } | |
549 | |
550 int | |
551 rmdir (const std::string& name, std::string& msg) | |
552 { | |
553 msg = ""; | |
554 | |
555 int status = -1; | |
556 | |
557 status = gnulib::rmdir (name.c_str ()); | |
558 | |
559 if (status < 0) | |
560 msg = gnulib::strerror (errno); | |
561 | |
562 return status; | |
563 } | |
564 | |
565 // And a version that works recursively. | |
566 | |
567 int | |
568 recursive_rmdir (const std::string& name) | |
569 { | |
570 std::string msg; | |
571 return recursive_rmdir (name, msg); | |
572 } | |
573 | |
574 int | |
575 recursive_rmdir (const std::string& name, std::string& msg) | |
576 { | |
577 msg = ""; | |
578 | |
579 int status = 0; | |
580 | |
581 dir_entry dir (name); | |
582 | |
583 if (dir) | |
584 { | |
585 string_vector dirlist = dir.read (); | |
586 | |
587 for (octave_idx_type i = 0; i < dirlist.numel (); i++) | |
588 { | |
589 octave_quit (); | |
590 | |
591 std::string nm = dirlist[i]; | |
592 | |
593 // Skip current directory and parent. | |
594 if (nm == "." || nm == "..") | |
595 continue; | |
596 | |
597 std::string fullnm = name + octave::sys::file_ops::dir_sep_str () + nm; | |
598 | |
599 // Get info about the file. Don't follow links. | |
600 file_stat fs (fullnm, false); | |
601 | |
602 if (fs) | |
601 { | 603 { |
602 status = octave_recursive_rmdir (fullnm, msg); | 604 if (fs.is_dir ()) |
603 | 605 { |
604 if (status < 0) | 606 status = recursive_rmdir (fullnm, msg); |
605 break; | 607 |
608 if (status < 0) | |
609 break; | |
610 } | |
611 else | |
612 { | |
613 status = unlink (fullnm, msg); | |
614 | |
615 if (status < 0) | |
616 break; | |
617 } | |
606 } | 618 } |
607 else | 619 else |
608 { | 620 { |
609 status = octave_unlink (fullnm, msg); | 621 msg = fs.error (); |
610 | 622 break; |
611 if (status < 0) | |
612 break; | |
613 } | 623 } |
614 } | 624 } |
615 else | 625 |
626 if (status >= 0) | |
616 { | 627 { |
617 msg = fs.error (); | 628 dir.close (); |
618 break; | 629 status = rmdir (name, msg); |
619 } | 630 } |
620 } | 631 } |
621 | 632 else |
622 if (status >= 0) | 633 { |
623 { | 634 status = -1; |
624 dir.close (); | 635 |
625 status = octave_rmdir (name, msg); | 636 msg = dir.error (); |
626 } | 637 } |
627 } | 638 |
628 else | 639 return status; |
629 { | 640 } |
630 status = -1; | 641 |
631 | 642 int |
632 msg = dir.error (); | 643 umask (mode_t mode) |
633 } | 644 { |
634 | 645 #if defined (HAVE_UMASK) |
635 return status; | 646 return umask (mode); |
647 #else | |
648 return 0; | |
649 #endif | |
650 } | |
651 | |
652 int | |
653 unlink (const std::string& name) | |
654 { | |
655 std::string msg; | |
656 return unlink (name, msg); | |
657 } | |
658 | |
659 int | |
660 unlink (const std::string& name, std::string& msg) | |
661 { | |
662 msg = ""; | |
663 | |
664 int status = -1; | |
665 | |
666 status = gnulib::unlink (name.c_str ()); | |
667 | |
668 if (status < 0) | |
669 msg = gnulib::strerror (errno); | |
670 | |
671 return status; | |
672 } | |
673 | |
674 std::string | |
675 tempnam (const std::string& dir, const std::string& pfx) | |
676 { | |
677 std::string msg; | |
678 return tempnam (dir, pfx, msg); | |
679 } | |
680 | |
681 std::string | |
682 tempnam (const std::string& dir, const std::string& pfx, | |
683 std::string& msg) | |
684 { | |
685 msg = ""; | |
686 | |
687 std::string retval; | |
688 | |
689 // get dir path to use for template | |
690 std::string templatename; | |
691 if (dir.empty ()) | |
692 templatename = octave::sys::env::get_temp_directory (); | |
693 else if (! file_stat (dir, false).is_dir ()) | |
694 templatename = octave::sys::env::get_temp_directory (); | |
695 else | |
696 templatename = dir; | |
697 | |
698 // add dir sep char if it is not there | |
699 if (*templatename.rbegin () != octave::sys::file_ops::dir_sep_char ()) | |
700 templatename += octave::sys::file_ops::dir_sep_char (); | |
701 | |
702 if (pfx.empty ()) | |
703 templatename += "file"; | |
704 else | |
705 templatename += pfx; | |
706 | |
707 // add the required XXXXXX for the template | |
708 templatename += "XXXXXX"; | |
709 | |
710 // create and copy template to char array for call to gen_tempname | |
711 char tname [templatename.length () + 1]; | |
712 | |
713 strcpy (tname, templatename.c_str ()); | |
714 | |
715 if (gen_tempname (tname, 0, 0, GT_NOCREATE) == -1) | |
716 msg = gnulib::strerror (errno); | |
717 else | |
718 retval = tname; | |
719 | |
720 return retval; | |
721 } | |
722 | |
723 std::string | |
724 canonicalize_file_name (const std::string& name) | |
725 { | |
726 std::string msg; | |
727 return canonicalize_file_name (name, msg); | |
728 } | |
729 | |
730 std::string | |
731 canonicalize_file_name (const std::string& name, std::string& msg) | |
732 { | |
733 msg = ""; | |
734 | |
735 std::string retval; | |
736 | |
737 char *tmp = gnulib::canonicalize_file_name (name.c_str ()); | |
738 | |
739 if (tmp) | |
740 { | |
741 retval = tmp; | |
742 free (tmp); | |
743 } | |
744 | |
745 #if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) | |
746 // Canonical Windows file separator is backslash. | |
747 std::replace (retval.begin (), retval.end (), '/', '\\'); | |
748 #endif | |
749 | |
750 if (retval.empty ()) | |
751 msg = gnulib::strerror (errno); | |
752 | |
753 return retval; | |
754 } | |
755 } | |
636 } | 756 } |
637 | |
638 int | |
639 octave_umask (mode_t mode) | |
640 { | |
641 #if defined (HAVE_UMASK) | |
642 return umask (mode); | |
643 #else | |
644 return 0; | |
645 #endif | |
646 } | |
647 | |
648 int | |
649 octave_unlink (const std::string& name) | |
650 { | |
651 std::string msg; | |
652 return octave_unlink (name, msg); | |
653 } | |
654 | |
655 int | |
656 octave_unlink (const std::string& name, std::string& msg) | |
657 { | |
658 msg = ""; | |
659 | |
660 int status = -1; | |
661 | |
662 status = gnulib::unlink (name.c_str ()); | |
663 | |
664 if (status < 0) | |
665 msg = gnulib::strerror (errno); | |
666 | |
667 return status; | |
668 } | |
669 | |
670 std::string | |
671 octave_tempnam (const std::string& dir, const std::string& pfx) | |
672 { | |
673 std::string msg; | |
674 return octave_tempnam (dir, pfx, msg); | |
675 } | |
676 | |
677 std::string | |
678 octave_tempnam (const std::string& dir, const std::string& pfx, | |
679 std::string& msg) | |
680 { | |
681 msg = ""; | |
682 | |
683 std::string retval; | |
684 | |
685 // get dir path to use for template | |
686 std::string templatename; | |
687 if (dir.empty ()) | |
688 templatename = octave::sys::env::get_temp_directory (); | |
689 else if (! file_stat (dir, false).is_dir ()) | |
690 templatename = octave::sys::env::get_temp_directory (); | |
691 else | |
692 templatename = dir; | |
693 | |
694 // add dir sep char if it is not there | |
695 if (*templatename.rbegin () != file_ops::dir_sep_char ()) | |
696 templatename += file_ops::dir_sep_char (); | |
697 | |
698 if (pfx.empty ()) | |
699 templatename += "file"; | |
700 else | |
701 templatename += pfx; | |
702 | |
703 // add the required XXXXXX for the template | |
704 templatename += "XXXXXX"; | |
705 | |
706 // create and copy template to char array for call to gen_tempname | |
707 char tname [templatename.length () + 1]; | |
708 | |
709 strcpy (tname, templatename.c_str ()); | |
710 | |
711 if (gen_tempname (tname, 0, 0, GT_NOCREATE) == -1) | |
712 msg = gnulib::strerror (errno); | |
713 else | |
714 retval = tname; | |
715 | |
716 return retval; | |
717 } | |
718 | |
719 std::string | |
720 octave_canonicalize_file_name (const std::string& name) | |
721 { | |
722 std::string msg; | |
723 return octave_canonicalize_file_name (name, msg); | |
724 } | |
725 | |
726 std::string | |
727 octave_canonicalize_file_name (const std::string& name, std::string& msg) | |
728 { | |
729 msg = ""; | |
730 | |
731 std::string retval; | |
732 | |
733 char *tmp = gnulib::canonicalize_file_name (name.c_str ()); | |
734 | |
735 if (tmp) | |
736 { | |
737 retval = tmp; | |
738 free (tmp); | |
739 } | |
740 | |
741 #if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) | |
742 // Canonical Windows file separator is backslash. | |
743 std::replace (retval.begin (), retval.end (), '/', '\\'); | |
744 #endif | |
745 | |
746 if (retval.empty ()) | |
747 msg = gnulib::strerror (errno); | |
748 | |
749 return retval; | |
750 } | |
751 |