]> granicus.if.org Git - strace/blob - quota.c
Fix decoding of arm struct stat64 by aarch64 strace.
[strace] / quota.c
1 /*
2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5  * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6  * Copyright (c) 2005, 2006 Dmitry V. Levin <ldv@altlinux.org>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "defs.h"
33
34 #define SUBCMDMASK  0x00ff
35 #define SUBCMDSHIFT 8
36 #define QCMD_CMD(cmd)   ((u_int32_t)(cmd) >> SUBCMDSHIFT)
37 #define QCMD_TYPE(cmd)  ((u_int32_t)(cmd) & SUBCMDMASK)
38
39 #define OLD_CMD(cmd)    ((u_int32_t)(cmd) << 8)
40 #define NEW_CMD(cmd)    ((u_int32_t)(cmd) | 0x800000)
41 #define XQM_CMD(cmd)    ((u_int32_t)(cmd) | ('X'<<8))
42
43 #define Q_V1_QUOTAON    OLD_CMD(0x1)
44 #define Q_V1_QUOTAOFF   OLD_CMD(0x2)
45 #define Q_V1_GETQUOTA   OLD_CMD(0x3)
46 #define Q_V1_SETQUOTA   OLD_CMD(0x4)
47 #define Q_V1_SETUSE     OLD_CMD(0x5)
48 #define Q_V1_SYNC       OLD_CMD(0x6)
49 #define Q_SETQLIM       OLD_CMD(0x7)
50 #define Q_V1_GETSTATS   OLD_CMD(0x8)
51 #define Q_V1_RSQUASH    OLD_CMD(0x10)
52
53 #define Q_V2_GETQUOTA   OLD_CMD(0xD)
54 #define Q_V2_SETQUOTA   OLD_CMD(0xE)
55 #define Q_V2_SETUSE     OLD_CMD(0xF)
56 #define Q_V2_GETINFO    OLD_CMD(0x9)
57 #define Q_V2_SETINFO    OLD_CMD(0xA)
58 #define Q_V2_SETGRACE   OLD_CMD(0xB)
59 #define Q_V2_SETFLAGS   OLD_CMD(0xC)
60 #define Q_V2_GETSTATS   OLD_CMD(0x11)
61
62 #define Q_SYNC          NEW_CMD(0x1)
63 #define Q_QUOTAON       NEW_CMD(0x2)
64 #define Q_QUOTAOFF      NEW_CMD(0x3)
65 #define Q_GETFMT        NEW_CMD(0x4)
66 #define Q_GETINFO       NEW_CMD(0x5)
67 #define Q_SETINFO       NEW_CMD(0x6)
68 #define Q_GETQUOTA      NEW_CMD(0x7)
69 #define Q_SETQUOTA      NEW_CMD(0x8)
70
71 #define Q_XQUOTAON      XQM_CMD(0x1)
72 #define Q_XQUOTAOFF     XQM_CMD(0x2)
73 #define Q_XGETQUOTA     XQM_CMD(0x3)
74 #define Q_XSETQLIM      XQM_CMD(0x4)
75 #define Q_XGETQSTAT     XQM_CMD(0x5)
76 #define Q_XQUOTARM      XQM_CMD(0x6)
77 #define Q_XQUOTASYNC    XQM_CMD(0x7)
78
79 static const struct xlat quotacmds[] = {
80         XLAT(Q_V1_QUOTAON),
81         XLAT(Q_V1_QUOTAOFF),
82         XLAT(Q_V1_GETQUOTA),
83         XLAT(Q_V1_SETQUOTA),
84         XLAT(Q_V1_SETUSE),
85         XLAT(Q_V1_SYNC),
86         XLAT(Q_SETQLIM),
87         XLAT(Q_V1_GETSTATS),
88         XLAT(Q_V1_RSQUASH),
89
90         XLAT(Q_V2_GETQUOTA),
91         XLAT(Q_V2_SETQUOTA),
92         XLAT(Q_V2_SETUSE),
93         XLAT(Q_V2_GETINFO),
94         XLAT(Q_V2_SETINFO),
95         XLAT(Q_V2_SETGRACE),
96         XLAT(Q_V2_SETFLAGS),
97         XLAT(Q_V2_GETSTATS),
98
99         XLAT(Q_SYNC),
100         XLAT(Q_QUOTAON),
101         XLAT(Q_QUOTAOFF),
102         XLAT(Q_GETFMT),
103         XLAT(Q_GETINFO),
104         XLAT(Q_SETINFO),
105         XLAT(Q_GETQUOTA),
106         XLAT(Q_SETQUOTA),
107
108         XLAT(Q_XQUOTAON),
109         XLAT(Q_XQUOTAOFF),
110         XLAT(Q_XGETQUOTA),
111         XLAT(Q_XSETQLIM),
112         XLAT(Q_XGETQSTAT),
113         XLAT(Q_XQUOTARM),
114         XLAT(Q_XQUOTASYNC),
115
116         XLAT_END
117 };
118
119 #define USRQUOTA 0
120 #define GRPQUOTA 1
121
122 static const struct xlat quotatypes[] = {
123         XLAT(USRQUOTA),
124         XLAT(GRPQUOTA),
125         XLAT_END
126 };
127
128 /* Quota format identifiers */
129 #define QFMT_VFS_OLD 1
130 #define QFMT_VFS_V0  2
131
132 static const struct xlat quota_formats[] = {
133         XLAT(QFMT_VFS_OLD),
134         XLAT(QFMT_VFS_V0),
135         XLAT_END
136 };
137
138 #define XFS_QUOTA_UDQ_ACCT      (1<<0)  /* user quota accounting */
139 #define XFS_QUOTA_UDQ_ENFD      (1<<1)  /* user quota limits enforcement */
140 #define XFS_QUOTA_GDQ_ACCT      (1<<2)  /* group quota accounting */
141 #define XFS_QUOTA_GDQ_ENFD      (1<<3)  /* group quota limits enforcement */
142
143 #define XFS_USER_QUOTA          (1<<0)  /* user quota type */
144 #define XFS_PROJ_QUOTA          (1<<1)  /* (IRIX) project quota type */
145 #define XFS_GROUP_QUOTA         (1<<2)  /* group quota type */
146
147 static const struct xlat xfs_quota_flags[] = {
148         XLAT(XFS_QUOTA_UDQ_ACCT),
149         XLAT(XFS_QUOTA_UDQ_ENFD),
150         XLAT(XFS_QUOTA_GDQ_ACCT),
151         XLAT(XFS_QUOTA_GDQ_ENFD),
152         XLAT_END
153 };
154
155 static const struct xlat xfs_dqblk_flags[] = {
156         XLAT(XFS_USER_QUOTA),
157         XLAT(XFS_PROJ_QUOTA),
158         XLAT(XFS_GROUP_QUOTA),
159         XLAT_END
160 };
161
162 /*
163  * Following flags are used to specify which fields are valid
164  */
165 #define QIF_BLIMITS     1
166 #define QIF_SPACE       2
167 #define QIF_ILIMITS     4
168 #define QIF_INODES      8
169 #define QIF_BTIME       16
170 #define QIF_ITIME       32
171
172 static const struct xlat if_dqblk_valid[] = {
173         XLAT(QIF_BLIMITS),
174         XLAT(QIF_SPACE),
175         XLAT(QIF_ILIMITS),
176         XLAT(QIF_INODES),
177         XLAT(QIF_BTIME),
178         XLAT(QIF_ITIME),
179         XLAT_END
180 };
181
182 struct if_dqblk
183 {
184         u_int64_t dqb_bhardlimit;
185         u_int64_t dqb_bsoftlimit;
186         u_int64_t dqb_curspace;
187         u_int64_t dqb_ihardlimit;
188         u_int64_t dqb_isoftlimit;
189         u_int64_t dqb_curinodes;
190         u_int64_t dqb_btime;
191         u_int64_t dqb_itime;
192         u_int32_t dqb_valid;
193 };
194
195 struct v1_dqblk
196 {
197         u_int32_t dqb_bhardlimit;       /* absolute limit on disk blks alloc */
198         u_int32_t dqb_bsoftlimit;       /* preferred limit on disk blks */
199         u_int32_t dqb_curblocks;        /* current block count */
200         u_int32_t dqb_ihardlimit;       /* maximum # allocated inodes */
201         u_int32_t dqb_isoftlimit;       /* preferred inode limit */
202         u_int32_t dqb_curinodes;        /* current # allocated inodes */
203         time_t  dqb_btime;      /* time limit for excessive disk use */
204         time_t  dqb_itime;      /* time limit for excessive files */
205 };
206
207 struct v2_dqblk
208 {
209         unsigned int dqb_ihardlimit;
210         unsigned int dqb_isoftlimit;
211         unsigned int dqb_curinodes;
212         unsigned int dqb_bhardlimit;
213         unsigned int dqb_bsoftlimit;
214         u_int64_t dqb_curspace;
215         time_t  dqb_btime;
216         time_t  dqb_itime;
217 };
218
219 struct xfs_dqblk
220 {
221         int8_t  d_version;      /* version of this structure */
222         int8_t  d_flags;        /* XFS_{USER,PROJ,GROUP}_QUOTA */
223         u_int16_t d_fieldmask;  /* field specifier */
224         u_int32_t d_id;         /* user, project, or group ID */
225         u_int64_t d_blk_hardlimit;      /* absolute limit on disk blks */
226         u_int64_t d_blk_softlimit;      /* preferred limit on disk blks */
227         u_int64_t d_ino_hardlimit;      /* maximum # allocated inodes */
228         u_int64_t d_ino_softlimit;      /* preferred inode limit */
229         u_int64_t d_bcount;     /* # disk blocks owned by the user */
230         u_int64_t d_icount;     /* # inodes owned by the user */
231         int32_t d_itimer;       /* zero if within inode limits */
232         int32_t d_btimer;       /* similar to above; for disk blocks */
233         u_int16_t d_iwarns;     /* # warnings issued wrt num inodes */
234         u_int16_t d_bwarns;     /* # warnings issued wrt disk blocks */
235         int32_t d_padding2;     /* padding2 - for future use */
236         u_int64_t d_rtb_hardlimit;      /* absolute limit on realtime blks */
237         u_int64_t d_rtb_softlimit;      /* preferred limit on RT disk blks */
238         u_int64_t d_rtbcount;   /* # realtime blocks owned */
239         int32_t d_rtbtimer;     /* similar to above; for RT disk blks */
240         u_int16_t d_rtbwarns;   /* # warnings issued wrt RT disk blks */
241         int16_t d_padding3;     /* padding3 - for future use */
242         char    d_padding4[8];  /* yet more padding */
243 };
244
245 /*
246  * Following flags are used to specify which fields are valid
247  */
248 #define IIF_BGRACE      1
249 #define IIF_IGRACE      2
250 #define IIF_FLAGS       4
251
252 static const struct xlat if_dqinfo_valid[] = {
253         XLAT(IIF_BGRACE),
254         XLAT(IIF_IGRACE),
255         XLAT(IIF_FLAGS),
256         XLAT_END
257 };
258
259 struct if_dqinfo
260 {
261         u_int64_t dqi_bgrace;
262         u_int64_t dqi_igrace;
263         u_int32_t dqi_flags;
264         u_int32_t dqi_valid;
265 };
266
267 struct v2_dqinfo
268 {
269         unsigned int dqi_bgrace;
270         unsigned int dqi_igrace;
271         unsigned int dqi_flags;
272         unsigned int dqi_blocks;
273         unsigned int dqi_free_blk;
274         unsigned int dqi_free_entry;
275 };
276
277 struct v1_dqstats
278 {
279         u_int32_t lookups;
280         u_int32_t drops;
281         u_int32_t reads;
282         u_int32_t writes;
283         u_int32_t cache_hits;
284         u_int32_t allocated_dquots;
285         u_int32_t free_dquots;
286         u_int32_t syncs;
287 };
288
289 struct v2_dqstats
290 {
291         u_int32_t lookups;
292         u_int32_t drops;
293         u_int32_t reads;
294         u_int32_t writes;
295         u_int32_t cache_hits;
296         u_int32_t allocated_dquots;
297         u_int32_t free_dquots;
298         u_int32_t syncs;
299         u_int32_t version;
300 };
301
302 typedef struct fs_qfilestat
303 {
304         u_int64_t qfs_ino;      /* inode number */
305         u_int64_t qfs_nblks;    /* number of BBs 512-byte-blks */
306         u_int32_t qfs_nextents; /* number of extents */
307 } fs_qfilestat_t;
308
309 struct xfs_dqstats
310 {
311         int8_t  qs_version;     /* version number for future changes */
312         u_int16_t qs_flags;     /* XFS_QUOTA_{U,P,G}DQ_{ACCT,ENFD} */
313         int8_t  qs_pad;         /* unused */
314         fs_qfilestat_t qs_uquota;       /* user quota storage information */
315         fs_qfilestat_t qs_gquota;       /* group quota storage information */
316         u_int32_t qs_incoredqs; /* number of dquots incore */
317         int32_t qs_btimelimit;  /* limit for blks timer */
318         int32_t qs_itimelimit;  /* limit for inodes timer */
319         int32_t qs_rtbtimelimit;        /* limit for rt blks timer */
320         u_int16_t qs_bwarnlimit;        /* limit for num warnings */
321         u_int16_t qs_iwarnlimit;        /* limit for num warnings */
322 };
323
324 static void
325 decode_cmd_data(struct tcb *tcp, u_int32_t cmd, unsigned long data)
326 {
327         switch (cmd) {
328                 case Q_GETQUOTA:
329                 case Q_SETQUOTA:
330                 {
331                         struct if_dqblk dq;
332
333                         if (cmd == Q_GETQUOTA && syserror(tcp)) {
334                                 tprintf("%#lx", data);
335                                 break;
336                         }
337                         if (umove(tcp, data, &dq) < 0) {
338                                 tprintf("{???} %#lx", data);
339                                 break;
340                         }
341                         tprintf("{bhardlimit=%" PRIu64 ", ", dq.dqb_bhardlimit);
342                         tprintf("bsoftlimit=%" PRIu64 ", ", dq.dqb_bsoftlimit);
343                         tprintf("curspace=%" PRIu64 ", ", dq.dqb_curspace);
344                         tprintf("ihardlimit=%" PRIu64 ", ", dq.dqb_ihardlimit);
345                         tprintf("isoftlimit=%" PRIu64 ", ", dq.dqb_isoftlimit);
346                         tprintf("curinodes=%" PRIu64 ", ", dq.dqb_curinodes);
347                         if (!abbrev(tcp)) {
348                                 tprintf("btime=%" PRIu64 ", ", dq.dqb_btime);
349                                 tprintf("itime=%" PRIu64 ", ", dq.dqb_itime);
350                                 tprints("valid=");
351                                 printflags(if_dqblk_valid,
352                                            dq.dqb_valid, "QIF_???");
353                                 tprints("}");
354                         } else
355                                 tprints("...}");
356                         break;
357                 }
358                 case Q_V1_GETQUOTA:
359                 case Q_V1_SETQUOTA:
360                 {
361                         struct v1_dqblk dq;
362
363                         if (cmd == Q_V1_GETQUOTA && syserror(tcp)) {
364                                 tprintf("%#lx", data);
365                                 break;
366                         }
367                         if (umove(tcp, data, &dq) < 0) {
368                                 tprintf("{???} %#lx", data);
369                                 break;
370                         }
371                         tprintf("{bhardlimit=%u, ", dq.dqb_bhardlimit);
372                         tprintf("bsoftlimit=%u, ", dq.dqb_bsoftlimit);
373                         tprintf("curblocks=%u, ", dq.dqb_curblocks);
374                         tprintf("ihardlimit=%u, ", dq.dqb_ihardlimit);
375                         tprintf("isoftlimit=%u, ", dq.dqb_isoftlimit);
376                         tprintf("curinodes=%u, ", dq.dqb_curinodes);
377                         tprintf("btime=%lu, ", (long) dq.dqb_btime);
378                         tprintf("itime=%lu}", (long) dq.dqb_itime);
379                         break;
380                 }
381                 case Q_V2_GETQUOTA:
382                 case Q_V2_SETQUOTA:
383                 {
384                         struct v2_dqblk dq;
385
386                         if (cmd == Q_V2_GETQUOTA && syserror(tcp)) {
387                                 tprintf("%#lx", data);
388                                 break;
389                         }
390                         if (umove(tcp, data, &dq) < 0) {
391                                 tprintf("{???} %#lx", data);
392                                 break;
393                         }
394                         tprintf("{ihardlimit=%u, ", dq.dqb_ihardlimit);
395                         tprintf("isoftlimit=%u, ", dq.dqb_isoftlimit);
396                         tprintf("curinodes=%u, ", dq.dqb_curinodes);
397                         tprintf("bhardlimit=%u, ", dq.dqb_bhardlimit);
398                         tprintf("bsoftlimit=%u, ", dq.dqb_bsoftlimit);
399                         tprintf("curspace=%" PRIu64 ", ", dq.dqb_curspace);
400                         tprintf("btime=%lu, ", (long) dq.dqb_btime);
401                         tprintf("itime=%lu}", (long) dq.dqb_itime);
402                         break;
403                 }
404                 case Q_XGETQUOTA:
405                 case Q_XSETQLIM:
406                 {
407                         struct xfs_dqblk dq;
408
409                         if (cmd == Q_XGETQUOTA && syserror(tcp)) {
410                                 tprintf("%#lx", data);
411                                 break;
412                         }
413                         if (umove(tcp, data, &dq) < 0) {
414                                 tprintf("{???} %#lx", data);
415                                 break;
416                         }
417                         tprintf("{version=%d, ", dq.d_version);
418                         tprints("flags=");
419                         printflags(xfs_dqblk_flags,
420                                    dq.d_flags, "XFS_???_QUOTA");
421                         tprintf(", fieldmask=%#x, ", dq.d_fieldmask);
422                         tprintf("id=%u, ", dq.d_id);
423                         tprintf("blk_hardlimit=%" PRIu64 ", ", dq.d_blk_hardlimit);
424                         tprintf("blk_softlimit=%" PRIu64 ", ", dq.d_blk_softlimit);
425                         tprintf("ino_hardlimit=%" PRIu64 ", ", dq.d_ino_hardlimit);
426                         tprintf("ino_softlimit=%" PRIu64 ", ", dq.d_ino_softlimit);
427                         tprintf("bcount=%" PRIu64 ", ", dq.d_bcount);
428                         tprintf("icount=%" PRIu64 ", ", dq.d_icount);
429                         if (!abbrev(tcp)) {
430                                 tprintf("itimer=%d, ", dq.d_itimer);
431                                 tprintf("btimer=%d, ", dq.d_btimer);
432                                 tprintf("iwarns=%u, ", dq.d_iwarns);
433                                 tprintf("bwarns=%u, ", dq.d_bwarns);
434                                 tprintf("rtbcount=%" PRIu64 ", ", dq.d_rtbcount);
435                                 tprintf("rtbtimer=%d, ", dq.d_rtbtimer);
436                                 tprintf("rtbwarns=%u}", dq.d_rtbwarns);
437                         } else
438                                 tprints("...}");
439                         break;
440                 }
441                 case Q_GETFMT:
442                 {
443                         u_int32_t fmt;
444
445                         if (syserror(tcp)) {
446                                 tprintf("%#lx", data);
447                                 break;
448                         }
449                         if (umove(tcp, data, &fmt) < 0) {
450                                 tprintf("{???} %#lx", data);
451                                 break;
452                         }
453                         tprints("{");
454                         printxval(quota_formats, fmt, "QFMT_VFS_???");
455                         tprints("}");
456                         break;
457                 }
458                 case Q_GETINFO:
459                 case Q_SETINFO:
460                 {
461                         struct if_dqinfo dq;
462
463                         if (cmd == Q_GETINFO && syserror(tcp)) {
464                                 tprintf("%#lx", data);
465                                 break;
466                         }
467                         if (umove(tcp, data, &dq) < 0) {
468                                 tprintf("{???} %#lx", data);
469                                 break;
470                         }
471                         tprintf("{bgrace=%" PRIu64 ", ", dq.dqi_bgrace);
472                         tprintf("igrace=%" PRIu64 ", ", dq.dqi_igrace);
473                         tprintf("flags=%#x, ", dq.dqi_flags);
474                         tprints("valid=");
475                         printflags(if_dqinfo_valid, dq.dqi_valid, "IIF_???");
476                         tprints("}");
477                         break;
478                 }
479                 case Q_V2_GETINFO:
480                 case Q_V2_SETINFO:
481                 {
482                         struct v2_dqinfo dq;
483
484                         if (cmd == Q_V2_GETINFO && syserror(tcp)) {
485                                 tprintf("%#lx", data);
486                                 break;
487                         }
488                         if (umove(tcp, data, &dq) < 0) {
489                                 tprintf("{???} %#lx", data);
490                                 break;
491                         }
492                         tprintf("{bgrace=%u, ", dq.dqi_bgrace);
493                         tprintf("igrace=%u, ", dq.dqi_igrace);
494                         tprintf("flags=%#x, ", dq.dqi_flags);
495                         tprintf("blocks=%u, ", dq.dqi_blocks);
496                         tprintf("free_blk=%u, ", dq.dqi_free_blk);
497                         tprintf("free_entry=%u}", dq.dqi_free_entry);
498                         break;
499                 }
500                 case Q_V1_GETSTATS:
501                 {
502                         struct v1_dqstats dq;
503
504                         if (syserror(tcp)) {
505                                 tprintf("%#lx", data);
506                                 break;
507                         }
508                         if (umove(tcp, data, &dq) < 0) {
509                                 tprintf("{???} %#lx", data);
510                                 break;
511                         }
512                         tprintf("{lookups=%u, ", dq.lookups);
513                         tprintf("drops=%u, ", dq.drops);
514                         tprintf("reads=%u, ", dq.reads);
515                         tprintf("writes=%u, ", dq.writes);
516                         tprintf("cache_hits=%u, ", dq.cache_hits);
517                         tprintf("allocated_dquots=%u, ", dq.allocated_dquots);
518                         tprintf("free_dquots=%u, ", dq.free_dquots);
519                         tprintf("syncs=%u}", dq.syncs);
520                         break;
521                 }
522                 case Q_V2_GETSTATS:
523                 {
524                         struct v2_dqstats dq;
525
526                         if (syserror(tcp)) {
527                                 tprintf("%#lx", data);
528                                 break;
529                         }
530                         if (umove(tcp, data, &dq) < 0) {
531                                 tprintf("{???} %#lx", data);
532                                 break;
533                         }
534                         tprintf("{lookups=%u, ", dq.lookups);
535                         tprintf("drops=%u, ", dq.drops);
536                         tprintf("reads=%u, ", dq.reads);
537                         tprintf("writes=%u, ", dq.writes);
538                         tprintf("cache_hits=%u, ", dq.cache_hits);
539                         tprintf("allocated_dquots=%u, ", dq.allocated_dquots);
540                         tprintf("free_dquots=%u, ", dq.free_dquots);
541                         tprintf("syncs=%u, ", dq.syncs);
542                         tprintf("version=%u}", dq.version);
543                         break;
544                 }
545                 case Q_XGETQSTAT:
546                 {
547                         struct xfs_dqstats dq;
548
549                         if (syserror(tcp)) {
550                                 tprintf("%#lx", data);
551                                 break;
552                         }
553                         if (umove(tcp, data, &dq) < 0) {
554                                 tprintf("{???} %#lx", data);
555                                 break;
556                         }
557                         tprintf("{version=%d, ", dq.qs_version);
558                         if (abbrev(tcp)) {
559                                 tprints("...}");
560                                 break;
561                         }
562                         tprints("flags=");
563                         printflags(xfs_quota_flags,
564                                    dq.qs_flags, "XFS_QUOTA_???");
565                         tprintf(", incoredqs=%u, ", dq.qs_incoredqs);
566                         tprintf("u_ino=%" PRIu64 ", ", dq.qs_uquota.qfs_ino);
567                         tprintf("u_nblks=%" PRIu64 ", ", dq.qs_uquota.qfs_nblks);
568                         tprintf("u_nextents=%u, ", dq.qs_uquota.qfs_nextents);
569                         tprintf("g_ino=%" PRIu64 ", ", dq.qs_gquota.qfs_ino);
570                         tprintf("g_nblks=%" PRIu64 ", ", dq.qs_gquota.qfs_nblks);
571                         tprintf("g_nextents=%u, ", dq.qs_gquota.qfs_nextents);
572                         tprintf("btimelimit=%d, ", dq.qs_btimelimit);
573                         tprintf("itimelimit=%d, ", dq.qs_itimelimit);
574                         tprintf("rtbtimelimit=%d, ", dq.qs_rtbtimelimit);
575                         tprintf("bwarnlimit=%u, ", dq.qs_bwarnlimit);
576                         tprintf("iwarnlimit=%u}", dq.qs_iwarnlimit);
577                         break;
578                 }
579                 case Q_XQUOTAON:
580                 {
581                         u_int32_t flag;
582
583                         if (umove(tcp, data, &flag) < 0) {
584                                 tprintf("{???} %#lx", data);
585                                 break;
586                         }
587                         tprints("{");
588                         printflags(xfs_quota_flags, flag, "XFS_QUOTA_???");
589                         tprints("}");
590                         break;
591                 }
592                 default:
593                         tprintf("%#lx", data);
594                         break;
595         }
596 }
597
598 int
599 sys_quotactl(struct tcb *tcp)
600 {
601         /*
602          * The Linux kernel only looks at the low 32 bits of command and id
603          * arguments, but on some 64-bit architectures (s390x) this word
604          * will have been sign-extended when we see it.  The high 1 bits
605          * don't mean anything, so don't confuse the output with them.
606          */
607         u_int32_t qcmd = tcp->u_arg[0];
608         u_int32_t cmd = QCMD_CMD(qcmd);
609         u_int32_t type = QCMD_TYPE(qcmd);
610         u_int32_t id = tcp->u_arg[2];
611
612         if (!verbose(tcp))
613                 return printargs(tcp);
614
615         if (entering(tcp)) {
616                 printxval(quotacmds, cmd, "Q_???");
617                 tprints("|");
618                 printxval(quotatypes, type, "???QUOTA");
619                 tprints(", ");
620                 printpath(tcp, tcp->u_arg[1]);
621                 tprints(", ");
622                 switch (cmd) {
623                         case Q_V1_QUOTAON:
624                         case Q_QUOTAON:
625                                 printxval(quota_formats, id, "QFMT_VFS_???");
626                                 break;
627                         case Q_V1_GETQUOTA:
628                         case Q_V2_GETQUOTA:
629                         case Q_GETQUOTA:
630                         case Q_V1_SETQUOTA:
631                         case Q_V2_SETQUOTA:
632                         case Q_V1_SETUSE:
633                         case Q_V2_SETUSE:
634                         case Q_SETQLIM:
635                         case Q_SETQUOTA:
636                         case Q_XGETQUOTA:
637                         case Q_XSETQLIM:
638                                 tprintf("%u", id);
639                                 break;
640                         default:
641                                 tprintf("%#lx", tcp->u_arg[2]);
642                                 break;
643                 }
644                 tprints(", ");
645         } else {
646                 if (!tcp->u_arg[3])
647                         tprints("NULL");
648                 else
649                         decode_cmd_data(tcp, cmd, tcp->u_arg[3]);
650         }
651         return 0;
652 }