You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@mina.apache.org by Julien Vermillard <jv...@archean.fr> on 2009/02/27 10:07:38 UTC

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Le Fri, 27 Feb 2009 09:37:24 +0100,
Emmanuel Lecharny <el...@apache.org> a écrit :

> Niklas Gustavsson wrote:
> > On Fri, Feb 27, 2009 at 1:17 AM, Emmanuel Lecharny
> > <el...@apache.org> wrote: 
> >> We haved conducted more tests this afternoon, using another JVM on
> >> Mac OS X 10.5 (java 6), and didn't had the same problem.
> >>     
> >
> > Sounds like we can conclude that it's a JVM bug then.
> >   
> 
> This is also my opinion...
> >   
> >> Here is the failing test in
> >> this case :
> >>     
> >
> > Would you be able to send me the debug level log for this failing
> > test? 
> Will do asap.
> > Damn, I need to get myself a Mac :-)
> >   
> Well, considering how crappy is the JVM on these machines ... :)

Get a Mac running Linux ;)
Julien

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Fri, Feb 27, 2009 at 2:06 PM, Ashish <pa...@gmail.com> wrote:
> Is OS name not sufficient for this? Agree that it leads to hard-coding.

HFS+ seems to be able to have different settings that affect the case
handling, thus looking at the OS name will not help. Also, you can
mount an ext3 file system on a Mac or a HFS+ file system on Linux.

/niklas

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Fri, Mar 6, 2009 at 8:30 PM, David Latorre <dv...@gmail.com> wrote:
> Do you know when it's likely that getCanonical*   fails? Should we try a
> workaround in that case? If you think our code is ok as is, that's much
> better!

I have no idea, which is why I choose to throw the exception. I'm also
okay with swallowing the exception and returning null like you did, if
we add a logging statement on WARN level.

/niklas

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by David Latorre <dv...@gmail.com>.
2009/3/6 Emmanuel Lecharny <el...@apache.org>

> Niklas Gustavsson wrote:
>
>> On Fri, Mar 6, 2009 at 11:57 AM, Emmanuel Lecharny <el...@apache.org>
>> wrote:
>>
>>
>>> Just a small remark : it would be _very_ cool if you can extend the
>>> NativeFtpFile interface with a getFile() method, because having to cast
>>> the
>>> object to get the so called PhysicalFile is a bit a PITA, IMHO :)
>>>
>>>
>>
>> Not sure I understand, NativeFtpFile is not an interface but an
>> implementation of the FtpFile interface. And you should pretty much
>> never need to get the underlying java.io.File object unless you really
>> know you're working with the native file system (FtpServer never makes
>> that assumption). And, since there are file system implementations
>> for, for example JDBC, there might not even be a file or even a
>> reasonable object we could return, at least not a java.io.File.
>>
>>
> Never mind. David's solution is way better. Yesturday, it was late, and it
> took me a bit of time to find the way to grab the File object, and I found
> the solution I proposed kind of dirty, to say the least. Doing the job in
> NativeFtpFile.equals() method is way cleaner.


Actually niklas had already commited the change himself when I sent the
email, the only difference being that he is not swallowing the Exception as
my quick code  - I sent the whole code just to remark that I didn't know
what to do with that exception.
Still I have some concerns about the getCanonicalFile/getCanonicalPath
methods because of that IOException. My thinking is that Sun is not using
getCanonical... in the File equals() method because it is not safe to rely
on it, otherwise, why would they provide a broken implementation of
FIle.equals()?

Do you know when it's likely that getCanonical*   fails? Should we try a
workaround in that case? If you think our code is ok as is, that's much
better!



> /niklas
>>
>>
>>
>
>
> --
> --
> cordialement, regards,
> Emmanuel Lécharny
> www.iktek.com
> directory.apache.org
>
>
>

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Emmanuel Lecharny <el...@apache.org>.
Niklas Gustavsson wrote:
> On Fri, Mar 6, 2009 at 11:57 AM, Emmanuel Lecharny <el...@apache.org> wrote:
>   
>> Just a small remark : it would be _very_ cool if you can extend the
>> NativeFtpFile interface with a getFile() method, because having to cast the
>> object to get the so called PhysicalFile is a bit a PITA, IMHO :)
>>     
>
> Not sure I understand, NativeFtpFile is not an interface but an
> implementation of the FtpFile interface. And you should pretty much
> never need to get the underlying java.io.File object unless you really
> know you're working with the native file system (FtpServer never makes
> that assumption). And, since there are file system implementations
> for, for example JDBC, there might not even be a file or even a
> reasonable object we could return, at least not a java.io.File.
>   
Never mind. David's solution is way better. Yesturday, it was late, and 
it took me a bit of time to find the way to grab the File object, and I 
found the solution I proposed kind of dirty, to say the least. Doing the 
job in NativeFtpFile.equals() method is way cleaner.
> /niklas
>
>   


-- 
--
cordialement, regards,
Emmanuel Lécharny
www.iktek.com
directory.apache.org



Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Fri, Mar 6, 2009 at 11:57 AM, Emmanuel Lecharny <el...@apache.org> wrote:
> Just a small remark : it would be _very_ cool if you can extend the
> NativeFtpFile interface with a getFile() method, because having to cast the
> object to get the so called PhysicalFile is a bit a PITA, IMHO :)

Not sure I understand, NativeFtpFile is not an interface but an
implementation of the FtpFile interface. And you should pretty much
never need to get the underlying java.io.File object unless you really
know you're working with the native file system (FtpServer never makes
that assumption). And, since there are file system implementations
for, for example JDBC, there might not even be a file or even a
reasonable object we could return, at least not a java.io.File.

/niklas

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Emmanuel Lecharny <el...@apache.org>.
Niklas Gustavsson wrote:
> I've moved the patch into NativeFtpFile where it belongs, and the test
> still pass on Linux. I've commited this to trunk (rev 750819),
> Emmanuel would you be able to rerun the test from trunk? If it passed,
> I will merge this into the 1.0.x branch as well.
>   
Will do.

Just a small remark : it would be _very_ cool if you can extend the 
NativeFtpFile interface with a getFile() method, because having to cast 
the object to get the so called PhysicalFile is a bit a PITA, IMHO :)


-- 
--
cordialement, regards,
Emmanuel Lécharny
www.iktek.com
directory.apache.org



Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Fri, Mar 6, 2009 at 12:56 AM, Emmanuel Lecharny <el...@apache.org> wrote:
> Ok, I have changed the RMDIR impl, and now, all the tests are passing.

This is great news!

> Could someone do the test on W$ and Linux ?

I've moved the patch into NativeFtpFile where it belongs, and the test
still pass on Linux. I've commited this to trunk (rev 750819),
Emmanuel would you be able to rerun the test from trunk? If it passed,
I will merge this into the 1.0.x branch as well.

/niklas

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Fri, Mar 6, 2009 at 12:04 PM, Emmanuel Lecharny <el...@apache.org> wrote:
> Apple, I know at least 8 persons who need a Mac Book Pro 17", 8 Gb, Quad
> core 3Ghz, 300 Gb SSD disk, 6h battery...

Yeah, send one my way :-D

/niklas

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Emmanuel Lecharny <el...@apache.org>.
David Latorre wrote:
> After changing NativeFtpFile equals to the followingcode :
>  @Override
>     public boolean equals(Object obj) {
>      try{
>      if(obj != null && obj instanceof NativeFtpFile) {
>      return this.file.getCanonicalPath().equals( ((NativeFtpFile)
> obj).file.getCanonicalPath() ) ;
>      }
>      }catch(IOException e){}
>      return false;
>     }
>
> All the tests are passing under Windows (Vista) with Jre 1.6.0_7 and  Jre
> 1.5.0_15
>   
Way better than the quick hack I submitted (but I did it around 1 am).

