Exemple #1
0
static int maybe_do_delta_stuff(struct asfd *asfd,
	struct sdirs *sdirs, struct sbuf *cb, struct sbuf *p1b,
	struct fzp *ucfp, struct conf **cconfs)
{
	int oldcompressed=0;
	int compression=get_int(cconfs[OPT_COMPRESSION]);

	// If the file type changed, I think it is time to back it up again
	// (for example, EFS changing to normal file, or back again).
	if(cb->path.cmd!=p1b->path.cmd)
		return process_new_file(sdirs, cconfs, cb, p1b, ucfp);

	// mtime is the actual file data.
	// ctime is the attributes or meta data.
	if(cb->statp.st_mtime==p1b->statp.st_mtime
	  && cb->statp.st_ctime==p1b->statp.st_ctime)
	{
		// got an unchanged file
		//logp("got unchanged file: %s %c %c\n",
		//	cb->path.buf, cb->path.cmd, p1b->path.cmd);
		return process_unchanged_file(p1b, cb, ucfp, cconfs);
	}

	if(cb->statp.st_mtime==p1b->statp.st_mtime
	  && cb->statp.st_ctime!=p1b->statp.st_ctime)
	{
		// File data stayed the same, but attributes or meta data
		// changed. We already have the attributes, but may need to get
		// extra meta data.
		// FIX THIS horrible mess.
		if(cb->path.cmd==CMD_ENC_METADATA
		  || p1b->path.cmd==CMD_ENC_METADATA
		// FIX THIS: make unencrypted metadata use the librsync
		  || cb->path.cmd==CMD_METADATA
		  || p1b->path.cmd==CMD_METADATA
		  || cb->path.cmd==CMD_VSS
		  || p1b->path.cmd==CMD_VSS
		  || cb->path.cmd==CMD_ENC_VSS
		  || p1b->path.cmd==CMD_ENC_VSS
		  || cb->path.cmd==CMD_VSS_T
		  || p1b->path.cmd==CMD_VSS_T
		  || cb->path.cmd==CMD_ENC_VSS_T
		  || p1b->path.cmd==CMD_ENC_VSS_T
		  || cb->path.cmd==CMD_EFS_FILE
		  || p1b->path.cmd==CMD_EFS_FILE)
			return process_new_file(sdirs, cconfs, cb, p1b, ucfp);
		// On Windows, we have to back up the whole file if ctime
		// changed, otherwise things like permission changes do not get
		// noticed. So, in that case, fall through to the changed stuff
		// below.
		// Non-Windows clients finish here.
		else if(!get_int(cconfs[OPT_CLIENT_IS_WINDOWS]))
			return process_unchanged_file(p1b, cb, ucfp, cconfs);
	}

	// Got a changed file.
	//logp("got changed file: %s\n", p1b->path);

	// If either old or new is encrypted, or librsync is off, we need to
	// get a new file.
	// FIX THIS horrible mess.
	if(get_int(cconfs[OPT_LIBRSYNC])
	  || cb->path.cmd==CMD_ENC_FILE
	  || p1b->path.cmd==CMD_ENC_FILE
	  || cb->path.cmd==CMD_ENC_METADATA
	  || p1b->path.cmd==CMD_ENC_METADATA
	  || cb->path.cmd==CMD_EFS_FILE
	  || p1b->path.cmd==CMD_EFS_FILE
	// FIX THIS: make unencrypted metadata use the librsync
	  || cb->path.cmd==CMD_METADATA
	  || p1b->path.cmd==CMD_METADATA
	  || cb->path.cmd==CMD_VSS
	  || p1b->path.cmd==CMD_VSS
	  || cb->path.cmd==CMD_ENC_VSS
	  || p1b->path.cmd==CMD_ENC_VSS
	  || cb->path.cmd==CMD_VSS_T
	  || p1b->path.cmd==CMD_VSS_T
	  || cb->path.cmd==CMD_ENC_VSS_T
	  || p1b->path.cmd==CMD_ENC_VSS_T)
		return process_new_file(sdirs, cconfs, cb, p1b, ucfp);

	// Get new files if they have switched between compression on or off.
	if(cb->protocol1->datapth.buf
	  && dpth_protocol1_is_compressed(cb->compression,
	    cb->protocol1->datapth.buf))
		oldcompressed=1;
	if( ( oldcompressed && !compression)
	 || (!oldcompressed &&  compression))
		return process_new_file(sdirs, cconfs, cb, p1b, ucfp);

