/* * functions glob2 and glob3 are mutually recursive; there is one level * of recursion for each segment in the pattern that contains one or * more meta characters. */ static int glob2(struct strbuf *pathbuf, const Char *pattern, glob_t *pglob, int no_match) { struct stat sbuf; int anymeta; const Char *p; size_t orig_len; /* * loop over pattern segments until end of pattern or until segment with * meta character found. */ anymeta = 0; for (;;) { if (*pattern == EOS) { /* end of pattern? */ strbuf_terminate(pathbuf); if (Lstat(pathbuf->s, &sbuf)) return (0); if (((pglob->gl_flags & GLOB_MARK) && pathbuf->s[pathbuf->len - 1] != SEP) && (S_ISDIR(sbuf.st_mode) #ifdef S_IFLNK || (S_ISLNK(sbuf.st_mode) && (Stat(pathbuf->s, &sbuf) == 0) && S_ISDIR(sbuf.st_mode)) #endif )) { strbuf_append1(pathbuf, SEP); strbuf_terminate(pathbuf); } ++pglob->gl_matchc; globextend(pathbuf->s, pglob); return 0; } /* find end of next segment, tentatively copy to pathbuf */ p = pattern; orig_len = pathbuf->len; while (*p != EOS && *p != SEP) { if (ismeta(*p)) anymeta = 1; strbuf_append1(pathbuf, *p++); } if (!anymeta) { /* no expansion, do next segment */ pattern = p; while (*pattern == SEP) strbuf_append1(pathbuf, *pattern++); } else { /* need expansion, recurse */ pathbuf->len = orig_len; return (glob3(pathbuf, pattern, p, pattern, pglob, no_match)); } } /* NOTREACHED */ }
/* returns 0 if it could create lock; 1 if the lock exists; -1 on error */ int xiogetlock(const char *lockfile) { char *s; struct stat strat; int fd; pid_t pid; char pidbuf[3*sizeof(pid_t)+1]; size_t bytes; if (Lstat(lockfile, &strat) == 0) { return 1; } switch (errno) { case ENOENT: break; default: Error3("Lstat(\"%s\", %p): %s", lockfile, &strat, strerror(errno)); return -1; } /* in this moment, the file did not exist */ if ((s = Malloc(strlen(lockfile)+8)) == NULL) { errno = ENOMEM; return -1; } strcpy(s, lockfile); strcat(s, ".XXXXXX"); if ((fd = Mkstemp(s)) < 0) { Error2("mkstemp(\"%s\"): %s", s, strerror(errno)); return -1; } pid = Getpid(); bytes = sprintf(pidbuf, F_pid, pid); if (writefull(fd, pidbuf, bytes) < 0) { Error4("write(%d, %p, "F_Zu"): %s", fd, pidbuf, bytes, strerror(errno)); return -1; } Close(fd); /* Chmod(lockfile, 0600); */ if (Link(s, lockfile) < 0) { int _errno = errno; Error3("link(\"%s\", \"%s\"): %s", s, lockfile, strerror(errno)); Unlink(s); errno = _errno; return -1; } Unlink(s); return 0; }
/* analyse a file system entry, referred by file name */ int filan_file(const char *filename, FILE *outfile) { int fd = -1; int result; #if HAVE_STAT64 struct stat64 buf = {0}; #else struct stat buf = {0}; #endif /* !HAVE_STAT64 */ if (filan_followsymlinks) { #if HAVE_STAT64 result = Stat64(filename, &buf); #else result = Stat(filename, &buf); #endif /* !HAVE_STAT64 */ if (result < 0) { Warn3("stat(\"%s\", %p): %s", filename, &buf, strerror(errno)); } } else { #if HAVE_STAT64 result = Lstat64(filename, &buf); #else result = Lstat(filename, &buf); #endif /* !HAVE_STAT64 */ if (result < 0) { Warn3("lstat(\"%s\", %p): %s", filename, &buf, strerror(errno)); } } switch (buf.st_mode&S_IFMT) { #ifdef S_IFSOCK case S_IFSOCK: /* probably, it's useless to make a socket and describe it */ break; #endif /* S_IFSOCK */ default: if ((fd = Open(filename, O_RDONLY|O_NOCTTY|O_NONBLOCK #ifdef O_LARGEFILE |O_LARGEFILE #endif , 0700)) < 0) { Warn2("open(\"%s\", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE, 0700): %s", filename, strerror(errno)); } } result = filan_stat(&buf, fd, -1, outfile); fputc('\n', outfile); return result; }
/** * Check that file owner and group are known. * @param urlfn file url * @return RPMRC_OK on success */ static rpmRC checkOwners(const char * urlfn) /*@globals h_errno, fileSystem, internalState @*/ /*@modifies fileSystem, internalState @*/ { struct stat sb; if (Lstat(urlfn, &sb)) { rpmlog(RPMLOG_ERR, _("Bad source: %s: %s\n"), urlfn, strerror(errno)); return RPMRC_FAIL; } if (!getUname(sb.st_uid) || !getGname(sb.st_gid)) { rpmlog(RPMLOG_ERR, _("Bad owner/group: %s\n"), urlfn); return RPMRC_FAIL; } return RPMRC_OK; }
static int glob3(struct strbuf *pathbuf, const Char *pattern, const Char *restpattern, const Char *pglobstar, glob_t *pglob, int no_match) { DIR *dirp; struct dirent *dp; struct stat sbuf; int err; Char m_not = (pglob->gl_flags & GLOB_ALTNOT) ? M_ALTNOT : M_NOT; size_t orig_len; int globstar = 0; int chase_symlinks = 0; const Char *termstar = NULL; strbuf_terminate(pathbuf); orig_len = pathbuf->len; errno = err = 0; while (pglobstar < restpattern) { __Char wc; size_t width = One_Char_mbtowc(&wc, pglobstar, MB_LEN_MAX); if ((pglobstar[0] & M_MASK) == M_ALL && (pglobstar[width] & M_MASK) == M_ALL) { globstar = 1; chase_symlinks = (pglobstar[2 * width] & M_MASK) == M_ALL; termstar = pglobstar + (2 + chase_symlinks) * width; break; } pglobstar += width; } if (globstar) { err = pglobstar==pattern && termstar==restpattern ? *restpattern == EOS ? glob2(pathbuf, restpattern - 1, pglob, no_match) : glob2(pathbuf, restpattern + 1, pglob, no_match) : glob3(pathbuf, pattern, restpattern, termstar, pglob, no_match); if (err) return err; pathbuf->len = orig_len; strbuf_terminate(pathbuf); } if (*pathbuf->s && (Lstat(pathbuf->s, &sbuf) || !S_ISDIR(sbuf.st_mode) #ifdef S_IFLINK && ((globstar && !chase_symlinks) || !S_ISLNK(sbuf.st_mode)) #endif )) return 0; if (!(dirp = Opendir(pathbuf->s))) { /* todo: don't call for ENOENT or ENOTDIR? */ if ((pglob->gl_errfunc && (*pglob->gl_errfunc) (pathbuf->s, errno)) || (pglob->gl_flags & GLOB_ERR)) return (GLOB_ABEND); else return (0); } /* search directory for matching names */ while ((dp = readdir(dirp)) != NULL) { /* initial DOT must be matched literally */ if (dp->d_name[0] == DOT && *pattern != DOT) if (!(pglob->gl_flags & GLOB_DOT) || !dp->d_name[1] || (dp->d_name[1] == DOT && !dp->d_name[2])) continue; /*unless globdot and not . or .. */ pathbuf->len = orig_len; strbuf_append(pathbuf, dp->d_name); strbuf_terminate(pathbuf); if (globstar) { #ifdef S_IFLNK if (!chase_symlinks && (Lstat(pathbuf->s, &sbuf) || S_ISLNK(sbuf.st_mode))) continue; #endif if (match(pathbuf->s + orig_len, pattern, termstar, (int)m_not) == no_match) continue; strbuf_append1(pathbuf, SEP); strbuf_terminate(pathbuf); if ((err = glob2(pathbuf, pglobstar, pglob, no_match)) != 0) break; } else { if (match(pathbuf->s + orig_len, pattern, restpattern, (int) m_not) == no_match) continue; if ((err = glob2(pathbuf, restpattern, pglob, no_match)) != 0) break; } } /* todo: check error from readdir? */ closedir(dirp); return (err); }
/** \ingroup rpmcli * Verify file attributes (including file digest). * @param vf file data to verify * #param spew should verify results be printed? * @return 0 on success (or not installed), 1 on error */ static int rpmvfVerify(rpmvf vf, int spew) /*@globals h_errno, fileSystem, internalState @*/ /*@modifies vf, fileSystem, internalState @*/ { rpmVerifyAttrs res = RPMVERIFY_NONE; struct stat sb; int ec = 0; /* Check to see if the file was installed - if not pretend all is OK. */ switch (vf->fstate) { default: case RPMFILE_STATE_NETSHARED: case RPMFILE_STATE_REPLACED: case RPMFILE_STATE_NOTINSTALLED: case RPMFILE_STATE_WRONGCOLOR: goto exit; /*@notreached@*/ break; case RPMFILE_STATE_NORMAL: break; } assert(vf->fn != NULL); if (vf->fn == NULL || Lstat(vf->fn, &sb) != 0) { res |= RPMVERIFY_LSTATFAIL; ec = 1; goto exit; } /* Not all attributes of non-regular files can be verified. */ if (S_ISDIR(sb.st_mode)) vf->vflags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | RPMVERIFY_LINKTO | RPMVERIFY_HMAC); else if (S_ISLNK(sb.st_mode)) { vf->vflags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | RPMVERIFY_MODE | RPMVERIFY_HMAC); #if CHOWN_FOLLOWS_SYMLINK vf->vflags &= ~(RPMVERIFY_USER | RPMVERIFY_GROUP); #endif } else if (S_ISFIFO(sb.st_mode)) vf->vflags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | RPMVERIFY_LINKTO | RPMVERIFY_HMAC); else if (S_ISCHR(sb.st_mode)) vf->vflags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | RPMVERIFY_LINKTO | RPMVERIFY_HMAC); else if (S_ISBLK(sb.st_mode)) vf->vflags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | RPMVERIFY_LINKTO | RPMVERIFY_HMAC); else vf->vflags &= ~(RPMVERIFY_LINKTO); if (vf->vflags & (RPMVERIFY_FDIGEST | RPMVERIFY_HMAC)) { if (vf->digest == NULL || vf->dlen == 0) res |= RPMVERIFY_FDIGEST; else { /* XXX If --nofdigest, then prelinked library sizes fail to verify. */ unsigned char * fdigest = memset(alloca(vf->dlen), 0, vf->dlen); size_t fsize = 0; #define _mask (RPMVERIFY_FDIGEST|RPMVERIFY_HMAC) unsigned dflags = (vf->vflags & _mask) == RPMVERIFY_HMAC ? 0x2 : 0x0; #undef _mask int rc = dodigest(vf->dalgo, vf->fn, fdigest, dflags, &fsize); sb.st_size = fsize; if (rc) res |= (RPMVERIFY_READFAIL|RPMVERIFY_FDIGEST); else if (memcmp(fdigest, vf->digest, vf->dlen)) res |= RPMVERIFY_FDIGEST; } } if (vf->vflags & RPMVERIFY_LINKTO) { char linkto[1024+1]; int size = 0; if ((size = Readlink(vf->fn, linkto, sizeof(linkto)-1)) == -1) res |= (RPMVERIFY_READLINKFAIL|RPMVERIFY_LINKTO); else { linkto[size] = '\0'; if (vf->flink == NULL || strcmp(linkto, vf->flink)) res |= RPMVERIFY_LINKTO; } } if (vf->vflags & RPMVERIFY_FILESIZE) { if (sb.st_size != vf->sb.st_size) res |= RPMVERIFY_FILESIZE; } if (vf->vflags & RPMVERIFY_MODE) { /* XXX AIX has sizeof(mode_t) > sizeof(unsigned short) */ unsigned short metamode = (unsigned short)vf->sb.st_mode; unsigned short filemode = (unsigned short)sb.st_mode; /* Comparing type of %ghost files is meaningless, but perms are OK. */ if (vf->fflags & RPMFILE_GHOST) { metamode &= ~0xf000; filemode &= ~0xf000; } if (metamode != filemode) res |= RPMVERIFY_MODE; } if (vf->vflags & RPMVERIFY_RDEV) { if (S_ISCHR(vf->sb.st_mode) != S_ISCHR(sb.st_mode) || S_ISBLK(vf->sb.st_mode) != S_ISBLK(sb.st_mode)) res |= RPMVERIFY_RDEV; else if (S_ISDEV(vf->sb.st_mode) && S_ISDEV(sb.st_mode)) { rpmuint16_t st_rdev = (rpmuint16_t)(sb.st_rdev & 0xffff); rpmuint16_t frdev = (rpmuint16_t)(vf->sb.st_rdev & 0xffff); if (st_rdev != frdev) res |= RPMVERIFY_RDEV; } } if (vf->vflags & RPMVERIFY_MTIME) { if (sb.st_mtime != vf->sb.st_mtime) res |= RPMVERIFY_MTIME; } if (vf->vflags & RPMVERIFY_USER) { const char * fuser = uidToUname(sb.st_uid); if (fuser == NULL || vf->fuser == NULL || strcmp(fuser, vf->fuser)) res |= RPMVERIFY_USER; } if (vf->vflags & RPMVERIFY_GROUP) { const char * fgroup = gidToGname(sb.st_gid); if (fgroup == NULL || vf->fgroup == NULL || strcmp(fgroup, vf->fgroup)) res |= RPMVERIFY_GROUP; } exit: if (spew) { /* XXX no output w verify(...) probe. */ char buf[BUFSIZ]; char * t = buf; char * te = t; *te = '\0'; if (ec) { if (!(vf->fflags & (RPMFILE_MISSINGOK|RPMFILE_GHOST)) || rpmIsVerbose()) { sprintf(te, _("missing %c %s"), ((vf->fflags & RPMFILE_CONFIG) ? 'c' : (vf->fflags & RPMFILE_DOC) ? 'd' : (vf->fflags & RPMFILE_GHOST) ? 'g' : (vf->fflags & RPMFILE_LICENSE) ? 'l' : (vf->fflags & RPMFILE_PUBKEY) ? 'P' : (vf->fflags & RPMFILE_README) ? 'r' : ' '), vf->fn); if ((res & RPMVERIFY_LSTATFAIL) != 0 && errno != ENOENT) { te += strlen(te); sprintf(te, " (%s)", strerror(errno)); } } } else if (res || rpmIsVerbose()) { /*@observer@*/ static const char aok[] = "."; /*@observer@*/ static const char unknown[] = "?"; #define _verify(_RPMVERIFY_F, _C) \ ((res & _RPMVERIFY_F) ? _C : aok) #define _verifylink(_RPMVERIFY_F, _C) \ ((res & RPMVERIFY_READLINKFAIL) ? unknown : \ (res & _RPMVERIFY_F) ? _C : aok) #define _verifyfile(_RPMVERIFY_F, _C) \ ((res & RPMVERIFY_READFAIL) ? unknown : \ (res & _RPMVERIFY_F) ? _C : aok) const char * digest = _verifyfile(RPMVERIFY_FDIGEST, "5"); const char * size = _verify(RPMVERIFY_FILESIZE, "S"); const char * link = _verifylink(RPMVERIFY_LINKTO, "L"); const char * mtime = _verify(RPMVERIFY_MTIME, "T"); const char * rdev = _verify(RPMVERIFY_RDEV, "D"); const char * user = _verify(RPMVERIFY_USER, "U"); const char * group = _verify(RPMVERIFY_GROUP, "G"); const char * mode = _verify(RPMVERIFY_MODE, "M"); #undef _verifyfile #undef _verifylink #undef _verify sprintf(te, "%s%s%s%s%s%s%s%s %c %s", size, mode, digest, rdev, link, user, group, mtime, ((vf->fflags & RPMFILE_CONFIG) ? 'c' : (vf->fflags & RPMFILE_DOC) ? 'd' : (vf->fflags & RPMFILE_GHOST) ? 'g' : (vf->fflags & RPMFILE_LICENSE) ? 'l' : (vf->fflags & RPMFILE_PUBKEY) ? 'P' : (vf->fflags & RPMFILE_README) ? 'r' : ' '), vf->fn); } if (t && *t) rpmlog(RPMLOG_NOTICE, "%s\n", t); } return (res != 0); }
static int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3) { /* we expect the form: filename */ const char *name; xiosingle_t *xfd = &xxfd->stream; int pf = PF_UNIX; int socktype = SOCK_DGRAM; int protocol = 0; union sockaddr_union us; socklen_t uslen; bool tight = true; bool opt_unlink_early = false; bool opt_unlink_close = true; int result; if (argc != 2) { Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); return STAT_NORETRY; } name = argv[1]; retropt_socket_pf(opts, &pf); retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); uslen = xiosetunix(pf, &us.un, name, abstract, tight); #if 1 /*!!! why bind option? */ retropt_bind(opts, pf, socktype, protocol, &us.soa, &uslen, 1, 0, 0); #endif if (!(ABSTRACT && abstract)) { /* only for non abstract because abstract do not work in file system */ retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); if (opt_unlink_early) { if (Unlink(name) < 0) { if (errno == ENOENT) { Warn2("unlink(\"%s\"): %s", name, strerror(errno)); } else { Error2("unlink(\"%s\"): %s", name, strerror(errno)); } } } else { struct stat buf; if (Lstat(name, &buf) == 0) { Error1("\"%s\" exists", name); return STAT_RETRYLATER; } } if (opt_unlink_close) { if ((xfd->unlink_close = strdup(name)) == NULL) { Error1("strdup(\"%s\"): out of memory", name); } xfd->opt_unlink_close = true; } } applyopts_named(name, opts, PH_EARLY); /* umask! */ xfd->para.socket.la.soa.sa_family = pf; xfd->dtype = XIODATA_RECV; result = _xioopen_dgram_recv(xfd, xioflags, &us.soa, uslen, opts, pf, socktype, protocol, E_ERROR); return result; }
static int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3) { /* we expect the form: filename */ const char *name; xiosingle_t *xfd = &xxfd->stream; int pf = PF_UNIX; int socktype = SOCK_DGRAM; int protocol = 0; struct sockaddr_un us; socklen_t uslen; bool tight = true; bool needbind = true; bool opt_unlink_early = false; bool opt_unlink_close = true; if (argc != 2) { Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); return STAT_NORETRY; } name = argv[1]; retropt_socket_pf(opts, &pf); retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); uslen = xiosetunix(pf, &us, name, abstract, tight); xfd->howtoend = END_NONE; retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen, 1, 0, 0); if (!(ABSTRACT && abstract)) { /* only for non abstract because abstract do not work in file system */ retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); } if (!(ABSTRACT && abstract)) { if (opt_unlink_early) { if (Unlink(name) < 0) { if (errno == ENOENT) { Warn2("unlink(\"%s\"): %s", name, strerror(errno)); } else { Error2("unlink(\"%s\"): %s", name, strerror(errno)); } } } else { struct stat buf; if (Lstat(name, &buf) == 0) { Error1("\"%s\" exists", name); return STAT_RETRYLATER; } } if (opt_unlink_close) { if ((xfd->unlink_close = strdup(name)) == NULL) { Error1("strdup(\"%s\"): out of memory", name); } xfd->opt_unlink_close = true; } /* trying to set user-early, perm-early etc. here is useless because file system entry is available only past bind() call. */ } applyopts_named(name, opts, PH_EARLY); /* umask! */ xfd->para.socket.la.soa.sa_family = pf; xfd->dtype = XIODATA_RECVFROM_ONE; /* this may fork */ return _xioopen_dgram_recvfrom(xfd, xioflags, needbind?(struct sockaddr *)&us:NULL, uslen, opts, pf, socktype, protocol, E_ERROR); }
static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3) { /* we expect the form: filename */ const char *name; xiosingle_t *xfd = &xxfd->stream; int pf = PF_UNIX; int socktype = SOCK_STREAM; int protocol = 0; struct sockaddr_un us; socklen_t uslen; bool tight = true; struct opt *opts0 = NULL; pid_t pid = Getpid(); bool opt_unlink_early = false; bool opt_unlink_close = true; int result; if (argc != 2) { Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); return STAT_NORETRY; } name = argv[1]; retropt_socket_pf(opts, &pf); retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); uslen = xiosetunix(pf, &us, name, abstract, tight); xfd->howtoend = END_SHUTDOWN; if (!(ABSTRACT && abstract)) { /* only for non abstract because abstract do not work in file system */ retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); } if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; applyopts(-1, opts, PH_INIT); applyopts_named(name, opts, PH_EARLY); /* umask! */ applyopts(-1, opts, PH_EARLY); if (!(ABSTRACT && abstract)) { if (opt_unlink_early) { if (Unlink(name) < 0) { if (errno == ENOENT) { Warn2("unlink(\"%s\"): %s", name, strerror(errno)); } else { Error2("unlink(\"%s\"): %s", name, strerror(errno)); } } } else { struct stat buf; if (Lstat(name, &buf) == 0) { Error1("\"%s\" exists", name); return STAT_RETRYLATER; } } if (opt_unlink_close) { if ((xfd->unlink_close = strdup(name)) == NULL) { Error1("strdup(\"%s\"): out of memory", name); } xfd->opt_unlink_close = true; } /* trying to set user-early, perm-early etc. here is useless because file system entry is available only past bind() call. */ } opts0 = copyopts(opts, GROUP_ALL); /* this may fork() */ if ((result = xioopen_listen(xfd, xioflags, (struct sockaddr *)&us, uslen, opts, opts0, pf, socktype, protocol)) != 0) return result; if (!(ABSTRACT && abstract)) { if (opt_unlink_close) { if (pid != Getpid()) { /* in a child process - do not unlink-close here! */ xfd->opt_unlink_close = false; } } } return 0; }
static int FtwTraverse(const FtwInfoPtr ftwip, size_t dirPathLen, int depth) { DIR *DIRp; char *cp; size_t fnLen; struct dirent *dentp; mode_t m; char *filename; char *newBuf; char *path = ftwip->curPath; int nSubdirs; FtwSubDirListPtr head = NULL, tail = NULL, sdp, nextsdp; int rc = (-1); int isRootDir; isRootDir = ((dirPathLen == 1) && (IsLocalPathDelim(path[0]))) ? 1 : 0; if ((DIRp = opendir(dirPathLen ? path : ".")) == NULL) { /* Not an error unless the first directory could not be opened. */ return (0); } nSubdirs = 0; ++ftwip->numDirs; ftwip->depth = depth; if (ftwip->maxDepth < ftwip->depth) { ftwip->maxDepth = ftwip->depth; } filename = path + dirPathLen; if (isRootDir == 0) /* Root directory is a separator. */ { *filename++ = (char) ftwip->dirSeparator; dirPathLen++; } *filename = '\0'; /* Path now contains dir/ */ dentp = (struct dirent *) ftwip->direntbuf; for (;;) { if (Readdir(DIRp, dentp, ftwip->direntbufSize) == NULL) break; cp = dentp->d_name; if ((cp[0] == '.') && ((cp[1] == '\0') || ((cp[1] == '.') && (cp[2] == '\0')))) continue; /* Skip . and .. */ *filename = '\0'; fnLen = strlen(cp) + 1 /* include \0 */; if ((fnLen + dirPathLen) > ftwip->curPathAllocSize) { if (ftwip->autoGrow == kFtwNoAutoGrowAndFail) { goto panic; } else if (ftwip->autoGrow == kFtwNoAutoGrowButContinue) { continue; } newBuf = (char *) realloc(ftwip->curPath, fnLen + dirPathLen + 30 + 2 /* room for / and \0 */); if (newBuf == NULL) goto panic; ftwip->curPath = newBuf; ftwip->curPathAllocSize = fnLen + dirPathLen + 30; path = ftwip->curPath; filename = path + dirPathLen; if (isRootDir == 0) /* Root directory is a separator. */ *filename++ = (char) ftwip->dirSeparator; *filename = '\0'; } memcpy(filename, cp, fnLen); ftwip->curPathLen = dirPathLen + fnLen - 1; ftwip->curFile = filename; ftwip->curFileLen = fnLen - 1; if (Lstat(path, &ftwip->curStat) == 0) { m = ftwip->curStat.st_mode; if (S_ISREG(m)) { ++ftwip->numFiles; ftwip->curType = '-'; if ((*ftwip->proc)(ftwip) < 0) { goto panic; } #ifdef S_ISLNK } else if (S_ISLNK(m)) { ftwip->curType = 'l'; ++ftwip->numLinks; if ((*ftwip->proc)(ftwip) < 0) { goto panic; } #endif /* S_ISLNK */ } else if (S_ISDIR(m)) { /* We delay entering the subdirectories * until we have closed this directory. * This will conserve file descriptors * and also have the effect of having * the files processed first. */ sdp = (FtwSubDirListPtr) malloc(sizeof(FtwSubDirList) + fnLen); if (sdp == NULL) goto panic; memcpy(&sdp->st, &ftwip->curStat, sizeof(sdp->st)); memcpy(sdp->name, cp, fnLen); sdp->fnLen = fnLen; sdp->next = NULL; if (head == NULL) { head = tail = sdp; } else { tail->next = sdp; tail = sdp; } nSubdirs++; } } } (void) closedir(DIRp); DIRp = NULL; /* Now enter each subdirectory. */ for (sdp = head; sdp != NULL; sdp = nextsdp) { nextsdp = sdp->next; memcpy(&ftwip->curStat, &sdp->st, sizeof(ftwip->curStat)); fnLen = sdp->fnLen; memcpy(filename, sdp->name, fnLen); ftwip->curPathLen = dirPathLen + fnLen - 1; ftwip->curFile = filename; ftwip->curFileLen = fnLen - 1; head = nextsdp; free(sdp); ftwip->curType = 'd'; if ((*ftwip->proc)(ftwip) < 0) { goto panic; } if (FtwTraverse(ftwip, dirPathLen + fnLen - 1, depth + 1) < 0) goto panic; /* Reset these, since buffer could have * been reallocated. */ path = ftwip->curPath; filename = path + dirPathLen; *filename = '\0'; } head = NULL; rc = 0; panic: if (DIRp != NULL) (void) closedir(DIRp); for (sdp = head; sdp != NULL; sdp = nextsdp) { nextsdp = sdp->next; free(sdp); } return (rc); } /* FtwTraverse */
/** * Check that all sources/patches/icons exist locally, fetching if necessary. */ static int prepFetch(Spec spec) /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/ { #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */ const char *Smacro; #endif const char *Lmacro, *Lurlfn = NULL; const char *Rmacro, *Rurlfn = NULL; struct Source *sp; struct stat st; rpmRC rpmrc; int ec, rc; char *cp; /* XXX insure that %{_sourcedir} exists */ rpmrc = RPMRC_OK; Lurlfn = rpmGenPath(NULL, "%{?_sourcedir}", NULL); if (Lurlfn != NULL && *Lurlfn != '\0') rpmrc = rpmMkdirPath(Lurlfn, "_sourcedir"); Lurlfn = _free(Lurlfn); if (rpmrc != RPMRC_OK) return -1; /* XXX insure that %{_patchdir} exists */ rpmrc = RPMRC_OK; Lurlfn = rpmGenPath(NULL, "%{?_patchdir}", NULL); if (Lurlfn != NULL && *Lurlfn != '\0') rpmrc = rpmMkdirPath(Lurlfn, "_patchdir"); Lurlfn = _free(Lurlfn); if (rpmrc != RPMRC_OK) return -1; /* XXX insure that %{_icondir} exists */ rpmrc = RPMRC_OK; Lurlfn = rpmGenPath(NULL, "%{?_icondir}", NULL); if (Lurlfn != NULL && *Lurlfn != '\0') rpmrc = rpmMkdirPath(Lurlfn, "_icondir"); Lurlfn = _free(Lurlfn); if (rpmrc != RPMRC_OK) return -1; if (rpmIsVerbose() && !quietly && (rpmBTArgs.buildAmount & RPMBUILD_FETCHSOURCE)) rpmlog(RPMLOG_NOTICE, "Checking source and patch file(s):\n"); ec = 0; for (sp = spec->sources; sp != NULL; sp = sp->next) { #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */ Smacro = "%{?_specdir}/"; #endif #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */ if (! (Lmacro = getSourceDir(sp->flags, sp->source))) #else if (! (Lmacro = getSourceDir(sp->flags))) #endif continue; if (sp->flags & RPMFILE_SOURCE) { Rmacro = "%{?_Rsourcedir}/"; } else if (sp->flags & RPMFILE_PATCH) { Rmacro = "%{?_Rpatchdir}/"; } else if (sp->flags & RPMFILE_ICON) { Rmacro = "%{?_Ricondir}/"; } else continue; #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */ /* support splitted source directories, i.e., source files which are alternatively placed into the .spec directory and picked up from there, too. */ Lurlfn = rpmGenPath(NULL, Smacro, sp->source); rc = Lstat(Lurlfn, &st); if (rc == 0) { prepFetchVerbose(sp, &st); goto bottom; } #endif Lurlfn = rpmGenPath(NULL, Lmacro, sp->source); rc = Lstat(Lurlfn, &st); if (rc == 0) { /*@-noeffect@*/ prepFetchVerbose(sp, &st); /*@=noeffect@*/ goto bottom; } /*@-noeffect@*/ prepFetchVerbose(sp, NULL); /*@=noeffect@*/ if (errno != ENOENT) { ec++; rpmlog(RPMLOG_ERR, _("Missing %s%d %s: %s\n"), ((sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch"), sp->num, sp->source, strerror(ENOENT)); goto bottom; } /* try to fetch via macro-controlled remote locations */ cp = rpmExpand(Rmacro, NULL); if (cp != NULL && strcmp(cp, "/") != 0) { cp = _free(cp); Rurlfn = rpmGenPath(NULL, Rmacro, sp->source); if (!(Rurlfn == NULL || Rurlfn[0] == '\0' || !strcmp(Rurlfn, "/") || !strcmp(Lurlfn, Rurlfn))) { rpmlog(RPMLOG_NOTICE, _("Fetching(%s%d): %s\n"), (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, Rurlfn); rc = urlGetFile(Rurlfn, Lurlfn); if (rc == 0) goto bottom; else { rpmlog(RPMLOG_ERR, _("Fetching %s%d failed: %s\n"), (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, ftpStrerror(rc)); ec++; } } } cp = _free(cp); /* try to fetch from original location */ rpmlog(RPMLOG_NOTICE, _("Fetching(%s%d): %s\n"), (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, sp->fullSource); rc = urlGetFile(sp->fullSource, Lurlfn); if (rc == 0) goto bottom; else { rpmlog(RPMLOG_ERR, _("Fetching %s%d failed: %s\n"), (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, ftpStrerror(rc)); ec++; } rpmlog(RPMLOG_ERR, _("Missing %s%d: %s: %s\n"), ((sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch"), sp->num, sp->source, strerror(ENOENT)); ec++; bottom: Lurlfn = _free(Lurlfn); Rurlfn = _free(Rurlfn); } return ec; }