Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/sub.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 21 - (show annotations) (download) (as text)
Fri Feb 27 13:35:04 2009 UTC (15 years, 1 month ago) by hirohitohigashi
File MIME type: text/x-csrc
File size: 11027 byte(s)
added delete command.

1 /*
2 Some global functions for libOftp.
3
4 Copyright (c) 2009-2009 hirohito higashi. All rights reserved.
5 This file is distributed under BSD license.
6 */
7
8
9 /***** Feature test switches ************************************************/
10 /***** System headers *******************************************************/
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <errno.h>
16 #include <string.h>
17 #include <arpa/inet.h>
18 #include <sys/time.h>
19 #include <sys/select.h>
20
21
22 /***** Local headers ********************************************************/
23 #include "liboftp.h"
24 #include "sub.h"
25
26
27 /***** Constat values *******************************************************/
28 /***** Macros ***************************************************************/
29 /***** Typedefs *************************************************************/
30 /***** Function prototypes **************************************************/
31 /***** Local variables ******************************************************/
32 /***** Global variables *****************************************************/
33 /***** Signal catching functions ********************************************/
34 /***** Local functions ******************************************************/
35 /***** Global functions *****************************************************/
36
37 /****************************************************************************/
38 /*! send n bytes.
39 *
40 *@param sd socket descriptor
41 *@param buf pointer of send buffer
42 *@param len message length
43 *@param flags flags of send()
44 *@retval int number of bytes sent, or -1 if an error.
45 *@note
46 *
47 */
48 int sendn( int sd, const char *buf, int len, int flags )
49 {
50 int left = len;
51 int n;
52
53 while( left > 0 ) {
54 n = send( sd, buf, left, flags );
55 if( n < 0 ) {
56 if( errno == EINTR ) continue;
57 DEBUGPRINT1( "sendn: get minus. %s\n", strerror(errno) );
58 return n;
59 }
60 buf += n;
61 left -= n;
62 }
63
64 return len;
65 }
66
67
68
69 /****************************************************************************/
70 /*! read a line
71 *
72 *@param sd socket descriptor
73 *@param buf pointer of receive buffer
74 *@param bufsiz buffer size
75 *@param flags flags of recv()
76 *@retval int number of bytes received, or -1 if an error.
77 *@note
78 *
79 */
80 int recv_line( int sd, char *buf, int bufsiz, int flags )
81 {
82 int n;
83 char c;
84 char *p = buf;
85 int total_len = 0;
86
87 bufsiz--;
88
89 while( 1 ) {
90 n = recv( sd, &c, 1, flags );
91 if( n < 0 ) {
92 if( errno == EINTR ) continue;
93 *p = 0;
94 DEBUGPRINT1( "recv_line: get minus. %s\n", strerror(errno) );
95 return n;
96 }
97
98 *p++ = c;
99 total_len++;
100
101 if( c == '\n' ) break;
102 if( bufsiz < total_len ) break;
103 }
104 *p = 0;
105
106 return total_len;
107 }
108
109
110
111 /****************************************************************************/
112 /*! send ftp command
113 *
114 *@param ftp pointer of LIBOFTP.
115 *@param cmd ftp command.
116 *@retval int 0 is no error, or -1 if an error.
117 *@note
118 *
119 */
120 int ftp_send_command( LIBOFTP *ftp, const char *cmd )
121 {
122 int ret;
123 DEBUGPRINT1( "SENDC: %s", cmd );
124 ret = sendn( ftp->socket, cmd, strlen( cmd ), 0 );
125 if( ret < 0 ) {
126 return ret;
127 }
128
129 return 0;
130 }
131
132
133
134 /****************************************************************************/
135 /*! receive response
136 *
137 *@param ftp pointer of LIBOFTP.
138 *@param res_buf response buffer ( null ok )
139 *@param bufsiz response buffer size.
140 *@retval int response code, or error code (minus value)
141 *@note
142 *
143 */
144 int ftp_receive_response( LIBOFTP *ftp, char *res_buf, int bufsiz )
145 {
146 char str1[256];
147 int res_code = 0;
148 int n;
149
150 if( res_buf ) {
151 *res_buf = 0;
152 }
153
154 /*
155 * receive 1st line.
156 */
157 if( (n = recv_line( ftp->socket, str1, sizeof(str1), 0 )) < 0 ) {
158 return -1;
159 }
160 DEBUGPRINT1( "RESP1: %s", str1 );
161 if( n < 3 ) {
162 return -2;
163 }
164 res_code = atoi( str1 );
165
166 /*
167 * if exist next line, receive all response.
168 */
169 if( str1[3] == '-' ) {
170 while( 1 ) {
171 if( (n = recv_line( ftp->socket, str1, sizeof(str1), 0 )) < 0 ) {
172 return -1;
173 }
174 DEBUGPRINT1( "RESP2: %s", str1 );
175 if( n < 3 ) {
176 return -2;
177 }
178
179 if( atoi(str1) == res_code && str1[3] == ' ' ) {
180 break;
181 }
182 }
183 }
184
185 /*
186 * copy a response strings to user buffer, if need
187 */
188 if( res_buf ) {
189 strncpy( res_buf, str1, bufsiz );
190 res_buf[bufsiz-1] = 0;
191 }
192
193 return res_code;
194 }
195
196
197
198 /****************************************************************************/
199 /*! set receive timeout.
200 *
201 *@param sock socket descriptor
202 *@param sec second.
203 *@param usec micro second.
204 *@retval int 0 if no error, -1 if error occurred.
205 *@note
206 *
207 */
208 int ftp_set_so_rcvtimeo( int sock, int sec, int usec )
209 {
210 struct timeval tval;
211
212 tval.tv_sec = sec;
213 tval.tv_usec = usec;
214
215 return setsockopt( sock, SOL_SOCKET, SO_RCVTIMEO, &tval, sizeof(struct timeval) );
216 }
217
218
219
220 /****************************************************************************/
221 /*! ������������������������������������������
222 *
223 *@param ftp LIBOFTP���������������������
224 *@param fname ������������������������������
225 *@param cmd FTP������������ (ex: RETR, STOR, APPE)
226 *@retval int ������������, ������������������������������
227 *@note
228 ������������������������������������������������������������������������������������������������
229 ���) ���������
230 (port open) --> PORT --> RETR
231 */
232 int ftp_getready_active( LIBOFTP *ftp, const char *fname, const char *cmd )
233 {
234 int sock;
235 struct sockaddr_in saddr;
236 int saddr_len;
237 unsigned char *ip, *pt;
238 char str1[256];
239 int res;
240 struct timeval timeout;
241 fd_set rfds, wfds;
242
243 /*
244 * open data port.
245 * (note)
246 * same command port ip and automatic random port.
247 */
248 sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
249 if( sock < 0 ) {
250 DEBUGPRINT1( "getready_active: can't open socket. %s\n", strerror(errno) );
251 return -1;
252 }
253
254 memset( &saddr, 0, sizeof( saddr ) );
255 saddr_len = sizeof( saddr );
256 if( getsockname( ftp->socket, (struct sockaddr *)&saddr, &saddr_len ) < 0 ) {
257 DEBUGPRINT1( "getready_active: can't get control socket name. %s\n", strerror(errno) );
258 close( sock );
259 return -2;
260 }
261 saddr.sin_port = htons( 0 );
262
263 if( bind( sock, (struct sockaddr *)&saddr, sizeof( saddr ) ) < 0 ) {
264 DEBUGPRINT1( "getready_active: can't bind socket. %s\n", strerror(errno) );
265 close( sock );
266 return -2;
267 }
268
269 if( listen( sock, 1 ) < 0 ) {
270 DEBUGPRINT1( "getready_active: can't listen socket. %s\n", strerror(errno) );
271 close( sock );
272 return -2;
273 }
274
275
276 /*
277 * make PORT command.
278 */
279 memset( &saddr, 0, sizeof( saddr ) );
280 saddr_len = sizeof( saddr );
281 if( getsockname( sock, (struct sockaddr *)&saddr, &saddr_len ) < 0 ) {
282 DEBUGPRINT1( "getready_active: can't get data socket name. %s\n", strerror(errno) );
283 close( sock );
284 return -2;
285 }
286 ip = (unsigned char*)&saddr.sin_addr.s_addr;
287 pt = (unsigned char*)&saddr.sin_port;
288 snprintf( str1, sizeof(str1), "PORT %d,%d,%d,%d,%d,%d\r\n", ip[0], ip[1], ip[2], ip[3], pt[0], pt[1] );
289
290 /*
291 * send PORT command and get status.
292 */
293 if( ftp_send_command( ftp, str1 ) < 0 ) {
294 close( sock );
295 return -1;
296 }
297 res = ftp_receive_response( ftp, str1, sizeof(str1) );
298 if( res != 200 ) { /* 200: Command okay. */
299 DEBUGPRINT1( "getready_active: get PORT response code %d\n", res );
300 close( sock );
301 return -2;
302 }
303
304 /*
305 * send ftp command.
306 */
307 snprintf( str1, sizeof(str1), "%s %s\r\n", cmd, fname );
308 if( ftp_send_command( ftp, str1 ) < 0 ) {
309 close( sock );
310 return -2;
311 }
312
313 /*
314 * accept data connection with timeout.
315 */
316 timeout.tv_sec = ftp->timeout_sec;
317 timeout.tv_usec = 0;
318 FD_ZERO( &rfds );
319 FD_ZERO( &wfds );
320 FD_SET( sock, &rfds );
321 FD_SET( sock, &wfds );
322
323 res = select( sock+1, &rfds, &wfds, 0, &timeout );
324 if( res == 0 ) { /* timeout */
325 DEBUGPRINT1( "getready_active: waiting connection timeout.%s\n", "" );
326 close( sock );
327 return -3;
328 }
329
330 res = accept( sock, (struct sockaddr *)&saddr, &saddr_len );
331 close( sock );
332 if( res < 0 ) {
333 DEBUGPRINT1( "getready_active: socket accept error. %s\n", strerror(errno) );
334 close( sock );
335 return -1;
336 }
337 sock = res;
338
339 /*
340 * get status.
341 */
342 res = ftp_receive_response( ftp, str1, sizeof(str1) );
343 if( res != 150 ) { /* 150: File status okay; about to open data connection. */
344 DEBUGPRINT1( "getready_active: get STOR/RETR response code %d\n", res );
345 close( sock );
346 return -2;
347 }
348
349
350 return sock;
351 }
352
353
354
355 /****************************************************************************/
356 /*! ���������������������������������������
357 *
358 *@param ftp LIBOFTP���������������������
359 *@param fname ������������������������������
360 *@param cmd FTP������������ (ex: RETR, STOR, APPE)
361 *@retval int ������������, ������������������������������
362 *@note
363 ���������������������������������������������������������������������������������������������
364 ���) ���������
365 PASV --> RETR --> (port open)
366 */
367 int ftp_getready_pasv( LIBOFTP *ftp, const char *fname, const char *cmd )
368 {
369 char str1[256];
370 int res;
371 char *p;
372 int h1, h2, h3, h4, p1, p2;
373 struct sockaddr_in saddr;
374 int sock;
375
376 /*
377 * send "PASV" command and get status.
378 */
379 str1[255] = 0;
380 snprintf( str1, sizeof(str1)-1, "PASV\r\n" );
381 if( ftp_send_command( ftp, str1 ) < 0 ) {
382 return -1;
383 }
384 res = ftp_receive_response( ftp, str1, sizeof(str1) );
385 if( res != 227 ) { /* 227: Entering Passive Mode */
386 DEBUGPRINT1( "getready_pasv: get ftp response code %d\n", res );
387 return -2;
388 }
389
390 /*
391 * parse (h1,h2,h3,h4,p1,p2)
392 */
393 p = strchr( str1, '(' );
394 if( p == NULL ) {
395 DEBUGPRINT1( "getready_pasv: response parse error. %d", 1 );
396 return -2;
397 }
398 if( sscanf( p+1, "%d,%d,%d,%d,%d,%d", &h1, &h2, &h3, &h4, &p1, &p2 ) != 6 ) {
399 DEBUGPRINT1( "getready_pasv: response parse error. %d", 2 );
400 return -2;
401 }
402
403
404 /*
405 * send ftp command.
406 */
407 snprintf( str1, sizeof(str1), "%s %s\r\n", cmd, fname );
408 if( ftp_send_command( ftp, str1 ) < 0 ) {
409 return -2;
410 }
411
412 /*
413 * open data port.
414 */
415 sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
416 if( sock < 0 ) {
417 DEBUGPRINT1( "getready_pasv: can't open socket. %s\n", strerror(errno) );
418 return -1;
419 }
420
421 memset( &saddr, 0, sizeof( saddr ) );
422 saddr.sin_family = AF_INET;
423 saddr.sin_addr.s_addr = htonl( (((unsigned long)h1) << 24) | (h2 << 16) | (h3 << 8) | h4 );
424 saddr.sin_port = htons( (p1 << 8) | p2 );
425
426 if( connect( sock, (struct sockaddr *)&saddr, sizeof( saddr ) ) < 0 ) {
427 DEBUGPRINT1( "getready_pasv: can't connect socket. %s\n", strerror(errno) );
428 close( sock );
429 return -2;
430 }
431 ftp_set_so_rcvtimeo( sock, ftp->timeout_sec, 0 );
432
433 /*
434 * check response.
435 */
436 res = ftp_receive_response( ftp, 0, 0 );
437 if( res == 150 || res == 125 ) {
438 return sock;
439 } else {
440 close( sock );
441 return -2;
442 }
443 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26