aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2019-11-22 12:48:35 -0800
committerRob Landley <rob@landley.net>2019-11-23 09:57:24 -0600
commite028208e53fb94c7c6c2873a116f680e234784ec (patch)
tree98ef0fe2cbcf392fe28847f9596aa8f6a41592a1
parent41dd4878451806ff3b27b9739fc77c0d34037883 (diff)
downloadtoybox-e028208e53fb94c7c6c2873a116f680e234784ec.tar.gz
Fix dev_minor()/dev_major()/dev_makedev() for Mac.
Major/minor device encoding is not portable. No two BSDs agree with each other, and Darwin is different again. Everyone does agree on having major()/minor()/makedev() macros, but they disagree whether they should be in <sys/types.h> (the BSDs including Darwin, and old versions of glibc) or <sys/sysmacros.h> (glibc >= 2.26 and bionic). This fixes `ls -l /dev/zero` and `stat /dev/zero` on Mac.
-rw-r--r--lib/lib.c15
-rw-r--r--lib/lib.h3
-rw-r--r--lib/portability.c33
-rw-r--r--lib/portability.h5
4 files changed, 38 insertions, 18 deletions
diff --git a/lib/lib.c b/lib/lib.c
index 3bfee2ef..2250caf4 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -1213,21 +1213,6 @@ char *next_printf(char *s, char **start)
return 0;
}
-int dev_minor(int dev)
-{
- return ((dev&0xfff00000)>>12)|(dev&0xff);
-}
-
-int dev_major(int dev)
-{
- return (dev&0xfff00)>>8;
-}
-
-int dev_makedev(int major, int minor)
-{
- return (minor&0xff)|((major&0xfff)<<8)|((minor&0xfff00)<<12);
-}
-
// Return cached passwd entries.
struct passwd *bufgetpwuid(uid_t uid)
{
diff --git a/lib/lib.h b/lib/lib.h
index f3eacb9d..8f949096 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -255,9 +255,6 @@ int qstrcmp(const void *a, const void *b);
void create_uuid(char *uuid);
char *show_uuid(char *uuid);
char *next_printf(char *s, char **start);
-int dev_minor(int dev);
-int dev_major(int dev);
-int dev_makedev(int major, int minor);
struct passwd *bufgetpwuid(uid_t uid);
struct group *bufgetgrgid(gid_t gid);
int readlinkat0(int dirfd, char *path, char *buf, int len);
diff --git a/lib/portability.c b/lib/portability.c
index 0b5677cc..ae862c97 100644
--- a/lib/portability.c
+++ b/lib/portability.c
@@ -515,3 +515,36 @@ char *num_to_sig(int sig)
return NULL;
}
+
+int dev_minor(int dev)
+{
+#if defined(__linux__)
+ return ((dev&0xfff00000)>>12)|(dev&0xff);
+#elif defined(__APPLE__)
+ return dev&0xffffff;
+#else
+#error
+#endif
+}
+
+int dev_major(int dev)
+{
+#if defined(__linux__)
+ return (dev&0xfff00)>>8;
+#elif defined(__APPLE__)
+ return (dev>>24)&0xff;
+#else
+#error
+#endif
+}
+
+int dev_makedev(int major, int minor)
+{
+#if defined(__linux__)
+ return (minor&0xff)|((major&0xfff)<<8)|((minor&0xfff00)<<12);
+#elif defined(__APPLE__)
+ return (minor&0xffffff)|((major&0xff)<<24);
+#else
+#error
+#endif
+}
diff --git a/lib/portability.h b/lib/portability.h
index 481e3f04..24cd1297 100644
--- a/lib/portability.h
+++ b/lib/portability.h
@@ -350,3 +350,8 @@ struct signame {
char *name;
};
void xsignal_all_killers(void *handler);
+
+// Different OSes encode major/minor device numbers differently.
+int dev_minor(int dev);
+int dev_major(int dev);
+int dev_makedev(int major, int minor);