[Mono-bugs] [Bug 490002] New: IS_PORTABILITY_DRIVE && IS_PORTABILITY_CASE has unexpected effects

bugzilla_noreply at novell.com bugzilla_noreply at novell.com
Sat Mar 28 03:04:04 EDT 2009


https://bugzilla.novell.com/show_bug.cgi?id=490002


           Summary: IS_PORTABILITY_DRIVE && IS_PORTABILITY_CASE has
                    unexpected effects
    Classification: Mono
           Product: Mono: Runtime
           Version: unspecified
          Platform: Other
        OS/Version: Other
            Status: NEW
          Severity: Normal
          Priority: P5 - None
         Component: io-layer
        AssignedTo: lupus at novell.com
        ReportedBy: matthew.flaschen at gatech.edu
         QAContact: mono-bugs at lists.ximian.com
          Found By: ---


Created an attachment (id=282680)
 --> (https://bugzilla.novell.com/attachment.cgi?id=282680)
Tests opening an existing file called C:\foo

User-Agent:       Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.7)
Gecko/2009030422 Ubuntu/8.04 (hardy) Firefox/3.0.7

http://www.mono-project.com/IOMap says that MONO_IOMAP=drive strips drive name
from pathnames.  I would have expected that to mean that accessing and/or
modifying C:\foo always results in an attempt to access and/or create /foo. 
This would usually throw an error on GNU/Linux, but it makes conceptual sense
to me, as both are usually the root of the main drive.

However, it turns out (I originally discovered this issue in NUnit's runtime,
but a much simpler test is attached) it doesn't work quite like that. When
/accessing/ C:/ foo without O_CREAT (e.g. with FileMode.Open) MONO_IOMAP=drive
does what I expects.  It fails with System.IO.FileNotFoundException when /foo
does not exist, and writes to the file when it exists and is writable.  To
verify this works as expected run:

sudo rm -f /foo; sudo touch /foo; sudo chmod a+w /foo; MONO_IOMAP=drive
/root_file_oe.exe

However, MONO_IOMAP=drive alone does not rewrite attempts to create a file,
such as with FileMode.Create.  That means you get a C:\foo in the current
directory.  See mono_iomap_drive.txt which was created with:

rm -f ./C:\\foo; MONO_IOMAP=drive strace root_file.exe > mono_iomap_drive.txt
2>&1

Also note ./C:\\foo is created

The strangest part, though is that MONO_IOMAP=all does rewrite such attempts. 
So the same program run with MONO_IOMAP=all does attempt to create /foo,
typically resulting in a System.UnauthorizedAccessException (unless of course /
is writable).  See mono_iomap_all.txt which was created with:

sudo rm /foo; MONO_IOMAP=all strace root_file.exe > mono_iomap_all.txt 2>&1

The reason can be seen in the source
(http://anonsvn.mono-project.com/viewvc/trunk/mono/mono/utils/mono-io-portability.c?view=log&pathrev=130455)
though it definitely wasn't obvious.  last_exists is false when _wapi_open
(http://anonsvn.mono-project.com/viewvc/trunk/mono/mono/io-layer/io-portability.c?revision=122961&view=markup&pathrev=130455)
calls mono_portability_find_file, because O_CREAT was sent (meaning the OS is
allowed to create the file).  The first two places where
mono_portability_find_file returns a non-null pathname both require last_exist
to be true (corresponding with O_CREAT not being set).  After those two
returns, it returns NULL if !(IS_PORTABILITY_CASE).   Otherwise, if case
refactoring /is/ allowed, it goes into an entirely new set of case-insensitive
logic which eventually results in it creating /foo because /foo=/foo
(case-insensitive path comparison)

Of course, if only IS_PORTABILITY_CASE is set, then it won't drop the drive
letter, so it still creates ./C:/foo

So the only way to get it to create files in the root is to use MONO_IOMAP=all.
 I don't know what The Right Thing To Do is.  It seems sort of reasonable to
only fallback to /foo when creation is not allowed.  But if so, it should
/still/ not create /foo when IS_PORTABILITY_CASE is set.  It would be simpler
and probably more in line with the docs to always create /foo if
MONO_IOMAP=drive is set

I created two short test programs (referred to above), root_file.cs and
root_file_oe.cs.  root_file.cs attempts to create a file, while root_file_oe
attempts to open an existing file.

I hope this is report is helpful.  Let me know if you need any additional info.

Reproducible: Always

Steps to Reproduce:
1.
2.
3.

-- 
Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.


More information about the mono-bugs mailing list