[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