RPM Package Manager, CVS Repository
  http://rpm5.org/cvs/
  ____________________________________________________________________________

  Server: rpm5.org                         Name:   Jeff Johnson
  Root:   /v/rpm/cvs                       Email:  j...@rpm5.org
  Module: rpm                              Date:   12-Sep-2014 06:38:48
  Branch: rpm-5_4                          Handle: 2014091204384600

  Added files:              (Branch: rpm-5_4)
    rpm/rpmio               rpmct.c rpmct.h

  Log:
    - rpmct: orphans.

  Summary:
    Revision    Changes     Path
    1.1.2.1     +1028 -0    rpm/rpmio/rpmct.c
    1.1.2.1     +145 -0     rpm/rpmio/rpmct.h
  ____________________________________________________________________________

  patch -p0 <<'@@ .'
  Index: rpm/rpmio/rpmct.c
  ============================================================================
  $ cvs diff -u -r0 -r1.1.2.1 rpmct.c
  --- /dev/null 2014-09-12 06:36:27.000000000 +0200
  +++ rpmct.c   2014-09-12 06:38:47.697067680 +0200
  @@ -0,0 +1,1028 @@
  +/*-
  + * Copyright (c) 1988, 1993, 1994
  + *   The Regents of the University of California.  All rights reserved.
  + *
  + * This code is derived from software contributed to Berkeley by
  + * David Hitz of Auspex Systems Inc.
  + *
  + * Redistribution and use in source and binary forms, with or without
  + * modification, are permitted provided that the following conditions
  + * are met:
  + * 1. Redistributions of source code must retain the above copyright
  + *    notice, this list of conditions and the following disclaimer.
  + * 2. Redistributions in binary form must reproduce the above copyright
  + *    notice, this list of conditions and the following disclaimer in the
  + *    documentation and/or other materials provided with the distribution.
  + * 4. Neither the name of the University nor the names of its contributors
  + *    may be used to endorse or promote products derived from this software
  + *    without specific prior written permission.
  + *
  + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  + * SUCH DAMAGE.
  + */
  +
  +#include "system.h"
  +
  +#include <rpmio.h>
  +#include <rpmacl.h>
  +#include <rpmlog.h>
  +#include <poptIO.h>
  +
  +#define      _RPMCT_INTERNAL
  +#include <rpmct.h>
  +
  +#include "debug.h"
  +
  +/*@unchecked@*/
  +int _rpmct_debug;
  +#define      SPEW(_list)     if (_rpmct_debug) fprintf _list
  +
  +#if !defined(MIN)    /* XXX OpenIndiana needs */
  +#define      MIN(a,b) (((a)<(b))?(a):(b))
  +#endif
  +
  +/* Memory strategy threshold, in pages: if physmem is larger then this, use 
a 
  + * large buffer */
  +#define PHYSPAGES_THRESHOLD (32*1024)
  +
  +/* Maximum buffer size in bytes - do not allow it to grow larger than this */
  +#define BUFSIZE_MAX (2*1024*1024)
  +
  +/* Small (default) buffer size in bytes. It's inefficient for this to be
  + * smaller than MAXPHYS */
  +#define BUFSIZE_SMALL (MAXPHYS)
  +
  +/*==============================================================*/
  +
  +#define CP_ISSET(_FLAG) ((ct->flags & ((COPY_FLAGS_##_FLAG) & ~0x40000000)) 
