[Toybox] [HACK] hackfixing cp for compilation

Rob Landley rob at landley.net
Mon Nov 19 15:34:40 PST 2012


On 11/01/2012 08:16:39 PM, Rob Landley wrote:
> On 10/28/2012 10:42:32 PM, Roy Tam wrote:
>> It is broken for months, so I hackfixed it.
> 
> Sigh. Good point.
> 
> I was fixing cp properly before work and email and life went nuts.
> 
> Let's see...

TT.destname isn't getting initialized. Last commit that worked (before  
the dirtree changes) was 528, so comparing with that. What was I  
thinking?

   http://landley.net/hg/toybox/file/538/toys/cp.c

First line of cp_main() used to be TT.destname =  
toys.optargs[--toys.optc]; and the reason I removed that was:

A) I was thinking about someday adding NOFORK capability (the ability  
for toysh or similar to just call cp_main() as a function, probably  
through some variant of toy_exec(), and clean up after it in the same  
process context without fork/exec overhead). This meant the ability to  
free the argument memory, so permuting the arguments so it lost track  
of one and potentially leaked memory would be a downside. But that's  
bogus because toys.argc still has them all.

B) Adding the ability to tell the optstring to parse non-option  
arguments into the global block, so the <2 fixed arguments would wing  
up in TT without needing to do it by hand. (The idea was getting it to  
automatically do the type conversions.) I poked at this a bit, but  
couldn't work out a good way to express it that actually reduced  
complexity.

So, putting that back in...

Next up, TT.destisnew was only ever set, not read, so I yanked that  
case, tested for the other one, and unified the else cases to avoid the  
goto that was combining the two error_exit() cases.

That gets us to the TODO, which is about this problem:

   readlink -f ./nonexistent : prints absolute path of where it _would_  
go.
   realpath("./nonexistent", NULL): returns NULL

This is actually why toybox's readlink defaults to "n" for now, I need  
to make this case work.

However, what I'm trying to do here is duplicate detection, as  
mentioned in the previous reply...

Rob

>> diff -U8 toys/posix/cp.c toys/posix/cp.c_hf
>> --- toys/posix/cp.c     2012-10-27 10:15:31.000000000 +0800
>> +++ toys/posix/cp.c_hf  2012-10-29 11:41:01.000000000 +0800
>> @@ -171,37 +171,37 @@
>> 
>>         // Loop through sources
>> 
>>         for (i=0; i<toys.optc; i++) {
>>                 char *dst, *src = toys.optargs[i];
>> 
>>                 // Skip src==dest (TODO check inodes to catch "cp  
>> blah ./blah").
>> 
>> -               if (!strncmp(src, TT.destname)) continue;
>> +               if (!strcmp(src, TT.destname)) continue;
> 
> Sigh.  Looks like I checked in half-finished work at some point.  
> (Possibly when I categorized commands into subdirectories.)
> 
> What I was going for here is trying to catch destinations that are  
> _under_ source, ala:
> 
>   cp -r dir dir/sub
> 
> If I'm using cannonicalized absolute paths (with all the symlinks  
> resolved), then a
> matching prefix tells me I've got an endless loop coming up. But I  
> also need to catch:
> 
>   cp * .
> 
> Last I poked at this, I'm was trying to work out what all the cases  
> were and a
> graceful way to catch them without a forest of special cases...



>>                 // Skip nonexistent sources.
>> 
>>                 TT.keep_symlinks = toys.optflags & (FLAG_d|FLAG_a);
>>                 if (TT.keep_symlinks ? lstat(src, &st) : stat(src,  
>> &st)
>> -                       || (st.st_dev = dst.st_dev && st.st_ino ==  
>> dst.dst_ino))
>> +                       /*|| (st.st_dev = dst.st_dev && st.st_ino ==
>> dst.dst_ino)*/)
> 
> Another variant of the same thing. I was stepping back and trying to  
> collate it all into one test.
> 
> Unfortunately, "endless recursion with -r" and "copy over itself"  
> seem like the need to be two separate tests.
> 
>>                 {
>>  objection:
>>                         perror_msg("bad '%s'", src);
>>                         toys.exitval = 1;
>>                         continue;
>>                 }
>> 
>>                 // Copy directory or file.
>> 
>>                 if (TT.destisdir) {
>>                         char *s;
>> 
>>                         // Catch "cp -R .. ." and friends that would
>> go on forever
>> -                       if (dpath && (s = realpath(src, NULL)) {
>> +                       if (dpath && (s = realpath(src, NULL))) {
> 
> Ok, that's just embarassing. But it also means "I never actually  
> tested this code, and it needs a largeish test suite entry because  
> it's a pile of corner cases with a bunch of command line options".
> 
> I'm poking at it.
> 
> Thanks,
> 
> Rob



More information about the Toybox mailing list