(root)/
util-linux-2.39/
lib/
idcache.c
       1  /*
       2   * No copyright is claimed.  This code is in the public domain; do with
       3   * it what you wish.
       4   *
       5   * Written by Karel Zak <kzak@redhat.com>
       6   */
       7  #include <wchar.h>
       8  #include <pwd.h>
       9  #include <grp.h>
      10  #include <sys/types.h>
      11  
      12  #include "c.h"
      13  #include "idcache.h"
      14  
      15  struct identry *get_id(struct idcache *ic, unsigned long int id)
      16  {
      17  	struct identry *ent;
      18  
      19  	if (!ic)
      20  		return NULL;
      21  
      22  	for (ent = ic->ent; ent; ent = ent->next) {
      23  		if (ent->id == id)
      24  			return ent;
      25  	}
      26  
      27  	return NULL;
      28  }
      29  
      30  struct idcache *new_idcache(void)
      31  {
      32  	return calloc(1, sizeof(struct idcache));
      33  }
      34  
      35  void free_idcache(struct idcache *ic)
      36  {
      37  	struct identry *ent = ic->ent;
      38  
      39  	while (ent) {
      40  		struct identry *next = ent->next;
      41  		free(ent->name);
      42  		free(ent);
      43  		ent = next;
      44  	}
      45  
      46  	free(ic);
      47  }
      48  
      49  static void add_id(struct idcache *ic, char *name, unsigned long int id)
      50  {
      51  	struct identry *ent, *x;
      52  	int w = 0;
      53  
      54  	ent = calloc(1, sizeof(struct identry));
      55  	if (!ent)
      56  		return;
      57  	ent->id = id;
      58  
      59  	if (name) {
      60  #ifdef HAVE_WIDECHAR
      61  		wchar_t wc[LOGIN_NAME_MAX + 1];
      62  
      63  		if (mbstowcs(wc, name, LOGIN_NAME_MAX) > 0) {
      64  			wc[LOGIN_NAME_MAX] = '\0';
      65  			w = wcswidth(wc, LOGIN_NAME_MAX);
      66  		}
      67  		else
      68  #endif
      69  			w = strlen(name);
      70  	}
      71  
      72  	/* note, we ignore names with non-printable widechars */
      73  	if (w > 0) {
      74  		ent->name = strdup(name);
      75  		if (!ent->name) {
      76  			free(ent);
      77  			return;
      78  		}
      79  	} else {
      80  		if (asprintf(&ent->name, "%lu", id) < 0) {
      81  			free(ent);
      82  			return;
      83  		}
      84  	}
      85  
      86  	for (x = ic->ent; x && x->next; x = x->next);
      87  
      88  	if (x)
      89  		x->next = ent;
      90  	else
      91  		ic->ent = ent;
      92  
      93  	if (w <= 0)
      94  		w = ent->name ? strlen(ent->name) : 0;
      95  	ic->width = ic->width < w ? w : ic->width;
      96  }
      97  
      98  void add_uid(struct idcache *cache, unsigned long int id)
      99  {
     100  	struct identry *ent = get_id(cache, id);
     101  
     102  	if (!ent) {
     103  		struct passwd *pw = getpwuid((uid_t) id);
     104  		add_id(cache, pw ? pw->pw_name : NULL, id);
     105  	}
     106  }
     107  
     108  void add_gid(struct idcache *cache, unsigned long int id)
     109  {
     110  	struct identry *ent = get_id(cache, id);
     111  
     112  	if (!ent) {
     113  		struct group *gr = getgrgid((gid_t) id);
     114  		add_id(cache, gr ? gr->gr_name : NULL, id);
     115  	}
     116  }
     117