static void test_get_files_in_directory(void) { _cleanup_strv_free_ char **l = NULL, **t = NULL; assert_se(get_files_in_directory("/tmp", &l) >= 0); assert_se(get_files_in_directory(".", &t) >= 0); assert_se(get_files_in_directory(".", NULL) >= 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; }
static int enumerate_dir_d(Hashmap *top, Hashmap *bottom, Hashmap *drops, const char *toppath, const char *drop) { _cleanup_free_ char *unit = NULL; _cleanup_free_ char *path = NULL; _cleanup_strv_free_ char **list = NULL; char **file; char *c; int r; assert(!endswith(drop, "/")); path = strjoin(toppath, "/", drop); if (!path) return -ENOMEM; log_debug("Looking at %s", path); unit = strdup(drop); if (!unit) return -ENOMEM; c = strrchr(unit, '.'); if (!c) return -EINVAL; *c = 0; r = get_files_in_directory(path, &list); if (r < 0) return log_error_errno(r, "Failed to enumerate %s: %m", path); STRV_FOREACH(file, list) { Hashmap *h; int k; char *p; char *d; if (!endswith(*file, ".conf")) continue; p = strjoin(path, "/", *file); if (!p) return -ENOMEM; d = p + strlen(toppath) + 1; log_debug("Adding at top: %s %s %s", d, special_glyph(ARROW), p); k = hashmap_put(top, d, p); if (k >= 0) { p = strdup(p); if (!p) return -ENOMEM; d = p + strlen(toppath) + 1; } else if (k != -EEXIST) { free(p); return k; } log_debug("Adding at bottom: %s %s %s", d, special_glyph(ARROW), p); free(hashmap_remove(bottom, d)); k = hashmap_put(bottom, d, p); if (k < 0) { free(p); return k; } h = hashmap_get(drops, unit); if (!h) { h = hashmap_new(&string_hash_ops); if (!h) return -ENOMEM; hashmap_put(drops, unit, h); unit = strdup(unit); if (!unit) return -ENOMEM; } p = strdup(p); if (!p) return -ENOMEM; log_debug("Adding to drops: %s %s %s %s %s", unit, special_glyph(ARROW), basename(p), special_glyph(ARROW), p); k = hashmap_put(h, basename(p), p); if (k < 0) { free(p); if (k != -EEXIST) return k; } }