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 SilcSFTPSendPacketCallback send_packet;
44 SilcSFTPVersionCallback version;
45 void *version_context;
52 struct SilcSFTPHandleStruct {
57 /* Creates SilcSFTPHandle and returns pointer to it. The caller must free
60 static SilcSFTPHandle silc_sftp_handle_create(unsigned char *data,
63 SilcSFTPHandle handle;
65 handle = silc_calloc(1, sizeof(*handle));
66 handle->data = silc_calloc(data_len, sizeof(*handle->data));
67 memcpy(handle->data, data, data_len);
68 handle->data_len = data_len;
73 /* Deletes the handle indicated by the `handle'. */
75 static void silc_sftp_handle_delete(SilcSFTPHandle handle)
77 silc_free(handle->data);
81 /* Returns the handle data of the `handle' to the `data' pointer. */
83 static void silc_sftp_handle_get(SilcSFTPHandle handle,
84 const unsigned char **data,
87 *data = (const unsigned char *)handle->data;
88 *data_len = handle->data_len;
91 /* General routine to send SFTP packet to the SFTP server. */
93 static void silc_sftp_send_packet(SilcSFTPClient sftp,
101 tmp = silc_sftp_packet_encode_vp(type, sftp->packet, len, vp);
107 SILC_LOG_HEXDUMP(("SFTP packet to server"), sftp->packet->data,
110 /* Send the packet */
111 (*sftp->send_packet)(sftp->packet, sftp->send_context);
114 sftp->packet->data = sftp->packet->tail = sftp->packet->head;
115 sftp->packet->len = 0;
118 /* Finds request by request ID. */
120 static SilcSFTPRequest silc_sftp_find_request(SilcSFTPClient sftp, SilcUInt32 id)
124 SILC_LOG_DEBUG(("Finding request ID: %d", id));
126 silc_list_start(sftp->requests);
127 while ((req = silc_list_get(sftp->requests)) != SILC_LIST_END) {
132 SILC_LOG_DEBUG(("Unknown request ID"));
137 /* Function used to call the request callback indicated by the `req'. The
138 `status' will be sent to the callback function as the status of the
139 operation. The variable argument list includes the status and req->type
142 static void silc_sftp_call_request(SilcSFTPClient sftp,
145 SilcSFTPStatus status, ...)
149 SILC_LOG_DEBUG(("Start"));
151 va_start(vp, status);
160 if (status != SILC_SFTP_STATUS_OK) {
162 (*req->data)((SilcSFTP)sftp, status, NULL, 0, req->context);
166 data = (unsigned char *)va_arg(vp, unsigned char *);
167 data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
170 (*req->data)((SilcSFTP)sftp, status, (const unsigned char *)data,
171 data_len, req->context);
176 case SILC_SFTP_OPENDIR:
178 /* Handle returned */
179 SilcSFTPHandle handle;
180 unsigned char *hdata;
181 SilcUInt32 hdata_len;
183 if (status != SILC_SFTP_STATUS_OK) {
185 (*req->handle)((SilcSFTP)sftp, status, NULL, req->context);
189 hdata = (unsigned char *)va_arg(vp, unsigned char *);
190 hdata_len = (SilcUInt32)va_arg(vp, SilcUInt32);
191 handle = silc_sftp_handle_create(hdata, hdata_len);
194 (*req->handle)((SilcSFTP)sftp, status, handle, req->context);
198 case SILC_SFTP_CLOSE:
199 case SILC_SFTP_WRITE:
200 case SILC_SFTP_REMOVE:
201 case SILC_SFTP_RENAME:
202 case SILC_SFTP_MKDIR:
203 case SILC_SFTP_RMDIR:
204 case SILC_SFTP_SETSTAT:
205 case SILC_SFTP_FSETSTAT:
206 case SILC_SFTP_SYMLINK:
208 /* Status returned */
209 char *message, *language_tag;
211 message = (char *)va_arg(vp, char *);
212 language_tag = (char *)va_arg(vp, char *);
215 (*req->status)((SilcSFTP)sftp, status, (const char *)message,
216 (const char *)language_tag, req->context);
221 case SILC_SFTP_LSTAT:
222 case SILC_SFTP_FSTAT:
224 /* Attributes returned */
225 SilcSFTPAttributes attr;
227 if (status != SILC_SFTP_STATUS_OK) {
229 (*req->attr)((SilcSFTP)sftp, status, NULL, req->context);
233 attr = (SilcSFTPAttributes)va_arg(vp, SilcSFTPAttributes);
236 (*req->attr)((SilcSFTP)sftp, status, (const SilcSFTPAttributes)attr,
241 case SILC_SFTP_READDIR:
242 case SILC_SFTP_REALPATH:
243 case SILC_SFTP_READLINK:
245 /* Name(s) returned */
248 if (status != SILC_SFTP_STATUS_OK) {
250 (*req->name)((SilcSFTP)sftp, status, NULL, req->context);
254 name = (SilcSFTPName)va_arg(vp, SilcSFTPName);
257 (*req->name)((SilcSFTP)sftp, status, name, req->context);
261 case SILC_SFTP_EXTENDED:
263 /* Extended reply returned */
267 if (status != SILC_SFTP_STATUS_OK) {
269 (*req->extended)((SilcSFTP)sftp, status, NULL, 0, req->context);
273 data = (unsigned char *)va_arg(vp, unsigned char *);
274 data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
277 (*req->extended)((SilcSFTP)sftp, status, (const unsigned char *)data,
278 data_len, req->context);
286 /* Remove this request */
287 silc_list_del(sftp->requests, req);
293 /* Starts SFTP client and returns context for it. The version callback
294 indicated by the `callback' will be called after the SFTP session has
295 been started and server has returned the version of the protocol. The
296 SFTP client context is returned in the callback too. This returns
297 allocated SFTP client context or NULL on error. */
299 SilcSFTP silc_sftp_client_start(SilcSFTPSendPacketCallback send_packet,
301 SilcSFTPVersionCallback callback,
309 sftp = silc_calloc(1, sizeof(*sftp));
310 sftp->send_packet = send_packet;
311 sftp->send_context = send_context;
312 sftp->version = callback;
313 sftp->version_context = context;
314 silc_list_init(sftp->requests, struct SilcSFTPRequestStruct, next);
316 /* Send the SFTP session initialization to the server */
317 silc_sftp_send_packet(sftp, SILC_SFTP_INIT, 4,
318 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
321 return (SilcSFTP)sftp;
324 /* Shutdown's the SFTP client. The caller is responsible of closing
325 the associated socket connection. The SFTP context is freed and is
326 invalid after this function returns. */
328 void silc_sftp_client_shutdown(SilcSFTP context)
330 SilcSFTPClient sftp = (SilcSFTPClient)context;
333 silc_buffer_free(sftp->packet);
337 /* Function that is called to process the incmoing SFTP packet. */
338 /* XXX Some day this will go away and we have automatic receive callbacks
339 for SilcSocketConnection API or SilcPacketContext API. */
341 void silc_sftp_client_receive_process(SilcSFTP context,
342 SilcSocketConnection sock,
343 SilcPacketContext *packet)
345 SilcSFTPClient sftp = (SilcSFTPClient)context;
348 const unsigned char *payload = NULL;
349 SilcUInt32 payload_len;
351 SilcBufferStruct buf;
354 SILC_LOG_DEBUG(("Start"));
356 /* Parse the packet */
357 type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload,
362 silc_buffer_set(&buf, (unsigned char *)payload, payload_len);
365 case SILC_SFTP_VERSION:
367 SilcSFTPVersion version;
369 SILC_LOG_DEBUG(("Version packet"));
371 ret = silc_buffer_unformat(&buf,
372 SILC_STR_UI_INT(&version),
375 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_FAILURE, 0,
376 sftp->version_context);
380 /* Call the callback */
381 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_OK, version,
382 sftp->version_context);
386 case SILC_SFTP_STATUS:
389 char *message = NULL, *language_tag = NULL;
391 SILC_LOG_DEBUG(("Status packet"));
393 ret = silc_buffer_unformat(&buf,
394 SILC_STR_UI_INT(&id),
395 SILC_STR_UI_INT(&status),
400 if (status != SILC_SFTP_STATUS_OK) {
401 silc_buffer_pull(&buf, 8);
402 ret = silc_buffer_unformat(&buf,
403 SILC_STR_UI32_STRING_ALLOC(&message),
404 SILC_STR_UI32_STRING_ALLOC(&language_tag),
409 silc_buffer_push(&buf, 8);
413 req = silc_sftp_find_request(sftp, id);
416 silc_free(language_tag);
420 /* Call the callback */
421 silc_sftp_call_request(sftp, req, type, status, message, language_tag);
424 silc_free(language_tag);
428 case SILC_SFTP_HANDLE:
430 unsigned char *handle = NULL;
431 SilcUInt32 handle_len;
433 SILC_LOG_DEBUG(("Handle packet"));
435 ret = silc_buffer_unformat(&buf,
436 SILC_STR_UI_INT(&id),
437 SILC_STR_UI32_NSTRING(&handle,
444 req = silc_sftp_find_request(sftp, id);
448 /* Call the callback */
449 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
456 unsigned char *data = NULL;
457 SilcUInt32 data_len = 0;
459 SILC_LOG_DEBUG(("Data packet"));
461 ret = silc_buffer_unformat(&buf,
462 SILC_STR_UI_INT(&id),
463 SILC_STR_UI32_NSTRING(&data, &data_len),
469 req = silc_sftp_find_request(sftp, id);
473 /* Call the callback */
474 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
482 SilcSFTPName name = NULL;
484 SILC_LOG_DEBUG(("Name packet"));
486 ret = silc_buffer_unformat(&buf,
487 SILC_STR_UI_INT(&id),
488 SILC_STR_UI_INT(&count),
494 req = silc_sftp_find_request(sftp, id);
498 silc_buffer_pull(&buf, 8);
499 name = silc_sftp_name_decode(count, &buf);
502 silc_buffer_push(&buf, 8);
504 /* Call the callback */
505 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, name);
506 silc_sftp_name_free(name);
510 case SILC_SFTP_ATTRS:
512 SilcSFTPAttributes attr = NULL;
514 SilcBufferStruct tmpbuf;
516 SILC_LOG_DEBUG(("Attributes packet"));
518 ret = silc_buffer_unformat(&buf,
519 SILC_STR_UI_INT(&id),
520 SILC_STR_UI_XNSTRING(&data, buf.len - 4),
526 req = silc_sftp_find_request(sftp, id);
530 silc_buffer_set(&tmpbuf, data, buf.len - 4);
531 attr = silc_sftp_attr_decode(&tmpbuf);
535 /* Call the callback */
536 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, attr);
540 case SILC_SFTP_EXTENDED_REPLY:
542 unsigned char *data = NULL;
544 SILC_LOG_DEBUG(("Extended reply packet"));
546 ret = silc_buffer_unformat(&buf,
547 SILC_STR_UI_INT(&id),
548 SILC_STR_UI_XNSTRING(&data, buf.len - 4),
554 req = silc_sftp_find_request(sftp, id);
558 /* Call the callback */
559 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
569 void silc_sftp_open(SilcSFTP sftp,
570 const char *filename,
571 SilcSFTPFileOperation pflags,
572 SilcSFTPAttributes attrs,
573 SilcSFTPHandleCallback callback,
576 SilcSFTPClient client = (SilcSFTPClient)sftp;
578 SilcBuffer attrs_buf;
581 SILC_LOG_DEBUG(("Open request"));
583 req = silc_calloc(1, sizeof(*req));
584 req->id = client->id++;
585 req->type = SILC_SFTP_OPEN;
586 req->handle = callback;
587 req->context = context;
588 silc_list_add(client->requests, req);
590 attrs_buf = silc_sftp_attr_encode(attrs);
591 len = 4 + 4 + strlen(filename) + 4 + attrs_buf->len;
593 silc_sftp_send_packet(client, req->type, len,
594 SILC_STR_UI_INT(req->id),
595 SILC_STR_UI_INT(strlen(filename)),
596 SILC_STR_UI32_STRING(filename),
597 SILC_STR_UI_INT(pflags),
598 SILC_STR_UI_XNSTRING(attrs_buf->data,
602 silc_buffer_free(attrs_buf);
605 void silc_sftp_close(SilcSFTP sftp,
606 SilcSFTPHandle handle,
607 SilcSFTPStatusCallback callback,
610 SilcSFTPClient client = (SilcSFTPClient)sftp;
613 const unsigned char *hdata;
614 SilcUInt32 hdata_len;
616 SILC_LOG_DEBUG(("Close request"));
618 req = silc_calloc(1, sizeof(*req));
619 req->id = client->id++;
620 req->type = SILC_SFTP_CLOSE;
621 req->status = callback;
622 req->context = context;
623 silc_list_add(client->requests, req);
625 silc_sftp_handle_get(handle, &hdata, &hdata_len);
626 len = 4 + 4 + hdata_len;
628 silc_sftp_send_packet(client, req->type, len,
629 SILC_STR_UI_INT(req->id),
630 SILC_STR_UI_INT(hdata_len),
631 SILC_STR_UI_XNSTRING(hdata, hdata_len),
635 void silc_sftp_read(SilcSFTP sftp,
636 SilcSFTPHandle handle,
639 SilcSFTPDataCallback callback,
642 SilcSFTPClient client = (SilcSFTPClient)sftp;
645 const unsigned char *hdata;
646 SilcUInt32 hdata_len;
648 SILC_LOG_DEBUG(("Read request"));
650 req = silc_calloc(1, sizeof(*req));
651 req->id = client->id++;
652 req->type = SILC_SFTP_READ;
653 req->data = callback;
654 req->context = context;
655 silc_list_add(client->requests, req);
657 silc_sftp_handle_get(handle, &hdata, &hdata_len);
658 len2 = 4 + 4 + hdata_len + 8 + 4;
660 silc_sftp_send_packet(client, req->type, len2,
661 SILC_STR_UI_INT(req->id),
662 SILC_STR_UI_INT(hdata_len),
663 SILC_STR_UI_XNSTRING(hdata, hdata_len),
664 SILC_STR_UI_INT64(offset),
665 SILC_STR_UI_INT(len),
669 void silc_sftp_write(SilcSFTP sftp,
670 SilcSFTPHandle handle,
672 const unsigned char *data,
674 SilcSFTPStatusCallback callback,
677 SilcSFTPClient client = (SilcSFTPClient)sftp;
680 const unsigned char *hdata;
681 SilcUInt32 hdata_len;
683 SILC_LOG_DEBUG(("Write request"));
685 req = silc_calloc(1, sizeof(*req));
686 req->id = client->id++;
687 req->type = SILC_SFTP_WRITE;
688 req->status = callback;
689 req->context = context;
690 silc_list_add(client->requests, req);
692 silc_sftp_handle_get(handle, &hdata, &hdata_len);
693 len = 4 + 4 + hdata_len + 8 + 4 + data_len;
695 silc_sftp_send_packet(client, req->type, len,
696 SILC_STR_UI_INT(req->id),
697 SILC_STR_UI_INT(hdata_len),
698 SILC_STR_UI_XNSTRING(hdata, hdata_len),
699 SILC_STR_UI_INT64(offset),
700 SILC_STR_UI_INT(data_len),
701 SILC_STR_UI_XNSTRING(data, data_len),
705 void silc_sftp_remove(SilcSFTP sftp,
706 const char *filename,
707 SilcSFTPStatusCallback callback,
710 SilcSFTPClient client = (SilcSFTPClient)sftp;
714 SILC_LOG_DEBUG(("Remove request"));
716 req = silc_calloc(1, sizeof(*req));
717 req->id = client->id++;
718 req->type = SILC_SFTP_REMOVE;
719 req->status = callback;
720 req->context = context;
721 silc_list_add(client->requests, req);
723 len = 4 + 4 + strlen(filename);
725 silc_sftp_send_packet(client, req->type, len,
726 SILC_STR_UI_INT(req->id),
727 SILC_STR_UI_INT(strlen(filename)),
728 SILC_STR_UI32_STRING(filename),
732 void silc_sftp_rename(SilcSFTP sftp,
735 SilcSFTPStatusCallback callback,
738 SilcSFTPClient client = (SilcSFTPClient)sftp;
742 SILC_LOG_DEBUG(("Rename request"));
744 req = silc_calloc(1, sizeof(*req));
745 req->id = client->id++;
746 req->type = SILC_SFTP_RENAME;
747 req->status = callback;
748 req->context = context;
749 silc_list_add(client->requests, req);
751 len = 4 + 4 + strlen(oldname) + 4 + strlen(newname);
753 silc_sftp_send_packet(client, req->type, len,
754 SILC_STR_UI_INT(req->id),
755 SILC_STR_UI_INT(strlen(oldname)),
756 SILC_STR_UI32_STRING(oldname),
757 SILC_STR_UI_INT(strlen(newname)),
758 SILC_STR_UI32_STRING(newname),
762 void silc_sftp_mkdir(SilcSFTP sftp,
764 SilcSFTPAttributes attrs,
765 SilcSFTPStatusCallback callback,
768 SilcSFTPClient client = (SilcSFTPClient)sftp;
771 SilcBuffer attrs_buf;
773 SILC_LOG_DEBUG(("Mkdir request"));
775 req = silc_calloc(1, sizeof(*req));
776 req->id = client->id++;
777 req->type = SILC_SFTP_MKDIR;
778 req->status = callback;
779 req->context = context;
780 silc_list_add(client->requests, req);
782 attrs_buf = silc_sftp_attr_encode(attrs);
783 len = 4 + 4 + strlen(path) + attrs_buf->len;
785 silc_sftp_send_packet(client, req->type, len,
786 SILC_STR_UI_INT(req->id),
787 SILC_STR_UI_INT(strlen(path)),
788 SILC_STR_UI32_STRING(path),
789 SILC_STR_UI_XNSTRING(attrs_buf->data,
793 silc_buffer_free(attrs_buf);
796 void silc_sftp_rmdir(SilcSFTP sftp,
798 SilcSFTPStatusCallback callback,
801 SilcSFTPClient client = (SilcSFTPClient)sftp;
805 SILC_LOG_DEBUG(("Rmdir request"));
807 req = silc_calloc(1, sizeof(*req));
808 req->id = client->id++;
809 req->type = SILC_SFTP_RMDIR;
810 req->status = callback;
811 req->context = context;
812 silc_list_add(client->requests, req);
814 len = 4 + 4 + strlen(path);
816 silc_sftp_send_packet(client, req->type, len,
817 SILC_STR_UI_INT(req->id),
818 SILC_STR_UI_INT(strlen(path)),
819 SILC_STR_UI32_STRING(path),
823 void silc_sftp_opendir(SilcSFTP sftp,
825 SilcSFTPHandleCallback callback,
828 SilcSFTPClient client = (SilcSFTPClient)sftp;
832 SILC_LOG_DEBUG(("Opendir request"));
834 req = silc_calloc(1, sizeof(*req));
835 req->id = client->id++;
836 req->type = SILC_SFTP_OPENDIR;
837 req->handle = callback;
838 req->context = context;
839 silc_list_add(client->requests, req);
841 len = 4 + 4 + strlen(path);
843 silc_sftp_send_packet(client, req->type, len,
844 SILC_STR_UI_INT(req->id),
845 SILC_STR_UI_INT(strlen(path)),
846 SILC_STR_UI32_STRING(path),
850 void silc_sftp_readdir(SilcSFTP sftp,
851 SilcSFTPHandle handle,
852 SilcSFTPNameCallback callback,
855 SilcSFTPClient client = (SilcSFTPClient)sftp;
858 const unsigned char *hdata;
859 SilcUInt32 hdata_len;
861 SILC_LOG_DEBUG(("Readdir request"));
863 req = silc_calloc(1, sizeof(*req));
864 req->id = client->id++;
865 req->type = SILC_SFTP_READDIR;
866 req->name = callback;
867 req->context = context;
868 silc_list_add(client->requests, req);
870 silc_sftp_handle_get(handle, &hdata, &hdata_len);
871 len = 4 + 4 + hdata_len;
873 silc_sftp_send_packet(client, req->type, len,
874 SILC_STR_UI_INT(req->id),
875 SILC_STR_UI_INT(hdata_len),
876 SILC_STR_UI_XNSTRING(hdata, hdata_len),
880 void silc_sftp_stat(SilcSFTP sftp,
882 SilcSFTPAttrCallback callback,
885 SilcSFTPClient client = (SilcSFTPClient)sftp;
889 SILC_LOG_DEBUG(("Stat request"));
891 req = silc_calloc(1, sizeof(*req));
892 req->id = client->id++;
893 req->type = SILC_SFTP_STAT;
894 req->attr = callback;
895 req->context = context;
896 silc_list_add(client->requests, req);
898 len = 4 + 4 + strlen(path);
900 silc_sftp_send_packet(client, req->type, len,
901 SILC_STR_UI_INT(req->id),
902 SILC_STR_UI_INT(strlen(path)),
903 SILC_STR_UI32_STRING(path),
907 void silc_sftp_lstat(SilcSFTP sftp,
909 SilcSFTPAttrCallback callback,
912 SilcSFTPClient client = (SilcSFTPClient)sftp;
916 SILC_LOG_DEBUG(("Lstat request"));
918 req = silc_calloc(1, sizeof(*req));
919 req->id = client->id++;
920 req->type = SILC_SFTP_LSTAT;
921 req->attr = callback;
922 req->context = context;
923 silc_list_add(client->requests, req);
925 len = 4 + 4 + strlen(path);
927 silc_sftp_send_packet(client, req->type, len,
928 SILC_STR_UI_INT(req->id),
929 SILC_STR_UI_INT(strlen(path)),
930 SILC_STR_UI32_STRING(path),
934 void silc_sftp_fstat(SilcSFTP sftp,
935 SilcSFTPHandle handle,
936 SilcSFTPAttrCallback callback,
939 SilcSFTPClient client = (SilcSFTPClient)sftp;
942 const unsigned char *hdata;
943 SilcUInt32 hdata_len;
945 SILC_LOG_DEBUG(("Fstat request"));
947 req = silc_calloc(1, sizeof(*req));
948 req->id = client->id++;
949 req->type = SILC_SFTP_FSTAT;
950 req->attr = callback;
951 req->context = context;
952 silc_list_add(client->requests, req);
954 silc_sftp_handle_get(handle, &hdata, &hdata_len);
955 len = 4 + 4 + hdata_len;
957 silc_sftp_send_packet(client, req->type, len,
958 SILC_STR_UI_INT(req->id),
959 SILC_STR_UI_INT(hdata_len),
960 SILC_STR_UI_XNSTRING(hdata, hdata_len),
964 void silc_sftp_setstat(SilcSFTP sftp,
966 SilcSFTPAttributes attrs,
967 SilcSFTPStatusCallback callback,
970 SilcSFTPClient client = (SilcSFTPClient)sftp;
973 SilcBuffer attrs_buf;
975 SILC_LOG_DEBUG(("Setstat request"));
977 req = silc_calloc(1, sizeof(*req));
978 req->id = client->id++;
979 req->type = SILC_SFTP_SETSTAT;
980 req->status = callback;
981 req->context = context;
982 silc_list_add(client->requests, req);
984 attrs_buf = silc_sftp_attr_encode(attrs);
985 len = 4 + 4 + strlen(path) + attrs_buf->len;
987 silc_sftp_send_packet(client, req->type, len,
988 SILC_STR_UI_INT(req->id),
989 SILC_STR_UI_INT(strlen(path)),
990 SILC_STR_UI32_STRING(path),
991 SILC_STR_UI_XNSTRING(attrs_buf->data,
995 silc_buffer_free(attrs_buf);
998 void silc_sftp_fsetstat(SilcSFTP sftp,
999 SilcSFTPHandle handle,
1000 SilcSFTPAttributes attrs,
1001 SilcSFTPStatusCallback callback,
1004 SilcSFTPClient client = (SilcSFTPClient)sftp;
1005 SilcSFTPRequest req;
1007 SilcBuffer attrs_buf;
1008 const unsigned char *hdata;
1009 SilcUInt32 hdata_len;
1011 SILC_LOG_DEBUG(("Fsetstat request"));
1013 req = silc_calloc(1, sizeof(*req));
1014 req->id = client->id++;
1015 req->type = SILC_SFTP_FSETSTAT;
1016 req->status = callback;
1017 req->context = context;
1018 silc_list_add(client->requests, req);
1020 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1021 attrs_buf = silc_sftp_attr_encode(attrs);
1022 len = 4 + 4 + hdata_len + attrs_buf->len;
1024 silc_sftp_send_packet(client, req->type, len,
1025 SILC_STR_UI_INT(req->id),
1026 SILC_STR_UI_INT(hdata_len),
1027 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1028 SILC_STR_UI_XNSTRING(attrs_buf->data,
1032 silc_buffer_free(attrs_buf);
1035 void silc_sftp_readlink(SilcSFTP sftp,
1037 SilcSFTPNameCallback callback,
1040 SilcSFTPClient client = (SilcSFTPClient)sftp;
1041 SilcSFTPRequest req;
1044 SILC_LOG_DEBUG(("Readlink request"));
1046 req = silc_calloc(1, sizeof(*req));
1047 req->id = client->id++;
1048 req->type = SILC_SFTP_READLINK;
1049 req->name = callback;
1050 req->context = context;
1051 silc_list_add(client->requests, req);
1053 len = 4 + 4 + strlen(path);
1055 silc_sftp_send_packet(client, req->type, len,
1056 SILC_STR_UI_INT(req->id),
1057 SILC_STR_UI_INT(strlen(path)),
1058 SILC_STR_UI32_STRING(path),
1062 void silc_sftp_symlink(SilcSFTP sftp,
1063 const char *linkpath,
1064 const char *targetpath,
1065 SilcSFTPStatusCallback callback,
1068 SilcSFTPClient client = (SilcSFTPClient)sftp;
1069 SilcSFTPRequest req;
1072 SILC_LOG_DEBUG(("Symlink request"));
1074 req = silc_calloc(1, sizeof(*req));
1075 req->id = client->id++;
1076 req->type = SILC_SFTP_SYMLINK;
1077 req->status = callback;
1078 req->context = context;
1079 silc_list_add(client->requests, req);
1081 len = 4 + 4 + strlen(linkpath) + 4 + strlen(targetpath);
1083 silc_sftp_send_packet(client, req->type, len,
1084 SILC_STR_UI_INT(req->id),
1085 SILC_STR_UI_INT(strlen(linkpath)),
1086 SILC_STR_UI32_STRING(linkpath),
1087 SILC_STR_UI_INT(strlen(targetpath)),
1088 SILC_STR_UI32_STRING(targetpath),
1092 void silc_sftp_realpath(SilcSFTP sftp,
1094 SilcSFTPNameCallback callback,
1097 SilcSFTPClient client = (SilcSFTPClient)sftp;
1098 SilcSFTPRequest req;
1101 SILC_LOG_DEBUG(("Realpath request"));
1103 req = silc_calloc(1, sizeof(*req));
1104 req->id = client->id++;
1105 req->type = SILC_SFTP_REALPATH;
1106 req->name = callback;
1107 req->context = context;
1108 silc_list_add(client->requests, req);
1110 len = 4 + 4 + strlen(path);
1112 silc_sftp_send_packet(client, req->type, len,
1113 SILC_STR_UI_INT(req->id),
1114 SILC_STR_UI_INT(strlen(path)),
1115 SILC_STR_UI32_STRING(path),
1119 void silc_sftp_extended(SilcSFTP sftp,
1120 const char *request,
1121 const unsigned char *data,
1122 SilcUInt32 data_len,
1123 SilcSFTPExtendedCallback callback,
1126 SilcSFTPClient client = (SilcSFTPClient)sftp;
1127 SilcSFTPRequest req;
1130 SILC_LOG_DEBUG(("Extended request"));
1132 req = silc_calloc(1, sizeof(*req));
1133 req->id = client->id++;
1134 req->type = SILC_SFTP_WRITE;
1135 req->extended = callback;
1136 req->context = context;
1137 silc_list_add(client->requests, req);
1139 len = 4 + 4 + strlen(request) + data_len;
1141 silc_sftp_send_packet(client, req->type, len,
1142 SILC_STR_UI_INT(req->id),
1143 SILC_STR_UI_INT(strlen(request)),
1144 SILC_STR_UI32_STRING(request),
1145 SILC_STR_UI_XNSTRING(data, data_len),