5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "silcincludes.h"
23 #include "sftp_util.h"
25 /* Request context. Every request will allocate this context and set
26 the correct callback function according the `type' field. */
27 typedef struct SilcSFTPRequestStruct {
30 SilcSFTPStatusCallback status;
31 SilcSFTPHandleCallback handle;
32 SilcSFTPDataCallback data;
33 SilcSFTPNameCallback name;
34 SilcSFTPAttrCallback attr;
35 SilcSFTPExtendedCallback extended;
37 struct SilcSFTPRequestStruct *next;
40 /* SFTP client context */
42 SilcSocketConnection sock;
43 SilcSFTPSendPacketCallback send_packet;
45 SilcSFTPVersionCallback version;
46 void *version_context;
53 struct SilcSFTPHandleStruct {
58 /* Creates SilcSFTPHandle and returns pointer to it. The caller must free
61 static SilcSFTPHandle silc_sftp_handle_create(unsigned char *data,
64 SilcSFTPHandle handle;
66 handle = silc_calloc(1, sizeof(*handle));
67 handle->data = silc_calloc(data_len, sizeof(*handle->data));
68 memcpy(handle->data, data, data_len);
69 handle->data_len = data_len;
74 /* Deletes the handle indicated by the `handle'. */
76 static void silc_sftp_handle_delete(SilcSFTPHandle handle)
78 silc_free(handle->data);
82 /* Returns the handle data of the `handle' to the `data' pointer. */
84 static void silc_sftp_handle_get(SilcSFTPHandle handle,
85 const unsigned char **data,
88 *data = (const unsigned char *)handle->data;
89 *data_len = handle->data_len;
92 /* General routine to send SFTP packet to the SFTP server. */
94 static void silc_sftp_send_packet(SilcSFTPClient sftp,
102 tmp = silc_sftp_packet_encode_vp(type, sftp->packet, len, vp);
108 SILC_LOG_HEXDUMP(("SFTP packet to server"), sftp->packet->data,
111 /* Send the packet */
112 (*sftp->send_packet)(sftp->sock, sftp->packet, sftp->send_context);
115 sftp->packet->data = sftp->packet->tail = sftp->packet->head;
116 sftp->packet->len = 0;
119 /* Finds request by request ID. */
121 static SilcSFTPRequest silc_sftp_find_request(SilcSFTPClient sftp, SilcUInt32 id)
125 SILC_LOG_DEBUG(("Finding request ID: %d", id));
127 silc_list_start(sftp->requests);
128 while ((req = silc_list_get(sftp->requests)) != SILC_LIST_END) {
133 SILC_LOG_DEBUG(("Unknown request ID"));
138 /* Function used to call the request callback indicated by the `req'. The
139 `status' will be sent to the callback function as the status of the
140 operation. The variable argument list includes the status and req->type
143 static void silc_sftp_call_request(SilcSFTPClient sftp,
146 SilcSFTPStatus status, ...)
150 SILC_LOG_DEBUG(("Start"));
152 va_start(vp, status);
161 if (status != SILC_SFTP_STATUS_OK) {
163 (*req->data)((SilcSFTP)sftp, status, NULL, 0, req->context);
167 data = (unsigned char *)va_arg(vp, unsigned char *);
168 data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
171 (*req->data)((SilcSFTP)sftp, status, (const unsigned char *)data,
172 data_len, req->context);
177 case SILC_SFTP_OPENDIR:
179 /* Handle returned */
180 SilcSFTPHandle handle;
181 unsigned char *hdata;
182 SilcUInt32 hdata_len;
184 if (status != SILC_SFTP_STATUS_OK) {
186 (*req->handle)((SilcSFTP)sftp, status, NULL, req->context);
190 hdata = (unsigned char *)va_arg(vp, unsigned char *);
191 hdata_len = (SilcUInt32)va_arg(vp, SilcUInt32);
192 handle = silc_sftp_handle_create(hdata, hdata_len);
195 (*req->handle)((SilcSFTP)sftp, status, handle, req->context);
199 case SILC_SFTP_CLOSE:
200 case SILC_SFTP_WRITE:
201 case SILC_SFTP_REMOVE:
202 case SILC_SFTP_RENAME:
203 case SILC_SFTP_MKDIR:
204 case SILC_SFTP_RMDIR:
205 case SILC_SFTP_SETSTAT:
206 case SILC_SFTP_FSETSTAT:
207 case SILC_SFTP_SYMLINK:
209 /* Status returned */
210 char *message, *language_tag;
212 message = (char *)va_arg(vp, char *);
213 language_tag = (char *)va_arg(vp, char *);
216 (*req->status)((SilcSFTP)sftp, status, (const char *)message,
217 (const char *)language_tag, req->context);
222 case SILC_SFTP_LSTAT:
223 case SILC_SFTP_FSTAT:
225 /* Attributes returned */
226 SilcSFTPAttributes attr;
228 if (status != SILC_SFTP_STATUS_OK) {
230 (*req->attr)((SilcSFTP)sftp, status, NULL, req->context);
234 attr = (SilcSFTPAttributes)va_arg(vp, SilcSFTPAttributes);
237 (*req->attr)((SilcSFTP)sftp, status, (const SilcSFTPAttributes)attr,
242 case SILC_SFTP_READDIR:
243 case SILC_SFTP_REALPATH:
244 case SILC_SFTP_READLINK:
246 /* Name(s) returned */
249 if (status != SILC_SFTP_STATUS_OK) {
251 (*req->name)((SilcSFTP)sftp, status, NULL, req->context);
255 name = (SilcSFTPName)va_arg(vp, SilcSFTPName);
258 (*req->name)((SilcSFTP)sftp, status, name, req->context);
262 case SILC_SFTP_EXTENDED:
264 /* Extended reply returned */
268 if (status != SILC_SFTP_STATUS_OK) {
270 (*req->extended)((SilcSFTP)sftp, status, NULL, 0, req->context);
274 data = (unsigned char *)va_arg(vp, unsigned char *);
275 data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
278 (*req->extended)((SilcSFTP)sftp, status, (const unsigned char *)data,
279 data_len, req->context);
287 /* Remove this request */
288 silc_list_del(sftp->requests, req);
294 /* Starts SFTP client by associating the socket connection `sock' to the
295 created SFTP client context. The version callback indicated by the
296 `callback' will be called after the SFTP session has been started
297 and server has returned the version of the protocol. The SFTP client
298 context is returned in the callback too. This returns the allocated
299 SFTP client context or NULL on error. */
301 SilcSFTP silc_sftp_client_start(SilcSocketConnection sock,
302 SilcSFTPSendPacketCallback send_packet,
304 SilcSFTPVersionCallback callback,
312 sftp = silc_calloc(1, sizeof(*sftp));
314 sftp->send_packet = send_packet;
315 sftp->send_context = send_context;
316 sftp->version = callback;
317 sftp->version_context = context;
318 silc_list_init(sftp->requests, struct SilcSFTPRequestStruct, next);
320 /* Send the SFTP session initialization to the server */
321 silc_sftp_send_packet(sftp, SILC_SFTP_INIT, 4,
322 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
325 return (SilcSFTP)sftp;
328 /* Shutdown's the SFTP client. The caller is responsible of closing
329 the associated socket connection. The SFTP context is freed and is
330 invalid after this function returns. */
332 void silc_sftp_client_shutdown(SilcSFTP context)
334 SilcSFTPClient sftp = (SilcSFTPClient)context;
337 silc_buffer_free(sftp->packet);
341 /* Function that is called to process the incmoing SFTP packet. */
342 /* XXX Some day this will go away and we have automatic receive callbacks
343 for SilcSocketConnection API or SilcPacketContext API. */
345 void silc_sftp_client_receive_process(SilcSFTP context,
346 SilcSocketConnection sock,
347 SilcPacketContext *packet)
349 SilcSFTPClient sftp = (SilcSFTPClient)context;
352 const unsigned char *payload = NULL;
353 SilcUInt32 payload_len;
355 SilcBufferStruct buf;
358 SILC_LOG_DEBUG(("Start"));
360 /* Parse the packet */
361 type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload,
366 silc_buffer_set(&buf, (unsigned char *)payload, payload_len);
369 case SILC_SFTP_VERSION:
371 SilcSFTPVersion version;
373 SILC_LOG_DEBUG(("Version packet"));
375 ret = silc_buffer_unformat(&buf,
376 SILC_STR_UI_INT(&version),
379 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_FAILURE, 0,
380 sftp->version_context);
384 /* Call the callback */
385 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_OK, version,
386 sftp->version_context);
390 case SILC_SFTP_STATUS:
393 char *message = NULL, *language_tag = NULL;
395 SILC_LOG_DEBUG(("Status packet"));
397 ret = silc_buffer_unformat(&buf,
398 SILC_STR_UI_INT(&id),
399 SILC_STR_UI_INT(&status),
404 if (status != SILC_SFTP_STATUS_OK) {
405 silc_buffer_pull(&buf, 8);
406 ret = silc_buffer_unformat(&buf,
407 SILC_STR_UI32_STRING_ALLOC(&message),
408 SILC_STR_UI32_STRING_ALLOC(&language_tag),
413 silc_buffer_push(&buf, 8);
417 req = silc_sftp_find_request(sftp, id);
420 silc_free(language_tag);
424 /* Call the callback */
425 silc_sftp_call_request(sftp, req, type, status, message, language_tag);
428 silc_free(language_tag);
432 case SILC_SFTP_HANDLE:
434 unsigned char *handle = NULL;
435 SilcUInt32 handle_len;
437 SILC_LOG_DEBUG(("Handle packet"));
439 ret = silc_buffer_unformat(&buf,
440 SILC_STR_UI_INT(&id),
441 SILC_STR_UI32_NSTRING(&handle,
448 req = silc_sftp_find_request(sftp, id);
452 /* Call the callback */
453 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
460 unsigned char *data = NULL;
461 SilcUInt32 data_len = 0;
463 SILC_LOG_DEBUG(("Data packet"));
465 ret = silc_buffer_unformat(&buf,
466 SILC_STR_UI_INT(&id),
467 SILC_STR_UI32_NSTRING(&data, &data_len),
473 req = silc_sftp_find_request(sftp, id);
477 /* Call the callback */
478 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
486 SilcSFTPName name = NULL;
488 SILC_LOG_DEBUG(("Name packet"));
490 ret = silc_buffer_unformat(&buf,
491 SILC_STR_UI_INT(&id),
492 SILC_STR_UI_INT(&count),
498 req = silc_sftp_find_request(sftp, id);
502 silc_buffer_pull(&buf, 8);
503 name = silc_sftp_name_decode(count, &buf);
506 silc_buffer_push(&buf, 8);
508 /* Call the callback */
509 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, name);
510 silc_sftp_name_free(name);
514 case SILC_SFTP_ATTRS:
516 SilcSFTPAttributes attr = NULL;
518 SilcBufferStruct tmpbuf;
520 SILC_LOG_DEBUG(("Attributes packet"));
522 ret = silc_buffer_unformat(&buf,
523 SILC_STR_UI_INT(&id),
524 SILC_STR_UI_XNSTRING(&data, buf.len - 4),
530 req = silc_sftp_find_request(sftp, id);
534 silc_buffer_set(&tmpbuf, data, buf.len - 4);
535 attr = silc_sftp_attr_decode(&tmpbuf);
539 /* Call the callback */
540 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, attr);
544 case SILC_SFTP_EXTENDED_REPLY:
546 unsigned char *data = NULL;
548 SILC_LOG_DEBUG(("Extended reply packet"));
550 ret = silc_buffer_unformat(&buf,
551 SILC_STR_UI_INT(&id),
552 SILC_STR_UI_XNSTRING(&data, buf.len - 4),
558 req = silc_sftp_find_request(sftp, id);
562 /* Call the callback */
563 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
573 void silc_sftp_open(SilcSFTP sftp,
574 const char *filename,
575 SilcSFTPFileOperation pflags,
576 SilcSFTPAttributes attrs,
577 SilcSFTPHandleCallback callback,
580 SilcSFTPClient client = (SilcSFTPClient)sftp;
582 SilcBuffer attrs_buf;
585 SILC_LOG_DEBUG(("Open request"));
587 req = silc_calloc(1, sizeof(*req));
588 req->id = client->id++;
589 req->type = SILC_SFTP_OPEN;
590 req->handle = callback;
591 req->context = context;
592 silc_list_add(client->requests, req);
594 attrs_buf = silc_sftp_attr_encode(attrs);
595 len = 4 + 4 + strlen(filename) + 4 + attrs_buf->len;
597 silc_sftp_send_packet(client, req->type, len,
598 SILC_STR_UI_INT(req->id),
599 SILC_STR_UI_INT(strlen(filename)),
600 SILC_STR_UI32_STRING(filename),
601 SILC_STR_UI_INT(pflags),
602 SILC_STR_UI_XNSTRING(attrs_buf->data,
606 silc_buffer_free(attrs_buf);
609 void silc_sftp_close(SilcSFTP sftp,
610 SilcSFTPHandle handle,
611 SilcSFTPStatusCallback callback,
614 SilcSFTPClient client = (SilcSFTPClient)sftp;
617 const unsigned char *hdata;
618 SilcUInt32 hdata_len;
620 SILC_LOG_DEBUG(("Close request"));
622 req = silc_calloc(1, sizeof(*req));
623 req->id = client->id++;
624 req->type = SILC_SFTP_CLOSE;
625 req->status = callback;
626 req->context = context;
627 silc_list_add(client->requests, req);
629 silc_sftp_handle_get(handle, &hdata, &hdata_len);
630 len = 4 + 4 + hdata_len;
632 silc_sftp_send_packet(client, req->type, len,
633 SILC_STR_UI_INT(req->id),
634 SILC_STR_UI_INT(hdata_len),
635 SILC_STR_UI_XNSTRING(hdata, hdata_len),
639 void silc_sftp_read(SilcSFTP sftp,
640 SilcSFTPHandle handle,
643 SilcSFTPDataCallback callback,
646 SilcSFTPClient client = (SilcSFTPClient)sftp;
649 const unsigned char *hdata;
650 SilcUInt32 hdata_len;
652 SILC_LOG_DEBUG(("Read request"));
654 req = silc_calloc(1, sizeof(*req));
655 req->id = client->id++;
656 req->type = SILC_SFTP_READ;
657 req->data = callback;
658 req->context = context;
659 silc_list_add(client->requests, req);
661 silc_sftp_handle_get(handle, &hdata, &hdata_len);
662 len2 = 4 + 4 + hdata_len + 8 + 4;
664 silc_sftp_send_packet(client, req->type, len2,
665 SILC_STR_UI_INT(req->id),
666 SILC_STR_UI_INT(hdata_len),
667 SILC_STR_UI_XNSTRING(hdata, hdata_len),
668 SILC_STR_UI_INT64(offset),
669 SILC_STR_UI_INT(len),
673 void silc_sftp_write(SilcSFTP sftp,
674 SilcSFTPHandle handle,
676 const unsigned char *data,
678 SilcSFTPStatusCallback callback,
681 SilcSFTPClient client = (SilcSFTPClient)sftp;
684 const unsigned char *hdata;
685 SilcUInt32 hdata_len;
687 SILC_LOG_DEBUG(("Write request"));
689 req = silc_calloc(1, sizeof(*req));
690 req->id = client->id++;
691 req->type = SILC_SFTP_WRITE;
692 req->status = callback;
693 req->context = context;
694 silc_list_add(client->requests, req);
696 silc_sftp_handle_get(handle, &hdata, &hdata_len);
697 len = 4 + 4 + hdata_len + 8 + 4 + data_len;
699 silc_sftp_send_packet(client, req->type, len,
700 SILC_STR_UI_INT(req->id),
701 SILC_STR_UI_INT(hdata_len),
702 SILC_STR_UI_XNSTRING(hdata, hdata_len),
703 SILC_STR_UI_INT64(offset),
704 SILC_STR_UI_INT(data_len),
705 SILC_STR_UI_XNSTRING(data, data_len),
709 void silc_sftp_remove(SilcSFTP sftp,
710 const char *filename,
711 SilcSFTPStatusCallback callback,
714 SilcSFTPClient client = (SilcSFTPClient)sftp;
718 SILC_LOG_DEBUG(("Remove request"));
720 req = silc_calloc(1, sizeof(*req));
721 req->id = client->id++;
722 req->type = SILC_SFTP_REMOVE;
723 req->status = callback;
724 req->context = context;
725 silc_list_add(client->requests, req);
727 len = 4 + 4 + strlen(filename);
729 silc_sftp_send_packet(client, req->type, len,
730 SILC_STR_UI_INT(req->id),
731 SILC_STR_UI_INT(strlen(filename)),
732 SILC_STR_UI32_STRING(filename),
736 void silc_sftp_rename(SilcSFTP sftp,
739 SilcSFTPStatusCallback callback,
742 SilcSFTPClient client = (SilcSFTPClient)sftp;
746 SILC_LOG_DEBUG(("Rename request"));
748 req = silc_calloc(1, sizeof(*req));
749 req->id = client->id++;
750 req->type = SILC_SFTP_RENAME;
751 req->status = callback;
752 req->context = context;
753 silc_list_add(client->requests, req);
755 len = 4 + 4 + strlen(oldname) + 4 + strlen(newname);
757 silc_sftp_send_packet(client, req->type, len,
758 SILC_STR_UI_INT(req->id),
759 SILC_STR_UI_INT(strlen(oldname)),
760 SILC_STR_UI32_STRING(oldname),
761 SILC_STR_UI_INT(strlen(newname)),
762 SILC_STR_UI32_STRING(newname),
766 void silc_sftp_mkdir(SilcSFTP sftp,
768 SilcSFTPAttributes attrs,
769 SilcSFTPStatusCallback callback,
772 SilcSFTPClient client = (SilcSFTPClient)sftp;
775 SilcBuffer attrs_buf;
777 SILC_LOG_DEBUG(("Mkdir request"));
779 req = silc_calloc(1, sizeof(*req));
780 req->id = client->id++;
781 req->type = SILC_SFTP_MKDIR;
782 req->status = callback;
783 req->context = context;
784 silc_list_add(client->requests, req);
786 attrs_buf = silc_sftp_attr_encode(attrs);
787 len = 4 + 4 + strlen(path) + attrs_buf->len;
789 silc_sftp_send_packet(client, req->type, len,
790 SILC_STR_UI_INT(req->id),
791 SILC_STR_UI_INT(strlen(path)),
792 SILC_STR_UI32_STRING(path),
793 SILC_STR_UI_XNSTRING(attrs_buf->data,
797 silc_buffer_free(attrs_buf);
800 void silc_sftp_rmdir(SilcSFTP sftp,
802 SilcSFTPStatusCallback callback,
805 SilcSFTPClient client = (SilcSFTPClient)sftp;
809 SILC_LOG_DEBUG(("Rmdir request"));
811 req = silc_calloc(1, sizeof(*req));
812 req->id = client->id++;
813 req->type = SILC_SFTP_RMDIR;
814 req->status = callback;
815 req->context = context;
816 silc_list_add(client->requests, req);
818 len = 4 + 4 + strlen(path);
820 silc_sftp_send_packet(client, req->type, len,
821 SILC_STR_UI_INT(req->id),
822 SILC_STR_UI_INT(strlen(path)),
823 SILC_STR_UI32_STRING(path),
827 void silc_sftp_opendir(SilcSFTP sftp,
829 SilcSFTPHandleCallback callback,
832 SilcSFTPClient client = (SilcSFTPClient)sftp;
836 SILC_LOG_DEBUG(("Opendir request"));
838 req = silc_calloc(1, sizeof(*req));
839 req->id = client->id++;
840 req->type = SILC_SFTP_OPENDIR;
841 req->handle = callback;
842 req->context = context;
843 silc_list_add(client->requests, req);
845 len = 4 + 4 + strlen(path);
847 silc_sftp_send_packet(client, req->type, len,
848 SILC_STR_UI_INT(req->id),
849 SILC_STR_UI_INT(strlen(path)),
850 SILC_STR_UI32_STRING(path),
854 void silc_sftp_readdir(SilcSFTP sftp,
855 SilcSFTPHandle handle,
856 SilcSFTPNameCallback callback,
859 SilcSFTPClient client = (SilcSFTPClient)sftp;
862 const unsigned char *hdata;
863 SilcUInt32 hdata_len;
865 SILC_LOG_DEBUG(("Readdir request"));
867 req = silc_calloc(1, sizeof(*req));
868 req->id = client->id++;
869 req->type = SILC_SFTP_READDIR;
870 req->name = callback;
871 req->context = context;
872 silc_list_add(client->requests, req);
874 silc_sftp_handle_get(handle, &hdata, &hdata_len);
875 len = 4 + 4 + hdata_len;
877 silc_sftp_send_packet(client, req->type, len,
878 SILC_STR_UI_INT(req->id),
879 SILC_STR_UI_INT(hdata_len),
880 SILC_STR_UI_XNSTRING(hdata, hdata_len),
884 void silc_sftp_stat(SilcSFTP sftp,
886 SilcSFTPAttrCallback callback,
889 SilcSFTPClient client = (SilcSFTPClient)sftp;
893 SILC_LOG_DEBUG(("Stat request"));
895 req = silc_calloc(1, sizeof(*req));
896 req->id = client->id++;
897 req->type = SILC_SFTP_STAT;
898 req->attr = callback;
899 req->context = context;
900 silc_list_add(client->requests, req);
902 len = 4 + 4 + strlen(path);
904 silc_sftp_send_packet(client, req->type, len,
905 SILC_STR_UI_INT(req->id),
906 SILC_STR_UI_INT(strlen(path)),
907 SILC_STR_UI32_STRING(path),
911 void silc_sftp_lstat(SilcSFTP sftp,
913 SilcSFTPAttrCallback callback,
916 SilcSFTPClient client = (SilcSFTPClient)sftp;
920 SILC_LOG_DEBUG(("Lstat request"));
922 req = silc_calloc(1, sizeof(*req));
923 req->id = client->id++;
924 req->type = SILC_SFTP_LSTAT;
925 req->attr = callback;
926 req->context = context;
927 silc_list_add(client->requests, req);
929 len = 4 + 4 + strlen(path);
931 silc_sftp_send_packet(client, req->type, len,
932 SILC_STR_UI_INT(req->id),
933 SILC_STR_UI_INT(strlen(path)),
934 SILC_STR_UI32_STRING(path),
938 void silc_sftp_fstat(SilcSFTP sftp,
939 SilcSFTPHandle handle,
940 SilcSFTPAttrCallback callback,
943 SilcSFTPClient client = (SilcSFTPClient)sftp;
946 const unsigned char *hdata;
947 SilcUInt32 hdata_len;
949 SILC_LOG_DEBUG(("Fstat request"));
951 req = silc_calloc(1, sizeof(*req));
952 req->id = client->id++;
953 req->type = SILC_SFTP_FSTAT;
954 req->attr = callback;
955 req->context = context;
956 silc_list_add(client->requests, req);
958 silc_sftp_handle_get(handle, &hdata, &hdata_len);
959 len = 4 + 4 + hdata_len;
961 silc_sftp_send_packet(client, req->type, len,
962 SILC_STR_UI_INT(req->id),
963 SILC_STR_UI_INT(hdata_len),
964 SILC_STR_UI_XNSTRING(hdata, hdata_len),
968 void silc_sftp_setstat(SilcSFTP sftp,
970 SilcSFTPAttributes attrs,
971 SilcSFTPStatusCallback callback,
974 SilcSFTPClient client = (SilcSFTPClient)sftp;
977 SilcBuffer attrs_buf;
979 SILC_LOG_DEBUG(("Setstat request"));
981 req = silc_calloc(1, sizeof(*req));
982 req->id = client->id++;
983 req->type = SILC_SFTP_SETSTAT;
984 req->status = callback;
985 req->context = context;
986 silc_list_add(client->requests, req);
988 attrs_buf = silc_sftp_attr_encode(attrs);
989 len = 4 + 4 + strlen(path) + attrs_buf->len;
991 silc_sftp_send_packet(client, req->type, len,
992 SILC_STR_UI_INT(req->id),
993 SILC_STR_UI_INT(strlen(path)),
994 SILC_STR_UI32_STRING(path),
995 SILC_STR_UI_XNSTRING(attrs_buf->data,
999 silc_buffer_free(attrs_buf);
1002 void silc_sftp_fsetstat(SilcSFTP sftp,
1003 SilcSFTPHandle handle,
1004 SilcSFTPAttributes attrs,
1005 SilcSFTPStatusCallback callback,
1008 SilcSFTPClient client = (SilcSFTPClient)sftp;
1009 SilcSFTPRequest req;
1011 SilcBuffer attrs_buf;
1012 const unsigned char *hdata;
1013 SilcUInt32 hdata_len;
1015 SILC_LOG_DEBUG(("Fsetstat request"));
1017 req = silc_calloc(1, sizeof(*req));
1018 req->id = client->id++;
1019 req->type = SILC_SFTP_FSETSTAT;
1020 req->status = callback;
1021 req->context = context;
1022 silc_list_add(client->requests, req);
1024 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1025 attrs_buf = silc_sftp_attr_encode(attrs);
1026 len = 4 + 4 + hdata_len + attrs_buf->len;
1028 silc_sftp_send_packet(client, req->type, len,
1029 SILC_STR_UI_INT(req->id),
1030 SILC_STR_UI_INT(hdata_len),
1031 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1032 SILC_STR_UI_XNSTRING(attrs_buf->data,
1036 silc_buffer_free(attrs_buf);
1039 void silc_sftp_readlink(SilcSFTP sftp,
1041 SilcSFTPNameCallback callback,
1044 SilcSFTPClient client = (SilcSFTPClient)sftp;
1045 SilcSFTPRequest req;
1048 SILC_LOG_DEBUG(("Readlink request"));
1050 req = silc_calloc(1, sizeof(*req));
1051 req->id = client->id++;
1052 req->type = SILC_SFTP_READLINK;
1053 req->name = callback;
1054 req->context = context;
1055 silc_list_add(client->requests, req);
1057 len = 4 + 4 + strlen(path);
1059 silc_sftp_send_packet(client, req->type, len,
1060 SILC_STR_UI_INT(req->id),
1061 SILC_STR_UI_INT(strlen(path)),
1062 SILC_STR_UI32_STRING(path),
1066 void silc_sftp_symlink(SilcSFTP sftp,
1067 const char *linkpath,
1068 const char *targetpath,
1069 SilcSFTPStatusCallback callback,
1072 SilcSFTPClient client = (SilcSFTPClient)sftp;
1073 SilcSFTPRequest req;
1076 SILC_LOG_DEBUG(("Symlink request"));
1078 req = silc_calloc(1, sizeof(*req));
1079 req->id = client->id++;
1080 req->type = SILC_SFTP_SYMLINK;
1081 req->status = callback;
1082 req->context = context;
1083 silc_list_add(client->requests, req);
1085 len = 4 + 4 + strlen(linkpath) + 4 + strlen(targetpath);
1087 silc_sftp_send_packet(client, req->type, len,
1088 SILC_STR_UI_INT(req->id),
1089 SILC_STR_UI_INT(strlen(linkpath)),
1090 SILC_STR_UI32_STRING(linkpath),
1091 SILC_STR_UI_INT(strlen(targetpath)),
1092 SILC_STR_UI32_STRING(targetpath),
1096 void silc_sftp_realpath(SilcSFTP sftp,
1098 SilcSFTPNameCallback callback,
1101 SilcSFTPClient client = (SilcSFTPClient)sftp;
1102 SilcSFTPRequest req;
1105 SILC_LOG_DEBUG(("Realpath request"));
1107 req = silc_calloc(1, sizeof(*req));
1108 req->id = client->id++;
1109 req->type = SILC_SFTP_REALPATH;
1110 req->name = callback;
1111 req->context = context;
1112 silc_list_add(client->requests, req);
1114 len = 4 + 4 + strlen(path);
1116 silc_sftp_send_packet(client, req->type, len,
1117 SILC_STR_UI_INT(req->id),
1118 SILC_STR_UI_INT(strlen(path)),
1119 SILC_STR_UI32_STRING(path),
1123 void silc_sftp_extended(SilcSFTP sftp,
1124 const char *request,
1125 const unsigned char *data,
1126 SilcUInt32 data_len,
1127 SilcSFTPExtendedCallback callback,
1130 SilcSFTPClient client = (SilcSFTPClient)sftp;
1131 SilcSFTPRequest req;
1134 SILC_LOG_DEBUG(("Extended request"));
1136 req = silc_calloc(1, sizeof(*req));
1137 req->id = client->id++;
1138 req->type = SILC_SFTP_WRITE;
1139 req->extended = callback;
1140 req->context = context;
1141 silc_list_add(client->requests, req);
1143 len = 4 + 4 + strlen(request) + data_len;
1145 silc_sftp_send_packet(client, req->type, len,
1146 SILC_STR_UI_INT(req->id),
1147 SILC_STR_UI_INT(strlen(request)),
1148 SILC_STR_UI32_STRING(request),
1149 SILC_STR_UI_XNSTRING(data, data_len),