Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Ticket #1375 (closed defect: fixed)

Opened 12 years ago

Last modified 12 years ago

FilePath.isFolder always returns false (linux, svn trunk)

Reported by: Digited Assigned to: kris
Priority: major Milestone: 0.99.8
Component: Core Functionality Version: trunk
Keywords: FilePath isFolder linux Cc:

Description

Using tango svn trunk on openSUSE 11 linux with dmd 1.036, following code always prints "false":

import
	tango.io.Stdout,
	tango.sys.Environment,
	tango.io.FilePath;
		
int main( char[][] args )
{
	auto currentDir = Environment.get()["PWD"];
	auto currentPath = new FilePath( currentDir );
	Stdout.formatln( "Is [{}] a folder: {}", currentDir, currentPath.isFolder ); // tango svn trunk on openSUSE 11 always returns false
	return 0;
}

On windows isFolder works fine.

Attachments

stat.d.diff (0.7 kB) - added by Cyborg16 on 12/04/08 17:07:42.
stdc.diff (3.8 kB) - added by Cyborg16 on 12/06/08 13:15:18.
Correct stat_t for X86/X86_64, and small/large file support

Change History

11/28/08 13:34:52 changed by Digited

  • owner deleted.

11/28/08 13:46:54 changed by larsivi

  • owner set to kris.

11/29/08 16:26:56 changed by Cyborg16

Same problem here: I've narrowed it down to r4117 (hence no problem when building with -version=SMALLFILE).

This is on 64-bit linux, but using dmd.

Using 64-bit gdc there isn't a problem.

11/29/08 18:40:06 changed by kris

Does that mean the tango.stdc headers are incorrect?

11/30/08 15:30:43 changed by Cyborg16

As far as I can make out, it's correct. Those C headers are horrible!

It doesn't look like it would be correct if compiled as X86_64 (when WORDSIZE == 64 in the C files), which is strange since I didn't get any problems with a gdc 64-bit build. Am I right in assuming it's not intended to work in this case or...? I'm confused.

11/30/08 15:31:48 changed by Cyborg16

That was meant to be __WORDSIZE.

11/30/08 18:34:26 changed by kris

