summaryrefslogtreecommitdiff
path: root/build/files.c
diff options
context:
space:
mode:
Diffstat (limited to 'build/files.c')
-rw-r--r--build/files.c1800
1 files changed, 1036 insertions, 764 deletions
diff --git a/build/files.c b/build/files.c
index 1159ff6f6..fe2023b40 100644
--- a/build/files.c
+++ b/build/files.c
@@ -1,651 +1,703 @@
-/* RPM - Copyright (C) 1995 Red Hat Software
- *
- * prepack.c - routines for packaging
- */
-
-#include "miscfn.h"
-
-#include <stdlib.h>
-#include <unistd.h>
#include <string.h>
-#include <sys/stat.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <glob.h>
#include <time.h>
#include "spec.h"
-#include "specP.h"
-#include "stringbuf.h"
-#include "build.h"
-#include "messages.h"
-#include "md5.h"
+#include "package.h"
+#include "rpmlib.h"
+#include "misc.h"
+#include "lib/misc.h"
#include "myftw.h"
+#include "lib/cpio.h"
#include "header.h"
-#include "files.h"
+#include "md5.h"
#include "names.h"
-#include "rpmlead.h"
-#include "rpmlib.h"
-#include "misc.h"
+#include "messages.h"
#include "macro.h"
+#include "build.h"
-#define BINARY_HEADER 0
-#define SOURCE_HEADER 1
-
-struct file_entry {
- char file[1024];
- int isdoc;
- int conf;
- int isspecfile;
- int isghost;
- int verify_flags;
- char *uname; /* reference -- do not free */
- char *gname; /* reference -- do not free */
- struct stat statbuf;
- struct file_entry *next;
+#define MAXDOCDIR 1024
+
+struct FileListRec {
+ char *diskName; /* get file from here */
+ char *fileName; /* filename in cpio archive */
+ mode_t mode;
+ uid_t uid;
+ gid_t gid;
+ dev_t device;
+ ino_t inode;
+ char *uname;
+ char *gname;
+ int flags;
+ int verifyFlags;
+ int size;
+ int mtime;
+ dev_t rdev;
+ char *lang;
};
-static int add_file(struct file_entry **festack, const char *name,
- int isdoc, int isconf, int isdir, int isghost,
- int verify_flags,
- char *Pmode, char *Uname, char *Gname, char *prefix);
-static int compare_fe(const void *ap, const void *bp);
-static int add_file_aux(const char *file, struct stat *sb, int flag);
-static int glob_error(const char *foo, int bar);
-static int glob_pattern_p (char *pattern);
-static int parseForVerify(char *buf, int *verify_flags);
-static int parseForConfig(char *buf, int *conf);
-static int parseForAttr(char *origbuf, char **currPmode,
- char **currUname, char **currGname);
-
-static void resetDocdir(void);
-static void addDocdir(char *dirname);
-static int isDoc(char *filename);
+struct AttrRec {
+ char *PmodeString;
+ int Pmode;
+ char *PdirmodeString;
+ int Pdirmode;
+ char *Uname;
+ char *Gname;
+};
-static int processFileListFailed;
+struct FileList {
+ char *buildRoot;
+ char *prefix;
-static void parseForDocFiles(struct PackageRec *package, char *line)
-{
- if (! (line = strstr(line, "%doc"))) {
- return;
- }
+ int fileCount;
+ int totalFileSize;
+ int processingFailed;
- line += 4;
- if ((*line != ' ') && (*line != '\t')) {
- return;
- }
- line += strspn(line, " \t\n");
- if ((! *line) || (*line == '/')) {
- return;
- }
+ int passedSpecialDoc;
+ int isSpecialDoc;
- appendLineStringBuf(package->doc, "mkdir -p $DOCDIR");
- appendStringBuf(package->doc, "cp -pr ");
- appendStringBuf(package->doc, line);
- appendLineStringBuf(package->doc, " $DOCDIR");
-}
+ int isDir;
+ int inFtw;
+ int currentFlags;
+ int currentVerifyFlags;
+ struct AttrRec current;
+ struct AttrRec def;
+ int defVerifyFlags;
+ char *currentLang;
+
+ /* Hard coded limit of MAXDOCDIR docdirs. */
+ /* If you break it you are doing something wrong. */
+ char *docDirs[MAXDOCDIR];
+ int docDirCount;
+
+ struct FileListRec *fileList;
+ int fileListRecsAlloced;
+ int fileListRecsUsed;
+};
+
+static int processPackageFiles(Spec spec, Package pkg, int installSpecialDoc);
+static void freeFileList(struct FileListRec *fileList, int count);
+static int compareFileListRecs(const void *ap, const void *bp);
+static int isDoc(struct FileList *fl, char *fileName);
+static int processBinaryFile(Package pkg, struct FileList *fl, char *fileName);
+static int addFile(struct FileList *fl, char *name, struct stat *statp);
+static int parseForSimple(Spec spec, Package pkg, char *buf,
+ struct FileList *fl, char **fileName);
+static int parseForVerify(char *buf, struct FileList *fl);
+static int parseForLang(char *buf, struct FileList *fl);
+static int parseForAttr(char *buf, struct FileList *fl);
+static int parseForConfig(char *buf, struct FileList *fl);
+static int myGlobPatternP(char *pattern);
+static int glob_error(const char *foo, int bar);
+static void timeCheck(int tc, Header h);
+static void genCpioListAndHeader(struct FileList *fl,
+ struct cpioFileMapping **cpioList,
+ int *cpioCount, Header h, int isSrc);
-int finish_filelists(Spec spec)
+int processSourceFiles(Spec spec)
{
- char buf[1024];
- FILE *file;
- struct PackageRec *pr = spec->packages;
- char *s, **files, **line;
- char *version, *release, *packageVersion, *docs, *name;
-
- headerGetEntry(spec->packages->header, RPMTAG_VERSION, NULL,
- (void *) &version, NULL);
- headerGetEntry(spec->packages->header, RPMTAG_RELEASE, NULL,
- (void *) &release, NULL);
-
- while (pr) {
- if (pr->fileFile) {
- sprintf(buf, "%s/%s/%s", rpmGetVar(RPMVAR_BUILDDIR),
- build_subdir, pr->fileFile);
- rpmMessage(RPMMESS_DEBUG, "Reading file names from: %s\n", buf);
- if ((file = fopen(buf, "r")) == NULL) {
- rpmError(RPMERR_BADSPEC, "unable to open filelist: %s\n", buf);
- return(RPMERR_BADSPEC);
+ struct Source *srcPtr;
+ char buf[BUFSIZ];
+ StringBuf sourceFiles;
+ int x, isSpec = 1;
+ struct FileList fl;
+ char *s, **files, **fp, *fn;
+ struct stat sb;
+ HeaderIterator hi;
+ int tag, type, count;
+ void * ptr;
+
+ sourceFiles = newStringBuf();
+ spec->sourceHeader = headerNew();
+
+ /* Only specific tags are added to the source package header */
+ hi = headerInitIterator(spec->packages->header);
+ while (headerNextIterator(hi, &tag, &type, &ptr, &count)) {
+ switch (tag) {
+ case RPMTAG_NAME:
+ case RPMTAG_VERSION:
+ case RPMTAG_RELEASE:
+ case RPMTAG_SERIAL:
+ case RPMTAG_SUMMARY:
+ case RPMTAG_DESCRIPTION:
+ case RPMTAG_PACKAGER:
+ case RPMTAG_DISTRIBUTION:
+ case RPMTAG_VENDOR:
+ case RPMTAG_COPYRIGHT:
+ case RPMTAG_GROUP:
+ case RPMTAG_OS:
+ case RPMTAG_ARCH:
+ case RPMTAG_CHANGELOGTIME:
+ case RPMTAG_CHANGELOGNAME:
+ case RPMTAG_CHANGELOGTEXT:
+ case RPMTAG_URL:
+ headerAddEntry(spec->sourceHeader, tag, type, ptr, count);
+ break;
+ default:
+ /* do not copy */
+ break;
+ }
+ if (type == RPM_STRING_ARRAY_TYPE) {
+ FREE(ptr);
+ }
+ }
+ headerFreeIterator(hi);
+
+ /* Construct the file list and source entries */
+ appendLineStringBuf(sourceFiles, spec->specFile);
+ srcPtr = spec->sources;
+ while (srcPtr) {
+ if (srcPtr->flags & RPMBUILD_ISSOURCE) {
+ headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_SOURCE,
+ RPM_STRING_ARRAY_TYPE, &srcPtr->source, 1);
+ if (srcPtr->flags & RPMBUILD_ISNO) {
+ headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_NOSOURCE,
+ RPM_INT32_TYPE, &srcPtr->num, 1);
}
- while (fgets(buf, sizeof(buf), file)) {
- expandMacros(buf);
- appendStringBuf(pr->filelist, buf);
+ }
+ if (srcPtr->flags & RPMBUILD_ISPATCH) {
+ headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_PATCH,
+ RPM_STRING_ARRAY_TYPE, &srcPtr->source, 1);
+ if (srcPtr->flags & RPMBUILD_ISNO) {
+ headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_NOPATCH,
+ RPM_INT32_TYPE, &srcPtr->num, 1);
}
- fclose(file);
}
+ sprintf(buf, "%s%s/%s",
+ srcPtr->flags & RPMBUILD_ISNO ? "!" : "",
+ rpmGetVar(RPMVAR_SOURCEDIR), srcPtr->source);
+ appendLineStringBuf(sourceFiles, buf);
+ srcPtr = srcPtr->next;
+ }
+
+ spec->sourceCpioList = NULL;
+ spec->sourceCpioCount = 0;
- /* parse for %doc wierdness */
- s = getStringBuf(pr->filelist);
- files = splitString(s, strlen(s), '\n');
- line = files;
- while (*line) {
- parseForDocFiles(pr, *line);
- line++;
+ fl.fileList = malloc((spec->numSources + 1) * sizeof(struct FileListRec));
+ fl.processingFailed = 0;
+ fl.fileListRecsUsed = 0;
+ fl.totalFileSize = 0;
+ fl.prefix = NULL;
+
+ s = getStringBuf(sourceFiles);
+ files = splitString(s, strlen(s), '\n');
+ fp = files;
+
+ /* The first source file is the spec file */
+ x = 0;
+ while (*fp) {
+ s = *fp;
+ SKIPSPACE(s);
+ if (! *s) {
+ fp++; continue;
}
- freeSplitString(files);
- /* Handle subpackage version overrides */
- if (!headerGetEntry(pr->header, RPMTAG_VERSION, NULL,
- (void *) &packageVersion, NULL)) {
- packageVersion = version;
+ fl.fileList[x].flags = isSpec ? RPMFILE_SPECFILE : 0;
+ /* files with leading ! are no source files */
+ if (*s == '!') {
+ fl.fileList[x].flags |= RPMFILE_GHOST;
+ s++;
+ }
+ fl.fileList[x].diskName = strdup(s);
+ fn = strrchr(s, '/');
+ if (fn) {
+ fn++;
+ } else {
+ fn = s;
}
+ fl.fileList[x].fileName = strdup(fn);
+ fl.fileList[x].verifyFlags = RPMVERIFY_ALL;
+ lstat(s, &sb);
+ fl.fileList[x].mode = sb.st_mode;
+ fl.fileList[x].uid = sb.st_uid;
+ fl.fileList[x].gid = sb.st_gid;
+ fl.fileList[x].uname = getUname(sb.st_uid);
+ fl.fileList[x].gname = getGname(sb.st_gid);
+ fl.fileList[x].size = sb.st_size;
+ fl.fileList[x].mtime = sb.st_mtime;
+ fl.fileList[x].rdev = sb.st_rdev;
+ fl.fileList[x].device = sb.st_dev;
+ fl.fileList[x].inode = sb.st_ino;
+ fl.fileList[x].lang = strdup("");
+
+ fl.totalFileSize += sb.st_size;
+
+ if (! (fl.fileList[x].uname && fl.fileList[x].gname)) {
+ rpmError(RPMERR_BADSPEC, "Bad owner/group: %s", s);
+ fl.processingFailed = 1;
+ }
+
+ isSpec = 0;
+ fp++;
+ x++;
+ }
+ fl.fileListRecsUsed = x;
+ FREE(files);
- /* Generate the doc script */
- appendStringBuf(spec->doc, "DOCDIR=$RPM_ROOT_DIR/$RPM_DOC_DIR/");
- headerGetEntry(pr->header, RPMTAG_NAME, NULL, (void *) &name, NULL);
- sprintf(buf, "%s-%s", name, packageVersion);
- appendLineStringBuf(spec->doc, buf);
- docs = getStringBuf(pr->doc);
- if (*docs) {
- appendLineStringBuf(spec->doc, "rm -rf $DOCDIR");
- appendLineStringBuf(spec->doc, docs);
+ if (! fl.processingFailed) {
+ genCpioListAndHeader(&fl, &(spec->sourceCpioList),
+ &(spec->sourceCpioCount), spec->sourceHeader, 1);
+ }
+
+ freeStringBuf(sourceFiles);
+ freeFileList(fl.fileList, fl.fileListRecsUsed);
+ return fl.processingFailed;
+}
+
+int processBinaryFiles(Spec spec, int installSpecialDoc)
+{
+ Package pkg;
+ int rc;
+
+ pkg = spec->packages;
+ while (pkg) {
+ if (!pkg->fileList) {
+ pkg = pkg->next;
+ continue;
+ }
+
+ if ((rc = processPackageFiles(spec, pkg, installSpecialDoc))) {
+ return rc;
}
- pr = pr->next;
+ pkg = pkg->next;
}
return 0;
}
-int process_filelist(Header header, struct PackageRec *pr,
- StringBuf sb, int *size, char *name,
- char *version, char *release, int type,
- char *prefix, char *specFile)
+static int processPackageFiles(Spec spec, Package pkg, int installSpecialDoc)
{
- char buf[1024];
- char **files, **fp;
- struct file_entry *fes, *fest;
- struct file_entry **file_entry_array;
- int isdoc, conf, isdir, verify_flags, isghost;
- char *currPmode=NULL; /* hold info from %attr() */
- char *currUname=NULL; /* hold info from %attr() */
- char *currGname=NULL; /* hold info from %attr() */
- char *filename, *s;
- char *str;
- int count = 0;
- int c, x;
- glob_t glob_result;
- int special_doc;
- int passed_special_doc = 0;
- int tc;
- char *tcs;
- int currentTime;
+ struct FileList fl;
+ char *s, **files, **fp, *fileName;
+ char buf[BUFSIZ];
+ FILE *f;
- processFileListFailed = 0;
- fes = NULL;
- *size = 0;
+ struct AttrRec specialDocAttrRec;
+ char *specialDoc = NULL;
+
+ pkg->cpioList = NULL;
+ pkg->cpioCount = 0;
+
+ if (pkg->fileFile) {
+ sprintf(buf, "%s/%s/%s", rpmGetVar(RPMVAR_BUILDDIR),
+ spec->buildSubdir, pkg->fileFile);
+ if ((f = fopen(buf, "r")) == NULL) {
+ rpmError(RPMERR_BADFILENAME,
+ "Could not open %%files file: %s", pkg->fileFile);
+ return RPMERR_BADFILENAME;
+ }
+ while (fgets(buf, sizeof(buf), f)) {
+ expandMacros(&spec->macros, buf);
+ appendStringBuf(pkg->fileList, buf);
+ }
+ fclose(f);
+ }
+
+ /* Init the file list structure */
+
+ fl.buildRoot = spec->buildRoot ? spec->buildRoot : "";
+ if (headerGetEntry(pkg->header, RPMTAG_DEFAULTPREFIX,
+ NULL, (void *)&fl.prefix, NULL)) {
+ fl.prefix = strdup(fl.prefix);
+ } else {
+ fl.prefix = NULL;
+ }
- resetDocdir();
+ fl.fileCount = 0;
+ fl.totalFileSize = 0;
+ fl.processingFailed = 0;
- str = getStringBuf(sb);
- files = splitString(str, strlen(str), '\n');
+ fl.passedSpecialDoc = 0;
+
+ fl.current.PmodeString = NULL;
+ fl.current.PdirmodeString = NULL;
+ fl.current.Uname = NULL;
+ fl.current.Gname = NULL;
+ fl.def.PmodeString = NULL;
+ fl.def.PdirmodeString = NULL;
+ fl.def.Uname = NULL;
+ fl.def.Gname = NULL;
+ fl.currentLang = NULL;
+
+ fl.defVerifyFlags = RPMVERIFY_ALL;
+
+ fl.docDirCount = 0;
+ fl.docDirs[fl.docDirCount++] = strdup("/usr/doc");
+ fl.docDirs[fl.docDirCount++] = strdup("/usr/man");
+ fl.docDirs[fl.docDirCount++] = strdup("/usr/info");
+ fl.docDirs[fl.docDirCount++] = strdup("/usr/X11R6/man");
+ fl.docDirs[fl.docDirCount++] = strdup(spec->docDir);
+
+ fl.fileList = NULL;
+ fl.fileListRecsAlloced = 0;
+ fl.fileListRecsUsed = 0;
+
+ s = getStringBuf(pkg->fileList);
+ files = splitString(s, strlen(s), '\n');
fp = files;
while (*fp) {
- strcpy(buf, *fp); /* temp copy */
- isdoc = 0;
- special_doc = 0;
- conf = 0;
- isdir = 0;
- isghost = 0;
- if (currPmode) {
- free (currPmode);
- currPmode = NULL;
- }
- if (currUname) {
- free (currUname);
- currUname = NULL;
- }
- if (currGname) {
- free (currGname);
- currGname = NULL;
- }
- verify_flags = RPMVERIFY_ALL;
- filename = NULL;
-
- /* First preparse buf for %verify() */
- if (parseForVerify(buf, &verify_flags)) {
- processFileListFailed = 1;
+ s = *fp;
+ SKIPSPACE(s);
+ if (! *s) {
fp++; continue;
}
+ fileName = NULL;
+ strcpy(buf, s);
- /* Next parse for %attr() */
- if (parseForAttr(buf, &currPmode, &currUname, &currGname)) {
- processFileListFailed = 1;
- fp++; continue;
+ /* Reset for a new line in %files */
+ fl.isDir = 0;
+ fl.inFtw = 0;
+ fl.currentFlags = 0;
+ fl.currentVerifyFlags = fl.defVerifyFlags;
+ fl.current.Pmode = fl.def.Pmode;
+ fl.current.Pdirmode = fl.def.Pdirmode;
+ fl.isSpecialDoc = 0;
+ FREE(fl.current.PmodeString);
+ FREE(fl.current.PdirmodeString);
+ FREE(fl.current.Uname);
+ FREE(fl.current.Gname);
+ FREE(fl.currentLang);
+ if (fl.def.PmodeString) {
+ fl.current.PmodeString = strdup(fl.def.PmodeString);
+ }
+ if (fl.def.PdirmodeString) {
+ fl.current.PdirmodeString = strdup(fl.def.PdirmodeString);
+ }
+ if (fl.def.Uname) {
+ fl.current.Uname = strdup(fl.def.Uname);
+ }
+ if (fl.def.Gname) {
+ fl.current.Gname = strdup(fl.def.Gname);
}
- /* Then parse for %config or %config() */
- if (parseForConfig(buf, &conf)) {
- processFileListFailed = 1;
+ if (parseForVerify(buf, &fl)) {
fp++; continue;
}
-
- s = strtok(buf, " \t\n");
- while (s) {
- if (!strcmp(s, "%docdir")) {
- s = strtok(NULL, " \t\n");
- addDocdir(s);
- break;
- } else if (!strcmp(s, "%doc")) {
- isdoc = 1;
- } else if (!strcmp(s, "%dir")) {
- isdir = 1;
- } else if (!strcmp(s, "%ghost")) {
- isghost = 1;
- } else {
- if (filename) {
- /* We already got a file -- error */
- rpmError(RPMERR_BADSPEC,
- "Two files on one line: %s", filename);
- processFileListFailed = 1;
- }
- if (*s != '/') {
- if (isdoc) {
- special_doc = 1;
- } else {
- /* not in %doc, does not begin with / -- error */
- rpmError(RPMERR_BADSPEC,
- "File must begin with \"/\": %s", s);
- processFileListFailed = 1;
- }
- } else {
- filename = s;
- }
- }
- s = strtok(NULL, " \t\n");
+ if (parseForAttr(buf, &fl)) {
+ fp++; continue;
}
- if (special_doc) {
- if (passed_special_doc) {
- fp++;
- continue;
- } else {
- if (filename || conf || isdir || isghost) {
- rpmError(RPMERR_BADSPEC,
- "Can't mix special %%doc with other forms: %s", fp);
- processFileListFailed = 1;
- fp++; continue;
- }
- sprintf(buf, "%s/%s-%s", rpmGetVar(RPMVAR_DEFAULTDOCDIR),
- name, version);
- filename = buf;
- passed_special_doc = 1;
- }
+ if (parseForConfig(buf, &fl)) {
+ fp++; continue;
}
- if (! filename) {
- fp++;
- continue;
+ if (parseForLang(buf, &fl)) {
+ fp++; continue;
+ }
+ if (parseForSimple(spec, pkg, buf, &fl, &fileName)) {
+ fp++; continue;
+ }
+ if (! fileName) {
+ fp++; continue;
}
- if (type == RPMLEAD_BINARY) {
- /* check that file starts with leading "/" */
- if (*filename != '/') {
- rpmError(RPMERR_BADSPEC,
- "File needs leading \"/\": %s", filename);
- processFileListFailed = 1;
- fp++; continue;
+ if (fl.isSpecialDoc) {
+ /* Save this stuff for last */
+ specialDoc = strdup(fileName);
+ specialDocAttrRec = fl.current;
+ if (specialDocAttrRec.PmodeString) {
+ specialDocAttrRec.PmodeString =
+ strdup(specialDocAttrRec.PmodeString);
}
-
- if (glob_pattern_p(filename)) {
- char fullname[1024];
-
- if (rpmGetVar(RPMVAR_ROOT)) {
- sprintf(fullname, "%s%s", rpmGetVar(RPMVAR_ROOT), filename);
- } else {
- strcpy(fullname, filename);
- }
-
- if (glob(fullname, 0, glob_error, &glob_result) ||
- (glob_result.gl_pathc < 1)) {
- rpmError(RPMERR_BADSPEC, "No matches: %s", fullname);
- processFileListFailed = 1;
- globfree(&glob_result);
- fp++; continue;
- }
-
- c = 0;
- x = 0;
- while (x < glob_result.gl_pathc) {
- int offset = strlen(rpmGetVar(RPMVAR_ROOT) ? : "");
- c += add_file(&fes, &(glob_result.gl_pathv[x][offset]),
- isdoc, conf, isdir, isghost, verify_flags,
- currPmode, currUname, currGname, prefix);
- x++;
- }
- globfree(&glob_result);
- } else {
- c = add_file(&fes, filename, isdoc, conf, isdir, isghost,
- verify_flags, currPmode, currUname,
- currGname, prefix);
+ if (specialDocAttrRec.PdirmodeString) {
+ specialDocAttrRec.PdirmodeString =
+ strdup(specialDocAttrRec.PdirmodeString);
}
- } else {
- /* Source package are the simple case */
- fest = malloc(sizeof(struct file_entry));
- fest->isdoc = 0;
- fest->conf = 0;
- fest->isghost = 0;
- if (!strcmp(filename, specFile)) {
- fest->isspecfile = 1;
- } else {
- fest->isspecfile = 0;
+ if (specialDocAttrRec.Uname) {
+ specialDocAttrRec.Uname = strdup(specialDocAttrRec.Uname);
}
- fest->verify_flags = 0; /* XXX - something else? */
- stat(filename, &fest->statbuf);
- fest->uname = getUname(fest->statbuf.st_uid);
- fest->gname = getGname(fest->statbuf.st_gid);
- if (! (fest->uname && fest->gname)) {
- rpmError(RPMERR_BADSPEC, "Bad owner/group: %s", filename);
- fest->uname = "";
- fest->gname = "";
- processFileListFailed = 1;
+ if (specialDocAttrRec.Gname) {
+ specialDocAttrRec.Gname = strdup(specialDocAttrRec.Gname);
}
- strcpy(fest->file, filename);
- fest->next = fes;
- fes = fest;
- c = 1;
- }
-
- if (! c) {
- rpmError(RPMERR_BADSPEC, "File not found: %s", filename);
- processFileListFailed = 1;
+ } else {
+ processBinaryFile(pkg, &fl, fileName);
}
- count += c;
fp++;
}
- /* If there are no files, don't add anything to the header */
- if (count) {
- char ** fileList;
- char ** fileMD5List;
- char ** fileLinktoList;
- int_32 * fileSizeList;
- int_32 * fileUIDList;
- int_32 * fileGIDList;
- char ** fileUnameList;
- char ** fileGnameList;
- int_32 * fileMtimesList;
- int_32 * fileFlagsList;
- int_16 * fileModesList;
- int_16 * fileRDevsList;
- int_32 * fileVerifyFlagsList;
-
- fileList = malloc(sizeof(char *) * count);
- fileLinktoList = malloc(sizeof(char *) * count);
- fileMD5List = malloc(sizeof(char *) * count);
- fileSizeList = malloc(sizeof(int_32) * count);
- fileUIDList = malloc(sizeof(int_32) * count);
- fileGIDList = malloc(sizeof(int_32) * count);
- fileUnameList = malloc(sizeof(char *) * count);
- fileGnameList = malloc(sizeof(char *) * count);
- fileMtimesList = malloc(sizeof(int_32) * count);
- fileFlagsList = malloc(sizeof(int_32) * count);
- fileModesList = malloc(sizeof(int_16) * count);
- fileRDevsList = malloc(sizeof(int_16) * count);
- fileVerifyFlagsList = malloc(sizeof(int_32) * count);
-
- /* Build a reverse sorted file array. */
- /* This makes uninstalls a lot easier. */
- file_entry_array = malloc(sizeof(struct file_entry *) * count);
- c = 0;
- fest = fes;
- while (fest) {
- file_entry_array[c++] = fest;
- fest = fest->next;
- }
- qsort(file_entry_array, count, sizeof(struct file_entry *),
- compare_fe);
-
- /* Do timecheck */
- tc = 0;
- currentTime = time(NULL);
- if ((tcs = rpmGetVar(RPMVAR_TIMECHECK))) {
- tc = strtoul(tcs, NULL, 10);
+ /* Now process special doc, if there is one */
+ if (specialDoc) {
+ if (installSpecialDoc) {
+ doScript(spec, RPMBUILD_STRINGBUF, "%doc", pkg->specialDoc, 0);
}
+ fl.current = specialDocAttrRec;
+ processBinaryFile(pkg, &fl, specialDoc);
+ FREE(specialDoc);
+ FREE(specialDocAttrRec.PmodeString);
+ FREE(specialDocAttrRec.PdirmodeString);
+ FREE(specialDocAttrRec.Uname);
+ FREE(specialDocAttrRec.Gname);
+ }
- c = 0;
- while (c < count) {
- fest = file_entry_array[c];
- if (type == RPMLEAD_BINARY) {
- x = strlen(fest->file) - 1;
- if (x && fest->file[x] == '/') {
- fest->file[x] = '\0';
- }
- fileList[c] = fest->file;
- } else {
- fileList[c] = strrchr(fest->file, '/') + 1;
- }
- if ((c > 0) && !strcmp(fileList[c], fileList[c-1])) {
- rpmError(RPMERR_BADSPEC, "File listed twice: %s", fileList[c]);
- processFileListFailed = 1;
- }
-
- fileUnameList[c] = fest->uname;
- fileGnameList[c] = fest->gname;
- *size += fest->statbuf.st_size;
- if (S_ISREG(fest->statbuf.st_mode)) {
- if ((type == RPMLEAD_BINARY) &&
- rpmGetVar(RPMVAR_ROOT)) {
- sprintf(buf, "%s%s", rpmGetVar(RPMVAR_ROOT), fest->file);
- } else {
- strcpy(buf, fest->file);
- }
- mdfile(buf, buf);
- fileMD5List[c] = strdup(buf);
- rpmMessage(RPMMESS_DEBUG, "md5(%s) = %s\n", fest->file, buf);
- } else {
- /* This is stupid */
- fileMD5List[c] = strdup("");
- }
- fileSizeList[c] = fest->statbuf.st_size;
- fileUIDList[c] = fest->statbuf.st_uid;
- fileGIDList[c] = fest->statbuf.st_gid;
- fileMtimesList[c] = fest->statbuf.st_mtime;
-
- /* Do timecheck */
- if (tc && (type == RPMLEAD_BINARY)) {
- if (currentTime - fest->statbuf.st_mtime > tc) {
- rpmMessage(RPMMESS_WARNING, "TIMECHECK failure: %s\n",
- fest->file);
- }
- }
-
- fileFlagsList[c] = 0;
- if (isDoc(fest->file))
- fileFlagsList[c] |= RPMFILE_DOC;
- if (fest->isdoc)
- fileFlagsList[c] |= RPMFILE_DOC;
- if (fest->isghost)
- fileFlagsList[c] |= RPMFILE_GHOST;
- if (fest->conf && !(fest->statbuf.st_mode & S_IFDIR))
- fileFlagsList[c] |= fest->conf;
- if (fest->isspecfile)
- fileFlagsList[c] |= RPMFILE_SPECFILE;
-
- fileModesList[c] = fest->statbuf.st_mode;
- fileRDevsList[c] = fest->statbuf.st_rdev;
- if (! fest->isghost) {
- fileVerifyFlagsList[c] = fest->verify_flags;
- } else {
- fileVerifyFlagsList[c] = fest->verify_flags &
- ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE |
- RPMVERIFY_LINKTO | RPMVERIFY_MTIME);
- }
+ FREE(files);
- if (S_ISLNK(fest->statbuf.st_mode)) {
- if (rpmGetVar(RPMVAR_ROOT)) {
- sprintf(buf, "%s%s", rpmGetVar(RPMVAR_ROOT), fest->file);
- } else {
- strcpy(buf, fest->file);
- }
- buf[readlink(buf, buf, 1024)] = '\0';
- fileLinktoList[c] = strdup(buf);
- } else {
- /* This is stupid */
- fileLinktoList[c] = strdup("");
- }
- c++;
- }
-
- /* Add the header entries */
- c = count;
- headerAddEntry(header, RPMTAG_FILENAMES, RPM_STRING_ARRAY_TYPE, fileList, c);
- headerAddEntry(header, RPMTAG_FILELINKTOS, RPM_STRING_ARRAY_TYPE,
- fileLinktoList, c);
- headerAddEntry(header, RPMTAG_FILEMD5S, RPM_STRING_ARRAY_TYPE, fileMD5List, c);
- headerAddEntry(header, RPMTAG_FILESIZES, RPM_INT32_TYPE, fileSizeList, c);
- headerAddEntry(header, RPMTAG_FILEUIDS, RPM_INT32_TYPE, fileUIDList, c);
- headerAddEntry(header, RPMTAG_FILEGIDS, RPM_INT32_TYPE, fileGIDList, c);
- headerAddEntry(header, RPMTAG_FILEUSERNAME, RPM_STRING_ARRAY_TYPE,
- fileUnameList, c);
- headerAddEntry(header, RPMTAG_FILEGROUPNAME, RPM_STRING_ARRAY_TYPE,
- fileGnameList, c);
- headerAddEntry(header, RPMTAG_FILEMTIMES, RPM_INT32_TYPE, fileMtimesList, c);
- headerAddEntry(header, RPMTAG_FILEFLAGS, RPM_INT32_TYPE, fileFlagsList, c);
- headerAddEntry(header, RPMTAG_FILEMODES, RPM_INT16_TYPE, fileModesList, c);
- headerAddEntry(header, RPMTAG_FILERDEVS, RPM_INT16_TYPE, fileRDevsList, c);
- headerAddEntry(header, RPMTAG_FILEVERIFYFLAGS, RPM_INT32_TYPE,
- fileVerifyFlagsList, c);
-
- /* Free the allocated strings */
- c = count;
- while (c--) {
- free(fileMD5List[c]);
- free(fileLinktoList[c]);
- }
-
- /* Free all those lists */
- free(fileList);
- free(fileLinktoList);
- free(fileMD5List);
- free(fileSizeList);
- free(fileUIDList);
- free(fileGIDList);
- free(fileUnameList);
- free(fileGnameList);
- free(fileMtimesList);
- free(fileFlagsList);
- free(fileModesList);
- free(fileRDevsList);
- free(fileVerifyFlagsList);
-
- /* Free the file entry array */
- free(file_entry_array);
-
- /* Free the file entry stack */
- fest = fes;
- while (fest) {
- fes = fest->next;
- free(fest);
- fest = fes;
+ if (! fl.processingFailed) {
+ genCpioListAndHeader(&fl, &(pkg->cpioList), &(pkg->cpioCount),
+ pkg->header, 0);
+
+ if (spec->timeCheck) {
+ timeCheck(spec->timeCheck, pkg->header);
}
}
- freeSplitString(files);
- return processFileListFailed;
+ /* Clean up */
+ FREE(fl.prefix);
+ FREE(fl.current.PmodeString);
+ FREE(fl.current.PdirmodeString);
+ FREE(fl.current.Uname);
+ FREE(fl.current.Gname);
+ FREE(fl.def.PmodeString);
+ FREE(fl.def.PdirmodeString);
+ FREE(fl.def.Uname);
+ FREE(fl.def.Gname);
+ FREE(fl.currentLang);
+ freeFileList(fl.fileList, fl.fileListRecsUsed);
+ while (fl.docDirCount--) {
+ FREE(fl.docDirs[fl.docDirCount]);
+ }
+ return fl.processingFailed;
}
-/*************************************************************/
-/* */
-/* misc */
-/* */
-/*************************************************************/
-
-static int compare_fe(const void *ap, const void *bp)
+static void timeCheck(int tc, Header h)
{
- char *a, *b;
+ int *mtime;
+ char **file;
+ int count, x, currentTime;
- a = (*(struct file_entry **)ap)->file;
- b = (*(struct file_entry **)bp)->file;
+ headerGetEntry(h, RPMTAG_FILENAMES, NULL, (void **) &file, &count);
+ headerGetEntry(h, RPMTAG_FILEMTIMES, NULL, (void **) &mtime, NULL);
- return strcmp(a, b);
+ currentTime = time(NULL);
+
+ x = 0;
+ while (x < count) {
+ if (currentTime - mtime[x] > tc) {
+ rpmMessage(RPMMESS_WARNING, "TIMECHECK failure: %s\n", file[x]);
+ }
+ x++;
+ }
}
-/*************************************************************/
-/* */
-/* Doc dir stuff */
-/* */
-/*************************************************************/
-
-/* XXX hard coded limit -- only 1024 %docdir allowed */
-static char *docdirs[1024];
-static int docdir_count;
+static void genCpioListAndHeader(struct FileList *fl,
+ struct cpioFileMapping **cpioList,
+ int *cpioCount, Header h, int isSrc)
+{
+ int skipLen = 0;
+ struct FileListRec *p;
+ int count;
+ struct cpioFileMapping *cpioListPtr;
+ char *s, buf[BUFSIZ];
+
+ /* Sort the big list */
+ qsort(fl->fileList, fl->fileListRecsUsed,
+ sizeof(*(fl->fileList)), compareFileListRecs);
+
+ /* Generate the cpio list and the header */
+ if (! isSrc) {
+ if (fl->prefix) {
+ skipLen = 1 + strlen(fl->prefix);
+ } else {
+ skipLen = 1;
+ }
+ }
+ *cpioList = malloc(sizeof(**cpioList) * fl->fileListRecsUsed);
+ *cpioCount = 0;
+ cpioListPtr = *cpioList;
+ p = fl->fileList;
+ count = fl->fileListRecsUsed;
+ while (count) {
+ if ((count > 1) && !strcmp(p->fileName, p[1].fileName)) {
+ rpmError(RPMERR_BADSPEC, "File listed twice: %s", p->fileName);
+ fl->processingFailed = 1;
+ }
+
+ /* Make the cpio list */
+ if (! (p->flags & RPMFILE_GHOST)) {
+ cpioListPtr->fsPath = strdup(p->diskName);
+ cpioListPtr->archivePath = strdup(p->fileName + skipLen);
+ cpioListPtr->finalMode = p->mode;
+ cpioListPtr->finalUid = p->uid;
+ cpioListPtr->finalGid = p->gid;
+ cpioListPtr->mapFlags = CPIO_MAP_PATH | CPIO_MAP_MODE |
+ CPIO_MAP_UID | CPIO_MAP_GID;
+ cpioListPtr++;
+ (*cpioCount)++;
+ }
+
+ /* Make the header */
+ headerAddOrAppendEntry(h, RPMTAG_FILENAMES, RPM_STRING_ARRAY_TYPE,
+ &(p->fileName), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILESIZES, RPM_INT32_TYPE,
+ &(p->size), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILEUSERNAME, RPM_STRING_ARRAY_TYPE,
+ &(p->uname), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILEGROUPNAME, RPM_STRING_ARRAY_TYPE,
+ &(p->gname), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILEMTIMES, RPM_INT32_TYPE,
+ &(p->mtime), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILEMODES, RPM_INT16_TYPE,
+ &(p->mode), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILERDEVS, RPM_INT16_TYPE,
+ &(p->rdev), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILEDEVICES, RPM_INT32_TYPE,
+ &(p->device), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILEINODES, RPM_INT32_TYPE,
+ &(p->inode), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILELANGS, RPM_STRING_ARRAY_TYPE,
+ &(p->lang), 1);
+
+ /* We used to add these, but they should not be needed */
+ /* headerAddOrAppendEntry(h, RPMTAG_FILEUIDS,
+ * RPM_INT32_TYPE, &(p->uid), 1);
+ * headerAddOrAppendEntry(h, RPMTAG_FILEGIDS,
+ * RPM_INT32_TYPE, &(p->gid), 1);
+ */
+
+ buf[0] = '\0';
+ s = buf;
+ if (S_ISREG(p->mode)) {
+ mdfile(p->diskName, buf);
+ }
+ headerAddOrAppendEntry(h, RPMTAG_FILEMD5S, RPM_STRING_ARRAY_TYPE,
+ &s, 1);
+
+ buf[0] = '\0';
+ s = buf;
+ if (S_ISLNK(p->mode)) {
+ buf[readlink(p->diskName, buf, BUFSIZ)] = '\0';
+ }
+ headerAddOrAppendEntry(h, RPMTAG_FILELINKTOS, RPM_STRING_ARRAY_TYPE,
+ &s, 1);
+
+ if (p->flags & RPMFILE_GHOST) {
+ p->verifyFlags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE |
+ RPMVERIFY_LINKTO | RPMVERIFY_MTIME);
+ }
+ headerAddOrAppendEntry(h, RPMTAG_FILEVERIFYFLAGS, RPM_INT32_TYPE,
+ &(p->verifyFlags), 1);
+
+ if (!isSrc && isDoc(fl, p->fileName)) {
+ p->flags |= RPMFILE_DOC;
+ }
+ if (p->mode & S_IFDIR) {
+ p->flags &= ~RPMFILE_CONFIG;
+ p->flags &= ~RPMFILE_DOC;
+ }
+ headerAddOrAppendEntry(h, RPMTAG_FILEFLAGS, RPM_INT32_TYPE,
+ &(p->flags), 1);
+
+ p++;
+ count--;
+ }
+ headerAddEntry(h, RPMTAG_SIZE, RPM_INT32_TYPE,
+ &(fl->totalFileSize), 1);
+}
-static void resetDocdir(void)
+static void freeFileList(struct FileListRec *fileList, int count)
{
- while (docdir_count--) {
- free(docdirs[docdir_count]);
- }
- docdir_count = 0;
- docdirs[docdir_count++] = strdup("/usr/doc");
- docdirs[docdir_count++] = strdup("/usr/man");
- docdirs[docdir_count++] = strdup("/usr/info");
- docdirs[docdir_count++] = strdup("/usr/X11R6/man");
+ while (count--) {
+ FREE(fileList[count].diskName);
+ FREE(fileList[count].fileName);
+ FREE(fileList[count].lang);
+ }
+ FREE(fileList);
}
-static void addDocdir(char *dirname)
+void freeCpioList(struct cpioFileMapping *cpioList, int cpioCount)
{
- if (docdir_count == 1024) {
- fprintf(stderr, "RPMERR_INTERNAL: Hit limit in addDocdir()\n");
- exit(RPMERR_INTERNAL);
+ struct cpioFileMapping *p = cpioList;
+
+ while (cpioCount--) {
+ rpmMessage(RPMMESS_DEBUG, "archive = %s, fs = %s\n",
+ p->archivePath, p->fsPath);
+ FREE(p->archivePath);
+ FREE(p->fsPath);
+ p++;
}
- docdirs[docdir_count++] = strdup(dirname);
+ FREE(cpioList);
+}
+
+static int compareFileListRecs(const void *ap, const void *bp)
+{
+ char *a, *b;
+
+ a = ((struct FileListRec *)ap)->fileName;
+ b = ((struct FileListRec *)bp)->fileName;
+
+ return strcmp(a, b);
}
-static int isDoc(char *filename)
+static int isDoc(struct FileList *fl, char *fileName)
{
- int x = 0;
+ int x = fl->docDirCount;
- while (x < docdir_count) {
- if (strstr(filename, docdirs[x]) == filename) {
+ while (x--) {
+ if (strstr(fileName, fl->docDirs[x]) == fileName) {
return 1;
}
- x++;
}
return 0;
}
-/*************************************************************/
-/* */
-/* File stating / tree walk */
-/* */
-/*************************************************************/
-
-/* Need a bunch of globals to keep track of things in ftw() */
-static int Gisdoc;
-static int Gisghost;
-static int Gconf;
-static int Gverify_flags;
-static int Gcount;
-static char *GPmode;
-static char *GUname;
-static char *GGname;
-static struct file_entry **Gfestack;
-static char *Gprefix;
-
-static int add_file(struct file_entry **festack, const char *name,
- int isdoc, int conf, int isdir, int isghost,
- int verify_flags,
- char *Pmode, char *Uname, char *Gname, char *prefix)
+static int processBinaryFile(Package pkg, struct FileList *fl, char *fileName)
+{
+ char fullname[BUFSIZ];
+ glob_t glob_result;
+ int x, offset, rc = 0;
+
+ /* check that file starts with leading "/" */
+ if (*fileName != '/') {
+ rpmError(RPMERR_BADSPEC, "File needs leading \"/\": %s", *fileName);
+ fl->processingFailed = 1;
+ return 1;
+ }
+
+ if (myGlobPatternP(fileName)) {
+ if (fl->buildRoot) {
+ sprintf(fullname, "%s%s", fl->buildRoot, fileName);
+ offset = strlen(fl->buildRoot);
+ } else {
+ strcpy(fullname, fileName);
+ offset = 0;
+ }
+
+ if (glob(fullname, 0, glob_error, &glob_result) ||
+ (glob_result.gl_pathc < 1)) {
+ rpmError(RPMERR_BADSPEC, "File not found: %s", fullname);
+ fl->processingFailed = 1;
+ globfree(&glob_result);
+ return 1;
+ }
+
+ x = 0;
+ while (x < glob_result.gl_pathc) {
+ rc = addFile(fl, &(glob_result.gl_pathv[x][offset]), NULL);
+ x++;
+ }
+ globfree(&glob_result);
+ } else {
+ rc = addFile(fl, fileName, NULL);
+ }
+
+ return rc;
+}
+
+static int addFile(struct FileList *fl, char *name, struct stat *statp)
{
- struct file_entry *p;
- char *copyTo, copied;
- const char *prefixTest, *prefixPtr;
- const char *copyFrom;
- char fullname[1024];
- int mode;
-
- /* Set these up for ftw() */
- Gfestack = festack;
- Gisdoc = isdoc;
- Gconf = conf;
- Gisghost = isghost;
- Gverify_flags = verify_flags;
- GPmode = Pmode;
- GUname = Uname;
- GGname = Gname;
- Gprefix = prefix;
-
- p = malloc(sizeof(struct file_entry));
-
- copyTo = p->file;
+ char fileName[BUFSIZ];
+ char diskName[BUFSIZ];
+ char *copyTo, *copyFrom, copied;
+ char *prefixTest, *prefixPtr;
+ struct stat statbuf;
+ int_16 fileMode;
+ int fileUid, fileGid;
+ char *fileUname, *fileGname;
+
+ /* Copy to fileName, eliminate duplicate "/" and trailing "/" */
+ copyTo = fileName;
copied = '\0';
copyFrom = name;
while (*copyFrom) {
@@ -655,178 +707,325 @@ static int add_file(struct file_entry **festack, const char *name,
copyFrom++;
}
*copyTo = '\0';
+ copyTo--;
+ if ((copyTo != fileName) && (*copyTo == '/')) {
+ *copyTo = '\0';
+ }
- p->isdoc = isdoc;
- p->conf = conf;
- p->isghost = isghost;
- p->isspecfile = 0; /* source packages are done by hand */
- p->verify_flags = verify_flags;
- if (rpmGetVar(RPMVAR_ROOT)) {
- sprintf(fullname, "%s%s", rpmGetVar(RPMVAR_ROOT), name);
+ if (fl->inFtw) {
+ /* Any buildRoot is already prepended */
+ strcpy(diskName, fileName);
+ if (fl->buildRoot) {
+ strcpy(fileName, diskName + strlen(fl->buildRoot));
+ }
} else {
- strcpy(fullname, name);
+ if (fl->buildRoot) {
+ sprintf(diskName, "%s%s", fl->buildRoot, fileName);
+ } else {
+ strcpy(diskName, fileName);
+ }
}
/* If we are using a prefix, validate the file */
- if (prefix) {
- prefixTest = name;
- prefixPtr = prefix;
- while (*prefixTest == '/') {
- prefixTest++; /* Skip leading "/" */
- }
+ if (!fl->inFtw && fl->prefix) {
+ prefixTest = fileName;
+ prefixPtr = fl->prefix;
+
while (*prefixPtr && *prefixTest && (*prefixTest == *prefixPtr)) {
prefixPtr++;
prefixTest++;
}
- if (*prefixPtr) {
+ if (*prefixPtr || (*prefixTest && *prefixTest != '/')) {
rpmError(RPMERR_BADSPEC, "File doesn't match prefix (%s): %s",
- prefix, name);
- return 0;
+ fl->prefix, fileName);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
}
}
- /* OK, finally stat() the file */
- if (lstat(fullname, &p->statbuf)) {
- return 0;
- }
-
- /*
- * If %attr() was specified, then use those values instead of
- * what lstat() returned.
- */
- if (Pmode && strcmp(Pmode, "-")) {
- sscanf(Pmode, "%o", &mode);
- mode |= p->statbuf.st_mode & S_IFMT;
- p->statbuf.st_mode = (unsigned short)mode;
+ if (! statp) {
+ statp = &statbuf;
+ if (lstat(diskName, statp)) {
+ rpmError(RPMERR_BADSPEC, "File not found: %s", diskName);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
+ }
}
- if (Uname && strcmp(Uname, "-")) {
- p->uname = getUnameS(Uname);
- } else {
- p->uname = getUname(p->statbuf.st_uid);
- }
-
- if (Gname && strcmp(Gname, "-")) {
- p->gname = getGnameS(Gname);
- } else {
- p->gname = getGname(p->statbuf.st_gid);
- }
-
- if (! (p->uname && p->gname)) {
- rpmError(RPMERR_BADSPEC, "Bad owner/group: %s\n", fullname);
- p->uname = "";
- p->gname = "";
- return 0;
- }
-
- if ((! isdir) && S_ISDIR(p->statbuf.st_mode)) {
- /* This means we need to descend with ftw() */
- Gcount = 0;
-
+ if ((! fl->isDir) && S_ISDIR(statp->st_mode)) {
/* We use our own ftw() call, because ftw() uses stat() */
/* instead of lstat(), which causes it to follow symlinks! */
- myftw(fullname, add_file_aux, 16);
+ /* It also has better callback support. */
- free(p);
-
- return Gcount;
+ fl->inFtw = 1; /* Flag to indicate file has buildRoot prefixed */
+ fl->isDir = 1; /* Keep it from following myftw() again */
+ myftw(diskName, 16, addFile, fl);
+ fl->isDir = 0;
+ fl->inFtw = 0;
} else {
- /* Link it in */
- p->next = *festack;
- *festack = p;
+ fileMode = statp->st_mode;
+ fileUid = statp->st_uid;
+ fileGid = statp->st_gid;
+
+ /* %attr ? */
+ if (S_ISDIR(fileMode) && fl->current.PdirmodeString) {
+ if (fl->current.PdirmodeString[0] != '-') {
+ fileMode &= S_IFMT;
+ fileMode |= fl->current.Pdirmode;
+ }
+ } else {
+ if (fl->current.PmodeString) {
+ fileMode &= S_IFMT;
+ fileMode |= fl->current.Pmode;
+ }
+ }
+ if (fl->current.Uname) {
+ fileUname = getUnameS(fl->current.Uname);
+ } else {
+ fileUname = getUname(fileUid);
+ }
+ if (fl->current.Gname) {
+ fileGname = getGnameS(fl->current.Gname);
+ } else {
+ fileGname = getGname(fileGid);
+ }
+
+ if (! (fileUname && fileGname)) {
+ rpmError(RPMERR_BADSPEC, "Bad owner/group: %s\n", diskName);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
+ }
+
+ rpmMessage(RPMMESS_DEBUG, "File %d: %s\n", fl->fileCount, fileName);
+
+ /* Add to the file list */
+ if (fl->fileListRecsUsed == fl->fileListRecsAlloced) {
+ fl->fileListRecsAlloced += 128;
+ fl->fileList = realloc(fl->fileList,
+ fl->fileListRecsAlloced *
+ sizeof(*(fl->fileList)));
+ }
+
+ fl->fileList[fl->fileListRecsUsed].fileName = strdup(fileName);
+ fl->fileList[fl->fileListRecsUsed].diskName = strdup(diskName);
+ fl->fileList[fl->fileListRecsUsed].mode = fileMode;
+ fl->fileList[fl->fileListRecsUsed].uid = fileUid;
+ fl->fileList[fl->fileListRecsUsed].gid = fileGid;
+ fl->fileList[fl->fileListRecsUsed].uname = fileUname;
+ fl->fileList[fl->fileListRecsUsed].gname = fileGname;
+
+ fl->fileList[fl->fileListRecsUsed].lang =
+ strdup(fl->currentLang ? fl->currentLang : "");
+
+ fl->fileList[fl->fileListRecsUsed].flags = fl->currentFlags;
+ fl->fileList[fl->fileListRecsUsed].verifyFlags =
+ fl->currentVerifyFlags;
+ fl->fileList[fl->fileListRecsUsed].size = statp->st_size;
+ fl->fileList[fl->fileListRecsUsed].mtime = statp->st_mtime;
+ fl->fileList[fl->fileListRecsUsed].rdev = statp->st_rdev;
+ fl->fileList[fl->fileListRecsUsed].device = statp->st_dev;
+ fl->fileList[fl->fileListRecsUsed].inode = statp->st_ino;
+ fl->fileListRecsUsed++;
+
+ fl->totalFileSize += statp->st_size;
+ fl->fileCount++;
+ }
- rpmMessage(RPMMESS_DEBUG, "ADDING: %s\n", name);
+ return 0;
+}
- /* return number of entries added */
- return 1;
+static int parseForSimple(Spec spec, Package pkg, char *buf,
+ struct FileList *fl, char **fileName)
+{
+ char *s;
+ int res, specialDoc = 0;
+ char *name, *version;
+ char specialDocBuf[BUFSIZ];
+
+ specialDocBuf[0] = '\0';
+ *fileName = NULL;
+ res = 0;
+ s = strtok(buf, " \t\n");
+ while (s) {
+ if (!strcmp(s, "%docdir")) {
+ s = strtok(NULL, " \t\n");
+ if (fl->docDirCount == MAXDOCDIR) {
+ rpmError(RPMERR_INTERNAL, "Hit limit for %%docdir");
+ fl->processingFailed = 1;
+ res = 1;
+ }
+ fl->docDirs[fl->docDirCount++] = strdup(s);
+ if (strtok(NULL, " \t\n")) {
+ rpmError(RPMERR_INTERNAL, "Only one arg for %%docdir");
+ fl->processingFailed = 1;
+ res = 1;
+ }
+ break;
+ } else if (!strcmp(s, "%doc")) {
+ fl->currentFlags |= RPMFILE_DOC;
+ } else if (!strcmp(s, "%ghost")) {
+ fl->currentFlags |= RPMFILE_GHOST;
+ } else if (!strcmp(s, "%dir")) {
+ fl->isDir = 1;
+ } else {
+ if (*fileName) {
+ /* We already got a file -- error */
+ rpmError(RPMERR_BADSPEC,
+ "Two files on one line: %s", *fileName);
+ fl->processingFailed = 1;
+ res = 1;
+ }
+ if (*s != '/') {
+ if (fl->currentFlags & RPMFILE_DOC) {
+ specialDoc = 1;
+ strcat(specialDocBuf, " ");
+ strcat(specialDocBuf, s);
+ } else {
+ /* not in %doc, does not begin with / -- error */
+ rpmError(RPMERR_BADSPEC,
+ "File must begin with \"/\": %s", s);
+ fl->processingFailed = 1;
+ res = 1;
+ }
+ } else {
+ *fileName = s;
+ }
+ }
+ s = strtok(NULL, " \t\n");
+ }
+
+ if (specialDoc) {
+ if (*fileName || (fl->currentFlags & ~(RPMFILE_DOC))) {
+ rpmError(RPMERR_BADSPEC,
+ "Can't mix special %%doc with other forms: %s",
+ *fileName);
+ fl->processingFailed = 1;
+ res = 1;
+ } else {
+ headerGetEntry(pkg->header, RPMTAG_NAME, NULL,
+ (void *) &name, NULL);
+ headerGetEntry(pkg->header, RPMTAG_VERSION, NULL,
+ (void *) &version, NULL);
+ sprintf(buf, "%s/%s-%s", spec->docDir, name, version);
+
+ if (! fl->passedSpecialDoc) {
+ pkg->specialDoc = newStringBuf();
+ appendStringBuf(pkg->specialDoc,
+ "export DOCDIR=$RPM_BUILD_ROOT");
+ appendLineStringBuf(pkg->specialDoc, buf);
+ appendLineStringBuf(pkg->specialDoc, "rm -rf $DOCDIR");
+ appendLineStringBuf(pkg->specialDoc, "mkdir -p $DOCDIR");
+
+ *fileName = buf;
+ fl->passedSpecialDoc = 1;
+ fl->isSpecialDoc = 1;
+ }
+
+ appendStringBuf(pkg->specialDoc, "cp -pr ");
+ appendStringBuf(pkg->specialDoc, specialDocBuf);
+ appendLineStringBuf(pkg->specialDoc, " $DOCDIR");
+ }
}
+
+ return res;
}
-static int add_file_aux(const char *file, struct stat *sb, int flag)
+static int parseForVerify(char *buf, struct FileList *fl)
{
- const char *name = file;
+ char *p, *start, *end, *name;
+ char ourbuf[BUFSIZ];
+ int not, verifyFlags;
+ int *resultVerify;
- if (rpmGetVar(RPMVAR_ROOT)) {
- name += strlen(rpmGetVar(RPMVAR_ROOT));
+ if (!(p = start = strstr(buf, "%verify"))) {
+ if (!(p = start = strstr(buf, "%defverify"))) {
+ return 0;
+ }
+ name = "%defverify";
+ resultVerify = &(fl->defVerifyFlags);
+ p += 10;
+ } else {
+ name = "%verify";
+ resultVerify = &(fl->currentVerifyFlags);
+ p += 7;
}
- /* The 1 will cause add_file() to *not* descend */
- /* directories -- ftw() is already doing it! */
- Gcount += add_file(Gfestack, name, Gisdoc, Gconf, 1, Gisghost,
- Gverify_flags,
- GPmode, GUname, GGname, Gprefix);
+ SKIPSPACE(p);
- return 0; /* for ftw() */
-}
+ if (*p != '(') {
+ rpmError(RPMERR_BADSPEC, "Bad %s() syntax: %s", name, buf);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
+ }
+ p++;
-/*************************************************************/
-/* */
-/* globbing */
-/* */
-/*************************************************************/
+ end = p;
+ while (*end && *end != ')') {
+ end++;
+ }
-/* glob_pattern_p() taken from bash
- * Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc.
- */
+ if (! *end) {
+ rpmError(RPMERR_BADSPEC, "Bad %s() syntax: %s", name, buf);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
+ }
-/* Return nonzero if PATTERN has any special globbing chars in it. */
-static int glob_pattern_p (char *pattern)
-{
- register char *p = pattern;
- register char c;
- int open = 0;
-
- while ((c = *p++) != '\0')
- switch (c) {
- case '?':
- case '*':
- return (1);
- case '[': /* Only accept an open brace if there is a close */
- open++; /* brace to match it. Bracket expressions must be */
- continue; /* complete, according to Posix.2 */
- case ']':
- if (open)
- return (1);
- continue;
- case '\\':
- if (*p++ == '\0')
- return (0);
+ strncpy(ourbuf, p, end-p);
+ ourbuf[end-p] = '\0';
+ while (start <= end) {
+ *start++ = ' ';
+ }
+
+ p = strtok(ourbuf, ", \n\t");
+ not = 0;
+ verifyFlags = RPMVERIFY_NONE;
+ while (p) {
+ if (!strcmp(p, "not")) {
+ not = 1;
+ } else if (!strcmp(p, "md5")) {
+ verifyFlags |= RPMVERIFY_MD5;
+ } else if (!strcmp(p, "size")) {
+ verifyFlags |= RPMVERIFY_FILESIZE;
+ } else if (!strcmp(p, "link")) {
+ verifyFlags |= RPMVERIFY_LINKTO;
+ } else if (!strcmp(p, "user")) {
+ verifyFlags |= RPMVERIFY_USER;
+ } else if (!strcmp(p, "group")) {
+ verifyFlags |= RPMVERIFY_GROUP;
+ } else if (!strcmp(p, "mtime")) {
+ verifyFlags |= RPMVERIFY_MTIME;
+ } else if (!strcmp(p, "mode")) {
+ verifyFlags |= RPMVERIFY_MODE;
+ } else if (!strcmp(p, "rdev")) {
+ verifyFlags |= RPMVERIFY_RDEV;
+ } else {
+ rpmError(RPMERR_BADSPEC, "Invalid %s token: %s", name, p);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
}
+ p = strtok(NULL, ", \n\t");
+ }
- return (0);
-}
+ *resultVerify = not ? ~(verifyFlags) : verifyFlags;
-static int glob_error(const char *foo, int bar)
-{
- return 1;
+ return 0;
}
-/*************************************************************/
-/* */
-/* %attr parsing */
-/* */
-/*************************************************************/
-
-static int parseForAttr(char *buf, char **currPmode,
- char **currUname, char **currGname)
+static int parseForLang(char *buf, struct FileList *fl)
{
char *p, *start, *end;
char ourbuf[1024];
- int mode, x;
- if (!(p = start = strstr(buf, "%attr"))) {
+ if (!(p = start = strstr(buf, "%lang"))) {
return 0;
}
- *currPmode = *currUname = *currGname = NULL;
-
p += 5;
- while (*p && (*p == ' ' || *p == '\t')) {
- p++;
- }
+ SKIPSPACE(p);
if (*p != '(') {
- rpmError(RPMERR_BADSPEC, "Bad %%attr() syntax: %s", buf);
+ rpmError(RPMERR_BADSPEC, "Bad %%lang() syntax: %s", buf);
+ fl->processingFailed = 1;
return RPMERR_BADSPEC;
}
p++;
@@ -837,68 +1036,66 @@ static int parseForAttr(char *buf, char **currPmode,
}
if (! *end) {
- rpmError(RPMERR_BADSPEC, "Bad %%attr() syntax: %s", buf);
+ rpmError(RPMERR_BADSPEC, "Bad %%lang() syntax: %s", buf);
+ fl->processingFailed = 1;
return RPMERR_BADSPEC;
}
strncpy(ourbuf, p, end-p);
ourbuf[end-p] = '\0';
+ while (start <= end) {
+ *start++ = ' ';
+ }
- *currPmode = strtok(ourbuf, ", \n\t");
- *currUname = strtok(NULL, ", \n\t");
- *currGname = strtok(NULL, ", \n\t");
-
- if (! (*currPmode && *currUname && *currGname)) {
- rpmError(RPMERR_BADSPEC, "Bad %%attr() syntax: %s", buf);
- *currPmode = *currUname = *currGname = NULL;
+ p = strtok(ourbuf, ", \n\t");
+ if (!p) {
+ rpmError(RPMERR_BADSPEC, "Bad %%lang() syntax: %s", buf);
+ fl->processingFailed = 1;
return RPMERR_BADSPEC;
}
-
- /* Do a quick test on the mode argument */
- if (strcmp(*currPmode, "-")) {
- x = sscanf(*currPmode, "%o", &mode);
- if ((x == 0) || (mode >> 12)) {
- rpmError(RPMERR_BADSPEC, "Bad %%attr() mode spec: %s", buf);
- *currPmode = *currUname = *currGname = NULL;
- return RPMERR_BADSPEC;
- }
+ if (strlen(p) != 2) {
+ rpmError(RPMERR_BADSPEC, "%%lang() entries are 2 characters: %s", buf);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
}
-
- *currPmode = strdup(*currPmode);
- *currUname = strdup(*currUname);
- *currGname = strdup(*currGname);
-
- /* Set everything we just parsed to blank spaces */
- while (start <= end) {
- *start++ = ' ';
+ if (strtok(NULL, ", \n\t")) {
+ rpmError(RPMERR_BADSPEC, "Only one entry in %%lang(): %s", buf);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
}
-
+ fl->currentLang = strdup(p);
+
return 0;
}
-/*************************************************************/
-/* */
-/* %verify parsing */
-/* */
-/*************************************************************/
-
-static int parseForVerify(char *buf, int *verify_flags)
+static int parseForAttr(char *buf, struct FileList *fl)
{
- char *p, *start, *end;
+ char *p, *s, *start, *end, *name;
char ourbuf[1024];
- int not;
+ int x, defattr = 0;
+ struct AttrRec *resultAttr;
- if (!(p = start = strstr(buf, "%verify"))) {
- return 0;
+ if (!(p = start = strstr(buf, "%attr"))) {
+ if (!(p = start = strstr(buf, "%defattr"))) {
+ return 0;
+ }
+ defattr = 1;
+ name = "%defattr";
+ resultAttr = &(fl->def);
+ p += 8;
+ } else {
+ name = "%attr";
+ resultAttr = &(fl->current);
+ p += 5;
}
- p += 7;
- while (*p && (*p == ' ' || *p == '\t')) {
- p++;
- }
+ resultAttr->PmodeString = resultAttr->Uname = resultAttr->Gname = NULL;
+
+ SKIPSPACE(p);
if (*p != '(') {
- rpmError(RPMERR_BADSPEC, "Bad %%verify() syntax: %s", buf);
+ rpmError(RPMERR_BADSPEC, "Bad %s() syntax: %s", name, buf);
+ fl->processingFailed = 1;
return RPMERR_BADSPEC;
}
p++;
@@ -909,53 +1106,92 @@ static int parseForVerify(char *buf, int *verify_flags)
}
if (! *end) {
- rpmError(RPMERR_BADSPEC, "Bad %%verify() syntax: %s", buf);
+ rpmError(RPMERR_BADSPEC, "Bad %s() syntax: %s", name, buf);
+ fl->processingFailed = 1;
return RPMERR_BADSPEC;
}
+ if (defattr) {
+ s = end;
+ s++;
+ SKIPSPACE(s);
+ if (*s) {
+ rpmError(RPMERR_BADSPEC,
+ "No files after %%defattr(): %s", buf);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
+ }
+ }
+
strncpy(ourbuf, p, end-p);
ourbuf[end-p] = '\0';
- while (start <= end) {
- *start++ = ' ';
+
+ resultAttr->PmodeString = strtok(ourbuf, ", \n\t");
+ resultAttr->Uname = strtok(NULL, ", \n\t");
+ resultAttr->Gname = strtok(NULL, ", \n\t");
+ resultAttr->PdirmodeString = strtok(NULL, ", \n\t");
+
+ if (! (resultAttr->PmodeString &&
+ resultAttr->Uname && resultAttr->Gname)) {
+ rpmError(RPMERR_BADSPEC, "Bad %s() syntax: %s", name, buf);
+ resultAttr->PmodeString = resultAttr->Uname = resultAttr->Gname = NULL;
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
}
- p = strtok(ourbuf, ", \n\t");
- not = 0;
- *verify_flags = RPMVERIFY_NONE;
- while (p) {
- if (!strcmp(p, "not")) {
- not = 1;
- } else if (!strcmp(p, "md5")) {
- *verify_flags |= RPMVERIFY_MD5;
- } else if (!strcmp(p, "size")) {
- *verify_flags |= RPMVERIFY_FILESIZE;
- } else if (!strcmp(p, "link")) {
- *verify_flags |= RPMVERIFY_LINKTO;
- } else if (!strcmp(p, "user")) {
- *verify_flags |= RPMVERIFY_USER;
- } else if (!strcmp(p, "group")) {
- *verify_flags |= RPMVERIFY_GROUP;
- } else if (!strcmp(p, "mtime")) {
- *verify_flags |= RPMVERIFY_MTIME;
- } else if (!strcmp(p, "mode")) {
- *verify_flags |= RPMVERIFY_MODE;
- } else if (!strcmp(p, "rdev")) {
- *verify_flags |= RPMVERIFY_RDEV;
- } else {
- rpmError(RPMERR_BADSPEC, "Invalid %%verify token: %s", p);
+ /* Do a quick test on the mode argument and adjust for "-" */
+ if (!strcmp(resultAttr->PmodeString, "-")) {
+ resultAttr->PmodeString = NULL;
+ } else {
+ x = sscanf(resultAttr->PmodeString, "%o", &(resultAttr->Pmode));
+ if ((x == 0) || (resultAttr->Pmode >> 12)) {
+ rpmError(RPMERR_BADSPEC, "Bad %s() mode spec: %s", name, buf);
+ resultAttr->PmodeString = resultAttr->Uname =
+ resultAttr->Gname = NULL;
+ fl->processingFailed = 1;
return RPMERR_BADSPEC;
}
- p = strtok(NULL, ", \n\t");
+ resultAttr->PmodeString = strdup(resultAttr->PmodeString);
}
-
- if (not) {
- *verify_flags = ~(*verify_flags);
+ if (resultAttr->PdirmodeString) {
+ /* The processing here is slightly different to maintain */
+ /* compatibility with old spec files. */
+ if (!strcmp(resultAttr->PdirmodeString, "-")) {
+ resultAttr->PdirmodeString = strdup(resultAttr->PdirmodeString);
+ } else {
+ x = sscanf(resultAttr->PdirmodeString, "%o",
+ &(resultAttr->Pdirmode));
+ if ((x == 0) || (resultAttr->Pdirmode >> 12)) {
+ rpmError(RPMERR_BADSPEC,
+ "Bad %s() dirmode spec: %s", name, buf);
+ resultAttr->PmodeString = resultAttr->Uname =
+ resultAttr->Gname = resultAttr->PdirmodeString = NULL;
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
+ }
+ resultAttr->PdirmodeString = strdup(resultAttr->PdirmodeString);
+ }
+ }
+ if (!strcmp(resultAttr->Uname, "-")) {
+ resultAttr->Uname = NULL;
+ } else {
+ resultAttr->Uname = strdup(resultAttr->Uname);
+ }
+ if (!strcmp(resultAttr->Gname, "-")) {
+ resultAttr->Gname = NULL;
+ } else {
+ resultAttr->Gname = strdup(resultAttr->Gname);
+ }
+
+ /* Set everything we just parsed to blank spaces */
+ while (start <= end) {
+ *start++ = ' ';
}
return 0;
}
-static int parseForConfig(char *buf, int *conf)
+static int parseForConfig(char *buf, struct FileList *fl)
{
char *p, *start, *end;
char ourbuf[1024];
@@ -963,12 +1199,10 @@ static int parseForConfig(char *buf, int *conf)
if (!(p = start = strstr(buf, "%config"))) {
return 0;
}
- *conf = RPMFILE_CONFIG;
+ fl->currentFlags = RPMFILE_CONFIG;
p += 7;
- while (*p && (*p == ' ' || *p == '\t')) {
- p++;
- }
+ SKIPSPACE(p);
if (*p != '(') {
while (start < p) {
@@ -985,6 +1219,7 @@ static int parseForConfig(char *buf, int *conf)
if (! *end) {
rpmError(RPMERR_BADSPEC, "Bad %%config() syntax: %s", buf);
+ fl->processingFailed = 1;
return RPMERR_BADSPEC;
}
@@ -997,11 +1232,12 @@ static int parseForConfig(char *buf, int *conf)
p = strtok(ourbuf, ", \n\t");
while (p) {
if (!strcmp(p, "missingok")) {
- *conf |= RPMFILE_MISSINGOK;
+ fl->currentFlags |= RPMFILE_MISSINGOK;
} else if (!strcmp(p, "noreplace")) {
- *conf |= RPMFILE_NOREPLACE;
+ fl->currentFlags |= RPMFILE_NOREPLACE;
} else {
rpmError(RPMERR_BADSPEC, "Invalid %%config token: %s", p);
+ fl->processingFailed = 1;
return RPMERR_BADSPEC;
}
p = strtok(NULL, ", \n\t");
@@ -1009,3 +1245,39 @@ static int parseForConfig(char *buf, int *conf)
return 0;
}
+
+/* glob_pattern_p() taken from bash
+ * Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc.
+ *
+ * Return nonzero if PATTERN has any special globbing chars in it.
+ */
+static int myGlobPatternP (char *pattern)
+{
+ register char *p = pattern;
+ register char c;
+ int open = 0;
+
+ while ((c = *p++) != '\0')
+ switch (c) {
+ case '?':
+ case '*':
+ return (1);
+ case '[': /* Only accept an open brace if there is a close */
+ open++; /* brace to match it. Bracket expressions must be */
+ continue; /* complete, according to Posix.2 */
+ case ']':
+ if (open)
+ return (1);
+ continue;
+ case '\\':
+ if (*p++ == '\0')
+ return (0);
+ }
+
+ return (0);
+}
+
+static int glob_error(const char *foo, int bar)
+{
+ return 1;
+}