Merge "translate: Skip matrix_rebuild during shutdown."
[asterisk/asterisk.git] / main / file.c
index 37b9e79..41131f9 100644 (file)
@@ -1093,27 +1093,27 @@ int ast_filecopy(const char *filename, const char *filename2, const char *fmt)
        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)
 {
        DIR *dir;
        struct dirent *entry;
-       size_t size;
        int res;
 
-       if (!(dir = opendir(ast_str_buffer(*path)))) {
+       if (!(dir = opendir(path))) {
                ast_log(LOG_ERROR, "Error opening directory - %s: %s\n",
-                       ast_str_buffer(*path), strerror(errno));
+                       path, strerror(errno));
                return -1;
        }
-       size = ast_str_strlen(*path);
 
        --max_depth;
 
        res = 0;
 
        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, "..")) {
                        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) {
                        is_file = entry->d_type == DT_REG;
                        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
 #endif
                {
                        struct stat statbuf;
 
                        /*
-                        * If using the stat function the file needs to be appended to the
-                        * path so it can be found. However, before appending make sure the
-                        * path contains only the directory for this depth level.
+                        * Don't use alloca or we risk blowing out the stack if recursing
+                        * into subdirectories.
                         */
-                       ast_str_truncate(*path, size);
-                       ast_str_append(path, 0, "/%s", entry->d_name);
+                       full_path = ast_malloc(strlen(path) + strlen(entry->d_name) + 2);
+                       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_str_buffer(*path), strerror(errno));
+                                       full_path, strerror(errno));
                                /*
                                 * Output an error, but keep going. It could just be
                                 * 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_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 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;
                        }
                        /* 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) {
-                       ast_debug(5, "Skipping %s: not a regular file or directory\n",
-                                 ast_str_buffer(*path));
+                       ast_debug(5, "Skipping %s: not a regular file or directory\n", full_path);
                        continue;
                }
 
                /* Only re-curse into sub-directories if not at the max depth */
                if (max_depth != 0) {
-                       /*
-                        * If the stat function was used then the sub-directory has
-                        * already been appended, otherwise append it.
-                        */
-                       ast_log(LOG_VERBOSE, "!###### do dir d_name=%s, path=%s, used_stat=%d\n", entry->d_name, ast_str_buffer(*path), used_stat);
-                       if (!used_stat) {
-                               ast_str_truncate(*path, size);
-                               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 (!full_path) {
+                               /* Don't use alloca.  See note above. */
+                               full_path = ast_malloc(strlen(path) + strlen(entry->d_name) + 2);
+                               if (!full_path) {
+                                       return -1;
+                               }
+                               sprintf(full_path, "%s/%s", path, entry->d_name);
                        }
 
-                       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;
                        }
                }
@@ -1196,7 +1192,7 @@ static int __ast_file_read_dirs(struct ast_str **path, ast_file_on_file on_file,
 
        if (!res && errno) {
                ast_log(LOG_ERROR, "Error while reading directories - %s: %s\n",
-                       ast_str_buffer(*path), strerror(errno));
+                       path, strerror(errno));
                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)
 {
-       struct ast_str *path;
        int res;
 
-       if (!(path = ast_str_create(256))) {
-               return -1;
-       }
-
-       ast_str_set(&path, 0, "%s", dir_name);
        errno = 0;
 
 #if !defined(__GLIBC__)
        ast_mutex_lock(&read_dirs_lock);
 #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__)
        ast_mutex_unlock(&read_dirs_lock);
 #endif
 
-       ast_free(path);
        return res;
 }
 
@@ -1554,7 +1543,7 @@ static int waitstream_core(struct ast_channel *c,
                reverse = "";
 
        /* Switch the channel to end DTMF frame only. waitstream_core doesn't care about the start of DTMF. */
-       ast_set_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
+       ast_channel_set_flag(c, AST_FLAG_END_DTMF_ONLY);
 
        if (ast_test_flag(ast_channel_flags(c), AST_FLAG_MASQ_NOSTREAM))
                orig_chan_name = ast_strdupa(ast_channel_name(c));
@@ -1586,7 +1575,7 @@ static int waitstream_core(struct ast_channel *c,
                        res = ast_waitfor(c, ms);
                        if (res < 0) {
                                ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno));
-                               ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
+                               ast_channel_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
                                return res;
                        }
                } else {
@@ -1597,11 +1586,11 @@ static int waitstream_core(struct ast_channel *c,
                                if (errno == EINTR)
                                        continue;
                                ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno));
-                               ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
+                               ast_channel_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
                                return -1;
                        } else if (outfd > -1) { /* this requires cmdfd set */
                                /* The FD we were watching has something waiting */
-                               ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
+                               ast_channel_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
                                return 1;
                        }
                        /* if rchan is set, it is 'c' */
@@ -1610,7 +1599,7 @@ static int waitstream_core(struct ast_channel *c,
                if (res > 0) {
                        struct ast_frame *fr = ast_read(c);
                        if (!fr) {
-                               ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
+                               ast_channel_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
                                return -1;
                        }
                        switch (fr->frametype) {
@@ -1621,7 +1610,7 @@ static int waitstream_core(struct ast_channel *c,
                                                S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
                                                res = fr->subclass.integer;
                                                ast_frfree(fr);
-                                               ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
+                                               ast_channel_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
                                                return res;
                                        }
                                } else {
@@ -1637,7 +1626,7 @@ static int waitstream_core(struct ast_channel *c,
                                                        "Break");
 
                                                ast_frfree(fr);
-                                               ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
+                                               ast_channel_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
                                                return res;
                                        }
                                }
@@ -1654,7 +1643,7 @@ static int waitstream_core(struct ast_channel *c,
                                                "Break");
                                        res = fr->subclass.integer;
                                        ast_frfree(fr);
-                                       ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
+                                       ast_channel_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
                                        return res;
                                case AST_CONTROL_STREAM_REVERSE:
                                        if (!skip_ms) {
@@ -1672,7 +1661,7 @@ static int waitstream_core(struct ast_channel *c,
                                case AST_CONTROL_BUSY:
                                case AST_CONTROL_CONGESTION:
                                        ast_frfree(fr);
-                                       ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
+                                       ast_channel_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
                                        return -1;
                                case AST_CONTROL_RINGING:
                                case AST_CONTROL_ANSWER:
@@ -1709,7 +1698,7 @@ static int waitstream_core(struct ast_channel *c,
                ast_sched_runq(ast_channel_sched(c));
        }
 
-       ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
+       ast_channel_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
 
        return (err || ast_channel_softhangup_internal_flag(c)) ? -1 : 0;
 }