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