BackupPC-XS

 view release on metacpan or  search on metacpan

bpc_attrib.c  view on Meta::CPAN

     */
    if ( (attribFileName = strrchr(attribFilePath, '/')) ) {
        attribFileName++;
    } else {
        attribFileName = attribFilePath;
    }

    if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_attrib_dirRead(%s); dirPath = %s, attribFilePath = %s, attribFileName = %s\n",
                                         attribPath, dirPath, attribFilePath, attribFileName);

    if ( (p = strchr(attribFileName, '_')) && !stat(attribPath, &st) && S_ISREG(st.st_mode) ) {
        /*
         * Explicit path name to new-style attrib file, and it exists; extract digest
         */
        if ( !strcmp(p + 1, "0") ) return 0;
        bpc_digest_str2digest(&dir->digest, p + 1);
        if ( BPC_LogLevel >= 6 ) {
            char str[256];
            bpc_digest_digest2str(&dir->digest, str);
            bpc_logMsgf("bpc_attrib_dirRead: called with attrib file %s: digest = %s, len = %d\n",
                                              attribPath, str, dir->digest.len);
        }
        /*
         * Write new type attrib files (since we found a new-style one)
         */
	WriteOldStyleAttribFile = 0;
        magic = BPC_ATTRIB_TYPE_XATTR;
    } else if ( stat(attribPath, &st) || !S_ISREG(st.st_mode) || strchr(attribFileName, '_') ) {
        DIR *dirOs;
        struct dirent *dp;
        int attribFileNameLen = strlen(attribFileName);
        char attribDirPath[BPC_MAXPATHLEN];
        /*
         * Starting in 0.50, the attrib files are zero length with the digest encoded in
         * the file name, so there is no file just called "attrib".  Look in the directory
         * to find it.
         */
        strcpy(attribDirPath, attribPath);

bpc_attribCache.c  view on Meta::CPAN


            bpc_attrib_dirInit(&dir, ac->bkupMergeList[i].compress);
            if ( (status = bpc_attrib_dirRead(&dir, topDir, attribPath, ac->bkupMergeList[i].num)) ) {
                if ( ac->bkupMergeList[i].version < 4 ) {
                    char *p;
                    int attribDirExists = 1;
                    STRUCT_STAT st;

                    if ( (p = strrchr(fullAttribPath, '/')) ) {
                        *p = '\0';
                        attribDirExists = !stat(fullAttribPath, &st) && S_ISDIR(st.st_mode);
                        *p = '/';
                    }
                    if ( i == ac->bkupMergeCnt - 1 && !attribDirExists ) {
                        /*
                         * For V3, if the last backup doesn't have a directory, then the merged view is empty
                         */
                        bpc_attrib_dirDestroy(&dir);
                        bpc_attrib_dirDestroy(&attr->dir);
                        bpc_attrib_dirInit(&attr->dir, ac->compress);
                        break;

bpc_attribCache.c  view on Meta::CPAN

            bpc_attrib_dir dir;
            ssize_t entrySize;
            char *entries, *entry;

            snprintf(inodeDir, sizeof(inodeDir), "%s/pc/%s/%d/%s", BPC_TopDir, ac->hostName, ac->bkupMergeList[i].num, attribDir);
            snprintf(fullAttribPath, sizeof(fullAttribPath), "%s/%s", inodeDir, attribFile);

            bpc_attrib_dirInit(&dir, ac->bkupMergeList[i].compress);
            if ( (status = bpc_attrib_dirRead(&dir, inodeDir, attribFile, ac->bkupMergeList[i].num)) ) {
                STRUCT_STAT st;
                int attribDirExists = !stat(inodeDir, &st) && S_ISDIR(st.st_mode);
                if ( ac->bkupMergeList[i].version < 4 || !attribDirExists ) {
                     /*
                      * nothing to update here - keep going
                      */
                     bpc_attrib_dirDestroy(&dir);
                     continue;
                }
                bpc_logErrf("bpc_attribCache_loadInode: bpc_attrib_dirRead(%s/%s) returned %d\n", inodeDir, attribFile, status);
            }
            if ( bpc_attrib_dirNeedRewrite(&dir) ) {

bpc_dirOps.c  view on Meta::CPAN

int bpc_path_create(char *path)
{
    char *p = path;
    STRUCT_STAT st;
    int levels = 0;

    if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_path_create(%s)\n", path);
    /*
     * check if it exists already
     */
    if ( !stat(path, &st) && S_ISDIR(st.st_mode) ) return 0;

    /*
     * We walk up until we find the deepest level directory that exists.
     * First remove trailing slashes.
     */
    p = path + strlen(path);
    while ( p > path && p[-1] == '/' ) p--;
    if ( *p == '/' ) *p = '\0';
    while ( p > path ) {
        while ( p > path && p[-1] != '/' ) p--;
        while ( p > path && p[-1] == '/' ) p--;
        if ( *p == '/' ) {
            *p = '\0';
            levels++;
            if ( !stat(path, &st) && S_ISDIR(st.st_mode) ) break;
        }
    }
    if ( BPC_LogLevel >= 9 ) bpc_logMsgf("bpc_path_create: found that %s exists (%d levels up)\n", path, levels);

    /*
     * We have removed levels '/' characters from path.  Replace each one and create the directory.
     */
    while ( levels-- > 0 ) {
        p = path + strlen(path);
        *p = '/';

bpc_dirOps.c  view on Meta::CPAN


    if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_path_remove(%s)\n", path);
    if ( !(dir = opendir(path)) ) {
        unlink(path);
        return errorCnt;
    }
    while ( (dp = readdir(dir)) ) {
        if ( !strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..") ) continue;
        snprintf(filePath, sizeof(filePath), "%s/%s", path, dp->d_name);
        if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_path_remove: removing %s\n", filePath);
        if ( stat(filePath, &st) ) {
            /*
             * hmmm.  stat failed - just try to remove it
             */
            unlink(filePath);
            continue;
        }
        if ( S_ISDIR(st.st_mode) ) {
            /*
             * To avoid recursing with dir still open (consuming an open fd), remember all the dirs
             * and recurse after we close dir.

bpc_dirOps.c  view on Meta::CPAN

    char *dirList = NULL, *dirListP;

    if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_path_refCountAll(%s)\n", path);
    if ( !(dir = opendir(path)) ) {
        return errorCnt;
    }
    while ( (dp = readdir(dir)) ) {
        if ( !strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..") ) continue;
        snprintf(filePath, sizeof(filePath), "%s/%s", path, dp->d_name);
        if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_path_refCountAll: got %s\n", filePath);
        if ( stat(filePath, &st) ) continue;
        if ( S_ISDIR(st.st_mode) ) {
            /*
             * To avoid recursing with dir still open (consuming an open fd), remember all the dirs
             * and recurse after we close dir.
             */
            if ( !dirList ) {
                dirListSize = 4096;
                if ( !(dirList = malloc(dirListSize)) ) {
                    bpc_logErrf("bpc_path_refCountAll: can't allocate %u bytes\n", (unsigned)dirListSize);
                    return ++errorCnt;

bpc_poolWrite.c  view on Meta::CPAN

            /*
             * For >= V4.x pool, don't attempt to match pool files that
             * are empty, since in >= V4.x we don't rename pool
             * files in a repeated chain and instead replace them
             * with an empty file.
             * If the candidate has the other execute bit set, we do a safe
             * reset of the bit and allow matches to occur.  This is used to flag
             * pool files that will be deleted next time BackupPC_refCountUpdate
             * runs, so resetting that bit prevents the deletion.
             */
            if ( stat(poolPath, &st) ) break;
            if ( S_ISREG(st.st_mode) ) {
                if ( st.st_size > 0 ) {
                    bpc_candidate_file *candidateFile;
                    if ( (st.st_mode & S_IXOTH) && bpc_poolWrite_unmarkPendingDelete(poolPath) ) {
                        bpc_logErrf("Couldn't unmark candidate matching file %s (skipped; errno = %d)\n", poolPath, errno);
                        info->errorCnt++;
                        break;
                    }
                    candidateFile = malloc(sizeof(bpc_candidate_file));
                    if ( !candidateFile ) {

bpc_poolWrite.c  view on Meta::CPAN

                /*
                 * For V3.x pool, don't attempt to match pool files:
                 *  - that already have too many hardlinks.
                 *  - with only one link since starting in BackupPC v3.0,
                 *    BackupPC_nightly could be running in parallel (and
                 *    removing those files).  This doesn't eliminate all
                 *    possible race conditions, but just reduces the
                 *    odds.  Other design steps eliminate the remaining
                 *    race conditions of linking vs removing.
                 */
                if ( stat(poolPath, &st) ) break;
                if ( S_ISREG(st.st_mode)
                        && 1 < st.st_nlink && st.st_nlink < (unsigned)BPC_HardLinkMax ) {
                    bpc_candidate_file *candidateFile = malloc(sizeof(bpc_candidate_file));
                    if ( !candidateFile ) {
                        info->errorCnt++;
                        bpc_logErrf("bpc_poolWrite_write: can't allocate bpc_candidate_file\n");
                        return -1;
                    }
                    candidateFile->digest   = info->digest_v3;
                    candidateFile->fileSize = st.st_size;

bpc_poolWrite.c  view on Meta::CPAN


    /*
     * If originally present, make sure the zero-length file is still there (and still
     * zero-length), and the open slot is still open.  If not, it probably means someone
     * beat us to it, and we should re-do the whole pool matching to see if the newly
     * added pool file now matches.
     */
    if ( info->digestExtZeroLen >= 0 ) {
        bpc_digest_append_ext(&info->digest, info->digestExtZeroLen);
        bpc_digest_md52path(poolPath, info->compress, &info->digest);
        if ( stat(poolPath, &st) || st.st_size != 0 ) {
            redo = 1;
        }
    }
    if ( !redo ) {
        bpc_digest_append_ext(&info->digest, info->digestExtOpen);
        bpc_digest_md52path(poolPath, info->compress, &info->digest);
        if ( !stat(poolPath, &st) ) {
            redo = 1;
        }
    }

    /*
     * Try to insert the new file at the zero-length file slot (if present).
     */
    if ( !redo && info->digestExtZeroLen >= 0 ) {
        char lockFile[BPC_MAXPATHLEN];
        int lockFd;

bpc_poolWrite.c  view on Meta::CPAN

         */
        bpc_digest_append_ext(&info->digest, info->digestExtZeroLen);
        bpc_digest_md52path(poolPath, info->compress, &info->digest);
        if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_poolWrite_addToPool: replacing empty pool file %s with %s\n", poolPath, fileName);
        snprintf(lockFile, BPC_MAXPATHLEN, "%s.lock", poolPath);
        lockFd = bpc_lockRangeFile(lockFile, 0, 1, 1);
        /*
         * If we don't have the lock, or the file is no longer zero length, or the rename fails,
         * then try again.
         */
        if ( lockFd < 0 || stat(poolPath, &st) || st.st_size != 0 || rename(fileName, poolPath) ) {
            if ( BPC_LogLevel >= 5 ) {
                bpc_logMsgf("bpc_poolWrite_addToPool: lock/rename failed: need to repeat write (lockFd = %d, size = %lu, errno = %d)\n",
                             lockFd, (unsigned long)st.st_size, errno);
            }
            if ( lockFd >= 0 ) {
                bpc_unlockRangeFile(lockFd);
            }
            unlink(lockFile);
            redo = 1;
        } else {
            chmod(poolPath, 0444);
            stat(poolPath, &st);
            info->retValue     = v3PoolFile ? 2 : 0;
            info->poolFileSize = st.st_size;
            bpc_unlockRangeFile(lockFd);
            unlink(lockFile);
            return;
        }
    }

    /*
     * Now try to link the file to the new empty slot at the end

bpc_poolWrite.c  view on Meta::CPAN

        int linkOk, statOk;
        ino_t fileIno, poolIno;
        /*
         * Since this is a new slot, there is no need to do locking since
         * the link or open operations below are atomic/exclusive.
         *
         * First try to hardlink to the empty pool file slot
         */
        bpc_digest_append_ext(&info->digest, info->digestExtOpen);
        bpc_digest_md52path(poolPath, info->compress, &info->digest);
        if ( stat(fileName, &st) ) {
            info->errorCnt++;
            bpc_logErrf("bpc_poolWrite_addToPool: can't stat %s\n", fileName);
            return;
        }
        fileIno = st.st_ino;
        linkOk = !link(fileName, poolPath);
        if ( !(statOk = !stat(poolPath, &st)) ) linkOk = 0;
        poolIno = st.st_ino;
        if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_poolWrite_addToPool: link %s -> %s (linkOk = %d, statOk = %d, ino = %lu/%lu)\n",
                                                poolPath, fileName, linkOk, statOk, (unsigned long)fileIno, (unsigned long)poolIno);

        /*
         * make sure the link really worked by checking inode numbers
         * TODO: test these different cases.
         */
        if ( statOk && fileIno == poolIno ) {
            /*

bpc_poolWrite.c  view on Meta::CPAN

    /*
     * The lock file is in the first level of pool sub directories - one level
     * up from the full path.  So we need to find the 2nd last '/'.
     */
    snprintf(lockFile, BPC_MAXPATHLEN, "%s", poolPath);
    if ( !(p = strrchr(lockFile, '/')) ) return -1;
    *p = '\0';
    if ( !(p = strrchr(lockFile, '/')) ) return -1;
    snprintf(p + 1, BPC_MAXPATHLEN - (p + 1 - lockFile), "%s", "LOCK");
    if ( (lockFd = bpc_lockRangeFile(lockFile, 0, 1, 1)) < 0 ) return -1;
    if ( !stat(poolPath, &st) && !chmod(poolPath, st.st_mode & ~S_IXOTH & ~S_IFMT) ) {
        if ( BPC_LogLevel >= 7 ) bpc_logMsgf("bpc_poolWrite_unmarkPendingDelete(%s) succeeded\n", poolPath);
        bpc_unlockRangeFile(lockFd);
        return 0;
    } else {
        bpc_logErrf("bpc_poolWrite_unmarkPendingDelete(%s) failed; errno = %d\n", poolPath, errno);
        bpc_unlockRangeFile(lockFd);
        return -1;
    }
}

configure.sh  view on Meta::CPAN

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
main() {
  struct stat st;
  char tpl[20]="/tmp/test.XXXXXX";
  int fd = mkstemp(tpl);
  if (fd == -1) exit(1);
  unlink(tpl);
  if (fstat(fd, &st) != 0) exit(1);
  if ((st.st_mode & 0777) != 0600) exit(1);
  exit(0);
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
  rsync_cv_HAVE_SECURE_MKSTEMP=yes
else
  rsync_cv_HAVE_SECURE_MKSTEMP=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \

lib/BackupPC/XS.pm  view on Meta::CPAN

#
# If $compress is >0, copy and compress $srcFile putting the output
# in $destFileZ.  Otherwise, copy the file to $destFileNoZ, or do
# nothing if $destFileNoZ is undef.  Finally, if rename is set, then
# the source file is removed.
#
sub compressCopy
{
    my($srcFile, $destFileZ, $destFileNoZ, $compress, $rmSrc) = @_;
    my($srcFh);
    my(@s) = stat($srcFile);
    my $atime = $s[8];
    my $mtime = $s[9];

    if ( $compress > 0 ) {
        my $fh = BackupPC::XS::FileZIO::open($destFileZ, 1, $compress);
        my $data;
        if ( defined($fh) && open($srcFh, "<", $srcFile) ) {
            binmode($srcFh);
            while ( sysread($srcFh, $data, 65536 *4) > 0 ) {
                $fh->write(\$data);



( run in 1.607 second using v1.01-cache-2.11-cpan-49f99fa48dc )