JDK-6395581 : File.listFiles() is unable to read nfs-mounted directory (MacOS X)
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.io
  • Affected Version: 1.4.0,1.4.2_11
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris_8,solaris_10
  • CPU: sparc
  • Submitted: 2006-03-08
  • Updated: 2010-07-29
  • Resolved: 2006-04-01
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other JDK 6
1.4.2_13Fixed 6 b79Fixed
Related Reports
Duplicate :  
Relates :  
Description
java.io.File.listFiles() is unable to read nfs-mounted directory from MacOS X.

1. Testcase
-----------
Here is a short testprogram:
% more Main.java
import java.io.File;

public class Main {

        public static void main(String[] args){
                if(args.length != 1){
                        System.out.println("USAGE: ");
                        System.out.println(" java Main <directory_on_nfs_mount>");
                        System.out.println();
                        System.exit(1);
                }

                String filename = args[0];
                File file = new File(filename);

                if(! file.exists() ){
                        System.out.println("file "+filename+" does not exist.");
                }
                else if ( file.isFile() ){
                        System.out.println("f "+filename);
                }
                else if ( file.isDirectory() ){
                        System.out.println("listing contents of directory "+filename);
                        File[] subfiles = file.listFiles();
                        for( int i=0 ; i<subfiles.length ; i++ ){
                                System.out.print( subfiles[i].isFile() ? "f " : "d " );
                                System.out.println( subfiles[i].getName() );
                        }
                        System.out.println();
                        System.out.println( subfiles.length + " files total");
                }
        }
}

2. nfs-directory
----------------
I used an nfs directory mounted via automounter shared from MacOS 10.4.5 (Darwin 8.5.0):

3. Compile
----------
% /j2sdk1.4.2_11/bin/java -version
java version "1.4.2_11"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_11-b02)
Java HotSpot(TM) Client VM (build 1.4.2_11-b02, mixed mode)
% /j2sdk1.4.2_11/bin/javac Main.java
% 

4. Run
------
 I blanked the ip_adress using "<ip_addr>" in the output below.

% /j2sdk1.4.2_11/bin/java -version
java version "1.4.2_11"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_11-b02)
Java HotSpot(TM) Client VM (build 1.4.2_11-b02, mixed mode)
% /j2sdk1.4.2_11/bin/java Main /net/<ip_addr>
listing contents of directory /net/<ip_addr>
d Users

1 files total
% 
 That's fine...

% /j2sdk1.4.2_11/bin/java Main /net/<ip_addr>/Users
listing contents of directory /net/<ip_addr>/Users
d thomas

1 files total
% 
 That's fine...

% /j2sdk1.4.2_11/bin/java Main /net/<ip_addr>/Users/thomas
listing contents of directory /net/<ip_addr>/Users/thomas
d Public

1 files total
% 
 That's fine...

% /j2sdk1.4.2_11/bin/java Main /net/<ip_addr>/Users/thomas/Public
listing contents of directory /net/<ip_addr>/Users/thomas/Public

0 files total
% 
 That's wrong ....

% ls -l /net/<ip_addr>/Users/thomas/Public
total 16
drwx-wx-wx   3 thomas  990          102 Nov 30 13:18 Drop Box
-rwxrwxrwx   1 thomas  990           18 Mar  8 13:35 Hallo_Thomas.txt
%


% df -k /net/<ip_addr>/
Filesystem            kbytes    used   avail capacity  Mounted on
-hosts                     0       0       0     0%    /net
% df -k /net/<ip_addr>/Users/
Filesystem            kbytes    used   avail capacity  Mounted on
-hosts                     0       0       0     0%    /net/<ip_addr>/Users
% df -k /net/<ip_addr>/Users/thomas/
Filesystem            kbytes    used   avail capacity  Mounted on
-hosts                     0       0       0     0%    /net/<ip_addr>/Users/thomas
% df -k /net/<ip_addr>/Users/thomas/Public
Filesystem            kbytes    used   avail capacity  Mounted on
<ip_addr>:/Users/thomas/Public
                     58474008 31462436 26755572    55%    /net/<ip_addr>/Users/thomas/Public
%

Comments
EVALUATION Update implementation to readdir64_r(). Use reentrant version of readdir64 to take care of 4621211
21-03-2006

SUGGESTED FIX Ideally the implementation should be changed to use readdir64_r but there seems to be issues with the reentrant functions in Solaris 8 and 9 (see 4621211). Asssuming these issues still exist then a simple solution is to just switch to readdir64: ------- UnixFileSystem_md.c ------- *** /tmp/sccs.52ayoa Tue Mar 14 13:54:21 2006 --- UnixFileSystem_md.c Tue Mar 14 13:54:16 2006 *************** *** 335,341 **** jobject file) { DIR *dir = NULL; ! struct dirent *ptr; int len, maxlen; jobjectArray rv, old; --- 335,341 ---- jobject file) { DIR *dir = NULL; ! struct dirent64 *ptr; int len, maxlen; jobjectArray rv, old; *************** *** 351,357 **** if (rv == NULL) goto error; /* Scan the directory */ ! while ((ptr = readdir(dir)) != NULL) { jstring name; if (!strcmp(ptr->d_name, ".") || !strcmp(ptr->d_name, "..")) continue; --- 351,357 ---- if (rv == NULL) goto error; /* Scan the directory */ ! while ((ptr = readdir64(dir)) != NULL) { jstring name; if (!strcmp(ptr->d_name, ".") || !strcmp(ptr->d_name, "..")) continue;
14-03-2006

EVALUATION The output from truss shows the issue: 8901/1: getdents64(5, 0x000EC4C0, 8192) = 176 8901/1: ino=107547 off=1 rlen=24 "." 8901/1: ino=107490 off=2 rlen=24 ".." 8901/1: ino=321247 off=461915142750211 rlen=32 ".DS_Store" 8901/1: ino=107548 off=461919437717508 rlen=32 ".localized" 8901/1: ino=107549 off=6473847154933765 rlen=32 "Drop Box" 8901/1: ino=1507310 off=9223372032559808518 rlen=32 "stoiber.mp3" File.list is implemented using readdir(3C) which limits the offset to 32-bits. So in this case the offset 9223372032559808518 leads to readdir failing with an overflow error. The implementation needs to be changed to use readdir64.
08-03-2006