United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6395581 File.listFiles() is unable to read nfs-mounted directory (MacOS X)
JDK-6395581 : File.listFiles() is unable to read nfs-mounted directory (MacOS X)

Details
Type:
Bug
Submit Date:
2006-03-08
Status:
Resolved
Updated Date:
2010-07-29
Project Name:
JDK
Resolved Date:
2006-04-01
Component:
core-libs
OS:
solaris_8,solaris_10
Sub-Component:
java.io
CPU:
sparc
Priority:
P2
Resolution:
Fixed
Affected Versions:
1.4.0,1.4.2_11
Fixed Versions:

Related Reports
Backport:
Backport:
Duplicate:
Relates:

Sub Tasks

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

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.
                                     
2006-03-08
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;
                                     
2006-03-14
EVALUATION

Update implementation to readdir64_r(). 

Use reentrant version of readdir64 to take care of 4621211
                                     
2006-03-21



Hardware and Software, Engineered to Work Together