@ -380,7 +380,8 @@ static int process_media_file(struct ast_media_index *index, const char *variant
static int process_description_file ( struct ast_media_index * index ,
const char * subdir ,
const char * variant_str ,
const char * filename )
const char * filename ,
const char * match_filename )
{
RAII_VAR ( struct ast_str * , description_file_path , ast_str_create ( 64 ) , ast_free ) ;
RAII_VAR ( struct ast_str * , cumulative_description , ast_str_create ( 64 ) , ast_free ) ;
@ -450,16 +451,21 @@ static int process_description_file(struct ast_media_index *index,
if ( file_id_persist & & ! ast_strlen_zero ( ast_str_buffer ( cumulative_description ) ) ) {
struct media_variant * variant ;
variant = alloc_variant ( index , file_id_persist , variant_str ) ;
if ( ! variant ) {
res = - 1 ;
break ;
/*
* If we were only searching for a specific sound filename
* don ' t include others .
*/
if ( ast_strlen_zero ( match_filename ) | | strcmp ( match_filename , file_id_persist ) = = 0 ) {
variant = alloc_variant ( index , file_id_persist , variant_str ) ;
if ( ! variant ) {
res = - 1 ;
break ;
}
ast_string_field_set ( variant , description , ast_str_buffer ( cumulative_description ) ) ;
ao2_ref ( variant , - 1 ) ;
}
ast_string_field_set ( variant , description , ast_str_buffer ( cumulative_description ) ) ;
ast_str_reset ( cumulative_description ) ;
ao2_ref ( variant , - 1 ) ;
}
ast_free ( file_id_persist ) ;
@ -473,12 +479,18 @@ static int process_description_file(struct ast_media_index *index,
if ( file_id_persist & & ! ast_strlen_zero ( ast_str_buffer ( cumulative_description ) ) ) {
struct media_variant * variant ;
variant = alloc_variant ( index , file_id_persist , variant_str ) ;
if ( variant ) {
ast_string_field_set ( variant , description , ast_str_buffer ( cumulative_description ) ) ;
ao2_ref ( variant , - 1 ) ;
} else {
res = - 1 ;
/*
* If we were only searching for a specific sound filename
* don ' t include others .
*/
if ( ast_strlen_zero ( match_filename ) | | strcmp ( match_filename , file_id_persist ) = = 0 ) {
variant = alloc_variant ( index , file_id_persist , variant_str ) ;
if ( variant ) {
ast_string_field_set ( variant , description , ast_str_buffer ( cumulative_description ) ) ;
ao2_ref ( variant , - 1 ) ;
} else {
res = - 1 ;
}
}
}
@ -487,110 +499,121 @@ static int process_description_file(struct ast_media_index *index,
return res ;
}
/*! \brief process an individual file listing */
static int process_file ( struct ast_media_index * index , const char * variant_str , const char * subdir , const char * filename )
struct read_dirs_data {
const char * search_filename ;
size_t search_filename_len ;
const char * search_variant ;
struct ast_media_index * index ;
size_t dirname_len ;
} ;
static int read_dirs_cb ( const char * dir_name , const char * filename , void * obj )
{
RAII_VAR ( char * , filename_stripped , ast_strdup ( filename ) , ast_free ) ;
struct read_dirs_data * data = obj ;
char * ext ;
if ( ! filename_stripped ) {
return - 1 ;
}
ext = strrchr ( filename_stripped , ' . ' ) ;
size_t match_len ;
char * match ;
size_t match_base_len ;
char * subdirs = ( char * ) dir_name + data - > dirname_len ;
/*
* Example :
* From the filesystem :
* index ' s base_dir = " /var/lib/asterisk/sounds "
* search_variant = " en "
* search directory base = " /var/lib/asterisk/sounds/en "
* dirname_len = 27
* current dir_name = " /var/lib/asterisk/sounds/en/digits "
* subdirs = " /digits "
* filename = " 1.ulaw "
*
* From the search criteria :
* search_filename = " digits/1 "
* search_filename_len = 8
*/
if ( * subdirs = = ' / ' ) {
subdirs + + ;
}
/* subdirs = "digits" */
match_len = strlen ( subdirs ) + strlen ( filename ) + 2 ;
match = ast_alloca ( match_len ) ;
snprintf ( match , match_len , " %s%s%s " , subdirs ,
ast_strlen_zero ( subdirs ) ? " " : " / " , filename ) ;
/* match = discovered filename relative to language = "digits/1.ulaw" */
ext = strrchr ( match , ' . ' ) ;
if ( ! ext ) {
/* file has no extension */
return 0 ;
}
* ext + + = ' \0 ' ;
if ( ! strcmp ( ext , " txt " ) ) {
if ( process_description_file ( index , subdir , variant_str , filename ) ) {
return - 1 ;
/* ext = ".ulaw" */
if ( data - > search_filename_len > 0 ) {
match_base_len = ext - match ;
/*
* match_base_len = length of " digits/1 " = 8 which
* happens to match the length of search_filename .
* However if the discovered filename was 11. ulaw
* it would be length of " digits/11 " = 9.
* We need to use the larger during the compare to
* make sure we don ' t match just search_filename
* as a substring of the discovered filename .
*/
if ( data - > search_filename_len > match_base_len ) {
match_base_len = data - > search_filename_len ;
}
} else {
if ( process_media_file ( index , variant_str , subdir , filename_stripped , ext ) ) {
}
/* We always process txt files because they should contain description. */
if ( strcmp ( ext , " .txt " ) = = 0 ) {
if ( process_description_file ( data - > index , NULL , data - > search_variant ,
match , data - > search_filename ) ) {
return - 1 ;
}
} else if ( data - > search_filename_len = = 0
| | strncmp ( data - > search_filename , match , match_base_len ) = = 0 ) {
* ext = ' \0 ' ;
ext + + ;
process_media_file ( data - > index , data - > search_variant , NULL , match , ext ) ;
}
return 0 ;
}
/*! \brief internal function for updating the index, recursive */
static int media_index_update ( struct ast_media_index * index ,
const char * variant ,
const char * subdir )
int ast_media_index_update_for_file ( struct ast_media_index * index ,
const char * variant , const char * filename )
{
struct dirent * dent ;
DIR * srcdir ;
RAII_VAR ( struct ast_str * , index_dir , ast_str_create ( 64 ) , ast_free ) ;
RAII_VAR ( struct ast_str * , statfile , ast_str_create ( 64 ) , ast_free ) ;
int res = 0 ;
if ( ! index_dir ) {
return 0 ;
}
ast_str_set ( & index_dir , 0 , " %s " , index - > base_dir ) ;
if ( ! ast_strlen_zero ( variant ) ) {
ast_str_append ( & index_dir , 0 , " /%s " , variant ) ;
}
if ( ! ast_strlen_zero ( subdir ) ) {
ast_str_append ( & index_dir , 0 , " /%s " , subdir ) ;
}
srcdir = opendir ( ast_str_buffer ( index_dir ) ) ;
if ( srcdir = = NULL ) {
ast_log ( LOG_ERROR , " Failed to open %s: %s \n " , ast_str_buffer ( index_dir ) , strerror ( errno ) ) ;
return - 1 ;
}
while ( ( dent = readdir ( srcdir ) ) ! = NULL ) {
struct stat st ;
if ( ! strcmp ( dent - > d_name , " . " ) | | ! strcmp ( dent - > d_name , " .. " ) ) {
continue ;
}
ast_str_reset ( statfile ) ;
ast_str_set ( & statfile , 0 , " %s/%s " , ast_str_buffer ( index_dir ) , dent - > d_name ) ;
if ( stat ( ast_str_buffer ( statfile ) , & st ) < 0 ) {
ast_log ( LOG_WARNING , " Failed to stat %s: %s \n " , ast_str_buffer ( statfile ) , strerror ( errno ) ) ;
continue ;
}
if ( S_ISDIR ( st . st_mode ) ) {
if ( ast_strlen_zero ( subdir ) ) {
res = media_index_update ( index , variant , dent - > d_name ) ;
} else {
RAII_VAR ( struct ast_str * , new_subdir , ast_str_create ( 64 ) , ast_free ) ;
ast_str_set ( & new_subdir , 0 , " %s/%s " , subdir , dent - > d_name ) ;
res = media_index_update ( index , variant , ast_str_buffer ( new_subdir ) ) ;
}
if ( res ) {
break ;
}
continue ;
}
if ( ! S_ISREG ( st . st_mode ) ) {
continue ;
}
if ( process_file ( index , variant , subdir , dent - > d_name ) ) {
res = - 1 ;
break ;
}
}
closedir ( srcdir ) ;
return res ;
struct timeval start ;
struct timeval end ;
int64_t elapsed ;
int rc ;
size_t dirname_len = strlen ( index - > base_dir ) + strlen ( S_OR ( variant , " " ) ) + 1 ;
struct read_dirs_data data = {
. search_filename = S_OR ( filename , " " ) ,
. search_filename_len = strlen ( S_OR ( filename , " " ) ) ,
. search_variant = S_OR ( variant , " " ) ,
. index = index ,
. dirname_len = dirname_len ,
} ;
char * search_dir = ast_alloca ( dirname_len + 1 ) ;
sprintf ( search_dir , " %s%s%s " , index - > base_dir , ast_strlen_zero ( variant ) ? " " : " / " ,
data . search_variant ) ;
gettimeofday ( & start , NULL ) ;
rc = ast_file_read_dirs ( search_dir , read_dirs_cb , & data , - 1 ) ;
gettimeofday ( & end , NULL ) ;
elapsed = ast_tvdiff_us ( end , start ) ;
ast_debug ( 1 , " Media for language '%s' indexed in %8.6f seconds \n " , data . search_variant , elapsed / 1E6 ) ;
return rc ;
}
int ast_media_index_update ( struct ast_media_index * index ,
const char * variant )
int ast_media_index_update ( struct ast_media_index * index , const char * variant )
{
return media_index_update( index , variant , NULL ) ;
return ast_media_index_update_for_file ( index , variant , NULL ) ;
}