#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include "actions.h"
char *
-do_readlink (char *path)
+do_readlink (const char *path)
{
ssize_t r;
char *ret;
char link[PATH_MAX];
- NEED_ROOT (NULL);
- ABS_PATH (path, NULL);
-
CHROOT_IN;
r = readlink (path, link, sizeof link);
CHROOT_OUT;
return ret; /* caller frees */
}
+char **
+do_readlinklist (const char *path, char *const *names)
+{
+ int fd_cwd;
+ size_t i;
+ ssize_t r;
+ char link[PATH_MAX];
+ const char *str;
+ char **ret = NULL;
+ int size = 0, alloc = 0;
+
+ CHROOT_IN;
+ fd_cwd = open (path, O_RDONLY | O_DIRECTORY);
+ CHROOT_OUT;
+
+ if (fd_cwd == -1) {
+ reply_with_perror ("open: %s", path);
+ return NULL;
+ }
+
+ for (i = 0; names[i] != NULL; ++i) {
+ r = readlinkat (fd_cwd, names[i], link, sizeof link);
+ if (r >= PATH_MAX) {
+ reply_with_perror ("readlinkat: returned link is too long");
+ free_strings (ret);
+ close (fd_cwd);
+ return NULL;
+ }
+ /* Because of the way this function is intended to be used,
+ * we actually expect to see errors here, and they are not fatal.
+ */
+ if (r >= 0) {
+ link[r] = '\0';
+ str = link;
+ } else
+ str = "";
+ if (add_string (&ret, &size, &alloc, str) == -1) {
+ close (fd_cwd);
+ return NULL;
+ }
+ }
+
+ close (fd_cwd);
+
+ if (add_string (&ret, &size, &alloc, NULL) == -1)
+ return NULL;
+
+ return ret;
+}
+
static int
_link (const char *flag, int symbolic, const char *target, const char *linkname)
{
char *buf_linkname;
char *buf_target;
- NEED_ROOT (-1);
- ABS_PATH (linkname, -1);
- /* but target does not need to be absolute */
-
/* Prefix linkname with sysroot. */
buf_linkname = sysroot_path (linkname);
if (!buf_linkname) {
if (flag)
r = command (NULL, &err,
- "ln", flag, "--", /* target could begin with '-' */
- buf_target ? : target, buf_linkname, NULL);
+ "ln", flag, "--", /* target could begin with '-' */
+ buf_target ? : target, buf_linkname, NULL);
else
r = command (NULL, &err,
- "ln", "--",
- buf_target ? : target, buf_linkname, NULL);
+ "ln", "--",
+ buf_target ? : 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);
+ flag ? " " : "",
+ flag ? : "",
+ target, linkname, err);
free (err);
return -1;
}
}
int
-do_ln (char *target, char *linkname)
+do_ln (const char *target, const char *linkname)
{
return _link (NULL, 0, target, linkname);
}
int
-do_ln_f (char *target, char *linkname)
+do_ln_f (const char *target, const char *linkname)
{
return _link ("-f", 0, target, linkname);
}
int
-do_ln_s (char *target, char *linkname)
+do_ln_s (const char *target, const char *linkname)
{
return _link ("-s", 1, target, linkname);
}
int
-do_ln_sf (char *target, char *linkname)
+do_ln_sf (const char *target, const char *linkname)
{
return _link ("-sf", 1, target, linkname);
}