]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - quota/util.c
2 * Copyright (c) 2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <sys/types.h>
27 #define SECONDS_IN_A_DAY (24 * 60 * 60)
28 #define SECONDS_IN_A_HOUR (60 * 60)
29 #define SECONDS_IN_A_MINUTE (60)
36 static char timestamp
[32];
38 uint days
, hours
, minutes
, seconds
;
40 if (flags
& ABSOLUTE_FLAG
) {
44 timer
= MAX(origin
- now
, 0);
48 * If we are in verbose mode, or if less than a day remains, we
49 * will show "X days hh:mm:ss" so the user knows the exact timer status.
51 * Otherwise, we round down to the nearest day - so we add 30s here
52 * such that setting and reporting a limit in rapid succession will
53 * show the limit which was just set, rather than immediately reporting
56 if ((timer
> SECONDS_IN_A_DAY
) && !(flags
& VERBOSE_FLAG
))
57 timer
+= 30; /* seconds */
59 days
= timer
/ SECONDS_IN_A_DAY
;
61 timer
%= SECONDS_IN_A_DAY
;
62 hours
= timer
/ SECONDS_IN_A_HOUR
;
64 timer
%= SECONDS_IN_A_HOUR
;
65 minutes
= timer
/ SECONDS_IN_A_MINUTE
;
66 seconds
= timer
% SECONDS_IN_A_MINUTE
;
68 if (flags
& LIMIT_FLAG
) {
69 snprintf(timestamp
, sizeof(timestamp
), (flags
& HUMAN_FLAG
) ?
70 _("[-none-]") : _("[--none--]"));
71 } else if (origin
== 0) {
72 snprintf(timestamp
, sizeof(timestamp
), (flags
& HUMAN_FLAG
) ?
73 _("[------]") : _("[--------]"));
74 } else if ((hours
== 0 && minutes
== 0 && seconds
== 0) ||
75 (!(flags
& VERBOSE_FLAG
) && days
> 0)) {
76 snprintf(timestamp
, sizeof(timestamp
), "[%u %s]",
77 days
, days
== 1 ? _("day") : _("days"));
78 } else if (flags
& VERBOSE_FLAG
) {
79 snprintf(timestamp
, sizeof(timestamp
), "[%u %s %02u:%02u:%02u]",
80 days
, days
== 1 ? _("day") : _("days"),
81 hours
, minutes
, seconds
);
82 } else { /* non-verbose, less than a day remaining */
83 snprintf(timestamp
, sizeof(timestamp
),
84 (flags
& HUMAN_FLAG
) ?
85 "%02u:%02u:%02u" : "[%02u:%02u:%02u]",
86 hours
, minutes
, seconds
);
95 const char *fmt_round
,
96 const char *fmt_not_round
,
100 double v
= (double)value
/ divisor
;
103 if (v
== (double)value
)
104 return snprintf(sp
, size
, fmt_round
, (uint
)value
);
106 return snprintf(sp
, size
, fmt_not_round
, v
);
109 /* Basic blocks (512) bytes are returned from quotactl */
110 #define BBS_TO_EXABYTES(bbs) ((uint64_t)(bbs)>>51)
111 #define BBS_TO_PETABYTES(bbs) ((uint64_t)(bbs)>>41)
112 #define BBS_TO_TERABYTES(bbs) ((uint64_t)(bbs)>>31)
113 #define BBS_TO_GIGABYTES(bbs) ((uint64_t)(bbs)>>21)
114 #define BBS_TO_MEGABYTES(bbs) ((uint64_t)(bbs)>>11)
115 #define BBS_TO_KILOBYTES(bbs) ((uint64_t)(bbs)>>1)
117 #define BBEXABYTE ((uint64_t)1<<51)
118 #define BBPETABYTE ((uint64_t)1<<41)
119 #define BBTERABYTE ((uint64_t)1<<31)
120 #define BBGIGABYTE ((uint64_t)1<<21)
121 #define BBMEGABYTE ((uint64_t)1<<11)
122 #define BBKILOBYTE ((uint64_t)1<< 1)
131 snprintf(sp
, size
, "%4u", (uint
)v
);
132 else if (BBS_TO_EXABYTES(v
))
133 round_snprintf(sp
, size
, "%3uE", "%3.1fE", v
, BBEXABYTE
);
134 else if (BBS_TO_PETABYTES(v
))
135 round_snprintf(sp
, size
, "%3uP", "%3.1fP", v
, BBPETABYTE
);
136 else if (BBS_TO_TERABYTES(v
))
137 round_snprintf(sp
, size
, "%3uT", "%3.1fT", v
, BBTERABYTE
);
138 else if (BBS_TO_GIGABYTES(v
))
139 round_snprintf(sp
, size
, "%3uG", "%3.1fG", v
, BBGIGABYTE
);
140 else if (BBS_TO_MEGABYTES(v
))
141 round_snprintf(sp
, size
, "%3uM", "%3.1fM", v
, BBMEGABYTE
);
142 else if (BBS_TO_KILOBYTES(v
))
143 round_snprintf(sp
, size
, "%3uK", "%3.1fK", v
, BBKILOBYTE
);
145 snprintf(sp
, size
, "%4u", (uint
)v
<< BBSHIFT
); /* bytes */
149 #define THOUSAND ((uint64_t)1000)
150 #define MILLION ((uint64_t)1000*1000)
151 #define BILLION ((uint64_t)1000*1000*1000)
152 #define TRILLION ((uint64_t)1000*1000*1000*1000)
153 #define GAZILLION ((uint64_t)1000*1000*1000*1000*1000)
154 #define RIDICULOUS ((uint64_t)1000*1000*1000*1000*1000*1000)
155 #define STOPALREADY ((uint64_t)1000*1000*1000*1000*1000*1000*1000)
164 snprintf(sp
, size
, "%4u", (uint
)v
);
165 else if (v
> STOPALREADY
)
166 round_snprintf(sp
, size
, "%3us", "%3.1fs", v
, STOPALREADY
);
167 else if (v
> RIDICULOUS
)
168 round_snprintf(sp
, size
, "%3ur", "%3.1fr", v
, RIDICULOUS
);
169 else if (v
> GAZILLION
)
170 round_snprintf(sp
, size
, "%3ug", "%3.1fg", v
, GAZILLION
);
171 else if (v
> TRILLION
)
172 round_snprintf(sp
, size
, "%3ut", "%3.1ft", v
, TRILLION
);
173 else if (v
> BILLION
)
174 round_snprintf(sp
, size
, "%3ub", "%3.1fb", v
, BILLION
);
175 else if (v
> MILLION
)
176 round_snprintf(sp
, size
, "%3um", "%3.1fm", v
, MILLION
);
177 else if (v
> THOUSAND
)
178 round_snprintf(sp
, size
, "%3uk", "%3.1fk", v
, THOUSAND
);
180 snprintf(sp
, size
, "%4u", (uint
)v
);
193 percent
= whole
? (uint
) (100.0 * portion
/ whole
+ 0.5) : 0;
194 if (snprintf(buf
, size
, "%3u", percent
) < 0)
205 _("Blocks"), _("Inodes"), _("Realtime Blocks") };
207 if (form
& XFS_BLOCK_QUOTA
)
209 if (form
& XFS_INODE_QUOTA
)
211 if (form
& XFS_RTBLOCK_QUOTA
)
220 char *types
[] = { _("User"), _("Group"), _("Project") };
222 if (type
& XFS_USER_QUOTA
)
224 if (type
& XFS_GROUP_QUOTA
)
226 if (type
& XFS_PROJ_QUOTA
)
233 * Identifier caches - user/group/project names/IDs
237 #define IDMASK (NID-1)
244 static idcache_t uidnc
[NID
];
245 static idcache_t gidnc
[NID
];
246 static idcache_t pidnc
[NID
];
247 static int uentriesleft
= NID
;
248 static int gentriesleft
= NID
;
249 static int pentriesleft
= NID
;
257 static idcache_t idc
;
260 if ((pw
= byid
? getpwuid(id
) : getpwent()) == NULL
)
263 strncpy(idc
.name
, pw
->pw_name
, NMAX
);
273 static idcache_t idc
;
275 if ((gr
= byid
? getgrgid(id
) : getgrent()) == NULL
)
278 strncpy(idc
.name
, gr
->gr_name
, NMAX
);
288 static idcache_t idc
;
290 if ((pr
= byid
? getprprid(id
) : getprent()) == NULL
)
292 idc
.id
= pr
->pr_prid
;
293 strncpy(idc
.name
, pr
->pr_name
, NMAX
);
301 idcache_t
*ncp
, *idp
;
303 /* Check cache for name first */
304 ncp
= &uidnc
[id
& IDMASK
];
305 if (ncp
->id
== id
&& ncp
->name
[0])
309 * Fill this cache while seaching for a name.
310 * This lets us run through the file serially.
312 if (uentriesleft
== NID
)
314 while (((idp
= getnextpwent(id
, 0)) != NULL
) && uentriesleft
) {
316 ncp
= &uidnc
[idp
->id
& IDMASK
];
317 if (ncp
->name
[0] == '\0' || idp
->id
== id
)
318 memcpy(ncp
, idp
, sizeof(idcache_t
));
324 ncp
= &uidnc
[id
& IDMASK
];
327 /* Not cached - do it the slow way & insert into cache */
328 if ((idp
= getnextpwent(id
, 1)) == NULL
)
330 memcpy(ncp
, idp
, sizeof(idcache_t
));
338 idcache_t
*ncp
, *idp
;
340 /* Check cache for name first */
341 ncp
= &gidnc
[id
& IDMASK
];
342 if (ncp
->id
== id
&& ncp
->name
[0])
346 * Fill this cache while seaching for a name.
347 * This lets us run through the file serially.
349 if (gentriesleft
== NID
)
351 while (((idp
= getnextgrent(id
, 0)) != NULL
) && gentriesleft
) {
353 ncp
= &gidnc
[idp
->id
& IDMASK
];
354 if (ncp
->name
[0] == '\0' || idp
->id
== id
)
355 memcpy(ncp
, idp
, sizeof(idcache_t
));
361 ncp
= &gidnc
[id
& IDMASK
];
364 /* Not cached - do it the slow way & insert into cache */
365 if ((idp
= getnextgrent(id
, 1)) == NULL
)
367 memcpy(ncp
, idp
, sizeof(idcache_t
));
375 idcache_t
*ncp
, *idp
;
377 /* Check cache for name first */
378 ncp
= &pidnc
[id
& IDMASK
];
379 if (ncp
->id
== id
&& ncp
->name
[0])
383 * Fill this cache while seaching for a name.
384 * This lets us run through the file serially.
386 if (pentriesleft
== NID
)
388 while (((idp
= getnextprent(id
, 0)) != NULL
) && pentriesleft
) {
390 ncp
= &pidnc
[idp
->id
& IDMASK
];
391 if (ncp
->name
[0] == '\0' || idp
->id
== id
)
392 memcpy(ncp
, idp
, sizeof(idcache_t
));
398 ncp
= &pidnc
[id
& IDMASK
];
401 /* Not cached - do it the slow way & insert into cache */
402 if ((idp
= getnextprent(id
, 1)) == NULL
)
404 memcpy(ncp
, idp
, sizeof(idcache_t
));
410 * Utility routine for opening an output file so that it can
411 * be "securely" written to (i.e. without vulnerability to a
414 * Returns NULL on failure, stdout on NULL input.
426 if ((fd
= open(fname
, O_CREAT
|O_WRONLY
|O_EXCL
, 0600)) < 0) {
428 fprintf(stderr
, _("%s: open on %s failed: %s\n"),
429 progname
, fname
, strerror(errno
));
432 if ((fp
= fdopen(fd
, "w")) == NULL
) {
434 fprintf(stderr
, _("%s: fdopen on %s failed: %s\n"),
435 progname
, fname
, strerror(errno
));