We now build libssh2 in Xcode and it's a much better UB/10.4 citizen
[printdrop.git] / Vendor / libssh2 / Source / sftp.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 "libssh2_sftp.h"
40
41 /* Note: Version 6 was documented at the time of writing
42 * However it was marked as "DO NOT IMPLEMENT" due to pending changes
43 *
44 * This release of libssh2 implements Version 5 with automatic downgrade
45 * based on server's declaration
46 */
47
48 /* SFTP packet types */
49 #define SSH_FXP_INIT 1
50 #define SSH_FXP_VERSION 2
51 #define SSH_FXP_OPEN 3
52 #define SSH_FXP_CLOSE 4
53 #define SSH_FXP_READ 5
54 #define SSH_FXP_WRITE 6
55 #define SSH_FXP_LSTAT 7
56 #define SSH_FXP_FSTAT 8
57 #define SSH_FXP_SETSTAT 9
58 #define SSH_FXP_FSETSTAT 10
59 #define SSH_FXP_OPENDIR 11
60 #define SSH_FXP_READDIR 12
61 #define SSH_FXP_REMOVE 13
62 #define SSH_FXP_MKDIR 14
63 #define SSH_FXP_RMDIR 15
64 #define SSH_FXP_REALPATH 16
65 #define SSH_FXP_STAT 17
66 #define SSH_FXP_RENAME 18
67 #define SSH_FXP_READLINK 19
68 #define SSH_FXP_SYMLINK 20
69 #define SSH_FXP_STATUS 101
70 #define SSH_FXP_HANDLE 102
71 #define SSH_FXP_DATA 103
72 #define SSH_FXP_NAME 104
73 #define SSH_FXP_ATTRS 105
74 #define SSH_FXP_EXTENDED 200
75 #define SSH_FXP_EXTENDED_REPLY 201
76
77 #define LIBSSH2_SFTP_HANDLE_FILE 0
78 #define LIBSSH2_SFTP_HANDLE_DIR 1
79
80 /* S_IFREG */
81 #define LIBSSH2_SFTP_ATTR_PFILETYPE_FILE 0100000
82 /* S_IFDIR */
83 #define LIBSSH2_SFTP_ATTR_PFILETYPE_DIR 0040000
84
85 /* {{{ libssh2_sftp_packet_add
86 * Add a packet to the SFTP packet brigade
87 */
88 static int
89 libssh2_sftp_packet_add(LIBSSH2_SFTP * sftp, unsigned char *data,
90 unsigned long data_len)
91 {
92 LIBSSH2_SESSION *session = sftp->channel->session;
93 LIBSSH2_PACKET *packet;
94
95 _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Received packet %d",
96 (int) data[0]);
97 packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
98 if (!packet) {
99 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
100 "Unable to allocate datablock for SFTP packet", 0);
101 return -1;
102 }
103 memset(packet, 0, sizeof(LIBSSH2_PACKET));
104
105 packet->data = data;
106 packet->data_len = data_len;
107 packet->data_head = 5;
108 packet->brigade = &sftp->packets;
109 packet->next = NULL;
110 packet->prev = sftp->packets.tail;
111 if (packet->prev) {
112 packet->prev->next = packet;
113 } else {
114 sftp->packets.head = packet;
115 }
116 sftp->packets.tail = packet;
117
118 return 0;
119 }
120
121 /* }}} */
122
123 /* {{{ libssh2_sftp_packet_read
124 * Frame an SFTP packet off the channel
125 */
126 static int
127 libssh2_sftp_packet_read(LIBSSH2_SFTP * sftp, int flush)
128 {
129 LIBSSH2_CHANNEL *channel = sftp->channel;
130 LIBSSH2_SESSION *session = channel->session;
131 unsigned char buffer[4]; /* To store the packet length */
132 unsigned char *packet;
133 unsigned long packet_len, packet_received;
134 ssize_t bytes_received;
135 int rc;
136
137 _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Waiting for packet");
138
139 if (flush && sftp->partial_packet) {
140 /* When flushing, remove previous partial */
141 LIBSSH2_FREE(session, sftp->partial_packet);
142 sftp->partial_packet = NULL;
143 }
144
145 /* If there was a previous partial, start using it */
146 if (sftp->partial_packet) {
147 packet = sftp->partial_packet;
148 packet_len = sftp->partial_len;
149 packet_received = sftp->partial_received;
150 sftp->partial_packet = NULL;
151 } else {
152 if (flush && session->socket_block && !libssh2_waitsocket(session, 0)) {
153 /* While flushing in blocking mode, check before reading */
154 return -1;
155 }
156 rc = libssh2_channel_read_ex(channel, 0, (char *) buffer, 4);
157 if (flush && (rc < 0)) {
158 /* When flushing, exit quickly */
159 return -1;
160 } else if (rc == PACKET_EAGAIN) {
161 return PACKET_EAGAIN;
162 } else if (4 != rc) {
163 libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
164 "Timeout waiting for FXP packet", 0);
165 return -1;
166 }
167
168 packet_len = libssh2_ntohu32(buffer);
169 _libssh2_debug(session, LIBSSH2_DBG_SFTP,
170 "Data begin - Packet Length: %lu", packet_len);
171 if (packet_len > LIBSSH2_SFTP_PACKET_MAXLEN) {
172 libssh2_error(session, LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED,
173 "SFTP packet too large", 0);
174 return -1;
175 }
176
177 packet = LIBSSH2_ALLOC(session, packet_len);
178 if (!packet) {
179 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
180 "Unable to allocate SFTP packet", 0);
181 return -1;
182 }
183
184 packet_received = 0;
185 }
186
187 /* Read as much of the packet as we can */
188 while (packet_len > packet_received) {
189 bytes_received =
190 libssh2_channel_read_ex(channel, 0,
191 (char *) packet + packet_received,
192 packet_len - packet_received);
193
194 if (flush && (bytes_received < 0)) {
195 if (packet) {
196 /* When flushing, remove packet if existing */
197 LIBSSH2_FREE(session, packet);
198 }
199 /* When flushing, exit quickly */
200 return -1;
201 } else if (bytes_received == PACKET_EAGAIN) {
202 /*
203 * We received EAGAIN, save what we have and
204 * return to EAGAIN to the caller
205 */
206 sftp->partial_packet = packet;
207 sftp->partial_len = packet_len;
208 sftp->partial_received = packet_received;
209 packet = NULL;
210
211 return PACKET_EAGAIN;
212 } else if (bytes_received < 0) {
213 libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
214 "Receive error waiting for SFTP packet", 0);
215 LIBSSH2_FREE(session, packet);
216 return -1;
217 }
218 packet_received += bytes_received;
219 }
220
221 if (libssh2_sftp_packet_add(sftp, packet, packet_len)) {
222 LIBSSH2_FREE(session, packet);
223 return -1;
224 }
225
226 return packet[0];
227 }
228
229 /* }}} */
230
231 /* {{{ libssh2_sftp_packet_ask
232 * A la libssh2_packet_ask()
233 */
234 static int
235 libssh2_sftp_packet_ask(LIBSSH2_SFTP * sftp, unsigned char packet_type,
236 unsigned long request_id, unsigned char **data,
237 unsigned long *data_len, int poll_channel)
238 {
239 LIBSSH2_SESSION *session = sftp->channel->session;
240 LIBSSH2_PACKET *packet = sftp->packets.head;
241 unsigned char match_buf[5];
242 int match_len = 5;
243
244 _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Asking for %d packet",
245 (int) packet_type);
246 if (poll_channel) {
247 int ret = libssh2_sftp_packet_read(sftp, 0);
248 if (ret == PACKET_EAGAIN) {
249 return PACKET_EAGAIN;
250 } else if (ret < 0) {
251 return -1;
252 }
253 }
254
255 match_buf[0] = packet_type;
256 if (packet_type == SSH_FXP_VERSION) {
257 /* Special consideration when matching VERSION packet */
258 match_len = 1;
259 } else {
260 libssh2_htonu32(match_buf + 1, request_id);
261 }
262
263 while (packet) {
264 if (strncmp((char *) packet->data, (char *) match_buf, match_len) == 0) {
265 *data = packet->data;
266 *data_len = packet->data_len;
267
268 if (packet->prev) {
269 packet->prev->next = packet->next;
270 } else {
271 sftp->packets.head = packet->next;
272 }
273
274 if (packet->next) {
275 packet->next->prev = packet->prev;
276 } else {
277 sftp->packets.tail = packet->prev;
278 }
279
280 LIBSSH2_FREE(session, packet);
281
282 return 0;
283 }
284 packet = packet->next;
285 }
286 return -1;
287 }
288
289 /* }}} */
290
291 /* {{{ libssh2_sftp_packet_require
292 * A la libssh2_packet_require
293 */
294 static int
295 libssh2_sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
296 unsigned long request_id, unsigned char **data,
297 unsigned long *data_len)
298 {
299 LIBSSH2_SESSION *session = sftp->channel->session;
300 int ret;
301
302 _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Requiring %d packet",
303 (int) packet_type);
304
305 if (libssh2_sftp_packet_ask
306 (sftp, packet_type, request_id, data, data_len, 0) == 0) {
307 /* The right packet was available in the packet brigade */
308 return 0;
309 }
310
311 while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
312 ret = libssh2_sftp_packet_read(sftp, 0);
313 if (ret == PACKET_EAGAIN) {
314 return PACKET_EAGAIN;
315 } else if (ret <= 0) {
316 return -1;
317 }
318
319 if (packet_type == ret) {
320 /* Be lazy, let packet_ask pull it out of the brigade */
321 return libssh2_sftp_packet_ask(sftp, packet_type, request_id, data,
322 data_len, 0);
323 }
324 }
325
326 /* Only reached if the socket died */
327 return -1;
328 }
329
330 /* }}} */
331
332 /* {{{ libssh2_sftp_packet_requirev
333 * Requie one of N possible reponses
334 */
335 static int
336 libssh2_sftp_packet_requirev(LIBSSH2_SFTP * sftp, int num_valid_responses,
337 const unsigned char *valid_responses,
338 unsigned long request_id, unsigned char **data,
339 unsigned long *data_len)
340 {
341 int i;
342 int ret;
343
344 /*
345 * If no timeout is active, start a new one and flush
346 * any pending packets
347 */
348 if (sftp->requirev_start == 0) {
349 _libssh2_debug(sftp->channel->session, LIBSSH2_DBG_SFTP,
350 "_requirev(): Initialize timeout");
351 sftp->requirev_start = time(NULL);
352
353 /* Flush */
354 while (libssh2_sftp_packet_read(sftp, 1) > 0);
355 }
356
357 while (sftp->channel->session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
358 for(i = 0; i < num_valid_responses; i++) {
359 if (libssh2_sftp_packet_ask
360 (sftp, valid_responses[i], request_id, data, data_len,
361 0) == 0) {
362 /*
363 * Set to zero before all returns to say
364 * the timeout is not active
365 */
366 sftp->requirev_start = 0;
367 return 0;
368 }
369 }
370
371 ret = libssh2_sftp_packet_read(sftp, 0);
372 if ((ret < 0) && (ret != PACKET_EAGAIN)) {
373 sftp->requirev_start = 0;
374 return -1;
375 } else if (ret <= 0) {
376 /* prevent busy-looping */
377 long left =
378 LIBSSH2_READ_TIMEOUT - (time(NULL) - sftp->requirev_start);
379
380 if (left <= 0) {
381 sftp->requirev_start = 0;
382 return PACKET_TIMEOUT;
383 } else if (sftp->channel->session->socket_block
384 && (libssh2_waitsocket(sftp->channel->session, left) <=
385 0)) {
386 sftp->requirev_start = 0;
387 return PACKET_TIMEOUT;
388 } else if (ret == PACKET_EAGAIN) {
389 return PACKET_EAGAIN;
390 }
391 }
392 }
393
394 sftp->requirev_start = 0;
395 return -1;
396 }
397
398 /* }}} */
399
400 /* {{{ libssh2_sftp_attrsize
401 * Size that attr will occupy when turned into a bin struct
402 */
403 static int
404 libssh2_sftp_attrsize(const LIBSSH2_SFTP_ATTRIBUTES * attrs)
405 {
406 int attrsize = 4; /* flags(4) */
407
408 if (!attrs) {
409 return attrsize;
410 }
411
412 if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE)
413 attrsize += 8;
414 if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID)
415 attrsize += 8;
416 if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS)
417 attrsize += 4;
418 if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME)
419 attrsize += 8; /* atime + mtime as u32 */
420
421 return attrsize;
422 }
423
424 /* }}} */
425
426 /* {{{ libssh2_sftp_attr2bin
427 * Populate attributes into an SFTP block
428 */
429 static int
430 libssh2_sftp_attr2bin(unsigned char *p, const LIBSSH2_SFTP_ATTRIBUTES * attrs)
431 {
432 unsigned char *s = p;
433 unsigned long flag_mask =
434 LIBSSH2_SFTP_ATTR_SIZE | LIBSSH2_SFTP_ATTR_UIDGID |
435 LIBSSH2_SFTP_ATTR_PERMISSIONS | LIBSSH2_SFTP_ATTR_ACMODTIME;
436
437 /* TODO: When we add SFTP4+ functionality flag_mask can get additional bits */
438
439 if (!attrs) {
440 libssh2_htonu32(s, 0);
441 return 4;
442 }
443
444 libssh2_htonu32(s, attrs->flags & flag_mask);
445 s += 4;
446
447 if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
448 libssh2_htonu64(s, attrs->filesize);
449 s += 8;
450 }
451
452 if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
453 libssh2_htonu32(s, attrs->uid);
454 s += 4;
455 libssh2_htonu32(s, attrs->gid);
456 s += 4;
457 }
458
459 if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
460 libssh2_htonu32(s, attrs->permissions);
461 s += 4;
462 }
463
464 if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
465 libssh2_htonu32(s, attrs->atime);
466 s += 4;
467 libssh2_htonu32(s, attrs->mtime);
468 s += 4;
469 }
470
471 return (s - p);
472 }
473
474 /* }}} */
475
476 /* {{{ libssh2_sftp_bin2attr
477 */
478 static int
479 libssh2_sftp_bin2attr(LIBSSH2_SFTP_ATTRIBUTES * attrs, const unsigned char *p)
480 {
481 const unsigned char *s = p;
482
483 memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
484 attrs->flags = libssh2_ntohu32(s);
485 s += 4;
486
487 if (attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
488 attrs->filesize = libssh2_ntohu64(s);
489 s += 8;
490 }
491
492 if (attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
493 attrs->uid = libssh2_ntohu32(s);
494 s += 4;
495 attrs->gid = libssh2_ntohu32(s);
496 s += 4;
497 }
498
499 if (attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
500 attrs->permissions = libssh2_ntohu32(s);
501 s += 4;
502 }
503
504 if (attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
505 attrs->atime = libssh2_ntohu32(s);
506 s += 4;
507 attrs->mtime = libssh2_ntohu32(s);
508 s += 4;
509 }
510
511 return (s - p);
512 }
513
514 /* }}} */
515
516 /* ************
517 * SFTP API *
518 ************ */
519
520 LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor);
521
522 /* {{{ libssh2_sftp_dtor
523 * Shutdown an SFTP stream when the channel closes
524 */
525 LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor)
526 {
527 LIBSSH2_SFTP *sftp = (LIBSSH2_SFTP *) (*channel_abstract);
528
529 (void) session_abstract;
530 (void) channel;
531
532 /* Loop through handles closing them */
533 while (sftp->handles) {
534 libssh2_sftp_close_handle(sftp->handles);
535 }
536
537 /* Free the partial packet storage for libssh2_sftp_packet_read */
538 if (sftp->partial_packet) {
539 LIBSSH2_FREE(session, sftp->partial_packet);
540 }
541
542 /* Free the packet storage for _libssh2_sftp_packet_readdir */
543 if (sftp->readdir_packet) {
544 LIBSSH2_FREE(session, sftp->readdir_packet);
545 }
546
547 LIBSSH2_FREE(session, sftp);
548 }
549
550 /* }}} */
551
552 /* {{{ libssh2_sftp_init
553 * Startup an SFTP session
554 *
555 * NOTE: Will block in a busy loop on error. This has to be done,
556 * otherwise the blocking error code would erase the true
557 * cause of the error.
558 */
559 LIBSSH2_API LIBSSH2_SFTP *
560 libssh2_sftp_init(LIBSSH2_SESSION * session)
561 {
562 unsigned char *data, *s;
563 unsigned long data_len;
564 int rc;
565
566 if (session->sftpInit_state == libssh2_NB_state_idle) {
567 _libssh2_debug(session, LIBSSH2_DBG_SFTP,
568 "Initializing SFTP subsystem");
569
570 session->sftpInit_sftp = NULL;
571
572 session->sftpInit_state = libssh2_NB_state_created;
573 }
574
575 if (session->sftpInit_state == libssh2_NB_state_created) {
576 session->sftpInit_channel =
577 libssh2_channel_open_ex(session, "session", sizeof("session") - 1,
578 LIBSSH2_CHANNEL_WINDOW_DEFAULT,
579 LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0);
580 if (!session->sftpInit_channel) {
581 if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
582 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
583 "Would block starting up channel", 0);
584 return NULL;
585 } else if (libssh2_session_last_errno(session) !=
586 LIBSSH2_ERROR_EAGAIN) {
587 libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
588 "Unable to startup channel", 0);
589 session->sftpInit_state = libssh2_NB_state_idle;
590 return NULL;
591 }
592 }
593
594 session->sftpInit_state = libssh2_NB_state_sent;
595 }
596
597 if (session->sftpInit_state == libssh2_NB_state_sent) {
598 rc = libssh2_channel_process_startup(session->sftpInit_channel,
599 "subsystem",
600 sizeof("subsystem") - 1, "sftp",
601 strlen("sftp"));
602 if (rc == PACKET_EAGAIN) {
603 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
604 "Would block to request SFTP subsystem", 0);
605 return NULL;
606 } else if (rc) {
607 libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
608 "Unable to request SFTP subsystem", 0);
609 goto sftp_init_error;
610 }
611
612 session->sftpInit_state = libssh2_NB_state_sent1;
613 }
614
615 if (session->sftpInit_state == libssh2_NB_state_sent1) {
616 rc = libssh2_channel_handle_extended_data2(session->sftpInit_channel,
617 LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE);
618 if (rc == PACKET_EAGAIN) {
619 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
620 "Would block requesting handle extended data", 0);
621 return NULL;
622 }
623
624 session->sftpInit_sftp = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP));
625 if (!session->sftpInit_sftp) {
626 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
627 "Unable to allocate a new SFTP structure", 0);
628 goto sftp_init_error;
629 }
630 memset(session->sftpInit_sftp, 0, sizeof(LIBSSH2_SFTP));
631 session->sftpInit_sftp->channel = session->sftpInit_channel;
632 session->sftpInit_sftp->request_id = 0;
633
634 libssh2_htonu32(session->sftpInit_buffer, 5);
635 session->sftpInit_buffer[4] = SSH_FXP_INIT;
636 libssh2_htonu32(session->sftpInit_buffer + 5, LIBSSH2_SFTP_VERSION);
637
638 _libssh2_debug(session, LIBSSH2_DBG_SFTP,
639 "Sending FXP_INIT packet advertising version %d support",
640 (int) LIBSSH2_SFTP_VERSION);
641
642 session->sftpInit_state = libssh2_NB_state_sent2;
643 }
644
645 if (session->sftpInit_state == libssh2_NB_state_sent2) {
646 rc = libssh2_channel_write_ex(session->sftpInit_channel, 0,
647 (char *) session->sftpInit_buffer, 9);
648 if (rc == PACKET_EAGAIN) {
649 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
650 "Would block sending SSH_FXP_INIT", 0);
651 return NULL;
652 } else if (9 != rc) {
653 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
654 "Unable to send SSH_FXP_INIT", 0);
655 goto sftp_init_error;
656 }
657
658 session->sftpInit_state = libssh2_NB_state_sent3;
659 }
660
661 /* For initiallization we are requiring blocking, probably reasonable */
662 rc = libssh2_sftp_packet_require(session->sftpInit_sftp, SSH_FXP_VERSION,
663 0, &data, &data_len);
664 if (rc == PACKET_EAGAIN) {
665 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
666 "Would block waiting for response from SFTP subsystem",
667 0);
668 return NULL;
669 } else if (rc) {
670 libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
671 "Timeout waiting for response from SFTP subsystem", 0);
672 goto sftp_init_error;
673 }
674 if (data_len < 5) {
675 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
676 "Invalid SSH_FXP_VERSION response", 0);
677 goto sftp_init_error;
678 }
679
680 s = data + 1;
681 session->sftpInit_sftp->version = libssh2_ntohu32(s);
682 s += 4;
683 if (session->sftpInit_sftp->version > LIBSSH2_SFTP_VERSION) {
684 _libssh2_debug(session, LIBSSH2_DBG_SFTP,
685 "Truncating remote SFTP version from %lu",
686 session->sftpInit_sftp->version);
687 session->sftpInit_sftp->version = LIBSSH2_SFTP_VERSION;
688 }
689 _libssh2_debug(session, LIBSSH2_DBG_SFTP,
690 "Enabling SFTP version %lu compatability",
691 session->sftpInit_sftp->version);
692 while (s < (data + data_len)) {
693 unsigned char *extension_name, *extension_data;
694 unsigned long extname_len, extdata_len;
695
696 extname_len = libssh2_ntohu32(s);
697 s += 4;
698 extension_name = s;
699 s += extname_len;
700
701 extdata_len = libssh2_ntohu32(s);
702 s += 4;
703 extension_data = s;
704 s += extdata_len;
705
706 /* TODO: Actually process extensions */
707 }
708 LIBSSH2_FREE(session, data);
709
710 /* Make sure that when the channel gets closed, the SFTP service is shut down too */
711 session->sftpInit_sftp->channel->abstract = session->sftpInit_sftp;
712 session->sftpInit_sftp->channel->close_cb = libssh2_sftp_dtor;
713
714 session->sftpInit_state = libssh2_NB_state_idle;
715 return session->sftpInit_sftp;
716
717 sftp_init_error:
718 while (libssh2_channel_free(session->sftpInit_channel) == PACKET_EAGAIN);
719 session->sftpInit_channel = NULL;
720 if (session->sftpInit_sftp) {
721 LIBSSH2_FREE(session, session->sftpInit_sftp);
722 session->sftpInit_sftp = NULL;
723 }
724 session->sftpInit_state = libssh2_NB_state_idle;
725 return NULL;
726 }
727
728 /* }}} */
729
730 /* {{{ libssh2_sftp_shutdown
731 * Shutsdown the SFTP subsystem
732 */
733 LIBSSH2_API int
734 libssh2_sftp_shutdown(LIBSSH2_SFTP * sftp)
735 {
736 /*
737 * Make sure all memory used in the state variables are free
738 */
739 if (sftp->partial_packet) {
740 LIBSSH2_FREE(sftp->channel->session, sftp->partial_packet);
741 sftp->partial_packet = NULL;
742 }
743 if (sftp->open_packet) {
744 LIBSSH2_FREE(sftp->channel->session, sftp->open_packet);
745 sftp->open_packet = NULL;
746 }
747 if (sftp->read_packet) {
748 LIBSSH2_FREE(sftp->channel->session, sftp->read_packet);
749 sftp->read_packet = NULL;
750 }
751 if (sftp->readdir_packet) {
752 LIBSSH2_FREE(sftp->channel->session, sftp->readdir_packet);
753 sftp->readdir_packet = NULL;
754 }
755 if (sftp->write_packet) {
756 LIBSSH2_FREE(sftp->channel->session, sftp->write_packet);
757 sftp->write_packet = NULL;
758 }
759 if (sftp->fstat_packet) {
760 LIBSSH2_FREE(sftp->channel->session, sftp->fstat_packet);
761 sftp->fstat_packet = NULL;
762 }
763 if (sftp->unlink_packet) {
764 LIBSSH2_FREE(sftp->channel->session, sftp->unlink_packet);
765 sftp->unlink_packet = NULL;
766 }
767 if (sftp->rename_packet) {
768 LIBSSH2_FREE(sftp->channel->session, sftp->rename_packet);
769 sftp->rename_packet = NULL;
770 }
771 if (sftp->mkdir_packet) {
772 LIBSSH2_FREE(sftp->channel->session, sftp->mkdir_packet);
773 sftp->mkdir_packet = NULL;
774 }
775 if (sftp->rmdir_packet) {
776 LIBSSH2_FREE(sftp->channel->session, sftp->rmdir_packet);
777 sftp->rmdir_packet = NULL;
778 }
779 if (sftp->stat_packet) {
780 LIBSSH2_FREE(sftp->channel->session, sftp->stat_packet);
781 sftp->stat_packet = NULL;
782 }
783 if (sftp->symlink_packet) {
784 LIBSSH2_FREE(sftp->channel->session, sftp->symlink_packet);
785 sftp->symlink_packet = NULL;
786 }
787
788 return libssh2_channel_free(sftp->channel);
789 }
790
791 /* }}} */
792
793 /* *******************************
794 * SFTP File and Directory Ops *
795 ******************************* */
796
797 /* {{{ libssh2_sftp_open_ex
798 */
799 LIBSSH2_API LIBSSH2_SFTP_HANDLE *
800 libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
801 unsigned int filename_len, unsigned long flags, long mode,
802 int open_type)
803 {
804 LIBSSH2_CHANNEL *channel = sftp->channel;
805 LIBSSH2_SESSION *session = channel->session;
806 LIBSSH2_SFTP_HANDLE *fp;
807 LIBSSH2_SFTP_ATTRIBUTES attrs = {
808 LIBSSH2_SFTP_ATTR_PERMISSIONS, 0, 0, 0, 0, 0, 0
809 };
810 unsigned long data_len;
811 unsigned char *data, *s;
812 static const unsigned char fopen_responses[2] =
813 { SSH_FXP_HANDLE, SSH_FXP_STATUS };
814 int rc;
815
816 if (sftp->open_state == libssh2_NB_state_idle) {
817 /* packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) + flags(4) */
818 sftp->open_packet_len = filename_len + 13 +
819 ((open_type ==
820 LIBSSH2_SFTP_OPENFILE) ? (4 +
821 libssh2_sftp_attrsize(&attrs)) : 0);
822
823 s = sftp->open_packet = LIBSSH2_ALLOC(session, sftp->open_packet_len);
824 if (!sftp->open_packet) {
825 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
826 "Unable to allocate memory for FXP_OPEN or FXP_OPENDIR packet",
827 0);
828 return NULL;
829 }
830 /* Filetype in SFTP 3 and earlier */
831 attrs.permissions = mode |
832 ((open_type ==
833 LIBSSH2_SFTP_OPENFILE) ? LIBSSH2_SFTP_ATTR_PFILETYPE_FILE :
834 LIBSSH2_SFTP_ATTR_PFILETYPE_DIR);
835
836 libssh2_htonu32(s, sftp->open_packet_len - 4);
837 s += 4;
838 *(s++) =
839 (open_type ==
840 LIBSSH2_SFTP_OPENFILE) ? SSH_FXP_OPEN : SSH_FXP_OPENDIR;
841 sftp->open_request_id = sftp->request_id++;
842 libssh2_htonu32(s, sftp->open_request_id);
843 s += 4;
844 libssh2_htonu32(s, filename_len);
845 s += 4;
846 memcpy(s, filename, filename_len);
847 s += filename_len;
848 if (open_type == LIBSSH2_SFTP_OPENFILE) {
849 libssh2_htonu32(s, flags);
850 s += 4;
851 s += libssh2_sftp_attr2bin(s, &attrs);
852 }
853
854 _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Sending %s open request",
855 (open_type ==
856 LIBSSH2_SFTP_OPENFILE) ? "file" : "directory");
857
858 sftp->open_state = libssh2_NB_state_created;
859 }
860
861 if (sftp->open_state == libssh2_NB_state_created) {
862 rc = libssh2_channel_write_ex(channel, 0, (char *) sftp->open_packet,
863 sftp->open_packet_len);
864 if (rc == PACKET_EAGAIN) {
865 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
866 "Would block sending FXP_OPEN or FXP_OPENDIR command",
867 0);
868 return NULL;
869 } else if (sftp->open_packet_len != rc) {
870 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
871 "Unable to send FXP_OPEN or FXP_OPENDIR command", 0);
872 LIBSSH2_FREE(session, sftp->open_packet);
873 sftp->open_packet = NULL;
874 sftp->open_state = libssh2_NB_state_idle;
875 return NULL;
876 }
877 LIBSSH2_FREE(session, sftp->open_packet);
878 sftp->open_packet = NULL;
879
880 sftp->open_state = libssh2_NB_state_sent;
881 }
882
883 if (sftp->open_state == libssh2_NB_state_sent) {
884 rc = libssh2_sftp_packet_requirev(sftp, 2, fopen_responses,
885 sftp->open_request_id, &data,
886 &data_len);
887 if (rc == PACKET_EAGAIN) {
888 libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
889 "Would block waiting for status message", 0);
890 return NULL;
891 } else if (rc) {
892 libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
893 "Timeout waiting for status message", 0);
894 sftp->open_state = libssh2_NB_state_idle;
895 return NULL;
896 }
897 }
898
899 sftp->open_state = libssh2_NB_state_idle;
900
901 if (data[0] == SSH_FXP_STATUS) {
902 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
903 "Failed opening remote file", 0);
904 sftp->last_errno = libssh2_ntohu32(data + 5);
905 LIBSSH2_FREE(session, data);
906 return NULL;
907 }
908
909 fp = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP_HANDLE));
910 if (!fp) {
911 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
912 "Unable to allocate new SFTP handle structure", 0);
913 LIBSSH2_FREE(session, data);
914 return NULL;
915 }
916 memset(fp, 0, sizeof(LIBSSH2_SFTP_HANDLE));
917 fp->handle_type =
918 (open_type ==
919 LIBSSH2_SFTP_OPENFILE) ? LIBSSH2_SFTP_HANDLE_FILE :
920 LIBSSH2_SFTP_HANDLE_DIR;
921
922 fp->handle_len = libssh2_ntohu32(data + 5);
923 if (fp->handle_len > 256) {
924 /* SFTP doesn't allow handles longer than 256 characters */
925 fp->handle_len = 256;
926 }
927 fp->handle = LIBSSH2_ALLOC(session, fp->handle_len);
928 if (!fp->handle) {
929 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
930 "Unable to allocate space for SFTP file/dir handle", 0);
931 LIBSSH2_FREE(session, data);
932 LIBSSH2_FREE(session, fp);
933 return NULL;
934 }
935 memcpy(fp->handle, data + 9, fp->handle_len);
936 LIBSSH2_FREE(session, data);
937
938 /* Link the file and the sftp session together */
939 fp->next = sftp->handles;
940 if (fp->next) {
941 fp->next->prev = fp;
942 }
943 fp->sftp = sftp;
944
945 fp->u.file.offset = 0;
946
947 _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Open command successful");
948 return fp;
949 }
950
951 /* }}} */
952
953 /* {{{ libssh2_sftp_read
954 * Read from an SFTP file handle
955 */
956 LIBSSH2_API ssize_t
957 libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
958 size_t buffer_maxlen)
959 {
960 LIBSSH2_SFTP *sftp = handle->sftp;
961 LIBSSH2_CHANNEL *channel = sftp->channel;
962 LIBSSH2_SESSION *session = channel->session;
963 unsigned long data_len, request_id;
964 /* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) + offset(8) + length(4) */
965 ssize_t packet_len = handle->handle_len + 25;
966 unsigned char *packet, *s, *data;
967 static const unsigned char read_responses[2] =
968 { SSH_FXP_DATA, SSH_FXP_STATUS };
969 size_t bytes_read = 0;
970 size_t bytes_requested = 0;
971 size_t total_read = 0;
972 int retcode;
973
974 if (sftp->read_state == libssh2_NB_state_idle) {
975 _libssh2_debug(session, LIBSSH2_DBG_SFTP,
976 "Reading %lu bytes from SFTP handle",
977 (unsigned long) buffer_maxlen);
978 packet = LIBSSH2_ALLOC(session, packet_len);
979 if (!packet) {
980 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
981 "Unable to allocate memory for FXP_CLOSE packet", 0);
982 return -1;
983 }
984 sftp->read_state = libssh2_NB_state_allocated;
985 } else {
986 packet = sftp->read_packet;
987 request_id = sftp->read_request_id;
988 total_read = sftp->read_total_read;
989 }
990
991 while (total_read < buffer_maxlen) {
992 s = packet;
993 /*
994 * If buffer_maxlen bytes will be requested, server may return all
995 * with one packet. But libssh2 have packet length limit.
996 * So we request data by pieces.
997 */
998 bytes_requested = buffer_maxlen - total_read;
999 /* 10 = packet_type(1)+request_id(4)+data_length(4)+end_of_line_flag(1) */
1000 if (bytes_requested > LIBSSH2_SFTP_PACKET_MAXLEN - 10) {
1001 bytes_requested = LIBSSH2_SFTP_PACKET_MAXLEN - 10;
1002 }
1003 #ifdef LIBSSH2_DEBUG_SFTP
1004 _libssh2_debug(session, LIBSSH2_DBG_SFTP,
1005 "Requesting %lu bytes from SFTP handle",
1006 (unsigned long) bytes_requested);
1007 #endif
1008
1009 if (sftp->read_state == libssh2_NB_state_allocated) {
1010 libssh2_htonu32(s, packet_len - 4);
1011 s += 4;
1012 *(s++) = SSH_FXP_READ;
1013 request_id = sftp->request_id++;
1014 libssh2_htonu32(s, request_id);
1015 s += 4;
1016 libssh2_htonu32(s, handle->handle_len);
1017 s += 4;
1018
1019 memcpy(s, handle->handle, handle->handle_len);
1020 s += handle->handle_len;
1021
1022 libssh2_htonu64(s, handle->u.file.offset);
1023 s += 8;
1024
1025 libssh2_htonu32(s, buffer_maxlen);
1026 s += 4;
1027
1028 sftp->read_state = libssh2_NB_state_created;
1029 }
1030
1031 if (sftp->read_state == libssh2_NB_state_created) {
1032 retcode =
1033 libssh2_channel_write_ex(channel, 0, (char *) packet,
1034 packet_len);
1035 if (retcode == PACKET_EAGAIN) {
1036 sftp->read_packet = packet;
1037 sftp->read_request_id = request_id;
1038 sftp->read_total_read = total_read;
1039 return PACKET_EAGAIN;
1040 } else if (packet_len != retcode) {
1041 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
1042 "Unable to send FXP_READ command", 0);
1043 LIBSSH2_FREE(session, packet);
1044 sftp->read_packet = NULL;
1045 sftp->read_state = libssh2_NB_state_idle;
1046 return -1;
1047 }
1048 sftp->read_packet = packet;
1049 sftp->read_request_id = request_id;
1050 sftp->read_total_read = total_read;
1051 sftp->read_state = libssh2_NB_state_sent;
1052 }
1053
1054 if (sftp->read_state == libssh2_NB_state_sent) {
1055 retcode =
1056 libssh2_sftp_packet_requirev(sftp, 2, read_responses,
1057 request_id, &data, &data_len);
1058 if (retcode == PACKET_EAGAIN) {
1059 return PACKET_EAGAIN;
1060 } else if (retcode) {
1061 libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
1062 "Timeout waiting for status message", 0);
1063 LIBSSH2_FREE(session, packet);
1064 sftp->read_packet = NULL;
1065 sftp->read_state = libssh2_NB_state_idle;
1066 return -1;
1067 }
1068
1069 sftp->read_state = libssh2_NB_state_sent1;
1070 }
1071
1072 switch (data[0]) {
1073 case SSH_FXP_STATUS:
1074 retcode = libssh2_ntohu32(data + 5);
1075 LIBSSH2_FREE(session, packet);
1076 LIBSSH2_FREE(session, data);
1077 sftp->read_packet = NULL;
1078 sftp->read_state = libssh2_NB_state_idle;
1079
1080 if (retcode == LIBSSH2_FX_EOF) {
1081 return total_read;
1082 } else {
1083 sftp->last_errno = retcode;
1084 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1085 "SFTP Protocol Error", 0);
1086 return -1;
1087 }
1088
1089 case SSH_FXP_DATA:
1090 bytes_read = libssh2_ntohu32(data + 5);
1091 if (bytes_read > (data_len - 9)) {
1092 LIBSSH2_FREE(session, packet);
1093 sftp->read_packet = NULL;
1094 sftp->read_state = libssh2_NB_state_idle;
1095 return -1;
1096 }
1097 #ifdef LIBSSH2_DEBUG_SFTP
1098 _libssh2_debug(session, LIBSSH2_DBG_SFTP, "%lu bytes returned",
1099 (unsigned long) bytes_read);
1100 #endif
1101 memcpy(buffer + total_read, data + 9, bytes_read);
1102 handle->u.file.offset += bytes_read;
1103 total_read += bytes_read;
1104 LIBSSH2_FREE(session, data);
1105 /*
1106 * Set the state back to allocated, so a new one will be
1107 * created to either request more data or get EOF
1108 */
1109 sftp->read_state = libssh2_NB_state_allocated;
1110 }
1111 }
1112
1113 LIBSSH2_FREE(session, packet);
1114 sftp->read_packet = NULL;
1115 sftp->read_state = libssh2_NB_state_idle;
1116 return total_read;
1117 }
1118
1119 /* }}} */
1120
1121 /* {{{ libssh2_sftp_readdir
1122 * Read from an SFTP directory handle
1123 */
1124 LIBSSH2_API int
1125 libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
1126 size_t buffer_maxlen, char *longentry,
1127 size_t longentry_maxlen,
1128 LIBSSH2_SFTP_ATTRIBUTES * attrs)
1129 {
1130 LIBSSH2_SFTP *sftp = handle->sftp;
1131 LIBSSH2_CHANNEL *channel = sftp->channel;
1132 LIBSSH2_SESSION *session = channel->session;
1133 LIBSSH2_SFTP_ATTRIBUTES attrs_dummy;
1134 unsigned long data_len, filename_len, longentry_len, num_names;
1135 /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
1136 ssize_t packet_len = handle->handle_len + 13;
1137 unsigned char *s, *data;
1138 unsigned char read_responses[2] = { SSH_FXP_NAME, SSH_FXP_STATUS };
1139 int retcode;
1140
1141 if (sftp->readdir_state == libssh2_NB_state_idle) {
1142 if (handle->u.dir.names_left) {
1143 /*
1144 * A prior request returned more than one directory entry,
1145 * feed it back from the buffer
1146 */
1147 unsigned char *s = (unsigned char *) handle->u.dir.next_name;
1148 unsigned long real_filename_len = libssh2_ntohu32(s);
1149
1150 filename_len = real_filename_len;
1151 s += 4;
1152 if (filename_len > buffer_maxlen) {
1153 filename_len = buffer_maxlen;
1154 }
1155 memcpy(buffer, s, filename_len);
1156 s += real_filename_len;
1157
1158 /* The filename is not null terminated, make it so if possible */
1159 if (filename_len < buffer_maxlen) {
1160 buffer[filename_len] = '\0';
1161 }
1162
1163 if ((longentry == NULL) || (longentry_maxlen == 0)) {
1164 /* Skip longname */
1165 s += 4 + libssh2_ntohu32(s);
1166 } else {
1167 unsigned long real_longentry_len = libssh2_ntohu32(s);
1168
1169 longentry_len = real_longentry_len;
1170 s += 4;
1171 if (longentry_len > longentry_maxlen) {
1172 longentry_len = longentry_maxlen;
1173 }
1174 memcpy(longentry, s, longentry_len);
1175 s += real_longentry_len;
1176
1177 /* The longentry is not null terminated, make it so if possible */
1178 if (longentry_len < longentry_maxlen) {
1179 longentry[longentry_len] = '\0';
1180 }
1181 }
1182
1183 if (attrs) {
1184 memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
1185 }
1186 s += libssh2_sftp_bin2attr(attrs ? attrs : &attrs_dummy, s);
1187
1188 handle->u.dir.next_name = (char *) s;
1189 if ((--handle->u.dir.names_left) == 0) {
1190 LIBSSH2_FREE(session, handle->u.dir.names_packet);
1191 }
1192
1193 _libssh2_debug(session, LIBSSH2_DBG_SFTP,
1194 "libssh2_sftp_readdir_ex() return %d",
1195 filename_len);
1196 return filename_len;
1197 }
1198
1199 /* Request another entry(entries?) */
1200
1201 s = sftp->readdir_packet = LIBSSH2_ALLOC(session, packet_len);
1202 if (!sftp->readdir_packet) {
1203 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1204 "Unable to allocate memory for FXP_READDIR packet",
1205 0);
1206 return -1;
1207 }
1208
1209 libssh2_htonu32(s, packet_len - 4);
1210 s += 4;
1211 *(s++) = SSH_FXP_READDIR;
1212 sftp->readdir_request_id = sftp->request_id++;
1213 libssh2_htonu32(s, sftp->readdir_request_id);
1214 s += 4;
1215 libssh2_htonu32(s, handle->handle_len);
1216 s += 4;
1217 memcpy(s, handle->handle, handle->handle_len);
1218 s += handle->handle_len;
1219
1220 sftp->readdir_state = libssh2_NB_state_created;
1221 }
1222
1223 if (sftp->readdir_state == libssh2_NB_state_created) {
1224 _libssh2_debug(session, LIBSSH2_DBG_SFTP,
1225 "Reading entries from directory handle");
1226 if ((retcode =
1227 libssh2_channel_write_ex(channel, 0,
1228 (char *) sftp->readdir_packet,
1229 packet_len)) == PACKET_EAGAIN) {
1230 return PACKET_EAGAIN;
1231 } else if (packet_len != retcode) {
1232 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
1233 "Unable to send FXP_READ command", 0);
1234 LIBSSH2_FREE(session, sftp->readdir_packet);
1235 sftp->readdir_packet = NULL;
1236 sftp->readdir_state = libssh2_NB_state_idle;
1237 return -1;
1238 }
1239
1240 LIBSSH2_FREE(session, sftp->readdir_packet);
1241 sftp->readdir_packet = NULL;
1242
1243 sftp->readdir_state = libssh2_NB_state_sent;
1244 }
1245
1246 retcode =
1247 libssh2_sftp_packet_requirev(sftp, 2, read_responses,
1248 sftp->readdir_request_id, &data,
1249 &data_len);
1250 if (retcode == PACKET_EAGAIN) {
1251 return PACKET_EAGAIN;
1252 } else if (retcode) {
1253 libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
1254 "Timeout waiting for status message", 0);
1255 sftp->readdir_state = libssh2_NB_state_idle;
1256 return -1;
1257 }
1258
1259 if (data[0] == SSH_FXP_STATUS) {
1260 retcode = libssh2_ntohu32(data + 5);
1261 LIBSSH2_FREE(session, data);
1262 if (retcode == LIBSSH2_FX_EOF) {
1263 sftp->readdir_state = libssh2_NB_state_idle;
1264 return 0;
1265 } else {
1266 sftp->last_errno = retcode;
1267 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1268 "SFTP Protocol Error", 0);
1269 sftp->readdir_state = libssh2_NB_state_idle;
1270 return -1;
1271 }
1272 }
1273
1274 num_names = libssh2_ntohu32(data + 5);
1275 _libssh2_debug(session, LIBSSH2_DBG_SFTP, "%lu entries returned",
1276 num_names);
1277 if (num_names <= 0) {
1278 LIBSSH2_FREE(session, data);
1279 sftp->readdir_state = libssh2_NB_state_idle;
1280 return (num_names == 0) ? 0 : -1;
1281 }
1282
1283 if (num_names == 1) {
1284 unsigned long real_filename_len = libssh2_ntohu32(data + 9);
1285
1286 filename_len = real_filename_len;
1287 if (filename_len > buffer_maxlen) {
1288 filename_len = buffer_maxlen;
1289 }
1290 memcpy(buffer, data + 13, filename_len);
1291
1292 /* The filename is not null terminated, make it so if possible */
1293 if (filename_len < buffer_maxlen) {
1294 buffer[filename_len] = '\0';
1295 }
1296
1297 if (attrs) {
1298 memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
1299 libssh2_sftp_bin2attr(attrs, data + 13 + real_filename_len +
1300 (4 +
1301 libssh2_ntohu32(data + 13 +
1302 real_filename_len)));
1303 }
1304 LIBSSH2_FREE(session, data);
1305
1306 sftp->readdir_state = libssh2_NB_state_idle;
1307 return filename_len;
1308 }
1309
1310 handle->u.dir.names_left = num_names;
1311 handle->u.dir.names_packet = data;
1312 handle->u.dir.next_name = (char *) data + 9;
1313
1314 sftp->readdir_state = libssh2_NB_state_idle;
1315
1316 /* Be lazy, just use the name popping mechanism from the start of the function */
1317 return libssh2_sftp_readdir_ex(handle, buffer, buffer_maxlen, longentry,
1318 longentry_maxlen, attrs);
1319 }
1320
1321 /* }}} */
1322
1323 /* {{{ libssh2_sftp_write
1324 * Write data to a file handle
1325 */
1326 LIBSSH2_API ssize_t
1327 libssh2_sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
1328 size_t count)
1329 {
1330 LIBSSH2_SFTP *sftp = handle->sftp;
1331 LIBSSH2_CHANNEL *channel = sftp->channel;
1332 LIBSSH2_SESSION *session = channel->session;
1333 unsigned long data_len, retcode;
1334 /* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) + offset(8) + count(4) */
1335 ssize_t packet_len = handle->handle_len + count + 25;
1336 unsigned char *s, *data;
1337 int rc;
1338
1339 if (sftp->write_state == libssh2_NB_state_idle) {
1340 _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Writing %lu bytes",
1341 (unsigned long) count);
1342 s = sftp->write_packet = LIBSSH2_ALLOC(session, packet_len);
1343 if (!sftp->write_packet) {
1344 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1345 "Unable to allocate memory for FXP_WRITE packet", 0);
1346 return -1;
1347 }
1348
1349 libssh2_htonu32(s, packet_len - 4);
1350 s += 4;
1351 *(s++) = SSH_FXP_WRITE;
1352 sftp->write_request_id = sftp->request_id++;
1353 libssh2_htonu32(s, sftp->write_request_id);
1354 s += 4;
1355 libssh2_htonu32(s, handle->handle_len);
1356 s += 4;
1357 memcpy(s, handle->handle, handle->handle_len);
1358 s += handle->handle_len;
1359 libssh2_htonu64(s, handle->u.file.offset);
1360 s += 8;
1361 libssh2_htonu32(s, count);
1362 s += 4;
1363 memcpy(s, buffer, count);
1364 s += count;
1365
1366 sftp->write_state = libssh2_NB_state_created;
1367 }
1368
1369 if (sftp->write_state == libssh2_NB_state_created) {
1370 if ((rc =
1371 libssh2_channel_write_ex(channel, 0, (char *) sftp->write_packet,
1372 packet_len)) == PACKET_EAGAIN) {
1373 return PACKET_EAGAIN;
1374 }
1375 if (packet_len != rc) {
1376 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
1377 "Unable to send FXP_READ command", 0);
1378 LIBSSH2_FREE(session, sftp->write_packet);
1379 sftp->write_packet = NULL;
1380 sftp->write_state = libssh2_NB_state_idle;
1381 return -1;
1382 }
1383 LIBSSH2_FREE(session, sftp->write_packet);
1384 sftp->write_packet = NULL;
1385 sftp->write_state = libssh2_NB_state_sent;
1386 }
1387
1388 rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS,
1389 sftp->write_request_id, &data, &data_len);
1390 if (rc == PACKET_EAGAIN) {
1391 return PACKET_EAGAIN;
1392 } else if (rc) {
1393 libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
1394 "Timeout waiting for status message", 0);
1395 sftp->write_state = libssh2_NB_state_idle;
1396 return -1;
1397 }
1398
1399 sftp->write_state = libssh2_NB_state_idle;
1400
1401 retcode = libssh2_ntohu32(data + 5);
1402 LIBSSH2_FREE(session, data);
1403
1404 if (retcode == LIBSSH2_FX_OK) {
1405 handle->u.file.offset += count;
1406 return count;
1407 }
1408 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error",
1409 0);
1410 sftp->last_errno = retcode;
1411
1412 return -1;
1413 }
1414
1415 /* }}} */
1416
1417 /* {{{ libssh2_sftp_fstat_ex
1418 * Get or Set stat on a file
1419 */
1420 LIBSSH2_API int
1421 libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE * handle,
1422 LIBSSH2_SFTP_ATTRIBUTES * attrs, int setstat)
1423 {
1424 LIBSSH2_SFTP *sftp = handle->sftp;
1425 LIBSSH2_CHANNEL *channel = sftp->channel;
1426 LIBSSH2_SESSION *session = channel->session;
1427 unsigned long data_len;
1428 /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
1429 ssize_t packet_len =
1430 handle->handle_len + 13 + (setstat ? libssh2_sftp_attrsize(attrs) : 0);
1431 unsigned char *s, *data;
1432 static const unsigned char fstat_responses[2] =
1433 { SSH_FXP_ATTRS, SSH_FXP_STATUS };
1434 int rc;
1435
1436 if (sftp->fstat_state == libssh2_NB_state_idle) {
1437 _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Issuing %s command",
1438 setstat ? "set-stat" : "stat");
1439 s = sftp->fstat_packet = LIBSSH2_ALLOC(session, packet_len);
1440 if (!sftp->fstat_packet) {
1441 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1442 "Unable to allocate memory for FSTAT/FSETSTAT packet",
1443 0);
1444 return -1;
1445 }
1446
1447 libssh2_htonu32(s, packet_len - 4);
1448 s += 4;
1449 *(s++) = setstat ? SSH_FXP_FSETSTAT : SSH_FXP_FSTAT;
1450 sftp->fstat_request_id = sftp->request_id++;
1451 libssh2_htonu32(s, sftp->fstat_request_id);
1452 s += 4;
1453 libssh2_htonu32(s, handle->handle_len);
1454 s += 4;
1455 memcpy(s, handle->handle, handle->handle_len);
1456 s += handle->handle_len;
1457 if (setstat) {
1458 s += libssh2_sftp_attr2bin(s, attrs);
1459 }
1460
1461 sftp->fstat_state = libssh2_NB_state_created;
1462 }
1463
1464 if (sftp->fstat_state == libssh2_NB_state_created) {
1465 rc = libssh2_channel_write_ex(channel, 0, (char *) sftp->fstat_packet,
1466 packet_len);
1467 if (rc == PACKET_EAGAIN) {
1468 return PACKET_EAGAIN;
1469 } else if (packet_len != rc) {
1470 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
1471 setstat ? (char *) "Unable to send FXP_FSETSTAT"
1472 : (char *) "Unable to send FXP_FSTAT command", 0);
1473 LIBSSH2_FREE(session, sftp->fstat_packet);
1474 sftp->fstat_packet = NULL;
1475 sftp->fstat_state = libssh2_NB_state_idle;
1476 return -1;
1477 }
1478 LIBSSH2_FREE(session, sftp->fstat_packet);
1479 sftp->fstat_packet = NULL;
1480
1481 sftp->fstat_state = libssh2_NB_state_sent;
1482 }
1483
1484 rc = libssh2_sftp_packet_requirev(sftp, 2, fstat_responses,
1485 sftp->fstat_request_id, &data,
1486 &data_len);
1487 if (rc == PACKET_EAGAIN) {
1488 return PACKET_EAGAIN;
1489 } else if (rc) {
1490 libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
1491 "Timeout waiting for status message", 0);
1492 sftp->fstat_state = libssh2_NB_state_idle;
1493 return -1;
1494 }
1495
1496 sftp->fstat_state = libssh2_NB_state_idle;
1497
1498 if (data[0] == SSH_FXP_STATUS) {
1499 int retcode;
1500
1501 retcode = libssh2_ntohu32(data + 5);
1502 LIBSSH2_FREE(session, data);
1503 if (retcode == LIBSSH2_FX_OK) {
1504 return 0;
1505 } else {
1506 sftp->last_errno = retcode;
1507 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1508 "SFTP Protocol Error", 0);
1509 return -1;
1510 }
1511 }
1512
1513 libssh2_sftp_bin2attr(attrs, data + 5);
1514
1515 return 0;
1516 }
1517
1518 /* }}} */
1519
1520 /* {{{ libssh2_sftp_seek
1521 * Set the read/write pointer to an arbitrary position within the file
1522 */
1523 LIBSSH2_API void
1524 libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE * handle, size_t offset)
1525 {
1526 handle->u.file.offset = offset;
1527 }
1528
1529 /* }}} */
1530
1531 /* {{{ libssh2_sftp_tell
1532 * Return the current read/write pointer's offset
1533 */
1534 LIBSSH2_API size_t
1535 libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE * handle)
1536 {
1537 return handle->u.file.offset;
1538 }
1539
1540 /* }}} */
1541
1542
1543 /* {{{ libssh2_sftp_close_handle
1544 * Close a file or directory handle
1545 * Also frees handle resource and unlinks it from the SFTP structure
1546 */
1547 LIBSSH2_API int
1548 libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE * handle)
1549 {
1550 LIBSSH2_SFTP *sftp = handle->sftp;
1551 LIBSSH2_CHANNEL *channel = sftp->channel;
1552 LIBSSH2_SESSION *session = channel->session;
1553 unsigned long data_len, retcode;
1554 /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
1555 ssize_t packet_len = handle->handle_len + 13;
1556 unsigned char *s, *data;
1557 int rc;
1558
1559 if (handle->close_state == libssh2_NB_state_idle) {
1560 _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Closing handle");
1561 s = handle->close_packet = LIBSSH2_ALLOC(session, packet_len);
1562 if (!handle->close_packet) {
1563 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1564 "Unable to allocate memory for FXP_CLOSE packet", 0);
1565 return -1;
1566 }
1567
1568 libssh2_htonu32(s, packet_len - 4);
1569 s += 4;
1570 *(s++) = SSH_FXP_CLOSE;
1571 handle->close_request_id = sftp->request_id++;
1572 libssh2_htonu32(s, handle->close_request_id);
1573 s += 4;
1574 libssh2_htonu32(s, handle->handle_len);
1575 s += 4;
1576 memcpy(s, handle->handle, handle->handle_len);
1577 s += handle->handle_len;
1578
1579 handle->close_state = libssh2_NB_state_created;
1580 }
1581
1582 if (handle->close_state == libssh2_NB_state_created) {
1583 rc = libssh2_channel_write_ex(channel, 0,
1584 (char *) handle->close_packet,
1585 packet_len);
1586 if (rc == PACKET_EAGAIN) {
1587 return PACKET_EAGAIN;
1588 } else if (packet_len != rc) {
1589 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
1590 "Unable to send FXP_CLOSE command", 0);
1591 LIBSSH2_FREE(session, handle->close_packet);
1592 handle->close_packet = NULL;
1593 handle->close_state = libssh2_NB_state_idle;
1594 return -1;
1595 }
1596 LIBSSH2_FREE(session, handle->close_packet);
1597 handle->close_packet = NULL;
1598
1599 handle->close_state = libssh2_NB_state_sent;
1600 }
1601
1602 if (handle->close_state == libssh2_NB_state_sent) {
1603 rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS,
1604 handle->close_request_id, &data,
1605 &data_len);
1606 if (rc == PACKET_EAGAIN) {
1607 return PACKET_EAGAIN;
1608 } else if (rc) {
1609 libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
1610 "Timeout waiting for status message", 0);
1611 handle->close_state = libssh2_NB_state_idle;
1612 return -1;
1613 }
1614
1615 handle->close_state = libssh2_NB_state_sent1;
1616 }
1617
1618 retcode = libssh2_ntohu32(data + 5);
1619 LIBSSH2_FREE(session, data);
1620
1621 if (retcode != LIBSSH2_FX_OK) {
1622 sftp->last_errno = retcode;
1623 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1624 "SFTP Protocol Error", 0);
1625 handle->close_state = libssh2_NB_state_idle;
1626 return -1;
1627 }
1628
1629 if (handle == sftp->handles) {
1630 sftp->handles = handle->next;
1631 }
1632 if (handle->next) {
1633 handle->next->prev = NULL;
1634 }
1635
1636 if ((handle->handle_type == LIBSSH2_SFTP_HANDLE_DIR)
1637 && handle->u.dir.names_left) {
1638 LIBSSH2_FREE(session, handle->u.dir.names_packet);
1639 }
1640
1641 handle->close_state = libssh2_NB_state_idle;
1642
1643 LIBSSH2_FREE(session, handle->handle);
1644 LIBSSH2_FREE(session, handle);
1645
1646 return 0;
1647 }
1648
1649 /* }}} */
1650
1651 /* **********************
1652 * SFTP Miscellaneous *
1653 ********************** */
1654
1655 /* {{{ libssh2_sftp_unlink_ex
1656 * Delete a file from the remote server
1657 */
1658 /* libssh2_sftp_unlink_ex - NB-UNSAFE?? */
1659 LIBSSH2_API int
1660 libssh2_sftp_unlink_ex(LIBSSH2_SFTP * sftp, const char *filename,
1661 unsigned int filename_len)
1662 {
1663 LIBSSH2_CHANNEL *channel = sftp->channel;
1664 LIBSSH2_SESSION *session = channel->session;
1665 unsigned long data_len, retcode;
1666 /* 13 = packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) */
1667 ssize_t packet_len = filename_len + 13;
1668 unsigned char *s, *data;
1669 int rc;
1670
1671 if (sftp->unlink_state == libssh2_NB_state_idle) {
1672 _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Unlinking %s", filename);
1673 s = sftp->unlink_packet = LIBSSH2_ALLOC(session, packet_len);
1674 if (!sftp->unlink_packet) {
1675 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1676 "Unable to allocate memory for FXP_REMOVE packet",
1677 0);
1678 return -1;
1679 }
1680
1681 libssh2_htonu32(s, packet_len - 4);
1682 s += 4;
1683 *(s++) = SSH_FXP_REMOVE;
1684 sftp->unlink_request_id = sftp->request_id++;
1685 libssh2_htonu32(s, sftp->unlink_request_id);
1686 s += 4;
1687 libssh2_htonu32(s, filename_len);
1688 s += 4;
1689 memcpy(s, filename, filename_len);
1690 s += filename_len;
1691
1692 sftp->unlink_state = libssh2_NB_state_created;
1693 }
1694
1695 if (sftp->unlink_state == libssh2_NB_state_created) {
1696 rc = libssh2_channel_write_ex(channel, 0, (char *) sftp->unlink_packet,
1697 packet_len);
1698 if (rc == PACKET_EAGAIN) {
1699 return PACKET_EAGAIN;
1700 } else if (packet_len != rc) {
1701 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
1702 "Unable to send FXP_REMOVE command", 0);
1703 LIBSSH2_FREE(session, sftp->unlink_packet);
1704 sftp->unlink_packet = NULL;
1705 sftp->unlink_state = libssh2_NB_state_idle;
1706 return -1;
1707 }
1708 LIBSSH2_FREE(session, sftp->unlink_packet);
1709 sftp->unlink_packet = NULL;
1710
1711 sftp->unlink_state = libssh2_NB_state_sent;
1712 }
1713
1714 rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS,
1715 sftp->unlink_request_id, &data,
1716 &data_len);
1717 if (rc == PACKET_EAGAIN) {
1718 return PACKET_EAGAIN;
1719 } else if (rc) {
1720 libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
1721 "Timeout waiting for status message", 0);
1722 sftp->unlink_state = libssh2_NB_state_idle;
1723 return -1;
1724 }
1725
1726 sftp->unlink_state = libssh2_NB_state_idle;
1727
1728 retcode = libssh2_ntohu32(data + 5);
1729 LIBSSH2_FREE(session, data);
1730
1731 if (retcode == LIBSSH2_FX_OK) {
1732 return 0;
1733 } else {
1734 sftp->last_errno = retcode;
1735 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1736 "SFTP Protocol Error", 0);
1737 return -1;
1738 }
1739 }
1740
1741 /* }}} */
1742
1743 /* {{{ libssh2_sftp_rename_ex
1744 * Rename a file on the remote server
1745 */
1746 LIBSSH2_API int
1747 libssh2_sftp_rename_ex(LIBSSH2_SFTP * sftp, const char *source_filename,
1748 unsigned int source_filename_len,
1749 const char *dest_filename,
1750 unsigned int dest_filename_len, long flags)
1751 {
1752 LIBSSH2_CHANNEL *channel = sftp->channel;
1753 LIBSSH2_SESSION *session = channel->session;
1754 unsigned long data_len, retcode;
1755 ssize_t packet_len =
1756 source_filename_len + dest_filename_len + 17 + (sftp->version >=
1757 5 ? 4 : 0);
1758 /* packet_len(4) + packet_type(1) + request_id(4) +
1759 source_filename_len(4) + dest_filename_len(4) + flags(4){SFTP5+) */
1760 unsigned char *data;
1761 int rc;
1762
1763 if (sftp->version < 2) {
1764 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1765 "Server does not support RENAME", 0);
1766 return -1;
1767 }
1768
1769 if (sftp->rename_state == libssh2_NB_state_idle) {
1770 _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Renaming %s to %s",
1771 source_filename, dest_filename);
1772 sftp->rename_s = sftp->rename_packet =
1773 LIBSSH2_ALLOC(session, packet_len);
1774 if (!sftp->rename_packet) {
1775 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1776 "Unable to allocate memory for FXP_RENAME packet",
1777 0);
1778 return -1;
1779 }
1780
1781 libssh2_htonu32(sftp->rename_s, packet_len - 4);
1782 sftp->rename_s += 4;
1783 *(sftp->rename_s++) = SSH_FXP_RENAME;
1784 sftp->rename_request_id = sftp->request_id++;
1785 libssh2_htonu32(sftp->rename_s, sftp->rename_request_id);
1786 sftp->rename_s += 4;
1787 libssh2_htonu32(sftp->rename_s, source_filename_len);
1788 sftp->rename_s += 4;
1789 memcpy(sftp->rename_s, source_filename, source_filename_len);
1790 sftp->rename_s += source_filename_len;
1791 libssh2_htonu32(sftp->rename_s, dest_filename_len);
1792 sftp->rename_s += 4;
1793 memcpy(sftp->rename_s, dest_filename, dest_filename_len);
1794 sftp->rename_s += dest_filename_len;
1795
1796 if (sftp->version >= 5) {
1797 libssh2_htonu32(sftp->rename_s, flags);
1798 sftp->rename_s += 4;
1799 }
1800
1801 sftp->rename_state = libssh2_NB_state_created;
1802 }
1803
1804 if (sftp->rename_state == libssh2_NB_state_created) {
1805 rc = libssh2_channel_write_ex(channel, 0, (char *) sftp->rename_packet,
1806 sftp->rename_s - sftp->rename_packet);
1807 if (rc == PACKET_EAGAIN) {
1808 return PACKET_EAGAIN;
1809 } else if (packet_len != rc) {
1810 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
1811 "Unable to send FXP_RENAME command", 0);
1812 LIBSSH2_FREE(session, sftp->rename_packet);
1813 sftp->rename_packet = NULL;
1814 sftp->rename_state = libssh2_NB_state_idle;
1815 return -1;
1816 }
1817 LIBSSH2_FREE(session, sftp->rename_packet);
1818 sftp->rename_packet = NULL;
1819
1820 sftp->rename_state = libssh2_NB_state_sent;
1821 }
1822
1823 rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS,
1824 sftp->rename_request_id, &data,
1825 &data_len);
1826 if (rc == PACKET_EAGAIN) {
1827 return PACKET_EAGAIN;
1828 } else if (rc) {
1829 libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
1830 "Timeout waiting for status message", 0);
1831 sftp->rename_state = libssh2_NB_state_idle;
1832 return -1;
1833 }
1834
1835 sftp->rename_state = libssh2_NB_state_idle;
1836
1837 retcode = libssh2_ntohu32(data + 5);
1838 LIBSSH2_FREE(session, data);
1839
1840 switch (retcode) {
1841 case LIBSSH2_FX_OK:
1842 retcode = 0;
1843 break;
1844
1845 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
1846 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1847 "File already exists and SSH_FXP_RENAME_OVERWRITE not specified",
1848 0);
1849 sftp->last_errno = retcode;
1850 retcode = -1;
1851 break;
1852
1853 case LIBSSH2_FX_OP_UNSUPPORTED:
1854 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1855 "Operation Not Supported", 0);
1856 sftp->last_errno = retcode;
1857 retcode = -1;
1858 break;
1859
1860 default:
1861 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1862 "SFTP Protocol Error", 0);
1863 sftp->last_errno = retcode;
1864 retcode = -1;
1865 }
1866
1867 return retcode;
1868 }
1869
1870 /* }}} */
1871
1872 /* {{{ libssh2_sftp_mkdir_ex
1873 * Create an SFTP directory
1874 */
1875 LIBSSH2_API int
1876 libssh2_sftp_mkdir_ex(LIBSSH2_SFTP * sftp, const char *path,
1877 unsigned int path_len, long mode)
1878 {
1879 LIBSSH2_CHANNEL *channel = sftp->channel;
1880 LIBSSH2_SESSION *session = channel->session;
1881 LIBSSH2_SFTP_ATTRIBUTES attrs = {
1882 LIBSSH2_SFTP_ATTR_PERMISSIONS, 0, 0, 0, 0, 0, 0
1883 };
1884 unsigned long data_len, retcode, request_id;
1885 /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
1886 ssize_t packet_len = path_len + 13 + libssh2_sftp_attrsize(&attrs);
1887 unsigned char *packet, *s, *data;
1888 int rc;
1889
1890 if (sftp->mkdir_state == libssh2_NB_state_idle) {
1891 _libssh2_debug(session, LIBSSH2_DBG_SFTP,
1892 "Creating directory %s with mode 0%lo", path, mode);
1893 s = packet = LIBSSH2_ALLOC(session, packet_len);
1894 if (!packet) {
1895 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1896 "Unable to allocate memory for FXP_MKDIR packet", 0);
1897 return -1;
1898 }
1899 /* Filetype in SFTP 3 and earlier */
1900 attrs.permissions = mode | LIBSSH2_SFTP_ATTR_PFILETYPE_DIR;
1901
1902 libssh2_htonu32(s, packet_len - 4);
1903 s += 4;
1904 *(s++) = SSH_FXP_MKDIR;
1905 request_id = sftp->request_id++;
1906 libssh2_htonu32(s, request_id);
1907 s += 4;
1908 libssh2_htonu32(s, path_len);
1909 s += 4;
1910 memcpy(s, path, path_len);
1911 s += path_len;
1912 s += libssh2_sftp_attr2bin(s, &attrs);
1913
1914 sftp->mkdir_state = libssh2_NB_state_created;
1915 } else {
1916 packet = sftp->mkdir_packet;
1917 request_id = sftp->mkdir_request_id;
1918 }
1919
1920 if (sftp->mkdir_state == libssh2_NB_state_created) {
1921 rc = libssh2_channel_write_ex(channel, 0, (char *) packet, packet_len);
1922 if (rc == PACKET_EAGAIN) {
1923 sftp->mkdir_packet = packet;
1924 sftp->mkdir_request_id = request_id;
1925 return PACKET_EAGAIN;
1926 }
1927 if (packet_len != rc) {
1928 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
1929 "Unable to send FXP_READ command", 0);
1930 LIBSSH2_FREE(session, packet);
1931 sftp->mkdir_state = libssh2_NB_state_idle;
1932 return -1;
1933 }
1934 LIBSSH2_FREE(session, packet);
1935 sftp->mkdir_state = libssh2_NB_state_sent;
1936 sftp->mkdir_packet = NULL;
1937 }
1938
1939 rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS, request_id, &data,
1940 &data_len);
1941 if (rc == PACKET_EAGAIN) {
1942 return PACKET_EAGAIN;
1943 } else if (rc) {
1944 libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
1945 "Timeout waiting for status message", 0);
1946 sftp->mkdir_state = libssh2_NB_state_idle;
1947 return -1;
1948 }
1949
1950 sftp->mkdir_state = libssh2_NB_state_idle;
1951
1952 retcode = libssh2_ntohu32(data + 5);
1953 LIBSSH2_FREE(session, data);
1954
1955 if (retcode == LIBSSH2_FX_OK) {
1956 return 0;
1957 } else {
1958 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1959 "SFTP Protocol Error", 0);
1960 sftp->last_errno = retcode;
1961 return -1;
1962 }
1963 }
1964
1965 /* }}} */
1966
1967 /* {{{ libssh2_sftp_rmdir_ex
1968 * Remove a directory
1969 */
1970 /* libssh2_sftp_rmdir_ex - NB-UNSAFE?? */
1971 LIBSSH2_API int
1972 libssh2_sftp_rmdir_ex(LIBSSH2_SFTP * sftp, const char *path,
1973 unsigned int path_len)
1974 {
1975 LIBSSH2_CHANNEL *channel = sftp->channel;
1976 LIBSSH2_SESSION *session = channel->session;
1977 unsigned long data_len, retcode;
1978 /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
1979 ssize_t packet_len = path_len + 13;
1980 unsigned char *s, *data;
1981 int rc;
1982
1983 if (sftp->rmdir_state == libssh2_NB_state_idle) {
1984 _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Removing directory: %s",
1985 path);
1986 s = sftp->rmdir_packet = LIBSSH2_ALLOC(session, packet_len);
1987 if (!sftp->rmdir_packet) {
1988 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1989 "Unable to allocate memory for FXP_MKDIR packet", 0);
1990 return -1;
1991 }
1992
1993 libssh2_htonu32(s, packet_len - 4);
1994 s += 4;
1995 *(s++) = SSH_FXP_RMDIR;
1996 sftp->rmdir_request_id = sftp->request_id++;
1997 libssh2_htonu32(s, sftp->rmdir_request_id);
1998 s += 4;
1999 libssh2_htonu32(s, path_len);
2000 s += 4;
2001 memcpy(s, path, path_len);
2002 s += path_len;
2003
2004 sftp->rmdir_state = libssh2_NB_state_created;
2005 }
2006
2007 if (sftp->rmdir_state == libssh2_NB_state_created) {
2008 rc = libssh2_channel_write_ex(channel, 0, (char *) sftp->rmdir_packet,
2009 packet_len);
2010 if (rc == PACKET_EAGAIN) {
2011 return PACKET_EAGAIN;
2012 } else if (packet_len != rc) {
2013 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2014 "Unable to send FXP_MKDIR command", 0);
2015 LIBSSH2_FREE(session, sftp->rmdir_packet);
2016 sftp->rmdir_packet = NULL;
2017 sftp->rmdir_state = libssh2_NB_state_idle;
2018 return -1;
2019 }
2020 LIBSSH2_FREE(session, sftp->rmdir_packet);
2021 sftp->rmdir_packet = NULL;
2022
2023 sftp->rmdir_state = libssh2_NB_state_sent;
2024 }
2025
2026 rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS,
2027 sftp->rmdir_request_id, &data, &data_len);
2028 if (rc == PACKET_EAGAIN) {
2029 return PACKET_EAGAIN;
2030 } else if (rc) {
2031 libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
2032 "Timeout waiting for status message", 0);
2033 sftp->rmdir_state = libssh2_NB_state_idle;
2034 return -1;
2035 }
2036
2037 sftp->rmdir_state = libssh2_NB_state_idle;
2038
2039 retcode = libssh2_ntohu32(data + 5);
2040 LIBSSH2_FREE(session, data);
2041
2042 if (retcode == LIBSSH2_FX_OK) {
2043 return 0;
2044 } else {
2045 sftp->last_errno = retcode;
2046 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2047 "SFTP Protocol Error", 0);
2048 return -1;
2049 }
2050 }
2051
2052 /* }}} */
2053
2054 /* {{{ libssh2_sftp_stat_ex
2055 * Stat a file or symbolic link
2056 */
2057 /* libssh2_sftp_stat_ex - NB-UNSAFE?? */
2058 LIBSSH2_API int
2059 libssh2_sftp_stat_ex(LIBSSH2_SFTP * sftp, const char *path,
2060 unsigned int path_len, int stat_type,
2061 LIBSSH2_SFTP_ATTRIBUTES * attrs)
2062 {
2063 LIBSSH2_CHANNEL *channel = sftp->channel;
2064 LIBSSH2_SESSION *session = channel->session;
2065 unsigned long data_len;
2066 /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
2067 ssize_t packet_len =
2068 path_len + 13 +
2069 ((stat_type ==
2070 LIBSSH2_SFTP_SETSTAT) ? libssh2_sftp_attrsize(attrs) : 0);
2071 unsigned char *s, *data;
2072 static const unsigned char stat_responses[2] =
2073 { SSH_FXP_ATTRS, SSH_FXP_STATUS };
2074 int rc;
2075
2076 if (sftp->stat_state == libssh2_NB_state_idle) {
2077 _libssh2_debug(session, LIBSSH2_DBG_SFTP, "%s %s",
2078 (stat_type == LIBSSH2_SFTP_SETSTAT) ? "Set-statting" :
2079 (stat_type ==
2080 LIBSSH2_SFTP_LSTAT ? "LStatting" : "Statting"), path);
2081 s = sftp->stat_packet = LIBSSH2_ALLOC(session, packet_len);
2082 if (!sftp->stat_packet) {
2083 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2084 "Unable to allocate memory for FXP_MKDIR packet", 0);
2085 return -1;
2086 }
2087
2088 libssh2_htonu32(s, packet_len - 4);
2089 s += 4;
2090 switch (stat_type) {
2091 case LIBSSH2_SFTP_SETSTAT:
2092 *(s++) = SSH_FXP_SETSTAT;
2093 break;
2094
2095 case LIBSSH2_SFTP_LSTAT:
2096 *(s++) = SSH_FXP_LSTAT;
2097 break;
2098
2099 case LIBSSH2_SFTP_STAT:
2100 default:
2101 *(s++) = SSH_FXP_STAT;
2102 }
2103 sftp->stat_request_id = sftp->request_id++;
2104 libssh2_htonu32(s, sftp->stat_request_id);
2105 s += 4;
2106 libssh2_htonu32(s, path_len);
2107 s += 4;
2108 memcpy(s, path, path_len);
2109 s += path_len;
2110 if (stat_type == LIBSSH2_SFTP_SETSTAT) {
2111 s += libssh2_sftp_attr2bin(s, attrs);
2112 }
2113
2114 sftp->stat_state = libssh2_NB_state_created;
2115 }
2116
2117 if (sftp->stat_state == libssh2_NB_state_created) {
2118 rc = libssh2_channel_write_ex(channel, 0, (char *) sftp->stat_packet,
2119 packet_len);
2120 if (rc == PACKET_EAGAIN) {
2121 return PACKET_EAGAIN;
2122 } else if (packet_len != rc) {
2123 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2124 "Unable to send STAT/LSTAT/SETSTAT command", 0);
2125 LIBSSH2_FREE(session, sftp->stat_packet);
2126 sftp->stat_packet = NULL;
2127 sftp->stat_state = libssh2_NB_state_idle;
2128 return -1;
2129 }
2130 LIBSSH2_FREE(session, sftp->stat_packet);
2131 sftp->stat_packet = NULL;
2132
2133 sftp->stat_state = libssh2_NB_state_sent;
2134 }
2135
2136 rc = libssh2_sftp_packet_requirev(sftp, 2, stat_responses,
2137 sftp->stat_request_id, &data, &data_len);
2138 if (rc == PACKET_EAGAIN) {
2139 return PACKET_EAGAIN;
2140 } else if (rc) {
2141 libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
2142 "Timeout waiting for status message", 0);
2143 sftp->stat_state = libssh2_NB_state_idle;
2144 return -1;
2145 }
2146
2147 sftp->stat_state = libssh2_NB_state_idle;
2148
2149 if (data[0] == SSH_FXP_STATUS) {
2150 int retcode;
2151
2152 retcode = libssh2_ntohu32(data + 5);
2153 LIBSSH2_FREE(session, data);
2154 if (retcode == LIBSSH2_FX_OK) {
2155 return 0;
2156 } else {
2157 sftp->last_errno = retcode;
2158 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2159 "SFTP Protocol Error", 0);
2160 return -1;
2161 }
2162 }
2163
2164 memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
2165 libssh2_sftp_bin2attr(attrs, data + 5);
2166 LIBSSH2_FREE(session, data);
2167
2168 return 0;
2169 }
2170
2171 /* }}} */
2172
2173 /* {{{ libssh2_sftp_symlink_ex
2174 * Read or set a symlink
2175 */
2176 LIBSSH2_API int
2177 libssh2_sftp_symlink_ex(LIBSSH2_SFTP * sftp, const char *path,
2178 unsigned int path_len, char *target,
2179 unsigned int target_len, int link_type)
2180 {
2181 LIBSSH2_CHANNEL *channel = sftp->channel;
2182 LIBSSH2_SESSION *session = channel->session;
2183 unsigned long data_len, link_len;
2184 /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
2185 ssize_t packet_len =
2186 path_len + 13 +
2187 ((link_type == LIBSSH2_SFTP_SYMLINK) ? (4 + target_len) : 0);
2188 unsigned char *s, *data;
2189 static const unsigned char link_responses[2] =
2190 { SSH_FXP_NAME, SSH_FXP_STATUS };
2191 int rc;
2192
2193 if ((sftp->version < 3) && (link_type != LIBSSH2_SFTP_REALPATH)) {
2194 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2195 "Server does not support SYMLINK or READLINK", 0);
2196 return -1;
2197 }
2198
2199 if (sftp->symlink_state == libssh2_NB_state_idle) {
2200 s = sftp->symlink_packet = LIBSSH2_ALLOC(session, packet_len);
2201 if (!sftp->symlink_packet) {
2202 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2203 "Unable to allocate memory for SYMLINK/READLINK/REALPATH packet",
2204 0);
2205 return -1;
2206 }
2207
2208 _libssh2_debug(session, LIBSSH2_DBG_SFTP, "%s %s on %s",
2209 (link_type ==
2210 LIBSSH2_SFTP_SYMLINK) ? "Creating" : "Reading",
2211 (link_type ==
2212 LIBSSH2_SFTP_REALPATH) ? "realpath" : "symlink", path);
2213
2214 libssh2_htonu32(s, packet_len - 4);
2215 s += 4;
2216 switch (link_type) {
2217 case LIBSSH2_SFTP_REALPATH:
2218 *(s++) = SSH_FXP_REALPATH;
2219 break;
2220
2221 case LIBSSH2_SFTP_SYMLINK:
2222 *(s++) = SSH_FXP_SYMLINK;
2223 break;
2224
2225 case LIBSSH2_SFTP_READLINK:
2226 default:
2227 *(s++) = SSH_FXP_READLINK;
2228 }
2229 sftp->symlink_request_id = sftp->request_id++;
2230 libssh2_htonu32(s, sftp->symlink_request_id);
2231 s += 4;
2232 libssh2_htonu32(s, path_len);
2233 s += 4;
2234 memcpy(s, path, path_len);
2235 s += path_len;
2236 if (link_type == LIBSSH2_SFTP_SYMLINK) {
2237 libssh2_htonu32(s, target_len);
2238 s += 4;
2239 memcpy(s, target, target_len);
2240 s += target_len;
2241 }
2242
2243 sftp->symlink_state = libssh2_NB_state_created;
2244 }
2245
2246 if (sftp->symlink_state == libssh2_NB_state_created) {
2247 rc = libssh2_channel_write_ex(channel, 0,
2248 (char *) sftp->symlink_packet,
2249 packet_len);
2250 if (rc == PACKET_EAGAIN) {
2251 return PACKET_EAGAIN;
2252 } else if (packet_len != rc) {
2253 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2254 "Unable to send SYMLINK/READLINK command", 0);
2255 LIBSSH2_FREE(session, sftp->symlink_packet);
2256 sftp->symlink_packet = NULL;
2257 sftp->symlink_state = libssh2_NB_state_idle;
2258 return -1;
2259 }
2260 LIBSSH2_FREE(session, sftp->symlink_packet);
2261 sftp->symlink_packet = NULL;
2262
2263 sftp->symlink_state = libssh2_NB_state_sent;
2264 }
2265
2266 rc = libssh2_sftp_packet_requirev(sftp, 2, link_responses,
2267 sftp->symlink_request_id, &data,
2268 &data_len);
2269 if (rc == PACKET_EAGAIN) {
2270 return PACKET_EAGAIN;
2271 } else if (rc) {
2272 libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
2273 "Timeout waiting for status message", 0);
2274 sftp->symlink_state = libssh2_NB_state_idle;
2275 return -1;
2276 }
2277
2278 sftp->symlink_state = libssh2_NB_state_idle;
2279
2280 if (data[0] == SSH_FXP_STATUS) {
2281 int retcode;
2282
2283 retcode = libssh2_ntohu32(data + 5);
2284 LIBSSH2_FREE(session, data);
2285 if (retcode == LIBSSH2_FX_OK) {
2286 return 0;
2287 } else {
2288 sftp->last_errno = retcode;
2289 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2290 "SFTP Protocol Error", 0);
2291 return -1;
2292 }
2293 }
2294
2295 if (libssh2_ntohu32(data + 5) < 1) {
2296 libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2297 "Invalid READLINK/REALPATH response, no name entries",
2298 0);
2299 LIBSSH2_FREE(session, data);
2300 return -1;
2301 }
2302
2303 link_len = libssh2_ntohu32(data + 9);
2304 if (link_len >= target_len) {
2305 link_len = target_len - 1;
2306 }
2307 memcpy(target, data + 13, link_len);
2308 target[link_len] = 0;
2309 LIBSSH2_FREE(session, data);
2310
2311 return link_len;
2312 }
2313
2314 /* }}} */
2315
2316 /* {{{ libssh2_sftp_last_error
2317 * Returns the last error code reported by SFTP
2318 */
2319 LIBSSH2_API unsigned long
2320 libssh2_sftp_last_error(LIBSSH2_SFTP * sftp)
2321 {
2322 return sftp->last_errno;
2323 }
2324
2325 /* }}} */