]> granicus.if.org Git - strace/blob - tests/quotactl.h
Remove XLAT_END
[strace] / tests / quotactl.h
1 /*
2  * Common definitions for Linux and XFS quota tests.
3  *
4  * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@gmail.com>
5  * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
6  * Copyright (c) 2016-2018 The strace developers.
7  * All rights reserved.
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11
12 #ifndef STRACE_TESTS_QUOTACTL_H
13 # define STRACE_TESTS_QUOTACTL_H
14
15 # include <inttypes.h>
16 # include <stdarg.h>
17 # include <stdio.h>
18 # include "print_fields.h"
19
20 # ifdef HAVE_LINUX_QUOTA_H
21 /* Broken in CentOS 5: has extern spinlock_t dq_data_lock; declaration */
22 #  include <linux/quota.h>
23 # else
24 #  include <linux/types.h>
25 /* Broken in some new glibc versions: have Q_GETNEXTQUOTA definition but no
26  * struct nextdqblk defined. Fixed in glibc-2.24-106-g4d72808. */
27 #  include <sys/quota.h>
28 # endif
29
30 # ifndef QCMD_CMD
31 #  define QCMD_CMD(_val) ((unsigned) (_val) >> SUBCMDSHIFT)
32 # endif /* !QCMD_CMD */
33
34 # ifndef QCMD_TYPE
35 #  define QCMD_TYPE(_val) ((unsigned) (_val) & SUBCMDMASK)
36 # endif /* !QCMD_TYPE */
37
38 # ifndef PRJQUOTA
39 #  define PRJQUOTA 2
40 # endif
41
42 typedef void (*print_cb)(long rc, void *addr, void *arg);
43
44 enum check_quotactl_flag_bits {
45         CQF_ID_SKIP_BIT,
46         CQF_ID_STR_BIT,
47         CQF_ADDR_SKIP_BIT,
48         CQF_ADDR_STR_BIT,
49         CQF_ADDR_CB_BIT,
50 };
51
52 enum check_quotactl_flags {
53         CQF_NONE,
54         CQF_ID_SKIP   = 1 << CQF_ID_SKIP_BIT,
55         CQF_ID_STR    = 1 << CQF_ID_STR_BIT,
56         CQF_ADDR_SKIP = 1 << CQF_ADDR_SKIP_BIT,
57         CQF_ADDR_STR  = 1 << CQF_ADDR_STR_BIT,
58         CQF_ADDR_CB   = 1 << CQF_ADDR_CB_BIT,
59 };
60
61 static const char *errstr;
62
63 /**
64  * Generic quotactl syscall checker function.  Call convention:
65  *
66  *     check_quota(flags, cmd, cmd_str, special, special_str
67  *                 [, id [, id_str]]
68  *                 [, addr [, { addr_cb, addr_cb_arg | addr_str }]])
69  *
70  * check_quota performs a syscall invocation and prints the expected output
71  * for it.
72  *
73  * It might be useful to employ ARG_STR macro for passing cmd/cmd_str,
74  * special_special_str, id/id_str, and addr/addr_str argument pairs.
75  *
76  * @param flags Check flags:
77  *               - CQF_ID_SKIP: the "id" syscall argument is ignored
78  *                 in the syscall invocation.  No id and id_str arguments
79  *                 should be provided if this flag is set.
80  *                 This flag has priority over the CQF_ID_STR flag.
81  *               - CQF_ID_STR: the "id" syscall argument has a special string
82  *                 representation.  id_str argument should be provided if this
83  *                 flag is set; no id_str argument should be provided and id
84  *                 argument is printed as unsigned integer (with an exception
85  *                 for -1, which is printed as signed) if this flag is not set.
86  *               - CQF_ADDR_SKIP: the "addr" syscall argument is ignored
87  *                 in the syscall invocation.  None of the addr, addr_cb,
88  *                 addr_cb_arg, and/or addr_str arguments should be provided
89  *                 if this flag is set.  This flag has priority
90  *                 over the CQF_ADDR_STR and CQF_ADDR_CB flags.
91  *               - CQF_ADDR_CB: the "addr" syscall argument printing is handled
92  *                 via a callback function.  addr_cb (that points to a callback
93  *                 function of type print_cb) and addr_cb_arg (an opaque pointer
94  *                 that is passed to addr_cb in the third argument) should
95  *                 be provided if this flag is set.
96  *                 This flag has priority over the CQF_ADDR_STR flag.
97  *               - CQF_ADDR_STR: addr syscall argument has a special string
98  *                 representation.  addr_str argument should be provided if this
99  *                 flag is set.  If both CQF_ADDR_CB and CQF_ADDR_STR flags
100  *                 are not set, addr syscall argument is printed using "%p"
101  *                 printf format.
102  * @param cmd Value of the "cmd" syscall argument that should be passed
103  *            in the syscall invocation.
104  * @param cmd_str String representation of the "cmd" syscall argument.
105  * @param special Value of the "special" syscall argument that should be passed
106  *                in the syscall invocation.
107  * @param special_str String representation of the "special" syscall argument.
108  * @param ... Additional arguments depend on the flags being set:
109  *             - id: Value of the "id" syscall argument.  Provided
110  *               if CQF_ID_SKIP is not set, otherwise -1 is passed
111  *               in the syscall invocation and the argument is not printed
112  *               in the expected output.
113  *             - id_str: String representation of the "id" syscall argument.
114  *               Provided if CQF_ID_SKIP is not set and CQF_ID_STR is set.
115  *             - addr: Value of the "addr" syscall argument.  Provided
116  *               if CQF_ADDR_SKIP is not set, otherwise NULL is passed
117  *               in the syscall invocation and the argument is not printed
118  *               in the expected output.
119  *             - addr_cb: Callback function that is called for the "addr"
120  *               syscall argument printing. Should be of print_cb type.
121  *               Provided if CQF_ADDR_SKIP is not set and CQF_ADDR_CB is set.
122  *             - addr_cb_arg: Opaque pointer that is passed to addr_cb,
123  *               Provided if CQF_ADDR_SKIP is not set and CQF_ADDR_CB is set.
124  *             - addr_str: String representation of the "addr" syscall argument.
125  *               Provided if CQF_ADDR_SKIP is not set, CQF_ADDR_CB is not set,
126  *               and CQF_ADDR_STR is set.
127  */
128 static inline void
129 check_quota(uint32_t flags, int cmd, const char *cmd_str,
130         const char *special, const char *special_str, ...)
131 {
132         long rc;
133         const char *addr_str = NULL;
134         const char *id_str = NULL;
135         void *addr = NULL;
136         print_cb addr_cb = NULL;
137         void *addr_cb_arg = NULL;
138         uint32_t id = -1;
139
140         va_list ap;
141
142         va_start(ap, special_str);
143
144         if (!(flags & CQF_ID_SKIP)) {
145                 id = va_arg(ap, uint32_t);
146
147                 if (flags & CQF_ID_STR)
148                         id_str = va_arg(ap, const char *);
149         }
150
151         if (!(flags & CQF_ADDR_SKIP)) {
152                 addr = va_arg(ap, void *);
153
154                 if (flags & CQF_ADDR_CB) {
155                         addr_cb = va_arg(ap, print_cb);
156                         addr_cb_arg = va_arg(ap, void *);
157                 } else if (flags & CQF_ADDR_STR) {
158                         addr_str = va_arg(ap, const char *);
159                 }
160         }
161
162         va_end(ap);
163
164         rc = syscall(__NR_quotactl, cmd, special, id, addr);
165
166         errstr = sprintrc(rc);
167
168 # ifdef INJECT_RETVAL
169         if (rc != INJECT_RETVAL)
170                 error_msg_and_fail("Got a return value of %ld != %d",
171                                    rc, INJECT_RETVAL);
172
173         static char inj_errstr[4096];
174
175         snprintf(inj_errstr, sizeof(inj_errstr), "%s (INJECTED)", errstr);
176         errstr = inj_errstr;
177 # endif
178
179         printf("quotactl(%s, %s", cmd_str, special_str);
180
181         if (!(flags & CQF_ID_SKIP)) {
182                 if (flags & CQF_ID_STR) {
183                         printf(", %s", id_str);
184                 } else {
185                         if (id == (uint32_t)-1)
186                                 printf(", -1");
187                         else
188                                 printf(", %u", id);
189                 }
190         }
191
192         if (!(flags & CQF_ADDR_SKIP)) {
193                 if (flags & CQF_ADDR_CB) {
194                         printf(", ");
195                         addr_cb(rc, addr, addr_cb_arg);
196                 } else if (flags & CQF_ADDR_STR) {
197                         printf(", %s", addr_str);
198                 } else {
199                         printf(", %p", addr);
200                 }
201         }
202
203         printf(") = %s\n", errstr);
204 }
205
206
207 static const int bogus_cmd = 0xbadc0ded;
208 static const int bogus_id = 0xca7faced;
209
210 /* It is invalid anyway due to the slash in the end */
211 static const char *bogus_dev = "/dev/bogus/";
212 static const char *bogus_dev_str = "\"/dev/bogus/\"";
213
214 static const char unterminated_data[] = { '\1', '\2', '\3' };
215
216 #endif /* !STRACE_TESTS_QUOTACTL_H */