1996-09-26 03:14:17 +08:00
|
|
|
#ifdef HAVE_ALLOCA_H
|
|
|
|
# include <alloca.h>
|
|
|
|
#endif
|
|
|
|
|
1996-01-09 03:31:44 +08:00
|
|
|
#include <errno.h>
|
1996-01-15 03:32:17 +08:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <grp.h>
|
|
|
|
#include <pwd.h>
|
1996-01-09 03:31:44 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/signal.h>
|
1996-01-15 03:32:17 +08:00
|
|
|
#include <sys/stat.h> /* needed for mkdir(2) prototype! */
|
1996-01-09 03:31:44 +08:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/wait.h>
|
1996-01-30 03:37:59 +08:00
|
|
|
#include <time.h>
|
1996-01-09 03:31:44 +08:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <zlib.h>
|
|
|
|
|
|
|
|
#include "header.h"
|
|
|
|
#include "install.h"
|
1996-01-30 03:37:59 +08:00
|
|
|
#include "md5.h"
|
1996-02-15 06:20:08 +08:00
|
|
|
#include "misc.h"
|
1996-09-17 06:28:56 +08:00
|
|
|
#include "rpmdb.h"
|
1996-01-09 03:31:44 +08:00
|
|
|
#include "rpmlib.h"
|
1996-11-19 02:02:36 +08:00
|
|
|
#include "messages.h"
|
1996-01-09 03:31:44 +08:00
|
|
|
|
1996-03-30 04:52:03 +08:00
|
|
|
enum instActions { CREATE, BACKUP, KEEP, SAVE, SKIP };
|
1996-09-26 03:14:17 +08:00
|
|
|
enum fileTypes { XDIR, BDEV, CDEV, SOCK, PIPE, REG, LINK } ;
|
1996-01-23 05:13:12 +08:00
|
|
|
|
|
|
|
struct fileToInstall {
|
|
|
|
char * fileName;
|
|
|
|
int size;
|
|
|
|
} ;
|
|
|
|
|
1996-02-16 05:08:48 +08:00
|
|
|
struct replacedFile {
|
|
|
|
int recOffset, fileNumber;
|
|
|
|
} ;
|
|
|
|
|
1996-02-29 11:38:33 +08:00
|
|
|
enum fileTypes whatis(short mode);
|
1996-09-29 10:27:20 +08:00
|
|
|
static int filecmp(short mode1, char * md51, char * link1,
|
|
|
|
short mode2, char * md52, char * link2);
|
|
|
|
static enum instActions decideFileFate(char * filespec, short dbMode,
|
|
|
|
char * dbMd5, char * dbLink, short newMode,
|
|
|
|
char * newMd5, char * newLink, int brokenMd5);
|
1996-01-23 05:13:12 +08:00
|
|
|
static int installArchive(char * prefix, int fd, struct fileToInstall * files,
|
1996-11-19 02:02:36 +08:00
|
|
|
int fileCount, rpmNotifyFunction notify,
|
1996-08-29 12:16:07 +08:00
|
|
|
char ** installArchive, char * tmpPath,
|
|
|
|
int archiveSize);
|
1996-01-15 03:32:17 +08:00
|
|
|
static int packageAlreadyInstalled(rpmdb db, char * name, char * version,
|
1996-02-15 05:26:21 +08:00
|
|
|
char * release, int * recOffset, int flags);
|
1996-07-10 10:33:38 +08:00
|
|
|
static int setFileOwnerships(char * rootdir, char ** fileList,
|
1996-01-15 03:32:17 +08:00
|
|
|
char ** fileOwners, char ** fileGroups,
|
1996-05-23 10:42:51 +08:00
|
|
|
int_16 * fileModes,
|
1996-03-30 04:52:03 +08:00
|
|
|
enum instActions * instActions, int fileCount);
|
1996-06-28 01:18:07 +08:00
|
|
|
static int setFileOwner(char * file, char * owner, char * group, int_16 mode);
|
1996-12-06 06:04:44 +08:00
|
|
|
static int createDirectories(char ** fileList, uint_32 * modesList,
|
|
|
|
int fileCount);
|
1996-01-15 03:32:17 +08:00
|
|
|
static int mkdirIfNone(char * directory, mode_t perms);
|
1996-01-23 05:13:12 +08:00
|
|
|
static int instHandleSharedFiles(rpmdb db, int ignoreOffset, char ** fileList,
|
1996-02-29 11:38:33 +08:00
|
|
|
char ** fileMd5List, int_16 * fileModeList,
|
1996-07-28 07:35:07 +08:00
|
|
|
char ** fileLinkList, uint_32 * fileFlagsList,
|
1996-02-29 11:38:33 +08:00
|
|
|
int fileCount, enum instActions * instActions,
|
1996-07-10 10:33:38 +08:00
|
|
|
char ** prootdirootdir, int * notErrors,
|
1996-02-16 05:08:48 +08:00
|
|
|
struct replacedFile ** repListPtr, int flags);
|
1996-01-23 05:13:12 +08:00
|
|
|
static int fileCompare(const void * one, const void * two);
|
1996-08-29 12:16:07 +08:00
|
|
|
static int installSources(Header h, char * rootdir, int fd,
|
1996-11-19 02:02:36 +08:00
|
|
|
char ** specFilePtr, rpmNotifyFunction notify,
|
1996-08-29 12:16:07 +08:00
|
|
|
char * labelFormat);
|
1996-02-16 05:08:48 +08:00
|
|
|
static int markReplacedFiles(rpmdb db, struct replacedFile * replList);
|
1996-07-10 10:33:38 +08:00
|
|
|
static int relocateFilelist(Header * hp, char * defaultPrefix,
|
|
|
|
char * newPrefix, int * relocationSize);
|
1996-07-16 11:37:07 +08:00
|
|
|
static int archOkay(Header h);
|
|
|
|
static int osOkay(Header h);
|
1996-08-29 12:16:07 +08:00
|
|
|
static int moveFile(char * sourceName, char * destName);
|
|
|
|
static int copyFile(char * sourceName, char * destName);
|
1996-10-21 10:17:39 +08:00
|
|
|
static void unglobFilename(char * dptr, char * sptr);
|
1996-02-15 04:09:14 +08:00
|
|
|
|
|
|
|
/* 0 success */
|
|
|
|
/* 1 bad magic */
|
|
|
|
/* 2 error */
|
1996-08-29 12:16:07 +08:00
|
|
|
int rpmInstallSourcePackage(char * rootdir, int fd, char ** specFile,
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmNotifyFunction notify, char * labelFormat) {
|
1996-02-15 04:09:14 +08:00
|
|
|
int rc, isSource;
|
|
|
|
Header h;
|
1996-08-29 12:16:07 +08:00
|
|
|
int major, minor;
|
1996-02-15 04:09:14 +08:00
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rc = rpmReadPackageHeader(fd, &h, &isSource, &major, &minor);
|
1996-02-15 04:09:14 +08:00
|
|
|
if (rc) return rc;
|
|
|
|
|
|
|
|
if (!isSource) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_NOTSRPM, "source package expected, binary found");
|
1996-02-15 04:09:14 +08:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
1996-08-29 12:16:07 +08:00
|
|
|
if (major == 1) {
|
|
|
|
notify = NULL;
|
|
|
|
labelFormat = NULL;
|
|
|
|
h = NULL;
|
|
|
|
}
|
1996-03-30 03:40:08 +08:00
|
|
|
|
1996-08-29 12:16:07 +08:00
|
|
|
rc = installSources(h, rootdir, fd, specFile, notify, labelFormat);
|
1996-11-19 02:02:36 +08:00
|
|
|
if (h) headerFree(h);
|
1996-08-29 12:16:07 +08:00
|
|
|
|
|
|
|
return rc;
|
1996-02-15 04:09:14 +08:00
|
|
|
}
|
1996-01-09 03:31:44 +08:00
|
|
|
|
|
|
|
/* 0 success */
|
|
|
|
/* 1 bad magic */
|
|
|
|
/* 2 error */
|
1996-07-10 10:33:38 +08:00
|
|
|
int rpmInstallPackage(char * rootdir, rpmdb db, int fd, char * location,
|
1996-11-19 02:02:36 +08:00
|
|
|
int flags, rpmNotifyFunction notify, char * labelFormat,
|
1996-10-21 10:17:39 +08:00
|
|
|
char * netsharedPath) {
|
1996-08-29 12:16:07 +08:00
|
|
|
int rc, isSource, major, minor;
|
1996-01-15 03:32:17 +08:00
|
|
|
char * name, * version, * release;
|
1996-02-27 06:53:35 +08:00
|
|
|
Header h;
|
1996-08-29 12:16:07 +08:00
|
|
|
int fileCount, type, count;
|
1996-01-15 03:32:17 +08:00
|
|
|
char ** fileList;
|
1996-02-29 11:38:33 +08:00
|
|
|
char ** fileOwners, ** fileGroups, ** fileMd5s, ** fileLinkList;
|
1996-01-23 05:13:12 +08:00
|
|
|
uint_32 * fileFlagsList;
|
|
|
|
uint_32 * fileSizesList;
|
1996-02-29 11:38:33 +08:00
|
|
|
int_16 * fileModesList;
|
1996-01-30 03:37:59 +08:00
|
|
|
int_32 installTime;
|
1996-10-21 10:17:39 +08:00
|
|
|
char * fileStatesList = NULL;
|
1996-01-23 05:13:12 +08:00
|
|
|
struct fileToInstall * files;
|
1996-01-30 03:37:59 +08:00
|
|
|
enum instActions * instActions = NULL;
|
1996-01-23 05:13:12 +08:00
|
|
|
int i;
|
1996-01-30 03:37:59 +08:00
|
|
|
int archiveFileCount = 0;
|
|
|
|
int installFile = 0;
|
1996-02-15 05:26:21 +08:00
|
|
|
int otherOffset = 0;
|
1996-01-30 03:37:59 +08:00
|
|
|
char * ext = NULL, * newpath;
|
1996-12-06 05:11:17 +08:00
|
|
|
int rootLength = strlen(rootdir);
|
|
|
|
char ** rootedFileList = NULL;
|
|
|
|
char ** finalFileList = NULL;
|
1996-12-06 06:04:44 +08:00
|
|
|
char ** mkdirFileList = NULL;
|
|
|
|
int mkdirFileCount = 0;
|
|
|
|
uint_32 * mkdirModesList;
|
1996-02-16 05:08:48 +08:00
|
|
|
struct replacedFile * replacedList = NULL;
|
1996-10-21 10:17:39 +08:00
|
|
|
char * defaultPrefix;
|
1996-11-19 02:02:36 +08:00
|
|
|
dbiIndexSet matches;
|
1996-02-22 02:09:31 +08:00
|
|
|
int * oldVersions;
|
1996-02-21 05:54:02 +08:00
|
|
|
int * intptr;
|
1996-07-26 00:39:01 +08:00
|
|
|
char * archivePrefix, * tmpPath;
|
1996-06-28 22:38:12 +08:00
|
|
|
int scriptArg;
|
1996-12-11 23:39:57 +08:00
|
|
|
int hasOthers = 0;
|
1996-07-10 10:33:38 +08:00
|
|
|
int relocationSize = 1; /* strip at least first / for cpio */
|
1996-08-29 12:16:07 +08:00
|
|
|
uint_32 * archiveSizePtr;
|
1996-01-09 03:31:44 +08:00
|
|
|
|
1996-02-22 02:09:31 +08:00
|
|
|
oldVersions = alloca(sizeof(int));
|
|
|
|
*oldVersions = 0;
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rc = rpmReadPackageHeader(fd, &h, &isSource, &major, &minor);
|
1996-01-09 03:31:44 +08:00
|
|
|
if (rc) return rc;
|
|
|
|
|
1996-02-15 01:54:37 +08:00
|
|
|
if (isSource) {
|
1996-11-19 02:02:36 +08:00
|
|
|
if (flags & RPMINSTALL_TEST) {
|
|
|
|
rpmMessage(RPMMESS_DEBUG, "stopping install as we're running --test\n");
|
1996-02-15 01:54:37 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1996-08-29 12:16:07 +08:00
|
|
|
if (major == 1) {
|
|
|
|
notify = NULL;
|
|
|
|
labelFormat = NULL;
|
|
|
|
h = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = installSources(h, rootdir, fd, NULL, notify, labelFormat);
|
1996-11-19 02:02:36 +08:00
|
|
|
if (h) headerFree(h);
|
1996-03-30 03:40:08 +08:00
|
|
|
|
1996-08-29 12:16:07 +08:00
|
|
|
return rc;
|
1996-07-10 10:33:38 +08:00
|
|
|
}
|
|
|
|
|
1996-07-11 23:48:21 +08:00
|
|
|
/* Do this now so we can give error messages, even though we'll just
|
|
|
|
do it again after relocating everything */
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &fileCount);
|
|
|
|
headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &fileCount);
|
|
|
|
headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &fileCount);
|
1996-07-11 23:48:21 +08:00
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
if (!headerGetEntry(h, RPMTAG_DEFAULTPREFIX, &type, (void *)
|
1996-07-10 10:33:38 +08:00
|
|
|
&defaultPrefix, &fileCount)) {
|
1996-07-10 22:11:19 +08:00
|
|
|
defaultPrefix = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (location && !defaultPrefix) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_NORELOCATE, "package %s-%s-%s is not relocatable",
|
1996-07-10 10:33:38 +08:00
|
|
|
name, version, release);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(h);
|
1996-07-10 10:33:38 +08:00
|
|
|
return 2;
|
1996-07-10 22:11:19 +08:00
|
|
|
} else if (!location && defaultPrefix)
|
|
|
|
location = defaultPrefix;
|
|
|
|
|
1996-07-10 10:33:38 +08:00
|
|
|
if (location) {
|
|
|
|
relocateFilelist(&h, defaultPrefix, location, &relocationSize);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_DEFAULTPREFIX, &type, (void *) &defaultPrefix,
|
1996-07-10 10:33:38 +08:00
|
|
|
&fileCount);
|
|
|
|
archivePrefix = alloca(strlen(rootdir) + strlen(location) + 2);
|
|
|
|
sprintf(archivePrefix, "%s/%s", rootdir, location);
|
1996-07-10 22:11:19 +08:00
|
|
|
} else {
|
1996-07-10 10:33:38 +08:00
|
|
|
archivePrefix = rootdir;
|
1996-07-10 22:11:19 +08:00
|
|
|
relocationSize = 1;
|
|
|
|
}
|
1996-07-10 10:33:38 +08:00
|
|
|
|
1996-10-21 10:17:39 +08:00
|
|
|
/* You're probably upset because name already points to the name of
|
|
|
|
this package, right? Almost... it points to the name in the original
|
1996-12-06 05:11:17 +08:00
|
|
|
header, which could have been trashed by relocateFileList() */
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &fileCount);
|
|
|
|
headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &fileCount);
|
|
|
|
headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &fileCount);
|
1996-01-15 03:32:17 +08:00
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
if (!(flags & RPMINSTALL_NOARCH) && !archOkay(h)) {
|
|
|
|
rpmError(RPMERR_BADARCH, "package %s-%s-%s is for a different "
|
1996-07-16 11:37:07 +08:00
|
|
|
"architecture", name, version, release);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(h);
|
1996-07-16 11:43:13 +08:00
|
|
|
return 2;
|
1996-07-16 11:37:07 +08:00
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
if (!(flags & RPMINSTALL_NOOS) && !osOkay(h)) {
|
|
|
|
rpmError(RPMERR_BADOS, "package %s-%s-%s is for a different "
|
1996-07-16 11:43:13 +08:00
|
|
|
"operating system", name, version, release);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(h);
|
1996-07-16 11:43:13 +08:00
|
|
|
return 2;
|
1996-02-27 06:45:24 +08:00
|
|
|
}
|
|
|
|
|
1996-10-21 10:17:39 +08:00
|
|
|
if (packageAlreadyInstalled(db, name, version, release, &otherOffset,
|
|
|
|
flags)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(h);
|
1996-10-21 10:17:39 +08:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
1996-02-25 07:46:09 +08:00
|
|
|
if (labelFormat) {
|
|
|
|
printf(labelFormat, name, version, release);
|
1996-02-20 08:24:43 +08:00
|
|
|
fflush(stdout);
|
1996-02-20 08:17:51 +08:00
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "package: %s-%s-%s files test = %d\n",
|
|
|
|
name, version, release, flags & RPMINSTALL_TEST);
|
1996-01-15 03:32:17 +08:00
|
|
|
|
1996-06-28 22:38:12 +08:00
|
|
|
rc = rpmdbFindPackage(db, name, &matches);
|
|
|
|
if (rc == -1) return 2;
|
1996-12-11 23:39:57 +08:00
|
|
|
if (rc) {
|
1996-06-28 22:38:12 +08:00
|
|
|
scriptArg = 1;
|
1996-12-11 23:39:57 +08:00
|
|
|
} else {
|
1996-12-11 23:53:58 +08:00
|
|
|
hasOthers = 1;
|
1996-06-28 22:38:12 +08:00
|
|
|
scriptArg = matches.count + 1;
|
1996-12-11 23:39:57 +08:00
|
|
|
}
|
1996-06-28 22:38:12 +08:00
|
|
|
|
1996-12-06 05:11:17 +08:00
|
|
|
/* This canonicalizes the root */
|
|
|
|
if (rootdir && rootdir[rootLength] == '/') {
|
|
|
|
char * newRootdir;
|
|
|
|
|
|
|
|
newRootdir = alloca(rootLength + 2);
|
|
|
|
strcpy(newRootdir, rootdir);
|
|
|
|
newRootdir[rootLength++] = '/';
|
|
|
|
newRootdir[rootLength] = '\0';
|
|
|
|
rootdir = newRootdir;
|
|
|
|
}
|
|
|
|
|
1996-12-11 23:39:57 +08:00
|
|
|
if (flags & RPMINSTALL_UPGRADE && hasOthers) {
|
1996-02-21 05:54:02 +08:00
|
|
|
/*
|
|
|
|
We need to get a list of all old version of this package. We let
|
|
|
|
this install procede normally then, but:
|
|
|
|
|
|
|
|
1) we don't report conflicts between the new package and
|
|
|
|
the old versions installed
|
|
|
|
2) when we're done, we uninstall the old versions
|
|
|
|
|
|
|
|
Note if the version being installed is already installed, we don't
|
|
|
|
put that in the list -- that situation is handled normally.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!rc) {
|
|
|
|
intptr = oldVersions = alloca((matches.count + 1) * sizeof(int));
|
|
|
|
for (i = 0; i < matches.count; i++) {
|
1996-02-26 06:11:00 +08:00
|
|
|
if (matches.recs[i].recOffset != otherOffset) {
|
1996-11-19 02:02:36 +08:00
|
|
|
if (!(flags & RPMINSTALL_UPGRADETOOLD))
|
1996-07-23 02:32:03 +08:00
|
|
|
if (rpmEnsureOlder(db, name, version, release,
|
1996-12-06 12:07:28 +08:00
|
|
|
matches.recs[i].recOffset)) {
|
|
|
|
headerFree(h);
|
|
|
|
dbiFreeIndexRecord(matches);
|
1996-04-16 05:09:40 +08:00
|
|
|
return 2;
|
1996-12-06 12:07:28 +08:00
|
|
|
}
|
1996-02-21 05:54:02 +08:00
|
|
|
*intptr++ = matches.recs[i].recOffset;
|
1996-02-26 06:11:00 +08:00
|
|
|
}
|
1996-02-21 05:54:02 +08:00
|
|
|
}
|
|
|
|
*intptr++ = 0;
|
|
|
|
}
|
1996-12-11 23:39:57 +08:00
|
|
|
}
|
1996-02-21 05:54:02 +08:00
|
|
|
|
1996-12-11 23:39:57 +08:00
|
|
|
if (hasOthers)
|
1996-12-07 04:25:36 +08:00
|
|
|
dbiFreeIndexRecord(matches);
|
1996-12-06 12:07:28 +08:00
|
|
|
|
1996-01-23 05:13:12 +08:00
|
|
|
fileList = NULL;
|
1996-11-19 02:02:36 +08:00
|
|
|
if (headerGetEntry(h, RPMTAG_FILENAMES, &type, (void **) &fileList,
|
1996-01-23 05:13:12 +08:00
|
|
|
&fileCount)) {
|
1996-10-21 10:17:39 +08:00
|
|
|
char ** netsharedPaths;
|
|
|
|
char ** nsp;
|
|
|
|
|
|
|
|
if (netsharedPath)
|
|
|
|
netsharedPaths = splitString(netsharedPath,
|
|
|
|
strlen(netsharedPath), ':');
|
|
|
|
else
|
|
|
|
netsharedPaths = NULL;
|
1996-01-23 05:13:12 +08:00
|
|
|
|
|
|
|
instActions = alloca(sizeof(enum instActions) * fileCount);
|
1996-12-06 05:11:17 +08:00
|
|
|
rootedFileList = alloca(sizeof(char *) * fileCount);
|
1996-10-21 10:17:39 +08:00
|
|
|
fileStatesList = alloca(sizeof(*fileStatesList) * fileCount);
|
1996-01-23 05:13:12 +08:00
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_FILEMD5S, &type, (void **) &fileMd5s, &fileCount);
|
|
|
|
headerGetEntry(h, RPMTAG_FILEFLAGS, &type, (void **) &fileFlagsList,
|
1996-01-23 05:13:12 +08:00
|
|
|
&fileCount);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_FILEMODES, &type, (void **) &fileModesList,
|
1996-02-29 11:38:33 +08:00
|
|
|
&fileCount);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_FILELINKTOS, &type, (void **) &fileLinkList,
|
1996-02-29 11:38:33 +08:00
|
|
|
&fileCount);
|
1996-01-23 05:13:12 +08:00
|
|
|
|
1996-01-30 03:37:59 +08:00
|
|
|
/* check for any config files that already exist. If they do, plan
|
|
|
|
on making a backup copy. If that's not the right thing to do
|
|
|
|
instHandleSharedFiles() below will take care of the problem */
|
|
|
|
for (i = 0; i < fileCount; i++) {
|
1996-12-06 05:11:17 +08:00
|
|
|
if (rootLength > 1) {
|
|
|
|
rootedFileList[i] = alloca(strlen(fileList[i]) +
|
|
|
|
rootLength + 3);
|
|
|
|
strcpy(rootedFileList[i], rootdir);
|
|
|
|
strcat(rootedFileList[i], fileList[i]);
|
1996-01-30 07:27:12 +08:00
|
|
|
} else
|
1996-12-06 05:11:17 +08:00
|
|
|
rootedFileList[i] = fileList[i];
|
1996-01-30 07:27:12 +08:00
|
|
|
|
1996-12-06 05:11:17 +08:00
|
|
|
/* netsharedPaths are not relative to the current root (though
|
|
|
|
they do need to take the package prefix into account */
|
1996-10-21 10:17:39 +08:00
|
|
|
for (nsp = netsharedPaths; nsp && *nsp; nsp++)
|
1996-12-06 05:11:17 +08:00
|
|
|
if (!strncmp(fileList[i], *nsp, strlen(*nsp))) break;
|
1996-03-30 04:52:03 +08:00
|
|
|
|
1996-10-21 10:17:39 +08:00
|
|
|
if (nsp && *nsp) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "file %s in netshared path\n",
|
1996-12-06 05:11:17 +08:00
|
|
|
rootedFileList[i]);
|
1996-10-21 10:17:39 +08:00
|
|
|
instActions[i] = SKIP;
|
|
|
|
fileStatesList[i] = RPMFILE_STATE_NETSHARED;
|
|
|
|
} else if ((fileFlagsList[i] & RPMFILE_DOC) &&
|
1996-11-19 02:02:36 +08:00
|
|
|
(flags & RPMINSTALL_NODOCS)) {
|
1996-03-30 04:52:03 +08:00
|
|
|
instActions[i] = SKIP;
|
1996-10-21 10:17:39 +08:00
|
|
|
fileStatesList[i] = RPMFILE_STATE_NOTINSTALLED;
|
|
|
|
} else {
|
|
|
|
fileStatesList[i] = RPMFILE_STATE_NORMAL;
|
|
|
|
|
|
|
|
instActions[i] = CREATE;
|
|
|
|
if ((fileFlagsList[i] & RPMFILE_CONFIG) &&
|
|
|
|
!S_ISDIR(fileModesList[i])) {
|
1996-12-06 05:11:17 +08:00
|
|
|
if (exists(rootedFileList[i])) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "%s exists - backing up\n",
|
1996-12-06 05:11:17 +08:00
|
|
|
rootedFileList[i]);
|
1996-10-21 10:17:39 +08:00
|
|
|
instActions[i] = BACKUP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1996-01-30 03:37:59 +08:00
|
|
|
}
|
|
|
|
|
1996-02-29 11:38:33 +08:00
|
|
|
rc = instHandleSharedFiles(db, 0, fileList, fileMd5s, fileModesList,
|
1996-07-28 07:35:07 +08:00
|
|
|
fileLinkList, fileFlagsList, fileCount,
|
1996-12-06 05:11:17 +08:00
|
|
|
instActions, rootedFileList, oldVersions,
|
1996-02-29 11:38:33 +08:00
|
|
|
&replacedList, flags);
|
1996-01-23 05:13:12 +08:00
|
|
|
|
|
|
|
free(fileMd5s);
|
1996-02-29 11:38:33 +08:00
|
|
|
free(fileLinkList);
|
1996-01-23 05:13:12 +08:00
|
|
|
if (rc) {
|
1996-02-16 05:08:48 +08:00
|
|
|
if (replacedList) free(replacedList);
|
1996-01-23 05:13:12 +08:00
|
|
|
free(fileList);
|
1996-04-16 05:09:40 +08:00
|
|
|
return 2;
|
1996-01-23 05:13:12 +08:00
|
|
|
}
|
|
|
|
}
|
1996-01-15 03:32:17 +08:00
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
if (flags & RPMINSTALL_TEST) {
|
|
|
|
rpmMessage(RPMMESS_DEBUG, "stopping install as we're running --test\n");
|
1996-01-23 05:13:12 +08:00
|
|
|
free(fileList);
|
1996-02-16 05:08:48 +08:00
|
|
|
if (replacedList) free(replacedList);
|
1996-01-15 03:32:17 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "running preinstall script (if any)\n");
|
1996-07-10 10:33:38 +08:00
|
|
|
if (runScript(rootdir, h, RPMTAG_PREIN, scriptArg,
|
1996-11-19 02:02:36 +08:00
|
|
|
flags & RPMINSTALL_NOSCRIPTS)) {
|
1996-01-23 05:13:12 +08:00
|
|
|
free(fileList);
|
1996-02-16 05:08:48 +08:00
|
|
|
if (replacedList) free(replacedList);
|
1996-01-09 03:31:44 +08:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
1996-01-23 05:13:12 +08:00
|
|
|
if (fileList) {
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_FILESIZES, &type, (void **) &fileSizesList,
|
1996-01-23 05:13:12 +08:00
|
|
|
&fileCount);
|
|
|
|
|
|
|
|
files = alloca(sizeof(struct fileToInstall) * fileCount);
|
1996-12-06 05:11:17 +08:00
|
|
|
finalFileList = alloca(sizeof(char *) * fileCount);
|
1996-12-06 06:04:44 +08:00
|
|
|
mkdirFileList = alloca(sizeof(char *) * fileCount);
|
|
|
|
mkdirModesList = alloca(sizeof(*mkdirModesList) * fileCount);
|
1996-01-23 05:13:12 +08:00
|
|
|
for (i = 0; i < fileCount; i++) {
|
1996-01-30 03:37:59 +08:00
|
|
|
switch (instActions[i]) {
|
|
|
|
case BACKUP:
|
|
|
|
ext = ".rpmorig";
|
|
|
|
installFile = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SAVE:
|
|
|
|
ext = ".rpmsave";
|
|
|
|
installFile = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CREATE:
|
|
|
|
installFile = 1;
|
|
|
|
ext = NULL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KEEP:
|
|
|
|
installFile = 0;
|
1996-03-30 04:52:03 +08:00
|
|
|
ext = NULL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SKIP:
|
|
|
|
installFile = 0;
|
1996-01-30 03:37:59 +08:00
|
|
|
ext = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ext) {
|
1996-12-06 05:11:17 +08:00
|
|
|
newpath = alloca(strlen(rootedFileList[i]) + 20);
|
|
|
|
strcpy(newpath, rootedFileList[i]);
|
1996-01-30 03:37:59 +08:00
|
|
|
strcat(newpath, ext);
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMMESS_BACKUP, "warning: %s saved as %s",
|
1996-12-06 05:11:17 +08:00
|
|
|
rootedFileList[i], newpath);
|
1996-01-30 03:37:59 +08:00
|
|
|
|
1996-12-06 05:11:17 +08:00
|
|
|
if (rename(rootedFileList[i], newpath)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_RENAME, "rename of %s to %s failed: %s",
|
1996-12-06 05:11:17 +08:00
|
|
|
rootedFileList[i], newpath, strerror(errno));
|
1996-02-16 05:08:48 +08:00
|
|
|
if (replacedList) free(replacedList);
|
1996-04-16 05:09:40 +08:00
|
|
|
return 2;
|
1996-01-30 03:37:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (installFile) {
|
1996-07-10 10:33:38 +08:00
|
|
|
/* if we are using a relocateable package, we need to strip
|
1996-10-21 10:17:39 +08:00
|
|
|
off whatever part of the (already relocated!) filelist
|
|
|
|
|
|
|
|
we also need to strip globbing characters, as cpio
|
|
|
|
globs the patterns we pass to it against the filenames
|
|
|
|
in the archive */
|
1996-01-30 03:37:59 +08:00
|
|
|
|
1996-10-21 10:17:39 +08:00
|
|
|
files[archiveFileCount].fileName =
|
|
|
|
alloca((strlen(fileList[i]) * 2) + 1);
|
|
|
|
|
|
|
|
unglobFilename(files[archiveFileCount].fileName,
|
|
|
|
fileList[i] + relocationSize);
|
1996-01-30 03:37:59 +08:00
|
|
|
files[archiveFileCount].size = fileSizesList[i];
|
1996-02-20 07:34:25 +08:00
|
|
|
|
1996-12-06 05:11:17 +08:00
|
|
|
|
1996-12-06 06:04:44 +08:00
|
|
|
/* both of these list what files need to be installed and
|
|
|
|
where they end up *after* any relocations have been done
|
|
|
|
the mkdir list includes direcories though, while the final
|
|
|
|
list does *not -- we don't let cpio expand directories as
|
|
|
|
it has a bad habit of replacing symlinks with directories
|
|
|
|
when we'd rather it didn't */
|
|
|
|
mkdirFileList[mkdirFileCount] = rootedFileList[i];
|
|
|
|
mkdirModesList[mkdirFileCount] = fileModesList[i];
|
|
|
|
mkdirFileCount++;
|
1996-12-06 05:11:17 +08:00
|
|
|
|
1996-12-06 06:04:44 +08:00
|
|
|
if (!S_ISDIR(fileModesList[i])) {
|
|
|
|
finalFileList[archiveFileCount] = rootedFileList[i];
|
|
|
|
archiveFileCount++;
|
|
|
|
}
|
1996-01-30 03:37:59 +08:00
|
|
|
}
|
1996-01-23 05:13:12 +08:00
|
|
|
}
|
|
|
|
|
1996-07-26 00:39:01 +08:00
|
|
|
if (rootdir) {
|
|
|
|
tmpPath = alloca(strlen(rootdir) + 15);
|
|
|
|
strcpy(tmpPath, rootdir);
|
1996-11-19 02:02:36 +08:00
|
|
|
strcat(tmpPath, rpmGetVar(RPMVAR_TMPPATH));
|
1996-07-26 00:39:01 +08:00
|
|
|
} else
|
1996-11-19 02:02:36 +08:00
|
|
|
tmpPath = rpmGetVar(RPMVAR_TMPPATH);
|
1996-07-26 00:39:01 +08:00
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
if (!headerGetEntry(h, RPMTAG_ARCHIVESIZE, &type, (void *) &archiveSizePtr,
|
1996-08-29 12:16:07 +08:00
|
|
|
&count))
|
|
|
|
archiveSizePtr = NULL;
|
|
|
|
|
1996-12-06 06:04:44 +08:00
|
|
|
if (createDirectories(mkdirFileList, mkdirModesList, mkdirFileCount)) {
|
1996-12-06 05:11:17 +08:00
|
|
|
headerFree(h);
|
|
|
|
free(fileList);
|
|
|
|
if (replacedList) free(replacedList);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
1996-01-15 03:32:17 +08:00
|
|
|
/* the file pointer for fd is pointing at the cpio archive */
|
1996-07-10 10:33:38 +08:00
|
|
|
if (installArchive(archivePrefix, fd, files, archiveFileCount, notify,
|
1996-08-29 12:16:07 +08:00
|
|
|
NULL, tmpPath,
|
|
|
|
archiveSizePtr ? *archiveSizePtr : 0)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(h);
|
1996-01-15 03:32:17 +08:00
|
|
|
free(fileList);
|
1996-02-16 05:08:48 +08:00
|
|
|
if (replacedList) free(replacedList);
|
1996-01-15 03:32:17 +08:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
if (headerGetEntry(h, RPMTAG_FILEUSERNAME, &type, (void **) &fileOwners,
|
1996-01-15 03:32:17 +08:00
|
|
|
&fileCount)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
if (headerGetEntry(h, RPMTAG_FILEGROUPNAME, &type, (void **) &fileGroups,
|
1996-01-15 03:32:17 +08:00
|
|
|
&fileCount)) {
|
1996-07-10 10:33:38 +08:00
|
|
|
if (setFileOwnerships(rootdir, fileList, fileOwners, fileGroups,
|
1996-05-23 10:42:51 +08:00
|
|
|
fileModesList, instActions, fileCount)) {
|
1996-01-15 03:32:17 +08:00
|
|
|
free(fileOwners);
|
|
|
|
free(fileGroups);
|
|
|
|
free(fileList);
|
1996-02-16 05:08:48 +08:00
|
|
|
if (replacedList) free(replacedList);
|
|
|
|
|
1996-01-15 03:32:17 +08:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
free(fileGroups);
|
|
|
|
}
|
|
|
|
free(fileOwners);
|
|
|
|
}
|
|
|
|
free(fileList);
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerAddEntry(h, RPMTAG_FILESTATES, RPM_CHAR_TYPE, fileStatesList, fileCount);
|
1996-01-09 03:31:44 +08:00
|
|
|
|
1996-01-30 03:37:59 +08:00
|
|
|
installTime = time(NULL);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerAddEntry(h, RPMTAG_INSTALLTIME, RPM_INT32_TYPE, &installTime, 1);
|
1996-01-09 03:31:44 +08:00
|
|
|
}
|
|
|
|
|
1996-02-16 05:08:48 +08:00
|
|
|
if (replacedList) {
|
|
|
|
rc = markReplacedFiles(db, replacedList);
|
|
|
|
free(replacedList);
|
|
|
|
|
|
|
|
if (rc) return rc;
|
|
|
|
}
|
|
|
|
|
1996-02-15 05:26:21 +08:00
|
|
|
/* if this package has already been installed, remove it from the database
|
|
|
|
before adding the new one */
|
|
|
|
if (otherOffset) {
|
|
|
|
rpmdbRemove(db, otherOffset, 1);
|
|
|
|
}
|
|
|
|
|
1996-01-09 03:31:44 +08:00
|
|
|
if (rpmdbAdd(db, h)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(h);
|
1996-01-09 03:31:44 +08:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "running postinstall script (if any)\n");
|
1996-01-30 03:37:59 +08:00
|
|
|
|
1996-07-10 10:33:38 +08:00
|
|
|
if (runScript(rootdir, h, RPMTAG_POSTIN, scriptArg,
|
1996-11-19 02:02:36 +08:00
|
|
|
flags & RPMINSTALL_NOSCRIPTS)) {
|
1996-04-16 05:09:40 +08:00
|
|
|
return 2;
|
1996-01-30 03:37:59 +08:00
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
if (flags & RPMINSTALL_UPGRADE) {
|
|
|
|
rpmMessage(RPMMESS_DEBUG, "removing old versions of package\n");
|
1996-02-21 05:54:02 +08:00
|
|
|
intptr = oldVersions;
|
|
|
|
while (*intptr) {
|
1996-07-10 10:33:38 +08:00
|
|
|
rpmRemovePackage(rootdir, db, *intptr, 0);
|
1996-02-21 05:54:02 +08:00
|
|
|
intptr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(h);
|
1996-08-31 03:17:33 +08:00
|
|
|
|
1996-01-09 03:31:44 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define BLOCKSIZE 1024
|
|
|
|
|
1996-09-06 03:58:04 +08:00
|
|
|
/* -1 fileCount means install all files */
|
1996-01-23 05:13:12 +08:00
|
|
|
static int installArchive(char * prefix, int fd, struct fileToInstall * files,
|
1996-11-19 02:02:36 +08:00
|
|
|
int fileCount, rpmNotifyFunction notify,
|
1996-08-29 12:16:07 +08:00
|
|
|
char ** specFile, char * tmpPath, int archiveSize) {
|
1996-01-09 03:31:44 +08:00
|
|
|
gzFile stream;
|
|
|
|
char buf[BLOCKSIZE];
|
|
|
|
pid_t child;
|
|
|
|
int p[2];
|
1996-01-23 05:13:12 +08:00
|
|
|
int statusPipe[2];
|
1996-01-09 03:31:44 +08:00
|
|
|
int bytesRead;
|
1996-01-23 05:13:12 +08:00
|
|
|
int bytes;
|
1996-01-09 03:31:44 +08:00
|
|
|
int status;
|
|
|
|
int cpioFailed = 0;
|
|
|
|
void * oldhandler;
|
1996-01-23 05:13:12 +08:00
|
|
|
int needSecondPipe;
|
|
|
|
char line[1024];
|
1996-01-30 03:37:59 +08:00
|
|
|
int j;
|
|
|
|
int i = 0;
|
1996-11-23 06:24:59 +08:00
|
|
|
int childGotStatus = 0;
|
1996-01-23 05:13:12 +08:00
|
|
|
unsigned long totalSize = 0;
|
|
|
|
unsigned long sizeInstalled = 0;
|
|
|
|
struct fileToInstall fileInstalled;
|
|
|
|
struct fileToInstall * file;
|
1996-07-26 00:39:01 +08:00
|
|
|
char * chptr, * filelist;
|
1996-01-30 03:37:59 +08:00
|
|
|
char ** args;
|
1996-05-07 11:21:44 +08:00
|
|
|
FILE * f;
|
1996-02-15 01:54:37 +08:00
|
|
|
int len;
|
1996-02-15 05:56:29 +08:00
|
|
|
int childDead = 0;
|
1996-01-09 03:31:44 +08:00
|
|
|
|
1996-09-06 03:58:04 +08:00
|
|
|
/* no files to install */
|
1996-09-01 02:35:40 +08:00
|
|
|
if (!fileCount) return 0;
|
|
|
|
|
1996-09-06 03:58:04 +08:00
|
|
|
/* install all files, so don't pass a filelist to cpio */
|
|
|
|
if (fileCount == -1) fileCount = 0;
|
|
|
|
|
1996-01-09 03:31:44 +08:00
|
|
|
/* fd should be a gzipped cpio archive */
|
1996-01-23 05:13:12 +08:00
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "installing archive into %s\n", prefix);
|
1996-07-10 22:11:19 +08:00
|
|
|
|
1996-08-29 12:16:07 +08:00
|
|
|
needSecondPipe = (notify != NULL && !archiveSize) || specFile;
|
1996-02-15 01:54:37 +08:00
|
|
|
|
|
|
|
if (specFile) *specFile = NULL;
|
1996-01-09 03:31:44 +08:00
|
|
|
|
1996-01-30 03:37:59 +08:00
|
|
|
args = alloca(sizeof(char *) * (fileCount + 10));
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
args[i++] = rpmGetVar(RPMVAR_CPIOBIN);
|
1996-01-30 03:37:59 +08:00
|
|
|
args[i++] = "--extract";
|
|
|
|
args[i++] = "--unconditional";
|
|
|
|
args[i++] = "--preserve-modification-time";
|
|
|
|
args[i++] = "--make-directories";
|
|
|
|
args[i++] = "--quiet";
|
|
|
|
|
1996-10-15 07:49:27 +08:00
|
|
|
if (!args[0]) args[0] = "cpio";
|
|
|
|
|
1996-01-30 03:37:59 +08:00
|
|
|
if (needSecondPipe)
|
|
|
|
args[i++] = "--verbose";
|
|
|
|
|
1996-02-15 01:54:37 +08:00
|
|
|
/* note - if fileCount == 0, all files get installed */
|
1996-05-07 11:21:44 +08:00
|
|
|
/* if fileCount > 500, we use a temporary file to pass the file
|
|
|
|
list to cpio rather then args because we're in danger of passing
|
|
|
|
too much argv/env stuff */
|
|
|
|
|
|
|
|
if (fileCount > 500) {
|
1996-07-26 00:39:01 +08:00
|
|
|
filelist = alloca(strlen(tmpPath) + 40);
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "using a %s filelist\n", tmpPath);
|
1996-09-26 03:14:17 +08:00
|
|
|
sprintf(filelist, "%s/rpm-cpiofilelist.%d.tmp", tmpPath,
|
|
|
|
(int) getpid());
|
1996-05-07 11:21:44 +08:00
|
|
|
f = fopen(filelist, "w");
|
|
|
|
if (!f) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_CREATE, "failed to create %s: %s", filelist,
|
1996-05-07 11:21:44 +08:00
|
|
|
strerror(errno));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (j = 0; j < fileCount; j++) {
|
|
|
|
if ((fputs(files[j].fileName, f) == EOF) ||
|
|
|
|
(fputs("\n", f) == EOF)) {
|
|
|
|
if (errno == ENOSPC) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_NOSPACE, "out of space on device");
|
1996-05-07 11:21:44 +08:00
|
|
|
} else {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_CREATE, "failed to create %s: %s", filelist,
|
1996-05-07 11:21:44 +08:00
|
|
|
strerror(errno));
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(f);
|
|
|
|
unlink(filelist);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
1996-02-15 01:54:37 +08:00
|
|
|
|
1996-05-07 11:21:44 +08:00
|
|
|
fclose(f);
|
1996-01-30 03:37:59 +08:00
|
|
|
|
1996-05-07 11:21:44 +08:00
|
|
|
args[i++] = "--pattern-file";
|
|
|
|
args[i++] = filelist;
|
|
|
|
} else {
|
1996-07-26 00:39:01 +08:00
|
|
|
filelist = NULL;
|
1996-05-07 11:21:44 +08:00
|
|
|
for (j = 0; j < fileCount; j++)
|
|
|
|
args[i++] = files[j].fileName;
|
|
|
|
}
|
1996-07-14 06:18:48 +08:00
|
|
|
|
|
|
|
args[i++] = NULL;
|
1996-01-30 03:37:59 +08:00
|
|
|
|
1996-01-09 03:31:44 +08:00
|
|
|
stream = gzdopen(fd, "r");
|
|
|
|
pipe(p);
|
|
|
|
|
1996-01-23 05:13:12 +08:00
|
|
|
if (needSecondPipe) {
|
|
|
|
pipe(statusPipe);
|
|
|
|
for (i = 0; i < fileCount; i++)
|
|
|
|
totalSize += files[i].size;
|
|
|
|
qsort(files, fileCount, sizeof(struct fileToInstall), fileCompare);
|
1996-01-09 03:31:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
oldhandler = signal(SIGPIPE, SIG_IGN);
|
|
|
|
|
|
|
|
child = fork();
|
|
|
|
if (!child) {
|
1996-01-23 05:13:12 +08:00
|
|
|
chdir(prefix);
|
|
|
|
|
1996-01-09 03:31:44 +08:00
|
|
|
close(p[1]); /* we don't need to write to it */
|
|
|
|
close(0); /* stdin will come from the pipe instead */
|
|
|
|
dup2(p[0], 0);
|
|
|
|
close(p[0]);
|
|
|
|
|
1996-01-23 05:13:12 +08:00
|
|
|
if (needSecondPipe) {
|
|
|
|
close(statusPipe[0]); /* we don't need to read from it*/
|
|
|
|
close(2); /* stderr will go to a pipe instead */
|
|
|
|
dup2(statusPipe[1], 2);
|
|
|
|
close(statusPipe[1]);
|
|
|
|
}
|
|
|
|
|
1996-05-23 03:39:24 +08:00
|
|
|
execvp(args[0], args);
|
1996-01-30 03:37:59 +08:00
|
|
|
|
1996-08-31 03:17:33 +08:00
|
|
|
_exit(-1);
|
1996-01-09 03:31:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
close(p[0]);
|
1996-01-23 05:13:12 +08:00
|
|
|
if (needSecondPipe) {
|
|
|
|
close(statusPipe[1]);
|
|
|
|
fcntl(statusPipe[0], F_SETFL, O_NONBLOCK);
|
|
|
|
}
|
1996-01-09 03:31:44 +08:00
|
|
|
|
|
|
|
do {
|
1996-02-15 05:56:29 +08:00
|
|
|
if (waitpid(child, &status, WNOHANG)) childDead = 1;
|
|
|
|
|
1996-01-09 03:31:44 +08:00
|
|
|
bytesRead = gzread(stream, buf, sizeof(buf));
|
1996-07-16 11:43:13 +08:00
|
|
|
if (bytesRead < 0) {
|
1996-07-16 11:37:07 +08:00
|
|
|
cpioFailed = 1;
|
|
|
|
childDead = 1;
|
1996-11-01 03:54:26 +08:00
|
|
|
kill(child, SIGTERM);
|
1996-11-01 03:45:35 +08:00
|
|
|
} else if (bytesRead == 0) {
|
|
|
|
/* if it's not dead yet, it will be when we close the pipe */
|
1996-11-23 06:24:59 +08:00
|
|
|
waitpid(child, &status, 0);
|
1996-11-01 03:45:35 +08:00
|
|
|
childDead = 1;
|
1996-11-23 06:24:59 +08:00
|
|
|
childGotStatus = 1;
|
1996-11-01 03:45:35 +08:00
|
|
|
} else if (bytesRead && write(p[1], buf, bytesRead) != bytesRead) {
|
1996-01-09 03:31:44 +08:00
|
|
|
cpioFailed = 1;
|
1996-02-15 05:56:29 +08:00
|
|
|
childDead = 1;
|
1996-11-01 03:54:26 +08:00
|
|
|
kill(child, SIGTERM);
|
1996-01-09 03:31:44 +08:00
|
|
|
}
|
1996-01-23 05:13:12 +08:00
|
|
|
|
|
|
|
if (needSecondPipe) {
|
|
|
|
bytes = read(statusPipe[0], line, sizeof(line));
|
1996-02-15 05:56:29 +08:00
|
|
|
|
1996-01-30 03:37:59 +08:00
|
|
|
while (bytes > 0) {
|
1996-05-07 11:21:44 +08:00
|
|
|
/* the sooner we erase this, the better. less chance
|
|
|
|
of leaving it sitting around after a SIGINT
|
|
|
|
(or SIGSEGV!) */
|
1996-07-26 00:39:01 +08:00
|
|
|
if (filelist) {
|
1996-05-07 11:21:44 +08:00
|
|
|
unlink(filelist);
|
1996-07-26 00:39:01 +08:00
|
|
|
filelist = NULL;
|
1996-05-07 11:21:44 +08:00
|
|
|
}
|
|
|
|
|
1996-01-23 05:13:12 +08:00
|
|
|
fileInstalled.fileName = line;
|
|
|
|
|
|
|
|
while ((chptr = (strchr(fileInstalled.fileName, '\n')))) {
|
|
|
|
*chptr = '\0';
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "file \"%s\" complete\n",
|
1996-02-15 05:56:29 +08:00
|
|
|
fileInstalled.fileName);
|
1996-01-23 05:13:12 +08:00
|
|
|
|
1996-08-29 12:16:07 +08:00
|
|
|
if (notify && !archiveSize) {
|
1996-02-15 01:54:37 +08:00
|
|
|
file = bsearch(&fileInstalled, files, fileCount,
|
|
|
|
sizeof(struct fileToInstall),
|
|
|
|
fileCompare);
|
|
|
|
if (file) {
|
|
|
|
sizeInstalled += file->size;
|
|
|
|
notify(sizeInstalled, totalSize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (specFile) {
|
|
|
|
len = strlen(fileInstalled.fileName);
|
|
|
|
if (fileInstalled.fileName[len - 1] == 'c' &&
|
|
|
|
fileInstalled.fileName[len - 2] == 'e' &&
|
|
|
|
fileInstalled.fileName[len - 3] == 'p' &&
|
|
|
|
fileInstalled.fileName[len - 4] == 's' &&
|
|
|
|
fileInstalled.fileName[len - 5] == '.') {
|
|
|
|
|
|
|
|
if (*specFile) free(*specFile);
|
|
|
|
*specFile = strdup(fileInstalled.fileName);
|
|
|
|
}
|
1996-01-23 05:13:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fileInstalled.fileName = chptr + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bytes = read(statusPipe[0], line, sizeof(line));
|
|
|
|
}
|
1996-08-29 12:16:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (notify && archiveSize) {
|
|
|
|
sizeInstalled += bytesRead;
|
|
|
|
notify(sizeInstalled, archiveSize);
|
1996-01-23 05:13:12 +08:00
|
|
|
}
|
1996-02-15 05:56:29 +08:00
|
|
|
} while (!childDead);
|
1996-01-09 03:31:44 +08:00
|
|
|
|
|
|
|
gzclose(stream);
|
|
|
|
close(p[1]);
|
1996-01-23 05:13:12 +08:00
|
|
|
if (needSecondPipe) close(statusPipe[0]);
|
1996-01-09 03:31:44 +08:00
|
|
|
signal(SIGPIPE, oldhandler);
|
1996-11-23 06:24:59 +08:00
|
|
|
|
|
|
|
if (!childGotStatus)
|
|
|
|
waitpid(child, &status, 0);
|
1996-01-09 03:31:44 +08:00
|
|
|
|
1996-07-26 00:39:01 +08:00
|
|
|
if (filelist) {
|
1996-05-07 11:21:44 +08:00
|
|
|
unlink(filelist);
|
|
|
|
}
|
|
|
|
|
1996-01-09 03:31:44 +08:00
|
|
|
if (cpioFailed || !WIFEXITED(status) || WEXITSTATUS(status)) {
|
|
|
|
/* this would probably be a good place to check if disk space
|
|
|
|
was used up - if so, we should return a different error */
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_CPIO, "unpacking of archive failed");
|
1996-01-09 03:31:44 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1996-01-30 03:37:59 +08:00
|
|
|
if (notify)
|
|
|
|
notify(totalSize, totalSize);
|
1996-01-23 05:13:12 +08:00
|
|
|
|
1996-01-09 03:31:44 +08:00
|
|
|
return 0;
|
|
|
|
}
|
1996-01-15 03:32:17 +08:00
|
|
|
|
|
|
|
static int packageAlreadyInstalled(rpmdb db, char * name, char * version,
|
1996-02-15 05:26:21 +08:00
|
|
|
char * release, int * offset, int flags) {
|
1996-01-15 03:32:17 +08:00
|
|
|
char * secVersion, * secRelease;
|
|
|
|
Header sech;
|
|
|
|
int i;
|
1996-11-19 02:02:36 +08:00
|
|
|
dbiIndexSet matches;
|
1996-01-15 03:32:17 +08:00
|
|
|
int type, count;
|
|
|
|
|
|
|
|
if (!rpmdbFindPackage(db, name, &matches)) {
|
|
|
|
for (i = 0; i < matches.count; i++) {
|
|
|
|
sech = rpmdbGetRecord(db, matches.recs[i].recOffset);
|
|
|
|
if (!sech) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(sech, RPMTAG_VERSION, &type, (void **) &secVersion,
|
1996-01-15 03:32:17 +08:00
|
|
|
&count);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(sech, RPMTAG_RELEASE, &type, (void **) &secRelease,
|
1996-01-15 03:32:17 +08:00
|
|
|
&count);
|
|
|
|
|
|
|
|
if (!strcmp(secVersion, version) && !strcmp(secRelease, release)) {
|
1996-02-15 05:26:21 +08:00
|
|
|
*offset = matches.recs[i].recOffset;
|
1996-11-19 02:02:36 +08:00
|
|
|
if (!(flags & RPMINSTALL_REPLACEPKG)) {
|
|
|
|
rpmError(RPMERR_PKGINSTALLED,
|
1996-01-15 03:32:17 +08:00
|
|
|
"package %s-%s-%s is already installed",
|
|
|
|
name, version, release);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(sech);
|
1996-01-15 03:32:17 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
1996-02-20 06:15:38 +08:00
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(sech);
|
1996-01-15 03:32:17 +08:00
|
|
|
}
|
1996-12-06 12:07:28 +08:00
|
|
|
|
|
|
|
dbiFreeIndexRecord(matches);
|
1996-01-15 03:32:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1996-07-10 10:33:38 +08:00
|
|
|
static int setFileOwnerships(char * rootdir, char ** fileList,
|
1996-01-15 03:32:17 +08:00
|
|
|
char ** fileOwners, char ** fileGroups,
|
1996-05-23 10:42:51 +08:00
|
|
|
int_16 * fileModesList,
|
1996-03-30 04:52:03 +08:00
|
|
|
enum instActions * instActions, int fileCount) {
|
1996-01-15 03:32:17 +08:00
|
|
|
int i;
|
1996-06-28 01:18:07 +08:00
|
|
|
char * chptr;
|
1996-06-28 04:52:29 +08:00
|
|
|
int doFork = 0;
|
1996-06-28 01:18:07 +08:00
|
|
|
pid_t child;
|
|
|
|
int status;
|
1996-01-15 03:32:17 +08:00
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "setting file owners and groups by name (not id)\n");
|
1996-01-15 03:32:17 +08:00
|
|
|
|
1996-07-10 10:33:38 +08:00
|
|
|
chptr = rootdir;
|
1996-06-28 01:18:07 +08:00
|
|
|
while (*chptr && *chptr == '/')
|
|
|
|
chptr++;
|
|
|
|
|
|
|
|
if (*chptr) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "forking child to setid's in chroot() "
|
1996-06-28 01:18:07 +08:00
|
|
|
"environment\n");
|
|
|
|
doFork = 1;
|
|
|
|
|
|
|
|
if ((child = fork())) {
|
|
|
|
waitpid(child, &status, 0);
|
|
|
|
return 0;
|
|
|
|
} else {
|
1996-07-10 10:33:38 +08:00
|
|
|
chroot(rootdir);
|
1996-06-28 01:18:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-01-15 03:32:17 +08:00
|
|
|
for (i = 0; i < fileCount; i++) {
|
1996-03-30 04:52:03 +08:00
|
|
|
if (instActions[i] != SKIP) {
|
|
|
|
/* ignore errors here - setFileOwner handles them reasonable
|
|
|
|
and we want to keep running */
|
1996-06-28 01:18:07 +08:00
|
|
|
setFileOwner(fileList[i], fileOwners[i], fileGroups[i],
|
1996-05-23 10:42:51 +08:00
|
|
|
fileModesList[i]);
|
1996-03-30 04:52:03 +08:00
|
|
|
}
|
1996-01-15 03:32:17 +08:00
|
|
|
}
|
|
|
|
|
1996-06-28 01:18:07 +08:00
|
|
|
if (doFork)
|
1996-08-31 03:17:33 +08:00
|
|
|
_exit(0);
|
1996-06-28 01:18:07 +08:00
|
|
|
|
1996-01-15 03:32:17 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* setFileOwner() is really poorly implemented. It 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 :-( */
|
|
|
|
|
1996-06-28 01:18:07 +08:00
|
|
|
static int setFileOwner(char * file, char * owner, char * group,
|
|
|
|
int_16 mode ) {
|
1996-01-15 03:32:17 +08:00
|
|
|
static char * lastOwner = NULL, * lastGroup = NULL;
|
|
|
|
static uid_t lastUID;
|
|
|
|
static gid_t lastGID;
|
|
|
|
uid_t uid = 0;
|
|
|
|
gid_t gid = 0;
|
|
|
|
struct passwd * pwent;
|
|
|
|
struct group * grent;
|
|
|
|
|
|
|
|
if (!strcmp(owner, "root"))
|
|
|
|
uid = 0;
|
|
|
|
else if (lastOwner && !strcmp(lastOwner, owner))
|
|
|
|
uid = lastUID;
|
|
|
|
else {
|
|
|
|
pwent = getpwnam(owner);
|
|
|
|
if (!pwent) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_NOUSER, "user %s does not exist - using root", owner);
|
1996-01-15 03:32:17 +08:00
|
|
|
uid = 0;
|
|
|
|
} else {
|
|
|
|
uid = pwent->pw_uid;
|
|
|
|
if (lastOwner) free(lastOwner);
|
|
|
|
lastOwner = strdup(owner);
|
|
|
|
lastUID = uid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(group, "root"))
|
|
|
|
gid = 0;
|
|
|
|
else if (lastGroup && !strcmp(lastGroup, group))
|
|
|
|
gid = lastGID;
|
|
|
|
else {
|
|
|
|
grent = getgrnam(group);
|
|
|
|
if (!grent) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_NOGROUP, "group %s does not exist - using root",
|
1996-01-15 03:32:17 +08:00
|
|
|
group);
|
|
|
|
gid = 0;
|
|
|
|
} else {
|
|
|
|
gid = grent->gr_gid;
|
|
|
|
if (lastGroup) free(lastGroup);
|
1996-09-20 22:40:57 +08:00
|
|
|
lastGroup = strdup(group);
|
1996-01-15 03:32:17 +08:00
|
|
|
lastGID = gid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "%s owned by %s (%d), group %s (%d) mode %o\n",
|
1996-06-28 01:18:07 +08:00
|
|
|
file, owner, uid, group, gid, mode & 07777);
|
|
|
|
if (chown(file, uid, gid)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_CHOWN, "cannot set owner and group for %s - %s",
|
1996-06-28 01:18:07 +08:00
|
|
|
file, strerror(errno));
|
1996-01-31 01:35:13 +08:00
|
|
|
/* screw with the permissions so it's not SUID and 0.0 */
|
1996-06-28 01:18:07 +08:00
|
|
|
chmod(file, 0644);
|
1996-01-15 03:32:17 +08:00
|
|
|
return 1;
|
|
|
|
}
|
1996-05-23 10:42:51 +08:00
|
|
|
/* Also set the mode according to what is stored in the header */
|
1996-06-05 06:53:56 +08:00
|
|
|
if (! S_ISLNK(mode)) {
|
1996-06-28 01:18:07 +08:00
|
|
|
if (chmod(file, mode & 07777)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_CHOWN, "cannot change mode for %s - %s",
|
1996-06-28 01:18:07 +08:00
|
|
|
file, strerror(errno));
|
1996-06-05 06:53:56 +08:00
|
|
|
/* screw with the permissions so it's not SUID and 0.0 */
|
1996-06-28 01:18:07 +08:00
|
|
|
chmod(file, 0644);
|
1996-06-05 06:53:56 +08:00
|
|
|
return 1;
|
|
|
|
}
|
1996-05-23 10:42:51 +08:00
|
|
|
}
|
1996-01-15 03:32:17 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This could be more efficient. A brute force tokenization and mkdir's
|
1996-01-30 03:37:59 +08:00
|
|
|
seems like horrible overkill. I did make it know better then trying to
|
1996-12-06 06:04:44 +08:00
|
|
|
create the same directory string twice in a row though. That should make it
|
1996-01-30 03:37:59 +08:00
|
|
|
perform adequatally thanks to the sorted filelist.
|
1996-01-15 03:32:17 +08:00
|
|
|
|
|
|
|
This could create directories that should be symlinks :-( RPM building
|
1996-12-06 06:04:44 +08:00
|
|
|
should probably resolve symlinks in paths.
|
1996-01-15 03:32:17 +08:00
|
|
|
|
1996-01-30 03:37:59 +08:00
|
|
|
This creates directories which are always 0755, despite the current umask */
|
1996-01-15 03:32:17 +08:00
|
|
|
|
1996-12-06 06:04:44 +08:00
|
|
|
static int createDirectories(char ** fileList, uint_32 * modesList,
|
|
|
|
int fileCount) {
|
1996-01-15 03:32:17 +08:00
|
|
|
int i;
|
|
|
|
char * lastDirectory;
|
|
|
|
char * buffer;
|
|
|
|
int bufferLength;
|
|
|
|
int neededLength;
|
|
|
|
char * chptr;
|
|
|
|
|
|
|
|
lastDirectory = malloc(1);
|
|
|
|
lastDirectory[0] = '\0';
|
|
|
|
|
|
|
|
bufferLength = 1000; /* should be more then adequate */
|
|
|
|
buffer = malloc(bufferLength);
|
|
|
|
|
|
|
|
for (i = 0; i < fileCount; i++) {
|
1996-12-06 05:11:17 +08:00
|
|
|
neededLength = strlen(fileList[i]) + 1;
|
1996-01-15 03:32:17 +08:00
|
|
|
if (neededLength > bufferLength) {
|
|
|
|
free(buffer);
|
|
|
|
bufferLength = neededLength * 2;
|
|
|
|
buffer = malloc(bufferLength);
|
|
|
|
}
|
1996-12-06 05:11:17 +08:00
|
|
|
strcpy(buffer, fileList[i]);
|
1996-01-15 03:32:17 +08:00
|
|
|
|
|
|
|
for (chptr = buffer + strlen(buffer) - 1; *chptr; chptr--) {
|
|
|
|
if (*chptr == '/') break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! *chptr) continue; /* no path, just filename */
|
|
|
|
if (chptr == buffer) continue; /* /filename - no directories */
|
|
|
|
|
|
|
|
*chptr = '\0'; /* buffer is now just directories */
|
|
|
|
|
1996-12-06 06:04:44 +08:00
|
|
|
if (strcmp(buffer, lastDirectory)) {
|
|
|
|
for (chptr = buffer + 1; *chptr; chptr++) {
|
|
|
|
if (*chptr == '/') {
|
|
|
|
if (*(chptr -1) != '/') {
|
|
|
|
*chptr = '\0';
|
|
|
|
if (mkdirIfNone(buffer, 0755)) {
|
|
|
|
free(lastDirectory);
|
|
|
|
free(buffer);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
*chptr = '/';
|
1996-01-30 07:27:12 +08:00
|
|
|
}
|
1996-01-15 03:32:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-12-06 06:04:44 +08:00
|
|
|
if (mkdirIfNone(buffer, 0755)) {
|
|
|
|
free(lastDirectory);
|
|
|
|
free(buffer);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1996-01-15 03:32:17 +08:00
|
|
|
free(lastDirectory);
|
1996-12-06 06:04:44 +08:00
|
|
|
lastDirectory = strdup(buffer);
|
1996-01-15 03:32:17 +08:00
|
|
|
}
|
|
|
|
|
1996-12-06 06:04:44 +08:00
|
|
|
if (S_ISDIR(modesList[i])) {
|
|
|
|
if (mkdirIfNone(fileList[i], 0755)) {
|
|
|
|
free(lastDirectory);
|
|
|
|
free(buffer);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
1996-01-15 03:32:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
free(lastDirectory);
|
|
|
|
free(buffer);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mkdirIfNone(char * directory, mode_t perms) {
|
|
|
|
int rc;
|
|
|
|
char * chptr;
|
|
|
|
|
|
|
|
/* if the path is '/' we get ENOFILE not found" from mkdir, rather
|
|
|
|
then EEXIST which is weird */
|
|
|
|
for (chptr = directory; *chptr; chptr++)
|
|
|
|
if (*chptr != '/') break;
|
|
|
|
if (!*chptr) return 0;
|
|
|
|
|
1996-02-15 06:20:08 +08:00
|
|
|
if (exists(directory)) return 0;
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "trying to make %s\n", directory);
|
1996-01-15 03:32:17 +08:00
|
|
|
|
|
|
|
rc = mkdir(directory, perms);
|
|
|
|
if (!rc || errno == EEXIST) return 0;
|
|
|
|
|
1996-01-30 03:37:59 +08:00
|
|
|
chmod(directory, perms); /* this should not be modified by the umask */
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_MKDIR, "failed to create %s - %s", directory,
|
1996-01-15 03:32:17 +08:00
|
|
|
strerror(errno));
|
|
|
|
|
|
|
|
return errno;
|
|
|
|
}
|
1996-01-23 05:13:12 +08:00
|
|
|
|
1996-09-26 03:14:17 +08:00
|
|
|
static int filecmp(short mode1, char * md51, char * link1,
|
|
|
|
short mode2, char * md52, char * link2) {
|
1996-02-29 11:38:33 +08:00
|
|
|
enum fileTypes what1, what2;
|
|
|
|
|
|
|
|
what1 = whatis(mode1);
|
|
|
|
what2 = whatis(mode2);
|
|
|
|
|
|
|
|
if (what1 != what2) return 1;
|
|
|
|
|
|
|
|
if (what1 == LINK)
|
|
|
|
return strcmp(link1, link2);
|
|
|
|
else if (what1 == REG)
|
|
|
|
return strcmp(md51, md52);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1996-09-26 03:14:17 +08:00
|
|
|
static enum instActions decideFileFate(char * filespec, short dbMode,
|
1996-09-29 10:27:20 +08:00
|
|
|
char * dbMd5, char * dbLink, short newMode,
|
|
|
|
char * newMd5, char * newLink, int brokenMd5) {
|
1996-02-29 11:38:33 +08:00
|
|
|
char buffer[1024];
|
|
|
|
char * dbAttr, * newAttr;
|
|
|
|
enum fileTypes dbWhat, newWhat, diskWhat;
|
|
|
|
struct stat sb;
|
1996-09-01 02:35:40 +08:00
|
|
|
int i, rc;
|
1996-02-29 11:38:33 +08:00
|
|
|
|
|
|
|
if (lstat(filespec, &sb)) {
|
|
|
|
/* the file doesn't exist on the disk - might as well make it */
|
|
|
|
return CREATE;
|
|
|
|
}
|
|
|
|
|
|
|
|
diskWhat = whatis(sb.st_mode);
|
|
|
|
dbWhat = whatis(dbMode);
|
|
|
|
newWhat = whatis(newMode);
|
|
|
|
|
|
|
|
if (diskWhat != newWhat) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, " file type on disk is different then package - "
|
1996-02-29 11:38:33 +08:00
|
|
|
"saving\n");
|
|
|
|
return SAVE;
|
|
|
|
} else if (newWhat != dbWhat && diskWhat != dbWhat) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, " file type in database is different then disk"
|
1996-02-29 11:38:33 +08:00
|
|
|
" and package file - saving\n");
|
|
|
|
return SAVE;
|
|
|
|
} else if (dbWhat != newWhat) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, " file type changed - replacing\n");
|
1996-02-29 11:38:33 +08:00
|
|
|
return CREATE;
|
|
|
|
} else if (dbWhat != LINK && dbWhat != REG) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, " can't check file for changes - replacing\n");
|
1996-02-29 11:38:33 +08:00
|
|
|
return CREATE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dbWhat == REG) {
|
1996-09-01 02:35:40 +08:00
|
|
|
if (brokenMd5)
|
|
|
|
rc = mdfileBroken(filespec, buffer);
|
|
|
|
else
|
|
|
|
rc = mdfile(filespec, buffer);
|
|
|
|
|
|
|
|
if (rc) {
|
1996-02-29 11:38:33 +08:00
|
|
|
/* assume the file has been removed, don't freak */
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, " file not present - creating");
|
1996-02-29 11:38:33 +08:00
|
|
|
return CREATE;
|
|
|
|
}
|
|
|
|
dbAttr = dbMd5;
|
|
|
|
newAttr = newMd5;
|
|
|
|
} else /* dbWhat == LINK */ {
|
1996-08-09 00:46:15 +08:00
|
|
|
memset(buffer, 0, sizeof(buffer));
|
1996-02-29 11:38:33 +08:00
|
|
|
i = readlink(filespec, buffer, sizeof(buffer) - 1);
|
|
|
|
if (i == -1) {
|
|
|
|
/* assume the file has been removed, don't freak */
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, " file not present - creating");
|
1996-02-29 11:38:33 +08:00
|
|
|
return CREATE;
|
|
|
|
}
|
|
|
|
dbAttr = dbLink;
|
|
|
|
newAttr = newLink;
|
|
|
|
}
|
|
|
|
|
1996-09-01 02:35:40 +08:00
|
|
|
/* this order matters - we'd prefer to CREATE the file if at all
|
1996-03-01 09:59:26 +08:00
|
|
|
possible in case something else (like the timestamp) has changed */
|
1996-02-29 11:38:33 +08:00
|
|
|
|
|
|
|
if (!strcmp(dbAttr, buffer)) {
|
|
|
|
/* this config file has never been modified, so
|
|
|
|
just replace it */
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, " old == current, replacing "
|
1996-02-29 11:38:33 +08:00
|
|
|
"with new version\n");
|
|
|
|
return CREATE;
|
|
|
|
}
|
|
|
|
|
1996-03-01 09:59:26 +08:00
|
|
|
if (!strcmp(dbAttr, newAttr)) {
|
|
|
|
/* this file is the same in all versions of this package */
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, " old == new, keeping\n");
|
1996-03-01 09:59:26 +08:00
|
|
|
return KEEP;
|
|
|
|
}
|
|
|
|
|
1996-02-29 11:38:33 +08:00
|
|
|
/* the config file on the disk has been modified, but
|
|
|
|
the ones in the two packages are different. It would
|
|
|
|
be nice if RPM was smart enough to at least try and
|
|
|
|
merge the difference ala CVS, but... */
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, " files changed too much - backing up\n");
|
1996-02-29 11:38:33 +08:00
|
|
|
|
|
|
|
return SAVE;
|
|
|
|
}
|
|
|
|
|
1996-01-23 05:13:12 +08:00
|
|
|
/* return 0: okay, continue install */
|
|
|
|
/* return 1: problem, halt install */
|
|
|
|
|
|
|
|
static int instHandleSharedFiles(rpmdb db, int ignoreOffset, char ** fileList,
|
1996-02-29 11:38:33 +08:00
|
|
|
char ** fileMd5List, int_16 * fileModesList,
|
1996-07-28 07:35:07 +08:00
|
|
|
char ** fileLinkList, uint_32 * fileFlagsList,
|
1996-02-29 11:38:33 +08:00
|
|
|
int fileCount, enum instActions * instActions,
|
1996-02-21 05:54:02 +08:00
|
|
|
char ** prefixedFileList, int * notErrors,
|
1996-02-16 05:08:48 +08:00
|
|
|
struct replacedFile ** repListPtr, int flags) {
|
1996-01-23 05:13:12 +08:00
|
|
|
struct sharedFile * sharedList;
|
1996-02-29 11:38:33 +08:00
|
|
|
int secNum, mainNum;
|
1996-01-23 05:13:12 +08:00
|
|
|
int sharedCount;
|
|
|
|
int i, type;
|
1996-02-21 05:54:02 +08:00
|
|
|
int * intptr;
|
|
|
|
Header sech = NULL;
|
1996-01-23 05:13:12 +08:00
|
|
|
int secOffset = 0;
|
|
|
|
int secFileCount;
|
1996-02-29 11:38:33 +08:00
|
|
|
char ** secFileMd5List, ** secFileList, ** secFileLinksList;
|
1996-01-23 05:13:12 +08:00
|
|
|
char * secFileStatesList;
|
1996-02-29 11:38:33 +08:00
|
|
|
int_16 * secFileModesList;
|
1996-01-30 03:37:59 +08:00
|
|
|
uint_32 * secFileFlagsList;
|
1996-01-23 05:13:12 +08:00
|
|
|
char * name, * version, * release;
|
|
|
|
int rc = 0;
|
1996-02-16 05:08:48 +08:00
|
|
|
struct replacedFile * replacedList;
|
|
|
|
int numReplacedFiles, numReplacedAlloced;
|
1996-10-21 10:17:39 +08:00
|
|
|
char state;
|
1996-01-23 05:13:12 +08:00
|
|
|
|
|
|
|
if (findSharedFiles(db, 0, fileList, fileCount, &sharedList,
|
|
|
|
&sharedCount)) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1996-02-16 05:08:48 +08:00
|
|
|
numReplacedAlloced = 10;
|
|
|
|
numReplacedFiles = 0;
|
|
|
|
replacedList = malloc(sizeof(*replacedList) * numReplacedAlloced);
|
|
|
|
|
1996-01-23 05:13:12 +08:00
|
|
|
for (i = 0; i < sharedCount; i++) {
|
1996-02-16 05:08:48 +08:00
|
|
|
if (sharedList[i].secRecOffset == ignoreOffset) continue;
|
1996-01-23 05:13:12 +08:00
|
|
|
|
|
|
|
if (secOffset != sharedList[i].secRecOffset) {
|
|
|
|
if (secOffset) {
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(sech);
|
1996-01-23 05:13:12 +08:00
|
|
|
free(secFileMd5List);
|
1996-02-29 11:38:33 +08:00
|
|
|
free(secFileLinksList);
|
1996-01-23 05:13:12 +08:00
|
|
|
free(secFileList);
|
|
|
|
}
|
|
|
|
|
|
|
|
secOffset = sharedList[i].secRecOffset;
|
|
|
|
sech = rpmdbGetRecord(db, secOffset);
|
|
|
|
if (!sech) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_DBCORRUPT, "cannot read header at %d for "
|
1996-01-23 05:13:12 +08:00
|
|
|
"uninstall", secOffset);
|
|
|
|
rc = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(sech, RPMTAG_NAME, &type, (void **) &name,
|
1996-01-23 05:13:12 +08:00
|
|
|
&secFileCount);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(sech, RPMTAG_VERSION, &type, (void **) &version,
|
1996-01-23 05:13:12 +08:00
|
|
|
&secFileCount);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(sech, RPMTAG_RELEASE, &type, (void **) &release,
|
1996-01-23 05:13:12 +08:00
|
|
|
&secFileCount);
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "package %s-%s-%s contain shared files\n",
|
1996-01-23 05:13:12 +08:00
|
|
|
name, version, release);
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
if (!headerGetEntry(sech, RPMTAG_FILENAMES, &type,
|
1996-01-23 05:13:12 +08:00
|
|
|
(void **) &secFileList, &secFileCount)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_DBCORRUPT, "package %s contains no files",
|
1996-01-23 05:13:12 +08:00
|
|
|
name);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(sech);
|
1996-01-23 05:13:12 +08:00
|
|
|
rc = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(sech, RPMTAG_FILESTATES, &type,
|
1996-01-23 05:13:12 +08:00
|
|
|
(void **) &secFileStatesList, &secFileCount);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(sech, RPMTAG_FILEMD5S, &type,
|
1996-01-23 05:13:12 +08:00
|
|
|
(void **) &secFileMd5List, &secFileCount);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(sech, RPMTAG_FILEFLAGS, &type,
|
1996-01-30 03:37:59 +08:00
|
|
|
(void **) &secFileFlagsList, &secFileCount);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(sech, RPMTAG_FILELINKTOS, &type,
|
1996-02-29 11:38:33 +08:00
|
|
|
(void **) &secFileLinksList, &secFileCount);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(sech, RPMTAG_FILEMODES, &type,
|
1996-02-29 11:38:33 +08:00
|
|
|
(void **) &secFileModesList, &secFileCount);
|
1996-01-23 05:13:12 +08:00
|
|
|
}
|
|
|
|
|
1996-02-29 11:38:33 +08:00
|
|
|
secNum = sharedList[i].secFileNumber;
|
|
|
|
mainNum = sharedList[i].mainFileNumber;
|
1996-01-30 03:37:59 +08:00
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "file %s is shared\n", secFileList[secNum]);
|
1996-02-24 00:21:06 +08:00
|
|
|
|
1996-02-21 05:54:02 +08:00
|
|
|
intptr = notErrors;
|
|
|
|
while (*intptr) {
|
|
|
|
if (*intptr == sharedList[i].secRecOffset) break;
|
|
|
|
intptr++;
|
|
|
|
}
|
|
|
|
|
1996-01-30 03:37:59 +08:00
|
|
|
/* if this instance of the shared file is already recorded as
|
|
|
|
replaced, just forget about it */
|
1996-10-21 10:17:39 +08:00
|
|
|
state = secFileStatesList[sharedList[i].secFileNumber];
|
|
|
|
if (state == RPMFILE_STATE_REPLACED) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, " old version already replaced\n");
|
1996-01-30 03:37:59 +08:00
|
|
|
continue;
|
1996-10-21 10:17:39 +08:00
|
|
|
} else if (state == RPMFILE_STATE_NOTINSTALLED) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, " other version never installed\n");
|
1996-03-30 04:52:03 +08:00
|
|
|
continue;
|
1996-01-30 03:37:59 +08:00
|
|
|
}
|
|
|
|
|
1996-02-29 11:38:33 +08:00
|
|
|
if (filecmp(fileModesList[mainNum], fileMd5List[mainNum],
|
|
|
|
fileLinkList[mainNum], secFileModesList[secNum],
|
|
|
|
secFileMd5List[secNum], secFileLinksList[secNum])) {
|
1996-11-19 02:02:36 +08:00
|
|
|
if (!(flags & RPMINSTALL_REPLACEFILES) && !(*intptr)) {
|
|
|
|
rpmError(RPMERR_PKGINSTALLED, "%s conflicts with file from "
|
1996-02-29 11:38:33 +08:00
|
|
|
"%s-%s-%s", fileList[sharedList[i].mainFileNumber],
|
|
|
|
name, version, release);
|
|
|
|
rc = 1;
|
1996-01-30 03:37:59 +08:00
|
|
|
} else {
|
1996-02-29 11:38:33 +08:00
|
|
|
if (numReplacedFiles == numReplacedAlloced) {
|
|
|
|
numReplacedAlloced += 10;
|
|
|
|
replacedList = realloc(replacedList,
|
|
|
|
sizeof(*replacedList) *
|
|
|
|
numReplacedAlloced);
|
1996-01-30 03:37:59 +08:00
|
|
|
}
|
1996-02-29 11:38:33 +08:00
|
|
|
|
|
|
|
replacedList[numReplacedFiles].recOffset =
|
|
|
|
sharedList[i].secRecOffset;
|
|
|
|
replacedList[numReplacedFiles].fileNumber =
|
|
|
|
sharedList[i].secFileNumber;
|
|
|
|
numReplacedFiles++;
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "%s from %s-%s-%s will be replaced\n",
|
1996-02-29 11:38:33 +08:00
|
|
|
fileList[sharedList[i].mainFileNumber],
|
|
|
|
name, version, release);
|
1996-01-30 03:37:59 +08:00
|
|
|
}
|
|
|
|
}
|
1996-02-29 11:38:33 +08:00
|
|
|
|
|
|
|
/* if this is a config file, we need to be carefull here */
|
1996-07-28 07:35:07 +08:00
|
|
|
if (fileFlagsList[sharedList[i].mainFileNumber] & RPMFILE_CONFIG ||
|
|
|
|
secFileFlagsList[sharedList[i].secFileNumber] & RPMFILE_CONFIG) {
|
1996-02-29 11:38:33 +08:00
|
|
|
instActions[sharedList[i].mainFileNumber] =
|
1996-08-01 02:45:22 +08:00
|
|
|
decideFileFate(prefixedFileList[mainNum],
|
|
|
|
secFileModesList[secNum],
|
1996-02-29 11:38:33 +08:00
|
|
|
secFileMd5List[secNum], secFileLinksList[secNum],
|
|
|
|
fileModesList[mainNum], fileMd5List[mainNum],
|
1996-09-01 02:35:40 +08:00
|
|
|
fileLinkList[mainNum],
|
1996-11-19 02:02:36 +08:00
|
|
|
!headerIsEntry(sech, RPMTAG_RPMVERSION));
|
1996-02-29 11:38:33 +08:00
|
|
|
}
|
1996-01-23 05:13:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (secOffset) {
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(sech);
|
1996-01-23 05:13:12 +08:00
|
|
|
free(secFileMd5List);
|
1996-02-29 11:38:33 +08:00
|
|
|
free(secFileLinksList);
|
1996-01-23 05:13:12 +08:00
|
|
|
free(secFileList);
|
|
|
|
}
|
|
|
|
|
1996-10-21 10:17:39 +08:00
|
|
|
if (sharedList) free(sharedList);
|
1996-02-16 05:08:48 +08:00
|
|
|
|
|
|
|
if (!numReplacedFiles)
|
|
|
|
free(replacedList);
|
|
|
|
else {
|
|
|
|
replacedList[numReplacedFiles].recOffset = 0; /* mark the end */
|
|
|
|
*repListPtr = replacedList;
|
|
|
|
}
|
1996-01-23 05:13:12 +08:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int fileCompare(const void * one, const void * two) {
|
|
|
|
return strcmp(((struct fileToInstall *) one)->fileName,
|
|
|
|
((struct fileToInstall *) two)->fileName);
|
|
|
|
}
|
1996-02-15 01:54:37 +08:00
|
|
|
|
1996-11-01 05:06:55 +08:00
|
|
|
/* 0 success */
|
|
|
|
/* 1 bad magic */
|
|
|
|
/* 2 error */
|
1996-08-29 12:16:07 +08:00
|
|
|
static int installSources(Header h, char * rootdir, int fd,
|
1996-11-19 02:02:36 +08:00
|
|
|
char ** specFilePtr, rpmNotifyFunction notify,
|
1996-08-29 12:16:07 +08:00
|
|
|
char * labelFormat) {
|
1996-02-15 01:54:37 +08:00
|
|
|
char * specFile;
|
|
|
|
char * sourceDir, * specDir;
|
|
|
|
char * realSourceDir, * realSpecDir;
|
|
|
|
char * instSpecFile, * correctSpecFile;
|
1996-08-29 12:16:07 +08:00
|
|
|
char * tmpPath, * name, * release, * version;
|
|
|
|
uint_32 * archiveSizePtr = NULL;
|
|
|
|
int type, count;
|
1996-02-15 01:54:37 +08:00
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "installing a source package\n");
|
1996-02-15 04:09:14 +08:00
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
sourceDir = rpmGetVar(RPMVAR_SOURCEDIR);
|
|
|
|
specDir = rpmGetVar(RPMVAR_SPECDIR);
|
1996-02-15 01:54:37 +08:00
|
|
|
|
1996-11-01 05:06:55 +08:00
|
|
|
if (access(sourceDir, W_OK)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_CREATE, "cannot write to %s", sourceDir);
|
1996-11-01 05:06:55 +08:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (access(specDir, W_OK)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_CREATE, "cannot write to %s", sourceDir);
|
1996-11-01 05:06:55 +08:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
1996-07-10 10:33:38 +08:00
|
|
|
realSourceDir = alloca(strlen(rootdir) + strlen(sourceDir) + 2);
|
|
|
|
strcpy(realSourceDir, rootdir);
|
1996-02-15 01:54:37 +08:00
|
|
|
strcat(realSourceDir, "/");
|
|
|
|
strcat(realSourceDir, sourceDir);
|
|
|
|
|
1996-07-10 10:33:38 +08:00
|
|
|
realSpecDir = alloca(strlen(rootdir) + strlen(specDir) + 2);
|
|
|
|
strcpy(realSpecDir, rootdir);
|
1996-02-15 01:54:37 +08:00
|
|
|
strcat(realSpecDir, "/");
|
|
|
|
strcat(realSpecDir, specDir);
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "sources in: %s\n", realSourceDir);
|
|
|
|
rpmMessage(RPMMESS_DEBUG, "spec file in: %s\n", realSpecDir);
|
1996-02-15 01:54:37 +08:00
|
|
|
|
1996-07-26 00:39:01 +08:00
|
|
|
if (rootdir) {
|
|
|
|
tmpPath = alloca(strlen(rootdir) + 15);
|
|
|
|
strcpy(tmpPath, rootdir);
|
1996-11-19 02:02:36 +08:00
|
|
|
strcat(tmpPath, rpmGetVar(RPMVAR_TMPPATH));
|
1996-07-26 00:39:01 +08:00
|
|
|
} else
|
1996-11-19 02:02:36 +08:00
|
|
|
tmpPath = rpmGetVar(RPMVAR_TMPPATH);
|
1996-07-26 00:39:01 +08:00
|
|
|
|
1996-08-29 12:16:07 +08:00
|
|
|
if (labelFormat && h) {
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_NAME, &type, (void *) &name, &count);
|
|
|
|
headerGetEntry(h, RPMTAG_VERSION, &type, (void *) &version, &count);
|
|
|
|
headerGetEntry(h, RPMTAG_RELEASE, &type, (void *) &release, &count);
|
|
|
|
if (!headerGetEntry(h, RPMTAG_ARCHIVESIZE, &type, (void *) &archiveSizePtr,
|
1996-08-29 12:16:07 +08:00
|
|
|
&count))
|
|
|
|
archiveSizePtr = NULL;
|
|
|
|
printf(labelFormat, name, version, release);
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
|
|
|
|
1996-09-06 03:58:04 +08:00
|
|
|
if (installArchive(realSourceDir, fd, NULL, -1, notify, &specFile,
|
1996-08-29 12:16:07 +08:00
|
|
|
tmpPath, archiveSizePtr ? *archiveSizePtr : 0)) {
|
1996-11-01 05:06:55 +08:00
|
|
|
return 2;
|
1996-02-15 01:54:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!specFile) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_NOSPEC, "source package contains no .spec file");
|
1996-02-15 01:54:37 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This logic doesn't work is realSpecDir and realSourceDir are on
|
|
|
|
different filesystems XXX */
|
|
|
|
instSpecFile = alloca(strlen(realSourceDir) + strlen(specFile) + 2);
|
|
|
|
strcpy(instSpecFile, realSourceDir);
|
|
|
|
strcat(instSpecFile, "/");
|
|
|
|
strcat(instSpecFile, specFile);
|
|
|
|
|
|
|
|
correctSpecFile = alloca(strlen(realSpecDir) + strlen(specFile) + 2);
|
|
|
|
strcpy(correctSpecFile, realSpecDir);
|
|
|
|
strcat(correctSpecFile, "/");
|
|
|
|
strcat(correctSpecFile, specFile);
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "renaming %s to %s\n", instSpecFile, correctSpecFile);
|
1996-02-15 01:54:37 +08:00
|
|
|
if (rename(instSpecFile, correctSpecFile)) {
|
1996-08-29 12:16:07 +08:00
|
|
|
/* try copying the file */
|
|
|
|
if (moveFile(instSpecFile, correctSpecFile))
|
1996-11-01 05:06:55 +08:00
|
|
|
return 2;
|
1996-02-15 01:54:37 +08:00
|
|
|
}
|
|
|
|
|
1996-02-15 04:09:14 +08:00
|
|
|
if (specFilePtr)
|
|
|
|
*specFilePtr = strdup(correctSpecFile);
|
|
|
|
|
1996-02-15 01:54:37 +08:00
|
|
|
return 0;
|
|
|
|
}
|
1996-02-16 05:08:48 +08:00
|
|
|
|
|
|
|
static int markReplacedFiles(rpmdb db, struct replacedFile * replList) {
|
|
|
|
struct replacedFile * fileInfo;
|
|
|
|
Header secHeader = NULL, sh;
|
|
|
|
char * secStates;
|
|
|
|
int type, count;
|
|
|
|
|
|
|
|
int secOffset = 0;
|
|
|
|
|
|
|
|
for (fileInfo = replList; fileInfo->recOffset; fileInfo++) {
|
|
|
|
if (secOffset != fileInfo->recOffset) {
|
|
|
|
if (secHeader) {
|
|
|
|
/* ignore errors here - just do the best we can */
|
|
|
|
|
|
|
|
rpmdbUpdateRecord(db, secOffset, secHeader);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(secHeader);
|
1996-02-16 05:08:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
secOffset = fileInfo->recOffset;
|
|
|
|
sh = rpmdbGetRecord(db, secOffset);
|
|
|
|
if (!sh) {
|
|
|
|
secOffset = 0;
|
|
|
|
} else {
|
1996-11-19 02:02:36 +08:00
|
|
|
secHeader = headerCopy(sh); /* so we can modify it */
|
|
|
|
headerFree(sh);
|
1996-02-16 05:08:48 +08:00
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(secHeader, RPMTAG_FILESTATES, &type, (void **) &secStates,
|
1996-02-16 05:08:48 +08:00
|
|
|
&count);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* by now, secHeader is the right header to modify, secStates is
|
|
|
|
the right states list to modify */
|
|
|
|
|
|
|
|
secStates[fileInfo->fileNumber] = RPMFILE_STATE_REPLACED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (secHeader) {
|
|
|
|
/* ignore errors here - just do the best we can */
|
|
|
|
|
|
|
|
rpmdbUpdateRecord(db, secOffset, secHeader);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(secHeader);
|
1996-02-16 05:08:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
1996-02-26 06:11:00 +08:00
|
|
|
|
1996-07-23 02:32:03 +08:00
|
|
|
int rpmEnsureOlder(rpmdb db, char * name, char * newVersion,
|
|
|
|
char * newRelease, int dbOffset) {
|
1996-02-26 06:11:00 +08:00
|
|
|
Header h;
|
|
|
|
char * oldVersion, * oldRelease;
|
|
|
|
int rc, result;
|
|
|
|
int type, count;
|
|
|
|
|
|
|
|
h = rpmdbGetRecord(db, dbOffset);
|
|
|
|
if (!h) return 1;
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &oldVersion, &count);
|
|
|
|
headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &oldRelease, &count);
|
1996-02-26 06:11:00 +08:00
|
|
|
|
|
|
|
result = vercmp(oldVersion, newVersion);
|
|
|
|
if (result < 0)
|
|
|
|
rc = 0;
|
|
|
|
else if (result > 0)
|
|
|
|
rc = 1;
|
|
|
|
else {
|
|
|
|
result = vercmp(oldRelease, newRelease);
|
|
|
|
if (result < 0)
|
|
|
|
rc = 0;
|
|
|
|
else
|
|
|
|
rc = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rc)
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_OLDPACKAGE, "package %s-%s-%s (which is newer) is already"
|
1996-02-26 06:11:00 +08:00
|
|
|
" installed", name, oldVersion, oldRelease);
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(h);
|
1996-02-26 06:11:00 +08:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
1996-02-29 11:38:33 +08:00
|
|
|
|
|
|
|
enum fileTypes whatis(short mode) {
|
|
|
|
enum fileTypes result;
|
|
|
|
|
|
|
|
if (S_ISDIR(mode))
|
1996-09-26 03:14:17 +08:00
|
|
|
result = XDIR;
|
1996-02-29 11:38:33 +08:00
|
|
|
else if (S_ISCHR(mode))
|
|
|
|
result = CDEV;
|
|
|
|
else if (S_ISBLK(mode))
|
|
|
|
result = BDEV;
|
|
|
|
else if (S_ISLNK(mode))
|
|
|
|
result = LINK;
|
|
|
|
else if (S_ISSOCK(mode))
|
|
|
|
result = SOCK;
|
|
|
|
else if (S_ISFIFO(mode))
|
|
|
|
result = PIPE;
|
|
|
|
else
|
|
|
|
result = REG;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
1996-07-10 10:33:38 +08:00
|
|
|
|
|
|
|
/* This is *much* more difficult then it should be. Rather then just
|
|
|
|
modifying an entry with a single call to modifyEntry(), we have to
|
|
|
|
clone most of the header. Once the internal data structures of
|
|
|
|
header.c get cleaned up, this will be *much* easier */
|
|
|
|
static int relocateFilelist(Header * hp, char * defaultPrefix,
|
|
|
|
char * newPrefix, int * relocationLength) {
|
|
|
|
Header newh, h = *hp;
|
|
|
|
HeaderIterator it;
|
|
|
|
char ** newFileList, ** fileList;
|
|
|
|
int type, count, tag, fileCount, i;
|
|
|
|
void * data;
|
|
|
|
int defaultPrefixLength;
|
|
|
|
int newPrefixLength;
|
|
|
|
|
|
|
|
/* a trailing '/' in the defaultPrefix or in the newPrefix would really
|
|
|
|
confuse us */
|
|
|
|
defaultPrefix = strcpy(alloca(strlen(defaultPrefix) + 1), defaultPrefix);
|
|
|
|
stripTrailingSlashes(defaultPrefix);
|
|
|
|
newPrefix = strcpy(alloca(strlen(newPrefix) + 1), newPrefix);
|
|
|
|
stripTrailingSlashes(newPrefix);
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "relocating files from %s to %s\n", defaultPrefix,
|
1996-07-10 10:33:38 +08:00
|
|
|
newPrefix);
|
|
|
|
|
1996-07-10 22:11:19 +08:00
|
|
|
if (!strcmp(newPrefix, defaultPrefix)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
headerAddEntry(h, RPMTAG_INSTALLPREFIX, RPM_STRING_TYPE, defaultPrefix, 1);
|
1996-07-10 22:11:19 +08:00
|
|
|
*relocationLength = strlen(defaultPrefix) + 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1996-07-10 10:33:38 +08:00
|
|
|
defaultPrefixLength = strlen(defaultPrefix);
|
|
|
|
newPrefixLength = strlen(newPrefix);
|
|
|
|
|
|
|
|
/* packages can have empty filelists */
|
1996-11-19 02:02:36 +08:00
|
|
|
if (!headerGetEntry(h, RPMTAG_FILENAMES, &type, (void *) &fileList, &fileCount))
|
1996-07-10 10:33:38 +08:00
|
|
|
return 0;
|
|
|
|
if (!count)
|
|
|
|
return 0;
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
newh = headerNew();
|
|
|
|
it = headerInitIterator(h);
|
|
|
|
while (headerNextIterator(it, &tag, &type, &data, &count))
|
1996-07-10 10:33:38 +08:00
|
|
|
if (tag != RPMTAG_FILENAMES)
|
1996-11-19 02:02:36 +08:00
|
|
|
headerAddEntry(newh, tag, type, data, count);
|
1996-07-10 10:33:38 +08:00
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFreeIterator(it);
|
1996-10-21 10:17:39 +08:00
|
|
|
|
1996-07-10 10:33:38 +08:00
|
|
|
newFileList = alloca(sizeof(char *) * fileCount);
|
|
|
|
for (i = 0; i < fileCount; i++) {
|
|
|
|
if (!strncmp(fileList[i], defaultPrefix, defaultPrefixLength)) {
|
|
|
|
newFileList[i] = alloca(strlen(fileList[i]) + newPrefixLength -
|
|
|
|
defaultPrefixLength + 2);
|
|
|
|
sprintf(newFileList[i], "%s/%s", newPrefix,
|
|
|
|
fileList[i] + defaultPrefixLength + 1);
|
|
|
|
} else {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "BAD - unprefixed file in relocatable package");
|
1996-07-10 10:33:38 +08:00
|
|
|
newFileList[i] = alloca(strlen(fileList[i]) -
|
|
|
|
defaultPrefixLength + 2);
|
|
|
|
sprintf(newFileList[i], "/%s", fileList[i] +
|
|
|
|
defaultPrefixLength + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerAddEntry(newh, RPMTAG_FILENAMES, RPM_STRING_ARRAY_TYPE, newFileList, fileCount);
|
|
|
|
headerAddEntry(newh, RPMTAG_INSTALLPREFIX, RPM_STRING_TYPE, newPrefix, 1);
|
1996-07-10 10:33:38 +08:00
|
|
|
|
|
|
|
*relocationLength = newPrefixLength + 1;
|
|
|
|
*hp = newh;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
1996-07-16 11:37:07 +08:00
|
|
|
|
|
|
|
static int archOkay(Header h) {
|
|
|
|
int_8 * pkgArchNum;
|
|
|
|
void * pkgArch;
|
|
|
|
int type, count;
|
|
|
|
|
|
|
|
/* make sure we're trying to install this on the proper architecture */
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_ARCH, &type, (void **) &pkgArch, &count);
|
|
|
|
if (type == RPM_INT8_TYPE) {
|
1996-07-16 11:37:07 +08:00
|
|
|
/* old arch handling */
|
|
|
|
pkgArchNum = pkgArch;
|
1996-11-19 02:02:36 +08:00
|
|
|
if (rpmGetArchNum() != *pkgArchNum) {
|
1996-07-16 11:37:07 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* new arch handling */
|
|
|
|
if (!rpmArchScore(pkgArch)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int osOkay(Header h) {
|
|
|
|
void * pkgOs;
|
|
|
|
int type, count;
|
|
|
|
|
|
|
|
/* make sure we're trying to install this on the proper os */
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_OS, &type, (void **) &pkgOs, &count);
|
|
|
|
if (type == RPM_INT8_TYPE) {
|
1996-07-19 05:42:12 +08:00
|
|
|
/* v1 packages and v2 packages both used improper OS numbers, so just
|
|
|
|
deal with it hope things work */
|
1996-07-20 06:31:37 +08:00
|
|
|
return 1;
|
1996-07-16 11:37:07 +08:00
|
|
|
} else {
|
|
|
|
/* new os handling */
|
|
|
|
if (!rpmOsScore(pkgOs)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
1996-08-29 12:16:07 +08:00
|
|
|
|
|
|
|
static int moveFile(char * sourceName, char * destName) {
|
|
|
|
if (copyFile(sourceName, destName)) return 1;
|
|
|
|
|
|
|
|
unlink(sourceName);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int copyFile(char * sourceName, char * destName) {
|
|
|
|
int source, dest, i;
|
|
|
|
char buf[16384];
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "coping %s to %s\n", sourceName, destName);
|
1996-09-06 03:58:04 +08:00
|
|
|
|
1996-08-29 12:16:07 +08:00
|
|
|
source = open(sourceName, O_RDONLY);
|
|
|
|
if (source < 0) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_INTERNAL, "file %s missing from source directory",
|
1996-08-29 12:16:07 +08:00
|
|
|
sourceName);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
dest = creat(destName, 0644);
|
|
|
|
if (dest < 0) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_CREATE, "failed to create file %s", destName);
|
1996-08-29 12:16:07 +08:00
|
|
|
close(source);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((i = read(source, buf, sizeof(buf))) > 0) {
|
1996-09-06 03:58:04 +08:00
|
|
|
if (write(dest, buf, i) != i) {
|
1996-08-29 12:16:07 +08:00
|
|
|
if (errno == ENOSPC) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_NOSPACE, "out of disk space writing file %s",
|
1996-08-29 12:16:07 +08:00
|
|
|
destName);
|
|
|
|
} else {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_CREATE, "error writing to file %s: %s",
|
1996-08-29 12:16:07 +08:00
|
|
|
destName, strerror(errno));
|
|
|
|
}
|
|
|
|
close(source);
|
|
|
|
close(dest);
|
|
|
|
unlink(destName);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i < 0) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_CREATE, "error reading from file %s: %s",
|
1996-08-29 12:16:07 +08:00
|
|
|
sourceName, strerror(errno));
|
|
|
|
}
|
|
|
|
|
|
|
|
close(source);
|
|
|
|
close(dest);
|
|
|
|
|
|
|
|
if (i < 0)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
1996-10-21 10:17:39 +08:00
|
|
|
|
|
|
|
static void unglobFilename(char * dptr, char * sptr) {
|
|
|
|
while (*sptr) {
|
|
|
|
switch (*sptr) {
|
|
|
|
case '*': case '[': case ']': case '?': case '\\':
|
|
|
|
*dptr++ = '\\';
|
|
|
|
/*fallthrough*/
|
|
|
|
default:
|
|
|
|
*dptr++ = *sptr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*dptr++ = *sptr;
|
|
|
|
}
|