Still do it so we capture FilePath.remote (which many JRE methods suppress),
but fix the wrapper Throwable.message to include cause.toString() according to convention.
If we ever decide to develop a compatibility thunk library for these changes to help promote deployment in plugins,
then these classes being a nested type is problematic as they'll fail to load under onld Jenkins
If a @SlaveToMaster Callable gets sent to the master, and if inside its call() method the code directly/indirectly performs file system access (for example on files and directories that it didn't receive as parameters), that is not meant to be the subject of the filter check.
Rather, the check is meant for FilePath that the other side sends to us, when it points to a local file.
So it makes more sense to compute the effective FilePathFilter during the deserialization, as opposed to doing so when the actual operation is attempted.
Various FileCallable impls in FilePath fits this pattern, as it drags outer FilePath instance with itself. In addition, this change addresses other situations correctly, where FilePath is used as arguments and return values of other Callables, such as the following:
FilePath f = channel.call(new SlaveWillDoSomeComputationAndGiveMeTheResultAsFile());
f.copyTo(build.getRootDir().child("data.xml"))
"f.copyTo" happens in the context of Channel.current()==null, but we need to check that 'f' is legit and not something like
new FilePath(new File("/etc/shadow"))
- If a write results in a file creation, do the create check, to align with the POSIX semantics.
- Don't make pointless mkdirs check if the directory already exists
- read vs readSymlink difference is dangerous because read() can be called for symlinks in other context as well.
Instead it was being thrown in a Future that the master did not wait for:
the writing side failed with a closed pipe exception, and this meaningless error was thrown up.
Fixing by waiting for the reading side first, so any error there will be thrown up.
(If there was _also_ an error on the writing side, we would miss it, but typically this will just be the closed stream.)
Confusingly, it is instead MasterComputer.localChannel!
If that is fed back into FilePath.<init>(VirtualChannel,String) rather than using .<init>(FilePath,String)
you get an object that behaves strangely and throws exceptions.
The updated version uses the locally cached timestamp, '.timestamp', to set the
'If-Modified-Since' header. 304 Not Modified responses are dealt with by
aborting the installation.