Merge branch 'topic/mm-fixes' of git://208.110.73.182/silc into silc.1.1.branch
[silc.git] / lib / silcsftp / tests / sftp_client.c
1 /*
2
3   sftp_client.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2001 - 2007 Pekka Riikonen
8
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.
12
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.
17
18 */
19
20 /* Tests:
21    silc_sftp_client_start();
22    silc_sftp_client_receive_process();
23    silc_sftp_opendir();
24    silc_sftp_readdir();
25    silc_sftp_open();
26    silc_sftp_read();
27    silc_sftp_fstat();
28    silc_sftp_lstat();
29    silc_sftp_close();
30 */
31
32 #include "silc.h"
33 #include "silcsftp.h"
34
35 typedef struct {
36   SilcSchedule schedule;
37   SilcStream stream;
38   SilcSFTP sftp;
39 } *Client;
40
41 Client gclient;
42
43 char *dir;
44 char *file;
45 bool opendir;
46 SilcUInt64 offset;
47 bool success = FALSE;
48
49 static void sftp_name(SilcSFTP sftp, SilcSFTPStatus status,
50                       const SilcSFTPName name, void *context);
51 static void sftp_handle(SilcSFTP sftp, SilcSFTPStatus status,
52                         SilcSFTPHandle handle, void *context);
53 static void sftp_data(SilcSFTP sftp, SilcSFTPStatus status,
54                       const unsigned char *data, SilcUInt32 data_len,
55                       void *context);
56 static void end_test(void);
57
58 static void sftp_status(SilcSFTP sftp, SilcSFTPStatus status,
59                         const char *message, const char *lang_tag,
60                         void *context)
61 {
62   fprintf(stderr, "Status %d\n", status);
63   if (status != SILC_SFTP_STATUS_OK) {
64     SILC_LOG_DEBUG(("Error status"));
65     success = FALSE;
66     end_test();
67     return;
68   }
69
70   success = TRUE;
71   end_test();
72 }
73
74 static void sftp_attr(SilcSFTP sftp, SilcSFTPStatus status,
75                       const SilcSFTPAttributes attrs, void *context)
76 {
77   SilcSFTPHandle handle = (SilcSFTPHandle)context;
78   int i;
79
80   fprintf(stderr, "Status %d\n", status);
81   if (status != SILC_SFTP_STATUS_OK) {
82     SILC_LOG_DEBUG(("Error status"));
83     success = FALSE;
84     end_test();
85     return;
86   }
87
88
89   SILC_LOG_DEBUG(("Attr.flags: %d", attrs->flags));
90   SILC_LOG_DEBUG(("Attr.size: %lu", attrs->size));
91   SILC_LOG_DEBUG(("Attr.uid: %d", attrs->uid));
92   SILC_LOG_DEBUG(("Attr.gid: %d", attrs->gid));
93   SILC_LOG_DEBUG(("Attr.permissions: %d", attrs->permissions));
94   SILC_LOG_DEBUG(("Attr.atime: %d", attrs->atime));
95   SILC_LOG_DEBUG(("Attr.mtime: %d", attrs->mtime));
96   SILC_LOG_DEBUG(("Attr.extended count: %d", attrs->extended_count));
97   for (i = 0; i < attrs->extended_count; i++) {
98     SILC_LOG_HEXDUMP(("Attr.extended_type[i]:", i),
99                      attrs->extended_type[i]->data,
100                      silc_buffer_len(attrs->extended_type[i]));
101     SILC_LOG_HEXDUMP(("Attr.extended_data[i]:", i),
102                      attrs->extended_data[i]->data,
103                      silc_buffer_len(attrs->extended_data[i]));
104   }
105
106   if (!file) {
107     fprintf(stderr, "Closing file\n");
108     silc_sftp_close(sftp, handle, sftp_status, context);
109     return;
110   }
111
112   fprintf(stderr, "LStatting file %s\n", file);
113   silc_sftp_lstat(sftp, file, sftp_attr, context);
114   file = NULL;
115 }
116
117 static void sftp_data(SilcSFTP sftp, SilcSFTPStatus status,
118                       const unsigned char *data, SilcUInt32 data_len,
119                       void *context)
120 {
121   SilcSFTPHandle handle = (SilcSFTPHandle)context;
122
123   if (status != SILC_SFTP_STATUS_OK) {
124     SilcSFTPAttributesStruct attrs;
125
126     fprintf(stderr, "Status %d\n", status);
127
128     if (status != SILC_SFTP_STATUS_EOF) {
129       SILC_LOG_DEBUG(("Error status"));
130       success = FALSE;
131       end_test();
132       return;
133     }
134
135     if (!strcmp(file, "/sftp/sftp_server.c")) {
136       fprintf(stderr, "FStatting file handle %s\n", file);
137       silc_sftp_fstat(sftp, handle, sftp_attr, context);
138       return;
139     }
140
141     /* Open another file */
142     opendir = FALSE;
143     memset(&attrs, 0, sizeof(attrs));
144     file = "/sftp/sftp_server.c";
145     fprintf(stderr, "Opening file %s\n", file);
146     offset = 0;
147     silc_sftp_open(sftp, file, SILC_SFTP_FXF_READ,
148                    &attrs, sftp_handle, gclient);
149     return;
150   }
151
152   SILC_LOG_HEXDUMP(("data"), (unsigned char *)data, data_len);
153
154   offset += data_len;
155
156   /* Attempt to read more */
157   fprintf(stderr, "Reading more of file %s\n", file);
158   silc_sftp_read(sftp, handle, offset, 2048, sftp_data, handle);
159 }
160
161 static void sftp_name(SilcSFTP sftp, SilcSFTPStatus status,
162                       const SilcSFTPName name, void *context)
163 {
164   Client client = (Client)context;
165   int i;
166
167   SILC_LOG_DEBUG(("Name"));
168   fprintf(stderr, "Status %d\n", status);
169
170   if (status != SILC_SFTP_STATUS_OK) {
171     SILC_LOG_DEBUG(("Error status"));
172     success = FALSE;
173     end_test();
174     return;
175   }
176
177   fprintf(stderr, "Directory: %s\n", dir);
178   for (i = 0; i < name->count; i++) {
179     fprintf(stderr, "%s\n", name->long_filename[i]);
180   }
181
182   if (!strcmp(dir, "sftp")) {
183     SilcSFTPAttributesStruct attrs;
184
185     /* open */
186     opendir = FALSE;
187     memset(&attrs, 0, sizeof(attrs));
188     file = "passwd";
189     fprintf(stderr, "Opening file %s\n", file);
190     offset = 0;
191     silc_sftp_open(sftp, file, SILC_SFTP_FXF_READ,
192                    &attrs, sftp_handle, client);
193     return;
194   }
195
196   if (!strcmp(dir, "/"))
197     dir = "sftp";
198
199   fprintf(stderr, "Opening %s\n", dir);
200
201   /* opendir */
202   opendir = TRUE;
203   silc_sftp_opendir(sftp, dir, sftp_handle, client);
204 }
205
206 static void sftp_handle(SilcSFTP sftp, SilcSFTPStatus status,
207                         SilcSFTPHandle handle, void *context)
208 {
209   Client client = (Client)context;
210
211   SILC_LOG_DEBUG(("Handle"));
212   fprintf(stderr, "Status %d\n", status);
213   if (status != SILC_SFTP_STATUS_OK) {
214     SILC_LOG_DEBUG(("Error status"));
215     success = FALSE;
216     end_test();
217     return;
218   }
219
220   if (opendir) {
221     fprintf(stderr, "Reading %s\n", dir);
222     /* Readdir */
223     silc_sftp_readdir(sftp, handle, sftp_name, client);
224   } else {
225     fprintf(stderr, "Reading file %s\n", file);
226
227     /* Read */
228     silc_sftp_read(sftp, handle, 0, 2048, sftp_data, handle);
229   }
230 }
231
232 static void sftp_version(SilcSFTP sftp, SilcSFTPStatus status,
233                          SilcSFTPVersion version, void *context)
234 {
235   Client client = (Client)context;
236   fprintf(stderr, "Version: %d\n", (int)version);
237
238   SILC_LOG_DEBUG(("Version"));
239   fprintf(stderr, "Status %d\n", status);
240   if (status != SILC_SFTP_STATUS_OK) {
241     SILC_LOG_DEBUG(("Error status"));
242     success = FALSE;
243     end_test();
244     return;
245   }
246
247   /* opendir */
248   dir = "/";
249   fprintf(stderr, "Opening %s\n", dir);
250   opendir = TRUE;
251   silc_sftp_opendir(sftp, dir, sftp_handle, client);
252 }
253
254 static void sftp_error(SilcSFTP sftp, SilcSFTPStatus status,
255                        void *context)
256 {
257   Client client = context;
258   SILC_LOG_DEBUG(("Error %d", status));
259   silc_stream_destroy(client->stream);
260   success = FALSE;
261   end_test();
262 }
263
264 static void connect_callback(SilcNetStatus status, SilcStream stream,
265                              void *context)
266 {
267   Client client = context;
268
269   if (!stream) {
270     SILC_LOG_DEBUG(("Connect error"));
271     success = FALSE;
272     end_test();
273   }
274
275   /* Start SFTP session */
276   client->stream = stream;
277   client->sftp = silc_sftp_client_start(stream, client->schedule, sftp_version,
278                                         sftp_error, client);
279   if (!client->sftp) {
280     success = FALSE;
281     end_test();
282   }
283 }
284
285 int main(int argc, char **argv)
286 {
287   Client client = silc_calloc(1, sizeof(*client));
288
289   gclient = client;
290
291   if (argc > 1) {
292     if (!strcmp(argv[1], "-d"))
293       silc_log_debug(TRUE);
294     if (argc > 2 && !strcmp(argv[2], "-x"))
295       silc_log_debug_hexdump(TRUE);
296     silc_log_set_debug_string("*");
297   }
298
299   client->schedule = silc_schedule_init(0, NULL);
300   if (!client->schedule)
301     return -1;
302
303   /* Connecto to server */
304   silc_net_tcp_connect(NULL, "127.0.0.1", 5000, client->schedule,
305                        connect_callback, client);
306
307   silc_schedule(client->schedule);
308   return 0;
309 }
310
311 static void end_test(void)
312 {
313   SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
314   fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
315   exit(success);
316 }