Funny how such a simple problem has stuck at least 8 high level 
developpers (!) for one full week... May be not having a Mac is also the 
reason we got stuck and also the lack of time for many of us...

Apple, I know at least 8 persons who need a Mac Book Pro 17", 8 Gb, Quad 
core 3Ghz, 300 Gb SSD disk, 6h battery...


And a special thank for Saï who finally found the way out of this maze !

-- 
--
cordialement, regards,
Emmanuel Lécharny
www.iktek.com
directory.apache.org



Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by David Latorre <dv...@gmail.com>.
2009/3/6 Emmanuel Lecharny <el...@apache.org>

> Sai Pullabhotla wrote:
>
>> That's what I was expecting. So, if the issue is about RMDIR on the
>> current
>> working directory, we should be able to match up the canonical paths and
>> if
>> they are same (the directory that was requested for deletion and the
>> current
>> working directory), send an error back. Does that sound correct?
>>
>>
> :)
>
> Ok, I have changed the RMDIR impl, and now, all the tests are passing.
> Following Sai's suggestion, here is what I have :
>
> instead of :
>
> if(file.equals(cwd)) { blah
>
> I now have :
>
> File cwdFile = ((NativeFtpFile)cwd).getPhysicalFile();
> File currentFile = ((NativeFtpFile)file).getPhysicalFile();
>
> if (cwdFile.getCanonicalPath().equals(currentFile.getCanonicalPath())) {
> blah
>
>
> and it works on mac.
>
> Could someone do the test on W$ and Linux ?
>

After changing NativeFtpFile equals to the followingcode :
 @Override
    public boolean equals(Object obj) {
     try{
     if(obj != null && obj instanceof NativeFtpFile) {
     return this.file.getCanonicalPath().equals( ((NativeFtpFile)
obj).file.getCanonicalPath() ) ;
     }
     }catch(IOException e){}
     return false;
    }

All the tests are passing under Windows (Vista) with Jre 1.6.0_7 and  Jre
1.5.0_15





>
> Thanks for the heads up, Sai !
>
> --
> --
> cordialement, regards,
> Emmanuel Lécharny
> www.iktek.com
> directory.apache.org
>
>
>

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Emmanuel Lecharny <el...@apache.org>.
Sai Pullabhotla wrote:
> That's what I was expecting. So, if the issue is about RMDIR on the current
> working directory, we should be able to match up the canonical paths and if
> they are same (the directory that was requested for deletion and the current
> working directory), send an error back. Does that sound correct?
>   
:)

Ok, I have changed the RMDIR impl, and now, all the tests are passing. 
Following Sai's suggestion, here is what I have :

instead of :

if(file.equals(cwd)) { blah

I now have :

File cwdFile = ((NativeFtpFile)cwd).getPhysicalFile();
File currentFile = ((NativeFtpFile)file).getPhysicalFile();

if (cwdFile.getCanonicalPath().equals(currentFile.getCanonicalPath())) { 
blah


and it works on mac.

Could someone do the test on W$ and Linux ?

Thanks for the heads up, Sai !

-- 
--
cordialement, regards,
Emmanuel Lécharny
www.iktek.com
directory.apache.org



Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Sai Pullabhotla <sa...@jmethods.com>.
That's what I was expecting. So, if the issue is about RMDIR on the current
working directory, we should be able to match up the canonical paths and if
they are same (the directory that was requested for deletion and the current
working directory), send an error back. Does that sound correct?

Sai Pullabhotla
Phone: (402) 408-5753
Fax: (402) 408-6861
www.jMethods.com



On Thu, Mar 5, 2009 at 3:38 PM, Emmanuel Lecharny <el...@apache.org>wrote:

> Niklas Gustavsson wrote:
>
>> On Thu, Mar 5, 2009 at 8:55 PM, Emmanuel Lecharny <el...@apache.org>
>> wrote:
>>
>>
>>> i'm pretty sure I tested it, and the getCanonicalPath() keeps the name
>>> which
>>> as been used on HSF+.
>>>
>>>
>>
>> Could you please clarify that? If a file exists with the name "foo",
>> and we call new File("FOO").getCanonicalPath(), what casing will it
>> return?
>>
>>
>
> new File("FOO").getCanonicalPath() --> foo if the foo file exists.
> new File("FOO").getCanonicalPath() --> FOO if the foo file does not exist.
>
> In other words, it returns the existing name, or the new name.
>
>
>>
>
>  /niklas
>>
>>
>>
>
>
> --
> --
> cordialement, regards,
> Emmanuel Lécharny
> www.iktek.com
> directory.apache.org
>
>
>

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Emmanuel Lecharny <el...@apache.org>.
Niklas Gustavsson wrote:
> On Thu, Mar 5, 2009 at 8:55 PM, Emmanuel Lecharny <el...@apache.org> wrote:
>   
>> i'm pretty sure I tested it, and the getCanonicalPath() keeps the name which
>> as been used on HSF+.
>>     
>
> Could you please clarify that? If a file exists with the name "foo",
> and we call new File("FOO").getCanonicalPath(), what casing will it
> return?
>   

new File("FOO").getCanonicalPath() --> foo if the foo file exists.
new File("FOO").getCanonicalPath() --> FOO if the foo file does not exist.

In other words, it returns the existing name, or the new name.
>   

> /niklas
>
>   


-- 
--
cordialement, regards,
Emmanuel Lécharny
www.iktek.com
directory.apache.org



Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Thu, Mar 5, 2009 at 8:55 PM, Emmanuel Lecharny <el...@apache.org> wrote:
> i'm pretty sure I tested it, and the getCanonicalPath() keeps the name which
> as been used on HSF+.

Could you please clarify that? If a file exists with the name "foo",
and we call new File("FOO").getCanonicalPath(), what casing will it
return?

/niklas

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Emmanuel Lecharny <el...@apache.org>.
Niklas Gustavsson wrote:
> On Thu, Mar 5, 2009 at 5:34 PM, Sai Pullabhotla
> <sa...@jmethods.com> wrote:
>   
>> I would like to take this one step back as I think that the
>> getCanonicalFile() or getCanonicalPath() on an existing file should return
>> the exact file name with the correct case as it is stored on the file
>> system. At least that is what the JavaDoc says.
>>     
>
> There was some discussion previously on this thread where I believe
> Emmanuel tested canonical paths with no success. But, let's hope I got
> it wrong :-)
>   
i'm pretty sure I tested it, and the getCanonicalPath() keeps the name 
which as been used on HSF+.
> /niklas
>
>   


-- 
--
cordialement, regards,
Emmanuel Lécharny
www.iktek.com
directory.apache.org



Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Thu, Mar 5, 2009 at 5:34 PM, Sai Pullabhotla
<sa...@jmethods.com> wrote:
> I would like to take this one step back as I think that the
> getCanonicalFile() or getCanonicalPath() on an existing file should return
> the exact file name with the correct case as it is stored on the file
> system. At least that is what the JavaDoc says.

There was some discussion previously on this thread where I believe
Emmanuel tested canonical paths with no success. But, let's hope I got
it wrong :-)

/niklas

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Sai Pullabhotla <sa...@jmethods.com>.
I would like to take this one step back as I think that the
getCanonicalFile() or getCanonicalPath() on an existing file should return
the exact file name with the correct case as it is stored on the file
system. At least that is what the JavaDoc says.

Can some one run this test program on OS X/HFS and post the results back?
Before running this, make sure there is no directory named "Foo" in your
working directory.

import java.io.File;
import java.io.IOException;

public class FileCaseTest {

    public static void main(String[] args) throws IOException {
        File dir = new File("Foo");
        boolean created = dir.mkdir();
        System.out.println("Created directory " + dir + ": " + created);

        dir = new File("FOO");
        System.out.println("Absolute Path: " + dir.getAbsoluteFile());
        System.out.println("Canonical Path: " + dir.getCanonicalFile());
    }
}

This is what I get on Windows:

Created directory Foo: true
Absolute Path: D:\linomasoftware\projects\test\FOO
Canonical Path: D:\linomasoftware\projects\test\Foo

On Linux:

Created directory Foo: true
Absolute Path: /home/inspiron/dev/eclipseworkspace/develop/FOO
Canonical Path: /home/inspiron/dev/eclipseworkspace/develop/FOO

The canonical path is still in all CAPS because there is no file with the
name FOO exists. I would be curious to see what results we get back with the
HFS file system in question.

Regards,

Sai Pullabhotla
Phone: (402) 408-5753
Fax: (402) 408-6861
www.jMethods.com



On Wed, Mar 4, 2009 at 4:13 PM, Niklas Gustavsson <ni...@protocol7.com>wrote:

> On Mon, Mar 2, 2009 at 4:54 PM, Niklas Gustavsson <ni...@protocol7.com>
> wrote:
> > Let me whip up a prototype and we can test it on the available platforms.
>
> Alright, here's a prototype that I would much appreciate if all of you
> would take the time to test. First of all, you need to set the
> FILE_SYSTEM_TYPE to the correct value (this is only used for
> verification in the tests). On case sensitive file systems (most of
> the *nix file systems), this should be set to
> FileSystemType.CaseSensitive. On NTFS it should be set to
> CaseInsensitiveMissingAsTrue, and on case-insensitive HFS to
> CaseInsensitiveMissingAsFalse. It would be very interesting to have
> this code tested on other file systems. If you do, please report the
> file system and the test results.
>
> /niklas
>
> package org.apache.ftpserver.filesystem.nativefs.impl;
>
> import java.io.File;
> import java.io.FilenameFilter;
> import java.io.IOException;
>
> import junit.framework.TestCase;
>
> public class FileEqualsTest extends TestCase {
>
>    private enum FileSystemType {
>        CaseSensitive,
>        // non-existing files with different casing are equal
>        // e.g. NTFS
>        CaseInsensitiveMissingAsTrue,
>        // non-existing files with different casing are non-equal
>        // e.g. HFS
>        CaseInsensitiveMissingAsFalse
>    };
>
>    private static final FileSystemType FILE_SYSTEM_TYPE =
> FileSystemType.CaseSensitive;
>
>    private boolean isCaseSensitive() {
>        return FILE_SYSTEM_TYPE == FileSystemType.CaseSensitive;
>    }
>
>    private boolean isCaseInsensitive() {
>        return FILE_SYSTEM_TYPE != FileSystemType.CaseSensitive;
>    }
>
>    @Override
>    protected void setUp() throws Exception {
>        System.out.println("File system type: " + FILE_SYSTEM_TYPE);
>        super.setUp();
>    }
>
>    public void testSimple() throws IOException {
>        File f1 = new File("foo");
>        assertTrue(f1.createNewFile());
>        File f2 = new File("foo");
>
>        assertTrue(equals(f1, f2));
>    }
>
>    public void testNonExistingButSimple() {
>        File f1 = new File("foo");
>        File f2 = new File("foo");
>
>        assertTrue(equals(f1, f2));
>    }
>
>    public void testDifferentCase() throws IOException {
>        File f1 = new File("foo");
>        assertTrue(f1.createNewFile());
>        File f2 = new File("FOO");
>
>        // if this succeeds, we have two different files
>        assertEquals(isCaseSensitive(), f2.createNewFile());
>
>        assertEquals(isCaseInsensitive(), equals(f1, f2));
>    }
>
>    public void testDifferentCaseNonExisting() throws IOException {
>        File f1 = new File("foo");
>        File f2 = new File("FOO");
>
>        assertEquals(FILE_SYSTEM_TYPE ==
> FileSystemType.CaseInsensitiveMissingAsTrue, equals(f1, f2));
>    }
>
>    public void testSameNameDifferentParent() throws IOException {
>        File f1 = new File("foo");
>        assertTrue(f1.createNewFile());
>        File dir2 = new File("dir");
>        assertTrue(dir2.mkdir());
>        File f2 = new File(dir2, "foo");
>        assertTrue(f2.createNewFile());
>
>        assertFalse(equals(f1, f2));
>    }
>
>    public boolean equals(final File f1, final File f2) {
>        if (f1 == null || f2 == null) {
>            return false;
>        }
>
>        if (f1.equals(f2)) {
>            // file equals, valid on all file systems
>            return true;
>        } else {
>            boolean f1Exists = f1.exists();
>            boolean f2Exists = f2.exists();
>
>            if (f1.getName().equalsIgnoreCase(f2.getName())) {
>                // same name, do both exist?
>                if (f1Exists && f2Exists) {
>                    // both files exists, do they have the same parent?
>
>                    // TODO should we use canonical or absolute path?
>                    File f1Parent = f1.getAbsoluteFile().getParentFile();
>                    File f2Parent = f2.getAbsoluteFile().getParentFile();
>
>                    if (f1Parent != null && f2Parent != null) {
>                        if (equals(f1Parent, f2Parent)) {
>                            // okay, if we got here, the parents are the
> same,
>                            // the file names are the same and both files
> exists
>                            // let's check if there are multiple files
> or only one in the parent
>                            // with that name
>
>
>                            // choosing either parent should be fine,
> they are equal
>                            String[] files = f1Parent
>                                    .list(new FilenameFilter() {
>                                        public boolean accept(File
> dir, String name) {
>                                            return name.equalsIgnoreCase(f1
>                                                    .getName());
>                                        }
>                                    });
>
>                            if (files.length == 1) {
>                                // exactly one file matched the name,
> the files must be equal
>                                return true;
>                            } else if (files.length > 1) {
>                                return false;
>                            } else {
>                                // no file matching, must be a bug somewhere
>                                throw new RuntimeException("Should not
> happen");
>                            }
>                        } else {
>                            // different parents, return false
>                            return false;
>                        }
>                    } else if (f1Parent == null && f2Parent == null) {
>                        // no parents, we can do nothing more and thus
> have to return false
>                        return false;
>                    } else {
>                        // different parents
>                        return false;
>                    }
>                } else if (!f1Exists && !f2Exists) {
>                    // none of the file exists, we can only trust the
> equals result (which by now must be false)
>                    return false;
>                } else {
>                    // only one of the files exists, return false
>                    return false;
>                }
>            } else {
>                // file names not equal
>                return false;
>            }
>        }
>    }
>
>    @Override
>    protected void tearDown() throws Exception {
>        new File("foo").delete();
>        new File("FOO").delete();
>        new File("dir/foo").delete();
>        new File("dir").delete();
>    }
>
> }
>

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Maarten Bosteels <mb...@gmail.com>.
Works fine on Fedora 10, ext2, ext3 and ntfs mounted with ntfs-3g (fuseblk)
For the mounted ntfs partition I had to use CaseSensitive.

Maarten

On Thu, Mar 5, 2009 at 10:39 AM, Emmanuel Lecharny <el...@apache.org>wrote:

> Works fine on my Mac OS X 10.4/Java 5
>
> On Wed, Mar 4, 2009 at 11:13 PM, Niklas Gustavsson <ni...@protocol7.com>
> wrote:
> > On Mon, Mar 2, 2009 at 4:54 PM, Niklas Gustavsson <ni...@protocol7.com>
> wrote:
> >> Let me whip up a prototype and we can test it on the available
> platforms.
> >
> > Alright, here's a prototype that I would much appreciate if all of you
> > would take the time to test. First of all, you need to set the
> > FILE_SYSTEM_TYPE to the correct value (this is only used for
> > verification in the tests). On case sensitive file systems (most of
> > the *nix file systems), this should be set to
> > FileSystemType.CaseSensitive. On NTFS it should be set to
> > CaseInsensitiveMissingAsTrue, and on case-insensitive HFS to
> > CaseInsensitiveMissingAsFalse. It would be very interesting to have
> > this code tested on other file systems. If you do, please report the
> > file system and the test results.
> >
> > /niklas
> >
> > package org.apache.ftpserver.filesystem.nativefs.impl;
> >
> > import java.io.File;
> > import java.io.FilenameFilter;
> > import java.io.IOException;
> >
> > import junit.framework.TestCase;
> >
> > public class FileEqualsTest extends TestCase {
> >
> >    private enum FileSystemType {
> >        CaseSensitive,
> >        // non-existing files with different casing are equal
> >        // e.g. NTFS
> >        CaseInsensitiveMissingAsTrue,
> >        // non-existing files with different casing are non-equal
> >        // e.g. HFS
> >        CaseInsensitiveMissingAsFalse
> >    };
> >
> >    private static final FileSystemType FILE_SYSTEM_TYPE =
> > FileSystemType.CaseSensitive;
> >
> >    private boolean isCaseSensitive() {
> >        return FILE_SYSTEM_TYPE == FileSystemType.CaseSensitive;
> >    }
> >
> >    private boolean isCaseInsensitive() {
> >        return FILE_SYSTEM_TYPE != FileSystemType.CaseSensitive;
> >    }
> >
> >    @Override
> >    protected void setUp() throws Exception {
> >        System.out.println("File system type: " + FILE_SYSTEM_TYPE);
> >        super.setUp();
> >    }
> >
> >    public void testSimple() throws IOException {
> >        File f1 = new File("foo");
> >        assertTrue(f1.createNewFile());
> >        File f2 = new File("foo");
> >
> >        assertTrue(equals(f1, f2));
> >    }
> >
> >    public void testNonExistingButSimple() {
> >        File f1 = new File("foo");
> >        File f2 = new File("foo");
> >
> >        assertTrue(equals(f1, f2));
> >    }
> >
> >    public void testDifferentCase() throws IOException {
> >        File f1 = new File("foo");
> >        assertTrue(f1.createNewFile());
> >        File f2 = new File("FOO");
> >
> >        // if this succeeds, we have two different files
> >        assertEquals(isCaseSensitive(), f2.createNewFile());
> >
> >        assertEquals(isCaseInsensitive(), equals(f1, f2));
> >    }
> >
> >    public void testDifferentCaseNonExisting() throws IOException {
> >        File f1 = new File("foo");
> >        File f2 = new File("FOO");
> >
> >        assertEquals(FILE_SYSTEM_TYPE ==
> > FileSystemType.CaseInsensitiveMissingAsTrue, equals(f1, f2));
> >    }
> >
> >    public void testSameNameDifferentParent() throws IOException {
> >        File f1 = new File("foo");
> >        assertTrue(f1.createNewFile());
> >        File dir2 = new File("dir");
> >        assertTrue(dir2.mkdir());
> >        File f2 = new File(dir2, "foo");
> >        assertTrue(f2.createNewFile());
> >
> >        assertFalse(equals(f1, f2));
> >    }
> >
> >    public boolean equals(final File f1, final File f2) {
> >        if (f1 == null || f2 == null) {
> >            return false;
> >        }
> >
> >        if (f1.equals(f2)) {
> >            // file equals, valid on all file systems
> >            return true;
> >        } else {
> >            boolean f1Exists = f1.exists();
> >            boolean f2Exists = f2.exists();
> >
> >            if (f1.getName().equalsIgnoreCase(f2.getName())) {
> >                // same name, do both exist?
> >                if (f1Exists && f2Exists) {
> >                    // both files exists, do they have the same parent?
> >
> >                    // TODO should we use canonical or absolute path?
> >                    File f1Parent = f1.getAbsoluteFile().getParentFile();
> >                    File f2Parent = f2.getAbsoluteFile().getParentFile();
> >
> >                    if (f1Parent != null && f2Parent != null) {
> >                        if (equals(f1Parent, f2Parent)) {
> >                            // okay, if we got here, the parents are the
> same,
> >                            // the file names are the same and both files
> exists
> >                            // let's check if there are multiple files
> > or only one in the parent
> >                            // with that name
> >
> >
> >                            // choosing either parent should be fine,
> > they are equal
> >                            String[] files = f1Parent
> >                                    .list(new FilenameFilter() {
> >                                        public boolean accept(File
> > dir, String name) {
> >                                            return
> name.equalsIgnoreCase(f1
> >                                                    .getName());
> >                                        }
> >                                    });
> >
> >                            if (files.length == 1) {
> >                                // exactly one file matched the name,
> > the files must be equal
> >                                return true;
> >                            } else if (files.length > 1) {
> >                                return false;
> >                            } else {
> >                                // no file matching, must be a bug
> somewhere
> >                                throw new RuntimeException("Should not
> happen");
> >                            }
> >                        } else {
> >                            // different parents, return false
> >                            return false;
> >                        }
> >                    } else if (f1Parent == null && f2Parent == null) {
> >                        // no parents, we can do nothing more and thus
> > have to return false
> >                        return false;
> >                    } else {
> >                        // different parents
> >                        return false;
> >                    }
> >                } else if (!f1Exists && !f2Exists) {
> >                    // none of the file exists, we can only trust the
> > equals result (which by now must be false)
> >                    return false;
> >                } else {
> >                    // only one of the files exists, return false
> >                    return false;
> >                }
> >            } else {
> >                // file names not equal
> >                return false;
> >            }
> >        }
> >    }
> >
> >    @Override
> >    protected void tearDown() throws Exception {
> >        new File("foo").delete();
> >        new File("FOO").delete();
> >        new File("dir/foo").delete();
> >        new File("dir").delete();
> >    }
> >
> > }
> >
>
>
>
> --
> Regards,
> Cordialement,
> Emmanuel Lécharny
> www.iktek.com
>

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Emmanuel Lecharny <el...@apache.org>.
Works fine on my Mac OS X 10.4/Java 5

On Wed, Mar 4, 2009 at 11:13 PM, Niklas Gustavsson <ni...@protocol7.com> wrote:
> On Mon, Mar 2, 2009 at 4:54 PM, Niklas Gustavsson <ni...@protocol7.com> wrote:
>> Let me whip up a prototype and we can test it on the available platforms.
>
> Alright, here's a prototype that I would much appreciate if all of you
> would take the time to test. First of all, you need to set the
> FILE_SYSTEM_TYPE to the correct value (this is only used for
> verification in the tests). On case sensitive file systems (most of
> the *nix file systems), this should be set to
> FileSystemType.CaseSensitive. On NTFS it should be set to
> CaseInsensitiveMissingAsTrue, and on case-insensitive HFS to
> CaseInsensitiveMissingAsFalse. It would be very interesting to have
> this code tested on other file systems. If you do, please report the
> file system and the test results.
>
> /niklas
>
> package org.apache.ftpserver.filesystem.nativefs.impl;
>
> import java.io.File;
> import java.io.FilenameFilter;
> import java.io.IOException;
>
> import junit.framework.TestCase;
>
> public class FileEqualsTest extends TestCase {
>
>    private enum FileSystemType {
>        CaseSensitive,
>        // non-existing files with different casing are equal
>        // e.g. NTFS
>        CaseInsensitiveMissingAsTrue,
>        // non-existing files with different casing are non-equal
>        // e.g. HFS
>        CaseInsensitiveMissingAsFalse
>    };
>
>    private static final FileSystemType FILE_SYSTEM_TYPE =
> FileSystemType.CaseSensitive;
>
>    private boolean isCaseSensitive() {
>        return FILE_SYSTEM_TYPE == FileSystemType.CaseSensitive;
>    }
>
>    private boolean isCaseInsensitive() {
>        return FILE_SYSTEM_TYPE != FileSystemType.CaseSensitive;
>    }
>
>    @Override
>    protected void setUp() throws Exception {
>        System.out.println("File system type: " + FILE_SYSTEM_TYPE);
>        super.setUp();
>    }
>
>    public void testSimple() throws IOException {
>        File f1 = new File("foo");
>        assertTrue(f1.createNewFile());
>        File f2 = new File("foo");
>
>        assertTrue(equals(f1, f2));
>    }
>
>    public void testNonExistingButSimple() {
>        File f1 = new File("foo");
>        File f2 = new File("foo");
>
>        assertTrue(equals(f1, f2));
>    }
>
>    public void testDifferentCase() throws IOException {
>        File f1 = new File("foo");
>        assertTrue(f1.createNewFile());
>        File f2 = new File("FOO");
>
>        // if this succeeds, we have two different files
>        assertEquals(isCaseSensitive(), f2.createNewFile());
>
>        assertEquals(isCaseInsensitive(), equals(f1, f2));
>    }
>
>    public void testDifferentCaseNonExisting() throws IOException {
>        File f1 = new File("foo");
>        File f2 = new File("FOO");
>
>        assertEquals(FILE_SYSTEM_TYPE ==
> FileSystemType.CaseInsensitiveMissingAsTrue, equals(f1, f2));
>    }
>
>    public void testSameNameDifferentParent() throws IOException {
>        File f1 = new File("foo");
>        assertTrue(f1.createNewFile());
>        File dir2 = new File("dir");
>        assertTrue(dir2.mkdir());
>        File f2 = new File(dir2, "foo");
>        assertTrue(f2.createNewFile());
>
>        assertFalse(equals(f1, f2));
>    }
>
>    public boolean equals(final File f1, final File f2) {
>        if (f1 == null || f2 == null) {
>            return false;
>        }
>
>        if (f1.equals(f2)) {
>            // file equals, valid on all file systems
>            return true;
>        } else {
>            boolean f1Exists = f1.exists();
>            boolean f2Exists = f2.exists();
>
>            if (f1.getName().equalsIgnoreCase(f2.getName())) {
>                // same name, do both exist?
>                if (f1Exists && f2Exists) {
>                    // both files exists, do they have the same parent?
>
>                    // TODO should we use canonical or absolute path?
>                    File f1Parent = f1.getAbsoluteFile().getParentFile();
>                    File f2Parent = f2.getAbsoluteFile().getParentFile();
>
>                    if (f1Parent != null && f2Parent != null) {
>                        if (equals(f1Parent, f2Parent)) {
>                            // okay, if we got here, the parents are the same,
>                            // the file names are the same and both files exists
>                            // let's check if there are multiple files
> or only one in the parent
>                            // with that name
>
>
>                            // choosing either parent should be fine,
> they are equal
>                            String[] files = f1Parent
>                                    .list(new FilenameFilter() {
>                                        public boolean accept(File
> dir, String name) {
>                                            return name.equalsIgnoreCase(f1
>                                                    .getName());
>                                        }
>                                    });
>
>                            if (files.length == 1) {
>                                // exactly one file matched the name,
> the files must be equal
>                                return true;
>                            } else if (files.length > 1) {
>                                return false;
>                            } else {
>                                // no file matching, must be a bug somewhere
>                                throw new RuntimeException("Should not happen");
>                            }
>                        } else {
>                            // different parents, return false
>                            return false;
>                        }
>                    } else if (f1Parent == null && f2Parent == null) {
>                        // no parents, we can do nothing more and thus
> have to return false
>                        return false;
>                    } else {
>                        // different parents
>                        return false;
>                    }
>                } else if (!f1Exists && !f2Exists) {
>                    // none of the file exists, we can only trust the
> equals result (which by now must be false)
>                    return false;
>                } else {
>                    // only one of the files exists, return false
>                    return false;
>                }
>            } else {
>                // file names not equal
>                return false;
>            }
>        }
>    }
>
>    @Override
>    protected void tearDown() throws Exception {
>        new File("foo").delete();
>        new File("FOO").delete();
>        new File("dir/foo").delete();
>        new File("dir").delete();
>    }
>
> }
>



-- 
Regards,
Cordialement,
Emmanuel Lécharny
www.iktek.com

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Mon, Mar 2, 2009 at 4:54 PM, Niklas Gustavsson <ni...@protocol7.com> wrote:
> Let me whip up a prototype and we can test it on the available platforms.

Alright, here's a prototype that I would much appreciate if all of you
would take the time to test. First of all, you need to set the
FILE_SYSTEM_TYPE to the correct value (this is only used for
verification in the tests). On case sensitive file systems (most of
the *nix file systems), this should be set to
FileSystemType.CaseSensitive. On NTFS it should be set to
CaseInsensitiveMissingAsTrue, and on case-insensitive HFS to
CaseInsensitiveMissingAsFalse. It would be very interesting to have
this code tested on other file systems. If you do, please report the
file system and the test results.

/niklas

package org.apache.ftpserver.filesystem.nativefs.impl;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;

import junit.framework.TestCase;

public class FileEqualsTest extends TestCase {

    private enum FileSystemType {
        CaseSensitive,
        // non-existing files with different casing are equal
        // e.g. NTFS
        CaseInsensitiveMissingAsTrue,
        // non-existing files with different casing are non-equal
        // e.g. HFS
        CaseInsensitiveMissingAsFalse
    };

    private static final FileSystemType FILE_SYSTEM_TYPE =
FileSystemType.CaseSensitive;

    private boolean isCaseSensitive() {
        return FILE_SYSTEM_TYPE == FileSystemType.CaseSensitive;
    }

    private boolean isCaseInsensitive() {
        return FILE_SYSTEM_TYPE != FileSystemType.CaseSensitive;
    }

    @Override
    protected void setUp() throws Exception {
        System.out.println("File system type: " + FILE_SYSTEM_TYPE);
        super.setUp();
    }

    public void testSimple() throws IOException {
        File f1 = new File("foo");
        assertTrue(f1.createNewFile());
        File f2 = new File("foo");

        assertTrue(equals(f1, f2));
    }

    public void testNonExistingButSimple() {
        File f1 = new File("foo");
        File f2 = new File("foo");

        assertTrue(equals(f1, f2));
    }

    public void testDifferentCase() throws IOException {
        File f1 = new File("foo");
        assertTrue(f1.createNewFile());
        File f2 = new File("FOO");

        // if this succeeds, we have two different files
        assertEquals(isCaseSensitive(), f2.createNewFile());

        assertEquals(isCaseInsensitive(), equals(f1, f2));
    }

    public void testDifferentCaseNonExisting() throws IOException {
        File f1 = new File("foo");
        File f2 = new File("FOO");

        assertEquals(FILE_SYSTEM_TYPE ==
FileSystemType.CaseInsensitiveMissingAsTrue, equals(f1, f2));
    }

    public void testSameNameDifferentParent() throws IOException {
        File f1 = new File("foo");
        assertTrue(f1.createNewFile());
        File dir2 = new File("dir");
        assertTrue(dir2.mkdir());
        File f2 = new File(dir2, "foo");
        assertTrue(f2.createNewFile());

        assertFalse(equals(f1, f2));
    }

    public boolean equals(final File f1, final File f2) {
        if (f1 == null || f2 == null) {
            return false;
        }

        if (f1.equals(f2)) {
            // file equals, valid on all file systems
            return true;
        } else {
            boolean f1Exists = f1.exists();
            boolean f2Exists = f2.exists();

            if (f1.getName().equalsIgnoreCase(f2.getName())) {
                // same name, do both exist?
                if (f1Exists && f2Exists) {
                    // both files exists, do they have the same parent?

                    // TODO should we use canonical or absolute path?
                    File f1Parent = f1.getAbsoluteFile().getParentFile();
                    File f2Parent = f2.getAbsoluteFile().getParentFile();

                    if (f1Parent != null && f2Parent != null) {
                        if (equals(f1Parent, f2Parent)) {
                            // okay, if we got here, the parents are the same,
                            // the file names are the same and both files exists
                            // let's check if there are multiple files
or only one in the parent
                            // with that name


                            // choosing either parent should be fine,
they are equal
                            String[] files = f1Parent
                                    .list(new FilenameFilter() {
                                        public boolean accept(File
dir, String name) {
                                            return name.equalsIgnoreCase(f1
                                                    .getName());
                                        }
                                    });

                            if (files.length == 1) {
                                // exactly one file matched the name,
the files must be equal
                                return true;
                            } else if (files.length > 1) {
                                return false;
                            } else {
                                // no file matching, must be a bug somewhere
                                throw new RuntimeException("Should not happen");
                            }
                        } else {
                            // different parents, return false
                            return false;
                        }
                    } else if (f1Parent == null && f2Parent == null) {
                        // no parents, we can do nothing more and thus
have to return false
                        return false;
                    } else {
                        // different parents
                        return false;
                    }
                } else if (!f1Exists && !f2Exists) {
                    // none of the file exists, we can only trust the
equals result (which by now must be false)
                    return false;
                } else {
                    // only one of the files exists, return false
                    return false;
                }
            } else {
                // file names not equal
                return false;
            }
        }
    }

    @Override
    protected void tearDown() throws Exception {
        new File("foo").delete();
        new File("FOO").delete();
        new File("dir/foo").delete();
        new File("dir").delete();
    }

}

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Mon, Mar 2, 2009 at 8:02 PM, Maarten Bosteels
<mb...@gmail.com> wrote:
> Would it be a viable option to let users of FtpServer define which
> mount-points use a case-insensitive file-system ?
> I mean an out-of-the-box FtpServer config that works for 95% of the
> user-base and the other 5% would have to do some extra configuration.

Yes, I think that would be the fallback if we fail to find a good
enough code for doing this.

/niklas

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Maarten Bosteels <mb...@gmail.com>.
Would it be a viable option to let users of FtpServer define which
mount-points use a case-insensitive file-system ?
I mean an out-of-the-box FtpServer config that works for 95% of the
user-base and the other 5% would have to do some extra configuration.

Maarten


On Mon, Mar 2, 2009 at 6:12 PM, Niklas Gustavsson <ni...@protocol7.com>wrote:

> On Mon, Mar 2, 2009 at 6:01 PM, Sai Pullabhotla
> <sa...@jmethods.com> wrote:
> > Does this help at all?
> >
> > http://lists.apple.com/archives/java-dev/2004/Feb/msg00331.html
>
> I've posted this previously in this thread, however they do not seem
> to reach any conclusion beyond this being more complex that you might
> think :-)
>
> /niklas
>

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Mon, Mar 2, 2009 at 6:01 PM, Sai Pullabhotla
<sa...@jmethods.com> wrote:
> Does this help at all?
>
> http://lists.apple.com/archives/java-dev/2004/Feb/msg00331.html

I've posted this previously in this thread, however they do not seem
to reach any conclusion beyond this being more complex that you might
think :-)

/niklas

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Sai Pullabhotla <sa...@jmethods.com>.
Does this help at all?

http://lists.apple.com/archives/java-dev/2004/Feb/msg00331.html

Sai Pullabhotla
Phone: (402) 408-5753
Fax: (402) 408-6861
www.jMethods.com



On Mon, Mar 2, 2009 at 9:54 AM, Niklas Gustavsson <ni...@protocol7.com>wrote:

> On Mon, Mar 2, 2009 at 1:17 PM, Emmanuel Lecharny <el...@apache.org>
> wrote:
> > It may be just a matter of checking that the file can be deleted, then
> check
> > that the working directory still exists after having done the deletion.
> If
> > so, we are golden, otherwise, we have to recreate it, and send an error.
>
> Recreating it will cause several side effects (might change ownership,
> permissions, inode).
>
> > In case the working directory is not empty, the deletion will fail
> anyway.
> >
> > if we don't want to delete the working directory for some reason, we can
> > rename it.
>
> Not convinced this is a very good anyways. As mentioned previously,
> FTP server file systems are commonly monitored for file changes,
> concurrent users might access the same directory and so on. I would
> prefer that we either do or do not do an action, rather than doing it
> in several steps.
>
> Let me whip up a prototype and we can test it on the available platforms.
>
> /niklas
>

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Mon, Mar 2, 2009 at 1:17 PM, Emmanuel Lecharny <el...@apache.org> wrote:
> It may be just a matter of checking that the file can be deleted, then check
> that the working directory still exists after having done the deletion. If
> so, we are golden, otherwise, we have to recreate it, and send an error.

Recreating it will cause several side effects (might change ownership,
permissions, inode).

> In case the working directory is not empty, the deletion will fail anyway.
>
> if we don't want to delete the working directory for some reason, we can
> rename it.

Not convinced this is a very good anyways. As mentioned previously,
FTP server file systems are commonly monitored for file changes,
concurrent users might access the same directory and so on. I would
prefer that we either do or do not do an action, rather than doing it
in several steps.

Let me whip up a prototype and we can test it on the available platforms.

/niklas

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Emmanuel Lecharny <el...@apache.org>.
What about taking the problem from the other side ?

The test fails because :
- we are trying to delete the current working directory
- doing a
FtpFile cwd = session.getFileSystemView().getWorkingDirectory();
        if(file.equals(cwd)) {
does not work on Mac OS X and Java 6 because the file handler are 
considered as different, just because their name are not the same
- but the deletion works because behind the curtain, Mac OS X can delete 
the file, without taking care of the case sentivity.

It may be just a matter of checking that the file can be deleted, then 
check that the working directory still exists after having done the 
deletion. If so, we are golden, otherwise, we have to recreate it, and 
send an error.

In case the working directory is not empty, the deletion will fail anyway.

if we don't want to delete the working directory for some reason, we can 
rename it.

That should do the trick, IMO.

-- 
--
cordialement, regards,
Emmanuel Lécharny
www.iktek.com
directory.apache.org



Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Ashish <pa...@gmail.com>.
On Mon, Mar 2, 2009 at 4:34 PM, Niklas Gustavsson <ni...@protocol7.com> wrote:
> On Mon, Mar 2, 2009 at 11:52 AM, Ashish <pa...@gmail.com> wrote:
>> Can't we create the name like File file = new
>> File("FiLe"+System.currentTimeMillis());
>> check if it exists. Chance are very rare that it will.
>>
>> If it exist recreate a new file name.
>> If it doesn't exist, we call file.createNewFile(); and do the case
>> sensitive stuff.
>
> Problem is, we might be running on a read-only file system. Or, as
> common with FTP servers, file systems that is being monitored by other
> applications (over FTP or locally).

Can't we ship two weirdly name files with our distribution and test
for equality on them :-)
Or how about providing a default behavior(like we discussed) and
provide a hook for customizing the same.


>>> Would that work? Step 4 would mean taking a performance penalty if
>>> there are lots of files in the parent directory, but it should not be
>>> a very common case.
>>
>> I hope, we would be doing this once, to establish if File System is
>> case sensitive or not.
>> So performance shouldn't really be a big cause.
>
> Problem is, we don't know where file systems (as in the *nix sense)
> change as you can mount or link file systems together where ever. So,
> we pretty much have to do this on every equals... currently we don't
> use equals so much so it would probably be okay, but the Javadoc must
> come with a huge warning post if we decide to go with any of these
> ideas for checking file equivalence.

Yeah I got it :) May be I should take a break

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Ashish <pa...@gmail.com>.
>
> File f1 = new File( "test" );
> File f2 = new File( "TEST" );
>
> if ( !f1.equals( f2 ) ) {
>   if ( f1.createNewFile() != f2.createNewFile() ) {
>     // Case insensitive but name preserving
>   } else {
>     // case sensitive
>   }
> } else {
>  // case insensitive
> }
>
> Maybe someone else has a better idea ?