!= COPY_FLAGS_NONE)
  +
  +#if defined(SIGINFO)
  +static volatile sig_atomic_t info;
  +
  +static void
  +siginfo(int sig __attribute__((__unused__)))
  +{
  +    info = 1;
  +}
  +
  +#define      cp_pct(x, y)    ((y == 0) ? 0 : (int)(100.0 * (x) / (y)))
  +
  +static sig_atomic_t rpmctProgress(rpmct ct, size_t current, size_t total)
  +{
  +    fprintf(stderr, "%s -> %s %3d%%\n",
  +         ct->p->fts_path, ct->npath,
  +         cp_pct(current, total));
  +    return (sig_atomic_t)0;
  +}
  +#endif
  +
  +/*==============================================================*/
  +
  +static rpmRC
  +rpmctioUnlink(rpmct ct)
  +{
  +    if (Unlink(ct->npath)) {
  +     rpmlog(RPMLOG_ERR, "Unlink: %s: %s\n", ct->npath, strerror(errno));
  +     return RPMRC_FAIL;
  +    }
  +    return RPMRC_OK;
  +}
  +
  +static rpmRC
  +rpmctioReadlink(rpmct ct, char * b, size_t nb)
  +{
  +    int len;
  +
  +    if ((len = Readlink(ct->p->fts_path, b, nb - 1)) == -1) {
  +     rpmlog(RPMLOG_ERR, "Readlink: %s: %s\n", ct->p->fts_path, 
strerror(errno));
  +     return RPMRC_FAIL;
  +    }
  +    b[len] = '\0';
  +    return RPMRC_OK;
  +}
  +
  +static rpmRC
  +rpmctioSymlink(rpmct ct, char * opath)
  +{
  +    if (Symlink(opath, ct->npath)) {
  +     rpmlog(RPMLOG_ERR, "Symlink: %s: %s\n", opath, strerror(errno));
  +     return RPMRC_FAIL;
  +    }
  +    return RPMRC_OK;
  +}
  +
  +static rpmRC
  +rpmctioMkfifo(rpmct ct, struct stat * st)
  +{
  +    if (Mkfifo(ct->npath, st->st_mode)) {
  +     rpmlog(RPMLOG_ERR, "Mkfifo: %s: %s\n", ct->npath, strerror(errno));
  +     return RPMRC_FAIL;
  +    }
  +    return RPMRC_OK;
  +}
  +
  +static rpmRC
  +rpmctioMknod(rpmct ct, struct stat * st)
  +{
  +    if (Mknod(ct->npath, st->st_mode, st->st_rdev)) {
  +     rpmlog(RPMLOG_ERR, "Mknod: %s: %s\n", ct->npath, strerror(errno));
  +     return RPMRC_FAIL;
  +    }
  +    return RPMRC_OK;
  +}
  +
  +static rpmRC
  +rpmctSetFile(rpmct ct, FD_t fd)
  +{
  +    struct stat * st = ct->p->fts_statp;
  +    struct stat ts;
  +    rpmRC rval = RPMRC_OK;
  +    int fdno = (fd ? Fileno(fd) : -1);
  +    int fdval = fdno >= 0;
  +    int islink = !fdval && S_ISLNK(st->st_mode);
  +    int gotstat;
  +
  +    st->st_mode &= S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO;
  +
  +    TIMESPEC_TO_TIMEVAL(&ct->tv[0], &st->st_atimespec);
  +    TIMESPEC_TO_TIMEVAL(&ct->tv[1], &st->st_mtimespec);
  +    if (islink ? Lutimes(ct->npath, ct->tv) : Utimes(ct->npath, ct->tv)) {
  +     rpmlog(RPMLOG_ERR, "%stimes: %s: %s\n", islink ? "lu" : "U", ct->npath, 
strerror(errno));
  +     rval = RPMRC_FAIL;
  +    }
  +    if (fdval ? Fstat(fd, &ts) :
  +     (islink ? Lstat(ct->npath, &ts) : Stat(ct->npath, &ts)))
  +         gotstat = 0;
  +    else {
  +     gotstat = 1;
  +     ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO;
  +    }
  +
  +    /*
  +    * Changing the ownership probably won't succeed, unless we're root
  +    * or POSIX_CHOWN_RESTRICTED is not set.  Set uid/gid before setting
  +    * the mode; current BSD behavior is to remove all setuid bits on
  +    * chown.  If chown fails, lose setuid/setgid bits.
  +    */
  +    if (!gotstat || st->st_uid != ts.st_uid || st->st_gid != ts.st_gid)
  +     if (fdval ? Fchown(fd, st->st_uid, st->st_gid) :
  +        (islink ? Lchown(ct->npath, st->st_uid, st->st_gid) :
  +        Chown(ct->npath, st->st_uid, st->st_gid)))
  +     {
  +         if (errno != EPERM) {
  +             rpmlog(RPMLOG_ERR, "Chown: %s: %s\n", ct->npath, 
strerror(errno));
  +             rval = RPMRC_FAIL;
  +         }
  +         st->st_mode &= ~(S_ISUID | S_ISGID);
  +     }
  +
  +    if (!gotstat || st->st_mode != ts.st_mode)
  +     if (fdval ? Fchmod(fd, st->st_mode) :
  +        (islink ? Lchmod(ct->npath, st->st_mode) :
  +        Chmod(ct->npath, st->st_mode)))
  +     {
  +         rpmlog(RPMLOG_ERR, "Chmod: %s: %s\n", ct->npath, strerror(errno));
  +         rval = RPMRC_FAIL;
  +     }
  +
  +#if defined(HAVE_STRUCT_STAT_ST_FLAGS)
  +    if (!gotstat || st->st_flags != ts.st_flags)
  +     if (fdval ?  Fchflags(fd, st->st_flags) :
  +        (islink ? Lchflags(ct->npath, st->st_flags) :
  +        Chflags(ct->npath, st->st_flags)))
  +     {
  +         rpmlog(RPMLOG_ERR, "Chflags: %s: %s\n", ct->npath, strerror(errno));
  +         rval = RPMRC_FAIL;
  +     }
  +#endif
  +
  +    return rval;
  +}
  +
  +static rpmRC
  +rpmctCopyFile(rpmct ct, int dne)
  +{
  +    struct stat * st = ct->p->fts_statp;
  +    ssize_t wcount;
  +    size_t wresid;
  +    off_t wtotal;
  +    int ch;
  +    int checkch;
  +    FD_t ifd = NULL;
  +    size_t rcount;
  +    rpmRC rval;
  +    FD_t ofd = NULL;
  +    char * bufp;
  +#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
  +    char *p;
  +#endif
  +
  +    ifd = Fopen(ct->p->fts_path, "r.ufdio");
  +    if (ifd == NULL || Ferror(ifd)) {
  +     if (ifd) (void) Fclose(ifd);
  +     rpmlog(RPMLOG_ERR, "Fopen: %s: %s\n", ct->p->fts_path, strerror(errno));
  +     return RPMRC_FAIL;
  +    }
  +
  +    /*
  +     * If the file exists and we're interactive, verify with the user.
  +     * If the file DNE, set the mode to be the from file, minus setuid
  +     * bits, modified by the umask; arguably wrong, but it makes copying
  +     * executables work right and it's been that way forever.  (The
  +     * other choice is 666 or'ed with the execute bits on the from file
  +     * modified by the umask.)
  +     */
  +    if (!dne) {
  +#define YESNO "(y/n [n]) "
  +     if (CP_ISSET(NOCLOBBER)) {
  +         if (rpmIsVerbose())
  +             rpmlog(RPMLOG_INFO, "%s not overwritten\n", ct->npath);
  +         (void) Fclose(ifd);
  +         return RPMRC_OK;
  +     } else if (CP_ISSET(INTERACTIVE)) {
  +         (void)fprintf(stderr, "overwrite %s? %s", ct->npath, YESNO);
  +         checkch = ch = getchar();
  +         while (ch != '\n' && ch != EOF)
  +             ch = getchar();
  +         if (checkch != 'y' && checkch != 'Y') {
  +             (void) Fclose(ifd);
  +             (void)fprintf(stderr, "not overwritten\n");
  +             return RPMRC_FAIL;
  +         }
  +     }
  +
  +     if (CP_ISSET(FORCE)) {
  +         /* remove existing destination file name, 
  +          * create a new file  */
  +         (void)Unlink(ct->npath);
  +         if (!CP_ISSET(HARDLINK))
  +             ofd = Fopen(ct->npath, "wb");
  +     } else {
  +         if (!CP_ISSET(HARDLINK))
  +             /* overwrite existing destination file name */
  +             ofd = Fopen(ct->npath, "wb");
  +     }
  +    } else {
  +     if (!CP_ISSET(HARDLINK))
  +         ofd = Fopen(ct->npath, "wb");
  +    }
  +     
  +    if (ofd == NULL || Ferror(ofd)
  +     || Fchmod(ofd, st->st_mode & ~(S_ISUID | S_ISGID)))
  +    {
  +     rpmlog(RPMLOG_ERR, "Fchmod: %s: %s\n", ct->npath, strerror(errno));
  +     if (ofd) (void) Fclose(ofd);
  +     (void) Fclose(ifd);
  +     return RPMRC_FAIL;
  +    }
  +
  +    rval = RPMRC_OK;
  +
  +    if (!CP_ISSET(HARDLINK)) {
  +     /*
  +      * Mmap and write if less than 8M (the limit is so we don't totally
  +      * trash memory on big files.  This is really a minor hack, but it
  +      * wins some CPU back.
  +      * Some filesystems, such as smbnetfs, don't support mmap,
  +      * so this is a best-effort attempt.
  +      */
  +#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
  +     if (S_ISREG(st->st_mode) && st->st_size > 0
  +      && st->st_size <= 8 * 1024 * 1024
  +      && (p = Mmap(NULL, (size_t)st->st_size, PROT_READ,
  +                 MAP_SHARED, Fileno(ifd), (off_t)0)) != MAP_FAILED)
  +     {
  +         wtotal = 0;
  +         for (bufp = p, wresid = st->st_size; ;
  +             bufp += wcount, wresid -= (size_t)wcount)
  +         {
  +             wcount = Fwrite(bufp, 1, wresid, ofd);
  +             if (Ferror(ofd) || wcount <= 0)
  +                 break;
  +             wtotal += wcount;
  +#if defined(SIGINFO)
  +             if (info)
  +                 info = rpmctProgress(ct, wtotal, st->st_size);
  +#endif
  +             if (wcount >= (ssize_t)wresid)
  +                 break;
  +         }
  +         if (wcount != (ssize_t)wresid) {
  +             rpmlog(RPMLOG_ERR, "Fwrite: %s: %s\n", ct->npath, 
strerror(errno));
  +             rval = RPMRC_FAIL;
  +         }
  +         /* Some systems don't unmap on close(2). */
  +         if (Munmap(p, st->st_size) < 0) {
  +             rpmlog(RPMLOG_ERR, "Munmap: %s: %s\n", ct->p->fts_path, 
strerror(errno));
  +             rval = RPMRC_FAIL;
  +         }
  +     } else
  +#endif
  +     {
  +         if (ct->b == NULL) {
  +             ct->b = xmalloc(ct->ballocated);
  +             ct->blen = ct->ballocated;
  +         }
  +         wtotal = 0;
  +         while ((rcount = Fread(ct->b, 1, ct->blen, ifd)) > 0 && 
!Ferror(ifd)) {
  +             for (bufp = ct->b, wresid = rcount; ;
  +                     bufp += wcount, wresid -= wcount)
  +             {
  +                 wcount = Fwrite(bufp, 1, wresid, ofd);
  +                 if (Ferror(ofd) || wcount <= 0)
  +                     break;
  +                 wtotal += wcount;
  +#if defined(SIGINFO)
  +                 if (info)
  +                     info = rpmctProgress(ct, wtotal, st->st_size);
  +#endif
  +                 if (wcount >= (ssize_t)wresid)
  +                     break;
  +             }
  +             if (wcount != (ssize_t)wresid) {
  +                 rpmlog(RPMLOG_ERR, "Fwrite: %s: %s\n", ct->npath, 
strerror(errno));
  +                 rval = RPMRC_FAIL;
  +                 break;
  +             }
  +         }
  +         if (Ferror(ifd)) {
  +             rpmlog(RPMLOG_ERR, "Fread: %s: %s\n", ct->p->fts_path, 
strerror(errno));
  +             rval = RPMRC_FAIL;
  +         }
  +     }
  +    } else {
  +     if (Link(ct->p->fts_path, ct->npath)) {
  +         rpmlog(RPMLOG_ERR, "Link: %s: %s\n", ct->npath, strerror(errno));
  +         rval = RPMRC_FAIL;
  +     }
  +    }
  +     
  +    /*
  +     * Don't remove the target even after an error.  The target might
  +     * not be a regular file, or its attributes might be important,
  +     * or its contents might be irreplaceable.  It would only be safe
  +     * to remove it if we created it and its length is 0.
  +     */
  +
  +    if (!CP_ISSET(HARDLINK)) {
  +     if (CP_ISSET(PRESERVE) && rpmctSetFile(ct, ofd))
  +         rval = RPMRC_FAIL;
  +     if (CP_ISSET(PRESERVE) && rpmaclCopyFd(ifd, ofd) != 0)
  +         rval = RPMRC_FAIL;
  +     if (ofd && Fclose(ofd)) {
  +         rpmlog(RPMLOG_ERR, "Fclose: %s: %s\n", ct->npath, strerror(errno));
  +         rval = RPMRC_FAIL;
  +     }
  +    }
  +
  +    (void) Fclose(ifd);
  +
  +    return rval;
  +}
  +
  +/*
  + * mastercmp --
  + *   The comparison function for the copy order.  The order is to copy
  + *   non-directory files before directory files.  The reason for this
  + *   is because files tend to be in the same cylinder group as their
  + *   parent directory, whereas directories tend not to be.  Copying the
  + *   files first reduces seeking.
  + */
  +static int
  +mastercmp(const FTSENT ** a, const FTSENT ** b)
  +{
  +    int a_info = (*a)->fts_info;
  +    int b_info = (*b)->fts_info;
  +
  +    if (a_info == FTS_ERR || a_info == FTS_NS || a_info == FTS_DNR)
  +     return 0;
  +    if (b_info == FTS_ERR || b_info == FTS_NS || b_info == FTS_DNR)
  +     return 0;
  +    if (a_info == FTS_D)
  +     return -1;
  +    if (b_info == FTS_D)
  +     return 1;
  +    return 0;
  +}
  +
  +rpmRC
  +rpmctCopy(rpmct ct)
  +{
  +    int base = 0;
  +    int dne;
  +    int badcp = 0;
  +    rpmRC rval = RPMRC_OK;
  +    size_t nlen;
  +    char *p;
  +    char *target_mid;
  +    mode_t mask;
  +    mode_t mode;
  +
  +    if (ct == NULL) {
  +     rval = RPMRC_FAIL;
  +     goto exit;
  +    }
  +    /*
  +     * Keep an inverted copy of the umask, for use in correcting
  +     * permissions on created directories when not using -p.
  +     */
  +    mask = ~umask(0777);
  +    umask(~mask);
  +
  +    if ((ct->t = Fts_open((char *const *)ct->av, ct->ftsoptions, mastercmp)) 
== NULL) {
  +     rpmlog(RPMLOG_ERR, "Fts_open: %s\n", strerror(errno));
  +     rval = RPMRC_FAIL;
  +     goto exit;
  +    }
  +    while ((ct->p = Fts_read(ct->t)) != NULL) {
  +     switch (ct->p->fts_info) {
  +     case FTS_NS:
  +     case FTS_DNR:
  +     case FTS_ERR:
  +         rpmlog(RPMLOG_ERR, "Fts_read: %s: %s\n", ct->p->fts_path, 
strerror(ct->p->fts_errno));
  +         rval = RPMRC_FAIL;
  +         continue;
  +     case FTS_DC:                    /* Warn, continue. */
  +         rpmlog(RPMLOG_ERR, "Fts_read: %s: directory causes a cycle\n", 
ct->p->fts_path);
  +         rval = RPMRC_FAIL;
  +         continue;
  +     default:
  +         ;
  +     }
  +
  +     /*
  +      * If we are in case (2) or (3) above, we need to append the
  +      * source name to the target name.
  +      */
  +     if (ct->type != FILE_TO_FILE) {
  +         /*
  +          * Need to remember the roots of traversals to create
  +          * correct pathnames.  If there's a directory being
  +          * copied to a non-existent directory, e.g.
  +          *  cp -R a/dir noexist
  +          * the resulting path name should be noexist/foo, not
  +          * noexist/dir/foo (where foo is a file in dir), which
  +          * is the case where the target exists.
  +          *
  +          * Also, check for "..".  This is for correct path
  +          * concatenation for paths ending in "..", e.g.
  +          *  cp -R .. /tmp
  +          * Paths ending in ".." are changed to ".".  This is
  +          * tricky, but seems the easiest way to fix the problem.
  +          *
  +          * XXX
  +          * Since the first level MUST be FTS_ROOTLEVEL, base
  +          * is always initialized.
  +          */
  +         if (ct->p->fts_level == FTS_ROOTLEVEL) {
  +             if (ct->type != DIR_TO_DNE) {
  +                 p = strrchr(ct->p->fts_path, '/');
  +                 base = (p == NULL) ? 0 : (int)(p - ct->p->fts_path + 1);
  +                 if (!strcmp(&ct->p->fts_path[base], ".."))
  +                     base += 1;
  +             } else
  +                 base = ct->p->fts_pathlen;
  +         }
  +
  +         p = &ct->p->fts_path[base];
  +         nlen = ct->p->fts_pathlen - base;
  +         target_mid = ct->target_end;
  +         if (*p != '/' && target_mid[-1] != '/')
  +             *target_mid++ = '/';
  +         *target_mid = 0;
  +         if (target_mid - ct->npath + nlen >= PATH_MAX) {
  +             rpmlog(RPMLOG_ERR, "%s%s: name too long (not copied)\n", 
ct->npath, p);
  +             rval = RPMRC_FAIL;
  +             continue;
  +         }
  +         (void)strncat(target_mid, p, nlen);
  +         ct->p_end = target_mid + nlen;
  +         *ct->p_end = '\0';
  +         while (ct->p_end > ct->npath + 1 && ct->p_end[-1] == '/')
  +             *--ct->p_end = '\0';
  +     }
  +
  +     if (ct->p->fts_info == FTS_DP) {
  +         /*
  +          * We are nearly finished with this directory.  If we
  +          * didn't actually copy it, or otherwise don't need to
  +          * change its attributes, then we are done.
  +          */
  +         if (!ct->p->fts_number)
  +             continue;
  +         /*
  +          * If -p is in effect, set all the attributes.
  +          * Otherwise, set the correct permissions, limited
  +          * by the umask.  Optimise by avoiding a Chmod()
  +          * if possible (which is usually the case if we
  +          * made the directory).  Note that Mkdir() does not
  +          * honour setuid, setgid and sticky bits, but we
  +          * normally want to preserve them on directories.
  +          */
  +         mode = ct->p->fts_statp->st_mode;
  +         if (CP_ISSET(PRESERVE)) {
  +             if (rpmctSetFile(ct, NULL))
  +                 rval = RPMRC_FAIL;
  +             if (rpmaclCopyDir(ct->p->fts_accpath, ct->npath, mode) != 0)
  +                 rval = RPMRC_FAIL;
  +         } else {
  +             if ((mode & (S_ISUID | S_ISGID | S_ISTXT))
  +              || ((mode | S_IRWXU) & mask) != (mode & mask))
  +                 if (Chmod(ct->npath, mode & mask) != 0) {
  +                     rpmlog(RPMLOG_ERR, "Chmod: %s: %s\n", ct->npath, 
strerror(errno));
  +                     rval = RPMRC_FAIL;
  +                 }
  +         }
  +         continue;
  +     }
  +
  +     /* Not an error but need to remember it happened */
  +     if (Stat(ct->npath, &ct->sb) == -1)
  +         dne = 1;
  +     else {
  +         if (ct->sb.st_dev == ct->p->fts_statp->st_dev &&
  +             ct->sb.st_ino == ct->p->fts_statp->st_ino)
  +         {
  +             rpmlog(RPMLOG_ERR, "%s and %s are identical (not copied).\n",
  +                 ct->npath, ct->p->fts_path);
  +             rval = RPMRC_FAIL;
  +             if (S_ISDIR(ct->p->fts_statp->st_mode))
  +                 (void)Fts_set(ct->t, ct->p, FTS_SKIP);
  +             continue;
  +         }
  +         if (!S_ISDIR(ct->p->fts_statp->st_mode) && S_ISDIR(ct->sb.st_mode)) 
{
  +             rpmlog(RPMLOG_ERR, "cannot overwrite directory %s with 
non-directory %s\n",
  +                 ct->npath, ct->p->fts_path);
  +             rval = RPMRC_FAIL;
  +             continue;
  +         }
  +         dne = 0;
  +     }
  +
  +     badcp = 0;
  +     switch (ct->p->fts_statp->st_mode & S_IFMT) {
  +     case S_IFLNK:
  +         /* Catch special case of a non-dangling symlink */
  +         if ((ct->ftsoptions & FTS_LOGICAL)
  +          || ((ct->ftsoptions & FTS_COMFOLLOW) && ct->p->fts_level == 0))
  +         {
  +             if (rpmctCopyFile(ct, dne))
  +                 badcp = 1;
  +         } else {    
  +             char opath[PATH_MAX];
  +             if (rpmctioReadlink(ct, opath, sizeof(opath))
  +              || (!dne && rpmctioUnlink(ct))
  +              || rpmctioSymlink(ct, opath)
  +              || (CP_ISSET(PRESERVE) && rpmctSetFile(ct, NULL)))
  +                 badcp = 1;
  +         }
  +         break;
  +     case S_IFDIR:
  +         if (!CP_ISSET(RECURSE)) {
  +             rpmlog(RPMLOG_ERR, "%s is a directory (not copied).\n", 
ct->p->fts_path);
  +             (void)Fts_set(ct->t, ct->p, FTS_SKIP);
  +             badcp = 1;
  +             break;
  +         }
  +         /*
  +          * If the directory doesn't exist, create the new
  +          * one with the from file mode plus owner RWX bits,
  +          * modified by the umask.  Trade-off between being
  +          * able to write the directory (if from directory is
  +          * 555) and not causing a permissions race.  If the
  +          * umask blocks owner writes, we fail.
  +          */
  +         if (dne) {
  +             if (Mkdir(ct->npath, ct->p->fts_statp->st_mode | S_IRWXU) < 0) {
  +                 rpmlog(RPMLOG_ERR, "Mkdir: %s: %s\n", ct->npath, 
strerror(errno));
  +                 rval = RPMRC_FAIL;
  +                 goto exit;
  +             }
  +         } else if (!S_ISDIR(ct->sb.st_mode)) {
  +             errno = ENOTDIR;
  +             rpmlog(RPMLOG_ERR, "%s: %s\n", ct->npath, strerror(errno));
  +             rval = RPMRC_FAIL;
  +             goto exit;
  +         }
  +         /*
  +          * Arrange to correct directory attributes later
  +          * (in the post-order phase) if this is a new
  +          * directory, or if the -p flag is in effect.
  +          */
  +         ct->p->fts_number = CP_ISSET(PRESERVE) || dne;
  +         break;
  +     case S_IFBLK:
  +     case S_IFCHR:
  +         if (CP_ISSET(RECURSE)) {
  +             if ((!dne && rpmctioUnlink(ct))
  +              || rpmctioMknod(ct, ct->p->fts_statp)
  +              || (CP_ISSET(PRESERVE) && rpmctSetFile(ct, NULL)))
  +                 badcp = 1;
  +         } else {
  +             if (rpmctCopyFile(ct, dne))
  +                 badcp = 1;
  +         }
  +         break;
  +     case S_IFSOCK:
  +         rpmlog(RPMLOG_ERR, "%s is a socket (not copied).\n", 
ct->p->fts_path);
  +         break;
  +     case S_IFIFO:
  +         if (CP_ISSET(RECURSE)) {
  +             if ((!dne && rpmctioUnlink(ct))
  +              || rpmctioMkfifo(ct, ct->p->fts_statp)
  +              || (CP_ISSET(PRESERVE) && rpmctSetFile(ct, NULL)))
  +                 badcp = 1;
  +         } else {
  +             if (rpmctCopyFile(ct, dne))
  +                 badcp = 1;
  +         }
  +         break;
  +     default:
  +         if (rpmctCopyFile(ct, dne))
  +             badcp = 1;
  +         break;
  +     }
  +     if (badcp)
  +         rval = RPMRC_FAIL;
  +     else if (rpmIsVerbose())
  +         rpmlog(RPMLOG_INFO, "%s -> %s\n", ct->p->fts_path, ct->npath);
  +    }
  +
  +exit:
  +    if (ct->t != NULL)
  +     Fts_close(ct->t);
  +    ct->t = NULL;
  +    ct->p = NULL;
  +    return rval;
  +}
  +
  +/*==============================================================*/
  +
  +/**
  + */
  +static void copyArgCallback(poptContext con,
  +                /*@unused@*/ enum poptCallbackReason reason,
  +                const struct poptOption * opt, const char * arg,
  +                /*@unused@*/ void * data)
  +        /*@globals _rpmct, h_errno, fileSystem, internalState @*/
  +        /*@modifies _rpmct, fileSystem, internalState @*/
  +{
  +    rpmct ct = (rpmct) data;
  +
  +assert(ct);
  +    /* XXX avoid accidental collisions with POPT_BIT_SET for flags */
  +    if (opt->arg == NULL)
  +    switch (opt->val) {
  +    case 'H':
  +     ct->flags |= COPY_FLAGS_FOLLOWARGS;
  +     ct->flags &= ~COPY_FLAGS_FOLLOW;
  +     break;
  +    case 'L':
  +     ct->flags |= COPY_FLAGS_FOLLOW;
  +     ct->flags &= ~COPY_FLAGS_FOLLOWARGS;
  +     break;
  +    case 'P':
  +     ct->flags &= ~COPY_FLAGS_FOLLOWARGS;
  +     ct->flags &= ~COPY_FLAGS_FOLLOW;
  +     break;
  +    case 'R':
  +     ct->flags |= COPY_FLAGS_RECURSE;
  +     break;
  +    case 'a':
  +     ct->flags |= COPY_FLAGS_PRESERVE;
  +     ct->flags |= COPY_FLAGS_RECURSE;
  +     ct->flags &= ~COPY_FLAGS_FOLLOWARGS;
  +     ct->flags &= ~COPY_FLAGS_FOLLOW;
  +     break;
  +    case 'f':
  +     ct->flags |= COPY_FLAGS_FORCE;
  +     ct->flags &= ~COPY_FLAGS_INTERACTIVE;
  +     ct->flags &= ~COPY_FLAGS_NOCLOBBER;
  +     break;
  +    case 'i':
  +     ct->flags |= COPY_FLAGS_INTERACTIVE;
  +     ct->flags &= ~COPY_FLAGS_FORCE;
  +     ct->flags &= ~COPY_FLAGS_NOCLOBBER;
  +     break;
  +    case 'l':
  +     ct->flags |= COPY_FLAGS_HARDLINK;
  +     break;
  +    case 'n':
  +     ct->flags |= COPY_FLAGS_NOCLOBBER;
  +     ct->flags &= ~COPY_FLAGS_FORCE;
  +     ct->flags &= ~COPY_FLAGS_INTERACTIVE;
  +     break;
  +    case 'p':
  +     ct->flags |= COPY_FLAGS_PRESERVE;
  +     break;
  +    case 'r':
  +     ct->flags |= COPY_FLAGS_RECURSE;
  +     ct->flags |= COPY_FLAGS_FOLLOW;
  +     ct->flags &= ~COPY_FLAGS_FOLLOWARGS;
  +     break;
  +    case 'x':
  +     ct->flags |= COPY_FLAGS_XDEV;
  +     break;
  +
  +    case '?':
  +    default:
  +     fprintf(stderr, _("%s: Unknown option -%c\n"), __progname, opt->val);
  +     poptPrintUsage(con, stderr, 0);
  +     exit(EXIT_FAILURE);
  +     /*@notreached@*/ break;
  +    }
  +}
  +
  +/*@unchecked@*/ /*@observer@*/
  +static struct poptOption rpmctOptionsTable[] = {
  +/*@-type@*/ /* FIX: cast? */
  + { NULL, '\0', POPT_ARG_CALLBACK | POPT_CBFLAG_INC_DATA,
  +        copyArgCallback, 0, NULL, NULL },
  +/*@=type@*/
  +
  +  { NULL,'H', POPT_ARG_NONE,         NULL, (int)'H',
  +     N_("Follow command-line symbolic links"), NULL },
  +  { "dereference",'L', POPT_ARG_NONE,                NULL, (int)'L',
  +     N_("Always follow symbolic links"), NULL },
  +  { "nodereference",'P', POPT_ARG_NONE,              NULL, (int)'P',
  +     N_("Never follow symbolic links"), NULL },
  +  { "recursive",'R', POPT_ARG_NONE,          NULL, (int)'R',
  +     N_("Copy directories recursively"), NULL },
  +  { "recursive",'r', POPT_ARG_NONE|POPT_ARGFLAG_DOC_HIDDEN,  NULL, (int)'R',
  +     N_("Copy directories recursively"), NULL },
  +  { "archive",'a', POPT_ARG_NONE,    NULL, (int)'a',
  +     N_("Archive mode (same as -RpP)"), NULL },
  +  { "force",'f', POPT_ARG_NONE,              NULL, (int)'f',
  +     N_("Unlink and retry if 1st open fails"), NULL },
  +  { "interactive",'i', POPT_ARG_NONE,        NULL, (int)'i',
  +     N_("Prompt before overwriting a file"), NULL },
  +  { "link",'l', POPT_ARG_NONE,               NULL, (int)'l',
  +     N_("Link files instead of copying"), NULL },
  +  { "noclobber",'n', POPT_ARG_NONE,  NULL, (int)'n',
  +     N_("Do not overwrite an existing file"), NULL },
  +  { "preserve",'p', POPT_ARG_NONE,   NULL, (int)'p',
  +     N_("Preserve mode/ownership/timestamps"), NULL },
  +  { "xdev",'x', POPT_ARG_NONE,       NULL, (int)'x',
  +     N_("Stay on thgis file system"), NULL },
  +
  +#ifdef       NOTYET
  + { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmioFtsPoptTable, 0,
  +     N_("Fts(3) traversal options:"), NULL },
  +
  + { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmioDigestPoptTable, 0,
  +     N_("Available digests:"), NULL },
  +#endif
  +
  + { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmioAllPoptTable, 0,
  +     N_("Common options for all rpmio executables:"),
  +     NULL },
  +
  +  POPT_AUTOALIAS
  +  POPT_AUTOHELP
  +
  +  { NULL, (char)-1, POPT_ARG_INCLUDE_TABLE, NULL, 0,
  +        "\
  +Usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpv] source_file 
target_file\n\
  +       cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpv] source_file ... 
target_dir\n\
  +", NULL },
  +
  +  POPT_TABLEEND
  +};
  +
  +static rpmRC
  +rpmctInitPopt(rpmct ct, int ac, char * const* av, poptOption tbl)
  +        /*@modifies ct @*/
  +{
  +    static int _popt_context_flags = 0;      /* XXX 
POPT_CONTEXT_POSIXMEHARDER */
  +    poptContext con = NULL;
  +    int have_trailing_slash;
  +    int r;
  +    rpmRC rc = RPMRC_FAIL;   /* assume failure */
  +    int xx;
  +
  +    tbl->descrip = (const char *) ct;
  +    con = poptGetContext(av[0], ac, (const char **)av, 
tbl,_popt_context_flags);
  +    while ((xx = poptGetNextOpt(con)) > 0)
  +    switch (xx) {
  +    default:
  +     fprintf(stderr, _("%s: option table misconfigured (%d)\n"),
  +                __FUNCTION__, xx);
  +     goto exit;
  +     break;
  +    }
  +
  +    ct->av = NULL;
  +    r = argvAppend(&ct->av, poptGetArgs(con));
  +    ct->ac = argvCount(ct->av);
  +    if (ct->ac < 2) {
  +     poptPrintUsage(con, stderr, 0);
  +     goto exit;
  +    }
  +    rc = RPMRC_OK;
  +
  +exit:
  +    if (con)
  +     con = poptFreeContext(con);
  +
  +SPEW((stderr, "<-- %s(%p,%p[%d]) rc %d\n", __FUNCTION__, ct, av, ac, rc));
  +    return rc;
  +}
  +
  +static rpmRC
  +rpmctInit(rpmct ct, int ac, char * const* av, unsigned flags)
  +        /*@modifies ct @*/
  +{
  +    int have_trailing_slash;
  +    int r;
  +    rpmRC rc;
  +    int xx;
  +
  +    ct->flags = (flags ? flags : COPY_FLAGS_NONE);   /* XXX already 0 */
  +    rc = rpmctInitPopt(ct, ac, av, rpmctOptionsTable);
  +    if (rc)
  +     goto exit;
  +
  +#if defined(_SC_PHYS_PAGES)
  +    if (sysconf(_SC_PHYS_PAGES) > PHYSPAGES_THRESHOLD)
  +     ct->ballocated = MIN(BUFSIZE_MAX, MAXPHYS * 8);
  +    else
  +#endif
  +     ct->ballocated = BUFSIZE_SMALL;
  +
  +    ct->npath[0] = '\0';
  +    ct->target_end = "";
  +    ct->p_end = ct->npath;
  +    ct->ftsoptions = FTS_NOCHDIR | FTS_PHYSICAL;
  +
  +    if (CP_ISSET(RECURSE)) {
  +     if (CP_ISSET(FOLLOWARGS))
  +         ct->ftsoptions |= FTS_COMFOLLOW;
  +     if (CP_ISSET(FOLLOW)) {
  +         ct->ftsoptions &= ~FTS_PHYSICAL;
  +         ct->ftsoptions |= FTS_LOGICAL;
  +     }
  +    } else {
  +     ct->ftsoptions &= ~FTS_PHYSICAL;
  +     ct->ftsoptions |= FTS_LOGICAL | FTS_COMFOLLOW;
  +    }
  +    if (CP_ISSET(XDEV))
  +     ct->ftsoptions |= FTS_XDEV;
  +
  +#if defined(SIGINFO)
  +    (void)signal(SIGINFO, siginfo);
  +#endif
  +
  +    /* Save the target base. */
  +    {        const char * target = ct->av[--ct->ac];
  +     if (strlen(target) > sizeof(ct->npath) - 2) {
  +         rpmlog(RPMLOG_ERR, "%s: name too long\n", target);
  +         goto exit;
  +     }
  +     (void) strcpy(ct->npath, target);
  +    }
  +    ct->p_end = ct->npath + strlen(ct->npath);
  +    if (ct->npath == ct->p_end) {
  +     *ct->p_end++ = '.';
  +     *ct->p_end = '\0';
  +    }
  +    have_trailing_slash = (ct->p_end[-1] == '/');
  +    if (have_trailing_slash)
  +     while (ct->p_end > ct->npath + 1 && ct->p_end[-1] == '/')
  +         *--ct->p_end = '\0';
  +    ct->target_end = ct->p_end;
  +
  +    /* Set end of argument list for fts(3). */
  +    ct->av[ct->ac] = NULL;
  +
  +    /*
  +     * Cp has two distinct cases:
  +     *
  +     * cp [-R] source target
  +     * cp [-R] source1 ... sourceN directory
  +     *
  +     * In both cases, source can be either a file or a directory.
  +     *
  +     * In (1), the target becomes a copy of the source. That is, if the
  +     * source is a file, the target will be a file, and likewise for
  +     * directories.
  +     *
  +     * In (2), the real target is not directory, but "directory/source".
  +     */
  +    r = Stat(ct->npath, &ct->sb);
  +    if (r == -1 && errno != ENOENT) {
  +     rpmlog(RPMLOG_ERR, "Stat: %s: %s\n", ct->npath, strerror(errno));
  +     goto exit;
  +    }
  +    if (r == -1 || !S_ISDIR(ct->sb.st_mode)) {
  +     /* Case (1).  Target is not a directory. */
  +     if (ct->ac > 1) {
  +         rpmlog(RPMLOG_ERR, "%s is not a directory\n", ct->npath);
  +         goto exit;
  +     }
  +
  +     /*
  +      * Need to detect the case:
  +      *      cp -R dir foo
  +      * Where dir is a directory and foo does not exist, where
  +      * we want pathname concatenations turned on but not for
  +      * the initial Mkdir().
  +      */
  +     if (r == -1) {
  +         struct stat sb;
  +         int xx;     /* XXX coverity #1035731 */
  +         if (CP_ISSET(RECURSE) && (CP_ISSET(FOLLOW) || CP_ISSET(FOLLOWARGS)))
  +         {
  +             if ((xx = Stat(ct->av[0], &sb))) {
  +                 rpmlog(RPMLOG_ERR, "Stat(%s) returns %d\n", ct->av[0], xx);
  +                 goto exit;
  +             }
  +         } else {
  +             if ((xx = Lstat(ct->av[0], &sb))) {
  +                 rpmlog(RPMLOG_ERR, "Lstat(%s) returns %d\n", ct->av[0], xx);
  +                 goto exit;
  +             }
  +         }
  +
  +         if (S_ISDIR(sb.st_mode) && CP_ISSET(RECURSE))
  +             ct->type = DIR_TO_DNE;
  +         else
  +             ct->type = FILE_TO_FILE;
  +     } else
  +         ct->type = FILE_TO_FILE;
  +
  +     if (have_trailing_slash && ct->type == FILE_TO_FILE) {
  +         if (r == -1)
  +             rpmlog(RPMLOG_ERR, "directory %s does not exist\n", ct->npath);
  +         else
  +             rpmlog(RPMLOG_ERR, "%s is not a directory\n", ct->npath);
  +         goto exit;
  +     }
  +    } else
  +     /* Case (2).  Target is a directory. */
  +     ct->type = FILE_TO_DIR;
  +
  +    rc = RPMRC_OK;
  +
  +exit:
  +SPEW((stderr, "<-- %s(%p,%p[%d]) rc %d\n", __FUNCTION__, ct, av, ac, rc));
  +    return rc;
  +}
  +
  +/*@-mustmod@*/       /* XXX splint on crack */
  +static void rpmctFini(void * _ct)
  +     /*@globals fileSystem @*/
  +     /*@modifies *_ct, fileSystem @*/
  +{
  +    rpmct ct = _ct;
  +
  +    ct->av = argvFree(ct->av);
  +    ct ->ac = 0;
  +    ct->b = _free(ct->b);
  +
  +}
  +/*@=mustmod@*/
  +
  +/*@unchecked@*/ /*@only@*/ /*@null@*/
  +rpmioPool _rpmctPool = NULL;
  +
  +static rpmct rpmctGetPool(/*@null@*/ rpmioPool pool)
  +     /*@globals _rpmctPool, fileSystem @*/
  +     /*@modifies pool, _rpmctPool, fileSystem @*/
  +{
  +    rpmct ct;
  +
  +    if (_rpmctPool == NULL) {
  +     _rpmctPool = rpmioNewPool("ct", sizeof(*ct), -1, _rpmct_debug,
  +                     NULL, NULL, rpmctFini);
  +     pool = _rpmctPool;
  +    }
  +    ct = (rpmct) rpmioGetPool(pool, sizeof(*ct));
  +    memset(((char *)ct)+sizeof(ct->_item), 0, sizeof(*ct)-sizeof(ct->_item));
  +    return ct;
  +}
  +
  +rpmct rpmctNew(char ** argv, unsigned flags)
  +{
  +    static char *_argv[] = { "rpmct", NULL };
  +    ARGV_t av = (ARGV_t) (argv ? argv : _argv);
  +    int ac = argvCount(av);
  +    rpmct ct = rpmctGetPool(_rpmctPool);
  +    rpmRC rc;
  +
  +SPEW((stderr, "--> %s(%p,0x%x)\n", __FUNCTION__, argv, flags));
  +
  +    rc = rpmctInit(ct, ac, (char * const*)av, flags);
  +    if (rc)
  +     ct = rpmctFree(ct);
  +
  +    return rpmctLink(ct);
  +}
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmio/rpmct.h
  ============================================================================
  $ cvs diff -u -r0 -r1.1.2.1 rpmct.h
  --- /dev/null 2014-09-12 06:36:27.000000000 +0200
  +++ rpmct.h   2014-09-12 06:38:48.067080082 +0200
  @@ -0,0 +1,145 @@
  +#ifndef      H_RPMCT
  +#define      H_RPMCT
  +
  +/** \ingroup rpmpgp
  + * \file rpmio/rpmct.h
  + */
  +
  +#include <rpmiotypes.h>
  +
  +extern int _rpmct_debug;
  +
  +typedef /*refcounted@*/ struct rpmct_s * rpmct;
  +
  +/*
  + * Cp copies source files to target files.
  + *
  + * The global PATH_T structure "to" always contains the path to the
  + * current target file.  Since Fts(3) does not change directories,
  + * this path can be either absolute or dot-relative.
  + *
  + * The basic algorithm is to initialize rpmct target and use Fts(3) to 
traverse
  + * the file hierarchy rooted in the argument list.  A trivial case is the
  + * case of 'cp file1 file2'.  The more interesting case is the case of
  + * 'cp file1 file2 ... fileN dir' where the hierarchy is traversed and the
  + * path (relative to the root of the traversal) is appended to dir (stored
  + * in rpmct) to form the final target path.
  + */
  +
  +#if defined(_RPMCT_INTERNAL)
  +#include <argv.h>
  +#include <fts.h>
  +
  +/**
  + * Bit field enum for copy CLI options.
  + */
  +#define _KFB(n) (1U << (n))
  +#define _MFB(n) (_KFB(n) | 0x40000000)
  +enum rpmctFlags_e {
  +    COPY_FLAGS_NONE          = 0,
  +    COPY_FLAGS_FOLLOWARGS    = _MFB( 0), /*!< -H ... */
  +    COPY_FLAGS_FOLLOW                = _MFB( 1), /*!< -L ... */
  +    COPY_FLAGS_RECURSE               = _MFB( 2), /*!< -R ... */
  +    COPY_FLAGS_ARCHIVE               = _MFB( 3), /*!< -a,--archive ... */
  +    COPY_FLAGS_FORCE         = _MFB( 4), /*!< -f,--force ... */
  +    COPY_FLAGS_INTERACTIVE   = _MFB( 5), /*!< -i,--interactive ... */
  +    COPY_FLAGS_HARDLINK              = _MFB( 6), /*!< -l,--link ... */
  +    COPY_FLAGS_NOCLOBBER     = _MFB( 7), /*!< -n,--noclobber ... */
  +    COPY_FLAGS_PRESERVE              = _MFB( 8), /*!< -p,--preserve ... */
  +    COPY_FLAGS_XDEV          = _MFB( 9), /*!< -x,--xdev ... */
  +
  +    COPY_FLAGS_SYMLINK               = _MFB(10), /*!< -s,--symlink ... */
  +    COPY_FLAGS_UPDATE                = _MFB(11), /*!< -u,--update ... */
  +    COPY_FLAGS_SPARSE                = _MFB(12), /*!<    --sparse ... */
  +
  +     /* 13-31 unused */
  +};
  +
  +enum rpmctType_e { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE };
  +
  +struct rpmct_s {
  +    struct rpmioItem_s _item;        /*!< usage mutex and pool identifier. */
  +
  +    enum rpmctFlags_e flags;
  +    enum rpmctType_e type;
  +    ARGV_t av;
  +    int ac;
  +    int ftsoptions;
  +    FTS * t;
  +    FTSENT * p;
  +    struct stat sb;
  +    char * b;
  +    size_t blen;
  +    size_t ballocated;
  +    struct timeval tv[2];
  +    char * p_end;            /* pointer to NULL at end of path */
  +    char * target_end;               /* pointer to end of target base */
  +    char npath[PATH_MAX];    /* pointer to the start of a path */
  +
  +#if defined(__LCLINT__)
  +/*@refs@*/
  +    int nrefs;                       /*!< (unused) keep splint happy */
  +#endif
  +};
  +#endif       /* defined(_RPMCT_INTERNAL) */
  +
  +#ifdef __cplusplus
  +extern "C" {
  +#endif
  +
  +/**
  + * Unreference a copytree wrapper instance.
  + * @param ct         copytree wrapper
  + * @return           NULL on last dereference
  + */
  +/*@unused@*/ /*@null@*/
  +rpmct rpmctUnlink (/*@killref@*/ /*@only@*/ /*@null@*/ rpmct ct)
  +     /*@modifies ct @*/;
  +#define      rpmctUnlink(_ct)        \
  +    ((rpmct)rpmioUnlinkPoolItem((rpmioItem)(_ct), __FUNCTION__, __FILE__, 
__LINE__))
  +
  +/**
  + * Reference a copytree wrapper instance.
  + * @param ct         copytree wrapper
  + * @return           new copytree wrapper reference
  + */
  +/*@unused@*/ /*@newref@*/ /*@null@*/
  +rpmct rpmctLink (/*@null@*/ rpmct ct)
  +     /*@modifies ct @*/;
  +#define      rpmctLink(_ct)  \
  +    ((rpmct)rpmioLinkPoolItem((rpmioItem)(_ct), __FUNCTION__, __FILE__, 
__LINE__))
  +
  +/**
  + * Destroy a copytree wrapper.
  + * @param ct         copytree wrapper
  + * @return           NULL on last dereference
  + */
  +/*@null@*/
  +rpmct rpmctFree(/*@killref@*/ /*@null@*/rpmct ct)
  +     /*@globals fileSystem @*/
  +     /*@modifies ct, fileSystem @*/;
  +#define      rpmctFree(_ct)  \
  +    ((rpmct)rpmioFreePoolItem((rpmioItem)(_ct), __FUNCTION__, __FILE__, 
__LINE__))
  +
  +/**
  + * Create a copytree wrapper.
  + * @param argv               copytree arguments
  + * @param flags              copytree flags
  + * @return           new copytree wrapper (NULL on error)
  + */
  +rpmct rpmctNew(char ** argv, unsigned flags)
  +     /*@*/;
  +
  +/**
  + * Copy a tree.
  + * @param ct         copytree wrapper
  + * @return           RPMRC_OK on success
  + */
  +rpmRC rpmctCopy(/*@null@*/ rpmct ct)
  +     /*@*/;
  +
  +#ifdef __cplusplus
  +}
  +#endif
  +
  +#endif       /* H_RPMCT */
  @@ .
______________________________________________________________________
RPM Package Manager                                    http://rpm5.org
CVS Sources Repository                                rpm-cvs@rpm5.org

Reply via email to