root/maint/gnulib/tests/test-userspec.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. maybe_null
  2. same_diag
  3. main

   1 /* Test userspec.c
   2    Copyright (C) 2009-2021 Free Software Foundation, Inc.
   3 
   4    This program is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU General Public License as published by
   6    the Free Software Foundation; either version 3 of the License, or
   7    (at your option) any later version.
   8 
   9    This program is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU General Public License for more details.
  13 
  14    You should have received a copy of the GNU General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 /* Written by Jim Meyering.  */
  18 
  19 #include <config.h>
  20 
  21 #include "userspec.h"
  22 
  23 #include <stdio.h>
  24 #include <assert.h>
  25 #include <string.h>
  26 #include <stdlib.h>
  27 #include <stdbool.h>
  28 #include <sys/types.h>
  29 #include <pwd.h>
  30 #include <grp.h>
  31 
  32 #include "xalloc.h"
  33 
  34 #define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array))
  35 
  36 struct test
  37 {
  38   const char *in;
  39   uid_t uid;
  40   gid_t gid;
  41   const char *user_name;
  42   const char *group_name;
  43   const char *result;
  44 };
  45 
  46 static struct test T[] =
  47   {
  48     { "",                       -1, -1, "",   "",   NULL},
  49     { ":",                      -1, -1, "",   "",   NULL},
  50     { "+0:+0",                   0,  0, "",   "",   NULL},
  51     { ":+1",                    -1,  1, "",   "",   NULL},
  52     { "+1",                      1, -1, "",   "",   NULL},
  53     { ":+0",                    -1,  0, "",   "",   NULL},
  54     { "+22:+42",                22, 42, "",   "",   NULL},
  55     /* (uint32_t)-1 should be invalid everywhere */
  56     { "+4294967295:+4294967295", 0,  0, NULL, NULL, "invalid user"},
  57     /* likewise, but with only the group being invalid */
  58     { "+0:+4294967295",          0,  0, NULL, NULL, "invalid group"},
  59     { ":+4294967295",            0,  0, NULL, NULL, "invalid group"},
  60     /* and only the user being invalid */
  61     { "+4294967295:+0",          0,  0, NULL, NULL, "invalid user"},
  62     /* and using 2^32 */
  63     { "+4294967296:+4294967296", 0,  0, NULL, NULL, "invalid user"},
  64     { "+0:+4294967296",          0,  0, NULL, NULL, "invalid group"},
  65     { ":+4294967296",            0,  0, NULL, NULL, "invalid group"},
  66     { "+4294967296:+0",          0,  0, NULL, NULL, "invalid user"},
  67     /* numeric user and no group is invalid */
  68     { "+4294967295:",            0,  0, NULL, NULL, "invalid spec"},
  69     { "+4294967296:",            0,  0, NULL, NULL, "invalid spec"},
  70     { "+1:",                     0,  0, NULL, NULL, "invalid spec"},
  71     { "+0:",                     0,  0, NULL, NULL, "invalid spec"},
  72 
  73     /* "username:" must expand to UID:GID where GID is username's login group */
  74     /* Add an entry like the following to the table, if possible.
  75     { "U_NAME:",              UID,GID, U_NAME, G_NAME, NULL}, */
  76     { NULL,                     0,  0, NULL, NULL, ""},  /* place-holder */
  77 
  78     { NULL,                     0,  0, NULL, NULL, ""}
  79   };
  80 
  81 #define STREQ(a, b) (strcmp (a, b) == 0)
  82 
  83 static char const *
  84 maybe_null (char const *s)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86   return s ? s : "NULL";
  87 }
  88 
  89 static bool
  90 same_diag (char const *s, char const *t)
     /* [previous][next][first][last][top][bottom][index][help] */
  91 {
  92   if (s == NULL && t == NULL)
  93     return true;
  94   if (s == NULL || t == NULL)
  95     return false;
  96   return STREQ (s, t);
  97 }
  98 
  99 int
 100 main (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102   unsigned int i;
 103   int fail = 0;
 104 
 105   /* Find a UID that has both a user name and login group name,
 106      but skip UID 0.  */
 107   {
 108     uid_t uid;
 109     for (uid = 1200; 0 < uid; uid--)
 110       {
 111         struct group *gr;
 112         struct passwd *pw = getpwuid (uid);
 113         unsigned int j;
 114         size_t len;
 115         if (!pw || !pw->pw_name || !(gr = getgrgid (pw->pw_gid)) || !gr->gr_name)
 116           continue;
 117         j = ARRAY_CARDINALITY (T) - 2;
 118         assert (T[j].in == NULL);
 119         assert (T[j+1].in == NULL);
 120         len = strlen (pw->pw_name);
 121 
 122         /* Store "username:" in T[j].in.  */
 123         {
 124           char *t = xmalloc (len + 1 + 1);
 125           memcpy (t, pw->pw_name, len);
 126           t[len] = ':';
 127           t[len+1] = '\0';
 128           T[j].in = t;
 129         }
 130 
 131         T[j].uid = uid;
 132         T[j].gid = gr->gr_gid;
 133         T[j].user_name = xstrdup (pw->pw_name);
 134         T[j].group_name = xstrdup (gr->gr_name);
 135         T[j].result = NULL;
 136         break;
 137       }
 138   }
 139 
 140   for (i = 0; T[i].in; i++)
 141     {
 142       uid_t uid = (uid_t) -1;
 143       gid_t gid = (gid_t) -1;
 144       char *user_name;
 145       char *group_name;
 146       char const *diag = parse_user_spec (T[i].in, &uid, &gid,
 147                                           &user_name, &group_name);
 148       free (user_name);
 149       free (group_name);
 150       if (!same_diag (diag, T[i].result))
 151         {
 152           printf ("%s return value mismatch: got %s, expected %s\n",
 153                   T[i].in, maybe_null (diag), maybe_null (T[i].result));
 154           fail = 1;
 155           continue;
 156         }
 157 
 158       if (diag)
 159         continue;
 160 
 161       if (uid != T[i].uid || gid != T[i].gid)
 162         {
 163           printf ("%s mismatch (-: expected uid,gid; +:actual)\n"
 164                   "-%3lu,%3lu\n+%3lu,%3lu\n",
 165                   T[i].in,
 166                   (unsigned long int) T[i].uid,
 167                   (unsigned long int) T[i].gid,
 168                   (unsigned long int) uid,
 169                   (unsigned long int) gid);
 170           fail = 1;
 171         }
 172 
 173       if (!T[i].result)
 174         continue;
 175 
 176       /* Expected a non-NULL result diagnostic, yet got NULL.  */
 177       diag = "NULL";
 178       printf ("%s diagnostic mismatch (-: expected diagnostic; +:actual)\n"
 179               "-%s\n+%s\n", T[i].in, T[i].result, diag);
 180       fail = 1;
 181     }
 182 
 183   /* Ensure NULL parameters are ignored.  */
 184   {
 185     uid_t uid = (uid_t) -1;
 186     char const *diag = parse_user_spec ("", &uid, NULL, NULL, NULL);
 187     if (diag)
 188       {
 189         printf ("unexpected error: %s\n", diag);
 190         fail = 1;
 191       }
 192   }
 193 
 194   return fail;
 195 }
 196 
 197 /*
 198 Local Variables:
 199 indent-tabs-mode: nil
 200 End:
 201 */

/* [previous][next][first][last][top][bottom][index][help] */