1998-07-26 05:00:26 +08:00
|
|
|
#include "system.h"
|
1997-05-07 22:56:06 +08:00
|
|
|
|
1999-07-14 05:37:57 +08:00
|
|
|
#include <rpmlib.h>
|
1999-10-31 05:26:45 +08:00
|
|
|
#include <rpmurl.h>
|
1999-07-14 05:37:57 +08:00
|
|
|
#include <rpmmacro.h> /* XXX for rpmGetPath */
|
1995-11-28 06:31:21 +08:00
|
|
|
|
|
|
|
#include "misc.h"
|
|
|
|
|
1998-01-13 05:31:29 +08:00
|
|
|
char * RPMVERSION = VERSION; /* just to put a marker in librpm.a */
|
1997-08-24 21:04:39 +08:00
|
|
|
|
1999-01-07 01:33:50 +08:00
|
|
|
char ** splitString(const char * str, int length, char sep) {
|
|
|
|
const char * source;
|
|
|
|
char * s, * dest;
|
1995-11-28 06:31:21 +08:00
|
|
|
char ** list;
|
|
|
|
int i;
|
|
|
|
int fields;
|
|
|
|
|
1999-09-21 11:22:53 +08:00
|
|
|
s = xmalloc(length + 1);
|
1995-11-28 06:31:21 +08:00
|
|
|
|
|
|
|
fields = 1;
|
|
|
|
for (source = str, dest = s, i = 0; i < length; i++, source++, dest++) {
|
|
|
|
*dest = *source;
|
|
|
|
if (*dest == sep) fields++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*dest = '\0';
|
|
|
|
|
1999-09-21 11:22:53 +08:00
|
|
|
list = xmalloc(sizeof(char *) * (fields + 1));
|
1995-11-28 06:31:21 +08:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
1995-12-14 04:11:31 +08:00
|
|
|
|
1999-11-13 01:20:49 +08:00
|
|
|
int rpmfileexists(const char * urlfn) {
|
|
|
|
const char *fn;
|
|
|
|
int urltype = urlPath(urlfn, &fn);
|
1995-12-14 04:11:31 +08:00
|
|
|
struct stat buf;
|
|
|
|
|
1999-11-20 02:19:41 +08:00
|
|
|
if (*fn == '\0') fn = "/";
|
1999-11-13 01:20:49 +08:00
|
|
|
switch (urltype) {
|
|
|
|
case URL_IS_FTP: /* XXX WRONG WRONG WRONG */
|
|
|
|
case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */
|
1999-10-31 05:26:45 +08:00
|
|
|
case URL_IS_PATH:
|
|
|
|
case URL_IS_UNKNOWN:
|
1999-11-13 01:20:49 +08:00
|
|
|
if (Stat(fn, &buf)) {
|
1999-10-31 05:26:45 +08:00
|
|
|
switch(errno) {
|
|
|
|
case ENOENT:
|
|
|
|
case EINVAL:
|
1995-12-14 04:11:31 +08:00
|
|
|
return 0;
|
1999-10-31 05:26:45 +08:00
|
|
|
}
|
1995-12-14 04:11:31 +08:00
|
|
|
}
|
1999-10-31 05:26:45 +08:00
|
|
|
break;
|
1999-11-11 06:09:49 +08:00
|
|
|
case URL_IS_DASH:
|
1999-10-31 05:26:45 +08:00
|
|
|
default:
|
1999-11-01 05:38:21 +08:00
|
|
|
return 0;
|
1999-10-31 05:26:45 +08:00
|
|
|
break;
|
1995-12-14 04:11:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
1995-12-28 00:29:55 +08:00
|
|
|
|
1999-06-30 22:18:05 +08:00
|
|
|
/* compare alpha and numeric segments of two versions */
|
|
|
|
/* return 1: a is newer than b */
|
|
|
|
/* 0: a and b are the same version */
|
|
|
|
/* -1: b is newer than a */
|
1999-01-07 01:33:50 +08:00
|
|
|
int rpmvercmp(const char * a, const char * b) {
|
1996-02-26 06:10:25 +08:00
|
|
|
char oldch1, oldch2;
|
|
|
|
char * str1, * str2;
|
1999-01-07 01:33:50 +08:00
|
|
|
char * one, * two;
|
1996-02-26 06:10:25 +08:00
|
|
|
int rc;
|
|
|
|
int isnum;
|
|
|
|
|
1999-06-30 22:18:05 +08:00
|
|
|
/* easy comparison to see if versions are identical */
|
1999-01-07 01:33:50 +08:00
|
|
|
if (!strcmp(a, b)) return 0;
|
1996-02-26 06:10:25 +08:00
|
|
|
|
1999-01-07 01:33:50 +08:00
|
|
|
str1 = alloca(strlen(a) + 1);
|
|
|
|
str2 = alloca(strlen(b) + 1);
|
1996-02-26 06:10:25 +08:00
|
|
|
|
1999-01-07 01:33:50 +08:00
|
|
|
strcpy(str1, a);
|
|
|
|
strcpy(str2, b);
|
1996-02-26 06:10:25 +08:00
|
|
|
|
|
|
|
one = str1;
|
|
|
|
two = str2;
|
|
|
|
|
1999-06-30 22:18:05 +08:00
|
|
|
/* loop through each version segment of str1 and str2 and compare them */
|
1996-02-26 06:10:25 +08:00
|
|
|
while (*one && *two) {
|
|
|
|
while (*one && !isalnum(*one)) one++;
|
|
|
|
while (*two && !isalnum(*two)) two++;
|
|
|
|
|
|
|
|
str1 = one;
|
|
|
|
str2 = two;
|
|
|
|
|
1999-06-30 22:18:05 +08:00
|
|
|
/* grab first completely alpha or completely numeric segment */
|
|
|
|
/* leave one and two pointing to the start of the alpha or numeric */
|
|
|
|
/* segment and walk str1 and str2 to end of segment */
|
1996-02-26 06:10:25 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
1999-06-30 22:18:05 +08:00
|
|
|
/* save character at the end of the alpha or numeric segment */
|
|
|
|
/* so that they can be restored after the comparison */
|
1996-02-26 06:10:25 +08:00
|
|
|
oldch1 = *str1;
|
|
|
|
*str1 = '\0';
|
|
|
|
oldch2 = *str2;
|
|
|
|
*str2 = '\0';
|
|
|
|
|
1999-06-30 22:18:05 +08:00
|
|
|
/* take care of the case where the two version segments are */
|
|
|
|
/* different types: one numeric and one alpha */
|
1996-02-26 06:10:25 +08:00
|
|
|
if (one == str1) return -1; /* arbitrary */
|
|
|
|
if (two == str2) return -1;
|
|
|
|
|
|
|
|
if (isnum) {
|
1999-06-30 22:18:05 +08:00
|
|
|
/* this used to be done by converting the digit segments */
|
|
|
|
/* to ints using atoi() - it's changed because long */
|
|
|
|
/* digit segments can overflow an int - this should fix that. */
|
|
|
|
|
|
|
|
/* throw away any leading zeros - it's a number, right? */
|
|
|
|
while (*one == '0') one++;
|
|
|
|
while (*two == '0') two++;
|
|
|
|
|
|
|
|
/* whichever number has more digits wins */
|
|
|
|
if (strlen(one) > strlen(two)) return 1;
|
|
|
|
if (strlen(two) > strlen(one)) return -1;
|
1996-02-26 06:10:25 +08:00
|
|
|
}
|
1999-06-30 22:18:05 +08:00
|
|
|
|
|
|
|
/* strcmp will return which one is greater - even if the two */
|
|
|
|
/* segments are alpha or if they are numeric. don't return */
|
|
|
|
/* if they are equal because there might be more segments to */
|
|
|
|
/* compare */
|
|
|
|
rc = strcmp(one, two);
|
|
|
|
if (rc) return rc;
|
1996-02-26 06:10:25 +08:00
|
|
|
|
1999-06-30 22:18:05 +08:00
|
|
|
/* restore character that was replaced by null above */
|
1996-02-26 06:10:25 +08:00
|
|
|
*str1 = oldch1;
|
|
|
|
one = str1;
|
|
|
|
*str2 = oldch2;
|
|
|
|
two = str2;
|
|
|
|
}
|
|
|
|
|
1999-06-30 22:18:05 +08:00
|
|
|
/* this catches the case where all numeric and alpha segments have */
|
|
|
|
/* compared identically but the segment sepparating characters were */
|
|
|
|
/* different */
|
1996-02-26 06:10:25 +08:00
|
|
|
if ((!*one) && (!*two)) return 0;
|
|
|
|
|
1999-06-30 22:18:05 +08:00
|
|
|
/* whichever version still has characters left over wins */
|
1996-03-01 09:58:27 +08:00
|
|
|
if (!*one) return -1; else return 1;
|
1996-02-26 06:10:25 +08:00
|
|
|
}
|
1996-07-10 10:33:54 +08:00
|
|
|
|
|
|
|
void stripTrailingSlashes(char * str) {
|
|
|
|
char * chptr;
|
|
|
|
|
|
|
|
chptr = str + strlen(str) - 1;
|
|
|
|
while (*chptr == '/' && chptr >= str) {
|
|
|
|
*chptr = '\0';
|
|
|
|
chptr--;
|
|
|
|
}
|
|
|
|
}
|
1996-12-24 22:01:56 +08:00
|
|
|
|
|
|
|
int doputenv(const char *str) {
|
|
|
|
char * a;
|
|
|
|
|
|
|
|
/* FIXME: this leaks memory! */
|
|
|
|
|
1999-09-21 11:22:53 +08:00
|
|
|
a = xmalloc(strlen(str) + 1);
|
1996-12-24 22:01:56 +08:00
|
|
|
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;
|
1999-10-09 00:38:33 +08:00
|
|
|
a = xmalloc(i);
|
1996-12-24 22:01:56 +08:00
|
|
|
if (!a) return 1;
|
|
|
|
|
|
|
|
strcpy(a, name);
|
|
|
|
strcat(a, "=");
|
|
|
|
strcat(a, value);
|
|
|
|
|
|
|
|
return putenv(a);
|
|
|
|
}
|
1997-02-14 10:05:13 +08:00
|
|
|
|
|
|
|
/* 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 :-( */
|
|
|
|
|
1999-10-21 05:40:10 +08:00
|
|
|
int unameToUid(const char * thisUname, uid_t * uid) {
|
|
|
|
/*@only@*/ static char * lastUname = NULL;
|
1997-02-14 10:05:13 +08:00
|
|
|
static int lastUnameLen = 0;
|
|
|
|
static int lastUnameAlloced;
|
|
|
|
static uid_t lastUid;
|
|
|
|
struct passwd * pwent;
|
|
|
|
int thisUnameLen;
|
1997-07-16 09:40:23 +08:00
|
|
|
|
1997-02-14 10:05:13 +08:00
|
|
|
if (!thisUname) {
|
|
|
|
lastUnameLen = 0;
|
|
|
|
return -1;
|
1997-07-16 09:40:23 +08:00
|
|
|
} else if (!strcmp(thisUname, "root")) {
|
|
|
|
*uid = 0;
|
|
|
|
return 0;
|
1997-02-14 10:05:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
thisUnameLen = strlen(thisUname);
|
1997-02-18 04:20:32 +08:00
|
|
|
if (!lastUname || thisUnameLen != lastUnameLen ||
|
|
|
|
strcmp(thisUname, lastUname)) {
|
1997-02-14 10:05:13 +08:00
|
|
|
if (lastUnameAlloced < thisUnameLen + 1) {
|
|
|
|
lastUnameAlloced = thisUnameLen + 10;
|
1999-09-22 01:21:57 +08:00
|
|
|
lastUname = xrealloc(lastUname, lastUnameAlloced); /* XXX memory leak */
|
1997-02-14 10:05:13 +08:00
|
|
|
}
|
|
|
|
strcpy(lastUname, thisUname);
|
|
|
|
|
|
|
|
pwent = getpwnam(thisUname);
|
|
|
|
if (!pwent) {
|
1997-07-18 03:18:33 +08:00
|
|
|
endpwent();
|
|
|
|
pwent = getpwnam(thisUname);
|
|
|
|
if (!pwent) return -1;
|
1997-02-14 10:05:13 +08:00
|
|
|
}
|
1997-07-18 03:18:33 +08:00
|
|
|
|
|
|
|
lastUid = pwent->pw_uid;
|
1997-02-14 10:05:13 +08:00
|
|
|
}
|
|
|
|
|
1997-05-06 04:46:58 +08:00
|
|
|
*uid = lastUid;
|
|
|
|
|
|
|
|
return 0;
|
1997-02-14 10:05:13 +08:00
|
|
|
}
|
|
|
|
|
1999-10-21 05:40:10 +08:00
|
|
|
int gnameToGid(const char * thisGname, gid_t * gid) {
|
|
|
|
/*@only@*/ static char * lastGname = NULL;
|
1997-02-14 10:05:13 +08:00
|
|
|
static int lastGnameLen = 0;
|
|
|
|
static int lastGnameAlloced;
|
|
|
|
static uid_t lastGid;
|
|
|
|
int thisGnameLen;
|
|
|
|
struct group * grent;
|
|
|
|
|
|
|
|
if (!thisGname) {
|
|
|
|
lastGnameLen = 0;
|
|
|
|
return -1;
|
1997-07-16 09:40:23 +08:00
|
|
|
} else if (!strcmp(thisGname, "root")) {
|
|
|
|
*gid = 0;
|
|
|
|
return 0;
|
1997-02-14 10:05:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
thisGnameLen = strlen(thisGname);
|
1997-02-18 04:20:32 +08:00
|
|
|
if (!lastGname || thisGnameLen != lastGnameLen ||
|
|
|
|
strcmp(thisGname, lastGname)) {
|
1997-02-14 10:05:13 +08:00
|
|
|
if (lastGnameAlloced < thisGnameLen + 1) {
|
|
|
|
lastGnameAlloced = thisGnameLen + 10;
|
1999-09-22 01:21:57 +08:00
|
|
|
lastGname = xrealloc(lastGname, lastGnameAlloced); /* XXX memory leak */
|
1997-02-14 10:05:13 +08:00
|
|
|
}
|
|
|
|
strcpy(lastGname, thisGname);
|
|
|
|
|
|
|
|
grent = getgrnam(thisGname);
|
|
|
|
if (!grent) {
|
1997-07-18 03:18:33 +08:00
|
|
|
endgrent();
|
|
|
|
grent = getgrnam(thisGname);
|
|
|
|
if (!grent) return -1;
|
1997-02-14 10:05:13 +08:00
|
|
|
}
|
1997-07-18 03:18:33 +08:00
|
|
|
lastGid = grent->gr_gid;
|
1997-02-14 10:05:13 +08:00
|
|
|
}
|
|
|
|
|
1997-05-06 04:46:58 +08:00
|
|
|
*gid = lastGid;
|
|
|
|
|
|
|
|
return 0;
|
1997-02-14 10:05:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
char * uidToUname(uid_t uid) {
|
|
|
|
static int lastUid = -1;
|
1999-10-21 05:40:10 +08:00
|
|
|
/*@only@*/ static char * lastUname = NULL;
|
1997-02-14 10:05:13 +08:00
|
|
|
static int lastUnameLen = 0;
|
|
|
|
struct passwd * pwent;
|
|
|
|
int len;
|
|
|
|
|
1997-02-18 04:20:32 +08:00
|
|
|
if (uid == (uid_t) -1) {
|
1997-02-14 10:05:13 +08:00
|
|
|
lastUid = -1;
|
|
|
|
return NULL;
|
1997-07-16 09:40:23 +08:00
|
|
|
} else if (!uid) {
|
|
|
|
return "root";
|
1997-02-14 10:05:13 +08:00
|
|
|
} 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;
|
1999-09-21 11:22:53 +08:00
|
|
|
lastUname = xrealloc(lastUname, lastUnameLen);
|
1997-02-14 10:05:13 +08:00
|
|
|
}
|
|
|
|
strcpy(lastUname, pwent->pw_name);
|
|
|
|
|
|
|
|
return lastUname;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
char * gidToGname(gid_t gid) {
|
|
|
|
static int lastGid = -1;
|
1999-10-21 05:40:10 +08:00
|
|
|
/*@only@*/ static char * lastGname = NULL;
|
1997-02-14 10:05:13 +08:00
|
|
|
static int lastGnameLen = 0;
|
|
|
|
struct group * grent;
|
|
|
|
int len;
|
|
|
|
|
1997-07-16 09:40:23 +08:00
|
|
|
if (gid == (gid_t) -1) {
|
1997-02-14 10:05:13 +08:00
|
|
|
lastGid = -1;
|
|
|
|
return NULL;
|
1997-07-16 09:40:23 +08:00
|
|
|
} else if (!gid) {
|
|
|
|
return "root";
|
1997-02-14 10:05:13 +08:00
|
|
|
} 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;
|
1999-09-21 11:22:53 +08:00
|
|
|
lastGname = xrealloc(lastGname, lastGnameLen);
|
1997-02-14 10:05:13 +08:00
|
|
|
}
|
|
|
|
strcpy(lastGname, grent->gr_name);
|
|
|
|
|
|
|
|
return lastGname;
|
|
|
|
}
|
|
|
|
}
|
1997-08-29 03:13:54 +08:00
|
|
|
|
1999-01-07 01:33:50 +08:00
|
|
|
int makeTempFile(const char * prefix, const char ** fnptr, FD_t * fdptr) {
|
1999-11-20 02:19:41 +08:00
|
|
|
const char * tempfn = NULL;
|
|
|
|
const char * tfn = NULL;
|
1999-11-19 02:07:46 +08:00
|
|
|
int temput;
|
1998-11-19 05:41:05 +08:00
|
|
|
FD_t fd;
|
1997-08-29 03:13:54 +08:00
|
|
|
int ran;
|
|
|
|
|
|
|
|
if (!prefix) prefix = "";
|
|
|
|
|
1999-11-11 06:09:49 +08:00
|
|
|
/* XXX should probably use mktemp here */
|
1997-11-01 01:31:17 +08:00
|
|
|
srand(time(NULL));
|
|
|
|
ran = rand() % 100000;
|
1998-09-15 02:55:18 +08:00
|
|
|
|
|
|
|
/* maybe this should use link/stat? */
|
|
|
|
|
1997-08-29 03:13:54 +08:00
|
|
|
do {
|
1999-11-11 06:09:49 +08:00
|
|
|
char tfnbuf[64];
|
|
|
|
#ifndef NOTYET
|
|
|
|
sprintf(tfnbuf, "rpm-tmp.%d", ran++);
|
1999-11-20 02:19:41 +08:00
|
|
|
if (tempfn) xfree(tempfn);
|
1999-11-19 02:07:46 +08:00
|
|
|
tempfn = rpmGenPath(prefix, "%{_tmppath}/", tfnbuf);
|
1999-11-11 06:09:49 +08:00
|
|
|
#else
|
|
|
|
strcpy(tfnbuf, "rpm-tmp.XXXXXX");
|
1999-11-20 02:19:41 +08:00
|
|
|
if (tempfn) xfree(tempfn);
|
1999-11-19 02:07:46 +08:00
|
|
|
tempfn = rpmGenPath(prefix, "%{_tmppath}/", mktemp(tfnbuf));
|
1999-11-11 06:09:49 +08:00
|
|
|
#endif
|
|
|
|
|
1999-11-19 02:07:46 +08:00
|
|
|
temput = urlPath(tempfn, &tfn);
|
1999-11-20 02:19:41 +08:00
|
|
|
if (*tfn == '\0') goto errxit;
|
|
|
|
|
1999-11-19 02:07:46 +08:00
|
|
|
switch (temput) {
|
1999-11-11 06:09:49 +08:00
|
|
|
case URL_IS_HTTP:
|
|
|
|
case URL_IS_DASH:
|
1999-11-19 02:07:46 +08:00
|
|
|
goto errxit;
|
|
|
|
/*@notreached@*/ break;
|
1999-11-01 05:38:21 +08:00
|
|
|
default:
|
1999-11-19 02:07:46 +08:00
|
|
|
break;
|
1999-11-01 05:38:21 +08:00
|
|
|
}
|
1999-11-13 01:20:49 +08:00
|
|
|
|
1999-11-20 02:19:41 +08:00
|
|
|
fd = Fopen(tempfn, "w+x.ufdio");
|
1999-11-11 06:09:49 +08:00
|
|
|
} while ((fd == NULL || Ferror(fd)) && errno == EEXIST);
|
|
|
|
|
1999-11-19 02:07:46 +08:00
|
|
|
switch(temput) {
|
|
|
|
struct stat sb, sb2;
|
|
|
|
case URL_IS_PATH:
|
|
|
|
case URL_IS_UNKNOWN:
|
|
|
|
if (!stat(tfn, &sb) && S_ISLNK(sb.st_mode)) {
|
|
|
|
rpmError(RPMERR_SCRIPT, _("error creating temporary file %s"), tfn);
|
|
|
|
goto errxit;
|
|
|
|
}
|
1998-03-04 05:45:38 +08:00
|
|
|
|
1999-11-19 02:07:46 +08:00
|
|
|
if (sb.st_nlink != 1) {
|
1999-11-15 03:15:18 +08:00
|
|
|
rpmError(RPMERR_SCRIPT, _("error creating temporary file %s"), tfn);
|
1999-11-19 02:07:46 +08:00
|
|
|
goto errxit;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fstat(Fileno(fd), &sb2) == 0) {
|
|
|
|
if (sb2.st_ino != sb.st_ino || sb2.st_dev != sb.st_dev) {
|
|
|
|
rpmError(RPMERR_SCRIPT, _("error creating temporary file %s"), tfn);
|
|
|
|
goto errxit;
|
|
|
|
}
|
1999-11-15 03:15:18 +08:00
|
|
|
}
|
1999-11-19 02:07:46 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
1998-03-04 05:45:38 +08:00
|
|
|
}
|
|
|
|
|
1999-01-07 01:33:50 +08:00
|
|
|
if (fnptr)
|
1999-11-20 02:19:41 +08:00
|
|
|
*fnptr = tempfn;
|
|
|
|
else if (tempfn)
|
1999-11-19 02:07:46 +08:00
|
|
|
xfree(tempfn);
|
1997-08-29 03:13:54 +08:00
|
|
|
*fdptr = fd;
|
|
|
|
|
|
|
|
return 0;
|
1999-11-19 02:07:46 +08:00
|
|
|
|
|
|
|
errxit:
|
1999-11-20 02:19:41 +08:00
|
|
|
if (tempfn) xfree(tempfn);
|
1999-11-19 02:07:46 +08:00
|
|
|
return 1;
|
1997-08-29 03:13:54 +08:00
|
|
|
}
|
1999-01-08 11:10:12 +08:00
|
|
|
|
|
|
|
char * currentDirectory(void) {
|
|
|
|
int currDirLen;
|
|
|
|
char * currDir;
|
|
|
|
|
|
|
|
currDirLen = 50;
|
1999-09-21 11:22:53 +08:00
|
|
|
currDir = xmalloc(currDirLen);
|
1999-01-08 11:10:12 +08:00
|
|
|
while (!getcwd(currDir, currDirLen) && errno == ERANGE) {
|
|
|
|
currDirLen += 50;
|
1999-09-21 11:22:53 +08:00
|
|
|
currDir = xrealloc(currDir, currDirLen);
|
1999-01-08 11:10:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return currDir;
|
|
|
|
}
|
1999-10-06 23:51:14 +08:00
|
|
|
|
|
|
|
void compressFilelist(Header h) {
|
1999-10-30 00:06:01 +08:00
|
|
|
const char ** files;
|
|
|
|
const char ** dirList;
|
1999-10-06 23:51:14 +08:00
|
|
|
int * compDirList;
|
1999-10-30 00:06:01 +08:00
|
|
|
const char ** baseNames;
|
1999-10-06 23:51:14 +08:00
|
|
|
int fileCount;
|
|
|
|
int i;
|
|
|
|
int lastDir = -1;
|
1999-10-07 02:29:27 +08:00
|
|
|
int lastLen = -1;
|
1999-10-06 23:51:14 +08:00
|
|
|
|
|
|
|
/* This assumes thie file list is already sorted, and begins with a
|
|
|
|
single '/'. That assumption isn't critical, but it makes things go
|
|
|
|
a bit faster. */
|
|
|
|
|
|
|
|
if (!headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, (void **) &files,
|
|
|
|
&fileCount))
|
|
|
|
/* no file list */
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (files[0][0] != '/') {
|
|
|
|
/* HACK. Source RPM, so just do things differently */
|
1999-10-30 00:06:01 +08:00
|
|
|
free(files);
|
|
|
|
return;
|
1999-10-06 23:51:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
dirList = alloca(sizeof(*dirList) * fileCount); /* worst case */
|
|
|
|
baseNames = alloca(sizeof(*dirList) * fileCount);
|
|
|
|
compDirList = alloca(sizeof(*compDirList) * fileCount);
|
|
|
|
|
|
|
|
for (i = 0; i < fileCount; i++) {
|
1999-10-30 00:06:01 +08:00
|
|
|
char *tail = strrchr(files[i], '/') + 1;
|
1999-10-06 23:51:14 +08:00
|
|
|
|
1999-10-07 02:29:27 +08:00
|
|
|
if (lastDir < 0 || (lastLen != (tail - files[i])) ||
|
1999-10-06 23:51:14 +08:00
|
|
|
strncmp(dirList[lastDir], files[i], tail - files[i])) {
|
1999-10-30 00:06:01 +08:00
|
|
|
char *s = alloca(tail - files[i] + 1);
|
|
|
|
memcpy(s, files[i], tail - files[i]);
|
|
|
|
s[tail - files[i]] = '\0';
|
|
|
|
dirList[++lastDir] = s;
|
1999-10-07 02:29:27 +08:00
|
|
|
lastLen = tail - files[i];
|
1999-10-06 23:51:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
compDirList[i] = lastDir;
|
|
|
|
baseNames[i] = tail;
|
|
|
|
}
|
|
|
|
|
|
|
|
headerAddEntry(h, RPMTAG_COMPDIRLIST, RPM_STRING_ARRAY_TYPE, dirList,
|
|
|
|
lastDir + 1);
|
|
|
|
headerAddEntry(h, RPMTAG_COMPFILEDIRS, RPM_INT32_TYPE, compDirList,
|
|
|
|
fileCount);
|
|
|
|
headerAddEntry(h, RPMTAG_COMPFILELIST, RPM_STRING_ARRAY_TYPE, baseNames,
|
|
|
|
fileCount);
|
|
|
|
|
|
|
|
free(files);
|
|
|
|
|
|
|
|
headerRemoveEntry(h, RPMTAG_OLDFILENAMES);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* this is pretty straight-forward. The only thing that even resembles a trick
|
1999-10-09 00:38:33 +08:00
|
|
|
is getting all of this into a single xmalloc'd block */
|
1999-10-31 00:43:29 +08:00
|
|
|
static void doBuildFileList(Header h, /*@out@*/ const char *** fileListPtr,
|
1999-10-22 04:36:16 +08:00
|
|
|
/*@out@*/ int * fileCountPtr, int baseNameTag,
|
1999-10-21 10:40:57 +08:00
|
|
|
int dirListTag, int dirIndexesTag) {
|
1999-10-06 23:51:14 +08:00
|
|
|
int * dirList;
|
1999-10-30 00:06:01 +08:00
|
|
|
const char ** dirs;
|
|
|
|
const char ** tails;
|
1999-10-06 23:51:14 +08:00
|
|
|
int count;
|
1999-10-30 00:06:01 +08:00
|
|
|
const char ** fileList;
|
1999-10-06 23:51:14 +08:00
|
|
|
int size;
|
|
|
|
char * data;
|
|
|
|
int i;
|
|
|
|
|
1999-10-21 10:40:57 +08:00
|
|
|
if (!headerGetEntry(h, baseNameTag, NULL, (void **) &tails,
|
1999-10-06 23:51:14 +08:00
|
|
|
&count))
|
|
|
|
/* no file list */
|
|
|
|
return;
|
|
|
|
|
1999-10-21 10:40:57 +08:00
|
|
|
headerGetEntry(h, dirListTag, NULL, (void **) &dirs,
|
1999-10-06 23:51:14 +08:00
|
|
|
&count);
|
1999-10-21 10:40:57 +08:00
|
|
|
headerGetEntry(h, dirIndexesTag, NULL, (void **) &dirList,
|
1999-10-06 23:51:14 +08:00
|
|
|
&count);
|
|
|
|
|
|
|
|
size = sizeof(*fileList) * count;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
size += strlen(tails[i]) + strlen(dirs[dirList[i]]) + 1;
|
|
|
|
}
|
|
|
|
|
1999-10-09 00:38:33 +08:00
|
|
|
fileList = xmalloc(size);
|
1999-10-06 23:51:14 +08:00
|
|
|
data = ((char *) fileList) + (sizeof(*fileList) * count);
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
fileList[i] = data;
|
|
|
|
strcpy(data, dirs[dirList[i]]);
|
|
|
|
strcat(data, tails[i]);
|
|
|
|
data += strlen(tails[i]) + strlen(dirs[dirList[i]]) + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
*fileListPtr = fileList;
|
|
|
|
*fileCountPtr = count;
|
1999-10-30 00:06:01 +08:00
|
|
|
free(tails);
|
|
|
|
free(dirs);
|
1999-10-06 23:51:14 +08:00
|
|
|
}
|
1999-10-21 10:40:57 +08:00
|
|
|
|
1999-10-31 00:43:29 +08:00
|
|
|
void buildFileList(Header h, const char *** fileListPtr, int * fileCountPtr)
|
|
|
|
{
|
1999-10-21 10:40:57 +08:00
|
|
|
doBuildFileList(h, fileListPtr, fileCountPtr, RPMTAG_COMPFILELIST,
|
|
|
|
RPMTAG_COMPDIRLIST, RPMTAG_COMPFILEDIRS);
|
|
|
|
}
|
|
|
|
|
1999-10-31 00:43:29 +08:00
|
|
|
void buildOrigFileList(Header h, const char *** fileListPtr, int * fileCountPtr)
|
|
|
|
{
|
1999-10-21 10:40:57 +08:00
|
|
|
doBuildFileList(h, fileListPtr, fileCountPtr, RPMTAG_ORIGCOMPFILELIST,
|
|
|
|
RPMTAG_ORIGCOMPDIRLIST, RPMTAG_ORIGCOMPFILEDIRS);
|
|
|
|
}
|