Merge "file.c/__ast_file_read_dirs: Fix issues on filesystems without d_type"

This commit is contained in:
George Joseph
2016-11-16 14:17:34 -06:00
committed by Gerrit Code Review
2 changed files with 41 additions and 38 deletions

View File

@@ -1093,27 +1093,27 @@ int ast_filecopy(const char *filename, const char *filename2, const char *fmt)
return filehelper(filename, filename2, fmt, ACTION_COPY); return filehelper(filename, filename2, fmt, ACTION_COPY);
} }
static int __ast_file_read_dirs(struct ast_str **path, ast_file_on_file on_file, static int __ast_file_read_dirs(const char *path, ast_file_on_file on_file,
void *obj, int max_depth) void *obj, int max_depth)
{ {
DIR *dir; DIR *dir;
struct dirent *entry; struct dirent *entry;
size_t size;
int res; int res;
if (!(dir = opendir(ast_str_buffer(*path)))) { if (!(dir = opendir(path))) {
ast_log(LOG_ERROR, "Error opening directory - %s: %s\n", ast_log(LOG_ERROR, "Error opening directory - %s: %s\n",
ast_str_buffer(*path), strerror(errno)); path, strerror(errno));
return -1; return -1;
} }
size = ast_str_strlen(*path);
--max_depth; --max_depth;
res = 0; res = 0;
while ((entry = readdir(dir)) != NULL && !errno) { while ((entry = readdir(dir)) != NULL && !errno) {
int is_file, is_dir, used_stat = 0; int is_file = 0;
int is_dir = 0;
RAII_VAR(char *, full_path, NULL, ast_free);
if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) { if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) {
continue; continue;
@@ -1128,23 +1128,24 @@ static int __ast_file_read_dirs(struct ast_str **path, ast_file_on_file on_file,
if (entry->d_type != DT_UNKNOWN && entry->d_type != DT_LNK) { if (entry->d_type != DT_UNKNOWN && entry->d_type != DT_LNK) {
is_file = entry->d_type == DT_REG; is_file = entry->d_type == DT_REG;
is_dir = entry->d_type == DT_DIR; is_dir = entry->d_type == DT_DIR;
ast_log(LOG_VERBOSE, "!###### d_name=%s, path=%s, NO USE STAT used_stat=%d\n", entry->d_name, ast_str_buffer(*path), used_stat);
} else } else
#endif #endif
{ {
struct stat statbuf; struct stat statbuf;
/* /*
* If using the stat function the file needs to be appended to the * Don't use alloca or we risk blowing out the stack if recursing
* path so it can be found. However, before appending make sure the * into subdirectories.
* path contains only the directory for this depth level.
*/ */
ast_str_truncate(*path, size); full_path = ast_malloc(strlen(path) + strlen(entry->d_name) + 2);
ast_str_append(path, 0, "/%s", entry->d_name); if (!full_path) {
return -1;
}
sprintf(full_path, "%s/%s", path, entry->d_name);
if (stat(ast_str_buffer(*path), &statbuf)) { if (stat(full_path, &statbuf)) {
ast_log(LOG_ERROR, "Error reading path stats - %s: %s\n", ast_log(LOG_ERROR, "Error reading path stats - %s: %s\n",
ast_str_buffer(*path), strerror(errno)); full_path, strerror(errno));
/* /*
* Output an error, but keep going. It could just be * Output an error, but keep going. It could just be
* a broken link and other files could be fine. * a broken link and other files could be fine.
@@ -1154,13 +1155,11 @@ static int __ast_file_read_dirs(struct ast_str **path, ast_file_on_file on_file,
is_file = S_ISREG(statbuf.st_mode); is_file = S_ISREG(statbuf.st_mode);
is_dir = S_ISDIR(statbuf.st_mode); is_dir = S_ISDIR(statbuf.st_mode);
used_stat = 1;
ast_log(LOG_VERBOSE, "!###### d_name=%s, path=%s, WE USED IT YO used_stat=%d\n", entry->d_name, ast_str_buffer(*path), used_stat);
} }
if (is_file) { if (is_file) {
/* If the handler returns non-zero then stop */ /* If the handler returns non-zero then stop */
if ((res = on_file(ast_str_buffer(*path), entry->d_name, obj))) { if ((res = on_file(path, entry->d_name, obj))) {
break; break;
} }
/* Otherwise move on to next item in directory */ /* Otherwise move on to next item in directory */
@@ -1168,25 +1167,22 @@ static int __ast_file_read_dirs(struct ast_str **path, ast_file_on_file on_file,
} }
if (!is_dir) { if (!is_dir) {
ast_debug(5, "Skipping %s: not a regular file or directory\n", ast_debug(5, "Skipping %s: not a regular file or directory\n", full_path);
ast_str_buffer(*path));
continue; continue;
} }
/* Only re-curse into sub-directories if not at the max depth */ /* Only re-curse into sub-directories if not at the max depth */
if (max_depth != 0) { if (max_depth != 0) {
/* if (!full_path) {
* If the stat function was used then the sub-directory has /* Don't use alloca. See note above. */
* already been appended, otherwise append it. full_path = ast_malloc(strlen(path) + strlen(entry->d_name) + 2);
*/ if (!full_path) {
ast_log(LOG_VERBOSE, "!###### do dir d_name=%s, path=%s, used_stat=%d\n", entry->d_name, ast_str_buffer(*path), used_stat); return -1;
if (!used_stat) { }
ast_str_truncate(*path, size); sprintf(full_path, "%s/%s", path, entry->d_name);
ast_str_append(path, 0, "/%s", entry->d_name);
ast_log(LOG_VERBOSE, "!###### d_name=%s, path=%s\n", entry->d_name, ast_str_buffer(*path));
} }
if ((res = __ast_file_read_dirs(path, on_file, obj, max_depth))) { if ((res = __ast_file_read_dirs(full_path, on_file, obj, max_depth))) {
break; break;
} }
} }
@@ -1196,7 +1192,7 @@ static int __ast_file_read_dirs(struct ast_str **path, ast_file_on_file on_file,
if (!res && errno) { if (!res && errno) {
ast_log(LOG_ERROR, "Error while reading directories - %s: %s\n", ast_log(LOG_ERROR, "Error while reading directories - %s: %s\n",
ast_str_buffer(*path), strerror(errno)); path, strerror(errno));
res = -1; res = -1;
} }
@@ -1217,27 +1213,20 @@ AST_MUTEX_DEFINE_STATIC(read_dirs_lock);
int ast_file_read_dirs(const char *dir_name, ast_file_on_file on_file, void *obj, int max_depth) int ast_file_read_dirs(const char *dir_name, ast_file_on_file on_file, void *obj, int max_depth)
{ {
struct ast_str *path;
int res; int res;
if (!(path = ast_str_create(256))) {
return -1;
}
ast_str_set(&path, 0, "%s", dir_name);
errno = 0; errno = 0;
#if !defined(__GLIBC__) #if !defined(__GLIBC__)
ast_mutex_lock(&read_dirs_lock); ast_mutex_lock(&read_dirs_lock);
#endif #endif
res = __ast_file_read_dirs(&path, on_file, obj, max_depth); res = __ast_file_read_dirs(dir_name, on_file, obj, max_depth);
#if !defined(__GLIBC__) #if !defined(__GLIBC__)
ast_mutex_unlock(&read_dirs_lock); ast_mutex_unlock(&read_dirs_lock);
#endif #endif
ast_free(path);
return res; return res;
} }

View File

@@ -21,7 +21,10 @@
<support_level>core</support_level> <support_level>core</support_level>
***/ ***/
#include "asterisk.h" #include "asterisk.h"
#include <sys/stat.h>
#include <stdio.h>
#include "asterisk/file.h" #include "asterisk/file.h"
#include "asterisk/paths.h" #include "asterisk/paths.h"
@@ -115,6 +118,17 @@ static char *test_files_get_one(struct _filenames *filenames, int num)
static int handle_find_file(const char *dir_name, const char *filename, void *obj) static int handle_find_file(const char *dir_name, const char *filename, void *obj)
{ {
struct stat statbuf;
char *full_path = ast_alloca(strlen(dir_name) + strlen(filename) + 2);
sprintf(full_path, "%s/%s", dir_name, filename);
errno = 0;
if (stat(full_path, &statbuf)) {
ast_log(LOG_ERROR, "Error reading path stats - %s: %s\n",
full_path, strerror(errno));
return 0;
}
/* obj contains the name of the file we are looking for */ /* obj contains the name of the file we are looking for */
return strcmp(obj, filename) ? 0 : FOUND; return strcmp(obj, filename) ? 0 : FOUND;
} }