Home | History | Annotate | Download | only in strace
      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  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. The name of the author may not be used to endorse or promote products
     17  *    derived from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  *
     30  *	$Id: resource.c,v 1.13 2004/10/06 22:14:53 roland Exp $
     31  */
     32 
     33 #include "defs.h"
     34 
     35 #include <sys/resource.h>
     36 #ifdef LINUX
     37 #include <sys/times.h>
     38 #include <linux/kernel.h>
     39 #ifdef HAVE_ANDROID_OS
     40 #define spinlock_t struct spinlock_t
     41 #define if_dqblk dqblk
     42 #define dqb_curblocks dqb_curspace
     43 #else
     44 #include <sys/quota.h>
     45 #endif
     46 #include <linux/quota.h>
     47 #endif /* LINUX */
     48 #ifdef SUNOS4
     49 #include <ufs/quota.h>
     50 #endif /* SUNOS4 */
     51 #if defined(SVR4) || defined(FREEBSD)
     52 #include <sys/times.h>
     53 #include <sys/time.h>
     54 #endif
     55 
     56 #if HAVE_LONG_LONG_RLIM_T
     57 /*
     58  * Hacks for systems that have a long long rlim_t
     59  */
     60 
     61 #define rlimit64 rlimit			/* Ugly hack */
     62 #define rlim64_t rlim_t			/* Ugly hack */
     63 #define RLIM64_INFINITY RLIM_INFINITY	/* You guessed it */
     64 
     65 #define sys_getrlimit64	sys_getrlimit
     66 #define sys_setrlimit64	sys_setrlimit
     67 #endif
     68 
     69 static const struct xlat resources[] = {
     70 #ifdef RLIMIT_CPU
     71 	{ RLIMIT_CPU,	"RLIMIT_CPU"	},
     72 #endif
     73 #ifdef RLIMIT_FSIZE
     74 	{ RLIMIT_FSIZE,	"RLIMIT_FSIZE"	},
     75 #endif
     76 #ifdef RLIMIT_DATA
     77 	{ RLIMIT_DATA,	"RLIMIT_DATA"	},
     78 #endif
     79 #ifdef RLIMIT_STACK
     80 	{ RLIMIT_STACK,	"RLIMIT_STACK"	},
     81 #endif
     82 #ifdef RLIMIT_CORE
     83 	{ RLIMIT_CORE,	"RLIMIT_CORE"	},
     84 #endif
     85 #ifdef RLIMIT_RSS
     86 	{ RLIMIT_RSS,	"RLIMIT_RSS"	},
     87 #endif
     88 #ifdef RLIMIT_NPROC
     89 	{ RLIMIT_NPROC,"RLIMIT_NPROC"	},
     90 #endif
     91 #ifdef RLIMIT_NOFILE
     92 	{ RLIMIT_NOFILE,"RLIMIT_NOFILE"	},
     93 #endif
     94 #ifdef RLIMIT_MEMLOCK
     95 	{ RLIMIT_MEMLOCK,	"RLIMIT_MEMLOCK"	},
     96 #endif
     97 #ifdef RLIMIT_VMEM
     98 	{ RLIMIT_VMEM,	"RLIMIT_VMEM"	},
     99 #endif
    100 #ifdef RLIMIT_AS
    101 	{ RLIMIT_AS,	"RLIMIT_AS"	},
    102 #endif
    103 #ifdef RLIMIT_LOCKS
    104 	{ RLIMIT_LOCKS,	"RLIMIT_LOCKS"	},
    105 #endif
    106 #ifdef RLIMIT_SIGPENDING
    107 	{ RLIMIT_SIGPENDING,	"RLIMIT_SIGPENDING"	},
    108 #endif
    109 #ifdef RLIMIT_MSGQUEUE
    110 	{ RLIMIT_MSGQUEUE,	"RLIMIT_MSGQUEUE"	},
    111 #endif
    112 	{ 0,		NULL		},
    113 };
    114 
    115 #if !HAVE_LONG_LONG_RLIM_T
    116 static char *
    117 sprintrlim(lim)
    118 long lim;
    119 {
    120 	static char buf[32];
    121 
    122 	if (lim == RLIM_INFINITY)
    123 		sprintf(buf, "RLIM_INFINITY");
    124 	else if (lim > 1024 && lim%1024 == 0)
    125 		sprintf(buf, "%ld*1024", lim/1024);
    126 	else
    127 		sprintf(buf, "%ld", lim);
    128 	return buf;
    129 }
    130 
    131 int
    132 sys_getrlimit(tcp)
    133 struct tcb *tcp;
    134 {
    135 	struct rlimit rlim;
    136 
    137 	if (entering(tcp)) {
    138 		printxval(resources, tcp->u_arg[0], "RLIMIT_???");
    139 		tprintf(", ");
    140 	}
    141 	else {
    142 		if (syserror(tcp) || !verbose(tcp))
    143 			tprintf("%#lx", tcp->u_arg[1]);
    144 		else if (umove(tcp, tcp->u_arg[1], &rlim) < 0)
    145 			tprintf("{...}");
    146 		else {
    147 			tprintf("{rlim_cur=%s,", sprintrlim(rlim.rlim_cur));
    148 			tprintf(" rlim_max=%s}", sprintrlim(rlim.rlim_max));
    149 		}
    150 	}
    151 	return 0;
    152 }
    153 
    154 int
    155 sys_setrlimit(tcp)
    156 struct tcb *tcp;
    157 {
    158 	struct rlimit rlim;
    159 
    160 	if (entering(tcp)) {
    161 		printxval(resources, tcp->u_arg[0], "RLIMIT_???");
    162 		tprintf(", ");
    163 		if (!verbose(tcp))
    164 			tprintf("%#lx", tcp->u_arg[1]);
    165 		else if (umove(tcp, tcp->u_arg[1], &rlim) < 0)
    166 			tprintf("{...}");
    167 		else {
    168 			tprintf("{rlim_cur=%s,", sprintrlim(rlim.rlim_cur));
    169 			tprintf(" rlim_max=%s}", sprintrlim(rlim.rlim_max));
    170 		}
    171 	}
    172 	return 0;
    173 }
    174 #endif /* !HAVE_LONG_LONG_RLIM_T */
    175 
    176 #ifndef HAVE_ANDROID_OS
    177 #if _LFS64_LARGEFILE || HAVE_LONG_LONG_RLIM_T
    178 static char *
    179 sprintrlim64(lim)
    180 rlim64_t lim;
    181 {
    182 	static char buf[64];
    183 
    184 	if (lim == RLIM64_INFINITY)
    185 		sprintf(buf, "RLIM64_INFINITY");
    186 	else if (lim > 1024 && lim%1024 == 0)
    187 		sprintf(buf, "%lld*1024", (long long) lim/1024);
    188 	else
    189 		sprintf(buf, "%lld", (long long) lim);
    190 	return buf;
    191 }
    192 
    193 int
    194 sys_getrlimit64(tcp)
    195 struct tcb *tcp;
    196 {
    197 	struct rlimit64 rlim;
    198 
    199 	if (entering(tcp)) {
    200 		printxval(resources, tcp->u_arg[0], "RLIMIT_???");
    201 		tprintf(", ");
    202 	}
    203 	else {
    204 		if (syserror(tcp) || !verbose(tcp))
    205 			tprintf("%#lx", tcp->u_arg[1]);
    206 		else if (umove(tcp, tcp->u_arg[1], &rlim) < 0)
    207 			tprintf("{...}");
    208 		else {
    209 			tprintf("{rlim_cur=%s,", sprintrlim64(rlim.rlim_cur));
    210 			tprintf(" rlim_max=%s}", sprintrlim64(rlim.rlim_max));
    211 		}
    212 	}
    213 	return 0;
    214 }
    215 
    216 int
    217 sys_setrlimit64(tcp)
    218 struct tcb *tcp;
    219 {
    220 	struct rlimit64 rlim;
    221 
    222 	if (entering(tcp)) {
    223 		printxval(resources, tcp->u_arg[0], "RLIMIT_???");
    224 		tprintf(", ");
    225 		if (!verbose(tcp))
    226 			tprintf("%#lx", tcp->u_arg[1]);
    227 		else if (umove(tcp, tcp->u_arg[1], &rlim) < 0)
    228 			tprintf("{...}");
    229 		else {
    230 			tprintf("{rlim_cur=%s,", sprintrlim64(rlim.rlim_cur));
    231 			tprintf(" rlim_max=%s}", sprintrlim64(rlim.rlim_max));
    232 		}
    233 	}
    234 	return 0;
    235 }
    236 #endif /* _LFS64_LARGEFILES || HAVE_LONG_LONG_RLIM_T */
    237 #endif /* HAVE_ANDROID_OS */
    238 
    239 #ifndef SVR4
    240 
    241 static const struct xlat usagewho[] = {
    242 	{ RUSAGE_SELF,		"RUSAGE_SELF"		},
    243 	{ RUSAGE_CHILDREN,	"RUSAGE_CHILDREN"	},
    244 #ifdef RUSAGE_BOTH
    245 	{ RUSAGE_BOTH,		"RUSAGE_BOTH"		},
    246 #endif
    247 	{ 0,			NULL			},
    248 };
    249 
    250 #ifdef ALPHA
    251 void
    252 printrusage32(tcp, addr)
    253 struct tcb *tcp;
    254 long addr;
    255 {
    256     struct timeval32
    257     {
    258 	unsigned tv_sec;
    259 	unsigned tv_usec;
    260     };
    261     struct rusage32
    262     {
    263 	struct timeval32 ru_utime;	/* user time used */
    264 	struct timeval32 ru_stime;	/* system time used */
    265 	long	ru_maxrss;		/* maximum resident set size */
    266 	long	ru_ixrss;		/* integral shared memory size */
    267 	long	ru_idrss;		/* integral unshared data size */
    268 	long	ru_isrss;		/* integral unshared stack size */
    269 	long	ru_minflt;		/* page reclaims */
    270 	long	ru_majflt;		/* page faults */
    271 	long	ru_nswap;		/* swaps */
    272 	long	ru_inblock;		/* block input operations */
    273 	long	ru_oublock;		/* block output operations */
    274 	long	ru_msgsnd;		/* messages sent */
    275 	long	ru_msgrcv;		/* messages received */
    276 	long	ru_nsignals;		/* signals received */
    277 	long	ru_nvcsw;		/* voluntary context switches */
    278 	long	ru_nivcsw;		/* involuntary " */
    279     } ru;
    280 
    281     if (!addr)
    282 	tprintf("NULL");
    283     else if (syserror(tcp) || !verbose(tcp))
    284 	tprintf("%#lx", addr);
    285     else if (umove(tcp, addr, &ru) < 0)
    286 	tprintf("{...}");
    287     else if (!abbrev(tcp)) {
    288 	tprintf("{ru_utime={%lu, %lu}, ru_stime={%lu, %lu}, ",
    289 		(long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec,
    290 		(long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec);
    291 	tprintf("ru_maxrss=%lu, ru_ixrss=%lu, ",
    292 		ru.ru_maxrss, ru.ru_ixrss);
    293 	tprintf("ru_idrss=%lu, ru_isrss=%lu, ",
    294 		ru.ru_idrss, ru.ru_isrss);
    295 	tprintf("ru_minflt=%lu, ru_majflt=%lu, ru_nswap=%lu, ",
    296 		ru.ru_minflt, ru.ru_majflt, ru.ru_nswap);
    297 	tprintf("ru_inblock=%lu, ru_oublock=%lu, ",
    298 		ru.ru_inblock, ru.ru_oublock);
    299 	tprintf("ru_msgsnd=%lu, ru_msgrcv=%lu, ",
    300 		ru.ru_msgsnd, ru.ru_msgrcv);
    301 	tprintf("ru_nsignals=%lu, ru_nvcsw=%lu, ru_nivcsw=%lu}",
    302 		ru.ru_nsignals, ru.ru_nvcsw, ru.ru_nivcsw);
    303     }
    304     else {
    305 	tprintf("{ru_utime={%lu, %lu}, ru_stime={%lu, %lu}, ...}",
    306 		(long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec,
    307 		(long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec);
    308     }
    309 }
    310 #endif
    311 
    312 void
    313 printrusage(tcp, addr)
    314 struct tcb *tcp;
    315 long addr;
    316 {
    317 	struct rusage ru;
    318 
    319 	if (!addr)
    320 		tprintf("NULL");
    321 	else if (syserror(tcp) || !verbose(tcp))
    322 		tprintf("%#lx", addr);
    323 	else if (umove(tcp, addr, &ru) < 0)
    324 		tprintf("{...}");
    325 	else if (!abbrev(tcp)) {
    326 		tprintf("{ru_utime={%lu, %lu}, ru_stime={%lu, %lu}, ",
    327 			(long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec,
    328 			(long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec);
    329 		tprintf("ru_maxrss=%lu, ru_ixrss=%lu, ",
    330 			ru.ru_maxrss, ru.ru_ixrss);
    331 		tprintf("ru_idrss=%lu, ru_isrss=%lu, ",
    332 			ru.ru_idrss, ru.ru_isrss);
    333 		tprintf("ru_minflt=%lu, ru_majflt=%lu, ru_nswap=%lu, ",
    334 			ru.ru_minflt, ru.ru_majflt, ru.ru_nswap);
    335 		tprintf("ru_inblock=%lu, ru_oublock=%lu, ",
    336 			ru.ru_inblock, ru.ru_oublock);
    337 		tprintf("ru_msgsnd=%lu, ru_msgrcv=%lu, ",
    338 			ru.ru_msgsnd, ru.ru_msgrcv);
    339 		tprintf("ru_nsignals=%lu, ru_nvcsw=%lu, ru_nivcsw=%lu}",
    340 			ru.ru_nsignals, ru.ru_nvcsw, ru.ru_nivcsw);
    341 	}
    342 	else {
    343 		tprintf("{ru_utime={%lu, %lu}, ru_stime={%lu, %lu}, ...}",
    344 			(long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec,
    345 			(long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec);
    346 	}
    347 }
    348 
    349 int
    350 sys_getrusage(tcp)
    351 struct tcb *tcp;
    352 {
    353 	if (entering(tcp)) {
    354 		printxval(usagewho, tcp->u_arg[0], "RUSAGE_???");
    355 		tprintf(", ");
    356 	}
    357 	else
    358 		printrusage(tcp, tcp->u_arg[1]);
    359 	return 0;
    360 }
    361 
    362 #ifdef ALPHA
    363 int
    364 sys_osf_getrusage(tcp)
    365 struct tcb *tcp;
    366 {
    367     if (entering(tcp)) {
    368 	printxval(usagewho, tcp->u_arg[0], "RUSAGE_???");
    369 	tprintf(", ");
    370     }
    371     else
    372 	printrusage32(tcp, tcp->u_arg[1]);
    373     return 0;
    374 }
    375 #endif /* ALPHA */
    376 
    377 #endif /* !SVR4 */
    378 
    379 #ifdef LINUX
    380 
    381 int
    382 sys_sysinfo(tcp)
    383 struct tcb *tcp;
    384 {
    385 	struct sysinfo si;
    386 
    387 	if (exiting(tcp)) {
    388 		if (syserror(tcp) || !verbose(tcp))
    389 			tprintf("%#lx", tcp->u_arg[0]);
    390 		else if (umove(tcp, tcp->u_arg[0], &si) < 0)
    391 			tprintf("{...}");
    392 		else {
    393 			tprintf("{uptime=%lu, loads=[%lu, %lu, %lu] ",
    394 				si.uptime, si.loads[0], si.loads[1],
    395 				si.loads[2]);
    396 			tprintf("totalram=%lu, freeram=%lu, ",
    397 				si.totalram, si.freeram);
    398 			tprintf("sharedram=%lu, bufferram=%lu} ",
    399 				si.sharedram, si.bufferram);
    400 			tprintf("totalswap=%lu, freeswap=%lu, procs=%hu}",
    401 				si.totalswap, si.freeswap, si.procs);
    402 		}
    403 	}
    404 	return 0;
    405 }
    406 
    407 #endif /* LINUX */
    408 
    409 static const struct xlat priorities[] = {
    410 	{ PRIO_PROCESS,	"PRIO_PROCESS"	},
    411 	{ PRIO_PGRP,	"PRIO_PGRP"	},
    412 	{ PRIO_USER,	"PRIO_USER"	},
    413 	{ 0,		NULL		},
    414 };
    415 
    416 int
    417 sys_getpriority(tcp)
    418 struct tcb *tcp;
    419 {
    420 	if (entering(tcp)) {
    421 		printxval(priorities, tcp->u_arg[0], "PRIO_???");
    422 		tprintf(", %lu", tcp->u_arg[1]);
    423 	}
    424 	return 0;
    425 }
    426 
    427 int
    428 sys_setpriority(tcp)
    429 struct tcb *tcp;
    430 {
    431 	if (entering(tcp)) {
    432 		printxval(priorities, tcp->u_arg[0], "PRIO_???");
    433 		tprintf(", %lu, %ld", tcp->u_arg[1], tcp->u_arg[2]);
    434 	}
    435 	return 0;
    436 }
    437 
    438 int
    439 sys_nice(tcp)
    440 struct tcb *tcp;
    441 {
    442 	if (entering(tcp))
    443 		tprintf("%ld", tcp->u_arg[0]);
    444 	return 0;
    445 }
    446 
    447 #ifndef SUNOS4
    448 
    449 int
    450 sys_times(tcp)
    451 struct tcb *tcp;
    452 {
    453 	struct tms tbuf;
    454 
    455 	if (exiting(tcp)) {
    456 		if (tcp->u_arg[0] == 0)
    457 			tprintf("NULL");
    458 		else if (syserror(tcp))
    459 			tprintf("%#lx", tcp->u_arg[0]);
    460 		else if (umove(tcp, tcp->u_arg[0], &tbuf) < 0)
    461 			tprintf("{...}");
    462 		else {
    463 			tprintf("{tms_utime=%lu, tms_stime=%lu, ",
    464 				tbuf.tms_utime, tbuf.tms_stime);
    465 			tprintf("tms_cutime=%lu, tms_cstime=%lu}",
    466 				tbuf.tms_cutime, tbuf.tms_cstime);
    467 		}
    468 	}
    469 	return 0;
    470 }
    471 
    472 #endif /* !SUNOS4 */
    473 
    474 
    475 //#ifndef HAVE_ANDROID_OS
    476 #ifdef LINUX
    477 
    478 #define NEW_CMD(c)      ((0x80<<16)+(c))
    479 #define XQM_CMD(c)      (('X'<<8)+(c))
    480 #define NEW_COMMAND(c) (( ((c) >> SUBCMDSHIFT) & (0x80 << 16)))
    481 #define XQM_COMMAND(c) (( ((c) >> SUBCMDSHIFT) & ('X' << 8)) == ('X' << 8))
    482 #define OLD_COMMAND(c) (!NEW_COMMAND(c) && !XQM_COMMAND(c))
    483 
    484 static const struct xlat quotacmds[] = {
    485 	{ Q_QUOTAON,	"Q_QUOTAON"	},
    486 	{ Q_QUOTAOFF,	"Q_QUOTAOFF"	},
    487 	{ Q_GETQUOTA,	"Q_GETQUOTA"	},
    488 	{ Q_SETQUOTA,	"Q_SETQUOTA"	},
    489 #ifndef HAVE_ANDROID_OS
    490 	{ Q_SETUSE,	"Q_SETUSE"	},
    491 #endif
    492 	{ Q_SYNC,	"Q_SYNC"	},
    493 #ifndef HAVE_ANDROID_OS
    494 	{ Q_SETQLIM,	"Q_SETQLIM"	},
    495 	{ Q_GETSTATS,	"Q_GETSTATS"	},
    496 	{ Q_RSQUASH,	"Q_RSQUASH"	},
    497 #endif
    498 	{ NEW_CMD(0x1), "Q_SYNC"        },
    499 	{ NEW_CMD(0x2), "Q_QUOTAON"     },
    500 	{ NEW_CMD(0x3), "Q_QUOTAOFF"    },
    501 	{ NEW_CMD(0x4), "Q_GETFMT"      },
    502 	{ NEW_CMD(0x5), "Q_GETINFO"     },
    503 	{ NEW_CMD(0x6), "Q_SETINFO"     },
    504 	{ NEW_CMD(0x7), "Q_GETQUOTA"    },
    505 	{ NEW_CMD(0x8), "Q_SETQUOTA"    },
    506 	{ XQM_CMD(0x1), "Q_XQUOTAON"    },
    507 	{ XQM_CMD(0x2), "Q_XQUOTAOFF"   },
    508 	{ XQM_CMD(0x3), "Q_XGETQUOTA"   },
    509 	{ XQM_CMD(0x4), "Q_XSETQLIM"    },
    510 	{ XQM_CMD(0x5), "Q_XGETQSTAT"   },
    511 	{ XQM_CMD(0x6), "Q_XQUOTARM"    },
    512 	{ 0,		NULL		},
    513 };
    514 
    515 static const struct xlat quotatypes[] = {
    516 	{ USRQUOTA,	"USRQUOTA"	},
    517 	{ GRPQUOTA,	"GRPQUOTA"	},
    518 	{ 0,		NULL		},
    519 };
    520 
    521 int
    522 sys_quotactl(tcp)
    523 struct tcb *tcp;
    524 {
    525 	/*
    526 	 * The Linux kernel only looks at the low 32 bits of the command
    527 	 * argument, but on some 64-bit architectures (s390x) this word
    528 	 * will have been sign-extended when we see it.  The high 1 bits
    529 	 * don't mean anything, so don't confuse the output with them.
    530 	 */
    531 	unsigned int cmd = tcp->u_arg[0];
    532 
    533 	if (entering(tcp)) {
    534 		printxval(quotacmds, cmd >> SUBCMDSHIFT, "Q_???");
    535 		tprintf("|");
    536 		printxval(quotatypes, cmd & SUBCMDMASK, "???QUOTA");
    537 		tprintf(", ");
    538 		printstr(tcp, tcp->u_arg[1], -1);
    539 		tprintf(", %lu, ", tcp->u_arg[2]);
    540 	}
    541 	else {
    542 		struct dqblk dq;
    543 
    544 		if (!tcp->u_arg[3])
    545 			tprintf("NULL");
    546                else if (!verbose(tcp) || !OLD_COMMAND(cmd))
    547 			tprintf("%#lx", tcp->u_arg[3]);
    548                 else if (umoven(tcp, tcp->u_arg[3], sizeof(struct dqblk),
    549                     (char *) &dq) < 0)
    550                         tprintf("???");
    551 		else {
    552                         tprintf("{");
    553 			tprintf("%u, ", dq.dqb_bhardlimit);
    554 			tprintf("%u, ", dq.dqb_bsoftlimit);
    555 			tprintf("%u, ", dq.dqb_curblocks);
    556 			tprintf("%u, ", dq.dqb_ihardlimit);
    557 			tprintf("%u, ", dq.dqb_isoftlimit);
    558 			tprintf("%u, ", dq.dqb_curinodes);
    559 			tprintf("%lu, ", dq.dqb_btime);
    560 			tprintf("%lu", dq.dqb_itime);
    561                         tprintf("}");
    562 		}
    563 
    564 	}
    565 	return 0;
    566 }
    567 
    568 #endif /* Linux */
    569 //#endif /* HAVE_ANDROID_OS */
    570 
    571 #if defined(SUNOS4) || defined(FREEBSD)
    572 
    573 #ifdef FREEBSD
    574 #include <ufs/ufs/quota.h>
    575 #endif
    576 
    577 static const struct xlat quotacmds[] = {
    578 	{ Q_QUOTAON,	"Q_QUOTAON"	},
    579 	{ Q_QUOTAOFF,	"Q_QUOTAOFF"	},
    580 	{ Q_GETQUOTA,	"Q_GETQUOTA"	},
    581 	{ Q_SETQUOTA,	"Q_SETQUOTA"	},
    582 #ifdef Q_SETQLIM
    583 	{ Q_SETQLIM,	"Q_SETQLIM"	},
    584 #endif
    585 #ifdef Q_SETUSE
    586 	{ Q_SETUSE,	"Q_SETUSE"	},
    587 #endif
    588 	{ Q_SYNC,	"Q_SYNC"	},
    589 	{ 0,		NULL		},
    590 };
    591 
    592 int
    593 sys_quotactl(tcp)
    594 struct tcb *tcp;
    595 {
    596 	/* fourth arg (addr) not interpreted here */
    597 	if (entering(tcp)) {
    598 #ifdef SUNOS4
    599 		printxval(quotacmds, tcp->u_arg[0], "Q_???");
    600 		tprintf(", ");
    601 		printstr(tcp, tcp->u_arg[1], -1);
    602 #endif
    603 #ifdef FREEBSD
    604 		printpath(tcp, tcp->u_arg[0]);
    605 		tprintf(", ");
    606 		printxval(quotacmds, tcp->u_arg[1], "Q_???");
    607 #endif
    608 		tprintf(", %lu, %#lx", tcp->u_arg[2], tcp->u_arg[3]);
    609 	}
    610 	return 0;
    611 }
    612 
    613 #endif /* SUNOS4 || FREEBSD */
    614