1 /* $NetBSD: progress.c,v 1.5 2009/04/11 06:48:36 lukem 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #ifndef SMALL 33 #include <sys/cdefs.h> 34 __RCSID("$NetBSD: progress.c,v 1.5 2009/04/11 06:48:36 lukem Exp $"); 35 36 /* 37 * File system independent fsck progress bar routines. 38 */ 39 40 #include <sys/param.h> 41 #include <sys/tty.h> 42 #include <sys/ioctl.h> 43 #include <errno.h> 44 #include <stdio.h> 45 #include <string.h> 46 #include <unistd.h> 47 48 #include "progress.h" 49 50 static size_t ttywidth = 80; 51 52 static int progress_onoff; 53 static int progress_lowlim; 54 static int progress_highlim; 55 56 #define BUFLEFT (sizeof(buf) - len) 57 58 void 59 progress_switch(int onoff) 60 { 61 progress_onoff = onoff; 62 } 63 64 void 65 progress_init(void) 66 { 67 progress_setrange(0, 100); 68 } 69 70 /* Set both low and high limit. */ 71 void 72 progress_setrange(int lowlim, int highlim) 73 { 74 progress_lowlim = lowlim; 75 progress_highlim = highlim; 76 } 77 78 /* Previous high limit becomes new low limit; set new high limit. */ 79 void 80 progress_sethighlim(int highlim) 81 { 82 progress_setrange(progress_highlim, highlim); 83 } 84 85 /* 86 * Display a progress bar, assuming that current/total represents a 87 * percentage in the range [progress_lowlim .. progress_highlim]. 88 */ 89 void 90 progress_bar(const char *dev, const char *label, off_t current, off_t total) 91 { 92 static int lastpercentage = -1; 93 char buf[256]; 94 int len, percentage; 95 int barlength; 96 int i; 97 int lengthextras; 98 99 #define BAROVERHEAD 10 /* non-* portion of progress bar */ 100 101 /* 102 * stars should contain at least sizeof(buf) - BAROVERHEAD 103 * entries. 104 */ 105 static const char stars[] = 106 "*****************************************************************************" 107 "*****************************************************************************" 108 "*****************************************************************************"; 109 110 if (progress_onoff == 0) 111 return; 112 113 len = 0; 114 lengthextras = strlen(dev) + (label != NULL ? strlen(label) : 0); 115 percentage = progress_lowlim + 116 (current * (progress_highlim - progress_lowlim)) / total; 117 percentage = MAX(percentage, 0); 118 percentage = MIN(percentage, 100); 119 120 if (percentage == lastpercentage) 121 return; 122 lastpercentage = percentage; 123 124 len += snprintf(buf + len, BUFLEFT, "%s: ", dev); 125 if (label != NULL) 126 len += snprintf(buf + len, BUFLEFT, "%s ", label); 127 128 barlength = MIN(sizeof(buf) - 1, ttywidth) - BAROVERHEAD - lengthextras; 129 if (barlength > 0) { 130 i = barlength * percentage / 100; 131 len += snprintf(buf + len, BUFLEFT, 132 "|%.*s%*s| ", i, stars, barlength - i, ""); 133 } 134 len += snprintf(buf + len, BUFLEFT, "%3d%%\r", percentage); 135 write(fileno(stdout), buf, len); 136 } 137 138 void 139 progress_done(void) 140 { 141 char buf[256]; 142 int len; 143 144 if (progress_onoff == 0) 145 return; 146 147 len = MIN(sizeof(buf) - 2, ttywidth); 148 memset(buf, ' ', len); 149 buf[len] = '\r'; 150 buf[len + 1] = '\0'; 151 write(fileno(stdout), buf, len + 1); 152 } 153 154 void 155 progress_ttywidth(int a) 156 { 157 struct winsize winsize; 158 int oerrno = errno; 159 160 if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1 && 161 winsize.ws_col != 0) 162 ttywidth = winsize.ws_col; 163 else 164 ttywidth = 80; 165 errno = oerrno; 166 } 167 168 #endif /* ! SMALL */ 169