[Toybox] [PATCH] fix dmesg default size/level filtering/performance

enh enh at google.com
Mon Nov 24 17:26:06 PST 2014


* the kernel buffer hasn't defaulted to 16KiB for a very long time.
i'm not sure why the original code said < 2 rather than <= 0 (or 1KiB,
say), but i've left that as it was.

* there's also a bug with the filtering out of level markers; they can
be more than one digit. (this is true of all kernels, not just Android
ones.)

* finally, the use of xputc for every character makes the toybox dmesg
human-noticeably slow. writing line at a time is orders of magnitude
faster/fewer syscalls.

here's the patch, which attempts to imitate your style:

diff --git a/generated/help.h b/generated/help.h
index 6c017cf..1a44a37 100644
--- a/generated/help.h
+++ b/generated/help.h
@@ -54,7 +54,7 @@

 #define help_hostname "usage: hostname [newname]\n\nGet/Set the
current hostname\n\n"

-#define help_dmesg "usage: dmesg [-n level] [-s bufsize] |
-c\n\nPrint or control the kernel ring buffer.\n\n-n Set kernel
logging level (1-9).\n-s Size of buffer to read (in bytes), default
16384.\n-c Clear the ring buffer after printing.\n\n"
+#define help_dmesg "usage: dmesg [-n level] [-s bufsize] |
-c\n\nPrint or control the kernel ring buffer.\n\n-n Set kernel
logging level (1-9).\n-s Size of buffer to read (in bytes), default
kernel buffer size.\n-c Clear the ring buffer after printing.\n\n"

 #define help_yes "usage: yes [args...]\n\nRepeatedly output line
until killed. If no args, output 'y'.\n\n\n"

diff --git a/toys/lsb/dmesg.c b/toys/lsb/dmesg.c
index 1003256..d4a2b66 100644
--- a/toys/lsb/dmesg.c
+++ b/toys/lsb/dmesg.c
@@ -15,7 +15,7 @@ config DMESG
     Print or control the kernel ring buffer.

     -n Set kernel logging level (1-9).
-    -s Size of buffer to read (in bytes), default 16384.
+    -s Size of buffer to read (in bytes), default kernel buffer size.
     -c Clear the ring buffer after printing.
 */

@@ -34,22 +34,34 @@ void dmesg_main(void)
   if (toys.optflags & 2) {
     if (klogctl(8, NULL, TT.level)) error_exit("klogctl");
   } else {
-    int size, i, last = '\n';
-    char *data;
+    int size, i;
+    char *data, *end;

     // Figure out how much data we need, and fetch it.
     size = TT.size;
-    if (size<2) size = 16384;
+    if (size < 2) size = klogctl(10, 0, 0); // SYSLOG_ACTION_SIZE_BUFFER.
+    if (size < 0) size = 16384;
     data = xmalloc(size);
     size = klogctl(3 + (toys.optflags&1), data, size);
     if (size < 0) error_exit("klogctl");

-    // Display data, filtering out level markers.
+    // Display data, filtering out level markers (<\d+>).
     for (i=0; i<size; ) {
-      if (last=='\n' && data[i]=='<') i += 3;
-      else xputc(last = data[i++]);
+      if (data[i]=='<') {
+        end = strchr(data+i, '>');
+        if (end) i = end-data+1;
+      } else {
+        end = strchr(data+i, '\n');
+        if (end) {
+          xwrite(1, data+i, end-(data+i)+1);
+          i += end - (data+i) + 1;
+        } else {
+          xwrite(1, data+i, size-i);
+          xputc('\n');
+          i = size;
+        }
+      }
     }
-    if (last!='\n') xputc('\n');
     if (CFG_TOYBOX_FREE) free(data);
   }
 }

i'm assuming no one actually cares about the old Android "implicit -r"
behavior. if i get a complaint, adding -r is trivial. (once i learn
how to add an option at all :-) )

 1416878766.0


More information about the Toybox mailing list