diff toys/pending/lspci.c @ 969:a47c6658210c

lspci: use toybuf instead of dynamic memory allocation
author Felix Janda <felix.janda@posteo.de>
date Fri, 26 Jul 2013 22:49:05 -0500
parents b2b4bd208b65
children f84dd3473233
line wrap: on
line diff
--- a/toys/pending/lspci.c	Fri Jul 26 15:41:31 2013 -0500
+++ b/toys/pending/lspci.c	Fri Jul 26 22:49:05 2013 -0500
@@ -1,75 +1,65 @@
 /*
  * lspci - written by Isaac Dunham
 
-USE_LSPCI(NEWTOY(lspci, "emkn", TOYFLAG_USR|TOYFLAG_BIN))
+USE_LSPCI(NEWTOY(lspci, "emkns:", TOYFLAG_USR|TOYFLAG_BIN))
 
 config LSPCI
   bool "lspci"
   default n
   help
-    usage: lspci [-ekmn] 
+    usage: lspci [-ekmn]
 
     List PCI devices.
-    -e  Output all 6 digits in class (like elspci)
+    -e  Print all 6 digits in class (like elspci)
     -k  Print kernel driver
     -m  Machine parseable format
     -n  Numeric output (default)
 */
 #define FOR_lspci
 #include "toys.h"
-char * preadat_name(int dirfd, char *fname, size_t nbyte, off_t offset)
-{
-  int fd;
-  char *buf = malloc(nbyte+1);
-  memset(buf, 0, sizeof(buf));
-  fd = openat(dirfd, fname, O_RDONLY);
-  if (fd < 0) {
-    return NULL;
-  }
-  lseek(fd, offset, SEEK_SET);
-  read(fd, buf, nbyte);
-  close(fd);
-  buf[nbyte +1] = '\0';
-  return buf;
-}
 
 int do_lspci(struct dirtree *new)
 {
-  int alen = 8;
+  int alen = 8, dirfd;
   char *dname = dirtree_path(new, &alen);
+  struct {
+    char class[16], vendor[16], device[16], module[256];
+  } *bufs = (void*)(toybuf + 2);
+
+  if (!strcmp("/sys/bus/pci/devices", dname)) return DIRTREE_RECURSE;
   errno = 0;
-  int dirfd = open(dname, O_RDONLY);
+  dirfd = open(dname, O_RDONLY);
   if (dirfd > 0) {
-    char *class = preadat_name(dirfd, "class",
-                (toys.optflags & FLAG_e) ? 6 :4, 2);
-    char *vendor = preadat_name(dirfd, "vendor", 4, 2);
-    char *device = preadat_name(dirfd, "device", 4, 2);
+    char *p, **fields = (char*[]){"class", "vendor", "device", ""};
+
+    for (p = toybuf; **fields; p+=16, fields++) {
+      int fd, size;
+
+      if ((fd = openat(dirfd, *fields, O_RDONLY)) < 0) continue;
+      size = 6 + 2*((toys.optflags & FLAG_e) && (p != toybuf));
+      p[read(fd, p, size)] = '\0';
+      close(fd);
+    }
+
     close(dirfd);
     if (!errno) {
       char *driver = "";
+      char *fmt = toys.optflags & FLAG_m ? "%s, \"%s\" \"%s\" \"%s\" \"%s\"\n"
+                                                   : "%s Class %s: %s:%s %s\n";
+
       if (toys.optflags & FLAG_k) {
-        char module[256] = "";
         strcat(dname, "/driver");
-        readlink(dname, module, sizeof(module));
-        driver = basename(module);
+        if (readlink(dname, bufs->module, sizeof(bufs->module)) != -1)
+          driver = basename(bufs->module);
       }
-      if (toys.optflags & FLAG_m) {
-        printf("%s, \"%s\" \"%s\" \"%s\" \"%s\"\n",new->name + 5, class, 
-               vendor, device, driver);
-      } else {
-        printf("%s Class %s: %s:%s %s\n", new->name + 5, class, vendor, device, 
+      printf(fmt, new->name + 5, bufs->class, bufs->vendor, bufs->device, 
                driver);
-      }
     }
   }
-  if (!strcmp("/sys/bus/pci/devices", new->name)) {
-    return DIRTREE_RECURSE;
-  }
   return 0;
 }
 
 void lspci_main(void)
 {
-  sprintf(toybuf, "/sys/bus/pci/devices");
-  dirtree_read(toybuf, do_lspci);
+  dirtree_read("/sys/bus/pci/devices", do_lspci);
 }