[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