diff options
author | Magnus Damm <magnus.damm@gmail.com> | 2009-11-08 18:03:09 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-11-08 18:03:09 +0100 |
commit | 8bd0af996226b720342f792129f21581aa08bb5d (patch) | |
tree | 831650442ce03bdb6f51465ac5b4162fb7e18d5e | |
parent | bbd423530f58ab695030f3d26cb81089a2f7a945 (diff) | |
download | busybox-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.in | 11 | ||||
-rw-r--r-- | networking/tftp.c | 91 |
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 | ||
848 | config FEATURE_TFTP_BLOCKSIZE | 848 | config 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 | |||
856 | config 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 | ||
856 | config TFTP_DEBUG | 863 | config 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) |
95 | struct 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 */ | ||
108 | static 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 | } | ||
132 | static void tftp_progress_init(const char *file) | ||
133 | { | ||
134 | G.file = file; | ||
135 | progress_meter(-1); | ||
136 | } | ||
137 | static 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 | ||