]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - quota/util.c
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2005 Silicon Graphics, Inc.
15 #define SECONDS_IN_A_DAY (24 * 60 * 60)
16 #define SECONDS_IN_A_HOUR (60 * 60)
17 #define SECONDS_IN_A_MINUTE (60)
24 static char timestamp
[32];
26 uint days
, hours
, minutes
, seconds
;
28 if (flags
& ABSOLUTE_FLAG
) {
32 timer
= max(origin
- now
, 0);
36 * If we are in verbose mode, or if less than a day remains, we
37 * will show "X days hh:mm:ss" so the user knows the exact timer status.
39 * Otherwise, we round down to the nearest day - so we add 30s here
40 * such that setting and reporting a limit in rapid succession will
41 * show the limit which was just set, rather than immediately reporting
44 if ((timer
> SECONDS_IN_A_DAY
) && !(flags
& VERBOSE_FLAG
))
45 timer
+= 30; /* seconds */
47 days
= timer
/ SECONDS_IN_A_DAY
;
49 timer
%= SECONDS_IN_A_DAY
;
50 hours
= timer
/ SECONDS_IN_A_HOUR
;
52 timer
%= SECONDS_IN_A_HOUR
;
53 minutes
= timer
/ SECONDS_IN_A_MINUTE
;
54 seconds
= timer
% SECONDS_IN_A_MINUTE
;
56 if (flags
& LIMIT_FLAG
) {
57 snprintf(timestamp
, sizeof(timestamp
), (flags
& HUMAN_FLAG
) ?
58 _("[-none-]") : _("[--none--]"));
59 } else if (origin
== 0) {
60 snprintf(timestamp
, sizeof(timestamp
), (flags
& HUMAN_FLAG
) ?
61 _("[------]") : _("[--------]"));
62 } else if ((hours
== 0 && minutes
== 0 && seconds
== 0) ||
63 (!(flags
& VERBOSE_FLAG
) && days
> 0)) {
64 snprintf(timestamp
, sizeof(timestamp
), "[%u %s]",
65 days
, days
== 1 ? _("day") : _("days"));
66 } else if (flags
& VERBOSE_FLAG
) {
67 snprintf(timestamp
, sizeof(timestamp
), "[%u %s %02u:%02u:%02u]",
68 days
, days
== 1 ? _("day") : _("days"),
69 hours
, minutes
, seconds
);
70 } else { /* non-verbose, less than a day remaining */
71 snprintf(timestamp
, sizeof(timestamp
),
72 (flags
& HUMAN_FLAG
) ?
73 "%02u:%02u:%02u" : "[%02u:%02u:%02u]",
74 hours
, minutes
, seconds
);
83 const char *fmt_round
,
84 const char *fmt_not_round
,
88 double v
= (double)value
/ divisor
;
91 if (v
== (double)value
)
92 return snprintf(sp
, size
, fmt_round
, (uint
)value
);
94 return snprintf(sp
, size
, fmt_not_round
, v
);
97 /* Basic blocks (512) bytes are returned from quotactl */
98 #define BBS_TO_EXABYTES(bbs) ((uint64_t)(bbs)>>51)
99 #define BBS_TO_PETABYTES(bbs) ((uint64_t)(bbs)>>41)
100 #define BBS_TO_TERABYTES(bbs) ((uint64_t)(bbs)>>31)
101 #define BBS_TO_GIGABYTES(bbs) ((uint64_t)(bbs)>>21)
102 #define BBS_TO_MEGABYTES(bbs) ((uint64_t)(bbs)>>11)
103 #define BBS_TO_KILOBYTES(bbs) ((uint64_t)(bbs)>>1)
105 #define BBEXABYTE ((uint64_t)1<<51)
106 #define BBPETABYTE ((uint64_t)1<<41)
107 #define BBTERABYTE ((uint64_t)1<<31)
108 #define BBGIGABYTE ((uint64_t)1<<21)
109 #define BBMEGABYTE ((uint64_t)1<<11)
110 #define BBKILOBYTE ((uint64_t)1<< 1)
119 snprintf(sp
, size
, "%4u", (uint
)v
);
120 else if (BBS_TO_EXABYTES(v
))
121 round_snprintf(sp
, size
, "%3uE", "%3.1fE", v
, BBEXABYTE
);
122 else if (BBS_TO_PETABYTES(v
))
123 round_snprintf(sp
, size
, "%3uP", "%3.1fP", v
, BBPETABYTE
);
124 else if (BBS_TO_TERABYTES(v
))
125 round_snprintf(sp
, size
, "%3uT", "%3.1fT", v
, BBTERABYTE
);
126 else if (BBS_TO_GIGABYTES(v
))
127 round_snprintf(sp
, size
, "%3uG", "%3.1fG", v
, BBGIGABYTE
);
128 else if (BBS_TO_MEGABYTES(v
))
129 round_snprintf(sp
, size
, "%3uM", "%3.1fM", v
, BBMEGABYTE
);
130 else if (BBS_TO_KILOBYTES(v
))
131 round_snprintf(sp
, size
, "%3uK", "%3.1fK", v
, BBKILOBYTE
);
133 snprintf(sp
, size
, "%4u", (uint
)v
<< BBSHIFT
); /* bytes */
137 #define THOUSAND ((uint64_t)1000)
138 #define MILLION ((uint64_t)1000*1000)
139 #define BILLION ((uint64_t)1000*1000*1000)
140 #define TRILLION ((uint64_t)1000*1000*1000*1000)
141 #define GAZILLION ((uint64_t)1000*1000*1000*1000*1000)
142 #define RIDICULOUS ((uint64_t)1000*1000*1000*1000*1000*1000)
143 #define STOPALREADY ((uint64_t)1000*1000*1000*1000*1000*1000*1000)
152 snprintf(sp
, size
, "%4u", (uint
)v
);
153 else if (v
> STOPALREADY
)
154 round_snprintf(sp
, size
, "%3us", "%3.1fs", v
, STOPALREADY
);
155 else if (v
> RIDICULOUS
)
156 round_snprintf(sp
, size
, "%3ur", "%3.1fr", v
, RIDICULOUS
);
157 else if (v
> GAZILLION
)
158 round_snprintf(sp
, size
, "%3ug", "%3.1fg", v
, GAZILLION
);
159 else if (v
> TRILLION
)
160 round_snprintf(sp
, size
, "%3ut", "%3.1ft", v
, TRILLION
);
161 else if (v
> BILLION
)
162 round_snprintf(sp
, size
, "%3ub", "%3.1fb", v
, BILLION
);
163 else if (v
> MILLION
)
164 round_snprintf(sp
, size
, "%3um", "%3.1fm", v
, MILLION
);
165 else if (v
> THOUSAND
)
166 round_snprintf(sp
, size
, "%3uk", "%3.1fk", v
, THOUSAND
);
168 snprintf(sp
, size
, "%4u", (uint
)v
);
181 percent
= whole
? (uint
) (100.0 * portion
/ whole
+ 0.5) : 0;
182 if (snprintf(buf
, size
, "%3u", percent
) < 0)
193 _("Blocks"), _("Inodes"), _("Realtime Blocks") };
195 if (form
& XFS_BLOCK_QUOTA
)
197 if (form
& XFS_INODE_QUOTA
)
199 if (form
& XFS_RTBLOCK_QUOTA
)
208 char *types
[] = { _("User"), _("Group"), _("Project") };
210 if (type
& XFS_USER_QUOTA
)
212 if (type
& XFS_GROUP_QUOTA
)
214 if (type
& XFS_PROJ_QUOTA
)
221 * Identifier caches - user/group/project names/IDs
225 #define IDMASK (NID-1)
232 static idcache_t uidnc
[NID
];
233 static idcache_t gidnc
[NID
];
234 static idcache_t pidnc
[NID
];
235 static int uentriesleft
= NID
;
236 static int gentriesleft
= NID
;
237 static int pentriesleft
= NID
;
245 static idcache_t idc
;
248 if ((pw
= byid
? getpwuid(id
) : getpwent()) == NULL
)
251 strncpy(idc
.name
, pw
->pw_name
, NMAX
);
261 static idcache_t idc
;
263 if ((gr
= byid
? getgrgid(id
) : getgrent()) == NULL
)
266 strncpy(idc
.name
, gr
->gr_name
, NMAX
);
276 static idcache_t idc
;
278 if ((pr
= byid
? getprprid(id
) : getprent()) == NULL
)
280 idc
.id
= pr
->pr_prid
;
281 strncpy(idc
.name
, pr
->pr_name
, NMAX
);
289 idcache_t
*ncp
, *idp
;
291 /* Check cache for name first */
292 ncp
= &uidnc
[id
& IDMASK
];
293 if (ncp
->id
== id
&& ncp
->name
[0])
297 * Fill this cache while seaching for a name.
298 * This lets us run through the file serially.
300 if (uentriesleft
== NID
)
302 while (((idp
= getnextpwent(id
, 0)) != NULL
) && uentriesleft
) {
304 ncp
= &uidnc
[idp
->id
& IDMASK
];
305 if (ncp
->name
[0] == '\0' || idp
->id
== id
)
306 memcpy(ncp
, idp
, sizeof(idcache_t
));
312 ncp
= &uidnc
[id
& IDMASK
];
315 /* Not cached - do it the slow way & insert into cache */
316 if ((idp
= getnextpwent(id
, 1)) == NULL
)
318 memcpy(ncp
, idp
, sizeof(idcache_t
));
326 idcache_t
*ncp
, *idp
;
328 /* Check cache for name first */
329 ncp
= &gidnc
[id
& IDMASK
];
330 if (ncp
->id
== id
&& ncp
->name
[0])
334 * Fill this cache while seaching for a name.
335 * This lets us run through the file serially.
337 if (gentriesleft
== NID
)
339 while (((idp
= getnextgrent(id
, 0)) != NULL
) && gentriesleft
) {
341 ncp
= &gidnc
[idp
->id
& IDMASK
];
342 if (ncp
->name
[0] == '\0' || idp
->id
== id
)
343 memcpy(ncp
, idp
, sizeof(idcache_t
));
349 ncp
= &gidnc
[id
& IDMASK
];
352 /* Not cached - do it the slow way & insert into cache */
353 if ((idp
= getnextgrent(id
, 1)) == NULL
)
355 memcpy(ncp
, idp
, sizeof(idcache_t
));
363 idcache_t
*ncp
, *idp
;
365 /* Check cache for name first */
366 ncp
= &pidnc
[id
& IDMASK
];
367 if (ncp
->id
== id
&& ncp
->name
[0])
371 * Fill this cache while seaching for a name.
372 * This lets us run through the file serially.
374 if (pentriesleft
== NID
)
376 while (((idp
= getnextprent(id
, 0)) != NULL
) && pentriesleft
) {
378 ncp
= &pidnc
[idp
->id
& IDMASK
];
379 if (ncp
->name
[0] == '\0' || idp
->id
== id
)
380 memcpy(ncp
, idp
, sizeof(idcache_t
));
386 ncp
= &pidnc
[id
& IDMASK
];
389 /* Not cached - do it the slow way & insert into cache */
390 if ((idp
= getnextprent(id
, 1)) == NULL
)
392 memcpy(ncp
, idp
, sizeof(idcache_t
));
398 * Utility routine for opening an output file so that it can
399 * be "securely" written to (i.e. without vulnerability to a
402 * Returns NULL on failure, stdout on NULL input.
414 if ((fd
= open(fname
, O_CREAT
|O_WRONLY
|O_EXCL
, 0600)) < 0) {
416 fprintf(stderr
, _("%s: open on %s failed: %s\n"),
417 progname
, fname
, strerror(errno
));
420 if ((fp
= fdopen(fd
, "w")) == NULL
) {
422 fprintf(stderr
, _("%s: fdopen on %s failed: %s\n"),
423 progname
, fname
, strerror(errno
));