fix building w/ABIs that have broken stat structures

If the system's stat buffer is broken and doesn't declare st_dev as a
dev_t, we hit a build failure when we try to pass it into a func that
expects a dev_t.

Add some checks to handle this case.  It produces the same code on sane
ABIs, so other than ugliness, it should be fine.

BUG=chromium:358419
TEST=`emerge-link rootdev` produces same code
TEST=`emerge-daisy rootdev` produces same code
TEST=`emerge-mipsel-o32-generic rootdev` now works

Change-Id: I956436e0c40318c8f2ac61b2e202ec739132c245
Reviewed-on: https://chromium-review.googlesource.com/192550
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Commit-Queue: Mike Frysinger <vapier@chromium.org>
Tested-by: Mike Frysinger <vapier@chromium.org>
diff --git a/rootdev.c b/rootdev.c
index 76c931c..ea88b39 100644
--- a/rootdev.c
+++ b/rootdev.c
@@ -404,16 +404,28 @@
 
 int rootdev(char *path, size_t size, bool full, bool strip) {
   struct stat root_statbuf;
+  dev_t _root_dev, *root_dev = &_root_dev;
 
   /* Yields the containing dev_t in st_dev. */
   if (stat("/", &root_statbuf) != 0)
     return -1;
 
+  /* Some ABIs (like mips o32) are broken and the st_dev field isn't actually
+   * a dev_t.  In that case, pass a pointer to a local dev_t who we took care
+   * of truncating the value into.  On sane arches, gcc can optimize this to
+   * the same code, so should only be a penalty when the ABI is broken. */
+  if (sizeof(root_statbuf.st_dev) == sizeof(*root_dev)) {
+    /* Cast is OK since we verified size here. */
+    root_dev = (dev_t *)&root_statbuf.st_dev;
+  } else {
+    *root_dev = root_statbuf.st_dev;
+  }
+
   return rootdev_wrapper(path,
                          size,
                          full,
                          strip,
-                         &root_statbuf.st_dev,
+                         root_dev,
                          NULL,  /* default /sys dir */
                          NULL);  /* default /dev dir */
 }