aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2020-02-13 15:27:23 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2020-02-13 15:27:23 +0100
commitadc540f0dbcd640b37f39364aa4a1c6857a96a96 (patch)
tree400e54e15e2320ba443205152146634857b1f1c0
parent0c4e5977dfc32b54e452cd88a9cf14afde29c89d (diff)
downloadbusybox-w32-adc540f0dbcd640b37f39364aa4a1c6857a96a96.tar.gz
busybox-w32-adc540f0dbcd640b37f39364aa4a1c6857a96a96.tar.bz2
busybox-w32-adc540f0dbcd640b37f39364aa4a1c6857a96a96.zip
tftp: on download, open local file only when first bit of data arrived
No reason to potentially clobber existing file before absolutely necessary. function old new delta tftp_protocol 1947 2020 +73 tftp_main 393 376 -17 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 73/-17) Total: 56 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/tftp.c61
1 files changed, 33 insertions, 28 deletions
diff --git a/networking/tftp.c b/networking/tftp.c
index 043747d0d..60fdff232 100644
--- a/networking/tftp.c
+++ b/networking/tftp.c
@@ -319,7 +319,7 @@ static int tftp_protocol(
319 uint16_t opcode; 319 uint16_t opcode;
320 uint16_t block_nr; 320 uint16_t block_nr;
321 uint16_t recv_blk; 321 uint16_t recv_blk;
322 int open_mode, local_fd; 322 int local_fd = -1;
323 int retries, waittime_ms; 323 int retries, waittime_ms;
324 int io_bufsize = blksize + 4; 324 int io_bufsize = blksize + 4;
325 char *cp; 325 char *cp;
@@ -354,19 +354,6 @@ static int tftp_protocol(
354 } 354 }
355 } 355 }
356 356
357 /* Prepare open mode */
358 if (CMD_PUT(option_mask32)) {
359 open_mode = O_RDONLY;
360 } else {
361 open_mode = O_WRONLY | O_TRUNC | O_CREAT;
362#if ENABLE_TFTPD
363 if ((option_mask32 & (TFTPD_OPT+TFTPD_OPT_c)) == TFTPD_OPT) {
364 /* tftpd without -c */
365 open_mode = O_WRONLY | O_TRUNC;
366 }
367#endif
368 }
369
370 /* Examples of network traffic. 357 /* Examples of network traffic.
371 * Note two cases when ACKs with block# of 0 are sent. 358 * Note two cases when ACKs with block# of 0 are sent.
372 * 359 *
@@ -400,6 +387,14 @@ static int tftp_protocol(
400 387
401 if (!ENABLE_TFTP || our_lsa) { /* tftpd */ 388 if (!ENABLE_TFTP || our_lsa) { /* tftpd */
402 /* Open file (must be after changing user) */ 389 /* Open file (must be after changing user) */
390 int open_mode = O_RDONLY;
391 if (CMD_GET(option_mask32)) {
392 open_mode = O_WRONLY | O_TRUNC | O_CREAT;
393 if ((option_mask32 & (TFTPD_OPT+TFTPD_OPT_c)) == TFTPD_OPT) {
394 /* tftpd without -c */
395 open_mode = O_WRONLY | O_TRUNC;
396 }
397 }
403 local_fd = open(local_file, open_mode, 0666); 398 local_fd = open(local_file, open_mode, 0666);
404 if (local_fd < 0) { 399 if (local_fd < 0) {
405 /* sanitize name, it came from untrusted remote side */ 400 /* sanitize name, it came from untrusted remote side */
@@ -414,6 +409,7 @@ static int tftp_protocol(
414 strcpy(G_error_pkt_str, "can't open file"); 409 strcpy(G_error_pkt_str, "can't open file");
415 goto send_err_pkt_nomsg; 410 goto send_err_pkt_nomsg;
416 } 411 }
412
417/* gcc 4.3.1 would NOT optimize it out as it should! */ 413/* gcc 4.3.1 would NOT optimize it out as it should! */
418#if ENABLE_FEATURE_TFTP_BLOCKSIZE 414#if ENABLE_FEATURE_TFTP_BLOCKSIZE
419 if (blksize != TFTP_BLKSIZE_DEFAULT || want_transfer_size) { 415 if (blksize != TFTP_BLKSIZE_DEFAULT || want_transfer_size) {
@@ -432,10 +428,11 @@ static int tftp_protocol(
432 block_nr = 0; 428 block_nr = 0;
433 } 429 }
434 } else { /* tftp */ 430 } else { /* tftp */
435 /* Open file (must be after changing user) */ 431 if (CMD_PUT(option_mask32)) {
436 local_fd = CMD_GET(option_mask32) ? STDOUT_FILENO : STDIN_FILENO; 432 local_fd = STDIN_FILENO;
437 if (NOT_LONE_DASH(local_file)) 433 if (local_file)
438 local_fd = xopen(local_file, open_mode); 434 local_fd = xopen(local_file, O_RDONLY);
435 }
439/* Removing #if, or using if() statement instead of #if may lead to 436/* Removing #if, or using if() statement instead of #if may lead to
440 * "warning: null argument where non-null required": */ 437 * "warning: null argument where non-null required": */
441#if ENABLE_TFTP 438#if ENABLE_TFTP
@@ -491,7 +488,7 @@ static int tftp_protocol(
491 } 488 }
492 if (want_transfer_size) { 489 if (want_transfer_size) {
493 /* add "tsize", <nul>, size, <nul> (see RFC2349) */ 490 /* add "tsize", <nul>, size, <nul> (see RFC2349) */
494 /* if tftp and downloading, we send "0" (since we opened local_fd with O_TRUNC) 491 /* if tftp and downloading, we send "0" (local_fd is not open yet)
495 * and this makes server to send "tsize" option with the size */ 492 * and this makes server to send "tsize" option with the size */
496 /* if tftp and uploading, we send file size (maybe dont, to not confuse old servers???) */ 493 /* if tftp and uploading, we send file size (maybe dont, to not confuse old servers???) */
497 /* if tftpd and downloading, we are answering to client's request */ 494 /* if tftpd and downloading, we are answering to client's request */
@@ -500,7 +497,8 @@ static int tftp_protocol(
500 strcpy(cp, "tsize"); 497 strcpy(cp, "tsize");
501 cp += sizeof("tsize"); 498 cp += sizeof("tsize");
502 st.st_size = 0; 499 st.st_size = 0;
503 fstat(local_fd, &st); 500 if (local_fd >= 0)
501 fstat(local_fd, &st);
504 cp += sprintf(cp, "%"OFF_FMT"u", (off_t)st.st_size) + 1; 502 cp += sprintf(cp, "%"OFF_FMT"u", (off_t)st.st_size) + 1;
505# if ENABLE_FEATURE_TFTP_PROGRESS_BAR 503# if ENABLE_FEATURE_TFTP_PROGRESS_BAR
506 /* Save for progress bar. If 0 (tftp downloading), 504 /* Save for progress bar. If 0 (tftp downloading),
@@ -690,7 +688,13 @@ static int tftp_protocol(
690 688
691 if (CMD_GET(option_mask32) && (opcode == TFTP_DATA)) { 689 if (CMD_GET(option_mask32) && (opcode == TFTP_DATA)) {
692 if (recv_blk == block_nr) { 690 if (recv_blk == block_nr) {
693 int sz = full_write(local_fd, &rbuf[4], len - 4); 691 int sz;
692 if (local_fd == -1) {
693 local_fd = STDOUT_FILENO;
694 if (local_file)
695 local_fd = xopen(local_file, O_WRONLY | O_TRUNC | O_CREAT);
696 }
697 sz = full_write(local_fd, &rbuf[4], len - 4);
694 if (sz != len - 4) { 698 if (sz != len - 4) {
695 strcpy(G_error_pkt_str, bb_msg_write_error); 699 strcpy(G_error_pkt_str, bb_msg_write_error);
696 G_error_pkt_reason = ERR_WRITE; 700 G_error_pkt_reason = ERR_WRITE;
@@ -739,7 +743,9 @@ static int tftp_protocol(
739 free(xbuf); 743 free(xbuf);
740 free(rbuf); 744 free(rbuf);
741 } 745 }
742 return finished == 0; /* returns 1 on failure */ 746 if (!finished)
747 goto err;
748 return EXIT_SUCCESS;
743 749
744 send_read_err_pkt: 750 send_read_err_pkt:
745 strcpy(G_error_pkt_str, bb_msg_read_error); 751 strcpy(G_error_pkt_str, bb_msg_read_error);
@@ -750,6 +756,9 @@ static int tftp_protocol(
750 G.error_pkt[1] = TFTP_ERROR; 756 G.error_pkt[1] = TFTP_ERROR;
751 xsendto(socket_fd, G.error_pkt, 4 + 1 + strlen(G_error_pkt_str), 757 xsendto(socket_fd, G.error_pkt, 4 + 1 + strlen(G_error_pkt_str),
752 &peer_lsa->u.sa, peer_lsa->len); 758 &peer_lsa->u.sa, peer_lsa->len);
759 err:
760 if (local_fd >= 0 && CMD_GET(option_mask32) && local_file)
761 unlink(local_file);
753 return EXIT_FAILURE; 762 return EXIT_FAILURE;
754#undef remote_file 763#undef remote_file
755} 764}
@@ -767,7 +776,6 @@ int tftp_main(int argc UNUSED_PARAM, char **argv)
767# endif 776# endif
768 int result; 777 int result;
769 int port; 778 int port;
770 IF_GETPUT(int opt;)
771 779
772 INIT_G(); 780 INIT_G();
773 781
@@ -808,7 +816,7 @@ int tftp_main(int argc UNUSED_PARAM, char **argv)
808 } 816 }
809 } 817 }
810 818
811 IF_GETPUT(opt =) getopt32(argv, "^" 819 getopt32(argv, "^"
812 IF_FEATURE_TFTP_GET("g") IF_FEATURE_TFTP_PUT("p") 820 IF_FEATURE_TFTP_GET("g") IF_FEATURE_TFTP_PUT("p")
813 "l:r:" IF_FEATURE_TFTP_BLOCKSIZE("b:") 821 "l:r:" IF_FEATURE_TFTP_BLOCKSIZE("b:")
814 IF_FEATURE_TFTP_HPA_COMPAT("m:") 822 IF_FEATURE_TFTP_HPA_COMPAT("m:")
@@ -859,15 +867,12 @@ int tftp_main(int argc UNUSED_PARAM, char **argv)
859# endif 867# endif
860 result = tftp_protocol( 868 result = tftp_protocol(
861 NULL /*our_lsa*/, peer_lsa, 869 NULL /*our_lsa*/, peer_lsa,
862 local_file, remote_file 870 (LONE_DASH(local_file) ? NULL : local_file), remote_file
863 IF_FEATURE_TFTP_BLOCKSIZE(, 1 /* want_transfer_size */) 871 IF_FEATURE_TFTP_BLOCKSIZE(, 1 /* want_transfer_size */)
864 IF_FEATURE_TFTP_BLOCKSIZE(, blksize) 872 IF_FEATURE_TFTP_BLOCKSIZE(, blksize)
865 ); 873 );
866 tftp_progress_done(); 874 tftp_progress_done();
867 875
868 if (result != EXIT_SUCCESS && NOT_LONE_DASH(local_file) && CMD_GET(opt)) {
869 unlink(local_file);
870 }
871 return result; 876 return result;
872} 877}
873#endif /* ENABLE_TFTP */ 878#endif /* ENABLE_TFTP */