would be much appreciated if you can track this down (don't have an environment that exposes the issue)

12/01/08 12:01:01 changed by Cyborg16

I can try. I was hoping you could tell me whether your stat interface was intended to work when compiled as x86_64 (i.e. when __WORDSIZE == 64 or not (because it looks to me like it's not, but appears to work).

12/01/08 17:22:44 changed by kris

Sean wrote all that stuff, so he'd be the best one to answer that

12/01/08 22:47:47 changed by mandel

Same problem occurs on Debian 32bit, DMD v1.037, Tango svn 4145.

12/01/08 23:42:38 changed by sean

you have to set _USE_LARGEFILE64 to true in stdc.posix.conf and then it should work on x86_64 bit systems. This aspect o the posix headers is very different from the glibc headers, but I'm pretty sure the behavior will be correct--I tried to trim out as much unnecessary complexity as possible.

12/02/08 03:38:17 changed by kris

the logic for _USE_LARGEFILE was inverted in order to enable large files by default on all platforms. It appears that there's an additional aspect to consider when using a 32bit compiler?

12/04/08 14:12:07 changed by mandel

isFolder uses the st_mode field of struct stat_t.
I checked the stat_t and compared it to the C equivalent.

D/Tango: /tango/stdc/posix/sys/stat.d : stat_t
C : /usr/include/bits/stat.h : struct stat

Fields __pad1 and __st_ino/st_ino are probably the culprits.
From a quick look at the hex dumps of the structs it seems that they shouldn't change in size depending on __USE_FILE_OFFSET64.

The struct stat_t is wrong for __USE_FILE_OFFSET64 enabled (== _USE_LARGEFILE64 => SMALLFILE disabled).

stat struct sizes:

__USE_FILE_OFFSET64 enabled

  • Tango stat_t: 112 bytes
  • C header stat: 96 bytes bytes

__USE_FILE_OFFSET64 disabled

  • Tango stat_t: 88 bytes
  • C header stat: 88 bytes bytes

The stat struct is a complex beast.

12/04/08 16:46:18 changed by Cyborg16

Two changes appear to be needed:

  • __st_ino should be 4 bytes (uint), not 8.
  • 8-byte types should be aligned on 4-byte boundaries, not 8. It's enough to change line 104 to:
            align (4) off_t       st_size;
    

since other 8-byte types align correctly anyway.

This brings the struct to 96 bytes as mandel said it should be and a byte dump looks good (all members initialized to all bits set):

dump of stats (96 bytes, align boundary: 8) by members:
8 000   s.st_dev        : 806
4 008   s.__pad1        : ffffffff
4 012   s.__st_ino      : 200e9ed
4 016   s.st_mode       : 41ed
4 020   s.st_nlink      : 4
4 024   s.st_uid        : 3e8
4 028   s.st_gid        : 3e8
8 032   s.st_rdev       : 0
4 040   s.__pad2        : ffffffff
8 044   s.st_size       : 1000
4 052   s.st_blksize    : 1000
8 056   s.st_blocks     : 8
4 064   s.st_atime      : 493807d3
4 068   s.st_atimensec  : 1709ac16
4 072   s.st_mtime      : 49380629
4 076   s.st_mtimensec  : 5b153d8
4 080   s.st_ctime      : 49380629
4 084   s.st_ctimensec  : 5b153d8
8 088   s.st_ino        : 200e9ed

This appears to fix the problem. I checked building with -version=SMALLFILE too, and everything appears OK. I guess gcc just uses 4-byte alignment - presumably that won't be a problem elsewhere as this is linux specific anyway.

12/04/08 16:50:36 changed by kris

thank you, both. Can you provide a patch please?

12/04/08 17:07:42 changed by Cyborg16

  • attachment stat.d.diff added.

12/06/08 11:40:06 changed by Cyborg16

Err... just realized my changes break x86_64 code. Actually, the struct wasn't right anyway, the st_mode field just happened to be in the right place, but isn't with my change. So I guess I'd better do it properly.

12/06/08 13:15:18 changed by Cyborg16

  • attachment stdc.diff added.

Correct stat_t for X86/X86_64, and small/large file support

12/06/08 13:26:44 changed by Cyborg16

OK, the stdc.diff patch gets stat_t right in all modes. I also added comments to explain what each member is, and reordered the aliases in types.d (I double-checked them all).

Here's a dump of stat_t for a device file (/dev/dvd) just to show it works in all modes:

X86_64:
dump of stats (144 bytes, align boundary: 4) by members:
8 000   s.st_dev        : d                             
8 008   s.__st_ino      : 9bc                           
8 016   s.st_nlink      : 1                             
4 024   s.st_mode       : 61b0                          
4 028   s.st_uid        : 0                             
4 032   s.st_gid        : 18                            
4 036   s.pad0  : 0                                     
8 040   s.st_rdev       : b00                           
8 048   s.st_size       : 0                             
8 056   s.st_blksize    : 1000                          
8 064   s.st_blocks     : 0                             
8 072   s.st_atime      : 493a5ee3                      
8 080   s.st_atimensec  : 341fa18c                      
8 088   s.st_mtime      : 493a5ee3                      
8 096   s.st_mtimensec  : 341fa18c                      
8 104   s.st_ctime      : 493a5ee6                      
8 112   s.st_ctimensec  : 34d6b8b2                      
24 120   s.__unused     : [0, 0, 0]                     

X86_64, SMALLFILE (same as above):
dump of stats (144 bytes, align boundary: 4) by members:
8 000   s.st_dev        : d                             
8 008   s.st_ino        : 9bc                           
8 016   s.st_nlink      : 1                             
4 024   s.st_mode       : 61b0
4 028   s.st_uid        : 0
4 032   s.st_gid        : 18
4 036   s.pad0  : 0
8 040   s.st_rdev       : b00
8 048   s.st_size       : 0
8 056   s.st_blksize    : 1000
8 064   s.st_blocks     : 0
8 072   s.st_atime      : 493a5ee3
8 080   s.st_atimensec  : 341fa18c
8 088   s.st_mtime      : 493a5ee3
8 096   s.st_mtimensec  : 341fa18c
8 104   s.st_ctime      : 493a5ee6
8 112   s.st_ctimensec  : 34d6b8b2
24 120   s.__unused     : [0, 0, 0]

X86:
dump of stats (96 bytes, align boundary: 4) by members:
8 000   s.st_dev        : d                            
4 008   s.__pad1        : ffffffff                     
4 012   s.__st_ino      : 9bc                          
4 016   s.st_mode       : 61b0                         
4 020   s.st_nlink      : 1                            
4 024   s.st_uid        : 0                            
4 028   s.st_gid        : 18                           
8 032   s.st_rdev       : b00                          
4 040   s.__pad2        : ffffffff                     
8 044   s.st_size       : 0                            
4 052   s.st_blksize    : 1000                         
8 056   s.st_blocks     : 0                            
4 064   s.st_atime      : 493a5ee3                     
4 068   s.st_atimensec  : 341fa18c                     
4 072   s.st_mtime      : 493a5ee3                     
4 076   s.st_mtimensec  : 341fa18c                     
4 080   s.st_ctime      : 493a5ee6                     
4 084   s.st_ctimensec  : 34d6b8b2                     
8 088   s.st_ino        : 9bc                          

X86, SMALLFILE:
dump of stats (88 bytes, align boundary: 4) by members:
8 000   s.st_dev        : d
2 008   s.__pad1        : 0
4 012   s.st_ino        : 9bc
4 016   s.st_mode       : 61b0
4 020   s.st_nlink      : 1
4 024   s.st_uid        : 0
4 028   s.st_gid        : 18
8 032   s.st_rdev       : b00
2 040   s.__pad2        : 0
4 044   s.st_size       : 0
4 048   s.st_blksize    : 1000
4 052   s.st_blocks     : 0
4 056   s.st_atime      : 493a5ee3
4 060   s.st_atimensec  : 341fa18c
4 064   s.st_mtime      : 493a5ee3
4 068   s.st_mtimensec  : 341fa18c
4 072   s.st_ctime      : 493a5ee6
4 076   s.st_ctimensec  : 34d6b8b2
4 080   s.__unused4     : 0
4 084   s.__unused5     : 0

Interestingly, putting align(4) before the struct doesn't stop everything getting aligned at 8-byte boundaries in X86_64 mode, which appears to be correct. (Also the type of _pad_t doesn't matter because of alignment, but there's no point changing it.)

12/08/08 22:44:25 changed by larsivi

  • status changed from new to closed.
  • resolution set to fixed.

(In [4151]) Applied patch from Cyborg16, thanks! closes #1375 - please reopen if you find any problems.