BackupPC-XS

 view release on metacpan or  search on metacpan

BackupPC_XS.xs  view on Meta::CPAN

 * with this program; if not, visit the http://fsf.org website.
 */


#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "ppport.h"

#include <backuppc.h>

typedef bpc_fileZIO_fd          *BackupPC__XS__FileZIO;
typedef bpc_refCount_info       *BackupPC__XS__PoolRefCnt;
typedef bpc_deltaCount_info     *BackupPC__XS__DeltaRefCnt;
typedef bpc_poolWrite_info      *BackupPC__XS__PoolWrite;
typedef bpc_attrib_dir          *BackupPC__XS__Attrib;
typedef bpc_attribCache_info    *BackupPC__XS__AttribCache;

#define hv_get_int(hv, key, value)       { SV** svp = hv_fetch((hv), (key), strlen(key), 0); if ( svp && *svp ) (value) = SvIV(*svp); }
#define hv_get_uint(hv, key, value)      { SV** svp = hv_fetch((hv), (key), strlen(key), 0); if ( svp && *svp ) (value) = SvUV(*svp); }

BackupPC_XS.xs  view on Meta::CPAN

void
backwardCompat(writeOldStyleAttribFile, keepOldAttribFiles)
        int writeOldStyleAttribFile;
        int keepOldAttribFiles;
    CODE:
        bpc_attrib_backwardCompat(writeOldStyleAttribFile, keepOldAttribFiles);

MODULE = BackupPC::XS		PACKAGE = BackupPC::XS::AttribCache

BackupPC::XS::AttribCache
new(host, backupNum, shareNameUM, compress)
        char *host;
        int backupNum;
        char *shareNameUM;
        int compress;
    CODE:
    {
        RETVAL = calloc(1, sizeof(bpc_attribCache_info));
        bpc_attribCache_init(RETVAL, host, backupNum, shareNameUM, compress);
    }
    OUTPUT:
        RETVAL

