* Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
* Samuel Hocevar <sam@zoy.org>
* Gildas Bazin <gbazin@videolan.org>
+ * Derk-Jan Hartman <hartman at videolan dot org>
+ * Christophe Massiot <massiot@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
# include <iconv.h>
#endif
+#ifdef HAVE_DIRENT_H
+# include <dirent.h>
+#endif
+
+#ifdef HAVE_FORK
+# include <sys/time.h>
+# include <unistd.h>
+# include <errno.h>
+# include <sys/wait.h>
+#endif
+
/*****************************************************************************
* getenv: just in case, but it should never be called
*****************************************************************************/
}
#endif
+/*****************************************************************************
+ * vlc_*dir_wrapper: wrapper under Windows to return the list of drive letters
+ * when called with an empty argument or just '\'
+ *****************************************************************************/
+#if defined(WIN32) || defined(UNDER_CE)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h> /* for GetLogicalDrives */
+
+typedef struct vlc_DIR
+{
+ DIR *p_real_dir;
+ int i_drives;
+ struct dirent dd_dir;
+ vlc_bool_t b_insert_back;
+} vlc_DIR;
+
+void *vlc_opendir_wrapper( const char *psz_path )
+{
+ vlc_DIR *p_dir;
+ DIR *p_real_dir;
+
+ if ( psz_path == NULL || psz_path[0] == '\0'
+ || (psz_path[0] == '\\' && psz_path[1] == '\0') )
+ {
+ /* Special mode to list drive letters */
+ p_dir = malloc( sizeof(vlc_DIR) );
+ p_dir->p_real_dir = NULL;
+ p_dir->i_drives = GetLogicalDrives();
+ return (void *)p_dir;
+ }
+
+ p_real_dir = opendir( psz_path );
+ if ( p_real_dir == NULL )
+ return NULL;
+
+ p_dir = malloc( sizeof(vlc_DIR) );
+ p_dir->p_real_dir = p_real_dir;
+ p_dir->b_insert_back = ( psz_path[1] == ':' && psz_path[2] == '\\'
+ && psz_path[3] =='\0' );
+ return (void *)p_dir;
+}
+
+struct dirent *vlc_readdir_wrapper( void *_p_dir )
+{
+ vlc_DIR *p_dir = (vlc_DIR *)_p_dir;
+ unsigned int i;
+ DWORD i_drives;
+
+ if ( p_dir->p_real_dir != NULL )
+ {
+ if ( p_dir->b_insert_back )
+ {
+ p_dir->dd_dir.d_ino = 0;
+ p_dir->dd_dir.d_reclen = 0;
+ p_dir->dd_dir.d_namlen = 2;
+ strcpy( p_dir->dd_dir.d_name, ".." );
+ p_dir->b_insert_back = VLC_FALSE;
+ return &p_dir->dd_dir;
+ }
+
+ return readdir( p_dir->p_real_dir );
+ }
+
+ /* Drive letters mode */
+ i_drives = p_dir->i_drives;
+ if ( !i_drives )
+ return NULL; /* end */
+
+ for ( i = 0; i < sizeof(DWORD)*8; i++, i_drives >>= 1 )
+ if ( i_drives & 1 ) break;
+
+ if ( i >= 26 )
+ return NULL; /* this should not happen */
+
+ sprintf( p_dir->dd_dir.d_name, "%c:\\", 'A' + i );
+ p_dir->dd_dir.d_namlen = strlen(p_dir->dd_dir.d_name);
+ p_dir->i_drives &= ~(1UL << i);
+ return &p_dir->dd_dir;
+}
+
+int vlc_closedir_wrapper( void *_p_dir )
+{
+ vlc_DIR *p_dir = (vlc_DIR *)_p_dir;
+
+ if ( p_dir->p_real_dir != NULL )
+ {
+ int i_ret = closedir( p_dir->p_real_dir );
+ free( p_dir );
+ return i_ret;
+ }
+
+ free( p_dir );
+ return 0;
+}
+#else
+void *vlc_opendir_wrapper( const char *psz_path )
+{
+ return (void *)opendir( psz_path );
+}
+struct dirent *vlc_readdir_wrapper( void *_p_dir )
+{
+ return readdir( (DIR *)_p_dir );
+}
+int vlc_closedir_wrapper( void *_p_dir )
+{
+ return closedir( (DIR *)_p_dir );
+}
+#endif
+
+/*****************************************************************************
+ * scandir: scan a directory alpha-sorted
+ *****************************************************************************/
+#if !defined( HAVE_SCANDIR )
+int vlc_alphasort( const struct dirent **a, const struct dirent **b )
+{
+ return strcoll( (*a)->d_name, (*b)->d_name );
+}
+
+int vlc_scandir( const char *name, struct dirent ***namelist,
+ int (*filter) ( const struct dirent * ),
+ int (*compar) ( const struct dirent **,
+ const struct dirent ** ) )
+{
+ DIR * p_dir;
+ struct dirent * p_content;
+ struct dirent ** pp_list;
+ int ret, size;
+
+ if( !namelist || !( p_dir = vlc_opendir_wrapper( name ) ) ) return -1;
+
+ ret = 0;
+ pp_list = NULL;
+ while( ( p_content = vlc_readdir_wrapper( p_dir ) ) )
+ {
+ if( filter && !filter( p_content ) )
+ {
+ continue;
+ }
+ pp_list = realloc( pp_list, ( ret + 1 ) * sizeof( struct dirent * ) );
+ size = sizeof( struct dirent ) + strlen( p_content->d_name ) + 1;
+ pp_list[ret] = malloc( size );
+ memcpy( pp_list[ret], p_content, size );
+ ret++;
+ }
+
+ vlc_closedir_wrapper( p_dir );
+
+ if( compar )
+ {
+ qsort( pp_list, ret, sizeof( struct dirent * ),
+ (int (*)(const void *, const void *)) compar );
+ }
+
+ *namelist = pp_list;
+ return ret;
+}
+#endif
+
/*****************************************************************************
* dgettext: gettext for plugins.
*****************************************************************************/
* reduce a fraction
* (adapted from libavcodec, author Michael Niedermayer <michaelni@gmx.at>)
*****************************************************************************/
-vlc_bool_t vlc_reduce( unsigned *pi_dst_nom, unsigned *pi_dst_den,
- uint64_t i_nom, uint64_t i_den, uint64_t i_max )
+vlc_bool_t vlc_ureduce( unsigned *pi_dst_nom, unsigned *pi_dst_den,
+ uint64_t i_nom, uint64_t i_den, uint64_t i_max )
{
vlc_bool_t b_exact = 1;
uint64_t i_gcd;
if( i_nom > i_max || i_den > i_max )
{
- uint i_a0_num = 0, i_a0_den = 1, i_a1_num = 1, i_a1_den = 0;
+ uint64_t i_a0_num = 0, i_a0_den = 1, i_a1_num = 1, i_a1_den = 0;
b_exact = 0;
for( ; ; )
free( psz_orig );
return argv;
}
+
+/*************************************************************************
+ * vlc_execve: Execute an external program with a given environment,
+ * wait until it finishes and return its standard output
+ *************************************************************************/
+int __vlc_execve( vlc_object_t *p_object, int i_argc, char **ppsz_argv,
+ char **ppsz_env, char *psz_cwd, char *p_in, int i_in,
+ char **pp_data, int *pi_data )
+{
+#ifdef HAVE_FORK
+ int pi_stdin[2];
+ int pi_stdout[2];
+ pid_t i_child_pid;
+
+ pipe( pi_stdin );
+ pipe( pi_stdout );
+
+ if ( (i_child_pid = fork()) == -1 )
+ {
+ msg_Err( p_object, "unable to fork (%s)", strerror(errno) );
+ return -1;
+ }
+
+ if ( i_child_pid == 0 )
+ {
+ close(0);
+ dup(pi_stdin[1]);
+ close(pi_stdin[0]);
+
+ close(1);
+ dup(pi_stdout[1]);
+ close(pi_stdout[0]);
+
+ close(2);
+
+ if ( psz_cwd != NULL )
+ chdir( psz_cwd );
+ execve( ppsz_argv[0], ppsz_argv, ppsz_env );
+ exit(1);
+ }
+
+ close(pi_stdin[1]);
+ close(pi_stdout[1]);
+ if ( !i_in )
+ close( pi_stdin[0] );
+
+ *pi_data = 0;
+ *pp_data = malloc( 1025 ); /* +1 for \0 */
+
+ while ( !p_object->b_die )
+ {
+ int i_ret, i_status;
+ fd_set readfds, writefds;
+ struct timeval tv;
+
+ FD_ZERO( &readfds );
+ FD_ZERO( &writefds );
+ FD_SET( pi_stdout[0], &readfds );
+ if ( i_in )
+ FD_SET( pi_stdin[0], &writefds );
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 10000;
+
+ i_ret = select( pi_stdin[0] > pi_stdout[0] ? pi_stdin[0] + 1 :
+ pi_stdout[0] + 1, &readfds, &writefds, NULL, &tv );
+ if ( i_ret > 0 )
+ {
+ if ( FD_ISSET( pi_stdout[0], &readfds ) )
+ {
+ ssize_t i_read = read( pi_stdout[0], &(*pp_data)[*pi_data],
+ 1024 );
+ if ( i_read > 0 )
+ {
+ *pi_data += i_read;
+ *pp_data = realloc( *pp_data, *pi_data + 1025 );
+ }
+ }
+ if ( FD_ISSET( pi_stdin[0], &writefds ) )
+ {
+ ssize_t i_write = write( pi_stdin[0], p_in, __MIN(i_in, 1024) );
+
+ if ( i_write > 0 )
+ {
+ p_in += i_write;
+ i_in -= i_write;
+ }
+ if ( !i_in )
+ close( pi_stdin[0] );
+ }
+ }
+
+ if ( waitpid( i_child_pid, &i_status, WNOHANG ) == i_child_pid )
+ {
+ if ( WIFEXITED( i_status ) )
+ {
+ if ( WEXITSTATUS( i_status ) )
+ {
+ msg_Warn( p_object,
+ "child %s returned with error code %d",
+ ppsz_argv[0], WEXITSTATUS( i_status ) );
+ }
+ }
+ else
+ {
+ if ( WIFSIGNALED( i_status ) )
+ {
+ msg_Warn( p_object,
+ "child %s quit on signal %d", ppsz_argv[0],
+ WTERMSIG( i_status ) );
+ }
+ }
+ if ( i_in )
+ close( pi_stdin[0] );
+ close( pi_stdout[0] );
+ break;
+ }
+
+ if ( i_ret < 0 && errno != EINTR )
+ {
+ msg_Warn( p_object, "select failed (%s)", strerror(errno) );
+ }
+ }
+
+#else
+ msg_Err( p_object, "vlc_execve called but no implementation is available" );
+ return -1;
+
+#endif
+
+ (*pp_data)[*pi_data] = '\0';
+
+ return 0;
+}