В Fri, 16 Sep 2011 18:06:15 +0300
Roman Yeryomin <leroi.li...@gmail.com> пишет:

> On 16 September 2011 17:51, Alexander Gordeev <lasa...@lvk.cs.msu.su> wrote:
> > В Fri, 16 Sep 2011 17:41:37 +0300
> > Roman Yeryomin <leroi.li...@gmail.com> пишет:
> >
> >> On 16 September 2011 01:40, Alexander Gordeev <lasa...@lvk.cs.msu.su> 
> >> wrote:
> >> > В Fri, 26 Aug 2011 04:30:43 +0300
> >> > Roman Yeryomin <leroi.li...@gmail.com> пишет:
> >> >
> >> >> This method is much more stable than reading dd's output via stdin.
> >> >
> >> > What kind of problems do you have with piping dd's output to stdin?
> >> >
> >>
> >> It outputs garbage very frequently and maccalc fails to convert the
> >> mac (and as a consequence uci-default script fails to set the real mac
> >> address). Try dd without piping to maccalc and you'll see.
> >> I've noticed this bug on ramips platform and can't say anything about
> >> other boards.
> >
> > Well, then this is probably a bug in dd? Or uClibc? Or kernel?
> > Ok, I'll try to reproduce it. Can you please tell me what exactly is
> > happening?
> >
> 
> Two different reads:
> root@OpenWrt:/# dd bs=1 skip=262148 count=6 if=/dev/mtd0
> "u�������6+0 records in
> 6+0 records out
> root@OpenWrt:/# dd bs=1 skip=262148 count=6 if=/dev/mtd0
> "u���6+0 records in
> 6+0 records out
> 
> I don't think this is the bug in dd/kernel/uclibc - it would probably
> expose when writing to a file too.
> Maybe it's something with busybox. I'm not sure of cause.

The bug is in maccalc. It does a single read() and expects to get
everything in one shot which doesn't happen sometimes. The patch is
attached. It fixes the problem according to my tests.

I don't know whether Roman's change is necessary anymore. What do you
think, Roman?

-- 
  Alexander
From ae35ee0ce9fc9b6cb5d8bea0a5a059df71602eab Mon Sep 17 00:00:00 2001
From: Alexander Gordeev <lasa...@lvk.cs.msu.su>
Date: Sun, 18 Sep 2011 21:43:12 +0400
Subject: [PATCH] maccalc: don't expect to get all data in one read

Signed-off-by: Alexander Gordeev <lasa...@lvk.cs.msu.su>
---
 package/maccalc/src/main.c |   31 ++++++++++++++++++++++++++++++-
 1 files changed, 30 insertions(+), 1 deletions(-)

diff --git a/package/maccalc/src/main.c b/package/maccalc/src/main.c
index e1e12cd..dcb5f55 100644
--- a/package/maccalc/src/main.c
+++ b/package/maccalc/src/main.c
@@ -9,6 +9,7 @@
  *
  */
 
+#include <errno.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdint.h>
@@ -124,6 +125,34 @@ static int maccalc_do_mac2bin(int argc, const char *argv[])
 	return 0;
 }
 
+static ssize_t read_safe(int fd, void *buf, size_t count)
+{
+	ssize_t total = 0;
+	ssize_t r;
+
+	while(count > 0) {
+		r = read(fd, buf, count);
+		if (r == 0)
+			/* EOF */
+			break;
+		if (r < 0) {
+			if (errno == EINTR)
+				/* interrupted by a signal, restart */
+				continue;
+			/* error */
+			total = -1;
+			break;
+		}
+
+		/* ok */
+		total += r;
+		count -= r;
+		buf += r;
+	}
+
+	return total;
+}
+
 static int maccalc_do_bin2mac(int argc, const char *argv[])
 {
 	unsigned char mac[MAC_ADDRESS_LEN];
@@ -134,7 +163,7 @@ static int maccalc_do_bin2mac(int argc, const char *argv[])
 		return ERR_INVALID;
 	}
 
-	c = read(STDIN_FILENO, mac, sizeof(mac));
+	c = read_safe(STDIN_FILENO, mac, sizeof(mac));
 	if (c != sizeof(mac)) {
 		fprintf(stderr, "failed to read from stdin\n");
 		return ERR_IO;
-- 
1.7.5.4

Attachment: signature.asc
Description: PGP signature

_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to