rpm/lib/misc.c

357 lines
7.1 KiB
C
Raw Normal View History

#include "system.h"
#include "rpmlib.h"
#include "misc.h"
char * RPMVERSION = VERSION; /* just to put a marker in librpm.a */
char ** splitString(char * str, int length, char sep) {
char * s, * source, * dest;
char ** list;
int i;
int fields;
s = malloc(length + 1);
fields = 1;
for (source = str, dest = s, i = 0; i < length; i++, source++, dest++) {
*dest = *source;
if (*dest == sep) fields++;
}
*dest = '\0';
list = malloc(sizeof(char *) * (fields + 1));
dest = s;
list[0] = dest;
i = 1;
while (i < fields) {
if (*dest == sep) {
list[i++] = dest + 1;
*dest = 0;
}
dest++;
}
list[i] = NULL;
return list;
}
void freeSplitString(char ** list) {
free(list[0]);
free(list);
}
int exists(char * filespec) {
struct stat buf;
if (stat(filespec, &buf)) {
switch(errno) {
case ENOENT:
case EINVAL:
return 0;
}
}
return 1;
}
int rpmvercmp(char * one, char * two) {
int num1, num2;
char oldch1, oldch2;
char * str1, * str2;
int rc;
int isnum;
if (!strcmp(one, two)) return 0;
str1 = alloca(strlen(one) + 1);
str2 = alloca(strlen(two) + 1);
strcpy(str1, one);
strcpy(str2, two);
one = str1;
two = str2;
while (*one && *two) {
while (*one && !isalnum(*one)) one++;
while (*two && !isalnum(*two)) two++;
str1 = one;
str2 = two;
if (isdigit(*str1)) {
while (*str1 && isdigit(*str1)) str1++;
while (*str2 && isdigit(*str2)) str2++;
isnum = 1;
} else {
while (*str1 && isalpha(*str1)) str1++;
while (*str2 && isalpha(*str2)) str2++;
isnum = 0;
}
oldch1 = *str1;
*str1 = '\0';
oldch2 = *str2;
*str2 = '\0';
if (one == str1) return -1; /* arbitrary */
if (two == str2) return -1;
if (isnum) {
num1 = atoi(one);
num2 = atoi(two);
if (num1 < num2)
return -1;
else if (num1 > num2)
return 1;
} else {
rc = strcmp(one, two);
if (rc) return rc;
}
*str1 = oldch1;
one = str1;
*str2 = oldch2;
two = str2;
}
if ((!*one) && (!*two)) return 0;
if (!*one) return -1; else return 1;
}
void stripTrailingSlashes(char * str) {
char * chptr;
chptr = str + strlen(str) - 1;
while (*chptr == '/' && chptr >= str) {
*chptr = '\0';
chptr--;
}
}
int doputenv(const char *str) {
char * a;
/* FIXME: this leaks memory! */
a = malloc(strlen(str) + 1);
strcpy(a, str);
return putenv(a);
}
int dosetenv(const char *name, const char *value, int overwrite) {
int i;
char * a;
/* FIXME: this leaks memory! */
if (!overwrite && getenv(name)) return 0;
i = strlen(name) + strlen(value) + 2;
a = malloc(i);
if (!a) return 1;
strcpy(a, name);
strcat(a, "=");
strcat(a, value);
return putenv(a);
}
/* unameToUid(), uidTouname() and the group variants are really poorly
implemented. They 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 unameToUid(char * thisUname, uid_t * uid) {
static char * lastUname = NULL;
static int lastUnameLen = 0;
static int lastUnameAlloced;
static uid_t lastUid;
struct passwd * pwent;
int thisUnameLen;
if (!thisUname) {
lastUnameLen = 0;
return -1;
} else if (!strcmp(thisUname, "root")) {
*uid = 0;
return 0;
}
thisUnameLen = strlen(thisUname);
if (!lastUname || thisUnameLen != lastUnameLen ||
strcmp(thisUname, lastUname)) {
if (lastUnameAlloced < thisUnameLen + 1) {
lastUnameAlloced = thisUnameLen + 10;
lastUname = realloc(lastUname, lastUnameAlloced);
}
strcpy(lastUname, thisUname);
pwent = getpwnam(thisUname);
if (!pwent) {
endpwent();
pwent = getpwnam(thisUname);
if (!pwent) return -1;
}
lastUid = pwent->pw_uid;
}
*uid = lastUid;
return 0;
}
int gnameToGid(char * thisGname, gid_t * gid) {
static char * lastGname = NULL;
static int lastGnameLen = 0;
static int lastGnameAlloced;
static uid_t lastGid;
int thisGnameLen;
struct group * grent;
if (!thisGname) {
lastGnameLen = 0;
return -1;
} else if (!strcmp(thisGname, "root")) {
*gid = 0;
return 0;
}
thisGnameLen = strlen(thisGname);
if (!lastGname || thisGnameLen != lastGnameLen ||
strcmp(thisGname, lastGname)) {
if (lastGnameAlloced < thisGnameLen + 1) {
lastGnameAlloced = thisGnameLen + 10;
lastGname = realloc(lastGname, lastGnameAlloced);
}
strcpy(lastGname, thisGname);
grent = getgrnam(thisGname);
if (!grent) {
endgrent();
grent = getgrnam(thisGname);
if (!grent) return -1;
}
lastGid = grent->gr_gid;
}
*gid = lastGid;
return 0;
}
char * uidToUname(uid_t uid) {
static int lastUid = -1;
static char * lastUname = NULL;
static int lastUnameLen = 0;
struct passwd * pwent;
int len;
if (uid == (uid_t) -1) {
lastUid = -1;
return NULL;
} else if (!uid) {
return "root";
} else if (uid == lastUid) {
return lastUname;
} else {
pwent = getpwuid(uid);
if (!pwent) return NULL;
lastUid = uid;
len = strlen(pwent->pw_name);
if (lastUnameLen < len + 1) {
lastUnameLen = len + 20;
lastUname = realloc(lastUname, lastUnameLen);
}
strcpy(lastUname, pwent->pw_name);
return lastUname;
}
}
char * gidToGname(gid_t gid) {
static int lastGid = -1;
static char * lastGname = NULL;
static int lastGnameLen = 0;
struct group * grent;
int len;
if (gid == (gid_t) -1) {
lastGid = -1;
return NULL;
} else if (!gid) {
return "root";
} else if (gid == lastGid) {
return lastGname;
} else {
grent = getgrgid(gid);
if (!grent) return NULL;
lastGid = gid;
len = strlen(grent->gr_name);
if (lastGnameLen < len + 1) {
lastGnameLen = len + 20;
lastGname = realloc(lastGname, lastGnameLen);
}
strcpy(lastGname, grent->gr_name);
return lastGname;
}
}
int makeTempFile(char * prefix, char ** fnptr, FD_t * fdptr) {
char * fn;
FD_t fd;
int ran;
char * tmpdir = rpmGetVar(RPMVAR_TMPPATH);
struct stat sb, sb2;
if (!prefix) prefix = "";
fn = malloc(strlen(prefix) + 25 + strlen(tmpdir));
srand(time(NULL));
ran = rand() % 100000;
/* maybe this should use link/stat? */
do {
sprintf(fn, "%s%s/rpm-tmp.%d", prefix, tmpdir, ran++);
fd = fdOpen(fn, O_CREAT | O_RDWR | O_EXCL, 0700);
} while (fdFileno(fd) < 0 && errno == EEXIST);
if (!stat(fn, &sb) && S_ISLNK(sb.st_mode)) {
rpmError(RPMERR_SCRIPT, _("error creating temporary file %s"), fn);
return 1;
}
if (sb.st_nlink != 1) {
rpmError(RPMERR_SCRIPT, _("error creating temporary file %s"), fn);
return 1;
}
fdFstat(fd, &sb2);
if (sb2.st_ino != sb.st_ino || sb2.st_dev != sb.st_dev) {
rpmError(RPMERR_SCRIPT, _("error creating temporary file %s"), fn);
return 1;
}
if (fnptr) *fnptr = fn;
*fdptr = fd;
return 0;
}