A good generic solution.

Was wondering, could there be a Use Case where FtpServer is being
purely used for Read-Only purpose (running from an account with RX
permission) and may not have write permission. (Assuming logging is
disabled or to a common folder).

Is OS name not sufficient for this? Agree that it leads to hard-coding.

- ashish

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Mon, Mar 2, 2009 at 11:52 AM, Ashish <pa...@gmail.com> wrote:
> Can't we create the name like File file = new
> File("FiLe"+System.currentTimeMillis());
> check if it exists. Chance are very rare that it will.
>
> If it exist recreate a new file name.
> If it doesn't exist, we call file.createNewFile(); and do the case
> sensitive stuff.

Problem is, we might be running on a read-only file system. Or, as
common with FTP servers, file systems that is being monitored by other
applications (over FTP or locally).

>> Would that work? Step 4 would mean taking a performance penalty if
>> there are lots of files in the parent directory, but it should not be
>> a very common case.
>
> I hope, we would be doing this once, to establish if File System is
> case sensitive or not.
> So performance shouldn't really be a big cause.

Problem is, we don't know where file systems (as in the *nix sense)
change as you can mount or link file systems together where ever. So,
we pretty much have to do this on every equals... currently we don't
use equals so much so it would probably be okay, but the Javadoc must
come with a huge warning post if we decide to go with any of these
ideas for checking file equivalence.

