1 /* Copyright (c) 2004-2008, Sara Golemon <sarag@libssh2.org>
2 * Copyright (c) 2007 Eli Fant <elifantu@mail.ru>
3 * Copyright (c) 2009-2019 by Daniel Stenberg
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms,
7 * with or without modification, are permitted provided
8 * that the following conditions are met:
9 *
10 * Redistributions of source code must retain the above
11 * copyright notice, this list of conditions and the
12 * following disclaimer.
13 *
14 * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials
17 * provided with the distribution.
18 *
19 * Neither the name of the copyright holder nor the names
20 * of any other contributors may be used to endorse or
21 * promote products derived from this software without
22 * specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
25 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
37 * OF SUCH DAMAGE.
38 */
39
40 #include <assert.h>
41
42 #include "libssh2_priv.h"
43 #include "libssh2_sftp.h"
44 #include "channel.h"
45 #include "session.h"
46 #include "sftp.h"
47
48 /* Note: Version 6 was documented at the time of writing
49 * However it was marked as "DO NOT IMPLEMENT" due to pending changes
50 *
51 * This release of libssh2 implements Version 5 with automatic downgrade
52 * based on server's declaration
53 */
54
55 /* SFTP packet types */
56 #define SSH_FXP_INIT 1
57 #define SSH_FXP_VERSION 2
58 #define SSH_FXP_OPEN 3
59 #define SSH_FXP_CLOSE 4
60 #define SSH_FXP_READ 5
61 #define SSH_FXP_WRITE 6
62 #define SSH_FXP_LSTAT 7
63 #define SSH_FXP_FSTAT 8
64 #define SSH_FXP_SETSTAT 9
65 #define SSH_FXP_FSETSTAT 10
66 #define SSH_FXP_OPENDIR 11
67 #define SSH_FXP_READDIR 12
68 #define SSH_FXP_REMOVE 13
69 #define SSH_FXP_MKDIR 14
70 #define SSH_FXP_RMDIR 15
71 #define SSH_FXP_REALPATH 16
72 #define SSH_FXP_STAT 17
73 #define SSH_FXP_RENAME 18
74 #define SSH_FXP_READLINK 19
75 #define SSH_FXP_SYMLINK 20
76 #define SSH_FXP_STATUS 101
77 #define SSH_FXP_HANDLE 102
78 #define SSH_FXP_DATA 103
79 #define SSH_FXP_NAME 104
80 #define SSH_FXP_ATTRS 105
81 #define SSH_FXP_EXTENDED 200
82 #define SSH_FXP_EXTENDED_REPLY 201
83
84 /* S_IFREG */
85 #define LIBSSH2_SFTP_ATTR_PFILETYPE_FILE 0100000
86 /* S_IFDIR */
87 #define LIBSSH2_SFTP_ATTR_PFILETYPE_DIR 0040000
88
89 #define SSH_FXE_STATVFS_ST_RDONLY 0x00000001
90 #define SSH_FXE_STATVFS_ST_NOSUID 0x00000002
91
92 /* This is the maximum packet length to accept, as larger than this indicate
93 some kind of server problem. */
94 #define LIBSSH2_SFTP_PACKET_MAXLEN (256 * 1024)
95
96 static int sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type,
97 uint32_t request_id, unsigned char **data,
98 size_t *data_len);
99 static void sftp_packet_flush(LIBSSH2_SFTP *sftp);
100
101 /* sftp_attrsize
102 * Size that attr with this flagset will occupy when turned into a bin struct
103 */
sftp_attrsize(unsigned long flags)104 static int sftp_attrsize(unsigned long flags)
105 {
106 return (4 + /* flags(4) */
107 ((flags & LIBSSH2_SFTP_ATTR_SIZE) ? 8 : 0) +
108 ((flags & LIBSSH2_SFTP_ATTR_UIDGID) ? 8 : 0) +
109 ((flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) ? 4 : 0) +
110 ((flags & LIBSSH2_SFTP_ATTR_ACMODTIME) ? 8 : 0));
111 /* atime + mtime as u32 */
112 }
113
114 /* _libssh2_store_u64
115 */
_libssh2_store_u64(unsigned char ** ptr,libssh2_uint64_t value)116 static void _libssh2_store_u64(unsigned char **ptr, libssh2_uint64_t value)
117 {
118 uint32_t msl = (uint32_t)(value >> 32);
119 unsigned char *buf = *ptr;
120
121 buf[0] = (unsigned char)((msl >> 24) & 0xFF);
122 buf[1] = (unsigned char)((msl >> 16) & 0xFF);
123 buf[2] = (unsigned char)((msl >> 8) & 0xFF);
124 buf[3] = (unsigned char)( msl & 0xFF);
125
126 buf[4] = (unsigned char)((value >> 24) & 0xFF);
127 buf[5] = (unsigned char)((value >> 16) & 0xFF);
128 buf[6] = (unsigned char)((value >> 8) & 0xFF);
129 buf[7] = (unsigned char)( value & 0xFF);
130
131 *ptr += 8;
132 }
133
134 /*
135 * Search list of zombied FXP_READ request IDs.
136 *
137 * Returns NULL if ID not in list.
138 */
139 static struct sftp_zombie_requests *
find_zombie_request(LIBSSH2_SFTP * sftp,uint32_t request_id)140 find_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id)
141 {
142 struct sftp_zombie_requests *zombie =
143 _libssh2_list_first(&sftp->zombie_requests);
144
145 while(zombie) {
146 if(zombie->request_id == request_id)
147 break;
148 else
149 zombie = _libssh2_list_next(&zombie->node);
150 }
151
152 return zombie;
153 }
154
155 static void
remove_zombie_request(LIBSSH2_SFTP * sftp,uint32_t request_id)156 remove_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id)
157 {
158 LIBSSH2_SESSION *session = sftp->channel->session;
159
160 struct sftp_zombie_requests *zombie = find_zombie_request(sftp,
161 request_id);
162 if(zombie) {
163 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
164 "Removing request ID %ld from the list of "
165 "zombie requests",
166 request_id);
167
168 _libssh2_list_remove(&zombie->node);
169 LIBSSH2_FREE(session, zombie);
170 }
171 }
172
173 static int
add_zombie_request(LIBSSH2_SFTP * sftp,uint32_t request_id)174 add_zombie_request(LIBSSH2_SFTP *sftp, uint32_t request_id)
175 {
176 LIBSSH2_SESSION *session = sftp->channel->session;
177
178 struct sftp_zombie_requests *zombie;
179
180 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
181 "Marking request ID %ld as a zombie request", request_id);
182
183 zombie = LIBSSH2_ALLOC(sftp->channel->session,
184 sizeof(struct sftp_zombie_requests));
185 if(!zombie)
186 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
187 "malloc fail for zombie request ID");
188 else {
189 zombie->request_id = request_id;
190 _libssh2_list_add(&sftp->zombie_requests, &zombie->node);
191 return LIBSSH2_ERROR_NONE;
192 }
193 }
194
195 /*
196 * sftp_packet_add
197 *
198 * Add a packet to the SFTP packet brigade
199 */
200 static int
sftp_packet_add(LIBSSH2_SFTP * sftp,unsigned char * data,size_t data_len)201 sftp_packet_add(LIBSSH2_SFTP *sftp, unsigned char *data,
202 size_t data_len)
203 {
204 LIBSSH2_SESSION *session = sftp->channel->session;
205 LIBSSH2_SFTP_PACKET *packet;
206 uint32_t request_id;
207
208 if(data_len < 5) {
209 return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
210 }
211
212 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
213 "Received packet type %d (len %d)",
214 (int) data[0], data_len);
215
216 /*
217 * Experience shows that if we mess up EAGAIN handling somewhere or
218 * otherwise get out of sync with the channel, this is where we first get
219 * a wrong byte and if so we need to bail out at once to aid tracking the
220 * problem better.
221 */
222
223 switch(data[0]) {
224 case SSH_FXP_INIT:
225 case SSH_FXP_VERSION:
226 case SSH_FXP_OPEN:
227 case SSH_FXP_CLOSE:
228 case SSH_FXP_READ:
229 case SSH_FXP_WRITE:
230 case SSH_FXP_LSTAT:
231 case SSH_FXP_FSTAT:
232 case SSH_FXP_SETSTAT:
233 case SSH_FXP_FSETSTAT:
234 case SSH_FXP_OPENDIR:
235 case SSH_FXP_READDIR:
236 case SSH_FXP_REMOVE:
237 case SSH_FXP_MKDIR:
238 case SSH_FXP_RMDIR:
239 case SSH_FXP_REALPATH:
240 case SSH_FXP_STAT:
241 case SSH_FXP_RENAME:
242 case SSH_FXP_READLINK:
243 case SSH_FXP_SYMLINK:
244 case SSH_FXP_STATUS:
245 case SSH_FXP_HANDLE:
246 case SSH_FXP_DATA:
247 case SSH_FXP_NAME:
248 case SSH_FXP_ATTRS:
249 case SSH_FXP_EXTENDED:
250 case SSH_FXP_EXTENDED_REPLY:
251 break;
252 default:
253 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
254 "Out of sync with the world");
255 }
256
257 request_id = _libssh2_ntohu32(&data[1]);
258
259 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Received packet id %d",
260 request_id);
261
262 /* Don't add the packet if it answers a request we've given up on. */
263 if((data[0] == SSH_FXP_STATUS || data[0] == SSH_FXP_DATA)
264 && find_zombie_request(sftp, request_id)) {
265
266 /* If we get here, the file ended before the response arrived. We
267 are no longer interested in the request so we discard it */
268
269 LIBSSH2_FREE(session, data);
270
271 remove_zombie_request(sftp, request_id);
272 return LIBSSH2_ERROR_NONE;
273 }
274
275 packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP_PACKET));
276 if(!packet) {
277 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
278 "Unable to allocate datablock for SFTP packet");
279 }
280
281 packet->data = data;
282 packet->data_len = data_len;
283 packet->request_id = request_id;
284
285 _libssh2_list_add(&sftp->packets, &packet->node);
286
287 return LIBSSH2_ERROR_NONE;
288 }
289
290 /*
291 * sftp_packet_read
292 *
293 * Frame an SFTP packet off the channel
294 */
295 static int
sftp_packet_read(LIBSSH2_SFTP * sftp)296 sftp_packet_read(LIBSSH2_SFTP *sftp)
297 {
298 LIBSSH2_CHANNEL *channel = sftp->channel;
299 LIBSSH2_SESSION *session = channel->session;
300 unsigned char *packet = NULL;
301 ssize_t rc;
302 unsigned long recv_window;
303 int packet_type;
304
305 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "recv packet");
306
307 switch(sftp->packet_state) {
308 case libssh2_NB_state_sent: /* EAGAIN from window adjusting */
309 sftp->packet_state = libssh2_NB_state_idle;
310
311 packet = sftp->partial_packet;
312 goto window_adjust;
313
314 case libssh2_NB_state_sent1: /* EAGAIN from channel read */
315 sftp->packet_state = libssh2_NB_state_idle;
316
317 packet = sftp->partial_packet;
318
319 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
320 "partial read cont, len: %lu", sftp->partial_len);
321 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
322 "partial read cont, already recvd: %lu",
323 sftp->partial_received);
324 /* fall-through */
325 default:
326 if(!packet) {
327 /* only do this if there's not already a packet buffer allocated
328 to use */
329
330 /* each packet starts with a 32 bit length field */
331 rc = _libssh2_channel_read(channel, 0,
332 (char *)&sftp->partial_size[
333 sftp->partial_size_len],
334 4 - sftp->partial_size_len);
335 if(rc == LIBSSH2_ERROR_EAGAIN)
336 return rc;
337 else if(rc < 0)
338 return _libssh2_error(session, rc, "channel read");
339
340 sftp->partial_size_len += rc;
341
342 if(4 != sftp->partial_size_len)
343 /* we got a short read for the length part */
344 return LIBSSH2_ERROR_EAGAIN;
345
346 sftp->partial_len = _libssh2_ntohu32(sftp->partial_size);
347 /* make sure we don't proceed if the packet size is unreasonably
348 large */
349 if(sftp->partial_len > LIBSSH2_SFTP_PACKET_MAXLEN) {
350 libssh2_channel_flush(channel);
351 sftp->partial_size_len = 0;
352 return _libssh2_error(session,
353 LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED,
354 "SFTP packet too large");
355 }
356
357 if(sftp->partial_len == 0)
358 return _libssh2_error(session,
359 LIBSSH2_ERROR_ALLOC,
360 "Unable to allocate empty SFTP packet");
361
362 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
363 "Data begin - Packet Length: %lu",
364 sftp->partial_len);
365 packet = LIBSSH2_ALLOC(session, sftp->partial_len);
366 if(!packet)
367 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
368 "Unable to allocate SFTP packet");
369 sftp->partial_size_len = 0;
370 sftp->partial_received = 0; /* how much of the packet already
371 received */
372 sftp->partial_packet = packet;
373
374 window_adjust:
375 recv_window = libssh2_channel_window_read_ex(channel, NULL, NULL);
376
377 if(sftp->partial_len > recv_window) {
378 /* ask for twice the data amount we need at once */
379 rc = _libssh2_channel_receive_window_adjust(channel,
380 sftp->partial_len
381 * 2,
382 1, NULL);
383 /* store the state so that we continue with the correct
384 operation at next invoke */
385 sftp->packet_state = (rc == LIBSSH2_ERROR_EAGAIN)?
386 libssh2_NB_state_sent:
387 libssh2_NB_state_idle;
388
389 if(rc == LIBSSH2_ERROR_EAGAIN)
390 return rc;
391 }
392 }
393
394 /* Read as much of the packet as we can */
395 while(sftp->partial_len > sftp->partial_received) {
396 rc = _libssh2_channel_read(channel, 0,
397 (char *)&packet[sftp->partial_received],
398 sftp->partial_len -
399 sftp->partial_received);
400
401 if(rc == LIBSSH2_ERROR_EAGAIN) {
402 /*
403 * We received EAGAIN, save what we have and return EAGAIN to
404 * the caller. Set 'partial_packet' so that this function
405 * knows how to continue on the next invoke.
406 */
407 sftp->packet_state = libssh2_NB_state_sent1;
408 return rc;
409 }
410 else if(rc < 0) {
411 LIBSSH2_FREE(session, packet);
412 sftp->partial_packet = NULL;
413 return _libssh2_error(session, rc,
414 "Error waiting for SFTP packet");
415 }
416 sftp->partial_received += rc;
417 }
418
419 sftp->partial_packet = NULL;
420
421 /* sftp_packet_add takes ownership of the packet and might free it
422 so we take a copy of the packet type before we call it. */
423 packet_type = packet[0];
424 rc = sftp_packet_add(sftp, packet, sftp->partial_len);
425 if(rc) {
426 LIBSSH2_FREE(session, packet);
427 return rc;
428 }
429 else {
430 return packet_type;
431 }
432 }
433 /* WON'T REACH */
434 }
435 /*
436 * sftp_packetlist_flush
437 *
438 * Remove all pending packets in the packet_list and the corresponding one(s)
439 * in the SFTP packet brigade.
440 */
sftp_packetlist_flush(LIBSSH2_SFTP_HANDLE * handle)441 static void sftp_packetlist_flush(LIBSSH2_SFTP_HANDLE *handle)
442 {
443 struct sftp_pipeline_chunk *chunk;
444 LIBSSH2_SFTP *sftp = handle->sftp;
445 LIBSSH2_SESSION *session = sftp->channel->session;
446
447 /* remove pending packets, if any */
448 chunk = _libssh2_list_first(&handle->packet_list);
449 while(chunk) {
450 unsigned char *data;
451 size_t data_len;
452 int rc;
453 struct sftp_pipeline_chunk *next = _libssh2_list_next(&chunk->node);
454
455 rc = sftp_packet_ask(sftp, SSH_FXP_STATUS,
456 chunk->request_id, &data, &data_len);
457 if(rc)
458 rc = sftp_packet_ask(sftp, SSH_FXP_DATA,
459 chunk->request_id, &data, &data_len);
460
461 if(!rc)
462 /* we found a packet, free it */
463 LIBSSH2_FREE(session, data);
464 else if(chunk->sent)
465 /* there was no incoming packet for this request, mark this
466 request as a zombie if it ever sent the request */
467 add_zombie_request(sftp, chunk->request_id);
468
469 _libssh2_list_remove(&chunk->node);
470 LIBSSH2_FREE(session, chunk);
471 chunk = next;
472 }
473 }
474
475
476 /*
477 * sftp_packet_ask()
478 *
479 * Checks if there's a matching SFTP packet available.
480 */
481 static int
sftp_packet_ask(LIBSSH2_SFTP * sftp,unsigned char packet_type,uint32_t request_id,unsigned char ** data,size_t * data_len)482 sftp_packet_ask(LIBSSH2_SFTP *sftp, unsigned char packet_type,
483 uint32_t request_id, unsigned char **data,
484 size_t *data_len)
485 {
486 LIBSSH2_SESSION *session = sftp->channel->session;
487 LIBSSH2_SFTP_PACKET *packet = _libssh2_list_first(&sftp->packets);
488
489 if(!packet)
490 return -1;
491
492 /* Special consideration when getting VERSION packet */
493
494 while(packet) {
495 if((packet->data[0] == packet_type) &&
496 ((packet_type == SSH_FXP_VERSION) ||
497 (packet->request_id == request_id))) {
498
499 /* Match! Fetch the data */
500 *data = packet->data;
501 *data_len = packet->data_len;
502
503 /* unlink and free this struct */
504 _libssh2_list_remove(&packet->node);
505 LIBSSH2_FREE(session, packet);
506
507 return 0;
508 }
509 /* check next struct in the list */
510 packet = _libssh2_list_next(&packet->node);
511 }
512 return -1;
513 }
514
515 /* sftp_packet_require
516 * A la libssh2_packet_require
517 */
518 static int
sftp_packet_require(LIBSSH2_SFTP * sftp,unsigned char packet_type,uint32_t request_id,unsigned char ** data,size_t * data_len,size_t required_size)519 sftp_packet_require(LIBSSH2_SFTP *sftp, unsigned char packet_type,
520 uint32_t request_id, unsigned char **data,
521 size_t *data_len, size_t required_size)
522 {
523 LIBSSH2_SESSION *session = sftp->channel->session;
524 int rc;
525
526 if(data == NULL || data_len == NULL || required_size == 0) {
527 return LIBSSH2_ERROR_BAD_USE;
528 }
529
530 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Requiring packet %d id %ld",
531 (int) packet_type, request_id);
532
533 if(sftp_packet_ask(sftp, packet_type, request_id, data, data_len) == 0) {
534 /* The right packet was available in the packet brigade */
535 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Got %d",
536 (int) packet_type);
537
538 if (*data_len < required_size) {
539 return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
540 }
541
542 return LIBSSH2_ERROR_NONE;
543 }
544
545 while(session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
546 rc = sftp_packet_read(sftp);
547 if(rc < 0)
548 return rc;
549
550 /* data was read, check the queue again */
551 if(!sftp_packet_ask(sftp, packet_type, request_id, data, data_len)) {
552 /* The right packet was available in the packet brigade */
553 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Got %d",
554 (int) packet_type);
555
556 if (*data_len < required_size) {
557 return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
558 }
559
560 return LIBSSH2_ERROR_NONE;
561 }
562 }
563
564 /* Only reached if the socket died */
565 return LIBSSH2_ERROR_SOCKET_DISCONNECT;
566 }
567
568 /* sftp_packet_requirev
569 * Require one of N possible responses
570 */
571 static int
sftp_packet_requirev(LIBSSH2_SFTP * sftp,int num_valid_responses,const unsigned char * valid_responses,uint32_t request_id,unsigned char ** data,size_t * data_len,size_t required_size)572 sftp_packet_requirev(LIBSSH2_SFTP *sftp, int num_valid_responses,
573 const unsigned char *valid_responses,
574 uint32_t request_id, unsigned char **data,
575 size_t *data_len, size_t required_size)
576 {
577 int i;
578 int rc;
579
580 if(data == NULL || data_len == NULL || required_size == 0) {
581 return LIBSSH2_ERROR_BAD_USE;
582 }
583
584 /* If no timeout is active, start a new one */
585 if(sftp->requirev_start == 0)
586 sftp->requirev_start = time(NULL);
587
588 while(sftp->channel->session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
589 for(i = 0; i < num_valid_responses; i++) {
590 if(sftp_packet_ask(sftp, valid_responses[i], request_id,
591 data, data_len) == 0) {
592 /*
593 * Set to zero before all returns to say
594 * the timeout is not active
595 */
596 sftp->requirev_start = 0;
597
598 if (*data_len < required_size) {
599 return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
600 }
601
602 return LIBSSH2_ERROR_NONE;
603 }
604 }
605
606 rc = sftp_packet_read(sftp);
607 if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) {
608 sftp->requirev_start = 0;
609 return rc;
610 }
611 else if(rc <= 0) {
612 /* prevent busy-looping */
613 long left =
614 LIBSSH2_READ_TIMEOUT -
615 (long)(time(NULL) - sftp->requirev_start);
616
617 if(left <= 0) {
618 sftp->requirev_start = 0;
619 return LIBSSH2_ERROR_TIMEOUT;
620 }
621 else if(rc == LIBSSH2_ERROR_EAGAIN) {
622 return rc;
623 }
624 }
625 }
626
627 sftp->requirev_start = 0;
628
629 /* Only reached if the socket died */
630 return LIBSSH2_ERROR_SOCKET_DISCONNECT;
631 }
632
633 /* sftp_attr2bin
634 * Populate attributes into an SFTP block
635 */
636 static ssize_t
sftp_attr2bin(unsigned char * p,const LIBSSH2_SFTP_ATTRIBUTES * attrs)637 sftp_attr2bin(unsigned char *p, const LIBSSH2_SFTP_ATTRIBUTES * attrs)
638 {
639 unsigned char *s = p;
640 uint32_t flag_mask =
641 LIBSSH2_SFTP_ATTR_SIZE | LIBSSH2_SFTP_ATTR_UIDGID |
642 LIBSSH2_SFTP_ATTR_PERMISSIONS | LIBSSH2_SFTP_ATTR_ACMODTIME;
643
644 /* TODO: When we add SFTP4+ functionality flag_mask can get additional
645 bits */
646
647 if(!attrs) {
648 _libssh2_htonu32(s, 0);
649 return 4;
650 }
651
652 _libssh2_store_u32(&s, attrs->flags & flag_mask);
653
654 if(attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
655 _libssh2_store_u64(&s, attrs->filesize);
656 }
657
658 if(attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
659 _libssh2_store_u32(&s, attrs->uid);
660 _libssh2_store_u32(&s, attrs->gid);
661 }
662
663 if(attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
664 _libssh2_store_u32(&s, attrs->permissions);
665 }
666
667 if(attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
668 _libssh2_store_u32(&s, attrs->atime);
669 _libssh2_store_u32(&s, attrs->mtime);
670 }
671
672 return (s - p);
673 }
674
675 /* sftp_bin2attr
676 */
677 static int
sftp_bin2attr(LIBSSH2_SFTP_ATTRIBUTES * attrs,const unsigned char * p,size_t data_len)678 sftp_bin2attr(LIBSSH2_SFTP_ATTRIBUTES *attrs, const unsigned char *p,
679 size_t data_len)
680 {
681 struct string_buf buf;
682 uint32_t flags = 0;
683 buf.data = (unsigned char *)p;
684 buf.dataptr = buf.data;
685 buf.len = data_len;
686
687 if(_libssh2_get_u32(&buf, &flags) != 0) {
688 return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
689 }
690 attrs->flags = flags;
691
692 if(attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) {
693 if(_libssh2_get_u64(&buf, &(attrs->filesize)) != 0) {
694 return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
695 }
696 }
697
698 if(attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) {
699 uint32_t uid = 0;
700 uint32_t gid = 0;
701 if(_libssh2_get_u32(&buf, &uid) != 0 ||
702 _libssh2_get_u32(&buf, &gid) != 0) {
703 return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
704 }
705 attrs->uid = uid;
706 attrs->gid = gid;
707 }
708
709 if(attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
710 uint32_t permissions;
711 if(_libssh2_get_u32(&buf, &permissions) != 0) {
712 return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
713 }
714 attrs->permissions = permissions;
715 }
716
717 if(attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
718 uint32_t atime;
719 uint32_t mtime;
720 if(_libssh2_get_u32(&buf, &atime) != 0 ||
721 _libssh2_get_u32(&buf, &mtime) != 0) {
722 return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
723 }
724 attrs->atime = atime;
725 attrs->mtime = mtime;
726 }
727
728 return (buf.dataptr - buf.data);
729 }
730
731 /* ************
732 * SFTP API *
733 ************ */
734
735 LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor);
736
737 /* libssh2_sftp_dtor
738 * Shutdown an SFTP stream when the channel closes
739 */
LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor)740 LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor)
741 {
742 LIBSSH2_SFTP *sftp = (LIBSSH2_SFTP *) (*channel_abstract);
743
744 (void) session_abstract;
745 (void) channel;
746
747 /* Free the partial packet storage for sftp_packet_read */
748 if(sftp->partial_packet) {
749 LIBSSH2_FREE(session, sftp->partial_packet);
750 }
751
752 /* Free the packet storage for _libssh2_sftp_packet_readdir */
753 if(sftp->readdir_packet) {
754 LIBSSH2_FREE(session, sftp->readdir_packet);
755 }
756
757 LIBSSH2_FREE(session, sftp);
758 }
759
760 /*
761 * sftp_init
762 *
763 * Startup an SFTP session
764 */
sftp_init(LIBSSH2_SESSION * session)765 static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
766 {
767 unsigned char *data;
768 size_t data_len;
769 ssize_t rc;
770 LIBSSH2_SFTP *sftp_handle;
771 struct string_buf buf;
772 unsigned char *endp;
773
774 if(session->sftpInit_state == libssh2_NB_state_idle) {
775 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
776 "Initializing SFTP subsystem");
777
778 /*
779 * The 'sftpInit_sftp' and 'sftpInit_channel' struct fields within the
780 * session struct are only to be used during the setup phase. As soon
781 * as the SFTP session is created they are cleared and can thus be
782 * re-used again to allow any amount of SFTP handles per sessions.
783 *
784 * Note that you MUST NOT try to call libssh2_sftp_init() again to get
785 * another handle until the previous call has finished and either
786 * successfully made a handle or failed and returned error (not
787 * including *EAGAIN).
788 */
789
790 assert(session->sftpInit_sftp == NULL);
791 session->sftpInit_sftp = NULL;
792 session->sftpInit_state = libssh2_NB_state_created;
793 }
794
795 sftp_handle = session->sftpInit_sftp;
796
797 if(session->sftpInit_state == libssh2_NB_state_created) {
798 session->sftpInit_channel =
799 _libssh2_channel_open(session, "session", sizeof("session") - 1,
800 LIBSSH2_CHANNEL_WINDOW_DEFAULT,
801 LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0);
802 if(!session->sftpInit_channel) {
803 if(libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
804 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
805 "Would block starting up channel");
806 }
807 else {
808 _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
809 "Unable to startup channel");
810 session->sftpInit_state = libssh2_NB_state_idle;
811 }
812 return NULL;
813 }
814
815 session->sftpInit_state = libssh2_NB_state_sent;
816 }
817
818 if(session->sftpInit_state == libssh2_NB_state_sent) {
819 int ret = _libssh2_channel_process_startup(session->sftpInit_channel,
820 "subsystem",
821 sizeof("subsystem") - 1,
822 "sftp",
823 strlen("sftp"));
824 if(ret == LIBSSH2_ERROR_EAGAIN) {
825 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
826 "Would block to request SFTP subsystem");
827 return NULL;
828 }
829 else if(ret) {
830 _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
831 "Unable to request SFTP subsystem");
832 goto sftp_init_error;
833 }
834
835 session->sftpInit_state = libssh2_NB_state_sent1;
836 }
837
838 if(session->sftpInit_state == libssh2_NB_state_sent1) {
839 rc = _libssh2_channel_extended_data(session->sftpInit_channel,
840 LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE);
841 if(rc == LIBSSH2_ERROR_EAGAIN) {
842 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
843 "Would block requesting handle extended data");
844 return NULL;
845 }
846
847 sftp_handle =
848 session->sftpInit_sftp =
849 LIBSSH2_CALLOC(session, sizeof(LIBSSH2_SFTP));
850 if(!sftp_handle) {
851 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
852 "Unable to allocate a new SFTP structure");
853 goto sftp_init_error;
854 }
855 sftp_handle->channel = session->sftpInit_channel;
856 sftp_handle->request_id = 0;
857
858 _libssh2_htonu32(session->sftpInit_buffer, 5);
859 session->sftpInit_buffer[4] = SSH_FXP_INIT;
860 _libssh2_htonu32(session->sftpInit_buffer + 5, LIBSSH2_SFTP_VERSION);
861 session->sftpInit_sent = 0; /* nothing's sent yet */
862
863 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
864 "Sending FXP_INIT packet advertising "
865 "version %d support",
866 (int) LIBSSH2_SFTP_VERSION);
867
868 session->sftpInit_state = libssh2_NB_state_sent2;
869 }
870
871 if(session->sftpInit_state == libssh2_NB_state_sent2) {
872 /* sent off what's left of the init buffer to send */
873 rc = _libssh2_channel_write(session->sftpInit_channel, 0,
874 session->sftpInit_buffer +
875 session->sftpInit_sent,
876 9 - session->sftpInit_sent);
877 if(rc == LIBSSH2_ERROR_EAGAIN) {
878 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
879 "Would block sending SSH_FXP_INIT");
880 return NULL;
881 }
882 else if(rc < 0) {
883 _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
884 "Unable to send SSH_FXP_INIT");
885 goto sftp_init_error;
886 }
887 else {
888 /* add up the number of bytes sent */
889 session->sftpInit_sent += rc;
890
891 if(session->sftpInit_sent == 9)
892 /* move on */
893 session->sftpInit_state = libssh2_NB_state_sent3;
894
895 /* if less than 9, we remain in this state to send more later on */
896 }
897 }
898
899 rc = sftp_packet_require(sftp_handle, SSH_FXP_VERSION,
900 0, &data, &data_len, 5);
901 if(rc == LIBSSH2_ERROR_EAGAIN) {
902 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
903 "Would block receiving SSH_FXP_VERSION");
904 return NULL;
905 }
906 else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
907 if(data_len > 0) {
908 LIBSSH2_FREE(session, data);
909 }
910 _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
911 "Invalid SSH_FXP_VERSION response");
912 goto sftp_init_error;
913 }
914 else if(rc) {
915 _libssh2_error(session, rc,
916 "Timeout waiting for response from SFTP subsystem");
917 goto sftp_init_error;
918 }
919
920 buf.data = data;
921 buf.dataptr = buf.data + 1;
922 buf.len = data_len;
923 endp = &buf.data[data_len];
924
925 if(_libssh2_get_u32(&buf, &(sftp_handle->version)) != 0) {
926 LIBSSH2_FREE(session, data);
927 rc = LIBSSH2_ERROR_BUFFER_TOO_SMALL;
928 goto sftp_init_error;
929 }
930
931 if(sftp_handle->version > LIBSSH2_SFTP_VERSION) {
932 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
933 "Truncating remote SFTP version from %lu",
934 sftp_handle->version);
935 sftp_handle->version = LIBSSH2_SFTP_VERSION;
936 }
937 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
938 "Enabling SFTP version %lu compatibility",
939 sftp_handle->version);
940 while(buf.dataptr < endp) {
941 unsigned char *extname, *extdata;
942
943 if(_libssh2_get_string(&buf, &extname, NULL)) {
944 LIBSSH2_FREE(session, data);
945 _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
946 "Data too short when extracting extname");
947 goto sftp_init_error;
948 }
949
950 if(_libssh2_get_string(&buf, &extdata, NULL)) {
951 LIBSSH2_FREE(session, data);
952 _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
953 "Data too short when extracting extdata");
954 goto sftp_init_error;
955 }
956 }
957 LIBSSH2_FREE(session, data);
958
959 /* Make sure that when the channel gets closed, the SFTP service is shut
960 down too */
961 sftp_handle->channel->abstract = sftp_handle;
962 sftp_handle->channel->close_cb = libssh2_sftp_dtor;
963
964 session->sftpInit_state = libssh2_NB_state_idle;
965
966 /* clear the sftp and channel pointers in this session struct now */
967 session->sftpInit_sftp = NULL;
968 session->sftpInit_channel = NULL;
969
970 _libssh2_list_init(&sftp_handle->sftp_handles);
971
972 return sftp_handle;
973
974 sftp_init_error:
975 while(_libssh2_channel_free(session->sftpInit_channel) ==
976 LIBSSH2_ERROR_EAGAIN);
977 session->sftpInit_channel = NULL;
978 if(session->sftpInit_sftp) {
979 LIBSSH2_FREE(session, session->sftpInit_sftp);
980 session->sftpInit_sftp = NULL;
981 }
982 session->sftpInit_state = libssh2_NB_state_idle;
983 return NULL;
984 }
985
986 /*
987 * libssh2_sftp_init
988 *
989 * Startup an SFTP session
990 */
libssh2_sftp_init(LIBSSH2_SESSION * session)991 LIBSSH2_API LIBSSH2_SFTP *libssh2_sftp_init(LIBSSH2_SESSION *session)
992 {
993 LIBSSH2_SFTP *ptr;
994
995 if(!session)
996 return NULL;
997
998 if(!(session->state & LIBSSH2_STATE_AUTHENTICATED)) {
999 _libssh2_error(session, LIBSSH2_ERROR_INVAL,
1000 "session not authenticated yet");
1001 return NULL;
1002 }
1003
1004 BLOCK_ADJUST_ERRNO(ptr, session, sftp_init(session));
1005 return ptr;
1006 }
1007
1008 /*
1009 * sftp_shutdown
1010 *
1011 * Shuts down the SFTP subsystem
1012 */
1013 static int
sftp_shutdown(LIBSSH2_SFTP * sftp)1014 sftp_shutdown(LIBSSH2_SFTP *sftp)
1015 {
1016 int rc;
1017 LIBSSH2_SESSION *session = sftp->channel->session;
1018 /*
1019 * Make sure all memory used in the state variables are free
1020 */
1021 if(sftp->partial_packet) {
1022 LIBSSH2_FREE(session, sftp->partial_packet);
1023 sftp->partial_packet = NULL;
1024 }
1025 if(sftp->open_packet) {
1026 LIBSSH2_FREE(session, sftp->open_packet);
1027 sftp->open_packet = NULL;
1028 }
1029 if(sftp->readdir_packet) {
1030 LIBSSH2_FREE(session, sftp->readdir_packet);
1031 sftp->readdir_packet = NULL;
1032 }
1033 if(sftp->fstat_packet) {
1034 LIBSSH2_FREE(session, sftp->fstat_packet);
1035 sftp->fstat_packet = NULL;
1036 }
1037 if(sftp->unlink_packet) {
1038 LIBSSH2_FREE(session, sftp->unlink_packet);
1039 sftp->unlink_packet = NULL;
1040 }
1041 if(sftp->rename_packet) {
1042 LIBSSH2_FREE(session, sftp->rename_packet);
1043 sftp->rename_packet = NULL;
1044 }
1045 if(sftp->fstatvfs_packet) {
1046 LIBSSH2_FREE(session, sftp->fstatvfs_packet);
1047 sftp->fstatvfs_packet = NULL;
1048 }
1049 if(sftp->statvfs_packet) {
1050 LIBSSH2_FREE(session, sftp->statvfs_packet);
1051 sftp->statvfs_packet = NULL;
1052 }
1053 if(sftp->mkdir_packet) {
1054 LIBSSH2_FREE(session, sftp->mkdir_packet);
1055 sftp->mkdir_packet = NULL;
1056 }
1057 if(sftp->rmdir_packet) {
1058 LIBSSH2_FREE(session, sftp->rmdir_packet);
1059 sftp->rmdir_packet = NULL;
1060 }
1061 if(sftp->stat_packet) {
1062 LIBSSH2_FREE(session, sftp->stat_packet);
1063 sftp->stat_packet = NULL;
1064 }
1065 if(sftp->symlink_packet) {
1066 LIBSSH2_FREE(session, sftp->symlink_packet);
1067 sftp->symlink_packet = NULL;
1068 }
1069 if(sftp->fsync_packet) {
1070 LIBSSH2_FREE(session, sftp->fsync_packet);
1071 sftp->fsync_packet = NULL;
1072 }
1073
1074 sftp_packet_flush(sftp);
1075
1076 /* TODO: We should consider walking over the sftp_handles list and kill
1077 * any remaining sftp handles ... */
1078
1079 rc = _libssh2_channel_free(sftp->channel);
1080
1081 return rc;
1082 }
1083
1084 /* libssh2_sftp_shutdown
1085 * Shutsdown the SFTP subsystem
1086 */
1087 LIBSSH2_API int
libssh2_sftp_shutdown(LIBSSH2_SFTP * sftp)1088 libssh2_sftp_shutdown(LIBSSH2_SFTP *sftp)
1089 {
1090 int rc;
1091 if(!sftp)
1092 return LIBSSH2_ERROR_BAD_USE;
1093 BLOCK_ADJUST(rc, sftp->channel->session, sftp_shutdown(sftp));
1094 return rc;
1095 }
1096
1097 /* *******************************
1098 * SFTP File and Directory Ops *
1099 ******************************* */
1100
1101 /* sftp_open
1102 */
1103 static LIBSSH2_SFTP_HANDLE *
sftp_open(LIBSSH2_SFTP * sftp,const char * filename,size_t filename_len,uint32_t flags,long mode,int open_type)1104 sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
1105 size_t filename_len, uint32_t flags, long mode,
1106 int open_type)
1107 {
1108 LIBSSH2_CHANNEL *channel = sftp->channel;
1109 LIBSSH2_SESSION *session = channel->session;
1110 LIBSSH2_SFTP_HANDLE *fp;
1111 LIBSSH2_SFTP_ATTRIBUTES attrs = {
1112 LIBSSH2_SFTP_ATTR_PERMISSIONS, 0, 0, 0, 0, 0, 0
1113 };
1114 unsigned char *s;
1115 ssize_t rc;
1116 int open_file = (open_type == LIBSSH2_SFTP_OPENFILE)?1:0;
1117
1118 if(sftp->open_state == libssh2_NB_state_idle) {
1119 /* packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) +
1120 flags(4) */
1121 sftp->open_packet_len = filename_len + 13 +
1122 (open_file? (4 +
1123 sftp_attrsize(LIBSSH2_SFTP_ATTR_PERMISSIONS)) : 0);
1124
1125 /* surprise! this starts out with nothing sent */
1126 sftp->open_packet_sent = 0;
1127 s = sftp->open_packet = LIBSSH2_ALLOC(session, sftp->open_packet_len);
1128 if(!sftp->open_packet) {
1129 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1130 "Unable to allocate memory for FXP_OPEN or "
1131 "FXP_OPENDIR packet");
1132 return NULL;
1133 }
1134 /* Filetype in SFTP 3 and earlier */
1135 attrs.permissions = mode |
1136 (open_file ? LIBSSH2_SFTP_ATTR_PFILETYPE_FILE :
1137 LIBSSH2_SFTP_ATTR_PFILETYPE_DIR);
1138
1139 _libssh2_store_u32(&s, sftp->open_packet_len - 4);
1140 *(s++) = open_file? SSH_FXP_OPEN : SSH_FXP_OPENDIR;
1141 sftp->open_request_id = sftp->request_id++;
1142 _libssh2_store_u32(&s, sftp->open_request_id);
1143 _libssh2_store_str(&s, filename, filename_len);
1144
1145 if(open_file) {
1146 _libssh2_store_u32(&s, flags);
1147 s += sftp_attr2bin(s, &attrs);
1148 }
1149
1150 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Sending %s open request",
1151 open_file? "file" : "directory");
1152
1153 sftp->open_state = libssh2_NB_state_created;
1154 }
1155
1156 if(sftp->open_state == libssh2_NB_state_created) {
1157 rc = _libssh2_channel_write(channel, 0, sftp->open_packet+
1158 sftp->open_packet_sent,
1159 sftp->open_packet_len -
1160 sftp->open_packet_sent);
1161 if(rc == LIBSSH2_ERROR_EAGAIN) {
1162 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
1163 "Would block sending FXP_OPEN or "
1164 "FXP_OPENDIR command");
1165 return NULL;
1166 }
1167 else if(rc < 0) {
1168 _libssh2_error(session, rc, "Unable to send FXP_OPEN*");
1169 LIBSSH2_FREE(session, sftp->open_packet);
1170 sftp->open_packet = NULL;
1171 sftp->open_state = libssh2_NB_state_idle;
1172 return NULL;
1173 }
1174
1175 /* bump the sent counter and remain in this state until the whole
1176 data is off */
1177 sftp->open_packet_sent += rc;
1178
1179 if(sftp->open_packet_len == sftp->open_packet_sent) {
1180 LIBSSH2_FREE(session, sftp->open_packet);
1181 sftp->open_packet = NULL;
1182
1183 sftp->open_state = libssh2_NB_state_sent;
1184 }
1185 }
1186
1187 if(sftp->open_state == libssh2_NB_state_sent) {
1188 size_t data_len;
1189 unsigned char *data;
1190 static const unsigned char fopen_responses[2] =
1191 { SSH_FXP_HANDLE, SSH_FXP_STATUS };
1192 rc = sftp_packet_requirev(sftp, 2, fopen_responses,
1193 sftp->open_request_id, &data,
1194 &data_len, 1);
1195 if(rc == LIBSSH2_ERROR_EAGAIN) {
1196 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
1197 "Would block waiting for status message");
1198 return NULL;
1199 }
1200 else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
1201 if(data_len > 0) {
1202 LIBSSH2_FREE(session, data);
1203 }
1204 _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1205 "Response too small");
1206 return NULL;
1207 }
1208 sftp->open_state = libssh2_NB_state_idle;
1209 if(rc) {
1210 _libssh2_error(session, rc, "Timeout waiting for status message");
1211 return NULL;
1212 }
1213
1214 /* OPEN can basically get STATUS or HANDLE back, where HANDLE implies
1215 a fine response while STATUS means error. It seems though that at
1216 times we get an SSH_FX_OK back in a STATUS, followed the "real"
1217 HANDLE so we need to properly deal with that. */
1218 if(data[0] == SSH_FXP_STATUS) {
1219 int badness = 1;
1220
1221 if(data_len < 9) {
1222 _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1223 "Too small FXP_STATUS");
1224 LIBSSH2_FREE(session, data);
1225 return NULL;
1226 }
1227
1228 sftp->last_errno = _libssh2_ntohu32(data + 5);
1229
1230 if(LIBSSH2_FX_OK == sftp->last_errno) {
1231 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
1232 "got HANDLE FXOK!");
1233
1234 LIBSSH2_FREE(session, data);
1235
1236 /* silly situation, but check for a HANDLE */
1237 rc = sftp_packet_require(sftp, SSH_FXP_HANDLE,
1238 sftp->open_request_id, &data,
1239 &data_len, 10);
1240 if(rc == LIBSSH2_ERROR_EAGAIN) {
1241 /* go back to sent state and wait for something else */
1242 sftp->open_state = libssh2_NB_state_sent;
1243 return NULL;
1244 }
1245 else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
1246 if(data_len > 0) {
1247 LIBSSH2_FREE(session, data);
1248 }
1249 _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1250 "Too small FXP_HANDLE");
1251 return NULL;
1252 }
1253 else if(!rc)
1254 /* we got the handle so this is not a bad situation */
1255 badness = 0;
1256 }
1257
1258 if(badness) {
1259 _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1260 "Failed opening remote file");
1261 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
1262 "got FXP_STATUS %d",
1263 sftp->last_errno);
1264 LIBSSH2_FREE(session, data);
1265 return NULL;
1266 }
1267 }
1268
1269 if(data_len < 10) {
1270 _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1271 "Too small FXP_HANDLE");
1272 LIBSSH2_FREE(session, data);
1273 return NULL;
1274 }
1275
1276 fp = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_SFTP_HANDLE));
1277 if(!fp) {
1278 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1279 "Unable to allocate new SFTP handle structure");
1280 LIBSSH2_FREE(session, data);
1281 return NULL;
1282 }
1283 fp->handle_type = open_file ? LIBSSH2_SFTP_HANDLE_FILE :
1284 LIBSSH2_SFTP_HANDLE_DIR;
1285
1286 fp->handle_len = _libssh2_ntohu32(data + 5);
1287 if(fp->handle_len > SFTP_HANDLE_MAXLEN)
1288 /* SFTP doesn't allow handles longer than 256 characters */
1289 fp->handle_len = SFTP_HANDLE_MAXLEN;
1290
1291 if(fp->handle_len > (data_len - 9))
1292 /* do not reach beyond the end of the data we got */
1293 fp->handle_len = data_len - 9;
1294
1295 memcpy(fp->handle, data + 9, fp->handle_len);
1296
1297 LIBSSH2_FREE(session, data);
1298
1299 /* add this file handle to the list kept in the sftp session */
1300 _libssh2_list_add(&sftp->sftp_handles, &fp->node);
1301
1302 fp->sftp = sftp; /* point to the parent struct */
1303
1304 fp->u.file.offset = 0;
1305 fp->u.file.offset_sent = 0;
1306
1307 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Open command successful");
1308 return fp;
1309 }
1310 return NULL;
1311 }
1312
1313 /* libssh2_sftp_open_ex
1314 */
1315 LIBSSH2_API LIBSSH2_SFTP_HANDLE *
libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp,const char * filename,unsigned int filename_len,unsigned long flags,long mode,int open_type)1316 libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp, const char *filename,
1317 unsigned int filename_len, unsigned long flags, long mode,
1318 int open_type)
1319 {
1320 LIBSSH2_SFTP_HANDLE *hnd;
1321
1322 if(!sftp)
1323 return NULL;
1324
1325 BLOCK_ADJUST_ERRNO(hnd, sftp->channel->session,
1326 sftp_open(sftp, filename, filename_len, flags, mode,
1327 open_type));
1328 return hnd;
1329 }
1330
1331 /*
1332 * sftp_read
1333 *
1334 * Read from an SFTP file handle
1335 *
1336 */
sftp_read(LIBSSH2_SFTP_HANDLE * handle,char * buffer,size_t buffer_size)1337 static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
1338 size_t buffer_size)
1339 {
1340 LIBSSH2_SFTP *sftp = handle->sftp;
1341 LIBSSH2_CHANNEL *channel = sftp->channel;
1342 LIBSSH2_SESSION *session = channel->session;
1343 size_t count = 0;
1344 struct sftp_pipeline_chunk *chunk;
1345 struct sftp_pipeline_chunk *next;
1346 ssize_t rc;
1347 struct _libssh2_sftp_handle_file_data *filep =
1348 &handle->u.file;
1349 size_t bytes_in_buffer = 0;
1350 char *sliding_bufferp = buffer;
1351
1352 /* This function can be interrupted in three different places where it
1353 might need to wait for data from the network. It returns EAGAIN to
1354 allow non-blocking clients to do other work but these client are
1355 expected to call this function again (possibly many times) to finish
1356 the operation.
1357
1358 The tricky part is that if we previously aborted a sftp_read due to
1359 EAGAIN, we must continue at the same spot to continue the previously
1360 interrupted operation. This is done using a state machine to record
1361 what phase of execution we were at. The state is stored in
1362 sftp->read_state.
1363
1364 libssh2_NB_state_idle: The first phase is where we prepare multiple
1365 FXP_READ packets to do optimistic read-ahead. We send off as many as
1366 possible in the second phase without waiting for a response to each
1367 one; this is the key to fast reads. But we may have to adjust the
1368 channel window size to do this which may interrupt this function while
1369 waiting. The state machine saves the phase as libssh2_NB_state_idle so
1370 it returns here on the next call.
1371
1372 libssh2_NB_state_sent: The second phase is where we send the FXP_READ
1373 packets. Writing them to the channel can be interrupted with EAGAIN
1374 but the state machine ensures we skip the first phase on the next call
1375 and resume sending.
1376
1377 libssh2_NB_state_sent2: In the third phase (indicated by ) we read the
1378 data from the responses that have arrived so far. Reading can be
1379 interrupted with EAGAIN but the state machine ensures we skip the first
1380 and second phases on the next call and resume sending.
1381 */
1382
1383 switch(sftp->read_state) {
1384 case libssh2_NB_state_idle:
1385
1386 /* Some data may already have been read from the server in the
1387 previous call but didn't fit in the buffer at the time. If so, we
1388 return that now as we can't risk being interrupted later with data
1389 partially written to the buffer. */
1390 if(filep->data_left) {
1391 size_t copy = MIN(buffer_size, filep->data_left);
1392
1393 memcpy(buffer, &filep->data[ filep->data_len - filep->data_left],
1394 copy);
1395
1396 filep->data_left -= copy;
1397 filep->offset += copy;
1398
1399 if(!filep->data_left) {
1400 LIBSSH2_FREE(session, filep->data);
1401 filep->data = NULL;
1402 }
1403
1404 return copy;
1405 }
1406
1407 if(filep->eof) {
1408 return 0;
1409 }
1410 else {
1411 /* We allow a number of bytes being requested at any given time
1412 without having been acked - until we reach EOF. */
1413
1414 /* Number of bytes asked for that haven't been acked yet */
1415 size_t already = (size_t)(filep->offset_sent - filep->offset);
1416
1417 size_t max_read_ahead = buffer_size*4;
1418 unsigned long recv_window;
1419
1420 if(max_read_ahead > LIBSSH2_CHANNEL_WINDOW_DEFAULT*4)
1421 max_read_ahead = LIBSSH2_CHANNEL_WINDOW_DEFAULT*4;
1422
1423 /* if the buffer_size passed in now is smaller than what has
1424 already been sent, we risk getting count become a very large
1425 number */
1426 if(max_read_ahead > already)
1427 count = max_read_ahead - already;
1428
1429 /* 'count' is how much more data to ask for, and 'already' is how
1430 much data that already has been asked for but not yet returned.
1431 Specificly, 'count' means how much data that have or will be
1432 asked for by the nodes that are already added to the linked
1433 list. Some of those read requests may not actually have been
1434 sent off successfully yet.
1435
1436 If 'already' is very large it should be perfectly fine to have
1437 count set to 0 as then we don't have to ask for more data
1438 (right now).
1439
1440 buffer_size*4 is just picked more or less out of the air. The
1441 idea is that when reading SFTP from a remote server, we send
1442 away multiple read requests guessing that the client will read
1443 more than only this 'buffer_size' amount of memory. So we ask
1444 for maximum buffer_size*4 amount of data so that we can return
1445 them very fast in subsequent calls.
1446 */
1447
1448 recv_window = libssh2_channel_window_read_ex(sftp->channel,
1449 NULL, NULL);
1450 if(max_read_ahead > recv_window) {
1451 /* more data will be asked for than what the window currently
1452 allows, expand it! */
1453
1454 rc = _libssh2_channel_receive_window_adjust(sftp->channel,
1455 max_read_ahead*8,
1456 1, NULL);
1457 /* if this returns EAGAIN, we will get back to this function
1458 at next call */
1459 assert(rc != LIBSSH2_ERROR_EAGAIN || !filep->data_left);
1460 assert(rc != LIBSSH2_ERROR_EAGAIN || !filep->eof);
1461 if(rc)
1462 return rc;
1463 }
1464 }
1465
1466 while(count > 0) {
1467 unsigned char *s;
1468
1469 /* 25 = packet_len(4) + packet_type(1) + request_id(4) +
1470 handle_len(4) + offset(8) + count(4) */
1471 uint32_t packet_len = (uint32_t)handle->handle_len + 25;
1472 uint32_t request_id;
1473
1474 uint32_t size = count;
1475 if(size < buffer_size)
1476 size = buffer_size;
1477 if(size > MAX_SFTP_READ_SIZE)
1478 size = MAX_SFTP_READ_SIZE;
1479
1480 chunk = LIBSSH2_ALLOC(session, packet_len +
1481 sizeof(struct sftp_pipeline_chunk));
1482 if(!chunk)
1483 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1484 "malloc fail for FXP_WRITE");
1485
1486 chunk->offset = filep->offset_sent;
1487 chunk->len = size;
1488 chunk->lefttosend = packet_len;
1489 chunk->sent = 0;
1490
1491 s = chunk->packet;
1492
1493 _libssh2_store_u32(&s, packet_len - 4);
1494 *s++ = SSH_FXP_READ;
1495 request_id = sftp->request_id++;
1496 chunk->request_id = request_id;
1497 _libssh2_store_u32(&s, request_id);
1498 _libssh2_store_str(&s, handle->handle, handle->handle_len);
1499 _libssh2_store_u64(&s, filep->offset_sent);
1500 filep->offset_sent += size; /* advance offset at once */
1501 _libssh2_store_u32(&s, size);
1502
1503 /* add this new entry LAST in the list */
1504 _libssh2_list_add(&handle->packet_list, &chunk->node);
1505 count -= MIN(size, count); /* deduct the size we used, as we might
1506 * have to create more packets */
1507 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
1508 "read request id %d sent (offset: %d, size: %d)",
1509 request_id, (int)chunk->offset, (int)chunk->len);
1510 }
1511 /* FALL-THROUGH */
1512 case libssh2_NB_state_sent:
1513
1514 sftp->read_state = libssh2_NB_state_idle;
1515
1516 /* move through the READ packets that haven't been sent and send as
1517 many as possible - remember that we don't block */
1518 chunk = _libssh2_list_first(&handle->packet_list);
1519
1520 while(chunk) {
1521 if(chunk->lefttosend) {
1522
1523 rc = _libssh2_channel_write(channel, 0,
1524 &chunk->packet[chunk->sent],
1525 chunk->lefttosend);
1526 if(rc < 0) {
1527 sftp->read_state = libssh2_NB_state_sent;
1528 return rc;
1529 }
1530
1531 /* remember where to continue sending the next time */
1532 chunk->lefttosend -= rc;
1533 chunk->sent += rc;
1534
1535 if(chunk->lefttosend) {
1536 /* We still have data left to send for this chunk.
1537 * If there is at least one completely sent chunk,
1538 * we can get out of this loop and start reading. */
1539 if(chunk != _libssh2_list_first(&handle->packet_list)) {
1540 break;
1541 }
1542 else {
1543 continue;
1544 }
1545 }
1546 }
1547
1548 /* move on to the next chunk with data to send */
1549 chunk = _libssh2_list_next(&chunk->node);
1550 }
1551 /* FALL-THROUGH */
1552
1553 case libssh2_NB_state_sent2:
1554
1555 sftp->read_state = libssh2_NB_state_idle;
1556
1557 /*
1558 * Count all ACKed packets and act on the contents of them.
1559 */
1560 chunk = _libssh2_list_first(&handle->packet_list);
1561
1562 while(chunk) {
1563 unsigned char *data;
1564 size_t data_len;
1565 uint32_t rc32;
1566 static const unsigned char read_responses[2] = {
1567 SSH_FXP_DATA, SSH_FXP_STATUS
1568 };
1569
1570 if(chunk->lefttosend) {
1571 /* if the chunk still has data left to send, we shouldn't wait
1572 for an ACK for it just yet */
1573 if(bytes_in_buffer > 0) {
1574 return bytes_in_buffer;
1575 }
1576 else {
1577 /* we should never reach this point */
1578 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1579 "sftp_read() internal error");
1580 }
1581 }
1582
1583 rc = sftp_packet_requirev(sftp, 2, read_responses,
1584 chunk->request_id, &data, &data_len, 9);
1585 if(rc == LIBSSH2_ERROR_EAGAIN && bytes_in_buffer != 0) {
1586 /* do not return EAGAIN if we have already
1587 * written data into the buffer */
1588 return bytes_in_buffer;
1589 }
1590
1591 if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
1592 if(data_len > 0) {
1593 LIBSSH2_FREE(session, data);
1594 }
1595 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1596 "Response too small");
1597 }
1598 else if(rc < 0) {
1599 sftp->read_state = libssh2_NB_state_sent2;
1600 return rc;
1601 }
1602
1603 /*
1604 * We get DATA or STATUS back. STATUS can be error, or it is
1605 * FX_EOF when we reach the end of the file.
1606 */
1607
1608 switch(data[0]) {
1609 case SSH_FXP_STATUS:
1610 /* remove the chunk we just processed */
1611
1612 _libssh2_list_remove(&chunk->node);
1613 LIBSSH2_FREE(session, chunk);
1614
1615 /* we must remove all outstanding READ requests, as either we
1616 got an error or we're at end of file */
1617 sftp_packetlist_flush(handle);
1618
1619 rc32 = _libssh2_ntohu32(data + 5);
1620 LIBSSH2_FREE(session, data);
1621
1622 if(rc32 == LIBSSH2_FX_EOF) {
1623 filep->eof = TRUE;
1624 return bytes_in_buffer;
1625 }
1626 else {
1627 sftp->last_errno = rc32;
1628 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1629 "SFTP READ error");
1630 }
1631 break;
1632
1633 case SSH_FXP_DATA:
1634 if(chunk->offset != filep->offset) {
1635 /* This could happen if the server returns less bytes than
1636 requested, which shouldn't happen for normal files. See:
1637 https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02
1638 #section-6.4
1639 */
1640 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1641 "Read Packet At Unexpected Offset");
1642 }
1643
1644 rc32 = _libssh2_ntohu32(data + 5);
1645 if(rc32 > (data_len - 9))
1646 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1647 "SFTP Protocol badness");
1648
1649 if(rc32 > chunk->len) {
1650 /* A chunk larger than we requested was returned to us.
1651 This is a protocol violation and we don't know how to
1652 deal with it. Bail out! */
1653 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1654 "FXP_READ response too big");
1655 }
1656
1657 if(rc32 != chunk->len) {
1658 /* a short read does not imply end of file, but we must
1659 adjust the offset_sent since it was advanced with a
1660 full chunk->len before */
1661 filep->offset_sent -= (chunk->len - rc32);
1662 }
1663
1664 if((bytes_in_buffer + rc32) > buffer_size) {
1665 /* figure out the overlap amount */
1666 filep->data_left = (bytes_in_buffer + rc32) - buffer_size;
1667
1668 /* getting the full packet would overflow the buffer, so
1669 only get the correct amount and keep the remainder */
1670 rc32 = (uint32_t)buffer_size - bytes_in_buffer;
1671
1672 /* store data to keep for next call */
1673 filep->data = data;
1674 filep->data_len = data_len;
1675 }
1676 else
1677 filep->data_len = 0;
1678
1679 /* copy the received data from the received FXP_DATA packet to
1680 the buffer at the correct index */
1681 memcpy(sliding_bufferp, data + 9, rc32);
1682 filep->offset += rc32;
1683 bytes_in_buffer += rc32;
1684 sliding_bufferp += rc32;
1685
1686 if(filep->data_len == 0)
1687 /* free the allocated data if not stored to keep */
1688 LIBSSH2_FREE(session, data);
1689
1690 /* remove the chunk we just processed keeping track of the
1691 * next one in case we need it */
1692 next = _libssh2_list_next(&chunk->node);
1693 _libssh2_list_remove(&chunk->node);
1694 LIBSSH2_FREE(session, chunk);
1695
1696 /* check if we have space left in the buffer
1697 * and either continue to the next chunk or stop
1698 */
1699 if(bytes_in_buffer < buffer_size) {
1700 chunk = next;
1701 }
1702 else {
1703 chunk = NULL;
1704 }
1705
1706 break;
1707 default:
1708 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1709 "SFTP Protocol badness: unrecognised "
1710 "read request response");
1711 }
1712 }
1713
1714 if(bytes_in_buffer > 0)
1715 return bytes_in_buffer;
1716
1717 break;
1718
1719 default:
1720 assert(!"State machine error; unrecognised read state");
1721 }
1722
1723 /* we should never reach this point */
1724 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1725 "sftp_read() internal error");
1726 }
1727
1728 /* libssh2_sftp_read
1729 * Read from an SFTP file handle
1730 */
1731 LIBSSH2_API ssize_t
libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * hnd,char * buffer,size_t buffer_maxlen)1732 libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *hnd, char *buffer,
1733 size_t buffer_maxlen)
1734 {
1735 ssize_t rc;
1736 if(!hnd)
1737 return LIBSSH2_ERROR_BAD_USE;
1738 BLOCK_ADJUST(rc, hnd->sftp->channel->session,
1739 sftp_read(hnd, buffer, buffer_maxlen));
1740 return rc;
1741 }
1742
1743 /* sftp_readdir
1744 * Read from an SFTP directory handle
1745 */
sftp_readdir(LIBSSH2_SFTP_HANDLE * handle,char * buffer,size_t buffer_maxlen,char * longentry,size_t longentry_maxlen,LIBSSH2_SFTP_ATTRIBUTES * attrs)1746 static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
1747 size_t buffer_maxlen, char *longentry,
1748 size_t longentry_maxlen,
1749 LIBSSH2_SFTP_ATTRIBUTES *attrs)
1750 {
1751 LIBSSH2_SFTP *sftp = handle->sftp;
1752 LIBSSH2_CHANNEL *channel = sftp->channel;
1753 LIBSSH2_SESSION *session = channel->session;
1754 size_t data_len;
1755 uint32_t num_names;
1756 /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
1757 uint32_t packet_len = handle->handle_len + 13;
1758 unsigned char *s, *data;
1759 static const unsigned char read_responses[2] = {
1760 SSH_FXP_NAME, SSH_FXP_STATUS };
1761 ssize_t retcode;
1762
1763 if(sftp->readdir_state == libssh2_NB_state_idle) {
1764 if(handle->u.dir.names_left) {
1765 /*
1766 * A prior request returned more than one directory entry,
1767 * feed it back from the buffer
1768 */
1769 LIBSSH2_SFTP_ATTRIBUTES attrs_dummy;
1770 size_t real_longentry_len;
1771 size_t real_filename_len;
1772 size_t filename_len;
1773 size_t longentry_len;
1774 size_t names_packet_len = handle->u.dir.names_packet_len;
1775 int attr_len = 0;
1776
1777 if(names_packet_len >= 4) {
1778 s = (unsigned char *) handle->u.dir.next_name;
1779 real_filename_len = _libssh2_ntohu32(s);
1780 s += 4;
1781 names_packet_len -= 4;
1782 }
1783 else {
1784 filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
1785 goto end;
1786 }
1787
1788 filename_len = real_filename_len;
1789 if(filename_len >= buffer_maxlen) {
1790 filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
1791 goto end;
1792 }
1793
1794 if(buffer_maxlen >= filename_len && names_packet_len >=
1795 filename_len) {
1796 memcpy(buffer, s, filename_len);
1797 buffer[filename_len] = '\0'; /* zero terminate */
1798 s += real_filename_len;
1799 names_packet_len -= real_filename_len;
1800 }
1801 else {
1802 filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
1803 goto end;
1804 }
1805
1806 if(names_packet_len >= 4) {
1807 real_longentry_len = _libssh2_ntohu32(s);
1808 s += 4;
1809 names_packet_len -= 4;
1810 }
1811 else {
1812 filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
1813 goto end;
1814 }
1815
1816 if(longentry && (longentry_maxlen>1)) {
1817 longentry_len = real_longentry_len;
1818
1819 if(longentry_len >= longentry_maxlen ||
1820 longentry_len > names_packet_len) {
1821 filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
1822 goto end;
1823 }
1824
1825 memcpy(longentry, s, longentry_len);
1826 longentry[longentry_len] = '\0'; /* zero terminate */
1827 }
1828
1829 if(real_longentry_len <= names_packet_len) {
1830 s += real_longentry_len;
1831 names_packet_len -= real_longentry_len;
1832 }
1833 else {
1834 filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
1835 goto end;
1836 }
1837
1838 if(attrs)
1839 memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
1840
1841 attr_len = sftp_bin2attr(attrs ? attrs : &attrs_dummy, s,
1842 names_packet_len);
1843
1844 if(attr_len >= 0) {
1845 s += attr_len;
1846 names_packet_len -= attr_len;
1847 }
1848 else {
1849 filename_len = (size_t)LIBSSH2_ERROR_BUFFER_TOO_SMALL;
1850 goto end;
1851 }
1852
1853 handle->u.dir.next_name = (char *) s;
1854 handle->u.dir.names_packet_len = names_packet_len;
1855 end:
1856
1857 if((--handle->u.dir.names_left) == 0)
1858 LIBSSH2_FREE(session, handle->u.dir.names_packet);
1859
1860 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
1861 "libssh2_sftp_readdir_ex() return %d",
1862 filename_len);
1863 return (ssize_t)filename_len;
1864 }
1865
1866 /* Request another entry(entries?) */
1867
1868 s = sftp->readdir_packet = LIBSSH2_ALLOC(session, packet_len);
1869 if(!sftp->readdir_packet)
1870 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1871 "Unable to allocate memory for "
1872 "FXP_READDIR packet");
1873
1874 _libssh2_store_u32(&s, packet_len - 4);
1875 *(s++) = SSH_FXP_READDIR;
1876 sftp->readdir_request_id = sftp->request_id++;
1877 _libssh2_store_u32(&s, sftp->readdir_request_id);
1878 _libssh2_store_str(&s, handle->handle, handle->handle_len);
1879
1880 sftp->readdir_state = libssh2_NB_state_created;
1881 }
1882
1883 if(sftp->readdir_state == libssh2_NB_state_created) {
1884 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
1885 "Reading entries from directory handle");
1886 retcode = _libssh2_channel_write(channel, 0, sftp->readdir_packet,
1887 packet_len);
1888 if(retcode == LIBSSH2_ERROR_EAGAIN) {
1889 return retcode;
1890 }
1891 else if((ssize_t)packet_len != retcode) {
1892 LIBSSH2_FREE(session, sftp->readdir_packet);
1893 sftp->readdir_packet = NULL;
1894 sftp->readdir_state = libssh2_NB_state_idle;
1895 return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
1896 "_libssh2_channel_write() failed");
1897 }
1898
1899 LIBSSH2_FREE(session, sftp->readdir_packet);
1900 sftp->readdir_packet = NULL;
1901
1902 sftp->readdir_state = libssh2_NB_state_sent;
1903 }
1904
1905 retcode = sftp_packet_requirev(sftp, 2, read_responses,
1906 sftp->readdir_request_id, &data,
1907 &data_len, 9);
1908 if(retcode == LIBSSH2_ERROR_EAGAIN)
1909 return retcode;
1910 else if(retcode == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
1911 if(data_len > 0) {
1912 LIBSSH2_FREE(session, data);
1913 }
1914 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1915 "Status message too short");
1916 }
1917 else if(retcode) {
1918 sftp->readdir_state = libssh2_NB_state_idle;
1919 return _libssh2_error(session, retcode,
1920 "Timeout waiting for status message");
1921 }
1922
1923 if(data[0] == SSH_FXP_STATUS) {
1924 retcode = _libssh2_ntohu32(data + 5);
1925 LIBSSH2_FREE(session, data);
1926 if(retcode == LIBSSH2_FX_EOF) {
1927 sftp->readdir_state = libssh2_NB_state_idle;
1928 return 0;
1929 }
1930 else {
1931 sftp->last_errno = retcode;
1932 sftp->readdir_state = libssh2_NB_state_idle;
1933 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
1934 "SFTP Protocol Error");
1935 }
1936 }
1937
1938 sftp->readdir_state = libssh2_NB_state_idle;
1939
1940 num_names = _libssh2_ntohu32(data + 5);
1941 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%lu entries returned",
1942 num_names);
1943 if(!num_names) {
1944 LIBSSH2_FREE(session, data);
1945 return 0;
1946 }
1947
1948 handle->u.dir.names_left = num_names;
1949 handle->u.dir.names_packet = data;
1950 handle->u.dir.next_name = (char *) data + 9;
1951 handle->u.dir.names_packet_len = data_len - 9;
1952
1953 /* use the name popping mechanism from the start of the function */
1954 return sftp_readdir(handle, buffer, buffer_maxlen, longentry,
1955 longentry_maxlen, attrs);
1956 }
1957
1958 /* libssh2_sftp_readdir_ex
1959 * Read from an SFTP directory handle
1960 */
1961 LIBSSH2_API int
libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE * hnd,char * buffer,size_t buffer_maxlen,char * longentry,size_t longentry_maxlen,LIBSSH2_SFTP_ATTRIBUTES * attrs)1962 libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *hnd, char *buffer,
1963 size_t buffer_maxlen, char *longentry,
1964 size_t longentry_maxlen,
1965 LIBSSH2_SFTP_ATTRIBUTES *attrs)
1966 {
1967 int rc;
1968 if(!hnd)
1969 return LIBSSH2_ERROR_BAD_USE;
1970 BLOCK_ADJUST(rc, hnd->sftp->channel->session,
1971 sftp_readdir(hnd, buffer, buffer_maxlen, longentry,
1972 longentry_maxlen, attrs));
1973 return rc;
1974 }
1975
1976 /*
1977 * sftp_write
1978 *
1979 * Write data to an SFTP handle. Returns the number of bytes written, or
1980 * a negative error code.
1981 *
1982 * We recommend sending very large data buffers to this function!
1983 *
1984 * Concept:
1985 *
1986 * - Detect how much of the given buffer that was already sent in a previous
1987 * call by inspecting the linked list of outgoing chunks. Make sure to skip
1988 * passed the data that has already been taken care of.
1989 *
1990 * - Split all (new) outgoing data in chunks no larger than N.
1991 *
1992 * - Each N bytes chunk gets created as a separate SFTP packet.
1993 *
1994 * - Add all created outgoing packets to the linked list.
1995 *
1996 * - Walk through the list and send the chunks that haven't been sent,
1997 * as many as possible until EAGAIN. Some of the chunks may have been put
1998 * in the list in a previous invoke.
1999 *
2000 * - For all the chunks in the list that have been completely sent off, check
2001 * for ACKs. If a chunk has been ACKed, it is removed from the linked
2002 * list and the "acked" counter gets increased with that data amount.
2003 *
2004 * - Return TOTAL bytes acked so far.
2005 *
2006 * Caveats:
2007 * - be careful: we must not return a higher number than what was given!
2008 *
2009 * TODO:
2010 * Introduce an option that disables this sort of "speculative" ahead writing
2011 * as there's a risk that it will do harm to some app.
2012 */
2013
sftp_write(LIBSSH2_SFTP_HANDLE * handle,const char * buffer,size_t count)2014 static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
2015 size_t count)
2016 {
2017 LIBSSH2_SFTP *sftp = handle->sftp;
2018 LIBSSH2_CHANNEL *channel = sftp->channel;
2019 LIBSSH2_SESSION *session = channel->session;
2020 size_t data_len;
2021 uint32_t retcode;
2022 uint32_t packet_len;
2023 unsigned char *s, *data;
2024 ssize_t rc;
2025 struct sftp_pipeline_chunk *chunk;
2026 struct sftp_pipeline_chunk *next;
2027 size_t acked = 0;
2028 size_t org_count = count;
2029 size_t already;
2030
2031 switch(sftp->write_state) {
2032 default:
2033 case libssh2_NB_state_idle:
2034
2035 /* Number of bytes sent off that haven't been acked and therefore we
2036 will get passed in here again.
2037
2038 Also, add up the number of bytes that actually already have been
2039 acked but we haven't been able to return as such yet, so we will
2040 get that data as well passed in here again.
2041 */
2042 already = (size_t) (handle->u.file.offset_sent -
2043 handle->u.file.offset)+
2044 handle->u.file.acked;
2045
2046 if(count >= already) {
2047 /* skip the part already made into packets */
2048 buffer += already;
2049 count -= already;
2050 }
2051 else
2052 /* there is more data already fine than what we got in this call */
2053 count = 0;
2054
2055 sftp->write_state = libssh2_NB_state_idle;
2056 while(count) {
2057 /* TODO: Possibly this should have some logic to prevent a very
2058 very small fraction to be left but lets ignore that for now */
2059 uint32_t size = MIN(MAX_SFTP_OUTGOING_SIZE, count);
2060 uint32_t request_id;
2061
2062 /* 25 = packet_len(4) + packet_type(1) + request_id(4) +
2063 handle_len(4) + offset(8) + count(4) */
2064 packet_len = handle->handle_len + size + 25;
2065
2066 chunk = LIBSSH2_ALLOC(session, packet_len +
2067 sizeof(struct sftp_pipeline_chunk));
2068 if(!chunk)
2069 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2070 "malloc fail for FXP_WRITE");
2071
2072 chunk->len = size;
2073 chunk->sent = 0;
2074 chunk->lefttosend = packet_len;
2075
2076 s = chunk->packet;
2077 _libssh2_store_u32(&s, packet_len - 4);
2078
2079 *(s++) = SSH_FXP_WRITE;
2080 request_id = sftp->request_id++;
2081 chunk->request_id = request_id;
2082 _libssh2_store_u32(&s, request_id);
2083 _libssh2_store_str(&s, handle->handle, handle->handle_len);
2084 _libssh2_store_u64(&s, handle->u.file.offset_sent);
2085 handle->u.file.offset_sent += size; /* advance offset at once */
2086 _libssh2_store_str(&s, buffer, size);
2087
2088 /* add this new entry LAST in the list */
2089 _libssh2_list_add(&handle->packet_list, &chunk->node);
2090
2091 buffer += size;
2092 count -= size; /* deduct the size we used, as we might have
2093 to create more packets */
2094 }
2095
2096 /* move through the WRITE packets that haven't been sent and send as
2097 many as possible - remember that we don't block */
2098 chunk = _libssh2_list_first(&handle->packet_list);
2099
2100 while(chunk) {
2101 if(chunk->lefttosend) {
2102 rc = _libssh2_channel_write(channel, 0,
2103 &chunk->packet[chunk->sent],
2104 chunk->lefttosend);
2105 if(rc < 0)
2106 /* remain in idle state */
2107 return rc;
2108
2109 /* remember where to continue sending the next time */
2110 chunk->lefttosend -= rc;
2111 chunk->sent += rc;
2112
2113 if(chunk->lefttosend)
2114 /* data left to send, get out of loop */
2115 break;
2116 }
2117
2118 /* move on to the next chunk with data to send */
2119 chunk = _libssh2_list_next(&chunk->node);
2120 }
2121
2122 /* fall-through */
2123 case libssh2_NB_state_sent:
2124
2125 sftp->write_state = libssh2_NB_state_idle;
2126 /*
2127 * Count all ACKed packets
2128 */
2129 chunk = _libssh2_list_first(&handle->packet_list);
2130
2131 while(chunk) {
2132 if(chunk->lefttosend)
2133 /* if the chunk still has data left to send, we shouldn't wait
2134 for an ACK for it just yet */
2135 break;
2136
2137 else if(acked)
2138 /* if we have sent data that is acked, we must return that
2139 info before we call a function that might return EAGAIN */
2140 break;
2141
2142 /* we check the packets in order */
2143 rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
2144 chunk->request_id, &data, &data_len, 9);
2145 if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
2146 if(data_len > 0) {
2147 LIBSSH2_FREE(session, data);
2148 }
2149 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2150 "FXP write packet too short");
2151 }
2152 else if(rc < 0) {
2153 if(rc == LIBSSH2_ERROR_EAGAIN)
2154 sftp->write_state = libssh2_NB_state_sent;
2155 return rc;
2156 }
2157
2158 retcode = _libssh2_ntohu32(data + 5);
2159 LIBSSH2_FREE(session, data);
2160
2161 sftp->last_errno = retcode;
2162 if(retcode == LIBSSH2_FX_OK) {
2163 acked += chunk->len; /* number of payload data that was acked
2164 here */
2165
2166 /* we increase the offset value for all acks */
2167 handle->u.file.offset += chunk->len;
2168
2169 next = _libssh2_list_next(&chunk->node);
2170
2171 _libssh2_list_remove(&chunk->node); /* remove from list */
2172 LIBSSH2_FREE(session, chunk); /* free memory */
2173
2174 chunk = next;
2175 }
2176 else {
2177 /* flush all pending packets from the outgoing list */
2178 sftp_packetlist_flush(handle);
2179
2180 /* since we return error now, the application will not get any
2181 outstanding data acked, so we need to rewind the offset to
2182 where the application knows it has reached with acked
2183 data */
2184 handle->u.file.offset -= handle->u.file.acked;
2185
2186 /* then reset the offset_sent to be the same as the offset */
2187 handle->u.file.offset_sent = handle->u.file.offset;
2188
2189 /* clear the acked counter since we can have no pending data to
2190 ack after an error */
2191 handle->u.file.acked = 0;
2192
2193 /* the server returned an error for that written chunk,
2194 propagate this back to our parent function */
2195 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2196 "FXP write failed");
2197 }
2198 }
2199 break;
2200 }
2201
2202 /* if there were acked data in a previous call that wasn't returned then,
2203 add that up and try to return it all now. This can happen if the app
2204 first sends a huge buffer of data, and then in a second call it sends a
2205 smaller one. */
2206 acked += handle->u.file.acked;
2207
2208 if(acked) {
2209 ssize_t ret = MIN(acked, org_count);
2210 /* we got data acked so return that amount, but no more than what
2211 was asked to get sent! */
2212
2213 /* store the remainder. 'ret' is always equal to or less than 'acked'
2214 here */
2215 handle->u.file.acked = acked - ret;
2216
2217 return ret;
2218 }
2219
2220 else
2221 return 0; /* nothing was acked, and no EAGAIN was received! */
2222 }
2223
2224 /* libssh2_sftp_write
2225 * Write data to a file handle
2226 */
2227 LIBSSH2_API ssize_t
libssh2_sftp_write(LIBSSH2_SFTP_HANDLE * hnd,const char * buffer,size_t count)2228 libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *hnd, const char *buffer,
2229 size_t count)
2230 {
2231 ssize_t rc;
2232 if(!hnd)
2233 return LIBSSH2_ERROR_BAD_USE;
2234 BLOCK_ADJUST(rc, hnd->sftp->channel->session,
2235 sftp_write(hnd, buffer, count));
2236 return rc;
2237
2238 }
2239
sftp_fsync(LIBSSH2_SFTP_HANDLE * handle)2240 static int sftp_fsync(LIBSSH2_SFTP_HANDLE *handle)
2241 {
2242 LIBSSH2_SFTP *sftp = handle->sftp;
2243 LIBSSH2_CHANNEL *channel = sftp->channel;
2244 LIBSSH2_SESSION *session = channel->session;
2245 /* 34 = packet_len(4) + packet_type(1) + request_id(4) +
2246 string_len(4) + strlen("fsync@openssh.com")(17) + handle_len(4) */
2247 uint32_t packet_len = handle->handle_len + 34;
2248 size_t data_len;
2249 unsigned char *packet, *s, *data;
2250 ssize_t rc;
2251 uint32_t retcode;
2252
2253 if(sftp->fsync_state == libssh2_NB_state_idle) {
2254 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
2255 "Issuing fsync command");
2256 s = packet = LIBSSH2_ALLOC(session, packet_len);
2257 if(!packet) {
2258 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2259 "Unable to allocate memory for FXP_EXTENDED "
2260 "packet");
2261 }
2262
2263 _libssh2_store_u32(&s, packet_len - 4);
2264 *(s++) = SSH_FXP_EXTENDED;
2265 sftp->fsync_request_id = sftp->request_id++;
2266 _libssh2_store_u32(&s, sftp->fsync_request_id);
2267 _libssh2_store_str(&s, "fsync@openssh.com", 17);
2268 _libssh2_store_str(&s, handle->handle, handle->handle_len);
2269
2270 sftp->fsync_state = libssh2_NB_state_created;
2271 }
2272 else {
2273 packet = sftp->fsync_packet;
2274 }
2275
2276 if(sftp->fsync_state == libssh2_NB_state_created) {
2277 rc = _libssh2_channel_write(channel, 0, packet, packet_len);
2278 if(rc == LIBSSH2_ERROR_EAGAIN ||
2279 (0 <= rc && rc < (ssize_t)packet_len)) {
2280 sftp->fsync_packet = packet;
2281 return LIBSSH2_ERROR_EAGAIN;
2282 }
2283
2284 LIBSSH2_FREE(session, packet);
2285 sftp->fsync_packet = NULL;
2286
2287 if(rc < 0) {
2288 sftp->fsync_state = libssh2_NB_state_idle;
2289 return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2290 "_libssh2_channel_write() failed");
2291 }
2292 sftp->fsync_state = libssh2_NB_state_sent;
2293 }
2294
2295 rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
2296 sftp->fsync_request_id, &data, &data_len, 9);
2297 if(rc == LIBSSH2_ERROR_EAGAIN) {
2298 return rc;
2299 }
2300 else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
2301 if(data_len > 0) {
2302 LIBSSH2_FREE(session, data);
2303 }
2304 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2305 "SFTP fsync packet too short");
2306 }
2307 else if(rc) {
2308 sftp->fsync_state = libssh2_NB_state_idle;
2309 return _libssh2_error(session, rc,
2310 "Error waiting for FXP EXTENDED REPLY");
2311 }
2312
2313 sftp->fsync_state = libssh2_NB_state_idle;
2314
2315 retcode = _libssh2_ntohu32(data + 5);
2316 LIBSSH2_FREE(session, data);
2317
2318 if(retcode != LIBSSH2_FX_OK) {
2319 sftp->last_errno = retcode;
2320 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2321 "fsync failed");
2322 }
2323
2324 return 0;
2325 }
2326
2327 /* libssh2_sftp_fsync
2328 * Commit data on the handle to disk.
2329 */
2330 LIBSSH2_API int
libssh2_sftp_fsync(LIBSSH2_SFTP_HANDLE * hnd)2331 libssh2_sftp_fsync(LIBSSH2_SFTP_HANDLE *hnd)
2332 {
2333 int rc;
2334 if(!hnd)
2335 return LIBSSH2_ERROR_BAD_USE;
2336 BLOCK_ADJUST(rc, hnd->sftp->channel->session,
2337 sftp_fsync(hnd));
2338 return rc;
2339 }
2340
2341
2342 /*
2343 * sftp_fstat
2344 *
2345 * Get or Set stat on a file
2346 */
sftp_fstat(LIBSSH2_SFTP_HANDLE * handle,LIBSSH2_SFTP_ATTRIBUTES * attrs,int setstat)2347 static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
2348 LIBSSH2_SFTP_ATTRIBUTES *attrs, int setstat)
2349 {
2350 LIBSSH2_SFTP *sftp = handle->sftp;
2351 LIBSSH2_CHANNEL *channel = sftp->channel;
2352 LIBSSH2_SESSION *session = channel->session;
2353 size_t data_len;
2354 /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
2355 uint32_t packet_len =
2356 handle->handle_len + 13 + (setstat ? sftp_attrsize(attrs->flags) : 0);
2357 unsigned char *s, *data;
2358 static const unsigned char fstat_responses[2] =
2359 { SSH_FXP_ATTRS, SSH_FXP_STATUS };
2360 ssize_t rc;
2361
2362 if(sftp->fstat_state == libssh2_NB_state_idle) {
2363 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Issuing %s command",
2364 setstat ? "set-stat" : "stat");
2365 s = sftp->fstat_packet = LIBSSH2_ALLOC(session, packet_len);
2366 if(!sftp->fstat_packet) {
2367 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2368 "Unable to allocate memory for "
2369 "FSTAT/FSETSTAT packet");
2370 }
2371
2372 _libssh2_store_u32(&s, packet_len - 4);
2373 *(s++) = setstat ? SSH_FXP_FSETSTAT : SSH_FXP_FSTAT;
2374 sftp->fstat_request_id = sftp->request_id++;
2375 _libssh2_store_u32(&s, sftp->fstat_request_id);
2376 _libssh2_store_str(&s, handle->handle, handle->handle_len);
2377
2378 if(setstat) {
2379 s += sftp_attr2bin(s, attrs);
2380 }
2381
2382 sftp->fstat_state = libssh2_NB_state_created;
2383 }
2384
2385 if(sftp->fstat_state == libssh2_NB_state_created) {
2386 rc = _libssh2_channel_write(channel, 0, sftp->fstat_packet,
2387 packet_len);
2388 if(rc == LIBSSH2_ERROR_EAGAIN) {
2389 return rc;
2390 }
2391 else if((ssize_t)packet_len != rc) {
2392 LIBSSH2_FREE(session, sftp->fstat_packet);
2393 sftp->fstat_packet = NULL;
2394 sftp->fstat_state = libssh2_NB_state_idle;
2395 return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2396 (setstat ? "Unable to send FXP_FSETSTAT"
2397 : "Unable to send FXP_FSTAT command"));
2398 }
2399 LIBSSH2_FREE(session, sftp->fstat_packet);
2400 sftp->fstat_packet = NULL;
2401
2402 sftp->fstat_state = libssh2_NB_state_sent;
2403 }
2404
2405 rc = sftp_packet_requirev(sftp, 2, fstat_responses,
2406 sftp->fstat_request_id, &data,
2407 &data_len, 9);
2408 if(rc == LIBSSH2_ERROR_EAGAIN)
2409 return rc;
2410 else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
2411 if(data_len > 0) {
2412 LIBSSH2_FREE(session, data);
2413 }
2414 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2415 "SFTP fstat packet too short");
2416 }
2417 else if(rc) {
2418 sftp->fstat_state = libssh2_NB_state_idle;
2419 return _libssh2_error(session, rc,
2420 "Timeout waiting for status message");
2421 }
2422
2423 sftp->fstat_state = libssh2_NB_state_idle;
2424
2425 if(data[0] == SSH_FXP_STATUS) {
2426 uint32_t retcode;
2427
2428 retcode = _libssh2_ntohu32(data + 5);
2429 LIBSSH2_FREE(session, data);
2430 if(retcode == LIBSSH2_FX_OK) {
2431 return 0;
2432 }
2433 else {
2434 sftp->last_errno = retcode;
2435 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2436 "SFTP Protocol Error");
2437 }
2438 }
2439
2440 if(sftp_bin2attr(attrs, data + 5, data_len - 5) < 0) {
2441 LIBSSH2_FREE(session, data);
2442 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2443 "Attributes too short in SFTP fstat");
2444 }
2445
2446 LIBSSH2_FREE(session, data);
2447
2448 return 0;
2449 }
2450
2451 /* libssh2_sftp_fstat_ex
2452 * Get or Set stat on a file
2453 */
2454 LIBSSH2_API int
libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE * hnd,LIBSSH2_SFTP_ATTRIBUTES * attrs,int setstat)2455 libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE *hnd,
2456 LIBSSH2_SFTP_ATTRIBUTES *attrs, int setstat)
2457 {
2458 int rc;
2459 if(!hnd || !attrs)
2460 return LIBSSH2_ERROR_BAD_USE;
2461 BLOCK_ADJUST(rc, hnd->sftp->channel->session,
2462 sftp_fstat(hnd, attrs, setstat));
2463 return rc;
2464 }
2465
2466
2467 /* libssh2_sftp_seek64
2468 * Set the read/write pointer to an arbitrary position within the file
2469 */
2470 LIBSSH2_API void
libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE * handle,libssh2_uint64_t offset)2471 libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE *handle, libssh2_uint64_t offset)
2472 {
2473 if(!handle)
2474 return;
2475 if(handle->u.file.offset == offset && handle->u.file.offset_sent == offset)
2476 return;
2477
2478 handle->u.file.offset = handle->u.file.offset_sent = offset;
2479 /* discard all pending requests and currently read data */
2480 sftp_packetlist_flush(handle);
2481
2482 /* free the left received buffered data */
2483 if(handle->u.file.data_left) {
2484 LIBSSH2_FREE(handle->sftp->channel->session, handle->u.file.data);
2485 handle->u.file.data_left = handle->u.file.data_len = 0;
2486 handle->u.file.data = NULL;
2487 }
2488
2489 /* reset EOF to False */
2490 handle->u.file.eof = FALSE;
2491 }
2492
2493 /* libssh2_sftp_seek
2494 * Set the read/write pointer to an arbitrary position within the file
2495 */
2496 LIBSSH2_API void
libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE * handle,size_t offset)2497 libssh2_sftp_seek(LIBSSH2_SFTP_HANDLE *handle, size_t offset)
2498 {
2499 libssh2_sftp_seek64(handle, (libssh2_uint64_t)offset);
2500 }
2501
2502 /* libssh2_sftp_tell
2503 * Return the current read/write pointer's offset
2504 */
2505 LIBSSH2_API size_t
libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE * handle)2506 libssh2_sftp_tell(LIBSSH2_SFTP_HANDLE *handle)
2507 {
2508 if(!handle)
2509 return 0; /* no handle, no size */
2510
2511 /* NOTE: this may very well truncate the size if it is larger than what
2512 size_t can hold, so libssh2_sftp_tell64() is really the function you
2513 should use */
2514 return (size_t)(handle->u.file.offset);
2515 }
2516
2517 /* libssh2_sftp_tell64
2518 * Return the current read/write pointer's offset
2519 */
2520 LIBSSH2_API libssh2_uint64_t
libssh2_sftp_tell64(LIBSSH2_SFTP_HANDLE * handle)2521 libssh2_sftp_tell64(LIBSSH2_SFTP_HANDLE *handle)
2522 {
2523 if(!handle)
2524 return 0; /* no handle, no size */
2525
2526 return handle->u.file.offset;
2527 }
2528
2529 /*
2530 * Flush all remaining incoming SFTP packets and zombies.
2531 */
sftp_packet_flush(LIBSSH2_SFTP * sftp)2532 static void sftp_packet_flush(LIBSSH2_SFTP *sftp)
2533 {
2534 LIBSSH2_CHANNEL *channel = sftp->channel;
2535 LIBSSH2_SESSION *session = channel->session;
2536 LIBSSH2_SFTP_PACKET *packet = _libssh2_list_first(&sftp->packets);
2537 struct sftp_zombie_requests *zombie =
2538 _libssh2_list_first(&sftp->zombie_requests);
2539
2540 while(packet) {
2541 LIBSSH2_SFTP_PACKET *next;
2542
2543 /* check next struct in the list */
2544 next = _libssh2_list_next(&packet->node);
2545 _libssh2_list_remove(&packet->node);
2546 LIBSSH2_FREE(session, packet->data);
2547 LIBSSH2_FREE(session, packet);
2548
2549 packet = next;
2550 }
2551
2552 while(zombie) {
2553 /* figure out the next node */
2554 struct sftp_zombie_requests *next = _libssh2_list_next(&zombie->node);
2555 /* unlink the current one */
2556 _libssh2_list_remove(&zombie->node);
2557 /* free the memory */
2558 LIBSSH2_FREE(session, zombie);
2559 zombie = next;
2560 }
2561
2562 }
2563
2564 /* sftp_close_handle
2565 *
2566 * Close a file or directory handle.
2567 * Also frees handle resource and unlinks it from the SFTP structure.
2568 * The handle is no longer usable after return of this function, unless
2569 * the return value is LIBSSH2_ERROR_EAGAIN in which case this function
2570 * should be called again.
2571 */
2572 static int
sftp_close_handle(LIBSSH2_SFTP_HANDLE * handle)2573 sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
2574 {
2575 LIBSSH2_SFTP *sftp = handle->sftp;
2576 LIBSSH2_CHANNEL *channel = sftp->channel;
2577 LIBSSH2_SESSION *session = channel->session;
2578 size_t data_len;
2579 /* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
2580 uint32_t packet_len = handle->handle_len + 13;
2581 unsigned char *s, *data = NULL;
2582 int rc = 0;
2583
2584 if(handle->close_state == libssh2_NB_state_idle) {
2585 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Closing handle");
2586 s = handle->close_packet = LIBSSH2_ALLOC(session, packet_len);
2587 if(!handle->close_packet) {
2588 handle->close_state = libssh2_NB_state_idle;
2589 rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2590 "Unable to allocate memory for FXP_CLOSE "
2591 "packet");
2592 }
2593 else {
2594
2595 _libssh2_store_u32(&s, packet_len - 4);
2596 *(s++) = SSH_FXP_CLOSE;
2597 handle->close_request_id = sftp->request_id++;
2598 _libssh2_store_u32(&s, handle->close_request_id);
2599 _libssh2_store_str(&s, handle->handle, handle->handle_len);
2600 handle->close_state = libssh2_NB_state_created;
2601 }
2602 }
2603
2604 if(handle->close_state == libssh2_NB_state_created) {
2605 rc = _libssh2_channel_write(channel, 0, handle->close_packet,
2606 packet_len);
2607 if(rc == LIBSSH2_ERROR_EAGAIN) {
2608 return rc;
2609 }
2610 else if((ssize_t)packet_len != rc) {
2611 handle->close_state = libssh2_NB_state_idle;
2612 rc = _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2613 "Unable to send FXP_CLOSE command");
2614 }
2615 else
2616 handle->close_state = libssh2_NB_state_sent;
2617
2618 LIBSSH2_FREE(session, handle->close_packet);
2619 handle->close_packet = NULL;
2620 }
2621
2622 if(handle->close_state == libssh2_NB_state_sent) {
2623 rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
2624 handle->close_request_id, &data,
2625 &data_len, 9);
2626 if(rc == LIBSSH2_ERROR_EAGAIN) {
2627 return rc;
2628 }
2629 else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
2630 if(data_len > 0) {
2631 LIBSSH2_FREE(session, data);
2632 }
2633 data = NULL;
2634 _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2635 "Packet too short in FXP_CLOSE command");
2636 }
2637 else if(rc) {
2638 _libssh2_error(session, rc,
2639 "Error waiting for status message");
2640 }
2641
2642 handle->close_state = libssh2_NB_state_sent1;
2643 }
2644
2645 if(!data) {
2646 /* if it reaches this point with data unset, something unwanted
2647 happened for which we should have set an error code */
2648 assert(rc);
2649
2650 }
2651 else {
2652 int retcode = _libssh2_ntohu32(data + 5);
2653 LIBSSH2_FREE(session, data);
2654
2655 if(retcode != LIBSSH2_FX_OK) {
2656 sftp->last_errno = retcode;
2657 handle->close_state = libssh2_NB_state_idle;
2658 rc = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2659 "SFTP Protocol Error");
2660 }
2661 }
2662
2663 /* remove this handle from the parent's list */
2664 _libssh2_list_remove(&handle->node);
2665
2666 if(handle->handle_type == LIBSSH2_SFTP_HANDLE_DIR) {
2667 if(handle->u.dir.names_left)
2668 LIBSSH2_FREE(session, handle->u.dir.names_packet);
2669 }
2670 else if(handle->handle_type == LIBSSH2_SFTP_HANDLE_FILE) {
2671 if(handle->u.file.data)
2672 LIBSSH2_FREE(session, handle->u.file.data);
2673 }
2674
2675 sftp_packetlist_flush(handle);
2676 sftp->read_state = libssh2_NB_state_idle;
2677
2678 handle->close_state = libssh2_NB_state_idle;
2679
2680 LIBSSH2_FREE(session, handle);
2681
2682 return rc;
2683 }
2684
2685 /* libssh2_sftp_close_handle
2686 *
2687 * Close a file or directory handle
2688 * Also frees handle resource and unlinks it from the SFTP structure
2689 */
2690 LIBSSH2_API int
libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE * hnd)2691 libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *hnd)
2692 {
2693 int rc;
2694 if(!hnd)
2695 return LIBSSH2_ERROR_BAD_USE;
2696 BLOCK_ADJUST(rc, hnd->sftp->channel->session, sftp_close_handle(hnd));
2697 return rc;
2698 }
2699
2700 /* sftp_unlink
2701 * Delete a file from the remote server
2702 */
sftp_unlink(LIBSSH2_SFTP * sftp,const char * filename,size_t filename_len)2703 static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename,
2704 size_t filename_len)
2705 {
2706 LIBSSH2_CHANNEL *channel = sftp->channel;
2707 LIBSSH2_SESSION *session = channel->session;
2708 size_t data_len;
2709 int retcode;
2710 /* 13 = packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) */
2711 uint32_t packet_len = filename_len + 13;
2712 unsigned char *s, *data;
2713 int rc;
2714
2715 if(sftp->unlink_state == libssh2_NB_state_idle) {
2716 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Unlinking %s", filename);
2717 s = sftp->unlink_packet = LIBSSH2_ALLOC(session, packet_len);
2718 if(!sftp->unlink_packet) {
2719 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2720 "Unable to allocate memory for FXP_REMOVE "
2721 "packet");
2722 }
2723
2724 _libssh2_store_u32(&s, packet_len - 4);
2725 *(s++) = SSH_FXP_REMOVE;
2726 sftp->unlink_request_id = sftp->request_id++;
2727 _libssh2_store_u32(&s, sftp->unlink_request_id);
2728 _libssh2_store_str(&s, filename, filename_len);
2729 sftp->unlink_state = libssh2_NB_state_created;
2730 }
2731
2732 if(sftp->unlink_state == libssh2_NB_state_created) {
2733 rc = _libssh2_channel_write(channel, 0, sftp->unlink_packet,
2734 packet_len);
2735 if(rc == LIBSSH2_ERROR_EAGAIN) {
2736 return rc;
2737 }
2738 else if((ssize_t)packet_len != rc) {
2739 LIBSSH2_FREE(session, sftp->unlink_packet);
2740 sftp->unlink_packet = NULL;
2741 sftp->unlink_state = libssh2_NB_state_idle;
2742 return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2743 "Unable to send FXP_REMOVE command");
2744 }
2745 LIBSSH2_FREE(session, sftp->unlink_packet);
2746 sftp->unlink_packet = NULL;
2747
2748 sftp->unlink_state = libssh2_NB_state_sent;
2749 }
2750
2751 rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
2752 sftp->unlink_request_id, &data,
2753 &data_len, 9);
2754 if(rc == LIBSSH2_ERROR_EAGAIN) {
2755 return rc;
2756 }
2757 else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
2758 if(data_len > 0) {
2759 LIBSSH2_FREE(session, data);
2760 }
2761 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2762 "SFTP unlink packet too short");
2763 }
2764 else if(rc) {
2765 sftp->unlink_state = libssh2_NB_state_idle;
2766 return _libssh2_error(session, rc,
2767 "Error waiting for FXP STATUS");
2768 }
2769
2770 sftp->unlink_state = libssh2_NB_state_idle;
2771
2772 retcode = _libssh2_ntohu32(data + 5);
2773 LIBSSH2_FREE(session, data);
2774
2775 if(retcode == LIBSSH2_FX_OK) {
2776 return 0;
2777 }
2778 else {
2779 sftp->last_errno = retcode;
2780 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2781 "SFTP Protocol Error");
2782 }
2783 }
2784
2785 /* libssh2_sftp_unlink_ex
2786 * Delete a file from the remote server
2787 */
2788 LIBSSH2_API int
libssh2_sftp_unlink_ex(LIBSSH2_SFTP * sftp,const char * filename,unsigned int filename_len)2789 libssh2_sftp_unlink_ex(LIBSSH2_SFTP *sftp, const char *filename,
2790 unsigned int filename_len)
2791 {
2792 int rc;
2793 if(!sftp)
2794 return LIBSSH2_ERROR_BAD_USE;
2795 BLOCK_ADJUST(rc, sftp->channel->session,
2796 sftp_unlink(sftp, filename, filename_len));
2797 return rc;
2798 }
2799
2800 /*
2801 * sftp_rename
2802 *
2803 * Rename a file on the remote server
2804 */
sftp_rename(LIBSSH2_SFTP * sftp,const char * source_filename,unsigned int source_filename_len,const char * dest_filename,unsigned int dest_filename_len,long flags)2805 static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename,
2806 unsigned int source_filename_len,
2807 const char *dest_filename,
2808 unsigned int dest_filename_len, long flags)
2809 {
2810 LIBSSH2_CHANNEL *channel = sftp->channel;
2811 LIBSSH2_SESSION *session = channel->session;
2812 size_t data_len;
2813 int retcode;
2814 uint32_t packet_len =
2815 source_filename_len + dest_filename_len + 17 + (sftp->version >=
2816 5 ? 4 : 0);
2817 /* packet_len(4) + packet_type(1) + request_id(4) +
2818 source_filename_len(4) + dest_filename_len(4) + flags(4){SFTP5+) */
2819 unsigned char *data;
2820 ssize_t rc;
2821
2822 if(sftp->version < 2) {
2823 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2824 "Server does not support RENAME");
2825 }
2826
2827 if(sftp->rename_state == libssh2_NB_state_idle) {
2828 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Renaming %s to %s",
2829 source_filename, dest_filename);
2830 sftp->rename_s = sftp->rename_packet =
2831 LIBSSH2_ALLOC(session, packet_len);
2832 if(!sftp->rename_packet) {
2833 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2834 "Unable to allocate memory for FXP_RENAME "
2835 "packet");
2836 }
2837
2838 _libssh2_store_u32(&sftp->rename_s, packet_len - 4);
2839 *(sftp->rename_s++) = SSH_FXP_RENAME;
2840 sftp->rename_request_id = sftp->request_id++;
2841 _libssh2_store_u32(&sftp->rename_s, sftp->rename_request_id);
2842 _libssh2_store_str(&sftp->rename_s, source_filename,
2843 source_filename_len);
2844 _libssh2_store_str(&sftp->rename_s, dest_filename, dest_filename_len);
2845
2846 if(sftp->version >= 5)
2847 _libssh2_store_u32(&sftp->rename_s, flags);
2848
2849 sftp->rename_state = libssh2_NB_state_created;
2850 }
2851
2852 if(sftp->rename_state == libssh2_NB_state_created) {
2853 rc = _libssh2_channel_write(channel, 0, sftp->rename_packet,
2854 sftp->rename_s - sftp->rename_packet);
2855 if(rc == LIBSSH2_ERROR_EAGAIN) {
2856 return rc;
2857 }
2858 else if((ssize_t)packet_len != rc) {
2859 LIBSSH2_FREE(session, sftp->rename_packet);
2860 sftp->rename_packet = NULL;
2861 sftp->rename_state = libssh2_NB_state_idle;
2862 return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2863 "Unable to send FXP_RENAME command");
2864 }
2865 LIBSSH2_FREE(session, sftp->rename_packet);
2866 sftp->rename_packet = NULL;
2867
2868 sftp->rename_state = libssh2_NB_state_sent;
2869 }
2870
2871 rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
2872 sftp->rename_request_id, &data,
2873 &data_len, 9);
2874 if(rc == LIBSSH2_ERROR_EAGAIN) {
2875 return rc;
2876 }
2877 else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
2878 if(data_len > 0) {
2879 LIBSSH2_FREE(session, data);
2880 }
2881 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2882 "SFTP rename packet too short");
2883 }
2884 else if(rc) {
2885 sftp->rename_state = libssh2_NB_state_idle;
2886 return _libssh2_error(session, rc,
2887 "Error waiting for FXP STATUS");
2888 }
2889
2890 sftp->rename_state = libssh2_NB_state_idle;
2891
2892 retcode = _libssh2_ntohu32(data + 5);
2893 LIBSSH2_FREE(session, data);
2894
2895 sftp->last_errno = retcode;
2896
2897 /* now convert the SFTP error code to libssh2 return code or error
2898 message */
2899 switch(retcode) {
2900 case LIBSSH2_FX_OK:
2901 retcode = LIBSSH2_ERROR_NONE;
2902 break;
2903
2904 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
2905 retcode = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2906 "File already exists and "
2907 "SSH_FXP_RENAME_OVERWRITE not specified");
2908 break;
2909
2910 case LIBSSH2_FX_OP_UNSUPPORTED:
2911 retcode = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2912 "Operation Not Supported");
2913 break;
2914
2915 default:
2916 retcode = _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
2917 "SFTP Protocol Error");
2918 break;
2919 }
2920
2921 return retcode;
2922 }
2923
2924 /* libssh2_sftp_rename_ex
2925 * Rename a file on the remote server
2926 */
2927 LIBSSH2_API int
libssh2_sftp_rename_ex(LIBSSH2_SFTP * sftp,const char * source_filename,unsigned int source_filename_len,const char * dest_filename,unsigned int dest_filename_len,long flags)2928 libssh2_sftp_rename_ex(LIBSSH2_SFTP *sftp, const char *source_filename,
2929 unsigned int source_filename_len,
2930 const char *dest_filename,
2931 unsigned int dest_filename_len, long flags)
2932 {
2933 int rc;
2934 if(!sftp)
2935 return LIBSSH2_ERROR_BAD_USE;
2936 BLOCK_ADJUST(rc, sftp->channel->session,
2937 sftp_rename(sftp, source_filename, source_filename_len,
2938 dest_filename, dest_filename_len, flags));
2939 return rc;
2940 }
2941
2942 /*
2943 * sftp_fstatvfs
2944 *
2945 * Get file system statistics
2946 */
sftp_fstatvfs(LIBSSH2_SFTP_HANDLE * handle,LIBSSH2_SFTP_STATVFS * st)2947 static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st)
2948 {
2949 LIBSSH2_SFTP *sftp = handle->sftp;
2950 LIBSSH2_CHANNEL *channel = sftp->channel;
2951 LIBSSH2_SESSION *session = channel->session;
2952 size_t data_len;
2953 /* 17 = packet_len(4) + packet_type(1) + request_id(4) + ext_len(4)
2954 + handle_len (4) */
2955 /* 20 = strlen ("fstatvfs@openssh.com") */
2956 uint32_t packet_len = handle->handle_len + 20 + 17;
2957 unsigned char *packet, *s, *data;
2958 ssize_t rc;
2959 unsigned int flag;
2960 static const unsigned char responses[2] =
2961 { SSH_FXP_EXTENDED_REPLY, SSH_FXP_STATUS };
2962
2963 if(sftp->fstatvfs_state == libssh2_NB_state_idle) {
2964 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
2965 "Getting file system statistics");
2966 s = packet = LIBSSH2_ALLOC(session, packet_len);
2967 if(!packet) {
2968 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2969 "Unable to allocate memory for FXP_EXTENDED "
2970 "packet");
2971 }
2972
2973 _libssh2_store_u32(&s, packet_len - 4);
2974 *(s++) = SSH_FXP_EXTENDED;
2975 sftp->fstatvfs_request_id = sftp->request_id++;
2976 _libssh2_store_u32(&s, sftp->fstatvfs_request_id);
2977 _libssh2_store_str(&s, "fstatvfs@openssh.com", 20);
2978 _libssh2_store_str(&s, handle->handle, handle->handle_len);
2979
2980 sftp->fstatvfs_state = libssh2_NB_state_created;
2981 }
2982 else {
2983 packet = sftp->fstatvfs_packet;
2984 }
2985
2986 if(sftp->fstatvfs_state == libssh2_NB_state_created) {
2987 rc = _libssh2_channel_write(channel, 0, packet, packet_len);
2988 if(rc == LIBSSH2_ERROR_EAGAIN ||
2989 (0 <= rc && rc < (ssize_t)packet_len)) {
2990 sftp->fstatvfs_packet = packet;
2991 return LIBSSH2_ERROR_EAGAIN;
2992 }
2993
2994 LIBSSH2_FREE(session, packet);
2995 sftp->fstatvfs_packet = NULL;
2996
2997 if(rc < 0) {
2998 sftp->fstatvfs_state = libssh2_NB_state_idle;
2999 return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
3000 "_libssh2_channel_write() failed");
3001 }
3002 sftp->fstatvfs_state = libssh2_NB_state_sent;
3003 }
3004
3005 rc = sftp_packet_requirev(sftp, 2, responses, sftp->fstatvfs_request_id,
3006 &data, &data_len, 9);
3007
3008 if(rc == LIBSSH2_ERROR_EAGAIN) {
3009 return rc;
3010 }
3011 else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
3012 if(data_len > 0) {
3013 LIBSSH2_FREE(session, data);
3014 }
3015 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3016 "SFTP rename packet too short");
3017 }
3018 else if(rc) {
3019 sftp->fstatvfs_state = libssh2_NB_state_idle;
3020 return _libssh2_error(session, rc,
3021 "Error waiting for FXP EXTENDED REPLY");
3022 }
3023
3024 if(data[0] == SSH_FXP_STATUS) {
3025 int retcode = _libssh2_ntohu32(data + 5);
3026 sftp->fstatvfs_state = libssh2_NB_state_idle;
3027 LIBSSH2_FREE(session, data);
3028 sftp->last_errno = retcode;
3029 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3030 "SFTP Protocol Error");
3031 }
3032
3033 if(data_len < 93) {
3034 LIBSSH2_FREE(session, data);
3035 sftp->fstatvfs_state = libssh2_NB_state_idle;
3036 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3037 "SFTP Protocol Error: short response");
3038 }
3039
3040 sftp->fstatvfs_state = libssh2_NB_state_idle;
3041
3042 st->f_bsize = _libssh2_ntohu64(data + 5);
3043 st->f_frsize = _libssh2_ntohu64(data + 13);
3044 st->f_blocks = _libssh2_ntohu64(data + 21);
3045 st->f_bfree = _libssh2_ntohu64(data + 29);
3046 st->f_bavail = _libssh2_ntohu64(data + 37);
3047 st->f_files = _libssh2_ntohu64(data + 45);
3048 st->f_ffree = _libssh2_ntohu64(data + 53);
3049 st->f_favail = _libssh2_ntohu64(data + 61);
3050 st->f_fsid = _libssh2_ntohu64(data + 69);
3051 flag = (unsigned int)_libssh2_ntohu64(data + 77);
3052 st->f_namemax = _libssh2_ntohu64(data + 85);
3053
3054 st->f_flag = (flag & SSH_FXE_STATVFS_ST_RDONLY)
3055 ? LIBSSH2_SFTP_ST_RDONLY : 0;
3056 st->f_flag |= (flag & SSH_FXE_STATVFS_ST_NOSUID)
3057 ? LIBSSH2_SFTP_ST_NOSUID : 0;
3058
3059 LIBSSH2_FREE(session, data);
3060 return 0;
3061 }
3062
3063 /* libssh2_sftp_fstatvfs
3064 * Get filesystem space and inode utilization (requires fstatvfs@openssh.com
3065 * support on the server)
3066 */
3067 LIBSSH2_API int
libssh2_sftp_fstatvfs(LIBSSH2_SFTP_HANDLE * handle,LIBSSH2_SFTP_STATVFS * st)3068 libssh2_sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st)
3069 {
3070 int rc;
3071 if(!handle || !st)
3072 return LIBSSH2_ERROR_BAD_USE;
3073 BLOCK_ADJUST(rc, handle->sftp->channel->session,
3074 sftp_fstatvfs(handle, st));
3075 return rc;
3076 }
3077
3078 /*
3079 * sftp_statvfs
3080 *
3081 * Get file system statistics
3082 */
sftp_statvfs(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len,LIBSSH2_SFTP_STATVFS * st)3083 static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path,
3084 unsigned int path_len, LIBSSH2_SFTP_STATVFS *st)
3085 {
3086 LIBSSH2_CHANNEL *channel = sftp->channel;
3087 LIBSSH2_SESSION *session = channel->session;
3088 size_t data_len;
3089 /* 17 = packet_len(4) + packet_type(1) + request_id(4) + ext_len(4)
3090 + path_len (4) */
3091 /* 19 = strlen ("statvfs@openssh.com") */
3092 uint32_t packet_len = path_len + 19 + 17;
3093 unsigned char *packet, *s, *data;
3094 ssize_t rc;
3095 unsigned int flag;
3096 static const unsigned char responses[2] =
3097 { SSH_FXP_EXTENDED_REPLY, SSH_FXP_STATUS };
3098
3099 if(sftp->statvfs_state == libssh2_NB_state_idle) {
3100 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
3101 "Getting file system statistics of %s", path);
3102 s = packet = LIBSSH2_ALLOC(session, packet_len);
3103 if(!packet) {
3104 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
3105 "Unable to allocate memory for FXP_EXTENDED "
3106 "packet");
3107 }
3108
3109 _libssh2_store_u32(&s, packet_len - 4);
3110 *(s++) = SSH_FXP_EXTENDED;
3111 sftp->statvfs_request_id = sftp->request_id++;
3112 _libssh2_store_u32(&s, sftp->statvfs_request_id);
3113 _libssh2_store_str(&s, "statvfs@openssh.com", 19);
3114 _libssh2_store_str(&s, path, path_len);
3115
3116 sftp->statvfs_state = libssh2_NB_state_created;
3117 }
3118 else {
3119 packet = sftp->statvfs_packet;
3120 }
3121
3122 if(sftp->statvfs_state == libssh2_NB_state_created) {
3123 rc = _libssh2_channel_write(channel, 0, packet, packet_len);
3124 if(rc == LIBSSH2_ERROR_EAGAIN ||
3125 (0 <= rc && rc < (ssize_t)packet_len)) {
3126 sftp->statvfs_packet = packet;
3127 return LIBSSH2_ERROR_EAGAIN;
3128 }
3129
3130 LIBSSH2_FREE(session, packet);
3131 sftp->statvfs_packet = NULL;
3132
3133 if(rc < 0) {
3134 sftp->statvfs_state = libssh2_NB_state_idle;
3135 return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
3136 "_libssh2_channel_write() failed");
3137 }
3138 sftp->statvfs_state = libssh2_NB_state_sent;
3139 }
3140
3141 rc = sftp_packet_requirev(sftp, 2, responses, sftp->statvfs_request_id,
3142 &data, &data_len, 9);
3143 if(rc == LIBSSH2_ERROR_EAGAIN) {
3144 return rc;
3145 }
3146 else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
3147 if(data_len > 0) {
3148 LIBSSH2_FREE(session, data);
3149 }
3150 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3151 "SFTP fstat packet too short");
3152 }
3153 else if(rc) {
3154 sftp->statvfs_state = libssh2_NB_state_idle;
3155 return _libssh2_error(session, rc,
3156 "Error waiting for FXP EXTENDED REPLY");
3157 }
3158
3159 if(data[0] == SSH_FXP_STATUS) {
3160 int retcode = _libssh2_ntohu32(data + 5);
3161 sftp->statvfs_state = libssh2_NB_state_idle;
3162 LIBSSH2_FREE(session, data);
3163 sftp->last_errno = retcode;
3164 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3165 "SFTP Protocol Error");
3166 }
3167
3168 if(data_len < 93) {
3169 LIBSSH2_FREE(session, data);
3170 sftp->statvfs_state = libssh2_NB_state_idle;
3171 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3172 "SFTP Protocol Error: short response");
3173 }
3174
3175 sftp->statvfs_state = libssh2_NB_state_idle;
3176
3177 st->f_bsize = _libssh2_ntohu64(data + 5);
3178 st->f_frsize = _libssh2_ntohu64(data + 13);
3179 st->f_blocks = _libssh2_ntohu64(data + 21);
3180 st->f_bfree = _libssh2_ntohu64(data + 29);
3181 st->f_bavail = _libssh2_ntohu64(data + 37);
3182 st->f_files = _libssh2_ntohu64(data + 45);
3183 st->f_ffree = _libssh2_ntohu64(data + 53);
3184 st->f_favail = _libssh2_ntohu64(data + 61);
3185 st->f_fsid = _libssh2_ntohu64(data + 69);
3186 flag = (unsigned int)_libssh2_ntohu64(data + 77);
3187 st->f_namemax = _libssh2_ntohu64(data + 85);
3188
3189 st->f_flag = (flag & SSH_FXE_STATVFS_ST_RDONLY)
3190 ? LIBSSH2_SFTP_ST_RDONLY : 0;
3191 st->f_flag |= (flag & SSH_FXE_STATVFS_ST_NOSUID)
3192 ? LIBSSH2_SFTP_ST_NOSUID : 0;
3193
3194 LIBSSH2_FREE(session, data);
3195 return 0;
3196 }
3197
3198 /* libssh2_sftp_statvfs_ex
3199 * Get filesystem space and inode utilization (requires statvfs@openssh.com
3200 * support on the server)
3201 */
3202 LIBSSH2_API int
libssh2_sftp_statvfs(LIBSSH2_SFTP * sftp,const char * path,size_t path_len,LIBSSH2_SFTP_STATVFS * st)3203 libssh2_sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path,
3204 size_t path_len, LIBSSH2_SFTP_STATVFS *st)
3205 {
3206 int rc;
3207 if(!sftp || !st)
3208 return LIBSSH2_ERROR_BAD_USE;
3209 BLOCK_ADJUST(rc, sftp->channel->session, sftp_statvfs(sftp, path, path_len,
3210 st));
3211 return rc;
3212 }
3213
3214
3215 /*
3216 * sftp_mkdir
3217 *
3218 * Create an SFTP directory
3219 */
sftp_mkdir(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len,long mode)3220 static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
3221 unsigned int path_len, long mode)
3222 {
3223 LIBSSH2_CHANNEL *channel = sftp->channel;
3224 LIBSSH2_SESSION *session = channel->session;
3225 LIBSSH2_SFTP_ATTRIBUTES attrs = {
3226 0, 0, 0, 0, 0, 0, 0
3227 };
3228 size_t data_len;
3229 int retcode;
3230 ssize_t packet_len;
3231 unsigned char *packet, *s, *data;
3232 int rc;
3233
3234 if(mode != LIBSSH2_SFTP_DEFAULT_MODE) {
3235 /* Filetype in SFTP 3 and earlier */
3236 attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
3237 attrs.permissions = mode | LIBSSH2_SFTP_ATTR_PFILETYPE_DIR;
3238 }
3239
3240 /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
3241 packet_len = path_len + 13 + sftp_attrsize(attrs.flags);
3242
3243 if(sftp->mkdir_state == libssh2_NB_state_idle) {
3244 _libssh2_debug(session, LIBSSH2_TRACE_SFTP,
3245 "Creating directory %s with mode 0%lo", path, mode);
3246 s = packet = LIBSSH2_ALLOC(session, packet_len);
3247 if(!packet) {
3248 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
3249 "Unable to allocate memory for FXP_MKDIR "
3250 "packet");
3251 }
3252
3253 _libssh2_store_u32(&s, packet_len - 4);
3254 *(s++) = SSH_FXP_MKDIR;
3255 sftp->mkdir_request_id = sftp->request_id++;
3256 _libssh2_store_u32(&s, sftp->mkdir_request_id);
3257 _libssh2_store_str(&s, path, path_len);
3258
3259 s += sftp_attr2bin(s, &attrs);
3260
3261 sftp->mkdir_state = libssh2_NB_state_created;
3262 }
3263 else {
3264 packet = sftp->mkdir_packet;
3265 }
3266
3267 if(sftp->mkdir_state == libssh2_NB_state_created) {
3268 rc = _libssh2_channel_write(channel, 0, packet, packet_len);
3269 if(rc == LIBSSH2_ERROR_EAGAIN) {
3270 sftp->mkdir_packet = packet;
3271 return rc;
3272 }
3273 if(packet_len != rc) {
3274 LIBSSH2_FREE(session, packet);
3275 sftp->mkdir_state = libssh2_NB_state_idle;
3276 return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
3277 "_libssh2_channel_write() failed");
3278 }
3279 LIBSSH2_FREE(session, packet);
3280 sftp->mkdir_state = libssh2_NB_state_sent;
3281 sftp->mkdir_packet = NULL;
3282 }
3283
3284 rc = sftp_packet_require(sftp, SSH_FXP_STATUS, sftp->mkdir_request_id,
3285 &data, &data_len, 9);
3286 if(rc == LIBSSH2_ERROR_EAGAIN) {
3287 return rc;
3288 }
3289 else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
3290 if(data_len > 0) {
3291 LIBSSH2_FREE(session, data);
3292 }
3293 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3294 "SFTP mkdir packet too short");
3295 }
3296 else if(rc) {
3297 sftp->mkdir_state = libssh2_NB_state_idle;
3298 return _libssh2_error(session, rc,
3299 "Error waiting for FXP STATUS");
3300 }
3301
3302 sftp->mkdir_state = libssh2_NB_state_idle;
3303
3304 retcode = _libssh2_ntohu32(data + 5);
3305 LIBSSH2_FREE(session, data);
3306
3307 if(retcode == LIBSSH2_FX_OK) {
3308 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "OK!");
3309 return 0;
3310 }
3311 else {
3312 sftp->last_errno = retcode;
3313 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3314 "SFTP Protocol Error");
3315 }
3316 }
3317
3318 /*
3319 * libssh2_sftp_mkdir_ex
3320 *
3321 * Create an SFTP directory
3322 */
3323 LIBSSH2_API int
libssh2_sftp_mkdir_ex(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len,long mode)3324 libssh2_sftp_mkdir_ex(LIBSSH2_SFTP *sftp, const char *path,
3325 unsigned int path_len, long mode)
3326 {
3327 int rc;
3328 if(!sftp)
3329 return LIBSSH2_ERROR_BAD_USE;
3330 BLOCK_ADJUST(rc, sftp->channel->session,
3331 sftp_mkdir(sftp, path, path_len, mode));
3332 return rc;
3333 }
3334
3335 /* sftp_rmdir
3336 * Remove a directory
3337 */
sftp_rmdir(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len)3338 static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path,
3339 unsigned int path_len)
3340 {
3341 LIBSSH2_CHANNEL *channel = sftp->channel;
3342 LIBSSH2_SESSION *session = channel->session;
3343 size_t data_len;
3344 int retcode;
3345 /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
3346 ssize_t packet_len = path_len + 13;
3347 unsigned char *s, *data;
3348 int rc;
3349
3350 if(sftp->rmdir_state == libssh2_NB_state_idle) {
3351 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Removing directory: %s",
3352 path);
3353 s = sftp->rmdir_packet = LIBSSH2_ALLOC(session, packet_len);
3354 if(!sftp->rmdir_packet) {
3355 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
3356 "Unable to allocate memory for FXP_RMDIR "
3357 "packet");
3358 }
3359
3360 _libssh2_store_u32(&s, packet_len - 4);
3361 *(s++) = SSH_FXP_RMDIR;
3362 sftp->rmdir_request_id = sftp->request_id++;
3363 _libssh2_store_u32(&s, sftp->rmdir_request_id);
3364 _libssh2_store_str(&s, path, path_len);
3365
3366 sftp->rmdir_state = libssh2_NB_state_created;
3367 }
3368
3369 if(sftp->rmdir_state == libssh2_NB_state_created) {
3370 rc = _libssh2_channel_write(channel, 0, sftp->rmdir_packet,
3371 packet_len);
3372 if(rc == LIBSSH2_ERROR_EAGAIN) {
3373 return rc;
3374 }
3375 else if(packet_len != rc) {
3376 LIBSSH2_FREE(session, sftp->rmdir_packet);
3377 sftp->rmdir_packet = NULL;
3378 sftp->rmdir_state = libssh2_NB_state_idle;
3379 return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
3380 "Unable to send FXP_RMDIR command");
3381 }
3382 LIBSSH2_FREE(session, sftp->rmdir_packet);
3383 sftp->rmdir_packet = NULL;
3384
3385 sftp->rmdir_state = libssh2_NB_state_sent;
3386 }
3387
3388 rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
3389 sftp->rmdir_request_id, &data, &data_len, 9);
3390 if(rc == LIBSSH2_ERROR_EAGAIN) {
3391 return rc;
3392 }
3393 else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
3394 if(data_len > 0) {
3395 LIBSSH2_FREE(session, data);
3396 }
3397 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3398 "SFTP rmdir packet too short");
3399 }
3400 else if(rc) {
3401 sftp->rmdir_state = libssh2_NB_state_idle;
3402 return _libssh2_error(session, rc,
3403 "Error waiting for FXP STATUS");
3404 }
3405
3406 sftp->rmdir_state = libssh2_NB_state_idle;
3407
3408 retcode = _libssh2_ntohu32(data + 5);
3409 LIBSSH2_FREE(session, data);
3410
3411 if(retcode == LIBSSH2_FX_OK) {
3412 return 0;
3413 }
3414 else {
3415 sftp->last_errno = retcode;
3416 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3417 "SFTP Protocol Error");
3418 }
3419 }
3420
3421 /* libssh2_sftp_rmdir_ex
3422 * Remove a directory
3423 */
3424 LIBSSH2_API int
libssh2_sftp_rmdir_ex(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len)3425 libssh2_sftp_rmdir_ex(LIBSSH2_SFTP *sftp, const char *path,
3426 unsigned int path_len)
3427 {
3428 int rc;
3429 if(!sftp)
3430 return LIBSSH2_ERROR_BAD_USE;
3431 BLOCK_ADJUST(rc, sftp->channel->session,
3432 sftp_rmdir(sftp, path, path_len));
3433 return rc;
3434 }
3435
3436 /* sftp_stat
3437 * Stat a file or symbolic link
3438 */
sftp_stat(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len,int stat_type,LIBSSH2_SFTP_ATTRIBUTES * attrs)3439 static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
3440 unsigned int path_len, int stat_type,
3441 LIBSSH2_SFTP_ATTRIBUTES * attrs)
3442 {
3443 LIBSSH2_CHANNEL *channel = sftp->channel;
3444 LIBSSH2_SESSION *session = channel->session;
3445 size_t data_len;
3446 /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
3447 ssize_t packet_len =
3448 path_len + 13 +
3449 ((stat_type ==
3450 LIBSSH2_SFTP_SETSTAT) ? sftp_attrsize(attrs->flags) : 0);
3451 unsigned char *s, *data;
3452 static const unsigned char stat_responses[2] =
3453 { SSH_FXP_ATTRS, SSH_FXP_STATUS };
3454 int rc;
3455
3456 if(sftp->stat_state == libssh2_NB_state_idle) {
3457 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%s %s",
3458 (stat_type == LIBSSH2_SFTP_SETSTAT) ? "Set-statting" :
3459 (stat_type ==
3460 LIBSSH2_SFTP_LSTAT ? "LStatting" : "Statting"), path);
3461 s = sftp->stat_packet = LIBSSH2_ALLOC(session, packet_len);
3462 if(!sftp->stat_packet) {
3463 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
3464 "Unable to allocate memory for FXP_*STAT "
3465 "packet");
3466 }
3467
3468 _libssh2_store_u32(&s, packet_len - 4);
3469
3470 switch(stat_type) {
3471 case LIBSSH2_SFTP_SETSTAT:
3472 *(s++) = SSH_FXP_SETSTAT;
3473 break;
3474
3475 case LIBSSH2_SFTP_LSTAT:
3476 *(s++) = SSH_FXP_LSTAT;
3477 break;
3478
3479 case LIBSSH2_SFTP_STAT:
3480 default:
3481 *(s++) = SSH_FXP_STAT;
3482 }
3483 sftp->stat_request_id = sftp->request_id++;
3484 _libssh2_store_u32(&s, sftp->stat_request_id);
3485 _libssh2_store_str(&s, path, path_len);
3486
3487 if(stat_type == LIBSSH2_SFTP_SETSTAT)
3488 s += sftp_attr2bin(s, attrs);
3489
3490 sftp->stat_state = libssh2_NB_state_created;
3491 }
3492
3493 if(sftp->stat_state == libssh2_NB_state_created) {
3494 rc = _libssh2_channel_write(channel, 0, sftp->stat_packet, packet_len);
3495 if(rc == LIBSSH2_ERROR_EAGAIN) {
3496 return rc;
3497 }
3498 else if(packet_len != rc) {
3499 LIBSSH2_FREE(session, sftp->stat_packet);
3500 sftp->stat_packet = NULL;
3501 sftp->stat_state = libssh2_NB_state_idle;
3502 return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
3503 "Unable to send STAT/LSTAT/SETSTAT command");
3504 }
3505 LIBSSH2_FREE(session, sftp->stat_packet);
3506 sftp->stat_packet = NULL;
3507
3508 sftp->stat_state = libssh2_NB_state_sent;
3509 }
3510
3511 rc = sftp_packet_requirev(sftp, 2, stat_responses,
3512 sftp->stat_request_id, &data, &data_len, 9);
3513 if(rc == LIBSSH2_ERROR_EAGAIN)
3514 return rc;
3515 else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
3516 if(data_len > 0) {
3517 LIBSSH2_FREE(session, data);
3518 }
3519 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3520 "SFTP stat packet too short");
3521 }
3522 else if(rc) {
3523 sftp->stat_state = libssh2_NB_state_idle;
3524 return _libssh2_error(session, rc,
3525 "Timeout waiting for status message");
3526 }
3527
3528 sftp->stat_state = libssh2_NB_state_idle;
3529
3530 if(data[0] == SSH_FXP_STATUS) {
3531 int retcode;
3532
3533 retcode = _libssh2_ntohu32(data + 5);
3534 LIBSSH2_FREE(session, data);
3535 if(retcode == LIBSSH2_FX_OK) {
3536 memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
3537 return 0;
3538 }
3539 else {
3540 sftp->last_errno = retcode;
3541 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3542 "SFTP Protocol Error");
3543 }
3544 }
3545
3546 memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
3547 if(sftp_bin2attr(attrs, data + 5, data_len - 5) < 0) {
3548 LIBSSH2_FREE(session, data);
3549 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3550 "Attributes too short in SFTP fstat");
3551 }
3552
3553 LIBSSH2_FREE(session, data);
3554
3555 return 0;
3556 }
3557
3558 /* libssh2_sftp_stat_ex
3559 * Stat a file or symbolic link
3560 */
3561 LIBSSH2_API int
libssh2_sftp_stat_ex(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len,int stat_type,LIBSSH2_SFTP_ATTRIBUTES * attrs)3562 libssh2_sftp_stat_ex(LIBSSH2_SFTP *sftp, const char *path,
3563 unsigned int path_len, int stat_type,
3564 LIBSSH2_SFTP_ATTRIBUTES *attrs)
3565 {
3566 int rc;
3567 if(!sftp)
3568 return LIBSSH2_ERROR_BAD_USE;
3569 BLOCK_ADJUST(rc, sftp->channel->session,
3570 sftp_stat(sftp, path, path_len, stat_type, attrs));
3571 return rc;
3572 }
3573
3574 /* sftp_symlink
3575 * Read or set a symlink
3576 */
sftp_symlink(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len,char * target,unsigned int target_len,int link_type)3577 static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
3578 unsigned int path_len, char *target,
3579 unsigned int target_len, int link_type)
3580 {
3581 LIBSSH2_CHANNEL *channel = sftp->channel;
3582 LIBSSH2_SESSION *session = channel->session;
3583 size_t data_len, link_len;
3584 /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
3585 ssize_t packet_len =
3586 path_len + 13 +
3587 ((link_type == LIBSSH2_SFTP_SYMLINK) ? (4 + target_len) : 0);
3588 unsigned char *s, *data;
3589 static const unsigned char link_responses[2] =
3590 { SSH_FXP_NAME, SSH_FXP_STATUS };
3591 int retcode;
3592
3593 if((sftp->version < 3) && (link_type != LIBSSH2_SFTP_REALPATH)) {
3594 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3595 "Server does not support SYMLINK or READLINK");
3596 }
3597
3598 if(sftp->symlink_state == libssh2_NB_state_idle) {
3599 s = sftp->symlink_packet = LIBSSH2_ALLOC(session, packet_len);
3600 if(!sftp->symlink_packet) {
3601 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
3602 "Unable to allocate memory for "
3603 "SYMLINK/READLINK/REALPATH packet");
3604 }
3605
3606 _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "%s %s on %s",
3607 (link_type ==
3608 LIBSSH2_SFTP_SYMLINK) ? "Creating" : "Reading",
3609 (link_type ==
3610 LIBSSH2_SFTP_REALPATH) ? "realpath" : "symlink", path);
3611
3612 _libssh2_store_u32(&s, packet_len - 4);
3613
3614 switch(link_type) {
3615 case LIBSSH2_SFTP_REALPATH:
3616 *(s++) = SSH_FXP_REALPATH;
3617 break;
3618
3619 case LIBSSH2_SFTP_SYMLINK:
3620 *(s++) = SSH_FXP_SYMLINK;
3621 break;
3622
3623 case LIBSSH2_SFTP_READLINK:
3624 default:
3625 *(s++) = SSH_FXP_READLINK;
3626 }
3627 sftp->symlink_request_id = sftp->request_id++;
3628 _libssh2_store_u32(&s, sftp->symlink_request_id);
3629 _libssh2_store_str(&s, path, path_len);
3630
3631 if(link_type == LIBSSH2_SFTP_SYMLINK)
3632 _libssh2_store_str(&s, target, target_len);
3633
3634 sftp->symlink_state = libssh2_NB_state_created;
3635 }
3636
3637 if(sftp->symlink_state == libssh2_NB_state_created) {
3638 ssize_t rc = _libssh2_channel_write(channel, 0, sftp->symlink_packet,
3639 packet_len);
3640 if(rc == LIBSSH2_ERROR_EAGAIN)
3641 return rc;
3642 else if(packet_len != rc) {
3643 LIBSSH2_FREE(session, sftp->symlink_packet);
3644 sftp->symlink_packet = NULL;
3645 sftp->symlink_state = libssh2_NB_state_idle;
3646 return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
3647 "Unable to send SYMLINK/READLINK command");
3648 }
3649 LIBSSH2_FREE(session, sftp->symlink_packet);
3650 sftp->symlink_packet = NULL;
3651
3652 sftp->symlink_state = libssh2_NB_state_sent;
3653 }
3654
3655 retcode = sftp_packet_requirev(sftp, 2, link_responses,
3656 sftp->symlink_request_id, &data,
3657 &data_len, 9);
3658 if(retcode == LIBSSH2_ERROR_EAGAIN)
3659 return retcode;
3660 else if(retcode == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
3661 if(data_len > 0) {
3662 LIBSSH2_FREE(session, data);
3663 }
3664 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3665 "SFTP symlink packet too short");
3666 }
3667 else if(retcode) {
3668 sftp->symlink_state = libssh2_NB_state_idle;
3669 return _libssh2_error(session, retcode,
3670 "Error waiting for status message");
3671 }
3672
3673 sftp->symlink_state = libssh2_NB_state_idle;
3674
3675 if(data[0] == SSH_FXP_STATUS) {
3676 retcode = _libssh2_ntohu32(data + 5);
3677 LIBSSH2_FREE(session, data);
3678 if(retcode == LIBSSH2_FX_OK)
3679 return LIBSSH2_ERROR_NONE;
3680 else {
3681 sftp->last_errno = retcode;
3682 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3683 "SFTP Protocol Error");
3684 }
3685 }
3686
3687 if(_libssh2_ntohu32(data + 5) < 1) {
3688 LIBSSH2_FREE(session, data);
3689 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3690 "Invalid READLINK/REALPATH response, "
3691 "no name entries");
3692 }
3693
3694 if(data_len < 13) {
3695 if(data_len > 0) {
3696 LIBSSH2_FREE(session, data);
3697 }
3698 return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
3699 "SFTP stat packet too short");
3700 }
3701
3702 /* this reads a u32 and stores it into a signed 32bit value */
3703 link_len = _libssh2_ntohu32(data + 9);
3704 if(link_len < target_len) {
3705 memcpy(target, data + 13, link_len);
3706 target[link_len] = 0;
3707 retcode = (int)link_len;
3708 }
3709 else
3710 retcode = LIBSSH2_ERROR_BUFFER_TOO_SMALL;
3711 LIBSSH2_FREE(session, data);
3712
3713 return retcode;
3714 }
3715
3716 /* libssh2_sftp_symlink_ex
3717 * Read or set a symlink
3718 */
3719 LIBSSH2_API int
libssh2_sftp_symlink_ex(LIBSSH2_SFTP * sftp,const char * path,unsigned int path_len,char * target,unsigned int target_len,int link_type)3720 libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, const char *path,
3721 unsigned int path_len, char *target,
3722 unsigned int target_len, int link_type)
3723 {
3724 int rc;
3725 if(!sftp)
3726 return LIBSSH2_ERROR_BAD_USE;
3727 BLOCK_ADJUST(rc, sftp->channel->session,
3728 sftp_symlink(sftp, path, path_len, target, target_len,
3729 link_type));
3730 return rc;
3731 }
3732
3733 /* libssh2_sftp_last_error
3734 * Returns the last error code reported by SFTP
3735 */
3736 LIBSSH2_API unsigned long
libssh2_sftp_last_error(LIBSSH2_SFTP * sftp)3737 libssh2_sftp_last_error(LIBSSH2_SFTP *sftp)
3738 {
3739 if(!sftp)
3740 return 0;
3741
3742 return sftp->last_errno;
3743 }
3744
3745 /* libssh2_sftp_get_channel
3746 * Return the channel of sftp, then caller can control the channel's behavior.
3747 */
3748 LIBSSH2_API LIBSSH2_CHANNEL *
libssh2_sftp_get_channel(LIBSSH2_SFTP * sftp)3749 libssh2_sftp_get_channel(LIBSSH2_SFTP *sftp)
3750 {
3751 if(!sftp)
3752 return NULL;
3753
3754 return sftp->channel;
3755 }
3756