]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/guid_to_name.c
Remove double include of sellist.h
[bacula/bacula] / bacula / src / lib / guid_to_name.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2011 Kern Sibbald
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation, which is 
11    listed in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  * Written by Kern Sibbald, July 2007 to replace idcache.c
30  * 
31  *  Program to convert uid and gid into names, and cache the results
32  *   for preformance reasons.
33  *
34  */
35
36 #include "bacula.h"
37
38 #ifndef WIN32
39 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
40 #endif
41
42 struct guitem {
43    dlink link;
44    char *name;
45    union {
46       uid_t uid;
47       gid_t gid;
48    };
49 };
50
51
52 guid_list *new_guid_list()
53 {
54    guid_list *list;
55    guitem *item = NULL;
56    list = (guid_list *)malloc(sizeof(guid_list));
57    list->uid_list = New(dlist(item, &item->link));
58    list->gid_list = New(dlist(item, &item->link));
59    return list;
60 }
61
62 void free_guid_list(guid_list *list)
63 {
64    guitem *item;
65    foreach_dlist(item, list->uid_list) {
66       free(item->name);
67    }
68    foreach_dlist(item, list->gid_list) {
69       free(item->name);
70    }
71    delete list->uid_list;
72    delete list->gid_list;
73    free(list);
74 }
75
76 static int uid_compare(void *item1, void *item2)
77 {
78    guitem *i1 = (guitem *)item1;
79    guitem *i2 = (guitem *)item2;
80    if (i1->uid < i2->uid) {
81       return -1;
82    } else if (i1->uid > i2->uid) {
83       return 1;
84    } else {
85       return 0;
86    }
87 }
88
89 static int gid_compare(void *item1, void *item2)
90 {
91    guitem *i1 = (guitem *)item1;
92    guitem *i2 = (guitem *)item2;
93    if (i1->gid < i2->gid) {
94       return -1;
95    } else if (i1->gid > i2->gid) {
96       return 1;
97    } else {
98       return 0;
99    }
100 }
101
102
103 static void get_uidname(uid_t uid, guitem *item)
104 {
105 #ifndef HAVE_WIN32
106    struct passwd *pwbuf;
107    P(mutex);
108    pwbuf = getpwuid(uid);
109    if (pwbuf != NULL && strcmp(pwbuf->pw_name, "????????") != 0) {
110       item->name = bstrdup(pwbuf->pw_name);
111    }
112    V(mutex);
113 #endif
114 }
115
116 static void get_gidname(gid_t gid, guitem *item)
117 {
118 #ifndef HAVE_WIN32
119    struct group *grbuf;
120    P(mutex);
121    grbuf = getgrgid(gid);
122    if (grbuf != NULL && strcmp(grbuf->gr_name, "????????") != 0) {
123       item->name = bstrdup(grbuf->gr_name);
124    }
125    V(mutex);
126 #endif
127 }
128
129
130 char *guid_list::uid_to_name(uid_t uid, char *name, int maxlen)
131 {
132    guitem sitem, *item, *fitem;
133    sitem.uid = uid;
134    char buf[50];
135
136    item = (guitem *)uid_list->binary_search(&sitem, uid_compare);
137    Dmsg2(900, "uid=%d item=%p\n", uid, item);
138    if (!item) {
139       item = (guitem *)malloc(sizeof(guitem));
140       item->uid = uid;
141       item->name = NULL;
142       get_uidname(uid, item);
143       if (!item->name) {
144          item->name = bstrdup(edit_int64(uid, buf));
145          Dmsg2(900, "set uid=%d name=%s\n", uid, item->name);
146       }
147       fitem = (guitem *)uid_list->binary_insert(item, uid_compare);
148       if (fitem != item) {               /* item already there this shouldn't happen */
149          free(item->name);
150          free(item);
151          item = fitem;   
152       }
153    }
154    bstrncpy(name, item->name, maxlen);
155    return name;
156 }
157
158 char *guid_list::gid_to_name(gid_t gid, char *name, int maxlen)
159 {
160    guitem sitem, *item, *fitem;
161    sitem.gid = gid;
162    char buf[50];
163
164    item = (guitem *)gid_list->binary_search(&sitem, gid_compare);
165    if (!item) {
166       item = (guitem *)malloc(sizeof(guitem));
167       item->gid = gid;
168       item->name = NULL;
169       get_gidname(gid, item);
170       if (!item->name) {
171          item->name = bstrdup(edit_int64(gid, buf));
172       }
173       fitem = (guitem *)gid_list->binary_insert(item, gid_compare);
174       if (fitem != item) {               /* item already there this shouldn't happen */
175          free(item->name);
176          free(item);
177          item = fitem;   
178       }
179    }
180
181    bstrncpy(name, item->name, maxlen);
182    return name;
183 }
184
185 #ifdef TEST_PROGRAM
186
187 int main()
188 {
189    int i;
190    guid_list *list;
191    char ed1[50], ed2[50];
192    list = new_guid_list();
193    for (i=0; i<1001; i++) {
194       printf("uid=%d name=%s  gid=%d name=%s\n", i, list->uid_to_name(i, ed1, sizeof(ed1)),
195          i, list->gid_to_name(i, ed2, sizeof(ed2)));
196       printf("uid=%d name=%s  gid=%d name=%s\n", i, list->uid_to_name(i, ed1, sizeof(ed1)),
197          i, list->gid_to_name(i, ed2, sizeof(ed2)));
198    }
199     
200    free_guid_list(list);
201    sm_dump(false);     /* unit test */
202
203    return 0;
204 }
205  
206 #endif