/niklas

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Ashish <pa...@gmail.com>.
On Mon, Mar 2, 2009 at 4:00 PM, Niklas Gustavsson <ni...@protocol7.com> wrote:
> On Mon, Mar 2, 2009 at 11:01 AM, Emmanuel Lecharny <el...@apache.org> wrote:
>> Nah, i'm wrong. I'm confusing the two issues : the socket error and the case
>> sensitive directory error.
>
> Damn. Okay, think out loud, could we do an equals implementation that:
>
> 1. Check if equals return true, if so, return true
> 2. Else, check if File.getName() is equal ignoring case. If not,
> return false (this is just an optimization to skip the remaining steps
> for most cases)
> 3. Check if File.exists() returns true for both casings
> 4. Do a file listing on the parent, if we get exactly one match on the
> file name (case insensitive matching), we return true
> 5. Else return false

Can't we create the name like File file = new
File("FiLe"+System.currentTimeMillis());
check if it exists. Chance are very rare that it will.

If it exist recreate a new file name.
If it doesn't exist, we call file.createNewFile(); and do the case
sensitive stuff.

I doubt it has made life simple :-(

>
> Would that work? Step 4 would mean taking a performance penalty if
> there are lots of files in the parent directory, but it should not be
> a very common case.

I hope, we would be doing this once, to establish if File System is
case sensitive or not.
So performance shouldn't really be a big cause.

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Mon, Mar 2, 2009 at 11:19 AM, Maarten Bosteels
<mb...@gmail.com> wrote:
> But even when it's not fixed in java 6...
> When it's a JVM bug on OS X, and there is no clean work-around, then IMO we
> shouldn't jumpt through too many hoops trying to solve it.

I'm not sure we can really claim this to be a bug in the JVM (even
though I think it is). I had hoped that Apple would have acknowledge
the limitation as a and fixed it, but I guess not.

