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);