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.
20 #include "silcincludes.h"
22 #include "sftp_util.h"
24 /* Request context. Every request will allocate this context and set
25 the correct callback function according the `type' field. */
29 SilcSFTPStatusCallback status;
30 SilcSFTPHandleCallback handle;
31 SilcSFTPDataCallback data;
32 SilcSFTPNameCallback name;
33 SilcSFTPAttrCallback attr;
34 SilcSFTPExtendedCallback extended;
38 /* SFTP client context */
40 SilcSocketConnection sock;
41 SilcSFTPSendPacketCallback send_packet;
43 SilcSFTPVersionCallback version;
44 void *version_context;
50 struct SilcSFTPHandleStruct {
55 /* Creates SilcSFTPHandle and returns pointer to it. The caller must free
58 static SilcSFTPHandle silc_sftp_handle_create(unsigned char *data,
61 SilcSFTPHandle handle;
63 handle = silc_calloc(1, sizeof(*handle));
64 handle->data = silc_calloc(data_len, sizeof(*handle->data));
65 memcpy(handle->data, data, data_len);
66 handle->data_len = data_len;
71 /* Deletes the handle indicated by the `handle'. */
73 static void silc_sftp_handle_delete(SilcSFTPHandle handle)
75 silc_free(handle->data);
79 /* Returns the handle data of the `handle' to the `data' pointer. */
81 static void silc_sftp_handle_get(SilcSFTPHandle handle,
82 const unsigned char **data,
85 *data = (const unsigned char *)handle->data;
86 *data_len = handle->data_len;
89 /* General routine to send SFTP packet to the SFTP server. */
91 static void silc_sftp_send_packet(SilcSFTPClient sftp,
99 packet = silc_sftp_packet_encode_vp(type, len, vp);
105 SILC_LOG_HEXDUMP(("SFTP packet to server"), packet->data, packet->len);
107 /* Send the packet */
108 (*sftp->send_packet)(sftp->sock, packet, sftp->send_context);
110 silc_buffer_free(packet);
113 /* Finds request by request ID. */
115 static SilcSFTPRequest silc_sftp_find_request(SilcSFTPClient sftp, uint32 id)
119 SILC_LOG_DEBUG(("Finding request ID: %d", id));
121 silc_dlist_start(sftp->requests);
122 while ((req = silc_dlist_get(sftp->requests)) != SILC_LIST_END) {
127 SILC_LOG_DEBUG(("Unknown request ID"));
132 /* Function used to call the request callback indicated by the `req'. The
133 `status' will be sent to the callback function as the status of the
134 operation. The variable argument list includes the status and req->type
137 static void silc_sftp_call_request(SilcSFTPClient sftp,
140 SilcSFTPStatus status, ...)
144 SILC_LOG_DEBUG(("Start"));
146 va_start(vp, status);
155 if (status != SILC_SFTP_STATUS_OK) {
157 (*req->data)((SilcSFTP)sftp, status, NULL, 0, req->context);
161 data = (unsigned char *)va_arg(vp, unsigned char *);
162 data_len = (uint32)va_arg(vp, uint32);
165 (*req->data)((SilcSFTP)sftp, status, (const unsigned char *)data,
166 data_len, req->context);
171 case SILC_SFTP_OPENDIR:
173 /* Handle returned */
174 SilcSFTPHandle handle;
175 unsigned char *hdata;
178 if (status != SILC_SFTP_STATUS_OK) {
180 (*req->handle)((SilcSFTP)sftp, status, NULL, req->context);
184 hdata = (unsigned char *)va_arg(vp, unsigned char *);
185 hdata_len = (uint32)va_arg(vp, uint32);
186 handle = silc_sftp_handle_create(hdata, hdata_len);
189 (*req->handle)((SilcSFTP)sftp, status, handle, req->context);
193 case SILC_SFTP_CLOSE:
194 case SILC_SFTP_WRITE:
195 case SILC_SFTP_REMOVE:
196 case SILC_SFTP_RENAME:
197 case SILC_SFTP_MKDIR:
198 case SILC_SFTP_RMDIR:
199 case SILC_SFTP_SETSTAT:
200 case SILC_SFTP_FSETSTAT:
201 case SILC_SFTP_SYMLINK:
203 /* Status returned */
204 char *message, *language_tag;
206 message = (char *)va_arg(vp, char *);
207 language_tag = (char *)va_arg(vp, char *);
210 (*req->status)((SilcSFTP)sftp, status, (const char *)message,
211 (const char *)language_tag, req->context);
216 case SILC_SFTP_LSTAT:
217 case SILC_SFTP_FSTAT:
219 /* Attributes returned */
220 SilcSFTPAttributes attr;
222 if (status != SILC_SFTP_STATUS_OK) {
224 (*req->attr)((SilcSFTP)sftp, status, NULL, req->context);
228 attr = (SilcSFTPAttributes)va_arg(vp, SilcSFTPAttributes);
231 (*req->attr)((SilcSFTP)sftp, status, (const SilcSFTPAttributes)attr,
236 case SILC_SFTP_READDIR:
237 case SILC_SFTP_REALPATH:
238 case SILC_SFTP_READLINK:
240 /* Name(s) returned */
243 if (status != SILC_SFTP_STATUS_OK) {
245 (*req->name)((SilcSFTP)sftp, status, NULL, req->context);
249 name = (SilcSFTPName)va_arg(vp, SilcSFTPName);
252 (*req->name)((SilcSFTP)sftp, status, name, req->context);
256 case SILC_SFTP_EXTENDED:
258 /* Extended reply returned */
262 if (status != SILC_SFTP_STATUS_OK) {
264 (*req->extended)((SilcSFTP)sftp, status, NULL, 0, req->context);
268 data = (unsigned char *)va_arg(vp, unsigned char *);
269 data_len = (uint32)va_arg(vp, uint32);
272 (*req->extended)((SilcSFTP)sftp, status, (const unsigned char *)data,
273 data_len, req->context);
281 /* Remove this request */
282 silc_dlist_del(sftp->requests, req);
288 /* Starts SFTP client by associating the socket connection `sock' to the
289 created SFTP client context. The version callback indicated by the
290 `callback' will be called after the SFTP session has been started
291 and server has returned the version of the protocol. The SFTP client
292 context is returned in the callback too. This returns the allocated
293 SFTP client context or NULL on error. */
295 SilcSFTP silc_sftp_client_start(SilcSocketConnection sock,
296 SilcSFTPSendPacketCallback send_packet,
298 SilcSFTPVersionCallback callback,
306 sftp = silc_calloc(1, sizeof(*sftp));
308 sftp->send_packet = send_packet;
309 sftp->send_context = send_context;
310 sftp->version = callback;
311 sftp->version_context = context;
312 sftp->requests = silc_dlist_init();
314 /* Send the SFTP session initialization to the server */
315 silc_sftp_send_packet(sftp, SILC_SFTP_INIT, 4,
316 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
319 return (SilcSFTP)sftp;
322 /* Shutdown's the SFTP client. The caller is responsible of closing
323 the associated socket connection. The SFTP context is freed and is
324 invalid after this function returns. */
326 void silc_sftp_client_shutdown(SilcSFTP context)
328 SilcSFTPClient sftp = (SilcSFTPClient)context;
330 silc_dlist_uninit(sftp->requests);
334 /* Function that is called to process the incmoing SFTP packet. */
335 /* XXX Some day this will go away and we have automatic receive callbacks
336 for SilcSocketConnection API or SilcPacketContext API. */
338 void silc_sftp_client_receive_process(SilcSFTP context,
339 SilcSocketConnection sock,
340 SilcPacketContext *packet)
342 SilcSFTPClient sftp = (SilcSFTPClient)context;
345 const unsigned char *payload = NULL;
348 SilcBufferStruct buf;
351 SILC_LOG_DEBUG(("Start"));
353 /* Parse the packet */
354 type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload,
359 silc_buffer_set(&buf, (unsigned char *)payload, payload_len);
362 case SILC_SFTP_VERSION:
364 SilcSFTPVersion version;
366 SILC_LOG_DEBUG(("Version packet"));
368 ret = silc_buffer_unformat(&buf,
369 SILC_STR_UI_INT(&version),
372 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_FAILURE, 0,
373 sftp->version_context);
377 /* Call the callback */
378 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_OK, version,
379 sftp->version_context);
383 case SILC_SFTP_STATUS:
386 char *message = NULL, *language_tag = NULL;
388 SILC_LOG_DEBUG(("Status packet"));
390 ret = silc_buffer_unformat(&buf,
391 SILC_STR_UI_INT(&id),
392 SILC_STR_UI_INT(&status),
397 if (status != SILC_SFTP_STATUS_OK) {
398 silc_buffer_pull(&buf, 8);
399 ret = silc_buffer_unformat(&buf,
400 SILC_STR_UI32_STRING_ALLOC(&message),
401 SILC_STR_UI32_STRING_ALLOC(&language_tag),
406 silc_buffer_push(&buf, 8);
410 req = silc_sftp_find_request(sftp, id);
413 silc_free(language_tag);
417 /* Call the callback */
418 silc_sftp_call_request(sftp, req, type, status, message, language_tag);
421 silc_free(language_tag);
425 case SILC_SFTP_HANDLE:
427 unsigned char *handle = NULL;
430 SILC_LOG_DEBUG(("Handle packet"));
432 ret = silc_buffer_unformat(&buf,
433 SILC_STR_UI_INT(&id),
434 SILC_STR_UI32_NSTRING(&handle,
441 req = silc_sftp_find_request(sftp, id);
445 /* Call the callback */
446 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
453 unsigned char *data = NULL;
456 SILC_LOG_DEBUG(("Data packet"));
458 ret = silc_buffer_unformat(&buf,
459 SILC_STR_UI_INT(&id),
460 SILC_STR_UI32_NSTRING(&data, &data_len),
466 req = silc_sftp_find_request(sftp, id);
470 /* Call the callback */
471 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
479 SilcSFTPName name = NULL;
481 SILC_LOG_DEBUG(("Name packet"));
483 ret = silc_buffer_unformat(&buf,
484 SILC_STR_UI_INT(&id),
485 SILC_STR_UI_INT(&count),
491 req = silc_sftp_find_request(sftp, id);
495 silc_buffer_pull(&buf, 8);
496 name = silc_sftp_name_decode(count, &buf);
499 silc_buffer_push(&buf, 8);
501 /* Call the callback */
502 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, name);
503 silc_sftp_name_free(name);
507 case SILC_SFTP_ATTRS:
509 SilcSFTPAttributes attr = NULL;
511 SilcBufferStruct tmpbuf;
513 SILC_LOG_DEBUG(("Attributes packet"));
515 ret = silc_buffer_unformat(&buf,
516 SILC_STR_UI_INT(&id),
517 SILC_STR_UI_XNSTRING(&data, buf.len - 4),
523 req = silc_sftp_find_request(sftp, id);
527 silc_buffer_set(&tmpbuf, data, buf.len - 4);
528 attr = silc_sftp_attr_decode(&tmpbuf);
532 /* Call the callback */
533 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, attr);
537 case SILC_SFTP_EXTENDED_REPLY:
539 unsigned char *data = NULL;
541 SILC_LOG_DEBUG(("Extended reply packet"));
543 ret = silc_buffer_unformat(&buf,
544 SILC_STR_UI_INT(&id),
545 SILC_STR_UI_XNSTRING(&data, buf.len - 4),
551 req = silc_sftp_find_request(sftp, id);
555 /* Call the callback */
556 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
566 void silc_sftp_open(SilcSFTP sftp,
567 const char *filename,
568 SilcSFTPFileOperation pflags,
569 SilcSFTPAttributes attrs,
570 SilcSFTPHandleCallback callback,
573 SilcSFTPClient client = (SilcSFTPClient)sftp;
575 SilcBuffer attrs_buf;
578 SILC_LOG_DEBUG(("Open request"));
580 req = silc_calloc(1, sizeof(*req));
581 req->id = client->id++;
582 req->type = SILC_SFTP_OPEN;
583 req->handle = callback;
584 req->context = context;
585 silc_dlist_add(client->requests, req);
587 attrs_buf = silc_sftp_attr_encode(attrs);
588 len = 4 + 4 + strlen(filename) + 4 + attrs_buf->len;
590 silc_sftp_send_packet(client, req->type, len,
591 SILC_STR_UI_INT(req->id),
592 SILC_STR_UI_INT(strlen(filename)),
593 SILC_STR_UI32_STRING(filename),
594 SILC_STR_UI_INT(pflags),
595 SILC_STR_UI_XNSTRING(attrs_buf->data,
599 silc_buffer_free(attrs_buf);
602 void silc_sftp_close(SilcSFTP sftp,
603 SilcSFTPHandle handle,
604 SilcSFTPStatusCallback callback,
607 SilcSFTPClient client = (SilcSFTPClient)sftp;
610 const unsigned char *hdata;
613 SILC_LOG_DEBUG(("Close request"));
615 req = silc_calloc(1, sizeof(*req));
616 req->id = client->id++;
617 req->type = SILC_SFTP_CLOSE;
618 req->status = callback;
619 req->context = context;
620 silc_dlist_add(client->requests, req);
622 silc_sftp_handle_get(handle, &hdata, &hdata_len);
623 len = 4 + 4 + hdata_len;
625 silc_sftp_send_packet(client, req->type, len,
626 SILC_STR_UI_INT(req->id),
627 SILC_STR_UI_INT(hdata_len),
628 SILC_STR_UI_XNSTRING(hdata, hdata_len),
632 void silc_sftp_read(SilcSFTP sftp,
633 SilcSFTPHandle handle,
636 SilcSFTPDataCallback callback,
639 SilcSFTPClient client = (SilcSFTPClient)sftp;
642 const unsigned char *hdata;
645 SILC_LOG_DEBUG(("Read request"));
647 req = silc_calloc(1, sizeof(*req));
648 req->id = client->id++;
649 req->type = SILC_SFTP_READ;
650 req->data = callback;
651 req->context = context;
652 silc_dlist_add(client->requests, req);
654 silc_sftp_handle_get(handle, &hdata, &hdata_len);
655 len2 = 4 + 4 + hdata_len + 8 + 4;
657 silc_sftp_send_packet(client, req->type, len2,
658 SILC_STR_UI_INT(req->id),
659 SILC_STR_UI_INT(hdata_len),
660 SILC_STR_UI_XNSTRING(hdata, hdata_len),
661 SILC_STR_UI_INT64(offset),
662 SILC_STR_UI_INT(len),
666 void silc_sftp_write(SilcSFTP sftp,
667 SilcSFTPHandle handle,
669 const unsigned char *data,
671 SilcSFTPStatusCallback callback,
674 SilcSFTPClient client = (SilcSFTPClient)sftp;
677 const unsigned char *hdata;
680 SILC_LOG_DEBUG(("Write request"));
682 req = silc_calloc(1, sizeof(*req));
683 req->id = client->id++;
684 req->type = SILC_SFTP_WRITE;
685 req->status = callback;
686 req->context = context;
687 silc_dlist_add(client->requests, req);
689 silc_sftp_handle_get(handle, &hdata, &hdata_len);
690 len = 4 + 4 + hdata_len + 8 + 4 + data_len;
692 silc_sftp_send_packet(client, req->type, len,
693 SILC_STR_UI_INT(req->id),
694 SILC_STR_UI_INT(hdata_len),
695 SILC_STR_UI_XNSTRING(hdata, hdata_len),
696 SILC_STR_UI_INT64(offset),
697 SILC_STR_UI_INT(data_len),
698 SILC_STR_UI_XNSTRING(data, data_len),
702 void silc_sftp_remove(SilcSFTP sftp,
703 const char *filename,
704 SilcSFTPStatusCallback callback,
707 SilcSFTPClient client = (SilcSFTPClient)sftp;
711 SILC_LOG_DEBUG(("Remove request"));
713 req = silc_calloc(1, sizeof(*req));
714 req->id = client->id++;
715 req->type = SILC_SFTP_REMOVE;
716 req->status = callback;
717 req->context = context;
718 silc_dlist_add(client->requests, req);
720 len = 4 + 4 + strlen(filename);
722 silc_sftp_send_packet(client, req->type, len,
723 SILC_STR_UI_INT(req->id),
724 SILC_STR_UI_INT(strlen(filename)),
725 SILC_STR_UI32_STRING(filename),
729 void silc_sftp_rename(SilcSFTP sftp,
732 SilcSFTPStatusCallback callback,
735 SilcSFTPClient client = (SilcSFTPClient)sftp;
739 SILC_LOG_DEBUG(("Rename request"));
741 req = silc_calloc(1, sizeof(*req));
742 req->id = client->id++;
743 req->type = SILC_SFTP_RENAME;
744 req->status = callback;
745 req->context = context;
746 silc_dlist_add(client->requests, req);
748 len = 4 + 4 + strlen(oldname) + 4 + strlen(newname);
750 silc_sftp_send_packet(client, req->type, len,
751 SILC_STR_UI_INT(req->id),
752 SILC_STR_UI_INT(strlen(oldname)),
753 SILC_STR_UI32_STRING(oldname),
754 SILC_STR_UI_INT(strlen(newname)),
755 SILC_STR_UI32_STRING(newname),
759 void silc_sftp_mkdir(SilcSFTP sftp,
761 SilcSFTPAttributes attrs,
762 SilcSFTPStatusCallback callback,
765 SilcSFTPClient client = (SilcSFTPClient)sftp;
768 SilcBuffer attrs_buf;
770 SILC_LOG_DEBUG(("Mkdir request"));
772 req = silc_calloc(1, sizeof(*req));
773 req->id = client->id++;
774 req->type = SILC_SFTP_MKDIR;
775 req->status = callback;
776 req->context = context;
777 silc_dlist_add(client->requests, req);
779 attrs_buf = silc_sftp_attr_encode(attrs);
780 len = 4 + 4 + strlen(path) + attrs_buf->len;
782 silc_sftp_send_packet(client, req->type, len,
783 SILC_STR_UI_INT(req->id),
784 SILC_STR_UI_INT(strlen(path)),
785 SILC_STR_UI32_STRING(path),
786 SILC_STR_UI_XNSTRING(attrs_buf->data,
790 silc_buffer_free(attrs_buf);
793 void silc_sftp_rmdir(SilcSFTP sftp,
795 SilcSFTPStatusCallback callback,
798 SilcSFTPClient client = (SilcSFTPClient)sftp;
802 SILC_LOG_DEBUG(("Rmdir request"));
804 req = silc_calloc(1, sizeof(*req));
805 req->id = client->id++;
806 req->type = SILC_SFTP_RMDIR;
807 req->status = callback;
808 req->context = context;
809 silc_dlist_add(client->requests, req);
811 len = 4 + 4 + strlen(path);
813 silc_sftp_send_packet(client, req->type, len,
814 SILC_STR_UI_INT(req->id),
815 SILC_STR_UI_INT(strlen(path)),
816 SILC_STR_UI32_STRING(path),
820 void silc_sftp_opendir(SilcSFTP sftp,
822 SilcSFTPHandleCallback callback,
825 SilcSFTPClient client = (SilcSFTPClient)sftp;
829 SILC_LOG_DEBUG(("Opendir request"));
831 req = silc_calloc(1, sizeof(*req));
832 req->id = client->id++;
833 req->type = SILC_SFTP_OPENDIR;
834 req->handle = callback;
835 req->context = context;
836 silc_dlist_add(client->requests, req);
838 len = 4 + 4 + strlen(path);
840 silc_sftp_send_packet(client, req->type, len,
841 SILC_STR_UI_INT(req->id),
842 SILC_STR_UI_INT(strlen(path)),
843 SILC_STR_UI32_STRING(path),
847 void silc_sftp_readdir(SilcSFTP sftp,
848 SilcSFTPHandle handle,
849 SilcSFTPNameCallback callback,
852 SilcSFTPClient client = (SilcSFTPClient)sftp;
855 const unsigned char *hdata;
858 SILC_LOG_DEBUG(("Readdir request"));
860 req = silc_calloc(1, sizeof(*req));
861 req->id = client->id++;
862 req->type = SILC_SFTP_READDIR;
863 req->name = callback;
864 req->context = context;
865 silc_dlist_add(client->requests, req);
867 silc_sftp_handle_get(handle, &hdata, &hdata_len);
868 len = 4 + 4 + hdata_len;
870 silc_sftp_send_packet(client, req->type, len,
871 SILC_STR_UI_INT(req->id),
872 SILC_STR_UI_INT(hdata_len),
873 SILC_STR_UI_XNSTRING(hdata, hdata_len),
877 void silc_sftp_stat(SilcSFTP sftp,
879 SilcSFTPAttrCallback callback,
882 SilcSFTPClient client = (SilcSFTPClient)sftp;
886 SILC_LOG_DEBUG(("Stat request"));
888 req = silc_calloc(1, sizeof(*req));
889 req->id = client->id++;
890 req->type = SILC_SFTP_STAT;
891 req->attr = callback;
892 req->context = context;
893 silc_dlist_add(client->requests, req);
895 len = 4 + 4 + strlen(path);
897 silc_sftp_send_packet(client, req->type, len,
898 SILC_STR_UI_INT(req->id),
899 SILC_STR_UI_INT(strlen(path)),
900 SILC_STR_UI32_STRING(path),
904 void silc_sftp_lstat(SilcSFTP sftp,
906 SilcSFTPAttrCallback callback,
909 SilcSFTPClient client = (SilcSFTPClient)sftp;
913 SILC_LOG_DEBUG(("Lstat request"));
915 req = silc_calloc(1, sizeof(*req));
916 req->id = client->id++;
917 req->type = SILC_SFTP_LSTAT;
918 req->attr = callback;
919 req->context = context;
920 silc_dlist_add(client->requests, req);
922 len = 4 + 4 + strlen(path);
924 silc_sftp_send_packet(client, req->type, len,
925 SILC_STR_UI_INT(req->id),
926 SILC_STR_UI_INT(strlen(path)),
927 SILC_STR_UI32_STRING(path),
931 void silc_sftp_fstat(SilcSFTP sftp,
932 SilcSFTPHandle handle,
933 SilcSFTPAttrCallback callback,
936 SilcSFTPClient client = (SilcSFTPClient)sftp;
939 const unsigned char *hdata;
942 SILC_LOG_DEBUG(("Fstat request"));
944 req = silc_calloc(1, sizeof(*req));
945 req->id = client->id++;
946 req->type = SILC_SFTP_FSTAT;
947 req->attr = callback;
948 req->context = context;
949 silc_dlist_add(client->requests, req);
951 silc_sftp_handle_get(handle, &hdata, &hdata_len);
952 len = 4 + 4 + hdata_len;
954 silc_sftp_send_packet(client, req->type, len,
955 SILC_STR_UI_INT(req->id),
956 SILC_STR_UI_INT(hdata_len),
957 SILC_STR_UI_XNSTRING(hdata, hdata_len),
961 void silc_sftp_setstat(SilcSFTP sftp,
963 SilcSFTPAttributes attrs,
964 SilcSFTPStatusCallback callback,
967 SilcSFTPClient client = (SilcSFTPClient)sftp;
970 SilcBuffer attrs_buf;
972 SILC_LOG_DEBUG(("Setstat request"));
974 req = silc_calloc(1, sizeof(*req));
975 req->id = client->id++;
976 req->type = SILC_SFTP_SETSTAT;
977 req->status = callback;
978 req->context = context;
979 silc_dlist_add(client->requests, req);
981 attrs_buf = silc_sftp_attr_encode(attrs);
982 len = 4 + 4 + strlen(path) + attrs_buf->len;
984 silc_sftp_send_packet(client, req->type, len,
985 SILC_STR_UI_INT(req->id),
986 SILC_STR_UI_INT(strlen(path)),
987 SILC_STR_UI32_STRING(path),
988 SILC_STR_UI_XNSTRING(attrs_buf->data,
992 silc_buffer_free(attrs_buf);
995 void silc_sftp_fsetstat(SilcSFTP sftp,
996 SilcSFTPHandle handle,
997 SilcSFTPAttributes attrs,
998 SilcSFTPStatusCallback callback,
1001 SilcSFTPClient client = (SilcSFTPClient)sftp;
1002 SilcSFTPRequest req;
1004 SilcBuffer attrs_buf;
1005 const unsigned char *hdata;
1008 SILC_LOG_DEBUG(("Fsetstat request"));
1010 req = silc_calloc(1, sizeof(*req));
1011 req->id = client->id++;
1012 req->type = SILC_SFTP_FSETSTAT;
1013 req->status = callback;
1014 req->context = context;
1015 silc_dlist_add(client->requests, req);
1017 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1018 attrs_buf = silc_sftp_attr_encode(attrs);
1019 len = 4 + 4 + hdata_len + attrs_buf->len;
1021 silc_sftp_send_packet(client, req->type, len,
1022 SILC_STR_UI_INT(req->id),
1023 SILC_STR_UI_INT(hdata_len),
1024 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1025 SILC_STR_UI_XNSTRING(attrs_buf->data,
1029 silc_buffer_free(attrs_buf);
1032 void silc_sftp_readlink(SilcSFTP sftp,
1034 SilcSFTPNameCallback callback,
1037 SilcSFTPClient client = (SilcSFTPClient)sftp;
1038 SilcSFTPRequest req;
1041 SILC_LOG_DEBUG(("Readlink request"));
1043 req = silc_calloc(1, sizeof(*req));
1044 req->id = client->id++;
1045 req->type = SILC_SFTP_READLINK;
1046 req->name = callback;
1047 req->context = context;
1048 silc_dlist_add(client->requests, req);
1050 len = 4 + 4 + strlen(path);
1052 silc_sftp_send_packet(client, req->type, len,
1053 SILC_STR_UI_INT(req->id),
1054 SILC_STR_UI_INT(strlen(path)),
1055 SILC_STR_UI32_STRING(path),
1059 void silc_sftp_symlink(SilcSFTP sftp,
1060 const char *linkpath,
1061 const char *targetpath,
1062 SilcSFTPStatusCallback callback,
1065 SilcSFTPClient client = (SilcSFTPClient)sftp;
1066 SilcSFTPRequest req;
1069 SILC_LOG_DEBUG(("Symlink request"));
1071 req = silc_calloc(1, sizeof(*req));
1072 req->id = client->id++;
1073 req->type = SILC_SFTP_SYMLINK;
1074 req->status = callback;
1075 req->context = context;
1076 silc_dlist_add(client->requests, req);
1078 len = 4 + 4 + strlen(linkpath) + 4 + strlen(targetpath);
1080 silc_sftp_send_packet(client, req->type, len,
1081 SILC_STR_UI_INT(req->id),
1082 SILC_STR_UI_INT(strlen(linkpath)),
1083 SILC_STR_UI32_STRING(linkpath),
1084 SILC_STR_UI_INT(strlen(targetpath)),
1085 SILC_STR_UI32_STRING(targetpath),
1089 void silc_sftp_realpath(SilcSFTP sftp,
1091 SilcSFTPNameCallback callback,
1094 SilcSFTPClient client = (SilcSFTPClient)sftp;
1095 SilcSFTPRequest req;
1098 SILC_LOG_DEBUG(("Realpath request"));
1100 req = silc_calloc(1, sizeof(*req));
1101 req->id = client->id++;
1102 req->type = SILC_SFTP_REALPATH;
1103 req->name = callback;
1104 req->context = context;
1105 silc_dlist_add(client->requests, req);
1107 len = 4 + 4 + strlen(path);
1109 silc_sftp_send_packet(client, req->type, len,
1110 SILC_STR_UI_INT(req->id),
1111 SILC_STR_UI_INT(strlen(path)),
1112 SILC_STR_UI32_STRING(path),
1116 void silc_sftp_extended(SilcSFTP sftp,
1117 const char *request,
1118 const unsigned char *data,
1120 SilcSFTPExtendedCallback callback,
1123 SilcSFTPClient client = (SilcSFTPClient)sftp;
1124 SilcSFTPRequest req;
1127 SILC_LOG_DEBUG(("Extended request"));
1129 req = silc_calloc(1, sizeof(*req));
1130 req->id = client->id++;
1131 req->type = SILC_SFTP_WRITE;
1132 req->extended = callback;
1133 req->context = context;
1134 silc_dlist_add(client->requests, req);
1136 len = 4 + 4 + strlen(request) + data_len;
1138 silc_sftp_send_packet(client, req->type, len,
1139 SILC_STR_UI_INT(req->id),
1140 SILC_STR_UI_INT(strlen(request)),
1141 SILC_STR_UI32_STRING(request),
1142 SILC_STR_UI_XNSTRING(data, data_len),