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