lavf/libssh: fix seek with whence==SEEK_CUR
[ffmpeg.git] / libavformat / libssh.c
index 3bd581b..d513df2 100644 (file)
@@ -38,6 +38,30 @@ typedef struct {
     char *priv_key;
 } LIBSSHContext;
 
+static av_cold int libssh_create_ssh_session(LIBSSHContext *libssh, const char* hostname, unsigned int port)
+{
+    static const int verbosity = SSH_LOG_NOLOG;
+
+    if (!(libssh->session = ssh_new())) {
+        av_log(libssh, AV_LOG_ERROR, "SSH session creation failed: %s\n", ssh_get_error(libssh->session));
+        return AVERROR(ENOMEM);
+    }
+    ssh_options_set(libssh->session, SSH_OPTIONS_HOST, hostname);
+    ssh_options_set(libssh->session, SSH_OPTIONS_PORT, &port);
+    ssh_options_set(libssh->session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
+    if (libssh->rw_timeout > 0) {
+        long timeout = libssh->rw_timeout * 1000;
+        ssh_options_set(libssh->session, SSH_OPTIONS_TIMEOUT_USEC, &timeout);
+    }
+
+    if (ssh_connect(libssh->session) != SSH_OK) {
+        av_log(libssh, AV_LOG_ERROR, "Connection failed: %s\n", ssh_get_error(libssh->session));
+        return AVERROR(EIO);
+    }
+
+    return 0;
+}
+
 static av_cold int libssh_authentication(LIBSSHContext *libssh, const char *user, const char *password)
 {
     int authorized = 0;
@@ -84,6 +108,21 @@ static av_cold int libssh_authentication(LIBSSHContext *libssh, const char *user
     return 0;
 }
 
+static av_cold int libssh_create_sftp_session(LIBSSHContext *libssh)
+{
+    if (!(libssh->sftp = sftp_new(libssh->session))) {
+        av_log(libssh, AV_LOG_ERROR, "SFTP session creation failed: %s\n", ssh_get_error(libssh->session));
+        return AVERROR(ENOMEM);
+    }
+
+    if (sftp_init(libssh->sftp) != SSH_OK) {
+        av_log(libssh, AV_LOG_ERROR, "Error initializing sftp session: %s\n", ssh_get_error(libssh->session));
+        return AVERROR(EIO);
+    }
+
+    return 0;
+}
+
 static av_cold int libssh_open_file(LIBSSHContext *libssh, int flags, const char *file)
 {
     int access;
@@ -121,27 +160,25 @@ static av_cold void libssh_stat_file(LIBSSHContext *libssh)
     }
 }
 
-static int libssh_close(URLContext *h)
+static av_cold int libssh_close(URLContext *h)
 {
-    LIBSSHContext *s = h->priv_data;
-    if (s->file)
-        sftp_close(s->file);
-    if (s->sftp)
-        sftp_free(s->sftp);
-    if (s->session) {
-        ssh_disconnect(s->session);
-        ssh_free(s->session);
+    LIBSSHContext *libssh = h->priv_data;
+    if (libssh->file)
+        sftp_close(libssh->file);
+    if (libssh->sftp)
+        sftp_free(libssh->sftp);
+    if (libssh->session) {
+        ssh_disconnect(libssh->session);
+        ssh_free(libssh->session);
     }
     return 0;
 }
 
-static int libssh_open(URLContext *h, const char *url, int flags)
+static av_cold int libssh_open(URLContext *h, const char *url, int flags)
 {
-    static const int verbosity = SSH_LOG_NOLOG;
-    LIBSSHContext *s = h->priv_data;
+    LIBSSHContext *libssh = h->priv_data;
     char proto[10], path[MAX_URL_SIZE], hostname[1024], credencials[1024];
     int port = 22, ret;
-    long timeout = s->rw_timeout * 1000;
     const char *user = NULL, *pass = NULL;
     char *end = NULL;
 
@@ -155,43 +192,22 @@ static int libssh_open(URLContext *h, const char *url, int flags)
     if (port <= 0 || port > 65535)
         port = 22;
 
-    if (!(s->session = ssh_new())) {
-        ret = AVERROR(ENOMEM);
+    if ((ret = libssh_create_ssh_session(libssh, hostname, port)) < 0)
         goto fail;
-    }
+
     user = av_strtok(credencials, ":", &end);
     pass = av_strtok(end, ":", &end);
-    ssh_options_set(s->session, SSH_OPTIONS_HOST, hostname);
-    ssh_options_set(s->session, SSH_OPTIONS_PORT, &port);
-    ssh_options_set(s->session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
-    if (timeout > 0)
-        ssh_options_set(s->session, SSH_OPTIONS_TIMEOUT_USEC, &timeout);
-
-    if (ssh_connect(s->session) != SSH_OK) {
-        av_log(h, AV_LOG_ERROR, "Connection failed. %s\n", ssh_get_error(s->session));
-        ret = AVERROR(EIO);
-        goto fail;
-    }
 
-    if ((ret = libssh_authentication(s, user, pass)) < 0)
+    if ((ret = libssh_authentication(libssh, user, pass)) < 0)
         goto fail;
 
-    if (!(s->sftp = sftp_new(s->session))) {
-        av_log(h, AV_LOG_ERROR, "SFTP session creation failed: %s\n", ssh_get_error(s->session));
-        ret = AVERROR(ENOMEM);
+    if ((ret = libssh_create_sftp_session(libssh)) < 0)
         goto fail;
-    }
-
-    if (sftp_init(s->sftp) != SSH_OK) {
-        av_log(h, AV_LOG_ERROR, "Error initializing sftp session: %s\n", ssh_get_error(s->session));
-        ret = AVERROR(EIO);
-        goto fail;
-    }
 
-    if ((ret = libssh_open_file(s, flags, path)) < 0)
+    if ((ret = libssh_open_file(libssh, flags, path)) < 0)
         goto fail;
 
-    libssh_stat_file(s);
+    libssh_stat_file(libssh);
 
     return 0;
 
@@ -202,31 +218,31 @@ static int libssh_open(URLContext *h, const char *url, int flags)
 
 static int64_t libssh_seek(URLContext *h, int64_t pos, int whence)
 {
-    LIBSSHContext *s = h->priv_data;
+    LIBSSHContext *libssh = h->priv_data;
     int64_t newpos;
 
-    if (s->filesize == -1 && (whence == AVSEEK_SIZE || whence == SEEK_END)) {
+    if (libssh->filesize == -1 && (whence == AVSEEK_SIZE || whence == SEEK_END)) {
         av_log(h, AV_LOG_ERROR, "Error during seeking.\n");
         return AVERROR(EIO);
     }
 
     switch(whence) {
     case AVSEEK_SIZE:
-        return s->filesize;
+        return libssh->filesize;
     case SEEK_SET:
         newpos = pos;
         break;
     case SEEK_CUR:
-        newpos = sftp_tell64(s->file);
+        newpos = sftp_tell64(libssh->file) + pos;
         break;
     case SEEK_END:
-        newpos = s->filesize + pos;
+        newpos = libssh->filesize + pos;
         break;
     default:
         return AVERROR(EINVAL);
     }
 
-    if (sftp_seek64(s->file, newpos)) {
+    if (sftp_seek64(libssh->file, newpos)) {
         av_log(h, AV_LOG_ERROR, "Error during seeking.\n");
         return AVERROR(EIO);
     }
@@ -236,11 +252,11 @@ static int64_t libssh_seek(URLContext *h, int64_t pos, int whence)
 
 static int libssh_read(URLContext *h, unsigned char *buf, int size)
 {
-    LIBSSHContext *s = h->priv_data;
+    LIBSSHContext *libssh = h->priv_data;
     int bytes_read;
 
-    if ((bytes_read = sftp_read(s->file, buf, size)) < 0) {
-        av_log(h, AV_LOG_ERROR, "Read error.\n");
+    if ((bytes_read = sftp_read(libssh->file, buf, size)) < 0) {
+        av_log(libssh, AV_LOG_ERROR, "Read error.\n");
         return AVERROR(EIO);
     }
     return bytes_read;
@@ -248,11 +264,11 @@ static int libssh_read(URLContext *h, unsigned char *buf, int size)
 
 static int libssh_write(URLContext *h, const unsigned char *buf, int size)
 {
-    LIBSSHContext *s = h->priv_data;
+    LIBSSHContext *libssh = h->priv_data;
     int bytes_written;
 
-    if ((bytes_written = sftp_write(s->file, buf, size)) < 0) {
-        av_log(h, AV_LOG_ERROR, "Write error.\n");
+    if ((bytes_written = sftp_write(libssh->file, buf, size)) < 0) {
+        av_log(libssh, AV_LOG_ERROR, "Write error.\n");
         return AVERROR(EIO);
     }
     return bytes_written;