Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /trunk/sub.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (hide annotations) (download) (as text)
Sat Feb 28 04:14:38 2009 UTC (15 years, 1 month ago) by hirohitohigashi
File MIME type: text/x-csrc
File size: 11441 byte(s)
marged ftp_append_buffer.c and ftp_put_buffer.c. added ftp_append_file() function.

1 hirohitohigashi 17 /*
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 hirohitohigashi 20 #include <sys/select.h>
20 hirohitohigashi 17
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 hirohitohigashi 20 /*! 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 hirohitohigashi 17 /*! 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 hirohitohigashi 21 /*! ������������������������������������������
222 hirohitohigashi 17 *
223     *@param ftp LIBOFTP���������������������
224 hirohitohigashi 26 *@param cmd FTP������������ (ex: RETR, STOR, APPE)
225 hirohitohigashi 17 *@param fname ������������������������������
226     *@retval int ������������, ������������������������������
227     *@note
228 hirohitohigashi 21 ������������������������������������������������������������������������������������������������
229 hirohitohigashi 17 ���) ���������
230 hirohitohigashi 21 (port open) --> PORT --> RETR
231 hirohitohigashi 17 */
232 hirohitohigashi 26 int ftp_getready_active( LIBOFTP *ftp, const char *cmd, const char *fname )
233 hirohitohigashi 20 {
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 hirohitohigashi 26 if( fname ) {
308     snprintf( str1, sizeof(str1), "%s %s\r\n", cmd, fname );
309     } else {
310     snprintf( str1, sizeof(str1), "%s\r\n", cmd );
311     }
312 hirohitohigashi 20 if( ftp_send_command( ftp, str1 ) < 0 ) {
313     close( sock );
314     return -2;
315     }
316    
317     /*
318     * accept data connection with timeout.
319     */
320     timeout.tv_sec = ftp->timeout_sec;
321     timeout.tv_usec = 0;
322    
323 hirohitohigashi 28 do {
324     FD_ZERO( &rfds );
325     FD_ZERO( &wfds );
326     FD_SET( sock, &rfds );
327     FD_SET( sock, &wfds );
328    
329     res = select( sock+1, &rfds, &wfds, 0, &timeout );
330     if( res == 0 ) { /* timeout */
331     DEBUGPRINT1( "getready_active: waiting connection timeout.%s\n", "" );
332     close( sock );
333     return -3;
334     }
335     if( res < 0 ) {
336     if( errno == EINTR ) continue;
337     DEBUGPRINT1( "getready_active: select error. %s\n", strerror(errno) );
338     close( sock );
339     return -3;
340     }
341    
342     if( FD_ISSET( sock, &rfds ) || FD_ISSET( sock, &wfds ) ) break;
343     } while( 1 );
344    
345 hirohitohigashi 20 res = accept( sock, (struct sockaddr *)&saddr, &saddr_len );
346     close( sock );
347     if( res < 0 ) {
348     DEBUGPRINT1( "getready_active: socket accept error. %s\n", strerror(errno) );
349     close( sock );
350     return -1;
351     }
352     sock = res;
353    
354     /*
355     * get status.
356     */
357     res = ftp_receive_response( ftp, str1, sizeof(str1) );
358     if( res != 150 ) { /* 150: File status okay; about to open data connection. */
359     DEBUGPRINT1( "getready_active: get STOR/RETR response code %d\n", res );
360     close( sock );
361     return -2;
362     }
363    
364    
365     return sock;
366     }
367 hirohitohigashi 21
368    
369    
370     /****************************************************************************/
371     /*! ���������������������������������������
372     *
373     *@param ftp LIBOFTP���������������������
374 hirohitohigashi 26 *@param cmd FTP������������ (ex: RETR, STOR, APPE)
375 hirohitohigashi 21 *@param fname ������������������������������
376     *@retval int ������������, ������������������������������
377     *@note
378     ���������������������������������������������������������������������������������������������
379     ���) ���������
380     PASV --> RETR --> (port open)
381     */
382 hirohitohigashi 26 int ftp_getready_pasv( LIBOFTP *ftp, const char *cmd, const char *fname )
383 hirohitohigashi 21 {
384     char str1[256];
385     int res;
386     char *p;
387     int h1, h2, h3, h4, p1, p2;
388     struct sockaddr_in saddr;
389     int sock;
390    
391     /*
392     * send "PASV" command and get status.
393     */
394     str1[255] = 0;
395     snprintf( str1, sizeof(str1)-1, "PASV\r\n" );
396     if( ftp_send_command( ftp, str1 ) < 0 ) {
397     return -1;
398     }
399     res = ftp_receive_response( ftp, str1, sizeof(str1) );
400     if( res != 227 ) { /* 227: Entering Passive Mode */
401     DEBUGPRINT1( "getready_pasv: get ftp response code %d\n", res );
402     return -2;
403     }
404    
405     /*
406     * parse (h1,h2,h3,h4,p1,p2)
407     */
408     p = strchr( str1, '(' );
409     if( p == NULL ) {
410     DEBUGPRINT1( "getready_pasv: response parse error. %d", 1 );
411     return -2;
412     }
413     if( sscanf( p+1, "%d,%d,%d,%d,%d,%d", &h1, &h2, &h3, &h4, &p1, &p2 ) != 6 ) {
414     DEBUGPRINT1( "getready_pasv: response parse error. %d", 2 );
415     return -2;
416     }
417    
418    
419     /*
420     * send ftp command.
421     */
422 hirohitohigashi 26 if( fname ) {
423     snprintf( str1, sizeof(str1), "%s %s\r\n", cmd, fname );
424     } else {
425     snprintf( str1, sizeof(str1), "%s\r\n", cmd );
426     }
427 hirohitohigashi 21 if( ftp_send_command( ftp, str1 ) < 0 ) {
428     return -2;
429     }
430    
431     /*
432     * open data port.
433     */
434     sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
435     if( sock < 0 ) {
436     DEBUGPRINT1( "getready_pasv: can't open socket. %s\n", strerror(errno) );
437     return -1;
438     }
439    
440     memset( &saddr, 0, sizeof( saddr ) );
441     saddr.sin_family = AF_INET;
442     saddr.sin_addr.s_addr = htonl( (((unsigned long)h1) << 24) | (h2 << 16) | (h3 << 8) | h4 );
443     saddr.sin_port = htons( (p1 << 8) | p2 );
444    
445     if( connect( sock, (struct sockaddr *)&saddr, sizeof( saddr ) ) < 0 ) {
446     DEBUGPRINT1( "getready_pasv: can't connect socket. %s\n", strerror(errno) );
447     close( sock );
448     return -2;
449     }
450     ftp_set_so_rcvtimeo( sock, ftp->timeout_sec, 0 );
451    
452     /*
453     * check response.
454     */
455     res = ftp_receive_response( ftp, 0, 0 );
456     if( res == 150 || res == 125 ) {
457     return sock;
458     } else {
459     close( sock );
460     return -2;
461     }
462     }

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