@@ -1174,7 +1174,7 @@ int rtnl_listen(struct rtnl_handle *rtnl,
int rtnl_from_file(FILE *rtnl, rtnl_listen_filter_t handler,
void *jarg)
{
- int status;
+ size_t status;
char buf[16384];
struct nlmsghdr *h = (struct nlmsghdr *)buf;
@@ -1184,14 +1184,15 @@ int rtnl_from_file(FILE *rtnl, rtnl_listen_filter_t handler,
status = fread(&buf, 1, sizeof(*h), rtnl);
- if (status < 0) {
- if (errno == EINTR)
- continue;
- perror("rtnl_from_file: fread");
+ if (status == 0 && feof(rtnl))
+ return 0;
+ if (status != sizeof(*h)) {
+ if (ferror(rtnl))
+ perror("rtnl_from_file: fread");
+ if (feof(rtnl))
+ fprintf(stderr, "rtnl-from_file: truncated message\n");
return -1;
}
- if (status == 0)
- return 0;
len = h->nlmsg_len;
l = len - sizeof(*h);
@@ -1204,12 +1205,11 @@ int rtnl_from_file(FILE *rtnl, rtnl_listen_filter_t handler,
status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl);
- if (status < 0) {
- perror("rtnl_from_file: fread");
- return -1;
- }
- if (status < l) {
- fprintf(stderr, "rtnl-from_file: truncated message\n");
+ if (status != NLMSG_ALIGN(l)) {
+ if (ferror(rtnl))
+ perror("rtnl_from_file: fread");
+ if (feof(rtnl))
+ fprintf(stderr, "rtnl-from_file: truncated message\n");
return -1;
}
@@ -3329,28 +3329,28 @@ static int tcp_show_netlink_file(struct filter *f)
}
while (1) {
- int status, err2;
+ int err2;
+ size_t status, nitems;
struct nlmsghdr *h = (struct nlmsghdr *)buf;
struct sockstat s = {};
status = fread(buf, 1, sizeof(*h), fp);
- if (status < 0) {
- perror("Reading header from $TCPDIAG_FILE");
- break;
- }
if (status != sizeof(*h)) {
- perror("Unexpected EOF reading $TCPDIAG_FILE");
+ if (ferror(fp))
+ perror("Reading header from $TCPDIAG_FILE");
+ if (feof(fp))
+ fprintf(stderr, "Unexpected EOF reading $TCPDIAG_FILE");
break;
}
- status = fread(h+1, 1, NLMSG_ALIGN(h->nlmsg_len-sizeof(*h)), fp);
+ nitems = NLMSG_ALIGN(h->nlmsg_len - sizeof(*h));
+ status = fread(h+1, 1, nitems, fp);
- if (status < 0) {
- perror("Reading $TCPDIAG_FILE");
- break;
- }
- if (status + sizeof(*h) < h->nlmsg_len) {
- perror("Unexpected EOF reading $TCPDIAG_FILE");
+ if (status != nitems) {
+ if (ferror(fp))
+ perror("Reading $TCPDIAG_FILE");
+ if (feof(fp))
+ fprintf(stderr, "Unexpected EOF reading $TCPDIAG_FILE");
break;
}
fread(3) returns size_t data type which is unsigned, thus check `if (fread(...) < 0)' is always false. To check if fread(3) has failed, user should check error indicator with ferror(3). This commit also changes read logic a little bit by being less forgiving for errors. Previous logic was checking if fread(3) read *at least* required ammount of data, now code checks if fread(3) read *exactly* expected ammount of data. This makes sense because code parses very specific binary file, and reading even 1 less/more byte than expected, will later corrupt data anyway. Signed-off-by: Michał Łyszczek <michal.lyszczek@bofc.pl> --- v1 -> v2: fread(3) can also return error on truncated reads and not only on 0bytes read (suggested by Stephen Hemminger) --- lib/libnetlink.c | 26 +++++++++++++------------- misc/ss.c | 26 +++++++++++++------------- 2 files changed, 26 insertions(+), 26 deletions(-)