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