We now build libssh2 in Xcode and it's a much better UB/10.4 citizen
[printdrop.git] / Vendor / libssh2 / Source / scp.c
1 /* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms,
5 * with or without modification, are permitted provided
6 * that the following conditions are met:
7 *
8 * Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the
10 * following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
16 *
17 * Neither the name of the copyright holder nor the names
18 * of any other contributors may be used to endorse or
19 * promote products derived from this software without
20 * specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
34 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
35 * OF SUCH DAMAGE.
36 */
37
38 #include "libssh2_priv.h"
39 #include <errno.h>
40 #include <stdlib.h>
41
42 /* {{{ libssh2_scp_recv
43 * Open a channel and request a remote file via SCP
44 *
45 * NOTE: Will block in a busy loop on error. This has to be done,
46 * otherwise the blocking error code would erase the true
47 * cause of the error.
48 */
49 LIBSSH2_API LIBSSH2_CHANNEL *
50 libssh2_scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
51 {
52 int path_len = strlen(path);
53 int rc;
54
55 if (session->scpRecv_state == libssh2_NB_state_idle) {
56 session->scpRecv_mode = 0;
57 session->scpRecv_size = 0;
58 session->scpRecv_mtime = 0;
59 session->scpRecv_atime = 0;
60
61 session->scpRecv_command_len = path_len + sizeof("scp -f ");
62
63 if (sb) {
64 session->scpRecv_command_len++;
65 }
66
67 session->scpRecv_command =
68 LIBSSH2_ALLOC(session, session->scpRecv_command_len);
69 if (!session->scpRecv_command) {
70 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
71 "Unable to allocate a command buffer for SCP session",
72 0);
73 return NULL;
74 }
75 if (sb) {
76 memcpy(session->scpRecv_command, "scp -pf ",
77 sizeof("scp -pf ") - 1);
78 memcpy(session->scpRecv_command + sizeof("scp -pf ") - 1, path,
79 path_len);
80 } else {
81 memcpy(session->scpRecv_command, "scp -f ", sizeof("scp -f ") - 1);
82 memcpy(session->scpRecv_command + sizeof("scp -f ") - 1, path,
83 path_len);
84 }
85 session->scpRecv_command[session->scpRecv_command_len - 1] = '\0';
86
87 _libssh2_debug(session, LIBSSH2_DBG_SCP,
88 "Opening channel for SCP receive");
89
90 session->scpRecv_state = libssh2_NB_state_created;
91 }
92
93 if (session->scpRecv_state == libssh2_NB_state_created) {
94 /* Allocate a channel */
95 do {
96 session->scpRecv_channel =
97 libssh2_channel_open_ex(session, "session",
98 sizeof("session") - 1,
99 LIBSSH2_CHANNEL_WINDOW_DEFAULT,
100 LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL,
101 0);
102 if (!session->scpRecv_channel) {
103 if (libssh2_session_last_errno(session) !=
104 LIBSSH2_ERROR_EAGAIN) {
105 LIBSSH2_FREE(session, session->scpRecv_command);
106 session->scpRecv_command = NULL;
107 session->scpRecv_state = libssh2_NB_state_idle;
108 return NULL;
109 } else if (libssh2_session_last_errno(session) ==
110 LIBSSH2_ERROR_EAGAIN) {
111 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
112 "Would block starting up channel", 0);
113 return NULL;
114 }
115 }
116 } while (!session->scpRecv_channel);
117
118 session->scpRecv_state = libssh2_NB_state_sent;
119 }
120
121 if (session->scpRecv_state == libssh2_NB_state_sent) {
122 /* Request SCP for the desired file */
123 rc = libssh2_channel_process_startup(session->scpRecv_channel, "exec",
124 sizeof("exec") - 1,
125 (char *) session->scpRecv_command,
126 session->scpRecv_command_len);
127 if (rc == PACKET_EAGAIN) {
128 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
129 "Would block requesting SCP startup", 0);
130 return NULL;
131 } else if (rc) {
132 LIBSSH2_FREE(session, session->scpRecv_command);
133 session->scpRecv_command = NULL;
134 goto scp_recv_error;
135 }
136 LIBSSH2_FREE(session, session->scpRecv_command);
137 session->scpRecv_command = NULL;
138
139 _libssh2_debug(session, LIBSSH2_DBG_SCP, "Sending initial wakeup");
140 /* SCP ACK */
141 session->scpRecv_response[0] = '\0';
142
143 session->scpRecv_state = libssh2_NB_state_sent1;
144 }
145
146 if (session->scpRecv_state == libssh2_NB_state_sent1) {
147 rc = libssh2_channel_write_ex(session->scpRecv_channel, 0,
148 (char *) session->scpRecv_response, 1);
149 if (rc == PACKET_EAGAIN) {
150 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
151 "Would block sending initial wakeup", 0);
152 return NULL;
153 } else if (rc != 1) {
154 goto scp_recv_error;
155 }
156
157 /* Parse SCP response */
158 session->scpRecv_response_len = 0;
159
160 session->scpRecv_state = libssh2_NB_state_sent2;
161 }
162
163 if ((session->scpRecv_state == libssh2_NB_state_sent2)
164 || (session->scpRecv_state == libssh2_NB_state_sent3)) {
165 while (sb
166 && (session->scpRecv_response_len <
167 LIBSSH2_SCP_RESPONSE_BUFLEN)) {
168 unsigned char *s, *p;
169
170 if (session->scpRecv_state == libssh2_NB_state_sent2) {
171 rc = libssh2_channel_read_ex(session->scpRecv_channel, 0,
172 (char *) session->
173 scpRecv_response +
174 session->scpRecv_response_len, 1);
175 if (rc == PACKET_EAGAIN) {
176 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
177 "Would block waiting for SCP response", 0);
178 return NULL;
179 } else if (rc <= 0) {
180 /* Timeout, give up */
181 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
182 "Timed out waiting for SCP response", 0);
183 goto scp_recv_error;
184 }
185 session->scpRecv_response_len++;
186
187 if (session->scpRecv_response[0] != 'T') {
188 /*
189 * Set this as the default error for here, if
190 * we are successful it will be replaced
191 */
192 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
193 "Invalid data in SCP response, missing Time data",
194 0);
195
196 session->scpRecv_err_len =
197 libssh2_channel_packet_data_len(session->
198 scpRecv_channel, 0);
199 session->scpRecv_err_msg =
200 LIBSSH2_ALLOC(session, session->scpRecv_err_len + 1);
201 if (!session->scpRecv_err_msg) {
202 goto scp_recv_error;
203 }
204 memset(session->scpRecv_err_msg, 0,
205 session->scpRecv_err_len + 1);
206
207 /* Read the remote error message */
208 rc = libssh2_channel_read_ex(session->scpRecv_channel, 0,
209 session->scpRecv_err_msg,
210 session->scpRecv_err_len);
211 if (rc <= 0) {
212 /*
213 * Since we have alread started reading this packet, it is
214 * already in the systems so it can't return PACKET_EAGAIN
215 */
216 LIBSSH2_FREE(session, session->scpRecv_err_msg);
217 session->scpRecv_err_msg = NULL;
218 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
219 "Unknown error while getting error string",
220 0);
221 goto scp_recv_error;
222 }
223
224 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
225 session->scpRecv_err_msg, 1);
226 session->scpRecv_err_msg = NULL;
227 goto scp_recv_error;
228 }
229
230 if ((session->scpRecv_response_len > 1) &&
231 ((session->
232 scpRecv_response[session->scpRecv_response_len - 1] <
233 '0')
234 || (session->
235 scpRecv_response[session->scpRecv_response_len - 1] >
236 '9'))
237 && (session->
238 scpRecv_response[session->scpRecv_response_len - 1] !=
239 ' ')
240 && (session->
241 scpRecv_response[session->scpRecv_response_len - 1] !=
242 '\r')
243 && (session->
244 scpRecv_response[session->scpRecv_response_len - 1] !=
245 '\n')) {
246 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
247 "Invalid data in SCP response", 0);
248 goto scp_recv_error;
249 }
250
251 if ((session->scpRecv_response_len < 9)
252 || (session->
253 scpRecv_response[session->scpRecv_response_len - 1] !=
254 '\n')) {
255 if (session->scpRecv_response_len ==
256 LIBSSH2_SCP_RESPONSE_BUFLEN) {
257 /* You had your chance */
258 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
259 "Unterminated response from SCP server",
260 0);
261 goto scp_recv_error;
262 }
263 /* Way too short to be an SCP response, or not done yet, short circuit */
264 continue;
265 }
266
267 /* We're guaranteed not to go under response_len == 0 by the logic above */
268 while ((session->
269 scpRecv_response[session->scpRecv_response_len - 1] ==
270 '\r')
271 || (session->
272 scpRecv_response[session->scpRecv_response_len -
273 1] == '\n'))
274 session->scpRecv_response_len--;
275 session->scpRecv_response[session->scpRecv_response_len] =
276 '\0';
277
278 if (session->scpRecv_response_len < 8) {
279 /* EOL came too soon */
280 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
281 "Invalid response from SCP server, too short",
282 0);
283 goto scp_recv_error;
284 }
285
286 s = session->scpRecv_response + 1;
287
288 p = (unsigned char *) strchr((char *) s, ' ');
289 if (!p || ((p - s) <= 0)) {
290 /* No spaces or space in the wrong spot */
291 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
292 "Invalid response from SCP server, malformed mtime",
293 0);
294 goto scp_recv_error;
295 }
296
297 *(p++) = '\0';
298 /* Make sure we don't get fooled by leftover values */
299 errno = 0;
300 session->scpRecv_mtime = strtol((char *) s, NULL, 10);
301 if (errno) {
302 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
303 "Invalid response from SCP server, invalid mtime",
304 0);
305 goto scp_recv_error;
306 }
307 s = (unsigned char *) strchr((char *) p, ' ');
308 if (!s || ((s - p) <= 0)) {
309 /* No spaces or space in the wrong spot */
310 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
311 "Invalid response from SCP server, malformed mtime.usec",
312 0);
313 goto scp_recv_error;
314 }
315
316 /* Ignore mtime.usec */
317 s++;
318 p = (unsigned char *) strchr((char *) s, ' ');
319 if (!p || ((p - s) <= 0)) {
320 /* No spaces or space in the wrong spot */
321 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
322 "Invalid response from SCP server, too short or malformed",
323 0);
324 goto scp_recv_error;
325 }
326
327 *(p++) = '\0';
328 /* Make sure we don't get fooled by leftover values */
329 errno = 0;
330 session->scpRecv_atime = strtol((char *) s, NULL, 10);
331 if (errno) {
332 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
333 "Invalid response from SCP server, invalid atime",
334 0);
335 goto scp_recv_error;
336 }
337
338 /* SCP ACK */
339 session->scpRecv_response[0] = '\0';
340
341 session->scpRecv_state = libssh2_NB_state_sent3;
342 }
343
344 if (session->scpRecv_state == libssh2_NB_state_sent3) {
345 rc = libssh2_channel_write_ex(session->scpRecv_channel, 0,
346 (char *) session->
347 scpRecv_response, 1);
348 if (rc == PACKET_EAGAIN) {
349 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
350 "Would block waiting to send SCP ACK", 0);
351 return NULL;
352 } else if (rc != 1) {
353 goto scp_recv_error;
354 }
355
356 _libssh2_debug(session, LIBSSH2_DBG_SCP,
357 "mtime = %ld, atime = %ld",
358 session->scpRecv_mtime, session->scpRecv_atime);
359
360 /* We *should* check that atime.usec is valid, but why let that stop use? */
361 break;
362 }
363 }
364
365 session->scpRecv_state = libssh2_NB_state_sent4;
366 }
367
368 if (session->scpRecv_state == libssh2_NB_state_sent4) {
369 session->scpRecv_response_len = 0;
370
371 session->scpRecv_state = libssh2_NB_state_sent5;
372 }
373
374 if ((session->scpRecv_state == libssh2_NB_state_sent5)
375 || (session->scpRecv_state == libssh2_NB_state_sent6)) {
376 while (session->scpRecv_response_len < LIBSSH2_SCP_RESPONSE_BUFLEN) {
377 char *s, *p, *e = NULL;
378
379 if (session->scpRecv_state == libssh2_NB_state_sent5) {
380 rc = libssh2_channel_read_ex(session->scpRecv_channel, 0,
381 (char *) session->
382 scpRecv_response +
383 session->scpRecv_response_len, 1);
384 if (rc == PACKET_EAGAIN) {
385 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
386 "Would block waiting for SCP response", 0);
387 return NULL;
388 } else if (rc <= 0) {
389 /* Timeout, give up */
390 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
391 "Timed out waiting for SCP response", 0);
392 goto scp_recv_error;
393 }
394 session->scpRecv_response_len++;
395
396 if (session->scpRecv_response[0] != 'C') {
397 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
398 "Invalid response from SCP server", 0);
399 goto scp_recv_error;
400 }
401
402 if ((session->scpRecv_response_len > 1) &&
403 (session->
404 scpRecv_response[session->scpRecv_response_len - 1] !=
405 '\r')
406 && (session->
407 scpRecv_response[session->scpRecv_response_len - 1] !=
408 '\n')
409 &&
410 ((session->
411 scpRecv_response[session->scpRecv_response_len - 1] < 32)
412 || (session->
413 scpRecv_response[session->scpRecv_response_len - 1] >
414 126))) {
415 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
416 "Invalid data in SCP response", 0);
417 goto scp_recv_error;
418 }
419
420 if ((session->scpRecv_response_len < 7)
421 || (session->
422 scpRecv_response[session->scpRecv_response_len - 1] !=
423 '\n')) {
424 if (session->scpRecv_response_len ==
425 LIBSSH2_SCP_RESPONSE_BUFLEN) {
426 /* You had your chance */
427 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
428 "Unterminated response from SCP server",
429 0);
430 goto scp_recv_error;
431 }
432 /* Way too short to be an SCP response, or not done yet, short circuit */
433 continue;
434 }
435
436 /* We're guaranteed not to go under response_len == 0 by the logic above */
437 while ((session->
438 scpRecv_response[session->scpRecv_response_len - 1] ==
439 '\r')
440 || (session->
441 scpRecv_response[session->scpRecv_response_len -
442 1] == '\n')) {
443 session->scpRecv_response_len--;
444 }
445 session->scpRecv_response[session->scpRecv_response_len] =
446 '\0';
447
448 if (session->scpRecv_response_len < 6) {
449 /* EOL came too soon */
450 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
451 "Invalid response from SCP server, too short",
452 0);
453 goto scp_recv_error;
454 }
455
456 s = (char *) session->scpRecv_response + 1;
457
458 p = strchr(s, ' ');
459 if (!p || ((p - s) <= 0)) {
460 /* No spaces or space in the wrong spot */
461 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
462 "Invalid response from SCP server, malformed mode",
463 0);
464 goto scp_recv_error;
465 }
466
467 *(p++) = '\0';
468 /* Make sure we don't get fooled by leftover values */
469 errno = 0;
470 session->scpRecv_mode = strtol(s, &e, 8);
471 if ((e && *e) || errno) {
472 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
473 "Invalid response from SCP server, invalid mode",
474 0);
475 goto scp_recv_error;
476 }
477
478 s = strchr(p, ' ');
479 if (!s || ((s - p) <= 0)) {
480 /* No spaces or space in the wrong spot */
481 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
482 "Invalid response from SCP server, too short or malformed",
483 0);
484 goto scp_recv_error;
485 }
486
487 *(s++) = '\0';
488 /* Make sure we don't get fooled by leftover values */
489 errno = 0;
490 session->scpRecv_size = strtol(p, &e, 10);
491 if ((e && *e) || errno) {
492 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
493 "Invalid response from SCP server, invalid size",
494 0);
495 goto scp_recv_error;
496 }
497
498 /* SCP ACK */
499 session->scpRecv_response[0] = '\0';
500
501 session->scpRecv_state = libssh2_NB_state_sent6;
502 }
503
504 if (session->scpRecv_state == libssh2_NB_state_sent6) {
505 rc = libssh2_channel_write_ex(session->scpRecv_channel, 0,
506 (char *) session->
507 scpRecv_response, 1);
508 if (rc == PACKET_EAGAIN) {
509 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
510 "Would block sending SCP ACK", 0);
511 return NULL;
512 } else if (rc != 1) {
513 goto scp_recv_error;
514 }
515 _libssh2_debug(session, LIBSSH2_DBG_SCP,
516 "mode = 0%lo size = %ld", session->scpRecv_mode,
517 session->scpRecv_size);
518
519 /* We *should* check that basename is valid, but why let that stop us? */
520 break;
521 }
522 }
523
524 session->scpRecv_state = libssh2_NB_state_sent7;
525 }
526
527 if (sb) {
528 memset(sb, 0, sizeof(struct stat));
529
530 sb->st_mtime = session->scpRecv_mtime;
531 sb->st_atime = session->scpRecv_atime;
532 sb->st_size = session->scpRecv_size;
533 sb->st_mode = session->scpRecv_mode;
534 }
535
536 session->scpRecv_state = libssh2_NB_state_idle;
537 return session->scpRecv_channel;
538
539 scp_recv_error:
540 while (libssh2_channel_free(session->scpRecv_channel) == PACKET_EAGAIN);
541 session->scpRecv_channel = NULL;
542 session->scpRecv_state = libssh2_NB_state_idle;
543 return NULL;
544 }
545
546 /* }}} */
547
548 /* {{{ libssh2_scp_send_ex
549 * Send a file using SCP
550 *
551 * NOTE: Will block in a busy loop on error. This has to be done,
552 * otherwise the blocking error code would erase the true
553 * cause of the error.
554 */
555 LIBSSH2_API LIBSSH2_CHANNEL *
556 libssh2_scp_send_ex(LIBSSH2_SESSION * session, const char *path, int mode,
557 size_t size, long mtime, long atime)
558 {
559 int path_len = strlen(path);
560 unsigned const char *base;
561 int rc;
562
563 if (session->scpSend_state == libssh2_NB_state_idle) {
564 session->scpSend_command_len = path_len + sizeof("scp -t ");
565
566 if (mtime || atime) {
567 session->scpSend_command_len++;
568 }
569
570 session->scpSend_command =
571 LIBSSH2_ALLOC(session, session->scpSend_command_len);
572 if (!session->scpSend_command) {
573 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
574 "Unable to allocate a command buffer for scp session",
575 0);
576 return NULL;
577 }
578
579 if (mtime || atime) {
580 memcpy(session->scpSend_command, "scp -pt ",
581 sizeof("scp -pt ") - 1);
582 memcpy(session->scpSend_command + sizeof("scp -pt ") - 1, path,
583 path_len);
584 } else {
585 memcpy(session->scpSend_command, "scp -t ", sizeof("scp -t ") - 1);
586 memcpy(session->scpSend_command + sizeof("scp -t ") - 1, path,
587 path_len);
588 }
589 session->scpSend_command[session->scpSend_command_len - 1] = '\0';
590
591 _libssh2_debug(session, LIBSSH2_DBG_SCP,
592 "Opening channel for SCP send");
593 /* Allocate a channel */
594
595 session->scpSend_state = libssh2_NB_state_created;
596 }
597
598 if (session->scpSend_state == libssh2_NB_state_created) {
599 session->scpSend_channel =
600 libssh2_channel_open_ex(session, "session", sizeof("session") - 1,
601 LIBSSH2_CHANNEL_WINDOW_DEFAULT,
602 LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0);
603 if (!session->scpSend_channel) {
604 if (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) {
605 /* previous call set libssh2_session_last_error(), pass it through */
606 LIBSSH2_FREE(session, session->scpSend_command);
607 session->scpSend_command = NULL;
608 session->scpSend_state = libssh2_NB_state_idle;
609 return NULL;
610 } else if (libssh2_session_last_errno(session) ==
611 LIBSSH2_ERROR_EAGAIN) {
612 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
613 "Would block starting up channel", 0);
614 return NULL;
615 }
616 }
617
618 session->scpSend_state = libssh2_NB_state_sent;
619 }
620
621 if (session->scpSend_state == libssh2_NB_state_sent) {
622 /* Request SCP for the desired file */
623 rc = libssh2_channel_process_startup(session->scpSend_channel, "exec",
624 sizeof("exec") - 1,
625 (char *) session->scpSend_command,
626 session->scpSend_command_len);
627 if (rc == PACKET_EAGAIN) {
628 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
629 "Would block requesting SCP startup", 0);
630 return NULL;
631 } else if (rc) {
632 /* previous call set libssh2_session_last_error(), pass it through */
633 LIBSSH2_FREE(session, session->scpSend_command);
634 session->scpSend_command = NULL;
635 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
636 "Unknown error while getting error string", 0);
637 goto scp_send_error;
638 }
639 LIBSSH2_FREE(session, session->scpSend_command);
640 session->scpSend_command = NULL;
641
642 session->scpSend_state = libssh2_NB_state_sent1;
643 }
644
645 if (session->scpSend_state == libssh2_NB_state_sent1) {
646 /* Wait for ACK */
647 rc = libssh2_channel_read_ex(session->scpSend_channel, 0,
648 (char *) session->scpSend_response, 1);
649 if (rc == PACKET_EAGAIN) {
650 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
651 "Would block waiting for response from remote", 0);
652 return NULL;
653 } else if ((rc <= 0) || (session->scpSend_response[0] != 0)) {
654 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
655 "Invalid ACK response from remote", 0);
656 goto scp_send_error;
657 }
658
659 if (mtime || atime) {
660 /* Send mtime and atime to be used for file */
661 session->scpSend_response_len =
662 snprintf((char *) session->scpSend_response,
663 LIBSSH2_SCP_RESPONSE_BUFLEN, "T%ld 0 %ld 0\n", mtime,
664 atime);
665 _libssh2_debug(session, LIBSSH2_DBG_SCP, "Sent %s",
666 session->scpSend_response);
667 }
668
669 session->scpSend_state = libssh2_NB_state_sent2;
670 }
671
672 /* Send mtime and atime to be used for file */
673 if (mtime || atime) {
674 if (session->scpSend_state == libssh2_NB_state_sent2) {
675 rc = libssh2_channel_write_ex(session->scpSend_channel, 0,
676 (char *) session->scpSend_response,
677 session->scpSend_response_len);
678 if (rc == PACKET_EAGAIN) {
679 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
680 "Would block sending time data for SCP file", 0);
681 return NULL;
682 } else if (rc != session->scpSend_response_len) {
683 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
684 "Unable to send time data for SCP file", 0);
685 goto scp_send_error;
686 }
687
688 session->scpSend_state = libssh2_NB_state_sent3;
689 }
690
691 if (session->scpSend_state == libssh2_NB_state_sent3) {
692 /* Wait for ACK */
693 rc = libssh2_channel_read_ex(session->scpSend_channel, 0,
694 (char *) session->scpSend_response,
695 1);
696 if (rc == PACKET_EAGAIN) {
697 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
698 "Would block waiting for response", 0);
699 return NULL;
700 } else if ((rc <= 0) || (session->scpSend_response[0] != 0)) {
701 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
702 "Invalid ACK response from remote", 0);
703 goto scp_send_error;
704 }
705
706 session->scpSend_state = libssh2_NB_state_sent4;
707 }
708 } else {
709 if (session->scpSend_state == libssh2_NB_state_sent2) {
710 session->scpSend_state = libssh2_NB_state_sent4;
711 }
712 }
713
714 if (session->scpSend_state == libssh2_NB_state_sent4) {
715 /* Send mode, size, and basename */
716 base = (unsigned char *) strrchr(path, '/');
717 if (base) {
718 base++;
719 } else {
720 base = (unsigned char *) path;
721 }
722
723 session->scpSend_response_len =
724 snprintf((char *) session->scpSend_response,
725 LIBSSH2_SCP_RESPONSE_BUFLEN, "C0%o %lu %s\n", mode,
726 (unsigned long) size, base);
727 _libssh2_debug(session, LIBSSH2_DBG_SCP, "Sent %s",
728 session->scpSend_response);
729
730 session->scpSend_state = libssh2_NB_state_sent5;
731 }
732
733 if (session->scpSend_state == libssh2_NB_state_sent5) {
734 rc = libssh2_channel_write_ex(session->scpSend_channel, 0,
735 (char *) session->scpSend_response,
736 session->scpSend_response_len);
737 if (rc == PACKET_EAGAIN) {
738 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
739 "Would block send core file data for SCP file", 0);
740 return NULL;
741 } else if (rc != session->scpSend_response_len) {
742 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
743 "Unable to send core file data for SCP file", 0);
744 goto scp_send_error;
745 }
746
747 session->scpSend_state = libssh2_NB_state_sent6;
748 }
749
750 if (session->scpSend_state == libssh2_NB_state_sent6) {
751 /* Wait for ACK */
752 rc = libssh2_channel_read_ex(session->scpSend_channel, 0,
753 (char *) session->scpSend_response, 1);
754 if (rc == PACKET_EAGAIN) {
755 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
756 "Would block waiting for response", 0);
757 return NULL;
758 } else if (rc <= 0) {
759 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
760 "Invalid ACK response from remote", 0);
761 goto scp_send_error;
762 } else if (session->scpSend_response[0] != 0) {
763 /*
764 * Set this as the default error for here, if
765 * we are successful it will be replaced
766 */
767 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
768 "Invalid ACK response from remote", 0);
769
770 session->scpSend_err_len =
771 libssh2_channel_packet_data_len(session->scpSend_channel, 0);
772 session->scpSend_err_msg =
773 LIBSSH2_ALLOC(session, session->scpSend_err_len + 1);
774 if (!session->scpSend_err_msg) {
775 goto scp_send_error;
776 }
777 memset(session->scpSend_err_msg, 0, session->scpSend_err_len + 1);
778
779 /* Read the remote error message */
780 rc = libssh2_channel_read_ex(session->scpSend_channel, 0,
781 session->scpSend_err_msg,
782 session->scpSend_err_len);
783 if (rc <= 0) {
784 /*
785 * Since we have alread started reading this packet, it is
786 * already in the systems so it can't return PACKET_EAGAIN
787 */
788 LIBSSH2_FREE(session, session->scpSend_err_msg);
789 session->scpSend_err_msg = NULL;
790 goto scp_send_error;
791 }
792
793 libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
794 session->scpSend_err_msg, 1);
795 session->scpSend_err_msg = NULL;
796 goto scp_send_error;
797 }
798 }
799
800 session->scpSend_state = libssh2_NB_state_idle;
801
802 return session->scpSend_channel;
803
804 scp_send_error:
805 while (libssh2_channel_free(session->scpSend_channel) == PACKET_EAGAIN);
806 session->scpSend_channel = NULL;
807 session->scpSend_state = libssh2_NB_state_idle;
808 return NULL;
809 }
810
811 /* }}} */