1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2007-2011 Kern Sibbald
5 
6    This program is Free Software; you can redistribute it and/or
7    modify it under the terms of version three of the GNU Affero General Public
8    License as published by the Free Software Foundation, which is
9    listed in the file LICENSE.
10 
11    This program is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14    Affero General Public License for more details.
15 
16    You should have received a copy of the GNU Affero General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19    02110-1301, USA.
20 */
21 /*
22  * Written by Kern Sibbald, July 2007 to replace idcache.c
23  *
24  * Program to convert uid and gid into names, and cache the results
25  * for preformance reasons.
26  */
27 
28 #include "include/bareos.h"
29 #include "lib/edit.h"
30 #include "lib/dlist.h"
31 
32 #ifndef WIN32
33 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
34 #endif
35 
36 struct guitem {
37   dlink link;
38   char* name;
39   union {
40     uid_t uid;
41     gid_t gid;
42   };
43 };
44 
45 
new_guid_list()46 guid_list* new_guid_list()
47 {
48   guid_list* list;
49   guitem* item = NULL;
50   list = (guid_list*)malloc(sizeof(guid_list));
51   list->uid_list = new dlist(item, &item->link);
52   list->gid_list = new dlist(item, &item->link);
53   return list;
54 }
55 
FreeGuidList(guid_list * list)56 void FreeGuidList(guid_list* list)
57 {
58   guitem* item;
59   foreach_dlist (item, list->uid_list) {
60     free(item->name);
61   }
62   foreach_dlist (item, list->gid_list) {
63     free(item->name);
64   }
65   delete list->uid_list;
66   delete list->gid_list;
67   free(list);
68 }
69 
UidCompare(void * item1,void * item2)70 static int UidCompare(void* item1, void* item2)
71 {
72   guitem* i1 = (guitem*)item1;
73   guitem* i2 = (guitem*)item2;
74   if (i1->uid < i2->uid) {
75     return -1;
76   } else if (i1->uid > i2->uid) {
77     return 1;
78   } else {
79     return 0;
80   }
81 }
82 
GidCompare(void * item1,void * item2)83 static int GidCompare(void* item1, void* item2)
84 {
85   guitem* i1 = (guitem*)item1;
86   guitem* i2 = (guitem*)item2;
87   if (i1->gid < i2->gid) {
88     return -1;
89   } else if (i1->gid > i2->gid) {
90     return 1;
91   } else {
92     return 0;
93   }
94 }
95 
96 
GetUidname(uid_t uid,guitem * item)97 static void GetUidname(uid_t uid, guitem* item)
98 {
99 #ifndef HAVE_WIN32
100   struct passwd* pwbuf;
101   P(mutex);
102   pwbuf = getpwuid(uid);
103   if (pwbuf != NULL && !bstrcmp(pwbuf->pw_name, "????????")) {
104     item->name = strdup(pwbuf->pw_name);
105   }
106   V(mutex);
107 #endif
108 }
109 
GetGidname(gid_t gid,guitem * item)110 static void GetGidname(gid_t gid, guitem* item)
111 {
112 #ifndef HAVE_WIN32
113   struct group* grbuf;
114   P(mutex);
115   grbuf = getgrgid(gid);
116   if (grbuf != NULL && !bstrcmp(grbuf->gr_name, "????????")) {
117     item->name = strdup(grbuf->gr_name);
118   }
119   V(mutex);
120 #endif
121 }
122 
123 
uid_to_name(uid_t uid,char * name,int maxlen)124 char* guid_list::uid_to_name(uid_t uid, char* name, int maxlen)
125 {
126   guitem sitem, *item, *fitem;
127   sitem.uid = uid;
128   char buf[50];
129 
130   item = (guitem*)uid_list->binary_search(&sitem, UidCompare);
131   Dmsg2(900, "uid=%d item=%p\n", uid, item);
132   if (!item) {
133     item = (guitem*)malloc(sizeof(guitem));
134     item->uid = uid;
135     item->name = NULL;
136     GetUidname(uid, item);
137     if (!item->name) {
138       item->name = strdup(edit_int64(uid, buf));
139       Dmsg2(900, "set uid=%d name=%s\n", uid, item->name);
140     }
141     fitem = (guitem*)uid_list->binary_insert(item, UidCompare);
142     if (fitem != item) { /* item already there this shouldn't happen */
143       free(item->name);
144       free(item);
145       item = fitem;
146     }
147   }
148   bstrncpy(name, item->name, maxlen);
149   return name;
150 }
151 
gid_to_name(gid_t gid,char * name,int maxlen)152 char* guid_list::gid_to_name(gid_t gid, char* name, int maxlen)
153 {
154   guitem sitem, *item, *fitem;
155   sitem.gid = gid;
156   char buf[50];
157 
158   item = (guitem*)gid_list->binary_search(&sitem, GidCompare);
159   if (!item) {
160     item = (guitem*)malloc(sizeof(guitem));
161     item->gid = gid;
162     item->name = NULL;
163     GetGidname(gid, item);
164     if (!item->name) { item->name = strdup(edit_int64(gid, buf)); }
165     fitem = (guitem*)gid_list->binary_insert(item, GidCompare);
166     if (fitem != item) { /* item already there this shouldn't happen */
167       free(item->name);
168       free(item);
169       item = fitem;
170     }
171   }
172 
173   bstrncpy(name, item->name, maxlen);
174   return name;
175 }
176