daemon: Change ln, ln-f (hard-link) APIs to use link(2) instead of external ln (RHBZ#895905).

The reasons to do this are twofold:

(a) It's probably a tiny bit faster.

(b) It lets us capture the real errno if the link(2) syscall fails.

The errno is also passed through guestmount, fixing RHBZ#895905:

+ guestmount -a test1.img -m /dev/sda1:/ -m /dev/sda2:/boot /tmp/mnt
+ touch /tmp/mnt/foo
+ cd /tmp/mnt
+ ln foo boot/foo
ln: failed to create hard link ‘boot/foo’ => ‘foo’: Invalid cross-device link
This commit is contained in:
Richard W.M. Jones
2013-01-21 13:41:23 +00:00
parent ebc86ae6d7
commit 533082e282

View File

@@ -102,13 +102,47 @@ do_internal_readlinklist (const char *path, char *const *names)
return ret.argv;
}
int
do_ln (const char *target, const char *linkname)
{
int r;
CHROOT_IN;
r = link (target, linkname);
CHROOT_OUT;
if (r == -1) {
reply_with_perror ("link: %s: %s", target, linkname);
return -1;
}
return 0;
}
int
do_ln_f (const char *target, const char *linkname)
{
int r;
CHROOT_IN;
unlink (linkname);
r = link (target, linkname);
CHROOT_OUT;
if (r == -1) {
reply_with_perror ("link: %s: %s", target, linkname);
return -1;
}
return 0;
}
static int
_link (const char *flag, int symbolic, const char *target, const char *linkname)
_symlink (const char *flag, const char *target, const char *linkname)
{
int r;
char *err;
char *buf_linkname;
char *buf_target;
/* Prefix linkname with sysroot. */
buf_linkname = sysroot_path (linkname);
@@ -117,36 +151,13 @@ _link (const char *flag, int symbolic, const char *target, const char *linkname)
return -1;
}
/* Only prefix target if it's _not_ a symbolic link, and if
* the target is absolute. Note that the resulting link will
* always be "broken" from the p.o.v. of the appliance, ie:
* /a -> /b but the path as seen here is /sysroot/b
*/
buf_target = NULL;
if (!symbolic && target[0] == '/') {
buf_target = sysroot_path (target);
if (!buf_target) {
reply_with_perror ("malloc");
free (buf_linkname);
return -1;
}
}
if (flag)
r = command (NULL, &err,
str_ln, flag, "--", /* target could begin with '-' */
buf_target ? : target, buf_linkname, NULL);
else
r = command (NULL, &err,
str_ln, "--",
buf_target ? : target, buf_linkname, NULL);
r = command (NULL, &err,
str_ln, flag, "--", /* target could begin with '-' */
target, buf_linkname, NULL);
free (buf_linkname);
free (buf_target);
if (r == -1) {
reply_with_error ("ln%s%s: %s: %s: %s",
flag ? " " : "",
flag ? : "",
target, linkname, err);
reply_with_error ("ln %s: %s: %s: %s",
flag, target, linkname, err);
free (err);
return -1;
}
@@ -156,26 +167,14 @@ _link (const char *flag, int symbolic, const char *target, const char *linkname)
return 0;
}
int
do_ln (const char *target, const char *linkname)
{
return _link (NULL, 0, target, linkname);
}
int
do_ln_f (const char *target, const char *linkname)
{
return _link ("-f", 0, target, linkname);
}
int
do_ln_s (const char *target, const char *linkname)
{
return _link ("-s", 1, target, linkname);
return _symlink ("-s", target, linkname);
}
int
do_ln_sf (const char *target, const char *linkname)
{
return _link ("-sf", 1, target, linkname);
return _symlink ("-sf", target, linkname);
}