/niklas

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Mon, Mar 2, 2009 at 11:01 AM, Emmanuel Lecharny <el...@apache.org> wrote:
> Nah, i'm wrong. I'm confusing the two issues : the socket error and the case
> sensitive directory error.

Damn. Okay, think out loud, could we do an equals implementation that:

1. Check if equals return true, if so, return true
2. Else, check if File.getName() is equal ignoring case. If not,
return false (this is just an optimization to skip the remaining steps
for most cases)
3. Check if File.exists() returns true for both casings
4. Do a file listing on the parent, if we get exactly one match on the
file name (case insensitive matching), we return true
5. Else return false

Would that work? Step 4 would mean taking a performance penalty if
there are lots of files in the parent directory, but it should not be
a very common case.

/niklas

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Maarten Bosteels <mb...@gmail.com>.
But even when it's not fixed in java 6...
When it's a JVM bug on OS X, and there is no clean work-around, then IMO we
shouldn't jumpt through too many hoops trying to solve it.

Maarten

On Mon, Mar 2, 2009 at 11:01 AM, Emmanuel Lecharny <el...@apache.org>wrote:

> Niklas Gustavsson wrote:
>
>> On Sun, Mar 1, 2009 at 11:06 PM, Emmanuel Lecharny <el...@apache.org>
>> wrote:
>>
>>
>>>  I'm not
>>>> really happy with this but I can't figure out a better way, besides
>>>> someone fixing the JVM.
>>>>
>>>>
>>> Btw, it's fixed in Java 6 on Mac OSX, AFAICT. The biggest issue is that
>>> you
>>> can't run this JVM on OS X 10.4.
>>>
>>>
>>
>> Really? If so, I'll be happy to declare this a known issue with Java
>> 1.5 on OS X (like the problem we had with NIO) and closing it from out
>> point of view.
>>
>>
> Nah, i'm wrong. I'm confusing the two issues : the socket error and the
> case sensitive directory error.
>
> The first one is fixed on Java 6, but not the second one...
>
>
> --
> --
> cordialement, regards,
> Emmanuel Lécharny
> www.iktek.com
> directory.apache.org
>
>
>

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Emmanuel Lecharny <el...@apache.org>.
Niklas Gustavsson wrote:
> On Sun, Mar 1, 2009 at 11:06 PM, Emmanuel Lecharny <el...@apache.org> wrote:
>   
>>>  I'm not
>>> really happy with this but I can't figure out a better way, besides
>>> someone fixing the JVM.
>>>       
>> Btw, it's fixed in Java 6 on Mac OSX, AFAICT. The biggest issue is that you
>> can't run this JVM on OS X 10.4.
>>     
>
> Really? If so, I'll be happy to declare this a known issue with Java
> 1.5 on OS X (like the problem we had with NIO) and closing it from out
> point of view.
>   
Nah, i'm wrong. I'm confusing the two issues : the socket error and the 
case sensitive directory error.

