changeset 33234:e104e9f0cf62

allow dup2, fcntl, and stat to work for file IDs not tracked by Octave (bug #65393) * syscalls.cc (Fdup2, Ffcntl, Fstat): Do stream lookup of input FID within a try block. If this throws an error then catch block will use the provided file ID directly.
author Rik <rik@octave.org>
date Thu, 21 Mar 2024 17:18:36 -0700
parents a0ea07a4c043
children c0ee9e8e3117
files libinterp/corefcn/syscalls.cc
diffstat 1 files changed, 51 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/syscalls.cc	Thu Mar 21 13:32:15 2024 -0400
+++ b/libinterp/corefcn/syscalls.cc	Thu Mar 21 17:18:36 2024 -0700
@@ -124,33 +124,34 @@
   if (args.length () != 2)
     print_usage ();
 
-  stream_list& streams = interp.get_stream_list ();
-
-  stream old_stream = streams.lookup (args(0), "dup2");
-  stream new_stream = streams.lookup (args(1), "dup2");
+  int i_old, i_new;
+  try
+    {
+      // Look up FID in Octave's list of open streams.
+      stream_list& streams = interp.get_stream_list ();
 
-  int i_old = old_stream.file_number ();
-  int i_new = new_stream.file_number ();
-
-  // If the file is not known to Octave, try the operation on the
-  // provided file ID.
-
-  if (i_old < 0)
-    i_old = args(0).int_value (true);
+      stream old_stream = streams.lookup (args(0), "dup2");
+      stream new_stream = streams.lookup (args(1), "dup2");
 
-  if (i_new < 0)
-    i_new = args(1).int_value (true);
-
-  if (i_old >= 0 && i_new >= 0)
+      i_old = old_stream.file_number ();
+      i_new = new_stream.file_number ();
+    }
+  catch (execution_exception& ee)
     {
-      std::string msg;
+      // If the FIDs are not known to Octave, try the provided FIDs directly.
+      i_old = args(0).int_value (true);
+      i_new = args(1).int_value (true);
+    }
 
-      int status = sys::dup2 (i_old, i_new, msg);
+  if (i_old < 0 || i_new < 0)
+    // Bad FIDs, return error immediately
+    return ovl (-1, "");
 
-      return ovl (status, msg);
-    }
-  else
-    return ovl (-1, "");
+  std::string msg;
+
+  int status = sys::dup2 (i_old, i_new, msg);
+
+  return ovl (status, msg);
 }
 
 DEFMETHODX ("exec", Fexec, interp, args, ,
@@ -447,28 +448,28 @@
   if (args.length () != 3)
     print_usage ();
 
-  stream_list& streams = interp.get_stream_list ();
+  int fid;
+  try
+    {
+      // Look up FID in Octave's list of open streams.
+      stream_list& streams = interp.get_stream_list ();
+      stream strm = streams.lookup (args(0), "fcntl");
+      fid = strm.file_number ();
+    }
+  catch (execution_exception& ee)
+    {
+      // If the file is not known to Octave, try the provided file ID directly.
+      fid = args(0).int_value (true);
+    }
 
-  stream strm = streams.lookup (args(0), "fcntl");
-
-  int fid = strm.file_number ();
+  if (fid < 0)
+    error ("fcntl: invalid file id FID");
 
   // FIXME: Do we want to use xint_value and throw a warning message
   //        if input validation fails?
   int req = args(1).int_value (true);
   int arg = args(2).int_value (true);
 
-  // FIXME: Need better checking here?
-
-  // If the file is not known to Octave, try the operation on the
-  // provided file ID.
-
-  if (fid < 0)
-    fid = args(0).int_value (true);
-
-  if (fid < 0)
-    error ("fcntl: invalid file id");
-
   octave_value_list retval;
   std::string msg;
 
@@ -923,15 +924,21 @@
 
   if (args(0).is_scalar_type ())
     {
-      stream_list& streams = interp.get_stream_list ();
-
-      int fid = streams.get_file_number (args(0));
-
-      // If the file is not known to Octave, try the operation on the
-      // provided file ID.
+      int fid;
+      try
+        {
+          // Look up FID in Octave's list of open streams.
+          stream_list& streams = interp.get_stream_list ();
+          fid = streams.get_file_number (args(0));
+        }
+      catch (execution_exception& ee)
+        {
+          // If the file is not known to Octave, try provided file ID directly.
+          fid = args(0).int_value (true);
+        }
 
       if (fid < 0)
-        fid = args(0).int_value (true);
+        error ("stat: invalid file id FID");
 
       sys::file_fstat fs (fid);