void
DESTROY(ac)
        BackupPC::XS::AttribCache ac;
    CODE:
    {
        bpc_attribCache_destroy(ac);

Changes  view on Meta::CPAN

0.62: June 20, 2020

   - force rewrite of attr file if xattr key fixup was applied

   - fixed attrib refCnt when attrib is unchanged

   - bpc_attrib_dirWrite() doesn't create empty attrib files

0.61: June 8, 2020

   - fix view of migrated v3 backup

   - convert_hv2file() ensures xattr type is hash, and uses correct keyLen+1

   - added BackupPC::XS::FileDigest::digest and bpc_fileDigest()

0.60: May 30, 2020

   - allow mtime to be signed in attrib files

   - added bpc_attrib_fileIterate() and BackupPC::XS::Attrib::iterate()

Changes  view on Meta::CPAN

     change in rsync-bpc and has no effect here since BackupPC::XS doesn't set
     ac->currentDir[].

   - bpc_attrib_dirWrite() updates dir->digest with new digest.

   - updated configure.sh with package name and current version

0.57: Dec 2, 2017

    - added BackupPC::XS::DirOps::refCountAllInodeMax() and bpc_path_refCountAllInodeMax() to allow
      BackupPC_refCountAll to get the largest inode as the backup tree is traversed.

0.56: Jun 11, 2017

    - change to Makefile.PL to ensure that parallel builds (make -j N) work with BSD make
      (pull request #4 from Alexander Moisseev).

0.55: Jun 4, 2017

    - updated Makefile.PL so ./configure is run before subdirs are built when parallel make (eg: make -j 4) is used

Changes  view on Meta::CPAN

    - updated config.guess and config.sub; fixes problem with aarch64 and ppc64le
      reported by Denis Fateyev.

0.51: March 5, 2017

    - added dynamic:: target to subdir Makefile.PLs to fix build issue on gentoo
      (patch submitted by Slaven Rezic; see https://rt.cpan.org/Ticket/Display.html?id=120495)

0.50: March 3, 2017

    - Reference counting is now per-backup; replaced static delta information with callable interface.

    - Attribute files are now zero-length with the md5 digest encoded in the file name.

    - several bug fixes 
    
0.40: June 18, 2016

    - Significant rewrite of bpc_hashTable.c so that resizing doesn't move the entries. The nodes are stored as pointers
      (rather than flat); a freelist maintains unused nodes.

Changes  view on Meta::CPAN


    - Fixed bug triggered during certain smb transfers and tar/zip restore.  Reported
      by Steve Palm and Denis Jedig.

    - Some clean up of perl RV/SV reference counting.

0.20: September 2, 2013

    - BackupPC-XS-0.20/BackupPC_XS.xs: added lockRangeFd() and unlockRangeFd()

    - BackupPC-XS-0.20/backuppc.h: changed BPC_POOL_WRITE_CONCURRENT_MATCH from 4 to 16

    - BackupPC-XS-0.20/bpc_lib.c: bpc_lib_conf_init debug message now only logLevel >= 8

0.10: July 1, 2013

    - BackupPC-XS-0.10/bpc_poolWrite.c: improved matching and redo logic

0.01: June 24, 2013
    - original version; created by h2xs 1.23 with options
		-A -n BackupPC-XS backuppc.h

MANIFEST  view on Meta::CPAN

MANIFEST
README
BackupPC_XS.xs
Changes
Makefile.PL
ppport.h
typemap
backuppc.h
bpc_attrib.c
bpc_attribCache.c
bpc_dirOps.c
bpc_fileDigest.c
bpc_fileZIO.c
bpc_hashtable.c
bpc_lib.c
bpc_poolWrite.c
bpc_refCount.c
byteorder.h

backuppc.h  view on Meta::CPAN

     * reference counts.
     */
    ushort isTemp;
    uint32 mode;
    uid_t uid;
    gid_t gid;
    uint32 nlinks;
    time_t mtime;
    OFF_T size;
    ino_t inode;
    int32 backupNum;
    bpc_digest digest;
    /*
     * hash table of bpc_attrib_xattr entries, indexed by xattr key
     */
    bpc_hashtable xattrHT;
} bpc_attrib_file;

/*
 * A directory is a hash table of file attributes, indexed by file name
 */

backuppc.h  view on Meta::CPAN

int bpc_attrib_dirNeedRewrite(bpc_attrib_dir *dir);
ssize_t bpc_attrib_getEntries(bpc_attrib_dir *dir, char *entries, ssize_t entrySize);
void bpc_attrib_dirRefCount(bpc_deltaCount_info *deltaInfo, bpc_attrib_dir *dir, int incr);
void bpc_attrib_dirRefCountInodeMax(bpc_deltaCount_info *deltaInfo, bpc_attrib_dir *dir, int incr, unsigned int *inodeMax);
void bpc_attrib_attribFilePath(char *path, char *dir, char *attribFileName);
bpc_digest *bpc_attrib_dirDigestGet(bpc_attrib_dir *dir);
uchar *bpc_attrib_buf2file(bpc_attrib_file *file, uchar *buf, uchar *bufEnd, int xattrNumEntries, int *xattrFixup);
uchar *bpc_attrib_buf2fileFull(bpc_attrib_file *file, uchar *buf, uchar *bufEnd);
uchar *bpc_attrib_file2buf(bpc_attrib_file *file, uchar *buf, uchar *bufEnd);
int bpc_attrib_digestRead(bpc_attrib_dir *dir, bpc_digest *digest, char *attribPath);
int bpc_attrib_dirRead(bpc_attrib_dir *dir, char *dirPath, char *attribFileName, int backupNum);
int bpc_attrib_dirWrite(bpc_deltaCount_info *deltaInfo, bpc_attrib_dir *dir, char *dirPath, char *attribFileName, bpc_digest *oldDigest);
void bpc_attrib_backwardCompat(int writeOldStyleAttribFile, int keepOldAttribFiles);

/*
 * Attrib caching
 */ 

#define BPC_FTYPE_FILE                  (0)
#define BPC_FTYPE_HARDLINK              (1)
#define BPC_FTYPE_SYMLINK               (2)

backuppc.h  view on Meta::CPAN

#define BPC_FTYPE_FIFO                  (6)
#define BPC_FTYPE_SOCKET                (8)
#define BPC_FTYPE_UNKNOWN               (9)
#define BPC_FTYPE_DELETED               (10)
#define BPC_FTYPE_INVALID               (11)

typedef struct {
    int num;
    int compress;
    int version;
} bpc_backup_info;

typedef struct {
    int backupNum;
    int compress;
    int readOnly;
    uint cacheLruCnt;

    /*
     * optional merging of backups to create view for restore
     */
    bpc_backup_info *bkupMergeList;
    int bkupMergeCnt;

    /*
     * Hash table of cached file attributes.
     * Key   is the mangled attrib path (excluding backupTopDir[], and including attrib file name).
     * Value is a bpc_attrib_dir structure.
     *    - Keys of the bpc_attrib_dir hash table are the file names in that directory.
     */
    bpc_hashtable attrHT;

    /*
     * Hash table of cached inode attributes.
     * Key is the inode attribute path (excluding backupTopDir[]).
     * Value is a bpc_attrib_dir structure.
     *    - Keys of the bpc_attrib_dir hash table are the inode numbers converted to ascii hex, lsb first.
     */
    bpc_hashtable inodeHT;

    /*
     * Delta reference count for any changes as we write/change files or attributes
     */
    bpc_deltaCount_info *deltaInfo;

    char shareName[BPC_MAXPATHLEN];
    int shareNameLen;
    char shareNameUM[BPC_MAXPATHLEN];
    char hostName[BPC_MAXPATHLEN];
    char hostDir[BPC_MAXPATHLEN];
    char backupTopDir[BPC_MAXPATHLEN];
    char currentDir[BPC_MAXPATHLEN];
} bpc_attribCache_info;

typedef struct {
    bpc_hashtable_key key;
    int dirty;
    /* 
     * We flag directories whose parents either don't exist or aren't directories.
     * We ignore attributes on bad directories.
     * Initially this flag is zero, meaning we don't know if this directory is ok.
     * After we check, > 0 means parent does exist and is a directory ; < 0 means dir is bad
     */
    int dirOk;
    uint lruCnt;
    bpc_attrib_dir dir;
} bpc_attribCache_dir;

void bpc_attribCache_init(bpc_attribCache_info *ac, char *host, int backupNum, char *shareNameUM, int compress);
void bpc_attribCache_setDeltaInfo(bpc_attribCache_info *ac, bpc_deltaCount_info *deltaInfo);
void bpc_attribCache_setMergeList(bpc_attribCache_info *ac, bpc_backup_info *bkupList, int bkupCnt);
void bpc_attribCache_destroy(bpc_attribCache_info *ac);
int bpc_attribCache_readOnly(bpc_attribCache_info *ac, int readOnly);
void bpc_attribCache_setCurrentDirectory(bpc_attribCache_info *ac, char *dir);
bpc_attrib_file *bpc_attribCache_getFile(bpc_attribCache_info *ac, char *path, int allocate_if_missing, int dontReadInode);
int bpc_attribCache_setFile(bpc_attribCache_info *ac, char *path, bpc_attrib_file *file, int dontOverwriteInode);
int bpc_attribCache_deleteFile(bpc_attribCache_info *ac, char *path);
bpc_attrib_file *bpc_attribCache_getInode(bpc_attribCache_info *ac, ino_t inode, int allocate_if_missing);
int bpc_attribCache_setInode(bpc_attribCache_info *ac, ino_t inode, bpc_attrib_file *inodeSrc);
int bpc_attribCache_deleteInode(bpc_attribCache_info *ac, ino_t inode);
int bpc_attribCache_getDirEntryCnt(bpc_attribCache_info *ac, char *path);
ssize_t bpc_attribCache_getDirEntries(bpc_attribCache_info *ac, char *path, char *entries, ssize_t entrySize);
void bpc_attribCache_flush(bpc_attribCache_info *ac, int all, char *path);
void bpc_attribCache_getFullMangledPath(bpc_attribCache_info *ac, char *path, char *dirName, int backupNum);

#endif

bpc_attrib.c  view on Meta::CPAN

 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, visit the http://fsf.org website.
 */

#include "backuppc.h"

/*
 * Type of attribute file.  This is saved as a magic number at the
 * start of the file.  This type is for V3 and earlier.
 */
#define BPC_ATTRIB_TYPE_UNIX    (0x17555555)

/*
 * super set of UNIX, including extended attribs and digest, for 4.x+
 */
#define BPC_ATTRIB_TYPE_XATTR   (0x17565353)

/*
 * starting in 4.x, attrib files in the pc backup tree are
 * just digests that give the location of the real attrib file
 * in the pool.  attrib files written in the pc backup tree
 * start with this magic number, followed by the digest.
 */
#define BPC_ATTRIB_TYPE_DIGEST  (0x17585451)

static char *FileType2Text[] = {
    "file",
    "hardlink",
    "symlink",
    "chardev",
    "blockdev",

bpc_attrib.c  view on Meta::CPAN

    fileDest->type      = fileSrc->type;
    fileDest->compress  = fileSrc->compress;
    fileDest->mode      = fileSrc->mode;
    fileDest->isTemp    = fileSrc->isTemp;
    fileDest->uid       = fileSrc->uid;
    fileDest->gid       = fileSrc->gid;
    fileDest->nlinks    = fileSrc->nlinks;
    fileDest->mtime     = fileSrc->mtime;
    fileDest->size      = fileSrc->size;
    fileDest->inode     = fileSrc->inode;
    fileDest->backupNum = fileSrc->backupNum;
    if ( fileSrc->digest.len > 0 || overwriteEmptyDigest ) {
        fileDest->digest = fileSrc->digest;
    }
    bpc_hashtable_iterate(&fileDest->xattrHT, (void*)bpc_attrib_xattrDestroy, NULL);
    bpc_hashtable_erase(&fileDest->xattrHT);
    bpc_hashtable_iterate(&fileSrc->xattrHT, (void*)bpc_attrib_xattrCopy, fileDest);
}

/*
 * Copy all the attributes from fileSrc to fileDest.  fileDest should already have a

bpc_attrib.c  view on Meta::CPAN

    bpc_attrib_xattrDeleteAll(file);
    xattrNumEntries = getVarInt(&bufP, bufEnd);
    if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_attrib_buf2fileFull: xattrNumEntries = %d\n", xattrNumEntries);
    bufP = bpc_attrib_buf2file(file, bufP, bufEnd, xattrNumEntries, NULL);
    return bufP;
}

/*
 * Read the attribute file at dirPath/attribFilePath and populate dir
 */
int bpc_attrib_dirRead(bpc_attrib_dir *dir, char *dirPath, char *attribFilePath, int backupNum)
{
    char attribPath[BPC_MAXPATHLEN];
    bpc_fileZIO_fd fd;
    size_t nRead;
    uint32 magic = 0;
    uchar buf[8 * 65536], *bufP;
    STRUCT_STAT st;
    char *p, *attribFileName;

    bpc_attrib_attribFilePath(attribPath, dirPath, attribFilePath);

bpc_attrib.c  view on Meta::CPAN

            close(fdNum);
            unlink(attribPath);
            if ( BPC_LogLevel >= 4 ) bpc_logMsgf("bpc_attrib_dirRead: replaced %s with %s\n",
                                                    attribPath, attribPathNew);
        }
    }

    if ( dir->digest.len > 0 ) {
        /*
         * Handle V4+ case - open the pool file directly
         * For V3, digest.len == 0 since we opened the attrib file above (it is stored hardlinked in the backup
         * directory; there is no digest)
         */
        bpc_digest_md52path(attribPath, dir->compress, &dir->digest);
        if ( bpc_fileZIO_open(&fd, attribPath, 0, dir->compress) ) {
            bpc_logErrf("bpc_attrib_dirRead: can't open %s\n", attribPath);
            return -1;
        }
        nRead = bpc_fileZIO_read(&fd, buf, sizeof(buf));
        if ( nRead < 4 ) {
            bpc_logErrf("bpc_attrib_dirRead: can't read at least 4 bytes from %s\n", attribPath);

bpc_attrib.c  view on Meta::CPAN

             * After we consume the next varint, we can safely NULL-terminate
             * the fileName, which allows us to look up or create the file entry.
             */
            fileName = (char*)bufP;
            bufP    += fileNameLen;
            xattrNumEntries = getVarInt(&bufP, buf + nRead);
            fileName[fileNameLen] = '\0';

            file = bpc_attrib_fileGet(dir, fileName, 1);
            bpc_attrib_fileInit(file, fileName, xattrNumEntries);
            file->backupNum = backupNum;

            bufP = bpc_attrib_buf2file(file, bufP, buf + nRead, xattrNumEntries, &xattrFixup);
            dir->needRewrite |= xattrFixup;
            if ( bufP > buf + nRead ) {
                /*
                 * Need to get more data and try again.  We have allocated file->name,
                 * and perhaps partially filled the xattr structure, which will be ok
                 * on the retry since the same structure will be used.
                 */
                if ( retry ) {

bpc_attrib.c  view on Meta::CPAN

            bpc_attrib_fileInit(file, fileName, 0);

            file->type      = type;
            file->mode      = getVarInt_v3(&bufP, buf + nRead);
            file->uid       = getVarInt_v3(&bufP, buf + nRead);
            file->gid       = getVarInt_v3(&bufP, buf + nRead);
            sizeDiv4GB      = getVarInt_v3(&bufP, buf + nRead);
            file->size      = (sizeDiv4GB << 32) + getVarInt_v3(&bufP, buf + nRead);
            file->mtime     = CONV_BUF_TO_UINT32(bufP); bufP += 4;
            file->compress  = dir->compress;
            file->backupNum = backupNum;

            if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_attrib_dirRead(%s): Got v3 file %s: type = %d, mode = 0%o, uid/gid = %d/%d, size = %d\n",
                                                  attribPath, file->name, file->type, file->mode, file->uid, file->gid, file->size);
        }
    } else {
        bpc_logErrf("Unexpected magic number 0x%x read from %s\n", magic, attribPath);
        return -1;
    }
    /* TODO: make sure we are at EOF? */
    bpc_fileZIO_close(&fd);

bpc_attribCache.c  view on Meta::CPAN

 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, visit the http://fsf.org website.
 */

#include "backuppc.h"

#define  BPC_ATTRIBCACHE_DIR_COUNT_MAX        (380)
#define  BPC_ATTRIBCACHE_DIR_HT_SIZE          (512)

void bpc_attribCache_init(bpc_attribCache_info *ac, char *hostName, int backupNum, char *shareNameUM, int compress)
{
    ac->backupNum     = backupNum;
    ac->compress      = compress;
    ac->cacheLruCnt   = 0;
    ac->bkupMergeList = NULL;
    ac->bkupMergeCnt  = 0;
    ac->currentDir[0] = '\0';
    ac->deltaInfo     = NULL;
    strncpy(ac->hostName, hostName, BPC_MAXPATHLEN);
    ac->hostName[BPC_MAXPATHLEN - 1] = '\0';
    strncpy(ac->shareNameUM, shareNameUM, BPC_MAXPATHLEN);
    ac->shareNameUM[BPC_MAXPATHLEN - 1] = '\0';
    bpc_fileNameEltMangle(ac->shareName, BPC_MAXPATHLEN, ac->shareNameUM);
    ac->shareNameLen = strlen(ac->shareName);
    snprintf(ac->hostDir, BPC_MAXPATHLEN, "%s/pc/%s", BPC_TopDir, hostName);
    snprintf(ac->backupTopDir, BPC_MAXPATHLEN, "%s/pc/%s/%d", BPC_TopDir, hostName, ac->backupNum);
    bpc_path_create(ac->backupTopDir);

    bpc_hashtable_create(&ac->attrHT,  BPC_ATTRIBCACHE_DIR_HT_SIZE, sizeof(bpc_attribCache_dir));
    bpc_hashtable_create(&ac->inodeHT, BPC_ATTRIBCACHE_DIR_HT_SIZE, sizeof(bpc_attribCache_dir));
}

void bpc_attribCache_setDeltaInfo(bpc_attribCache_info *ac, bpc_deltaCount_info *deltaInfo)
{
    ac->deltaInfo = deltaInfo;
}

/*
 * Caller is responsible for calling malloc for bkupList.
 */
void bpc_attribCache_setMergeList(bpc_attribCache_info *ac, bpc_backup_info *bkupList, int bkupCnt)
{
    ac->bkupMergeList = bkupList;
    ac->bkupMergeCnt  = bkupCnt;
}

static void bpc_attribCache_destroyEntry(bpc_attribCache_dir *attr)
{
    bpc_attrib_dirDestroy(&attr->dir);
}

bpc_attribCache.c  view on Meta::CPAN


void bpc_attribCache_setCurrentDirectory(bpc_attribCache_info *ac, char *dir)
{
    char *p;
    snprintf(ac->currentDir, BPC_MAXPATHLEN, "%s", dir);
    p = ac->currentDir + strlen(ac->currentDir) - 1;
    while ( p >= ac->currentDir && p[0] == '/' ) *p-- = '\0';
}

/*
 * Given a backup path, split it into the directory, file name, and path to the directory (starting
 * with the share name, ie: relative to ac->backupTopDir).
 *
 * splitPath will strip initial "./" and trailing "/." or "/" before splitting the path, but isn't
 * capable of handling paths with "/." in the middle, or ".." anywhere.
 */
static void splitPath(bpc_attribCache_info *ac, char *dir, char *fileName, char *attribPath, char *path)
{
    char *dirOrig = dir;
    char fullPath[2*BPC_MAXPATHLEN];
    size_t pathLen;

bpc_attribCache.c  view on Meta::CPAN

    bpc_attrib_dirInit(&attr->dir, ac->compress);
    attr->dirty  = 0;
    attr->dirOk  = 0;
    attr->lruCnt = ac->cacheLruCnt++;

    if ( ac->bkupMergeCnt > 0 ) {
        int i;
        char topDir[2*BPC_MAXPATHLEN], fullAttribPath[2*BPC_MAXPATHLEN];

        /*
         * Merge multiple attrib files to create the "view" for this backup.
         * There are two cases: merging forward for v3, or merging in reverse
         * for v4+.  bkupMergeList is already in the order we need.
         */
        for ( i = 0 ; i < ac->bkupMergeCnt ; i++ ) {
            bpc_attrib_dir dir;
            ssize_t entrySize;
            char *entries, *entry;

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

bpc_attribCache.c  view on Meta::CPAN

                    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;
                    }
                    if ( !attribDirExists ) {
                        /*
                         * nothing to update here - keep going
                         */

bpc_attribCache.c  view on Meta::CPAN

                        bpc_attrib_file *fileDest;

                        if ( !(fileDest = bpc_attrib_fileGet(&attr->dir, entry, 1)) ) return NULL;
                        if ( fileDest->key.key == entry ) {
                            /*
                             * new entry - initialize
                             */
                            bpc_attrib_fileInit(fileDest, entry, 0);
                        }
                        bpc_attrib_fileCopy(fileDest, file);
                        fileDest->backupNum = ac->bkupMergeList[i].num;
                    }
                }
            } else {
                bpc_logErrf("bpc_attribCache_loadPath(%s/%s): can't malloc %lu bytes for entries\n",
                                    topDir, attribPath, (unsigned long)entrySize);
                if ( entries ) free(entries);
                bpc_attrib_dirDestroy(&dir);
                return NULL;
            }
            free(entries);
            bpc_attrib_dirDestroy(&dir);
        }
    } else {
        /*
         * non-merge case - read the single attrib file
         */
        if ( (status = bpc_attrib_dirRead(&attr->dir, ac->backupTopDir, attribPath, ac->backupNum)) ) {
            bpc_logErrf("bpc_attribCache_loadPath: bpc_attrib_dirRead(%s, %s) returned %d\n", ac->backupTopDir, attribPath, status);
        }
        if ( bpc_attrib_dirNeedRewrite(&attr->dir) ) {
            attr->dirty = 1;
        }
        /*
         * remove any extraneous BPC_FTYPE_DELETED file types
         */
	bpc_hashtable_iterate(&attr->dir.filesHT, (void*)bpc_attribCache_removeDeletedEntries, attr);
    }
    if ( attr->dirty ) {

bpc_attribCache.c  view on Meta::CPAN

    strcpy(attr->key.key, attribPath);
    bpc_attrib_dirInit(&attr->dir, ac->compress);
    attr->dirty  = 0;
    attr->dirOk  = 1;
    attr->lruCnt = ac->cacheLruCnt++;
    if ( ac->bkupMergeCnt > 0 ) {
        int i;
        char inodeDir[2*BPC_MAXPATHLEN], fullAttribPath[2*BPC_MAXPATHLEN];

        /*
         * Merge multiple attrib files to create the "view" for this backup.
         * There is only one case here, v4, since v3 didn't have inodes. 
         */
        for ( i = 0 ; i < ac->bkupMergeCnt ; i++ ) {
            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_attribCache.c  view on Meta::CPAN

                return NULL;
            }
            free(entries);
            bpc_attrib_dirDestroy(&dir);
        }
    } else {
        /*
         * non-merge case - read the single attrib file
         */
        char inodeDir[2*BPC_MAXPATHLEN];
        snprintf(inodeDir, sizeof(inodeDir), "%s/%s", ac->backupTopDir, attribDir);

        if ( (status = bpc_attrib_dirRead(&attr->dir, inodeDir, attribFile, ac->backupNum)) ) {
            bpc_logErrf("bpc_attribCache_loadInode: bpc_attrib_dirRead(%s/%s) returned %d\n", inodeDir, attribFile, status);
        }
        if ( bpc_attrib_dirNeedRewrite(&attr->dir) ) {
            attr->dirty = 1;
        }
    }
    if ( attr->dirty ) {
        if ( BPC_LogLevel >= 8 ) bpc_logMsgf("bpc_attribCache_loadInode: will rewrite path = %s -> dir = %s, fileName = %s\n", attribPath, attribDir, attribFile);
    }
    if ( bpc_hashtable_entryCount(&ac->inodeHT) > BPC_ATTRIBCACHE_DIR_COUNT_MAX ) {

bpc_attribCache.c  view on Meta::CPAN

        if ( BPC_LogLevel >= 9 ) bpc_logMsgf("bpc_attribCache_dirWrite: comparing %s vs key %s\n", info->path, attr->key.key);
        if ( strncmp(info->path, attr->key.key, info->pathLen)
                || (((char*)attr->key.key)[info->pathLen] != '/' && ((char*)attr->key.key)[info->pathLen] != '\0') ) {
            if ( BPC_LogLevel >= 9 ) bpc_logMsgf("bpc_attribCache_dirWrite: skipping %s (doesn't match %s)\n", (char*)attr->key.key, info->path);
            return;
        }
    }
    if ( !info->ac->readOnly && attr->dirty ) {
        bpc_digest *oldDigest = bpc_attrib_dirDigestGet(&attr->dir);
        if ( BPC_LogLevel >= 6 ) bpc_logMsgf("bpc_attribCache_dirWrite: writing %s/%s with %d entries (oldDigest = 0x%02x%02x...)\n",
                                            info->ac->backupTopDir, (char*)attr->key.key, bpc_hashtable_entryCount(&attr->dir.filesHT),
                                            oldDigest ? oldDigest->digest[0] : 0, oldDigest ? oldDigest->digest[1] : 0);
        if ( (status = bpc_attrib_dirWrite(info->ac->deltaInfo, &attr->dir, info->ac->backupTopDir, attr->key.key, oldDigest)) ) {
            bpc_logErrf("bpc_attribCache_dirWrite: failed to write attributes for dir %s\n", (char*)attr->key.key);
            info->errorCnt++;
        }
    }

    /*
     * Now deallocate memory
     */
    bpc_attrib_dirDestroy(&attr->dir);
    if ( attr->key.key ) free(attr->key.key);

