From patchwork Sat Feb 8 21:18:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 17728 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 304A044B956 for ; Sat, 8 Feb 2020 23:19:30 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1F1F568B05C; Sat, 8 Feb 2020 23:19:30 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8663768B0B0 for ; Sat, 8 Feb 2020 23:19:28 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 5EB7AE3925; Sat, 8 Feb 2020 22:19:28 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id IyxdMxoufhYr; Sat, 8 Feb 2020 22:19:26 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 41F72E3B93; Sat, 8 Feb 2020 22:19:25 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Sat, 8 Feb 2020 22:18:23 +0100 Message-Id: <20200208211823.31345-12-cus@passwd.hu> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200208211823.31345-1-cus@passwd.hu> References: <20200208211823.31345-1-cus@passwd.hu> Subject: [FFmpeg-devel] [PATCH 12/12] avformat/ftp: slightly rework file retrieval with seeking X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Marton Balint MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" - do not require a known file size for seek to work - read the files till the actual end, do not limit data at the queried file size - fix a bug which causes reading 0 byte files for non-existing files - properly check the return status of the FTP server at the end of the file retrieval Signed-off-by: Marton Balint --- libavformat/ftp.c | 54 +++++++++++++++++++++++++----------------------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/libavformat/ftp.c b/libavformat/ftp.c index ab7368256c..e3d194da58 100644 --- a/libavformat/ftp.c +++ b/libavformat/ftp.c @@ -39,7 +39,8 @@ typedef enum { DOWNLOADING, UPLOADING, LISTING_DIR, - DISCONNECTED + DISCONNECTED, + ENDOFFILE, } FTPState; typedef enum { @@ -231,7 +232,6 @@ static int ftp_send_command(FTPContext *s, const char *command, static void ftp_close_data_connection(FTPContext *s) { ffurl_closep(&s->conn_data); - s->position = 0; s->state = DISCONNECTED; } @@ -740,8 +740,7 @@ static int ftp_open(URLContext *h, const char *url, int flags) if (ftp_restart(s, 0) < 0) { h->is_streamed = 1; } else { - if (ftp_file_size(s) < 0 && flags & AVIO_FLAG_READ) - h->is_streamed = 1; + ftp_file_size(s); if (s->write_seekable != 1 && flags & AVIO_FLAG_WRITE) h->is_streamed = 1; } @@ -758,7 +757,7 @@ static int64_t ftp_seek(URLContext *h, int64_t pos, int whence) { FTPContext *s = h->priv_data; int err; - int64_t new_pos, fake_pos; + int64_t new_pos; ff_dlog(h, "ftp protocol seek %"PRId64" %d\n", pos, whence); @@ -788,11 +787,10 @@ static int64_t ftp_seek(URLContext *h, int64_t pos, int whence) return AVERROR(EINVAL); } - fake_pos = s->filesize != -1 ? FFMIN(new_pos, s->filesize) : new_pos; - if (fake_pos != s->position) { + if (new_pos != s->position) { if ((err = ftp_abort(h)) < 0) return err; - s->position = fake_pos; + s->position = new_pos; } return new_pos; } @@ -804,16 +802,13 @@ static int ftp_read(URLContext *h, unsigned char *buf, int size) ff_dlog(h, "ftp protocol read %d bytes\n", size); retry: + if (s->state == ENDOFFILE) + return AVERROR_EOF; if (s->state == DISCONNECTED) { - /* optimization */ - if (s->position >= s->filesize) - return AVERROR_EOF; if ((err = ftp_connect_data_connection(h)) < 0) return err; } if (s->state == READY) { - if (s->position >= s->filesize) - return AVERROR_EOF; if ((err = ftp_retrieve(s)) < 0) return err; } @@ -821,27 +816,28 @@ static int ftp_read(URLContext *h, unsigned char *buf, int size) read = ffurl_read(s->conn_data, buf, size); if (read >= 0) { s->position += read; - if (s->position >= s->filesize) { - /* server will terminate, but keep current position to avoid madness */ - /* save position to restart from it */ - int64_t pos = s->position; - if (ftp_abort(h) < 0) { - s->position = pos; - return AVERROR(EIO); - } - s->position = pos; - } + s->filesize = FFMAX(s->filesize, s->position); + } + if (read == AVERROR_EOF) { + static const int retr_codes[] = {226, 250, 425, 426, 451, 0}; + char *response = NULL; + err = ftp_status(s, &response, retr_codes); + if (err == 226) { + ftp_close_data_connection(s); + av_freep(&response); + s->state = ENDOFFILE; + return AVERROR_EOF; + } + /* 250 is not allowed, any other status means some kind of error */ + av_log(h, AV_LOG_ERROR, "FTP transfer failed: %s\n", response ? response : (err < 0 ? av_err2str(err) : "?")); + av_freep(&response); + read = AVERROR(EIO); } - if (read <= 0 && s->position < s->filesize && !h->is_streamed) { + if (read <= 0 && !h->is_streamed) { /* Server closed connection. Probably due to inactivity */ - int64_t pos = s->position; av_log(h, AV_LOG_INFO, "Reconnect to FTP server.\n"); if ((err = ftp_abort(h)) < 0) return err; - if ((err = ftp_seek(h, pos, SEEK_SET)) < 0) { - av_log(h, AV_LOG_ERROR, "Position cannot be restored.\n"); - return err; - } if (!retry_done) { retry_done = 1; goto retry;