mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
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:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user