static int ListScripts( addons_finder_t *p_finder, addon_type_t type ) { char *psz_dir = getAddonInstallDir( type ); if ( ! psz_dir ) return VLC_EGENERIC; char **ppsz_list = NULL; int i_count = vlc_scandir( psz_dir, &ppsz_list, ListScript_filter, NULL ); for ( int i=0; i< i_count; i++ ) { char *psz_file = ppsz_list[i]; if( !psz_file ) break; if ( FileBelongsToManagedAddon( p_finder, type, psz_file ) ) continue; addon_entry_t *p_entry = addon_entry_New(); p_entry->e_state = ADDON_INSTALLED; p_entry->e_type = type; p_entry->e_flags |= ADDON_BROKEN; p_entry->psz_name = strdup(psz_file); p_entry->psz_description = strdup("Lua script"); ARRAY_APPEND( p_finder->entries, p_entry ); free( psz_file ); } free( ppsz_list ); free( psz_dir ); return VLC_SUCCESS; }
/***************************************************************************** * Will execute func on all scripts in luadirname, and stop if func returns * success. *****************************************************************************/ int vlclua_scripts_batch_execute( vlc_object_t *p_this, const char * luadirname, int (*func)(vlc_object_t *, const char *, void *), void * user_data) { char **ppsz_dir_list = NULL; int i_ret = vlclua_dir_list( p_this, luadirname, &ppsz_dir_list ); if( i_ret != VLC_SUCCESS ) return i_ret; i_ret = VLC_EGENERIC; for( char **ppsz_dir = ppsz_dir_list; *ppsz_dir; ppsz_dir++ ) { char **ppsz_filelist; int i_files; msg_Dbg( p_this, "Trying Lua scripts in %s", *ppsz_dir ); i_files = vlc_scandir( *ppsz_dir, &ppsz_filelist, file_select, file_compare ); if( i_files < 0 ) continue; char **ppsz_file = ppsz_filelist; char **ppsz_fileend = ppsz_filelist + i_files; while( ppsz_file < ppsz_fileend ) { char *psz_filename; if( asprintf( &psz_filename, "%s" DIR_SEP "%s", *ppsz_dir, *ppsz_file ) == -1 ) psz_filename = NULL; free( *(ppsz_file++) ); if( likely(psz_filename != NULL) ) { msg_Dbg( p_this, "Trying Lua playlist script %s", psz_filename ); i_ret = func( p_this, psz_filename, user_data ); free( psz_filename ); if( i_ret == VLC_SUCCESS ) break; } } while( ppsz_file < ppsz_fileend ) free( *(ppsz_file++) ); free( ppsz_filelist ); if( i_ret == VLC_SUCCESS ) break; } vlclua_dir_list_free( ppsz_dir_list ); return i_ret; }
static int vlc_sd_probe_Open( vlc_object_t *obj ) { vlc_dictionary_t name_d; char **ppsz_dir_list; if( vlclua_dir_list( "sd", &ppsz_dir_list ) ) return VLC_ENOMEM; vlc_dictionary_init( &name_d, 32 ); for( char **ppsz_dir = ppsz_dir_list; *ppsz_dir; ppsz_dir++ ) { char **ppsz_filelist; int i_files = vlc_scandir( *ppsz_dir, &ppsz_filelist, file_select, file_compare ); if( i_files < 1 ) continue; for( char **ppsz_file = ppsz_filelist; ppsz_file < ppsz_filelist + i_files; ppsz_file++ ) { char *temp = strchr( *ppsz_file, '.' ); if( temp ) *temp = '\0'; if( vlc_dictionary_value_for_key( &name_d, *ppsz_file ) == kVLCDictionaryNotFound ) vlc_dictionary_insert( &name_d, *ppsz_file, &name_d ); free( *ppsz_file ); } free( ppsz_filelist ); } vlclua_dir_list_free( ppsz_dir_list ); int r = VLC_PROBE_CONTINUE; char **names = vlc_dictionary_all_keys( &name_d ); if( names != NULL ) { for( char **name = names; *name; ++name ) { r = vlclua_probe_sd( obj, *name ); if( r != VLC_PROBE_CONTINUE ) break; } for( char **name = names; *name; ++name ) free( *name ); free( names ); } vlc_dictionary_clear( &name_d, NULL, NULL ); return r; }
static int ListSkins( addons_finder_t *p_finder ) { char *psz_dir = getAddonInstallDir( ADDON_SKIN2 ); if ( !psz_dir ) return VLC_EGENERIC; char **ppsz_list = NULL; int i_count = vlc_scandir( psz_dir, &ppsz_list, ListSkin_filter, NULL ); for ( int i=0; i< i_count; i++ ) { char *psz_file = ppsz_list[i]; if( !psz_file ) break; if ( FileBelongsToManagedAddon( p_finder, ADDON_SKIN2, psz_file ) ) continue; char *psz_uri; if( asprintf( &psz_uri, "unzip://%s/%s!/theme.xml", psz_dir, psz_file ) >= 0) { int i_ret; char *psz_name = NULL; char *psz_source = NULL; stream_t *p_stream = stream_UrlNew( p_finder, psz_uri ); free( psz_uri ); if ( !p_stream ) { i_ret = VLC_EGENERIC; } else { i_ret = ParseSkins2Info( p_finder, p_stream, &psz_name, &psz_source ); if ( i_ret != VLC_SUCCESS ) { free( psz_name ); free( psz_source ); } stream_Delete( p_stream ); } addon_entry_t *p_entry = addon_entry_New(); p_entry->e_type = ADDON_SKIN2; p_entry->e_state = ADDON_INSTALLED; if ( i_ret == VLC_SUCCESS ) { p_entry->psz_name = psz_name; p_entry->psz_description = strdup("Skins2 theme"); p_entry->psz_source_uri = psz_source; } else { p_entry->e_flags |= ADDON_BROKEN; p_entry->psz_name = strdup(psz_file); p_entry->psz_description = strdup("Skins2 theme"); } ARRAY_APPEND( p_finder->entries, p_entry ); } free( psz_file ); } free( ppsz_list ); free( psz_dir ); return VLC_SUCCESS; }
mvar_t *mvar_FileSetNew( intf_thread_t *p_intf, char *name, char *psz_dir ) { mvar_t *s = mvar_New( name, "set" ); char **ppsz_dir_content; int i_dir_content, i; psz_dir = RealPath( psz_dir ); /* parse psz_src dir */ if( ( i_dir_content = vlc_scandir( psz_dir, &ppsz_dir_content, Filter, InsensitiveAlphasort ) ) == -1 ) { if( errno != ENOENT && errno != ENOTDIR ) msg_Warn( p_intf, "error while scanning dir %s (%m)", psz_dir ); free( psz_dir ); return s; } for( i = 0; i < i_dir_content; i++ ) { #ifdef HAVE_SYS_STAT_H struct stat stat_info; #endif char *psz_name = ppsz_dir_content[i], *psz_ext, *psz_dummy; char psz_tmp[strlen( psz_dir ) + 1 + strlen( psz_name ) + 1]; mvar_t *f; #if defined( WIN32 ) if( psz_dir[0] == '\0' || (psz_dir[0] == '\\' && psz_dir[1] == '\0') ) { strcpy( psz_tmp, psz_name ); } else #endif { sprintf( psz_tmp, "%s"DIR_SEP"%s", psz_dir, psz_name ); #ifdef HAVE_SYS_STAT_H if( vlc_stat( psz_tmp, &stat_info ) == -1 ) { free( psz_name ); continue; } #endif } f = mvar_New( name, "set" ); /* put lower-case file extension in 'ext' */ psz_ext = strrchr( psz_name, '.' ); psz_ext = strdup( psz_ext != NULL ? psz_ext + 1 : "" ); for( psz_dummy = psz_ext; *psz_dummy != '\0'; psz_dummy++ ) *psz_dummy = tolower( *psz_dummy ); mvar_AppendNewVar( f, "ext", psz_ext ); free( psz_ext ); #if defined( WIN32 ) if( psz_dir[0] == '\0' || (psz_dir[0] == '\\' && psz_dir[1] == '\0') ) { char psz_tmp[3]; sprintf( psz_tmp, "%c:", psz_name[0] ); mvar_AppendNewVar( f, "name", psz_name ); mvar_AppendNewVar( f, "basename", psz_tmp ); mvar_AppendNewVar( f, "type", "directory" ); mvar_AppendNewVar( f, "size", "unknown" ); mvar_AppendNewVar( f, "date", "unknown" ); } else #endif { char psz_buf[26]; char psz_tmp[strlen( psz_dir ) + 1 + strlen( psz_name ) + 1]; sprintf( psz_tmp, "%s"DIR_SEP"%s", psz_dir, psz_name ); mvar_AppendNewVar( f, "name", psz_tmp ); mvar_AppendNewVar( f, "basename", psz_name ); #ifdef HAVE_SYS_STAT_H if( S_ISDIR( stat_info.st_mode ) ) { mvar_AppendNewVar( f, "type", "directory" ); } else if( S_ISREG( stat_info.st_mode ) ) { mvar_AppendNewVar( f, "type", "file" ); } else { mvar_AppendNewVar( f, "type", "unknown" ); } snprintf( psz_buf, sizeof( psz_buf ), "%"PRId64, (int64_t)stat_info.st_size ); mvar_AppendNewVar( f, "size", psz_buf ); /* FIXME memory leak FIXME */ # ifdef HAVE_CTIME_R ctime_r( &stat_info.st_mtime, psz_buf ); mvar_AppendNewVar( f, "date", psz_buf ); # else mvar_AppendNewVar( f, "date", ctime( &stat_info.st_mtime ) ); # endif #else mvar_AppendNewVar( f, "type", "unknown" ); mvar_AppendNewVar( f, "size", "unknown" ); mvar_AppendNewVar( f, "date", "unknown" ); #endif } mvar_AppendVar( s, f ); free( psz_name ); } free( psz_dir ); free( ppsz_dir_content ); return s; }
static int vlc_sd_probe_Open( vlc_object_t *obj ) { vlc_probe_t *probe = (vlc_probe_t *)obj; char **ppsz_filelist = NULL; char **ppsz_fileend = NULL; char **ppsz_file; char *psz_name; char **ppsz_dir_list = NULL; char **ppsz_dir; lua_State *L = NULL; vlclua_dir_list( obj, "sd", &ppsz_dir_list ); for( ppsz_dir = ppsz_dir_list; *ppsz_dir; ppsz_dir++ ) { int i_files; if( ppsz_filelist ) { for( ppsz_file = ppsz_filelist; ppsz_file < ppsz_fileend; ppsz_file++ ) free( *ppsz_file ); free( ppsz_filelist ); ppsz_filelist = NULL; } i_files = vlc_scandir( *ppsz_dir, &ppsz_filelist, file_select, file_compare ); if( i_files < 1 ) continue; ppsz_fileend = ppsz_filelist + i_files; for( ppsz_file = ppsz_filelist; ppsz_file < ppsz_fileend; ppsz_file++ ) { char *psz_filename; if( asprintf( &psz_filename, "%s" DIR_SEP "%s", *ppsz_dir, *ppsz_file ) < 0 ) { goto error; } L = luaL_newstate(); if( !L ) { msg_Err( probe, "Could not create new Lua State" ); free( psz_filename ); goto error; } luaL_openlibs( L ); if( vlclua_add_modules_path( probe, L, psz_filename ) ) { msg_Err( probe, "Error while setting the module search path for %s", psz_filename ); free( psz_filename ); goto error; } if( luaL_dofile( L, psz_filename ) ) { msg_Err( probe, "Error loading script %s: %s", psz_filename, lua_tostring( L, lua_gettop( L ) ) ); lua_pop( L, 1 ); free( psz_filename ); lua_close( L ); continue; } char *psz_longname; char *temp = strchr( *ppsz_file, '.' ); if( temp ) *temp = '\0'; lua_getglobal( L, "descriptor" ); if( !lua_isfunction( L, lua_gettop( L ) ) || lua_pcall( L, 0, 1, 0 ) ) { msg_Warn( probe, "No 'descriptor' function in '%s'", psz_filename ); lua_pop( L, 1 ); if( !( psz_longname = strdup( *ppsz_file ) ) ) { free( psz_filename ); goto error; } } else { lua_getfield( L, -1, "title" ); if( !lua_isstring( L, -1 ) || !( psz_longname = strdup( lua_tostring( L, -1 ) ) ) ) { free( psz_filename ); goto error; } } char *psz_file_esc = config_StringEscape( *ppsz_file ); char *psz_longname_esc = config_StringEscape( psz_longname ); if( asprintf( &psz_name, "lua{sd='%s',longname='%s'}", psz_file_esc, psz_longname_esc ) < 0 ) { free( psz_file_esc ); free( psz_longname_esc ); free( psz_filename ); free( psz_longname ); goto error; } free( psz_file_esc ); free( psz_longname_esc ); vlc_sd_probe_Add( probe, psz_name, psz_longname, SD_CAT_INTERNET ); free( psz_name ); free( psz_longname ); free( psz_filename ); lua_close( L ); } } if( ppsz_filelist ) { for( ppsz_file = ppsz_filelist; ppsz_file < ppsz_fileend; ppsz_file++ ) free( *ppsz_file ); free( ppsz_filelist ); } vlclua_dir_list_free( ppsz_dir_list ); return VLC_PROBE_CONTINUE; error: if( ppsz_filelist ) { for( ppsz_file = ppsz_filelist; ppsz_file < ppsz_fileend; ppsz_file++ ) free( *ppsz_file ); free( ppsz_filelist ); } if( L ) lua_close( L ); vlclua_dir_list_free( ppsz_dir_list ); return VLC_ENOMEM; }
/** * @brief Scan files in a particular directory */ static void ScanFiles( monitoring_thread_t *p_mon, int i_dir_id, bool b_recursive, stat_list_t *stparent ) { int i_rows, i_cols, i_dir_content, i, i_mon_rows, i_mon_cols; char **ppsz_monitored_files; char **pp_results, *psz_dir; char **pp_dir_content; bool *pb_processed; input_item_t *p_input; struct stat s_stat; media_library_t *p_ml = (media_library_t *)p_mon->p_ml; Query( p_ml, &pp_results, &i_rows, &i_cols, "SELECT uri AS directory_uri FROM directories WHERE id = '%d'", i_dir_id ); if( i_rows < 1 ) { msg_Dbg( p_mon, "query returned no directory for dir_id: %d (%s:%d)", i_dir_id, __FILE__, __LINE__ ); return; } psz_dir = strdup( pp_results[1] ); FreeSQLResult( p_ml, pp_results ); struct stat_list_t stself; if( vlc_stat( psz_dir, &stself.st ) == -1 ) { msg_Err( p_ml, "Cannot stat `%s': %m", psz_dir ); free( psz_dir ); return; } #ifndef WIN32 for( stat_list_t *stats = stparent; stats != NULL; stats = stats->parent ) { if( ( stself.st.st_ino == stats->st.st_ino ) && ( stself.st.st_dev == stats->st.st_dev ) ) { msg_Warn( p_ml, "Ignoring infinitely recursive directory `%s'", psz_dir ); free( psz_dir ); return; } } #else /* Windows has st_dev (driver letter - 'A'), but it zeroes st_ino, * so that the test above will always incorrectly succeed. * Besides, Windows does not have dirfd(). */ #endif stself.parent = stparent; QuerySimple( p_ml, "UPDATE directories SET timestamp=%d WHERE id = %d", stself.st.st_mtime, i_dir_id ); Query( p_ml, &ppsz_monitored_files, &i_mon_rows, &i_mon_cols, "SELECT id AS media_id, timestamp AS media_ts, uri AS media_uri " "FROM media WHERE directory_id = %d", i_dir_id ); pb_processed = malloc(sizeof(bool) * i_mon_rows); for( i = 0; i < i_mon_rows ; i++) pb_processed[i] = false; i_dir_content = vlc_scandir( psz_dir, &pp_dir_content, NULL, Sort ); if( i_dir_content == -1 ) { msg_Err( p_mon, "Cannot read `%s': %m", psz_dir ); free( pb_processed ); free( psz_dir ); return; } else if( i_dir_content == 0 ) { msg_Dbg( p_mon, "Nothing in directory `%s'", psz_dir ); free( pb_processed ); free( psz_dir ); return; } for( i = 0; i < i_dir_content; i++ ) { const char *psz_entry = pp_dir_content[i]; if( psz_entry[0] != '.' ) { /* 7 is the size of "file://" */ char psz_uri[strlen(psz_dir) + strlen(psz_entry) + 2 + 7]; sprintf( psz_uri, "%s/%s", psz_dir, psz_entry ); if( vlc_stat( psz_uri, &s_stat ) == -1 ) { msg_Err( p_mon, "%s: %m", psz_uri ); free( pb_processed ); free( psz_dir ); return; } if( S_ISREG( s_stat.st_mode ) ) { const char *psz_dot = strrchr( psz_uri, '.' ); if( psz_dot++ && *psz_dot ) { int i_is_media = 0; for( int a = 0; ppsz_MediaExtensions[a]; a++ ) { if( !strcasecmp( psz_dot, ppsz_MediaExtensions[a] ) ) { i_is_media = 1; break; } } if( !i_is_media ) { msg_Dbg( p_mon, "ignoring file %s", psz_uri ); continue; } } char * psz_tmp = encode_URI_component( psz_uri ); char * psz_encoded_uri = ( char * )calloc( strlen( psz_tmp ) + 9, 1 ); strcpy( psz_encoded_uri, "file:///" ); strcat( psz_encoded_uri, psz_tmp ); free( psz_tmp ); /* Check if given media is already in DB and it has been updated */ bool b_skip = false; bool b_update = false; int j = 1; for( j = 1; j <= i_mon_rows; j++ ) { if( strcasecmp( ppsz_monitored_files[ j * i_mon_cols + 2 ], psz_encoded_uri ) != 0 ) continue; b_update = true; pb_processed[ j - 1 ] = true; if( atoi( ppsz_monitored_files[ j * i_mon_cols + 1 ] ) < s_stat.st_mtime ) { b_skip = false; break; } else { b_skip = true; break; } } msg_Dbg( p_ml , "Checking if %s is in DB. Found: %d", psz_encoded_uri, b_skip? 1 : 0 ); if( b_skip ) continue; p_input = input_item_New( psz_encoded_uri, psz_entry ); playlist_t* p_pl = pl_Get( p_mon ); preparsed_item_t* p_itemobject; p_itemobject = malloc( sizeof( preparsed_item_t ) ); p_itemobject->i_dir_id = i_dir_id; p_itemobject->psz_uri = psz_encoded_uri; p_itemobject->i_mtime = s_stat.st_mtime; p_itemobject->p_mon = p_mon; p_itemobject->b_update = b_update; p_itemobject->i_update_id = b_update ? atoi( ppsz_monitored_files[ j * i_mon_cols + 0 ] ) : 0 ; vlc_event_manager_t *p_em = &p_input->event_manager; vlc_event_attach( p_em, vlc_InputItemPreparsedChanged, PreparseComplete, p_itemobject ); playlist_PreparseEnqueue( p_pl, p_input ); } else if( S_ISDIR( s_stat.st_mode ) && b_recursive ) { Query( p_ml, &pp_results, &i_rows, &i_cols, "SELECT id AS directory_id FROM directories " "WHERE uri=%Q", psz_uri ); FreeSQLResult( p_ml, pp_results ); if( i_rows <= 0 ) { msg_Dbg( p_mon, "New directory `%s' in dir of id %d", psz_uri, i_dir_id ); QuerySimple( p_ml, "INSERT INTO directories (uri, timestamp, " "recursive) VALUES(%Q, 0, 1)", psz_uri ); // We get the id of the directory we've just added Query( p_ml, &pp_results, &i_rows, &i_cols, "SELECT id AS directory_id FROM directories WHERE uri=%Q", psz_uri ); if( i_rows <= 0 ) { msg_Err( p_mon, "Directory `%s' was not sucessfully" " added to the database", psz_uri ); FreeSQLResult( p_ml, pp_results ); continue; } ScanFiles( p_mon, atoi( pp_results[1] ), b_recursive, &stself ); FreeSQLResult( p_ml, pp_results ); } } } } vlc_array_t* delete_ids = vlc_array_new(); for( i = 0; i < i_mon_rows; i++ ) { if( !pb_processed[i] ) { /* This file doesn't exist anymore. Let's...urm...delete it. */ ml_element_t* find = ( ml_element_t* ) calloc( 1, sizeof( ml_element_t ) ); find->criteria = ML_ID; find->value.i = atoi( ppsz_monitored_files[ (i + 1) * i_mon_cols ] ); vlc_array_append( delete_ids, find ); } } /* Delete the unfound media */ if( Delete( p_ml, delete_ids ) != VLC_SUCCESS ) msg_Dbg( p_ml, "Something went wrong in multi delete" ); for( i = 0; i < vlc_array_count( delete_ids ); i++ ) { free( vlc_array_item_at_index( delete_ids, i ) ); } vlc_array_destroy( delete_ids ); FreeSQLResult( p_ml, ppsz_monitored_files ); for( i = 0; i < i_dir_content; i++ ) free( pp_dir_content[i] ); free( pp_dir_content ); free( psz_dir ); free( pb_processed ); }