Пример #1
0
static int found_directory(struct asfd *asfd, FF_PKT *ff_pkt, struct conf *conf,
	char *fname, dev_t parent_device, bool top_level)
{
	int rtn_stat;
	DIR *directory;
	char *link=NULL;
	size_t link_len;
	size_t len;
	int nbret=0;
	int count=0;
	bool recurse;
	dev_t our_device;
	struct dirent **nl=NULL;

	recurse=true;
	our_device=ff_pkt->statp.st_dev;

	/*
	* Ignore this directory and everything below if one of the files defined
	* by the 'nobackup' option exists.
	*/
	if((nbret=nobackup_directory(conf->nobackup, ff_pkt->fname)))
	{
		if(nbret<0) return -1; // error
		return 0; // do not back it up.
	}

	/* Build a canonical directory name with a trailing slash in link var */
	len=strlen(fname);
	link_len=len+200;
	if(!(link=(char *)malloc_w(link_len+2, __func__)))
		return -1;
	snprintf(link, link_len, "%s", fname);

	/* Strip all trailing slashes */
	while(len >= 1 && IsPathSeparator(link[len - 1])) len--;
	/* add back one */
	link[len++]='/';
	link[len]=0;

	ff_pkt->link=link;
	ff_pkt->type=FT_DIR;

#if defined(HAVE_WIN32)
	windows_reparse_point_fiddling(ff_pkt);
#endif

	rtn_stat=send_file(asfd, ff_pkt, top_level, conf);
	if(rtn_stat || ff_pkt->type==FT_REPARSE || ff_pkt->type==FT_JUNCTION)
	{
		/* ignore or error status */
		free_w(&link);
		return rtn_stat;
	}

	/*
	* Do not descend into subdirectories (recurse) if the
	* user has turned it off for this directory.
	*
	* If we are crossing file systems, we are either not allowed
	* to cross, or we may be restricted by a list of permitted
	* file systems.
	*/
	if(!top_level
	  && (parent_device!=ff_pkt->statp.st_dev
#if defined(HAVE_WIN32)
		|| ff_pkt->statp.st_rdev==WIN32_MOUNT_POINT
#endif
		))
	{
		if(fstype_excluded(asfd, conf, ff_pkt->fname))
		{
			free_w(&link);
			return send_file(asfd, ff_pkt, top_level, conf);
		}
		if(!fs_change_is_allowed(conf, ff_pkt->fname))
		{
			ff_pkt->type=FT_NOFSCHG;
			recurse=false;
		}
	}
	/* If not recursing, just backup dir and return */
	if(!recurse)
	{
		free_w(&link);
		return send_file(asfd, ff_pkt, top_level, conf);
	}

	/* reset "link" */
	ff_pkt->link=ff_pkt->fname;

	/*
	* Descend into or "recurse" into the directory to read
	*   all the files in it.
	*/
	errno = 0;
#if defined(O_DIRECTORY) && defined(O_NOATIME)
	int dfd=-1;
	if((dfd=open(fname, O_RDONLY|O_DIRECTORY|conf->atime?0:O_NOATIME))<0
	  || !(directory=fdopendir(dfd)))
#else
// Mac OS X appears to have no O_NOATIME and no fdopendir(), so it should
// end up using opendir() here.
	if(!(directory=opendir(fname)))
#endif
	{
#if defined(O_DIRECTORY) && defined(O_NOATIME)
		if(dfd>=0) close(dfd);
#endif
		ff_pkt->type=FT_NOOPEN;
		rtn_stat=send_file(asfd, ff_pkt, top_level, conf);
		free_w(&link);
		return rtn_stat;
	}

	/*
	* Process all files in this directory entry (recursing).
	*    This would possibly run faster if we chdir to the directory
	*    before traversing it.
	*/
	if(get_files_in_directory(directory, &nl, &count))
	{
		closedir(directory);
		free_w(&link);
		return -1;
	}
	closedir(directory);

	rtn_stat=0;
	if(nl)
	{
		if(process_files_in_directory(asfd, nl, count,
			&rtn_stat, &link, len, &link_len, conf,
			ff_pkt, our_device))
		{
			free_w(&link);
			free(nl);
			return -1;
		}
	}
	free_w(&link);
	if(nl) free(nl);

	return rtn_stat;
}
Пример #2
0
static int found_directory(struct asfd *asfd,
	FF_PKT *ff_pkt, struct conf **confs,
	char *fname, dev_t parent_device, bool top_level)
{
	int ret=-1;
	char *link=NULL;
	size_t link_len;
	size_t len;
	int nbret=0;
	int count=0;
	dev_t our_device;
	struct dirent **nl=NULL;

	our_device=ff_pkt->statp.st_dev;

	if((nbret=nobackup_directory(get_strlist(confs[OPT_NOBACKUP]),
		ff_pkt->fname)))
	{
		if(nbret<0) goto end; // Error.
		ret=0; // Do not back it up.
		goto end;
	}

	/* Build a canonical directory name with a trailing slash in link var */
	len=strlen(fname);
	link_len=len+200;
	if(!(link=(char *)malloc_w(link_len+2, __func__)))
		goto end;
	snprintf(link, link_len, "%s", fname);

	/* Strip all trailing slashes */
	while(len >= 1 && IsPathSeparator(link[len - 1])) len--;
	/* add back one */
	link[len++]='/';
	link[len]=0;

	ff_pkt->link=link;
	ff_pkt->type=FT_DIR;

#if defined(HAVE_WIN32)
	windows_reparse_point_fiddling(ff_pkt);
#endif

	if(send_file_w(asfd, ff_pkt, top_level, confs))
		goto end;
	if(ff_pkt->type==FT_REPARSE || ff_pkt->type==FT_JUNCTION)
	{
		// Ignore.
		ret=0;
		goto end;
	}

	if(top_level
	  || (parent_device!=ff_pkt->statp.st_dev
#if defined(HAVE_WIN32)
		|| ff_pkt->statp.st_rdev==WIN32_MOUNT_POINT
#endif
		))
	{
		if(fstype_excluded(asfd, confs, ff_pkt->fname))
		{
			ret=send_file_w(asfd, ff_pkt, top_level, confs);
			goto end;
		}
		if(!top_level && !fs_change_is_allowed(confs, ff_pkt->fname))
		{
			ff_pkt->type=FT_NOFSCHG;
			// Just backup the directory and return.
			ret=send_file_w(asfd, ff_pkt, top_level, confs);
			goto end;
		}
	}

	ff_pkt->link=ff_pkt->fname;

	errno=0;
	switch(entries_in_directory_alphasort(fname,
		&nl, &count, get_int(confs[OPT_ATIME])))
	{
		case 0: break;
		case 1:
			ff_pkt->type=FT_NOOPEN;
			ret=send_file_w(asfd, ff_pkt, top_level, confs);
		default:
			goto end;
	}

	if(nl)
	{
		if(process_entries_in_directory(asfd, nl, count,
			&link, len, &link_len, confs, ff_pkt, our_device))
				goto end;
	}
	ret=0;
end:
	free_w(&link);
	free_v((void **)&nl);
	return ret;
}