bpc_attribCache.c  view on Meta::CPAN

        info.ht = &ac->attrHT;
        bpc_hashtable_iterate(&ac->attrHT, (void*)bpc_attribCache_dirWrite, &info);
        info.ht = &ac->inodeHT;
        bpc_hashtable_iterate(&ac->inodeHT, (void*)bpc_attribCache_dirWrite, &info);
    }
    if ( info.errorCnt ) {
        /*
         * Any errors likely mean the deltas are probably out of sync with the
         * file system, so request an fsck.
         */
        bpc_poolRefRequestFsck(ac->backupTopDir, 1);
    }
}

/*
 * Returns the full mangled path, given a file path.
 */
void bpc_attribCache_getFullMangledPath(bpc_attribCache_info *ac, char *path, char *dirName, int backupNum)
{
    char *p;
    int len;

    do {
        p = dirName;
        while ( dirName[0] == '.' && dirName[1] == '/' ) dirName += 2;
        while ( dirName[0] == '/' ) dirName++;
    } while ( p != dirName );

    if ( backupNum < 0 || ac->bkupMergeCnt <= 0 ) {
        backupNum = ac->backupNum;
    }

    len = snprintf(path, BPC_MAXPATHLEN, "%s/pc/%s/%d/%s", BPC_TopDir, ac->hostName, backupNum, ac->shareName);
    if ( (dirName[0] == '/' && dirName[1] == '\0') || dirName[0] == '\0' || len >= BPC_MAXPATHLEN - 1 ) {
        return;
    }
    path[len++] = '/';
    bpc_fileNameMangle(path + len, BPC_MAXPATHLEN - len, dirName);
}

