1 | /* |
---|
2 | * ssh_api.h |
---|
3 | * |
---|
4 | * Created on: 2 juil. 2015 |
---|
5 | * Author: cresson |
---|
6 | */ |
---|
7 | |
---|
8 | #ifndef SSH_API_H_ |
---|
9 | #define SSH_API_H_ |
---|
10 | |
---|
11 | #include <libssh/libssh.h> |
---|
12 | #include <stdlib.h> |
---|
13 | #include <stdio.h> |
---|
14 | #include <errno.h> |
---|
15 | #include <string.h> |
---|
16 | #include <iostream> |
---|
17 | #include <sstream> |
---|
18 | |
---|
19 | // For remote files upload |
---|
20 | #include <fstream> // std::ifstream |
---|
21 | #include <libssh/sftp.h> |
---|
22 | #include <sys/stat.h> |
---|
23 | #include <fcntl.h> |
---|
24 | |
---|
25 | // Remote constants TODO: get them from cfg |
---|
26 | const std::string REMOTE_PROCESS_GET_STATUS = "/gpfs-dell/data/work/GEOSUD/drmaa/test/drmaa_operator/bin/get_status "; |
---|
27 | const std::string REMOTE_PROCESS_SUBMIT_COMMAND_ASYNC = "/gpfs-dell/data/work/GEOSUD/drmaa/test/drmaa_operator/bin/submit_command_async "; |
---|
28 | const std::string REMOTE_PROCESS_SUBMIT_COMMAND_SYNC = "/gpfs-dell/data/work/GEOSUD/drmaa/test/drmaa_operator/bin/submit_command_sync "; |
---|
29 | const std::string REMOTE_SCRATCH_DIRECTORY = "/gpfs-dell/scratch/cressonr/"; |
---|
30 | const std::string REMOTE_SERVER_NAME = "<your server name here (frontal)>"; |
---|
31 | const int REMOTE_SHELL_TIMEOUT_MS = 10000; // 10 sec |
---|
32 | |
---|
33 | // Good chunk size |
---|
34 | #define MAX_XFER_BUF_SIZE 16384 |
---|
35 | |
---|
36 | /* |
---|
37 | * Authenticating the server |
---|
38 | */ |
---|
39 | int verify_knownhost(ssh_session &session) |
---|
40 | { |
---|
41 | int state, hlen; |
---|
42 | unsigned char *hash = NULL; |
---|
43 | char *hexa; |
---|
44 | char buf[10]; |
---|
45 | state = ssh_is_server_known(session); |
---|
46 | ssh_key srv_pubkey; |
---|
47 | if (ssh_get_publickey(session, &srv_pubkey) < 0) |
---|
48 | { |
---|
49 | fprintf(stderr, "Public key not found:\n"); |
---|
50 | return SSH_ERROR; |
---|
51 | } |
---|
52 | switch (state) |
---|
53 | { |
---|
54 | case SSH_SERVER_KNOWN_OK: |
---|
55 | break; /* ok */ |
---|
56 | case SSH_SERVER_KNOWN_CHANGED: |
---|
57 | fprintf(stderr, "Host key for server changed: it is now:\n"); |
---|
58 | ssh_print_hexa("Public key hash", hash, hlen); |
---|
59 | fprintf(stderr, "For security reasons, connection will be stopped\n"); |
---|
60 | free(hash); |
---|
61 | return SSH_ERROR; |
---|
62 | case SSH_SERVER_FOUND_OTHER: |
---|
63 | fprintf(stderr, "The host key for this server was not found but an other" |
---|
64 | "type of key exists.\n"); |
---|
65 | fprintf(stderr, "An attacker might change the default server key to" |
---|
66 | "confuse your client into thinking the key does not exist\n"); |
---|
67 | free(hash); |
---|
68 | return SSH_ERROR; |
---|
69 | case SSH_SERVER_FILE_NOT_FOUND: |
---|
70 | fprintf(stderr, "Could not find known host file.\n"); |
---|
71 | fprintf(stderr, "If you accept the host key here, the file will be" |
---|
72 | "automatically created.\n"); |
---|
73 | return SSH_ERROR; |
---|
74 | case SSH_SERVER_NOT_KNOWN: |
---|
75 | hexa = ssh_get_hexa(hash, hlen); |
---|
76 | fprintf(stderr,"The server is unknown. Do you trust the host key?\n"); |
---|
77 | fprintf(stderr, "Public key hash: %s\n", hexa); |
---|
78 | free(hexa); |
---|
79 | if (fgets(buf, sizeof(buf), stdin) == NULL) |
---|
80 | { |
---|
81 | free(hash); |
---|
82 | return SSH_ERROR; |
---|
83 | } |
---|
84 | if (strncasecmp(buf, "yes", 3) != 0) |
---|
85 | { |
---|
86 | free(hash); |
---|
87 | return SSH_ERROR; |
---|
88 | } |
---|
89 | if (ssh_write_knownhost(session) < 0) |
---|
90 | { |
---|
91 | fprintf(stderr, "Error %s\n", strerror(errno)); |
---|
92 | free(hash); |
---|
93 | return SSH_ERROR; |
---|
94 | } |
---|
95 | break; |
---|
96 | case SSH_SERVER_ERROR: |
---|
97 | fprintf(stderr, "Error %s\n", ssh_get_error(session)); |
---|
98 | free(hash); |
---|
99 | return SSH_ERROR; |
---|
100 | } |
---|
101 | free(hash); |
---|
102 | return SSH_OK; |
---|
103 | } |
---|
104 | |
---|
105 | /* |
---|
106 | * Authenticate ourselves |
---|
107 | */ |
---|
108 | int authenticate_pubkey(ssh_session &session) |
---|
109 | { |
---|
110 | int rc; |
---|
111 | rc = ssh_userauth_publickey_auto(session, "cressonr", NULL); |
---|
112 | if (rc == SSH_AUTH_ERROR) |
---|
113 | { |
---|
114 | fprintf(stderr, "Authentication failed: %s\n", |
---|
115 | ssh_get_error(session)); |
---|
116 | return SSH_ERROR; |
---|
117 | } |
---|
118 | return SSH_OK; |
---|
119 | } |
---|
120 | |
---|
121 | /* |
---|
122 | * Show remote process output |
---|
123 | */ |
---|
124 | int show_remote_processes(ssh_session &session, const std::string &command, std::string &output) |
---|
125 | { |
---|
126 | output.clear(); |
---|
127 | ssh_channel channel; |
---|
128 | int rc; |
---|
129 | char buffer[256]; |
---|
130 | unsigned int nbytes; |
---|
131 | channel = ssh_channel_new(session); |
---|
132 | fprintf(stderr, "Opening ssh session\n" ); |
---|
133 | if (channel == NULL) |
---|
134 | { |
---|
135 | fprintf(stderr, "ssh_channel_new(session) failed %s\n", ssh_get_error(session)); |
---|
136 | output = "ssh_channel_new(session) failed"; |
---|
137 | return SSH_ERROR; |
---|
138 | } |
---|
139 | |
---|
140 | rc = ssh_channel_open_session(channel); |
---|
141 | if (rc != SSH_OK) |
---|
142 | { |
---|
143 | fprintf(stderr, "Error opening session\n"); |
---|
144 | output = "Error opening session"; |
---|
145 | ssh_channel_free(channel); |
---|
146 | return SSH_ERROR; |
---|
147 | } |
---|
148 | |
---|
149 | rc = ssh_channel_request_pty(channel); |
---|
150 | if (rc != SSH_OK) |
---|
151 | { |
---|
152 | fprintf(stderr, "Error requesting pty\n"); |
---|
153 | output = "Error requesting pty\n"; |
---|
154 | ssh_channel_close(channel); |
---|
155 | ssh_channel_free(channel); |
---|
156 | |
---|
157 | return rc; |
---|
158 | } |
---|
159 | rc = ssh_channel_change_pty_size(channel, 80, 24); |
---|
160 | if (rc != SSH_OK) |
---|
161 | { |
---|
162 | fprintf(stderr, "Error changing pty size\n"); |
---|
163 | output = "Error changing pty size\n"; |
---|
164 | ssh_channel_close(channel); |
---|
165 | ssh_channel_free(channel); |
---|
166 | |
---|
167 | return rc; |
---|
168 | } |
---|
169 | rc = ssh_channel_request_shell(channel); |
---|
170 | if (rc != SSH_OK) |
---|
171 | { |
---|
172 | fprintf(stderr, "Error requesting shell\n"); |
---|
173 | output = "Error requesting shell\n"; |
---|
174 | ssh_channel_close(channel); |
---|
175 | ssh_channel_free(channel); |
---|
176 | |
---|
177 | return rc; |
---|
178 | } |
---|
179 | |
---|
180 | // Send the command to shell |
---|
181 | std::string tosend = command + " ; RETVAL=$? ; [ $RETVAL -eq 0 ] && echo Success ; [ $RETVAL -ne 0 ] && echo Failure ; exit\n"; |
---|
182 | char * tosendBuffer = (char*)tosend.c_str(); |
---|
183 | nbytes = tosend.size(); //read(0, tosendBuffer, sizeof(tosendBuffer)); |
---|
184 | fprintf(stderr, "Sending number of bytes:%d\n", nbytes); |
---|
185 | int nwritten; |
---|
186 | if (nbytes < 0) return SSH_ERROR; |
---|
187 | if (nbytes > 0) |
---|
188 | { |
---|
189 | nwritten = ssh_channel_write(channel, tosendBuffer, nbytes); |
---|
190 | if (nwritten != nbytes) return SSH_ERROR; |
---|
191 | } |
---|
192 | |
---|
193 | // Receive the shell output |
---|
194 | while (ssh_channel_is_open(channel) && |
---|
195 | !ssh_channel_is_eof(channel)) |
---|
196 | { |
---|
197 | nbytes = ssh_channel_read_timeout(channel, buffer, sizeof(buffer), 0, REMOTE_SHELL_TIMEOUT_MS); |
---|
198 | if (nbytes < 0) |
---|
199 | { |
---|
200 | if (nbytes==SSH_AGAIN) |
---|
201 | { |
---|
202 | fprintf(stderr, "SSH Channel read error: Timeout"); |
---|
203 | output += "SSH Channel read error: Timeout"; |
---|
204 | } |
---|
205 | return SSH_ERROR; |
---|
206 | } |
---|
207 | else if (nbytes>0) |
---|
208 | { |
---|
209 | write(2, buffer, nbytes); |
---|
210 | |
---|
211 | char subbuff[nbytes+1]; |
---|
212 | memcpy( subbuff, &buffer[0], nbytes); |
---|
213 | subbuff[nbytes] = '\0'; |
---|
214 | std::string tmpStr(subbuff); |
---|
215 | output += tmpStr; |
---|
216 | |
---|
217 | } |
---|
218 | } |
---|
219 | |
---|
220 | if (nbytes < 0) |
---|
221 | { |
---|
222 | fprintf(stderr, "Error receiving command result\n"); |
---|
223 | output = "Error receiving command result"; |
---|
224 | ssh_channel_close(channel); |
---|
225 | ssh_channel_free(channel); |
---|
226 | return SSH_ERROR; |
---|
227 | } |
---|
228 | ssh_channel_send_eof(channel); |
---|
229 | ssh_channel_close(channel); |
---|
230 | ssh_channel_free(channel); |
---|
231 | return SSH_OK; |
---|
232 | } |
---|
233 | |
---|
234 | /* |
---|
235 | * Open an SSH session |
---|
236 | */ |
---|
237 | int open_ssh_session(const std::string &hostname, ssh_session &my_ssh_session) |
---|
238 | { |
---|
239 | int rc; |
---|
240 | char *password; |
---|
241 | |
---|
242 | // Open session and set options |
---|
243 | my_ssh_session = ssh_new(); |
---|
244 | if (my_ssh_session == NULL) |
---|
245 | { |
---|
246 | fprintf(stderr, "ssh_new() failed: %s\n", |
---|
247 | ssh_get_error(my_ssh_session)); |
---|
248 | return SSH_ERROR; |
---|
249 | } |
---|
250 | ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, hostname.c_str()); |
---|
251 | |
---|
252 | // Connect to server |
---|
253 | rc = ssh_connect(my_ssh_session); |
---|
254 | if (rc != SSH_OK) |
---|
255 | { |
---|
256 | fprintf(stderr, "Error connecting to host: %s\n", |
---|
257 | ssh_get_error(my_ssh_session)); |
---|
258 | ssh_free(my_ssh_session); |
---|
259 | return rc; |
---|
260 | } |
---|
261 | |
---|
262 | // Verify the server's identity |
---|
263 | // For the source code of verify_knowhost(), check previous example |
---|
264 | if (verify_knownhost(my_ssh_session) < 0) |
---|
265 | { |
---|
266 | fprintf(stderr, "Error verifying the server's identity: %s\n", |
---|
267 | ssh_get_error(my_ssh_session)); |
---|
268 | ssh_disconnect(my_ssh_session); |
---|
269 | ssh_free(my_ssh_session); |
---|
270 | return SSH_ERROR; |
---|
271 | } |
---|
272 | |
---|
273 | // Authenticate ourselves |
---|
274 | rc = authenticate_pubkey(my_ssh_session); |
---|
275 | if (rc != SSH_OK) |
---|
276 | { |
---|
277 | fprintf(stderr, "Error authenticating ourselves: %s\n", |
---|
278 | ssh_get_error(my_ssh_session)); |
---|
279 | ssh_free(my_ssh_session); |
---|
280 | } |
---|
281 | return rc; |
---|
282 | } |
---|
283 | |
---|
284 | |
---|
285 | /* |
---|
286 | * Output the result of the given input command |
---|
287 | */ |
---|
288 | int get_command_output(const std::string &command, std::string &output) |
---|
289 | { |
---|
290 | // Create a ssh session |
---|
291 | ssh_session my_ssh_session; |
---|
292 | fprintf(stderr,"Creating ssh session\n"); |
---|
293 | int rc = open_ssh_session(REMOTE_SERVER_NAME, my_ssh_session); |
---|
294 | if (rc != SSH_OK) |
---|
295 | { |
---|
296 | fprintf(stderr, "Error creating ssh session %s \n", |
---|
297 | ssh_get_error(my_ssh_session)); |
---|
298 | output = "Error opening ssh session"; |
---|
299 | return SSH_ERROR; |
---|
300 | } |
---|
301 | |
---|
302 | // Execute remote process |
---|
303 | fprintf(stderr,"Executing remote process\n"); |
---|
304 | rc = show_remote_processes(my_ssh_session, command, output); |
---|
305 | if (rc != SSH_OK) |
---|
306 | { |
---|
307 | fprintf(stderr, "Error showing remote process %s : %s\n", |
---|
308 | command.c_str(), |
---|
309 | ssh_get_error(my_ssh_session)); |
---|
310 | output = "Error showing remote process"; |
---|
311 | } |
---|
312 | |
---|
313 | // Disconnect session |
---|
314 | ssh_disconnect(my_ssh_session); |
---|
315 | ssh_free(my_ssh_session); |
---|
316 | |
---|
317 | return rc; |
---|
318 | } |
---|
319 | |
---|
320 | /* |
---|
321 | * Get the status of a job |
---|
322 | */ |
---|
323 | int get_status(int job_id, std::string &output) |
---|
324 | { |
---|
325 | std::string command (REMOTE_PROCESS_GET_STATUS); |
---|
326 | command += static_cast<std::ostringstream*>( &(std::ostringstream() << job_id) )->str(); |
---|
327 | |
---|
328 | return get_command_output(command, output); |
---|
329 | } |
---|
330 | |
---|
331 | /* |
---|
332 | * Submit a command, asynchronous way (and returns its ID) |
---|
333 | */ |
---|
334 | int submit_command_async(const std::string &input_command, std::string &output) |
---|
335 | { |
---|
336 | std::string command(REMOTE_PROCESS_SUBMIT_COMMAND_ASYNC); |
---|
337 | command += input_command; |
---|
338 | |
---|
339 | return get_command_output(command, output); |
---|
340 | } |
---|
341 | |
---|
342 | /* |
---|
343 | * Submit a job, synchronous way (and returns its status) |
---|
344 | */ |
---|
345 | int submit_command_sync(const std::string &input_command, std::string &output) |
---|
346 | { |
---|
347 | |
---|
348 | std::string command(REMOTE_PROCESS_SUBMIT_COMMAND_SYNC); |
---|
349 | command += input_command; |
---|
350 | |
---|
351 | return get_command_output(command, output); |
---|
352 | } |
---|
353 | |
---|
354 | /* |
---|
355 | * sftp: upload a file |
---|
356 | */ |
---|
357 | int sftp_uploadfile(ssh_session &session, sftp_session &sftp) |
---|
358 | { |
---|
359 | int access_type = O_WRONLY | O_CREAT | O_TRUNC; |
---|
360 | sftp_file file; |
---|
361 | const char *helloworld = "Hello, World!\n"; |
---|
362 | int length = strlen(helloworld); |
---|
363 | int rc, nwritten; |
---|
364 | //... |
---|
365 | file = sftp_open(sftp, "helloworld.txt", |
---|
366 | access_type, S_IRWXU); |
---|
367 | if (file == NULL) |
---|
368 | { |
---|
369 | fprintf(stderr, "Can't open file for writing: %s\n", |
---|
370 | ssh_get_error(session)); |
---|
371 | return SSH_ERROR; |
---|
372 | } |
---|
373 | nwritten = sftp_write(file, helloworld, length); |
---|
374 | if (nwritten != length) |
---|
375 | { |
---|
376 | fprintf(stderr, "Can't write data to file: %s\n", |
---|
377 | ssh_get_error(session)); |
---|
378 | sftp_close(file); |
---|
379 | return SSH_ERROR; |
---|
380 | } |
---|
381 | rc = sftp_close(file); |
---|
382 | if (rc != SSH_OK) |
---|
383 | { |
---|
384 | fprintf(stderr, "Can't close the written file: %s\n", |
---|
385 | ssh_get_error(session)); |
---|
386 | return rc; |
---|
387 | } |
---|
388 | return SSH_OK; |
---|
389 | } |
---|
390 | |
---|
391 | void display_sftp_error_message(sftp_session &sftp) |
---|
392 | { |
---|
393 | int error = sftp_get_error(sftp); |
---|
394 | |
---|
395 | switch (error) { |
---|
396 | case SSH_FX_NO_SUCH_FILE: |
---|
397 | fprintf(stderr, "No such file\n"); |
---|
398 | break; |
---|
399 | case SSH_FX_PERMISSION_DENIED: |
---|
400 | fprintf(stderr, "Permission denied\n"); |
---|
401 | break; |
---|
402 | case SSH_FX_EOF: |
---|
403 | fprintf(stderr, "EOF encountered\n"); |
---|
404 | break; |
---|
405 | case SSH_FX_FAILURE: |
---|
406 | fprintf(stderr, "Failure\n"); |
---|
407 | break; |
---|
408 | case SSH_FX_BAD_MESSAGE: |
---|
409 | fprintf(stderr, "Strange error message received\n"); |
---|
410 | break; |
---|
411 | case SSH_FX_NO_CONNECTION: |
---|
412 | fprintf(stderr, "No connection\n"); |
---|
413 | break; |
---|
414 | case SSH_FX_CONNECTION_LOST: |
---|
415 | fprintf(stderr, "Conection lost\n"); |
---|
416 | break; |
---|
417 | case SSH_FX_OP_UNSUPPORTED: |
---|
418 | fprintf(stderr, "Operation not supported\n"); |
---|
419 | break; |
---|
420 | case SSH_FX_INVALID_HANDLE: |
---|
421 | fprintf(stderr, "Invalid handle\n"); |
---|
422 | break; |
---|
423 | case SSH_FX_NO_SUCH_PATH: |
---|
424 | fprintf(stderr, "No such path\n"); |
---|
425 | break; |
---|
426 | case SSH_FX_FILE_ALREADY_EXISTS: |
---|
427 | fprintf(stderr, "Already exists\n"); |
---|
428 | break; |
---|
429 | case SSH_FX_WRITE_PROTECT: |
---|
430 | fprintf(stderr, "Write protected\n"); |
---|
431 | break; |
---|
432 | case SSH_FX_NO_MEDIA: |
---|
433 | fprintf(stderr, "No media\n"); |
---|
434 | break; |
---|
435 | } |
---|
436 | } |
---|
437 | |
---|
438 | /* |
---|
439 | * sftp: mkdir |
---|
440 | */ |
---|
441 | int sftp_mkdir(ssh_session &session, sftp_session &sftp, |
---|
442 | const std::string &directory) |
---|
443 | { |
---|
444 | int rc; |
---|
445 | rc = sftp_mkdir(sftp, directory.c_str(), S_IRWXU); |
---|
446 | if (rc != SSH_OK) |
---|
447 | { |
---|
448 | display_sftp_error_message(sftp); |
---|
449 | } |
---|
450 | return rc; |
---|
451 | } |
---|
452 | |
---|
453 | /* |
---|
454 | * init. a sftp session |
---|
455 | */ |
---|
456 | int initialize_sftp_session(ssh_session &session, sftp_session &sftp) |
---|
457 | { |
---|
458 | // Connect to server |
---|
459 | fprintf(stderr,"Open ssh session\n"); |
---|
460 | int rc = open_ssh_session(REMOTE_SERVER_NAME, session); |
---|
461 | if (rc != SSH_OK) |
---|
462 | { |
---|
463 | fprintf(stderr, "open_ssh_session failed: %s\n", |
---|
464 | ssh_get_error(session)); |
---|
465 | return SSH_ERROR; |
---|
466 | } |
---|
467 | |
---|
468 | // init. sftp session |
---|
469 | fprintf(stderr,"Init. sftp session\n"); |
---|
470 | sftp = sftp_new(session); |
---|
471 | if (sftp == NULL) |
---|
472 | { |
---|
473 | fprintf(stderr, "sftp_new(session) failed: %s\n", |
---|
474 | ssh_get_error(session)); |
---|
475 | return SSH_ERROR; |
---|
476 | } |
---|
477 | rc = sftp_init(sftp); |
---|
478 | if (rc != SSH_OK) |
---|
479 | { |
---|
480 | fprintf(stderr, "Error initializing SFTP session: %s\n", |
---|
481 | sftp_get_error(sftp)); |
---|
482 | } |
---|
483 | return rc; |
---|
484 | } |
---|
485 | |
---|
486 | /* |
---|
487 | * create a directory on the host |
---|
488 | */ |
---|
489 | int create_remote_dir(const std::string &directory_name) |
---|
490 | { |
---|
491 | std::string dir = directory_name; |
---|
492 | fprintf(stderr,"Creating directory: %s\n", dir.c_str() ); |
---|
493 | |
---|
494 | int rc; |
---|
495 | |
---|
496 | // init. session |
---|
497 | ssh_session session; |
---|
498 | sftp_session sftp; |
---|
499 | rc = initialize_sftp_session(session, sftp); |
---|
500 | if (rc != SSH_OK) |
---|
501 | { |
---|
502 | return rc; |
---|
503 | } |
---|
504 | |
---|
505 | // create a directory |
---|
506 | rc = sftp_mkdir(session, sftp, dir.c_str()); |
---|
507 | if (rc == SSH_OK) |
---|
508 | { |
---|
509 | fprintf(stderr,"Directory successfuly created\n"); |
---|
510 | } |
---|
511 | |
---|
512 | // close sftp connection |
---|
513 | sftp_free(sftp); |
---|
514 | |
---|
515 | // Disconnect session |
---|
516 | ssh_disconnect(session); |
---|
517 | ssh_free(session); |
---|
518 | |
---|
519 | return SSH_OK; |
---|
520 | } |
---|
521 | |
---|
522 | /* |
---|
523 | * download a file |
---|
524 | */ |
---|
525 | int sftp_download_file(ssh_session &session, sftp_session &sftp, |
---|
526 | const std::string &local_filename, const std::string &remote_filename) |
---|
527 | { |
---|
528 | std::string true_remote_filename = remote_filename; |
---|
529 | fprintf(stderr,"Creating local file: %s\n", local_filename.c_str() ); |
---|
530 | |
---|
531 | int access_type; |
---|
532 | sftp_file file; |
---|
533 | char buffer[MAX_XFER_BUF_SIZE]; |
---|
534 | int nbytes, nwritten, rc; |
---|
535 | int fd; |
---|
536 | access_type = O_RDONLY; |
---|
537 | file = sftp_open(sftp, true_remote_filename.c_str(), |
---|
538 | access_type, 0); |
---|
539 | if (file == NULL) { |
---|
540 | fprintf(stderr, "Can't open file for reading: %s\n", |
---|
541 | ssh_get_error(session)); |
---|
542 | return SSH_ERROR; |
---|
543 | } |
---|
544 | mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; |
---|
545 | // fd = open(local_filename.c_str(), O_RDWR|O_CREAT); |
---|
546 | fd = open(local_filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, mode); |
---|
547 | if (fd < 0) { |
---|
548 | fprintf(stderr, "Can't open file for writing: %s\n", |
---|
549 | strerror(errno)); |
---|
550 | return SSH_ERROR; |
---|
551 | } |
---|
552 | for (;;) { |
---|
553 | nbytes = sftp_read(file, buffer, sizeof(buffer)); |
---|
554 | if (nbytes == 0) { |
---|
555 | break; // EOF |
---|
556 | } else if (nbytes < 0) { |
---|
557 | fprintf(stderr, "Error while reading file: %s\n", |
---|
558 | ssh_get_error(session)); |
---|
559 | sftp_close(file); |
---|
560 | close(fd); |
---|
561 | return SSH_ERROR; |
---|
562 | } |
---|
563 | nwritten = write(fd, buffer, nbytes); |
---|
564 | if (nwritten != nbytes) { |
---|
565 | fprintf(stderr, "Error writing: %s\n", |
---|
566 | strerror(errno)); |
---|
567 | sftp_close(file); |
---|
568 | close(fd); |
---|
569 | return SSH_ERROR; |
---|
570 | } |
---|
571 | } |
---|
572 | rc = sftp_close(file); |
---|
573 | if (rc != SSH_OK) { |
---|
574 | fprintf(stderr, "Can't close the read file: %s\n", |
---|
575 | ssh_get_error(session)); |
---|
576 | } |
---|
577 | close(fd); |
---|
578 | return rc; |
---|
579 | } |
---|
580 | |
---|
581 | /* |
---|
582 | * upload a file |
---|
583 | */ |
---|
584 | int sftp_upload_file(ssh_session &session, sftp_session &sftp, |
---|
585 | const std::string &local_filename, const std::string &remote_filename) |
---|
586 | { |
---|
587 | std::string true_remote_filename = remote_filename; |
---|
588 | fprintf(stderr, "Creating remote file: %s\n", true_remote_filename.c_str() ); |
---|
589 | |
---|
590 | int access_type; |
---|
591 | sftp_file file; |
---|
592 | char buffer[MAX_XFER_BUF_SIZE]; |
---|
593 | int nbytes, nwritten, rc; |
---|
594 | int fd; |
---|
595 | // access_type = O_WRONLY; |
---|
596 | access_type = O_WRONLY | O_CREAT | O_TRUNC; |
---|
597 | file = sftp_open(sftp, true_remote_filename.c_str(), |
---|
598 | access_type, S_IRWXU /* 0 */); |
---|
599 | if (file == NULL) { |
---|
600 | fprintf(stderr, "Can't open file for writing: %s\n", |
---|
601 | ssh_get_error(session)); |
---|
602 | return SSH_ERROR; |
---|
603 | } |
---|
604 | |
---|
605 | fd = open(local_filename.c_str(), O_RDONLY); |
---|
606 | if (fd < 0) { |
---|
607 | fprintf(stderr, "Can't open file for reading: %s\n", |
---|
608 | strerror(errno)); |
---|
609 | return SSH_ERROR; |
---|
610 | } |
---|
611 | |
---|
612 | for (;;) { |
---|
613 | nbytes = read(fd, buffer, sizeof(buffer)); |
---|
614 | if (nbytes == 0) { |
---|
615 | break; // EOF |
---|
616 | } else if (nbytes < 0) { |
---|
617 | fprintf(stderr, "Error while reading file: %s\n", |
---|
618 | ssh_get_error(session)); |
---|
619 | sftp_close(file); |
---|
620 | return SSH_ERROR; |
---|
621 | } |
---|
622 | nwritten = sftp_write(file, buffer, nbytes); |
---|
623 | if (nwritten != nbytes) { |
---|
624 | fprintf(stderr, "Error writing: %s\n", |
---|
625 | strerror(errno)); |
---|
626 | sftp_close(file); |
---|
627 | return SSH_ERROR; |
---|
628 | } |
---|
629 | } |
---|
630 | rc = sftp_close(file); |
---|
631 | if (rc != SSH_OK) { |
---|
632 | fprintf(stderr, "Can't close the write file: %s\n", |
---|
633 | ssh_get_error(session)); |
---|
634 | rc = SSH_ERROR; |
---|
635 | } |
---|
636 | return rc; |
---|
637 | } |
---|
638 | |
---|
639 | /* |
---|
640 | * Upload a file to the remote host |
---|
641 | */ |
---|
642 | int upload_file(const std::string &local_filename, const std::string &remote_filename) |
---|
643 | { |
---|
644 | |
---|
645 | fprintf(stderr, "Upload file %s (local) to %s (remote)\n", local_filename.c_str(), remote_filename.c_str() ); |
---|
646 | |
---|
647 | int rc; |
---|
648 | |
---|
649 | // init. session |
---|
650 | ssh_session session; |
---|
651 | sftp_session sftp; |
---|
652 | rc = initialize_sftp_session(session, sftp); |
---|
653 | if (rc != SSH_OK) |
---|
654 | { |
---|
655 | return rc; |
---|
656 | } |
---|
657 | |
---|
658 | // transfert file |
---|
659 | rc = sftp_upload_file(session, sftp, local_filename, remote_filename); |
---|
660 | if (rc == SSH_OK) |
---|
661 | { |
---|
662 | fprintf(stderr,"Remote file successfuly uploaded\n"); |
---|
663 | } |
---|
664 | |
---|
665 | // close sftp connection |
---|
666 | sftp_free(sftp); |
---|
667 | |
---|
668 | // Disconnect session |
---|
669 | ssh_disconnect(session); |
---|
670 | ssh_free(session); |
---|
671 | |
---|
672 | return rc; |
---|
673 | } |
---|
674 | |
---|
675 | /* |
---|
676 | * Download a file to the remote host |
---|
677 | */ |
---|
678 | int download_file(const std::string &local_filename, const std::string &remote_filename) |
---|
679 | { |
---|
680 | |
---|
681 | fprintf(stderr,"Download file %s (remote) to %s (local)\n", remote_filename.c_str(), local_filename.c_str() ); |
---|
682 | |
---|
683 | int rc; |
---|
684 | |
---|
685 | // init. session |
---|
686 | ssh_session session; |
---|
687 | sftp_session sftp; |
---|
688 | rc = initialize_sftp_session(session, sftp); |
---|
689 | if (rc != SSH_OK) |
---|
690 | { |
---|
691 | return rc; |
---|
692 | } |
---|
693 | |
---|
694 | // transfert file |
---|
695 | rc = sftp_download_file(session, sftp, local_filename, remote_filename); |
---|
696 | if (rc == SSH_OK) |
---|
697 | { |
---|
698 | fprintf(stderr,"Remote file successfuly downloaded\n"); |
---|
699 | } |
---|
700 | |
---|
701 | // close sftp connection |
---|
702 | sftp_free(sftp); |
---|
703 | |
---|
704 | // Disconnect session |
---|
705 | ssh_disconnect(session); |
---|
706 | ssh_free(session); |
---|
707 | |
---|
708 | return rc; |
---|
709 | } |
---|
710 | |
---|
711 | |
---|
712 | #endif /* SSH_API_H_ */ |
---|