rpm/lib/rpmug.c

203 lines
4.3 KiB
C

#include "system.h"
#include <pwd.h>
#include <grp.h>
#include <rpm/rpmlog.h>
#include <rpm/rpmstring.h>
#include "lib/misc.h"
#include "lib/rpmug.h"
#include "debug.h"
#define HASHTYPE strCache
#define HTKEYTYPE const char *
#include "lib/rpmhash.H"
#include "lib/rpmhash.C"
#undef HASHTYPE
#undef HTKEYTYPE
static strCache strStash = NULL;
const char * rpmugStashStr(const char *str)
{
const char *ret = NULL;
if (str) {
if (strStash == NULL) {
strStash = strCacheCreate(64, rstrhash, strcmp,
(strCacheFreeKey)rfree);
}
if (!strCacheGetEntry(strStash, str, &ret)) {
strCacheAddEntry(strStash, xstrdup(str));
(void) strCacheGetEntry(strStash, str, &ret);
}
}
return ret;
}
/*
* These really ought to use hash tables. I just made the
* guess that most files would be owned by root or the same person/group
* who owned the last file. Those two values are cached, everything else
* is looked up via getpw() and getgr() functions. If this performs
* too poorly I'll have to implement it properly :-(
*/
int rpmugUid(const char * thisUname, uid_t * uid)
{
static char * lastUname = NULL;
static size_t lastUnameLen = 0;
static size_t lastUnameAlloced;
static uid_t lastUid;
struct passwd * pwent;
size_t thisUnameLen;
if (!thisUname) {
lastUnameLen = 0;
return -1;
} else if (rstreq(thisUname, "root")) {
*uid = 0;
return 0;
}
thisUnameLen = strlen(thisUname);
if (lastUname == NULL || thisUnameLen != lastUnameLen ||
!rstreq(thisUname, lastUname))
{
if (lastUnameAlloced < thisUnameLen + 1) {
lastUnameAlloced = thisUnameLen + 10;
lastUname = xrealloc(lastUname, lastUnameAlloced); /* XXX memory leak */
}
strcpy(lastUname, thisUname);
pwent = getpwnam(thisUname);
if (pwent == NULL) {
/* FIX: shrug */
endpwent();
pwent = getpwnam(thisUname);
if (pwent == NULL) return -1;
}
lastUid = pwent->pw_uid;
}
*uid = lastUid;
return 0;
}
int rpmugGid(const char * thisGname, gid_t * gid)
{
static char * lastGname = NULL;
static size_t lastGnameLen = 0;
static size_t lastGnameAlloced;
static gid_t lastGid;
size_t thisGnameLen;
struct group * grent;
if (thisGname == NULL) {
lastGnameLen = 0;
return -1;
} else if (rstreq(thisGname, "root")) {
*gid = 0;
return 0;
}
thisGnameLen = strlen(thisGname);
if (lastGname == NULL || thisGnameLen != lastGnameLen ||
!rstreq(thisGname, lastGname))
{
if (lastGnameAlloced < thisGnameLen + 1) {
lastGnameAlloced = thisGnameLen + 10;
lastGname = xrealloc(lastGname, lastGnameAlloced); /* XXX memory leak */
}
strcpy(lastGname, thisGname);
grent = getgrnam(thisGname);
if (grent == NULL) {
/* FIX: shrug */
endgrent();
grent = getgrnam(thisGname);
if (grent == NULL) {
return -1;
}
}
lastGid = grent->gr_gid;
}
*gid = lastGid;
return 0;
}
const char * rpmugUname(uid_t uid)
{
static uid_t lastUid = (uid_t) -1;
static char * lastUname = NULL;
static size_t lastUnameLen = 0;
if (uid == (uid_t) -1) {
lastUid = (uid_t) -1;
return NULL;
} else if (uid == (uid_t) 0) {
return "root";
} else if (uid == lastUid) {
return lastUname;
} else {
struct passwd * pwent = getpwuid(uid);
size_t len;
if (pwent == NULL) return NULL;
lastUid = uid;
len = strlen(pwent->pw_name);
if (lastUnameLen < len + 1) {
lastUnameLen = len + 20;
lastUname = xrealloc(lastUname, lastUnameLen);
}
strcpy(lastUname, pwent->pw_name);
return lastUname;
}
}
const char * rpmugGname(gid_t gid)
{
static gid_t lastGid = (gid_t) -1;
static char * lastGname = NULL;
static size_t lastGnameLen = 0;
if (gid == (gid_t) -1) {
lastGid = (gid_t) -1;
return NULL;
} else if (gid == (gid_t) 0) {
return "root";
} else if (gid == lastGid) {
return lastGname;
} else {
struct group * grent = getgrgid(gid);
size_t len;
if (grent == NULL) return NULL;
lastGid = gid;
len = strlen(grent->gr_name);
if (lastGnameLen < len + 1) {
lastGnameLen = len + 20;
lastGname = xrealloc(lastGname, lastGnameLen);
}
strcpy(lastGname, grent->gr_name);
return lastGname;
}
}
void rpmugFree(void)
{
rpmugUid(NULL, NULL);
rpmugGid(NULL, NULL);
rpmugUname(-1);
rpmugGname(-1);
strStash = strCacheFree(strStash);
}