From eb86d661d79f25c91788964a768b54223717e8f6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 2 Jul 1998 00:47:13 +0000 Subject: [PATCH] added --progress option which shows the progress of transfers. This gives bored users something to watch. --- log.c | 2 + match.c | 10 ++++ options.c | 12 ++++- rsync.c | 146 ++++++++++++++++++++++++++++++------------------------ rsync.yo | 5 ++ util.c | 25 ++++++++++ 6 files changed, 133 insertions(+), 67 deletions(-) diff --git a/log.c b/log.c index 71eb234d..2454088e 100644 --- a/log.c +++ b/log.c @@ -102,6 +102,8 @@ void rprintf(int fd, const char *format, ...) if (fwrite(buf, len, 1, f) != 1) exit_cleanup(1); + if (buf[len-1] == '\r') fflush(f); + depth--; } diff --git a/match.c b/match.c index 272025aa..f54c2295 100644 --- a/match.c +++ b/match.c @@ -118,6 +118,10 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf, last_match = offset + s->sums[i].len; else last_match = offset; + + show_progress(last_match, buf->size); + + if (i == -1) end_progress(); } @@ -252,6 +256,12 @@ void match_sums(int f,struct sum_struct *s,struct map_struct *buf,OFF_T len) if (verbose > 2) rprintf(FINFO,"done hash search\n"); } else { + OFF_T j; + /* by doing this in pieces we avoid too many seeks */ + for (j=0;j<(len-CHUNK_SIZE);j+=CHUNK_SIZE) { + int n1 = MIN(CHUNK_SIZE,(len-CHUNK_SIZE)-j); + matched(f,s,buf,j+n1,-2); + } matched(f,s,buf,len,-1); } diff --git a/options.c b/options.c index 10c27733..0a0e680f 100644 --- a/options.c +++ b/options.c @@ -56,6 +56,7 @@ int recurse = 0; int am_daemon=0; int am_client=0; int do_stats=0; +int do_progress=0; int keep_partial=0; int block_size=BLOCK_SIZE; @@ -126,6 +127,7 @@ void usage(int F) rprintf(F," --config=FILE specify alternate rsyncd.conf file\n"); rprintf(F," --port=PORT specify alternate rsyncd port number\n"); rprintf(F," --stats give some file transfer stats\n"); + rprintf(F," --progress show progress during transfer\n"); rprintf(F," -h, --help show this help screen\n"); rprintf(F,"\n"); @@ -139,7 +141,7 @@ void usage(int F) enum {OPT_VERSION,OPT_SUFFIX,OPT_SENDER,OPT_SERVER,OPT_EXCLUDE, OPT_EXCLUDE_FROM,OPT_DELETE,OPT_NUMERIC_IDS,OPT_RSYNC_PATH, OPT_FORCE,OPT_TIMEOUT,OPT_DAEMON,OPT_CONFIG,OPT_PORT, - OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS, OPT_PARTIAL}; + OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS, OPT_PARTIAL, OPT_PROGRESS}; static char *short_options = "oblLWHpguDCtcahvrRIxnSe:B:T:z"; @@ -185,6 +187,7 @@ static struct option long_options[] = { {"compress", 0, 0, 'z'}, {"daemon", 0, 0, OPT_DAEMON}, {"stats", 0, 0, OPT_STATS}, + {"progress", 0, 0, OPT_PROGRESS}, {"partial", 0, 0, OPT_PARTIAL}, {"config", 1, 0, OPT_CONFIG}, {"port", 1, 0, OPT_PORT}, @@ -385,6 +388,10 @@ void parse_arguments(int argc, char *argv[]) do_stats = 1; break; + case OPT_PROGRESS: + do_progress = 1; + break; + case OPT_PARTIAL: keep_partial = 1; break; @@ -487,6 +494,9 @@ void server_options(char **args,int *argc) if (keep_partial) args[ac++] = "--partial"; + if (do_progress) + args[ac++] = "--progress"; + if (force_delete) args[ac++] = "--force"; diff --git a/rsync.c b/rsync.c index 48ed69f8..5af71933 100644 --- a/rsync.c +++ b/rsync.c @@ -577,78 +577,92 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out) -static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname) +static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname, + OFF_T total_size) { - int i,n,remainder,len,count; - OFF_T offset = 0; - OFF_T offset2; - char *data; - static char file_sum1[MD4_SUM_LENGTH]; - static char file_sum2[MD4_SUM_LENGTH]; - char *map=NULL; - - count = read_int(f_in); - n = read_int(f_in); - remainder = read_int(f_in); + int i,n,remainder,len,count; + OFF_T offset = 0; + OFF_T offset2; + char *data; + static char file_sum1[MD4_SUM_LENGTH]; + static char file_sum2[MD4_SUM_LENGTH]; + char *map=NULL; + + count = read_int(f_in); + n = read_int(f_in); + remainder = read_int(f_in); + + sum_init(); + + for (i=recv_token(f_in,&data); i != 0; i=recv_token(f_in,&data)) { - sum_init(); + show_progress(offset, total_size); - for (i=recv_token(f_in,&data); i != 0; i=recv_token(f_in,&data)) { - if (i > 0) { - if (verbose > 3) - rprintf(FINFO,"data recv %d at %d\n",i,(int)offset); + if (i > 0) { + if (verbose > 3) { + rprintf(FINFO,"data recv %d at %d\n", + i,(int)offset); + } - stats.literal_data += i; - cleanup_got_literal = 1; + stats.literal_data += i; + cleanup_got_literal = 1; - sum_update(data,i); - - if (fd != -1 && write_file(fd,data,i) != i) { - rprintf(FERROR,"write failed on %s : %s\n",fname,strerror(errno)); - exit_cleanup(1); - } - offset += i; - } else { - i = -(i+1); - offset2 = i*n; - len = n; - if (i == count-1 && remainder != 0) - len = remainder; + sum_update(data,i); - stats.matched_data += len; - - if (verbose > 3) - rprintf(FINFO,"chunk[%d] of size %d at %d offset=%d\n", - i,len,(int)offset2,(int)offset); - - map = map_ptr(buf,offset2,len); + if (fd != -1 && write_file(fd,data,i) != i) { + rprintf(FERROR,"write failed on %s : %s\n",fname,strerror(errno)); + exit_cleanup(1); + } + offset += i; + continue; + } - see_token(map, len); - sum_update(map,len); + i = -(i+1); + offset2 = i*n; + len = n; + if (i == count-1 && remainder != 0) + len = remainder; + + stats.matched_data += len; + + if (verbose > 3) + rprintf(FINFO,"chunk[%d] of size %d at %d offset=%d\n", + i,len,(int)offset2,(int)offset); + + map = map_ptr(buf,offset2,len); + + see_token(map, len); + sum_update(map,len); + + if (fd != -1 && write_file(fd,map,len) != len) { + rprintf(FERROR,"write failed on %s : %s\n", + fname,strerror(errno)); + exit_cleanup(1); + } + offset += len; + } - if (fd != -1 && write_file(fd,map,len) != len) { - rprintf(FERROR,"write failed on %s : %s\n",fname,strerror(errno)); - exit_cleanup(1); - } - offset += len; - } - } + end_progress(); - if (fd != -1 && offset > 0 && sparse_end(fd) != 0) { - rprintf(FERROR,"write failed on %s : %s\n",fname,strerror(errno)); - exit_cleanup(1); - } + if (fd != -1 && offset > 0 && sparse_end(fd) != 0) { + rprintf(FERROR,"write failed on %s : %s\n", + fname,strerror(errno)); + exit_cleanup(1); + } - sum_end(file_sum1); + sum_end(file_sum1); - if (remote_version >= 14) { - read_buf(f_in,file_sum2,MD4_SUM_LENGTH); - if (verbose > 2) - rprintf(FINFO,"got file_sum\n"); - if (fd != -1 && memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0) - return 0; - } - return 1; + if (remote_version >= 14) { + read_buf(f_in,file_sum2,MD4_SUM_LENGTH); + if (verbose > 2) { + rprintf(FINFO,"got file_sum\n"); + } + if (fd != -1 && + memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0) { + return 0; + } + } + return 1; } @@ -915,14 +929,14 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) if (fd1 != -1 && do_fstat(fd1,&st) != 0) { rprintf(FERROR,"fstat %s : %s\n",fname,strerror(errno)); - receive_data(f_in,NULL,-1,NULL); + receive_data(f_in,NULL,-1,NULL,file->length); close(fd1); continue; } if (fd1 != -1 && !S_ISREG(st.st_mode)) { rprintf(FERROR,"%s : not a regular file (recv_files)\n",fname); - receive_data(f_in,NULL,-1,NULL); + receive_data(f_in,NULL,-1,NULL,file->length); close(fd1); continue; } @@ -943,7 +957,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) if (NULL == do_mktemp(fnametmp)) { rprintf(FERROR,"mktemp %s failed\n",fnametmp); - receive_data(f_in,buf,-1,NULL); + receive_data(f_in,buf,-1,NULL,file->length); if (buf) unmap_file(buf); close(fd1); continue; @@ -964,7 +978,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) } if (fd2 == -1) { rprintf(FERROR,"open %s : %s\n",fnametmp,strerror(errno)); - receive_data(f_in,buf,-1,NULL); + receive_data(f_in,buf,-1,NULL,file->length); if (buf) unmap_file(buf); close(fd1); continue; @@ -978,7 +992,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) printf("%s\n",fname); /* recv file data */ - recv_ok = receive_data(f_in,buf,fd2,fname); + recv_ok = receive_data(f_in,buf,fd2,fname,file->length); if (buf) unmap_file(buf); if (fd1 != -1) { diff --git a/rsync.yo b/rsync.yo index b13a8b8c..9847ac90 100644 --- a/rsync.yo +++ b/rsync.yo @@ -234,6 +234,7 @@ verb( --config=FILE specify alternate rsyncd.conf file --port=PORT specify alternate rsyncd port number --stats give some file transfer stats + --progress show progress during transfer -h, --help show this help screen ) @@ -510,6 +511,10 @@ on the file transfer, allowing you to tell how effective the rsync algorithm is for your data. This option only works in conjunction with the -v (verbose) option. +dit(bf(--progress)) This option tells rsync to print information +showing the progress of the transfer. This gives a bored user +something to watch. + enddit() manpagesection(EXCLUDE PATTERNS) diff --git a/util.c b/util.c index 639a4a4f..34c8f8b0 100644 --- a/util.c +++ b/util.c @@ -685,3 +685,28 @@ int u_strcmp(const char *cs1, const char *cs2) return (int)*s1 - (int)*s2; } + +static int last_pct = -1; + +void end_progress(void) +{ + extern int do_progress, am_server; + + if (do_progress && !am_server) { + rprintf(FINFO,"\n"); + } + last_pct = -1; +} + +void show_progress(OFF_T ofs, OFF_T size) +{ + extern int do_progress, am_server; + + if (do_progress && !am_server) { + int pct = (int)((100.0*ofs)/size + 0.5); + if (pct != last_pct) { + rprintf(FINFO,"%.0f (%d%%)\r", (double)ofs, pct); + last_pct = pct; + } + } +} -- 2.34.1