1 /* $NetBSD: progress.c,v 1.2 2005/05/10 00:39:04 atatat 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.2 2005/05/10 00:39:04 atatat 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 off_t progress_current; 61 static off_t progress_total; 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(off_t total) 73 { 74 progress_current = 0; 75 progress_total = total; 76 } 77 78 void 79 progress_add(off_t amt) 80 { 81 progress_current += amt; 82 } 83 84 void 85 progress_bar(const char *dev, const char *label, off_t current, off_t total) 86 { 87 static int lastpercentage = -1; 88 char buf[256]; 89 int len, percentage; 90 int barlength; 91 int i; 92 int lengthextras; 93 94 #define BAROVERHEAD 10 /* non-* portion of progress bar */ 95 96 /* 97 * starts should contain at least sizeof(buf) - BAROVERHEAD 98 * entries. 99 */ 100 static const char stars[] = 101 "*****************************************************************************" 102 "*****************************************************************************" 103 "*****************************************************************************"; 104 105 if (progress_onoff == 0) 106 return; 107 108 current += progress_current; 109 total += progress_total; 110 111 len = 0; 112 lengthextras = strlen(dev) + (label != NULL ? strlen(label) : 0); 113 percentage = (current * 100) / total; 114 percentage = MAX(percentage, 0); 115 percentage = MIN(percentage, 100); 116 117 if (percentage == lastpercentage) 118 return; 119 lastpercentage = percentage; 120 121 len += snprintf(buf + len, BUFLEFT, "%s: ", dev); 122 if (label != NULL) 123 len += snprintf(buf + len, BUFLEFT, "%s ", label); 124 125 barlength = MIN(sizeof(buf) - 1, ttywidth) - BAROVERHEAD - lengthextras; 126 if (barlength > 0) { 127 i = barlength * percentage / 100; 128 len += snprintf(buf + len, BUFLEFT, 129 "|%.*s%*s| ", i, stars, barlength - i, ""); 130 } 131 len += snprintf(buf + len, BUFLEFT, "%3d%%\r", percentage); 132 write(fileno(stdout), buf, len); 133 } 134 135 void 136 progress_done(void) 137 { 138 char buf[256]; 139 int len; 140 141 if (progress_onoff == 0) 142 return; 143 144 len = MIN(sizeof(buf) - 2, ttywidth); 145 memset(buf, ' ', len); 146 buf[len] = '\r'; 147 buf[len + 1] = '\0'; 148 write(fileno(stdout), buf, len + 1); 149 } 150 151 void 152 progress_ttywidth(int a) 153 { 154 struct winsize winsize; 155 int oerrno = errno; 156 157 if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1 && 158 winsize.ws_col != 0) 159 ttywidth = winsize.ws_col; 160 else 161 ttywidth = 80; 162 errno = oerrno; 163 } 164 165 #endif /* ! SMALL */ 166