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