aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2016-06-15 15:47:01 -0500
committerRob Landley <rob@landley.net>2016-06-15 15:47:01 -0500
commit46409d50e5632b28b88cfa4991fffef9adaa490d (patch)
tree4c3347b37664b580996e4551bde023346567728b
parent97ddc600c95623bf803eac4f2a4deda2a2db02d4 (diff)
downloadtoybox-46409d50e5632b28b88cfa4991fffef9adaa490d.tar.gz
Add readlink0() and readlinkat0() which null terminate the data.
-rw-r--r--lib/lib.c20
-rw-r--r--lib/lib.h2
-rw-r--r--toys/other/lspci.c6
-rw-r--r--toys/other/pwdx.c14
-rw-r--r--toys/other/stat.c2
-rw-r--r--toys/posix/cp.c3
-rw-r--r--toys/posix/ps.c14
7 files changed, 34 insertions, 27 deletions
diff --git a/lib/lib.c b/lib/lib.c
index 66814a45..b742bd17 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -444,7 +444,8 @@ off_t fdlength(int fd)
// Read contents of file as a single nul-terminated string.
// measure file size if !len, allocate buffer if !buf
-// note: for existing buffers use len = size-1, will set buf[len] = 0
+// Existing buffers need len in *plen
+// Returns amount of data read in *plen
char *readfileat(int dirfd, char *name, char *ibuf, off_t *plen)
{
off_t len, rlen;
@@ -1130,3 +1131,20 @@ struct group *bufgetgrgid(gid_t gid)
return &list->gr;
}
+
+// Always null terminates, returns 0 for failure, len for success
+int readlinkat0(int dirfd, char *path, char *buf, int len)
+{
+ if (!len) return 0;
+
+ len = readlinkat(dirfd, path, buf, len-1);
+ if (len<1) return 0;
+ buf[len] = 0;
+
+ return len;
+}
+
+int readlink0(char *path, char *buf, int len)
+{
+ return readlinkat0(AT_FDCWD, path, buf, len);
+}
diff --git a/lib/lib.h b/lib/lib.h
index f545a794..3088f252 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -207,6 +207,8 @@ int dev_major(int dev);
int dev_makedev(int major, int minor);
struct passwd *bufgetpwuid(uid_t uid);
struct group *bufgetgrgid(gid_t gid);
+int readlinkat0(int dirfd, char *path, char *buf, int len);
+int readlink0(char *path, char *buf, int len);
#define HR_SPACE 1 // Space between number and units
#define HR_B 2 // Use "B" for single byte units
diff --git a/toys/other/lspci.c b/toys/other/lspci.c
index 077ce757..a0671791 100644
--- a/toys/other/lspci.c
+++ b/toys/other/lspci.c
@@ -50,10 +50,9 @@ static int do_lspci(struct dirtree *new)
if (-1 == (dirfd = openat(dirtree_parentfd(new), new->name, O_RDONLY)))
return 0;
- // it's ok for the driver link not to be there, whatever fortify says
*driver = 0;
if (toys.optflags & FLAG_k)
- if (readlinkat(dirfd, "driver", driver, sizeof(driver))) {};
+ readlinkat0(dirfd, "driver", driver, sizeof(driver));
for (fields = (char*[]){"class", "vendor", "device", 0}; *fields; fields++) {
int fd, size = 6 + 2*((toys.optflags & FLAG_e) && p == toybuf);
@@ -122,8 +121,7 @@ void lspci_main(void)
{
if (CFG_LSPCI_TEXT && TT.numeric != 1) {
if (!TT.ids) TT.ids = "/usr/share/misc/pci.ids";
- if (!(TT.db = fopen(TT.ids, "r")))
- perror_msg("could not open PCI ID db");
+ if (!(TT.db = fopen(TT.ids, "r"))) perror_msg("%s", TT.ids);
}
dirtree_read("/sys/bus/pci/devices", do_lspci);
diff --git a/toys/other/pwdx.c b/toys/other/pwdx.c
index bde16e79..2a72dba3 100644
--- a/toys/other/pwdx.c
+++ b/toys/other/pwdx.c
@@ -20,20 +20,14 @@ void pwdx_main(void)
char **optargs;
for (optargs = toys.optargs; *optargs; optargs++) {
- char *path;
- int num_bytes;
+ char *path = toybuf;
- path = xmprintf("/proc/%s/cwd", *optargs);
- num_bytes = readlink(path, toybuf, sizeof(toybuf)-1);
- free(path);
-
- if (num_bytes==-1) {
+ sprintf(toybuf, "/proc/%d/cwd", atoi(*optargs));
+ if (!readlink0(path, toybuf, sizeof(toybuf))) {
path = strerror(errno);
toys.exitval = 1;
- } else {
- path = toybuf;
- toybuf[num_bytes] = 0;
}
+
xprintf("%s: %s\n", *optargs, path);
}
}
diff --git a/toys/other/stat.c b/toys/other/stat.c
index 9f77a600..7a6b38d7 100644
--- a/toys/other/stat.c
+++ b/toys/other/stat.c
@@ -110,7 +110,7 @@ static void print_stat(char type)
} else if (type == 'N') {
xprintf("`%s'", TT.file);
if (S_ISLNK(stat->st_mode))
- if (0<readlink(TT.file, toybuf, sizeof(toybuf)))
+ if (readlink0(TT.file, toybuf, sizeof(toybuf)))
xprintf(" -> `%s'", toybuf);
} else if (type == 'o') out('u', stat->st_blksize);
else if (type == 's') out('u', stat->st_size);
diff --git a/toys/posix/cp.c b/toys/posix/cp.c
index 77e7f132..eafabcd1 100644
--- a/toys/posix/cp.c
+++ b/toys/posix/cp.c
@@ -251,8 +251,7 @@ int cp_node(struct dirtree *try)
// make symlink, or make block/char/fifo/socket
if (S_ISLNK(try->st.st_mode)
- ? (0 < (i = readlinkat(tfd, try->name, toybuf, sizeof(toybuf))) &&
- sizeof(toybuf) > i && !(toybuf[i] = '\0') &&
+ ? ((i = readlinkat0(tfd, try->name, toybuf, sizeof(toybuf))) &&
!symlinkat(toybuf, cfd, catch))
: !mknodat(cfd, catch, try->st.st_mode, try->st.st_rdev))
{
diff --git a/toys/posix/ps.c b/toys/posix/ps.c
index 8ac6eef7..773f40c4 100644
--- a/toys/posix/ps.c
+++ b/toys/posix/ps.c
@@ -751,9 +751,8 @@ static int get_ps(struct dirtree *new)
if (TT.threadparent && TT.threadparent->extra)
ptb = (void *)TT.threadparent->extra;
- if (j==3 && !ptb) {
- if ((len = readlinkat(fd, buf, buf, len))<1) len = 0;
- } else {
+ if (j==3 && !ptb) len = readlinkat0(fd, buf, buf, len);
+ else {
if (j==3) i = strlen(s = ptb->str+ptb->offset[3]);
else {
if (!ptb || tb->slot[SLOT_argv0len]) ptb = tb;
@@ -766,8 +765,8 @@ static int get_ps(struct dirtree *new)
}
if (i<len) len = i;
memcpy(buf, s, len);
+ buf[len] = 0;
}
- buf[len] = 0;
// If it's not the TTY field, data we want is in a file.
// Last length saved in slot[] is command line (which has embedded NULs)
@@ -782,11 +781,8 @@ static int get_ps(struct dirtree *new)
for (i = 0; i<3; i++) {
sprintf(buf, "%lld/fd/%i", *slot, i);
if (!fstatat(fd, buf, &st, 0) && S_ISCHR(st.st_mode)
- && st.st_rdev == rdev && 0<(len = readlinkat(fd, buf, buf, len)))
- {
- buf[len] = 0;
- break;
- }
+ && st.st_rdev == rdev && (len = readlinkat0(fd, buf, buf, len)))
+ break;
}
// Couldn't find it, try all the tty drivers.