1 /*- 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Mike Karels at Berkeley Software Design, Inc. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)kern_sysctl.c 8.3 (Berkeley) 01/06/94 11 */ 12 13 /* 14 * sysctl system call. 15 */ 16 17 #include <sys/param.h> 18 #include <sys/systm.h> 19 #include <sys/kernel.h> 20 #include <sys/malloc.h> 21 #include <sys/proc.h> 22 #include <sys/file.h> 23 #include <sys/vnode.h> 24 #include <sys/unistd.h> 25 #include <sys/buf.h> 26 #include <sys/ioctl.h> 27 #include <sys/tty.h> 28 #include <vm/vm.h> 29 #include <sys/sysctl.h> 30 31 sysctlfn kern_sysctl; 32 sysctlfn hw_sysctl; 33 #ifdef DEBUG 34 sysctlfn debug_sysctl; 35 #endif 36 extern sysctlfn vm_sysctl; 37 extern sysctlfn fs_sysctl; 38 extern sysctlfn net_sysctl; 39 extern sysctlfn cpu_sysctl; 40 41 /* 42 * Locking and stats 43 */ 44 static struct sysctl_lock { 45 int sl_lock; 46 int sl_want; 47 int sl_locked; 48 } memlock; 49 50 struct sysctl_args { 51 int *name; 52 u_int namelen; 53 void *old; 54 size_t *oldlenp; 55 void *new; 56 size_t newlen; 57 }; 58 59 int 60 __sysctl(p, uap, retval) 61 struct proc *p; 62 register struct sysctl_args *uap; 63 int *retval; 64 { 65 int error, dolock = 1; 66 u_int savelen, oldlen = 0; 67 sysctlfn *fn; 68 int name[CTL_MAXNAME]; 69 70 if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag))) 71 return (error); 72 /* 73 * all top-level sysctl names are non-terminal 74 */ 75 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 76 return (EINVAL); 77 if (error = copyin(uap->name, &name, uap->namelen * sizeof(int))) 78 return (error); 79 80 switch (name[0]) { 81 case CTL_KERN: 82 fn = kern_sysctl; 83 if (name[2] != KERN_VNODE) /* XXX */ 84 dolock = 0; 85 break; 86 case CTL_HW: 87 fn = hw_sysctl; 88 break; 89 case CTL_VM: 90 fn = vm_sysctl; 91 break; 92 case CTL_NET: 93 fn = net_sysctl; 94 break; 95 #ifdef notyet 96 case CTL_FS: 97 fn = fs_sysctl; 98 break; 99 #endif 100 case CTL_MACHDEP: 101 fn = cpu_sysctl; 102 break; 103 #ifdef DEBUG 104 case CTL_DEBUG: 105 fn = debug_sysctl; 106 break; 107 #endif 108 default: 109 return (EOPNOTSUPP); 110 } 111 112 if (uap->oldlenp && 113 (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen)))) 114 return (error); 115 if (uap->old != NULL) { 116 if (!useracc(uap->old, oldlen, B_WRITE)) 117 return (EFAULT); 118 while (memlock.sl_lock) { 119 memlock.sl_want = 1; 120 sleep((caddr_t)&memlock, PRIBIO+1); 121 memlock.sl_locked++; 122 } 123 memlock.sl_lock = 1; 124 if (dolock) 125 vslock(uap->old, oldlen); 126 savelen = oldlen; 127 } 128 error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen, 129 uap->new, uap->newlen, p); 130 if (uap->old != NULL) { 131 if (dolock) 132 vsunlock(uap->old, savelen, B_WRITE); 133 memlock.sl_lock = 0; 134 if (memlock.sl_want) { 135 memlock.sl_want = 0; 136 wakeup((caddr_t)&memlock); 137 } 138 } 139 if (error) 140 return (error); 141 if (uap->oldlenp) 142 error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen)); 143 *retval = oldlen; 144 return (0); 145 } 146 147 /* 148 * Attributes stored in the kernel. 149 */ 150 char hostname[MAXHOSTNAMELEN]; 151 int hostnamelen; 152 long hostid; 153 int securelevel; 154 155 /* 156 * kernel related system variables. 157 */ 158 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 159 int *name; 160 u_int namelen; 161 void *oldp; 162 size_t *oldlenp; 163 void *newp; 164 size_t newlen; 165 struct proc *p; 166 { 167 int error, level, inthostid; 168 extern char ostype[], osrelease[], version[]; 169 170 /* all sysctl names at this level are terminal */ 171 if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF)) 172 return (ENOTDIR); /* overloaded */ 173 174 switch (name[0]) { 175 case KERN_OSTYPE: 176 return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); 177 case KERN_OSRELEASE: 178 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); 179 case KERN_OSREV: 180 return (sysctl_rdint(oldp, oldlenp, newp, BSD)); 181 case KERN_VERSION: 182 return (sysctl_rdstring(oldp, oldlenp, newp, version)); 183 case KERN_MAXVNODES: 184 return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes)); 185 case KERN_MAXPROC: 186 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc)); 187 case KERN_MAXFILES: 188 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); 189 case KERN_ARGMAX: 190 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); 191 case KERN_SECURELVL: 192 level = securelevel; 193 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 194 newp == NULL) 195 return (error); 196 if (level < securelevel && p->p_pid != 1) 197 return (EPERM); 198 securelevel = level; 199 return (0); 200 case KERN_HOSTNAME: 201 error = sysctl_string(oldp, oldlenp, newp, newlen, 202 hostname, sizeof(hostname)); 203 if (newp && !error) 204 hostnamelen = newlen; 205 return (error); 206 case KERN_HOSTID: 207 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */ 208 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid); 209 hostid = inthostid; 210 return (error); 211 case KERN_CLOCKRATE: 212 return (sysctl_clockrate(oldp, oldlenp)); 213 case KERN_BOOTTIME: 214 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, 215 sizeof(struct timeval))); 216 case KERN_VNODE: 217 return (sysctl_vnode(oldp, oldlenp)); 218 case KERN_PROC: 219 return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); 220 case KERN_FILE: 221 return (sysctl_file(oldp, oldlenp)); 222 #ifdef GPROF 223 case KERN_PROF: 224 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 225 newp, newlen)); 226 #endif 227 case KERN_POSIX1: 228 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); 229 case KERN_NGROUPS: 230 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX)); 231 case KERN_JOB_CONTROL: 232 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 233 case KERN_SAVED_IDS: 234 #ifdef _POSIX_SAVED_IDS 235 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 236 #else 237 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 238 #endif 239 default: 240 return (EOPNOTSUPP); 241 } 242 /* NOTREACHED */ 243 } 244 245 /* 246 * hardware related system variables. 247 */ 248 hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 249 int *name; 250 u_int namelen; 251 void *oldp; 252 size_t *oldlenp; 253 void *newp; 254 size_t newlen; 255 struct proc *p; 256 { 257 extern char machine[], cpu_model[]; 258 259 /* all sysctl names at this level are terminal */ 260 if (namelen != 1) 261 return (ENOTDIR); /* overloaded */ 262 263 switch (name[0]) { 264 case HW_MACHINE: 265 return (sysctl_rdstring(oldp, oldlenp, newp, machine)); 266 case HW_MODEL: 267 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); 268 case HW_NCPU: 269 return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */ 270 case HW_BYTEORDER: 271 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); 272 case HW_PHYSMEM: 273 return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 274 case HW_USERMEM: 275 return (sysctl_rdint(oldp, oldlenp, newp, 276 ctob(physmem - cnt.v_wire_count))); 277 case HW_PAGESIZE: 278 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); 279 default: 280 return (EOPNOTSUPP); 281 } 282 /* NOTREACHED */ 283 } 284 285 #ifdef DEBUG 286 /* 287 * Debugging related system variables. 288 */ 289 struct ctldebug debug0, debug1, debug2, debug3, debug4; 290 struct ctldebug debug5, debug6, debug7, debug8, debug9; 291 struct ctldebug debug10, debug11, debug12, debug13, debug14; 292 struct ctldebug debug15, debug16, debug17, debug18, debug19; 293 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 294 &debug0, &debug1, &debug2, &debug3, &debug4, 295 &debug5, &debug6, &debug7, &debug8, &debug9, 296 &debug10, &debug11, &debug12, &debug13, &debug14, 297 &debug15, &debug16, &debug17, &debug18, &debug19, 298 }; 299 int 300 debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 301 int *name; 302 u_int namelen; 303 void *oldp; 304 size_t *oldlenp; 305 void *newp; 306 size_t newlen; 307 struct proc *p; 308 { 309 struct ctldebug *cdp; 310 311 /* all sysctl names at this level are name and field */ 312 if (namelen != 2) 313 return (ENOTDIR); /* overloaded */ 314 cdp = debugvars[name[0]]; 315 if (cdp->debugname == 0) 316 return (EOPNOTSUPP); 317 switch (name[1]) { 318 case CTL_DEBUG_NAME: 319 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 320 case CTL_DEBUG_VALUE: 321 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 322 default: 323 return (EOPNOTSUPP); 324 } 325 /* NOTREACHED */ 326 } 327 #endif /* DEBUG */ 328 329 /* 330 * Validate parameters and get old / set new parameters 331 * for an integer-valued sysctl function. 332 */ 333 sysctl_int(oldp, oldlenp, newp, newlen, valp) 334 void *oldp; 335 size_t *oldlenp; 336 void *newp; 337 size_t newlen; 338 int *valp; 339 { 340 int error = 0; 341 342 if (oldp && *oldlenp < sizeof(int)) 343 return (ENOMEM); 344 if (newp && newlen != sizeof(int)) 345 return (EINVAL); 346 *oldlenp = sizeof(int); 347 if (oldp) 348 error = copyout(valp, oldp, sizeof(int)); 349 if (error == 0 && newp) 350 error = copyin(newp, valp, sizeof(int)); 351 return (error); 352 } 353 354 /* 355 * As above, but read-only. 356 */ 357 sysctl_rdint(oldp, oldlenp, newp, val) 358 void *oldp; 359 size_t *oldlenp; 360 void *newp; 361 int val; 362 { 363 int error = 0; 364 365 if (oldp && *oldlenp < sizeof(int)) 366 return (ENOMEM); 367 if (newp) 368 return (EPERM); 369 *oldlenp = sizeof(int); 370 if (oldp) 371 error = copyout((caddr_t)&val, oldp, sizeof(int)); 372 return (error); 373 } 374 375 /* 376 * Validate parameters and get old / set new parameters 377 * for a string-valued sysctl function. 378 */ 379 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 380 void *oldp; 381 size_t *oldlenp; 382 void *newp; 383 size_t newlen; 384 char *str; 385 int maxlen; 386 { 387 int len, error = 0; 388 389 len = strlen(str) + 1; 390 if (oldp && *oldlenp < len) 391 return (ENOMEM); 392 if (newp && newlen >= maxlen) 393 return (EINVAL); 394 if (oldp) { 395 *oldlenp = len; 396 error = copyout(str, oldp, len); 397 } 398 if (error == 0 && newp) { 399 error = copyin(newp, str, newlen); 400 str[newlen] = 0; 401 } 402 return (error); 403 } 404 405 /* 406 * As above, but read-only. 407 */ 408 sysctl_rdstring(oldp, oldlenp, newp, str) 409 void *oldp; 410 size_t *oldlenp; 411 void *newp; 412 char *str; 413 { 414 int len, error = 0; 415 416 len = strlen(str) + 1; 417 if (oldp && *oldlenp < len) 418 return (ENOMEM); 419 if (newp) 420 return (EPERM); 421 *oldlenp = len; 422 if (oldp) 423 error = copyout(str, oldp, len); 424 return (error); 425 } 426 427 /* 428 * Validate parameters and get old / set new parameters 429 * for a structure oriented sysctl function. 430 */ 431 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) 432 void *oldp; 433 size_t *oldlenp; 434 void *newp; 435 size_t newlen; 436 void *sp; 437 int len; 438 { 439 int error = 0; 440 441 if (oldp && *oldlenp < len) 442 return (ENOMEM); 443 if (newp && newlen > len) 444 return (EINVAL); 445 if (oldp) { 446 *oldlenp = len; 447 error = copyout(sp, oldp, len); 448 } 449 if (error == 0 && newp) 450 error = copyin(newp, sp, len); 451 return (error); 452 } 453 454 /* 455 * Validate parameters and get old parameters 456 * for a structure oriented sysctl function. 457 */ 458 sysctl_rdstruct(oldp, oldlenp, newp, sp, len) 459 void *oldp; 460 size_t *oldlenp; 461 void *newp, *sp; 462 int len; 463 { 464 int error = 0; 465 466 if (oldp && *oldlenp < len) 467 return (ENOMEM); 468 if (newp) 469 return (EPERM); 470 *oldlenp = len; 471 if (oldp) 472 error = copyout(sp, oldp, len); 473 return (error); 474 } 475 476 /* 477 * Get file structures. 478 */ 479 sysctl_file(where, sizep) 480 char *where; 481 size_t *sizep; 482 { 483 int buflen, error; 484 struct file *fp; 485 char *start = where; 486 487 buflen = *sizep; 488 if (where == NULL) { 489 /* 490 * overestimate by 10 files 491 */ 492 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 493 return (0); 494 } 495 496 /* 497 * first copyout filehead 498 */ 499 if (buflen < sizeof(filehead)) { 500 *sizep = 0; 501 return (0); 502 } 503 if (error = copyout((caddr_t)&filehead, where, sizeof(filehead))) 504 return (error); 505 buflen += sizeof(filehead); 506 where += sizeof(filehead); 507 508 /* 509 * followed by an array of file structures 510 */ 511 for (fp = filehead; fp != NULL; fp = fp->f_filef) { 512 if (buflen < sizeof(struct file)) { 513 *sizep = where - start; 514 return (ENOMEM); 515 } 516 if (error = copyout((caddr_t)fp, where, sizeof (struct file))) 517 return (error); 518 buflen -= sizeof(struct file); 519 where += sizeof(struct file); 520 } 521 *sizep = where - start; 522 return (0); 523 } 524 525 /* 526 * try over estimating by 5 procs 527 */ 528 #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) 529 530 sysctl_doproc(name, namelen, where, sizep) 531 int *name; 532 u_int namelen; 533 char *where; 534 size_t *sizep; 535 { 536 register struct proc *p; 537 register struct kinfo_proc *dp = (struct kinfo_proc *)where; 538 register int needed = 0; 539 int buflen = where != NULL ? *sizep : 0; 540 int doingzomb; 541 struct eproc eproc; 542 int error = 0; 543 544 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) 545 return (EINVAL); 546 p = (struct proc *)allproc; 547 doingzomb = 0; 548 again: 549 for (; p != NULL; p = p->p_next) { 550 /* 551 * Skip embryonic processes. 552 */ 553 if (p->p_stat == SIDL) 554 continue; 555 /* 556 * TODO - make more efficient (see notes below). 557 * do by session. 558 */ 559 switch (name[0]) { 560 561 case KERN_PROC_PID: 562 /* could do this with just a lookup */ 563 if (p->p_pid != (pid_t)name[1]) 564 continue; 565 break; 566 567 case KERN_PROC_PGRP: 568 /* could do this by traversing pgrp */ 569 if (p->p_pgrp->pg_id != (pid_t)name[1]) 570 continue; 571 break; 572 573 case KERN_PROC_TTY: 574 if ((p->p_flag & P_CONTROLT) == 0 || 575 p->p_session->s_ttyp == NULL || 576 p->p_session->s_ttyp->t_dev != (dev_t)name[1]) 577 continue; 578 break; 579 580 case KERN_PROC_UID: 581 if (p->p_ucred->cr_uid != (uid_t)name[1]) 582 continue; 583 break; 584 585 case KERN_PROC_RUID: 586 if (p->p_cred->p_ruid != (uid_t)name[1]) 587 continue; 588 break; 589 } 590 if (buflen >= sizeof(struct kinfo_proc)) { 591 fill_eproc(p, &eproc); 592 if (error = copyout((caddr_t)p, &dp->kp_proc, 593 sizeof(struct proc))) 594 return (error); 595 if (error = copyout((caddr_t)&eproc, &dp->kp_eproc, 596 sizeof(eproc))) 597 return (error); 598 dp++; 599 buflen -= sizeof(struct kinfo_proc); 600 } 601 needed += sizeof(struct kinfo_proc); 602 } 603 if (doingzomb == 0) { 604 p = zombproc; 605 doingzomb++; 606 goto again; 607 } 608 if (where != NULL) { 609 *sizep = (caddr_t)dp - where; 610 if (needed > *sizep) 611 return (ENOMEM); 612 } else { 613 needed += KERN_PROCSLOP; 614 *sizep = needed; 615 } 616 return (0); 617 } 618 619 /* 620 * Fill in an eproc structure for the specified process. 621 */ 622 void 623 fill_eproc(p, ep) 624 register struct proc *p; 625 register struct eproc *ep; 626 { 627 register struct tty *tp; 628 629 ep->e_paddr = p; 630 ep->e_sess = p->p_pgrp->pg_session; 631 ep->e_pcred = *p->p_cred; 632 ep->e_ucred = *p->p_ucred; 633 if (p->p_stat == SIDL || p->p_stat == SZOMB) { 634 ep->e_vm.vm_rssize = 0; 635 ep->e_vm.vm_tsize = 0; 636 ep->e_vm.vm_dsize = 0; 637 ep->e_vm.vm_ssize = 0; 638 #ifndef sparc 639 /* ep->e_vm.vm_pmap = XXX; */ 640 #endif 641 } else { 642 register struct vmspace *vm = p->p_vmspace; 643 644 #ifdef pmap_resident_count 645 ep->e_vm.vm_rssize = pmap_resident_count(&vm->vm_pmap); /*XXX*/ 646 #else 647 ep->e_vm.vm_rssize = vm->vm_rssize; 648 #endif 649 ep->e_vm.vm_tsize = vm->vm_tsize; 650 ep->e_vm.vm_dsize = vm->vm_dsize; 651 ep->e_vm.vm_ssize = vm->vm_ssize; 652 #ifndef sparc 653 ep->e_vm.vm_pmap = vm->vm_pmap; 654 #endif 655 } 656 if (p->p_pptr) 657 ep->e_ppid = p->p_pptr->p_pid; 658 else 659 ep->e_ppid = 0; 660 ep->e_pgid = p->p_pgrp->pg_id; 661 ep->e_jobc = p->p_pgrp->pg_jobc; 662 if ((p->p_flag & P_CONTROLT) && 663 (tp = ep->e_sess->s_ttyp)) { 664 ep->e_tdev = tp->t_dev; 665 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 666 ep->e_tsess = tp->t_session; 667 } else 668 ep->e_tdev = NODEV; 669 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; 670 if (SESS_LEADER(p)) 671 ep->e_flag |= EPROC_SLEADER; 672 if (p->p_wmesg) 673 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 674 ep->e_xsize = ep->e_xrssize = 0; 675 ep->e_xccount = ep->e_xswrss = 0; 676 } 677 678 #ifdef COMPAT_43 679 #include <sys/socket.h> 680 #define KINFO_PROC (0<<8) 681 #define KINFO_RT (1<<8) 682 #define KINFO_VNODE (2<<8) 683 #define KINFO_FILE (3<<8) 684 #define KINFO_METER (4<<8) 685 #define KINFO_LOADAVG (5<<8) 686 #define KINFO_CLOCKRATE (6<<8) 687 688 struct getkerninfo_args { 689 int op; 690 char *where; 691 int *size; 692 int arg; 693 }; 694 695 ogetkerninfo(p, uap, retval) 696 struct proc *p; 697 register struct getkerninfo_args *uap; 698 int *retval; 699 { 700 int error, name[5]; 701 u_int size; 702 703 if (uap->size && 704 (error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size)))) 705 return (error); 706 707 switch (uap->op & 0xff00) { 708 709 case KINFO_RT: 710 name[0] = PF_ROUTE; 711 name[1] = 0; 712 name[2] = (uap->op & 0xff0000) >> 16; 713 name[3] = uap->op & 0xff; 714 name[4] = uap->arg; 715 error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p); 716 break; 717 718 case KINFO_VNODE: 719 name[0] = KERN_VNODE; 720 error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 721 break; 722 723 case KINFO_PROC: 724 name[0] = KERN_PROC; 725 name[1] = uap->op & 0xff; 726 name[2] = uap->arg; 727 error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p); 728 break; 729 730 case KINFO_FILE: 731 name[0] = KERN_FILE; 732 error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 733 break; 734 735 case KINFO_METER: 736 name[0] = VM_METER; 737 error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 738 break; 739 740 case KINFO_LOADAVG: 741 name[0] = VM_LOADAVG; 742 error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 743 break; 744 745 case KINFO_CLOCKRATE: 746 name[0] = KERN_CLOCKRATE; 747 error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 748 break; 749 750 default: 751 return (EOPNOTSUPP); 752 } 753 if (error) 754 return (error); 755 *retval = size; 756 if (uap->size) 757 error = copyout((caddr_t)&size, (caddr_t)uap->size, 758 sizeof(size)); 759 return (error); 760 } 761 #endif /* COMPAT_43 */ 762