Made new xreadlink function for libbb and changed applets to use it instead of
readlink(2).
diff --git a/Makefile b/Makefile
index 5713cdc..91ed745 100644
--- a/Makefile
+++ b/Makefile
@@ -247,8 +247,8 @@
process_escape_sequence.c read_package_field.c read_text_file_to_buffer.c \
recursive_action.c safe_read.c safe_strncpy.c seek_ared_file.c syscalls.c \
syslog_msg_with_name.c time_string.c trim.c untar.c unzip.c vdprintf.c \
-verror_msg.c vperror_msg.c wfopen.c xfuncs.c xgetcwd.c xregcomp.c interface.c \
-remove_file.c last_char_is.c
+verror_msg.c vperror_msg.c wfopen.c xfuncs.c xgetcwd.c xreadlink.c\
+xregcomp.c interface.c remove_file.c last_char_is.c
LIBBB_OBJS=$(patsubst %.c,$(LIBBB)/%.o, $(LIBBB_CSRC))
LIBBB_CFLAGS = -I$(LIBBB)
ifneq ($(strip $(BB_SRC_DIR)),)
diff --git a/applets/busybox.c b/applets/busybox.c
index b4939e1..badd53d 100644
--- a/applets/busybox.c
+++ b/applets/busybox.c
@@ -37,21 +37,10 @@
*/
static char *busybox_fullpath()
{
- pid_t pid;
- char path[256];
char proc[256];
- int len;
- pid = getpid();
- sprintf(proc, "/proc/%d/exe", pid);
- len = readlink(proc, path, 256);
- if (len != -1) {
- path[len] = 0;
- } else {
- perror_msg("%s", proc);
- return NULL;
- }
- return strdup(path);
+ sprintf(proc, "/proc/%d/exe", getpid());
+ return xreadlink(proc);
}
/* create (sym)links for each applet */
diff --git a/archival/tar.c b/archival/tar.c
index c168564..4bf8004 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -921,16 +921,10 @@
header.typeflag = LNKTYPE;
strncpy(header.linkname, tbInfo->hlInfo->name, sizeof(header.linkname));
} else if (S_ISLNK(statbuf->st_mode)) {
- int link_size=0;
- char buffer[BUFSIZ];
+ char *lpath = xreadlink(real_name);
header.typeflag = SYMTYPE;
- link_size = readlink(real_name, buffer, sizeof(buffer) - 1);
- if ( link_size < 0) {
- perror_msg("Error reading symlink '%s'", header.name);
- return ( FALSE);
- }
- buffer[link_size] = '\0';
- strncpy(header.linkname, buffer, sizeof(header.linkname));
+ strncpy(header.linkname, lpath, sizeof(header.linkname));
+ free(lpath);
} else if (S_ISDIR(statbuf->st_mode)) {
header.typeflag = DIRTYPE;
strncat(header.name, "/", sizeof(header.name));
diff --git a/busybox.c b/busybox.c
index b4939e1..badd53d 100644
--- a/busybox.c
+++ b/busybox.c
@@ -37,21 +37,10 @@
*/
static char *busybox_fullpath()
{
- pid_t pid;
- char path[256];
char proc[256];
- int len;
- pid = getpid();
- sprintf(proc, "/proc/%d/exe", pid);
- len = readlink(proc, path, 256);
- if (len != -1) {
- path[len] = 0;
- } else {
- perror_msg("%s", proc);
- return NULL;
- }
- return strdup(path);
+ sprintf(proc, "/proc/%d/exe", getpid());
+ return xreadlink(proc);
}
/* create (sym)links for each applet */
diff --git a/coreutils/ls.c b/coreutils/ls.c
index d24ba98..c13b225 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -577,7 +577,7 @@
/*----------------------------------------------------------------------*/
static int list_single(struct dnode *dn)
{
- int i, len;
+ int i;
char scratch[BUFSIZ + 1];
#ifdef BB_FEATURE_LS_TIMESTAMPS
char *filetime;
@@ -688,16 +688,16 @@
break;
case LIST_SYMLINK:
if (S_ISLNK(dn->dstat.st_mode)) {
- len= readlink(dn->fullname, scratch, (sizeof scratch)-1);
- if (len > 0) {
- scratch[len]= '\0';
- printf(" -> %s", scratch);
+ char *lpath = xreadlink(dn->fullname);
+ if (lpath) {
+ printf(" -> %s", lpath);
#ifdef BB_FEATURE_LS_FILETYPES
if (!stat(dn->fullname, &info)) {
append = append_char(info.st_mode);
}
#endif
- column += len+4;
+ column += strlen(lpath) + 4;
+ free(lpath);
}
}
break;
diff --git a/include/libbb.h b/include/libbb.h
index a53e647..d2f9a95 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -217,6 +217,7 @@
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/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 @@
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 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;
+}
+
diff --git a/ls.c b/ls.c
index d24ba98..c13b225 100644
--- a/ls.c
+++ b/ls.c
@@ -577,7 +577,7 @@
/*----------------------------------------------------------------------*/
static int list_single(struct dnode *dn)
{
- int i, len;
+ int i;
char scratch[BUFSIZ + 1];
#ifdef BB_FEATURE_LS_TIMESTAMPS
char *filetime;
@@ -688,16 +688,16 @@
break;
case LIST_SYMLINK:
if (S_ISLNK(dn->dstat.st_mode)) {
- len= readlink(dn->fullname, scratch, (sizeof scratch)-1);
- if (len > 0) {
- scratch[len]= '\0';
- printf(" -> %s", scratch);
+ char *lpath = xreadlink(dn->fullname);
+ if (lpath) {
+ printf(" -> %s", lpath);
#ifdef BB_FEATURE_LS_FILETYPES
if (!stat(dn->fullname, &info)) {
append = append_char(info.st_mode);
}
#endif
- column += len+4;
+ column += strlen(lpath) + 4;
+ free(lpath);
}
}
break;
diff --git a/miscutils/readlink.c b/miscutils/readlink.c
index 74196e1..2266495 100644
--- a/miscutils/readlink.c
+++ b/miscutils/readlink.c
@@ -30,21 +30,17 @@
int readlink_main(int argc, char **argv)
{
char *buf = NULL;
- int bufsize = 128, size = 128;
+
+ /* no options, no getopt */
if (argc != 2)
show_usage();
- while (bufsize < size + 1) {
- bufsize *= 2;
- buf = xrealloc(buf, bufsize);
- size = readlink(argv[1], buf, bufsize);
- if (size == -1)
- perror_msg_and_die("%s", argv[1]);
- }
-
- buf[size] = '\0';
+ buf = xreadlink(argv[1]);
puts(buf);
+#ifdef BB_FEATURE_CLEAN_UP
+ free(buf);
+#endif
return EXIT_SUCCESS;
}
diff --git a/readlink.c b/readlink.c
index 74196e1..2266495 100644
--- a/readlink.c
+++ b/readlink.c
@@ -30,21 +30,17 @@
int readlink_main(int argc, char **argv)
{
char *buf = NULL;
- int bufsize = 128, size = 128;
+
+ /* no options, no getopt */
if (argc != 2)
show_usage();
- while (bufsize < size + 1) {
- bufsize *= 2;
- buf = xrealloc(buf, bufsize);
- size = readlink(argv[1], buf, bufsize);
- if (size == -1)
- perror_msg_and_die("%s", argv[1]);
- }
-
- buf[size] = '\0';
+ buf = xreadlink(argv[1]);
puts(buf);
+#ifdef BB_FEATURE_CLEAN_UP
+ free(buf);
+#endif
return EXIT_SUCCESS;
}
diff --git a/tar.c b/tar.c
index c168564..4bf8004 100644
--- a/tar.c
+++ b/tar.c
@@ -921,16 +921,10 @@
header.typeflag = LNKTYPE;
strncpy(header.linkname, tbInfo->hlInfo->name, sizeof(header.linkname));
} else if (S_ISLNK(statbuf->st_mode)) {
- int link_size=0;
- char buffer[BUFSIZ];
+ char *lpath = xreadlink(real_name);
header.typeflag = SYMTYPE;
- link_size = readlink(real_name, buffer, sizeof(buffer) - 1);
- if ( link_size < 0) {
- perror_msg("Error reading symlink '%s'", header.name);
- return ( FALSE);
- }
- buffer[link_size] = '\0';
- strncpy(header.linkname, buffer, sizeof(header.linkname));
+ strncpy(header.linkname, lpath, sizeof(header.linkname));
+ free(lpath);
} else if (S_ISDIR(statbuf->st_mode)) {
header.typeflag = DIRTYPE;
strncat(header.name, "/", sizeof(header.name));