diff options
Diffstat (limited to 'main/config.c')
-rw-r--r-- | main/config.c | 85 |
1 files changed, 76 insertions, 9 deletions
diff --git a/main/config.c b/main/config.c index 446bac2df..a45f57311 100644 --- a/main/config.c +++ b/main/config.c @@ -89,7 +89,12 @@ struct cache_file_mtime { AST_LIST_ENTRY(cache_file_mtime) list; AST_LIST_HEAD_NOLOCK(includes, cache_file_include) includes; unsigned int has_exec:1; - time_t mtime; + /*! stat() file size */ + unsigned long stat_size; + /*! stat() file modtime nanoseconds */ + unsigned long stat_mtime_nsec; + /*! stat() file modtime seconds since epoc */ + time_t stat_mtime; /*! String stuffed in filename[] after the filename string. */ const char *who_asked; @@ -1214,6 +1219,61 @@ enum config_cache_attribute_enum { ATTRIBUTE_EXEC = 1, }; +/*! + * \internal + * \brief Clear the stat() data in the cached file modtime struct. + * + * \param cfmtime Cached file modtime. + * + * \return Nothing + */ +static void cfmstat_clear(struct cache_file_mtime *cfmtime) +{ + cfmtime->stat_size = 0; + cfmtime->stat_mtime_nsec = 0; + cfmtime->stat_mtime = 0; +} + +/*! + * \internal + * \brief Save the stat() data to the cached file modtime struct. + * + * \param cfmtime Cached file modtime. + * \param statbuf Buffer filled in by stat(). + * + * \return Nothing + */ +static void cfmstat_save(struct cache_file_mtime *cfmtime, struct stat *statbuf) +{ + cfmtime->stat_size = statbuf->st_size; +#if defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || (defined(_POSIX_C_SOURCE) && 200809L <= _POSIX_C_SOURCE) || (defined(_XOPEN_SOURCE) && 700 <= _XOPEN_SOURCE) + cfmtime->stat_mtime_nsec = statbuf->st_mtim.tv_nsec; +#else + cfmtime->stat_mtime_nsec = statbuf->st_mtimensec; +#endif + cfmtime->stat_mtime = statbuf->st_mtime; +} + +/*! + * \internal + * \brief Compare the stat() data with the cached file modtime struct. + * + * \param cfmtime Cached file modtime. + * \param statbuf Buffer filled in by stat(). + * + * \retval non-zero if different. + */ +static int cfmstat_cmp(struct cache_file_mtime *cfmtime, struct stat *statbuf) +{ + struct cache_file_mtime cfm_buf; + + cfmstat_save(&cfm_buf, statbuf); + + return cfmtime->stat_size != cfm_buf.stat_size + || cfmtime->stat_mtime != cfm_buf.stat_mtime + || cfmtime->stat_mtime_nsec != cfm_buf.stat_mtime_nsec; +} + static void config_cache_attribute(const char *configfile, enum config_cache_attribute_enum attrtype, const char *filename, const char *who_asked) { struct cache_file_mtime *cfmtime; @@ -1236,10 +1296,11 @@ static void config_cache_attribute(const char *configfile, enum config_cache_att AST_LIST_INSERT_SORTALPHA(&cfmtime_head, cfmtime, list, filename); } - if (!stat(configfile, &statbuf)) - cfmtime->mtime = 0; - else - cfmtime->mtime = statbuf.st_mtime; + if (!stat(configfile, &statbuf)) { + cfmstat_clear(cfmtime); + } else { + cfmstat_save(cfmtime, &statbuf); + } switch (attrtype) { case ATTRIBUTE_INCLUDE: @@ -1621,14 +1682,19 @@ static struct ast_config *config_text_file_load(const char *database, const char } if (!cfmtime) { cfmtime = cfmtime_new(fn, who_asked); - if (!cfmtime) + if (!cfmtime) { + AST_LIST_UNLOCK(&cfmtime_head); continue; + } /* Note that the file mtime is initialized to 0, i.e. 1970 */ AST_LIST_INSERT_SORTALPHA(&cfmtime_head, cfmtime, list, filename); } } - if (cfmtime && (!cfmtime->has_exec) && (cfmtime->mtime == statbuf.st_mtime) && ast_test_flag(&flags, CONFIG_FLAG_FILEUNCHANGED)) { + if (cfmtime + && !cfmtime->has_exec + && !cfmstat_cmp(cfmtime, &statbuf) + && ast_test_flag(&flags, CONFIG_FLAG_FILEUNCHANGED)) { /* File is unchanged, what about the (cached) includes (if any)? */ int unchanged = 1; AST_LIST_TRAVERSE(&cfmtime->includes, cfinclude, list) { @@ -1685,8 +1751,9 @@ static struct ast_config *config_text_file_load(const char *database, const char return NULL; } - if (cfmtime) - cfmtime->mtime = statbuf.st_mtime; + if (cfmtime) { + cfmstat_save(cfmtime, &statbuf); + } if (!(f = fopen(fn, "r"))) { ast_debug(1, "No file to parse: %s\n", fn); |