<commit_before>#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#endif

#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/signal.h>
#include <sys/stat.h>		/* needed for mkdir(2) prototype! */
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <zlib.h>

#include "header.h"
#include "install.h"
#include "md5.h"
#include "misc.h"
#include "rpmdb.h"
#include "rpmlib.h"
#include "messages.h"

enum instActions { CREATE, BACKUP, KEEP, SAVE, SKIP };
enum fileTypes { XDIR, BDEV, CDEV, SOCK, PIPE, REG, LINK } ;

struct fileToInstall {
    char * fileName;
    int size;
} ;

struct replacedFile {
    int recOffset, fileNumber;
} ;

enum fileTypes whatis(short mode);
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);
static int installArchive(char * prefix, int fd, struct fileToInstall * files,
			  int fileCount, rpmNotifyFunction notify,
			  char ** installArchive, char * tmpPath,
			  int archiveSize);
static int packageAlreadyInstalled(rpmdb db, char * name, char * version, 
				   char * release, int * recOffset, int flags);
static int setFileOwnerships(char * rootdir, char ** fileList, 
			     char ** fileOwners, char ** fileGroups, 
			     int_16 * fileModes, 
			     enum instActions * instActions, int fileCount);
static int setFileOwner(char * file, char * owner, char * group, int_16 mode);
static int createDirectories(char ** fileList, uint_32 * modesList, 
			     int fileCount);
static int mkdirIfNone(char * directory, mode_t perms);
static int instHandleSharedFiles(rpmdb db, int ignoreOffset, char ** fileList, 
			         char ** fileMd5List, int_16 * fileModeList,
				 char ** fileLinkList, uint_32 * fileFlagsList,
				 int fileCount, enum instActions * instActions, 
			 	 char ** prootdirootdir, int * notErrors,
				 struct replacedFile ** repListPtr, int flags);
static int fileCompare(const void * one, const void * two);
static int installSources(Header h, char * rootdir, int fd, 
			  char ** specFilePtr, rpmNotifyFunction notify,
			  char * labelFormat);
static int markReplacedFiles(rpmdb db, struct replacedFile * replList);
static int relocateFilelist(Header * hp, char * defaultPrefix, 
			char * newPrefix, int * relocationSize);
static int archOkay(Header h);
static int osOkay(Header h);
static int moveFile(char * sourceName, char * destName);
static int copyFile(char * sourceName, char * destName);
static void unglobFilename(char * dptr, char * sptr);

/* 0 success */
/* 1 bad magic */
/* 2 error */
int rpmInstallSourcePackage(char * rootdir, int fd, char ** specFile,
			    rpmNotifyFunction notify, char * labelFormat) {
    int rc, isSource;
    Header h;
    int major, minor;

    rc = rpmReadPackageHeader(fd, &h, &isSource, &major, &minor);
    if (rc) return rc;

    if (!isSource) {
	rpmError(RPMERR_NOTSRPM, "source package expected, binary found");
	return 2;
    }

    if (major == 1) {
	notify = NULL;
	labelFormat = NULL;
	h = NULL;
    }

    rc = installSources(h, rootdir, fd, specFile, notify, labelFormat);
    if (h) headerFree(h);
 
    return rc;
}