The first one is fixed on Java 6, but not the second one...

-- 
--
cordialement, regards,
Emmanuel Lécharny
www.iktek.com
directory.apache.org



Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Sun, Mar 1, 2009 at 11:06 PM, Emmanuel Lecharny <el...@apache.org> wrote:
>>  I'm not
>> really happy with this but I can't figure out a better way, besides
>> someone fixing the JVM.
>
> Btw, it's fixed in Java 6 on Mac OSX, AFAICT. The biggest issue is that you
> can't run this JVM on OS X 10.4.

Really? If so, I'll be happy to declare this a known issue with Java
1.5 on OS X (like the problem we had with NIO) and closing it from out
point of view.

/niklas

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Emmanuel Lecharny <el...@apache.org>.
Niklas Gustavsson wrote:
> On Fri, Feb 27, 2009 at 1:36 PM, Emmanuel Lecharny <el...@apache.org> wrote:
>   
>>> Given a file name which might not be in the correct casing, is there a
>>> way to detect the "real" casing in HSF+? For example, what would the
>>> following return?
>>> new File("FOO").getName()
>>> new File("FOO").getAbsolutePath()
>>> new File("FOO").getCanonicalPath()
>>> new File("FOO").getPath()
>>>
>>>       
>> The name is kept. You will have FOO for all those guys.
>>     
>
> Sucks. This is true also if "foo" exists right?
>   
yep.
>> Now, to detect if the underlying FS is case insensitive, I found that doing
>> something like :
>>
>> File f1 = new File( "test" );
>> File f2 = new File( "TEST" );
>>
>> if ( !f1.equals( f2 ) ) {
>>   if ( f1.createNewFile() != f2.createNewFile() ) {
>>     // Case insensitive but name preserving
>>   } else {
>>     // case sensitive
>>   }
>> } else {
>>  // case insensitive
>> }
>>     
>
> Since different directories might come from different file systems,
> with different case handling, we would have to do this for each call
> to equals (and potentially other methods where this matters). And, as
> Ashish points out, we might be in a read-only directory.
Yeah, that would suck...
>  I'm not
> really happy with this but I can't figure out a better way, besides
> someone fixing the JVM.
Btw, it's fixed in Java 6 on Mac OSX, AFAICT. The biggest issue is that 
you can't run this JVM on OS X 10.4.

