[vlc-devel] [PATCH 2/3] ftp: implement readdir
Thomas Guillem
thomas at gllm.fr
Sun May 3 19:38:04 CEST 2015
On Sun, May 3, 2015, at 19:36, Thomas Guillem wrote:
> ---
> modules/access/ftp.c | 129
> +++++++++++++++++++++++++++++++++++++--------------
> 1 file changed, 93 insertions(+), 36 deletions(-)
>
> diff --git a/modules/access/ftp.c b/modules/access/ftp.c
> index fa22a20..e16a0c4 100644
> --- a/modules/access/ftp.c
> +++ b/modules/access/ftp.c
> @@ -37,6 +37,7 @@
>
> #include <vlc_access.h>
> #include <vlc_dialog.h>
> +#include <vlc_input_item.h>
>
> #include <vlc_network.h>
> #include <vlc_url.h>
> @@ -105,6 +106,8 @@ vlc_module_end ()
> static ssize_t Read( access_t *, uint8_t *, size_t );
> static int Seek( access_t *, uint64_t );
> static int Control( access_t *, int, va_list );
> +static int DirRead( access_t *, input_item_node_t * );
> +static int DirControl( access_t *, int, va_list );
> #ifdef ENABLE_SOUT
> static int OutSeek( sout_access_out_t *, off_t );
> static ssize_t Write( sout_access_out_t *, block_t * );
> @@ -141,7 +144,6 @@ struct access_sys_t
>
> char sz_epsv_ip[NI_MAXNUMERICHOST];
> bool out;
> - bool directory;
> uint64_t size;
> };
> #define GET_OUT_SYS( p_this ) \
> @@ -263,7 +265,7 @@ static int ftp_RecvCommand( vlc_object_t *obj,
> access_sys_t *sys,
> return ftp_RecvAnswer( obj, sys, codep, strp, DummyLine, NULL );
> }
>
> -static int ftp_StartStream( vlc_object_t *, access_sys_t *, uint64_t );
> +static int ftp_StartStream( vlc_object_t *, access_sys_t *, uint64_t,
> bool );
> static int ftp_StopStream ( vlc_object_t *, access_sys_t * );
>
> static void readTLSMode( access_sys_t *p_sys, const char * psz_access )
> @@ -614,12 +616,15 @@ static int InOpen( vlc_object_t *p_this )
> access_t *p_access = (access_t*)p_this;
> access_sys_t *p_sys;
> char *psz_arg;
> + bool b_directory = false;
>
> /* Init p_access */
> - STANDARD_READ_ACCESS_INIT
> + access_InitFields( p_access );
> + p_sys = p_access->p_sys = (access_sys_t*)calloc( 1, sizeof(
> access_sys_t ) );
> + if( !p_sys )
> + return VLC_ENOMEM;
> p_sys->data.fd = -1;
> p_sys->out = false;
> - p_sys->directory = false;
> p_sys->size = 0;
> readTLSMode( p_sys, p_access->psz_access );
>
> @@ -631,7 +636,7 @@ static int InOpen( vlc_object_t *p_this )
>
> /* get size */
> if( p_sys->url.psz_path == NULL )
> - p_sys->directory = true;
> + b_directory = true;
> else
> if( ftp_SendCommand( p_this, p_sys, "SIZE %s", p_sys->url.psz_path )
> < 0 )
> goto error;
> @@ -652,10 +657,20 @@ static int InOpen( vlc_object_t *p_this )
> goto error;
> }
> else
> - p_sys->directory = true;
> + b_directory = true;
> +
> + if( b_directory )
> + {
> + p_access->pf_readdir = DirRead;
> + p_access->pf_control = DirControl;
> + }
> + else
> + {
> + ACCESS_SET_CALLBACKS( Read, NULL, Control, Seek ); \
> + }
>
> /* Start the 'stream' */
> - if( ftp_StartStream( p_this, p_sys, 0 ) < 0 )
> + if( ftp_StartStream( p_this, p_sys, 0, b_directory ) < 0 )
> {
> msg_Err( p_this, "cannot retrieve file" );
> clearCmdTLS( p_sys );
> @@ -702,7 +717,7 @@ static int OutOpen( vlc_object_t *p_this )
> goto exit_error;
>
> /* Start the 'stream' */
> - if( ftp_StartStream( p_this, p_sys, 0 ) < 0 )
> + if( ftp_StartStream( p_this, p_sys, 0, false ) < 0 )
> {
> msg_Err( p_access, "cannot store file" );
> clearCmdTLS( p_sys );
> @@ -769,7 +784,7 @@ static int _Seek( vlc_object_t *p_access,
> access_sys_t *p_sys, uint64_t i_pos )
> msg_Dbg( p_access, "seeking to %"PRIu64, i_pos );
>
> ftp_StopStream( (vlc_object_t *)p_access, p_sys );
> - if( ftp_StartStream( (vlc_object_t *)p_access, p_sys, i_pos ) < 0 )
> + if( ftp_StartStream( (vlc_object_t *)p_access, p_sys, i_pos, false )
> < 0 )
> return VLC_EGENERIC;
>
> return VLC_SUCCESS;
> @@ -800,6 +815,7 @@ static int OutSeek( sout_access_out_t *p_access,
> off_t i_pos )
> static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len
> )
> {
> access_sys_t *p_sys = p_access->p_sys;
> + int i_read;
>
> assert( p_sys->data.fd != -1 );
> assert( !p_sys->out );
> @@ -807,36 +823,48 @@ static ssize_t Read( access_t *p_access, uint8_t
> *p_buffer, size_t i_len )
> if( p_access->info.b_eof )
> return 0;
>
> - if( p_sys->directory )
> + i_read = net_Read( p_access, p_sys->data.fd, p_sys->data.p_vs,
> + p_buffer, i_len, false );
> + if( i_read == 0 )
> + p_access->info.b_eof = true;
> + else if( i_read > 0 )
> + p_access->info.i_pos += i_read;
> +
> + return i_read;
> +}
> +
> +/*****************************************************************************
> + * DirRead:
> +
> *****************************************************************************/
> +static int DirRead (access_t *p_access, input_item_node_t
> *p_current_node)
> +{
> + access_sys_t *p_sys = p_access->p_sys;
> + char *psz_line;
> +
> + assert( p_sys->data.fd != -1 );
> + assert( !p_sys->out );
> +
> + while( ( psz_line = net_Gets( p_access, p_sys->data.fd,
> p_sys->data.p_vs ) ) )
> {
> - char *psz_line = net_Gets( p_access, p_sys->data.fd,
> p_sys->data.p_vs );
> - if( !psz_line )
> - {
> - p_access->info.b_eof = true;
> - return 0;
> - }
> - else
> - {
> - snprintf( (char*)p_buffer, i_len, "%s://%s:%d/%s/%s\n",
> + char *psz_uri;
> +
> + if( asprintf( &psz_uri, "%s://%s:%d/%s/%s",
> ( p_sys->tlsmode == NONE ) ? "ftp" :
> ( ( p_sys->tlsmode == IMPLICIT ) ? "ftps" :
> "ftpes" ),
> p_sys->url.psz_host, p_sys->url.i_port,
> - p_sys->url.psz_path, psz_line );
> - free( psz_line );
> - return strlen( (const char *)p_buffer );
> + p_sys->url.psz_path, psz_line ) != -1 )
> + {
> + input_item_t *p_item;
> +
> + p_item = input_item_NewWithTypeExt( psz_uri, psz_line, 0,
> NULL,
> + 0, -1,
> ITEM_TYPE_UNKNOWN, 1 );
I would like to identify the file type: file or directory.
I wonder if it's possible without doing a "CWD psz_uri" and "CDUP" from
here.
"NLST -l" can give a full listing but I think that the parsing will be
OS/server dependent.
> + input_item_CopyOptions( p_current_node->p_item, p_item );
> + input_item_node_AppendItem( p_current_node, p_item );
> + free( psz_uri );
> }
> + free( psz_line );
> }
> - else
> - {
> - int i_read = net_Read( p_access, p_sys->data.fd,
> p_sys->data.p_vs,
> - p_buffer, i_len, false );
> - if( i_read == 0 )
> - p_access->info.b_eof = true;
> - else if( i_read > 0 )
> - p_access->info.i_pos += i_read;
> -
> - return i_read;
> - }
> + return VLC_SUCCESS;
> }
>
> /*****************************************************************************
> @@ -877,7 +905,7 @@ static int Control( access_t *p_access, int i_query,
> va_list args )
> {
> case ACCESS_CAN_SEEK:
> pb_bool = (bool*)va_arg( args, bool* );
> - *pb_bool = !p_access->p_sys->directory;
> + *pb_bool = true;
> break;
> case ACCESS_CAN_FASTSEEK:
> pb_bool = (bool*)va_arg( args, bool* );
> @@ -914,8 +942,37 @@ static int Control( access_t *p_access, int i_query,
> va_list args )
> return VLC_SUCCESS;
> }
>
> +/*****************************************************************************
> + * DirControl:
> +
> *****************************************************************************/
> +static int DirControl( access_t *p_access, int i_query, va_list args )
> +{
> + VLC_UNUSED( p_access );
> +
> + switch( i_query )
> + {
> + case ACCESS_CAN_SEEK:
> + case ACCESS_CAN_FASTSEEK:
> + *va_arg( args, bool* ) = false;
> + break;
> +
> + case ACCESS_CAN_PAUSE:
> + case ACCESS_CAN_CONTROL_PACE:
> + *va_arg( args, bool* ) = true;
> + break;
> +
> + case ACCESS_GET_PTS_DELAY:
> + *va_arg( args, int64_t * ) = DEFAULT_PTS_DELAY * 1000;
> + break;
> +
> + default:
> + return VLC_EGENERIC;
> + }
> + return VLC_SUCCESS;
> +}
> +
> static int ftp_StartStream( vlc_object_t *p_access, access_sys_t *p_sys,
> - uint64_t i_start )
> + uint64_t i_start, bool b_directory )
> {
> char psz_ipv4[16], *psz_ip = p_sys->sz_epsv_ip;
> int i_answer;
> @@ -999,7 +1056,7 @@ static int ftp_StartStream( vlc_object_t *p_access,
> access_sys_t *p_sys,
> msg_Dbg( p_access, "connection with \"%s:%d\" successful",
> psz_ip, i_port );
>
> - if( p_sys->directory )
> + if( b_directory )
> {
> if( ftp_SendCommand( p_access, p_sys, "NLST" ) < 0 ||
> ftp_RecvCommand( p_access, p_sys, NULL, &psz_arg ) > 2 )
> --
> 2.1.4
>
More information about the vlc-devel
mailing list