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 /* Encodes a SFTP packet of type `packet' of length `len'. The variable
25 argument list is encoded as data payload to the buffer. Returns the
26 encoded packet or NULL on error. The caller must free the returned
29 SilcBuffer silc_sftp_packet_encode(SilcSFTPPacket packet, uint32 len, ...)
35 buffer = silc_sftp_packet_encode_vp(packet, len, vp);
41 /* Same as silc_sftp_packet_encode but takes the variable argument list
42 pointer as argument. */
44 SilcBuffer silc_sftp_packet_encode_vp(SilcSFTPPacket packet, uint32 len,
50 buffer = silc_buffer_alloc(4 + 1 + len);
51 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
52 silc_buffer_format(buffer,
54 SILC_STR_UI_CHAR(packet),
56 silc_buffer_pull(buffer, 5);
58 ret = silc_buffer_format_vp(buffer, vp);
60 silc_buffer_free(buffer);
64 silc_buffer_push(buffer, 5);
69 /* Decodes the SFTP packet data `packet' and return the SFTP packet type.
70 The payload of the packet is returned to the `payload' pointer. Returns
71 0 if error occurred during decoding. */
73 SilcSFTPPacket silc_sftp_packet_decode(SilcBuffer packet,
74 unsigned char **payload,
81 ret = silc_buffer_unformat(packet,
82 SILC_STR_UI_INT(&len),
83 SILC_STR_UI_CHAR(&type),
88 if (type < SILC_SFTP_INIT || type > SILC_SFTP_EXTENDED_REPLY)
91 if (len > (packet->len - 5))
94 silc_buffer_pull(packet, 5);
95 ret = silc_buffer_unformat(packet,
96 SILC_STR_UI_XNSTRING(payload, len),
101 silc_buffer_push(packet, 5);
105 return (SilcSFTPPacket)type;
108 /* Encodes the SFTP attributes to a buffer and returns the allocated buffer.
109 The caller must free the buffer. */
111 SilcBuffer silc_sftp_attr_encode(SilcSFTPAttributes attr)
116 if (attr->flags & SILC_SFTP_ATTR_SIZE)
118 if (attr->flags & SILC_SFTP_ATTR_UIDGID)
120 if (attr->flags & SILC_SFTP_ATTR_PERMISSIONS)
122 if (attr->flags & SILC_SFTP_ATTR_ACMODTIME)
124 if (attr->flags & SILC_SFTP_ATTR_EXTENDED) {
126 for (i = 0; i < attr->extended_count; i++) {
128 len += attr->extended_type[i]->len;
129 len += attr->extended_data[i]->len;
133 buffer = silc_buffer_alloc(len);
134 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
136 silc_buffer_format(buffer,
137 SILC_STR_UI_INT(attr->flags),
139 silc_buffer_pull(buffer, 4);
141 if (attr->flags & SILC_SFTP_ATTR_SIZE) {
142 silc_buffer_format(buffer,
143 SILC_STR_UI_INT64(attr->size),
145 silc_buffer_pull(buffer, 8);
148 if (attr->flags & SILC_SFTP_ATTR_UIDGID) {
149 silc_buffer_format(buffer,
150 SILC_STR_UI_INT(attr->uid),
151 SILC_STR_UI_INT(attr->gid),
153 silc_buffer_pull(buffer, 8);
156 if (attr->flags & SILC_SFTP_ATTR_PERMISSIONS) {
157 silc_buffer_format(buffer,
158 SILC_STR_UI_INT(attr->permissions),
160 silc_buffer_pull(buffer, 4);
163 if (attr->flags & SILC_SFTP_ATTR_ACMODTIME) {
164 silc_buffer_format(buffer,
165 SILC_STR_UI_INT(attr->atime),
166 SILC_STR_UI_INT(attr->mtime),
168 silc_buffer_pull(buffer, 8);
171 if (attr->flags & SILC_SFTP_ATTR_EXTENDED) {
172 silc_buffer_format(buffer,
173 SILC_STR_UI_INT(attr->extended_count),
175 silc_buffer_pull(buffer, 4);
177 for (i = 0; i < attr->extended_count; i++) {
179 silc_buffer_format(buffer,
180 SILC_STR_UI_INT(attr->extended_type[i]->len),
181 SILC_STR_UI_XNSTRING(attr->extended_type[i]->data,
182 attr->extended_type[i]->len),
183 SILC_STR_UI_INT(attr->extended_data[i]->len),
184 SILC_STR_UI_XNSTRING(attr->extended_data[i]->data,
185 attr->extended_data[i]->len),
187 silc_buffer_pull(buffer, ret);
191 silc_buffer_push(buffer, buffer->data - buffer->head);
196 /* Decodes SilcSFTPAttributes from the buffer `buffer'. Returns the allocated
197 attributes that the caller must free or NULL on error. */
199 SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer)
201 SilcSFTPAttributes attr;
203 attr = silc_calloc(1, sizeof(*attr));
205 if (silc_buffer_unformat(buffer,
206 SILC_STR_UI_INT(&attr->flags),
210 silc_buffer_pull(buffer, 4);
212 if (attr->flags & SILC_SFTP_ATTR_SIZE) {
213 if (silc_buffer_unformat(buffer,
214 SILC_STR_UI_INT64(&attr->size),
218 silc_buffer_pull(buffer, 8);
221 if (attr->flags & SILC_SFTP_ATTR_UIDGID) {
222 if (silc_buffer_unformat(buffer,
223 SILC_STR_UI_INT(&attr->uid),
224 SILC_STR_UI_INT(&attr->gid),
228 silc_buffer_pull(buffer, 8);
231 if (attr->flags & SILC_SFTP_ATTR_PERMISSIONS) {
232 if (silc_buffer_unformat(buffer,
233 SILC_STR_UI_INT(&attr->permissions),
237 silc_buffer_pull(buffer, 4);
240 if (attr->flags & SILC_SFTP_ATTR_ACMODTIME) {
241 if (silc_buffer_unformat(buffer,
242 SILC_STR_UI_INT(&attr->atime),
243 SILC_STR_UI_INT(&attr->mtime),
247 silc_buffer_pull(buffer, 8);
250 if (attr->flags & SILC_SFTP_ATTR_EXTENDED) {
253 if (silc_buffer_unformat(buffer,
254 SILC_STR_UI_INT(&attr->extended_count),
258 silc_buffer_pull(buffer, 4);
260 attr->extended_type = silc_calloc(attr->extended_count,
261 sizeof(*attr->extended_type));
262 attr->extended_data = silc_calloc(attr->extended_count,
263 sizeof(*attr->extended_data));
264 for (i = 0; i < attr->extended_count; i++) {
265 unsigned char *tmp, *tmp2;
266 uint32 tmp_len, tmp2_len;
268 if (silc_buffer_unformat(buffer,
269 SILC_STR_UI32_NSTRING(&tmp, &tmp_len),
270 SILC_STR_UI32_NSTRING(&tmp2, &tmp2_len),
274 attr->extended_type[i] = silc_buffer_alloc(tmp_len);
275 attr->extended_data[i] = silc_buffer_alloc(tmp2_len);
276 silc_buffer_put(attr->extended_type[i], tmp, tmp_len);
277 silc_buffer_put(attr->extended_data[i], tmp2, tmp2_len);
279 silc_buffer_pull(buffer, tmp_len + 4 + tmp2_len + 4);
286 silc_sftp_attr_free(attr);
290 /* Frees the attributes context and its internals. */
292 void silc_sftp_attr_free(SilcSFTPAttributes attr)
296 for (i = 0; i < attr->extended_count; i++) {
297 silc_buffer_free(attr->extended_type[i]);
298 silc_buffer_free(attr->extended_data[i]);
300 silc_free(attr->extended_type);
301 silc_free(attr->extended_data);
305 /* Adds an entry to the `name' context. */
307 void silc_sftp_name_add(SilcSFTPName name, const char *short_name,
308 const char *long_name, SilcSFTPAttributes attrs)
310 name->filename = silc_realloc(name->filename, sizeof(*name->filename) *
312 name->long_filename = silc_realloc(name->long_filename,
313 sizeof(*name->long_filename) *
315 name->attrs = silc_realloc(name->attrs, sizeof(*name->attrs) *
318 name->filename[name->count] = strdup(short_name);
319 name->long_filename[name->count] = strdup(long_name);
320 name->attrs[name->count] = attrs;
324 /* Encodes the SilcSFTPName to a buffer and returns the allocated buffer.
325 The caller must free the buffer. */
327 SilcBuffer silc_sftp_name_encode(SilcSFTPName name)
331 SilcBuffer *attr_buf;
333 attr_buf = silc_calloc(name->count, sizeof(*attr_buf));
334 for (i = 0; i < name->count; i++) {
335 len += (8 + strlen(name->filename[i]) + strlen(name->long_filename[i]));
336 attr_buf[i] = silc_sftp_attr_encode(name->attrs[i]);
337 len += attr_buf[i]->len;
340 buffer = silc_buffer_alloc(len);
341 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
343 silc_buffer_format(buffer,
344 SILC_STR_UI_INT(name->count),
346 silc_buffer_pull(buffer, 4);
348 for (i = 0; i < name->count; i++) {
350 silc_buffer_format(buffer,
351 SILC_STR_UI_INT(strlen(name->filename[i])),
352 SILC_STR_UI32_STRING(name->filename[i]),
353 SILC_STR_UI_INT(strlen(name->long_filename[i])),
354 SILC_STR_UI32_STRING(name->long_filename[i]),
355 SILC_STR_UI_XNSTRING(attr_buf[i]->data,
359 silc_buffer_pull(buffer, len);
360 silc_free(attr_buf[i]);
364 silc_buffer_push(buffer, buffer->data - buffer->head);
369 /* Decodes a SilcSFTPName structure from the `buffer' that must include
370 `count' many name, longname and attribute values. Returns the allocated
371 structure or NULL on error. */
373 SilcSFTPName silc_sftp_name_decode(uint32 count, SilcBuffer buffer)
379 name = silc_calloc(1, sizeof(*name));
380 name->filename = silc_calloc(count, sizeof(*name->filename));
381 name->long_filename = silc_calloc(count, sizeof(*name->filename));
382 name->attrs = silc_calloc(count, sizeof(*name->attrs));
385 for (i = 0; i < count; i++) {
387 silc_buffer_unformat(buffer,
388 SILC_STR_UI32_STRING_ALLOC(&name->filename[i]),
389 SILC_STR_UI32_STRING_ALLOC(&name->long_filename[i]),
392 silc_sftp_name_free(name);
396 silc_buffer_pull(buffer, ret);
398 /* Decode attributes, this will pull the `buffer' to correct place
399 for next round automatically. */
400 name->attrs[i] = silc_sftp_attr_decode(buffer);
406 /* Frees the name context and its internals. */
408 void silc_sftp_name_free(SilcSFTPName name)
412 for (i = 0; i < name->count; i++) {
413 silc_free(name->filename[i]);
414 silc_free(name->long_filename[i]);
415 silc_sftp_attr_free(name->attrs[i]);
418 silc_free(name->filename);
419 silc_free(name->long_filename);
420 silc_free(name->attrs);
424 /* Maps errno to SFTP status message. */
426 SilcSFTPStatus silc_sftp_map_errno(int err)
432 ret = SILC_SFTP_STATUS_OK;
438 ret = SILC_SFTP_STATUS_NO_SUCH_FILE;
443 ret = SILC_SFTP_STATUS_PERMISSION_DENIED;
447 ret = SILC_SFTP_STATUS_BAD_MESSAGE;
450 ret = SILC_SFTP_STATUS_FAILURE;