aboutsummaryrefslogtreecommitdiff
path: root/networking/tftp.c
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 /networking/tftp.c
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>
Diffstat (limited to '')
-rw-r--r--networking/tftp.c91
1 files changed, 75 insertions, 16 deletions
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