2 * Copyright (c) 2016 Red Hat, 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
21 #include <sys/quota.h>
22 #include <sys/types.h>
26 * Exercise the Q_GETNEXTQUOTA and Q_XGETNEXTQUOTA quotactls.
27 * Really only returns a bare minimum of quota information,
28 * just enough to be sure we got a sane answer back.
30 * These quotactls take a quota ID as input, and return the
31 * next active quota >= that ID.
34 * test-nextquota [-v] -[u|g|p] -i id -d device
41 #ifndef Q_GETNEXTQUOTA
42 #define Q_GETNEXTQUOTA 0x800009 /* get disk limits and usage >= ID */
45 /* glibc 2.24 defines Q_GETNEXTQUOTA but not struct nextdqblk. */
48 u_int64_t dqb_bhardlimit; /* absolute limit on disk quota blocks alloc */
49 u_int64_t dqb_bsoftlimit; /* preferred limit on disk quota blocks */
50 u_int64_t dqb_curspace; /* current quota block count */
51 u_int64_t dqb_ihardlimit; /* maximum # allocated inodes */
52 u_int64_t dqb_isoftlimit; /* preferred inode limit */
53 u_int64_t dqb_curinodes; /* current # allocated inodes */
54 u_int64_t dqb_btime; /* time limit for excessive disk use */
55 u_int64_t dqb_itime; /* time limit for excessive files */
56 u_int32_t dqb_valid; /* bitmask of QIF_* constants */
57 u_int32_t dqb_id; /* id for this quota info*/
60 #ifndef Q_XGETNEXTQUOTA
61 #define Q_XGETNEXTQUOTA XQM_CMD(9)
64 void usage(char *progname)
66 printf("usage: %s [-v] -[u|g|p] -i id -d device\n", progname);
70 int main(int argc, char *argv[])
74 int type = -1, typeflag = 0;
77 uint id = 0, idflag = 0;
80 struct test_nextdqblk dqb;
81 struct fs_disk_quota xqb;
83 while ((c = getopt(argc,argv,"ugpi:d:v")) != EOF) {
98 id = (uint) strtoul(optarg, &tmp, 0);
100 fprintf(stderr, "Bad id: %s\n", optarg);
117 printf("No id specified\n");
121 printf("No type specified\n");
125 printf("Multiple types specified\n");
128 if (device == NULL) {
129 printf("No device specified\n");
134 printf("asking for quota type %d for id %u on %s\n", type, id, device);
136 memset(&dqb, 0, sizeof(struct test_nextdqblk));
137 memset(&xqb, 0, sizeof(struct fs_disk_quota));
140 printf("====Q_GETNEXTQUOTA====\n");
141 cmd = QCMD(Q_GETNEXTQUOTA, type);
142 if (quotactl(cmd, device, id, (void *)&dqb) < 0) {
143 perror("Q_GETNEXTQUOTA");
147 * We only print id and inode limits because
148 * block count varies depending on fs block size, etc;
149 * this is just a sanity test that we can retrieve the quota,
150 * and inode limits have the same units across both calls.
152 printf("id %u\n", dqb.dqb_id);
153 printf("ihard %llu\n",
154 (unsigned long long)dqb.dqb_ihardlimit);
155 printf("isoft %llu\n",
156 (unsigned long long)dqb.dqb_isoftlimit);
160 printf("====Q_XGETNEXTQUOTA====\n");
161 cmd = QCMD(Q_XGETNEXTQUOTA, USRQUOTA);
162 if (quotactl(cmd, device, id, (void *)&xqb) < 0) {
163 perror("Q_XGETNEXTQUOTA");
166 printf("id %u\n", xqb.d_id);
167 printf("ihard %llu\n", xqb.d_ino_hardlimit);
168 printf("isoft %llu\n", xqb.d_ino_softlimit);