Subject: Re: rm 8.1

From: Brad <[email-masked]>
Date: Thu, 24 Jun 2010 14:56:19 -0700

Hi Jim:

After learning a little more about the debugger I was able to solve the 
problem.

It is clear that the option test is not failing. However only one of 
three tests are being run because the code is linking to the new glibc. 
Therefore the program is calling the fts_open function defined in 
glibc-2.11.2/io/fts.c rather than lib/fts.c (which does three options 
checks).

	/* Options check. */
	if (options & ~FTS_OPTIONMASK) {
		__set_errno (EINVAL);
		return (NULL);
	}

	/* Allocate/initialize the stream */
	if ((sp = malloc((u_int)sizeof(FTS))) == NULL)
		return (NULL);

So the code is failing at the subsequent call to malloc. A segmentation 
fault is occurring because the glibc version of fts_open is incompatible 
with the new coreutils.

I fixed this on my system by redefining fts_open() as _fts_open(). That 
way there is no pollution of the namespace.

Here are the diffs:

diff fts_.h ../../core_source/lib/fts_.h
254c254
< FTS     *_fts_open (char * const *, int,
---
 > FTS     *fts_open (char * const *, int,

diff fts.c ../../core_source/lib/fts.c
362c362
< _fts_open (char * const *argv,
---
 > fts_open (char * const *argv,

diff xfts.c ../../core_source/lib/xfts.c
36c36
<   FTS *fts = _fts_open (argv, options | FTS_CWDFD, compar);
---
 >   FTS *fts = fts_open (argv, options | FTS_CWDFD, compar);

I think that's it. It's probably not a good idea to redefine a function 
that's already defined in a linked library. The behavior is undefined in 
C because it depends upon the linkage order that is determined by the 
compiler.

I hope this helps. Thank you for all of your savvy guidance.

Best wishes,

Brad

Brad wrote:
> Hi Jim, my copy of fts.i looks the same as yours. Here is the additional 
> gdb output:
> 
> ### begin gdb ###
> Starting program: /home/brad/tools/core_debug/src/rm -rf a/b/c/d
> 
> Breakpoint 1, fts_open (argv=0x7fffffffed08, options=536, compar=0) at 
> fts.c:92
> 92      {
> (gdb) print options & ~0x07ff
> $1 = 0
> 
> ### end gdb ###
> 
> Please tell me what this means. I knew the bit flags from function rm in 
> src/remove.c:
> 
>       int bit_flags = (FTS_CWDFD
>                        | FTS_NOSTAT
>                        | FTS_PHYSICAL);
> 
>       if (x->one_file_system)
>         bit_flags |= FTS_XDEV;
> 
>       FTS *fts = xfts_open (file, bit_flags, NULL);
> 
> 
> and of course the option mask from lib/fts_.h:
> 
> # define FTS_OPTIONMASK 0x07ff          /* valid user option mask */
> 
> But how do you read this from the gdb output?
> 
> Thanks for your help. I really appreciate your prompt attention to this 
> matter. Please let me know if there is anything else you need me to do.
> 
> 
> Jim Meyering wrote:
>> Brad wrote:
>> ...
>>> (gdb) run -rf a/b/c/d
>>> Starting program: /home/brad/tools/core_debug/src/rm -rf a/b/c/d
>>>
>>> Breakpoint 1, fts_open (argv=0x7fffffffed08, options=536, compar=0) at
>>> fts.c:92
>>> 92      {
>>> (gdb) n
>>> 100             if (options & ~FTS_OPTIONMASK) {
>>> (gdb) n
>>> 101                     __set_errno (EINVAL);
>>> (gdb) n
>>> 201     }
>>> (gdb) n
>>> xfts_open (argv=0x7fffffffed08, options=536, compar=0) at
>>> ../../coreutils-8.5/lib/xfts.c:37
>>
>> Thanks.  that "options" value is 0x218, which makes sense:
>>
>>     # define FTS_NOSTAT     0x0008          /* don't get stat info */
>>     # define FTS_PHYSICAL   0x0010          /* physical walk */
>>     # define FTS_CWDFD      0x0200
>>
>>       int bit_flags = (FTS_CWDFD | FTS_NOSTAT | FTS_PHYSICAL);
>>       ...
>>       FTS *fts = xfts_open (file, bit_flags, NULL);
>>
>> The other value in that comparison should come from fts_.h:
>>
>>     # define FTS_OPTIONMASK 0x07ff          /* valid user option mask */
>>
>> But is that actually the value used on your system?
>>
>> To find out, do this:
>>
>>     cd lib
>>     rm fts.o
>>     make AM_CFLAGS='-E -dD' fts.o
>>
>> That is a hack to obtain C-preprocessed sources.
>> Rename the file to have a sensible suffix, and so it
>> doesn't interfere with a subsequent build:
>>
>>     mv fts.o fts.i
>>
>> In my copy, I see this:
>>
>>         if (options & ~0x07ff) {
>>                 (*__errno_location ()) = (22);
>>                 return (((void *)0));
>>         }
>>
>> If you see the same thing, then suspect that your compiler is at fault.
>> In that case, there's one more thing you can do:
>>
>> Repeat the steps you performed above, then run this command right after
>> hitting the breakpoint, and tell us what it prints:
>>
>>   print options & ~0x07ff
>>
> 

-- 
Brad Mells
Quantum Harmonics
889 Mowry Ave #86
Fremont CA 94536

619.808.2359