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