/* 0 success */
/* 1 bad magic */
/* 2 error */
int rpmInstallPackage(char * rootdir, rpmdb db, int fd, char * location, 
		      int flags, rpmNotifyFunction notify, char * labelFormat,
		      char * netsharedPath) {
    int rc, isSource, major, minor;
    char * name, * version, * release;
    Header h;
    int fileCount, type, count;
    char ** fileList;
    char ** fileOwners, ** fileGroups, ** fileMd5s, ** fileLinkList;
    uint_32 * fileFlagsList;
    uint_32 * fileSizesList;
    int_16 * fileModesList;
    int_32 installTime;
    char * fileStatesList = NULL;
    struct fileToInstall * files;
    enum instActions * instActions = NULL;
    int i;
    int archiveFileCount = 0;
    int installFile = 0;
    int otherOffset = 0;
    char * ext = NULL, * newpath;
    int rootLength = strlen(rootdir);
    char ** rootedFileList = NULL;
    char ** finalFileList = NULL;
    char ** mkdirFileList = NULL;
    int mkdirFileCount = 0;
    uint_32 * mkdirModesList;
    struct replacedFile * replacedList = NULL;
    char * defaultPrefix;
    dbiIndexSet matches;
    int * oldVersions;
    int * intptr;
    char * archivePrefix, * tmpPath;
    int scriptArg;
    int relocationSize = 1;		/* strip at least first / for cpio */
    uint_32 * archiveSizePtr;

    oldVersions = alloca(sizeof(int));
    *oldVersions = 0;

    rc = rpmReadPackageHeader(fd, &h, &isSource, &major, &minor);
    if (rc) return rc;

    if (isSource) {
	if (flags & RPMINSTALL_TEST) {
	    rpmMessage(RPMMESS_DEBUG, "stopping install as we're running --test\n");
	    return 0;
	}

	if (major == 1) {
	    notify = NULL;
	    labelFormat = NULL;
	    h = NULL;
	}

	rc = installSources(h, rootdir, fd, NULL, notify, labelFormat);
	if (h) headerFree(h);

	return rc;
    }

    /* Do this now so we can give error messages, even though we'll just
       do it again after relocating everything */
    headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &fileCount);
    headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &fileCount);
    headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &fileCount);

    if (!headerGetEntry(h, RPMTAG_DEFAULTPREFIX, &type, (void *)
			      &defaultPrefix, &fileCount)) {
	defaultPrefix = NULL;
    }

    if (location && !defaultPrefix) {
	rpmError(RPMERR_NORELOCATE, "package %s-%s-%s is not relocatable",
		      name, version, release);
	headerFree(h);
	return 2;
    } else if (!location && defaultPrefix)
	location = defaultPrefix;
    
    if (location) {
	relocateFilelist(&h, defaultPrefix, location, &relocationSize);
        headerGetEntry(h, RPMTAG_DEFAULTPREFIX, &type, (void *) &defaultPrefix, 
		&fileCount);
	archivePrefix = alloca(strlen(rootdir) + strlen(location) + 2);
	sprintf(archivePrefix, "%s/%s", rootdir, location);
    } else {
	archivePrefix = rootdir;
	relocationSize = 1;
    }

    /* You're probably upset because name already points to the name of
       this package, right? Almost... it points to the name in the original
       header, which could have been trashed by relocateFileList() */
    headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &fileCount);
    headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &fileCount);
    headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &fileCount);

    if (!(flags & RPMINSTALL_NOARCH) && !archOkay(h)) {
	rpmError(RPMERR_BADARCH, "package %s-%s-%s is for a different "
	      "architecture", name, version, release);
	headerFree(h);
	return 2;
    }

    if (!(flags & RPMINSTALL_NOOS) && !osOkay(h)) {
	rpmError(RPMERR_BADOS, "package %s-%s-%s is for a different "
	      "operating system", name, version, release);
	headerFree(h);
	return 2;
    }

    if (packageAlreadyInstalled(db, name, version, release, &otherOffset, 
				flags)) {
	headerFree(h);
	return 2;
    }

    if (labelFormat) {
	printf(labelFormat, name, version, release);
	fflush(stdout);
    }

    rpmMessage(RPMMESS_DEBUG, "package: %s-%s-%s files test = %d\n", 
		name, version, release, flags & RPMINSTALL_TEST);

    rc = rpmdbFindPackage(db, name, &matches);
    if (rc == -1) return 2;
    if (rc)
 	scriptArg = 1;
    else
	scriptArg = matches.count + 1;

    /* This canonicalizes the root */
    if (rootdir && rootdir[rootLength] == '/') {
	char * newRootdir;

	newRootdir = alloca(rootLength + 2);
	strcpy(newRootdir, rootdir);
	newRootdir[rootLength++] = '/';
	newRootdir[rootLength] = '\0';
	rootdir = newRootdir;
    }

    if (flags & RPMINSTALL_UPGRADE) {
	/* 
	   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++) {
		if (matches.recs[i].recOffset != otherOffset) {
		    if (!(flags & RPMINSTALL_UPGRADETOOLD)) 
			if (rpmEnsureOlder(db, name, version, release, 
					matches.recs[i].recOffset)) {
			    headerFree(h);
			    dbiFreeIndexRecord(matches);
			    return 2;
			}
		    *intptr++ = matches.recs[i].recOffset;
		}
	    }
	    *intptr++ = 0;
	}

	dbiFreeIndexRecord(matches);
    }

    fileList = NULL;
    if (headerGetEntry(h, RPMTAG_FILENAMES, &type, (void **) &fileList, 
		 &fileCount)) {
	char ** netsharedPaths;
	char ** nsp;<commit_msg>fixed the fix from memory leak plugging <sigh><commit_after>#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#endif

#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/signal.h>
#include <sys/stat.h>		/* needed for mkdir(2) prototype! */
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <zlib.h>

#include "header.h"
#include "install.h"
#include "md5.h"
#include "misc.h"
#include "rpmdb.h"
#include "rpmlib.h"
#include "messages.h"

enum instActions { CREATE, BACKUP, KEEP, SAVE, SKIP };
enum fileTypes { XDIR, BDEV, CDEV, SOCK, PIPE, REG, LINK } ;

struct fileToInstall {
    char * fileName;
    int size;
} ;

struct replacedFile {
    int recOffset, fileNumber;
} ;

enum fileTypes whatis(short mode);
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);
static int installArchive(char * prefix, int fd, struct fileToInstall * files,
			  int fileCount, rpmNotifyFunction notify,
			  char ** installArchive, char * tmpPath,
			  int archiveSize);
