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>
23 #include <libssh/sftp.h>
31
43
45 {
46 static const int verbosity = SSH_LOG_NOLOG;
47
48 if (!(libssh->
session = ssh_new())) {
51 }
52 ssh_options_set(libssh->
session, SSH_OPTIONS_HOST, hostname);
53 ssh_options_set(libssh->
session, SSH_OPTIONS_PORT, &port);
54 ssh_options_set(libssh->
session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
57 ssh_options_set(libssh->
session, SSH_OPTIONS_TIMEOUT_USEC, &timeout);
58 }
59
60 if (ssh_options_parse_config(libssh->
session,
NULL) < 0) {
62 }
63
64 if (ssh_connect(libssh->
session) != SSH_OK) {
67 }
68
69 return 0;
70 }
71
73 {
74 int authorized = 0;
75 int auth_methods;
76
77 if (user)
78 ssh_options_set(libssh->
session, SSH_OPTIONS_USER, user);
79
80 if (ssh_userauth_none(libssh->
session,
NULL) == SSH_AUTH_SUCCESS)
81 return 0;
82
83 auth_methods = ssh_userauth_list(libssh->
session,
NULL);
84
85 if (auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
87 ssh_string pub_key;
88 ssh_private_key priv_key;
92 if (ssh_userauth_pubkey(libssh->
session,
NULL, pub_key, priv_key) == SSH_AUTH_SUCCESS) {
93 av_log(libssh,
AV_LOG_DEBUG,
"Authentication successful with selected private key.\n");
94 authorized = 1;
95 }
96 } else {
99 }
100 }
else if (ssh_userauth_autopubkey(libssh->
session, password) == SSH_AUTH_SUCCESS) {
102 authorized = 1;
103 }
104 }
105
106 if (!authorized && password && (auth_methods & SSH_AUTH_METHOD_PASSWORD)) {
107 if (ssh_userauth_password(libssh->
session,
NULL, password) == SSH_AUTH_SUCCESS) {
109 authorized = 1;
110 }
111 }
112
113 if (!authorized) {
116 }
117
118 return 0;
119 }
120
122 {
126 }
127
128 if (sftp_init(libssh->
sftp) != SSH_OK) {
131 }
132
133 return 0;
134 }
135
137 {
138 int access;
139
141 access = O_CREAT | O_RDWR;
143 access |= O_TRUNC;
145 access = O_CREAT | O_WRONLY;
147 access |= O_TRUNC;
148 } else
149 access = O_RDONLY;
150
151 /* 0666 = -rw-rw-rw- = read+write for everyone, minus umask */
152 if (!(libssh->
file = sftp_open(libssh->
sftp, file, access, 0666))) {
155 }
156
157 return 0;
158 }
159
161 {
162 sftp_attributes stat;
163
164 if (!(stat = sftp_fstat(libssh->
file))) {
167 } else {
169 sftp_attributes_free(stat);
170 }
171 }
172
174 {
177 sftp_close(libssh->
file);
179 }
181 sftp_free(libssh->
sftp);
183 }
185 ssh_disconnect(libssh->
session);
188 }
189 return 0;
190 }
191
193 {
195 char proto[10], hostname[1024], credencials[1024];
199
201 credencials, sizeof(credencials),
202 hostname, sizeof(hostname),
203 &port,
204 path, path_size,
205 url);
206
207 if (!(*path))
209
210 // a port of 0 will use a port from ~/.ssh/config or the default value 22
211 if (port < 0 || port > 65535)
212 port = 0;
213
216
217 user =
av_strtok(credencials,
":", &end);
219
222
225
226 return 0;
227 }
228
230 {
234
237
240
242
243 return 0;
244
248 }
249
251 {
253 int64_t newpos;
254
258 }
259
260 switch(whence) {
263 case SEEK_SET:
265 break;
266 case SEEK_CUR:
267 newpos = sftp_tell64(libssh->
file) +
pos;
268 break;
269 case SEEK_END:
271 break;
272 default:
274 }
275
276 if (newpos < 0) {
279 }
280
281 if (sftp_seek64(libssh->
file, newpos)) {
284 }
285
286 return newpos;
287 }
288
290 {
292 int bytes_read;
293
294 if ((bytes_read = sftp_read(libssh->
file, buf,
size)) < 0) {
297 }
299 }
300
302 {
304 int bytes_written;
305
306 if ((bytes_written = sftp_write(libssh->
file, buf,
size)) < 0) {
309 }
310 return bytes_written;
311 }
312
314 {
318
321
322 if (!(libssh->
dir = sftp_opendir(libssh->
sftp, path))) {
326 }
327
328 return 0;
329
333 }
334
336 {
338 sftp_attributes attr =
NULL;
340
342 if (!entry)
344
345 do {
346 if (attr)
347 sftp_attributes_free(attr);
348 attr = sftp_readdir(libssh->
sftp, libssh->
dir);
349 if (!attr) {
351 if (sftp_dir_eof(libssh->
dir))
352 return 0;
354 }
355 } while (!strcmp(attr->name, ".") || !strcmp(attr->name, ".."));
356
360 entry->
size = attr->size;
363 entry->
filemode = attr->permissions & 0777;
364 switch(attr->type) {
365 case SSH_FILEXFER_TYPE_REGULAR:
367 break;
368 case SSH_FILEXFER_TYPE_DIRECTORY:
370 break;
371 case SSH_FILEXFER_TYPE_SYMLINK:
373 break;
374 case SSH_FILEXFER_TYPE_SPECIAL:
375 /* Special type includes: sockets, char devices, block devices and pipes.
376 It is probably better to return unknown type, to not confuse anybody. */
377 case SSH_FILEXFER_TYPE_UNKNOWN:
378 default:
380 }
381 sftp_attributes_free(attr);
382 return 0;
383 }
384
386 {
389 sftp_closedir(libssh->
dir);
392 return 0;
393 }
394
396 {
399 sftp_attributes attr =
NULL;
401
404
405 if (!(attr = sftp_stat(libssh->
sftp, path))) {
408 }
409
410 if (attr->type == SSH_FILEXFER_TYPE_DIRECTORY) {
411 if (sftp_rmdir(libssh->
sftp, path) < 0) {
414 }
415 } else {
416 if (sftp_unlink(libssh->
sftp, path) < 0) {
419 }
420 }
421
423
425 if (attr)
426 sftp_attributes_free(attr);
429 }
430
432 {
436 char hostname_src[1024], hostname_dst[1024];
437 char credentials_src[1024], credentials_dst[1024];
438 int port_src = 22, port_dst = 22;
439
441 credentials_src, sizeof(credentials_src),
442 hostname_src, sizeof(hostname_src),
443 &port_src,
444 path_src, sizeof(path_src),
446
448 credentials_dst, sizeof(credentials_dst),
449 hostname_dst, sizeof(hostname_dst),
450 &port_dst,
451 path_dst, sizeof(path_dst),
453
454 if (strcmp(credentials_src, credentials_dst) ||
455 strcmp(hostname_src, hostname_dst) ||
456 port_src != port_dst) {
458 }
459
462
463 if (sftp_rename(libssh->
sftp, path_src, path_dst) < 0) {
466 }
467
469
473 }
474
475 #define OFFSET(x) offsetof(LIBSSHContext, x)
476 #define D AV_OPT_FLAG_DECODING_PARAM
477 #define E AV_OPT_FLAG_ENCODING_PARAM
479 {
"timeout",
"set timeout of socket I/O operations",
OFFSET(rw_timeout),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX,
D|
E },
483 };
484
490 };
491
507 };