X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faccess%2Fftp.c;h=cb7f639fdad6aff15dd7ffff0a826cf4c26f81d4;hb=ecc5eb9db29f4ae9c0ee1c667c51dd7fd0a6b887;hp=246ebe8e6de0c84c376ebc1dc30a88e1ab6e22f5;hpb=d18bfd92bb33df6e590efa02a55121ee75529b4f;p=vlc diff --git a/modules/access/ftp.c b/modules/access/ftp.c index 246ebe8e6d..cb7f639fda 100644 --- a/modules/access/ftp.c +++ b/modules/access/ftp.c @@ -1,7 +1,8 @@ /***************************************************************************** * ftp.c: FTP input module ***************************************************************************** - * Copyright (C) 2001-2005 the VideoLAN team + * Copyright (C) 2001-2006 the VideoLAN team + * Copyright © 2006 Rémi Denis-Courmont * $Id$ * * Authors: Laurent Aimar - original code @@ -25,32 +26,41 @@ /***************************************************************************** * Preamble *****************************************************************************/ -#include - #include -#include -#include "network.h" +#include + +#include +#include + +#include #include "vlc_url.h" +#include + +#ifndef IPPORT_FTP +# define IPPORT_FTP 21u +#endif /***************************************************************************** * Module descriptor *****************************************************************************/ -static int Open ( vlc_object_t * ); -static void Close( vlc_object_t * ); +static int InOpen ( vlc_object_t * ); +static void InClose( vlc_object_t * ); +static int OutOpen ( vlc_object_t * ); +static void OutClose( vlc_object_t * ); #define CACHING_TEXT N_("Caching value in ms") #define CACHING_LONGTEXT N_( \ - "Allows you to modify the default caching value for FTP streams. This " \ - "value should be set in millisecond units." ) + "Caching value for FTP streams. This " \ + "value should be set in milliseconds." ) #define USER_TEXT N_("FTP user name") -#define USER_LONGTEXT N_("Allows you to modify the user name that will " \ +#define USER_LONGTEXT N_("User name that will " \ "be used for the connection.") #define PASS_TEXT N_("FTP password") -#define PASS_LONGTEXT N_("Allows you to modify the password that will be " \ +#define PASS_LONGTEXT N_("Password that will be " \ "used for the connection.") #define ACCOUNT_TEXT N_("FTP account") -#define ACCOUNT_LONGTEXT N_("Allows you to modify the account that will be " \ +#define ACCOUNT_LONGTEXT N_("Account that will be " \ "used for the connection.") vlc_module_begin(); @@ -63,19 +73,29 @@ vlc_module_begin(); CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE ); add_string( "ftp-user", "anonymous", NULL, USER_TEXT, USER_LONGTEXT, VLC_FALSE ); - add_string( "ftp-pwd", "anonymous@dummy.org", NULL, PASS_TEXT, + add_string( "ftp-pwd", "anonymous@example.com", NULL, PASS_TEXT, PASS_LONGTEXT, VLC_FALSE ); add_string( "ftp-account", "anonymous", NULL, ACCOUNT_TEXT, ACCOUNT_LONGTEXT, VLC_FALSE ); add_shortcut( "ftp" ); - set_callbacks( Open, Close ); + set_callbacks( InOpen, InClose ); + + add_submodule(); + set_shortname( "FTP" ); + set_description( _("FTP upload output") ); + set_capability( "sout access", 0 ); + set_category( CAT_SOUT ); + set_subcategory( SUBCAT_SOUT_ACO ); + set_callbacks( OutOpen, OutClose ); vlc_module_end(); /***************************************************************************** * Local prototypes *****************************************************************************/ -static int Read( access_t *, uint8_t *, int ); +static ssize_t Read( access_t *, uint8_t *, size_t ); +static ssize_t Write( sout_access_out_t *, block_t * ); static int Seek( access_t *, int64_t ); +static int OutSeek( sout_access_out_t *, int64_t ); static int Control( access_t *, int, va_list ); struct access_sys_t @@ -84,48 +104,52 @@ struct access_sys_t int fd_cmd; int fd_data; - + char sz_epsv_ip[NI_MAXNUMERICHOST]; }; +#define GET_OUT_SYS( p_this ) \ + ((access_sys_t *)(((sout_access_out_t *)(p_this))->p_sys)) -static int ftp_SendCommand( access_t *, char *, ... ); -static int ftp_ReadCommand( access_t *, int *, char ** ); -static int ftp_StartStream( access_t *, int64_t ); -static int ftp_StopStream ( access_t *); +static int ftp_SendCommand( vlc_object_t *, access_sys_t *, const char *, ... ); +static int ftp_ReadCommand( vlc_object_t *, access_sys_t *, int *, char ** ); +static int ftp_StartStream( vlc_object_t *, access_sys_t *, int64_t ); +static int ftp_StopStream ( vlc_object_t *, access_sys_t * ); -static int Connect( access_t *p_access, access_sys_t *p_sys ) +static int Login( vlc_object_t *p_access, access_sys_t *p_sys ) { - int fd, i_answer; + int i_answer; char *psz; /* *** Open a TCP connection with server *** */ - msg_Dbg( p_access, "waiting for connection..." ); - p_sys->fd_cmd = fd = net_ConnectTCP( p_access, p_sys->url.psz_host, - p_sys->url.i_port ); - if( fd < 0 ) + int fd = p_sys->fd_cmd = net_ConnectTCP( p_access, p_sys->url.psz_host, + p_sys->url.i_port ); + if( fd == -1 ) { - msg_Err( p_access, "failed to connect with server" ); + msg_Err( p_access, "connection failed" ); + intf_UserFatal( p_access, VLC_FALSE, _("Network interaction failed"), + _("VLC could not connect with the given server.") ); return -1; } - for( ;; ) - { - if( ftp_ReadCommand( p_access, &i_answer, NULL ) != 1 ) - { - break; - } - } + while( ftp_ReadCommand( p_access, p_sys, &i_answer, NULL ) == 1 ); + if( i_answer / 100 != 2 ) { msg_Err( p_access, "connection rejected" ); + intf_UserFatal( p_access, VLC_FALSE, _("Network interaction failed"), + _("VLC's connection to the given server was rejected.") ); return -1; } msg_Dbg( p_access, "connection accepted (%d)", i_answer ); - psz = var_CreateGetString( p_access, "ftp-user" ); - if( ftp_SendCommand( p_access, "USER %s", psz ) < 0 || - ftp_ReadCommand( p_access, &i_answer, NULL ) < 0 ) + if( p_sys->url.psz_username && *p_sys->url.psz_username ) + psz = strdup( p_sys->url.psz_username ); + else + psz = var_CreateGetString( p_access, "ftp-user" ); + + if( ftp_SendCommand( p_access, p_sys, "USER %s", psz ) < 0 || + ftp_ReadCommand( p_access, p_sys, &i_answer, NULL ) < 0 ) { free( psz ); return -1; @@ -139,9 +163,13 @@ static int Connect( access_t *p_access, access_sys_t *p_sys ) break; case 3: msg_Dbg( p_access, "password needed" ); - psz = var_CreateGetString( p_access, "ftp-pwd" ); - if( ftp_SendCommand( p_access, "PASS %s", psz ) < 0 || - ftp_ReadCommand( p_access, &i_answer, NULL ) < 0 ) + if( p_sys->url.psz_password && *p_sys->url.psz_password ) + psz = strdup( p_sys->url.psz_password ); + else + psz = var_CreateGetString( p_access, "ftp-pwd" ); + + if( ftp_SendCommand( p_access, p_sys, "PASS %s", psz ) < 0 || + ftp_ReadCommand( p_access, p_sys, &i_answer, NULL ) < 0 ) { free( psz ); return -1; @@ -156,9 +184,9 @@ static int Connect( access_t *p_access, access_sys_t *p_sys ) case 3: msg_Dbg( p_access, "account needed" ); psz = var_CreateGetString( p_access, "ftp-account" ); - if( ftp_SendCommand( p_access, "ACCT %s", + if( ftp_SendCommand( p_access, p_sys, "ACCT %s", psz ) < 0 || - ftp_ReadCommand( p_access, &i_answer, NULL ) < 0 ) + ftp_ReadCommand( p_access, p_sys, &i_answer, NULL ) < 0 ) { free( psz ); return -1; @@ -168,6 +196,9 @@ static int Connect( access_t *p_access, access_sys_t *p_sys ) if( i_answer / 100 != 2 ) { msg_Err( p_access, "account rejected" ); + intf_UserFatal( p_access, VLC_FALSE, + _("Network interaction failed"), + _("Your account was rejected.") ); return -1; } msg_Dbg( p_access, "account accepted" ); @@ -175,83 +206,43 @@ static int Connect( access_t *p_access, access_sys_t *p_sys ) default: msg_Err( p_access, "password rejected" ); + intf_UserFatal( p_access, VLC_FALSE, + _("Network interaction failed"), + _("Your password was rejected.") ); return -1; } break; default: msg_Err( p_access, "user rejected" ); + intf_UserFatal( p_access, VLC_FALSE, + _("Network interaction failed"), + _("Your connection attempt to the server was rejected.") ); return -1; } return 0; } -/**************************************************************************** - * Open: connect to ftp server and ask for file - ****************************************************************************/ -static int Open( vlc_object_t *p_this ) +static int Connect( vlc_object_t *p_access, access_sys_t *p_sys ) { - access_t *p_access = (access_t*)p_this; - access_sys_t *p_sys; - char *psz; - - int i_answer; - char *psz_arg; - - /* Init p_access */ - p_access->pf_read = Read; - p_access->pf_block = NULL; - p_access->pf_seek = Seek; - p_access->pf_control = Control; - p_access->info.i_update = 0; - p_access->info.i_size = 0; - p_access->info.i_pos = 0; - p_access->info.b_eof = VLC_FALSE; - p_access->info.i_title = 0; - p_access->info.i_seekpoint = 0; - p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) ); - memset( p_sys, 0, sizeof( access_sys_t ) ); - p_sys->fd_cmd = -1; - p_sys->fd_data = -1; - - /* *** Parse URL and get server addr/port and path *** */ - psz = p_access->psz_path; - while( *psz == '/' ) - { - psz++; - } - vlc_UrlParse( &p_sys->url, psz, 0 ); - - if( p_sys->url.psz_host == NULL || *p_sys->url.psz_host == '\0' ) - { - msg_Err( p_access, "invalid server name" ); - goto exit_error; - } - if( p_sys->url.i_port <= 0 ) - { - p_sys->url.i_port = 21; /* default port */ - } - - /* FTP URLs are relative to user's default directory (RFC1738) - For absolute path use ftp://foo.bar//usr/local/etc/filename */ - - if( *p_sys->url.psz_path == '/' ) - p_sys->url.psz_path++; - - if( Connect( p_access, p_sys ) < 0 ) - goto exit_error; + if( Login( p_access, p_sys ) < 0 ) + return -1; /* Extended passive mode */ - if( ftp_SendCommand( p_access, "EPSV ALL" ) < 0 ) + if( ftp_SendCommand( p_access, p_sys, "EPSV ALL" ) < 0 ) { msg_Err( p_access, "cannot request extended passive mode" ); + net_Close( p_sys->fd_cmd ); return -1; } - if( ftp_ReadCommand( p_access, &i_answer, NULL ) == 2 ) + if( ftp_ReadCommand( p_access, p_sys, NULL, NULL ) == 2 ) { if( net_GetPeerAddress( p_sys->fd_cmd, p_sys->sz_epsv_ip, NULL ) ) - goto exit_error; + { + net_Close( p_sys->fd_cmd ); + return -1; + } } else { @@ -260,29 +251,81 @@ static int Open( vlc_object_t *p_this ) * understands EPSV ALL in the way, and hence won't allow PASV on * the initial connection. */ + msg_Info( p_access, "FTP Extended passive mode disabled" ); net_Close( p_sys->fd_cmd ); - p_sys->fd_cmd = -1; - *p_sys->sz_epsv_ip = '\0'; - - if( ( p_sys->fd_cmd = Connect( p_access, p_sys ) ) < 0 ) - goto exit_error; - msg_Info( p_access, "FTP Extended passive mode disabled" ); + if( Login( p_access, p_sys ) ) + { + net_Close( p_sys->fd_cmd ); + return -1; + } } - - /* binary mode */ - if( ftp_SendCommand( p_access, "TYPE I" ) < 0 || - ftp_ReadCommand( p_access, &i_answer, NULL ) != 2 ) + + /* check binary mode support */ + if( ftp_SendCommand( p_access, p_sys, "TYPE I" ) < 0 || + ftp_ReadCommand( p_access, p_sys, NULL, NULL ) != 2 ) { msg_Err( p_access, "cannot set binary transfer mode" ); - goto exit_error; + net_Close( p_sys->fd_cmd ); + return -1; } + return 0; +} + + +static int parseURL( vlc_url_t *url, const char *path ) +{ + if( path == NULL ) + return -1; + + /* *** Parse URL and get server addr/port and path *** */ + while( *path == '/' ) + path++; + + vlc_UrlParse( url, path, 0 ); + + if( url->psz_host == NULL || *url->psz_host == '\0' ) + return -1; + + if( url->i_port <= 0 ) + url->i_port = IPPORT_FTP; /* default port */ + + /* FTP URLs are relative to user's default directory (RFC1738) + For absolute path use ftp://foo.bar//usr/local/etc/filename */ + + if( *url->psz_path == '/' ) + url->psz_path++; + + return 0; +} + + +/**************************************************************************** + * Open: connect to ftp server and ask for file + ****************************************************************************/ +static int InOpen( vlc_object_t *p_this ) +{ + access_t *p_access = (access_t*)p_this; + access_sys_t *p_sys; + char *psz_arg; + + /* Init p_access */ + STANDARD_READ_ACCESS_INIT + p_sys->fd_data = -1; + + if( parseURL( &p_sys->url, p_access->psz_path ) ) + goto exit_error; + + if( Connect( p_this, p_sys ) ) + goto exit_error; + /* get size */ - if( ftp_SendCommand( p_access, "SIZE %s", p_sys->url.psz_path ) < 0 || - ftp_ReadCommand( p_access, &i_answer, &psz_arg ) != 2 ) + if( ftp_SendCommand( p_this, p_sys, "SIZE %s", p_sys->url.psz_path ) < 0 || + ftp_ReadCommand( p_this, p_sys, NULL, &psz_arg ) != 2 ) { msg_Err( p_access, "cannot get file size" ); + net_Close( p_sys->fd_cmd ); goto exit_error; } p_access->info.i_size = atoll( &psz_arg[4] ); @@ -290,9 +333,10 @@ static int Open( vlc_object_t *p_this ) msg_Dbg( p_access, "file size: "I64Fd, p_access->info.i_size ); /* Start the 'stream' */ - if( ftp_StartStream( p_access, 0 ) < 0 ) + if( ftp_StartStream( p_this, p_sys, 0 ) < 0 ) { msg_Err( p_access, "cannot retrieve file" ); + net_Close( p_sys->fd_cmd ); goto exit_error; } @@ -302,8 +346,45 @@ static int Open( vlc_object_t *p_this ) return VLC_SUCCESS; exit_error: - if( p_sys->fd_cmd >= 0 ) + vlc_UrlClean( &p_sys->url ); + free( p_sys ); + return VLC_EGENERIC; +} + +static int OutOpen( vlc_object_t *p_this ) +{ + sout_access_out_t *p_access = (sout_access_out_t *)p_this; + access_sys_t *p_sys; + + p_sys = malloc( sizeof( *p_sys ) ); + if( p_sys == NULL ) + return VLC_ENOMEM; + memset( p_sys, 0, sizeof( *p_sys ) ); + + /* Init p_access */ + p_sys->fd_data = -1; + + if( parseURL( &p_sys->url, p_access->psz_path ) ) + goto exit_error; + + if( Connect( p_this, p_sys ) ) + goto exit_error; + + /* Start the 'stream' */ + if( ftp_StartStream( p_this, p_sys, 0 ) < 0 ) + { + msg_Err( p_access, "cannot store file" ); net_Close( p_sys->fd_cmd ); + goto exit_error; + } + + p_access->pf_seek = OutSeek; + p_access->pf_write = Write; + p_access->p_sys = (void *)p_sys; + + return VLC_SUCCESS; + +exit_error: vlc_UrlClean( &p_sys->url ); free( p_sys ); return VLC_EGENERIC; @@ -312,21 +393,18 @@ exit_error: /***************************************************************************** * Close: free unused data structures *****************************************************************************/ -static void Close( vlc_object_t *p_this ) +static void Close( vlc_object_t *p_access, access_sys_t *p_sys ) { - access_t *p_access = (access_t*)p_this; - access_sys_t *p_sys = p_access->p_sys; - msg_Dbg( p_access, "stopping stream" ); - ftp_StopStream( p_access ); + ftp_StopStream( p_access, p_sys ); - if( ftp_SendCommand( p_access, "QUIT" ) < 0 ) + if( ftp_SendCommand( p_access, p_sys, "QUIT" ) < 0 ) { msg_Warn( p_access, "cannot quit" ); } else { - ftp_ReadCommand( p_access, NULL, NULL ); + ftp_ReadCommand( p_access, p_sys, NULL, NULL ); } net_Close( p_sys->fd_cmd ); @@ -335,23 +413,39 @@ static void Close( vlc_object_t *p_this ) free( p_sys ); } +static void InClose( vlc_object_t *p_this ) +{ + Close( p_this, ((access_t *)p_this)->p_sys); +} + +static void OutClose( vlc_object_t *p_this ) +{ + Close( p_this, GET_OUT_SYS(p_this)); +} + + /***************************************************************************** * Seek: try to go at the right place *****************************************************************************/ -static int Seek( access_t *p_access, int64_t i_pos ) +static int _Seek( vlc_object_t *p_access, access_sys_t *p_sys, int64_t i_pos ) { if( i_pos < 0 ) - { return VLC_EGENERIC; - } + msg_Dbg( p_access, "seeking to "I64Fd, i_pos ); - ftp_StopStream( p_access ); - if( ftp_StartStream( p_access, i_pos ) < 0 ) - { - p_access->info.b_eof = VLC_TRUE; + ftp_StopStream( (vlc_object_t *)p_access, p_sys ); + if( ftp_StartStream( (vlc_object_t *)p_access, p_sys, i_pos ) < 0 ) return VLC_EGENERIC; - } + + return VLC_SUCCESS; +} + +static int Seek( access_t *p_access, int64_t i_pos ) +{ + int val = _Seek( (vlc_object_t *)p_access, p_access->p_sys, i_pos ); + if( val ) + return val; p_access->info.b_eof = VLC_FALSE; p_access->info.i_pos = i_pos; @@ -359,14 +453,22 @@ static int Seek( access_t *p_access, int64_t i_pos ) return VLC_SUCCESS; } +static int OutSeek( sout_access_out_t *p_access, off_t i_pos ) +{ + return _Seek( (vlc_object_t *)p_access, GET_OUT_SYS( p_access ), i_pos); +} + /***************************************************************************** * Read: *****************************************************************************/ -static int Read( access_t *p_access, uint8_t *p_buffer, int i_len ) +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->fd_data != -1 ); + assert( p_access->i_object_type == VLC_OBJECT_ACCESS ); + if( p_access->info.b_eof ) return 0; @@ -380,6 +482,30 @@ static int Read( access_t *p_access, uint8_t *p_buffer, int i_len ) return i_read; } +/***************************************************************************** + * Write: + *****************************************************************************/ +static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer ) +{ + access_sys_t *p_sys = GET_OUT_SYS(p_access); + size_t i_write = 0; + + assert( p_sys->fd_data != -1 ); + + while( p_buffer != NULL ) + { + block_t *p_next = p_buffer->p_next;; + + i_write += net_Write( p_access, p_sys->fd_data, NULL, + p_buffer->p_buffer, p_buffer->i_buffer ); + block_Release( p_buffer ); + + p_buffer = p_next; + } + + return i_write; +} + /***************************************************************************** * Control: *****************************************************************************/ @@ -431,6 +557,7 @@ static int Control( access_t *p_access, int i_query, va_list args ) case ACCESS_SET_TITLE: case ACCESS_SET_SEEKPOINT: case ACCESS_SET_PRIVATE_ID_STATE: + case ACCESS_GET_CONTENT_TYPE: return VLC_EGENERIC; default: @@ -444,9 +571,9 @@ static int Control( access_t *p_access, int i_query, va_list args ) /***************************************************************************** * ftp_*: *****************************************************************************/ -static int ftp_SendCommand( access_t *p_access, char *psz_fmt, ... ) +static int ftp_SendCommand( vlc_object_t *p_access, access_sys_t *p_sys, + const char *psz_fmt, ... ) { - access_sys_t *p_sys = p_access->p_sys; va_list args; char *psz_cmd; @@ -479,15 +606,13 @@ static int ftp_SendCommand( access_t *p_access, char *psz_fmt, ... ) These strings are not part of the requests, except in the case \377\377, where the request contains one \377. */ -static int ftp_ReadCommand( access_t *p_access, +static int ftp_ReadCommand( vlc_object_t *p_access, access_sys_t *p_sys, int *pi_answer, char **ppsz_answer ) { - access_sys_t *p_sys = p_access->p_sys; char *psz_line; int i_answer; psz_line = net_Gets( p_access, p_sys->fd_cmd, NULL ); - msg_Dbg( p_access, "answer=%s", psz_line ); if( psz_line == NULL || strlen( psz_line ) < 3 ) { msg_Err( p_access, "cannot get answer" ); @@ -496,6 +621,7 @@ static int ftp_ReadCommand( access_t *p_access, if( ppsz_answer ) *ppsz_answer = NULL; return -1; } + msg_Dbg( p_access, "answer=%s", psz_line ); if( psz_line[3] == '-' ) /* Multiple response */ { @@ -534,19 +660,18 @@ static int ftp_ReadCommand( access_t *p_access, return( i_answer / 100 ); } -static int ftp_StartStream( access_t *p_access, off_t i_start ) +static int ftp_StartStream( vlc_object_t *p_access, access_sys_t *p_sys, + off_t i_start ) { - access_sys_t *p_sys = p_access->p_sys; - - char psz_ipv4[16], *psz_ip; + char psz_ipv4[16], *psz_ip = p_sys->sz_epsv_ip; int i_answer; char *psz_arg, *psz_parser; int i_port; - psz_ip = p_sys->sz_epsv_ip; + assert( p_sys->fd_data == -1 ); - if( ( ftp_SendCommand( p_access, *psz_ip ? "EPSV" : "PASV" ) < 0 ) - || ( ftp_ReadCommand( p_access, &i_answer, &psz_arg ) != 2 ) ) + if( ( ftp_SendCommand( p_access, p_sys, *psz_ip ? "EPSV" : "PASV" ) < 0 ) + || ( ftp_ReadCommand( p_access, p_sys, &i_answer, &psz_arg ) != 2 ) ) { msg_Err( p_access, "cannot set passive mode" ); return VLC_EGENERIC; @@ -560,7 +685,7 @@ static int ftp_StartStream( access_t *p_access, off_t i_start ) return VLC_EGENERIC; } - if( psz_ip != NULL ) + if( *psz_ip ) { char psz_fmt[7] = "(|||%u"; psz_fmt[1] = psz_fmt[2] = psz_fmt[3] = psz_parser[1]; @@ -574,7 +699,7 @@ static int ftp_StartStream( access_t *p_access, off_t i_start ) } else { - unsigned a1, a2, a3, a4, p1, p2; + unsigned a1, a2, a3, a4, p1, p2; if( ( sscanf( psz_parser, "(%u,%u,%u,%u,%u,%u", &a1, &a2, &a3, &a4, &p1, &p2 ) < 6 ) || ( a1 > 255 ) || ( a2 > 255 ) @@ -593,8 +718,8 @@ static int ftp_StartStream( access_t *p_access, off_t i_start ) msg_Dbg( p_access, "ip:%s port:%d", psz_ip, i_port ); - if( ftp_SendCommand( p_access, "TYPE I" ) < 0 || - ftp_ReadCommand( p_access, &i_answer, NULL ) != 2 ) + if( ftp_SendCommand( p_access, p_sys, "TYPE I" ) < 0 || + ftp_ReadCommand( p_access, p_sys, &i_answer, NULL ) != 2 ) { msg_Err( p_access, "cannot set binary transfer mode" ); return VLC_EGENERIC; @@ -602,10 +727,10 @@ static int ftp_StartStream( access_t *p_access, off_t i_start ) if( i_start > 0 ) { - if( ftp_SendCommand( p_access, "REST "I64Fu, i_start ) < 0 || - ftp_ReadCommand( p_access, &i_answer, NULL ) > 3 ) + if( ftp_SendCommand( p_access, p_sys, "REST "I64Fu, i_start ) < 0 || + ftp_ReadCommand( p_access, p_sys, &i_answer, NULL ) > 3 ) { - msg_Err( p_access, "cannot set restart point" ); + msg_Err( p_access, "cannot set restart offset" ); return VLC_EGENERIC; } } @@ -621,22 +746,25 @@ static int ftp_StartStream( access_t *p_access, off_t i_start ) psz_ip, i_port ); /* "1xx" message */ - if( ftp_SendCommand( p_access, "RETR %s", p_sys->url.psz_path ) < 0 || - ftp_ReadCommand( p_access, &i_answer, NULL ) > 2 ) + if( ftp_SendCommand( p_access, p_sys, "%s %s", + (p_access->i_object_type == VLC_OBJECT_ACCESS) + ? "RETR" : "STOR", + p_sys->url.psz_path ) < 0 || + ftp_ReadCommand( p_access, p_sys, &i_answer, NULL ) > 2 ) { - msg_Err( p_access, "cannot retreive file" ); + msg_Err( p_access, "cannot retrieve file" ); return VLC_EGENERIC; } + + shutdown( p_sys->fd_data, + ( p_access->i_object_type == VLC_OBJECT_ACCESS ) ); + return VLC_SUCCESS; } -static int ftp_StopStream ( access_t *p_access ) +static int ftp_StopStream ( vlc_object_t *p_access, access_sys_t *p_sys ) { - access_sys_t *p_sys = p_access->p_sys; - - int i_answer; - - if( ftp_SendCommand( p_access, "ABOR" ) < 0 ) + if( ftp_SendCommand( p_access, p_sys, "ABOR" ) < 0 ) { msg_Warn( p_access, "cannot abort file" ); if( p_sys->fd_data > 0 ) @@ -644,14 +772,14 @@ static int ftp_StopStream ( access_t *p_access ) p_sys->fd_data = -1; return VLC_EGENERIC; } - if( p_sys->fd_data > 0 ) + + if( p_sys->fd_data != -1 ) { net_Close( p_sys->fd_data ); p_sys->fd_data = -1; - ftp_ReadCommand( p_access, &i_answer, NULL ); + ftp_ReadCommand( p_access, p_sys, NULL, NULL ); } - ftp_ReadCommand( p_access, &i_answer, NULL ); + ftp_ReadCommand( p_access, p_sys, NULL, NULL ); return VLC_SUCCESS; } -