bpc_dirOps.c  view on Meta::CPAN

 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, visit the http://fsf.org website.
 */

#include "backuppc.h"

/*
 * Create all the directories in the given path.  Path must be non-const.  Trailing '/' characters are removed.
 */
int bpc_path_create(char *path)
{
    char *p = path;
    STRUCT_STAT st;
    int levels = 0;

bpc_fileDigest.c  view on Meta::CPAN

 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, visit the http://fsf.org website.
 */

#include "backuppc.h"

/*
 * Compute the md5 digest of a file. Returns 0 on success
 */
int bpc_fileDigest(char *fileName, int compress, bpc_digest *digest)
{
    md_context md5;
    bpc_fileZIO_fd fd;
    ssize_t nRead;
    uchar buffer[1 << 20];

bpc_fileZIO.c  view on Meta::CPAN

 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, visit the http://fsf.org website.
 */

#include "backuppc.h"

/*
 * A freelist of unused data buffers.
 * We use the first sizeof(void*) bytes of the buffer as a single-linked
 * list, with a NULL at the end.
 */
static void *DataBufferFreeList = (void*)NULL;

/*
 * Open a regular or compressed file for reading or writing/create

bpc_hashtable.c  view on Meta::CPAN

 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, visit the http://fsf.org website.
 */

#include "backuppc.h"

/*
 * Simple freelist of hash table entries.  We maintain a single linked list of
 * unused entries of each size, indexed by the FREELIST_SIZE2IDX() macro.
 *
 * FreeList[0] isn't used,
 * FreeList[1] is a free list of blocks of size 8,
 * FreeList[2] is a free list of blocks of size 16, ...
 *
 * eg, if you ask for a block of size 9, a block of size 16 will be returned.

bpc_lib.c  view on Meta::CPAN

 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, visit the http://fsf.org website.
 */

#include "backuppc.h"

char BPC_TopDir[BPC_MAXPATHLEN];
char BPC_PoolDir[BPC_MAXPATHLEN];
char BPC_CPoolDir[BPC_MAXPATHLEN];
char BPC_PoolDir3[BPC_MAXPATHLEN];
char BPC_CPoolDir3[BPC_MAXPATHLEN];

int BPC_HardLinkMax   = 32000;
int BPC_PoolV3Enabled = 0;
int BPC_TmpFileUnique = -1;

bpc_poolWrite.c  view on Meta::CPAN

 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, visit the http://fsf.org website.
 */

#include "backuppc.h"


static uint32 PoolWriteCnt = 0;

/*
 * Buffer used in various places for copying, comparing etc
 */
#define COMPARE_BUF_SZ     (1 << 20)     /* 1.0 MB */
static uchar TempBuf[2 * COMPARE_BUF_SZ];

bpc_refCount.c  view on Meta::CPAN

 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, visit the http://fsf.org website.
 */

#include "backuppc.h"

/*
 * magic number that appears at the start of the reference count (or delta count file)
 */
#define BPC_POOL_REF_MAGIC    (0x178e553c)

#define CONV_BUF_TO_UINT32(buf)    ((buf)[0] << 24 | (buf)[1] << 16 | (buf)[2] << 8 | (buf)[3])

#define CONV_UINT32_TO_BUF(buf, val)   { *(buf)++ = ((val) >> 24) & 0xff;               \
                                         *(buf)++ = ((val) >> 16) & 0xff;               \

bpc_refCount.c  view on Meta::CPAN

        }
        digestInfo->count = count;
    }

    close(fd);

    return 0;
}

