diff options
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/copy_file.c | 13 | ||||
-rw-r--r-- | libbb/libbb.h | 1 | ||||
-rw-r--r-- | libbb/xreadlink.c | 34 |
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; +} + |