I understand that unix user IDs (UIDs) are usually 16 or 32 bit unsigned integers but how can I find out for any given system (in a shell)?
4 Answers
You'll need to look in <limits.h> (or one of the files it includes, e.g., sys/syslimits.h on OS X) for the #define of UID_MAX.
Most recent operating systems (Solaris 2.x, OS X, BSD, Linux, HP-UX 11i, AIX 6) can handle up to two billion (2^31-2), so I would assume that and make a workaround for the more obscure systems that don't.
-
2Unfortunately, there is no such thing as
UID_MAX. For example, tools fromshadow-utilsuse(uid_t)-1to find out the max value for UID.kirelagin– kirelagin2014-03-30 09:12:26 +00:00Commented Mar 30, 2014 at 9:12 -
5Most systems use /etc/login.defs which does have UID_MAX set for the highest usable UID value, 60000 on any system I've checked.Ryaner– Ryaner2014-08-05 11:21:39 +00:00Commented Aug 5, 2014 at 11:21
-
7The manpage for
login.defsindicates that in that context,UID_MAXonly controls the highest uid that will automatically be assigned for new users created withuseradd.Stephen Touset– Stephen Touset2015-01-26 19:34:21 +00:00Commented Jan 26, 2015 at 19:34 -
2It's probably 2^32 (4 billion instead of 2). On RHEL UID 4,294,967,295 (2^32-1) is often reserved for an "invalid value" UID, and 4,294,967,294 (2^32-2) is reserved for the nfsnobody user in some operating systems. Thus the max non-reserved value is 4,294,967,293 (2^32-3)tehnicaorg– tehnicaorg2018-09-22 22:06:02 +00:00Commented Sep 22, 2018 at 22:06
-
Link to one of many examples of
(uid_t)-1in shadow-utils: github.com/shadow-maint/shadow/blob/…pevik– pevik2022-10-31 11:28:33 +00:00Commented Oct 31, 2022 at 11:28
glibc provides definitions for all those system types.
You can check /usr/include/bits/typesizes.h:
% grep UID_T /usr/include/bits/typesizes.h
#define __UID_T_TYPE __U32_TYPE
Next you look into /usr/include/bits/types.h:
% grep '#define __U32_TYPE' /usr/include/bits/types.h
#define __U32_TYPE unsigned int
This lets you find out the C type. Since you need the size in bytes, your best option is parsing the typedef name according to the specification in types.h:
We define __S<SIZE>_TYPE and __U<SIZE>_TYPE for the signed and unsigned
variants of each of the following integer types on this machine.
16 -- "natural" 16-bit type (always short)
32 -- "natural" 32-bit type (always int)
64 -- "natural" 64-bit type (long or long long)
LONG32 -- 32-bit type, traditionally long
QUAD -- 64-bit type, always long long
WORD -- natural type of __WORDSIZE bits (int or long)
LONGWORD -- type of __WORDSIZE bits, traditionally long
So, here is a one-liner:
% grep '#define __UID_T_TYPE' /usr/include/bits/typesizes.h | cut -f 3 | sed -r 's/__([US])([^_]*)_.*/\1 \2/'
U 32
Here U means unsigned (this can also be S for signed) and 32 is the size (look it up in the list above; I think, most of the time you can assume that that's already size in bytes, but if you want your script to be fully portable it might be better to do case switch on this value).
-
1On my system (Ubuntu 12.04) and other Debian based systems the header file is:
/usr/include/$(gcc -print-multiarch)/bits/typesizes.hor alternatively:/usr/include/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/bits/typesizes.hpabouk - Ukraine stay strong– pabouk - Ukraine stay strong2014-07-07 19:03:21 +00:00Commented Jul 7, 2014 at 19:03 -
1Having those glibc files would probably mean that there is a compiler available. So one could #include <sys/types.h> to have access to uid_t and print the result ( printf("uid_t: %d bytes (%d bits)\n", sizeof(uid_t), sizeof(uid_t) * 8); )tehnicaorg– tehnicaorg2018-09-22 22:10:12 +00:00Commented Sep 22, 2018 at 22:10
In this link the question is asked and a responder uses a trial & error method to determine the system in question uses a signed long int, leaving 31 bits to store the value, with a max of 2,147,483,647.
# groupadd -g 42949672950 testgrp
# more /etc/group
testgrp:*:2147483647:
That's an interesting question. I'd be surprised if there was a standard, portable method to determine this.
I don't have a Linux box handy, but the id command on FreeBSD 8.0 wraps back to zero:
# id 4294967296
uid=0(root) gid=0(wheel) groups=0(wheel),5(operator)
I'm sure this is undefined behavior, but I'd wager that most versions of id would either wrap to zero with 65'536 (if 16-bit UID) and 4'294'967'296 or error out if you went beyond the system limit.