OSDN Git Service

Add readlink0() and readlinkat0() which null terminate the data.
authorRob Landley <rob@landley.net>
Wed, 15 Jun 2016 20:47:01 +0000 (15:47 -0500)
committerRob Landley <rob@landley.net>
Wed, 15 Jun 2016 20:47:01 +0000 (15:47 -0500)
lib/lib.c
lib/lib.h
toys/other/lspci.c
toys/other/pwdx.c
toys/other/stat.c
toys/posix/cp.c
toys/posix/ps.c

index 66814a4..b742bd1 100644 (file)
--- 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);
+}
index f545a79..3088f25 100644 (file)
--- 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
index 077ce75..a067179 100644 (file)
@@ -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);
index bde16e7..2a72dba 100644 (file)
@@ -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);
   }
 }
index 9f77a60..7a6b38d 100644 (file)
@@ -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);
index 77e7f13..eafabcd 100644 (file)
@@ -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))
         {
index 8ac6eef..773f40c 100644 (file)
@@ -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.