static int packageAlreadyInstalled(rpmdb db, char * name, char * version, 
				   char * release, int * recOffset, int flags);
static int setFileOwnerships(char * rootdir, char ** fileList, 
			     char ** fileOwners, char ** fileGroups, 
			     int_16 * fileModes, 
			     enum instActions * instActions, int fileCount);
static int setFileOwner(char * file, char * owner, char * group, int_16 mode);
static int createDirectories(char ** fileList, uint_32 * modesList, 
			     int fileCount);
static int mkdirIfNone(char * directory, mode_t perms);
static int instHandleSharedFiles(rpmdb db, int ignoreOffset, char ** fileList, 
			         char ** fileMd5List, int_16 * fileModeList,
				 char ** fileLinkList, uint_32 * fileFlagsList,
				 int fileCount, enum instActions * instActions, 
			 	 char ** prootdirootdir, int * notErrors,
				 struct replacedFile ** repListPtr, int flags);
static int fileCompare(const void * one, const void * two);
static int installSources(Header h, char * rootdir, int fd, 
			  char ** specFilePtr, rpmNotifyFunction notify,
			  char * labelFormat);
static int markReplacedFiles(rpmdb db, struct replacedFile * replList);
static int relocateFilelist(Header * hp, char * defaultPrefix, 
			char * newPrefix, int * relocationSize);
static int archOkay(Header h);
static int osOkay(Header h);
static int moveFile(char * sourceName, char * destName);
static int copyFile(char * sourceName, char * destName);
static void unglobFilename(char * dptr, char * sptr);

/* 0 success */
/* 1 bad magic */
/* 2 error */
int rpmInstallSourcePackage(char * rootdir, int fd, char ** specFile,
			    rpmNotifyFunction notify, char * labelFormat) {
    int rc, isSource;
    Header h;
    int major, minor;

    rc = rpmReadPackageHeader(fd, &h, &isSource, &major, &minor);
    if (rc) return rc;

    if (!isSource) {
	rpmError(RPMERR_NOTSRPM, "source package expected, binary found");
	return 2;
    }

    if (major == 1) {
	notify = NULL;
	labelFormat = NULL;
	h = NULL;
    }

    rc = installSources(h, rootdir, fd, specFile, notify, labelFormat);
    if (h) headerFree(h);
 
    return rc;
}

