# HG changeset patch # User Rik # Date 1711066716 25200 # Node ID e104e9f0cf6251c8b93b9302c4aa3c155664a604 # Parent a0ea07a4c04325c460469db54bc15cf769d71d4a 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. diff -r a0ea07a4c043 -r e104e9f0cf62 libinterp/corefcn/syscalls.cc --- 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);