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