1 /* $NetBSD: progress.c,v 1.3 2006/11/14 21:01:46 apb Exp $ */ 2 3 /*- 4 * Copyright (c) 1997-2004 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Luke Mewburn; by Chris Gilbert; and by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #ifndef SMALL 40 #include <sys/cdefs.h> 41 __RCSID("$NetBSD: progress.c,v 1.3 2006/11/14 21:01:46 apb Exp $"); 42 43 /* 44 * File system independent fsck progress bar routines. 45 */ 46 47 #include <sys/param.h> 48 #include <sys/tty.h> 49 #include <sys/ioctl.h> 50 #include <errno.h> 51 #include <stdio.h> 52 #include <string.h> 53 #include <unistd.h> 54 55 #include "progress.h" 56 57 static int ttywidth = 80; 58 59 static int progress_onoff; 60 static int progress_lowlim; 61 static int progress_highlim; 62 63 #define BUFLEFT (sizeof(buf) - len) 64 65 void 66 progress_switch(int onoff) 67 { 68 progress_onoff = onoff; 69 } 70 71 void 72 progress_init(void) 73 { 74 progress_setrange(0, 100); 75 } 76 77 /* Set both low and high limit. */ 78 void 79 progress_setrange(int lowlim, int highlim) 80 { 81 progress_lowlim = lowlim; 82 progress_highlim = highlim; 83 } 84 85 /* Previous high limit becomes new low limit; set new high limit. */ 86 void 87 progress_sethighlim(int highlim) 88 { 89 progress_setrange(progress_highlim, highlim); 90 } 91 92 /* 93 * Display a progress bar, assuming that current/total represents a 94 * percentage in the range [progress_lowlim .. progress_highlim]. 95 */ 96 void 97 progress_bar(const char *dev, const char *label, off_t current, off_t total) 98 { 99 static int lastpercentage = -1; 100 char buf[256]; 101 int len, percentage; 102 int barlength; 103 int i; 104 int lengthextras; 105 106 #define BAROVERHEAD 10 /* non-* portion of progress bar */ 107 108 /* 109 * stars should contain at least sizeof(buf) - BAROVERHEAD 110 * entries. 111 */ 112 static const char stars[] = 113 "*****************************************************************************" 114 "*****************************************************************************" 115 "*****************************************************************************"; 116 117 if (progress_onoff == 0) 118 return; 119 120 len = 0; 121 lengthextras = strlen(dev) + (label != NULL ? strlen(label) : 0); 122 percentage = progress_lowlim + 123 (current * (progress_highlim - progress_lowlim)) / total; 124 percentage = MAX(percentage, 0); 125 percentage = MIN(percentage, 100); 126 127 if (percentage == lastpercentage) 128 return; 129 lastpercentage = percentage; 130 131 len += snprintf(buf + len, BUFLEFT, "%s: ", dev); 132 if (label != NULL) 133 len += snprintf(buf + len, BUFLEFT, "%s ", label); 134 135 barlength = MIN(sizeof(buf) - 1, ttywidth) - BAROVERHEAD - lengthextras; 136 if (barlength > 0) { 137 i = barlength * percentage / 100; 138 len += snprintf(buf + len, BUFLEFT, 139 "|%.*s%*s| ", i, stars, barlength - i, ""); 140 } 141 len += snprintf(buf + len, BUFLEFT, "%3d%%\r", percentage); 142 write(fileno(stdout), buf, len); 143 } 144 145 void 146 progress_done(void) 147 { 148 char buf[256]; 149 int len; 150 151 if (progress_onoff == 0) 152 return; 153 154 len = MIN(sizeof(buf) - 2, ttywidth); 155 memset(buf, ' ', len); 156 buf[len] = '\r'; 157 buf[len + 1] = '\0'; 158 write(fileno(stdout), buf, len + 1); 159 } 160 161 void 162 progress_ttywidth(int a) 163 { 164 struct winsize winsize; 165 int oerrno = errno; 166 167 if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1 && 168 winsize.ws_col != 0) 169 ttywidth = winsize.ws_col; 170 else 171 ttywidth = 80; 172 errno = oerrno; 173 } 174 175 #endif /* ! SMALL */ 176