build/files.c (addFile): replaced myftw() with fts(3)

This commit is contained in:
Alexey Tourbin 2011-01-14 23:34:04 +03:00
parent d3842e8715
commit 161864908a
6 changed files with 63 additions and 300 deletions

View File

@ -320,8 +320,6 @@ INPUT = \
@top_srcdir@/build/expression.c \
@top_srcdir@/build/files.c \
@top_srcdir@/build/misc.c \
@top_srcdir@/build/myftw.c \
@top_srcdir@/build/myftw.h \
@top_srcdir@/build/names.c \
@top_srcdir@/build/pack.c \
@top_srcdir@/build/parseBuildInstallClean.c \

View File

@ -12,11 +12,11 @@ LIBS =
pkgincdir = $(pkgincludedir)
pkginc_HEADERS = rpmbuild.h rpmspec.h
noinst_HEADERS = buildio.h myftw.h
noinst_HEADERS = buildio.h
lib_LTLIBRARIES = librpmbuild.la
librpmbuild_la_SOURCES = \
build.c expression.c files.c misc.c myftw.c names.c pack.c \
build.c expression.c files.c misc.c names.c pack.c \
parseBuildInstallClean.c parseChangelog.c parseDescription.c \
parseFiles.c parsePreamble.c parsePrep.c parseReqs.c parseScript.c \
parseSpec.c poptBT.c reqprov.c spec.c

View File

