]> granicus.if.org Git - strace/blob - tests/quotactl-xfs.c
Remove XLAT_END
[strace] / tests / quotactl-xfs.c
1 /*
2  * Check decoding of quotactl xfs subcommands.
3  *
4  * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@gmail.com>
5  * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
6  * Copyright (c) 2016-2019 The strace developers.
7  * All rights reserved.
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11
12 #include "tests.h"
13
14 #include "scno.h"
15
16 #if defined(__NR_quotactl) && \
17         (defined(HAVE_LINUX_QUOTA_H) || defined(HAVE_SYS_QUOTA_H)) && \
18         defined(HAVE_LINUX_DQBLK_XFS_H)
19
20 # include <stdio.h>
21 # include <string.h>
22 # include <unistd.h>
23
24 # include <linux/dqblk_xfs.h>
25
26 # include "quotactl.h"
27
28 # ifndef Q_GETNEXTQUOTA
29 #  define Q_XGETNEXTQUOTA       XQM_CMD(0x9)
30 # endif /* !Q_GETNEXTQUOTA */
31
32 # ifndef Q_XGETQSTATV
33
34 #  define Q_XGETQSTATV          XQM_CMD(8)
35 #  define FS_QSTATV_VERSION1    1
36
37 struct fs_qfilestatv {
38         uint64_t        qfs_ino;        /* inode number */
39         uint64_t        qfs_nblks;      /* number of BBs 512-byte-blks */
40         uint32_t        qfs_nextents;   /* number of extents */
41         uint32_t        qfs_pad;        /* pad for 8-byte alignment */
42 };
43
44 struct fs_quota_statv {
45         int8_t          qs_version;             /* version for future changes */
46         uint8_t         qs_pad1;                /* pad for 16bit alignment */
47         uint16_t        qs_flags;               /* XFS_QUOTA_.* flags */
48         uint32_t        qs_incoredqs;           /* number of dquots incore */
49         struct fs_qfilestatv    qs_uquota;      /* user quota information */
50         struct fs_qfilestatv    qs_gquota;      /* group quota information */
51         struct fs_qfilestatv    qs_pquota;      /* project quota information */
52         int32_t         qs_btimelimit;          /* limit for blks timer */
53         int32_t         qs_itimelimit;          /* limit for inodes timer */
54         int32_t         qs_rtbtimelimit;        /* limit for rt blks timer */
55         uint16_t        qs_bwarnlimit;          /* limit for num warnings */
56         uint16_t        qs_iwarnlimit;          /* limit for num warnings */
57         uint64_t        qs_pad2[8];             /* for future proofing */
58 };
59
60 # endif /* !Q_XGETQSTATV */
61
62 # include "xlat.h"
63 # include "xlat/xfs_dqblk_flags.h"
64 # if VERBOSE
65 #  include "xlat/xfs_quota_flags.h"
66 # endif
67
68
69 void
70 print_xdisk_quota(int rc, void *ptr, void *arg)
71 {
72         struct fs_disk_quota *dq = ptr;
73         long out_arg = (long) arg;
74
75         if (((rc < 0) && out_arg) || (out_arg > 1)) {
76                 printf("%p", dq);
77                 return;
78         }
79
80         PRINT_FIELD_D("{", *dq, d_version);
81         printf(", d_flags=");
82         printflags(xfs_dqblk_flags, (uint8_t) dq->d_flags, "XFS_???_QUOTA");
83
84         PRINT_FIELD_X(", ", *dq, d_fieldmask);
85         PRINT_FIELD_U(", ", *dq, d_id);
86         PRINT_FIELD_U(", ", *dq, d_blk_hardlimit);
87         PRINT_FIELD_U(", ", *dq, d_blk_softlimit);
88         PRINT_FIELD_U(", ", *dq, d_ino_hardlimit);
89         PRINT_FIELD_U(", ", *dq, d_ino_softlimit);
90         PRINT_FIELD_U(", ", *dq, d_bcount);
91         PRINT_FIELD_U(", ", *dq, d_icount);
92
93 # if VERBOSE
94         PRINT_FIELD_D(", ", *dq, d_itimer);
95         PRINT_FIELD_D(", ", *dq, d_btimer);
96         PRINT_FIELD_U(", ", *dq, d_iwarns);
97         PRINT_FIELD_U(", ", *dq, d_bwarns);
98         PRINT_FIELD_U(", ", *dq, d_rtb_hardlimit);
99         PRINT_FIELD_U(", ", *dq, d_rtb_softlimit);
100         PRINT_FIELD_U(", ", *dq, d_rtbcount);
101         PRINT_FIELD_D(", ", *dq, d_rtbtimer);
102         PRINT_FIELD_U(", ", *dq, d_rtbwarns);
103 # else
104         printf(", ...");
105 # endif /* !VERBOSE */
106         printf("}");
107 }
108
109 void
110 print_xquota_stat(int rc, void *ptr, void *arg)
111 {
112         struct fs_quota_stat *qs = ptr;
113         long out_arg = (long) arg;
114
115         if (((rc < 0) && out_arg) || (out_arg > 1)) {
116                 printf("%p", qs);
117                 return;
118         }
119
120         PRINT_FIELD_D("{", *qs, qs_version);
121
122 # if VERBOSE
123         printf(", qs_flags=");
124         printflags(xfs_quota_flags, qs->qs_flags, "XFS_QUOTA_???");
125         PRINT_FIELD_U(", qs_uquota={", qs->qs_uquota, qfs_ino);
126         PRINT_FIELD_U(", ", qs->qs_uquota, qfs_nblks);
127         PRINT_FIELD_U(", ", qs->qs_uquota, qfs_nextents);
128         PRINT_FIELD_U("}, qs_gquota={", qs->qs_gquota, qfs_ino);
129         PRINT_FIELD_U(", ", qs->qs_gquota, qfs_nblks);
130         PRINT_FIELD_U(", ", qs->qs_gquota, qfs_nextents);
131         PRINT_FIELD_U("}, ", *qs, qs_incoredqs);
132         PRINT_FIELD_D(", ", *qs, qs_btimelimit);
133         PRINT_FIELD_D(", ", *qs, qs_itimelimit);
134         PRINT_FIELD_D(", ", *qs, qs_rtbtimelimit);
135         PRINT_FIELD_U(", ", *qs, qs_bwarnlimit);
136         PRINT_FIELD_U(", ", *qs, qs_iwarnlimit);
137 # else
138         printf(", ...");
139 # endif /* !VERBOSE */
140         printf("}");
141 }
142
143 void
144 print_xquota_statv(int rc, void *ptr, void *arg)
145 {
146         struct fs_quota_statv *qs = ptr;
147         long out_arg = (long) arg;
148
149         if (((rc < 0) && out_arg) || (out_arg > 1)) {
150                 printf("%p", qs);
151                 return;
152         }
153
154         PRINT_FIELD_D("{", *qs, qs_version);
155
156 # if VERBOSE
157         printf(", qs_flags=");
158         printflags(xfs_quota_flags, qs->qs_flags, "XFS_QUOTA_???");
159         PRINT_FIELD_U(", ", *qs, qs_incoredqs);
160         PRINT_FIELD_U(", qs_uquota={", qs->qs_uquota, qfs_ino);
161         PRINT_FIELD_U(", ", qs->qs_uquota, qfs_nblks);
162         PRINT_FIELD_U(", ", qs->qs_uquota, qfs_nextents);
163         PRINT_FIELD_U("}, qs_gquota={", qs->qs_gquota, qfs_ino);
164         PRINT_FIELD_U(", ", qs->qs_gquota, qfs_nblks);
165         PRINT_FIELD_U(", ", qs->qs_gquota, qfs_nextents);
166         PRINT_FIELD_U("}, qs_pquota={", qs->qs_pquota, qfs_ino);
167         PRINT_FIELD_U(", ", qs->qs_pquota, qfs_nblks);
168         PRINT_FIELD_U(", ", qs->qs_pquota, qfs_nextents);
169         PRINT_FIELD_D("}, ", *qs, qs_btimelimit);
170         PRINT_FIELD_D(", ", *qs, qs_itimelimit);
171         PRINT_FIELD_D(", ", *qs, qs_rtbtimelimit);
172         PRINT_FIELD_U(", ", *qs, qs_bwarnlimit);
173         PRINT_FIELD_U(", ", *qs, qs_iwarnlimit);
174 # else
175         printf(", ...");
176 # endif /* !VERBOSE */
177         printf("}");
178 }
179
180 int
181 main(void)
182 {
183         char *bogus_special = (char *) tail_alloc(1) + 1;
184         void *bogus_addr = (char *) tail_alloc(1) + 1;
185
186         char bogus_special_str[sizeof(void *) * 2 + sizeof("0x")];
187         char bogus_addr_str[sizeof(void *) * 2 + sizeof("0x")];
188         char unterminated_str[sizeof(void *) * 2 + sizeof("0x")];
189
190         static char invalid_cmd_str[1024];
191         TAIL_ALLOC_OBJECT_CONST_PTR(struct fs_disk_quota, xdq);
192         TAIL_ALLOC_OBJECT_CONST_PTR(struct fs_quota_stat, xqstat);
193         TAIL_ALLOC_OBJECT_CONST_PTR(struct fs_quota_statv, xqstatv);
194         TAIL_ALLOC_OBJECT_CONST_PTR(uint32_t, flags);
195         char *unterminated = tail_memdup(unterminated_data,
196                                          sizeof(unterminated_data));
197
198         snprintf(bogus_special_str, sizeof(bogus_special_str), "%p",
199                  bogus_special);
200         snprintf(bogus_addr_str, sizeof(bogus_addr_str), "%p",
201                  bogus_addr);
202         snprintf(unterminated_str, sizeof(unterminated_str), "%p",
203                  unterminated);
204
205
206         /* Q_XQUOTAON */
207
208         *flags = 0xdeadbeef;
209
210         check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
211                     ARG_STR(QCMD(Q_XQUOTAON, USRQUOTA)),
212                     ARG_STR("/dev/bogus/"), flags,
213                     "[XFS_QUOTA_UDQ_ACCT|XFS_QUOTA_UDQ_ENFD"
214                     "|XFS_QUOTA_GDQ_ACCT|XFS_QUOTA_GDQ_ENFD"
215                     "|XFS_QUOTA_PDQ_ENFD|0xdeadbec0]");
216
217         snprintf(invalid_cmd_str, sizeof(invalid_cmd_str),
218                  "QCMD(Q_XQUOTAON, %#x /* ???QUOTA */)",
219                  QCMD_TYPE(QCMD(Q_XQUOTAON, 0xfacefeed)));
220         check_quota(CQF_ID_SKIP,
221                     QCMD(Q_XQUOTAON, 0xfacefeed), invalid_cmd_str,
222                     bogus_dev, bogus_dev_str, bogus_addr);
223
224
225         /* Q_XQUOTAOFF */
226
227         check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
228                     ARG_STR(QCMD(Q_XQUOTAOFF, USRQUOTA)),
229                     bogus_special, bogus_special_str,
230                     bogus_addr, bogus_addr_str);
231         check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
232                     ARG_STR(QCMD(Q_XQUOTAOFF, GRPQUOTA)),
233                     ARG_STR("/dev/bogus/"),
234                     ARG_STR(NULL));
235         check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
236                     QCMD(Q_XQUOTAOFF, 3),
237                     "QCMD(Q_XQUOTAOFF, 0x3 /* ???QUOTA */)",
238                     ARG_STR("/dev/bogus/"), flags,
239                     "[XFS_QUOTA_UDQ_ACCT|XFS_QUOTA_UDQ_ENFD"
240                     "|XFS_QUOTA_GDQ_ACCT|XFS_QUOTA_GDQ_ENFD"
241                     "|XFS_QUOTA_PDQ_ENFD|0xdeadbec0]");
242
243
244         /* Q_XGETQUOTA */
245
246         /* Trying our best to get successful result */
247         check_quota(CQF_ADDR_CB, ARG_STR(QCMD(Q_XGETQUOTA, USRQUOTA)),
248                     ARG_STR("/dev/sda1"), getuid(), xdq, print_xdisk_quota,
249                     (intptr_t) 1);
250
251         check_quota(CQF_ADDR_CB, ARG_STR(QCMD(Q_XGETQUOTA, GRPQUOTA)),
252                     ARG_STR(NULL), -1, xdq, print_xdisk_quota, (intptr_t) 1);
253
254
255         /* Q_XGETNEXTQUOTA */
256
257         check_quota(CQF_ADDR_CB, ARG_STR(QCMD(Q_XGETNEXTQUOTA, USRQUOTA)),
258                     ARG_STR("/dev/sda1"), 0, xdq, print_xdisk_quota,
259                     (intptr_t) 1);
260
261
262         /* Q_XSETQLIM */
263
264         check_quota(CQF_NONE, ARG_STR(QCMD(Q_XSETQLIM, PRJQUOTA)),
265                     bogus_special, bogus_special_str, 0, bogus_addr);
266
267         fill_memory_ex(xdq, sizeof(*xdq), 0x8e, 0x80);
268
269         check_quota(CQF_ADDR_CB, ARG_STR(QCMD(Q_XSETQLIM, PRJQUOTA)),
270                     bogus_dev, bogus_dev_str, 3141592653U,
271                     xdq, print_xdisk_quota, (intptr_t) 0);
272
273
274         /* Q_XGETQSTAT */
275
276         check_quota(CQF_ID_SKIP | CQF_ADDR_CB,
277                     ARG_STR(QCMD(Q_XGETQSTAT, USRQUOTA)),
278                     ARG_STR("/dev/sda1"), xqstat, print_xquota_stat, (intptr_t) 1);
279
280         check_quota(CQF_ID_SKIP | CQF_ADDR_CB,
281                     ARG_STR(QCMD(Q_XGETQSTAT, USRQUOTA)),
282                     ARG_STR("NULL"), xqstat, print_xquota_stat, (intptr_t) 1);
283
284         check_quota(CQF_ID_SKIP,
285                     ARG_STR(QCMD(Q_XGETQSTAT, PRJQUOTA)),
286                     unterminated, unterminated_str,
287                     xqstat + 1);
288
289
290         /* Q_XGETQSTATV */
291
292         check_quota(CQF_ID_SKIP | CQF_ADDR_CB,
293                     ARG_STR(QCMD(Q_XGETQSTATV, USRQUOTA)),
294                     ARG_STR("/dev/sda1"), xqstatv, print_xquota_statv, (intptr_t) 1);
295
296         check_quota(CQF_ID_SKIP | CQF_ADDR_CB,
297                     ARG_STR(QCMD(Q_XGETQSTATV, GRPQUOTA)),
298                     ARG_STR(NULL), xqstatv, print_xquota_statv, (intptr_t) 1);
299
300         check_quota(CQF_ID_SKIP,
301                     ARG_STR(QCMD(Q_XGETQSTATV, PRJQUOTA)),
302                     unterminated, unterminated_str,
303                     xqstatv + 1);
304
305
306         /* Q_XQUOTARM */
307
308         check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
309                     ARG_STR(QCMD(Q_XQUOTARM, PRJQUOTA)),
310                     bogus_special, bogus_special_str, ARG_STR(NULL));
311         check_quota(CQF_ID_SKIP,
312                     ARG_STR(QCMD(Q_XQUOTARM, USRQUOTA)),
313                     unterminated, unterminated_str, flags + 1);
314
315         *flags = 0xdeadbeef;
316         check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
317                     ARG_STR(QCMD(Q_XQUOTARM, GRPQUOTA)),
318                     ARG_STR(NULL), flags,
319                     "[XFS_USER_QUOTA|XFS_PROJ_QUOTA"
320                     "|XFS_GROUP_QUOTA|0xdeadbee8]");
321
322
323         /* Q_XQUOTASYNC */
324
325         check_quota(CQF_ID_SKIP | CQF_ADDR_SKIP,
326                     ARG_STR(QCMD(Q_XQUOTASYNC, USRQUOTA)),
327                     bogus_special, bogus_special_str);
328         check_quota(CQF_ID_SKIP | CQF_ADDR_SKIP,
329                     QCMD(Q_XQUOTASYNC, 0xfff),
330                     "QCMD(Q_XQUOTASYNC, 0xff /* ???QUOTA */)",
331                     ARG_STR(NULL));
332
333         puts("+++ exited with 0 +++");
334
335         return 0;
336 }
337
338 #else
339
340 SKIP_MAIN_UNDEFINED("__NR_quotactl && "
341         "(HAVE_LINUX_QUOTA_H || HAVE_SYS_QUOTA_H) && "
342         "HAVE_LINUX_DQBLK_XFS_H");
343
344 #endif