	// Otherwise, do the delta stuff (if possible).
	if(cmd_is_filedata(p1b->path.cmd))
	{
		if(process_changed_file(asfd, sdirs, cconfs, cb, p1b,
			sdirs->currentdata)) return -1;
	}
	else
	{
		if(changed_non_file(p1b, ucfp, p1b->path.cmd, cconfs))
			return -1;
	}
	sbuf_free_content(cb);
	return 1;
}
Exemple #2
0
// return 1 to say that a file was processed
static int maybe_process_file(struct sbuf *cb, struct sbuf *p1b, FILE *ucfp, const char *currentdata, const char *datadirtmp, const char *deltmppath, struct dpth *dpth, int *resume_partial, struct cntr *cntr, struct config *cconf)
{
	int pcmp;
//	logp("in maybe_proc %s\n", p1b->path);
	if(!(pcmp=sbuf_pathcmp(cb, p1b)))
	{
		int oldcompressed=0;

		// If the file type changed, I think it is time to back it
		// up again (for example, EFS changing to normal file, or
		// back again).
		if(cb->cmd!=p1b->cmd)
			return process_new_file(cb, p1b, ucfp, currentdata,
				datadirtmp, deltmppath,
				dpth, resume_partial,
				cntr, cconf);

		// mtime is the actual file data.
		// ctime is the attributes or meta data.
		if(cb->statp.st_mtime==p1b->statp.st_mtime
		  && cb->statp.st_ctime==p1b->statp.st_ctime)
		{
			// got an unchanged file
			//logp("got unchanged file: %s %c %c\n", cb->path, cb->cmd, p1b->cmd);
			return process_unchanged_file(cb, ucfp, cntr);
		}

		if(cb->statp.st_mtime==p1b->statp.st_mtime
		  && cb->statp.st_ctime!=p1b->statp.st_ctime)
		{
			// File data stayed the same, but attributes or meta
			// data changed. We already have the attributes, but
			// may need to get extra meta data.
			if(cb->cmd==CMD_ENC_METADATA
			  || p1b->cmd==CMD_ENC_METADATA
			// TODO: make unencrypted metadata use the librsync
			  || cb->cmd==CMD_METADATA
			  || p1b->cmd==CMD_METADATA
			  || cb->cmd==CMD_VSS
			  || p1b->cmd==CMD_VSS
			  || cb->cmd==CMD_ENC_VSS
			  || p1b->cmd==CMD_ENC_VSS
			  || cb->cmd==CMD_VSS_T
			  || p1b->cmd==CMD_VSS_T
			  || cb->cmd==CMD_ENC_VSS_T
			  || p1b->cmd==CMD_ENC_VSS_T
			  || cb->cmd==CMD_EFS_FILE
			  || p1b->cmd==CMD_EFS_FILE)
				return process_new_file(cb,
					p1b, ucfp, currentdata,
					datadirtmp, deltmppath,
					dpth, resume_partial,
					cntr, cconf);
			else
				return process_unchanged_file(cb, ucfp, cntr);
		}

		// Got a changed file.
		//logp("got changed file: %s\n", p1b->path);

		// If either old or new is encrypted, or librsync is off,
		// we need to get a new file.
		if(!cconf->librsync
		  || cb->cmd==CMD_ENC_FILE
		  || p1b->cmd==CMD_ENC_FILE
		  || cb->cmd==CMD_ENC_METADATA
		  || p1b->cmd==CMD_ENC_METADATA
		  || cb->cmd==CMD_EFS_FILE
		  || p1b->cmd==CMD_EFS_FILE
		// TODO: make unencrypted metadata use the librsync
		  || cb->cmd==CMD_METADATA
		  || p1b->cmd==CMD_METADATA
		  || cb->cmd==CMD_VSS
		  || p1b->cmd==CMD_VSS
		  || cb->cmd==CMD_ENC_VSS
		  || p1b->cmd==CMD_ENC_VSS
		  || cb->cmd==CMD_VSS_T
		  || p1b->cmd==CMD_VSS_T
		  || cb->cmd==CMD_ENC_VSS_T
		  || p1b->cmd==CMD_ENC_VSS_T)
			return process_new_file(cb, p1b, ucfp, currentdata,
				datadirtmp, deltmppath,
				dpth, resume_partial,
				cntr, cconf);

		// Get new files if they have switched between compression on
		// or off.
		if(cb->datapth && dpth_is_compressed(cb->compression, cb->datapth))
			oldcompressed=1;
		if( ( oldcompressed && !cconf->compression)
		 || (!oldcompressed &&  cconf->compression))
			return process_new_file(cb, p1b, ucfp, currentdata,
				datadirtmp, deltmppath,
				dpth, resume_partial,
				cntr, cconf);

		// Otherwise, do the delta stuff (if possible).
		if(filedata(p1b->cmd))
		{
			if(process_changed_file(cb, p1b, currentdata,
				datadirtmp, deltmppath, resume_partial,
				cntr, cconf)) return -1;
		}
		else
		{
			if(changed_non_file(p1b, ucfp, p1b->cmd, cntr))
				return -1;
		}
		free_sbuf(cb);
		return 1;
	}
	else if(pcmp>0)
	{
		//logp("ahead: %s\n", p1b->path);
		// ahead - need to get the whole file
		if(process_new(p1b, ucfp, currentdata, datadirtmp, deltmppath,
			dpth, resume_partial, cntr, cconf)) return -1;
		// do not free
		return 1;
	}
	else
	{
		//logp("behind: %s\n", p1b->path);
		// behind - need to read more from the old
		// manifest
		// Count a deleted file - it was in the old manifest but not
		// the new.
		do_filecounter_deleted(cntr, cb->cmd);
	}
	return 0;
}
Exemple #3
0
// TODO: Some of the repeated code in this can be factored out.
static int resume_partial_changed_file(struct sbuf *cb, struct sbuf *p1b, const char *currentdata, const char *curpath, const char *datadirtmp, const char *deltmppath, struct config *cconf, struct cntr *cntr)
{
	int ret=0;
	int istreedata=0;
	struct stat dstatp;
	struct stat cstatp;
	char *partial=NULL;
	char *partialdir=NULL;
	char *zdeltmp=NULL;
	struct sbuf xb;

	init_sbuf(&xb);
	xb.cmd=cb->cmd;
	xb.compression=cb->compression;
	xb.path=strdup(cb->path);
	xb.statbuf=strdup(cb->statbuf);
	xb.datapth=strdup(p1b->datapth);
	xb.endfile=strdup(cb->endfile);

	logp("Resume partial changed file: %s\n", xb.path);
	if(!lstat(deltmppath, &dstatp) && S_ISREG(dstatp.st_mode)
	     && !lstat(curpath, &cstatp) && S_ISREG(cstatp.st_mode))
	{
		int junk=0;
		gzFile dzp=NULL;
		FILE *dfp=NULL;
		struct stat pstatp;
		if(!(partialdir=prepend_s(datadirtmp, "p", strlen("p")))
		  || !(partial=prepend_s(partialdir,
			xb.datapth, strlen(xb.datapth)))
		  || build_path(partialdir, xb.datapth, strlen(xb.datapth),
			&partial, partialdir))
		{
			ret=-1;
			goto end;
		}

		if(!lstat(partial, &pstatp))
		{
			if(!S_ISREG(pstatp.st_mode))
			{
				logp("%s is not a regular file\n", partial);
				goto actuallyno;
			}
			if(pstatp.st_size>cstatp.st_size)
			{
				// Looks like a previously resumed file.
				if(xb.compression)
				{
					// Need to read and recreate it, in
					// case it was not fully created.
					if(!(zdeltmp=prepend(deltmppath,
						".z", strlen(".z"),
						0 /* no slash */))
					  || !(dzp=gzopen_file(zdeltmp, "wb"))
					  || copy_gzpath_to_gzFile(partial,
						dzp)
					  || do_rename(zdeltmp, partial))
					{
						ret=-1;
						goto end;
					}
				}
				else
				{
					// Append to the existing one.
					if(!(dfp=open_file(partial, "ab")))
					{
						ret=-1;
						goto end;
					}
				}
			}
			else
			{
				unlink(partial);
				// Copy the whole of p1b->sigfp/sigzp to
				// partial.
				if(xb.compression)
				{
					if(!(dzp=gzopen_file(partial, "wb"))
					  || copy_gzFile_to_gzFile(p1b->sigzp,
						dzp))
					{
						ret=-1;
						goto end;
					}
				}
				else
				{
					if(!(dfp=open_file(partial, "wb"))
					  || copy_File_to_File(p1b->sigfp, dfp))
					{
						ret=-1;
						goto end;
					}
				}
			}
			// Now, copy the whole of deltmppath onto partial.
			// dzp or dfp will be open by this point.
			if(xb.compression)
			{
				if(copy_gzpath_to_gzFile(deltmppath, dzp))
				{
					ret=-1;
					goto end;
				}
			}
			else
			{
				if(copy_path_to_File(deltmppath, dfp))
				{
					ret=-1;
					goto end;
				}
			}
		}
		else
		{
		//	Copy the whole of p1b->sigfp/sigzp onto partial.
		//	Copy the whole of deltmppath onto partial.
			if(xb.compression)
			{
				// There is no partial, this creates it.
				if(!(dzp=gzopen_file(partial, "wb"))
				  || copy_gzFile_to_gzFile(p1b->sigzp, dzp))
				{
					ret=-1;
					goto end;
				}
			}
			else
			{
				// There is no partial, this creates it.
				if(!(dfp=open_file(partial, "wb"))
				  || copy_File_to_File(p1b->sigfp, dfp))
				{
					ret=-1;
					goto end;
				}
			}
			if(xb.compression)
			{
				if(copy_gzpath_to_gzFile(deltmppath, dzp))
				{
					ret=-1;
					goto end;
				}
			}
			else
			{
				if(copy_path_to_File(deltmppath, dfp))
				{
					ret=-1;
					goto end;
				}
			}
		}
		if(dfp && close_fp(&dfp))
		{
			ret=-1;
			goto end;
		}
		if(dzp && gzclose_fp(&dzp))
		{
			ret=-1;
			goto end;
		}
		// Use partial as the basis for a librsync transfer.
		
		// So, we have created a new directory beginning with 'p',
		// and moved the partial download to it.
		// We can now use the partial file as the basis of a librsync
		// transfer. 
		if(process_changed_file(&xb, p1b, partialdir, NULL, NULL,
			&junk /* resume_partial=0 */,
			cntr, cconf))
		{
			ret=-1;
			goto end;
		}

		goto end;
	}

actuallyno:
	logp("Actually, no - just forget the previous delta\n");
end:
	if(partialdir) free(partialdir);
	if(partial) free(partial);
	if(zdeltmp) free(zdeltmp);
	free_sbuf(&xb);
	return ret;
}
Exemple #4
0
static int resume_partial_new_file(struct sbuf *p1b, struct cntr *cntr, const char *currentdata, const char *datadirtmp, const char *deltmppath, struct dpth *dpth, struct config *cconf)
{
	int ret=0;
	int junk=0;
	struct sbuf cb;
	char *rpath=NULL;
	int istreedata=0;
	struct stat statp;
	char *partial=NULL;
	char *partialdir=NULL;
	char *zdeltmp=NULL;
	// It does not matter what this checksum is set to.
	// This is just to get an endfile string in the format that
	// process_changed_file expects.
	unsigned char checksum[18]="0123456789ABCDEF";

	// Need to set up a fake current sbuf.
	init_sbuf(&cb);
	cb.cmd=p1b->cmd;
	cb.compression=p1b->compression;
	cb.path=strdup(p1b->path);
	cb.statbuf=strdup(p1b->statbuf);
	if(!(rpath=set_new_datapth(&cb, datadirtmp, dpth, &istreedata, cconf)))
	{
		ret=-1;
		goto end;
	}

	if(!(partialdir=prepend_s(datadirtmp, "p", strlen("p")))
	  || !(partial=prepend_s(partialdir,
		cb.datapth, strlen(cb.datapth)))
	  || build_path(partialdir, cb.datapth, strlen(cb.datapth),
		&partial, partialdir))
	{
		ret=-1;
		goto end;
	}

	if(!lstat(partial, &statp) && S_ISREG(statp.st_mode))
	{
		// A previous resume was going on.
		// Need to concatenate the possible delta onto the partial
		// file.
		FILE *dfp=NULL;
		gzFile dzp=NULL;
		logp("Resume previously resumed partial new file: %s %s\n",
			cb.path, rpath);

		if(!(cb.endfile=strdup(
			get_endfile_str(statp.st_size, checksum))))
		{
			ret=-1;
			goto end;
		}
		if(cb.compression)
		{
			// Recreate partial, in case it was only partially
			// written and consequently has gz errors.
			if(!(zdeltmp=prepend(deltmppath, ".z", strlen(".z"),
				0 /* no slash */))
			  || !(dzp=gzopen_file(zdeltmp, "wb"))
			  || copy_gzpath_to_gzFile(partial, dzp)
			  || do_rename(zdeltmp, partial))
			{
				ret=-1;
				goto end;
			}
		}
		else
		{
			// Just append to the existing one.
			if(!(dfp=open_file(partial, "ab")))
			{
				ret=-1;
				goto end;
			}
		}
		if(!lstat(deltmppath, &statp) && S_ISREG(statp.st_mode))
		{
			if(cb.compression)
			{
				if(copy_gzpath_to_gzFile(deltmppath, dzp))
				{
					ret=-1;
					goto end;
				}
			}
			else
			{
				if(copy_path_to_File(deltmppath, dfp))
				{
					ret=-1;
					goto end;
				}
			}
		}
		if(dfp && close_fp(&dfp))
		{
			ret=-1;
			goto end;
		}
		if(dzp && gzclose_fp(&dzp))
		{
			ret=-1;
			goto end;
		}
		if(process_changed_file(&cb, p1b, partialdir, NULL, NULL,
			&junk /* resume_partial=0 */,
			cntr, cconf))
		{
			ret=-1;
			goto end;
		}
		if(!istreedata) incr_dpth(dpth, cconf);

		goto end;
	}

	logp("Resume partial new file: %s %s\n", cb.path, rpath);
	if(!lstat(rpath, &statp) && S_ISREG(statp.st_mode))
	{
		if(!(cb.endfile=strdup(
			get_endfile_str(statp.st_size, checksum))))
		{
			ret=-1;
			goto end;
		}
		// If compression is on, be careful with gzip unexpected
		// end of file errors.
		// Otherwise, just rename the whole file.
		unlink(partial);
		if(cb.compression)
		{
			if(copy_gzpath_to_gzpath(rpath, partial))
			{
				logp("Error in copy_gzpath_to_gzpath\n");
				ret=-1;
				goto end;
			}
			// delete the original.
			if(unlink(rpath))
			{
				logp("Failed to unlink %s: %s\n",
					rpath, strerror(errno));
				return -1;
			}
		}
		else
		{
			if(do_rename(rpath, partial))
			{
				ret=-1;
				goto end;
			}
		}
		// So, we have created a new directory beginning with 'p',
		// and moved the partial download to it.
		// We can now use the partial file as the basis of a librsync
		// transfer.
		if(process_changed_file(&cb, p1b, partialdir, NULL, NULL,
			&junk /* resume_partial=0 */,
			cntr, cconf))
		{
			ret=-1;
			goto end;
		}
		if(!istreedata) incr_dpth(dpth, cconf);
		goto end;
	}

	logp("Actually, no - just treat it as completely new\n");
end:
	if(rpath) free(rpath);
	if(partialdir) free(partialdir);
	if(partial) free(partial);
	if(zdeltmp) free(zdeltmp);
	free_sbuf(&cb);
	return ret;
}
Exemple #5
0
// return 1 to say that a file was processed
static int maybe_process_file(struct asfd *asfd,
	struct sdirs *sdirs, struct conf *cconf,
	struct sbuf *cb, struct sbuf *p1b, FILE *ucfp,
	struct dpthl *dpthl)
{
	int pcmp;
	if(!(pcmp=sbuf_pathcmp(cb, p1b)))
	{
		int oldcompressed=0;

		// If the file type changed, I think it is time to back it
		// up again (for example, EFS changing to normal file, or
		// back again).
		if(cb->path.cmd!=p1b->path.cmd)
			return process_new_file(sdirs, cconf, cb, p1b, ucfp,
				dpthl);

		// mtime is the actual file data.
		// ctime is the attributes or meta data.
		if(cb->statp.st_mtime==p1b->statp.st_mtime
		  && cb->statp.st_ctime==p1b->statp.st_ctime)
		{
			// got an unchanged file
			//logp("got unchanged file: %s %c %c\n", cb->path, cb->cmd, p1b->cmd);
			return process_unchanged_file(cb, ucfp, cconf);
		}

		if(cb->statp.st_mtime==p1b->statp.st_mtime
		  && cb->statp.st_ctime!=p1b->statp.st_ctime)
		{
			// File data stayed the same, but attributes or meta
			// data changed. We already have the attributes, but
			// may need to get extra meta data.
			if(cb->path.cmd==CMD_ENC_METADATA
			  || p1b->path.cmd==CMD_ENC_METADATA
			// TODO: make unencrypted metadata use the librsync
			  || cb->path.cmd==CMD_METADATA
			  || p1b->path.cmd==CMD_METADATA
			  || cb->path.cmd==CMD_VSS
			  || p1b->path.cmd==CMD_VSS
			  || cb->path.cmd==CMD_ENC_VSS
			  || p1b->path.cmd==CMD_ENC_VSS
			  || cb->path.cmd==CMD_VSS_T
			  || p1b->path.cmd==CMD_VSS_T
			  || cb->path.cmd==CMD_ENC_VSS_T
			  || p1b->path.cmd==CMD_ENC_VSS_T
			  || cb->path.cmd==CMD_EFS_FILE
			  || p1b->path.cmd==CMD_EFS_FILE)
				return process_new_file(sdirs, cconf, cb,
					p1b, ucfp, dpthl);
			// On Windows, we have to back up the whole file if
			// ctime changed, otherwise things like permission
			// changes do not get noticed. So, in that case, fall
			// through to the changed stuff below.
			// Non-Windows clients finish here.
			else if(!cconf->client_is_windows)
				return process_unchanged_file(cb, ucfp, cconf);
		}

		// Got a changed file.
		//logp("got changed file: %s\n", p1b->path);

		// If either old or new is encrypted, or librsync is off,
		// we need to get a new file.
		if(!cconf->librsync
		  || cb->path.cmd==CMD_ENC_FILE
		  || p1b->path.cmd==CMD_ENC_FILE
		  || cb->path.cmd==CMD_ENC_METADATA
		  || p1b->path.cmd==CMD_ENC_METADATA
		  || cb->path.cmd==CMD_EFS_FILE
		  || p1b->path.cmd==CMD_EFS_FILE
		// TODO: make unencrypted metadata use the librsync
		  || cb->path.cmd==CMD_METADATA
		  || p1b->path.cmd==CMD_METADATA
		  || cb->path.cmd==CMD_VSS
		  || p1b->path.cmd==CMD_VSS
		  || cb->path.cmd==CMD_ENC_VSS
		  || p1b->path.cmd==CMD_ENC_VSS
		  || cb->path.cmd==CMD_VSS_T
		  || p1b->path.cmd==CMD_VSS_T
		  || cb->path.cmd==CMD_ENC_VSS_T
		  || p1b->path.cmd==CMD_ENC_VSS_T)
			return process_new_file(sdirs, cconf, cb, p1b, ucfp,
				dpthl);

		// Get new files if they have switched between compression on
		// or off.
		if(cb->burp1->datapth.buf
		  && dpthl_is_compressed(cb->compression, cb->burp1->datapth.buf))
			oldcompressed=1;
		if( ( oldcompressed && !cconf->compression)
		 || (!oldcompressed &&  cconf->compression))
			return process_new_file(sdirs, cconf, cb, p1b, ucfp,
				dpthl);

		// Otherwise, do the delta stuff (if possible).
		if(filedata(p1b->path.cmd))
		{
			if(process_changed_file(asfd, sdirs, cconf, cb, p1b,
				sdirs->currentdata)) return -1;
		}
		else
		{
			if(changed_non_file(p1b, ucfp, p1b->path.cmd, cconf))
				return -1;
		}
		sbuf_free_content(cb);
		return 1;
	}
	else if(pcmp>0)
	{
		//logp("ahead: %s\n", p1b->path);
		// ahead - need to get the whole file
		if(process_new(sdirs, cconf, p1b, ucfp, dpthl)) return -1;
		// do not free
		return 1;
	}
	else
	{
		//logp("behind: %s\n", p1b->path);
		// behind - need to read more from the old
		// manifest
		// Count a deleted file - it was in the old manifest but not
		// the new.
		cntr_add_deleted(cconf->cntr, cb->path.cmd);
	}
	return 0;
}