printquota.c revision 1.5 1 1.5 bouyer /* $NetBSD: printquota.c,v 1.5 2011/03/07 11:46:55 bouyer Exp $ */
2 1.2 bouyer
3 1.2 bouyer /*
4 1.2 bouyer * Copyright (c) 1980, 1990, 1993
5 1.2 bouyer * The Regents of the University of California. All rights reserved.
6 1.2 bouyer *
7 1.2 bouyer * This code is derived from software contributed to Berkeley by
8 1.2 bouyer * Robert Elz at The University of Melbourne.
9 1.2 bouyer *
10 1.2 bouyer * Redistribution and use in source and binary forms, with or without
11 1.2 bouyer * modification, are permitted provided that the following conditions
12 1.2 bouyer * are met:
13 1.2 bouyer * 1. Redistributions of source code must retain the above copyright
14 1.2 bouyer * notice, this list of conditions and the following disclaimer.
15 1.2 bouyer * 2. Redistributions in binary form must reproduce the above copyright
16 1.2 bouyer * notice, this list of conditions and the following disclaimer in the
17 1.2 bouyer * documentation and/or other materials provided with the distribution.
18 1.2 bouyer * 3. Neither the name of the University nor the names of its contributors
19 1.2 bouyer * may be used to endorse or promote products derived from this software
20 1.2 bouyer * without specific prior written permission.
21 1.2 bouyer *
22 1.2 bouyer * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 1.2 bouyer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 1.2 bouyer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 1.2 bouyer * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 1.2 bouyer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 1.2 bouyer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 1.2 bouyer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 1.2 bouyer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 1.2 bouyer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 1.2 bouyer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 1.2 bouyer * SUCH DAMAGE.
33 1.2 bouyer */
34 1.2 bouyer
35 1.2 bouyer #include <sys/cdefs.h>
36 1.2 bouyer #ifndef lint
37 1.2 bouyer __COPYRIGHT("@(#) Copyright (c) 1980, 1990, 1993\
38 1.2 bouyer The Regents of the University of California. All rights reserved.");
39 1.2 bouyer #endif /* not lint */
40 1.2 bouyer
41 1.2 bouyer #ifndef lint
42 1.2 bouyer #if 0
43 1.2 bouyer static char sccsid[] = "@(#)quota.c 8.4 (Berkeley) 4/28/95";
44 1.2 bouyer #else
45 1.5 bouyer __RCSID("$NetBSD: printquota.c,v 1.5 2011/03/07 11:46:55 bouyer Exp $");
46 1.2 bouyer #endif
47 1.2 bouyer #endif /* not lint */
48 1.2 bouyer
49 1.2 bouyer #include <sys/param.h>
50 1.2 bouyer #include <sys/types.h>
51 1.2 bouyer
52 1.2 bouyer #include <ctype.h>
53 1.2 bouyer #include <stdio.h>
54 1.2 bouyer #include <stdlib.h>
55 1.2 bouyer #include <string.h>
56 1.2 bouyer #include <time.h>
57 1.2 bouyer #include <unistd.h>
58 1.2 bouyer #include <errno.h>
59 1.2 bouyer #include <limits.h>
60 1.2 bouyer #include <inttypes.h>
61 1.2 bouyer
62 1.4 christos #include "printquota.h"
63 1.2 bouyer
64 1.2 bouyer /*
65 1.2 bouyer * convert 64bit value to a printable string
66 1.2 bouyer */
67 1.2 bouyer const char *
68 1.3 christos intprt(char *buf, size_t len, uint64_t val, int flags, int hflag)
69 1.2 bouyer {
70 1.2 bouyer if (val == UQUAD_MAX)
71 1.5 bouyer return (len > sizeof("unlimited")) ? "unlimited" : "-";
72 1.2 bouyer
73 1.2 bouyer if (flags & HN_B)
74 1.2 bouyer val = dbtob(val);
75 1.2 bouyer
76 1.2 bouyer if (hflag) {
77 1.3 christos (void)humanize_number(buf, len, (int64_t)val, "", HN_AUTOSCALE,
78 1.3 christos flags);
79 1.2 bouyer return buf;
80 1.2 bouyer }
81 1.2 bouyer if (flags & HN_B) {
82 1.2 bouyer /* traditionnal display: blocks are in kilobytes */
83 1.2 bouyer val = val / 1024;
84 1.2 bouyer }
85 1.3 christos (void)snprintf(buf, len, "%" PRId64, val);
86 1.2 bouyer return buf;
87 1.2 bouyer }
88 1.2 bouyer
89 1.2 bouyer /*
90 1.2 bouyer * Calculate the grace period and return a user-friendly string for it.
91 1.2 bouyer */
92 1.2 bouyer #define MINUTE 60
93 1.2 bouyer #define HOUR (MINUTE * 60)
94 1.2 bouyer #define DAY (HOUR * 24)
95 1.2 bouyer #define WEEK (DAY * 7)
96 1.2 bouyer #define MONTH (DAY * 30)
97 1.2 bouyer #define YEAR (DAY * 355)
98 1.2 bouyer
99 1.2 bouyer const char *
100 1.3 christos timeprt(char *buf, size_t len, time_t now, time_t seconds)
101 1.2 bouyer {
102 1.2 bouyer time_t years, months, weeks, days, hours, minutes;
103 1.2 bouyer
104 1.2 bouyer if (now > seconds)
105 1.3 christos return "none";
106 1.2 bouyer
107 1.2 bouyer seconds -= now;
108 1.2 bouyer
109 1.2 bouyer minutes = (seconds + MINUTE / 2) / MINUTE;
110 1.2 bouyer hours = (seconds + HOUR / 2) / HOUR;
111 1.2 bouyer days = (seconds + DAY / 2) / DAY;
112 1.2 bouyer years = (seconds + YEAR / 2) / YEAR;
113 1.2 bouyer months = (seconds + MONTH / 2) / MONTH;
114 1.2 bouyer weeks = (seconds + WEEK / 2) / WEEK;
115 1.2 bouyer
116 1.2 bouyer if (years >= 2) {
117 1.3 christos (void)snprintf(buf, len, "%" PRId64 "years", years);
118 1.2 bouyer return buf;
119 1.2 bouyer }
120 1.2 bouyer if (weeks > 9) {
121 1.3 christos (void)snprintf(buf, len, "%" PRId64 "months", months);
122 1.2 bouyer return buf;
123 1.2 bouyer }
124 1.2 bouyer if (days > 9) {
125 1.3 christos (void)snprintf(buf, len, "%" PRId64 "weeks", weeks);
126 1.2 bouyer return buf;
127 1.2 bouyer }
128 1.2 bouyer if (hours > 36) {
129 1.3 christos (void)snprintf(buf, len, "%" PRId64 "days", days);
130 1.2 bouyer return buf;
131 1.2 bouyer }
132 1.2 bouyer if (minutes > 60) {
133 1.3 christos (void)snprintf(buf, len, "%2d:%d",
134 1.2 bouyer (int)(minutes / 60), (int)(minutes % 60));
135 1.2 bouyer return buf;
136 1.2 bouyer }
137 1.3 christos (void)snprintf(buf, len, "%2d", (int)minutes);
138 1.2 bouyer return buf;
139 1.2 bouyer }
140 1.2 bouyer
141 1.2 bouyer /*
142 1.2 bouyer * Calculate the grace period and return a precise string for it,
143 1.2 bouyer * either in seconds or in format xWyDzHtMuS
144 1.2 bouyer */
145 1.2 bouyer const char *
146 1.4 christos timepprt(char *buf, size_t len, time_t seconds, int hflag)
147 1.2 bouyer {
148 1.3 christos ssize_t i = 0;
149 1.2 bouyer
150 1.2 bouyer if (hflag == 0) {
151 1.3 christos (void)snprintf(buf, len, "%" PRId64, seconds);
152 1.2 bouyer return buf;
153 1.2 bouyer }
154 1.2 bouyer
155 1.2 bouyer if ((seconds / WEEK) > 0) {
156 1.3 christos i += snprintf(buf + i, len - i, "%" PRId64 "W", seconds / WEEK);
157 1.2 bouyer seconds = seconds % WEEK;
158 1.2 bouyer }
159 1.3 christos
160 1.4 christos if (len - i < 3 || seconds == 0)
161 1.3 christos return buf;
162 1.3 christos
163 1.2 bouyer if ((seconds / DAY) > 0) {
164 1.3 christos i += snprintf(buf + i, len - i, "%" PRId64 "D", seconds / DAY);
165 1.2 bouyer seconds = seconds % DAY;
166 1.2 bouyer }
167 1.3 christos
168 1.4 christos if (len - i < 4 || seconds == 0)
169 1.3 christos return buf;
170 1.3 christos
171 1.2 bouyer if ((seconds / HOUR) > 0) {
172 1.3 christos i += snprintf(buf + i, len - i, "%" PRId64 "H", seconds / HOUR);
173 1.2 bouyer seconds = seconds % HOUR;
174 1.2 bouyer }
175 1.3 christos
176 1.4 christos if (len - i < 4 || seconds == 0)
177 1.3 christos return buf;
178 1.3 christos
179 1.2 bouyer if ((seconds / MINUTE) > 0) {
180 1.3 christos i += snprintf(buf + i , len - i, "%" PRId64 "M",
181 1.3 christos seconds / MINUTE);
182 1.2 bouyer seconds = seconds % MINUTE;
183 1.2 bouyer }
184 1.3 christos
185 1.4 christos if (len - i < 4 || seconds == 0)
186 1.3 christos return buf;
187 1.3 christos
188 1.3 christos (void)snprintf(buf + i, len - i, "%" PRId64 "S", seconds);
189 1.3 christos return buf;
190 1.2 bouyer }
191 1.2 bouyer
192 1.2 bouyer /*
193 1.2 bouyer * convert a string of the form xWyDzHtMuS, or plain decimal, to
194 1.2 bouyer * a time in seconds
195 1.2 bouyer */
196 1.2 bouyer int
197 1.2 bouyer timeprd(const char *str, time_t *valp)
198 1.2 bouyer {
199 1.2 bouyer char buf[20];
200 1.2 bouyer char *cur, *next, *end;
201 1.2 bouyer time_t val= 0;
202 1.2 bouyer
203 1.2 bouyer strncpy(buf, str, sizeof(buf));
204 1.2 bouyer next = buf;
205 1.2 bouyer cur = strsep(&next, "Ww");
206 1.2 bouyer if (next != NULL) {
207 1.2 bouyer val = strtoumax(cur, &end, 10) * WEEK;
208 1.2 bouyer if (end[0] != '\0')
209 1.2 bouyer return EINVAL;
210 1.2 bouyer } else
211 1.2 bouyer next = cur;
212 1.2 bouyer cur = strsep(&next, "Dd");
213 1.2 bouyer if (next != NULL) {
214 1.2 bouyer val += strtoumax(cur, &end, 10) * DAY;
215 1.2 bouyer if (end[0] != '\0')
216 1.2 bouyer return EINVAL;
217 1.2 bouyer } else
218 1.2 bouyer next = cur;
219 1.2 bouyer cur = strsep(&next, "Hh");
220 1.2 bouyer if (next != NULL) {
221 1.2 bouyer val += strtoumax(cur, &end, 10) * HOUR;
222 1.2 bouyer if (end[0] != '\0')
223 1.2 bouyer return EINVAL;
224 1.2 bouyer } else
225 1.2 bouyer next = cur;
226 1.2 bouyer cur = strsep(&next, "Mm");
227 1.2 bouyer if (next != NULL) {
228 1.2 bouyer val += strtoumax(cur, &end, 10) * MINUTE;
229 1.2 bouyer if (end[0] != '\0')
230 1.2 bouyer return EINVAL;
231 1.2 bouyer } else
232 1.2 bouyer next = cur;
233 1.2 bouyer cur = strsep(&next, "Ss");
234 1.2 bouyer val += strtoumax(cur, &end, 10);
235 1.2 bouyer if (end[0] != '\0')
236 1.2 bouyer return EINVAL;
237 1.2 bouyer *valp = val;
238 1.2 bouyer return 0;
239 1.2 bouyer }
240 1.2 bouyer
241 1.2 bouyer /*
242 1.2 bouyer * convert a string to a uint64 value
243 1.2 bouyer */
244 1.2 bouyer int
245 1.2 bouyer intrd(char *str, uint64_t *val, u_int flags)
246 1.2 bouyer {
247 1.2 bouyer char *last = &str[strlen(str) - 1];
248 1.2 bouyer int ret;
249 1.2 bouyer
250 1.2 bouyer if (*last >= '0' && *last <= '9') {
251 1.2 bouyer /* no unit provided, use default */
252 1.2 bouyer errno = 0;
253 1.2 bouyer *val = strtoumax(str, NULL, 10);
254 1.2 bouyer if (flags & HN_B) {
255 1.2 bouyer /* in kb, convert to disk blocks */
256 1.2 bouyer *val = btodb(*val * 1024);
257 1.2 bouyer }
258 1.2 bouyer
259 1.2 bouyer return errno;
260 1.2 bouyer }
261 1.2 bouyer if (strcmp(str, "-") == 0 || strcmp(str, "unlimited") == 0) {
262 1.2 bouyer *val = UQUAD_MAX;
263 1.2 bouyer return 0;
264 1.2 bouyer }
265 1.2 bouyer if (flags & HN_B) {
266 1.2 bouyer if (*last == 'B' || *last == 'b')
267 1.2 bouyer *last = '\0';
268 1.2 bouyer }
269 1.2 bouyer ret = dehumanize_number(str, (int64_t *)val);
270 1.2 bouyer if (flags & HN_B)
271 1.2 bouyer *val = btodb(*val);
272 1.2 bouyer return ret;
273 1.2 bouyer }
274