coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: first contribution: smart rename for the mv command


From: Kaz Kylheku
Subject: Re: first contribution: smart rename for the mv command
Date: Fri, 13 Jan 2023 23:57:33 -0800
User-agent: Roundcube Webmail/1.4.13

On 2022-12-22 07:59, Stéphane Archer wrote:
> Dear Gnu Coreutils community,
> 
> I would like to contribute to the project a feature I miss a lot in the
> `mv` command.
> I currently have a working patch but it's clearly not perfect. I would like
> to have feedback on it and would like to know if you are willing to accept
> this change.
> Do you think it's possible?

I have only technical feedback about code.

1. access function: you probably don't want to use this.
  
   The purpose of the access function is for setuid programs to determine
   whether the real user ID would have a certain access, without having
   to drop privileges to that ID. 

   This is almost certainly not what you want in a utility like this;
   mv just should wield whatever effective user ID powers it has, and
   not hold back.

   Even if the operation is F_OK for simple existence, the function is not
   appropriate, because POSIX says:

     The checks for accessibility (including directory permissions
     checked during pathname resolution) shall be performed using
     the real user ID in place of the effective user ID and the real
     group ID in place of the effective group ID.

   So if you do access("/home/bob/private/xyzzy.txt", F_OK), as EUID = root,
   but RUID = alice, access will pretend that it's running as alice and
   not allow the existence check through bob's private directory.

2. Don't invent new functions from scratch.
 
      find_dot(str)  ->  strcspn(str, ".")   // mostly

   This strcspn will return the length of the prefix of str
   before the first dot. If there is not dot, it returns strlen(str).

3. string functions like strlen return size_t, not unsigned int;
   don't mix types. It's not a huge deal because you probably
   won't get a 64 bit size_t value that is truncated when converted
   to a 32 bit unsigned int. It's untidy though.

4. I see a malloc call, but most GNU programs don't use malloc directly
   and the Coreutils are no exception: they use xmalloc, xzalloc
   and such, which are wrappers. Always look around in the code base
   for examples of the kind of thing you're trying to do, to see what
   functions it's using; reuse its idioms so your patch blends in.

5. I think your create_smart_name function can be condensed with some
   creative use of the snprintf function. Possibly one call to that,
   with some conditional in the argument list, could do the whole job
   of combining the pieces.

6. Re:

    +      unsigned int i = 0;
    +      char is[100]; // What len should I put?
    +      sprintf(is, "%d", i);

   Because i is unsigned int, use "%u" and not "%d",
   which will interpret it as int, possibly negative.

   Your loop should test for i hitting UINT_MAX;
   you don't want to increment from there to zero.
   One fine day someone will have that many files;
   and filesystems can be virtual (e.g. we could use
   FUSE in some way to make a test case for this without
   making billions of files.)

   Since the index is unsigned int with a UINT_MAX
   maximum value, we can conservatively estimate
   the number of digits needed by dividing
   (UINT_MAX * CHAR_BIT) / 3. (The idea being every 3
   binary digits encodes one decimal digit's worth of
   entropy). Then add 1 for the null terminator.

   For 32 bits we get 32 / 3 + 1 = 11. (exact fit for UINT_MAX)

   For 63 bits we get 64 / 3 + 1 = 22. (one byte wasted)

7. Pay attention to coding style. GNU uses funny indentation for braces:

   if (smart_rename)
     {                     // + 2
        dest =             // + 2 again
     }

   Do not even think about doing this outside of GNU, though. :)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]