Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/networking/ftpgetput.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/networking/ftpgetput.c
r821 r1770 14 14 */ 15 15 16 #include <sys/ioctl.h>17 18 #include <ctype.h>19 #include <errno.h>20 #include <fcntl.h>21 16 #include <getopt.h> 22 #include <signal.h> 23 #include <string.h> 24 #include <unistd.h> 25 26 #include <sys/socket.h> 27 28 #include "busybox.h" 17 #include "libbb.h" 29 18 30 19 typedef struct ftp_host_info_s { 31 c har *user;32 c har *password;33 struct sockaddr_in *s_in;20 const char *user; 21 const char *password; 22 struct len_and_sockaddr *lsa; 34 23 } ftp_host_info_t; 35 24 36 static char verbose_flag = 0; 37 static char do_continue = 0; 25 static smallint verbose_flag; 26 static smallint do_continue; 27 28 static void ftp_die(const char *msg, const char *remote) ATTRIBUTE_NORETURN; 29 static void ftp_die(const char *msg, const char *remote) 30 { 31 /* Guard against garbage from remote server */ 32 const char *cp = remote; 33 while (*cp >= ' ' && *cp < '\x7f') cp++; 34 bb_error_msg_and_die("unexpected server response%s%s: %.*s", 35 msg ? " to " : "", msg ? msg : "", 36 (int)(cp - remote), remote); 37 } 38 38 39 39 40 static int ftpcmd(const char *s1, const char *s2, FILE *stream, char *buf) 40 41 { 42 unsigned n; 41 43 if (verbose_flag) { 42 bb_error_msg("cmd %s %s", s1, s2);44 bb_error_msg("cmd %s %s", s1, s2); 43 45 } 44 46 45 47 if (s1) { 46 48 if (s2) { 47 fprintf(stream, "%s %s\r\n", s1, s2);49 fprintf(stream, "%s %s\r\n", s1, s2); 48 50 } else { 49 51 fprintf(stream, "%s\r\n", s1); … … 54 56 55 57 if (fgets(buf, 510, stream) == NULL) { 56 bb_perror_msg_and_die("fgets ()");58 bb_perror_msg_and_die("fgets"); 57 59 } 58 60 buf_ptr = strstr(buf, "\r\n"); … … 60 62 *buf_ptr = '\0'; 61 63 } 62 } while (! isdigit(buf[0]) || buf[3] != ' '); 63 64 return atoi(buf); 65 } 66 67 static int xconnect_ftpdata(ftp_host_info_t *server, const char *buf) 64 } while (!isdigit(buf[0]) || buf[3] != ' '); 65 66 buf[3] = '\0'; 67 n = xatou(buf); 68 buf[3] = ' '; 69 return n; 70 } 71 72 static int xconnect_ftpdata(ftp_host_info_t *server, char *buf) 68 73 { 69 74 char *buf_ptr; 70 75 unsigned short port_num; 71 76 77 /* Response is "NNN garbageN1,N2,N3,N4,P1,P2[)garbage] 78 * Server's IP is N1.N2.N3.N4 (we ignore it) 79 * Server's port for data connection is P1*256+P2 */ 80 buf_ptr = strrchr(buf, ')'); 81 if (buf_ptr) *buf_ptr = '\0'; 82 72 83 buf_ptr = strrchr(buf, ','); 73 84 *buf_ptr = '\0'; 74 port_num = atoi(buf_ptr + 1);85 port_num = xatoul_range(buf_ptr + 1, 0, 255); 75 86 76 87 buf_ptr = strrchr(buf, ','); 77 88 *buf_ptr = '\0'; 78 port_num += atoi(buf_ptr + 1) * 256;79 80 se rver->s_in->sin_port=htons(port_num);81 return (xconnect(server->s_in));89 port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256; 90 91 set_nport(server->lsa, htons(port_num)); 92 return xconnect_stream(server->lsa); 82 93 } 83 94 … … 88 99 89 100 /* Connect to the command socket */ 90 control_stream = fdopen(xconnect (server->s_in), "r+");101 control_stream = fdopen(xconnect_stream(server->lsa), "r+"); 91 102 if (control_stream == NULL) { 92 bb_perror_msg_and_die("Couldnt open control stream"); 103 /* fdopen failed - extremely unlikely */ 104 bb_perror_nomsg_and_die(); 93 105 } 94 106 95 107 if (ftpcmd(NULL, NULL, control_stream, buf) != 220) { 96 bb_error_msg_and_die("%s", buf + 4);108 ftp_die(NULL, buf); 97 109 } 98 110 99 111 /* Login to the server */ 100 switch (ftpcmd("USER 112 switch (ftpcmd("USER", server->user, control_stream, buf)) { 101 113 case 230: 102 114 break; 103 115 case 331: 104 if (ftpcmd("PASS 105 bb_error_msg_and_die("PASS error: %s", buf + 4);116 if (ftpcmd("PASS", server->password, control_stream, buf) != 230) { 117 ftp_die("PASS", buf); 106 118 } 107 119 break; 108 120 default: 109 bb_error_msg_and_die("USER error: %s", buf + 4);121 ftp_die("USER", buf); 110 122 } 111 123 112 124 ftpcmd("TYPE I", NULL, control_stream, buf); 113 125 114 return (control_stream);126 return control_stream; 115 127 } 116 128 117 129 #if !ENABLE_FTPGET 118 #define ftp_receive 0 130 int ftp_receive(ftp_host_info_t *server, FILE *control_stream, 131 const char *local_path, char *server_path); 119 132 #else 120 static int ftp_receive(ftp_host_info_t *server, FILE *control_stream, 133 static 134 int ftp_receive(ftp_host_info_t *server, FILE *control_stream, 121 135 const char *local_path, char *server_path) 122 136 { 123 137 char buf[512]; 124 off_t filesize = 0; 138 /* I think 'filesize' usage here is bogus. Let's see... */ 139 //off_t filesize = -1; 140 #define filesize ((off_t)-1) 125 141 int fd_data; 126 142 int fd_local = -1; … … 129 145 /* Connect to the data socket */ 130 146 if (ftpcmd("PASV", NULL, control_stream, buf) != 227) { 131 bb_error_msg_and_die("PASV error: %s", buf + 4);147 ftp_die("PASV", buf); 132 148 } 133 149 fd_data = xconnect_ftpdata(server, buf); 134 150 135 if (ftpcmd("SIZE ", server_path, control_stream, buf) == 213) { 136 unsigned long value=filesize; 137 if (safe_strtoul(buf + 4, &value)) 138 bb_error_msg_and_die("SIZE error: %s", buf + 4); 139 filesize = value; 151 if (ftpcmd("SIZE", server_path, control_stream, buf) == 213) { 152 //filesize = BB_STRTOOFF(buf + 4, NULL, 10); 153 //if (errno || filesize < 0) 154 // ftp_die("SIZE", buf); 140 155 } else { 141 filesize = -1;142 156 do_continue = 0; 143 157 } 144 158 145 if ( (local_path[0] == '-') && (local_path[1] == '\0')) {159 if (LONE_DASH(local_path)) { 146 160 fd_local = STDOUT_FILENO; 147 161 do_continue = 0; … … 151 165 struct stat sbuf; 152 166 if (lstat(local_path, &sbuf) < 0) { 153 bb_perror_msg_and_die(" fstat()");167 bb_perror_msg_and_die("lstat"); 154 168 } 155 169 if (sbuf.st_size > 0) { … … 161 175 162 176 if (do_continue) { 163 sprintf(buf, "REST % ld", (long)beg_range);177 sprintf(buf, "REST %"OFF_FMT"d", beg_range); 164 178 if (ftpcmd(buf, NULL, control_stream, buf) != 350) { 165 179 do_continue = 0; 166 180 } else { 167 filesize -= beg_range; 168 } 169 } 170 171 if (ftpcmd("RETR ", server_path, control_stream, buf) > 150) { 172 bb_error_msg_and_die("RETR error: %s", buf + 4); 181 //if (filesize != -1) 182 // filesize -= beg_range; 183 } 184 } 185 186 if (ftpcmd("RETR", server_path, control_stream, buf) > 150) { 187 ftp_die("RETR", buf); 173 188 } 174 189 … … 176 191 if (fd_local == -1) { 177 192 if (do_continue) { 178 fd_local = bb_xopen(local_path, O_APPEND | O_WRONLY);193 fd_local = xopen(local_path, O_APPEND | O_WRONLY); 179 194 } else { 180 fd_local = bb_xopen(local_path, O_CREAT | O_TRUNC | O_WRONLY);195 fd_local = xopen(local_path, O_CREAT | O_TRUNC | O_WRONLY); 181 196 } 182 197 } … … 184 199 /* Copy the file */ 185 200 if (filesize != -1) { 186 if ( -1 == bb_copyfd_size(fd_data, fd_local, filesize))187 exit(EXIT_FAILURE);201 if (bb_copyfd_size(fd_data, fd_local, filesize) == -1) 202 return EXIT_FAILURE; 188 203 } else { 189 if ( -1 == bb_copyfd_eof(fd_data, fd_local))190 exit(EXIT_FAILURE);204 if (bb_copyfd_eof(fd_data, fd_local) == -1) 205 return EXIT_FAILURE; 191 206 } 192 207 … … 194 209 close(fd_data); 195 210 if (ftpcmd(NULL, NULL, control_stream, buf) != 226) { 196 bb_error_msg_and_die("ftp error: %s", buf + 4);211 ftp_die(NULL, buf); 197 212 } 198 213 ftpcmd("QUIT", NULL, control_stream, buf); 199 214 200 return (EXIT_SUCCESS);215 return EXIT_SUCCESS; 201 216 } 202 217 #endif 203 218 204 219 #if !ENABLE_FTPPUT 205 #define ftp_send 0 220 int ftp_send(ftp_host_info_t *server, FILE *control_stream, 221 const char *server_path, char *local_path); 206 222 #else 207 static int ftp_send(ftp_host_info_t *server, FILE *control_stream, 223 static 224 int ftp_send(ftp_host_info_t *server, FILE *control_stream, 208 225 const char *server_path, char *local_path) 209 226 { … … 216 233 /* Connect to the data socket */ 217 234 if (ftpcmd("PASV", NULL, control_stream, buf) != 227) { 218 bb_error_msg_and_die("PASV error: %s", buf + 4);235 ftp_die("PASV", buf); 219 236 } 220 237 fd_data = xconnect_ftpdata(server, buf); 221 238 222 239 /* get the local file */ 223 if ((local_path[0] == '-') && (local_path[1] == '\0')) { 224 fd_local = STDIN_FILENO; 225 } else { 226 fd_local = bb_xopen(local_path, O_RDONLY); 240 fd_local = STDIN_FILENO; 241 if (NOT_LONE_DASH(local_path)) { 242 fd_local = xopen(local_path, O_RDONLY); 227 243 fstat(fd_local, &sbuf); 228 244 229 sprintf(buf, "ALLO % lu", (unsigned long)sbuf.st_size);245 sprintf(buf, "ALLO %"OFF_FMT"u", sbuf.st_size); 230 246 response = ftpcmd(buf, NULL, control_stream, buf); 231 247 switch (response) { … … 235 251 default: 236 252 close(fd_local); 237 bb_error_msg_and_die("ALLO error: %s", buf + 4);253 ftp_die("ALLO", buf); 238 254 break; 239 255 } 240 256 } 241 response = ftpcmd("STOR 257 response = ftpcmd("STOR", server_path, control_stream, buf); 242 258 switch (response) { 243 259 case 125: … … 246 262 default: 247 263 close(fd_local); 248 bb_error_msg_and_die("STOR error: %s", buf + 4);264 ftp_die("STOR", buf); 249 265 } 250 266 … … 257 273 close(fd_data); 258 274 if (ftpcmd(NULL, NULL, control_stream, buf) != 226) { 259 bb_error_msg_and_die("error: %s", buf + 4);275 ftp_die("close", buf); 260 276 } 261 277 ftpcmd("QUIT", NULL, control_stream, buf); 262 278 263 return (EXIT_SUCCESS);279 return EXIT_SUCCESS; 264 280 } 265 281 #endif … … 272 288 273 289 #if ENABLE_FEATURE_FTPGETPUT_LONG_OPTIONS 274 static const struct option ftpgetput_long_options[] = { 275 {"continue", 1, NULL, 'c'}, 276 {"verbose", 0, NULL, 'v'}, 277 {"username", 1, NULL, 'u'}, 278 {"password", 1, NULL, 'p'}, 279 {"port", 1, NULL, 'P'}, 280 {0, 0, 0, 0} 281 }; 282 #else 283 #define ftpgetput_long_options 0 284 #endif 285 290 static const char ftpgetput_longopts[] ALIGN1 = 291 "continue\0" Required_argument "c" 292 "verbose\0" No_argument "v" 293 "username\0" Required_argument "u" 294 "password\0" Required_argument "p" 295 "port\0" Required_argument "P" 296 ; 297 #endif 298 299 int ftpgetput_main(int argc, char **argv); 286 300 int ftpgetput_main(int argc, char **argv) 287 301 { 288 302 /* content-length of the file */ 289 unsigned long opt; 290 char *port = "ftp"; 291 303 unsigned opt; 304 const char *port = "ftp"; 292 305 /* socket to ftp server */ 293 306 FILE *control_stream; 294 struct sockaddr_in s_in; 295 296 /* continue a prev transfer (-c) */ 307 /* continue previous transfer (-c) */ 297 308 ftp_host_info_t *server; 298 309 299 int (*ftp_action)(ftp_host_info_t *, FILE *, const char *, char *) = NULL; 300 310 #if ENABLE_FTPPUT && !ENABLE_FTPGET 311 # define ftp_action ftp_send 312 #elif ENABLE_FTPGET && !ENABLE_FTPPUT 313 # define ftp_action ftp_receive 314 #else 315 int (*ftp_action)(ftp_host_info_t *, FILE *, const char *, char *) = ftp_send; 301 316 /* Check to see if the command is ftpget or ftput */ 302 if (ENABLE_FTPPUT && (!ENABLE_FTPGET || bb_applet_name[3] == 'p')) { 303 ftp_action = ftp_send; 304 } 305 if (ENABLE_FTPGET && (!ENABLE_FTPPUT || bb_applet_name[3] == 'g')) { 317 if (applet_name[3] == 'g') { 306 318 ftp_action = ftp_receive; 307 319 } 320 #endif 308 321 309 322 /* Set default values */ 310 server = xmalloc(sizeof( ftp_host_info_t));323 server = xmalloc(sizeof(*server)); 311 324 server->user = "anonymous"; 312 325 server->password = "busybox@"; 313 verbose_flag = 0;314 326 315 327 /* 316 328 * Decipher the command line 317 329 */ 318 if (ENABLE_FEATURE_FTPGETPUT_LONG_OPTIONS) 319 bb_applet_long_options = ftpgetput_long_options; 320 321 opt = bb_getopt_ulflags(argc, argv, "cvu:p:P:", &server->user, &server->password, &port); 330 #if ENABLE_FEATURE_FTPGETPUT_LONG_OPTIONS 331 applet_long_options = ftpgetput_longopts; 332 #endif 333 opt_complementary = "=3"; /* must have 3 params */ 334 opt = getopt32(argv, "cvu:p:P:", &server->user, &server->password, &port); 335 argv += optind; 322 336 323 337 /* Process the non-option command line arguments */ 324 if (argc - optind != 3) {325 bb_show_usage();326 }327 328 338 if (opt & FTPGETPUT_OPT_CONTINUE) { 329 339 do_continue = 1; … … 336 346 * sites (i.e. ftp.us.debian.org) use round-robin DNS 337 347 * and we want to connect to only one IP... */ 338 server->s_in = &s_in; 339 bb_lookup_host(&s_in, argv[optind]); 340 s_in.sin_port = bb_lookup_port(port, "tcp", 21); 348 server->lsa = xhost2sockaddr(argv[0], bb_lookup_port(port, "tcp", 21)); 341 349 if (verbose_flag) { 342 printf("Connecting to %s [%s]:%d\n",343 argv[optind], inet_ntoa(s_in.sin_addr), ntohs(s_in.sin_port));350 printf("Connecting to %s (%s)\n", argv[0], 351 xmalloc_sockaddr2dotted(&server->lsa->sa)); 344 352 } 345 353 … … 347 355 control_stream = ftp_login(server); 348 356 349 return (ftp_action(server, control_stream, argv[optind + 1], argv[optind + 2]));350 } 357 return ftp_action(server, control_stream, argv[1], argv[2]); 358 }
Note:
See TracChangeset
for help on using the changeset viewer.