summaryrefslogtreecommitdiffstats
path: root/stream
diff options
context:
space:
mode:
authoral <al@b3059339-0415-0410-9bf9-f77b7e298cf2>2012-11-20 22:13:57 +0000
committerwm4 <wm4@nowhere>2012-11-21 20:03:58 +0100
commita04b35013a055926ab57f60137518a204ce9e753 (patch)
treebb9da663935bc7cdc3d88d3ee038fdc3b83dd745 /stream
parent73618d11d4108e8c3f9ada2cf85bc48352e70eee (diff)
downloadmpv-a04b35013a055926ab57f60137518a204ce9e753.tar.bz2
mpv-a04b35013a055926ab57f60137518a204ce9e753.tar.xz
stream_ftp: support longer filenames
This change was split into 8 patches. Squash them together, as they affect stream_ftp.c only. stream ftp: readline: Fix off-by-one error Even if max bytes are available read at most max - 1 bytes. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@35427 b3059339-0415-0410-9bf9-f77b7e298cf2 Conflicts: stream/stream_ftp.c stream ftp: readline: Always initialize output parameter buf Only exception if passed parameter max is less than or equal to zero. That cannot happen with the current code. Additionally change readresp function to always copy the first response line if the parameter rsp is non-NULL. This fixes some error reporting that used uninitialized stack arrays. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@35428 b3059339-0415-0410-9bf9-f77b7e298cf2 stream ftp: readline: Always try to read complete lines If there is not enough space in the provided line buffer just skip the remaining bytes until reaching EOL. Usually we are only interested in the first 5 characters and for everything else the (on-stack) response buffer should still be big enough. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@35429 b3059339-0415-0410-9bf9-f77b7e298cf2 stream ftp: Revise file descriptor usage * Set unbound descriptor variables to -1 * Always test >= 0 to see if a variable refers to a valid descriptor git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@35430 b3059339-0415-0410-9bf9-f77b7e298cf2 stream ftp: Only send QUIT command if connected Do not attempt to send commands without control connections. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@35431 b3059339-0415-0410-9bf9-f77b7e298cf2 stream ftp: Create buffers before opening control connection git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@35432 b3059339-0415-0410-9bf9-f77b7e298cf2 stream ftp: Allocate command buffer on-heap git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@35433 b3059339-0415-0410-9bf9-f77b7e298cf2 stream ftp: Increase command buffer size Allow for more longish file names (be it because of length or more lengthy characters). git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@35434 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'stream')
-rw-r--r--stream/stream_ftp.c104
1 files changed, 73 insertions, 31 deletions
diff --git a/stream/stream_ftp.c b/stream/stream_ftp.c
index 8485e0e969..6879881b8e 100644
--- a/stream/stream_ftp.c
+++ b/stream/stream_ftp.c
@@ -32,6 +32,8 @@
#include <winsock2.h>
#endif
+#include <libavutil/avutil.h>
+
#include "core/mp_msg.h"
#include "network.h"
#include "stream.h"
@@ -50,6 +52,7 @@ static struct stream_priv_s {
int handle;
int cavail,cleft;
char *buf;
+ char *cmd_buf;
} stream_priv_dflts = {
"anonymous","no@spam",
NULL,
@@ -58,11 +61,14 @@ static struct stream_priv_s {
NULL,
NULL,
- 0,
+ -1,
0,0,
- NULL
+ NULL,
+ NULL,
};
+#define CMD_BUFSIZE 8192
+
#define BUFSIZE 2048
#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
@@ -103,6 +109,14 @@ static int fd_can_read(int fd,int timeout) {
/*
* read a line of text
*
+ * If the line is too long to fit in the buffer, provided via parameters
+ * buf and max, the remaining characters are skipped. So the next call to
+ * this function is synchronized to the start of the following response
+ * line.
+ *
+ * The parameter buf will always be initialized as long as max is bigger
+ * then 1. If nothing is read it will contain an empty string.
+ *
* return -1 on error or bytecount
*/
static int readline(char *buf,int max,struct stream_priv_s *ctl)
@@ -111,9 +125,14 @@ static int readline(char *buf,int max,struct stream_priv_s *ctl)
char *end,*bp=buf;
int eof = 0;
+ if (max <= 0) {
+ return -1;
+ }
+ *bp = '\0';
+
do {
if (ctl->cavail > 0) {
- x = (max >= ctl->cavail) ? ctl->cavail : max-1;
+ x = FFMIN(ctl->cavail, max-1);
end = memccpy(bp,ctl->cget,'\n',x);
if (end != NULL)
x = end - bp;
@@ -134,8 +153,18 @@ static int readline(char *buf,int max,struct stream_priv_s *ctl)
}
}
if (max == 1) {
- *buf = '\0';
- break;
+ char *q = memchr(ctl->cget, '\n', ctl->cavail);
+
+ if (q) { // found EOL: update state and return
+ ++q;
+ ctl->cavail -= q - ctl->cget;
+ ctl->cget = q;
+
+ break;
+ }
+
+ // receive more data to find end of current line
+ ctl->cget = ctl->cput;
}
if (ctl->cput == ctl->cget) {
ctl->cput = ctl->cget = ctl->buf;
@@ -179,13 +208,14 @@ static int readresp(struct stream_priv_s* ctl,char* rsp)
{
static char response[256];
char match[5];
- int r;
+ int r, len;
- if (readline(response,256,ctl) == -1)
+ len = readline(response,256,ctl);
+ if (rsp) strcpy(rsp,response);
+ if (len == -1)
return 0;
r = atoi(response)/100;
- if(rsp) strcpy(rsp,response);
mp_msg(MSGT_STREAM,MSGL_V, "[ftp] < %s",response);
@@ -263,7 +293,7 @@ static int FtpOpenPort(struct stream_priv_s* p) {
static int FtpOpenData(stream_t* s,int64_t newpos) {
struct stream_priv_s* p = s->priv;
int resp;
- char str[256],rsp_txt[256];
+ char rsp_txt[256];
// Open a new connection
s->fd = FtpOpenPort(p);
@@ -271,21 +301,21 @@ static int FtpOpenData(stream_t* s,int64_t newpos) {
if(s->fd < 0) return 0;
if(newpos > 0) {
- snprintf(str,255,"REST %"PRId64, (int64_t)newpos);
+ snprintf(p->cmd_buf,CMD_BUFSIZE - 1,"REST %"PRId64, (int64_t)newpos);
- resp = FtpSendCmd(str,p,rsp_txt);
+ resp = FtpSendCmd(p->cmd_buf,p,rsp_txt);
if(resp != 3) {
- mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
+ mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",p->cmd_buf,rsp_txt);
newpos = 0;
}
}
// Get the file
- snprintf(str,255,"RETR %s",p->filename);
- resp = FtpSendCmd(str,p,rsp_txt);
+ snprintf(p->cmd_buf,CMD_BUFSIZE - 1,"RETR %s",p->filename);
+ resp = FtpSendCmd(p->cmd_buf,p,rsp_txt);
if(resp != 1) {
- mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
+ mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",p->cmd_buf,rsp_txt);
return 0;
}
@@ -333,7 +363,7 @@ static int seek(stream_t *s,int64_t newpos) {
// First close the fd
closesocket(s->fd);
- s->fd = 0;
+ s->fd = -1;
// Send send the telnet sequence needed to make the server react
@@ -369,15 +399,18 @@ static void close_f(stream_t *s) {
if(!p) return;
- if(s->fd > 0) {
+ if(s->fd >= 0) {
closesocket(s->fd);
- s->fd = 0;
+ s->fd = -1;
}
- FtpSendCmd("QUIT",p,NULL);
+ if (p->handle >= 0) {
+ FtpSendCmd("QUIT", p, NULL);
+ closesocket(p->handle);
+ }
- if(p->handle) closesocket(p->handle);
free(p->buf);
+ free(p->cmd_buf);
m_struct_free(&stream_opts,p);
}
@@ -388,7 +421,7 @@ static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
int resp;
int64_t len = 0;
struct stream_priv_s* p = (struct stream_priv_s*)opts;
- char str[256],rsp_txt[256];
+ char rsp_txt[256];
if(mode != STREAM_READ) {
mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] Unknown open mode %d\n",mode);
@@ -402,6 +435,16 @@ static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
return STREAM_ERROR;
}
+ // Allocate buffers
+ p->buf = malloc(BUFSIZE);
+ p->cmd_buf = malloc(CMD_BUFSIZE);
+
+ if (!p->buf || !p->cmd_buf) {
+ close_f(stream);
+ m_struct_free(&stream_opts,opts);
+ return STREAM_ERROR;
+ }
+
// Open the control connection
p->handle = connect2Server(p->host,p->port,1);
@@ -413,7 +456,6 @@ static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
// We got a connection, let's start serious things
stream->fd = -1;
stream->priv = p;
- p->buf = malloc(BUFSIZE);
if (readresp(p, NULL) == 0) {
close_f(stream);
@@ -421,20 +463,20 @@ static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
}
// Login
- snprintf(str,255,"USER %s",p->user);
- resp = FtpSendCmd(str,p,rsp_txt);
+ snprintf(p->cmd_buf,CMD_BUFSIZE - 1,"USER %s",p->user);
+ resp = FtpSendCmd(p->cmd_buf,p,rsp_txt);
// password needed
if(resp == 3) {
- snprintf(str,255,"PASS %s",p->pass);
- resp = FtpSendCmd(str,p,rsp_txt);
+ snprintf(p->cmd_buf,CMD_BUFSIZE - 1,"PASS %s",p->pass);
+ resp = FtpSendCmd(p->cmd_buf,p,rsp_txt);
if(resp != 2) {
- mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
+ mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",p->cmd_buf,rsp_txt);
close_f(stream);
return STREAM_ERROR;
}
} else if(resp != 2) {
- mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
+ mp_msg(MSGT_OPEN,MSGL_ERR, "[ftp] command '%s' failed: %s\n",p->cmd_buf,rsp_txt);
close_f(stream);
return STREAM_ERROR;
}
@@ -448,10 +490,10 @@ static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
}
// Get the filesize
- snprintf(str,255,"SIZE %s",p->filename);
- resp = FtpSendCmd(str,p,rsp_txt);
+ snprintf(p->cmd_buf,CMD_BUFSIZE - 1,"SIZE %s",p->filename);
+ resp = FtpSendCmd(p->cmd_buf,p,rsp_txt);
if(resp != 2) {
- mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",str,rsp_txt);
+ mp_msg(MSGT_OPEN,MSGL_WARN, "[ftp] command '%s' failed: %s\n",p->cmd_buf,rsp_txt);
} else {
int dummy;
sscanf(rsp_txt,"%d %"SCNd64,&dummy,&len);