5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 2003 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));
68 handle->data = silc_calloc(data_len, sizeof(*handle->data));
71 memcpy(handle->data, data, data_len);
72 handle->data_len = data_len;
77 /* Deletes the handle indicated by the `handle'. */
79 static void silc_sftp_handle_delete(SilcSFTPHandle handle)
81 silc_free(handle->data);
85 /* Returns the handle data of the `handle' to the `data' pointer. */
87 static void silc_sftp_handle_get(SilcSFTPHandle handle,
88 const unsigned char **data,
91 *data = (const unsigned char *)handle->data;
92 *data_len = handle->data_len;
95 /* General routine to send SFTP packet to the SFTP server. */
97 static void silc_sftp_send_packet(SilcSFTPClient sftp,
105 tmp = silc_sftp_packet_encode_vp(type, sftp->packet, len, vp);
111 SILC_LOG_HEXDUMP(("SFTP packet to server"), sftp->packet->data,
114 /* Send the packet */
115 (*sftp->send_packet)(sftp->packet, sftp->send_context);
118 sftp->packet->data = sftp->packet->tail = sftp->packet->head;
119 sftp->packet->len = 0;
122 /* Finds request by request ID. */
124 static SilcSFTPRequest silc_sftp_find_request(SilcSFTPClient sftp, SilcUInt32 id)
128 SILC_LOG_DEBUG(("Finding request ID: %d", id));
130 silc_list_start(sftp->requests);
131 while ((req = silc_list_get(sftp->requests)) != SILC_LIST_END) {
136 SILC_LOG_DEBUG(("Unknown request ID"));
141 /* Function used to call the request callback indicated by the `req'. The
142 `status' will be sent to the callback function as the status of the
143 operation. The variable argument list includes the status and req->type
146 static void silc_sftp_call_request(SilcSFTPClient sftp,
149 SilcSFTPStatus status, ...)
153 SILC_LOG_DEBUG(("Start"));
155 va_start(vp, status);
164 if (status != SILC_SFTP_STATUS_OK) {
166 (*req->data)((SilcSFTP)sftp, status, NULL, 0, req->context);
170 data = (unsigned char *)va_arg(vp, unsigned char *);
171 data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
174 (*req->data)((SilcSFTP)sftp, status, (const unsigned char *)data,
175 data_len, req->context);
180 case SILC_SFTP_OPENDIR:
182 /* Handle returned */
183 SilcSFTPHandle handle;
184 unsigned char *hdata;
185 SilcUInt32 hdata_len;
187 if (status != SILC_SFTP_STATUS_OK) {
189 (*req->handle)((SilcSFTP)sftp, status, NULL, req->context);
193 hdata = (unsigned char *)va_arg(vp, unsigned char *);
194 hdata_len = (SilcUInt32)va_arg(vp, SilcUInt32);
195 handle = silc_sftp_handle_create(hdata, hdata_len);
198 (*req->handle)((SilcSFTP)sftp, status, NULL, req->context);
203 (*req->handle)((SilcSFTP)sftp, status, handle, req->context);
207 case SILC_SFTP_CLOSE:
208 case SILC_SFTP_WRITE:
209 case SILC_SFTP_REMOVE:
210 case SILC_SFTP_RENAME:
211 case SILC_SFTP_MKDIR:
212 case SILC_SFTP_RMDIR:
213 case SILC_SFTP_SETSTAT:
214 case SILC_SFTP_FSETSTAT:
215 case SILC_SFTP_SYMLINK:
217 /* Status returned */
218 char *message, *language_tag;
220 message = (char *)va_arg(vp, char *);
221 language_tag = (char *)va_arg(vp, char *);
224 (*req->status)((SilcSFTP)sftp, status, (const char *)message,
225 (const char *)language_tag, req->context);
230 case SILC_SFTP_LSTAT:
231 case SILC_SFTP_FSTAT:
233 /* Attributes returned */
234 SilcSFTPAttributes attr;
236 if (status != SILC_SFTP_STATUS_OK) {
238 (*req->attr)((SilcSFTP)sftp, status, NULL, req->context);
242 attr = (SilcSFTPAttributes)va_arg(vp, SilcSFTPAttributes);
245 (*req->attr)((SilcSFTP)sftp, status, (const SilcSFTPAttributes)attr,
250 case SILC_SFTP_READDIR:
251 case SILC_SFTP_REALPATH:
252 case SILC_SFTP_READLINK:
254 /* Name(s) returned */
257 if (status != SILC_SFTP_STATUS_OK) {
259 (*req->name)((SilcSFTP)sftp, status, NULL, req->context);
263 name = (SilcSFTPName)va_arg(vp, SilcSFTPName);
266 (*req->name)((SilcSFTP)sftp, status, name, req->context);
270 case SILC_SFTP_EXTENDED:
272 /* Extended reply returned */
276 if (status != SILC_SFTP_STATUS_OK) {
278 (*req->extended)((SilcSFTP)sftp, status, NULL, 0, req->context);
282 data = (unsigned char *)va_arg(vp, unsigned char *);
283 data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
286 (*req->extended)((SilcSFTP)sftp, status, (const unsigned char *)data,
287 data_len, req->context);
295 /* Remove this request */
296 silc_list_del(sftp->requests, req);
302 /* Starts SFTP client and returns context for it. The version callback
303 indicated by the `callback' will be called after the SFTP session has
304 been started and server has returned the version of the protocol. The
305 SFTP client context is returned in the callback too. This returns
306 allocated SFTP client context or NULL on error. */
308 SilcSFTP silc_sftp_client_start(SilcSFTPSendPacketCallback send_packet,
310 SilcSFTPVersionCallback callback,
318 sftp = silc_calloc(1, sizeof(*sftp));
321 sftp->send_packet = send_packet;
322 sftp->send_context = send_context;
323 sftp->version = callback;
324 sftp->version_context = context;
325 silc_list_init(sftp->requests, struct SilcSFTPRequestStruct, next);
327 /* Send the SFTP session initialization to the server */
328 silc_sftp_send_packet(sftp, SILC_SFTP_INIT, 4,
329 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
332 return (SilcSFTP)sftp;
335 /* Shutdown's the SFTP client. The caller is responsible of closing
336 the associated socket connection. The SFTP context is freed and is
337 invalid after this function returns. */
339 void silc_sftp_client_shutdown(SilcSFTP context)
341 SilcSFTPClient sftp = (SilcSFTPClient)context;
344 silc_buffer_free(sftp->packet);
348 /* Function that is called to process the incmoing SFTP packet. */
349 /* XXX Some day this will go away and we have automatic receive callbacks
350 for SilcSocketConnection API or SilcPacketContext API. */
352 void silc_sftp_client_receive_process(SilcSFTP context,
353 SilcSocketConnection sock,
354 SilcPacketContext *packet)
356 SilcSFTPClient sftp = (SilcSFTPClient)context;
359 const unsigned char *payload = NULL;
360 SilcUInt32 payload_len;
362 SilcBufferStruct buf;
365 SILC_LOG_DEBUG(("Start"));
367 /* Parse the packet */
368 type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload,
373 silc_buffer_set(&buf, (unsigned char *)payload, payload_len);
376 case SILC_SFTP_VERSION:
378 SilcSFTPVersion version;
380 SILC_LOG_DEBUG(("Version packet"));
382 ret = silc_buffer_unformat(&buf,
383 SILC_STR_UI_INT(&version),
386 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_FAILURE, 0,
387 sftp->version_context);
391 /* Call the callback */
392 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_OK, version,
393 sftp->version_context);
397 case SILC_SFTP_STATUS:
400 char *message = NULL, *language_tag = NULL;
402 SILC_LOG_DEBUG(("Status packet"));
404 ret = silc_buffer_unformat(&buf,
405 SILC_STR_UI_INT(&id),
406 SILC_STR_UI_INT(&status),
411 if (status != SILC_SFTP_STATUS_OK) {
412 silc_buffer_pull(&buf, 8);
413 ret = silc_buffer_unformat(&buf,
414 SILC_STR_UI32_STRING_ALLOC(&message),
415 SILC_STR_UI32_STRING_ALLOC(&language_tag),
420 silc_buffer_push(&buf, 8);
424 req = silc_sftp_find_request(sftp, id);
427 silc_free(language_tag);
431 /* Call the callback */
432 silc_sftp_call_request(sftp, req, type, status, message, language_tag);
435 silc_free(language_tag);
439 case SILC_SFTP_HANDLE:
441 unsigned char *handle = NULL;
442 SilcUInt32 handle_len;
444 SILC_LOG_DEBUG(("Handle packet"));
446 ret = silc_buffer_unformat(&buf,
447 SILC_STR_UI_INT(&id),
448 SILC_STR_UI32_NSTRING(&handle,
455 req = silc_sftp_find_request(sftp, id);
459 /* Call the callback */
460 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
467 unsigned char *data = NULL;
468 SilcUInt32 data_len = 0;
470 SILC_LOG_DEBUG(("Data packet"));
472 ret = silc_buffer_unformat(&buf,
473 SILC_STR_UI_INT(&id),
474 SILC_STR_UI32_NSTRING(&data, &data_len),
480 req = silc_sftp_find_request(sftp, id);
484 /* Call the callback */
485 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
493 SilcSFTPName name = NULL;
495 SILC_LOG_DEBUG(("Name packet"));
497 ret = silc_buffer_unformat(&buf,
498 SILC_STR_UI_INT(&id),
499 SILC_STR_UI_INT(&count),
505 req = silc_sftp_find_request(sftp, id);
509 silc_buffer_pull(&buf, 8);
510 name = silc_sftp_name_decode(count, &buf);
513 silc_buffer_push(&buf, 8);
515 /* Call the callback */
516 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, name);
517 silc_sftp_name_free(name);
521 case SILC_SFTP_ATTRS:
523 SilcSFTPAttributes attr = NULL;
525 SilcBufferStruct tmpbuf;
527 SILC_LOG_DEBUG(("Attributes packet"));
529 ret = silc_buffer_unformat(&buf,
530 SILC_STR_UI_INT(&id),
531 SILC_STR_UI_XNSTRING(&data, buf.len - 4),
537 req = silc_sftp_find_request(sftp, id);
541 silc_buffer_set(&tmpbuf, data, buf.len - 4);
542 attr = silc_sftp_attr_decode(&tmpbuf);
546 /* Call the callback */
547 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, attr);
551 case SILC_SFTP_EXTENDED_REPLY:
553 unsigned char *data = NULL;
555 SILC_LOG_DEBUG(("Extended reply packet"));
557 ret = silc_buffer_unformat(&buf,
558 SILC_STR_UI_INT(&id),
559 SILC_STR_UI_XNSTRING(&data, buf.len - 4),
565 req = silc_sftp_find_request(sftp, id);
569 /* Call the callback */
570 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
580 void silc_sftp_open(SilcSFTP sftp,
581 const char *filename,
582 SilcSFTPFileOperation pflags,
583 SilcSFTPAttributes attrs,
584 SilcSFTPHandleCallback callback,
587 SilcSFTPClient client = (SilcSFTPClient)sftp;
589 SilcBuffer attrs_buf;
592 SILC_LOG_DEBUG(("Open request"));
594 req = silc_calloc(1, sizeof(*req));
597 req->id = client->id++;
598 req->type = SILC_SFTP_OPEN;
599 req->handle = callback;
600 req->context = context;
601 silc_list_add(client->requests, req);
603 attrs_buf = silc_sftp_attr_encode(attrs);
606 len = 4 + 4 + strlen(filename) + 4 + attrs_buf->len;
608 silc_sftp_send_packet(client, req->type, len,
609 SILC_STR_UI_INT(req->id),
610 SILC_STR_UI_INT(strlen(filename)),
611 SILC_STR_UI32_STRING(filename),
612 SILC_STR_UI_INT(pflags),
613 SILC_STR_UI_XNSTRING(attrs_buf->data,
617 silc_buffer_free(attrs_buf);
620 void silc_sftp_close(SilcSFTP sftp,
621 SilcSFTPHandle handle,
622 SilcSFTPStatusCallback callback,
625 SilcSFTPClient client = (SilcSFTPClient)sftp;
628 const unsigned char *hdata;
629 SilcUInt32 hdata_len;
631 SILC_LOG_DEBUG(("Close request"));
633 req = silc_calloc(1, sizeof(*req));
636 req->id = client->id++;
637 req->type = SILC_SFTP_CLOSE;
638 req->status = callback;
639 req->context = context;
640 silc_list_add(client->requests, req);
642 silc_sftp_handle_get(handle, &hdata, &hdata_len);
643 len = 4 + 4 + hdata_len;
645 silc_sftp_send_packet(client, req->type, len,
646 SILC_STR_UI_INT(req->id),
647 SILC_STR_UI_INT(hdata_len),
648 SILC_STR_UI_XNSTRING(hdata, hdata_len),
650 silc_sftp_handle_delete(handle);
653 void silc_sftp_read(SilcSFTP sftp,
654 SilcSFTPHandle handle,
657 SilcSFTPDataCallback callback,
660 SilcSFTPClient client = (SilcSFTPClient)sftp;
663 const unsigned char *hdata;
664 SilcUInt32 hdata_len;
666 SILC_LOG_DEBUG(("Read request"));
668 req = silc_calloc(1, sizeof(*req));
671 req->id = client->id++;
672 req->type = SILC_SFTP_READ;
673 req->data = callback;
674 req->context = context;
675 silc_list_add(client->requests, req);
677 silc_sftp_handle_get(handle, &hdata, &hdata_len);
678 len2 = 4 + 4 + hdata_len + 8 + 4;
680 silc_sftp_send_packet(client, req->type, len2,
681 SILC_STR_UI_INT(req->id),
682 SILC_STR_UI_INT(hdata_len),
683 SILC_STR_UI_XNSTRING(hdata, hdata_len),
684 SILC_STR_UI_INT64(offset),
685 SILC_STR_UI_INT(len),
689 void silc_sftp_write(SilcSFTP sftp,
690 SilcSFTPHandle handle,
692 const unsigned char *data,
694 SilcSFTPStatusCallback callback,
697 SilcSFTPClient client = (SilcSFTPClient)sftp;
700 const unsigned char *hdata;
701 SilcUInt32 hdata_len;
703 SILC_LOG_DEBUG(("Write request"));
705 req = silc_calloc(1, sizeof(*req));
708 req->id = client->id++;
709 req->type = SILC_SFTP_WRITE;
710 req->status = callback;
711 req->context = context;
712 silc_list_add(client->requests, req);
714 silc_sftp_handle_get(handle, &hdata, &hdata_len);
715 len = 4 + 4 + hdata_len + 8 + 4 + data_len;
717 silc_sftp_send_packet(client, req->type, len,
718 SILC_STR_UI_INT(req->id),
719 SILC_STR_UI_INT(hdata_len),
720 SILC_STR_UI_XNSTRING(hdata, hdata_len),
721 SILC_STR_UI_INT64(offset),
722 SILC_STR_UI_INT(data_len),
723 SILC_STR_UI_XNSTRING(data, data_len),
727 void silc_sftp_remove(SilcSFTP sftp,
728 const char *filename,
729 SilcSFTPStatusCallback callback,
732 SilcSFTPClient client = (SilcSFTPClient)sftp;
736 SILC_LOG_DEBUG(("Remove request"));
738 req = silc_calloc(1, sizeof(*req));
741 req->id = client->id++;
742 req->type = SILC_SFTP_REMOVE;
743 req->status = callback;
744 req->context = context;
745 silc_list_add(client->requests, req);
747 len = 4 + 4 + strlen(filename);
749 silc_sftp_send_packet(client, req->type, len,
750 SILC_STR_UI_INT(req->id),
751 SILC_STR_UI_INT(strlen(filename)),
752 SILC_STR_UI32_STRING(filename),
756 void silc_sftp_rename(SilcSFTP sftp,
759 SilcSFTPStatusCallback callback,
762 SilcSFTPClient client = (SilcSFTPClient)sftp;
766 SILC_LOG_DEBUG(("Rename request"));
768 req = silc_calloc(1, sizeof(*req));
771 req->id = client->id++;
772 req->type = SILC_SFTP_RENAME;
773 req->status = callback;
774 req->context = context;
775 silc_list_add(client->requests, req);
777 len = 4 + 4 + strlen(oldname) + 4 + strlen(newname);
779 silc_sftp_send_packet(client, req->type, len,
780 SILC_STR_UI_INT(req->id),
781 SILC_STR_UI_INT(strlen(oldname)),
782 SILC_STR_UI32_STRING(oldname),
783 SILC_STR_UI_INT(strlen(newname)),
784 SILC_STR_UI32_STRING(newname),
788 void silc_sftp_mkdir(SilcSFTP sftp,
790 SilcSFTPAttributes attrs,
791 SilcSFTPStatusCallback callback,
794 SilcSFTPClient client = (SilcSFTPClient)sftp;
797 SilcBuffer attrs_buf;
799 SILC_LOG_DEBUG(("Mkdir request"));
801 req = silc_calloc(1, sizeof(*req));
804 req->id = client->id++;
805 req->type = SILC_SFTP_MKDIR;
806 req->status = callback;
807 req->context = context;
808 silc_list_add(client->requests, req);
810 attrs_buf = silc_sftp_attr_encode(attrs);
813 len = 4 + 4 + strlen(path) + attrs_buf->len;
815 silc_sftp_send_packet(client, req->type, len,
816 SILC_STR_UI_INT(req->id),
817 SILC_STR_UI_INT(strlen(path)),
818 SILC_STR_UI32_STRING(path),
819 SILC_STR_UI_XNSTRING(attrs_buf->data,
823 silc_buffer_free(attrs_buf);
826 void silc_sftp_rmdir(SilcSFTP sftp,
828 SilcSFTPStatusCallback callback,
831 SilcSFTPClient client = (SilcSFTPClient)sftp;
835 SILC_LOG_DEBUG(("Rmdir request"));
837 req = silc_calloc(1, sizeof(*req));
840 req->id = client->id++;
841 req->type = SILC_SFTP_RMDIR;
842 req->status = 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_opendir(SilcSFTP sftp,
857 SilcSFTPHandleCallback callback,
860 SilcSFTPClient client = (SilcSFTPClient)sftp;
864 SILC_LOG_DEBUG(("Opendir request"));
866 req = silc_calloc(1, sizeof(*req));
869 req->id = client->id++;
870 req->type = SILC_SFTP_OPENDIR;
871 req->handle = callback;
872 req->context = context;
873 silc_list_add(client->requests, req);
875 len = 4 + 4 + strlen(path);
877 silc_sftp_send_packet(client, req->type, len,
878 SILC_STR_UI_INT(req->id),
879 SILC_STR_UI_INT(strlen(path)),
880 SILC_STR_UI32_STRING(path),
884 void silc_sftp_readdir(SilcSFTP sftp,
885 SilcSFTPHandle handle,
886 SilcSFTPNameCallback callback,
889 SilcSFTPClient client = (SilcSFTPClient)sftp;
892 const unsigned char *hdata;
893 SilcUInt32 hdata_len;
895 SILC_LOG_DEBUG(("Readdir request"));
897 req = silc_calloc(1, sizeof(*req));
900 req->id = client->id++;
901 req->type = SILC_SFTP_READDIR;
902 req->name = callback;
903 req->context = context;
904 silc_list_add(client->requests, req);
906 silc_sftp_handle_get(handle, &hdata, &hdata_len);
907 len = 4 + 4 + hdata_len;
909 silc_sftp_send_packet(client, req->type, len,
910 SILC_STR_UI_INT(req->id),
911 SILC_STR_UI_INT(hdata_len),
912 SILC_STR_UI_XNSTRING(hdata, hdata_len),
916 void silc_sftp_stat(SilcSFTP sftp,
918 SilcSFTPAttrCallback callback,
921 SilcSFTPClient client = (SilcSFTPClient)sftp;
925 SILC_LOG_DEBUG(("Stat request"));
927 req = silc_calloc(1, sizeof(*req));
930 req->id = client->id++;
931 req->type = SILC_SFTP_STAT;
932 req->attr = callback;
933 req->context = context;
934 silc_list_add(client->requests, req);
936 len = 4 + 4 + strlen(path);
938 silc_sftp_send_packet(client, req->type, len,
939 SILC_STR_UI_INT(req->id),
940 SILC_STR_UI_INT(strlen(path)),
941 SILC_STR_UI32_STRING(path),
945 void silc_sftp_lstat(SilcSFTP sftp,
947 SilcSFTPAttrCallback callback,
950 SilcSFTPClient client = (SilcSFTPClient)sftp;
954 SILC_LOG_DEBUG(("Lstat request"));
956 req = silc_calloc(1, sizeof(*req));
959 req->id = client->id++;
960 req->type = SILC_SFTP_LSTAT;
961 req->attr = callback;
962 req->context = context;
963 silc_list_add(client->requests, req);
965 len = 4 + 4 + strlen(path);
967 silc_sftp_send_packet(client, req->type, len,
968 SILC_STR_UI_INT(req->id),
969 SILC_STR_UI_INT(strlen(path)),
970 SILC_STR_UI32_STRING(path),
974 void silc_sftp_fstat(SilcSFTP sftp,
975 SilcSFTPHandle handle,
976 SilcSFTPAttrCallback callback,
979 SilcSFTPClient client = (SilcSFTPClient)sftp;
982 const unsigned char *hdata;
983 SilcUInt32 hdata_len;
985 SILC_LOG_DEBUG(("Fstat request"));
987 req = silc_calloc(1, sizeof(*req));
990 req->id = client->id++;
991 req->type = SILC_SFTP_FSTAT;
992 req->attr = callback;
993 req->context = context;
994 silc_list_add(client->requests, req);
996 silc_sftp_handle_get(handle, &hdata, &hdata_len);
997 len = 4 + 4 + hdata_len;
999 silc_sftp_send_packet(client, req->type, len,
1000 SILC_STR_UI_INT(req->id),
1001 SILC_STR_UI_INT(hdata_len),
1002 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1006 void silc_sftp_setstat(SilcSFTP sftp,
1008 SilcSFTPAttributes attrs,
1009 SilcSFTPStatusCallback callback,
1012 SilcSFTPClient client = (SilcSFTPClient)sftp;
1013 SilcSFTPRequest req;
1015 SilcBuffer attrs_buf;
1017 SILC_LOG_DEBUG(("Setstat request"));
1019 req = silc_calloc(1, sizeof(*req));
1022 req->id = client->id++;
1023 req->type = SILC_SFTP_SETSTAT;
1024 req->status = callback;
1025 req->context = context;
1026 silc_list_add(client->requests, req);
1028 attrs_buf = silc_sftp_attr_encode(attrs);
1031 len = 4 + 4 + strlen(path) + attrs_buf->len;
1033 silc_sftp_send_packet(client, req->type, len,
1034 SILC_STR_UI_INT(req->id),
1035 SILC_STR_UI_INT(strlen(path)),
1036 SILC_STR_UI32_STRING(path),
1037 SILC_STR_UI_XNSTRING(attrs_buf->data,
1041 silc_buffer_free(attrs_buf);
1044 void silc_sftp_fsetstat(SilcSFTP sftp,
1045 SilcSFTPHandle handle,
1046 SilcSFTPAttributes attrs,
1047 SilcSFTPStatusCallback callback,
1050 SilcSFTPClient client = (SilcSFTPClient)sftp;
1051 SilcSFTPRequest req;
1053 SilcBuffer attrs_buf;
1054 const unsigned char *hdata;
1055 SilcUInt32 hdata_len;
1057 SILC_LOG_DEBUG(("Fsetstat request"));
1059 req = silc_calloc(1, sizeof(*req));
1062 req->id = client->id++;
1063 req->type = SILC_SFTP_FSETSTAT;
1064 req->status = callback;
1065 req->context = context;
1066 silc_list_add(client->requests, req);
1068 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1069 attrs_buf = silc_sftp_attr_encode(attrs);
1072 len = 4 + 4 + hdata_len + attrs_buf->len;
1074 silc_sftp_send_packet(client, req->type, len,
1075 SILC_STR_UI_INT(req->id),
1076 SILC_STR_UI_INT(hdata_len),
1077 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1078 SILC_STR_UI_XNSTRING(attrs_buf->data,
1082 silc_buffer_free(attrs_buf);
1085 void silc_sftp_readlink(SilcSFTP sftp,
1087 SilcSFTPNameCallback callback,
1090 SilcSFTPClient client = (SilcSFTPClient)sftp;
1091 SilcSFTPRequest req;
1094 SILC_LOG_DEBUG(("Readlink request"));
1096 req = silc_calloc(1, sizeof(*req));
1099 req->id = client->id++;
1100 req->type = SILC_SFTP_READLINK;
1101 req->name = callback;
1102 req->context = context;
1103 silc_list_add(client->requests, req);
1105 len = 4 + 4 + strlen(path);
1107 silc_sftp_send_packet(client, req->type, len,
1108 SILC_STR_UI_INT(req->id),
1109 SILC_STR_UI_INT(strlen(path)),
1110 SILC_STR_UI32_STRING(path),
1114 void silc_sftp_symlink(SilcSFTP sftp,
1115 const char *linkpath,
1116 const char *targetpath,
1117 SilcSFTPStatusCallback callback,
1120 SilcSFTPClient client = (SilcSFTPClient)sftp;
1121 SilcSFTPRequest req;
1124 SILC_LOG_DEBUG(("Symlink request"));
1126 req = silc_calloc(1, sizeof(*req));
1129 req->id = client->id++;
1130 req->type = SILC_SFTP_SYMLINK;
1131 req->status = callback;
1132 req->context = context;
1133 silc_list_add(client->requests, req);
1135 len = 4 + 4 + strlen(linkpath) + 4 + strlen(targetpath);
1137 silc_sftp_send_packet(client, req->type, len,
1138 SILC_STR_UI_INT(req->id),
1139 SILC_STR_UI_INT(strlen(linkpath)),
1140 SILC_STR_UI32_STRING(linkpath),
1141 SILC_STR_UI_INT(strlen(targetpath)),
1142 SILC_STR_UI32_STRING(targetpath),
1146 void silc_sftp_realpath(SilcSFTP sftp,
1148 SilcSFTPNameCallback callback,
1151 SilcSFTPClient client = (SilcSFTPClient)sftp;
1152 SilcSFTPRequest req;
1155 SILC_LOG_DEBUG(("Realpath request"));
1157 req = silc_calloc(1, sizeof(*req));
1160 req->id = client->id++;
1161 req->type = SILC_SFTP_REALPATH;
1162 req->name = callback;
1163 req->context = context;
1164 silc_list_add(client->requests, req);
1166 len = 4 + 4 + strlen(path);
1168 silc_sftp_send_packet(client, req->type, len,
1169 SILC_STR_UI_INT(req->id),
1170 SILC_STR_UI_INT(strlen(path)),
1171 SILC_STR_UI32_STRING(path),
1175 void silc_sftp_extended(SilcSFTP sftp,
1176 const char *request,
1177 const unsigned char *data,
1178 SilcUInt32 data_len,
1179 SilcSFTPExtendedCallback callback,
1182 SilcSFTPClient client = (SilcSFTPClient)sftp;
1183 SilcSFTPRequest req;
1186 SILC_LOG_DEBUG(("Extended request"));
1188 req = silc_calloc(1, sizeof(*req));
1191 req->id = client->id++;
1192 req->type = SILC_SFTP_WRITE;
1193 req->extended = callback;
1194 req->context = context;
1195 silc_list_add(client->requests, req);
1197 len = 4 + 4 + strlen(request) + data_len;
1199 silc_sftp_send_packet(client, req->type, len,
1200 SILC_STR_UI_INT(req->id),
1201 SILC_STR_UI_INT(strlen(request)),
1202 SILC_STR_UI32_STRING(request),
1203 SILC_STR_UI_XNSTRING(data, data_len),