@ -16,7 +16,6 @@
#include "buildio.h"
#include "myftw.h"
#include "debug.h"
/*@access Header @*/
@ -103,7 +102,6 @@ typedef struct FileList_s {
int devminor;
int isDir;
int inFtw;
int currentFlags;
specdFlags currentSpecdFlags;
int currentVerifyFlags;
@ -1460,6 +1458,9 @@ static int pathIsCanonical(const char *path)
return 0;
}
/* forward ref */
static rpmRC recurseDir(FileList fl, const char * diskPath);
/**
* Add a file to the package manifest.
* @param fl package file tree walk data
@ -1568,16 +1569,8 @@ static rpmRC addFile(FileList fl, const char * diskPath,
}
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! */
/* It also has better callback support. */
fl->inFtw = 1; /* Flag to indicate file has buildRootURL prefixed */
fl->isDir = 1; /* Keep it from following myftw() again */
(void) myftw(diskPath, 16, (myftwFunc) addFile, fl);
fl->isDir = 0;
fl->inFtw = 0;
return 0;
/* FIX: fl->buildRoot may be NULL */
return recurseDir(fl, diskPath);
}
fileMode = statp->st_mode;
@ -1666,6 +1659,61 @@ static rpmRC addFile(FileList fl, const char * diskPath,
return RPMRC_OK;
}
#include <fts.h>
/**
* Add directory (and all of its files) to the package manifest.
* @param fl package file tree walk data
* @param diskPath path to file
* @return RPMRC_OK on success
*/
static rpmRC recurseDir(FileList fl, const char * diskPath)
{
char * ftsSet[2];
FTS * ftsp;
FTSENT * fts;
int myFtsOpts = (FTS_COMFOLLOW | FTS_NOCHDIR | FTS_PHYSICAL);
rpmRC rc = RPMRC_FAIL;
fl->isDir = 1; /* Keep it from following myftw() again */
ftsSet[0] = (char *) diskPath;
ftsSet[1] = NULL;
ftsp = fts_open(ftsSet, myFtsOpts, NULL);
while ((fts = fts_read(ftsp)) != NULL) {
switch (fts->fts_info) {
case FTS_D: /* preorder directory */
case FTS_F: /* regular file */
case FTS_SL: /* symbolic link */
case FTS_SLNONE: /* symbolic link without target */
case FTS_DEFAULT: /* none of the above */
rc = addFile(fl, fts->fts_accpath, fts->fts_statp);
break;
case FTS_DOT: /* dot or dot-dot */
case FTS_DP: /* postorder directory */
rc = RPMRC_OK;
break;
case FTS_NS: /* stat(2) failed */
case FTS_DNR: /* unreadable directory */
case FTS_ERR: /* error; errno is set */
case FTS_DC: /* directory that causes cycles */
case FTS_NSOK: /* no stat(2) requested */
case FTS_INIT: /* initialized only */
case FTS_W: /* whiteout object */
default:
rc = RPMRC_FAIL;
break;
}
if (rc)
break;
}
(void) fts_close(ftsp);
fl->isDir = 0;
return rc;
}
/**
* Add a file to a binary package.
* @param pkg
@ -1679,7 +1727,7 @@ static int processBinaryFile(/*@unused@*/ Package pkg, FileList fl,
fileSystem@*/
/*@modifies *fl, fl->processingFailed,
fl->fileList, fl->fileListRecsAlloced, fl->fileListRecsUsed,
fl->totalFileSize, fl->fileCount, fl->inFtw, fl->isDir,
fl->totalFileSize, fl->fileCount, fl->isDir,
rpmGlobalMacroContext, fileSystem @*/
{
int doGlob;
@ -1819,7 +1867,6 @@ static int processPackageFiles(Spec spec, Package pkg,
fl.isSpecialDoc = 0;
fl.isDir = 0;
fl.inFtw = 0;
fl.currentFlags = 0;
fl.currentVerifyFlags = 0;
@ -1873,7 +1920,6 @@ static int processPackageFiles(Spec spec, Package pkg,
/* Reset for a new line in %files */
fl.isDir = 0;
fl.inFtw = 0;
fl.currentFlags = 0;
/* turn explicit flags into %def'd ones (gosh this is hacky...) */
fl.currentSpecdFlags = ((unsigned)fl.defSpecdFlags) >> 8;
@ -1940,7 +1986,6 @@ static int processPackageFiles(Spec spec, Package pkg,
/* Reset for %doc */
fl.isDir = 0;
fl.inFtw = 0;
fl.currentFlags = 0;
fl.currentVerifyFlags = 0;

View File

@ -1,247 +0,0 @@
/** \ingroup rpmbuild
* \file build/myftw.c
* Modified ftw() -- uses Lstat() instead of stat().
*/
/* Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ian Lance Taylor (ian@airs.com).
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include "system.h"
#include "rpmio.h"
#ifndef NAMLEN
#define NAMLEN(a) strlen((a)->d_name)
#endif
#if !defined(__LCLINT__)
#ifndef PATH_MAX
#ifdef _POSIX_VERSION
#define PATH_MAX _POSIX_PATH_MAX
#else
#ifdef MAXPATHLEN
#define PATH_MAX MAXPATHLEN
#else
#define PATH_MAX 1024
#endif
#endif
#endif
#endif /* !__LCLINT */
#include "myftw.h"
#include "debug.h"
/* Traverse one level of a directory tree. */
/**
*/
/*@-nullstate@*/
static int
myftw_dir (DIR **dirs, int level, int descriptors,
char *dir, size_t len,
myftwFunc func,
void *fl)
/*@globals errno, fileSystem @*/
/*@modifies *dirs, *dir, errno, fileSystem @*/
{
int got;
struct dirent *entry;
int d_namlen;
got = 0;
errno = 0;
while ((entry = Readdir (dirs[level])) != NULL)
{
struct stat s;
int flag, retval, newlev = 0;
++got;
if (entry->d_name[0] == '.'
&& (entry->d_name [1] == '\0' ||
(entry->d_name [2] == '\0' && entry->d_name[1] == '.')))
{
errno = 0;
continue;
}
d_namlen = NAMLEN(entry) + 1;
if (d_namlen + len > PATH_MAX)
{
#ifdef ENAMETOOLONG
errno = ENAMETOOLONG;
#else
errno = ENOMEM;
#endif
return -1;
}
dir[len] = '/';
memcpy ((void *) (dir + len + 1), (void *) entry->d_name, d_namlen);
if (Lstat (dir, &s) < 0)
{
/* Following POSIX.1 2.4 ENOENT is returned if the file cannot
* be stat'ed. This can happen for a file returned by Readdir
* if it's an unresolved symbolic link. This should be regarded
* as an forgivable error. -- Uli. */
if (errno != EACCES && errno != ENOENT)
return -1;
flag = MYFTW_NS;
}
else if (S_ISDIR (s.st_mode))
{
newlev = (level + 1) % descriptors;
/*@-unqualifiedtrans@*/
if (dirs[newlev] != NULL)
(void) Closedir (dirs[newlev]);
/*@=unqualifiedtrans@*/
dirs[newlev] = Opendir (dir);
if (dirs[newlev] != NULL)
flag = MYFTW_D;
else
{
if (errno != EACCES)
return -1;
flag = MYFTW_DNR;
}
}
else
flag = MYFTW_F;
retval = (*func) (fl, dir, &s);
if (flag == MYFTW_D)
{
if (retval == 0)
retval = myftw_dir (dirs, newlev, descriptors, dir,
d_namlen + len, func, fl);
if (dirs[newlev] != NULL)
{
int save;
save = errno;
(void) Closedir (dirs[newlev]);
errno = save;
dirs[newlev] = NULL;
}
}
if (retval != 0)
return retval;
if (dirs[level] == NULL)
{
int skip;
dir[len] = '\0';
dirs[level] = Opendir (dir);
if (dirs[level] == NULL)
return -1;
skip = got;
while (skip-- != 0)
{
errno = 0;
if (Readdir (dirs[level]) == NULL)
return errno == 0 ? 0 : -1;
}
}
errno = 0;
}
return errno == 0 ? 0 : -1;
}
/*@=nullstate@*/
/* Call a function on every element in a directory tree. */
int myftw (const char *dir,
int descriptors,
myftwFunc func,
void *fl)
{
DIR **dirs;
size_t len;
char buf[PATH_MAX + 1];
struct stat s;
int flag, retval;
int i;
if (descriptors <= 0)
descriptors = 1;
/*@access DIR@*/
dirs = (DIR **) alloca (descriptors * sizeof (*dirs));
i = descriptors;
while (i-- > 0)
dirs[i] = NULL;
if (Lstat (dir, &s) < 0)
{
/* Following POSIX.1 2.4 ENOENT is returned if the file cannot
* be stat'ed. This can happen for a file returned by Readdir
* if it's an unresolved symbolic link. This should be regarded
* as an forgivable error. -- Uli. */
if (errno != EACCES && errno != ENOENT)
return -1;
flag = MYFTW_NS;
}
else if (S_ISDIR (s.st_mode))
{
dirs[0] = Opendir (dir);
if (dirs[0] != NULL)
flag = MYFTW_D;
else
{
if (errno != EACCES)
return -1;
flag = MYFTW_DNR;
}
}
else
flag = MYFTW_F;
len = strlen (dir);
memcpy ((void *) buf, (void *) dir, len + 1);
retval = (*func) (fl, buf, &s);
if (flag == MYFTW_D)
{
if (retval == 0)
retval = myftw_dir (dirs, 0, descriptors, buf, len, func, fl);
if (dirs[0] != NULL)
{
int save;
save = errno;
(void) Closedir (dirs[0]);
/*@-mods@*/
errno = save;
/*@=mods@*/
}
}
return retval;
}

View File

@ -1,32 +0,0 @@
#ifndef _H_MYFTW_
#define _H_MYFTW_
/** \ingroup rpmbuild
* \file build/myftw.h
* Portable ftw(3) using lstat() instead of stat().
*/
#include <sys/stat.h>
/* The FLAG argument to the user function passed to ftw. */
#define MYFTW_F 0 /* Regular file. */
#define MYFTW_D 1 /* Directory. */
#define MYFTW_DNR 2 /* Unreadable directory. */
#define MYFTW_NS 3 /* Unstatable file. */
#ifdef __cplusplus
extern "C" {
#endif
typedef int (*myftwFunc) (void *fl, const char *name, struct stat *statp)
/*@*/;
int myftw (const char *dir, int descriptors, myftwFunc func, void *fl)
/*@globals fileSystem @*/
/*@modifies *fl, fileSystem @*/;
#ifdef __cplusplus
}
#endif
#endif /* _H_MYFTW_ */

View File

@ -9,7 +9,6 @@ build/build.c
build/expression.c
build/files.c
build/misc.c
build/myftw.c
build/names.c
build/pack.c
build/parseBuildInstallClean.c