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. */
30 SilcSFTPStatusCallback status;
31 SilcSFTPHandleCallback handle;
32 SilcSFTPDataCallback data;
33 SilcSFTPNameCallback name;
34 SilcSFTPAttrCallback attr;
35 SilcSFTPExtendedCallback extended;
39 /* SFTP client context */
41 SilcSocketConnection sock;
42 SilcSFTPSendPacketCallback send_packet;
44 SilcSFTPVersionCallback version;
45 void *version_context;
51 struct SilcSFTPHandleStruct {
56 /* Creates SilcSFTPHandle and returns pointer to it. The caller must free
59 static SilcSFTPHandle silc_sftp_handle_create(unsigned char *data,
62 SilcSFTPHandle handle;
64 handle = silc_calloc(1, sizeof(*handle));
65 handle->data = silc_calloc(data_len, sizeof(*handle->data));
66 memcpy(handle->data, data, data_len);
67 handle->data_len = data_len;
72 /* Deletes the handle indicated by the `handle'. */
74 static void silc_sftp_handle_delete(SilcSFTPHandle handle)
76 silc_free(handle->data);
80 /* Returns the handle data of the `handle' to the `data' pointer. */
82 static void silc_sftp_handle_get(SilcSFTPHandle handle,
83 const unsigned char **data,
86 *data = (const unsigned char *)handle->data;
87 *data_len = handle->data_len;
90 /* General routine to send SFTP packet to the SFTP server. */
92 static void silc_sftp_send_packet(SilcSFTPClient sftp,
100 packet = silc_sftp_packet_encode_vp(type, len, vp);
106 SILC_LOG_HEXDUMP(("SFTP packet to server"), packet->data, packet->len);
108 /* Send the packet */
109 (*sftp->send_packet)(sftp->sock, packet, sftp->send_context);
111 silc_buffer_free(packet);
114 /* Finds request by request ID. */
116 static SilcSFTPRequest silc_sftp_find_request(SilcSFTPClient sftp, uint32 id)
120 SILC_LOG_DEBUG(("Finding request ID: %d", id));
122 silc_dlist_start(sftp->requests);
123 while ((req = silc_dlist_get(sftp->requests)) != SILC_LIST_END) {
128 SILC_LOG_DEBUG(("Unknown request ID"));
133 /* Function used to call the request callback indicated by the `req'. The
134 `status' will be sent to the callback function as the status of the
135 operation. The variable argument list includes the status and req->type
138 static void silc_sftp_call_request(SilcSFTPClient sftp,
141 SilcSFTPStatus status, ...)
145 SILC_LOG_DEBUG(("Start"));
147 va_start(vp, status);
156 if (status != SILC_SFTP_STATUS_OK) {
158 (*req->data)((SilcSFTP)sftp, status, NULL, 0, req->context);
162 data = (unsigned char *)va_arg(vp, unsigned char *);
163 data_len = (uint32)va_arg(vp, uint32);
166 (*req->data)((SilcSFTP)sftp, status, (const unsigned char *)data,
167 data_len, req->context);
172 case SILC_SFTP_OPENDIR:
174 /* Handle returned */
175 SilcSFTPHandle handle;
176 unsigned char *hdata;
179 if (status != SILC_SFTP_STATUS_OK) {
181 (*req->handle)((SilcSFTP)sftp, status, NULL, req->context);
185 hdata = (unsigned char *)va_arg(vp, unsigned char *);
186 hdata_len = (uint32)va_arg(vp, uint32);
187 handle = silc_sftp_handle_create(hdata, hdata_len);
190 (*req->handle)((SilcSFTP)sftp, status, handle, req->context);
194 case SILC_SFTP_CLOSE:
195 case SILC_SFTP_WRITE:
196 case SILC_SFTP_REMOVE:
197 case SILC_SFTP_RENAME:
198 case SILC_SFTP_MKDIR:
199 case SILC_SFTP_RMDIR:
200 case SILC_SFTP_SETSTAT:
201 case SILC_SFTP_FSETSTAT:
202 case SILC_SFTP_SYMLINK:
204 /* Status returned */
205 char *message, *language_tag;
207 message = (char *)va_arg(vp, char *);
208 language_tag = (char *)va_arg(vp, char *);
211 (*req->status)((SilcSFTP)sftp, status, (const char *)message,
212 (const char *)language_tag, req->context);
217 case SILC_SFTP_LSTAT:
218 case SILC_SFTP_FSTAT:
220 /* Attributes returned */
221 SilcSFTPAttributes attr;
223 if (status != SILC_SFTP_STATUS_OK) {
225 (*req->attr)((SilcSFTP)sftp, status, NULL, req->context);
229 attr = (SilcSFTPAttributes)va_arg(vp, SilcSFTPAttributes);
232 (*req->attr)((SilcSFTP)sftp, status, (const SilcSFTPAttributes)attr,
237 case SILC_SFTP_READDIR:
238 case SILC_SFTP_REALPATH:
239 case SILC_SFTP_READLINK:
241 /* Name(s) returned */
244 if (status != SILC_SFTP_STATUS_OK) {
246 (*req->name)((SilcSFTP)sftp, status, NULL, req->context);
250 name = (SilcSFTPName)va_arg(vp, SilcSFTPName);
253 (*req->name)((SilcSFTP)sftp, status, name, req->context);
257 case SILC_SFTP_EXTENDED:
259 /* Extended reply returned */
263 if (status != SILC_SFTP_STATUS_OK) {
265 (*req->extended)((SilcSFTP)sftp, status, NULL, 0, req->context);
269 data = (unsigned char *)va_arg(vp, unsigned char *);
270 data_len = (uint32)va_arg(vp, uint32);
273 (*req->extended)((SilcSFTP)sftp, status, (const unsigned char *)data,
274 data_len, req->context);
282 /* Remove this request */
283 silc_dlist_del(sftp->requests, req);
289 /* Starts SFTP client by associating the socket connection `sock' to the
290 created SFTP client context. The version callback indicated by the
291 `callback' will be called after the SFTP session has been started
292 and server has returned the version of the protocol. The SFTP client
293 context is returned in the callback too. This returns the allocated
294 SFTP client context or NULL on error. */
296 SilcSFTP silc_sftp_client_start(SilcSocketConnection sock,
297 SilcSFTPSendPacketCallback send_packet,
299 SilcSFTPVersionCallback callback,
307 sftp = silc_calloc(1, sizeof(*sftp));
309 sftp->send_packet = send_packet;
310 sftp->send_context = send_context;
311 sftp->version = callback;
312 sftp->version_context = context;
313 sftp->requests = silc_dlist_init();
315 /* Send the SFTP session initialization to the server */
316 silc_sftp_send_packet(sftp, SILC_SFTP_INIT, 4,
317 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
320 return (SilcSFTP)sftp;
323 /* Shutdown's the SFTP client. The caller is responsible of closing
324 the associated socket connection. The SFTP context is freed and is
325 invalid after this function returns. */
327 void silc_sftp_client_shutdown(SilcSFTP context)
329 SilcSFTPClient sftp = (SilcSFTPClient)context;
331 silc_dlist_uninit(sftp->requests);
335 /* Function that is called to process the incmoing SFTP packet. */
336 /* XXX Some day this will go away and we have automatic receive callbacks
337 for SilcSocketConnection API or SilcPacketContext API. */
339 void silc_sftp_client_receive_process(SilcSFTP context,
340 SilcSocketConnection sock,
341 SilcPacketContext *packet)
343 SilcSFTPClient sftp = (SilcSFTPClient)context;
346 const unsigned char *payload = NULL;
349 SilcBufferStruct buf;
352 SILC_LOG_DEBUG(("Start"));
354 /* Parse the packet */
355 type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload,
360 silc_buffer_set(&buf, (unsigned char *)payload, payload_len);
363 case SILC_SFTP_VERSION:
365 SilcSFTPVersion version;
367 SILC_LOG_DEBUG(("Version packet"));
369 ret = silc_buffer_unformat(&buf,
370 SILC_STR_UI_INT(&version),
373 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_FAILURE, 0,
374 sftp->version_context);
378 /* Call the callback */
379 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_OK, version,
380 sftp->version_context);
384 case SILC_SFTP_STATUS:
387 char *message = NULL, *language_tag = NULL;
389 SILC_LOG_DEBUG(("Status packet"));
391 ret = silc_buffer_unformat(&buf,
392 SILC_STR_UI_INT(&id),
393 SILC_STR_UI_INT(&status),
398 if (status != SILC_SFTP_STATUS_OK) {
399 silc_buffer_pull(&buf, 8);
400 ret = silc_buffer_unformat(&buf,
401 SILC_STR_UI32_STRING_ALLOC(&message),
402 SILC_STR_UI32_STRING_ALLOC(&language_tag),
407 silc_buffer_push(&buf, 8);
411 req = silc_sftp_find_request(sftp, id);
414 silc_free(language_tag);
418 /* Call the callback */
419 silc_sftp_call_request(sftp, req, type, status, message, language_tag);
422 silc_free(language_tag);
426 case SILC_SFTP_HANDLE:
428 unsigned char *handle = NULL;
431 SILC_LOG_DEBUG(("Handle packet"));
433 ret = silc_buffer_unformat(&buf,
434 SILC_STR_UI_INT(&id),
435 SILC_STR_UI32_NSTRING(&handle,
442 req = silc_sftp_find_request(sftp, id);
446 /* Call the callback */
447 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
454 unsigned char *data = NULL;
457 SILC_LOG_DEBUG(("Data packet"));
459 ret = silc_buffer_unformat(&buf,
460 SILC_STR_UI_INT(&id),
461 SILC_STR_UI32_NSTRING(&data, &data_len),
467 req = silc_sftp_find_request(sftp, id);
471 /* Call the callback */
472 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
480 SilcSFTPName name = NULL;
482 SILC_LOG_DEBUG(("Name packet"));
484 ret = silc_buffer_unformat(&buf,
485 SILC_STR_UI_INT(&id),
486 SILC_STR_UI_INT(&count),
492 req = silc_sftp_find_request(sftp, id);
496 silc_buffer_pull(&buf, 8);
497 name = silc_sftp_name_decode(count, &buf);
500 silc_buffer_push(&buf, 8);
502 /* Call the callback */
503 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, name);
504 silc_sftp_name_free(name);
508 case SILC_SFTP_ATTRS:
510 SilcSFTPAttributes attr = NULL;
512 SilcBufferStruct tmpbuf;
514 SILC_LOG_DEBUG(("Attributes packet"));
516 ret = silc_buffer_unformat(&buf,
517 SILC_STR_UI_INT(&id),
518 SILC_STR_UI_XNSTRING(&data, buf.len - 4),
524 req = silc_sftp_find_request(sftp, id);
528 silc_buffer_set(&tmpbuf, data, buf.len - 4);
529 attr = silc_sftp_attr_decode(&tmpbuf);
533 /* Call the callback */
534 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, attr);
538 case SILC_SFTP_EXTENDED_REPLY:
540 unsigned char *data = NULL;
542 SILC_LOG_DEBUG(("Extended reply packet"));
544 ret = silc_buffer_unformat(&buf,
545 SILC_STR_UI_INT(&id),
546 SILC_STR_UI_XNSTRING(&data, buf.len - 4),
552 req = silc_sftp_find_request(sftp, id);
556 /* Call the callback */
557 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
567 void silc_sftp_open(SilcSFTP sftp,
568 const char *filename,
569 SilcSFTPFileOperation pflags,
570 SilcSFTPAttributes attrs,
571 SilcSFTPHandleCallback callback,
574 SilcSFTPClient client = (SilcSFTPClient)sftp;
576 SilcBuffer attrs_buf;
579 SILC_LOG_DEBUG(("Open request"));
581 req = silc_calloc(1, sizeof(*req));
582 req->id = client->id++;
583 req->type = SILC_SFTP_OPEN;
584 req->handle = callback;
585 req->context = context;
586 silc_dlist_add(client->requests, req);
588 attrs_buf = silc_sftp_attr_encode(attrs);
589 len = 4 + 4 + strlen(filename) + 4 + attrs_buf->len;
591 silc_sftp_send_packet(client, req->type, len,
592 SILC_STR_UI_INT(req->id),
593 SILC_STR_UI_INT(strlen(filename)),
594 SILC_STR_UI32_STRING(filename),
595 SILC_STR_UI_INT(pflags),
596 SILC_STR_UI_XNSTRING(attrs_buf->data,
600 silc_buffer_free(attrs_buf);
603 void silc_sftp_close(SilcSFTP sftp,
604 SilcSFTPHandle handle,
605 SilcSFTPStatusCallback callback,
608 SilcSFTPClient client = (SilcSFTPClient)sftp;
611 const unsigned char *hdata;
614 SILC_LOG_DEBUG(("Close request"));
616 req = silc_calloc(1, sizeof(*req));
617 req->id = client->id++;
618 req->type = SILC_SFTP_CLOSE;
619 req->status = callback;
620 req->context = context;
621 silc_dlist_add(client->requests, req);
623 silc_sftp_handle_get(handle, &hdata, &hdata_len);
624 len = 4 + 4 + hdata_len;
626 silc_sftp_send_packet(client, req->type, len,
627 SILC_STR_UI_INT(req->id),
628 SILC_STR_UI_INT(hdata_len),
629 SILC_STR_UI_XNSTRING(hdata, hdata_len),
633 void silc_sftp_read(SilcSFTP sftp,
634 SilcSFTPHandle handle,
637 SilcSFTPDataCallback callback,
640 SilcSFTPClient client = (SilcSFTPClient)sftp;
643 const unsigned char *hdata;
646 SILC_LOG_DEBUG(("Read request"));
648 req = silc_calloc(1, sizeof(*req));
649 req->id = client->id++;
650 req->type = SILC_SFTP_READ;
651 req->data = callback;
652 req->context = context;
653 silc_dlist_add(client->requests, req);
655 silc_sftp_handle_get(handle, &hdata, &hdata_len);
656 len2 = 4 + 4 + hdata_len + 8 + 4;
658 silc_sftp_send_packet(client, req->type, len2,
659 SILC_STR_UI_INT(req->id),
660 SILC_STR_UI_INT(hdata_len),
661 SILC_STR_UI_XNSTRING(hdata, hdata_len),
662 SILC_STR_UI_INT64(offset),
663 SILC_STR_UI_INT(len),
667 void silc_sftp_write(SilcSFTP sftp,
668 SilcSFTPHandle handle,
670 const unsigned char *data,
672 SilcSFTPStatusCallback callback,
675 SilcSFTPClient client = (SilcSFTPClient)sftp;
678 const unsigned char *hdata;
681 SILC_LOG_DEBUG(("Write request"));
683 req = silc_calloc(1, sizeof(*req));
684 req->id = client->id++;
685 req->type = SILC_SFTP_WRITE;
686 req->status = callback;
687 req->context = context;
688 silc_dlist_add(client->requests, req);
690 silc_sftp_handle_get(handle, &hdata, &hdata_len);
691 len = 4 + 4 + hdata_len + 8 + 4 + data_len;
693 silc_sftp_send_packet(client, req->type, len,
694 SILC_STR_UI_INT(req->id),
695 SILC_STR_UI_INT(hdata_len),
696 SILC_STR_UI_XNSTRING(hdata, hdata_len),
697 SILC_STR_UI_INT64(offset),
698 SILC_STR_UI_INT(data_len),
699 SILC_STR_UI_XNSTRING(data, data_len),
703 void silc_sftp_remove(SilcSFTP sftp,
704 const char *filename,
705 SilcSFTPStatusCallback callback,
708 SilcSFTPClient client = (SilcSFTPClient)sftp;
712 SILC_LOG_DEBUG(("Remove request"));
714 req = silc_calloc(1, sizeof(*req));
715 req->id = client->id++;
716 req->type = SILC_SFTP_REMOVE;
717 req->status = callback;
718 req->context = context;
719 silc_dlist_add(client->requests, req);
721 len = 4 + 4 + strlen(filename);
723 silc_sftp_send_packet(client, req->type, len,
724 SILC_STR_UI_INT(req->id),
725 SILC_STR_UI_INT(strlen(filename)),
726 SILC_STR_UI32_STRING(filename),
730 void silc_sftp_rename(SilcSFTP sftp,
733 SilcSFTPStatusCallback callback,
736 SilcSFTPClient client = (SilcSFTPClient)sftp;
740 SILC_LOG_DEBUG(("Rename request"));
742 req = silc_calloc(1, sizeof(*req));
743 req->id = client->id++;
744 req->type = SILC_SFTP_RENAME;
745 req->status = callback;
746 req->context = context;
747 silc_dlist_add(client->requests, req);
749 len = 4 + 4 + strlen(oldname) + 4 + strlen(newname);
751 silc_sftp_send_packet(client, req->type, len,
752 SILC_STR_UI_INT(req->id),
753 SILC_STR_UI_INT(strlen(oldname)),
754 SILC_STR_UI32_STRING(oldname),
755 SILC_STR_UI_INT(strlen(newname)),
756 SILC_STR_UI32_STRING(newname),
760 void silc_sftp_mkdir(SilcSFTP sftp,
762 SilcSFTPAttributes attrs,
763 SilcSFTPStatusCallback callback,
766 SilcSFTPClient client = (SilcSFTPClient)sftp;
769 SilcBuffer attrs_buf;
771 SILC_LOG_DEBUG(("Mkdir request"));
773 req = silc_calloc(1, sizeof(*req));
774 req->id = client->id++;
775 req->type = SILC_SFTP_MKDIR;
776 req->status = callback;
777 req->context = context;
778 silc_dlist_add(client->requests, req);
780 attrs_buf = silc_sftp_attr_encode(attrs);
781 len = 4 + 4 + strlen(path) + attrs_buf->len;
783 silc_sftp_send_packet(client, req->type, len,
784 SILC_STR_UI_INT(req->id),
785 SILC_STR_UI_INT(strlen(path)),
786 SILC_STR_UI32_STRING(path),
787 SILC_STR_UI_XNSTRING(attrs_buf->data,
791 silc_buffer_free(attrs_buf);
794 void silc_sftp_rmdir(SilcSFTP sftp,
796 SilcSFTPStatusCallback callback,
799 SilcSFTPClient client = (SilcSFTPClient)sftp;
803 SILC_LOG_DEBUG(("Rmdir request"));
805 req = silc_calloc(1, sizeof(*req));
806 req->id = client->id++;
807 req->type = SILC_SFTP_RMDIR;
808 req->status = callback;
809 req->context = context;
810 silc_dlist_add(client->requests, req);
812 len = 4 + 4 + strlen(path);
814 silc_sftp_send_packet(client, req->type, len,
815 SILC_STR_UI_INT(req->id),
816 SILC_STR_UI_INT(strlen(path)),
817 SILC_STR_UI32_STRING(path),
821 void silc_sftp_opendir(SilcSFTP sftp,
823 SilcSFTPHandleCallback callback,
826 SilcSFTPClient client = (SilcSFTPClient)sftp;
830 SILC_LOG_DEBUG(("Opendir request"));
832 req = silc_calloc(1, sizeof(*req));
833 req->id = client->id++;
834 req->type = SILC_SFTP_OPENDIR;
835 req->handle = callback;
836 req->context = context;
837 silc_dlist_add(client->requests, req);
839 len = 4 + 4 + strlen(path);
841 silc_sftp_send_packet(client, req->type, len,
842 SILC_STR_UI_INT(req->id),
843 SILC_STR_UI_INT(strlen(path)),
844 SILC_STR_UI32_STRING(path),
848 void silc_sftp_readdir(SilcSFTP sftp,
849 SilcSFTPHandle handle,
850 SilcSFTPNameCallback callback,
853 SilcSFTPClient client = (SilcSFTPClient)sftp;
856 const unsigned char *hdata;
859 SILC_LOG_DEBUG(("Readdir request"));
861 req = silc_calloc(1, sizeof(*req));
862 req->id = client->id++;
863 req->type = SILC_SFTP_READDIR;
864 req->name = callback;
865 req->context = context;
866 silc_dlist_add(client->requests, req);
868 silc_sftp_handle_get(handle, &hdata, &hdata_len);
869 len = 4 + 4 + hdata_len;
871 silc_sftp_send_packet(client, req->type, len,
872 SILC_STR_UI_INT(req->id),
873 SILC_STR_UI_INT(hdata_len),
874 SILC_STR_UI_XNSTRING(hdata, hdata_len),
878 void silc_sftp_stat(SilcSFTP sftp,
880 SilcSFTPAttrCallback callback,
883 SilcSFTPClient client = (SilcSFTPClient)sftp;
887 SILC_LOG_DEBUG(("Stat request"));
889 req = silc_calloc(1, sizeof(*req));
890 req->id = client->id++;
891 req->type = SILC_SFTP_STAT;
892 req->attr = callback;
893 req->context = context;
894 silc_dlist_add(client->requests, req);
896 len = 4 + 4 + strlen(path);
898 silc_sftp_send_packet(client, req->type, len,
899 SILC_STR_UI_INT(req->id),
900 SILC_STR_UI_INT(strlen(path)),
901 SILC_STR_UI32_STRING(path),
905 void silc_sftp_lstat(SilcSFTP sftp,
907 SilcSFTPAttrCallback callback,
910 SilcSFTPClient client = (SilcSFTPClient)sftp;
914 SILC_LOG_DEBUG(("Lstat request"));
916 req = silc_calloc(1, sizeof(*req));
917 req->id = client->id++;
918 req->type = SILC_SFTP_LSTAT;
919 req->attr = callback;
920 req->context = context;
921 silc_dlist_add(client->requests, req);
923 len = 4 + 4 + strlen(path);
925 silc_sftp_send_packet(client, req->type, len,
926 SILC_STR_UI_INT(req->id),
927 SILC_STR_UI_INT(strlen(path)),
928 SILC_STR_UI32_STRING(path),
932 void silc_sftp_fstat(SilcSFTP sftp,
933 SilcSFTPHandle handle,
934 SilcSFTPAttrCallback callback,
937 SilcSFTPClient client = (SilcSFTPClient)sftp;
940 const unsigned char *hdata;
943 SILC_LOG_DEBUG(("Fstat request"));
945 req = silc_calloc(1, sizeof(*req));
946 req->id = client->id++;
947 req->type = SILC_SFTP_FSTAT;
948 req->attr = callback;
949 req->context = context;
950 silc_dlist_add(client->requests, req);
952 silc_sftp_handle_get(handle, &hdata, &hdata_len);
953 len = 4 + 4 + hdata_len;
955 silc_sftp_send_packet(client, req->type, len,
956 SILC_STR_UI_INT(req->id),
957 SILC_STR_UI_INT(hdata_len),
958 SILC_STR_UI_XNSTRING(hdata, hdata_len),
962 void silc_sftp_setstat(SilcSFTP sftp,
964 SilcSFTPAttributes attrs,
965 SilcSFTPStatusCallback callback,
968 SilcSFTPClient client = (SilcSFTPClient)sftp;
971 SilcBuffer attrs_buf;
973 SILC_LOG_DEBUG(("Setstat request"));
975 req = silc_calloc(1, sizeof(*req));
976 req->id = client->id++;
977 req->type = SILC_SFTP_SETSTAT;
978 req->status = callback;
979 req->context = context;
980 silc_dlist_add(client->requests, req);
982 attrs_buf = silc_sftp_attr_encode(attrs);
983 len = 4 + 4 + strlen(path) + attrs_buf->len;
985 silc_sftp_send_packet(client, req->type, len,
986 SILC_STR_UI_INT(req->id),
987 SILC_STR_UI_INT(strlen(path)),
988 SILC_STR_UI32_STRING(path),
989 SILC_STR_UI_XNSTRING(attrs_buf->data,
993 silc_buffer_free(attrs_buf);
996 void silc_sftp_fsetstat(SilcSFTP sftp,
997 SilcSFTPHandle handle,
998 SilcSFTPAttributes attrs,
999 SilcSFTPStatusCallback callback,
1002 SilcSFTPClient client = (SilcSFTPClient)sftp;
1003 SilcSFTPRequest req;
1005 SilcBuffer attrs_buf;
1006 const unsigned char *hdata;
1009 SILC_LOG_DEBUG(("Fsetstat request"));
1011 req = silc_calloc(1, sizeof(*req));
1012 req->id = client->id++;
1013 req->type = SILC_SFTP_FSETSTAT;
1014 req->status = callback;
1015 req->context = context;
1016 silc_dlist_add(client->requests, req);
1018 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1019 attrs_buf = silc_sftp_attr_encode(attrs);
1020 len = 4 + 4 + hdata_len + attrs_buf->len;
1022 silc_sftp_send_packet(client, req->type, len,
1023 SILC_STR_UI_INT(req->id),
1024 SILC_STR_UI_INT(hdata_len),
1025 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1026 SILC_STR_UI_XNSTRING(attrs_buf->data,
1030 silc_buffer_free(attrs_buf);
1033 void silc_sftp_readlink(SilcSFTP sftp,
1035 SilcSFTPNameCallback callback,
1038 SilcSFTPClient client = (SilcSFTPClient)sftp;
1039 SilcSFTPRequest req;
1042 SILC_LOG_DEBUG(("Readlink request"));
1044 req = silc_calloc(1, sizeof(*req));
1045 req->id = client->id++;
1046 req->type = SILC_SFTP_READLINK;
1047 req->name = callback;
1048 req->context = context;
1049 silc_dlist_add(client->requests, req);
1051 len = 4 + 4 + strlen(path);
1053 silc_sftp_send_packet(client, req->type, len,
1054 SILC_STR_UI_INT(req->id),
1055 SILC_STR_UI_INT(strlen(path)),
1056 SILC_STR_UI32_STRING(path),
1060 void silc_sftp_symlink(SilcSFTP sftp,
1061 const char *linkpath,
1062 const char *targetpath,
1063 SilcSFTPStatusCallback callback,
1066 SilcSFTPClient client = (SilcSFTPClient)sftp;
1067 SilcSFTPRequest req;
1070 SILC_LOG_DEBUG(("Symlink request"));
1072 req = silc_calloc(1, sizeof(*req));
1073 req->id = client->id++;
1074 req->type = SILC_SFTP_SYMLINK;
1075 req->status = callback;
1076 req->context = context;
1077 silc_dlist_add(client->requests, req);
1079 len = 4 + 4 + strlen(linkpath) + 4 + strlen(targetpath);
1081 silc_sftp_send_packet(client, req->type, len,
1082 SILC_STR_UI_INT(req->id),
1083 SILC_STR_UI_INT(strlen(linkpath)),
1084 SILC_STR_UI32_STRING(linkpath),
1085 SILC_STR_UI_INT(strlen(targetpath)),
1086 SILC_STR_UI32_STRING(targetpath),
1090 void silc_sftp_realpath(SilcSFTP sftp,
1092 SilcSFTPNameCallback callback,
1095 SilcSFTPClient client = (SilcSFTPClient)sftp;
1096 SilcSFTPRequest req;
1099 SILC_LOG_DEBUG(("Realpath request"));
1101 req = silc_calloc(1, sizeof(*req));
1102 req->id = client->id++;
1103 req->type = SILC_SFTP_REALPATH;
1104 req->name = callback;
1105 req->context = context;
1106 silc_dlist_add(client->requests, req);
1108 len = 4 + 4 + strlen(path);
1110 silc_sftp_send_packet(client, req->type, len,
1111 SILC_STR_UI_INT(req->id),
1112 SILC_STR_UI_INT(strlen(path)),
1113 SILC_STR_UI32_STRING(path),
1117 void silc_sftp_extended(SilcSFTP sftp,
1118 const char *request,
1119 const unsigned char *data,
1121 SilcSFTPExtendedCallback callback,
1124 SilcSFTPClient client = (SilcSFTPClient)sftp;
1125 SilcSFTPRequest req;
1128 SILC_LOG_DEBUG(("Extended request"));
1130 req = silc_calloc(1, sizeof(*req));
1131 req->id = client->id++;
1132 req->type = SILC_SFTP_WRITE;
1133 req->extended = callback;
1134 req->context = context;
1135 silc_dlist_add(client->requests, req);
1137 len = 4 + 4 + strlen(request) + data_len;
1139 silc_sftp_send_packet(client, req->type, len,
1140 SILC_STR_UI_INT(req->id),
1141 SILC_STR_UI_INT(strlen(request)),
1142 SILC_STR_UI32_STRING(request),
1143 SILC_STR_UI_XNSTRING(data, data_len),