[Mono-dev] DirectoryInfo.GetFiles() returns soft links pointing to directories. Broken behavior in 1.2.5.2?

Max de Lavenne max at tfbc.com
Wed Nov 7 20:22:31 EST 2007


Hello,

After a an upgrade from mono 1.2.2.1 to 1.2.5.2, it appears that links to
folders (created by "ln -s") are now returned by DirectoryInfo.GetFiles()
instead of DirectoryInfo.GetDirectories(); which used to be the way since
mono 0.31

Is there a reason why this behavior has changed? Or is this a regression?
How can I check that the file in question is actually a soft link pointing
to a directory?

I've looked into the system classes for DirectoryInfo.GetFiles(), 

So, I've peeking into ./mcs/class/corlib/System.IO/Directory.cs, line 305:
=======================================================================
    public static string [] GetFiles (string path, string pattern)
    {
            return GetFileSystemEntries (path, pattern,
FileAttributes.Directory, 0);
    }
=======================================================================

(appearing to be searching for FileAttributes.Directory files (?))

Which then calls into  ./mcs/class/corlib/System.IO/MonoIO.cs, line 140:
=======================================================================
   [MethodImplAttribute (MethodImplOptions.InternalCall)]
   public extern static string [] GetFileSystemEntries (string path, string
path_with_pattern, int attrs, int mask, out MonoIOError error);
=======================================================================

Leading me to the file ./mono/metadata/file-io.c, line 289:
=======================================================================
  do {
    if ((data.cFileName[0] == '.' && data.cFileName[1] == 0) ||
        (data.cFileName[0] == '.' && data.cFileName[1] == '.' &&
data.cFileName[2] == 0)) {
            continue;
    }

    if ((data.dwFileAttributes & mask) == attrs) {
            utf8_result = g_utf16_to_utf8 (data.cFileName, -1, NULL, NULL,
NULL);
            if (utf8_result == NULL) {
                    continue;
            }

            full_name = g_build_filename (utf8_path, utf8_result, NULL);
            g_ptr_array_add (names, full_name);

            g_free (utf8_result);
    }
 } while(FindNextFile (find_handle, &data));
=======================================================================

Now, it seems that the dwFileAttributes is checked against being a
directory, if I understand the call stack.
I may be wrong, but it seems that GetFiles() is trying to list all
directories, is it not?

Here's the code that worked all the way up to mono 1.2.2.1 but now fails in
1.2.5.2:

/// <summary>
/// Build the listing of files. Return a value greater than 0 if there's
been files found
/// </summary>
private static int ListFiles(string dirpath,XmlTextWriter xw, ListingMode
listmode, string rootDir, string indent, VirtualDirectory vdir) {
	int count = 0;

	try {
		DirectoryInfo dirinfo = new DirectoryInfo(dirpath);
		if ( dirinfo.Exists ) {
			// add info about each encountered file
			FileInfo [] filelist = dirinfo.GetFiles();
			Array.Sort(filelist,new FileSystem());
			
			foreach ( FileInfo fileinfo in filelist ) {
				if ( vdir.CanShow(fileinfo.FullName) ) {
					string filename = fileinfo.Name;
					count++;
					xw.WriteRaw("\r\n");
					xw.WriteRaw(indent);
					xw.WriteStartElement("File");
	
xw.WriteAttributeString("Path",Strings.ToNeutral(filename));
	
xw.WriteAttributeString("Stamp",GetFileStampString(fileinfo));
	
xw.WriteAttributeString("Size",XmlConvert.ToString(fileinfo.Length));
					xw.WriteEndElement();
				}
			}

			// add info about each directory
			DirectoryInfo [] dirlist = dirinfo.GetDirectories();
			Array.Sort(dirlist,new FileSystem());

			foreach  ( DirectoryInfo dir in dirlist ) {
				string dirname = dir.Name;
				count++;
				xw.WriteRaw("\r\n");
				xw.WriteRaw(indent);
				xw.WriteStartElement("Directory");
	
xw.WriteAttributeString("Path",Strings.ToNeutral(dirname));
	
xw.WriteAttributeString("Stamp",GetFileStampString(dir));

				// go recursive if required
				if ( listmode == ListingMode.Recursive ) {
					if (
ListFiles(dir.FullName,xw,listmode,rootDir,indent+" ",vdir) > 0 ) {
						xw.WriteRaw("\r\n");
						xw.WriteRaw(indent);
					}
				}

				xw.WriteEndElement();
			}
		}
	} catch ( Exception ex ) {
		StaticLogger.WriteException(ex,LogLevel.Error);
		//StaticLogger.WriteLine("got exception:
"+ex.Message,LogLevel.Error);
	}

	return count;
}

How can I fix this behavior?

Thanks

Max




More information about the Mono-devel-list mailing list