Mac is not as cool as it seems to be. Not only their keybord and mouse 
sucks, but their Java policy stinks like a dead fish... IMHO, of course :)

-- 
--
cordialement, regards,
Emmanuel Lécharny
www.iktek.com
directory.apache.org



Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Fri, Feb 27, 2009 at 1:36 PM, Emmanuel Lecharny <el...@apache.org> wrote:
>> Given a file name which might not be in the correct casing, is there a
>> way to detect the "real" casing in HSF+? For example, what would the
>> following return?
>> new File("FOO").getName()
>> new File("FOO").getAbsolutePath()
>> new File("FOO").getCanonicalPath()
>> new File("FOO").getPath()
>>
>
> The name is kept. You will have FOO for all those guys.

Sucks. This is true also if "foo" exists right?

> Now, to detect if the underlying FS is case insensitive, I found that doing
> something like :
>
> File f1 = new File( "test" );
> File f2 = new File( "TEST" );
>
> if ( !f1.equals( f2 ) ) {
>   if ( f1.createNewFile() != f2.createNewFile() ) {
>     // Case insensitive but name preserving
>   } else {
>     // case sensitive
>   }
> } else {
>  // case insensitive
> }

Since different directories might come from different file systems,
with different case handling, we would have to do this for each call
to equals (and potentially other methods where this matters). And, as
Ashish points out, we might be in a read-only directory. I'm not
really happy with this but I can't figure out a better way, besides
someone fixing the JVM. Not that that is very likely of course. There
is an interesting discussion on this topic over here
http://lists.apple.com/archives/java-dev/2004/Feb/msg00331.html but it
merely makes to whole thing more complex, rather than find any
solutions. They also refers to a bug reported to Apple, but I always
fail to access their bug management tool so I haven't checked it out.

