changelog shortlog tags changeset files revisions annotate raw

src/dirfns.cc

changeset 9846: 1d90fc211872
parent:1d3b91166b9c
author: John W. Eaton <jwe@octave.org>
date: Sat Nov 21 21:44:51 2009 -0500 (21 hours ago)
permissions: -rw-r--r--
description: configure.ac: report freetype, fontconfig, and fltk cflags and libs info
1/*
2
3Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003,
4 2004, 2005, 2006, 2007, 2008, 2009 John W. Eaton
5
6This file is part of Octave.
7
8Octave is free software; you can redistribute it and/or modify it
9under the terms of the GNU General Public License as published by the
10Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
12
13Octave is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with Octave; see the file COPYING. If not, see
20<http://www.gnu.org/licenses/>.
21
22*/
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include <cerrno>
29#include <cstdio>
30#include <cstddef>
31#include <cstdlib>
32#include <cstring>
33
34#include <sstream>
35#include <string>
36
37#ifdef HAVE_UNISTD_H
38#ifdef HAVE_SYS_TYPES_H
39#include <sys/types.h>
40#endif
41#include <unistd.h>
42#endif
43
44#include "file-ops.h"
45#include "file-stat.h"
46#include "glob-match.h"
47#include "oct-env.h"
48#include "pathsearch.h"
49#include "str-vec.h"
50
51#include "Cell.h"
52#include "defun.h"
53#include "dir-ops.h"
54#include "dirfns.h"
55#include "error.h"
56#include "gripes.h"
57#include "input.h"
58#include "load-path.h"
59#include "oct-obj.h"
60#include "pager.h"
61#include "procstream.h"
62#include "sysdep.h"
63#include "toplev.h"
64#include "unwind-prot.h"
65#include "utils.h"
66#include "variables.h"
67
68// TRUE means we ask for confirmation before recursively removing a
69// directory tree.
70static bool Vconfirm_recursive_rmdir = true;
71
72// The time we last time we changed directories.
73octave_time Vlast_chdir_time = 0.0;
74
75static int
76octave_change_to_directory (const std::string& newdir)
77{
78 int cd_ok = octave_env::chdir (file_ops::tilde_expand (newdir));
79
80 if (cd_ok)
81 {
82 Vlast_chdir_time.stamp ();
83
84 // FIXME -- should this be handled as a list of functions
85 // to call so users can add their own chdir handlers?
86
87 load_path::update ();
88 }
89 else
90 {
91 using namespace std;
92
93 error ("%s: %s", newdir.c_str (), strerror (errno));
94 }
95
96 return cd_ok;
97}
98
99DEFUN (cd, args, ,
100 "-*- texinfo -*-\n\
101@deffn {Command} cd dir\n\
102@deffnx {Command} chdir dir\n\
103Change the current working directory to @var{dir}. If @var{dir} is\n\
104omitted, the current directory is changed to the user's home\n\
105directory. For example,\n\
106\n\
107@example\n\
108cd ~/octave\n\
109@end example\n\
110\n\
111@noindent\n\
112Changes the current working directory to @file{~/octave}. If the\n\
113directory does not exist, an error message is printed and the working\n\
114directory is not changed.\n\
115@seealso{mkdir, rmdir, dir}\n\
116@end deffn")
117{
118 octave_value_list retval;
119
120 int argc = args.length () + 1;
121
122 string_vector argv = args.make_argv ("cd");
123
124 if (error_state)
125 return retval;
126
127 if (argc > 1)
128 {
129 std::string dirname = argv[1];
130
131 if (dirname.length () > 0
132 && ! octave_change_to_directory (dirname))
133 {
134 return retval;
135 }
136 }
137 else
138 {
139 std::string home_dir = octave_env::get_home_directory ();
140
141 if (home_dir.empty () || ! octave_change_to_directory (home_dir))
142 return retval;
143 }
144
145 return retval;
146}
147
148DEFALIAS (chdir, cd);
149
150DEFUN (pwd, , ,
151 "-*- texinfo -*-\n\
152@deftypefn {Built-in Function} {} pwd ()\n\
153Return the current working directory.\n\
154@seealso{dir, ls}\n\
155@end deftypefn")
156{
157 return octave_value (octave_env::getcwd ());
158}
159
160DEFUN (readdir, args, ,
161 "-*- texinfo -*-\n\
162@deftypefn {Built-in Function} {[@var{files}, @var{err}, @var{msg}] =} readdir (@var{dir})\n\
163Return names of the files in the directory @var{dir} as a cell array of\n\
164strings. If an error occurs, return an empty cell array in @var{files}.\n\
165\n\
166If successful, @var{err} is 0 and @var{msg} is an empty string.\n\
167Otherwise, @var{err} is nonzero and @var{msg} contains a\n\
168system-dependent error message.\n\
169@seealso{dir, glob}\n\
170@end deftypefn")
171{
172 octave_value_list retval;
173
174 retval(2) = std::string ();
175 retval(1) = -1.0;
176 retval(0) = Cell ();
177
178 if (args.length () == 1)
179 {
180 std::string dirname = args(0).string_value ();
181
182 if (error_state)
183 gripe_wrong_type_arg ("readdir", args(0));
184 else
185 {
186 dir_entry dir (dirname);
187
188 if (dir)
189 {
190 string_vector dirlist = dir.read ();
191 retval(0) = Cell (dirlist.sort ());
192 retval(1) = 0.0;
193 }
194 else
195 {
196 retval(2) = dir.error ();
197 }
198 }
199 }
200 else
201 print_usage ();
202
203 return retval;
204}
205
206// FIXME -- should maybe also allow second arg to specify
207// mode? OTOH, that might cause trouble with compatibility later...
208
209DEFUN (mkdir, args, ,
210 "-*- texinfo -*-\n\
211@deftypefn {Built-in Function} {[@var{status}, @var{msg}, @var{msgid}] =} mkdir (@var{dir})\n\
212@deftypefnx {Built-in Function} {[@var{status}, @var{msg}, @var{msgid}] =} mkdir (@var{parent}, @var{dir})\n\
213Create a directory named @var{dir} in the directory @var{parent}.\n\
214\n\
215If successful, @var{status} is 1, with @var{msg} and @var{msgid} empty\n\
216character strings. Otherwise, @var{status} is 0, @var{msg} contains a\n\
217system-dependent error message, and @var{msgid} contains a unique\n\
218message identifier.\n\
219@seealso{rmdir}\n\
220@end deftypefn")
221{
222 octave_value_list retval;
223
224 retval(2) = std::string ();
225 retval(1) = std::string ();
226 retval(0) = false;
227
228 int nargin = args.length ();
229
230 std::string dirname;
231
232 if (nargin == 2)
233 {
234 std::string parent = args(0).string_value ();
235 std::string dir = args(1).string_value ();
236
237 if (error_state)
238 {
239 gripe_wrong_type_arg ("mkdir", args(0));
240 return retval;
241 }
242 else
243 dirname = file_ops::concat (parent, dir);
244 }
245 else if (nargin == 1)
246 {
247 dirname = args(0).string_value ();
248
249 if (error_state)
250 {
251 gripe_wrong_type_arg ("mkdir", args(0));
252 return retval;
253 }
254 }
255
256 if (nargin == 1 || nargin == 2)
257 {
258 std::string msg;
259
260 dirname = file_ops::tilde_expand (dirname);
261
262 file_stat fs (dirname);
263
264 if (fs && fs.is_dir ())
265 {
266 // For compatibility with Matlab, we return true when the
267 // directory already exists.
268
269 retval(2) = "mkdir";
270 retval(1) = "directory exists";
271 retval(0) = true;
272 }
273 else
274 {
275 int status = file_ops::mkdir (dirname, 0777, msg);
276
277 if (status < 0)
278 {
279 retval(2) = "mkdir";
280 retval(1) = msg;
281 }
282 else
283 retval(0) = true;
284 }
285 }
286 else
287 print_usage ();
288
289 return retval;
290}
291
292DEFUN (rmdir, args, ,
293 "-*- texinfo -*-\n\
294@deftypefn {Built-in Function} {[@var{status}, @var{msg}, @var{msgid}] =} rmdir (@var{dir})\n\
295@deftypefnx {Built-in Function} {[@var{status}, @var{msg}, @var{msgid}] =} rmdir (@var{dir}, @code{\"s\"})\n\
296Remove the directory named @var{dir}.\n\
297\n\
298If successful, @var{status} is 1, with @var{msg} and @var{msgid} empty\n\
299character strings. Otherwise, @var{status} is 0, @var{msg} contains a\n\
300system-dependent error message, and @var{msgid} contains a unique\n\
301message identifier.\n\
302\n\
303If the optional second parameter is supplied with value @code{\"s\"},\n\
304recursively remove all subdirectories as well.\n\
305@seealso{mkdir, confirm_recursive_rmdir}\n\
306@end deftypefn")
307{
308 octave_value_list retval;
309
310 retval(2) = std::string ();
311 retval(1) = std::string ();
312 retval(0) = false;
313
314 int nargin = args.length ();
315
316 if (nargin == 1 || nargin == 2)
317 {
318 std::string dirname = args(0).string_value ();
319
320 if (error_state)
321 gripe_wrong_type_arg ("rmdir", args(0));
322 else
323 {
324 std::string fulldir = file_ops::tilde_expand (dirname);
325 int status = -1;
326 std::string msg;
327
328 if (nargin == 2)
329 {
330 if (args(1).string_value () == "s")
331 {
332 bool doit = true;
333
334 if (interactive && Vconfirm_recursive_rmdir)
335 {
336 std::string prompt
337 = "remove entire contents of " + fulldir + "? ";
338
339 doit = octave_yes_or_no (prompt);
340 }
341
342 if (doit)
343 status = file_ops::recursive_rmdir (fulldir, msg);
344 }
345 else
346 error ("rmdir: expecting second argument to be \"s\"");
347 }
348 else
349 status = file_ops::rmdir (fulldir, msg);
350
351 if (status < 0)
352 {
353 retval(2) = "rmdir";
354 retval(1) = msg;
355 }
356 else
357 retval(0) = true;
358 }
359 }
360 else
361 print_usage ();
362
363 return retval;
364}
365
366DEFUN (link, args, ,
367 "-*- texinfo -*-\n\
368@deftypefn {Built-in Function} {[@var{err}, @var{msg}] =} link (@var{old}, @var{new})\n\
369Create a new link (also known as a hard link) to an existing file.\n\
370\n\
371If successful, @var{err} is 0 and @var{msg} is an empty string.\n\
372Otherwise, @var{err} is nonzero and @var{msg} contains a\n\
373system-dependent error message.\n\
374@seealso{symlink}\n\
375@end deftypefn")
376{
377 octave_value_list retval;
378
379 retval(1) = std::string ();
380 retval(0) = -1.0;
381
382 if (args.length () == 2)
383 {
384 std::string from = args(0).string_value ();
385
386 if (error_state)
387 gripe_wrong_type_arg ("link", args(0));
388 else
389 {
390 std::string to = args(1).string_value ();
391
392 if (error_state)
393 gripe_wrong_type_arg ("link", args(1));
394 else
395 {
396 std::string msg;
397
398 int status = file_ops::link (from, to, msg);
399
400 retval(0) = status;
401
402 if (status < 0)
403 retval(1) = msg;
404 }
405 }
406 }
407 else
408 print_usage ();
409
410 return retval;
411}
412
413DEFUN (symlink, args, ,
414 "-*- texinfo -*-\n\
415@deftypefn {Built-in Function} {[@var{err}, @var{msg}] =} symlink (@var{old}, @var{new})\n\
416Create a symbolic link @var{new} which contains the string @var{old}.\n\
417\n\
418If successful, @var{err} is 0 and @var{msg} is an empty string.\n\
419Otherwise, @var{err} is nonzero and @var{msg} contains a\n\
420system-dependent error message.\n\
421@seealso{link, readlink}\n\
422@end deftypefn")
423{
424 octave_value_list retval;
425
426 retval(1) = std::string ();
427 retval(0) = -1.0;
428
429 if (args.length () == 2)
430 {
431 std::string from = args(0).string_value ();
432
433 if (error_state)
434 gripe_wrong_type_arg ("symlink", args(0));
435 else
436 {
437 std::string to = args(1).string_value ();
438
439 if (error_state)
440 gripe_wrong_type_arg ("symlink", args(1));
441 else
442 {
443 std::string msg;
444
445 int status = file_ops::symlink (from, to, msg);
446
447 retval(0) = status;
448
449 if (status < 0)
450 retval(1) = msg;
451 }
452 }
453 }
454 else
455 print_usage ();
456
457 return retval;
458}
459
460DEFUN (readlink, args, ,
461 "-*- texinfo -*-\n\
462@deftypefn {Built-in Function} {[@var{result}, @var{err}, @var{msg}] =} readlink (@var{symlink})\n\
463Read the value of the symbolic link @var{symlink}.\n\
464\n\
465If successful, @var{result} contains the contents of the symbolic link\n\
466@var{symlink}, @var{err} is 0 and @var{msg} is an empty string.\n\
467Otherwise, @var{err} is nonzero and @var{msg} contains a\n\
468system-dependent error message.\n\
469@seealso{link, symlink}\n\
470@end deftypefn")
471{
472 octave_value_list retval;
473
474 retval(2) = std::string ();
475 retval(1) = -1.0;
476 retval(0) = std::string ();
477
478 if (args.length () == 1)
479 {
480 std::string symlink = args(0).string_value ();
481
482 if (error_state)
483 gripe_wrong_type_arg ("readlink", args(0));
484 else
485 {
486 std::string result;
487 std::string msg;
488
489 int status = file_ops::readlink (symlink, result, msg);
490
491 retval(0) = result;
492
493 retval(1) = status;
494
495 if (status < 0)
496 retval(2) = msg;
497 }
498 }
499 else
500 print_usage ();
501
502 return retval;
503}
504
505DEFUN (rename, args, ,
506 "-*- texinfo -*-\n\
507@deftypefn {Built-in Function} {[@var{err}, @var{msg}] =} rename (@var{old}, @var{new})\n\
508Change the name of file @var{old} to @var{new}.\n\
509\n\
510If successful, @var{err} is 0 and @var{msg} is an empty string.\n\
511Otherwise, @var{err} is nonzero and @var{msg} contains a\n\
512system-dependent error message.\n\
513@seealso{ls, dir}\n\
514@end deftypefn")
515{
516 octave_value_list retval;
517
518 retval(1) = std::string ();
519 retval(0) = -1.0;
520
521 if (args.length () == 2)
522 {
523 std::string from = args(0).string_value ();
524
525 if (error_state)
526 gripe_wrong_type_arg ("rename", args(0));
527 else
528 {
529 std::string to = args(1).string_value ();
530
531 if (error_state)
532 gripe_wrong_type_arg ("rename", args(1));
533 else
534 {
535 std::string msg;
536
537 int status = file_ops::rename (from, to, msg);
538
539 retval(0) = status;
540
541 if (status < 0)
542 retval(1) = msg;
543 }
544 }
545 }
546 else
547 print_usage ();
548
549 return retval;
550}
551
552DEFUN (glob, args, ,
553 "-*- texinfo -*-\n\
554@deftypefn {Built-in Function} {} glob (@var{pattern})\n\
555Given an array of strings (as a char array or a cell array) in\n\
556@var{pattern}, return a cell array of file names that match any of\n\
557them, or an empty cell array if no patterns match. Tilde expansion\n\
558is performed on each of the patterns before looking for matching file\n\
559names. For example,\n\
560\n\
561@example\n\
562@group\n\
563glob (\"/vm*\")\n\
564 @result{} \"/vmlinuz\"\n\
565@end group\n\
566@end example\n\
567@seealso{dir, ls, stat, readdir}\n\
568@end deftypefn")
569{
570 octave_value retval;
571
572 if (args.length () == 1)
573 {
574 string_vector pat = args(0).all_strings ();
575
576 if (error_state)
577 gripe_wrong_type_arg ("glob", args(0));
578 else
579 {
580 glob_match pattern (file_ops::tilde_expand (pat));
581
582 retval = Cell (pattern.glob ());
583 }
584 }
585 else
586 print_usage ();
587
588 return retval;
589}
590
591DEFUN (fnmatch, args, ,
592 "-*- texinfo -*-\n\
593@deftypefn {Built-in Function} {} fnmatch (@var{pattern}, @var{string})\n\
594Return 1 or zero for each element of @var{string} that matches any of\n\
595the elements of the string array @var{pattern}, using the rules of\n\
596filename pattern matching. For example,\n\
597\n\
598@example\n\
599@group\n\
600fnmatch (\"a*b\", @{\"ab\"; \"axyzb\"; \"xyzab\"@})\n\
601 @result{} [ 1; 1; 0 ]\n\
602@end group\n\
603@end example\n\
604@end deftypefn")
605{
606 octave_value retval;
607
608 if (args.length () == 2)
609 {
610 string_vector pat = args(0).all_strings ();
611 string_vector str = args(1).all_strings ();
612
613 if (error_state)
614 gripe_wrong_type_arg ("fnmatch", args(0));
615 else
616 {
617 glob_match pattern (file_ops::tilde_expand (pat));
618
619 Array<bool> tmp = pattern.match (str);
620
621 octave_idx_type n = tmp.length ();
622
623 ColumnVector result (n);
624
625 for (octave_idx_type i = 0; i < n; i++)
626 result(i) = tmp(i);
627
628 retval = result;
629 }
630 }
631 else
632 print_usage ();
633
634 return retval;
635}
636
637DEFUN (filesep, args, ,
638 "-*- texinfo -*-\n\
639@deftypefn {Built-in Function} {} filesep ()\n\
640@deftypefnx {Built-in Function} {} filesep ('all')\n\
641Return the system-dependent character used to separate directory names.\n\
642\n\
643If 'all' is given, the function return all valid file separators in\n\
644the form of a string. The list of file separators is system-dependent.\n\
645It is / (forward slash) under UNIX or Mac OS X, / and \\ (forward and\n\
646backward slashes) under Windows.\n\
647@seealso{pathsep, dir, ls}\n\
648@end deftypefn")
649{
650 octave_value retval;
651
652 if (args.length () == 0)
653 retval = file_ops::dir_sep_str ();
654 else if (args.length () == 1)
655 {
656 std::string s = args(0).string_value ();
657
658 if (! error_state)
659 {
660 if (s == "all")
661 retval = file_ops::dir_sep_chars ();
662 else
663 gripe_wrong_type_arg ("filesep", args(0));
664 }
665 else
666 gripe_wrong_type_arg ("filesep", args(0));
667 }
668 else
669 print_usage ();
670
671 return retval;
672}
673
674DEFUN (pathsep, args, nargout,
675 "-*- texinfo -*-\n\
676@deftypefn {Built-in Function} {@var{val} =} pathsep ()\n\
677@deftypefnx {Built-in Function} {@var{old_val} =} pathsep (@var{new_val})\n\
678Query or set the character used to separate directories in\n\
679a path.\n\
680@seealso{filesep, dir, ls}\n\
681@end deftypefn")
682{
683 octave_value retval;
684
685 int nargin = args.length ();
686
687 if (nargout > 0 || nargin == 0)
688 retval = dir_path::path_sep_str ();
689
690 if (nargin == 1)
691 {
692 std::string sval = args(0).string_value ();
693
694 if (! error_state)
695 {
696 switch (sval.length ())
697 {
698 case 1:
699 dir_path::path_sep_char (sval[0]);
700 break;
701
702 case 0:
703 dir_path::path_sep_char ('\0');
704 break;
705
706 default:
707 error ("pathsep: argument must be a single character");
708 break;
709 }
710 }
711 else
712 error ("pathsep: argument must be a single character");
713 }
714 else if (nargin > 1)
715 print_usage ();
716
717 return retval;
718}
719
720DEFUN (confirm_recursive_rmdir, args, nargout,
721 "-*- texinfo -*-\n\
722@deftypefn {Built-in Function} {@var{val} =} confirm_recursive_rmdir ()\n\
723@deftypefnx {Built-in Function} {@var{old_val} =} confirm_recursive_rmdir (@var{new_val})\n\
724Query or set the internal variable that controls whether Octave\n\
725will ask for confirmation before recursively removing a directory tree.\n\
726@end deftypefn")
727{
728 return SET_INTERNAL_VARIABLE (confirm_recursive_rmdir);
729}
730
731/*
732;;; Local Variables: ***
733;;; mode: C++ ***
734;;; End: ***
735*/