Wip/drun subdirs (#416)

* drun: Walk subdirectories too

Signed-off-by: Quentin Glidic <sardemff7+git@sardemff7.net>

* Remove goto, make it work for Filesystems that do not support reporting file type.

* Fix using filename before creating it.

* Run indenter over drun file.

* Fix stupid typo
This commit is contained in:
Dave Davenport 2016-06-05 19:01:38 +02:00
parent 9149e35248
commit 3f31620a3e
1 changed files with 64 additions and 42 deletions

View File

@ -32,6 +32,7 @@
#include <limits.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <strings.h>
#include <string.h>
@ -197,27 +198,64 @@ static void read_desktop_file ( DRunModePrivateData *pd, char *path, const char
/**
* Internal spider used to get list of executables.
*/
static void get_apps_dir ( DRunModePrivateData *pd, const char *bp )
static void walk_dir ( DRunModePrivateData *pd, const char *dirname )
{
DIR *dir = opendir ( bp );
DIR *dir;
if ( dir != NULL ) {
struct dirent *dent;
dir = opendir ( dirname );
if ( dir == NULL ) {
return;
}
while ( ( dent = readdir ( dir ) ) != NULL ) {
if ( dent->d_type != DT_REG && dent->d_type != DT_LNK && dent->d_type != DT_UNKNOWN ) {
continue;
}
// Skip dot files.
if ( dent->d_name[0] == '.' ) {
continue;
}
gchar *path = g_build_filename ( bp, dent->d_name, NULL );
read_desktop_file ( pd, path, dent->d_name );
struct dirent *file;
gchar *filename = NULL;
struct stat st;
while ( ( file = readdir ( dir ) ) != NULL ) {
if ( file->d_name[0] == '.' ) {
continue;
}
closedir ( dir );
switch ( file->d_type )
{
case DT_LNK:
case DT_REG:
case DT_DIR:
case DT_UNKNOWN:
filename = g_build_filename ( dirname, file->d_name, NULL );
break;
default:
continue;
}
// On a link, or if FS does not support providing this information
// Fallback to stat method.
if ( file->d_type == DT_LNK || file->d_type == DT_UNKNOWN ) {
file->d_type = DT_UNKNOWN;
if ( stat ( filename, &st ) == 0 ) {
if ( S_ISDIR ( st.st_mode ) ) {
file->d_type = DT_DIR;
}
else if ( S_ISREG ( st.st_mode ) ) {
file->d_type = DT_REG;
}
}
}
switch ( file->d_type )
{
case DT_REG:
read_desktop_file ( pd, filename, file->d_name );
filename = NULL;
break;
case DT_DIR:
walk_dir ( pd, filename );
break;
default:
break;
}
g_free ( filename );
}
closedir ( dir );
}
/**
* @param entry The command entry to remove from history
@ -232,6 +270,7 @@ static void delete_entry_history ( const DRunModeEntry *entry )
g_free ( path );
}
static void get_apps_history ( DRunModePrivateData *pd )
{
unsigned int length = 0;
@ -246,38 +285,21 @@ static void get_apps_history ( DRunModePrivateData *pd )
g_free ( retv );
pd->history_length = pd->cmd_list_length;
}
static void get_apps ( DRunModePrivateData *pd )
{
get_apps_history ( pd );
const char * const * dr = g_get_system_data_dirs ();
const char * const * iter = dr;
while ( iter != NULL && *iter != NULL && **iter != '\0' ) {
gboolean skip = FALSE;
for ( size_t i = 0; !skip && dr[i] != ( *iter ); i++ ) {
skip = ( g_strcmp0 ( *iter, dr[i] ) == 0 );
}
if ( skip ) {
iter++;
continue;
}
gchar *bp = g_build_filename ( *iter, "applications", NULL );
get_apps_dir ( pd, bp );
g_free ( bp );
iter++;
}
const char *d = g_get_user_data_dir ();
for ( size_t i = 0; dr && dr[i] != NULL; i++ ) {
if ( g_strcmp0 ( d, dr[i] ) == 0 ) {
// Done this already, no need to repeat.
return;
}
}
if ( d ) {
gchar *bp = g_build_filename ( d, "applications", NULL );
get_apps_dir ( pd, bp );
g_free ( bp );
gchar *dir;
const gchar * const * sys = g_get_system_data_dirs ();
for (; *sys != NULL; ++sys ) {
dir = g_build_filename ( *sys, "applications", NULL );
walk_dir ( pd, dir );
g_free ( dir );
}
dir = g_build_filename ( g_get_user_data_dir (), "applications", NULL );
walk_dir ( pd, dir );
g_free ( dir );
}
static int drun_mode_init ( Mode *sw )