Only update resolv.conf if changed (avoid logspam)
authorSteven Barth <steven@midlink.org>
Tue, 19 Feb 2013 08:36:23 +0000 (09:36 +0100)
committerSteven Barth <steven@midlink.org>
Tue, 19 Feb 2013 08:36:23 +0000 (09:36 +0100)
interface-ip.c
utils.c
utils.h

index df2904faf3eb3e76ac376b03f0182a4ee2215b0b..fc5a4a3aabfae0b945cd2f4a69b1963e57cfa1c8 100644 (file)
@@ -781,10 +781,11 @@ interface_write_resolv_conf(void)
        struct interface *iface;
        char *path = alloca(strlen(resolv_conf) + 5);
        FILE *f;
+       uint32_t crcold, crcnew;
 
        sprintf(path, "%s.tmp", resolv_conf);
        unlink(path);
-       f = fopen(path, "w");
+       f = fopen(path, "w+");
        if (!f) {
                D(INTERFACE, "Failed to open %s for writing\n", path);
                return;
@@ -805,8 +806,21 @@ interface_write_resolv_conf(void)
                if (!iface->proto_ip.no_dns)
                        write_resolv_conf_entries(f, &iface->proto_ip);
        }
+       fflush(f);
+       rewind(f);
+       crcnew = crc32_file(f);
        fclose(f);
-       if (rename(path, resolv_conf) < 0) {
+
+       crcold = crcnew + 1;
+       f = fopen(resolv_conf, "r");
+       if (f) {
+               crcold = crc32_file(f);
+               fclose(f);
+       }
+
+       if (crcold == crcnew) {
+               unlink(path);
+       } else if (rename(path, resolv_conf) < 0) {
                D(INTERFACE, "Failed to replace %s\n", resolv_conf);
                unlink(path);
        }
diff --git a/utils.c b/utils.c
index 14e966a49f8052dbe6a2727987aa54ff238fe80b..6b53c229190686b69bf7d8401843bcd720dd5dbf 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -140,3 +140,31 @@ format_macaddr(uint8_t *mac)
 
        return str;
 }
+
+uint32_t
+crc32_file(FILE *fp)
+{
+       static uint32_t *crcvals = NULL;
+       if (!crcvals) {
+               crcvals = malloc(sizeof(*crcvals) * 256);
+
+               for (size_t i = 0; i < 256; ++i) {
+                       uint32_t c = i;
+                       for (size_t j = 0; j < 8; ++j)
+                               c = (c & 1) ? (0xEDB88320 ^ (c >> 1)) : (c >> 1);
+                       crcvals[i] = c;
+               }
+       }
+
+       uint8_t buf[1024];
+       size_t len;
+       uint32_t c = 0xFFFFFFFF;
+
+       do {
+               len = fread(buf, 1, sizeof(buf), fp);
+               for (size_t i = 0; i < len; ++i)
+                       c = crcvals[(c ^ buf[i]) & 0xFF] ^ (c >> 8);
+       } while (len == sizeof(buf));
+
+       return c ^ 0xFFFFFFFF;
+}
diff --git a/utils.h b/utils.h
index d675a5c780450f7f0d1739e5b252cabe07e7e8ba..3a8e557063be53dfd52d591c37fc2134a2f5a778 100644 (file)
--- a/utils.h
+++ b/utils.h
@@ -14,6 +14,7 @@
 #ifndef __NETIFD_UTILS_H
 #define __NETIFD_UTILS_H
 
+#include <stdio.h>
 #include <libubox/list.h>
 #include <libubox/avl.h>
 #include <libubox/avl-cmp.h>
@@ -109,6 +110,8 @@ int parse_ip_and_netmask(int af, const char *str, void *addr, unsigned int *netm
 
 char * format_macaddr(uint8_t *mac);
 
+uint32_t crc32_file(FILE *fp);
+
 #ifdef __APPLE__
 #define s6_addr32      __u6_addr.__u6_addr32
 #endif