/*
 * Mark this host backup as needing an fsck.  Multiple requests can be supported with
 * unique numbers.  ext == 0 is used for the overall backup process, and it is removed when
 * the backup finished.  Various errors can use other extensions.  If any files are
 * present, an fsck is done either by the next backup, BackupPC_refCountUpdate or
 * BackupPC_fsck.
 */
void bpc_poolRefRequestFsck(char *backupDir, int ext)
{
    char fileName[BPC_MAXPATHLEN];
    int fd;

    snprintf(fileName, sizeof(fileName), "%s/refCnt/needFsck%d", backupDir, ext);
    if ( (fd = open(fileName, O_CREAT | O_WRONLY, 0660)) < 0 ) {
        bpc_logErrf("bpc_poolRefRequestFsck: can't open/create fsck request file %s (errno %d)\n", fileName, errno);
    }
}

/***********************************************************************
 * Reference count deltas - we maintain two hash tables for uncompressed
 * and compressed deltas.
 ***********************************************************************/

bpc_refCount.c  view on Meta::CPAN

            unlink(tempFileName);
            errorCnt++;
        }
        if ( !errorCnt ) {
            bpc_hashtable_erase(&info->refCnt[compress].ht);
        }
    }
    OutputFileCnt++;
    if ( errorCnt ) {
        /*
         * Need to fsck this particular backup on this host
         */
        bpc_poolRefRequestFsck(info->targetDir, getpid());
    }
    return errorCnt;
}

