xfs/{019, 031}: make sure we don't set rtinherit=1 on mkfs
[xfstests-dev.git] / src / test-nextquota.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2016 Red Hat, Inc.
4  * All Rights Reserved.
5  */
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <sys/quota.h>
10 #include <sys/types.h>
11 #include <xfs/xqm.h>
12
13 /*
14  * Exercise the Q_GETNEXTQUOTA and Q_XGETNEXTQUOTA quotactls.
15  * Really only returns a bare minimum of quota information,
16  * just enough to be sure we got a sane answer back.
17  *
18  * These quotactls take a quota ID as input, and return the
19  * next active quota >= that ID.
20  *
21  * usage:
22  *      test-nextquota [-v] -[u|g|p] -i id -d device
23  */
24
25 #ifndef PRJQUOTA
26 #define PRJQUOTA 2
27 #endif
28
29 #ifndef Q_GETNEXTQUOTA
30 #define Q_GETNEXTQUOTA 0x800009        /* get disk limits and usage >= ID */
31 #endif
32
33 /* glibc 2.24 defines Q_GETNEXTQUOTA but not struct nextdqblk. */
34 struct test_nextdqblk
35   {
36     u_int64_t dqb_bhardlimit;   /* absolute limit on disk quota blocks alloc */
37     u_int64_t dqb_bsoftlimit;   /* preferred limit on disk quota blocks */
38     u_int64_t dqb_curspace;     /* current quota block count */
39     u_int64_t dqb_ihardlimit;   /* maximum # allocated inodes */
40     u_int64_t dqb_isoftlimit;   /* preferred inode limit */
41     u_int64_t dqb_curinodes;    /* current # allocated inodes */
42     u_int64_t dqb_btime;        /* time limit for excessive disk use */
43     u_int64_t dqb_itime;        /* time limit for excessive files */
44     u_int32_t dqb_valid;        /* bitmask of QIF_* constants */
45     u_int32_t dqb_id;           /* id for this quota info*/
46   };
47
48 #ifndef Q_XGETNEXTQUOTA
49 #define Q_XGETNEXTQUOTA XQM_CMD(9)
50 #endif
51
52 void usage(char *progname)
53 {
54         printf("usage: %s [-v] -[u|g|p] -i id -d device\n", progname);
55         exit(1);
56 }
57
58 int main(int argc, char *argv[])
59 {
60         int c;
61         int cmd;
62         int type = -1, typeflag = 0;
63         int verbose = 0;
64         int retval = 0;
65         uint id = 0, idflag = 0;
66         char *device = NULL;
67         char *tmp;
68         struct test_nextdqblk dqb;
69         struct fs_disk_quota xqb;
70
71         while ((c = getopt(argc,argv,"ugpi:d:v")) != EOF) {
72                 switch (c) {
73                 case 'u':
74                         type = USRQUOTA;
75                         typeflag++;
76                         break;
77                 case 'g':
78                         type = GRPQUOTA;
79                         typeflag++;
80                         break;
81                 case 'p':
82                         type = PRJQUOTA;
83                         typeflag++;
84                         break;
85                 case 'i':
86                         id = (uint) strtoul(optarg, &tmp, 0);
87                         if (*tmp) {
88                                 fprintf(stderr, "Bad id: %s\n", optarg);
89                                 exit(1);
90                         }
91                         idflag++;
92                         break;
93                 case 'd':
94                         device = optarg;
95                         break;
96                 case 'v':
97                         verbose++;
98                         break;
99                 default:
100                         usage(argv[0]);
101                 }
102         }
103
104         if (idflag == 0) {
105                 printf("No id specified\n");
106                 usage(argv[0]);
107         }
108         if (typeflag == 0) {
109                 printf("No type specified\n");
110                 usage(argv[0]);
111         }
112         if (typeflag > 1) {
113                 printf("Multiple types specified\n");
114                 usage(argv[0]);
115         }
116         if (device == NULL) {
117                 printf("No device specified\n");
118                 usage(argv[0]);
119         }
120
121         if (verbose)
122                 printf("asking for quota type %d for id %u on %s\n", type, id, device);
123
124         memset(&dqb, 0, sizeof(struct test_nextdqblk));
125         memset(&xqb, 0, sizeof(struct fs_disk_quota));
126
127         if (verbose)
128                 printf("====Q_GETNEXTQUOTA====\n");
129         cmd = QCMD(Q_GETNEXTQUOTA, type);
130         if (quotactl(cmd, device, id, (void *)&dqb) < 0) {
131                 perror("Q_GETNEXTQUOTA");
132                 retval = 1;
133         } else {
134                 /*
135                  * We only print id and inode limits because
136                  * block count varies depending on fs block size, etc;
137                  * this is just a sanity test that we can retrieve the quota,
138                  * and inode limits have the same units across both calls.
139                  */
140                 printf("id        %u\n", dqb.dqb_id);
141                 printf("ihard     %llu\n",
142                                   (unsigned long long)dqb.dqb_ihardlimit);
143                 printf("isoft     %llu\n",
144                                   (unsigned long long)dqb.dqb_isoftlimit);
145         }
146
147         if (verbose)
148                 printf("====Q_XGETNEXTQUOTA====\n");
149         cmd = QCMD(Q_XGETNEXTQUOTA, USRQUOTA);
150         if (quotactl(cmd, device, id, (void *)&xqb) < 0) {
151                 perror("Q_XGETNEXTQUOTA");
152                 retval = 1;
153         } else {
154                 printf("id        %u\n", xqb.d_id);
155                 printf("ihard     %llu\n", xqb.d_ino_hardlimit);
156                 printf("isoft     %llu\n", xqb.d_ino_softlimit);
157         }
158
159         return retval;
160 }