[CentOS] Determine next UID number

Wed Oct 13 21:16:47 UTC 2010
Spiro Harvey <spiro at knossos.net.nz>

John Kennedy <skebi69 at gmail.com> wrote:
> This also does not tell me how useradd knows that on this system at
> this time the highest UID assigned to a user is 20015. 

From the source's mouth (this is from useradd.c in the shadow-utils package):

/*
 * find_new_uid - find the next available UID
 *
 *      find_new_uid() locates the next highest unused UID in the password
 *      file, or checks the given user ID against the existing ones for
 *      uniqueness.
 */
static void find_new_uid (void)
{
        const struct passwd *pwd;
        uid_t uid_min, uid_max;

        uid_min = getdef_unum ("UID_MIN", 1000);
        uid_max = getdef_unum ("UID_MAX", 60000);

        /*
         * Start with some UID value if the user didn't provide us with
         * one already.
         */
        if (!uflg)
                user_id = uid_min;

        /*
         * Search the entire password file, either looking for this
         * UID (if the user specified one with -u) or looking for the
         * largest unused value.
         */
#ifdef NO_GETPWENT
        pw_rewind ();
        while ((pwd = pw_next ())) {
#else                           /* using getpwent() we can check against NIS users etc. */
        setpwent ();
        while ((pwd = getpwent ())) {
#endif
                if (strcmp (user_name, pwd->pw_name) == 0) {
                        fprintf (stderr, _("%s: name %s is not unique\n"),
                                 Prog, user_name);
#ifdef WITH_AUDIT
                        audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "adding user",
                                      user_name, user_id, 0);
#endif
                        exit (E_NAME_IN_USE);
                }
                if (uflg && user_id == pwd->pw_uid) {
                        fprintf (stderr, _("%s: UID %u is not unique\n"),
                                 Prog, (unsigned int) user_id);
#ifdef WITH_AUDIT
                        audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "adding user",
                                      user_name, user_id, 0);
#endif
                        exit (E_UID_IN_USE);
                }
                if (!uflg && pwd->pw_uid >= user_id) {
                        if (pwd->pw_uid > uid_max)
                                continue;
                        user_id = pwd->pw_uid + 1;
                }
        }

        /*
         * If a user with UID equal to UID_MAX exists, the above algorithm
         * will give us UID_MAX+1 even if not unique. Search for the first
         * free UID starting with UID_MIN (it's O(n*n) but can be avoided
         * by not having users with UID equal to UID_MAX).  --marekm
         */
        if (!uflg && user_id == uid_max + 1) {
                for (user_id = uid_min; user_id < uid_max; user_id++) {
#ifdef NO_GETPWENT
                        pw_rewind ();
                        while ((pwd = pw_next ())
                               && pwd->pw_uid != user_id);
                        if (!pwd)
                                break;
#else
                        if (!getpwuid (user_id))
                                break;
#endif
                }
                if (user_id == uid_max) {
                        fprintf (stderr, _("%s: can't get unique UID\n"), Prog);
                        fail_exit (E_UID_IN_USE);
                }
        }
}



-- 
Spiro Harvey                  Knossos Networks Ltd
021-295-1923                  www.knossos.net.nz
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 197 bytes
Desc: not available
URL: <http://lists.centos.org/pipermail/centos/attachments/20101014/387df904/attachment-0004.sig>