void bpc_poolRefDeltaUpdate(bpc_deltaCount_info *info, int compress, bpc_digest *digest, int32 count)
{
    DigestInfo *digestInfo;

configure.sh  view on Meta::CPAN

ac_compiler_gnu=$ac_cv_c_compiler_gnu



ac_config_headers="$ac_config_headers config.h"



RSYNC_VERSION=0.62

{ $as_echo "$as_me:${as_lineno-$LINENO}: Configuring backuppc-xs $RSYNC_VERSION" >&5
$as_echo "$as_me: Configuring backuppc-xs $RSYNC_VERSION" >&6;}


cat >>confdefs.h <<_ACEOF
#define RSYNC_VERSION "$RSYNC_VERSION"
_ACEOF


LDFLAGS=${LDFLAGS-""}

ac_aux_dir=

configure.sh  view on Meta::CPAN

  $ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi


{ $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5
$as_echo "" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result:     backuppc-xs ${RSYNC_VERSION} configuration successful" >&5
$as_echo "    backuppc-xs ${RSYNC_VERSION} configuration successful" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5
$as_echo "" >&6; }

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

    $numDirEntries = $a->count();
    $a->read($dirPath, $attribFileName);
    $a->write($dirPath, $attribFileName);

    $textType = BackupPC::XS::Attrib::fileType2Text(BPC_FTYPE_....);

=head2 BackupPC::XS::AttribCache

Maintain a cache of directories, with full share/path semantics.

    $ac = BackupPC::XS::AttribCache::new($host, $backupNum, $shareNameUM, $compress);

    $attrHash = $ac->get($fileName, $allocateIfMissing, $dontReadInode);
    $ac->set($fileName, $attrHash, $dontOverwriteInode);
    $ac->delete($fileName);

    $attrHash = $ac->getInode($inode, $allocateIfMissing);
    $ac->setInode($inode, $attrHash);
    $ac->deleteInode($inode);

    $ac->getAll($path, $dontReadInode);

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

    $messageArrayRef = BackupPC::XS::Lib::logMsgGet();
    $errorCnt = BackupPC::XS::Lib::logErrorCntGet;
    BackupPC::XS::Lib::logLevelSet($level);

=head1 EXPORTS

If you specify :all (see SYNOPSIS), then the BPC_FTYPE_ values are exported.

=head1 SEE ALSO

BackupPC, backuppc.sourceforge.net.

rsync-bpc.

=head1 AUTHOR

Craig Barratt, E<lt>cbarratt@users.sourceforge.net<gt>

=head1 COPYRIGHT AND LICENSE

BackupPC code is copyright (C) 2013-2017 Craig Barratt



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