/* 0 success */
/* 1 bad magic */
/* 2 error */
int rpmInstallPackage(char * rootdir, rpmdb db, int fd, char * location, 
		      int flags, rpmNotifyFunction notify, char * labelFormat,
		      char * netsharedPath) {
    int rc, isSource, major, minor;
    char * name, * version, * release;
    Header h;
    int fileCount, type, count;
    char ** fileList;
    char ** fileOwners, ** fileGroups, ** fileMd5s, ** fileLinkList;
    uint_32 * fileFlagsList;
    uint_32 * fileSizesList;
    int_16 * fileModesList;
    int_32 installTime;
    char * fileStatesList = NULL;
    struct fileToInstall * files;
    enum instActions * instActions = NULL;
    int i;
    int archiveFileCount = 0;
    int installFile = 0;
    int otherOffset = 0;
    char * ext = NULL, * newpath;
    int rootLength = strlen(rootdir);
    char ** rootedFileList = NULL;
    char ** finalFileList = NULL;
    char ** mkdirFileList = NULL;
    int mkdirFileCount = 0;
    uint_32 * mkdirModesList;
    struct replacedFile * replacedList = NULL;
    char * defaultPrefix;
    dbiIndexSet matches;
    int * oldVersions;
    int * intptr;
    char * archivePrefix, * tmpPath;
    int scriptArg;
    int hasOthers = 0;
    int relocationSize = 1;		/* strip at least first / for cpio */
    uint_32 * archiveSizePtr;

    oldVersions = alloca(sizeof(int));
    *oldVersions = 0;

    rc = rpmReadPackageHeader(fd, &h, &isSource, &major, &minor);
    if (rc) return rc;

    if (isSource) {
	if (flags & RPMINSTALL_TEST) {
	    rpmMessage(RPMMESS_DEBUG, "stopping install as we're running --test\n");
	    return 0;
	}

	if (major == 1) {
	    notify = NULL;
	    labelFormat = NULL;
	    h = NULL;
	}

	rc = installSources(h, rootdir, fd, NULL, notify, labelFormat);
	if (h) headerFree(h);

	return rc;
    }

    /* Do this now so we can give error messages, even though we'll just
       do it again after relocating everything */
    headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &fileCount);
    headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &fileCount);
    headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &fileCount);

    if (!headerGetEntry(h, RPMTAG_DEFAULTPREFIX, &type, (void *)
			      &defaultPrefix, &fileCount)) {
	defaultPrefix = NULL;
    }

    if (location && !defaultPrefix) {
	rpmError(RPMERR_NORELOCATE, "package %s-%s-%s is not relocatable",
		      name, version, release);
	headerFree(h);
	return 2;
    } else if (!location && defaultPrefix)
	location = defaultPrefix;
    
    if (location) {
	relocateFilelist(&h, defaultPrefix, location, &relocationSize);
        headerGetEntry(h, RPMTAG_DEFAULTPREFIX, &type, (void *) &defaultPrefix, 
		&fileCount);
	archivePrefix = alloca(strlen(rootdir) + strlen(location) + 2);
	sprintf(archivePrefix, "%s/%s", rootdir, location);
    } else {
	archivePrefix = rootdir;
	relocationSize = 1;
    }

    /* You're probably upset because name already points to the name of
       this package, right? Almost... it points to the name in the original
       header, which could have been trashed by relocateFileList() */
    headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &fileCount);
    headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &fileCount);
    headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &fileCount);

    if (!(flags & RPMINSTALL_NOARCH) && !archOkay(h)) {
	rpmError(RPMERR_BADARCH, "package %s-%s-%s is for a different "
	      "architecture", name, version, release);
	headerFree(h);
	return 2;
    }

    if (!(flags & RPMINSTALL_NOOS) && !osOkay(h)) {
	rpmError(RPMERR_BADOS, "package %s-%s-%s is for a different "
	      "operating system", name, version, release);
	headerFree(h);
	return 2;
    }

    if (packageAlreadyInstalled(db, name, version, release, &otherOffset, 
				flags)) {
	headerFree(h);
	return 2;
    }

    if (labelFormat) {
	printf(labelFormat, name, version, release);
	fflush(stdout);
    }

    rpmMessage(RPMMESS_DEBUG, "package: %s-%s-%s files test = %d\n", 
		name, version, release, flags & RPMINSTALL_TEST);

    rc = rpmdbFindPackage(db, name, &matches);
    if (rc == -1) return 2;
    if (rc) {
 	scriptArg = 1;
	hasOthers = 1;
    } else {
	scriptArg = matches.count + 1;
    }

    /* This canonicalizes the root */
    if (rootdir && rootdir[rootLength] == '/') {
	char * newRootdir;

	newRootdir = alloca(rootLength + 2);
	strcpy(newRootdir, rootdir);
	newRootdir[rootLength++] = '/';
	newRootdir[rootLength] = '\0';
	rootdir = newRootdir;
    }

    if (flags & RPMINSTALL_UPGRADE && hasOthers) {
	/* 
	   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++) {
		if (matches.recs[i].recOffset != otherOffset) {
		    if (!(flags & RPMINSTALL_UPGRADETOOLD)) 
			if (rpmEnsureOlder(db, name, version, release, 
					matches.recs[i].recOffset)) {
			    headerFree(h);
			    dbiFreeIndexRecord(matches);
			    return 2;
			}
		    *intptr++ = matches.recs[i].recOffset;
		}
	    }
	    *intptr++ = 0;
	}
    }

    if (hasOthers) 
	dbiFreeIndexRecord(matches);

    fileList = NULL;
    if (headerGetEntry(h, RPMTAG_FILENAMES, &type, (void **) &fileList, 
		 &fileCount)) {
	char ** netsharedPaths;
	char ** nsp;
{'fraction_non_alphanumeric': 0.12368844723255426, 'fraction_numerical': 0.007994226392050186, 'mean_word_length': 3.4314883148831488, 'pattern_counts': {'":': 0, '<': 34, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1491263', 'n_tokens_mistral': 6459, 'n_tokens_neox': 5934, 'n_words': 1772}