GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
__ftp__.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2006-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <string>
31 #include <fstream>
32 #include <iomanip>
33 
34 #include "dir-ops.h"
35 #include "file-ops.h"
36 #include "file-stat.h"
37 #include "lo-sysdep.h"
38 #include "oct-env.h"
39 #include "oct-handle.h"
40 #include "glob-match.h"
41 #include "url-transfer.h"
42 
43 #include "defun.h"
44 #include "error.h"
45 #include "interpreter.h"
46 #include "oct-map.h"
47 #include "oct-refcount.h"
48 #include "ov-cell.h"
49 #include "ov-classdef.h"
50 #include "ovl.h"
51 #include "pager.h"
52 #include "unwind-prot.h"
53 #include "url-handle-manager.h"
54 
55 static void
56 delete_file (const std::string& file)
57 {
58  octave::sys::unlink (file);
59 }
60 
61 DEFMETHOD (__ftp__, interp, args, ,
62  doc: /* -*- texinfo -*-
63 @deftypefn {} {@var{handle} =} __ftp__ (@var{host})
64 @deftypefnx {} {@var{handle} =} __ftp__ (@var{host}, @var{username}, @var{password})
65 Undocumented internal function
66 @end deftypefn */)
67 {
68  int nargin = args.length ();
69 
70  if (nargin < 1 || nargin > 3)
71  print_usage ();
72 
73  std::string host = args(0).xstring_value ("__ftp__: HOST must be a string");
74 
75  std::string user = (nargin > 1)
76  ? args(1).xstring_value ("__ftp__: USER must be a string")
77  : "anonymous";
78 
79  std::string passwd = (nargin > 2)
80  ? args(2).xstring_value ("__ftp__: PASSWD must be a string")
81  : "";
82 
83  octave::url_handle_manager& uhm = interp.get_url_handle_manager ();
84 
85  octave::url_handle uh = uhm.make_url_handle (host, user, passwd,
87 
88  return ovl (uh.value ());
89 }
90 
91 DEFMETHOD (__ftp_pwd__, interp, args, ,
92  doc: /* -*- texinfo -*-
93 @deftypefn {} {} __ftp_pwd__ (@var{handle})
94 Undocumented internal function
95 @end deftypefn */)
96 {
97  if (args.length () != 1)
98  error ("__ftp_pwd__: incorrect number of arguments");
99 
100  octave::url_handle_manager& uhm = interp.get_url_handle_manager ();
101 
102  octave::url_transfer url_xfer = uhm.get_object (args(0));
103 
104  if (! url_xfer.is_valid ())
105  error ("__ftp_pwd__: invalid ftp handle");
106 
107  return ovl (url_xfer.pwd ());
108 }
109 
110 DEFMETHOD (__ftp_cwd__, interp, args, ,
111  doc: /* -*- texinfo -*-
112 @deftypefn {} {} __ftp_cwd__ (@var{handle}, @var{path})
113 Undocumented internal function
114 @end deftypefn */)
115 {
116  int nargin = args.length ();
117 
118  if (nargin != 1 && nargin != 2)
119  error ("__ftp_cwd__: incorrect number of arguments");
120 
121  std::string path = "";
122  if (nargin > 1)
123  path = args(1).xstring_value ("__ftp_cwd__: PATH must be a string");
124 
125  octave::url_handle_manager& uhm = interp.get_url_handle_manager ();
126 
127  octave::url_transfer url_xfer = uhm.get_object (args(0));
128 
129  if (! url_xfer.is_valid ())
130  error ("__ftp_cwd__: invalid ftp handle");
131 
132  url_xfer.cwd (path);
133 
134  return ovl ();
135 }
136 
137 DEFMETHOD (__ftp_dir__, interp, args, nargout,
138  doc: /* -*- texinfo -*-
139 @deftypefn {} {} __ftp_dir__ (@var{handle})
140 Undocumented internal function
141 @end deftypefn */)
142 {
143  if (args.length () != 1)
144  error ("__ftp_dir__: incorrect number of arguments");
145 
146  octave::url_handle_manager& uhm = interp.get_url_handle_manager ();
147 
148  octave::url_transfer url_xfer = uhm.get_object (args(0));
149 
150  if (! url_xfer.is_valid ())
151  error ("__ftp_dir__: invalid ftp handle");
152 
154 
155  if (nargout == 0)
156  url_xfer.dir ();
157  else
158  {
159  string_vector sv = url_xfer.list ();
160  octave_idx_type n = sv.numel ();
161 
162  if (n == 0)
163  {
164  string_vector flds (5);
165 
166  flds(0) = "name";
167  flds(1) = "date";
168  flds(2) = "bytes";
169  flds(3) = "isdir";
170  flds(4) = "datenum";
171 
172  retval = octave_map (flds);
173  }
174  else
175  {
176  octave_map st;
177 
178  Cell filectime (dim_vector (n, 1));
179  Cell filesize (dim_vector (n, 1));
180  Cell fileisdir (dim_vector (n, 1));
181  Cell filedatenum (dim_vector (n, 1));
182 
183  st.assign ("name", Cell (sv));
184 
185  for (octave_idx_type i = 0; i < n; i++)
186  {
187  time_t ftime;
188  bool fisdir;
189  double fsize;
190 
191  url_xfer.get_fileinfo (sv(i), fsize, ftime, fisdir);
192 
193  fileisdir (i) = fisdir;
194  filectime (i) = ctime (&ftime);
195  filesize (i) = fsize;
196  filedatenum (i) = double (ftime);
197  }
198 
199  st.assign ("date", filectime);
200  st.assign ("bytes", filesize);
201  st.assign ("isdir", fileisdir);
202  st.assign ("datenum", filedatenum);
203 
204  retval = st;
205  }
206  }
207 
208  return retval;
209 }
210 
211 DEFMETHOD (__ftp_ascii__, interp, args, ,
212  doc: /* -*- texinfo -*-
213 @deftypefn {} {} __ftp_ascii__ (@var{handle})
214 Undocumented internal function
215 @end deftypefn */)
216 {
217  if (args.length () != 1)
218  error ("__ftp_ascii__: incorrect number of arguments");
219 
220  octave::url_handle_manager& uhm = interp.get_url_handle_manager ();
221 
222  octave::url_transfer url_xfer = uhm.get_object (args(0));
223 
224  if (! url_xfer.is_valid ())
225  error ("__ftp_ascii__: invalid ftp handle");
226 
227  url_xfer.ascii ();
228 
229  return ovl ();
230 }
231 
232 DEFMETHOD (__ftp_binary__, interp, args, ,
233  doc: /* -*- texinfo -*-
234 @deftypefn {} {} __ftp_binary__ (@var{handle})
235 Undocumented internal function
236 @end deftypefn */)
237 {
238  if (args.length () != 1)
239  error ("__ftp_binary__: incorrect number of arguments");
240 
241  octave::url_handle_manager& uhm = interp.get_url_handle_manager ();
242 
243  octave::url_transfer url_xfer = uhm.get_object (args(0));
244 
245  if (! url_xfer.is_valid ())
246  error ("__ftp_binary__: invalid ftp handle");
247 
248  url_xfer.binary ();
249 
250  return ovl ();
251 }
252 
253 DEFMETHOD (__ftp_close__, interp, args, ,
254  doc: /* -*- texinfo -*-
255 @deftypefn {} {} __ftp_close__ (@var{handle})
256 Undocumented internal function
257 @end deftypefn */)
258 {
259  if (args.length () != 1)
260  error ("__ftp_close__: incorrect number of arguments");
261 
262  octave::url_handle_manager& uhm = interp.get_url_handle_manager ();
263 
264  octave::url_handle h = uhm.lookup (args(0));
265 
266  if (! h.ok ())
267  error ("__ftp_close__: invalid ftp handle");
268 
269  uhm.free (h);
270 
271  return ovl ();
272 }
273 
274 DEFMETHOD (__ftp_mode__, interp, args, ,
275  doc: /* -*- texinfo -*-
276 @deftypefn {} {} __ftp_mode__ (@var{handle})
277 Undocumented internal function
278 @end deftypefn */)
279 {
280  if (args.length () != 1)
281  error ("__ftp_mode__: incorrect number of arguments");
282 
283  octave::url_handle_manager& uhm = interp.get_url_handle_manager ();
284 
285  octave::url_transfer url_xfer = uhm.get_object (args(0));
286 
287  if (! url_xfer.is_valid ())
288  error ("__ftp_binary__: invalid ftp handle");
289 
290  return ovl (url_xfer.is_ascii () ? "ascii" : "binary");
291 }
292 
293 DEFMETHOD (__ftp_delete__, interp, args, ,
294  doc: /* -*- texinfo -*-
295 @deftypefn {} {} __ftp_delete__ (@var{handle}, @var{path})
296 Undocumented internal function
297 @end deftypefn */)
298 {
299  if (args.length () != 2)
300  error ("__ftp_delete__: incorrect number of arguments");
301 
302  std::string file = args(1).xstring_value ("__ftp_delete__: FILE must be a string");
303 
304  octave::url_handle_manager& uhm = interp.get_url_handle_manager ();
305 
306  octave::url_transfer url_xfer = uhm.get_object (args(0));
307 
308  if (! url_xfer.is_valid ())
309  error ("__ftp_delete__: invalid ftp handle");
310 
311  url_xfer.del (file);
312 
313  return ovl ();
314 }
315 
316 DEFMETHOD (__ftp_rmdir__, interp, args, ,
317  doc: /* -*- texinfo -*-
318 @deftypefn {} {} __ftp_rmdir__ (@var{handle}, @var{path})
319 Undocumented internal function
320 @end deftypefn */)
321 {
322  if (args.length () != 2)
323  error ("__ftp_rmdir__: incorrect number of arguments");
324 
325  std::string dir = args(1).xstring_value ("__ftp_rmdir__: DIR must be a string");
326 
327  octave::url_handle_manager& uhm = interp.get_url_handle_manager ();
328 
329  octave::url_transfer url_xfer = uhm.get_object (args(0));
330 
331  if (! url_xfer.is_valid ())
332  error ("__ftp_rmdir__: invalid ftp handle");
333 
334  url_xfer.rmdir (dir);
335 
336  return ovl ();
337 }
338 
339 DEFMETHOD (__ftp_mkdir__, interp, args, ,
340  doc: /* -*- texinfo -*-
341 @deftypefn {} {} __ftp_mkdir__ (@var{handle}, @var{path})
342 Undocumented internal function
343 @end deftypefn */)
344 {
345  if (args.length () != 2)
346  error ("__ftp_mkdir__: incorrect number of arguments");
347 
348  std::string dir = args(1).xstring_value ("__ftp_mkdir__: DIR must be a string");
349 
350  octave::url_handle_manager& uhm = interp.get_url_handle_manager ();
351 
352  octave::url_transfer url_xfer = uhm.get_object (args(0));
353 
354  if (! url_xfer.is_valid ())
355  error ("__ftp_mkdir__: invalid ftp handle");
356 
357  url_xfer.mkdir (dir);
358 
359  return ovl ();
360 }
361 
362 DEFMETHOD (__ftp_rename__, interp, args, ,
363  doc: /* -*- texinfo -*-
364 @deftypefn {} {} __ftp_rename__ (@var{handle}, @var{path})
365 Undocumented internal function
366 @end deftypefn */)
367 {
368  if (args.length () != 3)
369  error ("__ftp_rename__: incorrect number of arguments");
370 
371  std::string oldname = args(1).xstring_value ("__ftp_rename__: OLDNAME must be a string");
372  std::string newname = args(2).xstring_value ("__ftp_rename__: NEWNAME must be a string");
373 
374  octave::url_handle_manager& uhm = interp.get_url_handle_manager ();
375 
376  octave::url_transfer url_xfer = uhm.get_object (args(0));
377 
378  if (url_xfer.is_valid ())
379  error ("__ftp_rename__: invalid ftp handle");
380 
381  url_xfer.rename (oldname, newname);
382 
383  return ovl ();
384 }
385 
386 DEFMETHOD (__ftp_mput__, interp, args, nargout,
387  doc: /* -*- texinfo -*-
388 @deftypefn {} {} __ftp_mput__ (@var{handle}, @var{files})
389 Undocumented internal function
390 @end deftypefn */)
391 {
392  if (args.length () != 2)
393  error ("__ftp_mput__: incorrect number of arguments");
394 
395  std::string pat = args(1).xstring_value ("__ftp_mput__: PATTERN must be a string");
396 
397  octave::url_handle_manager& uhm = interp.get_url_handle_manager ();
398 
399  octave::url_transfer url_xfer = uhm.get_object (args(0));
400 
401  if (! url_xfer.is_valid ())
402  error ("__ftp_mput__: invalid ftp handle");
403 
404  string_vector file_list;
405 
407  string_vector files = pattern.glob ();
408 
409  for (octave_idx_type i = 0; i < files.numel (); i++)
410  {
411  std::string file = files(i);
412 
413  octave::sys::file_stat fs (file);
414 
415  if (! fs.exists ())
416  error ("__ftp__mput: file does not exist");
417 
418  if (fs.is_dir ())
419  {
420  file_list.append (url_xfer.mput_directory ("", file));
421 
422  if (! url_xfer.good ())
423  error ("__ftp_mput__: %s", url_xfer.lasterror ().c_str ());
424  }
425  else
426  {
427  // FIXME: Does ascii mode need to be flagged here?
428  std::ifstream ifile =
429  octave::sys::ifstream (file.c_str (),
430  std::ios::in | std::ios::binary);
431 
432  if (! ifile.is_open ())
433  error ("__ftp_mput__: unable to open file");
434 
435  url_xfer.put (file, ifile);
436 
437  ifile.close ();
438 
439  if (! url_xfer.good ())
440  error ("__ftp_mput__: %s", url_xfer.lasterror ().c_str ());
441 
442  file_list.append (file);
443  }
444  }
445 
446  if (nargout > 0)
447  return ovl (file_list);
448  else
449  return ovl ();
450 }
451 
452 DEFMETHOD (__ftp_mget__, interp, args, ,
453  doc: /* -*- texinfo -*-
454 @deftypefn {} {} __ftp_mget__ (@var{handle}, @var{pattern})
455 @deftypefnx {} {} __ftp_mget__ (@var{handle}, @var{pattern}, @var{target})
456 Undocumented internal function
457 @end deftypefn */)
458 {
459  int nargin = args.length ();
460 
461  if (nargin != 2 && nargin != 3)
462  error ("__ftp_mget__: incorrect number of arguments");
463 
464  std::string file = args(1).xstring_value ("__ftp_mget__: PATTERN must be a string");
465 
466  std::string target;
467 
468  if (nargin == 3 && ! args(2).isempty ())
469  target = args(2).xstring_value ("__ftp_mget__: TARGET must be a string")
471 
472  octave::url_handle_manager& uhm = interp.get_url_handle_manager ();
473 
474  octave::url_transfer url_xfer = uhm.get_object (args(0));
475 
476  if (! url_xfer.is_valid ())
477  error ("__ftp_mget__: invalid ftp handle");
478 
479  string_vector sv = url_xfer.list ();
480  octave_idx_type n = 0;
481  glob_match pattern (file);
482 
483  for (octave_idx_type i = 0; i < sv.numel (); i++)
484  {
485  if (pattern.match (sv(i)))
486  {
487  n++;
488 
489  time_t ftime;
490  bool fisdir;
491  double fsize;
492 
493  url_xfer.get_fileinfo (sv(i), fsize, ftime, fisdir);
494 
495  if (fisdir)
496  url_xfer.mget_directory (sv(i), target);
497  else
498  {
499  std::ofstream ofile =
500  octave::sys::ofstream ((target + sv(i)).c_str (),
501  std::ios::out | std::ios::binary);
502 
503  if (! ofile.is_open ())
504  error ("__ftp_mget__: unable to open file");
505 
507 
508  frame.add_fcn (delete_file, target + sv(i));
509 
510  url_xfer.get (sv(i), ofile);
511 
512  ofile.close ();
513 
514  if (url_xfer.good ())
515  frame.discard ();
516  }
517 
518  if (! url_xfer.good ())
519  error ("__ftp_mget__: %s", url_xfer.lasterror().c_str());
520  }
521  }
522 
523  if (n == 0)
524  error ("__ftp_mget__: file not found");
525 
526  return ovl ();
527 }
static void delete_file(const std::string &file)
Definition: __ftp__.cc:56
Definition: Cell.h:43
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:95
string_vector glob(void) const
Definition: glob-match.cc:41
bool match(const std::string &str) const
Definition: glob-match.cc:35
void add_fcn(void(*fcn)(Params...), Args &&... args)
bool is_dir(void) const
Definition: file-stat.cc:65
bool exists(void) const
Definition: file-stat.h:147
url_handle lookup(double val)
url_transfer get_object(double val)
void free(const url_handle &h)
url_handle make_url_handle(const std::string &host, const std::string &user, const std::string &passwd, std::ostream &os)
void mget_directory(const std::string &directory, const std::string &target)
Definition: url-transfer.h:243
std::string lasterror(void) const
Definition: url-transfer.h:200
bool good(void) const
Definition: url-transfer.h:198
void cwd(const std::string &path)
Definition: url-transfer.h:220
string_vector mput_directory(const std::string &base, const std::string &directory)
Definition: url-transfer.h:249
string_vector list(void)
Definition: url-transfer.h:257
void rename(const std::string &oldname, const std::string &newname)
Definition: url-transfer.h:228
bool is_valid(void) const
Definition: url-transfer.h:196
void mkdir(const std::string &path)
Definition: url-transfer.h:226
bool is_ascii(void) const
Definition: url-transfer.h:216
void rmdir(const std::string &path)
Definition: url-transfer.h:224
void put(const std::string &file, std::istream &is)
Definition: url-transfer.h:233
std::string pwd(void)
Definition: url-transfer.h:265
void del(const std::string &file)
Definition: url-transfer.h:222
void get(const std::string &file, std::ostream &os)
Definition: url-transfer.h:238
void get_fileinfo(const std::string &filename, double &filesize, time_t &filetime, bool &fileisdir)
Definition: url-transfer.h:259
double value(void) const
Definition: oct-handle.h:78
bool ok(void) const
Definition: oct-handle.h:113
void assign(const std::string &k, const Cell &val)
Definition: oct-map.h:365
string_vector & append(const std::string &s)
Definition: str-vec.cc:110
octave_idx_type numel(void) const
Definition: str-vec.h:100
OCTINTERP_API void print_usage(void)
Definition: defun.cc:53
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
Definition: defun.h:138
void error(const char *fmt,...)
Definition: error.cc:968
QString path
octave_idx_type n
Definition: mx-inlines.cc:753
std::string dir_sep_str(void)
Definition: file-ops.cc:243
std::string tilde_expand(const std::string &name)
Definition: file-ops.cc:286
std::ifstream ifstream(const std::string &filename, const std::ios::openmode mode)
Definition: lo-sysdep.cc:381
int unlink(const std::string &name)
Definition: file-ops.cc:626
std::ofstream ofstream(const std::string &filename, const std::ios::openmode mode)
Definition: lo-sysdep.cc:395
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:211
#define octave_stdout
Definition: pager.h:313