FFmpeg
libssh.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Lukasz Marek <lukasz.m.luki@gmail.com>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <fcntl.h>
22 #define LIBSSH_STATIC
23 #include <libssh/sftp.h>
24 #include "libavutil/avstring.h"
25 #include "libavutil/mem.h"
26 #include "libavutil/opt.h"
27 #include "libavutil/attributes.h"
28 #include "libavformat/avio.h"
29 #include "avformat.h"
30 #include "internal.h"
31 #include "url.h"
32 
33 typedef struct {
34  const AVClass *class;
35  ssh_session session;
36  sftp_session sftp;
37  sftp_file file;
38  sftp_dir dir;
41  int trunc;
42  char *priv_key;
44 
45 static av_cold int libssh_create_ssh_session(LIBSSHContext *libssh, const char* hostname, unsigned int port)
46 {
47  static const int verbosity = SSH_LOG_NOLOG;
48 
49  if (!(libssh->session = ssh_new())) {
50  av_log(libssh, AV_LOG_ERROR, "SSH session creation failed: %s\n", ssh_get_error(libssh->session));
51  return AVERROR(ENOMEM);
52  }
53  ssh_options_set(libssh->session, SSH_OPTIONS_HOST, hostname);
54  ssh_options_set(libssh->session, SSH_OPTIONS_PORT, &port);
55  ssh_options_set(libssh->session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
56  if (libssh->rw_timeout > 0) {
57  long timeout = libssh->rw_timeout * 1000;
58  ssh_options_set(libssh->session, SSH_OPTIONS_TIMEOUT_USEC, &timeout);
59  }
60 
61  if (ssh_options_parse_config(libssh->session, NULL) < 0) {
62  av_log(libssh, AV_LOG_WARNING, "Could not parse the config file.\n");
63  }
64 
65  if (ssh_connect(libssh->session) != SSH_OK) {
66  av_log(libssh, AV_LOG_ERROR, "Connection failed: %s\n", ssh_get_error(libssh->session));
67  return AVERROR(EIO);
68  }
69 
70  return 0;
71 }
72 
73 static av_cold int libssh_authentication(LIBSSHContext *libssh, const char *user, const char *password)
74 {
75  int authorized = 0;
76  int auth_methods;
77 
78  if (user)
79  ssh_options_set(libssh->session, SSH_OPTIONS_USER, user);
80 
81  if (ssh_userauth_none(libssh->session, NULL) == SSH_AUTH_SUCCESS)
82  return 0;
83 
84  auth_methods = ssh_userauth_list(libssh->session, NULL);
85 
86  if (auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
87  if (libssh->priv_key) {
88  ssh_key priv_key;
89  if (ssh_pki_import_privkey_file(libssh->priv_key, password, NULL, NULL, &priv_key) == SSH_OK) {
90  if (ssh_userauth_publickey(libssh->session, NULL, priv_key) == SSH_AUTH_SUCCESS) {
91  av_log(libssh, AV_LOG_DEBUG, "Authentication successful with selected private key.\n");
92  authorized = 1;
93  }
94  } else {
95  av_log(libssh, AV_LOG_DEBUG, "Invalid key is provided.\n");
96  return AVERROR(EACCES);
97  }
98  } else if (ssh_userauth_publickey_auto(libssh->session, NULL, password) == SSH_AUTH_SUCCESS) {
99  av_log(libssh, AV_LOG_DEBUG, "Authentication successful with auto selected key.\n");
100  authorized = 1;
101  }
102  }
103 
104  if (!authorized && password && (auth_methods & SSH_AUTH_METHOD_PASSWORD)) {
105  if (ssh_userauth_password(libssh->session, NULL, password) == SSH_AUTH_SUCCESS) {
106  av_log(libssh, AV_LOG_DEBUG, "Authentication successful with password.\n");
107  authorized = 1;
108  }
109  }
110 
111  if (!authorized) {
112  av_log(libssh, AV_LOG_ERROR, "Authentication failed.\n");
113  return AVERROR(EACCES);
114  }
115 
116  return 0;
117 }
118 
120 {
121  if (!(libssh->sftp = sftp_new(libssh->session))) {
122  av_log(libssh, AV_LOG_ERROR, "SFTP session creation failed: %s\n", ssh_get_error(libssh->session));
123  return AVERROR(ENOMEM);
124  }
125 
126  if (sftp_init(libssh->sftp) != SSH_OK) {
127  av_log(libssh, AV_LOG_ERROR, "Error initializing sftp session: %s\n", ssh_get_error(libssh->session));
128  return AVERROR(EIO);
129  }
130 
131  return 0;
132 }
133 
134 static av_cold int libssh_open_file(LIBSSHContext *libssh, int flags, const char *file)
135 {
136  int access;
137 
138  if ((flags & AVIO_FLAG_WRITE) && (flags & AVIO_FLAG_READ)) {
139  access = O_CREAT | O_RDWR;
140  if (libssh->trunc)
141  access |= O_TRUNC;
142  } else if (flags & AVIO_FLAG_WRITE) {
143  access = O_CREAT | O_WRONLY;
144  if (libssh->trunc)
145  access |= O_TRUNC;
146  } else
147  access = O_RDONLY;
148 
149  /* 0666 = -rw-rw-rw- = read+write for everyone, minus umask */
150  if (!(libssh->file = sftp_open(libssh->sftp, file, access, 0666))) {
151  av_log(libssh, AV_LOG_ERROR, "Error opening sftp file: %s\n", ssh_get_error(libssh->session));
152  return AVERROR(EIO);
153  }
154 
155  return 0;
156 }
157 
159 {
160  sftp_attributes stat;
161 
162  if (!(stat = sftp_fstat(libssh->file))) {
163  av_log(libssh, AV_LOG_WARNING, "Cannot stat remote file.\n");
164  libssh->filesize = -1;
165  } else {
166  libssh->filesize = stat->size;
167  sftp_attributes_free(stat);
168  }
169 }
170 
172 {
173  LIBSSHContext *libssh = h->priv_data;
174  if (libssh->file) {
175  sftp_close(libssh->file);
176  libssh->file = NULL;
177  }
178  if (libssh->sftp) {
179  sftp_free(libssh->sftp);
180  libssh->sftp = NULL;
181  }
182  if (libssh->session) {
183  ssh_disconnect(libssh->session);
184  ssh_free(libssh->session);
185  libssh->session = NULL;
186  }
187  return 0;
188 }
189 
190 static av_cold int libssh_connect(URLContext *h, const char *url, char *path, size_t path_size)
191 {
192  LIBSSHContext *libssh = h->priv_data;
193  char proto[10], hostname[1024], credentials[1024];
194  int port = 22, ret;
195  const char *user = NULL, *pass = NULL;
196  char *end = NULL;
197 
198  av_url_split(proto, sizeof(proto),
199  credentials, sizeof(credentials),
200  hostname, sizeof(hostname),
201  &port,
202  path, path_size,
203  url);
204 
205  if (!(*path))
206  av_strlcpy(path, "/", path_size);
207 
208  // a port of 0 will use a port from ~/.ssh/config or the default value 22
209  if (port < 0 || port > 65535)
210  port = 0;
211 
212  if ((ret = libssh_create_ssh_session(libssh, hostname, port)) < 0)
213  return ret;
214 
215  user = av_strtok(credentials, ":", &end);
216  pass = av_strtok(end, ":", &end);
217 
218  if ((ret = libssh_authentication(libssh, user, pass)) < 0)
219  return ret;
220 
221  if ((ret = libssh_create_sftp_session(libssh)) < 0)
222  return ret;
223 
224  return 0;
225 }
226 
227 static av_cold int libssh_open(URLContext *h, const char *url, int flags)
228 {
229  int ret;
230  LIBSSHContext *libssh = h->priv_data;
231  char path[MAX_URL_SIZE];
232 
233  if ((ret = libssh_connect(h, url, path, sizeof(path))) < 0)
234  goto fail;
235 
236  if ((ret = libssh_open_file(libssh, flags, path)) < 0)
237  goto fail;
238 
239  libssh_stat_file(libssh);
240 
241  return 0;
242 
243  fail:
244  libssh_close(h);
245  return ret;
246 }
247 
248 static int64_t libssh_seek(URLContext *h, int64_t pos, int whence)
249 {
250  LIBSSHContext *libssh = h->priv_data;
251  int64_t newpos;
252 
253  if (libssh->filesize == -1 && (whence == AVSEEK_SIZE || whence == SEEK_END)) {
254  av_log(h, AV_LOG_ERROR, "Error during seeking.\n");
255  return AVERROR(EIO);
256  }
257 
258  switch(whence) {
259  case AVSEEK_SIZE:
260  return libssh->filesize;
261  case SEEK_SET:
262  newpos = pos;
263  break;
264  case SEEK_CUR:
265  newpos = sftp_tell64(libssh->file) + pos;
266  break;
267  case SEEK_END:
268  newpos = libssh->filesize + pos;
269  break;
270  default:
271  return AVERROR(EINVAL);
272  }
273 
274  if (newpos < 0) {
275  av_log(h, AV_LOG_ERROR, "Seeking to nagative position.\n");
276  return AVERROR(EINVAL);
277  }
278 
279  if (sftp_seek64(libssh->file, newpos)) {
280  av_log(h, AV_LOG_ERROR, "Error during seeking.\n");
281  return AVERROR(EIO);
282  }
283 
284  return newpos;
285 }
286 
287 static int libssh_read(URLContext *h, unsigned char *buf, int size)
288 {
289  LIBSSHContext *libssh = h->priv_data;
290  int bytes_read;
291 
292  if ((bytes_read = sftp_read(libssh->file, buf, size)) < 0) {
293  av_log(libssh, AV_LOG_ERROR, "Read error.\n");
294  return AVERROR(EIO);
295  }
296  return bytes_read ? bytes_read : AVERROR_EOF;
297 }
298 
299 static int libssh_write(URLContext *h, const unsigned char *buf, int size)
300 {
301  LIBSSHContext *libssh = h->priv_data;
302  int bytes_written;
303 
304  if ((bytes_written = sftp_write(libssh->file, buf, size)) < 0) {
305  av_log(libssh, AV_LOG_ERROR, "Write error.\n");
306  return AVERROR(EIO);
307  }
308  return bytes_written;
309 }
310 
312 {
313  LIBSSHContext *libssh = h->priv_data;
314  int ret;
315  char path[MAX_URL_SIZE];
316 
317  if ((ret = libssh_connect(h, h->filename, path, sizeof(path))) < 0)
318  goto fail;
319 
320  if (!(libssh->dir = sftp_opendir(libssh->sftp, path))) {
321  av_log(libssh, AV_LOG_ERROR, "Error opening sftp dir: %s\n", ssh_get_error(libssh->session));
322  ret = AVERROR(EIO);
323  goto fail;
324  }
325 
326  return 0;
327 
328  fail:
329  libssh_close(h);
330  return ret;
331 }
332 
334 {
335  LIBSSHContext *libssh = h->priv_data;
336  sftp_attributes attr = NULL;
338 
339  *next = entry = ff_alloc_dir_entry();
340  if (!entry)
341  return AVERROR(ENOMEM);
342 
343  do {
344  if (attr)
345  sftp_attributes_free(attr);
346  attr = sftp_readdir(libssh->sftp, libssh->dir);
347  if (!attr) {
348  av_freep(next);
349  if (sftp_dir_eof(libssh->dir))
350  return 0;
351  return AVERROR(EIO);
352  }
353  } while (!strcmp(attr->name, ".") || !strcmp(attr->name, ".."));
354 
355  entry->name = av_strdup(attr->name);
356  entry->group_id = attr->gid;
357  entry->user_id = attr->uid;
358  entry->size = attr->size;
359  entry->access_timestamp = INT64_C(1000000) * attr->atime;
360  entry->modification_timestamp = INT64_C(1000000) * attr->mtime;
361  entry->filemode = attr->permissions & 0777;
362  switch(attr->type) {
363  case SSH_FILEXFER_TYPE_REGULAR:
364  entry->type = AVIO_ENTRY_FILE;
365  break;
366  case SSH_FILEXFER_TYPE_DIRECTORY:
367  entry->type = AVIO_ENTRY_DIRECTORY;
368  break;
369  case SSH_FILEXFER_TYPE_SYMLINK:
371  break;
372  case SSH_FILEXFER_TYPE_SPECIAL:
373  /* Special type includes: sockets, char devices, block devices and pipes.
374  It is probably better to return unknown type, to not confuse anybody. */
375  case SSH_FILEXFER_TYPE_UNKNOWN:
376  default:
377  entry->type = AVIO_ENTRY_UNKNOWN;
378  }
379  sftp_attributes_free(attr);
380  return 0;
381 }
382 
384 {
385  LIBSSHContext *libssh = h->priv_data;
386  if (libssh->dir)
387  sftp_closedir(libssh->dir);
388  libssh->dir = NULL;
389  libssh_close(h);
390  return 0;
391 }
392 
394 {
395  int ret;
396  LIBSSHContext *libssh = h->priv_data;
397  sftp_attributes attr = NULL;
398  char path[MAX_URL_SIZE];
399 
400  if ((ret = libssh_connect(h, h->filename, path, sizeof(path))) < 0)
401  goto cleanup;
402 
403  if (!(attr = sftp_stat(libssh->sftp, path))) {
404  ret = AVERROR(sftp_get_error(libssh->sftp));
405  goto cleanup;
406  }
407 
408  if (attr->type == SSH_FILEXFER_TYPE_DIRECTORY) {
409  if (sftp_rmdir(libssh->sftp, path) < 0) {
410  ret = AVERROR(sftp_get_error(libssh->sftp));
411  goto cleanup;
412  }
413  } else {
414  if (sftp_unlink(libssh->sftp, path) < 0) {
415  ret = AVERROR(sftp_get_error(libssh->sftp));
416  goto cleanup;
417  }
418  }
419 
420  ret = 0;
421 
422 cleanup:
423  if (attr)
424  sftp_attributes_free(attr);
425  libssh_close(h);
426  return ret;
427 }
428 
429 static int libssh_move(URLContext *h_src, URLContext *h_dst)
430 {
431  int ret;
432  LIBSSHContext *libssh = h_src->priv_data;
433  char path_src[MAX_URL_SIZE], path_dst[MAX_URL_SIZE];
434  char hostname_src[1024], hostname_dst[1024];
435  char credentials_src[1024], credentials_dst[1024];
436  int port_src = 22, port_dst = 22;
437 
438  av_url_split(NULL, 0,
439  credentials_src, sizeof(credentials_src),
440  hostname_src, sizeof(hostname_src),
441  &port_src,
442  path_src, sizeof(path_src),
443  h_src->filename);
444 
445  av_url_split(NULL, 0,
446  credentials_dst, sizeof(credentials_dst),
447  hostname_dst, sizeof(hostname_dst),
448  &port_dst,
449  path_dst, sizeof(path_dst),
450  h_dst->filename);
451 
452  if (strcmp(credentials_src, credentials_dst) ||
453  strcmp(hostname_src, hostname_dst) ||
454  port_src != port_dst) {
455  return AVERROR(EINVAL);
456  }
457 
458  if ((ret = libssh_connect(h_src, h_src->filename, path_src, sizeof(path_src))) < 0)
459  goto cleanup;
460 
461  if (sftp_rename(libssh->sftp, path_src, path_dst) < 0) {
462  ret = AVERROR(sftp_get_error(libssh->sftp));
463  goto cleanup;
464  }
465 
466  ret = 0;
467 
468 cleanup:
469  libssh_close(h_src);
470  return ret;
471 }
472 
473 #define OFFSET(x) offsetof(LIBSSHContext, x)
474 #define D AV_OPT_FLAG_DECODING_PARAM
475 #define E AV_OPT_FLAG_ENCODING_PARAM
476 static const AVOption options[] = {
477  {"timeout", "set timeout of socket I/O operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D|E },
478  {"truncate", "Truncate existing files on write", OFFSET(trunc), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, E },
479  {"private_key", "set path to private key", OFFSET(priv_key), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D|E },
480  {NULL}
481 };
482 
484  .class_name = "libssh",
485  .item_name = av_default_item_name,
486  .option = options,
487  .version = LIBAVUTIL_VERSION_INT,
488 };
489 
491  .name = "sftp",
492  .url_open = libssh_open,
493  .url_read = libssh_read,
494  .url_write = libssh_write,
495  .url_seek = libssh_seek,
496  .url_close = libssh_close,
497  .url_delete = libssh_delete,
498  .url_move = libssh_move,
499  .url_open_dir = libssh_open_dir,
500  .url_read_dir = libssh_read_dir,
501  .url_close_dir = libssh_close_dir,
502  .priv_data_size = sizeof(LIBSSHContext),
503  .priv_data_class = &libssh_context_class,
505 };
OFFSET
#define OFFSET(x)
Definition: libssh.c:473
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:215
entry
#define entry
Definition: aom_film_grain_template.c:66
libssh_stat_file
static av_cold void libssh_stat_file(LIBSSHContext *libssh)
Definition: libssh.c:158
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
URLContext::filename
char * filename
specified URL
Definition: url.h:39
URL_PROTOCOL_FLAG_NETWORK
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:33
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
libssh_seek
static int64_t libssh_seek(URLContext *h, int64_t pos, int whence)
Definition: libssh.c:248
int64_t
long long int64_t
Definition: coverity.c:34
cleanup
static av_cold void cleanup(FlashSV2Context *s)
Definition: flashsv2enc.c:130
AVOption
AVOption.
Definition: opt.h:429
AVSEEK_SIZE
#define AVSEEK_SIZE
ORing this as the "whence" parameter to a seek function causes it to return the filesize without seek...
Definition: avio.h:468
libssh_open
static av_cold int libssh_open(URLContext *h, const char *url, int flags)
Definition: libssh.c:227
libssh_delete
static int libssh_delete(URLContext *h)
Definition: libssh.c:393
URLProtocol
Definition: url.h:51
LIBSSHContext::file
sftp_file file
Definition: libssh.c:37
libssh_move
static int libssh_move(URLContext *h_src, URLContext *h_dst)
Definition: libssh.c:429
AVIO_ENTRY_UNKNOWN
@ AVIO_ENTRY_UNKNOWN
Definition: avio.h:68
AVIO_ENTRY_DIRECTORY
@ AVIO_ENTRY_DIRECTORY
Definition: avio.h:71
LIBSSHContext::filesize
int64_t filesize
Definition: libssh.c:39
LIBSSHContext::priv_key
char * priv_key
Definition: libssh.c:42
fail
#define fail()
Definition: checkasm.h:193
trunc
static __device__ float trunc(float a)
Definition: cuda_runtime.h:179
LIBSSHContext::trunc
int trunc
Definition: libssh.c:41
URLContext::priv_data
void * priv_data
Definition: url.h:38
libssh_open_dir
static int libssh_open_dir(URLContext *h)
Definition: libssh.c:311
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
av_cold
#define av_cold
Definition: attributes.h:90
AVIO_ENTRY_SYMBOLIC_LINK
@ AVIO_ENTRY_SYMBOLIC_LINK
Definition: avio.h:73
libssh_open_file
static av_cold int libssh_open_file(LIBSSHContext *libssh, int flags, const char *file)
Definition: libssh.c:134
av_strtok
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
Definition: avstring.c:178
LIBSSHContext
Definition: libssh.c:33
AVIO_FLAG_WRITE
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:618
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:230
libssh_close_dir
static int libssh_close_dir(URLContext *h)
Definition: libssh.c:383
libssh_close
static av_cold int libssh_close(URLContext *h)
Definition: libssh.c:171
internal.h
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
NULL
#define NULL
Definition: coverity.c:32
libssh_read
static int libssh_read(URLContext *h, unsigned char *buf, int size)
Definition: libssh.c:287
libssh_connect
static av_cold int libssh_connect(URLContext *h, const char *url, char *path, size_t path_size)
Definition: libssh.c:190
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
options
Definition: swscale.c:42
AVIO_ENTRY_FILE
@ AVIO_ENTRY_FILE
Definition: avio.h:75
libssh_create_sftp_session
static av_cold int libssh_create_sftp_session(LIBSSHContext *libssh)
Definition: libssh.c:119
options
static const AVOption options[]
Definition: libssh.c:476
libssh_read_dir
static int libssh_read_dir(URLContext *h, AVIODirEntry **next)
Definition: libssh.c:333
libssh_create_ssh_session
static av_cold int libssh_create_ssh_session(LIBSSHContext *libssh, const char *hostname, unsigned int port)
Definition: libssh.c:45
size
int size
Definition: twinvq_data.h:10344
AVIODirEntry
Describes single entry of the directory.
Definition: avio.h:87
avio.h
LIBSSHContext::dir
sftp_dir dir
Definition: libssh.c:38
URLProtocol::name
const char * name
Definition: url.h:52
LIBSSHContext::session
ssh_session session
Definition: libssh.c:35
attributes.h
ff_alloc_dir_entry
AVIODirEntry * ff_alloc_dir_entry(void)
Allocate directory entry with default values.
Definition: url.c:327
URLContext
Definition: url.h:35
LIBSSHContext::rw_timeout
int rw_timeout
Definition: libssh.c:40
av_url_split
void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, const char *url)
Split a URL string into components.
Definition: utils.c:351
url.h
ff_libssh_protocol
const URLProtocol ff_libssh_protocol
Definition: libssh.c:490
libssh_context_class
static const AVClass libssh_context_class
Definition: libssh.c:483
ret
ret
Definition: filter_design.txt:187
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:80
pos
unsigned int pos
Definition: spdifenc.c:414
avformat.h
E
#define E
Definition: libssh.c:475
libssh_authentication
static av_cold int libssh_authentication(LIBSSHContext *libssh, const char *user, const char *password)
Definition: libssh.c:73
MAX_URL_SIZE
#define MAX_URL_SIZE
Definition: internal.h:30
libssh_write
static int libssh_write(URLContext *h, const unsigned char *buf, int size)
Definition: libssh.c:299
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:617
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:272
LIBSSHContext::sftp
sftp_session sftp
Definition: libssh.c:36
mem.h
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:482
av_strlcpy
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:85
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
h
h
Definition: vp9dsp_template.c:2070
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition: opt.h:276
D
#define D
Definition: libssh.c:474