]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/guid_to_name.c
Backport from BEE
[bacula/bacula] / bacula / src / lib / guid_to_name.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2014 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from many
7    others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    Bacula® is a registered trademark of Kern Sibbald.
15 */
16 /*
17  * Written by Kern Sibbald, July 2007 to replace idcache.c
18  *
19  *  Program to convert uid and gid into names, and cache the results
20  *   for preformance reasons.
21  *
22  */
23
24 #include "bacula.h"
25
26 #ifndef WIN32
27 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
28 #endif
29
30 struct guitem {
31    dlink link;
32    char *name;
33    union {
34       uid_t uid;
35       gid_t gid;
36    };
37 };
38
39
40 guid_list *new_guid_list()
41 {
42    guid_list *list;
43    guitem *item = NULL;
44    list = (guid_list *)malloc(sizeof(guid_list));
45    list->uid_list = New(dlist(item, &item->link));
46    list->gid_list = New(dlist(item, &item->link));
47    return list;
48 }
49
50 void free_guid_list(guid_list *list)
51 {
52    guitem *item;
53    foreach_dlist(item, list->uid_list) {
54       free(item->name);
55    }
56    foreach_dlist(item, list->gid_list) {
57       free(item->name);
58    }
59    delete list->uid_list;
60    delete list->gid_list;
61    free(list);
62 }
63
64 static int uid_compare(void *item1, void *item2)
65 {
66    guitem *i1 = (guitem *)item1;
67    guitem *i2 = (guitem *)item2;
68    if (i1->uid < i2->uid) {
69       return -1;
70    } else if (i1->uid > i2->uid) {
71       return 1;
72    } else {
73       return 0;
74    }
75 }
76
77 static int gid_compare(void *item1, void *item2)
78 {
79    guitem *i1 = (guitem *)item1;
80    guitem *i2 = (guitem *)item2;
81    if (i1->gid < i2->gid) {
82       return -1;
83    } else if (i1->gid > i2->gid) {
84       return 1;
85    } else {
86       return 0;
87    }
88 }
89
90
91 static void get_uidname(uid_t uid, guitem *item)
92 {
93 #ifndef HAVE_WIN32
94    struct passwd *pwbuf;
95    P(mutex);
96    pwbuf = getpwuid(uid);
97    if (pwbuf != NULL && strcmp(pwbuf->pw_name, "????????") != 0) {
98       item->name = bstrdup(pwbuf->pw_name);
99    }
100    V(mutex);
101 #endif
102 }
103
104 static void get_gidname(gid_t gid, guitem *item)
105 {
106 #ifndef HAVE_WIN32
107    struct group *grbuf;
108    P(mutex);
109    grbuf = getgrgid(gid);
110    if (grbuf != NULL && strcmp(grbuf->gr_name, "????????") != 0) {
111       item->name = bstrdup(grbuf->gr_name);
112    }
113    V(mutex);
114 #endif
115 }
116
117
118 char *guid_list::uid_to_name(uid_t uid, char *name, int maxlen)
119 {
120    guitem sitem, *item, *fitem;
121    sitem.uid = uid;
122    char buf[50];
123
124    item = (guitem *)uid_list->binary_search(&sitem, uid_compare);
125    Dmsg2(900, "uid=%d item=%p\n", uid, item);
126    if (!item) {
127       item = (guitem *)malloc(sizeof(guitem));
128       item->uid = uid;
129       item->name = NULL;
130       get_uidname(uid, item);
131       if (!item->name) {
132          item->name = bstrdup(edit_int64(uid, buf));
133          Dmsg2(900, "set uid=%d name=%s\n", uid, item->name);
134       }
135       fitem = (guitem *)uid_list->binary_insert(item, uid_compare);
136       if (fitem != item) {               /* item already there this shouldn't happen */
137          free(item->name);
138          free(item);
139          item = fitem;
140       }
141    }
142    bstrncpy(name, item->name, maxlen);
143    return name;
144 }
145
146 char *guid_list::gid_to_name(gid_t gid, char *name, int maxlen)
147 {
148    guitem sitem, *item, *fitem;
149    sitem.gid = gid;
150    char buf[50];
151
152    item = (guitem *)gid_list->binary_search(&sitem, gid_compare);
153    if (!item) {
154       item = (guitem *)malloc(sizeof(guitem));
155       item->gid = gid;
156       item->name = NULL;
157       get_gidname(gid, item);
158       if (!item->name) {
159          item->name = bstrdup(edit_int64(gid, buf));
160       }
161       fitem = (guitem *)gid_list->binary_insert(item, gid_compare);
162       if (fitem != item) {               /* item already there this shouldn't happen */
163          free(item->name);
164          free(item);
165          item = fitem;
166       }
167    }
168
169    bstrncpy(name, item->name, maxlen);
170    return name;
171 }
172
173 #ifdef TEST_PROGRAM
174
175 int main()
176 {
177    int i;
178    guid_list *list;
179    char ed1[50], ed2[50];
180    list = new_guid_list();
181    for (i=0; i<1001; i++) {
182       printf("uid=%d name=%s  gid=%d name=%s\n", i, list->uid_to_name(i, ed1, sizeof(ed1)),
183          i, list->gid_to_name(i, ed2, sizeof(ed2)));
184       printf("uid=%d name=%s  gid=%d name=%s\n", i, list->uid_to_name(i, ed1, sizeof(ed1)),
185          i, list->gid_to_name(i, ed2, sizeof(ed2)));
186    }
187
188    free_guid_list(list);
189    sm_dump(false);     /* unit test */
190
191    return 0;
192 }
193
194 #endif