JDK-5018710 : FileWriter does not throw IOException for Samba mounted read-only drives
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.io
  • Affected Version: 5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: linux
  • CPU: x86
  • Submitted: 2004-03-23
  • Updated: 2005-11-17
  • Resolved: 2005-11-17
Description
Name: dk106046			Date: 03/23/2004

This occurs on all Java verions.

The program below tries to open a FileWriter object for a file which is mounted on a linux machine using Samba mount. 

//To demonstrate that JVM doesn't throw an IOException for Samba mounted drives on Linux platforms.

import java.io.*;
import java.nio.channels.*;
public class canWrite {
  public static void main(String[] args) {

    if (args.length != 0)
    {
      for (int i=0; i<args.length; i++)
      {
        boolean isWritable = true;
        System.out.println("Testing: "+args[i]);
        File file = new File(args[i]);
        if (file != null && file.exists())
        {
          //canWrite checks for read only
          isWritable = file.canWrite() && file.getAbsoluteFile().getParentFile().canWrite();
          //need to use FileWriter for files on network shares we don't
          //have write access to.
	      isWritable = true;
          if (isWritable)
          {
            FileWriter writer = null;
            try
            {
              System.out.println("Instantiating FileWriter...");
              writer = new FileWriter(file, true); // this should fail

              System.out.println("writing...");
              writer.write("test", 0,4);          // this definitely should fail

              System.out.println("flushing...");
            //writer.flush();                      // this does fail
            }
            catch (IOException fnfe)
            {
              isWritable = false;
              System.out.println("Exception creating or writing FileWriter: "+fnfe);
		fnfe.printStackTrace();
            }catch (Exception eee) {
		eee.printStackTrace();
	    }
 /*
 		   // Uncommenting this piece of code also exhibits an exception while closing.
           if (writer != null)
            {
              try
              {
                writer.close();
              }
              catch (IOException ioe)
              {
                System.out.println("Exception closing...");
		//ioe.printStackTrace();
              }
            }*/
          }
          else
          {
            System.out.println("file.canWrite="+file.canWrite()+", parent.canWrite="+file.getAbsoluteFile().getParentFile().canWrite());
          }
        }
        else
        {
          System.out.println(args[i]+" is null or does not exist.");
        }
        if (isWritable)
        {
          System.out.println("File can be written.");
        }
      }
    }
    else
    {
      System.out.println("Specify at least one file name.");
    }
  }
}

The mounted device is read only and hence ideally we expect an IOException either while creating the FileWriter or while writing into the file. Such an exception is never thrown.

If we uncomment the "flush" or the "close" calls to the FileWriter object an exception is thrown. These IOExceptions are either while closing the FileWriter or while flushing the same. If a programmer doesn't flush or close the file writer object there are no exceptions thrown.

The behavior should be such that an IO exception is thrown while we attempt to write the bytes to this read only file.

Steps to reproduce.

1. On a windows machine share a drive ( say d: as ntDrive ) after making the drive read-only.
2. Mount this drive on a linux machine using Samba. ( Ex : mount -t smbfs -o username=administrator //windowsMac/ntDrive /mnt/temp_win )
3. Compile and execute the canWrite.java as "java canWrite /mnt/temp_win/dev_win.txt. Note that dev_win.txt is read-only file.
4. Even though the file is not writable the output of the program would be "File can be written". This is wrong and an IOException should have been thrown.

Here is a sample output.

[root@lolo fileIO]# /workarea/builds/jdk1.4.2/bin/java canWrite /mnt/temp_win/dev_win.txt
Testing: /mnt/temp_win/dev_win.txt
Instantiating FileWriter...
writing...
flushing...
File can be written.

5. Uncomment the writer.flush() call on line number 34 and re-run the tests. This throws an IOException while flushing the file.

Additional Info:

If the same kind of setup is reversed for windows and linux, i.e., a read only directory from a linux machine is mapped on a windows machine the exception is thrown while creating the FileWriter Object.

======================================================================

Comments
EVALUATION As mentioned in the evaluation, this bug is a samba configuration problem, it's not a bug in the FileWriter. I tried to reproduce this problem. I've a readhat 7.1 running a samba server. I have a directory on a windows XP box that is sharable for read-only access. I mount this directory with smbfs on the linux machine. The directory has a write permission to the user. It's attribute listing is as below: # ls -l /smb-windows/file.txt -rwxr-xr-x 1 root ............ When I run the test program against it I get the following output : Testing: /smb-windows/file.txt Instantiating FileWriter... smb_open: //file.txt access denied, access=0, wish=1 writing... flushing... smb_open: //file.txt access denied, access=0, wish=1 Exception creating or writing FileWriter: java.io.IOException: Permission denied java.io.IOException: Permission denied at java.io.FileOutputStream.writeBytes(Native Method) at java.io.FileOutputStream.write(FileOutputStream.java:260) at sun.nio.cs.StreamEncoder$CharsetSE.writeBytes(StreamEncoder.java:336) at sun.nio.cs.StreamEncoder$CharsetSE.implFlushBuffer(StreamEncoder.java:404) at sun.nio.cs.StreamEncoder$CharsetSE.implFlush(StreamEncoder.java:408) at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:152) at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:213) at CanWrite.main(CanWrite.java:33) I used another samba mounted drive for testing. In this case the samba server is running on a solaris-sparc box. I've read-only directory on this mount, with the permission as below. # ls -l /smb-solaris/file.txt -r-xr-xr-x 1 root ....... When I run the test program of this bug report I get the following output: Testing: /smb-solaris/file.txt Instantiating FileWriter... Exception creating or writing FileWriter: java.io.FileNotFoundException: /smb-solaris/file.txt (Permission denied) java.io.FileNotFoundException: /smb-solaris/file.txt (Permission denied) at java.io.FileOutputStream.openAppend(Native Method) at java.io.FileOutputStream.<init>(FileOutputStream.java:177) at java.io.FileWriter.<init>(FileWriter.java:90) at CanWrite.main(CanWrite.java:27) It's clear that for a samba mounted directory from a sharable windows drive, there is some samba configuration involved that will make the mounted file to appear with correct permissions. From the output of the test program it's clear that the samba configuration underneath is not returning the correct status of the file for writing when the FileWriter creates it in the 'append' mode. However, it does sends the error message to the console. It's only when the bytes are actually going to be written to the file that the error is returned. Also, the method write() does not throw an exception, as it buffers the bytes that get written to the writer. The data actually gets written when the buffer is flushed with a call to flush(). Hence the exception is thrown during flush(). As we see from the above results for a samba mounted directory on linux from a solaris samba directory, the permissions are set the right way and the FileWriter is able to return with the error status right at the time of its creation. The problem is not with the FileWriter as it's doing it's best in passing errors back to the application from the OS. It cannot do anything if the OS itself doesn't return the error status. A Samba configuration for setting the permission of a mounted drive from a windows shared file needs to be investigated. I'm closing this bug as we don't need to fix anything in the FileWriter.
17-11-2005

EVALUATION Could also be a samba or configuration bug. Could be investigated further but not for Tiger. ###@###.### 2004-03-25
25-03-2004