[MonoDevelop] Monodevelop 5.10
Russell Haley
russ.haley at gmail.com
Mon Nov 2 06:17:34 UTC 2015
Hey Guys,
Romains suggestion was what I needed. The offending code is at the bottom
of SystemRename(string sourceFile,string destFile) in the file
src/core/MonoDevelop.Core/MonoDevelop.Core/FileService.cs:
else {
if (Syscall.rename (sourceFile, destFile) != 0) { //Should this be
Stdlib as well?
switch (Stdlib.GetLastError ()) {
case Errno.EACCES:
case Errno.EPERM:
throw new UnauthorizedAccessException ();
case Errno.EINVAL:
throw new InvalidOperationException ();
case Errno.ENOTDIR:
throw new DirectoryNotFoundException ();
case Errno.ENOENT:
throw new FileNotFoundException ();
case Errno.ENAMETOOLONG:
throw new PathTooLongException ();
default:
throw new IOException ();
}
}
}
Notice there is no case for ErrNo.EXDEV. I have added a new control case as
such:
else {
if (Stdlib.rename (sourceFile, destFile) != 0) {
switch (Stdlib.GetLastError ()) {
case Errno.EACCES:
case Errno.EPERM:
throw new UnauthorizedAccessException ();
case Errno.EINVAL:
throw new InvalidOperationException ();
case Errno.ENOTDIR:
throw new DirectoryNotFoundException ();
case Errno.ENOENT:
throw new FileNotFoundException ();
case Errno.ENAMETOOLONG:
throw new PathTooLongException ();
case Errno.EXDEV:
CrossFilesystemRename (sourceFile, destFile);
break;
default:
throw new IOException ();
}
}
}
With the new function here:
private static void CrossFilesystemRename(string sourceFile, string
destFile)
{
//copy the existing destfile to tmp
//move the sourceFile to the destFilename
//delete the old destFile contents
string tempFile = Path.Combine ("/tmp/", Path.GetRandomFileName () +
".tmp");
try{
InternalMoveFile (destFile, tempFile);
InternalMoveFile(sourceFile,destFile);
DeleteFile(tempFile);
}
catch
{
if (!File.Exists (destFile)) {
InternalMoveFile (tempFile, destFile);
}
if (File.Exists (tempFile)) {
DeleteFile(tempFile);
}
throw;
}
}
Two things to note:
1) I noticed that the original was using Syscall.rename, when the rename
function seems to be part of StdLib. Syscall in fact seems to only have a
reference to renameat not rename, so I changed FileService.cs to StdLib
with no discernible difference. Does anyone have some input on this?
2) As you can see there is a horrible hard coded /tmp file path. I am not
sure how to determine the temp directory in a unix system. That said in
FreeBSD, /tmp is part of the rootfs and seems to be pretty standard in
Linux too:
https://docs.freebsd.org/doc/5.4-RELEASE/usr/share/doc/handbook/dirstructure.html
Does anyone have a different solution?
Anyway, this fixes the issue I was having. Thank you everyone for helping
me pull this together. I'll look to submit a patch to Xamarin sometime
later in the week.
Cheers,
Russ
On Sun, Nov 1, 2015 at 1:34 AM, Romain Tartière <romain at blogreen.org> wrote:
> Hi,
>
> On Sat, Oct 31, 2015 at 09:48:03PM -0700, Russell Haley wrote:
> > Any thoughts? I am guessing that the syscall.rename is doing something
> > other than an mv and zfs doesn't like it. Or conversly, zfs is doing
> > something funky and the mono wrapper library doesn't like it?
>
> rename(2) is intended to rename a link, so can't move a file from a
> filesystem to another. mv(1) tries to rename(2) files, and if the
> rename failed with EXDEV, attempts to create the target file, copy data
> from the source file, copy permissions and unlink(2) the source (see
> fastcopy() function in mv.c).
>
> Mono should have a similar behavior, and something may get wrong in this
> logic. Maybe you can try to search what is happening there?
>
> --
> Romain Tartière <romain at FreeBSD.org> http://people.FreeBSD.org/~romain/
> pgp: 8234 9A78 E7C0 B807 0B59 80FF BA4D 1D95 5112 336F (ID: 0x5112336F)
> (plain text =non-HTML= PGP/GPG encrypted/signed e-mail much appreciated)
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ximian.com/pipermail/monodevelop-list/attachments/20151101/ebe3fa44/attachment.html>
More information about the Monodevelop-list
mailing list