1/* $NetBSD: progress.c,v 1.4 2008/04/28 20:23:08 martin 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.4 2008/04/28 20:23:08 martin 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 50static size_t ttywidth = 80; 51 52static int progress_onoff; 53static int progress_lowlim; 54static int progress_highlim; 55 56#define BUFLEFT (sizeof(buf) - len) 57 58void 59progress_switch(int onoff) 60{ 61 progress_onoff = onoff; 62} 63 64void 65progress_init(void) 66{ 67 progress_setrange(0, 100); 68} 69 70/* Set both low and high limit. */ 71void 72progress_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. */ 79void 80progress_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 */ 89void 90progress_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 138void 139progress_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 154void 155progress_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