GNU Octave  9.1.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-2024 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 
56 
57 DEFMETHOD (__ftp__, interp, args, ,
58  doc: /* -*- texinfo -*-
59 @deftypefn {} {@var{handle} =} __ftp__ (@var{host})
60 @deftypefnx {} {@var{handle} =} __ftp__ (@var{host}, @var{username}, @var{password})
61 Undocumented internal function
62 @end deftypefn */)
63 {
64  int nargin = args.length ();
65 
66  std::string host = args(0).xstring_value ("__ftp__: HOST must be a string");
67 
68  std::string user = (nargin > 1)
69  ? args(1).xstring_value ("__ftp__: USER must be a string")
70  : "anonymous";
71 
72  std::string passwd = (nargin > 2)
73  ? args(2).xstring_value ("__ftp__: PASSWD must be a string")
74  : "";
75 
76  url_handle_manager& uhm = interp.get_url_handle_manager ();
77 
78  url_handle uh = uhm.make_url_handle (host, user, passwd, octave_stdout);
79 
80  return ovl (uh.value ());
81 }
82 
83 DEFMETHOD (__ftp_pwd__, interp, args, ,
84  doc: /* -*- texinfo -*-
85 @deftypefn {} {@var{pwd} =} __ftp_pwd__ (@var{handle})
86 Undocumented internal function
87 @end deftypefn */)
88 {
89  url_handle_manager& uhm = interp.get_url_handle_manager ();
90 
91  url_transfer url_xfer = uhm.get_object (args(0));
92 
93  if (! url_xfer.is_valid ())
94  error ("__ftp_pwd__: invalid ftp handle");
95 
96  return ovl (url_xfer.pwd ());
97 }
98 
99 DEFMETHOD (__ftp_cwd__, interp, args, ,
100  doc: /* -*- texinfo -*-
101 @deftypefn {} {} __ftp_cwd__ (@var{handle}, @var{path})
102 Undocumented internal function
103 @end deftypefn */)
104 {
105  std::string path = "";
106  if (args.length () > 1)
107  path = args(1).xstring_value ("__ftp_cwd__: PATH must be a string");
108 
109  url_handle_manager& uhm = interp.get_url_handle_manager ();
110 
111  url_transfer url_xfer = uhm.get_object (args(0));
112 
113  if (! url_xfer.is_valid ())
114  error ("__ftp_cwd__: invalid ftp handle");
115 
116  url_xfer.cwd (path);
117 
118  return ovl ();
119 }
120 
121 DEFMETHOD (__ftp_dir__, interp, args, nargout,
122  doc: /* -*- texinfo -*-
123 @deftypefn {} {} __ftp_dir__ (@var{handle})
124 @deftypefnx {} {@var{S} =} __ftp_dir__ (@var{handle})
125 Undocumented internal function
126 @end deftypefn */)
127 {
128  url_handle_manager& uhm = interp.get_url_handle_manager ();
129 
130  url_transfer url_xfer = uhm.get_object (args(0));
131 
132  if (! url_xfer.is_valid ())
133  error ("__ftp_dir__: invalid ftp handle");
134 
135  octave_value retval;
136 
137  if (nargout == 0)
138  url_xfer.dir ();
139  else
140  {
141  string_vector sv = url_xfer.list ();
142  octave_idx_type n = sv.numel ();
143 
144  if (n == 0)
145  {
146  string_vector flds (5);
147 
148  flds(0) = "name";
149  flds(1) = "date";
150  flds(2) = "bytes";
151  flds(3) = "isdir";
152  flds(4) = "datenum";
153 
154  retval = octave_map (flds);
155  }
156  else
157  {
158  octave_map st;
159 
160  Cell filectime (dim_vector (n, 1));
161  Cell filesize (dim_vector (n, 1));
162  Cell fileisdir (dim_vector (n, 1));
163  Cell filedatenum (dim_vector (n, 1));
164 
165  st.assign ("name", Cell (sv));
166 
167  for (octave_idx_type i = 0; i < n; i++)
168  {
169  OCTAVE_TIME_T ftime;
170  bool fisdir;
171  double fsize;
172 
173  url_xfer.get_fileinfo (sv(i), fsize, ftime, fisdir);
174 
175  fileisdir(i) = fisdir;
176  time_t ftime_t = ftime;
177  filectime(i) = ctime (&ftime_t);
178  filesize(i) = fsize;
179  filedatenum(i) = double (ftime);
180  }
181 
182  st.assign ("date", filectime);
183  st.assign ("bytes", filesize);
184  st.assign ("isdir", fileisdir);
185  st.assign ("datenum", filedatenum);
186 
187  retval = st;
188  }
189  }
190 
191  return retval;
192 }
193 
194 DEFMETHOD (__ftp_ascii__, interp, args, ,
195  doc: /* -*- texinfo -*-
196 @deftypefn {} {} __ftp_ascii__ (@var{handle})
197 Undocumented internal function
198 @end deftypefn */)
199 {
200  url_handle_manager& uhm = interp.get_url_handle_manager ();
201 
202  url_transfer url_xfer = uhm.get_object (args(0));
203 
204  if (! url_xfer.is_valid ())
205  error ("__ftp_ascii__: invalid ftp handle");
206 
207  url_xfer.ascii ();
208 
209  return ovl ();
210 }
211 
212 DEFMETHOD (__ftp_binary__, interp, args, ,
213  doc: /* -*- texinfo -*-
214 @deftypefn {} {} __ftp_binary__ (@var{handle})
215 Undocumented internal function
216 @end deftypefn */)
217 {
218  url_handle_manager& uhm = interp.get_url_handle_manager ();
219 
220  url_transfer url_xfer = uhm.get_object (args(0));
221 
222  if (! url_xfer.is_valid ())
223  error ("__ftp_binary__: invalid ftp handle");
224 
225  url_xfer.binary ();
226 
227  return ovl ();
228 }
229 
230 DEFMETHOD (__ftp_close__, interp, args, ,
231  doc: /* -*- texinfo -*-
232 @deftypefn {} {} __ftp_close__ (@var{handle})
233 Undocumented internal function
234 @end deftypefn */)
235 {
236  url_handle_manager& uhm = interp.get_url_handle_manager ();
237 
238  url_handle h = uhm.lookup (args(0));
239 
240  if (! h.ok ())
241  error ("__ftp_close__: invalid ftp handle");
242 
243  uhm.free (h);
244 
245  return ovl ();
246 }
247 
248 DEFMETHOD (__ftp_mode__, interp, args, ,
249  doc: /* -*- texinfo -*-
250 @deftypefn {} {@var{mode} =} __ftp_mode__ (@var{handle})
251 Undocumented internal function
252 @end deftypefn */)
253 {
254  url_handle_manager& uhm = interp.get_url_handle_manager ();
255 
256  url_transfer url_xfer = uhm.get_object (args(0));
257 
258  if (! url_xfer.is_valid ())
259  error ("__ftp_binary__: invalid ftp handle");
260 
261  return ovl (url_xfer.is_ascii () ? "ascii" : "binary");
262 }
263 
264 DEFMETHOD (__ftp_delete__, interp, args, ,
265  doc: /* -*- texinfo -*-
266 @deftypefn {} {} __ftp_delete__ (@var{handle}, @var{path})
267 Undocumented internal function
268 @end deftypefn */)
269 {
270  std::string file = args(1).xstring_value ("__ftp_delete__: FILE must be a string");
271 
272  url_handle_manager& uhm = interp.get_url_handle_manager ();
273 
274  url_transfer url_xfer = uhm.get_object (args(0));
275 
276  if (! url_xfer.is_valid ())
277  error ("__ftp_delete__: invalid ftp handle");
278 
279  url_xfer.del (file);
280 
281  return ovl ();
282 }
283 
284 DEFMETHOD (__ftp_rmdir__, interp, args, ,
285  doc: /* -*- texinfo -*-
286 @deftypefn {} {} __ftp_rmdir__ (@var{handle}, @var{path})
287 Undocumented internal function
288 @end deftypefn */)
289 {
290  std::string dir = args(1).xstring_value ("__ftp_rmdir__: DIR must be a string");
291 
292  url_handle_manager& uhm = interp.get_url_handle_manager ();
293 
294  url_transfer url_xfer = uhm.get_object (args(0));
295 
296  if (! url_xfer.is_valid ())
297  error ("__ftp_rmdir__: invalid ftp handle");
298 
299  url_xfer.rmdir (dir);
300 
301  return ovl ();
302 }
303 
304 DEFMETHOD (__ftp_mkdir__, interp, args, ,
305  doc: /* -*- texinfo -*-
306 @deftypefn {} {} __ftp_mkdir__ (@var{handle}, @var{path})
307 Undocumented internal function
308 @end deftypefn */)
309 {
310  std::string dir = args(1).xstring_value ("__ftp_mkdir__: DIR must be a string");
311 
312  url_handle_manager& uhm = interp.get_url_handle_manager ();
313 
314  url_transfer url_xfer = uhm.get_object (args(0));
315 
316  if (! url_xfer.is_valid ())
317  error ("__ftp_mkdir__: invalid ftp handle");
318 
319  url_xfer.mkdir (dir);
320 
321  return ovl ();
322 }
323 
324 DEFMETHOD (__ftp_rename__, interp, args, ,
325  doc: /* -*- texinfo -*-
326 @deftypefn {} {} __ftp_rename__ (@var{handle}, @var{path})
327 Undocumented internal function
328 @end deftypefn */)
329 {
330  std::string oldname = args(1).xstring_value ("__ftp_rename__: OLDNAME must be a string");
331  std::string newname = args(2).xstring_value ("__ftp_rename__: NEWNAME must be a string");
332 
333  url_handle_manager& uhm = interp.get_url_handle_manager ();
334 
335  url_transfer url_xfer = uhm.get_object (args(0));
336 
337  if (url_xfer.is_valid ())
338  error ("__ftp_rename__: invalid ftp handle");
339 
340  url_xfer.rename (oldname, newname);
341 
342  return ovl ();
343 }
344 
345 DEFMETHOD (__ftp_mput__, interp, args, nargout,
346  doc: /* -*- texinfo -*-
347 @deftypefn {} {} __ftp_mput__ (@var{handle}, @var{files})
348 @deftypefnx {} {@var{filelist} =} __ftp_mput__ (@var{handle}, @var{files})
349 Undocumented internal function
350 @end deftypefn */)
351 {
352  std::string pat = args(1).xstring_value ("__ftp_mput__: PATTERN must be a string");
353 
354  url_handle_manager& uhm = interp.get_url_handle_manager ();
355 
356  url_transfer url_xfer = uhm.get_object (args(0));
357 
358  if (! url_xfer.is_valid ())
359  error ("__ftp_mput__: invalid ftp handle");
360 
361  string_vector file_list;
362 
363  glob_match pattern (sys::file_ops::tilde_expand (pat));
364  string_vector files = pattern.glob ();
365 
366  for (octave_idx_type i = 0; i < files.numel (); i++)
367  {
368  std::string file = files(i);
369 
370  if (! sys::file_exists (file))
371  error ("__ftp__mput: file does not exist");
372 
373  if (sys::dir_exists (file))
374  {
375  file_list.append (url_xfer.mput_directory ("", file));
376 
377  if (! url_xfer.good ())
378  error ("__ftp_mput__: %s", url_xfer.lasterror ().c_str ());
379  }
380  else
381  {
382  // FIXME: Does ascii mode need to be flagged here?
383  std::ifstream ifile =
384  sys::ifstream (file.c_str (),
385  std::ios::in | std::ios::binary);
386 
387  if (! ifile.is_open ())
388  error ("__ftp_mput__: unable to open file");
389 
390  url_xfer.put (file, ifile);
391 
392  ifile.close ();
393 
394  if (! url_xfer.good ())
395  error ("__ftp_mput__: %s", url_xfer.lasterror ().c_str ());
396 
397  file_list.append (file);
398  }
399  }
400 
401  if (nargout > 0)
402  return ovl (file_list);
403  else
404  return ovl ();
405 }
406 
407 DEFMETHOD (__ftp_mget__, interp, args, ,
408  doc: /* -*- texinfo -*-
409 @deftypefn {} {} __ftp_mget__ (@var{handle}, @var{pattern})
410 @deftypefnx {} {} __ftp_mget__ (@var{handle}, @var{pattern}, @var{target})
411 Undocumented internal function
412 @end deftypefn */)
413 {
414  std::string file = args(1).xstring_value ("__ftp_mget__: PATTERN must be a string");
415 
416  std::string target;
417 
418  if (args.length () == 3 && ! args(2).isempty ())
419  target = args(2).xstring_value ("__ftp_mget__: TARGET must be a string")
421 
422  url_handle_manager& uhm = interp.get_url_handle_manager ();
423 
424  url_transfer url_xfer = uhm.get_object (args(0));
425 
426  if (! url_xfer.is_valid ())
427  error ("__ftp_mget__: invalid ftp handle");
428 
429  string_vector sv = url_xfer.list ();
430  octave_idx_type n = 0;
431  glob_match pattern (file);
432 
433  for (octave_idx_type i = 0; i < sv.numel (); i++)
434  {
435  if (pattern.match (sv(i)))
436  {
437  n++;
438 
439  OCTAVE_TIME_T ftime;
440  bool fisdir;
441  double fsize;
442 
443  url_xfer.get_fileinfo (sv(i), fsize, ftime, fisdir);
444 
445  if (fisdir)
446  url_xfer.mget_directory (sv(i), target);
447  else
448  {
449  std::ofstream ofile =
450  sys::ofstream ((target + sv(i)).c_str (),
451  std::ios::out | std::ios::binary);
452 
453  if (! ofile.is_open ())
454  error ("__ftp_mget__: unable to open file");
455 
456  int(*unlink_fptr)(const std::string&) = sys::unlink;
457  unwind_action_safe delete_file (unlink_fptr, target + sv(i));
458 
459  url_xfer.get (sv(i), ofile);
460 
461  ofile.close ();
462 
463  if (url_xfer.good ())
464  delete_file.discard ();
465  }
466 
467  if (! url_xfer.good ())
468  error ("__ftp_mget__: %s", url_xfer.lasterror ().c_str ());
469  }
470  }
471 
472  if (n == 0)
473  error ("__ftp_mget__: file not found");
474 
475  return ovl ();
476 }
477 
478 OCTAVE_END_NAMESPACE(octave)
Definition: Cell.h:43
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
string_vector glob() const
Definition: glob-match.cc:41
bool match(const std::string &str) const
Definition: glob-match.cc:35
double value() const
Definition: oct-handle.h:78
bool ok() const
Definition: oct-handle.h:113
void assign(const std::string &k, const Cell &val)
Definition: oct-map.h:344
string_vector & append(const std::string &s)
Definition: str-vec.cc:110
octave_idx_type numel() const
Definition: str-vec.h:100
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)
url_handle lookup(double val)
url_transfer get_object(double val)
void put(const std::string &file, std::istream &is)
Definition: url-transfer.h:219
void get_fileinfo(const std::string &filename, double &filesize, OCTAVE_TIME_T &filetime, bool &fileisdir)
Definition: url-transfer.h:245
string_vector list()
Definition: url-transfer.h:243
void get(const std::string &file, std::ostream &os)
Definition: url-transfer.h:224
bool is_ascii() const
Definition: url-transfer.h:202
void cwd(const std::string &path)
Definition: url-transfer.h:206
bool is_valid() const
Definition: url-transfer.h:182
void mkdir(const std::string &path)
Definition: url-transfer.h:212
string_vector mput_directory(const std::string &base, const std::string &directory)
Definition: url-transfer.h:235
std::string lasterror() const
Definition: url-transfer.h:186
void mget_directory(const std::string &directory, const std::string &target)
Definition: url-transfer.h:229
std::string pwd()
Definition: url-transfer.h:251
void rmdir(const std::string &path)
Definition: url-transfer.h:210
void del(const std::string &file)
Definition: url-transfer.h:208
void rename(const std::string &oldname, const std::string &newname)
Definition: url-transfer.h:214
bool good() const
Definition: url-transfer.h:184
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
Definition: defun.h:111
void() error(const char *fmt,...)
Definition: error.cc:988
std::string dir_sep_str()
bool dir_exists(const std::string &dirname)
Definition: lo-sysdep.cc:389
bool file_exists(const std::string &filename, bool is_dir)
Definition: lo-sysdep.cc:341
std::ofstream ofstream(const std::string &filename, const std::ios::openmode mode)
Definition: lo-sysdep.cc:635
std::ifstream ifstream(const std::string &filename, const std::ios::openmode mode)
Definition: lo-sysdep.cc:621
octave_idx_type n
Definition: mx-inlines.cc:761
std::string tilde_expand(const std::string &name)
Definition: file-ops.cc:289
int unlink(const std::string &name)
Definition: file-ops.cc:727
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:219
#define octave_stdout
Definition: pager.h:309