aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagnus Damm <magnus.damm@gmail.com>2009-11-08 18:03:09 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2009-11-08 18:03:09 +0100
commit8bd0af996226b720342f792129f21581aa08bb5d (patch)
tree831650442ce03bdb6f51465ac5b4162fb7e18d5e
parentbbd423530f58ab695030f3d26cb81089a2f7a945 (diff)
downloadbusybox-w32-8bd0af996226b720342f792129f21581aa08bb5d.tar.gz
busybox-w32-8bd0af996226b720342f792129f21581aa08bb5d.tar.bz2
busybox-w32-8bd0af996226b720342f792129f21581aa08bb5d.zip
tftp: add optiona support for progress bar
function old new delta tftp_protocol 1662 1834 +172 progress_meter 212 365 +153 tftp_progress_init - 14 +14 tftp_main 276 281 +5 tftpd_main 513 500 -13 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 3/1 up/down: 344/-13) Total: 331 bytes Signed-off-by: Magnus Damm <magnus.damm@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/Config.in11
-rw-r--r--networking/tftp.c91
2 files changed, 84 insertions, 18 deletions
diff --git a/networking/Config.in b/networking/Config.in
index 59e88e016..5f1b6f636 100644
--- a/networking/Config.in
+++ b/networking/Config.in
@@ -846,12 +846,19 @@ config FEATURE_TFTP_PUT
846 Also enable download support in tftpd, if tftpd is selected. 846 Also enable download support in tftpd, if tftpd is selected.
847 847
848config FEATURE_TFTP_BLOCKSIZE 848config FEATURE_TFTP_BLOCKSIZE
849 bool "Enable \"blksize\" protocol option" 849 bool "Enable 'blksize' and 'tsize' protocol options"
850 default n 850 default n
851 depends on TFTP || TFTPD 851 depends on TFTP || TFTPD
852 help 852 help
853 Allow tftp to specify block size, and tftpd to understand 853 Allow tftp to specify block size, and tftpd to understand
854 "blksize" option. 854 "blksize" and "tsize" options.
855
856config FEATURE_TFTP_PROGRESS_BAR
857 bool "Enable tftp progress meter"
858 default n
859 depends on TFTP && FEATURE_TFTP_BLOCKSIZE
860 help
861 Show progress bar.
855 862
856config TFTP_DEBUG 863config TFTP_DEBUG
857 bool "Enable debug" 864 bool "Enable debug"
diff --git a/networking/tftp.c b/networking/tftp.c
index c2d3ccfa8..9a9bd2c34 100644
--- a/networking/tftp.c
+++ b/networking/tftp.c
@@ -84,8 +84,17 @@ struct globals {
84 char *user_opt; 84 char *user_opt;
85 /* used in tftpd_main(), a bit big for stack: */ 85 /* used in tftpd_main(), a bit big for stack: */
86 char block_buf[TFTP_BLKSIZE_DEFAULT]; 86 char block_buf[TFTP_BLKSIZE_DEFAULT];
87#if ENABLE_FEATURE_TFTP_PROGRESS_BAR
88 off_t pos;
89 off_t size;
90 const char *file;
91 bb_progress_t pmt;
92#endif
87}; 93};
88#define G (*(struct globals*)&bb_common_bufsiz1) 94#define G (*(struct globals*)&bb_common_bufsiz1)
95struct BUG_G_too_big {
96 char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
97};
89#define block_buf (G.block_buf ) 98#define block_buf (G.block_buf )
90#define user_opt (G.user_opt ) 99#define user_opt (G.user_opt )
91#define error_pkt (G.error_pkt ) 100#define error_pkt (G.error_pkt )
@@ -94,6 +103,45 @@ struct globals {
94#define error_pkt_reason (error_pkt[3]) 103#define error_pkt_reason (error_pkt[3])
95#define error_pkt_str (error_pkt + 4) 104#define error_pkt_str (error_pkt + 4)
96 105
106#if ENABLE_FEATURE_TFTP_PROGRESS_BAR
107/* SIGALRM logic nicked from the wget applet */
108static void progress_meter(int flag)
109{
110 /* We can be called from signal handler */
111 int save_errno = errno;
112
113 if (flag == -1) { /* first call to progress_meter */
114 bb_progress_init(&G.pmt);
115 }
116
117 bb_progress_update(&G.pmt, G.file, 0, G.pos, G.size);
118
119 if (flag == 0) {
120 /* last call to progress_meter */
121 alarm(0);
122 fputc('\n', stderr);
123 } else {
124 if (flag == -1) { /* first call to progress_meter */
125 signal_SA_RESTART_empty_mask(SIGALRM, progress_meter);
126 }
127 alarm(1);
128 }
129
130 errno = save_errno;
131}
132static void tftp_progress_init(const char *file)
133{
134 G.file = file;
135 progress_meter(-1);
136}
137static void tftp_progress_done(void)
138{
139 progress_meter(0);
140}
141#else
142# define tftp_progress_init(file) ((void)0)
143# define tftp_progress_done() ((void)0)
144#endif
97 145
98#if ENABLE_FEATURE_TFTP_BLOCKSIZE 146#if ENABLE_FEATURE_TFTP_BLOCKSIZE
99 147
@@ -163,7 +211,7 @@ static int tftp_protocol(
163# define remote_file NULL 211# define remote_file NULL
164#endif 212#endif
165 /* 1 for tftp; 1/0 for tftpd depending whether client asked about it: */ 213 /* 1 for tftp; 1/0 for tftpd depending whether client asked about it: */
166 IF_FEATURE_TFTP_BLOCKSIZE(, off_t transfer_size) 214 IF_FEATURE_TFTP_BLOCKSIZE(, int want_transfer_size)
167 IF_FEATURE_TFTP_BLOCKSIZE(, int blksize)) 215 IF_FEATURE_TFTP_BLOCKSIZE(, int blksize))
168{ 216{
169#if !ENABLE_FEATURE_TFTP_BLOCKSIZE 217#if !ENABLE_FEATURE_TFTP_BLOCKSIZE
@@ -269,7 +317,7 @@ static int tftp_protocol(
269 } 317 }
270/* gcc 4.3.1 would NOT optimize it out as it should! */ 318/* gcc 4.3.1 would NOT optimize it out as it should! */
271#if ENABLE_FEATURE_TFTP_BLOCKSIZE 319#if ENABLE_FEATURE_TFTP_BLOCKSIZE
272 if (blksize != TFTP_BLKSIZE_DEFAULT || transfer_size) { 320 if (blksize != TFTP_BLKSIZE_DEFAULT || want_transfer_size) {
273 /* Create and send OACK packet. */ 321 /* Create and send OACK packet. */
274 /* For the download case, block_nr is still 1 - 322 /* For the download case, block_nr is still 1 -
275 * we expect 1st ACK from peer to be for (block_nr-1), 323 * we expect 1st ACK from peer to be for (block_nr-1),
@@ -325,11 +373,11 @@ static int tftp_protocol(
325 cp += sizeof("octet"); 373 cp += sizeof("octet");
326 374
327# if ENABLE_FEATURE_TFTP_BLOCKSIZE 375# if ENABLE_FEATURE_TFTP_BLOCKSIZE
328 if (blksize == TFTP_BLKSIZE_DEFAULT && !transfer_size) 376 if (blksize == TFTP_BLKSIZE_DEFAULT && !want_transfer_size)
329 goto send_pkt; 377 goto send_pkt;
330 378
331 /* Need to add option to pkt */ 379 /* Need to add option to pkt */
332 if ((&xbuf[io_bufsize - 1] - cp) < sizeof("blksize NNNNN tsize ") + sizeof(transfer_size)*3) { 380 if ((&xbuf[io_bufsize - 1] - cp) < sizeof("blksize NNNNN tsize ") + sizeof(off_t)*3) {
333 bb_error_msg("remote filename is too long"); 381 bb_error_msg("remote filename is too long");
334 goto ret; 382 goto ret;
335 } 383 }
@@ -345,23 +393,25 @@ static int tftp_protocol(
345 cp += sizeof("blksize"); 393 cp += sizeof("blksize");
346 cp += snprintf(cp, 6, "%d", blksize) + 1; 394 cp += snprintf(cp, 6, "%d", blksize) + 1;
347 } 395 }
348 if (transfer_size) { 396 if (want_transfer_size) {
349 /* add "tsize", <nul>, size, <nul> (see RFC2349) */ 397 /* add "tsize", <nul>, size, <nul> (see RFC2349) */
350 /* if tftp and downloading, we send "0" (since we opened local_fd with O_TRUNC) 398 /* if tftp and downloading, we send "0" (since we opened local_fd with O_TRUNC)
351 * and this makes server to send "tsize" option with the size */ 399 * and this makes server to send "tsize" option with the size */
352 /* if tftp and uploading, we send file size (maybe dont, to not confuse old servers???) */ 400 /* if tftp and uploading, we send file size (maybe dont, to not confuse old servers???) */
353 /* if tftpd and downloading, we are answering to client's request */ 401 /* if tftpd and downloading, we are answering to client's request */
354 /* if tftpd and uploading: transfer_size == 0, this code is not executed */ 402 /* if tftpd and uploading: !want_transfer_size, this code is not executed */
355 struct stat st; 403 struct stat st;
356 strcpy(cp, "tsize"); 404 strcpy(cp, "tsize");
357 cp += sizeof("tsize"); 405 cp += sizeof("tsize");
358 st.st_size = 0; 406 st.st_size = 0;
359 fstat(local_fd, &st); 407 fstat(local_fd, &st);
360 cp += sprintf(cp, "%"OFF_FMT"u", (off_t)st.st_size) + 1; 408 cp += sprintf(cp, "%"OFF_FMT"u", (off_t)st.st_size) + 1;
361# if 0 /*ENABLE_FEATURE_TFTP_PROGRESS_BAR*/ 409# if ENABLE_FEATURE_TFTP_PROGRESS_BAR
362 /* Save for progress bar. If 0 (tftp downloading), 410 /* Save for progress bar. If 0 (tftp downloading),
363 * we look at server's reply later */ 411 * we look at server's reply later */
364 transfer_size = st.st_size; 412 G.size = st.st_size;
413 if (remote_file && st.st_size)
414 tftp_progress_init(remote_file);
365# endif 415# endif
366 } 416 }
367#endif 417#endif
@@ -407,6 +457,12 @@ static int tftp_protocol(
407 fprintf(stderr, "\n"); 457 fprintf(stderr, "\n");
408#endif 458#endif
409 xsendto(socket_fd, xbuf, send_len, &peer_lsa->u.sa, peer_lsa->len); 459 xsendto(socket_fd, xbuf, send_len, &peer_lsa->u.sa, peer_lsa->len);
460
461#if ENABLE_FEATURE_TFTP_PROGRESS_BAR
462 if (ENABLE_TFTP && remote_file) { /* tftp */
463 G.pos = (block_nr - 1) * (uoff_t)blksize;
464 }
465#endif
410 /* Was it final ACK? then exit */ 466 /* Was it final ACK? then exit */
411 if (finished && (opcode == TFTP_ACK)) 467 if (finished && (opcode == TFTP_ACK))
412 goto ret; 468 goto ret;
@@ -505,11 +561,13 @@ static int tftp_protocol(
505 } 561 }
506 io_bufsize = blksize + 4; 562 io_bufsize = blksize + 4;
507 } 563 }
508# if 0 /*ENABLE_FEATURE_TFTP_PROGRESS_BAR*/ 564# if ENABLE_FEATURE_TFTP_PROGRESS_BAR
509 if (transfer_size == 0) { /* if we don't know it yet */ 565 if (G.size == 0) { /* if we don't know it yet */
510 res = tftp_get_option("tsize", &rbuf[2], len - 2); 566 res = tftp_get_option("tsize", &rbuf[2], len - 2);
511 if (res) { 567 if (res) {
512 transfer_size = bb_strtoull(res, NULL, 10); 568 G.size = bb_strtoull(res, NULL, 10);
569 if (remote_file && G.size)
570 tftp_progress_init(remote_file);
513 } 571 }
514 } 572 }
515# endif 573# endif
@@ -660,9 +718,10 @@ int tftp_main(int argc UNUSED_PARAM, char **argv)
660 result = tftp_protocol( 718 result = tftp_protocol(
661 NULL /*our_lsa*/, peer_lsa, 719 NULL /*our_lsa*/, peer_lsa,
662 local_file, remote_file 720 local_file, remote_file
663 IF_FEATURE_TFTP_BLOCKSIZE(, 1 /* transfer_size */) 721 IF_FEATURE_TFTP_BLOCKSIZE(, 1 /* want_transfer_size */)
664 IF_FEATURE_TFTP_BLOCKSIZE(, blksize) 722 IF_FEATURE_TFTP_BLOCKSIZE(, blksize)
665 ); 723 );
724 tftp_progress_done();
666 725
667 if (result != EXIT_SUCCESS && NOT_LONE_DASH(local_file) && CMD_GET(opt)) { 726 if (result != EXIT_SUCCESS && NOT_LONE_DASH(local_file) && CMD_GET(opt)) {
668 unlink(local_file); 727 unlink(local_file);
@@ -682,7 +741,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
682 const char *error_msg; 741 const char *error_msg;
683 int opt, result, opcode; 742 int opt, result, opcode;
684 IF_FEATURE_TFTP_BLOCKSIZE(int blksize = TFTP_BLKSIZE_DEFAULT;) 743 IF_FEATURE_TFTP_BLOCKSIZE(int blksize = TFTP_BLKSIZE_DEFAULT;)
685 IF_FEATURE_TFTP_BLOCKSIZE(off_t transfer_size = 0;) 744 IF_FEATURE_TFTP_BLOCKSIZE(int want_transfer_size = 0;)
686 745
687 INIT_G(); 746 INIT_G();
688 747
@@ -746,7 +805,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
746 } 805 }
747 /* did client ask us about file size? */ 806 /* did client ask us about file size? */
748 if (tftp_get_option("tsize", opt_str, opt_len)) { 807 if (tftp_get_option("tsize", opt_str, opt_len)) {
749 transfer_size = 1; 808 want_transfer_size = 1;
750 } 809 }
751 } 810 }
752 } 811 }
@@ -760,7 +819,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
760 goto err; 819 goto err;
761 } 820 }
762 IF_GETPUT(option_mask32 |= TFTP_OPT_GET;) /* will receive file's data */ 821 IF_GETPUT(option_mask32 |= TFTP_OPT_GET;) /* will receive file's data */
763 transfer_size = 0; /* do not send file size, it's meaningless */ 822 want_transfer_size = 0; /* do not send file size, it's meaningless */
764 } else { 823 } else {
765 IF_GETPUT(option_mask32 |= TFTP_OPT_PUT;) /* will send file's data */ 824 IF_GETPUT(option_mask32 |= TFTP_OPT_PUT;) /* will send file's data */
766 } 825 }
@@ -774,7 +833,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
774 result = tftp_protocol( 833 result = tftp_protocol(
775 our_lsa, peer_lsa, 834 our_lsa, peer_lsa,
776 local_file IF_TFTP(, NULL /*remote_file*/) 835 local_file IF_TFTP(, NULL /*remote_file*/)
777 IF_FEATURE_TFTP_BLOCKSIZE(, transfer_size) 836 IF_FEATURE_TFTP_BLOCKSIZE(, want_transfer_size)
778 IF_FEATURE_TFTP_BLOCKSIZE(, blksize) 837 IF_FEATURE_TFTP_BLOCKSIZE(, blksize)
779 ); 838 );
780 839