Move the lone hashFunctionString() into misc.[ch], eliminate rpmhash.[ch]
[platform/upstream/rpm.git] / lib / misc.c
1 /**
2  * \file lib/misc.c
3  */
4
5 #include "system.h"
6
7 #include <pwd.h>
8 #include <grp.h>
9 #include <rpm/rpmlog.h>
10 #include <rpm/rpmstring.h>
11
12 #include "lib/misc.h"
13 #include "debug.h"
14
15 /* just to put a marker in librpm.a */
16 const char * const RPMVERSION = VERSION;
17
18 unsigned int hashFunctionString(const char * string)
19 {
20     /* Jenkins One-at-a-time hash */
21     unsigned int hash = 0xe4721b68;
22
23     while (*string != '\0') {
24       hash += *string;
25       hash += (hash << 10);
26       hash ^= (hash >> 6);
27       string++;
28     }
29     hash += (hash << 3);
30     hash ^= (hash >> 11);
31     hash += (hash << 15);
32     return hash;
33 }
34
35 /* unameToUid(), uidTouname() and the group variants are really poorly
36    implemented. They really ought to use hash tables. I just made the
37    guess that most files would be owned by root or the same person/group
38    who owned the last file. Those two values are cached, everything else
39    is looked up via getpw() and getgr() functions.  If this performs
40    too poorly I'll have to implement it properly :-( */
41
42 int unameToUid(const char * thisUname, uid_t * uid)
43 {
44 static char * lastUname = NULL;
45     static size_t lastUnameLen = 0;
46     static size_t lastUnameAlloced;
47     static uid_t lastUid;
48     struct passwd * pwent;
49     size_t thisUnameLen;
50
51     if (!thisUname) {
52         lastUnameLen = 0;
53         return -1;
54     } else if (rstreq(thisUname, "root")) {
55         *uid = 0;
56         return 0;
57     }
58
59     thisUnameLen = strlen(thisUname);
60     if (lastUname == NULL || thisUnameLen != lastUnameLen ||
61         !rstreq(thisUname, lastUname))
62     {
63         if (lastUnameAlloced < thisUnameLen + 1) {
64             lastUnameAlloced = thisUnameLen + 10;
65             lastUname = xrealloc(lastUname, lastUnameAlloced);  /* XXX memory leak */
66         }
67         strcpy(lastUname, thisUname);
68
69         pwent = getpwnam(thisUname);
70         if (pwent == NULL) {
71             /* FIX: shrug */
72             endpwent();
73             pwent = getpwnam(thisUname);
74             if (pwent == NULL) return -1;
75         }
76
77         lastUid = pwent->pw_uid;
78     }
79
80     *uid = lastUid;
81
82     return 0;
83 }
84
85 int gnameToGid(const char * thisGname, gid_t * gid)
86 {
87 static char * lastGname = NULL;
88     static size_t lastGnameLen = 0;
89     static size_t lastGnameAlloced;
90     static gid_t lastGid;
91     size_t thisGnameLen;
92     struct group * grent;
93
94     if (thisGname == NULL) {
95         lastGnameLen = 0;
96         return -1;
97     } else if (rstreq(thisGname, "root")) {
98         *gid = 0;
99         return 0;
100     }
101
102     thisGnameLen = strlen(thisGname);
103     if (lastGname == NULL || thisGnameLen != lastGnameLen ||
104         !rstreq(thisGname, lastGname))
105     {
106         if (lastGnameAlloced < thisGnameLen + 1) {
107             lastGnameAlloced = thisGnameLen + 10;
108             lastGname = xrealloc(lastGname, lastGnameAlloced);  /* XXX memory leak */
109         }
110         strcpy(lastGname, thisGname);
111
112         grent = getgrnam(thisGname);
113         if (grent == NULL) {
114             /* FIX: shrug */
115             endgrent();
116             grent = getgrnam(thisGname);
117             if (grent == NULL) {
118                 /* XXX The filesystem package needs group/lock w/o getgrnam. */
119                 if (rstreq(thisGname, "lock")) {
120                     *gid = lastGid = 54;
121                     return 0;
122                 } else
123                 if (rstreq(thisGname, "mail")) {
124                     *gid = lastGid = 12;
125                     return 0;
126                 } else
127                 return -1;
128             }
129         }
130         lastGid = grent->gr_gid;
131     }
132
133     *gid = lastGid;
134
135     return 0;
136 }
137
138 const char * uidToUname(uid_t uid)
139 {
140     static uid_t lastUid = (uid_t) -1;
141 static char * lastUname = NULL;
142     static size_t lastUnameLen = 0;
143
144     if (uid == (uid_t) -1) {
145         lastUid = (uid_t) -1;
146         return NULL;
147     } else if (uid == (uid_t) 0) {
148         return "root";
149     } else if (uid == lastUid) {
150         return lastUname;
151     } else {
152         struct passwd * pwent = getpwuid(uid);
153         size_t len;
154
155         if (pwent == NULL) return NULL;
156
157         lastUid = uid;
158         len = strlen(pwent->pw_name);
159         if (lastUnameLen < len + 1) {
160             lastUnameLen = len + 20;
161             lastUname = xrealloc(lastUname, lastUnameLen);
162         }
163         strcpy(lastUname, pwent->pw_name);
164
165         return lastUname;
166     }
167 }
168
169 const char * gidToGname(gid_t gid)
170 {
171     static gid_t lastGid = (gid_t) -1;
172 static char * lastGname = NULL;
173     static size_t lastGnameLen = 0;
174
175     if (gid == (gid_t) -1) {
176         lastGid = (gid_t) -1;
177         return NULL;
178     } else if (gid == (gid_t) 0) {
179         return "root";
180     } else if (gid == lastGid) {
181         return lastGname;
182     } else {
183         struct group * grent = getgrgid(gid);
184         size_t len;
185
186         if (grent == NULL) return NULL;
187
188         lastGid = gid;
189         len = strlen(grent->gr_name);
190         if (lastGnameLen < len + 1) {
191             lastGnameLen = len + 20;
192             lastGname = xrealloc(lastGname, lastGnameLen);
193         }
194         strcpy(lastGname, grent->gr_name);
195
196         return lastGname;
197     }
198 }