[Toybox] [landley/toybox] Add ln -r (#145)

Rob Landley rob at landley.net
Fri Oct 25 20:11:00 PDT 2019


On 10/25/19 6:29 PM, Rob Landley wrote:
> I think I need a new lib function to do this, and I should change cp -s to use
> it too. And I need more cp tests because the above cp -s made a broken symlink...

Well, I made the new lib function, which is just:

// return (malloced) relative path to get from "from" to "to"
char *relative_path(char *from, char *to)
{
  char *s, *ret = 0;
  int i, j, k;

  if (!(from = xabspath(from, -1))) return 0;
  if (!(to = xabspath(to, -1))) goto error;

  // skip common directories from root
  for (i = j = 0; from[i] && from[i] == to[i]; i++) if (to[i] == '/') j = i+1;

  // count remaining destination directories
  for (i = j, k = 0; from[i]; i++) if (from[i] == '/') k++;

  if (!k) ret = xstrdup(to+j);
  else {
    s = ret = xmprintf("%*c%s", 3*k, ' ', to+j);
    while (k--) memcpy(s+3*k, "../", 3);
  }

error:
  free(from);
  free(to);

  return ret;
}

But getting cp to use it turns out to be fiddly because the context I have for
destination path is a relative path under a directory file descriptor (which is
faster and avoids path depth issues), and I don't actually know how to turn that
into an absolute path? (Other than reading from /proc which always seems brittle.)

Sigh. In theory I could get the path to top of destination and then copy the
chunk of dirtree_parent() onto it to get the current directory, which would
assume we hadn't followed symlinks to get here (when copying into an existing
path)...

Also, doing two xabspath() per file is kind of expensive for something like cp
-r, but making a while second codepath to work _upwards_ for this also seems
overkill...

Rob

P.S. And I need an xabspath(file, -2) variant that resolves everything except
the last path component, because that's what tar wants for this directory
replaces symlink thing. I need to resolve before calling unlink() so you can't
trick tar into deleting random stuff by following a symlink...


More information about the Toybox mailing list