summaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
Diffstat (limited to 'libbb')
-rw-r--r--libbb/copy_file.c13
-rw-r--r--libbb/libbb.h1
-rw-r--r--libbb/xreadlink.c34
3 files changed, 38 insertions, 10 deletions
diff --git a/libbb/copy_file.c b/libbb/copy_file.c
index 2d18b60..22684be 100644
--- a/libbb/copy_file.c
+++ b/libbb/copy_file.c
@@ -196,19 +196,12 @@ int copy_file(const char *source, const char *dest, int flags)
return -1;
}
} else if (S_ISLNK(source_stat.st_mode)) {
- int size;
- char buf[BUFSIZ + 1];
-
- if ((size = readlink(source, buf, BUFSIZ)) < 0) {
- perror_msg("cannot read `%s'", source);
- return -1;
- }
- buf[size] = '\0';
-
- if (symlink(buf, dest) < 0) {
+ char *lpath = xreadlink(source);
+ if (symlink(lpath, dest) < 0) {
perror_msg("cannot create symlink `%s'", dest);
return -1;
}
+ free(lpath);
#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
if (flags & FILEUTILS_PRESERVE_STATUS)
diff --git a/libbb/libbb.h b/libbb/libbb.h
index a53e647..d2f9a95 100644
--- a/libbb/libbb.h
+++ b/libbb/libbb.h
@@ -217,6 +217,7 @@ int ask_confirmation(void);
int klogctl(int type, char * b, int len);
char *xgetcwd(char *cwd);
+char *xreadlink(const char *path);
char *concat_path_file(const char *path, const char *filename);
int last_char_is(const char *s, const int c);
diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c
new file mode 100644
index 0000000..66f63b8
--- /dev/null
+++ b/libbb/xreadlink.c
@@ -0,0 +1,34 @@
+/*
+ * xreadlink.c - safe implementation of readlink
+ */
+
+#include <stdio.h>
+
+/*
+ * NOTE: This function returns a malloced char* that you will have to free
+ * yourself. You have been warned.
+ */
+
+#include <unistd.h>
+#include "libbb.h"
+
+extern char *xreadlink(const char *path)
+{
+ static const int GROWBY = 80; /* how large we will grow strings by */
+
+ char *buf = NULL;
+ int bufsize = 0, readsize = 0;
+
+ do {
+ buf = xrealloc(buf, bufsize += GROWBY);
+ readsize = readlink(path, buf, bufsize); /* 1st try */
+ if (readsize == -1)
+ perror_msg("%s:%s", applet_name, path);
+ }
+ while (bufsize < readsize + 1);
+
+ buf[readsize] = '\0';
+
+ return buf;
+}
+