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, uint32 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 = (uint32)va_arg(vp, uint32);
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;
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 = (uint32)va_arg(vp, uint32);
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 = (uint32)va_arg(vp, uint32);
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;
336 silc_list_uninit(sftp->requests);
338 silc_buffer_free(sftp->packet);
342 /* Function that is called to process the incmoing SFTP packet. */
343 /* XXX Some day this will go away and we have automatic receive callbacks
344 for SilcSocketConnection API or SilcPacketContext API. */
346 void silc_sftp_client_receive_process(SilcSFTP context,
347 SilcSocketConnection sock,
348 SilcPacketContext *packet)
350 SilcSFTPClient sftp = (SilcSFTPClient)context;
353 const unsigned char *payload = NULL;
356 SilcBufferStruct buf;
359 SILC_LOG_DEBUG(("Start"));
361 /* Parse the packet */
362 type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload,
367 silc_buffer_set(&buf, (unsigned char *)payload, payload_len);
370 case SILC_SFTP_VERSION:
372 SilcSFTPVersion version;
374 SILC_LOG_DEBUG(("Version packet"));
376 ret = silc_buffer_unformat(&buf,
377 SILC_STR_UI_INT(&version),
380 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_FAILURE, 0,
381 sftp->version_context);
385 /* Call the callback */
386 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_OK, version,
387 sftp->version_context);
391 case SILC_SFTP_STATUS:
394 char *message = NULL, *language_tag = NULL;
396 SILC_LOG_DEBUG(("Status packet"));
398 ret = silc_buffer_unformat(&buf,
399 SILC_STR_UI_INT(&id),
400 SILC_STR_UI_INT(&status),
405 if (status != SILC_SFTP_STATUS_OK) {
406 silc_buffer_pull(&buf, 8);
407 ret = silc_buffer_unformat(&buf,
408 SILC_STR_UI32_STRING_ALLOC(&message),
409 SILC_STR_UI32_STRING_ALLOC(&language_tag),
414 silc_buffer_push(&buf, 8);
418 req = silc_sftp_find_request(sftp, id);
421 silc_free(language_tag);
425 /* Call the callback */
426 silc_sftp_call_request(sftp, req, type, status, message, language_tag);
429 silc_free(language_tag);
433 case SILC_SFTP_HANDLE:
435 unsigned char *handle = NULL;
438 SILC_LOG_DEBUG(("Handle packet"));
440 ret = silc_buffer_unformat(&buf,
441 SILC_STR_UI_INT(&id),
442 SILC_STR_UI32_NSTRING(&handle,
449 req = silc_sftp_find_request(sftp, id);
453 /* Call the callback */
454 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
461 unsigned char *data = NULL;
464 SILC_LOG_DEBUG(("Data packet"));
466 ret = silc_buffer_unformat(&buf,
467 SILC_STR_UI_INT(&id),
468 SILC_STR_UI32_NSTRING(&data, &data_len),
474 req = silc_sftp_find_request(sftp, id);
478 /* Call the callback */
479 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
487 SilcSFTPName name = NULL;
489 SILC_LOG_DEBUG(("Name packet"));
491 ret = silc_buffer_unformat(&buf,
492 SILC_STR_UI_INT(&id),
493 SILC_STR_UI_INT(&count),
499 req = silc_sftp_find_request(sftp, id);
503 silc_buffer_pull(&buf, 8);
504 name = silc_sftp_name_decode(count, &buf);
507 silc_buffer_push(&buf, 8);
509 /* Call the callback */
510 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, name);
511 silc_sftp_name_free(name);
515 case SILC_SFTP_ATTRS:
517 SilcSFTPAttributes attr = NULL;
519 SilcBufferStruct tmpbuf;
521 SILC_LOG_DEBUG(("Attributes packet"));
523 ret = silc_buffer_unformat(&buf,
524 SILC_STR_UI_INT(&id),
525 SILC_STR_UI_XNSTRING(&data, buf.len - 4),
531 req = silc_sftp_find_request(sftp, id);
535 silc_buffer_set(&tmpbuf, data, buf.len - 4);
536 attr = silc_sftp_attr_decode(&tmpbuf);
540 /* Call the callback */
541 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, attr);
545 case SILC_SFTP_EXTENDED_REPLY:
547 unsigned char *data = NULL;
549 SILC_LOG_DEBUG(("Extended reply packet"));
551 ret = silc_buffer_unformat(&buf,
552 SILC_STR_UI_INT(&id),
553 SILC_STR_UI_XNSTRING(&data, buf.len - 4),
559 req = silc_sftp_find_request(sftp, id);
563 /* Call the callback */
564 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
574 void silc_sftp_open(SilcSFTP sftp,
575 const char *filename,
576 SilcSFTPFileOperation pflags,
577 SilcSFTPAttributes attrs,
578 SilcSFTPHandleCallback callback,
581 SilcSFTPClient client = (SilcSFTPClient)sftp;
583 SilcBuffer attrs_buf;
586 SILC_LOG_DEBUG(("Open request"));
588 req = silc_calloc(1, sizeof(*req));
589 req->id = client->id++;
590 req->type = SILC_SFTP_OPEN;
591 req->handle = callback;
592 req->context = context;
593 silc_list_add(client->requests, req);
595 attrs_buf = silc_sftp_attr_encode(attrs);
596 len = 4 + 4 + strlen(filename) + 4 + attrs_buf->len;
598 silc_sftp_send_packet(client, req->type, len,
599 SILC_STR_UI_INT(req->id),
600 SILC_STR_UI_INT(strlen(filename)),
601 SILC_STR_UI32_STRING(filename),
602 SILC_STR_UI_INT(pflags),
603 SILC_STR_UI_XNSTRING(attrs_buf->data,
607 silc_buffer_free(attrs_buf);
610 void silc_sftp_close(SilcSFTP sftp,
611 SilcSFTPHandle handle,
612 SilcSFTPStatusCallback callback,
615 SilcSFTPClient client = (SilcSFTPClient)sftp;
618 const unsigned char *hdata;
621 SILC_LOG_DEBUG(("Close request"));
623 req = silc_calloc(1, sizeof(*req));
624 req->id = client->id++;
625 req->type = SILC_SFTP_CLOSE;
626 req->status = callback;
627 req->context = context;
628 silc_list_add(client->requests, req);
630 silc_sftp_handle_get(handle, &hdata, &hdata_len);
631 len = 4 + 4 + hdata_len;
633 silc_sftp_send_packet(client, req->type, len,
634 SILC_STR_UI_INT(req->id),
635 SILC_STR_UI_INT(hdata_len),
636 SILC_STR_UI_XNSTRING(hdata, hdata_len),
640 void silc_sftp_read(SilcSFTP sftp,
641 SilcSFTPHandle handle,
644 SilcSFTPDataCallback callback,
647 SilcSFTPClient client = (SilcSFTPClient)sftp;
650 const unsigned char *hdata;
653 SILC_LOG_DEBUG(("Read request"));
655 req = silc_calloc(1, sizeof(*req));
656 req->id = client->id++;
657 req->type = SILC_SFTP_READ;
658 req->data = callback;
659 req->context = context;
660 silc_list_add(client->requests, req);
662 silc_sftp_handle_get(handle, &hdata, &hdata_len);
663 len2 = 4 + 4 + hdata_len + 8 + 4;
665 silc_sftp_send_packet(client, req->type, len2,
666 SILC_STR_UI_INT(req->id),
667 SILC_STR_UI_INT(hdata_len),
668 SILC_STR_UI_XNSTRING(hdata, hdata_len),
669 SILC_STR_UI_INT64(offset),
670 SILC_STR_UI_INT(len),
674 void silc_sftp_write(SilcSFTP sftp,
675 SilcSFTPHandle handle,
677 const unsigned char *data,
679 SilcSFTPStatusCallback callback,
682 SilcSFTPClient client = (SilcSFTPClient)sftp;
685 const unsigned char *hdata;
688 SILC_LOG_DEBUG(("Write request"));
690 req = silc_calloc(1, sizeof(*req));
691 req->id = client->id++;
692 req->type = SILC_SFTP_WRITE;
693 req->status = callback;
694 req->context = context;
695 silc_list_add(client->requests, req);
697 silc_sftp_handle_get(handle, &hdata, &hdata_len);
698 len = 4 + 4 + hdata_len + 8 + 4 + data_len;
700 silc_sftp_send_packet(client, req->type, len,
701 SILC_STR_UI_INT(req->id),
702 SILC_STR_UI_INT(hdata_len),
703 SILC_STR_UI_XNSTRING(hdata, hdata_len),
704 SILC_STR_UI_INT64(offset),
705 SILC_STR_UI_INT(data_len),
706 SILC_STR_UI_XNSTRING(data, data_len),
710 void silc_sftp_remove(SilcSFTP sftp,
711 const char *filename,
712 SilcSFTPStatusCallback callback,
715 SilcSFTPClient client = (SilcSFTPClient)sftp;
719 SILC_LOG_DEBUG(("Remove request"));
721 req = silc_calloc(1, sizeof(*req));
722 req->id = client->id++;
723 req->type = SILC_SFTP_REMOVE;
724 req->status = callback;
725 req->context = context;
726 silc_list_add(client->requests, req);
728 len = 4 + 4 + strlen(filename);
730 silc_sftp_send_packet(client, req->type, len,
731 SILC_STR_UI_INT(req->id),
732 SILC_STR_UI_INT(strlen(filename)),
733 SILC_STR_UI32_STRING(filename),
737 void silc_sftp_rename(SilcSFTP sftp,
740 SilcSFTPStatusCallback callback,
743 SilcSFTPClient client = (SilcSFTPClient)sftp;
747 SILC_LOG_DEBUG(("Rename request"));
749 req = silc_calloc(1, sizeof(*req));
750 req->id = client->id++;
751 req->type = SILC_SFTP_RENAME;
752 req->status = callback;
753 req->context = context;
754 silc_list_add(client->requests, req);
756 len = 4 + 4 + strlen(oldname) + 4 + strlen(newname);
758 silc_sftp_send_packet(client, req->type, len,
759 SILC_STR_UI_INT(req->id),
760 SILC_STR_UI_INT(strlen(oldname)),
761 SILC_STR_UI32_STRING(oldname),
762 SILC_STR_UI_INT(strlen(newname)),
763 SILC_STR_UI32_STRING(newname),
767 void silc_sftp_mkdir(SilcSFTP sftp,
769 SilcSFTPAttributes attrs,
770 SilcSFTPStatusCallback callback,
773 SilcSFTPClient client = (SilcSFTPClient)sftp;
776 SilcBuffer attrs_buf;
778 SILC_LOG_DEBUG(("Mkdir request"));
780 req = silc_calloc(1, sizeof(*req));
781 req->id = client->id++;
782 req->type = SILC_SFTP_MKDIR;
783 req->status = callback;
784 req->context = context;
785 silc_list_add(client->requests, req);
787 attrs_buf = silc_sftp_attr_encode(attrs);
788 len = 4 + 4 + strlen(path) + attrs_buf->len;
790 silc_sftp_send_packet(client, req->type, len,
791 SILC_STR_UI_INT(req->id),
792 SILC_STR_UI_INT(strlen(path)),
793 SILC_STR_UI32_STRING(path),
794 SILC_STR_UI_XNSTRING(attrs_buf->data,
798 silc_buffer_free(attrs_buf);
801 void silc_sftp_rmdir(SilcSFTP sftp,
803 SilcSFTPStatusCallback callback,
806 SilcSFTPClient client = (SilcSFTPClient)sftp;
810 SILC_LOG_DEBUG(("Rmdir request"));
812 req = silc_calloc(1, sizeof(*req));
813 req->id = client->id++;
814 req->type = SILC_SFTP_RMDIR;
815 req->status = callback;
816 req->context = context;
817 silc_list_add(client->requests, req);
819 len = 4 + 4 + strlen(path);
821 silc_sftp_send_packet(client, req->type, len,
822 SILC_STR_UI_INT(req->id),
823 SILC_STR_UI_INT(strlen(path)),
824 SILC_STR_UI32_STRING(path),
828 void silc_sftp_opendir(SilcSFTP sftp,
830 SilcSFTPHandleCallback callback,
833 SilcSFTPClient client = (SilcSFTPClient)sftp;
837 SILC_LOG_DEBUG(("Opendir request"));
839 req = silc_calloc(1, sizeof(*req));
840 req->id = client->id++;
841 req->type = SILC_SFTP_OPENDIR;
842 req->handle = callback;
843 req->context = context;
844 silc_list_add(client->requests, req);
846 len = 4 + 4 + strlen(path);
848 silc_sftp_send_packet(client, req->type, len,
849 SILC_STR_UI_INT(req->id),
850 SILC_STR_UI_INT(strlen(path)),
851 SILC_STR_UI32_STRING(path),
855 void silc_sftp_readdir(SilcSFTP sftp,
856 SilcSFTPHandle handle,
857 SilcSFTPNameCallback callback,
860 SilcSFTPClient client = (SilcSFTPClient)sftp;
863 const unsigned char *hdata;
866 SILC_LOG_DEBUG(("Readdir request"));
868 req = silc_calloc(1, sizeof(*req));
869 req->id = client->id++;
870 req->type = SILC_SFTP_READDIR;
871 req->name = callback;
872 req->context = context;
873 silc_list_add(client->requests, req);
875 silc_sftp_handle_get(handle, &hdata, &hdata_len);
876 len = 4 + 4 + hdata_len;
878 silc_sftp_send_packet(client, req->type, len,
879 SILC_STR_UI_INT(req->id),
880 SILC_STR_UI_INT(hdata_len),
881 SILC_STR_UI_XNSTRING(hdata, hdata_len),
885 void silc_sftp_stat(SilcSFTP sftp,
887 SilcSFTPAttrCallback callback,
890 SilcSFTPClient client = (SilcSFTPClient)sftp;
894 SILC_LOG_DEBUG(("Stat request"));
896 req = silc_calloc(1, sizeof(*req));
897 req->id = client->id++;
898 req->type = SILC_SFTP_STAT;
899 req->attr = callback;
900 req->context = context;
901 silc_list_add(client->requests, req);
903 len = 4 + 4 + strlen(path);
905 silc_sftp_send_packet(client, req->type, len,
906 SILC_STR_UI_INT(req->id),
907 SILC_STR_UI_INT(strlen(path)),
908 SILC_STR_UI32_STRING(path),
912 void silc_sftp_lstat(SilcSFTP sftp,
914 SilcSFTPAttrCallback callback,
917 SilcSFTPClient client = (SilcSFTPClient)sftp;
921 SILC_LOG_DEBUG(("Lstat request"));
923 req = silc_calloc(1, sizeof(*req));
924 req->id = client->id++;
925 req->type = SILC_SFTP_LSTAT;
926 req->attr = callback;
927 req->context = context;
928 silc_list_add(client->requests, req);
930 len = 4 + 4 + strlen(path);
932 silc_sftp_send_packet(client, req->type, len,
933 SILC_STR_UI_INT(req->id),
934 SILC_STR_UI_INT(strlen(path)),
935 SILC_STR_UI32_STRING(path),
939 void silc_sftp_fstat(SilcSFTP sftp,
940 SilcSFTPHandle handle,
941 SilcSFTPAttrCallback callback,
944 SilcSFTPClient client = (SilcSFTPClient)sftp;
947 const unsigned char *hdata;
950 SILC_LOG_DEBUG(("Fstat request"));
952 req = silc_calloc(1, sizeof(*req));
953 req->id = client->id++;
954 req->type = SILC_SFTP_FSTAT;
955 req->attr = callback;
956 req->context = context;
957 silc_list_add(client->requests, req);
959 silc_sftp_handle_get(handle, &hdata, &hdata_len);
960 len = 4 + 4 + hdata_len;
962 silc_sftp_send_packet(client, req->type, len,
963 SILC_STR_UI_INT(req->id),
964 SILC_STR_UI_INT(hdata_len),
965 SILC_STR_UI_XNSTRING(hdata, hdata_len),
969 void silc_sftp_setstat(SilcSFTP sftp,
971 SilcSFTPAttributes attrs,
972 SilcSFTPStatusCallback callback,
975 SilcSFTPClient client = (SilcSFTPClient)sftp;
978 SilcBuffer attrs_buf;
980 SILC_LOG_DEBUG(("Setstat request"));
982 req = silc_calloc(1, sizeof(*req));
983 req->id = client->id++;
984 req->type = SILC_SFTP_SETSTAT;
985 req->status = callback;
986 req->context = context;
987 silc_list_add(client->requests, req);
989 attrs_buf = silc_sftp_attr_encode(attrs);
990 len = 4 + 4 + strlen(path) + attrs_buf->len;
992 silc_sftp_send_packet(client, req->type, len,
993 SILC_STR_UI_INT(req->id),
994 SILC_STR_UI_INT(strlen(path)),
995 SILC_STR_UI32_STRING(path),
996 SILC_STR_UI_XNSTRING(attrs_buf->data,
1000 silc_buffer_free(attrs_buf);
1003 void silc_sftp_fsetstat(SilcSFTP sftp,
1004 SilcSFTPHandle handle,
1005 SilcSFTPAttributes attrs,
1006 SilcSFTPStatusCallback callback,
1009 SilcSFTPClient client = (SilcSFTPClient)sftp;
1010 SilcSFTPRequest req;
1012 SilcBuffer attrs_buf;
1013 const unsigned char *hdata;
1016 SILC_LOG_DEBUG(("Fsetstat request"));
1018 req = silc_calloc(1, sizeof(*req));
1019 req->id = client->id++;
1020 req->type = SILC_SFTP_FSETSTAT;
1021 req->status = callback;
1022 req->context = context;
1023 silc_list_add(client->requests, req);
1025 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1026 attrs_buf = silc_sftp_attr_encode(attrs);
1027 len = 4 + 4 + hdata_len + attrs_buf->len;
1029 silc_sftp_send_packet(client, req->type, len,
1030 SILC_STR_UI_INT(req->id),
1031 SILC_STR_UI_INT(hdata_len),
1032 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1033 SILC_STR_UI_XNSTRING(attrs_buf->data,
1037 silc_buffer_free(attrs_buf);
1040 void silc_sftp_readlink(SilcSFTP sftp,
1042 SilcSFTPNameCallback callback,
1045 SilcSFTPClient client = (SilcSFTPClient)sftp;
1046 SilcSFTPRequest req;
1049 SILC_LOG_DEBUG(("Readlink request"));
1051 req = silc_calloc(1, sizeof(*req));
1052 req->id = client->id++;
1053 req->type = SILC_SFTP_READLINK;
1054 req->name = callback;
1055 req->context = context;
1056 silc_list_add(client->requests, req);
1058 len = 4 + 4 + strlen(path);
1060 silc_sftp_send_packet(client, req->type, len,
1061 SILC_STR_UI_INT(req->id),
1062 SILC_STR_UI_INT(strlen(path)),
1063 SILC_STR_UI32_STRING(path),
1067 void silc_sftp_symlink(SilcSFTP sftp,
1068 const char *linkpath,
1069 const char *targetpath,
1070 SilcSFTPStatusCallback callback,
1073 SilcSFTPClient client = (SilcSFTPClient)sftp;
1074 SilcSFTPRequest req;
1077 SILC_LOG_DEBUG(("Symlink request"));
1079 req = silc_calloc(1, sizeof(*req));
1080 req->id = client->id++;
1081 req->type = SILC_SFTP_SYMLINK;
1082 req->status = callback;
1083 req->context = context;
1084 silc_list_add(client->requests, req);
1086 len = 4 + 4 + strlen(linkpath) + 4 + strlen(targetpath);
1088 silc_sftp_send_packet(client, req->type, len,
1089 SILC_STR_UI_INT(req->id),
1090 SILC_STR_UI_INT(strlen(linkpath)),
1091 SILC_STR_UI32_STRING(linkpath),
1092 SILC_STR_UI_INT(strlen(targetpath)),
1093 SILC_STR_UI32_STRING(targetpath),
1097 void silc_sftp_realpath(SilcSFTP sftp,
1099 SilcSFTPNameCallback callback,
1102 SilcSFTPClient client = (SilcSFTPClient)sftp;
1103 SilcSFTPRequest req;
1106 SILC_LOG_DEBUG(("Realpath request"));
1108 req = silc_calloc(1, sizeof(*req));
1109 req->id = client->id++;
1110 req->type = SILC_SFTP_REALPATH;
1111 req->name = callback;
1112 req->context = context;
1113 silc_list_add(client->requests, req);
1115 len = 4 + 4 + strlen(path);
1117 silc_sftp_send_packet(client, req->type, len,
1118 SILC_STR_UI_INT(req->id),
1119 SILC_STR_UI_INT(strlen(path)),
1120 SILC_STR_UI32_STRING(path),
1124 void silc_sftp_extended(SilcSFTP sftp,
1125 const char *request,
1126 const unsigned char *data,
1128 SilcSFTPExtendedCallback callback,
1131 SilcSFTPClient client = (SilcSFTPClient)sftp;
1132 SilcSFTPRequest req;
1135 SILC_LOG_DEBUG(("Extended request"));
1137 req = silc_calloc(1, sizeof(*req));
1138 req->id = client->id++;
1139 req->type = SILC_SFTP_WRITE;
1140 req->extended = callback;
1141 req->context = context;
1142 silc_list_add(client->requests, req);
1144 len = 4 + 4 + strlen(request) + data_len;
1146 silc_sftp_send_packet(client, req->type, len,
1147 SILC_STR_UI_INT(req->id),
1148 SILC_STR_UI_INT(strlen(request)),
1149 SILC_STR_UI32_STRING(request),
1150 SILC_STR_UI_XNSTRING(data, data_len),