/niklas

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Emmanuel Lecharny <el...@apache.org>.
Niklas Gustavsson wrote:
> On Fri, Feb 27, 2009 at 12:04 PM, Emmanuel Lecharny
> <el...@apache.org> wrote:
>   
>> Files are considered as different.
>>     
>
> This makes our task somewhat harder :-) So, on OS X, if we got a
> directory (or file I assume) called "foo", the following will be
> correct, right?
>
> new File("foo").equals(new File("FOO")) => false
>   
Correct
> new File("FOO").delete() => true
>   
correct
> Given a file name which might not be in the correct casing, is there a
> way to detect the "real" casing in HSF+? For example, what would the
> following return?
> new File("FOO").getName()
> new File("FOO").getAbsolutePath()
> new File("FOO").getCanonicalPath()
> new File("FOO").getPath()
>   
The name is kept. You will have FOO for all those guys.

Now, to detect if the underlying FS is case insensitive, I found that 
doing something like :

File f1 = new File( "test" );
File f2 = new File( "TEST" );

if ( !f1.equals( f2 ) ) {
    if ( f1.createNewFile() != f2.createNewFile() ) {
      // Case insensitive but name preserving
    } else {
      // case sensitive
    }
} else {
  // case insensitive
}

Maybe someone else has a better idea ?

-- 
--
cordialement, regards,
Emmanuel Lécharny
www.iktek.com
directory.apache.org



Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Fri, Feb 27, 2009 at 12:04 PM, Emmanuel Lecharny
<el...@apache.org> wrote:
> Files are considered as different.

This makes our task somewhat harder :-) So, on OS X, if we got a
directory (or file I assume) called "foo", the following will be
correct, right?

new File("foo").equals(new File("FOO")) => false
new File("FOO").delete() => true

Given a file name which might not be in the correct casing, is there a
way to detect the "real" casing in HSF+? For example, what would the
following return?
new File("FOO").getName()
new File("FOO").getAbsolutePath()
new File("FOO").getCanonicalPath()
new File("FOO").getPath()

/niklas

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Emmanuel Lecharny <el...@apache.org>.
Niklas Gustavsson wrote:
> On Fri, Feb 27, 2009 at 11:36 AM, Emmanuel Lecharny
> <el...@apache.org> wrote:
>   
>> Ok, we have run the tests again and the problem is that using HSF+ file
>> system on Mac, the RMD command in the testRmdirCurrentWorkingDirectory test
>> simply succeed, because HSF+ can be set to be case-insensitive.
>>     
>
> That's bad, because FtpServer should never allow deleting the current
> working directory. Would you be able to see what happens in
> org.apache.ftpserver.command.impl.RMD line 97 and in
> org.apache.ftpserver.filesystem.nativefs.impl.NativeFtpFile.equals(Object)
> when this command is sent?
Files are considered as different.



-- 
--
cordialement, regards,
Emmanuel Lécharny
www.iktek.com
directory.apache.org



Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Niklas Gustavsson <ni...@protocol7.com>.
On Fri, Feb 27, 2009 at 11:36 AM, Emmanuel Lecharny
<el...@apache.org> wrote:
> Ok, we have run the tests again and the problem is that using HSF+ file
> system on Mac, the RMD command in the testRmdirCurrentWorkingDirectory test
> simply succeed, because HSF+ can be set to be case-insensitive.

That's bad, because FtpServer should never allow deleting the current
working directory. Would you be able to see what happens in
org.apache.ftpserver.command.impl.RMD line 97 and in
org.apache.ftpserver.filesystem.nativefs.impl.NativeFtpFile.equals(Object)
when this command is sent? What should happen is that the equals
method should return true as the java.io.Files that gets compared
should evaluate to the same file.

> I guess that the FtpServer check the underlying file-system during
> initialization, and if it's a linux based one, it considers the FS as case
> sensitive.

No, at least we're not that stupid ;-)

/niklas

Re: [FtpServer] Suspend problem on OSX (was Re: [VOTE] Releasing FtpServer 1.0.0)

Posted by Emmanuel Lecharny <el...@apache.org>.
Julien Vermillard wrote:
>>> Would you be able to send me the debug level log for this failing
>>> test? 
>>>       
>> Will do asap.
>>     

Ok, we have run the tests again and the problem is that using HSF+ file 
system on Mac, the RMD command in the testRmdirCurrentWorkingDirectory 
test simply succeed, because HSF+ can be set to be case-insensitive.

On windows, the test passes.

I guess that the FtpServer check the underlying file-system during 
initialization, and if it's a linux based one, it considers the FS as 
case sensitive.

If this is the case (I didn't read the FtpServer internals), one 
solution would be to check wether the underlying FS is case sensitive or 
not before starting the server.


-- 
--
cordialement, regards,
Emmanuel Lécharny
www.iktek.com
directory.apache.org