Esempio n. 1
0
// The failure conditions here are dealt with by the rubble cleaning code.
static int delete_backup(struct sdirs *sdirs, const char *cname, struct bu *bu,
	const char *manual_delete)
{
	logp("deleting %s backup %" PRId64 "\n", cname, bu->bno);

	if(sdirs->global_sparse)
	{
		const char *candidate_str=bu->path+strlen(sdirs->base)+1;
		if(remove_from_global_sparse(
			sdirs->global_sparse, candidate_str))
				return -1;
	}

	if(!bu->next && !bu->prev)
	{
		// The current, and only, backup.
		if(do_rename_w(bu->path, sdirs->deleteme, cname, bu))
			return -1;
		// If interrupted here, there will be a dangling 'current'
		// symlink.
		if(unlink(sdirs->current))
		{
			logp("unlink %s: %s\n",
				sdirs->current, strerror(errno));
			return -1;
		}
		return recursive_delete_w(sdirs, bu, manual_delete);
	}
	if(!bu->next && bu->prev)
	{
		// The current backup. There are other backups left.
		// Need to point the symlink at the previous backup.
		const char *target=NULL;
		
		target=bu->prev->basename;
		unlink(sdirs->currenttmp);
		if(do_symlink(target, sdirs->currenttmp))
			return -1;
		// If interrupted here, there is a currenttmp and a current
		// symlink, and they both point to valid directories.
		if(do_rename_w(bu->path, sdirs->deleteme, cname, bu))
			return -1;
		// If interrupted here, there is a currenttmp and a current
		// symlink, and the current link is dangling.
		if(do_rename(sdirs->currenttmp, sdirs->current))
			return -1;
		// If interrupted here, moving the symlink could have failed
		// after current was deleted but before currenttmp was renamed.
		if(recursive_delete_w(sdirs, bu, manual_delete))
			return -1;
		return 0;
	}

	// It is not the current backup.
	if(do_rename_w(bu->path, sdirs->deleteme, cname, bu)
	  || recursive_delete_w(sdirs, bu, manual_delete))
		return -1;
	return 0;
}
Esempio n. 2
0
// The failure conditions here are dealt with by the rubble cleaning code.
int delete_backup(struct sdirs *sdirs, struct conf *conf, struct bu *bu)
{
	logp("deleting %s backup %lu\n", conf->cname, bu->bno);

	if(!bu->next && !bu->prev)
	{
		// The current, and only, backup.
		if(do_rename_w(bu->path, sdirs->deleteme)) return -1;
		// If interrupted here, there will be a dangling 'current'
		// symlink.
		if(unlink(sdirs->current))
		{
			logp("unlink %s: %s\n",
				sdirs->current, strerror(errno));
			return -1;
		}
		return recursive_delete_w(sdirs, bu);
	}
	if(!bu->next && bu->prev)
	{
		// The current backup. There are other backups left.
		// Need to point the symlink at the previous backup.
		const char *target=NULL;
		
		target=bu->prev->basename;
		unlink(sdirs->currenttmp);
		if(symlink(target, sdirs->currenttmp))
		{
			logp("could not symlink '%s' to '%s': %s\n",
				sdirs->currenttmp, target, strerror(errno));
			return -1;
		}
		// If interrupted here, there is a currenttmp and a current
		// symlink, and they both point to valid directories.
		if(do_rename_w(bu->path, sdirs->deleteme))
			return -1;
		// If interrupted here, there is a currenttmp and a current
		// symlink, and the current link is dangling.
		if(do_rename_w(sdirs->currenttmp, sdirs->current))
			return -1;
		// If interrupted here, moving the symlink could have failed
		// after current was deleted but before currenttmp was renamed.
		if(recursive_delete_w(sdirs, bu))
			return -1;
		return 0;
	}

	// It is not the current backup.
	if(do_rename_w(bu->path, sdirs->deleteme)
	  || recursive_delete_w(sdirs, bu))
		return -1;
	return 0;
}